Index: Librarier/device/type.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/type.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/type.h	(working copy)
@@ -27,15 +27,19 @@
 
 
 #ifndef Boolean
+#ifndef IS_BOOLEAN
 typedef enum {FALSE = 0, TRUE =1} Boolean;
 #define IS_BOOLEAN(bool) ((bool == FALSE) || (bool == TRUE))
 #endif
+#endif
 
 
 #ifndef FunctionalState
+#ifndef IS_FUNCTIONAL_STATE
 typedef enum {DISABLE = 0, ENABLE =1} FunctionalState;
 #define IS_FUNCTIONAL_STATE(state) ((state== DISABLE) || (state == ENABLE))
 #endif
+#endif
 
 //#ifndef FunctionalState
 //typedef enum {ERROR = 0, SUCCESS = 1} ErrorStatus;
@@ -43,7 +47,10 @@
 //#endif
 
 #ifndef FlagStatus
+#ifndef IS_FLAG_STATUS_RESET
 typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
+#define IS_FLAG_STATUS_RESET(state) ((state== RESET) || (state == RESET))
+#endif
 #endif
 
 
Index: Librarier/device/yc11xx.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/yc11xx.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/yc11xx.h	(working copy)
@@ -492,6 +492,14 @@
 	GPIO_29,
 	GPIO_30,
 	GPIO_31,
+	GPIO_32,
+	GPIO_33,
+	GPIO_34,
+	GPIO_35,
+	GPIO_36,
+	GPIO_37,
+	GPIO_38,
+	GPIO_39,
 	GPIO_MAX_NUM,
 	GPIO_ACTIVE_BIT=0x80,
 }GPIO_NUM;
Index: /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/ycdef.h	(added)
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/ycdef.h	(revision 0)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/device/ycdef.h	(revision 0)
Index: Librarier/drivers/bt/yc11xx_bt_interface.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/bt/yc11xx_bt_interface.c	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/bt/yc11xx_bt_interface.c	(working copy)
@@ -1,5 +1,5 @@
 #include "yc11xx_bt_interface.h"
-#include "yc11xx_dev_oal.h"
+//#include "yc11xx_dev_oal.h"
 
 uint8_t *gpHFPCallState =(uint8_t *) reg_map( mem_hf_call_state);
 
Index: Librarier/drivers/debug/yc_debug.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/debug/yc_debug.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/debug/yc_debug.h	(working copy)
@@ -68,12 +68,12 @@
 void print_log(uint16_t flag, uint16_t value);
 void print_log_get_lock(void);
 void print_log_free_lock(void);
-void pringt_string_log(char *format, ...);
+void print_string_log(char *format, ...);
 void print_protocol_to_uart(uint16_t logLevel, uint16_t logType, uint8_t* buf, int len);
 void print_hci_h4_to_uart(uint8_t isRcv, uint8_t* buf, int len);
 #define DEBUG_INIT()	init_debugUart()
 #define DEBUG_LOG(LOG_LEVEL,TYPE_STR,STR,FLAG,VALUE)  print_log(FLAG,VALUE)
-#define DEBUG_LOG_STRING  pringt_string_log
+#define DEBUG_LOG_STRING  print_string_log
 #define DEBUG_LOG_2(LOG_LEVEL,TYPE_STR,STR,FLAG,VALUE_0,VALUE_1)  \
 	print_log(FLAG,(((VALUE_0) & 0xff)<<8)|(((VALUE_1) & 0xff)<<0))
 #define DEBUG_LOG_4(LOG_LEVEL,TYPE_STR,STR,FLAG,VALUE_0,VALUE_1,VALUE_2,VALUE_3) \
Index: Librarier/drivers/debug/yc_debug.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/debug/yc_debug.c	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/Librarier/drivers/debug/yc_debug.c	(working copy)
@@ -305,7 +305,7 @@
 //*****************************************************************************
 void print_string_to_uart(uint8_t* buf, int len)
 {
-	uint8_t uart_send_buf[3];
+	uint8_t uart_send_buf[10];
 	uint8_t offset = 0;
 
 	if(len == 0)
@@ -347,31 +347,30 @@
 		*uartSndBufUseLen = *uartSndBufUseLen+1;
 	}
 }
-void pringt_string_log(char *format, ...)
-{ 
-        uint32_t ulIdx, ulValue, ulPos, ulCount, ulBase, ulNeg;
-        char *pcStr, pcBuf[16], cFill;
-        char HexFormat;
-    	va_list vaArgP;
-        static const int8_t* const g_pcHex1 = "0123456789abcdef";
-        static const int8_t* const g_pcHex2 = "0123456789ABCDEF";
-    	va_start(vaArgP, format);
-    	uint8_t uart_tx_buff[DEBUG_STRING_LOG_SINGLE_LINE_MAX_SIZE];
-    	uint8_t uart_tx_local_ptr = 0;
-
-    	while(*format)
-    	{
-      	    // Find the first non-% character, or the end of the string.
-            for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0');ulIdx++)
-            {}
+        
+void print_string_log_raw(char *format, va_list vaArgP)
+{
+    uint32_t ulIdx, ulValue, ulPos, ulCount, ulBase, ulNeg;
+    char *pcStr, pcBuf[16], cFill;
+    char HexFormat;
+    static const int8_t* const g_pcHex1 = "0123456789abcdef";
+    static const int8_t* const g_pcHex2 = "0123456789ABCDEF";
+    uint8_t uart_tx_buff[DEBUG_STRING_LOG_SINGLE_LINE_MAX_SIZE];
+    uint8_t uart_tx_local_ptr = 0;
+
+    while(*format)
+    {
+        // Find the first non-% character, or the end of the string.
+        for(ulIdx = 0; (format[ulIdx] != '%') && (format[ulIdx] != '\0');ulIdx++)
+        {}
 
-        	// Write this portion of the string.
-            if(ulIdx>0)	 
-            {
-                print_string(uart_tx_buff, &uart_tx_local_ptr, (uint8_t*)format, ulIdx);
-            }
-            
-            format += ulIdx;
+        // Write this portion of the string.
+        if(ulIdx>0)  
+        {
+            print_string(uart_tx_buff, &uart_tx_local_ptr, (uint8_t*)format, ulIdx);
+        }
+        
+        format += ulIdx;
 
         if(*format == '%')
         {
@@ -382,7 +381,7 @@
             ulCount = 0;
             cFill = ' ';
 
-again:
+        again:
            switch(*format++)
             {
                 case '0':
@@ -415,6 +414,7 @@
                 }
 
                 case 'd':
+                case 'z':
                 {
                     ulValue = va_arg(vaArgP, unsigned long);
                     ulPos = 0;
@@ -482,7 +482,7 @@
                     ulNeg = 0;
                      HexFormat='x';
 
-convert:
+        convert:
                     for(ulIdx = 1;
                         (((ulIdx * ulBase) <= ulValue) &&
                          (((ulIdx * ulBase) / ulBase) == ulIdx));
@@ -516,8 +516,8 @@
 
                     for(; ulIdx; ulIdx /= ulBase)
                     {
-                        if(HexFormat=='x')	pcBuf[ulPos++] = g_pcHex1[(ulValue / ulIdx) % ulBase];//x
-                        else	pcBuf[ulPos++] = g_pcHex2[(ulValue / ulIdx) % ulBase];//X
+                        if(HexFormat=='x')  pcBuf[ulPos++] = g_pcHex1[(ulValue / ulIdx) % ulBase];//x
+                        else    pcBuf[ulPos++] = g_pcHex2[(ulValue / ulIdx) % ulBase];//X
                     }
 
                     print_string(uart_tx_buff, &uart_tx_local_ptr, (uint8_t*)pcBuf, ulPos);
@@ -539,11 +539,20 @@
         }//if
     }//while
 
-    va_end(vaArgP);
-
     print_string_to_uart(uart_tx_buff, uart_tx_local_ptr);
 }
 
+void print_string_log(char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+
+    print_string_log_raw(format, ap);
+
+    va_end(ap);
+}
+
 
 
 
Index: ModuleDemo/25_OTA/bt_demo/BT/a-l.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/a-l.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/a-l.bat	(nonexistent)
@@ -1,28 +0,0 @@
-
-e pu
-::e 8097   040307020506  
-:: enable flash vcc
-e 809a 3f
-:: set flash io port
-e 8090 060502
-e 8094 070304
-:: clear flash first
-e fe 0
-:: sometimes in lpm will power off qspi
-e pu
-e fa
-:: make sure flash ok
-e fr 0 30
-e fe 0
-:: clear store info
-e fe 7f000
-:: close wdt
-e 8043 00
-::e fw 3 a5
-e fp output/flash.dat 1000
-::e fp output/flash.dat 20000 
-e fw 4 a5
-:: make sure flash offset write after the file download, becouse in rom code, will check crc, if download failed in middle time, it will occur error.
-e fw 0 031000
-::e fw 0 030002
-e k
Index: ModuleDemo/25_OTA/bt_demo/BT/a.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/a.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/a.bat	(nonexistent)
@@ -1,28 +0,0 @@
-
-e pu
-::e 8097   040307020506  
-:: enable flash vcc
-e 809a 3f
-:: set flash io port
-e 8090 060502
-e 8094 070304
-:: clear flash first
-e fe 0
-:: sometimes in lpm will power off qspi
-e pu
-e fa
-:: make sure flash ok
-e fr 0 30
-e fe 0
-:: clear store info
-e fe 7f000
-:: close wdt
-e 8043 00
-::e fw 3 a5
-e fp output/flash.dat 1000
-::e fp output/flash.dat 20000 
-e fw 4 a5
-:: make sure flash offset write after the file download, becouse in rom code, will check crc, if download failed in middle time, it will occur error.
-::e fw 0 030002
-e fw 0 031000
-e k
Index: ModuleDemo/25_OTA/bt_demo/BT/do.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/do.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/do.bat	(nonexistent)
@@ -1,264 +0,0 @@
-
-@set FPGA_PATH=fpgajic\fpga
-@set YC_PATCH_FILE=yc_patch_yc1121.h
-@set enc=1
-@set enckey=0000000000000000
-@echo off
-
-::get Rom path
-set now_path=%~dp0
-call:getstrlocation %now_path% ModuleDemo location
-call:get_fix_len_str  %now_path% location soft_path
-set lib_path=%soft_path%Librarier
-set rom_path=%lib_path%\bt_rom
-set program=%rom_path%\program
-set format=%rom_path%\format
-set util=%rom_path%\util
-set patch_path=%now_path%patch
-set sched=%now_path%sched
-set output=%now_path%output
-set voice_prompt=%now_path%voice_prompt
-
-rem @echo rom_path=%rom_path%
-rem @echo program_path=%program%
-rem @echo format_path=%format%
-rem @echo util_path=%util%
-rem @echo patch_path=%patch_path%
-
-
-set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
-copy %program%\bt.prog + %progs% + %patch_path%\z.prog output\bt_program23.meta > nul
-set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
-copy %format%\bt.format + %fmts% + %format%\command.format  output\bt_format.meta > nul
-
-perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
-perl %util%/memalloc.pl 				output/bt_format.meta
-perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
-cd output
-osiuasm bt_program23 -O-W
-copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
-
-
-if "%1" equ "eep" (
-	goto genromrevc
-)else (
-  goto downloadram
-)
-
-:genromrevc
-echo off
-@echo Start to generate EEPROM code
-
-if exist "..\..\CM0\Prj\Output\out.rom" (
-	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
-) else (
-	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
-)
-
-::%util%/geneep  -n -z 
-@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
-%util%/geneep -f -n -z  
-
-perl %util%\flash2bin.pl
-
-::perl %util%\svnversion.pl %output%
-::perl %util%\getcodesize.pl %output%
-::perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
-::perl %util%\vp2.pl %voice_prompt% %output%
-::perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
-::perl %util%\add_ota_pcm.pl %output%/flash_add_coef.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
-
-::copy %output%\flash.dat  ..\..\..\..\24_TWS\bt_demo\BT\output\ota.dat
-copy sched.rom  	..\..\CM0\respin
-copy memmap.format  ..\..\CM0\respin
-copy ramcode.rom  ..\..\CM0\respin
-copy zcode.rom  ..\..\CM0\respin
-
-:gen_eep_end
-cd ..
-echo **********************************
-@rem echo flash.dat Generated.
-echo **********************************
-goto end
-
-
-
-:genrom
-@rem echo on
-perl ..\util\rom2mif.pl romcode
-del ..\..\%FPGA_PATH%\romcode.mif
-copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
-perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
-copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
-copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
-cd ..\..\%FPGA_PATH%
-quartus_cdb btspi -c btspi --update_mif
-quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
-quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
-@echo bitstream_compression=on >1
-@echo memory_map_file=on >> 1
-quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
-@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
-@del 1
-goto end
-
-
-
-:downloadram
-echo on
-@echo Start to download ram code
-e ku
-e hu
-e su sched.rom
-@echo **********************************
-@echo RAM CODE has been downloaded. 
-@echo **********************************
-cd ..
-
-
-:end
-goto:eof
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlocation-------
-::------------------------------------------
-:getstrlocation
-setlocal
-set "bstr=%1"
-set "cstr=%2"
-set %3=0
-set "num=0"
-set "len_bstr=0"
-set "len_cstr=0"
-
-call:getstrlen %bstr% len_bstr
-call:getstrlen %cstr% len_cstr
-
-:getstrlocation_next
-set /a len_remain=len_bstr-num
-if %len_remain% lss %len_cstr% (
-echo "cann't get str location"
-set /a num =0
-goto getstrlocation_last
-)
-
-call:get_fix_len_str %bstr%  len_cstr compar_str
-
-if not %compar_str%==%cstr% (
-set /a num+=1
-set "bstr=%bstr:~1%"
-goto getstrlocation_next
-)
-
-:getstrlocation_last
-(endlocal
-	set %3=%num%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-::------------------------------------------
-::---------------func:get_fix_len_str-------
-::------------------------------------------
-:get_fix_len_str
-setlocal
-set "getstr=%NULL%"
-set str=%1
-set /a len=%2
-set num=0
-:get_fix_len_str_loop
-set getstr=%getstr%%str:~0,1%
-set /a num+=1
-set str=%str:~1%
-if %num% lss %len% goto get_fix_len_str_loop
-(endlocal
- set %3=%getstr%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlen-------------
-::------------------------------------------
-:getstrlen
-setlocal
-set str=%1
-set %2=0
-set /a "num=0"
-
-:getstrlen_next
-if "%str%"=="" goto getstrlen_last
-
-if not "%str%"=="" (
-set /a num+=1 
-set "str=%str:~1%"
-goto getstrlen_next
-)
-
-:getstrlen_last
-(endlocal
-	set /a "%2=%num%"
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getcharlocation-------
-::------------------------------------------
-:getcharlocation
-setlocal
-set "str=%1"
-set "ch=%2"
-set %3=0
-set /a "num=0"
-
-:getcharnext
-if "%str%"=="" ( 
-set /a num=0
-goto getcharlast
-)
-
-if not "%str%"=="" (
-set /a num+=1
-if "%str:~0,1%"=="%ch%" goto getcharlast
-set "str=%str:~1%"
-goto getcharnext
-)
-:getcharlast
-(endlocal
-set %3=%num%
-)
-goto:eof 
-::---------------end:func-------------------
-
-
-
-
-
-
Index: ModuleDemo/25_OTA/bt_demo/BT/do_sdk.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/do_sdk.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/do_sdk.bat	(nonexistent)
@@ -1,262 +0,0 @@
-
-@set FPGA_PATH=fpgajic\fpga
-@set YC_PATCH_FILE=yc_patch_yc1121.h
-@set enc=1
-@set enckey=0000000000000000
-@echo off
-
-::get Rom path
-set now_path=%~dp0
-call:getstrlocation %now_path% ModuleDemo location
-call:get_fix_len_str  %now_path% location soft_path
-set lib_path=%soft_path%Librarier
-set rom_path=%lib_path%\bt_rom
-set program=%rom_path%\program
-set format=%rom_path%\format
-set util=%rom_path%\util
-set patch_path=%now_path%patch
-set sched=%now_path%sched
-set output=%now_path%output
-set voice_prompt=%now_path%voice_prompt
-
-rem @echo rom_path=%rom_path%
-rem @echo program_path=%program%
-rem @echo format_path=%format%
-rem @echo util_path=%util%
-rem @echo patch_path=%patch_path%
-
-
-::set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
-::copy %program%\bt.prog + %progs%  output\bt_program23.meta > nul
-copy patch\patch_sdk.prog + patch\patch.prog + %patch_path%\z.prog output\bt_program23.meta
-set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
-copy %format%\bt.format + %fmts% + format\labels.format + %format%\command.format  output\bt_format.meta > nul
-
-
-
-perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
-perl %util%/memalloc.pl 				output/bt_format.meta
-perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
-cd output
-osiuasm bt_program23 -O-W
-copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
-
-
-
-if "%1" equ "eep" (
-	goto genromrevc
-)else (
-  goto downloadram
-)
-
-:genromrevc
-echo off
-@echo Start to generate EEPROM code
-
-if exist "..\..\CM0\Prj\Output\out.rom" (
-	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
-) else (
-	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
-)
-
-%util%/geneep  -n -z 
-@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
-%util%/geneep -f -n -z  
-
-::perl %util%\svnversion.pl %output%
-::perl %util%\getcodesize.pl %output%
-::perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
-::perl %util%\vp2.pl %voice_prompt% %output%
-::perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
-::perl %util%\add_ota_pcm.pl %output%/flash_add_coef.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
-
-::copy %output%\flash.dat  ..\..\..\..\24_TWS\bt_demo\BT\output\ota.dat
-
-:gen_eep_end
-cd ..
-echo **********************************
-@rem echo flash.dat Generated.
-echo **********************************
-goto end
-
-
-
-:genrom
-@rem echo on
-perl ..\util\rom2mif.pl romcode
-del ..\..\%FPGA_PATH%\romcode.mif
-copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
-perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
-copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
-copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
-cd ..\..\%FPGA_PATH%
-quartus_cdb btspi -c btspi --update_mif
-quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
-quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
-@echo bitstream_compression=on >1
-@echo memory_map_file=on >> 1
-quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
-@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
-@del 1
-goto end
-
-
-
-:downloadram
-echo on
-@echo Start to download ram code
-e ku
-e hu
-e su sched.rom
-@echo **********************************
-@echo RAM CODE has been downloaded. 
-@echo **********************************
-cd ..
-
-
-:end
-goto:eof
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlocation-------
-::------------------------------------------
-:getstrlocation
-setlocal
-set "bstr=%1"
-set "cstr=%2"
-set %3=0
-set "num=0"
-set "len_bstr=0"
-set "len_cstr=0"
-
-call:getstrlen %bstr% len_bstr
-call:getstrlen %cstr% len_cstr
-
-:getstrlocation_next
-set /a len_remain=len_bstr-num
-if %len_remain% lss %len_cstr% (
-echo "cann't get str location"
-set /a num =0
-goto getstrlocation_last
-)
-
-call:get_fix_len_str %bstr%  len_cstr compar_str
-
-if not %compar_str%==%cstr% (
-set /a num+=1
-set "bstr=%bstr:~1%"
-goto getstrlocation_next
-)
-
-:getstrlocation_last
-(endlocal
-	set %3=%num%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-::------------------------------------------
-::---------------func:get_fix_len_str-------
-::------------------------------------------
-:get_fix_len_str
-setlocal
-set "getstr=%NULL%"
-set str=%1
-set /a len=%2
-set num=0
-:get_fix_len_str_loop
-set getstr=%getstr%%str:~0,1%
-set /a num+=1
-set str=%str:~1%
-if %num% lss %len% goto get_fix_len_str_loop
-(endlocal
- set %3=%getstr%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlen-------------
-::------------------------------------------
-:getstrlen
-setlocal
-set str=%1
-set %2=0
-set /a "num=0"
-
-:getstrlen_next
-if "%str%"=="" goto getstrlen_last
-
-if not "%str%"=="" (
-set /a num+=1 
-set "str=%str:~1%"
-goto getstrlen_next
-)
-
-:getstrlen_last
-(endlocal
-	set /a "%2=%num%"
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getcharlocation-------
-::------------------------------------------
-:getcharlocation
-setlocal
-set "str=%1"
-set "ch=%2"
-set %3=0
-set /a "num=0"
-
-:getcharnext
-if "%str%"=="" ( 
-set /a num=0
-goto getcharlast
-)
-
-if not "%str%"=="" (
-set /a num+=1
-if "%str:~0,1%"=="%ch%" goto getcharlast
-set "str=%str:~1%"
-goto getcharnext
-)
-:getcharlast
-(endlocal
-set %3=%num%
-)
-goto:eof 
-::---------------end:func-------------------
-
-
-
-
-
-
Index: ModuleDemo/25_OTA/bt_demo/BT/download_full_bin.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/download_full_bin.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/download_full_bin.bat	(nonexistent)
@@ -1,16 +0,0 @@
-::e pu
-
-::e hu output/romcode.rom 2000
-e pu
-::e 8097   040307020506  
-e 8090 060502
-e 8094 040307
-
-e fp output/flash_all.dat 0
-
-e fe 0
-e fe 7f000
-e fw 0 036000
-e fw 3 a5
-e fw 4 a5
-e k
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/BT/fdo.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/fdo.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/fdo.bat	(nonexistent)
@@ -1,3 +0,0 @@
-e pu
-e hu output/romcode.rom 2000
-e ku
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/BT/get_sdk_labels.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/get_sdk_labels.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/get_sdk_labels.bat	(nonexistent)
@@ -1,5 +0,0 @@
-call do.bat eep
-cd output
-perl ..\getlabels.pl > labels.format
-copy labels.format ..\format\labels.format
-cd ..
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/BT/getlabels.pl
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/getlabels.pl	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/getlabels.pl	(nonexistent)
@@ -1,19 +0,0 @@
-open file,"program.lis";
-$labe2 = 0;
-while(<file>) {
-	if(/^([a-z_0-9]+):\s*$/) {
-		#printf "%s\n", $labe2;
-		$label = $1;
-		$_ = <file>;
-		if(length($_) > 1 && hex(substr($_, 0, 4)) >= 0x2000){
-			if($labe2){
-				printf "0x%s %s\n", substr($_, 0, 4),  $labe2;
-				$labe2 = 0;
-			}
-			printf "0x%s %s\n", substr($_, 0, 4),  $label;
-		}else{
-			$labe2 = $label;
-		}
-	}
-}
-close file;
Index: ModuleDemo/25_OTA/bt_demo/BT/patch/patch.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/patch.prog	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/patch.prog	(nonexistent)
@@ -1,3086 +0,0 @@
-//define EFUSE_CODE
-//define FUNCTION_WATCH_DOG
-//define TEST_QUEUE_DEBUG
-define RF_DEBUG
-//define WHITE_LIST
-define MINZHAN_SDK
-define FSC_RTK_HOST
-//define LE_CONN_RCV_DEBUG
-define PATCH_DEBUG_LOG
-
-/******************************************/
-/**************   Start   *****************/
-/******************************************/
-ifdef EFUSE_CODE
-	call wdt_init_reset_with_start // this supervision timeout is near 16.76s
-	branch loadcode_spi+2
-endif //EFUSE_CODE
-
-	bbit1 8,pf_patch_ext
-	beq patch00_2,p_main_loop
-	beq patch01_6,p_inquiry_receive_rtn
-	beq patch02_0,p_master_page_timeout
-	beq patch03_4,p_master_loop
-	beq patch03_6,p_master_disconnect
-	beq patch04_0,p_linkkey_ready
-	beq patch04_4,p_role_switch_master
-	beq patch06_2,p_send_eir
-	beq patch07_1,p_slave_dispatch
-	beq patch07_2,p_slave_loop
-	beq patch07_6,p_slave_disconnect
-	beq patch08_1,p_roles_newconn_loop				
-	beq patch08_4,z_newconn_init
-	beq patch0a_4,p_rx_type_dispatch
-	beq patch0b_0,p_process_dmh_common
-	beq patch0b_4,p_process_dmh_data_end
-	beq patch0b_5,p_process_dmh_l2cap_packet
-	beq patch0d_2,z_sniff_init
-	beq patch0d_3,z_sniff_exit
-	beq patch0d_4,p_check_attempt
-	beq patch10_1,p_shutdown_radio
-	beq patch10_5,p_set_freq_tx
-	beq patch10_6,p_initialize_radio_cont
-
-	
-	beq patch13_6,p_initialize_radio_cont_by_init_param
-
-	beq patch14_0,p_lpm_hibernate
-	beq patch14_4,p_lpm_dispatch
-	beq patch15_0,p_lpm_dispatch_unconn
-	beq patch17_1,z_app_init
-	beq patch17_2,p_app_process_bb_event
-	beq patch1c_0,p_vp_check_get_data
-	branch assert
-pf_patch_ext:
-	beq patch20_7,z_ipc_init
-	beq patch21_4,p_ipc_rx_process
-	beq patch22_2,z_l2cap_init_queue
-	beq patch22_3,p_queue_insert
-	beq patch22_4,p_queue_delete
-	beq patch24_3,p_l2cap_load_channel_param
-	beq patch24_5,p_l2cap_malloc
-	beq patch24_6,p_l2cap_malloc_fifo_out
-	beq patch24_7,p_l2cap_malloc_free
-	beq patch25_0,p_l2cap_malloc_discard
-	beq patch25_1,p_l2cap_malloc_is_fifo_full
-	beq patch25_2,p_l2cap_malloc_fifo_get_first_ptr
-	beq patch27_3,p_le_init_conn
-	beq patch27_6,p_le_conn_dispatch
-	beq patch27_7,p_le_slave_match
-	beq patch28_1,p_le_slave_unsync
-	beq patch28_2,p_le_slave_disconn
-	beq patch29_0,p_le_context_nextevent
-	beq patch29_3,p_le_receive_slave
-	beq patch29_7,p_le_send_adv_ind
-	beq patch2a_2,p_le_acknowledge
-//	beq patch2a_4,p_le_scan_match
-	beq patch2b_0,z_le_parse_ll
-	beq patch2b_3,p_le_adv
-	beq patch2b_5,z_parse_connect_req
-	beq patch2c_0,p_le_fifo_malloc_tx
-	beq patch2c_4,p_le_fifo_release_first_node
-	beq patch2d_6,p_init_lmp_work
-	beq patch2e_0,z_parse_lmp_process
-	beq patch2e_1,z_parse_lmp_escape
-	beq patch2e_4,p_send_lmp
-	
-	beq patch32_2,p_scheduler_tx_l2cap_pkt
-	beq patch34_5,p_simple_pairing_sequence
-	beq patch34_6,p_master_simple_paring_sequence
-	rtneq patch36_2
-	rtneq patch3a_4
-	//beq patch36_2,p_tws_m_wait_connecting
-	//beq patch3a_4,p_tws_s_wait_connecting
-	branch assert
-
-p_main_loop:
-	call sp_calc_sequence 
-	call sp_calc_sequence_256
-	call publickey_calc
-	call p_le_dispatch
-	call idle_dispatch
-	call app_process_idle
-	call p_inquiry_dispatch
-	call inquiry_scan_dispatch
-	call p_page_scan_dispatch
-	branch main_loop+11
-
-p_inquiry_dispatch:
-	rtnmark0 mark_inquiry_on
-	force inquiry_length_timer,queue
-	call timer_check
-	nsetflag blank,mark_inquiry_on,mark
-	nbranch inquiry_start,blank
-	branch z_hci_send_inquiry_comple
-	
-p_page_scan_dispatch:
-	fetch 1,mem_scan_mode
-	rtnbit0 page_scan_mode
-	fetch 1,mem_state
-	rtnbit1 state_inconn
-p_page_scan_dispatch2:	
-	force pscan_interval_timer,queue
-	call timer_check
-	nrtn blank
-	fetcht 2,mem_pscan_window
-//	force 40,queue
-	disable swfine
-	copy temp,stop_watch
-	branch page_scan_dispatch+9
-
-p_le_dispatch:
-	 call le_enable 
-	 call p_le_scan
-	 branch le_dispatch+2
-
-p_le_scan:
-	fetch 1,mem_le_scan_enable
-	rtnne LE_SCAN_ENABLE
-	arg le_scan_interval_timer,queue
-	call timer_check
-	nrtn blank
-	
-	fetch 2,mem_le_scan_interval
-	arg le_scan_interval_timer,queue
-	call timer_init
-	
-	call le_init_adv
-	call le_next_adv_channel
-	fetch 2,mem_le_scan_window
-	store 2,mem_le_scan_window_temp
-p_le_scan_loop:	
-	disable master
-	disable swfine
-	fetchr timeup,2,mem_le_scan_window_temp
-	call p_le_receive_packet
-	nbranch p_le_scan_timeout_check,match	
-	//branch le_scan_match
-p_le_scan_match:
-	call le_scan_check_sender_addr_type
-	copy rega,pdata
-	store 1,mem_le_conn_peer_addr_type
-ifdef WHITE_LIST
-	arg mem_le_white_list_type_and_bd_addr,contw
-	istore 1,contw
-	fetch 6,mem_le_rxbuf+2
-	istore 6,contw
-	fetch 1,mem_le_white_list_cnt
-	beq 0,p_le_scan_match_send_event
-	fetch 1,mem_le_white_list_filter_policy
-	beq NONE_FILTER,p_le_scan_match_send_event
-	beq WHITE_LIST_SCAN_FILTER,p_white_filter_scan_check
-	beq WHITE_LIST_CONNECT_FILTER,p_le_scan_match_send_event
-	beq WHITE_LIST_CONN_SCAN_FILTER,p_white_filter_scan_check
-p_white_filter_scan_check:
-	call p_check_addr_in_white_list
-	nbranch p_le_scan_timeout_check,blank
-endif
-p_le_scan_match_send_event:
-	fetch 6,mem_le_rxbuf+2
-	store 6,mem_le_plap
-	
-	fetch 1,mem_mesh_creat_connection_flag
-	beq CREAT_CONNECTION,p_le_create_conn
-	call p_hci_send_event_le_advertising_report
-	
-	call le_send_scan_request
-	nbranch p_le_scan_timeout_check,match
-	fetch 1,mem_le_rxbuf+1
-	beq 6,p_le_scan_timeout_check
-	call p_hci_send_event_le_advertising_report
-
-p_le_scan_timeout_check:	
-	fetch 2,mem_le_scan_window_temp
-	nbranch  p_le_scan_loop,blank
-	rtn
-
-p_le_receive_packet:
-	call lerx_setfreq
-p_le_receive_rxon:
-	call le_prep
-	disable match
-	enable decode_fec0
-	enable is_rx
-	disable is_tx
-	copy timeup,stop_watch
-	correlate null,timeout
-	deposit stop_watch
-	store 2,mem_le_scan_window_temp
-	branch le_receive_rxon+7
-
-
-p_initialize_radio_cont:
-	fetch 1,mem_patch13
-	set0 6,pdata
-	store 1,mem_patch13
-	branch p_initialize_radio_process
-// be-careful, this patch is not from <initialize_radio_cont>.
-p_initialize_radio_cont_by_init_param:
-	call p_initialize_radio_process
-
-	// becouse patch is from <init_param>
-	branch init_param_cont
-
-p_initialize_radio_process:
-		// in efuse will enable wdt
-ifdef FUNCTION_WATCH_DOG
-	call wdt_init_reset_with_start
-else
-	call wdt_disable_watchdog
-endif //FUNCTION_WATCH_DOG
-
-	// Change mixer power
-	jam 0xba,0x894b
-	call p_initialize_radio_tx_power
-	// Always use 2M IF
-	jam 0xff,0x8907	//7~5 000:0M IF 011:1M IF 111:2M IF
-	call initialize_radio_cont+1
-	jam 0x74,0x8950
-	jam 0x0e,0x8952
-	jam 0x07,0x896d
-	rtn
-
-p_initialize_radio_tx_power:
-	fetch 1,mem_tx_power
-//	beq TX_POWER_0DB,p_initialize_radio_tx_power_0db
-ifdef ENABLE_F3DB
-	beq TX_POWER_f3DB,p_initialize_radio_tx_power_f3db	
-endif // ENABLE_F3DB
-	beq TX_POWER_3DB,p_initialize_radio_tx_power_3db	
-	beq TX_POWER_f5DB,p_initialize_radio_tx_power_f5db	
-	beq TX_POWER_5DB,p_initialize_radio_tx_power_5db
-ifdef ENABLE_8DB
-	beq TX_POWER_8DB,p_initialize_radio_tx_power_8db	
-endif // ENABLE_8DB
-
-ifdef ENABLE_8DB
-p_initialize_radio_tx_power_8db:
-	setarg 0xcce0d0
-	store 3,0x8955
-	setarg 0x7a103e
-	store 3,0x8958
-	jam 0x43,0x8954
-	rtn
-endif // ENABLE_8DB
-
-p_initialize_radio_tx_power_3db:
-p_initialize_radio_tx_power_5db:
-	setarg 0x88e0d0
-	store 3,0x8955
-p_initialize_radio_tx_power_common:
-	setarg 0x4a103c
-p_initialize_radio_tx_power_common2:
-	store 3,0x8958
-	jam 0x68,0x8954
-	rtn
-p_initialize_radio_tx_power_f3db:
-p_initialize_radio_tx_power_f5db:
-	setarg 0x88c0d0
-	store 3,0x8955
-	setarg 0x4a106c
-	branch p_initialize_radio_tx_power_common2
-
-p_shutdown_radio:
-ifdef RF_DEBUG
-	call rf_shutdown_radio_for_debug
-endif //RF_DEBUG
-	branch p_shutdown_radio0,is_rx
-	jam 0xd4, 0x8955
-	nop 4
-	jam 0xd2, 0x8955
-	nop 4
-	jam 0xd1, 0x8955
-	nop 4	
-	fetch 1,mem_tx_power
-ifdef ENABLE_F3DB	
-	beq TX_POWER_f3DB,p_shutdown_radio_f3db
-endif //ENABLE_F3DB
-	beq TX_POWER_3DB,p_shutdown_radio_3db
-	beq TX_POWER_f5DB,p_shutdown_radio_f5db
-p_shutdown_radio_8db:
-p_shutdown_radio_5db:	
-p_shutdown_radio_3db:
-p_shutdown_radio_0db:
-	jam 0xd0, 0x8955
-	jam 0xe0, 0x8956
-p_shutdown_radio0:
-	force 8,radio_ctrl
-	force 0,radio_ctrl
-	disable is_rx
-	disable is_tx
-	pulse packet_end
-	jam 0x0,rfen_mdm
-	jam 0x0,rfen_tx
-	jam 0x0,rfen_rx
-	jam 0,rfen_sn
-	jam 0x70,rfen_msc
-	fetch 1,rfen_adc
-	set0 0,pdata
-	store 1,rfen_adc
-//	jam 0x0,rfen_adc
-	rtn	
-p_shutdown_radio_f5db:
-p_shutdown_radio_f3db:
-	jam 0xd0,0x8955
-	jam 0xc0,0x8956
-	branch p_shutdown_radio0
-p_set_freq_tx:
-	storet 1,mem_last_freq
-	add temp,0,rega			/* index to frequency */
-	fetch 1,mem_sfreq_enable
-	ncall set_offset_sfreq,blank
-	call rf_write_freq
-	setarg param_pll_setup_min
-	call sleep
-p_rf_tx_enable:
-	// becouse we will change the tx power, so need initial again
-	call p_initialize_radio_tx_power
-	fetch 1,rfen_adc
-	set1 0,pdata
-	store 1,rfen_adc
-	jam 0x3c,rfen_rx
-	jam 0xe0,rfen_tx
-	nop 10 /* wait LDOs to turn ON*/
-	jam 0x01, rfen_mdm
-	jam 0x3d, rfen_mdm
-	nop 10 /* wait tx blocks to turn ON*/
-	jam 0xb7,rfen_sn
-	nop 10 /* wait tx lo buffer to turn ON*/
-	jam 0x7d, rfen_mdm
-	fetch 1,mem_tx_power
-	beq TX_POWER_0DB,p_set_tx_power_0db
-ifdef ENABLE_F3DB
-	beq TX_POWER_f3DB,set_tx_power_f3db	
-endif //ENABLE_F3DB
-	beq TX_POWER_f5DB,p_set_tx_power_f5db
-p_rx_high_sens:
-	jam 0xfb,0x894c 
-	jam 0xef,0x894d
-	jam 0xec,0x894e 
-	jam 0x5e,0x894f 
-	beq TX_POWER_3DB,p_set_tx_power_3db
-	beq TX_POWER_8DB,p_set_tx_power_8db
-p_set_tx_power_5db:  	
-  	branch set_tx_power_5db
-p_set_tx_power_8db:  	
-	jam 0xff,0x8956
-	call txon_common
-	jam 0xff,0x8955
-	rtn
-	
-p_set_tx_power_f5db:
-	call p_rx_low_sens
-	jam 0xcc,0x8956
-	call txon_common
-	jam 0xd8,0x8955
-	rtn	
-	
-p_set_tx_power_0db:
-	call p_rx_low_sens
-	branch set_tx_power_0db
-
-	
-p_set_tx_power_3db:
-	jam 0xf7,0x8956
-	call txon_common
-	jam 0xdf,0x8955
-	rtn
-p_rx_low_sens:
-	jam 0x5b,0x894c 
-	jam 0x96,0x894d
-	jam 0x2c,0x894e 
-	jam 0x46,0x894f 
-  	rtn
-
-/*
-p_enable_m0_work_clk:
-	fetch 1,0x1f000
-	arg 0x1c,temp
-	ior temp,pdata
-	store 1,0x1f000
-	rtn
-p_disable_m0_work_clk:
-	fetch 1,0x1f000
-	arg 0xe3,temp
-	iand temp,pdata
-	store 1,0x1f000
-	rtn
-*/
-
-
-p_lpm_write_wait_clock:
-	until null,lpo_edge
-	until null,lpo_edge
-	until null,lpo_edge
-	until null,lpo_edge
-	until null,lpo_edge
-	rtn
-
- 	
-
- 	
-p_headset_cb_idle_process:
-ifdef FUNCTION_WATCH_DOG
-	call p_wdt_kick_watchdog
-endif //FUNCTION_WATCH_DOG
-	rtn
-
-	
-//p_app_process_bb_event:
-//	fetch 1,mem_state
-//	bbit1 state_inconn,app_process_bb_event+1
-//	
-//	fetch 2,mem_ui_state_map
-//	jam 0x03,mem_scan_mode
-//	branch app_process_bb_event+1
-
-p_headset_evt_100ms_timer:
-// Voice all process by cm0
-p_vp_check_get_data:
-	rtn
-
-
-p_clear_charge_reset_flag:
-	fetch 4,core_lpm_buck_cfg
-	set0 29,pdata
- 	store 4,core_lpm_reg
-	branch  p_lpm_write_ctrl_buck
-p_lpm_write_ctrl_buck:
-	until null,lpo_edge
-	jam lpmreg_sel_buck_cfg,core_lpm_wr
-	until null,lpo_edge
-	rtn
-p_lpm_hibernate:
-	arg -1,temp // Here must be -1, the rom code is error
-	branch lpm_doze
-
-
-	
-/*********************************/
-/*********lmp send*************/
-/********************************/
-	/* enable user if a lmp packet is to send */
-p_send_lmp:
-	//bpatchx patch2e_4,mem_patch2e
-	disable user
-	call lmo_fifo_process
-	fetch 1,mem_lmp_to_send
-	rtn blank
-	branch z_send_lmp
-
-p_send_lmp_sres_startenc_slave_event_send:
-	call z_hci_send_linkkey_notification
-	branch p_hci_send_auth_complete
-
-p_prepare_disconnect:
-	fetch 1,mem_op
-	set1 op_disconn,pdata
-	store 1,mem_op
-	jam 1,mem_conn_timer
-	rtn
-
-p_send_eir:
-	fetch 1,mem_eir
-	branch send_eir+1,blank
-	arg mem_eir,contr
-	arg 240,loopcnt
-	arg 0,temp
-	call p_check_tx_length
-	storet 2,mem_tx_len
-	branch send_eir+22
-p_check_tx_length:
-	ifetch 1,contr
-	rtn blank
-	increase 1,temp
-	loop p_check_tx_length
-	rtn
-
-p_slave_dispatch:
-	jam 0,mem_check_attempt_limit
-	branch slave_dispatch+1
-
-
-p_slave_loop:
-//	bpatch patch07_2,mem_patch07
-	fetch 1,mem_check_attempt_limit
-	increase 1,pdata
-	store 1,mem_check_attempt_limit
-	call scheduler_process
-	call slave_conn_recv_packet	/* go listen for a packet */
-	nbranch slave_notmatch,match
-	call supervision_flush
-	call scheduler_tx_l2cap_pkt
-	call prepare_tx
-	call set_flow_flag
-	call slave_conn_send_packet
-	call parse_l2cap
-	call parse_lmp
-	call p_process_cmd
-	branch slave_loop+12
-
-p_master_loop:
-	call parse_lmp
-	call p_process_cmd
-	branch master_loop+3
-
-p_process_cmd:
-	fetch 1,mem_hci_cmd
-	rtn blank
-	fetch 1,mem_lmo_opcode2
-	nrtn blank
-	branch z_process_cmd
-
-
-p_hci_send_connection_complete:
-	jam 2,mem_conn_status
-	//force 0,temp
-	jam 0x00,mem_mesh_event_parameter_status
-//	jam 0,mem_scan_mode
-	branch p_hci_send_connection_rtn_error
-p_hci_send_connection_error:
-	//force HCI_EVENT_CONNECTION_COMPLETE,queue
-	//Status(1),Connection_Handle(2),BD_ADDR(6),Link_Type(1),Encryption_Enabled(1)
-	jam 0,mem_conn_status
-	jam 0,mem_conn_req_status
-p_hci_send_connection_rtn_error:	
-	jam 0,mem_io_cap_flag
-	branch z_hci_send_connection_rtn_error
-
-
-p_inquiry_receive_rtn:
-	fetch 1,mem_inquiry_num_check
-	branch z_hci_inquiry_reply_check_eir,blank
-	fetch 1,mem_inquiry_num_responses
-	branch z_hci_send_inquiry_comple,blank
-	increase -1,pdata
-	store 1,mem_inquiry_num_responses
-	branch z_hci_inquiry_reply_check_eir
-
-
-	
-p_rssi_convert:
-	fetch 1,mem_rssi
-	rshift4 pdata,temp
-	mul32 temp,10,temp
-	and pdata,0x0f,pdata
-	iadd temp,temp
-	sub temp,0,pdata
-	rtn
-
-
-p_master_page_timeout:	
-	call master_page_timeout+1
-//	fetch 1,mem_conn_status
-	//rtnne 1
-//	bne 1,assert
-	fetch 1,mem_hci_remote_name_req_flag
-	nbranch p_hci_send_remote_name_request_complete,blank
-	jam PAGE_TIMEOUT,mem_mesh_event_parameter_status
-	branch p_hci_send_connection_error 
-//<quit_connection> will call zcode, so should not push to zcode
-p_master_disconnect:
-	//bpatch patch03_6,mem_patch03
-	call quit_connection
-	disable master
-	fetch 1,mem_conn_status
-	beq 1,p_master_page_timeout
-	fetch 1,mem_state_map
-	bbit1 smap_name_req,master_name_disconnect
-	fetch 1,mem_state
-	bbit0 state_conn_comp,master_disconnect_quiet
-	branch p_hci_send_disconnect_complete
-	
-p_estimate_event_head_event_code:
-	fetch 1,mem_inquiry_mode
-	beq 0,p_hci_event_inquiry_result
-	beq 1,p_hci_event_inquiry_result_with_rssi
-	beq 2,p_hci_event_extended_inquiry_result
-	jam HCI_EVENT_INQUIRY_RESULT,mem_mesh_event_head_event_code
-	rtn
-p_hci_event_inquiry_result:
-	jam 15,mem_mesh_event_para_total_length
-	jam HCI_EVENT_INQUIRY_RESULT,mem_mesh_event_head_event_code
-	rtn
-p_hci_event_inquiry_result_with_rssi:
-	jam 15,mem_mesh_event_para_total_length
-	jam HCI_EVENT_INQUIRY_RESULT_WITHRSSI,mem_mesh_event_head_event_code
-	rtn
-p_hci_event_extended_inquiry_result:
-	jam 255,mem_mesh_event_para_total_length
-	jam HCI_EVENT_EXT_INQUIRY_RESULT,mem_mesh_event_head_event_code
-	rtn
-
-p_parse_lmp_name_res:
-	fetch 1,mem_hci_remote_name_req_flag
-	branch parse_lmp_name_res,blank
-	
-	fetch 2,mem_len
-	add pdata,-3,loopcnt	//for remote name length error
-	fetcht 1,mem_rxbuf+1
-	setarg mem_tmp_buffer
-	iadd temp,contw
-	arg mem_rxbuf+3,contr
-	call memcpy
-	call p_hci_save_mem_hci_remote_name
-	fetcht 1,mem_name_offset
-	fetch 1,mem_rxbuf+2	
-	isub temp,pdata
-	sub pdata,14,null
-	branch p_hci_send_remote_name_request_complete,positive
-	branch parse_lmp_name_res+12
-//	branch p_hci_send_remote_name_request_complete
-p_hci_send_remote_name_request_complete:
-	jam 255,mem_mesh_event_para_total_length
-	jam HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0x00
-	istore 1,contw
-	fetch 6,mem_hci_plap
-	istore 6,contw
- 	arg 64,loopcnt
-	arg mem_hci_remote_name,contr
-	call memcpy_fast
-	arg 184,loopcnt
-	call memset0
-	call ipc_hci_tx_start
-p_hci_remote_name_request_flag_init:
-	fetch 1,mem_hci_remote_name_req_flag
-	jam 0,mem_hci_remote_name_req_flag
-	jam 0,mem_name_offset
-	beq 2,p_hci_send_remote_name_request_complete_detach
-	branch parse_lmp_name_res_end
-p_hci_send_remote_name_request_complete_detach:
-	call lmp_disconnect+1
-	branch parse_lmp_name_res_end
-
-p_hci_save_mem_hci_remote_name:
-	fetcht 1,mem_rxbuf+1	
-	setarg mem_hci_remote_name
-	iadd temp,contw
-
-	fetch 1,mem_rxbuf+2
-	fetcht 1,mem_rxbuf+1	
-	isub temp,loopcnt
-	
-	arg mem_rxbuf+3,contr
-	branch memcpy_fast
-	
-	
-
-p_check_attempt:
-	fetch 1,mem_check_attempt_limit
-	sub pdata,100,null
-	nbranch check_attempt_nomore,positive
-	branch check_attempt+1
-
-p_hci_parse_connection_handle_check:
-	call p_ipc_rx_hci_data_two_byte
-	fetcht 1,mem_conn_handle
-	isub temp,null
-	rtn zero
-	branch p_hci_send_event_command_complete_error_command_disallowed
-
-p_roles_newconn_loop:
-	call master_newconn_once
-	branch p_roles_newconn_responded,sync
-	call new_conn_timeout
-	nbranch p_roles_newconn_loop,blank
-	disable clknt
-	deposit clke_bt
-	store 4,mem_next_btclk
-	rtn
-p_roles_newconn_responded:
-	call roles_newconn_responded
-	jam 0,mem_mesh_event_parameter_status
-	branch z_hci_send_role_change
-
-
-p_role_switch_master:
-	call role_switch_check
-	nrtn user
-	disable user
-	jam param_newconnto,mem_newconnto_counter
-	set0 mark_fhs_already_good,mark
-p_roles_waitfhs_loop:
-	call rf_setup_time_master_slot
-	call master_recv_packet
-	bmark1 mark_fhs_already_good,p_roles_replyto_fhs
-	call new_conn_timeout
-	nbranch p_roles_waitfhs_loop,blank
-p_role_switch_fail_master:
-	disable user
-	deposit clkn_bt
-	store 4,mem_next_btclk
-	enable clknt
-	enable master
-	branch z_hci_send_role_change_err
-	
-p_roles_replyto_fhs:
-	call rf_setup_time_slave_slot
-	arg type_id,type
-	call master_send_packet
-	disable clknt
-	disable master
-	call apply_switch_clke
-	call prepare_newconn
-p_roles_newconns_loop:
-	call slave_newconn_once
-	branch p_roles_newconns_responded,match
-	call new_conn_timeout
-	nbranch p_roles_newconns_loop,blank
-	branch p_role_switch_fail_master
-p_roles_newconns_responded:
-	force 1,temp
-	fetch 1,mem_mode
-	set0 mode_master,pdata
-	store 1,mem_mode
-	call supervision_flush
-	call calc_clke_offset
-	enable user
-	jam 1,mem_mesh_event_parameter_status
-	branch z_hci_send_role_change		
-
-//<quit_connection> will call zcode, so should not push to zcode
-p_slave_disconnect:
-	//bpatch patch07_6,mem_patch07
-	jam 0,mem_tester_emulate
-	jam 0,mem_debug_config
-	call quit_connection
-	set0 mark_testmode,mark
-	call test_enable_white
-	fetch 1,mem_conn_status
-	rtn blank
-	branch p_hci_send_disconnect_complete		
-/* lmp is not recognized, check to see if we respond to all messages */ 
-/* rejecting the unrecognized message with PDU not recognized */
-//p_reject_unknown_packet:
-//	jam UNKNOWN_LMP_PDU,mem_lmo_reason2
-//p_reject_lmp_packet:
-//	jam LMP_NOT_ACCEPTED,mem_lmo_opcode2
-//	rtn
-
-// <linkkey_ready> will call zcode, so should not push to zcode
-p_authentication_event:
-	call authentication_ok
-	rtnmark1 mark_slave_in_rand_accepted
-	branch p_hci_send_auth_complete
-p_linkkey_ready:
-	fetch 1,mem_state
-	bbit1 state_linkkey,linkkey_set
-	fetch 1,mem_pairing_auth
-	branch linkkey_set,blank
-	jam DEFALT_PAIRING_AUTH,mem_pairing_auth
-	//jam BT_EVT_LINKKEY_GENERATE,mem_fifo_temp
-	//call ui_ipc_send_event
-	
-	fetch 1,mem_op
-	isolate1 op_auth_req,pdata
-	set0 op_auth_req,pdata
-	store 1,mem_op
-//	call p_hci_send_auth_complete,true
-	call linkkey_set
-	rtnmark1 mark_slave_in_rand_accepted
-	branch z_hci_send_linkkey_notification
-
-
-
-p_hci_send_auth_complete:
-	jam 3,mem_mesh_event_para_total_length
-	jam HCI_EVENT_AUTHENTICATION_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	force 0,pdata
-	istore 1,contw
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-p_hci_send_linkkey_req_event:
-	//BD_ADDR(6)
-	jam 6,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LINK_KEY_REQUEST,mem_mesh_event_head_event_code
-p_hci_send_sec_req:	//used by linkkey and pin req 
-	call p_hci_prepare_send_event
-	fetch 6,mem_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-p_hci_send_pincode_req_event:
-	//BD_ADDR(6)
-	jam 6,mem_mesh_event_para_total_length
-	jam HCI_EVENT_PIN_CODE_REQUEST,mem_mesh_event_head_event_code
-	branch p_hci_send_sec_req
-
-
-p_ipc_rx_process:
-	fetch 1,mem_ipc_enable
-	rtn blank
-	call ipc_rx_items_inquire
-	rtn zero // no data
-	icopy contr
-	call ipc_rx_byte_read
-
-	beq IPC_TYPE_CM0_TO_BT_DATA,ipc_rx_data_buf
-	branch ipc_rx_process+7
-
-ifdef FUNCTION_WATCH_DOG
-p_wdt_kick_watchdog:
-	//fetch 1,mem_ota_wdt_en_flag
-	//beq 0xaa,p_ota_change_code_wdt
-	call wdt_set_watchdog_mode_reset
-	branch wdt_kick_watchdog_1_5s
-endif //FUNCTION_WATCH_DOG
-//p_ota_change_code_wdt:
-//	fetch 1,mem_ota_wdt_m0_en
-//	beq 0x55,p_wdt_kick_watchdog+2
-//	rtn
-
-
-// input: contw,loopcnt
-// output: null
-p_ipc_rx_hci_data_n_byte:
-	call p_ipc_rx_restore_contr
-	call memcpy_fast
-	branch p_ipc_rx_store_contr
-
-p_ipc_rx_hci_data_two_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 2,contr
-	branch p_ipc_rx_store_contr
-p_ipc_rx_hci_data_thr_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 3,contr
-	branch p_ipc_rx_store_contr
-p_ipc_rx_hci_data_six_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 6,contr
-	branch p_ipc_rx_store_contr
-p_ipc_rx_hci_data_seven_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 7,contr
-	branch p_ipc_rx_store_contr
-p_ipc_rx_hci_data_eight_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 8,contr
-	branch p_ipc_rx_store_contr
-
-p_ipc_rx_hci_data_one_byte:
-	call p_ipc_rx_restore_contr
-	ifetch 1,contr
-p_ipc_rx_store_contr:
-	copy contr,temp
-p_ipc_rx_store_contr1:
-	storet 3,mem_ipc_rx_ptr
-	rtn
-	
-p_ipc_rx_restore_contr:
-	fetcht 3,mem_ipc_rx_ptr
-	copy temp,contr
-	rtn
-p_white_filter_connect_filter:
-	jam WHITE_LIST_CONNECT_FILTER,mem_le_white_list_filter_policy
-	rtn
-p_parse_le_controller_create_connection:
-	jam ON,mem_le_scan_enable
-	jam CREAT_CONNECTION,mem_mesh_creat_connection_flag
-	branch p_hci_send_event_command_status
-
-/*
-p_hci_parse_packet_acl:
-	call le_fifo_check_full
-	nrtn blank
-	hfetch 2,core_uart_rxitems
-	add pdata,-5,rega
-	nrtn positive
-	call p_hci_parse_packet_acl_FB_flag
-	ifetch 2,contru
-	increase 1,rega		//´َسعµبسع
-	isub rega,null
-	rtn positive
-	copy pdata,rega
-	copy pdata,regb
-	call le_fifo_malloc_tx
-	copy regb,loopcnt
-	call uart_copy_rx_bytes_fast
-	call uartd_prepare_rx
-	increase 3,contru
-	ifetch 2,contru
-	iadd contru,contru
-	fetch 1,mem_mesh_recevie_acl_packet_number
-	pincrease 1
-	store 1,mem_mesh_recevie_acl_packet_number
-	branch uartd_rxdone
-
-p_hci_parse_packet_acl_FB_flag:
-	ifetch 2,contru
-	rshift8 pdata,pdata
-	rshift4 pdata,pdata
-	force LLID_CONTINUE,type
-	rtneq BT_ACL_CONT
-	force LLID_START,type
-	rtn
-*/
-
-/*********
-	HCI_OGF_LINK_CONTROL
-*********/
-
-
-
-
-/*********
-	HCI_OGF_LINK_POLICY
-*********/
-
-
-/*********
-	HCI_OGF_CONTROLLER_AND_BASEBAND
-*********/
-
-
-
-p_hci_init_bd_address:
-	fetch 6,mem_device_public_address
-	store 6,mem_le_lap
-	store 6,mem_lap
-	rtn
-	
-	
-/*********
-	HCI_OGF_LE_CONTROLLER
-*********/
-	
-
-
-
-// input: rega	return pdata=0:true  pdata = 1:false
-p_check_addr_in_white_list:
-ifdef WHITE_LIST
-	fetch 1,mem_le_white_list_cnt
-	copy pdata,loopcnt
-	arg mem_le_white_list,regb
-p_check_addr_in_white_list_loop:
-	ifetch 7,regb
-	fetcht 7,mem_le_white_list_type_and_bd_addr
-	isub temp,null
-	setarg 0
-	rtn zero
-	increase 7,regb
-	loop p_check_addr_in_white_list_loop
-	setarg 1
-endif
-	rtn
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// input: regb: payload ptr
-ipc_tx_bt_data_buf_free:
-	jam IPC_DATA_SUBTYPE_FREE,mem_ipc_data_tx_buf_subtype
-	branch ipc_tx_bt_data_buf_with_type
-
-// input: regb: payload ptr
-ipc_tx_bt_data_buf_hci:
-	jam IPC_DATA_SUBTYPE_HCI,mem_ipc_data_tx_buf_subtype
-	branch ipc_tx_bt_data_buf_with_type
-
-// input: regb: payload ptr
-//ipc_tx_bt_data_buf_ble:
-//	jam IPC_DATA_SUBTYPE_BLE,mem_ipc_data_tx_buf_subtype
-//	branch ipc_tx_bt_data_buf_with_type
-
-// input: regb: payload ptr
-//ipc_tx_bt_data_buf_br:
-//	jam IPC_DATA_SUBTYPE_SPP,mem_ipc_data_tx_buf_subtype
-//	branch ipc_tx_bt_data_buf_with_type
-	
-ipc_tx_bt_data_buf_with_type:
-	storer regb,3,mem_ipc_data_tx_buf_payload_ptr
-// input: mem_ipc_tx_data_buf_subtype, mem_ipc_data_buf_payload_ptr
-ipc_tx_bt_data_buf:
-ifdef TEST_QUEUE_DEBUG
-	arg 0x7100,rega
-	fetcht 1,mem_ipc_data_tx_buf_subtype
-	call debug_log_print
-	arg 0x7101,rega
-	fetcht 2,mem_ipc_data_tx_buf_payload_ptr
-	call debug_log_print
-endif
-
-	//fetch 1,mem_ipc_enable
-	//rtn blank
-	setarg mem_ipc_tx_buf
-	store 2,mem_ipc_tx_data_ptr
-	icopy contw
-	setarg IPC_TYPE_BT_TO_CM0_DATA
-	istore 1,contw
-	force 4,pdata // len
-	istore 1,contw
-	
-	fetch 1,mem_ipc_data_tx_buf_subtype
-	istore 1,contw
-	
-	fetch 3,mem_ipc_data_tx_buf_payload_ptr
-	istore 3,contw
-
-	 // total len
-	force 6,pdata
-	store 1,mem_ipc_tx_data_len
-	branch ipc_tx_common
-	
-ifdef ipc_zcode_test
-p_ipc_rx_hci:
-	fetcht 3,mem_ipc_data_rx_buf_payload_ptr
-	call p_ipc_rx_store_contr1
-	call p_ipc_rx_hci_data_one_byte
-	beq HCI_H4_TYPE_CMD,p_hci_parse_packet_cmd
-	beq HCI_H4_TYPE_ACL,p_hci_parse_packet_acl
-	branch assert
-endif
-
-ipc_rx_data_buf_sub_hci_data:
-	call z_ipc_rx_hci
-	fetchr regb,3,mem_ipc_data_rx_buf_payload_ptr
-	branch ipc_tx_bt_data_buf_free
-
-
-ipc_rx_data_buf_sub_free_buf:
-	call ipc_rx_data_buf_free_ipc_work
-	fetchr regb,3,mem_ipc_data_rx_buf_payload_ptr
-	branch free_buffer
-ipc_rx_data_buf_free_ipc_work:
-	call p_ipc_rx_restore_contr
-	arg 3,loopcnt
-	arg mem_ipc_data_rx_buf_payload_ptr,contw
-	branch ipc_rx_block_read
-
-ipc_rx_data_buf:
-	// ipc total length
-	call ipc_rx_byte_read
-	// subType
-	call ipc_rx_byte_read
-	store 1,mem_ipc_data_rx_buf_subtype
-	call p_ipc_rx_store_contr
-	
-	fetch 1,mem_ipc_data_rx_buf_subtype
-	beq IPC_DATA_SUBTYPE_FREE,ipc_rx_data_buf_sub_free_buf
-
-	// make sure have buffer to do this.
-	call malloc_buffer_is_full
-	rtn blank
-
-	call ipc_rx_data_buf_free_ipc_work
-
-ifdef TEST_QUEUE_DEBUG
-	arg 0x7000,rega
-	fetcht 1,mem_ipc_data_rx_buf_subtype
-	call debug_log_print
-	arg 0x7001,rega
-	fetcht 2,mem_ipc_data_rx_buf_payload_ptr
-	call debug_log_print
-endif
-
-	fetch 1,mem_ipc_data_rx_buf_subtype
-	beq IPC_DATA_SUBTYPE_HCI,ipc_rx_data_buf_sub_hci_data
-	branch assert
-
-
-
-
-p_hci_send_event_command_complete_error_command_invalid_param:
-	jam COMMAND_INVALID_HCI_COMMAND_PARAMETERS,mem_mesh_command_complete_return_parameter_status
-	branch p_hci_send_event_command_complete_without_payload+1
-p_hci_send_event_command_complete_error_command_nuknown:
-	jam COMMAND_UNKNOWN,mem_mesh_command_complete_return_parameter_status
-	branch p_hci_send_event_command_complete_without_payload+1
-p_hci_send_event_command_complete_error_command_disallowed:
-	jam COMMAND_DISALLOWED,mem_mesh_command_complete_return_parameter_status
-	branch p_hci_send_event_command_complete_without_payload+1
-p_hci_send_event_command_complete_without_payload:
-	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
-	arg 1,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status
-	branch ipc_hci_tx_start
-	
-p_hci_prepare_send_event_command_complete_with_status_success:
-	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
-p_hci_prepare_send_event_command_complete_with_status:
-	call p_hci_prepare_send_event_command_complete
-	fetch 1,mem_mesh_command_complete_return_parameter_status
-	istore 1,contw
-	rtn
-
-p_hci_prepare_send_event_command_complete:
-	jam HCI_EVENT_COMMAND_COMPLETE,mem_mesh_event_head_event_code
-	add loopcnt,3,pdata
-	store 1,mem_mesh_event_para_total_length
-	call p_hci_prepare_send_event
-	//Num_HCI_Command_Packets(1Byte), Command_Opcode(2Byte)
-	fetch 3,mem_mesh_command_complete_num_hci_command_packet
-	istore 3,contw
-	rtn
-
-p_hci_send_event_command_status:
-	jam COMMAND_CURRENTLY_PENDING,mem_temp
-	branch p_hci_send_event_command_status_raw
-p_hci_send_event_command_status_err_command_disallowed:
-	jam COMMAND_DISALLOWED,mem_temp
-	branch p_hci_send_event_command_status_raw
-p_hci_send_event_command_status_err_unknown_connection:
-	jam HCI_ERROR_NO_CONNECTION,mem_temp
-p_hci_send_event_command_status_raw:
-	jam HCI_EVENT_COMMAND_STATUS,mem_mesh_event_head_event_code
-	jam 4,mem_mesh_event_para_total_length
-	call p_hci_prepare_send_event
-	fetch 1,mem_temp
-	istore 1,contw
-	fetch 3,mem_mesh_command_complete_num_hci_command_packet
-	istore 3,contw
-	branch ipc_hci_tx_start
-
-p_hci_send_event_le_disconnection_complete:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 DISCONNECTION_COMPLETE_EVENT
-	fetch 1,mem_le_conn_handle
-	store 1,mem_hci_record_disc_conn_handle
-	branch z_hci_send_disconnect_complete
-p_hci_send_disconnect_complete:
-	//status(1), connection_handle(2), Reason(1)
-	fetch 1,mem_conn_handle
-	store 1,mem_hci_record_disc_conn_handle
-p_hci_send_disconnect_complete_init_connection_classic:
-	set0 mark_slave_in_rand_accepted,mark
-	jam 0,mem_conn_handle
-	jam 0,mem_conn_req_status
-	jam 0,mem_conn_status
-	branch z_hci_send_disconnect_complete
-
-
-p_le_get_role:
-	fetch 1,mem_le_mode
-	arg HCI_ROLE_MASTER,temp
-	rtneq lemode_master
-	arg HCI_ROLE_SLAVE,temp
-	rtn
-
-
-
-le_scan_check_event_type:
-	fetch 1,mem_le_rxbuf
-	and pdata,0x0f,pdata
-	arg 0,temp		//adv ind
-	rtneq ADV_IND
-	arg 1,temp		//adv direct ind
-	rtneq ADV_DIRECT_IND
-	arg 2,temp
-	rtneq ADV_SCAN_IND
-	arg 3,temp
-	rtneq ADV_NONCONN_IND
-	arg 4,temp
-//	rtneq SCAN_RSP
-	rtn
-
-p_hci_send_event_le_advertising_report:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 LE_ADVERTISING_REPORT_EVENT
-	arg 6,pdata
-	fetcht 1,mem_le_rxbuf+1	//length
-	iadd temp,pdata
-	store 1,mem_mesh_event_para_total_length
-
-	increase 3,pdata // evt type(04), evt code
-	store 2,mem_alloc_buffer_len
-	//call malloc_buffer_is_enough
-	//rtn blank
-
-	arg mem_alloc_big_block,rega
-	call p_queue_get_len
-	sub pdata,2,null
-	rtn positive
-
-	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-
-	setarg HCI_LE_SUBEVENT_ADV_REPORT
-	istore 1,contw		//subevent code
-	setarg 0x01
-	istore 1,contw		//Num reprot only 1
-	call le_scan_check_event_type
-	istoret 1,contw		//event type is ADV_IND
-	call le_scan_check_sender_addr_type
-	copy rega,pdata
-	istore 1,contw		//event type
-	fetcht 1,mem_le_rxbuf+1 //length
-	increase -6,temp
-	//fetch 6,mem_le_plap
-	ifetch 6,contr			//addr type
-	istore 6,contw
-	istoret 1,contw
-	copy temp,loopcnt
-	call memcpy_fast
-	call p_rssi_convert
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-
-
-
-
-
-
-
-
-
-p_hci_send_event_number_of_completed_packet_classic:
-	fetch 1,mem_conn_handle
-	store 1,mem_hci_conn_handle
-	branch p_hci_send_event_number_of_completed_packet
-p_hci_send_event_number_of_completed_packet_le:
-	fetch 1,mem_le_conn_handle
-	store 1,mem_hci_conn_handle
-p_hci_send_event_number_of_completed_packet:
-	jam 5,mem_mesh_event_para_total_length
-	jam HCI_EVENT_NUM_COMPLETED_PACKETS,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0x01 // Number of Handles: 1
-	istore 1,contw
-	fetch 1,mem_hci_conn_handle
-	istore 2,contw
-	setarg 0x01 // Num Completed Packets: 1
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-//mem_mesh_event_head_event_code:event code
-//mem_mesh_event_para_total_length:parameter total length
-p_hci_prepare_send_event:
-	fetch 1,mem_mesh_event_para_total_length
-	increase 3,pdata // evt type(04)(1Byte), evt code(1Byte), evt len(1Byte)
-	store 2,mem_alloc_buffer_len
-
-	call ipc_hci_prepare_tx
-
-	fetch 3,mem_mesh_event_head_type
-	istore 3,contw
-	rtn
-
-ipc_hci_prepare_tx:
-	call malloc_hci_snd_buffer
-	copy regb,contw
-	rtn
-	
-ipc_hci_tx_start:
-	arg mem_snd_hci_block,rega
-	call queue_delete
-	branch ipc_tx_bt_data_buf_hci
-
-p_le_send_empty:
-	force 0,temp
-	force 1,type
-p_le_send_packet:
-	storet 1,mem_le_txlen_temp
-	fetcht 1,mem_le_arq
-	set1 wak,temp
-	and temp,0xfc,pdata
-	ior type,pdata
-	store 1,mem_le_arq
-	and_into 0x1f,pdata
-	isolate1 mark_ble_tx_md,mark
-	setflag true,md,pdata
-	store 1,mem_le_txheader_temp
-	rtn
-
-
-
-p_le_prepare_tx:
-	fetch 1,mem_le_arq
-	rtnbit1 wak
-
-	call p_le_check_tx_md
-	
-	call p_le_malloc_fifo_out
-	branch p_le_send_empty,blank	
-	ifetch 1,contr		//total length
-	ifetchr rega,1,contr	//offset	
-	isub rega,pdata
-	copy contr,contw
-	fetcht 2,mem_remote_rx_max_octets
-	call not_greater_than
-	copy pdata,temp
-	copy contw,contr
-	ifetchr type,1,contr
-	copy rega,pdata
-	iadd contr,contr   
-	arg mem_le_txpayload_temp,contw
-	copy temp,loopcnt
-	call memcpy_fast	
-	call le_update_tx_type
-	call p_le_send_packet
-
-	call p_le_malloc_fifo_out
-	ifetch 1,contr
-	copy pdata,rega
-	copy contr, regd
-	ifetchr regb,1,contr
-	isub regb,pdata
-	fetcht 2,mem_remote_rx_max_octets
-	call not_greater_than
-	iadd regb,pdata
-	istore 1,regd  	//update offset
-	isub rega,null
-	nrtn zero
-	branch le_fifo_release_first_node
-
-p_le_check_tx_md:
-	fetch 1,mem_le_more_data
-	branch le_clear_md,blank
-	
-	call p_le_check_continue
-	rtnmark1 mark_ble_tx_md
-	
-	arg mem_snd_ble_block,rega
-	call p_queue_get_len	
-	beq 0,le_clear_md
-	beq 1,le_clear_md
-	set1 mark_ble_tx_md,mark
-	rtn
-
-p_le_check_continue:
-	call p_le_malloc_fifo_out
-	branch le_clear_md,blank
-	ifetch 1,contr				//pdata:length
-	ifetcht 1,contr				//temp:offest
-	isub temp,temp			//temp:length - offset
-	fetch 2,mem_remote_rx_max_octets
-	isub temp,null
-	branch le_clear_md,positive				//27 > length -offset
-	set1 mark_ble_tx_md,mark
-	rtn
-
-p_le_malloc_fifo_out:
-	arg mem_snd_ble_block,rega
-	branch queue_get_read_ptr		
-
-
-p_le_transmit_norx:
-	call p_le_transmit
-	branch end_of_packet
-
-
-p_le_transmit:
-	call le_prep
-	call letx_setfreq
-	call rf_debug_active_tx_line
-	set1 TXGFSK,radio_ctrl
-	enable encode_fec0
-	enable is_tx
-	disable is_rx
-	call le_wait_tx
-	rshift16 access,pdata
-	rshift8 pdata,pdata
-	rshift4 pdata,pdata
-	inject mod,40
-	enable enable_white
-	enable enable_crc
-p_le_transmit0:	
-	fetch 1,mem_le_txheader_temp
-	inject mod,8
-	ifetch 1,contr
-	copy pdata,loopcnt
-	inject mod,8
-	branch letr_nopayload,zero
-	branch letr_loop	
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-p_le_slave_match:
-ifdef RF_DEBUG
-	call rf_debug_active_sync_line
-endif
-	call le_got_first_packet
-	call le_acknowledge
-	call p_le_prepare_tx
-	call p_le_transmit_norx
-	call p_le_parse
-	call le_check_md
-	branch p_le_slave_more_data,user
-	branch le_slave_cont
-
-
-	
-p_le_send_connection_update_ind:
-	fetch 1,mem_le_state
-	set1 lestate_update_param,pdata
-	store 1,mem_le_state
-	
-	jam 1,mem_le_new_transmitwindowsize // window size 1 1.25ms
-	setarg 0x3
-	store 2,mem_le_new_transmitwindowoffset //window offset 3 3.75ms
-	fetch 2,mem_le_conn_interval
-	store 2,mem_le_new_conninterval  // event interval 30 37.5ms
-	fetch 2,mem_le_conn_latency
-	store 2,mem_le_new_connslavelatency // latency 
-	fetch 2,mem_le_conn_superto
-	store 2,mem_le_new_connsupervisiontimeout //supervision timeout 500 5s
-	fetch 2,mem_le_event_count
-	increase 0x10,pdata
-	store 2,mem_le_instant
-	arg 12,rega
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_CONNECTION_UPDATE_REQ
-	istore 1,contw
-	//winsize winoffset
-	fetch 9,mem_le_new_param
-	istore 9,contw
-	fetch 2,mem_le_instant
-	istore 2,contw
-	call clear_le_cmd
-	branch z_hci_send_le_connection_update_commplete
-	
-p_le_create_conn:
-	fetch 6,mem_le_plap
-	fetcht 6,mem_le_conn_peer_addr
-	isub temp,null
-	nrtn zero
-	call context_new
-	nrtn zero
-	call le_connect_request
-	call le_init_master
-	jam 0,mem_hci_cmd
-	jam 0,mem_le_peer_sca
-
-	call le_create_conn_ndongle
-
-	//arg MASTER_CONNECTION_HANDLE,temp
-	branch z_hci_send_event_le_connection_complete
-
-
-
-	
-
-
-
-//p_hci_prepare_send_acl:
-//	fetch 2,mem_hci_acl_packet_len_recved
-//	increase 5,pdata // acl type(02)(1Byte), handle(2Byte), length(2Byte)
-//	store 2,mem_alloc_buffer_len
-
-//	branch ipc_hci_prepare_tx
-
-//p_hci_send_acl_encode_le:
-//	fetch 1,mem_le_packet_llid
-//	store 1,mem_hci_acl_packet_pb_flag
-//	fetch 2,mem_le_payload_ptr
-//	store 2,mem_hci_acl_packet_payload_ptr
-//	fetch 2,mem_le_l2cap_size
-//	store 2,mem_hci_acl_packet_len_recved
-//	fetch 1,mem_le_conn_handle
-//	store 2,mem_hci_conn_handle
-//p_hci_send_acl_encode:
-//	call p_hci_prepare_send_acl
-//	setarg HCI_H4_TYPE_ACL
-//	istore 1,contw
-//	fetch 1,mem_hci_conn_handle
-//	fetcht 1,mem_hci_acl_packet_pb_flag
-//	lshift8 temp,temp
-//	lshift4 temp,temp
-//	ior temp,pdata
-//	istore 2,contw
-
-//	fetcht 2,mem_hci_acl_packet_len_recved
-//	istoret 2,contw //length
-//	copy temp,loopcnt
-//	fetch 2,mem_hci_acl_packet_payload_ptr
-//	copy pdata,contr
-//	call memcpy_fast
-
-//	branch ipc_hci_tx_start
-
-
-p_hci_send_acl_encode_classic:
-	call p_get_br_rcv_ptr
-	store 3,mem_hci_acl_packet_payload_ptr
-	//free buffer
-	setarg 0
-	store 3,mem_rcv_br_queue_ptr
-
-	fetch 1,mem_conn_handle
-	store 1,mem_hci_conn_handle
-	jam IPC_DATA_SUBTYPE_ACL_CLASSIC,mem_ipc_data_tx_buf_subtype
-
-ifdef TEST_QUEUE_DEBUG
-	arg 0x7100,rega
-	fetcht 1,mem_ipc_data_tx_buf_subtype
-	call debug_log_print
-	arg 0x7101,rega
-	fetcht 2,mem_hci_acl_packet_payload_ptr
-	call debug_log_print
-endif
-
-	branch p_hci_send_acl_encode
-p_hci_send_acl_encode_le:
-	call p_get_ble_rcv_ptr
-	store 3,mem_hci_acl_packet_payload_ptr
-	//free buffer
-	setarg 0
-	store 3,mem_rcv_ble_queue_ptr
-
-	fetch 1,mem_le_conn_handle
-	store 1,mem_hci_conn_handle
-	jam IPC_DATA_SUBTYPE_ACL_BLE,mem_ipc_data_tx_buf_subtype
-p_hci_send_acl_encode:
-	setarg mem_ipc_tx_buf
-	store 2,mem_ipc_tx_data_ptr
-	icopy contw
-	setarg IPC_TYPE_BT_TO_CM0_DATA
-	istore 1,contw
-	force 6,pdata // len
-	istore 1,contw
-	
-	fetch 1,mem_ipc_data_tx_buf_subtype
-	istore 1,contw
-	
-	fetch 3,mem_hci_acl_packet_payload_ptr
-	istore 3,contw
-
-	fetch 1,mem_hci_conn_handle
-	istore 2,contw
-	
-
-	 // total len
-	force 8,pdata
-	store 1,mem_ipc_tx_data_len
-	
-	branch ipc_tx_common
-
-	
-
-
-p_le_init_conn:
-	call le_init_conn+1
-	jam 1,mem_le_txheader_temp
-	jam 0,mem_le_txlen_temp
-	setarg 27
-	store 2,mem_remote_rx_max_octets
-	call new_conn_handle
-	pincrease 24
-	store 1,mem_le_conn_handle
-	rtn	
-
-
-p_le_conn_dispatch:
-	call le_enable
-	call app_process_ble
-	fetch 1,mem_le_mode
-	beq lemode_master,p_le_master_dispatch
-	branch le_slave_dispatch
-
-p_hci_parse_packet_cmd_ogf_le_controller_connection_update:
-		call p_ipc_rx_hci_data_two_byte
-		store 1,mem_hci_conn_handle      //connect handle
-		call p_ipc_rx_hci_data_two_byte   //connect interval min
-		lshift2 pdata,pdata
-		store 2,mem_le_conn_interval
-		call p_ipc_rx_hci_data_two_byte  //connect interval max
-		call p_ipc_rx_hci_data_two_byte		//connect latency
-		store 2,mem_le_conn_latency	
-		call p_ipc_rx_hci_data_two_byte		//supervision timeout
-		store 2,mem_le_conn_superto
-		call app_ble_master_update_conn
-		branch p_hci_send_event_command_status
-
-
-
-p_le_transmit_receive_sifs_master:
-	call p_le_transmit
-	branch p_le_transmit_receive_sifs_notx_slave
-p_le_master_sm:
-	fetch 1,mem_le_master_sm
-	beq LE_MASTER_SM_NULL,p_le_master_sm_null	
-	beq LE_MASTER_SM_SEND_VERSION,p_le_master_sm_send_version
-	beq LE_MASTER_SM_RCV_VERSION,p_le_master_sm_rcv_version
-	beq  LE_MASTER_SM_SEND_FEATURES,p_le_master_sm_send_features
-	beq LE_MASTER_SM_RCV_FEATURES,p_le_master_sm_rcv_features
-	beq LE_MASTER_SM_CHANNEL_MAP_IND,p_le_master_channel_map_match
-	rtn
-
-p_le_master_channel_map_match:
-	fetch 1,mem_le_state
-	set1 lestate_update_map,pdata
-	store 1,mem_le_state
-	setarg 0xffcf3ff3
-	store 4,mem_le_new_map
-	setarg 0x1f
-	istore 1,contw
-//	call le_update_channel_map
-	jam LE_MASTER_SM_END,mem_le_master_sm
-p_le_send_ll_channel_map_ind:
-	arg 12,rega
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_CHANNEL_MAP_REQ
-	istore 1,contw
-	fetch 5, mem_le_new_map
-	istore 5,contw
-	setarg conninstant
-	fetch 2,mem_le_event_count
-	increase 0x40,pdata
-	istore 2,contw
-	store 2,mem_le_instant
-	rtn
-	
-p_le_master_sm_null:
-	rtn
-p_le_master_sm_rcv_features:
-	jam LE_MASTER_SM_CHANNEL_MAP_IND,mem_le_master_sm
-	rtn
-p_le_master_sm_send_version:
-//	jam 20,mem_le_master_timer
-	jam LE_MASTER_SM_WAIT_VERSION,mem_le_master_sm
-	branch le_parse_version_ind+1
-
-p_le_master_sm_rcv_version:
-	jam LE_MASTER_SM_SEND_FEATURES,mem_le_master_sm
-	rtn
-	
-p_le_master_sm_send_features:
-	jam LE_MATSER_SM_WAIT_FEATURES,mem_le_master_sm
-	arg 9,rega
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_FEATURE_REQ
-	istore 1,contw
-	setarg param_le_features
-	istore 8,contw
-	rtn
-p_le_parse_feature_rsp_master:
-	fetch 1,mem_le_master_sm
-	rtnne LE_MATSER_SM_WAIT_FEATURES 
-	jam LE_MASTER_SM_RCV_FEATURES,mem_le_master_sm
-	rtn
-
-p_le_parse_version_ind_cmd_master:
-	fetch 1,mem_le_master_sm
-	rtnne LE_MASTER_SM_WAIT_VERSION
-	jam LE_MASTER_SM_RCV_VERSION,mem_le_master_sm
-	rtn
-	
-p_le_master_dispatch:	
-	enable master
-	call le_supervision_update
-	branch p_le_master_disconn,positive
-	call p_le_master_sm
-	call p_le_prepare_tx
-	call le_setup
-	disable match
-	call p_le_transmit_receive_sifs_master
-	nbranch p_le_master_not_match,match
-p_le_master_match:
-ifdef RF_DEBUG
-	call rf_debug_active_sync_line
-endif
-	call p_le_got_first_packet
-ifdef LE_CONN_RCV_DEBUG	
-	fetch 1,mem_le_conn_rcv
-	pincrease 1
-	store 1,mem_le_conn_rcv
-endif	
-	call le_acknowledge
-	call p_le_parse
-	call le_check_md
-	branch p_le_master_more_data,user
-p_le_master_cont:
-	call process_le_cmd
-	disable master
-	branch end_of_packet
-process_le_cmd:
-	fetch 1,mem_le_state
-	rtnbit1 lestate_update_map
-	fetch 1,mem_le_wait_process_cmd
-	rtn blank
-	beq BT_CMD_LE_MASTER_UPDATE_CONN,p_le_send_connection_update_ind
-	branch assert
-
-clear_le_cmd:
-	jam 0,mem_le_wait_process_cmd
-	rtn
-	
-app_ble_master_update_conn:	
-	jam BT_CMD_LE_MASTER_UPDATE_CONN,mem_le_wait_process_cmd
-	rtn
-	
-p_le_master_more_data:
-	call p_le_prepare_tx
-	call p_le_transmit_norx_master
-	enable attempt
-	call p_le_transmit_receive_sifs_notx_slave
-	branch p_le_master_match,match
-	branch p_le_master_cont
-
-
-p_le_transmit_norx_master:
-	call p_le_transmit_master
-	branch end_of_packet
-	
-p_le_transmit_master:
-	call le_prep
-	call letx_setfreq
-ifdef RF_DEBUG
-	call rf_debug_active_tx_line
-endif
-	set1 TXGFSK,radio_ctrl
-	enable encode_fec0
-	enable is_tx
-	disable is_rx
-	call p_le_wait_tx_cont
-	branch p_le_transmit+8
-
-p_le_wait_tx_cont:
-	until null,timeout
-	rtn
-
-
-p_le_got_first_packet:
-	fetch 1,mem_le_state
-	rtnbit1 lestate_got_first_packet
-	set1 lestate_got_first_packet
-	store 1,mem_le_state
-	jam LE_MASTER_SM_SEND_VERSION,mem_le_master_sm
-	rtn
-
-p_le_master_not_match:
-	fetch 1,mem_le_state
-	bbit1  lestate_got_first_packet,p_le_master_cont
-	fetch 1,mem_le_first_packet_count
-	sub pdata,6,null
-	nbranch p_le_master_disconn,positive
-	increase 1,pdata
-	store 1,mem_le_first_packet_count
-	branch p_le_master_cont
-
-
-
-
-
-
-
-
-
-
-
-
-p_le_get_public_addr:
-	fetcht 6,mem_le_lap
-	rtn
-	
-p_le_get_random_addr:
-	fetcht 6,mem_mesh_le_random_address
-	rtn
-
-
-p_le_send_adv_ind:
-	fetch 1,mem_le_adv_type
-	beq ADV_DIRECT_IND,le_send_adv_direct_ind
-	fetch 1,mem_le_adv_own_addr_type
-	lshift4 pdata,pdata
-	lshift2 pdata,pdata
-	fetcht 1,mem_le_adv_type
-	iadd temp,pdata
-	store 1,mem_le_txheader
-	fetcht 1,mem_le_adv_data_len
-	add temp,6,pdata
-	store 1,mem_le_txlen
-	copy temp,loopcnt
-	fetch 1,mem_le_adv_own_addr_type
-	call p_le_get_public_addr,blank
-	ncall p_le_get_random_addr,blank
-	storet 6,mem_le_txpayload
-	
-	arg mem_le_adv_data,contr
-	call memcpy_fast
-	branch le_send_adv_transmit	
-//	branch le_send_adv_ind+7
-
-p_le_update_param:
-	fetch 1,mem_le_state
-	rtnbit0 lestate_update_param
-	fetch 2,mem_le_event_count
-	fetcht 2,mem_le_instant
-	isub temp,pdata
-	store 2,mem_pdatatemp
-	nrtn positive
-	call le_update_param+7
-	branch z_hci_send_le_connection_update_commplete
-
-pop_stack_rega_b_c:
-	fetchr rega,4, mem_rega
-	fetchr regb,4, mem_regb
-	fetchr regc,3,mem_regc
-	rtn
-
-push_stack_rega_b_c:
-	storer rega,4, mem_rega
-	storer regb,4, mem_regb
-	storer regc,3, mem_regc
-	rtn
-p_le_context_nextevent:
-	call push_stack_rega_b_c
-	storer loopcnt,2,mem_loopcnt
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	rtnbit0 mode_le
-	add rega,coffset_le_event_cnt,contw
-	ifetch 2,contw
-	increase 1,pdata
-	istore 2,contw
-	call p_le_update_param_master
-	call p_le_update_channel_map
-	call  le_context_nexthop+8
-	call pop_stack_rega_b_c
-	fetchr loopcnt ,2,mem_loopcnt
-	rtn
-	
-//input: rega
-p_le_calc_channel_map:
-	add rega,coffset_le_channel_map,contr
-	ifetch 5,contr
-	force 0,temp
-	force 37,loopcnt
-p_le_count_channels_loop:
-	bbit0 0,le_count_channels_notused
-	increase 1,temp
-p_le_count_channels_notused:
-	rshift pdata,pdata
-	loop p_le_count_channels_loop
-	add temp,-1,pdata
-	add rega,coffset_le_channels,contw
-	istore 1,contw
-	rtn
-p_le_update_channel_map:
-	add rega,coffsset_state,contr
-	ifetch 1,contr
-	rtnbit0 lestate_update_map
-	
-	add rega,coffset_le_event_cnt,contr
-	ifetch 2,contr
-	fetcht 2,mem_le_instant
-	isub temp,pdata
-	nrtn positive
-	add rega,coffsset_state,contw
-	ifetch 1,contw
-	set0 lestate_update_map,pdata
-	istore 1,contw
-	store 1,mem_le_state
-	
- 	fetch 5,mem_le_new_map
- 	add rega,coffset_le_channel_map,contw
-	istore 5,contw
-	branch p_le_calc_channel_map	
-p_le_update_param_master:
-	add rega,coffsset_state,contr
-	ifetch 1,contr
-	rtnbit0 lestate_update_param	
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	rtnbit0 mode_master
-	add rega,coffset_le_event_cnt,contr
-	ifetcht 2,contr
-	fetch 2, mem_le_instant
-	isub temp,pdata
-	//nbranch p_le_check_update_small,positive
-	sub pdata,1,null
-	branch p_le_update_param_m,zero
-	rtn
-
-p_le_check_update_small:
-	add rega,coffset_le_event_cnt,contr
-	ifetch 2,contr
-	add rega,coffset_le_instant,contr
-	ifetch 2,contr
-	isub temp,pdata
-	arg 0xffff,temp
-	isub temp,null
-	branch p_le_update_param_m,zero
-	rtn
-
-p_le_update_param_m:
-	ifetch 1,rega
-	set0 lestate_update_param,pdata
-	istore 1,rega
-	
-	add rega,coffset_sniff_anchor,contr
-	ifetcht 4,contr
-	fetch 1,mem_le_new_transmitwindowsize
-	add rega,coffset_le_window_size,contw
-	istore 1,contw
-	ifetch 2,contr
-	lshift2 pdata,pdata
-	iadd temp,timeup    //window offset
-	increase 1,timeup
-	add rega,coffset_sniff_anchor,contw  
-	deposit timeup
-	istore 4,contw
-	ifetch 2,contr
-	lshift2 pdata,pdata
-	add rega,coffset_tsniff,contw
-	istore 2,contw
-	ifetch 4,contr
-	add rega,coffset_le_slave_latency,contw
-	istore 4,contw
-	rtn	
-	
-p_le_slave_unsync:
-//	call le_savelist
-	call le_lpm_set_mult
-	call le_update_channel_map
-	call p_le_update_param
-	branch calc_clke_offset
-
-
-
-
-
-//rega:len regb:ll opcode
-//le_fifo_malloc_tx_ll:
-//	arg LLID_LE_LL,type
-//	call le_fifo_malloc_tx
-//	copy regb,pdata
-//	istore 1,contw
-//	rtn
-
-
-
-
-
-
-
-
-p_le_receive_slave:
-	enable swfine
-	fetch 2,mem_le_receive_window
-	fetcht 4,mem_le_transmit_window
-	iadd temp,timeup
-p_le_receive_packet_slave:
-	call lerx_setfreq
-p_le_receive_rxon_slave:
-	call le_prep
-	disable match
-	disable user2 // for discard work
-	enable decode_fec0
-	enable is_rx
-	disable is_tx
-	copy timeup,stop_watch
-	correlate null,timeout
-	branch p_le_receive_on_attempt_slave,attempt
-	copy clke,temp
-	storet 6,mem_sync_clke
-p_le_receive_on_attempt_slave:
-	nbranch end_of_packet,sync
-	branch p_le_receive_skip_slave,attempt
-	arg param_clke_cal_le,clke_rt
-	copy bt_clk,clke_bt
-	fetch 1,mem_le_state
-	bbit0 lestate_got_first_packet,p_le_receive_skip_slave
-	call lpm_adjust_clk,wake
-p_le_receive_skip_slave:
-	call save_rssi
-	enable enable_white
-	enable enable_crc
-	parse demod,bucket,8
-	rshift3 pwindow,pdata
-	store 1,mem_le_rxbuf
-	// check retransmit
-	fetcht 1,mem_le_arq
-	//fetch 1,mem_le_rxbuf
-	rshift pdata,pdata
-	ixor temp,pdata
-	isolate1 nesn,pdata
-	setflag true,mark_old_packet,mark	/* retransmit */
-
-	// parse length	
-	parse demod,bucket,8
-	rshift3 pwindow,pdata
-	store 1,mem_le_rxbuf+1
-
-process_le_data_common:
-	//and pdata,0xff,pdata
-	copy pdata,loopcnt
-	store 1,mem_le_packet_size
-	branch p_lerx_nopayload_slave,blank							//empty rtn
-
-	fetch 1,mem_le_rxbuf
-	and pdata,0x03,pdata
-	beq LLID_LE_LL,process_le_LL
-
-	bmark1 mark_old_packet,p_lerx_discard_loop
-process_le_packet_common:
-	// reserve one big buffer for host
-	arg mem_alloc_big_block,rega
-	call p_queue_get_len
-	beq 1,p_lerx_discard_loop
-
-
-	call malloc_rcv_buffer_is_enough
-	branch p_lerx_discard_loop,blank
-	
-	call p_get_ble_rcv_ptr
-	copy contr,contw
-	fetch 2,mem_le_rxbuf
-	istore 2,contw
-	branch p_lerx_slave_loop
-
-process_le_LL:
-	arg mem_le_rxbuf+2,contw
-	branch p_lerx_slave_loop
-
-
-p_lerx_discard_loop:
-	// TODO: Think do more here
-	//branch end_of_packet
-
-	parse demod,bucket,8
-	rshift3 pwindow,pdata
-	//istore 1,temp
-	loop p_lerx_discard_loop
-
-	// use mark discard packet
-	enable user2
-
-	branch p_lerx_nopayload_slave
-
-p_lerx_slave_loop:
-	parse demod,bucket,8
-	rshift3 pwindow,pdata
-	istore 1,contw
-	loop p_lerx_slave_loop
-p_lerx_nopayload_slave:
-	parse demod,bucket,24	
-	enable swfine
-	arg param_sifs,stop_watch		// start SIFS timer after last bit of crc
-	branch p_lerx_nopayload_slave_end,user2
-	rshift32 pdata,pdata
-	rshift16 pdata,pdata
-	istore 3,contw // need save crc or not?
-p_lerx_nopayload_slave_end:
-ifdef RF_DEBUG
-	call rf_debug_active_crc_error_line,crc_failed
-endif	
-	branch end_of_packet,crc_failed
-	enable match
-	fetch 1,mem_sfreq_enable
-	nbranch p_lerx_nopayload_skip_write_freq,blank
-	fetch 1,mem_last_freq
-	add pdata,0,rega
-	call rf_write_freq				/* set frequency to tx mode freq */
-p_lerx_nopayload_skip_write_freq:
-	disable decode_fec0
-	branch set_sync_on
-
-p_le_parse_rcv_header:
-	ifetch 1,contr
-	and pdata,0x3,pdata
-	store 1,mem_le_packet_llid
-
-	ifetch 1,contr	//l2cap len
-	store 1,mem_le_packet_size
-	rtn blank
-
-	storer contr,2,mem_le_payload_ptr
-	rtn
-
-p_le_parse:
-	rtnmark1 mark_old_packet
-	rtnmark0 mark_le_mic_ok
-	rtn user2
-
-	// check length
-	fetch 1,mem_le_rxbuf+1
-	rtn blank
-	fetch 1,mem_le_rxbuf
-	and pdata,0x03,pdata
-	beq LLID_LE_LL,le_parse_ll
-
-	call p_get_ble_rcv_ptr
-	call p_le_parse_rcv_header
-	
-	fetch 1,mem_le_packet_size
-	rtn blank
-
-	fetch 1,mem_le_packet_llid
-	beq LLID_LE_LL,le_parse_ll
-p_le_parse_l2cap:
-	branch p_hci_send_acl_encode_le
-
-
-p_le_slave_more_data:
-	enable attempt
-	call p_le_transmit_receive_sifs_notx_slave
-	branch le_slave_match,match
-	branch le_slave_cont
-
-p_le_transmit_receive_sifs_notx_slave:
-	fetcht 1,mem_last_freq
-	call set_freq_rx
-	call rf_rx_enable
-	enable swfine
-	arg 5000,timeup	// about 417us
-	branch p_le_receive_rxon_slave
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//input1:rega --- mem block
-//output:regb --- block ptr
-p_queue_delete:
-	add rega,BLOCK_CUR_LEN_OFFSET,temp
-	ifetch 1,temp
-	branch assert,blank
-
-	add rega,BLOCK_RPTR_OFFSET,pdata
-	ifetcht 2,pdata
-	ifetchr regb,3,temp
-	setarg 0
-	istore 3,temp
-	add temp,3,regc
-	call queue_unit_increase
-	add rega,BLOCK_RPTR_OFFSET,pdata
-	istorer regc,2,pdata
-
-	add rega,BLOCK_CUR_LEN_OFFSET,temp
-	ifetch 1,temp
-	increase -1,pdata
-	istore 1,temp
-	rtn
-	
-//input --- rega
-p_queue_get_len:
-	add rega,BLOCK_CUR_LEN_OFFSET,temp
-	ifetch 1,temp
-	rtn
-	
-p_l2cap_load_channel_param:
-	arg 680,rege
-	fetch 1,mem_l2cap_temp_ch_psm
-	rtneq PSM_RFCOMM
-	branch l2cap_load_channel_param+2
-
-//input: regd -> len
-//rtn: regb,contr->ptr
-malloc_br_snd_buffer:
-	call malloc_buffer
-	arg mem_snd_br_block,rega
-	branch queue_insert
-
-free_br_snd_buffer:
-	arg mem_snd_br_block,rega
-	call queue_delete
-	branch free_buffer
-
-
-//input: regd -> len
-//rtn: regb,contr->ptr
-malloc_hci_snd_buffer:
-	call malloc_buffer
-	arg mem_snd_hci_block,rega
-	branch queue_insert
-
-//free_hci_snd_buffer:
-//	arg mem_snd_hci_block,rega
-//	call queue_delete
-//	branch free_buffer
-
-p_queue_insert:
-	add rega,BLOCK_WPTR_OFFSET,pdata
-	ifetcht 2,pdata
-	istorer regb,3,temp//store rxbuffer addr to wptr(start)
-	add temp,3,regc
-	call queue_unit_increase
-	add rega,BLOCK_WPTR_OFFSET,pdata
-	istorer regc,2,pdata
-	
-	add rega,BLOCK_CUR_LEN_OFFSET,regc
-	ifetcht 1,regc
-	increase 1,temp
-	istoret 1,regc
-	
-	// check buffer
-	add rega,BLOCK_TOTAL_SIZE_OFFSET,regc
-	ifetch 1,regc
-	isub temp,null
-	nbranch assert,positive
-	
-	copy regb,contr
-	copy regb,pdata
-	rtn
-
-
-/*********************************************************/
-//char* malloc(short len)
-//input: regd -> len
-//rtn: regb->ptr
-/*********************************************************/
-malloc_buffer:
-	call malloc_buffer_is_enough
-	branch assert,blank
-
-	fetch 2,mem_param_alloc_normal_buffer_max_length
-	increase -10,pdata // protect.
-	fetcht 2,mem_alloc_buffer_len
-	isub temp,null
-	branch malloc_buffer_normal,positive
-malloc_buffer_big:
-ifdef malloc_buffer_cnt_debug
-	fetch 2,mem_temp_alloc_big_malloc_cnt
-	increase 1,pdata
-	store 2,mem_temp_alloc_big_malloc_cnt
-endif
-	arg mem_alloc_big_block,rega
-	branch queue_delete
-malloc_buffer_normal:
-	arg mem_alloc_normal_block,rega
-	call p_queue_get_len
-	branch malloc_buffer_big,blank
-	
-ifdef malloc_buffer_cnt_debug
-	fetch 2,mem_temp_alloc_normal_malloc_cnt
-	increase 1,pdata
-	store 2,mem_temp_alloc_normal_malloc_cnt
-endif
-	arg mem_alloc_normal_block,rega
-	branch queue_delete
-
-/*********************************************************/
-//char* malloc(short len)
-//input: regb -> ptr
-//rtn: regb->ptr
-/*********************************************************/
-free_buffer:
-	call malloc_check_in_big_queue
-	arg mem_alloc_normal_block,rega
-	branch free_buffer_normal,blank
-free_buffer_big:
-ifdef malloc_buffer_cnt_debug
-	fetch 2,mem_temp_alloc_big_free_cnt
-	increase 1,pdata
-	store 2,mem_temp_alloc_big_free_cnt
-endif
-	arg mem_alloc_big_block,rega
-	branch queue_insert
-free_buffer_normal:
-	call malloc_check_in_normal_queue
-	branch assert,blank
-ifdef malloc_buffer_cnt_debug
-	fetch 2,mem_temp_alloc_normal_free_cnt
-	increase 1,pdata
-	store 2,mem_temp_alloc_normal_free_cnt
-endif
-	arg mem_alloc_normal_block,rega
-	branch queue_insert
-
-
-//input: regb -> buffer ptr
-malloc_check_in_normal_queue:
-	// store the big block ptr to list
-	fetchr loopcnt,1,mem_alloc_normal_total_size
-	arg mem_normal_block_ptr_list,contr
-	branch malloc_check_in_queue_loop
-
-
-//input: regd -> len
-//blank == 1, not in big queue
-malloc_check_in_big_queue:
-	// store the big block ptr to list
-	fetchr loopcnt,1,mem_alloc_big_total_size
-	arg mem_big_block_ptr_list,contr
-malloc_check_in_queue_loop:
-	ifetch 3,contr
-	isub regb,null
-	branch malloc_check_in_queue_end,zero
-	loop malloc_check_in_queue_loop
-malloc_check_in_queue_end:
-	copy loopcnt,pdata
-	rtn
-
-//input: regd -> len
-//rtn: blank == 0: enough
-malloc_buffer_is_enough:
-	fetch 2,mem_param_alloc_normal_buffer_max_length
-	increase -10,pdata // protect.
-	fetcht 2,mem_alloc_buffer_len
-	isub temp,null
-	//isub regd,null
-	branch malloc_buffer_is_enough_normal,positive
-malloc_buffer_is_enough_big:
-	arg mem_alloc_big_block,rega
-	branch p_queue_get_len
-malloc_buffer_is_enough_normal:
-	arg mem_alloc_normal_block,rega
-	call p_queue_get_len
-	nrtn blank	// if normal buffer is not enough, use big buffer.
-	branch malloc_buffer_is_enough_big
-
-//input: regd -> len
-//rtn: blank == 1: full
-
-malloc_buffer_is_full_big:
-	fetch 2,mem_param_alloc_big_buffer_max_length
-	branch malloc_buffer_is_full_raw
-malloc_buffer_is_full:
-	setarg 0x10
-malloc_buffer_is_full_raw:
-	store 2,mem_alloc_buffer_len
-	//arg 0x10,regd
-	
-	storer rega,4,mem_rega
-	call malloc_buffer_is_enough
-	fetchr rega,4,mem_rega
-	rtn
-
-// becouse we don't know the buffer length remote send.
-// or we can think do more in future, list read l2cap first two byte first?.
-malloc_rcv_buffer:
-
-ifdef malloc_buffer_cnt_debug
-	fetch 2,mem_temp_alloc_big_malloc_cnt
-	increase 1,pdata
-	store 2,mem_temp_alloc_big_malloc_cnt
-endif
-
-	arg mem_alloc_big_block,rega
-	branch queue_delete
-
-
-malloc_rcv_buffer_is_enough:
-	// avoid receive use all buffer
-	//arg mem_alloc_big_block,rega
-	//call p_queue_get_len
-	//copy pdata,temp
-	//arg mem_alloc_big_block,rega
-	//call p_queue_get_len
-	//iadd temp,pdata
-	//rtn blank
-	fetch 2,mem_rcv_br_queue_ptr
-	nrtn blank
-	
-	arg mem_alloc_big_block,rega
-	branch p_queue_get_len
-
-
-p_get_br_rcv_ptr:
-	fetch 3,mem_rcv_br_queue_ptr
-	nbranch get_pdata_contr,blank
-	call malloc_rcv_buffer
-	copy regb,pdata
-	store 3,mem_rcv_br_queue_ptr
-	branch get_pdata_contr
-
-
-
-p_get_ble_rcv_ptr:
-	fetch 3,mem_rcv_ble_queue_ptr
-	nbranch get_pdata_contr,blank
-	call malloc_rcv_buffer
-	copy regb,pdata
-	store 3,mem_rcv_ble_queue_ptr
-	branch get_pdata_contr
-
-p_app_process_bb_event:
-	//return if c51 need to process bb event
-	arg mem_ipc_fifo_bt2c51,rega
-	call fifo_out
-	rtn blank
-	//reaching here mains c51 cannot get bb event.
-	copy pdata,regc
-//	call app_event_normal_process
-	branch app_process_bb_event_priority
-
-p_app_event_normal_process:
-	copy regc,pdata
-	//beq BT_EVT_LE_CONNECTED,app_le_event_bb_connected
-	beq BT_EVT_LE_DISCONNECTED,p_app_le_event_bb_disconn
-	branch app_event_normal_process + 1
-
-
-p_app_le_event_bb_disconn:
-	jam 0,mem_mesh_recevie_acl_packet_number
-	jam 0,mem_mesh_le_version_exchange_times
-	call z_l2cap_ble_queue_init
-	call p_hci_send_event_le_disconnection_complete
-	branch app_le_event_bb_disconn
-
-p_le_check_wak:
-	fetcht 1,mem_le_arq
-	isolate0 wak,temp
-	rtn true
-	fetch 1,mem_le_rxbuf
-	lshift pdata,pdata
-	ixor temp,pdata
-	rtnbit0 sn			/* received NESN is same as SN, NAK */
-	set0 wak,temp
-	setflip sn,temp
-	storet 1,mem_le_arq
-	compare 3,temp,3
-	nrtn true
-	
-	fetch 1,mem_le_enc_state
-	beq FLAG_LE_ENC_PAUSE,le_clear_enc
-p_le_check_wak_end_ll:
-	fetch 1,mem_le_txpayload_temp
-	beq LL_TERMINATE_IND,p_le_master_disconn
-	beq LL_START_ENC_REQ,le_set_enc
-	rtn
-
-
-p_le_acknowledge:
-	call le_supervision_flush
-	call p_le_check_wak
-	fetch 1,mem_le_rxbuf
-	isolate1 md,pdata
-	setflag true,mark_ble_rx_md,mark
-	rshift pdata,pdata
-	ixor temp,pdata
-	isolate1 nesn,pdata
-	setflag true,mark_old_packet,mark	/* retransmit */
-	fetch 1,mem_le_rxbuf+1			
-	branch p_le_ack_unenc,blank		/* empty packet, no decryption */
-	fetch 1,mem_le_state
-	bbit0 lestate_encryption,p_le_ack_unenc
-	rtnmark1 mark_old_packet
-	call load_sk
-	call le_decrypt
-	setflag blank,mark_le_mic_ok,mark
-	nrtn blank
-p_le_ack_unenc:
-	rtn user2
-	rtnmark1 mark_old_packet
-	set1 mark_le_mic_ok,mark
-	fetcht 1,mem_le_arq
-	setflip nesn,temp
-	storet 1,mem_le_arq
-	rtn	
-
-p_le_adv:
-	fetch 1,mem_le_adv_enable
-	rtn blank
-	arg le_adv_interval_timer,queue
-	call timer_check
-	nrtn blank
-	branch z_le_adv
-
-
-
-
-p_le_fifo_release_first_node:
-	call free_ble_snd_buffer
-	deposit type
-	rtneq LLID_LE_LL
-	branch p_hci_send_event_number_of_completed_packet_le
-
-
-
-p_le_fifo_malloc_tx:
-	storer rega,2,mem_alloc_buffer_len
-	call malloc_ble_snd_buffer
-	copy regb,contw
-	fetch 2,mem_alloc_buffer_len
-	istore 1,contw
-	setarg 0
-	istore 1,contw
-	istorer type,1,contw
-	rtn
-
-malloc_ble_snd_buffer:
-	call malloc_buffer
-	arg mem_snd_ble_block,rega
-	branch queue_insert
-
-free_ble_snd_buffer:
-	arg mem_snd_ble_block,rega
-	call queue_delete
-	branch free_buffer	
-
-
-p_master_simple_paring_sequence:
-p_simple_pairing_sequence:
-	fetch 1,mem_sp_flag
-	nbranch z_simple_pairing_process,blank
-	fetch 1,mem_master_sp_flag
-	nbranch z_simple_pairing_process,blank
-	rtn
-
-
-p_parse_lmp_in_rand:
-	fetch 1,mem_op
-	set1 op_inrand_req,pdata
-	store 1,mem_op
-	call lmp_copy_rand
-	jam pincode_state_wait_pincode,mem_pincode_state
-	call p_hci_send_pincode_req_event
-//	branch parse_lmp_in_rand_hci
-	call tid_check
-	nbranch lmp_accept_inrand,true
-	nbranch parse_lmp_inrand_res,master // ignore this because of not ssp temporary
-	rtn
-	
-	
-p_sp_check_ssp_available:
-	//disable true
-	fetch 1,mem_simple_pairing_mode
-	rtn blank
-	//fetch 2,mem_lmpext_ssp_enable
-	//fetcht 1,mem_remote_sppcap
-	//iand temp,pdata
-	//rtn blank
-	fetch 1,mem_sp_state
-	nrtn blank			// avoid re-entry
-	
-	call context_search_plap
-	nrtn zero
-
-	// check if is master or slave 
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	rtnbit0 mode_master
-	call p_hci_send_io_cap_req_event
-	jam 0x01,mem_io_cap_flag //io cap req
-	rtn
-
-	
-//p_hci_send_user_confirmation_req_event:
-//	//call p_cmd_user_confirm_reply
-//	jam 10,mem_mesh_event_para_total_length
-//	jam HCI_EVENT_USER_CONFIRMATION_REQUEST,mem_mesh_event_head_event_code
-//	call p_hci_prepare_send_event
-//	fetch 6,mem_plap
-//	istore 6,contw
-	
-//	branch ipc_hci_tx_start
-
-p_hci_send_io_cap_req_event:
-	// BD_ADDR
-	jam 6,mem_mesh_event_para_total_length
-	jam HCI_EVENT_IO_CAP_REQ,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 6,mem_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-//p_hci_send_user_confirm_req_event:
-//	//BD_ADDR-6,Numeric_Value-4
-//	jam 10,mem_mesh_event_para_total_length
-//	jam HCI_EVENT_USER_CONFIRMATION_REQUEST,mem_mesh_event_head_event_code
-//	call p_hci_prepare_send_event
-//	fetch 6,mem_plap
-//	istore 6,contw
-//	fetch 4,mem_gkey	//mem_sp_gkey
-//	istore 4,contw
-//	branch ipc_hci_tx_start
-
-//hci_send_sp_complete_event:
-//	//Status-1,BD_ADDR-6
-//	jam 7,mem_mesh_event_para_total_length
-//	jam HCI_EVENT_SIMPLE_PAIRING_COMPLETE,mem_mesh_event_head_event_code
-//	call p_hci_prepare_send_event
-//	force 0,pdata
-//	istore 1,contw
-//	fetch 6,mem_plap
-//	istore 6,contw
-//	branch ipc_hci_tx_start
-
-
-
-
-	//jam LMP_IO_CAP_RES,mem_lmo_opcode2
-	//rtn
-
-
-
-
-
-
-
-
-process_dmh_common_zero_len:
-	fetch 1,mem_lch_code
-	and_into 0x03,pdata
-	bne LLID_L2CAP_CONT,process_dmh_data_end
-	// If we have no buffer to receive packet, then stop receive new packet
-	arg mem_alloc_big_block,rega
-	call queue_get_len
-	branch end_of_packet,blank
-	branch process_dmh_data_end
-
-
-
-
-p_process_dmh_common:
-	//storer loopcnt,2,mem_len
-	deposit loopcnt
-	store 2,mem_len
-	branch process_dmh_common_zero_len,blank
-	isub mask3ff,null
-	branch error_payload,positive	/* packet too large, discard */
-	and mark,0x01,pdata
-//	set0 mark_fhs_eir,mark
-	nbranch p_process_dmh_common_packet1,blank
-p_process_dmh_common_packet:	
-	// reserve one big buffer for host
-//	arg mem_alloc_big_block,rega
-//	call p_queue_get_len
-//	beq 1,end_of_packet
-	
-	fetch 1,mem_lch_code
-	and_into 0x03,pdata
-	beq LLID_LMP,process_lmp
-
-	// l2cap
-	bmark1 mark_old_packet,ack_payload
-p_process_dmh_common_packet1:
-	fetcht 2,mem_l2cap_rx_max_lenth
-	increase -3,temp
-	fetch 2,mem_len	
-	isub temp,null
-	branch error_payload,positive
-	
-	// reserve one big buffer for host
-	arg mem_alloc_big_block,rega
-	call p_queue_get_len
-	beq 1,end_of_packet
-
-	call malloc_rcv_buffer_is_enough
-	branch end_of_packet,blank
-
-p_process_dmh_data_into_buff_normal:
-	call p_get_br_rcv_ptr
-	copy contr,contw
-
-	fetch 1,mem_lch_code
-	istore 1,contw
-	fetch 2,mem_len
-	istore 2,contw
-	branch process_dmh_data
-
-
-
-p_process_dmh_data_end:
-	parse demod,bucket,16  /* cycle through the crc */
-
-	call rf_debug_active_crc_error_line,crc_failed
-
-//	fetch 1,mem_tws_state
-//	beq TWS_STATE_SLAVE_CONNECTED,process_dmh_data_end_tws
-//	beq TWS_STATE_MASTER_LISTEN,process_dmh_data_end_tws
-//	beq TWS_STATE_MASTER_CONNECTED,process_dmh_data_end_tws
-	
-	branch error_payload_crc,crc_failed
-	bmark0 mark_fhs_eir,process_dmh_packet
-	set0 mark_fhs_eir,mark
-	rtn
-
-
-
-p_process_dmh_l2cap_packet:
-	// Just send buffer 
-	call p_hci_send_acl_encode_classic
-
-	branch process_dmh_cont
-
-
-
-
-
-
-// Classic Snd Manager
-/*********************************************************/
-//char* malloc(short len)
-//input: rega -> len
-//rtn: regb -> pbuff;return from pdata
-//val: queue -> i
-//val: timeup -> buff_cnt
-/*********************************************************/
-p_l2cap_malloc:
-	storer rega,2,mem_alloc_buffer_len
-
-	call malloc_br_snd_buffer
-	fetchr rega,2,mem_alloc_buffer_len
-	rtn
-
-/*********************************************************/
-//void* l2cap_malloc_fifo_out(void)
-//output:len -> temp
-//output:ptr ->pdata
-//only get ptr,not free
-/*********************************************************/
-p_l2cap_malloc_fifo_out:
-	arg mem_snd_br_block,rega
-	branch queue_get_read_ptr
-
-/*********************************************************/
-//void free_first_buff_in_fifo(void)
-//only free the first one
-/*********************************************************/
-p_l2cap_malloc_free:
-	call free_br_snd_buffer
-	branch p_hci_send_event_number_of_completed_packet_classic
-/*********************************************************/
-//void l2cap_malloc_discard(void)
-//discard the latest malloc
-/*********************************************************/
-p_l2cap_malloc_discard:
-	branch free_br_snd_buffer
-/*********************************************************/
-//bool fifo_is_full(void)
-//blank == 1: not full
-//blank == 0: full
-/*********************************************************/
-p_l2cap_malloc_is_fifo_full:
-	call malloc_buffer_is_full_big
-	branch setarg1,blank
-	branch setarg0
-
-/*********************************************************/
-//bool fifo_nearly_full(void)
-//blank == 1: nearly full
-//blank == 0: not nearly full
-/*********************************************************/
-
-//p_l2cap_malloc_is_fifo_nearly_full:
-//	arg mem_alloc_big_block,rega
-//	call queue_get_len
-//	copy pdata,regb
-
-//	arg mem_alloc_normal_block,rega
-//	call queue_get_len
-//	iadd regb,pdata
-
-//	// reserve 2 buffer, sometimes need send two packet.
-//	sub pdata,2,null
-
-//	branch setarg1,positive
-//	branch setarg0
-
-
-/*********************************************************/
-//bool fifo_is_empty(void)
-//blank == 1: empty
-//blank == 0: not empty
-/*********************************************************/
-p_l2cap_malloc_is_fifo_empty:
-	arg mem_snd_br_block,rega
-	branch p_queue_get_len
-
-/*********************************************************/
-//char* l2cap_malloc_fifo_get_first_ptr(void)
-//output:contr  -->ptr
-/*********************************************************/	
-p_l2cap_malloc_fifo_get_first_ptr:
-	branch assert
-
-
-
-
-
-p_scheduler_tx_l2cap_pkt:
-	call p_l2cap_malloc_is_fifo_empty
-	rtn blank //empty
-	
-	fetch 1,mem_op
-	rtnbit1 op_txl2cap
-	call l2cap_malloc_fifo_out
-	//store 2,mem_txptr
-	//copy pdata,contr
-	ifetch 2,contr
-	store 2,mem_tx_len
-
-	ifetch 1,contr
-	set1 2,pdata //set go bit
-	store 1,mem_tx_lch//start pkt
-	
-	copy contr,pdata
-	store 2,mem_txptr
-
-	fetch 2,mem_l2cap_tx_multi_offset
-	branch p_scheduler_tx_l2cap_start_pkt,blank
-	// not think continue will send 2dh5, reduce code size
-	branch scheduler_tx_l2cap_cont_pkt
-p_scheduler_tx_l2cap_start_pkt:
-	fetch 2,mem_tx_len
-	branch assert,blank
-	arg l2cap_max_pkt_len_new,temp //max len of 2dh5 pkt
-	isub temp,pdata
-	branch scheduler_Tx_l2cap_last_pkt,zero
-	branch scheduler_tx_l2cap_start_pkt+4
-
-
-
-
-
-
-p_init_lmp_work:
-	jam 0,mem_link_key_exists
-	branch  init_lmp_work+1
-
-
-
-
-
-
-
-
-
-
-/*
-	Dynamic load, use for "mergepatch.pl"
-*/
-p_zcode_entrance_2Bytes_common:
-	store 2, mem_zcode_temp_param0
-	branch p_zcode_entrance
-
-p_zcode_entrance:
-	fetcht 2,mem_zcode_temp_param0 // zcode number @ high 4bit
-	rshift4 temp,temp
-	fetch 2,mem_zcode_current_number
-	isub temp,null
-	branch zcode_run,zero // if this zcode is already loaded, do not load again
-	storet 2,mem_zcode_current_number
-p_load_zcode:
-	//increase 1,temp
-	setarg ZCODE_BUFF_SIZE
-	imul32 temp,temp
-	fetch 3,mem_xip_flash_offset
-	isub temp,pdata
-	fetcht 3,mem_storage_start_addr
-	iadd temp,pdata
-	increase -4,pdata
-	store 3,mem_flash_address
-	setarg ZCODE_BUFF_SIZE
-	store 2,mem_flash_trans_length
-	setarg mem_zcode_buff_user
-	store 2,mem_flash_data_address
-	call qspi_get_lock
-	call check_m0_qspi_lock_and_pause
-	fetch 1,core_qspi_ctrl
-	store 1,mem_pdatatemp
-	call qspi_read
-	fetch 1,mem_pdatatemp
-	store 1,core_qspi_ctrl
-
-	jam 0,mem_qspi_lock_flag_respin
-	//call qspi_free_lock
-
-	setarg mem_zcode_buff_user
-	branch zcode_entrance0
-
-
-ifdef TEST_QUEUE_DEBUG
-//input: pdata
-test_buffer_check:
-	// start ptr
-	arg mem_alloc_big_block_start,rega
-	arg 10,loopcnt
-test_buffer_check_loop:
-	ifetcht 3,rega
-	isub temp,null
-	call ice_break,zero
-	// regb store the target ptr
-	add rega,3,rega
-	loop test_buffer_check_loop
-	rtn
-endif	
-
-p_le_slave_disconn:
-	call le_att_destroy_notify_pool
-	//fall through
-p_le_disconnect:
-	call le_clear_connection_info+1
-	call app_disconn_reason_collect_ble
-ifdef SECURE_CONNECTION
-	call sp_initialize_256
-endif
-	fetch 1,mem_le_state
-	set0 state_inconn,pdata
-	set0 state_insniff,pdata
-	store 1,mem_le_state
-	jam BT_EVT_LE_DISCONNECTED,mem_fifo_temp
-	branch ui_ipc_send_event	
-
-p_le_master_disconn:
-	call p_le_disconnect
-	disable master
-	rtn	
-
-p_lpm_dispatch_unconn:
-	fetch 1,mem_context
-	rtnbit1 state_inconn					// wont sleep in connection
-	rtnbit1 state_inpage					// wont sleep when paging
-	fetch 1,mem_ssp_enable
-	branch p_lpm_unconn_nossp,blank
-	fetch 1,mem_sp_local_key_invalid	// simple pairing is not ready
-	rtn blank
-p_lpm_unconn_nossp:
-//	fetch 1,mem_le_adv_enable
-//	nbranch lpm_unconn_cont,blank
-	branch lpm_unconn_cont
-
-cb_enter_lpm:
-	fetch 1,mem_lmp_conn_state
-	store 1,mem_xlmp_conn_state
-	branch z_enter_hibernate_prepare_work
-	
-
-cb_enter_hibernate:
-//	call ice_break
-	jam MCU_STATE_HIBERNATE,mem_ipc_mcu_state
-	call ipc_check_ack
-	branch z_enter_hibernate_prepare_work
-
-p_lpm_dispatch:
-ifdef MINZHAN_SDK
-	fetch 1,mem_ota_enable_xip_flag
-	beq OTA_NEED_ENABLE_XIP_FLAG,p_loadcode_normal
-endif	
-	fetch 1,mem_lpm_mode
-	rtn blank
-	call p_l2cap_malloc_is_fifo_empty
-	nrtn blank
-	arg mem_snd_ble_block,rega
-	call p_queue_get_len	
-	nrtn blank
-	arg mem_alloc_big_block,rega
-	call p_queue_get_len
-	fetcht 1,mem_alloc_normal_total_size
-	isub temp,null
-	nrtn zero
-	branch lpm_dispatch+12
-
-ifdef MINZHAN_SDK
-p_loadcode_normal:
-	branch soft_reset
-endif
-
-//get qspi lock
-qspi_get_lock:
-	jam 1,mem_qspi_lock_flag_respin // I'm interested
-
-	jam QSPI_LOCK_VICTIM_RESPIN,mem_qspi_lock_victim// you go first
-qspi_get_lock_wait:
-	fetch 1,mem_qspi_lock_flag_cm0
-	rtn blank
-	
-	fetch 1,mem_qspi_lock_victim
-	rtnne DEBUG_LOG_LOCK_VICTIM_RESPIN
-	branch qspi_get_lock_wait
-
-//free qspi lock
-//qspi_free_lock:
-//	jam 0,mem_qspi_lock_flag_respin
-//	rtn
-ifdef FYT_LJ_TEST
-p_feasyblue_test:
-p_feasyblue_assert_patch_counts_protect:
-	arg mem_patch00,contr
-	arg 0x40,loopcnt
-	setarg 0
-p_feasyblue_assert_patch_counts_protect_loop:
-	ifetcht 1,contr
-	iadd temp,pdata
-	loop p_feasyblue_assert_patch_counts_protect_loop
-	arg 0x5b9,temp
-	isub temp,null
-	ncall ice_break,zero
-//	rtn
-p_headset_end_addr_blank_protect:
-	arg mem_headset_end,contr
-	arg 0x10,loopcnt
-	setarg 0
-p_headset_end_addr_blank_protect_loop:
-	ifetcht 1,contr
-	iadd temp,pdata
-	loop p_headset_end_addr_blank_protect_loop
-	ncall ice_break,blank
-	rtn
-endif
-
-/*
- *in remote test,it may occured that we received a wrong packet header in low probability.
- *the hv3 and 2ev3 type packet have no protection.
- * We didn't judge the length of the package,the value of mem_sco_rx_packet_len is zero in default. so command 'loop' may errors.
-*/
-p_rx_type_dispatch:
-	deposit type
-	beq type_hv3, end_of_packet
-	beq type_2ev3,end_of_packet
-	branch rx_type_dispatch+2
-	
Index: ModuleDemo/25_OTA/bt_demo/BT/patch/patch_sdk.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/patch_sdk.prog	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/patch_sdk.prog	(nonexistent)
@@ -1,5 +0,0 @@
-define SDKCODE
-ifdef SDKCODE
-INCLUDE "bt_format"
-org 0x0000  // start from patch ram address start
-endif
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/BT/patch/z.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/z.prog	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/patch/z.prog	(nonexistent)
@@ -1,2700 +0,0 @@
-
-
-
-org z
-z_hci_parse_packet_cmd_ogf_link_control:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_INQUIRY,z_hci_parse_packet_cmd_ogf_link_control_inquiry	//1
-	beq HCI_INQUIRY_CANCEL,z_hci_parse_packet_cmd_ogf_link_control_inquiry_cancel	//2
-	beq HCI_CREATE_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_create_connection	//5
-	beq HCI_ACCEPT_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_accept_connection	//9
-
-	branch z_hci_parse_packet_cmd_ogf_link_control1
-	
-
-z_hci_parse_packet_cmd_ogf_link_control_inquiry:	//1
-	set1 mark_inquiry_on,mark
-	call p_ipc_rx_hci_data_thr_byte
-	store 3,mem_glap
-	call p_ipc_rx_hci_data_one_byte
-	arg 2048,temp
-	imul32 temp,pdata
-	arg 0xffff,temp
-	isub temp,null
-	nbranch z_hci_inquiry_nowrap,positive
-	deposit temp
-z_hci_inquiry_nowrap:
-	force inquiry_length_timer,queue
-	call timer_init
-	call p_ipc_rx_hci_data_one_byte //todo
-	store 1,mem_inquiry_num_responses
-	store 1,mem_inquiry_num_check
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_control_inquiry_cancel:	//2
-	jam hci_cmd_inquiry_cancel,mem_hci_cmd
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_link_control_create_connection:		//5
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_packet_type
-	call p_ipc_rx_hci_data_two_byte
-	store 1,mem_page_mode
-	call p_ipc_rx_hci_data_two_byte /*read clock*/
-//	bbit0 15,z_create_connection_unsave_clk_offset
-//	iadd clkn_bt,pdata
-//	and_into 0x1fc,pdata
-//	store 4,mem_page_clk
-//z_create_connection_unsave_clk_offset:
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_allow_switch
-	jam 1,mem_conn_status
-	jam hci_cmd_create_conn,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_control_accept_connection:	//9
-	fetch 1,mem_conn_req_status
-	beq 0,p_hci_send_event_command_status_err_unknown_connection
-	beq 2,p_hci_send_event_command_status_err_command_disallowed
-	fetch 1,mem_conn_status
-	beq 2,p_hci_send_event_command_status_err_command_disallowed
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	jam hci_cmd_accept_conn,mem_hci_cmd
-	call p_ipc_rx_hci_data_one_byte
-	beq 1,p_hci_send_event_command_status	
-	jam hci_cmd_accept_with_switch,mem_hci_cmd
-	call p_hci_send_event_command_status
-	branch accept_lmp_msg
-
-org z
-z_hci_parse_packet_cmd_ogf_controller_and_baseband:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_SET_EVENT_MASK,z_hci_parse_packet_cmd_ogf_controller_and_baseband_set_event_mask	//01
-	beq HCI_WRITE_LOCAL_NAME,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_local_name	//13
-	beq HCI_READ_LOCAL_NAME,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_local_name	//14
-	beq HCI_READ_PAGE_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_timeout	//17
-	beq HCI_WRITE_PAGE_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_timeout	//18
-	beq HCI_READ_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_scan_enable	//19
-	beq HCI_WRITE_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_scan_enable	//1A
-	beq HCI_READ_PAGE_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_activity	//1B
-	
-	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband1
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_set_event_mask:
-	call p_ipc_rx_hci_data_eight_byte
-	store 8,mem_mesh_event_mask
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_local_name:
-	call p_ipc_rx_restore_contr
-	arg mem_local_name,contw
-	arg 66,loopcnt
-	call memcpy
-	arg 66,loopcnt
-	arg mem_local_name,contr
-	arg 0,temp
-	call p_check_tx_length
-	storet 1,mem_local_name_length
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_local_name:
-	arg 249,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	arg mem_local_name,contr
-	arg 64,loopcnt
-	call memcpy_loop
-	arg 23,loopcnt
-	call memset0
-	branch ipc_hci_tx_start
-	
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_timeout:	//17
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 2, mem_page_to
-	istore 2,contw
-	branch ipc_hci_tx_start
-	
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_timeout:	//18
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_page_to
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_scan_enable:	//19
-	arg 2,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_scan_mode
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_scan_enable:	//1A
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_scan_mode
-	branch p_hci_send_event_command_complete_without_payload
-
-
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_activity:	//1B
-	arg 5,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	//setarg 0x0013
-	fetch 2,mem_pscan_interval
-	istore 2,contw
-	//setarg 0x0014
-	fetch 2,mem_pscan_window
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-
-org z
-z_hci_parse_packet_cmd_ogf_infomational_parameters:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_READ_LOCAL_VERSION_INFORMATION,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_version_information
-	beq HCI_READ_LOCAL_SUPPORTED_COMMANDS,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_command
-	beq HCI_READ_LOCAL_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_features
-	beq HCI_READ_LOCAL_EXT_FEATURES,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_local_ext_features
-	beq HCI_READ_BUFFER_SIZE,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_buffer_size
-	beq HCI_READ_BD_ADDR,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_bd_addr
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_version_information:
-	arg 9,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 8,mem_mesh_read_local_version_info
-	istore 8,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_command:
-	arg 65,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	arg mem_mesh_read_local_support_command,contr
-	arg 64,loopcnt
-	call memcpy
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_features:
-	arg 9,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 8,mem_features
-	istore 8,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_bd_addr:
-	arg 7,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 6,mem_lap
-	istore 6,contw
-	branch ipc_hci_tx_start
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_local_ext_features:
-z_hci_parse_packet_cmd_ogf_infomational_parameters_read_buffer_size:
-	arg 8,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	setarg 680
-	istore 2,contw
-	setarg 60
-	istore 1,contw
-	setarg 8
-	istore 2,contw
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-
-org z
-z_hci_parse_packet_cmd_ogf_le_controller:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_LE_SET_EVENT_MASK,z_hci_parse_packet_cmd_ogf_le_controller_set_event_mask	//01
-	beq HCI_LE_READ_BUFFER_SIZE,z_hci_parse_packet_cmd_ogf_le_controller_read_buffer_size		//02
-	beq HCI_LE_READ_LOCAL_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_le_controller_read_supported_features	//03
-	beq HCI_LE_SET_RANDOM_ADDRESS,z_hci_parse_packet_cmd_ogf_le_controller_set_random_address		//05
-	beq HCI_LE_SET_ADVERTISING_PARAMETERS,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_para	//06
-	branch z_hci_parse_packet_cmd_ogf_le_controller1
-	
-z_hci_parse_packet_cmd_ogf_le_controller_set_event_mask:	//01
-	call p_ipc_rx_hci_data_eight_byte
-	store 8,mem_mesh_le_event_mask
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_read_buffer_size:	//02
-	arg 4,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	setarg 0x0400fb
-	istore 3,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_le_controller_read_supported_features:	//03
-	arg 9,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 8,mem_le_features
-	istore 8,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_random_address:		//05
-	fetch 1,mem_le_adv_enable
-	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_mesh_le_random_address
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_adv_para:		//06
-	fetch 1,mem_le_adv_enable
-	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
-	call p_ipc_rx_hci_data_two_byte	//Advertising interval min
-	store 2,mem_le_adv_interval_min
-	call p_ipc_rx_hci_data_two_byte	//Advertising interval max
-	store 2,mem_le_adv_interval_max
-	call p_ipc_rx_hci_data_one_byte	//Advertising type
-	call z_hci_check_advertising_type
-	storet 1,mem_le_adv_type
-	call p_ipc_rx_hci_data_one_byte	//Own address type
-	call z_hci_set_public_addr,blank
-	ncall z_hci_set_random_addr,blank
-	call p_ipc_rx_hci_data_one_byte	//Peer Address type
-	call p_ipc_rx_hci_data_six_byte	//Peer Address
-	call p_ipc_rx_hci_data_one_byte	//Advertising channel map
-	store 1,mem_le_adv_channel_map
-	call p_ipc_rx_hci_data_one_byte //Advertising_Filter_Policy
-	store 1,mem_le_white_list_filter_policy
-	branch p_hci_send_event_command_complete_without_payload	
-
-z_hci_check_advertising_type:
-	arg ADV_IND,temp
-	rtneq 0x00
-	arg ADV_NONCONN_IND,temp
-	rtneq 0x03
-	arg ADV_SCAN_IND,temp
-	rtneq 0x02
-	arg ADV_DIRECT_IND,temp
-	rtn
-
-z_hci_set_public_addr:
-	fetcht 6,mem_device_public_address
-	storet 6,mem_le_lap
-	jam PUBLIC_ADDR,mem_le_adv_own_addr_type
-	rtn
-z_hci_set_random_addr:
- 	jam RANDOM_ADDR,mem_le_adv_own_addr_type
-	rtn
-
-
-org z
-z_hci_parse_packet_cmd_ogf_link_policy:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_SNIFF_MODE,z_hci_parse_packet_cmd_ogf_link_policy_sniff_mode
-	beq HCI_EXIT_SNIFF_MODE,z_hci_parse_packet_cmd_ogf_link_policy_exit_sniff_mode
-	beq HCI_SWITCH_ROLE,z_hci_parse_packet_cmd_ogf_link_policy_switch_role	//B
-	beq HCI_READ_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_read_link_policy_settings    //C
-	beq HCI_WRITE_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_write_link_policy_settings    //D
-	branch z_hci_parse_packet_cmd_ogf_link_policy_branch1
-
-z_hci_parse_packet_cmd_ogf_link_policy_sniff_mode:
-	fetch 2,mem_link_policy_settings
-	bbit0 Sniff_Mode,p_hci_send_event_command_status_err_command_disallowed
-	fetch 2,mem_default_link_policy_settings
-	bbit0 Sniff_Mode,p_hci_send_event_command_status_err_command_disallowed
-	fetch 1,mem_conn_status
-	bne 2,p_hci_send_event_command_status_err_unknown_connection
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_hci_sniff_conn_handle
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_hci_sniff_max_interval
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_hci_sniff_min_interval
-	setarg 0x40
-	store 2,mem_sniff_param_interval
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_sniff_param_attempt
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_sniff_param_timeout
-	jam hci_cmd_in_sniff,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_policy_exit_sniff_mode:
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_hci_sniff_conn_handle
-	fetch 1,mem_mode
-	bbit0 acl_in_sniff,p_hci_send_event_command_status_err_command_disallowed
-	jam hci_cmd_exit_sniff,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_policy_switch_role:	//B
-	fetch 1,mem_conn_status
-	bne 2,p_hci_send_event_command_status_err_unknown_connection
-	fetch 2,mem_link_policy_settings
-	bbit0 Role_Switch,p_hci_send_event_command_status_err_command_disallowed
-	fetch 2,mem_default_link_policy_settings
-	bbit0 Role_Switch,p_hci_send_event_command_status_err_command_disallowed
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_one_byte //todo deal
-	jam hci_cmd_role_switch,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_policy_read_link_policy_settings:
-	call p_hci_parse_connection_handle_check
-	arg 5,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	fetch 2,mem_link_policy_settings
-	istore 2,contw
-	branch ipc_hci_tx_start
-	
-z_hci_parse_packet_cmd_ogf_link_policy_write_link_policy_settings:
-	call p_hci_parse_connection_handle_check
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_link_policy_settings
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-org z
-z_hci_parse_packet_cmd_ogf_link_policy_branch1:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_READ_DEFAULT_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_read_default_link_policy_settings    //E
-	beq HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_write_default_link_policy_settings     //F
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-
-z_hci_parse_packet_cmd_ogf_link_policy_read_default_link_policy_settings:
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 2,mem_default_link_policy_settings
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_link_policy_write_default_link_policy_settings:
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_default_link_policy_settings
-	branch p_hci_send_event_command_complete_without_payload
-	
-org z
-z_hci_parse_packet_cmd_ogf_controller_and_baseband1:
-	fetch 1,mem_mesh_hci_opcode_ocf	
-	beq HCI_WRITE_PAGE_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_paga_scan_activity	//1C
-	beq HCI_READ_INQUIRY_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_activity	//1D
-	beq HCI_WRITE_INQUIRY_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_activity	//1E
-	beq HCI_READ_CLASS_OF_DEVICE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_class_of_device		//23
-	beq HCI_WRITE_CLASS_OF_DEVICE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_class_of_device		//24
-	beq HCI_READ_INQUIRY_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_type	//42
-	beq HCI_WRITE_INQUIRY_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_type	//43
-	beq HCI_READ_INQUIRY_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_mode	//44
-	beq HCI_WRITE_INQUIRY_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_mode	//45
-	beq HCI_READ_PAGE_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_type	//46
-	beq HCI_WRITE_PAGE_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_scan_type	//47
-	beq HCI_READ_EXTENDED_INQUIRY_RESPONSE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_eir //51
-
-	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband2
-	
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_paga_scan_activity:	//1C
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_pscan_interval
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_pscan_window
-	branch p_hci_send_event_command_complete_without_payload
-	
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_activity:	//1D
-	arg 5,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	//setarg 0x0013
-	fetch 2,mem_iscan_interval
-	istore 2,contw
-	//setarg 0x0014
-	fetch 2,mem_iscan_window
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_activity:	//1E
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_iscan_interval
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_iscan_window
-	branch p_hci_send_event_command_complete_without_payload
-
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_class_of_device:
-	arg 4,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 3,mem_class
-	istore 3,contw
-	branch ipc_hci_tx_start
-	
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_class_of_device:
-	call p_ipc_rx_hci_data_thr_byte
-	store 3,mem_class
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_type:	//42
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_type:	//43
-	call p_ipc_rx_hci_data_one_byte
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_mode:	//44
-	arg 2,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_inquiry_mode
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_mode:	//45
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_inquiry_mode
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_type:	//46
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_scan_type:	//47
-	//Standard Scan, normal reply
-	call p_ipc_rx_hci_data_one_byte
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_eir:    //51
-	arg 242,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_fec_required
-	istore 1,contw
-	// TODO: here think use match length, like 240
-	arg mem_eir,contr
-	arg 100,loopcnt
-	call memcpy
-	//call memset0
-	branch ipc_hci_tx_start
-
-
-
-org z
-z_hci_parse_packet_cmd_ogf_link_control1:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_DISCONNECT,z_hci_parse_packet_cmd_ogf_link_control_disconnect	//6
-	beq HCI_CREATE_CONNECTION_CANCEL,z_hci_parse_packet_cmd_ogf_link_control_create_connection_cancel	//8
-	beq HCI_REJECT_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_reject_connection	//A
-
-	branch z_hci_parse_packet_cmd_ogf_link_control2
-	
-	
-z_hci_parse_packet_cmd_ogf_link_control_disconnect:
-	call p_ipc_rx_hci_data_two_byte	/*connect handle*/
-	store 1,mem_hci_conn_handle
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_disconn_reason_send
-	
-	call context_search_conn_handle
-	nbranch p_hci_send_event_command_status_err_unknown_connection,zero
-
-	// check is classic or ble
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	bbit1 mode_le,z_hci_control_disconnect_le
-
-z_hci_control_disconnect_classic:
-	jam hci_cmd_disconn,mem_hci_cmd
-	//jam 0x16,mem_disconn_reason
-	fetch 1,mem_hci_conn_handle
-	fetcht 1,mem_sco_handle
-	isub temp,null
-	nbranch p_hci_send_event_command_status,zero
-	jam hci_cmd_disconn_sco,mem_hci_cmd
-	fetch 1,mem_sco_asso_handle
-	store 1,mem_hci_conn_handle
-	branch p_hci_send_event_command_status
-
-z_hci_control_disconnect_le:
-	fetch 1,mem_disconn_reason_send
-	store 1,mem_temp
-	call le_send_terminate_ind
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_control_create_connection_cancel:	//8
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	jam hci_cmd_detach,mem_hci_cmd
-	fetch 1,mem_conn_status
-	beq 0x01,z_hci_create_conn_cancel_success
-	beq 0x02,z_hci_connection_already_exists_err
-	branch z_hci_connection_cancel_err_no_connection
-z_hci_connection_already_exists_err:
-	jam HCI_ERROR_MAX_ACL_CONNECTIONS,mem_mesh_command_complete_return_parameter_status
-	branch z_hci_connection_cancel_err
-z_hci_create_conn_cancel_success:
-	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
-	call z_hci_connection_cancel_err
-	jam HCI_ERROR_NO_CONNECTION,mem_mesh_event_parameter_status
-	branch p_hci_send_connection_rtn_error
-z_hci_connection_cancel_err_no_connection:
-	jam HCI_ERROR_NO_CONNECTION,mem_mesh_command_complete_return_parameter_status
-z_hci_connection_cancel_err:
-	arg 7,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status
-	fetch 6,mem_hci_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_link_control_reject_connection:	//A
-	fetch 1,mem_conn_req_status
-	beq 0,p_hci_send_event_command_status_err_unknown_connection
-	beq 2,p_hci_send_event_command_status_err_command_disallowed
-	fetch 1,mem_conn_status
-	beq 2,p_hci_send_event_command_status_err_command_disallowed
-	jam 2,mem_conn_req_status
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_one_byte	//todo
-	store 1,mem_mesh_event_parameter_status
-	jam hci_cmd_reject_conn,mem_hci_cmd
-	call p_hci_send_event_command_status
-	branch p_hci_send_connection_rtn_error
-
-
-org z
-z_hci_parse_packet_cmd_ogf_link_control2:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_LINK_KEY_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_link_key_request_reply	//B
-	beq HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY,z_hci_parse_packet_cmd_ogf_link_control_link_key_request_negative_replay	//C
-	beq HCI_PIN_CODE_REQUEST_REPLY,z_hci_pin_code_request_reply
-	beq HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY,z_hci_pin_code_request_negative_reply
-	beq HCI_AUTHENTICATION_REQUESTED,z_hci_parse_packet_cmd_ogf_link_control_authentication_requested	//11
-	beq HCI_SET_CONNECTION_ENCRYPTION,z_hci_parse_packet_cmd_ogf_link_control_set_connection_encryption	//13
-
-	branch z_hci_parse_packet_cmd_ogf_link_control3
-	
-
-z_hci_parse_packet_cmd_ogf_link_control_link_key_request_reply:	//B
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	arg mem_link_key,contw
-	force 16,loopcnt
-	call p_ipc_rx_hci_data_n_byte
-	jam 1,mem_link_key_exists
-	jam hci_cmd_linkkey,mem_hci_cmd
-	branch z_hci_pin_code_reply
-
-z_hci_parse_packet_cmd_ogf_link_control_link_key_request_negative_replay:	//C
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	jam hci_cmd_nokey,mem_hci_cmd
-	call z_hci_pin_code_reply
-	call p_sp_check_ssp_available
-	fetch 1,mem_simple_pairing_mode
-	branch p_hci_send_pincode_req_event,blank
-	//force 0x01,pdata
-	//store 1,mem_io_cap_flag
-	//fetch 1,mem_simple_pairing_mode
-	//beq  1,p_hci_send_io_cap_req_event
-	//branch p_hci_send_pincode_req_event
-	rtn
-
-
-z_hci_pin_code_request_reply:
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_pin_length
-	iforce loopcnt
-	arg mem_pin,contw
-	call p_ipc_rx_hci_data_n_byte
-	jam hci_cmd_pair,mem_hci_cmd
-	branch z_hci_pin_code_reply
-
-z_hci_pin_code_request_negative_reply:
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	jam hci_cmd_nopair,mem_hci_cmd
-z_hci_pin_code_reply:
-	arg 7,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 6,mem_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-
-z_hci_parse_packet_cmd_ogf_link_control_authentication_requested:	//11
-	call p_ipc_rx_hci_data_two_byte
-	store 1,mem_hci_conn_handle
-	jam hci_cmd_auth,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_control_set_connection_encryption:	//13
-	call p_ipc_rx_hci_data_two_byte
-	store 1,mem_hci_conn_handle
-	call p_ipc_rx_hci_data_one_byte
-	increase hci_cmd_stopencrypt,pdata
-	store 1,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-org z
-z_hci_parse_packet_cmd_ogf_link_control3:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_REMOTE_NAME_REQUEST,z_hci_parse_packet_cmd_ogf_link_control_remote_name_request	//19
-	beq HCI_READ_REMOTE_EXT_FEATURES,z_hci_parse_packet_cmd_ogf_link_control_read_remote_ext_features	//1C
-	beq HCI_READ_REMOTE_VERSION_INFORMATION,z_hci_parse_packet_cmd_ogf_link_control_read_remote_version_information	//1D
-	beq HCI_READ_REMOTE_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_link_control_read_remote_supported_features	//1B
-
-	branch z_hci_parse_packet_cmd_ogf_link_control4
-
-z_hci_parse_packet_cmd_ogf_link_control_remote_name_request:	//19
-	jam 1,mem_hci_remote_name_req_flag
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_two_byte
-	store 1,mem_page_mode
-	call p_ipc_rx_hci_data_two_byte
-	iadd clkn_bt,pdata
-	and_into 0x1fc,pdata
-	store 4,mem_page_clk
- 	arg 8,loopcnt
-	arg mem_hci_remote_name,contw
-	call memset0
-	call context_search_plap
-	branch z_hci_parse_packet_cmd_ogf_link_control_remote_name_request_conn_exist,zero
-	jam 2,mem_hci_remote_name_req_flag
-z_hci_parse_packet_cmd_ogf_link_control_remote_name_request_conn_exist:
-	jam hci_cmd_remote_name_req,mem_hci_cmd
-	branch p_hci_send_event_command_status
-//	branch p_hci_send_remote_name_request_complete
-
-
-z_hci_parse_packet_cmd_ogf_link_control_read_remote_ext_features:	//1C
-	fetch 1,mem_conn_status
-	bne 2,p_hci_send_event_command_status_err_unknown_connection
-	call p_ipc_rx_hci_data_two_byte
-	branch p_hci_send_event_command_status_err_unknown_connection,blank
-	call p_ipc_rx_hci_data_one_byte
-	store 1, mem_ext_features_page
-	jam hci_cmd_remote_ext_features_req,mem_hci_cmd
-	branch p_hci_send_event_command_status
-
-z_hci_parse_packet_cmd_ogf_link_control_read_remote_version_information:
-	call p_ipc_rx_hci_data_two_byte	//connect handle
-	store 1,mem_hci_conn_handle
-
-	call context_search_conn_handle
-	nbranch p_hci_send_event_command_status_err_unknown_connection,zero
-
-	// check is classic or ble
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	bbit1 mode_le,z_hci_control_read_remote_version_le
-
-z_hci_control_read_remote_version_classic:
-	call p_hci_send_event_command_status
-	branch cmd_version_req
-
-z_hci_control_read_remote_version_le:
-	call p_hci_send_event_command_status
-	branch le_send_version_ind
-	
-
-z_hci_parse_packet_cmd_ogf_link_control_read_remote_supported_features:	//1B
-	// TODO: Think judge link exist or not.
-	fetch 1,mem_conn_status
-	bne 2,p_hci_send_event_command_status_err_unknown_connection
-	call p_ipc_rx_hci_data_two_byte		//rx parameters first
-	store 1,mem_hci_conn_handle
-	branch p_hci_send_event_command_status_err_unknown_connection,blank
-	call p_hci_send_event_command_status
-	fetch 8,mem_remote_features
-	nbranch z_hci_send_read_remote_supported_features_complete_event,blank
-	jam hci_cmd_remote_feature_req,mem_hci_cmd
-	rtn
-
-
-z_hci_send_read_remote_supported_features_complete_event:
-	//Status(1), Connection_Handle(2), LMP_Features(8)
-	jam 11,mem_mesh_event_para_total_length
-	jam HCI_EVENT_READ_REMOTE_FEATURES_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0
-	istore 1,contw
-	// Connection_Handle
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	// link type, 0:SCO, 1:ACL
-	fetch 8,mem_remote_features
-	istore 8,contw
-	branch ipc_hci_tx_start
-
-
-
-
-org z
-z_hci_parse_packet_cmd_ogf_link_control4:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_IO_CAP_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_io_cap_request_reply	//2B
-	beq HCI_USER_CONFIRMATION_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_user_confirmation_request_reply	//2C
-
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_link_control_io_cap_request_reply:	//2B
-	//BD_ADDR, IO_Capability, 
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	call p_ipc_rx_hci_data_thr_byte
-	store 3,mem_sp_iocap_local
-	arg 7,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 6,mem_plap
-	istore 6,contw
-	call ipc_hci_tx_start
-	fetch 1,mem_io_cap_flag
-	beq 1,z_io_cap_master_req
-z_io_cap_slave_req:
-	jam hci_cmd_io_cap,mem_hci_cmd
-//	arg 0xc600,rega
-//	arg 0xcc,temp
-//	call debug_log_print
-	rtn
-z_io_cap_master_req:
-	call cmd_ssp
-	jam LOCAL_STATEMACHINE,mem_sp_localsm //init ssp state machine
-//	arg 0xc600,rega
-//	arg 0xdd,temp
-//	call debug_log_print
-	rtn
-
-z_hci_parse_packet_cmd_ogf_link_control_user_confirmation_request_reply:	//2C
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_hci_plap
-	//jam hci_cmd_user_confirm_reply,mem_hci_cmd
-	call z_cmd_user_confirm_reply		//todo
-	arg 7,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 6,mem_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-
-z_cmd_user_confirm_reply:
-	// process dhkey check now
-	//rtn master
-	jam  SP_STAT_CONFIRM_CALC,mem_sp_state
-	jam  SP_FLAG_COMMIT,mem_sp_flag
-	rtn
-
-org z
-z_hci_parse_packet_cmd_ogf_controller_and_baseband2:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_RESET,z_hci_parse_packet_cmd_ogf_controller_and_baseband_reset	//03
-	beq HCI_WRITE_LINK_SUPERVISION_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_link_supervision_timeout  //37
-	beq HCI_WRITE_EXTENDED_INQUIRY_RESPONSE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_eir  //52
-	beq HCI_READ_SIMPLE_PAIRING_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_simple_pairing_mode //55
-	beq HCI_WRITE_SIMPLE_PAIRING_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_simple_pairing_mode //56
-	beq HCI_READ_LE_HOST_SUPPORT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_le_host_support	//6C
-	beq HCI_WRITE_LE_HOST_SUPPORT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_le_host_support	//6D
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-	
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_reset:
-	call p_hci_send_event_command_complete_without_payload
-	//branch p_hci_init_parameter
-z_hci_init_parameter:
-	setarg DEFAULT_LE_EVENT_MASK
-	store 8,mem_mesh_le_event_mask
-	setarg DEFAULT_EVENT_MASK
-	store 8,mem_mesh_event_mask
-	setarg 0
-	store 6,mem_mesh_le_random_address
-	store 1,mem_le_adv_enable
-	store 1,mem_le_scan_enable
-	store 1,mem_scan_mode
-	branch p_hci_init_bd_address
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_link_supervision_timeout:  //37
-	call p_hci_parse_connection_handle_check
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_supervision_to
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	jam hci_cmd_send_supervision,mem_hci_cmd
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_eir:   //52
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_fec_required
-	arg 100,loopcnt
-	arg mem_eir,contw
-	call p_ipc_rx_hci_data_n_byte
-	branch p_hci_send_event_command_complete_without_payload
-	
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_simple_pairing_mode:  //55
-	arg 2,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_simple_pairing_mode
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_simple_pairing_mode:  //56
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_simple_pairing_mode
-	branch p_hci_send_event_command_complete_error_command_invalid_param,blank
-	branch p_hci_send_event_command_complete_without_payload
-
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_le_host_support:  //6C
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 2,mem_le_supported_host
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_le_host_support:  //6D
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_le_supported_host
-	branch p_hci_send_event_command_complete_without_payload
-
-	
-org z
-z_hci_parse_packet_cmd_ogf_le_controller1:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_LE_SET_ADVERTISING_DATA,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_data	//08
-	beq HCI_LE_SET_SCAN_RESPONSE_DATA,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_rsp_data	//09
-	beq HCI_LE_SET_SCAN_PARAMETERS,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_para		//0b
-	beq HCI_LE_SET_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_enable		//0c
-	beq HCI_LE_CREATE_CONNECTION,z_hci_parse_packet_cmd_ogf_le_controller_create_connection		//0d
-
-	branch z_hci_parse_packet_cmd_ogf_le_controller2
-	
-	
-z_hci_parse_packet_cmd_ogf_le_controller_set_adv_data:	//OCF:0x0008
-	call p_ipc_rx_hci_data_one_byte	//Advertising_Data_length
-	store 1,mem_le_adv_data_len
-	copy pdata,loopcnt
-	call p_ipc_rx_hci_data_n_byte
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_scan_rsp_data:	//OCF:0x0009
-	call p_ipc_rx_hci_data_one_byte	//Advertising_Data_length
-	store 1,mem_le_scan_data_len
-	copy pdata,loopcnt
-	call p_ipc_rx_hci_data_n_byte
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_scan_para:		//OCF:0x000B	
-	fetch 1,mem_le_scan_enable
-	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
-	call p_ipc_rx_hci_data_one_byte		//LE Scan Type
-	store 1,mem_le_scan_type
-	call p_ipc_rx_hci_data_two_byte		//LE Scan Interval
-	store 2,mem_le_scan_interval
-	call p_ipc_rx_hci_data_two_byte		//LE Scan Window
-	store 2,mem_le_scan_window
-	call p_ipc_rx_hci_data_one_byte		//Own Address Type
-	store 1,mem_le_scan_own_addr_type
-	call p_ipc_rx_hci_data_one_byte		//Scanning Filter Policy
-	store 1,mem_le_white_list_filter_policy
-	// avoid param same
-	fetch 2,mem_le_scan_interval
-	fetcht 2,mem_le_scan_window
-	isub temp,null
-	nbranch p_hci_send_event_command_complete_without_payload,zero
-	lshift pdata,pdata
-	store 2,mem_le_scan_interval
-	
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_scan_enable:	//OCF:0x000C
-	call p_ipc_rx_hci_data_one_byte		//LE Scan Enable
-	store 1,mem_le_scan_enable
-	call p_ipc_rx_hci_data_one_byte		//Filter Duplicates
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_create_connection:		//OCF:0x000D
-	call p_ipc_rx_hci_data_two_byte		//LE Scan Interval
-	store 2,mem_le_scan_interval
-	call p_ipc_rx_hci_data_two_byte		//LE Scan Window
-	store 2,mem_le_scan_window
-	call p_ipc_rx_hci_data_one_byte		//initiator filter policy
-	store 1,mem_le_white_list_filter_policy
-	isub 0x01,null
-	call p_white_filter_connect_filter,zero
-	call p_ipc_rx_hci_data_one_byte		//peer address type
-	store 1,mem_le_conn_peer_addr_type
-	call p_ipc_rx_hci_data_six_byte		//peer address
-	store 6,mem_le_conn_peer_addr
-	call p_ipc_rx_hci_data_one_byte		//own address type
-	store 1,mem_le_conn_own_addr_type
-	call p_ipc_rx_hci_data_two_byte		//connect interval min
-	lshift2 pdata,pdata
-	store 2,mem_le_conn_interval
-	call p_ipc_rx_hci_data_two_byte		//connect interval max
-	call p_ipc_rx_hci_data_two_byte		//connect latency
-	store 2,mem_le_conn_latency	
-	call p_ipc_rx_hci_data_two_byte		//supervision timeout
-	store 2,mem_le_conn_superto
-	branch p_parse_le_controller_create_connection
-	
-
-org z
-z_hci_parse_packet_cmd_ogf_le_controller2:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_LE_SET_ADVERTISE_ENABLE,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_enable		//0a
-	beq HCI_LE_CREATE_CONNECTION_CANCEL,z_hci_parse_packet_cmd_ogf_le_controller_create_connection_cancel
-	beq HCI_LE_CONNECTION_UPDATE,p_hci_parse_packet_cmd_ogf_le_controller_connection_update
-	beq HCI_LE_READ_REMOTE_FEATURES,z_hci_parse_packet_cmd_ogf_le_controller_read_remote_features
-	beq HCI_LE_ENCRYPT,z_hci_parse_packet_cmd_ogf_le_controller_encrypt
-	beq HCI_LE_RAND,z_hci_parse_packet_cmd_ogf_le_controller_rand
-	beq HCI_LE_START_ENCRYPTION,z_hci_parse_packet_cmd_ogf_le_controller_start_encryption
-	beq HCI_LE_LONG_TERM_KEY_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_reply
-	beq HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY,z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_negative_reply
-
-	beq HCI_LE_READ_WHITE_LIST_SIZE,z_hci_parse_packet_cmd_ogf_le_controller_read_white_list_size
-	beq HCI_LE_CLEAR_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_clear_white_list
-	beq HCI_LE_ADD_DEVICE_TO_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_add_device_to_white_list
-	
-	branch z_hci_parse_packet_cmd_ogf_le_controller3
-
-z_hci_parse_packet_cmd_ogf_le_controller_read_remote_features:
-	call p_ipc_rx_hci_data_two_byte 		//connection handle
-	call p_hci_send_event_command_status
-	//branch p_le_send_feature_req
-z_le_send_feature_req:
-	arg 9,rega
-//	arg LL_FEATURE_REQ,regb
-//	call le_fifo_malloc_tx_ll
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_FEATURE_REQ
-	istore 1,contw
-	fetch 8,mem_le_features
-	istore 8,contw
-	rtn
-
-		
-z_hci_parse_packet_cmd_ogf_le_controller_encrypt:
-z_hci_parse_packet_cmd_ogf_le_controller_rand:
-z_hci_parse_packet_cmd_ogf_le_controller_start_encryption:
-z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_reply:
-z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_negative_reply:
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_adv_enable:	//OCF:0x000A
-	call p_ipc_rx_hci_data_one_byte
-	store 1,mem_le_adv_enable
-	branch p_hci_send_event_command_complete_without_payload
-
-
-z_hci_parse_packet_cmd_ogf_le_controller_create_connection_cancel:
-	jam OFF,mem_le_scan_enable
-	jam CANCEL_CONNECTION,mem_mesh_creat_connection_flag
-	branch p_hci_send_event_command_complete_without_payload
-
-z_hci_parse_packet_cmd_ogf_le_controller_read_white_list_size:
-	arg 2,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	setarg LE_WHITE_LIST_MAX_SIZE
-	istore 1,contw
-	branch ipc_hci_tx_start
-z_hci_parse_packet_cmd_ogf_le_controller_clear_white_list:
-	jam 0,mem_le_white_list_cnt
-	jam 0,mem_le_white_list_type_and_bd_addr
-	jam 0,mem_le_white_list
-	branch p_hci_send_event_command_complete_without_payload
-z_hci_parse_packet_cmd_ogf_le_controller_add_device_to_white_list:
-	fetcht 1,mem_le_white_list_cnt
-	sub temp,LE_WHITE_LIST_MAX_SIZE,null
-	branch p_hci_send_event_command_complete_error_command_disallowed,zero
-	call p_ipc_rx_hci_data_seven_byte
-	store 7,mem_le_white_list_type_and_bd_addr
-	call z_le_add_device_to_white_list
-	branch p_hci_send_event_command_complete_without_payload
-
-
-
-// input: rega
-z_le_add_device_to_white_list:
-	fetch 1,mem_le_white_list_cnt
-	arg mem_le_white_list,contw
-	mul32 pdata,7,pdata
-	iadd contw,contw
-	fetch 7,mem_le_white_list_type_and_bd_addr
-	istore 7,contw
-	fetch 1,mem_le_white_list_cnt
-	pincrease 1
-	store 1,mem_le_white_list_cnt
-	rtn
-
-
-org z
-z_l2cap_init_queue:
-	fetch 1,mem_queue_init_flag
-	nbranch z_l2cap_link_queue_init,blank
-
-	jam 1,mem_queue_init_flag
-
-//	// TODO: here may occur l2cap buffer rcv error.
-//	jam BLOCK_MAX_NUM_NEW,mem_l2cap_rx_malloc_num
-//	setarg L2CAP_BIG_BUFF_LENTH
-//	store 2,mem_l2cap_rx_max_lenth
-	call z_init_all_queue
-
-	// init the big buffer queue
-	fetchr loopcnt,1,mem_alloc_big_total_size
-	fetchr regb,2,mem_param_alloc_big_buffer_start_address
-	fetch 2,mem_param_alloc_big_buffer_max_length
-	store 2,mem_temp
-	setarg mem_alloc_big_block
-	store 2,mem_temp1
-	call z_queue_init_loop
-	
-	// store the big block ptr to list
-	fetch 1,mem_alloc_big_total_size
-	mul32 pdata,3,loopcnt
-	arg mem_alloc_big_block_start,contr
-	arg mem_big_block_ptr_list,contw
-	call memcpy_fast
-	
-	// init the normal buffer queue
-	fetchr loopcnt,1,mem_alloc_normal_total_size
-	fetchr regb,2,mem_param_alloc_normal_buffer_start_address
-	fetch 2,mem_param_alloc_normal_buffer_max_length
-	store 2,mem_temp
-	setarg mem_alloc_normal_block
-	store 2,mem_temp1
-	call z_queue_init_loop
-
-	// store the big block ptr to list
-	fetch 1,mem_alloc_normal_total_size
-	mul32 pdata,3,loopcnt
-	arg mem_alloc_normal_block_start,contr
-	arg mem_normal_block_ptr_list,contw
-	branch memcpy_fast
-	
-z_queue_init_loop:
-	fetchr rega,2,mem_temp1
-	call queue_insert
-	fetch 2,mem_temp
-	iadd regb,regb
-	loop z_queue_init_loop
-	rtn
-
-z_init_all_queue:
-	setarg mem_alloc_normal_block
-	call z_queue_init
-	setarg mem_alloc_big_block
-	call z_queue_init
-	setarg mem_snd_br_block
-	call z_queue_init
-	setarg mem_snd_ble_block
-	call z_queue_init
-	setarg mem_snd_hci_block
-//input: pdata: queue start addr
-z_queue_init:
-	copy pdata,contw
-	add pdata,BLOCK_TOTAL_SIZE_OFFSET,rega // point to data ptr
-	add pdata,BLOCK_DATA_OFFSET,pdata // point to data ptr
-	istore 2,contw // header
-	istore 2,contw // rptr
-	istore 2,contw // wptr
-
-	ifetcht 1,rega // get total buffer size.
-	mul32 temp,3,temp
-	iadd temp,pdata
-	istore 2,contw // end ptr
-
-	increase 1,contw // skip total length
-
-	setarg 0
-	istore 1,contw // cur len
-
-	copy temp,loopcnt
-	branch clear_mem
-/*	
-//input:pdata
-queue_get_wrtie_ptr:
-	add rega,BLOCK_WPTR_OFFSET,pdata
-	ifetcht 2,pdata
-	ifetch 3,temp
-	branch get_pdata_contw
-*/
-
-
-org z
-z_l2cap_link_queue_init:
-	fetch 3,mem_rcv_br_queue_ptr
-	ncall z_l2cap_link_queue_free_rx_buffer,blank
-//	fetch 3,mem_rcv_ble_queue_ptr
-//	ncall z_l2cap_link_queue_free_rx_buffer,blank
-	
-	setarg 0
-	store 3,mem_rcv_br_queue_ptr
-//	store 3,mem_rcv_ble_queue_ptr
-	
-//	call z_l2cap_ble_link_queue_init
-z_l2cap_br_link_queue_init:
-	arg mem_snd_br_block,pdata
-	store 2,mem_temp
-	
-	branch z_l2cap_queue_free_all
-
-//z_l2cap_ble_queue_init:
-//	fetch 3,mem_rcv_ble_queue_ptr
-//	ncall z_l2cap_link_queue_free_rx_buffer,blank	
-//	setarg 0
-//	store 3,mem_rcv_ble_queue_ptr
-//	branch  z_l2cap_ble_link_queue_init 
-
-//z_l2cap_ble_link_queue_init:
-//	arg mem_snd_ble_block,pdata
-//	store 2,mem_temp
-//input: rega: queue block
-z_l2cap_queue_free_all:
-	fetchr rega,2,mem_temp
-	call p_queue_get_len
-	rtn blank
-	// get len will change rega
-	fetchr rega,2,mem_temp
-	call queue_delete
-	call free_buffer
-	branch z_l2cap_queue_free_all
-	
-z_l2cap_link_queue_free_rx_buffer:
-	copy pdata,regb
-	branch free_buffer
-	
-org z
-z_hci_parse_complete_packet:
-	fetch 1,mem_mesh_hci_opcode_ogf
-	beq HCI_OGF_LINK_CONTROL,z_hci_parse_packet_cmd_ogf_link_control_base
-	beq HCI_OGF_LINK_POLICY,z_hci_parse_packet_cmd_ogf_link_policy_base
-	beq HCI_OGF_CONTROLLER_AND_BASEBAND,z_hci_parse_packet_cmd_ogf_controller_and_baseband_base
-	beq HCI_OGF_INFOMATIONAL_PARAM,z_hci_parse_packet_cmd_ogf_infomational_parameters_base
-	beq HCI_OGF_STATUS_PARAM,z_hci_parse_packet_cmd_ogf_status_parameters_base
-	beq HCI_OGF_TEST,z_hci_parse_packet_cmd_ogf_testing_base
-	beq HCI_OGF_LE_CONTROLLER,z_hci_parse_packet_cmd_ogf_le_controller_base
-	beq HCI_OGF_VENDOR_SPECIFIC_DEBUG,z_hci_parse_packet_cmd_ogf_vendorspecific_debug_base
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_link_control_base:
-	branch z_hci_parse_packet_cmd_ogf_link_control
-
-z_hci_parse_packet_cmd_ogf_controller_and_baseband_base:
-	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband
-
-z_hci_parse_packet_cmd_ogf_infomational_parameters_base:
-	branch z_hci_parse_packet_cmd_ogf_infomational_parameters
-
-z_hci_parse_packet_cmd_ogf_le_controller_base:
-	branch z_hci_parse_packet_cmd_ogf_le_controller
-	
-z_hci_parse_packet_cmd_ogf_link_policy_base:
-	branch z_hci_parse_packet_cmd_ogf_link_policy
-
-/*********
-	HCI_OGF_INFOMATIONAL_PARAM
-*********/
-
-/*********
-	HCI_OGF_STATUS_PARAM
-*********/
-z_hci_parse_packet_cmd_ogf_status_parameters_base:
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-
-/*********
-	HCI_OGF_TEST
-*********/
-z_hci_parse_packet_cmd_ogf_testing_base:
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-
-
-/*********
-	HCI_OGF_VENDOR_SPECIFIC_DEBUG
-*********/
-z_hci_parse_packet_cmd_ogf_vendorspecific_debug_base:
-	fetch 1,mem_mesh_hci_opcode_ocf
-	beq HCI_WRITE_BD_ADDR,z_hci_parse_packet_cmd_ogf_vendorspecific_write_bd_addr
-ifdef FSC_RTK_HOST
-	beq 0x17,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_17
-	beq 0x20,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_20
-	beq 0xa3,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3
-	beq 0x60,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_read_svn_version
-endif
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_vendorspecific_write_bd_addr:
-	call p_ipc_rx_hci_data_six_byte
-	store 6,mem_device_public_address
-	call p_hci_init_bd_address
-	branch p_hci_send_event_command_complete_without_payload
-
-
-ifdef FSC_RTK_HOST
-z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_17:
-	jam 0x3f,mem_fsc_rtk_host
-	branch p_hci_send_event_command_complete_without_payload
-
-
-
-z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_20:
-	arg 0x02,loopcnt
-	call p_hci_prepare_send_event_command_complete
-	setarg 0
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3:
-	call p_ipc_rx_hci_data_two_byte// Opcode
-	fetcht 1,mem_conn_handle
-	isub temp,null
-	branch z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3_event,zero
-	fetcht 1,mem_le_conn_handle
-	isub temp,null
-	nrtn zero
-z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3_event:	
-	storet 1,mem_hci_conn_handle
-	arg 0x03,loopcnt
-	call p_hci_prepare_send_event_command_complete
-	fetch 1,mem_hci_conn_handle
-	istore 2,contw
-	fetch 1,mem_rssi
-	call p_rssi_convert
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_read_svn_version:
-	arg 2,loopcnt
-	call p_hci_prepare_send_event_command_complete
-	fetch 2,mem_hci_version_svnid
-	istore 2,contw
-	branch ipc_hci_tx_start
-endif	
-
-
-org z
-z_hci_send_connection_rtn_error:
-	jam 11,mem_mesh_event_para_total_length
-	jam HCI_EVENT_CONNECTION_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 1,mem_mesh_event_parameter_status
-	istore 1,contw
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	fetch 6,mem_plap
-	istore 6,contw
-	force 1,pdata				/* connection type=1:ACL */
-	istore 1,contw
-	force 0,pdata
-	fetcht 1,mem_state_map
-	isolate1 smap_encryption,temp
-	setflag true,0,pdata
-	istore 1,contw
-	//TODO: restore connection handle
-	fetch 1,mem_conn_handle
-	branch ipc_hci_tx_start
-
-	/* temp is connection type 0=sco,1=acl */
-
-org z
-z_hci_send_page_scan_repetition_mode_change:
-	jam 7,mem_mesh_event_para_total_length
-	jam HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 6,mem_plap
-	istore 6,contw
-	fetch 1,mem_page_scan_repetition_mode
-	istore 1,contw
-	branch ipc_hci_tx_start
-	
-
-org z
-z_hci_send_disconnect_complete:
-	jam 4,mem_mesh_event_para_total_length
-	jam HCI_EVENT_DISCONNECTION_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0x00
-	istore 1,contw
-	fetch 1,mem_hci_record_disc_conn_handle
-	istore 2,contw
-	fetch 1,mem_disconn_reason_send
-	istore 1,contw
-	fetch 1,mem_state_map
-	set0 smap_edr,pdata
-	store 1,mem_state_map
-	branch ipc_hci_tx_start
-
-	
-org z
-z_hci_send_mode_change:
-	jam 6,mem_mesh_event_para_total_length
-	jam HCI_EVENT_MODE_CHANGE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 1,mem_mesh_event_parameter_rtn
-	istore 1,contw
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	fetch 1,mem_mesh_event_parameter_status
-	istore 1,contw
-	branch z_hci_send_mode_change_active,blank
-	fetch 2,mem_tsniff
-	rshift pdata,pdata
-	branch z_hci_send_mode_change_sniff
-z_hci_send_mode_change_active:
-	setarg 0
-z_hci_send_mode_change_sniff:
-	istore 2,contw
-	branch ipc_hci_tx_start
-
-org z
-z_hci_parse_packet_cmd_ogf_le_controller3:
- 	fetch 1,mem_mesh_hci_opcode_ocf
- 	beq HCI_LE_REMOVE_DEVICE_FROM_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_remove_device_from_white_list
-	beq HCI_LE_SET_DATA_LENGTH,z_hci_parse_packet_cmd_ogf_le_controller_set_data_length
-	branch p_hci_send_event_command_complete_error_command_nuknown
-
-z_hci_parse_packet_cmd_ogf_le_controller_remove_device_from_white_list:
-	fetch 1,mem_le_white_list_cnt
-	branch p_hci_send_event_command_complete_error_command_disallowed,blank
-	call p_ipc_rx_hci_data_seven_byte
-	store 7,mem_le_white_list_type_and_bd_addr
-	call z_le_remove_device_from_white_list
-	fetch 1,mem_le_white_list_cnt
-	pincrease -1
-	store 1,mem_le_white_list_cnt
-	branch p_hci_send_event_command_complete_without_payload
-
-z_le_remove_device_from_white_list:
-	call p_check_addr_in_white_list
-	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
-z_le_remove_device_from_white_list_loop:
-	copy regb,contw
-	increase 7,regb
-	copy regb,contr
-	ifetch 7,contr
-	istore 7,contw
-	loop z_le_remove_device_from_white_list_loop
-	setarg 0
-	increase -7,contw
-	istore 7,contw
-	rtn
-	
-
-z_hci_parse_packet_cmd_ogf_le_controller_set_data_length:
-	//length
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_local_tx_max_octets
-	//time
-	call p_ipc_rx_hci_data_two_byte
-	store 2,mem_local_tx_max_time
-	call z_le_send_data_length_req
-	
-	arg 3,loopcnt
-	call p_hci_prepare_send_event_command_complete_with_status_success
-	fetch 1,mem_le_conn_handle
-	istore 2,contw
-	branch ipc_hci_tx_start
-	//branch p_hci_send_event_command_complete_without_payload
-	
-z_le_send_data_length_req:
-	arg LL_LENGTH_REQ,regb
-	//branch z_le_send_data_length
-//z_le_send_data_length:
-	arg 9,rega
-//	call le_fifo_malloc_tx_ll
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_LENGTH_RSP
-	istore 1,contw
-	fetch 8,mem_local_rx_max_octets
-	istore 8,contw
-	rtn
-
-
-org z
-z_hci_inquiry_reply_check_eir:
-	fetch 1,mem_inquiry_mode
-	bne 2,z_hci_inquiry_reply
-	call inquiry_receive_eir
-	nrtn sync
-	rtnmark1 mark_fhs_eir	
-z_hci_inquiry_reply:
-	//call inquiry_receive_eir_rtn
-	fetcht 6,extm_lap
-	call context_search_plap2
-	rtn zero
-	call p_estimate_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0x01
-	//Num_responses
-	istore 1,contw
-	fetch 6,extm_lap
-	//bd_addr
-	istore 6,contw
-	fetch 1, extm_fhs_misc
-	copy pdata, temp
-	rshift3 pdata, pdata
-	rshift3 pdata, pdata
-	//page_scan_repetition_mode
-	istore 1,contw
-	setarg 0x00
-	//reserved1
-	istore 1,contw
-	fetch 1,mem_inquiry_mode
-	bne 0,z_hci_inquiry_reply_mode1		
-z_hci_inquiry_reply_mode0:
-	setarg 0x00
-	//reseved2
-	istore 1,contw
-	fetch 3, extm_class
-	istore 3,contw
-	fetch 4,mem_clke_bt
-	isub clkn_bt,pdata
-	istore 2,contw
-	branch ipc_hci_tx_start
-z_hci_inquiry_reply_mode1:
-	fetch 3, extm_class
-	istore 3,contw
-	fetch 4,mem_clke_bt
-	isub clkn_bt,pdata
-	istore 2,contw
-	fetch 1,mem_rssi
-	call p_rssi_convert
-	istore 1,contw
-	fetch 1,mem_inquiry_mode
-	beq 2,z_hci_inquiry_reply_mode2
-	branch ipc_hci_tx_start
-z_hci_inquiry_reply_mode2:
-	fetch 3,mem_rcv_br_queue_ptr
-	copy pdata,contr
-	ifetch 1,contr
-	ifetch 2,contr
-	rtn blank
-	copy pdata,temp
-	copy pdata,loopcnt
-	call memcpy_fast
-	sub temp,240,loopcnt
-	call clear_mem
-	branch ipc_hci_tx_start
-
-org z
-z_send_lmp_escape:
-	fetch 1,mem_lmp_to_send
-	beq LMP_EXT_FEATURES_RES,z_send_lmpext_features_res
-	beq LMP_EXT_FEATURES_REQ,z_send_lmpext_features_req
-	branch send_lmp_escape
-z_send_lmpext_features_res:
-	fetcht 1,mem_simple_pairing_mode
-	storet 1,mem_lmpext_ssp_enable+1
-	branch send_lmpext_features_res
-z_send_lmpext_features_req:
-	fetcht 1,mem_simple_pairing_mode
-	storet 1,mem_lmpext_ssp_enable+1
-	branch send_lmpext_features_req
-
-org z
-z_hci_send_linkkey_notification:
-	jam 0x17,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LINK_KEY_NOTIFICATION,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 6,mem_plap
-	istore 6,contw
-	arg mem_link_key,contr
-	force 16,loopcnt
-	call memcpy_fast
-	force 0,pdata
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-org z
-
-//input:temp connection handle
-//MASTER_CONNECTION_HANDLE
-//SLAVE_CONNECTION_HANDLE
-z_hci_send_event_le_connection_complete:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 LE_CONNECTION_COMPLETE_EVENT
-	jam 19,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg HCI_LE_SUBEVENT_CONN_COMPLETE
-	istore 2,contw	//subevent code & status
-	fetch 1,mem_le_conn_handle
-	istore 2,contw	//connection handle
-	call p_le_get_role
-	istoret 1,contw	//role
-	fetch 1,mem_le_conn_peer_addr_type
-	istore 1,contw	//peer address type
-	fetch 6,mem_le_plap
-	istore 6,contw	//peer address
-	fetch 2,mem_le_tsniff
-	rshift2 pdata,pdata
-	istore 2,contw	//connection interval
-	fetch 4,mem_le_slave_latency
-	istore 4,contw	//connect latency & supervision timeout
-	fetch 1,mem_le_peer_sca
-	istore 1,contw	//master clock accuracy
-	fetch 1,mem_le_conn_handle
-	branch ipc_hci_tx_start
-
-org z
-z_hci_send_le_connection_update_commplete:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 LE_CONNECTION_UPDATE_COMPLETE_EVENT
-	jam 10,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg HCI_LE_SUBEVENT_CONN_UPDATE_COMPLETE
-	istore 2,contw		//subevent code & status
-	fetch 1,mem_le_conn_handle
-	istore 2,contw
-	fetch 6,mem_le_new_conninterval
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-
-
-org z
-z_parse_lmp_escape:
-	//bpatchx patch2e_1,mem_patch2e
-	fetch 1,mem_rxbuf+1
-	set1 7,pdata
-	store 1,mem_lmi_opcode2
-	beq LMP_EXT_FEATURES_REQ,z_parse_lmpext_features_req
-	beq LMP_EXT_FEATURES_RES,z_parse_lmpext_features_res
-	beq LMP_IO_CAP_REQ,z_parse_lmpext_iocap_req
-	beq LMP_IO_CAP_RES,z_parse_lmpext_iocap_res
-	branch parse_lmp_escape+4
-
-z_parse_lmpext_features_req:
-	call parse_lmpext_features_req
-// TODO: judge page index.
-z_store_remote_ext_features:
-	// features page & max supported page
-	fetch 2,mem_rxbuf+2
-	// extended features
-	fetch 8,mem_rxbuf+4
-	store 8,mem_remote_ext_features0
-	rtn	
-
-z_parse_lmpext_features_res:
-	call parse_lmpext_features_res
-	branch z_store_remote_ext_features	
-
-z_parse_lmpext_iocap_req:
-	call iocap_lmpext_load
-	call z_hci_send_io_cap_response_event
-	branch p_hci_send_io_cap_req_event	
-
-z_parse_lmpext_iocap_res:
-	call z_hci_send_io_cap_response_event
-	call iocap_lmpext_load
-	call iocap_lmpext_hci
-	jam SP_FLAG_COMMIT,mem_master_sp_flag
-	jam SP_STAT_KEY_SEND,mem_master_sp_state
-	rtn	
-	
-z_hci_send_io_cap_response_event:
-	//BD_ADDR-6,IO_Capability-1,OOB_Data_Present-1,Authentication_Requirements-1
-	jam 9,mem_mesh_event_para_total_length
-	jam HCI_EVENT_IO_CAP_RESPONSE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 6,mem_plap
-	istore 6,contw
-	fetch 3,mem_sp_iocap_remote
-	istore 3,contw
-	branch ipc_hci_tx_start
-
-org z
-// input --- mem_encryp_inital_value  output --- mem_encryp_inital_value
-z_efuse_custom_encryption:
-	arg 0x20,pdata
-	arg mem_efuse_encryp_data,rega
-	arg 32,temp
-	call efuse_read_data
-//	setarg 0xaa55
-//	store 2,mem_encryp_inital_value
-	arg mem_efuse_encryp_data,contr
-	ifetch 2,contr
-	rtn blank
-	store 2,mem_encryp_param
-	call z_efuse_custom_encryption_init
-	call z_efuse_custom_encryption_read_efuse_data_add_loop
-	call z_efuse_custom_encryption_init
-	branch z_efuse_custom_encryption_read_efuse_data_ixor_loop
-	
-z_efuse_custom_encryption_init:
-	arg mem_efuse_encryp_data+2,rega
-	arg 6,loopcnt
-	jam 1,mem_encryp_count
-	rtn
-	
-// input:pdata----read efuse addr
-z_efuse_custom_encryption_read_efuse_data_add_loop:
-	ifetch 2,rega
-	fetcht 2,mem_encryp_inital_value
-	iadd temp,pdata
-	store 2,mem_encryp_inital_value
-	fetch 1,mem_encryp_count
-	iadd rega,rega
-	increase 2,rega
-	fetch 1,mem_encryp_count
-	pincrease 1
-	store 1,mem_encryp_count
-	loop z_efuse_custom_encryption_read_efuse_data_add_loop
-	rtn
-z_efuse_custom_encryption_read_efuse_data_ixor_loop:
-	ifetch 2,rega
-	fetcht 2,mem_encryp_inital_value
-	ixor temp,pdata
-	store 2,mem_encryp_inital_value
-	fetch 1,mem_encryp_count
-	iadd rega,rega
-	add rega,2,rega
-	fetch 1,mem_encryp_count
-	pincrease 1
-	store 1,mem_encryp_count
-	loop z_efuse_custom_encryption_read_efuse_data_ixor_loop
-	fetch 2,mem_encryp_inital_value
-	fetcht 2,mem_encryp_param
-	isub temp,null
-	nbranch assert,zero
-	rtn
-
-org z
-z_ipc_rx_hci:
-	fetcht 3,mem_ipc_data_rx_buf_payload_ptr
-	call p_ipc_rx_store_contr1
-	call p_ipc_rx_hci_data_one_byte
-	beq HCI_H4_TYPE_CMD,z_hci_parse_packet_cmd
-	beq HCI_H4_TYPE_ACL,z_hci_parse_packet_acl
-	branch assert
-
-z_hci_parse_packet_cmd:
-	call p_ipc_rx_hci_data_two_byte// Opcode
-	store 2,mem_mesh_hci_opcode
-	arg 0x3ff,temp
-	iand temp,temp	//low 10bit
-	storet 2,mem_mesh_hci_opcode_ocf
-	rshift2 pdata,pdata
-	rshift8 pdata,pdata	//high 6bit
-	store 1,mem_mesh_hci_opcode_ogf
-	call p_ipc_rx_hci_data_one_byte	// parameter total length
-	store 1,mem_mesh_hci_cmd_len
-	branch z_hci_parse_complete_packet
-
-z_hci_parse_packet_acl:
-	call p_ipc_rx_hci_data_two_byte// Opcode
-	store 1,mem_hci_conn_handle
-	call z_hci_parse_packet_acl_FB_flag
-	call p_ipc_rx_hci_data_two_byte// length
-	store 2,mem_temp
-
-	call context_search_conn_handle
-	// TODO: here need change to other work.
-	nrtn zero
-
-	// check is classic or ble
-	add rega,coffset_mode,contr
-	ifetch 1,contr
-	bbit1 mode_le,z_hci_parse_packet_acl_le
-z_hci_parse_packet_acl_classic:
-	fetch 2,mem_temp
-	//increase 3,pdata  // with l2cap header. 2byte length, 1byte type
-	store 2,mem_alloc_buffer_len
-	call malloc_buffer_is_enough
-	call ice_break,blank
-
-	
-	fetch 2,mem_temp
-	copy pdata,rega
-	copy pdata,regb
-	//TODO: classic need do here
-	call l2cap_malloc//return with pdata ptr
-	copy regb,contw
-	// l2cap payload header
-	fetch 2,mem_temp
-	istore 2,contw
-	istorer type,1,contw
-z_hci_parse_packet_acl_end:
-	fetch 2,mem_temp
-	copy pdata,loopcnt
-	call p_ipc_rx_restore_contr
-	branch memcpy_fast
-	
-
-z_hci_parse_packet_acl_le:	
-	// Think to judge classic or ble.
-	fetch 2,mem_temp	
-	//increase 3,pdata  // with l2cap header. 2byte length, 1byte type
-	call z_le_fifo_check_full
-	nrtn blank
-	fetch 2,mem_temp
-	copy pdata,rega
-	copy pdata,regb
-	call le_fifo_malloc_tx
-	branch z_hci_parse_packet_acl_end
-
-z_hci_parse_packet_acl_FB_flag:
-	rshift8 pdata,pdata
-	rshift4 pdata,pdata
-	force LLID_CONTINUE,type
-	rtneq BT_ACL_CONT
-	force LLID_START,type
-	rtn
-
-z_le_fifo_check_full:
-	call malloc_buffer_is_full_raw
-	branch setarg1,blank
-	branch setarg0
-
-org z
-z_l2cap_ble_queue_init:
-	fetch 3,mem_rcv_ble_queue_ptr
-	ncall z_l2cap_ble_queue_free_rx_buffer,blank	
-	setarg 0
-	store 3,mem_rcv_ble_queue_ptr
-z_l2cap_ble_link_queue_init:
-	arg mem_snd_ble_block,pdata
-	store 2,mem_temp
-//input: rega: queue block
-z_l2cap_ble_queue_free_all:
-	fetchr rega,2,mem_temp
-	call p_queue_get_len
-	rtn blank
-	// get len will change rega
-	fetchr rega,2,mem_temp
-	call queue_delete
-	call free_buffer
-	branch z_l2cap_ble_queue_free_all
-	
-z_l2cap_ble_queue_free_rx_buffer:
-	copy pdata,regb
-	branch free_buffer
-
-
-org z
-z_parse_lmp_process:
-	//bpatchx patch2e_0,mem_patch2e
-	// set flag
-	arg LOG_POINT_1000,rega
-	fetcht 2,mem_rxbuf
-	call debug_log_print
-  	fetch 1,mem_lmi_opcode2
-	beq LMP_ACCEPTED,z_parse_lmp_accepted//multi
-	beq LMP_NOT_ACCEPTED,z_parse_lmp_not_accepted//multi
-	beq LMP_START_ENCRYPTION_REQ, z_parse_lmp_start_encryption_req
-	beq LMP_FEATURES_REQ,z_parse_lmp_features_req
-	beq LMP_FEATURES_RES,z_parse_lmp_features_res
-	beq LMP_DETACH,z_parse_lmp_detach
-	beq LMP_IN_RAND,p_parse_lmp_in_rand		//in_rand
-	beq LMP_NAME_RES,p_parse_lmp_name_res
-
-	branch z_parse_lmp_process_sub
-
-
-z_parse_lmp_accepted:
-	fetch 1,mem_rxbuf+1
-	store 1,mem_lmi_accepted_opcode
-	beq LMP_START_ENCRYPTION_REQ,z_parse_lmp_accepted_start_enc//ok
-	branch parse_lmp_accepted+3
-
-z_parse_lmp_accepted_start_enc:
-	call parse_lmp_accepted_start_enc
-	branch z_hci_send_encryption_change_complete_event
-
-z_parse_lmp_start_encryption_req:
-	call parse_lmp_start_encryption_req+2
-	branch z_hci_send_encryption_change_complete_event
-
-z_hci_send_encryption_change_complete_event:
-	//Status(1), conn_handle(2), enc_mode(1)
-	jam 4,mem_mesh_event_para_total_length
-	jam HCI_EVENT_ENCRYPTION_CHANGE_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0
- 	istore 1,contw
- 
-	fetcht 1,mem_conn_handle
-	istoret 2,contw
-
-	//enc_mode
-	setarg 1
- 	istore 1,contw
- 
-	branch ipc_hci_tx_start
-
-z_parse_lmp_not_accepted:
-	fetch 1,mem_rxbuf+1
-	store 1,mem_lmi_accepted_opcode
-	beq LMP_AU_RAND,z_parse_lmp_not_accepted_aurand//ok
-	branch parse_lmp_not_accepted+3
-
-z_parse_lmp_not_accepted_aurand:
-	fetch 1,mem_device_option
-	bne dvc_op_headset,parse_lmp_not_accepted_aurand_send_detach
-	fetch 1,mem_link_key_exists
-	rtn blank
-	fetcht 1,mem_reconn_lmp_sm
-	jam 0,mem_reconn_lmp_sm
-	jam 0,mem_link_key_exists
-	fetch 1,mem_rxbuf+2
-	rtnne KEY_MISSING
-	storet 1,mem_reconn_lmp_sm
-	jam LOCAL_STATEMACHINE,mem_sp_localsm
-//	call p_hci_send_io_cap_req_event
-	call p_sp_check_ssp_available
-	fetch 1,mem_simple_pairing_mode
-	branch p_hci_send_pincode_req_event,blank
-	rtn	
-z_parse_lmp_features_req:
-	call parse_lmp_features_req
-z_store_remote_features:
-	// features
-	fetch 8,mem_rxbuf+1
-	store 8,mem_remote_features
-	rtn
-z_parse_lmp_detach:
-	fetch 1,mem_rxbuf+1
-	store 1,mem_disconn_reason_send
-//	branch parse_lmp_detach
-	call p_prepare_disconnect
-	branch accept_lmp_msg
-	
-z_parse_lmp_features_res:
-	call parse_lmp_features_res
-	branch z_store_remote_features
-
-
-
-org z
-z_parse_lmp_process_sub:
-  	fetch 1,mem_lmi_opcode2
-	beq LMP_SRES,z_parse_lmp_sres
-	beq LMP_SNIFF_REQ,z_parse_lmp_sniff_req
-	beq LMP_AU_RAND,z_parse_lmp_au_rand
-
-	beq LMP_HOST_CONNECTION_REQ,z_parse_lmp_conn_req
- 	beq LMP_MAX_SLOT_REQ,z_parse_lmp_max_slot_req
-	beq  LMP_DHKEY_CHECK,z_parse_dhkey_check
-
-	//branch z_parse_lmp_process_sub
-	branch parse_lmp_process+5
-
-	
-z_parse_lmp_sres:	
-	arg mem_plap,rega
-	call function_e1
-	fetch 4,mem_rxbuf+1
-	fetcht 4,mem_input_store
-	isub temp,null
-	branch p_authentication_event,zero
-	branch parse_lmp_sres+6
-
-
-z_parse_lmp_sniff_req:
-	fetch 2,mem_default_link_policy_settings
-	bbit0 sniff_mode,lmp_reject_sniff
-	branch parse_lmp_sniff_req+1
-
-
-
-z_parse_lmp_au_rand:
-	call push_tid_follow
-	store 1,mem_sres_tid
-	call lmp_copy_rand
-	jam LMP_SRES,mem_lmo_opcode2
-	fetch 1,mem_link_key_exists
-	nrtn blank
-	fetch 1,mem_state
-	rtnbit1 state_combkey		/* we have comb key, but not verified */
-	call parse_lmp_au_rand_1
-	// send link key request
-	branch p_hci_send_linkkey_req_event
-
-
-z_parse_lmp_max_slot_req:
-	fetch 1,mem_max_slot
-	pincrease 1
-	fetcht 1,mem_rxbuf+1
-	isub temp,null
-	nbranch z_parse_lmp_max_slot_req_not_accept,positive
-z_parse_lmp_max_slot_event:
-	storet 1,mem_max_slot
-	call accept_lmp_msg
-	branch z_hci_send_max_slots_change
-
-z_parse_dhkey_check:
-	fetch    1,mem_master_sp_state
-	beq SP_STAT_CONFIRM_SEND,z_parse_dhkey_check_test
-z_parse_dhkey_check_test:
-	jam LMP_ACCEPTED,mem_lmo_opcode2
-	branch parse_dhkey_check
-
-z_parse_lmp_max_slot_req_not_accept:
-	jam LMP_NOT_ACCEPTED,mem_lmo_opcode2
-	rtn
-
-z_hci_send_max_slots_change:
-	jam 3,mem_mesh_event_para_total_length
-	jam HCI_EVENT_MAX_SLOTS_CHANGE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	fetch 1,mem_conn_handle
-	istore 2,contw
-	fetch 1,mem_max_slot
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-	
-org z
-z_parse_lmp_conn_req:
-//	branch p_hci_send_conn_req_event
-
-z_hci_send_conn_req_event:
-	fetch 1,mem_conn_req_status
-	beq 1,z_hci_send_conn_req_event_estimate
-z_hci_send_conn_req_event_1:
-	call z_classic_connection_init
-	//BD_ADDR(6), Class_of_Device(3), Link_Type(1)
-	jam 10,mem_mesh_event_para_total_length
-	jam HCI_EVENT_CONNECTION_REQUEST,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	//call hci_write_plap
-	fetch 6,mem_plap
-	istore 6,contw
-	// class of device
-	fetch 3,extm_class
-	istore 3,contw
-	// link type, 0:SCO, 1:ACL
-	setarg 1
- 	istore 1,contw
-	fetch 6,mem_plap
-	store 6,mem_bd_addr_new
-	branch ipc_hci_tx_start
-z_hci_send_conn_req_event_estimate:
-	fetch 6,mem_bd_addr_new
-	fetcht 6,mem_plap
-	isub temp,null
-	branch z_hci_send_conn_req_event_1,zero
-	rtn	
-
-z_classic_connection_init:
-	jam 1,mem_conn_req_status
-	jam 0,mem_conn_status
-	//setarg 0
-	//store 8,mem_remote_features
-	//store 8,mem_remote_ext_features0
-	//store 8,mem_remote_ext_features1
-	rtn
-
-org z
-z_hci_send_inquiry_comple:
-	set0 mark_inquiry_on,mark
-	jam 1,mem_mesh_event_para_total_length
-	jam HCI_EVENT_INQUIRY_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-
-
-
-org z
-z_app_init:
-ifdef MINZHAN_SDK
-	jam 0,mem_ota_enable_xip_flag
-endif	
-	// RAM reset.
-	//jam 0,mem_ota_wdt_en_flag
-	//jam 0,mem_ota_wdt_m0_en
-	
-	jam 0x1c,0x1f000
-	jam 0x05,0x8042
-	call z_buck_setting
-	fetch 1,0x8341
-	store 1,mem_hibernate_flag
-
-	fetch 1,mem_xlmp_conn_state
-	store 1,mem_lmp_conn_state
-
-	ncall z_app_init_efuse_data,wake
-
-	
-ifdef FUNCTION_WATCH_DOG
-	call wdt_init_reset_with_start
-endif //FUNCTION_WATCH_DOG
-	call headset_init
-	
-ifdef MINZHAN_SDK	
-	call z_read_efuse_64_bytes
-endif
-
-	setarg p_app_event_normal_process
-	store 2,mem_cb_bb_event_process
-
-	setarg p_headset_evt_100ms_timer
-	store 2,mem_cb_event_timer
-	setarg p_headset_cb_idle_process
-	store 2,mem_cb_idle_process
-
-	setarg cb_enter_lpm
-	store 2,mem_cb_before_lpm
-	setarg cb_enter_hibernate
-	store 2,mem_cb_before_hibernate 
-
-	
-	//call headset_check_reconnet
-	//call p_ipc_notify_m0_wakeup_flag_init
-	
-	call z_set_gpio_after_lpm,wake
-//	call qspi_release_powerdown_flash,wake
-	nbranch wake_from_power,wake
-wake_for_lpm:
-	call ipc_lock_m0_lmp_wait_work_flag
-	call enable_xip
-	jam BT_EVT_WAKEUP,mem_fifo_temp
-	branch ipc_tx_bt_event
-
-ifdef MINZHAN_SDK
-z_read_efuse_64_bytes:
-	setarg 0
-	arg mem_efuse_64_bytes,rega
-	arg 64,temp
-	branch efuse_read_data
-endif
-
-wake_from_power:
-	// store local addr
-	fetch 6,mem_lap
-	store 6,mem_local_bdaddr
-ifdef MINZHAN_SDK
-	jam 2 ,core_reset 
-endif
-	call enable_xip
-
-	fetch 1,mem_hibernate_flag
-	bbit1 5,z_evt_restart
-	jam BT_EVT_RESET,mem_fifo_temp
-	call ipc_tx_bt_event
-
-	setarg 0x1171
-	store 2,mem_encryp_inital_value
-	branch z_efuse_custom_encryption
-
-z_evt_restart:
-	call p_clear_charge_reset_flag
-	jam BT_EVT_RESTART,mem_fifo_temp
-	branch ipc_tx_bt_event
-
-
-z_set_gpio_after_lpm:
-	call qspi_init_set
-	call qspi_gpio_init
-	nop 2000 // Delay for gpio26 work ready
-	branch qspi_release_powerdown_flash
-//	nop 100
-	//rtn
-
-z_buck_setting:
-	fetcht 4,core_lpm_buckctrl
-	storet 4,core_lpm_reg
-	jam 0xe6,0x804d
-	call p_lpm_write_wait_clock
-	jam 0x20,0x8005
-	branch p_lpm_write_wait_clock
-
-
-z_app_init_efuse_data:
-	setarg EFUSE_UCODE_ADC_GPIO_0_5
-	arg mem_efuse_adc_offset,rega
-	arg 8,temp
-	branch efuse_read_data
-
-
-org z
-z_ipc_init:
-	//fetch 1,mem_ipc_enable
-	//rtn blank
-	call z_ipc_notify_m0_wakeup_flag_init
-	call z_mram_clkon
-	branch ipc_init+5
-
-z_mram_clkon:
-	arg CLOCK_OFF_MRAM,queue
-	branch clk_on
-
-z_ipc_notify_m0_wakeup_flag_init:
-	jam 1,mem_wake_flag
-	rtn wake
-	jam 0,mem_wake_flag
-	rtn
-
-
-
-org z
-z_le_adv:
-	disable master
-	enable swfine
-	call le_init_adv
-	call le_next_adv_channel
-	call le_send_adv_ind
-	nbranch le_adv_not_match,match
-	fetch 1,mem_le_req_rcv
-	increase 1,pdata
-	store 1,mem_le_req_rcv
-	fetch 1,mem_le_rxbuf
-	and pdata,0x0f,pdata
-	beq SCAN_REQ,z_le_send_scan_response
-	branch le_adv+18
-
-z_le_send_scan_response:
-	arg SCAN_RSP,temp
-	fetch 1,mem_le_adv_own_addr_type
-	nsetflag blank,LE_SENDER_ADDR_BIT,temp
-	storet 1,mem_le_txheader
-	fetcht 1,mem_le_scan_data_len
-	add temp,6,pdata
-	store 1,mem_le_txlen
-	copy temp,loopcnt
-	fetch 1,mem_le_adv_own_addr_type
-	call p_le_get_public_addr,blank
-	ncall p_le_get_random_addr,blank
-	storet 6,mem_le_txpayload
-	arg mem_le_scan_data,contr
-	call memcpy
-	branch le_transmit_norx
-
-org z
-z_simple_pairing_process:
-	call z_master_simple_paring_sequence
-z_simple_pairing_sequence:
-	fetch 1,mem_sp_flag
-	rtn blank
-	jam      SP_FLAG_STANDBY,mem_sp_flag
-	fetch    1,mem_sp_state
-	beq  SP_STAT_CONFIRM_CHECK,z_sp_confirm_check
-	branch simple_pairing_sequence+5
-
-z_master_simple_paring_sequence:
-	fetch 1,mem_master_sp_flag
-	rtn blank
-	jam SP_FLAG_STANDBY,mem_master_sp_flag
-	fetch 1,mem_master_sp_state
-	beq SP_MASTER_STAT_START_SKIP,z_sp_master_send_io_cap_get
-	//beq SP_STAT_CONFIRM_SEND,p_master_sp_send_lmp_dhkey_check
-	beq SP_STAT_CONFIRM_CHECK,z_sp_confirm_check
-	//beq SP_STATE_END,p_master_sp_sm_end
-	branch master_simple_paring_sequence+5
-
-z_sp_confirm_check:
-	call sp_confirm_check
-	//branch p_hci_send_simple_pairing_complete_event
-z_hci_send_simple_pairing_complete_event:
-	//Status(1), BD_ADDR(6)
-	jam 7,mem_mesh_event_para_total_length
-	jam HCI_EVENT_SIMPLE_PAIRING_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg 0
- 	istore 1,contw
- 
-	fetch 6,mem_plap
-	istore 6,contw
-	branch ipc_hci_tx_start
-
-
-z_master_sp_send_lmp_dhkey_check:
-	branch tid_reply
-
-z_master_sp_sm_end:
-	//jam DEFAULT_STATEMACHINE,mem_sp_localsm
-	jam SP_STAT_DONE,mem_master_sp_state
-	call tid_initiate
-	//jam LMP_AU_RAND,mem_lmo_opcode2
-	call check_localsm_master
-ifdef SIMPLE_PAIRING
-	branch sp_master_key_prarm_push,true
-	branch sp_link_key_prarm_push
-endif
-	rtn
-
-z_sp_master_send_io_cap_get:
-	jam SP_FLAG_COMMIT,mem_master_sp_flag
-	jam SP_MASTER_STAT_START_DONE,mem_master_sp_state
-	rtn
-
-
-org z
-z_enter_hibernate_prepare_work:
-	call qspi_powerdown_flash
-z_clear_gpio_before_sleep:	
-	call z_clear_gpio_before_sleep_sub2
-	arg 32,loopcnt
-	arg core_gpio_conf,contr
-z_setgpio_loop:
-	copy contr,contw
-	ifetch 1,contr
-	beq gpcfg_qspi_sck,z_setgpio_pulldown
-	beq gpcfg_qspi_io0,z_setgpio_pulldown
-	beq gpcfg_qspi_io1,z_setgpio_pulldown
-	beq gpcfg_qspi_io3 ,z_setgpio_pulldown
-	beq gpcfg_iic_scl,z_setgpio_pulldown
-	beq gpcfg_iic_sda,z_setgpio_pulldown
-	bne gpcfg_input,z_setgpio_loop_end
-z_setgpio_pulldown:
-	setarg gpcfg_pulldown
-	istore 1,contw
-z_setgpio_loop_end:
-	loop z_setgpio_loop
-	rtn
-
-z_clear_gpio_before_sleep_sub2:	
-	arg 8,loopcnt
-	arg core_gpio_conf1,contr
-	branch z_setgpio_loop
-
-
-
-
-
-
-
-org z
-z_process_cmd:
-	call cmd_check_plap
-	nbranch z_process_cmd_conn_handle,zero
-//	branch process_cmd+6
-	
-	fetch 1,mem_hci_cmd
-	beq hci_cmd_remote_name_req,cmd_namereq
-	beq hci_cmd_pair,cmd_pair
-	beq hci_cmd_nopair,cmd_nopair
-	beq hci_cmd_linkkey,cmd_has_key
-	beq hci_cmd_nokey,cmd_no_key
-	beq hci_cmd_reject_conn,cmd_disconn
-	beq hci_cmd_role_switch,cmd_role_switch
-	beq hci_cmd_accept_conn,cmd_accept_conn
-	beq hci_cmd_accept_with_switch,cmd_accept_with_switch
-	beq hci_cmd_detach,cmd_detach
-	beq hci_cmd_in_sniff,cmd_in_sniff
-	beq hci_cmd_exit_sniff,z_cmd_exit_sniff
-z_process_cmd_conn_handle:
-	call cmd_check_handle
-	nrtn blank
-	fetch 1,mem_hci_cmd
-	beq hci_cmd_auth,z_cmd_auth
-	beq hci_cmd_send_supervision,z_cmd_send_supervision
-	branch process_cmd_conn_handle+4
-
-
-z_cmd_send_supervision:
-	jam LMP_SUPERVISION_TIMEOUT,mem_lmo_opcode2
-	branch cmd_exit
-
-z_cmd_exit_sniff:
-	jam LMP_UNSNIFF_REQ,mem_lmo_opcode2
-	branch cmd_exit
-
-z_cmd_auth:
-	fetch 1,mem_op
-	set1 op_auth_req,pdata
-	store 1,mem_op
-	fetch 1,mem_state
-	bbit1 state_linkkey,cmd_auth_sendaurand
-	call p_hci_send_linkkey_req_event
-	branch cmd_exit
-
-org z
-z_sniff_init:
-	bmark0 mark_sco_flag,z_sniff_init_acl
-	add clkn_bt,0,rega
-	branch z_sniff_init_master,master
-	add clke_bt,0,rega
-	branch z_sniff_init_master
-z_sniff_init_acl:
-	add clkn_bt,3,rega
-	branch z_sniff_init_master,master
-	add clke_bt,3,rega
-z_sniff_init_master:
-	fetcht 2,mem_tsniff
-	deposit rega
-	set0 27,pdata
-	idiv temp
-	fetch 2,mem_dsniff
-	call wait_div_end
-	remainder regc
-	isub regc,pdata
-	branch z_sniff_init_nowrap,positive
-	iadd temp,pdata
-z_sniff_init_nowrap:
-	iadd rega,pdata
-	store 4,mem_sniff_anchor
-	jam SWITCH_FLAG_INIT,mem_switch_flag
-	fetch 1,mem_state
-	set1 state_insniff,pdata
-	store 1,mem_state
-	fetch 1,mem_sniff_attempt
-	store 1,mem_current_sniff_attempt
-	setarg 0
-	store 3,mem_sniff_rcv
-	store 3,mem_sniff_lost
-	store 1,mem_sniff_unint_lost
-	fetch 2,mem_rx_window_sniff
-	store 2,mem_rx_window
-	nbranch z_sniff_init_mode_change,master
-	add am_addr,-1,queue
-z_sniff_init_mode_change:
-	jam 0x02,mem_mesh_event_parameter_status
-	branch z_hci_send_mode_change
-
-org z
-z_sniff_exit:
-	fetch 1,mem_state
-	rtnbit0 state_insniff
-	set0 state_insniff,pdata
-	store 1,mem_state
-	fetch 2,mem_rx_window_init
-	store 2,mem_rx_window
-	disable wake
-	jam 0x00,mem_mesh_event_parameter_status
-	branch z_hci_send_mode_change
-
-
-org z
-z_hci_send_role_change:
-	jam 8,mem_mesh_event_para_total_length
-	jam HCI_EVENT_ROLE_CHANGE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	force 0,pdata
-	istore 1,contw
-	fetch 6,mem_plap
-	istore 6,contw
-	fetch 1,mem_mesh_event_parameter_status
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-
-
-org z
-z_hci_send_role_change_err:
-	jam 0,mem_mesh_event_parameter_status
-	nbranch z_hci_send_role_change_err_slave,master
-	jam 1,mem_mesh_event_parameter_status
-z_hci_send_role_change_err_slave:
-	jam 8,mem_mesh_event_para_total_length
-	jam HCI_EVENT_ROLE_CHANGE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	force 0x35,pdata
-	istore 1,contw
-	fetch 6,mem_plap
-	istore 6,contw
-	fetch 1,mem_mesh_event_parameter_status
-	istore 1,contw
-	branch ipc_hci_tx_start
-
-
-org z
-z_newconn_init:
-	call init_lmp_reinit
-	call new_conn_handle
-	sub pdata,15,null
-	nbranch z_newconn_handle_init,positive
-	branch newconn_init+3
-z_newconn_handle_init:
-	jam 1,mem_handle_num
-	branch newconn_init+3
-
-
-org z
-z_parse_connect_req:
-//	fetch 1,mem_le_state
-//	rtnbit1 state_inconn
-	fetch 1,mem_le_rxbuf
-	fetcht 6,mem_le_lap
-	bbit1 LE_RECEIVER_ADDR_BIT,z_parse_connect_req_random_addr
-	branch z_parse_connect_req_public_addr
-z_parse_connect_req_random_addr:
-	fetcht 6,mem_mesh_le_random_address
-z_parse_connect_req_public_addr:
-	fetch 6,mem_le_rxbuf+8
-	isub temp,null
-	nrtn zero
-	call parse_connect_req+5
-	//arg SLAVE_CONNECTION_HANDLE,temp
-	//fetch 2,mem_le_init_superto
-	//store 2,mem_le_superto
-	branch z_hci_send_event_le_connection_complete
-
-
-org z 
-z_send_lmp:
-ifdef PATCH_DEBUG_LOG
-	// set flag
-	arg LOG_POINT_1001,rega
-	fetcht 1,mem_lmp_to_send
-	call debug_log_print
-endif
-	fetch 1,mem_lmp_to_send
-/* lmp message to be processed. this will either be because host??? */
-/* wants to send a lmp message or because one resulted from the LMP */
-/* processing section */
-/********* outgoing lmp lookup table *************/
-	bbit1 7,z_send_lmp_escape
-	beq LMP_SETUP_COMPLETE, z_send_lmp_setup_complete
-	beq LMP_SRES,z_send_lmp_sres
-	beq LMP_DETACH,z_send_lmp_detach
-	beq LMP_AU_RAND,z_send_lmp_aurand
-	branch send_lmp+10
-
-z_send_lmp_aurand:
-	fetch 1,mem_pairing_auth
-	branch z_send_lmp_aurand_notpairing,blank
-	call check_localsm
-	call tid_initiate,true				//master
-	ncall tid_reply,true				//slave
-	branch z_send_lmp_aurand_common
-z_send_lmp_aurand_notpairing:
-	call tid_initiate
-z_send_lmp_aurand_common:
-	call generate_random_number
-	force 17,pdata
-	call msg_send_lmp
-	arg mem_random_number,contr
-	call memcpy16
-	//branch p_send_lmp_tid
-z_send_lmp_tid:
-	fetcht 1,mem_state_map
-	and_into 1,temp	
-z_send_lmp_end:
-	fetch 1,mem_lmp_to_send
-	lshift pdata,pdata
-
-	bmark0 mark_slave_in_rand_accepted,z_send_lmp_end_master
-	nsetflag master,0,pdata
-	branch send_lmp_exit
-z_send_lmp_end_master:
-	setflag master,0,pdata
-	ixor temp,pdata
-	branch send_lmp_exit
-
-
-z_send_lmp_setup_complete:
-	fetch 1,mem_state
-	set1 state_conn_comp,pdata
-	store 1,mem_state
-	copy clkn_bt,pdata
-	store 4,mem_aurand_send_delay_time
-	fetch 1,mem_lmp_conn_state
-	bbit1 SENT_SETUP_COMPLETE,z_send_lmp_setup_complete_has_sent
-	set1 SENT_SETUP_COMPLETE,pdata
-	store 1,mem_lmp_conn_state
-	force 1,pdata
-	call msg_send_lmp
-	call send_lmp_request
-	branch p_hci_send_connection_complete
-
-z_send_lmp_setup_complete_has_sent:
-	jam 0,mem_lmp_to_send
-	rtn
-
-
-z_send_lmp_detach:
-	force 2,pdata
-	call msg_send_lmp
-	fetch 1,mem_disconn_reason_send
-	istore 1,contw
-	call send_lmp_request
-	branch p_prepare_disconnect
-
-org z 
-z_send_lmp_sres:
-	arg mem_lap,rega
-	call function_e1
-	force 5,pdata
-	call msg_send_lmp
-	fetch 4,mem_input_store
-	istore 4,contw
-	arg mem_sres_tid,temp
-	call special_tid_store
-	call copy_aco
-	call check_localsm
-	branch z_send_lmp_sres_master,true
-	jam DONE_ENCRYP,mem_wait_encryption
-	
-	bmark1 mark_slave_in_rand_accepted,z_send_lmp_sres_startenc_slave
-	fetch 1,mem_pairing_auth
-	rtn blank
-	jam LMP_AU_RAND,mem_lmo_opcode2
-z_send_lmp_sres_master:
-	bmark1 mark_slave_in_rand_accepted,z_send_lmp_sres_startenc_slave
-	fetch 1,mem_link_key_exists
-	rtn blank
-z_send_lmp_sres_startenc:
-	call check_localsm
-	nbranch z_send_lmp_sres_startenc_slave,true
-	rtn
-
-z_send_lmp_sres_startenc_slave:
-	rtnmark0 mark_slave_in_rand_accepted
-	set0 mark_slave_in_rand_accepted,mark
-	branch p_send_lmp_sres_startenc_slave_event_send
-
-
-
-
-
-org z
-z_le_parse_ll:
-//	fetch 2,mem_le_payload_ptr
-//	copy pdata,contr
-//	ifetch 1,contr
-	fetch 1,mem_le_rxbuf+2
-	beq LL_FEATURE_REQ,z_le_parse_feature_req
-	beq LL_FEATURE_RSP,z_le_parse_feature_rsp
-	beq LL_VERSION_IND,z_le_parse_version_ind
-	beq LL_CHANNEL_MAP_REQ,z_le_parse_channel_map_req
-	beq LL_CONNECTION_UPDATE_REQ,le_parse_connection_update_req
-	branch z_le_parse_ll_sub
-
-z_le_parse_channel_map_req:
-	ifetch 5,contr
-	store 5,mem_le_new_map
-	ifetch 2,contr
-	store 2,mem_le_instant
-	fetcht 2,mem_le_event_count
-	isub temp,null
-	nbranch le_parse_terminate_ind,positive
-	fetch 1,mem_le_state
-	set1 lestate_update_map,pdata
-	store 1,mem_le_state
-	rtn	
-
-
-z_le_parse_feature_req:
-	call z_le_parse_feature_rsp
-	arg 9,rega
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_FEATURE_RSP
-	istore 1,contw
-	fetch 8,mem_le_features
-	istore 8,contw
-	rtn	
-
-z_le_parse_feature_rsp:
-	ifetch 8,contr
-	store 8,mem_mesh_le_features
-	call p_le_parse_feature_rsp_master
-	//branch z_hci_send_le_read_remote_features_complete
-z_hci_send_le_read_remote_features_complete:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 LE_READ_REMOTE_FEATURES_COMPLETE_EVENT
-	jam 12,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg HCI_LE_SUBEVENT_REMOTE_FEATURE_COMPLETE
-	istore 2,contw		//subevent code & status
-	fetch 1,mem_le_conn_handle
-	istore 2,contw
-	fetch 8,mem_mesh_le_features
-	istore 8,contw
-	branch ipc_hci_tx_start
-
-z_le_parse_version_ind:
-	ifetch 5,contr
-	store 5,mem_mesh_le_version
-	call p_le_parse_version_ind_cmd_master
-	branch z_hci_send_read_remote_version_information_complete,master
-	fetch 1,mem_mesh_le_version_exchange_times
-	nrtn blank
-	pincrease 1
-	store 1,mem_mesh_le_version_exchange_times
-	branch le_send_version_ind
-
-z_hci_send_read_remote_version_information_complete:
-	fetch 8,mem_mesh_le_event_mask
-	rtnbit0 READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT
-	jam 8,mem_mesh_event_para_total_length
-	jam HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg COMMAND_SUCCEEDED
-	istore 1,contw		//subevent code & status
-	fetch 1,mem_le_conn_handle
-	istore 2,contw
-	fetch 5,mem_mesh_le_version
-	istore 5,contw
-	branch ipc_hci_tx_start
-
-
-
-org z
-z_le_parse_ll_sub:
-//	fetch 2,mem_le_payload_ptr
-//	copy pdata,contr
-//	ifetch 1,contr
-	fetch 1,mem_le_rxbuf+2
-	beq LL_LENGTH_REQ,z_le_parse_length_request
-	beq LL_LENGTH_RSP,z_le_parse_length_rsp
-	beq LL_TERMINATE_IND,z_le_parse_terminate_ind
-	branch le_parse_ll+2
-
-
-z_le_parse_terminate_ind:
-	ifetch 1,contr
-	store 1,mem_disconn_reason_send
-	branch le_parse_terminate_ind
-
-//input pdata, temp,return temp
-z_return_small:
-	isub temp,null
-	rtn positive
-	copy pdata,temp
-	rtn
-
-z_le_parse_length_rsp:
-	ifetch 8,contr
-	store 8,mem_remote_rx_max_octets
-
-	fetch 2,mem_remote_rx_max_octets
-	fetcht 2,mem_local_tx_max_octets
-	call z_return_small
-	storet 2,mem_remote_rx_max_octets
-	
-	fetch 2,mem_remote_tx_max_octets
-	fetcht 2,mem_local_rx_max_octets
-	call z_return_small
-	storet 2,mem_remote_tx_max_octets
-	//branch z_hci_send_event_le_connection_data_length_change
-z_hci_send_event_le_connection_data_length_change:
-	//fetch 8,mem_mesh_le_event_mask
-	//rtnbit0 LE_CONNECTION_UPDATE_COMPLETE_EVENT
-	jam 11,mem_mesh_event_para_total_length
-	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
-	call p_hci_prepare_send_event
-	setarg HCI_LE_SUBEVENT_DATA_LENGTH_CHANGE_EVENT
-	istore 1,contw		//subevent code
-	fetch 1,mem_le_conn_handle
-	istore 2,contw
-	fetch 8,mem_remote_rx_max_octets
-	istore 8,contw
-	branch ipc_hci_tx_start
-	
-z_le_parse_length_request:
-	call z_le_parse_length_rsp
-	//branch p_le_send_data_length_res
-//p_le_send_data_length_res:
-//	arg LL_LENGTH_RSP,regb
-z_le_send_data_length:
-	arg 9,rega
-//	call le_fifo_malloc_tx_ll
-	arg LLID_LE_LL,type
-	call le_fifo_malloc_tx
-	setarg LL_LENGTH_RSP
-	istore 1,contw
-	fetch 8,mem_local_rx_max_octets
-	istore 8,contw
-	rtn
-
-p_le_send_data_length_req:
-	arg LL_LENGTH_REQ,regb
-	branch z_le_send_data_length
-
-
Index: ModuleDemo/25_OTA/bt_demo/BT/sched/coef.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/coef.dat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/coef.dat	(nonexistent)
@@ -1,66 +0,0 @@
-
-
-
-#mem_coef_dac_table: 
-#48k
-	5d 02 00 73 07 00 92 0f 00 44 18 00 be 1c 00 bb 17 00 f3 06 00 56 ee ff
-      81 d8 ff cb d2 ff cb e5 ff 0c 0e 00 0b 3a 00 af 50 00 bc 3e 00 96 04 00
-	42 bb ff dc 8a ff 50 96 ff c4 e1 ff 0a 4c 00 0f 9a 00 31 97 00 b8 37 00
-	de a7 ff d5 39 ff f3 37 ff a8 b3 ff 84 70 00 43 fe 00 49 f9 00 23 4e 00
-	21 54 ff 0d a6 fe 1a c7 fe e8 c6 ff 75 21 01 72 fb 01 5c a4 01 80 15 00
-	56 19 fe 1d f0 fc f4 93 fd 2b 04 00 e3 0e 03 bc d5 04 60 de 03 57 1d 00
-	c7 50 fb b2 4d f8 23 77 f9 df 24 ff a6 ef 06 f9 7e 0c 2b af 0b 3b 18 03
-	83 9b f5 6f ee e9 28 06 e8 e4 63 f5 01 f8 11 ba 37 37 8d 12 5a 60 19 6f
-
-#44.1k
-	90 fb ff 94 f3 ff 94 e7 ff 58 db ff 53 d5 ff 60 dc ff ae f3 ff ff 16 00
-	be 39 00 d1 4a 00 9f 3c 00 03 0e 00 08 cf ff 3a 9d ff fa 96 ff a8 ca ff
-	31 2a 00 9a 8b 00 97 b9 00 d0 8e 00 b1 0e 00 f2 6c ff 71 fb fe e9 02 ff
-	43 98 ff 01 86 00 e8 5a 01 2c 9d 01 99 0c 01 5b d1 ff 57 79 fe 47 bc fd
-	83 1d fe e5 99 ff c6 91 01 d8 05 03 7e 13 03 8f 76 01 a7 c9 fe 97 56 fc
-	a1 7e fb af fc fc 61 63 00 96 27 04 86 48 06 89 53 05 c4 45 01 88 cc fb
-	a7 a7 f7 93 5d f7 d4 d4 fb 4b 8b 03 6f ee 0a a0 d7 0d 3c 9c 09 2b c2 fe
-	c6 74 f1 58 51 e8 56 de e9 a6 a8 f9 e6 45 16 ae 31 39 52 be 58 2c 6f 6b
-
-# 32k#24k#16k#12k#8k
-	1e 00 00 80 fe ff f8 fa ff 9c f4 ff f0 eb ff 18 e3 ff d0 dd ff 64 e0 ff
-	c7 ed ff 69 05 00 d4 21 00 2c 39 00 10 40 00 65 2e 00 45 04 00 c5 cc ff
-	66 9c ff 8b 8a ff 9a a7 ff 6f f3 ff d4 58 00 85 b1 00 26 d3 00 7d a1 00
-	b4 1e 00 a9 71 ff f6 dc fe 41 a7 fe 73 fc fe 36 d4 ff a7 ea 00 43 d2 01
-	3a 1c 02 72 89 01 dc 2f 00 1f 81 fe c0 29 fd 04 d0 fc 93 c9 fd f0 18 00
-	cc 70 02 b1 5e 04 3f bd 04 57 1b 03 99 d2 ff 9c 04 fc 6f 41 f9 f2 eb f8
-	1e a8 fb 4c d4 00 db af 06 49 d1 0a b9 0b 0b 1b 62 06 c7 ad fd 4e ac f3
-	43 59 ec 49 b9 eb 06 75 f4 c1 bd 06 23 e6 1f 43 e2 3a 1c 95 51 0b 89 5e
-
-#mem_coef_voice_table:
-	0c 00 12 00 1b 00 24 00 29 00 28 00 1d 00 07 00 
-	e4 ff b9 ff 8a ff 5f ff 42 ff 3c ff 53 ff 8c ff 
-	e4 ff 50 00 c2 00 25 01 63 01 68 01 27 01 9d 00 
-	d5 ff e7 fe f7 fd 33 fd cb fc ea fc af fd 27 ff 
-	49 01 f3 03 ee 06 f6 09 bd 0c f9 0e 6b 10 eb 10 00 00	
-
-#mem_coef_adc_table:
-	06 00 00 b4 ff ff a1 fe ff 59 fd ff 62 fe ff a4 04 00 ad 0e 00 cf 12 00
-	60 03 00 3f dd ff 9a b6 ff a8 bc ff 47 18 00 7a c8 00 04 92 01 1f 19 02
-	2c 00 00 aa 00 00 45 00 00 2e 00 00 cd ff ff 6d ff ff 2e ff ff 3e ff ff
-	ac ff ff 62 00 00 20 01 00 8f 01 00 6a 01 00 99 00 00 51 ff ff 08 fe ff
-	4f fd ff 99 fd ff ff fe ff 20 01 00 36 03 00 57 04 00 d5 03 00 97 01 00
-	3e fe ff 06 fb ff 53 f9 ff 26 fa ff 97 fd ff a4 02 00 71 07 00 ec 09 00
-	a7 08 00 8d 03 00 23 fc ff 23 f5 ff 8e f1 ff 6e f3 ff d9 fa ff 96 05 00
-	b4 0f 00 e3 14 00 32 12 00 7a 07 00 e3 f7 ff 18 e9 ff 60 e1 ff 27 e5 ff
-	df f4 ff 2d 0c 00 cf 22 00 3a 2f 00 28 2a 00 de 11 00 f2 eb ff b5 c4 ff
-	1d ac ff 03 b1 ff 18 dc ff 3a 2c 00 8b 95 00 bc 03 01 15 5f 01 ce 92 01
-	06 ff ff 0d fe ff eb 01 00 e0 01 00 83 fd ff e9 fc ff cb 03 00 7a 04 00
-	99 fa ff b0 f9 ff 7d 07 00 a7 08 00 de f5 ff 62 f4 ff 7b 0d 00 5f 0f 00
-	46 ee ff d6 eb ff 2e 17 00 63 1a 00 a4 e1 ff 44 dd ff 37 28 00 8f 2e 00
-	45 c9 ff 1e bf ff ca 4e 00 28 62 00 83 7f ff 0e 4a ff f6 31 01 5f 99 03
-
-#mem_coef_eq_table:
-	00 00 10 c8 00 20 3e 2e c0 1e d1 1f c4 d1 3f 1b 2e e0 13 05 20 48 41 c0
-	33 ba 1f b8 be 3f ba 40 e0 b6 da 1f 99 b5 c0 dc 71 1f 67 4a 3f 6e b3 e0
-	f7 dc 1f 07 3e c1 9d ed 1e f9 c1 3e 6c 35 e1 2f f7 1f 41 43 c2 7a e7 1d
-	bf bc 3d 57 21 e2 66 5e 20 1d 40 c4 79 e5 1b e3 bf 3b 20 bc e3 3f 7e 21
-	d7 71 c8 9f 05 18 29 8e 37 22 7c e6 50 01 22 0d 5b d3 b4 8b 11 f3 a4 2c
-	fd 72 ec 4c 3e 20 42 f2 eb 2f dd 07 be 0d 14 85 e4 f7 0f 60 23 67 35 13
-	39 ee 07 b3 c0 e9 9e bb f7
-	
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/BT/sched/patch.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/patch.dat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/patch.dat	(nonexistent)
@@ -1,67 +0,0 @@
-
-mem_patch00:     
-04   #mem_patch00
-40   #mem_patch01
-01   #mem_patch02
-50   #mem_patch03
-11   #mem_patch04
-00   #mem_patch05
-04   #mem_patch06
-46   #mem_patch07
-12   #mem_patch08
-00   #mem_patch09
-10   #mem_patch0A
-31   #mem_patch0B
-00   #mem_patch0C
-1c   #mem_patch0D
-00   #mem_patch0E
-00   #mem_patch0F
-62   #mem_patch10
-00   #mem_patch11
-00   #mem_patch12
-40   #mem_patch13
-11   #mem_patch14
-01   #mem_patch15
-00   #mem_patch16
-06   #mem_patch17
-00   #mem_patch18
-00   #mem_patch19
-00   #mem_patch1A
-00   #mem_patch1B
-01   #mem_patch1C
-00   #mem_patch1D  
-00   #mem_patch1E
-00   #mem_patch1F
-80   #mem_patch20
-10   #mem_patch21
-1c   #mem_patch22
-00   #mem_patch23
-e8   #mem_patch24
-07   #mem_patch25
-00   #mem_patch26
-c8   #mem_patch27
-06   #mem_patch28
-89   #mem_patch29
-04   #mem_patch2A
-29   #mem_patch2B
-11   #mem_patch2C
-40   #mem_patch2D
-13    #mem_patch2E
-00   #mem_patch2F
-00   #mem_patch30
-00   #mem_patch31
-04   #mem_patch32
-00   #mem_patch33
-60   #mem_patch34
-00   #mem_patch35
-04   #mem_patch36
-00   #mem_patch37
-00   #mem_patch38
-00   #mem_patch39
-10   #mem_patch3A
-00   #mem_patch3B
-00   #mem_patch3C
-00   #mem_patch3D
-00   #mem_patch3E
-00   #mem_patch3F
-
Index: ModuleDemo/25_OTA/bt_demo/BT/sched/rf.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/rf.dat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/rf.dat	(nonexistent)
@@ -1,34 +0,0 @@
-mem_lpm_config:8f 10 ca
-mem_lpm_buckcnt:0a 0b ef 07
-mem_lpm_hibernate_switch:00
-mem_gpio_wakeup_low:00 00 00 00 00 00 00 00
-mem_fcomp_mul:02
-mem_fcomp_div:24
-mem_iscan_window:20 00
-mem_iscan_interval:00 04
-mem_pscan_window:16 00
-mem_pscan_interval:00 04
-mem_inq_window:20 00
-mem_page_window:30 00
-mem_page_to:00 30
-mem_rx_window_init:80 03
-mem_rx_window_sniff:00 06
-
-#if you find lpo_time not near 0x2a, you must think the pre timer maybe error.
-#DVDD 0.1uF, VFB 1uF    Time:   DVDD up time: 4us, VFB up time: 255us
-#DVDD 0.1uF, VFB 10uF    Time:   DVDD up time: 4us, VFB up time: 305us 
-#clock unit is internal 32K, 1 step is near 32us
-#so we set:
-#1: digldo pre-on counter(DVDD):  0x02
-#2: exen pre-on counter(VFB):  0x14
-#3: xtal pre-on counter(XTAL) set to zero becouse it will set in lpm_cal_xtal_startup
-mem_lpm_xtalcnt:00 20 18 bf 07
-
-mem_ef_base:00 ff 87
-mem_eeprom_block_size:80
-
-mem_rf_init:
-ff
-
-mem_rf_init_ptr:mem_rf_init
-
Index: ModuleDemo/25_OTA/bt_demo/BT/sched/user.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/user.dat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT/sched/user.dat	(nonexistent)
@@ -1,324 +0,0 @@
-
-##############NVRAM CONFIG##############
-mem_nv_data_ptr:mem_nv_data
-mem_nv_data_number:05
-#####################################
-
-##############BLUETOOTH CONFIG##############
-###commom###
-mem_device_option:0f
-mem_lmp_version:09 0e 05 06 00
-###ble###
-mem_le_lap:d5 cc aa aa cc 52
-
-mem_le_adv_data_len:12
-mem_le_adv_data:
-02 01 0e 
-04 09 4f 54 41
-09 ff 0e 05 21 11
-
-mem_le_scan_data_len:05
-mem_le_scan_data:
-'\09OTA
-
-
-mem_le_adv_enable:00
-mem_le_scan_type:01
-mem_le_adv_type:00
-mem_le_adv_direct_addr_type:00
-mem_le_scan_own_addr_type:00
-mem_le_scan_filter_policy:00
-mem_le_scan_interval:28
-mem_le_scan_window:0c 00
-mem_le_transmit_window:50
-mem_le_adv_interval_max:60 01 
-mem_le_adv_own_addr_type:00
-
-mem_le_pairing_mode:00
-mem_le_secure_connect_enable:00
-mem_le_pres:02 03 00 01 10 02 03 #justwork
-
-mem_le_pairing_handle:00 00
-
-mem_le_interal_min:
-10 00 #interval max
-10 00 #interval min
-00 00 #latency
-00 01 #supervision timeout
-
-###3.0###
-mem_sp_iocap_local:03 00 00
-mem_role_switch_flag:00
-mem_scan_mode:00
-mem_class: 04 04 24
-mem_local_name_length:
-'EVKOTA
-
-#FF FF FF is Fixed for OTA.
-mem_lap:45 FF 31 FF FF FF
-
-mem_discovery_timeout:00 07 
-mem_ssp_enable:01
-mem_ui_profile_supported:48
-mem_app_connection_options:17
-mem_eir_enable:01
-mem_all_uuid_16bits:
-05
-03#Type: Complete list of 16-bit UUIDs
-1e11 0e11 0811 0d11 0b11
-
-mem_all_uuid_128bits:00
-
-mem_ota_version:0a 00
-mem_ota_write_handle:06
-mem_ota_notify_handle:03
-mem_ota_buck_size:00 10
-mem_ota_packet_max_len:be 00
-
-#attribute list: handle 2bytes, uuid 2bytes, length 1bytes, attribute Nbytes
-mem_le_att_list:
-
-#Primary service yichip transmit ------
-01 00 02 00 28 02 ff ff
-#Characteristic tx--notify
-02 00 02 03 28 01 10
-03 00 02 11 ff 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#Client Characteristic Configuration
-04 00 02 02 29 02 01 00
-
-#Characteristic rx--write
-05 00 02 03 28 01 04
-06 00 02 22 ff  14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-#End of Attribute list
-00 00
-
-
-
-mem_lpm_mode:00
-mem_lpm_overhead:08
-mem_lpm_interval:00 02
-mem_lpm_mult:03
-mem_lpm_mult_timeout:03
-mem_ptt:01
-mem_features:
-ff
-ff
-ff
-fa	#fe--EDR  F8--BR
-db	#AFHclose 83  #AFHenable_slave cap and classification LMP_SLAVE_AFH_CLASSIFICATION enable 9b, disable 8b
-fd    #9d
-7b
-83
-
-mem_le_features:
-21				//length extension
-00
-00
-00
-00
-00
-00
-00
-
-
-mem_xip_option:5d 40 bb
-
-mem_ui_le_uuid_table:mem_le_att_list
-
-mem_seqi:7f
-
-mem_le_connection_updata_param:
-06 00
-06 00
-00 00
-f4 01
-
-
-mem_codec_msbc_support:00
-mem_codec_type:01
-mem_eq_flag:01
-
-mem_UI_HF_brsf_feature:313538 #30 33 30 
-mem_le_more_data:01
-mem_ipc_enable:01
-
-mem_tws_state:00
-mem_tws_bdaddr:96 55 12 11 33 62
-#mem_tws_bdaddr:96 45 12 00 19 62
-
-
-mem_hsp_role:00
-mem_auto_hsp_role:01
-mem_tws_allow_pairing:01
-mem_tws_allow_pairing_rssi_limit:45
-
-mem_tws_rf_start_anchor:b0 04   # 0x1e0 40us,   0x78 10us,   0x4b0 100us,   0x618 130us
-mem_tws_rf_rcv_window_size:78 00
-
-mem_tws_rf_packet_rx_window_size:f0 0a # 2800
-mem_tws_rf_slave_send_full_packet_sleep_time:58 02 # 50us
-# mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us)
-# send delay is mem_tws_rf_slave_send_full_packet_sleep_time, so we can think the judge below
-# mem_tws_rf_packet_rx_window_size - (mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us) + mem_tws_rf_slave_send_full_packet_sleep_time/2)
-mem_tws_rf_master_check_raw_id_time:db 04
-
-mem_rf_debug_enable: 00
-mem_rf_debug_rf_rx_debug_gpio: 0c
-mem_rf_debug_rf_tx_debug_gpio: 0e
-mem_rf_debug_rf_sync_detect_debug_gpio: 13
-mem_rf_debug_rf_crc_error_debug_gpio: 19
-
-
-mem_param_sco_use_cm0:01
-
-
-# ipc define
-#mem_param_ipc_mem_block_start_addr
-mem_param_ipc_to_bt_buf_start_addr:00 d8 01
-mem_param_ipc_to_bt_buf_end_addr:00 db 01
-mem_param_ipc_to_bt_wptr_addr:00 db 01
-mem_param_ipc_to_bt_rptr_addr:04 db 01
-mem_param_ipc_to_m0_wptr_addr:08 db 01
-mem_param_ipc_to_m0_rptr_addr:0c db 01
-mem_param_ipc_to_m0_buf_start_addr:50 db 01
-mem_param_ipc_to_m0_buf_end_addr:00 dd 01
-#mem_param_ipc_mem_block_end_addr
-
-
-# debug log define
-#mem_param_debug_log_mem_block_start_addr
-mem_param_debug_log_func_enable:00
-
-mem_param_debug_log_initial_flag_addr:10 db 01
-mem_param_debug_log_lock_flag_cm0_addr:11 db 01
-mem_param_debug_log_lock_flag_respin_addr:12 db 01
-mem_param_debug_log_lock_victim_addr:13 db 01
-mem_param_debug_log_read_index_addr:14 db 01
-mem_param_debug_log_write_index_addr:16 db 01
-mem_param_debug_log_buffer_start_addr:18 db 01
-mem_param_debug_log_buffer_end_addr:50 db 01
-#mem_param_debug_log_mem_block_end_addr
-
-# soft dma define
-# size is SOFT_DMA_TABLE_TOTAL_COUNT*4 + SOFT_DMA_TABLE_TOTAL_COUNT*SOFT_DMA_TABLE_UNIT_SIZE = 0x100
-mem_param_soft_dma_enable:01
-mem_param_soft_dma_table_start_addr:10 d5 01
-
-
-# sco m0 rx buffer define
-# size is M0_SCO_RX_BUFFER_SIZE + M0_SCO_TX_BUFFER_SIZE
-mem_param_m0_respin_sco_buffer_start_addr:10 d6 01
-
-
-mem_param_use_cm0_control_flag:01
-# tishi buffer size is 0x2000
-mem_param_tishi_start_addr:00 a0
-
-#mem_app_debug_info_timer use to set first debug timeout
-#mem_param_app_debug_info_timeout use to set period
-mem_app_debug_info_timer:05
-mem_param_app_debug_info_timeout:32
-
-mem_param_tws_tx_power:02
-
-mem_param_tws_send_channel_array:08 24 08 24
-#mem_param_tws_send_channel_array:20 20 20 20
-#mem_param_tws_send_channel_array:08 09 10 11
-
-mem_tx_power:02
-
-mem_sfreq_enable:01
-#mem_param_rf_setup must big then mem_param_pll_setup, be-careful, mem_param_rf_setup real value = 0xEA6 - value
-#we suggest must reserve 0x3A6, means mem_param_rf_setup = (0xEA6 - mem_param_pll_setup - 0x3A6)
-#mem_param_rf_setup:B8 07
-#mem_param_pll_setup:48 03
-mem_param_rf_setup:00 06
-mem_param_pll_setup:00 05
-
-mem_audio_output_setting: 01
-
-
-mem_mram_qspi_tx_addr:00 60
-
-mem_vp_addr:
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-
-mem_fec_required:00		
-mem_eir:
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 00 00 00 00
-mem_simple_pairing_mode:00	
-mem_conn_status:00
-mem_io_cap_flag:00
-mem_inquiry_mode:00
-
-
-mem_param_alloc_normal_buffer_start_address:00 18
-mem_param_alloc_normal_buffer_max_length:83 00
-mem_param_alloc_big_buffer_start_address:00 20
-mem_param_alloc_big_buffer_max_length:b0 02
-mem_l2cap_rx_max_lenth:b0 02
-
-
-mem_alloc_normal_total_size:0a
-mem_alloc_big_total_size:0a
-mem_snd_br_total_size:0a
-mem_snd_ble_total_size:0a
-mem_snd_hci_total_size:0a
-
-mem_hci_version_svnid:4486
-
-mem_keyscan_switch:00
-
-mem_public_code_svn_version_code:00 00 00 00 00 00 00 00 00
-
-mem_le_tws_scan_interval:28 00
-mem_le_tws_scan_window:0c 00
-mem_param_le_tws_adv_interval_normal:00 01 
-mem_param_le_tws_adv_interval_master_listen:58 00 
-
-
-#mesh init
-mem_mesh_event_head_type:04	#HCI_H4_TYPE_EVENT
-
-mem_mesh_command_complete_num_hci_command_packet:01
-
-mem_mesh_read_local_version_info:
-09		#hci_version BT_HCI_VERSION_5_0
-00 00	#hci_revsion
-09		#lmp_version RADIO_BLE_VERSION_NUMBER:BT_HCI_VERSION_5_0
-0e 05	#manufacture_name Yichip Microelectronics (Hangzhou) Co.,Ltd.
-FF FF	#LPM_subversion
-
-mem_mesh_read_local_support_command:02 05 ff
-
-mem_device_public_address:11 22 33 44 55 66
-
-mem_local_rx_max_octets:fb 00 48 08 fb 00 48 08  
-
-
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_Powering_On.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_Powering_On.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_battery_is_near_empty.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_battery_is_near_empty.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_battery_is_near_empty48_48k.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_battery_is_near_empty48_48k.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_disconnect.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_disconnect.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_max_vol.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_max_vol.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_max_vol_48k.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_max_vol_48k.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_paired.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_paired.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_powering_off.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_powering_off.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_tws_connected.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/British_Eng_tws_connected.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/eight.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/eight.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/five.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/five.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/four.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/four.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/nine.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/nine.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/one.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/one.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/ring.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/ring.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/seven.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/seven.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/six.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/six.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/three.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/three.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/two.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/two.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/zero.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/25_OTA/bt_demo/BT/voice_prompt/zero.pcm
___________________________________________________________________
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: ModuleDemo/25_OTA/bt_demo/BT
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/BT	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/BT
___________________________________________________________________
Deleted: svn:ignore
## -1 +0,0 ##
-output
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Listings
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Listings	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Listings	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Listings
___________________________________________________________________
Deleted: svn:ignore
## -1,2 +0,0 ##
-startup.lst
-yc11xx.map
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/output
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/output	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/output	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/output
___________________________________________________________________
Deleted: svn:ignore
## -1 +0,0 ##
-out.rom
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/c.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/c.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/c.bat	(nonexistent)
@@ -1,159 +0,0 @@
-@echo on
-cls
-
-set ROOT_PATH=..\..
-set RESPIN_PATH=%ROOT_PATH%\respin
-set OBJ_PATH=.\Objects
-set now_path=%~dp0
-call:getstrlocation %now_path% ModuleDemo location
-call:get_fix_len_str  %now_path% location soft_path
-set lib_path=%soft_path%Librarier
-set rom_path=%lib_path%\bt_rom
-set util=%rom_path%\util
-@echo on
-echo start compile cm0 bin
-set OBJ_PATH=.\Objects
-perl %OBJ_PATH%\tool\hex2rom.pl 0 80000  32 %OBJ_PATH%\yc11xx.hex  %OBJ_PATH%\output\out.rom
-copy %OBJ_PATH%\output\out.rom ..\Output
-
-echo compile cm0 bin ok
-@echo off
-copy %RESPIN_PATH%\ramcode.rom ..\Output\ramcode.rom
-copy %RESPIN_PATH%\sched.rom   ..\Output\sched.rom
-copy %RESPIN_PATH%\memmap.format   ..\Output\memmap.format
-copy %RESPIN_PATH%\zcode.rom   ..\Output\zcode.rom 
-cd ..\Output
-::%util%/geneep  -n -z 
-%util%/geneep -f -n -z
-
-del zcode.rom 	/s
-del ramcode.rom 	/s
-del memmap.format 	/s
-del sched.rom 	/s
-
-perl %util%\flash2bin.pl
-
-echo compile full bin ok
-
-:end
-goto:eof
-
-::------------------------------------------
-::---------------func:get_fix_len_str-------
-::------------------------------------------
-:get_fix_len_str
-setlocal
-set "getstr=%NULL%"
-set str=%1
-set /a len=%2
-set num=0
-:get_fix_len_str_loop
-set getstr=%getstr%%str:~0,1%
-set /a num+=1
-set str=%str:~1%
-if %num% lss %len% goto get_fix_len_str_loop
-(endlocal
- set %3=%getstr%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-::------------------------------------------
-::---------------func:getstrlocation-------
-::------------------------------------------
-:getstrlocation
-setlocal
-set "bstr=%1"
-set "cstr=%2"
-set %3=0
-set "num=0"
-set "len_bstr=0"
-set "len_cstr=0"
-
-call:getstrlen %bstr% len_bstr
-call:getstrlen %cstr% len_cstr
-
-:getstrlocation_next
-set /a len_remain=len_bstr-num
-if %len_remain% lss %len_cstr% (
-echo "cann't get str location"
-set /a num =0
-goto getstrlocation_last
-)
-
-call:get_fix_len_str %bstr%  len_cstr compar_str
-
-if not %compar_str%==%cstr% (
-set /a num+=1
-set "bstr=%bstr:~1%"
-goto getstrlocation_next
-)
-
-:getstrlocation_last
-(endlocal
-	set %3=%num%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlen-------------
-::------------------------------------------
-:getstrlen
-setlocal
-set str=%1
-set %2=0
-set /a "num=0"
-
-:getstrlen_next
-if "%str%"=="" goto getstrlen_last
-
-if not "%str%"=="" (
-set /a num+=1 
-set "str=%str:~1%"
-goto getstrlen_next
-)
-
-:getstrlen_last
-(endlocal
-	set /a "%2=%num%"
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getcharlocation-------
-::------------------------------------------
-:getcharlocation
-setlocal
-set "str=%1"
-set "ch=%2"
-set %3=0
-set /a "num=0"
-
-:getcharnext
-if "%str%"=="" ( 
-set /a num=0
-goto getcharlast
-)
-
-if not "%str%"=="" (
-set /a num+=1
-if "%str:~0,1%"=="%ch%" goto getcharlast
-set "str=%str:~1%"
-goto getcharnext
-)
-:getcharlast
-(endlocal
-set %3=%num%
-)
-goto:eof 
-::---------------end:func-------------------
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/d.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/d.bat	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/d.bat	(nonexistent)
@@ -1,146 +0,0 @@
-::@echo off
-cls
-echo start download ROM code...
-cd ..\Output
-
-e pu
-::e 8097   040307020506  
-:: enable flash vcc
-e 809a 3f
-:: set flash io port
-e 8090 060502
-e 8094 070304
-e pu
-e fa
-e fr 0 30 
-e fc
-e 8043 00
-::e fw 3 a5
-e fp flash.dat 1000
-e fw 4 a5
-e fw 0 031000
-e k
-pause
-
-
-echo download ROM code OK
-goto:eof
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlocation-------
-::------------------------------------------
-:getstrlocation
-setlocal
-set "bstr=%1"
-set "cstr=%2"
-set %3=0
-set "num=0"
-set "len_bstr=0"
-set "len_cstr=0"
-
-call:getstrlen %bstr% len_bstr
-call:getstrlen %cstr% len_cstr
-
-:getstrlocation_next
-set /a len_remain=len_bstr-num
-if %len_remain% lss %len_cstr% (
-echo "cann't get str location"
-set /a num =0
-goto getstrlocation_last
-)
-
-call:get_fix_len_str %bstr%  len_cstr compar_str
-
-if not %compar_str%==%cstr% (
-set /a num+=1
-set "bstr=%bstr:~1%"
-goto getstrlocation_next
-)
-
-:getstrlocation_last
-(endlocal
-	set %3=%num%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-::------------------------------------------
-::---------------func:get_fix_len_str-------
-::------------------------------------------
-:get_fix_len_str
-setlocal
-set "getstr=%NULL%"
-set str=%1
-set /a len=%2
-set num=0
-:get_fix_len_str_loop
-set getstr=%getstr%%str:~0,1%
-set /a num+=1
-set str=%str:~1%
-if %num% lss %len% goto get_fix_len_str_loop
-(endlocal
- set %3=%getstr%
-)
-goto:eof
-::---------------end:func-------------------
-
-
-
-
-::------------------------------------------
-::---------------func:getstrlen-------------
-::------------------------------------------
-:getstrlen
-setlocal
-set str=%1
-set %2=0
-set /a "num=0"
-
-:getstrlen_next
-if "%str%"=="" goto getstrlen_last
-
-if not "%str%"=="" (
-set /a num+=1 
-set "str=%str:~1%"
-goto getstrlen_next
-)
-
-:getstrlen_last
-(endlocal
-	set /a "%2=%num%"
-)
-goto:eof
-::---------------end:func-------------------
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/hex2rom.pl
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/hex2rom.pl	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/tool/hex2rom.pl	(nonexistent)
@@ -1,65 +0,0 @@
-#!/usr/bin/perl
-
-my @rom = ();
-die "missing start and end address" if(@ARGV < 2);
-
-$addrhi = 0;
-$baseaddr = hex($ARGV[0]);
-$endaddr = hex($ARGV[1]);
-$bits = 32;
-$bits = $ARGV[2] if(@ARGV > 2);
-$endian = 1;
-
-
-$inputfile_addr = $ARGV[3];
-print "\input:  $inputfile_addr\n";
-$outputfile_addr =$ARGV[4];
-print "\output:  $outputfile_addr\n";
-
-
-open(DATA,$inputfile_addr);
-
-while(<DATA>){
-	$line++;
-	$count = (hex substr($_, 1, 2));
-	$addr = (hex substr($_, 3, 4));
-	$type = (hex substr($_, 7, 2));
-	if($type == 2 || $type == 4) {
-		$addrhi = hex(substr($_, 9, 4)) << ($type == 2 ? 4 : 16);
-		printf "type=%d, addr=%x, line=%d\n", $type, $addrhi, $line;
-	}
-	if($type == 0 && $addrhi >= $baseaddr && $addrhi <= $endaddr) {
-		for($x=0; $x<$count; $x++) {
-			$rom[$addrhi - $baseaddr + $addr + $x] = (hex substr($_, 9+2*$x, 2)) ; 
-		}
-	}
-}
-
-#هˆ é™¤ç›®و ‡و–‡ن»¶
-unlink($outputfile_addr);
-#هˆ›ه»؛ç›®و ‡و–‡ن»¶
-$outputfile_addr =$ARGV[4];
-$outputfile_addr = '+>'.$outputfile_addr;
-print "$outputfile_addr\n";
-open(DATA1,$outputfile_addr) or die "des file open fail,$!";
-
-if($bits == 1) {
-	for($x=0; $x<@rom; $x++) {
-			printf ("%04x\n", $rom[$x]);
-		}
-		print "\n";
-} else {
-	for($x=0; $x<@rom; $x+=$bits/8) {
-		for($i = 0;$i < $bits/8;$i++) {
-			$tmp = sprintf("%02x",($endian ? $rom[$x+$bits/8-1-$i] : $rom[$x+$i])),
-			print DATA1 "$tmp";
-#			printf "$tmp";
-			}
-		print DATA1 "\n";
-#		printf "\n";
-	}
-}
-$inputfile_addr = $ARGV[3];
-$outputfile_addr =$ARGV[4];
-close(inputfile_addr);
-close(outputfile_addr);
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/yc11xx.sct
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/yc11xx.sct	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects/yc11xx.sct	(nonexistent)
@@ -1,17 +0,0 @@
-; *************************************************************
-; *** Scatter-Loading Description File generated by uVision ***
-; *************************************************************
-
-LR_IROM1 0x00000000 0x00080000  {    ; load region size_region
-  ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
-   startup.o (|.text|,+RO)
-   startup.o (RESET, +First)
-	*(InRoot$$Sections)
-	.ANY (+RO)
-  }
-	; if change this, must change startup.s __initial_sp
-	 RW_IRAM1 0x10010000 0x7fff  {  ; RW data
-	.ANY (+RW +ZI)
-	}
-}
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/Objects
___________________________________________________________________
Deleted: svn:ignore
## -1,34 +0,0 ##
-drv_bt.crf
-drv_bt.d
-drv_bt.o
-drv_debug.crf
-drv_debug.d
-drv_debug.o
-main.crf
-main.d
-main.o
-startup.d
-startup.o
-system.crf
-system.d
-system.o
-yc11xx.axf
-yc11xx.build_log.htm
-yc11xx.hex
-yc11xx.htm
-yc11xx.lnp
-yc11xx_bt.crf
-yc11xx_bt.d
-yc11xx_bt.o
-yc11xx_gpio.crf
-yc11xx_gpio.d
-yc11xx_gpio.o
-yc11xx_qspi.crf
-yc11xx_qspi.d
-yc11xx_qspi.o
-yc11xx_uart.crf
-yc11xx_uart.d
-yc11xx_uart.o
-yc_drv_common.crf
-yc_drv_common.d
-yc_drv_common.o
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvoptx
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvoptx	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvoptx	(nonexistent)
@@ -1,471 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
-<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
-
-  <SchemaVersion>1.0</SchemaVersion>
-
-  <Header>### uVision Project, (C) Keil Software</Header>
-
-  <Extensions>
-    <cExt>*.c</cExt>
-    <aExt>*.s*; *.src; *.a*</aExt>
-    <oExt>*.obj; *.o</oExt>
-    <lExt>*.lib</lExt>
-    <tExt>*.txt; *.h; *.inc</tExt>
-    <pExt>*.plm</pExt>
-    <CppX>*.cpp</CppX>
-    <nMigrate>0</nMigrate>
-  </Extensions>
-
-  <DaveTm>
-    <dwLowDateTime>0</dwLowDateTime>
-    <dwHighDateTime>0</dwHighDateTime>
-  </DaveTm>
-
-  <Target>
-    <TargetName>Target 1</TargetName>
-    <ToolsetNumber>0x4</ToolsetNumber>
-    <ToolsetName>ARM-ADS</ToolsetName>
-    <TargetOption>
-      <CLKADS>12000000</CLKADS>
-      <OPTTT>
-        <gFlags>1</gFlags>
-        <BeepAtEnd>1</BeepAtEnd>
-        <RunSim>0</RunSim>
-        <RunTarget>1</RunTarget>
-        <RunAbUc>0</RunAbUc>
-      </OPTTT>
-      <OPTHX>
-        <HexSelection>1</HexSelection>
-        <FlashByte>65535</FlashByte>
-        <HexRangeLowAddress>0</HexRangeLowAddress>
-        <HexRangeHighAddress>0</HexRangeHighAddress>
-        <HexOffset>0</HexOffset>
-      </OPTHX>
-      <OPTLEX>
-        <PageWidth>79</PageWidth>
-        <PageLength>66</PageLength>
-        <TabStop>8</TabStop>
-        <ListingPath>.\Listings\</ListingPath>
-      </OPTLEX>
-      <ListingPage>
-        <CreateCListing>1</CreateCListing>
-        <CreateAListing>1</CreateAListing>
-        <CreateLListing>1</CreateLListing>
-        <CreateIListing>0</CreateIListing>
-        <AsmCond>1</AsmCond>
-        <AsmSymb>1</AsmSymb>
-        <AsmXref>0</AsmXref>
-        <CCond>1</CCond>
-        <CCode>0</CCode>
-        <CListInc>0</CListInc>
-        <CSymb>0</CSymb>
-        <LinkerCodeListing>0</LinkerCodeListing>
-      </ListingPage>
-      <OPTXL>
-        <LMap>1</LMap>
-        <LComments>1</LComments>
-        <LGenerateSymbols>1</LGenerateSymbols>
-        <LLibSym>1</LLibSym>
-        <LLines>1</LLines>
-        <LLocSym>1</LLocSym>
-        <LPubSym>1</LPubSym>
-        <LXref>0</LXref>
-        <LExpSel>0</LExpSel>
-      </OPTXL>
-      <OPTFL>
-        <tvExp>1</tvExp>
-        <tvExpOptDlg>0</tvExpOptDlg>
-        <IsCurrentTarget>1</IsCurrentTarget>
-      </OPTFL>
-      <CpuCode>7</CpuCode>
-      <DebugOpt>
-        <uSim>0</uSim>
-        <uTrg>1</uTrg>
-        <sLdApp>1</sLdApp>
-        <sGomain>1</sGomain>
-        <sRbreak>1</sRbreak>
-        <sRwatch>1</sRwatch>
-        <sRmem>1</sRmem>
-        <sRfunc>1</sRfunc>
-        <sRbox>1</sRbox>
-        <tLdApp>1</tLdApp>
-        <tGomain>1</tGomain>
-        <tRbreak>1</tRbreak>
-        <tRwatch>1</tRwatch>
-        <tRmem>1</tRmem>
-        <tRfunc>0</tRfunc>
-        <tRbox>1</tRbox>
-        <tRtrace>1</tRtrace>
-        <sRSysVw>1</sRSysVw>
-        <tRSysVw>1</tRSysVw>
-        <sRunDeb>0</sRunDeb>
-        <sLrtime>0</sLrtime>
-        <bEvRecOn>1</bEvRecOn>
-        <bSchkAxf>0</bSchkAxf>
-        <bTchkAxf>0</bTchkAxf>
-        <nTsel>4</nTsel>
-        <sDll></sDll>
-        <sDllPa></sDllPa>
-        <sDlgDll></sDlgDll>
-        <sDlgPa></sDlgPa>
-        <sIfile></sIfile>
-        <tDll></tDll>
-        <tDllPa></tDllPa>
-        <tDlgDll></tDlgDll>
-        <tDlgPa></tDlgPa>
-        <tIfile></tIfile>
-        <pMon>Segger\JL2CM3.dll</pMon>
-      </DebugOpt>
-      <TargetDriverDllRegistry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>DLGUARM</Key>
-          <Name>/</Name>
-        </SetRegEntry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>JL2CM3</Key>
-          <Name>-U4294967295 -O111 -S2 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN0</Name>
-        </SetRegEntry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>ARMRTXEVENTFLAGS</Key>
-          <Name>-L70 -Z18 -C0 -M0 -T1</Name>
-        </SetRegEntry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>DLGTARM</Key>
-          <Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)</Name>
-        </SetRegEntry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>ARMDBGFLAGS</Key>
-          <Name></Name>
-        </SetRegEntry>
-        <SetRegEntry>
-          <Number>0</Number>
-          <Key>UL2CM3</Key>
-          <Name>UL2CM3(-S0 -C0 -P0  -FC1000 -FD20000000</Name>
-        </SetRegEntry>
-      </TargetDriverDllRegistry>
-      <Breakpoint/>
-      <WatchWindow1>
-        <Ww>
-          <count>0</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>times</ItemText>
-        </Ww>
-        <Ww>
-          <count>1</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>CORE_UARTB_CTRL</ItemText>
-        </Ww>
-        <Ww>
-          <count>2</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>USART_InitStruct</ItemText>
-        </Ww>
-        <Ww>
-          <count>3</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>UartAdr</ItemText>
-        </Ww>
-        <Ww>
-          <count>4</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>WPtr</ItemText>
-        </Ww>
-        <Ww>
-          <count>5</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>regBeck</ItemText>
-        </Ww>
-        <Ww>
-          <count>6</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>I2cRxPtr</ItemText>
-        </Ww>
-        <Ww>
-          <count>7</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>I2cTxPtr</ItemText>
-        </Ww>
-        <Ww>
-          <count>8</count>
-          <WinNumber>1</WinNumber>
-          <ItemText>I2cAdr</ItemText>
-        </Ww>
-      </WatchWindow1>
-      <MemoryWindow1>
-        <Mm>
-          <WinNumber>1</WinNumber>
-          <SubType>0</SubType>
-          <ItemText>0xe000e100</ItemText>
-          <AccSizeX>0</AccSizeX>
-        </Mm>
-      </MemoryWindow1>
-      <MemoryWindow2>
-        <Mm>
-          <WinNumber>2</WinNumber>
-          <SubType>0</SubType>
-          <ItemText>0x100080aa</ItemText>
-          <AccSizeX>0</AccSizeX>
-        </Mm>
-      </MemoryWindow2>
-      <Tracepoint>
-        <THDelay>0</THDelay>
-      </Tracepoint>
-      <DebugFlag>
-        <trace>0</trace>
-        <periodic>1</periodic>
-        <aLwin>0</aLwin>
-        <aCover>0</aCover>
-        <aSer1>0</aSer1>
-        <aSer2>0</aSer2>
-        <aPa>0</aPa>
-        <viewmode>1</viewmode>
-        <vrSel>0</vrSel>
-        <aSym>0</aSym>
-        <aTbox>0</aTbox>
-        <AscS1>0</AscS1>
-        <AscS2>0</AscS2>
-        <AscS3>0</AscS3>
-        <aSer3>0</aSer3>
-        <eProf>0</eProf>
-        <aLa>0</aLa>
-        <aPa1>0</aPa1>
-        <AscS4>0</AscS4>
-        <aSer4>0</aSer4>
-        <StkLoc>0</StkLoc>
-        <TrcWin>0</TrcWin>
-        <newCpu>0</newCpu>
-        <uProt>0</uProt>
-      </DebugFlag>
-      <LintExecutable></LintExecutable>
-      <LintConfigFile></LintConfigFile>
-      <bLintAuto>0</bLintAuto>
-      <bAutoGenD>0</bAutoGenD>
-      <LntExFlags>0</LntExFlags>
-      <pMisraName></pMisraName>
-      <pszMrule></pszMrule>
-      <pSingCmds></pSingCmds>
-      <pMultCmds></pMultCmds>
-      <pMisraNamep></pMisraNamep>
-      <pszMrulep></pszMrulep>
-      <pSingCmdsp></pSingCmdsp>
-      <pMultCmdsp></pMultCmdsp>
-      <DebugDescription>
-        <Enable>1</Enable>
-        <EnableFlashSeq>0</EnableFlashSeq>
-        <EnableLog>0</EnableLog>
-        <Protocol>1</Protocol>
-        <DbgClock>10000000</DbgClock>
-      </DebugDescription>
-    </TargetOption>
-  </Target>
-
-  <Group>
-    <GroupName>main</GroupName>
-    <tvExp>1</tvExp>
-    <tvExpOptDlg>0</tvExpOptDlg>
-    <cbSel>0</cbSel>
-    <RteFlg>0</RteFlg>
-    <File>
-      <GroupNumber>1</GroupNumber>
-      <FileNumber>1</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\User\main.c</PathWithFileName>
-      <FilenameWithoutPath>main.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>1</GroupNumber>
-      <FileNumber>2</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\User\Drv_bt.c</PathWithFileName>
-      <FilenameWithoutPath>Drv_bt.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-  </Group>
-
-  <Group>
-    <GroupName>startup</GroupName>
-    <tvExp>1</tvExp>
-    <tvExpOptDlg>0</tvExpOptDlg>
-    <cbSel>0</cbSel>
-    <RteFlg>0</RteFlg>
-    <File>
-      <GroupNumber>2</GroupNumber>
-      <FileNumber>3</FileNumber>
-      <FileType>2</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\startup\startup.s</PathWithFileName>
-      <FilenameWithoutPath>startup.s</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-  </Group>
-
-  <Group>
-    <GroupName>driver</GroupName>
-    <tvExp>1</tvExp>
-    <tvExpOptDlg>0</tvExpOptDlg>
-    <cbSel>0</cbSel>
-    <RteFlg>0</RteFlg>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>4</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\device\yc11xx.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>5</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\User\hci\yc11xx_h4.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_h4.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>6</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\uart\yc11xx_uart.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_uart.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>7</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\bt\yc11xx_bt.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_bt.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>8</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\debug\yc_debug.c</PathWithFileName>
-      <FilenameWithoutPath>yc_debug.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>9</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\hal\yc_drv_common.c</PathWithFileName>
-      <FilenameWithoutPath>yc_drv_common.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>10</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\gpio\yc11xx_gpio.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_gpio.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>11</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\queue\yc_queue.c</PathWithFileName>
-      <FilenameWithoutPath>yc_queue.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>12</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\systick\yc11xx_systick.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_systick.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>13</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\timer\yc11xx_timer.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_timer.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>14</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\timer\yc_timer.c</PathWithFileName>
-      <FilenameWithoutPath>yc_timer.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-    <File>
-      <GroupNumber>3</GroupNumber>
-      <FileNumber>15</FileNumber>
-      <FileType>1</FileType>
-      <tvExp>0</tvExp>
-      <tvExpOptDlg>0</tvExpOptDlg>
-      <bDave2>0</bDave2>
-      <PathWithFileName>..\..\..\..\..\..\Librarier\drivers\wdt\yc11xx_wdt.c</PathWithFileName>
-      <FilenameWithoutPath>yc11xx_wdt.c</FilenameWithoutPath>
-      <RteFlg>0</RteFlg>
-      <bShared>0</bShared>
-    </File>
-  </Group>
-
-</ProjectOpt>
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvprojx
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvprojx	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK/yc11xx.uvprojx	(nonexistent)
@@ -1,501 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
-<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
-
-  <SchemaVersion>2.1</SchemaVersion>
-
-  <Header>### uVision Project, (C) Keil Software</Header>
-
-  <Targets>
-    <Target>
-      <TargetName>Target 1</TargetName>
-      <ToolsetNumber>0x4</ToolsetNumber>
-      <ToolsetName>ARM-ADS</ToolsetName>
-      <pCCUsed>5060750::V5.06 update 6 (build 750)::ARMCC</pCCUsed>
-      <uAC6>0</uAC6>
-      <TargetOption>
-        <TargetCommonOption>
-          <Device>ARMCM0</Device>
-          <Vendor>ARM</Vendor>
-          <PackID>ARM.CMSIS.5.5.1</PackID>
-          <PackURL>http://www.keil.com/pack/</PackURL>
-          <Cpu>IROM(0x00000000,0x00040000) IRAM(0x20000000,0x00020000) CPUTYPE("Cortex-M0") CLOCK(12000000) ESEL ELITTLE</Cpu>
-          <FlashUtilSpec></FlashUtilSpec>
-          <StartupFile></StartupFile>
-          <FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000)</FlashDriverDll>
-          <DeviceId>0</DeviceId>
-          <RegisterFile>$$Device:ARMCM0$Device/ARM/ARMCM0/Include/ARMCM0.h</RegisterFile>
-          <MemoryEnv></MemoryEnv>
-          <Cmp></Cmp>
-          <Asm></Asm>
-          <Linker></Linker>
-          <OHString></OHString>
-          <InfinionOptionDll></InfinionOptionDll>
-          <SLE66CMisc></SLE66CMisc>
-          <SLE66AMisc></SLE66AMisc>
-          <SLE66LinkerMisc></SLE66LinkerMisc>
-          <SFDFile></SFDFile>
-          <bCustSvd>0</bCustSvd>
-          <UseEnv>0</UseEnv>
-          <BinPath></BinPath>
-          <IncludePath></IncludePath>
-          <LibPath></LibPath>
-          <RegisterFilePath></RegisterFilePath>
-          <DBRegisterFilePath></DBRegisterFilePath>
-          <TargetStatus>
-            <Error>0</Error>
-            <ExitCodeStop>0</ExitCodeStop>
-            <ButtonStop>0</ButtonStop>
-            <NotGenerated>0</NotGenerated>
-            <InvalidFlash>1</InvalidFlash>
-          </TargetStatus>
-          <OutputDirectory>.\Objects\</OutputDirectory>
-          <OutputName>yc11xx</OutputName>
-          <CreateExecutable>1</CreateExecutable>
-          <CreateLib>0</CreateLib>
-          <CreateHexFile>1</CreateHexFile>
-          <DebugInformation>1</DebugInformation>
-          <BrowseInformation>1</BrowseInformation>
-          <ListingPath>.\Listings\</ListingPath>
-          <HexFormatSelection>1</HexFormatSelection>
-          <Merge32K>0</Merge32K>
-          <CreateBatchFile>0</CreateBatchFile>
-          <BeforeCompile>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-            <nStopU1X>0</nStopU1X>
-            <nStopU2X>0</nStopU2X>
-          </BeforeCompile>
-          <BeforeMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-            <nStopB1X>0</nStopB1X>
-            <nStopB2X>0</nStopB2X>
-          </BeforeMake>
-          <AfterMake>
-            <RunUserProg1>1</RunUserProg1>
-            <RunUserProg2>1</RunUserProg2>
-            <UserProg1Name>fromelf.exe --text -a -c --output=@L_asm.txt "!L"</UserProg1Name>
-            <UserProg2Name>"Objects/tool/c.bat"</UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-            <nStopA1X>0</nStopA1X>
-            <nStopA2X>0</nStopA2X>
-          </AfterMake>
-          <SelectedForBatchBuild>0</SelectedForBatchBuild>
-          <SVCSIdString></SVCSIdString>
-        </TargetCommonOption>
-        <CommonProperty>
-          <UseCPPCompiler>0</UseCPPCompiler>
-          <RVCTCodeConst>0</RVCTCodeConst>
-          <RVCTZI>0</RVCTZI>
-          <RVCTOtherData>0</RVCTOtherData>
-          <ModuleSelection>0</ModuleSelection>
-          <IncludeInBuild>1</IncludeInBuild>
-          <AlwaysBuild>0</AlwaysBuild>
-          <GenerateAssemblyFile>0</GenerateAssemblyFile>
-          <AssembleAssemblyFile>0</AssembleAssemblyFile>
-          <PublicsOnly>0</PublicsOnly>
-          <StopOnExitCode>3</StopOnExitCode>
-          <CustomArgument></CustomArgument>
-          <IncludeLibraryModules></IncludeLibraryModules>
-          <ComprImg>1</ComprImg>
-        </CommonProperty>
-        <DllOption>
-          <SimDllName>SARMCM3.DLL</SimDllName>
-          <SimDllArguments> </SimDllArguments>
-          <SimDlgDll>DARMCM1.DLL</SimDlgDll>
-          <SimDlgDllArguments>-pCM0</SimDlgDllArguments>
-          <TargetDllName>SARMCM3.DLL</TargetDllName>
-          <TargetDllArguments> </TargetDllArguments>
-          <TargetDlgDll>TARMCM1.DLL</TargetDlgDll>
-          <TargetDlgDllArguments>-pCM0</TargetDlgDllArguments>
-        </DllOption>
-        <DebugOption>
-          <OPTHX>
-            <HexSelection>1</HexSelection>
-            <HexRangeLowAddress>0</HexRangeLowAddress>
-            <HexRangeHighAddress>0</HexRangeHighAddress>
-            <HexOffset>0</HexOffset>
-            <Oh166RecLen>16</Oh166RecLen>
-          </OPTHX>
-        </DebugOption>
-        <Utilities>
-          <Flash1>
-            <UseTargetDll>0</UseTargetDll>
-            <UseExternalTool>1</UseExternalTool>
-            <RunIndependent>1</RunIndependent>
-            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
-            <Capability>1</Capability>
-            <DriverSelection>4096</DriverSelection>
-          </Flash1>
-          <bUseTDR>1</bUseTDR>
-          <Flash2>BIN\UL2CM3.DLL</Flash2>
-          <Flash3>"Objects\tool\d.bat" ()</Flash3>
-          <Flash4></Flash4>
-          <pFcarmOut></pFcarmOut>
-          <pFcarmGrp></pFcarmGrp>
-          <pFcArmRoot></pFcArmRoot>
-          <FcArmLst>0</FcArmLst>
-        </Utilities>
-        <TargetArmAds>
-          <ArmAdsMisc>
-            <GenerateListings>0</GenerateListings>
-            <asHll>1</asHll>
-            <asAsm>1</asAsm>
-            <asMacX>1</asMacX>
-            <asSyms>1</asSyms>
-            <asFals>1</asFals>
-            <asDbgD>1</asDbgD>
-            <asForm>1</asForm>
-            <ldLst>0</ldLst>
-            <ldmm>1</ldmm>
-            <ldXref>1</ldXref>
-            <BigEnd>0</BigEnd>
-            <AdsALst>1</AdsALst>
-            <AdsACrf>1</AdsACrf>
-            <AdsANop>0</AdsANop>
-            <AdsANot>0</AdsANot>
-            <AdsLLst>1</AdsLLst>
-            <AdsLmap>1</AdsLmap>
-            <AdsLcgr>1</AdsLcgr>
-            <AdsLsym>1</AdsLsym>
-            <AdsLszi>1</AdsLszi>
-            <AdsLtoi>1</AdsLtoi>
-            <AdsLsun>1</AdsLsun>
-            <AdsLven>1</AdsLven>
-            <AdsLsxf>1</AdsLsxf>
-            <RvctClst>0</RvctClst>
-            <GenPPlst>0</GenPPlst>
-            <AdsCpuType>"Cortex-M0"</AdsCpuType>
-            <RvctDeviceName></RvctDeviceName>
-            <mOS>0</mOS>
-            <uocRom>0</uocRom>
-            <uocRam>0</uocRam>
-            <hadIROM>1</hadIROM>
-            <hadIRAM>1</hadIRAM>
-            <hadXRAM>0</hadXRAM>
-            <uocXRam>0</uocXRam>
-            <RvdsVP>0</RvdsVP>
-            <RvdsMve>0</RvdsMve>
-            <hadIRAM2>0</hadIRAM2>
-            <hadIROM2>0</hadIROM2>
-            <StupSel>8</StupSel>
-            <useUlib>1</useUlib>
-            <EndSel>1</EndSel>
-            <uLtcg>0</uLtcg>
-            <nSecure>0</nSecure>
-            <RoSelD>3</RoSelD>
-            <RwSelD>3</RwSelD>
-            <CodeSel>0</CodeSel>
-            <OptFeed>0</OptFeed>
-            <NoZi1>0</NoZi1>
-            <NoZi2>0</NoZi2>
-            <NoZi3>0</NoZi3>
-            <NoZi4>0</NoZi4>
-            <NoZi5>0</NoZi5>
-            <Ro1Chk>0</Ro1Chk>
-            <Ro2Chk>0</Ro2Chk>
-            <Ro3Chk>0</Ro3Chk>
-            <Ir1Chk>1</Ir1Chk>
-            <Ir2Chk>0</Ir2Chk>
-            <Ra1Chk>0</Ra1Chk>
-            <Ra2Chk>0</Ra2Chk>
-            <Ra3Chk>0</Ra3Chk>
-            <Im1Chk>1</Im1Chk>
-            <Im2Chk>0</Im2Chk>
-            <OnChipMemories>
-              <Ocm1>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm1>
-              <Ocm2>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm2>
-              <Ocm3>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm3>
-              <Ocm4>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm4>
-              <Ocm5>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm5>
-              <Ocm6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm6>
-              <IRAM>
-                <Type>0</Type>
-                <StartAddress>0x20000000</StartAddress>
-                <Size>0x20000</Size>
-              </IRAM>
-              <IROM>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x40000</Size>
-              </IROM>
-              <XRAM>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </XRAM>
-              <OCR_RVCT1>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT1>
-              <OCR_RVCT2>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT2>
-              <OCR_RVCT3>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT3>
-              <OCR_RVCT4>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x40000</Size>
-              </OCR_RVCT4>
-              <OCR_RVCT5>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT5>
-              <OCR_RVCT6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT6>
-              <OCR_RVCT7>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT7>
-              <OCR_RVCT8>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT8>
-              <OCR_RVCT9>
-                <Type>0</Type>
-                <StartAddress>0x20000000</StartAddress>
-                <Size>0x20000</Size>
-              </OCR_RVCT9>
-              <OCR_RVCT10>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT10>
-            </OnChipMemories>
-            <RvctStartVector></RvctStartVector>
-          </ArmAdsMisc>
-          <Cads>
-            <interw>1</interw>
-            <Optim>1</Optim>
-            <oTime>0</oTime>
-            <SplitLS>0</SplitLS>
-            <OneElfS>0</OneElfS>
-            <Strict>0</Strict>
-            <EnumInt>0</EnumInt>
-            <PlainCh>0</PlainCh>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <wLevel>2</wLevel>
-            <uThumb>0</uThumb>
-            <uSurpInc>0</uSurpInc>
-            <uC99>0</uC99>
-            <uGnu>0</uGnu>
-            <useXO>0</useXO>
-            <v6Lang>1</v6Lang>
-            <v6LangP>1</v6LangP>
-            <vShortEn>1</vShortEn>
-            <vShortWch>1</vShortWch>
-            <v6Lto>0</v6Lto>
-            <v6WtE>0</v6WtE>
-            <v6Rtti>0</v6Rtti>
-            <VariousControls>
-              <MiscControls>--c99 --gnu</MiscControls>
-              <Define></Define>
-              <Undefine></Undefine>
-              <IncludePath>..\..\..\..\..\..\Librarier\device;..\..\User\hci;..\..\..\..\..\..\Librarier\drivers\uart;..\..\..\..\..\..\Librarier\drivers\gpio;..\..\..\..\..\..\Librarier\drivers\debug;..\..\..\..\..\..\Librarier\drivers\bt;..\..\..\..\..\..\Librarier\drivers\timer;..\..\..\..\..\..\Librarier\drivers\systick;..\..\..\..\..\..\Librarier\drivers\hal;..\..\..\..\..\..\Librarier\drivers\wdt;..\..\User</IncludePath>
-            </VariousControls>
-          </Cads>
-          <Aads>
-            <interw>1</interw>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <thumb>0</thumb>
-            <SplitLS>0</SplitLS>
-            <SwStkChk>0</SwStkChk>
-            <NoWarn>0</NoWarn>
-            <uSurpInc>0</uSurpInc>
-            <useXO>0</useXO>
-            <uClangAs>0</uClangAs>
-            <VariousControls>
-              <MiscControls></MiscControls>
-              <Define></Define>
-              <Undefine></Undefine>
-              <IncludePath></IncludePath>
-            </VariousControls>
-          </Aads>
-          <LDads>
-            <umfTarg>0</umfTarg>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <noStLib>0</noStLib>
-            <RepFail>1</RepFail>
-            <useFile>0</useFile>
-            <TextAddressRange>0x00000000</TextAddressRange>
-            <DataAddressRange>0x100010000</DataAddressRange>
-            <pXoBase></pXoBase>
-            <ScatterFile>.\Objects\yc11xx.sct</ScatterFile>
-            <IncludeLibs></IncludeLibs>
-            <IncludeLibsPath></IncludeLibsPath>
-            <Misc></Misc>
-            <LinkerInputFile></LinkerInputFile>
-            <DisabledWarnings></DisabledWarnings>
-          </LDads>
-        </TargetArmAds>
-      </TargetOption>
-      <Groups>
-        <Group>
-          <GroupName>main</GroupName>
-          <Files>
-            <File>
-              <FileName>main.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\User\main.c</FilePath>
-            </File>
-            <File>
-              <FileName>Drv_bt.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\User\Drv_bt.c</FilePath>
-            </File>
-          </Files>
-        </Group>
-        <Group>
-          <GroupName>startup</GroupName>
-          <Files>
-            <File>
-              <FileName>startup.s</FileName>
-              <FileType>2</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\startup\startup.s</FilePath>
-            </File>
-          </Files>
-        </Group>
-        <Group>
-          <GroupName>driver</GroupName>
-          <Files>
-            <File>
-              <FileName>yc11xx.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\device\yc11xx.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_h4.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\User\hci\yc11xx_h4.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_uart.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\uart\yc11xx_uart.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_bt.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\bt\yc11xx_bt.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc_debug.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\debug\yc_debug.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc_drv_common.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\hal\yc_drv_common.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_gpio.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\gpio\yc11xx_gpio.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc_queue.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\queue\yc_queue.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_systick.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\systick\yc11xx_systick.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_timer.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\timer\yc11xx_timer.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc_timer.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\timer\yc_timer.c</FilePath>
-            </File>
-            <File>
-              <FileName>yc11xx_wdt.c</FileName>
-              <FileType>1</FileType>
-              <FilePath>..\..\..\..\..\..\Librarier\drivers\wdt\yc11xx_wdt.c</FilePath>
-            </File>
-          </Files>
-        </Group>
-      </Groups>
-    </Target>
-  </Targets>
-
-  <RTE>
-    <apis/>
-    <components/>
-    <files>
-      <file attr="config" category="header" name="CMSIS\Config\RTE_Device.h" version="1.0.0">
-        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\RTE_Device.h</instance>
-        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
-        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
-        <targetInfos/>
-      </file>
-      <file attr="config" category="source" condition="ARMCC" name="Device\CMSDK_CM0\Source\ARM\startup_CMSDK_CM0.s" version="1.0.0">
-        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\startup_CMSDK_CM0.s</instance>
-        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
-        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
-        <targetInfos/>
-      </file>
-      <file attr="config" category="source" name="Device\CMSDK_CM0\Source\system_CMSDK_CM0.c" version="1.0.0">
-        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\system_CMSDK_CM0.c</instance>
-        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
-        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
-        <targetInfos/>
-      </file>
-    </files>
-  </RTE>
-
-</Project>
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj/MDK
___________________________________________________________________
Deleted: svn:ignore
## -1,5 +0,0 ##
-yc11xx.uvguix.bob.wen
-yc11xx_Target 1.dep
-yc11xx_asm.txt
-yc11xx_uvoptx.bak
-yc11xx_uvprojx.bak
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj/Output
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/Output	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj/Output	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj/Output
___________________________________________________________________
Deleted: svn:ignore
## -1 +0,0 ##
-out.rom
Index: ModuleDemo/25_OTA/bt_demo/CM0/Prj
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/Prj	(nonexistent)

Property changes on: ModuleDemo/25_OTA/bt_demo/CM0/Prj
___________________________________________________________________
Deleted: svn:ignore
## -1 +0,0 ##
-Output
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.h	(nonexistent)
@@ -1,85 +0,0 @@
-#ifndef  _DRV_BT_H_
-#define _DRV_BT_H_
-
-#include <stdio.h>
-#include "ipc.h"
-#include "yc11xx.h"
-#include "yc_debug.h"
-#include "yc11xx_timer.h"
-#include "yc_timer.h"
-
-#define DEVICE_INFO_BASE 	0x07f000 // mem_ef_base
-
-#define REVERSE_3BYTE_DEFINE(a) ((a>>16)+(a&0xff00)+((a&0xff)<<16))  
-//#define REVERSE_2BYTE_DEFINE(a,b)
-
-#define M0_SCO_BUF_START_ADDR    (reg_map(HREADADDR3(mem_param_m0_respin_sco_buffer_start_addr)))
-
-
-#define CODE_START_FLASHADDR1 0x1003
-#define CODE_START_FLASHADDR2 0X18003
-#define CODE_MAX_LENGTH 0x17000
-
-typedef struct
-{
-	uint8_t topState;
-		
-	SYS_TIMER_TYPE autoPowerTimer;
-}BR_STATE;
-
-typedef enum
-{
-	BR_POWER_OFF=0,
-	BR_WAIT_POWER_OFF,
-	BR_CHARGER_IN,
-	BR_WAIT_POWER_ON,
-	BR_POWER_ON,
-}BR_STATE_TOP_TYPE;
-
-
-extern BR_STATE gBRState;
-
-
-
-#define HCI_QUEUE_MAX (5)
-#define HCI_DATA_BUFFER_SIZE (800)
-
-typedef struct{
-        uint16_t len;
-	uint8_t data[HCI_DATA_BUFFER_SIZE];
-}__attribute__((packed)) BT_HCI_DATA;
-typedef struct{
-	uint8_t rptr;
-	uint8_t wptr;
-	uint8_t cnt;
-	BT_HCI_DATA queue[HCI_QUEUE_MAX];
-}__attribute__((packed)) BT_HCI_DATA_FIFO;
-
-void Bt_EvtCallBack(uint8_t len,uint8_t *dataPtr);
-void Bt_HciFifoInit(void);
-BT_HCI_DATA *Bt_HciGetSendBufferPtr(void);
-void Bt_HciFifoIn(void);
-
-void Bt_HciFifoOut(void);
-uint8_t Bt_HciCheckBufferFull(void);
-void Bt_SndToBtData(uint8_t subType, uint32_t payloadPtr);
-void Bt_HciCallback(uint8_t *dataPtr);
-void Bt_DataBufferCallBack(uint8_t len,uint8_t *dataPtr);
-void Bt_PowerResetWork(void);
-void Bt_Init(void);
-void Bt_Reset(void);
-void Bt_PowerOn(bool isPowerOnFromKeyPress);
-void Bt_PowerOnBtWork(void);
-uint8_t Bt_CheckPowerOn(void);
-void Bt_StartWork(void);
-void Bt_ActionBeforeHibernate(void);
-void Bt_ActionBeforeLpm(void);
-void Bt_SndCmdPwroff(void);
-void Bt_SndHciToRespin(uint8_t *data, uint16_t len);
-void Bt_ACLCallbackBle(uint8_t *dataPtr,uint16_t conn_handle);
-void Bt_ACLCallbackClassic(uint8_t *dataPtr,uint16_t conn_handle);
-
-// extern function defined
-extern void SCO_NVIC_Config(void);
-extern void SCO_NVIC_DeConfig(void);
-#endif //_DRV_IPC_H_
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.c	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/Drv_bt.c	(nonexistent)
@@ -1,392 +0,0 @@
-#include <stdio.h>
-#include "Drv_bt.h"
-#include "yc11xx_h4.h"
-
-BR_STATE gBRState;
-BT_HCI_DATA_FIFO gHciDataFifo;
-
-void Bt_EvtCallBack(uint8_t len,uint8_t *dataPtr)
-{
-    if (*dataPtr >BT_EVT_100MS_UINT)
-    {
-        Bt_100ms_timer((*dataPtr)&(0x0F));
-        return;
-    }
-    DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_EvtCallBack: 0x%04X", LOG_POINT_9001, *dataPtr);
-
-    switch(*dataPtr)
-    {
-        case BT_EVT_WAKEUP:
-            SYS_TimerStartTickTimer(CLOCK_48M_multiple);
-            break;
-        case BT_EVT_RESET:
-            Bt_Reset();
-            Bt_PowerOn(true);
-            Bt_PowerOnBtWork();
-            break;
-        case BT_EVT_RESTART:
-            Bt_PowerResetWork();
-            break;
-
-        default:
-            break;
-    }
-
-    return;
-}
-
-
-
-
-void Bt_HciFifoInit(void)
-{
-    memset((void *)&gHciDataFifo, 0, sizeof(BT_HCI_DATA_FIFO));
-}
-BT_HCI_DATA *Bt_HciGetSendBufferPtr(void)
-{
-    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
-    return &(pFifo->queue[pFifo->wptr]);
-}
-
-void Bt_HciFifoIn(void)
-{
-    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
-    if(pFifo->cnt >= HCI_QUEUE_MAX)
-    {
-        return;
-    }
-
-    pFifo->cnt++;
-    pFifo->wptr += 1;
-    //if(prxDataFifo->wptr == M0_SCO_RX_BUFFER_SIZE)
-    if(pFifo->wptr == HCI_QUEUE_MAX)
-    {
-    	pFifo->wptr = 0;
-    }
-}
-
-void Bt_HciFifoOut(void)
-{
-    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
-    if(pFifo->cnt == 0)
-    {
-        return;
-    }
-
-    pFifo->cnt--;
-    pFifo->rptr += 1;
-    //if(prxDataFifo->wptr == M0_SCO_RX_BUFFER_SIZE)
-    if(pFifo->rptr == HCI_QUEUE_MAX)
-    {
-    	pFifo->rptr = 0;
-    }
-}
-uint8_t Bt_HciCheckBufferFull(void)
-{
-    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
-    if(pFifo->cnt >= HCI_QUEUE_MAX)
-    {
-        return 1;
-    }
-    return 0;
-}
-void Bt_HciParseEvt(uint8_t evtCode, uint16_t len, uint8_t *dataPtr)
-{
-    uint16_t opcode = 0;
-    uint8_t numPacket = 0;
-    DEBUG_LOG_2(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E000, evtCode, len);
-    if(evtCode == BT_HCI_EVT_CMD_COMPLETE)
-    {
-        numPacket = (*(dataPtr + 0) << 0);
-        opcode = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
-        DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E001, opcode);
-        DEBUG_LOG_2(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E002, (*(dataPtr + 3)), (*(dataPtr + 4)));
-    }
-    
-}
-void Bt_HciParseCmd(uint16_t opcode, uint8_t len, uint8_t *dataPtr)
-{
-    DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E100, opcode);
-    
-}
-
-void Bt_SndToBtData(uint8_t subType, uint32_t payloadPtr)
-{
-    DEBUG_LOG_STRING("Bt_SndToBtData subType=%d, payloadPtr=0x%x\r\n",subType, payloadPtr);
-    uint8_t data[4];
-    data[0] = subType;
-    data[1] = payloadPtr;
-    data[2] = payloadPtr >> 8;
-    data[3] = payloadPtr >> 16;
-    IPC_TxCommon(IPC_TYPE_CM0_TO_BT_DATA, data, sizeof(data));
-}
-void Bt_HciCallback(uint8_t *dataPtr)
-{
-    uint8_t type = *(dataPtr);
-    uint16_t len = 0;
-    uint16_t handle = 0;
-    uint16_t totalLength = 0;
-    uint8_t evtCode = 0;
-    //Avoid host use respin buffer
-    uint8_t evtBuffer[500];
-    switch(type)
-    {
-        case H4_EVT:
-            evtCode = *(dataPtr + 1);
-            len = *(dataPtr + 2);
-            totalLength = len+3;// 04 + evtCode(1) + length(1)
-            
-            //Avoid host use respin buffer
-            xmemcpy(evtBuffer,dataPtr,totalLength);
-            dataPtr = evtBuffer;
-
-            Bt_HciParseEvt(evtCode, len, dataPtr + 3);
-
-            
-            break;
-        case H4_ACL:
-            handle = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
-            len = (*(dataPtr + 3) << 0) |(*(dataPtr + 4) << 8);
-            totalLength = len+5;// 02 + handle(2) + length(2)
-            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E010, handle);
-            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E011, len);
-            break;
-        default:
-            _ASSERT_FAULT();
-            break;
-    }
-
-
-    h4_send_data(dataPtr, totalLength);
-}
-void Bt_DataBufferCallBack(uint8_t len,uint8_t *dataPtr)
-{
-    uint32_t payloadPtr;
-    uint8_t subType;
-	uint16_t conn_handle;
-    //uint16_t lenPayload;
-    subType = dataPtr[0];
-    payloadPtr = reg_map(dataPtr[1] +(dataPtr[2]<<8)+(dataPtr[3]<<16));
-    DEBUG_LOG_STRING("Bt_DataBufferCallBack len: %d, subType=0x%x, payloadPtr=0x%x\r\n", len, subType, payloadPtr);
-    //	MyPrintf("handle=%x\r\n",handle);
-    switch(subType) 
-    {
-        case IPC_DATA_SUBTYPE_HCI:
-            // TODO: Need change to m0 ram.
-            Bt_HciCallback((uint8_t *)payloadPtr);
-            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
-            break;
-        case IPC_DATA_SUBTYPE_FREE:
-            /************************release tx buffer *****************************/
-            Bt_HciFifoOut();
-            break;
-        case IPC_DATA_SUBTYPE_ACL_BLE:
-            conn_handle = dataPtr[4]+(dataPtr[5]<<8);
-            Bt_ACLCallbackBle((uint8_t *)payloadPtr,conn_handle);
-            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
-            break;
-        case IPC_DATA_SUBTYPE_ACL_CLASSIC:
-            conn_handle = dataPtr[4]+(dataPtr[5]<<8);
-            Bt_ACLCallbackClassic((uint8_t *)payloadPtr,conn_handle);
-            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
-            break;
-    }
-}
-
-
-
-void Bt_PowerResetWork(void)
-{
-	Bt_Reset();
-	//WDT_Kick();
-	SYS_delay_ms(500);
-	//WDT_Kick();
-	SYS_delay_ms(500);
-	//WDT_Kick();
-	SYS_delay_ms(100);
-	Bt_PowerOn(false);
-	//Bat_StateSwitchPooling();
-	if(gBRState.topState != BR_CHARGER_IN)
-	{
-		Bt_PowerOnBtWork();
-	}
-}
-
-void Bt_Init(void)
-{
-	DEBUG_LOG(LOG_LEVEL_CORE, "UI" ,"Bt_Reset: 0x%04X", LOG_POINT_A200, gBRState.topState);
-	gBRState.topState = BR_WAIT_POWER_ON;
-
-}
-
-//extern void KeyPad_Event_Handle(KEY_INDEX index,KEYPAD_EVT_TYPE key_evt);
-void Bt_Reset(void)
-{
-	DEBUG_LOG(LOG_LEVEL_CORE, "UI" ,"Bt_Reset: 0x%04X", LOG_POINT_A201, gBRState.topState);
-	Bt_Init();	
-	//SYS_TimerInit(CLOCK_48M_multiple);
-	//keypad_init(KeyPad_Event_Handle);
-	//QSPI_ReadFlashData(OTA_LED_FLASH_ADDR,1,&gLedCfg.red_gpio);
-	//Read_Ledgpionum();
-	//VP_Init();
-	//Led_Init();
-	//Bat_InitDev();
-}
-
-void Bt_PowerOn(bool isPowerOnFromKeyPress)
-{
-	gBRState.topState = BR_POWER_ON;
-
-}
-
-
-void Bt_PowerOnBtWork(void)
-{
-}
-
-
-uint8_t Bt_CheckPowerOn(void)
-{
-	return (gBRState.topState >= BR_POWER_ON);
-}
-
-void Bt_StartWork(void)
-{
-
-	DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_startWork: 0x%04X", LOG_POINT_9011, gBRState.topState);
-
-	
-}
-
-
-void Bt_ActionBeforeHibernate()
-{
-	//gpio leakage of electricity
-	//Bat_ClcGpio();
-	uint8_t i;
-	
-	for(i=GPIO_0;i<GPIO_MAX_NUM;i++)
-	{
-		GPIO_ClearWakeup((GPIO_NUM)i);
-		if(
-		 i == (HREAD(mem_qspi_gpio_ncs)&GPIO_NUM_MASK)
-			|| i == (HREAD(mem_qspi_gpio_sck)&GPIO_NUM_MASK)
-			|| i == (HREAD(mem_qspi_gpio_io0)&GPIO_NUM_MASK)
-			|| i == (HREAD(mem_qspi_gpio_io1)&GPIO_NUM_MASK)
-			|| i == (HREAD(mem_qspi_gpio_io2)&GPIO_NUM_MASK)
-			|| i == (HREAD(mem_qspi_gpio_io3)&GPIO_NUM_MASK)	
-			|| i ==GPIO_31)
-			continue ;
-		else
-		{
-			
-			GPIO_SetGpioMultFunction((GPIO_NUM)i,GPCFG_PULLDOWN);
-		}
-	}	
-}
-void Bt_ActionBeforeLpm()
-{
-	//gpio leakage of electricity
-	//Bat_ClcGpio();
-	Bt_ActionBeforeHibernate();
-}
-
-void Bt_SndCmdPwroff(void)
-{
-	//disable interrupt,will disable keyscan
-	OS_ENTER_CRITICAL();
-	gBRState.topState = BR_POWER_OFF;
-	IPC_TxControlCmd(BT_CMD_ENTER_HIBERNATE);
-	
-	while(1){
-	 	uint8_t temp = HREAD(IPC_MCU_STATE);
-		if (temp == IPC_MCU_STATE_HIBERNATE)
-		{	
-			Bt_ActionBeforeHibernate();
-			HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
-			while(1);
-		}
-		else if (temp == IPC_MCU_STATE_LMP){
-			HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_RUNNING);
-		}
-		hw_delay();
-	}
-}
-
-void Bt_HciParseRcvData(uint8_t *dataPtr, uint16_t len)
-{
-    uint8_t type = *(dataPtr);
-    uint16_t handle = 0;
-    uint16_t opcode = 0;
-    switch(type)
-    {
-        case H4_CMD:
-            opcode = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
-            len = *(dataPtr + 3);
-            Bt_HciParseCmd(opcode, len, dataPtr + 4);
-            break;
-        case H4_ACL:
-            handle = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
-            len = (*(dataPtr + 3) << 0) |(*(dataPtr + 4) << 8);
-            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E110, handle);
-            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E111, len);
-            break;
-        default:
-            _ASSERT_FAULT();
-            break;
-    }
-    
-}
-void Bt_SndHciToRespin(uint8_t *data, uint16_t len)
-{
-    BT_HCI_DATA* pHciData = Bt_HciGetSendBufferPtr();
-
-    memcpy((pHciData->data), data, len);
-    pHciData->len = len;
-    Bt_HciParseRcvData(data, len);
-    Bt_SndToBtData(IPC_DATA_SUBTYPE_HCI, (uint32_t)pHciData->data);
-    //DEBUG_LOG_STRING("Bt_SndHciToRespin len=%d, payload=0x%x\r\n",len, (uint32_t)pHciData->data);
-    if(!len)
-    {
-        //while(1);
-        return;
-    }
-    Bt_HciFifoIn();
-}
-
-void Bt_ACLCallbackBle(uint8_t *dataPtr,uint16_t conn_handle)
-{
-	uint8_t packet[300];
-	uint16_t handle = 0;
-	uint16_t len=0;
-	uint16_t totalLength = 0;
-	handle = (((*(dataPtr))& 0x03)<<12)|conn_handle; 
-	len = (*(dataPtr+1));
-	packet[0] = H4_ACL;
-	packet[1] = handle& 0xff;
-	packet[2] = (handle>>8)& 0xff;
-	packet[3] = len & 0xff;
-	packet[4] = (len>>8)& 0xff;
-	totalLength =len+5;
-	xmemcpy(packet+5,dataPtr+2,len);
-	Bt_HciCallback(packet);
-}
-void Bt_ACLCallbackClassic(uint8_t *dataPtr,uint16_t conn_handle)
-{
-	uint8_t packet[800];
-	uint16_t handle = 0;
-	uint16_t len=0;
-	uint16_t totalLength = 0;
-	handle = (((*(dataPtr))& 0x03)<<12)|conn_handle; 
-	len = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
-	packet[0] = H4_ACL;
-	packet[1] = handle& 0xff;
-	packet[2] = (handle>>8)& 0xff;
-	packet[3] = len & 0xff;
-	packet[4] = (len>>8)& 0xff;
-	totalLength =len+5;
-	xmemcpy(packet+5,dataPtr+3,len);
-	Bt_HciCallback(packet);
-}
-
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/app_config.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/app_config.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/app_config.h	(nonexistent)
@@ -1,18 +0,0 @@
-#ifndef  _APP_CONFIG_H_
-#define _APP_CONFIG_H_
-
-#include <stdio.h>
-#include "type.h"
-#include "btreg.h"
-
-
-/////////////////// Function Control///////////////////
-#define FUNCTION_CONTROL_DEBUG_ENABLE
-//#define FUNCTION_WATCH_DOG
-//#define FUNCTION_FSC_RTK_HOST
-#define FUNCTION_FSC_RTK_HOST_WHITE
-
-/////////////////// DEBUG Setting///////////////////
-#define DEBUG_GPIO_DEFINE GPIO_23
-
-#endif //_APP_CONFIG_H_
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/btreg.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/btreg.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/btreg.h	(nonexistent)
@@ -1,2410 +0,0 @@
-#ifndef _BT_REG_H_
-#define _BT_REG_H_
-#define	mem_le_adv_transmit                     	0x0000
-#define	mem_le_adv_waitcnt                      	0x0001
-#define	mem_sbc_error                           	0x0002
-#define	mem_le_adv_rcv                          	0x0002
-#define	mem_le_req_rcv                          	0x0003
-#define	mem_le_scanrsp_rcv                      	0x0004
-#define	mem_le_conn_rcv                         	0x0005
-#define	mem_inquiryscan_waitcnt                 	0x0006
-#define	mem_inquiryscan_rcvcnt                  	0x0007
-#define	mem_pagescan_waitcnt                    	0x0008
-#define	mem_pagescan_rcvcnt                     	0x0009
-#define	mem_pagescan_rcvfhscnt                  	0x000a
-#define	mem_slave_rcvcnt                        	0x000b
-#define	mem_page_transmit                       	0x000c
-#define	mem_page_rcv                            	0x000d
-#define	mem_page_rcv_fhs                        	0x000e
-#define	mem_master_rcvcnt                       	0x000f
-#define	mem_fhs_wait_counter                    	0x0010
-#define	mem_newconnto_counter                   	0x0011
-#define	mem_inquiry_transmit                    	0x0012
-#define	mem_inquiry_rcv                         	0x0013
-#define	mem_fw_ver                              	0x0014
-#define	mem_current_context                     	0x0015
-#define	mem_empty_block                         	0x0016
-#define	mem_last_freq                           	0x0017
-#define	mem_rssi                                	0x0018
-#define	mem_rx_type                             	0x0019
-#define	mem_rx_hec_err                          	0x001a
-#define	mem_rx_crc_err                          	0x001c
-#define	mem_context_ptr                         	0x001e
-#define	mem_display                             	0x0020
-#define	mem_bcd                                 	0x0028
-#define	mem_state                               	0x0030
-#define	mem_mode                                	0x0031
-#define	mem_tsniff                              	0x0032
-#define	mem_sniff_anchor                        	0x0034
-#define	mem_clk_offset                          	0x0038
-#define	mem_rx_window                           	0x003e
-#define	mem_plap                                	0x0040
-#define	mem_puap                                	0x0043
-#define	mem_pnap                                	0x0044
-#define	mem_conn_handle                         	0x0046
-#define	mem_cur_arq                             	0x0047
-#define	mem_lmp_to_send                         	0x0048
-#define	mem_lmi_opcode                          	0x0049
-#define	mem_lmo_reason                          	0x004a
-#define	mem_op                                  	0x004b
-#define	mem_state_map                           	0x004c
-#define	mem_supervision_timer                   	0x004d
-#define	mem_supervision_to                      	0x0051
-#define	mem_name_offset                         	0x0053
-#define	mem_key_size                            	0x0054
-#define	mem_reconn_lmp_sm                       	0x0055
-#define	mem_aco                                 	0x0056
-#define	mem_kc                                  	0x0062
-#define	mem_conn_timer                          	0x0072
-#define	mem_sniff_attempt                       	0x0073
-#define	mem_sniff_timeout                       	0x0074
-#define	mem_dsniff                              	0x0075
-#define	mem_amaddr                              	0x0077
-#define	mem_lmo_opcode1                         	0x0078
-#define	mem_lmi_opcode1                         	0x0079
-#define	mem_lmo_reason1                         	0x007a
-#define	mem_lmo_tid1                            	0x007b
-#define	mem_lmo_opcode2                         	0x007c
-#define	mem_lmi_opcode2                         	0x007d
-#define	mem_lmo_reason2                         	0x007e
-#define	mem_lmo_tid2                            	0x007f
-#define	mem_mark_load                           	0x0080
-#define	mem_hci_version                         	0x0088
-#define	mem_acl_pktlen                          	0x008b
-#define	mem_sco_pktlen                          	0x008d
-#define	mem_acl_pktcnt                          	0x008e
-#define	mem_sco_pktcnt                          	0x0090
-#define	mem_current_sniff_attempt               	0x0092
-#define	mem_current_sniff_timeout               	0x0093
-#define	mem_nfreq_index_inq                     	0x0094
-#define	mem_nfreq_index_page                    	0x0095
-#define	mem_ninqy_index                         	0x0096
-#define	mem_fhs_misc                            	0x0097
-#define	mem_tx_lch                              	0x0098
-#define	mem_tx_len                              	0x0099
-#define	mem_subsniff_instant                    	0x009b
-#define	mem_subsniff_rate                       	0x009f
-#define	mem_subsniff_tcmax                      	0x00a0
-#define	mem_subsniff_tsniff                     	0x00a2
-#define	mem_lpm_adjust                          	0x00a3
-#define	mem_sync_clke                           	0x00a4
-#define	mem_lpm_current_mult                    	0x00aa
-#define	mem_gpio_wakeup_low                     	0x00ab
-#define	mem_gpio_wakeup_high                    	0x00b0
-#define	mem_npage_index                         	0x00b5
-#define	mem_page_mode                           	0x00b6
-#define	mem_page_clk                            	0x00b7
-#define	mem_tst_pktcnt_sync                     	0x00bb
-#define	mem_tst_pktcnt_hec                      	0x00bd
-#define	mem_tst_pktcnt_crc                      	0x00bf
-#define	mem_tst_pktcnt_dmh                      	0x00c1
-#define	mem_tmp_buffer_head                     	0x00c3
-#define	mem_tmp_buffer                          	0x00c6
-#define	mem_tester_emulate                      	0x0116
-#define	mem_temp_payload                        	0x0117
-#define	test_mode_scenario                      	0x0117
-#define	test_mode_hopping_mode                  	0x0118
-#define	test_mode_tx_freq                       	0x0119
-#define	test_mode_rx_freq                       	0x011a
-#define	test_mode_power_mode                    	0x011b
-#define	test_mode_poll_period                   	0x011c
-#define	test_mode_packet_type                   	0x011d
-#define	test_mode_data_length                   	0x011e
-#define	mem_test_mode_old_debug_config          	0x0120
-#define	mem_tester_cnt                          	0x0121
-#define	mem_temp_am_addr                        	0x0122
-#define	mem_temp_arq                            	0x0123
-#define	mem_pdatatemp                           	0x0124
-#define	mem_len                                 	0x012c
-#define	mem_clkn_bt                             	0x012e
-#define	mem_clke_bt                             	0x0132
-#define	mem_dpll_clkn                           	0x0136
-#define	mem_connection_options                  	0x013a
-#define	mem_nameres_cnt                         	0x013b
-#define	mem_txptr                               	0x013c
-#define	mem_slot_offset                         	0x013e
-#define	mem_wait_auth_clk                       	0x0140
-#define	extm_fhs_misc                           	0x0144
-#define	extm_newconn_am_addr                    	0x0145
-#define	extm_class                              	0x0146
-#define	extm_lap                                	0x0149
-#define	extm_uap                                	0x014c
-#define	extm_nap                                	0x014d
-#define	mem_debug_config                        	0x0150
-#define	mem_lch_code                            	0x0151
-#define	mem_fhs_am_addr                         	0x0152
-#define	mem_dpll_error                          	0x0153
-#define	mem_bdaddr_list_buff                    	0x0155
-#define	mem_select_list_item                    	0x0179
-#define	mem_temp_reconn_record                  	0x017a
-#define	mem_record_bt_mode                      	0x017a
-#define	mem_temp_lap                            	0x017b
-#define	mem_list_item_ptr                       	0x0181
-#define	mem_eir                                 	0x0183
-#define	mem_switch_timeout                      	0x01e7
-#define	mem_acl_dsniff                          	0x01e9
-#define	mem_acl_tsniff                          	0x01eb
-#define	mem_acl_attempt                         	0x01ed
-#define	mem_acl_timeout                         	0x01ee
-#define	mem_temp_force_nack                     	0x01ef
-#define	mem_avdtp_signal_cmd                    	0x01f0
-#define	mem_transaction_label                   	0x01f1
-#define	mem_temp_sbc_decode_buffer_size         	0x01f2
-#define	mem_temp_dac_soft_dma_work_wptr         	0x01f4
-#define	mem_temp_sbc_soft_dma_start_addr        	0x01f6
-#define	mem_temp_dac_soft_dma_start_addr        	0x01f8
-#define	mem_temp_soft_dma_work_length           	0x01fa
-#define	mem_temp_soft_dma_work_table_index_value	0x01fc
-#define	mem_ucode_status                        	0x01fd
-#define	mem_ucode_flag                          	0x01fe
-#define	mem_qspi_tbuf                           	0x0200
-#define	mem_iicd_tbuf                           	0x0201
-#define	mem_addr_hi                             	0x0201
-#define	mem_eep_addr_hi                         	0x0202
-#define	mem_addr_mi                             	0x0202
-#define	mem_addr_lo                             	0x0203
-#define	mem_iicd_addr                           	0x0204
-#define	mem_spid_rbuf                           	0x0205
-#define	mem_ucode_buf                           	0x0209
-#define	mem_ucode_len                           	0x020b
-#define	mem_sched_addr                          	0x020d
-#define	mem_ucode_ptr                           	0x020f
-#define	mem_ucode_keybuf                        	0x0212
-#define	mem_check_plap_temp                     	0x0222
-#define	mem_start_addr_temp                     	0x0234
-#define	mem_spid_tbuf                           	0x0237
-#define	mem_qspi_defualt                        	0x0239
-#define	mem_switch_fail_master_count            	0x023a
-#define	mem_app_evt_timer_count                 	0x023b
-#define	mem_flash_address                       	0x023c
-#define	mem_flash_data_address                  	0x023f
-#define	mem_flash_trans_length                  	0x0241
-#define	mem_soft_dma_src_addr                   	0x0243
-#define	mem_soft_dma_dst_addr                   	0x0247
-#define	mem_avctp_command_response              	0x024b
-#define	mem_avrcp_vol                           	0x024c
-#define	mem_avctp_rx_label                      	0x024d
-#define	mem_h5rx_ackcnt                         	0x024e
-#define	mem_check_err_acl_cont                  	0x024f
-#define	mem_rp_packets                          	0x0250
-#define	mem_packet_type                         	0x0251
-#define	mem_hci_sniff_conn_handle               	0x0253
-#define	mem_hci_sniff_max_interval              	0x0255
-#define	mem_hci_sniff_min_interval              	0x0257
-#define	mem_hci_sniff_attempt                   	0x0259
-#define	mem_hci_sniff_timeout                   	0x025b
-#define	mem_voice_setting                       	0x025d
-#define	mem_retransmission_effort               	0x025f
-#define	mem_sco_ptype                           	0x0260
-#define	mem_extm_uap_restore                    	0x0262
-#define	mem_h5rx_rptr                           	0x0265
-#define	mem_h5rx_ack                            	0x0267
-#define	mem_h5tx_ack                            	0x0268
-#define	mem_h5tx_rptr                           	0x0269
-#define	mem_h5tx_wptr                           	0x026b
-#define	mem_h5tx_free                           	0x026d
-#define	mem_h5rx_tmp                            	0x026f
-#define	mem_h5tx_seq                            	0x0270
-#define	mem_hci_acl_queue_wptr                  	0x0271
-#define	mem_hci_acl_queue_rptr                  	0x0273
-#define	mem_hci_acl_queue_end                   	0x0275
-#define	mem_hci_acl_queue_wcnt                  	0x0277
-#define	mem_hci_acl_cnt                         	0x0278
-#define	mem_hci_acl_tx_trigger_wptr             	0x0279
-#define	mem_ucode_id_local                      	0x027b
-#define	mem_ucode_id_remote                     	0x027c
-#define	mem_check_sum                           	0x027d
-#define	mem_ucode_temp                          	0x027e
-#define	mem_ucode_temp1                         	0x027f
-#define	mem_lock_in_enc                         	0x0280
-#define	mem_hci_disconn_reason                  	0x0281
-#define	mem_hci_curr_len                        	0x0282
-#define	mem_hci_curr_target                     	0x0283
-#define	mem_coef_table_temp                     	0x0285
-#define	mem_sco_indata                          	0x03d7
-#define	mem_sco_outdata                         	0x0413
-#define	mem_phone_num_count                     	0x044f
-#define	mem_phone_num_len                       	0x0450
-#define	mem_phone_number                        	0x0451
-#define	mem_at_command_data                     	0x0460
-#define	mem_sco_flag                            	0x047e
-#define	mem_l2cap_mem_start                     	0x047f
-#define	mem_l2cap_rxbuff1_len                   	0x047f
-#define	mem_l2cap_rxbuff2_len                   	0x0481
-#define	mem_l2cap_rxbuff_new_temp               	0x0483
-#define	mem_l2cap_rxbuff_new                    	0x0484
-#define	mem_l2cap_rxbuff_fifo                   	0x0485
-#define	mem_l2cap_rxbuff_fifo1                  	0x0485
-#define	mem_l2cap_rxbuff_fifo2                  	0x0486
-#define	mem_l2cap_payload_ptr                   	0x0487
-#define	mem_l2cap_rx_pkt_length                 	0x0489
-#define	mem_l2cap_rx_cid                        	0x048b
-#define	mem_l2cap_rx_done                       	0x048d
-#define	mem_l2cap_signal_ident                  	0x048e
-#define	mem_sdp_tx_buff_ptr                     	0x048f
-#define	mem_sdp_tx_payload_ptr                  	0x0491
-#define	mem_sdp_tx_pkt_length                   	0x0493
-#define	mem_tx_malloc_log                       	0x0495
-#define	mem_l2cap_temp_ch_info                  	0x04d5
-#define	mem_l2cap_temp_ch_psm                   	0x04d5
-#define	mem_l2cap_temp_ch_state                 	0x04d6
-#define	mem_l2cap_temp_local_cid                	0x04d7
-#define	mem_l2cap_temp_remote_cid               	0x04d9
-#define	mem_l2cap_mem_end                       	0x04db
-#define	mem_le_rxbuf                            	0x04db
-#define	mem_le_l2capbuf                         	0x0503
-#define	mem_le_mic                              	0x05db
-#define	mem_le_peer_mic                         	0x05df
-#define	mem_le_skdm                             	0x05e3
-#define	mem_le_skds                             	0x05eb
-#define	mem_le_peer_ltk                         	0x05f3
-#define	mem_le_my_ltk                           	0x0603
-#define	mem_le_mrand                            	0x0613
-#define	mem_le_state                            	0x0623
-#define	mem_le_mode                             	0x0624
-#define	mem_le_tsniff                           	0x0625
-#define	mem_le_anchor                           	0x0627
-#define	mem_le_clk_offset                       	0x062b
-#define	mem_le_receive_window                   	0x0631
-#define	mem_le_plap                             	0x0633
-#define	mem_le_conn_handle                      	0x0639
-#define	mem_le_arq                              	0x063a
-#define	mem_le_ch                               	0x063b
-#define	mem_le_hop                              	0x063c
-#define	mem_le_event_count                      	0x063d
-#define	mem_le_supervision_timer                	0x063f
-#define	mem_le_instant                          	0x0643
-#define	mem_le_channels                         	0x0645
-#define	mem_le_conn_sm                          	0x0646
-#define	mem_le_op                               	0x0647
-#define	mem_le_access                           	0x0648
-#define	mem_le_crcinit                          	0x064c
-#define	mem_le_window_size                      	0x064f
-#define	mem_le_slave_latency                    	0x0650
-#define	mem_le_superto                          	0x0652
-#define	mem_le_channel_map                      	0x0654
-#define	mem_le_no_using                         	0x0659
-#define	mem_le_peer_sca                         	0x065b
-#define	mem_le_att_opcode                       	0x065c
-#define	mem_le_att_handle                       	0x065d
-#define	mem_le_err_code                         	0x065f
-#define	mem_le_ll_pairing_fail_reason           	0x0660
-#define	mem_le_sk                               	0x0661
-#define	mem_le_testtype                         	0x0671
-#define	mem_le_test_sync                        	0x0672
-#define	mem_le_test_pcnt                        	0x0674
-#define	mem_le_notify_len                       	0x0676
-#define	mem_cmd_le_create_conn                  	0x0677
-#define	mem_le_adv_temp                         	0x0678
-#define	mem_le_packet_size                      	0x068c
-#define	mem_le_packet_llid                      	0x068d
-#define	mem_le_payload_ptr                      	0x068e
-#define	mem_lmo_header_length                   	0x0690
-#define	mem_lmo_header_opcode                   	0x0691
-#define	mem_lmo_payload                         	0x0692
-#define	mem_lmi_accepted_opcode                 	0x06a3
-#define	mem_disconn_reason_send                 	0x06a4
-#define	mem_tx_fixed_freq                       	0x06a5
-#define	mem_rx_fixed_freq                       	0x06a6
-#define	mem_ext_features_page                   	0x06a7
-#define	mem_lmpext_ssp_enable                   	0x06a8
-#define	mem_remote_sppcap                       	0x06aa
-#define	mem_lmp_conn_state                      	0x06ab
-#define	mem_soft_timer                          	0x06ac
-#define	mem_pincode_state                       	0x06ae
-#define	mem_sres_tid                            	0x06af
-#define	mem_accptsco_tid                        	0x06b0
-#define	mem_wait_encryption                     	0x06b1
-#define	mem_sniff_payload                       	0x06b2
-#define	mem_aurand_send_delay_time              	0x06c2
-#define	mem_prcp_data                           	0x06c6
-#define	mem_prcp                                	0x06da
-#define	mem_prcp_tx_len                         	0x06db
-#define	rx_buf_data_ptr                         	0x06dc
-#define	mem_mod2div_temp                        	0x06de
-#define	mem_contw_temp                          	0x06e1
-#define	mem_rfc_adss                            	0x06e3
-#define	mem_rfc_current_channel                 	0x06e4
-#define	mem_rfc_frame_type                      	0x06e5
-#define	mem_current_fcs                         	0x06e6
-#define	mem_rfc_paylead_length                  	0x06e7
-#define	mem_rfc_paylead_ptr                     	0x06e9
-#define	mem_uih_cmd_type                        	0x06eb
-#define	mem_uih_length                          	0x06ec
-#define	mem_rfc_payload_ptr                     	0x06ee
-#define	mem_ms_param                            	0x06f0
-#define	mem_pn_credit_flow_type_info            	0x06f1
-#define	mem_pn_priority                         	0x06f2
-#define	mem_pn_acknowledg_timer                 	0x06f3
-#define	mem_pn_max_retrans                      	0x06f4
-#define	mem_rfcomm_send_adss                    	0x06f5
-#define	mem_rfcomm_send_frame_type              	0x06f6
-#define	mem_rfcomm_send_fcs                     	0x06f7
-#define	mem_sdp_mem_start                       	0x06f8
-#define	mem_sdp_uuid_search_ptr                 	0x06f8
-#define	mem_sdp_continue_byte                   	0x0700
-#define	mem_sdp_pduid                           	0x0702
-#define	mem_sdp_transactionid                   	0x0703
-#define	mem_sdp_transactionid_local             	0x0705
-#define	mem_sdp_attribute_maxbyte               	0x0707
-#define	mem_sdp_record_maxcnt                   	0x0709
-#define	mem_sdp_record_handle                   	0x070b
-#define	mem_sdp_LACAP_found                     	0x070f
-#define	mem_sdp_RFCOMM_found                    	0x0710
-#define	mem_sdp_handle_list                     	0x0711
-#define	mem_sdp_attrib_list                     	0x0711
-#define	mem_sdp_error_code                      	0x0731
-#define	mem_sdp_all_length                      	0x0733
-#define	mem_handle_humber                       	0x0735
-#define	mem_search_uuid                         	0x0736
-#define	mem_sdp_mem_end                         	0x0738
-#define	mem_rxbuf                               	0x0738
-#define	mem_random_number                       	0x0749
-#define	mem_round_key                           	0x0759
-#define	mem_kinit                               	0x0769
-#define	mem_input_store                         	0x0779
-#define	mem_x                                   	0x0789
-#define	mem_y                                   	0x0799
-#define	mem_y15                                 	0x07a8
-#define	mem_key_store                           	0x07a9
-#define	mem_key_store_end                       	0x07ba
-#define	memp_ar_key                             	0x07bb
-#define	memp_ar_input                           	0x07bd
-#define	mem_ar_hround                           	0x07bf
-#define	mem_ec_infinite                         	0x07c9
-#define	mem_ec_loopc                            	0x07ca
-#define	mem_aes_cmac_data_length                	0x07cc
-#define	memdat                                  	0x07cd
-#define	mem_ax                                  	0x07cd
-#define	mem_ay                                  	0x07e5
-#define	mem_az                                  	0x07fd
-#define	mem_bx                                  	0x0815
-#define	mem_ax_256                              	0x082d
-#define	mem_by                                  	0x082d
-#define	mem_bz                                  	0x0845
-#define	mem_ay_256                              	0x084d
-#define	mem_cx                                  	0x085d
-#define	mem_az_256                              	0x086d
-#define	mem_cy                                  	0x0875
-#define	mem_cy5                                 	0x088c
-#define	mem_bx_256                              	0x088d
-#define	mem_cz                                  	0x088d
-#define	mem_k                                   	0x08a5
-#define	mem_by_256                              	0x08ad
-#define	mem_align                               	0x08bd
-#define	mem_bz_256                              	0x08cd
-#define	mem_tmp1                                	0x08cd
-#define	memahbak                                	0x08cd
-#define	mem_tmp5                                	0x08e5
-#define	mem_cx_256                              	0x08ed
-#define	memahsave                               	0x08ed
-#define	mem_tmp2                                	0x08fd
-#define	mem_cy_256                              	0x090d
-#define	memahsave_end                           	0x090d
-#define	mem_addr_padding                        	0x090d
-#define	mem_addr_value                          	0x090e
-#define	mem_tmp3                                	0x0915
-#define	mem_t1                                  	0x0915
-#define	mem_addr_value_end                      	0x091a
-#define	mem_addr_iocap_end                      	0x091d
-#define	mem_cy5_256                             	0x092c
-#define	mem_cz_256                              	0x092d
-#define	mem_tmp0                                	0x092d
-#define	mem_t0                                  	0x092d
-#define	mem_tmp0a                               	0x0935
-#define	mem_t2                                  	0x0945
-#define	mem_k_256                               	0x094d
-#define	mem_t3                                  	0x095d
-#define	mem_tmp1_256                            	0x096d
-#define	mem_t7                                  	0x0975
-#define	mem_tmp5_256                            	0x098d
-#define	mem_tmp2_256                            	0x09ad
-#define	mem_tmp3_256                            	0x09cd
-#define	mem_t1_256                              	0x09cd
-#define	mem_tmp0_256                            	0x09ed
-#define	mem_t0_256                              	0x09ed
-#define	mem_t2_256                              	0x0a0d
-#define	mem_t3_256                              	0x0a2d
-#define	mem_t7_256                              	0x0a4d
-#define	mem_p                                   	0x0a6d
-#define	mem_a                                   	0x0a85
-#define	mem_b                                   	0x0a9d
-#define	mem_gx                                  	0x0ab5
-#define	mem_gy                                  	0x0acd
-#define	memh0                                   	0x0ae5
-#define	mem_p_256                               	0x0b05
-#define	mem_a_256                               	0x0b25
-#define	mem_gx_256                              	0x0b45
-#define	mem_gy_256                              	0x0b65
-#define	mem_le_slat                             	0x0b85
-#define	mem_sp_state_start                      	0x0b95
-#define	mem_sp_state                            	0x0b95
-#define	mem_master_sp_state                     	0x0b96
-#define	mem_sp_flag                             	0x0b97
-#define	mem_master_sp_flag                      	0x0b98
-#define	mem_sp_calc                             	0x0b99
-#define	mem_sp_dh_ready                         	0x0b9a
-#define	mem_sp_localsm                          	0x0b9b
-#define	mem_pairing_auth                        	0x0b9c
-#define	mem_sp_flag_start                       	0x0b9d
-#define	mem_sp_local_key_send_count             	0x0b9d
-#define	mem_sp_remote_key_recv_count            	0x0b9e
-#define	mem_sp_remote_key_invalid               	0x0b9f
-#define	mem_sp_dhkey_invalid                    	0x0ba0
-#define	mem_gkey                                	0x0ba1
-#define	mem_le_pubkey_remote_x_256              	0x0ba5
-#define	mem_sp_pubkey_remote                    	0x0bad
-#define	mem_sp_pubkey_remote_x                  	0x0bad
-#define	mem_sp_pubkey_remote_x_end              	0x0bc5
-#define	mem_sp_pubkey_remote_y                  	0x0bc5
-#define	mem_le_pubkey_remote_y_256              	0x0bc5
-#define	mem_le_dhkey_256                        	0x0be5
-#define	mem_sp_dhkey                            	0x0bed
-#define	mem_sp_dhkey_end                        	0x0c05
-#define	mem_sp_random_local                     	0x0c05
-#define	mem_sp_random_local_end                 	0x0c15
-#define	mem_sp_random_remote                    	0x0c15
-#define	mem_sp_random_remote_end                	0x0c25
-#define	memresult                               	0x0c25
-#define	mem_sp_calc_result                      	0x0c25
-#define	memh                                    	0x0c25
-#define	memg                                    	0x0c29
-#define	memf                                    	0x0c2d
-#define	meme                                    	0x0c31
-#define	mem_sp_calc_result_high                 	0x0c35
-#define	memd                                    	0x0c35
-#define	memc                                    	0x0c39
-#define	memb                                    	0x0c3d
-#define	mema                                    	0x0c41
-#define	mem_sp_check_result                     	0x0c45
-#define	mem_sp_confirm_remote                   	0x0c55
-#define	mem_sp_prarm_stack                      	0x0c65
-#define	mem_ipc_skip_continue_proc              	0x0c75
-#define	mem_row_scanned_record                  	0x0c76
-#define	mem_col_scanned_record                  	0x0c77
-#define	mem_get_keypress_flag_record            	0x0c78
-#define	mem_usb_status                          	0x0c79
-#define	mem_usb_fifo_empty                      	0x0c7a
-#define	mem_usb_read_len                        	0x0c7b
-#define	mem_usb_txbuf                           	0x0c7d
-#define	mem_usb_txbuf1                          	0x0cbe
-#define	mem_usb_txbuf2                          	0x0cc8
-#define	mem_usb_rxbuf                           	0x0cd2
-#define	mem_usb_rxbuf_end                       	0x0d0e
-#define	mem_usb_state                           	0x0d0f
-#define	mem_bufptr                              	0x0d10
-#define	mem_remain                              	0x0d12
-#define	mem_devicedesc                          	0x0d13
-#define	mem_hidreportdesc_kb                    	0x0d27
-#define	mem_hidreportdesc_m                     	0x0d6d
-#define	mem_confdesc                            	0x0e35
-#define	mem_string0                             	0x0e7b
-#define	mem_string1                             	0x0e80
-#define	mem_string2                             	0x0e9e
-#define	mem_string3                             	0x0ebc
-#define	mem_usb_setup                           	0x0eda
-#define	mem_usb_setup_bmRequestType             	0x0eda
-#define	mem_usb_setup_bRequest                  	0x0edb
-#define	mem_usb_setup_bValue                    	0x0edc
-#define	mem_usb_setup_bValueH                   	0x0edd
-#define	mem_usb_setup_wIndex                    	0x0ede
-#define	mem_usb_setup_bLength                   	0x0ee0
-#define	mem_usb_setup_bLengthH                  	0x0ee1
-#define	mem_usb0_setup_ptr                      	0x0ee2
-#define	mem_usb0_set_report_data_ptr            	0x0ee4
-#define	mem_usb_setup_bValue_temp               	0x0ee6
-#define	mem_usb0_get_set_report                 	0x0ee8
-#define	mem_usb0_data_ready_report              	0x0ee9
-#define	mem_usb_tx_win_enable                   	0x0eea
-#define	mem_usb_tx_mac_enable                   	0x0eeb
-#define	mem_usb_zero_packet                     	0x0eec
-#define	mem_usb_ones_packet                     	0x0eee
-#define	mem_usb_two_packet                      	0x0ef0
-#define	mem_usb_idle_flag                       	0x0ef2
-#define	mem_usb_idle_rate                       	0x0ef3
-#define	mem_usb_get_protocol_flag               	0x0ef4
-#define	mem_usb_set_protocol_status             	0x0ef5
-#define	mem_usb_set_protocol_value              	0x0ef6
-#define	mem_usb0_state                          	0x0ef7
-#define	mem_usb_remote_wakeup                   	0x0ef8
-#define	mem_usb_clear_remote_wakeup             	0x0ef9
-#define	mem_usb_ep0_stall_status                	0x0efa
-#define	mem_usb_ep1_stall_status                	0x0efb
-#define	mem_usb_ep2_stall_status                	0x0efc
-#define	mem_usb_ep3_stall_status                	0x0efd
-#define	mem_dsc_info_data_pointer               	0x0efe
-#define	mem_dsc_info_len                        	0x0f00
-#define	mem_usb_ep1_data                        	0x0f01
-#define	mem_usb_ep2_data                        	0x0f02
-#define	mem_usb_tx_enable                       	0x0f03
-#define	mem_usb_device_enumeration_endflag      	0x0f04
-#define	mem_usb_wakestate_onetime_flag          	0x0f05
-#define	mem_usb_mac_wakeup_trig                 	0x0f06
-#define	mem_usb_set_high_addr_flag              	0x0f07
-#define	mem_usb_clear_halt                      	0x0f08
-#define	mem_hold_contr                          	0x0f09
-#define	mem_hold_contw                          	0x0f0b
-#define	mem_fifo_temp                           	0x0f0d
-#define	mem_max_bitsneed                        	0x0f0e
-#define	mem_bits_need00                         	0x0f12
-#define	mem_temp                                	0x0f12
-#define	mem_bits_need01                         	0x0f16
-#define	mem_temp1                               	0x0f16
-#define	mem_bits_need02                         	0x0f1a
-#define	mem_timeup                              	0x0f1a
-#define	mem_bits_need03                         	0x0f1e
-#define	mem_rega                                	0x0f1e
-#define	mem_bits_need04                         	0x0f22
-#define	mem_regb                                	0x0f22
-#define	mem_bits_need05                         	0x0f26
-#define	mem_regc                                	0x0f26
-#define	mem_bits_need06                         	0x0f2a
-#define	mem_contr                               	0x0f2a
-#define	mem_contw                               	0x0f2c
-#define	mem_bits_need07                         	0x0f2e
-#define	mem_bits_need10                         	0x0f32
-#define	mem_bits_need11                         	0x0f36
-#define	mem_bits_need12                         	0x0f3a
-#define	mem_bits_need13                         	0x0f3e
-#define	mem_bits_need14                         	0x0f42
-#define	mem_bits_need15                         	0x0f46
-#define	mem_bits_need16                         	0x0f4a
-#define	mem_bits_need17                         	0x0f4e
-#define	mem_wakup_from_power_flag               	0x0f52
-#define	mem_saved_gpio_in                       	0x0f53
-#define	mem_flash_data_address_t                	0x0f57
-#define	mem_le_data_len_temp                    	0x0f57
-#define	mem_tx_fifo_map_temp                    	0x0f57
-#define	mem_rpn_dlci                            	0x0f57
-#define	mem_event_cmd_response_content          	0x0f57
-#define	mem_le_prand                            	0x0f57
-#define	mem_AES_CMAC_k                          	0x0f57
-#define	mem_regext_index                        	0x0f57
-#define	mem_temp_block0                         	0x0f57
-#define	mem_le_data_temp                        	0x0f58
-#define	mem_temp_block1                         	0x0f58
-#define	mem_le_aes_128                          	0x0f67
-#define	mem_regext                              	0x0f67
-#define	mem_AES_CMAC_k1                         	0x0f67
-#define	mem_sum_temp                            	0x0f67
-#define	mem_temp_block2                         	0x0f67
-#define	mem_AES_CMAC_k2                         	0x0f77
-#define	mem_temp_block3                         	0x0f77
-#define	mem_AES_CMAC_temp                       	0x0f87
-#define	mem_temp_block4                         	0x0f87
-#define	mem_AES_CMAC_M_last                     	0x0f97
-#define	mem_temp_block5                         	0x0f97
-#define	mem_le_mackey                           	0x0fa7
-#define	mem_temp_block6                         	0x0fa7
-#define	mem_zcode_temp_param0                   	0x0fb7
-#define	mem_zcode_temp_param1                   	0x0fb8
-#define	mem_zcode_temp_param2                   	0x0fba
-#define	mem_tws_sync_clk                        	0x0fbc
-#define	mem_tws_connecting_phase                	0x0fc0
-#define	mem_temp_tx_power                       	0x0fc1
-#define	mem_msbc_miss                           	0x0fc2
-#define	mem_msbc_error                          	0x0fc4
-#define	mem_vp_length                           	0x0fc6
-#define	mem_ota_cmd                             	0x0fc9
-#define	mem_ota_return_result                   	0x0fca
-#define	mem_ota_update_flash_mode               	0x0fcb
-#define	mem_ota_write_index                     	0x0fcc
-#define	mem_ota_write_length                    	0x0fce
-#define	mem_ota_write_data_addr                 	0x0fd0
-#define	mem_ota_write_flash_addr                	0x0fd3
-#define	mem_ota_enable_xip_flag                 	0x0fd6
-#define	mem_xip_flash_offset_mram               	0x0fd7
-#define	mem_storage_start_addr_mram             	0x0fda
-#define	mem_ota_notify_handle_mram              	0x0fdd
-#define	mem_ota_write_handle_mram               	0x0fde
-#define	mem_ota_buck_size_mram                  	0x0fdf
-#define	mem_ota_packet_max_len_mram             	0x0fe1
-#define	mem_ota_wdt_en_flag                     	0x0fe3
-#define	mem_ota_wdt_m0_en                       	0x0fe4
-#define	mem_patch00                             	0x4000
-#define	mem_patch01                             	0x4001
-#define	mem_patch02                             	0x4002
-#define	mem_patch03                             	0x4003
-#define	mem_patch04                             	0x4004
-#define	mem_patch05                             	0x4005
-#define	mem_patch06                             	0x4006
-#define	mem_patch07                             	0x4007
-#define	mem_patch08                             	0x4008
-#define	mem_patch09                             	0x4009
-#define	mem_patch0a                             	0x400a
-#define	mem_patch0b                             	0x400b
-#define	mem_patch0c                             	0x400c
-#define	mem_patch0d                             	0x400d
-#define	mem_patch0e                             	0x400e
-#define	mem_patch0f                             	0x400f
-#define	mem_patch10                             	0x4010
-#define	mem_patch11                             	0x4011
-#define	mem_patch12                             	0x4012
-#define	mem_patch13                             	0x4013
-#define	mem_patch14                             	0x4014
-#define	mem_patch15                             	0x4015
-#define	mem_patch16                             	0x4016
-#define	mem_patch17                             	0x4017
-#define	mem_patch18                             	0x4018
-#define	mem_patch19                             	0x4019
-#define	mem_patch1a                             	0x401a
-#define	mem_patch1b                             	0x401b
-#define	mem_patch1c                             	0x401c
-#define	mem_patch1d                             	0x401d
-#define	mem_patch1e                             	0x401e
-#define	mem_patch1f                             	0x401f
-#define	mem_patch20                             	0x4020
-#define	mem_patch21                             	0x4021
-#define	mem_patch22                             	0x4022
-#define	mem_patch23                             	0x4023
-#define	mem_patch24                             	0x4024
-#define	mem_patch25                             	0x4025
-#define	mem_patch26                             	0x4026
-#define	mem_patch27                             	0x4027
-#define	mem_patch28                             	0x4028
-#define	mem_patch29                             	0x4029
-#define	mem_patch2a                             	0x402a
-#define	mem_patch2b                             	0x402b
-#define	mem_patch2c                             	0x402c
-#define	mem_patch2d                             	0x402d
-#define	mem_patch2e                             	0x402e
-#define	mem_patch2f                             	0x402f
-#define	mem_patch30                             	0x4030
-#define	mem_patch31                             	0x4031
-#define	mem_patch32                             	0x4032
-#define	mem_patch33                             	0x4033
-#define	mem_patch34                             	0x4034
-#define	mem_patch35                             	0x4035
-#define	mem_patch36                             	0x4036
-#define	mem_patch37                             	0x4037
-#define	mem_patch38                             	0x4038
-#define	mem_patch39                             	0x4039
-#define	mem_patch3a                             	0x403a
-#define	mem_patch3b                             	0x403b
-#define	mem_patch3c                             	0x403c
-#define	mem_patch3d                             	0x403d
-#define	mem_patch3e                             	0x403e
-#define	mem_patch3f                             	0x403f
-#define	mem_context                             	0x4040
-#define	mem_current_amaddr                      	0x4130
-#define	mem_lpm_mode                            	0x4131
-#define	mem_device_option                       	0x4132
-#define	mem_scan_mode                           	0x4133
-#define	mem_last_clkn                           	0x4134
-#define	mem_features                            	0x4138
-#define	mem_lap                                 	0x4140
-#define	mem_uap                                 	0x4143
-#define	mem_nap                                 	0x4144
-#define	mem_npage                               	0x4146
-#define	mem_glap                                	0x4147
-#define	mem_class                               	0x414a
-#define	mem_iscan_window                        	0x414d
-#define	mem_iscan_interval                      	0x414f
-#define	mem_pscan_window                        	0x4151
-#define	mem_pscan_interval                      	0x4153
-#define	mem_page_interval                       	0x4155
-#define	mem_page_window                         	0x4157
-#define	mem_page_to                             	0x4159
-#define	mem_inq_window                          	0x415b
-#define	mem_fcomp_mul                           	0x415d
-#define	mem_fcomp_div                           	0x415e
-#define	mem_rx_window_init                      	0x415f
-#define	mem_rx_window_sniff                     	0x4161
-#define	mem_rf_init_ptr                         	0x4163
-#define	mem_rf_init                             	0x4165
-#define	mem_last_type                           	0x4166
-#define	mem_retransmission_cnt                  	0x4167
-#define	mem_next_btclk                          	0x4169
-#define	mem_seqi                                	0x416d
-#define	mem_rf_rccal                            	0x416e
-#define	mem_handle_num                          	0x416f
-#define	mem_max_slot                            	0x4170
-#define	mem_eir_enable                          	0x4171
-#define	mem_afh_instant                         	0x4172
-#define	mem_afh_error_total                     	0x4176
-#define	mem_afh_cfg                             	0x4178
-#define	mem_afh_new_mod                         	0x4179
-#define	mem_afh_map_lo                          	0x417a
-#define	mem_afh_map_hi                          	0x417f
-#define	mem_afh_used                            	0x4184
-#define	mem_afh_index                           	0x4185
-#define	mem_afh_map_new                         	0x4187
-#define	mem_afh_map                             	0x4192
-#define	mem_afh_timer                           	0x41e2
-#define	mem_afh_classify_channel_map            	0x41e6
-#define	mem_chip_functions                      	0x41f0
-#define	mem_lpm_wake_lock                       	0x41f2
-#define	mem_lpm_interval                        	0x41f4
-#define	mem_lpm_overhead                        	0x41f6
-#define	mem_lpm_hibernate_switch                	0x41f7
-#define	mem_sniff_unint_lost                    	0x41f8
-#define	mem_ptt                                 	0x41f9
-#define	mem_sleep_counter                       	0x41fa
-#define	mem_sleep_counter_all                   	0x41fe
-#define	mem_sleep_clkn                          	0x4202
-#define	mem_sniff_rcv                           	0x4208
-#define	mem_sniff_lost                          	0x420b
-#define	mem_clks_per_lpo                        	0x420e
-#define	mem_lpm_loadcode_switch                 	0x4211
-#define	mem_lpm_memory_choose                   	0x4212
-#define	mem_lpm_mult                            	0x4213
-#define	mem_lpm_mult_timeout                    	0x4214
-#define	mem_lpm_mult_cnt                        	0x4215
-#define	mem_lpm_config                          	0x4216
-#define	mem_lpm_xtalcnt                         	0x4219
-#define	mem_lpm_buckcnt                         	0x421a
-#define	mem_lpm_ldocnt                          	0x421b
-#define	mem_lpm_isogate                         	0x421c
-#define	mem_lpm_isogate_final                   	0x421d
-#define	mem_saved_gpio                          	0x421e
-#define	mem_saved_mark                          	0x4246
-#define	mem_saved_spidctrl                      	0x424e
-#define	mem_patch_ptr                           	0x424f
-#define	mem_patch_len                           	0x4251
-#define	mem_timers                              	0x4253
-#define	mem_link_key_exists                     	0x4293
-#define	mem_link_key_eeprom_head                	0x4294
-#define	mem_link_key                            	0x4297
-#define	mem_hci_cmd                             	0x42a7
-#define	mem_hci_conn_handle                     	0x42a8
-#define	mem_hci_plap                            	0x42a9
-#define	mem_hci_puap                            	0x42ac
-#define	mem_hci_pnap                            	0x42ad
-#define	mem_uartd_rxitems_got_data              	0x42af
-#define	mem_uartd_rxitems_threshold             	0x42b0
-#define	mem_uartd_rx_timeout                    	0x42b1
-#define	mem_sco_attempt_cout                    	0x42b3
-#define	mem_tx_power                            	0x42b4
-#define	mem_sfreq_enable                        	0x42b5
-#define	mem_param_rf_setup                      	0x42b6
-#define	mem_param_pll_setup                     	0x42b8
-#define	mem_avdtp_xmem_start                    	0x42ba
-#define	mem_avdtpsignal_l2capch_ptr             	0x42ba
-#define	mem_avdtpmedia_l2capch_ptr              	0x42bc
-#define	mem_audio_allow                         	0x42be
-#define	mem_audio_state                         	0x42bf
-#define	mem_audio_src_endpoint                  	0x42c0
-#define	mem_audio_src_endpoint_state            	0x42c1
-#define	mem_a2dp_reconnct_delay_timer           	0x42c2
-#define	mem_avdtp_xmem_end                      	0x42c3
-#define	mem_get_media_type                      	0x42c3
-#define	mem_get_codec_type                      	0x42c4
-#define	mem_get_samplefreq_channelmode          	0x42c5
-#define	mem_get_blocklen_subb_allocation        	0x42c6
-#define	mem_get_min_bitpool                     	0x42c7
-#define	mem_get_max_bitpool                     	0x42c8
-#define	mem_get_r_media_type                    	0x42c9
-#define	mem_get_r_codec_type                    	0x42ca
-#define	mem_get_r_samplefreq_channelmode        	0x42cb
-#define	mem_get_r_blocklen_subb_allocation      	0x42cc
-#define	mem_get_r_min_bitpool                   	0x42cd
-#define	mem_get_r_max_bitpool                   	0x42ce
-#define	mem_conf_media_type                     	0x42cf
-#define	mem_conf_codec_type                     	0x42d0
-#define	mem_conf_samplefreq_channelmode         	0x42d1
-#define	mem_conf_blocklen_subb_allocation       	0x42d2
-#define	mem_conf_min_bitpool                    	0x42d3
-#define	mem_conf_max_bitpool                    	0x42d4
-#define	mem_avc_local_transaction_label         	0x42d5
-#define	mem_avdtp_signal                        	0x42d6
-#define	mem_avdtp_media                         	0x42d8
-#define	mem_a2dp_state                          	0x42da
-#define	mem_a2dp_seq_num                        	0x42db
-#define	mem_audio_output_setting                	0x42dd
-#define	mem_param_sco_use_cm0                   	0x42de
-#define	mem_media_in_fast_mode                  	0x42df
-#define	mem_a2dp_buffer_judge_add               	0x42e0
-#define	mem_param_a2dp_buffer_judge_add_limit   	0x42e1
-#define	mem_a2dp_buffer_judge_drop              	0x42e2
-#define	mem_param_a2dp_buffer_judge_drop_limit  	0x42e3
-#define	mem_drop_or_add_process_state           	0x42e4
-#define	mem_drop_or_add_min_receive_packet_size 	0x42e5
-#define	mem_first_buffer_cache                  	0x42e7
-#define	mem_farrow_filter_delta_uk_sign_bit     	0x42e8
-#define	mem_farrow_filter_delta_uk              	0x42e9
-#define	mem_a2dp_adjust_delta_uk_sign_bit       	0x42ed
-#define	mem_a2dp_adjust_delta_uk                	0x42ee
-#define	mem_a2dp_adjust_total_work_sample       	0x42f2
-#define	mem_a2dp_adjust_delta_bytes_sign_bit    	0x42f6
-#define	mem_a2dp_adjust_delta_bytes             	0x42f7
-#define	mem_slave_force_mute_a2dp_voice         	0x42f9
-#define	mem_slave_force_mute_a2dp_voice_cnt     	0x42fa
-#define	mem_tws_wait_sync_ok                    	0x42fb
-#define	mem_last_a2dp_seq_num                   	0x42fc
-#define	mem_param_a2dp_dac_sbc_same_buffer_flag 	0x42fe
-#define	mem_param_a2dp_dac_buffer_addr_mram_flag	0x42ff
-#define	mem_param_a2dp_dac_buffer_start_addr    	0x4300
-#define	mem_param_a2dp_dac_buffer_size          	0x4302
-#define	mem_param_a2dp_sbc_buffer_addr_mram_flag	0x4304
-#define	mem_param_a2dp_sbc_buffer_start_addr    	0x4305
-#define	mem_param_a2dp_sbc_buffer_size          	0x4307
-#define	mem_app_state                           	0x4309
-#define	mem_app_handshake_flag                  	0x430a
-#define	mem_sniff_param_interval                	0x430b
-#define	mem_sniff_param_attempt                 	0x430d
-#define	mem_sniff_param_timeout                 	0x430f
-#define	mem_cb_check_wakelock                   	0x4311
-#define	mem_cb_before_hibernate                 	0x4313
-#define	mem_cb_before_lpm                       	0x4315
-#define	mem_cb_le_process                       	0x4317
-#define	mem_cb_bt_process                       	0x4319
-#define	mem_cb_idle_process                     	0x431b
-#define	mem_cb_bb_event_process                 	0x431d
-#define	mem_cb_event_timer                      	0x431f
-#define	mem_cb_keyscan                          	0x4321
-#define	mem_device_nums                         	0x4323
-#define	mem_uart_txpin                          	0x4324
-#define	mem_uart_rxpin                          	0x4325
-#define	mem_uart_rtspin                         	0x4326
-#define	mem_uart_ctspin                         	0x4327
-#define	mem_uartb_txpin                         	0x4328
-#define	mem_uartb_rxpin                         	0x4329
-#define	mem_uartb_rtspin                        	0x432a
-#define	mem_uartb_ctspin                        	0x432b
-#define	mem_spid_sclkpin                        	0x432c
-#define	mem_spid_sdiopin                        	0x432d
-#define	mem_iic_sda_pin                         	0x432e
-#define	mem_iic_scl_pin                         	0x432f
-#define	mem_ef_base                             	0x4330
-#define	mem_eeprom_block_size                   	0x4333
-#define	mem_mram_qspi_tx_addr                   	0x4335
-#define	mem_poweron_state                       	0x4337
-#define	mem_app_connection_options              	0x4338
-#define	mem_app_disconn_reason                  	0x4339
-#define	mem_app_disconn_reason_flag             	0x433b
-#define	mem_storage_start_addr                  	0x433d
-#define	mem_local_bdaddr                        	0x4340
-#define	mem_qspi_gpio_ncs                       	0x4346
-#define	mem_qspi_gpio_sck                       	0x4347
-#define	mem_qspi_gpio_io0                       	0x4348
-#define	mem_qspi_gpio_io1                       	0x4349
-#define	mem_qspi_gpio_io2                       	0x434a
-#define	mem_qspi_gpio_io3                       	0x434b
-#define	mem_nv_data_ptr                         	0x434c
-#define	mem_nv_data_number                      	0x434e
-#define	mem_saradc_check_clk                    	0x434f
-#define	mem_saradc_flag                         	0x4350
-#define	mem_bat_read_timer                      	0x4351
-#define	mem_rf_debug_enable                     	0x4352
-#define	mem_rf_debug_rf_rx_debug_gpio           	0x4353
-#define	mem_rf_debug_rf_tx_debug_gpio           	0x4354
-#define	mem_rf_debug_rf_sync_detect_debug_gpio  	0x4355
-#define	mem_rf_debug_rf_crc_error_debug_gpio    	0x4356
-#define	mem_param_soft_dma_enable               	0x4357
-#define	mem_param_soft_dma_table_start_addr     	0x4358
-#define	mem_param_m0_respin_sco_buffer_start_addr	0x435b
-#define	mem_param_app_debug_info_timeout        	0x435e
-#define	mem_app_debug_info_timer                	0x435f
-#define	mem_public_code_svn_version_code        	0x4360
-#define	mem_public_code_time_info               	0x4362
-#define	mem_public_code_size                    	0x4366
-#define	mem_fixed_param_area_start              	0x4369
-#define	mem_fixed_param_area_reserve            	0x4369
-#define	mem_param_use_cm0_control_flag          	0x436e
-#define	mem_avctp_xmem_start                    	0x436f
-#define	mem_avctp_tx_label                      	0x436f
-#define	mem_avr_state                           	0x4370
-#define	mem_avr_l2capch_ptr                     	0x4371
-#define	mem_hp_avctp_timer                      	0x4373
-#define	mem_avctp_play_state                    	0x4374
-#define	mem_vlm_notify_enable                   	0x4375
-#define	mem_vlm_notify_label                    	0x4376
-#define	mem_avctp_xmem_end                      	0x4377
-#define	mem_cvsd_in_addr_end                    	0x4377
-#define	mem_cvsd_in_addr_ptr                    	0x4379
-#define	mem_cvsd_out_addr_start                 	0x437b
-#define	mem_cvsd_out_addr_end                   	0x437d
-#define	mem_cvsd_out_addr_ptr                   	0x437f
-#define	mem_pcm_in_addr_end                     	0x4381
-#define	mem_param_pcm_in_buffer_addr_mram_flag  	0x4383
-#define	mem_param_pcm_in_buffer_addr            	0x4384
-#define	mem_param_cvsd_out_buffer_addr_mram_flag	0x4386
-#define	mem_param_cvsd_out_buffer_addr          	0x4387
-#define	mem_param_cvsd_in_buffer_addr_mram_flag 	0x4389
-#define	mem_param_cvsd_in_buffer_addr           	0x438a
-#define	mem_param_pcm_8k_out_buffer_addr_mram_flag	0x438c
-#define	mem_param_pcm_8k_out_buffer_addr        	0x438d
-#define	mem_param_pcm_48k_out_buffer_addr_mram_flag	0x438f
-#define	mem_param_pcm_48k_out_buffer_addr       	0x4390
-#define	mem_cvsd_start_send                     	0x4392
-#define	mem_baud                                	0x4393
-#define	mem_hci_lt_rx_state                     	0x4395
-#define	mem_hid_xmem_start                      	0x4396
-#define	mem_hid_l2capch_ptr                     	0x4396
-#define	mem_hidint_l2capch_ptr                  	0x4398
-#define	mem_hid_xmem_end                        	0x439a
-#define	mem_xmem_sco_start                      	0x439a
-#define	mem_sco_asso_handle                     	0x439a
-#define	mem_sco_handle                          	0x439b
-#define	mem_sco_dsniff                          	0x439d
-#define	mem_sco_tsniff                          	0x439f
-#define	mem_sco_wsniff                          	0x43a1
-#define	mem_sco_tx_packet_type                  	0x43a2
-#define	mem_sco_rx_packet_type                  	0x43a3
-#define	mem_sco_rx_packet_len                   	0x43a4
-#define	mem_sco_tx_packet_len                   	0x43a6
-#define	mem_air_mode                            	0x43a8
-#define	mem_neogotiation_state                  	0x43a9
-#define	mem_acl_amaddr                          	0x43aa
-#define	mem_esco_amaddr                         	0x43ab
-#define	mem_esco_arq                            	0x43ac
-#define	mem_acl_arq                             	0x43ad
-#define	mem_last_type_esco                      	0x43ae
-#define	mem_last_type_acl                       	0x43af
-#define	mem_sco_poll                            	0x43b0
-#define	mem_esco_attempt                        	0x43b1
-#define	mem_esco_abnormal_attempt               	0x43b2
-#define	mem_xmem_sco_end                        	0x43b3
-#define	mem_xmem_hf_state_start                 	0x43b3
-#define	mem_hf_state                            	0x43b3
-#define	mem_hf_call_state                       	0x43b4
-#define	mem_hf_command                          	0x43b5
-#define	mem_agoption                            	0x43b6
-#define	mem_AG_indicator_map                    	0x43b8
-#define	mem_AG_indicator                        	0x43bf
-#define	mem_telephone_dialing_state             	0x43c6
-#define	mem_telephone_dialing_timer             	0x43c7
-#define	mem_xmem_hf_state_end                   	0x43c8
-#define	mem_hf_vlm_speaker                      	0x43c8
-#define	mem_music_vlm_speaker                   	0x43c9
-#define	mem_hf_vlm_mic                          	0x43ca
-#define	mem_at_payload_ptr                      	0x43cb
-#define	mem_at_command_ptr                      	0x43cd
-#define	mem_at_rfcomm_data_ptr                  	0x43cf
-#define	mem_UI_HF_brsf_feature                  	0x43d1
-#define	mem_codec_type                          	0x43d4
-#define	mem_codec_msbc_support                  	0x43d5
-#define	mem_cb_hfp_result_code                  	0x43d6
-#define	mem_hfp_battery_state                   	0x43d8
-#define	mem_esco_test                           	0x43d9
-#define	mem_sco_transaction_enable              	0x43da
-#define	mem_local_sco_in_process_flag           	0x43db
-#define	mem_ipc_mcu_phase                       	0x43dc
-#define	mem_ipc_mcu_state                       	0x43dd
-#define	mem_ipc_enable                          	0x43de
-#define	mem_ipc_le_data_len                     	0x43df
-#define	mem_ipc_le_data_att_handle              	0x43e0
-#define	mem_ipc_tx_data_len                     	0x43e2
-#define	mem_ipc_tx_data_ptr                     	0x43e3
-#define	mem_ipc_loss_packet                     	0x43e5
-#define	mem_temp_for_addr                       	0x43e7
-#define	mem_ipc_test_buff                       	0x43ea
-#define	mem_param_ipc_mem_block_start_addr      	0x43f4
-#define	mem_param_ipc_to_bt_buf_start_addr      	0x43f4
-#define	mem_param_ipc_to_bt_buf_end_addr        	0x43f7
-#define	mem_param_ipc_to_bt_wptr_addr           	0x43fa
-#define	mem_param_ipc_to_bt_rptr_addr           	0x43fd
-#define	mem_param_ipc_to_m0_wptr_addr           	0x4400
-#define	mem_param_ipc_to_m0_rptr_addr           	0x4403
-#define	mem_param_ipc_to_m0_buf_start_addr      	0x4406
-#define	mem_param_ipc_mem_block_end_addr        	0x4409
-#define	mem_param_ipc_to_m0_buf_end_addr        	0x4409
-#define	mem_param_debug_log_func_enable         	0x440c
-#define	mem_debug_log_temp_point                	0x440d
-#define	mem_param_debug_log_mem_block_start_addr	0x4411
-#define	mem_param_debug_log_initial_flag_addr   	0x4411
-#define	mem_param_debug_log_lock_flag_cm0_addr  	0x4414
-#define	mem_param_debug_log_lock_flag_respin_addr	0x4417
-#define	mem_param_debug_log_lock_victim_addr    	0x441a
-#define	mem_param_debug_log_read_index_addr     	0x441d
-#define	mem_param_debug_log_write_index_addr    	0x4420
-#define	mem_param_debug_log_buffer_start_addr   	0x4423
-#define	mem_param_debug_log_mem_block_end_addr  	0x4426
-#define	mem_param_debug_log_buffer_end_addr     	0x4426
-#define	mem_wake_flag                           	0x4429
-#define	mem_m0_lpm_flag                         	0x442a
-#define	mem_l2cap_xmem_start                    	0x442c
-#define	mem_l2cap_tx_multi_offset               	0x442c
-#define	mem_l2cap_pending_info                  	0x442e
-#define	mem_l2cap_pending_id0                   	0x442e
-#define	mem_l2cap_pending_delay_time0           	0x442f
-#define	mem_l2cap_pending_ptr0                  	0x4433
-#define	mem_l2cap_pending_id1                   	0x4435
-#define	mem_l2cap_pending_delay_time1           	0x4436
-#define	mem_l2cap_pending_ptr1                  	0x443a
-#define	mem_l2cap_pending_id2                   	0x443c
-#define	mem_l2cap_pending_delay_time2           	0x443d
-#define	mem_l2cap_pending_ptr2                  	0x4441
-#define	mem_l2cap_pending_count                 	0x4443
-#define	mem_l2cap_active_ch_count               	0x4444
-#define	mem_l2cap_ch_info                       	0x4445
-#define	mem_l2cap_ch_psm0                       	0x4445
-#define	mem_l2cap_ch_state0                     	0x4446
-#define	mem_l2cap_local_cid0                    	0x4447
-#define	mem_l2cap_remote_cid0                   	0x4449
-#define	mem_l2cap_ch_psm1                       	0x444b
-#define	mem_l2cap_ch_state1                     	0x444c
-#define	mem_l2cap_local_cid1                    	0x444d
-#define	mem_l2cap_remote_cid1                   	0x444f
-#define	mem_l2cap_ch_psm2                       	0x4451
-#define	mem_l2cap_ch_state2                     	0x4452
-#define	mem_l2cap_local_cid2                    	0x4453
-#define	mem_l2cap_remote_cid2                   	0x4455
-#define	mem_l2cap_ch_psm3                       	0x4457
-#define	mem_l2cap_ch_state3                     	0x4458
-#define	mem_l2cap_local_cid3                    	0x4459
-#define	mem_l2cap_remote_cid3                   	0x445b
-#define	mem_l2cap_ch_psm4                       	0x445d
-#define	mem_l2cap_ch_state4                     	0x445e
-#define	mem_l2cap_local_cid4                    	0x445f
-#define	mem_l2cap_remote_cid4                   	0x4461
-#define	mem_l2cap_ch_psm5                       	0x4463
-#define	mem_l2cap_ch_state5                     	0x4464
-#define	mem_l2cap_local_cid5                    	0x4465
-#define	mem_l2cap_remote_cid5                   	0x4467
-#define	mem_l2cap_ch_psm6                       	0x4469
-#define	mem_l2cap_ch_state6                     	0x446a
-#define	mem_l2cap_local_cid6                    	0x446b
-#define	mem_l2cap_remote_cid6                   	0x446d
-#define	mem_l2cap_ch_psm7                       	0x446f
-#define	mem_l2cap_ch_state7                     	0x4470
-#define	mem_l2cap_local_cid7                    	0x4471
-#define	mem_l2cap_remote_cid7                   	0x4473
-#define	mem_l2cap_prepare_confreq_count         	0x4475
-#define	mem_l2cap_channel_disconnect_timer      	0x4476
-#define	mem_sdp_state                           	0x4477
-#define	mem_ML2CAP_comm_id                      	0x4478
-#define	mem_used_map                            	0x4479
-#define	mem_tx_fifo0                            	0x447a
-#define	mem_tx_fifo0_map                        	0x447a
-#define	mem_tx_fifo0_ptr                        	0x447b
-#define	mem_tx_fifo1                            	0x447d
-#define	mem_tx_fifo1_map                        	0x447d
-#define	mem_tx_fifo1_ptr                        	0x447e
-#define	mem_tx_fifo2                            	0x4480
-#define	mem_tx_fifo2_map                        	0x4480
-#define	mem_tx_fifo2_ptr                        	0x4481
-#define	mem_tx_fifo3                            	0x4483
-#define	mem_tx_fifo3_map                        	0x4483
-#define	mem_tx_fifo3_ptr                        	0x4484
-#define	mem_tx_fifo_end                         	0x4486
-#define	mem_alloc_block                         	0x4486
-#define	mem_alloc_header                        	0x4486
-#define	mem_alloc_rptr                          	0x4488
-#define	mem_alloc_wptr                          	0x448a
-#define	mem_alloc_end                           	0x448c
-#define	mem_alloc_cur_len                       	0x448e
-#define	mem_alloc_block_start                   	0x448f
-#define	mem_media_release                       	0x449e
-#define	mem_media_block                         	0x449f
-#define	mem_media_header                        	0x449f
-#define	mem_media_rptr                          	0x44a1
-#define	mem_media_wptr                          	0x44a3
-#define	mem_media_end                           	0x44a5
-#define	mem_media_cur_len                       	0x44a7
-#define	mem_media_block_start                   	0x44a8
-#define	mem_lcp_block                           	0x44b7
-#define	mem_lcp_header                          	0x44b7
-#define	mem_lcp_rptr                            	0x44b9
-#define	mem_lcp_wptr                            	0x44bb
-#define	mem_lcp_end                             	0x44bd
-#define	mem_lcp_cur_len                         	0x44bf
-#define	mem_lcp_block_start                     	0x44c0
-#define	mem_l2cap_flow_ctrl_flag                	0x44cf
-#define	mem_l2cap_pending_item                  	0x44d0
-#define	mem_l2cap_rxbuff_len_error              	0x44d1
-#define	mem_l2cap_xmem_end                      	0x44d2
-#define	mem_l2cap_rx_max_lenth                  	0x44d2
-#define	mem_l2cap_rx_malloc_num                 	0x44d4
-#define	mem_le_dsniff                           	0x44d5
-#define	mem_le_conn_interval                    	0x44d7
-#define	mem_le_scan_enable                      	0x44d9
-#define	mem_le_scan_interval                    	0x44da
-#define	mem_le_scan_window                      	0x44dc
-#define	mem_le_adv_enable                       	0x44de
-#define	mem_le_adv_data_len                     	0x44df
-#define	mem_le_adv_data                         	0x44e0
-#define	mem_le_scan_data_len                    	0x44ff
-#define	mem_le_scan_data                        	0x4500
-#define	mem_le_interal_min                      	0x451f
-#define	mem_le_interal_max                      	0x4521
-#define	mem_le_latency                          	0x4523
-#define	mem_le_timeout                          	0x4525
-#define	mem_le_ch_mapped                        	0x4527
-#define	mem_le_new_map                          	0x4528
-#define	mem_le_new_param                        	0x452d
-#define	mem_le_new_transmitwindowsize           	0x452d
-#define	mem_le_new_transmitwindowoffset         	0x452e
-#define	mem_le_new_conninterval                 	0x4530
-#define	mem_le_new_connslavelatency             	0x4532
-#define	mem_le_new_connsupervisiontimeout       	0x4534
-#define	mem_le_txheader                         	0x4536
-#define	mem_le_txlen                            	0x4537
-#define	mem_le_txpayload                        	0x4538
-#define	mem_le_txcid                            	0x453a
-#define	mem_le_l2cap                            	0x453c
-#define	mem_le_l2cap_response                   	0x453d
-#define	mem_le_txbdy                            	0x453e
-#define	mem_le_pcnt_tx                          	0x455d
-#define	mem_le_pcnt_rx                          	0x4562
-#define	mem_le_last_mic                         	0x4567
-#define	mem_le_ivm                              	0x456b
-#define	mem_le_ivs                              	0x456f
-#define	mem_le_ltk                              	0x4573
-#define	mem_ltk_exists                          	0x4583
-#define	mem_le_rconfirm                         	0x4584
-#define	mem_le_srand                            	0x4594
-#define	mem_le_iat                              	0x45a4
-#define	mem_le_rat                              	0x45a5
-#define	mem_le_preq                             	0x45a6
-#define	mem_le_preq_iocap                       	0x45a7
-#define	mem_le_preq_oob                         	0x45a8
-#define	mem_le_preq_auth                        	0x45a9
-#define	mem_le_preq_max_keysize                 	0x45aa
-#define	mem_le_preq_init_key_distribution       	0x45ab
-#define	mem_le_preq_resp_key_distribution       	0x45ac
-#define	mem_le_pres                             	0x45ad
-#define	mem_le_pres_iocap                       	0x45ae
-#define	mem_le_pres_oob                         	0x45af
-#define	mem_le_pres_auth                        	0x45b0
-#define	mem_le_pres_max_keysize                 	0x45b1
-#define	mem_le_pres_init_key_distribution       	0x45b2
-#define	mem_le_pres_resp_key_distribution       	0x45b3
-#define	mem_le_pairing_state                    	0x45b4
-#define	mem_le_enc_state                        	0x45b5
-#define	mem_le_pairing_mode                     	0x45b6
-#define	mem_le_tk                               	0x45b7
-#define	mem_le_ediv                             	0x45bb
-#define	mem_le_rand                             	0x45bd
-#define	mem_le_irk                              	0x45c5
-#define	mem_le_fixed_passkey_flag               	0x45d5
-#define	mem_le_secure_connect_enable            	0x45d6
-#define	mem_le_secure_connect_flag              	0x45d7
-#define	mem_le_sc_calc                          	0x45d8
-#define	mem_le_secure_connect_state             	0x45d9
-#define	mem_le_sc_confirm_gkey_flag             	0x45da
-#define	mem_le_sc_local_key_invalid             	0x45db
-#define	mem_le_pairing_handle                   	0x45dc
-#define	mem_le_search_handle_start              	0x45de
-#define	mem_le_search_handle_end                	0x45e0
-#define	mem_le_att_offset                       	0x45e2
-#define	mem_le_search_att_type_length           	0x45e2
-#define	mem_le_search_att_type                  	0x45e3
-#define	mem_le_notify_handle                    	0x45f3
-#define	mem_le_search_uuid_length               	0x45f5
-#define	mem_le_search_uuid                      	0x45f6
-#define	mem_le_handle_data_len                  	0x4606
-#define	mem_le_handle_data                      	0x4607
-#define	mem_le_adv_param                        	0x4617
-#define	mem_le_adv_interval_min                 	0x4617
-#define	mem_le_adv_interval_max                 	0x4619
-#define	mem_le_adv_type                         	0x461b
-#define	mem_le_adv_own_addr_type                	0x461c
-#define	mem_le_adv_direct_addr_type             	0x461d
-#define	mem_le_adv_direct_addr                  	0x461e
-#define	mem_le_adv_channel_map                  	0x4624
-#define	mem_le_adv_filter_policy                	0x4625
-#define	mem_le_conn_param                       	0x4626
-#define	mem_le_conn_peer_addr_type              	0x4626
-#define	mem_le_conn_peer_addr                   	0x4627
-#define	mem_le_conn_own_addr_type               	0x462d
-#define	mem_le_conn_interval_min                	0x462e
-#define	mem_le_conn_interval_max                	0x4630
-#define	mem_le_conn_latency                     	0x4632
-#define	mem_le_conn_superto                     	0x4634
-#define	mem_le_scan_params                      	0x4636
-#define	mem_le_scan_type                        	0x4636
-#define	mem_le_scan_own_addr_type               	0x4637
-#define	mem_le_scan_filter_policy               	0x4638
-#define	mem_le_lap                              	0x4639
-#define	mem_le_uap                              	0x463c
-#define	mem_le_nap                              	0x463d
-#define	mem_le_xtype_fifo                       	0x463f
-#define	mem_le_transmit_window                  	0x4644
-#define	mem_le_connection_updata_param          	0x4648
-#define	mem_le_l2cap_size                       	0x4658
-#define	mem_le_packet_len_recved                	0x465a
-#define	mem_le_tx_buff_used                     	0x465b
-#define	mem_le_tx_ptr0                          	0x465c
-#define	mem_le_tx_ptr1                          	0x465e
-#define	mem_le_tx_ptr2                          	0x4660
-#define	mem_le_tx_ptr3                          	0x4662
-#define	mem_ui_le_uuid_table                    	0x4664
-#define	mem_le_cur_attlist_start_ptr            	0x4666
-#define	mem_le_cur_handle_start                 	0x4668
-#define	mem_le_cur_handle_end                   	0x466a
-#define	mem_le_cur_uuid_lenth                   	0x466c
-#define	mem_le_cur_uuid                         	0x466d
-#define	mem_notify_handle_pool                  	0x467d
-#define	mem_le_curr_att_len                     	0x4681
-#define	mem_le_signaling_identifier             	0x4682
-#define	mem_le_more_data                        	0x4683
-#define	mem_lmp_version                         	0x4684
-#define	mem_lmp_subversion                      	0x4687
-#define	mem_local_name_length                   	0x4689
-#define	mem_local_name                          	0x468a
-#define	mem_local_name2                         	0x468d
-#define	mem_local_name_end                      	0x46cd
-#define	mem_unsniff2sniff_timer                 	0x46ce
-#define	mem_switch_flag                         	0x46cf
-#define	mem_role_switch_flag                    	0x46d0
-#define	mem_eeprom_ota_base_addr                	0x46d1
-#define	mem_rfc_xmem_start                      	0x46d3
-#define	mem_pn_dlci                             	0x46d3
-#define	mem_pn_max_frame_size                   	0x46d4
-#define	memFCStemp1                             	0x46d6
-#define	memFCStemp2                             	0x46d7
-#define	memFCStemp3                             	0x46d8
-#define	mem_rfcomm_initiator                    	0x46d9
-#define	mem_remote_spp_channel                  	0x46da
-#define	mem_HIUfcs_SPP                          	0x46db
-#define	mem_HIUfcs_SPP_WCredits                 	0x46dc
-#define	mem_remote_credits                      	0x46dd
-#define	mem_credit_given                        	0x46df
-#define	mem_ms_channel                          	0x46e0
-#define	mem_current_packet_length               	0x46e1
-#define	mem_profile_channel                     	0x46e3
-#define	mem_rfc_l2capch_ptr                     	0x46e4
-#define	mem_rfc_server_state                    	0x46e6
-#define	mem_rfc_xmem_end                        	0x46e8
-#define	mem_ui_uuid_table                       	0x46e8
-#define	mem_all_uuid_16bits                     	0x46ea
-#define	mem_all_uuid_128bits                    	0x4700
-#define	mem_sdp_l2capch_ptr                     	0x4722
-#define	mem_sp_local_key_invalid                	0x4724
-#define	mem_le_private_key_256                  	0x4725
-#define	mem_le_pubkey_local_x_256               	0x4745
-#define	mem_le_pubkey_local_y_256               	0x4765
-#define	mem_sp_private_key                      	0x4785
-#define	mem_sp_pubkey_local                     	0x479d
-#define	mem_sp_pubkey_local_x                   	0x479d
-#define	mem_sp_pubkey_local_x_end               	0x47b5
-#define	mem_sp_pubkey_local_y                   	0x47b5
-#define	mem_ssp_enable                          	0x47cd
-#define	mem_sp_iocap_local                      	0x47ce
-#define	mem_ssp_mode_flag                       	0x47d1
-#define	mem_spp_reject_justwork_flag            	0x47d2
-#define	mem_sp_iocap_remote                     	0x47d3
-#define	mem_flag_mode_ssp_pin                   	0x47d6
-#define	mem_authentication_passkey_times        	0x47d7
-#define	mem_passkey_1bit                        	0x47d8
-#define	mem_flag_pairing_state                  	0x47d9
-#define	mem_ipc_lock_bt                         	0x47da
-#define	mem_ipc_lock_c51                        	0x47db
-#define	mem_ipc_fifo_bt2c51                     	0x47dc
-#define	mem_ipc_fifo_c512bt                     	0x47e1
-#define	mem_ui_timer_last_btclk                 	0x47e6
-#define	mem_ui_state_map                        	0x47ea
-#define	mem_discovery_timer_count               	0x47ec
-#define	mem_discovery_timeout                   	0x47ee
-#define	mem_ui_profile_supported                	0x47f0
-#define	mem_pin_length                          	0x47f1
-#define	mem_pin                                 	0x47f2
-#define	mem_keyscan_switch                      	0x4802
-#define	mem_kscan_row_nums                      	0x4803
-#define	mem_kscan_col_nums                      	0x4804
-#define	mem_row_scanned                         	0x4805
-#define	mem_col_scanned                         	0x4806
-#define	mem_row_cnt                             	0x4807
-#define	mem_get_keypress_flag                   	0x4808
-#define	mem_kscan_row_gpio_pin                  	0x4809
-#define	mem_kscan_col_gpio_pin                  	0x4829
-#define	mem_button_gpio1                        	0x4849
-#define	mem_button_last_state1                  	0x484a
-#define	mem_button_timer1                       	0x484b
-#define	mem_button_press_count1                 	0x484c
-#define	mem_button_timeout1                     	0x484d
-#define	mem_button_press_timeout1               	0x484e
-#define	mem_button_down_cb1                     	0x484f
-#define	mem_button_up_cb1                       	0x4851
-#define	mem_button_longpress_cb1                	0x4853
-#define	mem_button_long_release_cb1             	0x4855
-#define	mem_button_gpio2                        	0x4857
-#define	mem_button_last_state2                  	0x4858
-#define	mem_button_timer2                       	0x4859
-#define	mem_button_press_count2                 	0x485a
-#define	mem_button_timeout2                     	0x485b
-#define	mem_button_press_timeout2               	0x485c
-#define	mem_button_down_cb2                     	0x485d
-#define	mem_button_up_cb2                       	0x485f
-#define	mem_button_longpress_cb2                	0x4861
-#define	mem_button_long_release_cb2             	0x4863
-#define	mem_led_gpio1                           	0x4865
-#define	mem_led_state1                          	0x4866
-#define	mem_led_on_timer1                       	0x4867
-#define	mem_led_off_timer1                      	0x4868
-#define	mem_led_repeat1                         	0x4869
-#define	mem_led_timer1                          	0x486a
-#define	mem_led_gpio2                           	0x486b
-#define	mem_led_state2                          	0x486c
-#define	mem_led_on_timer2                       	0x486d
-#define	mem_led_off_timer2                      	0x486e
-#define	mem_led_repeat2                         	0x486f
-#define	mem_led_timer2                          	0x4870
-#define	mem_uppersm_xmem_start                  	0x4871
-#define	mem_major_uppersm                       	0x4871
-#define	mem_sub_uppersm                         	0x4872
-#define	mem_uppersm_list                        	0x4873
-#define	mem_uppersm_disl2capch_index            	0x4878
-#define	mem_uppersm_xmem_end                    	0x4879
-#define	mem_m0_lock_qspi                        	0x4879
-#define	mem_m0_pause_state                      	0x487a
-#define	mem_xip_flash_offset                    	0x487b
-#define	mem_xip_option                          	0x487e
-#define	mem_xip_flash_read_cmd                  	0x4880
-#define	mem_zcode_current_number                	0x4881
-#define	mem_zcode_buff                          	0x4882
-#define	mem_tws_bdaddr                          	0x4884
-#define	mem_tws_lap                             	0x4884
-#define	mem_tws_uap                             	0x4887
-#define	mem_tws_nap                             	0x4888
-#define	mem_hsp_role                            	0x488a
-#define	mem_auto_hsp_role                       	0x488b
-#define	mem_tws_allow_pairing_rssi_limit        	0x488c
-#define	mem_tws_role                            	0x488d
-#define	mem_tws_state                           	0x488e
-#define	mem_tws_last_rcv_phone_packet_crc_fail  	0x488f
-#define	mem_tws_rcv_ack                         	0x4890
-#define	mem_tws_local_rcv_packet                	0x4891
-#define	mem_tws_last_send_ack                   	0x4892
-#define	mem_tws_timeout_timer                   	0x4893
-#define	mem_param_tws_timeout_master            	0x4894
-#define	mem_param_tws_timeout_slave             	0x4895
-#define	mem_tws_observe_wait_connect_timeout_timer	0x4896
-#define	mem_param_tws_observe_wait_connect_timeout_no_connect	0x4897
-#define	mem_param_tws_observe_wait_connect_timeout_error_disconnect	0x4898
-#define	mem_tws_slave_loss_link_listen_master_timeout_timer	0x4899
-#define	mem_param_tws_slave_loss_link_listen_master_timeout	0x489a
-#define	mem_tws_poll_slave_timer                	0x489b
-#define	mem_param_tws_poll_slave                	0x489c
-#define	mem_tws_master_wait_slave_timeout_timer 	0x489d
-#define	mem_param_tws_master_wait_slave_timeout 	0x489e
-#define	mem_tws_m2s_ack_send_timeout_count      	0x489f
-#define	mem_param_tws_m2s_ack_send_timeout      	0x48a0
-#define	mem_tws_poll_null_ack_interval          	0x48a1
-#define	mem_tws_poll_null_ack_interval_count    	0x48a2
-#define	mem_loss_match                          	0x48a3
-#define	mem_count_rcv_adv                       	0x48a5
-#define	mem_tws_adv_match                       	0x48a6
-#define	mem_tws_ack                             	0x48a7
-#define	mem_tws_count_poll                      	0x48a8
-#define	mem_tws_role_switch_in_process          	0x48aa
-#define	mem_tws_slave_wait_master_first_polling_flag	0x48ab
-#define	mem_tws_profile_connected               	0x48ac
-#define	mem_tws_profile_disconnected_after_connected	0x48ad
-#define	mem_tws_adv_count                       	0x48ae
-#define	mem_tws_adv_try_num                     	0x48af
-#define	mem_tws_snd_op                          	0x48b0
-#define	mem_tws_snd_op_nextseq                  	0x48b1
-#define	mem_tws_snd_cur_arq                     	0x48b2
-#define	mem_tws_rcv_op                          	0x48b3
-#define	mem_tws_rcv_op_nextseq                  	0x48b4
-#define	mem_tws_rcv_old_seq                     	0x48b5
-#define	mem_tws_cmd_fifo                        	0x48b6
-#define	mem_tws_no_connect_cmd_trans_limit      	0x48bb
-#define	mem_tws_no_connect_cmd                  	0x48bc
-#define	mem_tws_is_slave_send                   	0x48bd
-#define	mem_tws_is_need_send_header             	0x48be
-#define	mem_tws_remote_version                  	0x48bf
-#define	mem_param_tws_tx_power                  	0x48c1
-#define	mem_le_tws_scan_interval_min            	0x48c2
-#define	mem_le_tws_scan_interval_max            	0x48c4
-#define	mem_le_tws_scan_interval                	0x48c6
-#define	mem_le_tws_scan_window                  	0x48c8
-#define	mem_le_tws_adv_interval                 	0x48ca
-#define	mem_param_le_tws_adv_interval_normal    	0x48cc
-#define	mem_param_le_tws_adv_interval_master_listen	0x48ce
-#define	mem_tws_first_packet_dynamic_buffer     	0x48d0
-#define	mem_tws_first_packet_dynamic_buffer_status	0x48d0
-#define	mem_tws_first_packet_dynamic_buffer_local_bdaddr	0x48d2
-#define	mem_tws_first_packet_dynamic_buffer_paired_bdaddr	0x48d8
-#define	mem_tws_first_packet_dynamic_buffer_reserved	0x48de
-#define	mem_tws_allow_pairing                   	0x48ee
-#define	mem_tws_last_paired_lap                 	0x48ef
-#define	mem_tws_rf_start_anchor                 	0x48f5
-#define	mem_tws_rf_rcv_window_size              	0x48f7
-#define	mem_tws_rf_packet_rx_window_size        	0x48f9
-#define	mem_tws_rf_slave_send_full_packet_sleep_time	0x48fb
-#define	mem_tws_rf_master_check_raw_id_time     	0x48fd
-#define	mem_temp_rf_freq_index                  	0x48ff
-#define	mem_temp_rf_switch_flag                 	0x4900
-#define	mem_tws_buffer_master_switch            	0x4901
-#define	mem_tws_buffer_master_switch_reason     	0x4901
-#define	mem_process_sync_buffer                 	0x4902
-#define	mem_process_a2dp_seq_num                	0x4902
-#define	mem_process_clk                         	0x4904
-#define	mem_process_clkrt                       	0x4908
-#define	mem_process_used_buffer_size            	0x490a
-#define	mem_process_audio_vol                   	0x490c
-#define	mem_process_sync_receive_buffer         	0x490d
-#define	mem_process_receive_a2dp_seq_num        	0x490d
-#define	mem_process_receive_clk                 	0x490f
-#define	mem_process_receive_clkrt               	0x4913
-#define	mem_process_receive_used_buffer_size    	0x4915
-#define	mem_process_receive_audio_vol           	0x4917
-#define	mem_enable_hfp_start_sync               	0x4918
-#define	mem_hfp_start_sync_buffer               	0x4919
-#define	mem_hfp_start_sync_clk                  	0x4919
-#define	mem_param_tws_send_channel_array        	0x491d
-#define	mem_tws_last_send_channel_index         	0x4921
-#define	mem_save_state                          	0x4922
-#define	mem_white_list                          	0x4923
-#define	mem_remote_rx_max_octets                	0x4953
-#define	mem_remote_rx_max_time                  	0x4955
-#define	mem_remote_tx_max_octets                	0x4957
-#define	mem_remote_tx_max_time                  	0x4959
-#define	mem_local_rx_max_octets                 	0x495b
-#define	mem_local_rx_max_time                   	0x495d
-#define	mem_local_tx_max_octets                 	0x495f
-#define	mem_local_tx_max_time                   	0x4961
-#define	mem_remote_reserve                      	0x4963
-#define	mem_sequence_number_rx                  	0x49f3
-#define	mem_sequence_number_tx                  	0x49f4
-#define	mem_msbc_pcm_in_wptr                    	0x49f5
-#define	mem_msbc_pcm_in_rptr                    	0x49f7
-#define	mem_msbc_out_wptr                       	0x49f9
-#define	mem_msbc_out_rptr                       	0x49fb
-#define	mem_msbc_in_wptr                        	0x49fd
-#define	mem_msbc_in_rptr                        	0x49ff
-#define	mem_msbc_pcm_out_saddr                  	0x4a01
-#define	mem_msbc_pcm_out_wptr                   	0x4a03
-#define	mem_msbc_pcm_out_rptr                   	0x4a05
-#define	mem_msbc_packet_len                     	0x4a07
-#define	mem_msbc_pcm_packet_len                 	0x4a09
-#define	mem_msbc_enc_dec_bt_lock                	0x4a0b
-#define	mem_msbc_enc_dec_m0_lock                	0x4a0c
-#define	mem_msbc_adc_start_send                 	0x4a0d
-#define	mem_vp_language                         	0x4a0e
-#define	mem_vp_play_phonenumber                 	0x4a0f
-#define	mem_vp_mram_flag                        	0x4a10
-#define	mem_vp_addr_temp                        	0x4a11
-#define	mem_vp_enable                           	0x4a14
-#define	mem_vp_dac_addr                         	0x4a15
-#define	mem_vp_dac_half                         	0x4a17
-#define	mem_vp_play_block_num                   	0x4a19
-#define	mem_vp_offset                           	0x4a1a
-#define	mem_vp_start_addr                       	0x4a1c
-#define	mem_vp_end_addr                         	0x4a1f
-#define	mem_vp_play_by_cmd                      	0x4a22
-#define	mem_vp_play_addr_offset_temp            	0x4a23
-#define	mem_param_tishi_start_addr              	0x4a24
-#define	mem_nv_le_data                          	0x4a26
-#define	mem_vp_addr                             	0x4a26
-#define	mem_vp_end                              	0x4ab6
-#define	mem_ota_notify_handle                   	0x4ab6
-#define	mem_ota_write_handle                    	0x4ab7
-#define	mem_ota_version                         	0x4ab8
-#define	mem_ota_buck_size                       	0x4aba
-#define	mem_ota_packet_max_len                  	0x4abc
-#define	mem_ota_work_mode                       	0x4abe
-#define	mem_adc_start_addr                      	0x4abf
-#define	mem_adc_buf_size                        	0x4ac1
-#define	mem_dac_start_addr                      	0x4ac3
-#define	mem_dac_buf_size                        	0x4ac5
-#define	mem_dac_clk                             	0x4ac7
-#define	mem_dac_mram_flag                       	0x4ac8
-#define	mem_adc_mram_flag                       	0x4ac9
-#define	mem_mono_flag                           	0x4aca
-#define	mem_l_din_sel                           	0x4acb
-#define	mem_r_din_sel                           	0x4acc
-#define	mem_eq_flag                             	0x4acd
-#define	mem_acl_credits                         	0x4ace
-#define	mem_allow_switch                        	0x4ad0
-#define	mem_hci_acl_queue_start                 	0x4ad1
-#define	mem_hci_wake_clk                        	0x4ad5
-#define	mem_nv_data                             	0x4ace
-#define	mem_nv_data0                            	0x4ace
-#define	mem_nv_data1                            	0x4ae6
-#define	mem_nv_data2                            	0x4afe
-#define	mem_nv_data3                            	0x4b16
-#define	mem_nv_data4                            	0x4b2e
-#define	mem_battery_vol                         	0x4b46
-#define	mem_coef_base_addr                      	0x4b47
-#define	mem_ipc_tx_buf                          	0x4b4a
-#define	mem_le_att_list                         	0x4bae
-#define	mem_tws_fac_adv_name                    	0x4bb0
-#define	mem_param_bt_tx_power                   	0x4bcc
-#define	mem_leadv_action                        	0x4bcd
-#define	mem_hibernate_flag                      	0x4bce
-#define	mem_lpm_write_temp_adc_low              	0x4bcf
-#define	mem_lpm_write_temp_adc_high             	0x4bd3
-#define	mem_lpm_write_temp_charge_control       	0x4bd7
-#define	mem_lpm_write_temp_charge_wakeup_low_active	0x4bdb
-#define	mem_lpm_write_temp_charge_wakeup_high_active	0x4bdd
-#define	mem_efuse_dc_offset                     	0x4bdf
-#define	mem_efuse_dc_offset_l                   	0x4bdf
-#define	mem_efuse_dc_offset_r                   	0x4be1
-#define	mem_efuse_dc_offset_f6                  	0x4be3
-#define	mem_efuse_dc_offset_l_f6                	0x4be3
-#define	mem_efuse_dc_offset_r_f6                	0x4be5
-#define	mem_efuse_adc_offset                    	0x4be7
-#define	mem_0_5_adc_io_data                     	0x4be7
-#define	mem_3v_adc_hvin_data                    	0x4be9
-#define	mem_1v_adc_io_data                      	0x4beb
-#define	mem_5v_adc_hvin_data                    	0x4bed
-#define	mem_xlmp_conn_state                     	0x4bef
-#define	mem_xlmp_clock_offset_valid             	0x4bf0
-#define	mem_rf_power_fix                        	0x4bf1
-#define	mem_ipc_rx_ptr                          	0x4bf2
-#define	mem_module_le_rx_data_len               	0x4bf5
-#define	mem_module_le_rx_data_address           	0x4bf6
-#define	mem_module_le_rx_data_handle            	0x4bf8
-#define	mem_module_data_write_handle            	0x4bfa
-#define	mem_module_data_write_handle2           	0x4bfc
-#define	mem_module_flag                         	0x4bfe
-#define	mem_module_hci_notify_len               	0x4bff
-#define	mem_module_hci_notify_handle            	0x4c00
-#define	mem_module_hci_nofiy_addr               	0x4c02
-#define	mem_last_transmite_clock                	0x4c04
-#define	mem_module_le_att_list                  	0x4c08
-#define	mem_module_le_att_list_end              	0x4c09
-#define	mem_le_disconnect_reason                	0x4c09
-#define	mem_mesh_le_features                    	0x4c0a
-#define	mem_mesh_le_version                     	0x4c12
-#define	mem_mesh_le_version_exchange_times      	0x4c17
-#define	mem_mesh_hci_opcode_ocf                 	0x4c18
-#define	mem_mesh_hci_opcode_ogf                 	0x4c1a
-#define	mem_mesh_hci_cmd_len                    	0x4c1b
-#define	mem_mesh_event_mask                     	0x4c1c
-#define	mem_mesh_read_local_version_info        	0x4c24
-#define	mem_mesh_read_local_version_info_hci_version	0x4c24
-#define	mem_mesh_read_local_version_info_hci_revision	0x4c25
-#define	mem_mesh_read_local_version_info_lmp_version	0x4c27
-#define	mem_mesh_read_local_version_info_manufacturer	0x4c28
-#define	mem_mesh_read_local_version_info_lmp_subversion	0x4c2a
-#define	mem_mesh_read_local_support_command     	0x4c2c
-#define	mem_mesh_le_event_mask                  	0x4c6c
-#define	mem_mesh_le_public_address              	0x4c74
-#define	mem_mesh_le_random_address              	0x4c7a
-#define	mem_mesh_vendor_tx_flag                 	0x4c80
-#define	mem_mesh_vendor_tx_freq                 	0x4c81
-#define	mem_mesh_vendor_tx_data                 	0x4c82
-#define	mem_mesh_vendor_tx_power_calibration    	0x4c83
-#define	mem_mesh_vendor_rx_flag                 	0x4c84
-#define	mem_mesh_vendor_rx_freq                 	0x4c85
-#define	mem_mesh_event_head_type                	0x4c86
-#define	mem_mesh_event_head_event_code          	0x4c87
-#define	mem_mesh_event_para_total_length        	0x4c88
-#define	mem_mesh_event_parameter_rtn            	0x4c89
-#define	mem_mesh_event_parameter_status         	0x4c8a
-#define	mem_mesh_creat_connection_flag          	0x4c8b
-#define	mem_mesh_recevie_acl_packet_number      	0x4c8c
-#define	mem_device_public_address               	0x4c8d
-#define	mem_mesh_command_complete_num_hci_command_packet	0x4c93
-#define	mem_mesh_command_complete_command_opcode	0x4c94
-#define	mem_mesh_hci_opcode                     	0x4c94
-#define	mem_mesh_command_complete_return_parameter_status	0x4c96
-#define	mem_simple_pairing_mode                 	0x4c97
-#define	mem_fec_required                        	0x4c98
-#define	mem_inquiry_num_responses               	0x4c99
-#define	mem_inquiry_num_check                   	0x4c9a
-#define	mem_conn_status                         	0x4c9b
-#define	mem_inquiry_mode                        	0x4c9c
-#define	mem_inquiry_eir_data                    	0x4c9d
-#define	mem_io_cap_flag                         	0x4c9f
-#define	mem_page_scan_repetition_mode           	0x4ca0
-#define	mem_conn_req_status                     	0x4ca1
-#define	mem_alloc_normal_block                  	0x4ca2
-#define	mem_alloc_normal_header                 	0x4ca2
-#define	mem_alloc_normal_rptr                   	0x4ca4
-#define	mem_alloc_normal_wptr                   	0x4ca6
-#define	mem_alloc_normal_end                    	0x4ca8
-#define	mem_alloc_normal_total_size             	0x4caa
-#define	mem_alloc_normal_cur_len                	0x4cab
-#define	mem_alloc_normal_block_start            	0x4cac
-#define	mem_alloc_big_block                     	0x4cca
-#define	mem_alloc_big_header                    	0x4cca
-#define	mem_alloc_big_rptr                      	0x4ccc
-#define	mem_alloc_big_wptr                      	0x4cce
-#define	mem_alloc_big_end                       	0x4cd0
-#define	mem_alloc_big_total_size                	0x4cd2
-#define	mem_alloc_big_cur_len                   	0x4cd3
-#define	mem_alloc_big_block_start               	0x4cd4
-#define	mem_normal_block_ptr_list               	0x4cf2
-#define	mem_big_block_ptr_list                  	0x4d10
-#define	mem_rcv_br_queue_ptr                    	0x4d2e
-#define	mem_rcv_ble_queue_ptr                   	0x4d31
-#define	mem_snd_br_block                        	0x4d34
-#define	mem_snd_br_header                       	0x4d34
-#define	mem_snd_br_rptr                         	0x4d36
-#define	mem_snd_br_wptr                         	0x4d38
-#define	mem_snd_br_end                          	0x4d3a
-#define	mem_snd_br_total_size                   	0x4d3c
-#define	mem_snd_br_cur_len                      	0x4d3d
-#define	mem_snd_br_block_start                  	0x4d3e
-#define	mem_snd_ble_block                       	0x4d5c
-#define	mem_snd_ble_header                      	0x4d5c
-#define	mem_snd_ble_rptr                        	0x4d5e
-#define	mem_snd_ble_wptr                        	0x4d60
-#define	mem_snd_ble_end                         	0x4d62
-#define	mem_snd_ble_total_size                  	0x4d64
-#define	mem_snd_ble_cur_len                     	0x4d65
-#define	mem_snd_ble_block_start                 	0x4d66
-#define	mem_snd_hci_block                       	0x4d84
-#define	mem_snd_hci_header                      	0x4d84
-#define	mem_snd_hci_rptr                        	0x4d86
-#define	mem_snd_hci_wptr                        	0x4d88
-#define	mem_snd_hci_end                         	0x4d8a
-#define	mem_snd_hci_total_size                  	0x4d8c
-#define	mem_snd_hci_cur_len                     	0x4d8e
-#define	mem_snd_hci_block_start                 	0x4d8f
-#define	mem_regd                                	0x4dad
-#define	mem_alloc_buffer_len                    	0x4db1
-#define	mem_temp_alloc_big_malloc_cnt           	0x4db3
-#define	mem_temp_alloc_normal_malloc_cnt        	0x4db5
-#define	mem_temp_send_br_malloc_cnt             	0x4db7
-#define	mem_temp_media_malloc_cnt               	0x4db9
-#define	mem_temp_lcp_malloc_cnt                 	0x4dbb
-#define	mem_temp_sco_rx_malloc_cnt              	0x4dbd
-#define	mem_temp_sco_tx_malloc_cnt              	0x4dbf
-#define	mem_temp_alloc_big_free_cnt             	0x4dc1
-#define	mem_temp_alloc_normal_free_cnt          	0x4dc3
-#define	mem_temp_send_br_free_cnt               	0x4dc5
-#define	mem_temp_media_free_cnt                 	0x4dc7
-#define	mem_temp_lcp_free_cnt                   	0x4dc9
-#define	mem_temp_sco_rx_free_cnt                	0x4dcb
-#define	mem_temp_sco_tx_free_cnt                	0x4dcd
-#define	mem_param_alloc_normal_buffer_start_address	0x4dcf
-#define	mem_param_alloc_normal_buffer_max_length	0x4dd1
-#define	mem_param_alloc_big_buffer_start_address	0x4dd3
-#define	mem_param_alloc_big_buffer_max_length   	0x4dd5
-#define	mem_ipc_data_rx_buf_subtype             	0x4dd7
-#define	mem_ipc_data_rx_buf_payload_ptr         	0x4dd8
-#define	mem_ipc_data_tx_buf_subtype             	0x4ddb
-#define	mem_ipc_data_tx_buf_payload_ptr         	0x4ddc
-#define	mem_le_features                         	0x4ddf
-#define	mem_le_supported_host                   	0x4de7
-#define	mem_simultaneous_le_host                	0x4de8
-#define	mem_default_link_policy_settings        	0x4de9
-#define	mem_link_policy_settings                	0x4deb
-#define	mem_le_white_list_cnt                   	0x4ded
-#define	mem_le_white_list                       	0x4dee
-#define	mem_le_white_list_type_and_bd_addr      	0x4e0a
-#define	mem_le_white_list_filter_policy         	0x4e11
-#define	mem_hci_acl_packet_pb_flag              	0x4e12
-#define	mem_hci_acl_packet_len_recved           	0x4e13
-#define	mem_hci_acl_packet_payload_ptr          	0x4e15
-#define	mem_le_first_packet_count               	0x4e17
-#define	mem_hci_record_disc_conn_handle         	0x4e18
-#define	mem_fsc_rtk_host                        	0x4e19
-#define	mem_remote_features                     	0x4e1a
-#define	mem_remote_ext_features0                	0x4e22
-#define	mem_remote_ext_features1                	0x4e2a
-#define	mem_le_scan_window_temp                 	0x4e32
-#define	mem_zcode_buff_user                     	0x4e34
-#define	mem_queue_init_flag                     	0x4f34
-#define	mem_hci_version_svnid                   	0x4f35
-#define	mem_bd_addr_new                         	0x4f37
-#define	mem_efuse_encryp_data                   	0x4f3d
-#define	mem_encryp_inital_value                 	0x4f5d
-#define	mem_encryp_param                        	0x4f5f
-#define	mem_encryp_count                        	0x4f61
-#define	mem_qspi_lock_flag_cm0                  	0x4f62
-#define	mem_qspi_lock_flag_respin               	0x4f63
-#define	mem_qspi_lock_victim                    	0x4f64
-#define	mem_efuse_64_bytes                      	0x4f65
-#define	mem_check_attempt_limit                 	0x4fa5
-#define	mem_hci_remote_name_req_flag            	0x4fa6
-#define	mem_hci_remote_name                     	0x4fa7
-#define	mem_le_wait_process_cmd                 	0x4fe7
-#define	mem_loopcnt                             	0x4fe8
-#define	mem_le_master_sm                        	0x4fea
-#define	mem_headset_end                         	0x4feb
-#define	mem_usb_mouse_data                      	0x4ace
-#define	mem_usb_kb_data                         	0x4ade
-#define	mem_usb_kb_multikey                     	0x4aee
-#define	mem_usb0_get_report_data                	0x4afe
-#define	mem_mcmd                                	0xff0
-#define	mem_mouse_data                          	0xff1
-#define	L2CAP_ONE_RXBUFF_LENTH_NEW              	0x266
-#define	L2CAP_ONE_RXBUFF_LENTH                  	0x300
-#define	L2CAP_NORMAL_BUFF_CNT                   	//0x01
-#define	L2CAP_NORMAL_BUFF_LENTH                 	//0x0083
-#define	L2CAP_NORMAL_BUFF_START_ADDR            	//0x2000
-#define	L2CAP_BIG_BUFF_CNT                      	//0x09
-#define	L2CAP_BIG_BUFF_LENTH                    	//0x2b0
-#define	L2CAP_BIG_BUFF_LENTH_BLE                	//0x200
-#define	L2CAP_BIG_BUFF_LENTH_CLASSIC            	//0x2b0
-#define	L2CAP_BIG_BUFF_START_ADDR               	//0x2200
-#define	mem_l2cap_rxbuff1                       	0x1400
-#define	mem_l2cap_rxbuff2                       	0x1700
-#define	mem_l2cap_rxbuff3                       	0x1a00
-#define	mem_l2cap_rxbuff4                       	0x1d00
-#define	mem_tx_buff0                            	0x1000
-#define	mem_tx_buff1                            	0x1080
-#define	mem_tx_buff2                            	0x1100
-#define	mem_tx_buff3                            	0x1180
-#define	mem_tx_buff4                            	0x1200
-#define	mem_tx_buff5                            	0x1280
-#define	mem_tx_buff6                            	0x1300
-#define	mem_tx_buff7                            	0x1380
-#define	mem_le_tx_buffer0                       	0x1c00
-#define	mem_le_tx_buffer1                       	0x1c80
-#define	mem_le_tx_buffer2                       	0x1d00
-#define	mem_le_tx_buffer3                       	0x1d80
-#define	mem_le_txheader_temp                    	0x1000
-#define	mem_le_txlen_temp                       	0x1001
-#define	mem_le_txpayload_temp                   	0x1002
-#define	mem_le_txcid_temp                       	0x1004
-#define	mem_le_l2cap_temp                       	0x1006
-#define	mem_le_l2cap_response_temp              	0x1007
-#define	mem_le_txbdy_temp                       	0x1008
-#define	mem_h5rx_buf                            	0x1e00
-#define	mem_h5rx_buf_end                        	0x1eff
-#define	mem_h5tx_buf                            	0x1f00
-#define	mem_h5tx_buf_end                        	0x1fff
-#define	DEBUG_LOG_INITIAL_SUCCESS_FLAG          	0x5f
-#define	DEBUG_LOG_LOCK_VICTIM_CM0               	0x35
-#define	DEBUG_LOG_LOCK_VICTIM_RESPIN            	0x53
-#define	IPC_DATA_SUBTYPE_FREE                   	0x00
-#define	IPC_DATA_SUBTYPE_BLE                    	0x01
-#define	IPC_DATA_SUBTYPE_SPP                    	0x02
-#define	IPC_DATA_SUBTYPE_HCI                    	0x03
-#define	IPC_DATA_SUBTYPE_ACL_BLE                	0x04
-#define	IPC_DATA_SUBTYPE_ACL_CLASSIC            	0x05
-#define	IPC_TYPE_CMD                            	0x01
-#define	IPC_TYPE_EVT                            	0x02
-#define	IPC_TYPE_HID                            	0x03
-#define	IPC_TYPE_SPP                            	0x04
-#define	IPC_TYPE_BLE                            	0x05
-#define	IPC_TYPE_24G                            	0x06
-#define	IPC_TYPE_MESH                           	0x07
-#define	IPC_TYPE_ADV                            	0x08
-#define	IPC_TYPE_SCAN                           	0x09
-#define	IPC_TYPE_BT_TO_CM0_DATA                 	0x0a
-#define	IPC_TYPE_CM0_TO_BT_DATA                 	0x0b
-#define	IPC_TYPE_A2DP                           	0x0a
-#define	IPC_TYPE_HFP                            	0x0b
-#define	IPC_TYPE_TWS                            	0x0c
-#define	IPC_TYPE_HCI                            	0x0d
-#define	QSPI_LOCK_VICTIM_CM0                    	0x35
-#define	QSPI_LOCK_VICTIM_RESPIN                 	0x53
-#define	MSBC_PCM_IN_BUFFER_ADDR                 	0x2000
-#define	MSBC_OUT_BUFFER_ADDR                    	0x2800
-#define	MSBC_IN_BUFFER_ADDR                     	0x3000
-#define	MSBC_PCM_OUT_BUFFER_ADDR                	0x3800
-#define	MSBC_PACKET_LEN                         	0x39
-#define	MSBC_PCM_PACKET_LEN                     	0xF0
-#define	MSBC_PACKET_MAX_LEN                     	0x1c8
-#define	MSBC_PCM_MAX_PACKET_LEN                 	0x780
-#define	MSBC_ENCODE_BUF_ADDRESS                 	0x2c00
-#define	MSBC_DECODE_BUF_ADDRESS                 	0x3400
-#define	MSBC_BUF_LENTH                          	0x400
-#define	MSBC_NEW_DAC_48K_START_ADDR             	0x2000
-#define	MSBC_NEW_DAC_8K_START_ADDR              	//0xB800
-#define	MSBC_NEW_ADC_8K_START_ADDR              	0xb640
-#define	MSBC_NEW_CACHE_START_ADDR               	0xC540
-#define	MSBC_NEW_DECODE_CACHE_START_ADDR        	0xC940
-#define	MSBC_NEW_PCM_MAX_BUFFER_LEN             	0xF00
-#define	MSBC_NEW_DAC_48K_MAX_BUFFER_LEN         	0x2000
-#define	PNP_PROFILE                             	0x00
-#define	AVCTP_PROFILE                           	0x01
-#define	AVRCP_TARGET_PROFILE                    	0x02
-#define	AVRCP_CONTROL_PROFILE                   	0x03
-#define	HFP_PROFILE                             	0x04
-#define	HSP_PROFILE                             	0x05
-#define	HID_PROFILE                             	0x06
-#define	AAP_PROFILE                             	0x07
-#define	SPP_PROFILE                             	0x08
-#define	NUM_PROFILE                             	0x09
-#define	LED_REPEAT_FORERVER                     	0xff
-#define	BUTTON_GPIO_DISABLE                     	0XFF
-#define	BUTTON_LONGPRESS                        	0xff
-#define	BT_CMD_STANDBY                          	0x00
-#define	BT_CMD_START_DISCOVERY                  	0x01
-#define	BT_CMD_STOP_DISCOVERY                   	0x02
-#define	BT_CMD_RECONNECT                        	0x03
-#define	BT_CMD_DISCONNECT                       	0x04
-#define	BT_CMD_ENTER_SNIFF                      	0x05
-#define	BT_CMD_EXIT_SNIFF                       	0x06
-#define	BT_CMD_ENTER_SNIFF_SUBRATING            	0x07
-#define	BT_CMD_EXIT_SNIFF_SUBRATING             	0x08
-#define	BT_CMD_SNIFF_TEST                       	0x09
-#define	BT_CMD_SET_PIN_CODE                     	0x0a
-#define	BT_CMD_START_INQUIRY                    	0x0b
-#define	BT_CMD_STOP_INQUIRY                     	0x0c
-#define	BT_CMD_START_ADV                        	0x0d
-#define	BT_CMD_STOP_ADV                         	0x0e
-#define	BT_CMD_START_DIRECT_ADV                 	0x0f
-#define	BT_CMD_STOP_DIRECT_ADV                  	0x10
-#define	BT_CMD_LE_DISCONNECT                    	0x11
-#define	BT_CMD_LE_UPDATE_CONN                   	0x12
-#define	BT_CMD_LE_MASTER_UPDATE_CONN            	0x13
-#define	BT_CMD_LE_START_CONN                    	0x16
-#define	BT_CMD_LE_START_SCAN                    	0x17
-#define	BT_CMD_LE_STOP_SCAN                     	0x18
-#define	BT_CMD_ENTER_HIBERNATE                  	0x19
-#define	BT_CMD_LE_SMP_SECURITY_REQUEST          	0x1b
-#define	BT_CMD_LE_START_WRITE                   	0x1c
-#define	BT_CMD_ROLE_SWITCH                      	0x1d
-#define	BT_CMD_BB_RECONN_CANCEL                 	0x1e
-#define	BT_CMD_STORE_RECONN_INFO_LE             	0x1f
-#define	BT_CMD_STORE_RECONN_INFO_BT             	0x20
-#define	BT_CMD_MTU_EXCHANGE                     	0x21
-#define	BT_CMD_DHKEY_NOT_ACCEPT                 	0x22
-#define	BT_CMD_EST_ESCO_REQ                     	0x23
-#define	BT_CMD_RMV_ESCO_REQ                     	0x24
-#define	BT_CMD_EST_SCO_REQ                      	0x25
-#define	BT_CMD_RMV_SCO_REQ                      	0x26
-#define	BT_CMD_LOAD_FLASH_PARAMS                	0x2d
-#define	BT_CMD_INCREASE_POWER_REQ               	0x2e
-#define	BT_CMD_READ_RESPONSE_READY              	0x2f
-#define	BT_CMD_LE_DATA_LEGNTH_REQ               	0x30
-#define	BT_CMD_PLAY_PAUSE                       	0x32
-#define	BT_CMD_BACKWARD                         	0x33
-#define	BT_CMD_FORWARD                          	0x34
-#define	BT_CMD_VOL_UP                           	0x35
-#define	BT_CMD_VOL_DOWN                         	0x36
-#define	BT_CMD_ACCEPT_CALL                      	0x37
-#define	BT_CMD_HANG_UP                          	0x38
-#define	BT_CMD_REDIAL                           	0x39
-#define	BT_CMD_RECOGNITION                      	0x3a
-#define	BT_CMD_PLAY_VP                          	0x3b
-#define	BT_CMD_PLAY_TISHI_VP                    	0x3c
-#define	BT_CMD_RECOGNITION_STOP                 	0x3d
-#define	BT_CMD_ThreeWay_ReleaseAll              	0x3e
-#define	BT_CMD_ThreeWay_ReleaseNAcp             	0x3f
-#define	BT_CMD_ThreeWay_HoldNAcp                	0x31
-#define	BT_CMD_ENTER_TWS_PAIR                   	0x40
-#define	BT_CMD_EXIT_TWS_PAIR                    	0x41
-#define	BT_CMD_START_RECON_TWS                  	0x42
-#define	BT_CMD_STOP_RECON_TWS                   	0x43
-#define	BT_CMD_START_WAIT_MASTER                	0x44
-#define	BT_CMD_STOP_WAIT_MASTER                 	0x45
-#define	BT_CMD_START_WAIT_SLAVE                 	0x46
-#define	BT_CMD_STOP_WAIT_SLAVE                  	0x47
-#define	BT_CMD_TWS_NONE                         	0x48
-#define	TWS_SYNC_CMD_START                      	0x4f
-#define	TWS_SYNC_CMD_IND_0                      	0x50
-#define	TWS_SYNC_CMD_IND_1                      	0x51
-#define	TWS_SYNC_CMD_IND_2                      	0x52
-#define	TWS_SYNC_CMD_IND_3                      	0x53
-#define	TWS_SYNC_CMD_FIX_VOICE_PLAY             	0x5d
-#define	TWS_SYNC_CMD_EAR_DETECT_ON              	0x5e
-#define	TWS_SYNC_CMD_EAR_DETECT_OFF             	0x5f
-#define	TWS_SYNC_CMD_POWR_OFF                   	0x60
-#define	TWS_SYNC_CMD_MASTER_SWITCH              	0x61
-#define	TWS_SYNC_CMD_POLLING                    	0x62
-#define	TWS_SYNC_CMD_USER1                      	0x63
-#define	TWS_SYNC_CMD_USER2                      	0x64
-#define	TWS_SYNC_CMD_USER3                      	0x65
-#define	TWS_SYNC_CMD_USER4                      	0x66
-#define	TWS_SYNC_CMD_USER5                      	0x67
-#define	TWS_SYNC_CMD_RESET_AUDIO                	0x68
-#define	TWS_SYNC_CMD_SLAVE_RESET_AUDIO          	0x69
-#define	TWS_SYNC_CMD_AUDIO_PROCESS_INFO         	0x6A
-#define	TWS_SYNC_CMD_HFP_START_SYNC             	0x6B
-#define	TWS_SYNC_CMD_HFP_SLVAE_START_SYNC       	0x6C
-#define	TWS_SYNC_CMD_ALL_PROFILE_DISCONNECTED   	0x6D
-#define	TWS_SYNC_CMD_DROP_ONE_PACKET            	0x6E
-#define	TWS_SYNC_CMD_AUTO_POWR_OFF              	0x6F
-#define	TWS_SYNC_CMD_ENTER_FAST_SYNC            	0x70
-#define	TWS_SYNC_CMD_EXIT_FAST_SYNC             	0x71
-#define	TWS_SYNC_CMD_ADD_ONE_PACKET             	0x72
-#define	TWS_SYNC_CMD_SLAVE_IN_STORAGE           	0x73
-#define	TWS_SYNC_CMD_USER6                      	0x74
-#define	TWS_SYNC_CMD_USER7                      	0x75
-#define	TWS_SYNC_CMD_OAL_CALL                   	0x76
-#define	TWS_SYNC_CMD_OAL_NOCALL                 	0x77
-#define	TWS_SYNC_CMD_OAL_MUSIC_PLAY             	0x78
-#define	TWS_SYNC_CMD_OAL_MUSIC_PAUSE            	0x79
-#define	TWS_SYNC_CMD_OAL_LAST_MUSIC             	0x7a
-#define	TWS_SYNC_CMD_OAL_NEXT_MUSIC             	0x7b
-#define	TWS_SYNC_CMD_OAL_ADD_VOL                	0x7c
-#define	TWS_SYNC_CMD_OAL_SUB_VOL                	0x7d
-#define	TWS_SYNC_CMD_END                        	0x7f
-#define	BT_CMD_LOAD_INFO                        	0x80
-#define	BT_CMD_RECOVER_AUDIO                    	0x81
-#define	BT_CMD_REPORT_BAT                       	0x82
-#define	BT_CMD_ENABLE_SNIFF_MUL                 	0x84
-#define	BT_CMD_DISABLE_SNIFF_MUL                	0x85
-#define	BT_CMD_BT_DISCONNECT                    	0x86
-#define	BT_CMD_RESET_M0_CLK                     	0x87
-#define	BT_CMD_HFP_INDICATORS_UPDATE            	0x88
-#define	BT_CMD_RECONNECT_AVDTP                  	0x89
-#define	TWS_SYNC_CMD_SWITCH_TO_MASTER           	0x8a
-#define	TWS_SYNC_CMD_ACCPET_SWITCH              	0x8b
-#define	BT_CMD_CHARGE_STOP_POWEROFF             	0X8c
-#define	BT_CMD_CHARGE_DISCONNECT                	0x8d
-#define	TWS_SYNC_CMD_WAIT_TWS_SLAVE             	0x8e
-#define	BT_CMD_VP_END_RECOVER_DAC               	0x8f
-#define	BT_CMD_CHARGE_POWER_OFF                 	0x90
-#define	BT_CMD_OTA_RESET                        	0x91
-#define	BT_CMD_OTA_SWITCH                       	0x92
-#define	BT_CMD_CHARGE_INSCENB                   	0x93
-#define	BT_CMD_CHARGE_INSCENB_CLEAR             	0x94
-#define	BT_CMD_SHUTDOWN_QSPI                    	0x95
-#define	BT_CMD_MSR_TEMP                         	0x96
-#define	BT_CMD_UPDATE_WAKEUP                    	0x97
-#define	BT_CMD_BATVALUE                         	0x98
-#define	BT_CMD_EnterTestMode                    	0x99
-#define	BT_CMD_ExitTestMode                     	0x9a
-#define	BT_CMD_TestPlay                         	0x9b
-#define	BT_CMD_TetstPause                       	0x9c
-#define	BT_CMD_TestEnterSCO                     	0x9d
-#define	BT_CMD_TestExitSCO                      	0x9e
-#define	TWS_NO_CONNECT_TRANS_CMD_START          	0xa0
-#define	TWS_NO_CONNECT_TRANS_CMD_POWER_OFF      	0xa1
-#define	TWS_NO_CONNECT_TRANS_CMD_IN_STORE       	0xa2
-#define	TWS_NO_CONNECT_TRANS_CMD_CHANGE_LANGUAGE_EN	0xa3
-#define	TWS_NO_CONNECT_TRANS_CMD_CHANGE_LANGUAGE_CH	0xa4
-#define	TWS_NO_CONNECT_TRANS_CMD_SWITCH_OAL_ON  	0xa5
-#define	TWS_NO_CONNECT_TRANS_CMD_SWITCH_OAL_OFF 	0xa6
-#define	TWS_NO_CONNECT_TRANS_CMD_END            	0xaf
-#define	BT_CMD_SET_POWER_ON_FLAG                	0xb0
-#define	BT_CMD_ENABLE_LE_LATENCY                	0xb1
-#define	BT_CMD_DISABLE_LE_LATENCY               	0xb2
-#define	BT_CMD_FREQ_CHECK                       	0xb3
-#define	BT_CMD_PLAY                             	0xb4
-#define	BT_CMD_PAUSE                            	0xb5
-#define	BT_CMD_ENTER_OTA                        	0xbd
-#define	BT_CMD_EXIT_OTA                         	0xbe
-#define	BT_EVT_NULL                             	0x00
-#define	BT_EVT_BB_CONNECTED                     	0x01
-#define	BT_EVT_BB_DISCONNECTED                  	0x02
-#define	BT_EVT_RECONN_STARTED                   	0x03
-#define	BT_EVT_RECONN_FAILED                    	0x04
-#define	BT_EVT_SETUP_COMPLETE                   	0x05
-#define	BT_EVT_HID_CONNECTED                    	0x06
-#define	BT_EVT_HID_DISCONNECTED                 	0x07
-#define	BT_EVT_SPP_CONNECTED                    	0x08
-#define	BT_EVT_SPP_DISCONNECTED                 	0x09
-#define	BT_EVT_PINCODE_REQ                      	0x0A
-#define	BT_EVT_ENTER_SNIFF                      	0x0B
-#define	BT_EVT_EXIT_SNIFF                       	0x0C
-#define	BT_EVT_ENTER_SNIFF_SUB                  	0x0D
-#define	BT_EVT_EXIT_SNIFF_SUB                   	0x0E
-#define	BT_EVT_DISCOVERY_STOPED                 	0x0F
-#define	BT_EVT_BUTTON_LONG_PRESSED              	0x10
-#define	BT_EVT_START_PAGE                       	0x11
-#define	BT_EVT_HID_HANDSHAKE                    	0x12
-#define	BT_EVT_RECONN_PAGE_TIMEOUT              	0x13
-#define	BT_EVT_LE_CONNECTED                     	0x14
-#define	BT_EVT_LE_DISCONNECTED                  	0x15
-#define	BT_EVT_ML2CAP_CONN_REFUSED              	0x16
-#define	BT_EVT_BUTTON_ENTER_HIBERNATE           	0x17
-#define	BT_EVT_LINKKEY_GENERATE                 	0x18
-#define	BT_EVT_SWITCH_NOT_ACCEPT                	0x19
-#define	BT_EVT_SWITCH_ACCEPT                    	0x20
-#define	BT_EVT_SNIFF_NOT_ACCEPT                 	0x21
-#define	BT_EVT_SNIFF_ACCEPT                     	0x22
-#define	BT_EVT_UNSNIFF_ACCEPT                   	0x23
-#define	BT_EVT_UNSNIFF_NOT_ACCEPT               	0x24
-#define	BT_EVT_SEND_UNSNIFF_ACCEPT              	0x26
-#define	BT_EVT_VIRTUAL_CABLE_UNPLUG             	0x27
-#define	BT_EVT_LE_WRITE_REQUEST                 	0x28
-#define	BT_EVT_LE_ENC_INFO                      	0x29
-#define	BT_EVT_SWITCH_FAIL_MASTER               	0x2a
-#define	BT_EVT_SWITCH_SUCCESS_MASTER            	0x2b
-#define	BT_EVT_BUTTON_DOWN                      	0x2c
-#define	BT_EVT_BUTTON_UP                        	0x2d
-#define	BT_EVT_REMOTE_UNSNIFF                   	0x2e
-#define	BT_EVT_LE_PAIRING_FAIL                  	0x30
-#define	BT_EVT_LE_PAIRING_SUCCESS               	0x31
-#define	BT_EVT_LE_START_ENC                     	0x32
-#define	BT_EVT_LE_PAUSE_ENC                     	0x33
-#define	BT_EVT_LE_TK_GENERATE                   	0x34
-#define	BT_EVT_BT_GKEY_GENERATE                 	0x35
-#define	BT_EVT_BT_GET_PASSKEY                   	0x36
-#define	BT_EVT_BT_PAIRING_FAIL                  	0x37
-#define	BT_EVT_BT_PAIRING_SUCCESS               	0x38
-#define	BT_EVT_BT_START_ENC                     	0x39
-#define	BT_EVT_LE_GKEY_GENERATE                 	0x3b
-#define	BT_EVT_HFP_RING                         	0x3c
-#define	BT_EVT_A2DP_OPEN                        	0x58
-#define	BT_EVT_HFP_START_DIALING                	0x59
-#define	BT_EVT_HFP_INCOMMING                    	0x5a
-#define	BT_EVT_HFP_OUTGOING                     	0x5b
-#define	BT_EVT_HFP_CALLACTIVE                   	0x5c
-#define	BT_EVT_HFP_CALLIMG                      	0x5d
-#define	BT_EVT_HFP_CALLOGG                      	0x5e
-#define	BT_EVT_HFP_CALMULTY                     	0x5f
-#define	BT_EVT_HFP_CONNECTED                    	0x60
-#define	BT_EVT_HFP_DISCONNECTED                 	0x61
-#define	BT_EVT_HFP_NONO                         	0x62
-#define	BT_EVT_HFP_UP_TO_MAX_VLM                	0x63
-#define	BT_EVT_HFP_DOWN_TO_MIN_VLM              	0x64
-#define	BT_EVT_RESET                            	0x65
-#define	BT_EVT_WAKEUP                           	0x66
-#define	BT_EVT_ENC_CONNECTED                    	0x67
-#define	BT_EVT_ENTER_DISCOVERABLE               	0x68
-#define	BT_EVT_EXIT_DISCOVERABLE                	0x69
-#define	BT_EVT_RESTART                          	0x6a
-#define	BT_EVT_DEV_UPDATE_INFO                  	0x70
-#define	BT_EVT_PROFILE_DISCONNECT               	0x71
-#define	BT_EVT_ABNORMAL_DISCONNECT              	0x72
-#define	BT_EVT_RECONNECT_RSP                    	0x73
-#define	BT_EVT_ALL_PROFILE_CONNECT              	0x74
-#define	BT_EVT_RESET_AUTO_TIMER                 	0x75
-#define	BT_EVT_PHONE_NUM                        	0x76
-#define	BT_EVT_MAX_POWER                        	0x77
-#define	BT_EVT_CLOSE_ADAC                       	0x78
-#define	BT_EVT_DISCONNECT_KEY_ERROR             	0x79
-#define	BT_EVT_DISCONNECT_KEY_MISSING           	0x7a
-#define	BT_EVT_A2DP_CONNECTED                   	0x80
-#define	BT_EVT_A2DP_DISCONNECTED                	0x81
-#define	BT_EVT_AVRCP_CONNECTED                  	0x82
-#define	BT_EVT_AVRCP_DISCONNECTED               	0x83
-#define	BT_EVT_PROFILE_DISCONNECTED             	0x84
-#define	BT_EVT_START_DAC                        	0x85
-#define	BT_EVT_STOP_DAC                         	0x86
-#define	BT_EVT_RESTART_HFP                      	0x87
-#define	BT_EVT_ENTER_TEST_MODE                  	0x88
-#define	BT_EVT_EXIT_TEST_MODE                   	0x89
-#define	BT_EVT_TEST_PLAY                        	0x8a
-#define	BT_EVT_TEST_PAUSE                       	0x8b
-#define	BT_EVT_TEST_ENTER_SCO                   	0x8c
-#define	BT_EVT_TEST_EXIT_SCO                    	0x8d
-#define	BT_EVT_TEST_ENTER_OTA                   	0x8e
-#define	BT_EVT_TEST_EXIT_OTA                    	0x8f
-#define	BT_EVT_OTA_SEND_SEITCH_REQURST          	0x90
-#define	BT_EVT_RECONN_PAGE_CANCELED             	0x91
-#define	BT_EVT_MSR_TEMP                         	0x92
-#define	BT_EVT_TWS_HFP_SYNC_START_PLAY          	0x93
-#define	BT_EVT_LE_DATA_LENGTH_CHANGE            	0x97
-#define	BT_EVT_LE_CONN_PARAM_UPDATE_COMPLETE    	0x98
-#define	BT_EVT_LE_RECEIVED_SMP_PAIRING_REQ      	0x99
-#define	BT_EVT_LE_ATT_EXCHANGE_MTU              	0x9a
-#define	BT_EVT_ENCRYPTION_CHANGE                	0x9b
-#define	BT_EVT_ATT_READ_REQUEST_HANDLE          	0x9c
-#define	BT_EVT_INDENTITYADDRESS                 	0x9d
-#define	BT_EVT_BATVALUE                         	0x9e
-#define	BT_EVT_FIRST_PWR_ON                     	0x9f
-#define	BT_EVT_VOL_CHANGE_MAP                   	0xa0
-#define	BT_EVT_100MS_UINT                       	0xE0
-#define	BT_EVT_100MS                            	0xE1
-#define	BT_EVT_200MS                            	0xE2
-#define	BT_EVT_300MS                            	0xE3
-#define	BT_EVT_400MS                            	0xE4
-#define	BT_EVT_500MS                            	0xE5
-#define	TWS_EVT_PAIR_SUCCESS                    	0x01
-#define	TWS_EVT_EXIT_PAIR                       	0x02
-#define	TWS_EVT_ENTER_PAIR                      	0x03
-#define	TWS_EVT_START_RECON                     	0x04
-#define	TWS_EVT_RECON_FAILE                     	0x05
-#define	TWS_EVT_WAIT_MASTER                     	0x06
-#define	TWS_EVT_SLAVE_CONNECTED                 	0x07
-#define	TWS_EVT_WAIT_SLAVE                      	0x08
-#define	TWS_EVT_MASTER_CONNECTED                	0x09
-#define	TWS_EVT_SLAVE_FOUND                     	0x0a
-#define	TWS_EVT_MASTER_FOUND                    	0x0b
-#define	TWS_SYNC_EVT_UPDATE_AUDIO_PROCESS_INFO  	0x0c
-#define	TWS_EVT_SLAVE_CHANGE_MASTER_NO_CON      	0x0d
-#define	TWS_EVT_SLAVE_SWITCH_MASTER_WAIT        	0x0e
-#define	TWS_EVT_TWS_NONE                        	0x0f
-#define	TWS_EVT_REMOTE_POWER_OFF                	0x10
-#define	TWS_EVT_LOCAL_POWER_OFF                 	0x11
-#define	TWS_SYNC_EVT_START                      	0x1f
-#define	TWS_SYNC_EVT_IND_0                      	0x20
-#define	TWS_SYNC_EVT_IND_1                      	0x21
-#define	TWS_SYNC_EVT_IND_2                      	0x22
-#define	TWS_SYNC_EVT_IND_3                      	0x23
-#define	TWS_SYNC_EVT_FIX_VOICE_PLAY             	0x2d
-#define	TWS_SYNC_EVT_EAR_DETECT_ON              	0x2e
-#define	TWS_SYNC_EVT_EAR_DETECT_OFF             	0x2f
-#define	TWS_SYNC_EVT_POWR_OFF                   	0x30
-#define	TWS_SYNC_EVT_MASTER_SWITCH              	0x31
-#define	TWS_SYNC_EVT_POLLING                    	0x32
-#define	TWS_SYNC_EVT_USER1                      	0x33
-#define	TWS_SYNC_EVT_USER2                      	0x34
-#define	TWS_SYNC_EVT_USER3                      	0x35
-#define	TWS_SYNC_EVT_USER4                      	0x36
-#define	TWS_SYNC_EVT_USER5                      	0x37
-#define	TWS_SYNC_EVT_RESET_AUDIO                	0x38
-#define	TWS_SYNC_EVT_SLAVE_RESET_AUDIO          	0x39
-#define	TWS_SYNC_EVT_AUDIO_PROCESS_INFO         	0x3A
-#define	TWS_SYNC_EVT_HFP_START_SYNC             	0x3B
-#define	TWS_SYNC_EVT_ALL_PROFILE_DISCONNECTED   	0x3D
-#define	TWS_SYNC_EVT_DROP_ONE_PACKET            	0x3E
-#define	TWS_SYNC_EVT_AUTO_POWR_OFF              	0x3F
-#define	TWS_SYNC_EVT_ENTER_FAST_SYNC            	0x40
-#define	TWS_SYNC_EVT_EXIT_FAST_SYNC             	0x41
-#define	TWS_SYNC_EVT_ADD_ONE_PACKET             	0x42
-#define	TWS_SYNC_EVT_SLAVE_IN_STORAGE           	0x43
-#define	TWS_SYNC_EVT_USER6                      	0x44
-#define	TWS_SYNC_EVT_USER7                      	0x45
-#define	TWS_SYNC_EVT_OAL_CALL                   	0x46
-#define	TWS_SYNC_EVT_OAL_NOCALL                 	0x47
-#define	TWS_SYNC_EVT_OAL_MUSIC_PLAY             	0x48
-#define	TWS_SYNC_EVT_OAL_MUSIC_PAUSE            	0x49
-#define	TWS_SYNC_EVT_OAL_LAST_MUSIC             	0x4a
-#define	TWS_SYNC_EVT_OAL_NEXT_MUSIC             	0x4b
-#define	TWS_SYNC_EVT_OAL_ADD_VOL                	0x4c
-#define	TWS_SYNC_EVT_OAL_SUB_VOL                	0x4d
-#define	TWS_SYNC_EVT_SLAVE_ACK                  	0x4e
-#define	TWS_SYNC_EVT_END                        	0x4f
-#define	TWS_NO_CONNECT_TRANS_EVT_START          	0x50
-#define	TWS_NO_CONNECT_TRANS_EVT_POWER_OFF      	0x51
-#define	TWS_NO_CONNECT_TRANS_EVT_IN_STORE       	0x52
-#define	TWS_NO_CONNECT_TRANS_EVT_CHANGE_LANGUAGE_EN	0x53
-#define	TWS_NO_CONNECT_TRANS_EVT_CHANGE_LANGUAGE_CH	0x54
-#define	TWS_NO_CONNECT_TRANS_EVT_SWITCH_OAL_ON  	0x55
-#define	TWS_NO_CONNECT_TRANS_EVT_SWITCH_OAL_OFF 	0x56
-#define	TWS_NO_CONNECT_TRANS_EVT_END            	0x5f
-#define	LOCAL_SCO_WORK_DONE                     	0x00
-#define	LOCAL_SCO_WORK_IN_PROCESS               	0x01
-#define	HFP_SPEAKER_MAX_VLM_MEDIA               	0x20
-#define	HFP_SPEAKER_MAX_VLM_SCO                 	0x1E
-#define	HFP_NONO                                	0x00
-#define	HFP_INCOMMING                           	0x01
-#define	HFP_OUTGOING                            	0x02
-#define	HFP_CALLACTIVE                          	0x03
-#define	HFP_CALLIMG                             	0x04
-#define	HFP_CALLOGG                             	0x05
-#define	HFP_CALMULTY                            	0x06
-#define	CODEC_TYPE_CVSD                         	0x01
-#define	CODEC_TYPE_mSBC                         	0x02
-#define	HF_STATE_WAITING_RFCOMM_CONN            	0x00
-#define	HF_STATE_HF_SEND_FEATURE                	0x01
-#define	HF_STATE_WAITING_AG_FEATURE_OK          	0x02
-#define	HF_STATE_HF_SEND_CODECS                 	0x03
-#define	HF_STATE_WAITING_CODECS_OK              	0x04
-#define	HF_STATE_HF_SEND_INDICATORS             	0x05
-#define	HF_STATE_WAITING_AG_INDICATORS_OK       	0x06
-#define	HF_STATE_HF_SEND_CURR_STATUS            	0x07
-#define	HF_STATE_WAITING_AG_STATUS_OK           	0x08
-#define	HF_STATE_HF_SEND_UPDATE_STATUS          	0x09
-#define	HF_STATE_WAITING_AG_UPDATE_STATUS_OK    	0x0a
-#define	HF_STATE_CONNECTED                      	0x0b
-#define	HF_STATE_HF_SEND_RECEIVE_INFO           	0x0c
-#define	HF_STATE_WAITING_AG_INFO                	0x0d
-#define	HF_STATE_HF_SEND_AT_CLIP                	0x0e
-#define	HF_STATE_WAITING_AT_CLIP                	0x0f
-#define	HF_STATE_HF_SEND_AT_CCWA                	0x10
-#define	HF_STATE_WAITING_AT_CCWA                	0x11
-#define	HFP_EVT_ESCO_START                      	0x01
-#define	HFP_EVT_ESCO_STOP                       	0x02
-#define	AUDIO_STATE_IDLE                        	0x00
-#define	AUDIO_STATE_WAIT_SBC                    	0x01
-#define	AUDIO_STATE_WAIT_SOFT_DMA               	0x02
-#define	AUDIO_STATE_WAIT_UPSTACK_PROCESS        	0x03
-#define	TWS_DROP_OR_ADD_PROCESS_STATE_NONE      	0x00
-#define	TWS_DROP_OR_ADD_PROCESS_STATE_INPROCESS 	0x17
-#define	TWS_DROP_OR_ADD_PROCESS_STATE_WAIT_ADD  	0x53
-#define	TWS_DROP_OR_ADD_PROCESS_STATE_WAIT_DROP 	0x54
-#define	FIRST_BUFFER_CACHE_ENABLE               	0x53
-#define	AUDIO_OUTPUT_FULLMODE                   	0x00
-#define	AUDIO_OUTPUT_TWS_SINGLE_EAR_LEFT        	0x01
-#define	AUDIO_OUTPUT_TWS_SINGLE_EAR_RIGHT       	0x02
-#define	AVDTP_PACKET_TYPE_SINGLE                	0x00
-#define	AVDTP_PACKET_TYPE_START                 	0x01
-#define	AVDTP_PACKET_TYPE_CONTINUE              	0x02
-#define	AVDTP_PACKET_TYPE_END                   	0x03
-#define	AVDTP_MESSAGE_TYPE_CMD                  	0x00
-#define	AVDTP_MESSGAE_TYPE_GENERAL_REJECT       	0x01
-#define	AVDTP_MESSGAE_TYPE_RSP_ACCEPT           	0x02
-#define	AVDTP_MESSGAE_TYPE_RSP_REJECT           	0x03
-#define	AVDTP_IDENTIFIER_DISCOVER               	0x01
-#define	AVDTP_IDENTIFIER_GET_CAPABILITIES       	0x02
-#define	AVDTP_IDENTIFIER_SET_CONFIGURATION      	0x03
-#define	AVDTP_IDENTIFIER_GET_CONFIGURATION      	0x04
-#define	AVDTP_IDENTIFIER_RECONFIGURE            	0x05
-#define	AVDTP_IDENTIFIER_OPEN                   	0x06
-#define	AVDTP_IDENTIFIER_START                  	0x07
-#define	AVDTP_IDENTIFIER_CLOSE                  	0x08
-#define	AVDTP_IDENTIFIER_SUSPEND                	0x09
-#define	AVDTP_IDENTIFIER_ABORT                  	0x0a
-#define	AVDTP_IDENTIFIER_SECURITY_CONTROL       	0x0b
-#define	AVDTP_IDENTIFIER_GET_ALL_CAPABILITIES   	0x0c
-#define	AVDTP_IDENTIFIER_DELAYREPORT            	0x0d
-#define	AVDTP_SEP1                              	0x01
-#define	AVDTP_SEP1_CONFIG                       	0x08
-#define	AVDTP_CATEGORY_MEDIA_TRANS              	0x01
-#define	AVDTP_CATEGORY_REPORTING                	0x02
-#define	AVDTP_CATEGORY_RECOVERY                 	0x03
-#define	AVDTP_CATEGORY_CONTECT_PROTECT          	0x04
-#define	AVDTP_CATEGORY_HEADER_COMPRESSION       	0x05
-#define	AVDTP_CATEGORY_MULTIPLEXING             	0x06
-#define	AVDTP_CATEGORY_MEDIA_CODEC              	0x07
-#define	AVDTP_CATEGORY_DELAY_REPORT             	0x08
-#define	AVD_CPTYPE_SCMS_T                       	0x0002
-#define	A2DP_STATE_OPEN                         	0x01
-#define	A2DP_STATE_START                        	0x02
-#define	A2DP_STATE_CLOSE                        	0x03
-#define	A2DP_STATE_SUSPEND                      	0x04
-#define	A2DP_STATE_PALY_PRESS                   	0x05
-#define	A2DP_STATE_PALY_RELEASE                 	0x06
-#define	A2DP_STATE_PAUSE_PRESS                  	0x07
-#define	A2DP_STATE_PAUSE_RELEASE                	0x08
-#define	AVDTP_SAMPLE_FREQ_44K1                  	0x20
-#define	AVDTP_SAMPLE_FREQ_48K                   	0x10
-#define	HSP_ROLE_L                              	0x00
-#define	HSP_ROLE_R                              	0x01
-#define	TWS_STATE_NONE                          	0x00
-#define	TWS_STATE_PAIRING                       	0x01
-#define	TWS_STATE_WAIT_MASTER                   	0x10
-#define	TWS_STATE_SLAVE_LISTEN                  	0x11
-#define	TWS_STATE_SLAVE_CONNECTED               	0x12
-#define	TWS_STATE_SLAVE_SWITCH_LISTEN           	0x13
-#define	TWS_STATE_WAIT_SLAVE                    	0x20
-#define	TWS_STATE_MASTER_LISTEN                 	0x21
-#define	TWS_STATE_MASTER_CONNECTED              	0x22
-#define	TWS_SET_NONE                            	0x00
-#define	TWS_SET_SLAVE                           	0x33
-#define	TWS_SET_MASTER                          	0x55
-#define	ADV_INTERVAL                            	0x38
-#define	TWS_BLE_ADV_FLAG_POWER_ON               	0xFFEE
-#define	TWS_BLE_ADV_FLAG_NO_CONNECTED           	0xFFDD
-#define	TWS_BLE_ADV_FLAG_CONNECTED              	0xFF0D
-#define	TWS_BLE_ADV_FLAG_TRANS                  	0x8FBB
-#define	TWS_BLE_ADV_FLAG_SPEC_SETTING           	0x9FD7
-#define	TWS_SPEC_ADV_FLAG_NAME                  	0x30
-#define	TWS_SPEC_ADV_FLAG_UPDATE_FLASH          	0x35
-#define	TWS_SPEC_ADV_FLAG_TEST_MUSIC            	0x37
-#define	HCI_ROLE_MASTER                         	0x00
-#define	HCI_ROLE_SLAVE                          	0x01
-#define	LE_WHITE_LIST_MAX_SIZE                  	0x04
-#define	AADC_0_DEFAULT_VALUE                    	0x28
-#define	AADC_1_DEFAULT_VALUE                    	0x52
-#define	AADC_2_DEFAULT_VALUE                    	0x02
-#define	AADC_3_DEFAULT_VALUE                    	0xc3
-#define	AADC_4_DEFAULT_VALUE                    	0x18
-#define	AADC_5_DEFAULT_VALUE                    	0x00
-#define	AADC_6_DEFAULT_VALUE                    	0x00
-#define	AADC_7_DEFAULT_VALUE                    	0xf0
-#define	AADC_8_DEFAULT_VALUE                    	0xa0
-#define	AADC_9_DEFAULT_VALUE                    	0xff
-#define	AADC_A_DEFAULT_VALUE                    	0x3c
-#define	rg_clkpll_8_16_48K                      	0x2D
-#define	rg_clkpll_44d1K                         	0x3D
-#define	rg_misc_8_16_48K                        	0x94
-#define	rg_misc_44d1K                           	0xC4
-#define	left_down_en                            	0x00
-#define	left_up_en                              	0x01
-#define	right_down_en                           	0x02
-#define	right_up_en                             	0x03
-#define	ramp_down_finish_clr                    	0x04
-#define	ramp_up_finish_clr                      	0x05
-#define	RG_ADAC_OPARES_SEL1                     	0x00
-#define	RG_ADAC_OPARES_SEL2                     	0x01
-#define	RG_ADAC_VCMIOPA_SEL                     	0x02
-#define	RG_ADAC_VCMIBUF_BYP                     	0x04
-#define	RG_ADAC_INT_CAPSEL                      	0x05
-#define	RG_ADAC_VOLL0                           	0x06
-#define	DA_ADAC_LDO_AVDD_EN                     	0x05
-#define	DA_ADAC_LDO_HPVDD_EN                    	0x07
-#define	DA_EN_ADAC_BIAS                         	0x00
-#define	DA_EN_ADAC_REF                          	0x01
-#define	DA_EN_ADAC_INT_L                        	0x02
-#define	DA_EN_ADAC_INT_R                        	0x03
-#define	DA_EN_ADAC_OPAL                         	0x04
-#define	DA_EN_ADAC_OPAR                         	0x05
-#define	DA_EN_ADAC_PATHL                        	0x06
-#define	DA_EN_ADAC_PATHR                        	0x07
-#define	DA_ADAC_RST_INT_L                       	0x00
-#define	DA_ADAC_RST_INT_R                       	0x01
-#define	DA_EN_ADAC_OPA_LOOP_L                   	0x02
-#define	DA_EN_ADAC_OPA_LOOP_R                   	0x03
-#define	DA_EN_ADAC_DEPOP_SW_L                   	0x04
-#define	DA_EN_ADAC_DEPOP_SW_R                   	0x05
-#define	DA_EN_ADAC_OPA_DUMMY_L                  	0x06
-#define	DA_EN_ADAC_OPA_DUMMY_R                  	0x07
-#define	CHARGE_PMU_CHGPUMP_EN                   	0x00
-#define	CHARGE_PMU_CHGPUMP_HV                   	0x01
-#define	CHARGE_CHGR_INSC_ENB                    	0x02
-#define	CHARGE_CHGR_UART_EN                     	0x03
-#define	CHARGE_CHGR_SHUTDOWN_SW                 	0x14
-#define	CHARGE_CHGR_SHUTDOWN_BIAS               	0x15
-#define	CHARGE_CHGR_SHUTDOWN_CORE               	0x16
-#define	CHARGE_CHGR_FORCE_CC                    	0x17
-#define	CHARGE_CHGR_FORCE_CV                    	0x18
-#define	CHARGE_CHGR_FORCE_CORE_ON               	0x19
-#define	CHARGE_LPM_CHARGER_EVENT_EN             	0x1A
-#define	CHGR_STATE_ICHG                         	0x01
-#define	CHGR_STATE_RCH_EN                       	0x02
-#define	CHGR_DPPM_OV_CC                         	0x04
-#define	CHGR_STATE_VBAT_LV                      	0x08
-#define	CHGR_DPPM_OV_CV                         	0x10
-#define	CHGR_CC_OV_CV                           	0x20
-#define	CHGR_STATE_IND                          	0x40
-#define	CHGR_PGOOD_AON                          	0x80
-#define	CHGR_PGOOD                              	0x100
-#define	CHGR_IN_PRESENT                         	0x200
-#define	rg_mic_diff_en                          	0x16
-#define	rg_mic_op_cm_en                         	0x17
-#define	rg_mic_pga_vcmsettle_en                 	0x18
-#define	rg_aadc_refbuf_en                       	0x19
-#define	da_aadc_en                              	0x1A
-#define	da_aadc_en_biasgen                      	0x1B
-#define	da_aadc_en_constgm                      	0x1C
-#define	da_aadc_en_reg                          	0x1D
-#define	da_aadda_bg_en                          	0x1E
-#define	da_aadda_bg_en_fc                       	0x1F
-#define	da_mic_pga_en                           	0x00
-#define	da_mic_bias_en                          	0x01
-#define	da_mic_lpm_en                           	0x05
-#define	OTA_SOFT_CHANGE_FLAG                    	0xa5
-#define	OTA_NEED_ENABLE_XIP_FLAG                	0xaa
-#define	DIN_SEL_L_LEFT_CHANNEL                  	0x00
-#define	DIN_SEL_L_RIGHT_CHANNEL                 	0x01
-#define	DIN_SEL_L_LEFT_RIGHT_MIX_CHANNEL        	0x02
-#define	DIN_SEL_L_FIX_ZERO                      	0x03
-#define	DIN_SEL_L_CLOSE                         	0xFF
-#define	DIN_SEL_R_LEFT_CHANNEL                  	0x00
-#define	DIN_SEL_R_RIGHT_CHANNEL                 	0x10
-#define	DIN_SEL_R_LEFT_RIGHT_MIX_CHANNEL        	0x20
-#define	DIN_SEL_R_FIX_ZERO                      	0x30
-#define	DIN_SEL_R_CLOSE                         	0xFF
-#define	RAMP_LEFT_DOWN_STEP_VALUE               	0x03
-#define	RAMP_RIGHT_DOWN_STEP_VALUE              	0x03
-#define	RAMP_LEFT_DOWN_DEST_VALUE               	0x0100
-#define	RAMP_RIGHT_DOWN_DEST_VALUE              	0x0100
-#define	RAMP_LEFT_UP_STEP_VALUE                 	0x03
-#define	RAMP_RIGHT_UP_STEP_VALUE                	0x03
-#define	RAMP_LEFT_UP_DEST_VALUE                 	0x09
-#define	RAMP_RIGHT_UP_DEST_VALUE                	0x09
-#define	ADV_STOP                                	0x00
-#define	ADV_DIS_OPEN_BOX                        	0x01
-#define	ADV_DIS_CLOSE_BOX                       	0x02
-#define	ADV_RESERVE_0                           	0x03
-#define	ADV_RESERVE_1                           	0x04
-#define	ADV_RESERVE_2                           	0x05
-#define	ADV_NORMAL_BLE                          	0x06
-#define	ADV_NUM                                 	0x06
-#define	ADV_OTA                                 	0xff
-#define	TX_POWER_0DB                            	0x00
-#define	TX_POWER_3DB                            	0x01
-#define	TX_POWER_5DB                            	0x02
-#define	TX_POWER_f3DB                           	0x03
-#define	TX_POWER_f5DB                           	0x04
-#define	TX_POWER_8DB                            	0x05
-#define	MEDIA_RELASE_STATE_NONE                 	0x00
-#define	MEDIA_RELASE_STATE_WAIT_UPSTACK         	0x01
-#define	MEDIA_RELASE_STATE_READY                	0x02
-#define	BT_RESPIN_HIBERNATE_FLAG                	0x10000
-#define	BT_RESPIN_HIBERNATE_CHG_LOW             	0x10002
-#define	BT_RESPIN_HIBERNATE_CHG_HIGH            	0x10004
-#define	BT_RESPIN_FLAG_VALID_FLAG               	0x3579
-#define	RSSI_ADJUST_PHO_F5DB                    	0x49
-#define	RSSI_ADJUST_PHO                         	0x55
-#define	RSSI_ADJUST_PHO_5DB                     	0x59
-#define	RSSI_ADJUST_PHO_8DB                     	0x60
-#define	OTA_EVENT                               	0XAB
-#define	OTA_COMMAND                             	0XBA
-#define	OTA_WORK_MODE_NORMAL                    	0x0
-#define	OTA_WORK_MODE_OTA                       	0x1
-#define	OTA_PORTOCOL_VERSION_REQUEST            	0x10
-#define	OTA_BUCK_SIZE_REQUEST                   	0x11
-#define	OTA_WORK_MODE_REQUEST                   	0x12
-#define	OTA_SWITCH_WORK_MODE_REQUEST            	0x13
-#define	OTA_FLASH_CHECKSUM_REQUEST              	0x14
-#define	OTA_START_REQUEST                       	0x15
-#define	OTA_DATA_WRITE_CMD                      	0x16
-#define	OTA_DATA_WRITE_REQUEST                  	0x17
-#define	OTA_END_REQUEST                         	0x18
-#define	OTA_UPDATE_FLASH_NORMAL                 	0x0
-#define	OTA_UPDATE_FLASH_OTA                    	0x1
-#define	OTA_UPDATE_FLASH_PCM                    	0x2
-#define	OTA_RESULT_SUCCESS                      	0x0
-#define	OTA_RESULT_WORKMODE_NOT_SUPPORT         	0x1
-#define	OTA_RESULT_WORKMODE_ERROR               	0x2
-#define	OTA_RESULT_FLASHMODE_NOT_SUPPORT        	0x3
-#define	OTA_RESULT_INDEX_ERROR                  	0x4
-#define	OTA_RESULT_LENGTH_ERROR                 	0x5
-#define	OTA_RESULT_BUCK_SIZE_ERROR              	0x6
-#define	OTA_RESULT_WRITE_FLASH_ERROR            	0x7
-#define	OTA_RESULT_ERROR                        	0xFF
-#define	OTA_CODE_START_ADDR                     	0x1000
-#define	NORMAL_CODE_START_ADDR                  	0x6000
-#define	OTA_DATA_ADDR                           	0x2000
-#define	OTA_FLASH_START_ADDR                    	0x1000
-#define	OTA_FLASH_ALL_LENGTH                    	0x5000
-#define	OTA_FLASH_NORMAL_LENGTH                 	0x29000
-#define	VP_FLASH_START_ADDR                     	0x30000
-#define	VP_FLASH_ALL_LENGTH                     	0X4F000
-#define	MSBC_H2_SYNCWORD                        	0x801
-#define	MSBC_SEQUENCE_NUMBER_0                  	0x00
-#define	MSBC_SEQUENCE_NUMBER_1                  	0x30
-#define	MSBC_SEQUENCE_NUMBER_2                  	0xC0
-#define	MSBC_SEQUENCE_NUMBER_3                  	0xF0
-#endif
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_addr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_addr.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_addr.h	(nonexistent)
@@ -1,108 +0,0 @@
-/** @file
- *  @brief Bluetooth device address definitions and utilities.
- */
-
-/*
- * Copyright (c) 2019 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#ifndef _YC11XX_ADDR_H_
-#define _YC11XX_ADDR_H_
-
-#include <stdbool.h>
-#include <string.h>
-#include "type.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Bluetooth device address definitions and utilities.
- * @defgroup bt_addr Device Address
- * @ingroup bluetooth
- * @{
- */
-
-#define BT_ADDR_LE_PUBLIC       0x00
-#define BT_ADDR_LE_RANDOM       0x01
-#define BT_ADDR_LE_PUBLIC_ID    0x02
-#define BT_ADDR_LE_RANDOM_ID    0x03
-
-/** Bluetooth Device Address */
-typedef struct {
-	uint8_t  val[6];
-} bt_addr_t;
-
-/** Bluetooth LE Device Address */
-typedef struct {
-	uint8_t      type;
-	bt_addr_t a;
-} bt_addr_le_t;
-
-#define BT_ADDR_ANY     ((bt_addr_t[]) { { { 0, 0, 0, 0, 0, 0 } } })
-#define BT_ADDR_NONE    ((bt_addr_t[]) { { \
-			 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } })
-#define BT_ADDR_LE_ANY  ((bt_addr_le_t[]) { { 0, { { 0, 0, 0, 0, 0, 0 } } } })
-#define BT_ADDR_LE_NONE ((bt_addr_le_t[]) { { 0, \
-			 { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } })
-
-static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b)
-{
-	return memcmp(a, b, sizeof(*a));
-}
-
-static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b)
-{
-	return memcmp(a, b, sizeof(*a));
-}
-
-static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src)
-{
-	memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src)
-{
-	memcpy(dst, src, sizeof(*dst));
-}
-
-#define BT_ADDR_IS_RPA(a)     (((a)->val[5] & 0xc0) == 0x40)
-#define BT_ADDR_IS_NRPA(a)    (((a)->val[5] & 0xc0) == 0x00)
-#define BT_ADDR_IS_STATIC(a)  (((a)->val[5] & 0xc0) == 0xc0)
-
-#define BT_ADDR_SET_RPA(a)    ((a)->val[5] = (((a)->val[5] & 0x3f) | 0x40))
-#define BT_ADDR_SET_NRPA(a)   ((a)->val[5] &= 0x3f)
-#define BT_ADDR_SET_STATIC(a) ((a)->val[5] |= 0xc0)
-
-int bt_addr_le_create_nrpa(bt_addr_le_t *addr);
-int bt_addr_le_create_static(bt_addr_le_t *addr);
-
-static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr)
-{
-	if (addr->type != BT_ADDR_LE_RANDOM) {
-		return false;
-	}
-
-	return BT_ADDR_IS_RPA(&addr->a);
-}
-
-static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr)
-{
-	if (addr->type == BT_ADDR_LE_PUBLIC) {
-		return true;
-	}
-
-	return BT_ADDR_IS_STATIC(&addr->a);
-}
-
-/**
- * @}
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _YC11XX_ADDR_H_ */
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.h	(nonexistent)
@@ -1,33 +0,0 @@
-#ifndef DRIVERS_HCI_YC11XX_H4_H_
-#define DRIVERS_HCI_YC11XX_H4_H_
-
-#include "yc11xx_hci.h"
-#include "yc11xx_uart.h"
-#include "yc11xx_gpio.h"
-
-
-#define H4_NONE 0x00
-#define H4_CMD  0x01
-#define H4_ACL  0x02
-#define H4_SCO  0x03
-#define H4_EVT  0x04
-#define H4_ISO  0x05
-
-#define HCI_H4_UART (UARTA)
-#define H4_UART_RXIO  (GPIO_28)
-#define H4_UART_TXIO  (GPIO_27)  
-
-#define BT_DBG(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
-#define BT_ERR(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
-#define BT_WARN(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
-#define BT_INFO(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
-
-#define  MIN(a, b)      (((a) < (b)) ? (a) : (b))
-
-void h4_init(void);
-void h4_polling_rx(void);
-void h4_send_data(uint8_t* buf, uint16_t len);
-
-#endif //DRIVERS_HCI_YC11XX_H4_H_
-
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.c	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_h4.c	(nonexistent)
@@ -1,336 +0,0 @@
-/* h4.c - H:4 UART based Bluetooth driver */
-
-/*
- * Copyright (c) 2015-2016 Intel Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-//#include <errno.h>
-#include "yc11xx_gpio.h"
-#include "yc11xx.h"
-#include "yc_drv_common.h"
-#include <string.h>
-//#include "yc11xx_pwm.h"
-#include "yc_debug.h"
-#include "yc11xx_h4.h"
-#include "Drv_bt.h"
-
-static struct {
-	uint8_t buf[600];
-	uint16_t buf_pos;
-
-	
-	uint16_t    remaining;
-	uint16_t    discard;
-
-	bool     have_hdr;
-	bool     discardable;
-
-	uint8_t     hdr_len;
-
-	uint8_t     type;
-	union {
-		struct bt_hci_cmd_hdr cmd;
-		struct bt_hci_evt_hdr evt;
-		struct bt_hci_acl_hdr acl;
-		struct bt_hci_iso_hdr iso;
-		uint8_t hdr[4];
-	};
-} rx;
-
-static struct {
-	uint8_t type;
-	uint8_t *buf;
-} tx;
-
-
-void h4_uart_init(uint16_t baudRate)
-{
-	USART_InitTypeDef USART_InitStruct ;
-
-	USART_InitStruct.USART_BaudRate             = baudRate;
-	USART_InitStruct.USART_HardwareFlowControl  = USART_HardwareFlowControl_None;
-	USART_InitStruct.USART_WordLength           = USART_WordLength_8b;	
-	USART_InitStruct.USART_StopBits             = USART_StopBits_1;
-	USART_InitStruct.USART_Mode                 = USART_Mode_duplex;
-	USART_InitStruct.USART_Parity               = USART_Parity_Even ;
-	USART_InitStruct.USART_TXLen                = 512;
-	USART_InitStruct.USART_RXLen                = 512;
-
-	if(UARTA == HCI_H4_UART){
-		GPIO_SetGpioMultFunction(H4_UART_TXIO,GPCFG_UART_TXD);
-		GPIO_SetGpioMultFunction(H4_UART_RXIO,GPCFG_UART_RXD|GPCFG_PULLUP);
-	}else if (UARTB == HCI_H4_UART){
-		GPIO_SetGpioMultFunction(H4_UART_TXIO,GPCFG_UARTB_TXD);
-		GPIO_SetGpioMultFunction(H4_UART_RXIO,GPCFG_UARTB_RXD|GPCFG_PULLUP);
-	}
-	USART_Init(HCI_H4_UART,&USART_InitStruct);
-}
-
-
-static size_t h4_discard(size_t len)
-{
-	uint8_t buf[33];
-	return USART_ReadDatatoBuff(HCI_H4_UART, buf, MIN(len, sizeof(buf)));
-}
-
-static size_t h4_read(uint8_t* rxBuff, size_t len)
-{
-	return USART_ReadDatatoBuff(HCI_H4_UART, rxBuff, len);
-}
-
-const char *bt_hex_real(const void *buf, size_t len)
-{
-	static const char hex[] = "0123456789abcdef";
-	static char str[129];
-	const uint8_t *b = buf;
-	size_t i;
-
-	len = MIN(len, (sizeof(str) - 1) / 2);
-
-	for (i = 0; i < len; i++) {
-		str[i * 2]     = hex[b[i] >> 4];
-		str[i * 2 + 1] = hex[b[i] & 0xf];
-	}
-
-	str[i * 2] = '\0';
-
-	return str;
-}
-
-static inline void h4_get_type(void)
-{
-	/* Get packet type */
-	if (h4_read(&rx.type, 1) != 1)
-	{
-		BT_WARN("Unable to read H:4 packet type\r\n");
-		rx.type = H4_NONE;
-		return;
-	}
-
-	switch (rx.type) {
-	case H4_CMD:
-		rx.remaining = sizeof(rx.cmd);
-		rx.hdr_len = rx.remaining;
-		break;
-	case H4_EVT:
-		rx.remaining = sizeof(rx.evt);
-		rx.hdr_len = rx.remaining;
-		break;
-	case H4_ACL:
-		rx.remaining = sizeof(rx.acl);
-		rx.hdr_len = rx.remaining;
-		break;
-	case H4_ISO:
-		rx.remaining = sizeof(rx.iso);
-		rx.hdr_len = rx.remaining;
-		break;
-	default:
-		BT_ERR("Unknown H:4 type 0x%02x\r\n", rx.type);
-		rx.type = H4_NONE;
-	}
-}
-
-static inline void get_acl_hdr(void)
-{
-	struct bt_hci_acl_hdr *hdr = &rx.acl;
-	int to_read = sizeof(*hdr) - rx.remaining;
-
-	rx.remaining -= h4_read((uint8_t *)hdr + to_read,
-				       rx.remaining);
-	if (!rx.remaining) {
-		rx.remaining = (hdr->len);
-		BT_DBG("Got ACL header. Payload %u bytes\r\n", rx.remaining);
-		rx.have_hdr = true;
-	}
-}
-
-static inline void get_cmd_hdr(void)
-{
-	struct bt_hci_cmd_hdr *hdr = &rx.cmd;
-	int to_read = rx.hdr_len - rx.remaining;
-
-	rx.remaining -= h4_read((uint8_t *)hdr + to_read,
-				       rx.remaining);
-
-	if (!rx.remaining) {
-		rx.remaining = hdr->param_len;
-		BT_DBG("Got cmd header. Payload %u bytes\r\n", hdr->param_len);
-		rx.have_hdr = true;
-	}
-}
-
-static inline uint8_t* get_rx_buf_read_pos(void)
-{
-	return rx.buf + rx.buf_pos;
-}
-static inline void increase_rx_buf_pos(uint16_t len)
-{
-	rx.buf_pos += len;
-}
-
-static inline void copy_hdr(void)
-{
-	// Save type.
-	*(uint8_t *)get_rx_buf_read_pos() = rx.type;
-	increase_rx_buf_pos(1);
-
-	// Save header
-	memcpy(get_rx_buf_read_pos(), rx.hdr, rx.hdr_len);
-	increase_rx_buf_pos(rx.hdr_len);
-}
-
-static void reset_rx(void)
-{
-	rx.type = H4_NONE;
-	rx.remaining = 0U;
-	rx.have_hdr = false;
-	rx.hdr_len = 0U;
-	rx.discardable = false;
-	rx.buf_pos= 0;
-}
-
-static inline void process_rx_packet(uint8_t type, uint8_t* buf, uint16_t len)
-{
-	//
-	BT_DBG("<--- process_rx_packet (type %u) (len %u): %s\r\n", type, len,
-	       bt_hex_real(buf, len));
-
-        DEBUG_LOG_PRINT_HCI_H4(0, buf, len);
-	Bt_SndHciToRespin(buf, len);
-}
-
-static inline void read_payload(void)
-{
-	uint8_t evt_flags;
-	int read;
-
-	if (rx.remaining) {
-		read = h4_read(get_rx_buf_read_pos(), rx.remaining);
-		increase_rx_buf_pos(read);
-		rx.remaining -= read;
-
-		BT_DBG("got %d bytes, remaining %u\r\n", read, rx.remaining);
-		BT_DBG("Payload (len %u): %s\r\n", rx.buf_pos,
-		       bt_hex_real(rx.buf, rx.buf_pos));
-
-		if (rx.remaining) {
-			return;
-		}
-	}
-
-	// receive a full packet
-	process_rx_packet(rx.type, rx.buf, rx.buf_pos);
-	
-	reset_rx();
-}
-
-static inline void read_header(void)
-{
-	switch (rx.type) {
-	case H4_NONE:
-		h4_get_type();
-		return;
-	case H4_CMD:
-		get_cmd_hdr();
-		break;
-	case H4_ACL:
-		get_acl_hdr();
-		break;
-	default:
-		BT_ERR("Something error\r\n");
-		return;
-	}
-
-	if (rx.have_hdr) {
-		if (rx.remaining > (sizeof(rx.buf) - rx.buf_pos)) {
-			BT_ERR("Not enough space in buffer\r\n");
-			rx.discard = rx.remaining;
-			reset_rx();
-		} else {
-			copy_hdr();
-
-			// Check receive full packet
-			if (!rx.remaining) {
-				// receive a full packet
-				process_rx_packet(rx.type, rx.buf, rx.buf_pos);
-				
-				reset_rx();
-			}
-
-		}
-	}
-}
-static inline void process_rx(void)
-{
-	if(USART_GetRxCount(HCI_H4_UART) == 0)
-	{
-		return;
-	}
-	BT_DBG("remaining %u discard %u have_hdr %u len %u\r\n",
-	       rx.remaining, rx.discard, rx.have_hdr,
-	       rx.buf_pos);
-
-	if (rx.discard) {
-		rx.discard -= h4_discard(rx.discard);
-		return;
-	}
-
-	if (rx.have_hdr) {
-		read_payload();
-	} else {
-		read_header();
-	}
-}
-
-
-static int h4_send(uint8_t* buf, uint16_t len)
-{
-	BT_DBG("---> h4_send Payload (len %u): %s\r\n", len,
-	       bt_hex_real(buf, len));
-
-	USART_SendDataFromBuff(HCI_H4_UART, buf, len);
-
-	return 0;
-}
-
-
-static int h4_open(void)
-{
-	int ret;
-
-	BT_DBG("");
-#ifdef FUNCTION_FSC_RTK_HOST
-	h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud115200);
-#else
-	h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud921600);
-#endif
-	
-	return 0;
-}
-
-
-void h4_init(void)
-{
-	h4_open();
-}
-void h4_polling_rx(void)
-{
-	process_rx();
-}
-void h4_send_data(uint8_t* buf, uint16_t len)
-{
-	h4_send(buf, len);
-        DEBUG_LOG_PRINT_HCI_H4(1, buf, len);
-        if(HREAD(mem_fsc_rtk_host) == 0x3f)
-        {
-#ifdef FUNCTION_FSC_RTK_HOST_WHITE
-            h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud512000);
-#else
-            h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud1M);
-#endif
-            HWRITE(mem_fsc_rtk_host, 0);
-        }
-}
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci.h	(nonexistent)
@@ -1,2235 +0,0 @@
-/* hci.h - Bluetooth Host Control Interface definitions */
-
-/*
- * Copyright (c) 2015-2016 Intel Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#ifndef _YC11XX_HCI_H_
-#define _YC11XX_HCI_H_
-
-#include <stdbool.h>
-#include <string.h>
-#include "yc11xx_hci_err.h"
-#include "yc11xx_addr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef __packed
-#define __packed        __attribute__((__packed__))
-#endif
-
-/**
- * @brief Unsigned integer with bit position @p n set (signed in
- * assembly language).
- */
-#define BIT(n)  (1UL << (n))
-
-/**
- * @brief Bit mask with bits 0 through <tt>n-1</tt> (inclusive) set,
- * or 0 if @p n is 0.
- */
-#define BIT_MASK(n) (BIT(n) - 1)
-
-/* Special own address types for LL privacy (used in adv & scan parameters) */
-#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC  0x02
-#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM  0x03
-#define BT_HCI_OWN_ADDR_RPA_MASK       0x02
-
-#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe
-#define BT_HCI_PEER_ADDR_ANONYMOUS      0xff
-
-#define BT_ENC_KEY_SIZE_MIN                     0x07
-#define BT_ENC_KEY_SIZE_MAX                     0x10
-
-
-
-
-
-
-
-/* Special own address types for LL privacy (used in adv & scan parameters) */
-#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC  0x02
-#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM  0x03
-#define BT_HCI_OWN_ADDR_RPA_MASK       0x02
-
-#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe
-#define BT_HCI_PEER_ADDR_ANONYMOUS      0xff
-
-#define BT_ENC_KEY_SIZE_MIN                     0x07
-#define BT_ENC_KEY_SIZE_MAX                     0x10
-
-struct bt_hci_evt_hdr {
-	uint8_t  evt;
-	uint8_t  len;
-} __packed;
-#define BT_HCI_EVT_HDR_SIZE             2
-
-#define BT_ACL_START_NO_FLUSH           0x00
-#define BT_ACL_CONT                     0x01
-#define BT_ACL_START                    0x02
-#define BT_ACL_COMPLETE                 0x03
-
-#define BT_ACL_POINT_TO_POINT           0x00
-#define BT_ACL_BROADCAST                0x01
-
-#define bt_acl_handle(h)                ((h) & BIT_MASK(12))
-#define bt_acl_flags(h)                 ((h) >> 12)
-#define bt_acl_flags_pb(f)              ((f) & BIT_MASK(2))
-#define bt_acl_flags_bc(f)              ((f) >> 2)
-#define bt_acl_handle_pack(h, f)        ((h) | ((f) << 12))
-
-struct bt_hci_acl_hdr {
-	uint16_t handle;
-	uint16_t len;
-} __packed;
-#define BT_HCI_ACL_HDR_SIZE             4
-
-#define BT_ISO_START                    0x00
-#define BT_ISO_CONT                     0x01
-#define BT_ISO_SINGLE                   0x02
-#define BT_ISO_END                      0x03
-
-#define bt_iso_handle(h)                ((h) & 0x0fff)
-#define bt_iso_flags(h)                 ((h) >> 12)
-#define bt_iso_flags_pb(f)              ((f) & 0x0003)
-#define bt_iso_flags_ts(f)              (((f) >> 2) & 0x0001)
-#define bt_iso_pack_flags(pb, ts) \
-	(((pb) & 0x0003) | (((ts) & 0x0001) << 2))
-#define bt_iso_handle_pack(h, pb, ts) \
-	((h) | (bt_iso_pack_flags(pb, ts) << 12))
-
-#define BT_ISO_DATA_VALID                0x00
-#define BT_ISO_DATA_INVALID              0x01
-#define BT_ISO_DATA_NOP                  0x02
-
-#define bt_iso_pkt_len(h)                ((h) & 0x3fff)
-#define bt_iso_pkt_flags(h)              ((h) >> 14)
-#define bt_iso_pkt_len_pack(h, f)        ((h) | ((f) << 14))
-
-struct bt_hci_iso_data_hdr {
-	uint16_t sn;
-	uint16_t slen;
-} __packed;
-#define BT_HCI_ISO_DATA_HDR_SIZE	4
-
-struct bt_hci_iso_ts_data_hdr {
-	uint32_t ts;
-	struct bt_hci_iso_data_hdr data;
-} __packed;
-#define BT_HCI_ISO_TS_DATA_HDR_SIZE     8
-
-struct bt_hci_iso_hdr {
-	uint16_t handle;
-	uint16_t len;
-} __packed;
-#define BT_HCI_ISO_HDR_SIZE             4
-
-struct bt_hci_cmd_hdr {
-	uint16_t opcode;
-	uint8_t  param_len;
-} __packed;
-#define BT_HCI_CMD_HDR_SIZE             3
-
-/* Supported Commands */
-#define BT_CMD_TEST(cmd, octet, bit)            (cmd[octet] & BIT(bit))
-#define BT_CMD_LE_STATES(cmd)                   BT_CMD_TEST(cmd, 28, 3)
-
-#define BT_FEAT_TEST(feat, page, octet, bit)    (feat[page][octet] & BIT(bit))
-
-#define BT_FEAT_BREDR(feat)                     !BT_FEAT_TEST(feat, 0, 4, 5)
-#define BT_FEAT_LE(feat)                        BT_FEAT_TEST(feat, 0, 4, 6)
-#define BT_FEAT_EXT_FEATURES(feat)              BT_FEAT_TEST(feat, 0, 7, 7)
-#define BT_FEAT_HOST_SSP(feat)                  BT_FEAT_TEST(feat, 1, 0, 0)
-#define BT_FEAT_SC(feat)                        BT_FEAT_TEST(feat, 2, 1, 0)
-
-#define BT_FEAT_LMP_ESCO_CAPABLE(feat)          BT_FEAT_TEST(feat, 0, 3, 7)
-#define BT_FEAT_HV2_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 4)
-#define BT_FEAT_HV3_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 5)
-#define BT_FEAT_EV4_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 0)
-#define BT_FEAT_EV5_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 1)
-#define BT_FEAT_2EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 5)
-#define BT_FEAT_3EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 6)
-#define BT_FEAT_3SLOT_PKT(feat)                 BT_FEAT_TEST(feat, 0, 5, 7)
-
-/* LE features */
-#define BT_LE_FEAT_BIT_ENC                      0
-#define BT_LE_FEAT_BIT_CONN_PARAM_REQ           1
-#define BT_LE_FEAT_BIT_EXT_REJ_IND              2
-#define BT_LE_FEAT_BIT_SLAVE_FEAT_REQ           3
-#define BT_LE_FEAT_BIT_PING                     4
-#define BT_LE_FEAT_BIT_DLE                      5
-#define BT_LE_FEAT_BIT_PRIVACY                  6
-#define BT_LE_FEAT_BIT_EXT_SCAN                 7
-#define BT_LE_FEAT_BIT_PHY_2M                   8
-#define BT_LE_FEAT_BIT_SMI_TX                   9
-#define BT_LE_FEAT_BIT_SMI_RX                   10
-#define BT_LE_FEAT_BIT_PHY_CODED                11
-#define BT_LE_FEAT_BIT_EXT_ADV                  12
-#define BT_LE_FEAT_BIT_PER_ADV                  13
-#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2          14
-#define BT_LE_FEAT_BIT_PWR_CLASS_1              15
-#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC       16
-#define BT_LE_FEAT_BIT_CONN_CTE_REQ             17
-#define BT_LE_FEAT_BIT_CONN_CTE_RESP            18
-#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX    19
-#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX    20
-#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD        21
-#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA        22
-#define BT_LE_FEAT_BIT_RX_CTE                   23
-#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_SEND  24
-#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_RECV  25
-#define BT_LE_FEAT_BIT_SCA_UPDATE               26
-#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE  27
-#define BT_LE_FEAT_BIT_CIS_MASTER               28
-#define BT_LE_FEAT_BIT_CIS_SLAVE                29
-#define BT_LE_FEAT_BIT_ISO_BROADCASTER          30
-#define BT_LE_FEAT_BIT_SYNC_RECEIVER            31
-#define BT_LE_FEAT_BIT_ISO_CHANNELS             32
-#define BT_LE_FEAT_BIT_PWR_CTRL_REQ             33
-#define BT_LE_FEAT_BIT_PWR_CHG_IND              34
-#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR        35
-
-#define BT_LE_FEAT_TEST(feat, n)                (feat[(n) >> 3] & \
-						 BIT((n) & 7))
-
-#define BT_FEAT_LE_ENCR(feat)                   BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_ENC)
-#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat)    BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_CONN_PARAM_REQ)
-#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat)     BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_SLAVE_FEAT_REQ)
-#define BT_FEAT_LE_DLE(feat)                    BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_DLE)
-#define BT_FEAT_LE_PHY_2M(feat)                 BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_PHY_2M)
-#define BT_FEAT_LE_PHY_CODED(feat)              BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_PHY_CODED)
-#define BT_FEAT_LE_PRIVACY(feat)                BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_PRIVACY)
-#define BT_FEAT_LE_EXT_ADV(feat)                BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_EXT_ADV)
-#define BT_FEAT_LE_EXT_PER_ADV(feat)            BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_PER_ADV)
-#define BT_FEAT_LE_CIS_MASTER(feat)             BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_CIS_MASTER)
-#define BT_FEAT_LE_CIS_SLAVE(feat)              BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_CIS_SLAVE)
-#define BT_FEAT_LE_ISO_BROADCASTER(feat)        BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_ISO_BROADCASTER)
-#define BT_FEAT_LE_SYNC_RECEIVER(feat)          BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_SYNC_RECEIVER)
-#define BT_FEAT_LE_ISO_CHANNELS(feat)           BT_LE_FEAT_TEST(feat, \
-						BT_LE_FEAT_BIT_ISO_CHANNELS)
-
-#define BT_FEAT_LE_CIS(feat)            (BT_FEAT_LE_CIS_MASTER(feat) | \
-					BT_FEAT_LE_CIS_SLAVE(feat))
-#define BT_FEAT_LE_BIS(feat)            (BT_FEAT_LE_ISO_BROADCASTER(feat) | \
-					BT_FEAT_LE_SYNC_RECEIVER(feat))
-#define BT_FEAT_LE_ISO(feat)            (BT_FEAT_LE_CIS(feat) | \
-					BT_FEAT_LE_BIS(feat))
-
-/* LE States */
-#define BT_LE_STATES_SLAVE_CONN_ADV(states)     (states & 0x0000004000000000)
-
-/* Bonding/authentication types */
-#define BT_HCI_NO_BONDING                       0x00
-#define BT_HCI_NO_BONDING_MITM                  0x01
-#define BT_HCI_DEDICATED_BONDING                0x02
-#define BT_HCI_DEDICATED_BONDING_MITM           0x03
-#define BT_HCI_GENERAL_BONDING                  0x04
-#define BT_HCI_GENERAL_BONDING_MITM             0x05
-
-/*
- * MITM protection is enabled in SSP authentication requirements octet when
- * LSB bit is set.
- */
-#define BT_MITM                                 0x01
-
-/* I/O capabilities */
-#define BT_IO_DISPLAY_ONLY                      0x00
-#define BT_IO_DISPLAY_YESNO                     0x01
-#define BT_IO_KEYBOARD_ONLY                     0x02
-#define BT_IO_NO_INPUT_OUTPUT                   0x03
-
-/* SCO packet types */
-#define HCI_PKT_TYPE_HV1                        0x0020
-#define HCI_PKT_TYPE_HV2                        0x0040
-#define HCI_PKT_TYPE_HV3                        0x0080
-
-/* eSCO packet types */
-#define HCI_PKT_TYPE_ESCO_HV1                   0x0001
-#define HCI_PKT_TYPE_ESCO_HV2                   0x0002
-#define HCI_PKT_TYPE_ESCO_HV3                   0x0004
-#define HCI_PKT_TYPE_ESCO_EV3                   0x0008
-#define HCI_PKT_TYPE_ESCO_EV4                   0x0010
-#define HCI_PKT_TYPE_ESCO_EV5                   0x0020
-#define HCI_PKT_TYPE_ESCO_2EV3                  0x0040
-#define HCI_PKT_TYPE_ESCO_3EV3                  0x0080
-#define HCI_PKT_TYPE_ESCO_2EV5                  0x0100
-#define HCI_PKT_TYPE_ESCO_3EV5                  0x0200
-
-
-#define ESCO_PKT_MASK                           (HCI_PKT_TYPE_ESCO_HV1 | \
-						 HCI_PKT_TYPE_ESCO_HV2 | \
-						 HCI_PKT_TYPE_ESCO_HV3)
-#define SCO_PKT_MASK                            (HCI_PKT_TYPE_HV1 | \
-						 HCI_PKT_TYPE_HV2 | \
-						 HCI_PKT_TYPE_HV3)
-#define EDR_ESCO_PKT_MASK                       (HCI_PKT_TYPE_ESCO_2EV3 | \
-						 HCI_PKT_TYPE_ESCO_3EV3 | \
-						 HCI_PKT_TYPE_ESCO_2EV5 | \
-						 HCI_PKT_TYPE_ESCO_3EV5)
-
-/* HCI BR/EDR link types */
-#define BT_HCI_SCO                              0x00
-#define BT_HCI_ACL                              0x01
-#define BT_HCI_ESCO                             0x02
-
-/* OpCode Group Fields */
-#define BT_OGF_LINK_CTRL                        0x01
-#define BT_OGF_BASEBAND                         0x03
-#define BT_OGF_INFO                             0x04
-#define BT_OGF_STATUS                           0x05
-#define BT_OGF_LE                               0x08
-#define BT_OGF_VS                               0x3f
-
-/* Construct OpCode from OGF and OCF */
-#define BT_OP(ogf, ocf)                         ((ocf) | ((ogf) << 10))
-
-/* Invalid opcode */
-#define BT_OP_NOP				0x0000
-
-/* Obtain OGF from OpCode */
-#define BT_OGF(opcode)                          (((opcode) >> 10) & BIT_MASK(6))
-/* Obtain OCF from OpCode */
-#define BT_OCF(opcode)                          ((opcode) & BIT_MASK(10))
-
-#define BT_HCI_OP_INQUIRY                       BT_OP(BT_OGF_LINK_CTRL, 0x0001)
-struct bt_hci_op_inquiry {
-	uint8_t lap[3];
-	uint8_t length;
-	uint8_t num_rsp;
-} __packed;
-
-#define BT_HCI_OP_INQUIRY_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0002)
-
-#define BT_HCI_OP_CONNECT                       BT_OP(BT_OGF_LINK_CTRL, 0x0005)
-struct bt_hci_cp_connect {
-	bt_addr_t bdaddr;
-	uint16_t  packet_type;
-	uint8_t   pscan_rep_mode;
-	uint8_t   reserved;
-	uint16_t  clock_offset;
-	uint8_t   allow_role_switch;
-} __packed;
-
-#define BT_HCI_OP_DISCONNECT                    BT_OP(BT_OGF_LINK_CTRL, 0x0006)
-struct bt_hci_cp_disconnect {
-	uint16_t handle;
-	uint8_t  reason;
-} __packed;
-
-#define BT_HCI_OP_CONNECT_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0008)
-struct bt_hci_cp_connect_cancel {
-	bt_addr_t bdaddr;
-} __packed;
-struct bt_hci_rp_connect_cancel {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_ACCEPT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x0009)
-struct bt_hci_cp_accept_conn_req {
-	bt_addr_t bdaddr;
-	uint8_t   role;
-} __packed;
-
-#define BT_HCI_OP_SETUP_SYNC_CONN               BT_OP(BT_OGF_LINK_CTRL, 0x0028)
-struct bt_hci_cp_setup_sync_conn {
-	uint16_t  handle;
-	uint32_t  tx_bandwidth;
-	uint32_t  rx_bandwidth;
-	uint16_t  max_latency;
-	uint16_t  content_format;
-	uint8_t   retrans_effort;
-	uint16_t  pkt_type;
-} __packed;
-
-#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ          BT_OP(BT_OGF_LINK_CTRL, 0x0029)
-struct bt_hci_cp_accept_sync_conn_req {
-	bt_addr_t bdaddr;
-	uint32_t  tx_bandwidth;
-	uint32_t  rx_bandwidth;
-	uint16_t  max_latency;
-	uint16_t  content_format;
-	uint8_t   retrans_effort;
-	uint16_t  pkt_type;
-} __packed;
-
-#define BT_HCI_OP_REJECT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x000a)
-struct bt_hci_cp_reject_conn_req {
-	bt_addr_t bdaddr;
-	uint8_t   reason;
-} __packed;
-
-#define BT_HCI_OP_LINK_KEY_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000b)
-struct bt_hci_cp_link_key_reply {
-	bt_addr_t bdaddr;
-	uint8_t   link_key[16];
-} __packed;
-
-#define BT_HCI_OP_LINK_KEY_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000c)
-struct bt_hci_cp_link_key_neg_reply {
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_PIN_CODE_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000d)
-struct bt_hci_cp_pin_code_reply {
-	bt_addr_t bdaddr;
-	uint8_t   pin_len;
-	uint8_t   pin_code[16];
-} __packed;
-struct bt_hci_rp_pin_code_reply {
-	uint8_t      status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_PIN_CODE_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000e)
-struct bt_hci_cp_pin_code_neg_reply {
-	bt_addr_t bdaddr;
-} __packed;
-struct bt_hci_rp_pin_code_neg_reply {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_AUTH_REQUESTED                BT_OP(BT_OGF_LINK_CTRL, 0x0011)
-struct bt_hci_cp_auth_requested {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_SET_CONN_ENCRYPT              BT_OP(BT_OGF_LINK_CTRL, 0x0013)
-struct bt_hci_cp_set_conn_encrypt {
-	uint16_t handle;
-	uint8_t  encrypt;
-} __packed;
-
-#define BT_HCI_OP_REMOTE_NAME_REQUEST           BT_OP(BT_OGF_LINK_CTRL, 0x0019)
-struct bt_hci_cp_remote_name_request {
-	bt_addr_t bdaddr;
-	uint8_t   pscan_rep_mode;
-	uint8_t   reserved;
-	uint16_t  clock_offset;
-} __packed;
-
-#define BT_HCI_OP_REMOTE_NAME_CANCEL            BT_OP(BT_OGF_LINK_CTRL, 0x001a)
-struct bt_hci_cp_remote_name_cancel {
-	bt_addr_t bdaddr;
-} __packed;
-struct bt_hci_rp_remote_name_cancel {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_READ_REMOTE_FEATURES          BT_OP(BT_OGF_LINK_CTRL, 0x001b)
-struct bt_hci_cp_read_remote_features {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES      BT_OP(BT_OGF_LINK_CTRL, 0x001c)
-struct bt_hci_cp_read_remote_ext_features {
-	uint16_t handle;
-	uint8_t  page;
-} __packed;
-
-#define BT_HCI_OP_READ_REMOTE_VERSION_INFO      BT_OP(BT_OGF_LINK_CTRL, 0x001d)
-struct bt_hci_cp_read_remote_version_info {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_IO_CAPABILITY_REPLY           BT_OP(BT_OGF_LINK_CTRL, 0x002b)
-struct bt_hci_cp_io_capability_reply {
-	bt_addr_t bdaddr;
-	uint8_t   capability;
-	uint8_t   oob_data;
-	uint8_t   authentication;
-} __packed;
-
-#define BT_HCI_OP_USER_CONFIRM_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002c)
-#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002d)
-struct bt_hci_cp_user_confirm_reply {
-	bt_addr_t bdaddr;
-} __packed;
-struct bt_hci_rp_user_confirm_reply {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_USER_PASSKEY_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002e)
-struct bt_hci_cp_user_passkey_reply {
-	bt_addr_t bdaddr;
-	uint32_t  passkey;
-} __packed;
-
-#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002f)
-struct bt_hci_cp_user_passkey_neg_reply {
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY       BT_OP(BT_OGF_LINK_CTRL, 0x0034)
-struct bt_hci_cp_io_capability_neg_reply {
-	bt_addr_t bdaddr;
-	uint8_t   reason;
-} __packed;
-
-#define BT_HCI_OP_SET_EVENT_MASK                BT_OP(BT_OGF_BASEBAND, 0x0001)
-struct bt_hci_cp_set_event_mask {
-	uint8_t  events[8];
-} __packed;
-
-#define BT_HCI_OP_RESET                         BT_OP(BT_OGF_BASEBAND, 0x0003)
-
-#define BT_HCI_OP_WRITE_LOCAL_NAME              BT_OP(BT_OGF_BASEBAND, 0x0013)
-struct bt_hci_write_local_name {
-	uint8_t local_name[248];
-} __packed;
-
-#define BT_HCI_OP_WRITE_PAGE_TIMEOUT            BT_OP(BT_OGF_BASEBAND, 0x0018)
-
-#define BT_HCI_OP_WRITE_SCAN_ENABLE             BT_OP(BT_OGF_BASEBAND, 0x001a)
-#define BT_BREDR_SCAN_DISABLED                  0x00
-#define BT_BREDR_SCAN_INQUIRY                   0x01
-#define BT_BREDR_SCAN_PAGE                      0x02
-
-#define BT_TX_POWER_LEVEL_CURRENT               0x00
-#define BT_TX_POWER_LEVEL_MAX                   0x01
-#define BT_HCI_OP_READ_TX_POWER_LEVEL           BT_OP(BT_OGF_BASEBAND, 0x002d)
-struct bt_hci_cp_read_tx_power_level {
-	uint16_t handle;
-	uint8_t  type;
-} __packed;
-
-struct bt_hci_rp_read_tx_power_level {
-	uint8_t  status;
-	uint16_t handle;
-	int8_t   tx_power_level;
-} __packed;
-
-#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE         0x00
-#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE          0x01
-#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW          BT_OP(BT_OGF_BASEBAND, 0x0031)
-struct bt_hci_cp_set_ctl_to_host_flow {
-	uint8_t  flow_enable;
-} __packed;
-
-#define BT_HCI_OP_HOST_BUFFER_SIZE              BT_OP(BT_OGF_BASEBAND, 0x0033)
-struct bt_hci_cp_host_buffer_size {
-	uint16_t acl_mtu;
-	uint8_t  sco_mtu;
-	uint16_t acl_pkts;
-	uint16_t sco_pkts;
-} __packed;
-
-struct bt_hci_handle_count {
-	uint16_t handle;
-	uint16_t count;
-} __packed;
-
-#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS    BT_OP(BT_OGF_BASEBAND, 0x0035)
-struct bt_hci_cp_host_num_completed_packets {
-	uint8_t  num_handles;
-	struct bt_hci_handle_count h[0];
-} __packed;
-
-#define BT_HCI_OP_WRITE_INQUIRY_MODE            BT_OP(BT_OGF_BASEBAND, 0x0045)
-struct bt_hci_cp_write_inquiry_mode {
-	uint8_t  mode;
-} __packed;
-
-#define BT_HCI_OP_WRITE_SSP_MODE                BT_OP(BT_OGF_BASEBAND, 0x0056)
-struct bt_hci_cp_write_ssp_mode {
-	uint8_t mode;
-} __packed;
-
-#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2         BT_OP(BT_OGF_BASEBAND, 0x0063)
-struct bt_hci_cp_set_event_mask_page_2 {
-	uint8_t  events_page_2[8];
-} __packed;
-
-#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP         BT_OP(BT_OGF_BASEBAND, 0x006d)
-struct bt_hci_cp_write_le_host_supp {
-	uint8_t  le;
-	uint8_t  simul;
-} __packed;
-
-#define BT_HCI_OP_WRITE_SC_HOST_SUPP            BT_OP(BT_OGF_BASEBAND, 0x007a)
-struct bt_hci_cp_write_sc_host_supp {
-	uint8_t  sc_support;
-} __packed;
-
-#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT     BT_OP(BT_OGF_BASEBAND, 0x007b)
-struct bt_hci_cp_read_auth_payload_timeout {
-	uint16_t handle;
-} __packed;
-
-struct bt_hci_rp_read_auth_payload_timeout {
-	uint8_t  status;
-	uint16_t handle;
-	uint16_t auth_payload_timeout;
-} __packed;
-
-#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT    BT_OP(BT_OGF_BASEBAND, 0x007c)
-struct bt_hci_cp_write_auth_payload_timeout {
-	uint16_t handle;
-	uint16_t auth_payload_timeout;
-} __packed;
-
-struct bt_hci_rp_write_auth_payload_timeout {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-/* HCI version from Assigned Numbers */
-#define BT_HCI_VERSION_1_0B                     0
-#define BT_HCI_VERSION_1_1                      1
-#define BT_HCI_VERSION_1_2                      2
-#define BT_HCI_VERSION_2_0                      3
-#define BT_HCI_VERSION_2_1                      4
-#define BT_HCI_VERSION_3_0                      5
-#define BT_HCI_VERSION_4_0                      6
-#define BT_HCI_VERSION_4_1                      7
-#define BT_HCI_VERSION_4_2                      8
-#define BT_HCI_VERSION_5_0                      9
-#define BT_HCI_VERSION_5_1                      10
-#define BT_HCI_VERSION_5_2                      11
-
-#define BT_HCI_OP_READ_LOCAL_VERSION_INFO       BT_OP(BT_OGF_INFO, 0x0001)
-struct bt_hci_rp_read_local_version_info {
-	uint8_t  status;
-	uint8_t  hci_version;
-	uint16_t hci_revision;
-	uint8_t  lmp_version;
-	uint16_t manufacturer;
-	uint16_t lmp_subversion;
-} __packed;
-
-#define BT_HCI_OP_READ_SUPPORTED_COMMANDS       BT_OP(BT_OGF_INFO, 0x0002)
-struct bt_hci_rp_read_supported_commands {
-	uint8_t  status;
-	uint8_t  commands[64];
-} __packed;
-
-#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES       BT_OP(BT_OGF_INFO, 0x0004)
-struct bt_hci_cp_read_local_ext_features {
-	uint8_t page;
-};
-struct bt_hci_rp_read_local_ext_features {
-	uint8_t  status;
-	uint8_t  page;
-	uint8_t  max_page;
-	uint8_t  ext_features[8];
-} __packed;
-
-#define BT_HCI_OP_READ_LOCAL_FEATURES           BT_OP(BT_OGF_INFO, 0x0003)
-struct bt_hci_rp_read_local_features {
-	uint8_t  status;
-	uint8_t  features[8];
-} __packed;
-
-#define BT_HCI_OP_READ_BUFFER_SIZE              BT_OP(BT_OGF_INFO, 0x0005)
-struct bt_hci_rp_read_buffer_size {
-	uint8_t  status;
-	uint16_t acl_max_len;
-	uint8_t  sco_max_len;
-	uint16_t acl_max_num;
-	uint16_t sco_max_num;
-} __packed;
-
-#define BT_HCI_OP_READ_BD_ADDR                  BT_OP(BT_OGF_INFO, 0x0009)
-struct bt_hci_rp_read_bd_addr {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_OP_READ_RSSI                     BT_OP(BT_OGF_STATUS, 0x0005)
-struct bt_hci_cp_read_rssi {
-	uint16_t handle;
-} __packed;
-struct bt_hci_rp_read_rssi {
-	uint8_t  status;
-	uint16_t handle;
-	int8_t   rssi;
-} __packed;
-
-#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN          7
-#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX          16
-
-#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE      BT_OP(BT_OGF_STATUS, 0x0008)
-struct bt_hci_cp_read_encryption_key_size {
-	uint16_t handle;
-} __packed;
-struct bt_hci_rp_read_encryption_key_size {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  key_size;
-} __packed;
-
-/* BLE */
-
-#define BT_HCI_OP_LE_SET_EVENT_MASK             BT_OP(BT_OGF_LE, 0x0001)
-struct bt_hci_cp_le_set_event_mask {
-	uint8_t events[8];
-} __packed;
-
-#define BT_HCI_OP_LE_READ_BUFFER_SIZE           BT_OP(BT_OGF_LE, 0x0002)
-struct bt_hci_rp_le_read_buffer_size {
-	uint8_t  status;
-	uint16_t le_max_len;
-	uint8_t  le_max_num;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_LOCAL_FEATURES        BT_OP(BT_OGF_LE, 0x0003)
-struct bt_hci_rp_le_read_local_features {
-	uint8_t  status;
-	uint8_t  features[8];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS         BT_OP(BT_OGF_LE, 0x0005)
-struct bt_hci_cp_le_set_random_address {
-	bt_addr_t bdaddr;
-} __packed;
-
-/* LE Advertising Types (LE Advertising Parameters Set)*/
-#define BT_LE_ADV_IND                  (__DEPRECATED_MACRO 0x00)
-#define BT_LE_ADV_DIRECT_IND           (__DEPRECATED_MACRO 0x01)
-#define BT_LE_ADV_SCAN_IND             (__DEPRECATED_MACRO 0x02)
-#define BT_LE_ADV_NONCONN_IND          (__DEPRECATED_MACRO 0x03)
-#define BT_LE_ADV_DIRECT_IND_LOW_DUTY  (__DEPRECATED_MACRO 0x04)
-/* LE Advertising PDU Types. */
-#define BT_LE_ADV_SCAN_RSP             (__DEPRECATED_MACRO 0x04)
-
-#define BT_HCI_ADV_IND                          0x00
-#define BT_HCI_ADV_DIRECT_IND                   0x01
-#define BT_HCI_ADV_SCAN_IND                     0x02
-#define BT_HCI_ADV_NONCONN_IND                  0x03
-#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY          0x04
-#define BT_HCI_ADV_SCAN_RSP                     0x04
-
-#define BT_LE_ADV_FP_NO_WHITELIST               0x00
-#define BT_LE_ADV_FP_WHITELIST_SCAN_REQ         0x01
-#define BT_LE_ADV_FP_WHITELIST_CONN_IND         0x02
-#define BT_LE_ADV_FP_WHITELIST_BOTH             0x03
-
-#define BT_HCI_OP_LE_SET_ADV_PARAM              BT_OP(BT_OGF_LE, 0x0006)
-struct bt_hci_cp_le_set_adv_param {
-	uint16_t     min_interval;
-	uint16_t     max_interval;
-	uint8_t      type;
-	uint8_t      own_addr_type;
-	bt_addr_le_t direct_addr;
-	uint8_t      channel_map;
-	uint8_t      filter_policy;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER     BT_OP(BT_OGF_LE, 0x0007)
-struct bt_hci_rp_le_read_chan_tx_power {
-	uint8_t status;
-	int8_t  tx_power_level;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_ADV_DATA               BT_OP(BT_OGF_LE, 0x0008)
-struct bt_hci_cp_le_set_adv_data {
-	uint8_t  len;
-	uint8_t  data[31];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA          BT_OP(BT_OGF_LE, 0x0009)
-struct bt_hci_cp_le_set_scan_rsp_data {
-	uint8_t  len;
-	uint8_t  data[31];
-} __packed;
-
-#define BT_HCI_LE_ADV_DISABLE                   0x00
-#define BT_HCI_LE_ADV_ENABLE                    0x01
-
-#define BT_HCI_OP_LE_SET_ADV_ENABLE             BT_OP(BT_OGF_LE, 0x000a)
-struct bt_hci_cp_le_set_adv_enable {
-	uint8_t  enable;
-} __packed;
-
-/* Scan types */
-#define BT_HCI_OP_LE_SET_SCAN_PARAM             BT_OP(BT_OGF_LE, 0x000b)
-#define BT_HCI_LE_SCAN_PASSIVE                  0x00
-#define BT_HCI_LE_SCAN_ACTIVE                   0x01
-
-#define BT_HCI_LE_SCAN_FP_NO_WHITELIST          0x00
-#define BT_HCI_LE_SCAN_FP_USE_WHITELIST         0x01
-
-struct bt_hci_cp_le_set_scan_param {
-	uint8_t  scan_type;
-	uint16_t interval;
-	uint16_t window;
-	uint8_t  addr_type;
-	uint8_t  filter_policy;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_SCAN_ENABLE            BT_OP(BT_OGF_LE, 0x000c)
-
-#define BT_HCI_LE_SCAN_DISABLE                  0x00
-#define BT_HCI_LE_SCAN_ENABLE                   0x01
-
-#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE       0x00
-#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE        0x01
-
-struct bt_hci_cp_le_set_scan_enable {
-	uint8_t  enable;
-	uint8_t  filter_dup;
-} __packed;
-
-#define BT_HCI_OP_LE_CREATE_CONN                BT_OP(BT_OGF_LE, 0x000d)
-
-#define BT_HCI_LE_CREATE_CONN_FP_DIRECT         0x00
-#define BT_HCI_LE_CREATE_CONN_FP_WHITELIST      0x01
-
-struct bt_hci_cp_le_create_conn {
-	uint16_t     scan_interval;
-	uint16_t     scan_window;
-	uint8_t      filter_policy;
-	bt_addr_le_t peer_addr;
-	uint8_t      own_addr_type;
-	uint16_t     conn_interval_min;
-	uint16_t     conn_interval_max;
-	uint16_t     conn_latency;
-	uint16_t     supervision_timeout;
-	uint16_t     min_ce_len;
-	uint16_t     max_ce_len;
-} __packed;
-
-#define BT_HCI_OP_LE_CREATE_CONN_CANCEL         BT_OP(BT_OGF_LE, 0x000e)
-
-#define BT_HCI_OP_LE_READ_WL_SIZE               BT_OP(BT_OGF_LE, 0x000f)
-struct bt_hci_rp_le_read_wl_size {
-	uint8_t  status;
-	uint8_t  wl_size;
-} __packed;
-
-#define BT_HCI_OP_LE_CLEAR_WL                   BT_OP(BT_OGF_LE, 0x0010)
-
-#define BT_HCI_OP_LE_ADD_DEV_TO_WL              BT_OP(BT_OGF_LE, 0x0011)
-struct bt_hci_cp_le_add_dev_to_wl {
-	bt_addr_le_t  addr;
-} __packed;
-
-#define BT_HCI_OP_LE_REM_DEV_FROM_WL            BT_OP(BT_OGF_LE, 0x0012)
-struct bt_hci_cp_le_rem_dev_from_wl {
-	bt_addr_le_t  addr;
-} __packed;
-
-#define BT_HCI_OP_LE_CONN_UPDATE                BT_OP(BT_OGF_LE, 0x0013)
-struct hci_cp_le_conn_update {
-	uint16_t handle;
-	uint16_t conn_interval_min;
-	uint16_t conn_interval_max;
-	uint16_t conn_latency;
-	uint16_t supervision_timeout;
-	uint16_t min_ce_len;
-	uint16_t max_ce_len;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF      BT_OP(BT_OGF_LE, 0x0014)
-struct bt_hci_cp_le_set_host_chan_classif {
-	uint8_t  ch_map[5];
-} __packed;
-
-#define BT_HCI_OP_LE_READ_CHAN_MAP              BT_OP(BT_OGF_LE, 0x0015)
-struct bt_hci_cp_le_read_chan_map {
-	uint16_t handle;
-} __packed;
-struct bt_hci_rp_le_read_chan_map {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  ch_map[5];
-} __packed;
-
-#define BT_HCI_OP_LE_READ_REMOTE_FEATURES       BT_OP(BT_OGF_LE, 0x0016)
-struct bt_hci_cp_le_read_remote_features {
-	uint16_t  handle;
-} __packed;
-
-#define BT_HCI_OP_LE_ENCRYPT                    BT_OP(BT_OGF_LE, 0x0017)
-struct bt_hci_cp_le_encrypt {
-	uint8_t  key[16];
-	uint8_t  plaintext[16];
-} __packed;
-struct bt_hci_rp_le_encrypt {
-	uint8_t  status;
-	uint8_t  enc_data[16];
-} __packed;
-
-#define BT_HCI_OP_LE_RAND                       BT_OP(BT_OGF_LE, 0x0018)
-struct bt_hci_rp_le_rand {
-	uint8_t  status;
-	uint8_t  rand[8];
-} __packed;
-
-#define BT_HCI_OP_LE_START_ENCRYPTION           BT_OP(BT_OGF_LE, 0x0019)
-struct bt_hci_cp_le_start_encryption {
-	uint16_t handle;
-	uint64_t rand;
-	uint16_t ediv;
-	uint8_t  ltk[16];
-} __packed;
-
-#define BT_HCI_OP_LE_LTK_REQ_REPLY              BT_OP(BT_OGF_LE, 0x001a)
-struct bt_hci_cp_le_ltk_req_reply {
-	uint16_t handle;
-	uint8_t  ltk[16];
-} __packed;
-struct bt_hci_rp_le_ltk_req_reply {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY          BT_OP(BT_OGF_LE, 0x001b)
-struct bt_hci_cp_le_ltk_req_neg_reply {
-	uint16_t handle;
-} __packed;
-struct bt_hci_rp_le_ltk_req_neg_reply {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_SUPP_STATES           BT_OP(BT_OGF_LE, 0x001c)
-struct bt_hci_rp_le_read_supp_states {
-	uint8_t  status;
-	uint8_t  le_states[8];
-} __packed;
-
-#define BT_HCI_OP_LE_RX_TEST                    BT_OP(BT_OGF_LE, 0x001d)
-struct bt_hci_cp_le_rx_test {
-	uint8_t  rx_ch;
-} __packed;
-
-#define BT_HCI_OP_LE_TX_TEST                    BT_OP(BT_OGF_LE, 0x001e)
-struct bt_hci_cp_le_tx_test {
-	uint8_t  tx_ch;
-	uint8_t  test_data_len;
-	uint8_t  pkt_payload;
-} __packed;
-
-#define BT_HCI_OP_LE_TEST_END                   BT_OP(BT_OGF_LE, 0x001f)
-struct bt_hci_rp_le_test_end {
-	uint8_t  status;
-	uint16_t rx_pkt_count;
-} __packed;
-
-#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY       BT_OP(BT_OGF_LE, 0x0020)
-struct bt_hci_cp_le_conn_param_req_reply {
-	uint16_t handle;
-	uint16_t interval_min;
-	uint16_t interval_max;
-	uint16_t latency;
-	uint16_t timeout;
-	uint16_t min_ce_len;
-	uint16_t max_ce_len;
-} __packed;
-struct bt_hci_rp_le_conn_param_req_reply {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY   BT_OP(BT_OGF_LE, 0x0021)
-struct bt_hci_cp_le_conn_param_req_neg_reply {
-	uint16_t handle;
-	uint8_t  reason;
-} __packed;
-struct bt_hci_rp_le_conn_param_req_neg_reply {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_DATA_LEN               BT_OP(BT_OGF_LE, 0x0022)
-struct bt_hci_cp_le_set_data_len {
-	uint16_t handle;
-	uint16_t tx_octets;
-	uint16_t tx_time;
-} __packed;
-struct bt_hci_rp_le_set_data_len {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN      BT_OP(BT_OGF_LE, 0x0023)
-struct bt_hci_rp_le_read_default_data_len {
-	uint8_t  status;
-	uint16_t max_tx_octets;
-	uint16_t max_tx_time;
-} __packed;
-
-#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN     BT_OP(BT_OGF_LE, 0x0024)
-struct bt_hci_cp_le_write_default_data_len {
-	uint16_t max_tx_octets;
-	uint16_t max_tx_time;
-} __packed;
-
-#define BT_HCI_OP_LE_P256_PUBLIC_KEY            BT_OP(BT_OGF_LE, 0x0025)
-
-#define BT_HCI_OP_LE_GENERATE_DHKEY             BT_OP(BT_OGF_LE, 0x0026)
-struct bt_hci_cp_le_generate_dhkey {
-	uint8_t key[64];
-} __packed;
-
-#define BT_HCI_OP_LE_ADD_DEV_TO_RL              BT_OP(BT_OGF_LE, 0x0027)
-struct bt_hci_cp_le_add_dev_to_rl {
-	bt_addr_le_t  peer_id_addr;
-	uint8_t       peer_irk[16];
-	uint8_t       local_irk[16];
-} __packed;
-
-#define BT_HCI_OP_LE_REM_DEV_FROM_RL            BT_OP(BT_OGF_LE, 0x0028)
-struct bt_hci_cp_le_rem_dev_from_rl {
-	bt_addr_le_t  peer_id_addr;
-} __packed;
-
-#define BT_HCI_OP_LE_CLEAR_RL                   BT_OP(BT_OGF_LE, 0x0029)
-
-#define BT_HCI_OP_LE_READ_RL_SIZE               BT_OP(BT_OGF_LE, 0x002a)
-struct bt_hci_rp_le_read_rl_size {
-	uint8_t  status;
-	uint8_t  rl_size;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_PEER_RPA              BT_OP(BT_OGF_LE, 0x002b)
-struct bt_hci_cp_le_read_peer_rpa {
-	bt_addr_le_t  peer_id_addr;
-} __packed;
-struct bt_hci_rp_le_read_peer_rpa {
-	uint8_t    status;
-	bt_addr_t  peer_rpa;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_LOCAL_RPA             BT_OP(BT_OGF_LE, 0x002c)
-struct bt_hci_cp_le_read_local_rpa {
-	bt_addr_le_t  peer_id_addr;
-} __packed;
-struct bt_hci_rp_le_read_local_rpa {
-	uint8_t    status;
-	bt_addr_t  local_rpa;
-} __packed;
-
-#define BT_HCI_ADDR_RES_DISABLE                 0x00
-#define BT_HCI_ADDR_RES_ENABLE                  0x01
-
-#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE        BT_OP(BT_OGF_LE, 0x002d)
-struct bt_hci_cp_le_set_addr_res_enable {
-	uint8_t  enable;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_RPA_TIMEOUT            BT_OP(BT_OGF_LE, 0x002e)
-struct bt_hci_cp_le_set_rpa_timeout {
-	uint16_t rpa_timeout;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_MAX_DATA_LEN          BT_OP(BT_OGF_LE, 0x002f)
-struct bt_hci_rp_le_read_max_data_len {
-	uint8_t  status;
-	uint16_t max_tx_octets;
-	uint16_t max_tx_time;
-	uint16_t max_rx_octets;
-	uint16_t max_rx_time;
-} __packed;
-
-#define BT_HCI_LE_PHY_1M                        0x01
-#define BT_HCI_LE_PHY_2M                        0x02
-#define BT_HCI_LE_PHY_CODED                     0x03
-
-#define BT_HCI_OP_LE_READ_PHY                   BT_OP(BT_OGF_LE, 0x0030)
-struct bt_hci_cp_le_read_phy {
-	uint16_t handle;
-} __packed;
-struct bt_hci_rp_le_read_phy {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  tx_phy;
-	uint8_t  rx_phy;
-} __packed;
-
-#define BT_HCI_LE_PHY_TX_ANY                    BIT(0)
-#define BT_HCI_LE_PHY_RX_ANY                    BIT(1)
-
-#define BT_HCI_LE_PHY_PREFER_1M                 BIT(0)
-#define BT_HCI_LE_PHY_PREFER_2M                 BIT(1)
-#define BT_HCI_LE_PHY_PREFER_CODED              BIT(2)
-
-#define BT_HCI_OP_LE_SET_DEFAULT_PHY            BT_OP(BT_OGF_LE, 0x0031)
-struct bt_hci_cp_le_set_default_phy {
-	uint8_t all_phys;
-	uint8_t tx_phys;
-	uint8_t rx_phys;
-} __packed;
-
-#define BT_HCI_LE_PHY_CODED_ANY                 0x00
-#define BT_HCI_LE_PHY_CODED_S2                  0x01
-#define BT_HCI_LE_PHY_CODED_S8                  0x02
-
-#define BT_HCI_OP_LE_SET_PHY                    BT_OP(BT_OGF_LE, 0x0032)
-struct bt_hci_cp_le_set_phy {
-	uint16_t  handle;
-	uint8_t   all_phys;
-	uint8_t   tx_phys;
-	uint8_t   rx_phys;
-	uint16_t  phy_opts;
-} __packed;
-
-#define BT_HCI_LE_MOD_INDEX_STANDARD            0x00
-#define BT_HCI_LE_MOD_INDEX_STABLE              0x01
-
-#define BT_HCI_OP_LE_ENH_RX_TEST                BT_OP(BT_OGF_LE, 0x0033)
-struct bt_hci_cp_le_enh_rx_test {
-	uint8_t  rx_ch;
-	uint8_t  phy;
-	uint8_t  mod_index;
-} __packed;
-
-/* Extends BT_HCI_LE_PHY */
-#define BT_HCI_LE_TX_PHY_CODED_S8               0x03
-#define BT_HCI_LE_TX_PHY_CODED_S2               0x04
-
-#define BT_HCI_OP_LE_ENH_TX_TEST                BT_OP(BT_OGF_LE, 0x0034)
-struct bt_hci_cp_le_enh_tx_test {
-	uint8_t  tx_ch;
-	uint8_t  test_data_len;
-	uint8_t  pkt_payload;
-	uint8_t  phy;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR    BT_OP(BT_OGF_LE, 0x0035)
-struct bt_hci_cp_le_set_adv_set_random_addr {
-	uint8_t   handle;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_LE_ADV_PROP_CONN                 BIT(0)
-#define BT_HCI_LE_ADV_PROP_SCAN                 BIT(1)
-#define BT_HCI_LE_ADV_PROP_DIRECT               BIT(2)
-#define BT_HCI_LE_ADV_PROP_HI_DC_CONN           BIT(3)
-#define BT_HCI_LE_ADV_PROP_LEGACY               BIT(4)
-#define BT_HCI_LE_ADV_PROP_ANON                 BIT(5)
-#define BT_HCI_LE_ADV_PROP_TX_POWER             BIT(6)
-
-#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE  1
-#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0
-
-#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F
-
-#define BT_HCI_LE_ADV_HANDLE_MAX       0xEF
-
-#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM          BT_OP(BT_OGF_LE, 0x0036)
-struct bt_hci_cp_le_set_ext_adv_param {
-	uint8_t      handle;
-	uint16_t     props;
-	uint8_t      prim_min_interval[3];
-	uint8_t      prim_max_interval[3];
-	uint8_t      prim_channel_map;
-	uint8_t      own_addr_type;
-	bt_addr_le_t peer_addr;
-	uint8_t      filter_policy;
-	int8_t       tx_power;
-	uint8_t      prim_adv_phy;
-	uint8_t      sec_adv_max_skip;
-	uint8_t      sec_adv_phy;
-	uint8_t      sid;
-	uint8_t      scan_req_notify_enable;
-} __packed;
-struct bt_hci_rp_le_set_ext_adv_param {
-	uint8_t status;
-	int8_t  tx_power;
-} __packed;
-
-#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG        0x00
-#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG         0x01
-#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG          0x02
-#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA      0x03
-#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA     0x04
-
-#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED          0x00
-#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED         0x01
-
-#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN          251
-
-#define BT_HCI_OP_LE_SET_EXT_ADV_DATA           BT_OP(BT_OGF_LE, 0x0037)
-struct bt_hci_cp_le_set_ext_adv_data {
-	uint8_t  handle;
-	uint8_t  op;
-	uint8_t  frag_pref;
-	uint8_t  len;
-	uint8_t  data[251];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA      BT_OP(BT_OGF_LE, 0x0038)
-struct bt_hci_cp_le_set_ext_scan_rsp_data {
-	uint8_t  handle;
-	uint8_t  op;
-	uint8_t  frag_pref;
-	uint8_t  len;
-	uint8_t  data[251];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0039)
-struct bt_hci_ext_adv_set {
-	uint8_t  handle;
-	uint16_t duration;
-	uint8_t  max_ext_adv_evts;
-} __packed;
-
-struct bt_hci_cp_le_set_ext_adv_enable {
-	uint8_t  enable;
-	uint8_t  set_num;
-	struct bt_hci_ext_adv_set s[0];
-} __packed;
-
-#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN      BT_OP(BT_OGF_LE, 0x003a)
-struct bt_hci_rp_le_read_max_adv_data_len {
-	uint8_t  status;
-	uint16_t max_adv_data_len;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_NUM_ADV_SETS          BT_OP(BT_OGF_LE, 0x003b)
-struct bt_hci_rp_le_read_num_adv_sets {
-	uint8_t  status;
-	uint8_t  num_sets;
-} __packed;
-
-#define BT_HCI_OP_LE_REMOVE_ADV_SET             BT_OP(BT_OGF_LE, 0x003c)
-struct bt_hci_cp_le_remove_adv_set {
-	uint8_t  handle;
-} __packed;
-
-#define BT_HCI_OP_CLEAR_ADV_SETS                BT_OP(BT_OGF_LE, 0x003d)
-
-#define BT_HCI_OP_LE_SET_PER_ADV_PARAM          BT_OP(BT_OGF_LE, 0x003e)
-struct bt_hci_cp_le_set_per_adv_param {
-	uint8_t  handle;
-	uint16_t min_interval;
-	uint16_t max_interval;
-	uint16_t props;
-} __packed;
-
-#define BT_HCI_LE_PER_ADV_OP_INTERM_FRAG        0x00
-#define BT_HCI_LE_PER_ADV_OP_FIRST_FRAG         0x01
-#define BT_HCI_LE_PER_ADV_OP_LAST_FRAG          0x02
-#define BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA      0x03
-
-#define BT_HCI_LE_PER_ADV_FRAG_MAX_LEN          252
-
-#define BT_HCI_OP_LE_SET_PER_ADV_DATA           BT_OP(BT_OGF_LE, 0x003f)
-struct bt_hci_cp_le_set_per_adv_data {
-	uint8_t  handle;
-	uint8_t  op;
-	uint8_t  len;
-	uint8_t  data[251];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0040)
-struct bt_hci_cp_le_set_per_adv_enable {
-	uint8_t  enable;
-	uint8_t  handle;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM         BT_OP(BT_OGF_LE, 0x0041)
-struct bt_hci_ext_scan_phy {
-	uint8_t  type;
-	uint16_t interval;
-	uint16_t window;
-} __packed;
-
-#define BT_HCI_LE_EXT_SCAN_PHY_1M               BIT(0)
-#define BT_HCI_LE_EXT_SCAN_PHY_2M               BIT(1)
-#define BT_HCI_LE_EXT_SCAN_PHY_CODED            BIT(2)
-
-struct bt_hci_cp_le_set_ext_scan_param {
-	uint8_t  own_addr_type;
-	uint8_t  filter_policy;
-	uint8_t  phys;
-	struct bt_hci_ext_scan_phy p[0];
-} __packed;
-
-/* Extends BT_HCI_LE_SCAN_FILTER_DUP */
-#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET  0x02
-
-#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE        BT_OP(BT_OGF_LE, 0x0042)
-struct bt_hci_cp_le_set_ext_scan_enable {
-	uint8_t  enable;
-	uint8_t  filter_dup;
-	uint16_t duration;
-	uint16_t period;
-} __packed;
-
-#define BT_HCI_OP_LE_EXT_CREATE_CONN            BT_OP(BT_OGF_LE, 0x0043)
-struct bt_hci_ext_conn_phy {
-	uint16_t scan_interval;
-	uint16_t scan_window;
-	uint16_t conn_interval_min;
-	uint16_t conn_interval_max;
-	uint16_t conn_latency;
-	uint16_t supervision_timeout;
-	uint16_t min_ce_len;
-	uint16_t max_ce_len;
-} __packed;
-
-struct bt_hci_cp_le_ext_create_conn {
-	uint8_t      filter_policy;
-	uint8_t      own_addr_type;
-	bt_addr_le_t peer_addr;
-	uint8_t      phys;
-	struct bt_hci_ext_conn_phy p[0];
-} __packed;
-
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST               BIT(0)
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED       BIT(1)
-
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA           BIT(0)
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US       BIT(1)
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US       BIT(2)
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_CTE           BIT(3)
-#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE         BIT(4)
-
-#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC        BT_OP(BT_OGF_LE, 0x0044)
-struct bt_hci_cp_le_per_adv_create_sync {
-	uint8_t      options;
-	uint8_t      sid;
-	bt_addr_le_t addr;
-	uint16_t     skip;
-	uint16_t     sync_timeout;
-	uint8_t      cte_type;
-} __packed;
-
-#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045)
-
-#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC     BT_OP(BT_OGF_LE, 0x0046)
-struct bt_hci_cp_le_per_adv_terminate_sync {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST    BT_OP(BT_OGF_LE, 0x0047)
-struct bt_hci_cp_le_add_dev_to_per_adv_list {
-	bt_addr_le_t addr;
-	uint8_t      sid;
-} __packed;
-
-#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST  BT_OP(BT_OGF_LE, 0x0048)
-struct bt_hci_cp_le_rem_dev_from_per_adv_list {
-	bt_addr_le_t addr;
-	uint8_t      sid;
-} __packed;
-
-#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST         BT_OP(BT_OGF_LE, 0x0049)
-
-#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE     BT_OP(BT_OGF_LE, 0x004a)
-struct bt_hci_rp_le_read_per_adv_list_size {
-	uint8_t  status;
-	uint8_t  list_size;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_TX_POWER              BT_OP(BT_OGF_LE, 0x004b)
-struct bt_hci_rp_le_read_tx_power {
-	uint8_t status;
-	int8_t  min_tx_power;
-	int8_t  max_tx_power;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_RF_PATH_COMP          BT_OP(BT_OGF_LE, 0x004c)
-struct bt_hci_rp_le_read_rf_path_comp {
-	uint8_t status;
-	int16_t tx_path_comp;
-	int16_t rx_path_comp;
-} __packed;
-
-#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP         BT_OP(BT_OGF_LE, 0x004d)
-struct bt_hci_cp_le_write_rf_path_comp {
-	int16_t  tx_path_comp;
-	int16_t  rx_path_comp;
-} __packed;
-
-#define BT_HCI_LE_PRIVACY_MODE_NETWORK          0x00
-#define BT_HCI_LE_PRIVACY_MODE_DEVICE           0x01
-
-#define BT_HCI_OP_LE_SET_PRIVACY_MODE           BT_OP(BT_OGF_LE, 0x004e)
-struct bt_hci_cp_le_set_privacy_mode {
-	bt_addr_le_t id_addr;
-	uint8_t         mode;
-} __packed;
-
-#define BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE     BT_OP(BT_OGF_LE, 0x0059)
-struct bt_hci_cp_le_set_per_adv_recv_enable {
-	uint16_t handle;
-	uint8_t  enable;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_BUFFER_SIZE_V2        BT_OP(BT_OGF_LE, 0x0060)
-struct bt_hci_rp_le_read_buffer_size_v2 {
-	uint8_t  status;
-	uint16_t acl_mtu;
-	uint8_t  acl_max_pkt;
-	uint16_t iso_mtu;
-	uint8_t  iso_max_pkt;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_ISO_TX_SYNC           BT_OP(BT_OGF_LE, 0x0061)
-struct bt_hci_cp_le_read_iso_tx_sync {
-	uint16_t handle;
-} __packed;
-
-struct bt_hci_rp_le_read_iso_tx_sync {
-	uint8_t  status;
-	uint16_t handle;
-	uint16_t seq;
-	uint32_t timestamp;
-	uint8_t  offset[3];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_CIG_PARAMS             BT_OP(BT_OGF_LE, 0x0062)
-struct bt_hci_cis_params {
-	uint8_t  cis_id;
-	uint16_t m_sdu;
-	uint16_t s_sdu;
-	uint8_t  m_phy;
-	uint8_t  s_phy;
-	uint8_t  m_rtn;
-	uint8_t  s_rtn;
-} __packed;
-
-struct bt_hci_cp_le_set_cig_params {
-	uint8_t  cig_id;
-	uint8_t  m_interval[3];
-	uint8_t  s_interval[3];
-	uint8_t  sca;
-	uint8_t  packing;
-	uint8_t  framing;
-	uint16_t m_latency;
-	uint16_t s_latency;
-	uint8_t  num_cis;
-	struct bt_hci_cis_params cis[0];
-} __packed;
-
-struct bt_hci_rp_le_set_cig_params {
-	uint8_t  status;
-	uint8_t  cig_id;
-	uint8_t  num_handles;
-	uint16_t handle[0];
-} __packed;
-
-#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST        BT_OP(BT_OGF_LE, 0x0063)
-
-#define BT_HCI_OP_LE_CREATE_CIS                 BT_OP(BT_OGF_LE, 0x0064)
-struct bt_hci_cis {
-	uint16_t  cis_handle;
-	uint16_t  acl_handle;
-} __packed;
-
-struct bt_hci_cp_le_create_cis {
-	uint8_t  num_cis;
-	struct bt_hci_cis cis[0];
-} __packed;
-
-#define BT_HCI_OP_LE_REMOVE_CIG                 BT_OP(BT_OGF_LE, 0x0065)
-struct bt_hci_cp_le_remove_cig {
-	uint8_t  cig_id;
-} __packed;
-
-struct bt_hci_rp_le_remove_cig {
-	uint8_t  status;
-	uint8_t  cig_id;
-} __packed;
-
-#define BT_HCI_OP_LE_ACCEPT_CIS                 BT_OP(BT_OGF_LE, 0x0066)
-struct bt_hci_cp_le_accept_cis {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_REJECT_CIS                 BT_OP(BT_OGF_LE, 0x0067)
-struct bt_hci_cp_le_reject_cis {
-	uint16_t handle;
-	uint8_t  reason;
-} __packed;
-
-struct bt_hci_rp_le_reject_cis {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_CREATE_BIG                 BT_OP(BT_OGF_LE, 0x0068)
-struct bt_hci_cp_le_create_big {
-	uint8_t  big_handle;
-	uint8_t  adv_handle;
-	uint8_t  num_bis;
-	uint8_t  sdu_interval[3];
-	uint16_t max_sdu;
-	uint16_t max_latency;
-	uint8_t  rtn;
-	uint8_t  phy;
-	uint8_t  packing;
-	uint8_t  framing;
-	uint8_t  encryption;
-	uint8_t  bcode[16];
-} __packed;
-
-#define BT_HCI_OP_LE_CREATE_BIG_TEST            BT_OP(BT_OGF_LE, 0x0069)
-struct bt_hci_cp_le_create_big_test {
-	uint8_t  big_handle;
-	uint8_t  adv_handle;
-	uint8_t  num_bis;
-	uint8_t  sdu_interval[3];
-	uint16_t iso_interval;
-	uint8_t  nse;
-	uint16_t max_sdu;
-	uint16_t max_pdu;
-	uint8_t  phy;
-	uint8_t  packing;
-	uint8_t  framing;
-	uint8_t  bn;
-	uint8_t  irc;
-	uint8_t  pto;
-	uint8_t  encryption;
-	uint8_t  bcode[16];
-} __packed;
-
-#define BT_HCI_OP_LE_TERMINATE_BIG              BT_OP(BT_OGF_LE, 0x006a)
-struct bt_hci_cp_le_terminate_big {
-	uint8_t  big_handle;
-	uint8_t  reason;
-} __packed;
-
-#define BT_HCI_OP_LE_BIG_CREATE_SYNC            BT_OP(BT_OGF_LE, 0x006b)
-struct bt_hci_cp_le_big_create_sync {
-	uint8_t  big_handle;
-	uint16_t sync_handle;
-	uint8_t  encryption;
-	uint8_t  bcode[16];
-	uint8_t  mse;
-	uint16_t sync_timeout;
-	uint8_t  num_bis;
-	uint8_t  bis[0];
-} __packed;
-
-#define BT_HCI_OP_LE_BIG_TERMINATE_SYNC         BT_OP(BT_OGF_LE, 0x006c)
-struct bt_hci_cp_le_big_terminate_sync {
-	uint8_t  big_handle;
-} __packed;
-
-struct bt_hci_rp_le_big_terminate_sync {
-	uint8_t  status;
-	uint8_t  big_handle;
-} __packed;
-
-#define BT_HCI_OP_LE_REQ_PEER_SC                BT_OP(BT_OGF_LE, 0x006d)
-struct bt_hci_cp_le_req_peer_sca {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_SETUP_ISO_PATH             BT_OP(BT_OGF_LE, 0x006e)
-struct bt_hci_cp_le_setup_iso_path {
-	uint16_t handle;
-	uint8_t  path_dir;
-	uint8_t  path_id;
-	uint8_t  coding_format;
-	uint16_t company_id;
-	uint16_t vendor_id;
-	uint8_t  controller_delay[3];
-	uint8_t  codec_config_len;
-	uint8_t  codec_config[0];
-} __packed;
-
-struct bt_hci_rp_le_setup_iso_path {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_REMOVE_ISO_PATH            BT_OP(BT_OGF_LE, 0x006f)
-struct bt_hci_cp_le_remove_iso_path {
-	uint16_t handle;
-	uint8_t  path_dir;
-} __packed;
-
-struct bt_hci_rp_le_remove_iso_path {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST          BT_OP(BT_OGF_LE, 0x0070)
-
-#define BT_HCI_OP_LE_ISO_RECEIVE_TEST           BT_OP(BT_OGF_LE, 0x0071)
-
-#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS     BT_OP(BT_OGF_LE, 0x0072)
-
-#define BT_HCI_OP_LE_ISO_TEST_END               BT_OP(BT_OGF_LE, 0x0073)
-
-#define BT_HCI_OP_LE_SET_HOST_FEATURE           BT_OP(BT_OGF_LE, 0x0074)
-struct bt_hci_cp_le_set_host_feature {
-	uint8_t  bit_number;
-	uint8_t  bit_value;
-} __packed;
-
-struct bt_hci_rp_le_set_host_feature {
-	uint8_t  status;
-} __packed;
-
-#define BT_HCI_OP_LE_READ_ISO_LINK_QUALITY      BT_OP(BT_OGF_LE, 0x0075)
-struct bt_hci_cp_le_read_iso_link_quality {
-	uint16_t handle;
-} __packed;
-
-struct bt_hci_rp_le_read_iso_link_quality {
-	uint8_t  status;
-	uint16_t handle;
-	uint32_t tx_unacked_packets;
-	uint32_t tx_flushed_packets;
-	uint32_t tx_last_subevent_packets;
-	uint32_t retransmitted_packets;
-	uint32_t crc_error_packets;
-	uint32_t rx_unreceived_packets;
-	uint32_t duplicate_packets;
-} __packed;
-
-/* Event definitions */
-
-#define BT_HCI_EVT_UNKNOWN                      0x00
-#define BT_HCI_EVT_VENDOR                       0xff
-
-#define BT_HCI_EVT_INQUIRY_COMPLETE             0x01
-struct bt_hci_evt_inquiry_complete {
-	uint8_t status;
-} __packed;
-
-#define BT_HCI_EVT_CONN_COMPLETE                0x03
-struct bt_hci_evt_conn_complete {
-	uint8_t   status;
-	uint16_t  handle;
-	bt_addr_t bdaddr;
-	uint8_t   link_type;
-	uint8_t   encr_enabled;
-} __packed;
-
-#define BT_HCI_EVT_CONN_REQUEST                 0x04
-struct bt_hci_evt_conn_request {
-	bt_addr_t bdaddr;
-	uint8_t   dev_class[3];
-	uint8_t   link_type;
-} __packed;
-
-#define BT_HCI_EVT_DISCONN_COMPLETE             0x05
-struct bt_hci_evt_disconn_complete {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  reason;
-} __packed;
-
-#define BT_HCI_EVT_AUTH_COMPLETE                0x06
-struct bt_hci_evt_auth_complete {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE     0x07
-struct bt_hci_evt_remote_name_req_complete {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-	uint8_t   name[248];
-} __packed;
-
-#define BT_HCI_EVT_ENCRYPT_CHANGE               0x08
-struct bt_hci_evt_encrypt_change {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  encrypt;
-} __packed;
-
-#define BT_HCI_EVT_REMOTE_FEATURES              0x0b
-struct bt_hci_evt_remote_features {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  features[8];
-} __packed;
-
-#define BT_HCI_EVT_REMOTE_VERSION_INFO          0x0c
-struct bt_hci_evt_remote_version_info {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  version;
-	uint16_t manufacturer;
-	uint16_t subversion;
-} __packed;
-
-#define BT_HCI_EVT_CMD_COMPLETE                 0x0e
-struct bt_hci_evt_cmd_complete {
-	uint8_t  ncmd;
-	uint16_t opcode;
-} __packed;
-
-struct bt_hci_evt_cc_status {
-	uint8_t  status;
-} __packed;
-
-#define BT_HCI_EVT_CMD_STATUS                   0x0f
-struct bt_hci_evt_cmd_status {
-	uint8_t  status;
-	uint8_t  ncmd;
-	uint16_t opcode;
-} __packed;
-
-#define BT_HCI_EVT_HARDWARE_ERROR               0x10
-struct bt_hci_evt_hardware_error {
-	uint8_t  hardware_code;
-} __packed;
-
-#define BT_HCI_EVT_ROLE_CHANGE                  0x12
-struct bt_hci_evt_role_change {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-	uint8_t   role;
-} __packed;
-
-#define BT_HCI_EVT_NUM_COMPLETED_PACKETS        0x13
-struct bt_hci_evt_num_completed_packets {
-	uint8_t  num_handles;
-	struct bt_hci_handle_count h[0];
-} __packed;
-
-#define BT_HCI_EVT_PIN_CODE_REQ                 0x16
-struct bt_hci_evt_pin_code_req {
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_EVT_LINK_KEY_REQ                 0x17
-struct bt_hci_evt_link_key_req {
-	bt_addr_t bdaddr;
-} __packed;
-
-/* Link Key types */
-#define BT_LK_COMBINATION                       0x00
-#define BT_LK_LOCAL_UNIT                        0x01
-#define BT_LK_REMOTE_UNIT                       0x02
-#define BT_LK_DEBUG_COMBINATION                 0x03
-#define BT_LK_UNAUTH_COMBINATION_P192           0x04
-#define BT_LK_AUTH_COMBINATION_P192             0x05
-#define BT_LK_CHANGED_COMBINATION               0x06
-#define BT_LK_UNAUTH_COMBINATION_P256           0x07
-#define BT_LK_AUTH_COMBINATION_P256             0x08
-
-#define BT_HCI_EVT_LINK_KEY_NOTIFY              0x18
-struct bt_hci_evt_link_key_notify {
-	bt_addr_t bdaddr;
-	uint8_t   link_key[16];
-	uint8_t   key_type;
-} __packed;
-
-/* Overflow link types */
-#define BT_OVERFLOW_LINK_SYNCH                  0x00
-#define BT_OVERFLOW_LINK_ACL                    0x01
-
-#define BT_HCI_EVT_DATA_BUF_OVERFLOW            0x1a
-struct bt_hci_evt_data_buf_overflow {
-	uint8_t  link_type;
-} __packed;
-
-#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI     0x22
-struct bt_hci_evt_inquiry_result_with_rssi {
-	bt_addr_t addr;
-	uint8_t   pscan_rep_mode;
-	uint8_t   reserved;
-	uint8_t   cod[3];
-	uint16_t  clock_offset;
-	int8_t    rssi;
-} __packed;
-
-#define BT_HCI_EVT_REMOTE_EXT_FEATURES          0x23
-struct bt_hci_evt_remote_ext_features {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  page;
-	uint8_t  max_page;
-	uint8_t  features[8];
-} __packed;
-
-#define BT_HCI_EVT_SYNC_CONN_COMPLETE           0x2c
-struct bt_hci_evt_sync_conn_complete {
-	uint8_t    status;
-	uint16_t   handle;
-	bt_addr_t  bdaddr;
-	uint8_t    link_type;
-	uint8_t    tx_interval;
-	uint8_t    retansmission_window;
-	uint16_t   rx_pkt_length;
-	uint16_t   tx_pkt_length;
-	uint8_t    air_mode;
-} __packed;
-
-#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT      0x2f
-struct bt_hci_evt_extended_inquiry_result {
-	uint8_t    num_reports;
-	bt_addr_t  addr;
-	uint8_t    pscan_rep_mode;
-	uint8_t    reserved;
-	uint8_t    cod[3];
-	uint16_t   clock_offset;
-	int8_t     rssi;
-	uint8_t    eir[240];
-} __packed;
-
-#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30
-struct bt_hci_evt_encrypt_key_refresh_complete {
-	uint8_t  status;
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_EVT_IO_CAPA_REQ                  0x31
-struct bt_hci_evt_io_capa_req {
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_EVT_IO_CAPA_RESP                 0x32
-struct bt_hci_evt_io_capa_resp {
-	bt_addr_t bdaddr;
-	uint8_t   capability;
-	uint8_t   oob_data;
-	uint8_t   authentication;
-} __packed;
-
-#define BT_HCI_EVT_USER_CONFIRM_REQ             0x33
-struct bt_hci_evt_user_confirm_req {
-	bt_addr_t bdaddr;
-	uint32_t  passkey;
-} __packed;
-
-#define BT_HCI_EVT_USER_PASSKEY_REQ             0x34
-struct bt_hci_evt_user_passkey_req {
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_EVT_SSP_COMPLETE                 0x36
-struct bt_hci_evt_ssp_complete {
-	uint8_t   status;
-	bt_addr_t bdaddr;
-} __packed;
-
-#define BT_HCI_EVT_USER_PASSKEY_NOTIFY          0x3b
-struct bt_hci_evt_user_passkey_notify {
-	bt_addr_t bdaddr;
-	uint32_t  passkey;
-} __packed;
-
-#define BT_HCI_EVT_LE_META_EVENT                0x3e
-struct bt_hci_evt_le_meta_event {
-	uint8_t  subevent;
-} __packed;
-
-#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP     0x57
-struct bt_hci_evt_auth_payload_timeout_exp {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_ROLE_MASTER                      0x00
-#define BT_HCI_ROLE_SLAVE                       0x01
-
-#define BT_HCI_EVT_LE_CONN_COMPLETE             0x01
-struct bt_hci_evt_le_conn_complete {
-	uint8_t      status;
-	uint16_t     handle;
-	uint8_t      role;
-	bt_addr_le_t peer_addr;
-	uint16_t     interval;
-	uint16_t     latency;
-	uint16_t     supv_timeout;
-	uint8_t      clock_accuracy;
-} __packed;
-
-#define BT_HCI_EVT_LE_ADVERTISING_REPORT        0x02
-struct bt_hci_evt_le_advertising_info {
-	uint8_t      evt_type;
-	bt_addr_le_t addr;
-	uint8_t      length;
-	uint8_t      data[0];
-} __packed;
-struct bt_hci_evt_le_advertising_report {
-	uint8_t num_reports;
-	struct bt_hci_evt_le_advertising_info adv_info[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE      0x03
-struct bt_hci_evt_le_conn_update_complete {
-	uint8_t  status;
-	uint16_t handle;
-	uint16_t interval;
-	uint16_t latency;
-	uint16_t supv_timeout;
-} __packed;
-
-#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE       0x04
-struct bt_hci_evt_le_remote_feat_complete {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  features[8];
-} __packed;
-
-#define BT_HCI_EVT_LE_LTK_REQUEST               0x05
-struct bt_hci_evt_le_ltk_request {
-	uint16_t handle;
-	uint64_t rand;
-	uint16_t ediv;
-} __packed;
-
-#define BT_HCI_EVT_LE_CONN_PARAM_REQ            0x06
-struct bt_hci_evt_le_conn_param_req {
-	uint16_t handle;
-	uint16_t interval_min;
-	uint16_t interval_max;
-	uint16_t latency;
-	uint16_t timeout;
-} __packed;
-
-#define BT_HCI_EVT_LE_DATA_LEN_CHANGE           0x07
-struct bt_hci_evt_le_data_len_change {
-	uint16_t handle;
-	uint16_t max_tx_octets;
-	uint16_t max_tx_time;
-	uint16_t max_rx_octets;
-	uint16_t max_rx_time;
-} __packed;
-
-#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE  0x08
-struct bt_hci_evt_le_p256_public_key_complete {
-	uint8_t status;
-	uint8_t key[64];
-} __packed;
-
-#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE   0x09
-struct bt_hci_evt_le_generate_dhkey_complete {
-	uint8_t status;
-	uint8_t dhkey[32];
-} __packed;
-
-#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE         0x0a
-struct bt_hci_evt_le_enh_conn_complete {
-	uint8_t      status;
-	uint16_t     handle;
-	uint8_t      role;
-	bt_addr_le_t peer_addr;
-	bt_addr_t    local_rpa;
-	bt_addr_t    peer_rpa;
-	uint16_t     interval;
-	uint16_t     latency;
-	uint16_t     supv_timeout;
-	uint8_t      clock_accuracy;
-} __packed;
-
-#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT         0x0b
-struct bt_hci_evt_le_direct_adv_info {
-	uint8_t      evt_type;
-	bt_addr_le_t addr;
-	bt_addr_le_t dir_addr;
-	int8_t       rssi;
-} __packed;
-struct bt_hci_evt_le_direct_adv_report {
-	uint8_t num_reports;
-	struct bt_hci_evt_le_direct_adv_info direct_adv_info[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE       0x0c
-struct bt_hci_evt_le_phy_update_complete {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  tx_phy;
-	uint8_t  rx_phy;
-} __packed;
-
-#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT    0x0d
-
-#define BT_HCI_LE_ADV_EVT_TYPE_CONN                 BIT(0)
-#define BT_HCI_LE_ADV_EVT_TYPE_SCAN                 BIT(1)
-#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT               BIT(2)
-#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP             BIT(3)
-#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY               BIT(4)
-
-#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03)
-#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE   0
-#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL    1
-#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2
-
-struct bt_hci_evt_le_ext_advertising_info {
-	uint16_t     evt_type;
-	bt_addr_le_t addr;
-	uint8_t      prim_phy;
-	uint8_t      sec_phy;
-	uint8_t      sid;
-	int8_t       tx_power;
-	int8_t       rssi;
-	uint16_t     interval;
-	bt_addr_le_t direct_addr;
-	uint8_t      length;
-	uint8_t      data[0];
-} __packed;
-struct bt_hci_evt_le_ext_advertising_report {
-	uint8_t num_reports;
-	struct bt_hci_evt_le_ext_advertising_info adv_info[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED  0x0e
-struct bt_hci_evt_le_per_adv_sync_established {
-	uint8_t      status;
-	uint16_t     handle;
-	uint8_t      sid;
-	bt_addr_le_t adv_addr;
-	uint8_t      phy;
-	uint16_t     interval;
-	uint8_t      clock_accuracy;
-} __packed;
-
-#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT    0x0f
-struct bt_hci_evt_le_per_advertising_report {
-	uint16_t handle;
-	int8_t   tx_power;
-	int8_t   rssi;
-	uint8_t  cte_type;
-	uint8_t  data_status;
-	uint8_t  length;
-	uint8_t  data[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST         0x10
-struct bt_hci_evt_le_per_adv_sync_lost {
-	uint16_t handle;
-} __packed;
-
-#define BT_HCI_EVT_LE_SCAN_TIMEOUT              0x11
-
-#define BT_HCI_EVT_LE_ADV_SET_TERMINATED        0x12
-struct bt_hci_evt_le_adv_set_terminated {
-	uint8_t  status;
-	uint8_t  adv_handle;
-	uint16_t conn_handle;
-	uint8_t  num_completed_ext_adv_evts;
-} __packed;
-
-#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED         0x13
-struct bt_hci_evt_le_scan_req_received {
-	uint8_t      handle;
-	bt_addr_le_t addr;
-} __packed;
-
-#define BT_HCI_LE_CHAN_SEL_ALGO_1               0x00
-#define BT_HCI_LE_CHAN_SEL_ALGO_2               0x01
-
-#define BT_HCI_EVT_LE_CHAN_SEL_ALGO             0x14
-struct bt_hci_evt_le_chan_sel_algo {
-	uint16_t handle;
-	uint8_t  chan_sel_algo;
-} __packed;
-
-#define BT_HCI_EVT_LE_CIS_ESTABLISHED           0x19
-struct bt_hci_evt_le_cis_established {
-	uint8_t  status;
-	uint16_t conn_handle;
-	uint8_t  cig_sync_delay[3];
-	uint8_t  cis_sync_delay[3];
-	uint8_t  m_latency[3];
-	uint8_t  s_latency[3];
-	uint8_t  m_phy;
-	uint8_t  s_phy;
-	uint8_t  nse;
-	uint8_t  m_bn;
-	uint8_t  s_bn;
-	uint8_t  m_ft;
-	uint8_t  s_ft;
-	uint16_t m_max_pdu;
-	uint16_t s_max_pdu;
-	uint16_t interval;
-} __packed;
-
-#define BT_HCI_EVT_LE_CIS_REQ                   0x1a
-struct bt_hci_evt_le_cis_req {
-	uint16_t acl_handle;
-	uint16_t cis_handle;
-	uint8_t  cig_id;
-	uint8_t  cis_id;
-} __packed;
-
-#define BT_HCI_EVT_LE_BIG_COMPLETE              0x1b
-struct bt_hci_evt_le_big_complete {
-	uint8_t  status;
-	uint8_t  big_handle;
-	uint8_t  sync_delay[3];
-	uint8_t  latency[3];
-	uint8_t  phy;
-	uint8_t  nse;
-	uint8_t  bn;
-	uint8_t  pto;
-	uint8_t  irc;
-	uint16_t max_pdu;
-	uint8_t  num_bis;
-	uint16_t handle[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_BIG_TERMINATE             0x1c
-struct bt_hci_evt_le_big_terminate {
-	uint8_t  big_handle;
-	uint8_t  reason;
-} __packed;
-
-#define BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED      0x1d
-struct bt_hci_evt_le_big_sync_established {
-	uint8_t  status;
-	uint8_t  big_handle;
-	uint8_t  latency[3];
-	uint8_t  nse;
-	uint8_t  bn;
-	uint8_t  pto;
-	uint8_t  irc;
-	uint16_t max_pdu;
-	uint8_t  num_bis;
-	uint16_t handle[0];
-} __packed;
-
-#define BT_HCI_EVT_LE_BIG_SYNC_LOST             0x1e
-struct bt_hci_evt_le_big_sync_lost {
-	uint8_t  big_handle;
-	uint8_t  reason;
-} __packed;
-
-#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE     0x1f
-struct bt_hci_evt_le_req_peer_sca_complete {
-	uint8_t  status;
-	uint16_t handle;
-	uint8_t  sca;
-} __packed;
-
-#define BT_HCI_EVT_LE_BIGINFO_ADV_REPORT        0x22
-struct bt_hci_evt_le_biginfo_adv_report {
-	uint16_t sync_handle;
-	uint8_t  num_bis;
-	uint8_t  nse;
-	uint16_t iso_interval;
-	uint8_t  bn;
-	uint8_t  pto;
-	uint8_t  irc;
-	uint16_t max_pdu;
-	uint8_t  sdu_interval[3];
-	uint16_t max_sdu;
-	uint8_t  phy;
-	uint8_t  framing;
-	uint8_t  encryption;
-} __packed;
-
-/* Event mask bits */
-
-#define BT_EVT_BIT(n) (1ULL << (n))
-
-#define BT_EVT_MASK_INQUIRY_COMPLETE             BT_EVT_BIT(0)
-#define BT_EVT_MASK_CONN_COMPLETE                BT_EVT_BIT(2)
-#define BT_EVT_MASK_CONN_REQUEST                 BT_EVT_BIT(3)
-#define BT_EVT_MASK_DISCONN_COMPLETE             BT_EVT_BIT(4)
-#define BT_EVT_MASK_AUTH_COMPLETE                BT_EVT_BIT(5)
-#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE     BT_EVT_BIT(6)
-#define BT_EVT_MASK_ENCRYPT_CHANGE               BT_EVT_BIT(7)
-#define BT_EVT_MASK_REMOTE_FEATURES              BT_EVT_BIT(10)
-#define BT_EVT_MASK_REMOTE_VERSION_INFO          BT_EVT_BIT(11)
-#define BT_EVT_MASK_HARDWARE_ERROR               BT_EVT_BIT(15)
-#define BT_EVT_MASK_ROLE_CHANGE                  BT_EVT_BIT(17)
-#define BT_EVT_MASK_PIN_CODE_REQ                 BT_EVT_BIT(21)
-#define BT_EVT_MASK_LINK_KEY_REQ                 BT_EVT_BIT(22)
-#define BT_EVT_MASK_LINK_KEY_NOTIFY              BT_EVT_BIT(23)
-#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW         BT_EVT_BIT(25)
-#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI     BT_EVT_BIT(33)
-#define BT_EVT_MASK_REMOTE_EXT_FEATURES          BT_EVT_BIT(34)
-#define BT_EVT_MASK_SYNC_CONN_COMPLETE           BT_EVT_BIT(43)
-#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT      BT_EVT_BIT(46)
-#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47)
-#define BT_EVT_MASK_IO_CAPA_REQ                  BT_EVT_BIT(48)
-#define BT_EVT_MASK_IO_CAPA_RESP                 BT_EVT_BIT(49)
-#define BT_EVT_MASK_USER_CONFIRM_REQ             BT_EVT_BIT(50)
-#define BT_EVT_MASK_USER_PASSKEY_REQ             BT_EVT_BIT(51)
-#define BT_EVT_MASK_SSP_COMPLETE                 BT_EVT_BIT(53)
-#define BT_EVT_MASK_USER_PASSKEY_NOTIFY          BT_EVT_BIT(58)
-#define BT_EVT_MASK_LE_META_EVENT                BT_EVT_BIT(61)
-
-/* Page 2 */
-#define BT_EVT_MASK_PHY_LINK_COMPLETE            BT_EVT_BIT(0)
-#define BT_EVT_MASK_CH_SELECTED_COMPLETE         BT_EVT_BIT(1)
-#define BT_EVT_MASK_DISCONN_PHY_LINK_COMPLETE    BT_EVT_BIT(2)
-#define BT_EVT_MASK_PHY_LINK_LOSS_EARLY_WARN     BT_EVT_BIT(3)
-#define BT_EVT_MASK_PHY_LINK_RECOVERY            BT_EVT_BIT(4)
-#define BT_EVT_MASK_LOG_LINK_COMPLETE            BT_EVT_BIT(5)
-#define BT_EVT_MASK_DISCONN_LOG_LINK_COMPLETE    BT_EVT_BIT(6)
-#define BT_EVT_MASK_FLOW_SPEC_MODIFY_COMPLETE    BT_EVT_BIT(7)
-#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS     BT_EVT_BIT(8)
-#define BT_EVT_MASK_AMP_START_TEST               BT_EVT_BIT(9)
-#define BT_EVT_MASK_AMP_TEST_END                 BT_EVT_BIT(10)
-#define BT_EVT_MASK_AMP_RX_REPORT                BT_EVT_BIT(11)
-#define BT_EVT_MASK_AMP_SR_MODE_CHANGE_COMPLETE  BT_EVT_BIT(12)
-#define BT_EVT_MASK_AMP_STATUS_CHANGE            BT_EVT_BIT(13)
-#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE          BT_EVT_BIT(14)
-#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE         BT_EVT_BIT(15)
-#define BT_EVT_MASK_SYNCH_TRAIN_RX               BT_EVT_BIT(16)
-#define BT_EVT_MASK_CL_SLAVE_BC_RX               BT_EVT_BIT(17)
-#define BT_EVT_MASK_CL_SLAVE_BC_TIMEOUT          BT_EVT_BIT(18)
-#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE          BT_EVT_BIT(19)
-#define BT_EVT_MASK_SLAVE_PAGE_RSP_TIMEOUT       BT_EVT_BIT(20)
-#define BT_EVT_MASK_CL_SLAVE_BC_CH_MAP_CHANGE    BT_EVT_BIT(21)
-#define BT_EVT_MASK_INQUIRY_RSP_NOT              BT_EVT_BIT(22)
-#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP     BT_EVT_BIT(23)
-#define BT_EVT_MASK_SAM_STATUS_CHANGE            BT_EVT_BIT(24)
-
-#define BT_EVT_MASK_LE_CONN_COMPLETE             BT_EVT_BIT(0)
-#define BT_EVT_MASK_LE_ADVERTISING_REPORT        BT_EVT_BIT(1)
-#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE      BT_EVT_BIT(2)
-#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE      BT_EVT_BIT(3)
-#define BT_EVT_MASK_LE_LTK_REQUEST               BT_EVT_BIT(4)
-#define BT_EVT_MASK_LE_CONN_PARAM_REQ            BT_EVT_BIT(5)
-#define BT_EVT_MASK_LE_DATA_LEN_CHANGE           BT_EVT_BIT(6)
-#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE  BT_EVT_BIT(7)
-#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE   BT_EVT_BIT(8)
-#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE         BT_EVT_BIT(9)
-#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT         BT_EVT_BIT(10)
-#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE       BT_EVT_BIT(11)
-#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT    BT_EVT_BIT(12)
-#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED  BT_EVT_BIT(13)
-#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT    BT_EVT_BIT(14)
-#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST         BT_EVT_BIT(15)
-#define BT_EVT_MASK_LE_SCAN_TIMEOUT              BT_EVT_BIT(16)
-#define BT_EVT_MASK_LE_ADV_SET_TERMINATED        BT_EVT_BIT(17)
-#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED         BT_EVT_BIT(18)
-#define BT_EVT_MASK_LE_CHAN_SEL_ALGO             BT_EVT_BIT(19)
-#define BT_EVT_MASK_LE_CIS_ESTABLISHED           BT_EVT_BIT(24)
-#define BT_EVT_MASK_LE_CIS_REQ                   BT_EVT_BIT(25)
-#define BT_EVT_MASK_LE_BIG_COMPLETE              BT_EVT_BIT(26)
-#define BT_EVT_MASK_LE_BIG_TERMINATED            BT_EVT_BIT(27)
-#define BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED      BT_EVT_BIT(28)
-#define BT_EVT_MASK_LE_BIG_SYNC_LOST             BT_EVT_BIT(29)
-#define BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE     BT_EVT_BIT(30)
-#define BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD       BT_EVT_BIT(31)
-#define BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING  BT_EVT_BIT(32)
-#define BT_EVT_MASK_LE_BIGINFO_ADV_REPORT        BT_EVT_BIT(33)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _YC11XX_HCI_H_ */
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci_err.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci_err.h	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/hci/yc11xx_hci_err.h	(nonexistent)
@@ -1,92 +0,0 @@
-/** @file
- *  @brief Bluetooth Host Control Interface status codes.
- */
-
-/*
- * Copyright (c) 2019 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#ifndef _YC11XX_HCI_ERR_H_
-#define _YC11XX_HCI_ERR_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */
-#define BT_HCI_ERR_SUCCESS                      0x00
-#define BT_HCI_ERR_UNKNOWN_CMD                  0x01
-#define BT_HCI_ERR_UNKNOWN_CONN_ID              0x02
-#define BT_HCI_ERR_HW_FAILURE                   0x03
-#define BT_HCI_ERR_PAGE_TIMEOUT                 0x04
-#define BT_HCI_ERR_AUTH_FAIL                    0x05
-#define BT_HCI_ERR_PIN_OR_KEY_MISSING           0x06
-#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED        0x07
-#define BT_HCI_ERR_CONN_TIMEOUT                 0x08
-#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED          0x09
-#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED     0x0a
-#define BT_HCI_ERR_CONN_ALREADY_EXISTS          0x0b
-#define BT_HCI_ERR_CMD_DISALLOWED               0x0c
-#define BT_HCI_ERR_INSUFFICIENT_RESOURCES       0x0d
-#define BT_HCI_ERR_INSUFFICIENT_SECURITY        0x0e
-#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE         0x0f
-#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT          0x10
-#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL     0x11
-#define BT_HCI_ERR_INVALID_PARAM                0x12
-#define BT_HCI_ERR_REMOTE_USER_TERM_CONN        0x13
-#define BT_HCI_ERR_REMOTE_LOW_RESOURCES         0x14
-#define BT_HCI_ERR_REMOTE_POWER_OFF             0x15
-#define BT_HCI_ERR_LOCALHOST_TERM_CONN          0x16
-#define BT_HCI_ERR_REPEATED_ATTEMPTS            0x17
-#define BT_HCI_ERR_PAIRING_NOT_ALLOWED          0x18
-#define BT_HCI_ERR_UNKNOWN_LMP_PDU              0x19
-#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE        0x1a
-#define BT_HCI_ERR_SCO_OFFSET_REJECTED          0x1b
-#define BT_HCI_ERR_SCO_INTERVAL_REJECTED        0x1c
-#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED        0x1d
-#define BT_HCI_ERR_INVALID_LL_PARAM             0x1e
-#define BT_HCI_ERR_UNSPECIFIED                  0x1f
-#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL          0x20
-#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED      0x21
-#define BT_HCI_ERR_LL_RESP_TIMEOUT              0x22
-#define BT_HCI_ERR_LL_PROC_COLLISION            0x23
-#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED          0x24
-#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE      0x25
-#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED   0x26
-#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED  0x27
-#define BT_HCI_ERR_INSTANT_PASSED               0x28
-#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED        0x29
-#define BT_HCI_ERR_DIFF_TRANS_COLLISION         0x2a
-#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM       0x2c
-#define BT_HCI_ERR_QOS_REJECTED                 0x2d
-#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED    0x2e
-#define BT_HCI_ERR_INSUFF_SECURITY              0x2f
-#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30
-#define BT_HCI_ERR_ROLE_SWITCH_PENDING          0x32
-#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION      0x34
-#define BT_HCI_ERR_ROLE_SWITCH_FAILED           0x35
-#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE       0x36
-#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37
-#define BT_HCI_ERR_HOST_BUSY_PAIRING            0x38
-#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39
-#define BT_HCI_ERR_CONTROLLER_BUSY              0x3a
-#define BT_HCI_ERR_UNACCEPT_CONN_PARAM          0x3b
-#define BT_HCI_ERR_ADV_TIMEOUT                  0x3c
-#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL         0x3d
-#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB           0x3e
-#define BT_HCI_ERR_MAC_CONN_FAILED              0x3f
-#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED        0x40
-#define BT_HCI_ERR_SUBMAP_NOT_DEFINED           0x41
-#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER       0x42
-#define BT_HCI_ERR_LIMIT_REACHED                0x43
-#define BT_HCI_ERR_OP_CANCELLED_BY_HOST         0x44
-#define BT_HCI_ERR_PACKET_TOO_LONG              0x45
-
-#define BT_HCI_ERR_AUTHENTICATION_FAIL __DEPRECATED_MACRO BT_HCI_ERR_AUTH_FAIL
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _YC11XX_HCI_ERR_H_ */
Index: ModuleDemo/25_OTA/bt_demo/CM0/User/main.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/main.c	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/User/main.c	(nonexistent)
@@ -1,156 +0,0 @@
-#include <stdarg.h>
-#include "yc11xx.h"
-#include "type.h"
-//#include "yc11xx_uart.h"
-#include "yc11xx_gpio.h"
-#include "btreg.h"
-#include "yc_debug.h"
-#include "ipc.h"
-#include "Drv_bt.h"
-#include "nvic.h"
-#include "yc11xx_wdt.h"
-#include "yc_drv_common.h"
-#include "yc11xx_h4.h"
-
-
-#define LPM_ENABLE    HWRITE(mem_lpm_mode,1);
-#define sleep_500ms	HWRITEW(mem_lpm_interval,800);		//*0.625ms	
-#define POWER_OFF	 IPC_TxControlCmd(BT_CMD_ENTER_HIBERNATE);
-tIPCHandleCb gTIPCHandleCb[IPC_TYPE_NUM]=
-{
-	0,
-	IpcDefaultCallBack,//cmd
-	Bt_EvtCallBack,//evt
-	IpcDefaultCallBack,//hid
-	//Bt_SPPCallBack,//spp
-	IpcDefaultCallBack,
-	IpcDefaultCallBack,//ble
-	IpcDefaultCallBack,//24g
-	IpcDefaultCallBack,//mesh
-	IpcDefaultCallBack,//mesh
-	IpcDefaultCallBack,//mesh
-	Bt_DataBufferCallBack,//a2dp
-	IpcDefaultCallBack,//hfp
-	IpcDefaultCallBack,//tws
-};
-WDT_InitTypeDef  gWdtInit =
-{
-	.WDTx =WDT2,
-	.mode =RESET_MODE,
-	.setload =WDT_timer_1_5s,
-
-};
-
-#define GPIO_0_5_ADC_DATA	HREADW(mem_0_5_adc_io_data)
-#define GPIO_1V_ADC_DATA	HREADW(mem_1v_adc_io_data)
-#define HVIN_3V_ADC_DATA	HREADW(mem_3v_adc_hvin_data)
-#define HVIN_5V_ADC_DATA	HREADW(mem_5v_adc_hvin_data)
-
-
-int main(void)
-{
-	*(volatile byte*)(reg_map_m0(0x1f000)) = 0x1c;//Enable cm0 debug
-	SYS_TimerInit(CLOCK_48M_multiple);
-	IPC_init(&gTIPCHandleCb);
-	
-	
-	DEBUG_INIT();
-	DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_EvtCallBack: 0x%04X", LOG_POINT_9010, gBRState.topState);
-
-#ifdef FUNCTION_WATCH_DOG
-	WDT_Start(&gWdtInit);
-#endif
-	h4_init();
-
-	sleep_500ms;
-//	LPM_ENABLE;
-//	POWER_OFF;
-	while (1)
-	{
-#ifdef FUNCTION_WATCH_DOG
-		WDT_Kick();
-#endif
-		//For respin log print
-		
-
-		switch (HREAD(IPC_MCU_STATE))
-		{
-			case IPC_MCU_STATE_RUNNING:
-				//always first init bt
-				IPC_HandleRxPacket();
-				
-				//Bt_watchdog();
-				if (gBRState.topState != BR_POWER_OFF)
-				{
-					DEBUG_POLLING_PRINT();
-					SYS_timerPolling();
-
-					h4_polling_rx();
-				}
-				Lpm_unLockLpm(M0_LPM_FLAG);
-				break;
-			case IPC_MCU_STATE_LMP:
-				if (IPC_IsTxBuffEmpty()
-					&& DEBUG_LOG_BUFFER_IS_EMPTY())
-				{
-					OS_ENTER_CRITICAL();
-					Bt_ActionBeforeLpm();
-					HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
-				}
-				else
-				{
-					HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_RUNNING);
-				}
-				break;
-			case IPC_MCU_STATE_HIBERNATE:
-				OS_ENTER_CRITICAL();
-				Bt_ActionBeforeHibernate();
-				HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
-				break;
-			case IPC_MCU_STATE_STOP:
-				break;
-		}
-		//hw_delay();
-	};
-}
-
-
-
-void SCO_NVIC_Config(void)
-{
-	NVIC_SetPriority(timer6_handler_IRQn, 0);
-	NVIC_EnableIRQ(timer6_handler_IRQn);
-}
-
-void SCO_NVIC_DeConfig(void)
-{
-	NVIC_SetPriority(timer6_handler_IRQn, 0);
-	NVIC_DisableIRQ(timer6_handler_IRQn);
-}
-
-
-
-
-void TIMER6_IRQHandler(void)
-{
-//	Bt_SCODataProcess();
-}
-
-
-/**
-  * @brief  Systick interrupt service function.
-  * @param  None
-  * @retval None
-  */
-void SysTick_Handler(void)
-{
-	SYStick_handle();
-}
-
-void _assert_handler(const char* file, int line,const char* func)
-{
-	while(1);
-}
-
- 
- 
\ No newline at end of file
Index: ModuleDemo/25_OTA/bt_demo/CM0/respin/memmap.format
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/memmap.format	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/memmap.format	(nonexistent)
@@ -1,1704 +0,0 @@
-0x0000 mem_le_adv_transmit
-0x0001 mem_le_adv_waitcnt
-0x0002 mem_sbc_error
-0x0002 mem_le_adv_rcv
-0x0003 mem_le_req_rcv
-0x0004 mem_le_scanrsp_rcv
-0x0005 mem_le_conn_rcv
-0x0006 mem_inquiryscan_waitcnt
-0x0007 mem_inquiryscan_rcvcnt
-0x0008 mem_pagescan_waitcnt
-0x0009 mem_pagescan_rcvcnt
-0x000a mem_pagescan_rcvfhscnt
-0x000b mem_slave_rcvcnt
-0x000c mem_page_transmit
-0x000d mem_page_rcv
-0x000e mem_page_rcv_fhs
-0x000f mem_master_rcvcnt
-0x0010 mem_fhs_wait_counter
-0x0011 mem_newconnto_counter
-0x0012 mem_inquiry_transmit
-0x0013 mem_inquiry_rcv
-0x0014 mem_fw_ver
-0x0015 mem_current_context
-0x0016 mem_empty_block
-0x0017 mem_last_freq
-0x0018 mem_rssi
-0x0019 mem_rx_type
-0x001a mem_rx_hec_err
-0x001c mem_rx_crc_err
-0x001e mem_context_ptr
-0x0020 mem_display
-0x0028 mem_bcd
-0x0030 mem_state
-0x0031 mem_mode
-0x0032 mem_tsniff
-0x0034 mem_sniff_anchor
-0x0038 mem_clk_offset
-0x003e mem_rx_window
-0x0040 mem_plap
-0x0043 mem_puap
-0x0044 mem_pnap
-0x0046 mem_conn_handle
-0x0047 mem_cur_arq
-0x0048 mem_lmp_to_send
-0x0049 mem_lmi_opcode
-0x004a mem_lmo_reason
-0x004b mem_op
-0x004c mem_state_map
-0x004d mem_supervision_timer
-0x0051 mem_supervision_to
-0x0053 mem_name_offset
-0x0054 mem_key_size
-0x0055 mem_reconn_lmp_sm
-0x0056 mem_aco
-0x0062 mem_kc
-0x0072 mem_conn_timer
-0x0073 mem_sniff_attempt
-0x0074 mem_sniff_timeout
-0x0075 mem_dsniff
-0x0077 mem_amaddr
-0x0078 mem_lmo_opcode1
-0x0079 mem_lmi_opcode1
-0x007a mem_lmo_reason1
-0x007b mem_lmo_tid1
-0x007c mem_lmo_opcode2
-0x007d mem_lmi_opcode2
-0x007e mem_lmo_reason2
-0x007f mem_lmo_tid2
-0x0080 mem_mark_load
-0x0088 mem_hci_version
-0x008b mem_acl_pktlen
-0x008d mem_sco_pktlen
-0x008e mem_acl_pktcnt
-0x0090 mem_sco_pktcnt
-0x0092 mem_current_sniff_attempt
-0x0093 mem_current_sniff_timeout
-0x0094 mem_nfreq_index_inq
-0x0095 mem_nfreq_index_page
-0x0096 mem_ninqy_index
-0x0097 mem_fhs_misc
-0x0098 mem_tx_lch
-0x0099 mem_tx_len
-0x009b mem_subsniff_instant
-0x009f mem_subsniff_rate
-0x00a0 mem_subsniff_tcmax
-0x00a2 mem_subsniff_tsniff
-0x00a3 mem_lpm_adjust
-0x00a4 mem_sync_clke
-0x00aa mem_lpm_current_mult
-0x00ab mem_gpio_wakeup_low
-0x00b0 mem_gpio_wakeup_high
-0x00b5 mem_npage_index
-0x00b6 mem_page_mode
-0x00b7 mem_page_clk
-0x00bb mem_tst_pktcnt_sync
-0x00bd mem_tst_pktcnt_hec
-0x00bf mem_tst_pktcnt_crc
-0x00c1 mem_tst_pktcnt_dmh
-0x00c3 mem_tmp_buffer_head
-0x00c6 mem_tmp_buffer
-0x0116 mem_tester_emulate
-0x0117 mem_temp_payload
-0x0117 test_mode_scenario
-0x0118 test_mode_hopping_mode
-0x0119 test_mode_tx_freq
-0x011a test_mode_rx_freq
-0x011b test_mode_power_mode
-0x011c test_mode_poll_period
-0x011d test_mode_packet_type
-0x011e test_mode_data_length
-0x0120 mem_test_mode_old_debug_config
-0x0121 mem_tester_cnt
-0x0122 mem_temp_am_addr
-0x0123 mem_temp_arq
-0x0124 mem_pdatatemp
-0x012c mem_len
-0x012e mem_clkn_bt
-0x0132 mem_clke_bt
-0x0136 mem_dpll_clkn
-0x013a mem_connection_options
-0x013b mem_nameres_cnt
-0x013c mem_txptr
-0x013e mem_slot_offset
-0x0140 mem_wait_auth_clk
-0x0144 extm_fhs_misc
-0x0145 extm_newconn_am_addr
-0x0146 extm_class
-0x0149 extm_lap
-0x014c extm_uap
-0x014d extm_nap
-0x0150 mem_debug_config
-0x0151 mem_lch_code
-0x0152 mem_fhs_am_addr
-0x0153 mem_dpll_error
-0x0155 mem_bdaddr_list_buff
-0x0179 mem_select_list_item
-0x017a mem_temp_reconn_record
-0x017a mem_record_bt_mode
-0x017b mem_temp_lap
-0x0181 mem_list_item_ptr
-0x0183 mem_eir
-0x01e7 mem_switch_timeout
-0x01e9 mem_acl_dsniff
-0x01eb mem_acl_tsniff
-0x01ed mem_acl_attempt
-0x01ee mem_acl_timeout
-0x01ef mem_temp_force_nack
-0x01f0 mem_avdtp_signal_cmd
-0x01f1 mem_transaction_label
-0x01f2 mem_temp_sbc_decode_buffer_size
-0x01f4 mem_temp_dac_soft_dma_work_wptr
-0x01f6 mem_temp_sbc_soft_dma_start_addr
-0x01f8 mem_temp_dac_soft_dma_start_addr
-0x01fa mem_temp_soft_dma_work_length
-0x01fc mem_temp_soft_dma_work_table_index_value
-0x01fd mem_ucode_status
-0x01fe mem_ucode_flag
-0x0200 mem_qspi_tbuf/* spid buf: 03 addr[23:16] addr[15:8] addr[7:0] */
-0x0201 mem_iicd_tbuf/* iicd buf: iic_adr addr[15:8] addr[7:0] iic_adr */
-0x0201 mem_addr_hi
-0x0202 mem_eep_addr_hi
-0x0202 mem_addr_mi
-0x0203 mem_addr_lo
-0x0204 mem_iicd_addr
-0x0205 mem_spid_rbuf
-0x0209 mem_ucode_buf
-0x020b mem_ucode_len
-0x020d mem_sched_addr
-0x020f mem_ucode_ptr
-0x0212 mem_ucode_keybuf
-0x0222 mem_check_plap_temp
-0x0234 mem_start_addr_temp
-0x0237 mem_spid_tbuf
-0x0239 mem_qspi_defualt
-0x023a mem_switch_fail_master_count
-0x023b mem_app_evt_timer_count
-0x023c mem_flash_address
-0x023f mem_flash_data_address
-0x0241 mem_flash_trans_length
-0x0243 mem_soft_dma_src_addr
-0x0247 mem_soft_dma_dst_addr
-0x024b mem_avctp_command_response
-0x024c mem_avrcp_vol
-0x024d mem_avctp_rx_label
-0x024e mem_h5rx_ackcnt
-0x024f mem_check_err_acl_cont
-0x0250 mem_rp_packets
-0x0251 mem_packet_type
-0x0253 mem_hci_sniff_conn_handle
-0x0255 mem_hci_sniff_max_interval
-0x0257 mem_hci_sniff_min_interval
-0x0259 mem_hci_sniff_attempt
-0x025b mem_hci_sniff_timeout
-0x025d mem_voice_setting
-0x025f mem_retransmission_effort
-0x0260 mem_sco_ptype
-0x0262 mem_extm_uap_restore
-0x0265 mem_h5rx_rptr
-0x0267 mem_h5rx_ack
-0x0268 mem_h5tx_ack
-0x0269 mem_h5tx_rptr
-0x026b mem_h5tx_wptr
-0x026d mem_h5tx_free
-0x026f mem_h5rx_tmp
-0x0270 mem_h5tx_seq
-0x0271 mem_hci_acl_queue_wptr
-0x0273 mem_hci_acl_queue_rptr
-0x0275 mem_hci_acl_queue_end
-0x0277 mem_hci_acl_queue_wcnt
-0x0278 mem_hci_acl_cnt
-0x0279 mem_hci_acl_tx_trigger_wptr//tx via uart
-0x027b mem_ucode_id_local
-0x027c mem_ucode_id_remote
-0x027d mem_check_sum
-0x027e mem_ucode_temp
-0x027f mem_ucode_temp1
-0x0280 mem_lock_in_enc
-0x0281 mem_hci_disconn_reason
-0x0282 mem_hci_curr_len
-0x0283 mem_hci_curr_target
-0x0285 mem_coef_table_temp
-0x03d7 mem_sco_indata
-0x0413 mem_sco_outdata
-0x044f mem_phone_num_count
-0x0450 mem_phone_num_len
-0x0451 mem_phone_number
-0x0460 mem_at_command_data
-0x047e mem_sco_flag
-0x047f mem_l2cap_mem_start
-0x047f mem_l2cap_rxbuff1_len
-0x0481 mem_l2cap_rxbuff2_len
-0x0483 mem_l2cap_rxbuff_new_temp
-0x0484 mem_l2cap_rxbuff_new
-0x0485 mem_l2cap_rxbuff_fifo
-0x0485 mem_l2cap_rxbuff_fifo1
-0x0486 mem_l2cap_rxbuff_fifo2
-0x0487 mem_l2cap_payload_ptr
-0x0489 mem_l2cap_rx_pkt_length
-0x048b mem_l2cap_rx_cid
-0x048d mem_l2cap_rx_done
-0x048e mem_l2cap_signal_ident
-0x048f mem_sdp_tx_buff_ptr
-0x0491 mem_sdp_tx_payload_ptr
-0x0493 mem_sdp_tx_pkt_length
-0x0495 mem_tx_malloc_log
-0x04d5 mem_l2cap_temp_ch_info
-0x04d5 mem_l2cap_temp_ch_psm
-0x04d6 mem_l2cap_temp_ch_state
-0x04d7 mem_l2cap_temp_local_cid
-0x04d9 mem_l2cap_temp_remote_cid
-0x04db mem_l2cap_mem_end
-0x04db mem_le_rxbuf
-0x0503 mem_le_l2capbuf
-0x05db mem_le_mic
-0x05df mem_le_peer_mic
-0x05e3 mem_le_skdm
-0x05eb mem_le_skds
-0x05f3 mem_le_peer_ltk
-0x0603 mem_le_my_ltk
-0x0613 mem_le_mrand
-0x0623 mem_le_state
-0x0624 mem_le_mode
-0x0625 mem_le_tsniff
-0x0627 mem_le_anchor
-0x062b mem_le_clk_offset
-0x0631 mem_le_receive_window
-0x0633 mem_le_plap
-0x0639 mem_le_conn_handle
-0x063a mem_le_arq
-0x063b mem_le_ch
-0x063c mem_le_hop
-0x063d mem_le_event_count
-0x063f mem_le_supervision_timer
-0x0643 mem_le_instant
-0x0645 mem_le_channels
-0x0646 mem_le_conn_sm
-0x0647 mem_le_op
-0x0648 mem_le_access
-0x064c mem_le_crcinit
-0x064f mem_le_window_size
-0x0650 mem_le_slave_latency
-0x0652 mem_le_superto
-0x0654 mem_le_channel_map
-0x0659 mem_le_no_using
-0x065b mem_le_peer_sca
-0x065c mem_le_att_opcode
-0x065d mem_le_att_handle
-0x065f mem_le_err_code
-0x0660 mem_le_ll_pairing_fail_reason
-0x0661 mem_le_sk
-0x0671 mem_le_testtype
-0x0672 mem_le_test_sync
-0x0674 mem_le_test_pcnt
-0x0676 mem_le_notify_len
-0x0677 mem_cmd_le_create_conn
-0x0678 mem_le_adv_temp
-0x068c mem_le_packet_size
-0x068d mem_le_packet_llid
-0x068e mem_le_payload_ptr
-0x0690 mem_lmo_header_length
-0x0691 mem_lmo_header_opcode
-0x0692 mem_lmo_payload
-0x06a3 mem_lmi_accepted_opcode
-0x06a4 mem_disconn_reason_send
-0x06a5 mem_tx_fixed_freq
-0x06a6 mem_rx_fixed_freq
-0x06a7 mem_ext_features_page
-0x06a8 mem_lmpext_ssp_enable
-0x06aa mem_remote_sppcap
-0x06ab mem_lmp_conn_state
-0x06ac mem_soft_timer
-0x06ae mem_pincode_state
-0x06af mem_sres_tid
-0x06b0 mem_accptsco_tid
-0x06b1 mem_wait_encryption
-0x06b2 mem_sniff_payload
-0x06c2 mem_aurand_send_delay_time
-0x06c6 mem_prcp_data
-0x06da mem_prcp
-0x06db mem_prcp_tx_len
-0x06dc rx_buf_data_ptr
-0x06de mem_mod2div_temp
-0x06e1 mem_contw_temp
-0x06e3 mem_rfc_adss
-0x06e4 mem_rfc_current_channel
-0x06e5 mem_rfc_frame_type
-0x06e6 mem_current_fcs
-0x06e7 mem_rfc_paylead_length
-0x06e9 mem_rfc_paylead_ptr
-0x06eb mem_uih_cmd_type
-0x06ec mem_uih_length
-0x06ee mem_rfc_payload_ptr
-0x06f0 mem_ms_param
-0x06f1 mem_pn_credit_flow_type_info
-0x06f2 mem_pn_priority
-0x06f3 mem_pn_acknowledg_timer
-0x06f4 mem_pn_max_retrans
-0x06f5 mem_rfcomm_send_adss
-0x06f6 mem_rfcomm_send_frame_type
-0x06f7 mem_rfcomm_send_fcs
-0x06f8 mem_sdp_mem_start
-0x06f8 mem_sdp_uuid_search_ptr
-0x0700 mem_sdp_continue_byte
-0x0702 mem_sdp_pduid
-0x0703 mem_sdp_transactionid
-0x0705 mem_sdp_transactionid_local
-0x0707 mem_sdp_attribute_maxbyte
-0x0709 mem_sdp_record_maxcnt
-0x070b mem_sdp_record_handle
-0x070f mem_sdp_LACAP_found
-0x0710 mem_sdp_RFCOMM_found
-0x0711 mem_sdp_handle_list
-0x0711 mem_sdp_attrib_list
-0x0731 mem_sdp_error_code
-0x0733 mem_sdp_all_length
-0x0735 mem_handle_humber
-0x0736 mem_search_uuid
-0x0738 mem_sdp_mem_end
-0x0738 mem_rxbuf
-0x0749 mem_random_number
-0x0759 mem_round_key
-0x0769 mem_kinit
-0x0779 mem_input_store
-0x0789 mem_x
-0x0799 mem_y
-0x07a8 mem_y15
-0x07a9 mem_key_store
-0x07ba mem_key_store_end
-0x07bb memp_ar_key
-0x07bd memp_ar_input
-0x07bf mem_ar_hround
-0x07c9 mem_ec_infinite
-0x07ca mem_ec_loopc
-0x07cc mem_aes_cmac_data_length
-0x07cd memdat
-0x07cd mem_ax
-0x07e5 mem_ay
-0x07fd mem_az
-0x0815 mem_bx
-0x082d mem_ax_256//32 bytes
-0x082d mem_by
-0x0845 mem_bz
-0x084d mem_ay_256// 32 bytes
-0x085d mem_cx
-0x086d mem_az_256// 32 bytes
-0x0875 mem_cy
-0x088c mem_cy5
-0x088d mem_bx_256// 32 bytes
-0x088d mem_cz
-0x08a5 mem_k
-0x08ad mem_by_256// 31 bytes
-0x08bd mem_align
-0x08cd mem_bz_256//32 bytes
-0x08cd mem_tmp1
-0x08cd memahbak
-0x08e5 mem_tmp5
-0x08ed mem_cx_256//32 bytes
-0x08ed memahsave
-0x08fd mem_tmp2
-0x090d mem_cy_256// 32 bytes
-0x090d memahsave_end
-0x090d mem_addr_padding
-0x090e mem_addr_value/* 12 bytes     */ 
-0x0915 mem_tmp3
-0x0915 mem_t1
-0x091a mem_addr_value_end
-0x091d mem_addr_iocap_end
-0x092c mem_cy5_256// 1 byte
-0x092d mem_cz_256// 32 bytes
-0x092d mem_tmp0
-0x092d mem_t0
-0x0935 mem_tmp0a
-0x0945 mem_t2
-0x094d mem_k_256//32 bytes
-0x095d mem_t3
-0x096d mem_tmp1_256//32 bytes
-0x0975 mem_t7
-0x098d mem_tmp5_256
-0x09ad mem_tmp2_256
-0x09cd mem_tmp3_256
-0x09cd mem_t1_256
-0x09ed mem_tmp0_256
-0x09ed mem_t0_256
-0x0a0d mem_t2_256
-0x0a2d mem_t3_256
-0x0a4d mem_t7_256
-0x0a6d mem_p
-0x0a85 mem_a
-0x0a9d mem_b
-0x0ab5 mem_gx
-0x0acd mem_gy
-0x0ae5 memh0
-0x0b05 mem_p_256
-0x0b25 mem_a_256
-0x0b45 mem_gx_256
-0x0b65 mem_gy_256
-0x0b85 mem_le_slat
-0x0b95 mem_sp_state_start
-0x0b95 mem_sp_state
-0x0b96 mem_master_sp_state
-0x0b97 mem_sp_flag
-0x0b98 mem_master_sp_flag
-0x0b99 mem_sp_calc
-0x0b9a mem_sp_dh_ready
-0x0b9b mem_sp_localsm
-0x0b9c mem_pairing_auth
-0x0b9d mem_sp_flag_start
-0x0b9d mem_sp_local_key_send_count
-0x0b9e mem_sp_remote_key_recv_count
-0x0b9f mem_sp_remote_key_invalid
-0x0ba0 mem_sp_dhkey_invalid
-0x0ba1 mem_gkey
-0x0ba5 mem_le_pubkey_remote_x_256
-0x0bad mem_sp_pubkey_remote
-0x0bad mem_sp_pubkey_remote_x
-0x0bc5 mem_sp_pubkey_remote_x_end
-0x0bc5 mem_sp_pubkey_remote_y
-0x0bc5 mem_le_pubkey_remote_y_256
-0x0be5 mem_le_dhkey_256
-0x0bed mem_sp_dhkey
-0x0c05 mem_sp_dhkey_end
-0x0c05 mem_sp_random_local
-0x0c15 mem_sp_random_local_end
-0x0c15 mem_sp_random_remote
-0x0c25 mem_sp_random_remote_end
-0x0c25 memresult
-0x0c25 mem_sp_calc_result
-0x0c25 memh
-0x0c29 memg
-0x0c2d memf
-0x0c31 meme
-0x0c35 mem_sp_calc_result_high
-0x0c35 memd
-0x0c39 memc
-0x0c3d memb
-0x0c41 mema
-0x0c45 mem_sp_check_result
-0x0c55 mem_sp_confirm_remote
-0x0c65 mem_sp_prarm_stack
-0x0c75 mem_ipc_skip_continue_proc
-0x0c76 mem_row_scanned_record
-0x0c77 mem_col_scanned_record
-0x0c78 mem_get_keypress_flag_record
-0x0c79 mem_usb_status
-0x0c7a mem_usb_fifo_empty
-0x0c7b mem_usb_read_len
-0x0c7d mem_usb_txbuf
-0x0cbe mem_usb_txbuf1
-0x0cc8 mem_usb_txbuf2
-0x0cd2 mem_usb_rxbuf
-0x0d0e mem_usb_rxbuf_end
-0x0d0f mem_usb_state
-0x0d10 mem_bufptr
-0x0d12 mem_remain
-0x0d13 mem_devicedesc
-0x0d27 mem_hidreportdesc_kb
-0x0d6d mem_hidreportdesc_m
-0x0e35 mem_confdesc
-0x0e7b mem_string0
-0x0e80 mem_string1
-0x0e9e mem_string2
-0x0ebc mem_string3
-0x0eda mem_usb_setup
-0x0eda mem_usb_setup_bmRequestType
-0x0edb mem_usb_setup_bRequest
-0x0edc mem_usb_setup_bValue
-0x0edd mem_usb_setup_bValueH
-0x0ede mem_usb_setup_wIndex
-0x0ee0 mem_usb_setup_bLength
-0x0ee1 mem_usb_setup_bLengthH
-0x0ee2 mem_usb0_setup_ptr
-0x0ee4 mem_usb0_set_report_data_ptr
-0x0ee6 mem_usb_setup_bValue_temp
-0x0ee8 mem_usb0_get_set_report
-0x0ee9 mem_usb0_data_ready_report
-0x0eea mem_usb_tx_win_enable
-0x0eeb mem_usb_tx_mac_enable
-0x0eec mem_usb_zero_packet
-0x0eee mem_usb_ones_packet
-0x0ef0 mem_usb_two_packet
-0x0ef2 mem_usb_idle_flag
-0x0ef3 mem_usb_idle_rate
-0x0ef4 mem_usb_get_protocol_flag
-0x0ef5 mem_usb_set_protocol_status
-0x0ef6 mem_usb_set_protocol_value
-0x0ef7 mem_usb0_state
-0x0ef8 mem_usb_remote_wakeup
-0x0ef9 mem_usb_clear_remote_wakeup
-0x0efa mem_usb_ep0_stall_status
-0x0efb mem_usb_ep1_stall_status
-0x0efc mem_usb_ep2_stall_status
-0x0efd mem_usb_ep3_stall_status
-0x0efe mem_dsc_info_data_pointer
-0x0f00 mem_dsc_info_len
-0x0f01 mem_usb_ep1_data
-0x0f02 mem_usb_ep2_data
-0x0f03 mem_usb_tx_enable
-0x0f04 mem_usb_device_enumeration_endflag
-0x0f05 mem_usb_wakestate_onetime_flag
-0x0f06 mem_usb_mac_wakeup_trig
-0x0f07 mem_usb_set_high_addr_flag
-0x0f08 mem_usb_clear_halt
-0x0f09 mem_hold_contr
-0x0f0b mem_hold_contw
-0x0f0d mem_fifo_temp
-0x0f0e mem_max_bitsneed
-0x0f12 mem_bits_need00
-0x0f12 mem_temp
-0x0f16 mem_bits_need01
-0x0f16 mem_temp1
-0x0f1a mem_bits_need02
-0x0f1a mem_timeup
-0x0f1e mem_bits_need03
-0x0f1e mem_rega
-0x0f22 mem_bits_need04
-0x0f22 mem_regb
-0x0f26 mem_bits_need05
-0x0f26 mem_regc
-0x0f2a mem_bits_need06
-0x0f2a mem_contr
-0x0f2c mem_contw
-0x0f2e mem_bits_need07
-0x0f32 mem_bits_need10
-0x0f36 mem_bits_need11
-0x0f3a mem_bits_need12
-0x0f3e mem_bits_need13
-0x0f42 mem_bits_need14
-0x0f46 mem_bits_need15
-0x0f4a mem_bits_need16
-0x0f4e mem_bits_need17
-0x0f52 mem_wakup_from_power_flag
-0x0f53 mem_saved_gpio_in
-0x0f57 mem_flash_data_address_t
-0x0f57 mem_le_data_len_temp//1byte
-0x0f57 mem_tx_fifo_map_temp
-0x0f57 mem_rpn_dlci//1byte
-0x0f57 mem_event_cmd_response_content//2byte
-0x0f57 mem_le_prand//16byte
-0x0f57 mem_AES_CMAC_k//16 bytes
-0x0f57 mem_regext_index//1 bytes
-0x0f57 mem_temp_block0
-0x0f58 mem_le_data_temp//15bytes
-0x0f58 mem_temp_block1
-0x0f67 mem_le_aes_128//16byte
-0x0f67 mem_regext//64 bytes
-0x0f67 mem_AES_CMAC_k1//16 bytes
-0x0f67 mem_sum_temp
-0x0f67 mem_temp_block2
-0x0f77 mem_AES_CMAC_k2//16 bytes
-0x0f77 mem_temp_block3
-0x0f87 mem_AES_CMAC_temp// 16 bytes
-0x0f87 mem_temp_block4
-0x0f97 mem_AES_CMAC_M_last// 16 bytes
-0x0f97 mem_temp_block5
-0x0fa7 mem_le_mackey//16 bytes
-0x0fa7 mem_temp_block6
-0x0fb7 mem_zcode_temp_param0
-0x0fb8 mem_zcode_temp_param1
-0x0fba mem_zcode_temp_param2
-0x0fbc mem_tws_sync_clk
-0x0fc0 mem_tws_connecting_phase
-0x0fc1 mem_temp_tx_power
-0x0fc2 mem_msbc_miss
-0x0fc4 mem_msbc_error
-0x0fc6 mem_vp_length
-0x0fc9 mem_ota_cmd
-0x0fca mem_ota_return_result
-0x0fcb mem_ota_update_flash_mode
-0x0fcc mem_ota_write_index
-0x0fce mem_ota_write_length
-0x0fd0 mem_ota_write_data_addr
-0x0fd3 mem_ota_write_flash_addr
-0x0fd6 mem_ota_enable_xip_flag
-0x0fd7 mem_xip_flash_offset_mram
-0x0fda mem_storage_start_addr_mram
-0x0fdd mem_ota_notify_handle_mram
-0x0fde mem_ota_write_handle_mram
-0x0fdf mem_ota_buck_size_mram
-0x0fe1 mem_ota_packet_max_len_mram
-0x0fe3 mem_ota_wdt_en_flag
-0x0fe4 mem_ota_wdt_m0_en
-0x4000 mem_patch00
-0x4001 mem_patch01
-0x4002 mem_patch02
-0x4003 mem_patch03
-0x4004 mem_patch04
-0x4005 mem_patch05
-0x4006 mem_patch06
-0x4007 mem_patch07
-0x4008 mem_patch08
-0x4009 mem_patch09
-0x400a mem_patch0a
-0x400b mem_patch0b
-0x400c mem_patch0c
-0x400d mem_patch0d
-0x400e mem_patch0e
-0x400f mem_patch0f
-0x4010 mem_patch10
-0x4011 mem_patch11
-0x4012 mem_patch12
-0x4013 mem_patch13
-0x4014 mem_patch14
-0x4015 mem_patch15
-0x4016 mem_patch16
-0x4017 mem_patch17
-0x4018 mem_patch18
-0x4019 mem_patch19
-0x401a mem_patch1a
-0x401b mem_patch1b
-0x401c mem_patch1c
-0x401d mem_patch1d
-0x401e mem_patch1e
-0x401f mem_patch1f
-0x4020 mem_patch20
-0x4021 mem_patch21
-0x4022 mem_patch22
-0x4023 mem_patch23
-0x4024 mem_patch24
-0x4025 mem_patch25
-0x4026 mem_patch26
-0x4027 mem_patch27
-0x4028 mem_patch28
-0x4029 mem_patch29
-0x402a mem_patch2a
-0x402b mem_patch2b
-0x402c mem_patch2c
-0x402d mem_patch2d
-0x402e mem_patch2e
-0x402f mem_patch2f
-0x4030 mem_patch30
-0x4031 mem_patch31
-0x4032 mem_patch32
-0x4033 mem_patch33
-0x4034 mem_patch34
-0x4035 mem_patch35
-0x4036 mem_patch36
-0x4037 mem_patch37
-0x4038 mem_patch38
-0x4039 mem_patch39
-0x403a mem_patch3a
-0x403b mem_patch3b
-0x403c mem_patch3c
-0x403d mem_patch3d
-0x403e mem_patch3e
-0x403f mem_patch3f
-0x4040 mem_context
-0x4130 mem_current_amaddr
-0x4131 mem_lpm_mode
-0x4132 mem_device_option
-0x4133 mem_scan_mode
-0x4134 mem_last_clkn
-0x4138 mem_features
-0x4140 mem_lap
-0x4143 mem_uap
-0x4144 mem_nap
-0x4146 mem_npage
-0x4147 mem_glap
-0x414a mem_class
-0x414d mem_iscan_window
-0x414f mem_iscan_interval
-0x4151 mem_pscan_window
-0x4153 mem_pscan_interval
-0x4155 mem_page_interval
-0x4157 mem_page_window
-0x4159 mem_page_to
-0x415b mem_inq_window
-0x415d mem_fcomp_mul
-0x415e mem_fcomp_div
-0x415f mem_rx_window_init
-0x4161 mem_rx_window_sniff
-0x4163 mem_rf_init_ptr
-0x4165 mem_rf_init
-0x4166 mem_last_type
-0x4167 mem_retransmission_cnt
-0x4169 mem_next_btclk
-0x416d mem_seqi
-0x416e mem_rf_rccal
-0x416f mem_handle_num
-0x4170 mem_max_slot
-0x4171 mem_eir_enable
-0x4172 mem_afh_instant
-0x4176 mem_afh_error_total
-0x4178 mem_afh_cfg
-0x4179 mem_afh_new_mod
-0x417a mem_afh_map_lo
-0x417f mem_afh_map_hi
-0x4184 mem_afh_used
-0x4185 mem_afh_index
-0x4187 mem_afh_map_new
-0x4192 mem_afh_map
-0x41e2 mem_afh_timer
-0x41e6 mem_afh_classify_channel_map
-0x41f0 mem_chip_functions
-0x41f2 mem_lpm_wake_lock
-0x41f4 mem_lpm_interval
-0x41f6 mem_lpm_overhead
-0x41f7 mem_lpm_hibernate_switch
-0x41f8 mem_sniff_unint_lost
-0x41f9 mem_ptt
-0x41fa mem_sleep_counter//should be 0x41fc in REVC
-0x41fe mem_sleep_counter_all
-0x4202 mem_sleep_clkn
-0x4208 mem_sniff_rcv
-0x420b mem_sniff_lost
-0x420e mem_clks_per_lpo
-0x4211 mem_lpm_loadcode_switch
-0x4212 mem_lpm_memory_choose
-0x4213 mem_lpm_mult
-0x4214 mem_lpm_mult_timeout
-0x4215 mem_lpm_mult_cnt
-0x4216 mem_lpm_config
-0x4219 mem_lpm_xtalcnt
-0x421a mem_lpm_buckcnt
-0x421b mem_lpm_ldocnt
-0x421c mem_lpm_isogate
-0x421d mem_lpm_isogate_final
-0x421e mem_saved_gpio// should be 0x421e in REVC
-0x4246 mem_saved_mark
-0x424e mem_saved_spidctrl
-0x424f mem_patch_ptr
-0x4251 mem_patch_len
-0x4253 mem_timers
-0x4293 mem_link_key_exists
-0x4294 mem_link_key_eeprom_head
-0x4297 mem_link_key
-0x42a7 mem_hci_cmd
-0x42a8 mem_hci_conn_handle
-0x42a9 mem_hci_plap
-0x42ac mem_hci_puap
-0x42ad mem_hci_pnap
-0x42af mem_uartd_rxitems_got_data
-0x42b0 mem_uartd_rxitems_threshold
-0x42b1 mem_uartd_rx_timeout
-0x42b3 mem_sco_attempt_cout
-0x42b4 mem_tx_power
-0x42b5 mem_sfreq_enable
-0x42b6 mem_param_rf_setup
-0x42b8 mem_param_pll_setup
-0x42ba mem_avdtp_xmem_start
-0x42ba mem_avdtpsignal_l2capch_ptr
-0x42bc mem_avdtpmedia_l2capch_ptr
-0x42be mem_audio_allow
-0x42bf mem_audio_state
-0x42c0 mem_audio_src_endpoint
-0x42c1 mem_audio_src_endpoint_state
-0x42c2 mem_a2dp_reconnct_delay_timer
-0x42c3 mem_avdtp_xmem_end
-0x42c3 mem_get_media_type
-0x42c4 mem_get_codec_type
-0x42c5 mem_get_samplefreq_channelmode
-0x42c6 mem_get_blocklen_subb_allocation
-0x42c7 mem_get_min_bitpool
-0x42c8 mem_get_max_bitpool
-0x42c9 mem_get_r_media_type
-0x42ca mem_get_r_codec_type
-0x42cb mem_get_r_samplefreq_channelmode
-0x42cc mem_get_r_blocklen_subb_allocation
-0x42cd mem_get_r_min_bitpool
-0x42ce mem_get_r_max_bitpool
-0x42cf mem_conf_media_type
-0x42d0 mem_conf_codec_type
-0x42d1 mem_conf_samplefreq_channelmode
-0x42d2 mem_conf_blocklen_subb_allocation
-0x42d3 mem_conf_min_bitpool
-0x42d4 mem_conf_max_bitpool
-0x42d5 mem_avc_local_transaction_label
-0x42d6 mem_avdtp_signal
-0x42d8 mem_avdtp_media
-0x42da mem_a2dp_state
-0x42db mem_a2dp_seq_num
-0x42dd mem_audio_output_setting
-0x42de mem_param_sco_use_cm0
-0x42df mem_media_in_fast_mode
-0x42e0 mem_a2dp_buffer_judge_add
-0x42e1 mem_param_a2dp_buffer_judge_add_limit
-0x42e2 mem_a2dp_buffer_judge_drop
-0x42e3 mem_param_a2dp_buffer_judge_drop_limit
-0x42e4 mem_drop_or_add_process_state
-0x42e5 mem_drop_or_add_min_receive_packet_size
-0x42e7 mem_first_buffer_cache
-0x42e8 mem_farrow_filter_delta_uk_sign_bit
-0x42e9 mem_farrow_filter_delta_uk
-0x42ed mem_a2dp_adjust_delta_uk_sign_bit
-0x42ee mem_a2dp_adjust_delta_uk
-0x42f2 mem_a2dp_adjust_total_work_sample
-0x42f6 mem_a2dp_adjust_delta_bytes_sign_bit
-0x42f7 mem_a2dp_adjust_delta_bytes
-0x42f9 mem_slave_force_mute_a2dp_voice
-0x42fa mem_slave_force_mute_a2dp_voice_cnt
-0x42fb mem_tws_wait_sync_ok
-0x42fc mem_last_a2dp_seq_num
-0x42fe mem_param_a2dp_dac_sbc_same_buffer_flag
-0x42ff mem_param_a2dp_dac_buffer_addr_mram_flag
-0x4300 mem_param_a2dp_dac_buffer_start_addr
-0x4302 mem_param_a2dp_dac_buffer_size
-0x4304 mem_param_a2dp_sbc_buffer_addr_mram_flag
-0x4305 mem_param_a2dp_sbc_buffer_start_addr
-0x4307 mem_param_a2dp_sbc_buffer_size
-0x4309 mem_app_state
-0x430a mem_app_handshake_flag
-0x430b mem_sniff_param_interval
-0x430d mem_sniff_param_attempt
-0x430f mem_sniff_param_timeout
-0x4311 mem_cb_check_wakelock
-0x4313 mem_cb_before_hibernate
-0x4315 mem_cb_before_lpm
-0x4317 mem_cb_le_process
-0x4319 mem_cb_bt_process
-0x431b mem_cb_idle_process
-0x431d mem_cb_bb_event_process
-0x431f mem_cb_event_timer
-0x4321 mem_cb_keyscan
-0x4323 mem_device_nums
-0x4324 mem_uart_txpin
-0x4325 mem_uart_rxpin
-0x4326 mem_uart_rtspin
-0x4327 mem_uart_ctspin
-0x4328 mem_uartb_txpin
-0x4329 mem_uartb_rxpin
-0x432a mem_uartb_rtspin
-0x432b mem_uartb_ctspin
-0x432c mem_spid_sclkpin
-0x432d mem_spid_sdiopin
-0x432e mem_iic_sda_pin
-0x432f mem_iic_scl_pin
-0x4330 mem_ef_base
-0x4333 mem_eeprom_block_size
-0x4335 mem_mram_qspi_tx_addr
-0x4337 mem_poweron_state
-0x4338 mem_app_connection_options
-0x4339 mem_app_disconn_reason
-0x433b mem_app_disconn_reason_flag
-0x433d mem_storage_start_addr
-0x4340 mem_local_bdaddr
-0x4346 mem_qspi_gpio_ncs
-0x4347 mem_qspi_gpio_sck
-0x4348 mem_qspi_gpio_io0
-0x4349 mem_qspi_gpio_io1
-0x434a mem_qspi_gpio_io2
-0x434b mem_qspi_gpio_io3
-0x434c mem_nv_data_ptr
-0x434e mem_nv_data_number
-0x434f mem_saradc_check_clk
-0x4350 mem_saradc_flag
-0x4351 mem_bat_read_timer
-0x4352 mem_rf_debug_enable
-0x4353 mem_rf_debug_rf_rx_debug_gpio
-0x4354 mem_rf_debug_rf_tx_debug_gpio
-0x4355 mem_rf_debug_rf_sync_detect_debug_gpio
-0x4356 mem_rf_debug_rf_crc_error_debug_gpio
-0x4357 mem_param_soft_dma_enable
-0x4358 mem_param_soft_dma_table_start_addr
-0x435b mem_param_m0_respin_sco_buffer_start_addr
-0x435e mem_param_app_debug_info_timeout
-0x435f mem_app_debug_info_timer
-0x4360 mem_public_code_svn_version_code
-0x4362 mem_public_code_time_info
-0x4366 mem_public_code_size
-0x4369 mem_fixed_param_area_start
-0x4369 mem_fixed_param_area_reserve
-0x436e mem_param_use_cm0_control_flag
-0x436f mem_avctp_xmem_start
-0x436f mem_avctp_tx_label
-0x4370 mem_avr_state
-0x4371 mem_avr_l2capch_ptr
-0x4373 mem_hp_avctp_timer
-0x4374 mem_avctp_play_state
-0x4375 mem_vlm_notify_enable
-0x4376 mem_vlm_notify_label
-0x4377 mem_avctp_xmem_end
-0x4377 mem_cvsd_in_addr_end
-0x4379 mem_cvsd_in_addr_ptr
-0x437b mem_cvsd_out_addr_start
-0x437d mem_cvsd_out_addr_end
-0x437f mem_cvsd_out_addr_ptr
-0x4381 mem_pcm_in_addr_end
-0x4383 mem_param_pcm_in_buffer_addr_mram_flag
-0x4384 mem_param_pcm_in_buffer_addr
-0x4386 mem_param_cvsd_out_buffer_addr_mram_flag
-0x4387 mem_param_cvsd_out_buffer_addr
-0x4389 mem_param_cvsd_in_buffer_addr_mram_flag
-0x438a mem_param_cvsd_in_buffer_addr
-0x438c mem_param_pcm_8k_out_buffer_addr_mram_flag
-0x438d mem_param_pcm_8k_out_buffer_addr
-0x438f mem_param_pcm_48k_out_buffer_addr_mram_flag
-0x4390 mem_param_pcm_48k_out_buffer_addr
-0x4392 mem_cvsd_start_send
-0x4393 mem_baud
-0x4395 mem_hci_lt_rx_state
-0x4396 mem_hid_xmem_start
-0x4396 mem_hid_l2capch_ptr
-0x4398 mem_hidint_l2capch_ptr
-0x439a mem_hid_xmem_end
-0x439a mem_xmem_sco_start
-0x439a mem_sco_asso_handle
-0x439b mem_sco_handle
-0x439d mem_sco_dsniff
-0x439f mem_sco_tsniff
-0x43a1 mem_sco_wsniff
-0x43a2 mem_sco_tx_packet_type
-0x43a3 mem_sco_rx_packet_type
-0x43a4 mem_sco_rx_packet_len
-0x43a6 mem_sco_tx_packet_len
-0x43a8 mem_air_mode
-0x43a9 mem_neogotiation_state
-0x43aa mem_acl_amaddr
-0x43ab mem_esco_amaddr
-0x43ac mem_esco_arq
-0x43ad mem_acl_arq
-0x43ae mem_last_type_esco
-0x43af mem_last_type_acl
-0x43b0 mem_sco_poll
-0x43b1 mem_esco_attempt
-0x43b2 mem_esco_abnormal_attempt
-0x43b3 mem_xmem_sco_end
-0x43b3 mem_xmem_hf_state_start
-0x43b3 mem_hf_state
-0x43b4 mem_hf_call_state
-0x43b5 mem_hf_command
-0x43b6 mem_agoption
-0x43b8 mem_AG_indicator_map
-0x43bf mem_AG_indicator
-0x43c6 mem_telephone_dialing_state
-0x43c7 mem_telephone_dialing_timer
-0x43c8 mem_xmem_hf_state_end
-0x43c8 mem_hf_vlm_speaker
-0x43c9 mem_music_vlm_speaker
-0x43ca mem_hf_vlm_mic
-0x43cb mem_at_payload_ptr
-0x43cd mem_at_command_ptr
-0x43cf mem_at_rfcomm_data_ptr
-0x43d1 mem_UI_HF_brsf_feature
-0x43d4 mem_codec_type
-0x43d5 mem_codec_msbc_support
-0x43d6 mem_cb_hfp_result_code
-0x43d8 mem_hfp_battery_state
-0x43d9 mem_esco_test
-0x43da mem_sco_transaction_enable
-0x43db mem_local_sco_in_process_flag
-0x43dc mem_ipc_mcu_phase
-0x43dd mem_ipc_mcu_state
-0x43de mem_ipc_enable
-0x43df mem_ipc_le_data_len
-0x43e0 mem_ipc_le_data_att_handle
-0x43e2 mem_ipc_tx_data_len
-0x43e3 mem_ipc_tx_data_ptr
-0x43e5 mem_ipc_loss_packet
-0x43e7 mem_temp_for_addr
-0x43ea mem_ipc_test_buff
-0x43f4 mem_param_ipc_mem_block_start_addr
-0x43f4 mem_param_ipc_to_bt_buf_start_addr
-0x43f7 mem_param_ipc_to_bt_buf_end_addr
-0x43fa mem_param_ipc_to_bt_wptr_addr
-0x43fd mem_param_ipc_to_bt_rptr_addr
-0x4400 mem_param_ipc_to_m0_wptr_addr
-0x4403 mem_param_ipc_to_m0_rptr_addr
-0x4406 mem_param_ipc_to_m0_buf_start_addr
-0x4409 mem_param_ipc_mem_block_end_addr
-0x4409 mem_param_ipc_to_m0_buf_end_addr
-0x440c mem_param_debug_log_func_enable
-0x440d mem_debug_log_temp_point
-0x4411 mem_param_debug_log_mem_block_start_addr
-0x4411 mem_param_debug_log_initial_flag_addr
-0x4414 mem_param_debug_log_lock_flag_cm0_addr
-0x4417 mem_param_debug_log_lock_flag_respin_addr
-0x441a mem_param_debug_log_lock_victim_addr
-0x441d mem_param_debug_log_read_index_addr
-0x4420 mem_param_debug_log_write_index_addr
-0x4423 mem_param_debug_log_buffer_start_addr
-0x4426 mem_param_debug_log_mem_block_end_addr
-0x4426 mem_param_debug_log_buffer_end_addr
-0x4429 mem_wake_flag
-0x442a mem_m0_lpm_flag
-0x442c mem_l2cap_xmem_start
-0x442c mem_l2cap_tx_multi_offset//0 means single packet
-0x442e mem_l2cap_pending_info
-0x442e mem_l2cap_pending_id0
-0x442f mem_l2cap_pending_delay_time0
-0x4433 mem_l2cap_pending_ptr0
-0x4435 mem_l2cap_pending_id1
-0x4436 mem_l2cap_pending_delay_time1
-0x443a mem_l2cap_pending_ptr1
-0x443c mem_l2cap_pending_id2
-0x443d mem_l2cap_pending_delay_time2
-0x4441 mem_l2cap_pending_ptr2
-0x4443 mem_l2cap_pending_count
-0x4444 mem_l2cap_active_ch_count
-0x4445 mem_l2cap_ch_info
-0x4445 mem_l2cap_ch_psm0
-0x4446 mem_l2cap_ch_state0
-0x4447 mem_l2cap_local_cid0
-0x4449 mem_l2cap_remote_cid0
-0x444b mem_l2cap_ch_psm1
-0x444c mem_l2cap_ch_state1
-0x444d mem_l2cap_local_cid1
-0x444f mem_l2cap_remote_cid1
-0x4451 mem_l2cap_ch_psm2
-0x4452 mem_l2cap_ch_state2
-0x4453 mem_l2cap_local_cid2
-0x4455 mem_l2cap_remote_cid2
-0x4457 mem_l2cap_ch_psm3
-0x4458 mem_l2cap_ch_state3
-0x4459 mem_l2cap_local_cid3
-0x445b mem_l2cap_remote_cid3
-0x445d mem_l2cap_ch_psm4
-0x445e mem_l2cap_ch_state4
-0x445f mem_l2cap_local_cid4
-0x4461 mem_l2cap_remote_cid4
-0x4463 mem_l2cap_ch_psm5
-0x4464 mem_l2cap_ch_state5
-0x4465 mem_l2cap_local_cid5
-0x4467 mem_l2cap_remote_cid5
-0x4469 mem_l2cap_ch_psm6
-0x446a mem_l2cap_ch_state6
-0x446b mem_l2cap_local_cid6
-0x446d mem_l2cap_remote_cid6
-0x446f mem_l2cap_ch_psm7
-0x4470 mem_l2cap_ch_state7
-0x4471 mem_l2cap_local_cid7
-0x4473 mem_l2cap_remote_cid7
-0x4475 mem_l2cap_prepare_confreq_count
-0x4476 mem_l2cap_channel_disconnect_timer
-0x4477 mem_sdp_state
-0x4478 mem_ML2CAP_comm_id
-0x4479 mem_used_map
-0x447a mem_tx_fifo0
-0x447a mem_tx_fifo0_map
-0x447b mem_tx_fifo0_ptr
-0x447d mem_tx_fifo1
-0x447d mem_tx_fifo1_map
-0x447e mem_tx_fifo1_ptr
-0x4480 mem_tx_fifo2
-0x4480 mem_tx_fifo2_map
-0x4481 mem_tx_fifo2_ptr
-0x4483 mem_tx_fifo3
-0x4483 mem_tx_fifo3_map
-0x4484 mem_tx_fifo3_ptr
-0x4486 mem_tx_fifo_end
-0x4486 mem_alloc_block
-0x4486 mem_alloc_header
-0x4488 mem_alloc_rptr
-0x448a mem_alloc_wptr
-0x448c mem_alloc_end
-0x448e mem_alloc_cur_len
-0x448f mem_alloc_block_start
-0x449e mem_media_release
-0x449f mem_media_block
-0x449f mem_media_header
-0x44a1 mem_media_rptr
-0x44a3 mem_media_wptr
-0x44a5 mem_media_end
-0x44a7 mem_media_cur_len
-0x44a8 mem_media_block_start
-0x44b7 mem_lcp_block
-0x44b7 mem_lcp_header
-0x44b9 mem_lcp_rptr
-0x44bb mem_lcp_wptr
-0x44bd mem_lcp_end
-0x44bf mem_lcp_cur_len
-0x44c0 mem_lcp_block_start
-0x44cf mem_l2cap_flow_ctrl_flag
-0x44d0 mem_l2cap_pending_item
-0x44d1 mem_l2cap_rxbuff_len_error
-0x44d2 mem_l2cap_xmem_end
-0x44d2 mem_l2cap_rx_max_lenth
-0x44d4 mem_l2cap_rx_malloc_num
-0x44d5 mem_le_dsniff
-0x44d7 mem_le_conn_interval
-0x44d9 mem_le_scan_enable
-0x44da mem_le_scan_interval
-0x44dc mem_le_scan_window
-0x44de mem_le_adv_enable
-0x44df mem_le_adv_data_len
-0x44e0 mem_le_adv_data
-0x44ff mem_le_scan_data_len
-0x4500 mem_le_scan_data
-0x451f mem_le_interal_min
-0x4521 mem_le_interal_max
-0x4523 mem_le_latency
-0x4525 mem_le_timeout
-0x4527 mem_le_ch_mapped
-0x4528 mem_le_new_map
-0x452d mem_le_new_param
-0x452d mem_le_new_transmitwindowsize
-0x452e mem_le_new_transmitwindowoffset
-0x4530 mem_le_new_conninterval
-0x4532 mem_le_new_connslavelatency
-0x4534 mem_le_new_connsupervisiontimeout
-0x4536 mem_le_txheader
-0x4537 mem_le_txlen
-0x4538 mem_le_txpayload
-0x453a mem_le_txcid
-0x453c mem_le_l2cap
-0x453d mem_le_l2cap_response
-0x453e mem_le_txbdy
-0x455d mem_le_pcnt_tx
-0x4562 mem_le_pcnt_rx
-0x4567 mem_le_last_mic
-0x456b mem_le_ivm
-0x456f mem_le_ivs
-0x4573 mem_le_ltk
-0x4583 mem_ltk_exists
-0x4584 mem_le_rconfirm
-0x4594 mem_le_srand
-0x45a4 mem_le_iat
-0x45a5 mem_le_rat
-0x45a6 mem_le_preq
-0x45a7 mem_le_preq_iocap
-0x45a8 mem_le_preq_oob
-0x45a9 mem_le_preq_auth
-0x45aa mem_le_preq_max_keysize
-0x45ab mem_le_preq_init_key_distribution
-0x45ac mem_le_preq_resp_key_distribution
-0x45ad mem_le_pres
-0x45ae mem_le_pres_iocap
-0x45af mem_le_pres_oob
-0x45b0 mem_le_pres_auth
-0x45b1 mem_le_pres_max_keysize
-0x45b2 mem_le_pres_init_key_distribution
-0x45b3 mem_le_pres_resp_key_distribution
-0x45b4 mem_le_pairing_state
-0x45b5 mem_le_enc_state
-0x45b6 mem_le_pairing_mode
-0x45b7 mem_le_tk
-0x45bb mem_le_ediv
-0x45bd mem_le_rand
-0x45c5 mem_le_irk
-0x45d5 mem_le_fixed_passkey_flag
-0x45d6 mem_le_secure_connect_enable
-0x45d7 mem_le_secure_connect_flag
-0x45d8 mem_le_sc_calc
-0x45d9 mem_le_secure_connect_state
-0x45da mem_le_sc_confirm_gkey_flag
-0x45db mem_le_sc_local_key_invalid
-0x45dc mem_le_pairing_handle
-0x45de mem_le_search_handle_start
-0x45e0 mem_le_search_handle_end
-0x45e2 mem_le_att_offset
-0x45e2 mem_le_search_att_type_length
-0x45e3 mem_le_search_att_type
-0x45f3 mem_le_notify_handle
-0x45f5 mem_le_search_uuid_length
-0x45f6 mem_le_search_uuid
-0x4606 mem_le_handle_data_len
-0x4607 mem_le_handle_data
-0x4617 mem_le_adv_param
-0x4617 mem_le_adv_interval_min
-0x4619 mem_le_adv_interval_max
-0x461b mem_le_adv_type
-0x461c mem_le_adv_own_addr_type
-0x461d mem_le_adv_direct_addr_type
-0x461e mem_le_adv_direct_addr
-0x4624 mem_le_adv_channel_map
-0x4625 mem_le_adv_filter_policy
-0x4626 mem_le_conn_param
-0x4626 mem_le_conn_peer_addr_type
-0x4627 mem_le_conn_peer_addr
-0x462d mem_le_conn_own_addr_type
-0x462e mem_le_conn_interval_min
-0x4630 mem_le_conn_interval_max
-0x4632 mem_le_conn_latency
-0x4634 mem_le_conn_superto
-0x4636 mem_le_scan_params
-0x4636 mem_le_scan_type
-0x4637 mem_le_scan_own_addr_type
-0x4638 mem_le_scan_filter_policy
-0x4639 mem_le_lap
-0x463c mem_le_uap
-0x463d mem_le_nap
-0x463f mem_le_xtype_fifo
-0x4644 mem_le_transmit_window
-0x4648 mem_le_connection_updata_param
-0x4658 mem_le_l2cap_size
-0x465a mem_le_packet_len_recved
-0x465b mem_le_tx_buff_used
-0x465c mem_le_tx_ptr0
-0x465e mem_le_tx_ptr1
-0x4660 mem_le_tx_ptr2
-0x4662 mem_le_tx_ptr3
-0x4664 mem_ui_le_uuid_table
-0x4666 mem_le_cur_attlist_start_ptr
-0x4668 mem_le_cur_handle_start
-0x466a mem_le_cur_handle_end
-0x466c mem_le_cur_uuid_lenth
-0x466d mem_le_cur_uuid
-0x467d mem_notify_handle_pool
-0x4681 mem_le_curr_att_len
-0x4682 mem_le_signaling_identifier
-0x4683 mem_le_more_data
-0x4684 mem_lmp_version
-0x4687 mem_lmp_subversion
-0x4689 mem_local_name_length
-0x468a mem_local_name
-0x468d mem_local_name2
-0x46cd mem_local_name_end
-0x46ce mem_unsniff2sniff_timer
-0x46cf mem_switch_flag
-0x46d0 mem_role_switch_flag
-0x46d1 mem_eeprom_ota_base_addr/*the start- writing addr in eeprom  */
-0x46d3 mem_rfc_xmem_start
-0x46d3 mem_pn_dlci
-0x46d4 mem_pn_max_frame_size
-0x46d6 memFCStemp1
-0x46d7 memFCStemp2
-0x46d8 memFCStemp3
-0x46d9 mem_rfcomm_initiator
-0x46da mem_remote_spp_channel
-0x46db mem_HIUfcs_SPP
-0x46dc mem_HIUfcs_SPP_WCredits
-0x46dd mem_remote_credits
-0x46df mem_credit_given
-0x46e0 mem_ms_channel
-0x46e1 mem_current_packet_length
-0x46e3 mem_profile_channel
-0x46e4 mem_rfc_l2capch_ptr
-0x46e6 mem_rfc_server_state
-0x46e8 mem_rfc_xmem_end
-0x46e8 mem_ui_uuid_table
-0x46ea mem_all_uuid_16bits
-0x4700 mem_all_uuid_128bits
-0x4722 mem_sdp_l2capch_ptr
-0x4724 mem_sp_local_key_invalid
-0x4725 mem_le_private_key_256
-0x4745 mem_le_pubkey_local_x_256
-0x4765 mem_le_pubkey_local_y_256
-0x4785 mem_sp_private_key
-0x479d mem_sp_pubkey_local
-0x479d mem_sp_pubkey_local_x
-0x47b5 mem_sp_pubkey_local_x_end
-0x47b5 mem_sp_pubkey_local_y
-0x47cd mem_ssp_enable
-0x47ce mem_sp_iocap_local
-0x47d1 mem_ssp_mode_flag
-0x47d2 mem_spp_reject_justwork_flag
-0x47d3 mem_sp_iocap_remote
-0x47d6 mem_flag_mode_ssp_pin
-0x47d7 mem_authentication_passkey_times
-0x47d8 mem_passkey_1bit
-0x47d9 mem_flag_pairing_state
-0x47da mem_ipc_lock_bt
-0x47db mem_ipc_lock_c51
-0x47dc mem_ipc_fifo_bt2c51
-0x47e1 mem_ipc_fifo_c512bt
-0x47e6 mem_ui_timer_last_btclk
-0x47ea mem_ui_state_map
-0x47ec mem_discovery_timer_count
-0x47ee mem_discovery_timeout
-0x47f0 mem_ui_profile_supported
-0x47f1 mem_pin_length
-0x47f2 mem_pin
-0x4802 mem_keyscan_switch
-0x4803 mem_kscan_row_nums
-0x4804 mem_kscan_col_nums
-0x4805 mem_row_scanned
-0x4806 mem_col_scanned
-0x4807 mem_row_cnt
-0x4808 mem_get_keypress_flag
-0x4809 mem_kscan_row_gpio_pin
-0x4829 mem_kscan_col_gpio_pin
-0x4849 mem_button_gpio1
-0x484a mem_button_last_state1
-0x484b mem_button_timer1
-0x484c mem_button_press_count1
-0x484d mem_button_timeout1
-0x484e mem_button_press_timeout1
-0x484f mem_button_down_cb1
-0x4851 mem_button_up_cb1
-0x4853 mem_button_longpress_cb1
-0x4855 mem_button_long_release_cb1
-0x4857 mem_button_gpio2
-0x4858 mem_button_last_state2
-0x4859 mem_button_timer2
-0x485a mem_button_press_count2
-0x485b mem_button_timeout2
-0x485c mem_button_press_timeout2
-0x485d mem_button_down_cb2
-0x485f mem_button_up_cb2
-0x4861 mem_button_longpress_cb2
-0x4863 mem_button_long_release_cb2
-0x4865 mem_led_gpio1
-0x4866 mem_led_state1
-0x4867 mem_led_on_timer1
-0x4868 mem_led_off_timer1
-0x4869 mem_led_repeat1
-0x486a mem_led_timer1
-0x486b mem_led_gpio2
-0x486c mem_led_state2
-0x486d mem_led_on_timer2
-0x486e mem_led_off_timer2
-0x486f mem_led_repeat2
-0x4870 mem_led_timer2
-0x4871 mem_uppersm_xmem_start
-0x4871 mem_major_uppersm
-0x4872 mem_sub_uppersm
-0x4873 mem_uppersm_list
-0x4878 mem_uppersm_disl2capch_index
-0x4879 mem_uppersm_xmem_end
-0x4879 mem_m0_lock_qspi
-0x487a mem_m0_pause_state
-0x487b mem_xip_flash_offset
-0x487e mem_xip_option
-0x4880 mem_xip_flash_read_cmd
-0x4881 mem_zcode_current_number
-0x4882 mem_zcode_buff
-0x4884 mem_tws_bdaddr
-0x4884 mem_tws_lap
-0x4887 mem_tws_uap
-0x4888 mem_tws_nap
-0x488a mem_hsp_role
-0x488b mem_auto_hsp_role
-0x488c mem_tws_allow_pairing_rssi_limit
-0x488d mem_tws_role
-0x488e mem_tws_state
-0x488f mem_tws_last_rcv_phone_packet_crc_fail
-0x4890 mem_tws_rcv_ack
-0x4891 mem_tws_local_rcv_packet
-0x4892 mem_tws_last_send_ack
-0x4893 mem_tws_timeout_timer
-0x4894 mem_param_tws_timeout_master
-0x4895 mem_param_tws_timeout_slave
-0x4896 mem_tws_observe_wait_connect_timeout_timer
-0x4897 mem_param_tws_observe_wait_connect_timeout_no_connect
-0x4898 mem_param_tws_observe_wait_connect_timeout_error_disconnect
-0x4899 mem_tws_slave_loss_link_listen_master_timeout_timer
-0x489a mem_param_tws_slave_loss_link_listen_master_timeout
-0x489b mem_tws_poll_slave_timer
-0x489c mem_param_tws_poll_slave
-0x489d mem_tws_master_wait_slave_timeout_timer
-0x489e mem_param_tws_master_wait_slave_timeout
-0x489f mem_tws_m2s_ack_send_timeout_count
-0x48a0 mem_param_tws_m2s_ack_send_timeout
-0x48a1 mem_tws_poll_null_ack_interval
-0x48a2 mem_tws_poll_null_ack_interval_count
-0x48a3 mem_loss_match
-0x48a5 mem_count_rcv_adv
-0x48a6 mem_tws_adv_match
-0x48a7 mem_tws_ack
-0x48a8 mem_tws_count_poll
-0x48aa mem_tws_role_switch_in_process
-0x48ab mem_tws_slave_wait_master_first_polling_flag
-0x48ac mem_tws_profile_connected
-0x48ad mem_tws_profile_disconnected_after_connected
-0x48ae mem_tws_adv_count
-0x48af mem_tws_adv_try_num
-0x48b0 mem_tws_snd_op
-0x48b1 mem_tws_snd_op_nextseq
-0x48b2 mem_tws_snd_cur_arq
-0x48b3 mem_tws_rcv_op
-0x48b4 mem_tws_rcv_op_nextseq
-0x48b5 mem_tws_rcv_old_seq
-0x48b6 mem_tws_cmd_fifo
-0x48bb mem_tws_no_connect_cmd_trans_limit
-0x48bc mem_tws_no_connect_cmd
-0x48bd mem_tws_is_slave_send
-0x48be mem_tws_is_need_send_header
-0x48bf mem_tws_remote_version
-0x48c1 mem_param_tws_tx_power
-0x48c2 mem_le_tws_scan_interval_min
-0x48c4 mem_le_tws_scan_interval_max
-0x48c6 mem_le_tws_scan_interval
-0x48c8 mem_le_tws_scan_window
-0x48ca mem_le_tws_adv_interval
-0x48cc mem_param_le_tws_adv_interval_normal
-0x48ce mem_param_le_tws_adv_interval_master_listen
-0x48d0 mem_tws_first_packet_dynamic_buffer
-0x48d0 mem_tws_first_packet_dynamic_buffer_status
-0x48d2 mem_tws_first_packet_dynamic_buffer_local_bdaddr
-0x48d8 mem_tws_first_packet_dynamic_buffer_paired_bdaddr
-0x48de mem_tws_first_packet_dynamic_buffer_reserved
-0x48ee mem_tws_allow_pairing
-0x48ef mem_tws_last_paired_lap
-0x48f5 mem_tws_rf_start_anchor
-0x48f7 mem_tws_rf_rcv_window_size
-0x48f9 mem_tws_rf_packet_rx_window_size
-0x48fb mem_tws_rf_slave_send_full_packet_sleep_time
-0x48fd mem_tws_rf_master_check_raw_id_time
-0x48ff mem_temp_rf_freq_index
-0x4900 mem_temp_rf_switch_flag
-0x4901 mem_tws_buffer_master_switch
-0x4901 mem_tws_buffer_master_switch_reason
-0x4902 mem_process_sync_buffer
-0x4902 mem_process_a2dp_seq_num
-0x4904 mem_process_clk
-0x4908 mem_process_clkrt
-0x490a mem_process_used_buffer_size
-0x490c mem_process_audio_vol
-0x490d mem_process_sync_receive_buffer// Tws process sync packet
-0x490d mem_process_receive_a2dp_seq_num
-0x490f mem_process_receive_clk
-0x4913 mem_process_receive_clkrt
-0x4915 mem_process_receive_used_buffer_size
-0x4917 mem_process_receive_audio_vol
-0x4918 mem_enable_hfp_start_sync// Tws hfp start sync control
-0x4919 mem_hfp_start_sync_buffer// Tws hfp start sync packet
-0x4919 mem_hfp_start_sync_clk
-0x491d mem_param_tws_send_channel_array
-0x4921 mem_tws_last_send_channel_index
-0x4922 mem_save_state
-0x4923 mem_white_list
-0x4953 mem_remote_rx_max_octets
-0x4955 mem_remote_rx_max_time
-0x4957 mem_remote_tx_max_octets
-0x4959 mem_remote_tx_max_time
-0x495b mem_local_rx_max_octets
-0x495d mem_local_rx_max_time
-0x495f mem_local_tx_max_octets
-0x4961 mem_local_tx_max_time
-0x4963 mem_remote_reserve
-0x49f3 mem_sequence_number_rx
-0x49f4 mem_sequence_number_tx
-0x49f5 mem_msbc_pcm_in_wptr
-0x49f7 mem_msbc_pcm_in_rptr
-0x49f9 mem_msbc_out_wptr
-0x49fb mem_msbc_out_rptr
-0x49fd mem_msbc_in_wptr
-0x49ff mem_msbc_in_rptr
-0x4a01 mem_msbc_pcm_out_saddr
-0x4a03 mem_msbc_pcm_out_wptr
-0x4a05 mem_msbc_pcm_out_rptr
-0x4a07 mem_msbc_packet_len
-0x4a09 mem_msbc_pcm_packet_len
-0x4a0b mem_msbc_enc_dec_bt_lock
-0x4a0c mem_msbc_enc_dec_m0_lock
-0x4a0d mem_msbc_adc_start_send
-0x4a0e mem_vp_language
-0x4a0f mem_vp_play_phonenumber
-0x4a10 mem_vp_mram_flag
-0x4a11 mem_vp_addr_temp
-0x4a14 mem_vp_enable
-0x4a15 mem_vp_dac_addr
-0x4a17 mem_vp_dac_half
-0x4a19 mem_vp_play_block_num
-0x4a1a mem_vp_offset
-0x4a1c mem_vp_start_addr
-0x4a1f mem_vp_end_addr
-0x4a22 mem_vp_play_by_cmd
-0x4a23 mem_vp_play_addr_offset_temp
-0x4a24 mem_param_tishi_start_addr
-0x4a26 mem_nv_le_data
-0x4a26 mem_vp_addr
-0x4ab6 mem_vp_end
-0x4ab6 mem_ota_notify_handle
-0x4ab7 mem_ota_write_handle
-0x4ab8 mem_ota_version
-0x4aba mem_ota_buck_size
-0x4abc mem_ota_packet_max_len
-0x4abe mem_ota_work_mode
-0x4abf mem_adc_start_addr
-0x4ac1 mem_adc_buf_size
-0x4ac3 mem_dac_start_addr
-0x4ac5 mem_dac_buf_size
-0x4ac7 mem_dac_clk
-0x4ac8 mem_dac_mram_flag
-0x4ac9 mem_adc_mram_flag
-0x4aca mem_mono_flag
-0x4acb mem_l_din_sel
-0x4acc mem_r_din_sel
-0x4acd mem_eq_flag
-0x4ace mem_acl_credits
-0x4ad0 mem_allow_switch
-0x4ad1 mem_hci_acl_queue_start/*param_acl_pktcnt+2 byte*/
-0x4ad5 mem_hci_wake_clk
-0x4ace mem_nv_data
-0x4ace mem_nv_data0
-0x4ae6 mem_nv_data1
-0x4afe mem_nv_data2
-0x4b16 mem_nv_data3
-0x4b2e mem_nv_data4
-0x4b46 mem_battery_vol
-0x4b47 mem_coef_base_addr
-0x4b4a mem_ipc_tx_buf
-0x4bae mem_le_att_list
-0x4bb0 mem_tws_fac_adv_name
-0x4bcc mem_param_bt_tx_power
-0x4bcd mem_leadv_action//OTA use,don't change location
-0x4bce mem_hibernate_flag
-0x4bcf mem_lpm_write_temp_adc_low
-0x4bd3 mem_lpm_write_temp_adc_high
-0x4bd7 mem_lpm_write_temp_charge_control
-0x4bdb mem_lpm_write_temp_charge_wakeup_low_active
-0x4bdd mem_lpm_write_temp_charge_wakeup_high_active
-0x4bdf mem_efuse_dc_offset
-0x4bdf mem_efuse_dc_offset_l
-0x4be1 mem_efuse_dc_offset_r
-0x4be3 mem_efuse_dc_offset_f6
-0x4be3 mem_efuse_dc_offset_l_f6
-0x4be5 mem_efuse_dc_offset_r_f6
-0x4be7 mem_efuse_adc_offset
-0x4be7 mem_0_5_adc_io_data
-0x4be9 mem_3v_adc_hvin_data
-0x4beb mem_1v_adc_io_data
-0x4bed mem_5v_adc_hvin_data
-0x4bef mem_xlmp_conn_state
-0x4bf0 mem_xlmp_clock_offset_valid
-0x4bf1 mem_rf_power_fix
-0x4bf2 mem_ipc_rx_ptr
-0x4bf5 mem_module_le_rx_data_len
-0x4bf6 mem_module_le_rx_data_address
-0x4bf8 mem_module_le_rx_data_handle
-0x4bfa mem_module_data_write_handle
-0x4bfc mem_module_data_write_handle2
-0x4bfe mem_module_flag
-0x4bff mem_module_hci_notify_len
-0x4c00 mem_module_hci_notify_handle
-0x4c02 mem_module_hci_nofiy_addr
-0x4c04 mem_last_transmite_clock
-0x4c08 mem_module_le_att_list
-0x4c09 mem_module_le_att_list_end
-0x4c09 mem_le_disconnect_reason
-0x4c0a mem_mesh_le_features
-0x4c12 mem_mesh_le_version
-0x4c17 mem_mesh_le_version_exchange_times
-0x4c18 mem_mesh_hci_opcode_ocf
-0x4c1a mem_mesh_hci_opcode_ogf
-0x4c1b mem_mesh_hci_cmd_len
-0x4c1c mem_mesh_event_mask
-0x4c24 mem_mesh_read_local_version_info
-0x4c24 mem_mesh_read_local_version_info_hci_version
-0x4c25 mem_mesh_read_local_version_info_hci_revision
-0x4c27 mem_mesh_read_local_version_info_lmp_version
-0x4c28 mem_mesh_read_local_version_info_manufacturer
-0x4c2a mem_mesh_read_local_version_info_lmp_subversion
-0x4c2c mem_mesh_read_local_support_command
-0x4c6c mem_mesh_le_event_mask
-0x4c74 mem_mesh_le_public_address
-0x4c7a mem_mesh_le_random_address
-0x4c80 mem_mesh_vendor_tx_flag
-0x4c81 mem_mesh_vendor_tx_freq
-0x4c82 mem_mesh_vendor_tx_data
-0x4c83 mem_mesh_vendor_tx_power_calibration
-0x4c84 mem_mesh_vendor_rx_flag
-0x4c85 mem_mesh_vendor_rx_freq
-0x4c86 mem_mesh_event_head_type
-0x4c87 mem_mesh_event_head_event_code
-0x4c88 mem_mesh_event_para_total_length
-0x4c89 mem_mesh_event_parameter_rtn
-0x4c8a mem_mesh_event_parameter_status
-0x4c8b mem_mesh_creat_connection_flag
-0x4c8c mem_mesh_recevie_acl_packet_number
-0x4c8d mem_device_public_address
-0x4c93 mem_mesh_command_complete_num_hci_command_packet
-0x4c94 mem_mesh_command_complete_command_opcode
-0x4c94 mem_mesh_hci_opcode
-0x4c96 mem_mesh_command_complete_return_parameter_status
-0x4c97 mem_simple_pairing_mode
-0x4c98 mem_fec_required
-0x4c99 mem_inquiry_num_responses
-0x4c9a mem_inquiry_num_check
-0x4c9b mem_conn_status
-0x4c9c mem_inquiry_mode
-0x4c9d mem_inquiry_eir_data
-0x4c9f mem_io_cap_flag
-0x4ca0 mem_page_scan_repetition_mode
-0x4ca1 mem_conn_req_status
-0x4ca2 mem_alloc_normal_block
-0x4ca2 mem_alloc_normal_header
-0x4ca4 mem_alloc_normal_rptr
-0x4ca6 mem_alloc_normal_wptr
-0x4ca8 mem_alloc_normal_end
-0x4caa mem_alloc_normal_total_size
-0x4cab mem_alloc_normal_cur_len
-0x4cac mem_alloc_normal_block_start
-0x4cca mem_alloc_big_block
-0x4cca mem_alloc_big_header
-0x4ccc mem_alloc_big_rptr
-0x4cce mem_alloc_big_wptr
-0x4cd0 mem_alloc_big_end
-0x4cd2 mem_alloc_big_total_size
-0x4cd3 mem_alloc_big_cur_len
-0x4cd4 mem_alloc_big_block_start
-0x4cf2 mem_normal_block_ptr_list
-0x4d10 mem_big_block_ptr_list
-0x4d2e mem_rcv_br_queue_ptr
-0x4d31 mem_rcv_ble_queue_ptr
-0x4d34 mem_snd_br_block
-0x4d34 mem_snd_br_header
-0x4d36 mem_snd_br_rptr
-0x4d38 mem_snd_br_wptr
-0x4d3a mem_snd_br_end
-0x4d3c mem_snd_br_total_size
-0x4d3d mem_snd_br_cur_len
-0x4d3e mem_snd_br_block_start
-0x4d5c mem_snd_ble_block
-0x4d5c mem_snd_ble_header
-0x4d5e mem_snd_ble_rptr
-0x4d60 mem_snd_ble_wptr
-0x4d62 mem_snd_ble_end
-0x4d64 mem_snd_ble_total_size
-0x4d65 mem_snd_ble_cur_len
-0x4d66 mem_snd_ble_block_start
-0x4d84 mem_snd_hci_block
-0x4d84 mem_snd_hci_header
-0x4d86 mem_snd_hci_rptr
-0x4d88 mem_snd_hci_wptr
-0x4d8a mem_snd_hci_end
-0x4d8c mem_snd_hci_total_size
-0x4d8e mem_snd_hci_cur_len
-0x4d8f mem_snd_hci_block_start
-0x4dad mem_regd
-0x4db1 mem_alloc_buffer_len
-0x4db3 mem_temp_alloc_big_malloc_cnt
-0x4db5 mem_temp_alloc_normal_malloc_cnt
-0x4db7 mem_temp_send_br_malloc_cnt
-0x4db9 mem_temp_media_malloc_cnt
-0x4dbb mem_temp_lcp_malloc_cnt
-0x4dbd mem_temp_sco_rx_malloc_cnt
-0x4dbf mem_temp_sco_tx_malloc_cnt
-0x4dc1 mem_temp_alloc_big_free_cnt
-0x4dc3 mem_temp_alloc_normal_free_cnt
-0x4dc5 mem_temp_send_br_free_cnt
-0x4dc7 mem_temp_media_free_cnt
-0x4dc9 mem_temp_lcp_free_cnt
-0x4dcb mem_temp_sco_rx_free_cnt
-0x4dcd mem_temp_sco_tx_free_cnt
-0x4dcf mem_param_alloc_normal_buffer_start_address
-0x4dd1 mem_param_alloc_normal_buffer_max_length
-0x4dd3 mem_param_alloc_big_buffer_start_address
-0x4dd5 mem_param_alloc_big_buffer_max_length
-0x4dd7 mem_ipc_data_rx_buf_subtype
-0x4dd8 mem_ipc_data_rx_buf_payload_ptr
-0x4ddb mem_ipc_data_tx_buf_subtype
-0x4ddc mem_ipc_data_tx_buf_payload_ptr
-0x4ddf mem_le_features
-0x4de7 mem_le_supported_host
-0x4de8 mem_simultaneous_le_host
-0x4de9 mem_default_link_policy_settings
-0x4deb mem_link_policy_settings
-0x4ded mem_le_white_list_cnt
-0x4dee mem_le_white_list
-0x4e0a mem_le_white_list_type_and_bd_addr
-0x4e11 mem_le_white_list_filter_policy
-0x4e12 mem_hci_acl_packet_pb_flag
-0x4e13 mem_hci_acl_packet_len_recved
-0x4e15 mem_hci_acl_packet_payload_ptr
-0x4e17 mem_le_first_packet_count
-0x4e18 mem_hci_record_disc_conn_handle
-0x4e19 mem_fsc_rtk_host
-0x4e1a mem_remote_features
-0x4e22 mem_remote_ext_features0
-0x4e2a mem_remote_ext_features1
-0x4e32 mem_le_scan_window_temp
-0x4e34 mem_zcode_buff_user
-0x4f34 mem_queue_init_flag
-0x4f35 mem_hci_version_svnid
-0x4f37 mem_bd_addr_new
-0x4f3d mem_efuse_encryp_data
-0x4f5d mem_encryp_inital_value
-0x4f5f mem_encryp_param
-0x4f61 mem_encryp_count
-0x4f62 mem_qspi_lock_flag_cm0
-0x4f63 mem_qspi_lock_flag_respin
-0x4f64 mem_qspi_lock_victim
-0x4f65 mem_efuse_64_bytes
-0x4fa5 mem_check_attempt_limit
-0x4fa6 mem_hci_remote_name_req_flag
-0x4fa7 mem_hci_remote_name
-0x4fe7 mem_le_wait_process_cmd
-0x4fe8 mem_loopcnt
-0x4fea mem_le_master_sm
-0x4feb mem_headset_end
-0x4ace mem_usb_mouse_data
-0x4ade mem_usb_kb_data
-0x4aee mem_usb_kb_multikey
-0x4afe mem_usb0_get_report_data
Index: ModuleDemo/25_OTA/bt_demo/CM0/respin/ramcode.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/ramcode.rom	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/ramcode.rom	(nonexistent)
@@ -1,1845 +0,0 @@
-20200040
-20000001
-20000002
-20000003
-20000004
-20000005
-20000006
-20000007
-20000008
-20000009
-2000000a
-2000000b
-2000000c
-2000000d
-2000000e
-2000000f
-20000010
-20000011
-20000012
-20000013
-20000014
-20000015
-20000016
-20000017
-20000018
-20000019
-2000001a
-2000001b
-2000001c
-2000001d
-2000001e
-2000001f
-20000020
-20000021
-20000022
-20000023
-20000024
-20000025
-20000026
-20000027
-20000028
-20000029
-2000002a
-2000002b
-2000002c
-2000002d
-2000002e
-2000002f
-20000030
-20000031
-20000032
-20000033
-20000034
-20000035
-20000036
-20000037
-20000038
-20000039
-2000003a
-2000003b
-2000003c
-2000003d
-2000003e
-2000003f
-c2840060
-c0010084
-c0070186
-c0080194
-c00e0177
-c00f0199
-c0100221
-c01201f1
-c0190159
-c01c8166
-c01d0168
-c01f0216
-c02081e6
-c02206d1
-c02a06cd
-c02c0633
-c02e064f
-c02e8655
-c03506d3
-c03586d5
-c03601dd
-c04080eb
-c0428109
-c04300ce
-c04f00d2
-c050014b
-c05206b6
-c05406a8
-c05c86d7
-c05d05ba
-c0700142
-20202baf
-c00386d9
-c006023e
-c00906db
-c0098561
-c00a0540
-c0118554
-c0128657
-c013065b
-c013865d
-c014065f
-c0148660
-c0150665
-c01d83ba
-c01f03c3
-c01f836c
-c02084c9
-c021069b
-c0240470
-c02584cd
-c027844c
-c02905d9
-c02c06dd
-c02d85f2
-c02e86df
-c03005fc
-c03205f8
-c037067b
-c03806e1
-c03886e3
-c03a014d
-c0490666
-c052860b
-c053060b
-c1590000
-c16a0000
-20202baf
-20406490
-20406863
-20406326
-2040009f
-2040203c
-20403153
-2040008e
-2040233d
-20400094
-20202021
-c68e0000
-18000e02
-20407148
-7d3a001c
-243a209e
-202006e5
-6fe24133
-c4008000
-6fe20030
-c3800000
-18000e06
-20407148
-247a0000
-68444151
-78487c00
-18423600
-202023b7
-204045b4
-204000a2
-2020455e
-6fe244d9
-c1808000
-d8e00003
-20407148
-247a0000
-6fe444da
-d8e00003
-20407141
-20404735
-2040460a
-6fe444dc
-67e44e32
-7854fc00
-78487c00
-69644e32
-204000c3
-243680c0
-204047d5
-1a227e00
-67e24626
-6fec04dd
-67ec0633
-6fe24c8b
-c000838f
-204002d3
-204046d3
-243680c0
-6fe204dc
-c00300c0
-204002d3
-6fe44e32
-243a00ae
-20600000
-204045c7
-204045bd
-7856fc00
-7826fc00
-7830fc00
-78507c00
-19623600
-37c18400
-1b627e00
-67e44e32
-2020465b
-6fe24013
-793ffe06
-67e24013
-202000d4
-204000d4
-20202bd8
-20405900
-70894bba
-204000dd
-708907ff
-20402a70
-70895074
-7089520e
-70896d07
-20600000
-6fe242b4
-c00080e1
-c00200e7
-c00100e1
-5888e0d0
-67e68955
-584a103c
-67e68958
-70895468
-20600000
-5888c0d0
-67e68955
-584a106c
-202000e4
-20407a63
-203080f8
-708955d4
-20000004
-708955d2
-20000004
-708955d1
-20000004
-6fe242b4
-c00080f6
-c0020106
-708955d0
-708956e0
-18002a08
-18002a00
-7850fc00
-78507c00
-782f7c00
-70890200
-70890100
-70890000
-70890300
-70890470
-6fe28906
-793ffe00
-67e28906
-20600000
-708955d0
-708956c0
-202000f8
-60420017
-1840a200
-6fe242b5
-245a2a2d
-20402a7b
-58000250
-20402bb1
-204000dd
-6fe28906
-79207e00
-67e28906
-7089003c
-708901e0
-2000000a
-70890201
-7089023d
-2000000a
-708903b7
-2000000a
-7089027d
-6fe242b4
-c0000130
-c002012b
-70894cfb
-70894def
-70894eec
-70894f5e
-c0008132
-c0028127
-20202a51
-708956ff
-20402a5d
-708955ff
-20600000
-20400136
-708956cc
-20402a5d
-708955d8
-20600000
-20400136
-20202a49
-708956f7
-20402a5d
-708955df
-20600000
-70894c5b
-70894d96
-70894e2c
-70894f46
-20600000
-37d98200
-37d98200
-37d98200
-37d98200
-37d98200
-20600000
-20600000
-20600000
-6fe8833e
-793ffe1d
-67e8804c
-20200147
-37d98200
-70800520
-37d98200
-20600000
-d85fffff
-20202cb8
-78547c00
-204052b0
-6fe20048
-207a0000
-202006e7
-204006e9
-2020022d
-6fe2004b
-79207e03
-67e2004b
-70007201
-20600000
-6fe20183
-203a2378
-d8c00183
-df2000f0
-d8400000
-20400161
-60440099
-2020238d
-efe20006
-207a0000
-18408401
-c2000161
-20600000
-704fa500
-20202414
-6fe24fa5
-1fe0fe01
-67e24fa5
-20405b02
-20402588
-2436a429
-20402bab
-20405b20
-20402500
-2040245a
-20402841
-20402827
-20404b89
-2040017a
-20202425
-20404b89
-2040017a
-20202198
-6fe242a7
-207a0000
-6fe2007c
-247a0000
-202006eb
-704c9b02
-704c8a00
-20200184
-704c9b00
-704ca100
-704c9f00
-202006ed
-6fe24c9a
-203a06ef
-6fe24c99
-203a06e5
-1fe0ffff
-67e24c99
-202006ef
-6fe20018
-1ff18400
-184f840a
-1fe17e0f
-98408400
-18467e00
-20600000
-20402108
-6fe24fa6
-243a01c1
-704c8a04
-20200182
-204024d2
-7854fc00
-6fe24c9b
-c0008194
-6fe2004c
-c28221c5
-6fe20030
-c30221c4
-202002bb
-6fe24c9c
-c00001a8
-c00081ab
-c00101ae
-704c8702
-20600000
-704c880f
-704c8702
-20600000
-704c880f
-704c8722
-20600000
-704c88ff
-704c872f
-20600000
-6fe24fa6
-203a4dab
-6fe4012c
-1fe0f3fd
-68420739
-580000c6
-98408a00
-d8c0073b
-2040713a
-204001d5
-68420053
-6fe2073a
-98467e00
-1fe67c0e
-202101c1
-20204db7
-704c88ff
-704c8707
-20400303
-58000000
-e7e20005
-6fec42a9
-e7ec0005
-df200040
-d8c04fa7
-2040712d
-df2000b8
-204070e4
-2040030d
-6fe24fa6
-704fa600
-70005300
-c00101d3
-20204dbb
-20404f5f
-20204dbb
-68420739
-58004fa7
-98408a00
-6fe2073a
-68420739
-98467200
-d8c0073b
-2020712d
-6fe24fa5
-1fe67c64
-242127fd
-202027ea
-20400249
-68420046
-98467c00
-20628000
-20200297
-20402337
-202c01ee
-204024ca
-243a01e6
-78587c00
-1d027e00
-67e84169
-20600000
-2040248f
-704c8a00
-202006f1
-204021ec
-24740000
-78547c00
-70001120
-793f800b
-20402b71
-2040232b
-c5058201
-204024ca
-243a01f6
-78547c00
-1c427e00
-67e84169
-78387c00
-7834fc00
-202006f3
-20402b6f
-d8200010
-20402321
-78587c00
-7854fc00
-20402917
-204024ab
-204024f3
-2036820d
-204024ca
-243a0208
-202001fb
-18000401
-6fe20031
-793ffe01
-67e20031
-20402bab
-20402940
-78347c00
-704c8a01
-202006f1
-70011600
-70015000
-204024d2
-793f8011
-2040724d
-6fe24c9b
-207a0000
-202002bb
-20404d8e
-c6108000
-2020022d
-6fe20030
-c283a1e1
-6fe20b9c
-203a21e1
-700b9c00
-6fe2004b
-2feffe01
-793ffe01
-67e2004b
-204021e1
-c6108000
-202006e9
-704c8803
-704c8706
-20400303
-18007e00
-e7e20005
-6fe20046
-e7e40005
-2020030d
-704c8806
-704c8717
-20400303
-6fec0040
-e7ec0005
-2020030d
-704c8806
-704c8716
-20200237
-6fe243de
-207a0000
-20403e9d
-20628000
-1fe20c00
-20403e92
-c0058287
-20203ef4
-2040025d
-2040712d
-2020025a
-2040025d
-efe40006
-2020025a
-2040025d
-efe60006
-2020025a
-2040025d
-efec0006
-2020025a
-2040025d
-efee0006
-2020025a
-2040025d
-eff00006
-2020025a
-2040025d
-efe20006
-18c20400
-60464bf2
-20600000
-68464bf2
-18420c00
-20600000
-704e1102
-20600000
-7044d901
-704c8b01
-202002a9
-6fec4c8d
-67ec4639
-67ec4140
-20600000
-20600000
-704ddb00
-2020026e
-704ddb03
-2020026e
-62464ddc
-58004b4a
-67e443e3
-1fe20a00
-5800000a
-e7e20005
-18007e04
-e7e20005
-6fe24ddb
-e7e20005
-6fe64ddc
-e7e60005
-18007e06
-67e243e2
-20203f1a
-204006f5
-6a464dd8
-2020026a
-20400283
-6a464dd8
-20200581
-2040025d
-df200003
-d8a04dd8
-20203e88
-20403e92
-20403e92
-67e24dd7
-2040025a
-6fe24dd7
-c0000280
-204005a2
-207a0000
-20400283
-6fe24dd7
-c001827d
-20202baf
-704c9612
-2020029a
-704c9601
-2020029a
-704c960c
-2020029a
-704c9600
-df200001
-2040029e
-2020030d
-704c9600
-204002a2
-6fe24c96
-e7e20005
-20600000
-704c870e
-1f20fe03
-67e24c88
-20400303
-6fe64c93
-e7e60005
-20600000
-700f1200
-202002ae
-700f120c
-202002ae
-700f1202
-704c870f
-704c8804
-20400303
-6fe20f12
-e7e20005
-6fe64c93
-e7e60005
-2020030d
-6ff04c6c
-c4020000
-6fe20639
-67e24e18
-202006f7
-6fe20046
-67e24e18
-793f8021
-70004600
-704ca100
-704c9b00
-202006f7
-6fe20624
-d8400000
-c1018000
-d8400001
-20600000
-6fe204db
-1fe17e0f
-d8400000
-c1000000
-d8400001
-c1008000
-d8400002
-c1030000
-d8400003
-c1010000
-d8400004
-20600000
-6ff04c6c
-c4008000
-dfe00006
-684204dc
-9840fe00
-67e24c88
-1fe0fe03
-67e44db1
-da204cca
-20400551
-1fe67c02
-20610000
-704c873e
-20400303
-58000002
-e7e20005
-58000001
-e7e20005
-204002c7
-e0420005
-204047d5
-1a227e00
-e7e20005
-684204dc
-184085fa
-efec0006
-e7ec0005
-e0420005
-18427200
-2040712d
-2040018d
-e7e20005
-2020030d
-6fe20046
-67e242a8
-202002f9
-6fe20639
-67e242a8
-704c8805
-704c8713
-20400303
-58000001
-e7e20005
-6fe242a8
-e7e40005
-58000001
-e7e40005
-2020030d
-6fe24c88
-1fe0fe03
-67e44db1
-2040030a
-6fe64c86
-e7e60005
-20600000
-2040055e
-1a420a00
-20600000
-da204d84
-20403fa5
-2020026c
-18000400
-18000201
-60421001
-6842063a
-79200405
-18417efc
-9821fe00
-67e2063a
-1fe17e1f
-280ffe26
-7920fe04
-67e21000
-20600000
-6fe2063a
-c3828000
-2040033f
-20400353
-203a0310
-efe20006
-ea220006
-9a267e00
-18c20a00
-68444953
-2040726f
-1fe20400
-18a20c00
-e8220006
-1a227e00
-98c08c00
-d8a01002
-18427200
-2040712d
-2040480e
-20400312
-20400353
-efe20006
-1fe22200
-18c23000
-ea420006
-9a467e00
-68444953
-2040726f
-9a40fe00
-e7e20018
-9a267c00
-24628000
-202049f1
-6fe24683
-203a480c
-20400349
-c6130000
-da204d5c
-20400551
-c000480c
-c000c80c
-79200026
-20600000
-20400353
-203a480c
-efe20006
-e8420006
-98460400
-6fe44953
-98467c00
-2021480c
-79200026
-20600000
-da204d5c
-20203fa1
-20400357
-20202739
-204045bd
-204045cd
-20407a47
-79202a00
-782efc00
-78307c00
-7850fc00
-20404644
-19317e00
-1fecfe00
-1ff1fe00
-08008628
-7823fc00
-7824fc00
-6fe21000
-08008608
-efe20006
-1fe27200
-08008608
-2022c6a6
-202046a3
-20407a4f
-204045aa
-20404766
-2040031d
-20400355
-20400527
-20404594
-20340536
-2020458a
-6fe20623
-79207e05
-67e20623
-70452d01
-58000003
-67e4452e
-6fe444d7
-67e44530
-6fe44632
-67e44532
-6fe44634
-67e44534
-6fe4063d
-1fe0fe10
-67e40643
-da20000c
-d8200003
-204049ab
-58000000
-e7e20005
-6ff2452d
-e7f20005
-6fe40643
-e7e40005
-20400423
-202006f9
-6fec0633
-684c4627
-98467c00
-24628000
-20402266
-24628000
-204046f1
-2040454a
-7042a700
-70065b00
-204047d2
-202006fb
-204005ae
-67e64e15
-58000000
-67e64d2e
-6fe20046
-67e242a8
-704ddb05
-202003aa
-204005b4
-67e64e15
-58000000
-67e64d31
-6fe20639
-67e242a8
-704ddb04
-58004b4a
-67e443e3
-1fe20a00
-5800000a
-e7e20005
-18007e06
-e7e20005
-6fe24ddb
-e7e20005
-6fe64e15
-e7e60005
-6fe242a8
-e7e40005
-18007e08
-67e243e2
-20203f1a
-20404536
-70100001
-70100100
-5800001b
-67e44953
-204024ce
-1fe0fe18
-67e20639
-20600000
-204045b4
-2040315c
-6fe20624
-c001840b
-20204579
-20400249
-67e242a8
-20400249
-1febfe00
-67e444d7
-20400249
-20400249
-67e44632
-20400249
-67e44634
-20400425
-202002a9
-20400357
-2020053a
-6fe24fea
-c00003f3
-c00083f6
-c00183f8
-c00203fa
-c00303f4
-c00503de
-20600000
-6fe20623
-79207e06
-67e20623
-5fcf3ff3
-67e84528
-5800001f
-e7e20005
-704feaff
-da20000c
-d8200003
-204049ab
-58000001
-e7e20005
-6fea4528
-e7ea0005
-580000fe
-6fe4063d
-1fe0fe40
-e7e40005
-67e40643
-20600000
-20600000
-704fea0a
-20600000
-704fea02
-202048f0
-704fea04
-20600000
-704fea05
-da200009
-d8200003
-204049ab
-58000008
-e7e20005
-58000001
-e7f00005
-20600000
-6fe24fea
-c1828000
-704fea06
-20600000
-6fe24fea
-c1810000
-704fea03
-20600000
-7834fc00
-204048fd
-202106a5
-204003d6
-2040031d
-204045fc
-7856fc00
-204003d4
-24368440
-20407a4f
-2040043a
-20404766
-20400527
-20404594
-20340427
-2040041d
-7854fc00
-20202739
-6fe20623
-c3830000
-6fe24fe7
-207a0000
-c0098375
-20202baf
-704fe700
-20600000
-704fe713
-20600000
-2040031d
-2040042d
-78377c00
-2040053a
-20368414
-2020041a
-2040042f
-20202739
-204045bd
-204045cd
-20407a47
-79202a00
-782efc00
-78307c00
-7850fc00
-20400438
-2020035f
-37c18200
-20600000
-6fe20623
-c3818000
-79207e03
-67e20623
-704fea01
-20600000
-6fe20623
-c281841a
-6fe24e17
-1fe67c06
-242106a5
-1fe0fe01
-67e24e17
-2020041a
-684c4639
-20600000
-684c4c7a
-20600000
-6fe2461b
-c000c6bd
-6fe2461c
-1ff27e00
-1febfe00
-6842461b
-9840fe00
-67e24536
-684244df
-1840fe06
-67e24537
-18427200
-6fe2461c
-205a0448
-245a044a
-604c4538
-d8c044e0
-2040712d
-202046cd
-6fe20623
-c4028000
-6fe4063d
-68440643
-98467e00
-67e40124
-24610000
-2040473e
-202006f9
-6a280f1e
-6a480f22
-6a660f26
-20600000
-62280f1e
-62480f22
-62660f26
-20600000
-2040046c
-67244fe8
-1a208c01
-efe20006
-c4000000
-1a208a1a
-efe40005
-1fe0fe01
-e7e40005
-2040049c
-2040048b
-20404618
-20400468
-6f244fe8
-20600000
-1a208c31
-efea0006
-18000400
-18007225
-c3004628
-18408401
-1fe37e00
-c2000483
-1840ffff
-1a208a22
-e7e20005
-20600000
-1a208c00
-efe20006
-c4030000
-1a208c1a
-efe40006
-68440643
-98467e00
-24610000
-1a208a00
-efe20005
-793ffe06
-e7e20005
-67e20623
-6fea4528
-1a208a31
-e7ea0005
-2020047f
-1a208c00
-efe20006
-c4028000
-1a208c01
-efe20006
-c4008000
-1a208c1a
-e8440006
-6fe40643
-98467e00
-1fe67c01
-202284b2
-20600000
-1a208c1a
-efe40006
-1a208c20
-efe40006
-98467e00
-d840ffff
-98467c00
-202284b2
-20600000
-efe20011
-793ffe05
-e7e20011
-1a208c04
-e8480006
-6fe2452d
-1a208a2c
-e7e20005
-efe40006
-1febfe00
-98409600
-19609601
-1a208a04
-19627e00
-e7e80005
-efe40006
-1febfe00
-1a208a02
-e7e40005
-efe80006
-1a208a2d
-e7e80005
-20600000
-20404972
-2040475a
-2040045f
-20202940
-78287c00
-6fe40631
-68484644
-98409600
-204045c7
-204045bd
-7856fc00
-78567c00
-7826fc00
-7830fc00
-78507c00
-19623600
-37c18400
-203704dd
-1b420400
-604c00a4
-242c2739
-203704e4
-dd2001e0
-1c225000
-6fe20623
-c30184e4
-2055ac9c
-20402abc
-7823fc00
-7824fc00
-09800008
-19897e00
-67e204db
-6842063a
-1fe37e00
-9842fe00
-2feffe02
-7920800f
-09800008
-19897e00
-67e204dc
-1fe27200
-67e2068c
-203a050e
-6fe204db
-1fe17e03
-c0018503
-c5078505
-da204cca
-20400551
-c0008505
-204005aa
-203a0505
-204005b4
-18c20a00
-6fe404db
-e7e40005
-2020050a
-d8a004dd
-2020050a
-09800008
-19897e00
-c2000505
-78367c00
-2020050e
-09800008
-19897e00
-e7e20005
-c200050a
-09800018
-78287c00
-db600664
-20360515
-1fef7e00
-1ff17e00
-e7e60005
-20437a57
-20232739
-7836fc00
-6fe242b5
-243a051d
-6fe20017
-1fe0a200
-20402a7b
-7846fc00
-20202a17
-efe20006
-1fe17e03
-67e2068d
-efe20006
-67e2068c
-207a0000
-60c4068e
-20600000
-c6078000
-c68d0000
-20760000
-6fe204dc
-207a0000
-6fe204db
-1fe17e03
-c001c866
-204005b4
-2040051f
-6fe2068c
-207a0000
-6fe2068d
-c001c866
-202003a3
-78377c00
-2040053a
-2036c582
-2020458a
-68420017
-20402a1f
-20402a23
-78287c00
-d9601388
-202004d2
-1a208409
-efe20002
-203a2baf
-1a20fe02
-e844003f
-ea460002
-58000000
-e7e60002
-1840a603
-20403f8d
-1a20fe02
-e264003f
-1a208409
-efe20002
-1fe0ffff
-e7e20002
-20600000
-1a208409
-efe20002
-20600000
-dee002a8
-6fe204d5
-c1018000
-20204146
-20400573
-da204d34
-20203f94
-da204d34
-20403fa5
-20200581
-20400573
-da204d84
-20203f94
-1a20fe04
-e844003f
-e2460002
-1840a603
-20403f8d
-1a20fe04
-e264003f
-1a20a609
-e8420013
-18408401
-e0420013
-1a20a608
-efe20013
-98467c00
-24212baf
-1a420c00
-1a427e00
-20600000
-20400595
-203a2baf
-6fe44dd1
-1fe0fff6
-68444db1
-98467c00
-2021057c
-da204cca
-20203fa5
-da204ca2
-20400551
-203a057a
-da204ca2
-20203fa5
-2040058d
-da204ca2
-203a0586
-da204cca
-20203f94
-2040058a
-203a2baf
-da204ca2
-20203f94
-6f224caa
-d8c04cf2
-2020058f
-6f224cd2
-d8c04d10
-efe60006
-9a467c00
-20228593
-c200058f
-1f227e00
-20600000
-6fe44dd1
-1fe0fff6
-68444db1
-98467c00
-2021059c
-da204cca
-20200551
-da204ca2
-20400551
-247a0000
-2020059a
-6fe44dd5
-202005a3
-58000010
-67e44db1
-62280f1e
-20400595
-6a280f1e
-20600000
-da204cca
-20203fa5
-6fe44d2e
-247a0000
-da204cca
-20200551
-6fe64d2e
-243a7111
-204005a8
-1a427e00
-67e64d2e
-20207111
-6fe64d31
-243a7111
-204005a8
-1a427e00
-67e64d31
-20207111
-da2047dc
-2040725d
-207a0000
-1fe22600
-20203190
-1a627e00
-c00a85c2
-20203168
-704c8c00
-704c1700
-204006fd
-204002b6
-202031c3
-6842063a
-284c0005
-20608000
-6fe204db
-1fe3fe00
-9842fe00
-c4018000
-793f8405
-79400403
-6042063a
-28400603
-24608000
-6fe245b5
-c0014794
-6fe21002
-c00106a5
-c002c790
-20600000
-20404906
-204005c7
-6fe204db
-2feffe04
-79208027
-1fe37e00
-9842fe00
-2feffe02
-7920800f
-6fe204dc
-203a05eb
-6fe20623
-c30205eb
-c6078000
-20406246
-204061b6
-793a001a
-247a0000
-20760000
-c6078000
-7920001a
-6842063a
-79400402
-6042063a
-20600000
-6fe244de
-207a0000
-d8e00001
-20407148
-247a0000
-202006ff
-20400608
-18227e00
-c1018000
-202002f7
-62244db1
-20400605
-1a420a00
-6fe44db1
-e7e20005
-58000000
-e7e20005
-e0220005
-20600000
-20400573
-da204d5c
-20203f94
-da204d5c
-20403fa5
-20200581
-6fe20b97
-243a0701
-6fe20b98
-243a0701
-20600000
-6fe2004b
-79207e02
-67e2004b
-20404f51
-7006ae01
-2040023b
-204052de
-2420cf59
-2434cd67
-20600000
-6fe24c97
-207a0000
-6fe20b95
-247a0000
-20402287
-24628000
-1a208c01
-efe20006
-c4008000
-20400626
-704c9f01
-20600000
-704c8806
-704c8731
-20400303
-6fec0040
-e7ec0005
-2020030d
-6fe20151
-1fe17e03
-c080a68a
-da204cca
-20403fb4
-203a2739
-2020268a
-1f227e00
-67e4012c
-203a062c
-9ea67c00
-20212729
-18017e01
-243a063e
-6fe20151
-1fe17e03
-c001a649
-c507a6f0
-684444d2
-184085fd
-6fe4012c
-98467c00
-20212729
-da204cca
-20400551
-c000a739
-204005aa
-203a2739
-204005ae
-18c20a00
-6fe20151
-e7e20005
-6fe4012c
-e7e40005
-20202686
-09800010
-20437a57
-20232722
-c58026ba
-793f8000
-20600000
-2040039b
-202026dd
-62244db1
-20400558
-6a244db1
-20600000
-da204d34
-20203fa1
-2040055b
-202002f4
-2020055b
-204005a0
-203a729b
-2020729d
-da204d34
-20200551
-20202baf
-20400663
-207a0000
-6fe2004b
-c3830000
-2040419e
-efe40006
-67e40099
-efe20006
-79207e02
-67e20098
-18c27e00
-67e4013c
-6fe4442c
-203a0675
-20205b2e
-6fe40099
-203a2baf
-d84002a7
-98467e00
-2022db44
-20205b3e
-70429300
-20204b77
-67e40fb7
-2020067f
-68440fb7
-18518400
-6fe44881
-98467c00
-2022d86b
-60444881
-58000100
-984f8400
-6fe6487b
-98467e00
-6846433d
-9840fe00
-1fe0fffc
-67e6023c
-58000100
-67e40241
-58004e34
-67e4023f
-204006c6
-204057e8
-6fe280a0
-67e20124
-20405589
-6fe20124
-67e280a0
-704f6300
-58004e34
-20205866
-20404528
-204045a4
-20403212
-2040682b
-6fe20623
-793ffe00
-793ffe01
-67e20623
-700f0d15
-20206b2e
-2040069c
-7854fc00
-20600000
-6fe24040
-c3800000
-c3818000
-6fe247cd
-203a06af
-6fe24724
-207a0000
-20202d53
-6fe206ab
-67e24bef
-20200703
-7043dd01
-20403f41
-20200703
-6fe20fd6
-c05506c5
-6fe24131
-207a0000
-20400663
-247a0000
-da204d5c
-20400551
-247a0000
-da204cca
-20400551
-68424caa
-98467c00
-24628000
-20202d15
-20202001
-704f6301
-704f6453
-6fe24f62
-207a0000
-6fe24f64
-c1a98000
-202006c8
-18227e00
-c003a739
-c0032739
-202025df
-580002e0
-2020067d
-580002a0
-2020067d
-580002b0
-2020067d
-58000240
-2020067d
-58000250
-2020067d
-580000f0
-2020067d
-58000320
-2020067d
-580002f0
-2020067d
-58000200
-2020067d
-580001c0
-2020067d
-58000230
-2020067d
-58000300
-2020067d
-58000190
-2020067d
-58000290
-2020067d
-58000120
-2020067d
-58000170
-2020067d
-580002c0
-2020067d
-580002d0
-2020067d
-580001e0
-2020067d
-58000140
-2020067d
-580001b0
-2020067d
-580001a0
-2020067d
-580001f0
-2020067d
-58000260
-2020067d
-58000270
-2020067d
-58000280
-2020067d
-58000080
-2020067d
-58000070
-2020067d
-580000d0
-2020067d
-58000060
-2020067d
-580000c0
-2020067d
-58000090
-2020067d
-580000a0
-2020067d
-580000b0
-2020067d
-580000e0
-2020067d
-58000160
-2020067d
-58000100
-2020067d
-58000010
-2020067d
-58000020
-2020067d
-58000030
-2020067d
-58000040
-2020067d
-58000050
-2020067d
-58000110
-2020067d
-58000210
-2020067d
-58000220
-2020067d
-580001d0
-2020067d
-58000150
-2020067d
-58000180
-2020067d
-58000310
-2020067d
-58000330
-2020067d
Index: ModuleDemo/25_OTA/bt_demo/CM0/respin/sched.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/sched.rom	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/sched.rom	(nonexistent)
@@ -1,425 +0,0 @@
-
-mem_patch00:     
-04   #mem_patch00
-40   #mem_patch01
-01   #mem_patch02
-50   #mem_patch03
-11   #mem_patch04
-00   #mem_patch05
-04   #mem_patch06
-46   #mem_patch07
-12   #mem_patch08
-00   #mem_patch09
-10   #mem_patch0A
-31   #mem_patch0B
-00   #mem_patch0C
-1c   #mem_patch0D
-00   #mem_patch0E
-00   #mem_patch0F
-62   #mem_patch10
-00   #mem_patch11
-00   #mem_patch12
-40   #mem_patch13
-11   #mem_patch14
-01   #mem_patch15
-00   #mem_patch16
-06   #mem_patch17
-00   #mem_patch18
-00   #mem_patch19
-00   #mem_patch1A
-00   #mem_patch1B
-01   #mem_patch1C
-00   #mem_patch1D  
-00   #mem_patch1E
-00   #mem_patch1F
-80   #mem_patch20
-10   #mem_patch21
-1c   #mem_patch22
-00   #mem_patch23
-e8   #mem_patch24
-07   #mem_patch25
-00   #mem_patch26
-c8   #mem_patch27
-06   #mem_patch28
-89   #mem_patch29
-04   #mem_patch2A
-29   #mem_patch2B
-11   #mem_patch2C
-40   #mem_patch2D
-13    #mem_patch2E
-00   #mem_patch2F
-00   #mem_patch30
-00   #mem_patch31
-04   #mem_patch32
-00   #mem_patch33
-60   #mem_patch34
-00   #mem_patch35
-04   #mem_patch36
-00   #mem_patch37
-00   #mem_patch38
-00   #mem_patch39
-10   #mem_patch3A
-00   #mem_patch3B
-00   #mem_patch3C
-00   #mem_patch3D
-00   #mem_patch3E
-00   #mem_patch3F
-
-
-##############NVRAM CONFIG##############
-mem_nv_data_ptr:mem_nv_data
-mem_nv_data_number:05
-#####################################
-
-##############BLUETOOTH CONFIG##############
-###commom###
-mem_device_option:0f
-mem_lmp_version:09 0e 05 06 00
-###ble###
-mem_le_lap:d5 cc aa aa cc 52
-
-mem_le_adv_data_len:12
-mem_le_adv_data:
-02 01 0e 
-04 09 4f 54 41
-09 ff 0e 05 21 11
-
-mem_le_scan_data_len:05
-mem_le_scan_data:
-'\09OTA
-
-
-mem_le_adv_enable:00
-mem_le_scan_type:01
-mem_le_adv_type:00
-mem_le_adv_direct_addr_type:00
-mem_le_scan_own_addr_type:00
-mem_le_scan_filter_policy:00
-mem_le_scan_interval:28
-mem_le_scan_window:0c 00
-mem_le_transmit_window:50
-mem_le_adv_interval_max:60 01 
-mem_le_adv_own_addr_type:00
-
-mem_le_pairing_mode:00
-mem_le_secure_connect_enable:00
-mem_le_pres:02 03 00 01 10 02 03 #justwork
-
-mem_le_pairing_handle:00 00
-
-mem_le_interal_min:
-10 00 #interval max
-10 00 #interval min
-00 00 #latency
-00 01 #supervision timeout
-
-###3.0###
-mem_sp_iocap_local:03 00 00
-mem_role_switch_flag:00
-mem_scan_mode:00
-mem_class: 04 04 24
-mem_local_name_length:
-'EVKOTA
-
-#FF FF FF is Fixed for OTA.
-mem_lap:45 FF 31 FF FF FF
-
-mem_discovery_timeout:00 07 
-mem_ssp_enable:01
-mem_ui_profile_supported:48
-mem_app_connection_options:17
-mem_eir_enable:01
-mem_all_uuid_16bits:
-05
-03#Type: Complete list of 16-bit UUIDs
-1e11 0e11 0811 0d11 0b11
-
-mem_all_uuid_128bits:00
-
-mem_ota_version:0a 00
-mem_ota_write_handle:06
-mem_ota_notify_handle:03
-mem_ota_buck_size:00 10
-mem_ota_packet_max_len:be 00
-
-#attribute list: handle 2bytes, uuid 2bytes, length 1bytes, attribute Nbytes
-mem_le_att_list:
-
-#Primary service yichip transmit ------
-01 00 02 00 28 02 ff ff
-#Characteristic tx--notify
-02 00 02 03 28 01 10
-03 00 02 11 ff 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#Client Characteristic Configuration
-04 00 02 02 29 02 01 00
-
-#Characteristic rx--write
-05 00 02 03 28 01 04
-06 00 02 22 ff  14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-
-#End of Attribute list
-00 00
-
-
-
-mem_lpm_mode:00
-mem_lpm_overhead:08
-mem_lpm_interval:00 02
-mem_lpm_mult:03
-mem_lpm_mult_timeout:03
-mem_ptt:01
-mem_features:
-ff
-ff
-ff
-fa	#fe--EDR  F8--BR
-db	#AFHclose 83  #AFHenable_slave cap and classification LMP_SLAVE_AFH_CLASSIFICATION enable 9b, disable 8b
-fd    #9d
-7b
-83
-
-mem_le_features:
-21				//length extension
-00
-00
-00
-00
-00
-00
-00
-
-
-mem_xip_option:5d 40 bb
-
-mem_ui_le_uuid_table:mem_le_att_list
-
-mem_seqi:7f
-
-mem_le_connection_updata_param:
-06 00
-06 00
-00 00
-f4 01
-
-
-mem_codec_msbc_support:00
-mem_codec_type:01
-mem_eq_flag:01
-
-mem_UI_HF_brsf_feature:313538 #30 33 30 
-mem_le_more_data:01
-mem_ipc_enable:01
-
-mem_tws_state:00
-mem_tws_bdaddr:96 55 12 11 33 62
-#mem_tws_bdaddr:96 45 12 00 19 62
-
-
-mem_hsp_role:00
-mem_auto_hsp_role:01
-mem_tws_allow_pairing:01
-mem_tws_allow_pairing_rssi_limit:45
-
-mem_tws_rf_start_anchor:b0 04   # 0x1e0 40us,   0x78 10us,   0x4b0 100us,   0x618 130us
-mem_tws_rf_rcv_window_size:78 00
-
-mem_tws_rf_packet_rx_window_size:f0 0a # 2800
-mem_tws_rf_slave_send_full_packet_sleep_time:58 02 # 50us
-# mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us)
-# send delay is mem_tws_rf_slave_send_full_packet_sleep_time, so we can think the judge below
-# mem_tws_rf_packet_rx_window_size - (mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us) + mem_tws_rf_slave_send_full_packet_sleep_time/2)
-mem_tws_rf_master_check_raw_id_time:db 04
-
-mem_rf_debug_enable: 00
-mem_rf_debug_rf_rx_debug_gpio: 0c
-mem_rf_debug_rf_tx_debug_gpio: 0e
-mem_rf_debug_rf_sync_detect_debug_gpio: 13
-mem_rf_debug_rf_crc_error_debug_gpio: 19
-
-
-mem_param_sco_use_cm0:01
-
-
-# ipc define
-#mem_param_ipc_mem_block_start_addr
-mem_param_ipc_to_bt_buf_start_addr:00 d8 01
-mem_param_ipc_to_bt_buf_end_addr:00 db 01
-mem_param_ipc_to_bt_wptr_addr:00 db 01
-mem_param_ipc_to_bt_rptr_addr:04 db 01
-mem_param_ipc_to_m0_wptr_addr:08 db 01
-mem_param_ipc_to_m0_rptr_addr:0c db 01
-mem_param_ipc_to_m0_buf_start_addr:50 db 01
-mem_param_ipc_to_m0_buf_end_addr:00 dd 01
-#mem_param_ipc_mem_block_end_addr
-
-
-# debug log define
-#mem_param_debug_log_mem_block_start_addr
-mem_param_debug_log_func_enable:00
-
-mem_param_debug_log_initial_flag_addr:10 db 01
-mem_param_debug_log_lock_flag_cm0_addr:11 db 01
-mem_param_debug_log_lock_flag_respin_addr:12 db 01
-mem_param_debug_log_lock_victim_addr:13 db 01
-mem_param_debug_log_read_index_addr:14 db 01
-mem_param_debug_log_write_index_addr:16 db 01
-mem_param_debug_log_buffer_start_addr:18 db 01
-mem_param_debug_log_buffer_end_addr:50 db 01
-#mem_param_debug_log_mem_block_end_addr
-
-# soft dma define
-# size is SOFT_DMA_TABLE_TOTAL_COUNT*4 + SOFT_DMA_TABLE_TOTAL_COUNT*SOFT_DMA_TABLE_UNIT_SIZE = 0x100
-mem_param_soft_dma_enable:01
-mem_param_soft_dma_table_start_addr:10 d5 01
-
-
-# sco m0 rx buffer define
-# size is M0_SCO_RX_BUFFER_SIZE + M0_SCO_TX_BUFFER_SIZE
-mem_param_m0_respin_sco_buffer_start_addr:10 d6 01
-
-
-mem_param_use_cm0_control_flag:01
-# tishi buffer size is 0x2000
-mem_param_tishi_start_addr:00 a0
-
-#mem_app_debug_info_timer use to set first debug timeout
-#mem_param_app_debug_info_timeout use to set period
-mem_app_debug_info_timer:05
-mem_param_app_debug_info_timeout:32
-
-mem_param_tws_tx_power:02
-
-mem_param_tws_send_channel_array:08 24 08 24
-#mem_param_tws_send_channel_array:20 20 20 20
-#mem_param_tws_send_channel_array:08 09 10 11
-
-mem_tx_power:02
-
-mem_sfreq_enable:01
-#mem_param_rf_setup must big then mem_param_pll_setup, be-careful, mem_param_rf_setup real value = 0xEA6 - value
-#we suggest must reserve 0x3A6, means mem_param_rf_setup = (0xEA6 - mem_param_pll_setup - 0x3A6)
-#mem_param_rf_setup:B8 07
-#mem_param_pll_setup:48 03
-mem_param_rf_setup:00 06
-mem_param_pll_setup:00 05
-
-mem_audio_output_setting: 01
-
-
-mem_mram_qspi_tx_addr:00 60
-
-mem_vp_addr:
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-000000 000000
-
-mem_fec_required:00		
-mem_eir:
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00
-00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 00 00 00 00
-mem_simple_pairing_mode:00	
-mem_conn_status:00
-mem_io_cap_flag:00
-mem_inquiry_mode:00
-
-
-mem_param_alloc_normal_buffer_start_address:00 18
-mem_param_alloc_normal_buffer_max_length:83 00
-mem_param_alloc_big_buffer_start_address:00 20
-mem_param_alloc_big_buffer_max_length:b0 02
-mem_l2cap_rx_max_lenth:b0 02
-
-
-mem_alloc_normal_total_size:0a
-mem_alloc_big_total_size:0a
-mem_snd_br_total_size:0a
-mem_snd_ble_total_size:0a
-mem_snd_hci_total_size:0a
-
-mem_hci_version_svnid:4486
-
-mem_keyscan_switch:00
-
-mem_public_code_svn_version_code:00 00 00 00 00 00 00 00 00
-
-mem_le_tws_scan_interval:28 00
-mem_le_tws_scan_window:0c 00
-mem_param_le_tws_adv_interval_normal:00 01 
-mem_param_le_tws_adv_interval_master_listen:58 00 
-
-
-#mesh init
-mem_mesh_event_head_type:04	#HCI_H4_TYPE_EVENT
-
-mem_mesh_command_complete_num_hci_command_packet:01
-
-mem_mesh_read_local_version_info:
-09		#hci_version BT_HCI_VERSION_5_0
-00 00	#hci_revsion
-09		#lmp_version RADIO_BLE_VERSION_NUMBER:BT_HCI_VERSION_5_0
-0e 05	#manufacture_name Yichip Microelectronics (Hangzhou) Co.,Ltd.
-FF FF	#LPM_subversion
-
-mem_mesh_read_local_support_command:02 05 ff
-
-mem_device_public_address:11 22 33 44 55 66
-
-mem_local_rx_max_octets:fb 00 48 08 fb 00 48 08  
-
-
-mem_lpm_config:8f 10 ca
-mem_lpm_buckcnt:0a 0b ef 07
-mem_lpm_hibernate_switch:00
-mem_gpio_wakeup_low:00 00 00 00 00 00 00 00
-mem_fcomp_mul:02
-mem_fcomp_div:24
-mem_iscan_window:20 00
-mem_iscan_interval:00 04
-mem_pscan_window:16 00
-mem_pscan_interval:00 04
-mem_inq_window:20 00
-mem_page_window:30 00
-mem_page_to:00 30
-mem_rx_window_init:80 03
-mem_rx_window_sniff:00 06
-
-#if you find lpo_time not near 0x2a, you must think the pre timer maybe error.
-#DVDD 0.1uF, VFB 1uF    Time:   DVDD up time: 4us, VFB up time: 255us
-#DVDD 0.1uF, VFB 10uF    Time:   DVDD up time: 4us, VFB up time: 305us 
-#clock unit is internal 32K, 1 step is near 32us
-#so we set:
-#1: digldo pre-on counter(DVDD):  0x02
-#2: exen pre-on counter(VFB):  0x14
-#3: xtal pre-on counter(XTAL) set to zero becouse it will set in lpm_cal_xtal_startup
-mem_lpm_xtalcnt:00 20 18 bf 07
-
-mem_ef_base:00 ff 87
-mem_eeprom_block_size:80
-
-mem_rf_init:
-ff
-
-mem_rf_init_ptr:mem_rf_init
-
Index: ModuleDemo/25_OTA/bt_demo/CM0/respin/zcode.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/zcode.rom	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA/bt_demo/CM0/respin/zcode.rom	(nonexistent)
@@ -1,3264 +0,0 @@
-20200040
-6fe204dd
-c00a0021
-c00a800d
-c0010006
-20204868
-efe20006
-67e206a4
-20204890
-98467c00
-20610000
-1fe20400
-20600000
-eff00006
-67f04953
-6fe44953
-6844495f
-20400009
-60444953
-6fe44957
-6844495b
-20400009
-60444957
-704c880b
-704c873e
-20400303
-58000007
-e7e20005
-6fe20639
-e7e40005
-6ff04953
-e7f00005
-2020030d
-2040000d
-da200009
-d8200003
-204049ab
-58000015
-e7e20005
-6ff0495b
-e7f00005
-20600000
-da400014
-20200022
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe204dd
-c0040013
-c004801c
-c006002b
-c0008008
-c0004880
-20200733
-efea0006
-67ea4528
-efe40006
-67e40643
-6844063d
-98467c00
-24214890
-6fe20623
-79207e06
-67e20623
-20600000
-2040001c
-da200009
-d8200003
-204049ab
-58000009
-e7e20005
-6ff04ddf
-e7f00005
-20600000
-eff00006
-67f04c0a
-20400403
-6ff04c6c
-c4018000
-704c880c
-704c873e
-20400303
-58000004
-e7e40005
-6fe20639
-e7e40005
-6ff04c0a
-e7f00005
-2020030d
-efea0006
-67ea4c12
-20400407
-20348034
-6fe24c17
-247a0000
-1fe0fe01
-67e24c17
-202048f0
-6ff04c6c
-c4028000
-704c8808
-704c870c
-20400303
-58000000
-e7e20005
-6fe20639
-e7e40005
-6fea4c12
-e7ea0005
-2020030d
-20200040
-da204140
-2040604d
-18007e05
-2040528d
-6fe80779
-e7e80005
-d84006af
-204052d0
-20406142
-204052e7
-20208011
-7006b101
-c5108017
-6fe20b9c
-207a0000
-70007c0b
-c5108017
-6fe24293
-207a0000
-204052e7
-24208017
-20600000
-c6908000
-793f8021
-20200152
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-da201001
-68420048
-20407a08
-6fe20048
-c283872f
-c0188021
-c0060731
-c0038030
-c005800b
-20204f6c
-6fe20b9c
-203a0011
-204052e7
-2040d2da
-2440d2d6
-20200012
-204052da
-204052f6
-18007e11
-2040528d
-d8c00749
-204070de
-6842004c
-18410401
-6fe20048
-1fe3fe00
-c590801e
-7d34fe00
-202052ab
-7934fe00
-9842fe00
-202052ab
-6fe20030
-79207e04
-67e20030
-1c427e00
-67e806c2
-6fe206ab
-c281802e
-79207e03
-67e206ab
-18007e01
-2040528d
-204052a6
-2020017f
-70004800
-20600000
-18007e02
-2040528d
-6fe206a4
-e7e20005
-204052a6
-20200154
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe204db
-684c4639
-c2838005
-20200006
-684c4c7a
-6fec04e3
-98467c00
-24628000
-2040493a
-202006fb
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-20404b82
-204024ce
-1fe67c0f
-24210006
-202024b9
-70416f01
-202024b9
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8a00
-24348004
-704c8a01
-704c8808
-704c8712
-20400303
-18007e35
-e7e20005
-6fec0040
-e7ec0005
-6fe24c8a
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8808
-704c8712
-20400303
-18007e00
-e7e20005
-6fec0040
-e7ec0005
-6fe24c8a
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe20030
-c4008000
-793ffe01
-67e20030
-6fe4415f
-67e4003e
-7855fc00
-704c8a00
-2020072d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-c5958006
-1c40a200
-20348009
-1d00a200
-20200009
-1c40a203
-20348009
-1d00a203
-68440032
-1a227e00
-793ffe1b
-9846fc00
-6fe40075
-204071c9
-18072600
-9a667e00
-20210013
-9840fe00
-9a20fe00
-67e80034
-7046cf00
-6fe20030
-79207e01
-67e20030
-6fe20073
-67e20092
-58000000
-67e64208
-67e6420b
-67e241f8
-6fe44161
-67e4003e
-24348023
-18808fff
-704c8a02
-2020072d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-204033cc
-24228010
-6fe242a7
-c001b3e2
-c004b3e8
-c00533f4
-c005b3fa
-c0063404
-c0043446
-c00c33da
-c003b3d4
-c00cb3d8
-c00d345d
-c0093422
-c0098018
-204033d0
-247a0000
-6fe242a7
-c006801a
-c00e8016
-202033bf
-70007c37
-202033ca
-70007c18
-202033ca
-6fe2004b
-79207e01
-67e2004b
-6fe20030
-c283b413
-20400235
-202033ca
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-2040554f
-20400012
-df200020
-d8c08080
-18c20a00
-efe20006
-c001800e
-c002000e
-c002800e
-c003800e
-c016000e
-c016800e
-c0800010
-58000080
-e7e20005
-c2000005
-20600000
-df200008
-d8c0812a
-20200005
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-20400008
-6fe20b97
-207a0000
-700b9700
-6fe20b95
-c004800f
-20206472
-6fe20b98
-207a0000
-700b9800
-6fe20b96
-c009001f
-c004800f
-20206481
-204063ce
-704c8807
-704c8736
-20400303
-58000000
-e7e20005
-6fec0040
-e7ec0005
-2020030d
-202052d6
-700b960f
-204052da
-204052f2
-2020e406
-20206410
-20600000
-700b9801
-700b9613
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-7854fc00
-78287c00
-20404735
-2040460a
-204046ad
-2436c91c
-6fe20003
-1fe0fe01
-67e20003
-6fe204db
-1fe17e0f
-c001800e
-2020491b
-d8400004
-6fe2461c
-7d3a0406
-60424536
-684244ff
-1840fe06
-67e24537
-18427200
-6fe2461c
-205a0448
-245a044a
-604c4538
-d8c04500
-2040713a
-2020468c
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-20400006
-20400004
-20203e60
-d8e00009
-20207357
-70442901
-20758000
-70442900
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-700fd600
-71f0001c
-70804205
-20400032
-6fe28341
-67e24bce
-6fe24bef
-67e206ab
-24558038
-20407988
-2040001c
-580005bf
-67e4431d
-58000142
-67e4431f
-58000141
-67e4431b
-580006b0
-67e44315
-580006b3
-67e44313
-2055802e
-24358020
-20403e79
-204057bf
-700f0d66
-20203f28
-58000000
-da204f65
-d8400040
-202056bd
-6fec4140
-67ec4340
-70801002
-204057bf
-6fe24bce
-c282802b
-700f0d65
-20403f28
-58001171
-67e44f5d
-2020072b
-20400143
-700f0d6a
-20203f28
-204054b0
-204054b5
-200007d0
-2020553b
-6848833e
-6048804c
-70804de6
-2040013b
-70800520
-2020013b
-58000034
-da204be7
-d8400008
-202056bd
-00000000
-00000000
-00000000
-00000000
-20200040
-793f801c
-704c8801
-704c8701
-20400303
-58000000
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24ca1
-c0008010
-20400015
-704c880a
-704c8704
-20400303
-6fec0040
-e7ec0005
-6fe60146
-e7e60005
-58000001
-e7e20005
-6fec0040
-67ec4f37
-2020030d
-6fec4f37
-684c0040
-98467c00
-20228003
-20600000
-704ca101
-704c9b00
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe2007d
-c0060009
-c00b8010
-c0058013
-c0198729
-c017001d
-c0208025
-20204ba4
-da200040
-2040604d
-6fe80739
-68480779
-98467c00
-2022821e
-20204d8b
-6fe44de9
-c3014e10
-20204def
-20404d6f
-67e206af
-20404f51
-70007c0c
-6fe24293
-247a0000
-6fe20030
-c3830000
-20404d80
-20200235
-6fe24170
-1fe0fe01
-68420739
-98467c00
-24210029
-60424170
-20404d51
-2020002b
-6fe20b96
-c0058027
-70007c03
-20204eb4
-70007c04
-20600000
-704c8803
-704c871b
-20400303
-6fe20046
-e7e40005
-6fe24170
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-da201000
-68440738
-20407a08
-6fe2007d
-c001800e
-c0020020
-c0088014
-c0138033
-c014003b
-c0038037
-c0040610
-c00101b1
-20200727
-6fe20739
-67e206a3
-c0088012
-20204cad
-20404d0a
-20200016
-20404e14
-20200016
-704c8804
-704c8708
-20400303
-58000000
-e7e20005
-68420046
-e0440005
-58000001
-e7e20005
-2020030d
-6fe20739
-67e206a3
-c0058024
-20204cc0
-6fe24132
-c087cd22
-6fe24293
-207a0000
-68420055
-70005500
-70429300
-6fe2073a
-c1830000
-60420055
-700b9b01
-2040061a
-6fe24c97
-203a023b
-20600000
-20404dc7
-6ff00739
-67f04e1a
-20600000
-6fe20739
-67e206a4
-20400154
-20204d51
-20404edd
-20200034
-00000000
-00000000
-00000000
-20200040
-6fe64d31
-245a000e
-58000000
-67e64d31
-dfe04d5c
-67e40f12
-6a240f12
-20400551
-207a0000
-6a240f12
-20403fa5
-20400581
-20200007
-1fe22400
-20200581
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-68464dd8
-2040025b
-20400258
-c0008007
-c0010012
-20202baf
-20400249
-67e44c94
-d84003ff
-98410400
-60444c18
-1feb7e00
-1fecfe00
-67e24c1a
-20400258
-67e24c1b
-20200725
-20400249
-67e242a8
-20400034
-20400249
-67e40f12
-20402284
-24628000
-1a208c01
-efe20006
-c280002c
-6fe40f12
-67e44db1
-20400595
-205a723a
-6fe40f12
-1fe22200
-1fe22400
-20404185
-1a420a00
-6fe40f12
-e7e40005
-e0220005
-6fe40f12
-1fe27200
-2040025d
-2020712d
-6fe40f12
-2040003a
-247a0000
-6fe40f12
-1fe22200
-1fe22400
-204049ab
-20200028
-1fecfe00
-1ff1fe00
-18000201
-c1008000
-18000202
-20600000
-204005a3
-203a729b
-2020729d
-00000000
-00000000
-00000000
-20200040
-dfe00020
-da204f3d
-d8400020
-204056bd
-d8c04f3d
-efe40006
-207a0000
-67e44f5f
-2040000d
-20400011
-2040000d
-2020001d
-da204f3f
-df200006
-704f6101
-20600000
-efe40011
-68444f5d
-9840fe00
-67e44f5d
-6fe24f61
-9a20a200
-1a20a202
-6fe24f61
-1fe0fe01
-67e24f61
-c2000011
-20600000
-efe40011
-68444f5d
-9842fe00
-67e44f5d
-6fe24f61
-9a20a200
-1a20a202
-6fe24f61
-1fe0fe01
-67e24f61
-c200001d
-6fe44f5d
-68444f5f
-98467c00
-2422abaf
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe20739
-79207e07
-67e2007d
-c0418009
-c042000e
-c04c8010
-c04d0013
-20204c5a
-20404c9e
-6fe4073a
-6ff0073c
-67f04e22
-20600000
-20404ca0
-2020000a
-20404c78
-20400019
-20200626
-20400019
-20404c78
-20404c7c
-700b9801
-700b9603
-20600000
-704c8809
-704c8732
-20400303
-6fec0040
-e7ec0005
-6fe647d3
-e7e60005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6ff04c6c
-c4010000
-704c880a
-704c873e
-20400303
-58000003
-e7e40005
-6fe20639
-e7e40005
-6fec4530
-e7ec0005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6ff04c6c
-c4000000
-704c8813
-704c873e
-20400303
-58000001
-e7e40005
-6fe20639
-e7e40005
-204002c2
-e0420005
-6fe24626
-e7e20005
-6fec0633
-e7ec0005
-6fe40625
-1feb7e00
-e7e40005
-6fe80650
-e7e80005
-6fe2065b
-e7e20005
-6fe20639
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8817
-704c8718
-20400303
-6fec0040
-e7ec0005
-d8c04297
-18007210
-2040712d
-18007e00
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe20048
-c0420005
-c0418008
-20204f9d
-68424c97
-604206a9
-20205046
-68424c97
-604206a9
-202050ba
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c9c
-c0810006
-204020dc
-246c0000
-c6000000
-684c0149
-20402289
-20628000
-204001a2
-20400303
-58000001
-e7e20005
-6fec0149
-e7ec0005
-6fe20144
-1fe20400
-1fe97e00
-1fe97e00
-e7e20005
-58000000
-e7e20005
-6fe24c9c
-c0800020
-58000000
-e7e20005
-6fe60146
-e7e60005
-6fe80132
-9c467e00
-e7e40005
-2020030d
-6fe60146
-e7e60005
-6fe80132
-9c467e00
-e7e40005
-6fe20018
-2040018d
-e7e20005
-6fe24c9c
-c001002b
-2020030d
-6fe64d2e
-1fe20c00
-efe20006
-efe40006
-207a0000
-1fe20400
-1fe27200
-2040712d
-184672f0
-20407100
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0090005
-c011001a
-20200295
-6fe24ded
-203a0297
-20400252
-67ee4e0a
-2040000e
-6fe24ded
-1fe0ffff
-67e24ded
-20200299
-20400269
-243a0297
-1a420a00
-1a40a407
-1a420c00
-efee0006
-e7ee0005
-c2000010
-58000000
-18a08bf9
-e7ee0005
-20600000
-20400249
-67e4495f
-20400249
-67e44961
-20400024
-df200003
-2040029d
-6fe20639
-e7e40005
-2020030d
-da400014
-da200009
-d8200003
-204049ab
-58000015
-e7e20005
-6ff0495b
-e7f00005
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8806
-704c8714
-20400303
-6fe24c89
-e7e20005
-6fe20046
-e7e40005
-6fe24c8a
-e7e20005
-203a000e
-6fe40032
-1fe37e00
-2020000f
-58000000
-e7e40005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8804
-704c8705
-20400303
-58000000
-e7e20005
-6fe24e18
-e7e40005
-6fe206a4
-e7e20005
-6fe2004c
-793ffe05
-67e2004c
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c8807
-704c8720
-20400303
-6fec0040
-e7ec0005
-6fe24ca0
-e7e20005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-704c880b
-704c8703
-20400303
-6fe24c8a
-e7e20005
-6fe20046
-e7e40005
-6fec0040
-e7ec0005
-18007e01
-e7e20005
-18007e00
-6842004c
-284ffe02
-7920fe00
-e7e20005
-6fe20046
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c1a
-c000800b
-c001000f
-c001800c
-c002000d
-c0028010
-c0030011
-c004000e
-c01f8012
-20200295
-2020071b
-2020071d
-2020071f
-20200721
-20200723
-20200295
-20200295
-6fe24c18
-c0008019
-c00b801d
-c010001f
-c0518024
-c0300034
-20200295
-2040024f
-67ec4c8d
-20400265
-20200299
-704e193f
-20200299
-df200002
-204002a2
-58000000
-e7e40005
-2020030d
-20400249
-68420046
-98467c00
-2022802b
-68420639
-98467c00
-24628000
-604242a8
-df200003
-204002a2
-6fe242a8
-e7e40005
-6fe20018
-2040018d
-e7e20005
-2020030d
-df200002
-204002a2
-6fe44f35
-e7e40005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe64d2e
-245a000f
-58000000
-67e64d2e
-dfe04d34
-67e40f12
-20200008
-6a240f12
-20400551
-207a0000
-6a240f12
-20403fa5
-20400581
-20200008
-1fe22400
-20200581
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24f34
-243a0719
-704f3401
-20400023
-6f224cd2
-6a444dd3
-6fe44dd5
-67e40f12
-58004cca
-67e40f16
-2040001d
-6fe24cd2
-1feff203
-d8c04cd4
-d8a04d10
-2040712d
-6f224caa
-6a444dcf
-6fe44dd1
-67e40f12
-58004ca2
-67e40f16
-2040001d
-6fe24caa
-1feff203
-d8c04cac
-d8a04cf2
-2020712d
-6a240f16
-20403f94
-6fe40f12
-9a40a400
-c200001d
-20600000
-58004ca2
-2040002c
-58004cca
-2040002c
-58004d34
-2040002c
-58004d5c
-2040002c
-58004d84
-1fe20a00
-1fe0a208
-1fe0fe0a
-e7e40005
-e7e40005
-e7e40005
-e8420011
-184f8403
-9840fe00
-e7e40005
-18a08a01
-58000000
-e7e20005
-18427200
-20207100
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c005001a
-c007001d
-c00983c8
-c00b000f
-c00b8019
-c00c0019
-c00c8019
-c00d0019
-c00d8019
-c0078020
-c0080025
-c0088029
-20200717
-20400249
-204002a9
-da200009
-d8200003
-204049ab
-58000008
-e7e20005
-6ff04ddf
-e7f00005
-20600000
-20200295
-20400258
-67e244de
-20200299
-7044d900
-704c8b00
-20200299
-df200002
-2040029d
-58000004
-e7e20005
-2020030d
-704ded00
-704e0a00
-704dee00
-20200299
-68424ded
-18467c04
-20228297
-20400252
-67ee4e0a
-20400030
-20200299
-6fe24ded
-d8a04dee
-1feffe07
-98a08a00
-6fee4e0a
-e7ee0005
-6fe24ded
-1fe0fe01
-67e24ded
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0040008
-c004800d
-c0058012
-c0060025
-c0068029
-20200715
-20400258
-67e244df
-1fe27200
-20400246
-20200299
-20400258
-67e244ff
-1fe27200
-20400246
-20200299
-6fe244d9
-243a0297
-20400258
-67e24636
-20400249
-67e444da
-20400249
-67e444dc
-20400258
-67e24637
-20400258
-67e24e11
-6fe444da
-684444dc
-98467c00
-24228299
-1fe3fe00
-67e444da
-20200299
-20400258
-67e244d9
-20400258
-20200299
-20400249
-67e444da
-20400249
-67e444dc
-20400258
-67e24e11
-98267c00
-20428260
-20400258
-67e24626
-2040024f
-67ec4627
-20400258
-67e2462d
-20400249
-1febfe00
-67e444d7
-20400249
-20400249
-67e44632
-20400249
-67e44634
-20200262
-20200040
-6fe24c18
-c001800a
-c01b8015
-c029001e
-c02a8024
-c02b0029
-c036002d
-c0368032
-20200295
-20400299
-5800003f
-67f04c6c
-5fffffff
-67f04c1c
-58000000
-67ec4c7a
-67e244de
-67e244d9
-67e24133
-20200265
-204001e1
-20400249
-67e40051
-df200003
-2040029d
-6fe20046
-e7e40005
-7042a71d
-2020030d
-20400258
-67e24c98
-df200064
-d8a00183
-20400246
-20200299
-df200002
-2040029d
-6fe24c97
-e7e20005
-2020030d
-20400258
-67e24c97
-203a0293
-20200299
-df200003
-2040029d
-6fe44de7
-e7e40005
-2020030d
-20400249
-67e44de7
-20200299
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0158005
-c0160015
-20200295
-2040024f
-67ec42a9
-2040024c
-67e647ce
-df200007
-2040029d
-6fec0040
-e7ec0005
-2040030d
-6fe24c9f
-c0008012
-7042a716
-20600000
-204033e5
-700b9b01
-20600000
-2040024f
-67ec42a9
-2040001d
-df200007
-2040029d
-6fec0040
-e7ec0005
-2020030d
-700b950a
-700b9701
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c00c8007
-c00e0018
-c00e8020
-c00d802b
-20200713
-704fa601
-2040024f
-67ec42a9
-20400249
-67e200b6
-20400249
-9c40fe00
-1fe17ffc
-67e800b7
-df200008
-d8a04fa7
-204070e4
-20402287
-20228016
-704fa602
-7042a703
-202002a9
-6fe24c9b
-c08102ad
-20400249
-203a02ad
-20400258
-67e206a7
-7042a715
-202002a9
-20400249
-67e242a8
-20402284
-242282ad
-1a208c01
-efe20006
-c2800029
-204002a9
-20203420
-204002a9
-202048f0
-6fe24c9b
-c08102ad
-20400249
-67e242a8
-203a02ad
-204002a9
-6ff04e1a
-243a0035
-7042a704
-20600000
-704c880b
-704c870b
-20400303
-58000000
-e7e20005
-6fe20046
-e7e40005
-6ff04e1a
-e7f00005
-2020030d
-00000000
-20200040
-6fe24c18
-c0058009
-c0060011
-c0068019
-c0070022
-c008802a
-c009802e
-20200711
-2040024f
-67ec42a9
-d8a04297
-18007210
-20400246
-70429301
-7042a70b
-20200025
-2040024f
-67ec42a9
-7042a70c
-20400025
-2040061a
-6fe24c97
-203a023b
-20600000
-2040024f
-67ec42a9
-20400258
-67e247f1
-98007200
-d8a047f2
-20400246
-7042a709
-20200025
-2040024f
-67ec42a9
-7042a70a
-df200007
-2040029d
-6fec0040
-e7ec0005
-2020030d
-20400249
-67e242a8
-7042a70d
-202002a9
-20400249
-67e242a8
-20400258
-1fe0fe0e
-67e242a7
-202002a9
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0030006
-c004001c
-c005002f
-2020070f
-20400249
-67e242a8
-20400258
-67e206a4
-20402284
-242282ad
-1a208c01
-efe20006
-c2800018
-7042a706
-6fe242a8
-6842439b
-98467c00
-242282a9
-7042a711
-6fe2439a
-67e242a8
-202002a9
-6fe206a4
-67e20f12
-20404894
-202002a9
-2040024f
-67ec42a9
-7042a71a
-6fe24c9b
-c0008025
-c0010023
-20200029
-704c960b
-2020002a
-704c9600
-2040002a
-704c8a02
-20200184
-704c9602
-df200007
-2040029e
-6fec42a9
-e7ec0005
-2020030d
-6fe24ca1
-c00002ad
-c00102ab
-6fe24c9b
-c00102ab
-704ca102
-2040024f
-67ec42a9
-20400258
-67e24c8a
-7042a708
-204002a9
-20200184
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c00e000f
-c00e8014
-c00f001b
-c0118020
-c0120025
-c0210028
-c0218029
-c022002b
-c0228030
-c0230033
-c0238034
-c0288036
-2020070d
-20400249
-67e44153
-20400249
-67e44151
-20200299
-df200005
-2040029d
-6fe4414f
-e7e40005
-6fe4414d
-e7e40005
-2020030d
-20400249
-67e4414f
-20400249
-67e4414d
-20200299
-df200004
-2040029d
-6fe6414a
-e7e60005
-2020030d
-2040024c
-67e6414a
-20200299
-20200295
-20400258
-20200295
-df200002
-2040029d
-6fe24c9c
-e7e20005
-2020030d
-20400258
-67e24c9c
-20200299
-20200295
-20400258
-20200295
-df2000f2
-2040029d
-6fe24c98
-e7e20005
-d8c00183
-df200064
-2040713a
-2020030d
-00000000
-00000000
-20200040
-6fe24c18
-c0070005
-c007800a
-20200295
-df200003
-2040029d
-6fe44de9
-e7e40005
-2020030d
-20400249
-67e44de9
-20200299
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0018008
-c002001c
-c0058022
-c006002d
-c0068035
-2020070b
-6fe44deb
-c30102ab
-6fe44de9
-c30102ab
-6fe24c9b
-c08102ad
-20400249
-67e40253
-20400249
-67e40255
-20400249
-67e40257
-58000040
-67e4430b
-20400249
-67e4430d
-20400249
-67e4430f
-7042a712
-202002a9
-20400249
-67e40253
-6fe20031
-c30302ab
-7042a713
-202002a9
-6fe24c9b
-c08102ad
-6fe44deb
-c30002ab
-6fe44de9
-c30002ab
-2040024f
-67ec42a9
-20400258
-7042a718
-202002a9
-204001e1
-df200005
-2040029d
-6fe20046
-e7e40005
-6fe44deb
-e7e40005
-2020030d
-204001e1
-20400249
-67e44deb
-df200003
-2040029d
-6fe20046
-e7e40005
-2020030d
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0008008
-c001000b
-c0018010
-c0028015
-c003001a
-20200709
-20400255
-67f04c6c
-20200299
-df200004
-2040029d
-580400fb
-e7e60005
-2020030d
-df200009
-2040029d
-6ff04ddf
-e7f00005
-2020030d
-6fe244de
-243a0297
-2040024f
-67ec4c7a
-20200299
-6fe244de
-243a0297
-20400249
-67e44617
-20400249
-67e44619
-20400258
-2040002d
-6042461b
-20400258
-205a0035
-245a0039
-20400258
-2040024f
-20400258
-67e24624
-20400258
-67e24e11
-20200299
-d8400000
-c1000000
-d8400002
-c1018000
-d8400006
-c1010000
-d8400001
-20600000
-684c4c8d
-604c4639
-70461c00
-20600000
-70461c01
-20600000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0008009
-c001000e
-c0018014
-c002001e
-c002801e
-c0048019
-20200295
-df200009
-2040029d
-6ff04c24
-e7f00005
-2020030d
-df200041
-2040029d
-d8c04c2c
-df200040
-2040713a
-2020030d
-df200009
-2040029d
-6ff04138
-e7f00005
-2020030d
-df200007
-2040029d
-6fec4140
-e7ec0005
-2020030d
-df200008
-2040029d
-580002a8
-e7e40005
-5800003c
-e7e20005
-58000008
-e7e40005
-e7e40005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c000800b
-c009800e
-c00a0018
-c00b8020
-c00c0025
-c00c8028
-c00d002d
-c00d8030
-20200707
-20400255
-67f04c1c
-20200299
-2040025d
-d8a0468a
-df200042
-2040713a
-df200042
-d8c0468a
-d8400000
-20400161
-60424689
-20200299
-df2000f9
-2040029d
-d8c0468a
-df200040
-2040713c
-df200017
-204070e4
-2020030d
-df200003
-2040029d
-6fe44159
-e7e40005
-2020030d
-20400249
-67e44159
-20200299
-df200002
-2040029d
-6fe24133
-e7e20005
-2020030d
-20400258
-67e24133
-20200299
-df200005
-2040029d
-6fe44153
-e7e40005
-6fe44151
-e7e40005
-2020030d
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-20200040
-6fe24c18
-c0008007
-c0010017
-c0028019
-c0048025
-20200705
-7920001c
-2040024c
-67e64147
-20400258
-d8400800
-984ffe00
-d840ffff
-98467c00
-24210011
-18427e00
-18000e02
-20407141
-20400258
-67e24c99
-67e24c9a
-202002a9
-7042a702
-20200299
-2040024f
-67ec42a9
-20400249
-67e40251
-20400249
-67e200b6
-20400249
-20400258
-67e24ad0
-704c9b01
-7042a705
-202002a9
-6fe24ca1
-c00002ad
-c00102ab
-6fe24c9b
-c00102ab
-2040024f
-67ec42a9
-7042a707
-20400258
-c00082a9
-7042a719
-204002a9
-20204d51
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
-00000000
Index: ModuleDemo/25_OTA
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA	(revision 4633)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/25_OTA	(nonexistent)

Property changes on: ModuleDemo/25_OTA
___________________________________________________________________
Deleted: svn:mergeinfo
## -0,3 +0,0 ##
   Reverse-merged /YC1121E/Soft/ModuleDemo/24_TWS:r926
   Reverse-merged /YC1121E/SoftCode/1121EB/branch/HSC_Airpods_pro/ModuleDemo/25_OTA:r2410
   Reverse-merged /YC1121E/SoftCode/1121EB/branch/ods_AirDots3/ModuleDemo/25_OTA:r2186
Index: ModuleDemo/BLE/BT/a-l.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/a-l.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/a-l.bat	(working copy)
@@ -0,0 +1,28 @@
+
+e pu
+::e 8097   040307020506  
+:: enable flash vcc
+e 809a 3f
+:: set flash io port
+e 8090 060502
+e 8094 070304
+:: clear flash first
+e fe 0
+:: sometimes in lpm will power off qspi
+e pu
+e fa
+:: make sure flash ok
+e fr 0 30
+e fe 0
+:: clear store info
+e fe 7f000
+:: close wdt
+e 8043 00
+::e fw 3 a5
+e fp output/flash.dat 1000
+::e fp output/flash.dat 20000 
+e fw 4 a5
+:: make sure flash offset write after the file download, becouse in rom code, will check crc, if download failed in middle time, it will occur error.
+e fw 0 031000
+::e fw 0 030002
+e k
Index: ModuleDemo/BLE/BT/a.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/a.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/a.bat	(working copy)
@@ -0,0 +1,28 @@
+
+e pu
+::e 8097   040307020506  
+:: enable flash vcc
+e 809a 3f
+:: set flash io port
+e 8090 060502
+e 8094 070304
+:: clear flash first
+e fe 0
+:: sometimes in lpm will power off qspi
+e pu
+e fa
+:: make sure flash ok
+e fr 0 30
+e fe 0
+:: clear store info
+e fe 7f000
+:: close wdt
+e 8043 00
+::e fw 3 a5
+e fp output/flash.dat 1000
+::e fp output/flash.dat 20000 
+e fw 4 a5
+:: make sure flash offset write after the file download, becouse in rom code, will check crc, if download failed in middle time, it will occur error.
+::e fw 0 030002
+e fw 0 031000
+e k
Index: ModuleDemo/BLE/BT/do.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do.bat	(working copy)
@@ -0,0 +1,264 @@
+
+@set FPGA_PATH=fpgajic\fpga
+@set YC_PATCH_FILE=yc_patch_yc1121.h
+@set enc=1
+@set enckey=0000000000000000
+@echo off
+
+::get Rom path
+set now_path=%~dp0
+call:getstrlocation %now_path% ModuleDemo location
+call:get_fix_len_str  %now_path% location soft_path
+set lib_path=%soft_path%Librarier
+set rom_path=%lib_path%\bt_rom
+set program=%rom_path%\program
+set format=%rom_path%\format
+set util=%rom_path%\util
+set patch_path=%now_path%patch
+set sched=%now_path%sched
+set output=%now_path%output
+set voice_prompt=%now_path%voice_prompt
+
+rem @echo rom_path=%rom_path%
+rem @echo program_path=%program%
+rem @echo format_path=%format%
+rem @echo util_path=%util%
+rem @echo patch_path=%patch_path%
+
+
+set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
+copy %program%\bt.prog + %progs% + %patch_path%\z.prog output\bt_program23.meta > nul
+set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
+copy %format%\bt.format + %fmts% + %format%\command.format  output\bt_format.meta > nul
+
+perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
+perl %util%/memalloc.pl 				output/bt_format.meta
+perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
+cd output
+osiuasm bt_program23 -O-W
+copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
+
+
+if "%1" equ "eep" (
+	goto genromrevc
+)else (
+  goto downloadram
+)
+
+:genromrevc
+echo off
+@echo Start to generate EEPROM code
+
+if exist "..\..\CM0\Prj\Output\out.rom" (
+	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
+) else (
+	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
+)
+
+::%util%/geneep  -n -z 
+@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
+%util%/geneep -f -n -z  
+
+perl %util%\flash2bin.pl
+
+::perl %util%\svnversion.pl %output%
+::perl %util%\getcodesize.pl %output%
+::perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
+::perl %util%\vp2.pl %voice_prompt% %output%
+::perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
+::perl %util%\add_ota_pcm.pl %output%/flash_add_coef.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
+
+::copy %output%\flash.dat  ..\..\..\..\24_TWS\bt_demo\BT\output\ota.dat
+copy sched.rom  	..\..\CM0\respin
+copy memmap.format  ..\..\CM0\respin
+copy ramcode.rom  ..\..\CM0\respin
+copy zcode.rom  ..\..\CM0\respin
+
+:gen_eep_end
+cd ..
+echo **********************************
+@rem echo flash.dat Generated.
+echo **********************************
+goto end
+
+
+
+:genrom
+@rem echo on
+perl ..\util\rom2mif.pl romcode
+del ..\..\%FPGA_PATH%\romcode.mif
+copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
+perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
+cd ..\..\%FPGA_PATH%
+quartus_cdb btspi -c btspi --update_mif
+quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
+quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
+@echo bitstream_compression=on >1
+@echo memory_map_file=on >> 1
+quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
+@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
+@del 1
+goto end
+
+
+
+:downloadram
+echo on
+@echo Start to download ram code
+e ku
+e hu
+e su sched.rom
+@echo **********************************
+@echo RAM CODE has been downloaded. 
+@echo **********************************
+cd ..
+
+
+:end
+goto:eof
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlocation-------
+::------------------------------------------
+:getstrlocation
+setlocal
+set "bstr=%1"
+set "cstr=%2"
+set %3=0
+set "num=0"
+set "len_bstr=0"
+set "len_cstr=0"
+
+call:getstrlen %bstr% len_bstr
+call:getstrlen %cstr% len_cstr
+
+:getstrlocation_next
+set /a len_remain=len_bstr-num
+if %len_remain% lss %len_cstr% (
+echo "cann't get str location"
+set /a num =0
+goto getstrlocation_last
+)
+
+call:get_fix_len_str %bstr%  len_cstr compar_str
+
+if not %compar_str%==%cstr% (
+set /a num+=1
+set "bstr=%bstr:~1%"
+goto getstrlocation_next
+)
+
+:getstrlocation_last
+(endlocal
+	set %3=%num%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+::------------------------------------------
+::---------------func:get_fix_len_str-------
+::------------------------------------------
+:get_fix_len_str
+setlocal
+set "getstr=%NULL%"
+set str=%1
+set /a len=%2
+set num=0
+:get_fix_len_str_loop
+set getstr=%getstr%%str:~0,1%
+set /a num+=1
+set str=%str:~1%
+if %num% lss %len% goto get_fix_len_str_loop
+(endlocal
+ set %3=%getstr%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlen-------------
+::------------------------------------------
+:getstrlen
+setlocal
+set str=%1
+set %2=0
+set /a "num=0"
+
+:getstrlen_next
+if "%str%"=="" goto getstrlen_last
+
+if not "%str%"=="" (
+set /a num+=1 
+set "str=%str:~1%"
+goto getstrlen_next
+)
+
+:getstrlen_last
+(endlocal
+	set /a "%2=%num%"
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getcharlocation-------
+::------------------------------------------
+:getcharlocation
+setlocal
+set "str=%1"
+set "ch=%2"
+set %3=0
+set /a "num=0"
+
+:getcharnext
+if "%str%"=="" ( 
+set /a num=0
+goto getcharlast
+)
+
+if not "%str%"=="" (
+set /a num+=1
+if "%str:~0,1%"=="%ch%" goto getcharlast
+set "str=%str:~1%"
+goto getcharnext
+)
+:getcharlast
+(endlocal
+set %3=%num%
+)
+goto:eof 
+::---------------end:func-------------------
+
+
+
+
+
+
Index: ModuleDemo/BLE/BT/do1.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do1.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do1.bat	(working copy)
@@ -0,0 +1,257 @@
+
+@set FPGA_PATH=fpgajic\fpga
+@set YC_PATCH_FILE=yc_patch_yc1121.h
+@set enc=1
+@set enckey=0000000000000000
+@echo off
+
+::get Rom path
+set now_path=%~dp0
+call:getstrlocation %now_path% ModuleDemo location
+call:get_fix_len_str  %now_path% location soft_path
+set lib_path=%soft_path%Librarier
+set rom_path=%lib_path%\bt_rom
+set program=%rom_path%\program
+set format=%rom_path%\format
+set util=%rom_path%\util
+set patch_path=%now_path%patch
+set sched=%now_path%sched
+set output=%now_path%output
+set voice_prompt=%now_path%voice_prompt
+
+rem @echo rom_path=%rom_path%
+rem @echo program_path=%program%
+rem @echo format_path=%format%
+rem @echo util_path=%util%
+rem @echo patch_path=%patch_path%
+
+
+set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
+copy %program%\bt.prog + %progs%  output\bt_program23.meta > nul
+set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
+copy %format%\bt.format + %fmts% + %format%\command.format  output\bt_format.meta > nul
+
+perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
+perl %util%/memalloc.pl 				output/bt_format.meta
+perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
+cd output
+osiuasm bt_program23 -O-W
+copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
+
+
+
+if "%1" equ "eep" (
+	goto genromrevc
+)else (
+  goto downloadram
+)
+
+:genromrevc
+echo off
+@echo Start to generate EEPROM code
+
+if exist "..\..\CM0\Prj\Output\out.rom" (
+	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
+) else (
+	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
+)
+
+%util%/geneep  -n  
+@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
+%util%/geneep -f -n   
+
+perl %util%\svnversion.pl %output%
+perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
+perl %util%\vp2.pl %voice_prompt% %output%
+perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
+perl %util%\getcodesize.pl %output%
+perl %util%\add_ota_pcm.pl %output%/ota.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
+
+:gen_eep_end
+cd ..
+echo **********************************
+@rem echo flash.dat Generated.
+echo **********************************
+goto end
+
+
+
+:genrom
+@rem echo on
+perl ..\util\rom2mif.pl romcode
+del ..\..\%FPGA_PATH%\romcode.mif
+copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
+perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
+cd ..\..\%FPGA_PATH%
+quartus_cdb btspi -c btspi --update_mif
+quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
+quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
+@echo bitstream_compression=on >1
+@echo memory_map_file=on >> 1
+quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
+@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
+@del 1
+goto end
+
+
+
+:downloadram
+echo on
+@echo Start to download ram code
+e ku
+e hu
+e su sched.rom
+@echo **********************************
+@echo RAM CODE has been downloaded. 
+@echo **********************************
+cd ..
+
+
+:end
+goto:eof
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlocation-------
+::------------------------------------------
+:getstrlocation
+setlocal
+set "bstr=%1"
+set "cstr=%2"
+set %3=0
+set "num=0"
+set "len_bstr=0"
+set "len_cstr=0"
+
+call:getstrlen %bstr% len_bstr
+call:getstrlen %cstr% len_cstr
+
+:getstrlocation_next
+set /a len_remain=len_bstr-num
+if %len_remain% lss %len_cstr% (
+echo "cann't get str location"
+set /a num =0
+goto getstrlocation_last
+)
+
+call:get_fix_len_str %bstr%  len_cstr compar_str
+
+if not %compar_str%==%cstr% (
+set /a num+=1
+set "bstr=%bstr:~1%"
+goto getstrlocation_next
+)
+
+:getstrlocation_last
+(endlocal
+	set %3=%num%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+::------------------------------------------
+::---------------func:get_fix_len_str-------
+::------------------------------------------
+:get_fix_len_str
+setlocal
+set "getstr=%NULL%"
+set str=%1
+set /a len=%2
+set num=0
+:get_fix_len_str_loop
+set getstr=%getstr%%str:~0,1%
+set /a num+=1
+set str=%str:~1%
+if %num% lss %len% goto get_fix_len_str_loop
+(endlocal
+ set %3=%getstr%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlen-------------
+::------------------------------------------
+:getstrlen
+setlocal
+set str=%1
+set %2=0
+set /a "num=0"
+
+:getstrlen_next
+if "%str%"=="" goto getstrlen_last
+
+if not "%str%"=="" (
+set /a num+=1 
+set "str=%str:~1%"
+goto getstrlen_next
+)
+
+:getstrlen_last
+(endlocal
+	set /a "%2=%num%"
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getcharlocation-------
+::------------------------------------------
+:getcharlocation
+setlocal
+set "str=%1"
+set "ch=%2"
+set %3=0
+set /a "num=0"
+
+:getcharnext
+if "%str%"=="" ( 
+set /a num=0
+goto getcharlast
+)
+
+if not "%str%"=="" (
+set /a num+=1
+if "%str:~0,1%"=="%ch%" goto getcharlast
+set "str=%str:~1%"
+goto getcharnext
+)
+:getcharlast
+(endlocal
+set %3=%num%
+)
+goto:eof 
+::---------------end:func-------------------
+
+
+
+
+
+
Index: ModuleDemo/BLE/BT/do_old.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do_old.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do_old.bat	(working copy)
@@ -0,0 +1,260 @@
+
+@set FPGA_PATH=fpgajic\fpga
+@set YC_PATCH_FILE=yc_patch_yc1121.h
+@set enc=1
+@set enckey=0000000000000000
+@echo off
+
+::get Rom path
+set now_path=%~dp0
+call:getstrlocation %now_path% ModuleDemo location
+call:get_fix_len_str  %now_path% location soft_path
+set lib_path=%soft_path%Librarier
+set rom_path=%lib_path%\bt_rom
+set program=%rom_path%\program
+set format=%rom_path%\format
+set util=%rom_path%\util
+set patch_path=%now_path%patch
+set sched=%now_path%sched
+set output=%now_path%output
+set voice_prompt=%now_path%voice_prompt
+
+rem @echo rom_path=%rom_path%
+rem @echo program_path=%program%
+rem @echo format_path=%format%
+rem @echo util_path=%util%
+rem @echo patch_path=%patch_path%
+
+
+set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
+copy %program%\bt.prog + %progs% + %patch_path%\z.prog output\bt_program23.meta > nul
+set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
+copy %format%\bt.format + %fmts% + %format%\command.format  output\bt_format.meta > nul
+
+perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
+perl %util%/memalloc.pl 				output/bt_format.meta
+perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
+cd output
+osiuasm bt_program23 -O-W
+copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
+
+
+if "%1" equ "eep" (
+	goto genromrevc
+)else (
+  goto downloadram
+)
+
+:genromrevc
+echo off
+@echo Start to generate EEPROM code
+
+if exist "..\..\CM0\Prj\Output\out.rom" (
+	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
+) else (
+	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
+)
+
+%util%/geneep  -n -z 
+@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
+%util%/geneep -f -n -z  
+
+perl %util%\flash2bin.pl
+
+::perl %util%\svnversion.pl %output%
+::perl %util%\getcodesize.pl %output%
+::perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
+::perl %util%\vp2.pl %voice_prompt% %output%
+::perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
+::perl %util%\add_ota_pcm.pl %output%/flash_add_coef.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
+
+::copy %output%\flash.dat  ..\..\..\..\24_TWS\bt_demo\BT\output\ota.dat
+
+:gen_eep_end
+cd ..
+echo **********************************
+@rem echo flash.dat Generated.
+echo **********************************
+goto end
+
+
+
+:genrom
+@rem echo on
+perl ..\util\rom2mif.pl romcode
+del ..\..\%FPGA_PATH%\romcode.mif
+copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
+perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
+cd ..\..\%FPGA_PATH%
+quartus_cdb btspi -c btspi --update_mif
+quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
+quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
+@echo bitstream_compression=on >1
+@echo memory_map_file=on >> 1
+quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
+@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
+@del 1
+goto end
+
+
+
+:downloadram
+echo on
+@echo Start to download ram code
+e ku
+e hu
+e su sched.rom
+@echo **********************************
+@echo RAM CODE has been downloaded. 
+@echo **********************************
+cd ..
+
+
+:end
+goto:eof
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlocation-------
+::------------------------------------------
+:getstrlocation
+setlocal
+set "bstr=%1"
+set "cstr=%2"
+set %3=0
+set "num=0"
+set "len_bstr=0"
+set "len_cstr=0"
+
+call:getstrlen %bstr% len_bstr
+call:getstrlen %cstr% len_cstr
+
+:getstrlocation_next
+set /a len_remain=len_bstr-num
+if %len_remain% lss %len_cstr% (
+echo "cann't get str location"
+set /a num =0
+goto getstrlocation_last
+)
+
+call:get_fix_len_str %bstr%  len_cstr compar_str
+
+if not %compar_str%==%cstr% (
+set /a num+=1
+set "bstr=%bstr:~1%"
+goto getstrlocation_next
+)
+
+:getstrlocation_last
+(endlocal
+	set %3=%num%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+::------------------------------------------
+::---------------func:get_fix_len_str-------
+::------------------------------------------
+:get_fix_len_str
+setlocal
+set "getstr=%NULL%"
+set str=%1
+set /a len=%2
+set num=0
+:get_fix_len_str_loop
+set getstr=%getstr%%str:~0,1%
+set /a num+=1
+set str=%str:~1%
+if %num% lss %len% goto get_fix_len_str_loop
+(endlocal
+ set %3=%getstr%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlen-------------
+::------------------------------------------
+:getstrlen
+setlocal
+set str=%1
+set %2=0
+set /a "num=0"
+
+:getstrlen_next
+if "%str%"=="" goto getstrlen_last
+
+if not "%str%"=="" (
+set /a num+=1 
+set "str=%str:~1%"
+goto getstrlen_next
+)
+
+:getstrlen_last
+(endlocal
+	set /a "%2=%num%"
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getcharlocation-------
+::------------------------------------------
+:getcharlocation
+setlocal
+set "str=%1"
+set "ch=%2"
+set %3=0
+set /a "num=0"
+
+:getcharnext
+if "%str%"=="" ( 
+set /a num=0
+goto getcharlast
+)
+
+if not "%str%"=="" (
+set /a num+=1
+if "%str:~0,1%"=="%ch%" goto getcharlast
+set "str=%str:~1%"
+goto getcharnext
+)
+:getcharlast
+(endlocal
+set %3=%num%
+)
+goto:eof 
+::---------------end:func-------------------
+
+
+
+
+
+
Index: ModuleDemo/BLE/BT/do_sdk.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do_sdk.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/do_sdk.bat	(working copy)
@@ -0,0 +1,262 @@
+
+@set FPGA_PATH=fpgajic\fpga
+@set YC_PATCH_FILE=yc_patch_yc1121.h
+@set enc=1
+@set enckey=0000000000000000
+@echo off
+
+::get Rom path
+set now_path=%~dp0
+call:getstrlocation %now_path% ModuleDemo location
+call:get_fix_len_str  %now_path% location soft_path
+set lib_path=%soft_path%Librarier
+set rom_path=%lib_path%\bt_rom
+set program=%rom_path%\program
+set format=%rom_path%\format
+set util=%rom_path%\util
+set patch_path=%now_path%patch
+set sched=%now_path%sched
+set output=%now_path%output
+set voice_prompt=%now_path%voice_prompt
+
+rem @echo rom_path=%rom_path%
+rem @echo program_path=%program%
+rem @echo format_path=%format%
+rem @echo util_path=%util%
+rem @echo patch_path=%patch_path%
+
+
+::set progs=  %program%\a2dp.prog +  %program%\app.prog +  %program%\avctp.prog +  %program%\c51.prog +  %program%\cvsd.prog +  %program%\hci_main.prog +  %program%\audio.prog +  %program%\hid.prog +  %program%\hsphfp.prog +  %program%\ipc.prog +  %program%\l2cap.prog +  %program%\le_att.prog +  %program%\le.prog +  %program%\le_smp.prog +  %program%\lmp.prog +  %program%\peripherals.prog +  %program%\rfcomm.prog +  %program%\scheduler.prog +  %program%\sdp.prog +  %program%\security.prog +  %program%\simple_pairing.prog +  %program%\ui.prog +  %program%\upper_sm.prog +  %program%\usb.prog +  %program%\utility.prog +  %program%\tws_m.prog +  %program%\tws_s.prog +  %program%\headset.prog +  %program%\debug.prog  +  %program%\ota.prog 
+::copy %program%\bt.prog + %progs%  output\bt_program23.meta > nul
+copy patch\patch_sdk.prog + patch\patch.prog + %patch_path%\z.prog output\bt_program23.meta
+set fmts= %format%\a2dp.format +  %format%\app.format +  %format%\avctp.format +  %format%\cvsd.format +  %format%\hci.format +  %format%\headset.format +  %format%\hid.format +  %format%\hsphfp.format +  %format%\ipc.format +  %format%\l2cap.format +  %format%\le.format +  %format%\lmp.format +  %format%\memblocks.format +  %format%\patch.format +  %format%\prcp.format +  %format%\regs.format +  %format%\rfcomm.format +  %format%\sdp.format +  %format%\security.format +  %format%\simple_pairing.format +  %format%\ui.format +  %format%\upper_sm.format +  %format%\usb.format +  %format%\utility.format +  %format%\var.format +  %format%\xip.format +  %format%\tws.format +  %format%\remote.format +  %format%\mSBC.format +  %format%\debug.format +  %format%\tishi.format + %format%\ota.format + %format%\audio_dac_adc.format
+copy %format%\bt.format + %fmts% + format\labels.format + %format%\command.format  output\bt_format.meta > nul
+
+
+
+perl %util%/mergepatch.pl 				output/bt_program23.meta %patch_path%
+perl %util%/memalloc.pl 				output/bt_format.meta
+perl %util%/transform_memmap2btreg.pl 	output/memmap.format %format%/memblocks.format %format%/ipc.format %format%/ui.format %format%/hsphfp.format %format%/a2dp.format %format%/tws.format %format%/headset.format %format%/ota.format %format%/msbc.format ..\CM0\User\btreg.h
+cd output
+osiuasm bt_program23 -O-W
+copy ..\sched\patch.dat + ..\sched\user.dat + ..\sched\rf.dat +..\sched\usb.dat  ..\output\sched.rom
+
+
+
+if "%1" equ "eep" (
+	goto genromrevc
+)else (
+  goto downloadram
+)
+
+:genromrevc
+echo off
+@echo Start to generate EEPROM code
+
+if exist "..\..\CM0\Prj\Output\out.rom" (
+	copy "..\..\CM0\Prj\Output\out.rom"  "out.rom" 
+) else (
+	@echo "*** !!! Waring: No CM0 CODE !!! ***" 
+)
+
+%util%/geneep  -n -z 
+@rem  %util%/geneep -f -n   -k %now_path%\key.dat 
+%util%/geneep -f -n -z  
+
+::perl %util%\svnversion.pl %output%
+::perl %util%\getcodesize.pl %output%
+::perl %util%\p_coef.pl %sched%\coef.dat %output%/coef_out.dat 
+::perl %util%\vp2.pl %voice_prompt% %output%
+::perl %util%\add_coef.pl %output% flash2.dat coef_out.dat flash_add_coef.dat
+::perl %util%\add_ota_pcm.pl %output%/flash_add_coef.dat %output%/flash_add_coef.dat %output%/all_pcm_data.dat %output%
+
+::copy %output%\flash.dat  ..\..\..\..\24_TWS\bt_demo\BT\output\ota.dat
+
+:gen_eep_end
+cd ..
+echo **********************************
+@rem echo flash.dat Generated.
+echo **********************************
+goto end
+
+
+
+:genrom
+@rem echo on
+perl ..\util\rom2mif.pl romcode
+del ..\..\%FPGA_PATH%\romcode.mif
+copy .\romcode.mif ..\..\%FPGA_PATH%\romcode.mif
+perl ..\util\gen_patch_h.pl >%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% ..\..\%MV_PATCH%\%YC_PATCH_FILE%
+copy .\%YC_PATCH_FILE% D:\work\yichip\mv_proj\src\inc\%YC_PATCH_FILE%
+cd ..\..\%FPGA_PATH%
+quartus_cdb btspi -c btspi --update_mif
+quartus_asm --read_settings_files=off --write_settings_files=off btspi -c btspi
+quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "p;.\output\btspi.sof" 
+@echo bitstream_compression=on >1
+@echo memory_map_file=on >> 1
+quartus_cpf -c -o 1 -s EP3C55 -d EPCS16 output\btspi.sof output\btspi.jic  
+@rem quartus_pgm -c USB-Blaster[USB-0] -m jtag -o "pi;.\output\btspi.jic"   
+@del 1
+goto end
+
+
+
+:downloadram
+echo on
+@echo Start to download ram code
+e ku
+e hu
+e su sched.rom
+@echo **********************************
+@echo RAM CODE has been downloaded. 
+@echo **********************************
+cd ..
+
+
+:end
+goto:eof
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlocation-------
+::------------------------------------------
+:getstrlocation
+setlocal
+set "bstr=%1"
+set "cstr=%2"
+set %3=0
+set "num=0"
+set "len_bstr=0"
+set "len_cstr=0"
+
+call:getstrlen %bstr% len_bstr
+call:getstrlen %cstr% len_cstr
+
+:getstrlocation_next
+set /a len_remain=len_bstr-num
+if %len_remain% lss %len_cstr% (
+echo "cann't get str location"
+set /a num =0
+goto getstrlocation_last
+)
+
+call:get_fix_len_str %bstr%  len_cstr compar_str
+
+if not %compar_str%==%cstr% (
+set /a num+=1
+set "bstr=%bstr:~1%"
+goto getstrlocation_next
+)
+
+:getstrlocation_last
+(endlocal
+	set %3=%num%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+::------------------------------------------
+::---------------func:get_fix_len_str-------
+::------------------------------------------
+:get_fix_len_str
+setlocal
+set "getstr=%NULL%"
+set str=%1
+set /a len=%2
+set num=0
+:get_fix_len_str_loop
+set getstr=%getstr%%str:~0,1%
+set /a num+=1
+set str=%str:~1%
+if %num% lss %len% goto get_fix_len_str_loop
+(endlocal
+ set %3=%getstr%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlen-------------
+::------------------------------------------
+:getstrlen
+setlocal
+set str=%1
+set %2=0
+set /a "num=0"
+
+:getstrlen_next
+if "%str%"=="" goto getstrlen_last
+
+if not "%str%"=="" (
+set /a num+=1 
+set "str=%str:~1%"
+goto getstrlen_next
+)
+
+:getstrlen_last
+(endlocal
+	set /a "%2=%num%"
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getcharlocation-------
+::------------------------------------------
+:getcharlocation
+setlocal
+set "str=%1"
+set "ch=%2"
+set %3=0
+set /a "num=0"
+
+:getcharnext
+if "%str%"=="" ( 
+set /a num=0
+goto getcharlast
+)
+
+if not "%str%"=="" (
+set /a num+=1
+if "%str:~0,1%"=="%ch%" goto getcharlast
+set "str=%str:~1%"
+goto getcharnext
+)
+:getcharlast
+(endlocal
+set %3=%num%
+)
+goto:eof 
+::---------------end:func-------------------
+
+
+
+
+
+
Index: ModuleDemo/BLE/BT/download_full_bin.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/download_full_bin.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/download_full_bin.bat	(working copy)
@@ -0,0 +1,16 @@
+::e pu
+
+::e hu output/romcode.rom 2000
+e pu
+::e 8097   040307020506  
+e 8090 060502
+e 8094 040307
+
+e fp output/flash_all.dat 0
+
+e fe 0
+e fe 7f000
+e fw 0 036000
+e fw 3 a5
+e fw 4 a5
+e k
\ No newline at end of file
Index: ModuleDemo/BLE/BT/fdo.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/fdo.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/fdo.bat	(working copy)
@@ -0,0 +1,3 @@
+e pu
+e hu output/romcode.rom 2000
+e ku
\ No newline at end of file
Index: /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/format/.keep	(added)
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/format/.keep	(revision 0)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/format/.keep	(revision 0)
Index: ModuleDemo/BLE/BT/format/labels.format
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/format/labels.format	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/format/labels.format	(working copy)
@@ -0,0 +1,3695 @@
+0x2000 jmpz_z_hci_parse_packet_cmd_ogf_link_policy
+0x2000 start
+0x2001 soft_reset
+0x2011 sp_cal_loop
+0x2016 main_loop
+0x2025 connection_dispatch
+0x202a connection_incontext
+0x2033 connection_nosniff
+0x203c idle_dispatch
+0x2047 idle_exit
+0x2049 idle_le_create_conn
+0x204c idle_inquiry
+0x2051 idle_inquiry_cancel
+0x2054 idle_remote_name_req
+0x2059 idle_create_conn
+0x205c idle_create_conn_device
+0x2062 idle_create_conn_hci
+0x2065 idle_create_conn_cont
+0x2066 idle_start_page
+0x206c idle_page_mode_r0
+0x208a idle_page_fail
+0x2091 idle_name_fail
+0x2098 inquiry_dispatch
+0x209e inquiry_start
+0x20a5 inquiry_restart
+0x20a8 inquiry_rx_restart
+0x20ad inquiry_transmit
+0x20ba inquiry_check_train
+0x20c7 inquiry_receive
+0x20d1 inquiry_sync
+0x20d7 inquiry_receive_rtn
+0x20d8 inquiry_receive_eir_rtn
+0x20dc inquiry_receive_eir
+0x20e6 inquiry_receive_eir_packet
+0x20eb rf_setup_time_slave_slot_eir
+0x20ec rf_setup_time_eir
+0x20f0 master_page
+0x20f8 master_page_no_interval
+0x2103 master_npage_timeout
+0x2107 master_page_timeout
+0x210d page_start
+0x2119 page_restart
+0x211e page_rx_restart
+0x2131 master_dispatch_exit
+0x2131 page_exit
+0x2137 page_check_train
+0x2145 page_receive
+0x214d page_sync
+0x2153 page_send_fhs
+0x2157 page_send_fhs_continue
+0x2163 page_wait_fhs_reply
+0x2172 page_wait_fhs_reply_ok
+0x2177 master_newconn_loop
+0x217c newconn_poll_responded
+0x2183 master_dispatch
+0x2195 master_loop
+0x219f master_notmatch
+0x21a5 master_exit
+0x21a7 master_attempt
+0x21aa check_master_disconnect
+0x21ad check_master_match
+0x21bb master_disconnect
+0x21c4 master_disconnect_quiet
+0x21c5 master_name_disconnect
+0x21c6 master_name_error
+0x21ca check_disconnect_timeout
+0x21d2 conn_timer_expired
+0x21d6 linkkey_ready
+0x21e1 linkkey_send_hci
+0x21e1 linkkey_set
+0x21e6 linkkey_set_continue
+0x21e7 generate_linkkey_continue
+0x21e8 clear_linkstate
+0x21ec role_switch_check
+0x21f6 role_switch_clkn
+0x21f7 role_switch_clke
+0x21fc role_switch_prepare
+0x21ff role_switch_prepare0
+0x2204 role_switch_master
+0x220a roles_waitfhs_loop
+0x220f role_switch_fail_master
+0x2217 roles_replyto_fhs
+0x221f roles_newconns_loop
+0x2225 roles_newconns_responded
+0x222e context_load
+0x223f context_load_master
+0x2246 context_load_normal
+0x2248 context_load_end
+0x224b context_save
+0x2253 context_get_next
+0x2255 context_get_next_loop
+0x2259 context_get_next_cont
+0x2262 context_get_next_nosniff
+0x2264 context_get_next_sniff
+0x2266 context_new
+0x226d context_check_all_wack
+0x2275 context_check_esco_wack
+0x227a context_esco_wack
+0x227c context_check_idle
+0x227e context_traverse_linkkey
+0x2281 context_traverse_max_slot
+0x2284 context_search_conn_handle
+0x2285 context_search_conn_handle2
+0x2287 context_search_plap
+0x2289 context_search_plap2
+0x228b context_search_insniff
+0x228d context_search_sniff_window
+0x228e context_search
+0x2291 context_search_loop
+0x2293 context_search_next
+0x2297 context_search_empty
+0x229a context_search_lap
+0x229c context_search_lap_cont
+0x22a1 context_search_handle
+0x22a7 context_search_sniff
+0x22a8 context_search_sniff_loop
+0x22b4 context_search_master
+0x22ba context_search_sniff_cont
+0x22bd context_search_sco_sniff
+0x22c0 context_search_sniff_check
+0x22c1 context_search_meet
+0x22c5 context_search_have_link
+0x22c8 context_search_have_link_loop
+0x22ca context_search_have_link_next
+0x22ce sign_pdata_temp
+0x22d8 sign_pdata_temp_p0
+0x22de context_check_inconn
+0x22e1 context_check_a_wack
+0x22ea context_get_anchor
+0x22f8 context_next_anchor
+0x22fe context_search_window
+0x2307 context_traverse_mslot
+0x2314 context_traverse_clearkey
+0x231f master_conn_send_packet
+0x2321 master_send_packet
+0x2329 master_conn_recv_packet
+0x232b master_recv_packet
+0x2333 master_rx_conn_finish_packet
+0x2337 master_newconn_once
+0x233d inquiry_scan_dispatch
+0x234d inquiry_scan_start
+0x2377 send_eir
+0x2399 get_all_uuid
+0x239d lshift_loop
+0x23ae page_scan_dispatch
+0x23be page_scan_start
+0x23df page_scan_wait_fhs_restart
+0x23e8 page_scan_wait_fhs_again
+0x23ee page_scan_reply_to_fhs
+0x23fb slave_apply_clke_bt
+0x23ff slave_apply_clke_bt_now
+0x2402 start_slave_connection
+0x2406 slave_newconn_loop
+0x240b sconn_successful
+0x2413 slave_dispatch
+0x2419 slave_loop
+0x2429 slave_notmatch
+0x2435 prepare_sco_packet
+0x243c prepare_sco_packet_cm0
+0x243e prepare_esco_packet_cm0
+0x2441 process_sco_packet
+0x2448 process_sco_packet_cm0
+0x2450 process_esco_packet_cm0
+0x2458 slave_discon_supervision_timeout
+0x245a set_flow_flag
+0x245f clear_flow_flag
+0x2463 slave_disconnect
+0x2469 role_switch_slave
+0x2471 roles_sendfhs_loop
+0x2483 roles_got_fhs_reply
+0x2486 roles_newconn_loop
+0x248f roles_newconn_responded
+0x2495 roles_newconn_nolmp
+0x24a0 init_rx_packet_flags
+0x24a6 init_rx_packet_header_flags
+0x24ab prepare_newconn
+0x24b6 newconn_init
+0x24c4 clear_linkkey
+0x24ca new_conn_timeout
+0x24ce new_conn_handle
+0x24d2 quit_connection
+0x24d7 quit_connection_name
+0x24db quit_connection_cont
+0x24ed quit_connection_not_clear_mark
+0x24ef quit_connection_not_clear_tx
+0x24f3 slave_newconn_once
+0x2500 prepare_tx
+0x2505 prepare_tx_hv3
+0x2508 prepare_tx_esco
+0x250d prepare_tx_sco
+0x250e prepare_tx_acl
+0x2512 prepare_tx_retransmit
+0x251c prepare_tx_nomore_retransmit
+0x251e prepare_tx_no_retransmit
+0x2527 prepare_tx_pollnull
+0x252b prepare_tx_loopback
+0x2531 prepare_tx_txpat
+0x2535 prepare_tx_sendlmp
+0x2537 prepare_tx_sendl2cap
+0x2538 set_wait_ack
+0x2541 tx_l2cap_type
+0x2554 tx_l2cap_type_edr
+0x2564 slave_receive_master_slot
+0x2569 slave_receive_notsniff
+0x256a slave_receive_access
+0x256b slave_receive_sniff
+0x2588 slave_conn_recv_packet
+0x258a tws_slave_conn_recv_packet
+0x2591 receive_packet
+0x2593 receive_packet_whitened
+0x25a9 receive_packet_noedr
+0x25b3 receive_packet_amchk
+0x25bf am_addr_match
+0x25c0 am_addr_ok
+0x25cf arqn_bypass
+0x25dc failed_seqn
+0x25dd rx_type_dispatch
+0x25ed process_2ev3
+0x25f1 process_hv3
+0x25f9 process_sco_noedr
+0x25ff get_hev_data_loop
+0x2603 process_sco_data_end
+0x2610 process_null
+0x2610 process_poll
+0x2614 process_poll_null_end
+0x2615 process_dm5
+0x2615 process_dm3
+0x2616 process_dm1
+0x2618 process_dh5
+0x2618 process_dh3
+0x2619 process_3dh1
+0x261a process_dh1
+0x261b process_dmh
+0x2627 process_dmh_noedr
+0x2632 process_dmh_long
+0x2635 process_dmh_common
+0x2641 process_dmh_common_packet
+0x2647 process_dmh_common_packet_tws
+0x2649 process_lmp
+0x264f process_dmh_data_l2cap_start_pkt
+0x265e process_dmh_data_into_buff_normal
+0x2662 l2cap_rxbuff_len_error
+0x266a process_l2cap_continue_check_len
+0x266f tws_end_of_packet0
+0x2674 process_dmh_data_l2cap_continue_pkt
+0x2686 process_dmh_data
+0x268a process_dmh_data_end
+0x2693 tws_remind_crc_failed_flag
+0x2697 tws_update_local_packet_rcv_flag
+0x269c tws_update_remote_packet_rcv_flag
+0x26a1 process_dmh_data_end_tws
+0x26a7 tws_print_log_info_end_of_packet
+0x26b0 print_log_old_packet
+0x26b5 print_log_crc_error_packet
+0x26ba process_dmh_packet
+0x26c1 process_dmh_l2cap_packet
+0x26d0 push_l2cap_to_queue
+0x26dd process_dmh_cont
+0x26e6 process_dmh_cont_rxbuf_not_use
+0x26f0 ack_payload
+0x26f8 ack_payload_normal
+0x26fd ack_payload_normal_after_ack
+0x270a bt_force_nack_remote
+0x270c ack_payload_normal_force_nack
+0x2713 ack_payload_tws
+0x271a ack_payload_force_nack
+0x271c error_header
+0x2722 error_payload_crc
+0x2729 error_payload
+0x272a discard_pkt
+0x272e discard_pkt_lmp
+0x2732 discard_pkt_l2cap
+0x2736 redundant_payload
+0x2739 end_of_packet
+0x2745 process_fhs
+0x275a fhs_parity_ok
+0x2773 clear_got_tx
+0x278b clear_got_txlmp
+0x2798 clear_lmp_escape
+0x279b clear_send_setup_complete
+0x27a0 sco_link_req_by_slave
+0x27a5 clean_mem_mode
+0x27a8 start_encryption
+0x27b1 stop_encryption
+0x27b9 sniff_init
+0x27ba sniff_init_sco
+0x27bf sniff_init_acl
+0x27c2 sniff_init_master
+0x27cc sniff_init_nowrap
+0x27df sniff_exit
+0x27e9 check_attempt
+0x27ee check_attempt0
+0x27f0 check_attempt1
+0x27f3 check_attempt_normal
+0x27fd check_attempt_nomore
+0x27ff check_attempt_sniff
+0x2807 check_attempt_sniff_change_to_acl
+0x280b check_attempt_sco_master
+0x2811 check_attempt_for_acl
+0x281a check_attempt_notimeout
+0x281e sniff_check_window
+0x2827 parse_l2cap
+0x282a parse_l2cap_buff_process
+0x2836 slave_send_access
+0x283e tws_slave_conn_send_packet
+0x2841 slave_conn_send_packet
+0x2847 slave_conn_send_packet_normal
+0x2850 slave_conn_send_access
+0x2851 transmit_packet
+0x2855 transmit_packet_whitened
+0x287c transmit_2ev3
+0x2882 transmit_hev
+0x2889 transmit_ev_loop
+0x288e transmit_fhs
+0x28ab transmit_lmp
+0x28b3 transmit_lmp_loop
+0x28b9 transmit_lmp_finish
+0x28bc transmit_dm1
+0x28be transmit_dm3
+0x28be transmit_dm5
+0x28c1 transmit_3dh1
+0x28c2 transmit_dh1
+0x28c4 transmit_dh3
+0x28c4 transmit_dh5
+0x28c7 transmit_dmh
+0x28d6 transmit_edr3m
+0x28da transmit_edr_sync_end
+0x28dc transmit_noedr
+0x28e6 transmit_long
+0x28e7 transmit_stuff
+0x28ed transmit_stuff_loop
+0x28f1 transmit_stuff_hci
+0x28f3 transmit_stuff_hci_loop
+0x28f6 transmit_end
+0x28ff transmit_loopback
+0x2901 transmit_loopback_short
+0x2907 transmit_loopback_long
+0x290c transmit_loopback_cont
+0x290d transmit_loopback_loop
+0x2913 transmit_loopback_end
+0x2917 apply_switch_clke
+0x291d apply_switch_nozero
+0x2920 apply_switch_loop
+0x2924 apply_switch_bt
+0x2925 apply_switch_wait_loop
+0x292c calc_slot_offset
+0x2936 calc_bt_portion
+0x2938 calc_slot_offset_loop
+0x293a calc_skip_bt
+0x2940 calc_clke_offset
+0x294b calc_clke_pos
+0x294e calc_clke
+0x2951 calc_clke_tws
+0x2952 calc_clke2
+0x295a calc_clke_pos2
+0x295c calc_clke_pos_adj
+0x295e calc_radio_freq
+0x2967 freq_not_connection
+0x2968 do_hop_mod_now
+0x2970 odd_half
+0x2972 freq_result
+0x2975 afh_process_0
+0x2983 afh_process_con
+0x2990 afh_process_1
+0x299c afh_process_end
+0x299f afh_same_channel
+0x29a2 afh_clear
+0x29a7 afh_process_freq_map
+0x29ae process_freq_3
+0x29b3 process_freq_1
+0x29b7 process_freq_0
+0x29c0 process_freq_2
+0x29ca rx_radio_freq
+0x29cf rx_radio_freq_now
+0x29d0 tx_radio_freq
+0x29d5 tx_radio_freq_now
+0x29d6 fetch_giac
+0x29da fetch_page_bt_adr
+0x29df fetch_self_bt_adr
+0x29e7 fetch_extm_bt_adr
+0x29ef fetch_diac
+0x29f2 fetch_diac_do
+0x29f6 shutdown_radio
+0x2a05 shutdown_radio_5db
+0x2a05 shutdown_radio_0db
+0x2a07 shutdown_radio0
+0x2a14 shutdown_radio_f3db
+0x2a14 shutdown_radio_3db
+0x2a17 set_sync_on
+0x2a1f set_freq_rx
+0x2a23 rf_rx_enable
+0x2a2d set_offset_sfreq
+0x2a2f set_freq_tx
+0x2a37 rf_tx_enable
+0x2a49 set_tx_power_0db
+0x2a4d set_tx_power_3db
+0x2a51 set_tx_power_5db
+0x2a55 set_tx_power_f3db
+0x2a59 set_tx_power_f5db
+0x2a5d txon_common
+0x2a64 initialize_radio
+0x2a65 initialize_radio_wait
+0x2a69 initialize_radio_loop
+0x2a6f initialize_radio_cont
+0x2a7b rf_write_freq
+0x2a92 sfreq_init
+0x2a95 do_rccal
+0x2aa2 do_rccal_loop
+0x2aa5 do_rccal_end
+0x2aac set_rccal
+0x2abc save_rssi
+0x2aca switchto_rcclk
+0x2ad3 switchto_dpllclk
+0x2aef check_dpll
+0x2af4 check_dpll_loop
+0x2afa check_dpll_loop2
+0x2b00 check_dpll_pos
+0x2b02 check_dpll_assert
+0x2b04 xtal_fast_wake
+0x2b06 init_lpm_ctrl
+0x2b08 start_receiver
+0x2b0e prep_crypt
+0x2b1f wait_access_clke_rt
+0x2b23 wait_access_end
+0x2b2b wait_access_mhalfbnd
+0x2b2c wait_access_mhalfbnd_correlate
+0x2b31 wait_access_clkn_rt
+0x2b38 wait_access_forever
+0x2b40 reserve_slot
+0x2b46 ahead_window
+0x2b55 setup_clk
+0x2b58 skip_setup_clke
+0x2b5a setup_clkn
+0x2b5c skip_setup_clkn
+0x2b5d setup_clknbt
+0x2b60 setup_complete
+0x2b69 setup_clk11
+0x2b6c rf_setup_time
+0x2b6f rf_setup_time_slave_slot
+0x2b71 rf_setup_time_master_slot
+0x2b73 start_transmitter
+0x2b78 start_tx_native
+0x2b7d start_rx_native
+0x2b81 start_tx_external
+0x2b86 send_access_word
+0x2b8e scan_mode_whiten
+0x2b92 get_free_amaddr
+0x2b97 get_free_amaddr_cont
+0x2b9a get_clk
+0x2b9e get_clkbt
+0x2ba2 supervision_update
+0x2bab supervision_flush
+0x2baf assert
+0x2bb1 sleep
+0x2bb4 sleep_loop
+0x2bb8 init_param
+0x2bd8 init_param_cont
+0x2bde kscan_init
+0x2be5 kscan_col_state_init
+0x2bea kscan_row_state_init
+0x2bef kscan_get_col_state_commom
+0x2bf1 kscan_get_col_state_commom_loop
+0x2bf7 kscan_no_keypress
+0x2bfa kscan_get_keypress
+0x2bfd kscan_enter_first_step
+0x2c00 kscan_get_col_state_loop
+0x2c07 kscan_avoid_shake
+0x2c0c kscan_confirm_col_num
+0x2c10 kscan_confirm_row_num
+0x2c14 kscan_enter_second_step
+0x2c17 kscan_row_output_reverse_loop
+0x2c1c kscan_row_output_reverse1
+0x2c28 keyscan_check_fail
+0x2c2b kscan_row_add_bcc_check
+0x2c2d kscan_add_bcc_check_common
+0x2c31 kscan_col_add_bcc_check
+0x2c34 keyscan_check
+0x2c37 keyscan_check1
+0x2c3d p_calc_bcc
+0x2c3f p_calc_bcc1
+0x2c43 keyscan_row_check_bcc
+0x2c46 keyscan_col_check_bcc
+0x2c49 keyscan_check_bcc
+0x2c4b keyscan_length_0
+0x2c4f lpmstate
+0x2c60 lpmwake
+0x2c78 lpm_load_context
+0x2c82 lpm_load_context_wakeup
+0x2c87 lpm_save_context
+0x2c91 lpo_calibration
+0x2c97 lpo_cal_inited
+0x2c9c lpm_adjust_clk
+0x2cac lpm_adjust_positive
+0x2caf lpm_clear_counter
+0x2cb2 lpm_close_patchram
+0x2cb8 lpm_doze
+0x2cbc lpm_hibernate
+0x2cc1 lpm_hibernate_normal
+0x2cc9 lpm_sleep
+0x2cdb lpm_enter_sleep
+0x2cdf lpm_read_retention
+0x2ce6 lpm_recover_clk
+0x2cef lpm_recover_xtal
+0x2cf1 lpm_recover_timeout
+0x2d09 lpm_dispatch
+0x2d1c lpm_dispatch_next
+0x2d3d lpm_dispatch_sleep
+0x2d3e lpm_dispatch_lpo
+0x2d47 lpm_dispatch_unconn
+0x2d4f lpm_unconn_nossp
+0x2d53 lpm_unconn_cont
+0x2d55 lpm_sleep_btclk
+0x2d5a lpm_set_mult
+0x2d69 lpm_mult_wait_timeout
+0x2d70 classic_bt_set_mult_short_flag
+0x2d72 classic_bt_clr_mult_short_flag
+0x2d74 lpm_match
+0x2d79 lpm_not_match
+0x2d7e lpm_lost
+0x2d86 lpm_mult_short
+0x2d8a lpm_mult_long
+0x2d8d lpm_cal_xtal_startup
+0x2da4 lpm_cal_xtal_startup_by_snooze
+0x2dbe lpm_write_config
+0x2dc9 lpm_write_gpio_wakeup
+0x2dd4 lpm_write_ctrl
+0x2dd8 lpm_write_ctrl2
+0x2ddc lpm_get_wake_lock
+0x2de0 lpm_put_wake_lock
+0x2de4 lpm_check_wake_lock
+0x2e0a lpm_uart_wake_lock
+0x2e0f lpm_shut_down
+0x2e14 lpm_enable_exen_output
+0x2e19 lpm_disable_exen_output
+0x2e1e check_bt_disabled
+0x2e21 check_ble_disabled
+0x2e24 check_module_disabled
+0x2e27 test_init
+0x2e2f test_proc
+0x2e35 test_sleep
+0x2e37 test_sleep_loop
+0x2e3b test_tx
+0x2e43 test_tx_loop
+0x2e46 check_amaddr_is_esco
+0x2e49 load_context_to_acl
+0x2e4a load_context_to_acl_no_mark
+0x2e4c load_to_acl
+0x2e5b load_context_to_esco
+0x2e5e load_context_to_esco0
+0x2e6d bt_check_have_classic_link_in_connecting
+0x2e70 bt_wake_up_m0_light_sleep
+0x2e74 l2cap_call_proc_avdtp
+0x2e86 l2cap_call_proc_avdtp_media_start_sbc
+0x2e98 l2cap_call_proc_avdtp_media_wait
+0x2e9c l2cap_call_proc_avdtp_media
+0x2ea0 l2cap_call_proc_avdtp_media_titshi
+0x2ea7 l2cap_call_proc_avdtp_media_allow
+0x2eab l2cap_call_proc_avdtp_media_allow_sbc_idle
+0x2eb6 l2cap_call_proc_avdtp_media_allow_sbc_prepare_dma_work
+0x2ec5 a2dp_soft_dma_work_process
+0x2edb a2dp_soft_dma_work_process_1
+0x2eea a2dp_soft_dma_work_process_end
+0x2eed a2dp_soft_dma_tws_add_or_drop_bytes
+0x2ef2 a2dp_soft_dma_tws_add_bytes
+0x2ef9 a2dp_soft_dma_tws_add_bytes_end
+0x2f00 a2dp_soft_dma_tws_add_bytes_end_big
+0x2f04 a2dp_soft_dma_tws_drop_bytes
+0x2f0a a2dp_soft_dma_tws_drop_bytes_end
+0x2f0f a2dp_soft_dma_tws_drop_bytes_end_big
+0x2f16 a2dp_soft_dma_work_process_allow_work_size
+0x2f1c a2dp_soft_dma_work_unit_set
+0x2f24 a2dp_soft_dma_update_dac_wptr_loopback
+0x2f2e a2dp_sbc_get_full_dst_addr_with_offset
+0x2f33 a2dp_dac_get_full_dst_addr_with_offset
+0x2f36 l2cap_call_proc_avdtp_media_allow_soft_dma_in_work
+0x2f3d a2dp_soft_dma_update_vol
+0x2f40 a2dp_soft_dma_mute_vol
+0x2f47 a2dp_soft_dma_update_dac_wptr
+0x2f4a l2cap_call_proc_avdtp_media_allow_sbc_in_work
+0x2f57 audio_dac_set_farrow_filter
+0x2f5d audio_dac_set_farrow_filter_end
+0x2f5e audio_dac_set_farrow_filter_process
+0x2f65 a2dp_update_farrow_filter_work_sample
+0x2f6d tws_clear_farrow_filter_work_sample
+0x2f71 l2cap_call_proc_avdtp_media_with_dac_empty_detect
+0x2f77 l2cap_call_proc_avdtp_media_free_packet
+0x2f79 l2cap_call_proc_avdtp_media_parse_header
+0x2f86 a2dp_check_rcv_seq_error
+0x2f90 a2dp_check_rcv_seq_error_end
+0x2f93 a2dp_update_min_receive_packet_size
+0x2f99 l2cap_call_proc_avdtp_media_data
+0x2fa8 avd_media_get_offset_loop
+0x2fb9 a2dp_sbc_clear_ptr_work
+0x2fbc a2dp_media_first_buffer_cache_work
+0x2fca a2dp_media_buffer_drop_packet_process
+0x2fd9 a2dp_media_buffer_add_packet_process
+0x2fe2 a2dp_media_buffer_add_drop_packet_judge
+0x2fea a2dp_media_buffer_add_drop_packet_judge_end
+0x2fed tws_check_master_slave_wait_sync_ok
+0x2ff3 a2dp_media_buffer_drop_packet_judge
+0x3007 a2dp_media_buffer_drop_packet
+0x300d a2dp_media_buffer_drop_packet_normal
+0x300e a2dp_media_buffer_drop_packet_tws
+0x3013 a2dp_media_buffer_drop_packet_action
+0x3018 a2dp_media_buffer_add_packet_judge
+0x302a a2dp_media_buffer_add_packet
+0x3030 a2dp_media_buffer_add_packet_normal
+0x3031 a2dp_media_buffer_add_packet_tws
+0x3036 a2dp_media_buffer_add_packet_action
+0x3040 avd_signal_parse_cmd
+0x3052 avd_signal_parse_cmd_discover
+0x305a avd_signal_parse_cmd_get_cap
+0x3070 avd_signal_parse_cmd_set_conf
+0x3076 avd_analy_conf_loop
+0x3083 avd_analy_conf_rsp
+0x3086 avd_analy_conf_codec_cap
+0x308a avd_signal_parse_cmd_open
+0x308e avd_signal_parse_cmd_start
+0x3091 avd_signal_parse_cmd_common
+0x3094 avd_signal_parse_cmd_suspend
+0x309b avd_signal_parse_cmd_close
+0x309e avd_stop_sbc_dac
+0x30a1 avd_signal_parse_cmd_get_all_cap
+0x30b7 avd_signal_parse_cmd_security_control
+0x30b7 avd_signal_parse_cmd_delayreport
+0x30b8 avd_signal_parse_general_reject
+0x30b8 avd_signal_parse_rsp_reject
+0x30b9 avd_signal_parse_rsp_accept
+0x30c1 avd_signal_parse_rsp_accept_discover
+0x30c6 avd_signal_src_inuse
+0x30c8 avd_signal_parse_rsp_accept_getcap2
+0x30cc avd_signal_parse_rsp_accept_getcap
+0x30d1 avd_signal_parse_rsp_accept_getcap_loop
+0x30de avd_signal_parse_rsp_getcap
+0x30e2 avd_signal_parse_rsp_accept_setconf
+0x30e6 avd_sginal_parse_rsp_accept_open
+0x30ea avd_signal_prase_uncomplete
+0x30eb avd_signal_rsp_reject
+0x30f0 avd_malloc_rsp_accept
+0x30f3 avd_org_res
+0x30fa avd_malloc_cmd
+0x3101 avd_signal_send_discover
+0x3104 avd_signal_send_getcap
+0x310b avd_signal_send_setconf
+0x311a avd_signal_send_setconf_44_1k
+0x3120 avd_signal_send_setconf_48k
+0x3126 avd_signal_send_open
+0x312d a2dp_send_evt_open
+0x312f a2dp_send_evt_start
+0x3131 a2dp_send_evt_close
+0x3133 a2dp_send_evt_suspend
+0x3135 a2dp_check_need_cal_media_frame_info
+0x313f a2dp_check_need_cal_media_frame_info_seq_check
+0x3143 a2dp_check_need_cal_media_frame_info_seq_check_0
+0x3146 app_init
+0x314d app_lpm_init
+0x3153 app_process_idle
+0x315a app_process_bt
+0x315c app_process_ble
+0x315e app_process_bb_event
+0x3165 app_discard_event
+0x3167 app_event_normal_process
+0x3179 app_evt_bt_conn
+0x3180 app_event_switch_success
+0x3182 app_event_switch_fail_master
+0x318c app_event_start_page
+0x3190 app_process_bb_event_priority
+0x3192 app_check_wake_lock
+0x3194 app_will_enter_lpm
+0x3196 app_check_keyscan
+0x319e app_event_linkkey_generate
+0x31a2 app_event_reconn_start
+0x31a9 app_evt_setup_complete
+0x31b0 app_evt_hid_handshake
+0x31b4 app_event_enter_sniff
+0x31bb app_event_exit_sniff
+0x31bf app_le_event_bb_connected
+0x31c3 app_le_event_bb_disconn
+0x31c7 app_bb_event_hid_connected
+0x31cb app_evt_button_long_pressed
+0x31cf app_evt_timer
+0x31d2 app_evt_100ms_loop
+0x31db app_debug_current_state
+0x31f0 app_bb_event_reconn_failed
+0x31f8 app_bb_event_bb_disconn
+0x31fc app_bb_event_bb_reconn_disconn
+0x3205 app_bb_hibernate
+0x3207 app_disconn_reason_clear
+0x320a app_disconn_reason_flag_clear
+0x320d app_disconn_reason_collect_bt
+0x3212 app_disconn_reason_collect_ble
+0x3218 app_le_check_reconn_target
+0x321b app_le_check_reconn_target_none
+0x321c app_check_plap
+0x3220 app_check_one_plap
+0x3224 app_check_one_plap_next
+0x3229 app_check_one_plap_device_exist
+0x322d app_check_conn_device_nums_addr
+0x322f app_check_sniff
+0x3232 app_get_lpm_wake_lock
+0x3234 app_put_lpm_wake_lock
+0x3236 app_l2cap_flow_control_enable
+0x3238 app_l2cap_flow_control_disable
+0x323a app_bt_set_pincode
+0x323c app_bt_role_switch
+0x323e app_bt_start_reconnect
+0x3243 app_bt_start_reconnect_and_discover
+0x3245 app_bt_reconnect_cancel
+0x3247 app_bt_disconnect
+0x3249 app_bt_start_discovery
+0x324e app_bt_stop_discovery
+0x3252 app_ble_start_direct_adv
+0x3254 app_ble_stop_direct_adv
+0x3256 app_ble_stop_adv
+0x3258 app_ble_start_adv
+0x325a app_ble_start_scan
+0x325c app_ble_stop_scan
+0x325e app_ble_start_conn
+0x3260 app_ble_disconnect
+0x3262 app_enter_hibernate
+0x3264 app_bt_sniff_exit
+0x3266 app_bt_enter_sniff
+0x3268 app_ble_store_reconn_info
+0x326a app_bt_store_reconn_info
+0x326c app_lpm_mult_enable
+0x326e app_lpm_mult_disable
+0x3270 app_bt_esco_req
+0x3272 app_bt_rmv_esco_req
+0x3274 app_bt_sco_req
+0x3276 app_bt_rmv_sco_req
+0x3278 app_bt_play_pause
+0x327a app_bt_backward
+0x327c app_bt_forward
+0x327e app_bt_vol_up
+0x3280 app_bt_vol_down
+0x3282 app_bt_accept_call
+0x3284 app_bt_hang_up
+0x3286 app_bt_redial
+0x3288 app_bt_recognition
+0x328a l2cap_call_proc_avctp
+0x3299 process_avctp_cmd
+0x32a0 process_avctp_rsp
+0x32a5 process_avctp_change
+0x32a9 process_avctp_notify
+0x32b3 process_avctp_notify_register_notification
+0x32b7 process_avctp_notify_vol_changed
+0x32b9 process_avctp_cmd_status
+0x32c3 process_avctp_get_cap
+0x32c5 process_avctp_control
+0x32c9 process_avctp_control_set_vol
+0x32d4 process_avctp_control_set_vols_res
+0x32e5 process_avctp_control_set_vol_max
+0x32e8 avctp_malloc_tx_buff
+0x32f3 avctp_send_avr_vd_get_cap
+0x32fc avctp_send_vd_get_cap
+0x330f avctp_get_vol
+0x3313 avctp_send_get_cap_rsp
+0x3328 avctp_send_vd_playback_status_change
+0x333b avctp_send_vol_changed
+0x3344 avctp_send_vol_changed2
+0x3351 avctp_send_notify_rsp
+0x335b avctp_send_vd_common
+0x3365 avctp_send_play_pause
+0x336c avctp_send_play
+0x3370 avctp_send_pause
+0x3374 avctp_send_backward
+0x3378 avctp_send_forward
+0x337c avctp_play_press
+0x337f avctp_play_release
+0x3382 avctp_pause_press
+0x3385 avctp_pause_release
+0x3388 avctp_backward_press
+0x338a avctp_backward_release
+0x338c avctp_forward_press
+0x338e avctp_forward_release
+0x3390 arctp_send_pass_through
+0x33a7 hci_init
+0x33a8 process_cmd
+0x33bb process_cmd_conn_handle
+0x33ca cmd_exit
+0x33cc cmd_check_plap
+0x33d0 cmd_check_handle
+0x33d4 cmd_accept_conn
+0x33d8 cmd_accept_with_switch
+0x33da cmd_role_switch
+0x33e2 cmd_namereq
+0x33e5 cmd_ssp
+0x33e8 cmd_pair
+0x33ed cmd_pair_passive
+0x33f4 cmd_nopair
+0x33fa cmd_has_key
+0x3400 cmd_send_sres
+0x3404 cmd_no_key
+0x3407 cmd_no_key_reject
+0x340d cmd_auth
+0x3413 cmd_send_aurand
+0x3413 cmd_auth_sendaurand
+0x3416 cmd_start_encrypt
+0x3418 cmd_stop_encrypt
+0x341a cmd_feature_req
+0x341d cmd_ext_feature_req
+0x3420 cmd_version_req
+0x3422 cmd_in_sniff
+0x343c cmd_exit_sniff
+0x3440 cmd_setup_esco
+0x3444 cmd_setup_sco
+0x3446 cmd_disconn
+0x3448 cmd_disconn_esco
+0x3448 cmd_disconn_sco
+0x344d cmd_accept_sco_conn
+0x3454 cmd_accept_sco_conn_master
+0x345b cmd_io_cap
+0x345d cmd_detach
+0x3460 audio_dac_init_mono
+0x3464 audio_dac_init_stero
+0x3468 audio_dac_init_tws_left_mono
+0x346c audio_dac_init_tws_left_stero
+0x3470 audio_dac_init_tws_right_mono
+0x3474 audio_dac_init_tws_right_stero
+0x3478 audio_dac_init_media
+0x347d audio_dac_init_vp_call
+0x3482 audio_dac_init
+0x349d audio_dac_start
+0x34a1 audio_dac_mono_stero
+0x34a3 audio_dac_mono
+0x34a7 audio_dac_stero
+0x34ab audio_dac_set_sample_rate
+0x34bf audio_dac_clk_check
+0x34c4 audio_dac_samplefreq_sel_44k
+0x34c6 audio_dac_analog_sel_44k
+0x34ca audio_dac_samplefreq_sel_48k
+0x34cd audio_dac_analog_sel_48k
+0x34d1 audio_dac_samplefreq_sel_8k
+0x34d4 audio_dac_samplefreq_sel_16k
+0x34d7 audio_dlychain_dac_init
+0x34df audio_dlychain_dac_init_loop
+0x34e9 audio_dac_coef_init
+0x34f4 audio_coef_init_loop
+0x34ff audio_get_coef_start_addr
+0x3503 audio_load_dac_48k_coef
+0x3505 audio_load_dac_coef_common
+0x3508 audio_load_coef_common
+0x350c audio_load_dac_44k_coef
+0x350f audio_load_dac_8k_coef
+0x350f audio_load_dac_16k_coef
+0x3512 audio_dac_set_l
+0x351b audio_dac_close_l
+0x351f audio_dac_set_r
+0x3528 audio_dac_close_r
+0x352c audio_dac_ana_clk_en
+0x3530 audio_dac_filter
+0x3534 audio_dac_sdm
+0x3538 audio_dac_mram
+0x353a audio_dac_sched_ram
+0x353c audio_dac_mram_sel
+0x3540 audio_dac_stop
+0x354a audio_dac_clk_off
+0x354e audio_dac_vol_adjust
+0x3555 audio_dac_vol_adjust_end
+0x3558 audio_dac_mute_vol
+0x355d audio_dac_hw_get_use_count
+0x3568 audio_dac_hw_get_reserve_count
+0x356d audio_dac_hw_check_empty
+0x3571 audio_dac_hw_get_write_ptr_right_reserve_buffer
+0x3579 audio_dac_get_sbc_decode_buffer_size_by_cal
+0x357e audio_dac_get_sbc_decode_buffer_size_by_cal_0
+0x357f audio_dac_get_sbc_decode_buffer_size
+0x358c audio_dac_get_sbc_decode_buffer_size_in_different_buffer
+0x358e audio_dac_judge_reserve_buffer_enough
+0x3596 ramp_left_down
+0x359d ramp_left_up
+0x35a5 ramp_right_down
+0x35ac ramp_right_up
+0x35b4 ramp_finish_clr
+0x35b6 ramp_store_ramp_ctrl
+0x35b8 ramp_finish_clr_down
+0x35ba ramp_finish_clr_up
+0x35bc audio_filter_init
+0x35c4 audio_filter_var_init
+0x35cb audio_soft_dma_var_init
+0x35cf audio_44k_no_filter
+0x35d1 audio_disable_44kto48k
+0x35d5 audio_filter_44kto48k
+0x35d9 audio_enable_44kto48k
+0x35dd audio_48k_no_filter
+0x35e0 audio_filter_48kto48k
+0x35e4 audio_enable_farrow_filter
+0x35e8 audio_disable_farrow_filter
+0x35ec audio_farrow_filter_clear
+0x35f0 audio_farrow_filter_set_delta_uk
+0x35f4 audio_farrow_filter_set_delta_uk_0
+0x3601 sbc_dac_address_init
+0x3608 sbc_clear
+0x360f sbc_init
+0x3622 sbc_update_stream_out
+0x362b sbc_update_stream_out_tws
+0x362f sbc_set_single_left_out
+0x3635 sbc_set_single_right_out
+0x363b sbc_set_left_right_mix_out
+0x3641 sbc_set_full_out
+0x3647 sbc_clk_on
+0x3649 sbc_hw_check_error
+0x3654 sbc_src_addr_ptr_clr
+0x3658 sbc_src_dst_addr_ptr_clr
+0x365c sbc_update_dac_wptr
+0x3662 sbc_hw_check_busy
+0x3666 sbc_dst_mram_sel
+0x366b sbc_block_enable
+0x366f sbc_block_disable
+0x3673 sbc_clear_dac_buf
+0x367a sbc_stop
+0x3688 sbc_clk_off
+0x368a sbc_busy_wait
+0x368d eq_init
+0x369c eq_coef_init_loop
+0x36a3 eq_coef_set0_loop
+0x36a8 eq_enable
+0x36ac eq_disable
+0x36b0 msbc_dac_init
+0x36b4 msbc_dac_address_init
+0x36b9 cvsd_dac_address_init_8k
+0x36c2 cvsd_dac_address_init_48k
+0x36cb cvsd_dac_init_8k
+0x36cf cvsd_dac_init_48k
+0x36d2 cvsd_dac_init_wait
+0x36d9 voice_dac_update_vol
+0x36dd audio_adc_filter
+0x36e6 audio_adc_coef_init_loop
+0x36ed audio_adc_coef_set0_loop
+0x36f3 aduio_adc_cvsd_init
+0x3709 aduio_adc_msbc_init
+0x370f audio_adc_init
+0x3720 audio_adc_start_8k
+0x3724 audio_adc_dma_enable
+0x3728 audio_adc_start_16k
+0x372d audio_adc_stop
+0x3735 audio_adc_mram_sel
+0x3739 cvsd_init
+0x373e cvsd_init_process
+0x375b cvsd_start_with_init_data
+0x375d cvsd_coef_init
+0x3763 cvsd_clk_enable
+0x3769 cvsd_start
+0x376f cvsd_write_ctrl
+0x3771 cvsd_enable_group
+0x3774 cvsd_disable_group
+0x3777 cvsd_wait_cvsd_filter_clr_done
+0x377a audio_cvsd_coef_init
+0x3783 audio_cvsd_coef_init_loop
+0x378a cvsd_stop
+0x378c cvsd_push_0x55_to_cvsd_fifo
+0x3790 cvsd_push_cvsd_in_fifo_ptr
+0x3796 cvsd_push_cvsd_in_fifo_end
+0x379a cvsd_push_cvsd_in_fifo_end_0
+0x379c cvsd_pop_cvsd_out_fifo_ptr
+0x37a4 cvsd_push_cvsd_out_fifo_end
+0x37a8 cvsd_push_cvsd_out_fifo_end_0
+0x37aa cvsd_check_decoded_data
+0x37b1 cvsd_check_decoded_data_tishi
+0x37b7 push_cvsd_data_dac_start
+0x37bf push_cvsd_data_to_dec
+0x37c7 push_0x55_to_dec
+0x37c9 push_cvsd_data_dac_not_start
+0x37ce cvsd_check_decoded_data_cm0
+0x37cf pop_cvsd_data_pcm_ahead
+0x37d1 pop_cvsd_data_send
+0x37db pop_cvsd_data_check_ahead
+0x37df pop_cvsd_data_send_start
+0x37e9 cvsd_pop_cvsd_fifo_end
+0x37eb pop_cvsd_0x55
+0x37ee pop_cvsd_data
+0x37f4 pop_cvsd_data_send_cm0
+0x37f5 cvsd_48kpcm_out_mram_sel
+0x37f9 cvsd_8kpcm_in_mram_sel
+0x37fd cvsd_8kpcm_out_mram_sel
+0x3801 cvsd_in_mram_sel
+0x3805 cvsd_out_mram_sel
+0x3809 msbc_init
+0x380f msbc_stop
+0x3810 msbc_encode_init
+0x3821 msbc_clear_buf
+0x3827 msbc_clear_txbuf
+0x382a msbc_clear_outbuf
+0x382e msbc_pcm_in_len_update
+0x3835 msbc_pcm_out_len_update
+0x383c msbc_in_len_update
+0x3843 msbc_out_len_update
+0x384a msbc_decode_init
+0x3852 msbc_enc_dec_stop
+0x3853 msbc_pop_packet
+0x385b msbc_pop_packet_normal
+0x3863 msbc_packet_sequence_number0
+0x3865 msbc_packet_sequence_number1
+0x3867 msbc_packet_sequence_number2
+0x3869 msbc_packet_sequence_number3
+0x386a msbc_packet_common
+0x3878 msbc_pop_packet_0
+0x387b msbc_pop_packet_cm0
+0x387c msbc_adc_wait
+0x3885 msbc_packet_process
+0x3898 msbc_packet_process2
+0x38a5 msbc_packet_process_cm0
+0x38a6 msbc_update_wptr
+0x38ac msbc_wait_dac_start
+0x38b4 msbc_packet_process_error
+0x38b8 msbc_packet_process_miss
+0x38bc vp_play_by_cmd
+0x38c3 vp_play_tishi_by_cmd
+0x38ca vp_play_poweron
+0x38cc vp_play_battery_near_empty
+0x38d0 vp_play_max_volume
+0x38d4 vp_play_poweroff
+0x38d6 vp_play_connect
+0x38d8 vp_play_disconnect
+0x38da vp_play_tws_connected
+0x38dc vp_play_phone_number_timer
+0x38e3 vp_play_number
+0x38f2 vp_play_check_48k
+0x38f9 vp_play_check_language
+0x38fd vp_play_check_language_1
+0x3900 vp_play_english
+0x3902 vp_play_voice_prompt
+0x390e vp_play_voice_prompt2
+0x391d vp_check_header
+0x3928 vp_state_sniff
+0x392d vp_enable
+0x3933 vp_play_wait_sniff
+0x3938 vp_wait_end
+0x393d vp_check_get_data
+0x3952 vp_get_last_data
+0x3955 vp_check_dac_wptr
+0x395b vp_check_dac_buff
+0x395f vp_check_dac_wptr_positive
+0x3963 vp_dac_disable
+0x396a vp_restart_a2dp
+0x396b vp_get_length
+0x3978 vp_get_data
+0x3980 vp_get_data_block1
+0x3982 vp_get_data_block0
+0x3983 vp_get_data_set_block
+0x3986 vp_check_mram
+0x3989 vp_update_dac_wptr
+0x398f vp_update_dac_wptr_start
+0x3991 vp_dac_address_init
+0x3999 vp_get_wake_lock
+0x399b vp_put_wake_lock
+0x399d tishi_play_battery_near_empty
+0x399f tishi_play_max_volume
+0x39a1 tishi_play_check_language
+0x39a6 tishi_play_check_language_1
+0x39a9 tishi_play_english
+0x39aa tishi_play_voice_prompt
+0x39b8 tishi_play_voice_prompt2
+0x39c5 tishi_address_init
+0x39d0 tisthi_enable
+0x39d2 tisthi_disable
+0x39d9 tishi_check_wptr
+0x39df tishi_check_dac_buff
+0x39e3 tishi_check_dac_wptr_positive
+0x39e7 tishi_update_dac_wptr
+0x39f0 tishi_update_dac_wptr_start
+0x39f2 tishi_check_get_data
+0x3a03 tishi_get_last_data
+0x3a06 l2cap_call_proc_hid
+0x3a08 hid_rx_process
+0x3a14 hid_rx_process_hid_control
+0x3a18 hid_rx_process_virtual_cable_unplug
+0x3a1a hid_rx_process_suspend
+0x3a1b hid_rx_process_set_report
+0x3a20 hid_rx_process_handshake
+0x3a26 hid_rx_process_data
+0x3a29 hid_rx_process_data_hid_kb
+0x3a2b hfp_clear_sco_params
+0x3a31 hfp_evt_update_state
+0x3a36 hfp_update_state_nocallactive
+0x3a40 hfp_update_incomming
+0x3a43 hfp_evt_incomming
+0x3a45 hfp_evt_nono
+0x3a47 hfp_evt_outgoing
+0x3a49 hfp_evt_callactive
+0x3a4b hfp_evt_callimg
+0x3a4d hfp_evt_callogg
+0x3a4f hfp_evt_calmulty
+0x3a51 hfp_update_outgoing
+0x3a55 hfp_update_state_callactived
+0x3a5d hfp_update_callincomming
+0x3a61 hfp_update_calloutgoing
+0x3a65 hfp_update_state_nocallheld
+0x3a6e hfp_dialing_stop
+0x3a71 hfp_dialing_clear
+0x3a74 hfp_dialing_start
+0x3a7a hfp_get_indicator_value
+0x3a7e hfp_send_answer_call
+0x3a7f send_ata
+0x3a88 hfp_send_hang_up
+0x3a89 send_at_chup
+0x3a94 send_at_vgs
+0x3aa3 send_at_vgs_body_two_byte
+0x3aab send_at_vgs_body_one_byte
+0x3ab0 send_at_cmd_body_end
+0x3ab2 send_at_vgm
+0x3ab5 send_at_vgm_body
+0x3ac1 send_at_vgm_body_two_byte
+0x3ac9 send_at_vgm_body_one_byte
+0x3acf hfp_hsp_process
+0x3ae6 hfp_connected
+0x3af1 hfp_set_content
+0x3af9 hfp_send_redial
+0x3b01 hfp_send_recognition
+0x3b02 send_recognition
+0x3b09 hfp_send_xevent_android
+0x3b0b send_android_bat
+0x3b14 hfp_send_cscs
+0x3b16 send_at_cscs
+0x3b21 hfp_send_nerc
+0x3b23 send_at_nerc
+0x3b2a hfp_send_bia
+0x3b2c send_at_bia
+0x3b3b hfp_send_xapl
+0x3b3d send_at_xapl
+0x3b4c hfp_send_xevent
+0x3b4e send_at_xevent
+0x3b5f hfp_send_android_bat
+0x3b61 send_at_android
+0x3b6f hfp_send_iphone_bat
+0x3b71 send_at_iphone
+0x3b83 hfp_waiting_rfcomm
+0x3b88 hfp_send_feature
+0x3b8c send_at_brsf
+0x3b94 send_0d_common
+0x3b97 hfp_send_receive_info
+0x3b99 send_at_chld
+0x3ba2 hfp_send_enable_cli
+0x3ba4 send_at_clip
+0x3bad hfp_send_enable_call_waiting
+0x3baf send_at_ccwa
+0x3bb8 hfp_send_codecs
+0x3bba send_at_bac
+0x3bc5 send_at_bac_msbc_not_support
+0x3bcc send_at_bcs
+0x3bd8 send_at_common
+0x3bdf hfp_send_indicators
+0x3be1 send_at_cind
+0x3bef hfp_send_curr_status
+0x3bf1 send_at_cind2
+0x3bfd hfp_send_update_status
+0x3bff send_at_cmer
+0x3c11 hfp_send_credit_return
+0x3c15 hfp_check_result_code_start
+0x3c15 hfp_check_result_code_end
+0x3c16 hfp_check_result_code
+0x3c21 hfp_process_rfcomm_packet
+0x3c30 hfp_translate_ascii_to_hex
+0x3c36 hfp_translate_calculate
+0x3c41 hfp_findcomma
+0x3c45 hfp_is_result_error
+0x3c54 hfp_is_result_ring
+0x3c60 hfp_is_result_ciev
+0x3c7c hfp_is_result_cind
+0x3c8d hfp_is_result_cind1
+0x3c90 hfp_is_result_cind1_loopcnt
+0x3ca2 hfp_get_indicator_index
+0x3ca6 hfp_find_double_quote
+0x3ca9 hfp_is_result_cind0
+0x3cab hfp_is_result_cind0_loopcnt
+0x3cb6 hfp_is_result_cind0_loopcnt_end
+0x3cb9 hfp_indicator_service
+0x3cc7 hfp_indicator_battchg
+0x3cd7 hfp_indicator_call_callheld_callsetup
+0x3ce9 hfp_indicator_callsetup
+0x3ceb hfp_indicator_call
+0x3cee hfp_indicator_callheld
+0x3cef hfp_indicator_store
+0x3cf6 hfp_indicator_roam
+0x3d04 hfp_indicator_signal
+0x3d12 hfp_is_result_brsf
+0x3d22 hfp_is_result_chld
+0x3d30 hfp_handler_error
+0x3d35 hfp_is_result_ok
+0x3d3d hfp_result_ok_handle
+0x3d4a hfp_battery_process
+0x3d53 hfp_battery_process_increase
+0x3d56 hfp_battery_clear
+0x3d58 hfp_battery
+0x3d5a hfp_result_ok_cmd
+0x3d61 hfp_hangup
+0x3d61 hfp_vgm_ok
+0x3d63 hfp_vgs_ok
+0x3d65 hfp_ag_feature_ok
+0x3d67 hfp_ag_codecs_error
+0x3d67 hfp_ag_codecs_ok
+0x3d69 hfp_ag_indicators_ok
+0x3d6b hfp_ag_status_ok
+0x3d6d hfp_ag_update_status_ok
+0x3d6f hfp_ag_receive_info_ok
+0x3d71 hfp_ag_enable_clip_ok
+0x3d73 hfp_ag_enable_call_waiting_ok
+0x3d79 hfp_is_result_vgm_vgs
+0x3d86 hfp_vgs_changed
+0x3d8a hfp_vgm_changed
+0x3d8d hfp_is_xapl
+0x3d9d hfp_is_bcs
+0x3daa hfp_is_bcs_20
+0x3daf hfp_set_codec_type_msbc
+0x3db1 hfp_set_codec_type_cvsd
+0x3db3 hfp_is_result_ccwa
+0x3dc1 hfp_is_result_clip
+0x3dd3 hfp_is_result_clip_loop
+0x3dd8 hfp_is_result_clip_phone_num
+0x3dde hfp_is_result_clip_end
+0x3de1 hfp_handle_at_result_code
+0x3e00 hfp_tx_rfcomm_without_credit
+0x3e1f hfp_clear_dac_mem
+0x3e27 hfp_voice_start_notify
+0x3e2b hfp_voice_start
+0x3e37 hfp_voice_start_init_process
+0x3e3b hfp_voice_stop_notify
+0x3e3f hfp_voice_stop
+0x3e45 hfp_voice_stop_init_process
+0x3e4b hfp_get_vol
+0x3e53 hfp_get_max_vol
+0x3e55 hfp_adjust_max_volume
+0x3e58 hfp_adjust_min_volume
+0x3e5b ipc_init
+0x3e6f ipc_clear_mem_block
+0x3e75 ipc_notify_m0_wakeup_flag_init
+0x3e79 ipc_lock_m0_lmp_wait_work_flag
+0x3e7d ipc_check_m0_state
+0x3e82 ipc_100ms_timer_work
+0x3e88 ipc_rx_block_read
+0x3e8d ipc_rx_block_read_end
+0x3e92 ipc_rx_byte_read
+0x3e95 ipc_rx_rptr_loopback
+0x3e9d ipc_rx_items_inquire
+0x3ea4 ipc_check_items
+0x3ea6 ipc_tx_items_inquire
+0x3eae ipc_check_enter_lpm
+0x3ebb ipc_rx_block_clear
+0x3ec6 ipc_tx_wptr_loopback
+0x3ecc ipc_tx_byte_write
+0x3ecf ipc_tx_block_write
+0x3ed4 ipc_tx_block_write_end
+0x3ed9 ipc_check_tx_buf_is_enough
+0x3ee1 ipc_check_tx_buffer_ptr
+0x3ee9 ipc_check_tx_buffer_not_enouth
+0x3eed ipc_rx_process
+0x3ef7 ipc_rx_cmd
+0x3efe ipc_rx_ble
+0x3f16 ipc_rx_ble_discard_packet
+0x3f1a ipc_tx_common
+0x3f28 ipc_tx_bt_event
+0x3f39 ipc_tx_bt_ble_test
+0x3f3b ipc_tx_buffer
+0x3f3d ipc_hfp_evt_received
+0x3f41 ipc_check_ack
+0x3f42 ipc_check_ack0
+0x3f47 l2cap_init
+0x3f48 l2cap_init_work
+0x3f4d l2cap_init_wake
+0x3f6f l2cap_init_queue
+0x3f77 queue_loop
+0x3f7d init_all_queue
+0x3f82 queue_init
+0x3f8d queue_unit_increase
+0x3f94 queue_insert
+0x3fa1 queue_get_read_ptr
+0x3fa5 queue_free
+0x3fa5 queue_delete
+0x3fb4 queue_get_len
+0x3fb7 push_l2cap_queue
+0x3fbd pop_l2cap_queue
+0x3fc1 push_media_queue
+0x3fca pop_media_queue
+0x3fd0 media_queue
+0x3fd8 process_rx_l2cap_pkt
+0x3fe8 process_normal_rx_l2cap_pkt
+0x3ffe process_listen_tws_rx_l2cap_pkt
+0x4006 l2cap_call_proc_signal
+0x400a l2cap_call_proc_sdp
+0x4013 l2cap_call_proc_rfcomm
+0x4017 l2cap_call_proc_no_reply
+0x4019 l2cap_rx_reset_state
+0x401b l2cap_process_signal_pkt
+0x4034 l2cap_proc_signal_info_req
+0x403b l2cap_send_signal_info_req_ext
+0x4046 l2cap_send_signal_info_req_fix
+0x4051 l2cap_proc_signal_cmd_reject
+0x4052 l2cap_proc_signal_connect_req
+0x405f l2cap_check_psm
+0x4067 l2cap_proc_signal_connect_req_allow_psm
+0x4069 l2cap_proc_signal_connect_req_allow_psm2
+0x4075 l2cap_proc_signal_connect_req_avdtp
+0x407c l2cap_prepare_send_connect_res_succ
+0x40a2 l2cap_send_conn_res_refused_no_resources
+0x40a5 l2cap_send_connect_res_succ
+0x40b0 l2cap_send_connect_res_pending
+0x40bc l2cap_send_connect_res
+0x40cc l2cap_proc_signal_connect_rsp
+0x40d8 l2cap_proc_signal_connect_rsp_success
+0x40e6 l2cap_proc_signal_connect_rsp_refused
+0x40ee l2cap_proc_signal_config_req
+0x40fd l2cap_proc_signal_config_res
+0x410d l2cap_proc_signal_config_rsp
+0x4119 l2cap_prepare_send_config_req
+0x4131 l2cap_send_config_req
+0x4144 l2cap_load_channel_param
+0x414e l2cap_proc_signal_disconnect_req
+0x415e l2cap_send_signal_disconnect_res
+0x416b l2cap_proc_signal_disconnect_rsp
+0x4173 l2cap_proc_signal_echo_req
+0x4173 l2cap_send_signal_echo_rsp
+0x417c l2cap_proc_signal_echo_rsp
+0x417d l2cap_proc_signal_info_rsp
+0x417e l2cap_get_req_id
+0x4183 l2cap_get_req_id_ok
+0x4185 l2cap_malloc
+0x418c l2cap_malloc_loop
+0x4194 l2cap_malloc_next
+0x419a l2cap_malloc_rtn
+0x419e l2cap_malloc_fifo_out
+0x41a3 l2cap_malloc_free
+0x41aa l2cap_malloc_discard
+0x41b4 l2cap_malloc_is_fifo_full
+0x41b9 l2cap_malloc_is_fifo_nearly_full
+0x41bb l2cap_malloc_is_fifo_empty
+0x41bd l2cap_malloc_fifo_get_first_ptr
+0x41c1 l2cap_malloc_free_loop
+0x41c5 l2cap_malloc_get_full_map
+0x41c9 l2cap_malloc_get_full_map_loop
+0x41cf l2cap_malloc_into_fifo
+0x41dc l2cap_malloc_into_fifo_no_push
+0x41df l2cap_malloc_into_fifo_loop
+0x41e7 l2cap_malloc_enough
+0x41ec l2cap_malloc_enough_loop
+0x41f7 l2cap_malloc_enough_end
+0x41fd l2cap_malloc_enough_rtn
+0x41ff l2cap_malloc_signal_channel
+0x4205 l2cap_malloc_server_channel
+0x420c l2cap_malloc_sdp_req
+0x4211 l2cap_malloc_sdp_channel
+0x421a l2cap_get_sdp_tx_buff
+0x421c l2cap_get_sdp_tx_payload
+0x421e l2cap_util_pdata_to_contw
+0x4221 l2cap_send_server_conn
+0x4239 l2cap_send_server_disconnct
+0x424a l2cap_create_empty_channel
+0x424d l2cap_create_channel_loop
+0x4252 l2cap_create_channel_rtn
+0x4257 l2cap_destory_channel
+0x425a l2cap_destory_channel_loop
+0x4262 l2cap_destory_channel_rtn
+0x4269 l2cap_check_channel_state
+0x426c l2cap_check_channel_loop
+0x4276 l2cap_check_channel_next
+0x4279 l2cap_check_channel_rtn
+0x427c l2cap_check_channel_loop_fast_loop
+0x427e l2cap_get_channel_info_by_local_cid
+0x4281 l2cap_get_channel_info_local_loop
+0x4289 l2cap_get_channel_info_rtn
+0x428c l2cap_get_channel_info_by_remote_cid
+0x428f l2cap_get_channel_info_remote_loop
+0x4296 l2cap_get_channel_info_by_psm
+0x4298 l2cap_get_channel_info_by_psm_loop
+0x429f l2cap_check_empty_channel_info
+0x42a2 l2cap_get_random_local_cid
+0x42a9 l2cap_get_tws_fix_local_cid
+0x42aa l2cap_get_tws_fix_local_cid_loop
+0x42af l2cap_get_empty_pending_info
+0x42b6 l2cap_get_empty_pending_info_rtn
+0x42b8 l2cap_get_active_pending_info
+0x42bf l2cap_get_active_pending_info_rtn
+0x42c1 l2cap_clear_server_ptr
+0x42c7 l2cap_clear_rfcomm_ptr
+0x42ca l2cap_clear_avr_ptr
+0x42cd l2cap_clear_a2dp_ptr
+0x42d4 l2cap_clear_a2dp_singal_ptr
+0x42d7 l2cap_clear_a2dp_media_ptr
+0x42da l2cap_save_server_ptr
+0x42e0 l2cap_save_rfcomm_ptr
+0x42e2 l2cap_save_avr_ptr
+0x42e5 l2cap_save_a2dp_ptr
+0x42ec l2cap_save_a2dp_media_ptr
+0x42f0 l2cap_clear_nochannel_watchdog
+0x42f2 l2cap_trigger_nochannel_waicthdog
+0x42f6 le_parse_att
+0x4306 le_parse_att_exchange_mtu_request
+0x430e le_parse_att_exchange_mtu_response
+0x430f le_parse_att_find_information_request
+0x4317 le_send_att_find_information_res_loop
+0x4323 le_send_att_find_information_res_write_handle_info
+0x432e le_send_att_find_information_res_next
+0x4330 le_send_att_find_information_res_end
+0x4332 le_parse_att_find_by_type_value_request
+0x433d le_send_att_find_by_type_value_response
+0x4342 le_send_att_find_by_type_value_res_primary
+0x4347 le_send_att_find_primary_search_loop
+0x4357 le_send_att_find_primary_search_loop1
+0x435b le_send_att_error_response_notfound2
+0x435e le_send_att_find_primary_search_end_start_handle_found
+0x4366 le_send_att_find_primary_search_end_ending_handle_found
+0x436c le_send_att_find_primary_search_end
+0x4376 le_parse_att_read_by_type_request
+0x437b le_send_att_read_by_type_response
+0x4383 le_send_att_read_by_type_response_loop
+0x439e le_send_att_read_by_type_response_next_handle
+0x43a0 le_send_att_read_by_type_response_end
+0x43a2 le_send_att_read_by_type_res_found_next
+0x43b0 le_send_att_read_by_type_res_not_characteristic
+0x43b2 le_send_att_read_by_type_res_not_char_loop
+0x43c7 le_send_att_read_by_type_res_not_char_next
+0x43c9 le_send_att_read_by_type_write_properties
+0x43d0 le_send_att_read_by_type_write_uuid
+0x43dc le_parse_att_read_request
+0x43df le_send_att_read_response
+0x43e6 le_send_att_read_response_less
+0x43f0 le_parse_att_read_request_check_pairing
+0x43f3 le_send_att_read_response_error_insufficient_auth
+0x43f9 le_parse_att_read_blob_request
+0x43fb le_send_att_read_blob_response
+0x440b le_send_att_read_blob_response_less
+0x4410 le_parse_att_read_multiple_request
+0x4411 le_parse_att_read_by_group_type_request
+0x441a le_send_att_read_by_group_type_response_loop
+0x442f le_send_att_read_by_group_type_store_write_record
+0x4435 le_send_att_read_by_group_type_store_record
+0x4439 le_send_att_read_by_group_type_next_handle
+0x443b le_send_att_read_by_group_type_end0
+0x443e le_send_att_read_by_group_type_end1
+0x4441 le_send_att_read_by_group_type_end_common
+0x4444 le_send_att_error_response_notfound
+0x4445 le_send_att_error_response
+0x4451 le_parse_att_write_request
+0x4453 le_parse_att_write_command
+0x4455 le_send_att_response
+0x445b le_parse_att_prepare_write_request
+0x445c le_parse_att_execute_write_request
+0x445d le_ipc_tx
+0x446d le_att_parse_write
+0x4476 le_att_deal_write_cont
+0x447f le_att_deal_write_check_characteristic
+0x448a le_att_deal_write_callback
+0x448e le_init_attlist_search
+0x4492 le_att_get_handle_ptr2
+0x4494 le_att_get_handle_loop1
+0x449d le_att_get_handle_ptr_found
+0x44a0 le_att_get_handle_info
+0x44a3 le_att_get_handle_loop
+0x44ac le_att_unfind_handle
+0x44ad le_att_finded_handle
+0x44b6 le_att_check_handle_end
+0x44ba le_att_same_uuid
+0x44bd le_att_same_type
+0x44bf le_att_check_same_common
+0x44c5 le_write_att_record
+0x44ca le_write_att_record_common
+0x44ce le_store_att_record
+0x44d3 le_att_next_handle
+0x44d7 le_att_get_handle_ptr
+0x44db le_send_auto_len_by_mem
+0x44e6 le_clean_att_list_handle_enable
+0x44ec le_att_check_notification_enable
+0x44f8 le_get_search_att_uuid
+0x44fb le_get_search_att_type
+0x44fd le_get_search_common
+0x44ff le_get_search_common2
+0x4503 le_att_malloc_tx_notify
+0x450d le_att_check_notify_switch
+0x450f le_att_check_notify_loop
+0x4514 le_att_clear_notify_switch
+0x4516 le_att_clear_notify_loop
+0x451b le_att_clear_notify
+0x451f le_att_create_notify_switch
+0x4521 le_att_creat_notify_loop
+0x4525 le_att_create_notify
+0x4528 le_att_destroy_notify_pool
+0x452b le_send_update_att_mtu
+0x4533 le_send_update_paramter
+0x4535 le_init_conn
+0x454a le_init_master
+0x4556 le_init_slave
+0x455c le_dispatch
+0x4560 le_conn_dispatch
+0x4566 le_master_dispatch
+0x4576 le_master_disconn
+0x4579 le_slave_dispatch
+0x4582 le_slave_match
+0x458a le_slave_cont
+0x458f le_slave_unsync
+0x4594 le_check_md
+0x4598 le_slave_more_data
+0x459c le_slave_disconn
+0x459e le_disconnect
+0x45a3 le_clear_connection_info
+0x45aa le_got_first_packet
+0x45b4 le_enable
+0x45b8 le_disable
+0x45bd le_prep
+0x45c7 lerx_setfreq
+0x45cd letx_setfreq
+0x45d0 le_setfreq
+0x45dc le_ctf_normal
+0x45df le_ctf_low
+0x45e2 le_ctf_test
+0x45e5 le_sca_map
+0x45f5 le_adv_access
+0x45fc le_setup
+0x4605 le_setup_master
+0x460a le_next_adv_channel
+0x4610 le_context_nexthop
+0x4620 le_nexthop_nowrap
+0x4622 le_calc_channel_map
+0x4626 le_count_channels_loop
+0x4628 le_count_channels_notused
+0x462d le_map_channel
+0x4632 le_map_channel_next
+0x4637 le_map_channel_cont
+0x4639 le_map_channel_loop
+0x463c le_map_channel_skip
+0x4641 le_map_channel_end
+0x4644 le_wait_tx
+0x4647 le_wait_master
+0x464a le_receive_adv
+0x464e le_receive_slave
+0x4653 le_receive_packet
+0x4654 le_receive_rxon
+0x465e le_receive_on_attempt
+0x4665 le_receive_skip
+0x4670 lerx_loop
+0x4674 lerx_nopayload
+0x4682 lerx_nopayload_skip_write_freq
+0x4684 le_transmit_receive_sifs
+0x4686 le_transmit_receive_sifs_notx
+0x468c le_transmit_norx
+0x468e le_transmit
+0x46a3 letr_loop
+0x46a6 letr_nopayload
+0x46ad le_send_adv_ind
+0x46bd le_send_adv_direct_ind
+0x46cd le_send_adv_transmit
+0x46d3 le_send_scan_request
+0x46e4 le_send_scan_response
+0x46f1 le_connect_request
+0x46fb le_con_req_hop_retry
+0x4735 le_init_adv
+0x4737 le_update_param
+0x475a le_update_channel_map
+0x4766 le_acknowledge
+0x4779 le_ack_unenc
+0x477f le_check_wak
+0x4790 le_set_enc
+0x4794 le_clear_enc
+0x479f le_wait_adv
+0x47a5 le_scan
+0x47b3 le_scan_match
+0x47c3 le_create_conn
+0x47d2 le_create_conn_ndongle
+0x47d5 le_scan_check_sender_addr_type
+0x47da le_prepare_tx
+0x47fb le_check_tx_md
+0x4803 le_check_continue
+0x480c le_clear_md
+0x480e le_update_tx_type
+0x4812 le_send_empty
+0x4814 le_send_packet
+0x4826 le_parse
+0x4834 le_parse_l2cap
+0x4840 le_check_l2cap_complete
+0x4844 le_check_l2cap_llid_start
+0x4853 le_check_l2cap_llid_continue
+0x4866 le_parse_ll
+0x4880 le_parse_connection_update_req
+0x4888 le_parse_channel_map_req
+0x4890 le_parse_terminate_ind
+0x4893 le_send_terminate_remote_user_ended_conn
+0x4894 le_send_terminate_ind
+0x489d le_parse_enc_req
+0x48aa le_parse_enc_req_ltk_exist
+0x48aa le_parse_enc_req_after_auth
+0x48ae le_ltk_lost
+0x48b0 le_send_reject_ind
+0x48b8 le_send_enc_rsp
+0x48c8 le_send_start_enc_req
+0x48ca le_send_start_enc_rsp
+0x48cc le_send_ll_one_lenth
+0x48d3 le_parse_enc_rsp
+0x48d8 le_parse_start_enc_req
+0x48dc le_parse_start_enc_rsp
+0x48e1 le_parse_feature_req
+0x48e9 le_parse_pause_enc_req
+0x48ed le_send_pause_enc_rsp
+0x48ef le_parse_version_ind
+0x48f0 le_send_version_ind
+0x48fa le_parse_reject_ind
+0x48fa le_parse_ping_rsp
+0x48fb le_parse_ping_req
+0x48fd le_supervision_update
+0x4906 le_supervision_flush
+0x4909 le_adv
+0x491c le_adv_not_match
+0x4922 le_receive_window_size
+0x4935 parse_connect_req
+0x4964 le_data_send_write_req
+0x4969 le_data_wait_write_res
+0x496a le_data_wait_write_res1
+0x496b le_conn_sm_master
+0x4972 le_lpm_set_mult
+0x4975 le_lpm_set_mult_attempt
+0x4981 le_lpm_lost
+0x4987 le_search_adtype
+0x498a le_search_adtype_loop
+0x4995 le_fifo_malloc_tx_l2cap_signaling
+0x499d le_l2cap_update_signaling_identifier
+0x49a1 le_l2cap_reset_signaling_identifier
+0x49a3 le_fifo_malloc_tx_l2cap
+0x49ab le_fifo_malloc_tx
+0x49b1 le_fifo_malloc_tx_loop
+0x49b6 le_fifo_malloc_tx_got_empty
+0x49bd le_fifo_tx_find_empty_ptr
+0x49bf le_fifo_tx_find_empty_ptr_loop
+0x49c5 le_fifo_tx_found_empty_ptr
+0x49ce le_fifo_get_first_tx_ptr
+0x49d2 le_fifo_get_second_tx_ptr
+0x49d5 le_fifo_get_last_tx_ptr
+0x49d9 le_fifo_get_last_tx_ptr0
+0x49e1 le_fifo_get_first_l2cap_ptr
+0x49e4 le_fifo_get_first_att_ptr
+0x49e7 le_fifo_get_last_att_ptr
+0x49ea le_fifo_get_last_l2cap_ptr
+0x49ed le_fifo_check_full
+0x49ef le_fifo_check_empty
+0x49f1 le_fifo_release_first_node
+0x49fb le_fifo_release_first_node_loop
+0x4a07 le_parse_signaling
+0x4a09 le_l2cap_tx_update_req
+0x4a11 le_pairing_mode_init
+0x4a1a le_set_pairing_mode_secure_justwork
+0x4a1c le_set_pairing_mode_secure_numeric
+0x4a1f le_set_pairing_mode_secure_passkey
+0x4a21 le_set_no_pairing
+0x4a22 le_set_noinputnooutput
+0x4a24 le_set_pairing_mode_lagacy_just_work
+0x4a26 le_set_pairing_mode_lagacy_passkey
+0x4a27 le_set_displayonly
+0x4a29 le_secure_connection_enable
+0x4a2d le_secure_connection_disable
+0x4a31 le_parse_smp
+0x4a40 le_send_smp_security_request
+0x4a48 le_parse_smp_pairing_request
+0x4a57 le_set_tk_0
+0x4a5a le_parse_smp_pairing_req_passkey
+0x4a5c le_genernate_tk
+0x4a63 le_parse_smp_pairing_req_fixed_passkey
+0x4a65 le_check_master_support_secure_connect
+0x4a6a le_send_smp_pairing_response
+0x4a7a le_parse_smp_pairing_confirm
+0x4a81 le_parse_smp_pairing_confirm_secure_passkey
+0x4a87 le_send_smp_pairing_confirm
+0x4a90 le_send_smp_pairing_confirm_sc
+0x4a99 le_parse_smp_pairing_random
+0x4a9f le_send_pairing_confirm_value_failed
+0x4aa0 le_send_pairing_failed
+0x4aa7 le_parse_smp_pairing_failed
+0x4aaa le_smp_pairing_fail_reason_not_support_pairing
+0x4aac le_parse_smp_pairing_random_sc
+0x4ab7 le_parse_smp_pairing_random_sc_passkey
+0x4ac0 le_parse_smp_pairing_random_success
+0x4ac5 le_send_smp_pairing_random
+0x4acc le_parse_smp_encryption_information
+0x4ace le_send_smp_encryption_information
+0x4ad5 le_send_smp_master_identification
+0x4ae2 le_send_smp_identity_information
+0x4aeb le_send_smp_identity_address_information
+0x4af5 le_parse_smp_signing_information
+0x4af5 le_parse_smp_security_request
+0x4af6 le_parse_smp_public_key
+0x4afb le_parse_smp_dhkey_check
+0x4b00 le_send_smp_pairing_public_key
+0x4b07 le_send_smp_pairing_dhkey_check
+0x4b0e le_pairing_sm
+0x4b16 le_pairing_sm_start
+0x4b18 le_pairing_sm_after_auth
+0x4b1b le_pairing_sm_after_auth_start_enc
+0x4b1f le_pairng_sm_send_enc_information
+0x4b21 le_pairng_sm_send_master_indentification
+0x4b26 le_pairng_sm_send_indentity_information
+0x4b28 le_parse_start_enc_rsp_after_auth_end
+0x4b2b le_secure_connect_sm
+0x4b39 le_sc_sm_passkey_wait_confirm
+0x4b43 le_sc_sm_wait_confirm_gkey
+0x4b48 le_sc_confirm_gkey_ok
+0x4b4c le_sc_sm_receive_dhkey
+0x4b50 le_dhkey_ready
+0x4b54 le_dhkey_ready_common
+0x4b5a le_dhkey_check_fail
+0x4b5c le_dhkey_check_ok
+0x4b65 le_sc_sm_send_public_key
+0x4b68 le_sc_sm_ready_send_pairing_confirm
+0x4b69 le_sc_sm_send_public_key_passkey
+0x4b6b le_sc_sm_receive_public_key
+0x4b6f le_public_key_ready
+0x4b72 le_sc_sm_wait_send_public_key
+0x4b75 init_lmp
+0x4b76 init_lmp_work
+0x4b82 init_lmp_reinit
+0x4b88 parse_rx_done
+0x4b89 parse_lmp
+0x4b90 parse_lmp_tws
+0x4b9f parse_lmp_process
+0x4bdc reject_unknown_packet
+0x4bdd reject_lmp_packet
+0x4bdf parse_lmpext_remove_esco_req
+0x4be3 parse_lmpext_esco_link_req_master
+0x4be5 parse_lmpext_esco_link_req
+0x4bff parse_lmpext_esco_link_req_cvsd
+0x4c02 parse_lmpext_esco_link_req_msbc
+0x4c05 parse_lmpext_esco_link_req2
+0x4c08 lmpext_esco_reject
+0x4c09 lmpext_esco_link_req_end
+0x4c0b lmpext_esco_accept_2ev3
+0x4c0c lmpext_esco_accept_ev3
+0x4c0e parse_lmp_sco_link_req
+0x4c1f parse_lmp_sco_link_req_cvsd
+0x4c22 parse_lmp_sco_link_req_msbc
+0x4c24 parse_lmp_sco_link_req_reject
+0x4c27 parse_lmp_sco_link_req2
+0x4c2d lmp_exit_sco_sniff
+0x4c3d parse_remove_sco_link
+0x4c41 parse_quality_of_server_req
+0x4c44 parse_quality_of_server
+0x4c45 parse_lmp_clkoffset_req
+0x4c47 parse_enc_key_size_mask_req
+0x4c49 parse_lmp_set_afh
+0x4c56 parse_lmp_escape
+0x4c69 reject_unknown_ext_packet
+0x4c6c parse_lmpext_chn_classification_req
+0x4c6f parse_lmpext_iocap_req
+0x4c74 parse_lmpext_iocap_res
+0x4c78 iocap_lmpext_load
+0x4c7c iocap_lmpext_hci
+0x4c7c iocap_lmpext_common
+0x4c7f parse_lmpext_accepted
+0x4c86 parse_lmp_accept_remove_sco_link
+0x4c86 parse_lmpext_remove_esco_link
+0x4c87 parse_lmpext_not_accepted
+0x4c8d parse_lmpext_accepted_ptt
+0x4c91 parse_lmpext_not_accepted_ptt
+0x4c97 parse_lmpext_pause_encrypt
+0x4c9a parse_lmpext_pause_encrypt_slave
+0x4c9c parse_lmpext_resume_encrypt
+0x4c9e parse_lmpext_features_req
+0x4ca0 parse_lmpext_features_res
+0x4ca6 parse_lmpext_features_res_not_hci
+0x4caa parse_lmp_accepted
+0x4cbd parse_lmp_not_accepted
+0x4ccb parse_lmp_not_accepted_switch
+0x4ccd parse_lmp_not_accepted_sco_link_req
+0x4ccf parse_lmpext_accepted_esco_link
+0x4cd2 send_lmpext_accept_esco_link
+0x4cd3 send_lmp_accepted_sco_link
+0x4cd3 parse_lmp_accepted_sco_link
+0x4cd4 lmp_enter_sco_sniff
+0x4cd9 lmp_enter_sco_sniff0
+0x4ce2 lmp_enter_sco_sniff_end
+0x4cee parse_lmp_accepted_switch
+0x4cef parse_lmp_accepted_hostconn
+0x4cf6 parse_lmp_not_accepted_hostconn
+0x4cfc parse_lmp_accepted_inrand
+0x4d03 parse_lmp_accepted_enc_mode
+0x4d09 parse_lmp_accepted_enc_keysize
+0x4d0a parse_lmp_accepted_start_enc
+0x4d11 parse_lmp_accepted_stop_enc
+0x4d12 parse_lmp_not_accepted_aurand
+0x4d22 parse_lmp_not_accepted_aurand_send_detach
+0x4d27 parse_lmp_not_accepted_inrand
+0x4d2d parse_lmp_inrand_key_missing
+0x4d32 parse_lmp_not_accepted_name_req
+0x4d33 parse_lmp_not_accepted_simple_pairing_number
+0x4d36 parse_lmp_not_accepted_dhkey_check
+0x4d39 parse_lmp_not_accepted_unsniff_req
+0x4d3a parse_lmp_accepted_unsniff_req
+0x4d3b parse_lmp_accepted_sniff_req
+0x4d3c parse_lmp_not_acdcept_sniff_req
+0x4d3d parse_lmp_crypt_key
+0x4d40 parse_lmp_setup_complete
+0x4d46 parse_lmp_max_slot
+0x4d47 parse_lmp_max_slot_req
+0x4d4f parse_lmp_detach
+0x4d51 accept_lmp_msg
+0x4d53 parse_lmp_incr_power
+0x4d55 parse_lmp_decr_power
+0x4d57 parse_lmp_version_res
+0x4d59 parse_lmp_auto_rate
+0x4d5a parse_lmp_in_rand
+0x4d60 parse_lmp_in_rand_hci
+0x4d67 parse_lmp_inrand_res
+0x4d6b pop_tid_follow
+0x4d6f push_tid_follow
+0x4d73 parse_lmp_au_rand
+0x4d80 parse_lmp_au_rand_1
+0x4d81 parse_lmp_inrand_sres
+0x4d85 parse_lmp_sres
+0x4d8e authentication_ok
+0x4d95 authentication_ok_conn_sm
+0x4d9a authentication_ok_common
+0x4da1 parse_lmp_comb_key
+0x4dab parse_lmp_name_res
+0x4dbb parse_lmp_name_res_end
+0x4dc0 parse_lmp_name_req
+0x4dc4 parse_lmp_conn_req
+0x4dc5 parse_lmp_timing_accuracy_req
+0x4dc7 parse_lmp_features_req
+0x4dc9 parse_lmp_version_req
+0x4dcb parse_lmp_supervision_timeout
+0x4dcc parse_lmp_sniff_subrating_req
+0x4dda parse_lmpext_packet_type_table_req
+0x4de5 parse_lmp_sniff_subrating_res
+0x4de6 parse_lmp_max_power
+0x4de7 parse_lmp_min_power
+0x4de8 parse_lmp_page_mode_req
+0x4de9 parse_lmp_page_scan_mode_req
+0x4dea parse_lmp_preferred_rate
+0x4deb parse_lmp_slot_offset
+0x4dee parse_lmp_sniff_req
+0x4dff parse_lmp_sniff_request
+0x4e0d set_big_value_to_attempt
+0x4e10 lmp_reject_sniff
+0x4e12 parse_lmp_start_encryption_req
+0x4e18 parse_lmp_stop_encryption_req
+0x4e1a parse_lmp_switch_req
+0x4e21 parse_lmp_switch_req_not_accept
+0x4e25 parse_lmp_switch_req_clear_mark
+0x4e28 parse_lmp_switch_accept
+0x4e2e parse_lmp_temp_rand
+0x4e2f parse_lmp_temp_key
+0x4e30 parse_lmp_timing_accuracy_res
+0x4e31 parse_lmp_unit_key
+0x4e32 parse_lmp_unsniff_req
+0x4e34 lmp_exit_acl_sniff
+0x4e39 parse_lmp_use_semi_permanend_key
+0x4e3a parse_lmp_encapsulated_header
+0x4e43 parse_lmp_encapsulated_header_master
+0x4e46 parse_lmp_encapsulated_header_reject
+0x4e48 parse_lmp_accepted_encapsulated_header
+0x4e4a parse_lmp_accepted_simple_pairing_number
+0x4e4d parse_lmp_accepted_simple_pairing_number_common
+0x4e51 parse_lmp_accepted_simple_pairing_number_ssp_pin
+0x4e55 parse_lmp_accepted_simple_pairing_number_passkey
+0x4e5b authentication_passkey
+0x4e65 authentication_passkey_end
+0x4e67 parse_lmp_accepted_dhkey_check
+0x4e68 pairing_success
+0x4e6d parse_lmp_accepted_dhkey_check_common
+0x4e75 parse_simple_pairing_confirm
+0x4e7b parse_lmp_encapsulated_payload
+0x4e7f parse_encapsulated_payload_master
+0x4e8c parse_lmp_encapsulated_payload_completed
+0x4e92 parse_lmp_encapsulated_payload_reject
+0x4e94 parse_lmp_accepted_encapsulated_payload
+0x4e98 parse_lmp_encapsulated_payload_all_accepted
+0x4e9f parse_lmp_encapsulated_payload_all_accepted_get_passkey
+0x4ea1 parse_lmp_encapsulated_payload_all_accepted_master
+0x4ea2 parse_lmp_simple_pairing_number
+0x4ea6 parse_lmp_simple_pairing_number_master
+0x4eb0 parse_lmp_simple_pairing_number_master0
+0x4eb2 parse_lmp_simple_pairing_number_reject
+0x4eb4 parse_dhkey_check
+0x4eb8 parse_dhkey_check_master
+0x4ebf number_comparison_successed
+0x4ec4 parse_dhkey_check_master0
+0x4ec7 parse_lmp_dhkey_check_reject
+0x4ec9 number_comparison_mode
+0x4ece comparison_result
+0x4ed1 parse_lmp_clkoffset_res
+0x4ed2 parse_lmp_encryption_mode_req
+0x4edd parse_lmp_features_res
+0x4ee1 parse_lmp_features_res_not_hci
+0x4ee7 parse_lmp_feature_ext_sm
+0x4ee9 parse_lmp_send_conn
+0x4eeb parse_lmp_test_activate
+0x4ef0 parse_lmp_test_control
+0x4ef5 parse_lmp_test_xor
+0x4f09 parse_lmp_test_control_exit
+0x4f0e parse_lmp_test_control_pattern
+0x4f15 parse_lmp_test_control_loopback_nowhite
+0x4f16 parse_lmp_test_control_loopback
+0x4f22 parse_lmp_test_control_pause
+0x4f28 check_test_cond
+0x4f49 check_test_exit
+0x4f51 lmp_copy_rand
+0x4f54 lmp_generate_key
+0x4f56 lmp_start_encryption
+0x4f59 lmp_accept_inrand
+0x4f5e lmp_disconnect
+0x4f62 send_lmp
+0x4f9b send_lmp_error
+0x4f9d send_lmp_escape
+0x4fab send_lmpext_esco_req
+0x4faf send_lmpext_esco_req_master
+0x4fb0 send_lmpext_esco_req_slave
+0x4fb3 send_lmpext_esco_req_2ev3
+0x4fbb send_lmpext_esco_req_ev3
+0x4fc2 send_lmpext_esco_req_end
+0x4fdf send_lmpext_remove_esco
+0x4fe8 send_lmpext_ping_req
+0x4feb send_lmp_accepted
+0x4ffb send_lmp_accept_remove_sco_link_req
+0x4ffc send_lmp_accept_sniff_req
+0x4ffc lmp_enter_acl_sniff
+0x5009 send_lmp_not_accepted
+0x5011 send_not_accept_aurand
+0x5016 send_remove_esco_link
+0x5017 send_lmpext_accepted
+0x5024 send_lmpext_not_accepted
+0x502e send_lmp_accepted_inrand
+0x5032 send_lmp_accepted_enc_mode
+0x5039 send_lmp_accepted_enc_start
+0x503b send_lmp_accepted_enc_exit
+0x503d send_lmp_accepted_enc_key
+0x5040 send_lmp_accepted_connection
+0x5045 send_lmp_accept_dhkey_check
+0x5046 send_lmpext_features_res
+0x5051 send_lmpext_io_cap_res
+0x505c responder_iocap_keyboard_only
+0x5062 responder_iocap_display_yesno
+0x5068 responder_iocap_no_input_no_output
+0x506e responder_iocap_no_input_no_output_initiator_iocap_no_input_no_output
+0x506e set_ssp_mode_justwork
+0x5072 responder_iocap_display_yesno_initiator_iocap_display_yesno
+0x5072 set_ssp_mode_numeric_comparison
+0x5074 responder_iocap_display_yesno_initiator_iocap_keyboard_only
+0x5074 set_ssp_mode_passkey
+0x5076 classic_bt_set_reject_justwork_flag
+0x5078 classic_bt_clr_reject_justwork_flag
+0x507a classic_bluetooth_set_flag
+0x507e classic_bluetooth_clr_flag
+0x5082 send_lmp_io_cap_req
+0x5087 send_lmpext_sniff_subrating_req
+0x5088 send_lmpext_sniff_subrating_res
+0x5091 send_lmp_name_res
+0x5099 send_lmp_name_res_offset_ok
+0x50a1 send_lmp_timing_accuracy_res
+0x50a6 send_lmp_clkoffset_res
+0x50ac send_lmp_clkoffset_res_master
+0x50b0 send_lmp_version_res
+0x50b5 send_lmp_features_res
+0x50ba send_lmpext_features_req
+0x50c5 send_lmpext_packet_type_table_req
+0x50d1 ssp_enable
+0x50d7 ssp_disable
+0x50dd afh_init
+0x50e7 afh_open_all_channels
+0x50eb afh_open_classify_map
+0x50f1 afh_reset_map
+0x50f8 afh_clear_error_counter
+0x50fb afh_set_send_flag
+0x50ff send_set_afh
+0x511f send_lmpext_pause_encryption_req
+0x5123 send_lmp_detach
+0x5128 prepare_disconnect
+0x512d send_lmp_no_payload
+0x5130 send_lmp_host_connection_req
+0x5136 send_lmp_nopayload_reply
+0x5139 send_lmp_sco_link_req
+0x513e send_lmp_sco_link_master
+0x5157 send_lmp_remove_sco_link_req
+0x515e send_lmp_encryption_mode_req
+0x5166 send_lmp_superto
+0x516b send_lmp_name_req
+0x5171 send_lmp_test_control
+0x5175 send_lmp_test_control_loop
+0x517a send_lmp_quality_of_service_req
+0x517b send_lmp_unit_key
+0x517c send_lmp_slot_offset
+0x518d send_lmp_slot_offset_reply
+0x5191 send_lmp_switch_req
+0x5195 switch_on_native
+0x5196 switch_slack
+0x51a0 send_lmp_sniff_req
+0x51a6 send_lmp_timing_accuracy_req
+0x51ab send_lmp_unsniff_req
+0x51ae send_lmp_max_slot
+0x51b3 send_lmp_max_slot_req
+0x51b8 send_lmp_setup_complete
+0x51c6 send_lmp_setup_complete_has_sent
+0x51c8 send_lmp_version_req
+0x51cd send_lmp_features_req
+0x51d2 sp_master_send_io_cap_get
+0x51d7 sp_master_send_io_cap_get_hci
+0x51d9 sp_master_send_io_cap_send
+0x51dd sp_master_send_lmp_encapsulated_header
+0x51e1 sp_master_commitment_compare
+0x51eb sp_master_commitment_compare_success
+0x51ef sp_master_send_lmp_simple_pairing_number
+0x51f1 sp_send_lmp_encapsulated_header
+0x51f3 send_lmp_encapsulated_header
+0x51ff send_lmp_encapsulated_payload
+0x520e sp_send_lmp_simple_pairing_comfirm
+0x5211 send_lmp_simple_pairing_comfirm
+0x5219 sp_send_lmp_simple_pairing_number
+0x521c send_lmp_simple_pairing_number
+0x5228 master_sp_sm_end
+0x5229 sp_aurand_send
+0x522e master_sp_send_lmp_dhkey_check
+0x522f sp_send_lmp_dhkey_check
+0x5231 send_lmp_dhkey_check
+0x523b send_lmp_enc_key_size_mask_res
+0x5240 send_lmp_auto_rate
+0x5241 send_lmp_clkoffset_req
+0x5242 send_lmp_quality_of_service
+0x5243 send_lmp_test_activate
+0x5244 send_incr_power_req
+0x5249 send_lmp_comb_key
+0x5253 send_lmp_inrand
+0x5256 send_lmp_rand
+0x525b send_lmp_aurand
+0x5261 send_lmp_aurand_notpairing
+0x5262 send_lmp_aurand_common
+0x5264 send_lmp_sres
+0x5273 send_lmp_sres_master
+0x5275 send_lmp_sres_startenc
+0x5279 send_lmp_sres_startenc_slave
+0x527d send_lmp_start_encryption
+0x5284 send_lmp_stop_encryption_req
+0x5287 send_lmp_encryption_key_size_req
+0x528d msg_send_lmp
+0x5295 send_lmpext
+0x529b send_lmp_follow
+0x52a1 send_lmp_tid
+0x52a4 send_lmp_reply
+0x52a6 send_lmp_request
+0x52a7 send_lmp_end
+0x52ab send_lmp_exit
+0x52b0 lmo_fifo_process
+0x52b5 lmo_fifo_process_lmo0empty
+0x52bf lmo_fifo_process_lmo2to1
+0x52c5 lmo_fifo_process_lmo1_empty
+0x52d0 special_tid_store
+0x52d6 tid_reply
+0x52da tid_initiate
+0x52de tid_check
+0x52e3 tid_set_reply
+0x52e7 check_localsm
+0x52ea setlocalsm_master
+0x52ee setlocalsm_slave
+0x52f2 check_localsm_master
+0x52f6 generate_random_number
+0x52f7 generate_random
+0x52f8 generate_random_another
+0x52f8 generate_random_loop
+0x52fc generate_linkkey
+0x5306 process_conn_sm
+0x530b process_conn_sm_continue
+0x5321 host_conn_judge_encrypt
+0x5325 host_creat_conn_send_feat_ext
+0x5328 host_creat_conn_send_auth
+0x532a host_creat_after_host_conn
+0x532c host_auth_remote_dev
+0x5333 host_sm_done
+0x5335 host_create_conn_send_features
+0x5338 host_create_conn_send_conn_req
+0x533c host_create_conn_wait_accept
+0x5341 host_create_conn_waiting
+0x5342 host_create_conn_switch
+0x534e host_create_conn_wait_switch
+0x534f host_create_conn_wait_switch_end
+0x5353 host_create_conn_wait_send_auth
+0x5359 host_create_conn_send_setup_complete
+0x535c host_create_conn_wait_setup_complete
+0x5360 host_create_conn_encrypt
+0x5363 host_create_conn_encrypt_start
+0x5368 host_create_conn_encrypt_wait
+0x536c host_create_conn_encrypt_wait_clear
+0x536e host_auth
+0x5373 remote_auth
+0x5379 pincode_reinit
+0x537f twspi_reset
+0x5380 twspi_write
+0x5381 twspi_read
+0x5382 read_enc
+0x5385 read_unenc
+0x5386 read_function
+0x5389 read_fuction_zero
+0x538b get_block_header
+0x538c get_block_header0
+0x5393 get_block_header_efuse
+0x5394 get_block_header0_efuse
+0x539c read_first_eep_block
+0x53a6 read_first_flash_block
+0x53b4 update_start_addr
+0x53b7 get_iv
+0x53bf load_storage
+0x53c9 load_storage_loop
+0x53cf load_storage_efuse
+0x53db load_storage_efuse_loop
+0x53e5 reload_eeprom
+0x53ea reload_eeprom_loop
+0x53f3 loadcode
+0x53f5 loadcode_lpm
+0x5405 loadcode_efuse
+0x540d loadcode_spi
+0x5422 loadcode_spi_not_match
+0x5424 loadcode_iic
+0x5427 loadcode_noenc
+0x5436 loadcode_iic_eeprom_2k
+0x543e loadcode_hci
+0x5447 loadcode_hci_loop
+0x5448 loadcode_iic_by_eeprom
+0x544e set_ucode_status
+0x5455 decrypt_code
+0x5457 decrypt_code_loop
+0x545e translate_mram
+0x5462 save_ucode
+0x546b save_ucode_loop
+0x5470 load_ucode
+0x5479 load_ucode_loop
+0x547e load_ucode_efuse
+0x5486 load_ucode_efuse_loop
+0x548b spid_init
+0x5497 spid_reset
+0x549d spid_write_reg
+0x54a4 spid_read_reg
+0x54a5 spid_read_regs
+0x54ad wait_spid_done
+0x54b0 qspi_init_set
+0x54b5 qspi_gpio_init
+0x54b9 qspi_check_gpio_init
+0x54bd qspi_gpio_init_defualt
+0x54c2 qspi_gpio_defualt_set0
+0x54c4 qspi_gpio_init_defualt1
+0x54cc qspi_gpio_init_defualt2
+0x54d4 qspi_gpio_init_defualt3
+0x54dc qspi_gpio_set
+0x54ee qspi_gpio_clear
+0x54fb qspi_unlock_flash
+0x5504 qspi_write_flash
+0x5513 qspi_read_for_loadcode
+0x5516 qspi_read_flash_raw
+0x5521 qspi_read_flash_wait
+0x5525 qspi_decryption_loop
+0x5529 qspi_no_decryption
+0x5538 wait_qspi_done
+0x553b qspi_release_powerdown_flash
+0x554f qspi_powerdown_flash
+0x555c qspi_mmode
+0x5560 qspi_nmode
+0x5564 mqspi_read
+0x5589 qspi_read
+0x55ab qspi_write
+0x55b8 qspi_write_loop
+0x55cf qspi_write_end
+0x55d4 qspi_write_page
+0x55d6 qspi_sector_earse_flash
+0x55e9 qspi_wait_write_flash
+0x55fa iicd_init_20clk
+0x5601 iicd_init_30clk
+0x5608 iicd_init_pin_defualt
+0x560b iicd_init_pin
+0x5615 iicd_init_pin_clear
+0x561a wait_iicd_done
+0x561d iicd_read_data
+0x5627 set_eeprom_size_2k
+0x562a clear_eeprom_size_2k
+0x562d iicd_read_eep_data_size_2k
+0x5631 iicd_read_eep_size_2k_loadcode
+0x5634 iicd_read_eep_size_2k
+0x5639 iicd_read_eep_data
+0x563f iicd_read_eep
+0x5645 iicd_read_eep_common
+0x565a iicd_read_eep_load_code_size_2k
+0x565f iicd_write_eep_data
+0x5665 iicd_write_eep_loop
+0x5674 iicd_eep_transparency
+0x5685 iicd_eep_deal_short_packet
+0x568a iicd_write_eep_size_2k
+0x5693 iicd_write_eep
+0x56a0 iicd_write_eep_common
+0x56a7 iic_check_eeprom_standby
+0x56a8 iic_check_eeprom_standby_wait
+0x56bd efuse_read_data
+0x56c2 efuse_read_loop
+0x56ce efuse_program
+0x56d3 efuse_program_loop
+0x56d5 efuse_program_bit_loop
+0x56e4 efuse_program_enable
+0x56e5 efuse_program_enable2
+0x56e9 efuse_program_disable
+0x56eb efuse_program_bit
+0x56f1 efuse_read_code
+0x56f6 efuse_read_code_loop
+0x5701 uartd_rx_cnt_got_first_byte
+0x5705 uartd_rx_cnt_with_threshold
+0x5711 uartd_rx_cnt_rtn_value
+0x5716 uartd_prepare_tx
+0x571a uartd_send
+0x571c uartd_prepare_rx
+0x5723 uartd_rxdone_by_len
+0x5726 uartd_rxdone
+0x5728 uart_set_baud_by_mem
+0x572b uart_copy_tx_bytes
+0x572d uart_copy_tx_bytes_loop
+0x5731 wait_uarttx
+0x5734 send_mem_to_uart
+0x5737 send_mem_to_uart0
+0x573a gpio_set_wake_by_current_state
+0x573d gpio_set_wake
+0x5748 gpio_clr_wake
+0x5753 gpio_config_input_nowake
+0x5755 gpio_config_input
+0x5756 gpio_config_input_without_wake
+0x575c gpio_get_bit
+0x5766 gpio_get_bit_reverse
+0x5768 gpio_out_inactive
+0x576a gpio_out_active
+0x576b gpio_out_flag
+0x576e gpio_out
+0x5773 gpio_check_active
+0x5778 gpio_check_active_high
+0x577a gpio_set_analog
+0x577c gpio_write
+0x577e gpio_pd_idle
+0x5780 gpio_pd_idle_loop
+0x5785 gpio_pd_idle_configured
+0x5787 gpio_addr
+0x578b gpio_config_param
+0x578e gpio_config_function
+0x578f gpio_config_function_int
+0x5794 gpio_get_config
+0x5799 gpio_config_uart
+0x57a5 gpio_config_uartb
+0x57b1 set_pwm_blink
+0x57b6 set_pwm_steadyon
+0x57bb set_pwm_off
+0x57bf enable_xip
+0x57ca enable_xip_patch
+0x57d1 enable_xip_cont
+0x57d4 xip_status
+0x57d7 reset_xip1
+0x57dd reset_xip2
+0x57e4 read_m0_dhcsr
+0x57e8 check_m0_qspi_lock_and_pause
+0x57ed check_m0_qspi_continue
+0x57f1 wait_m0_lock_qspi
+0x57f5 m0_continue
+0x57fa m0_pause
+0x57fe m0_pause_delay
+0x5800 m0_pause_write_scs
+0x5801 m0_set_dhcsr
+0x5804 write_scs
+0x5805 write_scs_loop
+0x5808 wait_scs
+0x580b read_scs
+0x580d load_le_ltk
+0x5818 soft_dma_table_init
+0x5822 soft_dma_table_init_loop
+0x5826 soft_dma_table_unit_set
+0x5832 soft_dma_get_table_unit_addr
+0x5837 soft_dma_add_task
+0x5843 soft_dma_check_work_ready
+0x5845 get_full_mram_addr
+0x5849 get_full_sram_addr
+0x584d zcode_entrance
+0x5866 zcode_entrance0
+0x586b zcode_run
+0x586d saradc_check_gpio
+0x5873 saradc_check_vinlpm
+0x5875 saradc_check_hvin
+0x5876 saradc_enable
+0x587e saradc_disable_sum
+0x5882 saradc_diable
+0x5886 saradc_read_hvin_timer
+0x5889 saradc_enable_hvin
+0x588d saradc_read_hvin_wait
+0x5895 saradc_read_hvin_wait_check_clk
+0x5898 saradc_read_hvin_start_timer
+0x589c m0_sco_data_buffer_init
+0x58a7 m0_sco_tx_data_pop
+0x58b9 m0_sco_tx_data_pop_0x55
+0x58ba m0_sco_tx_check_have_packet
+0x58c0 m0_sco_tx_data_get_fifo_unit_addr
+0x58c6 m0_sco_tx_update_rptr_loopback
+0x58ca m0_sco_rx_data_push
+0x58dc m0_sco_rx_update_wptr_loopback
+0x58e0 m0_sco_rx_data_get_fifo_unit_addr
+0x58e5 m0_sco_rx_reserve_buffer_size
+0x58e8 m0_sco_rx_use_buffer_size
+0x58f0 wdt_kick_watchdog_max
+0x58f2 wdt_kick_watchdog_100ms
+0x58f4 wdt_kick_watchdog_500ms
+0x58f6 wdt_kick_watchdog_1_5s
+0x58f8 wdt_set_watchdog_mode_interrupt
+0x58fc wdt_set_watchdog_mode_reset
+0x5900 wdt_disable_watchdog
+0x5904 wdt_enable_watchdog
+0x5908 wdt_init_reset_with_start
+0x590a wdt_init_interrupt_with_start
+0x590c rfc_init
+0x590d rfc_reinit
+0x5914 l2cap_rfc_process
+0x5924 rfc_parse_signal_sabm
+0x592d rfc_parse_signal_ua
+0x5931 rfc_parse_signal_packet
+0x5938 rfc_parse_signal_uih
+0x5941 rfc_parse_signal_cmd_pn
+0x5948 rfc_parse_signal_res_pn
+0x594d rfc_get_sigal_pn_param
+0x595e rfc_get_signal_ms_param
+0x5966 rfc_get_uih_head_struct
+0x596e rfc_get_frame_len
+0x5977 rfc_parse_signal_cmd_ms
+0x597e rfc_parse_signal_res_ms
+0x5983 rfc_parse_server_packet
+0x5988 rfc_parse_sever_uih
+0x598b rfc_parse_server_ua
+0x5993 rfc_parse_server_ua_disc
+0x5996 rfc_parse_server_sabm
+0x59aa rfc_parse_server_uih_credits
+0x59b2 rfc_parse_server_uih
+0x59ba parse_uih_spp_uih_cont0
+0x59bd rfc_send_uih_credit
+0x59c2 rfc_parse_sverver_disconnect
+0x59c8 rfcomm_rx_process_end
+0x59c9 rfc_prepare_send_signal_ms
+0x59d4 rfc_send_signal_ms_cmd
+0x59db rfc_org_signal_ms
+0x59ea rfc_send_ua
+0x59f3 rfc_send_signal_res_pn
+0x5a0a rfc_send_modem_status_res
+0x5a1d rfc_send_uih_without_payload
+0x5a2d rfcomm_increase_credit_given
+0x5a33 rfc_tx_write_length
+0x5a3a rfc_tx_write_long_packet
+0x5a43 rfc_tx_write_given_credit
+0x5a47 rfc_send_signal_cmd_pn
+0x5a63 rfc_send_signal_sabm
+0x5a68 rfc_send_server_sabm
+0x5a6f rfc_send_sabm
+0x5a78 rfc_send_server_disc
+0x5a80 rfc_send_signal_disc
+0x5a83 rfc_send_disc
+0x5a8c rfcomm_calculate_fcs_disc
+0x5a98 rfcomm_calculate_fcs_sabm
+0x5aa4 rfcomm_calculate_fcs_ua
+0x5aad rfcomm_calculate_fcs_dlci0
+0x5ab1 rfcomm_calculate_fcs_dlci0_res
+0x5ab3 rfcomm_save_fcs_uih
+0x5ac2 caculate_uihdata_fcs
+0x5ace caculate_fcs
+0x5adb mod2div
+0x5adf mod2div_loop
+0x5ae4 mod2div_not_enough_reduction
+0x5aee mod2div_end
+0x5af0 rfc_get_rfcomm_snd_adss
+0x5af1 rfc_dlci_to_address_cmd
+0x5af7 dlci_to_address_res
+0x5afc channel_to_dlci
+0x5b00 set_cr_bit
+0x5b02 scheduler_process
+0x5b1c handle_avrcp
+0x5b20 scheduler_tx_l2cap_pkt
+0x5b2e scheduler_tx_l2cap_cont_pkt
+0x5b3a scheduler_tx_l2cap_start_pkt
+0x5b44 scheduler_tx_l2cap_last_pkt
+0x5b46 scheduler_tx_l2cap_pkt_end
+0x5b4a sdp_process
+0x5b64 sdp_process_ss_req
+0x5b83 ss_req_loop
+0x5b86 ss_req_blank
+0x5b8b sdp_process_sa_req
+0x5b95 sa_isnot_wholerange
+0x5b98 sa_judge_wholerange
+0x5ba1 sa_judge_wholerange_false3
+0x5ba3 sa_judge_wholerange_false2
+0x5ba5 sa_judge_wholerange_false1
+0x5ba7 sa_req_loop
+0x5bab sa_req_range
+0x5bb1 sa_req_range_id_increase
+0x5bba sa_req_range_id_finish
+0x5bbd sa_req_one_id
+0x5bc2 sa_req_check_next_id
+0x5bc9 sa_req_handle_attributelist_next
+0x5bd9 sa_req_handle_attributelist_notfound
+0x5bdc sa_req_handle_attributelist_end
+0x5be1 sdp_store_continue_common
+0x5be5 sdp_store_continue_0byte
+0x5be7 sdp_store_continue_1byte
+0x5bea sdp_store_continue_2byte
+0x5bed sdp_store_continue_end
+0x5bef sa_req_all
+0x5c11 sa_req_all_fisrt_fragment
+0x5c15 sa_req_all_parlength_continue_byte
+0x5c18 sa_req_all_parlength_continue_byte_end
+0x5c1e sa_req_all_fragment_sdp
+0x5c2b sa_req_all_answer_attributelist_full_loop
+0x5c34 sa_req_all_last_frag_continue
+0x5c36 sa_req_all_frag_end
+0x5c38 sdp_process_ssa_req
+0x5c41 ssa_req_loop
+0x5c52 ssa_req_attributelist_next
+0x5c5e ssa_req_attributelist_notfound
+0x5c60 ssa_req_attributelist_end
+0x5c65 sdp_store_maxbyte
+0x5c6d ssa_req_range
+0x5c7d ssa_req_range_find_handle
+0x5c85 ssa_req_range_later_freg_with_continue
+0x5c8d ssa_req_range_send_not_maxbyte
+0x5c94 ssa_req_range_maxbyte_with_continue
+0x5c97 ssa_req_range_maxbyte_with_continue_cpy
+0x5c9d ssa_req_range_next_handle
+0x5ca2 ssa_req_range_get_length
+0x5cab ssa_req_range_first_freg
+0x5cb5 ssa_req_range_firstfreg_not_maxbyte_with_continue
+0x5cb7 ssa_req_range_freg_no_continue
+0x5cb9 ssa_req_range_lastfreg
+0x5cba ssa_req_range_lastfreg_common
+0x5cc5 ssa_req_range_firstfreg_maxbyte_with_continue
+0x5cca ssa_req_range_attrbutes_length
+0x5cd0 ssa_req_range_attrbutes_length_no_continue
+0x5cd6 ssa_req_range_freg_with_continue
+0x5ce6 ssa_req_range_common
+0x5cf0 sdp_process_ssa_res
+0x5cf1 sdp_process_ss_res
+0x5cfd sdp_process_sa_res
+0x5d07 sdp_process_error_res
+0x5d08 attribute_reading
+0x5d13 skp2bytes
+0x5d17 is032
+0x5d1a is016
+0x5d1c rduuid1
+0x5d26 rduuid2
+0x5d2f not16by
+0x5d43 unsign8
+0x5d46 unsign4
+0x5d49 unsign2
+0x5d4c unsign1
+0x5d4f rduuid3
+0x5d55 rdnortn
+0x5d57 sdp_invalid_service_record_handle
+0x5d5a sdp_invalid_pdu_size
+0x5d5d sdp_insufficient_resource
+0x5d60 sdp_invalid_request_syntax
+0x5d62 sdp_error_response
+0x5d6c ask_serviceclassid
+0x5d71 classidloop
+0x5d7a skip2bytes
+0x5d83 frstbwrong
+0x5d86 scndbwrong
+0x5d8f cmp032
+0x5d92 cmp016
+0x5d94 cmpuuid
+0x5d9a uuidsize
+0x5db5 wrong12b
+0x5db6 wrong12b1
+0x5dba chck12dn
+0x5dbc loopornot
+0x5dc1 asksrv_error
+0x5dc3 dataelementtype6
+0x5dd1 dsize32
+0x5dd3 dsize16
+0x5dd6 dsize
+0x5dd8 dsize_error
+0x5dda ss_empty_rsp
+0x5ddd sa_empty_rsp
+0x5de0 ssa_empty_rsp
+0x5de2 empty_response
+0x5df0 fullsearch
+0x5df2 outempty
+0x5df4 sdp_data_len
+0x5dfb sdp_get_data
+0x5dff sdp_get_data_type0
+0x5e02 sdp_get_data_type_not0_sizeindex01234
+0x5e05 sdp_get_data_type_not0
+0x5e0c sdp_get_data_type_not0_sizeindex5
+0x5e0f sdp_get_data_type_not0_sizeindex6
+0x5e13 sdp_get_data_type_not0_sizeindex7
+0x5e1b search_all_uuid
+0x5e1f search_all_uuid_llop
+0x5e26 search_uuid
+0x5e2a search_uuid_next
+0x5e30 search_uuid_loop
+0x5e34 search_uuid_not_found
+0x5e3a search_uuid_check_same_handle
+0x5e40 search_uuid_store_handle
+0x5e47 search_uuid_nomatch
+0x5e4b search_handle
+0x5e4e search_handle_loop
+0x5e60 search_attrib
+0x5e63 search_attrib_next
+0x5e66 search_attrib_loop
+0x5e6e search_attrib_found_uuid
+0x5e74 search_attrib_loop_attribs
+0x5e7e search_attrib_end
+0x5e81 search_handle_attrib
+0x5e84 search_handle_attrib_next
+0x5e90 search_handl_attrib_found_handle
+0x5e92 search_handle_attrib_loop_attribs
+0x5e9c search_handle_attrib_end
+0x5e9e search_rfcomm_cn
+0x5ea9 search_uuid_in_data
+0x5eac search_uuid_in_data_loop
+0x5ebc search_uuid_in_data_found_element_index5
+0x5ebf search_uuid_in_data_found_element_index6
+0x5ec2 search_uuid_in_data_found_element_index7
+0x5ec5 search_uuid_in_data_found_uuid
+0x5ecb search_uuid_in_data_type_uuid_128
+0x5ecc search_uuid_in_data_type_uuid_32
+0x5ece search_uuid_in_data_type_uuid_16
+0x5ed4 sdp_send_search_req
+0x5ee8 sdp_send_attribute_req
+0x5f00 sdp_send_spp_request
+0x5f17 function_g2
+0x5f2e function_f6_eb
+0x5f3e get_r
+0x5f42 function_f6_ea
+0x5f54 function_f5
+0x5f66 function_f5_common
+0x5f77 store_addr_common_b
+0x5f7c store_addr_common_a
+0x5f81 function_f4_ca
+0x5f8c function_f4_cb
+0x5f97 function_aes_cmac
+0x5f9a function_ceil16
+0x5fa8 function_aes_cmac_set_flag_0_balnk
+0x5fab function_aes_cmac_set_flag_0
+0x5fac function_aes_cmac_set_flag_0_common
+0x5fb6 function_aes_cmac_aes
+0x5fb9 function_aes_cmac_aes_loop
+0x5fbf function_aes_cmac_aes_loop_end
+0x5fc7 load_inverse_result
+0x5fcb store_inverse_k
+0x5fcd inverse_k
+0x5fd0 inverse_memdat
+0x5fd4 bn_lshift_0_inverse
+0x5fde function_aes_cmac_k1_inverse
+0x5fdf function_aes_cmac_inverse_common
+0x5fe3 function_aes_cmac_k2_inverse
+0x5fe5 function_aes_cmac_generate_subkey
+0x5fed function_aes_cmac_k1
+0x5ff5 function_aes_cmac_k1_0
+0x5ff6 function_aes_cmac_k2
+0x5fff function_aes_cmac_xor_rb
+0x6000 function_aes_cmac_xor_rb_loop
+0x6006 function_aes_cmac_xor_loop_common
+0x600a function_aes_cmac_padding
+0x600d function_aes_cmac_padding_loop
+0x6012 function_aes_cmac_padding_loop2
+0x6015 function_aes_cmac_padding_beq_length
+0x6016 function_aes_cmac_padding_common
+0x6018 function_aes_cmac_padding_big_length
+0x601a generate_kinit
+0x601e function_e21
+0x602d function_e22
+0x6033 function_e22_pin_init
+0x6034 function_e22_genx_pin
+0x6037 function_e22_genx_loop
+0x6041 function_e22_genx_end
+0x604d function_e1
+0x6050 function_e3
+0x6057 function_hash
+0x606d function_ar
+0x6076 function_ar_loop
+0x607d function_ar_original
+0x6093 key_scheduling
+0x6099 key_rotateloop
+0x60a4 key_select_octet_loop
+0x60a9 key_select_octet_nwrap
+0x60b3 bias_round_key_loop
+0x60ba key_sched_zero
+0x60bc create_byte_16_loop
+0x60c4 xor_mod32
+0x60c5 xor_mod32_ar2
+0x60c8 xor_mod32_loop
+0x60ce xor_mod32_invert
+0x60d1 xor_even
+0x60d6 el_boxes
+0x60d9 el_box_loop
+0x60df e_boxes
+0x60e5 pht
+0x60e8 pht_loop
+0x60f2 permute
+0x60ff permute_exchange
+0x6100 permute_loop
+0x610c add16
+0x610e xor16
+0x610f xor_add16
+0x6110 xoradd_loop
+0x6115 xoradd_add
+0x6116 xoradd_store
+0x611b function_expand
+0x6121 expand_12
+0x6122 expand_cont
+0x6126 key_offset
+0x6135 key_addxor
+0x6136 key_addxor_loop
+0x613a key_add
+0x613c key_high
+0x613d key_xor
+0x613e key_store
+0x6142 copy_aco
+0x6147 concatenate_temp24
+0x6148 concatenate_temp16
+0x614b loop1
+0x614c generate_stk
+0x614f authenticate_rconfirm
+0x6152 authenticate_mconfirm
+0x6157 generate_confirm
+0x615a generate_mrand
+0x615d generate_sk
+0x6166 first_block_counter
+0x6168 first_block_data
+0x6169 first_block
+0x617c generate_mic
+0x618a generate_mic_loop
+0x618f generate_mic_end
+0x6193 aes_crypt_data
+0x619e le_encrypt
+0x61b6 le_decrypt
+0x61d5 wait_aes
+0x61d7 do_aes_ecb256
+0x61da do_aes_ecb192
+0x61dd do_aes_ecb
+0x61e0 do_aes_cbc
+0x61e3 do_aes_cfb
+0x61e6 do_aes_ecb_be
+0x61e9 do_aes_cbc_be
+0x61ec aes_init
+0x61ef function_s1
+0x6201 function_c1
+0x620a function_c1_irat
+0x6219 function_c1_master
+0x6224 padding_data
+0x6229 padding_loop
+0x622e aes_load_data
+0x622f load_data_loop
+0x6233 load_data_padding
+0x6238 load_key256
+0x623a load_key192
+0x623c load_key128
+0x623d load_key
+0x623f load_data128
+0x6241 load_regext_loop
+0x6246 load_sk
+0x6248 clear_hidata
+0x624a aes_clear_data
+0x624b aes_clear
+0x624c clear_loop
+0x624d clear_data_rest
+0x6250 store_aes_result
+0x6252 send_aes_result_loop
+0x6257 store_enc_data
+0x625d store_enc_loop
+0x6265 store_enc_byte
+0x6269 compare_res
+0x626b compare_res_loop
+0x6272 enable_authrom
+0x6276 disable_authrom
+0x627a init_memp
+0x62d1 init_memp_256
+0x6323 publickey_init
+0x6326 publickey_calc
+0x6333 stop_publickey_calc_256
+0x6335 sp_initialize
+0x633a sp_clear_flags
+0x633f sp_generate_local_key
+0x6341 sp_master_generate_local_key
+0x6344 sp_generate_local_key0
+0x6347 sp_start_send_pubkey
+0x634c sp_calc_check_publickey_256
+0x6367 sp_calc_b256
+0x637d sp_calc_check_publickey
+0x6398 sp_calc_b
+0x63ae sp_calculate_commitment
+0x63b9 master_sp_calculate_commitment
+0x63c0 sp_calculate_commitment0
+0x63c6 master_sp_calculate_commitment0
+0x63c9 sp_local_random_key_generator
+0x63cc sp_calculate_commitment_wait_dhkey_calc
+0x63ce sp_confirm_check
+0x63e0 sp_confirm_check_success
+0x63e6 sp_confirm_check_success_master
+0x63e9 sp_confirm_check_failed
+0x63ef sp_confirm_check_failed_master
+0x63f2 sp_confirm_calc
+0x63f6 sp_confirm_calc_ready
+0x6403 sp_confirm_calc_master
+0x6406 sp_master_key_prarm_push
+0x6410 sp_link_key_prarm_push
+0x641a sp_link_key_calc
+0x6425 sp_pubkey_calc
+0x643c sp_pubkey_generated
+0x6442 sp_dhkey_calc
+0x6453 sp_dhkey_generated
+0x645a random_generator
+0x645f compare4
+0x6469 compare4_failed
+0x646b compare4_success
+0x646d simple_pairing_sequence
+0x647c master_simple_paring_sequence
+0x648c master_set_mem_master_sp_flag
+0x648e master_clear_mem_master_sp_flag
+0x6490 sp_calc_sequence
+0x649b sp_calc_sequence_done
+0x64a0 bn_testbit
+0x64a6 ec_copy
+0x64a9 bn_eq_zero
+0x64af bn_eq_0
+0x64b8 bn_bigeq
+0x64bb bn_bigeq_0
+0x64c5 bn_add
+0x64c7 bn_add_0
+0x64d3 bn_sub
+0x64d5 bn_sub_0
+0x64e1 bn_rshift6
+0x64e3 bn_rshift
+0x64e4 bn_rshift_0
+0x64ef bn_lshift
+0x64f1 bn_lshift_0
+0x64fc bn_lshiftmod
+0x64fd bn_lshiftmod_ismod
+0x6505 bn_lshiftmod_0
+0x6509 bn_addmod
+0x650c bn_submod
+0x6513 bn_p192mod
+0x6534 bn_load
+0x6535 bn_load_0
+0x653a bn_mulmod
+0x6544 bn_mulmod_1
+0x6546 bn_mulmod_0
+0x655c bn_sqrmod
+0x655e bn_rshifteven
+0x655f bn_rshifteven_1
+0x656e bn_rshifteven_0
+0x6572 bn_invmod
+0x6581 bn_invmod_2
+0x659c bn_invmod_1
+0x65aa bn_invmod_0
+0x65b7 ecdbl
+0x6608 ecadd
+0x6674 eckp_0
+0x6682 eckp_1
+0x6687 ecunmapz
+0x6699 sha_endian_swap2
+0x669c sha_endian_loop
+0x66a4 sha_getw
+0x66a8 sha_r
+0x66aa sha_r_loop
+0x66bf sha_init
+0x66c1 sha_init_0
+0x66c6 sha
+0x66ca sha_0
+0x66d3 sha_loop
+0x66fc sha_1
+0x6702 sha_result
+0x6704 sha_regext_save
+0x6709 pad_xor
+0x670c pad_xor_0
+0x6713 pad_xor_1
+0x6716 g_noninit_number_confirm
+0x6719 g_noninit
+0x671b g_noninit0
+0x6729 g_init
+0x6738 g_common
+0x6741 g_common0
+0x6752 function_f1_no_key
+0x6754 function_f1
+0x6756 function_f1_common
+0x678b function_f2
+0x67c1 function_f3a
+0x67c3 function_f3a_common
+0x67d2 function_f3a_no_pin
+0x67d5 function_f3b_no_pin
+0x67d8 function_f3b
+0x67da function_f3b_common
+0x67e7 function_f3_common
+0x6811 eckp_calc_init
+0x6812 eckp_calc_init_1
+0x681c eckp_calc
+0x6824 memcpy_dword_swap4
+0x6825 memcpy_dword_swap
+0x6826 memcpy_dword_swap_loop
+0x682b sp_initialize_256
+0x6831 sp_pubkey_calc_256
+0x6847 sp_pubkey_generated_256
+0x684d sp_dhkey_calc_256
+0x685d sp_dhkey_generated_256
+0x6863 sp_calc_sequence_256
+0x686d sp_calc_sequence_done_256
+0x6873 eckp_calc_256
+0x687b eckp_calc_init_256
+0x687e eckp_calc_init_256_1
+0x6888 ecunmapz_256
+0x689a ecdbl_256
+0x68eb ecadd_256
+0x6957 bn_invmod_256
+0x6965 bn_invmod_256_2
+0x6980 bn_invmod_256_1
+0x698e bn_invmod_256_0
+0x6995 bn_mulmod_256
+0x69a3 bn_mulmod_256_1
+0x69a9 bn_mulmod_256_0
+0x69be bn_p256mod
+0x6a27 bn_load_mem
+0x6a2b bn_load_256
+0x6a2d bn_sqrmod_256
+0x6a2f bn_add_256
+0x6a31 bn_addmod_256
+0x6a34 bn_lshiftmod_256
+0x6a35 bn_lshiftmod_ismod_256
+0x6a3e bn_lshiftmod_p_256
+0x6a46 sub_p2_256
+0x6a4a bn_submod_256
+0x6a54 bn_submod_256_np
+0x6a5d bn_sub_256
+0x6a5f bn_rshift_256
+0x6a62 bn_lshift_256
+0x6a65 bn_bigeq_256
+0x6a69 bn_eq_zero_256
+0x6a6c bn_rshifteven_256
+0x6a6d bn_rshifteven_256_1
+0x6a7c bn_rshifteven_256_0
+0x6a80 ui_init
+0x6a82 ui_dispatch
+0x6a85 ui_button_init
+0x6a8d ui_button_timer
+0x6a98 ui_button_timer_state_up
+0x6a99 ui_button_up_to_down
+0x6aa5 ui_button_timer_up_to_up
+0x6aa8 ui_button_up_cb
+0x6aaf ui_button_timer_state_down
+0x6ab0 ui_button_timer_state_down_to_down
+0x6ab4 ui_button_longpress_cb
+0x6aba ui_button_down_to_up
+0x6ac3 ui_button_long_release
+0x6ac9 ui_button_set_down
+0x6acb ui_button_set_up
+0x6acc ui_button_set_state
+0x6acf ui_button_set_timer_0
+0x6ad0 ui_button_set_timer
+0x6ad3 ui_led_blink_init
+0x6adb ui_led_blink_check
+0x6ae3 ui_led_state_on
+0x6ae4 ui_led_state_off
+0x6aec ui_led_on_with_timer
+0x6af1 ui_led_on
+0x6af7 ui_led_off_with_timer
+0x6afc ui_led_off
+0x6b02 ui_led_blink_stop
+0x6b07 ui_timer_timeout
+0x6b0c ui_timer_check
+0x6b13 ui_timer_check_loop
+0x6b1d ui_timer_init
+0x6b20 ui_timer_check_end
+0x6b26 ui_timer_check_send_evt
+0x6b27 ui_ipc_get_lock
+0x6b28 ui_ipc_get_lock_wait
+0x6b2b ui_ipc_put_lock
+0x6b2d ui_ipc_fifo_out
+0x6b2e ui_ipc_send_event
+0x6b38 ui_ipc_send_cmd
+0x6b41 ui_ipc_clean_all_fifo
+0x6b45 check_51cmd
+0x6b50 check_51cmd_once
+0x6b70 check_51cmd_once_1
+0x6b75 check_51cmd_once_normal
+0x6b84 check_51cmd_once_continue
+0x6b9f cmd_play_pause
+0x6ba1 cmd_backward
+0x6ba3 cmd_forward
+0x6ba5 cmd_vol_up
+0x6baf cmd_adjust_vol
+0x6bb3 cmd_vol_down
+0x6bbb cmd_accept_call
+0x6bbd cmd_hang_up
+0x6bbf cmd_redial
+0x6bc1 cmd_recognition
+0x6bc3 cmd_increase_power_req
+0x6bc5 check_51_cmd_dhkey_not_accept
+0x6bc8 check_51cmd_check_idle
+0x6bcd check_51cmd_restore
+0x6bcf check_51cmd_role_switch
+0x6bd8 check_51cmd_start_discovery
+0x6bdf check_51cmd_stop_discovery
+0x6be6 check_51cmd_reconnect
+0x6be8 check_51cmd_disconnect
+0x6beb check_51cmd_sniff_test
+0x6bec check_51cmd_pincode
+0x6bee check_51cmd_inq
+0x6bef check_51cmd_stop_inq
+0x6bf0 check_51cmd_adv
+0x6bf3 check_51cmd_stop_adv
+0x6bf5 check_51cmd_direct_adv
+0x6bf8 check_51cmd_stop_direct_adv
+0x6bfa check_51cmd_le_disconnect
+0x6bfb check_51cmd_start_scan
+0x6bfd check_51cmd_stop_scan
+0x6c00 check_51cmd_le_smp_sec_req
+0x6c01 check_51cmd_hibernate
+0x6c06 check_51cmd_bb_reconn_cancel
+0x6c08 check_51cmd_vp_end_recover_dac
+0x6c09 upper_init_reconnect
+0x6c11 upper_reset_sm
+0x6c17 upper_int_reconnect_avctp
+0x6c1b upper_int_reconnect_audio
+0x6c1f upper_disconnect_all_l2cap
+0x6c24 upper_init_reconnect_hid
+0x6c27 upper_init_reconnect_hf
+0x6c2c upper_init_reconnect_single
+0x6c2e upper_get_first_upper_sm
+0x6c30 upper_clear_upper_sm
+0x6c34 upper_sm_single_step
+0x6c3e upper_major_sm_ask_sever_process
+0x6c4b upper_sub_sm_create_sdp
+0x6c50 upper_sub_sm_create_sdp_wait
+0x6c56 upper_sub_sm_config_sdp
+0x6c58 upper_sub_sm_config_sdp_wait
+0x6c5f upper_sub_sm_search_service
+0x6c63 upper_major_sm_search_service_audio_gateway
+0x6c68 upper_sub_sm_search_service_wait
+0x6c70 upper_sub_sm_search_attrib
+0x6c74 upper_sub_sm_search_wait
+0x6c7a upper_sub_sm_sdp_disconenct
+0x6c7d upper_sub_sm_sdp_disconenct_wait
+0x6c85 upper_major_sm_connect_sever_process
+0x6c8b upper_major_connect_hf
+0x6c99 upper_sub_connect_rfcomm
+0x6ca0 upper_sub_connect_rfcomm_wait
+0x6ca6 upper_sub_config_rfcomm
+0x6ca8 upper_sub_config_rfcomm_wait
+0x6caf upper_sub_rfcomm_singnal_connect
+0x6cb6 upper_sub_rfcomm_singnal_connect_wait
+0x6cbb upper_sub_rfcomm_signal_cmd_pn
+0x6cc2 upper_sub_rfcomm_signal_cmd_pn_wait
+0x6cc6 upper_sub_connect_rfcomm_server
+0x6cd2 upper_sub_connect_rfcomm_server_wait
+0x6cd6 upper_sub_connect_server_cmd_ms
+0x6cd8 upper_sub_connect_server_cmd_ms_wait
+0x6cdb upper_major_sm_disconnect_server_process
+0x6ce0 upper_sub_sm_hf_send_sever_disc
+0x6ce8 upper_sub_sm_hf_wait_ua
+0x6cec upper_sub_sm_hf_send_signal_disc
+0x6cee upper_sub_sm_start_disc_l2cap
+0x6cf0 upper_sub_sm_disconnect_l2cap
+0x6cff upper_major_sm_disconnect_server_process_wait
+0x6d01 upper_major_sm_disconnect_server_next
+0x6d06 upper_major_sm_disconnect_server_complete
+0x6d08 upper_major_connect_hid
+0x6d12 upper_sub_connect_hid
+0x6d17 upper_sub_connect_hid_wait
+0x6d1d upper_sub_config_hid
+0x6d1f upper_sub_config_hid_wait
+0x6d26 upper_sub_connect_hidint
+0x6d29 sav_hid_interrupt_l2cap_ptr
+0x6d2b upper_sub_connect_hidint_wait
+0x6d31 upper_sub_config_hidint
+0x6d33 upper_sub_config_hidint_wait
+0x6d39 upper_major_connect_audio
+0x6d4f upper_sub_connect_avdtp_sig
+0x6d56 upper_sub_connect_avdtp_sig_wait
+0x6d5c upper_sub_config_avdtp_sig
+0x6d5e upper_sub_config_avdtp_sig_wait
+0x6d65 upper_sub_avdtp_sig_discover
+0x6d67 upper_sub_avdtp_sig_discover_wait
+0x6d6b upper_sub_avdtp_sig_getcap
+0x6d6d upper_sub_avdtp_sig_getcap_wait
+0x6d71 upper_sub_avdtp_sig_setconf
+0x6d73 upper_sub_avdtp_sig_setconf_wait
+0x6d77 upper_sub_avdtp_sig_open
+0x6d7d upper_sub_avdtp_sig_open_wait
+0x6d81 upper_sub_connect_avdtp_media
+0x6d86 upper_sub_connect_avdtp_media_wait
+0x6d8c upper_sub_config_avdtp_media
+0x6d8e upper_sub_config_avdtp_media_wait
+0x6d95 upper_sub_connect_avctp
+0x6d9e upper_sub_connect_avctp_wait
+0x6da4 upper_sub_config_avctp
+0x6da6 upper_sub_config_avctp_wait
+0x6dac usb_isr
+0x6db7 usb_init
+0x6de6 usb_nak_state_judge
+0x6de9 usb_nak_state_timer_init
+0x6dee usb0_attached_state_judge
+0x6df3 usb_clear_halt_dispose
+0x6df9 usb_rx_no_data
+0x6dfc usb_rx_data
+0x6e07 usb_rx_read
+0x6e0d usb_data_rx
+0x6e0e usb_rx
+0x6e16 usb0_rx
+0x6e19 usb_class_type
+0x6e1f usb_in_device
+0x6e27 usb_out_device
+0x6e2f usb_in_standard_req
+0x6e35 usb_in_class_req
+0x6e3a usb_in_manufacturer_req
+0x6e3b usb_out_standard_req
+0x6e43 usb_out_class_req
+0x6e48 usb_out_manufacturer_req
+0x6e49 usb0_force_stall
+0x6e4d usb0_reply_zerolen
+0x6e4f usb0_request_get_configuration
+0x6e61 usb0_request_get_cfg_dev_cfg
+0x6e63 usb0_request_get_cfg_dev_addr
+0x6e65 usb0_request_get_descriptor
+0x6e6e dsc_hid_info
+0x6e73 dsc_hid_info_interface0
+0x6e76 dsc_hid_info_interface1
+0x6e79 dsc_device_info
+0x6e7d dsc_info_set_data_len
+0x6e82 dsc_info_set_initial_data_len
+0x6e83 dsc_info_set_data_size_completed
+0x6e88 dsc_info_set_current_data_len
+0x6e8a usb_set_high_addr
+0x6e8e usb0_set_addr
+0x6e92 dsc_config_info
+0x6e95 dsc_string_info
+0x6ea3 dsc_hid_report_info
+0x6ea7 dsc_hid_report_info0
+0x6eab usb0_request_get_interface
+0x6ebd usb0_request_get_status
+0x6ece usb0_get_status_in_device
+0x6ed3 usb_send_zero_packet
+0x6ed5 usb_send_ones_packet
+0x6ed7 usb_send_two_packet
+0x6ed9 usb0_get_status_in_interface
+0x6edd usb0_get_status_in_endpoint
+0x6ee6 usb0_get_status_in_ep_in_ep0
+0x6eea usb0_get_status_in_ep_in_ep1
+0x6eee usb0_get_status_in_ep_in_ep2
+0x6ef2 usb0_get_status_in_ep_in_ep3
+0x6ef6 usb_get_idle
+0x6efa usb_get_report
+0x6eff usb_get_report_dispose
+0x6f02 usb_get_report_send_data
+0x6f06 usb_get_report_data_release
+0x6f09 usb_get_report_data_success
+0x6f0c usb_get_protocol_req
+0x6f14 usb_get_report_protocol
+0x6f15 usb_get_boot_protocol
+0x6f16 usb0_request_clear_feature
+0x6f25 usb0_request_clear_feature_out_device
+0x6f2d usb0_request_clear_feature_out_interface
+0x6f2e usb0_request_clear_feature_out_endpoint
+0x6f37 usb0_force_stall_ep0_in_off
+0x6f39 usb0_force_stall_ep1_in_off
+0x6f3c usb0_force_stall_ep2_in_off
+0x6f3f usb0_force_stall_ep3_in_off
+0x6f42 usb0_request_set_feature
+0x6f4b usb0_request_set_feature_out_device
+0x6f54 usb_wakeup_timer_reinit
+0x6f58 usb0_request_set_feature_out_interface
+0x6f59 usb0_request_set_feature_out_endpoint
+0x6f64 usb0_force_stall_ep0_in_on
+0x6f66 usb0_force_stall_ep1_in_on
+0x6f68 usb0_force_stall_ep2_in_on
+0x6f6a usb0_force_stall_ep3_in_on
+0x6f6c usb0_request_set_address
+0x6f7d usb_usb0_state_set_dev_default
+0x6f7e usb0_request_set_wait_address
+0x6f83 usb_usb0_state_set_dev_addr
+0x6f85 usb0_request_set_configuration
+0x6f9a usb0_request_set_cfg_addr_state
+0x6f9a usb0_request_set_cfg_cfg_state
+0x6f9e usb0_request_set_cfg_stay_addr_state
+0x6fa0 usb0_request_set_interface
+0x6fb1 usb_set_idle
+0x6fbf usb_clear_remote_wakeup_set0
+0x6fc3 usb_set_report
+0x6fd2 usb_set_report_resume_judge
+0x6fe0 usb_set_protocol_req
+0x6fe6 usb_set_boot_protocol
+0x6fe9 usb_set_report_protocol
+0x6fed usb0_respond_length
+0x6fef usb0_respond
+0x6ff4 usb0_respond_nostr
+0x6ff7 usb_no_respond_data
+0x6ff9 usb0_tx
+0x7007 usb0_tx_short
+0x700a usb0_tx_info
+0x7019 usb0_tx_nostr
+0x701b usb0_tx0
+0x7020 usb0_tx1
+0x702d usb_tx_ep1
+0x7030 usb_tx_buf
+0x7032 usb_tx_loop
+0x7035 usb_trig
+0x7039 usb_tx_ep2
+0x703d usb_tx
+0x7049 usb_tx_data_ep1
+0x7054 usb_tx_data_ep2
+0x7060 usb_tx_fifo_release
+0x7069 usb_tx_ms_data
+0x7071 usb_tx_ms_data_mac_boot_mode
+0x7072 usb_tx_ms_data_mac_boot_regroup
+0x7080 usb_tx_ms_data_normal_mode
+0x7081 usb_tx_mac_boot_ms_regroup_r_or_lrkey
+0x7084 usb_tx_kb_multikey_data
+0x7088 usb_tx_kb_normal_data
+0x708c usb_inwake_state_tx_dispose
+0x708f usb_mac_wakeup_trig
+0x7094 usb_windows_wakeup
+0x7097 usb_wakeup
+0x709d right_shift_n
+0x709f right_shift_n_loop
+0x70a2 left_shift_n
+0x70a5 left_shift_n_loop
+0x70a8 push_stack
+0x70b1 pop_stack
+0x70bb save_cont_pointers
+0x70c0 load_cont_pointers
+0x70c5 delay_10ms
+0x70c8 delay_ms_wait
+0x70cc memcpy96
+0x70cd memcpy64
+0x70cf memcpy12
+0x70d0 memcpy4
+0x70d3 memcpy8
+0x70d6 memcpy48
+0x70d8 memcpy40
+0x70da memcpy32
+0x70dc memcpy24
+0x70de memcpy16
+0x70e3 bn_zero
+0x70e4 memset0
+0x70e5 memset8
+0x70e8 memset0_8
+0x70e9 istore8_pdata
+0x70eb memset0_4
+0x70ec istore4_pdata
+0x70ee clear_mem_256
+0x70f0 clear_mem_512
+0x70f2 clear_mem_fast
+0x70f5 set_mem_fast_loop
+0x70fa set_mem_fast_loop_four
+0x7100 clear_mem
+0x7103 istore_mem_loop
+0x7106 set_0x55_fast
+0x710d get_contw
+0x710e get_pdata_contw
+0x7110 get_contr
+0x7111 get_pdata_contr
+0x7113 store_contw
+0x7116 store_contr
+0x7119 memcpy_smart
+0x7124 memcpy_smart_long
+0x7128 memcpy_smart_update_contw
+0x712d memcpy_fast
+0x712f memcpy_fast_loop
+0x7134 memcpy_fast_loop_four
+0x713a memcpy
+0x713c memcpy_loop
+0x7140 timer_stop
+0x7141 timer_init
+0x7147 timer_reinit
+0x7148 timer_check
+0x7151 timer_loop
+0x7155 timer_counting
+0x715c lshift8_queue
+0x715d lshift8_queue_loop
+0x7161 xor_loop
+0x7169 inverse_data
+0x716f inverse_loop
+0x7177 clk_add
+0x7182 clk_diff_rt
+0x7184 clk_diff
+0x7189 clk_diff_pos
+0x718e clk2rt
+0x7195 clk2lpo
+0x719c clk2bt
+0x71a4 pn9
+0x71a7 pn9_loop
+0x71b7 bcd_byte
+0x71bf bcd_pack
+0x71c3 bcd_pack_hi
+0x71c9 wait_div_end
+0x71cb bcd2
+0x71cf lpo_clear
+0x71d4 bcd_loop
+0x71dd bcd
+0x71e4 bcd_pack_loop
+0x71f1 string_compare
+0x71fa ceiling
+0x71fe swap
+0x7202 clean_mem
+0x7205 slave_savelist
+0x7210 le_savelist
+0x721d savelpo
+0x721f saveclke
+0x7223 savelist
+0x7224 savelist_2
+0x7234 dirty_mem
+0x7238 callback_func
+0x723a ice_break
+0x723c ice_setbp
+0x7241 ice_setbp2
+0x7246 ice_set_write_bp
+0x7249 test_no_white
+0x724d test_enable_white
+0x7251 fifo_in
+0x7257 fifo_in_push
+0x725d fifo_out
+0x7261 fifo_out_loop
+0x7266 fifo_out_end
+0x7269 fifo_is_empty
+0x726b fifo_is_full
+0x726d fifo_is_near_full
+0x726f not_greater_than
+0x7273 greater_than
+0x7277 check_number_range
+0x7280 disable_user
+0x7282 int_diff
+0x728a int_diff_pdata_negative
+0x728e disable_positive
+0x7290 enable_positive
+0x7290 disable_zero
+0x7292 enable_zero
+0x7294 p_delay
+0x7297 enable_user
+0x7299 enable_user2
+0x729b setarg1
+0x729d setarg0
+0x729f setarg2
+0x72a1 timer_single_step
+0x72a8 timer_single_step2
+0x72af nv_store_le_reconn_info
+0x72b3 nv_store_bd_reconn_info
+0x72b6 nv_store_reconn_info
+0x72b7 nv_find_addr_from_bd_list
+0x72c1 nv_find_addr_from_list
+0x72d1 nv_find_addr_from_list_compare
+0x72d6 nv_update_device_record
+0x72dd nv_write_device_record
+0x72e1 nv_write_device_loop_find
+0x72ed nv_write_device_loop_find0
+0x72f1 nv_set_index_finded_device
+0x72f7 store_rec_data_common
+0x72fa set_index_finded_device_ble_mode
+0x72fc nv_init_device_list
+0x72ff init_device_list_loop
+0x7304 nv_check_nvram
+0x730c nv_check_nvram_loop
+0x7313 nv_load_device_list
+0x731c nv_clear_key_exists
+0x731e nv_check_link_key_load
+0x7324 nv_store_device
+0x732b nv_flash_store_device
+0x7336 nv_ng_load_nvram
+0x733f nv_flash_load_device
+0x734d nv_get_last_record_ptr
+0x734f nv_get_last_connect_address_loop
+0x7354 nv_get_last_connect_rtn
+0x7357 clk_on
+0x7359 store_clkoff
+0x735b clk_off
+0x735e mram_clkoff
+0x7360 mram_clkon
+0x7362 tws_pairing
+0x7366 tws_pairing_work
+0x736a tws_pairing_state_check
+0x7371 tws_recon_remote_work_adv_and_scan
+0x7374 tws_recon_remote_work_scan
+0x7375 tws_recon_remote_work_adv
+0x7376 tws_handle_sco
+0x737d tws_handle_poll
+0x7385 tws_handle_poll_master
+0x738a tws_decrease_ack_interval
+0x738d tws_m_rcv_info_request_check
+0x739e tws_m_update_adv_interval
+0x73a1 tws_m_select_adv_interval
+0x73a5 tws_m_select_adv_interval_master_listen
+0x73a7 tws_m_wait_connecting
+0x73bd tws_m_wait_for_match
+0x73c3 tws_m_wait_for_match_continue
+0x73d0 tws_send_info_not_match
+0x73da tws_send_info_not_match_end
+0x73dd tws_send_context_info_keymap
+0x73f0 tws_send_context_info_phase_end
+0x73fc tws_send_context_info_phase_end_continue
+0x7404 tws_send_context_info_phase
+0x740a tws_set_send_context_header
+0x7412 tws_set_master_slot
+0x7414 tws_set_master_clk11
+0x741c tws_select_le_channel
+0x7421 tws_select_le_channel_end
+0x7423 tws_update_le_channel_index
+0x7427 tws_get_le_channel_by_index
+0x742d tws_select_le_channel_index_loopback
+0x7431 tws_set_first_packet_dynamic_buffer
+0x7440 tws_send_recon_adv
+0x7444 tws_send_recon_adv_set_flag_master
+0x7445 tws_send_recon_adv_set_flag
+0x7446 tws_send_no_connect_trans_info_reach_limit
+0x7448 tws_send_no_connect_trans_info
+0x745a tws_send_connecting_info
+0x7460 tws_send_connecting_info_1
+0x746a tws_send_connecting_info_header
+0x747a tws_send_connecting_info_header_end
+0x747e tws_reset_connecting
+0x7480 tws_set_rcv_rf
+0x748b tws_set_rcv_rf_after_set_freq
+0x7495 tws_set_need_send_header
+0x7497 tws_clear_need_send_header
+0x7499 tws_set_send_rf
+0x749e tws_set_send_rf_common
+0x74ab tws_set_send_rf_transmit
+0x74b0 tws_set_send_rf_end
+0x74b3 tws_slave_send_full_packet_delay
+0x74b6 tws_slave_tx_id
+0x74ba tws_set_send_rf_freq
+0x74bf tws_set_send_rf_freq_tx_enable
+0x74c0 tws_m_receive_spec_packet
+0x74ca tws_m_send_packet
+0x74d5 tws_m_receive_raw_id
+0x74d9 tws_clear_rcv_op
+0x74db tws_send_payload_check
+0x74e5 tws_receive_packet_header_handle
+0x74ef tws_handle_command
+0x74f9 tws_handle_command_cont
+0x7500 tws_handle_command_sync_evt_master_switch
+0x7503 tws_update_local_arqn
+0x750a tws_update_local_arqn_0
+0x7511 tws_receive_packet_header
+0x751d tws_receive_packet_payload_check
+0x7527 tws_receive_audio_process_info
+0x752a tws_receive_master_switch
+0x752d tws_receive_hfp_start_sync
+0x7530 tws_receive_packet_payload
+0x7533 tws_process_payload_data
+0x7537 tws_process_payload_data_end
+0x7539 tws_transmit_packet_prepare_hfp_start_sync_set_clk
+0x753d tws_transmit_packet
+0x7548 tws_transmit_packet_prepare
+0x754c tws_transmit_packet_header
+0x7559 tws_transmit_packet_payload_check
+0x7563 tws_transmit_packet_payload_master_switch
+0x7566 tws_transmit_packet_payload_audio_process_info
+0x7569 tws_transmit_packet_payload_hfp_start_sync
+0x756c tws_transmit_packet_payload
+0x756f tws_transmit_packet_payload_data_loop
+0x7572 tws_transmit_packet_payload_data_end
+0x7576 tws_check_m_rcv_packet_success
+0x757c tws_end_of_packet
+0x7586 tws_end_of_packet_0
+0x758a tws_rf_rx_switch_to_rx
+0x758d tws_m_check_role_switch_work
+0x7597 tws_m_role_switch_success
+0x75a7 tws_wait_ack_process
+0x75bd tws_wait_ack_process_end
+0x75c0 tws_rcv_ack_success
+0x75c4 tws_wait_ack_process_print_double_ack_info
+0x75ce tws_m_check_need_rcv_slave_ack
+0x75d5 tws_m_update_rcv_slave_ack
+0x75da tws_m_wait_ack_process_no_sync_check
+0x75db tws_m_clear_rcv_ack_flag
+0x75dd tws_m_set_rcv_ack_flag
+0x75df tws_m_clear_last_send_ack_flag
+0x75e1 tws_m_set_last_send_ack_flag
+0x75e3 tws_master_connected
+0x75e7 tws_master_poll_slave_timer_refresh
+0x75eb tws_master_poll_slave_timer_refresh_end
+0x75ed tws_set_master_connected
+0x75f2 tws_not_rcv_ack_error
+0x75f7 tws_set_ack_access
+0x75fd tws_clear_connected_info
+0x7600 tws_send_context_info_sub0
+0x7603 tws_send_context_info_sub1
+0x7606 tws_send_context_info_sub2
+0x7609 tws_send_afh_info
+0x7614 tws_send_sco_info
+0x761b tws_send_a2dp_info
+0x7628 tws_send_context_info_common
+0x762c tws_send_context_info_common_end
+0x7632 tws_transmit_receive_sifs
+0x7634 tws_transmit_receive_sifs_notx
+0x7639 tws_receive_rxon
+0x7644 tws_transmit_receive_sifs_end
+0x7645 tws_set_dynamic_freq
+0x764d tws_check_slave_anchor_pass_or_not
+0x765a tws_slave_change_to_master
+0x765c tws_slave_loss_link_switch_polling
+0x7662 tws_check_polling
+0x7668 tws_slave_timeout_switch_to_master
+0x766e tws_check_observe_connecting
+0x7675 tws_master_polling_slave
+0x767a tws_init_all
+0x7680 tws_init_all_timer
+0x7688 tws_init_all_var
+0x768f tws_init_double_ack_var
+0x7694 tws_init_role_switch_var
+0x7697 tws_force_free_local_link
+0x7698 tws_hp_evt_bb_disconnect
+0x769d bt_abnormal_disc_rec
+0x76a0 tws_master_is_found
+0x76a2 tws_slave_is_found
+0x76a3 tws_device_is_found
+0x76a6 tws_send_master_found_event
+0x76a9 tws_send_slave_found_event
+0x76ac tws_start_recon_work
+0x76b1 tws_exit_work_state
+0x76b4 tws_clear_sent_cmd
+0x76c1 tws_sync_evt_reset_hfp_audio
+0x76c4 tws_sync_evt_slave_ack_sent_success
+0x76c9 send_tws_local_power_off_ipc_tx_event
+0x76cb send_tws_remote_power_off_ipc_tx_event
+0x76cd send_tws_master_switch_ipc_tx_event
+0x76cf send_ipc_tx_event
+0x76d1 tws_sync_evt_master_switch_sent_success
+0x76d3 tws_m2s_timeout_refresh
+0x76d9 tws_check_m2s_timeout_reach
+0x76e0 send_tws_sync_cmd
+0x76e6 send_tws_sync_cmd0
+0x76e9 tws_push_cmd_fifo
+0x76eb send_tws_no_connect_trans_cmd
+0x76f3 tws_clear_send_no_connect_trans_command
+0x76f5 tws_handle_no_connect_trans_command
+0x76f7 clear_tws_fifo
+0x76fb tws_master_switch_to_slave
+0x7702 ipc_tx_tws_event
+0x7704 ipc_tx_hfp_event
+0x7706 ipc_tx_a2dp_event
+0x7707 ipc_tx_event
+0x770a ipc_tx_data
+0x770f tws_check_link_timeout
+0x7716 tws_change_to_wait_tws_slave
+0x7718 tws_clear_connect_info
+0x771a tws_start_wait_slave
+0x7720 tws_refresh_slave_no_connect_wait_switch_timeout
+0x7725 tws_refresh_slave_no_connect_wait_switch_timeout_end
+0x7727 tws_start_slave_switch_wait_work
+0x772c tws_start_wait_master
+0x772e tws_set_slave_role
+0x7733 tws_stop_wait_slave
+0x7733 tws_stop_wait_master
+0x7734 tws_recon_fail
+0x7736 tws_clear_flag_state
+0x7738 tws_clear_snd_rcv_flag
+0x773b tws_clear_snd_cmd_fifo
+0x773e tws_clear_snd_no_connect_cmd
+0x7741 tws_check_master_wait_slave_connect_timeout
+0x7749 tws_check_master_slave_connected
+0x774e tws_save_media_process_info
+0x7756 tws_check_end_hfp_start_sync
+0x7759 tws_check_end_hfp_start_sync_loop
+0x7762 tws_check_end_hfp_start_sync_loop_end
+0x776a tws_restart_hfp_audio
+0x776d tws_100ms_event_polling
+0x7774 tws_s_wait_connecting
+0x7782 tws_s_generate_scan_window
+0x7788 tws_s_generate_scan_window_end
+0x7794 tws_s_connecting_wait_match
+0x779b tws_s_connecting_wait_match_continue
+0x77a7 tws_check_paired_bdaddr_and_rssi_is_match
+0x77aa tws_check_paired_bdaddr_and_rssi_is_match_allready_paired
+0x77ae tws_check_paired_bdaddr_and_rssi_is_match_not_paired
+0x77b9 tws_check_hsp_role_is_match
+0x77c2 tws_slave_check_rcv_context_header
+0x77cb tws_reset_connecting_with_clear_context
+0x77cd tws_clear_slave_context
+0x77d0 tws_clear_mem_80
+0x77d2 tws_rcv_pkt_in_slave_listen
+0x77d5 tws_receive_first_adv_in_recon_state
+0x77e1 tws_receive_arbiter_connected_adv_flag
+0x77e2 tws_receive_arbiter_noconnect_adv_flag
+0x77e3 tws_receive_power_on_adv_flag
+0x77e7 tws_state_check_arbiter_in_reconnect
+0x77ed get_tws_rcv_context_info_btclk
+0x77ef tws_rcv_first_packet_allow_check
+0x77fc tws_rcv_no_connect_trans_info
+0x7803 tws_rcv_no_connect_trans_info_check
+0x780d tws_rcv_context_info_btclk
+0x7824 tws_rcv_context_info_btclk_1
+0x7836 tws_rcv_context_info_btclk_no_connect
+0x7838 tws_rcv_context_info_keymap
+0x7847 tws_rcv_context_info_phase_end
+0x7854 tws_rcv_context_info_phase_end_continue
+0x7867 tws_rcv_context_info_phase_end_no_afh
+0x7875 tws_slave_wait_match
+0x7879 tws_slave_wait_match_loop
+0x7880 tws_check_master_a2dp_start
+0x7886 tws_check_master_sco_start
+0x7889 tws_send_info_request
+0x7893 tws_check_bdaddr_is_match
+0x7898 tws_slave_listen
+0x78ac tws_slave_phone_connected
+0x78c0 tws_slave_listen_not_match
+0x78c4 tws_slave_scan_adv
+0x78e8 tws_slave_rcv_first_dynamic_buffer
+0x78ec tws_s_check_role_switch_work
+0x78f6 tws_s_role_switch_success
+0x7907 tws_send_ack_process
+0x7920 tws_slave_rcv_ack
+0x7923 tws_send_ack_process_end
+0x792a tws_send_ack_process_print_double_ack_info
+0x7934 tws_slave_ack_response_process
+0x793c tws_sec_link_connected
+0x7941 tws_sec_link_connected_end
+0x7943 tws_handle_old_packet
+0x7946 tws_discard_packet
+0x794b tws_rcv_context_info_memcontext_sub0
+0x794e tws_rcv_context_info_memcontext_sub1
+0x7951 tws_rcv_context_info_memcontext_sub2
+0x7954 tws_rcv_afh_info
+0x7960 tws_rcv_sco_info
+0x7968 tws_rcv_a2dp_info
+0x7976 tws_rcv_context_info_memcontext_common
+0x797c tws_rcv_context_info_memcontext_common_end
+0x7982 tws_wait_adv
+0x7988 headset_init
+0x7995 headset_poweron
+0x7997 headset_poweroff
+0x799a headset_poweroff_wait
+0x799c headset_clear_parms
+0x79a9 headset_check_reconnet
+0x79b6 headset_reconnet
+0x79bb headset_cb_idle_process
+0x79be headset_cb_bt_process
+0x79bf headset_cb_bb_event_process
+0x79c8 headset_evt_up_to_max_vlm
+0x79c9 headset_evt_bt_start_enc
+0x79cc headset_evt_pincode_req
+0x79d1 headset_evt_bb_disconnect
+0x79da headset_evt_page_timeout
+0x79db headset_evt_connected
+0x79e3 headset_cb_check_wakelock
+0x79eb headset_evt_100ms_timer
+0x79f1 headset_timer_l2cap_reconnect_audio
+0x79f5 headset_timer_connect_avrcp_timer
+0x79f9 headset_discovery_timer
+0x79fe headset_led_timer1
+0x7a03 headset_led_timer2
+0x7a08 debug_log_print
+0x7a14 debug_log_print_get_lock
+0x7a1a debug_log_print_get_lock_wait
+0x7a21 debug_log_print_get_lock_wait_end
+0x7a33 debug_log_print_end
+0x7a33 debug_log_print_free_lock
+0x7a37 debug_log_wptr_loopback
+0x7a3f rf_debug_active_rx_line
+0x7a43 rf_debug_inactive_rx_line
+0x7a47 rf_debug_active_tx_line
+0x7a4b rf_debug_inactive_tx_line
+0x7a4f rf_debug_active_sync_line
+0x7a53 rf_debug_inactive_sync_line
+0x7a57 rf_debug_active_crc_error_line
+0x7a5b rf_debug_inactive_crc_error_line
+0x7a5f rf_debug_gpio_active
+0x7a61 rf_debug_gpio_inactive
+0x7a63 rf_shutdown_radio_for_debug
+0x7a67 ota_init
+0x7a6e ota_process
+0x7a83 ota_process_version_request
+0x7a88 ota_process_buck_size_request
+0x7a8f ota_process_work_mode_request
+0x7a96 ota_check_work_mode
+0x7a9e ota_set_work_mode_ota
+0x7aa0 ota_set_work_mode_normal
+0x7aa2 ota_process_switch_work_mode
+0x7aa6 ota_process_switch_work_mode_normal
+0x7aa9 ota_process_switch_work_mode_ota
+0x7aac ota_process_switch_work_mod_success
+0x7aae ota_process_flash_checksum_rsp
+0x7ab4 ota_process_flash_checksum
+0x7abf ota_flash_read_loop
+0x7ad5 ota_flash_read_loop_end
+0x7adb ota_process_flash_checksum_success
+0x7add ota_sum_loop
+0x7ae1 ota_read_page
+0x7ae3 ota_process_start_request
+0x7ae9 ota_process_start_req_success
+0x7aee ota_process_start_update_normal
+0x7af3 ota_process_start_update_ota
+0x7af8 ota_process_start_update_pcm
+0x7afd ota_process_write_cmd
+0x7b16 ota_process_write_rsp
+0x7b19 ota_process_write_request
+0x7b2f ota_send_write_rsp_success
+0x7b37 ota_process_end_request
+0x7b3f ota_process_end_request_normal
+0x7b42 ota_process_end_request_ota
+0x7b45 ota_process_end_request_pcm
+0x7b45 ota_process_end_request_success
+0x7b4a ota_write_flash_start_addr_ota
+0x7b4b ota_write_flash_start_addr
+0x7b58 ota_write_flash_start_addr_normal
+0x7b5a ota_tx_buck_size_error
+0x7b5c ota_tx_write_index_error
+0x7b5e ota_tx_write_length_error
+0x7b60 ota_tx_result_error
+0x7b62 ota_tx_workmode_error
+0x7b65 ota_tx_workmode_not_support
+0x7b67 ota_tx_flashmode_not_support
+0x7b6d ota_tx_notify_success
+0x7b6e ota_tx_notify_common
+0x7b78 ota_reset
+0x2000 z_hci_parse_packet_cmd_ogf_link_control_accept_connection
+0x2000 z_hci_parse_packet_cmd_ogf_controller_and_baseband
+0x2000 z_hci_parse_packet_cmd_ogf_controller_and_baseband_set_event_mask
+0x2000 z_hci_parse_packet_cmd_ogf_controller_and_baseband_reset
+0x2001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_local_name
+0x2001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_local_name
+0x2002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_timeout
+0x2002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_timeout
+0x2002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_scan_enable
+0x2003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_scan_enable
+0x2003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_activity
+0x3000 z_hci_parse_packet_cmd_ogf_infomational_parameters
+0x3000 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_version_information
+0x3000 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_command
+0x3001 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_features
+0x3001 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_bd_addr
+0x3001 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_local_ext_features
+0x3001 z_hci_parse_packet_cmd_ogf_infomational_parameters_read_buffer_size
+0x4000 z_hci_parse_packet_cmd_ogf_le_controller
+0x4000 z_hci_parse_packet_cmd_ogf_le_controller_set_event_mask
+0x4000 z_hci_parse_packet_cmd_ogf_le_controller_read_buffer_size
+0x4001 z_hci_parse_packet_cmd_ogf_le_controller_read_supported_features
+0x4001 z_hci_parse_packet_cmd_ogf_le_controller_set_random_address
+0x4001 z_hci_parse_packet_cmd_ogf_le_controller_set_adv_para
+0x4002 z_hci_check_advertising_type
+0x4003 z_hci_set_public_addr
+0x4003 z_hci_set_random_addr
+0x5000 z_hci_parse_packet_cmd_ogf_link_policy
+0x5000 z_hci_parse_packet_cmd_ogf_link_policy_sniff_mode
+0x5001 z_hci_parse_packet_cmd_ogf_link_policy_exit_sniff_mode
+0x5002 z_hci_parse_packet_cmd_ogf_link_policy_switch_role
+0x5002 z_hci_parse_packet_cmd_ogf_link_policy_read_link_policy_settings
+0x5003 z_hci_parse_packet_cmd_ogf_link_policy_write_link_policy_settings
+0x6000 z_hci_parse_packet_cmd_ogf_link_policy_branch1
+0x6000 z_hci_parse_packet_cmd_ogf_link_policy_read_default_link_policy_settings
+0x6000 z_hci_parse_packet_cmd_ogf_link_policy_write_default_link_policy_settings
+0x7000 z_hci_parse_packet_cmd_ogf_controller_and_baseband1
+0x7000 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_paga_scan_activity
+0x7001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_activity
+0x7001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_activity
+0x7002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_class_of_device
+0x7002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_class_of_device
+0x7002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_type
+0x7002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_type
+0x7002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_mode
+0x7003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_mode
+0x7003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_type
+0x7003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_scan_type
+0x7003 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_eir
+0x8000 z_hci_parse_packet_cmd_ogf_link_control1
+0x8000 z_hci_parse_packet_cmd_ogf_link_control_disconnect
+0x8000 z_hci_control_disconnect_classic
+0x8001 z_hci_parse_packet_cmd_ogf_link_control_create_connection_cancel
+0x8001 z_hci_connection_already_exists_err
+0x8002 z_hci_create_conn_cancel_success
+0x8002 z_hci_connection_cancel_err_no_connection
+0x8002 z_hci_connection_cancel_err
+0x8002 z_hci_parse_packet_cmd_ogf_link_control_reject_connection
+0x9000 z_hci_parse_packet_cmd_ogf_link_control2
+0x9000 z_hci_parse_packet_cmd_ogf_link_control_link_key_request_reply
+0x9001 z_hci_parse_packet_cmd_ogf_link_control_link_key_request_negative_replay
+0x9001 z_hci_pin_code_request_reply
+0x9002 z_hci_pin_code_request_negative_reply
+0x9002 z_hci_pin_code_reply
+0x9002 z_hci_parse_packet_cmd_ogf_link_control_authentication_requested
+0x9002 z_hci_parse_packet_cmd_ogf_link_control_set_connection_encryption
+0xa000 z_hci_parse_packet_cmd_ogf_link_control3
+0xa000 z_hci_parse_packet_cmd_ogf_link_control_remote_name_request
+0xa001 z_hci_parse_packet_cmd_ogf_link_control_read_remote_ext_features
+0xa001 z_hci_parse_packet_cmd_ogf_link_control_read_remote_version_information
+0xa002 z_hci_control_read_remote_version_classic
+0xa002 z_hci_control_read_remote_version_le
+0xa002 z_hci_parse_packet_cmd_ogf_link_control_read_remote_supported_features
+0xa003 z_hci_send_read_remote_supported_features_complete_event
+0xb000 z_hci_parse_packet_cmd_ogf_controller_and_baseband2
+0xb000 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_link_supervision_timeout
+0xb001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_eir
+0xb001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_simple_pairing_mode
+0xb001 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_simple_pairing_mode
+0xb002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_le_host_support
+0xb002 z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_le_host_support
+0xc000 z_hci_parse_packet_cmd_ogf_le_controller1
+0xc000 z_hci_parse_packet_cmd_ogf_le_controller_set_adv_data
+0xc000 z_hci_parse_packet_cmd_ogf_le_controller_set_scan_rsp_data
+0xc001 z_hci_parse_packet_cmd_ogf_le_controller_set_scan_para
+0xc002 z_hci_parse_packet_cmd_ogf_le_controller_set_scan_enable
+0xc002 z_hci_parse_packet_cmd_ogf_le_controller_create_connection
+0xd000 z_hci_parse_packet_cmd_ogf_le_controller2
+0xd000 z_hci_parse_packet_cmd_ogf_le_controller_set_adv_enable
+0xd001 z_hci_parse_packet_cmd_ogf_le_controller_create_connection_cancel
+0xd001 z_hci_parse_packet_cmd_ogf_le_controller_read_white_list_size
+0xd001 z_hci_parse_packet_cmd_ogf_le_controller_clear_white_list
+0xd001 z_hci_parse_packet_cmd_ogf_le_controller_add_device_to_white_list
+0xd002 z_le_add_device_to_white_list
+0xe000 z_l2cap_init_queue
+0xe001 z_queue_init_loop
+0xe002 z_init_all_queue
+0xe002 z_queue_init
+0xf000 z_l2cap_link_queue_init
+0xf000 z_l2cap_br_link_queue_init
+0xf000 z_l2cap_ble_link_queue_init
+0xf000 z_l2cap_queue_free_all
+0xf001 z_l2cap_link_queue_free_rx_buffer
Index: ModuleDemo/BLE/BT/get_sdk_labels.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/get_sdk_labels.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/get_sdk_labels.bat	(working copy)
@@ -0,0 +1,5 @@
+call do.bat eep
+cd output
+perl ..\getlabels.pl > labels.format
+copy labels.format ..\format\labels.format
+cd ..
\ No newline at end of file
Index: ModuleDemo/BLE/BT/getlabels.pl
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/getlabels.pl	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/getlabels.pl	(working copy)
@@ -0,0 +1,19 @@
+open file,"program.lis";
+$labe2 = 0;
+while(<file>) {
+	if(/^([a-z_0-9]+):\s*$/) {
+		#printf "%s\n", $labe2;
+		$label = $1;
+		$_ = <file>;
+		if(length($_) > 1 && hex(substr($_, 0, 4)) >= 0x2000){
+			if($labe2){
+				printf "0x%s %s\n", substr($_, 0, 4),  $labe2;
+				$labe2 = 0;
+			}
+			printf "0x%s %s\n", substr($_, 0, 4),  $label;
+		}else{
+			$labe2 = $label;
+		}
+	}
+}
+close file;
Index: ModuleDemo/BLE/BT/patch/patch.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/patch.prog	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/patch.prog	(working copy)
@@ -0,0 +1,3074 @@
+//define EFUSE_CODE
+//define FUNCTION_WATCH_DOG
+//define TEST_QUEUE_DEBUG
+define RF_DEBUG
+//define WHITE_LIST
+define MINZHAN_SDK
+define FSC_RTK_HOST
+//define LE_CONN_RCV_DEBUG
+define PATCH_DEBUG_LOG
+
+/******************************************/
+/**************   Start   *****************/
+/******************************************/
+ifdef EFUSE_CODE
+	call wdt_init_reset_with_start // this supervision timeout is near 16.76s
+	branch loadcode_spi+2
+endif //EFUSE_CODE
+
+	bbit1 8,pf_patch_ext
+	beq patch00_2,p_main_loop
+	beq patch01_6,p_inquiry_receive_rtn
+	beq patch02_0,p_master_page_timeout
+	beq patch03_4,p_master_loop
+	beq patch03_6,p_master_disconnect
+	beq patch04_0,p_linkkey_ready
+	beq patch04_4,p_role_switch_master
+	beq patch06_2,p_send_eir
+	beq patch07_1,p_slave_dispatch
+	beq patch07_2,p_slave_loop
+	beq patch07_6,p_slave_disconnect
+	beq patch08_1,p_roles_newconn_loop				
+	beq patch08_4,z_newconn_init
+	beq patch0a_4,p_rx_type_dispatch
+	beq patch0b_0,p_process_dmh_common
+	beq patch0b_4,p_process_dmh_data_end
+	beq patch0b_5,p_process_dmh_l2cap_packet
+	beq patch0d_2,z_sniff_init
+	beq patch0d_3,z_sniff_exit
+	beq patch0d_4,p_check_attempt
+	beq patch10_1,p_shutdown_radio
+	beq patch10_5,p_set_freq_tx
+	beq patch10_6,p_initialize_radio_cont
+
+	
+	beq patch13_6,p_initialize_radio_cont_by_init_param
+
+	beq patch14_0,p_lpm_hibernate
+	beq patch14_4,p_lpm_dispatch
+	beq patch15_0,p_lpm_dispatch_unconn
+	beq patch17_1,z_app_init
+	beq patch17_2,p_app_process_bb_event
+	beq patch1c_0,p_vp_check_get_data
+	branch assert
+pf_patch_ext:
+	beq patch20_7,z_ipc_init
+	beq patch21_4,p_ipc_rx_process
+	beq patch22_2,z_l2cap_init_queue
+	beq patch22_3,p_queue_insert
+	beq patch22_4,p_queue_delete
+	beq patch24_3,p_l2cap_load_channel_param
+	beq patch24_5,p_l2cap_malloc
+	beq patch24_6,p_l2cap_malloc_fifo_out
+	beq patch24_7,p_l2cap_malloc_free
+	beq patch25_0,p_l2cap_malloc_discard
+	beq patch25_1,p_l2cap_malloc_is_fifo_full
+	beq patch25_2,p_l2cap_malloc_fifo_get_first_ptr
+	beq patch27_3,p_le_init_conn
+	beq patch27_6,p_le_conn_dispatch
+	beq patch27_7,p_le_slave_match
+	beq patch28_1,p_le_slave_unsync
+	beq patch28_2,p_le_slave_disconn
+	beq patch29_0,p_le_context_nextevent
+	beq patch29_3,p_le_receive_slave
+	beq patch29_7,p_le_send_adv_ind
+	beq patch2a_2,p_le_acknowledge
+//	beq patch2a_4,p_le_scan_match
+	beq patch2b_0,z_le_parse_ll
+	beq patch2b_3,p_le_adv
+	beq patch2b_5,z_parse_connect_req
+	beq patch2c_0,p_le_fifo_malloc_tx
+	beq patch2c_4,p_le_fifo_release_first_node
+	beq patch2d_6,p_init_lmp_work
+	beq patch2e_0,z_parse_lmp_process
+	beq patch2e_1,z_parse_lmp_escape
+	beq patch2e_4,p_send_lmp
+	
+	beq patch32_2,p_scheduler_tx_l2cap_pkt
+	beq patch34_5,p_simple_pairing_sequence
+	beq patch34_6,p_master_simple_paring_sequence
+	rtneq patch36_2
+	rtneq patch3a_4
+	//beq patch36_2,p_tws_m_wait_connecting
+	//beq patch3a_4,p_tws_s_wait_connecting
+	branch assert
+
+p_main_loop:
+	call sp_calc_sequence 
+	call sp_calc_sequence_256
+	call publickey_calc
+	call p_le_dispatch
+	call idle_dispatch
+	call app_process_idle
+	call p_inquiry_dispatch
+	call inquiry_scan_dispatch
+	call p_page_scan_dispatch
+	branch main_loop+11
+
+p_inquiry_dispatch:
+	rtnmark0 mark_inquiry_on
+	force inquiry_length_timer,queue
+	call timer_check
+	nsetflag blank,mark_inquiry_on,mark
+	nbranch inquiry_start,blank
+	branch z_hci_send_inquiry_comple
+	
+p_page_scan_dispatch:
+	fetch 1,mem_scan_mode
+	rtnbit0 page_scan_mode
+	fetch 1,mem_state
+	rtnbit1 state_inconn
+p_page_scan_dispatch2:	
+	force pscan_interval_timer,queue
+	call timer_check
+	nrtn blank
+	fetcht 2,mem_pscan_window
+//	force 40,queue
+	disable swfine
+	copy temp,stop_watch
+	branch page_scan_dispatch+9
+
+p_le_dispatch:
+	 call le_enable 
+	 call p_le_scan
+	 branch le_dispatch+2
+
+p_le_scan:
+	fetch 1,mem_le_scan_enable
+	rtnne LE_SCAN_ENABLE
+	arg le_scan_interval_timer,queue
+	call timer_check
+	nrtn blank
+	
+	fetch 2,mem_le_scan_interval
+	arg le_scan_interval_timer,queue
+	call timer_init
+	
+	call le_init_adv
+	call le_next_adv_channel
+	fetch 2,mem_le_scan_window
+	store 2,mem_le_scan_window_temp
+p_le_scan_loop:	
+	disable master
+	disable swfine
+	fetchr timeup,2,mem_le_scan_window_temp
+	call p_le_receive_packet
+	nbranch p_le_scan_timeout_check,match	
+	//branch le_scan_match
+p_le_scan_match:
+	call le_scan_check_sender_addr_type
+	copy rega,pdata
+	store 1,mem_le_conn_peer_addr_type
+ifdef WHITE_LIST
+	arg mem_le_white_list_type_and_bd_addr,contw
+	istore 1,contw
+	fetch 6,mem_le_rxbuf+2
+	istore 6,contw
+	fetch 1,mem_le_white_list_cnt
+	beq 0,p_le_scan_match_send_event
+	fetch 1,mem_le_white_list_filter_policy
+	beq NONE_FILTER,p_le_scan_match_send_event
+	beq WHITE_LIST_SCAN_FILTER,p_white_filter_scan_check
+	beq WHITE_LIST_CONNECT_FILTER,p_le_scan_match_send_event
+	beq WHITE_LIST_CONN_SCAN_FILTER,p_white_filter_scan_check
+p_white_filter_scan_check:
+	call p_check_addr_in_white_list
+	nbranch p_le_scan_timeout_check,blank
+endif
+p_le_scan_match_send_event:
+	fetch 6,mem_le_rxbuf+2
+	store 6,mem_le_plap
+	
+	fetch 1,mem_mesh_creat_connection_flag
+	beq CREAT_CONNECTION,p_le_create_conn
+	call p_hci_send_event_le_advertising_report
+	
+	call le_send_scan_request
+	nbranch p_le_scan_timeout_check,match
+	fetch 1,mem_le_rxbuf+1
+	beq 6,p_le_scan_timeout_check
+	call p_hci_send_event_le_advertising_report
+
+p_le_scan_timeout_check:	
+	fetch 2,mem_le_scan_window_temp
+	nbranch  p_le_scan_loop,blank
+	rtn
+
+p_le_receive_packet:
+	call lerx_setfreq
+p_le_receive_rxon:
+	call le_prep
+	disable match
+	enable decode_fec0
+	enable is_rx
+	disable is_tx
+	copy timeup,stop_watch
+	correlate null,timeout
+	deposit stop_watch
+	store 2,mem_le_scan_window_temp
+	branch le_receive_rxon+7
+
+
+p_initialize_radio_cont:
+	fetch 1,mem_patch13
+	set0 6,pdata
+	store 1,mem_patch13
+	branch p_initialize_radio_process
+// be-careful, this patch is not from <initialize_radio_cont>.
+p_initialize_radio_cont_by_init_param:
+	call p_initialize_radio_process
+
+	// becouse patch is from <init_param>
+	branch init_param_cont
+
+p_initialize_radio_process:
+		// in efuse will enable wdt
+ifdef FUNCTION_WATCH_DOG
+	call wdt_init_reset_with_start
+else
+	call wdt_disable_watchdog
+endif //FUNCTION_WATCH_DOG
+
+	// Change mixer power
+	jam 0xba,0x894b
+	call p_initialize_radio_tx_power
+	// Always use 2M IF
+	jam 0xff,0x8907	//7~5 000:0M IF 011:1M IF 111:2M IF
+	call initialize_radio_cont+1
+	jam 0x74,0x8950
+	jam 0x0e,0x8952
+	jam 0x07,0x896d
+	rtn
+
+p_initialize_radio_tx_power:
+	fetch 1,mem_tx_power
+//	beq TX_POWER_0DB,p_initialize_radio_tx_power_0db
+ifdef ENABLE_F3DB
+	beq TX_POWER_f3DB,p_initialize_radio_tx_power_f3db	
+endif // ENABLE_F3DB
+	beq TX_POWER_3DB,p_initialize_radio_tx_power_3db	
+	beq TX_POWER_f5DB,p_initialize_radio_tx_power_f5db	
+	beq TX_POWER_5DB,p_initialize_radio_tx_power_5db
+ifdef ENABLE_8DB
+	beq TX_POWER_8DB,p_initialize_radio_tx_power_8db	
+endif // ENABLE_8DB
+
+ifdef ENABLE_8DB
+p_initialize_radio_tx_power_8db:
+	setarg 0xcce0d0
+	store 3,0x8955
+	setarg 0x7a103e
+	store 3,0x8958
+	jam 0x43,0x8954
+	rtn
+endif // ENABLE_8DB
+
+p_initialize_radio_tx_power_3db:
+p_initialize_radio_tx_power_5db:
+	setarg 0x88e0d0
+	store 3,0x8955
+p_initialize_radio_tx_power_common:
+	setarg 0x4a103c
+p_initialize_radio_tx_power_common2:
+	store 3,0x8958
+	jam 0x68,0x8954
+	rtn
+p_initialize_radio_tx_power_f3db:
+p_initialize_radio_tx_power_f5db:
+	setarg 0x88c0d0
+	store 3,0x8955
+	setarg 0x4a106c
+	branch p_initialize_radio_tx_power_common2
+
+p_shutdown_radio:
+ifdef RF_DEBUG
+	call rf_shutdown_radio_for_debug
+endif //RF_DEBUG
+	branch p_shutdown_radio0,is_rx
+	jam 0xd4, 0x8955
+	nop 4
+	jam 0xd2, 0x8955
+	nop 4
+	jam 0xd1, 0x8955
+	nop 4	
+	fetch 1,mem_tx_power
+ifdef ENABLE_F3DB	
+	beq TX_POWER_f3DB,p_shutdown_radio_f3db
+endif //ENABLE_F3DB
+	beq TX_POWER_3DB,p_shutdown_radio_3db
+	beq TX_POWER_f5DB,p_shutdown_radio_f5db
+p_shutdown_radio_8db:
+p_shutdown_radio_5db:	
+p_shutdown_radio_3db:
+p_shutdown_radio_0db:
+	jam 0xd0, 0x8955
+	jam 0xe0, 0x8956
+p_shutdown_radio0:
+	force 8,radio_ctrl
+	force 0,radio_ctrl
+	disable is_rx
+	disable is_tx
+	pulse packet_end
+	jam 0x0,rfen_mdm
+	jam 0x0,rfen_tx
+	jam 0x0,rfen_rx
+	jam 0,rfen_sn
+	jam 0x70,rfen_msc
+	fetch 1,rfen_adc
+	set0 0,pdata
+	store 1,rfen_adc
+//	jam 0x0,rfen_adc
+	rtn	
+p_shutdown_radio_f5db:
+p_shutdown_radio_f3db:
+	jam 0xd0,0x8955
+	jam 0xc0,0x8956
+	branch p_shutdown_radio0
+p_set_freq_tx:
+	storet 1,mem_last_freq
+	add temp,0,rega			/* index to frequency */
+	fetch 1,mem_sfreq_enable
+	ncall set_offset_sfreq,blank
+	call rf_write_freq
+	setarg param_pll_setup_min
+	call sleep
+p_rf_tx_enable:
+	// becouse we will change the tx power, so need initial again
+	call p_initialize_radio_tx_power
+	fetch 1,rfen_adc
+	set1 0,pdata
+	store 1,rfen_adc
+	jam 0x3c,rfen_rx
+	jam 0xe0,rfen_tx
+	nop 10 /* wait LDOs to turn ON*/
+	jam 0x01, rfen_mdm
+	jam 0x3d, rfen_mdm
+	nop 10 /* wait tx blocks to turn ON*/
+	jam 0xb7,rfen_sn
+	nop 10 /* wait tx lo buffer to turn ON*/
+	jam 0x7d, rfen_mdm
+	fetch 1,mem_tx_power
+	beq TX_POWER_0DB,p_set_tx_power_0db
+ifdef ENABLE_F3DB
+	beq TX_POWER_f3DB,set_tx_power_f3db	
+endif //ENABLE_F3DB
+	beq TX_POWER_f5DB,p_set_tx_power_f5db
+p_rx_high_sens:
+	jam 0xfb,0x894c 
+	jam 0xef,0x894d
+	jam 0xec,0x894e 
+	jam 0x5e,0x894f 
+	beq TX_POWER_3DB,p_set_tx_power_3db
+	beq TX_POWER_8DB,p_set_tx_power_8db
+p_set_tx_power_5db:  	
+  	branch set_tx_power_5db
+p_set_tx_power_8db:  	
+	jam 0xff,0x8956
+	call txon_common
+	jam 0xff,0x8955
+	rtn
+	
+p_set_tx_power_f5db:
+	call p_rx_low_sens
+	jam 0xcc,0x8956
+	call txon_common
+	jam 0xd8,0x8955
+	rtn	
+	
+p_set_tx_power_0db:
+	call p_rx_low_sens
+	branch set_tx_power_0db
+
+	
+p_set_tx_power_3db:
+	jam 0xf7,0x8956
+	call txon_common
+	jam 0xdf,0x8955
+	rtn
+p_rx_low_sens:
+	jam 0x5b,0x894c 
+	jam 0x96,0x894d
+	jam 0x2c,0x894e 
+	jam 0x46,0x894f 
+  	rtn
+
+/*
+p_enable_m0_work_clk:
+	fetch 1,0x1f000
+	arg 0x1c,temp
+	ior temp,pdata
+	store 1,0x1f000
+	rtn
+p_disable_m0_work_clk:
+	fetch 1,0x1f000
+	arg 0xe3,temp
+	iand temp,pdata
+	store 1,0x1f000
+	rtn
+*/
+
+
+p_lpm_write_wait_clock:
+	until null,lpo_edge
+	until null,lpo_edge
+	until null,lpo_edge
+	until null,lpo_edge
+	until null,lpo_edge
+	rtn
+
+ 	
+
+ 	
+p_headset_cb_idle_process:
+ifdef FUNCTION_WATCH_DOG
+	call p_wdt_kick_watchdog
+endif //FUNCTION_WATCH_DOG
+	rtn
+
+	
+//p_app_process_bb_event:
+//	fetch 1,mem_state
+//	bbit1 state_inconn,app_process_bb_event+1
+//	
+//	fetch 2,mem_ui_state_map
+//	jam 0x03,mem_scan_mode
+//	branch app_process_bb_event+1
+
+p_headset_evt_100ms_timer:
+// Voice all process by cm0
+p_vp_check_get_data:
+	rtn
+
+
+p_clear_charge_reset_flag:
+	fetch 4,core_lpm_buck_cfg
+	set0 29,pdata
+ 	store 4,core_lpm_reg
+	branch  p_lpm_write_ctrl_buck
+p_lpm_write_ctrl_buck:
+	until null,lpo_edge
+	jam lpmreg_sel_buck_cfg,core_lpm_wr
+	until null,lpo_edge
+	rtn
+p_lpm_hibernate:
+	arg -1,temp // Here must be -1, the rom code is error
+	branch lpm_doze
+
+
+	
+/*********************************/
+/*********lmp send*************/
+/********************************/
+	/* enable user if a lmp packet is to send */
+p_send_lmp:
+	//bpatchx patch2e_4,mem_patch2e
+	disable user
+	call lmo_fifo_process
+	fetch 1,mem_lmp_to_send
+	rtn blank
+	branch z_send_lmp
+
+p_send_lmp_sres_startenc_slave_event_send:
+	call z_hci_send_linkkey_notification
+	branch p_hci_send_auth_complete
+
+p_prepare_disconnect:
+	fetch 1,mem_op
+	set1 op_disconn,pdata
+	store 1,mem_op
+	jam 1,mem_conn_timer
+	rtn
+
+p_send_eir:
+	fetch 1,mem_eir
+	branch send_eir+1,blank
+	arg mem_eir,contr
+	arg 240,loopcnt
+	arg 0,temp
+	call p_check_tx_length
+	storet 2,mem_tx_len
+	branch send_eir+22
+p_check_tx_length:
+	ifetch 1,contr
+	rtn blank
+	increase 1,temp
+	loop p_check_tx_length
+	rtn
+
+p_slave_dispatch:
+	jam 0,mem_check_attempt_limit
+	branch slave_dispatch+1
+
+
+p_slave_loop:
+//	bpatch patch07_2,mem_patch07
+	fetch 1,mem_check_attempt_limit
+	increase 1,pdata
+	store 1,mem_check_attempt_limit
+	call scheduler_process
+	call slave_conn_recv_packet	/* go listen for a packet */
+	nbranch slave_notmatch,match
+	call supervision_flush
+	call scheduler_tx_l2cap_pkt
+	call prepare_tx
+	call set_flow_flag
+	call slave_conn_send_packet
+	call parse_l2cap
+	call parse_lmp
+	call p_process_cmd
+	branch slave_loop+12
+
+p_master_loop:
+	call parse_lmp
+	call p_process_cmd
+	branch master_loop+3
+
+p_process_cmd:
+	fetch 1,mem_hci_cmd
+	rtn blank
+	fetch 1,mem_lmo_opcode2
+	nrtn blank
+	branch z_process_cmd
+
+
+p_hci_send_connection_complete:
+	jam 2,mem_conn_status
+	//force 0,temp
+	jam 0x00,mem_mesh_event_parameter_status
+//	jam 0,mem_scan_mode
+	branch p_hci_send_connection_rtn_error
+p_hci_send_connection_error:
+	//force HCI_EVENT_CONNECTION_COMPLETE,queue
+	//Status(1),Connection_Handle(2),BD_ADDR(6),Link_Type(1),Encryption_Enabled(1)
+	jam 0,mem_conn_status
+	jam 0,mem_conn_req_status
+p_hci_send_connection_rtn_error:	
+	jam 0,mem_io_cap_flag
+	branch z_hci_send_connection_rtn_error
+
+
+p_inquiry_receive_rtn:
+	fetch 1,mem_inquiry_num_check
+	branch z_hci_inquiry_reply_check_eir,blank
+	fetch 1,mem_inquiry_num_responses
+	branch z_hci_send_inquiry_comple,blank
+	increase -1,pdata
+	store 1,mem_inquiry_num_responses
+	branch z_hci_inquiry_reply_check_eir
+
+
+	
+p_rssi_convert:
+	fetch 1,mem_rssi
+	rshift4 pdata,temp
+	mul32 temp,10,temp
+	and pdata,0x0f,pdata
+	iadd temp,temp
+	sub temp,0,pdata
+	rtn
+
+
+p_master_page_timeout:	
+	call master_page_timeout+1
+//	fetch 1,mem_conn_status
+	//rtnne 1
+//	bne 1,assert
+	fetch 1,mem_hci_remote_name_req_flag
+	nbranch p_hci_send_remote_name_request_complete,blank
+	jam PAGE_TIMEOUT,mem_mesh_event_parameter_status
+	branch p_hci_send_connection_error 
+//<quit_connection> will call zcode, so should not push to zcode
+p_master_disconnect:
+	//bpatch patch03_6,mem_patch03
+	call quit_connection
+	disable master
+	fetch 1,mem_conn_status
+	beq 1,p_master_page_timeout
+	fetch 1,mem_state_map
+	bbit1 smap_name_req,master_name_disconnect
+	fetch 1,mem_state
+	bbit0 state_conn_comp,master_disconnect_quiet
+	branch p_hci_send_disconnect_complete
+	
+p_estimate_event_head_event_code:
+	fetch 1,mem_inquiry_mode
+	beq 0,p_hci_event_inquiry_result
+	beq 1,p_hci_event_inquiry_result_with_rssi
+	beq 2,p_hci_event_extended_inquiry_result
+	jam HCI_EVENT_INQUIRY_RESULT,mem_mesh_event_head_event_code
+	rtn
+p_hci_event_inquiry_result:
+	jam 15,mem_mesh_event_para_total_length
+	jam HCI_EVENT_INQUIRY_RESULT,mem_mesh_event_head_event_code
+	rtn
+p_hci_event_inquiry_result_with_rssi:
+	jam 15,mem_mesh_event_para_total_length
+	jam HCI_EVENT_INQUIRY_RESULT_WITHRSSI,mem_mesh_event_head_event_code
+	rtn
+p_hci_event_extended_inquiry_result:
+	jam 255,mem_mesh_event_para_total_length
+	jam HCI_EVENT_EXT_INQUIRY_RESULT,mem_mesh_event_head_event_code
+	rtn
+
+p_parse_lmp_name_res:
+	fetch 1,mem_hci_remote_name_req_flag
+	branch parse_lmp_name_res,blank
+	
+	fetch 2,mem_len
+	add pdata,-3,loopcnt	//for remote name length error
+	fetcht 1,mem_rxbuf+1
+	setarg mem_tmp_buffer
+	iadd temp,contw
+	arg mem_rxbuf+3,contr
+	call memcpy
+	call p_hci_save_mem_hci_remote_name
+	fetcht 1,mem_name_offset
+	fetch 1,mem_rxbuf+2	
+	isub temp,pdata
+	sub pdata,14,null
+	branch p_hci_send_remote_name_request_complete,positive
+	branch parse_lmp_name_res+12
+//	branch p_hci_send_remote_name_request_complete
+p_hci_send_remote_name_request_complete:
+	jam 255,mem_mesh_event_para_total_length
+	jam HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0x00
+	istore 1,contw
+	fetch 6,mem_hci_plap
+	istore 6,contw
+ 	arg 64,loopcnt
+	arg mem_hci_remote_name,contr
+	call memcpy_fast
+	arg 184,loopcnt
+	call memset0
+	call ipc_hci_tx_start
+p_hci_remote_name_request_flag_init:
+	fetch 1,mem_hci_remote_name_req_flag
+	jam 0,mem_hci_remote_name_req_flag
+	jam 0,mem_name_offset
+	beq 2,p_hci_send_remote_name_request_complete_detach
+	branch parse_lmp_name_res_end
+p_hci_send_remote_name_request_complete_detach:
+	call lmp_disconnect+1
+	branch parse_lmp_name_res_end
+
+p_hci_save_mem_hci_remote_name:
+	fetcht 1,mem_rxbuf+1	
+	setarg mem_hci_remote_name
+	iadd temp,contw
+
+	fetch 1,mem_rxbuf+2
+	fetcht 1,mem_rxbuf+1	
+	isub temp,loopcnt
+	
+	arg mem_rxbuf+3,contr
+	branch memcpy_fast
+	
+	
+
+p_check_attempt:
+	fetch 1,mem_check_attempt_limit
+	sub pdata,100,null
+	nbranch check_attempt_nomore,positive
+	branch check_attempt+1
+
+p_hci_parse_connection_handle_check:
+	call p_ipc_rx_hci_data_two_byte
+	fetcht 1,mem_conn_handle
+	isub temp,null
+	rtn zero
+	branch p_hci_send_event_command_complete_error_command_disallowed
+
+p_roles_newconn_loop:
+	call master_newconn_once
+	branch p_roles_newconn_responded,sync
+	call new_conn_timeout
+	nbranch p_roles_newconn_loop,blank
+	disable clknt
+	deposit clke_bt
+	store 4,mem_next_btclk
+	rtn
+p_roles_newconn_responded:
+	call roles_newconn_responded
+	jam 0,mem_mesh_event_parameter_status
+	branch z_hci_send_role_change
+
+
+p_role_switch_master:
+	call role_switch_check
+	nrtn user
+	disable user
+	jam param_newconnto,mem_newconnto_counter
+	set0 mark_fhs_already_good,mark
+p_roles_waitfhs_loop:
+	call rf_setup_time_master_slot
+	call master_recv_packet
+	bmark1 mark_fhs_already_good,p_roles_replyto_fhs
+	call new_conn_timeout
+	nbranch p_roles_waitfhs_loop,blank
+p_role_switch_fail_master:
+	disable user
+	deposit clkn_bt
+	store 4,mem_next_btclk
+	enable clknt
+	enable master
+	branch z_hci_send_role_change_err
+	
+p_roles_replyto_fhs:
+	call rf_setup_time_slave_slot
+	arg type_id,type
+	call master_send_packet
+	disable clknt
+	disable master
+	call apply_switch_clke
+	call prepare_newconn
+p_roles_newconns_loop:
+	call slave_newconn_once
+	branch p_roles_newconns_responded,match
+	call new_conn_timeout
+	nbranch p_roles_newconns_loop,blank
+	branch p_role_switch_fail_master
+p_roles_newconns_responded:
+	force 1,temp
+	fetch 1,mem_mode
+	set0 mode_master,pdata
+	store 1,mem_mode
+	call supervision_flush
+	call calc_clke_offset
+	enable user
+	jam 1,mem_mesh_event_parameter_status
+	branch z_hci_send_role_change		
+
+//<quit_connection> will call zcode, so should not push to zcode
+p_slave_disconnect:
+	//bpatch patch07_6,mem_patch07
+	jam 0,mem_tester_emulate
+	jam 0,mem_debug_config
+	call quit_connection
+	set0 mark_testmode,mark
+	call test_enable_white
+	fetch 1,mem_conn_status
+	rtn blank
+	branch p_hci_send_disconnect_complete		
+/* lmp is not recognized, check to see if we respond to all messages */ 
+/* rejecting the unrecognized message with PDU not recognized */
+//p_reject_unknown_packet:
+//	jam UNKNOWN_LMP_PDU,mem_lmo_reason2
+//p_reject_lmp_packet:
+//	jam LMP_NOT_ACCEPTED,mem_lmo_opcode2
+//	rtn
+
+// <linkkey_ready> will call zcode, so should not push to zcode
+p_authentication_event:
+	call authentication_ok
+	rtnmark1 mark_slave_in_rand_accepted
+	branch p_hci_send_auth_complete
+p_linkkey_ready:
+	fetch 1,mem_state
+	bbit1 state_linkkey,linkkey_set
+	fetch 1,mem_pairing_auth
+	branch linkkey_set,blank
+	jam DEFALT_PAIRING_AUTH,mem_pairing_auth
+	//jam BT_EVT_LINKKEY_GENERATE,mem_fifo_temp
+	//call ui_ipc_send_event
+	
+	fetch 1,mem_op
+	isolate1 op_auth_req,pdata
+	set0 op_auth_req,pdata
+	store 1,mem_op
+//	call p_hci_send_auth_complete,true
+	call linkkey_set
+	rtnmark1 mark_slave_in_rand_accepted
+	branch z_hci_send_linkkey_notification
+
+
+
+p_hci_send_auth_complete:
+	jam 3,mem_mesh_event_para_total_length
+	jam HCI_EVENT_AUTHENTICATION_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	force 0,pdata
+	istore 1,contw
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+p_hci_send_linkkey_req_event:
+	//BD_ADDR(6)
+	jam 6,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LINK_KEY_REQUEST,mem_mesh_event_head_event_code
+p_hci_send_sec_req:	//used by linkkey and pin req 
+	call p_hci_prepare_send_event
+	fetch 6,mem_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+p_hci_send_pincode_req_event:
+	//BD_ADDR(6)
+	jam 6,mem_mesh_event_para_total_length
+	jam HCI_EVENT_PIN_CODE_REQUEST,mem_mesh_event_head_event_code
+	branch p_hci_send_sec_req
+
+
+p_ipc_rx_process:
+	fetch 1,mem_ipc_enable
+	rtn blank
+	call ipc_rx_items_inquire
+	rtn zero // no data
+	icopy contr
+	call ipc_rx_byte_read
+
+	beq IPC_TYPE_CM0_TO_BT_DATA,ipc_rx_data_buf
+	branch ipc_rx_process+7
+
+ifdef FUNCTION_WATCH_DOG
+p_wdt_kick_watchdog:
+	//fetch 1,mem_ota_wdt_en_flag
+	//beq 0xaa,p_ota_change_code_wdt
+	call wdt_set_watchdog_mode_reset
+	branch wdt_kick_watchdog_1_5s
+endif //FUNCTION_WATCH_DOG
+//p_ota_change_code_wdt:
+//	fetch 1,mem_ota_wdt_m0_en
+//	beq 0x55,p_wdt_kick_watchdog+2
+//	rtn
+
+
+// input: contw,loopcnt
+// output: null
+p_ipc_rx_hci_data_n_byte:
+	call p_ipc_rx_restore_contr
+	call memcpy_fast
+	branch p_ipc_rx_store_contr
+
+p_ipc_rx_hci_data_two_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 2,contr
+	branch p_ipc_rx_store_contr
+p_ipc_rx_hci_data_thr_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 3,contr
+	branch p_ipc_rx_store_contr
+p_ipc_rx_hci_data_six_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 6,contr
+	branch p_ipc_rx_store_contr
+p_ipc_rx_hci_data_seven_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 7,contr
+	branch p_ipc_rx_store_contr
+p_ipc_rx_hci_data_eight_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 8,contr
+	branch p_ipc_rx_store_contr
+
+p_ipc_rx_hci_data_one_byte:
+	call p_ipc_rx_restore_contr
+	ifetch 1,contr
+p_ipc_rx_store_contr:
+	copy contr,temp
+p_ipc_rx_store_contr1:
+	storet 3,mem_ipc_rx_ptr
+	rtn
+	
+p_ipc_rx_restore_contr:
+	fetcht 3,mem_ipc_rx_ptr
+	copy temp,contr
+	rtn
+p_white_filter_connect_filter:
+	jam WHITE_LIST_CONNECT_FILTER,mem_le_white_list_filter_policy
+	rtn
+p_parse_le_controller_create_connection:
+	jam ON,mem_le_scan_enable
+	jam CREAT_CONNECTION,mem_mesh_creat_connection_flag
+	branch p_hci_send_event_command_status
+
+/*
+p_hci_parse_packet_acl:
+	call le_fifo_check_full
+	nrtn blank
+	hfetch 2,core_uart_rxitems
+	add pdata,-5,rega
+	nrtn positive
+	call p_hci_parse_packet_acl_FB_flag
+	ifetch 2,contru
+	increase 1,rega		//´َسعµبسع
+	isub rega,null
+	rtn positive
+	copy pdata,rega
+	copy pdata,regb
+	call le_fifo_malloc_tx
+	copy regb,loopcnt
+	call uart_copy_rx_bytes_fast
+	call uartd_prepare_rx
+	increase 3,contru
+	ifetch 2,contru
+	iadd contru,contru
+	fetch 1,mem_mesh_recevie_acl_packet_number
+	pincrease 1
+	store 1,mem_mesh_recevie_acl_packet_number
+	branch uartd_rxdone
+
+p_hci_parse_packet_acl_FB_flag:
+	ifetch 2,contru
+	rshift8 pdata,pdata
+	rshift4 pdata,pdata
+	force LLID_CONTINUE,type
+	rtneq BT_ACL_CONT
+	force LLID_START,type
+	rtn
+*/
+
+/*********
+	HCI_OGF_LINK_CONTROL
+*********/
+
+
+
+
+/*********
+	HCI_OGF_LINK_POLICY
+*********/
+
+
+/*********
+	HCI_OGF_CONTROLLER_AND_BASEBAND
+*********/
+
+
+
+p_hci_init_bd_address:
+	fetch 6,mem_device_public_address
+	store 6,mem_le_lap
+	store 6,mem_lap
+	rtn
+	
+	
+/*********
+	HCI_OGF_LE_CONTROLLER
+*********/
+	
+
+
+
+// input: rega	return pdata=0:true  pdata = 1:false
+p_check_addr_in_white_list:
+ifdef WHITE_LIST
+	fetch 1,mem_le_white_list_cnt
+	copy pdata,loopcnt
+	arg mem_le_white_list,regb
+p_check_addr_in_white_list_loop:
+	ifetch 7,regb
+	fetcht 7,mem_le_white_list_type_and_bd_addr
+	isub temp,null
+	setarg 0
+	rtn zero
+	increase 7,regb
+	loop p_check_addr_in_white_list_loop
+	setarg 1
+endif
+	rtn
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// input: regb: payload ptr
+ipc_tx_bt_data_buf_free:
+	jam IPC_DATA_SUBTYPE_FREE,mem_ipc_data_tx_buf_subtype
+	branch ipc_tx_bt_data_buf_with_type
+
+// input: regb: payload ptr
+ipc_tx_bt_data_buf_hci:
+	jam IPC_DATA_SUBTYPE_HCI,mem_ipc_data_tx_buf_subtype
+	branch ipc_tx_bt_data_buf_with_type
+
+// input: regb: payload ptr
+//ipc_tx_bt_data_buf_ble:
+//	jam IPC_DATA_SUBTYPE_BLE,mem_ipc_data_tx_buf_subtype
+//	branch ipc_tx_bt_data_buf_with_type
+
+// input: regb: payload ptr
+//ipc_tx_bt_data_buf_br:
+//	jam IPC_DATA_SUBTYPE_SPP,mem_ipc_data_tx_buf_subtype
+//	branch ipc_tx_bt_data_buf_with_type
+	
+ipc_tx_bt_data_buf_with_type:
+	storer regb,3,mem_ipc_data_tx_buf_payload_ptr
+// input: mem_ipc_tx_data_buf_subtype, mem_ipc_data_buf_payload_ptr
+ipc_tx_bt_data_buf:
+ifdef TEST_QUEUE_DEBUG
+	arg 0x7100,rega
+	fetcht 1,mem_ipc_data_tx_buf_subtype
+	call debug_log_print
+	arg 0x7101,rega
+	fetcht 2,mem_ipc_data_tx_buf_payload_ptr
+	call debug_log_print
+endif
+
+	//fetch 1,mem_ipc_enable
+	//rtn blank
+	setarg mem_ipc_tx_buf
+	store 2,mem_ipc_tx_data_ptr
+	icopy contw
+	setarg IPC_TYPE_BT_TO_CM0_DATA
+	istore 1,contw
+	force 4,pdata // len
+	istore 1,contw
+	
+	fetch 1,mem_ipc_data_tx_buf_subtype
+	istore 1,contw
+	
+	fetch 3,mem_ipc_data_tx_buf_payload_ptr
+	istore 3,contw
+
+	 // total len
+	force 6,pdata
+	store 1,mem_ipc_tx_data_len
+	branch ipc_tx_common
+	
+ifdef ipc_zcode_test
+p_ipc_rx_hci:
+	fetcht 3,mem_ipc_data_rx_buf_payload_ptr
+	call p_ipc_rx_store_contr1
+	call p_ipc_rx_hci_data_one_byte
+	beq HCI_H4_TYPE_CMD,p_hci_parse_packet_cmd
+	beq HCI_H4_TYPE_ACL,p_hci_parse_packet_acl
+	branch assert
+endif
+
+ipc_rx_data_buf_sub_hci_data:
+	call z_ipc_rx_hci
+	fetchr regb,3,mem_ipc_data_rx_buf_payload_ptr
+	branch ipc_tx_bt_data_buf_free
+
+
+ipc_rx_data_buf_sub_free_buf:
+	call ipc_rx_data_buf_free_ipc_work
+	fetchr regb,3,mem_ipc_data_rx_buf_payload_ptr
+	branch free_buffer
+ipc_rx_data_buf_free_ipc_work:
+	call p_ipc_rx_restore_contr
+	arg 3,loopcnt
+	arg mem_ipc_data_rx_buf_payload_ptr,contw
+	branch ipc_rx_block_read
+
+ipc_rx_data_buf:
+	// ipc total length
+	call ipc_rx_byte_read
+	// subType
+	call ipc_rx_byte_read
+	store 1,mem_ipc_data_rx_buf_subtype
+	call p_ipc_rx_store_contr
+	
+	fetch 1,mem_ipc_data_rx_buf_subtype
+	beq IPC_DATA_SUBTYPE_FREE,ipc_rx_data_buf_sub_free_buf
+
+	// make sure have buffer to do this.
+	call malloc_buffer_is_full
+	rtn blank
+
+	call ipc_rx_data_buf_free_ipc_work
+
+ifdef TEST_QUEUE_DEBUG
+	arg 0x7000,rega
+	fetcht 1,mem_ipc_data_rx_buf_subtype
+	call debug_log_print
+	arg 0x7001,rega
+	fetcht 2,mem_ipc_data_rx_buf_payload_ptr
+	call debug_log_print
+endif
+
+	fetch 1,mem_ipc_data_rx_buf_subtype
+	beq IPC_DATA_SUBTYPE_HCI,ipc_rx_data_buf_sub_hci_data
+	branch assert
+
+
+
+
+p_hci_send_event_command_complete_error_command_invalid_param:
+	jam COMMAND_INVALID_HCI_COMMAND_PARAMETERS,mem_mesh_command_complete_return_parameter_status
+	branch p_hci_send_event_command_complete_without_payload+1
+p_hci_send_event_command_complete_error_command_nuknown:
+	jam COMMAND_UNKNOWN,mem_mesh_command_complete_return_parameter_status
+	branch p_hci_send_event_command_complete_without_payload+1
+p_hci_send_event_command_complete_error_command_disallowed:
+	jam COMMAND_DISALLOWED,mem_mesh_command_complete_return_parameter_status
+	branch p_hci_send_event_command_complete_without_payload+1
+p_hci_send_event_command_complete_without_payload:
+	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
+	arg 1,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status
+	branch ipc_hci_tx_start
+	
+p_hci_prepare_send_event_command_complete_with_status_success:
+	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
+p_hci_prepare_send_event_command_complete_with_status:
+	call p_hci_prepare_send_event_command_complete
+	fetch 1,mem_mesh_command_complete_return_parameter_status
+	istore 1,contw
+	rtn
+
+p_hci_prepare_send_event_command_complete:
+	jam HCI_EVENT_COMMAND_COMPLETE,mem_mesh_event_head_event_code
+	add loopcnt,3,pdata
+	store 1,mem_mesh_event_para_total_length
+	call p_hci_prepare_send_event
+	//Num_HCI_Command_Packets(1Byte), Command_Opcode(2Byte)
+	fetch 3,mem_mesh_command_complete_num_hci_command_packet
+	istore 3,contw
+	rtn
+
+p_hci_send_event_command_status:
+	jam COMMAND_CURRENTLY_PENDING,mem_temp
+	branch p_hci_send_event_command_status_raw
+p_hci_send_event_command_status_err_command_disallowed:
+	jam COMMAND_DISALLOWED,mem_temp
+	branch p_hci_send_event_command_status_raw
+p_hci_send_event_command_status_err_unknown_connection:
+	jam HCI_ERROR_NO_CONNECTION,mem_temp
+p_hci_send_event_command_status_raw:
+	jam HCI_EVENT_COMMAND_STATUS,mem_mesh_event_head_event_code
+	jam 4,mem_mesh_event_para_total_length
+	call p_hci_prepare_send_event
+	fetch 1,mem_temp
+	istore 1,contw
+	fetch 3,mem_mesh_command_complete_num_hci_command_packet
+	istore 3,contw
+	branch ipc_hci_tx_start
+
+p_hci_send_event_le_disconnection_complete:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 DISCONNECTION_COMPLETE_EVENT
+	fetch 1,mem_le_conn_handle
+	store 1,mem_hci_record_disc_conn_handle
+	branch z_hci_send_disconnect_complete
+p_hci_send_disconnect_complete:
+	//status(1), connection_handle(2), Reason(1)
+	fetch 1,mem_conn_handle
+	store 1,mem_hci_record_disc_conn_handle
+p_hci_send_disconnect_complete_init_connection_classic:
+	set0 mark_slave_in_rand_accepted,mark
+	jam 0,mem_conn_handle
+	jam 0,mem_conn_req_status
+	jam 0,mem_conn_status
+	branch z_hci_send_disconnect_complete
+
+
+p_le_get_role:
+	fetch 1,mem_le_mode
+	arg HCI_ROLE_MASTER,temp
+	rtneq lemode_master
+	arg HCI_ROLE_SLAVE,temp
+	rtn
+
+
+
+le_scan_check_event_type:
+	fetch 1,mem_le_rxbuf
+	and pdata,0x0f,pdata
+	arg 0,temp		//adv ind
+	rtneq ADV_IND
+	arg 1,temp		//adv direct ind
+	rtneq ADV_DIRECT_IND
+	arg 2,temp
+	rtneq ADV_SCAN_IND
+	arg 3,temp
+	rtneq ADV_NONCONN_IND
+	arg 4,temp
+//	rtneq SCAN_RSP
+	rtn
+
+p_hci_send_event_le_advertising_report:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 LE_ADVERTISING_REPORT_EVENT
+	arg 6,pdata
+	fetcht 1,mem_le_rxbuf+1	//length
+	iadd temp,pdata
+	store 1,mem_mesh_event_para_total_length
+
+	increase 3,pdata // evt type(04), evt code
+	store 2,mem_alloc_buffer_len
+	//call malloc_buffer_is_enough
+	//rtn blank
+
+	arg mem_alloc_big_block,rega
+	call p_queue_get_len
+	sub pdata,2,null
+	rtn positive
+
+	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+
+	setarg HCI_LE_SUBEVENT_ADV_REPORT
+	istore 1,contw		//subevent code
+	setarg 0x01
+	istore 1,contw		//Num reprot only 1
+	call le_scan_check_event_type
+	istoret 1,contw		//event type is ADV_IND
+	call le_scan_check_sender_addr_type
+	copy rega,pdata
+	istore 1,contw		//event type
+	fetcht 1,mem_le_rxbuf+1 //length
+	increase -6,temp
+	//fetch 6,mem_le_plap
+	ifetch 6,contr			//addr type
+	istore 6,contw
+	istoret 1,contw
+	copy temp,loopcnt
+	call memcpy_fast
+	call p_rssi_convert
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+
+
+
+
+
+
+
+
+
+p_hci_send_event_number_of_completed_packet_classic:
+	fetch 1,mem_conn_handle
+	store 1,mem_hci_conn_handle
+	branch p_hci_send_event_number_of_completed_packet
+p_hci_send_event_number_of_completed_packet_le:
+	fetch 1,mem_le_conn_handle
+	store 1,mem_hci_conn_handle
+p_hci_send_event_number_of_completed_packet:
+	jam 5,mem_mesh_event_para_total_length
+	jam HCI_EVENT_NUM_COMPLETED_PACKETS,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0x01 // Number of Handles: 1
+	istore 1,contw
+	fetch 1,mem_hci_conn_handle
+	istore 2,contw
+	setarg 0x01 // Num Completed Packets: 1
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+//mem_mesh_event_head_event_code:event code
+//mem_mesh_event_para_total_length:parameter total length
+p_hci_prepare_send_event:
+	fetch 1,mem_mesh_event_para_total_length
+	increase 3,pdata // evt type(04)(1Byte), evt code(1Byte), evt len(1Byte)
+	store 2,mem_alloc_buffer_len
+
+	call ipc_hci_prepare_tx
+
+	fetch 3,mem_mesh_event_head_type
+	istore 3,contw
+	rtn
+
+ipc_hci_prepare_tx:
+	call malloc_hci_snd_buffer
+	copy regb,contw
+	rtn
+	
+ipc_hci_tx_start:
+	arg mem_snd_hci_block,rega
+	call queue_delete
+	branch ipc_tx_bt_data_buf_hci
+
+p_le_send_empty:
+	force 0,temp
+	force 1,type
+p_le_send_packet:
+	storet 1,mem_le_txlen_temp
+	fetcht 1,mem_le_arq
+	set1 wak,temp
+	and temp,0xfc,pdata
+	ior type,pdata
+	store 1,mem_le_arq
+	and_into 0x1f,pdata
+	isolate1 mark_ble_tx_md,mark
+	setflag true,md,pdata
+	store 1,mem_le_txheader_temp
+	rtn
+
+
+
+p_le_prepare_tx:
+	fetch 1,mem_le_arq
+	rtnbit1 wak
+
+	call p_le_check_tx_md
+	
+	call p_le_malloc_fifo_out
+	branch p_le_send_empty,blank	
+	ifetch 1,contr		//total length
+	ifetchr rega,1,contr	//offset	
+	isub rega,pdata
+	copy contr,contw
+	fetcht 2,mem_remote_rx_max_octets
+	call not_greater_than
+	copy pdata,temp
+	copy contw,contr
+	ifetchr type,1,contr
+	copy rega,pdata
+	iadd contr,contr   
+	arg mem_le_txpayload_temp,contw
+	copy temp,loopcnt
+	call memcpy_fast	
+	call le_update_tx_type
+	call p_le_send_packet
+
+	call p_le_malloc_fifo_out
+	ifetch 1,contr
+	copy pdata,rega
+	copy contr, regd
+	ifetchr regb,1,contr
+	isub regb,pdata
+	fetcht 2,mem_remote_rx_max_octets
+	call not_greater_than
+	iadd regb,pdata
+	istore 1,regd  	//update offset
+	isub rega,null
+	nrtn zero
+	branch le_fifo_release_first_node
+
+p_le_check_tx_md:
+	fetch 1,mem_le_more_data
+	branch le_clear_md,blank
+	
+	call p_le_check_continue
+	rtnmark1 mark_ble_tx_md
+	
+	arg mem_snd_ble_block,rega
+	call p_queue_get_len	
+	beq 0,le_clear_md
+	beq 1,le_clear_md
+	set1 mark_ble_tx_md,mark
+	rtn
+
+p_le_check_continue:
+	call p_le_malloc_fifo_out
+	branch le_clear_md,blank
+	ifetch 1,contr				//pdata:length
+	ifetcht 1,contr				//temp:offest
+	isub temp,temp			//temp:length - offset
+	fetch 2,mem_remote_rx_max_octets
+	isub temp,null
+	branch le_clear_md,positive				//27 > length -offset
+	set1 mark_ble_tx_md,mark
+	rtn
+
+p_le_malloc_fifo_out:
+	arg mem_snd_ble_block,rega
+	branch queue_get_read_ptr		
+
+
+p_le_transmit_norx:
+	call p_le_transmit
+	branch end_of_packet
+
+
+p_le_transmit:
+	call le_prep
+	call letx_setfreq
+	call rf_debug_active_tx_line
+	set1 TXGFSK,radio_ctrl
+	enable encode_fec0
+	enable is_tx
+	disable is_rx
+	call le_wait_tx
+	rshift16 access,pdata
+	rshift8 pdata,pdata
+	rshift4 pdata,pdata
+	inject mod,40
+	enable enable_white
+	enable enable_crc
+p_le_transmit0:	
+	fetch 1,mem_le_txheader_temp
+	inject mod,8
+	ifetch 1,contr
+	copy pdata,loopcnt
+	inject mod,8
+	branch letr_nopayload,zero
+	branch letr_loop	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+p_le_slave_match:
+ifdef RF_DEBUG
+	call rf_debug_active_sync_line
+endif
+	call le_got_first_packet
+	call le_acknowledge
+	call p_le_prepare_tx
+	call p_le_transmit_norx
+	call p_le_parse
+	call le_check_md
+	branch p_le_slave_more_data,user
+	branch le_slave_cont
+
+
+	
+p_le_send_connection_update_ind:
+	fetch 1,mem_le_state
+	set1 lestate_update_param,pdata
+	store 1,mem_le_state
+	
+	jam 1,mem_le_new_transmitwindowsize // window size 1 1.25ms
+	setarg 0x3
+	store 2,mem_le_new_transmitwindowoffset //window offset 3 3.75ms
+	fetch 2,mem_le_conn_interval
+	store 2,mem_le_new_conninterval  // event interval 30 37.5ms
+	fetch 2,mem_le_conn_latency
+	store 2,mem_le_new_connslavelatency // latency 
+	fetch 2,mem_le_conn_superto
+	store 2,mem_le_new_connsupervisiontimeout //supervision timeout 500 5s
+	fetch 2,mem_le_event_count
+	increase 0x10,pdata
+	store 2,mem_le_instant
+	arg 12,rega
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_CONNECTION_UPDATE_REQ
+	istore 1,contw
+	//winsize winoffset
+	fetch 9,mem_le_new_param
+	istore 9,contw
+	fetch 2,mem_le_instant
+	istore 2,contw
+	call clear_le_cmd
+	branch z_hci_send_le_connection_update_commplete
+	
+p_le_create_conn:
+	fetch 6,mem_le_plap
+	fetcht 6,mem_le_conn_peer_addr
+	isub temp,null
+	nrtn zero
+	call context_new
+	nrtn zero
+	call le_connect_request
+	call le_init_master
+	jam 0,mem_hci_cmd
+	jam 0,mem_le_peer_sca
+
+	call le_create_conn_ndongle
+
+	//arg MASTER_CONNECTION_HANDLE,temp
+	branch z_hci_send_event_le_connection_complete
+
+
+
+	
+
+
+
+//p_hci_prepare_send_acl:
+//	fetch 2,mem_hci_acl_packet_len_recved
+//	increase 5,pdata // acl type(02)(1Byte), handle(2Byte), length(2Byte)
+//	store 2,mem_alloc_buffer_len
+
+//	branch ipc_hci_prepare_tx
+
+//p_hci_send_acl_encode_le:
+//	fetch 1,mem_le_packet_llid
+//	store 1,mem_hci_acl_packet_pb_flag
+//	fetch 2,mem_le_payload_ptr
+//	store 2,mem_hci_acl_packet_payload_ptr
+//	fetch 2,mem_le_l2cap_size
+//	store 2,mem_hci_acl_packet_len_recved
+//	fetch 1,mem_le_conn_handle
+//	store 2,mem_hci_conn_handle
+//p_hci_send_acl_encode:
+//	call p_hci_prepare_send_acl
+//	setarg HCI_H4_TYPE_ACL
+//	istore 1,contw
+//	fetch 1,mem_hci_conn_handle
+//	fetcht 1,mem_hci_acl_packet_pb_flag
+//	lshift8 temp,temp
+//	lshift4 temp,temp
+//	ior temp,pdata
+//	istore 2,contw
+
+//	fetcht 2,mem_hci_acl_packet_len_recved
+//	istoret 2,contw //length
+//	copy temp,loopcnt
+//	fetch 2,mem_hci_acl_packet_payload_ptr
+//	copy pdata,contr
+//	call memcpy_fast
+
+//	branch ipc_hci_tx_start
+
+
+p_hci_send_acl_encode_classic:
+	call p_get_br_rcv_ptr
+	store 3,mem_hci_acl_packet_payload_ptr
+	//free buffer
+	setarg 0
+	store 3,mem_rcv_br_queue_ptr
+
+	fetch 1,mem_conn_handle
+	store 1,mem_hci_conn_handle
+	jam IPC_DATA_SUBTYPE_ACL_CLASSIC,mem_ipc_data_tx_buf_subtype
+
+ifdef TEST_QUEUE_DEBUG
+	arg 0x7100,rega
+	fetcht 1,mem_ipc_data_tx_buf_subtype
+	call debug_log_print
+	arg 0x7101,rega
+	fetcht 2,mem_hci_acl_packet_payload_ptr
+	call debug_log_print
+endif
+
+	branch p_hci_send_acl_encode
+p_hci_send_acl_encode_le:
+	call p_get_ble_rcv_ptr
+	store 3,mem_hci_acl_packet_payload_ptr
+	//free buffer
+	setarg 0
+	store 3,mem_rcv_ble_queue_ptr
+
+	fetch 1,mem_le_conn_handle
+	store 1,mem_hci_conn_handle
+	jam IPC_DATA_SUBTYPE_ACL_BLE,mem_ipc_data_tx_buf_subtype
+p_hci_send_acl_encode:
+	setarg mem_ipc_tx_buf
+	store 2,mem_ipc_tx_data_ptr
+	icopy contw
+	setarg IPC_TYPE_BT_TO_CM0_DATA
+	istore 1,contw
+	force 6,pdata // len
+	istore 1,contw
+	
+	fetch 1,mem_ipc_data_tx_buf_subtype
+	istore 1,contw
+	
+	fetch 3,mem_hci_acl_packet_payload_ptr
+	istore 3,contw
+
+	fetch 1,mem_hci_conn_handle
+	istore 2,contw
+	
+
+	 // total len
+	force 8,pdata
+	store 1,mem_ipc_tx_data_len
+	
+	branch ipc_tx_common
+
+	
+
+
+p_le_init_conn:
+	call le_init_conn+1
+	jam 1,mem_le_txheader_temp
+	jam 0,mem_le_txlen_temp
+	setarg 27
+	store 2,mem_remote_rx_max_octets
+	call new_conn_handle
+	pincrease 24
+	store 1,mem_le_conn_handle
+	rtn	
+
+
+p_le_conn_dispatch:
+	call le_enable
+	call app_process_ble
+	fetch 1,mem_le_mode
+	beq lemode_master,p_le_master_dispatch
+	branch le_slave_dispatch
+
+p_hci_parse_packet_cmd_ogf_le_controller_connection_update:
+		call p_ipc_rx_hci_data_two_byte
+		store 1,mem_hci_conn_handle      //connect handle
+		call p_ipc_rx_hci_data_two_byte   //connect interval min
+		lshift2 pdata,pdata
+		store 2,mem_le_conn_interval
+		call p_ipc_rx_hci_data_two_byte  //connect interval max
+		call p_ipc_rx_hci_data_two_byte		//connect latency
+		store 2,mem_le_conn_latency	
+		call p_ipc_rx_hci_data_two_byte		//supervision timeout
+		store 2,mem_le_conn_superto
+		call app_ble_master_update_conn
+		branch p_hci_send_event_command_status
+
+
+
+p_le_transmit_receive_sifs_master:
+	call p_le_transmit
+	branch p_le_transmit_receive_sifs_notx_slave
+p_le_master_sm:
+	fetch 1,mem_le_master_sm
+	beq LE_MASTER_SM_NULL,p_le_master_sm_null	
+	beq LE_MASTER_SM_SEND_VERSION,p_le_master_sm_send_version
+	beq LE_MASTER_SM_RCV_VERSION,p_le_master_sm_rcv_version
+	beq  LE_MASTER_SM_SEND_FEATURES,p_le_master_sm_send_features
+	beq LE_MASTER_SM_RCV_FEATURES,p_le_master_sm_rcv_features
+	beq LE_MASTER_SM_CHANNEL_MAP_IND,p_le_master_channel_map_match
+	rtn
+
+p_le_master_channel_map_match:
+	fetch 1,mem_le_state
+	set1 lestate_update_map,pdata
+	store 1,mem_le_state
+	setarg 0xffcf3ff3
+	store 4,mem_le_new_map
+	setarg 0x1f
+	istore 1,contw
+//	call le_update_channel_map
+	jam LE_MASTER_SM_END,mem_le_master_sm
+p_le_send_ll_channel_map_ind:
+	arg 12,rega
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_CHANNEL_MAP_REQ
+	istore 1,contw
+	fetch 5, mem_le_new_map
+	istore 5,contw
+	setarg conninstant
+	fetch 2,mem_le_event_count
+	increase 0x40,pdata
+	istore 2,contw
+	store 2,mem_le_instant
+	rtn
+	
+p_le_master_sm_null:
+	rtn
+p_le_master_sm_rcv_features:
+	jam LE_MASTER_SM_CHANNEL_MAP_IND,mem_le_master_sm
+	rtn
+p_le_master_sm_send_version:
+//	jam 20,mem_le_master_timer
+	jam LE_MASTER_SM_WAIT_VERSION,mem_le_master_sm
+	branch le_parse_version_ind+1
+
+p_le_master_sm_rcv_version:
+	jam LE_MASTER_SM_SEND_FEATURES,mem_le_master_sm
+	rtn
+	
+p_le_master_sm_send_features:
+	jam LE_MATSER_SM_WAIT_FEATURES,mem_le_master_sm
+	arg 9,rega
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_FEATURE_REQ
+	istore 1,contw
+	setarg param_le_features
+	istore 8,contw
+	rtn
+p_le_parse_feature_rsp_master:
+	fetch 1,mem_le_master_sm
+	rtnne LE_MATSER_SM_WAIT_FEATURES 
+	jam LE_MASTER_SM_RCV_FEATURES,mem_le_master_sm
+	rtn
+
+p_le_parse_version_ind_cmd_master:
+	fetch 1,mem_le_master_sm
+	rtnne LE_MASTER_SM_WAIT_VERSION
+	jam LE_MASTER_SM_RCV_VERSION,mem_le_master_sm
+	rtn
+	
+p_le_master_dispatch:	
+	enable master
+	call le_supervision_update
+	branch p_le_master_disconn,positive
+	call p_le_master_sm
+	call p_le_prepare_tx
+	call le_setup
+	disable match
+	call p_le_transmit_receive_sifs_master
+	nbranch p_le_master_not_match,match
+p_le_master_match:
+ifdef RF_DEBUG
+	call rf_debug_active_sync_line
+endif
+	call p_le_got_first_packet
+ifdef LE_CONN_RCV_DEBUG	
+	fetch 1,mem_le_conn_rcv
+	pincrease 1
+	store 1,mem_le_conn_rcv
+endif	
+	call le_acknowledge
+	call p_le_parse
+	call le_check_md
+	branch p_le_master_more_data,user
+p_le_master_cont:
+	call process_le_cmd
+	disable master
+	branch end_of_packet
+process_le_cmd:
+	fetch 1,mem_le_state
+	rtnbit1 lestate_update_map
+	fetch 1,mem_le_wait_process_cmd
+	rtn blank
+	beq BT_CMD_LE_MASTER_UPDATE_CONN,p_le_send_connection_update_ind
+	branch assert
+
+clear_le_cmd:
+	jam 0,mem_le_wait_process_cmd
+	rtn
+	
+app_ble_master_update_conn:	
+	jam BT_CMD_LE_MASTER_UPDATE_CONN,mem_le_wait_process_cmd
+	rtn
+	
+p_le_master_more_data:
+	call p_le_prepare_tx
+	call p_le_transmit_norx_master
+	enable attempt
+	call p_le_transmit_receive_sifs_notx_slave
+	branch p_le_master_match,match
+	branch p_le_master_cont
+
+
+p_le_transmit_norx_master:
+	call p_le_transmit_master
+	branch end_of_packet
+	
+p_le_transmit_master:
+	call le_prep
+	call letx_setfreq
+ifdef RF_DEBUG
+	call rf_debug_active_tx_line
+endif
+	set1 TXGFSK,radio_ctrl
+	enable encode_fec0
+	enable is_tx
+	disable is_rx
+	call p_le_wait_tx_cont
+	branch p_le_transmit+8
+
+p_le_wait_tx_cont:
+	until null,timeout
+	rtn
+
+
+p_le_got_first_packet:
+	fetch 1,mem_le_state
+	rtnbit1 lestate_got_first_packet
+	set1 lestate_got_first_packet
+	store 1,mem_le_state
+	jam LE_MASTER_SM_SEND_VERSION,mem_le_master_sm
+	rtn
+
+p_le_master_not_match:
+	fetch 1,mem_le_state
+	bbit1  lestate_got_first_packet,p_le_master_cont
+	fetch 1,mem_le_first_packet_count
+	sub pdata,6,null
+	nbranch p_le_master_disconn,positive
+	increase 1,pdata
+	store 1,mem_le_first_packet_count
+	branch p_le_master_cont
+
+
+
+
+
+
+
+
+
+
+
+
+p_le_get_public_addr:
+	fetcht 6,mem_le_lap
+	rtn
+	
+p_le_get_random_addr:
+	fetcht 6,mem_mesh_le_random_address
+	rtn
+
+
+p_le_send_adv_ind:
+	fetch 1,mem_le_adv_type
+	beq ADV_DIRECT_IND,le_send_adv_direct_ind
+	fetch 1,mem_le_adv_own_addr_type
+	lshift4 pdata,pdata
+	lshift2 pdata,pdata
+	fetcht 1,mem_le_adv_type
+	iadd temp,pdata
+	store 1,mem_le_txheader
+	fetcht 1,mem_le_adv_data_len
+	add temp,6,pdata
+	store 1,mem_le_txlen
+	copy temp,loopcnt
+	fetch 1,mem_le_adv_own_addr_type
+	call p_le_get_public_addr,blank
+	ncall p_le_get_random_addr,blank
+	storet 6,mem_le_txpayload
+	
+	arg mem_le_adv_data,contr
+	call memcpy_fast
+	branch le_send_adv_transmit	
+//	branch le_send_adv_ind+7
+
+p_le_update_param:
+	fetch 1,mem_le_state
+	rtnbit0 lestate_update_param
+	fetch 2,mem_le_event_count
+	fetcht 2,mem_le_instant
+	isub temp,pdata
+	store 2,mem_pdatatemp
+	nrtn positive
+	call le_update_param+7
+	branch z_hci_send_le_connection_update_commplete
+
+pop_stack_rega_b_c:
+	fetchr rega,4, mem_rega
+	fetchr regb,4, mem_regb
+	fetchr regc,3,mem_regc
+	rtn
+
+push_stack_rega_b_c:
+	storer rega,4, mem_rega
+	storer regb,4, mem_regb
+	storer regc,3, mem_regc
+	rtn
+p_le_context_nextevent:
+	call push_stack_rega_b_c
+	storer loopcnt,2,mem_loopcnt
+	add rega,coffset_mode,contr
+	ifetch 1,contr
+	rtnbit0 mode_le
+	add rega,coffset_le_event_cnt,contw
+	ifetch 2,contw
+	increase 1,pdata
+	istore 2,contw
+	call p_le_update_param_master
+	call p_le_update_channel_map
+	call  le_context_nexthop+8
+	call pop_stack_rega_b_c
+	fetchr loopcnt ,2,mem_loopcnt
+	rtn
+	
+//input: rega
+p_le_calc_channel_map:
+	add rega,coffset_le_channel_map,contr
+	ifetch 5,contr
+	force 0,temp
+	force 37,loopcnt
+p_le_count_channels_loop:
+	bbit0 0,le_count_channels_notused
+	increase 1,temp
+p_le_count_channels_notused:
+	rshift pdata,pdata
+	loop p_le_count_channels_loop
+	add temp,-1,pdata
+	add rega,coffset_le_channels,contw
+	istore 1,contw
+	rtn
+p_le_update_channel_map:
+	add rega,coffsset_state,contr
+	ifetch 1,contr
+	rtnbit0 lestate_update_map
+	
+	add rega,coffset_le_event_cnt,contr
+	ifetch 2,contr
+	fetcht 2,mem_le_instant
+	isub temp,pdata
+	nrtn positive
+	add rega,coffsset_state,contw
+	ifetch 1,contw
+	set0 lestate_update_map,pdata
+	istore 1,contw
+	store 1,mem_le_state
+	
+ 	fetch 5,mem_le_new_map
+ 	add rega,coffset_le_channel_map,contw
+	istore 5,contw
+	branch p_le_calc_channel_map	
+p_le_update_param_master:
+	add rega,coffsset_state,contr
+	ifetch 1,contr
+	rtnbit0 lestate_update_param	
+	add rega,coffset_mode,contr
+	ifetch 1,contr
+	rtnbit0 mode_master
+	add rega,coffset_le_event_cnt,contr
+	ifetcht 2,contr
+	fetch 2, mem_le_instant
+	isub temp,pdata
+	//nbranch p_le_check_update_small,positive
+	sub pdata,1,null
+	branch p_le_update_param_m,zero
+	rtn
+
+p_le_check_update_small:
+	add rega,coffset_le_event_cnt,contr
+	ifetch 2,contr
+	add rega,coffset_le_instant,contr
+	ifetch 2,contr
+	isub temp,pdata
+	arg 0xffff,temp
+	isub temp,null
+	branch p_le_update_param_m,zero
+	rtn
+
+p_le_update_param_m:
+	ifetch 1,rega
+	set0 lestate_update_param,pdata
+	istore 1,rega
+	
+	add rega,coffset_sniff_anchor,contr
+	ifetcht 4,contr
+	fetch 1,mem_le_new_transmitwindowsize
+	add rega,coffset_le_window_size,contw
+	istore 1,contw
+	ifetch 2,contr
+	lshift2 pdata,pdata
+	iadd temp,timeup    //window offset
+	increase 1,timeup
+	add rega,coffset_sniff_anchor,contw  
+	deposit timeup
+	istore 4,contw
+	ifetch 2,contr
+	lshift2 pdata,pdata
+	add rega,coffset_tsniff,contw
+	istore 2,contw
+	ifetch 4,contr
+	add rega,coffset_le_slave_latency,contw
+	istore 4,contw
+	rtn	
+	
+p_le_slave_unsync:
+//	call le_savelist
+	call le_lpm_set_mult
+	call le_update_channel_map
+	call p_le_update_param
+	branch calc_clke_offset
+
+
+
+
+
+//rega:len regb:ll opcode
+//le_fifo_malloc_tx_ll:
+//	arg LLID_LE_LL,type
+//	call le_fifo_malloc_tx
+//	copy regb,pdata
+//	istore 1,contw
+//	rtn
+
+
+
+
+
+
+
+
+p_le_receive_slave:
+	enable swfine
+	fetch 2,mem_le_receive_window
+	fetcht 4,mem_le_transmit_window
+	iadd temp,timeup
+p_le_receive_packet_slave:
+	call lerx_setfreq
+p_le_receive_rxon_slave:
+	call le_prep
+	disable match
+	disable user2 // for discard work
+	enable decode_fec0
+	enable is_rx
+	disable is_tx
+	copy timeup,stop_watch
+	correlate null,timeout
+	branch p_le_receive_on_attempt_slave,attempt
+	copy clke,temp
+	storet 6,mem_sync_clke
+p_le_receive_on_attempt_slave:
+	nbranch end_of_packet,sync
+	branch p_le_receive_skip_slave,attempt
+	arg param_clke_cal_le,clke_rt
+	copy bt_clk,clke_bt
+	fetch 1,mem_le_state
+	bbit0 lestate_got_first_packet,p_le_receive_skip_slave
+	call lpm_adjust_clk,wake
+p_le_receive_skip_slave:
+	call save_rssi
+	enable enable_white
+	enable enable_crc
+	parse demod,bucket,8
+	rshift3 pwindow,pdata
+	store 1,mem_le_rxbuf
+	// check retransmit
+	fetcht 1,mem_le_arq
+	//fetch 1,mem_le_rxbuf
+	rshift pdata,pdata
+	ixor temp,pdata
+	isolate1 nesn,pdata
+	setflag true,mark_old_packet,mark	/* retransmit */
+
+	// parse length	
+	parse demod,bucket,8
+	rshift3 pwindow,pdata
+	store 1,mem_le_rxbuf+1
+
+process_le_data_common:
+	//and pdata,0xff,pdata
+	copy pdata,loopcnt
+	store 1,mem_le_packet_size
+	branch p_lerx_nopayload_slave,blank							//empty rtn
+
+	fetch 1,mem_le_rxbuf
+	and pdata,0x03,pdata
+	beq LLID_LE_LL,process_le_LL
+
+	bmark1 mark_old_packet,p_lerx_discard_loop
+process_le_packet_common:
+	// reserve one big buffer for host
+	arg mem_alloc_big_block,rega
+	call p_queue_get_len
+	beq 1,p_lerx_discard_loop
+
+
+	call malloc_rcv_buffer_is_enough
+	branch p_lerx_discard_loop,blank
+	
+	call p_get_ble_rcv_ptr
+	copy contr,contw
+	fetch 2,mem_le_rxbuf
+	istore 2,contw
+	branch p_lerx_slave_loop
+
+process_le_LL:
+	arg mem_le_rxbuf+2,contw
+	branch p_lerx_slave_loop
+
+
+p_lerx_discard_loop:
+	// TODO: Think do more here
+	//branch end_of_packet
+
+	parse demod,bucket,8
+	rshift3 pwindow,pdata
+	//istore 1,temp
+	loop p_lerx_discard_loop
+
+	// use mark discard packet
+	enable user2
+
+	branch p_lerx_nopayload_slave
+
+p_lerx_slave_loop:
+	parse demod,bucket,8
+	rshift3 pwindow,pdata
+	istore 1,contw
+	loop p_lerx_slave_loop
+p_lerx_nopayload_slave:
+	parse demod,bucket,24	
+	enable swfine
+	arg param_sifs,stop_watch		// start SIFS timer after last bit of crc
+	branch p_lerx_nopayload_slave_end,user2
+	rshift32 pdata,pdata
+	rshift16 pdata,pdata
+	istore 3,contw // need save crc or not?
+p_lerx_nopayload_slave_end:
+ifdef RF_DEBUG
+	call rf_debug_active_crc_error_line,crc_failed
+endif	
+	branch end_of_packet,crc_failed
+	enable match
+	fetch 1,mem_sfreq_enable
+	nbranch p_lerx_nopayload_skip_write_freq,blank
+	fetch 1,mem_last_freq
+	add pdata,0,rega
+	call rf_write_freq				/* set frequency to tx mode freq */
+p_lerx_nopayload_skip_write_freq:
+	disable decode_fec0
+	branch set_sync_on
+
+p_le_parse_rcv_header:
+	ifetch 1,contr
+	and pdata,0x3,pdata
+	store 1,mem_le_packet_llid
+
+	ifetch 1,contr	//l2cap len
+	store 1,mem_le_packet_size
+	rtn blank
+
+	storer contr,2,mem_le_payload_ptr
+	rtn
+
+p_le_parse:
+	rtnmark1 mark_old_packet
+	rtnmark0 mark_le_mic_ok
+	rtn user2
+
+	// check length
+	fetch 1,mem_le_rxbuf+1
+	rtn blank
+	fetch 1,mem_le_rxbuf
+	and pdata,0x03,pdata
+	beq LLID_LE_LL,le_parse_ll
+
+	call p_get_ble_rcv_ptr
+	call p_le_parse_rcv_header
+	
+	fetch 1,mem_le_packet_size
+	rtn blank
+
+	fetch 1,mem_le_packet_llid
+	beq LLID_LE_LL,le_parse_ll
+p_le_parse_l2cap:
+	branch p_hci_send_acl_encode_le
+
+
+p_le_slave_more_data:
+	enable attempt
+	call p_le_transmit_receive_sifs_notx_slave
+	branch le_slave_match,match
+	branch le_slave_cont
+
+p_le_transmit_receive_sifs_notx_slave:
+	fetcht 1,mem_last_freq
+	call set_freq_rx
+	call rf_rx_enable
+	enable swfine
+	arg 5000,timeup	// about 417us
+	branch p_le_receive_rxon_slave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//input1:rega --- mem block
+//output:regb --- block ptr
+p_queue_delete:
+	add rega,BLOCK_CUR_LEN_OFFSET,temp
+	ifetch 1,temp
+	branch assert,blank
+
+	add rega,BLOCK_RPTR_OFFSET,pdata
+	ifetcht 2,pdata
+	ifetchr regb,3,temp
+	setarg 0
+	istore 3,temp
+	add temp,3,regc
+	call queue_unit_increase
+	add rega,BLOCK_RPTR_OFFSET,pdata
+	istorer regc,2,pdata
+
+	add rega,BLOCK_CUR_LEN_OFFSET,temp
+	ifetch 1,temp
+	increase -1,pdata
+	istore 1,temp
+	rtn
+	
+//input --- rega
+p_queue_get_len:
+	add rega,BLOCK_CUR_LEN_OFFSET,temp
+	ifetch 1,temp
+	rtn
+	
+p_l2cap_load_channel_param:
+	arg 680,rege
+	fetch 1,mem_l2cap_temp_ch_psm
+	rtneq PSM_RFCOMM
+	branch l2cap_load_channel_param+2
+
+//input: regd -> len
+//rtn: regb,contr->ptr
+malloc_br_snd_buffer:
+	call malloc_buffer
+	arg mem_snd_br_block,rega
+	branch queue_insert
+
+free_br_snd_buffer:
+	arg mem_snd_br_block,rega
+	call queue_delete
+	branch free_buffer
+
+
+//input: regd -> len
+//rtn: regb,contr->ptr
+malloc_hci_snd_buffer:
+	call malloc_buffer
+	arg mem_snd_hci_block,rega
+	branch queue_insert
+
+//free_hci_snd_buffer:
+//	arg mem_snd_hci_block,rega
+//	call queue_delete
+//	branch free_buffer
+
+p_queue_insert:
+	add rega,BLOCK_WPTR_OFFSET,pdata
+	ifetcht 2,pdata
+	istorer regb,3,temp//store rxbuffer addr to wptr(start)
+	add temp,3,regc
+	call queue_unit_increase
+	add rega,BLOCK_WPTR_OFFSET,pdata
+	istorer regc,2,pdata
+	
+	add rega,BLOCK_CUR_LEN_OFFSET,regc
+	ifetcht 1,regc
+	increase 1,temp
+	istoret 1,regc
+	
+	// check buffer
+	add rega,BLOCK_TOTAL_SIZE_OFFSET,regc
+	ifetch 1,regc
+	isub temp,null
+	nbranch assert,positive
+	
+	copy regb,contr
+	copy regb,pdata
+	rtn
+
+
+/*********************************************************/
+//char* malloc(short len)
+//input: regd -> len
+//rtn: regb->ptr
+/*********************************************************/
+malloc_buffer:
+	call malloc_buffer_is_enough
+	branch assert,blank
+
+	fetch 2,mem_param_alloc_normal_buffer_max_length
+	increase -10,pdata // protect.
+	fetcht 2,mem_alloc_buffer_len
+	isub temp,null
+	branch malloc_buffer_normal,positive
+malloc_buffer_big:
+ifdef malloc_buffer_cnt_debug
+	fetch 2,mem_temp_alloc_big_malloc_cnt
+	increase 1,pdata
+	store 2,mem_temp_alloc_big_malloc_cnt
+endif
+	arg mem_alloc_big_block,rega
+	branch queue_delete
+malloc_buffer_normal:
+	arg mem_alloc_normal_block,rega
+	call p_queue_get_len
+	branch malloc_buffer_big,blank
+	
+ifdef malloc_buffer_cnt_debug
+	fetch 2,mem_temp_alloc_normal_malloc_cnt
+	increase 1,pdata
+	store 2,mem_temp_alloc_normal_malloc_cnt
+endif
+	arg mem_alloc_normal_block,rega
+	branch queue_delete
+
+/*********************************************************/
+//char* malloc(short len)
+//input: regb -> ptr
+//rtn: regb->ptr
+/*********************************************************/
+free_buffer:
+	call malloc_check_in_big_queue
+	arg mem_alloc_normal_block,rega
+	branch free_buffer_normal,blank
+free_buffer_big:
+ifdef malloc_buffer_cnt_debug
+	fetch 2,mem_temp_alloc_big_free_cnt
+	increase 1,pdata
+	store 2,mem_temp_alloc_big_free_cnt
+endif
+	arg mem_alloc_big_block,rega
+	branch queue_insert
+free_buffer_normal:
+	call malloc_check_in_normal_queue
+	branch assert,blank
+ifdef malloc_buffer_cnt_debug
+	fetch 2,mem_temp_alloc_normal_free_cnt
+	increase 1,pdata
+	store 2,mem_temp_alloc_normal_free_cnt
+endif
+	arg mem_alloc_normal_block,rega
+	branch queue_insert
+
+
+//input: regb -> buffer ptr
+malloc_check_in_normal_queue:
+	// store the big block ptr to list
+	fetchr loopcnt,1,mem_alloc_normal_total_size
+	arg mem_normal_block_ptr_list,contr
+	branch malloc_check_in_queue_loop
+
+
+//input: regd -> len
+//blank == 1, not in big queue
+malloc_check_in_big_queue:
+	// store the big block ptr to list
+	fetchr loopcnt,1,mem_alloc_big_total_size
+	arg mem_big_block_ptr_list,contr
+malloc_check_in_queue_loop:
+	ifetch 3,contr
+	isub regb,null
+	branch malloc_check_in_queue_end,zero
+	loop malloc_check_in_queue_loop
+malloc_check_in_queue_end:
+	copy loopcnt,pdata
+	rtn
+
+//input: regd -> len
+//rtn: blank == 0: enough
+malloc_buffer_is_enough:
+	fetch 2,mem_param_alloc_normal_buffer_max_length
+	increase -10,pdata // protect.
+	fetcht 2,mem_alloc_buffer_len
+	isub temp,null
+	//isub regd,null
+	branch malloc_buffer_is_enough_normal,positive
+malloc_buffer_is_enough_big:
+	arg mem_alloc_big_block,rega
+	branch p_queue_get_len
+malloc_buffer_is_enough_normal:
+	arg mem_alloc_normal_block,rega
+	call p_queue_get_len
+	nrtn blank	// if normal buffer is not enough, use big buffer.
+	branch malloc_buffer_is_enough_big
+
+//input: regd -> len
+//rtn: blank == 1: full
+
+malloc_buffer_is_full_big:
+	fetch 2,mem_param_alloc_big_buffer_max_length
+	branch malloc_buffer_is_full_raw
+malloc_buffer_is_full:
+	setarg 0x10
+malloc_buffer_is_full_raw:
+	store 2,mem_alloc_buffer_len
+	//arg 0x10,regd
+	
+	storer rega,4,mem_rega
+	call malloc_buffer_is_enough
+	fetchr rega,4,mem_rega
+	rtn
+
+// becouse we don't know the buffer length remote send.
+// or we can think do more in future, list read l2cap first two byte first?.
+malloc_rcv_buffer:
+
+ifdef malloc_buffer_cnt_debug
+	fetch 2,mem_temp_alloc_big_malloc_cnt
+	increase 1,pdata
+	store 2,mem_temp_alloc_big_malloc_cnt
+endif
+
+	arg mem_alloc_big_block,rega
+	branch queue_delete
+
+
+malloc_rcv_buffer_is_enough:
+	// avoid receive use all buffer
+	//arg mem_alloc_big_block,rega
+	//call p_queue_get_len
+	//copy pdata,temp
+	//arg mem_alloc_big_block,rega
+	//call p_queue_get_len
+	//iadd temp,pdata
+	//rtn blank
+	fetch 2,mem_rcv_br_queue_ptr
+	nrtn blank
+	
+	arg mem_alloc_big_block,rega
+	branch p_queue_get_len
+
+
+p_get_br_rcv_ptr:
+	fetch 3,mem_rcv_br_queue_ptr
+	nbranch get_pdata_contr,blank
+	call malloc_rcv_buffer
+	copy regb,pdata
+	store 3,mem_rcv_br_queue_ptr
+	branch get_pdata_contr
+
+
+
+p_get_ble_rcv_ptr:
+	fetch 3,mem_rcv_ble_queue_ptr
+	nbranch get_pdata_contr,blank
+	call malloc_rcv_buffer
+	copy regb,pdata
+	store 3,mem_rcv_ble_queue_ptr
+	branch get_pdata_contr
+
+p_app_process_bb_event:
+	//return if c51 need to process bb event
+	arg mem_ipc_fifo_bt2c51,rega
+	call fifo_out
+	rtn blank
+	//reaching here mains c51 cannot get bb event.
+	copy pdata,regc
+//	call app_event_normal_process
+	branch app_process_bb_event_priority
+
+p_app_event_normal_process:
+	copy regc,pdata
+	//beq BT_EVT_LE_CONNECTED,app_le_event_bb_connected
+	beq BT_EVT_LE_DISCONNECTED,p_app_le_event_bb_disconn
+	branch app_event_normal_process + 1
+
+
+p_app_le_event_bb_disconn:
+	jam 0,mem_mesh_recevie_acl_packet_number
+	jam 0,mem_mesh_le_version_exchange_times
+	call z_l2cap_ble_queue_init
+	call p_hci_send_event_le_disconnection_complete
+	branch app_le_event_bb_disconn
+
+p_le_check_wak:
+	fetcht 1,mem_le_arq
+	isolate0 wak,temp
+	rtn true
+	fetch 1,mem_le_rxbuf
+	lshift pdata,pdata
+	ixor temp,pdata
+	rtnbit0 sn			/* received NESN is same as SN, NAK */
+	set0 wak,temp
+	setflip sn,temp
+	storet 1,mem_le_arq
+	compare 3,temp,3
+	nrtn true
+	
+	fetch 1,mem_le_enc_state
+	beq FLAG_LE_ENC_PAUSE,le_clear_enc
+p_le_check_wak_end_ll:
+	fetch 1,mem_le_txpayload_temp
+	beq LL_TERMINATE_IND,p_le_master_disconn
+	beq LL_START_ENC_REQ,le_set_enc
+	rtn
+
+
+p_le_acknowledge:
+	call le_supervision_flush
+	call p_le_check_wak
+	fetch 1,mem_le_rxbuf
+	isolate1 md,pdata
+	setflag true,mark_ble_rx_md,mark
+	rshift pdata,pdata
+	ixor temp,pdata
+	isolate1 nesn,pdata
+	setflag true,mark_old_packet,mark	/* retransmit */
+	fetch 1,mem_le_rxbuf+1			
+	branch p_le_ack_unenc,blank		/* empty packet, no decryption */
+	fetch 1,mem_le_state
+	bbit0 lestate_encryption,p_le_ack_unenc
+	rtnmark1 mark_old_packet
+	call load_sk
+	call le_decrypt
+	setflag blank,mark_le_mic_ok,mark
+	nrtn blank
+p_le_ack_unenc:
+	rtn user2
+	rtnmark1 mark_old_packet
+	set1 mark_le_mic_ok,mark
+	fetcht 1,mem_le_arq
+	setflip nesn,temp
+	storet 1,mem_le_arq
+	rtn	
+
+p_le_adv:
+	fetch 1,mem_le_adv_enable
+	rtn blank
+	arg le_adv_interval_timer,queue
+	call timer_check
+	nrtn blank
+	branch z_le_adv
+
+
+
+
+p_le_fifo_release_first_node:
+	call free_ble_snd_buffer
+	deposit type
+	rtneq LLID_LE_LL
+	branch p_hci_send_event_number_of_completed_packet_le
+
+
+
+p_le_fifo_malloc_tx:
+	storer rega,2,mem_alloc_buffer_len
+	call malloc_ble_snd_buffer
+	copy regb,contw
+	fetch 2,mem_alloc_buffer_len
+	istore 1,contw
+	setarg 0
+	istore 1,contw
+	istorer type,1,contw
+	rtn
+
+malloc_ble_snd_buffer:
+	call malloc_buffer
+	arg mem_snd_ble_block,rega
+	branch queue_insert
+
+free_ble_snd_buffer:
+	arg mem_snd_ble_block,rega
+	call queue_delete
+	branch free_buffer	
+
+
+p_master_simple_paring_sequence:
+p_simple_pairing_sequence:
+	fetch 1,mem_sp_flag
+	nbranch z_simple_pairing_process,blank
+	fetch 1,mem_master_sp_flag
+	nbranch z_simple_pairing_process,blank
+	rtn
+
+
+p_parse_lmp_in_rand:
+	fetch 1,mem_op
+	set1 op_inrand_req,pdata
+	store 1,mem_op
+	call lmp_copy_rand
+	jam pincode_state_wait_pincode,mem_pincode_state
+	call p_hci_send_pincode_req_event
+//	branch parse_lmp_in_rand_hci
+	call tid_check
+	nbranch lmp_accept_inrand,true
+	nbranch parse_lmp_inrand_res,master // ignore this because of not ssp temporary
+	rtn
+	
+	
+p_sp_check_ssp_available:
+	//disable true
+	fetch 1,mem_simple_pairing_mode
+	rtn blank
+	//fetch 2,mem_lmpext_ssp_enable
+	//fetcht 1,mem_remote_sppcap
+	//iand temp,pdata
+	//rtn blank
+	fetch 1,mem_sp_state
+	nrtn blank			// avoid re-entry
+	call p_hci_send_io_cap_req_event
+	jam 0x01,mem_io_cap_flag //io cap req
+	rtn
+
+	
+//p_hci_send_user_confirmation_req_event:
+//	//call p_cmd_user_confirm_reply
+//	jam 10,mem_mesh_event_para_total_length
+//	jam HCI_EVENT_USER_CONFIRMATION_REQUEST,mem_mesh_event_head_event_code
+//	call p_hci_prepare_send_event
+//	fetch 6,mem_plap
+//	istore 6,contw
+	
+//	branch ipc_hci_tx_start
+
+p_hci_send_io_cap_req_event:
+	// BD_ADDR
+	jam 6,mem_mesh_event_para_total_length
+	jam HCI_EVENT_IO_CAP_REQ,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 6,mem_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+//p_hci_send_user_confirm_req_event:
+//	//BD_ADDR-6,Numeric_Value-4
+//	jam 10,mem_mesh_event_para_total_length
+//	jam HCI_EVENT_USER_CONFIRMATION_REQUEST,mem_mesh_event_head_event_code
+//	call p_hci_prepare_send_event
+//	fetch 6,mem_plap
+//	istore 6,contw
+//	fetch 4,mem_gkey	//mem_sp_gkey
+//	istore 4,contw
+//	branch ipc_hci_tx_start
+
+//hci_send_sp_complete_event:
+//	//Status-1,BD_ADDR-6
+//	jam 7,mem_mesh_event_para_total_length
+//	jam HCI_EVENT_SIMPLE_PAIRING_COMPLETE,mem_mesh_event_head_event_code
+//	call p_hci_prepare_send_event
+//	force 0,pdata
+//	istore 1,contw
+//	fetch 6,mem_plap
+//	istore 6,contw
+//	branch ipc_hci_tx_start
+
+
+
+
+	//jam LMP_IO_CAP_RES,mem_lmo_opcode2
+	//rtn
+
+
+
+
+
+
+
+
+process_dmh_common_zero_len:
+	fetch 1,mem_lch_code
+	and_into 0x03,pdata
+	bne LLID_L2CAP_CONT,process_dmh_data_end
+	// If we have no buffer to receive packet, then stop receive new packet
+	arg mem_alloc_big_block,rega
+	call queue_get_len
+	branch end_of_packet,blank
+	branch process_dmh_data_end
+
+
+
+
+p_process_dmh_common:
+	//storer loopcnt,2,mem_len
+	deposit loopcnt
+	store 2,mem_len
+	branch process_dmh_common_zero_len,blank
+	isub mask3ff,null
+	branch error_payload,positive	/* packet too large, discard */
+	and mark,0x01,pdata
+//	set0 mark_fhs_eir,mark
+	nbranch p_process_dmh_common_packet1,blank
+p_process_dmh_common_packet:	
+	// reserve one big buffer for host
+//	arg mem_alloc_big_block,rega
+//	call p_queue_get_len
+//	beq 1,end_of_packet
+	
+	fetch 1,mem_lch_code
+	and_into 0x03,pdata
+	beq LLID_LMP,process_lmp
+
+	// l2cap
+	bmark1 mark_old_packet,ack_payload
+p_process_dmh_common_packet1:
+	fetcht 2,mem_l2cap_rx_max_lenth
+	increase -3,temp
+	fetch 2,mem_len	
+	isub temp,null
+	branch error_payload,positive
+	
+	// reserve one big buffer for host
+	arg mem_alloc_big_block,rega
+	call p_queue_get_len
+	beq 1,end_of_packet
+
+	call malloc_rcv_buffer_is_enough
+	branch end_of_packet,blank
+
+p_process_dmh_data_into_buff_normal:
+	call p_get_br_rcv_ptr
+	copy contr,contw
+
+	fetch 1,mem_lch_code
+	istore 1,contw
+	fetch 2,mem_len
+	istore 2,contw
+	branch process_dmh_data
+
+
+
+p_process_dmh_data_end:
+	parse demod,bucket,16  /* cycle through the crc */
+
+	call rf_debug_active_crc_error_line,crc_failed
+
+//	fetch 1,mem_tws_state
+//	beq TWS_STATE_SLAVE_CONNECTED,process_dmh_data_end_tws
+//	beq TWS_STATE_MASTER_LISTEN,process_dmh_data_end_tws
+//	beq TWS_STATE_MASTER_CONNECTED,process_dmh_data_end_tws
+	
+	branch error_payload_crc,crc_failed
+	bmark0 mark_fhs_eir,process_dmh_packet
+	set0 mark_fhs_eir,mark
+	rtn
+
+
+
+p_process_dmh_l2cap_packet:
+	// Just send buffer 
+	call p_hci_send_acl_encode_classic
+
+	branch process_dmh_cont
+
+
+
+
+
+
+// Classic Snd Manager
+/*********************************************************/
+//char* malloc(short len)
+//input: rega -> len
+//rtn: regb -> pbuff;return from pdata
+//val: queue -> i
+//val: timeup -> buff_cnt
+/*********************************************************/
+p_l2cap_malloc:
+	storer rega,2,mem_alloc_buffer_len
+
+	call malloc_br_snd_buffer
+	fetchr rega,2,mem_alloc_buffer_len
+	rtn
+
+/*********************************************************/
+//void* l2cap_malloc_fifo_out(void)
+//output:len -> temp
+//output:ptr ->pdata
+//only get ptr,not free
+/*********************************************************/
+p_l2cap_malloc_fifo_out:
+	arg mem_snd_br_block,rega
+	branch queue_get_read_ptr
+
+/*********************************************************/
+//void free_first_buff_in_fifo(void)
+//only free the first one
+/*********************************************************/
+p_l2cap_malloc_free:
+	call free_br_snd_buffer
+	branch p_hci_send_event_number_of_completed_packet_classic
+/*********************************************************/
+//void l2cap_malloc_discard(void)
+//discard the latest malloc
+/*********************************************************/
+p_l2cap_malloc_discard:
+	branch free_br_snd_buffer
+/*********************************************************/
+//bool fifo_is_full(void)
+//blank == 1: not full
+//blank == 0: full
+/*********************************************************/
+p_l2cap_malloc_is_fifo_full:
+	call malloc_buffer_is_full_big
+	branch setarg1,blank
+	branch setarg0
+
+/*********************************************************/
+//bool fifo_nearly_full(void)
+//blank == 1: nearly full
+//blank == 0: not nearly full
+/*********************************************************/
+
+//p_l2cap_malloc_is_fifo_nearly_full:
+//	arg mem_alloc_big_block,rega
+//	call queue_get_len
+//	copy pdata,regb
+
+//	arg mem_alloc_normal_block,rega
+//	call queue_get_len
+//	iadd regb,pdata
+
+//	// reserve 2 buffer, sometimes need send two packet.
+//	sub pdata,2,null
+
+//	branch setarg1,positive
+//	branch setarg0
+
+
+/*********************************************************/
+//bool fifo_is_empty(void)
+//blank == 1: empty
+//blank == 0: not empty
+/*********************************************************/
+p_l2cap_malloc_is_fifo_empty:
+	arg mem_snd_br_block,rega
+	branch p_queue_get_len
+
+/*********************************************************/
+//char* l2cap_malloc_fifo_get_first_ptr(void)
+//output:contr  -->ptr
+/*********************************************************/	
+p_l2cap_malloc_fifo_get_first_ptr:
+	branch assert
+
+
+
+
+
+p_scheduler_tx_l2cap_pkt:
+	call p_l2cap_malloc_is_fifo_empty
+	rtn blank //empty
+	
+	fetch 1,mem_op
+	rtnbit1 op_txl2cap
+	call l2cap_malloc_fifo_out
+	//store 2,mem_txptr
+	//copy pdata,contr
+	ifetch 2,contr
+	store 2,mem_tx_len
+
+	ifetch 1,contr
+	set1 2,pdata //set go bit
+	store 1,mem_tx_lch//start pkt
+	
+	copy contr,pdata
+	store 2,mem_txptr
+
+	fetch 2,mem_l2cap_tx_multi_offset
+	branch p_scheduler_tx_l2cap_start_pkt,blank
+	// not think continue will send 2dh5, reduce code size
+	branch scheduler_tx_l2cap_cont_pkt
+p_scheduler_tx_l2cap_start_pkt:
+	fetch 2,mem_tx_len
+	branch assert,blank
+	arg l2cap_max_pkt_len_new,temp //max len of 2dh5 pkt
+	isub temp,pdata
+	branch scheduler_Tx_l2cap_last_pkt,zero
+	branch scheduler_tx_l2cap_start_pkt+4
+
+
+
+
+
+
+p_init_lmp_work:
+	jam 0,mem_link_key_exists
+	branch  init_lmp_work+1
+
+
+
+
+
+
+
+
+
+
+/*
+	Dynamic load, use for "mergepatch.pl"
+*/
+p_zcode_entrance_2Bytes_common:
+	store 2, mem_zcode_temp_param0
+	branch p_zcode_entrance
+
+p_zcode_entrance:
+	fetcht 2,mem_zcode_temp_param0 // zcode number @ high 4bit
+	rshift4 temp,temp
+	fetch 2,mem_zcode_current_number
+	isub temp,null
+	branch zcode_run,zero // if this zcode is already loaded, do not load again
+	storet 2,mem_zcode_current_number
+p_load_zcode:
+	//increase 1,temp
+	setarg ZCODE_BUFF_SIZE
+	imul32 temp,temp
+	fetch 3,mem_xip_flash_offset
+	isub temp,pdata
+	fetcht 3,mem_storage_start_addr
+	iadd temp,pdata
+	increase -4,pdata
+	store 3,mem_flash_address
+	setarg ZCODE_BUFF_SIZE
+	store 2,mem_flash_trans_length
+	setarg mem_zcode_buff_user
+	store 2,mem_flash_data_address
+	call qspi_get_lock
+	call check_m0_qspi_lock_and_pause
+	fetch 1,core_qspi_ctrl
+	store 1,mem_pdatatemp
+	call qspi_read
+	fetch 1,mem_pdatatemp
+	store 1,core_qspi_ctrl
+
+	jam 0,mem_qspi_lock_flag_respin
+	//call qspi_free_lock
+
+	setarg mem_zcode_buff_user
+	branch zcode_entrance0
+
+
+ifdef TEST_QUEUE_DEBUG
+//input: pdata
+test_buffer_check:
+	// start ptr
+	arg mem_alloc_big_block_start,rega
+	arg 10,loopcnt
+test_buffer_check_loop:
+	ifetcht 3,rega
+	isub temp,null
+	call ice_break,zero
+	// regb store the target ptr
+	add rega,3,rega
+	loop test_buffer_check_loop
+	rtn
+endif	
+
+p_le_slave_disconn:
+	call le_att_destroy_notify_pool
+	//fall through
+p_le_disconnect:
+	call le_clear_connection_info+1
+	call app_disconn_reason_collect_ble
+ifdef SECURE_CONNECTION
+	call sp_initialize_256
+endif
+	jam BT_EVT_LE_DISCONNECTED,mem_fifo_temp
+	branch ui_ipc_send_event	
+
+p_le_master_disconn:
+	call p_le_disconnect
+	disable master
+	rtn	
+
+p_lpm_dispatch_unconn:
+	fetch 1,mem_context
+	rtnbit1 state_inconn					// wont sleep in connection
+	rtnbit1 state_inpage					// wont sleep when paging
+	fetch 1,mem_ssp_enable
+	branch p_lpm_unconn_nossp,blank
+	fetch 1,mem_sp_local_key_invalid	// simple pairing is not ready
+	rtn blank
+p_lpm_unconn_nossp:
+//	fetch 1,mem_le_adv_enable
+//	nbranch lpm_unconn_cont,blank
+	branch lpm_unconn_cont
+
+cb_enter_lpm:
+	fetch 1,mem_lmp_conn_state
+	store 1,mem_xlmp_conn_state
+	branch z_enter_hibernate_prepare_work
+	
+
+cb_enter_hibernate:
+//	call ice_break
+	jam MCU_STATE_HIBERNATE,mem_ipc_mcu_state
+	call ipc_check_ack
+	branch z_enter_hibernate_prepare_work
+
+p_lpm_dispatch:
+ifdef MINZHAN_SDK
+	fetch 1,mem_ota_enable_xip_flag
+	beq OTA_NEED_ENABLE_XIP_FLAG,p_loadcode_normal
+endif	
+	fetch 1,mem_lpm_mode
+	rtn blank
+	call p_l2cap_malloc_is_fifo_empty
+	nrtn blank
+	arg mem_snd_ble_block,rega
+	call p_queue_get_len	
+	nrtn blank
+	arg mem_alloc_big_block,rega
+	call p_queue_get_len
+	fetcht 1,mem_alloc_normal_total_size
+	isub temp,null
+	nrtn zero
+	branch lpm_dispatch+12
+
+ifdef MINZHAN_SDK
+p_loadcode_normal:
+	branch soft_reset
+endif
+
+//get qspi lock
+qspi_get_lock:
+	jam 1,mem_qspi_lock_flag_respin // I'm interested
+
+	jam QSPI_LOCK_VICTIM_RESPIN,mem_qspi_lock_victim// you go first
+qspi_get_lock_wait:
+	fetch 1,mem_qspi_lock_flag_cm0
+	rtn blank
+	
+	fetch 1,mem_qspi_lock_victim
+	rtnne DEBUG_LOG_LOCK_VICTIM_RESPIN
+	branch qspi_get_lock_wait
+
+//free qspi lock
+//qspi_free_lock:
+//	jam 0,mem_qspi_lock_flag_respin
+//	rtn
+ifdef FYT_LJ_TEST
+p_feasyblue_test:
+p_feasyblue_assert_patch_counts_protect:
+	arg mem_patch00,contr
+	arg 0x40,loopcnt
+	setarg 0
+p_feasyblue_assert_patch_counts_protect_loop:
+	ifetcht 1,contr
+	iadd temp,pdata
+	loop p_feasyblue_assert_patch_counts_protect_loop
+	arg 0x5b9,temp
+	isub temp,null
+	ncall ice_break,zero
+//	rtn
+p_headset_end_addr_blank_protect:
+	arg mem_headset_end,contr
+	arg 0x10,loopcnt
+	setarg 0
+p_headset_end_addr_blank_protect_loop:
+	ifetcht 1,contr
+	iadd temp,pdata
+	loop p_headset_end_addr_blank_protect_loop
+	ncall ice_break,blank
+	rtn
+endif
+
+/*
+ *in remote test,it may occured that we received a wrong packet header in low probability.
+ *the hv3 and 2ev3 type packet have no protection.
+ * We didn't judge the length of the package,the value of mem_sco_rx_packet_len is zero in default. so command 'loop' may errors.
+*/
+p_rx_type_dispatch:
+	deposit type
+	beq type_hv3, end_of_packet
+	beq type_2ev3,end_of_packet
+	branch rx_type_dispatch+2
+	
Index: ModuleDemo/BLE/BT/patch/patch_sdk.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/patch_sdk.prog	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/patch_sdk.prog	(working copy)
@@ -0,0 +1,5 @@
+define SDKCODE
+ifdef SDKCODE
+INCLUDE "bt_format"
+org 0x0000  // start from patch ram address start
+endif
\ No newline at end of file
Index: ModuleDemo/BLE/BT/patch/z.prog
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/z.prog	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/patch/z.prog	(working copy)
@@ -0,0 +1,2700 @@
+
+
+
+org z
+z_hci_parse_packet_cmd_ogf_link_control:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_INQUIRY,z_hci_parse_packet_cmd_ogf_link_control_inquiry	//1
+	beq HCI_INQUIRY_CANCEL,z_hci_parse_packet_cmd_ogf_link_control_inquiry_cancel	//2
+	beq HCI_CREATE_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_create_connection	//5
+	beq HCI_ACCEPT_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_accept_connection	//9
+
+	branch z_hci_parse_packet_cmd_ogf_link_control1
+	
+
+z_hci_parse_packet_cmd_ogf_link_control_inquiry:	//1
+	set1 mark_inquiry_on,mark
+	call p_ipc_rx_hci_data_thr_byte
+	store 3,mem_glap
+	call p_ipc_rx_hci_data_one_byte
+	arg 2048,temp
+	imul32 temp,pdata
+	arg 0xffff,temp
+	isub temp,null
+	nbranch z_hci_inquiry_nowrap,positive
+	deposit temp
+z_hci_inquiry_nowrap:
+	force inquiry_length_timer,queue
+	call timer_init
+	call p_ipc_rx_hci_data_one_byte //todo
+	store 1,mem_inquiry_num_responses
+	store 1,mem_inquiry_num_check
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_control_inquiry_cancel:	//2
+	jam hci_cmd_inquiry_cancel,mem_hci_cmd
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_link_control_create_connection:		//5
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_packet_type
+	call p_ipc_rx_hci_data_two_byte
+	store 1,mem_page_mode
+	call p_ipc_rx_hci_data_two_byte /*read clock*/
+//	bbit0 15,z_create_connection_unsave_clk_offset
+//	iadd clkn_bt,pdata
+//	and_into 0x1fc,pdata
+//	store 4,mem_page_clk
+//z_create_connection_unsave_clk_offset:
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_allow_switch
+	jam 1,mem_conn_status
+	jam hci_cmd_create_conn,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_control_accept_connection:	//9
+	fetch 1,mem_conn_req_status
+	beq 0,p_hci_send_event_command_status_err_unknown_connection
+	beq 2,p_hci_send_event_command_status_err_command_disallowed
+	fetch 1,mem_conn_status
+	beq 2,p_hci_send_event_command_status_err_command_disallowed
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	jam hci_cmd_accept_conn,mem_hci_cmd
+	call p_ipc_rx_hci_data_one_byte
+	beq 1,p_hci_send_event_command_status	
+	jam hci_cmd_accept_with_switch,mem_hci_cmd
+	call p_hci_send_event_command_status
+	branch accept_lmp_msg
+
+org z
+z_hci_parse_packet_cmd_ogf_controller_and_baseband:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_SET_EVENT_MASK,z_hci_parse_packet_cmd_ogf_controller_and_baseband_set_event_mask	//01
+	beq HCI_WRITE_LOCAL_NAME,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_local_name	//13
+	beq HCI_READ_LOCAL_NAME,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_local_name	//14
+	beq HCI_READ_PAGE_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_timeout	//17
+	beq HCI_WRITE_PAGE_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_timeout	//18
+	beq HCI_READ_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_scan_enable	//19
+	beq HCI_WRITE_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_scan_enable	//1A
+	beq HCI_READ_PAGE_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_activity	//1B
+	
+	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband1
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_set_event_mask:
+	call p_ipc_rx_hci_data_eight_byte
+	store 8,mem_mesh_event_mask
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_local_name:
+	call p_ipc_rx_restore_contr
+	arg mem_local_name,contw
+	arg 66,loopcnt
+	call memcpy
+	arg 66,loopcnt
+	arg mem_local_name,contr
+	arg 0,temp
+	call p_check_tx_length
+	storet 1,mem_local_name_length
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_local_name:
+	arg 249,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	arg mem_local_name,contr
+	arg 64,loopcnt
+	call memcpy_loop
+	arg 23,loopcnt
+	call memset0
+	branch ipc_hci_tx_start
+	
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_timeout:	//17
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 2, mem_page_to
+	istore 2,contw
+	branch ipc_hci_tx_start
+	
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_timeout:	//18
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_page_to
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_scan_enable:	//19
+	arg 2,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_scan_mode
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_scan_enable:	//1A
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_scan_mode
+	branch p_hci_send_event_command_complete_without_payload
+
+
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_activity:	//1B
+	arg 5,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	//setarg 0x0013
+	fetch 2,mem_pscan_interval
+	istore 2,contw
+	//setarg 0x0014
+	fetch 2,mem_pscan_window
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+
+org z
+z_hci_parse_packet_cmd_ogf_infomational_parameters:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_READ_LOCAL_VERSION_INFORMATION,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_version_information
+	beq HCI_READ_LOCAL_SUPPORTED_COMMANDS,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_command
+	beq HCI_READ_LOCAL_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_features
+	beq HCI_READ_LOCAL_EXT_FEATURES,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_local_ext_features
+	beq HCI_READ_BUFFER_SIZE,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_buffer_size
+	beq HCI_READ_BD_ADDR,z_hci_parse_packet_cmd_ogf_infomational_parameters_read_bd_addr
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_version_information:
+	arg 9,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 8,mem_mesh_read_local_version_info
+	istore 8,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_command:
+	arg 65,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	arg mem_mesh_read_local_support_command,contr
+	arg 64,loopcnt
+	call memcpy
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_supported_features:
+	arg 9,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 8,mem_features
+	istore 8,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_bd_addr:
+	arg 7,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 6,mem_lap
+	istore 6,contw
+	branch ipc_hci_tx_start
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_local_ext_features:
+z_hci_parse_packet_cmd_ogf_infomational_parameters_read_buffer_size:
+	arg 8,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	setarg 680
+	istore 2,contw
+	setarg 60
+	istore 1,contw
+	setarg 8
+	istore 2,contw
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+
+org z
+z_hci_parse_packet_cmd_ogf_le_controller:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_LE_SET_EVENT_MASK,z_hci_parse_packet_cmd_ogf_le_controller_set_event_mask	//01
+	beq HCI_LE_READ_BUFFER_SIZE,z_hci_parse_packet_cmd_ogf_le_controller_read_buffer_size		//02
+	beq HCI_LE_READ_LOCAL_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_le_controller_read_supported_features	//03
+	beq HCI_LE_SET_RANDOM_ADDRESS,z_hci_parse_packet_cmd_ogf_le_controller_set_random_address		//05
+	beq HCI_LE_SET_ADVERTISING_PARAMETERS,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_para	//06
+	branch z_hci_parse_packet_cmd_ogf_le_controller1
+	
+z_hci_parse_packet_cmd_ogf_le_controller_set_event_mask:	//01
+	call p_ipc_rx_hci_data_eight_byte
+	store 8,mem_mesh_le_event_mask
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_read_buffer_size:	//02
+	arg 4,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	setarg 0x0400fb
+	istore 3,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_le_controller_read_supported_features:	//03
+	arg 9,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 8,mem_le_features
+	istore 8,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_random_address:		//05
+	fetch 1,mem_le_adv_enable
+	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_mesh_le_random_address
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_adv_para:		//06
+	fetch 1,mem_le_adv_enable
+	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
+	call p_ipc_rx_hci_data_two_byte	//Advertising interval min
+	store 2,mem_le_adv_interval_min
+	call p_ipc_rx_hci_data_two_byte	//Advertising interval max
+	store 2,mem_le_adv_interval_max
+	call p_ipc_rx_hci_data_one_byte	//Advertising type
+	call z_hci_check_advertising_type
+	storet 1,mem_le_adv_type
+	call p_ipc_rx_hci_data_one_byte	//Own address type
+	call z_hci_set_public_addr,blank
+	ncall z_hci_set_random_addr,blank
+	call p_ipc_rx_hci_data_one_byte	//Peer Address type
+	call p_ipc_rx_hci_data_six_byte	//Peer Address
+	call p_ipc_rx_hci_data_one_byte	//Advertising channel map
+	store 1,mem_le_adv_channel_map
+	call p_ipc_rx_hci_data_one_byte //Advertising_Filter_Policy
+	store 1,mem_le_white_list_filter_policy
+	branch p_hci_send_event_command_complete_without_payload	
+
+z_hci_check_advertising_type:
+	arg ADV_IND,temp
+	rtneq 0x00
+	arg ADV_NONCONN_IND,temp
+	rtneq 0x03
+	arg ADV_SCAN_IND,temp
+	rtneq 0x02
+	arg ADV_DIRECT_IND,temp
+	rtn
+
+z_hci_set_public_addr:
+	fetcht 6,mem_device_public_address
+	storet 6,mem_le_lap
+	jam PUBLIC_ADDR,mem_le_adv_own_addr_type
+	rtn
+z_hci_set_random_addr:
+ 	jam RANDOM_ADDR,mem_le_adv_own_addr_type
+	rtn
+
+
+org z
+z_hci_parse_packet_cmd_ogf_link_policy:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_SNIFF_MODE,z_hci_parse_packet_cmd_ogf_link_policy_sniff_mode
+	beq HCI_EXIT_SNIFF_MODE,z_hci_parse_packet_cmd_ogf_link_policy_exit_sniff_mode
+	beq HCI_SWITCH_ROLE,z_hci_parse_packet_cmd_ogf_link_policy_switch_role	//B
+	beq HCI_READ_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_read_link_policy_settings    //C
+	beq HCI_WRITE_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_write_link_policy_settings    //D
+	branch z_hci_parse_packet_cmd_ogf_link_policy_branch1
+
+z_hci_parse_packet_cmd_ogf_link_policy_sniff_mode:
+	fetch 2,mem_link_policy_settings
+	bbit0 Sniff_Mode,p_hci_send_event_command_status_err_command_disallowed
+	fetch 2,mem_default_link_policy_settings
+	bbit0 Sniff_Mode,p_hci_send_event_command_status_err_command_disallowed
+	fetch 1,mem_conn_status
+	bne 2,p_hci_send_event_command_status_err_unknown_connection
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_hci_sniff_conn_handle
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_hci_sniff_max_interval
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_hci_sniff_min_interval
+	setarg 0x40
+	store 2,mem_sniff_param_interval
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_sniff_param_attempt
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_sniff_param_timeout
+	jam hci_cmd_in_sniff,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_policy_exit_sniff_mode:
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_hci_sniff_conn_handle
+	fetch 1,mem_mode
+	bbit0 acl_in_sniff,p_hci_send_event_command_status_err_command_disallowed
+	jam hci_cmd_exit_sniff,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_policy_switch_role:	//B
+	fetch 1,mem_conn_status
+	bne 2,p_hci_send_event_command_status_err_unknown_connection
+	fetch 2,mem_link_policy_settings
+	bbit0 Role_Switch,p_hci_send_event_command_status_err_command_disallowed
+	fetch 2,mem_default_link_policy_settings
+	bbit0 Role_Switch,p_hci_send_event_command_status_err_command_disallowed
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_one_byte //todo deal
+	jam hci_cmd_role_switch,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_policy_read_link_policy_settings:
+	call p_hci_parse_connection_handle_check
+	arg 5,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	fetch 2,mem_link_policy_settings
+	istore 2,contw
+	branch ipc_hci_tx_start
+	
+z_hci_parse_packet_cmd_ogf_link_policy_write_link_policy_settings:
+	call p_hci_parse_connection_handle_check
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_link_policy_settings
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+org z
+z_hci_parse_packet_cmd_ogf_link_policy_branch1:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_READ_DEFAULT_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_read_default_link_policy_settings    //E
+	beq HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS,z_hci_parse_packet_cmd_ogf_link_policy_write_default_link_policy_settings     //F
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+
+z_hci_parse_packet_cmd_ogf_link_policy_read_default_link_policy_settings:
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 2,mem_default_link_policy_settings
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_link_policy_write_default_link_policy_settings:
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_default_link_policy_settings
+	branch p_hci_send_event_command_complete_without_payload
+	
+org z
+z_hci_parse_packet_cmd_ogf_controller_and_baseband1:
+	fetch 1,mem_mesh_hci_opcode_ocf	
+	beq HCI_WRITE_PAGE_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_paga_scan_activity	//1C
+	beq HCI_READ_INQUIRY_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_activity	//1D
+	beq HCI_WRITE_INQUIRY_SCAN_ACTIVITY,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_activity	//1E
+	beq HCI_READ_CLASS_OF_DEVICE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_class_of_device		//23
+	beq HCI_WRITE_CLASS_OF_DEVICE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_class_of_device		//24
+	beq HCI_READ_INQUIRY_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_type	//42
+	beq HCI_WRITE_INQUIRY_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_type	//43
+	beq HCI_READ_INQUIRY_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_mode	//44
+	beq HCI_WRITE_INQUIRY_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_mode	//45
+	beq HCI_READ_PAGE_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_type	//46
+	beq HCI_WRITE_PAGE_SCAN_TYPE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_scan_type	//47
+	beq HCI_READ_EXTENDED_INQUIRY_RESPONSE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_eir //51
+
+	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband2
+	
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_paga_scan_activity:	//1C
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_pscan_interval
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_pscan_window
+	branch p_hci_send_event_command_complete_without_payload
+	
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_activity:	//1D
+	arg 5,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	//setarg 0x0013
+	fetch 2,mem_iscan_interval
+	istore 2,contw
+	//setarg 0x0014
+	fetch 2,mem_iscan_window
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_activity:	//1E
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_iscan_interval
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_iscan_window
+	branch p_hci_send_event_command_complete_without_payload
+
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_class_of_device:
+	arg 4,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 3,mem_class
+	istore 3,contw
+	branch ipc_hci_tx_start
+	
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_class_of_device:
+	call p_ipc_rx_hci_data_thr_byte
+	store 3,mem_class
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_scan_type:	//42
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_scan_type:	//43
+	call p_ipc_rx_hci_data_one_byte
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_inquiry_mode:	//44
+	arg 2,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_inquiry_mode
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_inquiry_mode:	//45
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_inquiry_mode
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_page_scan_type:	//46
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_page_scan_type:	//47
+	//Standard Scan, normal reply
+	call p_ipc_rx_hci_data_one_byte
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_eir:    //51
+	arg 242,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_fec_required
+	istore 1,contw
+	// TODO: here think use match length, like 240
+	arg mem_eir,contr
+	arg 100,loopcnt
+	call memcpy
+	//call memset0
+	branch ipc_hci_tx_start
+
+
+
+org z
+z_hci_parse_packet_cmd_ogf_link_control1:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_DISCONNECT,z_hci_parse_packet_cmd_ogf_link_control_disconnect	//6
+	beq HCI_CREATE_CONNECTION_CANCEL,z_hci_parse_packet_cmd_ogf_link_control_create_connection_cancel	//8
+	beq HCI_REJECT_CONNECTION,z_hci_parse_packet_cmd_ogf_link_control_reject_connection	//A
+
+	branch z_hci_parse_packet_cmd_ogf_link_control2
+	
+	
+z_hci_parse_packet_cmd_ogf_link_control_disconnect:
+	call p_ipc_rx_hci_data_two_byte	/*connect handle*/
+	store 1,mem_hci_conn_handle
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_disconn_reason_send
+	
+	call context_search_conn_handle
+	nbranch p_hci_send_event_command_status_err_unknown_connection,zero
+
+	// check is classic or ble
+	add rega,coffset_mode,contr
+	ifetch 1,contr
+	bbit1 mode_le,z_hci_control_disconnect_le
+
+z_hci_control_disconnect_classic:
+	jam hci_cmd_disconn,mem_hci_cmd
+	//jam 0x16,mem_disconn_reason
+	fetch 1,mem_hci_conn_handle
+	fetcht 1,mem_sco_handle
+	isub temp,null
+	nbranch p_hci_send_event_command_status,zero
+	jam hci_cmd_disconn_sco,mem_hci_cmd
+	fetch 1,mem_sco_asso_handle
+	store 1,mem_hci_conn_handle
+	branch p_hci_send_event_command_status
+
+z_hci_control_disconnect_le:
+	fetch 1,mem_disconn_reason_send
+	store 1,mem_temp
+	call le_send_terminate_ind
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_control_create_connection_cancel:	//8
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	jam hci_cmd_detach,mem_hci_cmd
+	fetch 1,mem_conn_status
+	beq 0x01,z_hci_create_conn_cancel_success
+	beq 0x02,z_hci_connection_already_exists_err
+	branch z_hci_connection_cancel_err_no_connection
+z_hci_connection_already_exists_err:
+	jam HCI_ERROR_MAX_ACL_CONNECTIONS,mem_mesh_command_complete_return_parameter_status
+	branch z_hci_connection_cancel_err
+z_hci_create_conn_cancel_success:
+	jam COMMAND_SUCCEEDED,mem_mesh_command_complete_return_parameter_status
+	call z_hci_connection_cancel_err
+	jam HCI_ERROR_NO_CONNECTION,mem_mesh_event_parameter_status
+	branch p_hci_send_connection_rtn_error
+z_hci_connection_cancel_err_no_connection:
+	jam HCI_ERROR_NO_CONNECTION,mem_mesh_command_complete_return_parameter_status
+z_hci_connection_cancel_err:
+	arg 7,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status
+	fetch 6,mem_hci_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_link_control_reject_connection:	//A
+	fetch 1,mem_conn_req_status
+	beq 0,p_hci_send_event_command_status_err_unknown_connection
+	beq 2,p_hci_send_event_command_status_err_command_disallowed
+	fetch 1,mem_conn_status
+	beq 2,p_hci_send_event_command_status_err_command_disallowed
+	jam 2,mem_conn_req_status
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_one_byte	//todo
+	store 1,mem_mesh_event_parameter_status
+	jam hci_cmd_reject_conn,mem_hci_cmd
+	call p_hci_send_event_command_status
+	branch p_hci_send_connection_rtn_error
+
+
+org z
+z_hci_parse_packet_cmd_ogf_link_control2:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_LINK_KEY_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_link_key_request_reply	//B
+	beq HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY,z_hci_parse_packet_cmd_ogf_link_control_link_key_request_negative_replay	//C
+	beq HCI_PIN_CODE_REQUEST_REPLY,z_hci_pin_code_request_reply
+	beq HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY,z_hci_pin_code_request_negative_reply
+	beq HCI_AUTHENTICATION_REQUESTED,z_hci_parse_packet_cmd_ogf_link_control_authentication_requested	//11
+	beq HCI_SET_CONNECTION_ENCRYPTION,z_hci_parse_packet_cmd_ogf_link_control_set_connection_encryption	//13
+
+	branch z_hci_parse_packet_cmd_ogf_link_control3
+	
+
+z_hci_parse_packet_cmd_ogf_link_control_link_key_request_reply:	//B
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	arg mem_link_key,contw
+	force 16,loopcnt
+	call p_ipc_rx_hci_data_n_byte
+	jam 1,mem_link_key_exists
+	jam hci_cmd_linkkey,mem_hci_cmd
+	branch z_hci_pin_code_reply
+
+z_hci_parse_packet_cmd_ogf_link_control_link_key_request_negative_replay:	//C
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	jam hci_cmd_nokey,mem_hci_cmd
+	call z_hci_pin_code_reply
+	call p_sp_check_ssp_available
+	fetch 1,mem_simple_pairing_mode
+	branch p_hci_send_pincode_req_event,blank
+	//force 0x01,pdata
+	//store 1,mem_io_cap_flag
+	//fetch 1,mem_simple_pairing_mode
+	//beq  1,p_hci_send_io_cap_req_event
+	//branch p_hci_send_pincode_req_event
+	rtn
+
+
+z_hci_pin_code_request_reply:
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_pin_length
+	iforce loopcnt
+	arg mem_pin,contw
+	call p_ipc_rx_hci_data_n_byte
+	jam hci_cmd_pair,mem_hci_cmd
+	branch z_hci_pin_code_reply
+
+z_hci_pin_code_request_negative_reply:
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	jam hci_cmd_nopair,mem_hci_cmd
+z_hci_pin_code_reply:
+	arg 7,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 6,mem_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+
+z_hci_parse_packet_cmd_ogf_link_control_authentication_requested:	//11
+	call p_ipc_rx_hci_data_two_byte
+	store 1,mem_hci_conn_handle
+	jam hci_cmd_auth,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_control_set_connection_encryption:	//13
+	call p_ipc_rx_hci_data_two_byte
+	store 1,mem_hci_conn_handle
+	call p_ipc_rx_hci_data_one_byte
+	increase hci_cmd_stopencrypt,pdata
+	store 1,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+org z
+z_hci_parse_packet_cmd_ogf_link_control3:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_REMOTE_NAME_REQUEST,z_hci_parse_packet_cmd_ogf_link_control_remote_name_request	//19
+	beq HCI_READ_REMOTE_EXT_FEATURES,z_hci_parse_packet_cmd_ogf_link_control_read_remote_ext_features	//1C
+	beq HCI_READ_REMOTE_VERSION_INFORMATION,z_hci_parse_packet_cmd_ogf_link_control_read_remote_version_information	//1D
+	beq HCI_READ_REMOTE_SUPPORTED_FEATURES,z_hci_parse_packet_cmd_ogf_link_control_read_remote_supported_features	//1B
+
+	branch z_hci_parse_packet_cmd_ogf_link_control4
+
+z_hci_parse_packet_cmd_ogf_link_control_remote_name_request:	//19
+	jam 1,mem_hci_remote_name_req_flag
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_two_byte
+	store 1,mem_page_mode
+	call p_ipc_rx_hci_data_two_byte
+	iadd clkn_bt,pdata
+	and_into 0x1fc,pdata
+	store 4,mem_page_clk
+ 	arg 8,loopcnt
+	arg mem_hci_remote_name,contw
+	call memset0
+	call context_search_plap
+	branch z_hci_parse_packet_cmd_ogf_link_control_remote_name_request_conn_exist,zero
+	jam 2,mem_hci_remote_name_req_flag
+z_hci_parse_packet_cmd_ogf_link_control_remote_name_request_conn_exist:
+	jam hci_cmd_remote_name_req,mem_hci_cmd
+	branch p_hci_send_event_command_status
+//	branch p_hci_send_remote_name_request_complete
+
+
+z_hci_parse_packet_cmd_ogf_link_control_read_remote_ext_features:	//1C
+	fetch 1,mem_conn_status
+	bne 2,p_hci_send_event_command_status_err_unknown_connection
+	call p_ipc_rx_hci_data_two_byte
+	branch p_hci_send_event_command_status_err_unknown_connection,blank
+	call p_ipc_rx_hci_data_one_byte
+	store 1, mem_ext_features_page
+	jam hci_cmd_remote_ext_features_req,mem_hci_cmd
+	branch p_hci_send_event_command_status
+
+z_hci_parse_packet_cmd_ogf_link_control_read_remote_version_information:
+	call p_ipc_rx_hci_data_two_byte	//connect handle
+	store 1,mem_hci_conn_handle
+
+	call context_search_conn_handle
+	nbranch p_hci_send_event_command_status_err_unknown_connection,zero
+
+	// check is classic or ble
+	add rega,coffset_mode,contr
+	ifetch 1,contr
+	bbit1 mode_le,z_hci_control_read_remote_version_le
+
+z_hci_control_read_remote_version_classic:
+	call p_hci_send_event_command_status
+	branch cmd_version_req
+
+z_hci_control_read_remote_version_le:
+	call p_hci_send_event_command_status
+	branch le_send_version_ind
+	
+
+z_hci_parse_packet_cmd_ogf_link_control_read_remote_supported_features:	//1B
+	// TODO: Think judge link exist or not.
+	fetch 1,mem_conn_status
+	bne 2,p_hci_send_event_command_status_err_unknown_connection
+	call p_ipc_rx_hci_data_two_byte		//rx parameters first
+	store 1,mem_hci_conn_handle
+	branch p_hci_send_event_command_status_err_unknown_connection,blank
+	call p_hci_send_event_command_status
+	fetch 8,mem_remote_features
+	nbranch z_hci_send_read_remote_supported_features_complete_event,blank
+	jam hci_cmd_remote_feature_req,mem_hci_cmd
+	rtn
+
+
+z_hci_send_read_remote_supported_features_complete_event:
+	//Status(1), Connection_Handle(2), LMP_Features(8)
+	jam 11,mem_mesh_event_para_total_length
+	jam HCI_EVENT_READ_REMOTE_FEATURES_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0
+	istore 1,contw
+	// Connection_Handle
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	// link type, 0:SCO, 1:ACL
+	fetch 8,mem_remote_features
+	istore 8,contw
+	branch ipc_hci_tx_start
+
+
+
+
+org z
+z_hci_parse_packet_cmd_ogf_link_control4:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_IO_CAP_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_io_cap_request_reply	//2B
+	beq HCI_USER_CONFIRMATION_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_link_control_user_confirmation_request_reply	//2C
+
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_link_control_io_cap_request_reply:	//2B
+	//BD_ADDR, IO_Capability, 
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	call p_ipc_rx_hci_data_thr_byte
+	store 3,mem_sp_iocap_local
+	arg 7,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 6,mem_plap
+	istore 6,contw
+	call ipc_hci_tx_start
+	fetch 1,mem_io_cap_flag
+	beq 1,z_io_cap_master_req
+z_io_cap_slave_req:
+	jam hci_cmd_io_cap,mem_hci_cmd
+//	arg 0xc600,rega
+//	arg 0xcc,temp
+//	call debug_log_print
+	rtn
+z_io_cap_master_req:
+	call cmd_ssp
+	jam LOCAL_STATEMACHINE,mem_sp_localsm //init ssp state machine
+//	arg 0xc600,rega
+//	arg 0xdd,temp
+//	call debug_log_print
+	rtn
+
+z_hci_parse_packet_cmd_ogf_link_control_user_confirmation_request_reply:	//2C
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_hci_plap
+	//jam hci_cmd_user_confirm_reply,mem_hci_cmd
+	call z_cmd_user_confirm_reply		//todo
+	arg 7,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 6,mem_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+
+z_cmd_user_confirm_reply:
+	// process dhkey check now
+	//rtn master
+	jam  SP_STAT_CONFIRM_CALC,mem_sp_state
+	jam  SP_FLAG_COMMIT,mem_sp_flag
+	rtn
+
+org z
+z_hci_parse_packet_cmd_ogf_controller_and_baseband2:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_RESET,z_hci_parse_packet_cmd_ogf_controller_and_baseband_reset	//03
+	beq HCI_WRITE_LINK_SUPERVISION_TIMEOUT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_link_supervision_timeout  //37
+	beq HCI_WRITE_EXTENDED_INQUIRY_RESPONSE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_eir  //52
+	beq HCI_READ_SIMPLE_PAIRING_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_simple_pairing_mode //55
+	beq HCI_WRITE_SIMPLE_PAIRING_MODE,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_simple_pairing_mode //56
+	beq HCI_READ_LE_HOST_SUPPORT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_le_host_support	//6C
+	beq HCI_WRITE_LE_HOST_SUPPORT,z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_le_host_support	//6D
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+	
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_reset:
+	call p_hci_send_event_command_complete_without_payload
+	//branch p_hci_init_parameter
+z_hci_init_parameter:
+	setarg DEFAULT_LE_EVENT_MASK
+	store 8,mem_mesh_le_event_mask
+	setarg DEFAULT_EVENT_MASK
+	store 8,mem_mesh_event_mask
+	setarg 0
+	store 6,mem_mesh_le_random_address
+	store 1,mem_le_adv_enable
+	store 1,mem_le_scan_enable
+	store 1,mem_scan_mode
+	branch p_hci_init_bd_address
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_link_supervision_timeout:  //37
+	call p_hci_parse_connection_handle_check
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_supervision_to
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	jam hci_cmd_send_supervision,mem_hci_cmd
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_eir:   //52
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_fec_required
+	arg 100,loopcnt
+	arg mem_eir,contw
+	call p_ipc_rx_hci_data_n_byte
+	branch p_hci_send_event_command_complete_without_payload
+	
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_simple_pairing_mode:  //55
+	arg 2,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_simple_pairing_mode
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_simple_pairing_mode:  //56
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_simple_pairing_mode
+	branch p_hci_send_event_command_complete_error_command_invalid_param,blank
+	branch p_hci_send_event_command_complete_without_payload
+
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_read_le_host_support:  //6C
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 2,mem_le_supported_host
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_write_le_host_support:  //6D
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_le_supported_host
+	branch p_hci_send_event_command_complete_without_payload
+
+	
+org z
+z_hci_parse_packet_cmd_ogf_le_controller1:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_LE_SET_ADVERTISING_DATA,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_data	//08
+	beq HCI_LE_SET_SCAN_RESPONSE_DATA,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_rsp_data	//09
+	beq HCI_LE_SET_SCAN_PARAMETERS,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_para		//0b
+	beq HCI_LE_SET_SCAN_ENABLE,z_hci_parse_packet_cmd_ogf_le_controller_set_scan_enable		//0c
+	beq HCI_LE_CREATE_CONNECTION,z_hci_parse_packet_cmd_ogf_le_controller_create_connection		//0d
+
+	branch z_hci_parse_packet_cmd_ogf_le_controller2
+	
+	
+z_hci_parse_packet_cmd_ogf_le_controller_set_adv_data:	//OCF:0x0008
+	call p_ipc_rx_hci_data_one_byte	//Advertising_Data_length
+	store 1,mem_le_adv_data_len
+	copy pdata,loopcnt
+	call p_ipc_rx_hci_data_n_byte
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_scan_rsp_data:	//OCF:0x0009
+	call p_ipc_rx_hci_data_one_byte	//Advertising_Data_length
+	store 1,mem_le_scan_data_len
+	copy pdata,loopcnt
+	call p_ipc_rx_hci_data_n_byte
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_scan_para:		//OCF:0x000B	
+	fetch 1,mem_le_scan_enable
+	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
+	call p_ipc_rx_hci_data_one_byte		//LE Scan Type
+	store 1,mem_le_scan_type
+	call p_ipc_rx_hci_data_two_byte		//LE Scan Interval
+	store 2,mem_le_scan_interval
+	call p_ipc_rx_hci_data_two_byte		//LE Scan Window
+	store 2,mem_le_scan_window
+	call p_ipc_rx_hci_data_one_byte		//Own Address Type
+	store 1,mem_le_scan_own_addr_type
+	call p_ipc_rx_hci_data_one_byte		//Scanning Filter Policy
+	store 1,mem_le_white_list_filter_policy
+	// avoid param same
+	fetch 2,mem_le_scan_interval
+	fetcht 2,mem_le_scan_window
+	isub temp,null
+	nbranch p_hci_send_event_command_complete_without_payload,zero
+	lshift pdata,pdata
+	store 2,mem_le_scan_interval
+	
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_scan_enable:	//OCF:0x000C
+	call p_ipc_rx_hci_data_one_byte		//LE Scan Enable
+	store 1,mem_le_scan_enable
+	call p_ipc_rx_hci_data_one_byte		//Filter Duplicates
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_create_connection:		//OCF:0x000D
+	call p_ipc_rx_hci_data_two_byte		//LE Scan Interval
+	store 2,mem_le_scan_interval
+	call p_ipc_rx_hci_data_two_byte		//LE Scan Window
+	store 2,mem_le_scan_window
+	call p_ipc_rx_hci_data_one_byte		//initiator filter policy
+	store 1,mem_le_white_list_filter_policy
+	isub 0x01,null
+	call p_white_filter_connect_filter,zero
+	call p_ipc_rx_hci_data_one_byte		//peer address type
+	store 1,mem_le_conn_peer_addr_type
+	call p_ipc_rx_hci_data_six_byte		//peer address
+	store 6,mem_le_conn_peer_addr
+	call p_ipc_rx_hci_data_one_byte		//own address type
+	store 1,mem_le_conn_own_addr_type
+	call p_ipc_rx_hci_data_two_byte		//connect interval min
+	lshift2 pdata,pdata
+	store 2,mem_le_conn_interval
+	call p_ipc_rx_hci_data_two_byte		//connect interval max
+	call p_ipc_rx_hci_data_two_byte		//connect latency
+	store 2,mem_le_conn_latency	
+	call p_ipc_rx_hci_data_two_byte		//supervision timeout
+	store 2,mem_le_conn_superto
+	branch p_parse_le_controller_create_connection
+	
+
+org z
+z_hci_parse_packet_cmd_ogf_le_controller2:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_LE_SET_ADVERTISE_ENABLE,z_hci_parse_packet_cmd_ogf_le_controller_set_adv_enable		//0a
+	beq HCI_LE_CREATE_CONNECTION_CANCEL,z_hci_parse_packet_cmd_ogf_le_controller_create_connection_cancel
+	beq HCI_LE_CONNECTION_UPDATE,p_hci_parse_packet_cmd_ogf_le_controller_connection_update
+	beq HCI_LE_READ_REMOTE_FEATURES,z_hci_parse_packet_cmd_ogf_le_controller_read_remote_features
+	beq HCI_LE_ENCRYPT,z_hci_parse_packet_cmd_ogf_le_controller_encrypt
+	beq HCI_LE_RAND,z_hci_parse_packet_cmd_ogf_le_controller_rand
+	beq HCI_LE_START_ENCRYPTION,z_hci_parse_packet_cmd_ogf_le_controller_start_encryption
+	beq HCI_LE_LONG_TERM_KEY_REQUEST_REPLY,z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_reply
+	beq HCI_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY,z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_negative_reply
+
+	beq HCI_LE_READ_WHITE_LIST_SIZE,z_hci_parse_packet_cmd_ogf_le_controller_read_white_list_size
+	beq HCI_LE_CLEAR_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_clear_white_list
+	beq HCI_LE_ADD_DEVICE_TO_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_add_device_to_white_list
+	
+	branch z_hci_parse_packet_cmd_ogf_le_controller3
+
+z_hci_parse_packet_cmd_ogf_le_controller_read_remote_features:
+	call p_ipc_rx_hci_data_two_byte 		//connection handle
+	call p_hci_send_event_command_status
+	//branch p_le_send_feature_req
+z_le_send_feature_req:
+	arg 9,rega
+//	arg LL_FEATURE_REQ,regb
+//	call le_fifo_malloc_tx_ll
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_FEATURE_REQ
+	istore 1,contw
+	fetch 8,mem_le_features
+	istore 8,contw
+	rtn
+
+		
+z_hci_parse_packet_cmd_ogf_le_controller_encrypt:
+z_hci_parse_packet_cmd_ogf_le_controller_rand:
+z_hci_parse_packet_cmd_ogf_le_controller_start_encryption:
+z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_reply:
+z_hci_parse_packet_cmd_ogf_le_controller_ltk_request_negative_reply:
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_adv_enable:	//OCF:0x000A
+	call p_ipc_rx_hci_data_one_byte
+	store 1,mem_le_adv_enable
+	branch p_hci_send_event_command_complete_without_payload
+
+
+z_hci_parse_packet_cmd_ogf_le_controller_create_connection_cancel:
+	jam OFF,mem_le_scan_enable
+	jam CANCEL_CONNECTION,mem_mesh_creat_connection_flag
+	branch p_hci_send_event_command_complete_without_payload
+
+z_hci_parse_packet_cmd_ogf_le_controller_read_white_list_size:
+	arg 2,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	setarg LE_WHITE_LIST_MAX_SIZE
+	istore 1,contw
+	branch ipc_hci_tx_start
+z_hci_parse_packet_cmd_ogf_le_controller_clear_white_list:
+	jam 0,mem_le_white_list_cnt
+	jam 0,mem_le_white_list_type_and_bd_addr
+	jam 0,mem_le_white_list
+	branch p_hci_send_event_command_complete_without_payload
+z_hci_parse_packet_cmd_ogf_le_controller_add_device_to_white_list:
+	fetcht 1,mem_le_white_list_cnt
+	sub temp,LE_WHITE_LIST_MAX_SIZE,null
+	branch p_hci_send_event_command_complete_error_command_disallowed,zero
+	call p_ipc_rx_hci_data_seven_byte
+	store 7,mem_le_white_list_type_and_bd_addr
+	call z_le_add_device_to_white_list
+	branch p_hci_send_event_command_complete_without_payload
+
+
+
+// input: rega
+z_le_add_device_to_white_list:
+	fetch 1,mem_le_white_list_cnt
+	arg mem_le_white_list,contw
+	mul32 pdata,7,pdata
+	iadd contw,contw
+	fetch 7,mem_le_white_list_type_and_bd_addr
+	istore 7,contw
+	fetch 1,mem_le_white_list_cnt
+	pincrease 1
+	store 1,mem_le_white_list_cnt
+	rtn
+
+
+org z
+z_l2cap_init_queue:
+	fetch 1,mem_queue_init_flag
+	nbranch z_l2cap_link_queue_init,blank
+
+	jam 1,mem_queue_init_flag
+
+//	// TODO: here may occur l2cap buffer rcv error.
+//	jam BLOCK_MAX_NUM_NEW,mem_l2cap_rx_malloc_num
+//	setarg L2CAP_BIG_BUFF_LENTH
+//	store 2,mem_l2cap_rx_max_lenth
+	call z_init_all_queue
+
+	// init the big buffer queue
+	fetchr loopcnt,1,mem_alloc_big_total_size
+	fetchr regb,2,mem_param_alloc_big_buffer_start_address
+	fetch 2,mem_param_alloc_big_buffer_max_length
+	store 2,mem_temp
+	setarg mem_alloc_big_block
+	store 2,mem_temp1
+	call z_queue_init_loop
+	
+	// store the big block ptr to list
+	fetch 1,mem_alloc_big_total_size
+	mul32 pdata,3,loopcnt
+	arg mem_alloc_big_block_start,contr
+	arg mem_big_block_ptr_list,contw
+	call memcpy_fast
+	
+	// init the normal buffer queue
+	fetchr loopcnt,1,mem_alloc_normal_total_size
+	fetchr regb,2,mem_param_alloc_normal_buffer_start_address
+	fetch 2,mem_param_alloc_normal_buffer_max_length
+	store 2,mem_temp
+	setarg mem_alloc_normal_block
+	store 2,mem_temp1
+	call z_queue_init_loop
+
+	// store the big block ptr to list
+	fetch 1,mem_alloc_normal_total_size
+	mul32 pdata,3,loopcnt
+	arg mem_alloc_normal_block_start,contr
+	arg mem_normal_block_ptr_list,contw
+	branch memcpy_fast
+	
+z_queue_init_loop:
+	fetchr rega,2,mem_temp1
+	call queue_insert
+	fetch 2,mem_temp
+	iadd regb,regb
+	loop z_queue_init_loop
+	rtn
+
+z_init_all_queue:
+	setarg mem_alloc_normal_block
+	call z_queue_init
+	setarg mem_alloc_big_block
+	call z_queue_init
+	setarg mem_snd_br_block
+	call z_queue_init
+	setarg mem_snd_ble_block
+	call z_queue_init
+	setarg mem_snd_hci_block
+//input: pdata: queue start addr
+z_queue_init:
+	copy pdata,contw
+	add pdata,BLOCK_TOTAL_SIZE_OFFSET,rega // point to data ptr
+	add pdata,BLOCK_DATA_OFFSET,pdata // point to data ptr
+	istore 2,contw // header
+	istore 2,contw // rptr
+	istore 2,contw // wptr
+
+	ifetcht 1,rega // get total buffer size.
+	mul32 temp,3,temp
+	iadd temp,pdata
+	istore 2,contw // end ptr
+
+	increase 1,contw // skip total length
+
+	setarg 0
+	istore 1,contw // cur len
+
+	copy temp,loopcnt
+	branch clear_mem
+/*	
+//input:pdata
+queue_get_wrtie_ptr:
+	add rega,BLOCK_WPTR_OFFSET,pdata
+	ifetcht 2,pdata
+	ifetch 3,temp
+	branch get_pdata_contw
+*/
+
+
+org z
+z_l2cap_link_queue_init:
+	fetch 3,mem_rcv_br_queue_ptr
+	ncall z_l2cap_link_queue_free_rx_buffer,blank
+//	fetch 3,mem_rcv_ble_queue_ptr
+//	ncall z_l2cap_link_queue_free_rx_buffer,blank
+	
+	setarg 0
+	store 3,mem_rcv_br_queue_ptr
+//	store 3,mem_rcv_ble_queue_ptr
+	
+//	call z_l2cap_ble_link_queue_init
+z_l2cap_br_link_queue_init:
+	arg mem_snd_br_block,pdata
+	store 2,mem_temp
+	
+	branch z_l2cap_queue_free_all
+
+//z_l2cap_ble_queue_init:
+//	fetch 3,mem_rcv_ble_queue_ptr
+//	ncall z_l2cap_link_queue_free_rx_buffer,blank	
+//	setarg 0
+//	store 3,mem_rcv_ble_queue_ptr
+//	branch  z_l2cap_ble_link_queue_init 
+
+//z_l2cap_ble_link_queue_init:
+//	arg mem_snd_ble_block,pdata
+//	store 2,mem_temp
+//input: rega: queue block
+z_l2cap_queue_free_all:
+	fetchr rega,2,mem_temp
+	call p_queue_get_len
+	rtn blank
+	// get len will change rega
+	fetchr rega,2,mem_temp
+	call queue_delete
+	call free_buffer
+	branch z_l2cap_queue_free_all
+	
+z_l2cap_link_queue_free_rx_buffer:
+	copy pdata,regb
+	branch free_buffer
+	
+org z
+z_hci_parse_complete_packet:
+	fetch 1,mem_mesh_hci_opcode_ogf
+	beq HCI_OGF_LINK_CONTROL,z_hci_parse_packet_cmd_ogf_link_control_base
+	beq HCI_OGF_LINK_POLICY,z_hci_parse_packet_cmd_ogf_link_policy_base
+	beq HCI_OGF_CONTROLLER_AND_BASEBAND,z_hci_parse_packet_cmd_ogf_controller_and_baseband_base
+	beq HCI_OGF_INFOMATIONAL_PARAM,z_hci_parse_packet_cmd_ogf_infomational_parameters_base
+	beq HCI_OGF_STATUS_PARAM,z_hci_parse_packet_cmd_ogf_status_parameters_base
+	beq HCI_OGF_TEST,z_hci_parse_packet_cmd_ogf_testing_base
+	beq HCI_OGF_LE_CONTROLLER,z_hci_parse_packet_cmd_ogf_le_controller_base
+	beq HCI_OGF_VENDOR_SPECIFIC_DEBUG,z_hci_parse_packet_cmd_ogf_vendorspecific_debug_base
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_link_control_base:
+	branch z_hci_parse_packet_cmd_ogf_link_control
+
+z_hci_parse_packet_cmd_ogf_controller_and_baseband_base:
+	branch z_hci_parse_packet_cmd_ogf_controller_and_baseband
+
+z_hci_parse_packet_cmd_ogf_infomational_parameters_base:
+	branch z_hci_parse_packet_cmd_ogf_infomational_parameters
+
+z_hci_parse_packet_cmd_ogf_le_controller_base:
+	branch z_hci_parse_packet_cmd_ogf_le_controller
+	
+z_hci_parse_packet_cmd_ogf_link_policy_base:
+	branch z_hci_parse_packet_cmd_ogf_link_policy
+
+/*********
+	HCI_OGF_INFOMATIONAL_PARAM
+*********/
+
+/*********
+	HCI_OGF_STATUS_PARAM
+*********/
+z_hci_parse_packet_cmd_ogf_status_parameters_base:
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+
+/*********
+	HCI_OGF_TEST
+*********/
+z_hci_parse_packet_cmd_ogf_testing_base:
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+
+
+/*********
+	HCI_OGF_VENDOR_SPECIFIC_DEBUG
+*********/
+z_hci_parse_packet_cmd_ogf_vendorspecific_debug_base:
+	fetch 1,mem_mesh_hci_opcode_ocf
+	beq HCI_WRITE_BD_ADDR,z_hci_parse_packet_cmd_ogf_vendorspecific_write_bd_addr
+ifdef FSC_RTK_HOST
+	beq 0x17,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_17
+	beq 0x20,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_20
+	beq 0xa3,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3
+	beq 0x60,z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_read_svn_version
+endif
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_vendorspecific_write_bd_addr:
+	call p_ipc_rx_hci_data_six_byte
+	store 6,mem_device_public_address
+	call p_hci_init_bd_address
+	branch p_hci_send_event_command_complete_without_payload
+
+
+ifdef FSC_RTK_HOST
+z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_17:
+	jam 0x3f,mem_fsc_rtk_host
+	branch p_hci_send_event_command_complete_without_payload
+
+
+
+z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_20:
+	arg 0x02,loopcnt
+	call p_hci_prepare_send_event_command_complete
+	setarg 0
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3:
+	call p_ipc_rx_hci_data_two_byte// Opcode
+	fetcht 1,mem_conn_handle
+	isub temp,null
+	branch z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3_event,zero
+	fetcht 1,mem_le_conn_handle
+	isub temp,null
+	nrtn zero
+z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_a3_event:	
+	storet 1,mem_hci_conn_handle
+	arg 0x03,loopcnt
+	call p_hci_prepare_send_event_command_complete
+	fetch 1,mem_hci_conn_handle
+	istore 2,contw
+	fetch 1,mem_rssi
+	call p_rssi_convert
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+z_hci_parse_packet_cmd_ogf_vendorspecific_rtk_read_svn_version:
+	arg 2,loopcnt
+	call p_hci_prepare_send_event_command_complete
+	fetch 2,mem_hci_version_svnid
+	istore 2,contw
+	branch ipc_hci_tx_start
+endif	
+
+
+org z
+z_hci_send_connection_rtn_error:
+	jam 11,mem_mesh_event_para_total_length
+	jam HCI_EVENT_CONNECTION_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 1,mem_mesh_event_parameter_status
+	istore 1,contw
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	fetch 6,mem_plap
+	istore 6,contw
+	force 1,pdata				/* connection type=1:ACL */
+	istore 1,contw
+	force 0,pdata
+	fetcht 1,mem_state_map
+	isolate1 smap_encryption,temp
+	setflag true,0,pdata
+	istore 1,contw
+	//TODO: restore connection handle
+	fetch 1,mem_conn_handle
+	branch ipc_hci_tx_start
+
+	/* temp is connection type 0=sco,1=acl */
+
+org z
+z_hci_send_page_scan_repetition_mode_change:
+	jam 7,mem_mesh_event_para_total_length
+	jam HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 6,mem_plap
+	istore 6,contw
+	fetch 1,mem_page_scan_repetition_mode
+	istore 1,contw
+	branch ipc_hci_tx_start
+	
+
+org z
+z_hci_send_disconnect_complete:
+	jam 4,mem_mesh_event_para_total_length
+	jam HCI_EVENT_DISCONNECTION_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0x00
+	istore 1,contw
+	fetch 1,mem_hci_record_disc_conn_handle
+	istore 2,contw
+	fetch 1,mem_disconn_reason_send
+	istore 1,contw
+	fetch 1,mem_state_map
+	set0 smap_edr,pdata
+	store 1,mem_state_map
+	branch ipc_hci_tx_start
+
+	
+org z
+z_hci_send_mode_change:
+	jam 6,mem_mesh_event_para_total_length
+	jam HCI_EVENT_MODE_CHANGE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 1,mem_mesh_event_parameter_rtn
+	istore 1,contw
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	fetch 1,mem_mesh_event_parameter_status
+	istore 1,contw
+	branch z_hci_send_mode_change_active,blank
+	fetch 2,mem_tsniff
+	rshift pdata,pdata
+	branch z_hci_send_mode_change_sniff
+z_hci_send_mode_change_active:
+	setarg 0
+z_hci_send_mode_change_sniff:
+	istore 2,contw
+	branch ipc_hci_tx_start
+
+org z
+z_hci_parse_packet_cmd_ogf_le_controller3:
+ 	fetch 1,mem_mesh_hci_opcode_ocf
+ 	beq HCI_LE_REMOVE_DEVICE_FROM_WHITE_LIST,z_hci_parse_packet_cmd_ogf_le_controller_remove_device_from_white_list
+	beq HCI_LE_SET_DATA_LENGTH,z_hci_parse_packet_cmd_ogf_le_controller_set_data_length
+	branch p_hci_send_event_command_complete_error_command_nuknown
+
+z_hci_parse_packet_cmd_ogf_le_controller_remove_device_from_white_list:
+	fetch 1,mem_le_white_list_cnt
+	branch p_hci_send_event_command_complete_error_command_disallowed,blank
+	call p_ipc_rx_hci_data_seven_byte
+	store 7,mem_le_white_list_type_and_bd_addr
+	call z_le_remove_device_from_white_list
+	fetch 1,mem_le_white_list_cnt
+	pincrease -1
+	store 1,mem_le_white_list_cnt
+	branch p_hci_send_event_command_complete_without_payload
+
+z_le_remove_device_from_white_list:
+	call p_check_addr_in_white_list
+	nbranch p_hci_send_event_command_complete_error_command_disallowed,blank
+z_le_remove_device_from_white_list_loop:
+	copy regb,contw
+	increase 7,regb
+	copy regb,contr
+	ifetch 7,contr
+	istore 7,contw
+	loop z_le_remove_device_from_white_list_loop
+	setarg 0
+	increase -7,contw
+	istore 7,contw
+	rtn
+	
+
+z_hci_parse_packet_cmd_ogf_le_controller_set_data_length:
+	//length
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_local_tx_max_octets
+	//time
+	call p_ipc_rx_hci_data_two_byte
+	store 2,mem_local_tx_max_time
+	call z_le_send_data_length_req
+	
+	arg 3,loopcnt
+	call p_hci_prepare_send_event_command_complete_with_status_success
+	fetch 1,mem_le_conn_handle
+	istore 2,contw
+	branch ipc_hci_tx_start
+	//branch p_hci_send_event_command_complete_without_payload
+	
+z_le_send_data_length_req:
+	arg LL_LENGTH_REQ,regb
+	//branch z_le_send_data_length
+//z_le_send_data_length:
+	arg 9,rega
+//	call le_fifo_malloc_tx_ll
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_LENGTH_RSP
+	istore 1,contw
+	fetch 8,mem_local_rx_max_octets
+	istore 8,contw
+	rtn
+
+
+org z
+z_hci_inquiry_reply_check_eir:
+	fetch 1,mem_inquiry_mode
+	bne 2,z_hci_inquiry_reply
+	call inquiry_receive_eir
+	nrtn sync
+	rtnmark1 mark_fhs_eir	
+z_hci_inquiry_reply:
+	//call inquiry_receive_eir_rtn
+	fetcht 6,extm_lap
+	call context_search_plap2
+	rtn zero
+	call p_estimate_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0x01
+	//Num_responses
+	istore 1,contw
+	fetch 6,extm_lap
+	//bd_addr
+	istore 6,contw
+	fetch 1, extm_fhs_misc
+	copy pdata, temp
+	rshift3 pdata, pdata
+	rshift3 pdata, pdata
+	//page_scan_repetition_mode
+	istore 1,contw
+	setarg 0x00
+	//reserved1
+	istore 1,contw
+	fetch 1,mem_inquiry_mode
+	bne 0,z_hci_inquiry_reply_mode1		
+z_hci_inquiry_reply_mode0:
+	setarg 0x00
+	//reseved2
+	istore 1,contw
+	fetch 3, extm_class
+	istore 3,contw
+	fetch 4,mem_clke_bt
+	isub clkn_bt,pdata
+	istore 2,contw
+	branch ipc_hci_tx_start
+z_hci_inquiry_reply_mode1:
+	fetch 3, extm_class
+	istore 3,contw
+	fetch 4,mem_clke_bt
+	isub clkn_bt,pdata
+	istore 2,contw
+	fetch 1,mem_rssi
+	call p_rssi_convert
+	istore 1,contw
+	fetch 1,mem_inquiry_mode
+	beq 2,z_hci_inquiry_reply_mode2
+	branch ipc_hci_tx_start
+z_hci_inquiry_reply_mode2:
+	fetch 3,mem_rcv_br_queue_ptr
+	copy pdata,contr
+	ifetch 1,contr
+	ifetch 2,contr
+	rtn blank
+	copy pdata,temp
+	copy pdata,loopcnt
+	call memcpy_fast
+	sub temp,240,loopcnt
+	call clear_mem
+	branch ipc_hci_tx_start
+
+org z
+z_send_lmp_escape:
+	fetch 1,mem_lmp_to_send
+	beq LMP_EXT_FEATURES_RES,z_send_lmpext_features_res
+	beq LMP_EXT_FEATURES_REQ,z_send_lmpext_features_req
+	branch send_lmp_escape
+z_send_lmpext_features_res:
+	fetcht 1,mem_simple_pairing_mode
+	storet 1,mem_lmpext_ssp_enable+1
+	branch send_lmpext_features_res
+z_send_lmpext_features_req:
+	fetcht 1,mem_simple_pairing_mode
+	storet 1,mem_lmpext_ssp_enable+1
+	branch send_lmpext_features_req
+
+org z
+z_hci_send_linkkey_notification:
+	jam 0x17,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LINK_KEY_NOTIFICATION,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 6,mem_plap
+	istore 6,contw
+	arg mem_link_key,contr
+	force 16,loopcnt
+	call memcpy_fast
+	force 0,pdata
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+org z
+
+//input:temp connection handle
+//MASTER_CONNECTION_HANDLE
+//SLAVE_CONNECTION_HANDLE
+z_hci_send_event_le_connection_complete:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 LE_CONNECTION_COMPLETE_EVENT
+	jam 19,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg HCI_LE_SUBEVENT_CONN_COMPLETE
+	istore 2,contw	//subevent code & status
+	fetch 1,mem_le_conn_handle
+	istore 2,contw	//connection handle
+	call p_le_get_role
+	istoret 1,contw	//role
+	fetch 1,mem_le_conn_peer_addr_type
+	istore 1,contw	//peer address type
+	fetch 6,mem_le_plap
+	istore 6,contw	//peer address
+	fetch 2,mem_le_tsniff
+	rshift2 pdata,pdata
+	istore 2,contw	//connection interval
+	fetch 4,mem_le_slave_latency
+	istore 4,contw	//connect latency & supervision timeout
+	fetch 1,mem_le_peer_sca
+	istore 1,contw	//master clock accuracy
+	fetch 1,mem_le_conn_handle
+	branch ipc_hci_tx_start
+
+org z
+z_hci_send_le_connection_update_commplete:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 LE_CONNECTION_UPDATE_COMPLETE_EVENT
+	jam 10,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg HCI_LE_SUBEVENT_CONN_UPDATE_COMPLETE
+	istore 2,contw		//subevent code & status
+	fetch 1,mem_le_conn_handle
+	istore 2,contw
+	fetch 6,mem_le_new_conninterval
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+
+
+org z
+z_parse_lmp_escape:
+	//bpatchx patch2e_1,mem_patch2e
+	fetch 1,mem_rxbuf+1
+	set1 7,pdata
+	store 1,mem_lmi_opcode2
+	beq LMP_EXT_FEATURES_REQ,z_parse_lmpext_features_req
+	beq LMP_EXT_FEATURES_RES,z_parse_lmpext_features_res
+	beq LMP_IO_CAP_REQ,z_parse_lmpext_iocap_req
+	beq LMP_IO_CAP_RES,z_parse_lmpext_iocap_res
+	branch parse_lmp_escape+4
+
+z_parse_lmpext_features_req:
+	call parse_lmpext_features_req
+// TODO: judge page index.
+z_store_remote_ext_features:
+	// features page & max supported page
+	fetch 2,mem_rxbuf+2
+	// extended features
+	fetch 8,mem_rxbuf+4
+	store 8,mem_remote_ext_features0
+	rtn	
+
+z_parse_lmpext_features_res:
+	call parse_lmpext_features_res
+	branch z_store_remote_ext_features	
+
+z_parse_lmpext_iocap_req:
+	call iocap_lmpext_load
+	call z_hci_send_io_cap_response_event
+	branch p_hci_send_io_cap_req_event	
+
+z_parse_lmpext_iocap_res:
+	call z_hci_send_io_cap_response_event
+	call iocap_lmpext_load
+	call iocap_lmpext_hci
+	jam SP_FLAG_COMMIT,mem_master_sp_flag
+	jam SP_STAT_KEY_SEND,mem_master_sp_state
+	rtn	
+	
+z_hci_send_io_cap_response_event:
+	//BD_ADDR-6,IO_Capability-1,OOB_Data_Present-1,Authentication_Requirements-1
+	jam 9,mem_mesh_event_para_total_length
+	jam HCI_EVENT_IO_CAP_RESPONSE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 6,mem_plap
+	istore 6,contw
+	fetch 3,mem_sp_iocap_remote
+	istore 3,contw
+	branch ipc_hci_tx_start
+
+org z
+// input --- mem_encryp_inital_value  output --- mem_encryp_inital_value
+z_efuse_custom_encryption:
+	arg 0x20,pdata
+	arg mem_efuse_encryp_data,rega
+	arg 32,temp
+	call efuse_read_data
+//	setarg 0xaa55
+//	store 2,mem_encryp_inital_value
+	arg mem_efuse_encryp_data,contr
+	ifetch 2,contr
+	rtn blank
+	store 2,mem_encryp_param
+	call z_efuse_custom_encryption_init
+	call z_efuse_custom_encryption_read_efuse_data_add_loop
+	call z_efuse_custom_encryption_init
+	branch z_efuse_custom_encryption_read_efuse_data_ixor_loop
+	
+z_efuse_custom_encryption_init:
+	arg mem_efuse_encryp_data+2,rega
+	arg 6,loopcnt
+	jam 1,mem_encryp_count
+	rtn
+	
+// input:pdata----read efuse addr
+z_efuse_custom_encryption_read_efuse_data_add_loop:
+	ifetch 2,rega
+	fetcht 2,mem_encryp_inital_value
+	iadd temp,pdata
+	store 2,mem_encryp_inital_value
+	fetch 1,mem_encryp_count
+	iadd rega,rega
+	increase 2,rega
+	fetch 1,mem_encryp_count
+	pincrease 1
+	store 1,mem_encryp_count
+	loop z_efuse_custom_encryption_read_efuse_data_add_loop
+	rtn
+z_efuse_custom_encryption_read_efuse_data_ixor_loop:
+	ifetch 2,rega
+	fetcht 2,mem_encryp_inital_value
+	ixor temp,pdata
+	store 2,mem_encryp_inital_value
+	fetch 1,mem_encryp_count
+	iadd rega,rega
+	add rega,2,rega
+	fetch 1,mem_encryp_count
+	pincrease 1
+	store 1,mem_encryp_count
+	loop z_efuse_custom_encryption_read_efuse_data_ixor_loop
+	fetch 2,mem_encryp_inital_value
+	fetcht 2,mem_encryp_param
+	isub temp,null
+	nbranch assert,zero
+	rtn
+
+org z
+z_ipc_rx_hci:
+	fetcht 3,mem_ipc_data_rx_buf_payload_ptr
+	call p_ipc_rx_store_contr1
+	call p_ipc_rx_hci_data_one_byte
+	beq HCI_H4_TYPE_CMD,z_hci_parse_packet_cmd
+	beq HCI_H4_TYPE_ACL,z_hci_parse_packet_acl
+	branch assert
+
+z_hci_parse_packet_cmd:
+	call p_ipc_rx_hci_data_two_byte// Opcode
+	store 2,mem_mesh_hci_opcode
+	arg 0x3ff,temp
+	iand temp,temp	//low 10bit
+	storet 2,mem_mesh_hci_opcode_ocf
+	rshift2 pdata,pdata
+	rshift8 pdata,pdata	//high 6bit
+	store 1,mem_mesh_hci_opcode_ogf
+	call p_ipc_rx_hci_data_one_byte	// parameter total length
+	store 1,mem_mesh_hci_cmd_len
+	branch z_hci_parse_complete_packet
+
+z_hci_parse_packet_acl:
+	call p_ipc_rx_hci_data_two_byte// Opcode
+	store 1,mem_hci_conn_handle
+	call z_hci_parse_packet_acl_FB_flag
+	call p_ipc_rx_hci_data_two_byte// length
+	store 2,mem_temp
+
+	call context_search_conn_handle
+	// TODO: here need change to other work.
+	nrtn zero
+
+	// check is classic or ble
+	add rega,coffset_mode,contr
+	ifetch 1,contr
+	bbit1 mode_le,z_hci_parse_packet_acl_le
+z_hci_parse_packet_acl_classic:
+	fetch 2,mem_temp
+	//increase 3,pdata  // with l2cap header. 2byte length, 1byte type
+	store 2,mem_alloc_buffer_len
+	call malloc_buffer_is_enough
+	call ice_break,blank
+
+	
+	fetch 2,mem_temp
+	copy pdata,rega
+	copy pdata,regb
+	//TODO: classic need do here
+	call l2cap_malloc//return with pdata ptr
+	copy regb,contw
+	// l2cap payload header
+	fetch 2,mem_temp
+	istore 2,contw
+	istorer type,1,contw
+z_hci_parse_packet_acl_end:
+	fetch 2,mem_temp
+	copy pdata,loopcnt
+	call p_ipc_rx_restore_contr
+	branch memcpy_fast
+	
+
+z_hci_parse_packet_acl_le:	
+	// Think to judge classic or ble.
+	fetch 2,mem_temp	
+	//increase 3,pdata  // with l2cap header. 2byte length, 1byte type
+	call z_le_fifo_check_full
+	nrtn blank
+	fetch 2,mem_temp
+	copy pdata,rega
+	copy pdata,regb
+	call le_fifo_malloc_tx
+	branch z_hci_parse_packet_acl_end
+
+z_hci_parse_packet_acl_FB_flag:
+	rshift8 pdata,pdata
+	rshift4 pdata,pdata
+	force LLID_CONTINUE,type
+	rtneq BT_ACL_CONT
+	force LLID_START,type
+	rtn
+
+z_le_fifo_check_full:
+	call malloc_buffer_is_full_raw
+	branch setarg1,blank
+	branch setarg0
+
+org z
+z_l2cap_ble_queue_init:
+	fetch 3,mem_rcv_ble_queue_ptr
+	ncall z_l2cap_ble_queue_free_rx_buffer,blank	
+	setarg 0
+	store 3,mem_rcv_ble_queue_ptr
+z_l2cap_ble_link_queue_init:
+	arg mem_snd_ble_block,pdata
+	store 2,mem_temp
+//input: rega: queue block
+z_l2cap_ble_queue_free_all:
+	fetchr rega,2,mem_temp
+	call p_queue_get_len
+	rtn blank
+	// get len will change rega
+	fetchr rega,2,mem_temp
+	call queue_delete
+	call free_buffer
+	branch z_l2cap_ble_queue_free_all
+	
+z_l2cap_ble_queue_free_rx_buffer:
+	copy pdata,regb
+	branch free_buffer
+
+
+org z
+z_parse_lmp_process:
+	//bpatchx patch2e_0,mem_patch2e
+	// set flag
+	arg LOG_POINT_1000,rega
+	fetcht 2,mem_rxbuf
+	call debug_log_print
+  	fetch 1,mem_lmi_opcode2
+	beq LMP_ACCEPTED,z_parse_lmp_accepted//multi
+	beq LMP_NOT_ACCEPTED,z_parse_lmp_not_accepted//multi
+	beq LMP_START_ENCRYPTION_REQ, z_parse_lmp_start_encryption_req
+	beq LMP_FEATURES_REQ,z_parse_lmp_features_req
+	beq LMP_FEATURES_RES,z_parse_lmp_features_res
+	beq LMP_DETACH,z_parse_lmp_detach
+	beq LMP_IN_RAND,p_parse_lmp_in_rand		//in_rand
+	beq LMP_NAME_RES,p_parse_lmp_name_res
+
+	branch z_parse_lmp_process_sub
+
+
+z_parse_lmp_accepted:
+	fetch 1,mem_rxbuf+1
+	store 1,mem_lmi_accepted_opcode
+	beq LMP_START_ENCRYPTION_REQ,z_parse_lmp_accepted_start_enc//ok
+	branch parse_lmp_accepted+3
+
+z_parse_lmp_accepted_start_enc:
+	call parse_lmp_accepted_start_enc
+	branch z_hci_send_encryption_change_complete_event
+
+z_parse_lmp_start_encryption_req:
+	call parse_lmp_start_encryption_req+2
+	branch z_hci_send_encryption_change_complete_event
+
+z_hci_send_encryption_change_complete_event:
+	//Status(1), conn_handle(2), enc_mode(1)
+	jam 4,mem_mesh_event_para_total_length
+	jam HCI_EVENT_ENCRYPTION_CHANGE_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0
+ 	istore 1,contw
+ 
+	fetcht 1,mem_conn_handle
+	istoret 2,contw
+
+	//enc_mode
+	setarg 1
+ 	istore 1,contw
+ 
+	branch ipc_hci_tx_start
+
+z_parse_lmp_not_accepted:
+	fetch 1,mem_rxbuf+1
+	store 1,mem_lmi_accepted_opcode
+	beq LMP_AU_RAND,z_parse_lmp_not_accepted_aurand//ok
+	branch parse_lmp_not_accepted+3
+
+z_parse_lmp_not_accepted_aurand:
+	fetch 1,mem_device_option
+	bne dvc_op_headset,parse_lmp_not_accepted_aurand_send_detach
+	fetch 1,mem_link_key_exists
+	rtn blank
+	fetcht 1,mem_reconn_lmp_sm
+	jam 0,mem_reconn_lmp_sm
+	jam 0,mem_link_key_exists
+	fetch 1,mem_rxbuf+2
+	rtnne KEY_MISSING
+	storet 1,mem_reconn_lmp_sm
+	jam LOCAL_STATEMACHINE,mem_sp_localsm
+//	call p_hci_send_io_cap_req_event
+	call p_sp_check_ssp_available
+	fetch 1,mem_simple_pairing_mode
+	branch p_hci_send_pincode_req_event,blank
+	rtn	
+z_parse_lmp_features_req:
+	call parse_lmp_features_req
+z_store_remote_features:
+	// features
+	fetch 8,mem_rxbuf+1
+	store 8,mem_remote_features
+	rtn
+z_parse_lmp_detach:
+	fetch 1,mem_rxbuf+1
+	store 1,mem_disconn_reason_send
+//	branch parse_lmp_detach
+	call p_prepare_disconnect
+	branch accept_lmp_msg
+	
+z_parse_lmp_features_res:
+	call parse_lmp_features_res
+	branch z_store_remote_features
+
+
+
+org z
+z_parse_lmp_process_sub:
+  	fetch 1,mem_lmi_opcode2
+	beq LMP_SRES,z_parse_lmp_sres
+	beq LMP_SNIFF_REQ,z_parse_lmp_sniff_req
+	beq LMP_AU_RAND,z_parse_lmp_au_rand
+
+	beq LMP_HOST_CONNECTION_REQ,z_parse_lmp_conn_req
+ 	beq LMP_MAX_SLOT_REQ,z_parse_lmp_max_slot_req
+	beq  LMP_DHKEY_CHECK,z_parse_dhkey_check
+
+	//branch z_parse_lmp_process_sub
+	branch parse_lmp_process+5
+
+	
+z_parse_lmp_sres:	
+	arg mem_plap,rega
+	call function_e1
+	fetch 4,mem_rxbuf+1
+	fetcht 4,mem_input_store
+	isub temp,null
+	branch p_authentication_event,zero
+	branch parse_lmp_sres+6
+
+
+z_parse_lmp_sniff_req:
+	fetch 2,mem_default_link_policy_settings
+	bbit0 sniff_mode,lmp_reject_sniff
+	branch parse_lmp_sniff_req+1
+
+
+
+z_parse_lmp_au_rand:
+	call push_tid_follow
+	store 1,mem_sres_tid
+	call lmp_copy_rand
+	jam LMP_SRES,mem_lmo_opcode2
+	fetch 1,mem_link_key_exists
+	nrtn blank
+	fetch 1,mem_state
+	rtnbit1 state_combkey		/* we have comb key, but not verified */
+	call parse_lmp_au_rand_1
+	// send link key request
+	branch p_hci_send_linkkey_req_event
+
+
+z_parse_lmp_max_slot_req:
+	fetch 1,mem_max_slot
+	pincrease 1
+	fetcht 1,mem_rxbuf+1
+	isub temp,null
+	nbranch z_parse_lmp_max_slot_req_not_accept,positive
+z_parse_lmp_max_slot_event:
+	storet 1,mem_max_slot
+	call accept_lmp_msg
+	branch z_hci_send_max_slots_change
+
+z_parse_dhkey_check:
+	fetch    1,mem_master_sp_state
+	beq SP_STAT_CONFIRM_SEND,z_parse_dhkey_check_test
+z_parse_dhkey_check_test:
+	jam LMP_ACCEPTED,mem_lmo_opcode2
+	branch parse_dhkey_check
+
+z_parse_lmp_max_slot_req_not_accept:
+	jam LMP_NOT_ACCEPTED,mem_lmo_opcode2
+	rtn
+
+z_hci_send_max_slots_change:
+	jam 3,mem_mesh_event_para_total_length
+	jam HCI_EVENT_MAX_SLOTS_CHANGE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	fetch 1,mem_conn_handle
+	istore 2,contw
+	fetch 1,mem_max_slot
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+	
+org z
+z_parse_lmp_conn_req:
+//	branch p_hci_send_conn_req_event
+
+z_hci_send_conn_req_event:
+	fetch 1,mem_conn_req_status
+	beq 1,z_hci_send_conn_req_event_estimate
+z_hci_send_conn_req_event_1:
+	call z_classic_connection_init
+	//BD_ADDR(6), Class_of_Device(3), Link_Type(1)
+	jam 10,mem_mesh_event_para_total_length
+	jam HCI_EVENT_CONNECTION_REQUEST,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	//call hci_write_plap
+	fetch 6,mem_plap
+	istore 6,contw
+	// class of device
+	fetch 3,extm_class
+	istore 3,contw
+	// link type, 0:SCO, 1:ACL
+	setarg 1
+ 	istore 1,contw
+	fetch 6,mem_plap
+	store 6,mem_bd_addr_new
+	branch ipc_hci_tx_start
+z_hci_send_conn_req_event_estimate:
+	fetch 6,mem_bd_addr_new
+	fetcht 6,mem_plap
+	isub temp,null
+	branch z_hci_send_conn_req_event_1,zero
+	rtn	
+
+z_classic_connection_init:
+	jam 1,mem_conn_req_status
+	jam 0,mem_conn_status
+	//setarg 0
+	//store 8,mem_remote_features
+	//store 8,mem_remote_ext_features0
+	//store 8,mem_remote_ext_features1
+	rtn
+
+org z
+z_hci_send_inquiry_comple:
+	set0 mark_inquiry_on,mark
+	jam 1,mem_mesh_event_para_total_length
+	jam HCI_EVENT_INQUIRY_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+
+
+
+org z
+z_app_init:
+ifdef MINZHAN_SDK
+	jam 0,mem_ota_enable_xip_flag
+endif	
+	// RAM reset.
+	//jam 0,mem_ota_wdt_en_flag
+	//jam 0,mem_ota_wdt_m0_en
+	
+	jam 0x1c,0x1f000
+	jam 0x05,0x8042
+	call z_buck_setting
+	fetch 1,0x8341
+	store 1,mem_hibernate_flag
+
+	fetch 1,mem_xlmp_conn_state
+	store 1,mem_lmp_conn_state
+
+	ncall z_app_init_efuse_data,wake
+
+	
+ifdef FUNCTION_WATCH_DOG
+	call wdt_init_reset_with_start
+endif //FUNCTION_WATCH_DOG
+	call headset_init
+	
+ifdef MINZHAN_SDK	
+	call z_read_efuse_64_bytes
+endif
+
+	setarg p_app_event_normal_process
+	store 2,mem_cb_bb_event_process
+
+	setarg p_headset_evt_100ms_timer
+	store 2,mem_cb_event_timer
+	setarg p_headset_cb_idle_process
+	store 2,mem_cb_idle_process
+
+	setarg cb_enter_lpm
+	store 2,mem_cb_before_lpm
+	setarg cb_enter_hibernate
+	store 2,mem_cb_before_hibernate 
+
+	
+	//call headset_check_reconnet
+	//call p_ipc_notify_m0_wakeup_flag_init
+	
+	call z_set_gpio_after_lpm,wake
+//	call qspi_release_powerdown_flash,wake
+	nbranch wake_from_power,wake
+wake_for_lpm:
+	call ipc_lock_m0_lmp_wait_work_flag
+	call enable_xip
+	jam BT_EVT_WAKEUP,mem_fifo_temp
+	branch ipc_tx_bt_event
+
+ifdef MINZHAN_SDK
+z_read_efuse_64_bytes:
+	setarg 0
+	arg mem_efuse_64_bytes,rega
+	arg 64,temp
+	branch efuse_read_data
+endif
+
+wake_from_power:
+	// store local addr
+	fetch 6,mem_lap
+	store 6,mem_local_bdaddr
+ifdef MINZHAN_SDK
+	jam 2 ,core_reset 
+endif
+	call enable_xip
+
+	fetch 1,mem_hibernate_flag
+	bbit1 5,z_evt_restart
+	jam BT_EVT_RESET,mem_fifo_temp
+	call ipc_tx_bt_event
+
+	setarg 0x1171
+	store 2,mem_encryp_inital_value
+	branch z_efuse_custom_encryption
+
+z_evt_restart:
+	call p_clear_charge_reset_flag
+	jam BT_EVT_RESTART,mem_fifo_temp
+	branch ipc_tx_bt_event
+
+
+z_set_gpio_after_lpm:
+	call qspi_init_set
+	call qspi_gpio_init
+	nop 2000 // Delay for gpio26 work ready
+	branch qspi_release_powerdown_flash
+//	nop 100
+	//rtn
+
+z_buck_setting:
+	fetcht 4,core_lpm_buckctrl
+	storet 4,core_lpm_reg
+	jam 0xe6,0x804d
+	call p_lpm_write_wait_clock
+	jam 0x20,0x8005
+	branch p_lpm_write_wait_clock
+
+
+z_app_init_efuse_data:
+	setarg EFUSE_UCODE_ADC_GPIO_0_5
+	arg mem_efuse_adc_offset,rega
+	arg 8,temp
+	branch efuse_read_data
+
+
+org z
+z_ipc_init:
+	//fetch 1,mem_ipc_enable
+	//rtn blank
+	call z_ipc_notify_m0_wakeup_flag_init
+	call z_mram_clkon
+	branch ipc_init+5
+
+z_mram_clkon:
+	arg CLOCK_OFF_MRAM,queue
+	branch clk_on
+
+z_ipc_notify_m0_wakeup_flag_init:
+	jam 1,mem_wake_flag
+	rtn wake
+	jam 0,mem_wake_flag
+	rtn
+
+
+
+org z
+z_le_adv:
+	disable master
+	enable swfine
+	call le_init_adv
+	call le_next_adv_channel
+	call le_send_adv_ind
+	nbranch le_adv_not_match,match
+	fetch 1,mem_le_req_rcv
+	increase 1,pdata
+	store 1,mem_le_req_rcv
+	fetch 1,mem_le_rxbuf
+	and pdata,0x0f,pdata
+	beq SCAN_REQ,z_le_send_scan_response
+	branch le_adv+18
+
+z_le_send_scan_response:
+	arg SCAN_RSP,temp
+	fetch 1,mem_le_adv_own_addr_type
+	nsetflag blank,LE_SENDER_ADDR_BIT,temp
+	storet 1,mem_le_txheader
+	fetcht 1,mem_le_scan_data_len
+	add temp,6,pdata
+	store 1,mem_le_txlen
+	copy temp,loopcnt
+	fetch 1,mem_le_adv_own_addr_type
+	call p_le_get_public_addr,blank
+	ncall p_le_get_random_addr,blank
+	storet 6,mem_le_txpayload
+	arg mem_le_scan_data,contr
+	call memcpy
+	branch le_transmit_norx
+
+org z
+z_simple_pairing_process:
+	call z_master_simple_paring_sequence
+z_simple_pairing_sequence:
+	fetch 1,mem_sp_flag
+	rtn blank
+	jam      SP_FLAG_STANDBY,mem_sp_flag
+	fetch    1,mem_sp_state
+	beq  SP_STAT_CONFIRM_CHECK,z_sp_confirm_check
+	branch simple_pairing_sequence+5
+
+z_master_simple_paring_sequence:
+	fetch 1,mem_master_sp_flag
+	rtn blank
+	jam SP_FLAG_STANDBY,mem_master_sp_flag
+	fetch 1,mem_master_sp_state
+	beq SP_MASTER_STAT_START_SKIP,z_sp_master_send_io_cap_get
+	//beq SP_STAT_CONFIRM_SEND,p_master_sp_send_lmp_dhkey_check
+	beq SP_STAT_CONFIRM_CHECK,z_sp_confirm_check
+	//beq SP_STATE_END,p_master_sp_sm_end
+	branch master_simple_paring_sequence+5
+
+z_sp_confirm_check:
+	call sp_confirm_check
+	//branch p_hci_send_simple_pairing_complete_event
+z_hci_send_simple_pairing_complete_event:
+	//Status(1), BD_ADDR(6)
+	jam 7,mem_mesh_event_para_total_length
+	jam HCI_EVENT_SIMPLE_PAIRING_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg 0
+ 	istore 1,contw
+ 
+	fetch 6,mem_plap
+	istore 6,contw
+	branch ipc_hci_tx_start
+
+
+z_master_sp_send_lmp_dhkey_check:
+	branch tid_reply
+
+z_master_sp_sm_end:
+	//jam DEFAULT_STATEMACHINE,mem_sp_localsm
+	jam SP_STAT_DONE,mem_master_sp_state
+	call tid_initiate
+	//jam LMP_AU_RAND,mem_lmo_opcode2
+	call check_localsm_master
+ifdef SIMPLE_PAIRING
+	branch sp_master_key_prarm_push,true
+	branch sp_link_key_prarm_push
+endif
+	rtn
+
+z_sp_master_send_io_cap_get:
+	jam SP_FLAG_COMMIT,mem_master_sp_flag
+	jam SP_MASTER_STAT_START_DONE,mem_master_sp_state
+	rtn
+
+
+org z
+z_enter_hibernate_prepare_work:
+	call qspi_powerdown_flash
+z_clear_gpio_before_sleep:	
+	call z_clear_gpio_before_sleep_sub2
+	arg 32,loopcnt
+	arg core_gpio_conf,contr
+z_setgpio_loop:
+	copy contr,contw
+	ifetch 1,contr
+	beq gpcfg_qspi_sck,z_setgpio_pulldown
+	beq gpcfg_qspi_io0,z_setgpio_pulldown
+	beq gpcfg_qspi_io1,z_setgpio_pulldown
+	beq gpcfg_qspi_io3 ,z_setgpio_pulldown
+	beq gpcfg_iic_scl,z_setgpio_pulldown
+	beq gpcfg_iic_sda,z_setgpio_pulldown
+	bne gpcfg_input,z_setgpio_loop_end
+z_setgpio_pulldown:
+	setarg gpcfg_pulldown
+	istore 1,contw
+z_setgpio_loop_end:
+	loop z_setgpio_loop
+	rtn
+
+z_clear_gpio_before_sleep_sub2:	
+	arg 8,loopcnt
+	arg core_gpio_conf1,contr
+	branch z_setgpio_loop
+
+
+
+
+
+
+
+org z
+z_process_cmd:
+	call cmd_check_plap
+	nbranch z_process_cmd_conn_handle,zero
+//	branch process_cmd+6
+	
+	fetch 1,mem_hci_cmd
+	beq hci_cmd_remote_name_req,cmd_namereq
+	beq hci_cmd_pair,cmd_pair
+	beq hci_cmd_nopair,cmd_nopair
+	beq hci_cmd_linkkey,cmd_has_key
+	beq hci_cmd_nokey,cmd_no_key
+	beq hci_cmd_reject_conn,cmd_disconn
+	beq hci_cmd_role_switch,cmd_role_switch
+	beq hci_cmd_accept_conn,cmd_accept_conn
+	beq hci_cmd_accept_with_switch,cmd_accept_with_switch
+	beq hci_cmd_detach,cmd_detach
+	beq hci_cmd_in_sniff,cmd_in_sniff
+	beq hci_cmd_exit_sniff,z_cmd_exit_sniff
+z_process_cmd_conn_handle:
+	call cmd_check_handle
+	nrtn blank
+	fetch 1,mem_hci_cmd
+	beq hci_cmd_auth,z_cmd_auth
+	beq hci_cmd_send_supervision,z_cmd_send_supervision
+	branch process_cmd_conn_handle+4
+
+
+z_cmd_send_supervision:
+	jam LMP_SUPERVISION_TIMEOUT,mem_lmo_opcode2
+	branch cmd_exit
+
+z_cmd_exit_sniff:
+	jam LMP_UNSNIFF_REQ,mem_lmo_opcode2
+	branch cmd_exit
+
+z_cmd_auth:
+	fetch 1,mem_op
+	set1 op_auth_req,pdata
+	store 1,mem_op
+	fetch 1,mem_state
+	bbit1 state_linkkey,cmd_auth_sendaurand
+	call p_hci_send_linkkey_req_event
+	branch cmd_exit
+
+org z
+z_sniff_init:
+	bmark0 mark_sco_flag,z_sniff_init_acl
+	add clkn_bt,0,rega
+	branch z_sniff_init_master,master
+	add clke_bt,0,rega
+	branch z_sniff_init_master
+z_sniff_init_acl:
+	add clkn_bt,3,rega
+	branch z_sniff_init_master,master
+	add clke_bt,3,rega
+z_sniff_init_master:
+	fetcht 2,mem_tsniff
+	deposit rega
+	set0 27,pdata
+	idiv temp
+	fetch 2,mem_dsniff
+	call wait_div_end
+	remainder regc
+	isub regc,pdata
+	branch z_sniff_init_nowrap,positive
+	iadd temp,pdata
+z_sniff_init_nowrap:
+	iadd rega,pdata
+	store 4,mem_sniff_anchor
+	jam SWITCH_FLAG_INIT,mem_switch_flag
+	fetch 1,mem_state
+	set1 state_insniff,pdata
+	store 1,mem_state
+	fetch 1,mem_sniff_attempt
+	store 1,mem_current_sniff_attempt
+	setarg 0
+	store 3,mem_sniff_rcv
+	store 3,mem_sniff_lost
+	store 1,mem_sniff_unint_lost
+	fetch 2,mem_rx_window_sniff
+	store 2,mem_rx_window
+	nbranch z_sniff_init_mode_change,master
+	add am_addr,-1,queue
+z_sniff_init_mode_change:
+	jam 0x02,mem_mesh_event_parameter_status
+	branch z_hci_send_mode_change
+
+org z
+z_sniff_exit:
+	fetch 1,mem_state
+	rtnbit0 state_insniff
+	set0 state_insniff,pdata
+	store 1,mem_state
+	fetch 2,mem_rx_window_init
+	store 2,mem_rx_window
+	disable wake
+	jam 0x00,mem_mesh_event_parameter_status
+	branch z_hci_send_mode_change
+
+
+org z
+z_hci_send_role_change:
+	jam 8,mem_mesh_event_para_total_length
+	jam HCI_EVENT_ROLE_CHANGE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	force 0,pdata
+	istore 1,contw
+	fetch 6,mem_plap
+	istore 6,contw
+	fetch 1,mem_mesh_event_parameter_status
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+
+
+org z
+z_hci_send_role_change_err:
+	jam 0,mem_mesh_event_parameter_status
+	nbranch z_hci_send_role_change_err_slave,master
+	jam 1,mem_mesh_event_parameter_status
+z_hci_send_role_change_err_slave:
+	jam 8,mem_mesh_event_para_total_length
+	jam HCI_EVENT_ROLE_CHANGE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	force 0x35,pdata
+	istore 1,contw
+	fetch 6,mem_plap
+	istore 6,contw
+	fetch 1,mem_mesh_event_parameter_status
+	istore 1,contw
+	branch ipc_hci_tx_start
+
+
+org z
+z_newconn_init:
+	call init_lmp_reinit
+	call new_conn_handle
+	sub pdata,15,null
+	nbranch z_newconn_handle_init,positive
+	branch newconn_init+3
+z_newconn_handle_init:
+	jam 1,mem_handle_num
+	branch newconn_init+3
+
+
+org z
+z_parse_connect_req:
+//	fetch 1,mem_le_state
+//	rtnbit1 state_inconn
+	fetch 1,mem_le_rxbuf
+	fetcht 6,mem_le_lap
+	bbit1 LE_RECEIVER_ADDR_BIT,z_parse_connect_req_random_addr
+	branch z_parse_connect_req_public_addr
+z_parse_connect_req_random_addr:
+	fetcht 6,mem_mesh_le_random_address
+z_parse_connect_req_public_addr:
+	fetch 6,mem_le_rxbuf+8
+	isub temp,null
+	nrtn zero
+	call parse_connect_req+5
+	//arg SLAVE_CONNECTION_HANDLE,temp
+	//fetch 2,mem_le_init_superto
+	//store 2,mem_le_superto
+	branch z_hci_send_event_le_connection_complete
+
+
+org z 
+z_send_lmp:
+ifdef PATCH_DEBUG_LOG
+	// set flag
+	arg LOG_POINT_1001,rega
+	fetcht 1,mem_lmp_to_send
+	call debug_log_print
+endif
+	fetch 1,mem_lmp_to_send
+/* lmp message to be processed. this will either be because host??? */
+/* wants to send a lmp message or because one resulted from the LMP */
+/* processing section */
+/********* outgoing lmp lookup table *************/
+	bbit1 7,z_send_lmp_escape
+	beq LMP_SETUP_COMPLETE, z_send_lmp_setup_complete
+	beq LMP_SRES,z_send_lmp_sres
+	beq LMP_DETACH,z_send_lmp_detach
+	beq LMP_AU_RAND,z_send_lmp_aurand
+	branch send_lmp+10
+
+z_send_lmp_aurand:
+	fetch 1,mem_pairing_auth
+	branch z_send_lmp_aurand_notpairing,blank
+	call check_localsm
+	call tid_initiate,true				//master
+	ncall tid_reply,true				//slave
+	branch z_send_lmp_aurand_common
+z_send_lmp_aurand_notpairing:
+	call tid_initiate
+z_send_lmp_aurand_common:
+	call generate_random_number
+	force 17,pdata
+	call msg_send_lmp
+	arg mem_random_number,contr
+	call memcpy16
+	//branch p_send_lmp_tid
+z_send_lmp_tid:
+	fetcht 1,mem_state_map
+	and_into 1,temp	
+z_send_lmp_end:
+	fetch 1,mem_lmp_to_send
+	lshift pdata,pdata
+
+	bmark0 mark_slave_in_rand_accepted,z_send_lmp_end_master
+	nsetflag master,0,pdata
+	branch send_lmp_exit
+z_send_lmp_end_master:
+	setflag master,0,pdata
+	ixor temp,pdata
+	branch send_lmp_exit
+
+
+z_send_lmp_setup_complete:
+	fetch 1,mem_state
+	set1 state_conn_comp,pdata
+	store 1,mem_state
+	copy clkn_bt,pdata
+	store 4,mem_aurand_send_delay_time
+	fetch 1,mem_lmp_conn_state
+	bbit1 SENT_SETUP_COMPLETE,z_send_lmp_setup_complete_has_sent
+	set1 SENT_SETUP_COMPLETE,pdata
+	store 1,mem_lmp_conn_state
+	force 1,pdata
+	call msg_send_lmp
+	call send_lmp_request
+	branch p_hci_send_connection_complete
+
+z_send_lmp_setup_complete_has_sent:
+	jam 0,mem_lmp_to_send
+	rtn
+
+
+z_send_lmp_detach:
+	force 2,pdata
+	call msg_send_lmp
+	fetch 1,mem_disconn_reason_send
+	istore 1,contw
+	call send_lmp_request
+	branch p_prepare_disconnect
+
+org z 
+z_send_lmp_sres:
+	arg mem_lap,rega
+	call function_e1
+	force 5,pdata
+	call msg_send_lmp
+	fetch 4,mem_input_store
+	istore 4,contw
+	arg mem_sres_tid,temp
+	call special_tid_store
+	call copy_aco
+	call check_localsm
+	branch z_send_lmp_sres_master,true
+	jam DONE_ENCRYP,mem_wait_encryption
+	
+	bmark1 mark_slave_in_rand_accepted,z_send_lmp_sres_startenc_slave
+	fetch 1,mem_pairing_auth
+	rtn blank
+	jam LMP_AU_RAND,mem_lmo_opcode2
+z_send_lmp_sres_master:
+	bmark1 mark_slave_in_rand_accepted,z_send_lmp_sres_startenc_slave
+	fetch 1,mem_link_key_exists
+	rtn blank
+z_send_lmp_sres_startenc:
+	call check_localsm
+	nbranch z_send_lmp_sres_startenc_slave,true
+	rtn
+
+z_send_lmp_sres_startenc_slave:
+	rtnmark0 mark_slave_in_rand_accepted
+	set0 mark_slave_in_rand_accepted,mark
+	branch p_send_lmp_sres_startenc_slave_event_send
+
+
+
+
+
+org z
+z_le_parse_ll:
+//	fetch 2,mem_le_payload_ptr
+//	copy pdata,contr
+//	ifetch 1,contr
+	fetch 1,mem_le_rxbuf+2
+	beq LL_FEATURE_REQ,z_le_parse_feature_req
+	beq LL_FEATURE_RSP,z_le_parse_feature_rsp
+	beq LL_VERSION_IND,z_le_parse_version_ind
+	beq LL_CHANNEL_MAP_REQ,z_le_parse_channel_map_req
+	beq LL_CONNECTION_UPDATE_REQ,le_parse_connection_update_req
+	branch z_le_parse_ll_sub
+
+z_le_parse_channel_map_req:
+	ifetch 5,contr
+	store 5,mem_le_new_map
+	ifetch 2,contr
+	store 2,mem_le_instant
+	fetcht 2,mem_le_event_count
+	isub temp,null
+	nbranch le_parse_terminate_ind,positive
+	fetch 1,mem_le_state
+	set1 lestate_update_map,pdata
+	store 1,mem_le_state
+	rtn	
+
+
+z_le_parse_feature_req:
+	call z_le_parse_feature_rsp
+	arg 9,rega
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_FEATURE_RSP
+	istore 1,contw
+	fetch 8,mem_le_features
+	istore 8,contw
+	rtn	
+
+z_le_parse_feature_rsp:
+	ifetch 8,contr
+	store 8,mem_mesh_le_features
+	call p_le_parse_feature_rsp_master
+	//branch z_hci_send_le_read_remote_features_complete
+z_hci_send_le_read_remote_features_complete:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 LE_READ_REMOTE_FEATURES_COMPLETE_EVENT
+	jam 12,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg HCI_LE_SUBEVENT_REMOTE_FEATURE_COMPLETE
+	istore 2,contw		//subevent code & status
+	fetch 1,mem_le_conn_handle
+	istore 2,contw
+	fetch 8,mem_mesh_le_features
+	istore 8,contw
+	branch ipc_hci_tx_start
+
+z_le_parse_version_ind:
+	ifetch 5,contr
+	store 5,mem_mesh_le_version
+	call p_le_parse_version_ind_cmd_master
+	branch z_hci_send_read_remote_version_information_complete,master
+	fetch 1,mem_mesh_le_version_exchange_times
+	nrtn blank
+	pincrease 1
+	store 1,mem_mesh_le_version_exchange_times
+	branch le_send_version_ind
+
+z_hci_send_read_remote_version_information_complete:
+	fetch 8,mem_mesh_le_event_mask
+	rtnbit0 READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT
+	jam 8,mem_mesh_event_para_total_length
+	jam HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg COMMAND_SUCCEEDED
+	istore 1,contw		//subevent code & status
+	fetch 1,mem_le_conn_handle
+	istore 2,contw
+	fetch 5,mem_mesh_le_version
+	istore 5,contw
+	branch ipc_hci_tx_start
+
+
+
+org z
+z_le_parse_ll_sub:
+//	fetch 2,mem_le_payload_ptr
+//	copy pdata,contr
+//	ifetch 1,contr
+	fetch 1,mem_le_rxbuf+2
+	beq LL_LENGTH_REQ,z_le_parse_length_request
+	beq LL_LENGTH_RSP,z_le_parse_length_rsp
+	beq LL_TERMINATE_IND,z_le_parse_terminate_ind
+	branch le_parse_ll+2
+
+
+z_le_parse_terminate_ind:
+	ifetch 1,contr
+	store 1,mem_disconn_reason_send
+	branch le_parse_terminate_ind
+
+//input pdata, temp,return temp
+z_return_small:
+	isub temp,null
+	rtn positive
+	copy pdata,temp
+	rtn
+
+z_le_parse_length_rsp:
+	ifetch 8,contr
+	store 8,mem_remote_rx_max_octets
+
+	fetch 2,mem_remote_rx_max_octets
+	fetcht 2,mem_local_tx_max_octets
+	call z_return_small
+	storet 2,mem_remote_rx_max_octets
+	
+	fetch 2,mem_remote_tx_max_octets
+	fetcht 2,mem_local_rx_max_octets
+	call z_return_small
+	storet 2,mem_remote_tx_max_octets
+	//branch z_hci_send_event_le_connection_data_length_change
+z_hci_send_event_le_connection_data_length_change:
+	//fetch 8,mem_mesh_le_event_mask
+	//rtnbit0 LE_CONNECTION_UPDATE_COMPLETE_EVENT
+	jam 11,mem_mesh_event_para_total_length
+	jam HCI_EVENT_LE_META_EVENT,mem_mesh_event_head_event_code
+	call p_hci_prepare_send_event
+	setarg HCI_LE_SUBEVENT_DATA_LENGTH_CHANGE_EVENT
+	istore 1,contw		//subevent code
+	fetch 1,mem_le_conn_handle
+	istore 2,contw
+	fetch 8,mem_remote_rx_max_octets
+	istore 8,contw
+	branch ipc_hci_tx_start
+	
+z_le_parse_length_request:
+	call z_le_parse_length_rsp
+	//branch p_le_send_data_length_res
+//p_le_send_data_length_res:
+//	arg LL_LENGTH_RSP,regb
+z_le_send_data_length:
+	arg 9,rega
+//	call le_fifo_malloc_tx_ll
+	arg LLID_LE_LL,type
+	call le_fifo_malloc_tx
+	setarg LL_LENGTH_RSP
+	istore 1,contw
+	fetch 8,mem_local_rx_max_octets
+	istore 8,contw
+	rtn
+
+p_le_send_data_length_req:
+	arg LL_LENGTH_REQ,regb
+	branch z_le_send_data_length
+
+
Index: ModuleDemo/BLE/BT/sched/coef.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/coef.dat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/coef.dat	(working copy)
@@ -0,0 +1,66 @@
+
+
+
+#mem_coef_dac_table: 
+#48k
+	5d 02 00 73 07 00 92 0f 00 44 18 00 be 1c 00 bb 17 00 f3 06 00 56 ee ff
+      81 d8 ff cb d2 ff cb e5 ff 0c 0e 00 0b 3a 00 af 50 00 bc 3e 00 96 04 00
+	42 bb ff dc 8a ff 50 96 ff c4 e1 ff 0a 4c 00 0f 9a 00 31 97 00 b8 37 00
+	de a7 ff d5 39 ff f3 37 ff a8 b3 ff 84 70 00 43 fe 00 49 f9 00 23 4e 00
+	21 54 ff 0d a6 fe 1a c7 fe e8 c6 ff 75 21 01 72 fb 01 5c a4 01 80 15 00
+	56 19 fe 1d f0 fc f4 93 fd 2b 04 00 e3 0e 03 bc d5 04 60 de 03 57 1d 00
+	c7 50 fb b2 4d f8 23 77 f9 df 24 ff a6 ef 06 f9 7e 0c 2b af 0b 3b 18 03
+	83 9b f5 6f ee e9 28 06 e8 e4 63 f5 01 f8 11 ba 37 37 8d 12 5a 60 19 6f
+
+#44.1k
+	90 fb ff 94 f3 ff 94 e7 ff 58 db ff 53 d5 ff 60 dc ff ae f3 ff ff 16 00
+	be 39 00 d1 4a 00 9f 3c 00 03 0e 00 08 cf ff 3a 9d ff fa 96 ff a8 ca ff
+	31 2a 00 9a 8b 00 97 b9 00 d0 8e 00 b1 0e 00 f2 6c ff 71 fb fe e9 02 ff
+	43 98 ff 01 86 00 e8 5a 01 2c 9d 01 99 0c 01 5b d1 ff 57 79 fe 47 bc fd
+	83 1d fe e5 99 ff c6 91 01 d8 05 03 7e 13 03 8f 76 01 a7 c9 fe 97 56 fc
+	a1 7e fb af fc fc 61 63 00 96 27 04 86 48 06 89 53 05 c4 45 01 88 cc fb
+	a7 a7 f7 93 5d f7 d4 d4 fb 4b 8b 03 6f ee 0a a0 d7 0d 3c 9c 09 2b c2 fe
+	c6 74 f1 58 51 e8 56 de e9 a6 a8 f9 e6 45 16 ae 31 39 52 be 58 2c 6f 6b
+
+# 32k#24k#16k#12k#8k
+	1e 00 00 80 fe ff f8 fa ff 9c f4 ff f0 eb ff 18 e3 ff d0 dd ff 64 e0 ff
+	c7 ed ff 69 05 00 d4 21 00 2c 39 00 10 40 00 65 2e 00 45 04 00 c5 cc ff
+	66 9c ff 8b 8a ff 9a a7 ff 6f f3 ff d4 58 00 85 b1 00 26 d3 00 7d a1 00
+	b4 1e 00 a9 71 ff f6 dc fe 41 a7 fe 73 fc fe 36 d4 ff a7 ea 00 43 d2 01
+	3a 1c 02 72 89 01 dc 2f 00 1f 81 fe c0 29 fd 04 d0 fc 93 c9 fd f0 18 00
+	cc 70 02 b1 5e 04 3f bd 04 57 1b 03 99 d2 ff 9c 04 fc 6f 41 f9 f2 eb f8
+	1e a8 fb 4c d4 00 db af 06 49 d1 0a b9 0b 0b 1b 62 06 c7 ad fd 4e ac f3
+	43 59 ec 49 b9 eb 06 75 f4 c1 bd 06 23 e6 1f 43 e2 3a 1c 95 51 0b 89 5e
+
+#mem_coef_voice_table:
+	0c 00 12 00 1b 00 24 00 29 00 28 00 1d 00 07 00 
+	e4 ff b9 ff 8a ff 5f ff 42 ff 3c ff 53 ff 8c ff 
+	e4 ff 50 00 c2 00 25 01 63 01 68 01 27 01 9d 00 
+	d5 ff e7 fe f7 fd 33 fd cb fc ea fc af fd 27 ff 
+	49 01 f3 03 ee 06 f6 09 bd 0c f9 0e 6b 10 eb 10 00 00	
+
+#mem_coef_adc_table:
+	06 00 00 b4 ff ff a1 fe ff 59 fd ff 62 fe ff a4 04 00 ad 0e 00 cf 12 00
+	60 03 00 3f dd ff 9a b6 ff a8 bc ff 47 18 00 7a c8 00 04 92 01 1f 19 02
+	2c 00 00 aa 00 00 45 00 00 2e 00 00 cd ff ff 6d ff ff 2e ff ff 3e ff ff
+	ac ff ff 62 00 00 20 01 00 8f 01 00 6a 01 00 99 00 00 51 ff ff 08 fe ff
+	4f fd ff 99 fd ff ff fe ff 20 01 00 36 03 00 57 04 00 d5 03 00 97 01 00
+	3e fe ff 06 fb ff 53 f9 ff 26 fa ff 97 fd ff a4 02 00 71 07 00 ec 09 00
+	a7 08 00 8d 03 00 23 fc ff 23 f5 ff 8e f1 ff 6e f3 ff d9 fa ff 96 05 00
+	b4 0f 00 e3 14 00 32 12 00 7a 07 00 e3 f7 ff 18 e9 ff 60 e1 ff 27 e5 ff
+	df f4 ff 2d 0c 00 cf 22 00 3a 2f 00 28 2a 00 de 11 00 f2 eb ff b5 c4 ff
+	1d ac ff 03 b1 ff 18 dc ff 3a 2c 00 8b 95 00 bc 03 01 15 5f 01 ce 92 01
+	06 ff ff 0d fe ff eb 01 00 e0 01 00 83 fd ff e9 fc ff cb 03 00 7a 04 00
+	99 fa ff b0 f9 ff 7d 07 00 a7 08 00 de f5 ff 62 f4 ff 7b 0d 00 5f 0f 00
+	46 ee ff d6 eb ff 2e 17 00 63 1a 00 a4 e1 ff 44 dd ff 37 28 00 8f 2e 00
+	45 c9 ff 1e bf ff ca 4e 00 28 62 00 83 7f ff 0e 4a ff f6 31 01 5f 99 03
+
+#mem_coef_eq_table:
+	00 00 10 c8 00 20 3e 2e c0 1e d1 1f c4 d1 3f 1b 2e e0 13 05 20 48 41 c0
+	33 ba 1f b8 be 3f ba 40 e0 b6 da 1f 99 b5 c0 dc 71 1f 67 4a 3f 6e b3 e0
+	f7 dc 1f 07 3e c1 9d ed 1e f9 c1 3e 6c 35 e1 2f f7 1f 41 43 c2 7a e7 1d
+	bf bc 3d 57 21 e2 66 5e 20 1d 40 c4 79 e5 1b e3 bf 3b 20 bc e3 3f 7e 21
+	d7 71 c8 9f 05 18 29 8e 37 22 7c e6 50 01 22 0d 5b d3 b4 8b 11 f3 a4 2c
+	fd 72 ec 4c 3e 20 42 f2 eb 2f dd 07 be 0d 14 85 e4 f7 0f 60 23 67 35 13
+	39 ee 07 b3 c0 e9 9e bb f7
+	
\ No newline at end of file
Index: ModuleDemo/BLE/BT/sched/efuse.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/efuse.dat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/efuse.dat	(working copy)
@@ -0,0 +1,64 @@
+60
+02
+55
+18
+70
+80
+9a
+3f
+6f
+e2
+83
+3d
+c3
+02
+80
+06
+20
+00
+27
+10
+20
+40
+54
+00
+20
+20
+20
+02
+55
+01
+00
+40
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+90
+95
+96
+91
+92
+94
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
\ No newline at end of file
Index: ModuleDemo/BLE/BT/sched/patch.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/patch.dat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/patch.dat	(working copy)
@@ -0,0 +1,67 @@
+
+mem_patch00:     
+04   #mem_patch00
+40   #mem_patch01
+01   #mem_patch02
+50   #mem_patch03
+11   #mem_patch04
+00   #mem_patch05
+04   #mem_patch06
+46   #mem_patch07
+12   #mem_patch08
+00   #mem_patch09
+10   #mem_patch0A
+31   #mem_patch0B
+00   #mem_patch0C
+1c   #mem_patch0D
+00   #mem_patch0E
+00   #mem_patch0F
+62   #mem_patch10
+00   #mem_patch11
+00   #mem_patch12
+40   #mem_patch13
+11   #mem_patch14
+01   #mem_patch15
+00   #mem_patch16
+06   #mem_patch17
+00   #mem_patch18
+00   #mem_patch19
+00   #mem_patch1A
+00   #mem_patch1B
+01   #mem_patch1C
+00   #mem_patch1D  
+00   #mem_patch1E
+00   #mem_patch1F
+80   #mem_patch20
+10   #mem_patch21
+1c   #mem_patch22
+00   #mem_patch23
+e8   #mem_patch24
+07   #mem_patch25
+00   #mem_patch26
+c8   #mem_patch27
+06   #mem_patch28
+89   #mem_patch29
+04   #mem_patch2A
+29   #mem_patch2B
+11   #mem_patch2C
+40   #mem_patch2D
+13    #mem_patch2E
+00   #mem_patch2F
+00   #mem_patch30
+00   #mem_patch31
+04   #mem_patch32
+00   #mem_patch33
+60   #mem_patch34
+00   #mem_patch35
+04   #mem_patch36
+00   #mem_patch37
+00   #mem_patch38
+00   #mem_patch39
+10   #mem_patch3A
+00   #mem_patch3B
+00   #mem_patch3C
+00   #mem_patch3D
+00   #mem_patch3E
+00   #mem_patch3F
+
Index: ModuleDemo/BLE/BT/sched/rf.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/rf.dat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/rf.dat	(working copy)
@@ -0,0 +1,34 @@
+mem_lpm_config:8f 10 ca
+mem_lpm_buckcnt:0a 0b ef 07
+mem_lpm_hibernate_switch:00
+mem_gpio_wakeup_low:00 00 00 00 00 00 00 00
+mem_fcomp_mul:02
+mem_fcomp_div:24
+mem_iscan_window:20 00
+mem_iscan_interval:00 04
+mem_pscan_window:16 00
+mem_pscan_interval:00 04
+mem_inq_window:20 00
+mem_page_window:30 00
+mem_page_to:00 30
+mem_rx_window_init:80 03
+mem_rx_window_sniff:00 06
+
+#if you find lpo_time not near 0x2a, you must think the pre timer maybe error.
+#DVDD 0.1uF, VFB 1uF    Time:   DVDD up time: 4us, VFB up time: 255us
+#DVDD 0.1uF, VFB 10uF    Time:   DVDD up time: 4us, VFB up time: 305us 
+#clock unit is internal 32K, 1 step is near 32us
+#so we set:
+#1: digldo pre-on counter(DVDD):  0x02
+#2: exen pre-on counter(VFB):  0x14
+#3: xtal pre-on counter(XTAL) set to zero becouse it will set in lpm_cal_xtal_startup
+mem_lpm_xtalcnt:00 20 18 bf 07
+
+mem_ef_base:00 ff 87
+mem_eeprom_block_size:80
+
+mem_rf_init:
+ff
+
+mem_rf_init_ptr:mem_rf_init
+
Index: ModuleDemo/BLE/BT/sched/user.dat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/user.dat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/sched/user.dat	(working copy)
@@ -0,0 +1,324 @@
+
+##############NVRAM CONFIG##############
+mem_nv_data_ptr:mem_nv_data
+mem_nv_data_number:05
+#####################################
+
+##############BLUETOOTH CONFIG##############
+###commom###
+mem_device_option:0f
+mem_lmp_version:09 0e 05 06 00
+###ble###
+mem_le_lap:d5 cc aa aa cc 52
+
+mem_le_adv_data_len:12
+mem_le_adv_data:
+02 01 0e 
+04 09 4f 54 41
+09 ff 0e 05 21 11
+
+mem_le_scan_data_len:05
+mem_le_scan_data:
+'\09OTA
+
+
+mem_le_adv_enable:00
+mem_le_scan_type:01
+mem_le_adv_type:00
+mem_le_adv_direct_addr_type:00
+mem_le_scan_own_addr_type:00
+mem_le_scan_filter_policy:00
+mem_le_scan_interval:28
+mem_le_scan_window:0c 00
+mem_le_transmit_window:50
+mem_le_adv_interval_max:60 01 
+mem_le_adv_own_addr_type:00
+
+mem_le_pairing_mode:00
+mem_le_secure_connect_enable:00
+mem_le_pres:02 03 00 01 10 02 03 #justwork
+
+mem_le_pairing_handle:00 00
+
+mem_le_interal_min:
+10 00 #interval max
+10 00 #interval min
+00 00 #latency
+00 01 #supervision timeout
+
+###3.0###
+mem_sp_iocap_local:03 00 00
+mem_role_switch_flag:00
+mem_scan_mode:00
+mem_class: 04 04 24
+mem_local_name_length:
+'EVKOTA
+
+#FF FF FF is Fixed for OTA.
+mem_lap:45 FF 31 FF FF FF
+
+mem_discovery_timeout:00 07 
+mem_ssp_enable:01
+mem_ui_profile_supported:48
+mem_app_connection_options:17
+mem_eir_enable:01
+mem_all_uuid_16bits:
+05
+03#Type: Complete list of 16-bit UUIDs
+1e11 0e11 0811 0d11 0b11
+
+mem_all_uuid_128bits:00
+
+mem_ota_version:0a 00
+mem_ota_write_handle:06
+mem_ota_notify_handle:03
+mem_ota_buck_size:00 10
+mem_ota_packet_max_len:be 00
+
+#attribute list: handle 2bytes, uuid 2bytes, length 1bytes, attribute Nbytes
+mem_le_att_list:
+
+#Primary service yichip transmit ------
+01 00 02 00 28 02 ff ff
+#Characteristic tx--notify
+02 00 02 03 28 01 10
+03 00 02 11 ff 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#Client Characteristic Configuration
+04 00 02 02 29 02 01 00
+
+#Characteristic rx--write
+05 00 02 03 28 01 04
+06 00 02 22 ff  14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+#End of Attribute list
+00 00
+
+
+
+mem_lpm_mode:00
+mem_lpm_overhead:08
+mem_lpm_interval:00 02
+mem_lpm_mult:03
+mem_lpm_mult_timeout:03
+mem_ptt:01
+mem_features:
+ff
+ff
+ff
+fa	#fe--EDR  F8--BR
+db	#AFHclose 83  #AFHenable_slave cap and classification LMP_SLAVE_AFH_CLASSIFICATION enable 9b, disable 8b
+fd    #9d
+7b
+83
+
+mem_le_features:
+21				//length extension
+00
+00
+00
+00
+00
+00
+00
+
+
+mem_xip_option:5d 40 bb
+
+mem_ui_le_uuid_table:mem_le_att_list
+
+mem_seqi:7f
+
+mem_le_connection_updata_param:
+06 00
+06 00
+00 00
+f4 01
+
+
+mem_codec_msbc_support:00
+mem_codec_type:01
+mem_eq_flag:01
+
+mem_UI_HF_brsf_feature:313538 #30 33 30 
+mem_le_more_data:01
+mem_ipc_enable:01
+
+mem_tws_state:00
+mem_tws_bdaddr:96 55 12 11 33 62
+#mem_tws_bdaddr:96 45 12 00 19 62
+
+
+mem_hsp_role:00
+mem_auto_hsp_role:01
+mem_tws_allow_pairing:01
+mem_tws_allow_pairing_rssi_limit:45
+
+mem_tws_rf_start_anchor:b0 04   # 0x1e0 40us,   0x78 10us,   0x4b0 100us,   0x618 130us
+mem_tws_rf_rcv_window_size:78 00
+
+mem_tws_rf_packet_rx_window_size:f0 0a # 2800
+mem_tws_rf_slave_send_full_packet_sleep_time:58 02 # 50us
+# mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us)
+# send delay is mem_tws_rf_slave_send_full_packet_sleep_time, so we can think the judge below
+# mem_tws_rf_packet_rx_window_size - (mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us) + mem_tws_rf_slave_send_full_packet_sleep_time/2)
+mem_tws_rf_master_check_raw_id_time:db 04
+
+mem_rf_debug_enable: 00
+mem_rf_debug_rf_rx_debug_gpio: 0c
+mem_rf_debug_rf_tx_debug_gpio: 0e
+mem_rf_debug_rf_sync_detect_debug_gpio: 13
+mem_rf_debug_rf_crc_error_debug_gpio: 19
+
+
+mem_param_sco_use_cm0:01
+
+
+# ipc define
+#mem_param_ipc_mem_block_start_addr
+mem_param_ipc_to_bt_buf_start_addr:00 d8 01
+mem_param_ipc_to_bt_buf_end_addr:00 db 01
+mem_param_ipc_to_bt_wptr_addr:00 db 01
+mem_param_ipc_to_bt_rptr_addr:04 db 01
+mem_param_ipc_to_m0_wptr_addr:08 db 01
+mem_param_ipc_to_m0_rptr_addr:0c db 01
+mem_param_ipc_to_m0_buf_start_addr:50 db 01
+mem_param_ipc_to_m0_buf_end_addr:00 dd 01
+#mem_param_ipc_mem_block_end_addr
+
+
+# debug log define
+#mem_param_debug_log_mem_block_start_addr
+mem_param_debug_log_func_enable:00
+
+mem_param_debug_log_initial_flag_addr:10 db 01
+mem_param_debug_log_lock_flag_cm0_addr:11 db 01
+mem_param_debug_log_lock_flag_respin_addr:12 db 01
+mem_param_debug_log_lock_victim_addr:13 db 01
+mem_param_debug_log_read_index_addr:14 db 01
+mem_param_debug_log_write_index_addr:16 db 01
+mem_param_debug_log_buffer_start_addr:18 db 01
+mem_param_debug_log_buffer_end_addr:50 db 01
+#mem_param_debug_log_mem_block_end_addr
+
+# soft dma define
+# size is SOFT_DMA_TABLE_TOTAL_COUNT*4 + SOFT_DMA_TABLE_TOTAL_COUNT*SOFT_DMA_TABLE_UNIT_SIZE = 0x100
+mem_param_soft_dma_enable:01
+mem_param_soft_dma_table_start_addr:10 d5 01
+
+
+# sco m0 rx buffer define
+# size is M0_SCO_RX_BUFFER_SIZE + M0_SCO_TX_BUFFER_SIZE
+mem_param_m0_respin_sco_buffer_start_addr:10 d6 01
+
+
+mem_param_use_cm0_control_flag:01
+# tishi buffer size is 0x2000
+mem_param_tishi_start_addr:00 a0
+
+#mem_app_debug_info_timer use to set first debug timeout
+#mem_param_app_debug_info_timeout use to set period
+mem_app_debug_info_timer:05
+mem_param_app_debug_info_timeout:32
+
+mem_param_tws_tx_power:02
+
+mem_param_tws_send_channel_array:08 24 08 24
+#mem_param_tws_send_channel_array:20 20 20 20
+#mem_param_tws_send_channel_array:08 09 10 11
+
+mem_tx_power:02
+
+mem_sfreq_enable:01
+#mem_param_rf_setup must big then mem_param_pll_setup, be-careful, mem_param_rf_setup real value = 0xEA6 - value
+#we suggest must reserve 0x3A6, means mem_param_rf_setup = (0xEA6 - mem_param_pll_setup - 0x3A6)
+#mem_param_rf_setup:B8 07
+#mem_param_pll_setup:48 03
+mem_param_rf_setup:00 06
+mem_param_pll_setup:00 05
+
+mem_audio_output_setting: 01
+
+
+mem_mram_qspi_tx_addr:00 60
+
+mem_vp_addr:
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+
+mem_fec_required:00		
+mem_eir:
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 00 00 00 00
+mem_simple_pairing_mode:00	
+mem_conn_status:00
+mem_io_cap_flag:00
+mem_inquiry_mode:00
+
+
+mem_param_alloc_normal_buffer_start_address:00 18
+mem_param_alloc_normal_buffer_max_length:83 00
+mem_param_alloc_big_buffer_start_address:00 20
+mem_param_alloc_big_buffer_max_length:b0 02
+mem_l2cap_rx_max_lenth:b0 02
+
+
+mem_alloc_normal_total_size:0a
+mem_alloc_big_total_size:0a
+mem_snd_br_total_size:0a
+mem_snd_ble_total_size:0a
+mem_snd_hci_total_size:0a
+
+mem_hci_version_svnid:4486
+
+mem_keyscan_switch:00
+
+mem_public_code_svn_version_code:00 00 00 00 00 00 00 00 00
+
+mem_le_tws_scan_interval:28 00
+mem_le_tws_scan_window:0c 00
+mem_param_le_tws_adv_interval_normal:00 01 
+mem_param_le_tws_adv_interval_master_listen:58 00 
+
+
+#mesh init
+mem_mesh_event_head_type:04	#HCI_H4_TYPE_EVENT
+
+mem_mesh_command_complete_num_hci_command_packet:01
+
+mem_mesh_read_local_version_info:
+09		#hci_version BT_HCI_VERSION_5_0
+00 00	#hci_revsion
+09		#lmp_version RADIO_BLE_VERSION_NUMBER:BT_HCI_VERSION_5_0
+0e 05	#manufacture_name Yichip Microelectronics (Hangzhou) Co.,Ltd.
+FF FF	#LPM_subversion
+
+mem_mesh_read_local_support_command:02 05 ff
+
+mem_device_public_address:11 22 33 44 55 66
+
+mem_local_rx_max_octets:fb 00 48 08 fb 00 48 08  
+
+
Index: ModuleDemo/BLE/BT/special_voice_mute.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/special_voice_mute.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/BT/special_voice_mute.bat	(working copy)
@@ -0,0 +1,48 @@
+e 1b800 0000
+e 1b802 0000
+e 1b804 0000
+e 1b806 0000
+e 1b808 0000
+e 1b80a 0000
+e 1b80c 0000
+e 1b80e 0000
+e 1b810 0000
+e 1b812 0000
+e 1b814 0000
+e 1b816 0000
+e 1b818 0000
+e 1b81a 0000
+e 1b81c 0000
+e 1b81e 0000
+e 1b820 0000
+e 1b822 0000
+e 1b824 0000
+e 1b826 0000
+e 1b828 0000
+e 1b82a 0000
+e 1b82c 0000
+e 1b82e 0000
+e 1b830 0000
+e 1b832 0000
+e 1b834 0000
+e 1b836 0000
+e 1b838 0000
+e 1b83a 0000
+e 1b83c 0000
+e 1b83e 0000
+e 1b840 0000
+e 1b842 0000
+e 1b844 0000
+e 1b846 0000
+e 1b848 0000
+e 1b84a 0000
+e 1b84c 0000
+e 1b84e 0000
+e 1b850 0000
+e 1b852 0000
+e 1b854 0000
+e 1b856 0000
+e 1b858 0000
+e 1b85a 0000
+e 1b85c 0000
+e 1b85e 0000
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_Powering_On.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_Powering_On.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_battery_is_near_empty.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_battery_is_near_empty.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_battery_is_near_empty48_48k.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_battery_is_near_empty48_48k.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_disconnect.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_disconnect.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_max_vol.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_max_vol.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_max_vol_48k.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_max_vol_48k.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_paired.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_paired.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_powering_off.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_powering_off.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/British_Eng_tws_connected.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/British_Eng_tws_connected.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/eight.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/eight.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/five.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/five.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/four.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/four.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/nine.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/nine.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/one.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/one.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/ring.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/ring.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/seven.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/seven.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/six.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/six.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/three.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/three.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/two.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/two.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/BT/voice_prompt/zero.pcm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: ModuleDemo/BLE/BT/voice_prompt/zero.pcm
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: ModuleDemo/BLE/CM0/Prj/MDK/Listings/startup.lst
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Listings/startup.lst	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Listings/startup.lst	(working copy)
@@ -0,0 +1,766 @@
+
+
+
+ARM Macro Assembler    Page 1 
+
+
+    1 00000000         
+    2 00000000 0000B640 
+                       Stack_Size
+                               EQU              0x00B640
+    3 00000000         
+    4 00000000                 AREA             STACK, NOINIT, READWRITE, ALIGN
+=4
+    5 00000000         Stack_Mem
+                               SPACE            Stack_Size
+    6 0000B640 1001B640 
+                       __initial_sp
+                               EQU              0x1001B640
+    7 0000B640         
+    8 0000B640         
+    9 0000B640         ; <h> Heap Configuration
+   10 0000B640         ;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+   11 0000B640         ; </h>
+   12 0000B640         
+   13 0000B640 00001000 
+                       Heap_Size
+                               EQU              0x00001000
+   14 0000B640                 AREA             HEAP, NOINIT, READWRITE, ALIGN=
+4
+   15 00000000         __heap_base
+   16 00000000         Heap_Mem
+                               SPACE            Heap_Size
+   17 00001000         __heap_limit
+   18 00001000         
+   19 00001000         
+   20 00001000                 PRESERVE8
+   21 00001000                 THUMB
+   22 00001000         ; Vector Table Mapped to Address 0 at Reset
+   23 00001000         
+   24 00001000                 AREA             RESET, DATA, READONLY
+   25 00000000                 EXPORT           __Vectors
+   26 00000000                 EXPORT           __Vectors_End
+   27 00000000                 EXPORT           __Vectors_Size
+   28 00000000 1001B640 
+                       __Vectors
+                               DCD              __initial_sp ; Top of Stack
+   29 00000004 00000000        DCD              Reset_Handler ; Reset Handler
+   30 00000008 00000000        DCD              NMI_Handler
+   31 0000000C 00000000        DCD              HardFault_Handler ; Hard Fault 
+                                                            Handler     
+   32 00000010 00000000        DCD              0           ; 
+   33 00000014 00000000        DCD              0           ;
+   34 00000018 00000000        DCD              0           ;
+   35 0000001C 00000000        DCD              0           ;
+   36 00000020 00000000        DCD              0           ;
+   37 00000024 00000000        DCD              0           ;
+   38 00000028 00000000        DCD              0           ;
+   39 0000002C 00000000        DCD              SVC_Handler ;
+   40 00000030 00000000        DCD              0           ;
+   41 00000034 00000000        DCD              0           ;
+   42 00000038 00000000        DCD              PendSV_Handler ;
+   43 0000003C 00000000        DCD              SysTick_Handler ; 
+   44 00000040         
+   45 00000040 00000000        DCD              USB_IRQHandler ;
+   46 00000044 00000000        DCD              IIC_IRQHandler ;
+
+
+
+ARM Macro Assembler    Page 2 
+
+
+   47 00000048 00000000        DCD              QSPI_IRQHandler ;
+   48 0000004C 00000000        DCD              SPI_IRQHandler ;
+   49 00000050 00000000        DCD              UART_IRQHandler ;
+   50 00000054 00000000        DCD              UARTB_IRQHandler ;
+   51 00000058 00000000        DCD              ADC_IRQHandler ;
+   52 0000005C 00000000        DCD              IIS_IRQHandler ;
+   53 00000060 00000000        DCD              BT_IRQHandler ;
+   54 00000064 00000000        DCD              GPIO_IRQHandler ;
+   55 00000068 00000000        DCD              OTP_IRQHandler ;
+   56 0000006C 00000000        DCD              SBC_ERR0_IRQHandler ;
+   57 00000070 00000000        DCD              SBC_ERR1_IRQHandler ;
+   58 00000074 00000000        DCD              FFT_IRQHandler ;
+   59 00000078 00000000        DCD              DMA_IRQHandler ;
+   60 0000007C 00000000        DCD              SD_IRQHandler ;
+   61 00000080 00000000        DCD              TIMER0_IRQHandler ;
+   62 00000084 00000000        DCD              TIMER1_IRQHandler ;
+   63 00000088 00000000        DCD              TIMER2_IRQHandler ;
+   64 0000008C 00000000        DCD              TIMER3_IRQHandler ;
+   65 00000090 00000000        DCD              TIMER4_IRQHandler ;
+   66 00000094 00000000        DCD              TIMER5_IRQHandler ;
+   67 00000098 00000000        DCD              TIMER6_IRQHandler ;
+   68 0000009C 00000000        DCD              TIMER7_IRQHandler ;
+   69 000000A0 00000000        DCD              WDT2_IRQHandler ;
+   70 000000A4 00000000        DCD              WDT_IRQHandler ;
+   71 000000A8 00000000        DCD              0           ;
+   72 000000AC 00000000        DCD              0           ;
+   73 000000B0 00000000        DCD              0           ;
+   74 000000B4 00000000        DCD              0           ;
+   75 000000B8 00000000        DCD              0           ;
+   76 000000BC 00000000        DCD              0           ;
+   77 000000C0         
+   78 000000C0         __Vectors_End
+   79 000000C0         
+   80 000000C0 000000C0 
+                       __Vectors_Size
+                               EQU              __Vectors_End - __Vectors
+   81 000000C0         
+   82 000000C0                 AREA             |.text|, CODE, READONLY ,ALIGN=
+4
+   83 00000000         
+   84 00000000         
+   85 00000000         
+   86 00000000         ; Reset Handler
+   87 00000000         
+   88 00000000         Reset_Handler
+                               PROC
+   89 00000000                 EXPORT           Reset_Handler             [WEAK
+]
+   90 00000000                 IMPORT           __main
+   91 00000000 4806            LDR              R0,= LOADRAMFLAG
+   92 00000002 6800            LDR              R0,[R0]
+   93 00000004 7800            LDRB             R0,[R0]
+   94 00000006 2801            CMP              R0,#1
+   95 00000008 D0FE            BEQ              RUN_TO_MAIN
+   96 0000000A 4805            LDR              R0, =__main
+   97 0000000C 4700            BX               R0
+   98 0000000E                 ENDP
+   99 0000000E         
+  100 0000000E         RUN_TO_MAIN
+
+
+
+ARM Macro Assembler    Page 3 
+
+
+                               PROC
+  101 0000000E                 IMPORT           main
+  102 0000000E 4805            LDR              R0, = main
+  103 00000010 4700            BX               R0
+  104 00000012                 ENDP
+  105 00000012         
+  106 00000012 00 00           align            4
+  107 00000014         ; mem_wake_flag
+  108 00000014 10004429 
+                       LOADRAMFLAG
+                               DCD              0x10004429
+  109 00000018         Default_Handler
+                               PROC
+  110 00000018         ; ToDo:  Add here the export definition for the device s
+                       pecific external interrupts handler
+  111 00000018                 EXPORT           HardFault_Handler   [WEAK]
+  112 00000018                 EXPORT           NMI_Handler      [WEAK]
+  113 00000018                 EXPORT           SVC_Handler      [WEAK]
+  114 00000018                 EXPORT           PendSV_Handler  [WEAK]
+  115 00000018                 EXPORT           SysTick_Handler  [WEAK]
+  116 00000018                 EXPORT           USB_IRQHandler      [WEAK]
+  117 00000018                 EXPORT           IIC_IRQHandler      [WEAK]
+  118 00000018                 EXPORT           QSPI_IRQHandler     [WEAK]
+  119 00000018                 EXPORT           SPI_IRQHandler      [WEAK]
+  120 00000018                 EXPORT           UART_IRQHandler     [WEAK]
+  121 00000018                 EXPORT           UARTB_IRQHandler    [WEAK]
+  122 00000018                 EXPORT           ADC_IRQHandler      [WEAK]
+  123 00000018                 EXPORT           IIS_IRQHandler      [WEAK]
+  124 00000018                 EXPORT           BT_IRQHandler       [WEAK]
+  125 00000018                 EXPORT           GPIO_IRQHandler  [WEAK]
+  126 00000018                 EXPORT           OTP_IRQHandler  [WEAK]
+  127 00000018                 EXPORT           SBC_ERR0_IRQHandler [WEAK]
+  128 00000018                 EXPORT           SBC_ERR1_IRQHandler [WEAK]
+  129 00000018                 EXPORT           FFT_IRQHandler  [WEAK]
+  130 00000018                 EXPORT           DMA_IRQHandler  [WEAK]
+  131 00000018                 EXPORT           SD_IRQHandler  [WEAK]
+  132 00000018                 EXPORT           TIMER0_IRQHandler [WEAK]
+  133 00000018                 EXPORT           TIMER1_IRQHandler [WEAK]
+  134 00000018                 EXPORT           TIMER2_IRQHandler [WEAK]
+  135 00000018                 EXPORT           TIMER3_IRQHandler [WEAK]
+  136 00000018                 EXPORT           TIMER4_IRQHandler [WEAK]
+  137 00000018                 EXPORT           TIMER5_IRQHandler [WEAK]
+  138 00000018                 EXPORT           TIMER6_IRQHandler [WEAK]
+  139 00000018                 EXPORT           TIMER7_IRQHandler [WEAK]
+  140 00000018         
+  141 00000018                 EXPORT           WDT2_IRQHandler  [WEAK]
+  142 00000018                 EXPORT           WDT_IRQHandler  [WEAK]
+  143 00000018         
+  144 00000018         ; ToDo:  Add here the names for the device specific exte
+                       rnal interrupts handler
+  145 00000018         HardFault_Handler
+  146 00000018         NMI_Handler
+  147 00000018         SVC_Handler
+  148 00000018         PendSV_Handler
+  149 00000018         SysTick_Handler
+  150 00000018         USB_IRQHandler
+  151 00000018         IIC_IRQHandler
+  152 00000018         QSPI_IRQHandler
+  153 00000018         SPI_IRQHandler
+
+
+
+ARM Macro Assembler    Page 4 
+
+
+  154 00000018         UART_IRQHandler
+  155 00000018         UARTB_IRQHandler
+  156 00000018         ADC_IRQHandler
+  157 00000018         IIS_IRQHandler
+  158 00000018         BT_IRQHandler
+  159 00000018         GPIO_IRQHandler
+  160 00000018         OTP_IRQHandler
+  161 00000018         SBC_ERR0_IRQHandler
+  162 00000018         SBC_ERR1_IRQHandler
+  163 00000018         FFT_IRQHandler
+  164 00000018         DMA_IRQHandler
+  165 00000018         SD_IRQHandler
+  166 00000018         TIMER0_IRQHandler
+  167 00000018         TIMER1_IRQHandler
+  168 00000018         TIMER2_IRQHandler
+  169 00000018         TIMER3_IRQHandler
+  170 00000018         TIMER4_IRQHandler
+  171 00000018         TIMER5_IRQHandler
+  172 00000018         TIMER6_IRQHandler
+  173 00000018         TIMER7_IRQHandler
+  174 00000018         
+  175 00000018         WDT2_IRQHandler
+  176 00000018         WDT_IRQHandler
+  177 00000018 E7FE            B                .
+  178 0000001A                 ENDP
+  179 0000001A         
+  180 0000001A 00 00           ALIGN
+  181 0000001C         
+  182 0000001C         
+  183 0000001C         ; User Initial Stack & Heap
+  184 0000001C         
+  185 0000001C                 IF               :DEF:__MICROLIB
+  186 0000001C                 EXPORT           __initial_sp
+  187 0000001C                 EXPORT           __heap_base
+  188 0000001C                 EXPORT           __heap_limit
+  189 0000001C         
+  190 0000001C                 ELSE
+  205                          ENDIF
+  206 0000001C         
+  207 0000001C                 END
+              00000000 
+              00000000 
+              00000000 
+Command Line: --debug --xref --diag_suppress=9931 --cpu=Cortex-M0 --apcs=interw
+ork --depend=.\objects\startup.d -o.\objects\startup.o -I.\RTE\_Target_1 -IC:\K
+eil_v5\ARM\PACK\Keil\V2M-MPS2_CMx_BSP\1.7.1\Device\CMSDK_CM0\Include -IC:\Keil_
+v5\ARM\CMSIS\Include --predefine="__MICROLIB SETA 1" --predefine="__UVISION_VER
+SION SETA 526" --predefine="CMSDK_CM0 SETA 1" --list=.\listings\startup.lst Obj
+ects\startup\startup.s
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+Relocatable symbols
+
+STACK 00000000
+
+Symbol: STACK
+   Definitions
+      At line 4 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: STACK unused
+Stack_Mem 00000000
+
+Symbol: Stack_Mem
+   Definitions
+      At line 5 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: Stack_Mem unused
+2 symbols
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+Relocatable symbols
+
+HEAP 00000000
+
+Symbol: HEAP
+   Definitions
+      At line 14 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: HEAP unused
+Heap_Mem 00000000
+
+Symbol: Heap_Mem
+   Definitions
+      At line 16 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: Heap_Mem unused
+__heap_base 00000000
+
+Symbol: __heap_base
+   Definitions
+      At line 15 in file Objects\startup\startup.s
+   Uses
+      At line 187 in file Objects\startup\startup.s
+Comment: __heap_base used once
+__heap_limit 00001000
+
+Symbol: __heap_limit
+   Definitions
+      At line 17 in file Objects\startup\startup.s
+   Uses
+      At line 188 in file Objects\startup\startup.s
+Comment: __heap_limit used once
+4 symbols
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+Relocatable symbols
+
+RESET 00000000
+
+Symbol: RESET
+   Definitions
+      At line 24 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: RESET unused
+__Vectors 00000000
+
+Symbol: __Vectors
+   Definitions
+      At line 28 in file Objects\startup\startup.s
+   Uses
+      At line 25 in file Objects\startup\startup.s
+      At line 80 in file Objects\startup\startup.s
+
+__Vectors_End 000000C0
+
+Symbol: __Vectors_End
+   Definitions
+      At line 78 in file Objects\startup\startup.s
+   Uses
+      At line 26 in file Objects\startup\startup.s
+      At line 80 in file Objects\startup\startup.s
+
+3 symbols
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+Relocatable symbols
+
+.text 00000000
+
+Symbol: .text
+   Definitions
+      At line 82 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: .text unused
+ADC_IRQHandler 00000018
+
+Symbol: ADC_IRQHandler
+   Definitions
+      At line 156 in file Objects\startup\startup.s
+   Uses
+      At line 51 in file Objects\startup\startup.s
+      At line 122 in file Objects\startup\startup.s
+
+BT_IRQHandler 00000018
+
+Symbol: BT_IRQHandler
+   Definitions
+      At line 158 in file Objects\startup\startup.s
+   Uses
+      At line 53 in file Objects\startup\startup.s
+      At line 124 in file Objects\startup\startup.s
+
+DMA_IRQHandler 00000018
+
+Symbol: DMA_IRQHandler
+   Definitions
+      At line 164 in file Objects\startup\startup.s
+   Uses
+      At line 59 in file Objects\startup\startup.s
+      At line 130 in file Objects\startup\startup.s
+
+Default_Handler 00000018
+
+Symbol: Default_Handler
+   Definitions
+      At line 109 in file Objects\startup\startup.s
+   Uses
+      None
+Comment: Default_Handler unused
+FFT_IRQHandler 00000018
+
+Symbol: FFT_IRQHandler
+   Definitions
+      At line 163 in file Objects\startup\startup.s
+   Uses
+      At line 58 in file Objects\startup\startup.s
+      At line 129 in file Objects\startup\startup.s
+
+GPIO_IRQHandler 00000018
+
+Symbol: GPIO_IRQHandler
+   Definitions
+      At line 159 in file Objects\startup\startup.s
+   Uses
+      At line 54 in file Objects\startup\startup.s
+
+
+
+ARM Macro Assembler    Page 2 Alphabetic symbol ordering
+Relocatable symbols
+
+      At line 125 in file Objects\startup\startup.s
+
+HardFault_Handler 00000018
+
+Symbol: HardFault_Handler
+   Definitions
+      At line 145 in file Objects\startup\startup.s
+   Uses
+      At line 31 in file Objects\startup\startup.s
+      At line 111 in file Objects\startup\startup.s
+
+IIC_IRQHandler 00000018
+
+Symbol: IIC_IRQHandler
+   Definitions
+      At line 151 in file Objects\startup\startup.s
+   Uses
+      At line 46 in file Objects\startup\startup.s
+      At line 117 in file Objects\startup\startup.s
+
+IIS_IRQHandler 00000018
+
+Symbol: IIS_IRQHandler
+   Definitions
+      At line 157 in file Objects\startup\startup.s
+   Uses
+      At line 52 in file Objects\startup\startup.s
+      At line 123 in file Objects\startup\startup.s
+
+LOADRAMFLAG 00000014
+
+Symbol: LOADRAMFLAG
+   Definitions
+      At line 108 in file Objects\startup\startup.s
+   Uses
+      At line 91 in file Objects\startup\startup.s
+Comment: LOADRAMFLAG used once
+NMI_Handler 00000018
+
+Symbol: NMI_Handler
+   Definitions
+      At line 146 in file Objects\startup\startup.s
+   Uses
+      At line 30 in file Objects\startup\startup.s
+      At line 112 in file Objects\startup\startup.s
+
+OTP_IRQHandler 00000018
+
+Symbol: OTP_IRQHandler
+   Definitions
+      At line 160 in file Objects\startup\startup.s
+   Uses
+      At line 55 in file Objects\startup\startup.s
+      At line 126 in file Objects\startup\startup.s
+
+PendSV_Handler 00000018
+
+Symbol: PendSV_Handler
+   Definitions
+
+
+
+ARM Macro Assembler    Page 3 Alphabetic symbol ordering
+Relocatable symbols
+
+      At line 148 in file Objects\startup\startup.s
+   Uses
+      At line 42 in file Objects\startup\startup.s
+      At line 114 in file Objects\startup\startup.s
+
+QSPI_IRQHandler 00000018
+
+Symbol: QSPI_IRQHandler
+   Definitions
+      At line 152 in file Objects\startup\startup.s
+   Uses
+      At line 47 in file Objects\startup\startup.s
+      At line 118 in file Objects\startup\startup.s
+
+RUN_TO_MAIN 0000000E
+
+Symbol: RUN_TO_MAIN
+   Definitions
+      At line 100 in file Objects\startup\startup.s
+   Uses
+      At line 95 in file Objects\startup\startup.s
+Comment: RUN_TO_MAIN used once
+Reset_Handler 00000000
+
+Symbol: Reset_Handler
+   Definitions
+      At line 88 in file Objects\startup\startup.s
+   Uses
+      At line 29 in file Objects\startup\startup.s
+      At line 89 in file Objects\startup\startup.s
+
+SBC_ERR0_IRQHandler 00000018
+
+Symbol: SBC_ERR0_IRQHandler
+   Definitions
+      At line 161 in file Objects\startup\startup.s
+   Uses
+      At line 56 in file Objects\startup\startup.s
+      At line 127 in file Objects\startup\startup.s
+
+SBC_ERR1_IRQHandler 00000018
+
+Symbol: SBC_ERR1_IRQHandler
+   Definitions
+      At line 162 in file Objects\startup\startup.s
+   Uses
+      At line 57 in file Objects\startup\startup.s
+      At line 128 in file Objects\startup\startup.s
+
+SD_IRQHandler 00000018
+
+Symbol: SD_IRQHandler
+   Definitions
+      At line 165 in file Objects\startup\startup.s
+   Uses
+      At line 60 in file Objects\startup\startup.s
+      At line 131 in file Objects\startup\startup.s
+
+SPI_IRQHandler 00000018
+
+
+
+ARM Macro Assembler    Page 4 Alphabetic symbol ordering
+Relocatable symbols
+
+
+Symbol: SPI_IRQHandler
+   Definitions
+      At line 153 in file Objects\startup\startup.s
+   Uses
+      At line 48 in file Objects\startup\startup.s
+      At line 119 in file Objects\startup\startup.s
+
+SVC_Handler 00000018
+
+Symbol: SVC_Handler
+   Definitions
+      At line 147 in file Objects\startup\startup.s
+   Uses
+      At line 39 in file Objects\startup\startup.s
+      At line 113 in file Objects\startup\startup.s
+
+SysTick_Handler 00000018
+
+Symbol: SysTick_Handler
+   Definitions
+      At line 149 in file Objects\startup\startup.s
+   Uses
+      At line 43 in file Objects\startup\startup.s
+      At line 115 in file Objects\startup\startup.s
+
+TIMER0_IRQHandler 00000018
+
+Symbol: TIMER0_IRQHandler
+   Definitions
+      At line 166 in file Objects\startup\startup.s
+   Uses
+      At line 61 in file Objects\startup\startup.s
+      At line 132 in file Objects\startup\startup.s
+
+TIMER1_IRQHandler 00000018
+
+Symbol: TIMER1_IRQHandler
+   Definitions
+      At line 167 in file Objects\startup\startup.s
+   Uses
+      At line 62 in file Objects\startup\startup.s
+      At line 133 in file Objects\startup\startup.s
+
+TIMER2_IRQHandler 00000018
+
+Symbol: TIMER2_IRQHandler
+   Definitions
+      At line 168 in file Objects\startup\startup.s
+   Uses
+      At line 63 in file Objects\startup\startup.s
+      At line 134 in file Objects\startup\startup.s
+
+TIMER3_IRQHandler 00000018
+
+Symbol: TIMER3_IRQHandler
+   Definitions
+      At line 169 in file Objects\startup\startup.s
+   Uses
+
+
+
+ARM Macro Assembler    Page 5 Alphabetic symbol ordering
+Relocatable symbols
+
+      At line 64 in file Objects\startup\startup.s
+      At line 135 in file Objects\startup\startup.s
+
+TIMER4_IRQHandler 00000018
+
+Symbol: TIMER4_IRQHandler
+   Definitions
+      At line 170 in file Objects\startup\startup.s
+   Uses
+      At line 65 in file Objects\startup\startup.s
+      At line 136 in file Objects\startup\startup.s
+
+TIMER5_IRQHandler 00000018
+
+Symbol: TIMER5_IRQHandler
+   Definitions
+      At line 171 in file Objects\startup\startup.s
+   Uses
+      At line 66 in file Objects\startup\startup.s
+      At line 137 in file Objects\startup\startup.s
+
+TIMER6_IRQHandler 00000018
+
+Symbol: TIMER6_IRQHandler
+   Definitions
+      At line 172 in file Objects\startup\startup.s
+   Uses
+      At line 67 in file Objects\startup\startup.s
+      At line 138 in file Objects\startup\startup.s
+
+TIMER7_IRQHandler 00000018
+
+Symbol: TIMER7_IRQHandler
+   Definitions
+      At line 173 in file Objects\startup\startup.s
+   Uses
+      At line 68 in file Objects\startup\startup.s
+      At line 139 in file Objects\startup\startup.s
+
+UARTB_IRQHandler 00000018
+
+Symbol: UARTB_IRQHandler
+   Definitions
+      At line 155 in file Objects\startup\startup.s
+   Uses
+      At line 50 in file Objects\startup\startup.s
+      At line 121 in file Objects\startup\startup.s
+
+UART_IRQHandler 00000018
+
+Symbol: UART_IRQHandler
+   Definitions
+      At line 154 in file Objects\startup\startup.s
+   Uses
+      At line 49 in file Objects\startup\startup.s
+      At line 120 in file Objects\startup\startup.s
+
+USB_IRQHandler 00000018
+
+
+
+
+ARM Macro Assembler    Page 6 Alphabetic symbol ordering
+Relocatable symbols
+
+Symbol: USB_IRQHandler
+   Definitions
+      At line 150 in file Objects\startup\startup.s
+   Uses
+      At line 45 in file Objects\startup\startup.s
+      At line 116 in file Objects\startup\startup.s
+
+WDT2_IRQHandler 00000018
+
+Symbol: WDT2_IRQHandler
+   Definitions
+      At line 175 in file Objects\startup\startup.s
+   Uses
+      At line 69 in file Objects\startup\startup.s
+      At line 141 in file Objects\startup\startup.s
+
+WDT_IRQHandler 00000018
+
+Symbol: WDT_IRQHandler
+   Definitions
+      At line 176 in file Objects\startup\startup.s
+   Uses
+      At line 70 in file Objects\startup\startup.s
+      At line 142 in file Objects\startup\startup.s
+
+36 symbols
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+Absolute symbols
+
+Heap_Size 00001000
+
+Symbol: Heap_Size
+   Definitions
+      At line 13 in file Objects\startup\startup.s
+   Uses
+      At line 16 in file Objects\startup\startup.s
+Comment: Heap_Size used once
+Stack_Size 0000B640
+
+Symbol: Stack_Size
+   Definitions
+      At line 2 in file Objects\startup\startup.s
+   Uses
+      At line 5 in file Objects\startup\startup.s
+Comment: Stack_Size used once
+__Vectors_Size 000000C0
+
+Symbol: __Vectors_Size
+   Definitions
+      At line 80 in file Objects\startup\startup.s
+   Uses
+      At line 27 in file Objects\startup\startup.s
+Comment: __Vectors_Size used once
+__initial_sp 1001B640
+
+Symbol: __initial_sp
+   Definitions
+      At line 6 in file Objects\startup\startup.s
+   Uses
+      At line 28 in file Objects\startup\startup.s
+      At line 186 in file Objects\startup\startup.s
+
+4 symbols
+
+
+
+ARM Macro Assembler    Page 1 Alphabetic symbol ordering
+External symbols
+
+__main 00000000
+
+Symbol: __main
+   Definitions
+      At line 90 in file Objects\startup\startup.s
+   Uses
+      At line 96 in file Objects\startup\startup.s
+Comment: __main used once
+main 00000000
+
+Symbol: main
+   Definitions
+      At line 101 in file Objects\startup\startup.s
+   Uses
+      At line 102 in file Objects\startup\startup.s
+Comment: main used once
+2 symbols
+386 symbols in table
Index: ModuleDemo/BLE/CM0/Prj/MDK/Listings/yc11xx.map
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Listings/yc11xx.map	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Listings/yc11xx.map	(working copy)
@@ -0,0 +1,1783 @@
+Component: ARM Compiler 5.06 update 6 (build 750) Tool: armlink [4d35ed]
+
+==============================================================================
+
+Section Cross References
+
+    main.o(.text) refers to strcpy.o(.text) for strcpy
+    main.o(.text) refers to printk.o(.text) for snprintk
+    main.o(.text) refers to memseta.o(.text) for __aeabi_memclr4
+    main.o(.text) refers to uuid.o(.text) for bt_uuid_cmp
+    main.o(.text) refers to gatt.o(.text) for bt_gatt_discover
+    main.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    main.o(.text) refers to hci_core.o(.text) for bt_le_scan_stop
+    main.o(.text) refers to conn.o(.text) for bt_conn_le_create
+    main.o(.text) refers to log.o(.text) for bt_hex_real
+    main.o(.text) refers to main.o(.constdata) for .constdata
+    main.o(.text) refers to main.o(.bss) for discover_params
+    main.o(.text) refers to main.o(.data) for uuid
+    main.o(.text) refers to yc_timer.o(.text) for SYS_TimerInit
+    main.o(.text) refers to yc11xx_bt.o(.text) for IPC_init
+    main.o(.text) refers to yc_debug.o(.text) for init_debugUart
+    main.o(.text) refers to yc11xx_dev_bt.o(.text) for ipc_bt_hci_init
+    main.o(.text) refers to yc11xx.o(.text) for HWRITE
+    main.o(.text) refers to yc_drv_common.o(.text) for Lpm_unLockLpm
+    main.o(.text) refers to yc11xx_dev_bt.o(.bss) for gBRState
+    main.o(.constdata) refers to main.o(.data) for <Data1>
+    main.o(.constdata) refers to main.o(.conststring) for .conststring
+    main.o(.data) refers to yc11xx_bt.o(.text) for IpcDefaultCallBack
+    main.o(.data) refers to yc11xx_dev_bt.o(.text) for Bt_EvtCallBack
+    main.o(.data) refers to main.o(.text) for connected
+    startup.o(RESET) refers to startup.o(.text) for Reset_Handler
+    startup.o(RESET) refers to main.o(.text) for SysTick_Handler
+    startup.o(.text) refers to entry.o(.ARM.Collect$$$$00000000) for __main
+    startup.o(.text) refers to main.o(.text) for main
+    yc11xx_gpio.o(.text) refers to yc11xx.o(.text) for HWRITE
+    yc11xx_gpio.o(.text) refers to yc_drv_common.o(.text) for error_handle
+    yc11xx_gpio.o(.text) refers to yc_timer.o(.text) for SYS_delay_ms
+    yc_drv_common.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc11xx_systick.o(.text) refers to yc11xx_systick.o(.data) for SystickCount
+    yc_timer.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc_timer.o(.text) refers to yc_debug.o(.text) for print_log
+    yc_timer.o(.text) refers to yc11xx_systick.o(.text) for SysTick_Config
+    yc_timer.o(.text) refers to yc_timer.o(.data) for gSystemInFastDpll
+    yc_timer.o(.text) refers to yc_timer.o(.bss) for header_Timer
+    yc11xx_timer.o(.text) refers to main.o(.text) for _assert_handler
+    yc11xx_timer.o(.text) refers to yc_drv_common.o(.text) for HW_REG_16BIT
+    yc11xx_timer.o(.text) refers to yc11xx_timer.o(.constdata) for __FUNCTION__
+    yc11xx_uart.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc11xx_uart.o(.text) refers to main.o(.text) for _assert_handler
+    yc11xx_uart.o(.text) refers to yc_drv_common.o(.text) for HW_REG_16BIT
+    yc11xx_uart.o(.text) refers to yc11xx_uart.o(.constdata) for __FUNCTION__
+    yc11xx_uart.o(.text) refers to yc11xx_uart.o(.bss) for regBeck
+    yc11xx_uart.o(.text) refers to yc11xx_uart.o(.data) for uartB_TX_buf
+    yc11xx_bt.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy4
+    yc11xx_bt.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc11xx_bt.o(.text) refers to yc_drv_common.o(.text) for HR_REG_24BIT
+    yc11xx_bt.o(.text) refers to yc_debug.o(.text) for print_log
+    yc11xx_bt.o(.text) refers to yc11xx_bt.o(.data) for gIPC_test
+    yc11xx_bt.o(.text) refers to yc11xx_bt.o(.bss) for ipcCb
+    yc11xx_bt.o(.text) refers to yc11xx_bt.o(.constdata) for .constdata
+    yc_debug.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc_debug.o(.text) refers to memseta.o(.text) for __aeabi_memclr4
+    yc_debug.o(.text) refers to yc_debug.o(.data) for txptr
+    yc_debug.o(.text) refers to yc_debug.o(.bss) for uarttxbuf
+    yc_debug.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    yc_debug.o(.text) refers to idiv.o(.text) for __aeabi_idivmod
+    yc_debug.o(.text) refers to yc_timer.o(.text) for SystemCheckInFastSpeed
+    yc_debug.o(.text) refers to main.o(.text) for _assert_handler
+    yc_debug.o(.text) refers to yc_debug.o(.constdata) for __FUNCTION__
+    yc_debug.o(.text) refers to uidiv.o(.text) for __aeabi_uidivmod
+    yc_debug.o(.constdata) refers to yc_debug.o(.conststring) for .conststring
+    yc11xx_wdt.o(.text) refers to yc11xx_wdt.o(.data) for gpWdtInit
+    yc_queue.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    printk.o(.text) refers to uidiv.o(.text) for __aeabi_uidivmod
+    printk.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    printk.o(.text) refers to printk.o(.data) for _char_out
+    printk.o(.text) refers to yc_debug.o(.text) for print_string_log_raw
+    printk.o(.data) refers to printk.o(.text) for arch_printk_char_out
+    buf.o(.text) refers to idiv.o(.text) for __aeabi_idivmod
+    buf.o(.text) refers to printk.o(.text) for printk
+    buf.o(.text) refers to queue.o(.text) for k_queue_get
+    buf.o(.text) refers to memcpy.o(.text) for memcpy
+    buf.o(.text) refers to buf.o(.constdata) for __func__
+    buf.o(.text) refers to uread4.o(.text) for __aeabi_uread4
+    buf.o(.text) refers to uread8.o(.text) for __aeabi_uread8
+    buf.o(.constdata) refers to buf.o(.text) for fixed_data_alloc
+    queue.o(.text) refers to mempool.o(.text) for k_free
+    log.o(.text) refers to printk.o(.text) for snprintk
+    log.o(.text) refers to uuid.o(.text) for bt_uuid_to_str
+    log.o(.text) refers to strcpy.o(.text) for strcpy
+    log.o(.text) refers to log.o(.constdata) for hex
+    log.o(.text) refers to log.o(.bss) for str
+    hci_common.o(.text) refers to hci_core.o(.text) for bt_buf_get_evt
+    hci_common.o(.text) refers to buf.o(.text) for net_buf_simple_add
+    hci_core.o(.text) refers to printk.o(.text) for printk
+    hci_core.o(.text) refers to log.o(.text) for bt_hex_real
+    hci_core.o(.text) refers to buf.o(.text) for net_buf_alloc_fixed_debug
+    hci_core.o(.text) refers to strlen.o(.text) for strlen
+    hci_core.o(.text) refers to idiv.o(.text) for __aeabi_idivmod
+    hci_core.o(.text) refers to hci_core.o(.constdata) for __func__
+    hci_core.o(.text) refers to hci_core.o(.data) for hci_cmd_pool
+    hci_core.o(.text) refers to hci_core.o(.bss) for cmd_data
+    hci_core.o(.text) refers to hex.o(.text) for char2hex
+    hci_core.o(.text) refers to strcmp.o(.text) for strcmp
+    hci_core.o(.text) refers to conn.o(.text) for bt_conn_lookup_handle
+    hci_core.o(.text) refers to memseta.o(.text) for __aeabi_memclr
+    hci_core.o(.text) refers to hci_core.o(.conststring) for .conststring
+    hci_core.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    hci_core.o(.text) refers to l2cap.o(.text) for bt_l2cap_update_conn_param
+    hci_core.o(.text) refers to gatt.o(.text) for bt_gatt_clear
+    hci_core.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    hci_core.o(.text) refers to memcmp.o(.text) for memcmp
+    hci_core.o(.constdata) refers to hci_core.o(.bss) for net_buf_data_hci_cmd_pool
+    hci_core.o(.constdata) refers to buf.o(.constdata) for net_buf_fixed_cb
+    hci_core.o(.constdata) refers to hci_core.o(.text) for le_adv_report
+    hci_core.o(.constdata) refers to hci_core.o(.conststring) for .conststring
+    hci_core.o(.data) refers to hci_core.o(.constdata) for net_buf_fixed_alloc_hci_cmd_pool
+    hci_core.o(.data) refers to hci_core.o(.bss) for net_buf_hci_cmd_pool
+    uuid.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    uuid.o(.text) refers to memcmp.o(.text) for memcmp
+    uuid.o(.text) refers to printk.o(.text) for snprintk
+    uuid.o(.text) refers to memseta.o(.text) for __aeabi_memclr
+    uuid.o(.text) refers to uuid.o(.constdata) for uuid128_base
+    att.o(.text) refers to printk.o(.text) for printk
+    att.o(.text) refers to mem_slab.o(.text) for k_mem_slab_free
+    att.o(.text) refers to buf.o(.text) for net_buf_unref_debug
+    att.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    att.o(.text) refers to l2cap.o(.text) for bt_l2cap_send_cb
+    att.o(.text) refers to queue.o(.text) for k_queue_prepend
+    att.o(.text) refers to att.o(._k_mem_slab.static.req_slab) for req_slab
+    att.o(.text) refers to att.o(.constdata) for __func__
+    att.o(.text) refers to log.o(.text) for bt_hex_real
+    att.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    att.o(.text) refers to att.o(.bss) for cancel
+    att.o(.text) refers to uuid.o(.text) for bt_uuid_cmp
+    att.o(.text) refers to memcmp.o(.text) for memcmp
+    att.o(.text) refers to memseta.o(.text) for __aeabi_memclr4
+    att.o(.text) refers to gatt.o(.text) for bt_gatt_check_perm
+    att.o(.text) refers to att.o(._k_mem_slab.static.att_slab) for att_slab
+    att.o(.text) refers to att.o(._k_mem_slab.static.chan_slab) for chan_slab
+    att.o(.text) refers to att.o(.data) for ops
+    att.o(._bt_l2cap_fixed_chan.static.att_fixed_chan) refers to att.o(.text) for bt_att_accept
+    att.o(._k_mem_slab.static.att_slab) refers to att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".1) for _k_mem_slab_buf_att_slab
+    att.o(._k_mem_slab.static.chan_slab) refers to att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".2) for _k_mem_slab_buf_chan_slab
+    att.o(._k_mem_slab.static.req_slab) refers to att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".0) for _k_mem_slab_buf_req_slab
+    att.o(.constdata) refers to att.o(.text) for att_mtu_req
+    att.o(.data) refers to att.o(.text) for bt_att_connected
+    conn.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    conn.o(.text) refers to gatt.o(.text) for bt_gatt_connected
+    conn.o(.text) refers to hci_core.o(.text) for bt_le_conn_params_valid
+    conn.o(.text) refers to buf.o(.text) for net_buf_simple_add
+    conn.o(.text) refers to memseta.o(.text) for __aeabi_memclr
+    conn.o(.text) refers to printk.o(.text) for printk
+    conn.o(.text) refers to l2cap.o(.text) for bt_l2cap_update_conn_param
+    conn.o(.text) refers to queue.o(.text) for k_queue_append
+    conn.o(.text) refers to conn.o(.data) for callback_list
+    conn.o(.text) refers to hci_core.o(.bss) for bt_dev
+    conn.o(.text) refers to conn.o(._k_queue.static.free_tx) for free_tx
+    conn.o(.text) refers to conn.o(.bss) for acl_conns
+    conn.o(.text) refers to conn.o(.constdata) for __func__
+    conn.o(.text) refers to conn.o(.conststring) for .conststring
+    conn.o(.text) refers to idiv.o(.text) for __aeabi_idivmod
+    conn.o(.text) refers to att.o(.text) for bt_att_init
+    conn.o(.text) refers to memcmp.o(.text) for memcmp
+    conn.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    conn.o(.text) refers to l2cap.o(._bt_l2cap_fixed_chan.static.le_fixed_chan) for le_fixed_chan
+    conn.o(.text) refers to att.o(._bt_l2cap_fixed_chan.static.att_fixed_chan) for att_fixed_chan
+    conn.o(.constdata) refers to conn.o(.bss) for net_buf_data_acl_tx_pool
+    conn.o(.constdata) refers to buf.o(.constdata) for net_buf_fixed_cb
+    conn.o(.data) refers to conn.o(.constdata) for net_buf_fixed_alloc_acl_tx_pool
+    conn.o(.data) refers to conn.o(.bss) for net_buf_acl_tx_pool
+    gatt.o(.text) refers to printk.o(.text) for printk
+    gatt.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    gatt.o(.text) refers to hci_core.o(.text) for bt_get_name
+    gatt.o(.text) refers to strlen.o(.text) for strlen
+    gatt.o(.text) refers to log.o(.text) for bt_addr_le_str_real
+    gatt.o(.text) refers to memseta.o(.text) for __aeabi_memclr
+    gatt.o(.text) refers to gatt.o(.data) for last_static_handle
+    gatt.o(.text) refers to uuid.o(.text) for bt_uuid_cmp
+    gatt.o(.text) refers to conn.o(.text) for bt_conn_is_peer_addr_le
+    gatt.o(.text) refers to gatt.o(.constdata) for .constdata
+    gatt.o(.text) refers to att.o(.text) for bt_att_create_pdu
+    gatt.o(.text) refers to buf.o(.text) for net_buf_simple_add
+    gatt.o(.text) refers to hci_core.o(.bss) for bt_dev
+    gatt.o(.text) refers to gatt.o(._bt_gatt_service_static.static._1_gatt_svc) for _1_gatt_svc
+    gatt.o(.text) refers to gatt.o(.bss) for sc_restore_params
+    gatt.o(.text) refers to idiv.o(.text) for __aeabi_idivmod
+    gatt.o(.text) refers to gatt.o(.conststring) for .conststring
+    gatt.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    gatt.o(.text) refers to memcmp.o(.text) for memcmp
+    gatt.o(._bt_gatt_service_static.static._1_gatt_svc) refers to gatt.o(.constdata) for attr__1_gatt_svc
+    gatt.o(._bt_gatt_service_static.static._2_gap_svc) refers to gatt.o(.constdata) for attr__2_gap_svc
+    gatt.o(.constdata) refers to gatt.o(.data) for <Data1>
+    gatt.o(.constdata) refers to gatt.o(.text) for bt_gatt_attr_read_service
+    gatt.o(.data) refers to gatt.o(.text) for sc_ccc_cfg_write
+    l2cap.o(.text) refers to printk.o(.text) for printk
+    l2cap.o(.text) refers to buf.o(.text) for net_buf_simple_push
+    l2cap.o(.text) refers to conn.o(.text) for bt_conn_send_cb
+    l2cap.o(.text) refers to printk.o(i.__ARM_common_switch8) for __ARM_common_switch8
+    l2cap.o(.text) refers to l2cap.o(.data) for ident
+    l2cap.o(.text) refers to conn.o(.bss) for _bt_l2cap_fixed_chan_list
+    l2cap.o(.text) refers to l2cap.o(.constdata) for __func__
+    l2cap.o(.text) refers to l2cap.o(.conststring) for .conststring
+    l2cap.o(.text) refers to l2cap.o(.bss) for bt_l2cap_pool
+    l2cap.o(._bt_l2cap_fixed_chan.static.le_fixed_chan) refers to l2cap.o(.text) for l2cap_accept
+    l2cap.o(.constdata) refers to l2cap.o(.text) for l2cap_connected
+    yc11xx_dev_bt.o(.text) refers to yc_debug.o(.text) for print_log
+    yc11xx_dev_bt.o(.text) refers to yc_timer.o(.text) for SYS_delay_ms
+    yc11xx_dev_bt.o(.text) refers to memseta.o(.text) for __aeabi_memclr4
+    yc11xx_dev_bt.o(.text) refers to yc11xx_bt.o(.text) for IPC_TxCommon
+    yc11xx_dev_bt.o(.text) refers to printk.o(.text) for printk
+    yc11xx_dev_bt.o(.text) refers to hci_core.o(.text) for bt_buf_get_evt
+    yc11xx_dev_bt.o(.text) refers to yc_drv_common.o(.text) for xmemcpy
+    yc11xx_dev_bt.o(.text) refers to main.o(.text) for _assert_handler
+    yc11xx_dev_bt.o(.text) refers to buf.o(.text) for net_buf_simple_add_mem
+    yc11xx_dev_bt.o(.text) refers to yc11xx_dev_bt.o(.bss) for gBRState
+    yc11xx_dev_bt.o(.text) refers to yc11xx_dev_bt.o(.constdata) for __FUNCTION__
+    yc11xx_dev_bt.o(.text) refers to yc11xx_gpio.o(.text) for GPIO_ClearWakeup
+    yc11xx_dev_bt.o(.text) refers to yc11xx.o(.text) for HREAD
+    yc11xx_dev_bt.o(.text) refers to memcpy.o(.text) for __aeabi_memcpy
+    yc11xx_dev_bt.o(.text) refers to log.o(.text) for bt_hex_real
+    yc11xx_dev_bt.o(.constdata) refers to yc11xx_dev_bt.o(.conststring) for .conststring
+    yc11xx_dev_bt.o(.constdata) refers to yc11xx_dev_bt.o(.text) for ipc_bt_hci_open
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry10a.o(.ARM.Collect$$$$0000000D) for __rt_final_cpp
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry11a.o(.ARM.Collect$$$$0000000F) for __rt_final_exit
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry7b.o(.ARM.Collect$$$$00000008) for _main_clock
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry8b.o(.ARM.Collect$$$$0000000A) for _main_cpp_init
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry9a.o(.ARM.Collect$$$$0000000B) for _main_init
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry5.o(.ARM.Collect$$$$00000004) for _main_scatterload
+    entry.o(.ARM.Collect$$$$00000000) refers (Special) to entry2.o(.ARM.Collect$$$$00000001) for _main_stk
+    idiv.o(.text) refers to uidiv.o(.text) for __aeabi_uidivmod
+    entry2.o(.ARM.Collect$$$$00000001) refers to entry2.o(.ARM.Collect$$$$00002712) for __lit__00000000
+    entry2.o(__vectab_stack_and_reset_area) refers to entry.o(.ARM.Collect$$$$00000000) for __main
+    entry5.o(.ARM.Collect$$$$00000004) refers to init.o(.text) for __scatterload
+    entry9a.o(.ARM.Collect$$$$0000000B) refers to main.o(.text) for main
+    entry9b.o(.ARM.Collect$$$$0000000C) refers to main.o(.text) for main
+    init.o(.text) refers to entry5.o(.ARM.Collect$$$$00000004) for __main_after_scatterload
+
+
+==============================================================================
+
+Removing Unused input sections from the image.
+
+    Removing startup.o(STACK), (46656 bytes).
+    Removing startup.o(HEAP), (4096 bytes).
+    Removing yc11xx_timer.o(.text), (556 bytes).
+    Removing yc11xx_timer.o(.constdata), (17 bytes).
+    Removing yc11xx_uart.o(.text), (1756 bytes).
+    Removing yc11xx_uart.o(.bss), (1056 bytes).
+    Removing yc11xx_uart.o(.constdata), (154 bytes).
+    Removing yc11xx_uart.o(.data), (4 bytes).
+    Removing yc11xx_wdt.o(.text), (284 bytes).
+    Removing yc11xx_wdt.o(.data), (4 bytes).
+    Removing yc_queue.o(.text), (318 bytes).
+    Removing hci_common.o(.text), (126 bytes).
+
+12 unused section(s) (total 55027 bytes) removed from the image.
+
+==============================================================================
+
+Image Symbol Table
+
+    Local Symbols
+
+    Symbol Name                              Value     Ov Type        Size  Object(Section)
+
+    RESET                                    0x00000000   Section      192  startup.o(RESET)
+    ../clib/../cmprslib/zerorunl2.c          0x00000000   Number         0  __dczerorl2.o ABSOLUTE
+    ../clib/microlib/division.c              0x00000000   Number         0  uidiv.o ABSOLUTE
+    ../clib/microlib/division.c              0x00000000   Number         0  idiv.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry9b.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry11a.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry9a.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry10b.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry10a.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry7b.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry7a.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry2.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry8a.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry8b.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry5.o ABSOLUTE
+    ../clib/microlib/init/entry.s            0x00000000   Number         0  entry11b.o ABSOLUTE
+    ../clib/microlib/string/memcmp.c         0x00000000   Number         0  memcmp.o ABSOLUTE
+    ../clib/microlib/string/memcpy.c         0x00000000   Number         0  memcpy.o ABSOLUTE
+    ../clib/microlib/string/memcpy.c         0x00000000   Number         0  memcpya.o ABSOLUTE
+    ../clib/microlib/string/memcpy.c         0x00000000   Number         0  memcpyc.o ABSOLUTE
+    ../clib/microlib/string/memcpy.c         0x00000000   Number         0  memcpyb.o ABSOLUTE
+    ../clib/microlib/string/memset.c         0x00000000   Number         0  memseta.o ABSOLUTE
+    ../clib/microlib/string/strcmp.c         0x00000000   Number         0  strcmp.o ABSOLUTE
+    ../clib/microlib/string/strcpy.c         0x00000000   Number         0  strcpy.o ABSOLUTE
+    ../clib/microlib/string/strlen.c         0x00000000   Number         0  strlen.o ABSOLUTE
+    ../clib/microlib/unhosted.c              0x00000000   Number         0  uread8.o ABSOLUTE
+    ../clib/microlib/unhosted.c              0x00000000   Number         0  uread4.o ABSOLUTE
+    ..\..\..\..\..\Librarier\device\yc11xx.c 0x00000000   Number         0  yc11xx.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\bt\yc11xx_bt.c 0x00000000   Number         0  yc11xx_bt.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\debug\yc_debug.c 0x00000000   Number         0  yc_debug.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\gpio\yc11xx_gpio.c 0x00000000   Number         0  yc11xx_gpio.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\hal_comm\yc_drv_common.c 0x00000000   Number         0  yc_drv_common.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\queue\yc_queue.c 0x00000000   Number         0  yc_queue.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\systick\yc11xx_systick.c 0x00000000   Number         0  yc11xx_systick.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\timer\yc11xx_timer.c 0x00000000   Number         0  yc11xx_timer.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\timer\yc_timer.c 0x00000000   Number         0  yc_timer.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\uart\yc11xx_uart.c 0x00000000   Number         0  yc11xx_uart.o ABSOLUTE
+    ..\..\..\..\..\Librarier\drivers\wdt\yc11xx_wdt.c 0x00000000   Number         0  yc11xx_wdt.o ABSOLUTE
+    ..\..\User\device\bt\yc11xx_dev_bt.c     0x00000000   Number         0  yc11xx_dev_bt.o ABSOLUTE
+    ..\..\User\main.c                        0x00000000   Number         0  main.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\common\log.c 0x00000000   Number         0  log.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\att.c   0x00000000   Number         0  att.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\conn.c  0x00000000   Number         0  conn.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\gatt.c  0x00000000   Number         0  gatt.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\hci_common.c 0x00000000   Number         0  hci_common.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\hci_core.c 0x00000000   Number         0  hci_core.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\l2cap.c 0x00000000   Number         0  l2cap.o ABSOLUTE
+    ..\..\User\subsys\bluetooth\host\uuid.c  0x00000000   Number         0  uuid.o ABSOLUTE
+    ..\..\User\utils\buf.c                   0x00000000   Number         0  buf.o ABSOLUTE
+    ..\..\User\utils\hex.c                   0x00000000   Number         0  hex.o ABSOLUTE
+    ..\..\User\utils\mem_slab.c              0x00000000   Number         0  mem_slab.o ABSOLUTE
+    ..\..\User\utils\mempool.c               0x00000000   Number         0  mempool.o ABSOLUTE
+    ..\..\User\utils\printk.c                0x00000000   Number         0  printk.o ABSOLUTE
+    ..\..\User\utils\queue.c                 0x00000000   Number         0  queue.o ABSOLUTE
+    Objects\startup\startup.s                0x00000000   Number         0  startup.o ABSOLUTE
+    dc.s                                     0x00000000   Number         0  dc.o ABSOLUTE
+    handlers.s                               0x00000000   Number         0  handlers.o ABSOLUTE
+    init.s                                   0x00000000   Number         0  init.o ABSOLUTE
+    .ARM.Collect$$$$00000000                 0x000000c0   Section        0  entry.o(.ARM.Collect$$$$00000000)
+    .ARM.Collect$$$$00000001                 0x000000c0   Section        4  entry2.o(.ARM.Collect$$$$00000001)
+    .ARM.Collect$$$$00000004                 0x000000c4   Section        4  entry5.o(.ARM.Collect$$$$00000004)
+    .ARM.Collect$$$$00000008                 0x000000c8   Section        0  entry7b.o(.ARM.Collect$$$$00000008)
+    .ARM.Collect$$$$0000000A                 0x000000c8   Section        0  entry8b.o(.ARM.Collect$$$$0000000A)
+    .ARM.Collect$$$$0000000B                 0x000000c8   Section        8  entry9a.o(.ARM.Collect$$$$0000000B)
+    .ARM.Collect$$$$0000000D                 0x000000d0   Section        0  entry10a.o(.ARM.Collect$$$$0000000D)
+    .ARM.Collect$$$$0000000F                 0x000000d0   Section        0  entry11a.o(.ARM.Collect$$$$0000000F)
+    .ARM.Collect$$$$00002712                 0x000000d0   Section        4  entry2.o(.ARM.Collect$$$$00002712)
+    __lit__00000000                          0x000000d0   Data           4  entry2.o(.ARM.Collect$$$$00002712)
+    .text                                    0x000000d4   Section        0  main.o(.text)
+    bt_addr_le_to_str                        0x00000127   Thumb Code   126  main.o(.text)
+    notify_func                              0x000001a5   Thumb Code    40  main.o(.text)
+    discover_func                            0x000001cd   Thumb Code   270  main.o(.text)
+    data_cb                                  0x000002db   Thumb Code   202  main.o(.text)
+    scan_cb                                  0x000003a5   Thumb Code    84  main.o(.text)
+    start_scan                               0x000003f9   Thumb Code    52  main.o(.text)
+    connected                                0x0000042d   Thumb Code   806  main.o(.text)
+    disconnected                             0x00000753   Thumb Code    68  main.o(.text)
+    bt_ready                                 0x00000797   Thumb Code    46  main.o(.text)
+    .text                                    0x00000950   Section       40  startup.o(.text)
+    RUN_TO_MAIN                              0x0000095f   Thumb Code     4  startup.o(.text)
+    LOADRAMFLAG                              0x00000964   Data           4  startup.o(.text)
+    .text                                    0x00000978   Section        0  yc11xx_gpio.o(.text)
+    hw_delay                                 0x00000bef   Thumb Code    12  yc11xx_gpio.o(.text)
+    .text                                    0x00000c04   Section        0  yc_drv_common.o(.text)
+    hw_delay                                 0x00000d8f   Thumb Code    12  yc_drv_common.o(.text)
+    .text                                    0x00000da4   Section        0  yc11xx_systick.o(.text)
+    .text                                    0x00000dfc   Section        0  yc_timer.o(.text)
+    hw_delay                                 0x000012a7   Thumb Code    12  yc_timer.o(.text)
+    .text                                    0x000012c4   Section        0  yc11xx_bt.o(.text)
+    ipcRx                                    0x000012e7   Thumb Code   284  yc11xx_bt.o(.text)
+    ipcTx                                    0x00001403   Thumb Code   308  yc11xx_bt.o(.text)
+    hw_delay                                 0x00001869   Thumb Code    12  yc11xx_bt.o(.text)
+    .text                                    0x0000188c   Section        0  yc_debug.o(.text)
+    .text                                    0x000023c8   Section        0  yc11xx.o(.text)
+    .text                                    0x00002400   Section        0  printk.o(.text)
+    print_digits                             0x00002413   Thumb Code   138  printk.o(.text)
+    print_hex                                0x0000249d   Thumb Code    54  printk.o(.text)
+    print_dec                                0x000024d3   Thumb Code    54  printk.o(.text)
+    ok64                                     0x00002509   Thumb Code    48  printk.o(.text)
+    negative                                 0x00002539   Thumb Code    10  printk.o(.text)
+    char_out                                 0x000027df   Thumb Code    50  printk.o(.text)
+    str_out                                  0x0000285f   Thumb Code    62  printk.o(.text)
+    .text                                    0x00002908   Section        0  buf.o(.text)
+    z_log_minimal_level_to_char              0x00002909   Thumb Code    40  buf.o(.text)
+    sys_put_be32                             0x00002931   Thumb Code    24  buf.o(.text)
+    sys_put_be48                             0x00002949   Thumb Code    26  buf.o(.text)
+    sys_put_be64                             0x00002963   Thumb Code    26  buf.o(.text)
+    sys_put_le32                             0x0000297d   Thumb Code    24  buf.o(.text)
+    sys_put_le48                             0x00002995   Thumb Code    26  buf.o(.text)
+    sys_put_le64                             0x000029af   Thumb Code    26  buf.o(.text)
+    sys_slist_get                            0x000029c9   Thumb Code    80  buf.o(.text)
+    pool_id                                  0x00002a1b   Thumb Code     2  buf.o(.text)
+    generic_data_ref                         0x00002a43   Thumb Code    14  buf.o(.text)
+    fixed_data_alloc                         0x00002a51   Thumb Code    50  buf.o(.text)
+    fixed_data_unref                         0x00002a83   Thumb Code     2  buf.o(.text)
+    data_alloc                               0x00002a85   Thumb Code    32  buf.o(.text)
+    data_ref                                 0x00002aa5   Thumb Code    28  buf.o(.text)
+    data_unref                               0x00002ac1   Thumb Code    42  buf.o(.text)
+    sys_put_be16                             0x000040a9   Thumb Code     8  buf.o(.text)
+    sys_put_be24                             0x000040b1   Thumb Code    22  buf.o(.text)
+    sys_put_le16                             0x000040c7   Thumb Code     8  buf.o(.text)
+    sys_put_le24                             0x000040cf   Thumb Code    22  buf.o(.text)
+    z_slist_head_set                         0x000040e5   Thumb Code     4  buf.o(.text)
+    z_slist_tail_set                         0x000040e9   Thumb Code     4  buf.o(.text)
+    net_buf_destroy                          0x000040ed   Thumb Code    22  buf.o(.text)
+    .text                                    0x00004102   Section        0  queue.o(.text)
+    sys_sflist_insert                        0x00004103   Thumb Code   176  queue.o(.text)
+    prepare_thread_to_run                    0x000041eb   Thumb Code     2  queue.o(.text)
+    queue_insert                             0x000041ef   Thumb Code    62  queue.o(.text)
+    z_sfnode_next_set                        0x000043b5   Thumb Code    18  queue.o(.text)
+    z_sflist_head_set                        0x000043c7   Thumb Code     4  queue.o(.text)
+    z_sflist_tail_set                        0x000043cb   Thumb Code     4  queue.o(.text)
+    sys_sflist_peek_head                     0x000043cf   Thumb Code     6  queue.o(.text)
+    sys_sflist_peek_tail                     0x000043d5   Thumb Code     6  queue.o(.text)
+    sys_sfnode_init                          0x000043db   Thumb Code     4  queue.o(.text)
+    .text                                    0x000043de   Section        0  mempool.o(.text)
+    .text                                    0x000043ec   Section        0  hex.o(.text)
+    .text                                    0x00004530   Section        0  log.o(.text)
+    bt_addr_le_to_str                        0x000045cd   Thumb Code   126  log.o(.text)
+    .text                                    0x000046d4   Section        0  mem_slab.o(.text)
+    .text                                    0x00004770   Section        0  hci_core.o(.text)
+    atomic_test_bit                          0x00004771   Thumb Code    28  hci_core.o(.text)
+    atomic_test_and_clear_bit                0x0000478d   Thumb Code    46  hci_core.o(.text)
+    atomic_test_and_set_bit                  0x000047bb   Thumb Code    46  hci_core.o(.text)
+    atomic_clear_bit                         0x000047e9   Thumb Code    30  hci_core.o(.text)
+    atomic_set_bit                           0x00004807   Thumb Code    30  hci_core.o(.text)
+    atomic_set_bit_to                        0x00004825   Thumb Code    50  hci_core.o(.text)
+    sys_slist_peek_next                      0x00004857   Thumb Code    20  hci_core.o(.text)
+    sys_slist_append                         0x0000486b   Thumb Code    62  hci_core.o(.text)
+    sys_put_le32                             0x000048a9   Thumb Code    24  hci_core.o(.text)
+    sys_put_le64                             0x000048c1   Thumb Code    26  hci_core.o(.text)
+    bt_hci_evt_get_flags                     0x000048db   Thumb Code    46  hci_core.o(.text)
+    z_log_minimal_level_to_char              0x00004909   Thumb Code    40  hci_core.o(.text)
+    handle_event                             0x0000493f   Thumb Code   132  hci_core.o(.text)
+    bt_adv_foreach                           0x00004b4b   Thumb Code    16  hci_core.o(.text)
+    adv_new_legacy                           0x00004b5b   Thumb Code     6  hci_core.o(.text)
+    adv_delete_legacy                        0x00004b61   Thumb Code     2  hci_core.o(.text)
+    set_le_adv_enable_legacy                 0x00004b69   Thumb Code   106  hci_core.o(.text)
+    set_random_address                       0x00004bd3   Thumb Code   134  hci_core.o(.text)
+    set_le_adv_enable_ext                    0x00004c59   Thumb Code   160  hci_core.o(.text)
+    set_le_adv_enable                        0x00004cf9   Thumb Code    16  hci_core.o(.text)
+    set_adv_random_address                   0x00004d09   Thumb Code    14  hci_core.o(.text)
+    adv_rpa_invalidate                       0x00004f55   Thumb Code    32  hci_core.o(.text)
+    le_rpa_invalidate                        0x00004f75   Thumb Code    28  hci_core.o(.text)
+    le_set_private_addr                      0x00004f91   Thumb Code    40  hci_core.o(.text)
+    le_adv_set_private_addr                  0x00004fb9   Thumb Code    44  hci_core.o(.text)
+    adv_update_rpa                           0x00004fe5   Thumb Code   110  hci_core.o(.text)
+    set_le_scan_enable_legacy                0x00005053   Thumb Code   120  hci_core.o(.text)
+    set_le_scan_enable                       0x000050cb   Thumb Code    12  hci_core.o(.text)
+    le_update_private_addr                   0x0000510f   Thumb Code   172  hci_core.o(.text)
+    adv_id_check_func                        0x000051bb   Thumb Code    36  hci_core.o(.text)
+    adv_id_check_connectable_func            0x000051df   Thumb Code    50  hci_core.o(.text)
+    bt_le_adv_random_addr_check              0x00005237   Thumb Code    38  hci_core.o(.text)
+    set_le_ext_scan_enable                   0x0000525d   Thumb Code   322  hci_core.o(.text)
+    hci_le_read_max_data_len                 0x0000539f   Thumb Code    14  hci_core.o(.text)
+    hci_acl                                  0x000053ad   Thumb Code   284  hci_core.o(.text)
+    hci_data_buf_overflow                    0x000054c9   Thumb Code    34  hci_core.o(.text)
+    hci_num_completed_packets                0x000054eb   Thumb Code   266  hci_core.o(.text)
+    le_create_conn_set_random_addr           0x000055f5   Thumb Code    40  hci_core.o(.text)
+    set_phy_conn_param                       0x0000561d   Thumb Code    52  hci_core.o(.text)
+    hci_disconn_complete_prio                0x000059f5   Thumb Code   114  hci_core.o(.text)
+    is_adv_using_rand_addr                   0x00005a67   Thumb Code    34  hci_core.o(.text)
+    le_scan_set_random_addr                  0x00005a89   Thumb Code    86  hci_core.o(.text)
+    start_le_scan_legacy                     0x00005adf   Thumb Code   158  hci_core.o(.text)
+    start_passive_scan                       0x00005b7d   Thumb Code    30  hci_core.o(.text)
+    hci_disconn_complete                     0x00005c11   Thumb Code   328  hci_core.o(.text)
+    hci_le_read_remote_features              0x00005d59   Thumb Code    56  hci_core.o(.text)
+    hci_read_remote_version                  0x00005d91   Thumb Code    82  hci_core.o(.text)
+    slave_update_conn_param                  0x00005e7f   Thumb Code     2  hci_core.o(.text)
+    find_pending_connect                     0x00005e81   Thumb Code    32  hci_core.o(.text)
+    conn_auto_initiate                       0x00005ea1   Thumb Code    68  hci_core.o(.text)
+    le_conn_complete_cancel                  0x00005ee5   Thumb Code    84  hci_core.o(.text)
+    le_conn_complete_adv_timeout             0x00005f39   Thumb Code    80  hci_core.o(.text)
+    enh_conn_complete                        0x00005f89   Thumb Code   724  hci_core.o(.text)
+    le_enh_conn_complete                     0x0000625d   Thumb Code    12  hci_core.o(.text)
+    le_legacy_conn_complete                  0x00006269   Thumb Code   178  hci_core.o(.text)
+    le_remote_feat_complete                  0x0000631b   Thumb Code    98  hci_core.o(.text)
+    le_conn_param_neg_reply                  0x000063d1   Thumb Code    78  hci_core.o(.text)
+    le_conn_param_req_reply                  0x0000641f   Thumb Code    98  hci_core.o(.text)
+    le_conn_param_req                        0x00006481   Thumb Code   152  hci_core.o(.text)
+    le_conn_update_complete                  0x00006519   Thumb Code   210  hci_core.o(.text)
+    check_pending_conn                       0x000065eb   Thumb Code   338  hci_core.o(.text)
+    unpair                                   0x0000673d   Thumb Code    58  hci_core.o(.text)
+    unpair_remote                            0x00006777   Thumb Code    18  hci_core.o(.text)
+    hci_hardware_error                       0x000067b1   Thumb Code    44  hci_core.o(.text)
+    hci_reset_complete                       0x000067dd   Thumb Code    68  hci_core.o(.text)
+    hci_cmd_done                             0x00006821   Thumb Code   198  hci_core.o(.text)
+    hci_cmd_status                           0x000068e7   Thumb Code    66  hci_core.o(.text)
+    start_le_scan_ext                        0x00006929   Thumb Code   202  hci_core.o(.text)
+    get_adv_props                            0x00006a5d   Thumb Code    42  hci_core.o(.text)
+    le_adv_recv                              0x00006a87   Thumb Code   790  hci_core.o(.text)
+    le_adv_report                            0x00006d9d   Thumb Code   172  hci_core.o(.text)
+    le_adv_stop_free_conn                    0x00006e49   Thumb Code    84  hci_core.o(.text)
+    hci_vendor_event                         0x00006eb3   Thumb Code     8  hci_core.o(.text)
+    hci_le_meta_event                        0x00006ebb   Thumb Code    56  hci_core.o(.text)
+    hci_event                                0x00006ef3   Thumb Code    66  hci_core.o(.text)
+    send_cmd                                 0x00006f35   Thumb Code   258  hci_core.o(.text)
+    process_events                           0x00007037   Thumb Code   166  hci_core.o(.text)
+    hci_tx_thread                            0x000070dd   Thumb Code    36  hci_core.o(.text)
+    read_local_ver_complete                  0x00007101   Thumb Code    92  hci_core.o(.text)
+    read_le_features_complete                0x0000715d   Thumb Code    46  hci_core.o(.text)
+    read_buffer_size_complete                0x0000718b   Thumb Code   448  hci_core.o(.text)
+    le_read_buffer_size_complete             0x0000734b   Thumb Code    88  hci_core.o(.text)
+    read_buffer_size_v2_complete             0x000073a3   Thumb Code     2  hci_core.o(.text)
+    le_set_host_feature                      0x000073a5   Thumb Code     8  hci_core.o(.text)
+    read_supported_commands_complete         0x000073ad   Thumb Code    46  hci_core.o(.text)
+    read_local_features_complete             0x000073db   Thumb Code    46  hci_core.o(.text)
+    le_read_supp_states_complete             0x00007409   Thumb Code    64  hci_core.o(.text)
+    send_hci_cmd_with_init_process           0x00007449   Thumb Code    54  hci_core.o(.text)
+    id_find                                  0x0000749f   Thumb Code    52  hci_core.o(.text)
+    id_create                                0x000074d3   Thumb Code   108  hci_core.o(.text)
+    read_bd_addr_complete                    0x0000753f   Thumb Code   114  hci_core.o(.text)
+    ver_str                                  0x000075b1   Thumb Code    36  hci_core.o(.text)
+    bt_dev_show_info                         0x000075d5   Thumb Code   238  hci_core.o(.text)
+    hci_init_end                             0x000076f3   Thumb Code   410  hci_core.o(.text)
+    set_event_mask                           0x0000788d   Thumb Code   104  hci_core.o(.text)
+    le_set_event_mask                        0x000078f5   Thumb Code   154  hci_core.o(.text)
+    hci_le_init_process                      0x0000798f   Thumb Code   108  hci_core.o(.text)
+    hci_init_process                         0x000079fb   Thumb Code   224  hci_core.o(.text)
+    hci_cmd_complete                         0x00007adb   Thumb Code   118  hci_core.o(.text)
+    le_init                                  0x00007b51   Thumb Code    58  hci_core.o(.text)
+    br_init                                  0x00007b8b   Thumb Code    28  hci_core.o(.text)
+    bt_read_public_addr                      0x00007bc7   Thumb Code    14  hci_core.o(.text)
+    hci_init                                 0x00007bd5   Thumb Code    62  hci_core.o(.text)
+    bt_init                                  0x00007e17   Thumb Code    20  hci_core.o(.text)
+    init_work                                0x00007e2b   Thumb Code    28  hci_core.o(.text)
+    hci_rx_thread                            0x00007e47   Thumb Code   178  hci_core.o(.text)
+    set_data_add                             0x00007fa5   Thumb Code   194  hci_core.o(.text)
+    hci_set_ad                               0x00008067   Thumb Code    92  hci_core.o(.text)
+    hci_set_ad_ext                           0x000080c3   Thumb Code   108  hci_core.o(.text)
+    set_ad                                   0x0000812f   Thumb Code   358  hci_core.o(.text)
+    set_sd                                   0x00008295   Thumb Code    20  hci_core.o(.text)
+    bt_le_per_adv_enable                     0x00008701   Thumb Code   136  hci_core.o(.text)
+    valid_adv_ext_param                      0x000087a5   Thumb Code   158  hci_core.o(.text)
+    valid_adv_param                          0x00008843   Thumb Code    46  hci_core.o(.text)
+    ad_has_name                              0x00008871   Thumb Code    38  hci_core.o(.text)
+    le_adv_update                            0x00008897   Thumb Code   236  hci_core.o(.text)
+    get_filter_policy                        0x000089db   Thumb Code     6  hci_core.o(.text)
+    get_adv_channel_map                      0x000089e1   Thumb Code    56  hci_core.o(.text)
+    le_adv_set_random_addr                   0x00008a19   Thumb Code   180  hci_core.o(.text)
+    le_adv_start_add_conn                    0x00008acd   Thumb Code   188  hci_core.o(.text)
+    le_ext_adv_param_set                     0x00008dd7   Thumb Code   546  hci_core.o(.text)
+    valid_le_scan_param                      0x000091b7   Thumb Code    88  hci_core.o(.text)
+    atomic_or                                0x00009509   Thumb Code    12  hci_core.o(.text)
+    atomic_and                               0x00009515   Thumb Code    12  hci_core.o(.text)
+    z_snode_next_set                         0x00009521   Thumb Code     4  hci_core.o(.text)
+    z_slist_head_set                         0x00009525   Thumb Code     4  hci_core.o(.text)
+    z_slist_tail_set                         0x00009529   Thumb Code     4  hci_core.o(.text)
+    sys_slist_peek_head                      0x0000952d   Thumb Code     6  hci_core.o(.text)
+    sys_slist_get                            0x00009533   Thumb Code    84  hci_core.o(.text)
+    sys_put_le16                             0x00009587   Thumb Code     8  hci_core.o(.text)
+    sys_put_le24                             0x0000958f   Thumb Code    22  hci_core.o(.text)
+    sys_get_le32                             0x000095a5   Thumb Code    22  hci_core.o(.text)
+    net_buf_simple_save                      0x000095bb   Thumb Code    20  hci_core.o(.text)
+    net_buf_simple_restore                   0x000095cf   Thumb Code    14  hci_core.o(.text)
+    net_buf_user_data                        0x000095dd   Thumb Code     8  hci_core.o(.text)
+    bt_addr_cmp                              0x000095e5   Thumb Code    18  hci_core.o(.text)
+    bt_addr_le_cmp                           0x000095f7   Thumb Code    18  hci_core.o(.text)
+    bt_addr_copy                             0x00009609   Thumb Code    18  hci_core.o(.text)
+    bt_addr_le_copy                          0x0000961b   Thumb Code    18  hci_core.o(.text)
+    bt_buf_set_type                          0x0000962d   Thumb Code    16  hci_core.o(.text)
+    bt_buf_get_type                          0x0000963d   Thumb Code    14  hci_core.o(.text)
+    create_random_addr                       0x0000964b   Thumb Code    18  hci_core.o(.text)
+    handle_hci_command_complete_work         0x0000965d   Thumb Code    84  hci_core.o(.text)
+    sys_get_le16                             0x000096b1   Thumb Code    12  hci_core.o(.text)
+    .text                                    0x000096f8   Section        0  uuid.o(.text)
+    uuid_to_uuid128                          0x000096f9   Thumb Code   100  uuid.o(.text)
+    uuid128_cmp                              0x0000975d   Thumb Code    42  uuid.o(.text)
+    sys_put_le16                             0x000098fd   Thumb Code     8  uuid.o(.text)
+    sys_get_le16                             0x00009905   Thumb Code    12  uuid.o(.text)
+    .text                                    0x00009944   Section        0  att.o(.text)
+    atomic_test_bit                          0x00009945   Thumb Code    28  att.o(.text)
+    sys_slist_peek_next                      0x00009961   Thumb Code    22  att.o(.text)
+    sys_slist_prepend                        0x00009977   Thumb Code    58  att.o(.text)
+    sys_slist_get                            0x000099b1   Thumb Code    76  att.o(.text)
+    sys_slist_find_and_remove                0x000099fd   Thumb Code    54  att.o(.text)
+    net_buf_frags_len                        0x00009a33   Thumb Code    18  att.o(.text)
+    z_log_minimal_level_to_char              0x00009a45   Thumb Code    40  att.o(.text)
+    att_req_destroy                          0x00009a93   Thumb Code    66  att.o(.text)
+    chan_req_sent                            0x00009b0b   Thumb Code    34  att.o(.text)
+    att_req_sent                             0x00009b2d   Thumb Code    52  att.o(.text)
+    chan_cfm_sent                            0x00009b61   Thumb Code    32  att.o(.text)
+    att_cfm_sent                             0x00009b81   Thumb Code    52  att.o(.text)
+    chan_rsp_sent                            0x00009bb5   Thumb Code    32  att.o(.text)
+    att_rsp_sent                             0x00009bd5   Thumb Code    52  att.o(.text)
+    att_cb                                   0x00009c09   Thumb Code    36  att.o(.text)
+    att_op_get_type                          0x00009c2d   Thumb Code   174  att.o(.text)
+    chan_cb                                  0x00009cdb   Thumb Code    48  att.o(.text)
+    chan_send                                0x00009d0b   Thumb Code   194  att.o(.text)
+    process_queue                            0x00009dcd   Thumb Code    62  att.o(.text)
+    chan_req_send                            0x00009e0b   Thumb Code   394  att.o(.text)
+    bt_att_sent                              0x00009f95   Thumb Code   172  att.o(.text)
+    bt_att_chan_send                         0x0000a0d7   Thumb Code    64  att.o(.text)
+    bt_att_chan_send_rsp                     0x0000a117   Thumb Code    36  att.o(.text)
+    send_err_rsp                             0x0000a13b   Thumb Code    72  att.o(.text)
+    att_get                                  0x0000a183   Thumb Code   128  att.o(.text)
+    att_mtu_req                              0x0000a2b9   Thumb Code   534  att.o(.text)
+    bt_att_chan_req_send                     0x0000a4cf   Thumb Code    46  att.o(.text)
+    att_process                              0x0000a4fd   Thumb Code   184  att.o(.text)
+    att_handle_rsp                           0x0000a5b5   Thumb Code   200  att.o(.text)
+    att_mtu_rsp                              0x0000a67d   Thumb Code   124  att.o(.text)
+    range_is_valid                           0x0000a6f9   Thumb Code    40  att.o(.text)
+    find_info_cb                             0x0000a721   Thumb Code   230  att.o(.text)
+    att_find_info_rsp                        0x0000a807   Thumb Code   108  att.o(.text)
+    att_find_info_req                        0x0000a873   Thumb Code   246  att.o(.text)
+    find_type_cb                             0x0000a969   Thumb Code   440  att.o(.text)
+    att_find_type_rsp                        0x0000ab21   Thumb Code   132  att.o(.text)
+    att_find_type_req                        0x0000aba5   Thumb Code   180  att.o(.text)
+    err_to_att                               0x0000ac59   Thumb Code    52  att.o(.text)
+    attr_read_type_cb                        0x0000ac8d   Thumb Code    50  att.o(.text)
+    att_chan_read                            0x0000acbf   Thumb Code   508  att.o(.text)
+    read_type_cb                             0x0000aebb   Thumb Code   206  att.o(.text)
+    att_read_type_rsp                        0x0000af89   Thumb Code   142  att.o(.text)
+    att_read_type_req                        0x0000b017   Thumb Code   168  att.o(.text)
+    read_cb                                  0x0000b0bf   Thumb Code   114  att.o(.text)
+    att_read_rsp                             0x0000b131   Thumb Code   152  att.o(.text)
+    att_read_req                             0x0000b1c9   Thumb Code   154  att.o(.text)
+    att_read_blob_req                        0x0000b263   Thumb Code    72  att.o(.text)
+    attr_read_group_cb                       0x0000b2ab   Thumb Code    56  att.o(.text)
+    read_group_cb                            0x0000b2e3   Thumb Code   236  att.o(.text)
+    att_read_group_rsp                       0x0000b3cf   Thumb Code   134  att.o(.text)
+    att_read_group_req                       0x0000b455   Thumb Code   224  att.o(.text)
+    write_cb                                 0x0000b535   Thumb Code   132  att.o(.text)
+    att_write_rsp                            0x0000b5b9   Thumb Code   268  att.o(.text)
+    att_write_req                            0x0000b6c5   Thumb Code    68  att.o(.text)
+    att_prepare_write_req                    0x0000b709   Thumb Code     6  att.o(.text)
+    att_exec_write_req                       0x0000b70f   Thumb Code     6  att.o(.text)
+    att_write_cmd                            0x0000b715   Thumb Code    66  att.o(.text)
+    att_error_rsp                            0x0000b757   Thumb Code   108  att.o(.text)
+    att_handle_find_info_rsp                 0x0000b7c3   Thumb Code    44  att.o(.text)
+    att_handle_find_type_rsp                 0x0000b7ef   Thumb Code    44  att.o(.text)
+    att_handle_read_type_rsp                 0x0000b81b   Thumb Code    44  att.o(.text)
+    att_handle_read_rsp                      0x0000b847   Thumb Code    44  att.o(.text)
+    att_handle_read_blob_rsp                 0x0000b873   Thumb Code    44  att.o(.text)
+    att_handle_read_group_rsp                0x0000b89f   Thumb Code    44  att.o(.text)
+    att_handle_write_rsp                     0x0000b8cb   Thumb Code    44  att.o(.text)
+    att_handle_prepare_write_rsp             0x0000b8f7   Thumb Code    44  att.o(.text)
+    att_handle_exec_write_rsp                0x0000b923   Thumb Code    44  att.o(.text)
+    att_notify                               0x0000b94f   Thumb Code    62  att.o(.text)
+    att_indicate                             0x0000b98d   Thumb Code    90  att.o(.text)
+    att_notify_mult                          0x0000b9e7   Thumb Code    48  att.o(.text)
+    att_confirm                              0x0000ba17   Thumb Code    44  att.o(.text)
+    bt_att_recv                              0x0000ba43   Thumb Code   490  att.o(.text)
+    att_reset                                0x0000bc2d   Thumb Code   172  att.o(.text)
+    att_chan_detach                          0x0000bcd9   Thumb Code   102  att.o(.text)
+    att_timeout                              0x0000bd3f   Thumb Code    72  att.o(.text)
+    att_get_fixed_chan                       0x0000bd87   Thumb Code    18  att.o(.text)
+    att_chan_attach                          0x0000bd99   Thumb Code    76  att.o(.text)
+    bt_att_connected                         0x0000bde5   Thumb Code    76  att.o(.text)
+    bt_att_disconnected                      0x0000be31   Thumb Code    74  att.o(.text)
+    bt_att_status                            0x0000be7b   Thumb Code   102  att.o(.text)
+    bt_att_released                          0x0000bee1   Thumb Code    44  att.o(.text)
+    att_chan_new                             0x0000bf0d   Thumb Code   538  att.o(.text)
+    bt_eatt_accept                           0x0000c1af   Thumb Code    72  att.o(.text)
+    bt_eatt_init                             0x0000c1f7   Thumb Code    58  att.o(.text)
+    bt_att_chan_req_cancel                   0x0000c677   Thumb Code    30  att.o(.text)
+    sys_slist_init                           0x0000c759   Thumb Code     8  att.o(.text)
+    z_snode_next_peek                        0x0000c761   Thumb Code     6  att.o(.text)
+    z_snode_next_set                         0x0000c767   Thumb Code     4  att.o(.text)
+    z_slist_head_set                         0x0000c76b   Thumb Code     4  att.o(.text)
+    z_slist_tail_set                         0x0000c76f   Thumb Code     4  att.o(.text)
+    sys_slist_peek_head                      0x0000c773   Thumb Code     6  att.o(.text)
+    sys_slist_peek_tail                      0x0000c779   Thumb Code     6  att.o(.text)
+    sys_slist_is_empty                       0x0000c77f   Thumb Code    22  att.o(.text)
+    sys_slist_remove                         0x0000c795   Thumb Code   100  att.o(.text)
+    k_queue_init                             0x0000c7f9   Thumb Code    12  att.o(.text)
+    net_buf_simple_save                      0x0000c805   Thumb Code    20  att.o(.text)
+    net_buf_simple_restore                   0x0000c819   Thumb Code    14  att.o(.text)
+    bt_gatt_foreach_attr                     0x0000c827   Thumb Code    32  att.o(.text)
+    .text                                    0x0000c874   Section        0  conn.o(.text)
+    atomic_test_bit                          0x0000c875   Thumb Code    32  conn.o(.text)
+    atomic_test_and_clear_bit                0x0000c895   Thumb Code    46  conn.o(.text)
+    atomic_clear_bit                         0x0000c8c3   Thumb Code    30  conn.o(.text)
+    atomic_set_bit                           0x0000c8e1   Thumb Code    30  conn.o(.text)
+    sys_slist_get_not_empty                  0x0000c8ff   Thumb Code    58  conn.o(.text)
+    z_log_minimal_level_to_char              0x0000c939   Thumb Code    40  conn.o(.text)
+    state2str                                0x0000c967   Thumb Code    62  conn.o(.text)
+    notify_connected                         0x0000c9a5   Thumb Code    44  conn.o(.text)
+    notify_disconnected                      0x0000c9d1   Thumb Code    32  conn.o(.text)
+    send_conn_le_param_update                0x0000cb05   Thumb Code   150  conn.o(.text)
+    tx_free                                  0x0000cb9b   Thumb Code    48  conn.o(.text)
+    tx_notify                                0x0000cbcb   Thumb Code   116  conn.o(.text)
+    tx_complete_polling                      0x0000cc3f   Thumb Code    80  conn.o(.text)
+    tx_complete_work                         0x0000cc8f   Thumb Code    40  conn.o(.text)
+    conn_update_timeout                      0x0000ccf5   Thumb Code   524  conn.o(.text)
+    acl_conn_new                             0x0000cf4b   Thumb Code    24  conn.o(.text)
+    conn_tx_alloc                            0x0000d183   Thumb Code    80  conn.o(.text)
+    send_acl                                 0x0000d2cb   Thumb Code   638  conn.o(.text)
+    send_iso                                 0x0000d549   Thumb Code   104  conn.o(.text)
+    send_frag                                0x0000d5b1   Thumb Code   340  conn.o(.text)
+    create_frag                              0x0000d7d1   Thumb Code   126  conn.o(.text)
+    send_buf                                 0x0000d84f   Thumb Code   160  conn.o(.text)
+    conn_cleanup                             0x0000d8ef   Thumb Code    72  conn.o(.text)
+    conn_prepare_events                      0x0000d937   Thumb Code   106  conn.o(.text)
+    process_unack_tx                         0x0000dd4b   Thumb Code    84  conn.o(.text)
+    conn_disconnect                          0x0000e1f7   Thumb Code    36  conn.o(.text)
+    bt_conn_set_param_le                     0x0000e29b   Thumb Code    26  conn.o(.text)
+    create_param_validate                    0x0000e49d   Thumb Code     6  conn.o(.text)
+    create_param_setup                       0x0000e4a3   Thumb Code    80  conn.o(.text)
+    atomic_get                               0x0000e70b   Thumb Code     6  conn.o(.text)
+    atomic_or                                0x0000e711   Thumb Code    12  conn.o(.text)
+    atomic_and                               0x0000e71d   Thumb Code    12  conn.o(.text)
+    sys_get_le16                             0x0000e729   Thumb Code    12  conn.o(.text)
+    z_snode_next_peek                        0x0000e735   Thumb Code     6  conn.o(.text)
+    z_snode_next_set                         0x0000e73b   Thumb Code     4  conn.o(.text)
+    z_slist_head_set                         0x0000e73f   Thumb Code     4  conn.o(.text)
+    z_slist_tail_set                         0x0000e743   Thumb Code     4  conn.o(.text)
+    sys_slist_peek_head                      0x0000e747   Thumb Code     6  conn.o(.text)
+    sys_slist_peek_tail                      0x0000e74d   Thumb Code     6  conn.o(.text)
+    sys_slist_is_empty                       0x0000e753   Thumb Code    22  conn.o(.text)
+    sys_slist_remove                         0x0000e769   Thumb Code   100  conn.o(.text)
+    net_buf_user_data                        0x0000e7cd   Thumb Code     8  conn.o(.text)
+    bt_addr_le_cmp                           0x0000e7d5   Thumb Code    18  conn.o(.text)
+    bt_addr_le_copy                          0x0000e7e7   Thumb Code    18  conn.o(.text)
+    bt_buf_set_type                          0x0000e7f9   Thumb Code    16  conn.o(.text)
+    conn_mtu                                 0x0000e809   Thumb Code    10  conn.o(.text)
+    .text                                    0x0000e854   Section        0  gatt.o(.text)
+    atomic_test_bit                          0x0000e855   Thumb Code    28  gatt.o(.text)
+    sys_slist_peek_next                      0x0000e871   Thumb Code    20  gatt.o(.text)
+    sys_slist_prepend                        0x0000e885   Thumb Code    56  gatt.o(.text)
+    sys_slist_remove                         0x0000e8bd   Thumb Code    92  gatt.o(.text)
+    foreach_attr_type_dyndb                  0x0000e919   Thumb Code     8  gatt.o(.text)
+    z_log_minimal_level_to_char              0x0000e957   Thumb Code    40  gatt.o(.text)
+    read_name                                0x0000e9d3   Thumb Code    42  gatt.o(.text)
+    read_appearance                          0x0000e9fd   Thumb Code    42  gatt.o(.text)
+    find_sc_cfg                              0x0000ea27   Thumb Code    54  gatt.o(.text)
+    sc_store                                 0x0000ea5d   Thumb Code    98  gatt.o(.text)
+    clear_sc_cfg                             0x0000eabf   Thumb Code    14  gatt.o(.text)
+    bt_gatt_clear_sc                         0x0000eacd   Thumb Code    32  gatt.o(.text)
+    sc_clear                                 0x0000eaed   Thumb Code    88  gatt.o(.text)
+    sc_reset                                 0x0000eb45   Thumb Code    50  gatt.o(.text)
+    update_range                             0x0000eb77   Thumb Code    78  gatt.o(.text)
+    sc_save                                  0x0000ebc5   Thumb Code   172  gatt.o(.text)
+    sc_ccc_cfg_write                         0x0000ec71   Thumb Code    64  gatt.o(.text)
+    clear_cf_cfg                             0x0000ecb1   Thumb Code    32  gatt.o(.text)
+    clear_ccc_cfg                            0x0000ecd1   Thumb Code    26  gatt.o(.text)
+    get_service_handles                      0x0000eebd   Thumb Code    62  gatt.o(.text)
+    gatt_foreach_iter                        0x0000f00b   Thumb Code   102  gatt.o(.text)
+    find_next                                0x0000f071   Thumb Code    14  gatt.o(.text)
+    find_ccc_cfg                             0x0000f0a1   Thumb Code    70  gatt.o(.text)
+    gatt_ccc_changed                         0x0000f127   Thumb Code    90  gatt.o(.text)
+    gatt_notify                              0x0000f377   Thumb Code   138  gatt.o(.text)
+    gatt_indicate_rsp                        0x0000f401   Thumb Code    22  gatt.o(.text)
+    gatt_send                                0x0000f417   Thumb Code   114  gatt.o(.text)
+    gatt_indicate                            0x0000f489   Thumb Code   164  gatt.o(.text)
+    notify_cb                                0x0000f52d   Thumb Code   176  gatt.o(.text)
+    match_uuid                               0x0000f5dd   Thumb Code    14  gatt.o(.text)
+    gatt_find_by_uuid                        0x0000f5eb   Thumb Code    46  gatt.o(.text)
+    sc_restore_rsp                           0x0000f8eb   Thumb Code    36  gatt.o(.text)
+    sc_restore                               0x0000f90f   Thumb Code   222  gatt.o(.text)
+    update_ccc                               0x0000f9ed   Thumb Code   162  gatt.o(.text)
+    disconnected_cb                          0x0000fa8f   Thumb Code   212  gatt.o(.text)
+    gatt_sub_remove                          0x0000fc13   Thumb Code   244  gatt.o(.text)
+    gatt_sub_find                            0x0000fd07   Thumb Code    68  gatt.o(.text)
+    gatt_sub_add                             0x0000fd4b   Thumb Code    44  gatt.o(.text)
+    gatt_sub_find_by_addr                    0x0000fd77   Thumb Code    48  gatt.o(.text)
+    gatt_sub_add_by_addr                     0x0000fda7   Thumb Code    44  gatt.o(.text)
+    gatt_write_ccc_rsp                       0x0000fdd3   Thumb Code   190  gatt.o(.text)
+    gatt_write_ccc                           0x0000fe91   Thumb Code   146  gatt.o(.text)
+    gatt_sub_update                          0x0001029d   Thumb Code    28  gatt.o(.text)
+    remove_subscriptions                     0x000102b9   Thumb Code   194  gatt.o(.text)
+    gatt_mtu_rsp                             0x0001037b   Thumb Code    22  gatt.o(.text)
+    gatt_find_info_rsp                       0x000103fb   Thumb Code   620  gatt.o(.text)
+    gatt_find_info                           0x00010667   Thumb Code   102  gatt.o(.text)
+    parse_characteristic                     0x000106cd   Thumb Code   358  gatt.o(.text)
+    read_included_uuid_cb                    0x00010833   Thumb Code   226  gatt.o(.text)
+    read_included_uuid                       0x00010915   Thumb Code    92  gatt.o(.text)
+    parse_include                            0x00010971   Thumb Code   526  gatt.o(.text)
+    gatt_read_type_rsp                       0x00010b7f   Thumb Code   110  gatt.o(.text)
+    gatt_read_type                           0x00010bed   Thumb Code   132  gatt.o(.text)
+    parse_service                            0x00010c71   Thumb Code   348  gatt.o(.text)
+    gatt_read_group_rsp                      0x00010dcd   Thumb Code    88  gatt.o(.text)
+    gatt_read_group                          0x00010e25   Thumb Code   134  gatt.o(.text)
+    gatt_find_type_rsp                       0x00010eab   Thumb Code   330  gatt.o(.text)
+    gatt_find_type                           0x00010ff5   Thumb Code   230  gatt.o(.text)
+    gatt_discover_next                       0x000111b1   Thumb Code    76  gatt.o(.text)
+    gatt_read_rsp                            0x000111fd   Thumb Code   172  gatt.o(.text)
+    gatt_read_blob                           0x000112a9   Thumb Code   102  gatt.o(.text)
+    gatt_read_mult                           0x0001130f   Thumb Code     8  gatt.o(.text)
+    gatt_read_uuid                           0x00011317   Thumb Code   294  gatt.o(.text)
+    parse_read_by_uuid                       0x000114d5   Thumb Code   240  gatt.o(.text)
+    gatt_read_mult_vl                        0x000115c5   Thumb Code     8  gatt.o(.text)
+    gatt_write_rsp                           0x000115cd   Thumb Code    48  gatt.o(.text)
+    gatt_exec_write                          0x000116c3   Thumb Code    86  gatt.o(.text)
+    gatt_prepare_write                       0x00011719   Thumb Code   178  gatt.o(.text)
+    gatt_prepare_write_rsp                   0x0001193f   Thumb Code    80  gatt.o(.text)
+    add_subscriptions                        0x00011aeb   Thumb Code   134  gatt.o(.text)
+    ccc_find_cfg                             0x00011b71   Thumb Code    58  gatt.o(.text)
+    ccc_clear                                0x00011bab   Thumb Code    60  gatt.o(.text)
+    ccc_load                                 0x00011be7   Thumb Code   462  gatt.o(.text)
+    ccc_set                                  0x00011db5   Thumb Code     8  gatt.o(.text)
+    ccc_set_cb                               0x00011dbd   Thumb Code    24  gatt.o(.text)
+    ccc_set_direct                           0x00011dd5   Thumb Code    10  gatt.o(.text)
+    bt_gatt_store_cf                         0x00011e53   Thumb Code     6  gatt.o(.text)
+    find_cf_cfg_by_addr                      0x00011e59   Thumb Code     6  gatt.o(.text)
+    remove_peer_from_attr                    0x00011e5f   Thumb Code    52  gatt.o(.text)
+    bt_gatt_clear_ccc                        0x00011e93   Thumb Code    28  gatt.o(.text)
+    bt_gatt_clear_cf                         0x00011eaf   Thumb Code    30  gatt.o(.text)
+    find_gatt_sub                            0x00011ecd   Thumb Code    48  gatt.o(.text)
+    bt_gatt_clear_subscriptions              0x00011efd   Thumb Code   152  gatt.o(.text)
+    z_snode_next_set                         0x00011fef   Thumb Code     4  gatt.o(.text)
+    z_slist_head_set                         0x00011ff3   Thumb Code     4  gatt.o(.text)
+    z_slist_tail_set                         0x00011ff7   Thumb Code     4  gatt.o(.text)
+    sys_slist_peek_head                      0x00011ffb   Thumb Code     6  gatt.o(.text)
+    bt_addr_le_cmp                           0x00012001   Thumb Code    18  gatt.o(.text)
+    bt_addr_le_copy                          0x00012013   Thumb Code    18  gatt.o(.text)
+    bt_gatt_foreach_attr                     0x00012025   Thumb Code    32  gatt.o(.text)
+    .text                                    0x0001208c   Section        0  l2cap.o(.text)
+    sys_slist_peek_next                      0x0001208d   Thumb Code    20  l2cap.o(.text)
+    z_log_minimal_level_to_char              0x000120a1   Thumb Code    40  l2cap.o(.text)
+    get_ident                                0x00012133   Thumb Code    32  l2cap.o(.text)
+    l2cap_rtx_timeout                        0x00012239   Thumb Code    50  l2cap.o(.text)
+    l2cap_chan_add                           0x000122db   Thumb Code    68  l2cap.o(.text)
+    l2cap_create_le_sig_pdu                  0x000124b3   Thumb Code   446  l2cap.o(.text)
+    l2cap_send_reject                        0x000126f9   Thumb Code    82  l2cap.o(.text)
+    le_conn_param_rsp                        0x0001274b   Thumb Code    78  l2cap.o(.text)
+    le_conn_param_update_req                 0x00012799   Thumb Code   250  l2cap.o(.text)
+    l2cap_recv                               0x0001294b   Thumb Code   580  l2cap.o(.text)
+    l2cap_chan_recv                          0x00012b8f   Thumb Code    56  l2cap.o(.text)
+    l2cap_connected                          0x00012ccb   Thumb Code    36  l2cap.o(.text)
+    l2cap_disconnected                       0x00012cef   Thumb Code    36  l2cap.o(.text)
+    l2cap_accept                             0x00012d13   Thumb Code   102  l2cap.o(.text)
+    z_snode_next_set                         0x00012d7b   Thumb Code     4  l2cap.o(.text)
+    z_slist_head_set                         0x00012d7f   Thumb Code     4  l2cap.o(.text)
+    z_slist_tail_set                         0x00012d83   Thumb Code     4  l2cap.o(.text)
+    sys_slist_peek_head                      0x00012d87   Thumb Code     6  l2cap.o(.text)
+    sys_slist_peek_tail                      0x00012d8d   Thumb Code     6  l2cap.o(.text)
+    sys_slist_remove                         0x00012d93   Thumb Code    96  l2cap.o(.text)
+    bt_l2cap_send                            0x00012df3   Thumb Code    26  l2cap.o(.text)
+    .text                                    0x00012f34   Section        0  yc11xx_dev_bt.o(.text)
+    z_log_minimal_level_to_char              0x00012f35   Thumb Code    40  yc11xx_dev_bt.o(.text)
+    get_rx                                   0x0001311b   Thumb Code    76  yc11xx_dev_bt.o(.text)
+    ipc_bt_hci_send                          0x0001360d   Thumb Code   186  yc11xx_dev_bt.o(.text)
+    ipc_bt_hci_open                          0x000136c7   Thumb Code    30  yc11xx_dev_bt.o(.text)
+    bt_buf_get_type                          0x000136ef   Thumb Code    12  yc11xx_dev_bt.o(.text)
+    .text                                    0x0001379c   Section        0  uidiv.o(.text)
+    .text                                    0x000137c8   Section        0  idiv.o(.text)
+    .text                                    0x000137f0   Section        0  memcpy.o(.text)
+    .text                                    0x00013818   Section        0  memseta.o(.text)
+    .text                                    0x0001383c   Section        0  strlen.o(.text)
+    .text                                    0x0001384a   Section        0  strcmp.o(.text)
+    .text                                    0x00013866   Section        0  memcmp.o(.text)
+    .text                                    0x00013880   Section        0  strcpy.o(.text)
+    .text                                    0x00013892   Section        0  uread4.o(.text)
+    .text                                    0x000138a6   Section        0  uread8.o(.text)
+    .text                                    0x000138c4   Section       36  init.o(.text)
+    .text                                    0x000138e8   Section        0  __dczerorl2.o(.text)
+    i.__ARM_common_switch8                   0x0001393e   Section        0  printk.o(i.__ARM_common_switch8)
+    i.__scatterload_copy                     0x0001395a   Section       14  handlers.o(i.__scatterload_copy)
+    i.__scatterload_null                     0x00013968   Section        2  handlers.o(i.__scatterload_null)
+    i.__scatterload_zeroinit                 0x0001396a   Section       14  handlers.o(i.__scatterload_zeroinit)
+    ._bt_gatt_service_static.static._1_gatt_svc 0x00013978   Section        8  gatt.o(._bt_gatt_service_static.static._1_gatt_svc)
+    __tagsym$$used                           0x00013978   Number         0  gatt.o(._bt_gatt_service_static.static._1_gatt_svc)
+    ._bt_gatt_service_static.static._2_gap_svc 0x00013980   Section        8  gatt.o(._bt_gatt_service_static.static._2_gap_svc)
+    __tagsym$$used                           0x00013980   Number         0  gatt.o(._bt_gatt_service_static.static._2_gap_svc)
+    ._bt_l2cap_fixed_chan.static.att_fixed_chan 0x00013988   Section       12  att.o(._bt_l2cap_fixed_chan.static.att_fixed_chan)
+    __tagsym$$used                           0x00013988   Number         0  att.o(._bt_l2cap_fixed_chan.static.att_fixed_chan)
+    ._bt_l2cap_fixed_chan.static.le_fixed_chan 0x00013994   Section       12  l2cap.o(._bt_l2cap_fixed_chan.static.le_fixed_chan)
+    __tagsym$$used                           0x00013994   Number         0  l2cap.o(._bt_l2cap_fixed_chan.static.le_fixed_chan)
+    .constdata                               0x000139a0   Section      100  main.o(.constdata)
+    ad                                       0x000139a0   Data          24  main.o(.constdata)
+    sd                                       0x000139b8   Data           8  main.o(.constdata)
+    .constdata                               0x00013a04   Section        3  yc11xx_bt.o(.constdata)
+    .constdata                               0x00013a08   Section       20  yc_debug.o(.constdata)
+    __FUNCTION__                             0x00013a08   Data          10  yc_debug.o(.constdata)
+    g_pcHex1                                 0x00013a14   Data           4  yc_debug.o(.constdata)
+    g_pcHex2                                 0x00013a18   Data           4  yc_debug.o(.constdata)
+    .constdata                               0x00013a1c   Section       26  buf.o(.constdata)
+    __func__                                 0x00013a28   Data          14  buf.o(.constdata)
+    .constdata                               0x00013a36   Section       17  log.o(.constdata)
+    hex                                      0x00013a36   Data          17  log.o(.constdata)
+    .constdata                               0x00013a48   Section      557  hci_core.o(.constdata)
+    net_buf_fixed_hci_cmd_pool               0x00013a48   Data           8  hci_core.o(.constdata)
+    net_buf_fixed_alloc_hci_cmd_pool         0x00013a50   Data           8  hci_core.o(.constdata)
+    net_buf_fixed_hci_rx_pool                0x00013a58   Data           8  hci_core.o(.constdata)
+    net_buf_fixed_alloc_hci_rx_pool          0x00013a60   Data           8  hci_core.o(.constdata)
+    net_buf_fixed_num_complete_pool          0x00013a68   Data           8  hci_core.o(.constdata)
+    net_buf_fixed_alloc_num_complete_pool    0x00013a70   Data           8  hci_core.o(.constdata)
+    meta_events                              0x00013a78   Data          48  hci_core.o(.constdata)
+    normal_events                            0x00013aa8   Data          32  hci_core.o(.constdata)
+    hci_cmd_cmp_handles                      0x00013ac8   Data          56  hci_core.o(.constdata)
+    prio_events                              0x00013b00   Data          40  hci_core.o(.constdata)
+    __func__                                 0x00013b28   Data          18  hci_core.o(.constdata)
+    __func__                                 0x00013b3a   Data          16  hci_core.o(.constdata)
+    __func__                                 0x00013b4a   Data          25  hci_core.o(.constdata)
+    __func__                                 0x00013b63   Data           8  hci_core.o(.constdata)
+    __func__                                 0x00013b83   Data          10  hci_core.o(.constdata)
+    __func__                                 0x00013b8d   Data           9  hci_core.o(.constdata)
+    __func__                                 0x00013b9e   Data           8  hci_core.o(.constdata)
+    __func__                                 0x00013ba6   Data           8  hci_core.o(.constdata)
+    __func__                                 0x00013bae   Data          20  hci_core.o(.constdata)
+    __func__                                 0x00013bfc   Data          15  hci_core.o(.constdata)
+    __func__                                 0x00013c0b   Data          14  hci_core.o(.constdata)
+    __func__                                 0x00013c19   Data          11  hci_core.o(.constdata)
+    __func__                                 0x00013c24   Data          15  hci_core.o(.constdata)
+    __func__                                 0x00013c43   Data          21  hci_core.o(.constdata)
+    __func__                                 0x00013c58   Data          14  hci_core.o(.constdata)
+    __func__                                 0x00013c66   Data          15  hci_core.o(.constdata)
+    .constdata                               0x00013c75   Section       17  uuid.o(.constdata)
+    uuid128_base                             0x00013c75   Data          17  uuid.o(.constdata)
+    .constdata                               0x00013c88   Section      492  att.o(.constdata)
+    handlers                                 0x00013c88   Data         208  att.o(.constdata)
+    __func__                                 0x00013d58   Data          16  att.o(.constdata)
+    __func__                                 0x00013d68   Data          10  att.o(.constdata)
+    __func__                                 0x00013d72   Data          14  att.o(.constdata)
+    __func__                                 0x00013d80   Data          14  att.o(.constdata)
+    __func__                                 0x00013d8e   Data          15  att.o(.constdata)
+    __func__                                 0x00013d9d   Data          18  att.o(.constdata)
+    __func__                                 0x00013daf   Data          13  att.o(.constdata)
+    __func__                                 0x00013dc4   Data          18  att.o(.constdata)
+    __func__                                 0x00013ddc   Data          14  att.o(.constdata)
+    __func__                                 0x00013dea   Data          18  att.o(.constdata)
+    __func__                                 0x00013dfc   Data          13  att.o(.constdata)
+    __func__                                 0x00013e14   Data          19  att.o(.constdata)
+    __func__                                 0x00013e30   Data          14  att.o(.constdata)
+    __func__                                 0x00013e3e   Data          10  att.o(.constdata)
+    __func__                                 0x00013e48   Data          16  att.o(.constdata)
+    __func__                                 0x00013e58   Data          12  att.o(.constdata)
+    __func__                                 0x00013e64   Data          16  att.o(.constdata)
+    .constdata                               0x00013e74   Section      122  conn.o(.constdata)
+    net_buf_fixed_acl_tx_pool                0x00013e74   Data           8  conn.o(.constdata)
+    net_buf_fixed_alloc_acl_tx_pool          0x00013e7c   Data           8  conn.o(.constdata)
+    __func__                                 0x00013e84   Data          23  conn.o(.constdata)
+    __func__                                 0x00013e9b   Data          13  conn.o(.constdata)
+    __func__                                 0x00013ea8   Data          16  conn.o(.constdata)
+    __func__                                 0x00013eb8   Data          10  conn.o(.constdata)
+    __func__                                 0x00013ec2   Data          12  conn.o(.constdata)
+    __func__                                 0x00013ece   Data          13  conn.o(.constdata)
+    __func__                                 0x00013edb   Data          19  conn.o(.constdata)
+    .constdata                               0x00013ef0   Section      268  gatt.o(.constdata)
+    __func__                                 0x00013f90   Data          15  gatt.o(.constdata)
+    __func__                                 0x00013fcc   Data          34  gatt.o(.constdata)
+    __func__                                 0x00013fee   Data          14  gatt.o(.constdata)
+    .constdata                               0x00013ffc   Section       92  l2cap.o(.constdata)
+    __func__                                 0x00013ffc   Data          28  l2cap.o(.constdata)
+    __func__                                 0x00014018   Data          16  l2cap.o(.constdata)
+    __func__                                 0x00014028   Data          14  l2cap.o(.constdata)
+    ops                                      0x00014038   Data          32  l2cap.o(.constdata)
+    .constdata                               0x00014058   Section       70  yc11xx_dev_bt.o(.constdata)
+    drv                                      0x00014058   Data          20  yc11xx_dev_bt.o(.constdata)
+    __FUNCTION__                             0x0001406c   Data          15  yc11xx_dev_bt.o(.constdata)
+    __FUNCTION__                             0x0001407b   Data          19  yc11xx_dev_bt.o(.constdata)
+    __func__                                 0x0001408e   Data          16  yc11xx_dev_bt.o(.constdata)
+    .conststring                             0x000140a0   Section       11  main.o(.conststring)
+    .conststring                             0x000140ac   Section       37  yc_debug.o(.conststring)
+    .conststring                             0x000140d4   Section      193  hci_core.o(.conststring)
+    .conststring                             0x00014198   Section       67  conn.o(.conststring)
+    .conststring                             0x000141dc   Section      135  gatt.o(.conststring)
+    .conststring                             0x00014264   Section       84  l2cap.o(.conststring)
+    .conststring                             0x000142b8   Section        4  yc11xx_dev_bt.o(.conststring)
+    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".0 0x10010000   Section      144  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".0)
+    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".1 0x10010090   Section       28  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".1)
+    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".2 0x100100b0   Section      100  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".2)
+    ._k_mem_slab.static.att_slab             0x10010114   Section       20  att.o(._k_mem_slab.static.att_slab)
+    __tagsym$$used                           0x10010114   Number         0  att.o(._k_mem_slab.static.att_slab)
+    ._k_mem_slab.static.chan_slab            0x10010128   Section       20  att.o(._k_mem_slab.static.chan_slab)
+    __tagsym$$used                           0x10010128   Number         0  att.o(._k_mem_slab.static.chan_slab)
+    ._k_mem_slab.static.req_slab             0x1001013c   Section       20  att.o(._k_mem_slab.static.req_slab)
+    __tagsym$$used                           0x1001013c   Number         0  att.o(._k_mem_slab.static.req_slab)
+    ._k_queue.static.free_tx                 0x10010150   Section        8  conn.o(._k_queue.static.free_tx)
+    __tagsym$$used                           0x10010150   Number         0  conn.o(._k_queue.static.free_tx)
+    .data                                    0x10010158   Section      112  main.o(.data)
+    <Data1>                                  0x10010158   Data           1  main.o(.data)
+    <Data2>                                  0x10010159   Data           2  main.o(.data)
+    <Data3>                                  0x1001015b   Data          19  main.o(.data)
+    uuid                                     0x100101ac   Data           4  main.o(.data)
+    conn_callbacks                           0x100101b4   Data          20  main.o(.data)
+    .data                                    0x100101c8   Section        4  yc11xx_systick.o(.data)
+    .data                                    0x100101cc   Section       14  yc_timer.o(.data)
+    .data                                    0x100101dc   Section        8  yc11xx_bt.o(.data)
+    ipcCbArray                               0x100101dc   Data           4  yc11xx_bt.o(.data)
+    .data                                    0x100101e4   Section       40  yc_debug.o(.data)
+    .data                                    0x1001020c   Section        4  printk.o(.data)
+    .data                                    0x10010210   Section       96  hci_core.o(.data)
+    ready_cb                                 0x10010210   Data           4  hci_core.o(.data)
+    scan_dev_found_cb                        0x10010214   Data           4  hci_core.o(.data)
+    scan_cbs                                 0x10010218   Data           8  hci_core.o(.data)
+    hci_cmd_pool                             0x10010220   Data          24  hci_core.o(.data)
+    hci_rx_pool                              0x10010238   Data          24  hci_core.o(.data)
+    num_complete_pool                        0x10010250   Data          24  hci_core.o(.data)
+    .data                                    0x10010270   Section       44  att.o(.data)
+    ops                                      0x10010270   Data          32  att.o(.data)
+    eatt_l2cap                               0x10010290   Data          12  att.o(.data)
+    .data                                    0x1001029c   Section       44  conn.o(.data)
+    acl_tx_pool                              0x1001029c   Data          24  conn.o(.data)
+    callback_list                            0x100102b4   Data           4  conn.o(.data)
+    conn_change                              0x100102b8   Data          16  conn.o(.data)
+    .data                                    0x100102c8   Section      105  gatt.o(.data)
+    <Data1>                                  0x100102c8   Data           4  gatt.o(.data)
+    <Data2>                                  0x100102cc   Data           4  gatt.o(.data)
+    <Data3>                                  0x100102d0   Data           4  gatt.o(.data)
+    <Data4>                                  0x100102d4   Data           4  gatt.o(.data)
+    <Data5>                                  0x100102d8   Data           4  gatt.o(.data)
+    <Data6>                                  0x100102dc   Data           4  gatt.o(.data)
+    <Data7>                                  0x100102e0   Data           4  gatt.o(.data)
+    <Data8>                                  0x100102e4   Data           4  gatt.o(.data)
+    <Data9>                                  0x100102e8   Data           8  gatt.o(.data)
+    <Data10>                                 0x100102f0   Data           8  gatt.o(.data)
+    <Data11>                                 0x100102f8   Data           4  gatt.o(.data)
+    <Data12>                                 0x100102fc   Data           4  gatt.o(.data)
+    last_static_handle                       0x10010300   Data           2  gatt.o(.data)
+    init                                     0x10010304   Data           4  gatt.o(.data)
+    sc_cfg                                   0x10010308   Data           0  gatt.o(.data)
+    sc_ccc                                   0x1001030c   Data          36  gatt.o(.data)
+    cf_cfg                                   0x10010330   Data           0  gatt.o(.data)
+    .data                                    0x10010331   Section        1  l2cap.o(.data)
+    ident                                    0x10010331   Data           1  l2cap.o(.data)
+    .bss                                     0x10010334   Section       44  main.o(.bss)
+    discover_params                          0x10010334   Data          20  main.o(.bss)
+    subscribe_params                         0x10010348   Data          24  main.o(.bss)
+    .bss                                     0x10010360   Section       24  yc_timer.o(.bss)
+    .bss                                     0x10010378   Section      334  yc11xx_bt.o(.bss)
+    .bss                                     0x100104c6   Section       50  yc_debug.o(.bss)
+    .bss                                     0x100104f8   Section      214  log.o(.bss)
+    str                                      0x100104f8   Data         129  log.o(.bss)
+    str                                      0x10010579   Data          18  log.o(.bss)
+    str                                      0x1001058b   Data          30  log.o(.bss)
+    str                                      0x100105a9   Data          37  log.o(.bss)
+    .bss                                     0x100105d0   Section     5487  hci_core.o(.bss)
+    cmd_data                                 0x10010690   Data          72  hci_core.o(.bss)
+    net_buf_hci_cmd_pool                     0x100106d8   Data         168  hci_core.o(.bss)
+    net_buf_data_hci_cmd_pool                0x10010780   Data        2424  hci_core.o(.bss)
+    net_buf_hci_rx_pool                      0x100110f8   Data         168  hci_core.o(.bss)
+    net_buf_data_hci_rx_pool                 0x100111a0   Data        2424  hci_core.o(.bss)
+    net_buf_num_complete_pool                0x10011b18   Data          28  hci_core.o(.bss)
+    net_buf_data_num_complete_pool           0x10011b34   Data          11  hci_core.o(.bss)
+    .bss                                     0x10011b40   Section       24  att.o(.bss)
+    cancel                                   0x10011b40   Data          24  att.o(.bss)
+    .bss                                     0x10011b58   Section     6612  conn.o(.bss)
+    net_buf_acl_tx_pool                      0x10011b70   Data         168  conn.o(.bss)
+    net_buf_data_acl_tx_pool                 0x10011c18   Data        6216  conn.o(.bss)
+    acl_conns                                0x10013460   Data         108  conn.o(.bss)
+    conn_tx                                  0x100134cc   Data          96  conn.o(.bss)
+    .bss                                     0x1001352c   Section       52  gatt.o(.bss)
+    subscriptions                            0x1001352c   Data          32  gatt.o(.bss)
+    sc_restore_params                        0x1001354c   Data          20  gatt.o(.bss)
+    .bss                                     0x10013560   Section       72  l2cap.o(.bss)
+    bt_l2cap_pool                            0x10013560   Data          72  l2cap.o(.bss)
+    .bss                                     0x100135a8   Section     4041  yc11xx_dev_bt.o(.bss)
+
+    Global Symbols
+
+    Symbol Name                              Value     Ov Type        Size  Object(Section)
+
+    BuildAttributes$$THM_ISAv3M$S$PE$A:L22$X:L11$S22$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$MICROLIB$REQ8$PRES8$EABIv2 0x00000000   Number         0  anon$$obj.o ABSOLUTE
+    __ARM_use_no_argv                        0x00000000   Number         0  main.o ABSOLUTE
+    __Vectors                                0x00000000   Data           4  startup.o(RESET)
+    __cpp_initialize__aeabi_                  - Undefined Weak Reference
+    __cxa_finalize                            - Undefined Weak Reference
+    _clock_init                               - Undefined Weak Reference
+    _microlib_exit                            - Undefined Weak Reference
+    __Vectors_End                            0x000000c0   Data           0  startup.o(RESET)
+    __Vectors_Size                           0x000000c0   Number         0  startup.o ABSOLUTE
+    __main                                   0x000000c1   Thumb Code     0  entry.o(.ARM.Collect$$$$00000000)
+    _main_stk                                0x000000c1   Thumb Code     0  entry2.o(.ARM.Collect$$$$00000001)
+    _main_scatterload                        0x000000c5   Thumb Code     0  entry5.o(.ARM.Collect$$$$00000004)
+    __main_after_scatterload                 0x000000c9   Thumb Code     0  entry5.o(.ARM.Collect$$$$00000004)
+    _main_clock                              0x000000c9   Thumb Code     0  entry7b.o(.ARM.Collect$$$$00000008)
+    _main_cpp_init                           0x000000c9   Thumb Code     0  entry8b.o(.ARM.Collect$$$$0000000A)
+    _main_init                               0x000000c9   Thumb Code     0  entry9a.o(.ARM.Collect$$$$0000000B)
+    __rt_final_cpp                           0x000000d1   Thumb Code     0  entry10a.o(.ARM.Collect$$$$0000000D)
+    __rt_final_exit                          0x000000d1   Thumb Code     0  entry11a.o(.ARM.Collect$$$$0000000F)
+    NVIC_EnableIRQ                           0x000000d5   Thumb Code    20  main.o(.text)
+    NVIC_DisableIRQ                          0x000000e9   Thumb Code    16  main.o(.text)
+    NVIC_SetPriority                         0x000000f9   Thumb Code    46  main.o(.text)
+    main                                     0x000007c5   Thumb Code   188  main.o(.text)
+    SCO_NVIC_Config                          0x00000881   Thumb Code    18  main.o(.text)
+    SCO_NVIC_DeConfig                        0x00000893   Thumb Code    18  main.o(.text)
+    TIMER6_IRQHandler                        0x000008a5   Thumb Code     2  main.o(.text)
+    SysTick_Handler                          0x000008a7   Thumb Code     8  main.o(.text)
+    _assert_handler                          0x000008af   Thumb Code     4  main.o(.text)
+    Reset_Handler                            0x00000951   Thumb Code    14  startup.o(.text)
+    ADC_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    BT_IRQHandler                            0x00000969   Thumb Code     0  startup.o(.text)
+    DMA_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    FFT_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    GPIO_IRQHandler                          0x00000969   Thumb Code     0  startup.o(.text)
+    HardFault_Handler                        0x00000969   Thumb Code     0  startup.o(.text)
+    IIC_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    IIS_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    NMI_Handler                              0x00000969   Thumb Code     0  startup.o(.text)
+    OTP_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    PendSV_Handler                           0x00000969   Thumb Code     0  startup.o(.text)
+    QSPI_IRQHandler                          0x00000969   Thumb Code     0  startup.o(.text)
+    SBC_ERR0_IRQHandler                      0x00000969   Thumb Code     0  startup.o(.text)
+    SBC_ERR1_IRQHandler                      0x00000969   Thumb Code     0  startup.o(.text)
+    SD_IRQHandler                            0x00000969   Thumb Code     0  startup.o(.text)
+    SPI_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    SVC_Handler                              0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER0_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER1_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER2_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER3_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER4_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER5_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    TIMER7_IRQHandler                        0x00000969   Thumb Code     0  startup.o(.text)
+    UARTB_IRQHandler                         0x00000969   Thumb Code     0  startup.o(.text)
+    UART_IRQHandler                          0x00000969   Thumb Code     0  startup.o(.text)
+    USB_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    WDT2_IRQHandler                          0x00000969   Thumb Code     0  startup.o(.text)
+    WDT_IRQHandler                           0x00000969   Thumb Code     0  startup.o(.text)
+    GPIO_SetOut                              0x00000979   Thumb Code    94  yc11xx_gpio.o(.text)
+    GPIO_SetInput                            0x000009d7   Thumb Code    56  yc11xx_gpio.o(.text)
+    GPIO_SetOutput                           0x00000a0f   Thumb Code    22  yc11xx_gpio.o(.text)
+    GPIO_SetWakeup                           0x00000a25   Thumb Code   136  yc11xx_gpio.o(.text)
+    gpioGetBit                               0x00000aad   Thumb Code    40  yc11xx_gpio.o(.text)
+    GPIO_GetInputStatus                      0x00000ad5   Thumb Code    54  yc11xx_gpio.o(.text)
+    GPIO_SetWakeupByCurrentState             0x00000b0b   Thumb Code    42  yc11xx_gpio.o(.text)
+    GPIO_ClearWakeup                         0x00000b35   Thumb Code    74  yc11xx_gpio.o(.text)
+    GPIO_SetGpioMultFunction                 0x00000b7f   Thumb Code    22  yc11xx_gpio.o(.text)
+    GPIO_GetInputStatusWithJitter            0x00000b95   Thumb Code    58  yc11xx_gpio.o(.text)
+    GPIO_CheckGpioIsInputFunction            0x00000bcf   Thumb Code    32  yc11xx_gpio.o(.text)
+    HW_REG_24BIT                             0x00000c05   Thumb Code    30  yc_drv_common.o(.text)
+    HW_REG_16BIT                             0x00000c23   Thumb Code    18  yc_drv_common.o(.text)
+    HR_REG_16BIT                             0x00000c35   Thumb Code    34  yc_drv_common.o(.text)
+    HR_REG_24BIT                             0x00000c57   Thumb Code    36  yc_drv_common.o(.text)
+    xmemcpy                                  0x00000c7b   Thumb Code    36  yc_drv_common.o(.text)
+    xstrlen                                  0x00000c9f   Thumb Code    20  yc_drv_common.o(.text)
+    error_handle                             0x00000cb3   Thumb Code     4  yc_drv_common.o(.text)
+    Lpm_LockLpm                              0x00000cb7   Thumb Code    24  yc_drv_common.o(.text)
+    Lpm_unLockLpm                            0x00000ccf   Thumb Code    24  yc_drv_common.o(.text)
+    Lpm_CheckLpmFlag                         0x00000ce7   Thumb Code    20  yc_drv_common.o(.text)
+    whileDelay                               0x00000cfb   Thumb Code    26  yc_drv_common.o(.text)
+    whileDelayshort                          0x00000d15   Thumb Code    28  yc_drv_common.o(.text)
+    xramcmp                                  0x00000d31   Thumb Code    44  yc_drv_common.o(.text)
+    xramcpy                                  0x00000d5d   Thumb Code    36  yc_drv_common.o(.text)
+    math_abs                                 0x00000d81   Thumb Code    14  yc_drv_common.o(.text)
+    SysTick_Config                           0x00000da5   Thumb Code    58  yc11xx_systick.o(.text)
+    SysTick_GetTick                          0x00000ddf   Thumb Code     6  yc11xx_systick.o(.text)
+    SysTick_IsTimeOut                        0x00000de5   Thumb Code     6  yc11xx_systick.o(.text)
+    SysTick_GetRelativeTime                  0x00000deb   Thumb Code     6  yc11xx_systick.o(.text)
+    SYS_TimerExpireDefaultHandle             0x00000dfd   Thumb Code     6  yc_timer.o(.text)
+    SYS_TimerGet1usTicks                     0x00000e03   Thumb Code    58  yc_timer.o(.text)
+    SYS_ChangeDPLL                           0x00000e3d   Thumb Code    70  yc_timer.o(.text)
+    SYS_ChangeToFastDPLL                     0x00000e83   Thumb Code   116  yc_timer.o(.text)
+    SYS_ChangeToNormalDPLL                   0x00000ef7   Thumb Code   116  yc_timer.o(.text)
+    SystemCheckInFastSpeed                   0x00000f6b   Thumb Code     6  yc_timer.o(.text)
+    SYS_ClkTicks                             0x00000f71   Thumb Code   126  yc_timer.o(.text)
+    SYS_TimerStartTickTimer                  0x00000fef   Thumb Code    16  yc_timer.o(.text)
+    SYS_TimerInit                            0x00000fff   Thumb Code    52  yc_timer.o(.text)
+    SYS_TimerisExist                         0x00001033   Thumb Code    46  yc_timer.o(.text)
+    SYS_SetTimer                             0x00001061   Thumb Code   118  yc_timer.o(.text)
+    SYS_ResetTimer                           0x000010d7   Thumb Code    56  yc_timer.o(.text)
+    SYS_TimerTest                            0x0000110f   Thumb Code    20  yc_timer.o(.text)
+    SYS_ReleaseTimer                         0x00001123   Thumb Code    82  yc_timer.o(.text)
+    SYS_timerPolling                         0x00001175   Thumb Code    96  yc_timer.o(.text)
+    SYS_ReleaseAllTimer                      0x000011d5   Thumb Code    86  yc_timer.o(.text)
+    SYStick_handle                           0x0000122b   Thumb Code    14  yc_timer.o(.text)
+    Bt_100ms_timer                           0x00001239   Thumb Code    16  yc_timer.o(.text)
+    SYS_delay_us                             0x00001249   Thumb Code    76  yc_timer.o(.text)
+    SYS_delay_ms                             0x00001295   Thumb Code    18  yc_timer.o(.text)
+    IpcDefaultCallBack                       0x000012c5   Thumb Code    12  yc11xx_bt.o(.text)
+    IPC_Initialize                           0x000012d1   Thumb Code    16  yc11xx_bt.o(.text)
+    IPC_init                                 0x000012e1   Thumb Code     6  yc11xx_bt.o(.text)
+    IPC_TxBufferIsEnough                     0x00001537   Thumb Code   204  yc11xx_bt.o(.text)
+    IPC_WaitBufferEnough                     0x00001603   Thumb Code    36  yc11xx_bt.o(.text)
+    IPC_TxCommon                             0x00001627   Thumb Code    98  yc11xx_bt.o(.text)
+    IPC_TxPacket                             0x00001689   Thumb Code    76  yc11xx_bt.o(.text)
+    IPC_TxControlCmd                         0x000016d5   Thumb Code    48  yc11xx_bt.o(.text)
+    IPC_GetBBDIsconnectReason                0x00001705   Thumb Code     4  yc11xx_bt.o(.text)
+    IPC_CheckServerConenct                   0x00001709   Thumb Code     4  yc11xx_bt.o(.text)
+    IPC_CheckReconnect                       0x0000170d   Thumb Code     4  yc11xx_bt.o(.text)
+    IPC_WaitLpm                              0x00001711   Thumb Code    20  yc11xx_bt.o(.text)
+    IPC_AbandonLpm                           0x00001725   Thumb Code     8  yc11xx_bt.o(.text)
+    IPC_DisableLpm                           0x0000172d   Thumb Code     8  yc11xx_bt.o(.text)
+    IPC_EnableLpm                            0x00001735   Thumb Code     8  yc11xx_bt.o(.text)
+    IPC_IsTxBuffEmpty                        0x0000173d   Thumb Code   110  yc11xx_bt.o(.text)
+    IPC_IsRxBuffEmpty                        0x000017ab   Thumb Code   110  yc11xx_bt.o(.text)
+    IPC_HandleRxPacket                       0x00001819   Thumb Code    80  yc11xx_bt.o(.text)
+    uart_txChar                              0x0000188d   Thumb Code    76  yc_debug.o(.text)
+    uart_txBuffer                            0x000018d9   Thumb Code    24  yc_debug.o(.text)
+    init_print_log                           0x000018f1   Thumb Code   460  yc_debug.o(.text)
+    init_debugUart                           0x00001abd   Thumb Code   300  yc_debug.o(.text)
+    yichip_debug_uart_protocol               0x00001be9   Thumb Code    48  yc_debug.o(.text)
+    print_log_free_lock                      0x00001c19   Thumb Code    10  yc_debug.o(.text)
+    print_log_get_lock                       0x00001c23   Thumb Code    40  yc_debug.o(.text)
+    print_log_to_uart                        0x00001c4b   Thumb Code   270  yc_debug.o(.text)
+    debugUart_pollTx                         0x00001d59   Thumb Code     8  yc_debug.o(.text)
+    write_long_value                         0x00001d61   Thumb Code    20  yc_debug.o(.text)
+    print_round_buffer                       0x00001d75   Thumb Code   106  yc_debug.o(.text)
+    print_log_buffer_is_empty                0x00001ddf   Thumb Code    38  yc_debug.o(.text)
+    print_log                                0x00001e05   Thumb Code   308  yc_debug.o(.text)
+    print_string_to_uart                     0x00001f39   Thumb Code    74  yc_debug.o(.text)
+    print_string                             0x00001f83   Thumb Code    40  yc_debug.o(.text)
+    print_string_log_raw                     0x00001fab   Thumb Code   786  yc_debug.o(.text)
+    print_string_log                         0x000022bd   Thumb Code    28  yc_debug.o(.text)
+    print_protocol_to_uart                   0x000022d9   Thumb Code   120  yc_debug.o(.text)
+    print_hci_h4_to_uart                     0x00002351   Thumb Code    98  yc_debug.o(.text)
+    print_string_empty_fuction               0x000023b3   Thumb Code     2  yc_debug.o(.text)
+    HREAD                                    0x000023c9   Thumb Code    34  yc11xx.o(.text)
+    HWRITE                                   0x000023eb   Thumb Code    18  yc11xx.o(.text)
+    arch_printk_char_out                     0x00002401   Thumb Code     6  printk.o(.text)
+    __printk_hook_install                    0x00002407   Thumb Code     6  printk.o(.text)
+    __printk_get_hook                        0x0000240d   Thumb Code     6  printk.o(.text)
+    z_vprintk                                0x00002543   Thumb Code   668  printk.o(.text)
+    vprintk                                  0x00002811   Thumb Code    24  printk.o(.text)
+    z_impl_k_str_out                         0x00002829   Thumb Code    26  printk.o(.text)
+    printk                                   0x00002843   Thumb Code    28  printk.o(.text)
+    vsnprintk                                0x0000289d   Thumb Code    54  printk.o(.text)
+    snprintk                                 0x000028d3   Thumb Code    40  printk.o(.text)
+    net_buf_pool_get                         0x00002a19   Thumb Code     2  buf.o(.text)
+    net_buf_id                               0x00002a1d   Thumb Code    24  buf.o(.text)
+    net_buf_reset                            0x00002a35   Thumb Code    14  buf.o(.text)
+    net_buf_alloc_len_debug                  0x00002aeb   Thumb Code   376  buf.o(.text)
+    net_buf_alloc_fixed_debug                0x00002c63   Thumb Code    34  buf.o(.text)
+    net_buf_simple_init_with_data            0x00002c85   Thumb Code    10  buf.o(.text)
+    net_buf_alloc_with_data_debug            0x00002c8f   Thumb Code    56  buf.o(.text)
+    net_buf_is_empty                         0x00002cc7   Thumb Code    40  buf.o(.text)
+    net_buf_get_debug                        0x00002cef   Thumb Code   128  buf.o(.text)
+    net_buf_simple_reserve                   0x00002d6f   Thumb Code    42  buf.o(.text)
+    net_buf_slist_put                        0x00002d99   Thumb Code    78  buf.o(.text)
+    net_buf_slist_get                        0x00002de7   Thumb Code    60  buf.o(.text)
+    net_buf_put                              0x00002e23   Thumb Code    38  buf.o(.text)
+    net_buf_unref_debug                      0x00002e49   Thumb Code   700  buf.o(.text)
+    net_buf_ref                              0x00003105   Thumb Code    46  buf.o(.text)
+    net_buf_simple_add                       0x00003133   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_mem                   0x00003169   Thumb Code    56  buf.o(.text)
+    net_buf_simple_headroom                  0x000031a1   Thumb Code    10  buf.o(.text)
+    net_buf_clone                            0x000031ab   Thumb Code   160  buf.o(.text)
+    net_buf_frag_last                        0x0000324b   Thumb Code    12  buf.o(.text)
+    net_buf_frag_insert                      0x00003257   Thumb Code    26  buf.o(.text)
+    net_buf_frag_add                         0x00003271   Thumb Code    36  buf.o(.text)
+    net_buf_frag_del_debug                   0x00003295   Thumb Code    40  buf.o(.text)
+    net_buf_linearize                        0x000032bd   Thumb Code   104  buf.o(.text)
+    net_buf_simple_tailroom                  0x00003325   Thumb Code    20  buf.o(.text)
+    net_buf_append_bytes                     0x00003339   Thumb Code   114  buf.o(.text)
+    net_buf_simple_clone                     0x000033ab   Thumb Code    12  buf.o(.text)
+    net_buf_simple_add_u8                    0x000033b7   Thumb Code    50  buf.o(.text)
+    net_buf_simple_add_le16                  0x000033e9   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_be16                  0x0000341f   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_le24                  0x00003455   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_be24                  0x0000348b   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_le32                  0x000034c1   Thumb Code    54  buf.o(.text)
+    net_buf_simple_add_be32                  0x000034f7   Thumb Code   468  buf.o(.text)
+    net_buf_simple_add_le48                  0x000036cb   Thumb Code    60  buf.o(.text)
+    net_buf_simple_add_be48                  0x00003707   Thumb Code    60  buf.o(.text)
+    net_buf_simple_add_le64                  0x00003743   Thumb Code    60  buf.o(.text)
+    net_buf_simple_add_be64                  0x0000377f   Thumb Code    60  buf.o(.text)
+    net_buf_simple_push                      0x000037bb   Thumb Code    50  buf.o(.text)
+    net_buf_simple_push_le16                 0x000037ed   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_be16                 0x00003823   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_u8                   0x00003859   Thumb Code    20  buf.o(.text)
+    net_buf_simple_push_le24                 0x0000386d   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_be24                 0x000038a3   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_le32                 0x000038d9   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_be32                 0x0000390f   Thumb Code    54  buf.o(.text)
+    net_buf_simple_push_le48                 0x00003945   Thumb Code    60  buf.o(.text)
+    net_buf_simple_push_be48                 0x00003981   Thumb Code    60  buf.o(.text)
+    net_buf_simple_push_le64                 0x000039bd   Thumb Code    60  buf.o(.text)
+    net_buf_simple_push_be64                 0x000039f9   Thumb Code    60  buf.o(.text)
+    net_buf_simple_pull                      0x00003a35   Thumb Code    48  buf.o(.text)
+    net_buf_simple_pull_mem                  0x00003a65   Thumb Code   904  buf.o(.text)
+    net_buf_simple_pull_u8                   0x00003ded   Thumb Code    20  buf.o(.text)
+    net_buf_simple_pull_le16                 0x00003e01   Thumb Code    30  buf.o(.text)
+    net_buf_simple_pull_be16                 0x00003e1f   Thumb Code    36  buf.o(.text)
+    net_buf_simple_pull_le24                 0x00003e43   Thumb Code    38  buf.o(.text)
+    net_buf_simple_pull_be24                 0x00003e69   Thumb Code    58  buf.o(.text)
+    net_buf_simple_pull_le32                 0x00003ea3   Thumb Code    28  buf.o(.text)
+    net_buf_simple_pull_be32                 0x00003ebf   Thumb Code    50  buf.o(.text)
+    net_buf_simple_pull_le48                 0x00003ef1   Thumb Code    60  buf.o(.text)
+    net_buf_simple_pull_be48                 0x00003f2d   Thumb Code   194  buf.o(.text)
+    net_buf_simple_pull_le64                 0x00003fef   Thumb Code    36  buf.o(.text)
+    net_buf_simple_pull_be64                 0x00004013   Thumb Code   150  buf.o(.text)
+    z_queue_node_peek                        0x000041b3   Thumb Code    44  queue.o(.text)
+    z_impl_k_queue_init                      0x000041df   Thumb Code    12  queue.o(.text)
+    z_impl_k_queue_cancel_wait               0x000041ed   Thumb Code     2  queue.o(.text)
+    k_queue_insert                           0x0000422d   Thumb Code    22  queue.o(.text)
+    k_queue_append                           0x00004243   Thumb Code    28  queue.o(.text)
+    k_queue_prepend                          0x0000425f   Thumb Code    20  queue.o(.text)
+    z_impl_k_queue_alloc_append              0x00004273   Thumb Code    28  queue.o(.text)
+    z_impl_k_queue_alloc_prepend             0x0000428f   Thumb Code    20  queue.o(.text)
+    k_queue_append_list                      0x000042a3   Thumb Code    86  queue.o(.text)
+    k_queue_merge_slist                      0x000042f9   Thumb Code    66  queue.o(.text)
+    z_impl_k_queue_get                       0x0000433b   Thumb Code   106  queue.o(.text)
+    k_queue_get                              0x000043a5   Thumb Code    16  queue.o(.text)
+    k_mem_pool_free                          0x000043df   Thumb Code     2  mempool.o(.text)
+    k_mem_pool_malloc                        0x000043e1   Thumb Code     6  mempool.o(.text)
+    k_free                                   0x000043e7   Thumb Code     2  mempool.o(.text)
+    z_thread_malloc                          0x000043e9   Thumb Code     4  mempool.o(.text)
+    char2hex                                 0x000043ed   Thumb Code    60  hex.o(.text)
+    hex2char                                 0x00004429   Thumb Code    36  hex.o(.text)
+    bin2hex                                  0x0000444d   Thumb Code    86  hex.o(.text)
+    hex2bin                                  0x000044a3   Thumb Code   140  hex.o(.text)
+    bt_hex_real                              0x00004531   Thumb Code    72  log.o(.text)
+    bt_addr_str_real                         0x00004579   Thumb Code    48  log.o(.text)
+    bt_addr_le_str_real                      0x000045a9   Thumb Code    18  log.o(.text)
+    bt_uuid_str_real                         0x000045bb   Thumb Code    18  log.o(.text)
+    create_free_list                         0x000046d5   Thumb Code    56  mem_slab.o(.text)
+    k_mem_slab_init                          0x0000470d   Thumb Code    44  mem_slab.o(.text)
+    k_mem_slab_alloc                         0x00004739   Thumb Code    38  mem_slab.o(.text)
+    k_mem_slab_free                          0x0000475f   Thumb Code    18  mem_slab.o(.text)
+    cmd_state_set_init                       0x00004931   Thumb Code     8  hci_core.o(.text)
+    bt_rand                                  0x00004939   Thumb Code     6  hci_core.o(.text)
+    bt_hci_cmd_create                        0x000049c3   Thumb Code   170  hci_core.o(.text)
+    bt_send                                  0x00004a6d   Thumb Code    54  hci_core.o(.text)
+    bt_hci_cmd_send                          0x00004aa3   Thumb Code   130  hci_core.o(.text)
+    bt_hci_cmd_send_sync                     0x00004b25   Thumb Code    32  hci_core.o(.text)
+    bt_lookup_id_addr                        0x00004b45   Thumb Code     6  hci_core.o(.text)
+    bt_adv_lookup_legacy                     0x00004b63   Thumb Code     6  hci_core.o(.text)
+    bt_addr_from_str                         0x00004d17   Thumb Code   418  hci_core.o(.text)
+    bt_addr_le_from_str                      0x00004eb9   Thumb Code   156  hci_core.o(.text)
+    bt_le_create_conn_cancel                 0x000050d7   Thumb Code    56  hci_core.o(.text)
+    bt_le_scan_random_addr_check             0x00005211   Thumb Code    38  hci_core.o(.text)
+    bt_le_create_conn_ext                    0x00005651   Thumb Code   636  hci_core.o(.text)
+    bt_le_create_conn_legacy                 0x000058cd   Thumb Code   228  hci_core.o(.text)
+    bt_le_create_conn                        0x000059b1   Thumb Code    12  hci_core.o(.text)
+    bt_hci_disconnect                        0x000059bd   Thumb Code    56  hci_core.o(.text)
+    bt_le_scan_update                        0x00005b9b   Thumb Code   118  hci_core.o(.text)
+    bt_le_set_data_len                       0x00005de3   Thumb Code    74  hci_core.o(.text)
+    bt_le_set_phy                            0x00005e2d   Thumb Code    82  hci_core.o(.text)
+    bt_le_conn_params_valid                  0x0000637d   Thumb Code    84  hci_core.o(.text)
+    bt_unpair                                0x00006789   Thumb Code    40  hci_core.o(.text)
+    bt_data_parse                            0x000069f3   Thumb Code   106  hci_core.o(.text)
+    bt_hci_get_conn_handle                   0x00006e9d   Thumb Code    22  hci_core.o(.text)
+    bt_addr_le_create_static                 0x0000747f   Thumb Code    32  hci_core.o(.text)
+    bt_finalize_init                         0x000076c3   Thumb Code    48  hci_core.o(.text)
+    bt_addr_le_create_nrpa                   0x00007ba7   Thumb Code    32  hci_core.o(.text)
+    hci_event_prio                           0x00007c13   Thumb Code   346  hci_core.o(.text)
+    bt_recv                                  0x00007d6d   Thumb Code    84  hci_core.o(.text)
+    bt_hci_driver_register                   0x00007dc1   Thumb Code    86  hci_core.o(.text)
+    bt_polling_work                          0x00007ef9   Thumb Code    12  hci_core.o(.text)
+    bt_set_name                              0x00007f05   Thumb Code     8  hci_core.o(.text)
+    bt_enable                                0x00007f0d   Thumb Code   152  hci_core.o(.text)
+    bt_get_name                              0x000082a9   Thumb Code     4  hci_core.o(.text)
+    bt_id_create                             0x000082ad   Thumb Code   140  hci_core.o(.text)
+    bt_set_id_addr                           0x00008339   Thumb Code    66  hci_core.o(.text)
+    bt_id_get                                0x0000837b   Thumb Code    42  hci_core.o(.text)
+    bt_id_reset                              0x000083a5   Thumb Code   208  hci_core.o(.text)
+    bt_id_delete                             0x00008475   Thumb Code   150  hci_core.o(.text)
+    bt_setup_public_id_addr                  0x0000850b   Thumb Code    10  hci_core.o(.text)
+    bt_setup_random_id_addr                  0x00008515   Thumb Code    12  hci_core.o(.text)
+    bt_addr_le_is_bonded                     0x00008521   Thumb Code     6  hci_core.o(.text)
+    bt_le_per_adv_set_param                  0x00008527   Thumb Code   196  hci_core.o(.text)
+    bt_le_per_adv_set_data                   0x000085eb   Thumb Code   278  hci_core.o(.text)
+    bt_le_per_adv_start                      0x00008789   Thumb Code    14  hci_core.o(.text)
+    bt_le_per_adv_stop                       0x00008797   Thumb Code    14  hci_core.o(.text)
+    bt_le_adv_update_data                    0x00008983   Thumb Code    88  hci_core.o(.text)
+    bt_le_adv_start_legacy                   0x00008b89   Thumb Code   590  hci_core.o(.text)
+    bt_le_adv_start_ext                      0x00008ff9   Thumb Code   254  hci_core.o(.text)
+    bt_le_adv_start                          0x000090f7   Thumb Code    62  hci_core.o(.text)
+    bt_le_adv_stop                           0x00009135   Thumb Code   130  hci_core.o(.text)
+    bt_le_scan_start                         0x0000920f   Thumb Code   184  hci_core.o(.text)
+    bt_le_scan_stop                          0x000092c7   Thumb Code    34  hci_core.o(.text)
+    bt_le_scan_cb_register                   0x000092e9   Thumb Code    16  hci_core.o(.text)
+    bt_le_set_chan_map                       0x000092f9   Thumb Code   112  hci_core.o(.text)
+    bt_buf_get_rx                            0x00009369   Thumb Code    48  hci_core.o(.text)
+    bt_buf_get_cmd_complete                  0x00009399   Thumb Code   226  hci_core.o(.text)
+    bt_buf_get_evt                           0x0000947b   Thumb Code    80  hci_core.o(.text)
+    bt_le_oob_get_local                      0x000094cb   Thumb Code    62  hci_core.o(.text)
+    bt_uuid_cmp                              0x00009787   Thumb Code    86  uuid.o(.text)
+    bt_uuid_create                           0x000097dd   Thumb Code    94  uuid.o(.text)
+    bt_uuid_to_str                           0x0000983b   Thumb Code   194  uuid.o(.text)
+    bt_att_req_free                          0x00009a6d   Thumb Code    38  att.o(.text)
+    att_sent                                 0x00009ad5   Thumb Code    54  att.o(.text)
+    bt_att_chan_create_pdu                   0x0000a041   Thumb Code   150  att.o(.text)
+    bt_att_create_pdu                        0x0000a203   Thumb Code   182  att.o(.text)
+    bt_att_accept                            0x0000c127   Thumb Code   136  att.o(.text)
+    bt_att_init                              0x0000c231   Thumb Code    26  att.o(.text)
+    bt_att_get_mtu                           0x0000c24b   Thumb Code   138  att.o(.text)
+    bt_att_req_alloc                         0x0000c2d5   Thumb Code    64  att.o(.text)
+    bt_att_send                              0x0000c315   Thumb Code   240  att.o(.text)
+    bt_att_req_send                          0x0000c405   Thumb Code   626  att.o(.text)
+    bt_att_req_cancel                        0x0000c695   Thumb Code   196  att.o(.text)
+    bt_conn_get_pkts                         0x0000c961   Thumb Code     6  conn.o(.text)
+    notify_le_param_updated                  0x0000c9f1   Thumb Code   110  conn.o(.text)
+    le_param_req                             0x0000ca5f   Thumb Code    70  conn.o(.text)
+    bt_conn_le_conn_update                   0x0000caa5   Thumb Code    96  conn.o(.text)
+    bt_conn_unref                            0x0000ccb7   Thumb Code    62  conn.o(.text)
+    bt_conn_new                              0x0000cf01   Thumb Code    74  conn.o(.text)
+    bt_conn_get_security                     0x0000cf63   Thumb Code     6  conn.o(.text)
+    bt_conn_cb_register                      0x0000cf69   Thumb Code    12  conn.o(.text)
+    bt_conn_reset_rx_state                   0x0000cf75   Thumb Code    30  conn.o(.text)
+    bt_conn_recv                             0x0000cf93   Thumb Code   496  conn.o(.text)
+    bt_conn_send_cb                          0x0000d1d3   Thumb Code   248  conn.o(.text)
+    bt_conn_create_pdu_timeout_debug         0x0000d705   Thumb Code   174  conn.o(.text)
+    bt_conn_create_frag_timeout_debug        0x0000d7b3   Thumb Code    30  conn.o(.text)
+    bt_conn_prepare_events                   0x0000d9a1   Thumb Code   452  conn.o(.text)
+    bt_conn_process_tx                       0x0000db65   Thumb Code   126  conn.o(.text)
+    bt_conn_ref                              0x0000dbe3   Thumb Code    62  conn.o(.text)
+    bt_conn_is_peer_addr_le                  0x0000dc21   Thumb Code    86  conn.o(.text)
+    bt_conn_lookup_addr_le                   0x0000dc77   Thumb Code    94  conn.o(.text)
+    bt_conn_exists_le                        0x0000dcd5   Thumb Code    68  conn.o(.text)
+    bt_conn_add_le                           0x0000dd19   Thumb Code    50  conn.o(.text)
+    conn_lookup_handle                       0x0000dd9f   Thumb Code   112  conn.o(.text)
+    conn_lookup_iso                          0x0000de0f   Thumb Code     6  conn.o(.text)
+    bt_conn_set_state                        0x0000de15   Thumb Code   602  conn.o(.text)
+    bt_conn_lookup_handle                    0x0000e06f   Thumb Code    28  conn.o(.text)
+    bt_conn_lookup_state_le                  0x0000e08b   Thumb Code   128  conn.o(.text)
+    bt_conn_foreach                          0x0000e10b   Thumb Code    74  conn.o(.text)
+    bt_conn_get_dst                          0x0000e155   Thumb Code     8  conn.o(.text)
+    bt_conn_get_info                         0x0000e15d   Thumb Code    94  conn.o(.text)
+    bt_conn_get_remote_info                  0x0000e1bb   Thumb Code    60  conn.o(.text)
+    bt_conn_le_param_update                  0x0000e21b   Thumb Code   128  conn.o(.text)
+    bt_le_set_auto_conn                      0x0000e2b5   Thumb Code   240  conn.o(.text)
+    bt_conn_disconnect                       0x0000e3a5   Thumb Code   248  conn.o(.text)
+    bt_conn_le_create                        0x0000e4f3   Thumb Code   276  conn.o(.text)
+    bt_conn_index                            0x0000e607   Thumb Code    26  conn.o(.text)
+    bt_conn_lookup_index                     0x0000e621   Thumb Code    42  conn.o(.text)
+    bt_conn_init                             0x0000e64b   Thumb Code   146  conn.o(.text)
+    bt_conn_tx_polling                       0x0000e6dd   Thumb Code    46  conn.o(.text)
+    bt_gatt_foreach_attr_type                0x0000e921   Thumb Code    54  gatt.o(.text)
+    bt_gatt_attr_read                        0x0000e97f   Thumb Code    84  gatt.o(.text)
+    bt_gatt_init                             0x0000eceb   Thumb Code   390  gatt.o(.text)
+    bt_gatt_attr_read_service                0x0000ee71   Thumb Code    76  gatt.o(.text)
+    bt_gatt_attr_get_handle                  0x0000eefb   Thumb Code    24  gatt.o(.text)
+    bt_gatt_attr_read_included               0x0000ef13   Thumb Code    90  gatt.o(.text)
+    bt_gatt_attr_value_handle                0x0000ef6d   Thumb Code    54  gatt.o(.text)
+    bt_gatt_attr_read_chrc                   0x0000efa3   Thumb Code   104  gatt.o(.text)
+    bt_gatt_attr_next                        0x0000f07f   Thumb Code    34  gatt.o(.text)
+    bt_gatt_attr_read_ccc                    0x0000f0e7   Thumb Code    64  gatt.o(.text)
+    bt_gatt_attr_write_ccc                   0x0000f181   Thumb Code   262  gatt.o(.text)
+    bt_gatt_attr_read_cep                    0x0000f287   Thumb Code   154  gatt.o(.text)
+    bt_gatt_attr_read_cud                    0x0000f321   Thumb Code    44  gatt.o(.text)
+    bt_gatt_attr_read_cpf                    0x0000f34d   Thumb Code    42  gatt.o(.text)
+    bt_gatt_notify_cb                        0x0000f619   Thumb Code   212  gatt.o(.text)
+    bt_gatt_indicate                         0x0000f6ed   Thumb Code   392  gatt.o(.text)
+    bt_gatt_get_mtu                          0x0000f875   Thumb Code    12  gatt.o(.text)
+    bt_gatt_check_perm                       0x0000f881   Thumb Code   106  gatt.o(.text)
+    bt_gatt_is_subscribed                    0x0000fb63   Thumb Code   176  gatt.o(.text)
+    bt_gatt_cancel                           0x0000ff23   Thumb Code    16  gatt.o(.text)
+    bt_gatt_unsubscribe                      0x0000ff33   Thumb Code   276  gatt.o(.text)
+    bt_gatt_notification                     0x00010047   Thumb Code   274  gatt.o(.text)
+    bt_gatt_mult_notification                0x00010159   Thumb Code   324  gatt.o(.text)
+    bt_gatt_exchange_mtu                     0x00010391   Thumb Code   106  gatt.o(.text)
+    bt_gatt_discover                         0x000110db   Thumb Code   214  gatt.o(.text)
+    bt_gatt_read                             0x0001143d   Thumb Code   152  gatt.o(.text)
+    bt_gatt_write_without_response_cb        0x000115fd   Thumb Code   198  gatt.o(.text)
+    bt_gatt_write                            0x000117cb   Thumb Code   372  gatt.o(.text)
+    bt_gatt_subscribe                        0x0001198f   Thumb Code   214  gatt.o(.text)
+    bt_gatt_resubscribe                      0x00011a65   Thumb Code   134  gatt.o(.text)
+    bt_gatt_connected                        0x00011ddf   Thumb Code    60  gatt.o(.text)
+    bt_gatt_encrypt_change                   0x00011e1b   Thumb Code    50  gatt.o(.text)
+    bt_gatt_change_aware                     0x00011e4d   Thumb Code     6  gatt.o(.text)
+    bt_gatt_clear                            0x00011f95   Thumb Code    36  gatt.o(.text)
+    bt_gatt_disconnected                     0x00011fb9   Thumb Code    54  gatt.o(.text)
+    bt_l2cap_send_cb                         0x000120c9   Thumb Code   106  l2cap.o(.text)
+    bt_l2cap_chan_remove                     0x00012153   Thumb Code   102  l2cap.o(.text)
+    bt_l2cap_chan_state_str                  0x000121b9   Thumb Code    42  l2cap.o(.text)
+    bt_l2cap_chan_del                        0x000121e3   Thumb Code    86  l2cap.o(.text)
+    bt_l2cap_chan_add                        0x0001226b   Thumb Code   112  l2cap.o(.text)
+    bt_l2cap_connected                       0x0001231f   Thumb Code   258  l2cap.o(.text)
+    bt_l2cap_disconnected                    0x00012421   Thumb Code   120  l2cap.o(.text)
+    bt_l2cap_create_pdu_timeout              0x00012499   Thumb Code    26  l2cap.o(.text)
+    bt_l2cap_security_changed                0x00012671   Thumb Code   136  l2cap.o(.text)
+    bt_l2cap_le_lookup_tx_cid                0x00012893   Thumb Code    92  l2cap.o(.text)
+    bt_l2cap_le_lookup_rx_cid                0x000128ef   Thumb Code    92  l2cap.o(.text)
+    bt_l2cap_recv                            0x00012bc7   Thumb Code   166  l2cap.o(.text)
+    bt_l2cap_update_conn_param               0x00012c6d   Thumb Code    94  l2cap.o(.text)
+    bt_l2cap_init                            0x00012d79   Thumb Code     2  l2cap.o(.text)
+    Bt_PowerOnBtWork                         0x00012f5d   Thumb Code     2  yc11xx_dev_bt.o(.text)
+    Bt_PowerOn                               0x00012f5f   Thumb Code     8  yc11xx_dev_bt.o(.text)
+    Bt_Init                                  0x00012f67   Thumb Code    22  yc11xx_dev_bt.o(.text)
+    Bt_Reset                                 0x00012f7d   Thumb Code    18  yc11xx_dev_bt.o(.text)
+    Bt_PowerResetWork                        0x00012f8f   Thumb Code    48  yc11xx_dev_bt.o(.text)
+    Bt_EvtCallBack                           0x00012fbf   Thumb Code    86  yc11xx_dev_bt.o(.text)
+    Bt_HciFifoInit                           0x00013015   Thumb Code    12  yc11xx_dev_bt.o(.text)
+    Bt_HciGetSendBufferPtr                   0x00013021   Thumb Code    14  yc11xx_dev_bt.o(.text)
+    Bt_HciFifoIn                             0x0001302f   Thumb Code    36  yc11xx_dev_bt.o(.text)
+    Bt_HciFifoOut                            0x00013053   Thumb Code    36  yc11xx_dev_bt.o(.text)
+    Bt_HciCheckBufferFull                    0x00013077   Thumb Code    16  yc11xx_dev_bt.o(.text)
+    Bt_HciParseEvt                           0x00013087   Thumb Code    78  yc11xx_dev_bt.o(.text)
+    Bt_HciParseCmd                           0x000130d5   Thumb Code    20  yc11xx_dev_bt.o(.text)
+    Bt_SndToBtData                           0x000130e9   Thumb Code    50  yc11xx_dev_bt.o(.text)
+    Bt_HciCallback                           0x00013167   Thumb Code   208  yc11xx_dev_bt.o(.text)
+    Bt_ACLCallbackClassic                    0x00013237   Thumb Code    92  yc11xx_dev_bt.o(.text)
+    Bt_ACLCallbackBle                        0x00013293   Thumb Code    78  yc11xx_dev_bt.o(.text)
+    Bt_DataBufferCallBack                    0x000132e1   Thumb Code   396  yc11xx_dev_bt.o(.text)
+    Bt_CheckPowerOn                          0x0001346d   Thumb Code    16  yc11xx_dev_bt.o(.text)
+    Bt_StartWork                             0x0001347d   Thumb Code    14  yc11xx_dev_bt.o(.text)
+    Bt_ActionBeforeHibernate                 0x0001348b   Thumb Code   132  yc11xx_dev_bt.o(.text)
+    Bt_ActionBeforeLpm                       0x0001350f   Thumb Code     8  yc11xx_dev_bt.o(.text)
+    Bt_SndCmdPwroff                          0x00013517   Thumb Code    80  yc11xx_dev_bt.o(.text)
+    Bt_HciParseRcvData                       0x00013567   Thumb Code   108  yc11xx_dev_bt.o(.text)
+    Bt_SndHciToRespin                        0x000135d3   Thumb Code    58  yc11xx_dev_bt.o(.text)
+    ipc_bt_hci_init                          0x000136e5   Thumb Code    10  yc11xx_dev_bt.o(.text)
+    __aeabi_uidiv                            0x0001379d   Thumb Code     0  uidiv.o(.text)
+    __aeabi_uidivmod                         0x0001379d   Thumb Code    44  uidiv.o(.text)
+    __aeabi_idiv                             0x000137c9   Thumb Code     0  idiv.o(.text)
+    __aeabi_idivmod                          0x000137c9   Thumb Code    40  idiv.o(.text)
+    ___aeabi_memcpy8$ret                     0x000137f1   Thumb Code     0  memcpy.o(.text)
+    __aeabi_memcpy                           0x000137f1   Thumb Code    40  memcpy.o(.text)
+    __aeabi_memcpy4                          0x000137f1   Thumb Code     0  memcpy.o(.text)
+    memcpy                                   0x000137f1   Thumb Code     0  memcpy.o(.text)
+    __aeabi_memset                           0x00013819   Thumb Code    14  memseta.o(.text)
+    __aeabi_memset4                          0x00013819   Thumb Code     0  memseta.o(.text)
+    __aeabi_memset8                          0x00013819   Thumb Code     0  memseta.o(.text)
+    __aeabi_memclr                           0x00013827   Thumb Code     4  memseta.o(.text)
+    __aeabi_memclr4                          0x00013827   Thumb Code     0  memseta.o(.text)
+    __aeabi_memclr8                          0x00013827   Thumb Code     0  memseta.o(.text)
+    _memset$wrapper                          0x0001382b   Thumb Code    18  memseta.o(.text)
+    strlen                                   0x0001383d   Thumb Code    14  strlen.o(.text)
+    strcmp                                   0x0001384b   Thumb Code    28  strcmp.o(.text)
+    memcmp                                   0x00013867   Thumb Code    26  memcmp.o(.text)
+    strcpy                                   0x00013881   Thumb Code    18  strcpy.o(.text)
+    __aeabi_uread4                           0x00013893   Thumb Code    20  uread4.o(.text)
+    __rt_uread4                              0x00013893   Thumb Code     0  uread4.o(.text)
+    _uread4                                  0x00013893   Thumb Code     0  uread4.o(.text)
+    __aeabi_uread8                           0x000138a7   Thumb Code    28  uread8.o(.text)
+    __rt_uread8                              0x000138a7   Thumb Code     0  uread8.o(.text)
+    _uread8                                  0x000138a7   Thumb Code     0  uread8.o(.text)
+    __scatterload                            0x000138c5   Thumb Code    28  init.o(.text)
+    __scatterload_rt2                        0x000138c5   Thumb Code     0  init.o(.text)
+    __decompress                             0x000138e9   Thumb Code     0  __dczerorl2.o(.text)
+    __decompress1                            0x000138e9   Thumb Code    86  __dczerorl2.o(.text)
+    __ARM_common_switch8                     0x0001393f   Thumb Code    28  printk.o(i.__ARM_common_switch8)
+    __scatterload_copy                       0x0001395b   Thumb Code    14  handlers.o(i.__scatterload_copy)
+    __scatterload_null                       0x00013969   Thumb Code     2  handlers.o(i.__scatterload_null)
+    __scatterload_zeroinit                   0x0001396b   Thumb Code    14  handlers.o(i.__scatterload_zeroinit)
+    _1_gatt_svc                              0x00013978   Data           8  gatt.o(._bt_gatt_service_static.static._1_gatt_svc)
+    _2_gap_svc                               0x00013980   Data           8  gatt.o(._bt_gatt_service_static.static._2_gap_svc)
+    att_fixed_chan                           0x00013988   Data          12  att.o(._bt_l2cap_fixed_chan.static.att_fixed_chan)
+    le_fixed_chan                            0x00013994   Data          12  l2cap.o(._bt_l2cap_fixed_chan.static.le_fixed_chan)
+    net_buf_fixed_cb                         0x00013a1c   Data          12  buf.o(.constdata)
+    attr__2_gap_svc                          0x00013ef0   Data         100  gatt.o(.constdata)
+    attr__1_gatt_svc                         0x00013f54   Data          20  gatt.o(.constdata)
+    Region$$Table$$Base                      0x000142bc   Number         0  anon$$obj.o(Region$$Table)
+    Region$$Table$$Limit                     0x000142dc   Number         0  anon$$obj.o(Region$$Table)
+    _k_mem_slab_buf_req_slab                 0x10010000   Data         144  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".0)
+    _k_mem_slab_buf_att_slab                 0x10010090   Data          28  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".1)
+    _k_mem_slab_buf_chan_slab                0x100100b0   Data         100  att.o(._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".2)
+    att_slab                                 0x10010114   Data          20  att.o(._k_mem_slab.static.att_slab)
+    chan_slab                                0x10010128   Data          20  att.o(._k_mem_slab.static.chan_slab)
+    req_slab                                 0x1001013c   Data          20  att.o(._k_mem_slab.static.req_slab)
+    free_tx                                  0x10010150   Data           8  conn.o(._k_queue.static.free_tx)
+    gTIPCHandleCb                            0x10010170   Data          52  main.o(.data)
+    gWdtInit                                 0x100101a4   Data           3  main.o(.data)
+    default_conn                             0x100101a8   Data           4  main.o(.data)
+    current_addr                             0x100101b0   Data           4  main.o(.data)
+    SystickCount                             0x100101c8   Data           4  yc11xx_systick.o(.data)
+    pheader                                  0x100101cc   Data           4  yc_timer.o(.data)
+    sys_tick_count                           0x100101d0   Data           4  yc_timer.o(.data)
+    gSystemTimerAdjustClknbt                 0x100101d4   Data           4  yc_timer.o(.data)
+    sys_Timer_Check_Flag                     0x100101d8   Data           1  yc_timer.o(.data)
+    gSystemInFastDpll                        0x100101d9   Data           1  yc_timer.o(.data)
+    gIPC_test                                0x100101e0   Data           1  yc11xx_bt.o(.data)
+    a2dpLen                                  0x100101e2   Data           2  yc11xx_bt.o(.data)
+    uartrxbuf                                0x100101e4   Data           2  yc_debug.o(.data)
+    txptr                                    0x100101e8   Data           4  yc_debug.o(.data)
+    log_bug_ptr                              0x100101ec   Data           4  yc_debug.o(.data)
+    log_initial_flag_ptr                     0x100101f0   Data           4  yc_debug.o(.data)
+    log_lock_flag_cm0_ptr                    0x100101f4   Data           4  yc_debug.o(.data)
+    log_lock_flag_respin_ptr                 0x100101f8   Data           4  yc_debug.o(.data)
+    log_lock_victim_ptr                      0x100101fc   Data           4  yc_debug.o(.data)
+    log_read_index_ptr                       0x10010200   Data           4  yc_debug.o(.data)
+    log_write_index_ptr                      0x10010204   Data           4  yc_debug.o(.data)
+    gHaltLogFlag                             0x10010208   Data           2  yc_debug.o(.data)
+    gHaltLogValue                            0x1001020a   Data           2  yc_debug.o(.data)
+    _char_out                                0x1001020c   Data           4  printk.o(.data)
+    gWorkInInitialWork                       0x10010268   Data           4  hci_core.o(.data)
+    gWorkInInitialWorkProcess                0x1001026c   Data           4  hci_core.o(.data)
+    header_Timer                             0x10010360   Data          24  yc_timer.o(.bss)
+    ipcCb                                    0x10010378   Data          40  yc11xx_bt.o(.bss)
+    ipcReadBuff                              0x100103a0   Data         254  yc11xx_bt.o(.bss)
+    ipcSendBuff                              0x1001049e   Data          40  yc11xx_bt.o(.bss)
+    uarttxbuf                                0x100104c6   Data          50  yc_debug.o(.bss)
+    bt_dev                                   0x100105d0   Data         192  hci_core.o(.bss)
+    _bt_l2cap_fixed_chan_list                0x10011b58   Data          24  conn.o(.bss)
+    gBRState                                 0x100135a8   Data          28  yc11xx_dev_bt.o(.bss)
+    gHciDataFifo                             0x100135c4   Data        4013  yc11xx_dev_bt.o(.bss)
+    __initial_sp                             0x1001b640   Number         0  startup.o ABSOLUTE
+
+
+
+==============================================================================
+
+Memory Map of the image
+
+  Image Entry point : 0x000000c1
+
+  Load Region LR_IROM1 (Base: 0x00000000, Size: 0x00014610, Max: 0x00080000, ABSOLUTE, COMPRESSED[0x00014398])
+
+    Execution Region ER_IROM1 (Exec base: 0x00000000, Load base: 0x00000000, Size: 0x000142dc, Max: 0x00080000, ABSOLUTE)
+
+    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
+
+    0x00000000   0x00000000   0x000000c0   Data   RO          214    RESET               startup.o
+    0x000000c0   0x000000c0   0x00000000   Code   RO         1253  * .ARM.Collect$$$$00000000  mc_p.l(entry.o)
+    0x000000c0   0x000000c0   0x00000004   Code   RO         1282    .ARM.Collect$$$$00000001  mc_p.l(entry2.o)
+    0x000000c4   0x000000c4   0x00000004   Code   RO         1285    .ARM.Collect$$$$00000004  mc_p.l(entry5.o)
+    0x000000c8   0x000000c8   0x00000000   Code   RO         1287    .ARM.Collect$$$$00000008  mc_p.l(entry7b.o)
+    0x000000c8   0x000000c8   0x00000000   Code   RO         1289    .ARM.Collect$$$$0000000A  mc_p.l(entry8b.o)
+    0x000000c8   0x000000c8   0x00000008   Code   RO         1290    .ARM.Collect$$$$0000000B  mc_p.l(entry9a.o)
+    0x000000d0   0x000000d0   0x00000000   Code   RO         1292    .ARM.Collect$$$$0000000D  mc_p.l(entry10a.o)
+    0x000000d0   0x000000d0   0x00000000   Code   RO         1294    .ARM.Collect$$$$0000000F  mc_p.l(entry11a.o)
+    0x000000d0   0x000000d0   0x00000004   Code   RO         1283    .ARM.Collect$$$$00002712  mc_p.l(entry2.o)
+    0x000000d4   0x000000d4   0x0000087c   Code   RO            1    .text               main.o
+    0x00000950   0x00000950   0x00000028   Code   RO          215    .text               startup.o
+    0x00000978   0x00000978   0x0000028c   Code   RO          220    .text               yc11xx_gpio.o
+    0x00000c04   0x00000c04   0x000001a0   Code   RO          251    .text               yc_drv_common.o
+    0x00000da4   0x00000da4   0x00000058   Code   RO          270    .text               yc11xx_systick.o
+    0x00000dfc   0x00000dfc   0x000004c8   Code   RO          288    .text               yc_timer.o
+    0x000012c4   0x000012c4   0x000005c8   Code   RO          340    .text               yc11xx_bt.o
+    0x0000188c   0x0000188c   0x00000b3c   Code   RO          372    .text               yc_debug.o
+    0x000023c8   0x000023c8   0x00000038   Code   RO          405    .text               yc11xx.o
+    0x00002400   0x00002400   0x00000508   Code   RO          436    .text               printk.o
+    0x00002908   0x00002908   0x000017fa   Code   RO          508    .text               buf.o
+    0x00004102   0x00004102   0x000002dc   Code   RO          564    .text               queue.o
+    0x000043de   0x000043de   0x0000000e   Code   RO          591    .text               mempool.o
+    0x000043ec   0x000043ec   0x00000142   Code   RO          609    .text               hex.o
+    0x0000452e   0x0000452e   0x00000002   PAD
+    0x00004530   0x00004530   0x000001a4   Code   RO          624    .text               log.o
+    0x000046d4   0x000046d4   0x0000009c   Code   RO          660    .text               mem_slab.o
+    0x00004770   0x00004770   0x00004f88   Code   RO          702    .text               hci_core.o
+    0x000096f8   0x000096f8   0x0000024c   Code   RO          817    .text               uuid.o
+    0x00009944   0x00009944   0x00002f30   Code   RO          837    .text               att.o
+    0x0000c874   0x0000c874   0x00001fe0   Code   RO          930    .text               conn.o
+    0x0000e854   0x0000e854   0x00003838   Code   RO         1019    .text               gatt.o
+    0x0001208c   0x0001208c   0x00000ea8   Code   RO         1099    .text               l2cap.o
+    0x00012f34   0x00012f34   0x00000868   Code   RO         1164    .text               yc11xx_dev_bt.o
+    0x0001379c   0x0001379c   0x0000002c   Code   RO         1256    .text               mc_p.l(uidiv.o)
+    0x000137c8   0x000137c8   0x00000028   Code   RO         1258    .text               mc_p.l(idiv.o)
+    0x000137f0   0x000137f0   0x00000028   Code   RO         1260    .text               mc_p.l(memcpy.o)
+    0x00013818   0x00013818   0x00000024   Code   RO         1264    .text               mc_p.l(memseta.o)
+    0x0001383c   0x0001383c   0x0000000e   Code   RO         1266    .text               mc_p.l(strlen.o)
+    0x0001384a   0x0001384a   0x0000001c   Code   RO         1268    .text               mc_p.l(strcmp.o)
+    0x00013866   0x00013866   0x0000001a   Code   RO         1270    .text               mc_p.l(memcmp.o)
+    0x00013880   0x00013880   0x00000012   Code   RO         1272    .text               mc_p.l(strcpy.o)
+    0x00013892   0x00013892   0x00000014   Code   RO         1278    .text               mc_p.l(uread4.o)
+    0x000138a6   0x000138a6   0x0000001c   Code   RO         1280    .text               mc_p.l(uread8.o)
+    0x000138c2   0x000138c2   0x00000002   PAD
+    0x000138c4   0x000138c4   0x00000024   Code   RO         1296    .text               mc_p.l(init.o)
+    0x000138e8   0x000138e8   0x00000056   Code   RO         1306    .text               mc_p.l(__dczerorl2.o)
+    0x0001393e   0x0001393e   0x0000001c   Code   RO          448    i.__ARM_common_switch8  printk.o
+    0x0001395a   0x0001395a   0x0000000e   Code   RO         1300    i.__scatterload_copy  mc_p.l(handlers.o)
+    0x00013968   0x00013968   0x00000002   Code   RO         1301    i.__scatterload_null  mc_p.l(handlers.o)
+    0x0001396a   0x0001396a   0x0000000e   Code   RO         1302    i.__scatterload_zeroinit  mc_p.l(handlers.o)
+    0x00013978   0x00013978   0x00000008   Data   RO         1020    ._bt_gatt_service_static.static._1_gatt_svc  gatt.o
+    0x00013980   0x00013980   0x00000008   Data   RO         1021    ._bt_gatt_service_static.static._2_gap_svc  gatt.o
+    0x00013988   0x00013988   0x0000000c   Data   RO          841    ._bt_l2cap_fixed_chan.static.att_fixed_chan  att.o
+    0x00013994   0x00013994   0x0000000c   Data   RO         1100    ._bt_l2cap_fixed_chan.static.le_fixed_chan  l2cap.o
+    0x000139a0   0x000139a0   0x00000064   Data   RO            3    .constdata          main.o
+    0x00013a04   0x00013a04   0x00000003   Data   RO          342    .constdata          yc11xx_bt.o
+    0x00013a07   0x00013a07   0x00000001   PAD
+    0x00013a08   0x00013a08   0x00000014   Data   RO          374    .constdata          yc_debug.o
+    0x00013a1c   0x00013a1c   0x0000001a   Data   RO          509    .constdata          buf.o
+    0x00013a36   0x00013a36   0x00000011   Data   RO          626    .constdata          log.o
+    0x00013a47   0x00013a47   0x00000001   PAD
+    0x00013a48   0x00013a48   0x0000022d   Data   RO          704    .constdata          hci_core.o
+    0x00013c75   0x00013c75   0x00000011   Data   RO          818    .constdata          uuid.o
+    0x00013c86   0x00013c86   0x00000002   PAD
+    0x00013c88   0x00013c88   0x000001ec   Data   RO          846    .constdata          att.o
+    0x00013e74   0x00013e74   0x0000007a   Data   RO          933    .constdata          conn.o
+    0x00013eee   0x00013eee   0x00000002   PAD
+    0x00013ef0   0x00013ef0   0x0000010c   Data   RO         1023    .constdata          gatt.o
+    0x00013ffc   0x00013ffc   0x0000005c   Data   RO         1102    .constdata          l2cap.o
+    0x00014058   0x00014058   0x00000046   Data   RO         1166    .constdata          yc11xx_dev_bt.o
+    0x0001409e   0x0001409e   0x00000002   PAD
+    0x000140a0   0x000140a0   0x0000000b   Data   RO            4    .conststring        main.o
+    0x000140ab   0x000140ab   0x00000001   PAD
+    0x000140ac   0x000140ac   0x00000025   Data   RO          375    .conststring        yc_debug.o
+    0x000140d1   0x000140d1   0x00000003   PAD
+    0x000140d4   0x000140d4   0x000000c1   Data   RO          705    .conststring        hci_core.o
+    0x00014195   0x00014195   0x00000003   PAD
+    0x00014198   0x00014198   0x00000043   Data   RO          934    .conststring        conn.o
+    0x000141db   0x000141db   0x00000001   PAD
+    0x000141dc   0x000141dc   0x00000087   Data   RO         1024    .conststring        gatt.o
+    0x00014263   0x00014263   0x00000001   PAD
+    0x00014264   0x00014264   0x00000054   Data   RO         1103    .conststring        l2cap.o
+    0x000142b8   0x000142b8   0x00000004   Data   RO         1167    .conststring        yc11xx_dev_bt.o
+    0x000142bc   0x000142bc   0x00000020   Data   RO         1298    Region$$Table       anon$$obj.o
+
+
+    Execution Region RW_IRAM1 (Exec base: 0x10010000, Load base: 0x000142dc, Size: 0x00004574, Max: 0x0000d800, ABSOLUTE, COMPRESSED[0x000000bc])
+
+    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
+
+    0x10010000   COMPRESSED   0x00000090   Data   RW          838    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".0  att.o
+    0x10010090   COMPRESSED   0x0000001c   Data   RW          839    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".1  att.o
+    0x100100ac   COMPRESSED   0x00000004   PAD
+    0x100100b0   COMPRESSED   0x00000064   Data   RW          840    ._NOINIT_SECTION_NAME."..\\..\\User\\subsys\\bluetooth\\host\\att.c".2  att.o
+    0x10010114   COMPRESSED   0x00000014   Data   RW          842    ._k_mem_slab.static.att_slab  att.o
+    0x10010128   COMPRESSED   0x00000014   Data   RW          843    ._k_mem_slab.static.chan_slab  att.o
+    0x1001013c   COMPRESSED   0x00000014   Data   RW          844    ._k_mem_slab.static.req_slab  att.o
+    0x10010150   COMPRESSED   0x00000008   Data   RW          931    ._k_queue.static.free_tx  conn.o
+    0x10010158   COMPRESSED   0x00000070   Data   RW            5    .data               main.o
+    0x100101c8   COMPRESSED   0x00000004   Data   RW          271    .data               yc11xx_systick.o
+    0x100101cc   COMPRESSED   0x0000000e   Data   RW          290    .data               yc_timer.o
+    0x100101da   COMPRESSED   0x00000002   PAD
+    0x100101dc   COMPRESSED   0x00000008   Data   RW          343    .data               yc11xx_bt.o
+    0x100101e4   COMPRESSED   0x00000028   Data   RW          376    .data               yc_debug.o
+    0x1001020c   COMPRESSED   0x00000004   Data   RW          437    .data               printk.o
+    0x10010210   COMPRESSED   0x00000060   Data   RW          706    .data               hci_core.o
+    0x10010270   COMPRESSED   0x0000002c   Data   RW          847    .data               att.o
+    0x1001029c   COMPRESSED   0x0000002c   Data   RW          935    .data               conn.o
+    0x100102c8   COMPRESSED   0x00000069   Data   RW         1025    .data               gatt.o
+    0x10010331   COMPRESSED   0x00000001   Data   RW         1104    .data               l2cap.o
+    0x10010332   COMPRESSED   0x00000002   PAD
+    0x10010334        -       0x0000002c   Zero   RW            2    .bss                main.o
+    0x10010360        -       0x00000018   Zero   RW          289    .bss                yc_timer.o
+    0x10010378        -       0x0000014e   Zero   RW          341    .bss                yc11xx_bt.o
+    0x100104c6        -       0x00000032   Zero   RW          373    .bss                yc_debug.o
+    0x100104f8        -       0x000000d6   Zero   RW          625    .bss                log.o
+    0x100105ce   COMPRESSED   0x00000002   PAD
+    0x100105d0        -       0x0000156f   Zero   RW          703    .bss                hci_core.o
+    0x10011b3f   COMPRESSED   0x00000001   PAD
+    0x10011b40        -       0x00000018   Zero   RW          845    .bss                att.o
+    0x10011b58        -       0x000019d4   Zero   RW          932    .bss                conn.o
+    0x1001352c        -       0x00000034   Zero   RW         1022    .bss                gatt.o
+    0x10013560        -       0x00000048   Zero   RW         1101    .bss                l2cap.o
+    0x100135a8        -       0x00000fc9   Zero   RW         1165    .bss                yc11xx_dev_bt.o
+
+
+==============================================================================
+
+Image component sizes
+
+
+      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
+
+     12080       2002        504        376         24     112223   att.o
+      6138       1758         26          0          0      48957   buf.o
+      8160       1766        189         52       6612     120412   conn.o
+     14392       1904        419        105         52      97678   gatt.o
+     20360       3478        750         96       5487     163037   hci_core.o
+       322          0          0          0          0       2312   hex.o
+      3752        980        188          1         72      50708   l2cap.o
+       420        138         17          0        214      33569   log.o
+      2172        808        111        112         44     104475   main.o
+       156          0          0          0          0       1540   mem_slab.o
+        14          0          0          0          0      10347   mempool.o
+      1316         62          0          4          0       7556   printk.o
+       732          0          0          0          0      17945   queue.o
+        40         20        192          0          0        484   startup.o
+       588         52         17          0          0       6200   uuid.o
+        56          4          0          0          0        675   yc11xx.o
+      1480         50          3          8        334      29927   yc11xx_bt.o
+      2152        418         74          0       4041      30784   yc11xx_dev_bt.o
+       652         10          0          0          0      25204   yc11xx_gpio.o
+        88         12          0          4          0      19394   yc11xx_systick.o
+      2876        154         57         40         50       8676   yc_debug.o
+       416         10          0          0          0       5090   yc_drv_common.o
+      1224         66          0         14         24       6628   yc_timer.o
+
+    ----------------------------------------------------------------------
+     79588      13692       2596        820      16960     903821   Object Totals
+         0          0         32          0          0          0   (incl. Generated)
+         2          0         17          8          6          0   (incl. Padding)
+
+    ----------------------------------------------------------------------
+
+      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name
+
+        86          0          0          0          0          0   __dczerorl2.o
+         0          0          0          0          0          0   entry.o
+         0          0          0          0          0          0   entry10a.o
+         0          0          0          0          0          0   entry11a.o
+         8          4          0          0          0          0   entry2.o
+         4          0          0          0          0          0   entry5.o
+         0          0          0          0          0          0   entry7b.o
+         0          0          0          0          0          0   entry8b.o
+         8          4          0          0          0          0   entry9a.o
+        30          0          0          0          0          0   handlers.o
+        40          0          0          0          0         72   idiv.o
+        36          8          0          0          0         68   init.o
+        26          0          0          0          0         72   memcmp.o
+        40          0          0          0          0         68   memcpy.o
+        36          0          0          0          0        100   memseta.o
+        28          0          0          0          0         68   strcmp.o
+        18          0          0          0          0         60   strcpy.o
+        14          0          0          0          0         60   strlen.o
+        44          0          0          0          0         72   uidiv.o
+        20          0          0          0          0         60   uread4.o
+        28          0          0          0          0         68   uread8.o
+
+    ----------------------------------------------------------------------
+       468         16          0          0          0        768   Library Totals
+         2          0          0          0          0          0   (incl. Padding)
+
+    ----------------------------------------------------------------------
+
+      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name
+
+       466         16          0          0          0        768   mc_p.l
+
+    ----------------------------------------------------------------------
+       468         16          0          0          0        768   Library Totals
+
+    ----------------------------------------------------------------------
+
+==============================================================================
+
+
+      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   
+
+     80056      13708       2596        820      16960     902217   Grand Totals
+     80056      13708       2596        188      16960     902217   ELF Image Totals (compressed)
+     80056      13708       2596        188          0          0   ROM Totals
+
+==============================================================================
+
+    Total RO  Size (Code + RO Data)                82652 (  80.71kB)
+    Total RW  Size (RW Data + ZI Data)             17780 (  17.36kB)
+    Total ROM Size (Code + RO Data + RW Data)      82840 (  80.90kB)
+
+==============================================================================
+
Index: ModuleDemo/BLE/CM0/Prj/MDK/Objects/startup/startup.s
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/startup/startup.s	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/startup/startup.s	(working copy)
@@ -0,0 +1,207 @@
+
+Stack_Size      EQU     0x00B640
+
+                AREA    STACK, NOINIT, READWRITE, ALIGN=4
+Stack_Mem       SPACE   Stack_Size
+__initial_sp    EQU		0x1001B640
+
+
+; <h> Heap Configuration
+;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+Heap_Size       EQU     0x00001000
+                AREA    HEAP, NOINIT, READWRITE, ALIGN=4
+__heap_base
+Heap_Mem        SPACE   Heap_Size
+__heap_limit
+
+
+                PRESERVE8
+                THUMB
+; Vector Table Mapped to Address 0 at Reset
+
+                AREA    RESET, DATA, READONLY	
+                EXPORT  __Vectors
+                EXPORT  __Vectors_End
+                EXPORT  __Vectors_Size
+__Vectors       DCD     __initial_sp				; Top of Stack
+                DCD     Reset_Handler				; Reset Handler
+                DCD     NMI_Handler
+                DCD     HardFault_Handler			; Hard Fault Handler					
+				DCD		0							;	
+				DCD		0							;
+				DCD		0							;
+				DCD		0							;
+				DCD		0							;
+				DCD		0							;
+				DCD		0							;
+				DCD		SVC_Handler					;
+				DCD		0							;
+				DCD		0							;
+				DCD		PendSV_Handler				;
+				DCD		SysTick_Handler				;	
+					
+				DCD		USB_IRQHandler              ;
+				DCD		IIC_IRQHandler              ;
+				DCD		QSPI_IRQHandler             ;
+				DCD		SPI_IRQHandler              ;
+				DCD		UART_IRQHandler             ;
+				DCD		UARTB_IRQHandler            ;
+				DCD		ADC_IRQHandler              ;
+				DCD		IIS_IRQHandler              ;
+				DCD		BT_IRQHandler               ;
+				DCD     GPIO_IRQHandler				;
+				DCD     OTP_IRQHandler				;
+				DCD     SBC_ERR0_IRQHandler			;
+				DCD     SBC_ERR1_IRQHandler			;
+				DCD     FFT_IRQHandler				;
+				DCD     DMA_IRQHandler				;
+				DCD     SD_IRQHandler				;
+				DCD     TIMER0_IRQHandler			;
+				DCD     TIMER1_IRQHandler			;
+				DCD     TIMER2_IRQHandler			;
+				DCD     TIMER3_IRQHandler			;
+				DCD     TIMER4_IRQHandler			;
+				DCD     TIMER5_IRQHandler			;
+				DCD     TIMER6_IRQHandler			;
+				DCD     TIMER7_IRQHandler			;
+				DCD     WDT2_IRQHandler				;
+				DCD     WDT_IRQHandler				;
+				DCD     0							;
+				DCD     0							;
+				DCD     0							;
+				DCD     0							;
+				DCD     0							;
+				DCD     0							;
+
+__Vectors_End					
+					
+__Vectors_Size  EQU     __Vectors_End - __Vectors
+
+                AREA    |.text|, CODE, READONLY	,ALIGN=4				
+					
+					
+					
+; Reset Handler
+
+Reset_Handler   PROC
+                EXPORT  Reset_Handler             [WEAK]
+                IMPORT  __main
+                LDR     R0,= LOADRAMFLAG
+                LDR     R0,[R0]
+                LDRB    R0,[R0]
+                CMP     R0,#1
+                BEQ     RUN_TO_MAIN		
+				LDR 	R0, =__main
+				BX 		R0
+                ENDP	
+
+RUN_TO_MAIN		PROC
+                IMPORT  main
+                LDR 	R0, = main
+                BX 		R0
+                ENDP
+				
+                align 4
+; mem_wake_flag
+LOADRAMFLAG     DCD    0x10004429		
+Default_Handler PROC
+; ToDo:  Add here the export definition for the device specific external interrupts handler
+				EXPORT      HardFault_Handler   [WEAK]
+				EXPORT      NMI_Handler		    [WEAK]
+				EXPORT      SVC_Handler		    [WEAK]
+				EXPORT      PendSV_Handler		[WEAK]
+                EXPORT 		SysTick_Handler		[WEAK]
+				EXPORT		USB_IRQHandler      [WEAK]
+				EXPORT		IIC_IRQHandler      [WEAK]
+				EXPORT		QSPI_IRQHandler     [WEAK]
+				EXPORT		SPI_IRQHandler      [WEAK]
+				EXPORT		UART_IRQHandler     [WEAK]
+				EXPORT		UARTB_IRQHandler    [WEAK]
+				EXPORT 		ADC_IRQHandler      [WEAK]				
+				EXPORT		IIS_IRQHandler      [WEAK]
+				EXPORT		BT_IRQHandler       [WEAK]
+				EXPORT		GPIO_IRQHandler		[WEAK]
+				EXPORT		OTP_IRQHandler		[WEAK]
+				EXPORT		SBC_ERR0_IRQHandler	[WEAK]
+				EXPORT		SBC_ERR1_IRQHandler	[WEAK]
+				EXPORT		FFT_IRQHandler		[WEAK]
+				EXPORT		DMA_IRQHandler		[WEAK]
+				EXPORT		SD_IRQHandler		[WEAK]
+				EXPORT		TIMER0_IRQHandler	[WEAK]
+				EXPORT		TIMER1_IRQHandler	[WEAK]
+				EXPORT		TIMER2_IRQHandler	[WEAK]
+				EXPORT		TIMER3_IRQHandler	[WEAK]	
+				EXPORT		TIMER4_IRQHandler	[WEAK]	
+				EXPORT		TIMER5_IRQHandler	[WEAK]	
+				EXPORT		TIMER6_IRQHandler	[WEAK]	
+				EXPORT 		TIMER7_IRQHandler	[WEAK]
+
+				EXPORT 		WDT2_IRQHandler		[WEAK]
+				EXPORT 		WDT_IRQHandler		[WEAK]
+
+; ToDo:  Add here the names for the device specific external interrupts handler
+HardFault_Handler
+NMI_Handler
+SVC_Handler
+PendSV_Handler
+SysTick_Handler
+USB_IRQHandler          	
+IIC_IRQHandler          	
+QSPI_IRQHandler         	
+SPI_IRQHandler          	 	
+UART_IRQHandler         	
+UARTB_IRQHandler        	
+ADC_IRQHandler          
+IIS_IRQHandler          
+BT_IRQHandler           			
+GPIO_IRQHandler			
+OTP_IRQHandler			
+SBC_ERR0_IRQHandler		
+SBC_ERR1_IRQHandler		
+FFT_IRQHandler			
+DMA_IRQHandler			
+SD_IRQHandler			
+TIMER0_IRQHandler
+TIMER1_IRQHandler
+TIMER2_IRQHandler
+TIMER3_IRQHandler
+TIMER4_IRQHandler
+TIMER5_IRQHandler
+TIMER6_IRQHandler
+TIMER7_IRQHandler
+
+WDT2_IRQHandler
+WDT_IRQHandler
+                B       .
+                ENDP												
+		
+				 ALIGN
+
+
+; User Initial Stack & Heap
+
+                IF      :DEF:__MICROLIB
+                EXPORT  __initial_sp
+                EXPORT  __heap_base
+                EXPORT  __heap_limit
+					
+                ELSE
+
+                IMPORT  __use_two_region_memory
+                EXPORT  __user_initial_stackheap
+
+__user_initial_stackheap PROC
+                LDR     R0, =  Heap_Mem
+                LDR     R1, =(Stack_Mem + Stack_Size)
+                LDR     R2, = (Heap_Mem +  Heap_Size)
+                LDR     R3, = Stack_Mem
+                BX      LR
+                ENDP
+
+                ALIGN
+
+                ENDIF
+					
+				END		
Index: ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/c.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/c.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/c.bat	(working copy)
@@ -0,0 +1,21 @@
+::@echo off
+cls
+
+set ROOT_PATH=..\..\..
+set BT_PATH=%ROOT_PATH%\BT
+set PATCH_PATH=%BT_PATH%\output
+set OBJ_PATH=.\Objects
+
+echo start compile cm0 bin
+set OBJ_PATH=.\Objects
+perl %OBJ_PATH%\tool\hex2rom.pl 0 80000  32 %OBJ_PATH%\yc11xx.hex  %OBJ_PATH%\output\out.rom
+copy %OBJ_PATH%\output\out.rom ..\Output
+
+echo compile cm0 bin ok
+
+
+echo start compile full bin
+echo %BT_PATH%
+cd %BT_PATH%
+call do.bat eep
+echo compile full bin ok
Index: ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/d.bat
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/d.bat	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/d.bat	(working copy)
@@ -0,0 +1,132 @@
+::@echo off
+cls
+
+set ROOT_PATH=..\..\..
+set BT_PATH=%ROOT_PATH%\BT
+set PATCH_PATH=%BT_PATH%\output
+set OBJ_PATH=.\Objects
+
+echo start download ROM code...
+cd %BT_PATH%
+call a-l.bat
+echo download ROM code OK
+goto:eof
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlocation-------
+::------------------------------------------
+:getstrlocation
+setlocal
+set "bstr=%1"
+set "cstr=%2"
+set %3=0
+set "num=0"
+set "len_bstr=0"
+set "len_cstr=0"
+
+call:getstrlen %bstr% len_bstr
+call:getstrlen %cstr% len_cstr
+
+:getstrlocation_next
+set /a len_remain=len_bstr-num
+if %len_remain% lss %len_cstr% (
+echo "cann't get str location"
+set /a num =0
+goto getstrlocation_last
+)
+
+call:get_fix_len_str %bstr%  len_cstr compar_str
+
+if not %compar_str%==%cstr% (
+set /a num+=1
+set "bstr=%bstr:~1%"
+goto getstrlocation_next
+)
+
+:getstrlocation_last
+(endlocal
+	set %3=%num%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+::------------------------------------------
+::---------------func:get_fix_len_str-------
+::------------------------------------------
+:get_fix_len_str
+setlocal
+set "getstr=%NULL%"
+set str=%1
+set /a len=%2
+set num=0
+:get_fix_len_str_loop
+set getstr=%getstr%%str:~0,1%
+set /a num+=1
+set str=%str:~1%
+if %num% lss %len% goto get_fix_len_str_loop
+(endlocal
+ set %3=%getstr%
+)
+goto:eof
+::---------------end:func-------------------
+
+
+
+
+::------------------------------------------
+::---------------func:getstrlen-------------
+::------------------------------------------
+:getstrlen
+setlocal
+set str=%1
+set %2=0
+set /a "num=0"
+
+:getstrlen_next
+if "%str%"=="" goto getstrlen_last
+
+if not "%str%"=="" (
+set /a num+=1 
+set "str=%str:~1%"
+goto getstrlen_next
+)
+
+:getstrlen_last
+(endlocal
+	set /a "%2=%num%"
+)
+goto:eof
+::---------------end:func-------------------
+
Index: ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/hex2rom.pl
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/hex2rom.pl	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/tool/hex2rom.pl	(working copy)
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+my @rom = ();
+die "missing start and end address" if(@ARGV < 2);
+
+$addrhi = 0;
+$baseaddr = hex($ARGV[0]);
+$endaddr = hex($ARGV[1]);
+$bits = 32;
+$bits = $ARGV[2] if(@ARGV > 2);
+$endian = 1;
+
+
+$inputfile_addr = $ARGV[3];
+print "\input:  $inputfile_addr\n";
+$outputfile_addr =$ARGV[4];
+print "\output:  $outputfile_addr\n";
+
+
+open(DATA,$inputfile_addr);
+
+while(<DATA>){
+	$line++;
+	$count = (hex substr($_, 1, 2));
+	$addr = (hex substr($_, 3, 4));
+	$type = (hex substr($_, 7, 2));
+	if($type == 2 || $type == 4) {
+		$addrhi = hex(substr($_, 9, 4)) << ($type == 2 ? 4 : 16);
+		printf "type=%d, addr=%x, line=%d\n", $type, $addrhi, $line;
+	}
+	if($type == 0 && $addrhi >= $baseaddr && $addrhi <= $endaddr) {
+		for($x=0; $x<$count; $x++) {
+			$rom[$addrhi - $baseaddr + $addr + $x] = (hex substr($_, 9+2*$x, 2)) ; 
+		}
+	}
+}
+
+#هˆ é™¤ç›®و ‡و–‡ن»¶
+unlink($outputfile_addr);
+#هˆ›ه»؛ç›®و ‡و–‡ن»¶
+$outputfile_addr =$ARGV[4];
+$outputfile_addr = '+>'.$outputfile_addr;
+print "$outputfile_addr\n";
+open(DATA1,$outputfile_addr) or die "des file open fail,$!";
+
+if($bits == 1) {
+	for($x=0; $x<@rom; $x++) {
+			printf ("%04x\n", $rom[$x]);
+		}
+		print "\n";
+} else {
+	for($x=0; $x<@rom; $x+=$bits/8) {
+		for($i = 0;$i < $bits/8;$i++) {
+			$tmp = sprintf("%02x",($endian ? $rom[$x+$bits/8-1-$i] : $rom[$x+$i])),
+			print DATA1 "$tmp";
+#			printf "$tmp";
+			}
+		print DATA1 "\n";
+#		printf "\n";
+	}
+}
+$inputfile_addr = $ARGV[3];
+$outputfile_addr =$ARGV[4];
+close(inputfile_addr);
+close(outputfile_addr);
Index: ModuleDemo/BLE/CM0/Prj/MDK/Objects/yc11xx.sct
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/yc11xx.sct	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/Objects/yc11xx.sct	(working copy)
@@ -0,0 +1,16 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+LR_IROM1 0x00000000 0x00080000  {    ; load region size_region
+  ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
+   startup.o (|.text|,+RO)
+   startup.o (RESET, +First)
+	*(InRoot$$Sections)
+	.ANY (+RO)
+  }
+	; if change this, must change startup.s __initial_sp
+	 RW_IRAM1 0x10010000 0xd800  {  ; RW data
+	.ANY (+RW +ZI)
+	}
+}
\ No newline at end of file
Index: ModuleDemo/BLE/CM0/Prj/MDK/RTE/_Target_1/RTE_Components.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/RTE/_Target_1/RTE_Components.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/RTE/_Target_1/RTE_Components.h	(working copy)
@@ -0,0 +1,20 @@
+
+/*
+ * Auto generated Run-Time-Environment Component Configuration File
+ *      *** Do not modify ! ***
+ *
+ * Project: 'yc11xx' 
+ * Target:  'Target 1' 
+ */
+
+#ifndef RTE_COMPONENTS_H
+#define RTE_COMPONENTS_H
+
+
+/*
+ * Define the Device Header File: 
+ */
+#define CMSIS_device_header "CMSDK_CM0.h"
+
+
+#endif /* RTE_COMPONENTS_H */
Index: ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvoptx
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvoptx	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvoptx	(working copy)
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
+
+  <SchemaVersion>1.0</SchemaVersion>
+
+  <Header>### uVision Project, (C) Keil Software</Header>
+
+  <Extensions>
+    <cExt>*.c</cExt>
+    <aExt>*.s*; *.src; *.a*</aExt>
+    <oExt>*.obj; *.o</oExt>
+    <lExt>*.lib</lExt>
+    <tExt>*.txt; *.h; *.inc</tExt>
+    <pExt>*.plm</pExt>
+    <CppX>*.cpp</CppX>
+    <nMigrate>0</nMigrate>
+  </Extensions>
+
+  <DaveTm>
+    <dwLowDateTime>0</dwLowDateTime>
+    <dwHighDateTime>0</dwHighDateTime>
+  </DaveTm>
+
+  <Target>
+    <TargetName>Target 1</TargetName>
+    <ToolsetNumber>0x4</ToolsetNumber>
+    <ToolsetName>ARM-ADS</ToolsetName>
+    <TargetOption>
+      <CLKADS>12000000</CLKADS>
+      <OPTTT>
+        <gFlags>1</gFlags>
+        <BeepAtEnd>1</BeepAtEnd>
+        <RunSim>0</RunSim>
+        <RunTarget>1</RunTarget>
+        <RunAbUc>0</RunAbUc>
+      </OPTTT>
+      <OPTHX>
+        <HexSelection>1</HexSelection>
+        <FlashByte>65535</FlashByte>
+        <HexRangeLowAddress>0</HexRangeLowAddress>
+        <HexRangeHighAddress>0</HexRangeHighAddress>
+        <HexOffset>0</HexOffset>
+      </OPTHX>
+      <OPTLEX>
+        <PageWidth>79</PageWidth>
+        <PageLength>66</PageLength>
+        <TabStop>8</TabStop>
+        <ListingPath>.\Listings\</ListingPath>
+      </OPTLEX>
+      <ListingPage>
+        <CreateCListing>1</CreateCListing>
+        <CreateAListing>1</CreateAListing>
+        <CreateLListing>1</CreateLListing>
+        <CreateIListing>0</CreateIListing>
+        <AsmCond>1</AsmCond>
+        <AsmSymb>1</AsmSymb>
+        <AsmXref>0</AsmXref>
+        <CCond>1</CCond>
+        <CCode>0</CCode>
+        <CListInc>0</CListInc>
+        <CSymb>0</CSymb>
+        <LinkerCodeListing>0</LinkerCodeListing>
+      </ListingPage>
+      <OPTXL>
+        <LMap>1</LMap>
+        <LComments>1</LComments>
+        <LGenerateSymbols>1</LGenerateSymbols>
+        <LLibSym>1</LLibSym>
+        <LLines>1</LLines>
+        <LLocSym>1</LLocSym>
+        <LPubSym>1</LPubSym>
+        <LXref>0</LXref>
+        <LExpSel>0</LExpSel>
+      </OPTXL>
+      <OPTFL>
+        <tvExp>1</tvExp>
+        <tvExpOptDlg>0</tvExpOptDlg>
+        <IsCurrentTarget>1</IsCurrentTarget>
+      </OPTFL>
+      <CpuCode>7</CpuCode>
+      <DebugOpt>
+        <uSim>0</uSim>
+        <uTrg>1</uTrg>
+        <sLdApp>1</sLdApp>
+        <sGomain>1</sGomain>
+        <sRbreak>1</sRbreak>
+        <sRwatch>1</sRwatch>
+        <sRmem>1</sRmem>
+        <sRfunc>1</sRfunc>
+        <sRbox>1</sRbox>
+        <tLdApp>1</tLdApp>
+        <tGomain>1</tGomain>
+        <tRbreak>1</tRbreak>
+        <tRwatch>1</tRwatch>
+        <tRmem>1</tRmem>
+        <tRfunc>0</tRfunc>
+        <tRbox>1</tRbox>
+        <tRtrace>1</tRtrace>
+        <sRSysVw>1</sRSysVw>
+        <tRSysVw>1</tRSysVw>
+        <sRunDeb>0</sRunDeb>
+        <sLrtime>0</sLrtime>
+        <bEvRecOn>1</bEvRecOn>
+        <bSchkAxf>0</bSchkAxf>
+        <bTchkAxf>0</bTchkAxf>
+        <nTsel>4</nTsel>
+        <sDll></sDll>
+        <sDllPa></sDllPa>
+        <sDlgDll></sDlgDll>
+        <sDlgPa></sDlgPa>
+        <sIfile></sIfile>
+        <tDll></tDll>
+        <tDllPa></tDllPa>
+        <tDlgDll></tDlgDll>
+        <tDlgPa></tDlgPa>
+        <tIfile></tIfile>
+        <pMon>Segger\JL2CM3.dll</pMon>
+      </DebugOpt>
+      <TargetDriverDllRegistry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>DLGUARM</Key>
+          <Name>/</Name>
+        </SetRegEntry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>JL2CM3</Key>
+          <Name>-U4294967295 -O111 -S2 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC1000 -FN0</Name>
+        </SetRegEntry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>ARMRTXEVENTFLAGS</Key>
+          <Name>-L70 -Z18 -C0 -M0 -T1</Name>
+        </SetRegEntry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>DLGTARM</Key>
+          <Name>(1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)</Name>
+        </SetRegEntry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>ARMDBGFLAGS</Key>
+          <Name></Name>
+        </SetRegEntry>
+        <SetRegEntry>
+          <Number>0</Number>
+          <Key>UL2CM3</Key>
+          <Name>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000)</Name>
+        </SetRegEntry>
+      </TargetDriverDllRegistry>
+      <Breakpoint/>
+      <WatchWindow1>
+        <Ww>
+          <count>0</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>times</ItemText>
+        </Ww>
+        <Ww>
+          <count>1</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>CORE_UARTB_CTRL</ItemText>
+        </Ww>
+        <Ww>
+          <count>2</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>USART_InitStruct</ItemText>
+        </Ww>
+        <Ww>
+          <count>3</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>UartAdr</ItemText>
+        </Ww>
+        <Ww>
+          <count>4</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>WPtr</ItemText>
+        </Ww>
+        <Ww>
+          <count>5</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>regBeck</ItemText>
+        </Ww>
+        <Ww>
+          <count>6</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>I2cRxPtr</ItemText>
+        </Ww>
+        <Ww>
+          <count>7</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>I2cTxPtr</ItemText>
+        </Ww>
+        <Ww>
+          <count>8</count>
+          <WinNumber>1</WinNumber>
+          <ItemText>I2cAdr</ItemText>
+        </Ww>
+      </WatchWindow1>
+      <MemoryWindow1>
+        <Mm>
+          <WinNumber>1</WinNumber>
+          <SubType>0</SubType>
+          <ItemText>0xe000e100</ItemText>
+          <AccSizeX>0</AccSizeX>
+        </Mm>
+      </MemoryWindow1>
+      <MemoryWindow2>
+        <Mm>
+          <WinNumber>2</WinNumber>
+          <SubType>0</SubType>
+          <ItemText>0x100080aa</ItemText>
+          <AccSizeX>0</AccSizeX>
+        </Mm>
+      </MemoryWindow2>
+      <Tracepoint>
+        <THDelay>0</THDelay>
+      </Tracepoint>
+      <DebugFlag>
+        <trace>0</trace>
+        <periodic>1</periodic>
+        <aLwin>0</aLwin>
+        <aCover>0</aCover>
+        <aSer1>0</aSer1>
+        <aSer2>0</aSer2>
+        <aPa>0</aPa>
+        <viewmode>1</viewmode>
+        <vrSel>0</vrSel>
+        <aSym>0</aSym>
+        <aTbox>0</aTbox>
+        <AscS1>0</AscS1>
+        <AscS2>0</AscS2>
+        <AscS3>0</AscS3>
+        <aSer3>0</aSer3>
+        <eProf>0</eProf>
+        <aLa>0</aLa>
+        <aPa1>0</aPa1>
+        <AscS4>0</AscS4>
+        <aSer4>0</aSer4>
+        <StkLoc>0</StkLoc>
+        <TrcWin>0</TrcWin>
+        <newCpu>0</newCpu>
+        <uProt>0</uProt>
+      </DebugFlag>
+      <LintExecutable></LintExecutable>
+      <LintConfigFile></LintConfigFile>
+      <bLintAuto>0</bLintAuto>
+      <bAutoGenD>0</bAutoGenD>
+      <LntExFlags>0</LntExFlags>
+      <pMisraName></pMisraName>
+      <pszMrule></pszMrule>
+      <pSingCmds></pSingCmds>
+      <pMultCmds></pMultCmds>
+      <pMisraNamep></pMisraNamep>
+      <pszMrulep></pszMrulep>
+      <pSingCmdsp></pSingCmdsp>
+      <pMultCmdsp></pMultCmdsp>
+      <DebugDescription>
+        <Enable>1</Enable>
+        <EnableFlashSeq>0</EnableFlashSeq>
+        <EnableLog>0</EnableLog>
+        <Protocol>1</Protocol>
+        <DbgClock>10000000</DbgClock>
+      </DebugDescription>
+    </TargetOption>
+  </Target>
+
+  <Group>
+    <GroupName>main</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>1</GroupNumber>
+      <FileNumber>1</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\main.c</PathWithFileName>
+      <FilenameWithoutPath>main.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>startup</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>2</FileNumber>
+      <FileType>2</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>.\Objects\startup\startup.s</PathWithFileName>
+      <FilenameWithoutPath>startup.s</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>driver</GroupName>
+    <tvExp>0</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>3</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\gpio\yc11xx_gpio.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_gpio.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>4</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\hal_comm\yc_drv_common.c</PathWithFileName>
+      <FilenameWithoutPath>yc_drv_common.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>5</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\systick\yc11xx_systick.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_systick.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>6</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\timer\yc_timer.c</PathWithFileName>
+      <FilenameWithoutPath>yc_timer.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>7</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\timer\yc11xx_timer.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_timer.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>8</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\uart\yc11xx_uart.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_uart.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>9</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\bt\yc11xx_bt.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_bt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>10</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\debug\yc_debug.c</PathWithFileName>
+      <FilenameWithoutPath>yc_debug.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>11</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\wdt\yc11xx_wdt.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_wdt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>12</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\device\yc11xx.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>3</GroupNumber>
+      <FileNumber>13</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\..\..\..\Librarier\drivers\queue\yc_queue.c</PathWithFileName>
+      <FilenameWithoutPath>yc_queue.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>utils</GroupName>
+    <tvExp>1</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>14</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\printk.c</PathWithFileName>
+      <FilenameWithoutPath>printk.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>15</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\buf.c</PathWithFileName>
+      <FilenameWithoutPath>buf.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>16</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\queue.c</PathWithFileName>
+      <FilenameWithoutPath>queue.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>17</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\mempool.c</PathWithFileName>
+      <FilenameWithoutPath>mempool.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>18</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\hex.c</PathWithFileName>
+      <FilenameWithoutPath>hex.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>19</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\common\log.c</PathWithFileName>
+      <FilenameWithoutPath>log.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>4</GroupNumber>
+      <FileNumber>20</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\utils\mem_slab.c</PathWithFileName>
+      <FilenameWithoutPath>mem_slab.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>bluetooth</GroupName>
+    <tvExp>1</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>21</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\hci_common.c</PathWithFileName>
+      <FilenameWithoutPath>hci_common.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>22</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\hci_core.c</PathWithFileName>
+      <FilenameWithoutPath>hci_core.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>23</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\uuid.c</PathWithFileName>
+      <FilenameWithoutPath>uuid.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>24</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\att.c</PathWithFileName>
+      <FilenameWithoutPath>att.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>25</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\conn.c</PathWithFileName>
+      <FilenameWithoutPath>conn.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>26</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\gatt.c</PathWithFileName>
+      <FilenameWithoutPath>gatt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+    <File>
+      <GroupNumber>5</GroupNumber>
+      <FileNumber>27</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\subsys\bluetooth\host\l2cap.c</PathWithFileName>
+      <FilenameWithoutPath>l2cap.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+  <Group>
+    <GroupName>device</GroupName>
+    <tvExp>1</tvExp>
+    <tvExpOptDlg>0</tvExpOptDlg>
+    <cbSel>0</cbSel>
+    <RteFlg>0</RteFlg>
+    <File>
+      <GroupNumber>6</GroupNumber>
+      <FileNumber>28</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\..\User\device\bt\yc11xx_dev_bt.c</PathWithFileName>
+      <FilenameWithoutPath>yc11xx_dev_bt.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
+  </Group>
+
+</ProjectOpt>
Index: ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvprojx
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvprojx	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/Prj/MDK/yc11xx.uvprojx	(working copy)
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd">
+
+  <SchemaVersion>2.1</SchemaVersion>
+
+  <Header>### uVision Project, (C) Keil Software</Header>
+
+  <Targets>
+    <Target>
+      <TargetName>Target 1</TargetName>
+      <ToolsetNumber>0x4</ToolsetNumber>
+      <ToolsetName>ARM-ADS</ToolsetName>
+      <pCCUsed>5060750::V5.06 update 6 (build 750)::ARMCC</pCCUsed>
+      <uAC6>0</uAC6>
+      <TargetOption>
+        <TargetCommonOption>
+          <Device>CMSDK_CM0</Device>
+          <Vendor>ARM</Vendor>
+          <PackID>Keil.V2M-MPS2_CMx_BSP.1.7.1</PackID>
+          <PackURL>http://www.keil.com/pack/</PackURL>
+          <Cpu>IRAM(0x20000000,0x00400000) IROM(0x00000000,0x00400000) CPUTYPE("Cortex-M0") CLOCK(12000000) ELITTLE</Cpu>
+          <FlashUtilSpec></FlashUtilSpec>
+          <StartupFile></StartupFile>
+          <FlashDriverDll>UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000)</FlashDriverDll>
+          <DeviceId>0</DeviceId>
+          <RegisterFile>$$Device:CMSDK_CM0$Device\CMSDK_CM0\Include\CMSDK_CM0.h</RegisterFile>
+          <MemoryEnv></MemoryEnv>
+          <Cmp></Cmp>
+          <Asm></Asm>
+          <Linker></Linker>
+          <OHString></OHString>
+          <InfinionOptionDll></InfinionOptionDll>
+          <SLE66CMisc></SLE66CMisc>
+          <SLE66AMisc></SLE66AMisc>
+          <SLE66LinkerMisc></SLE66LinkerMisc>
+          <SFDFile>$$Device:CMSDK_CM0$SVD\CMSDK_CM0.svd</SFDFile>
+          <bCustSvd>0</bCustSvd>
+          <UseEnv>0</UseEnv>
+          <BinPath></BinPath>
+          <IncludePath></IncludePath>
+          <LibPath></LibPath>
+          <RegisterFilePath></RegisterFilePath>
+          <DBRegisterFilePath></DBRegisterFilePath>
+          <TargetStatus>
+            <Error>0</Error>
+            <ExitCodeStop>0</ExitCodeStop>
+            <ButtonStop>0</ButtonStop>
+            <NotGenerated>0</NotGenerated>
+            <InvalidFlash>1</InvalidFlash>
+          </TargetStatus>
+          <OutputDirectory>.\Objects\</OutputDirectory>
+          <OutputName>yc11xx</OutputName>
+          <CreateExecutable>1</CreateExecutable>
+          <CreateLib>0</CreateLib>
+          <CreateHexFile>1</CreateHexFile>
+          <DebugInformation>1</DebugInformation>
+          <BrowseInformation>1</BrowseInformation>
+          <ListingPath>.\Listings\</ListingPath>
+          <HexFormatSelection>1</HexFormatSelection>
+          <Merge32K>0</Merge32K>
+          <CreateBatchFile>0</CreateBatchFile>
+          <BeforeCompile>
+            <RunUserProg1>0</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name></UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopU1X>0</nStopU1X>
+            <nStopU2X>0</nStopU2X>
+          </BeforeCompile>
+          <BeforeMake>
+            <RunUserProg1>0</RunUserProg1>
+            <RunUserProg2>0</RunUserProg2>
+            <UserProg1Name></UserProg1Name>
+            <UserProg2Name></UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopB1X>0</nStopB1X>
+            <nStopB2X>0</nStopB2X>
+          </BeforeMake>
+          <AfterMake>
+            <RunUserProg1>1</RunUserProg1>
+            <RunUserProg2>1</RunUserProg2>
+            <UserProg1Name>fromelf.exe --text -a -c --output=@L_asm.txt "!L"</UserProg1Name>
+            <UserProg2Name>"Objects/tool/c.bat"</UserProg2Name>
+            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
+            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
+            <nStopA1X>0</nStopA1X>
+            <nStopA2X>0</nStopA2X>
+          </AfterMake>
+          <SelectedForBatchBuild>0</SelectedForBatchBuild>
+          <SVCSIdString></SVCSIdString>
+        </TargetCommonOption>
+        <CommonProperty>
+          <UseCPPCompiler>0</UseCPPCompiler>
+          <RVCTCodeConst>0</RVCTCodeConst>
+          <RVCTZI>0</RVCTZI>
+          <RVCTOtherData>0</RVCTOtherData>
+          <ModuleSelection>0</ModuleSelection>
+          <IncludeInBuild>1</IncludeInBuild>
+          <AlwaysBuild>0</AlwaysBuild>
+          <GenerateAssemblyFile>0</GenerateAssemblyFile>
+          <AssembleAssemblyFile>0</AssembleAssemblyFile>
+          <PublicsOnly>0</PublicsOnly>
+          <StopOnExitCode>3</StopOnExitCode>
+          <CustomArgument></CustomArgument>
+          <IncludeLibraryModules></IncludeLibraryModules>
+          <ComprImg>1</ComprImg>
+        </CommonProperty>
+        <DllOption>
+          <SimDllName>SARMCM3.DLL</SimDllName>
+          <SimDllArguments>  </SimDllArguments>
+          <SimDlgDll>DARMCM1.DLL</SimDlgDll>
+          <SimDlgDllArguments>-pCM0</SimDlgDllArguments>
+          <TargetDllName>SARMCM3.DLL</TargetDllName>
+          <TargetDllArguments> </TargetDllArguments>
+          <TargetDlgDll>TARMCM1.DLL</TargetDlgDll>
+          <TargetDlgDllArguments>-pCM0</TargetDlgDllArguments>
+        </DllOption>
+        <DebugOption>
+          <OPTHX>
+            <HexSelection>1</HexSelection>
+            <HexRangeLowAddress>0</HexRangeLowAddress>
+            <HexRangeHighAddress>0</HexRangeHighAddress>
+            <HexOffset>0</HexOffset>
+            <Oh166RecLen>16</Oh166RecLen>
+          </OPTHX>
+        </DebugOption>
+        <Utilities>
+          <Flash1>
+            <UseTargetDll>0</UseTargetDll>
+            <UseExternalTool>1</UseExternalTool>
+            <RunIndependent>1</RunIndependent>
+            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
+            <Capability>1</Capability>
+            <DriverSelection>4096</DriverSelection>
+          </Flash1>
+          <bUseTDR>1</bUseTDR>
+          <Flash2>BIN\UL2CM3.DLL</Flash2>
+          <Flash3>"Objects\tool\d.bat" ()</Flash3>
+          <Flash4></Flash4>
+          <pFcarmOut></pFcarmOut>
+          <pFcarmGrp></pFcarmGrp>
+          <pFcArmRoot></pFcArmRoot>
+          <FcArmLst>0</FcArmLst>
+        </Utilities>
+        <TargetArmAds>
+          <ArmAdsMisc>
+            <GenerateListings>0</GenerateListings>
+            <asHll>1</asHll>
+            <asAsm>1</asAsm>
+            <asMacX>1</asMacX>
+            <asSyms>1</asSyms>
+            <asFals>1</asFals>
+            <asDbgD>1</asDbgD>
+            <asForm>1</asForm>
+            <ldLst>0</ldLst>
+            <ldmm>1</ldmm>
+            <ldXref>1</ldXref>
+            <BigEnd>0</BigEnd>
+            <AdsALst>1</AdsALst>
+            <AdsACrf>1</AdsACrf>
+            <AdsANop>0</AdsANop>
+            <AdsANot>0</AdsANot>
+            <AdsLLst>1</AdsLLst>
+            <AdsLmap>1</AdsLmap>
+            <AdsLcgr>1</AdsLcgr>
+            <AdsLsym>1</AdsLsym>
+            <AdsLszi>1</AdsLszi>
+            <AdsLtoi>1</AdsLtoi>
+            <AdsLsun>1</AdsLsun>
+            <AdsLven>1</AdsLven>
+            <AdsLsxf>1</AdsLsxf>
+            <RvctClst>0</RvctClst>
+            <GenPPlst>0</GenPPlst>
+            <AdsCpuType>"Cortex-M0"</AdsCpuType>
+            <RvctDeviceName></RvctDeviceName>
+            <mOS>0</mOS>
+            <uocRom>0</uocRom>
+            <uocRam>0</uocRam>
+            <hadIROM>1</hadIROM>
+            <hadIRAM>1</hadIRAM>
+            <hadXRAM>0</hadXRAM>
+            <uocXRam>0</uocXRam>
+            <RvdsVP>0</RvdsVP>
+            <RvdsMve>0</RvdsMve>
+            <hadIRAM2>0</hadIRAM2>
+            <hadIROM2>0</hadIROM2>
+            <StupSel>8</StupSel>
+            <useUlib>1</useUlib>
+            <EndSel>0</EndSel>
+            <uLtcg>0</uLtcg>
+            <nSecure>0</nSecure>
+            <RoSelD>3</RoSelD>
+            <RwSelD>3</RwSelD>
+            <CodeSel>0</CodeSel>
+            <OptFeed>0</OptFeed>
+            <NoZi1>0</NoZi1>
+            <NoZi2>0</NoZi2>
+            <NoZi3>0</NoZi3>
+            <NoZi4>0</NoZi4>
+            <NoZi5>0</NoZi5>
+            <Ro1Chk>0</Ro1Chk>
+            <Ro2Chk>0</Ro2Chk>
+            <Ro3Chk>0</Ro3Chk>
+            <Ir1Chk>1</Ir1Chk>
+            <Ir2Chk>0</Ir2Chk>
+            <Ra1Chk>0</Ra1Chk>
+            <Ra2Chk>0</Ra2Chk>
+            <Ra3Chk>0</Ra3Chk>
+            <Im1Chk>1</Im1Chk>
+            <Im2Chk>0</Im2Chk>
+            <OnChipMemories>
+              <Ocm1>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm1>
+              <Ocm2>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm2>
+              <Ocm3>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm3>
+              <Ocm4>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm4>
+              <Ocm5>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm5>
+              <Ocm6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </Ocm6>
+              <IRAM>
+                <Type>0</Type>
+                <StartAddress>0x20000000</StartAddress>
+                <Size>0x400000</Size>
+              </IRAM>
+              <IROM>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x400000</Size>
+              </IROM>
+              <XRAM>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </XRAM>
+              <OCR_RVCT1>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT1>
+              <OCR_RVCT2>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT2>
+              <OCR_RVCT3>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT3>
+              <OCR_RVCT4>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x400000</Size>
+              </OCR_RVCT4>
+              <OCR_RVCT5>
+                <Type>1</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT5>
+              <OCR_RVCT6>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT6>
+              <OCR_RVCT7>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT7>
+              <OCR_RVCT8>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT8>
+              <OCR_RVCT9>
+                <Type>0</Type>
+                <StartAddress>0x10010000</StartAddress>
+                <Size>0xb640</Size>
+              </OCR_RVCT9>
+              <OCR_RVCT10>
+                <Type>0</Type>
+                <StartAddress>0x0</StartAddress>
+                <Size>0x0</Size>
+              </OCR_RVCT10>
+            </OnChipMemories>
+            <RvctStartVector></RvctStartVector>
+          </ArmAdsMisc>
+          <Cads>
+            <interw>1</interw>
+            <Optim>1</Optim>
+            <oTime>0</oTime>
+            <SplitLS>0</SplitLS>
+            <OneElfS>0</OneElfS>
+            <Strict>0</Strict>
+            <EnumInt>0</EnumInt>
+            <PlainCh>0</PlainCh>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <wLevel>2</wLevel>
+            <uThumb>0</uThumb>
+            <uSurpInc>0</uSurpInc>
+            <uC99>0</uC99>
+            <uGnu>0</uGnu>
+            <useXO>0</useXO>
+            <v6Lang>1</v6Lang>
+            <v6LangP>1</v6LangP>
+            <vShortEn>1</vShortEn>
+            <vShortWch>1</vShortWch>
+            <v6Lto>0</v6Lto>
+            <v6WtE>0</v6WtE>
+            <v6Rtti>0</v6Rtti>
+            <VariousControls>
+              <MiscControls>--c99 --gnu </MiscControls>
+              <Define></Define>
+              <Undefine></Undefine>
+              <IncludePath>..\..\..\..\..\..\Librarier\device;..\..\..\..\..\..\Librarier\drivers\gpio;..\..\User;..\..\..\..\..\..\Librarier\cmsic;..\..\..\..\..\..\Librarier\drivers\timer;..\..\..\..\..\..\Librarier\drivers\systick;..\..\..\..\..\..\Librarier\drivers\hal_comm;..\..\..\..\..\..\Librarier\drivers\bt;..\..\..\..\..\..\Librarier\drivers\pwm;..\..\..\..\..\Librarier\drivers\hal_comm;..\..\..\..\..\Librarier\device;..\..\..\..\..\Librarier\drivers\gpio;..\..\..\..\..\Librarier\drivers\timer;..\..\..\..\..\Librarier\drivers\systick;..\..\..\..\..\Librarier\drivers\bt;..\..\..\..\..\Librarier\drivers\dev_bt;..\..\..\..\..\Librarier\drivers\uart;..\..\..\..\..\Librarier\drivers\debug;..\..\..\..\..\Librarier\drivers\wdt;..\..\User\device\bt;..\..\User;..\..\User;..\..\User\include;..\..\User\subsys\bluetooth</IncludePath>
+            </VariousControls>
+          </Cads>
+          <Aads>
+            <interw>1</interw>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <thumb>0</thumb>
+            <SplitLS>0</SplitLS>
+            <SwStkChk>0</SwStkChk>
+            <NoWarn>0</NoWarn>
+            <uSurpInc>0</uSurpInc>
+            <useXO>0</useXO>
+            <uClangAs>0</uClangAs>
+            <VariousControls>
+              <MiscControls></MiscControls>
+              <Define></Define>
+              <Undefine></Undefine>
+              <IncludePath></IncludePath>
+            </VariousControls>
+          </Aads>
+          <LDads>
+            <umfTarg>0</umfTarg>
+            <Ropi>0</Ropi>
+            <Rwpi>0</Rwpi>
+            <noStLib>0</noStLib>
+            <RepFail>1</RepFail>
+            <useFile>0</useFile>
+            <TextAddressRange>0x00000000</TextAddressRange>
+            <DataAddressRange>0x100010000</DataAddressRange>
+            <pXoBase></pXoBase>
+            <ScatterFile>.\Objects\yc11xx.sct</ScatterFile>
+            <IncludeLibs></IncludeLibs>
+            <IncludeLibsPath></IncludeLibsPath>
+            <Misc></Misc>
+            <LinkerInputFile></LinkerInputFile>
+            <DisabledWarnings></DisabledWarnings>
+          </LDads>
+        </TargetArmAds>
+      </TargetOption>
+      <Groups>
+        <Group>
+          <GroupName>main</GroupName>
+          <Files>
+            <File>
+              <FileName>main.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\main.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>startup</GroupName>
+          <Files>
+            <File>
+              <FileName>startup.s</FileName>
+              <FileType>2</FileType>
+              <FilePath>.\Objects\startup\startup.s</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>driver</GroupName>
+          <Files>
+            <File>
+              <FileName>yc11xx_gpio.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\gpio\yc11xx_gpio.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc_drv_common.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\hal_comm\yc_drv_common.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx_systick.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\systick\yc11xx_systick.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc_timer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\timer\yc_timer.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx_timer.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\timer\yc11xx_timer.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx_uart.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\uart\yc11xx_uart.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx_bt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\bt\yc11xx_bt.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc_debug.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\debug\yc_debug.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx_wdt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\wdt\yc11xx_wdt.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc11xx.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\device\yc11xx.c</FilePath>
+            </File>
+            <File>
+              <FileName>yc_queue.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\..\..\..\Librarier\drivers\queue\yc_queue.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>utils</GroupName>
+          <Files>
+            <File>
+              <FileName>printk.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\printk.c</FilePath>
+            </File>
+            <File>
+              <FileName>buf.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\buf.c</FilePath>
+            </File>
+            <File>
+              <FileName>queue.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\queue.c</FilePath>
+            </File>
+            <File>
+              <FileName>mempool.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\mempool.c</FilePath>
+            </File>
+            <File>
+              <FileName>hex.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\hex.c</FilePath>
+            </File>
+            <File>
+              <FileName>log.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\common\log.c</FilePath>
+            </File>
+            <File>
+              <FileName>mem_slab.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\utils\mem_slab.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>bluetooth</GroupName>
+          <Files>
+            <File>
+              <FileName>hci_common.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\hci_common.c</FilePath>
+            </File>
+            <File>
+              <FileName>hci_core.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\hci_core.c</FilePath>
+            </File>
+            <File>
+              <FileName>uuid.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\uuid.c</FilePath>
+            </File>
+            <File>
+              <FileName>att.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\att.c</FilePath>
+            </File>
+            <File>
+              <FileName>conn.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\conn.c</FilePath>
+            </File>
+            <File>
+              <FileName>gatt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\gatt.c</FilePath>
+            </File>
+            <File>
+              <FileName>l2cap.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\subsys\bluetooth\host\l2cap.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+        <Group>
+          <GroupName>device</GroupName>
+          <Files>
+            <File>
+              <FileName>yc11xx_dev_bt.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\..\User\device\bt\yc11xx_dev_bt.c</FilePath>
+            </File>
+          </Files>
+        </Group>
+      </Groups>
+    </Target>
+  </Targets>
+
+  <RTE>
+    <apis/>
+    <components/>
+    <files>
+      <file attr="config" category="header" name="CMSIS\Config\RTE_Device.h" version="1.0.0">
+        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\RTE_Device.h</instance>
+        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
+        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
+        <targetInfos/>
+      </file>
+      <file attr="config" category="source" condition="ARMCC" name="Device\CMSDK_CM0\Source\ARM\startup_CMSDK_CM0.s" version="1.0.0">
+        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\startup_CMSDK_CM0.s</instance>
+        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
+        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
+        <targetInfos/>
+      </file>
+      <file attr="config" category="source" name="Device\CMSDK_CM0\Source\system_CMSDK_CM0.c" version="1.0.0">
+        <instance index="0" removed="1">RTE\Device\CMSDK_CM0\system_CMSDK_CM0.c</instance>
+        <component Cclass="Device" Cgroup="Startup" Cvendor="Keil" Cversion="1.0.0" condition="CMSDK_CM0 CMSIS"/>
+        <package name="V2M-MPS2_CMx_BSP" schemaVersion="1.2" url="http://www.keil.com/pack/" vendor="Keil" version="1.7.0"/>
+        <targetInfos/>
+      </file>
+    </files>
+  </RTE>
+
+</Project>
Index: ModuleDemo/BLE/CM0/User/app_config.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/app_config.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/app_config.h	(working copy)
@@ -0,0 +1,18 @@
+#ifndef  _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+#include <stdio.h>
+#include "type.h"
+#include "btreg.h"
+
+
+/////////////////// Function Control///////////////////
+#define FUNCTION_CONTROL_DEBUG_ENABLE
+//#define FUNCTION_WATCH_DOG
+//#define FUNCTION_FSC_RTK_HOST
+#define FUNCTION_FSC_RTK_HOST_WHITE
+
+/////////////////// DEBUG Setting///////////////////
+#define DEBUG_GPIO_DEFINE GPIO_23
+
+#endif //_APP_CONFIG_H_
Index: ModuleDemo/BLE/CM0/User/btreg.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/btreg.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/btreg.h	(working copy)
@@ -0,0 +1,2410 @@
+#ifndef _BT_REG_H_
+#define _BT_REG_H_
+#define	mem_le_adv_transmit                     	0x0000
+#define	mem_le_adv_waitcnt                      	0x0001
+#define	mem_sbc_error                           	0x0002
+#define	mem_le_adv_rcv                          	0x0002
+#define	mem_le_req_rcv                          	0x0003
+#define	mem_le_scanrsp_rcv                      	0x0004
+#define	mem_le_conn_rcv                         	0x0005
+#define	mem_inquiryscan_waitcnt                 	0x0006
+#define	mem_inquiryscan_rcvcnt                  	0x0007
+#define	mem_pagescan_waitcnt                    	0x0008
+#define	mem_pagescan_rcvcnt                     	0x0009
+#define	mem_pagescan_rcvfhscnt                  	0x000a
+#define	mem_slave_rcvcnt                        	0x000b
+#define	mem_page_transmit                       	0x000c
+#define	mem_page_rcv                            	0x000d
+#define	mem_page_rcv_fhs                        	0x000e
+#define	mem_master_rcvcnt                       	0x000f
+#define	mem_fhs_wait_counter                    	0x0010
+#define	mem_newconnto_counter                   	0x0011
+#define	mem_inquiry_transmit                    	0x0012
+#define	mem_inquiry_rcv                         	0x0013
+#define	mem_fw_ver                              	0x0014
+#define	mem_current_context                     	0x0015
+#define	mem_empty_block                         	0x0016
+#define	mem_last_freq                           	0x0017
+#define	mem_rssi                                	0x0018
+#define	mem_rx_type                             	0x0019
+#define	mem_rx_hec_err                          	0x001a
+#define	mem_rx_crc_err                          	0x001c
+#define	mem_context_ptr                         	0x001e
+#define	mem_display                             	0x0020
+#define	mem_bcd                                 	0x0028
+#define	mem_state                               	0x0030
+#define	mem_mode                                	0x0031
+#define	mem_tsniff                              	0x0032
+#define	mem_sniff_anchor                        	0x0034
+#define	mem_clk_offset                          	0x0038
+#define	mem_rx_window                           	0x003e
+#define	mem_plap                                	0x0040
+#define	mem_puap                                	0x0043
+#define	mem_pnap                                	0x0044
+#define	mem_conn_handle                         	0x0046
+#define	mem_cur_arq                             	0x0047
+#define	mem_lmp_to_send                         	0x0048
+#define	mem_lmi_opcode                          	0x0049
+#define	mem_lmo_reason                          	0x004a
+#define	mem_op                                  	0x004b
+#define	mem_state_map                           	0x004c
+#define	mem_supervision_timer                   	0x004d
+#define	mem_supervision_to                      	0x0051
+#define	mem_name_offset                         	0x0053
+#define	mem_key_size                            	0x0054
+#define	mem_reconn_lmp_sm                       	0x0055
+#define	mem_aco                                 	0x0056
+#define	mem_kc                                  	0x0062
+#define	mem_conn_timer                          	0x0072
+#define	mem_sniff_attempt                       	0x0073
+#define	mem_sniff_timeout                       	0x0074
+#define	mem_dsniff                              	0x0075
+#define	mem_amaddr                              	0x0077
+#define	mem_lmo_opcode1                         	0x0078
+#define	mem_lmi_opcode1                         	0x0079
+#define	mem_lmo_reason1                         	0x007a
+#define	mem_lmo_tid1                            	0x007b
+#define	mem_lmo_opcode2                         	0x007c
+#define	mem_lmi_opcode2                         	0x007d
+#define	mem_lmo_reason2                         	0x007e
+#define	mem_lmo_tid2                            	0x007f
+#define	mem_mark_load                           	0x0080
+#define	mem_hci_version                         	0x0088
+#define	mem_acl_pktlen                          	0x008b
+#define	mem_sco_pktlen                          	0x008d
+#define	mem_acl_pktcnt                          	0x008e
+#define	mem_sco_pktcnt                          	0x0090
+#define	mem_current_sniff_attempt               	0x0092
+#define	mem_current_sniff_timeout               	0x0093
+#define	mem_nfreq_index_inq                     	0x0094
+#define	mem_nfreq_index_page                    	0x0095
+#define	mem_ninqy_index                         	0x0096
+#define	mem_fhs_misc                            	0x0097
+#define	mem_tx_lch                              	0x0098
+#define	mem_tx_len                              	0x0099
+#define	mem_subsniff_instant                    	0x009b
+#define	mem_subsniff_rate                       	0x009f
+#define	mem_subsniff_tcmax                      	0x00a0
+#define	mem_subsniff_tsniff                     	0x00a2
+#define	mem_lpm_adjust                          	0x00a3
+#define	mem_sync_clke                           	0x00a4
+#define	mem_lpm_current_mult                    	0x00aa
+#define	mem_gpio_wakeup_low                     	0x00ab
+#define	mem_gpio_wakeup_high                    	0x00b0
+#define	mem_npage_index                         	0x00b5
+#define	mem_page_mode                           	0x00b6
+#define	mem_page_clk                            	0x00b7
+#define	mem_tst_pktcnt_sync                     	0x00bb
+#define	mem_tst_pktcnt_hec                      	0x00bd
+#define	mem_tst_pktcnt_crc                      	0x00bf
+#define	mem_tst_pktcnt_dmh                      	0x00c1
+#define	mem_tmp_buffer_head                     	0x00c3
+#define	mem_tmp_buffer                          	0x00c6
+#define	mem_tester_emulate                      	0x0116
+#define	mem_temp_payload                        	0x0117
+#define	test_mode_scenario                      	0x0117
+#define	test_mode_hopping_mode                  	0x0118
+#define	test_mode_tx_freq                       	0x0119
+#define	test_mode_rx_freq                       	0x011a
+#define	test_mode_power_mode                    	0x011b
+#define	test_mode_poll_period                   	0x011c
+#define	test_mode_packet_type                   	0x011d
+#define	test_mode_data_length                   	0x011e
+#define	mem_test_mode_old_debug_config          	0x0120
+#define	mem_tester_cnt                          	0x0121
+#define	mem_temp_am_addr                        	0x0122
+#define	mem_temp_arq                            	0x0123
+#define	mem_pdatatemp                           	0x0124
+#define	mem_len                                 	0x012c
+#define	mem_clkn_bt                             	0x012e
+#define	mem_clke_bt                             	0x0132
+#define	mem_dpll_clkn                           	0x0136
+#define	mem_connection_options                  	0x013a
+#define	mem_nameres_cnt                         	0x013b
+#define	mem_txptr                               	0x013c
+#define	mem_slot_offset                         	0x013e
+#define	mem_wait_auth_clk                       	0x0140
+#define	extm_fhs_misc                           	0x0144
+#define	extm_newconn_am_addr                    	0x0145
+#define	extm_class                              	0x0146
+#define	extm_lap                                	0x0149
+#define	extm_uap                                	0x014c
+#define	extm_nap                                	0x014d
+#define	mem_debug_config                        	0x0150
+#define	mem_lch_code                            	0x0151
+#define	mem_fhs_am_addr                         	0x0152
+#define	mem_dpll_error                          	0x0153
+#define	mem_bdaddr_list_buff                    	0x0155
+#define	mem_select_list_item                    	0x0179
+#define	mem_temp_reconn_record                  	0x017a
+#define	mem_record_bt_mode                      	0x017a
+#define	mem_temp_lap                            	0x017b
+#define	mem_list_item_ptr                       	0x0181
+#define	mem_eir                                 	0x0183
+#define	mem_switch_timeout                      	0x01e7
+#define	mem_acl_dsniff                          	0x01e9
+#define	mem_acl_tsniff                          	0x01eb
+#define	mem_acl_attempt                         	0x01ed
+#define	mem_acl_timeout                         	0x01ee
+#define	mem_temp_force_nack                     	0x01ef
+#define	mem_avdtp_signal_cmd                    	0x01f0
+#define	mem_transaction_label                   	0x01f1
+#define	mem_temp_sbc_decode_buffer_size         	0x01f2
+#define	mem_temp_dac_soft_dma_work_wptr         	0x01f4
+#define	mem_temp_sbc_soft_dma_start_addr        	0x01f6
+#define	mem_temp_dac_soft_dma_start_addr        	0x01f8
+#define	mem_temp_soft_dma_work_length           	0x01fa
+#define	mem_temp_soft_dma_work_table_index_value	0x01fc
+#define	mem_ucode_status                        	0x01fd
+#define	mem_ucode_flag                          	0x01fe
+#define	mem_qspi_tbuf                           	0x0200
+#define	mem_iicd_tbuf                           	0x0201
+#define	mem_addr_hi                             	0x0201
+#define	mem_eep_addr_hi                         	0x0202
+#define	mem_addr_mi                             	0x0202
+#define	mem_addr_lo                             	0x0203
+#define	mem_iicd_addr                           	0x0204
+#define	mem_spid_rbuf                           	0x0205
+#define	mem_ucode_buf                           	0x0209
+#define	mem_ucode_len                           	0x020b
+#define	mem_sched_addr                          	0x020d
+#define	mem_ucode_ptr                           	0x020f
+#define	mem_ucode_keybuf                        	0x0212
+#define	mem_check_plap_temp                     	0x0222
+#define	mem_start_addr_temp                     	0x0234
+#define	mem_spid_tbuf                           	0x0237
+#define	mem_qspi_defualt                        	0x0239
+#define	mem_switch_fail_master_count            	0x023a
+#define	mem_app_evt_timer_count                 	0x023b
+#define	mem_flash_address                       	0x023c
+#define	mem_flash_data_address                  	0x023f
+#define	mem_flash_trans_length                  	0x0241
+#define	mem_soft_dma_src_addr                   	0x0243
+#define	mem_soft_dma_dst_addr                   	0x0247
+#define	mem_avctp_command_response              	0x024b
+#define	mem_avrcp_vol                           	0x024c
+#define	mem_avctp_rx_label                      	0x024d
+#define	mem_h5rx_ackcnt                         	0x024e
+#define	mem_check_err_acl_cont                  	0x024f
+#define	mem_rp_packets                          	0x0250
+#define	mem_packet_type                         	0x0251
+#define	mem_hci_sniff_conn_handle               	0x0253
+#define	mem_hci_sniff_max_interval              	0x0255
+#define	mem_hci_sniff_min_interval              	0x0257
+#define	mem_hci_sniff_attempt                   	0x0259
+#define	mem_hci_sniff_timeout                   	0x025b
+#define	mem_voice_setting                       	0x025d
+#define	mem_retransmission_effort               	0x025f
+#define	mem_sco_ptype                           	0x0260
+#define	mem_extm_uap_restore                    	0x0262
+#define	mem_h5rx_rptr                           	0x0265
+#define	mem_h5rx_ack                            	0x0267
+#define	mem_h5tx_ack                            	0x0268
+#define	mem_h5tx_rptr                           	0x0269
+#define	mem_h5tx_wptr                           	0x026b
+#define	mem_h5tx_free                           	0x026d
+#define	mem_h5rx_tmp                            	0x026f
+#define	mem_h5tx_seq                            	0x0270
+#define	mem_hci_acl_queue_wptr                  	0x0271
+#define	mem_hci_acl_queue_rptr                  	0x0273
+#define	mem_hci_acl_queue_end                   	0x0275
+#define	mem_hci_acl_queue_wcnt                  	0x0277
+#define	mem_hci_acl_cnt                         	0x0278
+#define	mem_hci_acl_tx_trigger_wptr             	0x0279
+#define	mem_ucode_id_local                      	0x027b
+#define	mem_ucode_id_remote                     	0x027c
+#define	mem_check_sum                           	0x027d
+#define	mem_ucode_temp                          	0x027e
+#define	mem_ucode_temp1                         	0x027f
+#define	mem_lock_in_enc                         	0x0280
+#define	mem_hci_disconn_reason                  	0x0281
+#define	mem_hci_curr_len                        	0x0282
+#define	mem_hci_curr_target                     	0x0283
+#define	mem_coef_table_temp                     	0x0285
+#define	mem_sco_indata                          	0x03d7
+#define	mem_sco_outdata                         	0x0413
+#define	mem_phone_num_count                     	0x044f
+#define	mem_phone_num_len                       	0x0450
+#define	mem_phone_number                        	0x0451
+#define	mem_at_command_data                     	0x0460
+#define	mem_sco_flag                            	0x047e
+#define	mem_l2cap_mem_start                     	0x047f
+#define	mem_l2cap_rxbuff1_len                   	0x047f
+#define	mem_l2cap_rxbuff2_len                   	0x0481
+#define	mem_l2cap_rxbuff_new_temp               	0x0483
+#define	mem_l2cap_rxbuff_new                    	0x0484
+#define	mem_l2cap_rxbuff_fifo                   	0x0485
+#define	mem_l2cap_rxbuff_fifo1                  	0x0485
+#define	mem_l2cap_rxbuff_fifo2                  	0x0486
+#define	mem_l2cap_payload_ptr                   	0x0487
+#define	mem_l2cap_rx_pkt_length                 	0x0489
+#define	mem_l2cap_rx_cid                        	0x048b
+#define	mem_l2cap_rx_done                       	0x048d
+#define	mem_l2cap_signal_ident                  	0x048e
+#define	mem_sdp_tx_buff_ptr                     	0x048f
+#define	mem_sdp_tx_payload_ptr                  	0x0491
+#define	mem_sdp_tx_pkt_length                   	0x0493
+#define	mem_tx_malloc_log                       	0x0495
+#define	mem_l2cap_temp_ch_info                  	0x04d5
+#define	mem_l2cap_temp_ch_psm                   	0x04d5
+#define	mem_l2cap_temp_ch_state                 	0x04d6
+#define	mem_l2cap_temp_local_cid                	0x04d7
+#define	mem_l2cap_temp_remote_cid               	0x04d9
+#define	mem_l2cap_mem_end                       	0x04db
+#define	mem_le_rxbuf                            	0x04db
+#define	mem_le_l2capbuf                         	0x0503
+#define	mem_le_mic                              	0x05db
+#define	mem_le_peer_mic                         	0x05df
+#define	mem_le_skdm                             	0x05e3
+#define	mem_le_skds                             	0x05eb
+#define	mem_le_peer_ltk                         	0x05f3
+#define	mem_le_my_ltk                           	0x0603
+#define	mem_le_mrand                            	0x0613
+#define	mem_le_state                            	0x0623
+#define	mem_le_mode                             	0x0624
+#define	mem_le_tsniff                           	0x0625
+#define	mem_le_anchor                           	0x0627
+#define	mem_le_clk_offset                       	0x062b
+#define	mem_le_receive_window                   	0x0631
+#define	mem_le_plap                             	0x0633
+#define	mem_le_conn_handle                      	0x0639
+#define	mem_le_arq                              	0x063a
+#define	mem_le_ch                               	0x063b
+#define	mem_le_hop                              	0x063c
+#define	mem_le_event_count                      	0x063d
+#define	mem_le_supervision_timer                	0x063f
+#define	mem_le_instant                          	0x0643
+#define	mem_le_channels                         	0x0645
+#define	mem_le_conn_sm                          	0x0646
+#define	mem_le_op                               	0x0647
+#define	mem_le_access                           	0x0648
+#define	mem_le_crcinit                          	0x064c
+#define	mem_le_window_size                      	0x064f
+#define	mem_le_slave_latency                    	0x0650
+#define	mem_le_superto                          	0x0652
+#define	mem_le_channel_map                      	0x0654
+#define	mem_le_no_using                         	0x0659
+#define	mem_le_peer_sca                         	0x065b
+#define	mem_le_att_opcode                       	0x065c
+#define	mem_le_att_handle                       	0x065d
+#define	mem_le_err_code                         	0x065f
+#define	mem_le_ll_pairing_fail_reason           	0x0660
+#define	mem_le_sk                               	0x0661
+#define	mem_le_testtype                         	0x0671
+#define	mem_le_test_sync                        	0x0672
+#define	mem_le_test_pcnt                        	0x0674
+#define	mem_le_notify_len                       	0x0676
+#define	mem_cmd_le_create_conn                  	0x0677
+#define	mem_le_adv_temp                         	0x0678
+#define	mem_le_packet_size                      	0x068c
+#define	mem_le_packet_llid                      	0x068d
+#define	mem_le_payload_ptr                      	0x068e
+#define	mem_lmo_header_length                   	0x0690
+#define	mem_lmo_header_opcode                   	0x0691
+#define	mem_lmo_payload                         	0x0692
+#define	mem_lmi_accepted_opcode                 	0x06a3
+#define	mem_disconn_reason_send                 	0x06a4
+#define	mem_tx_fixed_freq                       	0x06a5
+#define	mem_rx_fixed_freq                       	0x06a6
+#define	mem_ext_features_page                   	0x06a7
+#define	mem_lmpext_ssp_enable                   	0x06a8
+#define	mem_remote_sppcap                       	0x06aa
+#define	mem_lmp_conn_state                      	0x06ab
+#define	mem_soft_timer                          	0x06ac
+#define	mem_pincode_state                       	0x06ae
+#define	mem_sres_tid                            	0x06af
+#define	mem_accptsco_tid                        	0x06b0
+#define	mem_wait_encryption                     	0x06b1
+#define	mem_sniff_payload                       	0x06b2
+#define	mem_aurand_send_delay_time              	0x06c2
+#define	mem_prcp_data                           	0x06c6
+#define	mem_prcp                                	0x06da
+#define	mem_prcp_tx_len                         	0x06db
+#define	rx_buf_data_ptr                         	0x06dc
+#define	mem_mod2div_temp                        	0x06de
+#define	mem_contw_temp                          	0x06e1
+#define	mem_rfc_adss                            	0x06e3
+#define	mem_rfc_current_channel                 	0x06e4
+#define	mem_rfc_frame_type                      	0x06e5
+#define	mem_current_fcs                         	0x06e6
+#define	mem_rfc_paylead_length                  	0x06e7
+#define	mem_rfc_paylead_ptr                     	0x06e9
+#define	mem_uih_cmd_type                        	0x06eb
+#define	mem_uih_length                          	0x06ec
+#define	mem_rfc_payload_ptr                     	0x06ee
+#define	mem_ms_param                            	0x06f0
+#define	mem_pn_credit_flow_type_info            	0x06f1
+#define	mem_pn_priority                         	0x06f2
+#define	mem_pn_acknowledg_timer                 	0x06f3
+#define	mem_pn_max_retrans                      	0x06f4
+#define	mem_rfcomm_send_adss                    	0x06f5
+#define	mem_rfcomm_send_frame_type              	0x06f6
+#define	mem_rfcomm_send_fcs                     	0x06f7
+#define	mem_sdp_mem_start                       	0x06f8
+#define	mem_sdp_uuid_search_ptr                 	0x06f8
+#define	mem_sdp_continue_byte                   	0x0700
+#define	mem_sdp_pduid                           	0x0702
+#define	mem_sdp_transactionid                   	0x0703
+#define	mem_sdp_transactionid_local             	0x0705
+#define	mem_sdp_attribute_maxbyte               	0x0707
+#define	mem_sdp_record_maxcnt                   	0x0709
+#define	mem_sdp_record_handle                   	0x070b
+#define	mem_sdp_LACAP_found                     	0x070f
+#define	mem_sdp_RFCOMM_found                    	0x0710
+#define	mem_sdp_handle_list                     	0x0711
+#define	mem_sdp_attrib_list                     	0x0711
+#define	mem_sdp_error_code                      	0x0731
+#define	mem_sdp_all_length                      	0x0733
+#define	mem_handle_humber                       	0x0735
+#define	mem_search_uuid                         	0x0736
+#define	mem_sdp_mem_end                         	0x0738
+#define	mem_rxbuf                               	0x0738
+#define	mem_random_number                       	0x0749
+#define	mem_round_key                           	0x0759
+#define	mem_kinit                               	0x0769
+#define	mem_input_store                         	0x0779
+#define	mem_x                                   	0x0789
+#define	mem_y                                   	0x0799
+#define	mem_y15                                 	0x07a8
+#define	mem_key_store                           	0x07a9
+#define	mem_key_store_end                       	0x07ba
+#define	memp_ar_key                             	0x07bb
+#define	memp_ar_input                           	0x07bd
+#define	mem_ar_hround                           	0x07bf
+#define	mem_ec_infinite                         	0x07c9
+#define	mem_ec_loopc                            	0x07ca
+#define	mem_aes_cmac_data_length                	0x07cc
+#define	memdat                                  	0x07cd
+#define	mem_ax                                  	0x07cd
+#define	mem_ay                                  	0x07e5
+#define	mem_az                                  	0x07fd
+#define	mem_bx                                  	0x0815
+#define	mem_ax_256                              	0x082d
+#define	mem_by                                  	0x082d
+#define	mem_bz                                  	0x0845
+#define	mem_ay_256                              	0x084d
+#define	mem_cx                                  	0x085d
+#define	mem_az_256                              	0x086d
+#define	mem_cy                                  	0x0875
+#define	mem_cy5                                 	0x088c
+#define	mem_bx_256                              	0x088d
+#define	mem_cz                                  	0x088d
+#define	mem_k                                   	0x08a5
+#define	mem_by_256                              	0x08ad
+#define	mem_align                               	0x08bd
+#define	mem_bz_256                              	0x08cd
+#define	mem_tmp1                                	0x08cd
+#define	memahbak                                	0x08cd
+#define	mem_tmp5                                	0x08e5
+#define	mem_cx_256                              	0x08ed
+#define	memahsave                               	0x08ed
+#define	mem_tmp2                                	0x08fd
+#define	mem_cy_256                              	0x090d
+#define	memahsave_end                           	0x090d
+#define	mem_addr_padding                        	0x090d
+#define	mem_addr_value                          	0x090e
+#define	mem_tmp3                                	0x0915
+#define	mem_t1                                  	0x0915
+#define	mem_addr_value_end                      	0x091a
+#define	mem_addr_iocap_end                      	0x091d
+#define	mem_cy5_256                             	0x092c
+#define	mem_cz_256                              	0x092d
+#define	mem_tmp0                                	0x092d
+#define	mem_t0                                  	0x092d
+#define	mem_tmp0a                               	0x0935
+#define	mem_t2                                  	0x0945
+#define	mem_k_256                               	0x094d
+#define	mem_t3                                  	0x095d
+#define	mem_tmp1_256                            	0x096d
+#define	mem_t7                                  	0x0975
+#define	mem_tmp5_256                            	0x098d
+#define	mem_tmp2_256                            	0x09ad
+#define	mem_tmp3_256                            	0x09cd
+#define	mem_t1_256                              	0x09cd
+#define	mem_tmp0_256                            	0x09ed
+#define	mem_t0_256                              	0x09ed
+#define	mem_t2_256                              	0x0a0d
+#define	mem_t3_256                              	0x0a2d
+#define	mem_t7_256                              	0x0a4d
+#define	mem_p                                   	0x0a6d
+#define	mem_a                                   	0x0a85
+#define	mem_b                                   	0x0a9d
+#define	mem_gx                                  	0x0ab5
+#define	mem_gy                                  	0x0acd
+#define	memh0                                   	0x0ae5
+#define	mem_p_256                               	0x0b05
+#define	mem_a_256                               	0x0b25
+#define	mem_gx_256                              	0x0b45
+#define	mem_gy_256                              	0x0b65
+#define	mem_le_slat                             	0x0b85
+#define	mem_sp_state_start                      	0x0b95
+#define	mem_sp_state                            	0x0b95
+#define	mem_master_sp_state                     	0x0b96
+#define	mem_sp_flag                             	0x0b97
+#define	mem_master_sp_flag                      	0x0b98
+#define	mem_sp_calc                             	0x0b99
+#define	mem_sp_dh_ready                         	0x0b9a
+#define	mem_sp_localsm                          	0x0b9b
+#define	mem_pairing_auth                        	0x0b9c
+#define	mem_sp_flag_start                       	0x0b9d
+#define	mem_sp_local_key_send_count             	0x0b9d
+#define	mem_sp_remote_key_recv_count            	0x0b9e
+#define	mem_sp_remote_key_invalid               	0x0b9f
+#define	mem_sp_dhkey_invalid                    	0x0ba0
+#define	mem_gkey                                	0x0ba1
+#define	mem_le_pubkey_remote_x_256              	0x0ba5
+#define	mem_sp_pubkey_remote                    	0x0bad
+#define	mem_sp_pubkey_remote_x                  	0x0bad
+#define	mem_sp_pubkey_remote_x_end              	0x0bc5
+#define	mem_sp_pubkey_remote_y                  	0x0bc5
+#define	mem_le_pubkey_remote_y_256              	0x0bc5
+#define	mem_le_dhkey_256                        	0x0be5
+#define	mem_sp_dhkey                            	0x0bed
+#define	mem_sp_dhkey_end                        	0x0c05
+#define	mem_sp_random_local                     	0x0c05
+#define	mem_sp_random_local_end                 	0x0c15
+#define	mem_sp_random_remote                    	0x0c15
+#define	mem_sp_random_remote_end                	0x0c25
+#define	memresult                               	0x0c25
+#define	mem_sp_calc_result                      	0x0c25
+#define	memh                                    	0x0c25
+#define	memg                                    	0x0c29
+#define	memf                                    	0x0c2d
+#define	meme                                    	0x0c31
+#define	mem_sp_calc_result_high                 	0x0c35
+#define	memd                                    	0x0c35
+#define	memc                                    	0x0c39
+#define	memb                                    	0x0c3d
+#define	mema                                    	0x0c41
+#define	mem_sp_check_result                     	0x0c45
+#define	mem_sp_confirm_remote                   	0x0c55
+#define	mem_sp_prarm_stack                      	0x0c65
+#define	mem_ipc_skip_continue_proc              	0x0c75
+#define	mem_row_scanned_record                  	0x0c76
+#define	mem_col_scanned_record                  	0x0c77
+#define	mem_get_keypress_flag_record            	0x0c78
+#define	mem_usb_status                          	0x0c79
+#define	mem_usb_fifo_empty                      	0x0c7a
+#define	mem_usb_read_len                        	0x0c7b
+#define	mem_usb_txbuf                           	0x0c7d
+#define	mem_usb_txbuf1                          	0x0cbe
+#define	mem_usb_txbuf2                          	0x0cc8
+#define	mem_usb_rxbuf                           	0x0cd2
+#define	mem_usb_rxbuf_end                       	0x0d0e
+#define	mem_usb_state                           	0x0d0f
+#define	mem_bufptr                              	0x0d10
+#define	mem_remain                              	0x0d12
+#define	mem_devicedesc                          	0x0d13
+#define	mem_hidreportdesc_kb                    	0x0d27
+#define	mem_hidreportdesc_m                     	0x0d6d
+#define	mem_confdesc                            	0x0e35
+#define	mem_string0                             	0x0e7b
+#define	mem_string1                             	0x0e80
+#define	mem_string2                             	0x0e9e
+#define	mem_string3                             	0x0ebc
+#define	mem_usb_setup                           	0x0eda
+#define	mem_usb_setup_bmRequestType             	0x0eda
+#define	mem_usb_setup_bRequest                  	0x0edb
+#define	mem_usb_setup_bValue                    	0x0edc
+#define	mem_usb_setup_bValueH                   	0x0edd
+#define	mem_usb_setup_wIndex                    	0x0ede
+#define	mem_usb_setup_bLength                   	0x0ee0
+#define	mem_usb_setup_bLengthH                  	0x0ee1
+#define	mem_usb0_setup_ptr                      	0x0ee2
+#define	mem_usb0_set_report_data_ptr            	0x0ee4
+#define	mem_usb_setup_bValue_temp               	0x0ee6
+#define	mem_usb0_get_set_report                 	0x0ee8
+#define	mem_usb0_data_ready_report              	0x0ee9
+#define	mem_usb_tx_win_enable                   	0x0eea
+#define	mem_usb_tx_mac_enable                   	0x0eeb
+#define	mem_usb_zero_packet                     	0x0eec
+#define	mem_usb_ones_packet                     	0x0eee
+#define	mem_usb_two_packet                      	0x0ef0
+#define	mem_usb_idle_flag                       	0x0ef2
+#define	mem_usb_idle_rate                       	0x0ef3
+#define	mem_usb_get_protocol_flag               	0x0ef4
+#define	mem_usb_set_protocol_status             	0x0ef5
+#define	mem_usb_set_protocol_value              	0x0ef6
+#define	mem_usb0_state                          	0x0ef7
+#define	mem_usb_remote_wakeup                   	0x0ef8
+#define	mem_usb_clear_remote_wakeup             	0x0ef9
+#define	mem_usb_ep0_stall_status                	0x0efa
+#define	mem_usb_ep1_stall_status                	0x0efb
+#define	mem_usb_ep2_stall_status                	0x0efc
+#define	mem_usb_ep3_stall_status                	0x0efd
+#define	mem_dsc_info_data_pointer               	0x0efe
+#define	mem_dsc_info_len                        	0x0f00
+#define	mem_usb_ep1_data                        	0x0f01
+#define	mem_usb_ep2_data                        	0x0f02
+#define	mem_usb_tx_enable                       	0x0f03
+#define	mem_usb_device_enumeration_endflag      	0x0f04
+#define	mem_usb_wakestate_onetime_flag          	0x0f05
+#define	mem_usb_mac_wakeup_trig                 	0x0f06
+#define	mem_usb_set_high_addr_flag              	0x0f07
+#define	mem_usb_clear_halt                      	0x0f08
+#define	mem_hold_contr                          	0x0f09
+#define	mem_hold_contw                          	0x0f0b
+#define	mem_fifo_temp                           	0x0f0d
+#define	mem_max_bitsneed                        	0x0f0e
+#define	mem_bits_need00                         	0x0f12
+#define	mem_temp                                	0x0f12
+#define	mem_bits_need01                         	0x0f16
+#define	mem_temp1                               	0x0f16
+#define	mem_bits_need02                         	0x0f1a
+#define	mem_timeup                              	0x0f1a
+#define	mem_bits_need03                         	0x0f1e
+#define	mem_rega                                	0x0f1e
+#define	mem_bits_need04                         	0x0f22
+#define	mem_regb                                	0x0f22
+#define	mem_bits_need05                         	0x0f26
+#define	mem_regc                                	0x0f26
+#define	mem_bits_need06                         	0x0f2a
+#define	mem_contr                               	0x0f2a
+#define	mem_contw                               	0x0f2c
+#define	mem_bits_need07                         	0x0f2e
+#define	mem_bits_need10                         	0x0f32
+#define	mem_bits_need11                         	0x0f36
+#define	mem_bits_need12                         	0x0f3a
+#define	mem_bits_need13                         	0x0f3e
+#define	mem_bits_need14                         	0x0f42
+#define	mem_bits_need15                         	0x0f46
+#define	mem_bits_need16                         	0x0f4a
+#define	mem_bits_need17                         	0x0f4e
+#define	mem_wakup_from_power_flag               	0x0f52
+#define	mem_saved_gpio_in                       	0x0f53
+#define	mem_flash_data_address_t                	0x0f57
+#define	mem_le_data_len_temp                    	0x0f57
+#define	mem_tx_fifo_map_temp                    	0x0f57
+#define	mem_rpn_dlci                            	0x0f57
+#define	mem_event_cmd_response_content          	0x0f57
+#define	mem_le_prand                            	0x0f57
+#define	mem_AES_CMAC_k                          	0x0f57
+#define	mem_regext_index                        	0x0f57
+#define	mem_temp_block0                         	0x0f57
+#define	mem_le_data_temp                        	0x0f58
+#define	mem_temp_block1                         	0x0f58
+#define	mem_le_aes_128                          	0x0f67
+#define	mem_regext                              	0x0f67
+#define	mem_AES_CMAC_k1                         	0x0f67
+#define	mem_sum_temp                            	0x0f67
+#define	mem_temp_block2                         	0x0f67
+#define	mem_AES_CMAC_k2                         	0x0f77
+#define	mem_temp_block3                         	0x0f77
+#define	mem_AES_CMAC_temp                       	0x0f87
+#define	mem_temp_block4                         	0x0f87
+#define	mem_AES_CMAC_M_last                     	0x0f97
+#define	mem_temp_block5                         	0x0f97
+#define	mem_le_mackey                           	0x0fa7
+#define	mem_temp_block6                         	0x0fa7
+#define	mem_zcode_temp_param0                   	0x0fb7
+#define	mem_zcode_temp_param1                   	0x0fb8
+#define	mem_zcode_temp_param2                   	0x0fba
+#define	mem_tws_sync_clk                        	0x0fbc
+#define	mem_tws_connecting_phase                	0x0fc0
+#define	mem_temp_tx_power                       	0x0fc1
+#define	mem_msbc_miss                           	0x0fc2
+#define	mem_msbc_error                          	0x0fc4
+#define	mem_vp_length                           	0x0fc6
+#define	mem_ota_cmd                             	0x0fc9
+#define	mem_ota_return_result                   	0x0fca
+#define	mem_ota_update_flash_mode               	0x0fcb
+#define	mem_ota_write_index                     	0x0fcc
+#define	mem_ota_write_length                    	0x0fce
+#define	mem_ota_write_data_addr                 	0x0fd0
+#define	mem_ota_write_flash_addr                	0x0fd3
+#define	mem_ota_enable_xip_flag                 	0x0fd6
+#define	mem_xip_flash_offset_mram               	0x0fd7
+#define	mem_storage_start_addr_mram             	0x0fda
+#define	mem_ota_notify_handle_mram              	0x0fdd
+#define	mem_ota_write_handle_mram               	0x0fde
+#define	mem_ota_buck_size_mram                  	0x0fdf
+#define	mem_ota_packet_max_len_mram             	0x0fe1
+#define	mem_ota_wdt_en_flag                     	0x0fe3
+#define	mem_ota_wdt_m0_en                       	0x0fe4
+#define	mem_patch00                             	0x4000
+#define	mem_patch01                             	0x4001
+#define	mem_patch02                             	0x4002
+#define	mem_patch03                             	0x4003
+#define	mem_patch04                             	0x4004
+#define	mem_patch05                             	0x4005
+#define	mem_patch06                             	0x4006
+#define	mem_patch07                             	0x4007
+#define	mem_patch08                             	0x4008
+#define	mem_patch09                             	0x4009
+#define	mem_patch0a                             	0x400a
+#define	mem_patch0b                             	0x400b
+#define	mem_patch0c                             	0x400c
+#define	mem_patch0d                             	0x400d
+#define	mem_patch0e                             	0x400e
+#define	mem_patch0f                             	0x400f
+#define	mem_patch10                             	0x4010
+#define	mem_patch11                             	0x4011
+#define	mem_patch12                             	0x4012
+#define	mem_patch13                             	0x4013
+#define	mem_patch14                             	0x4014
+#define	mem_patch15                             	0x4015
+#define	mem_patch16                             	0x4016
+#define	mem_patch17                             	0x4017
+#define	mem_patch18                             	0x4018
+#define	mem_patch19                             	0x4019
+#define	mem_patch1a                             	0x401a
+#define	mem_patch1b                             	0x401b
+#define	mem_patch1c                             	0x401c
+#define	mem_patch1d                             	0x401d
+#define	mem_patch1e                             	0x401e
+#define	mem_patch1f                             	0x401f
+#define	mem_patch20                             	0x4020
+#define	mem_patch21                             	0x4021
+#define	mem_patch22                             	0x4022
+#define	mem_patch23                             	0x4023
+#define	mem_patch24                             	0x4024
+#define	mem_patch25                             	0x4025
+#define	mem_patch26                             	0x4026
+#define	mem_patch27                             	0x4027
+#define	mem_patch28                             	0x4028
+#define	mem_patch29                             	0x4029
+#define	mem_patch2a                             	0x402a
+#define	mem_patch2b                             	0x402b
+#define	mem_patch2c                             	0x402c
+#define	mem_patch2d                             	0x402d
+#define	mem_patch2e                             	0x402e
+#define	mem_patch2f                             	0x402f
+#define	mem_patch30                             	0x4030
+#define	mem_patch31                             	0x4031
+#define	mem_patch32                             	0x4032
+#define	mem_patch33                             	0x4033
+#define	mem_patch34                             	0x4034
+#define	mem_patch35                             	0x4035
+#define	mem_patch36                             	0x4036
+#define	mem_patch37                             	0x4037
+#define	mem_patch38                             	0x4038
+#define	mem_patch39                             	0x4039
+#define	mem_patch3a                             	0x403a
+#define	mem_patch3b                             	0x403b
+#define	mem_patch3c                             	0x403c
+#define	mem_patch3d                             	0x403d
+#define	mem_patch3e                             	0x403e
+#define	mem_patch3f                             	0x403f
+#define	mem_context                             	0x4040
+#define	mem_current_amaddr                      	0x4130
+#define	mem_lpm_mode                            	0x4131
+#define	mem_device_option                       	0x4132
+#define	mem_scan_mode                           	0x4133
+#define	mem_last_clkn                           	0x4134
+#define	mem_features                            	0x4138
+#define	mem_lap                                 	0x4140
+#define	mem_uap                                 	0x4143
+#define	mem_nap                                 	0x4144
+#define	mem_npage                               	0x4146
+#define	mem_glap                                	0x4147
+#define	mem_class                               	0x414a
+#define	mem_iscan_window                        	0x414d
+#define	mem_iscan_interval                      	0x414f
+#define	mem_pscan_window                        	0x4151
+#define	mem_pscan_interval                      	0x4153
+#define	mem_page_interval                       	0x4155
+#define	mem_page_window                         	0x4157
+#define	mem_page_to                             	0x4159
+#define	mem_inq_window                          	0x415b
+#define	mem_fcomp_mul                           	0x415d
+#define	mem_fcomp_div                           	0x415e
+#define	mem_rx_window_init                      	0x415f
+#define	mem_rx_window_sniff                     	0x4161
+#define	mem_rf_init_ptr                         	0x4163
+#define	mem_rf_init                             	0x4165
+#define	mem_last_type                           	0x4166
+#define	mem_retransmission_cnt                  	0x4167
+#define	mem_next_btclk                          	0x4169
+#define	mem_seqi                                	0x416d
+#define	mem_rf_rccal                            	0x416e
+#define	mem_handle_num                          	0x416f
+#define	mem_max_slot                            	0x4170
+#define	mem_eir_enable                          	0x4171
+#define	mem_afh_instant                         	0x4172
+#define	mem_afh_error_total                     	0x4176
+#define	mem_afh_cfg                             	0x4178
+#define	mem_afh_new_mod                         	0x4179
+#define	mem_afh_map_lo                          	0x417a
+#define	mem_afh_map_hi                          	0x417f
+#define	mem_afh_used                            	0x4184
+#define	mem_afh_index                           	0x4185
+#define	mem_afh_map_new                         	0x4187
+#define	mem_afh_map                             	0x4192
+#define	mem_afh_timer                           	0x41e2
+#define	mem_afh_classify_channel_map            	0x41e6
+#define	mem_chip_functions                      	0x41f0
+#define	mem_lpm_wake_lock                       	0x41f2
+#define	mem_lpm_interval                        	0x41f4
+#define	mem_lpm_overhead                        	0x41f6
+#define	mem_lpm_hibernate_switch                	0x41f7
+#define	mem_sniff_unint_lost                    	0x41f8
+#define	mem_ptt                                 	0x41f9
+#define	mem_sleep_counter                       	0x41fa
+#define	mem_sleep_counter_all                   	0x41fe
+#define	mem_sleep_clkn                          	0x4202
+#define	mem_sniff_rcv                           	0x4208
+#define	mem_sniff_lost                          	0x420b
+#define	mem_clks_per_lpo                        	0x420e
+#define	mem_lpm_loadcode_switch                 	0x4211
+#define	mem_lpm_memory_choose                   	0x4212
+#define	mem_lpm_mult                            	0x4213
+#define	mem_lpm_mult_timeout                    	0x4214
+#define	mem_lpm_mult_cnt                        	0x4215
+#define	mem_lpm_config                          	0x4216
+#define	mem_lpm_xtalcnt                         	0x4219
+#define	mem_lpm_buckcnt                         	0x421a
+#define	mem_lpm_ldocnt                          	0x421b
+#define	mem_lpm_isogate                         	0x421c
+#define	mem_lpm_isogate_final                   	0x421d
+#define	mem_saved_gpio                          	0x421e
+#define	mem_saved_mark                          	0x4246
+#define	mem_saved_spidctrl                      	0x424e
+#define	mem_patch_ptr                           	0x424f
+#define	mem_patch_len                           	0x4251
+#define	mem_timers                              	0x4253
+#define	mem_link_key_exists                     	0x4293
+#define	mem_link_key_eeprom_head                	0x4294
+#define	mem_link_key                            	0x4297
+#define	mem_hci_cmd                             	0x42a7
+#define	mem_hci_conn_handle                     	0x42a8
+#define	mem_hci_plap                            	0x42a9
+#define	mem_hci_puap                            	0x42ac
+#define	mem_hci_pnap                            	0x42ad
+#define	mem_uartd_rxitems_got_data              	0x42af
+#define	mem_uartd_rxitems_threshold             	0x42b0
+#define	mem_uartd_rx_timeout                    	0x42b1
+#define	mem_sco_attempt_cout                    	0x42b3
+#define	mem_tx_power                            	0x42b4
+#define	mem_sfreq_enable                        	0x42b5
+#define	mem_param_rf_setup                      	0x42b6
+#define	mem_param_pll_setup                     	0x42b8
+#define	mem_avdtp_xmem_start                    	0x42ba
+#define	mem_avdtpsignal_l2capch_ptr             	0x42ba
+#define	mem_avdtpmedia_l2capch_ptr              	0x42bc
+#define	mem_audio_allow                         	0x42be
+#define	mem_audio_state                         	0x42bf
+#define	mem_audio_src_endpoint                  	0x42c0
+#define	mem_audio_src_endpoint_state            	0x42c1
+#define	mem_a2dp_reconnct_delay_timer           	0x42c2
+#define	mem_avdtp_xmem_end                      	0x42c3
+#define	mem_get_media_type                      	0x42c3
+#define	mem_get_codec_type                      	0x42c4
+#define	mem_get_samplefreq_channelmode          	0x42c5
+#define	mem_get_blocklen_subb_allocation        	0x42c6
+#define	mem_get_min_bitpool                     	0x42c7
+#define	mem_get_max_bitpool                     	0x42c8
+#define	mem_get_r_media_type                    	0x42c9
+#define	mem_get_r_codec_type                    	0x42ca
+#define	mem_get_r_samplefreq_channelmode        	0x42cb
+#define	mem_get_r_blocklen_subb_allocation      	0x42cc
+#define	mem_get_r_min_bitpool                   	0x42cd
+#define	mem_get_r_max_bitpool                   	0x42ce
+#define	mem_conf_media_type                     	0x42cf
+#define	mem_conf_codec_type                     	0x42d0
+#define	mem_conf_samplefreq_channelmode         	0x42d1
+#define	mem_conf_blocklen_subb_allocation       	0x42d2
+#define	mem_conf_min_bitpool                    	0x42d3
+#define	mem_conf_max_bitpool                    	0x42d4
+#define	mem_avc_local_transaction_label         	0x42d5
+#define	mem_avdtp_signal                        	0x42d6
+#define	mem_avdtp_media                         	0x42d8
+#define	mem_a2dp_state                          	0x42da
+#define	mem_a2dp_seq_num                        	0x42db
+#define	mem_audio_output_setting                	0x42dd
+#define	mem_param_sco_use_cm0                   	0x42de
+#define	mem_media_in_fast_mode                  	0x42df
+#define	mem_a2dp_buffer_judge_add               	0x42e0
+#define	mem_param_a2dp_buffer_judge_add_limit   	0x42e1
+#define	mem_a2dp_buffer_judge_drop              	0x42e2
+#define	mem_param_a2dp_buffer_judge_drop_limit  	0x42e3
+#define	mem_drop_or_add_process_state           	0x42e4
+#define	mem_drop_or_add_min_receive_packet_size 	0x42e5
+#define	mem_first_buffer_cache                  	0x42e7
+#define	mem_farrow_filter_delta_uk_sign_bit     	0x42e8
+#define	mem_farrow_filter_delta_uk              	0x42e9
+#define	mem_a2dp_adjust_delta_uk_sign_bit       	0x42ed
+#define	mem_a2dp_adjust_delta_uk                	0x42ee
+#define	mem_a2dp_adjust_total_work_sample       	0x42f2
+#define	mem_a2dp_adjust_delta_bytes_sign_bit    	0x42f6
+#define	mem_a2dp_adjust_delta_bytes             	0x42f7
+#define	mem_slave_force_mute_a2dp_voice         	0x42f9
+#define	mem_slave_force_mute_a2dp_voice_cnt     	0x42fa
+#define	mem_tws_wait_sync_ok                    	0x42fb
+#define	mem_last_a2dp_seq_num                   	0x42fc
+#define	mem_param_a2dp_dac_sbc_same_buffer_flag 	0x42fe
+#define	mem_param_a2dp_dac_buffer_addr_mram_flag	0x42ff
+#define	mem_param_a2dp_dac_buffer_start_addr    	0x4300
+#define	mem_param_a2dp_dac_buffer_size          	0x4302
+#define	mem_param_a2dp_sbc_buffer_addr_mram_flag	0x4304
+#define	mem_param_a2dp_sbc_buffer_start_addr    	0x4305
+#define	mem_param_a2dp_sbc_buffer_size          	0x4307
+#define	mem_app_state                           	0x4309
+#define	mem_app_handshake_flag                  	0x430a
+#define	mem_sniff_param_interval                	0x430b
+#define	mem_sniff_param_attempt                 	0x430d
+#define	mem_sniff_param_timeout                 	0x430f
+#define	mem_cb_check_wakelock                   	0x4311
+#define	mem_cb_before_hibernate                 	0x4313
+#define	mem_cb_before_lpm                       	0x4315
+#define	mem_cb_le_process                       	0x4317
+#define	mem_cb_bt_process                       	0x4319
+#define	mem_cb_idle_process                     	0x431b
+#define	mem_cb_bb_event_process                 	0x431d
+#define	mem_cb_event_timer                      	0x431f
+#define	mem_cb_keyscan                          	0x4321
+#define	mem_device_nums                         	0x4323
+#define	mem_uart_txpin                          	0x4324
+#define	mem_uart_rxpin                          	0x4325
+#define	mem_uart_rtspin                         	0x4326
+#define	mem_uart_ctspin                         	0x4327
+#define	mem_uartb_txpin                         	0x4328
+#define	mem_uartb_rxpin                         	0x4329
+#define	mem_uartb_rtspin                        	0x432a
+#define	mem_uartb_ctspin                        	0x432b
+#define	mem_spid_sclkpin                        	0x432c
+#define	mem_spid_sdiopin                        	0x432d
+#define	mem_iic_sda_pin                         	0x432e
+#define	mem_iic_scl_pin                         	0x432f
+#define	mem_ef_base                             	0x4330
+#define	mem_eeprom_block_size                   	0x4333
+#define	mem_mram_qspi_tx_addr                   	0x4335
+#define	mem_poweron_state                       	0x4337
+#define	mem_app_connection_options              	0x4338
+#define	mem_app_disconn_reason                  	0x4339
+#define	mem_app_disconn_reason_flag             	0x433b
+#define	mem_storage_start_addr                  	0x433d
+#define	mem_local_bdaddr                        	0x4340
+#define	mem_qspi_gpio_ncs                       	0x4346
+#define	mem_qspi_gpio_sck                       	0x4347
+#define	mem_qspi_gpio_io0                       	0x4348
+#define	mem_qspi_gpio_io1                       	0x4349
+#define	mem_qspi_gpio_io2                       	0x434a
+#define	mem_qspi_gpio_io3                       	0x434b
+#define	mem_nv_data_ptr                         	0x434c
+#define	mem_nv_data_number                      	0x434e
+#define	mem_saradc_check_clk                    	0x434f
+#define	mem_saradc_flag                         	0x4350
+#define	mem_bat_read_timer                      	0x4351
+#define	mem_rf_debug_enable                     	0x4352
+#define	mem_rf_debug_rf_rx_debug_gpio           	0x4353
+#define	mem_rf_debug_rf_tx_debug_gpio           	0x4354
+#define	mem_rf_debug_rf_sync_detect_debug_gpio  	0x4355
+#define	mem_rf_debug_rf_crc_error_debug_gpio    	0x4356
+#define	mem_param_soft_dma_enable               	0x4357
+#define	mem_param_soft_dma_table_start_addr     	0x4358
+#define	mem_param_m0_respin_sco_buffer_start_addr	0x435b
+#define	mem_param_app_debug_info_timeout        	0x435e
+#define	mem_app_debug_info_timer                	0x435f
+#define	mem_public_code_svn_version_code        	0x4360
+#define	mem_public_code_time_info               	0x4362
+#define	mem_public_code_size                    	0x4366
+#define	mem_fixed_param_area_start              	0x4369
+#define	mem_fixed_param_area_reserve            	0x4369
+#define	mem_param_use_cm0_control_flag          	0x436e
+#define	mem_avctp_xmem_start                    	0x436f
+#define	mem_avctp_tx_label                      	0x436f
+#define	mem_avr_state                           	0x4370
+#define	mem_avr_l2capch_ptr                     	0x4371
+#define	mem_hp_avctp_timer                      	0x4373
+#define	mem_avctp_play_state                    	0x4374
+#define	mem_vlm_notify_enable                   	0x4375
+#define	mem_vlm_notify_label                    	0x4376
+#define	mem_avctp_xmem_end                      	0x4377
+#define	mem_cvsd_in_addr_end                    	0x4377
+#define	mem_cvsd_in_addr_ptr                    	0x4379
+#define	mem_cvsd_out_addr_start                 	0x437b
+#define	mem_cvsd_out_addr_end                   	0x437d
+#define	mem_cvsd_out_addr_ptr                   	0x437f
+#define	mem_pcm_in_addr_end                     	0x4381
+#define	mem_param_pcm_in_buffer_addr_mram_flag  	0x4383
+#define	mem_param_pcm_in_buffer_addr            	0x4384
+#define	mem_param_cvsd_out_buffer_addr_mram_flag	0x4386
+#define	mem_param_cvsd_out_buffer_addr          	0x4387
+#define	mem_param_cvsd_in_buffer_addr_mram_flag 	0x4389
+#define	mem_param_cvsd_in_buffer_addr           	0x438a
+#define	mem_param_pcm_8k_out_buffer_addr_mram_flag	0x438c
+#define	mem_param_pcm_8k_out_buffer_addr        	0x438d
+#define	mem_param_pcm_48k_out_buffer_addr_mram_flag	0x438f
+#define	mem_param_pcm_48k_out_buffer_addr       	0x4390
+#define	mem_cvsd_start_send                     	0x4392
+#define	mem_baud                                	0x4393
+#define	mem_hci_lt_rx_state                     	0x4395
+#define	mem_hid_xmem_start                      	0x4396
+#define	mem_hid_l2capch_ptr                     	0x4396
+#define	mem_hidint_l2capch_ptr                  	0x4398
+#define	mem_hid_xmem_end                        	0x439a
+#define	mem_xmem_sco_start                      	0x439a
+#define	mem_sco_asso_handle                     	0x439a
+#define	mem_sco_handle                          	0x439b
+#define	mem_sco_dsniff                          	0x439d
+#define	mem_sco_tsniff                          	0x439f
+#define	mem_sco_wsniff                          	0x43a1
+#define	mem_sco_tx_packet_type                  	0x43a2
+#define	mem_sco_rx_packet_type                  	0x43a3
+#define	mem_sco_rx_packet_len                   	0x43a4
+#define	mem_sco_tx_packet_len                   	0x43a6
+#define	mem_air_mode                            	0x43a8
+#define	mem_neogotiation_state                  	0x43a9
+#define	mem_acl_amaddr                          	0x43aa
+#define	mem_esco_amaddr                         	0x43ab
+#define	mem_esco_arq                            	0x43ac
+#define	mem_acl_arq                             	0x43ad
+#define	mem_last_type_esco                      	0x43ae
+#define	mem_last_type_acl                       	0x43af
+#define	mem_sco_poll                            	0x43b0
+#define	mem_esco_attempt                        	0x43b1
+#define	mem_esco_abnormal_attempt               	0x43b2
+#define	mem_xmem_sco_end                        	0x43b3
+#define	mem_xmem_hf_state_start                 	0x43b3
+#define	mem_hf_state                            	0x43b3
+#define	mem_hf_call_state                       	0x43b4
+#define	mem_hf_command                          	0x43b5
+#define	mem_agoption                            	0x43b6
+#define	mem_AG_indicator_map                    	0x43b8
+#define	mem_AG_indicator                        	0x43bf
+#define	mem_telephone_dialing_state             	0x43c6
+#define	mem_telephone_dialing_timer             	0x43c7
+#define	mem_xmem_hf_state_end                   	0x43c8
+#define	mem_hf_vlm_speaker                      	0x43c8
+#define	mem_music_vlm_speaker                   	0x43c9
+#define	mem_hf_vlm_mic                          	0x43ca
+#define	mem_at_payload_ptr                      	0x43cb
+#define	mem_at_command_ptr                      	0x43cd
+#define	mem_at_rfcomm_data_ptr                  	0x43cf
+#define	mem_UI_HF_brsf_feature                  	0x43d1
+#define	mem_codec_type                          	0x43d4
+#define	mem_codec_msbc_support                  	0x43d5
+#define	mem_cb_hfp_result_code                  	0x43d6
+#define	mem_hfp_battery_state                   	0x43d8
+#define	mem_esco_test                           	0x43d9
+#define	mem_sco_transaction_enable              	0x43da
+#define	mem_local_sco_in_process_flag           	0x43db
+#define	mem_ipc_mcu_phase                       	0x43dc
+#define	mem_ipc_mcu_state                       	0x43dd
+#define	mem_ipc_enable                          	0x43de
+#define	mem_ipc_le_data_len                     	0x43df
+#define	mem_ipc_le_data_att_handle              	0x43e0
+#define	mem_ipc_tx_data_len                     	0x43e2
+#define	mem_ipc_tx_data_ptr                     	0x43e3
+#define	mem_ipc_loss_packet                     	0x43e5
+#define	mem_temp_for_addr                       	0x43e7
+#define	mem_ipc_test_buff                       	0x43ea
+#define	mem_param_ipc_mem_block_start_addr      	0x43f4
+#define	mem_param_ipc_to_bt_buf_start_addr      	0x43f4
+#define	mem_param_ipc_to_bt_buf_end_addr        	0x43f7
+#define	mem_param_ipc_to_bt_wptr_addr           	0x43fa
+#define	mem_param_ipc_to_bt_rptr_addr           	0x43fd
+#define	mem_param_ipc_to_m0_wptr_addr           	0x4400
+#define	mem_param_ipc_to_m0_rptr_addr           	0x4403
+#define	mem_param_ipc_to_m0_buf_start_addr      	0x4406
+#define	mem_param_ipc_mem_block_end_addr        	0x4409
+#define	mem_param_ipc_to_m0_buf_end_addr        	0x4409
+#define	mem_param_debug_log_func_enable         	0x440c
+#define	mem_debug_log_temp_point                	0x440d
+#define	mem_param_debug_log_mem_block_start_addr	0x4411
+#define	mem_param_debug_log_initial_flag_addr   	0x4411
+#define	mem_param_debug_log_lock_flag_cm0_addr  	0x4414
+#define	mem_param_debug_log_lock_flag_respin_addr	0x4417
+#define	mem_param_debug_log_lock_victim_addr    	0x441a
+#define	mem_param_debug_log_read_index_addr     	0x441d
+#define	mem_param_debug_log_write_index_addr    	0x4420
+#define	mem_param_debug_log_buffer_start_addr   	0x4423
+#define	mem_param_debug_log_mem_block_end_addr  	0x4426
+#define	mem_param_debug_log_buffer_end_addr     	0x4426
+#define	mem_wake_flag                           	0x4429
+#define	mem_m0_lpm_flag                         	0x442a
+#define	mem_l2cap_xmem_start                    	0x442c
+#define	mem_l2cap_tx_multi_offset               	0x442c
+#define	mem_l2cap_pending_info                  	0x442e
+#define	mem_l2cap_pending_id0                   	0x442e
+#define	mem_l2cap_pending_delay_time0           	0x442f
+#define	mem_l2cap_pending_ptr0                  	0x4433
+#define	mem_l2cap_pending_id1                   	0x4435
+#define	mem_l2cap_pending_delay_time1           	0x4436
+#define	mem_l2cap_pending_ptr1                  	0x443a
+#define	mem_l2cap_pending_id2                   	0x443c
+#define	mem_l2cap_pending_delay_time2           	0x443d
+#define	mem_l2cap_pending_ptr2                  	0x4441
+#define	mem_l2cap_pending_count                 	0x4443
+#define	mem_l2cap_active_ch_count               	0x4444
+#define	mem_l2cap_ch_info                       	0x4445
+#define	mem_l2cap_ch_psm0                       	0x4445
+#define	mem_l2cap_ch_state0                     	0x4446
+#define	mem_l2cap_local_cid0                    	0x4447
+#define	mem_l2cap_remote_cid0                   	0x4449
+#define	mem_l2cap_ch_psm1                       	0x444b
+#define	mem_l2cap_ch_state1                     	0x444c
+#define	mem_l2cap_local_cid1                    	0x444d
+#define	mem_l2cap_remote_cid1                   	0x444f
+#define	mem_l2cap_ch_psm2                       	0x4451
+#define	mem_l2cap_ch_state2                     	0x4452
+#define	mem_l2cap_local_cid2                    	0x4453
+#define	mem_l2cap_remote_cid2                   	0x4455
+#define	mem_l2cap_ch_psm3                       	0x4457
+#define	mem_l2cap_ch_state3                     	0x4458
+#define	mem_l2cap_local_cid3                    	0x4459
+#define	mem_l2cap_remote_cid3                   	0x445b
+#define	mem_l2cap_ch_psm4                       	0x445d
+#define	mem_l2cap_ch_state4                     	0x445e
+#define	mem_l2cap_local_cid4                    	0x445f
+#define	mem_l2cap_remote_cid4                   	0x4461
+#define	mem_l2cap_ch_psm5                       	0x4463
+#define	mem_l2cap_ch_state5                     	0x4464
+#define	mem_l2cap_local_cid5                    	0x4465
+#define	mem_l2cap_remote_cid5                   	0x4467
+#define	mem_l2cap_ch_psm6                       	0x4469
+#define	mem_l2cap_ch_state6                     	0x446a
+#define	mem_l2cap_local_cid6                    	0x446b
+#define	mem_l2cap_remote_cid6                   	0x446d
+#define	mem_l2cap_ch_psm7                       	0x446f
+#define	mem_l2cap_ch_state7                     	0x4470
+#define	mem_l2cap_local_cid7                    	0x4471
+#define	mem_l2cap_remote_cid7                   	0x4473
+#define	mem_l2cap_prepare_confreq_count         	0x4475
+#define	mem_l2cap_channel_disconnect_timer      	0x4476
+#define	mem_sdp_state                           	0x4477
+#define	mem_ML2CAP_comm_id                      	0x4478
+#define	mem_used_map                            	0x4479
+#define	mem_tx_fifo0                            	0x447a
+#define	mem_tx_fifo0_map                        	0x447a
+#define	mem_tx_fifo0_ptr                        	0x447b
+#define	mem_tx_fifo1                            	0x447d
+#define	mem_tx_fifo1_map                        	0x447d
+#define	mem_tx_fifo1_ptr                        	0x447e
+#define	mem_tx_fifo2                            	0x4480
+#define	mem_tx_fifo2_map                        	0x4480
+#define	mem_tx_fifo2_ptr                        	0x4481
+#define	mem_tx_fifo3                            	0x4483
+#define	mem_tx_fifo3_map                        	0x4483
+#define	mem_tx_fifo3_ptr                        	0x4484
+#define	mem_tx_fifo_end                         	0x4486
+#define	mem_alloc_block                         	0x4486
+#define	mem_alloc_header                        	0x4486
+#define	mem_alloc_rptr                          	0x4488
+#define	mem_alloc_wptr                          	0x448a
+#define	mem_alloc_end                           	0x448c
+#define	mem_alloc_cur_len                       	0x448e
+#define	mem_alloc_block_start                   	0x448f
+#define	mem_media_release                       	0x449e
+#define	mem_media_block                         	0x449f
+#define	mem_media_header                        	0x449f
+#define	mem_media_rptr                          	0x44a1
+#define	mem_media_wptr                          	0x44a3
+#define	mem_media_end                           	0x44a5
+#define	mem_media_cur_len                       	0x44a7
+#define	mem_media_block_start                   	0x44a8
+#define	mem_lcp_block                           	0x44b7
+#define	mem_lcp_header                          	0x44b7
+#define	mem_lcp_rptr                            	0x44b9
+#define	mem_lcp_wptr                            	0x44bb
+#define	mem_lcp_end                             	0x44bd
+#define	mem_lcp_cur_len                         	0x44bf
+#define	mem_lcp_block_start                     	0x44c0
+#define	mem_l2cap_flow_ctrl_flag                	0x44cf
+#define	mem_l2cap_pending_item                  	0x44d0
+#define	mem_l2cap_rxbuff_len_error              	0x44d1
+#define	mem_l2cap_xmem_end                      	0x44d2
+#define	mem_l2cap_rx_max_lenth                  	0x44d2
+#define	mem_l2cap_rx_malloc_num                 	0x44d4
+#define	mem_le_dsniff                           	0x44d5
+#define	mem_le_conn_interval                    	0x44d7
+#define	mem_le_scan_enable                      	0x44d9
+#define	mem_le_scan_interval                    	0x44da
+#define	mem_le_scan_window                      	0x44dc
+#define	mem_le_adv_enable                       	0x44de
+#define	mem_le_adv_data_len                     	0x44df
+#define	mem_le_adv_data                         	0x44e0
+#define	mem_le_scan_data_len                    	0x44ff
+#define	mem_le_scan_data                        	0x4500
+#define	mem_le_interal_min                      	0x451f
+#define	mem_le_interal_max                      	0x4521
+#define	mem_le_latency                          	0x4523
+#define	mem_le_timeout                          	0x4525
+#define	mem_le_ch_mapped                        	0x4527
+#define	mem_le_new_map                          	0x4528
+#define	mem_le_new_param                        	0x452d
+#define	mem_le_new_transmitwindowsize           	0x452d
+#define	mem_le_new_transmitwindowoffset         	0x452e
+#define	mem_le_new_conninterval                 	0x4530
+#define	mem_le_new_connslavelatency             	0x4532
+#define	mem_le_new_connsupervisiontimeout       	0x4534
+#define	mem_le_txheader                         	0x4536
+#define	mem_le_txlen                            	0x4537
+#define	mem_le_txpayload                        	0x4538
+#define	mem_le_txcid                            	0x453a
+#define	mem_le_l2cap                            	0x453c
+#define	mem_le_l2cap_response                   	0x453d
+#define	mem_le_txbdy                            	0x453e
+#define	mem_le_pcnt_tx                          	0x455d
+#define	mem_le_pcnt_rx                          	0x4562
+#define	mem_le_last_mic                         	0x4567
+#define	mem_le_ivm                              	0x456b
+#define	mem_le_ivs                              	0x456f
+#define	mem_le_ltk                              	0x4573
+#define	mem_ltk_exists                          	0x4583
+#define	mem_le_rconfirm                         	0x4584
+#define	mem_le_srand                            	0x4594
+#define	mem_le_iat                              	0x45a4
+#define	mem_le_rat                              	0x45a5
+#define	mem_le_preq                             	0x45a6
+#define	mem_le_preq_iocap                       	0x45a7
+#define	mem_le_preq_oob                         	0x45a8
+#define	mem_le_preq_auth                        	0x45a9
+#define	mem_le_preq_max_keysize                 	0x45aa
+#define	mem_le_preq_init_key_distribution       	0x45ab
+#define	mem_le_preq_resp_key_distribution       	0x45ac
+#define	mem_le_pres                             	0x45ad
+#define	mem_le_pres_iocap                       	0x45ae
+#define	mem_le_pres_oob                         	0x45af
+#define	mem_le_pres_auth                        	0x45b0
+#define	mem_le_pres_max_keysize                 	0x45b1
+#define	mem_le_pres_init_key_distribution       	0x45b2
+#define	mem_le_pres_resp_key_distribution       	0x45b3
+#define	mem_le_pairing_state                    	0x45b4
+#define	mem_le_enc_state                        	0x45b5
+#define	mem_le_pairing_mode                     	0x45b6
+#define	mem_le_tk                               	0x45b7
+#define	mem_le_ediv                             	0x45bb
+#define	mem_le_rand                             	0x45bd
+#define	mem_le_irk                              	0x45c5
+#define	mem_le_fixed_passkey_flag               	0x45d5
+#define	mem_le_secure_connect_enable            	0x45d6
+#define	mem_le_secure_connect_flag              	0x45d7
+#define	mem_le_sc_calc                          	0x45d8
+#define	mem_le_secure_connect_state             	0x45d9
+#define	mem_le_sc_confirm_gkey_flag             	0x45da
+#define	mem_le_sc_local_key_invalid             	0x45db
+#define	mem_le_pairing_handle                   	0x45dc
+#define	mem_le_search_handle_start              	0x45de
+#define	mem_le_search_handle_end                	0x45e0
+#define	mem_le_att_offset                       	0x45e2
+#define	mem_le_search_att_type_length           	0x45e2
+#define	mem_le_search_att_type                  	0x45e3
+#define	mem_le_notify_handle                    	0x45f3
+#define	mem_le_search_uuid_length               	0x45f5
+#define	mem_le_search_uuid                      	0x45f6
+#define	mem_le_handle_data_len                  	0x4606
+#define	mem_le_handle_data                      	0x4607
+#define	mem_le_adv_param                        	0x4617
+#define	mem_le_adv_interval_min                 	0x4617
+#define	mem_le_adv_interval_max                 	0x4619
+#define	mem_le_adv_type                         	0x461b
+#define	mem_le_adv_own_addr_type                	0x461c
+#define	mem_le_adv_direct_addr_type             	0x461d
+#define	mem_le_adv_direct_addr                  	0x461e
+#define	mem_le_adv_channel_map                  	0x4624
+#define	mem_le_adv_filter_policy                	0x4625
+#define	mem_le_conn_param                       	0x4626
+#define	mem_le_conn_peer_addr_type              	0x4626
+#define	mem_le_conn_peer_addr                   	0x4627
+#define	mem_le_conn_own_addr_type               	0x462d
+#define	mem_le_conn_interval_min                	0x462e
+#define	mem_le_conn_interval_max                	0x4630
+#define	mem_le_conn_latency                     	0x4632
+#define	mem_le_conn_superto                     	0x4634
+#define	mem_le_scan_params                      	0x4636
+#define	mem_le_scan_type                        	0x4636
+#define	mem_le_scan_own_addr_type               	0x4637
+#define	mem_le_scan_filter_policy               	0x4638
+#define	mem_le_lap                              	0x4639
+#define	mem_le_uap                              	0x463c
+#define	mem_le_nap                              	0x463d
+#define	mem_le_xtype_fifo                       	0x463f
+#define	mem_le_transmit_window                  	0x4644
+#define	mem_le_connection_updata_param          	0x4648
+#define	mem_le_l2cap_size                       	0x4658
+#define	mem_le_packet_len_recved                	0x465a
+#define	mem_le_tx_buff_used                     	0x465b
+#define	mem_le_tx_ptr0                          	0x465c
+#define	mem_le_tx_ptr1                          	0x465e
+#define	mem_le_tx_ptr2                          	0x4660
+#define	mem_le_tx_ptr3                          	0x4662
+#define	mem_ui_le_uuid_table                    	0x4664
+#define	mem_le_cur_attlist_start_ptr            	0x4666
+#define	mem_le_cur_handle_start                 	0x4668
+#define	mem_le_cur_handle_end                   	0x466a
+#define	mem_le_cur_uuid_lenth                   	0x466c
+#define	mem_le_cur_uuid                         	0x466d
+#define	mem_notify_handle_pool                  	0x467d
+#define	mem_le_curr_att_len                     	0x4681
+#define	mem_le_signaling_identifier             	0x4682
+#define	mem_le_more_data                        	0x4683
+#define	mem_lmp_version                         	0x4684
+#define	mem_lmp_subversion                      	0x4687
+#define	mem_local_name_length                   	0x4689
+#define	mem_local_name                          	0x468a
+#define	mem_local_name2                         	0x468d
+#define	mem_local_name_end                      	0x46cd
+#define	mem_unsniff2sniff_timer                 	0x46ce
+#define	mem_switch_flag                         	0x46cf
+#define	mem_role_switch_flag                    	0x46d0
+#define	mem_eeprom_ota_base_addr                	0x46d1
+#define	mem_rfc_xmem_start                      	0x46d3
+#define	mem_pn_dlci                             	0x46d3
+#define	mem_pn_max_frame_size                   	0x46d4
+#define	memFCStemp1                             	0x46d6
+#define	memFCStemp2                             	0x46d7
+#define	memFCStemp3                             	0x46d8
+#define	mem_rfcomm_initiator                    	0x46d9
+#define	mem_remote_spp_channel                  	0x46da
+#define	mem_HIUfcs_SPP                          	0x46db
+#define	mem_HIUfcs_SPP_WCredits                 	0x46dc
+#define	mem_remote_credits                      	0x46dd
+#define	mem_credit_given                        	0x46df
+#define	mem_ms_channel                          	0x46e0
+#define	mem_current_packet_length               	0x46e1
+#define	mem_profile_channel                     	0x46e3
+#define	mem_rfc_l2capch_ptr                     	0x46e4
+#define	mem_rfc_server_state                    	0x46e6
+#define	mem_rfc_xmem_end                        	0x46e8
+#define	mem_ui_uuid_table                       	0x46e8
+#define	mem_all_uuid_16bits                     	0x46ea
+#define	mem_all_uuid_128bits                    	0x4700
+#define	mem_sdp_l2capch_ptr                     	0x4722
+#define	mem_sp_local_key_invalid                	0x4724
+#define	mem_le_private_key_256                  	0x4725
+#define	mem_le_pubkey_local_x_256               	0x4745
+#define	mem_le_pubkey_local_y_256               	0x4765
+#define	mem_sp_private_key                      	0x4785
+#define	mem_sp_pubkey_local                     	0x479d
+#define	mem_sp_pubkey_local_x                   	0x479d
+#define	mem_sp_pubkey_local_x_end               	0x47b5
+#define	mem_sp_pubkey_local_y                   	0x47b5
+#define	mem_ssp_enable                          	0x47cd
+#define	mem_sp_iocap_local                      	0x47ce
+#define	mem_ssp_mode_flag                       	0x47d1
+#define	mem_spp_reject_justwork_flag            	0x47d2
+#define	mem_sp_iocap_remote                     	0x47d3
+#define	mem_flag_mode_ssp_pin                   	0x47d6
+#define	mem_authentication_passkey_times        	0x47d7
+#define	mem_passkey_1bit                        	0x47d8
+#define	mem_flag_pairing_state                  	0x47d9
+#define	mem_ipc_lock_bt                         	0x47da
+#define	mem_ipc_lock_c51                        	0x47db
+#define	mem_ipc_fifo_bt2c51                     	0x47dc
+#define	mem_ipc_fifo_c512bt                     	0x47e1
+#define	mem_ui_timer_last_btclk                 	0x47e6
+#define	mem_ui_state_map                        	0x47ea
+#define	mem_discovery_timer_count               	0x47ec
+#define	mem_discovery_timeout                   	0x47ee
+#define	mem_ui_profile_supported                	0x47f0
+#define	mem_pin_length                          	0x47f1
+#define	mem_pin                                 	0x47f2
+#define	mem_keyscan_switch                      	0x4802
+#define	mem_kscan_row_nums                      	0x4803
+#define	mem_kscan_col_nums                      	0x4804
+#define	mem_row_scanned                         	0x4805
+#define	mem_col_scanned                         	0x4806
+#define	mem_row_cnt                             	0x4807
+#define	mem_get_keypress_flag                   	0x4808
+#define	mem_kscan_row_gpio_pin                  	0x4809
+#define	mem_kscan_col_gpio_pin                  	0x4829
+#define	mem_button_gpio1                        	0x4849
+#define	mem_button_last_state1                  	0x484a
+#define	mem_button_timer1                       	0x484b
+#define	mem_button_press_count1                 	0x484c
+#define	mem_button_timeout1                     	0x484d
+#define	mem_button_press_timeout1               	0x484e
+#define	mem_button_down_cb1                     	0x484f
+#define	mem_button_up_cb1                       	0x4851
+#define	mem_button_longpress_cb1                	0x4853
+#define	mem_button_long_release_cb1             	0x4855
+#define	mem_button_gpio2                        	0x4857
+#define	mem_button_last_state2                  	0x4858
+#define	mem_button_timer2                       	0x4859
+#define	mem_button_press_count2                 	0x485a
+#define	mem_button_timeout2                     	0x485b
+#define	mem_button_press_timeout2               	0x485c
+#define	mem_button_down_cb2                     	0x485d
+#define	mem_button_up_cb2                       	0x485f
+#define	mem_button_longpress_cb2                	0x4861
+#define	mem_button_long_release_cb2             	0x4863
+#define	mem_led_gpio1                           	0x4865
+#define	mem_led_state1                          	0x4866
+#define	mem_led_on_timer1                       	0x4867
+#define	mem_led_off_timer1                      	0x4868
+#define	mem_led_repeat1                         	0x4869
+#define	mem_led_timer1                          	0x486a
+#define	mem_led_gpio2                           	0x486b
+#define	mem_led_state2                          	0x486c
+#define	mem_led_on_timer2                       	0x486d
+#define	mem_led_off_timer2                      	0x486e
+#define	mem_led_repeat2                         	0x486f
+#define	mem_led_timer2                          	0x4870
+#define	mem_uppersm_xmem_start                  	0x4871
+#define	mem_major_uppersm                       	0x4871
+#define	mem_sub_uppersm                         	0x4872
+#define	mem_uppersm_list                        	0x4873
+#define	mem_uppersm_disl2capch_index            	0x4878
+#define	mem_uppersm_xmem_end                    	0x4879
+#define	mem_m0_lock_qspi                        	0x4879
+#define	mem_m0_pause_state                      	0x487a
+#define	mem_xip_flash_offset                    	0x487b
+#define	mem_xip_option                          	0x487e
+#define	mem_xip_flash_read_cmd                  	0x4880
+#define	mem_zcode_current_number                	0x4881
+#define	mem_zcode_buff                          	0x4882
+#define	mem_tws_bdaddr                          	0x4884
+#define	mem_tws_lap                             	0x4884
+#define	mem_tws_uap                             	0x4887
+#define	mem_tws_nap                             	0x4888
+#define	mem_hsp_role                            	0x488a
+#define	mem_auto_hsp_role                       	0x488b
+#define	mem_tws_allow_pairing_rssi_limit        	0x488c
+#define	mem_tws_role                            	0x488d
+#define	mem_tws_state                           	0x488e
+#define	mem_tws_last_rcv_phone_packet_crc_fail  	0x488f
+#define	mem_tws_rcv_ack                         	0x4890
+#define	mem_tws_local_rcv_packet                	0x4891
+#define	mem_tws_last_send_ack                   	0x4892
+#define	mem_tws_timeout_timer                   	0x4893
+#define	mem_param_tws_timeout_master            	0x4894
+#define	mem_param_tws_timeout_slave             	0x4895
+#define	mem_tws_observe_wait_connect_timeout_timer	0x4896
+#define	mem_param_tws_observe_wait_connect_timeout_no_connect	0x4897
+#define	mem_param_tws_observe_wait_connect_timeout_error_disconnect	0x4898
+#define	mem_tws_slave_loss_link_listen_master_timeout_timer	0x4899
+#define	mem_param_tws_slave_loss_link_listen_master_timeout	0x489a
+#define	mem_tws_poll_slave_timer                	0x489b
+#define	mem_param_tws_poll_slave                	0x489c
+#define	mem_tws_master_wait_slave_timeout_timer 	0x489d
+#define	mem_param_tws_master_wait_slave_timeout 	0x489e
+#define	mem_tws_m2s_ack_send_timeout_count      	0x489f
+#define	mem_param_tws_m2s_ack_send_timeout      	0x48a0
+#define	mem_tws_poll_null_ack_interval          	0x48a1
+#define	mem_tws_poll_null_ack_interval_count    	0x48a2
+#define	mem_loss_match                          	0x48a3
+#define	mem_count_rcv_adv                       	0x48a5
+#define	mem_tws_adv_match                       	0x48a6
+#define	mem_tws_ack                             	0x48a7
+#define	mem_tws_count_poll                      	0x48a8
+#define	mem_tws_role_switch_in_process          	0x48aa
+#define	mem_tws_slave_wait_master_first_polling_flag	0x48ab
+#define	mem_tws_profile_connected               	0x48ac
+#define	mem_tws_profile_disconnected_after_connected	0x48ad
+#define	mem_tws_adv_count                       	0x48ae
+#define	mem_tws_adv_try_num                     	0x48af
+#define	mem_tws_snd_op                          	0x48b0
+#define	mem_tws_snd_op_nextseq                  	0x48b1
+#define	mem_tws_snd_cur_arq                     	0x48b2
+#define	mem_tws_rcv_op                          	0x48b3
+#define	mem_tws_rcv_op_nextseq                  	0x48b4
+#define	mem_tws_rcv_old_seq                     	0x48b5
+#define	mem_tws_cmd_fifo                        	0x48b6
+#define	mem_tws_no_connect_cmd_trans_limit      	0x48bb
+#define	mem_tws_no_connect_cmd                  	0x48bc
+#define	mem_tws_is_slave_send                   	0x48bd
+#define	mem_tws_is_need_send_header             	0x48be
+#define	mem_tws_remote_version                  	0x48bf
+#define	mem_param_tws_tx_power                  	0x48c1
+#define	mem_le_tws_scan_interval_min            	0x48c2
+#define	mem_le_tws_scan_interval_max            	0x48c4
+#define	mem_le_tws_scan_interval                	0x48c6
+#define	mem_le_tws_scan_window                  	0x48c8
+#define	mem_le_tws_adv_interval                 	0x48ca
+#define	mem_param_le_tws_adv_interval_normal    	0x48cc
+#define	mem_param_le_tws_adv_interval_master_listen	0x48ce
+#define	mem_tws_first_packet_dynamic_buffer     	0x48d0
+#define	mem_tws_first_packet_dynamic_buffer_status	0x48d0
+#define	mem_tws_first_packet_dynamic_buffer_local_bdaddr	0x48d2
+#define	mem_tws_first_packet_dynamic_buffer_paired_bdaddr	0x48d8
+#define	mem_tws_first_packet_dynamic_buffer_reserved	0x48de
+#define	mem_tws_allow_pairing                   	0x48ee
+#define	mem_tws_last_paired_lap                 	0x48ef
+#define	mem_tws_rf_start_anchor                 	0x48f5
+#define	mem_tws_rf_rcv_window_size              	0x48f7
+#define	mem_tws_rf_packet_rx_window_size        	0x48f9
+#define	mem_tws_rf_slave_send_full_packet_sleep_time	0x48fb
+#define	mem_tws_rf_master_check_raw_id_time     	0x48fd
+#define	mem_temp_rf_freq_index                  	0x48ff
+#define	mem_temp_rf_switch_flag                 	0x4900
+#define	mem_tws_buffer_master_switch            	0x4901
+#define	mem_tws_buffer_master_switch_reason     	0x4901
+#define	mem_process_sync_buffer                 	0x4902
+#define	mem_process_a2dp_seq_num                	0x4902
+#define	mem_process_clk                         	0x4904
+#define	mem_process_clkrt                       	0x4908
+#define	mem_process_used_buffer_size            	0x490a
+#define	mem_process_audio_vol                   	0x490c
+#define	mem_process_sync_receive_buffer         	0x490d
+#define	mem_process_receive_a2dp_seq_num        	0x490d
+#define	mem_process_receive_clk                 	0x490f
+#define	mem_process_receive_clkrt               	0x4913
+#define	mem_process_receive_used_buffer_size    	0x4915
+#define	mem_process_receive_audio_vol           	0x4917
+#define	mem_enable_hfp_start_sync               	0x4918
+#define	mem_hfp_start_sync_buffer               	0x4919
+#define	mem_hfp_start_sync_clk                  	0x4919
+#define	mem_param_tws_send_channel_array        	0x491d
+#define	mem_tws_last_send_channel_index         	0x4921
+#define	mem_save_state                          	0x4922
+#define	mem_white_list                          	0x4923
+#define	mem_remote_rx_max_octets                	0x4953
+#define	mem_remote_rx_max_time                  	0x4955
+#define	mem_remote_tx_max_octets                	0x4957
+#define	mem_remote_tx_max_time                  	0x4959
+#define	mem_local_rx_max_octets                 	0x495b
+#define	mem_local_rx_max_time                   	0x495d
+#define	mem_local_tx_max_octets                 	0x495f
+#define	mem_local_tx_max_time                   	0x4961
+#define	mem_remote_reserve                      	0x4963
+#define	mem_sequence_number_rx                  	0x49f3
+#define	mem_sequence_number_tx                  	0x49f4
+#define	mem_msbc_pcm_in_wptr                    	0x49f5
+#define	mem_msbc_pcm_in_rptr                    	0x49f7
+#define	mem_msbc_out_wptr                       	0x49f9
+#define	mem_msbc_out_rptr                       	0x49fb
+#define	mem_msbc_in_wptr                        	0x49fd
+#define	mem_msbc_in_rptr                        	0x49ff
+#define	mem_msbc_pcm_out_saddr                  	0x4a01
+#define	mem_msbc_pcm_out_wptr                   	0x4a03
+#define	mem_msbc_pcm_out_rptr                   	0x4a05
+#define	mem_msbc_packet_len                     	0x4a07
+#define	mem_msbc_pcm_packet_len                 	0x4a09
+#define	mem_msbc_enc_dec_bt_lock                	0x4a0b
+#define	mem_msbc_enc_dec_m0_lock                	0x4a0c
+#define	mem_msbc_adc_start_send                 	0x4a0d
+#define	mem_vp_language                         	0x4a0e
+#define	mem_vp_play_phonenumber                 	0x4a0f
+#define	mem_vp_mram_flag                        	0x4a10
+#define	mem_vp_addr_temp                        	0x4a11
+#define	mem_vp_enable                           	0x4a14
+#define	mem_vp_dac_addr                         	0x4a15
+#define	mem_vp_dac_half                         	0x4a17
+#define	mem_vp_play_block_num                   	0x4a19
+#define	mem_vp_offset                           	0x4a1a
+#define	mem_vp_start_addr                       	0x4a1c
+#define	mem_vp_end_addr                         	0x4a1f
+#define	mem_vp_play_by_cmd                      	0x4a22
+#define	mem_vp_play_addr_offset_temp            	0x4a23
+#define	mem_param_tishi_start_addr              	0x4a24
+#define	mem_nv_le_data                          	0x4a26
+#define	mem_vp_addr                             	0x4a26
+#define	mem_vp_end                              	0x4ab6
+#define	mem_ota_notify_handle                   	0x4ab6
+#define	mem_ota_write_handle                    	0x4ab7
+#define	mem_ota_version                         	0x4ab8
+#define	mem_ota_buck_size                       	0x4aba
+#define	mem_ota_packet_max_len                  	0x4abc
+#define	mem_ota_work_mode                       	0x4abe
+#define	mem_adc_start_addr                      	0x4abf
+#define	mem_adc_buf_size                        	0x4ac1
+#define	mem_dac_start_addr                      	0x4ac3
+#define	mem_dac_buf_size                        	0x4ac5
+#define	mem_dac_clk                             	0x4ac7
+#define	mem_dac_mram_flag                       	0x4ac8
+#define	mem_adc_mram_flag                       	0x4ac9
+#define	mem_mono_flag                           	0x4aca
+#define	mem_l_din_sel                           	0x4acb
+#define	mem_r_din_sel                           	0x4acc
+#define	mem_eq_flag                             	0x4acd
+#define	mem_acl_credits                         	0x4ace
+#define	mem_allow_switch                        	0x4ad0
+#define	mem_hci_acl_queue_start                 	0x4ad1
+#define	mem_hci_wake_clk                        	0x4ad5
+#define	mem_nv_data                             	0x4ace
+#define	mem_nv_data0                            	0x4ace
+#define	mem_nv_data1                            	0x4ae6
+#define	mem_nv_data2                            	0x4afe
+#define	mem_nv_data3                            	0x4b16
+#define	mem_nv_data4                            	0x4b2e
+#define	mem_battery_vol                         	0x4b46
+#define	mem_coef_base_addr                      	0x4b47
+#define	mem_ipc_tx_buf                          	0x4b4a
+#define	mem_le_att_list                         	0x4bae
+#define	mem_tws_fac_adv_name                    	0x4bb0
+#define	mem_param_bt_tx_power                   	0x4bcc
+#define	mem_leadv_action                        	0x4bcd
+#define	mem_hibernate_flag                      	0x4bce
+#define	mem_lpm_write_temp_adc_low              	0x4bcf
+#define	mem_lpm_write_temp_adc_high             	0x4bd3
+#define	mem_lpm_write_temp_charge_control       	0x4bd7
+#define	mem_lpm_write_temp_charge_wakeup_low_active	0x4bdb
+#define	mem_lpm_write_temp_charge_wakeup_high_active	0x4bdd
+#define	mem_efuse_dc_offset                     	0x4bdf
+#define	mem_efuse_dc_offset_l                   	0x4bdf
+#define	mem_efuse_dc_offset_r                   	0x4be1
+#define	mem_efuse_dc_offset_f6                  	0x4be3
+#define	mem_efuse_dc_offset_l_f6                	0x4be3
+#define	mem_efuse_dc_offset_r_f6                	0x4be5
+#define	mem_efuse_adc_offset                    	0x4be7
+#define	mem_0_5_adc_io_data                     	0x4be7
+#define	mem_3v_adc_hvin_data                    	0x4be9
+#define	mem_1v_adc_io_data                      	0x4beb
+#define	mem_5v_adc_hvin_data                    	0x4bed
+#define	mem_xlmp_conn_state                     	0x4bef
+#define	mem_xlmp_clock_offset_valid             	0x4bf0
+#define	mem_rf_power_fix                        	0x4bf1
+#define	mem_ipc_rx_ptr                          	0x4bf2
+#define	mem_module_le_rx_data_len               	0x4bf5
+#define	mem_module_le_rx_data_address           	0x4bf6
+#define	mem_module_le_rx_data_handle            	0x4bf8
+#define	mem_module_data_write_handle            	0x4bfa
+#define	mem_module_data_write_handle2           	0x4bfc
+#define	mem_module_flag                         	0x4bfe
+#define	mem_module_hci_notify_len               	0x4bff
+#define	mem_module_hci_notify_handle            	0x4c00
+#define	mem_module_hci_nofiy_addr               	0x4c02
+#define	mem_last_transmite_clock                	0x4c04
+#define	mem_module_le_att_list                  	0x4c08
+#define	mem_module_le_att_list_end              	0x4c09
+#define	mem_le_disconnect_reason                	0x4c09
+#define	mem_mesh_le_features                    	0x4c0a
+#define	mem_mesh_le_version                     	0x4c12
+#define	mem_mesh_le_version_exchange_times      	0x4c17
+#define	mem_mesh_hci_opcode_ocf                 	0x4c18
+#define	mem_mesh_hci_opcode_ogf                 	0x4c1a
+#define	mem_mesh_hci_cmd_len                    	0x4c1b
+#define	mem_mesh_event_mask                     	0x4c1c
+#define	mem_mesh_read_local_version_info        	0x4c24
+#define	mem_mesh_read_local_version_info_hci_version	0x4c24
+#define	mem_mesh_read_local_version_info_hci_revision	0x4c25
+#define	mem_mesh_read_local_version_info_lmp_version	0x4c27
+#define	mem_mesh_read_local_version_info_manufacturer	0x4c28
+#define	mem_mesh_read_local_version_info_lmp_subversion	0x4c2a
+#define	mem_mesh_read_local_support_command     	0x4c2c
+#define	mem_mesh_le_event_mask                  	0x4c6c
+#define	mem_mesh_le_public_address              	0x4c74
+#define	mem_mesh_le_random_address              	0x4c7a
+#define	mem_mesh_vendor_tx_flag                 	0x4c80
+#define	mem_mesh_vendor_tx_freq                 	0x4c81
+#define	mem_mesh_vendor_tx_data                 	0x4c82
+#define	mem_mesh_vendor_tx_power_calibration    	0x4c83
+#define	mem_mesh_vendor_rx_flag                 	0x4c84
+#define	mem_mesh_vendor_rx_freq                 	0x4c85
+#define	mem_mesh_event_head_type                	0x4c86
+#define	mem_mesh_event_head_event_code          	0x4c87
+#define	mem_mesh_event_para_total_length        	0x4c88
+#define	mem_mesh_event_parameter_rtn            	0x4c89
+#define	mem_mesh_event_parameter_status         	0x4c8a
+#define	mem_mesh_creat_connection_flag          	0x4c8b
+#define	mem_mesh_recevie_acl_packet_number      	0x4c8c
+#define	mem_device_public_address               	0x4c8d
+#define	mem_mesh_command_complete_num_hci_command_packet	0x4c93
+#define	mem_mesh_command_complete_command_opcode	0x4c94
+#define	mem_mesh_hci_opcode                     	0x4c94
+#define	mem_mesh_command_complete_return_parameter_status	0x4c96
+#define	mem_simple_pairing_mode                 	0x4c97
+#define	mem_fec_required                        	0x4c98
+#define	mem_inquiry_num_responses               	0x4c99
+#define	mem_inquiry_num_check                   	0x4c9a
+#define	mem_conn_status                         	0x4c9b
+#define	mem_inquiry_mode                        	0x4c9c
+#define	mem_inquiry_eir_data                    	0x4c9d
+#define	mem_io_cap_flag                         	0x4c9f
+#define	mem_page_scan_repetition_mode           	0x4ca0
+#define	mem_conn_req_status                     	0x4ca1
+#define	mem_alloc_normal_block                  	0x4ca2
+#define	mem_alloc_normal_header                 	0x4ca2
+#define	mem_alloc_normal_rptr                   	0x4ca4
+#define	mem_alloc_normal_wptr                   	0x4ca6
+#define	mem_alloc_normal_end                    	0x4ca8
+#define	mem_alloc_normal_total_size             	0x4caa
+#define	mem_alloc_normal_cur_len                	0x4cab
+#define	mem_alloc_normal_block_start            	0x4cac
+#define	mem_alloc_big_block                     	0x4cca
+#define	mem_alloc_big_header                    	0x4cca
+#define	mem_alloc_big_rptr                      	0x4ccc
+#define	mem_alloc_big_wptr                      	0x4cce
+#define	mem_alloc_big_end                       	0x4cd0
+#define	mem_alloc_big_total_size                	0x4cd2
+#define	mem_alloc_big_cur_len                   	0x4cd3
+#define	mem_alloc_big_block_start               	0x4cd4
+#define	mem_normal_block_ptr_list               	0x4cf2
+#define	mem_big_block_ptr_list                  	0x4d10
+#define	mem_rcv_br_queue_ptr                    	0x4d2e
+#define	mem_rcv_ble_queue_ptr                   	0x4d31
+#define	mem_snd_br_block                        	0x4d34
+#define	mem_snd_br_header                       	0x4d34
+#define	mem_snd_br_rptr                         	0x4d36
+#define	mem_snd_br_wptr                         	0x4d38
+#define	mem_snd_br_end                          	0x4d3a
+#define	mem_snd_br_total_size                   	0x4d3c
+#define	mem_snd_br_cur_len                      	0x4d3d
+#define	mem_snd_br_block_start                  	0x4d3e
+#define	mem_snd_ble_block                       	0x4d5c
+#define	mem_snd_ble_header                      	0x4d5c
+#define	mem_snd_ble_rptr                        	0x4d5e
+#define	mem_snd_ble_wptr                        	0x4d60
+#define	mem_snd_ble_end                         	0x4d62
+#define	mem_snd_ble_total_size                  	0x4d64
+#define	mem_snd_ble_cur_len                     	0x4d65
+#define	mem_snd_ble_block_start                 	0x4d66
+#define	mem_snd_hci_block                       	0x4d84
+#define	mem_snd_hci_header                      	0x4d84
+#define	mem_snd_hci_rptr                        	0x4d86
+#define	mem_snd_hci_wptr                        	0x4d88
+#define	mem_snd_hci_end                         	0x4d8a
+#define	mem_snd_hci_total_size                  	0x4d8c
+#define	mem_snd_hci_cur_len                     	0x4d8e
+#define	mem_snd_hci_block_start                 	0x4d8f
+#define	mem_regd                                	0x4dad
+#define	mem_alloc_buffer_len                    	0x4db1
+#define	mem_temp_alloc_big_malloc_cnt           	0x4db3
+#define	mem_temp_alloc_normal_malloc_cnt        	0x4db5
+#define	mem_temp_send_br_malloc_cnt             	0x4db7
+#define	mem_temp_media_malloc_cnt               	0x4db9
+#define	mem_temp_lcp_malloc_cnt                 	0x4dbb
+#define	mem_temp_sco_rx_malloc_cnt              	0x4dbd
+#define	mem_temp_sco_tx_malloc_cnt              	0x4dbf
+#define	mem_temp_alloc_big_free_cnt             	0x4dc1
+#define	mem_temp_alloc_normal_free_cnt          	0x4dc3
+#define	mem_temp_send_br_free_cnt               	0x4dc5
+#define	mem_temp_media_free_cnt                 	0x4dc7
+#define	mem_temp_lcp_free_cnt                   	0x4dc9
+#define	mem_temp_sco_rx_free_cnt                	0x4dcb
+#define	mem_temp_sco_tx_free_cnt                	0x4dcd
+#define	mem_param_alloc_normal_buffer_start_address	0x4dcf
+#define	mem_param_alloc_normal_buffer_max_length	0x4dd1
+#define	mem_param_alloc_big_buffer_start_address	0x4dd3
+#define	mem_param_alloc_big_buffer_max_length   	0x4dd5
+#define	mem_ipc_data_rx_buf_subtype             	0x4dd7
+#define	mem_ipc_data_rx_buf_payload_ptr         	0x4dd8
+#define	mem_ipc_data_tx_buf_subtype             	0x4ddb
+#define	mem_ipc_data_tx_buf_payload_ptr         	0x4ddc
+#define	mem_le_features                         	0x4ddf
+#define	mem_le_supported_host                   	0x4de7
+#define	mem_simultaneous_le_host                	0x4de8
+#define	mem_default_link_policy_settings        	0x4de9
+#define	mem_link_policy_settings                	0x4deb
+#define	mem_le_white_list_cnt                   	0x4ded
+#define	mem_le_white_list                       	0x4dee
+#define	mem_le_white_list_type_and_bd_addr      	0x4e0a
+#define	mem_le_white_list_filter_policy         	0x4e11
+#define	mem_hci_acl_packet_pb_flag              	0x4e12
+#define	mem_hci_acl_packet_len_recved           	0x4e13
+#define	mem_hci_acl_packet_payload_ptr          	0x4e15
+#define	mem_le_first_packet_count               	0x4e17
+#define	mem_hci_record_disc_conn_handle         	0x4e18
+#define	mem_fsc_rtk_host                        	0x4e19
+#define	mem_remote_features                     	0x4e1a
+#define	mem_remote_ext_features0                	0x4e22
+#define	mem_remote_ext_features1                	0x4e2a
+#define	mem_le_scan_window_temp                 	0x4e32
+#define	mem_zcode_buff_user                     	0x4e34
+#define	mem_queue_init_flag                     	0x4f34
+#define	mem_hci_version_svnid                   	0x4f35
+#define	mem_bd_addr_new                         	0x4f37
+#define	mem_efuse_encryp_data                   	0x4f3d
+#define	mem_encryp_inital_value                 	0x4f5d
+#define	mem_encryp_param                        	0x4f5f
+#define	mem_encryp_count                        	0x4f61
+#define	mem_qspi_lock_flag_cm0                  	0x4f62
+#define	mem_qspi_lock_flag_respin               	0x4f63
+#define	mem_qspi_lock_victim                    	0x4f64
+#define	mem_efuse_64_bytes                      	0x4f65
+#define	mem_check_attempt_limit                 	0x4fa5
+#define	mem_hci_remote_name_req_flag            	0x4fa6
+#define	mem_hci_remote_name                     	0x4fa7
+#define	mem_le_wait_process_cmd                 	0x4fe7
+#define	mem_loopcnt                             	0x4fe8
+#define	mem_le_master_sm                        	0x4fea
+#define	mem_headset_end                         	0x4feb
+#define	mem_usb_mouse_data                      	0x4ace
+#define	mem_usb_kb_data                         	0x4ade
+#define	mem_usb_kb_multikey                     	0x4aee
+#define	mem_usb0_get_report_data                	0x4afe
+#define	mem_mcmd                                	0xff0
+#define	mem_mouse_data                          	0xff1
+#define	L2CAP_ONE_RXBUFF_LENTH_NEW              	0x266
+#define	L2CAP_ONE_RXBUFF_LENTH                  	0x300
+#define	L2CAP_NORMAL_BUFF_CNT                   	//0x01
+#define	L2CAP_NORMAL_BUFF_LENTH                 	//0x0083
+#define	L2CAP_NORMAL_BUFF_START_ADDR            	//0x2000
+#define	L2CAP_BIG_BUFF_CNT                      	//0x09
+#define	L2CAP_BIG_BUFF_LENTH                    	//0x2b0
+#define	L2CAP_BIG_BUFF_LENTH_BLE                	//0x200
+#define	L2CAP_BIG_BUFF_LENTH_CLASSIC            	//0x2b0
+#define	L2CAP_BIG_BUFF_START_ADDR               	//0x2200
+#define	mem_l2cap_rxbuff1                       	0x1400
+#define	mem_l2cap_rxbuff2                       	0x1700
+#define	mem_l2cap_rxbuff3                       	0x1a00
+#define	mem_l2cap_rxbuff4                       	0x1d00
+#define	mem_tx_buff0                            	0x1000
+#define	mem_tx_buff1                            	0x1080
+#define	mem_tx_buff2                            	0x1100
+#define	mem_tx_buff3                            	0x1180
+#define	mem_tx_buff4                            	0x1200
+#define	mem_tx_buff5                            	0x1280
+#define	mem_tx_buff6                            	0x1300
+#define	mem_tx_buff7                            	0x1380
+#define	mem_le_tx_buffer0                       	0x1c00
+#define	mem_le_tx_buffer1                       	0x1c80
+#define	mem_le_tx_buffer2                       	0x1d00
+#define	mem_le_tx_buffer3                       	0x1d80
+#define	mem_le_txheader_temp                    	0x1000
+#define	mem_le_txlen_temp                       	0x1001
+#define	mem_le_txpayload_temp                   	0x1002
+#define	mem_le_txcid_temp                       	0x1004
+#define	mem_le_l2cap_temp                       	0x1006
+#define	mem_le_l2cap_response_temp              	0x1007
+#define	mem_le_txbdy_temp                       	0x1008
+#define	mem_h5rx_buf                            	0x1e00
+#define	mem_h5rx_buf_end                        	0x1eff
+#define	mem_h5tx_buf                            	0x1f00
+#define	mem_h5tx_buf_end                        	0x1fff
+#define	DEBUG_LOG_INITIAL_SUCCESS_FLAG          	0x5f
+#define	DEBUG_LOG_LOCK_VICTIM_CM0               	0x35
+#define	DEBUG_LOG_LOCK_VICTIM_RESPIN            	0x53
+#define	IPC_DATA_SUBTYPE_FREE                   	0x00
+#define	IPC_DATA_SUBTYPE_BLE                    	0x01
+#define	IPC_DATA_SUBTYPE_SPP                    	0x02
+#define	IPC_DATA_SUBTYPE_HCI                    	0x03
+#define	IPC_DATA_SUBTYPE_ACL_BLE                	0x04
+#define	IPC_DATA_SUBTYPE_ACL_CLASSIC            	0x05
+#define	IPC_TYPE_CMD                            	0x01
+#define	IPC_TYPE_EVT                            	0x02
+#define	IPC_TYPE_HID                            	0x03
+#define	IPC_TYPE_SPP                            	0x04
+#define	IPC_TYPE_BLE                            	0x05
+#define	IPC_TYPE_24G                            	0x06
+#define	IPC_TYPE_MESH                           	0x07
+#define	IPC_TYPE_ADV                            	0x08
+#define	IPC_TYPE_SCAN                           	0x09
+#define	IPC_TYPE_BT_TO_CM0_DATA                 	0x0a
+#define	IPC_TYPE_CM0_TO_BT_DATA                 	0x0b
+#define	IPC_TYPE_A2DP                           	0x0a
+#define	IPC_TYPE_HFP                            	0x0b
+#define	IPC_TYPE_TWS                            	0x0c
+#define	IPC_TYPE_HCI                            	0x0d
+#define	QSPI_LOCK_VICTIM_CM0                    	0x35
+#define	QSPI_LOCK_VICTIM_RESPIN                 	0x53
+#define	MSBC_PCM_IN_BUFFER_ADDR                 	0x2000
+#define	MSBC_OUT_BUFFER_ADDR                    	0x2800
+#define	MSBC_IN_BUFFER_ADDR                     	0x3000
+#define	MSBC_PCM_OUT_BUFFER_ADDR                	0x3800
+#define	MSBC_PACKET_LEN                         	0x39
+#define	MSBC_PCM_PACKET_LEN                     	0xF0
+#define	MSBC_PACKET_MAX_LEN                     	0x1c8
+#define	MSBC_PCM_MAX_PACKET_LEN                 	0x780
+#define	MSBC_ENCODE_BUF_ADDRESS                 	0x2c00
+#define	MSBC_DECODE_BUF_ADDRESS                 	0x3400
+#define	MSBC_BUF_LENTH                          	0x400
+#define	MSBC_NEW_DAC_48K_START_ADDR             	0x2000
+#define	MSBC_NEW_DAC_8K_START_ADDR              	//0xB800
+#define	MSBC_NEW_ADC_8K_START_ADDR              	0xb640
+#define	MSBC_NEW_CACHE_START_ADDR               	0xC540
+#define	MSBC_NEW_DECODE_CACHE_START_ADDR        	0xC940
+#define	MSBC_NEW_PCM_MAX_BUFFER_LEN             	0xF00
+#define	MSBC_NEW_DAC_48K_MAX_BUFFER_LEN         	0x2000
+#define	PNP_PROFILE                             	0x00
+#define	AVCTP_PROFILE                           	0x01
+#define	AVRCP_TARGET_PROFILE                    	0x02
+#define	AVRCP_CONTROL_PROFILE                   	0x03
+#define	HFP_PROFILE                             	0x04
+#define	HSP_PROFILE                             	0x05
+#define	HID_PROFILE                             	0x06
+#define	AAP_PROFILE                             	0x07
+#define	SPP_PROFILE                             	0x08
+#define	NUM_PROFILE                             	0x09
+#define	LED_REPEAT_FORERVER                     	0xff
+#define	BUTTON_GPIO_DISABLE                     	0XFF
+#define	BUTTON_LONGPRESS                        	0xff
+#define	BT_CMD_STANDBY                          	0x00
+#define	BT_CMD_START_DISCOVERY                  	0x01
+#define	BT_CMD_STOP_DISCOVERY                   	0x02
+#define	BT_CMD_RECONNECT                        	0x03
+#define	BT_CMD_DISCONNECT                       	0x04
+#define	BT_CMD_ENTER_SNIFF                      	0x05
+#define	BT_CMD_EXIT_SNIFF                       	0x06
+#define	BT_CMD_ENTER_SNIFF_SUBRATING            	0x07
+#define	BT_CMD_EXIT_SNIFF_SUBRATING             	0x08
+#define	BT_CMD_SNIFF_TEST                       	0x09
+#define	BT_CMD_SET_PIN_CODE                     	0x0a
+#define	BT_CMD_START_INQUIRY                    	0x0b
+#define	BT_CMD_STOP_INQUIRY                     	0x0c
+#define	BT_CMD_START_ADV                        	0x0d
+#define	BT_CMD_STOP_ADV                         	0x0e
+#define	BT_CMD_START_DIRECT_ADV                 	0x0f
+#define	BT_CMD_STOP_DIRECT_ADV                  	0x10
+#define	BT_CMD_LE_DISCONNECT                    	0x11
+#define	BT_CMD_LE_UPDATE_CONN                   	0x12
+#define	BT_CMD_LE_MASTER_UPDATE_CONN            	0x13
+#define	BT_CMD_LE_START_CONN                    	0x16
+#define	BT_CMD_LE_START_SCAN                    	0x17
+#define	BT_CMD_LE_STOP_SCAN                     	0x18
+#define	BT_CMD_ENTER_HIBERNATE                  	0x19
+#define	BT_CMD_LE_SMP_SECURITY_REQUEST          	0x1b
+#define	BT_CMD_LE_START_WRITE                   	0x1c
+#define	BT_CMD_ROLE_SWITCH                      	0x1d
+#define	BT_CMD_BB_RECONN_CANCEL                 	0x1e
+#define	BT_CMD_STORE_RECONN_INFO_LE             	0x1f
+#define	BT_CMD_STORE_RECONN_INFO_BT             	0x20
+#define	BT_CMD_MTU_EXCHANGE                     	0x21
+#define	BT_CMD_DHKEY_NOT_ACCEPT                 	0x22
+#define	BT_CMD_EST_ESCO_REQ                     	0x23
+#define	BT_CMD_RMV_ESCO_REQ                     	0x24
+#define	BT_CMD_EST_SCO_REQ                      	0x25
+#define	BT_CMD_RMV_SCO_REQ                      	0x26
+#define	BT_CMD_LOAD_FLASH_PARAMS                	0x2d
+#define	BT_CMD_INCREASE_POWER_REQ               	0x2e
+#define	BT_CMD_READ_RESPONSE_READY              	0x2f
+#define	BT_CMD_LE_DATA_LEGNTH_REQ               	0x30
+#define	BT_CMD_PLAY_PAUSE                       	0x32
+#define	BT_CMD_BACKWARD                         	0x33
+#define	BT_CMD_FORWARD                          	0x34
+#define	BT_CMD_VOL_UP                           	0x35
+#define	BT_CMD_VOL_DOWN                         	0x36
+#define	BT_CMD_ACCEPT_CALL                      	0x37
+#define	BT_CMD_HANG_UP                          	0x38
+#define	BT_CMD_REDIAL                           	0x39
+#define	BT_CMD_RECOGNITION                      	0x3a
+#define	BT_CMD_PLAY_VP                          	0x3b
+#define	BT_CMD_PLAY_TISHI_VP                    	0x3c
+#define	BT_CMD_RECOGNITION_STOP                 	0x3d
+#define	BT_CMD_ThreeWay_ReleaseAll              	0x3e
+#define	BT_CMD_ThreeWay_ReleaseNAcp             	0x3f
+#define	BT_CMD_ThreeWay_HoldNAcp                	0x31
+#define	BT_CMD_ENTER_TWS_PAIR                   	0x40
+#define	BT_CMD_EXIT_TWS_PAIR                    	0x41
+#define	BT_CMD_START_RECON_TWS                  	0x42
+#define	BT_CMD_STOP_RECON_TWS                   	0x43
+#define	BT_CMD_START_WAIT_MASTER                	0x44
+#define	BT_CMD_STOP_WAIT_MASTER                 	0x45
+#define	BT_CMD_START_WAIT_SLAVE                 	0x46
+#define	BT_CMD_STOP_WAIT_SLAVE                  	0x47
+#define	BT_CMD_TWS_NONE                         	0x48
+#define	TWS_SYNC_CMD_START                      	0x4f
+#define	TWS_SYNC_CMD_IND_0                      	0x50
+#define	TWS_SYNC_CMD_IND_1                      	0x51
+#define	TWS_SYNC_CMD_IND_2                      	0x52
+#define	TWS_SYNC_CMD_IND_3                      	0x53
+#define	TWS_SYNC_CMD_FIX_VOICE_PLAY             	0x5d
+#define	TWS_SYNC_CMD_EAR_DETECT_ON              	0x5e
+#define	TWS_SYNC_CMD_EAR_DETECT_OFF             	0x5f
+#define	TWS_SYNC_CMD_POWR_OFF                   	0x60
+#define	TWS_SYNC_CMD_MASTER_SWITCH              	0x61
+#define	TWS_SYNC_CMD_POLLING                    	0x62
+#define	TWS_SYNC_CMD_USER1                      	0x63
+#define	TWS_SYNC_CMD_USER2                      	0x64
+#define	TWS_SYNC_CMD_USER3                      	0x65
+#define	TWS_SYNC_CMD_USER4                      	0x66
+#define	TWS_SYNC_CMD_USER5                      	0x67
+#define	TWS_SYNC_CMD_RESET_AUDIO                	0x68
+#define	TWS_SYNC_CMD_SLAVE_RESET_AUDIO          	0x69
+#define	TWS_SYNC_CMD_AUDIO_PROCESS_INFO         	0x6A
+#define	TWS_SYNC_CMD_HFP_START_SYNC             	0x6B
+#define	TWS_SYNC_CMD_HFP_SLVAE_START_SYNC       	0x6C
+#define	TWS_SYNC_CMD_ALL_PROFILE_DISCONNECTED   	0x6D
+#define	TWS_SYNC_CMD_DROP_ONE_PACKET            	0x6E
+#define	TWS_SYNC_CMD_AUTO_POWR_OFF              	0x6F
+#define	TWS_SYNC_CMD_ENTER_FAST_SYNC            	0x70
+#define	TWS_SYNC_CMD_EXIT_FAST_SYNC             	0x71
+#define	TWS_SYNC_CMD_ADD_ONE_PACKET             	0x72
+#define	TWS_SYNC_CMD_SLAVE_IN_STORAGE           	0x73
+#define	TWS_SYNC_CMD_USER6                      	0x74
+#define	TWS_SYNC_CMD_USER7                      	0x75
+#define	TWS_SYNC_CMD_OAL_CALL                   	0x76
+#define	TWS_SYNC_CMD_OAL_NOCALL                 	0x77
+#define	TWS_SYNC_CMD_OAL_MUSIC_PLAY             	0x78
+#define	TWS_SYNC_CMD_OAL_MUSIC_PAUSE            	0x79
+#define	TWS_SYNC_CMD_OAL_LAST_MUSIC             	0x7a
+#define	TWS_SYNC_CMD_OAL_NEXT_MUSIC             	0x7b
+#define	TWS_SYNC_CMD_OAL_ADD_VOL                	0x7c
+#define	TWS_SYNC_CMD_OAL_SUB_VOL                	0x7d
+#define	TWS_SYNC_CMD_END                        	0x7f
+#define	BT_CMD_LOAD_INFO                        	0x80
+#define	BT_CMD_RECOVER_AUDIO                    	0x81
+#define	BT_CMD_REPORT_BAT                       	0x82
+#define	BT_CMD_ENABLE_SNIFF_MUL                 	0x84
+#define	BT_CMD_DISABLE_SNIFF_MUL                	0x85
+#define	BT_CMD_BT_DISCONNECT                    	0x86
+#define	BT_CMD_RESET_M0_CLK                     	0x87
+#define	BT_CMD_HFP_INDICATORS_UPDATE            	0x88
+#define	BT_CMD_RECONNECT_AVDTP                  	0x89
+#define	TWS_SYNC_CMD_SWITCH_TO_MASTER           	0x8a
+#define	TWS_SYNC_CMD_ACCPET_SWITCH              	0x8b
+#define	BT_CMD_CHARGE_STOP_POWEROFF             	0X8c
+#define	BT_CMD_CHARGE_DISCONNECT                	0x8d
+#define	TWS_SYNC_CMD_WAIT_TWS_SLAVE             	0x8e
+#define	BT_CMD_VP_END_RECOVER_DAC               	0x8f
+#define	BT_CMD_CHARGE_POWER_OFF                 	0x90
+#define	BT_CMD_OTA_RESET                        	0x91
+#define	BT_CMD_OTA_SWITCH                       	0x92
+#define	BT_CMD_CHARGE_INSCENB                   	0x93
+#define	BT_CMD_CHARGE_INSCENB_CLEAR             	0x94
+#define	BT_CMD_SHUTDOWN_QSPI                    	0x95
+#define	BT_CMD_MSR_TEMP                         	0x96
+#define	BT_CMD_UPDATE_WAKEUP                    	0x97
+#define	BT_CMD_BATVALUE                         	0x98
+#define	BT_CMD_EnterTestMode                    	0x99
+#define	BT_CMD_ExitTestMode                     	0x9a
+#define	BT_CMD_TestPlay                         	0x9b
+#define	BT_CMD_TetstPause                       	0x9c
+#define	BT_CMD_TestEnterSCO                     	0x9d
+#define	BT_CMD_TestExitSCO                      	0x9e
+#define	TWS_NO_CONNECT_TRANS_CMD_START          	0xa0
+#define	TWS_NO_CONNECT_TRANS_CMD_POWER_OFF      	0xa1
+#define	TWS_NO_CONNECT_TRANS_CMD_IN_STORE       	0xa2
+#define	TWS_NO_CONNECT_TRANS_CMD_CHANGE_LANGUAGE_EN	0xa3
+#define	TWS_NO_CONNECT_TRANS_CMD_CHANGE_LANGUAGE_CH	0xa4
+#define	TWS_NO_CONNECT_TRANS_CMD_SWITCH_OAL_ON  	0xa5
+#define	TWS_NO_CONNECT_TRANS_CMD_SWITCH_OAL_OFF 	0xa6
+#define	TWS_NO_CONNECT_TRANS_CMD_END            	0xaf
+#define	BT_CMD_SET_POWER_ON_FLAG                	0xb0
+#define	BT_CMD_ENABLE_LE_LATENCY                	0xb1
+#define	BT_CMD_DISABLE_LE_LATENCY               	0xb2
+#define	BT_CMD_FREQ_CHECK                       	0xb3
+#define	BT_CMD_PLAY                             	0xb4
+#define	BT_CMD_PAUSE                            	0xb5
+#define	BT_CMD_ENTER_OTA                        	0xbd
+#define	BT_CMD_EXIT_OTA                         	0xbe
+#define	BT_EVT_NULL                             	0x00
+#define	BT_EVT_BB_CONNECTED                     	0x01
+#define	BT_EVT_BB_DISCONNECTED                  	0x02
+#define	BT_EVT_RECONN_STARTED                   	0x03
+#define	BT_EVT_RECONN_FAILED                    	0x04
+#define	BT_EVT_SETUP_COMPLETE                   	0x05
+#define	BT_EVT_HID_CONNECTED                    	0x06
+#define	BT_EVT_HID_DISCONNECTED                 	0x07
+#define	BT_EVT_SPP_CONNECTED                    	0x08
+#define	BT_EVT_SPP_DISCONNECTED                 	0x09
+#define	BT_EVT_PINCODE_REQ                      	0x0A
+#define	BT_EVT_ENTER_SNIFF                      	0x0B
+#define	BT_EVT_EXIT_SNIFF                       	0x0C
+#define	BT_EVT_ENTER_SNIFF_SUB                  	0x0D
+#define	BT_EVT_EXIT_SNIFF_SUB                   	0x0E
+#define	BT_EVT_DISCOVERY_STOPED                 	0x0F
+#define	BT_EVT_BUTTON_LONG_PRESSED              	0x10
+#define	BT_EVT_START_PAGE                       	0x11
+#define	BT_EVT_HID_HANDSHAKE                    	0x12
+#define	BT_EVT_RECONN_PAGE_TIMEOUT              	0x13
+#define	BT_EVT_LE_CONNECTED                     	0x14
+#define	BT_EVT_LE_DISCONNECTED                  	0x15
+#define	BT_EVT_ML2CAP_CONN_REFUSED              	0x16
+#define	BT_EVT_BUTTON_ENTER_HIBERNATE           	0x17
+#define	BT_EVT_LINKKEY_GENERATE                 	0x18
+#define	BT_EVT_SWITCH_NOT_ACCEPT                	0x19
+#define	BT_EVT_SWITCH_ACCEPT                    	0x20
+#define	BT_EVT_SNIFF_NOT_ACCEPT                 	0x21
+#define	BT_EVT_SNIFF_ACCEPT                     	0x22
+#define	BT_EVT_UNSNIFF_ACCEPT                   	0x23
+#define	BT_EVT_UNSNIFF_NOT_ACCEPT               	0x24
+#define	BT_EVT_SEND_UNSNIFF_ACCEPT              	0x26
+#define	BT_EVT_VIRTUAL_CABLE_UNPLUG             	0x27
+#define	BT_EVT_LE_WRITE_REQUEST                 	0x28
+#define	BT_EVT_LE_ENC_INFO                      	0x29
+#define	BT_EVT_SWITCH_FAIL_MASTER               	0x2a
+#define	BT_EVT_SWITCH_SUCCESS_MASTER            	0x2b
+#define	BT_EVT_BUTTON_DOWN                      	0x2c
+#define	BT_EVT_BUTTON_UP                        	0x2d
+#define	BT_EVT_REMOTE_UNSNIFF                   	0x2e
+#define	BT_EVT_LE_PAIRING_FAIL                  	0x30
+#define	BT_EVT_LE_PAIRING_SUCCESS               	0x31
+#define	BT_EVT_LE_START_ENC                     	0x32
+#define	BT_EVT_LE_PAUSE_ENC                     	0x33
+#define	BT_EVT_LE_TK_GENERATE                   	0x34
+#define	BT_EVT_BT_GKEY_GENERATE                 	0x35
+#define	BT_EVT_BT_GET_PASSKEY                   	0x36
+#define	BT_EVT_BT_PAIRING_FAIL                  	0x37
+#define	BT_EVT_BT_PAIRING_SUCCESS               	0x38
+#define	BT_EVT_BT_START_ENC                     	0x39
+#define	BT_EVT_LE_GKEY_GENERATE                 	0x3b
+#define	BT_EVT_HFP_RING                         	0x3c
+#define	BT_EVT_A2DP_OPEN                        	0x58
+#define	BT_EVT_HFP_START_DIALING                	0x59
+#define	BT_EVT_HFP_INCOMMING                    	0x5a
+#define	BT_EVT_HFP_OUTGOING                     	0x5b
+#define	BT_EVT_HFP_CALLACTIVE                   	0x5c
+#define	BT_EVT_HFP_CALLIMG                      	0x5d
+#define	BT_EVT_HFP_CALLOGG                      	0x5e
+#define	BT_EVT_HFP_CALMULTY                     	0x5f
+#define	BT_EVT_HFP_CONNECTED                    	0x60
+#define	BT_EVT_HFP_DISCONNECTED                 	0x61
+#define	BT_EVT_HFP_NONO                         	0x62
+#define	BT_EVT_HFP_UP_TO_MAX_VLM                	0x63
+#define	BT_EVT_HFP_DOWN_TO_MIN_VLM              	0x64
+#define	BT_EVT_RESET                            	0x65
+#define	BT_EVT_WAKEUP                           	0x66
+#define	BT_EVT_ENC_CONNECTED                    	0x67
+#define	BT_EVT_ENTER_DISCOVERABLE               	0x68
+#define	BT_EVT_EXIT_DISCOVERABLE                	0x69
+#define	BT_EVT_RESTART                          	0x6a
+#define	BT_EVT_DEV_UPDATE_INFO                  	0x70
+#define	BT_EVT_PROFILE_DISCONNECT               	0x71
+#define	BT_EVT_ABNORMAL_DISCONNECT              	0x72
+#define	BT_EVT_RECONNECT_RSP                    	0x73
+#define	BT_EVT_ALL_PROFILE_CONNECT              	0x74
+#define	BT_EVT_RESET_AUTO_TIMER                 	0x75
+#define	BT_EVT_PHONE_NUM                        	0x76
+#define	BT_EVT_MAX_POWER                        	0x77
+#define	BT_EVT_CLOSE_ADAC                       	0x78
+#define	BT_EVT_DISCONNECT_KEY_ERROR             	0x79
+#define	BT_EVT_DISCONNECT_KEY_MISSING           	0x7a
+#define	BT_EVT_A2DP_CONNECTED                   	0x80
+#define	BT_EVT_A2DP_DISCONNECTED                	0x81
+#define	BT_EVT_AVRCP_CONNECTED                  	0x82
+#define	BT_EVT_AVRCP_DISCONNECTED               	0x83
+#define	BT_EVT_PROFILE_DISCONNECTED             	0x84
+#define	BT_EVT_START_DAC                        	0x85
+#define	BT_EVT_STOP_DAC                         	0x86
+#define	BT_EVT_RESTART_HFP                      	0x87
+#define	BT_EVT_ENTER_TEST_MODE                  	0x88
+#define	BT_EVT_EXIT_TEST_MODE                   	0x89
+#define	BT_EVT_TEST_PLAY                        	0x8a
+#define	BT_EVT_TEST_PAUSE                       	0x8b
+#define	BT_EVT_TEST_ENTER_SCO                   	0x8c
+#define	BT_EVT_TEST_EXIT_SCO                    	0x8d
+#define	BT_EVT_TEST_ENTER_OTA                   	0x8e
+#define	BT_EVT_TEST_EXIT_OTA                    	0x8f
+#define	BT_EVT_OTA_SEND_SEITCH_REQURST          	0x90
+#define	BT_EVT_RECONN_PAGE_CANCELED             	0x91
+#define	BT_EVT_MSR_TEMP                         	0x92
+#define	BT_EVT_TWS_HFP_SYNC_START_PLAY          	0x93
+#define	BT_EVT_LE_DATA_LENGTH_CHANGE            	0x97
+#define	BT_EVT_LE_CONN_PARAM_UPDATE_COMPLETE    	0x98
+#define	BT_EVT_LE_RECEIVED_SMP_PAIRING_REQ      	0x99
+#define	BT_EVT_LE_ATT_EXCHANGE_MTU              	0x9a
+#define	BT_EVT_ENCRYPTION_CHANGE                	0x9b
+#define	BT_EVT_ATT_READ_REQUEST_HANDLE          	0x9c
+#define	BT_EVT_INDENTITYADDRESS                 	0x9d
+#define	BT_EVT_BATVALUE                         	0x9e
+#define	BT_EVT_FIRST_PWR_ON                     	0x9f
+#define	BT_EVT_VOL_CHANGE_MAP                   	0xa0
+#define	BT_EVT_100MS_UINT                       	0xE0
+#define	BT_EVT_100MS                            	0xE1
+#define	BT_EVT_200MS                            	0xE2
+#define	BT_EVT_300MS                            	0xE3
+#define	BT_EVT_400MS                            	0xE4
+#define	BT_EVT_500MS                            	0xE5
+#define	TWS_EVT_PAIR_SUCCESS                    	0x01
+#define	TWS_EVT_EXIT_PAIR                       	0x02
+#define	TWS_EVT_ENTER_PAIR                      	0x03
+#define	TWS_EVT_START_RECON                     	0x04
+#define	TWS_EVT_RECON_FAILE                     	0x05
+#define	TWS_EVT_WAIT_MASTER                     	0x06
+#define	TWS_EVT_SLAVE_CONNECTED                 	0x07
+#define	TWS_EVT_WAIT_SLAVE                      	0x08
+#define	TWS_EVT_MASTER_CONNECTED                	0x09
+#define	TWS_EVT_SLAVE_FOUND                     	0x0a
+#define	TWS_EVT_MASTER_FOUND                    	0x0b
+#define	TWS_SYNC_EVT_UPDATE_AUDIO_PROCESS_INFO  	0x0c
+#define	TWS_EVT_SLAVE_CHANGE_MASTER_NO_CON      	0x0d
+#define	TWS_EVT_SLAVE_SWITCH_MASTER_WAIT        	0x0e
+#define	TWS_EVT_TWS_NONE                        	0x0f
+#define	TWS_EVT_REMOTE_POWER_OFF                	0x10
+#define	TWS_EVT_LOCAL_POWER_OFF                 	0x11
+#define	TWS_SYNC_EVT_START                      	0x1f
+#define	TWS_SYNC_EVT_IND_0                      	0x20
+#define	TWS_SYNC_EVT_IND_1                      	0x21
+#define	TWS_SYNC_EVT_IND_2                      	0x22
+#define	TWS_SYNC_EVT_IND_3                      	0x23
+#define	TWS_SYNC_EVT_FIX_VOICE_PLAY             	0x2d
+#define	TWS_SYNC_EVT_EAR_DETECT_ON              	0x2e
+#define	TWS_SYNC_EVT_EAR_DETECT_OFF             	0x2f
+#define	TWS_SYNC_EVT_POWR_OFF                   	0x30
+#define	TWS_SYNC_EVT_MASTER_SWITCH              	0x31
+#define	TWS_SYNC_EVT_POLLING                    	0x32
+#define	TWS_SYNC_EVT_USER1                      	0x33
+#define	TWS_SYNC_EVT_USER2                      	0x34
+#define	TWS_SYNC_EVT_USER3                      	0x35
+#define	TWS_SYNC_EVT_USER4                      	0x36
+#define	TWS_SYNC_EVT_USER5                      	0x37
+#define	TWS_SYNC_EVT_RESET_AUDIO                	0x38
+#define	TWS_SYNC_EVT_SLAVE_RESET_AUDIO          	0x39
+#define	TWS_SYNC_EVT_AUDIO_PROCESS_INFO         	0x3A
+#define	TWS_SYNC_EVT_HFP_START_SYNC             	0x3B
+#define	TWS_SYNC_EVT_ALL_PROFILE_DISCONNECTED   	0x3D
+#define	TWS_SYNC_EVT_DROP_ONE_PACKET            	0x3E
+#define	TWS_SYNC_EVT_AUTO_POWR_OFF              	0x3F
+#define	TWS_SYNC_EVT_ENTER_FAST_SYNC            	0x40
+#define	TWS_SYNC_EVT_EXIT_FAST_SYNC             	0x41
+#define	TWS_SYNC_EVT_ADD_ONE_PACKET             	0x42
+#define	TWS_SYNC_EVT_SLAVE_IN_STORAGE           	0x43
+#define	TWS_SYNC_EVT_USER6                      	0x44
+#define	TWS_SYNC_EVT_USER7                      	0x45
+#define	TWS_SYNC_EVT_OAL_CALL                   	0x46
+#define	TWS_SYNC_EVT_OAL_NOCALL                 	0x47
+#define	TWS_SYNC_EVT_OAL_MUSIC_PLAY             	0x48
+#define	TWS_SYNC_EVT_OAL_MUSIC_PAUSE            	0x49
+#define	TWS_SYNC_EVT_OAL_LAST_MUSIC             	0x4a
+#define	TWS_SYNC_EVT_OAL_NEXT_MUSIC             	0x4b
+#define	TWS_SYNC_EVT_OAL_ADD_VOL                	0x4c
+#define	TWS_SYNC_EVT_OAL_SUB_VOL                	0x4d
+#define	TWS_SYNC_EVT_SLAVE_ACK                  	0x4e
+#define	TWS_SYNC_EVT_END                        	0x4f
+#define	TWS_NO_CONNECT_TRANS_EVT_START          	0x50
+#define	TWS_NO_CONNECT_TRANS_EVT_POWER_OFF      	0x51
+#define	TWS_NO_CONNECT_TRANS_EVT_IN_STORE       	0x52
+#define	TWS_NO_CONNECT_TRANS_EVT_CHANGE_LANGUAGE_EN	0x53
+#define	TWS_NO_CONNECT_TRANS_EVT_CHANGE_LANGUAGE_CH	0x54
+#define	TWS_NO_CONNECT_TRANS_EVT_SWITCH_OAL_ON  	0x55
+#define	TWS_NO_CONNECT_TRANS_EVT_SWITCH_OAL_OFF 	0x56
+#define	TWS_NO_CONNECT_TRANS_EVT_END            	0x5f
+#define	LOCAL_SCO_WORK_DONE                     	0x00
+#define	LOCAL_SCO_WORK_IN_PROCESS               	0x01
+#define	HFP_SPEAKER_MAX_VLM_MEDIA               	0x20
+#define	HFP_SPEAKER_MAX_VLM_SCO                 	0x1E
+#define	HFP_NONO                                	0x00
+#define	HFP_INCOMMING                           	0x01
+#define	HFP_OUTGOING                            	0x02
+#define	HFP_CALLACTIVE                          	0x03
+#define	HFP_CALLIMG                             	0x04
+#define	HFP_CALLOGG                             	0x05
+#define	HFP_CALMULTY                            	0x06
+#define	CODEC_TYPE_CVSD                         	0x01
+#define	CODEC_TYPE_mSBC                         	0x02
+#define	HF_STATE_WAITING_RFCOMM_CONN            	0x00
+#define	HF_STATE_HF_SEND_FEATURE                	0x01
+#define	HF_STATE_WAITING_AG_FEATURE_OK          	0x02
+#define	HF_STATE_HF_SEND_CODECS                 	0x03
+#define	HF_STATE_WAITING_CODECS_OK              	0x04
+#define	HF_STATE_HF_SEND_INDICATORS             	0x05
+#define	HF_STATE_WAITING_AG_INDICATORS_OK       	0x06
+#define	HF_STATE_HF_SEND_CURR_STATUS            	0x07
+#define	HF_STATE_WAITING_AG_STATUS_OK           	0x08
+#define	HF_STATE_HF_SEND_UPDATE_STATUS          	0x09
+#define	HF_STATE_WAITING_AG_UPDATE_STATUS_OK    	0x0a
+#define	HF_STATE_CONNECTED                      	0x0b
+#define	HF_STATE_HF_SEND_RECEIVE_INFO           	0x0c
+#define	HF_STATE_WAITING_AG_INFO                	0x0d
+#define	HF_STATE_HF_SEND_AT_CLIP                	0x0e
+#define	HF_STATE_WAITING_AT_CLIP                	0x0f
+#define	HF_STATE_HF_SEND_AT_CCWA                	0x10
+#define	HF_STATE_WAITING_AT_CCWA                	0x11
+#define	HFP_EVT_ESCO_START                      	0x01
+#define	HFP_EVT_ESCO_STOP                       	0x02
+#define	AUDIO_STATE_IDLE                        	0x00
+#define	AUDIO_STATE_WAIT_SBC                    	0x01
+#define	AUDIO_STATE_WAIT_SOFT_DMA               	0x02
+#define	AUDIO_STATE_WAIT_UPSTACK_PROCESS        	0x03
+#define	TWS_DROP_OR_ADD_PROCESS_STATE_NONE      	0x00
+#define	TWS_DROP_OR_ADD_PROCESS_STATE_INPROCESS 	0x17
+#define	TWS_DROP_OR_ADD_PROCESS_STATE_WAIT_ADD  	0x53
+#define	TWS_DROP_OR_ADD_PROCESS_STATE_WAIT_DROP 	0x54
+#define	FIRST_BUFFER_CACHE_ENABLE               	0x53
+#define	AUDIO_OUTPUT_FULLMODE                   	0x00
+#define	AUDIO_OUTPUT_TWS_SINGLE_EAR_LEFT        	0x01
+#define	AUDIO_OUTPUT_TWS_SINGLE_EAR_RIGHT       	0x02
+#define	AVDTP_PACKET_TYPE_SINGLE                	0x00
+#define	AVDTP_PACKET_TYPE_START                 	0x01
+#define	AVDTP_PACKET_TYPE_CONTINUE              	0x02
+#define	AVDTP_PACKET_TYPE_END                   	0x03
+#define	AVDTP_MESSAGE_TYPE_CMD                  	0x00
+#define	AVDTP_MESSGAE_TYPE_GENERAL_REJECT       	0x01
+#define	AVDTP_MESSGAE_TYPE_RSP_ACCEPT           	0x02
+#define	AVDTP_MESSGAE_TYPE_RSP_REJECT           	0x03
+#define	AVDTP_IDENTIFIER_DISCOVER               	0x01
+#define	AVDTP_IDENTIFIER_GET_CAPABILITIES       	0x02
+#define	AVDTP_IDENTIFIER_SET_CONFIGURATION      	0x03
+#define	AVDTP_IDENTIFIER_GET_CONFIGURATION      	0x04
+#define	AVDTP_IDENTIFIER_RECONFIGURE            	0x05
+#define	AVDTP_IDENTIFIER_OPEN                   	0x06
+#define	AVDTP_IDENTIFIER_START                  	0x07
+#define	AVDTP_IDENTIFIER_CLOSE                  	0x08
+#define	AVDTP_IDENTIFIER_SUSPEND                	0x09
+#define	AVDTP_IDENTIFIER_ABORT                  	0x0a
+#define	AVDTP_IDENTIFIER_SECURITY_CONTROL       	0x0b
+#define	AVDTP_IDENTIFIER_GET_ALL_CAPABILITIES   	0x0c
+#define	AVDTP_IDENTIFIER_DELAYREPORT            	0x0d
+#define	AVDTP_SEP1                              	0x01
+#define	AVDTP_SEP1_CONFIG                       	0x08
+#define	AVDTP_CATEGORY_MEDIA_TRANS              	0x01
+#define	AVDTP_CATEGORY_REPORTING                	0x02
+#define	AVDTP_CATEGORY_RECOVERY                 	0x03
+#define	AVDTP_CATEGORY_CONTECT_PROTECT          	0x04
+#define	AVDTP_CATEGORY_HEADER_COMPRESSION       	0x05
+#define	AVDTP_CATEGORY_MULTIPLEXING             	0x06
+#define	AVDTP_CATEGORY_MEDIA_CODEC              	0x07
+#define	AVDTP_CATEGORY_DELAY_REPORT             	0x08
+#define	AVD_CPTYPE_SCMS_T                       	0x0002
+#define	A2DP_STATE_OPEN                         	0x01
+#define	A2DP_STATE_START                        	0x02
+#define	A2DP_STATE_CLOSE                        	0x03
+#define	A2DP_STATE_SUSPEND                      	0x04
+#define	A2DP_STATE_PALY_PRESS                   	0x05
+#define	A2DP_STATE_PALY_RELEASE                 	0x06
+#define	A2DP_STATE_PAUSE_PRESS                  	0x07
+#define	A2DP_STATE_PAUSE_RELEASE                	0x08
+#define	AVDTP_SAMPLE_FREQ_44K1                  	0x20
+#define	AVDTP_SAMPLE_FREQ_48K                   	0x10
+#define	HSP_ROLE_L                              	0x00
+#define	HSP_ROLE_R                              	0x01
+#define	TWS_STATE_NONE                          	0x00
+#define	TWS_STATE_PAIRING                       	0x01
+#define	TWS_STATE_WAIT_MASTER                   	0x10
+#define	TWS_STATE_SLAVE_LISTEN                  	0x11
+#define	TWS_STATE_SLAVE_CONNECTED               	0x12
+#define	TWS_STATE_SLAVE_SWITCH_LISTEN           	0x13
+#define	TWS_STATE_WAIT_SLAVE                    	0x20
+#define	TWS_STATE_MASTER_LISTEN                 	0x21
+#define	TWS_STATE_MASTER_CONNECTED              	0x22
+#define	TWS_SET_NONE                            	0x00
+#define	TWS_SET_SLAVE                           	0x33
+#define	TWS_SET_MASTER                          	0x55
+#define	ADV_INTERVAL                            	0x38
+#define	TWS_BLE_ADV_FLAG_POWER_ON               	0xFFEE
+#define	TWS_BLE_ADV_FLAG_NO_CONNECTED           	0xFFDD
+#define	TWS_BLE_ADV_FLAG_CONNECTED              	0xFF0D
+#define	TWS_BLE_ADV_FLAG_TRANS                  	0x8FBB
+#define	TWS_BLE_ADV_FLAG_SPEC_SETTING           	0x9FD7
+#define	TWS_SPEC_ADV_FLAG_NAME                  	0x30
+#define	TWS_SPEC_ADV_FLAG_UPDATE_FLASH          	0x35
+#define	TWS_SPEC_ADV_FLAG_TEST_MUSIC            	0x37
+#define	HCI_ROLE_MASTER                         	0x00
+#define	HCI_ROLE_SLAVE                          	0x01
+#define	LE_WHITE_LIST_MAX_SIZE                  	0x04
+#define	AADC_0_DEFAULT_VALUE                    	0x28
+#define	AADC_1_DEFAULT_VALUE                    	0x52
+#define	AADC_2_DEFAULT_VALUE                    	0x02
+#define	AADC_3_DEFAULT_VALUE                    	0xc3
+#define	AADC_4_DEFAULT_VALUE                    	0x18
+#define	AADC_5_DEFAULT_VALUE                    	0x00
+#define	AADC_6_DEFAULT_VALUE                    	0x00
+#define	AADC_7_DEFAULT_VALUE                    	0xf0
+#define	AADC_8_DEFAULT_VALUE                    	0xa0
+#define	AADC_9_DEFAULT_VALUE                    	0xff
+#define	AADC_A_DEFAULT_VALUE                    	0x3c
+#define	rg_clkpll_8_16_48K                      	0x2D
+#define	rg_clkpll_44d1K                         	0x3D
+#define	rg_misc_8_16_48K                        	0x94
+#define	rg_misc_44d1K                           	0xC4
+#define	left_down_en                            	0x00
+#define	left_up_en                              	0x01
+#define	right_down_en                           	0x02
+#define	right_up_en                             	0x03
+#define	ramp_down_finish_clr                    	0x04
+#define	ramp_up_finish_clr                      	0x05
+#define	RG_ADAC_OPARES_SEL1                     	0x00
+#define	RG_ADAC_OPARES_SEL2                     	0x01
+#define	RG_ADAC_VCMIOPA_SEL                     	0x02
+#define	RG_ADAC_VCMIBUF_BYP                     	0x04
+#define	RG_ADAC_INT_CAPSEL                      	0x05
+#define	RG_ADAC_VOLL0                           	0x06
+#define	DA_ADAC_LDO_AVDD_EN                     	0x05
+#define	DA_ADAC_LDO_HPVDD_EN                    	0x07
+#define	DA_EN_ADAC_BIAS                         	0x00
+#define	DA_EN_ADAC_REF                          	0x01
+#define	DA_EN_ADAC_INT_L                        	0x02
+#define	DA_EN_ADAC_INT_R                        	0x03
+#define	DA_EN_ADAC_OPAL                         	0x04
+#define	DA_EN_ADAC_OPAR                         	0x05
+#define	DA_EN_ADAC_PATHL                        	0x06
+#define	DA_EN_ADAC_PATHR                        	0x07
+#define	DA_ADAC_RST_INT_L                       	0x00
+#define	DA_ADAC_RST_INT_R                       	0x01
+#define	DA_EN_ADAC_OPA_LOOP_L                   	0x02
+#define	DA_EN_ADAC_OPA_LOOP_R                   	0x03
+#define	DA_EN_ADAC_DEPOP_SW_L                   	0x04
+#define	DA_EN_ADAC_DEPOP_SW_R                   	0x05
+#define	DA_EN_ADAC_OPA_DUMMY_L                  	0x06
+#define	DA_EN_ADAC_OPA_DUMMY_R                  	0x07
+#define	CHARGE_PMU_CHGPUMP_EN                   	0x00
+#define	CHARGE_PMU_CHGPUMP_HV                   	0x01
+#define	CHARGE_CHGR_INSC_ENB                    	0x02
+#define	CHARGE_CHGR_UART_EN                     	0x03
+#define	CHARGE_CHGR_SHUTDOWN_SW                 	0x14
+#define	CHARGE_CHGR_SHUTDOWN_BIAS               	0x15
+#define	CHARGE_CHGR_SHUTDOWN_CORE               	0x16
+#define	CHARGE_CHGR_FORCE_CC                    	0x17
+#define	CHARGE_CHGR_FORCE_CV                    	0x18
+#define	CHARGE_CHGR_FORCE_CORE_ON               	0x19
+#define	CHARGE_LPM_CHARGER_EVENT_EN             	0x1A
+#define	CHGR_STATE_ICHG                         	0x01
+#define	CHGR_STATE_RCH_EN                       	0x02
+#define	CHGR_DPPM_OV_CC                         	0x04
+#define	CHGR_STATE_VBAT_LV                      	0x08
+#define	CHGR_DPPM_OV_CV                         	0x10
+#define	CHGR_CC_OV_CV                           	0x20
+#define	CHGR_STATE_IND                          	0x40
+#define	CHGR_PGOOD_AON                          	0x80
+#define	CHGR_PGOOD                              	0x100
+#define	CHGR_IN_PRESENT                         	0x200
+#define	rg_mic_diff_en                          	0x16
+#define	rg_mic_op_cm_en                         	0x17
+#define	rg_mic_pga_vcmsettle_en                 	0x18
+#define	rg_aadc_refbuf_en                       	0x19
+#define	da_aadc_en                              	0x1A
+#define	da_aadc_en_biasgen                      	0x1B
+#define	da_aadc_en_constgm                      	0x1C
+#define	da_aadc_en_reg                          	0x1D
+#define	da_aadda_bg_en                          	0x1E
+#define	da_aadda_bg_en_fc                       	0x1F
+#define	da_mic_pga_en                           	0x00
+#define	da_mic_bias_en                          	0x01
+#define	da_mic_lpm_en                           	0x05
+#define	OTA_SOFT_CHANGE_FLAG                    	0xa5
+#define	OTA_NEED_ENABLE_XIP_FLAG                	0xaa
+#define	DIN_SEL_L_LEFT_CHANNEL                  	0x00
+#define	DIN_SEL_L_RIGHT_CHANNEL                 	0x01
+#define	DIN_SEL_L_LEFT_RIGHT_MIX_CHANNEL        	0x02
+#define	DIN_SEL_L_FIX_ZERO                      	0x03
+#define	DIN_SEL_L_CLOSE                         	0xFF
+#define	DIN_SEL_R_LEFT_CHANNEL                  	0x00
+#define	DIN_SEL_R_RIGHT_CHANNEL                 	0x10
+#define	DIN_SEL_R_LEFT_RIGHT_MIX_CHANNEL        	0x20
+#define	DIN_SEL_R_FIX_ZERO                      	0x30
+#define	DIN_SEL_R_CLOSE                         	0xFF
+#define	RAMP_LEFT_DOWN_STEP_VALUE               	0x03
+#define	RAMP_RIGHT_DOWN_STEP_VALUE              	0x03
+#define	RAMP_LEFT_DOWN_DEST_VALUE               	0x0100
+#define	RAMP_RIGHT_DOWN_DEST_VALUE              	0x0100
+#define	RAMP_LEFT_UP_STEP_VALUE                 	0x03
+#define	RAMP_RIGHT_UP_STEP_VALUE                	0x03
+#define	RAMP_LEFT_UP_DEST_VALUE                 	0x09
+#define	RAMP_RIGHT_UP_DEST_VALUE                	0x09
+#define	ADV_STOP                                	0x00
+#define	ADV_DIS_OPEN_BOX                        	0x01
+#define	ADV_DIS_CLOSE_BOX                       	0x02
+#define	ADV_RESERVE_0                           	0x03
+#define	ADV_RESERVE_1                           	0x04
+#define	ADV_RESERVE_2                           	0x05
+#define	ADV_NORMAL_BLE                          	0x06
+#define	ADV_NUM                                 	0x06
+#define	ADV_OTA                                 	0xff
+#define	TX_POWER_0DB                            	0x00
+#define	TX_POWER_3DB                            	0x01
+#define	TX_POWER_5DB                            	0x02
+#define	TX_POWER_f3DB                           	0x03
+#define	TX_POWER_f5DB                           	0x04
+#define	TX_POWER_8DB                            	0x05
+#define	MEDIA_RELASE_STATE_NONE                 	0x00
+#define	MEDIA_RELASE_STATE_WAIT_UPSTACK         	0x01
+#define	MEDIA_RELASE_STATE_READY                	0x02
+#define	BT_RESPIN_HIBERNATE_FLAG                	0x10000
+#define	BT_RESPIN_HIBERNATE_CHG_LOW             	0x10002
+#define	BT_RESPIN_HIBERNATE_CHG_HIGH            	0x10004
+#define	BT_RESPIN_FLAG_VALID_FLAG               	0x3579
+#define	RSSI_ADJUST_PHO_F5DB                    	0x49
+#define	RSSI_ADJUST_PHO                         	0x55
+#define	RSSI_ADJUST_PHO_5DB                     	0x59
+#define	RSSI_ADJUST_PHO_8DB                     	0x60
+#define	OTA_EVENT                               	0XAB
+#define	OTA_COMMAND                             	0XBA
+#define	OTA_WORK_MODE_NORMAL                    	0x0
+#define	OTA_WORK_MODE_OTA                       	0x1
+#define	OTA_PORTOCOL_VERSION_REQUEST            	0x10
+#define	OTA_BUCK_SIZE_REQUEST                   	0x11
+#define	OTA_WORK_MODE_REQUEST                   	0x12
+#define	OTA_SWITCH_WORK_MODE_REQUEST            	0x13
+#define	OTA_FLASH_CHECKSUM_REQUEST              	0x14
+#define	OTA_START_REQUEST                       	0x15
+#define	OTA_DATA_WRITE_CMD                      	0x16
+#define	OTA_DATA_WRITE_REQUEST                  	0x17
+#define	OTA_END_REQUEST                         	0x18
+#define	OTA_UPDATE_FLASH_NORMAL                 	0x0
+#define	OTA_UPDATE_FLASH_OTA                    	0x1
+#define	OTA_UPDATE_FLASH_PCM                    	0x2
+#define	OTA_RESULT_SUCCESS                      	0x0
+#define	OTA_RESULT_WORKMODE_NOT_SUPPORT         	0x1
+#define	OTA_RESULT_WORKMODE_ERROR               	0x2
+#define	OTA_RESULT_FLASHMODE_NOT_SUPPORT        	0x3
+#define	OTA_RESULT_INDEX_ERROR                  	0x4
+#define	OTA_RESULT_LENGTH_ERROR                 	0x5
+#define	OTA_RESULT_BUCK_SIZE_ERROR              	0x6
+#define	OTA_RESULT_WRITE_FLASH_ERROR            	0x7
+#define	OTA_RESULT_ERROR                        	0xFF
+#define	OTA_CODE_START_ADDR                     	0x1000
+#define	NORMAL_CODE_START_ADDR                  	0x6000
+#define	OTA_DATA_ADDR                           	0x2000
+#define	OTA_FLASH_START_ADDR                    	0x1000
+#define	OTA_FLASH_ALL_LENGTH                    	0x5000
+#define	OTA_FLASH_NORMAL_LENGTH                 	0x29000
+#define	VP_FLASH_START_ADDR                     	0x30000
+#define	VP_FLASH_ALL_LENGTH                     	0X4F000
+#define	MSBC_H2_SYNCWORD                        	0x801
+#define	MSBC_SEQUENCE_NUMBER_0                  	0x00
+#define	MSBC_SEQUENCE_NUMBER_1                  	0x30
+#define	MSBC_SEQUENCE_NUMBER_2                  	0xC0
+#define	MSBC_SEQUENCE_NUMBER_3                  	0xF0
+#endif
Index: ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.h	(working copy)
@@ -0,0 +1,85 @@
+#ifndef  _DRV_BT_H_
+#define _DRV_BT_H_
+
+#include <stdio.h>
+#include "ipc.h"
+#include "yc11xx.h"
+#include "yc_debug.h"
+#include "yc11xx_timer.h"
+#include "yc_timer.h"
+
+#define DEVICE_INFO_BASE 	0x07f000 // mem_ef_base
+
+#define REVERSE_3BYTE_DEFINE(a) ((a>>16)+(a&0xff00)+((a&0xff)<<16))  
+//#define REVERSE_2BYTE_DEFINE(a,b)
+
+#define M0_SCO_BUF_START_ADDR    (reg_map(HREADADDR3(mem_param_m0_respin_sco_buffer_start_addr)))
+
+
+#define CODE_START_FLASHADDR1 0x1003
+#define CODE_START_FLASHADDR2 0X18003
+#define CODE_MAX_LENGTH 0x17000
+
+typedef struct
+{
+	uint8_t topState;
+		
+	SYS_TIMER_TYPE autoPowerTimer;
+}BR_STATE;
+
+typedef enum
+{
+	BR_POWER_OFF=0,
+	BR_WAIT_POWER_OFF,
+	BR_CHARGER_IN,
+	BR_WAIT_POWER_ON,
+	BR_POWER_ON,
+}BR_STATE_TOP_TYPE;
+
+
+extern BR_STATE gBRState;
+
+
+
+#define HCI_QUEUE_MAX (5)
+#define HCI_DATA_BUFFER_SIZE (800)
+
+typedef struct{
+        uint16_t len;
+	uint8_t data[HCI_DATA_BUFFER_SIZE];
+}__attribute__((packed)) BT_HCI_DATA;
+typedef struct{
+	uint8_t rptr;
+	uint8_t wptr;
+	uint8_t cnt;
+	BT_HCI_DATA queue[HCI_QUEUE_MAX];
+}__attribute__((packed)) BT_HCI_DATA_FIFO;
+
+void Bt_EvtCallBack(uint8_t len,uint8_t *dataPtr);
+void Bt_HciFifoInit(void);
+BT_HCI_DATA *Bt_HciGetSendBufferPtr(void);
+void Bt_HciFifoIn(void);
+
+void Bt_HciFifoOut(void);
+uint8_t Bt_HciCheckBufferFull(void);
+void Bt_SndToBtData(uint8_t subType, uint32_t payloadPtr);
+void Bt_HciCallback(uint8_t *dataPtr);
+void Bt_DataBufferCallBack(uint8_t len,uint8_t *dataPtr);
+void Bt_PowerResetWork(void);
+void Bt_Init(void);
+void Bt_Reset(void);
+void Bt_PowerOn(bool isPowerOnFromKeyPress);
+void Bt_PowerOnBtWork(void);
+uint8_t Bt_CheckPowerOn(void);
+void Bt_StartWork(void);
+void Bt_ActionBeforeHibernate(void);
+void Bt_ActionBeforeLpm(void);
+void Bt_SndCmdPwroff(void);
+void Bt_SndHciToRespin(uint8_t *data, uint16_t len);
+void Bt_ACLCallbackBle(uint8_t *dataPtr,uint16_t conn_handle);
+void Bt_ACLCallbackClassic(uint8_t *dataPtr,uint16_t conn_handle);
+
+// extern function defined
+extern void SCO_NVIC_Config(void);
+extern void SCO_NVIC_DeConfig(void);
+#endif //_DRV_IPC_H_
Index: ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/device/bt/yc11xx_dev_bt.c	(working copy)
@@ -0,0 +1,526 @@
+#include <stdio.h>
+#include "yc11xx_dev_bt.h"
+
+#include "common/log.h"
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_vs.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+
+#define H4_NONE 0x00
+#define H4_CMD  0x01
+#define H4_ACL  0x02
+#define H4_SCO  0x03
+#define H4_EVT  0x04
+#define H4_ISO  0x05
+
+BR_STATE gBRState;
+BT_HCI_DATA_FIFO gHciDataFifo;
+
+void Bt_EvtCallBack(uint8_t len,uint8_t *dataPtr)
+{
+    if (*dataPtr >BT_EVT_100MS_UINT)
+    {
+        Bt_100ms_timer((*dataPtr)&(0x0F));
+        return;
+    }
+    DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_EvtCallBack: 0x%04X", LOG_POINT_9001, *dataPtr);
+
+    switch(*dataPtr)
+    {
+        case BT_EVT_WAKEUP:
+            SYS_TimerStartTickTimer(CLOCK_48M_multiple);
+            break;
+        case BT_EVT_RESET:
+            Bt_Reset();
+            Bt_PowerOn(true);
+            Bt_PowerOnBtWork();
+            break;
+        case BT_EVT_RESTART:
+            Bt_PowerResetWork();
+            break;
+
+        default:
+            break;
+    }
+
+    return;
+}
+
+
+
+
+void Bt_HciFifoInit(void)
+{
+    memset((void *)&gHciDataFifo, 0, sizeof(BT_HCI_DATA_FIFO));
+}
+BT_HCI_DATA *Bt_HciGetSendBufferPtr(void)
+{
+    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
+    return &(pFifo->queue[pFifo->wptr]);
+}
+
+void Bt_HciFifoIn(void)
+{
+    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
+    if(pFifo->cnt >= HCI_QUEUE_MAX)
+    {
+        return;
+    }
+
+    pFifo->cnt++;
+    pFifo->wptr += 1;
+    //if(prxDataFifo->wptr == M0_SCO_RX_BUFFER_SIZE)
+    if(pFifo->wptr == HCI_QUEUE_MAX)
+    {
+    	pFifo->wptr = 0;
+    }
+}
+
+void Bt_HciFifoOut(void)
+{
+    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
+    if(pFifo->cnt == 0)
+    {
+        return;
+    }
+
+    pFifo->cnt--;
+    pFifo->rptr += 1;
+    //if(prxDataFifo->wptr == M0_SCO_RX_BUFFER_SIZE)
+    if(pFifo->rptr == HCI_QUEUE_MAX)
+    {
+    	pFifo->rptr = 0;
+    }
+}
+uint8_t Bt_HciCheckBufferFull(void)
+{
+    BT_HCI_DATA_FIFO* pFifo = &gHciDataFifo;
+    if(pFifo->cnt >= HCI_QUEUE_MAX)
+    {
+        return 1;
+    }
+    return 0;
+}
+void Bt_HciParseEvt(uint8_t evtCode, uint16_t len, uint8_t *dataPtr)
+{
+    uint16_t opcode = 0;
+    uint8_t numPacket = 0;
+    DEBUG_LOG_2(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E000, evtCode, len);
+    if(evtCode == BT_HCI_EVT_CMD_COMPLETE)
+    {
+        numPacket = (*(dataPtr + 0) << 0);
+        opcode = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
+        DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E001, opcode);
+        DEBUG_LOG_2(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E002, (*(dataPtr + 3)), (*(dataPtr + 4)));
+    }
+    
+}
+void Bt_HciParseCmd(uint16_t opcode, uint8_t len, uint8_t *dataPtr)
+{
+    DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E100, opcode);
+    
+}
+
+void Bt_SndToBtData(uint8_t subType, uint32_t payloadPtr)
+{
+    DEBUG_LOG_STRING("Bt_SndToBtData subType=%d, payloadPtr=0x%x\r\n",subType, payloadPtr);
+    uint8_t data[4];
+    data[0] = subType;
+    data[1] = payloadPtr;
+    data[2] = payloadPtr >> 8;
+    data[3] = payloadPtr >> 16;
+    IPC_TxCommon(IPC_TYPE_CM0_TO_BT_DATA, data, sizeof(data));
+}
+
+static struct net_buf *get_rx(uint8_t type, uint8_t evtCode)
+{
+	BT_DBG("get_rx type 0x%02x, evt 0x%02x", type, evtCode);
+
+	switch (type) {
+	case H4_EVT:
+		return bt_buf_get_evt(evtCode, FALSE, 0);
+	case H4_ACL:
+		return bt_buf_get_rx(BT_BUF_ACL_IN, 0);
+	case H4_ISO:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			return bt_buf_get_rx(BT_BUF_ISO_IN, 0);
+		}
+	}
+
+	return NULL;
+}
+
+void Bt_HciCallback(uint8_t *dataPtr)
+{
+    uint8_t type = *(dataPtr);
+    uint16_t len = 0;
+    uint16_t handle = 0;
+    uint16_t totalLength = 0;
+    uint8_t evtCode = 0;
+    //Avoid host use respin buffer
+    uint8_t evtBuffer[500];
+    switch(type)
+    {
+        case H4_EVT:
+            evtCode = *(dataPtr + 1);
+            len = *(dataPtr + 2);
+            totalLength = len+3;// 04 + evtCode(1) + length(1)
+            
+            //Avoid host use respin buffer
+            xmemcpy(evtBuffer,dataPtr,totalLength);
+            dataPtr = evtBuffer;
+
+            Bt_HciParseEvt(evtCode, len, dataPtr + 3);
+
+            
+            break;
+        case H4_ACL:
+            handle = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
+            len = (*(dataPtr + 3) << 0) |(*(dataPtr + 4) << 8);
+            totalLength = len+5;// 02 + handle(2) + length(2)
+            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E010, handle);
+            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E011, len);
+            break;
+        default:
+            _ASSERT_FAULT();
+            break;
+    }
+
+    
+    DEBUG_LOG_PRINT_HCI_H4(1, dataPtr, totalLength);
+
+    //h4_send_data(dataPtr, totalLength);
+    struct net_buf * buf = get_rx(type, evtCode);
+    if(buf == NULL)
+    {
+        BT_DBG("buffer loss 0x%02x, evt 0x%02x", type, evtCode);
+        return;
+    }
+	net_buf_add_mem(buf, dataPtr+1, totalLength-1);
+    bt_recv(buf);
+}
+
+
+void Bt_DataBufferCallBack(uint8_t len,uint8_t *dataPtr)
+{
+    uint32_t payloadPtr;
+    uint8_t subType;
+	uint16_t conn_handle;
+    //uint16_t lenPayload;
+    subType = dataPtr[0];
+    payloadPtr = reg_map(dataPtr[1] +(dataPtr[2]<<8)+(dataPtr[3]<<16));
+    DEBUG_LOG_STRING("Bt_DataBufferCallBack len: %d, subType=0x%x, payloadPtr=0x%x\r\n", len, subType, payloadPtr);
+    //	MyPrintf("handle=%x\r\n",handle);
+    switch(subType) 
+    {
+        case IPC_DATA_SUBTYPE_HCI:
+            // TODO: Need change to m0 ram.
+            Bt_HciCallback((uint8_t *)payloadPtr);
+            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
+            break;
+        case IPC_DATA_SUBTYPE_FREE:
+            /************************release tx buffer *****************************/
+            Bt_HciFifoOut();
+            break;
+        case IPC_DATA_SUBTYPE_ACL_BLE:
+            conn_handle = dataPtr[4]+(dataPtr[5]<<8);
+            Bt_ACLCallbackBle((uint8_t *)payloadPtr,conn_handle);
+            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
+            break;
+        case IPC_DATA_SUBTYPE_ACL_CLASSIC:
+            conn_handle = dataPtr[4]+(dataPtr[5]<<8);
+            Bt_ACLCallbackClassic((uint8_t *)payloadPtr,conn_handle);
+            Bt_SndToBtData(IPC_DATA_SUBTYPE_FREE, payloadPtr);
+            break;
+    }
+}
+
+
+
+void Bt_PowerResetWork(void)
+{
+	Bt_Reset();
+	//WDT_Kick();
+	SYS_delay_ms(500);
+	//WDT_Kick();
+	SYS_delay_ms(500);
+	//WDT_Kick();
+	SYS_delay_ms(100);
+	Bt_PowerOn(false);
+	//Bat_StateSwitchPooling();
+	if(gBRState.topState != BR_CHARGER_IN)
+	{
+		Bt_PowerOnBtWork();
+	}
+}
+
+void Bt_Init(void)
+{
+	DEBUG_LOG(LOG_LEVEL_CORE, "UI" ,"Bt_Reset: 0x%04X", LOG_POINT_A200, gBRState.topState);
+	gBRState.topState = BR_WAIT_POWER_ON;
+
+}
+
+//extern void KeyPad_Event_Handle(KEY_INDEX index,KEYPAD_EVT_TYPE key_evt);
+void Bt_Reset(void)
+{
+	DEBUG_LOG(LOG_LEVEL_CORE, "UI" ,"Bt_Reset: 0x%04X", LOG_POINT_A201, gBRState.topState);
+	Bt_Init();	
+	//SYS_TimerInit(CLOCK_48M_multiple);
+	//keypad_init(KeyPad_Event_Handle);
+	//QSPI_ReadFlashData(OTA_LED_FLASH_ADDR,1,&gLedCfg.red_gpio);
+	//Read_Ledgpionum();
+	//VP_Init();
+	//Led_Init();
+	//Bat_InitDev();
+}
+
+void Bt_PowerOn(bool isPowerOnFromKeyPress)
+{
+	gBRState.topState = BR_POWER_ON;
+
+}
+
+
+void Bt_PowerOnBtWork(void)
+{
+}
+
+
+uint8_t Bt_CheckPowerOn(void)
+{
+	return (gBRState.topState >= BR_POWER_ON);
+}
+
+void Bt_StartWork(void)
+{
+
+	DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_startWork: 0x%04X", LOG_POINT_9011, gBRState.topState);
+
+	
+}
+
+
+void Bt_ActionBeforeHibernate()
+{
+	//gpio leakage of electricity
+	//Bat_ClcGpio();
+	uint8_t i;
+	
+	for(i=GPIO_0;i<GPIO_MAX_NUM;i++)
+	{
+		GPIO_ClearWakeup((GPIO_NUM)i);
+		if(
+		 i == (HREAD(mem_qspi_gpio_ncs)&GPIO_NUM_MASK)
+			|| i == (HREAD(mem_qspi_gpio_sck)&GPIO_NUM_MASK)
+			|| i == (HREAD(mem_qspi_gpio_io0)&GPIO_NUM_MASK)
+			|| i == (HREAD(mem_qspi_gpio_io1)&GPIO_NUM_MASK)
+			|| i == (HREAD(mem_qspi_gpio_io2)&GPIO_NUM_MASK)
+			|| i == (HREAD(mem_qspi_gpio_io3)&GPIO_NUM_MASK)	
+			|| i ==GPIO_31)
+			continue ;
+		else
+		{
+			
+			GPIO_SetGpioMultFunction((GPIO_NUM)i,GPCFG_PULLDOWN);
+		}
+	}	
+}
+void Bt_ActionBeforeLpm()
+{
+	//gpio leakage of electricity
+	//Bat_ClcGpio();
+	Bt_ActionBeforeHibernate();
+}
+
+void Bt_SndCmdPwroff(void)
+{
+	//disable interrupt,will disable keyscan
+	OS_ENTER_CRITICAL();
+	gBRState.topState = BR_POWER_OFF;
+	IPC_TxControlCmd(BT_CMD_ENTER_HIBERNATE);
+	
+	while(1){
+	 	uint8_t temp = HREAD(IPC_MCU_STATE);
+		if (temp == IPC_MCU_STATE_HIBERNATE)
+		{	
+			Bt_ActionBeforeHibernate();
+			HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
+			while(1);
+		}
+		else if (temp == IPC_MCU_STATE_LMP){
+			HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_RUNNING);
+		}
+		hw_delay();
+	}
+}
+
+void Bt_HciParseRcvData(uint8_t *dataPtr, uint16_t len)
+{
+    uint8_t type = *(dataPtr);
+    uint16_t handle = 0;
+    uint16_t opcode = 0;
+    switch(type)
+    {
+        case H4_CMD:
+            opcode = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
+            len = *(dataPtr + 3);
+            Bt_HciParseCmd(opcode, len, dataPtr + 4);
+            break;
+        case H4_ACL:
+            handle = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
+            len = (*(dataPtr + 3) << 0) |(*(dataPtr + 4) << 8);
+            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E110, handle);
+            DEBUG_LOG(LOG_LEVEL_CORE, "HCI" ,"", LOG_POINT_E111, len);
+            break;
+        default:
+            _ASSERT_FAULT();
+            break;
+    }
+    
+}
+void Bt_SndHciToRespin(uint8_t *data, uint16_t len)
+{
+    BT_HCI_DATA* pHciData = Bt_HciGetSendBufferPtr();
+
+    memcpy((pHciData->data), data, len);
+    pHciData->len = len;
+    Bt_HciParseRcvData(data, len);
+    Bt_SndToBtData(IPC_DATA_SUBTYPE_HCI, (uint32_t)pHciData->data);
+    //DEBUG_LOG_STRING("Bt_SndHciToRespin len=%d, payload=0x%x\r\n",len, (uint32_t)pHciData->data);
+    if(!len)
+    {
+        //while(1);
+        return;
+    }
+    Bt_HciFifoIn();
+}
+
+void Bt_ACLCallbackBle(uint8_t *dataPtr,uint16_t conn_handle)
+{
+	uint8_t packet[300];
+	uint16_t handle = 0;
+	uint16_t len=0;
+	uint16_t totalLength = 0;
+	handle = (((*(dataPtr))& 0x03)<<12)|conn_handle; 
+	len = (*(dataPtr+1));
+	packet[0] = H4_ACL;
+	packet[1] = handle& 0xff;
+	packet[2] = (handle>>8)& 0xff;
+	packet[3] = len & 0xff;
+	packet[4] = (len>>8)& 0xff;
+	totalLength =len+5;
+	xmemcpy(packet+5,dataPtr+2,len);
+	Bt_HciCallback(packet);
+}
+void Bt_ACLCallbackClassic(uint8_t *dataPtr,uint16_t conn_handle)
+{
+	uint8_t packet[800];
+	uint16_t handle = 0;
+	uint16_t len=0;
+	uint16_t totalLength = 0;
+	handle = (((*(dataPtr))& 0x03)<<12)|conn_handle; 
+	len = (*(dataPtr + 1) << 0) |(*(dataPtr + 2) << 8);
+	packet[0] = H4_ACL;
+	packet[1] = handle& 0xff;
+	packet[2] = (handle>>8)& 0xff;
+	packet[3] = len & 0xff;
+	packet[4] = (len>>8)& 0xff;
+	totalLength =len+5;
+	xmemcpy(packet+5,dataPtr+3,len);
+	Bt_HciCallback(packet);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static int ipc_bt_hci_send(struct net_buf *buf)
+{
+	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
+
+    uint8_t type = H4_NONE;
+    switch (bt_buf_get_type(buf)) {
+        case BT_BUF_ACL_OUT:
+            type = H4_ACL;
+            break;
+        case BT_BUF_CMD:
+            type = H4_CMD;
+            break;
+        case BT_BUF_ISO_OUT:
+            if (IS_ENABLED(CONFIG_BT_ISO)) {
+                type = H4_ISO;
+                break;
+            }
+            __fallthrough;
+        default:
+            BT_ERR("Unknown buffer type");
+            //goto done;
+					break;
+        }
+    net_buf_push_u8(buf, type);
+	BT_DBG("---> ipc_bt_hci_send Payload (len %u): %s", buf->len,
+	       bt_hex_real(buf->data, buf->len));
+
+    DEBUG_LOG_PRINT_HCI_H4(0, buf->data, buf->len);
+	Bt_SndHciToRespin(buf->data, buf->len);
+
+    // unref the buffer.
+	net_buf_unref(buf);
+
+	return 0;
+}
+
+static int ipc_bt_hci_open(void)
+{
+	int ret;
+
+	BT_DBG("ipc_bt_hci_open\r\n");
+
+	// do nothing
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= "IPC",
+	.bus		= BT_HCI_DRIVER_BUS_VIRTUAL,
+	.open		= ipc_bt_hci_open,
+	.send		= ipc_bt_hci_send,
+};
+
+void ipc_bt_hci_init(void)
+{
+	bt_hci_driver_register(&drv);
+
+	return 0;
+}
+
+
+
+
+
+
+
+
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/CMakeLists.txt	(working copy)
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_sources_ifdef(CONFIG_BT_H4       h4.c)
+zephyr_sources_ifdef(CONFIG_BT_H5       h5.c)
+zephyr_sources_ifdef(CONFIG_BT_SPI      spi.c)
+zephyr_sources_ifdef(CONFIG_BT_RPMSG	rpmsg.c)
+zephyr_sources_ifdef(CONFIG_BT_RPMSG_NRF53	rpmsg_nrf53.c)
+zephyr_sources_ifdef(CONFIG_BT_STM32_IPM	ipm_stm32wb.c)
+zephyr_sources_ifdef(CONFIG_BT_USERCHAN userchan.c)
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/Kconfig	(working copy)
@@ -0,0 +1,149 @@
+# Bluetooth drivers configuration options
+
+# Copyright (c) 2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+comment "Bluetooth HCI Driver Options"
+
+config BT_UART
+	bool
+
+choice BT_HCI_BUS_TYPE
+	prompt "Bluetooth HCI driver"
+
+config BT_H4
+	bool "H:4 UART"
+	select UART_INTERRUPT_DRIVEN
+	select BT_UART
+	select BT_RECV_IS_RX_THREAD
+	depends on SERIAL
+	help
+	  Bluetooth H:4 UART driver. Requires hardware flow control
+	  lines to be available.
+
+config BT_H5
+	bool "H:5 UART [EXPERIMENTAL]"
+	select UART_INTERRUPT_DRIVEN
+	select BT_UART
+	depends on SERIAL
+	help
+	  Bluetooth three-wire (H:5) UART driver. Implementation of HCI
+	  Three-Wire UART Transport Layer.
+
+config BT_RPMSG
+	bool "HCI using RPMsg"
+	help
+	  Bluetooth HCI driver for communication with another CPU
+	  using RPMsg framework.
+
+config BT_SPI
+	bool "SPI HCI"
+	depends on SPI
+	help
+	  Supports Bluetooth ICs using SPI as the communication protocol.
+	  HCI packets are sent and received as single Byte transfers,
+	  prepended after a known header.  Headers may vary per device, so
+	  additional platform specific knowledge may need to be added as
+	  devices are.
+
+config BT_STM32_IPM
+	bool "IPM HCI"
+	select USE_STM32_HAL_CORTEX
+	select HAS_STM32LIB
+	help
+	  TODO
+
+config BT_USERCHAN
+	bool "HCI User Channel based driver"
+	depends on BOARD_NATIVE_POSIX
+	help
+	  This driver provides access to the local Linux host's Bluetooth
+	  adapter using a User Channel HCI socket to the Linux kernel. It
+	  is only intended to be used with the native POSIX build of Zephyr.
+	  The Bluetooth adapter must be powered off in order for Zephyr to
+	  be able to use it.
+
+config BT_NO_DRIVER
+	bool "No default HCI driver"
+	help
+	  This is intended for unit tests where no internal driver
+	  should be selected.
+
+endchoice
+
+# Workaround for not being able to have commas in macro arguments
+DT_CHOSEN_Z_BT_UART := zephyr,bt-uart
+
+config BT_UART_ON_DEV_NAME
+	string "Device Name of UART Device for Bluetooth"
+	default "$(dt_chosen_label,$(DT_CHOSEN_Z_BT_UART))" if HAS_DTS
+	default "UART_0"
+	depends on BT_UART
+	help
+	  This option specifies the name of UART device to be used
+	  for Bluetooth.
+
+if BT_SPI
+
+config BT_SPI_INIT_PRIORITY
+	int "BT SPI init priority"
+	default 75
+
+config BT_BLUENRG_ACI
+	bool "Enable ACI message with with BlueNRG-based devices"
+	help
+	  Enable support for devices compatible with the BlueNRG Bluetooth
+	  Stack. Current driver supports: ST BLUENRG-MS.
+
+config BT_SPI_BLUENRG
+	bool "Enable compatibility with BlueNRG-based devices"
+	help
+	  Enable support for devices compatible with the BlueNRG Bluetooth
+	  Stack. Current driver supports: ST BLUENRG-MS.
+
+endif # BT_SPI
+
+config BT_STM32_IPM_RX_STACK_SIZE
+	int "STM32 IPM stack size for RX thread"
+	depends on BT_STM32_IPM
+	default 512
+
+config BT_RPMSG_NRF53
+	bool "nRF53 configuration of RPMsg"
+	default y if SOC_NRF5340_CPUAPP
+	depends on BT_RPMSG
+	select IPM
+	select IPM_NRFX
+	select IPM_MSG_CH_1_ENABLE
+	select IPM_MSG_CH_0_ENABLE
+	select IPM_MSG_CH_0_TX
+	select IPM_MSG_CH_1_RX
+	select OPENAMP
+	help
+	  Enable RPMsg configuration for nRF53. Two channels of the IPM driver
+	  are used in the HCI driver: channel 0 for TX and channel 1 for RX.
+
+if BT_RPMSG_NRF53
+
+config BT_RPMSG_NRF53_RX_STACK_SIZE
+	int "RPMsg stack size for RX thread"
+	default 1024
+
+config BT_RPMSG_NRF53_RX_PRIO
+	int "RPMsg RX thread priority"
+	default 8
+
+endif # BT_RPMSG_NRF53
+
+config BT_DRIVER_QUIRK_NO_AUTO_DLE
+	bool "Host auto-initiated Data Length Update quirk"
+	depends on BT_AUTO_DATA_LEN_UPDATE
+	default y if BT_RPMSG_NRF53
+	help
+	  Enable the quirk wherein BT Host stack will auto-initiate Data Length
+	  Update procedure for new connections for controllers that do not
+	  auto-initiate the procedure if the default data length parameters are
+	  not equal to the initial parameters.
+
+	  This has to be enabled when the BLE controller connected is Zephyr
+	  open source controller.
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h4.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h4.c	(working copy)
@@ -0,0 +1,520 @@
+/* h4.c - H:4 UART based Bluetooth driver */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//#include <errno.h>
+#include <stddef.h>
+
+
+#include <sys/util.h>
+#include <sys/byteorder.h>
+#include <string.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME "bt_driver"
+#include "common/log.h"
+
+#include "../util.h"
+
+#define H4_NONE 0x00
+#define H4_CMD  0x01
+#define H4_ACL  0x02
+#define H4_SCO  0x03
+#define H4_EVT  0x04
+#define H4_ISO  0x05
+
+//static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE);
+//static struct k_thread rx_thread_data;
+
+static struct {
+	struct net_buf *buf;
+	struct k_fifo   fifo;
+
+	uint16_t    remaining;
+	uint16_t    discard;
+
+	bool     have_hdr;
+	bool     discardable;
+
+	uint8_t     hdr_len;
+
+	uint8_t     type;
+	union {
+		struct bt_hci_evt_hdr evt;
+		struct bt_hci_acl_hdr acl;
+		struct bt_hci_iso_hdr iso;
+		uint8_t hdr[4];
+	};
+} rx = {
+	.fifo = Z_FIFO_INITIALIZER(rx.fifo),
+};
+
+static struct {
+	uint8_t type;
+	struct net_buf *buf;
+	struct k_fifo   fifo;
+} tx = {
+	.fifo = Z_FIFO_INITIALIZER(tx.fifo),
+};
+
+static const struct device *h4_dev;
+
+static inline void h4_get_type(void)
+{
+	/* Get packet type */
+	//if (uart_fifo_read(h4_dev, &rx.type, 1) != 1) 
+	if(FALSE)
+	{
+		BT_WARN("Unable to read H:4 packet type");
+		rx.type = H4_NONE;
+		return;
+	}
+
+	switch (rx.type) {
+	case H4_EVT:
+		rx.remaining = sizeof(rx.evt);
+		rx.hdr_len = rx.remaining;
+		break;
+	case H4_ACL:
+		rx.remaining = sizeof(rx.acl);
+		rx.hdr_len = rx.remaining;
+		break;
+	case H4_ISO:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			rx.remaining = sizeof(rx.iso);
+			rx.hdr_len = rx.remaining;
+			break;
+		}
+		__fallthrough;
+	default:
+		BT_ERR("Unknown H:4 type 0x%02x", rx.type);
+		rx.type = H4_NONE;
+	}
+}
+
+static inline void get_acl_hdr(void)
+{
+	struct bt_hci_acl_hdr *hdr = &rx.acl;
+	int to_read = sizeof(*hdr) - rx.remaining;
+
+	//rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read,
+	//			       rx.remaining);
+	if (!rx.remaining) {
+		rx.remaining = sys_le16_to_cpu(hdr->len);
+		BT_DBG("Got ACL header. Payload %u bytes", rx.remaining);
+		rx.have_hdr = true;
+	}
+}
+
+static inline void get_iso_hdr(void)
+{
+	struct bt_hci_iso_hdr *hdr = &rx.iso;
+	unsigned int to_read = sizeof(*hdr) - rx.remaining;
+
+	//rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read,
+	//			       rx.remaining);
+	if (!rx.remaining) {
+		rx.remaining = sys_le16_to_cpu(hdr->len);
+		BT_DBG("Got ISO header. Payload %u bytes", rx.remaining);
+		rx.have_hdr = true;
+	}
+}
+
+static inline void get_evt_hdr(void)
+{
+	struct bt_hci_evt_hdr *hdr = &rx.evt;
+	int to_read = rx.hdr_len - rx.remaining;
+
+	//rx.remaining -= uart_fifo_read(h4_dev, (uint8_t *)hdr + to_read,
+	//			       rx.remaining);
+	if (rx.hdr_len == sizeof(*hdr) && rx.remaining < sizeof(*hdr)) {
+		switch (rx.evt.evt) {
+		case BT_HCI_EVT_LE_META_EVENT:
+			rx.remaining++;
+			rx.hdr_len++;
+			break;
+#if defined(CONFIG_BT_BREDR)
+		case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI:
+		case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT:
+			rx.discardable = true;
+			break;
+#endif
+		}
+	}
+
+	if (!rx.remaining) {
+		if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT &&
+		    rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
+			BT_DBG("Marking adv report as discardable");
+			rx.discardable = true;
+		}
+
+		rx.remaining = hdr->len - (rx.hdr_len - sizeof(*hdr));
+		BT_DBG("Got event header. Payload %u bytes", hdr->len);
+		rx.have_hdr = true;
+	}
+}
+
+
+static inline void copy_hdr(struct net_buf *buf)
+{
+	net_buf_add_mem(buf, rx.hdr, rx.hdr_len);
+}
+
+static void reset_rx(void)
+{
+	rx.type = H4_NONE;
+	rx.remaining = 0U;
+	rx.have_hdr = false;
+	rx.hdr_len = 0U;
+	rx.discardable = false;
+}
+
+static struct net_buf *get_rx(k_timeout_t timeout)
+{
+	BT_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt);
+
+	switch (rx.type) {
+	case H4_EVT:
+		return bt_buf_get_evt(rx.evt.evt, rx.discardable, timeout);
+	case H4_ACL:
+		return bt_buf_get_rx(BT_BUF_ACL_IN, timeout);
+	case H4_ISO:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			return bt_buf_get_rx(BT_BUF_ISO_IN, timeout);
+		}
+	}
+
+	return NULL;
+}
+
+static void rx_thread(void *p1, void *p2, void *p3)
+{
+	struct net_buf *buf;
+
+	ARG_UNUSED(p1);
+	ARG_UNUSED(p2);
+	ARG_UNUSED(p3);
+
+	BT_DBG("started");
+
+	while (1) {
+		BT_DBG("rx.buf %p", rx.buf);
+
+		/* We can only do the allocation if we know the initial
+		 * header, since Command Complete/Status events must use the
+		 * original command buffer (if available).
+		 */
+		if (rx.have_hdr && !rx.buf) {
+			rx.buf = get_rx(K_FOREVER);
+			BT_DBG("Got rx.buf %p", rx.buf);
+			if (rx.remaining > net_buf_tailroom(rx.buf)) {
+				BT_ERR("Not enough space in buffer");
+				rx.discard = rx.remaining;
+				reset_rx();
+			} else {
+				copy_hdr(rx.buf);
+			}
+		}
+
+		/* Let the ISR continue receiving new packets */
+		//uart_irq_rx_enable(h4_dev);
+
+		buf = net_buf_get(&rx.fifo, K_FOREVER);
+		do {
+			//uart_irq_rx_enable(h4_dev);
+
+			BT_DBG("Calling bt_recv(%p)", buf);
+			bt_recv(buf);
+
+			/* Give other threads a chance to run if the ISR
+			 * is receiving data so fast that rx.fifo never
+			 * or very rarely goes empty.
+			 */
+			//k_yield();
+
+			//uart_irq_rx_disable(h4_dev);
+			buf = net_buf_get(&rx.fifo, K_NO_WAIT);
+		} while (buf);
+	}
+}
+
+static size_t h4_discard(const struct device *uart, size_t len)
+{
+	uint8_t buf[33];
+	return 0;
+	//return uart_fifo_read(uart, buf, MIN(len, sizeof(buf)));
+}
+
+static inline void read_payload(void)
+{
+	struct net_buf *buf;
+	uint8_t evt_flags;
+	int read;
+
+	if (!rx.buf) {
+		rx.buf = get_rx(K_NO_WAIT);
+		if (!rx.buf) {
+			if (rx.discardable) {
+				BT_WARN("Discarding event 0x%02x", rx.evt.evt);
+				rx.discard = rx.remaining;
+				reset_rx();
+				return;
+			}
+
+			BT_WARN("Failed to allocate, deferring to rx_thread");
+			//uart_irq_rx_disable(h4_dev);
+			return;
+		}
+
+		BT_DBG("Allocated rx.buf %p", rx.buf);
+
+		if (rx.remaining > net_buf_tailroom(rx.buf)) {
+			BT_ERR("Not enough space in buffer");
+			rx.discard = rx.remaining;
+			reset_rx();
+			return;
+		}
+
+		copy_hdr(rx.buf);
+	}
+
+	//read = uart_fifo_read(h4_dev, net_buf_tail(rx.buf), rx.remaining);
+	net_buf_add(rx.buf, read);
+	rx.remaining -= read;
+
+	BT_DBG("got %d bytes, remaining %u", read, rx.remaining);
+	BT_DBG("Payload (len %u): %s", rx.buf->len,
+	       bt_hex(rx.buf->data, rx.buf->len));
+
+	if (rx.remaining) {
+		return;
+	}
+
+	buf = rx.buf;
+	rx.buf = NULL;
+
+	if (rx.type == H4_EVT) {
+		evt_flags = bt_hci_evt_get_flags(rx.evt.evt);
+		bt_buf_set_type(buf, BT_BUF_EVT);
+	} else {
+		evt_flags = BT_HCI_EVT_FLAG_RECV;
+		bt_buf_set_type(buf, BT_BUF_ACL_IN);
+	}
+
+	reset_rx();
+#if defined(CONFIG_BT_RECV_IS_RX_THREAD)
+	if (evt_flags & BT_HCI_EVT_FLAG_RECV_PRIO) {
+		BT_DBG("Calling bt_recv_prio(%p)", buf);
+		bt_recv_prio(buf);
+	}
+#endif
+
+	if (evt_flags & BT_HCI_EVT_FLAG_RECV) {
+		BT_DBG("Putting buf %p to rx fifo", buf);
+		net_buf_put(&rx.fifo, buf);
+	}
+}
+
+static inline void read_header(void)
+{
+	switch (rx.type) {
+	case H4_NONE:
+		h4_get_type();
+		return;
+	case H4_EVT:
+		get_evt_hdr();
+		break;
+	case H4_ACL:
+		get_acl_hdr();
+		break;
+	case H4_ISO:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			get_iso_hdr();
+			break;
+		}
+		__fallthrough;
+	default:
+		CODE_UNREACHABLE;
+		return;
+	}
+
+	if (rx.have_hdr && rx.buf) {
+		if (rx.remaining > net_buf_tailroom(rx.buf)) {
+			BT_ERR("Not enough space in buffer");
+			rx.discard = rx.remaining;
+			reset_rx();
+		} else {
+			copy_hdr(rx.buf);
+		}
+	}
+}
+
+static inline void process_tx(void)
+{
+	int bytes;
+
+	if (!tx.buf) {
+		tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT);
+		if (!tx.buf) {
+			BT_ERR("TX interrupt but no pending buffer!");
+			//uart_irq_tx_disable(h4_dev);
+			return;
+		}
+	}
+
+	if (!tx.type) {
+		switch (bt_buf_get_type(tx.buf)) {
+		case BT_BUF_ACL_OUT:
+			tx.type = H4_ACL;
+			break;
+		case BT_BUF_CMD:
+			tx.type = H4_CMD;
+			break;
+		case BT_BUF_ISO_OUT:
+			if (IS_ENABLED(CONFIG_BT_ISO)) {
+				tx.type = H4_ISO;
+				break;
+			}
+			__fallthrough;
+		default:
+			BT_ERR("Unknown buffer type");
+			goto done;
+		}
+
+		//bytes = uart_fifo_fill(h4_dev, &tx.type, 1);
+		if (bytes != 1) {
+			BT_WARN("Unable to send H:4 type");
+			tx.type = H4_NONE;
+			return;
+		}
+	}
+
+	//bytes = uart_fifo_fill(h4_dev, tx.buf->data, tx.buf->len);
+	net_buf_pull(tx.buf, bytes);
+
+	if (tx.buf->len) {
+		return;
+	}
+
+done:
+	tx.type = H4_NONE;
+	net_buf_unref(tx.buf);
+	tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT);
+	if (!tx.buf) {
+		//uart_irq_tx_disable(h4_dev);
+	}
+}
+
+static inline void process_rx(void)
+{
+	BT_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u",
+	       rx.remaining, rx.discard, rx.have_hdr, rx.buf,
+	       rx.buf ? rx.buf->len : 0);
+
+	if (rx.discard) {
+		rx.discard -= h4_discard(h4_dev, rx.discard);
+		return;
+	}
+
+	if (rx.have_hdr) {
+		read_payload();
+	} else {
+		read_header();
+	}
+}
+
+static void bt_uart_isr(const struct device *unused, void *user_data)
+{
+	ARG_UNUSED(unused);
+	ARG_UNUSED(user_data);
+#if 0
+	while (uart_irq_update(h4_dev) && uart_irq_is_pending(h4_dev)) {
+		if (uart_irq_tx_ready(h4_dev)) {
+			process_tx();
+		}
+
+		if (uart_irq_rx_ready(h4_dev)) {
+			process_rx();
+		}
+	}
+#endif
+}
+
+static int h4_send(struct net_buf *buf)
+{
+	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
+
+	net_buf_put(&tx.fifo, buf);
+	//uart_irq_tx_enable(h4_dev);
+
+	return 0;
+}
+
+/** Setup the HCI transport, which usually means to reset the Bluetooth IC
+  *
+  * @param dev The device structure for the bus connecting to the IC
+  *
+  * @return 0 on success, negative error value on failure
+  */
+int __weak bt_hci_transport_setup(const struct device *dev)
+{
+	h4_discard(h4_dev, 32);
+	return 0;
+}
+
+static int h4_open(void)
+{
+	int ret;
+
+	BT_DBG("");
+
+	//uart_irq_rx_disable(h4_dev);
+	//uart_irq_tx_disable(h4_dev);
+
+	ret = bt_hci_transport_setup(h4_dev);
+	if (ret < 0) {
+		return -EIO;
+	}
+
+	//uart_irq_callback_set(h4_dev, bt_uart_isr);
+/*
+	k_thread_create(&rx_thread_data, rx_thread_stack,
+			K_KERNEL_STACK_SIZEOF(rx_thread_stack),
+			rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_RX_PRIO),
+			0, K_NO_WAIT);
+*/
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= "H:4",
+	.bus		= BT_HCI_DRIVER_BUS_UART,
+	.open		= h4_open,
+	.send		= h4_send,
+};
+
+static int bt_uart_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	//h4_dev = device_get_binding(CONFIG_BT_UART_ON_DEV_NAME);
+	if (!h4_dev) {
+		return -EINVAL;
+	}
+
+	bt_hci_driver_register(&drv);
+
+	return 0;
+}
+
+//SYS_INIT(bt_uart_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h5.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h5.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/h5.c	(working copy)
@@ -0,0 +1,782 @@
+/* uart_h5.c - UART based Bluetooth driver */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <stddef.h>
+
+#include <zephyr.h>
+
+#include <init.h>
+#include <drivers/uart.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+#include <debug/stack.h>
+#include <sys/printk.h>
+#include <string.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_driver
+#include "common/log.h"
+
+#include "../util.h"
+
+static K_KERNEL_STACK_DEFINE(tx_stack, 256);
+static K_KERNEL_STACK_DEFINE(rx_stack, 256);
+
+static struct k_thread tx_thread_data;
+static struct k_thread rx_thread_data;
+
+static struct k_delayed_work ack_work;
+static struct k_delayed_work retx_work;
+
+#define HCI_3WIRE_ACK_PKT	0x00
+#define HCI_COMMAND_PKT		0x01
+#define HCI_ACLDATA_PKT		0x02
+#define HCI_SCODATA_PKT		0x03
+#define HCI_EVENT_PKT		0x04
+#define HCI_ISODATA_PKT		0x05
+#define HCI_3WIRE_LINK_PKT	0x0f
+#define HCI_VENDOR_PKT		0xff
+
+static bool reliable_packet(uint8_t type)
+{
+	switch (type) {
+	case HCI_COMMAND_PKT:
+	case HCI_ACLDATA_PKT:
+	case HCI_EVENT_PKT:
+	case HCI_ISODATA_PKT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* FIXME: Correct timeout */
+#define H5_RX_ACK_TIMEOUT	K_MSEC(250)
+#define H5_TX_ACK_TIMEOUT	K_MSEC(250)
+
+#define SLIP_DELIMITER	0xc0
+#define SLIP_ESC	0xdb
+#define SLIP_ESC_DELIM	0xdc
+#define SLIP_ESC_ESC	0xdd
+
+#define H5_RX_ESC	1
+#define H5_TX_ACK_PEND	2
+
+#define H5_HDR_SEQ(hdr)		((hdr)[0] & 0x07)
+#define H5_HDR_ACK(hdr)		(((hdr)[0] >> 3) & 0x07)
+#define H5_HDR_CRC(hdr)		(((hdr)[0] >> 6) & 0x01)
+#define H5_HDR_RELIABLE(hdr)	(((hdr)[0] >> 7) & 0x01)
+#define H5_HDR_PKT_TYPE(hdr)	((hdr)[1] & 0x0f)
+#define H5_HDR_LEN(hdr)		((((hdr)[1] >> 4) & 0x0f) + ((hdr)[2] << 4))
+
+#define H5_SET_SEQ(hdr, seq)	((hdr)[0] |= (seq))
+#define H5_SET_ACK(hdr, ack)	((hdr)[0] |= (ack) << 3)
+#define H5_SET_RELIABLE(hdr)	((hdr)[0] |= 1 << 7)
+#define H5_SET_TYPE(hdr, type)	((hdr)[1] |= type)
+#define H5_SET_LEN(hdr, len)	(((hdr)[1] |= ((len) & 0x0f) << 4), \
+				 ((hdr)[2] |= (len) >> 4))
+
+static struct h5 {
+	struct net_buf		*rx_buf;
+
+	struct k_fifo		tx_queue;
+	struct k_fifo		rx_queue;
+	struct k_fifo		unack_queue;
+
+	uint8_t			tx_win;
+	uint8_t			tx_ack;
+	uint8_t			tx_seq;
+
+	uint8_t			rx_ack;
+
+	enum {
+		UNINIT,
+		INIT,
+		ACTIVE,
+	}			link_state;
+
+	enum {
+		START,
+		HEADER,
+		PAYLOAD,
+		END,
+	}			rx_state;
+} h5;
+
+static uint8_t unack_queue_len;
+
+static const uint8_t sync_req[] = { 0x01, 0x7e };
+static const uint8_t sync_rsp[] = { 0x02, 0x7d };
+/* Third byte may change */
+static uint8_t conf_req[3] = { 0x03, 0xfc };
+static const uint8_t conf_rsp[] = { 0x04, 0x7b };
+
+/* H5 signal buffers pool */
+#define MAX_SIG_LEN	3
+#define SIGNAL_COUNT	2
+#define SIG_BUF_SIZE (BT_BUF_RESERVE + MAX_SIG_LEN)
+NET_BUF_POOL_DEFINE(h5_pool, SIGNAL_COUNT, SIG_BUF_SIZE, 0, NULL);
+
+static const struct device *h5_dev;
+
+static void h5_reset_rx(void)
+{
+	if (h5.rx_buf) {
+		net_buf_unref(h5.rx_buf);
+		h5.rx_buf = NULL;
+	}
+
+	h5.rx_state = START;
+}
+
+static int h5_unslip_byte(uint8_t *byte)
+{
+	int count;
+
+	if (*byte != SLIP_ESC) {
+		return 0;
+	}
+
+	do {
+		count = uart_fifo_read(h5_dev, byte, sizeof(*byte));
+	} while (!count);
+
+	switch (*byte) {
+	case SLIP_ESC_DELIM:
+		*byte = SLIP_DELIMITER;
+		break;
+	case SLIP_ESC_ESC:
+		*byte = SLIP_ESC;
+		break;
+	default:
+		BT_ERR("Invalid escape byte %x\n", *byte);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void process_unack(void)
+{
+	uint8_t next_seq = h5.tx_seq;
+	uint8_t number_removed = unack_queue_len;
+
+	if (!unack_queue_len) {
+		return;
+	}
+
+	BT_DBG("rx_ack %u tx_ack %u tx_seq %u unack_queue_len %u",
+	       h5.rx_ack, h5.tx_ack, h5.tx_seq, unack_queue_len);
+
+	while (unack_queue_len > 0) {
+		if (next_seq == h5.rx_ack) {
+			/* Next sequence number is the same as last received
+			 * ack number
+			 */
+			break;
+		}
+
+		number_removed--;
+		/* Similar to (n - 1) % 8 with unsigned conversion */
+		next_seq = (next_seq - 1) & 0x07;
+	}
+
+	if (next_seq != h5.rx_ack) {
+		BT_ERR("Wrong sequence: rx_ack %u tx_seq %u next_seq %u",
+		       h5.rx_ack, h5.tx_seq, next_seq);
+	}
+
+	BT_DBG("Need to remove %u packet from the queue", number_removed);
+
+	while (number_removed) {
+		struct net_buf *buf = net_buf_get(&h5.unack_queue, K_NO_WAIT);
+
+		if (!buf) {
+			BT_ERR("Unack queue is empty");
+			break;
+		}
+
+		/* TODO: print or do something with packet */
+		BT_DBG("Remove buf from the unack_queue");
+
+		net_buf_unref(buf);
+		unack_queue_len--;
+		number_removed--;
+	}
+}
+
+static void h5_print_header(const uint8_t *hdr, const char *str)
+{
+	if (H5_HDR_RELIABLE(hdr)) {
+		BT_DBG("%s REL: seq %u ack %u crc %u type %u len %u",
+		       str, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr),
+		       H5_HDR_CRC(hdr), H5_HDR_PKT_TYPE(hdr),
+		       H5_HDR_LEN(hdr));
+	} else {
+		BT_DBG("%s UNREL: ack %u crc %u type %u len %u",
+		       str, H5_HDR_ACK(hdr), H5_HDR_CRC(hdr),
+		       H5_HDR_PKT_TYPE(hdr), H5_HDR_LEN(hdr));
+	}
+}
+
+#if defined(CONFIG_BT_DEBUG_HCI_DRIVER)
+static void hexdump(const char *str, const uint8_t *packet, size_t length)
+{
+	int n = 0;
+
+	if (!length) {
+		printk("%s zero-length signal packet\n", str);
+		return;
+	}
+
+	while (length--) {
+		if (n % 16 == 0) {
+			printk("%s %08X ", str, n);
+		}
+
+		printk("%02X ", *packet++);
+
+		n++;
+		if (n % 8 == 0) {
+			if (n % 16 == 0) {
+				printk("\n");
+			} else {
+				printk(" ");
+			}
+		}
+	}
+
+	if (n % 16) {
+		printk("\n");
+	}
+}
+#else
+#define hexdump(str, packet, length)
+#endif
+
+static uint8_t h5_slip_byte(uint8_t byte)
+{
+	switch (byte) {
+	case SLIP_DELIMITER:
+		uart_poll_out(h5_dev, SLIP_ESC);
+		uart_poll_out(h5_dev, SLIP_ESC_DELIM);
+		return 2;
+	case SLIP_ESC:
+		uart_poll_out(h5_dev, SLIP_ESC);
+		uart_poll_out(h5_dev, SLIP_ESC_ESC);
+		return 2;
+	default:
+		uart_poll_out(h5_dev, byte);
+		return 1;
+	}
+}
+
+static void h5_send(const uint8_t *payload, uint8_t type, int len)
+{
+	uint8_t hdr[4];
+	int i;
+
+	hexdump("<= ", payload, len);
+
+	(void)memset(hdr, 0, sizeof(hdr));
+
+	/* Set ACK for outgoing packet and stop delayed work */
+	H5_SET_ACK(hdr, h5.tx_ack);
+	k_delayed_work_cancel(&ack_work);
+
+	if (reliable_packet(type)) {
+		H5_SET_RELIABLE(hdr);
+		H5_SET_SEQ(hdr, h5.tx_seq);
+		h5.tx_seq = (h5.tx_seq + 1) % 8;
+	}
+
+	H5_SET_TYPE(hdr, type);
+	H5_SET_LEN(hdr, len);
+
+	/* Calculate CRC */
+	hdr[3] = ~((hdr[0] + hdr[1] + hdr[2]) & 0xff);
+
+	h5_print_header(hdr, "TX: <");
+
+	uart_poll_out(h5_dev, SLIP_DELIMITER);
+
+	for (i = 0; i < 4; i++) {
+		h5_slip_byte(hdr[i]);
+	}
+
+	for (i = 0; i < len; i++) {
+		h5_slip_byte(payload[i]);
+	}
+
+	uart_poll_out(h5_dev, SLIP_DELIMITER);
+}
+
+/* Delayed work taking care about retransmitting packets */
+static void retx_timeout(struct k_work *work)
+{
+	ARG_UNUSED(work);
+
+	BT_DBG("unack_queue_len %u", unack_queue_len);
+
+	if (unack_queue_len) {
+		struct k_fifo tmp_queue;
+		struct net_buf *buf;
+
+		k_fifo_init(&tmp_queue);
+
+		/* Queue to temperary queue */
+		while ((buf = net_buf_get(&h5.tx_queue, K_NO_WAIT))) {
+			net_buf_put(&tmp_queue, buf);
+		}
+
+		/* Queue unack packets to the beginning of the queue */
+		while ((buf = net_buf_get(&h5.unack_queue, K_NO_WAIT))) {
+			/* include also packet type */
+			net_buf_push(buf, sizeof(uint8_t));
+			net_buf_put(&h5.tx_queue, buf);
+			h5.tx_seq = (h5.tx_seq - 1) & 0x07;
+			unack_queue_len--;
+		}
+
+		/* Queue saved packets from temp queue */
+		while ((buf = net_buf_get(&tmp_queue, K_NO_WAIT))) {
+			net_buf_put(&h5.tx_queue, buf);
+		}
+	}
+}
+
+static void ack_timeout(struct k_work *work)
+{
+	ARG_UNUSED(work);
+
+	BT_DBG("");
+
+	h5_send(NULL, HCI_3WIRE_ACK_PKT, 0);
+}
+
+static void h5_process_complete_packet(uint8_t *hdr)
+{
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	/* rx_ack should be in every packet */
+	h5.rx_ack = H5_HDR_ACK(hdr);
+
+	if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) {
+		/* For reliable packet increment next transmit ack number */
+		h5.tx_ack = (h5.tx_ack + 1) % 8;
+		/* Submit delayed work to ack the packet */
+		k_delayed_work_submit(&ack_work, H5_RX_ACK_TIMEOUT);
+	}
+
+	h5_print_header(hdr, "RX: >");
+
+	process_unack();
+
+	buf = h5.rx_buf;
+	h5.rx_buf = NULL;
+
+	switch (H5_HDR_PKT_TYPE(hdr)) {
+	case HCI_3WIRE_ACK_PKT:
+		net_buf_unref(buf);
+		break;
+	case HCI_3WIRE_LINK_PKT:
+		net_buf_put(&h5.rx_queue, buf);
+		break;
+	case HCI_EVENT_PKT:
+	case HCI_ACLDATA_PKT:
+	case HCI_ISODATA_PKT:
+		hexdump("=> ", buf->data, buf->len);
+		bt_recv(buf);
+		break;
+	}
+}
+
+static inline struct net_buf *get_evt_buf(uint8_t evt)
+{
+	return bt_buf_get_evt(evt, false, K_NO_WAIT);
+}
+
+static void bt_uart_isr(const struct device *unused, void *user_data)
+{
+	static int remaining;
+	uint8_t byte;
+	int ret;
+	static uint8_t hdr[4];
+
+	ARG_UNUSED(unused);
+	ARG_UNUSED(user_data);
+
+	while (uart_irq_update(h5_dev) &&
+	       uart_irq_is_pending(h5_dev)) {
+
+		if (!uart_irq_rx_ready(h5_dev)) {
+			if (uart_irq_tx_ready(h5_dev)) {
+				BT_DBG("transmit ready");
+			} else {
+				BT_DBG("spurious interrupt");
+			}
+			/* Only the UART RX path is interrupt-enabled */
+			break;
+		}
+
+		ret = uart_fifo_read(h5_dev, &byte, sizeof(byte));
+		if (!ret) {
+			continue;
+		}
+
+		switch (h5.rx_state) {
+		case START:
+			if (byte == SLIP_DELIMITER) {
+				h5.rx_state = HEADER;
+				remaining = sizeof(hdr);
+			}
+			break;
+		case HEADER:
+			/* In a case we confuse ending slip delimeter
+			 * with starting one.
+			 */
+			if (byte == SLIP_DELIMITER) {
+				remaining = sizeof(hdr);
+				continue;
+			}
+
+			if (h5_unslip_byte(&byte) < 0) {
+				h5_reset_rx();
+				continue;
+			}
+
+			memcpy(&hdr[sizeof(hdr) - remaining], &byte, 1);
+			remaining--;
+
+			if (remaining) {
+				break;
+			}
+
+			remaining = H5_HDR_LEN(hdr);
+
+			switch (H5_HDR_PKT_TYPE(hdr)) {
+			case HCI_EVENT_PKT:
+				/* The buffer is allocated only once we know
+				 * the exact event type.
+				 */
+				h5.rx_state = PAYLOAD;
+				break;
+			case HCI_ACLDATA_PKT:
+				h5.rx_buf = bt_buf_get_rx(BT_BUF_ACL_IN,
+							  K_NO_WAIT);
+				if (!h5.rx_buf) {
+					BT_WARN("No available data buffers");
+					h5_reset_rx();
+					continue;
+				}
+
+				h5.rx_state = PAYLOAD;
+				break;
+			case HCI_ISODATA_PKT:
+				h5.rx_buf = bt_buf_get_rx(BT_BUF_ISO_IN,
+							  K_NO_WAIT);
+				if (!h5.rx_buf) {
+					BT_WARN("No available data buffers");
+					h5_reset_rx();
+					continue;
+				}
+
+				h5.rx_state = PAYLOAD;
+				break;
+			case HCI_3WIRE_LINK_PKT:
+			case HCI_3WIRE_ACK_PKT:
+				h5.rx_buf = net_buf_alloc(&h5_pool, K_NO_WAIT);
+				if (!h5.rx_buf) {
+					BT_WARN("No available signal buffers");
+					h5_reset_rx();
+					continue;
+				}
+
+				h5.rx_state = PAYLOAD;
+				break;
+			default:
+				BT_ERR("Wrong packet type %u",
+				       H5_HDR_PKT_TYPE(hdr));
+				h5.rx_state = END;
+				break;
+			}
+			if (!remaining) {
+				h5.rx_state = END;
+			}
+			break;
+		case PAYLOAD:
+			if (h5_unslip_byte(&byte) < 0) {
+				h5_reset_rx();
+				continue;
+			}
+
+			/* Allocate HCI event buffer now that we know the
+			 * exact event type.
+			 */
+			if (!h5.rx_buf) {
+				h5.rx_buf = get_evt_buf(byte);
+				if (!h5.rx_buf) {
+					BT_WARN("No available event buffers");
+					h5_reset_rx();
+					continue;
+				}
+			}
+
+			net_buf_add_mem(h5.rx_buf, &byte, sizeof(byte));
+			remaining--;
+			if (!remaining) {
+				h5.rx_state = END;
+			}
+			break;
+		case END:
+			if (byte != SLIP_DELIMITER) {
+				BT_ERR("Missing ending SLIP_DELIMITER");
+				h5_reset_rx();
+				break;
+			}
+
+			BT_DBG("Received full packet: type %u",
+			       H5_HDR_PKT_TYPE(hdr));
+
+			/* Check when full packet is received, it can be done
+			 * when parsing packet header but we need to receive
+			 * full packet anyway to clear UART.
+			 */
+			if (H5_HDR_RELIABLE(hdr) &&
+			    H5_HDR_SEQ(hdr) != h5.tx_ack) {
+				BT_ERR("Seq expected %u got %u. Drop packet",
+				       h5.tx_ack, H5_HDR_SEQ(hdr));
+				h5_reset_rx();
+				break;
+			}
+
+			h5_process_complete_packet(hdr);
+			h5.rx_state = START;
+			break;
+		}
+	}
+}
+
+static uint8_t h5_get_type(struct net_buf *buf)
+{
+	return net_buf_pull_u8(buf);
+}
+
+static int h5_queue(struct net_buf *buf)
+{
+	uint8_t type;
+
+	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
+
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_CMD:
+		type = HCI_COMMAND_PKT;
+		break;
+	case BT_BUF_ACL_OUT:
+		type = HCI_ACLDATA_PKT;
+		break;
+	case BT_BUF_ISO_OUT:
+		type = HCI_ISODATA_PKT;
+		break;
+	default:
+		BT_ERR("Unknown packet type %u", bt_buf_get_type(buf));
+		return -1;
+	}
+
+	memcpy(net_buf_push(buf, sizeof(type)), &type, sizeof(type));
+
+	net_buf_put(&h5.tx_queue, buf);
+
+	return 0;
+}
+
+static void tx_thread(void)
+{
+	BT_DBG("");
+
+	/* FIXME: make periodic sending */
+	h5_send(sync_req, HCI_3WIRE_LINK_PKT, sizeof(sync_req));
+
+	while (true) {
+		struct net_buf *buf;
+		uint8_t type;
+
+		BT_DBG("link_state %u", h5.link_state);
+
+		switch (h5.link_state) {
+		case UNINIT:
+			/* FIXME: send sync */
+			k_sleep(K_MSEC(100));
+			break;
+		case INIT:
+			/* FIXME: send conf */
+			k_sleep(K_MSEC(100));
+			break;
+		case ACTIVE:
+			buf = net_buf_get(&h5.tx_queue, K_FOREVER);
+			type = h5_get_type(buf);
+
+			h5_send(buf->data, type, buf->len);
+
+			/* buf is dequeued from tx_queue and queued to unack
+			 * queue.
+			 */
+			net_buf_put(&h5.unack_queue, buf);
+			unack_queue_len++;
+
+			k_delayed_work_submit(&retx_work, H5_TX_ACK_TIMEOUT);
+
+			break;
+		}
+	}
+}
+
+static void h5_set_txwin(uint8_t *conf)
+{
+	conf[2] = h5.tx_win & 0x07;
+}
+
+static void rx_thread(void)
+{
+	BT_DBG("");
+
+	while (true) {
+		struct net_buf *buf;
+
+		buf = net_buf_get(&h5.rx_queue, K_FOREVER);
+
+		hexdump("=> ", buf->data, buf->len);
+
+		if (!memcmp(buf->data, sync_req, sizeof(sync_req))) {
+			if (h5.link_state == ACTIVE) {
+				/* TODO Reset H5 */
+			}
+
+			h5_send(sync_rsp, HCI_3WIRE_LINK_PKT, sizeof(sync_rsp));
+		} else if (!memcmp(buf->data, sync_rsp, sizeof(sync_rsp))) {
+			if (h5.link_state == ACTIVE) {
+				/* TODO Reset H5 */
+			}
+
+			h5.link_state = INIT;
+			h5_set_txwin(conf_req);
+			h5_send(conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req));
+		} else if (!memcmp(buf->data, conf_req, 2)) {
+			/*
+			 * The Host sends Config Response messages without a
+			 * Configuration Field.
+			 */
+			h5_send(conf_rsp, HCI_3WIRE_LINK_PKT, sizeof(conf_rsp));
+
+			/* Then send Config Request with Configuration Field */
+			h5_set_txwin(conf_req);
+			h5_send(conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req));
+		} else if (!memcmp(buf->data, conf_rsp, 2)) {
+			h5.link_state = ACTIVE;
+			if (buf->len > 2) {
+				/* Configuration field present */
+				h5.tx_win = (buf->data[2] & 0x07);
+			}
+
+			BT_DBG("Finished H5 configuration, tx_win %u",
+			       h5.tx_win);
+		} else {
+			BT_ERR("Not handled yet %x %x",
+			       buf->data[0], buf->data[1]);
+		}
+
+		net_buf_unref(buf);
+
+		/* Make sure we don't hog the CPU if the rx_queue never
+		 * gets empty.
+		 */
+		k_yield();
+	}
+}
+
+static void h5_init(void)
+{
+	BT_DBG("");
+
+	h5.link_state = UNINIT;
+	h5.rx_state = START;
+	h5.tx_win = 4U;
+
+	/* TX thread */
+	k_fifo_init(&h5.tx_queue);
+	k_thread_create(&tx_thread_data, tx_stack,
+			K_KERNEL_STACK_SIZEOF(tx_stack),
+			(k_thread_entry_t)tx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO),
+			0, K_NO_WAIT);
+	k_thread_name_set(&tx_thread_data, "tx_thread");
+
+	k_fifo_init(&h5.rx_queue);
+	k_thread_create(&rx_thread_data, rx_stack,
+			K_KERNEL_STACK_SIZEOF(rx_stack),
+			(k_thread_entry_t)rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_RX_PRIO),
+			0, K_NO_WAIT);
+	k_thread_name_set(&rx_thread_data, "rx_thread");
+
+	/* Unack queue */
+	k_fifo_init(&h5.unack_queue);
+
+	/* Init delayed work */
+	k_delayed_work_init(&ack_work, ack_timeout);
+	k_delayed_work_init(&retx_work, retx_timeout);
+}
+
+static int h5_open(void)
+{
+	BT_DBG("");
+
+	uart_irq_rx_disable(h5_dev);
+	uart_irq_tx_disable(h5_dev);
+
+	bt_uart_drain(h5_dev);
+
+	uart_irq_callback_set(h5_dev, bt_uart_isr);
+
+	h5_init();
+
+	uart_irq_rx_enable(h5_dev);
+
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= "H:5",
+	.bus		= BT_HCI_DRIVER_BUS_UART,
+	.open		= h5_open,
+	.send		= h5_queue,
+};
+
+static int bt_uart_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	h5_dev = device_get_binding(CONFIG_BT_UART_ON_DEV_NAME);
+
+	if (h5_dev == NULL) {
+		return -EINVAL;
+	}
+
+	bt_hci_driver_register(&drv);
+
+	return 0;
+}
+
+SYS_INIT(bt_uart_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/ipm_stm32wb.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/ipm_stm32wb.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/ipm_stm32wb.c	(working copy)
@@ -0,0 +1,539 @@
+/* ipm_stm32wb.c - HCI driver for stm32wb shared ram */
+
+/*
+ * Copyright (c) 2019 Linaro Ltd.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#include <init.h>
+#include <sys/util.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+#include "bluetooth/addr.h"
+
+#include "app_conf.h"
+#include "stm32_wpan_common.h"
+#include "shci.h"
+#include "shci_tl.h"
+
+#define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * \
+		DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4))
+
+/* Private variables ---------------------------------------------------------*/
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t BleCmdBuffer;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+	SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+	BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+	HciAclDataBuffer[sizeof(TL_PacketHeader_t) + 5 + 251];
+
+static void syscmd_status_not(SHCI_TL_CmdStatus_t status);
+static void sysevt_received(void *pdata);
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME hci_ipm
+#include "common/log.h"
+
+#define HCI_CMD                 0x01
+#define HCI_ACL                 0x02
+#define HCI_SCO                 0x03
+#define HCI_EVT                 0x04
+
+static K_SEM_DEFINE(c2_started, 0, 1);
+static K_SEM_DEFINE(ble_sys_wait_cmd_rsp, 0, 1);
+static K_SEM_DEFINE(acl_data_ack, 1, 1);
+static K_SEM_DEFINE(ipm_busy, 1, 1);
+
+struct aci_set_tx_power {
+	uint8_t cmd;
+	uint8_t value[2];
+};
+
+struct aci_set_ble_addr {
+	uint8_t config_offset;
+	uint8_t length;
+	uint8_t value[6];
+} __packed;
+
+#define ACI_WRITE_SET_TX_POWER_LEVEL       BT_OP(BT_OGF_VS, 0xFC0F)
+#define ACI_HAL_WRITE_CONFIG_DATA	   BT_OP(BT_OGF_VS, 0xFC0C)
+
+#define HCI_CONFIG_DATA_PUBADDR_OFFSET		0
+#define HCI_CONFIG_DATA_RANDOM_ADDRESS_OFFSET	0x2E
+
+static bt_addr_t bd_addr_udn;
+
+/* Rx thread definitions */
+K_FIFO_DEFINE(ipm_rx_events_fifo);
+static K_KERNEL_STACK_DEFINE(ipm_rx_stack, CONFIG_BT_STM32_IPM_RX_STACK_SIZE);
+static struct k_thread ipm_rx_thread_data;
+
+static void stm32wb_start_ble(void)
+{
+	SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
+	  { { 0, 0, 0 } },                     /**< Header unused */
+	  { 0,                                 /** pBleBufferAddress not used */
+	    0,                                 /** BleBufferSize not used */
+	    CFG_BLE_NUM_GATT_ATTRIBUTES,
+	    CFG_BLE_NUM_GATT_SERVICES,
+	    CFG_BLE_ATT_VALUE_ARRAY_SIZE,
+	    CFG_BLE_NUM_LINK,
+	    CFG_BLE_DATA_LENGTH_EXTENSION,
+	    CFG_BLE_PREPARE_WRITE_LIST_SIZE,
+	    CFG_BLE_MBLOCK_COUNT,
+	    CFG_BLE_MAX_ATT_MTU,
+	    CFG_BLE_SLAVE_SCA,
+	    CFG_BLE_MASTER_SCA,
+	    CFG_BLE_LSE_SOURCE,
+	    CFG_BLE_MAX_CONN_EVENT_LENGTH,
+	    CFG_BLE_HSE_STARTUP_TIME,
+	    CFG_BLE_VITERBI_MODE,
+	    CFG_BLE_LL_ONLY,
+	    0 }
+	};
+
+	/**
+	 * Starts the BLE Stack on CPU2
+	 */
+	SHCI_C2_BLE_Init(&ble_init_cmd_packet);
+}
+
+static void sysevt_received(void *pdata)
+{
+	k_sem_give(&c2_started);
+}
+
+static void syscmd_status_not(SHCI_TL_CmdStatus_t status)
+{
+	BT_DBG("status:%d", status);
+}
+
+/*
+ * https://github.com/zephyrproject-rtos/zephyr/issues/19509
+ * Tested on nucleo_wb55rg (stm32wb55rg) BLE stack (v1.2.0)
+ * Unresolved Resolvable Private Addresses (RPA)
+ * is reported in the peer_rpa field, and not in the peer address,
+ * as it should, when this happens the peer address is set to all FFs
+ * 0A 00 01 08 01 01 FF FF FF FF FF FF 00 00 00 00 00 00 0C AA C5 B3 3D 6B ...
+ * If such message is passed to HCI core than pairing will essentially fail.
+ * Solution: Rewrite the event with the RPA in the PEER address field
+ */
+static void tryfix_event(TL_Evt_t *tev)
+{
+	struct bt_hci_evt_le_meta_event *mev = (void *)&tev->payload;
+
+	if (tev->evtcode != BT_HCI_EVT_LE_META_EVENT ||
+	    mev->subevent != BT_HCI_EVT_LE_ENH_CONN_COMPLETE) {
+		return;
+	}
+
+	struct bt_hci_evt_le_enh_conn_complete *evt =
+			(void *)((uint8_t *)mev + (sizeof(*mev)));
+
+	if (!bt_addr_cmp(&evt->peer_addr.a, BT_ADDR_NONE)) {
+		BT_WARN("Invalid peer addr %s", bt_addr_le_str(&evt->peer_addr));
+		bt_addr_copy(&evt->peer_addr.a, &evt->peer_rpa);
+		evt->peer_addr.type = BT_ADDR_LE_RANDOM;
+	}
+}
+
+void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt)
+{
+	k_fifo_put(&ipm_rx_events_fifo, hcievt);
+}
+
+static void bt_ipm_rx_thread(void)
+{
+	while (true) {
+		static TL_EvtPacket_t *hcievt;
+		struct net_buf *buf = NULL;
+		struct bt_hci_acl_hdr acl_hdr;
+		TL_AclDataSerial_t *acl;
+
+		hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
+
+		k_sem_take(&ipm_busy, K_FOREVER);
+
+		switch (hcievt->evtserial.type) {
+		case HCI_EVT:
+			BT_DBG("EVT: hcievt->evtserial.evt.evtcode: 0x%02x",
+			       hcievt->evtserial.evt.evtcode);
+			switch (hcievt->evtserial.evt.evtcode) {
+			case BT_HCI_EVT_VENDOR:
+				/* Vendor events are currently unsupported */
+				BT_ERR("Unknown evtcode type 0x%02x",
+				       hcievt->evtserial.evt.evtcode);
+				TL_MM_EvtDone(hcievt);
+				goto end_loop;
+			default:
+				buf = bt_buf_get_evt(
+					hcievt->evtserial.evt.evtcode,
+					false, K_FOREVER);
+			}
+			tryfix_event(&hcievt->evtserial.evt);
+			net_buf_add_mem(buf, &hcievt->evtserial.evt,
+					hcievt->evtserial.evt.plen + 2);
+			break;
+		case HCI_ACL:
+			acl = &(((TL_AclDataPacket_t *)hcievt)->AclDataSerial);
+			buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
+			acl_hdr.handle = acl->handle;
+			acl_hdr.len = acl->length;
+			BT_DBG("ACL: handle %x, len %x",
+			       acl_hdr.handle, acl_hdr.len);
+			net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr));
+			net_buf_add_mem(buf, (uint8_t *)&acl->acl_data,
+					acl_hdr.len);
+			break;
+		default:
+			BT_ERR("Unknown BT buf type %d",
+			       hcievt->evtserial.type);
+			TL_MM_EvtDone(hcievt);
+			goto end_loop;
+		}
+
+		TL_MM_EvtDone(hcievt);
+
+		bt_recv(buf);
+end_loop:
+		k_sem_give(&ipm_busy);
+	}
+
+}
+
+static void TM_AclDataAck(void)
+{
+	k_sem_give(&acl_data_ack);
+}
+
+void shci_notify_asynch_evt(void *pdata)
+{
+	shci_user_evt_proc();
+}
+
+void shci_cmd_resp_release(uint32_t flag)
+{
+	k_sem_give(&ble_sys_wait_cmd_rsp);
+}
+
+void shci_cmd_resp_wait(uint32_t timeout)
+{
+	k_sem_take(&ble_sys_wait_cmd_rsp, K_MSEC(timeout));
+}
+
+void ipcc_reset(void)
+{
+	/* Reset IPCC */
+	LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
+
+	LL_C1_IPCC_ClearFlag_CHx(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	LL_C2_IPCC_ClearFlag_CHx(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	LL_C1_IPCC_DisableTransmitChannel(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	LL_C2_IPCC_DisableTransmitChannel(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	LL_C1_IPCC_DisableReceiveChannel(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	LL_C2_IPCC_DisableReceiveChannel(
+		IPCC,
+		LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
+		LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+	/* Set IPCC default IRQ handlers */
+	IRQ_CONNECT(IPCC_C1_RX_IRQn, 0, HW_IPCC_Rx_Handler, NULL, 0);
+	IRQ_CONNECT(IPCC_C1_TX_IRQn, 0, HW_IPCC_Tx_Handler, NULL, 0);
+}
+
+void transport_init(void)
+{
+	TL_MM_Config_t tl_mm_config;
+	TL_BLE_InitConf_t tl_ble_config;
+	SHCI_TL_HciInitConf_t shci_init_config;
+
+	BT_DBG("BleCmdBuffer: %p", (void *)&BleCmdBuffer);
+	BT_DBG("HciAclDataBuffer: %p", (void *)&HciAclDataBuffer);
+	BT_DBG("SystemCmdBuffer: %p", (void *)&SystemCmdBuffer);
+	BT_DBG("EvtPool: %p", (void *)&EvtPool);
+	BT_DBG("SystemSpareEvtBuffer: %p", (void *)&SystemSpareEvtBuffer);
+	BT_DBG("BleSpareEvtBuffer: %p", (void *)&BleSpareEvtBuffer);
+
+	/**< Reference table initialization */
+	TL_Init();
+
+	/**< System channel initialization */
+	shci_init_config.p_cmdbuffer = (uint8_t *)&SystemCmdBuffer;
+	shci_init_config.StatusNotCallBack = syscmd_status_not;
+	shci_init(sysevt_received, (void *) &shci_init_config);
+
+	/**< Memory Manager channel initialization */
+	tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer;
+	tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer;
+	tl_mm_config.p_AsynchEvtPool = EvtPool;
+	tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
+	TL_MM_Init(&tl_mm_config);
+
+	/**< BLE channel initialization */
+	tl_ble_config.p_cmdbuffer = (uint8_t *)&BleCmdBuffer;
+	tl_ble_config.p_AclDataBuffer = HciAclDataBuffer;
+	tl_ble_config.IoBusEvtCallBack = TM_EvtReceivedCb;
+	tl_ble_config.IoBusAclDataTxAck = TM_AclDataAck;
+	TL_BLE_Init((void *)&tl_ble_config);
+
+	TL_Enable();
+}
+
+static int bt_ipm_send(struct net_buf *buf)
+{
+	TL_CmdPacket_t *ble_cmd_buff = &BleCmdBuffer;
+
+	k_sem_take(&ipm_busy, K_FOREVER);
+
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_ACL_OUT:
+		BT_DBG("ACL: buf %p type %u len %u", buf, bt_buf_get_type(buf),
+		       buf->len);
+		k_sem_take(&acl_data_ack, K_FOREVER);
+		net_buf_push_u8(buf, HCI_ACL);
+		memcpy((void *)
+		       &((TL_AclDataPacket_t *)HciAclDataBuffer)->AclDataSerial,
+		       buf->data, buf->len);
+		TL_BLE_SendAclData(NULL, 0);
+		break;
+	case BT_BUF_CMD:
+		BT_DBG("CMD: buf %p type %u len %u", buf, bt_buf_get_type(buf),
+		       buf->len);
+		ble_cmd_buff->cmdserial.type = HCI_CMD;
+		ble_cmd_buff->cmdserial.cmd.plen = buf->len;
+		memcpy((void *)&ble_cmd_buff->cmdserial.cmd, buf->data,
+		       buf->len);
+		TL_BLE_SendCmd(NULL, 0);
+		break;
+	default:
+		k_sem_give(&ipm_busy);
+		BT_ERR("Unsupported type");
+		return -EINVAL;
+	}
+
+	k_sem_give(&ipm_busy);
+
+	net_buf_unref(buf);
+
+	return 0;
+}
+
+static void start_ble_rf(void)
+{
+	if ((LL_RCC_IsActiveFlag_PINRST()) && (!LL_RCC_IsActiveFlag_SFTRST())) {
+		/* Simulate power off reset */
+		LL_PWR_EnableBkUpAccess();
+		LL_PWR_EnableBkUpAccess();
+		LL_RCC_ForceBackupDomainReset();
+		LL_RCC_ReleaseBackupDomainReset();
+	}
+
+#ifdef CONFIG_CLOCK_STM32_LSE
+	/* Select LSE clock */
+	LL_RCC_LSE_Enable();
+	while (!LL_RCC_LSE_IsReady()) {
+	}
+
+	/* Select wakeup source of BLE RF */
+	LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
+	LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
+
+	/* Switch OFF LSI */
+	LL_RCC_LSI2_Disable();
+#else
+	LL_RCC_LSI2_Enable();
+	while (!LL_RCC_LSI2_IsReady()) {
+	}
+
+	/* Select wakeup source of BLE RF */
+	LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSI);
+	LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);
+#endif
+
+	/* Set RNG on HSI48 */
+	LL_RCC_HSI48_Enable();
+	while (!LL_RCC_HSI48_IsReady()) {
+	}
+
+	LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_HSI48);
+}
+
+bt_addr_t *bt_get_ble_addr(void)
+{
+	bt_addr_t *bd_addr;
+	uint32_t udn;
+	uint32_t company_id;
+	uint32_t device_id;
+
+	/* Get the 64 bit Unique Device Number UID */
+	/* The UID is used by firmware to derive   */
+	/* 48-bit Device Address EUI-48 */
+	udn = LL_FLASH_GetUDN();
+
+	if (udn != 0xFFFFFFFF) {
+		/* Get the ST Company ID */
+		company_id = LL_FLASH_GetSTCompanyID();
+		/* Get the STM32 Device ID */
+		device_id = LL_FLASH_GetDeviceID();
+		bd_addr_udn.val[0] = (uint8_t)(udn & 0x000000FF);
+		bd_addr_udn.val[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
+		bd_addr_udn.val[2] = (uint8_t)((udn & 0x00FF0000) >> 16);
+		bd_addr_udn.val[3] = (uint8_t)device_id;
+		bd_addr_udn.val[4] = (uint8_t)(company_id & 0x000000FF);
+		bd_addr_udn.val[5] = (uint8_t)((company_id & 0x0000FF00) >> 8);
+		bd_addr = &bd_addr_udn;
+	} else {
+		bd_addr = NULL;
+	}
+
+	return bd_addr;
+}
+
+static int bt_ipm_set_addr(void)
+{
+	bt_addr_t *uid_addr;
+	struct aci_set_ble_addr *param;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	uid_addr = bt_get_ble_addr();
+	if (!uid_addr) {
+		return -ENOMSG;
+	}
+
+	buf = bt_hci_cmd_create(ACI_HAL_WRITE_CONFIG_DATA, sizeof(*param));
+
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	param = net_buf_add(buf, sizeof(*param));
+	param->config_offset = HCI_CONFIG_DATA_PUBADDR_OFFSET;
+	param->length = 6;
+	param->value[0] = uid_addr->val[0];
+	param->value[1] = uid_addr->val[1];
+	param->value[2] = uid_addr->val[2];
+	param->value[3] = uid_addr->val[3];
+	param->value[4] = uid_addr->val[4];
+	param->value[5] = uid_addr->val[5];
+
+	err = bt_hci_cmd_send_sync(ACI_HAL_WRITE_CONFIG_DATA, buf, &rsp);
+	if (err) {
+		return err;
+	}
+	net_buf_unref(rsp);
+	return 0;
+}
+
+static int bt_ipm_ble_init(void)
+{
+	struct aci_set_tx_power *param;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	/* Send HCI_RESET */
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, &rsp);
+	if (err) {
+		return err;
+	}
+	/* TDB: Something to do on reset complete? */
+	net_buf_unref(rsp);
+	err = bt_ipm_set_addr();
+	if (err) {
+		BT_ERR("Can't set BLE UID addr");
+	}
+	/* Send ACI_WRITE_SET_TX_POWER_LEVEL */
+	buf = bt_hci_cmd_create(ACI_WRITE_SET_TX_POWER_LEVEL, 3);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+	param = net_buf_add(buf, sizeof(*param));
+	param->cmd = 0x0F;
+	param->value[0] = 0x18;
+	param->value[1] = 0x01;
+
+	err = bt_hci_cmd_send_sync(ACI_WRITE_SET_TX_POWER_LEVEL, buf, &rsp);
+	if (err) {
+		return err;
+	}
+	net_buf_unref(rsp);
+
+	return 0;
+}
+
+static int bt_ipm_open(void)
+{
+	int err;
+
+	/* Start RX thread */
+	k_thread_create(&ipm_rx_thread_data, ipm_rx_stack,
+			K_KERNEL_STACK_SIZEOF(ipm_rx_stack),
+			(k_thread_entry_t)bt_ipm_rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
+			0, K_NO_WAIT);
+
+	/* Take BLE out of reset */
+	ipcc_reset();
+
+	transport_init();
+
+	/* Device will let us know when it's ready */
+	k_sem_take(&c2_started, K_FOREVER);
+	BT_DBG("C2 unlocked");
+
+	stm32wb_start_ble();
+
+	BT_DBG("IPM Channel Open Completed");
+
+	err = bt_ipm_ble_init();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name           = "BT IPM",
+	.bus            = BT_HCI_DRIVER_BUS_IPM,
+	.quirks         = BT_QUIRK_NO_RESET,
+	.open           = bt_ipm_open,
+	.send           = bt_ipm_send,
+};
+
+static int _bt_ipm_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	bt_hci_driver_register(&drv);
+
+	start_ble_rf();
+	return 0;
+}
+
+SYS_INIT(_bt_ipm_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg.c	(working copy)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <init.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_hci_driver
+#include "common/log.h"
+
+#define RPMSG_CMD 0x01
+#define RPMSG_ACL 0x02
+#define RPMSG_SCO 0x03
+#define RPMSG_EVT 0x04
+
+int bt_rpmsg_platform_init(void);
+int bt_rpmsg_platform_send(struct net_buf *buf);
+
+static bool is_hci_event_discardable(const uint8_t *evt_data)
+{
+	uint8_t evt_type = evt_data[0];
+
+	switch (evt_type) {
+#if defined(CONFIG_BT_BREDR)
+	case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI:
+	case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT:
+		return true;
+#endif
+	case BT_HCI_EVT_LE_META_EVENT: {
+		uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)];
+
+		switch (subevt_type) {
+		case BT_HCI_EVT_LE_ADVERTISING_REPORT:
+			return true;
+		default:
+			return false;
+		}
+	}
+	default:
+		return false;
+	}
+}
+
+static struct net_buf *bt_rpmsg_evt_recv(uint8_t *data, size_t remaining)
+{
+	bool discardable;
+	struct bt_hci_evt_hdr hdr;
+	struct net_buf *buf;
+
+	if (remaining < sizeof(hdr)) {
+		BT_ERR("Not enough data for event header");
+		return NULL;
+	}
+
+	discardable = is_hci_event_discardable(data);
+
+	memcpy((void *)&hdr, data, sizeof(hdr));
+	data += sizeof(hdr);
+	remaining -= sizeof(hdr);
+
+	if (remaining != hdr.len) {
+		BT_ERR("Event payload length is not correct");
+		return NULL;
+	}
+	BT_DBG("len %u", hdr.len);
+
+	buf = bt_buf_get_evt(hdr.evt, discardable, K_NO_WAIT);
+	if (!buf) {
+		if (discardable) {
+			BT_DBG("Discardable buffer pool full, ignoring event");
+		} else {
+			BT_ERR("No available event buffers!");
+		}
+		return buf;
+	}
+
+	net_buf_add_mem(buf, &hdr, sizeof(hdr));
+	net_buf_add_mem(buf, data, remaining);
+
+	return buf;
+}
+
+static struct net_buf *bt_rpmsg_acl_recv(uint8_t *data, size_t remaining)
+{
+	struct bt_hci_acl_hdr hdr;
+	struct net_buf *buf;
+
+	if (remaining < sizeof(hdr)) {
+		BT_ERR("Not enough data for ACL header");
+		return NULL;
+	}
+
+	buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT);
+	if (buf) {
+		memcpy((void *)&hdr, data, sizeof(hdr));
+		data += sizeof(hdr);
+		remaining -= sizeof(hdr);
+
+		net_buf_add_mem(buf, &hdr, sizeof(hdr));
+	} else {
+		BT_ERR("No available ACL buffers!");
+		return NULL;
+	}
+
+	if (remaining != sys_le16_to_cpu(hdr.len)) {
+		BT_ERR("ACL payload length is not correct");
+		net_buf_unref(buf);
+		return NULL;
+	}
+
+	BT_DBG("len %u", remaining);
+	net_buf_add_mem(buf, data, remaining);
+
+	return buf;
+}
+
+void bt_rpmsg_rx(uint8_t *data, size_t len)
+{
+	uint8_t pkt_indicator;
+	struct net_buf *buf = NULL;
+	size_t remaining = len;
+
+	BT_HEXDUMP_DBG(data, len, "RPMsg data:");
+
+	pkt_indicator = *data++;
+	remaining -= sizeof(pkt_indicator);
+
+	switch (pkt_indicator) {
+	case RPMSG_EVT:
+		buf = bt_rpmsg_evt_recv(data, remaining);
+		break;
+
+	case RPMSG_ACL:
+		buf = bt_rpmsg_acl_recv(data, remaining);
+		break;
+
+	default:
+		BT_ERR("Unknown HCI type %u", pkt_indicator);
+		return;
+	}
+
+	if (buf) {
+		BT_DBG("Calling bt_recv(%p)", buf);
+
+		bt_recv(buf);
+
+		BT_HEXDUMP_DBG(buf->data, buf->len, "RX buf payload:");
+	}
+}
+
+static int bt_rpmsg_send(struct net_buf *buf)
+{
+	int err;
+	uint8_t pkt_indicator;
+
+	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
+
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_ACL_OUT:
+		pkt_indicator = RPMSG_ACL;
+		break;
+	case BT_BUF_CMD:
+		pkt_indicator = RPMSG_CMD;
+		break;
+	default:
+		BT_ERR("Unknown type %u", bt_buf_get_type(buf));
+		goto done;
+	}
+	net_buf_push_u8(buf, pkt_indicator);
+
+	BT_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
+	err = bt_rpmsg_platform_send(buf);
+	if (err < 0) {
+		BT_ERR("Failed to send (err %d)", err);
+	}
+
+done:
+	net_buf_unref(buf);
+	return 0;
+}
+
+static int bt_rpmsg_open(void)
+{
+	BT_DBG("");
+
+	return bt_rpmsg_platform_init();
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= "RPMsg",
+	.open		= bt_rpmsg_open,
+	.send		= bt_rpmsg_send,
+	.bus		= BT_HCI_DRIVER_BUS_IPM,
+#if defined(BT_DRIVER_QUIRK_NO_AUTO_DLE)
+	.quirks         = BT_QUIRK_NO_AUTO_DLE,
+#endif
+};
+
+static int bt_rpmsg_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	return bt_hci_driver_register(&drv);
+}
+
+SYS_INIT(bt_rpmsg_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg_nrf53.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg_nrf53.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/rpmsg_nrf53.c	(working copy)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <drivers/ipm.h>
+
+#include <openamp/open_amp.h>
+#include <metal/sys.h>
+#include <metal/device.h>
+#include <metal/alloc.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_hci_driver_nrf53
+#include "common/log.h"
+
+void bt_rpmsg_rx(uint8_t *data, size_t len);
+
+static K_SEM_DEFINE(ready_sem, 0, 1);
+static K_SEM_DEFINE(rx_sem, 0, 1);
+
+static K_KERNEL_STACK_DEFINE(bt_rpmsg_rx_thread_stack,
+			     CONFIG_BT_RPMSG_NRF53_RX_STACK_SIZE);
+static struct k_thread bt_rpmsg_rx_thread_data;
+
+static const struct device *ipm_tx_handle;
+static const struct device *ipm_rx_handle;
+
+/* Configuration defines */
+
+#define SHM_NODE            DT_CHOSEN(zephyr_ipc_shm)
+#define SHM_BASE_ADDRESS    DT_REG_ADDR(SHM_NODE)
+
+#define SHM_START_ADDR      (SHM_BASE_ADDRESS + 0x400)
+#define SHM_SIZE            0x7c00
+#define SHM_DEVICE_NAME     "sram0.shm"
+
+BUILD_ASSERT((SHM_START_ADDR + SHM_SIZE - SHM_BASE_ADDRESS)
+		<= DT_REG_SIZE(SHM_NODE),
+	"Allocated size exceeds available shared memory reserved for IPC");
+
+#define VRING_COUNT         2
+#define VRING_TX_ADDRESS    (SHM_START_ADDR + SHM_SIZE - 0x400)
+#define VRING_RX_ADDRESS    (VRING_TX_ADDRESS - 0x400)
+#define VRING_ALIGNMENT     4
+#define VRING_SIZE          16
+
+#define VDEV_STATUS_ADDR    SHM_BASE_ADDRESS
+
+BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >= 1024,
+	"Not enough heap memory for RPMsg queue allocation");
+
+/* End of configuration defines */
+
+static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR };
+static struct metal_device shm_device = {
+	.name = SHM_DEVICE_NAME,
+	.bus = NULL,
+	.num_regions = 1,
+	.regions = {
+		{
+			.virt       = (void *) SHM_START_ADDR,
+			.physmap    = shm_physmap,
+			.size       = SHM_SIZE,
+			.page_shift = 0xffffffff,
+			.page_mask  = 0xffffffff,
+			.mem_flags  = 0,
+			.ops        = { NULL },
+		},
+	},
+	.node = { NULL },
+	.irq_num = 0,
+	.irq_info = NULL
+};
+
+static struct virtqueue *vq[2];
+static struct rpmsg_endpoint ep;
+
+static unsigned char virtio_get_status(struct virtio_device *vdev)
+{
+	return VIRTIO_CONFIG_STATUS_DRIVER_OK;
+}
+
+static void virtio_set_status(struct virtio_device *vdev, unsigned char status)
+{
+	sys_write8(status, VDEV_STATUS_ADDR);
+}
+
+static uint32_t virtio_get_features(struct virtio_device *vdev)
+{
+	return BIT(VIRTIO_RPMSG_F_NS);
+}
+
+static void virtio_set_features(struct virtio_device *vdev, uint32_t features)
+{
+	/* No need for implementation */
+}
+
+static void virtio_notify(struct virtqueue *vq)
+{
+	int status;
+
+	status = ipm_send(ipm_tx_handle, 0, 0, NULL, 0);
+	if (status != 0) {
+		BT_ERR("ipm_send failed to notify: %d", status);
+	}
+}
+
+const struct virtio_dispatch dispatch = {
+	.get_status = virtio_get_status,
+	.set_status = virtio_set_status,
+	.get_features = virtio_get_features,
+	.set_features = virtio_set_features,
+	.notify = virtio_notify,
+};
+
+static void ipm_callback(const struct device *dev, void *context,
+			 uint32_t id, volatile void *data)
+{
+	BT_DBG("Got callback of id %u", id);
+	k_sem_give(&rx_sem);
+}
+
+static int endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,
+	uint32_t src, void *priv)
+{
+	BT_DBG("Received message of %u bytes.", len);
+	BT_HEXDUMP_DBG((uint8_t *)data, len, "Data:");
+
+	bt_rpmsg_rx(data, len);
+
+	return RPMSG_SUCCESS;
+}
+
+static void rpmsg_service_unbind(struct rpmsg_endpoint *ep)
+{
+	rpmsg_destroy_ept(ep);
+}
+
+static void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest)
+{
+	(void)rpmsg_create_ept(&ep,
+				rdev,
+				name,
+				RPMSG_ADDR_ANY,
+				dest,
+				endpoint_cb,
+				rpmsg_service_unbind);
+
+	k_sem_give(&ready_sem);
+}
+
+static void bt_rpmsg_rx_thread(void *p1, void *p2, void *p3)
+{
+	ARG_UNUSED(p1);
+	ARG_UNUSED(p2);
+	ARG_UNUSED(p3);
+
+	while (1) {
+		int status = k_sem_take(&rx_sem, K_FOREVER);
+
+		if (status == 0) {
+			virtqueue_notification(vq[0]);
+		}
+	}
+}
+
+int bt_rpmsg_platform_init(void)
+{
+	int err;
+	struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
+
+	static struct virtio_vring_info     rvrings[2];
+	static struct rpmsg_virtio_shm_pool shpool;
+	static struct virtio_device         vdev;
+	static struct rpmsg_virtio_device   rvdev;
+	static struct metal_io_region       *io;
+	static struct metal_device          *device;
+
+	/* Setup thread for RX data processing. */
+	k_thread_create(&bt_rpmsg_rx_thread_data, bt_rpmsg_rx_thread_stack,
+			K_KERNEL_STACK_SIZEOF(bt_rpmsg_rx_thread_stack),
+			bt_rpmsg_rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_RPMSG_NRF53_RX_PRIO),
+			0, K_NO_WAIT);
+
+	/* Libmetal setup */
+	err = metal_init(&metal_params);
+	if (err) {
+		BT_ERR("metal_init: failed - error code %d", err);
+		return err;
+	}
+
+	err = metal_register_generic_device(&shm_device);
+	if (err) {
+		BT_ERR("Couldn't register shared memory device: %d", err);
+		return err;
+	}
+
+	err = metal_device_open("generic", SHM_DEVICE_NAME, &device);
+	if (err) {
+		BT_ERR("metal_device_open failed: %d", err);
+		return err;
+	}
+
+	io = metal_device_io_region(device, 0);
+	if (!io) {
+		BT_ERR("metal_device_io_region failed to get region");
+		return -ENODEV;
+	}
+
+	/* IPM setup */
+	ipm_tx_handle = device_get_binding("IPM_0");
+	if (!ipm_tx_handle) {
+		BT_ERR("Could not get TX IPM device handle");
+		return -ENODEV;
+	}
+
+	ipm_rx_handle = device_get_binding("IPM_1");
+	if (!ipm_rx_handle) {
+		BT_ERR("Could not get RX IPM device handle");
+		return -ENODEV;
+	}
+
+	ipm_register_callback(ipm_rx_handle, ipm_callback, NULL);
+
+	/* Virtqueue setup */
+	vq[0] = virtqueue_allocate(VRING_SIZE);
+	if (!vq[0]) {
+		BT_ERR("virtqueue_allocate failed to alloc vq[0]");
+		return -ENOMEM;
+	}
+
+	vq[1] = virtqueue_allocate(VRING_SIZE);
+	if (!vq[1]) {
+		BT_ERR("virtqueue_allocate failed to alloc vq[1]");
+		return -ENOMEM;
+	}
+
+	rvrings[0].io = io;
+	rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS;
+	rvrings[0].info.num_descs = VRING_SIZE;
+	rvrings[0].info.align = VRING_ALIGNMENT;
+	rvrings[0].vq = vq[0];
+
+	rvrings[1].io = io;
+	rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS;
+	rvrings[1].info.num_descs = VRING_SIZE;
+	rvrings[1].info.align = VRING_ALIGNMENT;
+	rvrings[1].vq = vq[1];
+
+	vdev.role = RPMSG_MASTER;
+	vdev.vrings_num = VRING_COUNT;
+	vdev.func = &dispatch;
+	vdev.vrings_info = &rvrings[0];
+
+	rpmsg_virtio_init_shm_pool(&shpool, (void *)SHM_START_ADDR, SHM_SIZE);
+	err = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool);
+	if (err) {
+		BT_ERR("rpmsg_init_vdev failed %d", err);
+		return err;
+	}
+
+	/* Wait til nameservice ep is setup */
+	k_sem_take(&ready_sem, K_FOREVER);
+
+	return 0;
+}
+
+int bt_rpmsg_platform_send(struct net_buf *buf)
+{
+	return rpmsg_send(&ep, buf->data, buf->len);
+}
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/spi.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/spi.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/spi.c	(working copy)
@@ -0,0 +1,571 @@
+/* spi.c - SPI based Bluetooth driver */
+
+#define DT_DRV_COMPAT zephyr_bt_hci_spi
+
+/*
+ * Copyright (c) 2017 Linaro Ltd.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <drivers/gpio.h>
+#include <init.h>
+#include <drivers/spi.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_driver
+#include "common/log.h"
+
+#define HCI_CMD			0x01
+#define HCI_ACL			0x02
+#define HCI_SCO			0x03
+#define HCI_EVT			0x04
+
+/* Special Values */
+#define SPI_WRITE		0x0A
+#define SPI_READ		0x0B
+#define READY_NOW		0x02
+
+#define EVT_BLUE_INITIALIZED	0x01
+
+/* Offsets */
+#define STATUS_HEADER_READY	0
+#define STATUS_HEADER_TOREAD	3
+
+#define PACKET_TYPE		0
+#define EVT_HEADER_TYPE		0
+#define EVT_HEADER_EVENT	1
+#define EVT_HEADER_SIZE		2
+#define EVT_VENDOR_CODE_LSB	3
+#define EVT_VENDOR_CODE_MSB	4
+
+#define CMD_OGF			1
+#define CMD_OCF			2
+
+#define GPIO_IRQ_PIN		DT_INST_GPIO_PIN(0, irq_gpios)
+#define GPIO_IRQ_FLAGS		DT_INST_GPIO_FLAGS(0, irq_gpios)
+#define GPIO_RESET_PIN		DT_INST_GPIO_PIN(0, reset_gpios)
+#define GPIO_RESET_FLAGS	DT_INST_GPIO_FLAGS(0, reset_gpios)
+#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
+#define GPIO_CS_PIN		DT_INST_SPI_DEV_CS_GPIOS_PIN(0)
+#define GPIO_CS_FLAGS		DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0)
+#endif /* DT_INST_SPI_DEV_HAS_CS_GPIOS(0) */
+
+/* Max SPI buffer length for transceive operations.
+ *
+ * Buffer size needs to be at least the size of the larger RX/TX buffer
+ * required by the SPI slave, as the legacy spi_transceive requires both RX/TX
+ * to be the same length. Size also needs to be compatible with the
+ * slave device used (e.g. nRF5X max buffer length for SPIS is 255).
+ */
+#define SPI_MAX_MSG_LEN		255 /* As defined by X-NUCLEO-IDB04A1 BSP */
+
+static uint8_t rxmsg[SPI_MAX_MSG_LEN];
+static uint8_t txmsg[SPI_MAX_MSG_LEN];
+
+static const struct device *irq_dev;
+static const struct device *rst_dev;
+
+static struct gpio_callback	gpio_cb;
+
+static K_SEM_DEFINE(sem_initialised, 0, 1);
+static K_SEM_DEFINE(sem_request, 0, 1);
+static K_SEM_DEFINE(sem_busy, 1, 1);
+
+static K_KERNEL_STACK_DEFINE(spi_rx_stack, 256);
+static struct k_thread spi_rx_thread_data;
+
+#if defined(CONFIG_BT_DEBUG_HCI_DRIVER)
+#include <sys/printk.h>
+static inline void spi_dump_message(const uint8_t *pre, uint8_t *buf,
+				    uint8_t size)
+{
+	uint8_t i, c;
+
+	printk("%s (%d): ", pre, size);
+	for (i = 0U; i < size; i++) {
+		c = buf[i];
+		printk("%x ", c);
+		if (c >= 31U && c <= 126U) {
+			printk("[%c] ", c);
+		} else {
+			printk("[.] ");
+		}
+	}
+	printk("\n");
+}
+#else
+static inline
+void spi_dump_message(const uint8_t *pre, uint8_t *buf, uint8_t size) {}
+#endif
+
+#if defined(CONFIG_BT_SPI_BLUENRG)
+static const struct device *cs_dev;
+/* Define a limit when reading IRQ high */
+/* It can be required to be increased for */
+/* some particular cases. */
+#define IRQ_HIGH_MAX_READ 3
+static uint8_t attempts;
+#endif /* CONFIG_BT_SPI_BLUENRG */
+
+#if defined(CONFIG_BT_BLUENRG_ACI)
+#define BLUENRG_ACI_WRITE_CONFIG_DATA       BT_OP(BT_OGF_VS, 0x000C)
+#define BLUENRG_ACI_WRITE_CONFIG_CMD_LL     0x2C
+#define BLUENRG_ACI_LL_MODE                 0x01
+
+struct bluenrg_aci_cmd_ll_param {
+    uint8_t cmd;
+    uint8_t length;
+    uint8_t value;
+};
+static int bt_spi_send_aci_config_data_controller_mode(void);
+#endif /* CONFIG_BT_BLUENRG_ACI */
+
+static const struct device *spi_dev;
+
+static struct spi_config spi_conf = {
+	.frequency = DT_INST_PROP(0, spi_max_frequency),
+	.operation = (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) |
+		      SPI_LINES_SINGLE),
+	.slave     = 0,
+	.cs        = NULL,
+};
+static struct spi_buf spi_tx_buf;
+static struct spi_buf spi_rx_buf;
+static const struct spi_buf_set spi_tx = {
+	.buffers = &spi_tx_buf,
+	.count = 1
+};
+static const struct spi_buf_set spi_rx = {
+	.buffers = &spi_rx_buf,
+	.count = 1
+};
+
+static inline int bt_spi_transceive(void *tx, uint32_t tx_len,
+				    void *rx, uint32_t rx_len)
+{
+	spi_tx_buf.buf = tx;
+	spi_tx_buf.len = (size_t)tx_len;
+	spi_rx_buf.buf = rx;
+	spi_rx_buf.len = (size_t)rx_len;
+	return spi_transceive(spi_dev, &spi_conf, &spi_tx, &spi_rx);
+}
+
+static inline uint16_t bt_spi_get_cmd(uint8_t *txmsg)
+{
+	return (txmsg[CMD_OCF] << 8) | txmsg[CMD_OGF];
+}
+
+static inline uint16_t bt_spi_get_evt(uint8_t *rxmsg)
+{
+	return (rxmsg[EVT_VENDOR_CODE_MSB] << 8) | rxmsg[EVT_VENDOR_CODE_LSB];
+}
+
+static void bt_spi_isr(const struct device *unused1,
+		       struct gpio_callback *unused2,
+		       uint32_t unused3)
+{
+	BT_DBG("");
+
+	k_sem_give(&sem_request);
+}
+
+static void bt_spi_handle_vendor_evt(uint8_t *rxmsg)
+{
+	switch (bt_spi_get_evt(rxmsg)) {
+	case EVT_BLUE_INITIALIZED:
+		k_sem_give(&sem_initialised);
+#if defined(CONFIG_BT_BLUENRG_ACI)
+		/* force BlueNRG to be on controller mode */
+		bt_spi_send_aci_config_data_controller_mode();
+#endif
+	default:
+		break;
+	}
+}
+
+#if defined(CONFIG_BT_SPI_BLUENRG)
+/* BlueNRG has a particuliar way to wake up from sleep and be ready.
+ * All is done through its CS line:
+ * If it is in sleep mode, the first transaction will not return ready
+ * status. At this point, it's necessary to release the CS and retry
+ * within 2ms the same transaction. And again when it's required to
+ * know the amount of byte to read.
+ * (See section 5.2 of BlueNRG-MS datasheet)
+ */
+static int configure_cs(void)
+{
+	cs_dev = device_get_binding(DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
+	if (!cs_dev) {
+		BT_ERR("Failed to initialize GPIO driver: %s",
+		       DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
+		return -EIO;
+	}
+
+	/* Configure pin as output and set to active */
+	gpio_pin_configure(cs_dev, GPIO_CS_PIN,
+			   GPIO_OUTPUT_ACTIVE | GPIO_CS_FLAGS);
+
+
+	return 0;
+}
+
+static void kick_cs(void)
+{
+	gpio_pin_set(cs_dev, GPIO_CS_PIN, 1);
+	gpio_pin_set(cs_dev, GPIO_CS_PIN, 0);
+}
+
+static void release_cs(void)
+{
+	gpio_pin_set(cs_dev, GPIO_CS_PIN, 1);
+}
+
+static bool irq_pin_high(void)
+{
+	int pin_state;
+
+	pin_state = gpio_pin_get(irq_dev, GPIO_IRQ_PIN);
+
+	BT_DBG("IRQ Pin: %d", pin_state);
+
+	return pin_state > 0;
+}
+
+static void init_irq_high_loop(void)
+{
+	attempts = IRQ_HIGH_MAX_READ;
+}
+
+static bool exit_irq_high_loop(void)
+{
+	/* Limit attempts on BlueNRG-MS as we might */
+	/* enter this loop with nothing to read */
+
+	attempts--;
+
+	return attempts;
+}
+
+#else
+
+static int configure_cs(void)
+{
+#ifdef GPIO_CS_PIN
+	static struct spi_cs_control spi_conf_cs;
+
+	spi_conf_cs.gpio_pin = GPIO_CS_PIN;
+	spi_conf_cs.gpio_dt_flags = GPIO_CS_FLAGS;
+	spi_conf_cs.gpio_dev = device_get_binding(
+		DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
+	if (!spi_conf_cs.gpio_dev) {
+		BT_ERR("Failed to initialize GPIO driver: %s",
+		       DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
+		return -EIO;
+	}
+
+	spi_conf.cs = &spi_conf_cs;
+#endif /* GPIO_CS_PIN */
+
+	return 0;
+}
+#define kick_cs(...)
+#define release_cs(...)
+#define irq_pin_high(...) 0
+#define init_irq_high_loop(...)
+#define exit_irq_high_loop(...) 1
+
+#endif /* CONFIG_BT_SPI_BLUENRG */
+
+#if defined(CONFIG_BT_BLUENRG_ACI)
+static int bt_spi_send_aci_config_data_controller_mode(void)
+{
+	struct bluenrg_aci_cmd_ll_param *param;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BLUENRG_ACI_WRITE_CONFIG_DATA, sizeof(*param));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	param = net_buf_add(buf, sizeof(*param));
+	param->cmd = BLUENRG_ACI_WRITE_CONFIG_CMD_LL;
+	param->length = 0x1;
+	/* Force BlueNRG-MS roles to Link Layer only mode */
+	param->value = BLUENRG_ACI_LL_MODE;
+
+	bt_hci_cmd_send(BLUENRG_ACI_WRITE_CONFIG_DATA, buf);
+
+	return 0;
+}
+#endif /* CONFIG_BT_BLUENRG_ACI */
+
+static void bt_spi_rx_thread(void)
+{
+	struct net_buf *buf;
+	uint8_t header_master[5] = { SPI_READ, 0x00, 0x00, 0x00, 0x00 };
+	uint8_t header_slave[5];
+	struct bt_hci_acl_hdr acl_hdr;
+	uint8_t size = 0U;
+	int ret;
+
+	(void)memset(&txmsg, 0xFF, SPI_MAX_MSG_LEN);
+
+	while (true) {
+		k_sem_take(&sem_request, K_FOREVER);
+		/* Disable IRQ pin callback to avoid spurious IRQs */
+
+		gpio_pin_interrupt_configure(irq_dev, GPIO_IRQ_PIN,
+					     GPIO_INT_DISABLE);
+		k_sem_take(&sem_busy, K_FOREVER);
+
+		BT_DBG("");
+
+		do {
+			init_irq_high_loop();
+			do {
+				kick_cs();
+				ret = bt_spi_transceive(header_master, 5,
+							header_slave, 5);
+			} while ((((header_slave[STATUS_HEADER_TOREAD] == 0U ||
+				    header_slave[STATUS_HEADER_TOREAD] == 0xFF) &&
+				   !ret)) && exit_irq_high_loop());
+
+			size = header_slave[STATUS_HEADER_TOREAD];
+			if (!ret || size != 0) {
+				do {
+					ret = bt_spi_transceive(&txmsg, size,
+								&rxmsg, size);
+				} while (rxmsg[0] == 0U && ret == 0);
+			}
+
+			release_cs();
+			gpio_pin_interrupt_configure(irq_dev, GPIO_IRQ_PIN,
+						     GPIO_INT_EDGE_TO_ACTIVE);
+
+			k_sem_give(&sem_busy);
+
+			if (ret || size == 0) {
+				if (ret) {
+					BT_ERR("Error %d", ret);
+				}
+				continue;
+			}
+
+			spi_dump_message("RX:ed", rxmsg, size);
+
+			switch (rxmsg[PACKET_TYPE]) {
+			case HCI_EVT:
+				switch (rxmsg[EVT_HEADER_EVENT]) {
+				case BT_HCI_EVT_VENDOR:
+					/* Vendor events are currently unsupported */
+					bt_spi_handle_vendor_evt(rxmsg);
+					continue;
+				default:
+					buf = bt_buf_get_evt(rxmsg[EVT_HEADER_EVENT],
+							     false, K_FOREVER);
+					break;
+				}
+
+				net_buf_add_mem(buf, &rxmsg[1],
+						rxmsg[EVT_HEADER_SIZE] + 2);
+				break;
+			case HCI_ACL:
+				buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
+				memcpy(&acl_hdr, &rxmsg[1], sizeof(acl_hdr));
+				net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr));
+				net_buf_add_mem(buf, &rxmsg[5],
+						sys_le16_to_cpu(acl_hdr.len));
+				break;
+			default:
+				BT_ERR("Unknown BT buf type %d", rxmsg[0]);
+				continue;
+			}
+
+			bt_recv(buf);
+
+		/* On BlueNRG-MS, host is expected to read */
+		/* as long as IRQ pin is high */
+		} while (irq_pin_high());
+	}
+}
+
+static int bt_spi_send(struct net_buf *buf)
+{
+	uint8_t header[5] = { SPI_WRITE, 0x00,  0x00,  0x00,  0x00 };
+	int pending;
+	int ret;
+
+	BT_DBG("");
+
+	/* Buffer needs an additional byte for type */
+	if (buf->len >= SPI_MAX_MSG_LEN) {
+		BT_ERR("Message too long");
+		return -EINVAL;
+	}
+
+	/* Allow time for the read thread to handle interrupt */
+	while (true) {
+		pending = gpio_pin_get(irq_dev, GPIO_IRQ_PIN);
+		if (pending <= 0) {
+			break;
+		}
+		k_sleep(K_MSEC(1));
+	}
+
+	k_sem_take(&sem_busy, K_FOREVER);
+
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_ACL_OUT:
+		net_buf_push_u8(buf, HCI_ACL);
+		break;
+	case BT_BUF_CMD:
+		net_buf_push_u8(buf, HCI_CMD);
+		break;
+	default:
+		BT_ERR("Unsupported type");
+		k_sem_give(&sem_busy);
+		return -EINVAL;
+	}
+
+	/* Poll sanity values until device has woken-up */
+	do {
+		kick_cs();
+		ret = bt_spi_transceive(header, 5, rxmsg, 5);
+
+		/*
+		 * RX Header (rxmsg) must contain a sanity check Byte and size
+		 * information.  If it does not contain BOTH then it is
+		 * sleeping or still in the initialisation stage (waking-up).
+		 */
+	} while ((rxmsg[STATUS_HEADER_READY] != READY_NOW ||
+		  (rxmsg[1] | rxmsg[2] | rxmsg[3] | rxmsg[4]) == 0U) && !ret);
+
+
+	k_sem_give(&sem_busy);
+
+	if (!ret) {
+		/* Transmit the message */
+		do {
+			ret = bt_spi_transceive(buf->data, buf->len,
+						rxmsg, buf->len);
+		} while (rxmsg[0] == 0U && !ret);
+	}
+
+	release_cs();
+
+	if (ret) {
+		BT_ERR("Error %d", ret);
+		goto out;
+	}
+
+	spi_dump_message("TX:ed", buf->data, buf->len);
+
+#if defined(CONFIG_BT_SPI_BLUENRG)
+	/*
+	 * Since a RESET has been requested, the chip will now restart.
+	 * Unfortunately the BlueNRG will reply with "reset received" but
+	 * since it does not send back a NOP, we have no way to tell when the
+	 * RESET has actually taken place.  Instead, we use the vendor command
+	 * EVT_BLUE_INITIALIZED as an indication that it is safe to proceed.
+	 */
+	if (bt_spi_get_cmd(buf->data) == BT_HCI_OP_RESET) {
+		k_sem_take(&sem_initialised, K_FOREVER);
+	}
+#endif /* CONFIG_BT_SPI_BLUENRG */
+out:
+	net_buf_unref(buf);
+
+	return ret;
+}
+
+static int bt_spi_open(void)
+{
+	/* Configure RST pin and hold BLE in Reset */
+	gpio_pin_configure(rst_dev, GPIO_RESET_PIN,
+			   GPIO_OUTPUT_ACTIVE | GPIO_RESET_FLAGS);
+
+	/* Configure IRQ pin and the IRQ call-back/handler */
+	gpio_pin_configure(irq_dev, GPIO_IRQ_PIN,
+			   GPIO_INPUT | GPIO_IRQ_FLAGS);
+
+	gpio_init_callback(&gpio_cb, bt_spi_isr, BIT(GPIO_IRQ_PIN));
+
+	if (gpio_add_callback(irq_dev, &gpio_cb)) {
+		return -EINVAL;
+	}
+
+	gpio_pin_interrupt_configure(irq_dev, GPIO_IRQ_PIN,
+				     GPIO_INT_EDGE_TO_ACTIVE);
+
+	/* Start RX thread */
+	k_thread_create(&spi_rx_thread_data, spi_rx_stack,
+			K_KERNEL_STACK_SIZEOF(spi_rx_stack),
+			(k_thread_entry_t)bt_spi_rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
+			0, K_NO_WAIT);
+
+	/* Take BLE out of reset */
+	gpio_pin_set(rst_dev, GPIO_RESET_PIN, 0);
+
+	/* Device will let us know when it's ready */
+	k_sem_take(&sem_initialised, K_FOREVER);
+
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= DT_INST_LABEL(0),
+	.bus		= BT_HCI_DRIVER_BUS_SPI,
+#if defined(CONFIG_BT_BLUENRG_ACI)
+	.quirks		= BT_QUIRK_NO_RESET,
+#endif /* CONFIG_BT_BLUENRG_ACI */
+	.open		= bt_spi_open,
+	.send		= bt_spi_send,
+};
+
+static int bt_spi_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	spi_dev = device_get_binding(DT_INST_BUS_LABEL(0));
+	if (!spi_dev) {
+		BT_ERR("Failed to initialize SPI driver: %s",
+		       DT_INST_BUS_LABEL(0));
+		return -EIO;
+	}
+
+	if (configure_cs()) {
+		return -EIO;
+	}
+
+	irq_dev = device_get_binding(
+		DT_INST_GPIO_LABEL(0, irq_gpios));
+	if (!irq_dev) {
+		BT_ERR("Failed to initialize GPIO driver: %s",
+		       DT_INST_GPIO_LABEL(0, irq_gpios));
+		return -EIO;
+	}
+
+	rst_dev = device_get_binding(
+		DT_INST_GPIO_LABEL(0, reset_gpios));
+	if (!rst_dev) {
+		BT_ERR("Failed to initialize GPIO driver: %s",
+		       DT_INST_GPIO_LABEL(0, reset_gpios));
+		return -EIO;
+	}
+
+	bt_hci_driver_register(&drv);
+
+
+	BT_DBG("BT SPI initialized");
+
+	return 0;
+}
+
+SYS_INIT(bt_spi_init, POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/userchan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/userchan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/hci/userchan.c	(working copy)
@@ -0,0 +1,276 @@
+/* userchan.c - HCI User Channel based Bluetooth driver */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <device.h>
+#include <init.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "soc.h"
+#include "cmdline.h" /* native_posix command line options header */
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_driver
+#include "common/log.h"
+
+#define BTPROTO_HCI      1
+struct sockaddr_hci {
+	sa_family_t     hci_family;
+	unsigned short  hci_dev;
+	unsigned short  hci_channel;
+};
+#define HCI_CHANNEL_USER 1
+
+#define SOL_HCI          0
+
+#define H4_CMD           0x01
+#define H4_ACL           0x02
+#define H4_SCO           0x03
+#define H4_EVT           0x04
+#define H4_ISO           0x05
+
+static K_KERNEL_STACK_DEFINE(rx_thread_stack,
+			     CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
+static struct k_thread rx_thread_data;
+
+static int uc_fd = -1;
+
+static int bt_dev_index = -1;
+
+static struct net_buf *get_rx(const uint8_t *buf)
+{
+	switch (buf[0]) {
+	case H4_EVT:
+		return bt_buf_get_evt(buf[1], false, K_FOREVER);
+	case H4_ACL:
+		return bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
+	case H4_ISO:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			return bt_buf_get_rx(BT_BUF_ISO_IN, K_FOREVER);
+		}
+		__fallthrough;
+	default:
+		BT_ERR("Unknown packet type: %u", buf[0]);
+	}
+
+	return NULL;
+}
+
+static bool uc_ready(void)
+{
+	struct pollfd pollfd = { .fd = uc_fd, .events = POLLIN };
+
+	return (poll(&pollfd, 1, 0) == 1);
+}
+
+static void rx_thread(void *p1, void *p2, void *p3)
+{
+	ARG_UNUSED(p1);
+	ARG_UNUSED(p2);
+	ARG_UNUSED(p3);
+
+	BT_DBG("started");
+
+	while (1) {
+		static uint8_t frame[512];
+		struct net_buf *buf;
+		ssize_t len;
+
+		if (!uc_ready()) {
+			k_sleep(K_MSEC(20));
+			continue;
+		}
+
+		BT_DBG("calling read()");
+
+		len = read(uc_fd, frame, sizeof(frame));
+		if (len < 0) {
+			if (errno == EINTR) {
+				k_yield();
+				continue;
+			}
+
+			BT_ERR("Reading socket failed, errno %d", errno);
+			close(uc_fd);
+			uc_fd = -1;
+			return;
+		}
+
+		buf = get_rx(frame);
+		net_buf_add_mem(buf, &frame[1], len - 1);
+
+		BT_DBG("Calling bt_recv(%p)", buf);
+
+		bt_recv(buf);
+
+		k_yield();
+	}
+}
+
+static int uc_send(struct net_buf *buf)
+{
+	BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
+
+	if (uc_fd < 0) {
+		BT_ERR("User channel not open");
+		return -EIO;
+	}
+
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_ACL_OUT:
+		net_buf_push_u8(buf, H4_ACL);
+		break;
+	case BT_BUF_CMD:
+		net_buf_push_u8(buf, H4_CMD);
+		break;
+	case BT_BUF_ISO_OUT:
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			net_buf_push_u8(buf, H4_ISO);
+			break;
+		}
+		__fallthrough;
+	default:
+		BT_ERR("Unknown buffer type");
+		return -EINVAL;
+	}
+
+	if (write(uc_fd, buf->data, buf->len) < 0) {
+		return -errno;
+	}
+
+	net_buf_unref(buf);
+	return 0;
+}
+
+static int user_chan_open(uint16_t index)
+{
+	struct sockaddr_hci addr;
+	int fd;
+
+	fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
+		    BTPROTO_HCI);
+	if (fd < 0) {
+		return -errno;
+	}
+
+	(void)memset(&addr, 0, sizeof(addr));
+	addr.hci_family = AF_BLUETOOTH;
+	addr.hci_dev = index;
+	addr.hci_channel = HCI_CHANNEL_USER;
+
+	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+		int err = -errno;
+
+		close(fd);
+		return err;
+	}
+
+	return fd;
+}
+
+static int uc_open(void)
+{
+	if (bt_dev_index < 0) {
+		BT_ERR("No Bluetooth device specified");
+		return -ENODEV;
+	}
+
+	BT_DBG("hci%d", bt_dev_index);
+
+	uc_fd = user_chan_open(bt_dev_index);
+	if (uc_fd < 0) {
+		return uc_fd;
+	}
+
+	BT_DBG("User Channel opened as fd %d", uc_fd);
+
+	k_thread_create(&rx_thread_data, rx_thread_stack,
+			K_KERNEL_STACK_SIZEOF(rx_thread_stack),
+			rx_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
+			0, K_NO_WAIT);
+
+	BT_DBG("returning");
+
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name		= "HCI User Channel",
+	.bus		= BT_HCI_DRIVER_BUS_UART,
+	.open		= uc_open,
+	.send		= uc_send,
+};
+
+static int bt_uc_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	bt_hci_driver_register(&drv);
+
+	return 0;
+}
+
+SYS_INIT(bt_uc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
+
+static void cmd_bt_dev_found(char *argv, int offset)
+{
+	if (strncmp(&argv[offset], "hci", 3) || strlen(&argv[offset]) < 4) {
+		posix_print_error_and_exit("Error: Invalid Bluetooth device "
+					   "name '%s' (should be e.g. hci0)\n",
+					   &argv[offset]);
+		return;
+	}
+
+	bt_dev_index = strtol(&argv[offset + 3], NULL, 10);
+}
+
+static void add_btuserchan_arg(void)
+{
+	static struct args_struct_t btuserchan_args[] = {
+		/*
+		 * Fields:
+		 * manual, mandatory, switch,
+		 * option_name, var_name ,type,
+		 * destination, callback,
+		 * description
+		 */
+		{ false, true, false,
+		"bt-dev", "hciX", 's',
+		NULL, cmd_bt_dev_found,
+		"A local HCI device to be used for Bluetooth (e.g. hci0)" },
+		ARG_TABLE_ENDMARKER
+	};
+
+	native_add_command_line_opts(btuserchan_args);
+}
+
+static void btuserchan_check_arg(void)
+{
+	if (bt_dev_index < 0) {
+		posix_print_error_and_exit("Error: Bluetooth device missing. "
+					   "Specify one using --bt-dev=hciN\n");
+	}
+}
+
+NATIVE_TASK(add_btuserchan_arg, PRE_BOOT_1, 10);
+NATIVE_TASK(btuserchan_check_arg, PRE_BOOT_2, 10);
Index: ModuleDemo/BLE/CM0/User/drivers/bluetooth/util.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/util.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/drivers/bluetooth/util.h	(working copy)
@@ -0,0 +1,8 @@
+/* util.h - Common helpers for Bluetooth drivers */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
Index: ModuleDemo/BLE/CM0/User/hci/yc11xx_addr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_addr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_addr.h	(working copy)
@@ -0,0 +1,108 @@
+/** @file
+ *  @brief Bluetooth device address definitions and utilities.
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _YC11XX_ADDR_H_
+#define _YC11XX_ADDR_H_
+
+#include <stdbool.h>
+#include <string.h>
+#include "type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Bluetooth device address definitions and utilities.
+ * @defgroup bt_addr Device Address
+ * @ingroup bluetooth
+ * @{
+ */
+
+#define BT_ADDR_LE_PUBLIC       0x00
+#define BT_ADDR_LE_RANDOM       0x01
+#define BT_ADDR_LE_PUBLIC_ID    0x02
+#define BT_ADDR_LE_RANDOM_ID    0x03
+
+/** Bluetooth Device Address */
+typedef struct {
+	uint8_t  val[6];
+} bt_addr_t;
+
+/** Bluetooth LE Device Address */
+typedef struct {
+	uint8_t      type;
+	bt_addr_t a;
+} bt_addr_le_t;
+
+#define BT_ADDR_ANY     ((bt_addr_t[]) { { { 0, 0, 0, 0, 0, 0 } } })
+#define BT_ADDR_NONE    ((bt_addr_t[]) { { \
+			 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } })
+#define BT_ADDR_LE_ANY  ((bt_addr_le_t[]) { { 0, { { 0, 0, 0, 0, 0, 0 } } } })
+#define BT_ADDR_LE_NONE ((bt_addr_le_t[]) { { 0, \
+			 { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } })
+
+static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+
+static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+
+static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+#define BT_ADDR_IS_RPA(a)     (((a)->val[5] & 0xc0) == 0x40)
+#define BT_ADDR_IS_NRPA(a)    (((a)->val[5] & 0xc0) == 0x00)
+#define BT_ADDR_IS_STATIC(a)  (((a)->val[5] & 0xc0) == 0xc0)
+
+#define BT_ADDR_SET_RPA(a)    ((a)->val[5] = (((a)->val[5] & 0x3f) | 0x40))
+#define BT_ADDR_SET_NRPA(a)   ((a)->val[5] &= 0x3f)
+#define BT_ADDR_SET_STATIC(a) ((a)->val[5] |= 0xc0)
+
+int bt_addr_le_create_nrpa(bt_addr_le_t *addr);
+int bt_addr_le_create_static(bt_addr_le_t *addr);
+
+static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr)
+{
+	if (addr->type != BT_ADDR_LE_RANDOM) {
+		return false;
+	}
+
+	return BT_ADDR_IS_RPA(&addr->a);
+}
+
+static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr)
+{
+	if (addr->type == BT_ADDR_LE_PUBLIC) {
+		return true;
+	}
+
+	return BT_ADDR_IS_STATIC(&addr->a);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _YC11XX_ADDR_H_ */
Index: ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.h	(working copy)
@@ -0,0 +1,33 @@
+#ifndef DRIVERS_HCI_YC11XX_H4_H_
+#define DRIVERS_HCI_YC11XX_H4_H_
+
+#include "yc11xx_hci.h"
+#include "yc11xx_uart.h"
+#include "yc11xx_gpio.h"
+
+
+#define H4_NONE 0x00
+#define H4_CMD  0x01
+#define H4_ACL  0x02
+#define H4_SCO  0x03
+#define H4_EVT  0x04
+#define H4_ISO  0x05
+
+#define HCI_H4_UART (UARTA)
+#define H4_UART_RXIO  (GPIO_28)
+#define H4_UART_TXIO  (GPIO_27)  
+
+#define BT_DBG(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
+#define BT_ERR(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
+#define BT_WARN(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
+#define BT_INFO(fmt, ...) DEBUG_LOG_STRING(fmt, ##__VA_ARGS__)
+
+#define  MIN(a, b)      (((a) < (b)) ? (a) : (b))
+
+void h4_init(void);
+void h4_polling_rx(void);
+void h4_send_data(uint8_t* buf, uint16_t len);
+
+#endif //DRIVERS_HCI_YC11XX_H4_H_
+
+
Index: ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_h4.c	(working copy)
@@ -0,0 +1,336 @@
+/* h4.c - H:4 UART based Bluetooth driver */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//#include <errno.h>
+#include "yc11xx_gpio.h"
+#include "yc11xx.h"
+#include "yc_drv_common.h"
+#include <string.h>
+//#include "yc11xx_pwm.h"
+#include "yc_debug.h"
+#include "yc11xx_h4.h"
+#include "yc11xx_dev_bt.h"
+
+static struct {
+	uint8_t buf[600];
+	uint16_t buf_pos;
+
+	
+	uint16_t    remaining;
+	uint16_t    discard;
+
+	bool     have_hdr;
+	bool     discardable;
+
+	uint8_t     hdr_len;
+
+	uint8_t     type;
+	union {
+		struct bt_hci_cmd_hdr cmd;
+		struct bt_hci_evt_hdr evt;
+		struct bt_hci_acl_hdr acl;
+		struct bt_hci_iso_hdr iso;
+		uint8_t hdr[4];
+	};
+} rx;
+
+static struct {
+	uint8_t type;
+	uint8_t *buf;
+} tx;
+
+
+void h4_uart_init(uint16_t baudRate)
+{
+	USART_InitTypeDef USART_InitStruct ;
+
+	USART_InitStruct.USART_BaudRate             = baudRate;
+	USART_InitStruct.USART_HardwareFlowControl  = USART_HardwareFlowControl_None;
+	USART_InitStruct.USART_WordLength           = USART_WordLength_8b;	
+	USART_InitStruct.USART_StopBits             = USART_StopBits_1;
+	USART_InitStruct.USART_Mode                 = USART_Mode_duplex;
+	USART_InitStruct.USART_Parity               = USART_Parity_Even ;
+	USART_InitStruct.USART_TXLen                = 512;
+	USART_InitStruct.USART_RXLen                = 512;
+
+	if(UARTA == HCI_H4_UART){
+		GPIO_SetGpioMultFunction(H4_UART_TXIO,GPCFG_UART_TXD);
+		GPIO_SetGpioMultFunction(H4_UART_RXIO,GPCFG_UART_RXD|GPCFG_PULLUP);
+	}else if (UARTB == HCI_H4_UART){
+		GPIO_SetGpioMultFunction(H4_UART_TXIO,GPCFG_UARTB_TXD);
+		GPIO_SetGpioMultFunction(H4_UART_RXIO,GPCFG_UARTB_RXD|GPCFG_PULLUP);
+	}
+	USART_Init(HCI_H4_UART,&USART_InitStruct);
+}
+
+
+static size_t h4_discard(size_t len)
+{
+	uint8_t buf[33];
+	return USART_ReadDatatoBuff(HCI_H4_UART, buf, MIN(len, sizeof(buf)));
+}
+
+static size_t h4_read(uint8_t* rxBuff, size_t len)
+{
+	return USART_ReadDatatoBuff(HCI_H4_UART, rxBuff, len);
+}
+
+const char *bt_hex_real(const void *buf, size_t len)
+{
+	static const char hex[] = "0123456789abcdef";
+	static char str[129];
+	const uint8_t *b = buf;
+	size_t i;
+
+	len = MIN(len, (sizeof(str) - 1) / 2);
+
+	for (i = 0; i < len; i++) {
+		str[i * 2]     = hex[b[i] >> 4];
+		str[i * 2 + 1] = hex[b[i] & 0xf];
+	}
+
+	str[i * 2] = '\0';
+
+	return str;
+}
+
+static inline void h4_get_type(void)
+{
+	/* Get packet type */
+	if (h4_read(&rx.type, 1) != 1)
+	{
+		BT_WARN("Unable to read H:4 packet type\r\n");
+		rx.type = H4_NONE;
+		return;
+	}
+
+	switch (rx.type) {
+	case H4_CMD:
+		rx.remaining = sizeof(rx.cmd);
+		rx.hdr_len = rx.remaining;
+		break;
+	case H4_EVT:
+		rx.remaining = sizeof(rx.evt);
+		rx.hdr_len = rx.remaining;
+		break;
+	case H4_ACL:
+		rx.remaining = sizeof(rx.acl);
+		rx.hdr_len = rx.remaining;
+		break;
+	case H4_ISO:
+		rx.remaining = sizeof(rx.iso);
+		rx.hdr_len = rx.remaining;
+		break;
+	default:
+		BT_ERR("Unknown H:4 type 0x%02x\r\n", rx.type);
+		rx.type = H4_NONE;
+	}
+}
+
+static inline void get_acl_hdr(void)
+{
+	struct bt_hci_acl_hdr *hdr = &rx.acl;
+	int to_read = sizeof(*hdr) - rx.remaining;
+
+	rx.remaining -= h4_read((uint8_t *)hdr + to_read,
+				       rx.remaining);
+	if (!rx.remaining) {
+		rx.remaining = (hdr->len);
+		BT_DBG("Got ACL header. Payload %u bytes\r\n", rx.remaining);
+		rx.have_hdr = true;
+	}
+}
+
+static inline void get_cmd_hdr(void)
+{
+	struct bt_hci_cmd_hdr *hdr = &rx.cmd;
+	int to_read = rx.hdr_len - rx.remaining;
+
+	rx.remaining -= h4_read((uint8_t *)hdr + to_read,
+				       rx.remaining);
+
+	if (!rx.remaining) {
+		rx.remaining = hdr->param_len;
+		BT_DBG("Got cmd header. Payload %u bytes\r\n", hdr->param_len);
+		rx.have_hdr = true;
+	}
+}
+
+static inline uint8_t* get_rx_buf_read_pos(void)
+{
+	return rx.buf + rx.buf_pos;
+}
+static inline void increase_rx_buf_pos(uint16_t len)
+{
+	rx.buf_pos += len;
+}
+
+static inline void copy_hdr(void)
+{
+	// Save type.
+	*(uint8_t *)get_rx_buf_read_pos() = rx.type;
+	increase_rx_buf_pos(1);
+
+	// Save header
+	memcpy(get_rx_buf_read_pos(), rx.hdr, rx.hdr_len);
+	increase_rx_buf_pos(rx.hdr_len);
+}
+
+static void reset_rx(void)
+{
+	rx.type = H4_NONE;
+	rx.remaining = 0U;
+	rx.have_hdr = false;
+	rx.hdr_len = 0U;
+	rx.discardable = false;
+	rx.buf_pos= 0;
+}
+
+static inline void process_rx_packet(uint8_t type, uint8_t* buf, uint16_t len)
+{
+	//
+	BT_DBG("<--- process_rx_packet (type %u) (len %u): %s\r\n", type, len,
+	       bt_hex_real(buf, len));
+
+        DEBUG_LOG_PRINT_HCI_H4(0, buf, len);
+	Bt_SndHciToRespin(buf, len);
+}
+
+static inline void read_payload(void)
+{
+	uint8_t evt_flags;
+	int read;
+
+	if (rx.remaining) {
+		read = h4_read(get_rx_buf_read_pos(), rx.remaining);
+		increase_rx_buf_pos(read);
+		rx.remaining -= read;
+
+		BT_DBG("got %d bytes, remaining %u\r\n", read, rx.remaining);
+		BT_DBG("Payload (len %u): %s\r\n", rx.buf_pos,
+		       bt_hex_real(rx.buf, rx.buf_pos));
+
+		if (rx.remaining) {
+			return;
+		}
+	}
+
+	// receive a full packet
+	process_rx_packet(rx.type, rx.buf, rx.buf_pos);
+	
+	reset_rx();
+}
+
+static inline void read_header(void)
+{
+	switch (rx.type) {
+	case H4_NONE:
+		h4_get_type();
+		return;
+	case H4_CMD:
+		get_cmd_hdr();
+		break;
+	case H4_ACL:
+		get_acl_hdr();
+		break;
+	default:
+		BT_ERR("Something error\r\n");
+		return;
+	}
+
+	if (rx.have_hdr) {
+		if (rx.remaining > (sizeof(rx.buf) - rx.buf_pos)) {
+			BT_ERR("Not enough space in buffer\r\n");
+			rx.discard = rx.remaining;
+			reset_rx();
+		} else {
+			copy_hdr();
+
+			// Check receive full packet
+			if (!rx.remaining) {
+				// receive a full packet
+				process_rx_packet(rx.type, rx.buf, rx.buf_pos);
+				
+				reset_rx();
+			}
+
+		}
+	}
+}
+static inline void process_rx(void)
+{
+	if(USART_GetRxCount(HCI_H4_UART) == 0)
+	{
+		return;
+	}
+	BT_DBG("remaining %u discard %u have_hdr %u len %u\r\n",
+	       rx.remaining, rx.discard, rx.have_hdr,
+	       rx.buf_pos);
+
+	if (rx.discard) {
+		rx.discard -= h4_discard(rx.discard);
+		return;
+	}
+
+	if (rx.have_hdr) {
+		read_payload();
+	} else {
+		read_header();
+	}
+}
+
+
+static int h4_send(uint8_t* buf, uint16_t len)
+{
+	BT_DBG("---> h4_send Payload (len %u): %s\r\n", len,
+	       bt_hex_real(buf, len));
+
+	USART_SendDataFromBuff(HCI_H4_UART, buf, len);
+
+	return 0;
+}
+
+
+static int h4_open(void)
+{
+	int ret;
+
+	BT_DBG("h4_open");
+#ifdef FUNCTION_FSC_RTK_HOST
+	h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud115200);
+#else
+	h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud921600);
+#endif
+	
+	return 0;
+}
+
+
+void h4_init(void)
+{
+	h4_open();
+}
+void h4_polling_rx(void)
+{
+	process_rx();
+}
+void h4_send_data(uint8_t* buf, uint16_t len)
+{
+	h4_send(buf, len);
+        DEBUG_LOG_PRINT_HCI_H4(1, buf, len);
+        if(HREAD(mem_fsc_rtk_host) == 0x3f)
+        {
+#ifdef FUNCTION_FSC_RTK_HOST_WHITE
+            h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud512000);
+#else
+            h4_uart_init(UARTE_BAUDRATE_BAUDRATE_Baud1M);
+#endif
+            HWRITE(mem_fsc_rtk_host, 0);
+        }
+}
+
Index: ModuleDemo/BLE/CM0/User/hci/yc11xx_hci.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_hci.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_hci.h	(working copy)
@@ -0,0 +1,2235 @@
+/* hci.h - Bluetooth Host Control Interface definitions */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _YC11XX_HCI_H_
+#define _YC11XX_HCI_H_
+
+#include <stdbool.h>
+#include <string.h>
+#include "yc11xx_hci_err.h"
+#include "yc11xx_addr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __packed
+#define __packed        __attribute__((__packed__))
+#endif
+
+/**
+ * @brief Unsigned integer with bit position @p n set (signed in
+ * assembly language).
+ */
+#define BIT(n)  (1UL << (n))
+
+/**
+ * @brief Bit mask with bits 0 through <tt>n-1</tt> (inclusive) set,
+ * or 0 if @p n is 0.
+ */
+#define BIT_MASK(n) (BIT(n) - 1)
+
+/* Special own address types for LL privacy (used in adv & scan parameters) */
+#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC  0x02
+#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM  0x03
+#define BT_HCI_OWN_ADDR_RPA_MASK       0x02
+
+#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe
+#define BT_HCI_PEER_ADDR_ANONYMOUS      0xff
+
+#define BT_ENC_KEY_SIZE_MIN                     0x07
+#define BT_ENC_KEY_SIZE_MAX                     0x10
+
+
+
+
+
+
+
+/* Special own address types for LL privacy (used in adv & scan parameters) */
+#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC  0x02
+#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM  0x03
+#define BT_HCI_OWN_ADDR_RPA_MASK       0x02
+
+#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe
+#define BT_HCI_PEER_ADDR_ANONYMOUS      0xff
+
+#define BT_ENC_KEY_SIZE_MIN                     0x07
+#define BT_ENC_KEY_SIZE_MAX                     0x10
+
+struct bt_hci_evt_hdr {
+	uint8_t  evt;
+	uint8_t  len;
+} __packed;
+#define BT_HCI_EVT_HDR_SIZE             2
+
+#define BT_ACL_START_NO_FLUSH           0x00
+#define BT_ACL_CONT                     0x01
+#define BT_ACL_START                    0x02
+#define BT_ACL_COMPLETE                 0x03
+
+#define BT_ACL_POINT_TO_POINT           0x00
+#define BT_ACL_BROADCAST                0x01
+
+#define bt_acl_handle(h)                ((h) & BIT_MASK(12))
+#define bt_acl_flags(h)                 ((h) >> 12)
+#define bt_acl_flags_pb(f)              ((f) & BIT_MASK(2))
+#define bt_acl_flags_bc(f)              ((f) >> 2)
+#define bt_acl_handle_pack(h, f)        ((h) | ((f) << 12))
+
+struct bt_hci_acl_hdr {
+	uint16_t handle;
+	uint16_t len;
+} __packed;
+#define BT_HCI_ACL_HDR_SIZE             4
+
+#define BT_ISO_START                    0x00
+#define BT_ISO_CONT                     0x01
+#define BT_ISO_SINGLE                   0x02
+#define BT_ISO_END                      0x03
+
+#define bt_iso_handle(h)                ((h) & 0x0fff)
+#define bt_iso_flags(h)                 ((h) >> 12)
+#define bt_iso_flags_pb(f)              ((f) & 0x0003)
+#define bt_iso_flags_ts(f)              (((f) >> 2) & 0x0001)
+#define bt_iso_pack_flags(pb, ts) \
+	(((pb) & 0x0003) | (((ts) & 0x0001) << 2))
+#define bt_iso_handle_pack(h, pb, ts) \
+	((h) | (bt_iso_pack_flags(pb, ts) << 12))
+
+#define BT_ISO_DATA_VALID                0x00
+#define BT_ISO_DATA_INVALID              0x01
+#define BT_ISO_DATA_NOP                  0x02
+
+#define bt_iso_pkt_len(h)                ((h) & 0x3fff)
+#define bt_iso_pkt_flags(h)              ((h) >> 14)
+#define bt_iso_pkt_len_pack(h, f)        ((h) | ((f) << 14))
+
+struct bt_hci_iso_data_hdr {
+	uint16_t sn;
+	uint16_t slen;
+} __packed;
+#define BT_HCI_ISO_DATA_HDR_SIZE	4
+
+struct bt_hci_iso_ts_data_hdr {
+	uint32_t ts;
+	struct bt_hci_iso_data_hdr data;
+} __packed;
+#define BT_HCI_ISO_TS_DATA_HDR_SIZE     8
+
+struct bt_hci_iso_hdr {
+	uint16_t handle;
+	uint16_t len;
+} __packed;
+#define BT_HCI_ISO_HDR_SIZE             4
+
+struct bt_hci_cmd_hdr {
+	uint16_t opcode;
+	uint8_t  param_len;
+} __packed;
+#define BT_HCI_CMD_HDR_SIZE             3
+
+/* Supported Commands */
+#define BT_CMD_TEST(cmd, octet, bit)            (cmd[octet] & BIT(bit))
+#define BT_CMD_LE_STATES(cmd)                   BT_CMD_TEST(cmd, 28, 3)
+
+#define BT_FEAT_TEST(feat, page, octet, bit)    (feat[page][octet] & BIT(bit))
+
+#define BT_FEAT_BREDR(feat)                     !BT_FEAT_TEST(feat, 0, 4, 5)
+#define BT_FEAT_LE(feat)                        BT_FEAT_TEST(feat, 0, 4, 6)
+#define BT_FEAT_EXT_FEATURES(feat)              BT_FEAT_TEST(feat, 0, 7, 7)
+#define BT_FEAT_HOST_SSP(feat)                  BT_FEAT_TEST(feat, 1, 0, 0)
+#define BT_FEAT_SC(feat)                        BT_FEAT_TEST(feat, 2, 1, 0)
+
+#define BT_FEAT_LMP_ESCO_CAPABLE(feat)          BT_FEAT_TEST(feat, 0, 3, 7)
+#define BT_FEAT_HV2_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 4)
+#define BT_FEAT_HV3_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 5)
+#define BT_FEAT_EV4_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 0)
+#define BT_FEAT_EV5_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 1)
+#define BT_FEAT_2EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 5)
+#define BT_FEAT_3EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 6)
+#define BT_FEAT_3SLOT_PKT(feat)                 BT_FEAT_TEST(feat, 0, 5, 7)
+
+/* LE features */
+#define BT_LE_FEAT_BIT_ENC                      0
+#define BT_LE_FEAT_BIT_CONN_PARAM_REQ           1
+#define BT_LE_FEAT_BIT_EXT_REJ_IND              2
+#define BT_LE_FEAT_BIT_SLAVE_FEAT_REQ           3
+#define BT_LE_FEAT_BIT_PING                     4
+#define BT_LE_FEAT_BIT_DLE                      5
+#define BT_LE_FEAT_BIT_PRIVACY                  6
+#define BT_LE_FEAT_BIT_EXT_SCAN                 7
+#define BT_LE_FEAT_BIT_PHY_2M                   8
+#define BT_LE_FEAT_BIT_SMI_TX                   9
+#define BT_LE_FEAT_BIT_SMI_RX                   10
+#define BT_LE_FEAT_BIT_PHY_CODED                11
+#define BT_LE_FEAT_BIT_EXT_ADV                  12
+#define BT_LE_FEAT_BIT_PER_ADV                  13
+#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2          14
+#define BT_LE_FEAT_BIT_PWR_CLASS_1              15
+#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC       16
+#define BT_LE_FEAT_BIT_CONN_CTE_REQ             17
+#define BT_LE_FEAT_BIT_CONN_CTE_RESP            18
+#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX    19
+#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX    20
+#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD        21
+#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA        22
+#define BT_LE_FEAT_BIT_RX_CTE                   23
+#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_SEND  24
+#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_RECV  25
+#define BT_LE_FEAT_BIT_SCA_UPDATE               26
+#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE  27
+#define BT_LE_FEAT_BIT_CIS_MASTER               28
+#define BT_LE_FEAT_BIT_CIS_SLAVE                29
+#define BT_LE_FEAT_BIT_ISO_BROADCASTER          30
+#define BT_LE_FEAT_BIT_SYNC_RECEIVER            31
+#define BT_LE_FEAT_BIT_ISO_CHANNELS             32
+#define BT_LE_FEAT_BIT_PWR_CTRL_REQ             33
+#define BT_LE_FEAT_BIT_PWR_CHG_IND              34
+#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR        35
+
+#define BT_LE_FEAT_TEST(feat, n)                (feat[(n) >> 3] & \
+						 BIT((n) & 7))
+
+#define BT_FEAT_LE_ENCR(feat)                   BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ENC)
+#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat)    BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CONN_PARAM_REQ)
+#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat)     BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_SLAVE_FEAT_REQ)
+#define BT_FEAT_LE_DLE(feat)                    BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_DLE)
+#define BT_FEAT_LE_PHY_2M(feat)                 BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PHY_2M)
+#define BT_FEAT_LE_PHY_CODED(feat)              BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PHY_CODED)
+#define BT_FEAT_LE_PRIVACY(feat)                BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PRIVACY)
+#define BT_FEAT_LE_EXT_ADV(feat)                BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_EXT_ADV)
+#define BT_FEAT_LE_EXT_PER_ADV(feat)            BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PER_ADV)
+#define BT_FEAT_LE_CIS_MASTER(feat)             BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CIS_MASTER)
+#define BT_FEAT_LE_CIS_SLAVE(feat)              BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CIS_SLAVE)
+#define BT_FEAT_LE_ISO_BROADCASTER(feat)        BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ISO_BROADCASTER)
+#define BT_FEAT_LE_SYNC_RECEIVER(feat)          BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_SYNC_RECEIVER)
+#define BT_FEAT_LE_ISO_CHANNELS(feat)           BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ISO_CHANNELS)
+
+#define BT_FEAT_LE_CIS(feat)            (BT_FEAT_LE_CIS_MASTER(feat) | \
+					BT_FEAT_LE_CIS_SLAVE(feat))
+#define BT_FEAT_LE_BIS(feat)            (BT_FEAT_LE_ISO_BROADCASTER(feat) | \
+					BT_FEAT_LE_SYNC_RECEIVER(feat))
+#define BT_FEAT_LE_ISO(feat)            (BT_FEAT_LE_CIS(feat) | \
+					BT_FEAT_LE_BIS(feat))
+
+/* LE States */
+#define BT_LE_STATES_SLAVE_CONN_ADV(states)     (states & 0x0000004000000000)
+
+/* Bonding/authentication types */
+#define BT_HCI_NO_BONDING                       0x00
+#define BT_HCI_NO_BONDING_MITM                  0x01
+#define BT_HCI_DEDICATED_BONDING                0x02
+#define BT_HCI_DEDICATED_BONDING_MITM           0x03
+#define BT_HCI_GENERAL_BONDING                  0x04
+#define BT_HCI_GENERAL_BONDING_MITM             0x05
+
+/*
+ * MITM protection is enabled in SSP authentication requirements octet when
+ * LSB bit is set.
+ */
+#define BT_MITM                                 0x01
+
+/* I/O capabilities */
+#define BT_IO_DISPLAY_ONLY                      0x00
+#define BT_IO_DISPLAY_YESNO                     0x01
+#define BT_IO_KEYBOARD_ONLY                     0x02
+#define BT_IO_NO_INPUT_OUTPUT                   0x03
+
+/* SCO packet types */
+#define HCI_PKT_TYPE_HV1                        0x0020
+#define HCI_PKT_TYPE_HV2                        0x0040
+#define HCI_PKT_TYPE_HV3                        0x0080
+
+/* eSCO packet types */
+#define HCI_PKT_TYPE_ESCO_HV1                   0x0001
+#define HCI_PKT_TYPE_ESCO_HV2                   0x0002
+#define HCI_PKT_TYPE_ESCO_HV3                   0x0004
+#define HCI_PKT_TYPE_ESCO_EV3                   0x0008
+#define HCI_PKT_TYPE_ESCO_EV4                   0x0010
+#define HCI_PKT_TYPE_ESCO_EV5                   0x0020
+#define HCI_PKT_TYPE_ESCO_2EV3                  0x0040
+#define HCI_PKT_TYPE_ESCO_3EV3                  0x0080
+#define HCI_PKT_TYPE_ESCO_2EV5                  0x0100
+#define HCI_PKT_TYPE_ESCO_3EV5                  0x0200
+
+
+#define ESCO_PKT_MASK                           (HCI_PKT_TYPE_ESCO_HV1 | \
+						 HCI_PKT_TYPE_ESCO_HV2 | \
+						 HCI_PKT_TYPE_ESCO_HV3)
+#define SCO_PKT_MASK                            (HCI_PKT_TYPE_HV1 | \
+						 HCI_PKT_TYPE_HV2 | \
+						 HCI_PKT_TYPE_HV3)
+#define EDR_ESCO_PKT_MASK                       (HCI_PKT_TYPE_ESCO_2EV3 | \
+						 HCI_PKT_TYPE_ESCO_3EV3 | \
+						 HCI_PKT_TYPE_ESCO_2EV5 | \
+						 HCI_PKT_TYPE_ESCO_3EV5)
+
+/* HCI BR/EDR link types */
+#define BT_HCI_SCO                              0x00
+#define BT_HCI_ACL                              0x01
+#define BT_HCI_ESCO                             0x02
+
+/* OpCode Group Fields */
+#define BT_OGF_LINK_CTRL                        0x01
+#define BT_OGF_BASEBAND                         0x03
+#define BT_OGF_INFO                             0x04
+#define BT_OGF_STATUS                           0x05
+#define BT_OGF_LE                               0x08
+#define BT_OGF_VS                               0x3f
+
+/* Construct OpCode from OGF and OCF */
+#define BT_OP(ogf, ocf)                         ((ocf) | ((ogf) << 10))
+
+/* Invalid opcode */
+#define BT_OP_NOP				0x0000
+
+/* Obtain OGF from OpCode */
+#define BT_OGF(opcode)                          (((opcode) >> 10) & BIT_MASK(6))
+/* Obtain OCF from OpCode */
+#define BT_OCF(opcode)                          ((opcode) & BIT_MASK(10))
+
+#define BT_HCI_OP_INQUIRY                       BT_OP(BT_OGF_LINK_CTRL, 0x0001)
+struct bt_hci_op_inquiry {
+	uint8_t lap[3];
+	uint8_t length;
+	uint8_t num_rsp;
+} __packed;
+
+#define BT_HCI_OP_INQUIRY_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0002)
+
+#define BT_HCI_OP_CONNECT                       BT_OP(BT_OGF_LINK_CTRL, 0x0005)
+struct bt_hci_cp_connect {
+	bt_addr_t bdaddr;
+	uint16_t  packet_type;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint16_t  clock_offset;
+	uint8_t   allow_role_switch;
+} __packed;
+
+#define BT_HCI_OP_DISCONNECT                    BT_OP(BT_OGF_LINK_CTRL, 0x0006)
+struct bt_hci_cp_disconnect {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_OP_CONNECT_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0008)
+struct bt_hci_cp_connect_cancel {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_connect_cancel {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_ACCEPT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x0009)
+struct bt_hci_cp_accept_conn_req {
+	bt_addr_t bdaddr;
+	uint8_t   role;
+} __packed;
+
+#define BT_HCI_OP_SETUP_SYNC_CONN               BT_OP(BT_OGF_LINK_CTRL, 0x0028)
+struct bt_hci_cp_setup_sync_conn {
+	uint16_t  handle;
+	uint32_t  tx_bandwidth;
+	uint32_t  rx_bandwidth;
+	uint16_t  max_latency;
+	uint16_t  content_format;
+	uint8_t   retrans_effort;
+	uint16_t  pkt_type;
+} __packed;
+
+#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ          BT_OP(BT_OGF_LINK_CTRL, 0x0029)
+struct bt_hci_cp_accept_sync_conn_req {
+	bt_addr_t bdaddr;
+	uint32_t  tx_bandwidth;
+	uint32_t  rx_bandwidth;
+	uint16_t  max_latency;
+	uint16_t  content_format;
+	uint8_t   retrans_effort;
+	uint16_t  pkt_type;
+} __packed;
+
+#define BT_HCI_OP_REJECT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x000a)
+struct bt_hci_cp_reject_conn_req {
+	bt_addr_t bdaddr;
+	uint8_t   reason;
+} __packed;
+
+#define BT_HCI_OP_LINK_KEY_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000b)
+struct bt_hci_cp_link_key_reply {
+	bt_addr_t bdaddr;
+	uint8_t   link_key[16];
+} __packed;
+
+#define BT_HCI_OP_LINK_KEY_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000c)
+struct bt_hci_cp_link_key_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_PIN_CODE_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000d)
+struct bt_hci_cp_pin_code_reply {
+	bt_addr_t bdaddr;
+	uint8_t   pin_len;
+	uint8_t   pin_code[16];
+} __packed;
+struct bt_hci_rp_pin_code_reply {
+	uint8_t      status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_PIN_CODE_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000e)
+struct bt_hci_cp_pin_code_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_pin_code_neg_reply {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_AUTH_REQUESTED                BT_OP(BT_OGF_LINK_CTRL, 0x0011)
+struct bt_hci_cp_auth_requested {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_SET_CONN_ENCRYPT              BT_OP(BT_OGF_LINK_CTRL, 0x0013)
+struct bt_hci_cp_set_conn_encrypt {
+	uint16_t handle;
+	uint8_t  encrypt;
+} __packed;
+
+#define BT_HCI_OP_REMOTE_NAME_REQUEST           BT_OP(BT_OGF_LINK_CTRL, 0x0019)
+struct bt_hci_cp_remote_name_request {
+	bt_addr_t bdaddr;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint16_t  clock_offset;
+} __packed;
+
+#define BT_HCI_OP_REMOTE_NAME_CANCEL            BT_OP(BT_OGF_LINK_CTRL, 0x001a)
+struct bt_hci_cp_remote_name_cancel {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_remote_name_cancel {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_FEATURES          BT_OP(BT_OGF_LINK_CTRL, 0x001b)
+struct bt_hci_cp_read_remote_features {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES      BT_OP(BT_OGF_LINK_CTRL, 0x001c)
+struct bt_hci_cp_read_remote_ext_features {
+	uint16_t handle;
+	uint8_t  page;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_VERSION_INFO      BT_OP(BT_OGF_LINK_CTRL, 0x001d)
+struct bt_hci_cp_read_remote_version_info {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_IO_CAPABILITY_REPLY           BT_OP(BT_OGF_LINK_CTRL, 0x002b)
+struct bt_hci_cp_io_capability_reply {
+	bt_addr_t bdaddr;
+	uint8_t   capability;
+	uint8_t   oob_data;
+	uint8_t   authentication;
+} __packed;
+
+#define BT_HCI_OP_USER_CONFIRM_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002c)
+#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002d)
+struct bt_hci_cp_user_confirm_reply {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_user_confirm_reply {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_USER_PASSKEY_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002e)
+struct bt_hci_cp_user_passkey_reply {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002f)
+struct bt_hci_cp_user_passkey_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY       BT_OP(BT_OGF_LINK_CTRL, 0x0034)
+struct bt_hci_cp_io_capability_neg_reply {
+	bt_addr_t bdaddr;
+	uint8_t   reason;
+} __packed;
+
+#define BT_HCI_OP_SET_EVENT_MASK                BT_OP(BT_OGF_BASEBAND, 0x0001)
+struct bt_hci_cp_set_event_mask {
+	uint8_t  events[8];
+} __packed;
+
+#define BT_HCI_OP_RESET                         BT_OP(BT_OGF_BASEBAND, 0x0003)
+
+#define BT_HCI_OP_WRITE_LOCAL_NAME              BT_OP(BT_OGF_BASEBAND, 0x0013)
+struct bt_hci_write_local_name {
+	uint8_t local_name[248];
+} __packed;
+
+#define BT_HCI_OP_WRITE_PAGE_TIMEOUT            BT_OP(BT_OGF_BASEBAND, 0x0018)
+
+#define BT_HCI_OP_WRITE_SCAN_ENABLE             BT_OP(BT_OGF_BASEBAND, 0x001a)
+#define BT_BREDR_SCAN_DISABLED                  0x00
+#define BT_BREDR_SCAN_INQUIRY                   0x01
+#define BT_BREDR_SCAN_PAGE                      0x02
+
+#define BT_TX_POWER_LEVEL_CURRENT               0x00
+#define BT_TX_POWER_LEVEL_MAX                   0x01
+#define BT_HCI_OP_READ_TX_POWER_LEVEL           BT_OP(BT_OGF_BASEBAND, 0x002d)
+struct bt_hci_cp_read_tx_power_level {
+	uint16_t handle;
+	uint8_t  type;
+} __packed;
+
+struct bt_hci_rp_read_tx_power_level {
+	uint8_t  status;
+	uint16_t handle;
+	int8_t   tx_power_level;
+} __packed;
+
+#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE         0x00
+#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE          0x01
+#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW          BT_OP(BT_OGF_BASEBAND, 0x0031)
+struct bt_hci_cp_set_ctl_to_host_flow {
+	uint8_t  flow_enable;
+} __packed;
+
+#define BT_HCI_OP_HOST_BUFFER_SIZE              BT_OP(BT_OGF_BASEBAND, 0x0033)
+struct bt_hci_cp_host_buffer_size {
+	uint16_t acl_mtu;
+	uint8_t  sco_mtu;
+	uint16_t acl_pkts;
+	uint16_t sco_pkts;
+} __packed;
+
+struct bt_hci_handle_count {
+	uint16_t handle;
+	uint16_t count;
+} __packed;
+
+#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS    BT_OP(BT_OGF_BASEBAND, 0x0035)
+struct bt_hci_cp_host_num_completed_packets {
+	uint8_t  num_handles;
+	struct bt_hci_handle_count h[0];
+} __packed;
+
+#define BT_HCI_OP_WRITE_INQUIRY_MODE            BT_OP(BT_OGF_BASEBAND, 0x0045)
+struct bt_hci_cp_write_inquiry_mode {
+	uint8_t  mode;
+} __packed;
+
+#define BT_HCI_OP_WRITE_SSP_MODE                BT_OP(BT_OGF_BASEBAND, 0x0056)
+struct bt_hci_cp_write_ssp_mode {
+	uint8_t mode;
+} __packed;
+
+#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2         BT_OP(BT_OGF_BASEBAND, 0x0063)
+struct bt_hci_cp_set_event_mask_page_2 {
+	uint8_t  events_page_2[8];
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP         BT_OP(BT_OGF_BASEBAND, 0x006d)
+struct bt_hci_cp_write_le_host_supp {
+	uint8_t  le;
+	uint8_t  simul;
+} __packed;
+
+#define BT_HCI_OP_WRITE_SC_HOST_SUPP            BT_OP(BT_OGF_BASEBAND, 0x007a)
+struct bt_hci_cp_write_sc_host_supp {
+	uint8_t  sc_support;
+} __packed;
+
+#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT     BT_OP(BT_OGF_BASEBAND, 0x007b)
+struct bt_hci_cp_read_auth_payload_timeout {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_read_auth_payload_timeout {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t auth_payload_timeout;
+} __packed;
+
+#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT    BT_OP(BT_OGF_BASEBAND, 0x007c)
+struct bt_hci_cp_write_auth_payload_timeout {
+	uint16_t handle;
+	uint16_t auth_payload_timeout;
+} __packed;
+
+struct bt_hci_rp_write_auth_payload_timeout {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+/* HCI version from Assigned Numbers */
+#define BT_HCI_VERSION_1_0B                     0
+#define BT_HCI_VERSION_1_1                      1
+#define BT_HCI_VERSION_1_2                      2
+#define BT_HCI_VERSION_2_0                      3
+#define BT_HCI_VERSION_2_1                      4
+#define BT_HCI_VERSION_3_0                      5
+#define BT_HCI_VERSION_4_0                      6
+#define BT_HCI_VERSION_4_1                      7
+#define BT_HCI_VERSION_4_2                      8
+#define BT_HCI_VERSION_5_0                      9
+#define BT_HCI_VERSION_5_1                      10
+#define BT_HCI_VERSION_5_2                      11
+
+#define BT_HCI_OP_READ_LOCAL_VERSION_INFO       BT_OP(BT_OGF_INFO, 0x0001)
+struct bt_hci_rp_read_local_version_info {
+	uint8_t  status;
+	uint8_t  hci_version;
+	uint16_t hci_revision;
+	uint8_t  lmp_version;
+	uint16_t manufacturer;
+	uint16_t lmp_subversion;
+} __packed;
+
+#define BT_HCI_OP_READ_SUPPORTED_COMMANDS       BT_OP(BT_OGF_INFO, 0x0002)
+struct bt_hci_rp_read_supported_commands {
+	uint8_t  status;
+	uint8_t  commands[64];
+} __packed;
+
+#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES       BT_OP(BT_OGF_INFO, 0x0004)
+struct bt_hci_cp_read_local_ext_features {
+	uint8_t page;
+};
+struct bt_hci_rp_read_local_ext_features {
+	uint8_t  status;
+	uint8_t  page;
+	uint8_t  max_page;
+	uint8_t  ext_features[8];
+} __packed;
+
+#define BT_HCI_OP_READ_LOCAL_FEATURES           BT_OP(BT_OGF_INFO, 0x0003)
+struct bt_hci_rp_read_local_features {
+	uint8_t  status;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_OP_READ_BUFFER_SIZE              BT_OP(BT_OGF_INFO, 0x0005)
+struct bt_hci_rp_read_buffer_size {
+	uint8_t  status;
+	uint16_t acl_max_len;
+	uint8_t  sco_max_len;
+	uint16_t acl_max_num;
+	uint16_t sco_max_num;
+} __packed;
+
+#define BT_HCI_OP_READ_BD_ADDR                  BT_OP(BT_OGF_INFO, 0x0009)
+struct bt_hci_rp_read_bd_addr {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_READ_RSSI                     BT_OP(BT_OGF_STATUS, 0x0005)
+struct bt_hci_cp_read_rssi {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_read_rssi {
+	uint8_t  status;
+	uint16_t handle;
+	int8_t   rssi;
+} __packed;
+
+#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN          7
+#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX          16
+
+#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE      BT_OP(BT_OGF_STATUS, 0x0008)
+struct bt_hci_cp_read_encryption_key_size {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_read_encryption_key_size {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  key_size;
+} __packed;
+
+/* BLE */
+
+#define BT_HCI_OP_LE_SET_EVENT_MASK             BT_OP(BT_OGF_LE, 0x0001)
+struct bt_hci_cp_le_set_event_mask {
+	uint8_t events[8];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_BUFFER_SIZE           BT_OP(BT_OGF_LE, 0x0002)
+struct bt_hci_rp_le_read_buffer_size {
+	uint8_t  status;
+	uint16_t le_max_len;
+	uint8_t  le_max_num;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_LOCAL_FEATURES        BT_OP(BT_OGF_LE, 0x0003)
+struct bt_hci_rp_le_read_local_features {
+	uint8_t  status;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS         BT_OP(BT_OGF_LE, 0x0005)
+struct bt_hci_cp_le_set_random_address {
+	bt_addr_t bdaddr;
+} __packed;
+
+/* LE Advertising Types (LE Advertising Parameters Set)*/
+#define BT_LE_ADV_IND                  (__DEPRECATED_MACRO 0x00)
+#define BT_LE_ADV_DIRECT_IND           (__DEPRECATED_MACRO 0x01)
+#define BT_LE_ADV_SCAN_IND             (__DEPRECATED_MACRO 0x02)
+#define BT_LE_ADV_NONCONN_IND          (__DEPRECATED_MACRO 0x03)
+#define BT_LE_ADV_DIRECT_IND_LOW_DUTY  (__DEPRECATED_MACRO 0x04)
+/* LE Advertising PDU Types. */
+#define BT_LE_ADV_SCAN_RSP             (__DEPRECATED_MACRO 0x04)
+
+#define BT_HCI_ADV_IND                          0x00
+#define BT_HCI_ADV_DIRECT_IND                   0x01
+#define BT_HCI_ADV_SCAN_IND                     0x02
+#define BT_HCI_ADV_NONCONN_IND                  0x03
+#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY          0x04
+#define BT_HCI_ADV_SCAN_RSP                     0x04
+
+#define BT_LE_ADV_FP_NO_WHITELIST               0x00
+#define BT_LE_ADV_FP_WHITELIST_SCAN_REQ         0x01
+#define BT_LE_ADV_FP_WHITELIST_CONN_IND         0x02
+#define BT_LE_ADV_FP_WHITELIST_BOTH             0x03
+
+#define BT_HCI_OP_LE_SET_ADV_PARAM              BT_OP(BT_OGF_LE, 0x0006)
+struct bt_hci_cp_le_set_adv_param {
+	uint16_t     min_interval;
+	uint16_t     max_interval;
+	uint8_t      type;
+	uint8_t      own_addr_type;
+	bt_addr_le_t direct_addr;
+	uint8_t      channel_map;
+	uint8_t      filter_policy;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER     BT_OP(BT_OGF_LE, 0x0007)
+struct bt_hci_rp_le_read_chan_tx_power {
+	uint8_t status;
+	int8_t  tx_power_level;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_ADV_DATA               BT_OP(BT_OGF_LE, 0x0008)
+struct bt_hci_cp_le_set_adv_data {
+	uint8_t  len;
+	uint8_t  data[31];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA          BT_OP(BT_OGF_LE, 0x0009)
+struct bt_hci_cp_le_set_scan_rsp_data {
+	uint8_t  len;
+	uint8_t  data[31];
+} __packed;
+
+#define BT_HCI_LE_ADV_DISABLE                   0x00
+#define BT_HCI_LE_ADV_ENABLE                    0x01
+
+#define BT_HCI_OP_LE_SET_ADV_ENABLE             BT_OP(BT_OGF_LE, 0x000a)
+struct bt_hci_cp_le_set_adv_enable {
+	uint8_t  enable;
+} __packed;
+
+/* Scan types */
+#define BT_HCI_OP_LE_SET_SCAN_PARAM             BT_OP(BT_OGF_LE, 0x000b)
+#define BT_HCI_LE_SCAN_PASSIVE                  0x00
+#define BT_HCI_LE_SCAN_ACTIVE                   0x01
+
+#define BT_HCI_LE_SCAN_FP_NO_WHITELIST          0x00
+#define BT_HCI_LE_SCAN_FP_USE_WHITELIST         0x01
+
+struct bt_hci_cp_le_set_scan_param {
+	uint8_t  scan_type;
+	uint16_t interval;
+	uint16_t window;
+	uint8_t  addr_type;
+	uint8_t  filter_policy;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_SCAN_ENABLE            BT_OP(BT_OGF_LE, 0x000c)
+
+#define BT_HCI_LE_SCAN_DISABLE                  0x00
+#define BT_HCI_LE_SCAN_ENABLE                   0x01
+
+#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE       0x00
+#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE        0x01
+
+struct bt_hci_cp_le_set_scan_enable {
+	uint8_t  enable;
+	uint8_t  filter_dup;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_CONN                BT_OP(BT_OGF_LE, 0x000d)
+
+#define BT_HCI_LE_CREATE_CONN_FP_DIRECT         0x00
+#define BT_HCI_LE_CREATE_CONN_FP_WHITELIST      0x01
+
+struct bt_hci_cp_le_create_conn {
+	uint16_t     scan_interval;
+	uint16_t     scan_window;
+	uint8_t      filter_policy;
+	bt_addr_le_t peer_addr;
+	uint8_t      own_addr_type;
+	uint16_t     conn_interval_min;
+	uint16_t     conn_interval_max;
+	uint16_t     conn_latency;
+	uint16_t     supervision_timeout;
+	uint16_t     min_ce_len;
+	uint16_t     max_ce_len;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_CONN_CANCEL         BT_OP(BT_OGF_LE, 0x000e)
+
+#define BT_HCI_OP_LE_READ_WL_SIZE               BT_OP(BT_OGF_LE, 0x000f)
+struct bt_hci_rp_le_read_wl_size {
+	uint8_t  status;
+	uint8_t  wl_size;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_WL                   BT_OP(BT_OGF_LE, 0x0010)
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_WL              BT_OP(BT_OGF_LE, 0x0011)
+struct bt_hci_cp_le_add_dev_to_wl {
+	bt_addr_le_t  addr;
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_WL            BT_OP(BT_OGF_LE, 0x0012)
+struct bt_hci_cp_le_rem_dev_from_wl {
+	bt_addr_le_t  addr;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_UPDATE                BT_OP(BT_OGF_LE, 0x0013)
+struct hci_cp_le_conn_update {
+	uint16_t handle;
+	uint16_t conn_interval_min;
+	uint16_t conn_interval_max;
+	uint16_t conn_latency;
+	uint16_t supervision_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF      BT_OP(BT_OGF_LE, 0x0014)
+struct bt_hci_cp_le_set_host_chan_classif {
+	uint8_t  ch_map[5];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_CHAN_MAP              BT_OP(BT_OGF_LE, 0x0015)
+struct bt_hci_cp_le_read_chan_map {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_read_chan_map {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  ch_map[5];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_REMOTE_FEATURES       BT_OP(BT_OGF_LE, 0x0016)
+struct bt_hci_cp_le_read_remote_features {
+	uint16_t  handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ENCRYPT                    BT_OP(BT_OGF_LE, 0x0017)
+struct bt_hci_cp_le_encrypt {
+	uint8_t  key[16];
+	uint8_t  plaintext[16];
+} __packed;
+struct bt_hci_rp_le_encrypt {
+	uint8_t  status;
+	uint8_t  enc_data[16];
+} __packed;
+
+#define BT_HCI_OP_LE_RAND                       BT_OP(BT_OGF_LE, 0x0018)
+struct bt_hci_rp_le_rand {
+	uint8_t  status;
+	uint8_t  rand[8];
+} __packed;
+
+#define BT_HCI_OP_LE_START_ENCRYPTION           BT_OP(BT_OGF_LE, 0x0019)
+struct bt_hci_cp_le_start_encryption {
+	uint16_t handle;
+	uint64_t rand;
+	uint16_t ediv;
+	uint8_t  ltk[16];
+} __packed;
+
+#define BT_HCI_OP_LE_LTK_REQ_REPLY              BT_OP(BT_OGF_LE, 0x001a)
+struct bt_hci_cp_le_ltk_req_reply {
+	uint16_t handle;
+	uint8_t  ltk[16];
+} __packed;
+struct bt_hci_rp_le_ltk_req_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY          BT_OP(BT_OGF_LE, 0x001b)
+struct bt_hci_cp_le_ltk_req_neg_reply {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_ltk_req_neg_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_SUPP_STATES           BT_OP(BT_OGF_LE, 0x001c)
+struct bt_hci_rp_le_read_supp_states {
+	uint8_t  status;
+	uint8_t  le_states[8];
+} __packed;
+
+#define BT_HCI_OP_LE_RX_TEST                    BT_OP(BT_OGF_LE, 0x001d)
+struct bt_hci_cp_le_rx_test {
+	uint8_t  rx_ch;
+} __packed;
+
+#define BT_HCI_OP_LE_TX_TEST                    BT_OP(BT_OGF_LE, 0x001e)
+struct bt_hci_cp_le_tx_test {
+	uint8_t  tx_ch;
+	uint8_t  test_data_len;
+	uint8_t  pkt_payload;
+} __packed;
+
+#define BT_HCI_OP_LE_TEST_END                   BT_OP(BT_OGF_LE, 0x001f)
+struct bt_hci_rp_le_test_end {
+	uint8_t  status;
+	uint16_t rx_pkt_count;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY       BT_OP(BT_OGF_LE, 0x0020)
+struct bt_hci_cp_le_conn_param_req_reply {
+	uint16_t handle;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+struct bt_hci_rp_le_conn_param_req_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY   BT_OP(BT_OGF_LE, 0x0021)
+struct bt_hci_cp_le_conn_param_req_neg_reply {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+struct bt_hci_rp_le_conn_param_req_neg_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_DATA_LEN               BT_OP(BT_OGF_LE, 0x0022)
+struct bt_hci_cp_le_set_data_len {
+	uint16_t handle;
+	uint16_t tx_octets;
+	uint16_t tx_time;
+} __packed;
+struct bt_hci_rp_le_set_data_len {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN      BT_OP(BT_OGF_LE, 0x0023)
+struct bt_hci_rp_le_read_default_data_len {
+	uint8_t  status;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN     BT_OP(BT_OGF_LE, 0x0024)
+struct bt_hci_cp_le_write_default_data_len {
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+#define BT_HCI_OP_LE_P256_PUBLIC_KEY            BT_OP(BT_OGF_LE, 0x0025)
+
+#define BT_HCI_OP_LE_GENERATE_DHKEY             BT_OP(BT_OGF_LE, 0x0026)
+struct bt_hci_cp_le_generate_dhkey {
+	uint8_t key[64];
+} __packed;
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_RL              BT_OP(BT_OGF_LE, 0x0027)
+struct bt_hci_cp_le_add_dev_to_rl {
+	bt_addr_le_t  peer_id_addr;
+	uint8_t       peer_irk[16];
+	uint8_t       local_irk[16];
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_RL            BT_OP(BT_OGF_LE, 0x0028)
+struct bt_hci_cp_le_rem_dev_from_rl {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_RL                   BT_OP(BT_OGF_LE, 0x0029)
+
+#define BT_HCI_OP_LE_READ_RL_SIZE               BT_OP(BT_OGF_LE, 0x002a)
+struct bt_hci_rp_le_read_rl_size {
+	uint8_t  status;
+	uint8_t  rl_size;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_PEER_RPA              BT_OP(BT_OGF_LE, 0x002b)
+struct bt_hci_cp_le_read_peer_rpa {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+struct bt_hci_rp_le_read_peer_rpa {
+	uint8_t    status;
+	bt_addr_t  peer_rpa;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_LOCAL_RPA             BT_OP(BT_OGF_LE, 0x002c)
+struct bt_hci_cp_le_read_local_rpa {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+struct bt_hci_rp_le_read_local_rpa {
+	uint8_t    status;
+	bt_addr_t  local_rpa;
+} __packed;
+
+#define BT_HCI_ADDR_RES_DISABLE                 0x00
+#define BT_HCI_ADDR_RES_ENABLE                  0x01
+
+#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE        BT_OP(BT_OGF_LE, 0x002d)
+struct bt_hci_cp_le_set_addr_res_enable {
+	uint8_t  enable;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_RPA_TIMEOUT            BT_OP(BT_OGF_LE, 0x002e)
+struct bt_hci_cp_le_set_rpa_timeout {
+	uint16_t rpa_timeout;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_MAX_DATA_LEN          BT_OP(BT_OGF_LE, 0x002f)
+struct bt_hci_rp_le_read_max_data_len {
+	uint8_t  status;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+} __packed;
+
+#define BT_HCI_LE_PHY_1M                        0x01
+#define BT_HCI_LE_PHY_2M                        0x02
+#define BT_HCI_LE_PHY_CODED                     0x03
+
+#define BT_HCI_OP_LE_READ_PHY                   BT_OP(BT_OGF_LE, 0x0030)
+struct bt_hci_cp_le_read_phy {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_read_phy {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  tx_phy;
+	uint8_t  rx_phy;
+} __packed;
+
+#define BT_HCI_LE_PHY_TX_ANY                    BIT(0)
+#define BT_HCI_LE_PHY_RX_ANY                    BIT(1)
+
+#define BT_HCI_LE_PHY_PREFER_1M                 BIT(0)
+#define BT_HCI_LE_PHY_PREFER_2M                 BIT(1)
+#define BT_HCI_LE_PHY_PREFER_CODED              BIT(2)
+
+#define BT_HCI_OP_LE_SET_DEFAULT_PHY            BT_OP(BT_OGF_LE, 0x0031)
+struct bt_hci_cp_le_set_default_phy {
+	uint8_t all_phys;
+	uint8_t tx_phys;
+	uint8_t rx_phys;
+} __packed;
+
+#define BT_HCI_LE_PHY_CODED_ANY                 0x00
+#define BT_HCI_LE_PHY_CODED_S2                  0x01
+#define BT_HCI_LE_PHY_CODED_S8                  0x02
+
+#define BT_HCI_OP_LE_SET_PHY                    BT_OP(BT_OGF_LE, 0x0032)
+struct bt_hci_cp_le_set_phy {
+	uint16_t  handle;
+	uint8_t   all_phys;
+	uint8_t   tx_phys;
+	uint8_t   rx_phys;
+	uint16_t  phy_opts;
+} __packed;
+
+#define BT_HCI_LE_MOD_INDEX_STANDARD            0x00
+#define BT_HCI_LE_MOD_INDEX_STABLE              0x01
+
+#define BT_HCI_OP_LE_ENH_RX_TEST                BT_OP(BT_OGF_LE, 0x0033)
+struct bt_hci_cp_le_enh_rx_test {
+	uint8_t  rx_ch;
+	uint8_t  phy;
+	uint8_t  mod_index;
+} __packed;
+
+/* Extends BT_HCI_LE_PHY */
+#define BT_HCI_LE_TX_PHY_CODED_S8               0x03
+#define BT_HCI_LE_TX_PHY_CODED_S2               0x04
+
+#define BT_HCI_OP_LE_ENH_TX_TEST                BT_OP(BT_OGF_LE, 0x0034)
+struct bt_hci_cp_le_enh_tx_test {
+	uint8_t  tx_ch;
+	uint8_t  test_data_len;
+	uint8_t  pkt_payload;
+	uint8_t  phy;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR    BT_OP(BT_OGF_LE, 0x0035)
+struct bt_hci_cp_le_set_adv_set_random_addr {
+	uint8_t   handle;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_LE_ADV_PROP_CONN                 BIT(0)
+#define BT_HCI_LE_ADV_PROP_SCAN                 BIT(1)
+#define BT_HCI_LE_ADV_PROP_DIRECT               BIT(2)
+#define BT_HCI_LE_ADV_PROP_HI_DC_CONN           BIT(3)
+#define BT_HCI_LE_ADV_PROP_LEGACY               BIT(4)
+#define BT_HCI_LE_ADV_PROP_ANON                 BIT(5)
+#define BT_HCI_LE_ADV_PROP_TX_POWER             BIT(6)
+
+#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE  1
+#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0
+
+#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F
+
+#define BT_HCI_LE_ADV_HANDLE_MAX       0xEF
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM          BT_OP(BT_OGF_LE, 0x0036)
+struct bt_hci_cp_le_set_ext_adv_param {
+	uint8_t      handle;
+	uint16_t     props;
+	uint8_t      prim_min_interval[3];
+	uint8_t      prim_max_interval[3];
+	uint8_t      prim_channel_map;
+	uint8_t      own_addr_type;
+	bt_addr_le_t peer_addr;
+	uint8_t      filter_policy;
+	int8_t       tx_power;
+	uint8_t      prim_adv_phy;
+	uint8_t      sec_adv_max_skip;
+	uint8_t      sec_adv_phy;
+	uint8_t      sid;
+	uint8_t      scan_req_notify_enable;
+} __packed;
+struct bt_hci_rp_le_set_ext_adv_param {
+	uint8_t status;
+	int8_t  tx_power;
+} __packed;
+
+#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG        0x00
+#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG         0x01
+#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG          0x02
+#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA      0x03
+#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA     0x04
+
+#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED          0x00
+#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED         0x01
+
+#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN          251
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_DATA           BT_OP(BT_OGF_LE, 0x0037)
+struct bt_hci_cp_le_set_ext_adv_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  frag_pref;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA      BT_OP(BT_OGF_LE, 0x0038)
+struct bt_hci_cp_le_set_ext_scan_rsp_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  frag_pref;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0039)
+struct bt_hci_ext_adv_set {
+	uint8_t  handle;
+	uint16_t duration;
+	uint8_t  max_ext_adv_evts;
+} __packed;
+
+struct bt_hci_cp_le_set_ext_adv_enable {
+	uint8_t  enable;
+	uint8_t  set_num;
+	struct bt_hci_ext_adv_set s[0];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN      BT_OP(BT_OGF_LE, 0x003a)
+struct bt_hci_rp_le_read_max_adv_data_len {
+	uint8_t  status;
+	uint16_t max_adv_data_len;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_NUM_ADV_SETS          BT_OP(BT_OGF_LE, 0x003b)
+struct bt_hci_rp_le_read_num_adv_sets {
+	uint8_t  status;
+	uint8_t  num_sets;
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_ADV_SET             BT_OP(BT_OGF_LE, 0x003c)
+struct bt_hci_cp_le_remove_adv_set {
+	uint8_t  handle;
+} __packed;
+
+#define BT_HCI_OP_CLEAR_ADV_SETS                BT_OP(BT_OGF_LE, 0x003d)
+
+#define BT_HCI_OP_LE_SET_PER_ADV_PARAM          BT_OP(BT_OGF_LE, 0x003e)
+struct bt_hci_cp_le_set_per_adv_param {
+	uint8_t  handle;
+	uint16_t min_interval;
+	uint16_t max_interval;
+	uint16_t props;
+} __packed;
+
+#define BT_HCI_LE_PER_ADV_OP_INTERM_FRAG        0x00
+#define BT_HCI_LE_PER_ADV_OP_FIRST_FRAG         0x01
+#define BT_HCI_LE_PER_ADV_OP_LAST_FRAG          0x02
+#define BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA      0x03
+
+#define BT_HCI_LE_PER_ADV_FRAG_MAX_LEN          252
+
+#define BT_HCI_OP_LE_SET_PER_ADV_DATA           BT_OP(BT_OGF_LE, 0x003f)
+struct bt_hci_cp_le_set_per_adv_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0040)
+struct bt_hci_cp_le_set_per_adv_enable {
+	uint8_t  enable;
+	uint8_t  handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM         BT_OP(BT_OGF_LE, 0x0041)
+struct bt_hci_ext_scan_phy {
+	uint8_t  type;
+	uint16_t interval;
+	uint16_t window;
+} __packed;
+
+#define BT_HCI_LE_EXT_SCAN_PHY_1M               BIT(0)
+#define BT_HCI_LE_EXT_SCAN_PHY_2M               BIT(1)
+#define BT_HCI_LE_EXT_SCAN_PHY_CODED            BIT(2)
+
+struct bt_hci_cp_le_set_ext_scan_param {
+	uint8_t  own_addr_type;
+	uint8_t  filter_policy;
+	uint8_t  phys;
+	struct bt_hci_ext_scan_phy p[0];
+} __packed;
+
+/* Extends BT_HCI_LE_SCAN_FILTER_DUP */
+#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET  0x02
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE        BT_OP(BT_OGF_LE, 0x0042)
+struct bt_hci_cp_le_set_ext_scan_enable {
+	uint8_t  enable;
+	uint8_t  filter_dup;
+	uint16_t duration;
+	uint16_t period;
+} __packed;
+
+#define BT_HCI_OP_LE_EXT_CREATE_CONN            BT_OP(BT_OGF_LE, 0x0043)
+struct bt_hci_ext_conn_phy {
+	uint16_t scan_interval;
+	uint16_t scan_window;
+	uint16_t conn_interval_min;
+	uint16_t conn_interval_max;
+	uint16_t conn_latency;
+	uint16_t supervision_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+
+struct bt_hci_cp_le_ext_create_conn {
+	uint8_t      filter_policy;
+	uint8_t      own_addr_type;
+	bt_addr_le_t peer_addr;
+	uint8_t      phys;
+	struct bt_hci_ext_conn_phy p[0];
+} __packed;
+
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST               BIT(0)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED       BIT(1)
+
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA           BIT(0)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US       BIT(1)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US       BIT(2)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_CTE           BIT(3)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE         BIT(4)
+
+#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC        BT_OP(BT_OGF_LE, 0x0044)
+struct bt_hci_cp_le_per_adv_create_sync {
+	uint8_t      options;
+	uint8_t      sid;
+	bt_addr_le_t addr;
+	uint16_t     skip;
+	uint16_t     sync_timeout;
+	uint8_t      cte_type;
+} __packed;
+
+#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045)
+
+#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC     BT_OP(BT_OGF_LE, 0x0046)
+struct bt_hci_cp_le_per_adv_terminate_sync {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST    BT_OP(BT_OGF_LE, 0x0047)
+struct bt_hci_cp_le_add_dev_to_per_adv_list {
+	bt_addr_le_t addr;
+	uint8_t      sid;
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST  BT_OP(BT_OGF_LE, 0x0048)
+struct bt_hci_cp_le_rem_dev_from_per_adv_list {
+	bt_addr_le_t addr;
+	uint8_t      sid;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST         BT_OP(BT_OGF_LE, 0x0049)
+
+#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE     BT_OP(BT_OGF_LE, 0x004a)
+struct bt_hci_rp_le_read_per_adv_list_size {
+	uint8_t  status;
+	uint8_t  list_size;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_TX_POWER              BT_OP(BT_OGF_LE, 0x004b)
+struct bt_hci_rp_le_read_tx_power {
+	uint8_t status;
+	int8_t  min_tx_power;
+	int8_t  max_tx_power;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_RF_PATH_COMP          BT_OP(BT_OGF_LE, 0x004c)
+struct bt_hci_rp_le_read_rf_path_comp {
+	uint8_t status;
+	int16_t tx_path_comp;
+	int16_t rx_path_comp;
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP         BT_OP(BT_OGF_LE, 0x004d)
+struct bt_hci_cp_le_write_rf_path_comp {
+	int16_t  tx_path_comp;
+	int16_t  rx_path_comp;
+} __packed;
+
+#define BT_HCI_LE_PRIVACY_MODE_NETWORK          0x00
+#define BT_HCI_LE_PRIVACY_MODE_DEVICE           0x01
+
+#define BT_HCI_OP_LE_SET_PRIVACY_MODE           BT_OP(BT_OGF_LE, 0x004e)
+struct bt_hci_cp_le_set_privacy_mode {
+	bt_addr_le_t id_addr;
+	uint8_t         mode;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE     BT_OP(BT_OGF_LE, 0x0059)
+struct bt_hci_cp_le_set_per_adv_recv_enable {
+	uint16_t handle;
+	uint8_t  enable;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_BUFFER_SIZE_V2        BT_OP(BT_OGF_LE, 0x0060)
+struct bt_hci_rp_le_read_buffer_size_v2 {
+	uint8_t  status;
+	uint16_t acl_mtu;
+	uint8_t  acl_max_pkt;
+	uint16_t iso_mtu;
+	uint8_t  iso_max_pkt;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ISO_TX_SYNC           BT_OP(BT_OGF_LE, 0x0061)
+struct bt_hci_cp_le_read_iso_tx_sync {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_le_read_iso_tx_sync {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t seq;
+	uint32_t timestamp;
+	uint8_t  offset[3];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_CIG_PARAMS             BT_OP(BT_OGF_LE, 0x0062)
+struct bt_hci_cis_params {
+	uint8_t  cis_id;
+	uint16_t m_sdu;
+	uint16_t s_sdu;
+	uint8_t  m_phy;
+	uint8_t  s_phy;
+	uint8_t  m_rtn;
+	uint8_t  s_rtn;
+} __packed;
+
+struct bt_hci_cp_le_set_cig_params {
+	uint8_t  cig_id;
+	uint8_t  m_interval[3];
+	uint8_t  s_interval[3];
+	uint8_t  sca;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint16_t m_latency;
+	uint16_t s_latency;
+	uint8_t  num_cis;
+	struct bt_hci_cis_params cis[0];
+} __packed;
+
+struct bt_hci_rp_le_set_cig_params {
+	uint8_t  status;
+	uint8_t  cig_id;
+	uint8_t  num_handles;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST        BT_OP(BT_OGF_LE, 0x0063)
+
+#define BT_HCI_OP_LE_CREATE_CIS                 BT_OP(BT_OGF_LE, 0x0064)
+struct bt_hci_cis {
+	uint16_t  cis_handle;
+	uint16_t  acl_handle;
+} __packed;
+
+struct bt_hci_cp_le_create_cis {
+	uint8_t  num_cis;
+	struct bt_hci_cis cis[0];
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_CIG                 BT_OP(BT_OGF_LE, 0x0065)
+struct bt_hci_cp_le_remove_cig {
+	uint8_t  cig_id;
+} __packed;
+
+struct bt_hci_rp_le_remove_cig {
+	uint8_t  status;
+	uint8_t  cig_id;
+} __packed;
+
+#define BT_HCI_OP_LE_ACCEPT_CIS                 BT_OP(BT_OGF_LE, 0x0066)
+struct bt_hci_cp_le_accept_cis {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REJECT_CIS                 BT_OP(BT_OGF_LE, 0x0067)
+struct bt_hci_cp_le_reject_cis {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+struct bt_hci_rp_le_reject_cis {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_BIG                 BT_OP(BT_OGF_LE, 0x0068)
+struct bt_hci_cp_le_create_big {
+	uint8_t  big_handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	uint8_t  sdu_interval[3];
+	uint16_t max_sdu;
+	uint16_t max_latency;
+	uint8_t  rtn;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_BIG_TEST            BT_OP(BT_OGF_LE, 0x0069)
+struct bt_hci_cp_le_create_big_test {
+	uint8_t  big_handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	uint8_t  sdu_interval[3];
+	uint16_t iso_interval;
+	uint8_t  nse;
+	uint16_t max_sdu;
+	uint16_t max_pdu;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  bn;
+	uint8_t  irc;
+	uint8_t  pto;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+} __packed;
+
+#define BT_HCI_OP_LE_TERMINATE_BIG              BT_OP(BT_OGF_LE, 0x006a)
+struct bt_hci_cp_le_terminate_big {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_OP_LE_BIG_CREATE_SYNC            BT_OP(BT_OGF_LE, 0x006b)
+struct bt_hci_cp_le_big_create_sync {
+	uint8_t  big_handle;
+	uint16_t sync_handle;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  mse;
+	uint16_t sync_timeout;
+	uint8_t  num_bis;
+	uint8_t  bis[0];
+} __packed;
+
+#define BT_HCI_OP_LE_BIG_TERMINATE_SYNC         BT_OP(BT_OGF_LE, 0x006c)
+struct bt_hci_cp_le_big_terminate_sync {
+	uint8_t  big_handle;
+} __packed;
+
+struct bt_hci_rp_le_big_terminate_sync {
+	uint8_t  status;
+	uint8_t  big_handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REQ_PEER_SC                BT_OP(BT_OGF_LE, 0x006d)
+struct bt_hci_cp_le_req_peer_sca {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SETUP_ISO_PATH             BT_OP(BT_OGF_LE, 0x006e)
+struct bt_hci_cp_le_setup_iso_path {
+	uint16_t handle;
+	uint8_t  path_dir;
+	uint8_t  path_id;
+	uint8_t  coding_format;
+	uint16_t company_id;
+	uint16_t vendor_id;
+	uint8_t  controller_delay[3];
+	uint8_t  codec_config_len;
+	uint8_t  codec_config[0];
+} __packed;
+
+struct bt_hci_rp_le_setup_iso_path {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_ISO_PATH            BT_OP(BT_OGF_LE, 0x006f)
+struct bt_hci_cp_le_remove_iso_path {
+	uint16_t handle;
+	uint8_t  path_dir;
+} __packed;
+
+struct bt_hci_rp_le_remove_iso_path {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST          BT_OP(BT_OGF_LE, 0x0070)
+
+#define BT_HCI_OP_LE_ISO_RECEIVE_TEST           BT_OP(BT_OGF_LE, 0x0071)
+
+#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS     BT_OP(BT_OGF_LE, 0x0072)
+
+#define BT_HCI_OP_LE_ISO_TEST_END               BT_OP(BT_OGF_LE, 0x0073)
+
+#define BT_HCI_OP_LE_SET_HOST_FEATURE           BT_OP(BT_OGF_LE, 0x0074)
+struct bt_hci_cp_le_set_host_feature {
+	uint8_t  bit_number;
+	uint8_t  bit_value;
+} __packed;
+
+struct bt_hci_rp_le_set_host_feature {
+	uint8_t  status;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ISO_LINK_QUALITY      BT_OP(BT_OGF_LE, 0x0075)
+struct bt_hci_cp_le_read_iso_link_quality {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_le_read_iso_link_quality {
+	uint8_t  status;
+	uint16_t handle;
+	uint32_t tx_unacked_packets;
+	uint32_t tx_flushed_packets;
+	uint32_t tx_last_subevent_packets;
+	uint32_t retransmitted_packets;
+	uint32_t crc_error_packets;
+	uint32_t rx_unreceived_packets;
+	uint32_t duplicate_packets;
+} __packed;
+
+/* Event definitions */
+
+#define BT_HCI_EVT_UNKNOWN                      0x00
+#define BT_HCI_EVT_VENDOR                       0xff
+
+#define BT_HCI_EVT_INQUIRY_COMPLETE             0x01
+struct bt_hci_evt_inquiry_complete {
+	uint8_t status;
+} __packed;
+
+#define BT_HCI_EVT_CONN_COMPLETE                0x03
+struct bt_hci_evt_conn_complete {
+	uint8_t   status;
+	uint16_t  handle;
+	bt_addr_t bdaddr;
+	uint8_t   link_type;
+	uint8_t   encr_enabled;
+} __packed;
+
+#define BT_HCI_EVT_CONN_REQUEST                 0x04
+struct bt_hci_evt_conn_request {
+	bt_addr_t bdaddr;
+	uint8_t   dev_class[3];
+	uint8_t   link_type;
+} __packed;
+
+#define BT_HCI_EVT_DISCONN_COMPLETE             0x05
+struct bt_hci_evt_disconn_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_AUTH_COMPLETE                0x06
+struct bt_hci_evt_auth_complete {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE     0x07
+struct bt_hci_evt_remote_name_req_complete {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+	uint8_t   name[248];
+} __packed;
+
+#define BT_HCI_EVT_ENCRYPT_CHANGE               0x08
+struct bt_hci_evt_encrypt_change {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  encrypt;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_FEATURES              0x0b
+struct bt_hci_evt_remote_features {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_VERSION_INFO          0x0c
+struct bt_hci_evt_remote_version_info {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  version;
+	uint16_t manufacturer;
+	uint16_t subversion;
+} __packed;
+
+#define BT_HCI_EVT_CMD_COMPLETE                 0x0e
+struct bt_hci_evt_cmd_complete {
+	uint8_t  ncmd;
+	uint16_t opcode;
+} __packed;
+
+struct bt_hci_evt_cc_status {
+	uint8_t  status;
+} __packed;
+
+#define BT_HCI_EVT_CMD_STATUS                   0x0f
+struct bt_hci_evt_cmd_status {
+	uint8_t  status;
+	uint8_t  ncmd;
+	uint16_t opcode;
+} __packed;
+
+#define BT_HCI_EVT_HARDWARE_ERROR               0x10
+struct bt_hci_evt_hardware_error {
+	uint8_t  hardware_code;
+} __packed;
+
+#define BT_HCI_EVT_ROLE_CHANGE                  0x12
+struct bt_hci_evt_role_change {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+	uint8_t   role;
+} __packed;
+
+#define BT_HCI_EVT_NUM_COMPLETED_PACKETS        0x13
+struct bt_hci_evt_num_completed_packets {
+	uint8_t  num_handles;
+	struct bt_hci_handle_count h[0];
+} __packed;
+
+#define BT_HCI_EVT_PIN_CODE_REQ                 0x16
+struct bt_hci_evt_pin_code_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_LINK_KEY_REQ                 0x17
+struct bt_hci_evt_link_key_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+/* Link Key types */
+#define BT_LK_COMBINATION                       0x00
+#define BT_LK_LOCAL_UNIT                        0x01
+#define BT_LK_REMOTE_UNIT                       0x02
+#define BT_LK_DEBUG_COMBINATION                 0x03
+#define BT_LK_UNAUTH_COMBINATION_P192           0x04
+#define BT_LK_AUTH_COMBINATION_P192             0x05
+#define BT_LK_CHANGED_COMBINATION               0x06
+#define BT_LK_UNAUTH_COMBINATION_P256           0x07
+#define BT_LK_AUTH_COMBINATION_P256             0x08
+
+#define BT_HCI_EVT_LINK_KEY_NOTIFY              0x18
+struct bt_hci_evt_link_key_notify {
+	bt_addr_t bdaddr;
+	uint8_t   link_key[16];
+	uint8_t   key_type;
+} __packed;
+
+/* Overflow link types */
+#define BT_OVERFLOW_LINK_SYNCH                  0x00
+#define BT_OVERFLOW_LINK_ACL                    0x01
+
+#define BT_HCI_EVT_DATA_BUF_OVERFLOW            0x1a
+struct bt_hci_evt_data_buf_overflow {
+	uint8_t  link_type;
+} __packed;
+
+#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI     0x22
+struct bt_hci_evt_inquiry_result_with_rssi {
+	bt_addr_t addr;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint8_t   cod[3];
+	uint16_t  clock_offset;
+	int8_t    rssi;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_EXT_FEATURES          0x23
+struct bt_hci_evt_remote_ext_features {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  page;
+	uint8_t  max_page;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_SYNC_CONN_COMPLETE           0x2c
+struct bt_hci_evt_sync_conn_complete {
+	uint8_t    status;
+	uint16_t   handle;
+	bt_addr_t  bdaddr;
+	uint8_t    link_type;
+	uint8_t    tx_interval;
+	uint8_t    retansmission_window;
+	uint16_t   rx_pkt_length;
+	uint16_t   tx_pkt_length;
+	uint8_t    air_mode;
+} __packed;
+
+#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT      0x2f
+struct bt_hci_evt_extended_inquiry_result {
+	uint8_t    num_reports;
+	bt_addr_t  addr;
+	uint8_t    pscan_rep_mode;
+	uint8_t    reserved;
+	uint8_t    cod[3];
+	uint16_t   clock_offset;
+	int8_t     rssi;
+	uint8_t    eir[240];
+} __packed;
+
+#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30
+struct bt_hci_evt_encrypt_key_refresh_complete {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_IO_CAPA_REQ                  0x31
+struct bt_hci_evt_io_capa_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_IO_CAPA_RESP                 0x32
+struct bt_hci_evt_io_capa_resp {
+	bt_addr_t bdaddr;
+	uint8_t   capability;
+	uint8_t   oob_data;
+	uint8_t   authentication;
+} __packed;
+
+#define BT_HCI_EVT_USER_CONFIRM_REQ             0x33
+struct bt_hci_evt_user_confirm_req {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_EVT_USER_PASSKEY_REQ             0x34
+struct bt_hci_evt_user_passkey_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_SSP_COMPLETE                 0x36
+struct bt_hci_evt_ssp_complete {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_USER_PASSKEY_NOTIFY          0x3b
+struct bt_hci_evt_user_passkey_notify {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_EVT_LE_META_EVENT                0x3e
+struct bt_hci_evt_le_meta_event {
+	uint8_t  subevent;
+} __packed;
+
+#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP     0x57
+struct bt_hci_evt_auth_payload_timeout_exp {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_ROLE_MASTER                      0x00
+#define BT_HCI_ROLE_SLAVE                       0x01
+
+#define BT_HCI_EVT_LE_CONN_COMPLETE             0x01
+struct bt_hci_evt_le_conn_complete {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      role;
+	bt_addr_le_t peer_addr;
+	uint16_t     interval;
+	uint16_t     latency;
+	uint16_t     supv_timeout;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_ADVERTISING_REPORT        0x02
+struct bt_hci_evt_le_advertising_info {
+	uint8_t      evt_type;
+	bt_addr_le_t addr;
+	uint8_t      length;
+	uint8_t      data[0];
+} __packed;
+struct bt_hci_evt_le_advertising_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_advertising_info adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE      0x03
+struct bt_hci_evt_le_conn_update_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t interval;
+	uint16_t latency;
+	uint16_t supv_timeout;
+} __packed;
+
+#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE       0x04
+struct bt_hci_evt_le_remote_feat_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_LE_LTK_REQUEST               0x05
+struct bt_hci_evt_le_ltk_request {
+	uint16_t handle;
+	uint64_t rand;
+	uint16_t ediv;
+} __packed;
+
+#define BT_HCI_EVT_LE_CONN_PARAM_REQ            0x06
+struct bt_hci_evt_le_conn_param_req {
+	uint16_t handle;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+} __packed;
+
+#define BT_HCI_EVT_LE_DATA_LEN_CHANGE           0x07
+struct bt_hci_evt_le_data_len_change {
+	uint16_t handle;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+} __packed;
+
+#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE  0x08
+struct bt_hci_evt_le_p256_public_key_complete {
+	uint8_t status;
+	uint8_t key[64];
+} __packed;
+
+#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE   0x09
+struct bt_hci_evt_le_generate_dhkey_complete {
+	uint8_t status;
+	uint8_t dhkey[32];
+} __packed;
+
+#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE         0x0a
+struct bt_hci_evt_le_enh_conn_complete {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      role;
+	bt_addr_le_t peer_addr;
+	bt_addr_t    local_rpa;
+	bt_addr_t    peer_rpa;
+	uint16_t     interval;
+	uint16_t     latency;
+	uint16_t     supv_timeout;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT         0x0b
+struct bt_hci_evt_le_direct_adv_info {
+	uint8_t      evt_type;
+	bt_addr_le_t addr;
+	bt_addr_le_t dir_addr;
+	int8_t       rssi;
+} __packed;
+struct bt_hci_evt_le_direct_adv_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_direct_adv_info direct_adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE       0x0c
+struct bt_hci_evt_le_phy_update_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  tx_phy;
+	uint8_t  rx_phy;
+} __packed;
+
+#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT    0x0d
+
+#define BT_HCI_LE_ADV_EVT_TYPE_CONN                 BIT(0)
+#define BT_HCI_LE_ADV_EVT_TYPE_SCAN                 BIT(1)
+#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT               BIT(2)
+#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP             BIT(3)
+#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY               BIT(4)
+
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03)
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE   0
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL    1
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2
+
+struct bt_hci_evt_le_ext_advertising_info {
+	uint16_t     evt_type;
+	bt_addr_le_t addr;
+	uint8_t      prim_phy;
+	uint8_t      sec_phy;
+	uint8_t      sid;
+	int8_t       tx_power;
+	int8_t       rssi;
+	uint16_t     interval;
+	bt_addr_le_t direct_addr;
+	uint8_t      length;
+	uint8_t      data[0];
+} __packed;
+struct bt_hci_evt_le_ext_advertising_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_ext_advertising_info adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED  0x0e
+struct bt_hci_evt_le_per_adv_sync_established {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      sid;
+	bt_addr_le_t adv_addr;
+	uint8_t      phy;
+	uint16_t     interval;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT    0x0f
+struct bt_hci_evt_le_per_advertising_report {
+	uint16_t handle;
+	int8_t   tx_power;
+	int8_t   rssi;
+	uint8_t  cte_type;
+	uint8_t  data_status;
+	uint8_t  length;
+	uint8_t  data[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST         0x10
+struct bt_hci_evt_le_per_adv_sync_lost {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_LE_SCAN_TIMEOUT              0x11
+
+#define BT_HCI_EVT_LE_ADV_SET_TERMINATED        0x12
+struct bt_hci_evt_le_adv_set_terminated {
+	uint8_t  status;
+	uint8_t  adv_handle;
+	uint16_t conn_handle;
+	uint8_t  num_completed_ext_adv_evts;
+} __packed;
+
+#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED         0x13
+struct bt_hci_evt_le_scan_req_received {
+	uint8_t      handle;
+	bt_addr_le_t addr;
+} __packed;
+
+#define BT_HCI_LE_CHAN_SEL_ALGO_1               0x00
+#define BT_HCI_LE_CHAN_SEL_ALGO_2               0x01
+
+#define BT_HCI_EVT_LE_CHAN_SEL_ALGO             0x14
+struct bt_hci_evt_le_chan_sel_algo {
+	uint16_t handle;
+	uint8_t  chan_sel_algo;
+} __packed;
+
+#define BT_HCI_EVT_LE_CIS_ESTABLISHED           0x19
+struct bt_hci_evt_le_cis_established {
+	uint8_t  status;
+	uint16_t conn_handle;
+	uint8_t  cig_sync_delay[3];
+	uint8_t  cis_sync_delay[3];
+	uint8_t  m_latency[3];
+	uint8_t  s_latency[3];
+	uint8_t  m_phy;
+	uint8_t  s_phy;
+	uint8_t  nse;
+	uint8_t  m_bn;
+	uint8_t  s_bn;
+	uint8_t  m_ft;
+	uint8_t  s_ft;
+	uint16_t m_max_pdu;
+	uint16_t s_max_pdu;
+	uint16_t interval;
+} __packed;
+
+#define BT_HCI_EVT_LE_CIS_REQ                   0x1a
+struct bt_hci_evt_le_cis_req {
+	uint16_t acl_handle;
+	uint16_t cis_handle;
+	uint8_t  cig_id;
+	uint8_t  cis_id;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_COMPLETE              0x1b
+struct bt_hci_evt_le_big_complete {
+	uint8_t  status;
+	uint8_t  big_handle;
+	uint8_t  sync_delay[3];
+	uint8_t  latency[3];
+	uint8_t  phy;
+	uint8_t  nse;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  num_bis;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_TERMINATE             0x1c
+struct bt_hci_evt_le_big_terminate {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED      0x1d
+struct bt_hci_evt_le_big_sync_established {
+	uint8_t  status;
+	uint8_t  big_handle;
+	uint8_t  latency[3];
+	uint8_t  nse;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  num_bis;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_SYNC_LOST             0x1e
+struct bt_hci_evt_le_big_sync_lost {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE     0x1f
+struct bt_hci_evt_le_req_peer_sca_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  sca;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIGINFO_ADV_REPORT        0x22
+struct bt_hci_evt_le_biginfo_adv_report {
+	uint16_t sync_handle;
+	uint8_t  num_bis;
+	uint8_t  nse;
+	uint16_t iso_interval;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  sdu_interval[3];
+	uint16_t max_sdu;
+	uint8_t  phy;
+	uint8_t  framing;
+	uint8_t  encryption;
+} __packed;
+
+/* Event mask bits */
+
+#define BT_EVT_BIT(n) (1ULL << (n))
+
+#define BT_EVT_MASK_INQUIRY_COMPLETE             BT_EVT_BIT(0)
+#define BT_EVT_MASK_CONN_COMPLETE                BT_EVT_BIT(2)
+#define BT_EVT_MASK_CONN_REQUEST                 BT_EVT_BIT(3)
+#define BT_EVT_MASK_DISCONN_COMPLETE             BT_EVT_BIT(4)
+#define BT_EVT_MASK_AUTH_COMPLETE                BT_EVT_BIT(5)
+#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE     BT_EVT_BIT(6)
+#define BT_EVT_MASK_ENCRYPT_CHANGE               BT_EVT_BIT(7)
+#define BT_EVT_MASK_REMOTE_FEATURES              BT_EVT_BIT(10)
+#define BT_EVT_MASK_REMOTE_VERSION_INFO          BT_EVT_BIT(11)
+#define BT_EVT_MASK_HARDWARE_ERROR               BT_EVT_BIT(15)
+#define BT_EVT_MASK_ROLE_CHANGE                  BT_EVT_BIT(17)
+#define BT_EVT_MASK_PIN_CODE_REQ                 BT_EVT_BIT(21)
+#define BT_EVT_MASK_LINK_KEY_REQ                 BT_EVT_BIT(22)
+#define BT_EVT_MASK_LINK_KEY_NOTIFY              BT_EVT_BIT(23)
+#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW         BT_EVT_BIT(25)
+#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI     BT_EVT_BIT(33)
+#define BT_EVT_MASK_REMOTE_EXT_FEATURES          BT_EVT_BIT(34)
+#define BT_EVT_MASK_SYNC_CONN_COMPLETE           BT_EVT_BIT(43)
+#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT      BT_EVT_BIT(46)
+#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47)
+#define BT_EVT_MASK_IO_CAPA_REQ                  BT_EVT_BIT(48)
+#define BT_EVT_MASK_IO_CAPA_RESP                 BT_EVT_BIT(49)
+#define BT_EVT_MASK_USER_CONFIRM_REQ             BT_EVT_BIT(50)
+#define BT_EVT_MASK_USER_PASSKEY_REQ             BT_EVT_BIT(51)
+#define BT_EVT_MASK_SSP_COMPLETE                 BT_EVT_BIT(53)
+#define BT_EVT_MASK_USER_PASSKEY_NOTIFY          BT_EVT_BIT(58)
+#define BT_EVT_MASK_LE_META_EVENT                BT_EVT_BIT(61)
+
+/* Page 2 */
+#define BT_EVT_MASK_PHY_LINK_COMPLETE            BT_EVT_BIT(0)
+#define BT_EVT_MASK_CH_SELECTED_COMPLETE         BT_EVT_BIT(1)
+#define BT_EVT_MASK_DISCONN_PHY_LINK_COMPLETE    BT_EVT_BIT(2)
+#define BT_EVT_MASK_PHY_LINK_LOSS_EARLY_WARN     BT_EVT_BIT(3)
+#define BT_EVT_MASK_PHY_LINK_RECOVERY            BT_EVT_BIT(4)
+#define BT_EVT_MASK_LOG_LINK_COMPLETE            BT_EVT_BIT(5)
+#define BT_EVT_MASK_DISCONN_LOG_LINK_COMPLETE    BT_EVT_BIT(6)
+#define BT_EVT_MASK_FLOW_SPEC_MODIFY_COMPLETE    BT_EVT_BIT(7)
+#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS     BT_EVT_BIT(8)
+#define BT_EVT_MASK_AMP_START_TEST               BT_EVT_BIT(9)
+#define BT_EVT_MASK_AMP_TEST_END                 BT_EVT_BIT(10)
+#define BT_EVT_MASK_AMP_RX_REPORT                BT_EVT_BIT(11)
+#define BT_EVT_MASK_AMP_SR_MODE_CHANGE_COMPLETE  BT_EVT_BIT(12)
+#define BT_EVT_MASK_AMP_STATUS_CHANGE            BT_EVT_BIT(13)
+#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE          BT_EVT_BIT(14)
+#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE         BT_EVT_BIT(15)
+#define BT_EVT_MASK_SYNCH_TRAIN_RX               BT_EVT_BIT(16)
+#define BT_EVT_MASK_CL_SLAVE_BC_RX               BT_EVT_BIT(17)
+#define BT_EVT_MASK_CL_SLAVE_BC_TIMEOUT          BT_EVT_BIT(18)
+#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE          BT_EVT_BIT(19)
+#define BT_EVT_MASK_SLAVE_PAGE_RSP_TIMEOUT       BT_EVT_BIT(20)
+#define BT_EVT_MASK_CL_SLAVE_BC_CH_MAP_CHANGE    BT_EVT_BIT(21)
+#define BT_EVT_MASK_INQUIRY_RSP_NOT              BT_EVT_BIT(22)
+#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP     BT_EVT_BIT(23)
+#define BT_EVT_MASK_SAM_STATUS_CHANGE            BT_EVT_BIT(24)
+
+#define BT_EVT_MASK_LE_CONN_COMPLETE             BT_EVT_BIT(0)
+#define BT_EVT_MASK_LE_ADVERTISING_REPORT        BT_EVT_BIT(1)
+#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE      BT_EVT_BIT(2)
+#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE      BT_EVT_BIT(3)
+#define BT_EVT_MASK_LE_LTK_REQUEST               BT_EVT_BIT(4)
+#define BT_EVT_MASK_LE_CONN_PARAM_REQ            BT_EVT_BIT(5)
+#define BT_EVT_MASK_LE_DATA_LEN_CHANGE           BT_EVT_BIT(6)
+#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE  BT_EVT_BIT(7)
+#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE   BT_EVT_BIT(8)
+#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE         BT_EVT_BIT(9)
+#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT         BT_EVT_BIT(10)
+#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE       BT_EVT_BIT(11)
+#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT    BT_EVT_BIT(12)
+#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED  BT_EVT_BIT(13)
+#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT    BT_EVT_BIT(14)
+#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST         BT_EVT_BIT(15)
+#define BT_EVT_MASK_LE_SCAN_TIMEOUT              BT_EVT_BIT(16)
+#define BT_EVT_MASK_LE_ADV_SET_TERMINATED        BT_EVT_BIT(17)
+#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED         BT_EVT_BIT(18)
+#define BT_EVT_MASK_LE_CHAN_SEL_ALGO             BT_EVT_BIT(19)
+#define BT_EVT_MASK_LE_CIS_ESTABLISHED           BT_EVT_BIT(24)
+#define BT_EVT_MASK_LE_CIS_REQ                   BT_EVT_BIT(25)
+#define BT_EVT_MASK_LE_BIG_COMPLETE              BT_EVT_BIT(26)
+#define BT_EVT_MASK_LE_BIG_TERMINATED            BT_EVT_BIT(27)
+#define BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED      BT_EVT_BIT(28)
+#define BT_EVT_MASK_LE_BIG_SYNC_LOST             BT_EVT_BIT(29)
+#define BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE     BT_EVT_BIT(30)
+#define BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD       BT_EVT_BIT(31)
+#define BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING  BT_EVT_BIT(32)
+#define BT_EVT_MASK_LE_BIGINFO_ADV_REPORT        BT_EVT_BIT(33)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _YC11XX_HCI_H_ */
Index: ModuleDemo/BLE/CM0/User/hci/yc11xx_hci_err.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_hci_err.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/hci/yc11xx_hci_err.h	(working copy)
@@ -0,0 +1,92 @@
+/** @file
+ *  @brief Bluetooth Host Control Interface status codes.
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _YC11XX_HCI_ERR_H_
+#define _YC11XX_HCI_ERR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */
+#define BT_HCI_ERR_SUCCESS                      0x00
+#define BT_HCI_ERR_UNKNOWN_CMD                  0x01
+#define BT_HCI_ERR_UNKNOWN_CONN_ID              0x02
+#define BT_HCI_ERR_HW_FAILURE                   0x03
+#define BT_HCI_ERR_PAGE_TIMEOUT                 0x04
+#define BT_HCI_ERR_AUTH_FAIL                    0x05
+#define BT_HCI_ERR_PIN_OR_KEY_MISSING           0x06
+#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED        0x07
+#define BT_HCI_ERR_CONN_TIMEOUT                 0x08
+#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED          0x09
+#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED     0x0a
+#define BT_HCI_ERR_CONN_ALREADY_EXISTS          0x0b
+#define BT_HCI_ERR_CMD_DISALLOWED               0x0c
+#define BT_HCI_ERR_INSUFFICIENT_RESOURCES       0x0d
+#define BT_HCI_ERR_INSUFFICIENT_SECURITY        0x0e
+#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE         0x0f
+#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT          0x10
+#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL     0x11
+#define BT_HCI_ERR_INVALID_PARAM                0x12
+#define BT_HCI_ERR_REMOTE_USER_TERM_CONN        0x13
+#define BT_HCI_ERR_REMOTE_LOW_RESOURCES         0x14
+#define BT_HCI_ERR_REMOTE_POWER_OFF             0x15
+#define BT_HCI_ERR_LOCALHOST_TERM_CONN          0x16
+#define BT_HCI_ERR_REPEATED_ATTEMPTS            0x17
+#define BT_HCI_ERR_PAIRING_NOT_ALLOWED          0x18
+#define BT_HCI_ERR_UNKNOWN_LMP_PDU              0x19
+#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE        0x1a
+#define BT_HCI_ERR_SCO_OFFSET_REJECTED          0x1b
+#define BT_HCI_ERR_SCO_INTERVAL_REJECTED        0x1c
+#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED        0x1d
+#define BT_HCI_ERR_INVALID_LL_PARAM             0x1e
+#define BT_HCI_ERR_UNSPECIFIED                  0x1f
+#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL          0x20
+#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED      0x21
+#define BT_HCI_ERR_LL_RESP_TIMEOUT              0x22
+#define BT_HCI_ERR_LL_PROC_COLLISION            0x23
+#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED          0x24
+#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE      0x25
+#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED   0x26
+#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED  0x27
+#define BT_HCI_ERR_INSTANT_PASSED               0x28
+#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED        0x29
+#define BT_HCI_ERR_DIFF_TRANS_COLLISION         0x2a
+#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM       0x2c
+#define BT_HCI_ERR_QOS_REJECTED                 0x2d
+#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED    0x2e
+#define BT_HCI_ERR_INSUFF_SECURITY              0x2f
+#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30
+#define BT_HCI_ERR_ROLE_SWITCH_PENDING          0x32
+#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION      0x34
+#define BT_HCI_ERR_ROLE_SWITCH_FAILED           0x35
+#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE       0x36
+#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37
+#define BT_HCI_ERR_HOST_BUSY_PAIRING            0x38
+#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39
+#define BT_HCI_ERR_CONTROLLER_BUSY              0x3a
+#define BT_HCI_ERR_UNACCEPT_CONN_PARAM          0x3b
+#define BT_HCI_ERR_ADV_TIMEOUT                  0x3c
+#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL         0x3d
+#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB           0x3e
+#define BT_HCI_ERR_MAC_CONN_FAILED              0x3f
+#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED        0x40
+#define BT_HCI_ERR_SUBMAP_NOT_DEFINED           0x41
+#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER       0x42
+#define BT_HCI_ERR_LIMIT_REACHED                0x43
+#define BT_HCI_ERR_OP_CANCELLED_BY_HOST         0x44
+#define BT_HCI_ERR_PACKET_TOO_LONG              0x45
+
+#define BT_HCI_ERR_AUTHENTICATION_FAIL __DEPRECATED_MACRO BT_HCI_ERR_AUTH_FAIL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _YC11XX_HCI_ERR_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp-codec.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp-codec.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp-codec.h	(working copy)
@@ -0,0 +1,73 @@
+/** @file
+ * @brief Advance Audio Distribution Profile - SBC Codec header.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Sampling Frequency */
+#define A2DP_SBC_SAMP_FREQ_16000 BIT(7)
+#define A2DP_SBC_SAMP_FREQ_32000 BIT(6)
+#define A2DP_SBC_SAMP_FREQ_44100 BIT(5)
+#define A2DP_SBC_SAMP_FREQ_48000 BIT(4)
+
+/* Channel Mode */
+#define A2DP_SBC_CH_MODE_MONO  BIT(3)
+#define A2DP_SBC_CH_MODE_DUAL  BIT(2)
+#define A2DP_SBC_CH_MODE_STREO BIT(1)
+#define A2DP_SBC_CH_MODE_JOINT BIT(0)
+
+/* Block Length */
+#define A2DP_SBC_BLK_LEN_4  BIT(7)
+#define A2DP_SBC_BLK_LEN_8  BIT(6)
+#define A2DP_SBC_BLK_LEN_12 BIT(5)
+#define A2DP_SBC_BLK_LEN_16 BIT(4)
+
+/* Subbands */
+#define A2DP_SBC_SUBBAND_4 BIT(3)
+#define A2DP_SBC_SUBBAND_8 BIT(2)
+
+/* Allocation Method */
+#define A2DP_SBC_ALLOC_MTHD_SNR      BIT(1)
+#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0)
+
+#define BT_A2DP_SBC_SAMP_FREQ(preset)    ((preset->config[0] >> 4) & 0x0f)
+#define BT_A2DP_SBC_CHAN_MODE(preset)    ((preset->config[0]) & 0x0f)
+#define BT_A2DP_SBC_BLK_LEN(preset)      ((preset->config[1] >> 4) & 0x0f)
+#define BT_A2DP_SBC_SUB_BAND(preset)     ((preset->config[1] >> 2) & 0x03)
+#define BT_A2DP_SBC_ALLOC_MTHD(preset)   ((preset->config[1]) & 0x03)
+
+/** @brief SBC Codec */
+struct bt_a2dp_codec_sbc_params {
+	/** First two octets of configuration */
+	uint8_t config[2];
+	/** Minimum Bitpool Value */
+	uint8_t min_bitpool;
+	/** Maximum Bitpool Value */
+	uint8_t max_bitpool;
+} __packed;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/a2dp.h	(working copy)
@@ -0,0 +1,111 @@
+/** @file
+ * @brief Advance Audio Distribution Profile header.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_H_
+
+#include <bluetooth/avdtp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Stream Structure */
+struct bt_a2dp_stream {
+	/* TODO */
+};
+
+/** @brief Codec ID */
+enum bt_a2dp_codec_id {
+	/** Codec SBC */
+	BT_A2DP_SBC = 0x00,
+	/** Codec MPEG-1 */
+	BT_A2DP_MPEG1 = 0x01,
+	/** Codec MPEG-2 */
+	BT_A2DP_MPEG2 = 0x02,
+	/** Codec ATRAC */
+	BT_A2DP_ATRAC = 0x04,
+	/** Codec Non-A2DP */
+	BT_A2DP_VENDOR = 0xff
+};
+
+/** @brief Preset for the endpoint */
+struct bt_a2dp_preset {
+	/** Length of preset */
+	uint8_t len;
+	/** Preset */
+	uint8_t preset[0];
+};
+
+/** @brief Stream End Point */
+struct bt_a2dp_endpoint {
+	/** Code ID */
+	uint8_t codec_id;
+	/** Stream End Point Information */
+	struct bt_avdtp_seid_lsep info;
+	/** Pointer to preset codec chosen */
+	struct bt_a2dp_preset *preset;
+	/** Capabilities */
+	struct bt_a2dp_preset *caps;
+};
+
+/** @brief Stream End Point Media Type */
+enum MEDIA_TYPE {
+	/** Audio Media Type */
+	BT_A2DP_AUDIO = 0x00,
+	/** Video Media Type */
+	BT_A2DP_VIDEO = 0x01,
+	/** Multimedia Media Type */
+	BT_A2DP_MULTIMEDIA = 0x02
+};
+
+/** @brief Stream End Point Role */
+enum ROLE_TYPE {
+	/** Source Role */
+	BT_A2DP_SOURCE = 0,
+	/** Sink Role */
+	BT_A2DP_SINK = 1
+};
+
+/** @brief A2DP structure */
+struct bt_a2dp;
+
+/** @brief A2DP Connect.
+ *
+ *  This function is to be called after the conn parameter is obtained by
+ *  performing a GAP procedure. The API is to be used to establish A2DP
+ *  connection between devices.
+ *
+ *  @param conn Pointer to bt_conn structure.
+ *
+ *  @return pointer to struct bt_a2dp in case of success or NULL in case
+ *  of error.
+ */
+struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn);
+
+/** @brief Endpoint Registration.
+ *
+ *  This function is used for registering the stream end points. The user has
+ *  to take care of allocating the memory, the preset pointer and then pass the
+ *  required arguments. Also, only one sep can be registered at a time.
+ *
+ *  @param endpoint Pointer to bt_a2dp_endpoint structure.
+ *  @param media_type Media type that the Endpoint is.
+ *  @param role Role of Endpoint.
+ *
+ *  @return 0 in case of success and error code in case of error.
+ */
+int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint,
+			      uint8_t media_type, uint8_t role);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/addr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/addr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/addr.h	(working copy)
@@ -0,0 +1,107 @@
+/** @file
+ *  @brief Bluetooth device address definitions and utilities.
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_
+
+#include <string.h>
+#include <types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Bluetooth device address definitions and utilities.
+ * @defgroup bt_addr Device Address
+ * @ingroup bluetooth
+ * @{
+ */
+
+#define BT_ADDR_LE_PUBLIC       0x00
+#define BT_ADDR_LE_RANDOM       0x01
+#define BT_ADDR_LE_PUBLIC_ID    0x02
+#define BT_ADDR_LE_RANDOM_ID    0x03
+
+/** Bluetooth Device Address */
+typedef struct {
+	uint8_t  val[6];
+} bt_addr_t;
+
+/** Bluetooth LE Device Address */
+typedef struct {
+	uint8_t      type;
+	bt_addr_t a;
+} bt_addr_le_t;
+
+#define BT_ADDR_ANY     ((bt_addr_t[]) { { { 0, 0, 0, 0, 0, 0 } } })
+#define BT_ADDR_NONE    ((bt_addr_t[]) { { \
+			 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } })
+#define BT_ADDR_LE_ANY  ((bt_addr_le_t[]) { { 0, { { 0, 0, 0, 0, 0, 0 } } } })
+#define BT_ADDR_LE_NONE ((bt_addr_le_t[]) { { 0, \
+			 { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } })
+
+static inline int bt_addr_cmp(const bt_addr_t *a, const bt_addr_t *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+
+static inline int bt_addr_le_cmp(const bt_addr_le_t *a, const bt_addr_le_t *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+
+static inline void bt_addr_copy(bt_addr_t *dst, const bt_addr_t *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void bt_addr_le_copy(bt_addr_le_t *dst, const bt_addr_le_t *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+#define BT_ADDR_IS_RPA(a)     (((a)->val[5] & 0xc0) == 0x40)
+#define BT_ADDR_IS_NRPA(a)    (((a)->val[5] & 0xc0) == 0x00)
+#define BT_ADDR_IS_STATIC(a)  (((a)->val[5] & 0xc0) == 0xc0)
+
+#define BT_ADDR_SET_RPA(a)    ((a)->val[5] = (((a)->val[5] & 0x3f) | 0x40))
+#define BT_ADDR_SET_NRPA(a)   ((a)->val[5] &= 0x3f)
+#define BT_ADDR_SET_STATIC(a) ((a)->val[5] |= 0xc0)
+
+int bt_addr_le_create_nrpa(bt_addr_le_t *addr);
+int bt_addr_le_create_static(bt_addr_le_t *addr);
+
+static inline bool bt_addr_le_is_rpa(const bt_addr_le_t *addr)
+{
+	if (addr->type != BT_ADDR_LE_RANDOM) {
+		return false;
+	}
+
+	return BT_ADDR_IS_RPA(&addr->a);
+}
+
+static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr)
+{
+	if (addr->type == BT_ADDR_LE_PUBLIC) {
+		return true;
+	}
+
+	return BT_ADDR_IS_STATIC(&addr->a);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ADDR_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/att.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/att.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/att.h	(working copy)
@@ -0,0 +1,54 @@
+/** @file
+ *  @brief Attribute Protocol handling.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_
+
+#include <sys/slist.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Error codes for Error response PDU */
+#define BT_ATT_ERR_SUCCESS			0x00
+#define BT_ATT_ERR_INVALID_HANDLE		0x01
+#define BT_ATT_ERR_READ_NOT_PERMITTED		0x02
+#define BT_ATT_ERR_WRITE_NOT_PERMITTED		0x03
+#define BT_ATT_ERR_INVALID_PDU			0x04
+#define BT_ATT_ERR_AUTHENTICATION		0x05
+#define BT_ATT_ERR_NOT_SUPPORTED		0x06
+#define BT_ATT_ERR_INVALID_OFFSET		0x07
+#define BT_ATT_ERR_AUTHORIZATION		0x08
+#define BT_ATT_ERR_PREPARE_QUEUE_FULL		0x09
+#define BT_ATT_ERR_ATTRIBUTE_NOT_FOUND		0x0a
+#define BT_ATT_ERR_ATTRIBUTE_NOT_LONG		0x0b
+#define BT_ATT_ERR_ENCRYPTION_KEY_SIZE		0x0c
+#define BT_ATT_ERR_INVALID_ATTRIBUTE_LEN	0x0d
+#define BT_ATT_ERR_UNLIKELY			0x0e
+#define BT_ATT_ERR_INSUFFICIENT_ENCRYPTION	0x0f
+#define BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE	0x10
+#define BT_ATT_ERR_INSUFFICIENT_RESOURCES	0x11
+#define BT_ATT_ERR_DB_OUT_OF_SYNC		0x12
+#define BT_ATT_ERR_VALUE_NOT_ALLOWED		0x13
+
+/* Common Profile Error Codes (from CSS) */
+#define BT_ATT_ERR_WRITE_REQ_REJECTED		0xfc
+#define BT_ATT_ERR_CCC_IMPROPER_CONF		0xfd
+#define BT_ATT_ERR_PROCEDURE_IN_PROGRESS	0xfe
+#define BT_ATT_ERR_OUT_OF_RANGE			0xff
+
+/* Version 5.2, Vol 3, Part F, 3.2.9 defines maximum attribute length to 512 */
+#define BT_ATT_MAX_ATTRIBUTE_LEN		512
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ATT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/avdtp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/avdtp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/avdtp.h	(working copy)
@@ -0,0 +1,54 @@
+/** @file
+ * @brief Audio/Video Distribution Transport Protocol header.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief AVDTP SEID Information */
+struct bt_avdtp_seid_info {
+	/** Stream End Point ID */
+	uint8_t id:6;
+	/** End Point usage status */
+	uint8_t inuse:1;
+	/** Reserved */
+	uint8_t rfa0:1;
+	/** Media-type of the End Point */
+	uint8_t media_type:4;
+	/** TSEP of the End Point */
+	uint8_t tsep:1;
+	/** Reserved */
+	uint8_t rfa1:3;
+} __packed;
+
+/** @brief AVDTP Local SEP*/
+struct bt_avdtp_seid_lsep {
+	/** Stream End Point information */
+	struct bt_avdtp_seid_info sep;
+	/** Pointer to next local Stream End Point structure */
+	struct bt_avdtp_seid_lsep *next;
+};
+
+/** @brief AVDTP Stream */
+struct bt_avdtp_stream {
+	struct bt_l2cap_br_chan chan; /* Transport Channel*/
+	struct bt_avdtp_seid_info lsep; /* Configured Local SEP */
+	struct bt_avdtp_seid_info rsep; /* Configured Remote SEP*/
+	uint8_t state; /* current state of the stream */
+	struct bt_avdtp_stream *next;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/bluetooth.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/bluetooth.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/bluetooth.h	(working copy)
@@ -0,0 +1,1812 @@
+/** @file
+ *  @brief Bluetooth subsystem core APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_BLUETOOTH_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_BLUETOOTH_H_
+
+/**
+ * @brief Bluetooth APIs
+ * @defgroup bluetooth Bluetooth APIs
+ * @{
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <sys/util.h>
+#include <net/buf.h>
+#include <bluetooth/gap.h>
+#include <bluetooth/addr.h>
+#include <bluetooth/crypto.h>
+#include <config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Generic Access Profile
+ * @defgroup bt_gap Generic Access Profile
+ * @ingroup bluetooth
+ * @{
+ */
+
+/**
+ * @def BT_ID_DEFAULT
+ *
+ * Convenience macro for specifying the default identity. This helps
+ * make the code more readable, especially when only one identity is
+ * supported.
+ */
+#define BT_ID_DEFAULT 0
+
+/** Opaque type representing an advertiser. */
+struct bt_le_ext_adv;
+
+/** Opaque type representing an periodic advertising sync. */
+struct bt_le_per_adv_sync;
+
+/* Don't require everyone to include conn.h */
+struct bt_conn;
+
+struct bt_le_ext_adv_sent_info {
+	/** The number of advertising events completed. */
+	uint8_t num_sent;
+};
+
+struct bt_le_ext_adv_connected_info {
+	/** Connection object of the new connection */
+	struct bt_conn *conn;
+};
+
+struct bt_le_ext_adv_scanned_info {
+	/** Active scanner LE address and type */
+	bt_addr_le_t *addr;
+};
+
+struct bt_le_ext_adv_cb {
+	/**
+	 * @brief The advertising set has finished sending adv data.
+	 *
+	 * This callback notifies the application that the advertising set has
+	 * finished sending advertising data.
+	 * The advertising set can either have been stopped by a timeout or
+	 * because the specified number of advertising events has been reached.
+	 *
+	 * @param adv  The advertising set object.
+	 * @param info Information about the sent event.
+	 */
+	void (*sent)(struct bt_le_ext_adv *adv,
+		     struct bt_le_ext_adv_sent_info *info);
+
+	/**
+	 * @brief The advertising set has accepted a new connection.
+	 *
+	 * This callback notifies the application that the advertising set has
+	 * accepted a new connection.
+	 *
+	 * @param adv  The advertising set object.
+	 * @param info Information about the connected event.
+	 */
+	void (*connected)(struct bt_le_ext_adv *adv,
+			  struct bt_le_ext_adv_connected_info *info);
+
+	/**
+	 * @brief The advertising set has sent scan response data.
+	 *
+	 * This callback notifies the application that the advertising set has
+	 * has received a Scan Request packet, and has sent a Scan Response
+	 * packet.
+	 *
+	 * @param adv  The advertising set object.
+	 * @param addr Information about the scanned event.
+	 */
+	void (*scanned)(struct bt_le_ext_adv *adv,
+			struct bt_le_ext_adv_scanned_info *info);
+};
+
+/**
+ * @typedef bt_ready_cb_t
+ * @brief Callback for notifying that Bluetooth has been enabled.
+ *
+ * @param err zero on success or (negative) error code otherwise.
+ */
+typedef void (*bt_ready_cb_t)(int err);
+
+/**
+ * @brief Enable Bluetooth
+ *
+ * Enable Bluetooth. Must be the called before any calls that
+ * require communication with the local Bluetooth hardware.
+ *
+ * @param cb Callback to notify completion or NULL to perform the
+ * enabling synchronously.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_enable(bt_ready_cb_t cb);
+
+/**
+ * @brief Set Bluetooth Device Name
+ *
+ * Set Bluetooth GAP Device Name.
+ *
+ * @param name New name
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_set_name(const char *name);
+
+/**
+ * @brief Get Bluetooth Device Name
+ *
+ * Get Bluetooth GAP Device Name.
+ *
+ * @return Bluetooth Device Name
+ */
+const char *bt_get_name(void);
+
+/**
+ * @brief Set the local Identity Address
+ *
+ * Allows setting the local Identity Address from the application.
+ * This API must be called before calling bt_enable(). Calling it at any
+ * other time will cause it to fail. In most cases the application doesn't
+ * need to use this API, however there are a few valid cases where
+ * it can be useful (such as for testing).
+ *
+ * At the moment, the given address must be a static random address. In the
+ * future support for public addresses may be added.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_set_id_addr(const bt_addr_le_t *addr);
+
+/**
+ * @brief Get the currently configured identities.
+ *
+ * Returns an array of the currently configured identity addresses. To
+ * make sure all available identities can be retrieved, the number of
+ * elements in the @a addrs array should be CONFIG_BT_ID_MAX. The identity
+ * identifier that some APIs expect (such as advertising parameters) is
+ * simply the index of the identity in the @a addrs array.
+ *
+ * @note Deleted identities may show up as BT_LE_ADDR_ANY in the returned
+ * array.
+ *
+ * @param addrs Array where to store the configured identities.
+ * @param count Should be initialized to the array size. Once the function
+ *              returns it will contain the number of returned identities.
+ */
+void bt_id_get(bt_addr_le_t *addrs, size_t *count);
+
+/**
+ * @brief Create a new identity.
+ *
+ * Create a new identity using the given address and IRK. This function
+ * can be called before calling bt_enable(), in which case it can be used
+ * to override the controller's public address (in case it has one). However,
+ * the new identity will only be stored persistently in flash when this API
+ * is used after bt_enable(). The reason is that the persistent settings
+ * are loaded after bt_enable() and would therefore cause potential conflicts
+ * with the stack blindly overwriting what's stored in flash. The identity
+ * will also not be written to flash in case a pre-defined address is
+ * provided, since in such a situation the app clearly has some place it got
+ * the address from and will be able to repeat the procedure on every power
+ * cycle, i.e. it would be redundant to also store the information in flash.
+ *
+ * If the application wants to have the stack randomly generate identities
+ * and store them in flash for later recovery, the way to do it would be
+ * to first initialize the stack (using bt_enable), then call settings_load(),
+ * and after that check with bt_id_get() how many identities were recovered.
+ * If an insufficient amount of identities were recovered the app may then
+ * call bt_id_create() to create new ones.
+ *
+ * @param addr Address to use for the new identity. If NULL or initialized
+ *             to BT_ADDR_LE_ANY the stack will generate a new static
+ *             random address for the identity and copy it to the given
+ *             parameter upon return from this function (in case the
+ *             parameter was non-NULL).
+ * @param irk  Identity Resolving Key (16 bytes) to be used with this
+ *             identity. If set to all zeroes or NULL, the stack will
+ *             generate a random IRK for the identity and copy it back
+ *             to the parameter upon return from this function (in case
+ *             the parameter was non-NULL). If privacy
+ *             @option{CONFIG_BT_PRIVACY} is not enabled this parameter must
+ *             be NULL.
+ *
+ * @return Identity identifier (>= 0) in case of success, or a negative
+ *         error code on failure.
+ */
+int bt_id_create(bt_addr_le_t *addr, uint8_t *irk);
+
+/**
+ * @brief Reset/reclaim an identity for reuse.
+ *
+ * The semantics of the @a addr and @a irk parameters of this function
+ * are the same as with bt_id_create(). The difference is the first
+ * @a id parameter that needs to be an existing identity (if it doesn't
+ * exist this function will return an error). When given an existing
+ * identity this function will disconnect any connections created using it,
+ * remove any pairing keys or other data associated with it, and then create
+ * a new identity in the same slot, based on the @a addr and @a irk
+ * parameters.
+ *
+ * @note the default identity (BT_ID_DEFAULT) cannot be reset, i.e. this
+ * API will return an error if asked to do that.
+ *
+ * @param id   Existing identity identifier.
+ * @param addr Address to use for the new identity. If NULL or initialized
+ *             to BT_ADDR_LE_ANY the stack will generate a new static
+ *             random address for the identity and copy it to the given
+ *             parameter upon return from this function (in case the
+ *             parameter was non-NULL).
+ * @param irk  Identity Resolving Key (16 bytes) to be used with this
+ *             identity. If set to all zeroes or NULL, the stack will
+ *             generate a random IRK for the identity and copy it back
+ *             to the parameter upon return from this function (in case
+ *             the parameter was non-NULL). If privacy
+ *             @option{CONFIG_BT_PRIVACY} is not enabled this parameter must
+ *             be NULL.
+ *
+ * @return Identity identifier (>= 0) in case of success, or a negative
+ *         error code on failure.
+ */
+int bt_id_reset(uint8_t id, bt_addr_le_t *addr, uint8_t *irk);
+
+/**
+ * @brief Delete an identity.
+ *
+ * When given a valid identity this function will disconnect any connections
+ * created using it, remove any pairing keys or other data associated with
+ * it, and then flag is as deleted, so that it can not be used for any
+ * operations. To take back into use the slot the identity was occupying the
+ * bt_id_reset() API needs to be used.
+ *
+ * @note the default identity (BT_ID_DEFAULT) cannot be deleted, i.e. this
+ * API will return an error if asked to do that.
+ *
+ * @param id   Existing identity identifier.
+ *
+ * @return 0 in case of success, or a negative error code on failure.
+ */
+int bt_id_delete(uint8_t id);
+
+/**
+ * @brief Bluetooth data.
+ *
+ * Description of different data types that can be encoded into
+ * advertising data. Used to form arrays that are passed to the
+ * bt_le_adv_start() function.
+ */
+struct bt_data {
+	uint8_t type;
+	uint8_t data_len;
+	const uint8_t *data;
+};
+
+/**
+ * @brief Helper to declare elements of bt_data arrays
+ *
+ * This macro is mainly for creating an array of struct bt_data
+ * elements which is then passed to e.g. @ref bt_le_adv_start().
+ *
+ * @param _type Type of advertising data field
+ * @param _data Pointer to the data field payload
+ * @param _data_len Number of bytes behind the _data pointer
+ */
+#define BT_DATA(_type, _data, _data_len) \
+	{ \
+		.type = (_type), \
+		.data_len = (_data_len), \
+		.data = (const uint8_t *)(_data), \
+	}
+
+/**
+ * @brief Helper to declare elements of bt_data arrays
+ *
+ * This macro is mainly for creating an array of struct bt_data
+ * elements which is then passed to e.g. @ref bt_le_adv_start().
+ *
+ * @param _type Type of advertising data field
+ * @param _bytes Variable number of single-byte parameters
+ */
+#define BT_DATA_BYTES(_type, _bytes...) \
+	BT_DATA(_type, ((uint8_t []) { _bytes }), \
+		sizeof((uint8_t []) { _bytes }))
+
+/** Advertising options */
+enum {
+	/** Convenience value when no options are specified. */
+	BT_LE_ADV_OPT_NONE = 0,
+
+	/**
+	 * @brief Advertise as connectable.
+	 *
+	 * Advertise as connectable. If not connectable then the type of
+	 * advertising is determined by providing scan response data.
+	 * The advertiser address is determined by the type of advertising
+	 * and/or enabling privacy @option{CONFIG_BT_PRIVACY}.
+	 */
+	BT_LE_ADV_OPT_CONNECTABLE = BIT(0),
+
+	/**
+	 * @brief Advertise one time.
+	 *
+	 * Don't try to resume connectable advertising after a connection.
+	 * This option is only meaningful when used together with
+	 * BT_LE_ADV_OPT_CONNECTABLE. If set the advertising will be stopped
+	 * when bt_le_adv_stop() is called or when an incoming (slave)
+	 * connection happens. If this option is not set the stack will
+	 * take care of keeping advertising enabled even as connections
+	 * occur.
+	 * If Advertising directed or the advertiser was started with
+	 * @ref bt_le_ext_adv_start then this behavior is the default behavior
+	 * and this flag has no effect.
+	 */
+	BT_LE_ADV_OPT_ONE_TIME = BIT(1),
+
+	/**
+	 * @brief Advertise using identity address.
+	 *
+	 * Advertise using the identity address as the advertiser address.
+	 * @warning This will compromise the privacy of the device, so care
+	 *          must be taken when using this option.
+	 * @note The address used for advertising will not be the same as
+	 *        returned by @ref bt_le_oob_get_local, instead @ref bt_id_get
+	 *        should be used to get the LE address.
+	 */
+	BT_LE_ADV_OPT_USE_IDENTITY = BIT(2),
+
+	/** Advertise using GAP device name */
+	BT_LE_ADV_OPT_USE_NAME = BIT(3),
+
+	/**
+	 * @brief Low duty cycle directed advertising.
+	 *
+	 * Use low duty directed advertising mode, otherwise high duty mode
+	 * will be used.
+	 */
+	BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY = BIT(4),
+
+	/**
+	 * @brief Directed advertising to privacy-enabled peer.
+	 *
+	 * Enable use of Resolvable Private Address (RPA) as the target address
+	 * in directed advertisements when @option{CONFIG_BT_PRIVACY} is not
+	 * enabled.
+	 * This is required if the remote device is privacy-enabled and
+	 * supports address resolution of the target address in directed
+	 * advertisement.
+	 * It is the responsibility of the application to check that the remote
+	 * device supports address resolution of directed advertisements by
+	 * reading its Central Address Resolution characteristic.
+	 */
+	BT_LE_ADV_OPT_DIR_ADDR_RPA = BIT(5),
+
+	/** Use whitelist to filter devices that can request scan response data.
+	 */
+	BT_LE_ADV_OPT_FILTER_SCAN_REQ = BIT(6),
+
+	/** Use whitelist to filter devices that can connect. */
+	BT_LE_ADV_OPT_FILTER_CONN = BIT(7),
+
+	/** Notify the application when a scan response data has been sent to an
+	 *  active scanner.
+	 */
+	BT_LE_ADV_OPT_NOTIFY_SCAN_REQ = BIT(8),
+
+	/**
+	 * @brief Support scan response data.
+	 *
+	 * When used together with @ref BT_LE_ADV_OPT_EXT_ADV then this option
+	 * cannot be used together with the @ref BT_LE_ADV_OPT_CONNECTABLE
+	 * option.
+	 * When used together with @ref BT_LE_ADV_OPT_EXT_ADV then scan
+	 * response data must be set.
+	 */
+	BT_LE_ADV_OPT_SCANNABLE = BIT(9),
+
+	/**
+	 * @brief Advertise with extended advertising.
+	 *
+	 * This options enables extended advertising in the advertising set.
+	 * In extended advertising the advertising set will send a small header
+	 * packet on the three primary advertising channels. This small header
+	 * points to the advertising data packet that will be sent on one of
+	 * the 37 secondary advertising channels.
+	 * The advertiser will send primary advertising on LE 1M PHY, and
+	 * secondary advertising on LE 2M PHY.
+	 * Connections will be established on LE 2M PHY.
+	 *
+	 * Without this option the advertiser will send advertising data on the
+	 * three primary advertising channels.
+	 *
+	 * @note Enabling this option requires extended advertising support in
+	 *       the peer devices scanning for advertisement packets.
+	 */
+	BT_LE_ADV_OPT_EXT_ADV = BIT(10),
+
+	/**
+	 * @brief Disable use of LE 2M PHY on the secondary advertising
+	 * channel.
+	 *
+	 * Disabling the use of LE 2M PHY could be necessary if scanners don't
+	 * support the LE 2M PHY.
+	 * The advertiser will send primary advertising on LE 1M PHY, and
+	 * secondary advertising on LE 1M PHY.
+	 * Connections will be established on LE 1M PHY.
+	 *
+	 * @note Cannot be set if BT_LE_ADV_OPT_CODED is set.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV.
+	 */
+	BT_LE_ADV_OPT_NO_2M = BIT(11),
+
+	/**
+	 * @brief Advertise on the LE Coded PHY (Long Range).
+	 *
+	 * The advertiser will send both primary and secondary advertising
+	 * on the LE Coded PHY. This gives the advertiser increased range with
+	 * the trade-off of lower data rate and higher power consumption.
+	 * Connections will be established on LE Coded PHY.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 */
+	BT_LE_ADV_OPT_CODED = BIT(12),
+
+	/**
+	 * @brief Advertise without a device address (identity or RPA).
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 */
+	BT_LE_ADV_OPT_ANONYMOUS = BIT(13),
+
+	/**
+	 * @brief Advertise with transmit power.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 */
+	BT_LE_ADV_OPT_USE_TX_POWER = BIT(14),
+
+	/** Disable advertising on channel index 37. */
+	BT_LE_ADV_OPT_DISABLE_CHAN_37 = BIT(15),
+
+	/** Disable advertising on channel index 38. */
+	BT_LE_ADV_OPT_DISABLE_CHAN_38 = BIT(16),
+
+	/** Disable advertising on channel index 39. */
+	BT_LE_ADV_OPT_DISABLE_CHAN_39 = BIT(17),
+};
+
+/** LE Advertising Parameters. */
+struct bt_le_adv_param {
+	/**
+	 * @brief Local identity.
+	 *
+	 * @note When extended advertising @option{CONFIG_BT_EXT_ADV} is not
+	 *       enabled or not supported by the controller it is not possible
+	 *       to scan and advertise simultaneously using two different
+	 *       random addresses.
+	 *
+	 * @note It is not possible to have multiple connectable advertising
+	 *       sets advertising simultaneously using different identities.
+	 */
+	uint8_t  id;
+
+	/**
+	 * @brief Advertising Set Identifier, valid range 0x00 - 0x0f.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 **/
+	uint8_t  sid;
+
+	/**
+	 * @brief Secondary channel maximum skip count.
+	 *
+	 * Maximum advertising events the advertiser can skip before it must
+	 * send advertising data on the secondary advertising channel.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 */
+	uint8_t  secondary_max_skip;
+
+	/** Bit-field of advertising options */
+	uint32_t options;
+
+	/** Minimum Advertising Interval (N * 0.625) */
+	uint32_t interval_min;
+
+	/** Maximum Advertising Interval (N * 0.625) */
+	uint32_t interval_max;
+
+	/**
+	 * @brief Directed advertising to peer
+	 *
+	 * When this parameter is set the advertiser will send directed
+	 * advertising to the remote device.
+	 *
+	 * The advertising type will either be high duty cycle, or low duty
+	 * cycle if the BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY option is enabled.
+	 *
+	 * In case of connectable high duty cycle if the connection could not
+	 * be established within the timeout the connected() callback will be
+	 * called with the status set to @ref BT_HCI_ERR_ADV_TIMEOUT.
+	 */
+	const bt_addr_le_t *peer;
+};
+
+
+/** Periodic Advertising options */
+enum {
+	/** Convenience value when no options are specified. */
+	BT_LE_PER_ADV_OPT_NONE = 0,
+
+	/**
+	 * @brief Advertise with transmit power.
+	 *
+	 * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV
+	 */
+	BT_LE_PER_ADV_OPT_USE_TX_POWER = BIT(1),
+};
+
+struct bt_le_per_adv_param {
+	/** Minimum Periodic Advertising Interval (N * 1.25 ms) */
+	uint16_t interval_min;
+
+	/** Maximum Periodic Advertising Interval (N * 1.25 ms) */
+	uint16_t interval_max;
+
+	/** Bit-field of periodic advertising options */
+	uint32_t options;
+};
+
+/**
+ * @brief Initialize advertising parameters
+ *
+ * @param _options   Advertising Options
+ * @param _int_min   Minimum advertising interval
+ * @param _int_max   Maximum advertising interval
+ * @param _peer      Peer address, set to NULL for undirected advertising or
+ *                   address of peer for directed advertising.
+ */
+#define BT_LE_ADV_PARAM_INIT(_options, _int_min, _int_max, _peer) \
+{ \
+	.id = BT_ID_DEFAULT, \
+	.sid = 0, \
+	.secondary_max_skip = 0, \
+	.options = (_options), \
+	.interval_min = (_int_min), \
+	.interval_max = (_int_max), \
+	.peer = (_peer), \
+}
+
+/**
+ * @brief Helper to declare advertising parameters inline
+ *
+ * @param _options   Advertising Options
+ * @param _int_min   Minimum advertising interval
+ * @param _int_max   Maximum advertising interval
+ * @param _peer      Peer address, set to NULL for undirected advertising or
+ *                   address of peer for directed advertising.
+ */
+#define BT_LE_ADV_PARAM(_options, _int_min, _int_max, _peer) \
+	((struct bt_le_adv_param[]) { \
+		BT_LE_ADV_PARAM_INIT(_options, _int_min, _int_max, _peer) \
+	 })
+
+#define BT_LE_ADV_CONN_DIR(_peer) BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE |  \
+						  BT_LE_ADV_OPT_ONE_TIME, 0, 0,\
+						  _peer)
+
+
+#define BT_LE_ADV_CONN BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \
+				       BT_GAP_ADV_FAST_INT_MIN_2, \
+				       BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+
+#define BT_LE_ADV_CONN_NAME BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
+					    BT_LE_ADV_OPT_USE_NAME, \
+					    BT_GAP_ADV_FAST_INT_MIN_2, \
+					    BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+
+#define BT_LE_ADV_CONN_DIR_LOW_DUTY(_peer) \
+	BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME | \
+			BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY, \
+			BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, \
+			_peer)
+
+/** Non-connectable advertising with private address */
+#define BT_LE_ADV_NCONN BT_LE_ADV_PARAM(0, BT_GAP_ADV_FAST_INT_MIN_2, \
+					BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+
+/** Non-connectable advertising with @ref BT_LE_ADV_OPT_USE_NAME */
+#define BT_LE_ADV_NCONN_NAME BT_LE_ADV_PARAM(BT_LE_ADV_OPT_USE_NAME, \
+					     BT_GAP_ADV_FAST_INT_MIN_2, \
+					     BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+
+/** Non-connectable advertising with @ref BT_LE_ADV_OPT_USE_IDENTITY */
+#define BT_LE_ADV_NCONN_IDENTITY BT_LE_ADV_PARAM(BT_LE_ADV_OPT_USE_IDENTITY, \
+						 BT_GAP_ADV_FAST_INT_MIN_2, \
+						 BT_GAP_ADV_FAST_INT_MAX_2, \
+						 NULL)
+
+/**
+ * Helper to declare periodic advertising parameters inline
+ *
+ * @param _int_min     Minimum periodic advertising interval
+ * @param _int_max     Maximum periodic advertising interval
+ * @param _options     Periodic advertising properties bitfield.
+ */
+#define BT_LE_PER_ADV_PARAM_INIT(_int_min, _int_max, _options) \
+{ \
+	.interval_min = (_int_min), \
+	.interval_max = (_int_max), \
+	.options = (_options), \
+}
+
+/**
+ * Helper to declare periodic advertising parameters inline
+ *
+ * @param _int_min     Minimum periodic advertising interval
+ * @param _int_max     Maximum periodic advertising interval
+ * @param _options     Periodic advertising properties bitfield.
+ */
+#define BT_LE_PER_ADV_PARAM(_int_min, _int_max, _options) \
+	((struct bt_le_per_adv_param[]) { \
+		BT_LE_PER_ADV_PARAM_INIT(_int_min, _int_max, _options) \
+	})
+
+#define BT_LE_PER_ADV_DEFAULT BT_LE_PER_ADV_PARAM(BT_GAP_ADV_SLOW_INT_MIN, \
+						  BT_GAP_ADV_SLOW_INT_MAX, \
+						  BT_LE_PER_ADV_OPT_NONE)
+
+/**
+ * @brief Start advertising
+ *
+ * Set advertisement data, scan response data, advertisement parameters
+ * and start advertising.
+ *
+ * When the advertisement parameter peer address has been set the advertising
+ * will be directed to the peer. In this case advertisement data and scan
+ * response data parameters are ignored. If the mode is high duty cycle
+ * the timeout will be @ref BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT.
+ *
+ * @param param Advertising parameters.
+ * @param ad Data to be used in advertisement packets.
+ * @param ad_len Number of elements in ad
+ * @param sd Data to be used in scan response packets.
+ * @param sd_len Number of elements in sd
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ * @return -ENOMEM No free connection objects available for connectable
+ *                 advertiser.
+ * @return -ECONNREFUSED When connectable advertising is requested and there
+ *                       is already maximum number of connections established
+ *                       in the controller.
+ *                       This error code is only guaranteed when using Zephyr
+ *                       controller, for other controllers code returned in
+ *                       this case may be -EIO.
+ */
+int bt_le_adv_start(const struct bt_le_adv_param *param,
+		    const struct bt_data *ad, size_t ad_len,
+		    const struct bt_data *sd, size_t sd_len);
+
+/**
+ * @brief Update advertising
+ *
+ * Update advertisement and scan response data.
+ *
+ * @param ad Data to be used in advertisement packets.
+ * @param ad_len Number of elements in ad
+ * @param sd Data to be used in scan response packets.
+ * @param sd_len Number of elements in sd
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,
+			  const struct bt_data *sd, size_t sd_len);
+
+/**
+ * @brief Stop advertising
+ *
+ * Stops ongoing advertising.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_adv_stop(void);
+
+/**
+ * @brief Create advertising set.
+ *
+ * Create a new advertising set and set advertising parameters.
+ * Advertising parameters can be updated with @ref bt_le_ext_adv_update_param.
+ *
+ * @param[in] param Advertising parameters.
+ * @param[in] cb    Callback struct to notify about advertiser activity. Can be
+ *                  NULL. Must point to valid memory during the lifetime of the
+ *                  advertising set.
+ * @param[out] adv  Valid advertising set object on success.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_ext_adv_create(const struct bt_le_adv_param *param,
+			 const struct bt_le_ext_adv_cb *cb,
+			 struct bt_le_ext_adv **adv);
+
+struct bt_le_ext_adv_start_param {
+	/**
+	 * @brief Advertiser timeout (N * 10 ms).
+	 *
+	 * Application will be notified by the advertiser sent callback.
+	 * Set to zero for no timeout.
+	 *
+	 * When using high duty cycle directed connectable advertising then
+	 * this parameters must be set to a non-zero value less than or equal
+	 * to the maximum of @ref BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT.
+	 *
+	 * If privacy @option{CONFIG_BT_PRIVACY} is enabled then the timeout
+	 * must be less than @option{CONFIG_BT_RPA_TIMEOUT}.
+	 */
+	uint16_t timeout;
+	/**
+	 * @brief Number of advertising events.
+	 *
+	 * Application will be notified by the advertiser sent callback.
+	 * Set to zero for no limit.
+	 */
+	uint8_t  num_events;
+};
+
+/**
+ * @brief Start advertising with the given advertising set
+ *
+ * If the advertiser is limited by either the timeout or number of advertising
+ * events the application will be notified by the advertiser sent callback once
+ * the limit is reached.
+ * If the advertiser is limited by both the timeout and the number of
+ * advertising events then the limit that is reached first will stop the
+ * advertiser.
+ *
+ * @param adv    Advertising set object.
+ * @param param  Advertise start parameters.
+ */
+int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
+			struct bt_le_ext_adv_start_param *param);
+
+/**
+ * @brief Stop advertising with the given advertising set
+ *
+ * Stop advertising with a specific advertising set. When using this function
+ * the advertising sent callback will not be called.
+ *
+ * @param adv Advertising set object.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv);
+
+/**
+ * @brief Set an advertising set's advertising or scan response data.
+ *
+ * Set advertisement data or scan response data. If the advertising set is
+ * currently advertising then the advertising data will be updated in
+ * subsequent advertising events.
+ *
+ * When both @ref BT_LE_ADV_OPT_EXT_ADV and @ref BT_LE_ADV_OPT_SCANNABLE are
+ * enabled then advertising data is ignored.
+ * When @ref BT_LE_ADV_OPT_SCANNABLE is not enabled then scan response data is
+ * ignored.
+ *
+ * If the advertising set has been configured to send advertising data on the
+ * primary advertising channels then the maximum data length is
+ * @ref BT_GAP_ADV_MAX_ADV_DATA_LEN bytes.
+ * If the advertising set has been configured for extended advertising,
+ * then the maximum data length is defined by the controller with the maximum
+ * possible of @ref BT_GAP_ADV_MAX_EXT_ADV_DATA_LEN bytes.
+ *
+ * @note Not all scanners support extended data length advertising data.
+ *
+ * @note When updating the advertising data while advertising the advertising
+ *       data and scan response data length must be smaller or equal to what
+ *       can be fit in a single advertising packet. Otherwise the
+ *       advertiser must be stopped.
+ *
+ * @param adv     Advertising set object.
+ * @param ad      Data to be used in advertisement packets.
+ * @param ad_len  Number of elements in ad
+ * @param sd      Data to be used in scan response packets.
+ * @param sd_len  Number of elements in sd
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_ext_adv_set_data(struct bt_le_ext_adv *adv,
+			   const struct bt_data *ad, size_t ad_len,
+			   const struct bt_data *sd, size_t sd_len);
+
+/**
+ * @brief Update advertising parameters.
+ *
+ * Update the advertising parameters. The function will return an error if the
+ * advertiser set is currently advertising. Stop the advertising set before
+ * calling this function.
+ *
+ * @param adv   Advertising set object.
+ * @param param Advertising parameters.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_ext_adv_update_param(struct bt_le_ext_adv *adv,
+			       const struct bt_le_adv_param *param);
+
+/**
+ * @brief Delete advertising set.
+ *
+ * Delete advertising set. This will free up the advertising set and make it
+ * possible to create a new advertising set.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_ext_adv_delete(struct bt_le_ext_adv *adv);
+
+/**
+ * @brief Get array index of an advertising set.
+ *
+ * This function is used to map bt_adv to index of an array of
+ * advertising sets. The array has CONFIG_BT_EXT_ADV_MAX_ADV_SET elements.
+ *
+ * @param adv Advertising set.
+ *
+ * @return Index of the advertising set object.
+ * The range of the returned value is 0..CONFIG_BT_EXT_ADV_MAX_ADV_SET-1
+ */
+uint8_t bt_le_ext_adv_get_index(struct bt_le_ext_adv *adv);
+
+/** @brief Advertising set info structure. */
+struct bt_le_ext_adv_info {
+	/* Local identity */
+	uint8_t                    id;
+
+	/** Currently selected Transmit Power (dBM). */
+	int8_t                     tx_power;
+};
+
+/**
+ * @brief Get advertising set info
+ *
+ * @param adv Advertising set object
+ * @param info Advertising set info object
+ *
+ * @return Zero on success or (negative) error code on failure.
+ */
+int bt_le_ext_adv_get_info(const struct bt_le_ext_adv *adv,
+			   struct bt_le_ext_adv_info *info);
+
+/**
+ * @typedef bt_le_scan_cb_t
+ * @brief Callback type for reporting LE scan results.
+ *
+ * A function of this type is given to the bt_le_scan_start() function
+ * and will be called for any discovered LE device.
+ *
+ * @param addr Advertiser LE address and type.
+ * @param rssi Strength of advertiser signal.
+ * @param adv_type Type of advertising response from advertiser.
+ * @param buf Buffer containing advertiser data.
+ */
+typedef void bt_le_scan_cb_t(const bt_addr_le_t *addr, int8_t rssi,
+			     uint8_t adv_type, struct net_buf_simple *buf);
+
+/**
+ * @brief Set or update the periodic advertising parameters.
+ *
+ * The periodic advertising parameters can only be set or updated on an
+ * extended advertisement set which is neither scannable, connectable nor
+ * anonymous.
+ *
+ * @param adv   Advertising set object.
+ * @param param Advertising parameters.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_set_param(struct bt_le_ext_adv *adv,
+			    const struct bt_le_per_adv_param *param);
+
+/**
+ * @brief Set or update the periodic advertising data.
+ *
+ * The periodic advertisement data can only be set or updated on an
+ * extended advertisement set which is neither scannable, connectable nor
+ * anonymous.
+ *
+ * @param adv       Advertising set object.
+ * @param ad        Advertising data.
+ * @param ad_len    Advertising data length.
+ *
+ * @return          Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_set_data(const struct bt_le_ext_adv *adv,
+			   const struct bt_data *ad, size_t ad_len);
+
+/**
+ * @brief Starts periodic advertising.
+ *
+ * Enabling the periodic advertising can be done independently of extended
+ * advertising, but both periodic advertising and extended advertising
+ * shall be enabled before any periodic advertising data is sent. The
+ * periodic advertising and extended advertising can be enabled in any order.
+ *
+ * Once periodic advertising has been enabled, it will continue advertising
+ * until @ref bt_le_per_adv_stop() has been called, or if the advertising set
+ * is deleted by @ref bt_le_ext_adv_delete(). Calling @ref bt_le_ext_adv_stop()
+ * will not stop the periodic advertising.
+ *
+ * @param adv      Advertising set object.
+ *
+ * @return         Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_start(struct bt_le_ext_adv *adv);
+
+/**
+ * @brief Stops periodic advertising.
+ *
+ * Disabling the periodic advertising can be done independently of extended
+ * advertising. Disabling periodic advertising will not disable extended
+ * advertising.
+ *
+ * @param adv      Advertising set object.
+ *
+ * @return         Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_stop(struct bt_le_ext_adv *adv);
+
+struct bt_le_per_adv_sync_synced_info {
+	/** Advertiser LE address and type. */
+	const bt_addr_le_t *addr;
+
+	/** Advertiser SID */
+	uint8_t sid;
+
+	/** Periodic advertising interval (N * 1.25 ms) */
+	uint16_t interval;
+
+	/** Advertiser PHY */
+	uint8_t phy;
+};
+
+struct bt_le_per_adv_sync_term_info {
+	/** Advertiser LE address and type. */
+	const bt_addr_le_t *addr;
+
+	/** Advertiser SID */
+	uint8_t sid;
+};
+
+struct bt_le_per_adv_sync_recv_info {
+	/** Advertiser LE address and type. */
+	const bt_addr_le_t *addr;
+
+	/** Advertiser SID */
+	uint8_t sid;
+
+	/** The TX power of the advertisement. */
+	int8_t tx_power;
+
+	/** The RSSI of the advertisement excluding any CTE. */
+	int8_t rssi;
+
+	/** The Constant Tone Extension (CTE) of the advertisement */
+	uint8_t cte_type;
+};
+
+struct bt_le_per_adv_sync_cb {
+	/**
+	 * @brief The periodic advertising has been successfully synced.
+	 *
+	 * This callback notifies the application that the periodic advertising
+	 * set has been successfully synced, and will now start to
+	 * receive periodic advertising reports.
+	 *
+	 * @param sync The periodic advertising sync object.
+	 * @param info Information about the sync event.
+	 */
+	void (*synced)(struct bt_le_per_adv_sync *sync,
+		       struct bt_le_per_adv_sync_synced_info *info);
+
+	/**
+	 * @brief The periodic advertising sync has been terminated.
+	 *
+	 * This callback notifies the application that the periodic advertising
+	 * sync has been terminated, either by local request, remote request or
+	 * because due to missing data, e.g. by being out of range or sync.
+	 *
+	 * @param sync  The periodic advertising sync object.
+	 */
+	void (*term)(struct bt_le_per_adv_sync *sync,
+		     const struct bt_le_per_adv_sync_term_info *info);
+
+	/**
+	 * @brief Periodic advertising data received.
+	 *
+	 * This callback notifies the application of an periodic advertising
+	 * report.
+	 *
+	 * @param sync  The advertising set object.
+	 * @param info  Information about the periodic advertising event.
+	 * @param buf   Buffer containing the periodic advertising data.
+	 */
+	void (*recv)(struct bt_le_per_adv_sync *sync,
+		     const struct bt_le_per_adv_sync_recv_info *info,
+		     struct net_buf_simple *buf);
+
+	sys_snode_t node;
+};
+
+/** Periodic advertising sync options */
+enum {
+	/** Convenience value when no options are specified. */
+	BT_LE_PER_ADV_SYNC_OPT_NONE = 0,
+
+	/**
+	 * @brief Use the periodic advertising list to sync with advertiser
+	 *
+	 * When this option is set, the address and SID of the parameters
+	 * are ignored.
+	 */
+	BT_LE_PER_ADV_SYNC_OPT_USE_PER_ADV_LIST = BIT(0),
+
+	/**
+	 * @brief Disables periodic advertising reports
+	 *
+	 * No advertisement reports will be handled until enabled.
+	 */
+	BT_LE_PER_ADV_SYNC_OPT_REPORTING_INITIALLY_DISABLED = BIT(1),
+
+	/** Sync with Angle of Arrival (AoA) constant tone extension */
+	BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOA = BIT(2),
+
+	/** Sync with Angle of Departure (AoD) 1 us constant tone extension */
+	BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_1US = BIT(3),
+
+	/** Sync with Angle of Departure (AoD) 2 us constant tone extension */
+	BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_2US = BIT(4),
+
+	/** Do not sync to packets without a constant tone extension */
+	BT_LE_PER_ADV_SYNC_OPT_SYNC_ONLY_CONST_TONE_EXT = BIT(5),
+};
+
+struct bt_le_per_adv_sync_param {
+	/**
+	 * @brief Periodic Advertiser Address
+	 *
+	 * Only valid if not using the periodic advertising list
+	 */
+	bt_addr_le_t addr;
+
+	/**
+	 * @brief Advertiser SID
+	 *
+	 * Only valid if not using the periodic advertising list
+	 */
+	uint8_t sid;
+
+	/** Bit-field of periodic advertising sync options. */
+	uint32_t options;
+
+	/**
+	 * @brief Maximum event skip
+	 *
+	 * Maximum number of periodic advertising events that can be
+	 * skipped after a successful receive
+	 */
+	uint16_t skip;
+
+	/**
+	 * @brief Synchronization timeout (N * 10 ms)
+	 *
+	 * Synchronization timeout for the periodic advertising sync.
+	 * Range 0x000A to 0x4000 (100 ms to 163840 ms)
+	 */
+	uint16_t timeout;
+};
+
+/**
+ * @brief Get array index of an periodic advertising sync object.
+ *
+ * This function is get the index of an array of periodic advertising sync
+ * objects. The array has CONFIG_BT_PER_ADV_SYNC_MAX elements.
+ *
+ * @param per_adv_sync The periodic advertising sync object.
+ *
+ * @return Index of the periodic advertising sync object.
+ * The range of the returned value is 0..CONFIG_BT_PER_ADV_SYNC_MAX-1
+ */
+uint8_t bt_le_per_adv_sync_get_index(struct bt_le_per_adv_sync *per_adv_sync);
+
+/**
+ * @brief Create a periodic advertising sync object.
+ *
+ * Create a periodic advertising sync object that can try to synchronize
+ * to periodic advertising reports from an advertiser. Scan shall either be
+ * disabled or extended scan shall be enabled.
+ *
+ * @param[in]  param     Periodic advertising sync parameters.
+ * @param[out] out_sync  Periodic advertising sync object on.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_sync_create(const struct bt_le_per_adv_sync_param *param,
+			      struct bt_le_per_adv_sync **out_sync);
+
+/**
+ * @brief Delete periodic advertising sync.
+ *
+ * Delete the periodic advertising sync object. Can be called regardless of the
+ * state of the sync. If the syncing is currently syncing, the syncing is
+ * cancelled. If the sync has been established, it is terminated. The
+ * periodic advertising sync object will be invalidated afterwards.
+ *
+ * @param per_adv_sync The periodic advertising sync object.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_le_per_adv_sync_delete(struct bt_le_per_adv_sync *per_adv_sync);
+
+/**
+ * @brief Register periodic advertising sync callbacks.
+ *
+ * Adds the callback structure to the list of callback structures for periodic
+ * adverising syncs.
+ *
+ * This callback will be called for all periodic advertising sync activity,
+ * such as synced, terminated and when data is received.
+ *
+ * @param cb Callback struct. Must point to memory that remains valid.
+ */
+void bt_le_per_adv_sync_cb_register(struct bt_le_per_adv_sync_cb *cb);
+
+enum {
+	/** Convenience value when no options are specified. */
+	BT_LE_SCAN_OPT_NONE = 0,
+
+	/** Filter duplicates. */
+	BT_LE_SCAN_OPT_FILTER_DUPLICATE = BIT(0),
+
+	/** Filter using whitelist. */
+	BT_LE_SCAN_OPT_FILTER_WHITELIST = BIT(1),
+
+	/** Enable scan on coded PHY (Long Range).*/
+	BT_LE_SCAN_OPT_CODED = BIT(2),
+
+	/**
+	 * @brief Disable scan on 1M phy.
+	 *
+	 * @note Requires @ref BT_LE_SCAN_OPT_CODED.
+	 */
+	BT_LE_SCAN_OPT_NO_1M = BIT(3),
+
+	BT_LE_SCAN_FILTER_DUPLICATE __deprecated =
+		BT_LE_SCAN_OPT_FILTER_DUPLICATE,
+	BT_LE_SCAN_FILTER_WHITELIST __deprecated =
+		BT_LE_SCAN_OPT_FILTER_WHITELIST,
+};
+
+enum {
+	/** Scan without requesting additional information from advertisers. */
+	BT_LE_SCAN_TYPE_PASSIVE = 0x00,
+
+	/** Scan and request additional information from advertisers. */
+	BT_LE_SCAN_TYPE_ACTIVE = 0x01,
+};
+
+/** LE scan parameters */
+struct bt_le_scan_param {
+	/** Scan type (BT_LE_SCAN_TYPE_ACTIVE or BT_LE_SCAN_TYPE_PASSIVE) */
+	uint8_t  type;
+
+	union {
+		/** Bit-field of scanning filter options. */
+		uint32_t filter_dup __deprecated;
+
+		/** Bit-field of scanning options. */
+		uint32_t options;
+	};
+
+	/** Scan interval (N * 0.625 ms) */
+	uint16_t interval;
+
+	/** Scan window (N * 0.625 ms) */
+	uint16_t window;
+
+	/**
+	 * @brief Scan timeout (N * 10 ms)
+	 *
+	 * Application will be notified by the scan timeout callback.
+	 * Set zero to disable timeout.
+	 */
+	uint16_t timeout;
+
+	/**
+	 * @brief Scan interval LE Coded PHY (N * 0.625 MS)
+	 *
+	 * Set zero to use same as LE 1M PHY scan interval.
+	 */
+	uint16_t interval_coded;
+
+	/**
+	 * @brief Scan window LE Coded PHY (N * 0.625 MS)
+	 *
+	 * Set zero to use same as LE 1M PHY scan window.
+	 */
+	uint16_t window_coded;
+};
+
+/** LE advertisement packet information */
+struct bt_le_scan_recv_info {
+	/**
+	 * @brief Advertiser LE address and type.
+	 *
+	 * If advertiser is anonymous then this address will be
+	 * @ref BT_ADDR_LE_ANY.
+	 */
+	const bt_addr_le_t *addr;
+
+	/** Advertising Set Identifier. */
+	uint8_t sid;
+
+	/** Strength of advertiser signal. */
+	int8_t rssi;
+
+	/** Transmit power of the advertiser. */
+	int8_t tx_power;
+
+	/** Advertising packet type. */
+	uint8_t adv_type;
+
+	/** Advertising packet properties. */
+	uint16_t adv_props;
+
+	/**
+	 * @brief Periodic advertising interval.
+	 *
+	 * If 0 there is no periodic advertising.
+	 */
+	uint16_t interval;
+
+	/** Primary advertising channel PHY. */
+	uint8_t primary_phy;
+
+	/** Secondary advertising channel PHY. */
+	uint8_t secondary_phy;
+};
+
+/** Listener context for (LE) scanning. */
+struct bt_le_scan_cb {
+
+	/**
+	 * @brief Advertisement packet received callback.
+	 *
+	 * @param info Advertiser packet information.
+	 * @param buf  Buffer containing advertiser data.
+	 */
+	void (*recv)(const struct bt_le_scan_recv_info *info,
+		     struct net_buf_simple *buf);
+
+	/** @brief The scanner has stopped scanning after scan timeout. */
+	void (*timeout)(void);
+
+	sys_snode_t node;
+};
+
+/**
+ * @brief Initialize scan parameters
+ *
+ * @param _type     Scan Type, BT_LE_SCAN_TYPE_ACTIVE or
+ *                  BT_LE_SCAN_TYPE_PASSIVE.
+ * @param _options  Scan options
+ * @param _interval Scan Interval (N * 0.625 ms)
+ * @param _window   Scan Window (N * 0.625 ms)
+ */
+#define BT_LE_SCAN_PARAM_INIT(_type, _options, _interval, _window) \
+{ \
+	.type = (_type), \
+	.options = (_options), \
+	.interval = (_interval), \
+	.window = (_window), \
+	.timeout = 0, \
+	.interval_coded = 0, \
+	.window_coded = 0, \
+}
+
+/**
+ * @brief Helper to declare scan parameters inline
+ *
+ * @param _type     Scan Type, BT_LE_SCAN_TYPE_ACTIVE or
+ *                  BT_LE_SCAN_TYPE_PASSIVE.
+ * @param _options  Scan options
+ * @param _interval Scan Interval (N * 0.625 ms)
+ * @param _window   Scan Window (N * 0.625 ms)
+ */
+#define BT_LE_SCAN_PARAM(_type, _options, _interval, _window) \
+	((struct bt_le_scan_param[]) { \
+		BT_LE_SCAN_PARAM_INIT(_type, _options, _interval, _window) \
+	 })
+
+/** Helper macro to enable active scanning to discover new devices. */
+#define BT_LE_SCAN_ACTIVE BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_ACTIVE, \
+					   BT_LE_SCAN_OPT_FILTER_DUPLICATE, \
+					   BT_GAP_SCAN_FAST_INTERVAL, \
+					   BT_GAP_SCAN_FAST_WINDOW)
+
+/**
+ * @brief Helper macro to enable passive scanning to discover new devices.
+ *
+ * This macro should be used if information required for device identification
+ * (e.g., UUID) are known to be placed in Advertising Data.
+ */
+#define BT_LE_SCAN_PASSIVE BT_LE_SCAN_PARAM(BT_LE_SCAN_TYPE_PASSIVE, \
+					    BT_LE_SCAN_OPT_FILTER_DUPLICATE, \
+					    BT_GAP_SCAN_FAST_INTERVAL, \
+					    BT_GAP_SCAN_FAST_WINDOW)
+
+/**
+ * @brief Start (LE) scanning
+ *
+ * Start LE scanning with given parameters and provide results through
+ * the specified callback.
+ *
+ * @note The LE scanner by default does not use the Identity Address of the
+ *       local device when @option{CONFIG_BT_PRIVACY} is disabled. This is to
+ *       prevent the active scanner from disclosing the identity information
+ *       when requesting additional information from advertisers.
+ *       In order to enable directed advertiser reports then
+ *       @option{CONFIG_BT_SCAN_WITH_IDENTITY} must be enabled.
+ *
+ * @param param Scan parameters.
+ * @param cb Callback to notify scan results. May be NULL if callback
+ *           registration through @ref bt_le_scan_cb_register is preferred.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb);
+
+/**
+ * @brief Stop (LE) scanning.
+ *
+ * Stops ongoing LE scanning.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_scan_stop(void);
+
+/**
+ * @brief Register scanner packet callbacks.
+ *
+ * Adds the callback structure to the list of callback structures that monitors
+ * scanner activity.
+ *
+ * This callback will be called for all scanner activity, regardless of what
+ * API was used to start the scanner.
+ *
+ * @param cb Callback struct. Must point to memory that remains valid.
+ */
+void bt_le_scan_cb_register(struct bt_le_scan_cb *cb);
+
+/**
+ * @brief Add device (LE) to whitelist.
+ *
+ * Add peer device LE address to the whitelist.
+ *
+ * @note The whitelist cannot be modified when an LE role is using
+ * the whitelist, i.e advertiser or scanner using a whitelist or automatic
+ * connecting to devices using whitelist.
+ *
+ * @param addr Bluetooth LE identity address.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_whitelist_add(const bt_addr_le_t *addr);
+
+/**
+ * @brief Remove device (LE) from whitelist.
+ *
+ * Remove peer device LE address from the whitelist.
+ *
+ * @note The whitelist cannot be modified when an LE role is using
+ * the whitelist, i.e advertiser or scanner using a whitelist or automatic
+ * connecting to devices using whitelist.
+ *
+ * @param addr Bluetooth LE identity address.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_whitelist_rem(const bt_addr_le_t *addr);
+
+/**
+ * @brief Clear whitelist.
+ *
+ * Clear all devices from the whitelist.
+ *
+ * @note The whitelist cannot be modified when an LE role is using
+ * the whitelist, i.e advertiser or scanner using a whitelist or automatic
+ * connecting to devices using whitelist.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_whitelist_clear(void);
+
+/**
+ * @brief Set (LE) channel map.
+ *
+ * @param chan_map Channel map.
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_set_chan_map(uint8_t chan_map[5]);
+
+/**
+ * @brief Helper for parsing advertising (or EIR or OOB) data.
+ *
+ * A helper for parsing the basic data types used for Extended Inquiry
+ * Response (EIR), Advertising Data (AD), and OOB data blocks. The most
+ * common scenario is to call this helper on the advertising data
+ * received in the callback that was given to bt_le_scan_start().
+ *
+ * @param ad        Advertising data as given to the bt_le_scan_cb_t callback.
+ * @param func      Callback function which will be called for each element
+ *                  that's found in the data. The callback should return
+ *                  true to continue parsing, or false to stop parsing.
+ * @param user_data User data to be passed to the callback.
+ */
+void bt_data_parse(struct net_buf_simple *ad,
+		   bool (*func)(struct bt_data *data, void *user_data),
+		   void *user_data);
+
+/** LE Secure Connections pairing Out of Band data. */
+struct bt_le_oob_sc_data {
+	/** Random Number. */
+	uint8_t r[16];
+
+	/** Confirm Value. */
+	uint8_t c[16];
+};
+
+/** LE Out of Band information. */
+struct bt_le_oob {
+	/** LE address. If privacy is enabled this is a Resolvable Private
+	 *  Address.
+	 */
+	bt_addr_le_t addr;
+
+	/** LE Secure Connections pairing Out of Band data. */
+	struct bt_le_oob_sc_data le_sc_data;
+};
+
+/**
+ * @brief Get local LE Out of Band (OOB) information.
+ *
+ * This function allows to get local information that are useful for
+ * Out of Band pairing or connection creation.
+ *
+ * If privacy @option{CONFIG_BT_PRIVACY} is enabled this will result in
+ * generating new Resolvable Private Address (RPA) that is valid for
+ * @option{CONFIG_BT_RPA_TIMEOUT} seconds. This address will be used for
+ * advertising started by @ref bt_le_adv_start, active scanning and
+ * connection creation.
+ *
+ * @note If privacy is enabled the RPA cannot be refreshed in the following
+ *       cases:
+ *       - Creating a connection in progress, wait for the connected callback.
+ *      In addition when extended advertising @option{CONFIG_BT_EXT_ADV} is
+ *      not enabled or not supported by the controller:
+ *       - Advertiser is enabled using a Random Static Identity Address for a
+ *         different local identity.
+ *       - The local identity conflicts with the local identity used by other
+ *         roles.
+ *
+ * @param[in]  id  Local identity, in most cases BT_ID_DEFAULT.
+ * @param[out] oob LE OOB information
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob);
+
+/**
+ * @brief Get local LE Out of Band (OOB) information.
+ *
+ * This function allows to get local information that are useful for
+ * Out of Band pairing or connection creation.
+ *
+ * If privacy @option{CONFIG_BT_PRIVACY} is enabled this will result in
+ * generating new Resolvable Private Address (RPA) that is valid for
+ * @option{CONFIG_BT_RPA_TIMEOUT} seconds. This address will be used by the
+ * advertising set.
+ *
+ * @note When generating OOB information for multiple advertising set all
+ *       OOB information needs to be generated at the same time.
+ *
+ * @note If privacy is enabled the RPA cannot be refreshed in the following
+ *       cases:
+ *       - Creating a connection in progress, wait for the connected callback.
+ *
+ * @param[in]  adv The advertising set object
+ * @param[out] oob LE OOB information
+ *
+ * @return Zero on success or error code otherwise, positive in case
+ * of protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv,
+				struct bt_le_oob *oob);
+
+/** @brief BR/EDR discovery result structure */
+struct bt_br_discovery_result {
+	/** private */
+	uint8_t _priv[4];
+
+	/** Remote device address */
+	bt_addr_t addr;
+
+	/** RSSI from inquiry */
+	int8_t rssi;
+
+	/** Class of Device */
+	uint8_t cod[3];
+
+	/** Extended Inquiry Response */
+	uint8_t eir[240];
+};
+
+/**
+ * @typedef bt_br_discovery_cb_t
+ * @brief Callback type for reporting BR/EDR discovery (inquiry)
+ *        results.
+ *
+ * A callback of this type is given to the bt_br_discovery_start()
+ * function and will be called at the end of the discovery with
+ * information about found devices populated in the results array.
+ *
+ * @param results Storage used for discovery results
+ * @param count Number of valid discovery results.
+ */
+typedef void bt_br_discovery_cb_t(struct bt_br_discovery_result *results,
+				  size_t count);
+
+/** BR/EDR discovery parameters */
+struct bt_br_discovery_param {
+	/** Maximum length of the discovery in units of 1.28 seconds.
+	 *  Valid range is 0x01 - 0x30.
+	 */
+	uint8_t length;
+
+	/** True if limited discovery procedure is to be used. */
+	bool limited;
+};
+
+/**
+ * @brief Start BR/EDR discovery
+ *
+ * Start BR/EDR discovery (inquiry) and provide results through the specified
+ * callback. When bt_br_discovery_cb_t is called it indicates that discovery
+ * has completed. If more inquiry results were received during session than
+ * fits in provided result storage, only ones with highest RSSI will be
+ * reported.
+ *
+ * @param param Discovery parameters.
+ * @param results Storage for discovery results.
+ * @param count Number of results in storage. Valid range: 1-255.
+ * @param cb Callback to notify discovery results.
+ *
+ * @return Zero on success or error code otherwise, positive in case
+ * of protocol error or negative (POSIX) in case of stack internal error
+ */
+int bt_br_discovery_start(const struct bt_br_discovery_param *param,
+			  struct bt_br_discovery_result *results, size_t count,
+			  bt_br_discovery_cb_t cb);
+
+/**
+ * @brief Stop BR/EDR discovery.
+ *
+ * Stops ongoing BR/EDR discovery. If discovery was stopped by this call
+ * results won't be reported
+ *
+ * @return Zero on success or error code otherwise, positive in case of
+ *         protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_br_discovery_stop(void);
+
+struct bt_br_oob {
+	/** BR/EDR address. */
+	bt_addr_t addr;
+};
+
+/**
+ * @brief Get BR/EDR local Out Of Band information
+ *
+ * This function allows to get local controller information that are useful
+ * for Out Of Band pairing or connection creation process.
+ *
+ * @param oob Out Of Band information
+ */
+int bt_br_oob_get_local(struct bt_br_oob *oob);
+
+/**
+ * @def BT_ADDR_STR_LEN
+ *
+ * @brief Recommended length of user string buffer for Bluetooth address
+ *
+ * @details The recommended length guarantee the output of address
+ * conversion will not lose valuable information about address being
+ * processed.
+ */
+#define BT_ADDR_STR_LEN 18
+
+/**
+ * @def BT_ADDR_LE_STR_LEN
+ *
+ * @brief Recommended length of user string buffer for Bluetooth LE address
+ *
+ * @details The recommended length guarantee the output of address
+ * conversion will not lose valuable information about address being
+ * processed.
+ */
+#define BT_ADDR_LE_STR_LEN 30
+extern int snprintk(char *str, size_t size, const char *fmt, ...);
+/**
+ * @brief Converts binary Bluetooth address to string.
+ *
+ * @param addr Address of buffer containing binary Bluetooth address.
+ * @param str Address of user buffer with enough room to store formatted
+ * string containing binary address.
+ * @param len Length of data to be copied to user string buffer. Refer to
+ * BT_ADDR_STR_LEN about recommended value.
+ *
+ * @return Number of successfully formatted bytes from binary address.
+ */
+static inline int bt_addr_to_str(const bt_addr_t *addr, char *str, size_t len)
+{
+	return snprintk(str, len, "%02X:%02X:%02X:%02X:%02X:%02X",
+			addr->val[5], addr->val[4], addr->val[3],
+			addr->val[2], addr->val[1], addr->val[0]);
+}
+
+/**
+ * @brief Converts binary LE Bluetooth address to string.
+ *
+ * @param addr Address of buffer containing binary LE Bluetooth address.
+ * @param str Address of user buffer with enough room to store
+ * formatted string containing binary LE address.
+ * @param len Length of data to be copied to user string buffer. Refer to
+ * BT_ADDR_LE_STR_LEN about recommended value.
+ *
+ * @return Number of successfully formatted bytes from binary address.
+ */
+static inline int bt_addr_le_to_str(const bt_addr_le_t *addr, char *str,
+				    size_t len)
+{
+	char type[10];
+
+	switch (addr->type) {
+	case BT_ADDR_LE_PUBLIC:
+		strcpy(type, "public");
+		break;
+	case BT_ADDR_LE_RANDOM:
+		strcpy(type, "random");
+		break;
+	case BT_ADDR_LE_PUBLIC_ID:
+		strcpy(type, "public-id");
+		break;
+	case BT_ADDR_LE_RANDOM_ID:
+		strcpy(type, "random-id");
+		break;
+	default:
+		snprintk(type, sizeof(type), "0x%02x", addr->type);
+		break;
+	}
+
+	return snprintk(str, len, "%02X:%02X:%02X:%02X:%02X:%02X (%s)",
+			addr->a.val[5], addr->a.val[4], addr->a.val[3],
+			addr->a.val[2], addr->a.val[1], addr->a.val[0], type);
+}
+
+/**
+ * @brief Convert Bluetooth address from string to binary.
+ *
+ * @param[in]  str   The string representation of a Bluetooth address.
+ * @param[out] addr  Address of buffer to store the Bluetooth address
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_addr_from_str(const char *str, bt_addr_t *addr);
+
+/**
+ * @brief Convert LE Bluetooth address from string to binary.
+ *
+ * @param[in]  str   The string representation of an LE Bluetooth address.
+ * @param[in]  type  The string representation of the LE Bluetooth address
+ *                   type.
+ * @param[out] addr  Address of buffer to store the LE Bluetooth address
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr);
+
+/**
+ * @brief Enable/disable set controller in discoverable state.
+ *
+ * Allows make local controller to listen on INQUIRY SCAN channel and responds
+ * to devices making general inquiry. To enable this state it's mandatory
+ * to first be in connectable state.
+ *
+ * @param enable Value allowing/disallowing controller to become discoverable.
+ *
+ * @return Negative if fail set to requested state or requested state has been
+ *         already set. Zero if done successfully.
+ */
+int bt_br_set_discoverable(bool enable);
+
+/**
+ * @brief Enable/disable set controller in connectable state.
+ *
+ * Allows make local controller to be connectable. It means the controller
+ * start listen to devices requests on PAGE SCAN channel. If disabled also
+ * resets discoverability if was set.
+ *
+ * @param enable Value allowing/disallowing controller to be connectable.
+ *
+ * @return Negative if fail set to requested state or requested state has been
+ *         already set. Zero if done successfully.
+ */
+int bt_br_set_connectable(bool enable);
+
+/**
+ * @brief Clear pairing information.
+ *
+ * @param id    Local identity (mostly just BT_ID_DEFAULT).
+ * @param addr  Remote address, NULL or BT_ADDR_LE_ANY to clear all remote
+ *              devices.
+ *
+ * @return 0 on success or negative error value on failure.
+ */
+int bt_unpair(uint8_t id, const bt_addr_le_t *addr);
+
+/** Information about a bond with a remote device. */
+struct bt_bond_info {
+	/** Address of the remote device. */
+	bt_addr_le_t addr;
+};
+
+/**
+ * @brief Iterate through all existing bonds.
+ *
+ * @param id         Local identity (mostly just BT_ID_DEFAULT).
+ * @param func       Function to call for each bond.
+ * @param user_data  Data to pass to the callback function.
+ */
+void bt_foreach_bond(uint8_t id, void (*func)(const struct bt_bond_info *info,
+					   void *user_data),
+		     void *user_data);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_BLUETOOTH_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/buf.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/buf.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/buf.h	(working copy)
@@ -0,0 +1,141 @@
+/** @file
+ *  @brief Bluetooth data buffer API
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_
+
+/**
+ * @brief Data buffers
+ * @defgroup bt_buf Data buffers
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <types.h>
+#include <net/buf.h>
+#include <bluetooth/hci.h>
+
+/** Possible types of buffers passed around the Bluetooth stack */
+enum bt_buf_type {
+	/** HCI command */
+	BT_BUF_CMD,
+	/** HCI event */
+	BT_BUF_EVT,
+	/** Outgoing ACL data */
+	BT_BUF_ACL_OUT,
+	/** Incoming ACL data */
+	BT_BUF_ACL_IN,
+	/** Outgoing ISO data */
+	BT_BUF_ISO_OUT,
+	/** Incoming ISO data */
+	BT_BUF_ISO_IN,
+	/** H:4 data */
+	BT_BUF_H4,
+};
+
+/** Minimum amount of user data size for buffers passed to the stack. */
+#define BT_BUF_USER_DATA_MIN __DEPRECATED_MACRO 4
+
+#if defined(CONFIG_BT_HCI_RAW)
+#define BT_BUF_RESERVE MAX(CONFIG_BT_HCI_RESERVE, CONFIG_BT_HCI_RAW_RESERVE)
+#else
+#define BT_BUF_RESERVE CONFIG_BT_HCI_RESERVE
+#endif
+
+#define BT_BUF_SIZE(size) (BT_BUF_RESERVE + (size))
+
+/** Data size neeed for HCI RX buffers */
+#define BT_BUF_RX_SIZE (BT_BUF_SIZE(CONFIG_BT_RX_BUF_LEN))
+
+/** Allocate a buffer for incoming data
+ *
+ *  This will set the buffer type so bt_buf_set_type() does not need to
+ *  be explicitly called before bt_recv_prio().
+ *
+ *  @param type    Type of buffer. Only BT_BUF_EVT and BT_BUF_ACL_IN are
+ *                 allowed.
+ *  @param timeout Non-negative waiting period to obtain a buffer or one of the
+ *                 special values K_NO_WAIT and K_FOREVER.
+ *  @return A new buffer.
+ */
+struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout);
+
+/** Allocate a buffer for outgoing data
+ *
+ *  This will set the buffer type so bt_buf_set_type() does not need to
+ *  be explicitly called before bt_send().
+ *
+ *  @param type    Type of buffer. Only BT_BUF_CMD, BT_BUF_ACL_OUT or
+ *                 BT_BUF_H4, when operating on H:4 mode, are allowed.
+ *  @param timeout Non-negative waiting period to obtain a buffer or one of the
+ *                 special values K_NO_WAIT and K_FOREVER.
+ *  @param data    Initial data to append to buffer.
+ *  @param size    Initial data size.
+ *  @return A new buffer.
+ */
+struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
+			      const void *data, size_t size);
+
+/** Allocate a buffer for an HCI Command Complete/Status Event
+ *
+ *  This will set the buffer type so bt_buf_set_type() does not need to
+ *  be explicitly called before bt_recv_prio().
+ *
+ *  @param timeout Non-negative waiting period to obtain a buffer or one of the
+ *                 special values K_NO_WAIT and K_FOREVER.
+ *  @return A new buffer.
+ */
+struct net_buf *bt_buf_get_cmd_complete(k_timeout_t timeout);
+
+/** Allocate a buffer for an HCI Event
+ *
+ *  This will set the buffer type so bt_buf_set_type() does not need to
+ *  be explicitly called before bt_recv_prio() or bt_recv().
+ *
+ *  @param evt          HCI event code
+ *  @param discardable  Whether the driver considers the event discardable.
+ *  @param timeout      Non-negative waiting period to obtain a buffer or one of
+ *                      the special values K_NO_WAIT and K_FOREVER.
+ *  @return A new buffer.
+ */
+struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout);
+
+/** Set the buffer type
+ *
+ *  @param buf   Bluetooth buffer
+ *  @param type  The BT_* type to set the buffer to
+ */
+static inline void bt_buf_set_type(struct net_buf *buf, enum bt_buf_type type)
+{
+	*(uint8_t *)net_buf_user_data(buf) = type;
+}
+
+/** Get the buffer type
+ *
+ *  @param buf   Bluetooth buffer
+ *
+ *  @return The BT_* type to of the buffer
+ */
+static inline enum bt_buf_type bt_buf_get_type(struct net_buf *buf)
+{
+	/* De-referencing the pointer from net_buf_user_data(buf) as a
+	 * pointer to an enum causes issues on qemu_x86 because the true
+	 * size is 8-bit, but the enum is 32-bit on qemu_x86. So we put in
+	 * a temporary cast to 8-bit to ensure only 8 bits are read from
+	 * the pointer.
+	 */
+	return (enum bt_buf_type)(*(uint8_t *)net_buf_user_data(buf));
+}
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_BUF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/conn.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/conn.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/conn.h	(working copy)
@@ -0,0 +1,1438 @@
+/** @file
+ *  @brief Bluetooth connection handling
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_CONN_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_CONN_H_
+
+/**
+ * @brief Connection management
+ * @defgroup bt_conn Connection management
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <stdbool.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci_err.h>
+#include <bluetooth/addr.h>
+#include <bluetooth/gap.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Opaque type representing a connection to a remote device */
+struct bt_conn;
+
+/** Connection parameters for LE connections */
+struct bt_le_conn_param {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+};
+
+/** @brief Initialize connection parameters
+ *
+ *  @param int_min  Minimum Connection Interval (N * 1.25 ms)
+ *  @param int_max  Maximum Connection Interval (N * 1.25 ms)
+ *  @param lat      Connection Latency
+ *  @param to       Supervision Timeout (N * 10 ms)
+ */
+#define BT_LE_CONN_PARAM_INIT(int_min, int_max, lat, to) \
+{ \
+	.interval_min = (int_min), \
+	.interval_max = (int_max), \
+	.latency = (lat), \
+	.timeout = (to), \
+}
+
+/** Helper to declare connection parameters inline
+ *
+ *  @param int_min  Minimum Connection Interval (N * 1.25 ms)
+ *  @param int_max  Maximum Connection Interval (N * 1.25 ms)
+ *  @param lat      Connection Latency
+ *  @param to       Supervision Timeout (N * 10 ms)
+ */
+#define BT_LE_CONN_PARAM(int_min, int_max, lat, to) \
+	((struct bt_le_conn_param[]) { \
+		BT_LE_CONN_PARAM_INIT(int_min, int_max, lat, to) \
+	 })
+
+/** Default LE connection parameters:
+ *    Connection Interval: 30-50 ms
+ *    Latency: 0
+ *    Timeout: 4 s
+ */
+#define BT_LE_CONN_PARAM_DEFAULT BT_LE_CONN_PARAM(BT_GAP_INIT_CONN_INT_MIN, \
+						  BT_GAP_INIT_CONN_INT_MAX, \
+						  0, 400)
+
+/** Connection PHY information for LE connections */
+struct bt_conn_le_phy_info {
+	uint8_t tx_phy; /** Connection transmit PHY */
+	uint8_t rx_phy; /** Connection receive PHY */
+};
+
+/** Connection PHY options */
+enum {
+	/** Convenience value when no options are specified. */
+	BT_CONN_LE_PHY_OPT_NONE = 0,
+
+	/** LE Coded using S=2 coding preferred when transmitting. */
+	BT_CONN_LE_PHY_OPT_CODED_S2  = BIT(0),
+
+	/** LE Coded using S=8 coding preferred when transmitting. */
+	BT_CONN_LE_PHY_OPT_CODED_S8  = BIT(1),
+};
+
+/** Preferred PHY parameters for LE connections */
+struct bt_conn_le_phy_param {
+	uint16_t options;     /** Connection PHY options. */
+	uint8_t  pref_tx_phy; /** Bitmask of preferred transmit PHYs */
+	uint8_t  pref_rx_phy; /** Bitmask of preferred receive PHYs */
+};
+
+/** Initialize PHY parameters
+ *
+ * @param _pref_tx_phy Bitmask of preferred transmit PHYs.
+ * @param _pref_rx_phy Bitmask of preferred receive PHYs.
+ */
+#define BT_CONN_LE_PHY_PARAM_INIT(_pref_tx_phy, _pref_rx_phy) \
+{ \
+	.options = BT_CONN_LE_PHY_OPT_NONE, \
+	.pref_tx_phy = (_pref_tx_phy), \
+	.pref_rx_phy = (_pref_rx_phy), \
+}
+
+/** Helper to declare PHY parameters inline
+ *
+ * @param _pref_tx_phy Bitmask of preferred transmit PHYs.
+ * @param _pref_rx_phy Bitmask of preferred receive PHYs.
+ */
+#define BT_CONN_LE_PHY_PARAM(_pref_tx_phy, _pref_rx_phy) \
+	((struct bt_conn_le_phy_param []) { \
+		BT_CONN_LE_PHY_PARAM_INIT(_pref_tx_phy, _pref_rx_phy) \
+	 })
+
+/** Only LE 1M PHY */
+#define BT_CONN_LE_PHY_PARAM_1M BT_CONN_LE_PHY_PARAM(BT_GAP_LE_PHY_1M, \
+						     BT_GAP_LE_PHY_1M)
+
+/** Only LE 2M PHY */
+#define BT_CONN_LE_PHY_PARAM_2M BT_CONN_LE_PHY_PARAM(BT_GAP_LE_PHY_2M, \
+						     BT_GAP_LE_PHY_2M)
+
+/** Only LE Coded PHY. */
+#define BT_CONN_LE_PHY_PARAM_CODED BT_CONN_LE_PHY_PARAM(BT_GAP_LE_PHY_CODED, \
+							BT_GAP_LE_PHY_CODED)
+
+/** All LE PHYs. */
+#define BT_CONN_LE_PHY_PARAM_ALL BT_CONN_LE_PHY_PARAM(BT_GAP_LE_PHY_1M |   \
+						      BT_GAP_LE_PHY_2M |   \
+						      BT_GAP_LE_PHY_CODED, \
+						      BT_GAP_LE_PHY_1M |   \
+						      BT_GAP_LE_PHY_2M |   \
+						      BT_GAP_LE_PHY_CODED)
+
+/** Connection data length information for LE connections */
+struct bt_conn_le_data_len_info {
+	/** Maximum Link Layer transmission payload size in bytes. */
+	uint16_t tx_max_len;
+	/** Maximum Link Layer transmission payload time in us. */
+	uint16_t tx_max_time;
+	/** Maximum Link Layer reception payload size in bytes. */
+	uint16_t rx_max_len;
+	/** Maximum Link Layer reception payload time in us. */
+	uint16_t rx_max_time;
+};
+
+/** Connection data length parameters for LE connections */
+struct bt_conn_le_data_len_param {
+	/** Maximum Link Layer transmission payload size in bytes. */
+	uint16_t tx_max_len;
+	/** Maximum Link Layer transmission payload time in us. */
+	uint16_t tx_max_time;
+};
+
+/** Initialize transmit data length parameters
+ *
+ * @param  _tx_max_len  Maximum Link Layer transmission payload size in bytes.
+ * @param  _tx_max_time Maximum Link Layer transmission payload time in us.
+ */
+#define BT_CONN_LE_DATA_LEN_PARAM_INIT(_tx_max_len, _tx_max_time) \
+{ \
+	.tx_max_len = (_tx_max_len), \
+	.tx_max_time = (_tx_max_time), \
+}
+
+/** Helper to declare transmit data length parameters inline
+ *
+ * @param  _tx_max_len  Maximum Link Layer transmission payload size in bytes.
+ * @param  _tx_max_time Maximum Link Layer transmission payload time in us.
+ */
+#define BT_CONN_LE_DATA_LEN_PARAM(_tx_max_len, _tx_max_time) \
+	((struct bt_conn_le_data_len_param[]) { \
+		BT_CONN_LE_DATA_LEN_PARAM_INIT(_tx_max_len, _tx_max_time) \
+	 })
+
+/** Default LE data length parameters. */
+#define BT_LE_DATA_LEN_PARAM_DEFAULT \
+	BT_CONN_LE_DATA_LEN_PARAM(BT_GAP_DATA_LEN_DEFAULT, \
+				  BT_GAP_DATA_TIME_DEFAULT)
+
+/** Maximum LE data length parameters. */
+#define BT_LE_DATA_LEN_PARAM_MAX \
+	BT_CONN_LE_DATA_LEN_PARAM(BT_GAP_DATA_LEN_MAX, \
+				  BT_GAP_DATA_TIME_MAX)
+
+/** @brief Increment a connection's reference count.
+ *
+ *  Increment the reference count of a connection object.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Connection object with incremented reference count.
+ */
+struct bt_conn *bt_conn_ref(struct bt_conn *conn);
+
+/** @brief Decrement a connection's reference count.
+ *
+ *  Decrement the reference count of a connection object.
+ *
+ *  @param conn Connection object.
+ */
+void bt_conn_unref(struct bt_conn *conn);
+
+/** @brief Iterate through all existing connections.
+ *
+ * @param type  Connection Type
+ * @param func  Function to call for each connection.
+ * @param data  Data to pass to the callback function.
+ */
+void bt_conn_foreach(int type, void (*func)(struct bt_conn *conn, void *data),
+		     void *data);
+
+/** @brief Look up an existing connection by address.
+ *
+ *  Look up an existing connection based on the remote address.
+ *
+ *  The caller gets a new reference to the connection object which must be
+ *  released with bt_conn_unref() once done using the object.
+ *
+ *  @param id   Local identity (in most cases BT_ID_DEFAULT).
+ *  @param peer Remote address.
+ *
+ *  @return Connection object or NULL if not found.
+ */
+struct bt_conn *bt_conn_lookup_addr_le(uint8_t id, const bt_addr_le_t *peer);
+
+/** @brief Get destination (peer) address of a connection.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Destination address.
+ */
+const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn);
+
+/** @brief Get array index of a connection
+ *
+ *  This function is used to map bt_conn to index of an array of
+ *  connections. The array has CONFIG_BT_MAX_CONN elements.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Index of the connection object.
+ *          The range of the returned value is 0..CONFIG_BT_MAX_CONN-1
+ */
+uint8_t bt_conn_index(struct bt_conn *conn);
+
+/** Connection Type */
+enum {
+	/** LE Connection Type */
+	BT_CONN_TYPE_LE = BIT(0),
+	/** BR/EDR Connection Type */
+	BT_CONN_TYPE_BR = BIT(1),
+	/** SCO Connection Type */
+	BT_CONN_TYPE_SCO = BIT(2),
+	/** ISO Connection Type */
+	BT_CONN_TYPE_ISO = BIT(3),
+	/** All Connection Type */
+	BT_CONN_TYPE_ALL = BT_CONN_TYPE_LE | BT_CONN_TYPE_BR |
+			   BT_CONN_TYPE_SCO | BT_CONN_TYPE_ISO,
+};
+
+/** LE Connection Info Structure */
+struct bt_conn_le_info {
+	/** Source (Local) Identity Address */
+	const bt_addr_le_t *src;
+	/** Destination (Remote) Identity Address or remote Resolvable Private
+	 *  Address (RPA) before identity has been resolved.
+	 */
+	const bt_addr_le_t *dst;
+	/** Local device address used during connection setup. */
+	const bt_addr_le_t *local;
+	/** Remote device address used during connection setup. */
+	const bt_addr_le_t *remote;
+	uint16_t interval; /** Connection interval */
+	uint16_t latency; /** Connection slave latency */
+	uint16_t timeout; /** Connection supervision timeout */
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	const struct bt_conn_le_phy_info      *phy;
+#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	/* Connection maximum single fragment parameters */
+	const struct bt_conn_le_data_len_info *data_len;
+#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */
+};
+
+/** BR/EDR Connection Info Structure */
+struct bt_conn_br_info {
+	const bt_addr_t *dst; /** Destination (Remote) BR/EDR address */
+};
+
+/** Connection role (master or slave) */
+enum {
+	BT_CONN_ROLE_MASTER,
+	BT_CONN_ROLE_SLAVE,
+};
+
+/** Connection Info Structure */
+struct bt_conn_info {
+	/** Connection Type. */
+	uint8_t type;
+	/** Connection Role. */
+	uint8_t role;
+	/** Which local identity the connection was created with */
+	uint8_t id;
+	/** Connection Type specific Info.*/
+	union {
+		/** LE Connection specific Info. */
+		struct bt_conn_le_info le;
+		/** BR/EDR Connection specific Info. */
+		struct bt_conn_br_info br;
+	};
+};
+
+/** LE Connection Remote Info Structure */
+struct bt_conn_le_remote_info {
+
+	/** Remote LE feature set (bitmask). */
+	const uint8_t *features;
+};
+
+/** BR/EDR Connection Remote Info structure */
+struct bt_conn_br_remote_info {
+
+	/** Remote feature set (pages of bitmasks). */
+	const uint8_t *features;
+
+	/** Number of pages in the remote feature set. */
+	uint8_t num_pages;
+};
+
+/** @brief Connection Remote Info Structure
+ *
+ *  @note The version, manufacturer and subversion fields will only contain
+ *        valid data if @option{CONFIG_BT_REMOTE_VERSION} is enabled.
+ */
+struct bt_conn_remote_info {
+	/** Connection Type */
+	uint8_t  type;
+
+	/** Remote Link Layer version */
+	uint8_t  version;
+
+	/** Remote manufacturer identifier */
+	uint16_t manufacturer;
+
+	/** Per-manufacturer unique revision */
+	uint16_t subversion;
+
+	union {
+		/** LE connection remote info */
+		struct bt_conn_le_remote_info le;
+
+		/** BR/EDR connection remote info */
+		struct bt_conn_br_remote_info br;
+	};
+};
+
+/** @brief Get connection info
+ *
+ *  @param conn Connection object.
+ *  @param info Connection info object.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info);
+
+/** @brief Get connection info for the remote device.
+ *
+ *  @param conn Connection object.
+ *  @param remote_info Connection remote info object.
+ *
+ *  @note In order to retrieve the remote version (version, manufacturer
+ *  and subversion) @option{CONFIG_BT_REMOTE_VERSION} must be enabled
+ *
+ *  @note The remote information is exchanged directly after the connection has
+ *  been established. The application can be notified about when the remote
+ *  information is available through the remote_info_available callback.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ *  @return -EBUSY The remote information is not yet available.
+ */
+int bt_conn_get_remote_info(struct bt_conn *conn,
+			    struct bt_conn_remote_info *remote_info);
+
+/** @brief Update the connection parameters.
+ *
+ *  @param conn Connection object.
+ *  @param param Updated connection parameters.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_le_param_update(struct bt_conn *conn,
+			    const struct bt_le_conn_param *param);
+
+/** @brief Update the connection transmit data length parameters.
+ *
+ *  @param conn  Connection object.
+ *  @param param Updated data length parameters.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_le_data_len_update(struct bt_conn *conn,
+			       const struct bt_conn_le_data_len_param *param);
+
+/** @brief Update the connection PHY parameters.
+ *
+ *  Update the preferred transmit and receive PHYs of the connection.
+ *  Use @ref BT_GAP_LE_PHY_NONE to indicate no preference.
+ *
+ *  @param conn Connection object.
+ *  @param param Updated connection parameters.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_le_phy_update(struct bt_conn *conn,
+			  const struct bt_conn_le_phy_param *param);
+
+/** @brief Disconnect from a remote device or cancel pending connection.
+ *
+ *  Disconnect an active connection with the specified reason code or cancel
+ *  pending outgoing connection.
+ *
+ *  @param conn Connection to disconnect.
+ *  @param reason Reason code for the disconnection.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason);
+
+enum {
+	/** Convenience value when no options are specified. */
+	BT_CONN_LE_OPT_NONE = 0,
+
+	/** @brief Enable LE Coded PHY.
+	 *
+	 *  Enable scanning on the LE Coded PHY.
+	 */
+	BT_CONN_LE_OPT_CODED = BIT(0),
+
+	/** @brief Disable LE 1M PHY.
+	 *
+	 *  Disable scanning on the LE 1M PHY.
+	 *
+	 *  @note Requires @ref BT_CONN_LE_OPT_CODED.
+	 */
+	BT_CONN_LE_OPT_NO_1M = BIT(1),
+};
+
+struct bt_conn_le_create_param {
+
+	/** Bit-field of create connection options. */
+	uint32_t options;
+
+	/** Scan interval (N * 0.625 ms) */
+	uint16_t interval;
+
+	/** Scan window (N * 0.625 ms) */
+	uint16_t window;
+
+	/** @brief Scan interval LE Coded PHY (N * 0.625 MS)
+	 *
+	 *  Set zero to use same as LE 1M PHY scan interval
+	 */
+	uint16_t interval_coded;
+
+	/** @brief Scan window LE Coded PHY (N * 0.625 MS)
+	 *
+	 *  Set zero to use same as LE 1M PHY scan window.
+	 */
+	uint16_t window_coded;
+
+	/** @brief Connection initiation timeout (N * 10 MS)
+	 *
+	 *  Set zero to use the default @option{CONFIG_BT_CREATE_CONN_TIMEOUT}
+	 *  timeout.
+	 *
+	 *  @note Unused in @ref bt_conn_create_auto_le
+	 */
+	uint16_t timeout;
+};
+
+/** @brief Initialize create connection parameters
+ *
+ *  @param _options  Create connection options.
+ *  @param _interval Create connection scan interval (N * 0.625 ms).
+ *  @param _window   Create connection scan window (N * 0.625 ms).
+ */
+#define BT_CONN_LE_CREATE_PARAM_INIT(_options, _interval, _window) \
+{ \
+	.options = (_options), \
+	.interval = (_interval), \
+	.window = (_window), \
+	.interval_coded = 0, \
+	.window_coded = 0, \
+	.timeout = 0, \
+}
+
+/** Helper to declare create connection parameters inline
+ *
+ *  @param _options  Create connection options.
+ *  @param _interval Create connection scan interval (N * 0.625 ms).
+ *  @param _window   Create connection scan window (N * 0.625 ms).
+ */
+#define BT_CONN_LE_CREATE_PARAM(_options, _interval, _window) \
+	((struct bt_conn_le_create_param[]) { \
+		BT_CONN_LE_CREATE_PARAM_INIT(_options, _interval, _window) \
+	 })
+
+/** Default LE create connection parameters.
+ *  Scan continuously by setting scan interval equal to scan window.
+ */
+#define BT_CONN_LE_CREATE_CONN \
+	BT_CONN_LE_CREATE_PARAM(BT_CONN_LE_OPT_NONE, \
+				BT_GAP_SCAN_FAST_INTERVAL, \
+				BT_GAP_SCAN_FAST_INTERVAL)
+
+/** Default LE create connection using whitelist parameters.
+ *  Scan window:   30 ms.
+ *  Scan interval: 60 ms.
+ */
+#define BT_CONN_LE_CREATE_CONN_AUTO \
+	BT_CONN_LE_CREATE_PARAM(BT_CONN_LE_OPT_NONE, \
+				BT_GAP_SCAN_FAST_INTERVAL, \
+				BT_GAP_SCAN_FAST_WINDOW)
+
+/** @brief Initiate an LE connection to a remote device.
+ *
+ *  Allows initiate new LE link to remote peer using its address.
+ *
+ *  The caller gets a new reference to the connection object which must be
+ *  released with bt_conn_unref() once done using the object.
+ *
+ *  This uses the General Connection Establishment procedure.
+ *
+ *  @param[in]  peer         Remote address.
+ *  @param[in]  create_param Create connection parameters.
+ *  @param[in]  conn_param   Initial connection parameters.
+ *  @param[out] conn         Valid connection object on success.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_le_create(const bt_addr_le_t *peer,
+		      const struct bt_conn_le_create_param *create_param,
+		      const struct bt_le_conn_param *conn_param,
+		      struct bt_conn **conn);
+
+__deprecated static inline
+struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer,
+				  const struct bt_le_conn_param *conn_param)
+{
+	struct bt_conn *conn;
+	struct bt_conn_le_create_param param = BT_CONN_LE_CREATE_PARAM_INIT(
+						BT_CONN_LE_OPT_NONE,
+						BT_GAP_SCAN_FAST_INTERVAL,
+						BT_GAP_SCAN_FAST_INTERVAL);
+
+	if (bt_conn_le_create(peer, &param, conn_param,
+			      &conn)) {
+		return NULL;
+	}
+
+	return conn;
+}
+
+/** @brief Automatically connect to remote devices in whitelist.
+ *
+ *  This uses the Auto Connection Establishment procedure.
+ *  The procedure will continue until a single connection is established or the
+ *  procedure is stopped through @ref bt_conn_create_auto_stop.
+ *  To establish connections to all devices in the whitelist the procedure
+ *  should be started again in the connected callback after a new connection has
+ *  been established.
+ *
+ *  @param create_param Create connection parameters
+ *  @param conn_param   Initial connection parameters.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ *  @return -ENOMEM No free connection object available.
+ */
+int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param,
+			   const struct bt_le_conn_param *conn_param);
+
+__deprecated static inline
+int bt_conn_create_auto_le(const struct bt_le_conn_param *conn_param)
+{
+	struct bt_conn_le_create_param param = BT_CONN_LE_CREATE_PARAM_INIT(
+						BT_CONN_LE_OPT_NONE,
+						BT_GAP_SCAN_FAST_INTERVAL,
+						BT_GAP_SCAN_FAST_WINDOW);
+
+	return bt_conn_le_create_auto(&param, conn_param);
+}
+
+/** @brief Stop automatic connect creation.
+ *
+ *  @return Zero on success or (negative) error code on failure.
+ */
+int bt_conn_create_auto_stop(void);
+
+/** @brief Automatically connect to remote device if it's in range.
+ *
+ *  This function enables/disables automatic connection initiation.
+ *  Every time the device loses the connection with peer, this connection
+ *  will be re-established if connectable advertisement from peer is received.
+ *
+ *  @note Auto connect is disabled during explicit scanning.
+ *
+ *  @param addr Remote Bluetooth address.
+ *  @param param If non-NULL, auto connect is enabled with the given
+ *  parameters. If NULL, auto connect is disabled.
+ *
+ *  @return Zero on success or error code otherwise.
+ */
+int bt_le_set_auto_conn(const bt_addr_le_t *addr,
+			const struct bt_le_conn_param *param);
+
+/** @brief Initiate directed advertising to a remote device
+ *
+ *  Allows initiating a new LE connection to remote peer with the remote
+ *  acting in central role and the local device in peripheral role.
+ *
+ *  The advertising type will either be BT_LE_ADV_DIRECT_IND, or
+ *  BT_LE_ADV_DIRECT_IND_LOW_DUTY if the BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY
+ *  option was used as part of the advertising parameters.
+ *
+ *  In case of high duty cycle this will result in a callback with
+ *  connected() with a new connection or with an error.
+ *
+ *  The advertising may be canceled with bt_conn_disconnect().
+ *
+ *  The caller gets a new reference to the connection object which must be
+ *  released with bt_conn_unref() once done using the object.
+ *
+ *  @param peer  Remote address.
+ *  @param param Directed advertising parameters.
+ *
+ *  @return Valid connection object on success or NULL otherwise.
+ */
+__deprecated static inline
+struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer,
+					const struct bt_le_adv_param *param)
+{
+	struct bt_le_adv_param adv_param = *param;
+
+	adv_param.options |= (BT_LE_ADV_OPT_CONNECTABLE |
+			      BT_LE_ADV_OPT_ONE_TIME);
+	adv_param.peer = peer;
+
+	if (!bt_le_adv_start(&adv_param, NULL, 0, NULL, 0)) {
+		return NULL;
+	}
+
+	return bt_conn_lookup_addr_le(param->id, peer);
+}
+
+/** Security level. */
+typedef enum __packed {
+	/** Level 0: Only for BR/EDR special cases, like SDP */
+	BT_SECURITY_L0,
+	/** Level 1: No encryption and no authentication. */
+	BT_SECURITY_L1,
+	/** Level 2: Encryption and no authentication (no MITM). */
+	BT_SECURITY_L2,
+	/** Level 3: Encryption and authentication (MITM). */
+	BT_SECURITY_L3,
+	/** Level 4: Authenticated Secure Connections and 128-bit key. */
+	BT_SECURITY_L4,
+
+	BT_SECURITY_NONE   __deprecated = BT_SECURITY_L0,
+	BT_SECURITY_LOW    __deprecated = BT_SECURITY_L1,
+	BT_SECURITY_MEDIUM __deprecated = BT_SECURITY_L2,
+	BT_SECURITY_HIGH   __deprecated = BT_SECURITY_L3,
+	BT_SECURITY_FIPS   __deprecated = BT_SECURITY_L4,
+
+	/** Bit to force new pairing procedure, bit-wise OR with requested
+	 *  security level.
+	 */
+	BT_SECURITY_FORCE_PAIR = BIT(7),
+} bt_security_t;
+
+/** @brief Set security level for a connection.
+ *
+ *  This function enable security (encryption) for a connection. If device is
+ *  already paired with sufficiently strong key encryption will be enabled. If
+ *  link is already encrypted with sufficiently strong key this function does
+ *  nothing.
+ *
+ *  If device is not paired pairing will be initiated. If device is paired and
+ *  keys are too weak but input output capabilities allow for strong enough keys
+ *  pairing will be initiated.
+ *
+ *  This function may return error if required level of security is not possible
+ *  to achieve due to local or remote device limitation (e.g., input output
+ *  capabilities), or if the maximum number of paired devices has been reached.
+ *
+ *  This function may return error if the pairing procedure has already been
+ *  initiated by the local device or the peer device.
+ *
+ *  @note When @option{CONFIG_BT_SMP_SC_ONLY} is enabled then the security
+ *        level will always be level 4.
+ *
+ *  @note When @option{CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY} is enabled then the
+ *        security level will always be level 3.
+ *
+ *  @param conn Connection object.
+ *  @param sec Requested security level.
+ *
+ *  @return 0 on success or negative error
+ */
+int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec);
+
+/** @brief Get security level for a connection.
+ *
+ *  @return Connection security level
+ */
+bt_security_t bt_conn_get_security(struct bt_conn *conn);
+
+static inline int __deprecated bt_conn_security(struct bt_conn *conn,
+						bt_security_t sec)
+{
+	return bt_conn_set_security(conn, sec);
+}
+
+/** @brief Get encryption key size.
+ *
+ *  This function gets encryption key size.
+ *  If there is no security (encryption) enabled 0 will be returned.
+ *
+ *  @param conn Existing connection object.
+ *
+ *  @return Encryption key size.
+ */
+uint8_t bt_conn_enc_key_size(struct bt_conn *conn);
+
+enum bt_security_err {
+	/** Security procedure successful. */
+	BT_SECURITY_ERR_SUCCESS,
+
+	/** Authentication failed. */
+	BT_SECURITY_ERR_AUTH_FAIL,
+
+	/** PIN or encryption key is missing. */
+	BT_SECURITY_ERR_PIN_OR_KEY_MISSING,
+
+	/** OOB data is not available.  */
+	BT_SECURITY_ERR_OOB_NOT_AVAILABLE,
+
+	/** The requested security level could not be reached. */
+	BT_SECURITY_ERR_AUTH_REQUIREMENT,
+
+	/** Pairing is not supported */
+	BT_SECURITY_ERR_PAIR_NOT_SUPPORTED,
+
+	/** Pairing is not allowed. */
+	BT_SECURITY_ERR_PAIR_NOT_ALLOWED,
+
+	/** Invalid parameters. */
+	BT_SECURITY_ERR_INVALID_PARAM,
+
+	/** Pairing failed but the exact reason could not be specified. */
+	BT_SECURITY_ERR_UNSPECIFIED,
+};
+
+/** @brief Connection callback structure.
+ *
+ *  This structure is used for tracking the state of a connection.
+ *  It is registered with the help of the bt_conn_cb_register() API.
+ *  It's permissible to register multiple instances of this @ref bt_conn_cb
+ *  type, in case different modules of an application are interested in
+ *  tracking the connection state. If a callback is not of interest for
+ *  an instance, it may be set to NULL and will as a consequence not be
+ *  used for that instance.
+ */
+struct bt_conn_cb {
+	/** @brief A new connection has been established.
+	 *
+	 *  This callback notifies the application of a new connection.
+	 *  In case the err parameter is non-zero it means that the
+	 *  connection establishment failed.
+	 *
+	 *  @param conn New connection object.
+	 *  @param err HCI error. Zero for success, non-zero otherwise.
+	 *
+	 *  @p err can mean either of the following:
+	 *  - @ref BT_HCI_ERR_UNKNOWN_CONN_ID Creating the connection started by
+	 *    @ref bt_conn_create_le was canceled either by the user through
+	 *    @ref bt_conn_disconnect or by the timeout in the host through
+	 *    @ref bt_conn_le_create_param timeout parameter, which defaults to
+	 *    @option{CONFIG_BT_CREATE_CONN_TIMEOUT} seconds.
+	 *  - @p BT_HCI_ERR_ADV_TIMEOUT High duty cycle directed connectable
+	 *    advertiser started by @ref bt_le_adv_start failed to be connected
+	 *    within the timeout.
+	 */
+	void (*connected)(struct bt_conn *conn, uint8_t err);
+
+	/** @brief A connection has been disconnected.
+	 *
+	 *  This callback notifies the application that a connection
+	 *  has been disconnected.
+	 *
+	 *  When this callback is called the stack still has one reference to
+	 *  the connection object. If the application in this callback tries to
+	 *  start either a connectable advertiser or create a new connection
+	 *  this might fail because there are no free connection objects
+	 *  available.
+	 *  To avoid this issue it is recommended to either start connectable
+	 *  advertise or create a new connection using @ref k_work_submit or
+	 *  increase @option{CONFIG_BT_MAX_CONN}.
+	 *
+	 *  @param conn Connection object.
+	 *  @param reason HCI reason for the disconnection.
+	 */
+	void (*disconnected)(struct bt_conn *conn, uint8_t reason);
+
+	/** @brief LE connection parameter update request.
+	 *
+	 *  This callback notifies the application that a remote device
+	 *  is requesting to update the connection parameters. The
+	 *  application accepts the parameters by returning true, or
+	 *  rejects them by returning false. Before accepting, the
+	 *  application may also adjust the parameters to better suit
+	 *  its needs.
+	 *
+	 *  It is recommended for an application to have just one of these
+	 *  callbacks for simplicity. However, if an application registers
+	 *  multiple it needs to manage the potentially different
+	 *  requirements for each callback. Each callback gets the
+	 *  parameters as returned by previous callbacks, i.e. they are not
+	 *  necessarily the same ones as the remote originally sent.
+	 *
+	 *  @param conn Connection object.
+	 *  @param param Proposed connection parameters.
+	 *
+	 *  @return true to accept the parameters, or false to reject them.
+	 */
+	bool (*le_param_req)(struct bt_conn *conn,
+			     struct bt_le_conn_param *param);
+
+	/** @brief The parameters for an LE connection have been updated.
+	 *
+	 *  This callback notifies the application that the connection
+	 *  parameters for an LE connection have been updated.
+	 *
+	 *  @param conn Connection object.
+	 *  @param interval Connection interval.
+	 *  @param latency Connection latency.
+	 *  @param timeout Connection supervision timeout.
+	 */
+	void (*le_param_updated)(struct bt_conn *conn, uint16_t interval,
+				 uint16_t latency, uint16_t timeout);
+#if defined(CONFIG_BT_SMP)
+	/** @brief Remote Identity Address has been resolved.
+	 *
+	 *  This callback notifies the application that a remote
+	 *  Identity Address has been resolved
+	 *
+	 *  @param conn Connection object.
+	 *  @param rpa Resolvable Private Address.
+	 *  @param identity Identity Address.
+	 */
+	void (*identity_resolved)(struct bt_conn *conn,
+				  const bt_addr_le_t *rpa,
+				  const bt_addr_le_t *identity);
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	/** @brief The security level of a connection has changed.
+	 *
+	 *  This callback notifies the application that the security level
+	 *  of a connection has changed.
+	 *
+	 *  @param conn Connection object.
+	 *  @param level New security level of the connection.
+	 *  @param err Security error. Zero for success, non-zero otherwise.
+	 */
+	void (*security_changed)(struct bt_conn *conn, bt_security_t level,
+				 enum bt_security_err err);
+#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
+
+#if defined(CONFIG_BT_REMOTE_INFO)
+	/** @brief Remote information procedures has completed.
+	 *
+	 *  This callback notifies the application that the remote information
+	 *  has been retrieved from the remote peer.
+	 *
+	 *  @param conn Connection object.
+	 *  @param remote_info Connection information of remote device.
+	 */
+	void (*remote_info_available)(struct bt_conn *conn,
+				      struct bt_conn_remote_info *remote_info);
+#endif /* defined(CONFIG_BT_REMOTE_INFO) */
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	/** @brief The PHY of the connection has changed.
+	 *
+	 *  This callback notifies the application that the PHY of the
+	 *  connection has changed.
+	 *
+	 *  @param conn Connection object.
+	 *  @param info Connection LE PHY information.
+	 */
+	void (*le_phy_updated)(struct bt_conn *conn,
+			       struct bt_conn_le_phy_info *param);
+#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	/** @brief The data length parameters of the connection has changed.
+	 *
+	 *  This callback notifies the application that the maximum Link Layer
+	 *  payload length or transmission time has changed.
+	 *
+	 *  @param conn Connection object.
+	 *  @param info Connection data length information.
+	 */
+	void (*le_data_len_updated)(struct bt_conn *conn,
+				    struct bt_conn_le_data_len_info *info);
+#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
+
+	struct bt_conn_cb *_next;
+};
+
+/** @brief Register connection callbacks.
+ *
+ *  Register callbacks to monitor the state of connections.
+ *
+ *  @param cb Callback struct. Must point to memory that remains valid.
+ */
+void bt_conn_cb_register(struct bt_conn_cb *cb);
+
+/** @brief Enable/disable bonding.
+ *
+ *  Set/clear the Bonding flag in the Authentication Requirements of
+ *  SMP Pairing Request/Response data.
+ *  The initial value of this flag depends on BT_BONDABLE Kconfig setting.
+ *  For the vast majority of applications calling this function shouldn't be
+ *  needed.
+ *
+ *  @param enable Value allowing/disallowing to be bondable.
+ */
+void bt_set_bondable(bool enable);
+
+/** @brief Allow/disallow remote OOB data to be used for pairing.
+ *
+ *  Set/clear the OOB data flag for SMP Pairing Request/Response data.
+ *  The initial value of this flag depends on BT_OOB_DATA_PRESENT Kconfig
+ *  setting.
+ *
+ *  @param enable Value allowing/disallowing remote OOB data.
+ */
+void bt_set_oob_data_flag(bool enable);
+
+/** @brief Set OOB Temporary Key to be used for pairing
+ *
+ *  This function allows to set OOB data for the LE legacy pairing procedure.
+ *  The function should only be called in response to the oob_data_request()
+ *  callback provided that the legacy method is user pairing.
+ *
+ *  @param conn Connection object
+ *  @param tk Pointer to 16 byte long TK array
+ *
+ *  @return Zero on success or -EINVAL if NULL
+ */
+int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk);
+
+/** @brief Set OOB data during LE Secure Connections (SC) pairing procedure
+ *
+ *  This function allows to set OOB data during the LE SC pairing procedure.
+ *  The function should only be called in response to the oob_data_request()
+ *  callback provided that LE SC method is used for pairing.
+ *
+ *  The user should submit OOB data according to the information received in the
+ *  callback. This may yield three different configurations: with only local OOB
+ *  data present, with only remote OOB data present or with both local and
+ *  remote OOB data present.
+ *
+ *  @param conn Connection object
+ *  @param oobd_local Local OOB data or NULL if not present
+ *  @param oobd_remote Remote OOB data or NULL if not present
+ *
+ *  @return Zero on success or error code otherwise, positive in case of
+ *          protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_oob_set_sc_data(struct bt_conn *conn,
+			  const struct bt_le_oob_sc_data *oobd_local,
+			  const struct bt_le_oob_sc_data *oobd_remote);
+
+/** @brief Get OOB data used for LE Secure Connections (SC) pairing procedure
+ *
+ *  This function allows to get OOB data during the LE SC pairing procedure that
+ *  were set by the bt_le_oob_set_sc_data() API.
+ *
+ *  @note The OOB data will only be available as long as the connection object
+ *  associated with it is valid.
+ *
+ *  @param conn Connection object
+ *  @param oobd_local Local OOB data or NULL if not set
+ *  @param oobd_remote Remote OOB data or NULL if not set
+ *
+ *  @return Zero on success or error code otherwise, positive in case of
+ *          protocol error or negative (POSIX) in case of stack internal error.
+ */
+int bt_le_oob_get_sc_data(struct bt_conn *conn,
+			  const struct bt_le_oob_sc_data **oobd_local,
+			  const struct bt_le_oob_sc_data **oobd_remote);
+
+/** @def BT_PASSKEY_INVALID
+ *
+ *  Special passkey value that can be used to disable a previously
+ *  set fixed passkey.
+ */
+#define BT_PASSKEY_INVALID 0xffffffff
+
+/** @brief Set a fixed passkey to be used for pairing.
+ *
+ *  This API is only available when the CONFIG_BT_FIXED_PASSKEY
+ *  configuration option has been enabled.
+ *
+ *  Sets a fixed passkey to be used for pairing. If set, the
+ *  pairing_confim() callback will be called for all incoming pairings.
+ *
+ *  @param passkey A valid passkey (0 - 999999) or BT_PASSKEY_INVALID
+ *                 to disable a previously set fixed passkey.
+ *
+ *  @return 0 on success or a negative error code on failure.
+ */
+int bt_passkey_set(unsigned int passkey);
+
+/** Info Structure for OOB pairing */
+struct bt_conn_oob_info {
+	/** Type of OOB pairing method */
+	enum {
+		/** LE legacy pairing */
+		BT_CONN_OOB_LE_LEGACY,
+
+		/** LE SC pairing */
+		BT_CONN_OOB_LE_SC,
+	} type;
+
+	union {
+		/** LE Secure Connections OOB pairing parameters */
+		struct {
+			/** OOB data configuration */
+			enum {
+				/** Local OOB data requested */
+				BT_CONN_OOB_LOCAL_ONLY,
+
+				/** Remote OOB data requested */
+				BT_CONN_OOB_REMOTE_ONLY,
+
+				/** Both local and remote OOB data requested */
+				BT_CONN_OOB_BOTH_PEERS,
+
+				/** No OOB data requested */
+				BT_CONN_OOB_NO_DATA,
+			} oob_config;
+		} lesc;
+	};
+};
+
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+/** @brief Pairing request and pairing response info structure.
+ *
+ *  This structure is the same for both smp_pairing_req and smp_pairing_rsp
+ *  and a subset of the packet data, except for the initial Code octet.
+ *  It is documented in Core Spec. Vol. 3, Part H, 3.5.1 and 3.5.2.
+ */
+struct bt_conn_pairing_feat {
+	/** IO Capability, Core Spec. Vol 3, Part H, 3.5.1, Table 3.4 */
+	uint8_t io_capability;
+
+	/** OOB data flag, Core Spec. Vol 3, Part H, 3.5.1, Table 3.5 */
+	uint8_t oob_data_flag;
+
+	/** AuthReq, Core Spec. Vol 3, Part H, 3.5.1, Fig. 3.3 */
+	uint8_t auth_req;
+
+	/** Maximum Encryption Key Size, Core Spec. Vol 3, Part H, 3.5.1 */
+	uint8_t max_enc_key_size;
+
+	/** Initiator Key Distribution/Generation, Core Spec. Vol 3, Part H,
+	 *  3.6.1, Fig. 3.11
+	 */
+	uint8_t init_key_dist;
+
+	/** Responder Key Distribution/Generation, Core Spec. Vol 3, Part H
+	 *  3.6.1, Fig. 3.11
+	 */
+	uint8_t resp_key_dist;
+};
+#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
+
+/** Authenticated pairing callback structure */
+struct bt_conn_auth_cb {
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	/** @brief Query to proceed incoming pairing or not.
+	 *
+	 *  On any incoming pairing req/rsp this callback will be called for
+	 *  the application to decide whether to allow for the pairing to
+	 *  continue.
+	 *
+	 *  The pairing info received from the peer is passed to assist
+	 *  making the decision.
+	 *
+	 *  As this callback is synchronous the application should return
+	 *  a response value immediately. Otherwise it may affect the
+	 *  timing during pairing. Hence, this information should not be
+	 *  conveyed to the user to take action.
+	 *
+	 *  The remaining callbacks are not affected by this, but do notice
+	 *  that other callbacks can be called during the pairing. Eg. if
+	 *  pairing_confirm is registered both will be called for Just-Works
+	 *  pairings.
+	 *
+	 *  This callback may be unregistered in which case pairing continues
+	 *  as if the Kconfig flag was not set.
+	 *
+	 *  This callback is not called for BR/EDR Secure Simple Pairing (SSP).
+	 *
+	 *  @param conn Connection where pairing is initiated.
+	 *  @param feat Pairing req/resp info.
+	 */
+	enum bt_security_err (*pairing_accept)(struct bt_conn *conn,
+			      const struct bt_conn_pairing_feat *const feat);
+#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
+
+	/** @brief Display a passkey to the user.
+	 *
+	 *  When called the application is expected to display the given
+	 *  passkey to the user, with the expectation that the passkey will
+	 *  then be entered on the peer device. The passkey will be in the
+	 *  range of 0 - 999999, and is expected to be padded with zeroes so
+	 *  that six digits are always shown. E.g. the value 37 should be
+	 *  shown as 000037.
+	 *
+	 *  This callback may be set to NULL, which means that the local
+	 *  device lacks the ability do display a passkey. If set
+	 *  to non-NULL the cancel callback must also be provided, since
+	 *  this is the only way the application can find out that it should
+	 *  stop displaying the passkey.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 *  @param passkey Passkey to show to the user.
+	 */
+	void (*passkey_display)(struct bt_conn *conn, unsigned int passkey);
+
+	/** @brief Request the user to enter a passkey.
+	 *
+	 *  When called the user is expected to enter a passkey. The passkey
+	 *  must be in the range of 0 - 999999, and should be expected to
+	 *  be zero-padded, as that's how the peer device will typically be
+	 *  showing it (e.g. 37 would be shown as 000037).
+	 *
+	 *  Once the user has entered the passkey its value should be given
+	 *  to the stack using the bt_conn_auth_passkey_entry() API.
+	 *
+	 *  This callback may be set to NULL, which means that the local
+	 *  device lacks the ability to enter a passkey. If set to non-NULL
+	 *  the cancel callback must also be provided, since this is the
+	 *  only way the application can find out that it should stop
+	 *  requesting the user to enter a passkey.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 */
+	void (*passkey_entry)(struct bt_conn *conn);
+
+	/** @brief Request the user to confirm a passkey.
+	 *
+	 *  When called the user is expected to confirm that the given
+	 *  passkey is also shown on the peer device.. The passkey will
+	 *  be in the range of 0 - 999999, and should be zero-padded to
+	 *  always be six digits (e.g. 37 would be shown as 000037).
+	 *
+	 *  Once the user has confirmed the passkey to match, the
+	 *  bt_conn_auth_passkey_confirm() API should be called. If the
+	 *  user concluded that the passkey doesn't match the
+	 *  bt_conn_auth_cancel() API should be called.
+	 *
+	 *  This callback may be set to NULL, which means that the local
+	 *  device lacks the ability to confirm a passkey. If set to non-NULL
+	 *  the cancel callback must also be provided, since this is the
+	 *  only way the application can find out that it should stop
+	 *  requesting the user to confirm a passkey.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 *  @param passkey Passkey to be confirmed.
+	 */
+	void (*passkey_confirm)(struct bt_conn *conn, unsigned int passkey);
+
+	/** @brief Request the user to provide Out of Band (OOB) data.
+	 *
+	 *  When called the user is expected to provide OOB data. The required
+	 *  data are indicated by the information structure.
+	 *
+	 *  For LE Secure Connections OOB pairing, the user should provide
+	 *  local OOB data, remote OOB data or both depending on their
+	 *  availability. Their value should be given to the stack using the
+	 *  bt_le_oob_set_sc_data() API.
+	 *
+	 *  This callback must be set to non-NULL in order to support OOB
+	 *  pairing.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 *  @param info OOB pairing information.
+	 */
+	void (*oob_data_request)(struct bt_conn *conn,
+				 struct bt_conn_oob_info *info);
+
+	/** @brief Cancel the ongoing user request.
+	 *
+	 *  This callback will be called to notify the application that it
+	 *  should cancel any previous user request (passkey display, entry
+	 *  or confirmation).
+	 *
+	 *  This may be set to NULL, but must always be provided whenever the
+	 *  passkey_display, passkey_entry passkey_confirm or pairing_confirm
+	 *  callback has been provided.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 */
+	void (*cancel)(struct bt_conn *conn);
+
+	/** @brief Request confirmation for an incoming pairing.
+	 *
+	 *  This callback will be called to confirm an incoming pairing
+	 *  request where none of the other user callbacks is applicable.
+	 *
+	 *  If the user decides to accept the pairing the
+	 *  bt_conn_auth_pairing_confirm() API should be called. If the
+	 *  user decides to reject the pairing the bt_conn_auth_cancel() API
+	 *  should be called.
+	 *
+	 *  This callback may be set to NULL, which means that the local
+	 *  device lacks the ability to confirm a pairing request. If set
+	 *  to non-NULL the cancel callback must also be provided, since
+	 *  this is the only way the application can find out that it should
+	 *  stop requesting the user to confirm a pairing request.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 */
+	void (*pairing_confirm)(struct bt_conn *conn);
+
+#if defined(CONFIG_BT_BREDR)
+	/** @brief Request the user to enter a passkey.
+	 *
+	 *  This callback will be called for a BR/EDR (Bluetooth Classic)
+	 *  connection where pairing is being performed. Once called the
+	 *  user is expected to enter a PIN code with a length between
+	 *  1 and 16 digits. If the @a highsec parameter is set to true
+	 *  the PIN code must be 16 digits long.
+	 *
+	 *  Once entered, the PIN code should be given to the stack using
+	 *  the bt_conn_auth_pincode_entry() API.
+	 *
+	 *  This callback may be set to NULL, however in that case pairing
+	 *  over BR/EDR will not be possible. If provided, the cancel
+	 *  callback must be provided as well.
+	 *
+	 *  @param conn Connection where pairing is currently active.
+	 *  @param highsec true if 16 digit PIN is required.
+	 */
+	void (*pincode_entry)(struct bt_conn *conn, bool highsec);
+#endif
+
+	/** @brief notify that pairing process was complete.
+	 *
+	 *  This callback notifies the application that the pairing process
+	 *  has been completed.
+	 *
+	 *  @param conn Connection object.
+	 *  @param bonded pairing is bonded or not.
+	 */
+	void (*pairing_complete)(struct bt_conn *conn, bool bonded);
+
+	/** @brief notify that pairing process has failed.
+	 *
+	 *  @param conn Connection object.
+	 *  @param reason Pairing failed reason
+	 */
+	void (*pairing_failed)(struct bt_conn *conn,
+			       enum bt_security_err reason);
+
+	/** @brief Notify that bond has been deleted.
+	 *
+	 *  This callback notifies the application that the bond information
+	 *  for the remote peer has been deleted
+	 *
+	 *  @param id   Which local identity had the bond.
+	 *  @param peer Remote address.
+	 */
+	void (*bond_deleted)(uint8_t id, const bt_addr_le_t *peer);
+};
+
+/** @brief Register authentication callbacks.
+ *
+ *  Register callbacks to handle authenticated pairing. Passing NULL
+ *  unregisters a previous callbacks structure.
+ *
+ *  @param cb Callback struct.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb);
+
+/** @brief Reply with entered passkey.
+ *
+ *  This function should be called only after passkey_entry callback from
+ *  bt_conn_auth_cb structure was called.
+ *
+ *  @param conn Connection object.
+ *  @param passkey Entered passkey.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
+
+/** @brief Cancel ongoing authenticated pairing.
+ *
+ *  This function allows to cancel ongoing authenticated pairing.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_cancel(struct bt_conn *conn);
+
+/** @brief Reply if passkey was confirmed to match by user.
+ *
+ *  This function should be called only after passkey_confirm callback from
+ *  bt_conn_auth_cb structure was called.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_passkey_confirm(struct bt_conn *conn);
+
+/** @brief Reply if incoming pairing was confirmed by user.
+ *
+ *  This function should be called only after pairing_confirm callback from
+ *  bt_conn_auth_cb structure was called if user confirmed incoming pairing.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_pairing_confirm(struct bt_conn *conn);
+
+/** @brief Reply with entered PIN code.
+ *
+ *  This function should be called only after PIN code callback from
+ *  bt_conn_auth_cb structure was called. It's for legacy 2.0 devices.
+ *
+ *  @param conn Connection object.
+ *  @param pin Entered PIN code.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin);
+
+/** Connection parameters for BR/EDR connections */
+struct bt_br_conn_param {
+	bool allow_role_switch;
+};
+
+/** @brief Initialize BR/EDR connection parameters
+ *
+ *  @param role_switch True if role switch is allowed
+ */
+#define BT_BR_CONN_PARAM_INIT(role_switch) \
+{ \
+	.allow_role_switch = (role_switch), \
+}
+
+/** Helper to declare BR/EDR connection parameters inline
+  *
+  * @param role_switch True if role switch is allowed
+  */
+#define BT_BR_CONN_PARAM(role_switch) \
+	((struct bt_br_conn_param[]) { \
+		BT_BR_CONN_PARAM_INIT(role_switch) \
+	 })
+
+/** Default BR/EDR connection parameters:
+ *    Role switch allowed
+ */
+#define BT_BR_CONN_PARAM_DEFAULT BT_BR_CONN_PARAM(true)
+
+
+/** @brief Initiate an BR/EDR connection to a remote device.
+ *
+ *  Allows initiate new BR/EDR link to remote peer using its address.
+ *
+ *  The caller gets a new reference to the connection object which must be
+ *  released with bt_conn_unref() once done using the object.
+ *
+ *  @param peer  Remote address.
+ *  @param param Initial connection parameters.
+ *
+ *  @return Valid connection object on success or NULL otherwise.
+ */
+struct bt_conn *bt_conn_create_br(const bt_addr_t *peer,
+				  const struct bt_br_conn_param *param);
+
+/** @brief Initiate an SCO connection to a remote device.
+ *
+ *  Allows initiate new SCO link to remote peer using its address.
+ *
+ *  The caller gets a new reference to the connection object which must be
+ *  released with bt_conn_unref() once done using the object.
+ *
+ *  @param peer  Remote address.
+ *
+ *  @return Valid connection object on success or NULL otherwise.
+ */
+struct bt_conn *bt_conn_create_sco(const bt_addr_t *peer);
+
+void bt_conn_tx_polling(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CONN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/controller.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/controller.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/controller.h	(working copy)
@@ -0,0 +1,39 @@
+/** @file
+ *  @brief Bluetooth subsystem controller APIs.
+ */
+
+/*
+ * Copyright (c) 2018 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_
+
+/**
+ * @brief Bluetooth Controller
+ * @defgroup bt_ctrl Bluetooth Controller
+ * @ingroup bluetooth
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Set public address for controller
+ *
+ *  Should be called before bt_enable().
+ *
+ *  @param addr Public address
+ */
+void bt_ctlr_set_public_addr(const uint8_t *addr);
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CONTROLLER_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/crypto.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/crypto.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/crypto.h	(working copy)
@@ -0,0 +1,126 @@
+/** @file
+ *  @brief Bluetooth subsystem crypto APIs.
+ */
+
+/*
+ * Copyright (c) 2017-2020 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_CRYPTO_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_CRYPTO_H_
+
+/**
+ * @brief Cryptography
+ * @defgroup bt_crypto Cryptography
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Generate random data.
+ *
+ *  A random number generation helper which utilizes the Bluetooth
+ *  controller's own RNG.
+ *
+ *  @param buf Buffer to insert the random data
+ *  @param len Length of random data to generate
+ *
+ *  @return Zero on success or error code otherwise, positive in case
+ *  of protocol error or negative (POSIX) in case of stack internal error
+ */
+int bt_rand(void *buf, size_t len);
+
+/** @brief AES encrypt little-endian data.
+ *
+ *  An AES encrypt helper is used to request the Bluetooth controller's own
+ *  hardware to encrypt the plaintext using the key and returns the encrypted
+ *  data.
+ *
+ *  @param key 128 bit LS byte first key for the encryption of the plaintext
+ *  @param plaintext 128 bit LS byte first plaintext data block to be encrypted
+ *  @param enc_data 128 bit LS byte first encrypted data block
+ *
+ *  @return Zero on success or error code otherwise.
+ */
+int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16]);
+
+/** @brief AES encrypt big-endian data.
+ *
+ *  An AES encrypt helper is used to request the Bluetooth controller's own
+ *  hardware to encrypt the plaintext using the key and returns the encrypted
+ *  data.
+ *
+ *  @param key 128 bit MS byte first key for the encryption of the plaintext
+ *  @param plaintext 128 bit MS byte first plaintext data block to be encrypted
+ *  @param enc_data 128 bit MS byte first encrypted data block
+ *
+ *  @return Zero on success or error code otherwise.
+ */
+int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16]);
+
+
+/** @brief Decrypt big-endian data with AES-CCM.
+ *
+ *  Decrypts and authorizes @c enc_data with AES-CCM, as described in
+ *  https://tools.ietf.org/html/rfc3610.
+ *
+ *  Assumes that the MIC follows directly after the encrypted data.
+ *
+ *  @param key       128 bit MS byte first key
+ *  @param nonce     13 byte MS byte first nonce
+ *  @param enc_data  Encrypted data
+ *  @param len       Length of the encrypted data
+ *  @param aad       Additional input data
+ *  @param aad_len   Additional input data length
+ *  @param plaintext Plaintext buffer to place result in
+ *  @param mic_size  Size of the trailing MIC (in bytes)
+ *
+ *  @retval 0        Successfully decrypted the data.
+ *  @retval -EINVAL  Invalid parameters.
+ *  @retval -EBADMSG Authentication failed.
+ */
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+		   size_t len, const uint8_t *aad, size_t aad_len,
+		   uint8_t *plaintext, size_t mic_size);
+
+
+/** @brief Encrypt big-endian data with AES-CCM.
+ *
+ *  Encrypts and generates a MIC from @c plaintext with AES-CCM, as described in
+ *  https://tools.ietf.org/html/rfc3610.
+ *
+ *  Places the MIC directly after the encrypted data.
+ *
+ *  @param key       128 bit MS byte first key
+ *  @param nonce     13 byte MS byte first nonce
+ *  @param enc_data  Buffer to place encrypted data in
+ *  @param len       Length of the encrypted data
+ *  @param aad       Additional input data
+ *  @param aad_len   Additional input data length
+ *  @param plaintext Plaintext buffer to encrypt
+ *  @param mic_size  Size of the trailing MIC (in bytes)
+ *
+ *  @retval 0        Successfully encrypted the data.
+ *  @retval -EINVAL  Invalid parameters.
+ */
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+		   size_t len, const uint8_t *aad, size_t aad_len,
+		   uint8_t *plaintext, size_t mic_size);
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_CRYPTO_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/gap.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/gap.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/gap.h	(working copy)
@@ -0,0 +1,171 @@
+/** @file
+ *  @brief Bluetooth Generic Access Profile defines and Assigned Numbers.
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_GAP_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_GAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Bluetooth Generic Access Profile defines and Assigned Numbers.
+ * @defgroup bt_gap_defines Defines and Assigned Numbers
+ * @ingroup bluetooth
+ * @{
+ */
+
+/** Company Identifiers (see Bluetooth Assigned Numbers) */
+#define BT_COMP_ID_LF           0x05f1 /* The Linux Foundation */
+
+/** EIR/AD data type definitions */
+#define BT_DATA_FLAGS                   0x01 /* AD flags */
+#define BT_DATA_UUID16_SOME             0x02 /* 16-bit UUID, more available */
+#define BT_DATA_UUID16_ALL              0x03 /* 16-bit UUID, all listed */
+#define BT_DATA_UUID32_SOME             0x04 /* 32-bit UUID, more available */
+#define BT_DATA_UUID32_ALL              0x05 /* 32-bit UUID, all listed */
+#define BT_DATA_UUID128_SOME            0x06 /* 128-bit UUID, more available */
+#define BT_DATA_UUID128_ALL             0x07 /* 128-bit UUID, all listed */
+#define BT_DATA_NAME_SHORTENED          0x08 /* Shortened name */
+#define BT_DATA_NAME_COMPLETE           0x09 /* Complete name */
+#define BT_DATA_TX_POWER                0x0a /* Tx Power */
+#define BT_DATA_SM_TK_VALUE             0x10 /* Security Manager TK Value */
+#define BT_DATA_SM_OOB_FLAGS            0x11 /* Security Manager OOB Flags */
+#define BT_DATA_SOLICIT16               0x14 /* Solicit UUIDs, 16-bit */
+#define BT_DATA_SOLICIT128              0x15 /* Solicit UUIDs, 128-bit */
+#define BT_DATA_SVC_DATA16              0x16 /* Service data, 16-bit UUID */
+#define BT_DATA_GAP_APPEARANCE          0x19 /* GAP appearance */
+#define BT_DATA_LE_BT_DEVICE_ADDRESS    0x1b /* LE Bluetooth Device Address */
+#define BT_DATA_LE_ROLE                 0x1c /* LE Role */
+#define BT_DATA_SOLICIT32               0x1f /* Solicit UUIDs, 32-bit */
+#define BT_DATA_SVC_DATA32              0x20 /* Service data, 32-bit UUID */
+#define BT_DATA_SVC_DATA128             0x21 /* Service data, 128-bit UUID */
+#define BT_DATA_LE_SC_CONFIRM_VALUE     0x22 /* LE SC Confirmation Value */
+#define BT_DATA_LE_SC_RANDOM_VALUE      0x23 /* LE SC Random Value */
+#define BT_DATA_URI                     0x24 /* URI */
+#define BT_DATA_MESH_PROV               0x29 /* Mesh Provisioning PDU */
+#define BT_DATA_MESH_MESSAGE            0x2a /* Mesh Networking PDU */
+#define BT_DATA_MESH_BEACON             0x2b /* Mesh Beacon */
+
+#define BT_DATA_MANUFACTURER_DATA       0xff /* Manufacturer Specific Data */
+
+#define BT_LE_AD_LIMITED                0x01 /* Limited Discoverable */
+#define BT_LE_AD_GENERAL                0x02 /* General Discoverable */
+#define BT_LE_AD_NO_BREDR               0x04 /* BR/EDR not supported */
+
+/* Defined GAP timers */
+#define BT_GAP_SCAN_FAST_INTERVAL               0x0060  /* 60 ms    */
+#define BT_GAP_SCAN_FAST_WINDOW                 0x0030  /* 30 ms    */
+#define BT_GAP_SCAN_SLOW_INTERVAL_1             0x0800  /* 1.28 s   */
+#define BT_GAP_SCAN_SLOW_WINDOW_1               0x0012  /* 11.25 ms */
+#define BT_GAP_SCAN_SLOW_INTERVAL_2             0x1000  /* 2.56 s   */
+#define BT_GAP_SCAN_SLOW_WINDOW_2               0x0012  /* 11.25 ms */
+#define BT_GAP_ADV_FAST_INT_MIN_1               0x0030  /* 30 ms    */
+#define BT_GAP_ADV_FAST_INT_MAX_1               0x0060  /* 60 ms    */
+#define BT_GAP_ADV_FAST_INT_MIN_2               0x00a0  /* 100 ms   */
+#define BT_GAP_ADV_FAST_INT_MAX_2               0x00f0  /* 150 ms   */
+#define BT_GAP_ADV_SLOW_INT_MIN                 0x0640  /* 1 s      */
+#define BT_GAP_ADV_SLOW_INT_MAX                 0x0780  /* 1.2 s    */
+#define BT_GAP_INIT_CONN_INT_MIN                0x0018  /* 30 ms    */
+#define BT_GAP_INIT_CONN_INT_MAX                0x0028  /* 50 ms    */
+
+/** LE PHY types */
+enum {
+	/** Convenience macro for when no PHY is set. */
+	BT_GAP_LE_PHY_NONE                    = 0,
+	/** LE 1M PHY */
+	BT_GAP_LE_PHY_1M                      = BIT(0),
+	 /** LE 2M PHY */
+	BT_GAP_LE_PHY_2M                      = BIT(1),
+	/** LE Coded PHY */
+	BT_GAP_LE_PHY_CODED                   = BIT(2),
+};
+
+/** Advertising PDU types */
+enum {
+	/** Scannable and connectable advertising. */
+	BT_GAP_ADV_TYPE_ADV_IND               = 0x00,
+	/** Directed connectable advertising. */
+	BT_GAP_ADV_TYPE_ADV_DIRECT_IND        = 0x01,
+	/** Non-connectable and scannable advertising. */
+	BT_GAP_ADV_TYPE_ADV_SCAN_IND          = 0x02,
+	/** Non-connectable and non-scannable advertising. */
+	BT_GAP_ADV_TYPE_ADV_NONCONN_IND       = 0x03,
+	/** Additional advertising data requested by an active scanner. */
+	BT_GAP_ADV_TYPE_SCAN_RSP              = 0x04,
+	/** Extended advertising, see advertising properties. */
+	BT_GAP_ADV_TYPE_EXT_ADV               = 0x05,
+};
+
+/** Advertising PDU properties */
+enum {
+	/** Connectable advertising. */
+	BT_GAP_ADV_PROP_CONNECTABLE           = BIT(0),
+	/** Scannable advertising. */
+	BT_GAP_ADV_PROP_SCANNABLE             = BIT(1),
+	/** Directed advertising. */
+	BT_GAP_ADV_PROP_DIRECTED              = BIT(2),
+	/** Additional advertising data requested by an active scanner. */
+	BT_GAP_ADV_PROP_SCAN_RESPONSE         = BIT(3),
+	/** Extended advertising. */
+	BT_GAP_ADV_PROP_EXT_ADV               = BIT(4),
+};
+
+/** Maximum advertising data length. */
+#define BT_GAP_ADV_MAX_ADV_DATA_LEN             31
+/** Maximum extended advertising data length.
+ *
+ *  @note The maximum advertising data length that can be sent by an extended
+ *        advertiser is defined by the controller.
+ */
+#define BT_GAP_ADV_MAX_EXT_ADV_DATA_LEN         1650
+
+#define BT_GAP_TX_POWER_INVALID                 0x7f
+#define BT_GAP_RSSI_INVALID                     0x7f
+#define BT_GAP_SID_INVALID                      0xff
+#define BT_GAP_NO_TIMEOUT                       0x0000
+
+/* The maximum allowed high duty cycle directed advertising timeout, 1.28
+ * seconds in 10 ms unit.
+ */
+#define BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT  128
+
+#define BT_GAP_DATA_LEN_DEFAULT                 0x001b /* 27 bytes */
+#define BT_GAP_DATA_LEN_MAX                     0x00fb /* 251 bytes */
+
+#define BT_GAP_DATA_TIME_DEFAULT                0x0148 /* 328 us */
+#define BT_GAP_DATA_TIME_MAX                    0x4290 /* 17040 us */
+
+#define BT_GAP_SID_MAX                          0x0F
+#define BT_GAP_PER_ADV_MAX_MAX_SKIP             0x01F3
+#define BT_GAP_PER_ADV_MAX_MAX_TIMEOUT          0x4000
+
+
+/** Constant Tone Extension (CTE) types */
+enum {
+	/** Angle of Arrival */
+	BT_GAP_CTE_AOA = 0x00,
+	/** Angle of Departure with 1 us slots */
+	BT_GAP_CTE_AOD_1US = 0x01,
+	/** Angle of Departure with 2 us slots */
+	BT_GAP_CTE_AOD_2US = 0x02,
+	/** No extensions */
+	BT_GAP_CTE_NONE = 0xFF,
+};
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_GAP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/gatt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/gatt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/gatt.h	(working copy)
@@ -0,0 +1,1551 @@
+/** @file
+ *  @brief Generic Attribute Profile handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_GATT_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_GATT_H_
+
+/**
+ * @brief Generic Attribute Profile (GATT)
+ * @defgroup bt_gatt Generic Attribute Profile (GATT)
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <stddef.h>
+#include <sys/util.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/att.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** GATT attribute permission bit field values */
+enum {
+	/** No operations supported, e.g. for notify-only */
+	BT_GATT_PERM_NONE = 0,
+
+	/** Attribute read permission. */
+	BT_GATT_PERM_READ = BIT(0),
+
+	/** Attribute write permission. */
+	BT_GATT_PERM_WRITE = BIT(1),
+
+	/** @brief Attribute read permission with encryption.
+	 *
+	 *  If set, requires encryption for read access.
+	 */
+	BT_GATT_PERM_READ_ENCRYPT = BIT(2),
+
+	/** @brief Attribute write permission with encryption.
+	 *
+	 *  If set, requires encryption for write access.
+	 */
+	BT_GATT_PERM_WRITE_ENCRYPT = BIT(3),
+
+	/** @brief Attribute read permission with authentication.
+	 *
+	 *  If set, requires encryption using authenticated link-key for read
+	 *  access.
+	 */
+	BT_GATT_PERM_READ_AUTHEN = BIT(4),
+
+	/** @brief Attribute write permission with authentication.
+	 *
+	 *  If set, requires encryption using authenticated link-key for write
+	 *  access.
+	 */
+	BT_GATT_PERM_WRITE_AUTHEN = BIT(5),
+
+	/** @brief Attribute prepare write permission.
+	 *
+	 *  If set, allows prepare writes with use of BT_GATT_WRITE_FLAG_PREPARE
+	 *  passed to write callback.
+	 */
+	BT_GATT_PERM_PREPARE_WRITE = BIT(6),
+};
+
+/** @def BT_GATT_ERR
+ *  @brief Construct error return value for attribute read and write callbacks.
+ *
+ *  @param _att_err ATT error code
+ *
+ *  @return Appropriate error code for the attribute callbacks.
+ */
+#define BT_GATT_ERR(_att_err) (-(_att_err))
+
+/** GATT attribute write flags */
+enum {
+	/** @brief Attribute prepare write flag
+	 *
+	 * If set, write callback should only check if the device is
+	 * authorized but no data shall be written.
+	 */
+	BT_GATT_WRITE_FLAG_PREPARE = BIT(0),
+
+	/** @brief Attribute write command flag
+	 *
+	 * If set, indicates that write operation is a command (Write without
+	 * response) which doesn't generate any response.
+	 */
+	BT_GATT_WRITE_FLAG_CMD = BIT(1),
+};
+
+/** @brief GATT Attribute structure. */
+struct bt_gatt_attr {
+	/** Attribute UUID */
+	const struct bt_uuid *uuid;
+
+	/** @brief Attribute read callback
+	 *
+	 *  The callback can also be used locally to read the contents of the
+	 *  attribute in which case no connection will be set.
+	 *
+	 *  @param conn   The connection that is requesting to read
+	 *  @param attr   The attribute that's being read
+	 *  @param buf    Buffer to place the read result in
+	 *  @param len    Length of data to read
+	 *  @param offset Offset to start reading from
+	 *
+	 *  @return Number fo bytes read, or in case of an error
+	 *          BT_GATT_ERR() with a specific ATT error code.
+	 */
+	ssize_t (*read)(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			void *buf, uint16_t len, uint16_t offset);
+
+	/** @brief Attribute write callback
+	 *
+	 *  @param conn   The connection that is requesting to write
+	 *  @param attr   The attribute that's being written
+	 *  @param buf    Buffer with the data to write
+	 *  @param len    Number of bytes in the buffer
+	 *  @param offset Offset to start writing from
+	 *  @param flags  Flags (BT_GATT_WRITE_*)
+	 *
+	 *  @return Number of bytes written, or in case of an error
+	 *          BT_GATT_ERR() with a specific ATT error code.
+	 */
+	ssize_t	(*write)(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 const void *buf, uint16_t len, uint16_t offset,
+			 uint8_t flags);
+
+	/** Attribute user data */
+	void *user_data;
+	/** Attribute handle */
+	uint16_t handle;
+	/** Attribute permissions */
+	uint8_t perm;
+};
+
+/** @brief GATT Service structure */
+struct bt_gatt_service_static {
+	/** Service Attributes */
+	const struct bt_gatt_attr *attrs;
+	/** Service Attribute count */
+	size_t attr_count;
+};
+
+/** @brief GATT Service structure */
+struct bt_gatt_service {
+	/** Service Attributes */
+	struct bt_gatt_attr *attrs;
+	/** Service Attribute count */
+	size_t attr_count;
+
+	sys_snode_t node;
+};
+
+/** @brief Service Attribute Value. */
+struct bt_gatt_service_val {
+	/** Service UUID. */
+	const struct bt_uuid *uuid;
+	/** Service end handle. */
+	uint16_t end_handle;
+};
+
+/** @brief Include Attribute Value. */
+struct bt_gatt_include {
+	/** Service UUID. */
+	const struct bt_uuid *uuid;
+	/** Service start handle. */
+	uint16_t start_handle;
+	/** Service end handle. */
+	uint16_t end_handle;
+};
+
+/** Characteristic Properties Bit field values */
+
+/** @def BT_GATT_CHRC_BROADCAST
+ *  @brief Characteristic broadcast property.
+ *
+ *  If set, permits broadcasts of the Characteristic Value using Server
+ *  Characteristic Configuration Descriptor.
+ */
+#define BT_GATT_CHRC_BROADCAST			0x01
+/** @def BT_GATT_CHRC_READ
+ *  @brief Characteristic read property.
+ *
+ *  If set, permits reads of the Characteristic Value.
+ */
+#define BT_GATT_CHRC_READ			0x02
+/** @def BT_GATT_CHRC_WRITE_WITHOUT_RESP
+ *  @brief Characteristic write without response property.
+ *
+ *  If set, permits write of the Characteristic Value without response.
+ */
+#define BT_GATT_CHRC_WRITE_WITHOUT_RESP		0x04
+/** @def BT_GATT_CHRC_WRITE
+ *  @brief Characteristic write with response property.
+ *
+ *  If set, permits write of the Characteristic Value with response.
+ */
+#define BT_GATT_CHRC_WRITE			0x08
+/** @def BT_GATT_CHRC_NOTIFY
+ *  @brief Characteristic notify property.
+ *
+ *  If set, permits notifications of a Characteristic Value without
+ *  acknowledgment.
+ */
+#define BT_GATT_CHRC_NOTIFY			0x10
+/** @def BT_GATT_CHRC_INDICATE
+ *  @brief Characteristic indicate property.
+ *
+ * If set, permits indications of a Characteristic Value with acknowledgment.
+ */
+#define BT_GATT_CHRC_INDICATE			0x20
+/** @def BT_GATT_CHRC_AUTH
+ *  @brief Characteristic Authenticated Signed Writes property.
+ *
+ *  If set, permits signed writes to the Characteristic Value.
+ */
+#define BT_GATT_CHRC_AUTH			0x40
+/** @def BT_GATT_CHRC_EXT_PROP
+ *  @brief Characteristic Extended Properties property.
+ *
+ * If set, additional characteristic properties are defined in the
+ * Characteristic Extended Properties Descriptor.
+ */
+#define BT_GATT_CHRC_EXT_PROP			0x80
+
+/** @brief Characteristic Attribute Value. */
+struct bt_gatt_chrc {
+	/** Characteristic UUID. */
+	const struct bt_uuid *uuid;
+	/** Characteristic Value handle. */
+	uint16_t value_handle;
+	/** Characteristic properties. */
+	uint8_t	properties;
+};
+
+/** Characteristic Extended Properties Bit field values */
+#define BT_GATT_CEP_RELIABLE_WRITE		0x0001
+#define BT_GATT_CEP_WRITABLE_AUX		0x0002
+
+/** @brief Characteristic Extended Properties Attribute Value. */
+struct bt_gatt_cep {
+	/** Characteristic Extended properties */
+	uint16_t properties;
+};
+
+/** Client Characteristic Configuration Values */
+
+/** @def BT_GATT_CCC_NOTIFY
+ *  @brief Client Characteristic Configuration Notification.
+ *
+ *  If set, changes to Characteristic Value shall be notified.
+ */
+#define BT_GATT_CCC_NOTIFY			0x0001
+/** @def BT_GATT_CCC_INDICATE
+ *  @brief Client Characteristic Configuration Indication.
+ *
+ *  If set, changes to Characteristic Value shall be indicated.
+ */
+#define BT_GATT_CCC_INDICATE			0x0002
+
+/** Client Characteristic Configuration Attribute Value */
+struct bt_gatt_ccc {
+	/** Client Characteristic Configuration flags */
+	uint16_t flags;
+};
+
+/** @brief GATT Characteristic Presentation Format Attribute Value. */
+struct bt_gatt_cpf {
+	/** Format of the value of the characteristic */
+	uint8_t format;
+	/** Exponent field to determine how the value of this characteristic is
+	 * further formatted
+	 */
+	int8_t exponent;
+	/** Unit of the characteristic */
+	uint16_t unit;
+	/** Name space of the description */
+	uint8_t name_space;
+	/** Description of the characteristic as defined in a higher layer profile */
+	uint16_t description;
+} __packed;
+
+/**
+ * @defgroup bt_gatt_server GATT Server APIs
+ * @ingroup bt_gatt
+ * @{
+ */
+
+/** @brief Register GATT service.
+ *
+ *  Register GATT service. Applications can make use of
+ *  macros such as BT_GATT_PRIMARY_SERVICE, BT_GATT_CHARACTERISTIC,
+ *  BT_GATT_DESCRIPTOR, etc.
+ *
+ *  When using @option{CONFIG_BT_SETTINGS} then all services that should have
+ *  bond configuration loaded, i.e. CCC values, must be registered before
+ *  calling @ref settings_load.
+ *
+ *  When using @option{CONFIG_BT_GATT_CACHING} and @option{CONFIG_BT_SETTINGS}
+ *  then all services that should be included in the GATT Database Hash
+ *  calculation should be added before calling @ref settings_load.
+ *  All services registered after settings_load will trigger a new database hash
+ *  calculation and a new hash stored.
+ *
+ *  @param svc Service containing the available attributes
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_service_register(struct bt_gatt_service *svc);
+
+/** @brief Unregister GATT service.
+ * *
+ *  @param svc Service to be unregistered.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_service_unregister(struct bt_gatt_service *svc);
+
+enum {
+	BT_GATT_ITER_STOP = 0,
+	BT_GATT_ITER_CONTINUE,
+};
+
+/** @typedef bt_gatt_attr_func_t
+ *  @brief Attribute iterator callback.
+ *
+ *  @param attr Attribute found.
+ *  @param handle Attribute handle found.
+ *  @param user_data Data given.
+ *
+ *  @return BT_GATT_ITER_CONTINUE if should continue to the next attribute.
+ *  @return BT_GATT_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_gatt_attr_func_t)(const struct bt_gatt_attr *attr,
+				       uint16_t handle,
+				       void *user_data);
+
+/** @brief Attribute iterator by type.
+ *
+ *  Iterate attributes in the given range matching given UUID and/or data.
+ *
+ *  @param start_handle Start handle.
+ *  @param end_handle End handle.
+ *  @param uuid UUID to match, passing NULL skips UUID matching.
+ *  @param attr_data Attribute data to match, passing NULL skips data matching.
+ *  @param num_matches Number matches, passing 0 makes it unlimited.
+ *  @param func Callback function.
+ *  @param user_data Data to pass to the callback.
+ */
+void bt_gatt_foreach_attr_type(uint16_t start_handle, uint16_t end_handle,
+			       const struct bt_uuid *uuid,
+			       const void *attr_data, uint16_t num_matches,
+			       bt_gatt_attr_func_t func,
+			       void *user_data);
+
+/** @brief Attribute iterator.
+ *
+ *  Iterate attributes in the given range.
+ *
+ *  @param start_handle Start handle.
+ *  @param end_handle End handle.
+ *  @param func Callback function.
+ *  @param user_data Data to pass to the callback.
+ */
+static inline void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle,
+					bt_gatt_attr_func_t func,
+					void *user_data)
+{
+	bt_gatt_foreach_attr_type(start_handle, end_handle, NULL, NULL, 0, func,
+				  user_data);
+}
+
+/** @brief Iterate to the next attribute
+ *
+ *  Iterate to the next attribute following a given attribute.
+ *
+ *  @param attr Current Attribute.
+ *
+ *  @return The next attribute or NULL if it cannot be found.
+ */
+struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr);
+
+/** @brief Get Attribute handle.
+ *
+ *  @param attr Attribute object.
+ *
+ *  @return Handle of the corresponding attribute or zero if the attribute
+ *          could not be found.
+ */
+uint16_t bt_gatt_attr_get_handle(const struct bt_gatt_attr *attr);
+
+/** @brief Get the handle of the characteristic value descriptor.
+ *
+ * @param attr A Characteristic Attribute.
+ *
+ * @note The user_data of the attribute must of type @ref bt_gatt_chrc.
+ *
+ * @return the handle of the corresponding Characteristic Value. The value will
+ *         be zero (the invalid handle) if @p attr was not a characteristic
+ *         attribute.
+ */
+uint16_t bt_gatt_attr_value_handle(const struct bt_gatt_attr *attr);
+
+/** @brief Generic Read Attribute value helper.
+ *
+ *  Read attribute value from local database storing the result into buffer.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value.
+ *  @param buf_len Buffer length.
+ *  @param offset Start offset.
+ *  @param value Attribute value.
+ *  @param value_len Length of the attribute value.
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			  void *buf, uint16_t buf_len, uint16_t offset,
+			  const void *value, uint16_t value_len);
+
+/** @brief Read Service Attribute helper.
+ *
+ *  Read service attribute value from local database storing the result into
+ *  buffer after encoding it.
+ *  @note Only use this with attributes which user_data is a bt_uuid.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value read.
+ *  @param len Buffer length.
+ *  @param offset Start offset.
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_service(struct bt_conn *conn,
+				  const struct bt_gatt_attr *attr,
+				  void *buf, uint16_t len, uint16_t offset);
+
+/** @def BT_GATT_SERVICE_DEFINE
+ *  @brief Statically define and register a service.
+ *
+ *  Helper macro to statically define and register a service.
+ *
+ *  @param _name Service name.
+ */
+#define BT_GATT_SERVICE_DEFINE(_name, ...)				\
+	const struct bt_gatt_attr attr_##_name[] = { __VA_ARGS__ };	\
+	const Z_STRUCT_SECTION_ITERABLE(bt_gatt_service_static, _name) =\
+						BT_GATT_SERVICE(attr_##_name);
+
+#define _BT_GATT_ATTRS_ARRAY_DEFINE(n, _instances, _attrs_def)	\
+	static struct bt_gatt_attr attrs_##n[] = _attrs_def(_instances[n]);
+
+#define _BT_GATT_SERVICE_ARRAY_ITEM(_n, _) BT_GATT_SERVICE(attrs_##_n),
+
+/** @def BT_GATT_SERVICE_INSTANCE_DEFINE
+ *  @brief Statically define service structure array.
+ *
+ *  Helper macro to statically define service structure array. Each element
+ *  of the array is linked to the service attribute array which is also
+ *  defined in this scope using _attrs_def macro.
+ *
+ *  @param _name         Name of service structure array.
+ *  @param _instances    Array of instances to pass as user context to the
+ *                       attribute callbacks.
+ *  @param _instance_num Number of elements in instance array.
+ *  @param _attrs_def    Macro provided by the user that defines attribute
+ *                       array for the serivce. This macro should accept single
+ *                       parameter which is the instance context.
+ */
+#define BT_GATT_SERVICE_INSTANCE_DEFINE(				 \
+	_name, _instances, _instance_num, _attrs_def)			 \
+	BUILD_ASSERT(ARRAY_SIZE(_instances) == _instance_num,		 \
+		"The number of array elements does not match its size"); \
+	UTIL_EVAL(UTIL_REPEAT(						 \
+		_instance_num, _BT_GATT_ATTRS_ARRAY_DEFINE, _instances,  \
+		_attrs_def))						 \
+	static struct bt_gatt_service _name[] = {			 \
+		UTIL_LISTIFY(_instance_num, _BT_GATT_SERVICE_ARRAY_ITEM) \
+	}
+
+/** @def BT_GATT_SERVICE
+ *  @brief Service Structure Declaration Macro.
+ *
+ *  Helper macro to declare a service structure.
+ *
+ *  @param _attrs Service attributes.
+ */
+#define BT_GATT_SERVICE(_attrs)						\
+{									\
+	.attrs = _attrs,						\
+	.attr_count = ARRAY_SIZE(_attrs),				\
+}
+
+/** @def BT_GATT_PRIMARY_SERVICE
+ *  @brief Primary Service Declaration Macro.
+ *
+ *  Helper macro to declare a primary service attribute.
+ *
+ *  @param _service Service attribute value.
+ */
+#define BT_GATT_PRIMARY_SERVICE(_service)				\
+	BT_GATT_ATTRIBUTE(BT_UUID_GATT_PRIMARY, BT_GATT_PERM_READ,	\
+			 bt_gatt_attr_read_service, NULL, _service)
+
+/** @def BT_GATT_SECONDARY_SERVICE
+ *  @brief Secondary Service Declaration Macro.
+ *
+ *  Helper macro to declare a secondary service attribute.
+ *
+ *  @param _service Service attribute value.
+ */
+#define BT_GATT_SECONDARY_SERVICE(_service)				\
+	BT_GATT_ATTRIBUTE(BT_UUID_GATT_SECONDARY, BT_GATT_PERM_READ,	\
+			 bt_gatt_attr_read_service, NULL, _service)
+
+/** @brief Read Include Attribute helper.
+ *
+ *  Read include service attribute value from local database storing the result
+ *  into buffer after encoding it.
+ *  @note Only use this with attributes which user_data is a bt_gatt_include.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value read.
+ *  @param len Buffer length.
+ *  @param offset Start offset.
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   void *buf, uint16_t len, uint16_t offset);
+
+/** @def BT_GATT_INCLUDE_SERVICE
+ *  @brief Include Service Declaration Macro.
+ *
+ *  Helper macro to declare database internal include service attribute.
+ *
+ *  @param _service_incl the first service attribute of service to include
+ */
+#define BT_GATT_INCLUDE_SERVICE(_service_incl)				\
+	BT_GATT_ATTRIBUTE(BT_UUID_GATT_INCLUDE, BT_GATT_PERM_READ,	\
+			  bt_gatt_attr_read_included, NULL, _service_incl)
+
+/** @brief Read Characteristic Attribute helper.
+ *
+ *  Read characteristic attribute value from local database storing the result
+ *  into buffer after encoding it.
+ *  @note Only use this with attributes which user_data is a bt_gatt_chrc.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value read.
+ *  @param len Buffer length.
+ *  @param offset Start offset.
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, void *buf,
+			       uint16_t len, uint16_t offset);
+
+#define BT_GATT_CHRC_INIT(_uuid, _handle, _props) \
+{                                                 \
+	.uuid = _uuid,                            \
+	.value_handle = _handle,                  \
+	.properties = _props,                     \
+}
+
+/** @def BT_GATT_CHARACTERISTIC
+ *  @brief Characteristic and Value Declaration Macro.
+ *
+ *  Helper macro to declare a characteristic attribute along with its
+ *  attribute value.
+ *
+ *  @param _uuid Characteristic attribute uuid.
+ *  @param _props Characteristic attribute properties.
+ *  @param _perm Characteristic Attribute access permissions.
+ *  @param _read Characteristic Attribute read callback.
+ *  @param _write Characteristic Attribute write callback.
+ *  @param _value Characteristic Attribute value.
+ */
+#define BT_GATT_CHARACTERISTIC(_uuid, _props, _perm, _read, _write, _value)  \
+	BT_GATT_ATTRIBUTE(BT_UUID_GATT_CHRC, BT_GATT_PERM_READ,              \
+			  bt_gatt_attr_read_chrc, NULL,                      \
+			  ((struct bt_gatt_chrc[]) {                         \
+				BT_GATT_CHRC_INIT(_uuid, 0U, _props),        \
+						   })),                      \
+	BT_GATT_ATTRIBUTE(_uuid, _perm, _read, _write, _value)
+
+#if IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)
+	#define BT_GATT_CCC_MAX (CONFIG_BT_MAX_CONN)
+#else
+	#define BT_GATT_CCC_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
+#endif
+
+/** @brief GATT CCC configuration entry. */
+struct bt_gatt_ccc_cfg {
+	/** Local identity, BT_ID_DEFAULT in most cases. */
+	uint8_t id;
+	/** Remote peer address. */
+	bt_addr_le_t peer;
+	/** Configuration value. */
+	uint16_t value;
+};
+
+/** Internal representation of CCC value */
+struct _bt_gatt_ccc {
+	/** Configuration for each connection */
+	struct bt_gatt_ccc_cfg cfg[BT_GATT_CCC_MAX];
+
+	/** Highest value of all connected peer's subscriptions */
+	uint16_t value;
+
+	/** @brief CCC attribute changed callback
+	 *
+	 *  @param attr   The attribute that's changed value
+	 *  @param value  New value
+	 */
+	void (*cfg_changed)(const struct bt_gatt_attr *attr, uint16_t value);
+
+	/** @brief CCC attribute write validation callback
+	 *
+	 *  @param conn   The connection that is requesting to write
+	 *  @param attr   The attribute that's being written
+	 *  @param value  CCC value to write
+	 *
+	 *  @return Number of bytes to write, or in case of an error
+	 *          BT_GATT_ERR() with a specific error code.
+	 */
+	ssize_t (*cfg_write)(struct bt_conn *conn,
+			     const struct bt_gatt_attr *attr, uint16_t value);
+
+	/** @brief CCC attribute match handler
+	 *
+	 *  Indicate if it is OK to send a notification or indication
+	 *  to the subscriber.
+	 *
+	 *  @param conn   The connection that is being checked
+	 *  @param attr   The attribute that's being checked
+	 *
+	 *  @return true  if application has approved notification/indication,
+	 *          false if application does not approve.
+	 */
+	bool (*cfg_match)(struct bt_conn *conn,
+			  const struct bt_gatt_attr *attr);
+};
+
+/** @brief Read Client Characteristic Configuration Attribute helper.
+ *
+ *  Read CCC attribute value from local database storing the result into buffer
+ *  after encoding it.
+ *
+ *  @note Only use this with attributes which user_data is a _bt_gatt_ccc.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value read.
+ *  @param len Buffer length.
+ *  @param offset Start offset.
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset);
+
+/** @brief Write Client Characteristic Configuration Attribute helper.
+ *
+ *  Write value in the buffer into CCC attribute.
+ *
+ *  @note Only use this with attributes which user_data is a _bt_gatt_ccc.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute to read.
+ *  @param buf Buffer to store the value read.
+ *  @param len Buffer length.
+ *  @param offset Start offset.
+ *  @param flags Write flags.
+ *
+ *  @return number of bytes written in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, const void *buf,
+			       uint16_t len, uint16_t offset, uint8_t flags);
+
+
+/** @def BT_GATT_CCC_INITIALIZER
+ *  @brief Initialize Client Characteristic Configuration Declaration Macro.
+ *
+ *  Helper macro to initialize a Managed CCC attribute value.
+ *
+ *  @param _changed Configuration changed callback.
+ *  @param _write Configuration write callback.
+ *  @param _match Configuration match callback.
+ */
+#define BT_GATT_CCC_INITIALIZER(_changed, _write, _match) \
+	{                                            \
+		.cfg = {},                           \
+		.cfg_changed = _changed,             \
+		.cfg_write = _write,                 \
+		.cfg_match = _match,                 \
+	}
+
+/** @def BT_GATT_CCC_MANAGED
+ *  @brief Managed Client Characteristic Configuration Declaration Macro.
+ *
+ *  Helper macro to declare a Managed CCC attribute.
+ *
+ *  @param _ccc CCC attribute user data, shall point to a _bt_gatt_ccc.
+ *  @param _perm CCC access permissions.
+ */
+#define BT_GATT_CCC_MANAGED(_ccc, _perm)				\
+	BT_GATT_ATTRIBUTE(BT_UUID_GATT_CCC, _perm,			\
+			bt_gatt_attr_read_ccc, bt_gatt_attr_write_ccc,  \
+			_ccc)
+
+/** @def BT_GATT_CCC
+ *  @brief Client Characteristic Configuration Declaration Macro.
+ *
+ *  Helper macro to declare a CCC attribute.
+ *
+ *  @param _changed Configuration changed callback.
+ *  @param _perm CCC access permissions.
+ */
+#define BT_GATT_CCC(_changed, _perm)				\
+	BT_GATT_CCC_MANAGED(((struct _bt_gatt_ccc[])			\
+		{BT_GATT_CCC_INITIALIZER(_changed, NULL, NULL)}), _perm)
+
+/** @brief Read Characteristic Extended Properties Attribute helper
+ *
+ *  Read CEP attribute value from local database storing the result into buffer
+ *  after encoding it.
+ *
+ *  @note Only use this with attributes which user_data is a bt_gatt_cep.
+ *
+ *  @param conn Connection object
+ *  @param attr Attribute to read
+ *  @param buf Buffer to store the value read
+ *  @param len Buffer length
+ *  @param offset Start offset
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset);
+
+/** @def BT_GATT_CEP
+ *  @brief Characteristic Extended Properties Declaration Macro.
+ *
+ *  Helper macro to declare a CEP attribute.
+ *
+ *  @param _value Descriptor attribute value.
+ */
+#define BT_GATT_CEP(_value)						\
+	BT_GATT_DESCRIPTOR(BT_UUID_GATT_CEP, BT_GATT_PERM_READ,		\
+			  bt_gatt_attr_read_cep, NULL, (void *)_value)
+
+/** @brief Read Characteristic User Description Descriptor Attribute helper
+ *
+ *  Read CUD attribute value from local database storing the result into buffer
+ *  after encoding it.
+ *
+ *  @note Only use this with attributes which user_data is a NULL-terminated C
+ *        string.
+ *
+ *  @param conn Connection object
+ *  @param attr Attribute to read
+ *  @param buf Buffer to store the value read
+ *  @param len Buffer length
+ *  @param offset Start offset
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset);
+
+/** @def BT_GATT_CUD
+ *  @brief Characteristic User Format Descriptor Declaration Macro.
+ *
+ *  Helper macro to declare a CUD attribute.
+ *
+ *  @param _value User description NULL-terminated C string.
+ *  @param _perm Descriptor attribute access permissions.
+ */
+#define BT_GATT_CUD(_value, _perm)					\
+	BT_GATT_DESCRIPTOR(BT_UUID_GATT_CUD, _perm, bt_gatt_attr_read_cud, \
+			   NULL, (void *)_value)
+
+/** @brief Read Characteristic Presentation format Descriptor Attribute helper
+ *
+ *  Read CPF attribute value from local database storing the result into buffer
+ *  after encoding it.
+ *
+ *  @note Only use this with attributes which user_data is a bt_gatt_pf.
+ *
+ *  @param conn Connection object
+ *  @param attr Attribute to read
+ *  @param buf Buffer to store the value read
+ *  @param len Buffer length
+ *  @param offset Start offset
+ *
+ *  @return number of bytes read in case of success or negative values in
+ *          case of error.
+ */
+ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset);
+
+/** @def BT_GATT_CPF
+ *  @brief Characteristic Presentation Format Descriptor Declaration Macro.
+ *
+ *  Helper macro to declare a CPF attribute.
+ *
+ *  @param _value Descriptor attribute value.
+ */
+#define BT_GATT_CPF(_value)						\
+	BT_GATT_DESCRIPTOR(BT_UUID_GATT_CPF, BT_GATT_PERM_READ,		\
+			  bt_gatt_attr_read_cpf, NULL, (void *)_value)
+
+/** @def BT_GATT_DESCRIPTOR
+ *  @brief Descriptor Declaration Macro.
+ *
+ *  Helper macro to declare a descriptor attribute.
+ *
+ *  @param _uuid Descriptor attribute uuid.
+ *  @param _perm Descriptor attribute access permissions.
+ *  @param _read Descriptor attribute read callback.
+ *  @param _write Descriptor attribute write callback.
+ *  @param _value Descriptor attribute value.
+ */
+#define BT_GATT_DESCRIPTOR(_uuid, _perm, _read, _write, _value)		\
+	BT_GATT_ATTRIBUTE(_uuid, _perm, _read, _write, _value)
+
+/** @def BT_GATT_ATTRIBUTE
+ *  @brief Attribute Declaration Macro.
+ *
+ *  Helper macro to declare an attribute.
+ *
+ *  @param _uuid Attribute uuid.
+ *  @param _perm Attribute access permissions.
+ *  @param _read Attribute read callback.
+ *  @param _write Attribute write callback.
+ *  @param _value Attribute value.
+ */
+#define BT_GATT_ATTRIBUTE(_uuid, _perm, _read, _write, _value)		\
+{									\
+	.uuid = _uuid,							\
+	.read = _read,							\
+	.write = _write,						\
+	.user_data = _value,						\
+	.handle = 0,							\
+	.perm = _perm,							\
+}
+
+/** @brief Notification complete result callback.
+ *
+ *  @param conn Connection object.
+ */
+typedef void (*bt_gatt_complete_func_t) (struct bt_conn *conn, void *user_data);
+
+struct bt_gatt_notify_params {
+	/** Notification Attribute UUID type */
+	const struct bt_uuid *uuid;
+	/** Notification Attribute object*/
+	const struct bt_gatt_attr *attr;
+	/** Notification Value data */
+	const void *data;
+	/** Notification Value length */
+	uint16_t len;
+	/** Notification Value callback */
+	bt_gatt_complete_func_t func;
+	/** Notification Value callback user data */
+	void *user_data;
+};
+
+/** @brief Notify attribute value change.
+ *
+ *  This function works in the same way as @ref bt_gatt_notify.
+ *  With the addition that after sending the notification the
+ *  callback function will be called.
+ *
+ *  The callback is run from System Workqueue context.
+ *
+ *  Alternatively it is possible to notify by UUID by setting it on the
+ *  parameters, when using this method the attribute given is used as the
+ *  start range when looking up for possible matches.
+ *
+ *  @param conn Connection object.
+ *  @param params Notification parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_notify_cb(struct bt_conn *conn,
+		      struct bt_gatt_notify_params *params);
+
+/** @brief Notify multiple attribute value change.
+ *
+ *  @param conn Connection object.
+ *  @param num_params Number of notification parameters.
+ *  @param params Array of notification parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_notify_multiple(struct bt_conn *conn, uint16_t num_params,
+			    struct bt_gatt_notify_params *params);
+
+/** @brief Notify attribute value change.
+ *
+ *  Send notification of attribute value change, if connection is NULL notify
+ *  all peer that have notification enabled via CCC otherwise do a direct
+ *  notification only the given connection.
+ *
+ *  The attribute object on the parameters can be the so called Characteristic
+ *  Declaration, which is usually declared with BT_GATT_CHARACTERISTIC followed
+ *  by BT_GATT_CCC, or the Characteristic Value Declaration which is
+ *  automatically created after the Characteristic Declaration when using
+ *  BT_GATT_CHARACTERISTIC.
+ *
+ *  @param conn Connection object.
+ *  @param attr Characteristic or Characteristic Value attribute.
+ *  @param data Pointer to Attribute data.
+ *  @param len Attribute value length.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+static inline int bt_gatt_notify(struct bt_conn *conn,
+				 const struct bt_gatt_attr *attr,
+				 const void *data, uint16_t len)
+{
+	struct bt_gatt_notify_params params;
+
+	memset(&params, 0, sizeof(params));
+
+	params.attr = attr;
+	params.data = data;
+	params.len = len;
+
+	return bt_gatt_notify_cb(conn, &params);
+}
+
+/** @brief Notify attribute value change by UUID.
+ *
+ *  Send notification of attribute value change, if connection is NULL notify
+ *  all peer that have notification enabled via CCC otherwise do a direct
+ *  notification only on the given connection.
+ *
+ *  The attribute object is the starting point for the search of the UUID.
+ *
+ *  @param conn Connection object.
+ *  @param uuid The UUID. If the server contains multiple services with the same
+ *              UUID, then the first occurrence, starting from the attr given,
+ *              is used.
+ *  @param attr Pointer to an attribute that serves as the starting point for
+ *              the search of a match for the UUID.
+ *  @param data Pointer to Attribute data.
+ *  @param len  Attribute value length.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+static inline int bt_gatt_notify_uuid(struct bt_conn *conn,
+				      const struct bt_uuid *uuid,
+				      const struct bt_gatt_attr *attr,
+				      const void *data, uint16_t len)
+{
+	struct bt_gatt_notify_params params;
+
+	memset(&params, 0, sizeof(params));
+
+	params.uuid = uuid;
+	params.attr = attr;
+	params.data = data;
+	params.len = len;
+
+	return bt_gatt_notify_cb(conn, &params);
+}
+
+/** @typedef bt_gatt_indicate_func_t
+ *  @brief Indication complete result callback.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute object.
+ *  @param err ATT error code
+ */
+typedef void (*bt_gatt_indicate_func_t)(struct bt_conn *conn,
+					const struct bt_gatt_attr *attr,
+					uint8_t err);
+
+/** @brief GATT Indicate Value parameters */
+struct bt_gatt_indicate_params {
+	/** Notification Attribute UUID type */
+	const struct bt_uuid *uuid;
+	/** Indicate Attribute object*/
+	const struct bt_gatt_attr *attr;
+	/** Indicate Value callback */
+	bt_gatt_indicate_func_t func;
+	/** Indicate Value data*/
+	const void *data;
+	/** Indicate Value length*/
+	uint16_t len;
+};
+
+/** @brief Indicate attribute value change.
+ *
+ *  Send an indication of attribute value change. if connection is NULL
+ *  indicate all peer that have notification enabled via CCC otherwise do a
+ *  direct indication only the given connection.
+ *
+ *  The attribute object on the parameters can be the so called Characteristic
+ *  Declaration, which is usually declared with BT_GATT_CHARACTERISTIC followed
+ *  by BT_GATT_CCC, or the Characteristic Value Declaration which is
+ *  automatically created after the Characteristic Declaration when using
+ *  BT_GATT_CHARACTERISTIC.
+ *
+ *  The callback is run from System Workqueue context.
+ *
+ *  Alternatively it is possible to indicate by UUID by setting it on the
+ *  parameters, when using this method the attribute given is used as the
+ *  start range when looking up for possible matches.
+ *
+ *  @note This procedure is asynchronous therefore the parameters need to
+ *        remains valid while it is active.
+ *
+ *  @param conn Connection object.
+ *  @param params Indicate parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_indicate(struct bt_conn *conn,
+		     struct bt_gatt_indicate_params *params);
+
+
+/** @brief Check if connection have subscribed to attribute
+ *
+ *  Check if connection has subscribed to attribute value change.
+ *
+ *  The attribute object can be the so called Characteristic Declaration,
+ *  which is usually declared with BT_GATT_CHARACTERISTIC followed
+ *  by BT_GATT_CCC, or the Characteristic Value Declaration which is
+ *  automatically created after the Characteristic Declaration when using
+ *  BT_GATT_CHARACTERISTIC, or the Client Characteristic Configuration
+ *  Descriptor (CCCD) which is created by BT_GATT_CCC.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute object.
+ *  @param ccc_value The subscription type, either notifications or indications.
+ *
+ *  @return true if the attribute object has been subscribed.
+ */
+bool bt_gatt_is_subscribed(struct bt_conn *conn,
+			   const struct bt_gatt_attr *attr, uint16_t ccc_value);
+
+/** @brief Get ATT MTU for a connection
+ *
+ *  Get negotiated ATT connection MTU, note that this does not equal the largest
+ *  amount of attribute data that can be transferred within a single packet.
+ *
+ *  @param conn Connection object.
+ *
+ *  @return MTU in bytes
+ */
+uint16_t bt_gatt_get_mtu(struct bt_conn *conn);
+
+/** @} */
+
+/**
+ * @defgroup bt_gatt_client GATT Client APIs
+ * @ingroup bt_gatt
+ * @{
+ */
+
+/** @brief GATT Exchange MTU parameters */
+struct bt_gatt_exchange_params {
+	/** Response callback */
+	void (*func)(struct bt_conn *conn, uint8_t err,
+		     struct bt_gatt_exchange_params *params);
+};
+
+/** @brief Exchange MTU
+ *
+ *  This client procedure can be used to set the MTU to the maximum possible
+ *  size the buffers can hold.
+ *
+ *  @note Shall only be used once per connection.
+ *
+ *  @param conn Connection object.
+ *  @param params Exchange MTU parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_exchange_mtu(struct bt_conn *conn,
+			 struct bt_gatt_exchange_params *params);
+
+struct bt_gatt_discover_params;
+
+/** @typedef bt_gatt_discover_func_t
+ *  @brief Discover attribute callback function.
+ *
+ *  @param conn Connection object.
+ *  @param attr Attribute found, or NULL if not found.
+ *  @param params Discovery parameters given.
+ *
+ *  If discovery procedure has completed this callback will be called with
+ *  attr set to NULL. This will not happen if procedure was stopped by returning
+ *  BT_GATT_ITER_STOP.
+ *
+ *  The attribute object as well as its UUID and value objects are temporary and
+ *  must be copied to in order to cache its information.
+ *  Only the following fields of the attribute contains valid information:
+ *   - uuid      UUID representing the type of attribute.
+ *   - handle    Handle in the remote database.
+ *   - user_data The value of the attribute.
+ *               Will be NULL when discovering descriptors
+ *
+ *  To be able to read the value of the discovered attribute the user_data
+ *  must be cast to an appropriate type.
+ *   - @ref bt_gatt_service_val when UUID is @ref BT_UUID_GATT_PRIMARY or
+ *     @ref BT_UUID_GATT_SECONDARY.
+ *   - @ref bt_gatt_include when UUID is @ref BT_UUID_GATT_INCLUDE.
+ *   - @ref bt_gatt_chrc when UUID is @ref BT_UUID_GATT_CHRC.
+ *
+ *  @return BT_GATT_ITER_CONTINUE to continue discovery procedure.
+ *  @return BT_GATT_ITER_STOP to stop discovery procedure.
+ */
+typedef uint8_t (*bt_gatt_discover_func_t)(struct bt_conn *conn,
+					const struct bt_gatt_attr *attr,
+					struct bt_gatt_discover_params *params);
+
+/** GATT Discover types */
+enum {
+	/** Discover Primary Services. */
+	BT_GATT_DISCOVER_PRIMARY,
+	/** Discover Secondary Services. */
+	BT_GATT_DISCOVER_SECONDARY,
+	/** Discover Included Services. */
+	BT_GATT_DISCOVER_INCLUDE,
+	/** @brief Discover Characteristic Values.
+	 *
+	 *  Discover Characteristic Value and its properties.
+	 */
+	BT_GATT_DISCOVER_CHARACTERISTIC,
+	/** @brief Discover Descriptors.
+	 *
+	 *  Discover Attributes which are not services or characteristics.
+	 *
+	 *  @note The use of this type of discover is not recommended for
+	 *        discovering in ranges across multiple services/characteristics
+	 *        as it may incur in extra round trips.
+	 */
+	BT_GATT_DISCOVER_DESCRIPTOR,
+	/** @brief Discover Attributes.
+	 *
+	 *  Discover Attributes of any type.
+	 *
+	 *  @note The use of this type of discover is not recommended for
+	 *        discovering in ranges across multiple services/characteristics
+	 *        as it may incur in more round trips.
+	 */
+	BT_GATT_DISCOVER_ATTRIBUTE,
+};
+
+/** @brief GATT Discover Attributes parameters */
+struct bt_gatt_discover_params {
+	/** Discover UUID type */
+	const struct bt_uuid *uuid;
+	/** Discover attribute callback */
+	bt_gatt_discover_func_t func;
+	union {
+		struct {
+			/** Include service attribute declaration handle */
+			uint16_t attr_handle;
+			/** Included service start handle */
+			uint16_t start_handle;
+			/** Included service end handle */
+			uint16_t end_handle;
+		} _included;
+		/** Discover start handle */
+		uint16_t start_handle;
+	};
+	/** Discover end handle */
+	uint16_t end_handle;
+	/** Discover type */
+	uint8_t type;
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+	/** Only for stack-internal use, used for automatic discovery. */
+	struct bt_gatt_subscribe_params *sub_params;
+#endif /* defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC) */
+};
+
+/** @brief GATT Discover function
+ *
+ *  This procedure is used by a client to discover attributes on a server.
+ *
+ *  Primary Service Discovery: Procedure allows to discover specific Primary
+ *                             Service based on UUID.
+ *  Include Service Discovery: Procedure allows to discover all Include Services
+ *                             within specified range.
+ *  Characteristic Discovery:  Procedure allows to discover all characteristics
+ *                             within specified handle range as well as
+ *                             discover characteristics with specified UUID.
+ *  Descriptors Discovery:     Procedure allows to discover all characteristic
+ *                             descriptors within specified range.
+ *
+ *  For each attribute found the callback is called which can then decide
+ *  whether to continue discovering or stop.
+ *
+ *  @note This procedure is asynchronous therefore the parameters need to
+ *        remains valid while it is active.
+ *
+ *  @param conn Connection object.
+ *  @param params Discover parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_discover(struct bt_conn *conn,
+		     struct bt_gatt_discover_params *params);
+
+struct bt_gatt_read_params;
+
+/** @typedef bt_gatt_read_func_t
+ *  @brief Read callback function
+ *
+ *  @param conn Connection object.
+ *  @param err ATT error code.
+ *  @param params Read parameters used.
+ *  @param data Attribute value data. NULL means read has completed.
+ *  @param length Attribute value length.
+ *
+ *  @return BT_GATT_ITER_CONTINUE if should continue to the next attribute.
+ *  @return BT_GATT_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_gatt_read_func_t)(struct bt_conn *conn, uint8_t err,
+				    struct bt_gatt_read_params *params,
+				    const void *data, uint16_t length);
+
+/** @brief GATT Read parameters */
+struct bt_gatt_read_params {
+	/** Read attribute callback. */
+	bt_gatt_read_func_t func;
+	/** If equals to 1 single.handle and single.offset are used.
+	 *  If >1 Read Multiple Characteristic Values is performed and handles
+	 *  are used.
+	 *  If equals to 0 by_uuid is used for Read Using Characteristic UUID.
+	 */
+	size_t handle_count;
+	union {
+		struct {
+			/** Attribute handle. */
+			uint16_t handle;
+			/** Attribute data offset. */
+			uint16_t offset;
+		} single;
+		/** Handles to read in Read Multiple Characteristic Values. */
+		uint16_t *handles;
+		struct {
+			/** First requested handle number. */
+			uint16_t start_handle;
+			/** Last requested handle number. */
+			uint16_t end_handle;
+			/** 2 or 16 octet UUID. */
+			const struct bt_uuid *uuid;
+		} by_uuid;
+	};
+};
+
+/** @brief Read Attribute Value by handle
+ *
+ *  This procedure read the attribute value and return it to the callback.
+ *
+ *  When reading attributes by UUID the callback can be called multiple times
+ *  depending on how many instances of given the UUID exists with the
+ *  start_handle being updated for each instance.
+ *
+ *  If an instance does contain a long value which cannot be read entirely the
+ *  caller will need to read the remaining data separately using the handle and
+ *  offset.
+ *
+ *  @note This procedure is asynchronous therefore the parameters need to
+ *        remains valid while it is active.
+ *
+ *  @param conn Connection object.
+ *  @param params Read parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params);
+
+struct bt_gatt_write_params;
+
+/** @typedef bt_gatt_write_func_t
+ *  @brief Write callback function
+ *
+ *  @param conn Connection object.
+ *  @param err ATT error code.
+ *  @param params Write parameters used.
+ */
+typedef void (*bt_gatt_write_func_t)(struct bt_conn *conn, uint8_t err,
+				     struct bt_gatt_write_params *params);
+
+/** @brief GATT Write parameters */
+struct bt_gatt_write_params {
+	/** Response callback */
+	bt_gatt_write_func_t func;
+	/** Attribute handle */
+	uint16_t handle;
+	/** Attribute data offset */
+	uint16_t offset;
+	/** Data to be written */
+	const void *data;
+	/** Length of the data */
+	uint16_t length;
+};
+
+/** @brief Write Attribute Value by handle
+ *
+ *  This procedure write the attribute value and return the result in the
+ *  callback.
+ *
+ *  @note This procedure is asynchronous therefore the parameters need to
+ *        remains valid while it is active.
+ *
+ *  @param conn Connection object.
+ *  @param params Write parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params);
+
+/** @brief Write Attribute Value by handle without response with callback.
+ *
+ *  This function works in the same way as @ref bt_gatt_write_without_response.
+ *  With the addition that after sending the write the callback function will be
+ *  called.
+ *
+ *  The callback is run from System Workqueue context.
+ *
+ *  @note By using a callback it also disable the internal flow control
+ *        which would prevent sending multiple commands without waiting for
+ *        their transmissions to complete, so if that is required the caller
+ *        shall not submit more data until the callback is called.
+ *
+ *  @param conn Connection object.
+ *  @param handle Attribute handle.
+ *  @param data Data to be written.
+ *  @param length Data length.
+ *  @param sign Whether to sign data
+ *  @param func Transmission complete callback.
+ *  @param user_data User data to be passed back to callback.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_write_without_response_cb(struct bt_conn *conn, uint16_t handle,
+				      const void *data, uint16_t length,
+				      bool sign, bt_gatt_complete_func_t func,
+				      void *user_data);
+
+/** @brief Write Attribute Value by handle without response
+ *
+ *  This procedure write the attribute value without requiring an
+ *  acknowledgment that the write was successfully performed
+ *
+ *  @param conn Connection object.
+ *  @param handle Attribute handle.
+ *  @param data Data to be written.
+ *  @param length Data length.
+ *  @param sign Whether to sign data
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+static inline int bt_gatt_write_without_response(struct bt_conn *conn,
+						 uint16_t handle, const void *data,
+						 uint16_t length, bool sign)
+{
+	return bt_gatt_write_without_response_cb(conn, handle, data, length,
+						 sign, NULL, NULL);
+}
+
+struct bt_gatt_subscribe_params;
+
+/** @typedef bt_gatt_notify_func_t
+ *  @brief Notification callback function
+ *
+ *  @param conn Connection object. May be NULL, indicating that the peer is
+ *              being unpaired
+ *  @param params Subscription parameters.
+ *  @param data Attribute value data. If NULL then subscription was removed.
+ *  @param length Attribute value length.
+ *
+ *  @return BT_GATT_ITER_CONTINUE to continue receiving value notifications.
+ *          BT_GATT_ITER_STOP to unsubscribe from value notifications.
+ */
+typedef uint8_t (*bt_gatt_notify_func_t)(struct bt_conn *conn,
+				      struct bt_gatt_subscribe_params *params,
+				      const void *data, uint16_t length);
+
+/** Subscription flags */
+enum {
+	/** @brief Persistence flag
+	 *
+	 *  If set, indicates that the subscription is not saved
+	 *  on the GATT server side. Therefore, upon disconnection,
+	 *  the subscription will be automatically removed
+	 *  from the client's subscriptions list and
+	 *  when the client reconnects, it will have to
+	 *  issue a new subscription.
+	 */
+	BT_GATT_SUBSCRIBE_FLAG_VOLATILE,
+
+	/** @brief No resubscribe flag
+	 *
+	 *  By default when BT_GATT_SUBSCRIBE_FLAG_VOLATILE is unset, the
+	 *  subscription will be automatically renewed when the client
+	 *  reconnects, as a workaround for GATT servers that do not persist
+	 *  subscriptions.
+	 *
+	 *  This flag will disable the automatic resubscription. It is useful
+	 *  if the application layer knows that the GATT server remembers
+	 *  subscriptions from previous connections and wants to avoid renewing
+	 *  the subscriptions.
+	 */
+	BT_GATT_SUBSCRIBE_FLAG_NO_RESUB,
+
+	/** @brief Write pending flag
+	 *
+	 *  If set, indicates write operation is pending waiting remote end to
+	 *  respond.
+	 */
+	BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING,
+
+	BT_GATT_SUBSCRIBE_NUM_FLAGS
+};
+
+/** @brief GATT Subscribe parameters */
+struct bt_gatt_subscribe_params {
+	/** Notification value callback */
+	bt_gatt_notify_func_t notify;
+	/** Subscribe CCC write request response callback */
+	bt_gatt_write_func_t write;
+	/** Subscribe value handle */
+	uint16_t value_handle;
+	/** Subscribe CCC handle */
+	uint16_t ccc_handle;
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+	/** Subscribe End handle (for automatic discovery) */
+	uint16_t end_handle;
+	/** Discover parameters used when ccc_handle = 0 */
+	struct bt_gatt_discover_params *disc_params;
+#endif /* CONFIG_BT_GATT_AUTO_DISCOVER_CCC */
+	/** Subscribe value */
+	uint16_t value;
+	/** Subscription flags */
+	ATOMIC_DEFINE(flags, BT_GATT_SUBSCRIBE_NUM_FLAGS);
+
+	sys_snode_t node;
+};
+
+/** @brief Subscribe Attribute Value Notification
+ *
+ *  This procedure subscribe to value notification using the Client
+ *  Characteristic Configuration handle.
+ *  If notification received subscribe value callback is called to return
+ *  notified value. One may then decide whether to unsubscribe directly from
+ *  this callback. Notification callback with NULL data will not be called if
+ *  subscription was removed by this method.
+ *
+ *  @note Notifications are asynchronous therefore the parameters need to
+ *        remain valid while subscribed.
+ *
+ *  @param conn Connection object.
+ *  @param params Subscribe parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_subscribe(struct bt_conn *conn,
+		      struct bt_gatt_subscribe_params *params);
+
+/** @brief Resubscribe Attribute Value Notification subscription
+ *
+ *  Resubscribe to Attribute Value Notification when already subscribed from a
+ *  previous connection. The GATT server will remember subscription from
+ *  previous connections when bonded, so resubscribing can be done without
+ *  performing a new subscribe procedure after a power cycle.
+ *
+ *  @note Notifications are asynchronous therefore the parameters need to
+ *        remain valid while subscribed.
+ *
+ *  @param id     Local identity (in most cases BT_ID_DEFAULT).
+ *  @param peer   Remote address.
+ *  @param params Subscribe parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_resubscribe(uint8_t id, const bt_addr_le_t *peer,
+			struct bt_gatt_subscribe_params *params);
+
+/** @brief Unsubscribe Attribute Value Notification
+ *
+ *  This procedure unsubscribe to value notification using the Client
+ *  Characteristic Configuration handle. Notification callback with NULL data
+ *  will be called if subscription was removed by this call, until then the
+ *  parameters cannot be reused.
+ *
+ *  @param conn Connection object.
+ *  @param params Subscribe parameters.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_gatt_unsubscribe(struct bt_conn *conn,
+			struct bt_gatt_subscribe_params *params);
+
+/** @brief Cancel GATT pending request
+ *
+ *  @param conn Connection object.
+ *  @param params Requested params address.
+ */
+void bt_gatt_cancel(struct bt_conn *conn, void *params);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_GATT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/hci.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci.h	(working copy)
@@ -0,0 +1,2281 @@
+/* hci.h - Bluetooth Host Control Interface definitions */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_
+
+#include <toolchain.h>
+#include <types.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/util.h>
+#include <net/buf.h>
+#include <bluetooth/addr.h>
+#include <bluetooth/hci_err.h>
+#include <bluetooth/conn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Special own address types for LL privacy (used in adv & scan parameters) */
+#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC  0x02
+#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM  0x03
+#define BT_HCI_OWN_ADDR_RPA_MASK       0x02
+
+#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe
+#define BT_HCI_PEER_ADDR_ANONYMOUS      0xff
+
+#define BT_ENC_KEY_SIZE_MIN                     0x07
+#define BT_ENC_KEY_SIZE_MAX                     0x10
+
+struct bt_hci_evt_hdr {
+	uint8_t  evt;
+	uint8_t  len;
+} __packed;
+#define BT_HCI_EVT_HDR_SIZE             2
+
+#define BT_ACL_START_NO_FLUSH           0x00
+#define BT_ACL_CONT                     0x01
+#define BT_ACL_START                    0x02
+#define BT_ACL_COMPLETE                 0x03
+
+#define BT_ACL_POINT_TO_POINT           0x00
+#define BT_ACL_BROADCAST                0x01
+
+#define bt_acl_handle(h)                ((h) & BIT_MASK(12))
+#define bt_acl_flags(h)                 ((h) >> 12)
+#define bt_acl_flags_pb(f)              ((f) & BIT_MASK(2))
+#define bt_acl_flags_bc(f)              ((f) >> 2)
+#define bt_acl_handle_pack(h, f)        ((h) | ((f) << 12))
+
+struct bt_hci_acl_hdr {
+	uint16_t handle;
+	uint16_t len;
+} __packed;
+#define BT_HCI_ACL_HDR_SIZE             4
+
+#define BT_ISO_START                    0x00
+#define BT_ISO_CONT                     0x01
+#define BT_ISO_SINGLE                   0x02
+#define BT_ISO_END                      0x03
+
+#define bt_iso_handle(h)                ((h) & 0x0fff)
+#define bt_iso_flags(h)                 ((h) >> 12)
+#define bt_iso_flags_pb(f)              ((f) & 0x0003)
+#define bt_iso_flags_ts(f)              (((f) >> 2) & 0x0001)
+#define bt_iso_pack_flags(pb, ts) \
+	(((pb) & 0x0003) | (((ts) & 0x0001) << 2))
+#define bt_iso_handle_pack(h, pb, ts) \
+	((h) | (bt_iso_pack_flags(pb, ts) << 12))
+
+#define BT_ISO_DATA_VALID                0x00
+#define BT_ISO_DATA_INVALID              0x01
+#define BT_ISO_DATA_NOP                  0x02
+
+#define bt_iso_pkt_len(h)                ((h) & 0x3fff)
+#define bt_iso_pkt_flags(h)              ((h) >> 14)
+#define bt_iso_pkt_len_pack(h, f)        ((h) | ((f) << 14))
+
+struct bt_hci_iso_data_hdr {
+	uint16_t sn;
+	uint16_t slen;
+} __packed;
+#define BT_HCI_ISO_DATA_HDR_SIZE	4
+
+struct bt_hci_iso_ts_data_hdr {
+	uint32_t ts;
+	struct bt_hci_iso_data_hdr data;
+} __packed;
+#define BT_HCI_ISO_TS_DATA_HDR_SIZE     8
+
+struct bt_hci_iso_hdr {
+	uint16_t handle;
+	uint16_t len;
+} __packed;
+#define BT_HCI_ISO_HDR_SIZE             4
+
+struct bt_hci_cmd_hdr {
+	uint16_t opcode;
+	uint8_t  param_len;
+} __packed;
+#define BT_HCI_CMD_HDR_SIZE             3
+
+/* Supported Commands */
+#define BT_CMD_TEST(cmd, octet, bit)            (cmd[octet] & BIT(bit))
+#define BT_CMD_LE_STATES(cmd)                   BT_CMD_TEST(cmd, 28, 3)
+
+#define BT_FEAT_TEST(feat, page, octet, bit)    (feat[page][octet] & BIT(bit))
+
+#define BT_FEAT_BREDR(feat)                     !BT_FEAT_TEST(feat, 0, 4, 5)
+#define BT_FEAT_LE(feat)                        BT_FEAT_TEST(feat, 0, 4, 6)
+#define BT_FEAT_EXT_FEATURES(feat)              BT_FEAT_TEST(feat, 0, 7, 7)
+#define BT_FEAT_HOST_SSP(feat)                  BT_FEAT_TEST(feat, 1, 0, 0)
+#define BT_FEAT_SC(feat)                        BT_FEAT_TEST(feat, 2, 1, 0)
+
+#define BT_FEAT_LMP_ESCO_CAPABLE(feat)          BT_FEAT_TEST(feat, 0, 3, 7)
+#define BT_FEAT_HV2_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 4)
+#define BT_FEAT_HV3_PKT(feat)                   BT_FEAT_TEST(feat, 0, 1, 5)
+#define BT_FEAT_EV4_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 0)
+#define BT_FEAT_EV5_PKT(feat)                   BT_FEAT_TEST(feat, 0, 4, 1)
+#define BT_FEAT_2EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 5)
+#define BT_FEAT_3EV3_PKT(feat)                  BT_FEAT_TEST(feat, 0, 5, 6)
+#define BT_FEAT_3SLOT_PKT(feat)                 BT_FEAT_TEST(feat, 0, 5, 7)
+
+/* LE features */
+#define BT_LE_FEAT_BIT_ENC                      0
+#define BT_LE_FEAT_BIT_CONN_PARAM_REQ           1
+#define BT_LE_FEAT_BIT_EXT_REJ_IND              2
+#define BT_LE_FEAT_BIT_SLAVE_FEAT_REQ           3
+#define BT_LE_FEAT_BIT_PING                     4
+#define BT_LE_FEAT_BIT_DLE                      5
+#define BT_LE_FEAT_BIT_PRIVACY                  6
+#define BT_LE_FEAT_BIT_EXT_SCAN                 7
+#define BT_LE_FEAT_BIT_PHY_2M                   8
+#define BT_LE_FEAT_BIT_SMI_TX                   9
+#define BT_LE_FEAT_BIT_SMI_RX                   10
+#define BT_LE_FEAT_BIT_PHY_CODED                11
+#define BT_LE_FEAT_BIT_EXT_ADV                  12
+#define BT_LE_FEAT_BIT_PER_ADV                  13
+#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2          14
+#define BT_LE_FEAT_BIT_PWR_CLASS_1              15
+#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC       16
+#define BT_LE_FEAT_BIT_CONN_CTE_REQ             17
+#define BT_LE_FEAT_BIT_CONN_CTE_RESP            18
+#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX    19
+#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX    20
+#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD        21
+#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA        22
+#define BT_LE_FEAT_BIT_RX_CTE                   23
+#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_SEND  24
+#define BT_LE_FEAT_BIT_PERIODIC_SYNC_XFER_RECV  25
+#define BT_LE_FEAT_BIT_SCA_UPDATE               26
+#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE  27
+#define BT_LE_FEAT_BIT_CIS_MASTER               28
+#define BT_LE_FEAT_BIT_CIS_SLAVE                29
+#define BT_LE_FEAT_BIT_ISO_BROADCASTER          30
+#define BT_LE_FEAT_BIT_SYNC_RECEIVER            31
+#define BT_LE_FEAT_BIT_ISO_CHANNELS             32
+#define BT_LE_FEAT_BIT_PWR_CTRL_REQ             33
+#define BT_LE_FEAT_BIT_PWR_CHG_IND              34
+#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR        35
+
+#define BT_LE_FEAT_TEST(feat, n)                (feat[(n) >> 3] & \
+						 BIT((n) & 7))
+
+#define BT_FEAT_LE_ENCR(feat)                   BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ENC)
+#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat)    BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CONN_PARAM_REQ)
+#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat)     BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_SLAVE_FEAT_REQ)
+#define BT_FEAT_LE_DLE(feat)                    BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_DLE)
+#define BT_FEAT_LE_PHY_2M(feat)                 BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PHY_2M)
+#define BT_FEAT_LE_PHY_CODED(feat)              BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PHY_CODED)
+#define BT_FEAT_LE_PRIVACY(feat)                BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PRIVACY)
+#define BT_FEAT_LE_EXT_ADV(feat)                BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_EXT_ADV)
+#define BT_FEAT_LE_EXT_PER_ADV(feat)            BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_PER_ADV)
+#define BT_FEAT_LE_CIS_MASTER(feat)             BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CIS_MASTER)
+#define BT_FEAT_LE_CIS_SLAVE(feat)              BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_CIS_SLAVE)
+#define BT_FEAT_LE_ISO_BROADCASTER(feat)        BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ISO_BROADCASTER)
+#define BT_FEAT_LE_SYNC_RECEIVER(feat)          BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_SYNC_RECEIVER)
+#define BT_FEAT_LE_ISO_CHANNELS(feat)           BT_LE_FEAT_TEST(feat, \
+						BT_LE_FEAT_BIT_ISO_CHANNELS)
+
+#define BT_FEAT_LE_CIS(feat)            (BT_FEAT_LE_CIS_MASTER(feat) | \
+					BT_FEAT_LE_CIS_SLAVE(feat))
+#define BT_FEAT_LE_BIS(feat)            (BT_FEAT_LE_ISO_BROADCASTER(feat) | \
+					BT_FEAT_LE_SYNC_RECEIVER(feat))
+#define BT_FEAT_LE_ISO(feat)            (BT_FEAT_LE_CIS(feat) | \
+					BT_FEAT_LE_BIS(feat))
+
+/* LE States */
+#define BT_LE_STATES_SLAVE_CONN_ADV(states)     (states & 0x0000004000000000)
+
+/* Bonding/authentication types */
+#define BT_HCI_NO_BONDING                       0x00
+#define BT_HCI_NO_BONDING_MITM                  0x01
+#define BT_HCI_DEDICATED_BONDING                0x02
+#define BT_HCI_DEDICATED_BONDING_MITM           0x03
+#define BT_HCI_GENERAL_BONDING                  0x04
+#define BT_HCI_GENERAL_BONDING_MITM             0x05
+
+/*
+ * MITM protection is enabled in SSP authentication requirements octet when
+ * LSB bit is set.
+ */
+#define BT_MITM                                 0x01
+
+/* I/O capabilities */
+#define BT_IO_DISPLAY_ONLY                      0x00
+#define BT_IO_DISPLAY_YESNO                     0x01
+#define BT_IO_KEYBOARD_ONLY                     0x02
+#define BT_IO_NO_INPUT_OUTPUT                   0x03
+
+/* SCO packet types */
+#define HCI_PKT_TYPE_HV1                        0x0020
+#define HCI_PKT_TYPE_HV2                        0x0040
+#define HCI_PKT_TYPE_HV3                        0x0080
+
+/* eSCO packet types */
+#define HCI_PKT_TYPE_ESCO_HV1                   0x0001
+#define HCI_PKT_TYPE_ESCO_HV2                   0x0002
+#define HCI_PKT_TYPE_ESCO_HV3                   0x0004
+#define HCI_PKT_TYPE_ESCO_EV3                   0x0008
+#define HCI_PKT_TYPE_ESCO_EV4                   0x0010
+#define HCI_PKT_TYPE_ESCO_EV5                   0x0020
+#define HCI_PKT_TYPE_ESCO_2EV3                  0x0040
+#define HCI_PKT_TYPE_ESCO_3EV3                  0x0080
+#define HCI_PKT_TYPE_ESCO_2EV5                  0x0100
+#define HCI_PKT_TYPE_ESCO_3EV5                  0x0200
+
+
+#define ESCO_PKT_MASK                           (HCI_PKT_TYPE_ESCO_HV1 | \
+						 HCI_PKT_TYPE_ESCO_HV2 | \
+						 HCI_PKT_TYPE_ESCO_HV3)
+#define SCO_PKT_MASK                            (HCI_PKT_TYPE_HV1 | \
+						 HCI_PKT_TYPE_HV2 | \
+						 HCI_PKT_TYPE_HV3)
+#define EDR_ESCO_PKT_MASK                       (HCI_PKT_TYPE_ESCO_2EV3 | \
+						 HCI_PKT_TYPE_ESCO_3EV3 | \
+						 HCI_PKT_TYPE_ESCO_2EV5 | \
+						 HCI_PKT_TYPE_ESCO_3EV5)
+
+/* HCI BR/EDR link types */
+#define BT_HCI_SCO                              0x00
+#define BT_HCI_ACL                              0x01
+#define BT_HCI_ESCO                             0x02
+
+/* OpCode Group Fields */
+#define BT_OGF_LINK_CTRL                        0x01
+#define BT_OGF_BASEBAND                         0x03
+#define BT_OGF_INFO                             0x04
+#define BT_OGF_STATUS                           0x05
+#define BT_OGF_LE                               0x08
+#define BT_OGF_VS                               0x3f
+
+/* Construct OpCode from OGF and OCF */
+#define BT_OP(ogf, ocf)                         ((ocf) | ((ogf) << 10))
+
+/* Invalid opcode */
+#define BT_OP_NOP				0x0000
+
+/* Obtain OGF from OpCode */
+#define BT_OGF(opcode)                          (((opcode) >> 10) & BIT_MASK(6))
+/* Obtain OCF from OpCode */
+#define BT_OCF(opcode)                          ((opcode) & BIT_MASK(10))
+
+#define BT_HCI_OP_INQUIRY                       BT_OP(BT_OGF_LINK_CTRL, 0x0001)
+struct bt_hci_op_inquiry {
+	uint8_t lap[3];
+	uint8_t length;
+	uint8_t num_rsp;
+} __packed;
+
+#define BT_HCI_OP_INQUIRY_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0002)
+
+#define BT_HCI_OP_CONNECT                       BT_OP(BT_OGF_LINK_CTRL, 0x0005)
+struct bt_hci_cp_connect {
+	bt_addr_t bdaddr;
+	uint16_t  packet_type;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint16_t  clock_offset;
+	uint8_t   allow_role_switch;
+} __packed;
+
+#define BT_HCI_OP_DISCONNECT                    BT_OP(BT_OGF_LINK_CTRL, 0x0006)
+struct bt_hci_cp_disconnect {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_OP_CONNECT_CANCEL                BT_OP(BT_OGF_LINK_CTRL, 0x0008)
+struct bt_hci_cp_connect_cancel {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_connect_cancel {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_ACCEPT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x0009)
+struct bt_hci_cp_accept_conn_req {
+	bt_addr_t bdaddr;
+	uint8_t   role;
+} __packed;
+
+#define BT_HCI_OP_SETUP_SYNC_CONN               BT_OP(BT_OGF_LINK_CTRL, 0x0028)
+struct bt_hci_cp_setup_sync_conn {
+	uint16_t  handle;
+	uint32_t  tx_bandwidth;
+	uint32_t  rx_bandwidth;
+	uint16_t  max_latency;
+	uint16_t  content_format;
+	uint8_t   retrans_effort;
+	uint16_t  pkt_type;
+} __packed;
+
+#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ          BT_OP(BT_OGF_LINK_CTRL, 0x0029)
+struct bt_hci_cp_accept_sync_conn_req {
+	bt_addr_t bdaddr;
+	uint32_t  tx_bandwidth;
+	uint32_t  rx_bandwidth;
+	uint16_t  max_latency;
+	uint16_t  content_format;
+	uint8_t   retrans_effort;
+	uint16_t  pkt_type;
+} __packed;
+
+#define BT_HCI_OP_REJECT_CONN_REQ               BT_OP(BT_OGF_LINK_CTRL, 0x000a)
+struct bt_hci_cp_reject_conn_req {
+	bt_addr_t bdaddr;
+	uint8_t   reason;
+} __packed;
+
+#define BT_HCI_OP_LINK_KEY_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000b)
+struct bt_hci_cp_link_key_reply {
+	bt_addr_t bdaddr;
+	uint8_t   link_key[16];
+} __packed;
+
+#define BT_HCI_OP_LINK_KEY_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000c)
+struct bt_hci_cp_link_key_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_PIN_CODE_REPLY                BT_OP(BT_OGF_LINK_CTRL, 0x000d)
+struct bt_hci_cp_pin_code_reply {
+	bt_addr_t bdaddr;
+	uint8_t   pin_len;
+	uint8_t   pin_code[16];
+} __packed;
+struct bt_hci_rp_pin_code_reply {
+	uint8_t      status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_PIN_CODE_NEG_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x000e)
+struct bt_hci_cp_pin_code_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_pin_code_neg_reply {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_AUTH_REQUESTED                BT_OP(BT_OGF_LINK_CTRL, 0x0011)
+struct bt_hci_cp_auth_requested {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_SET_CONN_ENCRYPT              BT_OP(BT_OGF_LINK_CTRL, 0x0013)
+struct bt_hci_cp_set_conn_encrypt {
+	uint16_t handle;
+	uint8_t  encrypt;
+} __packed;
+
+#define BT_HCI_OP_REMOTE_NAME_REQUEST           BT_OP(BT_OGF_LINK_CTRL, 0x0019)
+struct bt_hci_cp_remote_name_request {
+	bt_addr_t bdaddr;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint16_t  clock_offset;
+} __packed;
+
+#define BT_HCI_OP_REMOTE_NAME_CANCEL            BT_OP(BT_OGF_LINK_CTRL, 0x001a)
+struct bt_hci_cp_remote_name_cancel {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_remote_name_cancel {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_FEATURES          BT_OP(BT_OGF_LINK_CTRL, 0x001b)
+struct bt_hci_cp_read_remote_features {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES      BT_OP(BT_OGF_LINK_CTRL, 0x001c)
+struct bt_hci_cp_read_remote_ext_features {
+	uint16_t handle;
+	uint8_t  page;
+} __packed;
+
+#define BT_HCI_OP_READ_REMOTE_VERSION_INFO      BT_OP(BT_OGF_LINK_CTRL, 0x001d)
+struct bt_hci_cp_read_remote_version_info {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_IO_CAPABILITY_REPLY           BT_OP(BT_OGF_LINK_CTRL, 0x002b)
+struct bt_hci_cp_io_capability_reply {
+	bt_addr_t bdaddr;
+	uint8_t   capability;
+	uint8_t   oob_data;
+	uint8_t   authentication;
+} __packed;
+
+#define BT_HCI_OP_USER_CONFIRM_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002c)
+#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002d)
+struct bt_hci_cp_user_confirm_reply {
+	bt_addr_t bdaddr;
+} __packed;
+struct bt_hci_rp_user_confirm_reply {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_USER_PASSKEY_REPLY            BT_OP(BT_OGF_LINK_CTRL, 0x002e)
+struct bt_hci_cp_user_passkey_reply {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY        BT_OP(BT_OGF_LINK_CTRL, 0x002f)
+struct bt_hci_cp_user_passkey_neg_reply {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY       BT_OP(BT_OGF_LINK_CTRL, 0x0034)
+struct bt_hci_cp_io_capability_neg_reply {
+	bt_addr_t bdaddr;
+	uint8_t   reason;
+} __packed;
+
+#define BT_HCI_OP_SET_EVENT_MASK                BT_OP(BT_OGF_BASEBAND, 0x0001)
+struct bt_hci_cp_set_event_mask {
+	uint8_t  events[8];
+} __packed;
+
+#define BT_HCI_OP_RESET                         BT_OP(BT_OGF_BASEBAND, 0x0003)
+
+#define BT_HCI_OP_WRITE_LOCAL_NAME              BT_OP(BT_OGF_BASEBAND, 0x0013)
+struct bt_hci_write_local_name {
+	uint8_t local_name[248];
+} __packed;
+
+#define BT_HCI_OP_WRITE_PAGE_TIMEOUT            BT_OP(BT_OGF_BASEBAND, 0x0018)
+
+#define BT_HCI_OP_WRITE_SCAN_ENABLE             BT_OP(BT_OGF_BASEBAND, 0x001a)
+#define BT_BREDR_SCAN_DISABLED                  0x00
+#define BT_BREDR_SCAN_INQUIRY                   0x01
+#define BT_BREDR_SCAN_PAGE                      0x02
+
+#define BT_TX_POWER_LEVEL_CURRENT               0x00
+#define BT_TX_POWER_LEVEL_MAX                   0x01
+#define BT_HCI_OP_READ_TX_POWER_LEVEL           BT_OP(BT_OGF_BASEBAND, 0x002d)
+struct bt_hci_cp_read_tx_power_level {
+	uint16_t handle;
+	uint8_t  type;
+} __packed;
+
+struct bt_hci_rp_read_tx_power_level {
+	uint8_t  status;
+	uint16_t handle;
+	int8_t   tx_power_level;
+} __packed;
+
+#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE         0x00
+#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE          0x01
+#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW          BT_OP(BT_OGF_BASEBAND, 0x0031)
+struct bt_hci_cp_set_ctl_to_host_flow {
+	uint8_t  flow_enable;
+} __packed;
+
+#define BT_HCI_OP_HOST_BUFFER_SIZE              BT_OP(BT_OGF_BASEBAND, 0x0033)
+struct bt_hci_cp_host_buffer_size {
+	uint16_t acl_mtu;
+	uint8_t  sco_mtu;
+	uint16_t acl_pkts;
+	uint16_t sco_pkts;
+} __packed;
+
+struct bt_hci_handle_count {
+	uint16_t handle;
+	uint16_t count;
+} __packed;
+
+#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS    BT_OP(BT_OGF_BASEBAND, 0x0035)
+struct bt_hci_cp_host_num_completed_packets {
+	uint8_t  num_handles;
+	struct bt_hci_handle_count h[0];
+} __packed;
+
+#define BT_HCI_OP_WRITE_INQUIRY_MODE            BT_OP(BT_OGF_BASEBAND, 0x0045)
+struct bt_hci_cp_write_inquiry_mode {
+	uint8_t  mode;
+} __packed;
+
+#define BT_HCI_OP_WRITE_SSP_MODE                BT_OP(BT_OGF_BASEBAND, 0x0056)
+struct bt_hci_cp_write_ssp_mode {
+	uint8_t mode;
+} __packed;
+
+#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2         BT_OP(BT_OGF_BASEBAND, 0x0063)
+struct bt_hci_cp_set_event_mask_page_2 {
+	uint8_t  events_page_2[8];
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP         BT_OP(BT_OGF_BASEBAND, 0x006d)
+struct bt_hci_cp_write_le_host_supp {
+	uint8_t  le;
+	uint8_t  simul;
+} __packed;
+
+#define BT_HCI_OP_WRITE_SC_HOST_SUPP            BT_OP(BT_OGF_BASEBAND, 0x007a)
+struct bt_hci_cp_write_sc_host_supp {
+	uint8_t  sc_support;
+} __packed;
+
+#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT     BT_OP(BT_OGF_BASEBAND, 0x007b)
+struct bt_hci_cp_read_auth_payload_timeout {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_read_auth_payload_timeout {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t auth_payload_timeout;
+} __packed;
+
+#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT    BT_OP(BT_OGF_BASEBAND, 0x007c)
+struct bt_hci_cp_write_auth_payload_timeout {
+	uint16_t handle;
+	uint16_t auth_payload_timeout;
+} __packed;
+
+struct bt_hci_rp_write_auth_payload_timeout {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+/* HCI version from Assigned Numbers */
+#define BT_HCI_VERSION_1_0B                     0
+#define BT_HCI_VERSION_1_1                      1
+#define BT_HCI_VERSION_1_2                      2
+#define BT_HCI_VERSION_2_0                      3
+#define BT_HCI_VERSION_2_1                      4
+#define BT_HCI_VERSION_3_0                      5
+#define BT_HCI_VERSION_4_0                      6
+#define BT_HCI_VERSION_4_1                      7
+#define BT_HCI_VERSION_4_2                      8
+#define BT_HCI_VERSION_5_0                      9
+#define BT_HCI_VERSION_5_1                      10
+#define BT_HCI_VERSION_5_2                      11
+
+#define BT_HCI_OP_READ_LOCAL_VERSION_INFO       BT_OP(BT_OGF_INFO, 0x0001)
+struct bt_hci_rp_read_local_version_info {
+	uint8_t  status;
+	uint8_t  hci_version;
+	uint16_t hci_revision;
+	uint8_t  lmp_version;
+	uint16_t manufacturer;
+	uint16_t lmp_subversion;
+} __packed;
+
+#define BT_HCI_OP_READ_SUPPORTED_COMMANDS       BT_OP(BT_OGF_INFO, 0x0002)
+struct bt_hci_rp_read_supported_commands {
+	uint8_t  status;
+	uint8_t  commands[64];
+} __packed;
+
+#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES       BT_OP(BT_OGF_INFO, 0x0004)
+struct bt_hci_cp_read_local_ext_features {
+	uint8_t page;
+};
+struct bt_hci_rp_read_local_ext_features {
+	uint8_t  status;
+	uint8_t  page;
+	uint8_t  max_page;
+	uint8_t  ext_features[8];
+} __packed;
+
+#define BT_HCI_OP_READ_LOCAL_FEATURES           BT_OP(BT_OGF_INFO, 0x0003)
+struct bt_hci_rp_read_local_features {
+	uint8_t  status;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_OP_READ_BUFFER_SIZE              BT_OP(BT_OGF_INFO, 0x0005)
+struct bt_hci_rp_read_buffer_size {
+	uint8_t  status;
+	uint16_t acl_max_len;
+	uint8_t  sco_max_len;
+	uint16_t acl_max_num;
+	uint16_t sco_max_num;
+} __packed;
+
+#define BT_HCI_OP_READ_BD_ADDR                  BT_OP(BT_OGF_INFO, 0x0009)
+struct bt_hci_rp_read_bd_addr {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_OP_READ_RSSI                     BT_OP(BT_OGF_STATUS, 0x0005)
+struct bt_hci_cp_read_rssi {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_read_rssi {
+	uint8_t  status;
+	uint16_t handle;
+	int8_t   rssi;
+} __packed;
+
+#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN          7
+#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX          16
+
+#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE      BT_OP(BT_OGF_STATUS, 0x0008)
+struct bt_hci_cp_read_encryption_key_size {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_read_encryption_key_size {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  key_size;
+} __packed;
+
+/* BLE */
+
+#define BT_HCI_OP_LE_SET_EVENT_MASK             BT_OP(BT_OGF_LE, 0x0001)
+struct bt_hci_cp_le_set_event_mask {
+	uint8_t events[8];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_BUFFER_SIZE           BT_OP(BT_OGF_LE, 0x0002)
+struct bt_hci_rp_le_read_buffer_size {
+	uint8_t  status;
+	uint16_t le_max_len;
+	uint8_t  le_max_num;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_LOCAL_FEATURES        BT_OP(BT_OGF_LE, 0x0003)
+struct bt_hci_rp_le_read_local_features {
+	uint8_t  status;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS         BT_OP(BT_OGF_LE, 0x0005)
+struct bt_hci_cp_le_set_random_address {
+	bt_addr_t bdaddr;
+} __packed;
+
+/* LE Advertising Types (LE Advertising Parameters Set)*/
+#define BT_LE_ADV_IND                  (__DEPRECATED_MACRO 0x00)
+#define BT_LE_ADV_DIRECT_IND           (__DEPRECATED_MACRO 0x01)
+#define BT_LE_ADV_SCAN_IND             (__DEPRECATED_MACRO 0x02)
+#define BT_LE_ADV_NONCONN_IND          (__DEPRECATED_MACRO 0x03)
+#define BT_LE_ADV_DIRECT_IND_LOW_DUTY  (__DEPRECATED_MACRO 0x04)
+/* LE Advertising PDU Types. */
+#define BT_LE_ADV_SCAN_RSP             (__DEPRECATED_MACRO 0x04)
+
+#define BT_HCI_ADV_IND                          0x00
+#define BT_HCI_ADV_DIRECT_IND                   0x01
+#define BT_HCI_ADV_SCAN_IND                     0x02
+#define BT_HCI_ADV_NONCONN_IND                  0x03
+#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY          0x04
+#define BT_HCI_ADV_SCAN_RSP                     0x04
+
+#define BT_LE_ADV_FP_NO_WHITELIST               0x00
+#define BT_LE_ADV_FP_WHITELIST_SCAN_REQ         0x01
+#define BT_LE_ADV_FP_WHITELIST_CONN_IND         0x02
+#define BT_LE_ADV_FP_WHITELIST_BOTH             0x03
+
+#define BT_HCI_OP_LE_SET_ADV_PARAM              BT_OP(BT_OGF_LE, 0x0006)
+struct bt_hci_cp_le_set_adv_param {
+	uint16_t     min_interval;
+	uint16_t     max_interval;
+	uint8_t      type;
+	uint8_t      own_addr_type;
+	bt_addr_le_t direct_addr;
+	uint8_t      channel_map;
+	uint8_t      filter_policy;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER     BT_OP(BT_OGF_LE, 0x0007)
+struct bt_hci_rp_le_read_chan_tx_power {
+	uint8_t status;
+	int8_t  tx_power_level;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_ADV_DATA               BT_OP(BT_OGF_LE, 0x0008)
+struct bt_hci_cp_le_set_adv_data {
+	uint8_t  len;
+	uint8_t  data[31];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA          BT_OP(BT_OGF_LE, 0x0009)
+struct bt_hci_cp_le_set_scan_rsp_data {
+	uint8_t  len;
+	uint8_t  data[31];
+} __packed;
+
+#define BT_HCI_LE_ADV_DISABLE                   0x00
+#define BT_HCI_LE_ADV_ENABLE                    0x01
+
+#define BT_HCI_OP_LE_SET_ADV_ENABLE             BT_OP(BT_OGF_LE, 0x000a)
+struct bt_hci_cp_le_set_adv_enable {
+	uint8_t  enable;
+} __packed;
+
+/* Scan types */
+#define BT_HCI_OP_LE_SET_SCAN_PARAM             BT_OP(BT_OGF_LE, 0x000b)
+#define BT_HCI_LE_SCAN_PASSIVE                  0x00
+#define BT_HCI_LE_SCAN_ACTIVE                   0x01
+
+#define BT_HCI_LE_SCAN_FP_NO_WHITELIST          0x00
+#define BT_HCI_LE_SCAN_FP_USE_WHITELIST         0x01
+
+struct bt_hci_cp_le_set_scan_param {
+	uint8_t  scan_type;
+	uint16_t interval;
+	uint16_t window;
+	uint8_t  addr_type;
+	uint8_t  filter_policy;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_SCAN_ENABLE            BT_OP(BT_OGF_LE, 0x000c)
+
+#define BT_HCI_LE_SCAN_DISABLE                  0x00
+#define BT_HCI_LE_SCAN_ENABLE                   0x01
+
+#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE       0x00
+#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE        0x01
+
+struct bt_hci_cp_le_set_scan_enable {
+	uint8_t  enable;
+	uint8_t  filter_dup;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_CONN                BT_OP(BT_OGF_LE, 0x000d)
+
+#define BT_HCI_LE_CREATE_CONN_FP_DIRECT         0x00
+#define BT_HCI_LE_CREATE_CONN_FP_WHITELIST      0x01
+
+struct bt_hci_cp_le_create_conn {
+	uint16_t     scan_interval;
+	uint16_t     scan_window;
+	uint8_t      filter_policy;
+	bt_addr_le_t peer_addr;
+	uint8_t      own_addr_type;
+	uint16_t     conn_interval_min;
+	uint16_t     conn_interval_max;
+	uint16_t     conn_latency;
+	uint16_t     supervision_timeout;
+	uint16_t     min_ce_len;
+	uint16_t     max_ce_len;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_CONN_CANCEL         BT_OP(BT_OGF_LE, 0x000e)
+
+#define BT_HCI_OP_LE_READ_WL_SIZE               BT_OP(BT_OGF_LE, 0x000f)
+struct bt_hci_rp_le_read_wl_size {
+	uint8_t  status;
+	uint8_t  wl_size;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_WL                   BT_OP(BT_OGF_LE, 0x0010)
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_WL              BT_OP(BT_OGF_LE, 0x0011)
+struct bt_hci_cp_le_add_dev_to_wl {
+	bt_addr_le_t  addr;
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_WL            BT_OP(BT_OGF_LE, 0x0012)
+struct bt_hci_cp_le_rem_dev_from_wl {
+	bt_addr_le_t  addr;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_UPDATE                BT_OP(BT_OGF_LE, 0x0013)
+struct hci_cp_le_conn_update {
+	uint16_t handle;
+	uint16_t conn_interval_min;
+	uint16_t conn_interval_max;
+	uint16_t conn_latency;
+	uint16_t supervision_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF      BT_OP(BT_OGF_LE, 0x0014)
+struct bt_hci_cp_le_set_host_chan_classif {
+	uint8_t  ch_map[5];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_CHAN_MAP              BT_OP(BT_OGF_LE, 0x0015)
+struct bt_hci_cp_le_read_chan_map {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_read_chan_map {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  ch_map[5];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_REMOTE_FEATURES       BT_OP(BT_OGF_LE, 0x0016)
+struct bt_hci_cp_le_read_remote_features {
+	uint16_t  handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ENCRYPT                    BT_OP(BT_OGF_LE, 0x0017)
+struct bt_hci_cp_le_encrypt {
+	uint8_t  key[16];
+	uint8_t  plaintext[16];
+} __packed;
+struct bt_hci_rp_le_encrypt {
+	uint8_t  status;
+	uint8_t  enc_data[16];
+} __packed;
+
+#define BT_HCI_OP_LE_RAND                       BT_OP(BT_OGF_LE, 0x0018)
+struct bt_hci_rp_le_rand {
+	uint8_t  status;
+	uint8_t  rand[8];
+} __packed;
+
+#define BT_HCI_OP_LE_START_ENCRYPTION           BT_OP(BT_OGF_LE, 0x0019)
+struct bt_hci_cp_le_start_encryption {
+	uint16_t handle;
+	uint64_t rand;
+	uint16_t ediv;
+	uint8_t  ltk[16];
+} __packed;
+
+#define BT_HCI_OP_LE_LTK_REQ_REPLY              BT_OP(BT_OGF_LE, 0x001a)
+struct bt_hci_cp_le_ltk_req_reply {
+	uint16_t handle;
+	uint8_t  ltk[16];
+} __packed;
+struct bt_hci_rp_le_ltk_req_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY          BT_OP(BT_OGF_LE, 0x001b)
+struct bt_hci_cp_le_ltk_req_neg_reply {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_ltk_req_neg_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_SUPP_STATES           BT_OP(BT_OGF_LE, 0x001c)
+struct bt_hci_rp_le_read_supp_states {
+	uint8_t  status;
+	uint8_t  le_states[8];
+} __packed;
+
+#define BT_HCI_OP_LE_RX_TEST                    BT_OP(BT_OGF_LE, 0x001d)
+struct bt_hci_cp_le_rx_test {
+	uint8_t  rx_ch;
+} __packed;
+
+#define BT_HCI_OP_LE_TX_TEST                    BT_OP(BT_OGF_LE, 0x001e)
+struct bt_hci_cp_le_tx_test {
+	uint8_t  tx_ch;
+	uint8_t  test_data_len;
+	uint8_t  pkt_payload;
+} __packed;
+
+#define BT_HCI_OP_LE_TEST_END                   BT_OP(BT_OGF_LE, 0x001f)
+struct bt_hci_rp_le_test_end {
+	uint8_t  status;
+	uint16_t rx_pkt_count;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY       BT_OP(BT_OGF_LE, 0x0020)
+struct bt_hci_cp_le_conn_param_req_reply {
+	uint16_t handle;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+struct bt_hci_rp_le_conn_param_req_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY   BT_OP(BT_OGF_LE, 0x0021)
+struct bt_hci_cp_le_conn_param_req_neg_reply {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+struct bt_hci_rp_le_conn_param_req_neg_reply {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_DATA_LEN               BT_OP(BT_OGF_LE, 0x0022)
+struct bt_hci_cp_le_set_data_len {
+	uint16_t handle;
+	uint16_t tx_octets;
+	uint16_t tx_time;
+} __packed;
+struct bt_hci_rp_le_set_data_len {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN      BT_OP(BT_OGF_LE, 0x0023)
+struct bt_hci_rp_le_read_default_data_len {
+	uint8_t  status;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN     BT_OP(BT_OGF_LE, 0x0024)
+struct bt_hci_cp_le_write_default_data_len {
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+#define BT_HCI_OP_LE_P256_PUBLIC_KEY            BT_OP(BT_OGF_LE, 0x0025)
+
+#define BT_HCI_OP_LE_GENERATE_DHKEY             BT_OP(BT_OGF_LE, 0x0026)
+struct bt_hci_cp_le_generate_dhkey {
+	uint8_t key[64];
+} __packed;
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_RL              BT_OP(BT_OGF_LE, 0x0027)
+struct bt_hci_cp_le_add_dev_to_rl {
+	bt_addr_le_t  peer_id_addr;
+	uint8_t       peer_irk[16];
+	uint8_t       local_irk[16];
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_RL            BT_OP(BT_OGF_LE, 0x0028)
+struct bt_hci_cp_le_rem_dev_from_rl {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_RL                   BT_OP(BT_OGF_LE, 0x0029)
+
+#define BT_HCI_OP_LE_READ_RL_SIZE               BT_OP(BT_OGF_LE, 0x002a)
+struct bt_hci_rp_le_read_rl_size {
+	uint8_t  status;
+	uint8_t  rl_size;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_PEER_RPA              BT_OP(BT_OGF_LE, 0x002b)
+struct bt_hci_cp_le_read_peer_rpa {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+struct bt_hci_rp_le_read_peer_rpa {
+	uint8_t    status;
+	bt_addr_t  peer_rpa;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_LOCAL_RPA             BT_OP(BT_OGF_LE, 0x002c)
+struct bt_hci_cp_le_read_local_rpa {
+	bt_addr_le_t  peer_id_addr;
+} __packed;
+struct bt_hci_rp_le_read_local_rpa {
+	uint8_t    status;
+	bt_addr_t  local_rpa;
+} __packed;
+
+#define BT_HCI_ADDR_RES_DISABLE                 0x00
+#define BT_HCI_ADDR_RES_ENABLE                  0x01
+
+#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE        BT_OP(BT_OGF_LE, 0x002d)
+struct bt_hci_cp_le_set_addr_res_enable {
+	uint8_t  enable;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_RPA_TIMEOUT            BT_OP(BT_OGF_LE, 0x002e)
+struct bt_hci_cp_le_set_rpa_timeout {
+	uint16_t rpa_timeout;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_MAX_DATA_LEN          BT_OP(BT_OGF_LE, 0x002f)
+struct bt_hci_rp_le_read_max_data_len {
+	uint8_t  status;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+} __packed;
+
+#define BT_HCI_LE_PHY_1M                        0x01
+#define BT_HCI_LE_PHY_2M                        0x02
+#define BT_HCI_LE_PHY_CODED                     0x03
+
+#define BT_HCI_OP_LE_READ_PHY                   BT_OP(BT_OGF_LE, 0x0030)
+struct bt_hci_cp_le_read_phy {
+	uint16_t handle;
+} __packed;
+struct bt_hci_rp_le_read_phy {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  tx_phy;
+	uint8_t  rx_phy;
+} __packed;
+
+#define BT_HCI_LE_PHY_TX_ANY                    BIT(0)
+#define BT_HCI_LE_PHY_RX_ANY                    BIT(1)
+
+#define BT_HCI_LE_PHY_PREFER_1M                 BIT(0)
+#define BT_HCI_LE_PHY_PREFER_2M                 BIT(1)
+#define BT_HCI_LE_PHY_PREFER_CODED              BIT(2)
+
+#define BT_HCI_OP_LE_SET_DEFAULT_PHY            BT_OP(BT_OGF_LE, 0x0031)
+struct bt_hci_cp_le_set_default_phy {
+	uint8_t all_phys;
+	uint8_t tx_phys;
+	uint8_t rx_phys;
+} __packed;
+
+#define BT_HCI_LE_PHY_CODED_ANY                 0x00
+#define BT_HCI_LE_PHY_CODED_S2                  0x01
+#define BT_HCI_LE_PHY_CODED_S8                  0x02
+
+#define BT_HCI_OP_LE_SET_PHY                    BT_OP(BT_OGF_LE, 0x0032)
+struct bt_hci_cp_le_set_phy {
+	uint16_t  handle;
+	uint8_t   all_phys;
+	uint8_t   tx_phys;
+	uint8_t   rx_phys;
+	uint16_t  phy_opts;
+} __packed;
+
+#define BT_HCI_LE_MOD_INDEX_STANDARD            0x00
+#define BT_HCI_LE_MOD_INDEX_STABLE              0x01
+
+#define BT_HCI_OP_LE_ENH_RX_TEST                BT_OP(BT_OGF_LE, 0x0033)
+struct bt_hci_cp_le_enh_rx_test {
+	uint8_t  rx_ch;
+	uint8_t  phy;
+	uint8_t  mod_index;
+} __packed;
+
+/* Extends BT_HCI_LE_PHY */
+#define BT_HCI_LE_TX_PHY_CODED_S8               0x03
+#define BT_HCI_LE_TX_PHY_CODED_S2               0x04
+
+#define BT_HCI_OP_LE_ENH_TX_TEST                BT_OP(BT_OGF_LE, 0x0034)
+struct bt_hci_cp_le_enh_tx_test {
+	uint8_t  tx_ch;
+	uint8_t  test_data_len;
+	uint8_t  pkt_payload;
+	uint8_t  phy;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR    BT_OP(BT_OGF_LE, 0x0035)
+struct bt_hci_cp_le_set_adv_set_random_addr {
+	uint8_t   handle;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_LE_ADV_PROP_CONN                 BIT(0)
+#define BT_HCI_LE_ADV_PROP_SCAN                 BIT(1)
+#define BT_HCI_LE_ADV_PROP_DIRECT               BIT(2)
+#define BT_HCI_LE_ADV_PROP_HI_DC_CONN           BIT(3)
+#define BT_HCI_LE_ADV_PROP_LEGACY               BIT(4)
+#define BT_HCI_LE_ADV_PROP_ANON                 BIT(5)
+#define BT_HCI_LE_ADV_PROP_TX_POWER             BIT(6)
+
+#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE  1
+#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0
+
+#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F
+
+#define BT_HCI_LE_ADV_HANDLE_MAX       0xEF
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM          BT_OP(BT_OGF_LE, 0x0036)
+struct bt_hci_cp_le_set_ext_adv_param {
+	uint8_t      handle;
+	uint16_t     props;
+	uint8_t      prim_min_interval[3];
+	uint8_t      prim_max_interval[3];
+	uint8_t      prim_channel_map;
+	uint8_t      own_addr_type;
+	bt_addr_le_t peer_addr;
+	uint8_t      filter_policy;
+	int8_t       tx_power;
+	uint8_t      prim_adv_phy;
+	uint8_t      sec_adv_max_skip;
+	uint8_t      sec_adv_phy;
+	uint8_t      sid;
+	uint8_t      scan_req_notify_enable;
+} __packed;
+struct bt_hci_rp_le_set_ext_adv_param {
+	uint8_t status;
+	int8_t  tx_power;
+} __packed;
+
+#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG        0x00
+#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG         0x01
+#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG          0x02
+#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA      0x03
+#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA     0x04
+
+#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED          0x00
+#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED         0x01
+
+#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN          251
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_DATA           BT_OP(BT_OGF_LE, 0x0037)
+struct bt_hci_cp_le_set_ext_adv_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  frag_pref;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA      BT_OP(BT_OGF_LE, 0x0038)
+struct bt_hci_cp_le_set_ext_scan_rsp_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  frag_pref;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0039)
+struct bt_hci_ext_adv_set {
+	uint8_t  handle;
+	uint16_t duration;
+	uint8_t  max_ext_adv_evts;
+} __packed;
+
+struct bt_hci_cp_le_set_ext_adv_enable {
+	uint8_t  enable;
+	uint8_t  set_num;
+	struct bt_hci_ext_adv_set s[0];
+} __packed;
+
+#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN      BT_OP(BT_OGF_LE, 0x003a)
+struct bt_hci_rp_le_read_max_adv_data_len {
+	uint8_t  status;
+	uint16_t max_adv_data_len;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_NUM_ADV_SETS          BT_OP(BT_OGF_LE, 0x003b)
+struct bt_hci_rp_le_read_num_adv_sets {
+	uint8_t  status;
+	uint8_t  num_sets;
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_ADV_SET             BT_OP(BT_OGF_LE, 0x003c)
+struct bt_hci_cp_le_remove_adv_set {
+	uint8_t  handle;
+} __packed;
+
+#define BT_HCI_OP_CLEAR_ADV_SETS                BT_OP(BT_OGF_LE, 0x003d)
+
+#define BT_HCI_OP_LE_SET_PER_ADV_PARAM          BT_OP(BT_OGF_LE, 0x003e)
+struct bt_hci_cp_le_set_per_adv_param {
+	uint8_t  handle;
+	uint16_t min_interval;
+	uint16_t max_interval;
+	uint16_t props;
+} __packed;
+
+#define BT_HCI_LE_PER_ADV_OP_INTERM_FRAG        0x00
+#define BT_HCI_LE_PER_ADV_OP_FIRST_FRAG         0x01
+#define BT_HCI_LE_PER_ADV_OP_LAST_FRAG          0x02
+#define BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA      0x03
+
+#define BT_HCI_LE_PER_ADV_FRAG_MAX_LEN          252
+
+#define BT_HCI_OP_LE_SET_PER_ADV_DATA           BT_OP(BT_OGF_LE, 0x003f)
+struct bt_hci_cp_le_set_per_adv_data {
+	uint8_t  handle;
+	uint8_t  op;
+	uint8_t  len;
+	uint8_t  data[251];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE         BT_OP(BT_OGF_LE, 0x0040)
+struct bt_hci_cp_le_set_per_adv_enable {
+	uint8_t  enable;
+	uint8_t  handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM         BT_OP(BT_OGF_LE, 0x0041)
+struct bt_hci_ext_scan_phy {
+	uint8_t  type;
+	uint16_t interval;
+	uint16_t window;
+} __packed;
+
+#define BT_HCI_LE_EXT_SCAN_PHY_1M               BIT(0)
+#define BT_HCI_LE_EXT_SCAN_PHY_2M               BIT(1)
+#define BT_HCI_LE_EXT_SCAN_PHY_CODED            BIT(2)
+
+struct bt_hci_cp_le_set_ext_scan_param {
+	uint8_t  own_addr_type;
+	uint8_t  filter_policy;
+	uint8_t  phys;
+	struct bt_hci_ext_scan_phy p[0];
+} __packed;
+
+/* Extends BT_HCI_LE_SCAN_FILTER_DUP */
+#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET  0x02
+
+#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE        BT_OP(BT_OGF_LE, 0x0042)
+struct bt_hci_cp_le_set_ext_scan_enable {
+	uint8_t  enable;
+	uint8_t  filter_dup;
+	uint16_t duration;
+	uint16_t period;
+} __packed;
+
+#define BT_HCI_OP_LE_EXT_CREATE_CONN            BT_OP(BT_OGF_LE, 0x0043)
+struct bt_hci_ext_conn_phy {
+	uint16_t scan_interval;
+	uint16_t scan_window;
+	uint16_t conn_interval_min;
+	uint16_t conn_interval_max;
+	uint16_t conn_latency;
+	uint16_t supervision_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __packed;
+
+struct bt_hci_cp_le_ext_create_conn {
+	uint8_t      filter_policy;
+	uint8_t      own_addr_type;
+	bt_addr_le_t peer_addr;
+	uint8_t      phys;
+	struct bt_hci_ext_conn_phy p[0];
+} __packed;
+
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST               BIT(0)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED       BIT(1)
+
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA           BIT(0)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US       BIT(1)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US       BIT(2)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_CTE           BIT(3)
+#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE         BIT(4)
+
+#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC        BT_OP(BT_OGF_LE, 0x0044)
+struct bt_hci_cp_le_per_adv_create_sync {
+	uint8_t      options;
+	uint8_t      sid;
+	bt_addr_le_t addr;
+	uint16_t     skip;
+	uint16_t     sync_timeout;
+	uint8_t      cte_type;
+} __packed;
+
+#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045)
+
+#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC     BT_OP(BT_OGF_LE, 0x0046)
+struct bt_hci_cp_le_per_adv_terminate_sync {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST    BT_OP(BT_OGF_LE, 0x0047)
+struct bt_hci_cp_le_add_dev_to_per_adv_list {
+	bt_addr_le_t addr;
+	uint8_t      sid;
+} __packed;
+
+#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST  BT_OP(BT_OGF_LE, 0x0048)
+struct bt_hci_cp_le_rem_dev_from_per_adv_list {
+	bt_addr_le_t addr;
+	uint8_t      sid;
+} __packed;
+
+#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST         BT_OP(BT_OGF_LE, 0x0049)
+
+#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE     BT_OP(BT_OGF_LE, 0x004a)
+struct bt_hci_rp_le_read_per_adv_list_size {
+	uint8_t  status;
+	uint8_t  list_size;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_TX_POWER              BT_OP(BT_OGF_LE, 0x004b)
+struct bt_hci_rp_le_read_tx_power {
+	uint8_t status;
+	int8_t  min_tx_power;
+	int8_t  max_tx_power;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_RF_PATH_COMP          BT_OP(BT_OGF_LE, 0x004c)
+struct bt_hci_rp_le_read_rf_path_comp {
+	uint8_t status;
+	int16_t tx_path_comp;
+	int16_t rx_path_comp;
+} __packed;
+
+#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP         BT_OP(BT_OGF_LE, 0x004d)
+struct bt_hci_cp_le_write_rf_path_comp {
+	int16_t  tx_path_comp;
+	int16_t  rx_path_comp;
+} __packed;
+
+#define BT_HCI_LE_PRIVACY_MODE_NETWORK          0x00
+#define BT_HCI_LE_PRIVACY_MODE_DEVICE           0x01
+
+#define BT_HCI_OP_LE_SET_PRIVACY_MODE           BT_OP(BT_OGF_LE, 0x004e)
+struct bt_hci_cp_le_set_privacy_mode {
+	bt_addr_le_t id_addr;
+	uint8_t         mode;
+} __packed;
+
+#define BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE     BT_OP(BT_OGF_LE, 0x0059)
+struct bt_hci_cp_le_set_per_adv_recv_enable {
+	uint16_t handle;
+	uint8_t  enable;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_BUFFER_SIZE_V2        BT_OP(BT_OGF_LE, 0x0060)
+struct bt_hci_rp_le_read_buffer_size_v2 {
+	uint8_t  status;
+	uint16_t acl_mtu;
+	uint8_t  acl_max_pkt;
+	uint16_t iso_mtu;
+	uint8_t  iso_max_pkt;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ISO_TX_SYNC           BT_OP(BT_OGF_LE, 0x0061)
+struct bt_hci_cp_le_read_iso_tx_sync {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_le_read_iso_tx_sync {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t seq;
+	uint32_t timestamp;
+	uint8_t  offset[3];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_CIG_PARAMS             BT_OP(BT_OGF_LE, 0x0062)
+struct bt_hci_cis_params {
+	uint8_t  cis_id;
+	uint16_t m_sdu;
+	uint16_t s_sdu;
+	uint8_t  m_phy;
+	uint8_t  s_phy;
+	uint8_t  m_rtn;
+	uint8_t  s_rtn;
+} __packed;
+
+struct bt_hci_cp_le_set_cig_params {
+	uint8_t  cig_id;
+	uint8_t  m_interval[3];
+	uint8_t  s_interval[3];
+	uint8_t  sca;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint16_t m_latency;
+	uint16_t s_latency;
+	uint8_t  num_cis;
+	struct bt_hci_cis_params cis[0];
+} __packed;
+
+struct bt_hci_rp_le_set_cig_params {
+	uint8_t  status;
+	uint8_t  cig_id;
+	uint8_t  num_handles;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST        BT_OP(BT_OGF_LE, 0x0063)
+
+#define BT_HCI_OP_LE_CREATE_CIS                 BT_OP(BT_OGF_LE, 0x0064)
+struct bt_hci_cis {
+	uint16_t  cis_handle;
+	uint16_t  acl_handle;
+} __packed;
+
+struct bt_hci_cp_le_create_cis {
+	uint8_t  num_cis;
+	struct bt_hci_cis cis[0];
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_CIG                 BT_OP(BT_OGF_LE, 0x0065)
+struct bt_hci_cp_le_remove_cig {
+	uint8_t  cig_id;
+} __packed;
+
+struct bt_hci_rp_le_remove_cig {
+	uint8_t  status;
+	uint8_t  cig_id;
+} __packed;
+
+#define BT_HCI_OP_LE_ACCEPT_CIS                 BT_OP(BT_OGF_LE, 0x0066)
+struct bt_hci_cp_le_accept_cis {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REJECT_CIS                 BT_OP(BT_OGF_LE, 0x0067)
+struct bt_hci_cp_le_reject_cis {
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+struct bt_hci_rp_le_reject_cis {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_BIG                 BT_OP(BT_OGF_LE, 0x0068)
+struct bt_hci_cp_le_create_big {
+	uint8_t  big_handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	uint8_t  sdu_interval[3];
+	uint16_t max_sdu;
+	uint16_t max_latency;
+	uint8_t  rtn;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+} __packed;
+
+#define BT_HCI_OP_LE_CREATE_BIG_TEST            BT_OP(BT_OGF_LE, 0x0069)
+struct bt_hci_cp_le_create_big_test {
+	uint8_t  big_handle;
+	uint8_t  adv_handle;
+	uint8_t  num_bis;
+	uint8_t  sdu_interval[3];
+	uint16_t iso_interval;
+	uint8_t  nse;
+	uint16_t max_sdu;
+	uint16_t max_pdu;
+	uint8_t  phy;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  bn;
+	uint8_t  irc;
+	uint8_t  pto;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+} __packed;
+
+#define BT_HCI_OP_LE_TERMINATE_BIG              BT_OP(BT_OGF_LE, 0x006a)
+struct bt_hci_cp_le_terminate_big {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_OP_LE_BIG_CREATE_SYNC            BT_OP(BT_OGF_LE, 0x006b)
+struct bt_hci_cp_le_big_create_sync {
+	uint8_t  big_handle;
+	uint16_t sync_handle;
+	uint8_t  encryption;
+	uint8_t  bcode[16];
+	uint8_t  mse;
+	uint16_t sync_timeout;
+	uint8_t  num_bis;
+	uint8_t  bis[0];
+} __packed;
+
+#define BT_HCI_OP_LE_BIG_TERMINATE_SYNC         BT_OP(BT_OGF_LE, 0x006c)
+struct bt_hci_cp_le_big_terminate_sync {
+	uint8_t  big_handle;
+} __packed;
+
+struct bt_hci_rp_le_big_terminate_sync {
+	uint8_t  status;
+	uint8_t  big_handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REQ_PEER_SC                BT_OP(BT_OGF_LE, 0x006d)
+struct bt_hci_cp_le_req_peer_sca {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_SETUP_ISO_PATH             BT_OP(BT_OGF_LE, 0x006e)
+struct bt_hci_cp_le_setup_iso_path {
+	uint16_t handle;
+	uint8_t  path_dir;
+	uint8_t  path_id;
+	uint8_t  coding_format;
+	uint16_t company_id;
+	uint16_t vendor_id;
+	uint8_t  controller_delay[3];
+	uint8_t  codec_config_len;
+	uint8_t  codec_config[0];
+} __packed;
+
+struct bt_hci_rp_le_setup_iso_path {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_REMOVE_ISO_PATH            BT_OP(BT_OGF_LE, 0x006f)
+struct bt_hci_cp_le_remove_iso_path {
+	uint16_t handle;
+	uint8_t  path_dir;
+} __packed;
+
+struct bt_hci_rp_le_remove_iso_path {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST          BT_OP(BT_OGF_LE, 0x0070)
+
+#define BT_HCI_OP_LE_ISO_RECEIVE_TEST           BT_OP(BT_OGF_LE, 0x0071)
+
+#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS     BT_OP(BT_OGF_LE, 0x0072)
+
+#define BT_HCI_OP_LE_ISO_TEST_END               BT_OP(BT_OGF_LE, 0x0073)
+
+#define BT_HCI_OP_LE_SET_HOST_FEATURE           BT_OP(BT_OGF_LE, 0x0074)
+struct bt_hci_cp_le_set_host_feature {
+	uint8_t  bit_number;
+	uint8_t  bit_value;
+} __packed;
+
+struct bt_hci_rp_le_set_host_feature {
+	uint8_t  status;
+} __packed;
+
+#define BT_HCI_OP_LE_READ_ISO_LINK_QUALITY      BT_OP(BT_OGF_LE, 0x0075)
+struct bt_hci_cp_le_read_iso_link_quality {
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_le_read_iso_link_quality {
+	uint8_t  status;
+	uint16_t handle;
+	uint32_t tx_unacked_packets;
+	uint32_t tx_flushed_packets;
+	uint32_t tx_last_subevent_packets;
+	uint32_t retransmitted_packets;
+	uint32_t crc_error_packets;
+	uint32_t rx_unreceived_packets;
+	uint32_t duplicate_packets;
+} __packed;
+
+/* Event definitions */
+
+#define BT_HCI_EVT_UNKNOWN                      0x00
+#define BT_HCI_EVT_VENDOR                       0xff
+
+#define BT_HCI_EVT_INQUIRY_COMPLETE             0x01
+struct bt_hci_evt_inquiry_complete {
+	uint8_t status;
+} __packed;
+
+#define BT_HCI_EVT_CONN_COMPLETE                0x03
+struct bt_hci_evt_conn_complete {
+	uint8_t   status;
+	uint16_t  handle;
+	bt_addr_t bdaddr;
+	uint8_t   link_type;
+	uint8_t   encr_enabled;
+} __packed;
+
+#define BT_HCI_EVT_CONN_REQUEST                 0x04
+struct bt_hci_evt_conn_request {
+	bt_addr_t bdaddr;
+	uint8_t   dev_class[3];
+	uint8_t   link_type;
+} __packed;
+
+#define BT_HCI_EVT_DISCONN_COMPLETE             0x05
+struct bt_hci_evt_disconn_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_AUTH_COMPLETE                0x06
+struct bt_hci_evt_auth_complete {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE     0x07
+struct bt_hci_evt_remote_name_req_complete {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+	uint8_t   name[248];
+} __packed;
+
+#define BT_HCI_EVT_ENCRYPT_CHANGE               0x08
+struct bt_hci_evt_encrypt_change {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  encrypt;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_FEATURES              0x0b
+struct bt_hci_evt_remote_features {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_VERSION_INFO          0x0c
+struct bt_hci_evt_remote_version_info {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  version;
+	uint16_t manufacturer;
+	uint16_t subversion;
+} __packed;
+
+#define BT_HCI_EVT_CMD_COMPLETE                 0x0e
+struct bt_hci_evt_cmd_complete {
+	uint8_t  ncmd;
+	uint16_t opcode;
+} __packed;
+
+struct bt_hci_evt_cc_status {
+	uint8_t  status;
+} __packed;
+
+#define BT_HCI_EVT_CMD_STATUS                   0x0f
+struct bt_hci_evt_cmd_status {
+	uint8_t  status;
+	uint8_t  ncmd;
+	uint16_t opcode;
+} __packed;
+
+#define BT_HCI_EVT_HARDWARE_ERROR               0x10
+struct bt_hci_evt_hardware_error {
+	uint8_t  hardware_code;
+} __packed;
+
+#define BT_HCI_EVT_ROLE_CHANGE                  0x12
+struct bt_hci_evt_role_change {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+	uint8_t   role;
+} __packed;
+
+#define BT_HCI_EVT_NUM_COMPLETED_PACKETS        0x13
+struct bt_hci_evt_num_completed_packets {
+	uint8_t  num_handles;
+	struct bt_hci_handle_count h[0];
+} __packed;
+
+#define BT_HCI_EVT_PIN_CODE_REQ                 0x16
+struct bt_hci_evt_pin_code_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_LINK_KEY_REQ                 0x17
+struct bt_hci_evt_link_key_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+/* Link Key types */
+#define BT_LK_COMBINATION                       0x00
+#define BT_LK_LOCAL_UNIT                        0x01
+#define BT_LK_REMOTE_UNIT                       0x02
+#define BT_LK_DEBUG_COMBINATION                 0x03
+#define BT_LK_UNAUTH_COMBINATION_P192           0x04
+#define BT_LK_AUTH_COMBINATION_P192             0x05
+#define BT_LK_CHANGED_COMBINATION               0x06
+#define BT_LK_UNAUTH_COMBINATION_P256           0x07
+#define BT_LK_AUTH_COMBINATION_P256             0x08
+
+#define BT_HCI_EVT_LINK_KEY_NOTIFY              0x18
+struct bt_hci_evt_link_key_notify {
+	bt_addr_t bdaddr;
+	uint8_t   link_key[16];
+	uint8_t   key_type;
+} __packed;
+
+/* Overflow link types */
+#define BT_OVERFLOW_LINK_SYNCH                  0x00
+#define BT_OVERFLOW_LINK_ACL                    0x01
+
+#define BT_HCI_EVT_DATA_BUF_OVERFLOW            0x1a
+struct bt_hci_evt_data_buf_overflow {
+	uint8_t  link_type;
+} __packed;
+
+#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI     0x22
+struct bt_hci_evt_inquiry_result_with_rssi {
+	bt_addr_t addr;
+	uint8_t   pscan_rep_mode;
+	uint8_t   reserved;
+	uint8_t   cod[3];
+	uint16_t  clock_offset;
+	int8_t    rssi;
+} __packed;
+
+#define BT_HCI_EVT_REMOTE_EXT_FEATURES          0x23
+struct bt_hci_evt_remote_ext_features {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  page;
+	uint8_t  max_page;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_SYNC_CONN_COMPLETE           0x2c
+struct bt_hci_evt_sync_conn_complete {
+	uint8_t    status;
+	uint16_t   handle;
+	bt_addr_t  bdaddr;
+	uint8_t    link_type;
+	uint8_t    tx_interval;
+	uint8_t    retansmission_window;
+	uint16_t   rx_pkt_length;
+	uint16_t   tx_pkt_length;
+	uint8_t    air_mode;
+} __packed;
+
+#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT      0x2f
+struct bt_hci_evt_extended_inquiry_result {
+	uint8_t    num_reports;
+	bt_addr_t  addr;
+	uint8_t    pscan_rep_mode;
+	uint8_t    reserved;
+	uint8_t    cod[3];
+	uint16_t   clock_offset;
+	int8_t     rssi;
+	uint8_t    eir[240];
+} __packed;
+
+#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30
+struct bt_hci_evt_encrypt_key_refresh_complete {
+	uint8_t  status;
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_IO_CAPA_REQ                  0x31
+struct bt_hci_evt_io_capa_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_IO_CAPA_RESP                 0x32
+struct bt_hci_evt_io_capa_resp {
+	bt_addr_t bdaddr;
+	uint8_t   capability;
+	uint8_t   oob_data;
+	uint8_t   authentication;
+} __packed;
+
+#define BT_HCI_EVT_USER_CONFIRM_REQ             0x33
+struct bt_hci_evt_user_confirm_req {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_EVT_USER_PASSKEY_REQ             0x34
+struct bt_hci_evt_user_passkey_req {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_SSP_COMPLETE                 0x36
+struct bt_hci_evt_ssp_complete {
+	uint8_t   status;
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_EVT_USER_PASSKEY_NOTIFY          0x3b
+struct bt_hci_evt_user_passkey_notify {
+	bt_addr_t bdaddr;
+	uint32_t  passkey;
+} __packed;
+
+#define BT_HCI_EVT_LE_META_EVENT                0x3e
+struct bt_hci_evt_le_meta_event {
+	uint8_t  subevent;
+} __packed;
+
+#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP     0x57
+struct bt_hci_evt_auth_payload_timeout_exp {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_ROLE_MASTER                      0x00
+#define BT_HCI_ROLE_SLAVE                       0x01
+
+#define BT_HCI_EVT_LE_CONN_COMPLETE             0x01
+struct bt_hci_evt_le_conn_complete {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      role;
+	bt_addr_le_t peer_addr;
+	uint16_t     interval;
+	uint16_t     latency;
+	uint16_t     supv_timeout;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_ADVERTISING_REPORT        0x02
+struct bt_hci_evt_le_advertising_info {
+	uint8_t      evt_type;
+	bt_addr_le_t addr;
+	uint8_t      length;
+	uint8_t      data[0];
+} __packed;
+struct bt_hci_evt_le_advertising_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_advertising_info adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE      0x03
+struct bt_hci_evt_le_conn_update_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t interval;
+	uint16_t latency;
+	uint16_t supv_timeout;
+} __packed;
+
+#define BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE       0x04
+struct bt_hci_evt_le_remote_feat_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_EVT_LE_LTK_REQUEST               0x05
+struct bt_hci_evt_le_ltk_request {
+	uint16_t handle;
+	uint64_t rand;
+	uint16_t ediv;
+} __packed;
+
+#define BT_HCI_EVT_LE_CONN_PARAM_REQ            0x06
+struct bt_hci_evt_le_conn_param_req {
+	uint16_t handle;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+} __packed;
+
+#define BT_HCI_EVT_LE_DATA_LEN_CHANGE           0x07
+struct bt_hci_evt_le_data_len_change {
+	uint16_t handle;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+} __packed;
+
+#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE  0x08
+struct bt_hci_evt_le_p256_public_key_complete {
+	uint8_t status;
+	uint8_t key[64];
+} __packed;
+
+#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE   0x09
+struct bt_hci_evt_le_generate_dhkey_complete {
+	uint8_t status;
+	uint8_t dhkey[32];
+} __packed;
+
+#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE         0x0a
+struct bt_hci_evt_le_enh_conn_complete {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      role;
+	bt_addr_le_t peer_addr;
+	bt_addr_t    local_rpa;
+	bt_addr_t    peer_rpa;
+	uint16_t     interval;
+	uint16_t     latency;
+	uint16_t     supv_timeout;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT         0x0b
+struct bt_hci_evt_le_direct_adv_info {
+	uint8_t      evt_type;
+	bt_addr_le_t addr;
+	bt_addr_le_t dir_addr;
+	int8_t       rssi;
+} __packed;
+struct bt_hci_evt_le_direct_adv_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_direct_adv_info direct_adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE       0x0c
+struct bt_hci_evt_le_phy_update_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  tx_phy;
+	uint8_t  rx_phy;
+} __packed;
+
+#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT    0x0d
+
+#define BT_HCI_LE_ADV_EVT_TYPE_CONN                 BIT(0)
+#define BT_HCI_LE_ADV_EVT_TYPE_SCAN                 BIT(1)
+#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT               BIT(2)
+#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP             BIT(3)
+#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY               BIT(4)
+
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03)
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE   0
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL    1
+#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2
+
+struct bt_hci_evt_le_ext_advertising_info {
+	uint16_t     evt_type;
+	bt_addr_le_t addr;
+	uint8_t      prim_phy;
+	uint8_t      sec_phy;
+	uint8_t      sid;
+	int8_t       tx_power;
+	int8_t       rssi;
+	uint16_t     interval;
+	bt_addr_le_t direct_addr;
+	uint8_t      length;
+	uint8_t      data[0];
+} __packed;
+struct bt_hci_evt_le_ext_advertising_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_le_ext_advertising_info adv_info[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED  0x0e
+struct bt_hci_evt_le_per_adv_sync_established {
+	uint8_t      status;
+	uint16_t     handle;
+	uint8_t      sid;
+	bt_addr_le_t adv_addr;
+	uint8_t      phy;
+	uint16_t     interval;
+	uint8_t      clock_accuracy;
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT    0x0f
+struct bt_hci_evt_le_per_advertising_report {
+	uint16_t handle;
+	int8_t   tx_power;
+	int8_t   rssi;
+	uint8_t  cte_type;
+	uint8_t  data_status;
+	uint8_t  length;
+	uint8_t  data[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST         0x10
+struct bt_hci_evt_le_per_adv_sync_lost {
+	uint16_t handle;
+} __packed;
+
+#define BT_HCI_EVT_LE_SCAN_TIMEOUT              0x11
+
+#define BT_HCI_EVT_LE_ADV_SET_TERMINATED        0x12
+struct bt_hci_evt_le_adv_set_terminated {
+	uint8_t  status;
+	uint8_t  adv_handle;
+	uint16_t conn_handle;
+	uint8_t  num_completed_ext_adv_evts;
+} __packed;
+
+#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED         0x13
+struct bt_hci_evt_le_scan_req_received {
+	uint8_t      handle;
+	bt_addr_le_t addr;
+} __packed;
+
+#define BT_HCI_LE_CHAN_SEL_ALGO_1               0x00
+#define BT_HCI_LE_CHAN_SEL_ALGO_2               0x01
+
+#define BT_HCI_EVT_LE_CHAN_SEL_ALGO             0x14
+struct bt_hci_evt_le_chan_sel_algo {
+	uint16_t handle;
+	uint8_t  chan_sel_algo;
+} __packed;
+
+#define BT_HCI_EVT_LE_CIS_ESTABLISHED           0x19
+struct bt_hci_evt_le_cis_established {
+	uint8_t  status;
+	uint16_t conn_handle;
+	uint8_t  cig_sync_delay[3];
+	uint8_t  cis_sync_delay[3];
+	uint8_t  m_latency[3];
+	uint8_t  s_latency[3];
+	uint8_t  m_phy;
+	uint8_t  s_phy;
+	uint8_t  nse;
+	uint8_t  m_bn;
+	uint8_t  s_bn;
+	uint8_t  m_ft;
+	uint8_t  s_ft;
+	uint16_t m_max_pdu;
+	uint16_t s_max_pdu;
+	uint16_t interval;
+} __packed;
+
+#define BT_HCI_EVT_LE_CIS_REQ                   0x1a
+struct bt_hci_evt_le_cis_req {
+	uint16_t acl_handle;
+	uint16_t cis_handle;
+	uint8_t  cig_id;
+	uint8_t  cis_id;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_COMPLETE              0x1b
+struct bt_hci_evt_le_big_complete {
+	uint8_t  status;
+	uint8_t  big_handle;
+	uint8_t  sync_delay[3];
+	uint8_t  latency[3];
+	uint8_t  phy;
+	uint8_t  nse;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  num_bis;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_TERMINATE             0x1c
+struct bt_hci_evt_le_big_terminate {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED      0x1d
+struct bt_hci_evt_le_big_sync_established {
+	uint8_t  status;
+	uint8_t  big_handle;
+	uint8_t  latency[3];
+	uint8_t  nse;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  num_bis;
+	uint16_t handle[0];
+} __packed;
+
+#define BT_HCI_EVT_LE_BIG_SYNC_LOST             0x1e
+struct bt_hci_evt_le_big_sync_lost {
+	uint8_t  big_handle;
+	uint8_t  reason;
+} __packed;
+
+#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE     0x1f
+struct bt_hci_evt_le_req_peer_sca_complete {
+	uint8_t  status;
+	uint16_t handle;
+	uint8_t  sca;
+} __packed;
+
+#define BT_HCI_EVT_LE_BIGINFO_ADV_REPORT        0x22
+struct bt_hci_evt_le_biginfo_adv_report {
+	uint16_t sync_handle;
+	uint8_t  num_bis;
+	uint8_t  nse;
+	uint16_t iso_interval;
+	uint8_t  bn;
+	uint8_t  pto;
+	uint8_t  irc;
+	uint16_t max_pdu;
+	uint8_t  sdu_interval[3];
+	uint16_t max_sdu;
+	uint8_t  phy;
+	uint8_t  framing;
+	uint8_t  encryption;
+} __packed;
+
+/* Event mask bits */
+
+#define BT_EVT_BIT(n) (1ULL << (n))
+
+#define BT_EVT_MASK_INQUIRY_COMPLETE             BT_EVT_BIT(0)
+#define BT_EVT_MASK_CONN_COMPLETE                BT_EVT_BIT(2)
+#define BT_EVT_MASK_CONN_REQUEST                 BT_EVT_BIT(3)
+#define BT_EVT_MASK_DISCONN_COMPLETE             BT_EVT_BIT(4)
+#define BT_EVT_MASK_AUTH_COMPLETE                BT_EVT_BIT(5)
+#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE     BT_EVT_BIT(6)
+#define BT_EVT_MASK_ENCRYPT_CHANGE               BT_EVT_BIT(7)
+#define BT_EVT_MASK_REMOTE_FEATURES              BT_EVT_BIT(10)
+#define BT_EVT_MASK_REMOTE_VERSION_INFO          BT_EVT_BIT(11)
+#define BT_EVT_MASK_HARDWARE_ERROR               BT_EVT_BIT(15)
+#define BT_EVT_MASK_ROLE_CHANGE                  BT_EVT_BIT(17)
+#define BT_EVT_MASK_PIN_CODE_REQ                 BT_EVT_BIT(21)
+#define BT_EVT_MASK_LINK_KEY_REQ                 BT_EVT_BIT(22)
+#define BT_EVT_MASK_LINK_KEY_NOTIFY              BT_EVT_BIT(23)
+#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW         BT_EVT_BIT(25)
+#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI     BT_EVT_BIT(33)
+#define BT_EVT_MASK_REMOTE_EXT_FEATURES          BT_EVT_BIT(34)
+#define BT_EVT_MASK_SYNC_CONN_COMPLETE           BT_EVT_BIT(43)
+#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT      BT_EVT_BIT(46)
+#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47)
+#define BT_EVT_MASK_IO_CAPA_REQ                  BT_EVT_BIT(48)
+#define BT_EVT_MASK_IO_CAPA_RESP                 BT_EVT_BIT(49)
+#define BT_EVT_MASK_USER_CONFIRM_REQ             BT_EVT_BIT(50)
+#define BT_EVT_MASK_USER_PASSKEY_REQ             BT_EVT_BIT(51)
+#define BT_EVT_MASK_SSP_COMPLETE                 BT_EVT_BIT(53)
+#define BT_EVT_MASK_USER_PASSKEY_NOTIFY          BT_EVT_BIT(58)
+#define BT_EVT_MASK_LE_META_EVENT                BT_EVT_BIT(61)
+
+/* Page 2 */
+#define BT_EVT_MASK_PHY_LINK_COMPLETE            BT_EVT_BIT(0)
+#define BT_EVT_MASK_CH_SELECTED_COMPLETE         BT_EVT_BIT(1)
+#define BT_EVT_MASK_DISCONN_PHY_LINK_COMPLETE    BT_EVT_BIT(2)
+#define BT_EVT_MASK_PHY_LINK_LOSS_EARLY_WARN     BT_EVT_BIT(3)
+#define BT_EVT_MASK_PHY_LINK_RECOVERY            BT_EVT_BIT(4)
+#define BT_EVT_MASK_LOG_LINK_COMPLETE            BT_EVT_BIT(5)
+#define BT_EVT_MASK_DISCONN_LOG_LINK_COMPLETE    BT_EVT_BIT(6)
+#define BT_EVT_MASK_FLOW_SPEC_MODIFY_COMPLETE    BT_EVT_BIT(7)
+#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS     BT_EVT_BIT(8)
+#define BT_EVT_MASK_AMP_START_TEST               BT_EVT_BIT(9)
+#define BT_EVT_MASK_AMP_TEST_END                 BT_EVT_BIT(10)
+#define BT_EVT_MASK_AMP_RX_REPORT                BT_EVT_BIT(11)
+#define BT_EVT_MASK_AMP_SR_MODE_CHANGE_COMPLETE  BT_EVT_BIT(12)
+#define BT_EVT_MASK_AMP_STATUS_CHANGE            BT_EVT_BIT(13)
+#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE          BT_EVT_BIT(14)
+#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE         BT_EVT_BIT(15)
+#define BT_EVT_MASK_SYNCH_TRAIN_RX               BT_EVT_BIT(16)
+#define BT_EVT_MASK_CL_SLAVE_BC_RX               BT_EVT_BIT(17)
+#define BT_EVT_MASK_CL_SLAVE_BC_TIMEOUT          BT_EVT_BIT(18)
+#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE          BT_EVT_BIT(19)
+#define BT_EVT_MASK_SLAVE_PAGE_RSP_TIMEOUT       BT_EVT_BIT(20)
+#define BT_EVT_MASK_CL_SLAVE_BC_CH_MAP_CHANGE    BT_EVT_BIT(21)
+#define BT_EVT_MASK_INQUIRY_RSP_NOT              BT_EVT_BIT(22)
+#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP     BT_EVT_BIT(23)
+#define BT_EVT_MASK_SAM_STATUS_CHANGE            BT_EVT_BIT(24)
+
+#define BT_EVT_MASK_LE_CONN_COMPLETE             BT_EVT_BIT(0)
+#define BT_EVT_MASK_LE_ADVERTISING_REPORT        BT_EVT_BIT(1)
+#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE      BT_EVT_BIT(2)
+#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE      BT_EVT_BIT(3)
+#define BT_EVT_MASK_LE_LTK_REQUEST               BT_EVT_BIT(4)
+#define BT_EVT_MASK_LE_CONN_PARAM_REQ            BT_EVT_BIT(5)
+#define BT_EVT_MASK_LE_DATA_LEN_CHANGE           BT_EVT_BIT(6)
+#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE  BT_EVT_BIT(7)
+#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE   BT_EVT_BIT(8)
+#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE         BT_EVT_BIT(9)
+#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT         BT_EVT_BIT(10)
+#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE       BT_EVT_BIT(11)
+#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT    BT_EVT_BIT(12)
+#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED  BT_EVT_BIT(13)
+#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT    BT_EVT_BIT(14)
+#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST         BT_EVT_BIT(15)
+#define BT_EVT_MASK_LE_SCAN_TIMEOUT              BT_EVT_BIT(16)
+#define BT_EVT_MASK_LE_ADV_SET_TERMINATED        BT_EVT_BIT(17)
+#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED         BT_EVT_BIT(18)
+#define BT_EVT_MASK_LE_CHAN_SEL_ALGO             BT_EVT_BIT(19)
+#define BT_EVT_MASK_LE_CIS_ESTABLISHED           BT_EVT_BIT(24)
+#define BT_EVT_MASK_LE_CIS_REQ                   BT_EVT_BIT(25)
+#define BT_EVT_MASK_LE_BIG_COMPLETE              BT_EVT_BIT(26)
+#define BT_EVT_MASK_LE_BIG_TERMINATED            BT_EVT_BIT(27)
+#define BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED      BT_EVT_BIT(28)
+#define BT_EVT_MASK_LE_BIG_SYNC_LOST             BT_EVT_BIT(29)
+#define BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE     BT_EVT_BIT(30)
+#define BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD       BT_EVT_BIT(31)
+#define BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING  BT_EVT_BIT(32)
+#define BT_EVT_MASK_LE_BIGINFO_ADV_REPORT        BT_EVT_BIT(33)
+
+/** Allocate a HCI command buffer.
+  *
+  * This function allocates a new buffer for a HCI command. It is given
+  * the OpCode (encoded e.g. using the BT_OP macro) and the total length
+  * of the parameters. Upon successful return the buffer is ready to have
+  * the parameters encoded into it.
+  *
+  * @param opcode     Command OpCode.
+  * @param param_len  Length of command parameters.
+  *
+  * @return Newly allocated buffer.
+  */
+struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len);
+
+/** Send a HCI command asynchronously.
+  *
+  * This function is used for sending a HCI command asynchronously. It can
+  * either be called for a buffer created using bt_hci_cmd_create(), or
+  * if the command has no parameters a NULL can be passed instead. The
+  * sending of the command will happen asynchronously, i.e. upon successful
+  * return from this function the caller only knows that it was queued
+  * successfully.
+  *
+  * If synchronous behavior, and retrieval of the Command Complete parameters
+  * is desired, the bt_hci_cmd_send_sync() API should be used instead.
+  *
+  * @param opcode Command OpCode.
+  * @param buf    Command buffer or NULL (if no parameters).
+  *
+  * @return 0 on success or negative error value on failure.
+  */
+int bt_hci_cmd_send(uint16_t opcode, struct net_buf *buf);
+
+/** Send a HCI command synchronously.
+  *
+  * This function is used for sending a HCI command synchronously. It can
+  * either be called for a buffer created using bt_hci_cmd_create(), or
+  * if the command has no parameters a NULL can be passed instead.
+  *
+  * The function will block until a Command Status or a Command Complete
+  * event is returned. If either of these have a non-zero status the function
+  * will return a negative error code and the response reference will not
+  * be set. If the command completed successfully and a non-NULL rsp parameter
+  * was given, this parameter will be set to point to a buffer containing
+  * the response parameters.
+  *
+  * @param opcode Command OpCode.
+  * @param buf    Command buffer or NULL (if no parameters).
+  * @param rsp    Place to store a reference to the command response. May
+  *               be NULL if the caller is not interested in the response
+  *               parameters. If non-NULL is passed the caller is responsible
+  *               for calling net_buf_unref() on the buffer when done parsing
+  *               it.
+  *
+  * @return 0 on success or negative error value on failure.
+  */
+int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf,
+			 struct net_buf **rsp);
+
+/** @brief Get connection handle for a connection.
+ *
+ * @param conn Connection object.
+ * @param conn_handle Place to store the Connection handle.
+ *
+ * @return 0 on success or negative error value on failure.
+ */
+int bt_hci_get_conn_handle(const struct bt_conn *conn, uint16_t *conn_handle);
+
+/** @typedef bt_hci_vnd_evt_cb_t
+  * @brief Callback type for vendor handling of HCI Vendor-Specific Events.
+  *
+  * A function of this type is registered with bt_hci_register_vnd_evt_cb()
+  * and will be called for any HCI Vendor-Specific Event.
+  *
+  * @param buf Buffer containing event parameters.
+  *
+  * @return true if the function handles the event or false to defer the
+  *         handling of this event back to the stack.
+  */
+typedef bool bt_hci_vnd_evt_cb_t(struct net_buf_simple *buf);
+
+/** Register user callback for HCI Vendor-Specific Events
+  *
+  * @param cb Callback to be called when the stack receives a
+  *           HCI Vendor-Specific Event.
+  *
+  * @return 0 on success or negative error value on failure.
+  */
+int bt_hci_register_vnd_evt_cb(bt_hci_vnd_evt_cb_t cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/hci_err.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_err.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_err.h	(working copy)
@@ -0,0 +1,92 @@
+/** @file
+ *  @brief Bluetooth Host Control Interface status codes.
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */
+#define BT_HCI_ERR_SUCCESS                      0x00
+#define BT_HCI_ERR_UNKNOWN_CMD                  0x01
+#define BT_HCI_ERR_UNKNOWN_CONN_ID              0x02
+#define BT_HCI_ERR_HW_FAILURE                   0x03
+#define BT_HCI_ERR_PAGE_TIMEOUT                 0x04
+#define BT_HCI_ERR_AUTH_FAIL                    0x05
+#define BT_HCI_ERR_PIN_OR_KEY_MISSING           0x06
+#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED        0x07
+#define BT_HCI_ERR_CONN_TIMEOUT                 0x08
+#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED          0x09
+#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED     0x0a
+#define BT_HCI_ERR_CONN_ALREADY_EXISTS          0x0b
+#define BT_HCI_ERR_CMD_DISALLOWED               0x0c
+#define BT_HCI_ERR_INSUFFICIENT_RESOURCES       0x0d
+#define BT_HCI_ERR_INSUFFICIENT_SECURITY        0x0e
+#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE         0x0f
+#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT          0x10
+#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL     0x11
+#define BT_HCI_ERR_INVALID_PARAM                0x12
+#define BT_HCI_ERR_REMOTE_USER_TERM_CONN        0x13
+#define BT_HCI_ERR_REMOTE_LOW_RESOURCES         0x14
+#define BT_HCI_ERR_REMOTE_POWER_OFF             0x15
+#define BT_HCI_ERR_LOCALHOST_TERM_CONN          0x16
+#define BT_HCI_ERR_REPEATED_ATTEMPTS            0x17
+#define BT_HCI_ERR_PAIRING_NOT_ALLOWED          0x18
+#define BT_HCI_ERR_UNKNOWN_LMP_PDU              0x19
+#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE        0x1a
+#define BT_HCI_ERR_SCO_OFFSET_REJECTED          0x1b
+#define BT_HCI_ERR_SCO_INTERVAL_REJECTED        0x1c
+#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED        0x1d
+#define BT_HCI_ERR_INVALID_LL_PARAM             0x1e
+#define BT_HCI_ERR_UNSPECIFIED                  0x1f
+#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL          0x20
+#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED      0x21
+#define BT_HCI_ERR_LL_RESP_TIMEOUT              0x22
+#define BT_HCI_ERR_LL_PROC_COLLISION            0x23
+#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED          0x24
+#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE      0x25
+#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED   0x26
+#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED  0x27
+#define BT_HCI_ERR_INSTANT_PASSED               0x28
+#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED        0x29
+#define BT_HCI_ERR_DIFF_TRANS_COLLISION         0x2a
+#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM       0x2c
+#define BT_HCI_ERR_QOS_REJECTED                 0x2d
+#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED    0x2e
+#define BT_HCI_ERR_INSUFF_SECURITY              0x2f
+#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30
+#define BT_HCI_ERR_ROLE_SWITCH_PENDING          0x32
+#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION      0x34
+#define BT_HCI_ERR_ROLE_SWITCH_FAILED           0x35
+#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE       0x36
+#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37
+#define BT_HCI_ERR_HOST_BUSY_PAIRING            0x38
+#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39
+#define BT_HCI_ERR_CONTROLLER_BUSY              0x3a
+#define BT_HCI_ERR_UNACCEPT_CONN_PARAM          0x3b
+#define BT_HCI_ERR_ADV_TIMEOUT                  0x3c
+#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL         0x3d
+#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB           0x3e
+#define BT_HCI_ERR_MAC_CONN_FAILED              0x3f
+#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED        0x40
+#define BT_HCI_ERR_SUBMAP_NOT_DEFINED           0x41
+#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER       0x42
+#define BT_HCI_ERR_LIMIT_REACHED                0x43
+#define BT_HCI_ERR_OP_CANCELLED_BY_HOST         0x44
+#define BT_HCI_ERR_PACKET_TOO_LONG              0x45
+
+#define BT_HCI_ERR_AUTHENTICATION_FAIL __DEPRECATED_MACRO BT_HCI_ERR_AUTH_FAIL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/hci_raw.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_raw.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_raw.h	(working copy)
@@ -0,0 +1,152 @@
+/** @file
+ *  @brief Bluetooth HCI RAW channel handling
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_
+
+/**
+ * @brief HCI RAW channel
+ * @defgroup hci_raw HCI RAW channel
+ * @ingroup bluetooth
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE)
+#define BT_L2CAP_MTU (CONFIG_BT_CTLR_TX_BUFFER_SIZE - BT_L2CAP_HDR_SIZE)
+#else
+#define BT_L2CAP_MTU 65 /* 64-byte public key + opcode */
+#endif /* CONFIG_BT_CTLR */
+
+/** Data size needed for ACL buffers */
+#define BT_BUF_ACL_SIZE BT_L2CAP_BUF_SIZE(BT_L2CAP_MTU)
+
+#if defined(CONFIG_BT_CTLR_TX_BUFFERS)
+#define BT_HCI_ACL_COUNT CONFIG_BT_CTLR_TX_BUFFERS
+#else
+#define BT_HCI_ACL_COUNT 6
+#endif
+
+#define BT_BUF_TX_SIZE MAX(BT_BUF_RX_SIZE, BT_BUF_ACL_SIZE)
+
+/** @brief Send packet to the Bluetooth controller
+ *
+ * Send packet to the Bluetooth controller. Caller needs to
+ * implement netbuf pool.
+ *
+ * @param buf netbuf packet to be send
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_send(struct net_buf *buf);
+
+enum {
+	/** Passthrough mode
+	 *
+	 *  While in this mode the buffers are passed as is between the stack
+	 *  and the driver.
+	 */
+	BT_HCI_RAW_MODE_PASSTHROUGH = 0x00,
+
+	/** H:4 mode
+	 *
+	 *  While in this mode H:4 headers will added into the buffers
+	 *  according to the buffer type when coming from the stack and will be
+	 *  removed and used to set the buffer type.
+	 */
+	BT_HCI_RAW_MODE_H4 = 0x01,
+};
+
+/** @brief Set Bluetooth RAW channel mode
+ *
+ *  Set access mode of Bluetooth RAW channel.
+ *
+ *  @param mode Access mode.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_hci_raw_set_mode(uint8_t mode);
+
+/** @brief Get Bluetooth RAW channel mode
+ *
+ *  Get access mode of Bluetooth RAW channel.
+ *
+ *  @return Access mode.
+ */
+uint8_t bt_hci_raw_get_mode(void);
+
+#define BT_HCI_ERR_EXT_HANDLED  0xff
+
+/** Helper macro to define a command extension
+ *
+ *  @param _op Opcode of the command.
+ *  @param _min_len Minimal length of the command.
+ *  @param _func Handler function to be called.
+ */
+#define BT_HCI_RAW_CMD_EXT(_op, _min_len, _func) \
+	{ \
+		.op = _op, \
+		.min_len = _min_len, \
+		.func = _func, \
+	}
+
+struct bt_hci_raw_cmd_ext {
+	/** Opcode of the command */
+	uint16_t  op;
+
+	/** Minimal length of the command */
+	size_t min_len;
+
+	/** Handler function.
+	 *
+	 *  Handler function to be called when a command is intercepted.
+	 *
+	 *  @param buf Buffer containing the command.
+	 *
+	 *  @return HCI Status code or BT_HCI_ERR_EXT_HANDLED if command has
+	 *  been handled already and a response has been sent as oppose to
+	 *  BT_HCI_ERR_SUCCESS which just indicates that the command can be
+	 *  sent to the controller to be processed.
+	 */
+	uint8_t   (*func)(struct net_buf *buf);
+};
+
+/** @brief Register Bluetooth RAW command extension table
+ *
+ *  Register Bluetooth RAW channel command extension table, opcodes in this
+ *  table are intercepted to sent to the handler function.
+ *
+ *  @param cmds Pointer to the command extension table.
+ *  @param size Size of the command extension table.
+ */
+void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size);
+
+/** @brief Enable Bluetooth RAW channel:
+ *
+ *  Enable Bluetooth RAW HCI channel.
+ *
+ *  @param rx_queue netbuf queue where HCI packets received from the Bluetooth
+ *  controller are to be queued. The queue is defined in the caller while
+ *  the available buffers pools are handled in the stack.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_enable_raw(struct k_fifo *rx_queue);
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_RAW_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/hci_vs.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_vs.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hci_vs.h	(working copy)
@@ -0,0 +1,379 @@
+/* hci_vs.h - Bluetooth Host Control Interface Vendor Specific definitions */
+
+/*
+ * Copyright (c) 2017-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_
+
+#include <bluetooth/hci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BT_VS_CMD_BIT_VERSION                       0
+#define BT_VS_CMD_BIT_SUP_CMD                       1
+#define BT_VS_CMD_BIT_SUP_FEAT                      2
+#define BT_VS_CMD_BIT_SET_EVT_MASK                  3
+#define BT_VS_CMD_BIT_RESET                         4
+#define BT_VS_CMD_BIT_WRITE_BDADDR                  5
+#define BT_VS_CMD_BIT_SET_TRACE_ENABLE              6
+#define BT_VS_CMD_BIT_READ_BUILD_INFO               7
+#define BT_VS_CMD_BIT_READ_STATIC_ADDRS             8
+#define BT_VS_CMD_BIT_READ_KEY_ROOTS                9
+#define BT_VS_CMD_BIT_READ_CHIP_TEMP               10
+#define BT_VS_CMD_BIT_READ_HOST_STACK_CMD          11
+#define BT_VS_CMD_BIT_SET_SCAN_REP_ENABLE          12
+#define BT_VS_CMD_BIT_WRITE_TX_POWER               13
+#define BT_VS_CMD_BIT_READ_TX_POWER                14
+
+#define BT_VS_CMD_SUP_FEAT(cmd)                 BT_LE_FEAT_TEST(cmd, \
+						BT_VS_CMD_BIT_SUP_FEAT)
+#define BT_VS_CMD_READ_STATIC_ADDRS(cmd)        BT_LE_FEAT_TEST(cmd, \
+						BT_VS_CMD_BIT_READ_STATIC_ADDRS)
+#define BT_VS_CMD_READ_KEY_ROOTS(cmd)           BT_LE_FEAT_TEST(cmd, \
+						BT_VS_CMD_BIT_READ_KEY_ROOTS)
+
+#define BT_HCI_VS_HW_PLAT_INTEL                 0x0001
+#define BT_HCI_VS_HW_PLAT_NORDIC                0x0002
+#define BT_HCI_VS_HW_PLAT_NXP                   0x0003
+
+#define BT_HCI_VS_HW_VAR_NORDIC_NRF51X          0x0001
+#define BT_HCI_VS_HW_VAR_NORDIC_NRF52X          0x0002
+#define BT_HCI_VS_HW_VAR_NORDIC_NRF53X          0x0003
+
+#define BT_HCI_VS_FW_VAR_STANDARD_CTLR          0x0001
+#define BT_HCI_VS_FW_VAR_VS_CTLR                0x0002
+#define BT_HCI_VS_FW_VAR_FW_LOADER              0x0003
+#define BT_HCI_VS_FW_VAR_RESCUE_IMG             0x0004
+#define BT_HCI_OP_VS_READ_VERSION_INFO		BT_OP(BT_OGF_VS, 0x0001)
+struct bt_hci_rp_vs_read_version_info {
+	uint8_t  status;
+	uint16_t hw_platform;
+	uint16_t hw_variant;
+	uint8_t  fw_variant;
+	uint8_t  fw_version;
+	uint16_t fw_revision;
+	uint32_t fw_build;
+} __packed;
+
+#define BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS	BT_OP(BT_OGF_VS, 0x0002)
+struct bt_hci_rp_vs_read_supported_commands {
+	uint8_t  status;
+	uint8_t  commands[64];
+} __packed;
+
+#define BT_HCI_OP_VS_READ_SUPPORTED_FEATURES	BT_OP(BT_OGF_VS, 0x0003)
+struct bt_hci_rp_vs_read_supported_features {
+	uint8_t  status;
+	uint8_t  features[8];
+} __packed;
+
+#define BT_HCI_OP_VS_SET_EVENT_MASK             BT_OP(BT_OGF_VS, 0x0004)
+struct bt_hci_cp_vs_set_event_mask {
+	uint8_t  event_mask[8];
+} __packed;
+
+#define BT_HCI_VS_RESET_SOFT                    0x00
+#define BT_HCI_VS_RESET_HARD                    0x01
+#define BT_HCI_OP_VS_RESET                      BT_OP(BT_OGF_VS, 0x0005)
+struct bt_hci_cp_vs_reset {
+	uint8_t  type;
+} __packed;
+
+#define BT_HCI_OP_VS_WRITE_BD_ADDR              BT_OP(BT_OGF_VS, 0x0006)
+struct bt_hci_cp_vs_write_bd_addr {
+	bt_addr_t bdaddr;
+} __packed;
+
+#define BT_HCI_VS_TRACE_DISABLED                0x00
+#define BT_HCI_VS_TRACE_ENABLED                 0x01
+
+#define BT_HCI_VS_TRACE_HCI_EVTS                0x00
+#define BT_HCI_VS_TRACE_VDC                     0x01
+#define BT_HCI_OP_VS_SET_TRACE_ENABLE           BT_OP(BT_OGF_VS, 0x0007)
+struct bt_hci_cp_vs_set_trace_enable {
+	uint8_t  enable;
+	uint8_t  type;
+} __packed;
+
+#define BT_HCI_OP_VS_READ_BUILD_INFO            BT_OP(BT_OGF_VS, 0x0008)
+struct bt_hci_rp_vs_read_build_info {
+	uint8_t  status;
+	uint8_t  info[0];
+} __packed;
+
+struct bt_hci_vs_static_addr {
+	bt_addr_t bdaddr;
+	uint8_t      ir[16];
+} __packed;
+
+#define BT_HCI_OP_VS_READ_STATIC_ADDRS          BT_OP(BT_OGF_VS, 0x0009)
+struct bt_hci_rp_vs_read_static_addrs {
+	uint8_t   status;
+	uint8_t   num_addrs;
+	struct bt_hci_vs_static_addr a[0];
+} __packed;
+
+#define BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS   BT_OP(BT_OGF_VS, 0x000a)
+struct bt_hci_rp_vs_read_key_hierarchy_roots {
+	uint8_t  status;
+	uint8_t  ir[16];
+	uint8_t  er[16];
+} __packed;
+
+#define BT_HCI_OP_VS_READ_CHIP_TEMP             BT_OP(BT_OGF_VS, 0x000b)
+struct bt_hci_rp_vs_read_chip_temp {
+	uint8_t  status;
+	int8_t  temps;
+} __packed;
+
+struct bt_hci_vs_cmd {
+	uint16_t vendor_id;
+	uint16_t opcode_base;
+} __packed;
+
+#define BT_HCI_VS_VID_ANDROID                   0x0001
+#define BT_HCI_VS_VID_MICROSOFT                 0x0002
+#define BT_HCI_OP_VS_READ_HOST_STACK_CMDS       BT_OP(BT_OGF_VS, 0x000c)
+struct bt_hci_rp_vs_read_host_stack_cmds {
+	uint8_t   status;
+	uint8_t   num_cmds;
+	struct bt_hci_vs_cmd c[0];
+} __packed;
+
+#define BT_HCI_VS_SCAN_REQ_REPORTS_DISABLED     0x00
+#define BT_HCI_VS_SCAN_REQ_REPORTS_ENABLED      0x01
+#define BT_HCI_OP_VS_SET_SCAN_REQ_REPORTS       BT_OP(BT_OGF_VS, 0x000d)
+struct bt_hci_cp_vs_set_scan_req_reports {
+	uint8_t  enable;
+} __packed;
+
+#define BT_HCI_VS_LL_HANDLE_TYPE_ADV       0x00
+#define BT_HCI_VS_LL_HANDLE_TYPE_SCAN      0x01
+#define BT_HCI_VS_LL_HANDLE_TYPE_CONN      0x02
+#define BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF     0x7F
+#define BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL       BT_OP(BT_OGF_VS, 0x000e)
+struct bt_hci_cp_vs_write_tx_power_level {
+	uint8_t  handle_type;
+	uint16_t handle;
+	int8_t  tx_power_level;
+} __packed;
+
+struct bt_hci_rp_vs_write_tx_power_level {
+	uint8_t  status;
+	uint8_t  handle_type;
+	uint16_t handle;
+	int8_t  selected_tx_power;
+} __packed;
+
+#define BT_HCI_OP_VS_READ_TX_POWER_LEVEL        BT_OP(BT_OGF_VS, 0x000f)
+struct bt_hci_cp_vs_read_tx_power_level {
+	uint8_t  handle_type;
+	uint16_t handle;
+} __packed;
+
+struct bt_hci_rp_vs_read_tx_power_level {
+	uint8_t  status;
+	uint8_t  handle_type;
+	uint16_t handle;
+	int8_t  tx_power_level;
+} __packed;
+
+#define BT_HCI_OP_VS_READ_USB_TRANSPORT_MODE    BT_OP(BT_OGF_VS, 0x0010)
+
+struct bt_hci_rp_vs_read_usb_transport_mode {
+	uint8_t  status;
+	uint8_t  num_supported_modes;
+	uint8_t  supported_mode[0];
+} __packed;
+
+#define BT_HCI_VS_USB_H2_MODE                  0x00
+#define BT_HCI_VS_USB_H4_MODE                  0x01
+
+#define BT_HCI_OP_VS_SET_USB_TRANSPORT_MODE    BT_OP(BT_OGF_VS, 0x0011)
+
+struct bt_hci_cp_vs_set_usb_transport_mode {
+	uint8_t  mode;
+} __packed;
+
+/* Events */
+
+struct bt_hci_evt_vs {
+	uint8_t  subevent;
+} __packed;
+
+#define BT_HCI_EVT_VS_FATAL_ERROR              0x02
+struct bt_hci_evt_vs_fatal_error {
+	uint64_t pc;
+	uint8_t  err_info[0];
+} __packed;
+
+#define BT_HCI_VS_TRACE_LMP_TX                 0x01
+#define BT_HCI_VS_TRACE_LMP_RX                 0x02
+#define BT_HCI_VS_TRACE_LLCP_TX                0x03
+#define BT_HCI_VS_TRACE_LLCP_RX                0x04
+#define BT_HCI_VS_TRACE_LE_CONN_IND            0x05
+#define BT_HCI_EVT_VS_TRACE_INFO               0x03
+struct bt_hci_evt_vs_trace_info {
+	uint8_t  type;
+	uint8_t  data[0];
+} __packed;
+
+#define BT_HCI_EVT_VS_SCAN_REQ_RX              0x04
+struct bt_hci_evt_vs_scan_req_rx {
+	bt_addr_le_t addr;
+	int8_t         rssi;
+} __packed;
+
+/* Event mask bits */
+
+#define BT_EVT_MASK_VS_FATAL_ERROR             BT_EVT_BIT(1)
+#define BT_EVT_MASK_VS_TRACE_INFO              BT_EVT_BIT(2)
+#define BT_EVT_MASK_VS_SCAN_REQ_RX             BT_EVT_BIT(3)
+
+/* Mesh HCI commands */
+#define BT_HCI_MESH_REVISION                   0x01
+
+#define BT_HCI_OP_VS_MESH                      BT_OP(BT_OGF_VS, 0x0042)
+#define BT_HCI_MESH_EVT_PREFIX                 0xF0
+
+struct bt_hci_cp_mesh {
+	uint8_t         opcode;
+} __packed;
+
+#define BT_HCI_OC_MESH_GET_OPTS                0x00
+struct bt_hci_rp_mesh_get_opts {
+	uint8_t      status;
+	uint8_t      opcode;
+	uint8_t      revision;
+	uint8_t      ch_map;
+	int8_t      min_tx_power;
+	int8_t      max_tx_power;
+	uint8_t      max_scan_filter;
+	uint8_t      max_filter_pattern;
+	uint8_t      max_adv_slot;
+	uint8_t      max_tx_window;
+	uint8_t      evt_prefix_len;
+	uint8_t      evt_prefix;
+} __packed;
+
+#define BT_HCI_MESH_PATTERN_LEN_MAX            0x0f
+
+#define BT_HCI_OC_MESH_SET_SCAN_FILTER         0x01
+struct bt_hci_mesh_pattern {
+	uint8_t pattern_len;
+	uint8_t pattern[0];
+} __packed;
+
+struct bt_hci_cp_mesh_set_scan_filter {
+	uint8_t      scan_filter;
+	uint8_t      filter_dup;
+	uint8_t      num_patterns;
+	struct    bt_hci_mesh_pattern patterns[0];
+} __packed;
+struct bt_hci_rp_mesh_set_scan_filter {
+	uint8_t      status;
+	uint8_t      opcode;
+	uint8_t      scan_filter;
+} __packed;
+
+#define BT_HCI_OC_MESH_ADVERTISE               0x02
+struct bt_hci_cp_mesh_advertise {
+	uint8_t      adv_slot;
+	uint8_t      own_addr_type;
+	bt_addr_t random_addr;
+	uint8_t      ch_map;
+	int8_t      tx_power;
+	uint8_t      min_tx_delay;
+	uint8_t      max_tx_delay;
+	uint8_t      retx_count;
+	uint8_t      retx_interval;
+	uint8_t      scan_delay;
+	uint16_t     scan_duration;
+	uint8_t      scan_filter;
+	uint8_t      data_len;
+	uint8_t      data[31];
+} __packed;
+struct bt_hci_rp_mesh_advertise {
+	uint8_t      status;
+	uint8_t      opcode;
+	uint8_t      adv_slot;
+} __packed;
+
+#define BT_HCI_OC_MESH_ADVERTISE_TIMED         0x03
+struct bt_hci_cp_mesh_advertise_timed {
+	uint8_t      adv_slot;
+	uint8_t      own_addr_type;
+	bt_addr_t random_addr;
+	uint8_t      ch_map;
+	int8_t      tx_power;
+	uint8_t      retx_count;
+	uint8_t      retx_interval;
+	uint32_t     instant;
+	uint16_t     tx_delay;
+	uint16_t     tx_window;
+	uint8_t      data_len;
+	uint8_t      data[31];
+} __packed;
+struct bt_hci_rp_mesh_advertise_timed {
+	uint8_t      status;
+	uint8_t      opcode;
+	uint8_t      adv_slot;
+} __packed;
+
+#define BT_HCI_OC_MESH_ADVERTISE_CANCEL        0x04
+struct bt_hci_cp_mesh_advertise_cancel {
+	uint8_t      adv_slot;
+} __packed;
+struct bt_hci_rp_mesh_advertise_cancel {
+	uint8_t      status;
+	uint8_t      opcode;
+	uint8_t      adv_slot;
+} __packed;
+
+#define BT_HCI_OC_MESH_SET_SCANNING            0x05
+struct bt_hci_cp_mesh_set_scanning {
+	uint8_t      enable;
+	uint8_t      ch_map;
+	uint8_t      scan_filter;
+} __packed;
+struct bt_hci_rp_mesh_set_scanning {
+	uint8_t      status;
+	uint8_t      opcode;
+} __packed;
+
+/* Events */
+struct bt_hci_evt_mesh {
+	uint8_t  prefix;
+	uint8_t  subevent;
+} __packed;
+
+#define BT_HCI_EVT_MESH_ADV_COMPLETE           0x00
+struct bt_hci_evt_mesh_adv_complete {
+	uint8_t         adv_slot;
+} __packed;
+
+#define BT_HCI_EVT_MESH_SCANNING_REPORT        0x01
+struct bt_hci_evt_mesh_scan_report {
+	bt_addr_le_t addr;
+	uint8_t         chan;
+	int8_t         rssi;
+	uint32_t        instant;
+	uint8_t         data_len;
+	uint8_t         data[0];
+} __packed;
+struct bt_hci_evt_mesh_scanning_report {
+	uint8_t num_reports;
+	struct bt_hci_evt_mesh_scan_report reports[0];
+} __packed;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_VS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/hfp_hf.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hfp_hf.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/hfp_hf.h	(working copy)
@@ -0,0 +1,172 @@
+/** @file
+ *  @brief Handsfree Profile handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HFP_HF_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_HFP_HF_H_
+
+/**
+ * @brief Hands Free Profile (HFP)
+ * @defgroup bt_hfp Hands Free Profile (HFP)
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <bluetooth/bluetooth.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* AT Commands */
+enum bt_hfp_hf_at_cmd {
+	BT_HFP_HF_ATA,
+	BT_HFP_HF_AT_CHUP,
+};
+
+/*
+ * Command complete types for the application
+ */
+#define HFP_HF_CMD_OK             0
+#define HFP_HF_CMD_ERROR          1
+#define HFP_HF_CMD_CME_ERROR      2
+#define HFP_HF_CMD_UNKNOWN_ERROR  4
+
+/** @brief HFP HF Command completion field */
+struct bt_hfp_hf_cmd_complete {
+	/* Command complete status */
+	uint8_t type;
+	/* CME error number to be added */
+	uint8_t cme;
+};
+
+/** @brief HFP profile application callback */
+struct bt_hfp_hf_cb {
+	/** HF connected callback to application
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  connection completes.
+	 *
+	 *  @param conn Connection object.
+	 */
+	void (*connected)(struct bt_conn *conn);
+	/** HF disconnected callback to application
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  connection gets disconnected, including when a connection gets
+	 *  rejected or cancelled or any error in SLC establisment.
+	 *
+	 *  @param conn Connection object.
+	 */
+	void (*disconnected)(struct bt_conn *conn);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides service indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value service indicator value received from the AG.
+	 */
+	void (*service)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides call indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value call indicator value received from the AG.
+	 */
+	void (*call)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides call setup indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value call setup indicator value received from the AG.
+	 */
+	void (*call_setup)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides call held indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value call held indicator value received from the AG.
+	 */
+	void (*call_held)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides signal indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value signal indicator value received from the AG.
+	 */
+	void (*signal)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback provides roaming indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value roaming indicator value received from the AG.
+	 */
+	void (*roam)(struct bt_conn *conn, uint32_t value);
+	/** HF indicator Callback
+	 *
+	 *  This callback battery service indicator value to the application
+	 *
+	 *  @param conn Connection object.
+	 *  @param value battery indicator value received from the AG.
+	 */
+	void (*battery)(struct bt_conn *conn, uint32_t value);
+	/** HF incoming call Ring indication callback to application
+	 *
+	 *  If this callback is provided it will be called whenever there
+	 *  is an incoming call.
+	 *
+	 *  @param conn Connection object.
+	 */
+	void (*ring_indication)(struct bt_conn *conn);
+	/** HF notify command completed callback to application
+	 *
+	 *  The command sent from the application is notified about its status
+	 *
+	 *  @param conn Connection object.
+	 *  @param cmd structure contains status of the command including cme.
+	 */
+	void (*cmd_complete_cb)(struct bt_conn *conn,
+			      struct bt_hfp_hf_cmd_complete *cmd);
+};
+
+/** @brief Register HFP HF profile
+ *
+ *  Register Handsfree profile callbacks to monitor the state and get the
+ *  required HFP details to display.
+ *
+ *  @param cb callback structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_hfp_hf_register(struct bt_hfp_hf_cb *cb);
+
+/** @brief Handsfree client Send AT
+ *
+ *  Send specific AT commands to handsfree client profile.
+ *
+ *  @param conn Connection object.
+ *  @param cmd AT command to be sent.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_hfp_hf_send_cmd(struct bt_conn *conn, enum bt_hfp_hf_at_cmd cmd);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HFP_HF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/iso.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/iso.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/iso.h	(working copy)
@@ -0,0 +1,256 @@
+/** @file
+ *  @brief Bluetooth ISO handling
+ */
+
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_
+
+/**
+ * @brief ISO
+ * @defgroup bt_iso ISO
+ * @ingroup bluetooth
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/atomic.h>
+#include <bluetooth/buf.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/hci.h>
+
+/** @def BT_ISO_CHAN_SEND_RESERVE
+ *  @brief Headroom needed for outgoing buffers
+ */
+#define BT_ISO_CHAN_SEND_RESERVE (CONFIG_BT_HCI_RESERVE + \
+				  BT_HCI_ISO_HDR_SIZE + \
+				  BT_HCI_ISO_DATA_HDR_SIZE)
+
+struct bt_iso_chan;
+
+/** @brief Life-span states of ISO channel. Used only by internal APIs
+ *  dealing with setting channel to proper state depending on operational
+ *  context.
+ */
+enum {
+	/** Channel disconnected */
+	BT_ISO_DISCONNECTED,
+	/** Channel bound to a connection */
+	BT_ISO_BOUND,
+	/** Channel in connecting state */
+	BT_ISO_CONNECT,
+	/** Channel ready for upper layer traffic on it */
+	BT_ISO_CONNECTED,
+	/** Channel in disconnecting state */
+	BT_ISO_DISCONNECT,
+};
+
+/** @brief ISO Channel structure. */
+struct bt_iso_chan {
+	/** Channel connection reference */
+	struct bt_conn			*conn;
+	/** Channel operations reference */
+	struct bt_iso_chan_ops		*ops;
+	/** Channel QoS reference */
+	struct bt_iso_chan_qos		*qos;
+	/** Channel data path reference*/
+	struct bt_iso_chan_path		*path;
+	sys_snode_t			node;
+	uint8_t				state;
+	bt_security_t			required_sec_level;
+};
+
+/** @brief Audio QoS direction */
+enum {
+	BT_ISO_CHAN_QOS_IN,
+	BT_ISO_CHAN_QOS_OUT,
+	BT_ISO_CHAN_QOS_INOUT
+};
+
+/** @brief ISO Channel QoS structure. */
+struct bt_iso_chan_qos {
+	/** @brief Channel direction
+	 *
+	 *  Possible values: BT_ISO_CHAN_QOS_IN, BT_ISO_CHAN_QOS_OUT or
+	 *  BT_ISO_CHAN_QOS_INOUT.
+	 */
+	uint8_t				dir;
+	/** Channel interval */
+	uint32_t			interval;
+	/** Channel SCA */
+	uint8_t				sca;
+	/** Channel packing mode */
+	uint8_t				packing;
+	/** Channel framing mode */
+	uint8_t				framing;
+	/** Channel Latency */
+	uint16_t			latency;
+	/** Channel SDU */
+	uint8_t				sdu;
+	/** Channel PHY */
+	uint8_t				phy;
+	/** Channel Retransmission Number */
+	uint8_t				rtn;
+};
+
+/** @brief ISO Channel Data Path structure. */
+struct bt_iso_chan_path {
+	/** Default path ID */
+	uint8_t				pid;
+	/** Coding Format */
+	uint8_t				format;
+	/** Company ID */
+	uint16_t			cid;
+	/** Vendor-defined Codec ID */
+	uint16_t			vid;
+	/** Controller Delay */
+	uint32_t			delay;
+	/** Codec Configuration length*/
+	uint8_t				cc_len;
+	/** Codec Configuration */
+	uint8_t				cc[0];
+};
+
+/** @brief ISO Channel operations structure. */
+struct bt_iso_chan_ops {
+	/** @brief Channel connected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  connection completes.
+	 *
+	 *  @param chan The channel that has been connected
+	 */
+	void (*connected)(struct bt_iso_chan *chan);
+
+	/** @brief Channel disconnected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  channel is disconnected, including when a connection gets
+	 *  rejected.
+	 *
+	 *  @param chan The channel that has been Disconnected
+	 */
+	void (*disconnected)(struct bt_iso_chan *chan);
+
+	/** @brief Channel alloc_buf callback
+	 *
+	 *  If this callback is provided the channel will use it to allocate
+	 *  buffers to store incoming data.
+	 *
+	 *  @param chan The channel requesting a buffer.
+	 *
+	 *  @return Allocated buffer.
+	 */
+	struct net_buf *(*alloc_buf)(struct bt_iso_chan *chan);
+
+	/** @brief Channel recv callback
+	 *
+	 *  @param chan The channel receiving data.
+	 *  @param buf Buffer containing incoming data.
+	 */
+	void (*recv)(struct bt_iso_chan *chan, struct net_buf *buf);
+};
+
+/** @brief ISO Server structure. */
+struct bt_iso_server {
+	/** Required minimim security level */
+	bt_security_t		sec_level;
+
+	/** @brief Server accept callback
+	 *
+	 *  This callback is called whenever a new incoming connection requires
+	 *  authorization.
+	 *
+	 *  @param conn The connection that is requesting authorization
+	 *  @param chan Pointer to receive the allocated channel
+	 *
+	 *  @return 0 in case of success or negative value in case of error.
+	 */
+	int (*accept)(struct bt_conn *conn, struct bt_iso_chan **chan);
+};
+
+/** @brief Register ISO server.
+ *
+ *  Register ISO server, each new connection is authorized using the accept()
+ *  callback which in case of success shall allocate the channel structure
+ *  to be used by the new connection.
+ *
+ *  @param server Server structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_iso_server_register(struct bt_iso_server *server);
+
+/** @brief Bind ISO channels
+ *
+ *  Bind ISO channels with existing ACL connections, Channel objects passed
+ *  (over an address of it) shouldn't be instantiated in application as
+ *  standalone.
+ *
+ *  @param conns Array of ACL connection objects
+ *  @param num_conns Number of connection objects
+ *  @param chans Array of ISO Channel objects to be created
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_iso_chan_bind(struct bt_conn **conns, uint8_t num_conns,
+		     struct bt_iso_chan **chans);
+
+/** @brief Connect ISO channels
+ *
+ *  Connect ISO channels, once the connection is completed each channel
+ *  connected() callback will be called. If the connection is rejected
+ *  disconnected() callback is called instead.
+ *  Channel object passed (over an address of it) as second parameter shouldn't
+ *  be instantiated in application as standalone.
+ *
+ *  @param chans Array of ISO channel objects
+ *  @param num_chans Number of channel objects
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_iso_chan_connect(struct bt_iso_chan **chans, uint8_t num_chans);
+
+/** @brief Disconnect ISO channel
+ *
+ *  Disconnect ISO channel, if the connection is pending it will be
+ *  canceled and as a result the channel disconnected() callback is called.
+ *  Regarding to input parameter, to get details see reference description
+ *  to bt_iso_chan_connect() API above.
+ *
+ *  @param chan Channel object.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_iso_chan_disconnect(struct bt_iso_chan *chan);
+
+/** @brief Send data to ISO channel
+ *
+ *  Send data from buffer to the channel. If credits are not available, buf will
+ *  be queued and sent as and when credits are received from peer.
+ *  Regarding to first input parameter, to get details see reference description
+ *  to bt_iso_chan_connect() API above.
+ *
+ *  @param chan Channel object.
+ *  @param buf Buffer containing data to be sent.
+ *
+ *  @return Bytes sent in case of success or negative value in case of error.
+ */
+int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/l2cap.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/l2cap.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/l2cap.h	(working copy)
@@ -0,0 +1,432 @@
+/** @file
+ *  @brief Bluetooth L2CAP handling
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_L2CAP_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_L2CAP_H_
+
+/**
+ * @brief L2CAP
+ * @defgroup bt_l2cap L2CAP
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <sys/atomic.h>
+#include <bluetooth/buf.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/hci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** L2CAP header size, used for buffer size calculations */
+#define BT_L2CAP_HDR_SIZE               4
+
+/** @def BT_L2CAP_BUF_SIZE
+ *
+ *  @brief Helper to calculate needed outgoing buffer size, useful e.g. for
+ *  creating buffer pools.
+ *
+ *  @param mtu Needed L2CAP MTU.
+ *
+ *  @return Needed buffer size to match the requested L2CAP MTU.
+ */
+#define BT_L2CAP_BUF_SIZE(mtu) (BT_BUF_RESERVE + \
+				BT_HCI_ACL_HDR_SIZE + BT_L2CAP_HDR_SIZE + \
+				(mtu))
+
+struct bt_l2cap_chan;
+
+/** @typedef bt_l2cap_chan_destroy_t
+ *  @brief Channel destroy callback
+ *
+ *  @param chan Channel object.
+ */
+typedef void (*bt_l2cap_chan_destroy_t)(struct bt_l2cap_chan *chan);
+
+/** @brief Life-span states of L2CAP CoC channel.
+ *
+ *  Used only by internal APIs dealing with setting channel to proper state
+ *  depending on operational context.
+ */
+typedef enum bt_l2cap_chan_state {
+	/** Channel disconnected */
+	BT_L2CAP_DISCONNECTED,
+	/** Channel in connecting state */
+	BT_L2CAP_CONNECT,
+	/** Channel in config state, BR/EDR specific */
+	BT_L2CAP_CONFIG,
+	/** Channel ready for upper layer traffic on it */
+	BT_L2CAP_CONNECTED,
+	/** Channel in disconnecting state */
+	BT_L2CAP_DISCONNECT,
+
+} __packed bt_l2cap_chan_state_t;
+
+/** @brief Status of L2CAP channel. */
+typedef enum bt_l2cap_chan_status {
+	/** Channel output status */
+	BT_L2CAP_STATUS_OUT,
+
+	/** @brief Channel shutdown status
+	 *
+	 * Once this status is notified it means the channel will no longer be
+	 * able to transmit or receive data.
+	 */
+	BT_L2CAP_STATUS_SHUTDOWN,
+
+	/** @brief Channel encryption pending status */
+	BT_L2CAP_STATUS_ENCRYPT_PENDING,
+
+	/* Total number of status - must be at the end of the enum */
+	BT_L2CAP_NUM_STATUS,
+} __packed bt_l2cap_chan_status_t;
+
+/** @brief L2CAP Channel structure. */
+struct bt_l2cap_chan {
+	/** Channel connection reference */
+	struct bt_conn			*conn;
+	/** Channel operations reference */
+	const struct bt_l2cap_chan_ops	*ops;
+	sys_snode_t			node;
+	bt_l2cap_chan_destroy_t		destroy;
+	/* Response Timeout eXpired (RTX) timer */
+	//struct k_delayed_work		rtx_work;
+	ATOMIC_DEFINE(status, BT_L2CAP_NUM_STATUS);
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	bt_l2cap_chan_state_t		state;
+	/** Remote PSM to be connected */
+	uint16_t				psm;
+	/** Helps match request context during CoC */
+	uint8_t				ident;
+	bt_security_t			required_sec_level;
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+};
+
+/** @brief LE L2CAP Endpoint structure. */
+struct bt_l2cap_le_endpoint {
+	/** Endpoint CID */
+	uint16_t				cid;
+	/** Endpoint Maximum Transmission Unit */
+	uint16_t				mtu;
+	/** Endpoint Maximum PDU payload Size */
+	uint16_t				mps;
+	/** Endpoint initial credits */
+	uint16_t				init_credits;
+	/** Endpoint credits */
+	atomic_t			credits;
+};
+
+/** @brief LE L2CAP Channel structure. */
+struct bt_l2cap_le_chan {
+	/** Common L2CAP channel reference object */
+	struct bt_l2cap_chan		chan;
+	/** Channel Receiving Endpoint */
+	struct bt_l2cap_le_endpoint	rx;
+	/** Channel Transmission Endpoint */
+	struct bt_l2cap_le_endpoint	tx;
+	/** Channel Transmission queue */
+	struct k_fifo                   tx_queue;
+	/** Channel Pending Transmission buffer  */
+	struct net_buf                  *tx_buf;
+	/** Channel Transmission work  */
+	//struct k_work			tx_work;
+	/** Segment SDU packet from upper layer */
+	struct net_buf			*_sdu;
+	uint16_t				_sdu_len;
+
+	//struct k_work			rx_work;
+	struct k_fifo			rx_queue;
+};
+
+/** @def BT_L2CAP_LE_CHAN(_ch)
+ *  @brief Helper macro getting container object of type bt_l2cap_le_chan
+ *  address having the same container chan member address as object in question.
+ *
+ *  @param _ch Address of object of bt_l2cap_chan type
+ *
+ *  @return Address of in memory bt_l2cap_le_chan object type containing
+ *          the address of in question object.
+ */
+#define BT_L2CAP_LE_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_le_chan, chan)
+
+/** @brief BREDR L2CAP Endpoint structure. */
+struct bt_l2cap_br_endpoint {
+	/** Endpoint CID */
+	uint16_t				cid;
+	/** Endpoint Maximum Transmission Unit */
+	uint16_t				mtu;
+};
+
+/** @brief BREDR L2CAP Channel structure. */
+struct bt_l2cap_br_chan {
+	/** Common L2CAP channel reference object */
+	struct bt_l2cap_chan		chan;
+	/** Channel Receiving Endpoint */
+	struct bt_l2cap_br_endpoint	rx;
+	/** Channel Transmission Endpoint */
+	struct bt_l2cap_br_endpoint	tx;
+	/* For internal use only */
+	atomic_t			flags[1];
+};
+
+/** @brief L2CAP Channel operations structure. */
+struct bt_l2cap_chan_ops {
+	/** @brief Channel connected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  connection completes.
+	 *
+	 *  @param chan The channel that has been connected
+	 */
+	void (*connected)(struct bt_l2cap_chan *chan);
+
+	/** @brief Channel disconnected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  channel is disconnected, including when a connection gets
+	 *  rejected.
+	 *
+	 *  @param chan The channel that has been Disconnected
+	 */
+	void (*disconnected)(struct bt_l2cap_chan *chan);
+
+	/** @brief Channel encrypt_change callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  security level changed (indirectly link encryption done) or
+	 *  authentication procedure fails. In both cases security initiator
+	 *  and responder got the final status (HCI status) passed by
+	 *  related to encryption and authentication events from local host's
+	 *  controller.
+	 *
+	 *  @param chan The channel which has made encryption status changed.
+	 *  @param status HCI status of performed security procedure caused
+	 *  by channel security requirements. The value is populated
+	 *  by HCI layer and set to 0 when success and to non-zero (reference to
+	 *  HCI Error Codes) when security/authentication failed.
+	 */
+	void (*encrypt_change)(struct bt_l2cap_chan *chan, uint8_t hci_status);
+
+	/** @brief Channel alloc_buf callback
+	 *
+	 *  If this callback is provided the channel will use it to allocate
+	 *  buffers to store incoming data. Channels that requires segmentation
+	 *  must set this callback.
+	 *
+	 *  @param chan The channel requesting a buffer.
+	 *
+	 *  @return Allocated buffer.
+	 */
+	struct net_buf *(*alloc_buf)(struct bt_l2cap_chan *chan);
+
+	/** @brief Channel recv callback
+	 *
+	 *  @param chan The channel receiving data.
+	 *  @param buf Buffer containing incoming data.
+	 *
+	 *  @return 0 in case of success or negative value in case of error.
+	 *  @return -EINPROGRESS in case where user has to confirm once the data
+	 *                       has been processed by calling
+	 *                       @ref bt_l2cap_chan_recv_complete passing back
+	 *                       the buffer received with its original user_data
+	 *                       which contains the number of segments/credits
+	 *                       used by the packet.
+	 */
+	int (*recv)(struct bt_l2cap_chan *chan, struct net_buf *buf);
+
+	/** @brief Channel sent callback
+	 *
+	 *  If this callback is provided it will be called whenever a SDU has
+	 *  been completely sent.
+	 *
+	 *  @param chan The channel which has sent data.
+	 */
+	void (*sent)(struct bt_l2cap_chan *chan);
+
+	/** @brief Channel status callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  channel status changes.
+	 *
+	 *  @param chan The channel which status changed
+	 *  @param status The channel status
+	 */
+	void (*status)(struct bt_l2cap_chan *chan, atomic_t *status);
+
+	/* @brief Channel released callback
+	 *
+	 * If this callback is set it is called when the stack has release all
+	 * references to the channel object.
+	 */
+	void (*released)(struct bt_l2cap_chan *chan);
+};
+
+/** @def BT_L2CAP_CHAN_SEND_RESERVE
+ *  @brief Headroom needed for outgoing buffers
+ */
+#define BT_L2CAP_CHAN_SEND_RESERVE (BT_BUF_RESERVE + 4 + 4)
+
+/** @brief L2CAP Server structure. */
+struct bt_l2cap_server {
+	/** @brief Server PSM.
+	 *
+	 *  Possible values:
+	 *  0               A dynamic value will be auto-allocated when
+	 *                  bt_l2cap_server_register() is called.
+	 *
+	 *  0x0001-0x007f   Standard, Bluetooth SIG-assigned fixed values.
+	 *
+	 *  0x0080-0x00ff   Dynamically allocated. May be pre-set by the
+	 *                  application before server registration (not
+	 *                  recommended however), or auto-allocated by the
+	 *                  stack if the app gave 0 as the value.
+	 */
+	uint16_t			psm;
+
+	/** Required minimim security level */
+	bt_security_t		sec_level;
+
+	/** @brief Server accept callback
+	 *
+	 *  This callback is called whenever a new incoming connection requires
+	 *  authorization.
+	 *
+	 *  @param conn The connection that is requesting authorization
+	 *  @param chan Pointer to received the allocated channel
+	 *
+	 *  @return 0 in case of success or negative value in case of error.
+	 *  @return -ENOMEM if no available space for new channel.
+	 *  @return -EACCES if application did not authorize the connection.
+	 *  @return -EPERM if encryption key size is too short.
+	 */
+	int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
+
+	sys_snode_t node;
+};
+
+/** @brief Register L2CAP server.
+ *
+ *  Register L2CAP server for a PSM, each new connection is authorized using
+ *  the accept() callback which in case of success shall allocate the channel
+ *  structure to be used by the new connection.
+ *
+ *  For fixed, SIG-assigned PSMs (in the range 0x0001-0x007f) the PSM should
+ *  be assigned to server->psm before calling this API. For dynamic PSMs
+ *  (in the range 0x0080-0x00ff) server->psm may be pre-set to a given value
+ *  (this is however not recommended) or be left as 0, in which case upon
+ *  return a newly allocated value will have been assigned to it. For
+ *  dynamically allocated values the expectation is that it's exposed through
+ *  a GATT service, and that's how L2CAP clients discover how to connect to
+ *  the server.
+ *
+ *  @param server Server structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_server_register(struct bt_l2cap_server *server);
+
+/** @brief Register L2CAP server on BR/EDR oriented connection.
+ *
+ *  Register L2CAP server for a PSM, each new connection is authorized using
+ *  the accept() callback which in case of success shall allocate the channel
+ *  structure to be used by the new connection.
+ *
+ *  @param server Server structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_br_server_register(struct bt_l2cap_server *server);
+
+/** @brief Connect Enhanced Credit Based L2CAP channels
+ *
+ *  Connect up to 5 L2CAP channels by PSM, once the connection is completed
+ *  each channel connected() callback will be called. If the connection is
+ *  rejected disconnected() callback is called instead.
+ *
+ *  @param conn Connection object.
+ *  @param chans Array of channel objects.
+ *  @param psm Channel PSM to connect to.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_ecred_chan_connect(struct bt_conn *conn,
+				struct bt_l2cap_chan **chans, uint16_t psm);
+
+/** @brief Connect L2CAP channel
+ *
+ *  Connect L2CAP channel by PSM, once the connection is completed channel
+ *  connected() callback will be called. If the connection is rejected
+ *  disconnected() callback is called instead.
+ *  Channel object passed (over an address of it) as second parameter shouldn't
+ *  be instantiated in application as standalone. Instead of, application should
+ *  create transport dedicated L2CAP objects, i.e. type of bt_l2cap_le_chan for
+ *  LE and/or type of bt_l2cap_br_chan for BR/EDR. Then pass to this API
+ *  the location (address) of bt_l2cap_chan type object which is a member
+ *  of both transport dedicated objects.
+ *
+ *  @param conn Connection object.
+ *  @param chan Channel object.
+ *  @param psm Channel PSM to connect to.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			  uint16_t psm);
+
+/** @brief Disconnect L2CAP channel
+ *
+ *  Disconnect L2CAP channel, if the connection is pending it will be
+ *  canceled and as a result the channel disconnected() callback is called.
+ *  Regarding to input parameter, to get details see reference description
+ *  to bt_l2cap_chan_connect() API above.
+ *
+ *  @param chan Channel object.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan);
+
+/** @brief Send data to L2CAP channel
+ *
+ *  Send data from buffer to the channel. If credits are not available, buf will
+ *  be queued and sent as and when credits are received from peer.
+ *  Regarding to first input parameter, to get details see reference description
+ *  to bt_l2cap_chan_connect() API above.
+ *
+ *  @return Bytes sent in case of success or negative value in case of error.
+ */
+int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
+
+/** @brief Complete receiving L2CAP channel data
+ *
+ * Complete the reception of incoming data. This shall only be called if the
+ * channel recv callback has returned -EINPROGRESS to process some incoming
+ * data. The buffer shall contain the original user_data as that is used for
+ * storing the credits/segments used by the packet.
+ *
+ * @param chan Channel object.
+ * @param buf Buffer containing the data.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_l2cap_chan_recv_complete(struct bt_l2cap_chan *chan,
+				struct net_buf *buf);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_L2CAP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh.h	(working copy)
@@ -0,0 +1,26 @@
+/** @file
+ *  @brief Bluetooth Mesh Profile APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_H_
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <net/buf.h>
+
+#include <bluetooth/mesh/access.h>
+#include <bluetooth/mesh/main.h>
+#include <bluetooth/mesh/cfg_srv.h>
+#include <bluetooth/mesh/health_srv.h>
+#include <bluetooth/mesh/cfg_cli.h>
+#include <bluetooth/mesh/health_cli.h>
+#include <bluetooth/mesh/proxy.h>
+#include <bluetooth/mesh/cdb.h>
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/access.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/access.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/access.h	(working copy)
@@ -0,0 +1,728 @@
+/** @file
+ *  @brief Bluetooth Mesh Access Layer APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_ACCESS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_ACCESS_H_
+
+#include <settings/settings.h>
+#include <sys/util.h>
+
+/* Internal macros used to initialize array members */
+#define BT_MESH_KEY_UNUSED_ELT_(IDX, _) BT_MESH_KEY_UNUSED,
+#define BT_MESH_ADDR_UNASSIGNED_ELT_(IDX, _) BT_MESH_ADDR_UNASSIGNED,
+#define BT_MESH_MODEL_KEYS_UNUSED			\
+	{ UTIL_LISTIFY(CONFIG_BT_MESH_MODEL_KEY_COUNT,	\
+		       BT_MESH_KEY_UNUSED_ELT_) }
+#define BT_MESH_MODEL_GROUPS_UNASSIGNED				\
+	{ UTIL_LISTIFY(CONFIG_BT_MESH_MODEL_GROUP_COUNT,	\
+		       BT_MESH_ADDR_UNASSIGNED_ELT_) }
+
+/**
+ * @brief Bluetooth Mesh Access Layer
+ * @defgroup bt_mesh_access Bluetooth Mesh Access Layer
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BT_MESH_ADDR_UNASSIGNED   0x0000
+#define BT_MESH_ADDR_ALL_NODES    0xffff
+#define BT_MESH_ADDR_PROXIES      0xfffc
+#define BT_MESH_ADDR_FRIENDS      0xfffd
+#define BT_MESH_ADDR_RELAYS       0xfffe
+
+#define BT_MESH_KEY_UNUSED        0xffff
+#define BT_MESH_KEY_DEV           0xfffe
+#define BT_MESH_KEY_DEV_LOCAL     BT_MESH_KEY_DEV
+#define BT_MESH_KEY_DEV_REMOTE    0xfffd
+#define BT_MESH_KEY_DEV_ANY       0xfffc
+
+#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
+				 key == BT_MESH_KEY_DEV_REMOTE)
+
+/** Helper to define a mesh element within an array.
+ *
+ *  In case the element has no SIG or Vendor models the helper
+ *  macro BT_MESH_MODEL_NONE can be given instead.
+ *
+ *  @param _loc       Location Descriptor.
+ *  @param _mods      Array of models.
+ *  @param _vnd_mods  Array of vendor models.
+ */
+#define BT_MESH_ELEM(_loc, _mods, _vnd_mods)        \
+{                                                   \
+	.loc              = (_loc),                 \
+	.model_count      = ARRAY_SIZE(_mods),      \
+	.vnd_model_count  = ARRAY_SIZE(_vnd_mods),  \
+	.models           = (_mods),                \
+	.vnd_models       = (_vnd_mods),            \
+}
+
+/** Abstraction that describes a Mesh Element */
+struct bt_mesh_elem {
+	/** Unicast Address. Set at runtime during provisioning. */
+	uint16_t addr;
+
+	/** Location Descriptor (GATT Bluetooth Namespace Descriptors) */
+	const uint16_t loc;
+	/** The number of SIG models in this element */
+	const uint8_t model_count;
+	/** The number of vendor models in this element */
+	const uint8_t vnd_model_count;
+
+	/** The list of SIG models in this element */
+	struct bt_mesh_model * const models;
+	/** The list of vendor models in this element */
+	struct bt_mesh_model * const vnd_models;
+};
+
+/* Foundation Models */
+#define BT_MESH_MODEL_ID_CFG_SRV                   0x0000
+#define BT_MESH_MODEL_ID_CFG_CLI                   0x0001
+#define BT_MESH_MODEL_ID_HEALTH_SRV                0x0002
+#define BT_MESH_MODEL_ID_HEALTH_CLI                0x0003
+
+/* Models from the Mesh Model Specification */
+#define BT_MESH_MODEL_ID_GEN_ONOFF_SRV             0x1000
+#define BT_MESH_MODEL_ID_GEN_ONOFF_CLI             0x1001
+#define BT_MESH_MODEL_ID_GEN_LEVEL_SRV             0x1002
+#define BT_MESH_MODEL_ID_GEN_LEVEL_CLI             0x1003
+#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV    0x1004
+#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI    0x1005
+#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV       0x1006
+#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV 0x1007
+#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI       0x1008
+#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV       0x1009
+#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV 0x100a
+#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI       0x100b
+#define BT_MESH_MODEL_ID_GEN_BATTERY_SRV           0x100c
+#define BT_MESH_MODEL_ID_GEN_BATTERY_CLI           0x100d
+#define BT_MESH_MODEL_ID_GEN_LOCATION_SRV          0x100e
+#define BT_MESH_MODEL_ID_GEN_LOCATION_SETUPSRV     0x100f
+#define BT_MESH_MODEL_ID_GEN_LOCATION_CLI          0x1010
+#define BT_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV        0x1011
+#define BT_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV 0x1012
+#define BT_MESH_MODEL_ID_GEN_USER_PROP_SRV         0x1013
+#define BT_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV       0x1014
+#define BT_MESH_MODEL_ID_GEN_PROP_CLI              0x1015
+#define BT_MESH_MODEL_ID_SENSOR_SRV                0x1100
+#define BT_MESH_MODEL_ID_SENSOR_SETUP_SRV          0x1101
+#define BT_MESH_MODEL_ID_SENSOR_CLI                0x1102
+#define BT_MESH_MODEL_ID_TIME_SRV                  0x1200
+#define BT_MESH_MODEL_ID_TIME_SETUP_SRV            0x1201
+#define BT_MESH_MODEL_ID_TIME_CLI                  0x1202
+#define BT_MESH_MODEL_ID_SCENE_SRV                 0x1203
+#define BT_MESH_MODEL_ID_SCENE_SETUP_SRV           0x1204
+#define BT_MESH_MODEL_ID_SCENE_CLI                 0x1205
+#define BT_MESH_MODEL_ID_SCHEDULER_SRV             0x1206
+#define BT_MESH_MODEL_ID_SCHEDULER_SETUP_SRV       0x1207
+#define BT_MESH_MODEL_ID_SCHEDULER_CLI             0x1208
+#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV       0x1300
+#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV 0x1301
+#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI       0x1302
+#define BT_MESH_MODEL_ID_LIGHT_CTL_SRV             0x1303
+#define BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV       0x1304
+#define BT_MESH_MODEL_ID_LIGHT_CTL_CLI             0x1305
+#define BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV        0x1306
+#define BT_MESH_MODEL_ID_LIGHT_HSL_SRV             0x1307
+#define BT_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV       0x1308
+#define BT_MESH_MODEL_ID_LIGHT_HSL_CLI             0x1309
+#define BT_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV         0x130a
+#define BT_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV         0x130b
+#define BT_MESH_MODEL_ID_LIGHT_XYL_SRV             0x130c
+#define BT_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV       0x130d
+#define BT_MESH_MODEL_ID_LIGHT_XYL_CLI             0x130e
+#define BT_MESH_MODEL_ID_LIGHT_LC_SRV              0x130f
+#define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV         0x1310
+#define BT_MESH_MODEL_ID_LIGHT_LC_CLI              0x1311
+
+/** Message sending context. */
+struct bt_mesh_msg_ctx {
+	/** NetKey Index of the subnet to send the message on. */
+	uint16_t net_idx;
+
+	/** AppKey Index to encrypt the message with. */
+	uint16_t app_idx;
+
+	/** Remote address. */
+	uint16_t addr;
+
+	/** Destination address of a received message. Not used for sending. */
+	uint16_t recv_dst;
+
+	/** RSSI of received packet. Not used for sending. */
+	int8_t  recv_rssi;
+
+	/** Received TTL value. Not used for sending. */
+	uint8_t  recv_ttl;
+
+	/** Force sending reliably by using segment acknowledgement */
+	bool  send_rel;
+
+	/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
+	uint8_t  send_ttl;
+};
+
+/** Model opcode handler. */
+struct bt_mesh_model_op {
+	/** OpCode encoded using the BT_MESH_MODEL_OP_* macros */
+	const uint32_t  opcode;
+
+	/** Minimum required message length */
+	const size_t min_len;
+
+	/** @brief Handler function for this opcode.
+	 *
+	 *  @param model Model instance receiving the message.
+	 *  @param ctx   Message context for the message.
+	 *  @param buf   Message buffer containing the message payload, not
+	 *               including the opcode.
+	 */
+	void (*const func)(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf);
+};
+
+#define BT_MESH_MODEL_OP_1(b0) (b0)
+#define BT_MESH_MODEL_OP_2(b0, b1) (((b0) << 8) | (b1))
+#define BT_MESH_MODEL_OP_3(b0, cid) ((((b0) << 16) | 0xc00000) | (cid))
+
+/** End of the opcode list. Must always be present. */
+#define BT_MESH_MODEL_OP_END { 0, 0, NULL }
+/** Helper to define an empty opcode list. */
+#define BT_MESH_MODEL_NO_OPS ((struct bt_mesh_model_op []) \
+			      { BT_MESH_MODEL_OP_END })
+
+/** Helper to define an empty model array */
+#define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){})
+
+/** Length of a short Mesh MIC. */
+#define BT_MESH_MIC_SHORT 4
+/** Length of a long Mesh MIC. */
+#define BT_MESH_MIC_LONG 8
+
+/** @def BT_MESH_MODEL_OP_LEN
+ *
+ *  @brief Helper to determine the length of an opcode.
+ *
+ *  @param _op Opcode.
+ */
+#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
+
+/** @def BT_MESH_MODEL_BUF_LEN
+ *
+ *  @brief Helper for model message buffer length.
+ *
+ *  Returns the length of a Mesh model message buffer, including the opcode
+ *  length and a short MIC.
+ *
+ *  @param _op          Opcode of the message.
+ *  @param _payload_len Length of the model payload.
+ */
+#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len)                               \
+	(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT)
+
+/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC
+ *
+ *  @brief Helper for model message buffer length.
+ *
+ *  Returns the length of a Mesh model message buffer, including the opcode
+ *  length and a long MIC.
+ *
+ *  @param _op          Opcode of the message.
+ *  @param _payload_len Length of the model payload.
+ */
+#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len)                      \
+	(BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG)
+
+/** @def BT_MESH_MODEL_BUF_DEFINE
+ *
+ *  @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE.
+ *
+ *  @param _buf         Buffer name.
+ *  @param _op          Opcode of the message.
+ *  @param _payload_len Length of the model message payload.
+ */
+#define BT_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len)                      \
+	NET_BUF_SIMPLE_DEFINE(_buf, BT_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
+
+/** @def BT_MESH_MODEL_CB
+ *
+ *  @brief Composition data SIG model entry with callback functions.
+ *
+ *  @param _id        Model ID.
+ *  @param _op        Array of model opcode handlers.
+ *  @param _pub       Model publish parameters.
+ *  @param _user_data User data for the model.
+ *  @param _cb        Callback structure, or NULL to keep no callbacks.
+ */
+#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb)                    \
+{                                                                            \
+	.id = (_id),                                                         \
+	.pub = _pub,                                                         \
+	.keys = BT_MESH_MODEL_KEYS_UNUSED,                                   \
+	.groups = BT_MESH_MODEL_GROUPS_UNASSIGNED,                           \
+	.op = _op,                                                           \
+	.cb = _cb,                                                           \
+	.user_data = _user_data,                                             \
+}
+
+/** @def BT_MESH_MODEL_VND_CB
+ *
+ *  @brief Composition data vendor model entry with callback functions.
+ *
+ *  @param _company   Company ID.
+ *  @param _id        Model ID.
+ *  @param _op        Array of model opcode handlers.
+ *  @param _pub       Model publish parameters.
+ *  @param _user_data User data for the model.
+ *  @param _cb        Callback structure, or NULL to keep no callbacks.
+ */
+#define BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb)      \
+{                                                                            \
+	.vnd.company = (_company),                                           \
+	.vnd.id = (_id),                                                     \
+	.op = _op,                                                           \
+	.pub = _pub,                                                         \
+	.keys = BT_MESH_MODEL_KEYS_UNUSED,                                   \
+	.groups = BT_MESH_MODEL_GROUPS_UNASSIGNED,                           \
+	.user_data = _user_data,                                             \
+	.cb = _cb,                                                           \
+}
+
+
+/** @def BT_MESH_MODEL
+ *
+ *  @brief Composition data SIG model entry.
+ *
+ *  @param _id        Model ID.
+ *  @param _op        Array of model opcode handlers.
+ *  @param _pub       Model publish parameters.
+ *  @param _user_data User data for the model.
+ */
+#define BT_MESH_MODEL(_id, _op, _pub, _user_data)                              \
+	BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, NULL)
+
+/** @def BT_MESH_MODEL_VND
+ *
+ *  @brief Composition data vendor model entry.
+ *
+ *  @param _company   Company ID.
+ *  @param _id        Model ID.
+ *  @param _op        Array of model opcode handlers.
+ *  @param _pub       Model publish parameters.
+ *  @param _user_data User data for the model.
+ */
+#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data)                \
+	BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, NULL)
+
+/** @def BT_MESH_TRANSMIT
+ *
+ *  @brief Encode transmission count & interval steps.
+ *
+ *  @param count   Number of retransmissions (first transmission is excluded).
+ *  @param int_ms  Interval steps in milliseconds. Must be greater than 0,
+ *                 less than or equal to 320, and a multiple of 10.
+ *
+ *  @return Mesh transmit value that can be used e.g. for the default
+ *          values of the configuration model data.
+ */
+#define BT_MESH_TRANSMIT(count, int_ms) ((count) | (((int_ms / 10) - 1) << 3))
+
+/** @def BT_MESH_TRANSMIT_COUNT
+ *
+ *  @brief Decode transmit count from a transmit value.
+ *
+ *  @param transmit Encoded transmit count & interval value.
+ *
+ *  @return Transmission count (actual transmissions is N + 1).
+ */
+#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
+
+/** @def BT_MESH_TRANSMIT_INT
+ *
+ *  @brief Decode transmit interval from a transmit value.
+ *
+ *  @param transmit Encoded transmit count & interval value.
+ *
+ *  @return Transmission interval in milliseconds.
+ */
+#define BT_MESH_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 10)
+
+/** @def BT_MESH_PUB_TRANSMIT
+ *
+ *  @brief Encode Publish Retransmit count & interval steps.
+ *
+ *  @param count  Number of retransmissions (first transmission is excluded).
+ *  @param int_ms Interval steps in milliseconds. Must be greater than 0 and a
+ *                multiple of 50.
+ *
+ *  @return Mesh transmit value that can be used e.g. for the default
+ *          values of the configuration model data.
+ */
+#define BT_MESH_PUB_TRANSMIT(count, int_ms) BT_MESH_TRANSMIT(count,           \
+							     (int_ms) / 5)
+
+/** @def BT_MESH_PUB_TRANSMIT_COUNT
+ *
+ *  @brief Decode Publish Retransmit count from a given value.
+ *
+ *  @param transmit Encoded Publish Retransmit count & interval value.
+ *
+ *  @return Retransmission count (actual transmissions is N + 1).
+ */
+#define BT_MESH_PUB_TRANSMIT_COUNT(transmit) BT_MESH_TRANSMIT_COUNT(transmit)
+
+/** @def BT_MESH_PUB_TRANSMIT_INT
+ *
+ *  @brief Decode Publish Retransmit interval from a given value.
+ *
+ *  @param transmit Encoded Publish Retransmit count & interval value.
+ *
+ *  @return Transmission interval in milliseconds.
+ */
+#define BT_MESH_PUB_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 50)
+
+/** Model publication context.
+ *
+ *  The context should primarily be created using the
+ *  BT_MESH_MODEL_PUB_DEFINE macro.
+ */
+struct bt_mesh_model_pub {
+	/** The model the context belongs to. Initialized by the stack. */
+	struct bt_mesh_model *mod;
+
+	uint16_t addr;         /**< Publish Address. */
+	uint16_t key:12,       /**< Publish AppKey Index. */
+	      cred:1,       /**< Friendship Credentials Flag. */
+	      send_rel:1;   /**< Force reliable sending (segment acks) */
+
+	uint8_t  ttl;          /**< Publish Time to Live. */
+	uint8_t  retransmit;   /**< Retransmit Count & Interval Steps. */
+	uint8_t  period;       /**< Publish Period. */
+	uint8_t  period_div:4, /**< Divisor for the Period. */
+	      fast_period:1,/**< Use FastPeriodDivisor */
+	      count:3;      /**< Retransmissions left. */
+
+	uint32_t period_start; /**< Start of the current period. */
+
+	/** @brief Publication buffer, containing the publication message.
+	 *
+	 *  This will get correctly created when the publication context
+	 *  has been defined using the BT_MESH_MODEL_PUB_DEFINE macro.
+	 *
+	 *	BT_MESH_MODEL_PUB_DEFINE(name, update, size);
+	 */
+	struct net_buf_simple *msg;
+
+	/** @brief Callback for updating the publication buffer.
+	 *
+	 *  When set to NULL, the model is assumed not to support
+	 *  periodic publishing. When set to non-NULL the callback
+	 *  will be called periodically and is expected to update
+	 *  @ref bt_mesh_model_pub.msg with a valid publication
+	 *  message.
+	 *
+	 *  If the callback returns non-zero, the publication is skipped
+	 *  and will resume on the next periodic publishing interval.
+	 *
+	 *  @param mod The Model the Publication Context belogs to.
+	 *
+	 *  @return Zero on success or (negative) error code otherwise.
+	 */
+	int (*update)(struct bt_mesh_model *mod);
+
+	/** Publish Period Timer. Only for stack-internal use. */
+	struct k_delayed_work timer;
+};
+
+/** @def BT_MESH_MODEL_PUB_DEFINE
+ *
+ *  Define a model publication context.
+ *
+ *  @param _name Variable name given to the context.
+ *  @param _update Optional message update callback (may be NULL).
+ *  @param _msg_len Length of the publication message.
+ */
+#define BT_MESH_MODEL_PUB_DEFINE(_name, _update, _msg_len) \
+	NET_BUF_SIMPLE_DEFINE_STATIC(bt_mesh_pub_msg_##_name, _msg_len); \
+	static struct bt_mesh_model_pub _name = { \
+		.msg = &bt_mesh_pub_msg_##_name, \
+		.update = _update, \
+	}
+
+/** Model callback functions. */
+struct bt_mesh_model_cb {
+	/** @brief Set value handler of user data tied to the model.
+	 *
+	 *  @sa settings_handler::h_set
+	 *
+	 *  @param model   Model to set the persistent data of.
+	 *  @param name    Name/key of the settings item.
+	 *  @param len_rd  The size of the data found in the backend.
+	 *  @param read_cb Function provided to read the data from the backend.
+	 *  @param cb_arg  Arguments for the read function provided by the
+	 *                 backend.
+	 *
+	 *  @return 0 on success, error otherwise.
+	 */
+	int (*const settings_set)(struct bt_mesh_model *model,
+				  const char *name, size_t len_rd,
+				  settings_read_cb read_cb, void *cb_arg);
+
+	/** @brief Callback called when the mesh is started.
+	 *
+	 *  This handler gets called after the node has been provisioned, or
+	 *  after all mesh data has been loaded from persistent storage.
+	 *
+	 *  When this callback fires, the mesh model may start its behavior,
+	 *  and all Access APIs are ready for use.
+	 *
+	 *  @param model      Model this callback belongs to.
+	 *
+	 *  @return 0 on success, error otherwise.
+	 */
+	int (*const start)(struct bt_mesh_model *model);
+
+	/** @brief Model init callback.
+	 *
+	 *  Called on every model instance during mesh initialization.
+	 *
+	 *  If any of the model init callbacks return an error, the Mesh
+	 *  subsystem initialization will be aborted, and the error will be
+	 *  returned to the caller of @ref bt_mesh_init.
+	 *
+	 *  @param model Model to be initialized.
+	 *
+	 *  @return 0 on success, error otherwise.
+	 */
+	int (*const init)(struct bt_mesh_model *model);
+
+	/** @brief Model reset callback.
+	 *
+	 *  Called when the mesh node is reset. All model data is deleted on
+	 *  reset, and the model should clear its state.
+	 *
+	 *  @note If the model stores any persistent data, this needs to be
+	 *  erased manually.
+	 *
+	 *  @param model Model this callback belongs to.
+	 */
+	void (*const reset)(struct bt_mesh_model *model);
+};
+
+/** Abstraction that describes a Mesh Model instance */
+struct bt_mesh_model {
+	union {
+		/** SIG model ID */
+		const uint16_t id;
+		/** Vendor model ID */
+		struct {
+			uint16_t company; /**< Vendor's company ID */
+			uint16_t id;      /**< Model ID */
+		} vnd;
+	};
+
+	/* Internal information, mainly for persistent storage */
+	uint8_t  elem_idx;   /* Belongs to Nth element */
+	uint8_t  mod_idx;    /* Is the Nth model in the element */
+	uint16_t flags;      /* Model flags for internal bookkeeping */
+
+	/** Model Publication */
+	struct bt_mesh_model_pub * const pub;
+
+	/** AppKey List */
+	uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+
+	/** Subscription List (group or virtual addresses) */
+	uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+
+	/** Opcode handler list */
+	const struct bt_mesh_model_op * const op;
+
+	/** Model callback structure. */
+	const struct bt_mesh_model_cb * const cb;
+
+#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
+	/* Pointer to the next model in a model extension tree. */
+	struct bt_mesh_model *next;
+	/* Pointer to the first model this model extends. */
+	struct bt_mesh_model *extends;
+#endif
+	/** Model-specific user data */
+	void *user_data;
+};
+
+/** Callback structure for monitoring model message sending */
+struct bt_mesh_send_cb {
+	/** @brief Handler called at the start of the transmission.
+	 *
+	 *  @param duration The duration of the full transmission.
+	 *  @param err      Error occurring during sending.
+	 *  @param cb_data  Callback data, as passed to the send API.
+	 */
+	void (*start)(uint16_t duration, int err, void *cb_data);
+	/** @brief Handler called at the end of the transmission.
+	 *
+	 *  @param err     Error occurring during sending.
+	 *  @param cb_data Callback data, as passed to the send API.
+	 */
+	void (*end)(int err, void *cb_data);
+};
+
+
+/** @brief Initialize a model message.
+ *
+ *  Clears the message buffer contents, and encodes the given opcode.
+ *  The message buffer will be ready for filling in payload data.
+ *
+ *  @param msg    Message buffer.
+ *  @param opcode Opcode to encode.
+ */
+void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode);
+
+/** Special TTL value to request using configured default TTL */
+#define BT_MESH_TTL_DEFAULT 0xff
+
+/** Maximum allowed TTL value */
+#define BT_MESH_TTL_MAX     0x7f
+
+/** @brief Send an Access Layer message.
+ *
+ *  @param model   Mesh (client) Model that the message belongs to.
+ *  @param ctx     Message context, includes keys, TTL, etc.
+ *  @param msg     Access Layer payload (the actual message to be sent).
+ *  @param cb      Optional "message sent" callback.
+ *  @param cb_data User data to be passed to the callback.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_model_send(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *msg,
+		       const struct bt_mesh_send_cb *cb,
+		       void *cb_data);
+
+/** @brief Send a model publication message.
+ *
+ *  Before calling this function, the user needs to ensure that the model
+ *  publication message (@ref bt_mesh_model_pub.msg) contains a valid
+ *  message to be sent. Note that this API is only to be used for
+ *  non-period publishing. For periodic publishing the app only needs
+ *  to make sure that @ref bt_mesh_model_pub.msg contains a valid message
+ *  whenever the @ref bt_mesh_model_pub.update callback is called.
+ *
+ *  @param model Mesh (client) Model that's publishing the message.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_model_publish(struct bt_mesh_model *model);
+
+/** @brief Get the element that a model belongs to.
+ *
+ *  @param mod Mesh model.
+ *
+ *  @return Pointer to the element that the given model belongs to.
+ */
+struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
+
+/** @brief Find a SIG model.
+ *
+ *  @param elem Element to search for the model in.
+ *  @param id   Model ID of the model.
+ *
+ *  @return A pointer to the Mesh model matching the given parameters, or NULL
+ *          if no SIG model with the given ID exists in the given element.
+ */
+struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
+					 uint16_t id);
+
+/** @brief Find a vendor model.
+ *
+ *  @param elem    Element to search for the model in.
+ *  @param company Company ID of the model.
+ *  @param id      Model ID of the model.
+ *
+ *  @return A pointer to the Mesh model matching the given parameters, or NULL
+ *          if no vendor model with the given ID exists in the given element.
+ */
+struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
+					     uint16_t company, uint16_t id);
+
+/** @brief Get whether the model is in the primary element of the device.
+ *
+ *  @param mod Mesh model.
+ *
+ *  @return true if the model is on the primary element, false otherwise.
+ */
+static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
+{
+	return (mod->elem_idx == 0);
+}
+
+/** @brief Immediately store the model's user data in persistent storage.
+ *
+ *  @param mod      Mesh model.
+ *  @param vnd      This is a vendor model.
+ *  @param name     Name/key of the settings item.
+ *  @param data     Model data to store, or NULL to delete any model data.
+ *  @param data_len Length of the model data.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
+			 const char *name, const void *data,
+			 size_t data_len);
+
+/** @brief Let a model extend another.
+ *
+ *  Mesh models may be extended to reuse their functionality, forming a more
+ *  complex model. A Mesh model may extend any number of models, in any element.
+ *  The extensions may also be nested, ie a model that extends another may
+ *  itself be extended. Extensions may not be cyclical, and a model can only be
+ *  extended by one other model.
+ *
+ *  A set of models that extend each other form a model extension tree.
+ *
+ *  All models in an extension tree share one subscription list per element. The
+ *  access layer will utilize the combined subscription list of all models in an
+ *  extension tree and element, giving the models extended subscription list
+ *  capacity.
+ *
+ *  @param mod      Mesh model.
+ *  @param base_mod The model being extended.
+ *
+ *  @retval 0 Successfully extended the base_mod model.
+ *  @retval -EALREADY The base_mod model is already extended.
+ */
+int bt_mesh_model_extend(struct bt_mesh_model *mod,
+			 struct bt_mesh_model *base_mod);
+
+/** Node Composition */
+struct bt_mesh_comp {
+	uint16_t cid; /**< Company ID */
+	uint16_t pid; /**< Product ID */
+	uint16_t vid; /**< Version ID */
+
+	size_t elem_count; /**< The number of elements in this device. */
+	struct bt_mesh_elem *elem; /**< List of elements. */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_ACCESS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cdb.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cdb.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cdb.h	(working copy)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_
+
+#include <inttypes.h>
+#include <sys/atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_BT_MESH_CDB)
+#define NODE_COUNT    CONFIG_BT_MESH_CDB_NODE_COUNT
+#define SUBNET_COUNT  CONFIG_BT_MESH_CDB_SUBNET_COUNT
+#define APP_KEY_COUNT CONFIG_BT_MESH_CDB_APP_KEY_COUNT
+#else
+#define NODE_COUNT    0
+#define SUBNET_COUNT  0
+#define APP_KEY_COUNT 0
+#endif
+
+enum {
+	BT_MESH_CDB_NODE_CONFIGURED,
+	BT_MESH_CDB_NODE_BLACKLISTED,
+
+	BT_MESH_CDB_NODE_FLAG_COUNT
+};
+
+struct bt_mesh_cdb_node {
+	uint8_t  uuid[16];
+	uint16_t addr;
+	uint16_t net_idx;
+	uint8_t  num_elem;
+	uint8_t  dev_key[16];
+
+	ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
+};
+
+struct bt_mesh_cdb_subnet {
+	uint16_t net_idx;
+
+	bool kr_flag;
+	uint8_t kr_phase;
+
+	struct {
+		uint8_t net_key[16];
+	} keys[2];
+};
+
+struct bt_mesh_cdb_app_key {
+	uint16_t net_idx;
+	uint16_t app_idx;
+
+	struct {
+		uint8_t app_key[16];
+	} keys[2];
+};
+
+enum {
+	BT_MESH_CDB_VALID,
+	BT_MESH_CDB_SUBNET_PENDING,
+	BT_MESH_CDB_KEYS_PENDING,
+	BT_MESH_CDB_NODES_PENDING,
+	BT_MESH_CDB_IVU_IN_PROGRESS,
+
+	BT_MESH_CDB_FLAG_COUNT,
+};
+
+struct bt_mesh_cdb {
+	uint32_t iv_index;
+
+	ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
+
+	struct bt_mesh_cdb_node nodes[NODE_COUNT];
+	struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
+	struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
+};
+
+extern struct bt_mesh_cdb bt_mesh_cdb;
+
+/** @brief Create the Mesh Configuration Database.
+ *
+ *  Create and initialize the Mesh Configuration Database. A primary subnet,
+ *  ie one with NetIdx 0, will be added and the provided key will be used as
+ *  NetKey for that subnet.
+ *
+ *  @param key The NetKey to be used for the primary subnet.
+ *
+ *  @return 0 on success or negative error code on failure.
+ */
+int bt_mesh_cdb_create(const uint8_t key[16]);
+
+/** @brief Clear the Mesh Configuration Database.
+ *
+ *  Remove all nodes, subnets and app-keys stored in the database and mark
+ *  the database as invalid. The data will be cleared from persistent storage
+ *  if CONFIG_BT_SETTINGS is enabled.
+ */
+void bt_mesh_cdb_clear(void);
+
+/** @brief Set and store the IV Index and IV Update flag.
+ *
+ *  The IV Index stored in the CDB will be the one used during provisioning
+ *  of new nodes. This function is generally only used from inside the stack.
+ *
+ *  This function will store the data to persistent storage if
+ *  CONFIG_BT_SETTINGS is enabled.
+ *
+ *  @param iv_index The new IV Index to use.
+ *  @param iv_update True if there is an ongoing IV Update procedure.
+ */
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
+
+/** @brief Allocate a node.
+ *
+ *  Allocate a new node in the CDB.
+ *
+ *  @param uuid UUID of the node.
+ *  @param addr Address of the node's primary element. If 0, the lowest
+ *              possible address available will be assigned to the node.
+ *  @param num_elem Number of elements that the node has.
+ *  @param net_idx NetIdx that the node was provisioned to.
+ *
+ *  @return The new node or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+						uint8_t num_elem, uint16_t net_idx);
+
+/** @brief Delete a node.
+ *
+ *  Delete a node from the CDB.
+ *
+ *  @param node The node to be deleted.
+ *  @param store If true, the node will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
+
+/** @brief Get a node by address.
+ *
+ *  Try to find the node that has the provided address assigned to one of its
+ *  elements.
+ *
+ *  @param addr Address of the element to look for.
+ *
+ *  @return The node that has an element with address addr or NULL if no such
+ *          node exists.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
+
+/** @brief Store node to persistent storage.
+ *
+ *  @param node Node to be stored.
+ */
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
+
+enum {
+	BT_MESH_CDB_ITER_STOP = 0,
+	BT_MESH_CDB_ITER_CONTINUE,
+};
+
+/** @typedef bt_mesh_cdb_node_func_t
+ *  @brief Node iterator callback.
+ *
+ *  @param node Node found.
+ *  @param user_data Data given.
+ *
+ *  @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
+ *          or BT_MESH_CDB_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
+					void *user_data);
+
+/** @brief Node iterator.
+ *
+ *  Iterate nodes in the Mesh Configuration Database. The callback function
+ *  will only be called for valid, ie allocated, nodes.
+ *
+ *  @param func Callback function.
+ *  @param user_data Data to pass to the callback.
+ */
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
+
+/** @brief Allocate a subnet.
+ *
+ *  Allocate a new subnet in the CDB.
+ *
+ *  @param net_idx NetIdx of the subnet.
+ *
+ *  @return The new subnet or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
+
+/** @brief Delete a subnet.
+ *
+ *  Delete a subnet from the CDB.
+ *
+ *  @param sub The subnet to be deleted.
+ *  @param store If true, the subnet will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
+
+/** @brief Get a subnet by NetIdx
+ *
+ *  Try to find the subnet with the specified NetIdx.
+ *
+ *  @param net_idx NetIdx of the subnet to look for.
+ *
+ *  @return The subnet with the specified NetIdx or NULL if no such subnet
+ *          exists.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
+
+/** @brief Store subnet to persistent storage.
+ *
+ *  @param sub Subnet to be stored.
+ */
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
+
+/** @brief Get the flags for a subnet
+ *
+ *  @param sub The subnet to get flags for.
+ *
+ *  @return The flags for the subnet.
+ */
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
+
+
+/** @brief Allocate an application key.
+ *
+ *  Allocate a new application key in the CDB.
+ *
+ *  @param net_idx NetIdx of NetKey that the application key is bound to.
+ *  @param app_idx AppIdx of the application key.
+ *
+ *  @return The new application key or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+						      uint16_t app_idx);
+
+/** @brief Delete an application key.
+ *
+ *  Delete an application key from the CDB.
+ *
+ *  @param key The application key to be deleted.
+ *  @param store If true, the key will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
+
+/** @brief Get an application key by AppIdx
+ *
+ *  Try to find the application key with the specified AppIdx.
+ *
+ *  @param app_idx AppIdx of the application key to look for.
+ *
+ *  @return The application key with the specified AppIdx or NULL if no such key
+ *          exists.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
+
+/** @brief Store application key to persistent storage.
+ *
+ *  @param key Application key to be stored.
+ */
+void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_cli.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_cli.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_cli.h	(working copy)
@@ -0,0 +1,941 @@
+/** @file
+ *  @brief Bluetooth Mesh Configuration Client Model APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_CLI_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_CLI_H_
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh_cfg_cli Bluetooth Mesh Configuration Client Model
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Mesh Configuration Client Model Context */
+struct bt_mesh_cfg_cli {
+	/** Composition data model entry pointer. */
+	struct bt_mesh_model *model;
+
+	/* Internal parameters for tracking message responses. */
+	struct k_sem          op_sync;
+	uint32_t                 op_pending;
+	void                 *op_param;
+};
+
+/** @def BT_MESH_MODEL_CFG_CLI
+ *
+ *  @brief Generic Configuration Client model composition data entry.
+ *
+ *  @param cli_data Pointer to a @ref bt_mesh_cfg_cli instance.
+ */
+#define BT_MESH_MODEL_CFG_CLI(cli_data)                                        \
+	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL,   \
+			 cli_data, &bt_mesh_cfg_cli_cb)
+
+/** @brief Get the target node's composition data.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param page    Composition data page, or 0xff to request the first available
+ *                 page.
+ *  @param status  Status response parameter.
+ *  @param comp    Composition data buffer to fill.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+			      uint8_t *status, struct net_buf_simple *comp);
+
+/** @brief Get the target node's network beacon state.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param status  Status response parameter, returns one of
+ *                 @ref BT_MESH_BEACON_DISABLED or @ref BT_MESH_BEACON_ENABLED
+ *                 on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
+
+/** @brief Set the target node's network beacon state.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param val     New network beacon state, should be one of
+ *                 @ref BT_MESH_BEACON_DISABLED or @ref BT_MESH_BEACON_ENABLED.
+ *  @param status  Status response parameter. Returns one of
+ *                 @ref BT_MESH_BEACON_DISABLED or @ref BT_MESH_BEACON_ENABLED
+ *                 on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
+
+/** @brief Get the target node's Time To Live value.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param ttl     TTL response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
+
+/** @brief Set the target node's Time To Live value.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param val     New Time To Live value.
+ *  @param ttl     TTL response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
+
+/** @brief Get the target node's Friend feature status.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param status  Status response parameter. Returns one of
+ *                 @ref BT_MESH_FRIEND_DISABLED, @ref BT_MESH_FRIEND_ENABLED or
+ *                 @ref BT_MESH_FRIEND_NOT_SUPPORTED on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
+
+/** @brief Set the target node's Friend feature state.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param val     New Friend feature state. Should be one of
+ *                 @ref BT_MESH_FRIEND_DISABLED or
+ *                 @ref BT_MESH_FRIEND_ENABLED.
+ *  @param status  Status response parameter. Returns one of
+ *                 @ref BT_MESH_FRIEND_DISABLED, @ref BT_MESH_FRIEND_ENABLED or
+ *                 @ref BT_MESH_FRIEND_NOT_SUPPORTED on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
+
+/** @brief Get the target node's Proxy feature state.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param status  Status response parameter. Returns one of
+ *                 @ref BT_MESH_GATT_PROXY_DISABLED,
+ *                 @ref BT_MESH_GATT_PROXY_ENABLED or
+ *                 @ref BT_MESH_GATT_PROXY_NOT_SUPPORTED on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
+
+/** @brief Set the target node's Proxy feature state.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param val     New Proxy feature state. Must be one of
+ *                 @ref BT_MESH_GATT_PROXY_DISABLED or
+ *                 @ref BT_MESH_GATT_PROXY_ENABLED.
+ *  @param status  Status response parameter. Returns one of
+ *                 @ref BT_MESH_GATT_PROXY_DISABLED,
+ *                 @ref BT_MESH_GATT_PROXY_ENABLED or
+ *                 @ref BT_MESH_GATT_PROXY_NOT_SUPPORTED on success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+			       uint8_t *status);
+
+/** @brief Get the target node's network_transmit state.
+ *
+ *  @param net_idx  Network index to encrypt with.
+ *  @param addr     Target node address.
+ *  @param transmit Network transmit response parameter. Returns the encoded
+ *                  network transmission parameters on success. Decoded with
+ *                  @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+			  uint8_t *transmit);
+
+/** @brief Set the target node's network transmit parameters.
+ *
+ *  @param net_idx    Network index to encrypt with.
+ *  @param addr       Target node address.
+ *  @param val        New encoded network transmit parameters.
+ *                    @see BT_MESH_TRANSMIT.
+ *  @param transmit   Network transmit response parameter. Returns the encoded
+ *                    network transmission parameters on success. Decoded with
+ *                    @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT.
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+		uint8_t val, uint8_t *transmit);
+
+/** @brief Get the target node's Relay feature state.
+ *
+ *  @param net_idx  Network index to encrypt with.
+ *  @param addr     Target node address.
+ *  @param status   Status response parameter. Returns one of
+ *                  @ref BT_MESH_RELAY_DISABLED, @ref BT_MESH_RELAY_ENABLED or
+ *                  @ref BT_MESH_RELAY_NOT_SUPPORTED on success.
+ *  @param transmit Transmit response parameter. Returns the encoded relay
+ *                  transmission parameters on success. Decoded with
+ *                  @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+			  uint8_t *transmit);
+
+/** @brief Set the target node's Relay parameters.
+ *
+ *  @param net_idx      Network index to encrypt with.
+ *  @param addr         Target node address.
+ *  @param new_relay    New relay state. Must be one of
+ *                      @ref BT_MESH_RELAY_DISABLED or
+ *                      @ref BT_MESH_RELAY_ENABLED.
+ *  @param new_transmit New encoded relay transmit parameters.
+ *                      @see BT_MESH_TRANSMIT.
+ *  @param status       Status response parameter. Returns one of
+ *                      @ref BT_MESH_RELAY_DISABLED, @ref BT_MESH_RELAY_ENABLED
+ *                      or @ref BT_MESH_RELAY_NOT_SUPPORTED on success.
+ *  @param transmit     Transmit response parameter. Returns the encoded relay
+ *                      transmission parameters on success. Decoded with
+ *                      @ref BT_MESH_TRANSMIT_COUNT and
+ *                      @ref BT_MESH_TRANSMIT_INT.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+			  uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
+
+/** @brief Add a network key to the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param key_net_idx Network key index.
+ *  @param net_key     Network key.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			    const uint8_t net_key[16], uint8_t *status);
+
+/** @brief Get a list of the target node's network key indexes.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param keys    Net key index list response parameter. Will be filled with
+ *                 all the returned network key indexes it can fill.
+ *  @param key_cnt Net key index list length. Should be set to the
+ *                 capacity of the @c keys list when calling. Will return the
+ *                 number of returned network key indexes upon success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+			    size_t *key_cnt);
+
+/** @brief Delete a network key from the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param key_net_idx Network key index.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+			    uint16_t key_net_idx, uint8_t *status);
+
+/** @brief Add an application key to the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param key_net_idx Network key index the application key belongs to.
+ *  @param key_app_idx Application key index.
+ *  @param app_key     Application key.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			    uint16_t key_app_idx, const uint8_t app_key[16],
+			    uint8_t *status);
+
+/** @brief Get a list of the target node's application key indexes for a
+ *         specific network key.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param key_net_idx Network key index to request the app key indexes of.
+ *  @param status      Status response parameter.
+ *  @param keys        App key index list response parameter. Will be filled
+ *                     with all the returned application key indexes it can
+ *                     fill.
+ *  @param key_cnt     App key index list length. Should be set to the
+ *                     capacity of the @c keys list when calling. Will return
+ *                     the number of returned application key indexes upon
+ *                     success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			    uint8_t *status, uint16_t *keys, size_t *key_cnt);
+
+
+/** @brief Delete an application key from the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param key_net_idx Network key index the application key belongs to.
+ *  @param key_app_idx Application key index.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+		uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
+
+/** @brief Bind an application to a SIG model on the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param elem_addr   Element address the model is in.
+ *  @param mod_app_idx Application index to bind.
+ *  @param mod_id      Model ID.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			     uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
+
+/** @brief Unbind an application from a SIG model on the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param elem_addr   Element address the model is in.
+ *  @param mod_app_idx Application index to unbind.
+ *  @param mod_id      Model ID.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+	uint16_t elem_addr, uint16_t mod_app_idx,
+	uint16_t mod_id, uint8_t *status);
+
+/** @brief Bind an application to a vendor model on the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param elem_addr   Element address the model is in.
+ *  @param mod_app_idx Application index to bind.
+ *  @param mod_id      Model ID.
+ *  @param cid         Company ID of the model.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status);
+
+/** @brief Unbind an application from a vendor model on the target node.
+ *
+ *  @param net_idx     Network index to encrypt with.
+ *  @param addr        Target node address.
+ *  @param elem_addr   Element address the model is in.
+ *  @param mod_app_idx Application index to unbind.
+ *  @param mod_id      Model ID.
+ *  @param cid         Company ID of the model.
+ *  @param status      Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+	uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
+	uint16_t cid, uint8_t *status);
+
+/** @brief Get a list of all applications bound to a SIG model on the target
+ *         node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param status    Status response parameter.
+ *  @param apps      App index list response parameter. Will be filled with all
+ *                   the returned application key indexes it can fill.
+ *  @param app_cnt   App index list length. Should be set to the capacity of the
+ *                   @c apps list when calling. Will return the number of
+ *                   returned application key indexes upon success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, uint8_t *status, uint16_t *apps,
+			    size_t *app_cnt);
+
+
+/** @brief Get a list of all applications bound to a vendor model on the target
+ *         node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param status    Status response parameter.
+ *  @param apps      App index list response parameter. Will be filled with all
+ *                   the returned application key indexes it can fill.
+ *  @param app_cnt   App index list length. Should be set to the capacity of the
+ *                   @c apps list when calling. Will return the number of
+ *                   returned application key indexes upon success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid, uint8_t *status,
+				uint16_t *apps, size_t *app_cnt);
+
+/** @def BT_MESH_PUB_PERIOD_100MS
+ *
+ *  @brief Helper macro to encode model publication period in units of 100ms
+ *
+ *  @param steps Number of 100ms steps.
+ *
+ *  @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period
+ */
+#define BT_MESH_PUB_PERIOD_100MS(steps)  ((steps) & BIT_MASK(6))
+
+/** @def BT_MESH_PUB_PERIOD_SEC
+ *
+ *  @brief Helper macro to encode model publication period in units of 1 second
+ *
+ *  @param steps Number of 1 second steps.
+ *
+ *  @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period
+ */
+#define BT_MESH_PUB_PERIOD_SEC(steps)   (((steps) & BIT_MASK(6)) | (1 << 6))
+
+/** @def BT_MESH_PUB_PERIOD_10SEC
+ *
+ *  @brief Helper macro to encode model publication period in units of 10
+ *  seconds
+ *
+ *  @param steps Number of 10 second steps.
+ *
+ *  @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period
+ */
+#define BT_MESH_PUB_PERIOD_10SEC(steps) (((steps) & BIT_MASK(6)) | (2 << 6))
+
+/** @def BT_MESH_PUB_PERIOD_10MIN
+ *
+ *  @brief Helper macro to encode model publication period in units of 10
+ *  minutes
+ *
+ *  @param steps Number of 10 minute steps.
+ *
+ *  @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period
+ */
+#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
+
+/** Model publication configuration parameters. */
+struct bt_mesh_cfg_mod_pub {
+	/** Publication destination address. */
+	uint16_t  addr;
+	/** Application index to publish with. */
+	uint16_t  app_idx;
+	/** Friendship credential flag. */
+	bool   cred_flag;
+	/** Time To Live to publish with. */
+	uint8_t   ttl;
+	/**
+	 * Encoded publish period.
+	 * @see BT_MESH_PUB_PERIOD_100MS, BT_MESH_PUB_PERIOD_SEC,
+	 * BT_MESH_PUB_PERIOD_10SEC,
+	 * BT_MESH_PUB_PERIOD_10MIN
+	 */
+	uint8_t   period;
+	/**
+	 * Encoded transmit parameters.
+	 * @see BT_MESH_TRANSMIT
+	 */
+	uint8_t   transmit;
+};
+
+/** @brief Get publish parameters for a SIG model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param pub       Publication parameter return buffer.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+			    uint8_t *status);
+
+/** @brief Get publish parameters for a vendor model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param pub       Publication parameter return buffer.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid,
+				struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
+
+/** @brief Set publish parameters for a SIG model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param pub       Publication parameters.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+			    uint8_t *status);
+
+/** @brief Set publish parameters for a vendor model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param pub       Publication parameters.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid,
+				struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
+
+/** @brief Add a group address to a SIG model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
+
+/** @brief Add a group address to a vendor model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status);
+
+/** @brief Delete a group address in a SIG model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
+
+/** @brief Delete a group address in a vendor model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status);
+
+/** @brief Overwrite all addresses in a SIG model's subscription list with a
+ * group address.
+ *
+ * Deletes all subscriptions in the model's subscription list, and adds a
+ * single group address instead.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				  uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
+
+/** @brief Overwrite all addresses in a vendor model's subscription list with a
+ * group address.
+ *
+ * Deletes all subscriptions in the model's subscription list, and adds a
+ * single group address instead.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param sub_addr  Group address to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+				      uint16_t elem_addr, uint16_t sub_addr,
+				      uint16_t mod_id, uint16_t cid, uint8_t *status);
+
+/** @brief Add a virtual address to a SIG model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address label to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			       const uint8_t label[16], uint16_t mod_id,
+			       uint16_t *virt_addr, uint8_t *status);
+
+/** @brief Add a virtual address to a vendor model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address label to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				   const uint8_t label[16], uint16_t mod_id,
+				   uint16_t cid, uint16_t *virt_addr, uint8_t *status);
+
+/** @brief Delete a virtual address in a SIG model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address parameter to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			       const uint8_t label[16], uint16_t mod_id,
+			       uint16_t *virt_addr, uint8_t *status);
+
+/** @brief Delete a virtual address in a vendor model's subscription list.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address label to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				   const uint8_t label[16], uint16_t mod_id,
+				   uint16_t cid, uint16_t *virt_addr, uint8_t *status);
+
+/** @brief Overwrite all addresses in a SIG model's subscription list with a
+ * virtual address.
+ *
+ * Deletes all subscriptions in the model's subscription list, and adds a
+ * single group address instead.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address label to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+				     uint16_t elem_addr, const uint8_t label[16],
+				     uint16_t mod_id, uint16_t *virt_addr,
+				     uint8_t *status);
+
+/** @brief Overwrite all addresses in a vendor model's subscription list with a
+ * virtual address.
+ *
+ * Deletes all subscriptions in the model's subscription list, and adds a
+ * single group address instead.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param label     Virtual address label to add to the subscription list.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param virt_addr Virtual address response parameter.
+ *  @param status    Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+					 uint16_t elem_addr, const uint8_t label[16],
+					 uint16_t mod_id, uint16_t cid,
+					 uint16_t *virt_addr, uint8_t *status);
+
+/** @brief Get the subscription list of a SIG model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param status    Status response parameter.
+ *  @param subs      Subscription list response parameter. Will be filled with
+ *                   all the returned subscriptions it can fill.
+ *  @param sub_cnt   Subscription list element count. Should be set to the
+ *                   capacity of the @c subs list when calling. Will return the
+ *                   number of returned subscriptions upon success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, uint8_t *status, uint16_t *subs,
+			    size_t *sub_cnt);
+
+/** @brief Get the subscription list of a vendor model on the target node.
+ *
+ *  @param net_idx   Network index to encrypt with.
+ *  @param addr      Target node address.
+ *  @param elem_addr Element address the model is in.
+ *  @param mod_id    Model ID.
+ *  @param cid       Company ID of the model.
+ *  @param status    Status response parameter.
+ *  @param subs      Subscription list response parameter. Will be filled with
+ *                   all the returned subscriptions it can fill.
+ *  @param sub_cnt   Subscription list element count. Should be set to the
+ *                   capacity of the @c subs list when calling. Will return the
+ *                   number of returned subscriptions upon success.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid, uint8_t *status,
+				uint16_t *subs, size_t *sub_cnt);
+
+/** Heartbeat subscription configuration parameters. */
+struct bt_mesh_cfg_hb_sub {
+	/** Source address to receive Heartbeat messages from. */
+	uint16_t src;
+	/** Destination address to receive Heartbeat messages on. */
+	uint16_t dst;
+	/**
+	 * Logarithmic subscription period to keep listening for.
+	 * The decoded subscription period is (1 << (period - 1)) seconds, or 0
+	 * seconds if period is 0.
+	 */
+	uint8_t  period;
+	/**
+	 * Logarithmic Heartbeat subscription receive count.
+	 * The decoded Heartbeat count is (1 << (count - 1)) if count is
+	 * between 1 and 0xfe, 0 if count is 0 and 0xffff if count is 0xff.
+	 *
+	 * Ignored in Heartbeat subscription set.
+	 */
+	uint8_t  count;
+	/**
+	 * Minimum hops in received messages, ie the shortest registered path
+	 * from the publishing node to the subscribing node. A Heartbeat
+	 * received from an immediate neighbor has hop count = 1.
+	 *
+	 * Ignored in Heartbeat subscription set.
+	 */
+	uint8_t  min;
+	/**
+	 * Maximum hops in received messages, ie the longest registered path
+	 * from the publishing node to the subscribing node. A Heartbeat
+	 * received from an immediate neighbor has hop count = 1.
+	 *
+	 * Ignored in Heartbeat subscription set.
+	 */
+	uint8_t  max;
+};
+
+/** @brief Set the target node's Heartbeat subscription parameters.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param sub     New Heartbeat subscription parameters.
+ *  @param status  Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
+
+/** @brief Get the target node's Heartbeta subscription parameters.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param sub     Heartbeat subscription parameter return buffer.
+ *  @param status  Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
+
+/** Heartbeat publication configuration parameters. */
+struct bt_mesh_cfg_hb_pub {
+	/** Heartbeat destination address. */
+	uint16_t dst;
+	/**
+	 * Logarithmic Heartbeat count. Decoded as (1 << (count - 1)) if count
+	 * is between 1 and 0x11, 0 if count is 0, or "indefinitely" if count is
+	 * 0xff.
+	 *
+	 * When used in Heartbeat publication set, this parameter denotes the
+	 * number of Heartbeat messages to send.
+	 *
+	 * When returned from Heartbeat publication get, this parameter denotes
+	 * the number of Heartbeat messages remaining to be sent.
+	 */
+	uint8_t  count;
+	/**
+	 * Logarithmic Heartbeat publication transmit interval in seconds.
+	 * Decoded as (1 << (period - 1)) if period is between 1 and 0x11.
+	 * If period is 0, Heartbeat publication is disabled.
+	 */
+	uint8_t  period;
+	/** Publication message Time To Live value. */
+	uint8_t  ttl;
+	/**
+	 * Bitmap of features that trigger Heartbeat publications.
+	 * Legal values are @ref BT_MESH_FEAT_RELAY,
+	 * @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and
+	 * @ref BT_MESH_FEAT_LOW_POWER
+	 */
+	uint16_t feat;
+	/** Network index to publish with. */
+	uint16_t net_idx;
+};
+
+/** @brief Set the target node's Heartbeat publication parameters.
+ *
+ *  @note The target node must already have received the specified network key.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param pub     New Heartbeat publication parameters.
+ *  @param status  Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+			   const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
+
+/** @brief Get the target node's Heartbeat publication parameters.
+ *
+ *  @param net_idx Network index to encrypt with.
+ *  @param addr    Target node address.
+ *  @param pub     Heartbeat publication parameter return buffer.
+ *  @param status  Status response parameter.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
+
+/** @brief Get the current transmission timeout value.
+ *
+ *  @return The configured transmission timeout in milliseconds.
+ */
+int32_t bt_mesh_cfg_cli_timeout_get(void);
+
+/** @brief Set the transmission timeout value.
+ *
+ *  @param timeout The new transmission timeout.
+ */
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[];
+extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_CLI_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_srv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_srv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/cfg_srv.h	(working copy)
@@ -0,0 +1,124 @@
+/** @file
+ *  @brief Bluetooth Mesh Configuration Server Model APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_SRV_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_SRV_H_
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh_cfg_srv Bluetooth Mesh Configuration Server Model
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Mesh Configuration Server Model Context */
+struct bt_mesh_cfg_srv {
+	/** Composition data model entry pointer. */
+	struct bt_mesh_model *model;
+
+	uint8_t net_transmit;         /**< Network Transmit state */
+	uint8_t relay;                /**< Relay Mode state */
+	uint8_t relay_retransmit;     /**< Relay Retransmit state */
+	uint8_t beacon;               /**< Secure Network Beacon state */
+	uint8_t gatt_proxy;           /**< GATT Proxy state */
+	uint8_t frnd;                 /**< Friend state */
+	uint8_t default_ttl;          /**< Default TTL */
+
+	/** Heartbeat Publication parameters */
+	struct bt_mesh_hb_pub {
+		struct k_delayed_work timer;
+
+		/** Destination address. */
+		uint16_t dst;
+		/** Remaining publish count. */
+		uint16_t count;
+		/** Logarithmic publish interval in seconds. */
+		uint8_t  period;
+		/** Time To Live value. */
+		uint8_t  ttl;
+		/**
+		 * Bitmap of features that trigger a Heartbeat publication if
+		 * they change. Legal values are
+		 * @ref BT_MESH_FEAT_RELAY, @ref BT_MESH_FEAT_PROXY,
+		 * @ref BT_MESH_FEAT_FRIEND and @ref BT_MESH_FEAT_LOW_POWER.
+		 */
+		uint16_t feat;
+		/** Network index used for publishing. */
+		uint16_t net_idx;
+	} hb_pub;
+
+	/** Heartbeat Subscription parameters. */
+	struct bt_mesh_hb_sub {
+		/** Subscription period exipration timestamp. */
+		int64_t  expiry;
+		/** Source address to receive Heartbeats from. */
+		uint16_t src;
+		/** Destination address to received Heartbeats on. */
+		uint16_t dst;
+		/** The number of received Heartbeat messages so far. */
+		uint16_t count;
+		/**
+		 * Minimum hops in received messages, ie the shortest registered
+		 * path from the publishing node to the subscribing node. A
+		 * Heartbeat received from an immediate neighbor has hop
+		 * count = 1.
+		 */
+		uint8_t  min_hops;
+		/**
+		 * Maximum hops in received messages, ie the longest registered
+		 * path from the publishing node to the subscribing node. A
+		 * Heartbeat received from an immediate neighbor has hop
+		 * count = 1.
+		 */
+		uint8_t  max_hops;
+
+		/** @brief Optional Heartbeat subscription tracking callback.
+		 *
+		 *  Gets called on every received Heartbeat.
+		 *
+		 *  @param hops The number of hops the Heartbeat was received
+		 *              with.
+		 *  @param feat The feature set of the publishing node. The
+		 *              value is a bitmap of @ref BT_MESH_FEAT_RELAY,
+		 *              @ref BT_MESH_FEAT_PROXY,
+		 *              @ref BT_MESH_FEAT_FRIEND and
+		 *              @ref BT_MESH_FEAT_LOW_POWER.
+		 */
+		void (*func)(uint8_t hops, uint16_t feat);
+	} hb_sub;
+};
+
+/** @def BT_MESH_MODEL_CFG_SRV
+ *
+ *  @brief Generic Configuration Server model composition data entry.
+ *
+ *  @param srv_data Pointer to a @ref bt_mesh_cfg_srv instance.
+ */
+#define BT_MESH_MODEL_CFG_SRV(srv_data)                                        \
+	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL,   \
+			 srv_data, &bt_mesh_cfg_srv_cb)
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
+extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CFG_SRV_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_cli.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_cli.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_cli.h	(working copy)
@@ -0,0 +1,208 @@
+/** @file
+ *  @brief Bluetooth Mesh Health Client Model APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_CLI_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_CLI_H_
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh_health_cli Bluetooth Mesh Health Client Model
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Mesh Health Client Model Context */
+struct bt_mesh_health_cli {
+	/** Composition data model entry pointer. */
+	struct bt_mesh_model *model;
+
+	/** @brief Optional callback for Health Current Status messages.
+	 *
+	 *  Handles received Health Current Status messages from a Health
+	 *  server. The @c fault array represents all faults that are
+	 *  currently present in the server's element.
+	 *
+	 *  @see bt_mesh_health_faults
+	 *
+	 *  @param cli         Health client that received the status message.
+	 *  @param addr        Address of the sender.
+	 *  @param test_id     Identifier of a most recently performed test.
+	 *  @param cid         Company Identifier of the node.
+	 *  @param faults      Array of faults.
+	 *  @param fault_count Number of faults in the fault array.
+	 */
+	void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
+			       uint8_t test_id, uint16_t cid, uint8_t *faults,
+			       size_t fault_count);
+
+	/* Internal parameters for tracking message responses. */
+	struct k_sem          op_sync;
+	uint32_t                 op_pending;
+	void                 *op_param;
+};
+
+
+/** @def BT_MESH_MODEL_HEALTH_CLI
+ *
+ *  @brief Generic Health Client model composition data entry.
+ *
+ *  @param cli_data Pointer to a @ref bt_mesh_health_cli instance.
+ */
+#define BT_MESH_MODEL_HEALTH_CLI(cli_data)                                     \
+	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_op,   \
+			 NULL, cli_data, &bt_mesh_health_cli_cb)
+
+/** @brief Set Health client model instance to use for communication.
+ *
+ *  @param model Health Client model instance from the composition data.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_cli_set(struct bt_mesh_model *model);
+
+/** @brief Get the registered fault state for the given Company ID.
+ *
+ *  @see bt_mesh_health_faults
+ *
+ *  @param addr        Target node element address.
+ *  @param app_idx     Application index to encrypt with.
+ *  @param cid         Company ID to get the registered faults of.
+ *  @param test_id     Test ID response buffer.
+ *  @param faults      Fault array response buffer.
+ *  @param fault_count Fault count response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t *test_id, uint8_t *faults,
+				 size_t *fault_count);
+
+/** @brief Clear the registered faults for the given Company ID.
+ *
+ *  @see bt_mesh_health_faults
+ *
+ *  @param addr        Target node element address.
+ *  @param app_idx     Application index to encrypt with.
+ *  @param cid         Company ID to clear the registered faults for.
+ *  @param test_id     Test ID response buffer.
+ *  @param faults      Fault array response buffer.
+ *  @param fault_count Fault count response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t *test_id, uint8_t *faults,
+				 size_t *fault_count);
+
+/** @brief Invoke a self-test procedure for the given Company ID.
+ *
+ *  @param addr        Target node element address.
+ *  @param app_idx     Application index to encrypt with.
+ *  @param cid         Company ID to invoke the test for.
+ *  @param test_id     Test ID response buffer.
+ *  @param faults      Fault array response buffer.
+ *  @param fault_count Fault count response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t test_id, uint8_t *faults,
+				 size_t *fault_count);
+
+/** @brief Get the target node's Health fast period divisor.
+ *
+ *  The health period divisor is used to increase the publish rate when a fault
+ *  is registered. Normally, the Health server will publish with the period in
+ *  the configured publish parameters. When a fault is registered, the publish
+ *  period is divided by (1 << divisor). For example, if the target node's
+ *  Health server is configured to publish with a period of 16 seconds, and the
+ *  Health fast period divisor is 5, the Health server will publish with an
+ *  interval of 500 ms when a fault is registered.
+ *
+ *  @param addr    Target node element address.
+ *  @param app_idx Application index to encrypt with.
+ *  @param divisor Health period divisor response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
+
+/** @brief Set the target node's Health fast period divisor.
+ *
+ *  The health period divisor is used to increase the publish rate when a fault
+ *  is registered. Normally, the Health server will publish with the period in
+ *  the configured publish parameters. When a fault is registered, the publish
+ *  period is divided by (1 << divisor). For example, if the target node's
+ *  Health server is configured to publish with a period of 16 seconds, and the
+ *  Health fast period divisor is 5, the Health server will publish with an
+ *  interval of 500 ms when a fault is registered.
+ *
+ *  @param addr            Target node element address.
+ *  @param app_idx         Application index to encrypt with.
+ *  @param divisor         New Health period divisor.
+ *  @param updated_divisor Health period divisor response buffer.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+				 uint8_t *updated_divisor);
+
+/** @brief Get the current attention timer value.
+ *
+ *  @param addr      Target node element address.
+ *  @param app_idx   Application index to encrypt with.
+ *  @param attention Attention timer response buffer, measured in seconds.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
+
+/** @brief Set the attention timer.
+ *
+ *  @param addr              Target node element address.
+ *  @param app_idx           Application index to encrypt with.
+ *  @param attention         New attention timer time, in seconds.
+ *  @param updated_attention Attention timer response buffer, measured in
+ *                           seconds.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+				 uint8_t *updated_attention);
+
+/** @brief Get the current transmission timeout value.
+ *
+ *  @return The configured transmission timeout in milliseconds.
+ */
+int32_t bt_mesh_health_cli_timeout_get(void);
+
+/** @brief Set the transmission timeout value.
+ *
+ *  @param timeout The new transmission timeout.
+ */
+void bt_mesh_health_cli_timeout_set(int32_t timeout);
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct bt_mesh_model_op bt_mesh_health_cli_op[];
+extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_CLI_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_faults.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_faults.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_faults.h	(working copy)
@@ -0,0 +1,85 @@
+/** @file
+ * @brief Bluetooth Mesh Health faults
+ */
+
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_FAULTS_H__
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_FAULTS_H__
+
+/**
+ * @brief List of specification defined Health Fault values.
+ * @defgroup bt_mesh_health_faults Bluetooth Mesh Health Faults
+ * @ingroup bt_mesh
+ * @{
+ */
+
+/** No fault has occurred. */
+#define BT_MESH_HEALTH_FAULT_NO_FAULT                           0x00
+
+#define BT_MESH_HEALTH_FAULT_BATTERY_LOW_WARNING                0x01
+#define BT_MESH_HEALTH_FAULT_BATTERY_LOW_ERROR                  0x02
+#define BT_MESH_HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_LOW_WARNING     0x03
+#define BT_MESH_HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_LOW_ERROR       0x04
+#define BT_MESH_HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_HIGH_WARNING    0x05
+#define BT_MESH_HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_HIGH_ERROR      0x06
+#define BT_MESH_HEALTH_FAULT_POWER_SUPPLY_INTERRUPTED_WARNING   0x07
+#define BT_MESH_HEALTH_FAULT_POWER_SUPPLY_INTERRUPTED_ERROR     0x08
+#define BT_MESH_HEALTH_FAULT_NO_LOAD_WARNING                    0x09
+#define BT_MESH_HEALTH_FAULT_NO_LOAD_ERROR                      0x0A
+#define BT_MESH_HEALTH_FAULT_OVERLOAD_WARNING                   0x0B
+#define BT_MESH_HEALTH_FAULT_OVERLOAD_ERROR                     0x0C
+#define BT_MESH_HEALTH_FAULT_OVERHEAT_WARNING                   0x0D
+#define BT_MESH_HEALTH_FAULT_OVERHEAT_ERROR                     0x0E
+#define BT_MESH_HEALTH_FAULT_CONDENSATION_WARNING               0x0F
+#define BT_MESH_HEALTH_FAULT_CONDENSATION_ERROR                 0x10
+#define BT_MESH_HEALTH_FAULT_VIBRATION_WARNING                  0x11
+#define BT_MESH_HEALTH_FAULT_VIBRATION_ERROR                    0x12
+#define BT_MESH_HEALTH_FAULT_CONFIGURATION_WARNING              0x13
+#define BT_MESH_HEALTH_FAULT_CONFIGURATION_ERROR                0x14
+#define BT_MESH_HEALTH_FAULT_ELEMENT_NOT_CALIBRATED_WARNING     0x15
+#define BT_MESH_HEALTH_FAULT_ELEMENT_NOT_CALIBRATED_ERROR       0x16
+#define BT_MESH_HEALTH_FAULT_MEMORY_WARNING                     0x17
+#define BT_MESH_HEALTH_FAULT_MEMORY_ERROR                       0x18
+#define BT_MESH_HEALTH_FAULT_SELF_TEST_WARNING                  0x19
+#define BT_MESH_HEALTH_FAULT_SELF_TEST_ERROR                    0x1A
+#define BT_MESH_HEALTH_FAULT_INPUT_TOO_LOW_WARNING              0x1B
+#define BT_MESH_HEALTH_FAULT_INPUT_TOO_LOW_ERROR                0x1C
+#define BT_MESH_HEALTH_FAULT_INPUT_TOO_HIGH_WARNING             0x1D
+#define BT_MESH_HEALTH_FAULT_INPUT_TOO_HIGH_ERROR               0x1E
+#define BT_MESH_HEALTH_FAULT_INPUT_NO_CHANGE_WARNING            0x1F
+#define BT_MESH_HEALTH_FAULT_INPUT_NO_CHANGE_ERROR              0x20
+#define BT_MESH_HEALTH_FAULT_ACTUATOR_BLOCKED_WARNING           0x21
+#define BT_MESH_HEALTH_FAULT_ACTUATOR_BLOCKED_ERROR             0x22
+#define BT_MESH_HEALTH_FAULT_HOUSING_OPENED_WARNING             0x23
+#define BT_MESH_HEALTH_FAULT_HOUSING_OPENED_ERROR               0x24
+#define BT_MESH_HEALTH_FAULT_TAMPER_WARNING                     0x25
+#define BT_MESH_HEALTH_FAULT_TAMPER_ERROR                       0x26
+#define BT_MESH_HEALTH_FAULT_DEVICE_MOVED_WARNING               0x27
+#define BT_MESH_HEALTH_FAULT_DEVICE_MOVED_ERROR                 0x28
+#define BT_MESH_HEALTH_FAULT_DEVICE_DROPPED_WARNING             0x29
+#define BT_MESH_HEALTH_FAULT_DEVICE_DROPPED_ERROR               0x2A
+#define BT_MESH_HEALTH_FAULT_OVERFLOW_WARNING                   0x2B
+#define BT_MESH_HEALTH_FAULT_OVERFLOW_ERROR                     0x2C
+#define BT_MESH_HEALTH_FAULT_EMPTY_WARNING                      0x2D
+#define BT_MESH_HEALTH_FAULT_EMPTY_ERROR                        0x2E
+#define BT_MESH_HEALTH_FAULT_INTERNAL_BUS_WARNING               0x2F
+#define BT_MESH_HEALTH_FAULT_INTERNAL_BUS_ERROR                 0x30
+#define BT_MESH_HEALTH_FAULT_MECHANISM_JAMMED_WARNING           0x31
+#define BT_MESH_HEALTH_FAULT_MECHANISM_JAMMED_ERROR             0x32
+
+/**
+ * Start of the vendor specific fault values.
+ *
+ * All values below this are reserved for the Bluetooth Specification.
+ */
+#define BT_MESH_HEALTH_FAULT_VENDOR_SPECIFIC_START              0x80
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_FAULTS_H__ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_srv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_srv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/health_srv.h	(working copy)
@@ -0,0 +1,200 @@
+/** @file
+ *  @brief Bluetooth Mesh Health Server Model APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_SRV_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_SRV_H_
+
+/**
+ * @brief Bluetooth Mesh Health Server Model
+ * @defgroup bt_mesh_health_srv Bluetooth Mesh Health Server Model
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Callback function for the Health Server model */
+struct bt_mesh_health_srv_cb {
+	/** @brief Callback for fetching current faults.
+	 *
+	 *  Fault values may either be defined by the specification, or by a
+	 *  vendor. Vendor specific faults should be interpreted in the context
+	 *  of the accompanying Company ID. Specification defined faults may be
+	 *  reported for any Company ID, and the same fault may be presented
+	 *  for multiple Company IDs.
+	 *
+	 *  All faults shall be associated with at least one Company ID,
+	 *  representing the device vendor or some other vendor whose vendor
+	 *  specific fault values are used.
+	 *
+	 *  If there are multiple Company IDs that have active faults,
+	 *  return only the faults associated with one of them at the time.
+	 *  To report faults for multiple Company IDs, interleave which Company
+	 *  ID is reported for each call.
+	 *
+	 *  @param model       Health Server model instance to get faults of.
+	 *  @param test_id     Test ID response buffer.
+	 *  @param company_id  Company ID response buffer.
+	 *  @param faults      Array to fill with current faults.
+	 *  @param fault_count The number of faults the fault array can fit.
+	 *                     Should be updated to reflect the number of faults
+	 *                     copied into the array.
+	 *
+	 *  @return 0 on success, or (negative) error code otherwise.
+	 */
+	int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id,
+			     uint16_t *company_id, uint8_t *faults,
+			     uint8_t *fault_count);
+
+	/** @brief Callback for fetching all registered faults.
+	 *
+	 *  Registered faults are all past and current faults since the last
+	 *  call to @c fault_clear. Only faults associated with the given
+	 *  Company ID should be reported.
+	 *
+	 *  Fault values may either be defined by the specification, or by a
+	 *  vendor. Vendor specific faults should be interpreted in the context
+	 *  of the accompanying Company ID. Specification defined faults may be
+	 *  reported for any Company ID, and the same fault may be presented
+	 *  for multiple Company IDs.
+	 *
+	 *  @param model       Health Server model instance to get faults of.
+	 *  @param company_id  Company ID to get faults for.
+	 *  @param test_id     Test ID response buffer.
+	 *  @param faults      Array to fill with registered faults.
+	 *  @param fault_count The number of faults the fault array can fit.
+	 *                     Should be updated to reflect the number of faults
+	 *                     copied into the array.
+	 *
+	 *  @return 0 on success, or (negative) error code otherwise.
+	 */
+	int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id,
+			     uint8_t *test_id, uint8_t *faults,
+			     uint8_t *fault_count);
+
+	/** @brief Clear all registered faults associated with the given Company
+	 * ID.
+	 *
+	 *  @param model      Health Server model instance to clear faults of.
+	 *  @param company_id Company ID to clear faults for.
+	 *
+	 *  @return 0 on success, or (negative) error code otherwise.
+	 */
+	int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id);
+
+	/** @brief Run a self-test.
+	 *
+	 *  The Health server may support up to 256 self-tests for each Company
+	 *  ID. The behavior for all test IDs are vendor specific, and should be
+	 *  interpreted based on the accompanying Company ID. Test failures
+	 *  should result in changes to the fault array.
+	 *
+	 *  @param model      Health Server model instance to run test for.
+	 *  @param test_id    Test ID to run.
+	 *  @param company_id Company ID to run test for.
+	 *
+	 *  @return 0 if the test execution was started successfully, or
+	 * (negative) error code otherwise. Note that the fault array will not
+	 * be reported back to the client if the test execution didn't start.
+	 */
+	int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id,
+			  uint16_t company_id);
+
+	/** @brief Start calling attention to the device.
+	 *
+	 *  The attention state is used to map an element address to a
+	 *  physical device. When this callback is called, the device should
+	 *  start some physical procedure meant to call attention to itself,
+	 *  like blinking, buzzing, vibrating or moving. If there are multiple
+	 *  Health server instances on the device, the attention state should
+	 *  also help identify the specific element the server is in.
+	 *
+	 *  The attention calling behavior should continue until the @c attn_off
+	 *  callback is called.
+	 *
+	 *  @param model Health Server model to start the attention state of.
+	 */
+	void (*attn_on)(struct bt_mesh_model *model);
+
+	/** @brief Stop the attention state.
+	 *
+	 *  Any physical activity started to call attention to the device should
+	 *  be stopped.
+	 *
+	 *  @param model
+	 */
+	void (*attn_off)(struct bt_mesh_model *model);
+};
+
+/** @def BT_MESH_HEALTH_PUB_DEFINE
+ *
+ *  A helper to define a health publication context
+ *
+ *  @param _name       Name given to the publication context variable.
+ *  @param _max_faults Maximum number of faults the element can have.
+ */
+#define BT_MESH_HEALTH_PUB_DEFINE(_name, _max_faults) \
+	BT_MESH_MODEL_PUB_DEFINE(_name, NULL, (1 + 3 + (_max_faults)))
+
+/** Mesh Health Server Model Context */
+struct bt_mesh_health_srv {
+	/** Composition data model entry pointer. */
+	struct bt_mesh_model *model;
+
+	/** Optional callback struct */
+	const struct bt_mesh_health_srv_cb *cb;
+
+	/** Attention Timer state */
+	struct k_delayed_work attn_timer;
+};
+
+/** @def BT_MESH_MODEL_HEALTH_SRV
+ *
+ *  Define a new health server model. Note that this API needs to be
+ *  repeated for each element that the application wants to have a
+ *  health server model on. Each instance also needs a unique
+ *  bt_mesh_health_srv and bt_mesh_model_pub context.
+ *
+ *  @param srv Pointer to a unique struct bt_mesh_health_srv.
+ *  @param pub Pointer to a unique struct bt_mesh_model_pub.
+ *
+ *  @return New mesh model instance.
+ */
+#define BT_MESH_MODEL_HEALTH_SRV(srv, pub)                                     \
+	BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op,   \
+			 pub, srv, &bt_mesh_health_srv_cb)
+
+/** @brief Notify the stack that the fault array state of the given element has
+ *  changed.
+ *
+ *  This prompts the Health server on this element to publish the current fault
+ *  array if periodic publishing is disabled.
+ *
+ *  @param elem Element to update the fault state of.
+ *
+ *  @return 0 on success, or (negative) error code otherwise.
+ */
+int bt_mesh_fault_update(struct bt_mesh_elem *elem);
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct bt_mesh_model_op bt_mesh_health_srv_op[];
+extern const struct bt_mesh_model_cb bt_mesh_health_srv_cb;
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_HEALTH_SRV_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/main.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/main.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/main.h	(working copy)
@@ -0,0 +1,445 @@
+/** @file
+ *  @brief Bluetooth Mesh Profile APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_MAIN_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_MAIN_H_
+
+/**
+ * @brief Bluetooth Mesh Provisioning
+ * @defgroup bt_mesh_prov Bluetooth Mesh Provisioning
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Available Provisioning output authentication actions. */
+typedef enum {
+	BT_MESH_NO_OUTPUT       = 0,
+	BT_MESH_BLINK           = BIT(0),
+	BT_MESH_BEEP            = BIT(1),
+	BT_MESH_VIBRATE         = BIT(2),
+	BT_MESH_DISPLAY_NUMBER  = BIT(3),
+	BT_MESH_DISPLAY_STRING  = BIT(4),
+} bt_mesh_output_action_t;
+
+/** Available Provisioning input authentication actions. */
+typedef enum {
+	BT_MESH_NO_INPUT      = 0,
+	BT_MESH_PUSH          = BIT(0),
+	BT_MESH_TWIST         = BIT(1),
+	BT_MESH_ENTER_NUMBER  = BIT(2),
+	BT_MESH_ENTER_STRING  = BIT(3),
+} bt_mesh_input_action_t;
+
+/** Available Provisioning bearers. */
+typedef enum {
+	BT_MESH_PROV_ADV   = BIT(0),
+	BT_MESH_PROV_GATT  = BIT(1),
+} bt_mesh_prov_bearer_t;
+
+/** Out of Band information location. */
+typedef enum {
+	BT_MESH_PROV_OOB_OTHER     = BIT(0),
+	BT_MESH_PROV_OOB_URI       = BIT(1),
+	BT_MESH_PROV_OOB_2D_CODE   = BIT(2),
+	BT_MESH_PROV_OOB_BAR_CODE  = BIT(3),
+	BT_MESH_PROV_OOB_NFC       = BIT(4),
+	BT_MESH_PROV_OOB_NUMBER    = BIT(5),
+	BT_MESH_PROV_OOB_STRING    = BIT(6),
+	/* 7 - 10 are reserved */
+	BT_MESH_PROV_OOB_ON_BOX    = BIT(11),
+	BT_MESH_PROV_OOB_IN_BOX    = BIT(12),
+	BT_MESH_PROV_OOB_ON_PAPER  = BIT(13),
+	BT_MESH_PROV_OOB_IN_MANUAL = BIT(14),
+	BT_MESH_PROV_OOB_ON_DEV    = BIT(15),
+} bt_mesh_prov_oob_info_t;
+
+/** Provisioning properties & capabilities. */
+struct bt_mesh_prov {
+	/** The UUID that's used when advertising as unprovisioned */
+	const uint8_t *uuid;
+
+	/** Optional URI. This will be advertised separately from the
+	 *  unprovisioned beacon, however the unprovisioned beacon will
+	 *  contain a hash of it so the two can be associated by the
+	 *  provisioner.
+	 */
+	const char *uri;
+
+	/** Out of Band information field. */
+	bt_mesh_prov_oob_info_t oob_info;
+
+	/** Static OOB value */
+	const uint8_t *static_val;
+	/** Static OOB value length */
+	uint8_t        static_val_len;
+
+	/** Maximum size of Output OOB supported */
+	uint8_t        output_size;
+	/** Supported Output OOB Actions */
+	uint16_t       output_actions;
+
+	/** Maximum size of Input OOB supported */
+	uint8_t        input_size;
+	/** Supported Input OOB Actions */
+	uint16_t       input_actions;
+
+	/** @brief Output of a number is requested.
+	 *
+	 *  This callback notifies the application that it should
+	 *  output the given number using the given action.
+	 *
+	 *  @param act Action for outputting the number.
+	 *  @param num Number to be outputted.
+	 *
+	 *  @return Zero on success or negative error code otherwise
+	 */
+	int         (*output_number)(bt_mesh_output_action_t act, uint32_t num);
+
+	/** @brief Output of a string is requested.
+	 *
+	 *  This callback notifies the application that it should
+	 *  display the given string to the user.
+	 *
+	 *  @param str String to be displayed.
+	 *
+	 *  @return Zero on success or negative error code otherwise
+	 */
+	int         (*output_string)(const char *str);
+
+	/** @brief Input is requested.
+	 *
+	 *  This callback notifies the application that it should
+	 *  request input from the user using the given action. The
+	 *  requested input will either be a string or a number, and
+	 *  the application needs to consequently call the
+	 *  bt_mesh_input_string() or bt_mesh_input_number() functions
+	 *  once the data has been acquired from the user.
+	 *
+	 *  @param act Action for inputting data.
+	 *  @param num Maximum size of the inputted data.
+	 *
+	 *  @return Zero on success or negative error code otherwise
+	 */
+	int         (*input)(bt_mesh_input_action_t act, uint8_t size);
+
+	/** @brief The other device finished their OOB input.
+	 *
+	 *  This callback notifies the application that it should stop
+	 *  displaying its output OOB value, as the other party finished their
+	 *  OOB input.
+	 */
+	void 	    (*input_complete)(void);
+
+	/** @brief Unprovisioned beacon has been received.
+	 *
+	 *  This callback notifies the application that an unprovisioned
+	 *  beacon has been received.
+	 *
+	 *  @param uuid     UUID
+	 *  @param oob_info OOB Information
+	 *  @param uri_hash Pointer to URI Hash value. NULL if no hash was
+	 *                  present in the beacon.
+	 */
+	void        (*unprovisioned_beacon)(uint8_t uuid[16],
+					    bt_mesh_prov_oob_info_t oob_info,
+					    uint32_t *uri_hash);
+
+	/** @brief Provisioning link has been opened.
+	 *
+	 *  This callback notifies the application that a provisioning
+	 *  link has been opened on the given provisioning bearer.
+	 *
+	 *  @param bearer Provisioning bearer.
+	 */
+	void        (*link_open)(bt_mesh_prov_bearer_t bearer);
+
+	/** @brief Provisioning link has been closed.
+	 *
+	 *  This callback notifies the application that a provisioning
+	 *  link has been closed on the given provisioning bearer.
+	 *
+	 *  @param bearer Provisioning bearer.
+	 */
+	void        (*link_close)(bt_mesh_prov_bearer_t bearer);
+
+	/** @brief Provisioning is complete.
+	 *
+	 *  This callback notifies the application that provisioning has
+	 *  been successfully completed, and that the local node has been
+	 *  assigned the specified NetKeyIndex and primary element address.
+	 *
+	 *  @param net_idx NetKeyIndex given during provisioning.
+	 *  @param addr    Primary element address.
+	 */
+	void        (*complete)(uint16_t net_idx, uint16_t addr);
+
+	/** @brief A new node has been added to the provisioning database.
+	 *
+	 *  This callback notifies the application that provisioning has
+	 *  been successfully completed, and that a node has been assigned
+	 *  the specified NetKeyIndex and primary element address.
+	 *
+	 *  @param net_idx  NetKeyIndex given during provisioning.
+	 *  @param uuid     UUID of the added node
+	 *  @param addr     Primary element address.
+	 *  @param num_elem Number of elements that this node has.
+	 */
+	void        (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+				  uint8_t num_elem);
+
+	/** @brief Node has been reset.
+	 *
+	 *  This callback notifies the application that the local node
+	 *  has been reset and needs to be reprovisioned. The node will
+	 *  not automatically advertise as unprovisioned, rather the
+	 *  bt_mesh_prov_enable() API needs to be called to enable
+	 *  unprovisioned advertising on one or more provisioning bearers.
+	 */
+	void        (*reset)(void);
+};
+
+/** @brief Provide provisioning input OOB string.
+ *
+ *  This is intended to be called after the bt_mesh_prov input callback
+ *  has been called with BT_MESH_ENTER_STRING as the action.
+ *
+ *  @param str String.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_input_string(const char *str);
+
+/** @brief Provide provisioning input OOB number.
+ *
+ *  This is intended to be called after the bt_mesh_prov input callback
+ *  has been called with BT_MESH_ENTER_NUMBER as the action.
+ *
+ *  @param num Number.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_input_number(uint32_t num);
+
+/** @brief Enable specific provisioning bearers
+ *
+ *  Enable one or more provisioning bearers.
+ *
+ *  @param bearers Bit-wise or of provisioning bearers.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers);
+
+/** @brief Disable specific provisioning bearers
+ *
+ *  Disable one or more provisioning bearers.
+ *
+ *  @param bearers Bit-wise or of provisioning bearers.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
+
+/** @brief Provision the local Mesh Node.
+ *
+ *  This API should normally not be used directly by the application. The
+ *  only exception is for testing purposes where manual provisioning is
+ *  desired without an actual external provisioner.
+ *
+ *  @param net_key  Network Key
+ *  @param net_idx  Network Key Index
+ *  @param flags    Provisioning Flags
+ *  @param iv_index IV Index
+ *  @param addr     Primary element address
+ *  @param dev_key  Device Key
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
+		      uint8_t flags, uint32_t iv_index, uint16_t addr,
+		      const uint8_t dev_key[16]);
+
+/** @brief Provision a Mesh Node using PB-ADV
+ *
+ *  @param uuid               UUID
+ *  @param net_idx            Network Key Index
+ *  @param addr               Address to assign to remote device. If addr is 0,
+ *                            the lowest available address will be chosen.
+ *  @param attention_duration The attention duration to be send to remote device
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+			  uint8_t attention_duration);
+
+/** @brief Check if the local node has been provisioned.
+ *
+ *  This API can be used to check if the local node has been provisioned
+ *  or not. It can e.g. be helpful to determine if there was a stored
+ *  network in flash, i.e. if the network was restored after calling
+ *  settings_load().
+ *
+ *  @return True if the node is provisioned. False otherwise.
+ */
+bool bt_mesh_is_provisioned(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh Bluetooth Mesh
+ * @ingroup bluetooth
+ * @{
+ */
+
+/* Primary Network Key index */
+#define BT_MESH_NET_PRIMARY                 0x000
+
+#define BT_MESH_RELAY_DISABLED              0x00
+#define BT_MESH_RELAY_ENABLED               0x01
+#define BT_MESH_RELAY_NOT_SUPPORTED         0x02
+
+#define BT_MESH_BEACON_DISABLED             0x00
+#define BT_MESH_BEACON_ENABLED              0x01
+
+#define BT_MESH_GATT_PROXY_DISABLED         0x00
+#define BT_MESH_GATT_PROXY_ENABLED          0x01
+#define BT_MESH_GATT_PROXY_NOT_SUPPORTED    0x02
+
+#define BT_MESH_FRIEND_DISABLED             0x00
+#define BT_MESH_FRIEND_ENABLED              0x01
+#define BT_MESH_FRIEND_NOT_SUPPORTED        0x02
+
+#define BT_MESH_NODE_IDENTITY_STOPPED       0x00
+#define BT_MESH_NODE_IDENTITY_RUNNING       0x01
+#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02
+
+/* Features */
+#define BT_MESH_FEAT_RELAY                  BIT(0)
+#define BT_MESH_FEAT_PROXY                  BIT(1)
+#define BT_MESH_FEAT_FRIEND                 BIT(2)
+#define BT_MESH_FEAT_LOW_POWER              BIT(3)
+#define BT_MESH_FEAT_SUPPORTED              (BT_MESH_FEAT_RELAY |   \
+					     BT_MESH_FEAT_PROXY |   \
+					     BT_MESH_FEAT_FRIEND |  \
+					     BT_MESH_FEAT_LOW_POWER)
+
+/** @brief Initialize Mesh support
+ *
+ *  After calling this API, the node will not automatically advertise as
+ *  unprovisioned, rather the bt_mesh_prov_enable() API needs to be called
+ *  to enable unprovisioned advertising on one or more provisioning bearers.
+ *
+ *  @param prov Node provisioning information.
+ *  @param comp Node Composition.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_init(const struct bt_mesh_prov *prov,
+		 const struct bt_mesh_comp *comp);
+
+/** @brief Reset the state of the local Mesh node.
+ *
+ *  Resets the state of the node, which means that it needs to be
+ *  reprovisioned to become an active node in a Mesh network again.
+ *
+ *  After calling this API, the node will not automatically advertise as
+ *  unprovisioned, rather the bt_mesh_prov_enable() API needs to be called
+ *  to enable unprovisioned advertising on one or more provisioning bearers.
+ *
+ */
+void bt_mesh_reset(void);
+
+/** @brief Suspend the Mesh network temporarily.
+ *
+ *  This API can be used for power saving purposes, but the user should be
+ *  aware that leaving the local node suspended for a long period of time
+ *  may cause it to become permanently disconnected from the Mesh network.
+ *  If at all possible, the Friendship feature should be used instead, to
+ *  make the node into a Low Power Node.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_suspend(void);
+
+/** @brief Resume a suspended Mesh network.
+ *
+ *  This API resumes the local node, after it has been suspended using the
+ *  bt_mesh_suspend() API.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_resume(void);
+
+/** @brief Toggle the IV Update test mode
+ *
+ *  This API is only available if the IV Update test mode has been enabled
+ *  in Kconfig. It is needed for passing most of the IV Update qualification
+ *  test cases.
+ *
+ *  @param enable true to enable IV Update test mode, false to disable it.
+ */
+void bt_mesh_iv_update_test(bool enable);
+
+/** @brief Toggle the IV Update state
+ *
+ *  This API is only available if the IV Update test mode has been enabled
+ *  in Kconfig. It is needed for passing most of the IV Update qualification
+ *  test cases.
+ *
+ *  @return true if IV Update In Progress state was entered, false otherwise.
+ */
+bool bt_mesh_iv_update(void);
+
+/** @brief Toggle the Low Power feature of the local device
+ *
+ *  Enables or disables the Low Power feature of the local device. This is
+ *  exposed as a run-time feature, since the device might want to change
+ *  this e.g. based on being plugged into a stable power source or running
+ *  from a battery power source.
+ *
+ *  @param enable  true to enable LPN functionality, false to disable it.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_lpn_set(bool enable);
+
+/** @brief Send out a Friend Poll message.
+ *
+ *  Send a Friend Poll message to the Friend of this node. If there is no
+ *  established Friendship the function will return an error.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_lpn_poll(void);
+
+/** @brief Register a callback for Friendship changes.
+ *
+ *  Registers a callback that will be called whenever Friendship gets
+ *  established or is lost.
+ *
+ *  @param cb Function to call when the Friendship status changes.
+ */
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MAIN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/proxy.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/proxy.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/mesh/proxy.h	(working copy)
@@ -0,0 +1,42 @@
+/** @file
+ *  @brief Bluetooth Mesh Proxy APIs.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_PROXY_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_PROXY_H_
+
+/**
+ * @brief Bluetooth Mesh Proxy
+ * @defgroup bt_mesh_proxy Bluetooth Mesh Proxy
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Enable advertising with Node Identity.
+ *
+ *  This API requires that GATT Proxy support has been enabled. Once called
+ *  each subnet will start advertising using Node Identity for the next
+ *  60 seconds.
+ *
+ *  @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_proxy_identity_enable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_PROXY_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/rfcomm.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/rfcomm.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/rfcomm.h	(working copy)
@@ -0,0 +1,188 @@
+/** @file
+ *  @brief Bluetooth RFCOMM handling
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_RFCOMM_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_RFCOMM_H_
+
+/**
+ * @brief RFCOMM
+ * @defgroup bt_rfcomm RFCOMM
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <bluetooth/buf.h>
+#include <bluetooth/conn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* RFCOMM channels (1-30): pre-allocated for profiles to avoid conflicts */
+enum {
+	BT_RFCOMM_CHAN_HFP_HF = 1,
+	BT_RFCOMM_CHAN_HFP_AG,
+	BT_RFCOMM_CHAN_HSP_AG,
+	BT_RFCOMM_CHAN_HSP_HS,
+	BT_RFCOMM_CHAN_SPP,
+};
+
+struct bt_rfcomm_dlc;
+
+/** @brief RFCOMM DLC operations structure. */
+struct bt_rfcomm_dlc_ops {
+	/** DLC connected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  connection completes.
+	 *
+	 *  @param dlc The dlc that has been connected
+	 */
+	void (*connected)(struct bt_rfcomm_dlc *dlc);
+
+	/** DLC disconnected callback
+	 *
+	 *  If this callback is provided it will be called whenever the
+	 *  dlc is disconnected, including when a connection gets
+	 *  rejected or cancelled (both incoming and outgoing)
+	 *
+	 *  @param dlc The dlc that has been Disconnected
+	 */
+	void (*disconnected)(struct bt_rfcomm_dlc *dlc);
+
+	/** DLC recv callback
+	 *
+	 *  @param dlc The dlc receiving data.
+	 *  @param buf Buffer containing incoming data.
+	 */
+	void (*recv)(struct bt_rfcomm_dlc *dlc, struct net_buf *buf);
+};
+
+/** @brief Role of RFCOMM session and dlc. Used only by internal APIs
+ */
+typedef enum bt_rfcomm_role {
+	BT_RFCOMM_ROLE_ACCEPTOR,
+	BT_RFCOMM_ROLE_INITIATOR
+} __packed bt_rfcomm_role_t;
+
+/** @brief RFCOMM DLC structure. */
+struct bt_rfcomm_dlc {
+	/* Response Timeout eXpired (RTX) timer */
+	//struct k_delayed_work      rtx_work;
+
+	/* Queue for outgoing data */
+	struct k_fifo              tx_queue;
+
+	/* TX credits, Reuse as a binary sem for MSC FC if CFC is not enabled */
+	//struct k_sem               tx_credits;
+
+	struct bt_rfcomm_session  *session;
+	struct bt_rfcomm_dlc_ops  *ops;
+	struct bt_rfcomm_dlc      *_next;
+
+	bt_security_t              required_sec_level;
+	bt_rfcomm_role_t           role;
+
+	uint16_t                      mtu;
+	uint8_t                       dlci;
+	uint8_t                       state;
+	uint8_t                       rx_credit;
+
+	/* Stack & kernel data for TX thread */
+	//struct k_thread            tx_thread;
+	//K_KERNEL_STACK_MEMBER(stack, 256);
+};
+
+struct bt_rfcomm_server {
+	/** Server Channel */
+	uint8_t channel;
+
+	/** Server accept callback
+	 *
+	 *  This callback is called whenever a new incoming connection requires
+	 *  authorization.
+	 *
+	 *  @param conn The connection that is requesting authorization
+	 *  @param dlc Pointer to received the allocated dlc
+	 *
+	 *  @return 0 in case of success or negative value in case of error.
+	 */
+	int (*accept)(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc);
+
+	struct bt_rfcomm_server	*_next;
+};
+
+/** @brief Register RFCOMM server
+ *
+ *  Register RFCOMM server for a channel, each new connection is authorized
+ *  using the accept() callback which in case of success shall allocate the dlc
+ *  structure to be used by the new connection.
+ *
+ *  @param server Server structure.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_rfcomm_server_register(struct bt_rfcomm_server *server);
+
+/** @brief Connect RFCOMM channel
+ *
+ *  Connect RFCOMM dlc by channel, once the connection is completed dlc
+ *  connected() callback will be called. If the connection is rejected
+ *  disconnected() callback is called instead.
+ *
+ *  @param conn Connection object.
+ *  @param dlc Dlc object.
+ *  @param channel Server channel to connect to.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
+			  uint8_t channel);
+
+/** @brief Send data to RFCOMM
+ *
+ *  Send data from buffer to the dlc. Length should be less than or equal to
+ *  mtu.
+ *
+ *  @param dlc Dlc object.
+ *  @param buf Data buffer.
+ *
+ *  @return Bytes sent in case of success or negative value in case of error.
+ */
+int bt_rfcomm_dlc_send(struct bt_rfcomm_dlc *dlc, struct net_buf *buf);
+
+/** @brief Disconnect RFCOMM dlc
+ *
+ *  Disconnect RFCOMM dlc, if the connection is pending it will be
+ *  canceled and as a result the dlc disconnected() callback is called.
+ *
+ *  @param dlc Dlc object.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc);
+
+/** @brief Allocate the buffer from pool after reserving head room for RFCOMM,
+ *  L2CAP and ACL headers.
+ *
+ *  @param pool Which pool to take the buffer from.
+ *
+ *  @return New buffer.
+ */
+struct net_buf *bt_rfcomm_create_pdu(struct net_buf_pool *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_RFCOMM_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/sdp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/sdp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/sdp.h	(working copy)
@@ -0,0 +1,613 @@
+/** @file
+ *  @brief Service Discovery Protocol handling.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SDP_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_SDP_H_
+
+/**
+ * @brief Service Discovery Protocol (SDP)
+ * @defgroup bt_sdp Service Discovery Protocol (SDP)
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <bluetooth/uuid.h>
+#include <bluetooth/conn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * All definitions are based on Bluetooth Assigned Numbers
+ * of the Bluetooth Specification
+ */
+
+/*
+ * Service class identifiers of standard services and service groups
+ */
+#define BT_SDP_SDP_SERVER_SVCLASS           0x1000
+#define BT_SDP_BROWSE_GRP_DESC_SVCLASS      0x1001
+#define BT_SDP_PUBLIC_BROWSE_GROUP          0x1002
+#define BT_SDP_SERIAL_PORT_SVCLASS          0x1101
+#define BT_SDP_LAN_ACCESS_SVCLASS           0x1102
+#define BT_SDP_DIALUP_NET_SVCLASS           0x1103
+#define BT_SDP_IRMC_SYNC_SVCLASS            0x1104
+#define BT_SDP_OBEX_OBJPUSH_SVCLASS         0x1105
+#define BT_SDP_OBEX_FILETRANS_SVCLASS       0x1106
+#define BT_SDP_IRMC_SYNC_CMD_SVCLASS        0x1107
+#define BT_SDP_HEADSET_SVCLASS              0x1108
+#define BT_SDP_CORDLESS_TELEPHONY_SVCLASS   0x1109
+#define BT_SDP_AUDIO_SOURCE_SVCLASS         0x110a
+#define BT_SDP_AUDIO_SINK_SVCLASS           0x110b
+#define BT_SDP_AV_REMOTE_TARGET_SVCLASS     0x110c
+#define BT_SDP_ADVANCED_AUDIO_SVCLASS       0x110d
+#define BT_SDP_AV_REMOTE_SVCLASS            0x110e
+#define BT_SDP_AV_REMOTE_CONTROLLER_SVCLASS 0x110f
+#define BT_SDP_INTERCOM_SVCLASS             0x1110
+#define BT_SDP_FAX_SVCLASS                  0x1111
+#define BT_SDP_HEADSET_AGW_SVCLASS          0x1112
+#define BT_SDP_WAP_SVCLASS                  0x1113
+#define BT_SDP_WAP_CLIENT_SVCLASS           0x1114
+#define BT_SDP_PANU_SVCLASS                 0x1115
+#define BT_SDP_NAP_SVCLASS                  0x1116
+#define BT_SDP_GN_SVCLASS                   0x1117
+#define BT_SDP_DIRECT_PRINTING_SVCLASS      0x1118
+#define BT_SDP_REFERENCE_PRINTING_SVCLASS   0x1119
+#define BT_SDP_IMAGING_SVCLASS              0x111a
+#define BT_SDP_IMAGING_RESPONDER_SVCLASS    0x111b
+#define BT_SDP_IMAGING_ARCHIVE_SVCLASS      0x111c
+#define BT_SDP_IMAGING_REFOBJS_SVCLASS      0x111d
+#define BT_SDP_HANDSFREE_SVCLASS            0x111e
+#define BT_SDP_HANDSFREE_AGW_SVCLASS        0x111f
+#define BT_SDP_DIRECT_PRT_REFOBJS_SVCLASS   0x1120
+#define BT_SDP_REFLECTED_UI_SVCLASS         0x1121
+#define BT_SDP_BASIC_PRINTING_SVCLASS       0x1122
+#define BT_SDP_PRINTING_STATUS_SVCLASS      0x1123
+#define BT_SDP_HID_SVCLASS                  0x1124
+#define BT_SDP_HCR_SVCLASS                  0x1125
+#define BT_SDP_HCR_PRINT_SVCLASS            0x1126
+#define BT_SDP_HCR_SCAN_SVCLASS             0x1127
+#define BT_SDP_CIP_SVCLASS                  0x1128
+#define BT_SDP_VIDEO_CONF_GW_SVCLASS        0x1129
+#define BT_SDP_UDI_MT_SVCLASS               0x112a
+#define BT_SDP_UDI_TA_SVCLASS               0x112b
+#define BT_SDP_AV_SVCLASS                   0x112c
+#define BT_SDP_SAP_SVCLASS                  0x112d
+#define BT_SDP_PBAP_PCE_SVCLASS             0x112e
+#define BT_SDP_PBAP_PSE_SVCLASS             0x112f
+#define BT_SDP_PBAP_SVCLASS                 0x1130
+#define BT_SDP_MAP_MSE_SVCLASS              0x1132
+#define BT_SDP_MAP_MCE_SVCLASS              0x1133
+#define BT_SDP_MAP_SVCLASS                  0x1134
+#define BT_SDP_GNSS_SVCLASS                 0x1135
+#define BT_SDP_GNSS_SERVER_SVCLASS          0x1136
+#define BT_SDP_MPS_SC_SVCLASS               0x113a
+#define BT_SDP_MPS_SVCLASS                  0x113b
+#define BT_SDP_PNP_INFO_SVCLASS             0x1200
+#define BT_SDP_GENERIC_NETWORKING_SVCLASS   0x1201
+#define BT_SDP_GENERIC_FILETRANS_SVCLASS    0x1202
+#define BT_SDP_GENERIC_AUDIO_SVCLASS        0x1203
+#define BT_SDP_GENERIC_TELEPHONY_SVCLASS    0x1204
+#define BT_SDP_UPNP_SVCLASS                 0x1205
+#define BT_SDP_UPNP_IP_SVCLASS              0x1206
+#define BT_SDP_UPNP_PAN_SVCLASS             0x1300
+#define BT_SDP_UPNP_LAP_SVCLASS             0x1301
+#define BT_SDP_UPNP_L2CAP_SVCLASS           0x1302
+#define BT_SDP_VIDEO_SOURCE_SVCLASS         0x1303
+#define BT_SDP_VIDEO_SINK_SVCLASS           0x1304
+#define BT_SDP_VIDEO_DISTRIBUTION_SVCLASS   0x1305
+#define BT_SDP_HDP_SVCLASS                  0x1400
+#define BT_SDP_HDP_SOURCE_SVCLASS           0x1401
+#define BT_SDP_HDP_SINK_SVCLASS             0x1402
+#define BT_SDP_GENERIC_ACCESS_SVCLASS       0x1800
+#define BT_SDP_GENERIC_ATTRIB_SVCLASS       0x1801
+#define BT_SDP_APPLE_AGENT_SVCLASS          0x2112
+
+/*
+ * Attribute identifier codes
+ */
+#define BT_SDP_SERVER_RECORD_HANDLE 0x0000
+
+/*
+ * Possible values for attribute-id are listed below.
+ * See SDP Spec, section "Service Attribute Definitions" for more details.
+ */
+#define BT_SDP_ATTR_RECORD_HANDLE               0x0000
+#define BT_SDP_ATTR_SVCLASS_ID_LIST             0x0001
+#define BT_SDP_ATTR_RECORD_STATE                0x0002
+#define BT_SDP_ATTR_SERVICE_ID                  0x0003
+#define BT_SDP_ATTR_PROTO_DESC_LIST             0x0004
+#define BT_SDP_ATTR_BROWSE_GRP_LIST             0x0005
+#define BT_SDP_ATTR_LANG_BASE_ATTR_ID_LIST      0x0006
+#define BT_SDP_ATTR_SVCINFO_TTL                 0x0007
+#define BT_SDP_ATTR_SERVICE_AVAILABILITY        0x0008
+#define BT_SDP_ATTR_PROFILE_DESC_LIST           0x0009
+#define BT_SDP_ATTR_DOC_URL                     0x000a
+#define BT_SDP_ATTR_CLNT_EXEC_URL               0x000b
+#define BT_SDP_ATTR_ICON_URL                    0x000c
+#define BT_SDP_ATTR_ADD_PROTO_DESC_LIST         0x000d
+
+#define BT_SDP_ATTR_GROUP_ID                    0x0200
+#define BT_SDP_ATTR_IP_SUBNET                   0x0200
+#define BT_SDP_ATTR_VERSION_NUM_LIST            0x0200
+#define BT_SDP_ATTR_SUPPORTED_FEATURES_LIST     0x0200
+#define BT_SDP_ATTR_GOEP_L2CAP_PSM              0x0200
+#define BT_SDP_ATTR_SVCDB_STATE                 0x0201
+
+#define BT_SDP_ATTR_MPSD_SCENARIOS              0x0200
+#define BT_SDP_ATTR_MPMD_SCENARIOS              0x0201
+#define BT_SDP_ATTR_MPS_DEPENDENCIES            0x0202
+
+#define BT_SDP_ATTR_SERVICE_VERSION             0x0300
+#define BT_SDP_ATTR_EXTERNAL_NETWORK            0x0301
+#define BT_SDP_ATTR_SUPPORTED_DATA_STORES_LIST  0x0301
+#define BT_SDP_ATTR_DATA_EXCHANGE_SPEC          0x0301
+#define BT_SDP_ATTR_NETWORK                     0x0301
+#define BT_SDP_ATTR_FAX_CLASS1_SUPPORT          0x0302
+#define BT_SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302
+#define BT_SDP_ATTR_MCAP_SUPPORTED_PROCEDURES   0x0302
+#define BT_SDP_ATTR_FAX_CLASS20_SUPPORT         0x0303
+#define BT_SDP_ATTR_SUPPORTED_FORMATS_LIST      0x0303
+#define BT_SDP_ATTR_FAX_CLASS2_SUPPORT          0x0304
+#define BT_SDP_ATTR_AUDIO_FEEDBACK_SUPPORT      0x0305
+#define BT_SDP_ATTR_NETWORK_ADDRESS             0x0306
+#define BT_SDP_ATTR_WAP_GATEWAY                 0x0307
+#define BT_SDP_ATTR_HOMEPAGE_URL                0x0308
+#define BT_SDP_ATTR_WAP_STACK_TYPE              0x0309
+#define BT_SDP_ATTR_SECURITY_DESC               0x030a
+#define BT_SDP_ATTR_NET_ACCESS_TYPE             0x030b
+#define BT_SDP_ATTR_MAX_NET_ACCESSRATE          0x030c
+#define BT_SDP_ATTR_IP4_SUBNET                  0x030d
+#define BT_SDP_ATTR_IP6_SUBNET                  0x030e
+#define BT_SDP_ATTR_SUPPORTED_CAPABILITIES      0x0310
+#define BT_SDP_ATTR_SUPPORTED_FEATURES          0x0311
+#define BT_SDP_ATTR_SUPPORTED_FUNCTIONS         0x0312
+#define BT_SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313
+#define BT_SDP_ATTR_SUPPORTED_REPOSITORIES      0x0314
+#define BT_SDP_ATTR_MAS_INSTANCE_ID             0x0315
+#define BT_SDP_ATTR_SUPPORTED_MESSAGE_TYPES     0x0316
+#define BT_SDP_ATTR_PBAP_SUPPORTED_FEATURES     0x0317
+#define BT_SDP_ATTR_MAP_SUPPORTED_FEATURES      0x0317
+
+#define BT_SDP_ATTR_SPECIFICATION_ID            0x0200
+#define BT_SDP_ATTR_VENDOR_ID                   0x0201
+#define BT_SDP_ATTR_PRODUCT_ID                  0x0202
+#define BT_SDP_ATTR_VERSION                     0x0203
+#define BT_SDP_ATTR_PRIMARY_RECORD              0x0204
+#define BT_SDP_ATTR_VENDOR_ID_SOURCE            0x0205
+
+#define BT_SDP_ATTR_HID_DEVICE_RELEASE_NUMBER   0x0200
+#define BT_SDP_ATTR_HID_PARSER_VERSION          0x0201
+#define BT_SDP_ATTR_HID_DEVICE_SUBCLASS         0x0202
+#define BT_SDP_ATTR_HID_COUNTRY_CODE            0x0203
+#define BT_SDP_ATTR_HID_VIRTUAL_CABLE           0x0204
+#define BT_SDP_ATTR_HID_RECONNECT_INITIATE      0x0205
+#define BT_SDP_ATTR_HID_DESCRIPTOR_LIST         0x0206
+#define BT_SDP_ATTR_HID_LANG_ID_BASE_LIST       0x0207
+#define BT_SDP_ATTR_HID_SDP_DISABLE             0x0208
+#define BT_SDP_ATTR_HID_BATTERY_POWER           0x0209
+#define BT_SDP_ATTR_HID_REMOTE_WAKEUP           0x020a
+#define BT_SDP_ATTR_HID_PROFILE_VERSION         0x020b
+#define BT_SDP_ATTR_HID_SUPERVISION_TIMEOUT     0x020c
+#define BT_SDP_ATTR_HID_NORMALLY_CONNECTABLE    0x020d
+#define BT_SDP_ATTR_HID_BOOT_DEVICE             0x020e
+
+/*
+ * These identifiers are based on the SDP spec stating that
+ * "base attribute id of the primary (universal) language must be 0x0100"
+ *
+ * Other languages should have their own offset; e.g.:
+ * #define XXXLangBase yyyy
+ * #define AttrServiceName_XXX 0x0000+XXXLangBase
+ */
+#define BT_SDP_PRIMARY_LANG_BASE  0x0100
+
+#define BT_SDP_ATTR_SVCNAME_PRIMARY (0x0000 + BT_SDP_PRIMARY_LANG_BASE)
+#define BT_SDP_ATTR_SVCDESC_PRIMARY (0x0001 + BT_SDP_PRIMARY_LANG_BASE)
+#define BT_SDP_ATTR_PROVNAME_PRIMARY (0x0002 + BT_SDP_PRIMARY_LANG_BASE)
+
+/*
+ * The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec)
+ * These are the exact data type+size descriptor values
+ * that go into the PDU buffer.
+ *
+ * The datatype (leading 5bits) + size descriptor (last 3 bits)
+ * is 8 bits. The size descriptor is critical to extract the
+ * right number of bytes for the data value from the PDU.
+ *
+ * For most basic types, the datatype+size descriptor is
+ * straightforward. However for constructed types and strings,
+ * the size of the data is in the next "n" bytes following the
+ * 8 bits (datatype+size) descriptor. Exactly what the "n" is
+ * specified in the 3 bits of the data size descriptor.
+ *
+ * TextString and URLString can be of size 2^{8, 16, 32} bytes
+ * DataSequence and DataSequenceAlternates can be of size 2^{8, 16, 32}
+ * The size are computed post-facto in the API and are not known apriori
+ */
+#define BT_SDP_DATA_NIL        0x00
+#define BT_SDP_UINT8           0x08
+#define BT_SDP_UINT16          0x09
+#define BT_SDP_UINT32          0x0a
+#define BT_SDP_UINT64          0x0b
+#define BT_SDP_UINT128         0x0c
+#define BT_SDP_INT8            0x10
+#define BT_SDP_INT16           0x11
+#define BT_SDP_INT32           0x12
+#define BT_SDP_INT64           0x13
+#define BT_SDP_INT128          0x14
+#define BT_SDP_UUID_UNSPEC     0x18
+#define BT_SDP_UUID16          0x19
+#define BT_SDP_UUID32          0x1a
+#define BT_SDP_UUID128         0x1c
+#define BT_SDP_TEXT_STR_UNSPEC 0x20
+#define BT_SDP_TEXT_STR8       0x25
+#define BT_SDP_TEXT_STR16      0x26
+#define BT_SDP_TEXT_STR32      0x27
+#define BT_SDP_BOOL            0x28
+#define BT_SDP_SEQ_UNSPEC      0x30
+#define BT_SDP_SEQ8            0x35
+#define BT_SDP_SEQ16           0x36
+#define BT_SDP_SEQ32           0x37
+#define BT_SDP_ALT_UNSPEC      0x38
+#define BT_SDP_ALT8            0x3d
+#define BT_SDP_ALT16           0x3e
+#define BT_SDP_ALT32           0x3f
+#define BT_SDP_URL_STR_UNSPEC  0x40
+#define BT_SDP_URL_STR8        0x45
+#define BT_SDP_URL_STR16       0x46
+#define BT_SDP_URL_STR32       0x47
+
+#define BT_SDP_TYPE_DESC_MASK 0xf8
+#define BT_SDP_SIZE_DESC_MASK 0x07
+#define BT_SDP_SIZE_INDEX_OFFSET 5
+
+/** @brief SDP Generic Data Element Value. */
+struct bt_sdp_data_elem {
+	uint8_t        type;
+	uint32_t       data_size;
+	uint32_t       total_size;
+	const void *data;
+};
+
+/** @brief SDP Attribute Value. */
+struct bt_sdp_attribute {
+	uint16_t                id;  /* Attribute ID */
+	struct bt_sdp_data_elem val; /* Attribute data */
+};
+
+/** @brief SDP Service Record Value. */
+struct bt_sdp_record {
+	uint32_t                    handle;     /* Redundant, for quick ref */
+	struct bt_sdp_attribute *attrs;      /* Base addr of attr array */
+	size_t                   attr_count; /* Number of attributes */
+	uint8_t                     index;      /* Index of the record in LL */
+	struct bt_sdp_record    *next;
+};
+
+/*
+ * ---------------------------------------------------    ------------------
+ * | Service Hdl | Attr list ptr | Attr count | Next | -> | Service Hdl | ...
+ * ---------------------------------------------------    ------------------
+ */
+
+/** @def BT_SDP_ARRAY_8
+ *  @brief Declare an array of 8-bit elements in an attribute.
+ */
+#define BT_SDP_ARRAY_8(...) ((uint8_t[]) {__VA_ARGS__})
+
+/** @def BT_SDP_ARRAY_16
+ *  @brief Declare an array of 16-bit elements in an attribute.
+ */
+#define BT_SDP_ARRAY_16(...) ((uint16_t[]) {__VA_ARGS__})
+
+/** @def BT_SDP_ARRAY_32
+ *  @brief Declare an array of 32-bit elements in an attribute.
+ */
+#define BT_SDP_ARRAY_32(...) ((uint32_t[]) {__VA_ARGS__})
+
+/** @def BT_SDP_TYPE_SIZE
+ *  @brief Declare a fixed-size data element header.
+ *
+ *  @param _type Data element header containing type and size descriptors.
+ */
+#define BT_SDP_TYPE_SIZE(_type) .type = _type, \
+			.data_size = BIT(_type & BT_SDP_SIZE_DESC_MASK), \
+			.total_size = BIT(_type & BT_SDP_SIZE_DESC_MASK) + 1
+
+/** @def BT_SDP_TYPE_SIZE_VAR
+ *  @brief Declare a variable-size data element header.
+ *
+ *  @param _type Data element header containing type and size descriptors.
+ *  @param _size The actual size of the data.
+ */
+#define BT_SDP_TYPE_SIZE_VAR(_type, _size) .type = _type, \
+			.data_size = _size, \
+			.total_size = BIT((_type & BT_SDP_SIZE_DESC_MASK) - \
+					  BT_SDP_SIZE_INDEX_OFFSET) + _size + 1
+
+/** @def BT_SDP_DATA_ELEM_LIST
+ *  @brief Declare a list of data elements.
+ */
+#define BT_SDP_DATA_ELEM_LIST(...) ((struct bt_sdp_data_elem[]) {__VA_ARGS__})
+
+
+/** @def BT_SDP_NEW_SERVICE
+ *  @brief SDP New Service Record Declaration Macro.
+ *
+ *  Helper macro to declare a new service record.
+ *  Default attributes: Record Handle, Record State,
+ *  Language Base, Root Browse Group
+ *
+ */
+#define BT_SDP_NEW_SERVICE \
+{ \
+	BT_SDP_ATTR_RECORD_HANDLE, \
+	{ BT_SDP_TYPE_SIZE(BT_SDP_UINT32), BT_SDP_ARRAY_32(0) } \
+}, \
+{ \
+	BT_SDP_ATTR_RECORD_STATE, \
+	{ BT_SDP_TYPE_SIZE(BT_SDP_UINT32), BT_SDP_ARRAY_32(0) } \
+}, \
+{ \
+	BT_SDP_ATTR_LANG_BASE_ATTR_ID_LIST, \
+	{ BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 9), \
+	  BT_SDP_DATA_ELEM_LIST( \
+		{ BT_SDP_TYPE_SIZE(BT_SDP_UINT16), BT_SDP_ARRAY_8('n', 'e') }, \
+		{ BT_SDP_TYPE_SIZE(BT_SDP_UINT16), BT_SDP_ARRAY_16(106) }, \
+		{ BT_SDP_TYPE_SIZE(BT_SDP_UINT16), \
+			BT_SDP_ARRAY_16(BT_SDP_PRIMARY_LANG_BASE) } \
+	  ), \
+	} \
+}, \
+{ \
+	BT_SDP_ATTR_BROWSE_GRP_LIST, \
+	{ BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3), \
+	  BT_SDP_DATA_ELEM_LIST( \
+		{ BT_SDP_TYPE_SIZE(BT_SDP_UUID16), \
+			BT_SDP_ARRAY_16(BT_SDP_PUBLIC_BROWSE_GROUP) }, \
+	  ), \
+	} \
+}
+
+
+/** @def BT_SDP_LIST
+ *  @brief Generic SDP List Attribute Declaration Macro.
+ *
+ *  Helper macro to declare a list attribute.
+ *
+ *  @param _att_id List Attribute ID.
+ *  @param _data_elem_seq Data element sequence for the list.
+ *  @param _type_size SDP type and size descriptor.
+ */
+#define BT_SDP_LIST(_att_id, _type_size, _data_elem_seq) \
+{ \
+	_att_id, { _type_size, _data_elem_seq } \
+}
+
+/** @def BT_SDP_SERVICE_ID
+ *  @brief SDP Service ID Attribute Declaration Macro.
+ *
+ *  Helper macro to declare a service ID attribute.
+ *
+ *  @param _uuid Service ID 16bit UUID.
+ */
+#define BT_SDP_SERVICE_ID(_uuid) \
+{ \
+	BT_SDP_ATTR_SERVICE_ID, \
+	{ BT_SDP_TYPE_SIZE(BT_SDP_UUID16), &((struct bt_uuid_16) _uuid) } \
+}
+
+/** @def BT_SDP_SERVICE_NAME
+ *  @brief SDP Name Attribute Declaration Macro.
+ *
+ *  Helper macro to declare a service name attribute.
+ *
+ *  @param _name Service name as a string (up to 256 chars).
+ */
+#define BT_SDP_SERVICE_NAME(_name) \
+{ \
+	BT_SDP_ATTR_SVCNAME_PRIMARY, \
+	{ BT_SDP_TYPE_SIZE_VAR(BT_SDP_TEXT_STR8, (sizeof(_name)-1)), _name } \
+}
+
+/** @def BT_SDP_SUPPORTED_FEATURES
+ *  @brief SDP Supported Features Attribute Declaration Macro.
+ *
+ *  Helper macro to declare supported features of a profile/protocol.
+ *
+ *  @param _features Feature mask as 16bit unsigned integer.
+ */
+#define BT_SDP_SUPPORTED_FEATURES(_features) \
+{ \
+	BT_SDP_ATTR_SUPPORTED_FEATURES, \
+	{ BT_SDP_TYPE_SIZE(BT_SDP_UINT16), BT_SDP_ARRAY_16(_features) } \
+}
+
+/** @def BT_SDP_RECORD
+ *  @brief SDP Service Declaration Macro.
+ *
+ *  Helper macro to declare a service.
+ *
+ *  @param _attrs List of attributes for the service record.
+ */
+#define BT_SDP_RECORD(_attrs) \
+{ \
+	.attrs = _attrs, \
+	.attr_count = ARRAY_SIZE((_attrs)), \
+}
+
+/* Server API */
+
+/** @brief Register a Service Record.
+ *
+ *  Register a Service Record. Applications can make use of
+ *  macros such as BT_SDP_DECLARE_SERVICE, BT_SDP_LIST,
+ *  BT_SDP_SERVICE_ID, BT_SDP_SERVICE_NAME, etc.
+ *  A service declaration must start with BT_SDP_NEW_SERVICE.
+ *
+ *  @param service Service record declared using BT_SDP_DECLARE_SERVICE.
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+int bt_sdp_register_service(struct bt_sdp_record *service);
+
+/* Client API */
+
+/** @brief Generic SDP Client Query Result data holder */
+struct bt_sdp_client_result {
+	/* buffer containing unparsed SDP record result for given UUID */
+	struct net_buf        *resp_buf;
+	/* flag pointing that there are more result chunks for given UUID */
+	bool                   next_record_hint;
+	/* Reference to UUID object on behalf one discovery was started */
+	const struct bt_uuid  *uuid;
+};
+
+/** @brief Helper enum to be used as return value of bt_sdp_discover_func_t.
+ *  The value informs the caller to perform further pending actions or stop them.
+ */
+enum {
+	BT_SDP_DISCOVER_UUID_STOP = 0,
+	BT_SDP_DISCOVER_UUID_CONTINUE,
+};
+
+/** @typedef bt_sdp_discover_func_t
+ *
+ *  @brief Callback type reporting to user that there is a resolved result
+ *  on remote for given UUID and the result record buffer can be used by user
+ *  for further inspection.
+ *
+ *  A function of this type is given by the user to the bt_sdp_discover_params
+ *  object. It'll be called on each valid record discovery completion for given
+ *  UUID. When UUID resolution gives back no records then NULL is passed
+ *  to the user. Otherwise user can get valid record(s) and then the internal
+ *  hint 'next record' is set to false saying the UUID resolution is complete or
+ *  the hint can be set by caller to true meaning that next record is available
+ *  for given UUID.
+ *  The returned function value allows the user to control retrieving follow-up
+ *  resolved records if any. If the user doesn't want to read more resolved
+ *  records for given UUID since current record data fulfills its requirements
+ *  then should return BT_SDP_DISCOVER_UUID_STOP. Otherwise returned value means
+ *  more subcall iterations are allowable.
+ *
+ *  @param conn Connection object identifying connection to queried remote.
+ *  @param result Object pointing to logical unparsed SDP record collected on
+ *  base of response driven by given UUID.
+ *
+ *  @return BT_SDP_DISCOVER_UUID_STOP in case of no more need to read next
+ *  record data and continue discovery for given UUID. By returning
+ *  BT_SDP_DISCOVER_UUID_CONTINUE user allows this discovery continuation.
+ */
+typedef uint8_t (*bt_sdp_discover_func_t)
+		(struct bt_conn *conn, struct bt_sdp_client_result *result);
+
+/** @brief Main user structure used in SDP discovery of remote. */
+struct bt_sdp_discover_params {
+	sys_snode_t		_node;
+	/** UUID (service) to be discovered on remote SDP entity */
+	const struct bt_uuid   *uuid;
+	/** Discover callback to be called on resolved SDP record */
+	bt_sdp_discover_func_t  func;
+	/** Memory buffer enabled by user for SDP query results  */
+	struct net_buf_pool    *pool;
+};
+
+/** @brief Allows user to start SDP discovery session.
+ *
+ *  The function performs SDP service discovery on remote server driven by user
+ *  delivered discovery parameters. Discovery session is made as soon as
+ *  no SDP transaction is ongoing between peers and if any then this one
+ *  is queued to be processed at discovery completion of previous one.
+ *  On the service discovery completion the callback function will be
+ *  called to get feedback to user about findings.
+ *
+ * @param conn Object identifying connection to remote.
+ * @param params SDP discovery parameters.
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+
+int bt_sdp_discover(struct bt_conn *conn,
+		    const struct bt_sdp_discover_params *params);
+
+/** @brief Release waiting SDP discovery request.
+ *
+ *  It can cancel valid waiting SDP client request identified by SDP discovery
+ *  parameters object.
+ *
+ * @param conn Object identifying connection to remote.
+ * @param params SDP discovery parameters.
+ *
+ * @return 0 in case of success or negative value in case of error.
+ */
+int bt_sdp_discover_cancel(struct bt_conn *conn,
+			   const struct bt_sdp_discover_params *params);
+
+
+/* Helper types & functions for SDP client to get essential data from server */
+
+/** @brief Protocols to be asked about specific parameters */
+enum bt_sdp_proto {
+	BT_SDP_PROTO_RFCOMM = 0x0003,
+	BT_SDP_PROTO_L2CAP  = 0x0100,
+};
+
+/** @brief Give to user parameter value related to given stacked protocol UUID.
+ *
+ *  API extracts specific parameter associated with given protocol UUID
+ *  available in Protocol Descriptor List attribute.
+ *
+ *  @param buf Original buffered raw record data.
+ *  @param proto Known protocol to be checked like RFCOMM or L2CAP.
+ *  @param param On success populated by found parameter value.
+ *
+ *  @return 0 on success when specific parameter associated with given protocol
+ *  value is found, or negative if error occurred during processing.
+ */
+int bt_sdp_get_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
+			   uint16_t *param);
+
+/** @brief Get profile version.
+ *
+ *  Helper API extracting remote profile version number. To get it proper
+ *  generic profile parameter needs to be selected usually listed in SDP
+ *  Interoperability Requirements section for given profile specification.
+ *
+ *  @param buf Original buffered raw record data.
+ *  @param profile Profile family identifier the profile belongs.
+ *  @param version On success populated by found version number.
+ *
+ *  @return 0 on success, negative value if error occurred during processing.
+ */
+int bt_sdp_get_profile_version(const struct net_buf *buf, uint16_t profile,
+			       uint16_t *version);
+
+/** @brief Get SupportedFeatures attribute value
+ *
+ *  Allows if exposed by remote retrieve SupportedFeature attribute.
+ *
+ *  @param buf Buffer holding original raw record data from remote.
+ *  @param features On success object to be populated with SupportedFeature
+ *  mask.
+ *
+ *  @return 0 on success if feature found and valid, negative in case any error
+ */
+int bt_sdp_get_features(const struct net_buf *buf, uint16_t *features);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SDP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/services/bas.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/bas.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/bas.h	(working copy)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_BAS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_BAS_H_
+
+/**
+ * @brief Battery Service (BAS)
+ * @defgroup bt_bas Battery Service (BAS)
+ * @ingroup bluetooth
+ * @{
+ *
+ * [Experimental] Users should note that the APIs can change
+ * as a part of ongoing development.
+ */
+
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Read battery level value.
+ *
+ * Read the characteristic value of the battery level
+ *
+ *  @return The battery level in percent.
+ */
+uint8_t bt_bas_get_battery_level(void);
+
+/** @brief Update battery level value.
+ *
+ * Update the characteristic value of the battery level
+ * This will send a GATT notification to all current subscribers.
+ *
+ *  @param level The battery level in percent.
+ *
+ *  @return Zero in case of success and error code in case of error.
+ */
+int bt_bas_set_battery_level(uint8_t level);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_BAS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/services/dis.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/dis.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/dis.h	(working copy)
@@ -0,0 +1,18 @@
+/** @file
+ *  @brief GATT Device Information Service
+ */
+
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/services/hrs.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/hrs.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/hrs.h	(working copy)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_
+
+/**
+ * @brief Heart Rate Service (HRS)
+ * @defgroup bt_hrs Heart Rate Service (HRS)
+ * @ingroup bluetooth
+ * @{
+ *
+ * [Experimental] Users should note that the APIs can change
+ * as a part of ongoing development.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Notify heart rate measurement.
+ *
+ * This will send a GATT notification to all current subscribers.
+ *
+ *  @param heartrate The heartrate measurement in beats per minute.
+ *
+ *  @return Zero in case of success and error code in case of error.
+ */
+int bt_hrs_notify(uint16_t heartrate);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/services/ots.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/ots.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/services/ots.h	(working copy)
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_OTS_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_OTS_H_
+
+/**
+ * @brief Object Transfer Service (OTS)
+ * @defgroup bt_ots Object Transfer Service (OTS)
+ * @ingroup bluetooth
+ * @{
+ *
+ * [Experimental] Users should note that the APIs can change
+ * as a part of ongoing development.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+
+/** @brief Size of OTS object ID (in bytes). */
+#define BT_OTS_OBJ_ID_SIZE 6
+
+/** @brief Length of OTS object ID string (in bytes). */
+#define BT_OTS_OBJ_ID_STR_LEN 15
+
+/** @brief Type of an OTS object. */
+struct bt_ots_obj_type {
+	union {
+		/* Used to indicate UUID type */
+		struct bt_uuid uuid;
+
+		/* 16-bit UUID value */
+		struct bt_uuid_16 uuid_16;
+
+		/* 128-bit UUID value */
+		struct bt_uuid_128 uuid_128;
+	};
+};
+
+/** @brief Properties of an OTS object. */
+enum {
+	/** Bit 0 Deletion of this object is permitted */
+	BT_OTS_OBJ_PROP_DELETE    = 0,
+
+	/** Bit 1 Execution of this object is permitted */
+	BT_OTS_OBJ_PROP_EXECUTE   = 1,
+
+	/** Bit 2 Reading this object is permitted */
+	BT_OTS_OBJ_PROP_READ      = 2,
+
+	/** Bit 3 Writing data to this object is permitted */
+	BT_OTS_OBJ_PROP_WRITE     = 3,
+
+	/** @brief Bit 4 Appending data to this object is permitted.
+	 *
+	 * Appending data increases its Allocated Size.
+	 */
+	BT_OTS_OBJ_PROP_APPEND    = 4,
+
+	/** Bit 5 Truncation of this object is permitted */
+	BT_OTS_OBJ_PROP_TRUNCATE  = 5,
+
+	/** @brief Bit 6 Patching this object is permitted
+	 *
+	 *  Patching this object overwrites some of
+	 *  the object's existing contents.
+	 */
+	BT_OTS_OBJ_PROP_PATCH     = 6,
+
+	/** Bit 7 This object is a marked object */
+	BT_OTS_OBJ_PROP_MARKED    = 7,
+};
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_DELETE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_DELETE(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_DELETE, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_EXECUTE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_EXECUTE(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_EXECUTE, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_READ property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_READ(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_READ, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_WRITE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_WRITE(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_WRITE, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_APPEND property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_APPEND(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_APPEND, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_TRUNCATE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_TRUNCATE(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_TRUNCATE, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_PROP_PATCH property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_PATCH(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_PATCH, 1)
+
+/** @brief Set @ref BT_OTS_OBJ_SET_PROP_MARKED property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_SET_PROP_MARKED(prop) \
+	WRITE_BIT(prop, BT_OTS_OBJ_PROP_MARKED, 1)
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_DELETE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_DELETE(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_DELETE))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_EXECUTE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_EXECUTE(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_EXECUTE))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_READ property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_READ(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_READ))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_WRITE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_WRITE(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_WRITE))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_APPEND property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_APPEND(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_APPEND))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_TRUNCATE property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_TRUNCATE(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_TRUNCATE))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_PATCH property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_PATCH(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_PATCH))
+
+/** @brief Get @ref BT_OTS_OBJ_PROP_MARKED property.
+ *
+ *  @param prop Object properties.
+ */
+#define BT_OTS_OBJ_GET_PROP_MARKED(prop) \
+	((prop) & BIT(BT_OTS_OBJ_PROP_MARKED))
+
+/** @brief Descriptor for OTS Object Size parameter. */
+struct bt_ots_obj_size {
+	/* Current Size */
+	uint32_t cur;
+
+	/* Allocated Size */
+	uint32_t alloc;
+} __packed;
+
+/** @brief Descriptor for OTS object initialization. */
+struct bt_ots_obj_metadata {
+	/* Object Name */
+	char                   *name;
+
+	/* Object Type */
+	struct bt_ots_obj_type type;
+
+	/* Object Size */
+	struct bt_ots_obj_size size;
+
+	/* Object Properties */
+	uint32_t               props;
+};
+
+/** @brief Object Action Control Point Feature bits. */
+enum {
+	/** Bit 0 OACP Create Op Code Supported */
+	BT_OTS_OACP_FEAT_CREATE     = 0,
+
+	/** Bit 1 OACP Delete Op Code Supported  */
+	BT_OTS_OACP_FEAT_DELETE     = 1,
+
+	/** Bit 2 OACP Calculate Checksum Op Code Supported */
+	BT_OTS_OACP_FEAT_CHECKSUM   = 2,
+
+	/** Bit 3 OACP Execute Op Code Supported */
+	BT_OTS_OACP_FEAT_EXECUTE    = 3,
+
+	/** Bit 4 OACP Read Op Code Supported */
+	BT_OTS_OACP_FEAT_READ       = 4,
+
+	/** Bit 5 OACP Write Op Code Supported */
+	BT_OTS_OACP_FEAT_WRITE      = 5,
+
+	/** Bit 6 Appending Additional Data to Objects Supported  */
+	BT_OTS_OACP_FEAT_APPEND     = 6,
+
+	/** Bit 7 Truncation of Objects Supported */
+	BT_OTS_OACP_FEAT_TRUNCATE   = 7,
+
+	/** Bit 8 Patching of Objects Supported  */
+	BT_OTS_OACP_FEAT_PATCH      = 8,
+
+	/** Bit 9 OACP Abort Op Code Supported */
+	BT_OTS_OACP_FEAT_ABORT      = 9,
+};
+
+/** @brief Set @ref BT_OTS_OACP_SET_FEAT_CREATE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_CREATE(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_CREATE, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_DELETE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_DELETE(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_DELETE, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_CHECKSUM feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_CHECKSUM(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_CHECKSUM, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_EXECUTE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_EXECUTE(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_EXECUTE, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_READ feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_READ(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_READ, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_WRITE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_WRITE(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_WRITE, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_APPEND feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_APPEND(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_APPEND, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_TRUNCATE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_TRUNCATE(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_TRUNCATE, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_PATCH feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_PATCH(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_PATCH, 1)
+
+/** @brief Set @ref BT_OTS_OACP_FEAT_ABORT feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_SET_FEAT_ABORT(feat) \
+	WRITE_BIT(feat, BT_OTS_OACP_FEAT_ABORT, 1)
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_CREATE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_CREATE(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_CREATE))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_DELETE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_DELETE(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_DELETE))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_CHECKSUM feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_CHECKSUM(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_CHECKSUM))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_EXECUTE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_EXECUTE(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_EXECUTE))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_READ feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_READ(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_READ))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_WRITE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_WRITE(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_WRITE))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_APPEND feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_APPEND(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_APPEND))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_TRUNCATE feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_TRUNCATE(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_TRUNCATE))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_PATCH feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_PATCH(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_PATCH))
+
+/** @brief Get @ref BT_OTS_OACP_FEAT_ABORT feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OACP_GET_FEAT_ABORT(feat) \
+	((feat) & BIT(BT_OTS_OACP_FEAT_ABORT))
+
+/** @brief Object List Control Point Feature bits. */
+enum {
+	/** Bit 0 OLCP Go To Op Code Supported */
+	BT_OTS_OLCP_FEAT_GO_TO      = 0,
+
+	/** Bit 1 OLCP Order Op Code Supported */
+	BT_OTS_OLCP_FEAT_ORDER      = 1,
+
+	/** Bit 2 OLCP Request Number of Objects Op Code Supported */
+	BT_OTS_OLCP_FEAT_NUM_REQ    = 2,
+
+	/** Bit 3 OLCP Clear Marking Op Code Supported*/
+	BT_OTS_OLCP_FEAT_CLEAR      = 3,
+};
+
+/** @brief Set @ref BT_OTS_OLCP_FEAT_GO_TO feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_SET_FEAT_GO_TO(feat) \
+	WRITE_BIT(feat, BT_OTS_OLCP_FEAT_GO_TO, 1)
+
+/** @brief Set @ref BT_OTS_OLCP_FEAT_ORDER feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_SET_FEAT_ORDER(feat) \
+	WRITE_BIT(feat, BT_OTS_OLCP_FEAT_ORDER, 1)
+
+/** @brief Set @ref BT_OTS_OLCP_FEAT_NUM_REQ feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_SET_FEAT_NUM_REQ(feat) \
+	WRITE_BIT(feat, BT_OTS_OLCP_FEAT_NUM_REQ, 1)
+
+/** @brief Set @ref BT_OTS_OLCP_FEAT_CLEAR feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_SET_FEAT_CLEAR(feat) \
+	WRITE_BIT(feat, BT_OTS_OLCP_FEAT_CLEAR, 1)
+
+/** @brief Get @ref BT_OTS_OLCP_GET_FEAT_GO_TO feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_GET_FEAT_GO_TO(feat) \
+	((feat) & BIT(BT_OTS_OLCP_FEAT_GO_TO))
+
+/** @brief Get @ref BT_OTS_OLCP_GET_FEAT_ORDER feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_GET_FEAT_ORDER(feat) \
+	((feat) & BIT(BT_OTS_OLCP_FEAT_ORDER))
+
+/** @brief Get @ref BT_OTS_OLCP_GET_FEAT_NUM_REQ feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_GET_FEAT_NUM_REQ(feat) \
+	((feat) & BIT(BT_OTS_OLCP_FEAT_NUM_REQ))
+
+/** @brief Get @ref BT_OTS_OLCP_GET_FEAT_CLEAR feature.
+ *
+ *  @param feat OTS features.
+ */
+#define BT_OTS_OLCP_GET_FEAT_CLEAR(feat) \
+	((feat) & BIT(BT_OTS_OLCP_FEAT_CLEAR))
+
+/**@brief Features of the OTS. */
+struct bt_ots_feat {
+	/* OACP Features */
+	uint32_t oacp;
+
+	/* OLCP Features */
+	uint32_t olcp;
+} __packed;
+
+/** @brief Opaque OTS instance. */
+struct bt_ots;
+
+/** @brief OTS callback structure. */
+struct bt_ots_cb {
+	/** @brief Object created callback
+	 *
+	 *  This callback is called whenever a new object is created.
+	 *  Application can reject this request by returning an error
+	 *  when it does not have necessary resources to hold this new
+	 *  object. This callback is also triggered when the server
+	 *  creates a new object with bt_ots_obj_add() API.
+	 *
+	 *  @param ots  OTS instance.
+	 *  @param conn The connection that is requesting object creation or
+	 *              NULL if object is created by the following function:
+	 *              bt_ots_obj_add().
+	 *  @param id   Object ID.
+	 *  @param init Object initialization metadata.
+	 *
+	 *  @return 0 in case of success or negative value in case of error.
+	 *  Possible return values:
+	 *  -ENOMEM if no available space for new object.
+	 */
+	int (*obj_created)(struct bt_ots *ots, struct bt_conn *conn,
+			   uint64_t id,
+			   const struct bt_ots_obj_metadata *init);
+
+	/** @brief Object deleted callback
+	 *
+	 *  This callback is called whenever an object is deleted. It is
+	 *  also triggered when the server deletes an object with
+	 *  bt_ots_obj_delete() API.
+	 *
+	 *  @param ots  OTS instance.
+	 *  @param conn The connection that deleted the object or NULL if
+	 *              this request came from the server.
+	 *  @param id   Object ID.
+	 */
+	void (*obj_deleted)(struct bt_ots *ots, struct bt_conn *conn,
+			    uint64_t id);
+
+	/** @brief Object selected callback
+	 *
+	 *  This callback is called on successful object selection.
+	 *
+	 *  @param ots  OTS instance.
+	 *  @param conn The connection that selected new object.
+	 *  @param id   Object ID.
+	 */
+	void (*obj_selected)(struct bt_ots *ots, struct bt_conn *conn,
+			     uint64_t id);
+
+	/** @brief Object read callback
+	 *
+	 *  This callback is called multiple times during the Object read
+	 *  operation. OTS module will keep requesting successive Object
+	 *  fragments from the application until the read operation is
+	 *  completed. The end of read operation is indicated by NULL data
+	 *  parameter.
+	 *
+	 *  @param ots    OTS instance.
+	 *  @param conn   The connection that read object.
+	 *  @param id     Object ID.
+	 *  @param data   In:  NULL once the read operations is completed.
+	 *                Out: Next chunk of data to be sent.
+	 *  @param len    Remaining length requested by the client.
+	 *  @param offset Object data offset.
+	 *
+	 *  @return Data length to be sent via data parameter. This value
+	 *          shall be smaller or equal to the len parameter.
+	 */
+	uint32_t (*obj_read)(struct bt_ots *ots, struct bt_conn *conn,
+			     uint64_t id, uint8_t **data, uint32_t len,
+			     uint32_t offset);
+};
+
+/** @brief Descriptor for OTS initialization. */
+struct bt_ots_init {
+	/* OTS features */
+	struct bt_ots_feat features;
+
+	/* Callbacks */
+	struct bt_ots_cb *cb;
+};
+
+/** @brief Add an object to the OTS instance.
+ *
+ *  This function adds an object to the OTS database. When the
+ *  object is being added, a callback obj_created() is called
+ *  to notify the user about a new object ID.
+ *
+ *  @param ots      OTS instance.
+ *  @param obj_init Meta data of the object.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_ots_obj_add(struct bt_ots *ots, struct bt_ots_obj_metadata *obj_init);
+
+/** @brief Delete an object from the OTS instance.
+ *
+ *  This function deletes an object from the OTS database. When the
+ *  object is deleted a callback obj_deleted() is called
+ *  to notify the user about this event. At this point, it is possible
+ *  to free allocated buffer for object data.
+ *
+ *  @param ots OTS instance.
+ *  @param id  ID of the object to be deleted (uint48).
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_ots_obj_delete(struct bt_ots *ots, uint64_t id);
+
+/** @brief Get the service declaration attribute.
+ *
+ *  This function is enabled for CONFIG_BT_OTS_SECONDARY_SVC configuration.
+ *  The first service attribute can be included in any other GATT service.
+ *
+ *  @param ots OTS instance.
+ *
+ *  @return The first OTS attribute instance.
+ */
+void *bt_ots_svc_decl_get(struct bt_ots *ots);
+
+/** @brief Initialize the OTS instance.
+ *
+ *  @param ots      OTS instance.
+ *  @param ots_init OTS initialization descriptor.
+ *
+ *  @return 0 in case of success or negative value in case of error.
+ */
+int bt_ots_init(struct bt_ots *ots, struct bt_ots_init *ots_init);
+
+/** @brief Get a free instance of OTS from the pool.
+ *
+ *  @return OTS instance in case of success or NULL in case of error.
+ */
+struct bt_ots *bt_ots_free_instance_get(void);
+
+/** @brief Converts binary OTS Object ID to string.
+ *
+ *  @param obj_id Object ID.
+ *  @param str    Address of user buffer with enough room to store
+ *                formatted string containing binary Object ID.
+ *  @param len    Length of data to be copied to user string buffer.
+ *                Refer to BT_OTS_OBJ_ID_STR_LEN about
+ *                recommended value.
+ *
+ *  @return Number of successfully formatted bytes from binary ID.
+ */
+static inline int bt_ots_obj_id_to_str(uint64_t obj_id, char *str, size_t len)
+{
+	uint8_t id[6];
+
+	sys_put_le48(obj_id, id);
+
+	return snprintk(str, len, "0x%02X%02X%02X%02X%02X%02X",
+			id[5], id[4], id[3], id[2], id[1], id[0]);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_OTS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/testing.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/testing.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/testing.h	(working copy)
@@ -0,0 +1,99 @@
+/**
+ * @file testing.h
+ * @brief Internal API for Bluetooth testing.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_
+
+#if defined(CONFIG_BT_MESH)
+#include <bluetooth/mesh.h>
+#endif /* CONFIG_BT_MESH */
+
+/**
+ * @brief Bluetooth testing
+ * @defgroup bt_test_cb Bluetooth testing callbacks
+ * @ingroup bluetooth
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Bluetooth Testing callbacks structure.
+ *
+ *  Callback structure to be used for Bluetooth testing purposes.
+ *  Allows access to Bluetooth stack internals, not exposed by public API.
+ */
+struct bt_test_cb {
+#if defined(CONFIG_BT_MESH)
+	void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
+			      const void *payload, size_t payload_len);
+	void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model,
+				 uint16_t key_idx);
+	void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model,
+				   uint16_t key_idx);
+	void (*mesh_prov_invalid_bearer)(uint8_t opcode);
+	void (*mesh_trans_incomp_timer_exp)(void);
+#endif /* CONFIG_BT_MESH */
+
+	sys_snode_t node;
+};
+
+/** Register callbacks for Bluetooth testing purposes
+ *
+ *  @param cb bt_test_cb callback structure
+ */
+void bt_test_cb_register(struct bt_test_cb *cb);
+
+/** Unregister callbacks for Bluetooth testing purposes
+ *
+ *  @param cb bt_test_cb callback structure
+ */
+void bt_test_cb_unregister(struct bt_test_cb *cb);
+
+/** Send Friend Subscription List Add message.
+ *
+ *  Used by Low Power node to send the group address for which messages are to
+ *  be stored by Friend node.
+ *
+ *  @param group Group address
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_test_mesh_lpn_group_add(uint16_t group);
+
+/** Send Friend Subscription List Remove message.
+ *
+ *  Used by Low Power node to remove the group addresses from Friend node
+ *  subscription list. Messages sent to those addresses will not be stored
+ *  by Friend node.
+ *
+ *  @param groups Group addresses
+ *  @param groups_count Group addresses count
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count);
+
+/** Clear replay protection list cache.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int bt_test_mesh_rpl_clear(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_TESTING_H_ */
Index: ModuleDemo/BLE/CM0/User/include/bluetooth/uuid.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/uuid.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/bluetooth/uuid.h	(working copy)
@@ -0,0 +1,1223 @@
+/** @file
+ *  @brief Bluetooth UUID handling
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_BLUETOOTH_UUID_H_
+#define ZEPHYR_INCLUDE_BLUETOOTH_UUID_H_
+
+/**
+ * @brief UUIDs
+ * @defgroup bt_uuid UUIDs
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <sys/util.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Bluetooth UUID types */
+enum {
+	BT_UUID_TYPE_16,
+	BT_UUID_TYPE_32,
+	BT_UUID_TYPE_128,
+};
+
+/** @brief This is a 'tentative' type and should be used as a pointer only */
+struct bt_uuid {
+	uint8_t type;
+};
+
+struct bt_uuid_16 {
+	struct bt_uuid uuid;
+	uint16_t val;
+};
+
+struct bt_uuid_32 {
+	struct bt_uuid uuid;
+	uint32_t val;
+};
+
+struct bt_uuid_128 {
+	struct bt_uuid uuid;
+	uint8_t val[16];
+};
+
+#define BT_UUID_INIT_16(value)		\
+{					\
+	.uuid = { BT_UUID_TYPE_16 },	\
+	.val = (value),			\
+}
+
+#define BT_UUID_INIT_32(value)		\
+{					\
+	.uuid = { BT_UUID_TYPE_32 },	\
+	.val = (value),			\
+}
+
+#define BT_UUID_INIT_128(value...)	\
+{					\
+	.uuid = { BT_UUID_TYPE_128 },	\
+	.val = { value },		\
+}
+
+#define BT_UUID_DECLARE_16(value) \
+	((struct bt_uuid *) ((struct bt_uuid_16[]) {BT_UUID_INIT_16(value)}))
+#define BT_UUID_DECLARE_32(value) \
+	((struct bt_uuid *) ((struct bt_uuid_32[]) {BT_UUID_INIT_32(value)}))
+#define BT_UUID_DECLARE_128(value...) \
+	((struct bt_uuid *) ((struct bt_uuid_128[]) {BT_UUID_INIT_128(value)}))
+
+#define BT_UUID_16(__u) CONTAINER_OF(__u, struct bt_uuid_16, uuid)
+#define BT_UUID_32(__u) CONTAINER_OF(__u, struct bt_uuid_32, uuid)
+#define BT_UUID_128(__u) CONTAINER_OF(__u, struct bt_uuid_128, uuid)
+
+/** @brief Encode 128 bit UUID into an array values
+ *
+ *  Helper macro to initialize a 128-bit UUID value from the UUID format.
+ *  Can be combined with BT_UUID_DECLARE_128 to declare a 128-bit UUID from
+ *  the readable form of UUIDs.
+ *
+ *  Example for how to declare the UUID `6E400001-B5A3-F393-E0A9-E50E24DCCA9E`
+ *
+ *  @code
+ *  BT_UUID_DECLARE_128(
+ *       BT_UUID_128_ENCODE(0x6E400001, 0xB5A3, 0xF393, 0xE0A9, 0xE50E24DCCA9E))
+ *  @endcode
+ *
+ *  Just replace the hyphen by the comma and add `0x` prefixes.
+ *
+ *  @param w32 First part of the UUID (32 bits)
+ *  @param w1  Second part of the UUID (16 bits)
+ *  @param w2  Third part of the UUID (16 bits)
+ *  @param w3  Fourth part of the UUID (16 bits)
+ *  @param w48 Fifth part of the UUID (48 bits)
+ *
+ *  @return The comma separated values for UUID 128 initializer that
+ *          may be used directly as an argument for
+ *          @ref BT_UUID_INIT_128 or @ref BT_UUID_DECLARE_128
+ */
+#define BT_UUID_128_ENCODE(w32, w1, w2, w3, w48) \
+	(((w48) >>  0) & 0xFF), \
+	(((w48) >>  8) & 0xFF), \
+	(((w48) >> 16) & 0xFF), \
+	(((w48) >> 24) & 0xFF), \
+	(((w48) >> 32) & 0xFF), \
+	(((w48) >> 40) & 0xFF), \
+	(((w3)  >>  0) & 0xFF), \
+	(((w3)  >>  8) & 0xFF), \
+	(((w2)  >>  0) & 0xFF), \
+	(((w2)  >>  8) & 0xFF), \
+	(((w1)  >>  0) & 0xFF), \
+	(((w1)  >>  8) & 0xFF), \
+	(((w32) >>  0) & 0xFF), \
+	(((w32) >>  8) & 0xFF), \
+	(((w32) >> 16) & 0xFF), \
+	(((w32) >> 24) & 0xFF)
+
+/** @brief Encode 16 bit UUID into an array values
+ *
+ *  Helper macro to encode 16-bit UUID values into advertising data.
+ *
+ *  Example for how to declare the UUID `0x180a`
+ *
+ *  @code
+ *  BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(0x180a),
+ *  @endcode
+ *
+ * @param w16 UUID value (16-bits)
+ *
+ * @return The comma separated values for UUID 16 value that
+ *         may be used directly as an argument for @ref BT_DATA_BYTES.
+ */
+#define BT_UUID_16_ENCODE(w16)  \
+	(((w16) >>  0) & 0xFF), \
+	(((w16) >>  8) & 0xFF)
+
+/** @brief Encode 32 bit UUID into an array values
+ *
+ *  Helper macro to encode 32-bit UUID values into advertising data.
+ *
+ *  Example for how to declare the UUID `0x180a01af`
+ *
+ *  @code
+ *  BT_DATA_BYTES(BT_DATA_UUID32_ALL, BT_UUID_32_ENCODE(0x180a01af),
+ *  @endcode
+ *
+ * @param w32 UUID value (32-bits)
+ *
+ * @return The comma separated values for UUID 32 value that
+ *         may be used directly as an argument for @ref BT_DATA_BYTES.
+ */
+#define BT_UUID_32_ENCODE(w32)  \
+	(((w32) >>  0) & 0xFF), \
+	(((w32) >>  8) & 0xFF), \
+	(((w32) >> 16) & 0xFF), \
+	(((w32) >> 24) & 0xFF)
+
+/** @def BT_UUID_STR_LEN
+ *
+ *  @brief Recommended length of user string buffer for Bluetooth UUID.
+ *
+ *  @details The recommended length guarantee the output of UUID
+ *  conversion will not lose valuable information about the UUID being
+ *  processed. If the length of the UUID is known the string can be shorter.
+ */
+#define BT_UUID_STR_LEN 37
+
+/** @def BT_UUID_GAP_VAL
+ *  @brief Generic Access UUID value
+ */
+#define BT_UUID_GAP_VAL 0x1800
+/** @def BT_UUID_GAP
+ *  @brief Generic Access
+ */
+#define BT_UUID_GAP \
+	BT_UUID_DECLARE_16(BT_UUID_GAP_VAL)
+/** @def BT_UUID_GATT_VAL
+ *  @brief Generic attribute UUID value
+ */
+#define BT_UUID_GATT_VAL 0x1801
+/** @def BT_UUID_GATT
+ *  @brief Generic Attribute
+ */
+#define BT_UUID_GATT \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_VAL)
+/** @def BT_UUID_CTS_VAL
+ *  @brief Current Time Service UUID value
+ */
+#define BT_UUID_CTS_VAL 0x1805
+/** @def BT_UUID_CTS
+ *  @brief Current Time Service
+ */
+#define BT_UUID_CTS \
+	BT_UUID_DECLARE_16(BT_UUID_CTS_VAL)
+/** @def BT_UUID_HTS_VAL
+ *  @brief Health Thermometer Service UUID value
+ */
+#define BT_UUID_HTS_VAL 0x1809
+/** @def BT_UUID_HTS
+ *  @brief Health Thermometer Service
+ */
+#define BT_UUID_HTS \
+	BT_UUID_DECLARE_16(BT_UUID_HTS_VAL)
+/** @def BT_UUID_DIS_VAL
+ *  @brief Device Information Service UUID value
+ */
+#define BT_UUID_DIS_VAL 0x180a
+/** @def BT_UUID_DIS
+ *  @brief Device Information Service
+ */
+#define BT_UUID_DIS \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_VAL)
+/** @def BT_UUID_HRS_VAL
+ *  @brief Heart Rate Service UUID value
+ */
+#define BT_UUID_HRS_VAL 0x180d
+/** @def BT_UUID_HRS
+ *  @brief Heart Rate Service
+ */
+#define BT_UUID_HRS \
+	BT_UUID_DECLARE_16(BT_UUID_HRS_VAL)
+/** @def BT_UUID_BAS_VAL
+ *  @brief Battery Service UUID value
+ */
+#define BT_UUID_BAS_VAL 0x180f
+/** @def BT_UUID_BAS
+ *  @brief Battery Service
+ */
+#define BT_UUID_BAS \
+	BT_UUID_DECLARE_16(BT_UUID_BAS_VAL)
+/** @def BT_UUID_HIDS_VAL
+ *  @brief HID Service UUID value
+ */
+#define BT_UUID_HIDS_VAL 0x1812
+/** @def BT_UUID_HIDS
+ *  @brief HID Service
+ */
+#define BT_UUID_HIDS \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_VAL)
+/** @def BT_UUID_CSC_VAL
+ *  @brief Cycling Speed and Cadence Service UUID value
+ */
+#define BT_UUID_CSC_VAL 0x1816
+/** @def BT_UUID_CSC
+ *  @brief Cycling Speed and Cadence Service
+ */
+#define BT_UUID_CSC \
+	BT_UUID_DECLARE_16(BT_UUID_CSC_VAL)
+/** @def BT_UUID_ESS_VAL
+ *  @brief Environmental Sensing Service UUID value
+ */
+#define BT_UUID_ESS_VAL 0x181a
+/** @def BT_UUID_ESS
+ *  @brief Environmental Sensing Service
+ */
+#define BT_UUID_ESS \
+	BT_UUID_DECLARE_16(BT_UUID_ESS_VAL)
+/** @def BT_UUID_BMS_VAL
+ *  @brief Bond Management Service UUID value
+ */
+#define BT_UUID_BMS_VAL 0x181e
+/** @def BT_UUID_BMS
+ *  @brief Bond Management Service
+ */
+#define BT_UUID_BMS \
+	BT_UUID_DECLARE_16(BT_UUID_BMS_VAL)
+/** @def BT_UUID_IPSS_VAL
+ *  @brief IP Support Service UUID value
+ */
+#define BT_UUID_IPSS_VAL 0x1820
+/** @def BT_UUID_IPSS
+ *  @brief IP Support Service
+ */
+#define BT_UUID_IPSS \
+	BT_UUID_DECLARE_16(BT_UUID_IPSS_VAL)
+/** @def BT_UUID_OTS_VAL
+ *  @brief Object Transfer Service UUID value
+ */
+#define BT_UUID_OTS_VAL 0x1825
+/** @def BT_UUID_OTS
+ *  @brief Object Transfer Service
+ */
+#define BT_UUID_OTS \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_VAL)
+/** @def BT_UUID_MESH_PROV_VAL
+ *  @brief Mesh Provisioning Service UUID value
+ */
+#define BT_UUID_MESH_PROV_VAL 0x1827
+/** @def BT_UUID_MESH_PROV
+ *  @brief Mesh Provisioning Service
+ */
+#define BT_UUID_MESH_PROV \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROV_VAL)
+/** @def BT_UUID_MESH_PROXY_VAL
+ *  @brief Mesh Proxy Service UUID value
+ */
+#define BT_UUID_MESH_PROXY_VAL 0x1828
+/** @def BT_UUID_MESH_PROXY
+ *  @brief Mesh Proxy Service
+ */
+#define BT_UUID_MESH_PROXY \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROXY_VAL)
+/** @def BT_UUID_GATT_PRIMARY_VAL
+ *  @brief GATT Primary Service UUID value
+ */
+#define BT_UUID_GATT_PRIMARY_VAL 0x2800
+/** @def BT_UUID_GATT_PRIMARY
+ *  @brief GATT Primary Service
+ */
+#define BT_UUID_GATT_PRIMARY \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_PRIMARY_VAL)
+/** @def BT_UUID_GATT_SECONDARY_VAL
+ *  @brief GATT Secondary Service UUID value
+ */
+#define BT_UUID_GATT_SECONDARY_VAL 0x2801
+/** @def BT_UUID_GATT_SECONDARY
+ *  @brief GATT Secondary Service
+ */
+#define BT_UUID_GATT_SECONDARY \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_SECONDARY_VAL)
+/** @def BT_UUID_GATT_INCLUDE_VAL
+ *  @brief GATT Include Service UUID value
+ */
+#define BT_UUID_GATT_INCLUDE_VAL 0x2802
+/** @def BT_UUID_GATT_INCLUDE
+ *  @brief GATT Include Service
+ */
+#define BT_UUID_GATT_INCLUDE \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_INCLUDE_VAL)
+/** @def BT_UUID_GATT_CHRC_VAL
+ *  @brief GATT Characteristic UUID value
+ */
+#define BT_UUID_GATT_CHRC_VAL 0x2803
+/** @def BT_UUID_GATT_CHRC
+ *  @brief GATT Characteristic
+ */
+#define BT_UUID_GATT_CHRC \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CHRC_VAL)
+/** @def BT_UUID_GATT_CEP_VAL
+ *  @brief GATT Characteristic Extended Properties UUID value
+ */
+#define BT_UUID_GATT_CEP_VAL 0x2900
+/** @def BT_UUID_GATT_CEP
+ *  @brief GATT Characteristic Extended Properties
+ */
+#define BT_UUID_GATT_CEP \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CEP_VAL)
+/** @def BT_UUID_GATT_CUD_VAL
+ *  @brief GATT Characteristic User Description UUID value
+ */
+#define BT_UUID_GATT_CUD_VAL 0x2901
+/** @def BT_UUID_GATT_CUD
+ *  @brief GATT Characteristic User Description
+ */
+#define BT_UUID_GATT_CUD \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CUD_VAL)
+/** @def BT_UUID_GATT_CCC_VAL
+ *  @brief GATT Client Characteristic Configuration UUID value
+ */
+#define BT_UUID_GATT_CCC_VAL 0x2902
+/** @def BT_UUID_GATT_CCC
+ *  @brief GATT Client Characteristic Configuration
+ */
+#define BT_UUID_GATT_CCC \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CCC_VAL)
+/** @def BT_UUID_GATT_SCC_VAL
+ *  @brief GATT Server Characteristic Configuration UUID value
+ */
+#define BT_UUID_GATT_SCC_VAL 0x2903
+/** @def BT_UUID_GATT_SCC
+ *  @brief GATT Server Characteristic Configuration
+ */
+#define BT_UUID_GATT_SCC \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_SCC_VAL)
+/** @def BT_UUID_GATT_CPF_VAL
+ *  @brief GATT Characteristic Presentation Format UUID value
+ */
+#define BT_UUID_GATT_CPF_VAL 0x2904
+/** @def BT_UUID_GATT_CPF
+ *  @brief GATT Characteristic Presentation Format
+ */
+#define BT_UUID_GATT_CPF \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CPF_VAL)
+/** @def BT_UUID_VALID_RANGE_VAL
+ *  @brief Valid Range Descriptor UUID value
+ */
+#define BT_UUID_VALID_RANGE_VAL 0x2906
+/** @def BT_UUID_VALID_RANGE
+ *  @brief Valid Range Descriptor
+ */
+#define BT_UUID_VALID_RANGE \
+	BT_UUID_DECLARE_16(BT_UUID_VALID_RANGE_VAL)
+/** @def BT_UUID_HIDS_EXT_REPORT_VAL
+ *  @brief HID External Report Descriptor UUID value
+ */
+#define BT_UUID_HIDS_EXT_REPORT_VAL 0x2907
+/** @def BT_UUID_HIDS_EXT_REPORT
+ *  @brief HID External Report Descriptor
+ */
+#define BT_UUID_HIDS_EXT_REPORT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_EXT_REPORT_VAL)
+/** @def BT_UUID_HIDS_REPORT_REF_VAL
+ *  @brief HID Report Reference Descriptor UUID value
+ */
+#define BT_UUID_HIDS_REPORT_REF_VAL 0x2908
+/** @def BT_UUID_HIDS_REPORT_REF
+ *  @brief HID Report Reference Descriptor
+ */
+#define BT_UUID_HIDS_REPORT_REF \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_REPORT_REF_VAL)
+/** @def BT_UUID_ES_CONFIGURATION_VAL
+ *  @brief Environmental Sensing Configuration Descriptor UUID value
+ */
+#define BT_UUID_ES_CONFIGURATION_VAL 0x290b
+/** @def BT_UUID_ES_CONFIGURATION
+ *  @brief Environmental Sensing Configuration Descriptor
+ */
+#define BT_UUID_ES_CONFIGURATION \
+	BT_UUID_DECLARE_16(BT_UUID_ES_CONFIGURATION_VAL)
+/** @def BT_UUID_ES_MEASUREMENT_VAL
+ *  @brief Environmental Sensing Measurement Descriptor UUID value
+ */
+#define BT_UUID_ES_MEASUREMENT_VAL 0x290c
+/** @def BT_UUID_ES_MEASUREMENT
+ *  @brief Environmental Sensing Measurement Descriptor
+ */
+#define BT_UUID_ES_MEASUREMENT \
+	BT_UUID_DECLARE_16(BT_UUID_ES_MEASUREMENT_VAL)
+/** @def BT_UUID_ES_TRIGGER_SETTING_VAL
+ *  @brief Environmental Sensing Trigger Setting Descriptor UUID value
+ */
+#define BT_UUID_ES_TRIGGER_SETTING_VAL 0x290d
+/** @def BT_UUID_ES_TRIGGER_SETTING
+ *  @brief Environmental Sensing Trigger Setting Descriptor
+ */
+#define BT_UUID_ES_TRIGGER_SETTING \
+	BT_UUID_DECLARE_16(BT_UUID_ES_TRIGGER_SETTING_VAL)
+/** @def BT_UUID_GAP_DEVICE_NAME_VAL
+ *  @brief GAP Characteristic Device Name UUID value
+ */
+#define BT_UUID_GAP_DEVICE_NAME_VAL 0x2a00
+/** @def BT_UUID_GAP_DEVICE_NAME
+ *  @brief GAP Characteristic Device Name
+ */
+#define BT_UUID_GAP_DEVICE_NAME \
+	BT_UUID_DECLARE_16(BT_UUID_GAP_DEVICE_NAME_VAL)
+/** @def BT_UUID_GAP_APPEARANCE_VAL
+ *  @brief GAP Characteristic Appearance UUID value
+ */
+#define BT_UUID_GAP_APPEARANCE_VAL 0x2a01
+/** @def BT_UUID_GAP_APPEARANCE
+ *  @brief GAP Characteristic Appearance
+ */
+#define BT_UUID_GAP_APPEARANCE \
+	BT_UUID_DECLARE_16(BT_UUID_GAP_APPEARANCE_VAL)
+/** @def BT_UUID_GAP_PPCP_VAL
+ *  @brief GAP Characteristic Peripheral Preferred Connection Parameters UUID
+ *         value
+ */
+#define BT_UUID_GAP_PPCP_VAL 0x2a04
+/** @def BT_UUID_GAP_PPCP
+ *  @brief GAP Characteristic Peripheral Preferred Connection Parameters
+ */
+#define BT_UUID_GAP_PPCP \
+	BT_UUID_DECLARE_16(BT_UUID_GAP_PPCP_VAL)
+/** @def BT_UUID_GATT_SC_VAL
+ *  @brief GATT Characteristic Service Changed UUID value
+ */
+#define BT_UUID_GATT_SC_VAL 0x2a05
+/** @def BT_UUID_GATT_SC
+ *  @brief GATT Characteristic Service Changed
+ */
+#define BT_UUID_GATT_SC \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_SC_VAL)
+/** @def BT_UUID_BAS_BATTERY_LEVEL_VAL
+ *  @brief BAS Characteristic Battery Level UUID value
+ */
+#define BT_UUID_BAS_BATTERY_LEVEL_VAL 0x2a19
+/** @def BT_UUID_BAS_BATTERY_LEVEL
+ *  @brief BAS Characteristic Battery Level
+ */
+#define BT_UUID_BAS_BATTERY_LEVEL \
+	BT_UUID_DECLARE_16(BT_UUID_BAS_BATTERY_LEVEL_VAL)
+/** @def BT_UUID_HTS_MEASUREMENT_VAL
+ *  @brief HTS Characteristic Measurement Value UUID value
+ */
+#define BT_UUID_HTS_MEASUREMENT_VAL 0x2a1c
+/** @def BT_UUID_HTS_MEASUREMENT
+ *  @brief HTS Characteristic Measurement Value
+ */
+#define BT_UUID_HTS_MEASUREMENT \
+	BT_UUID_DECLARE_16(BT_UUID_HTS_MEASUREMENT_VAL)
+/** @def BT_UUID_HIDS_BOOT_KB_IN_REPORT_VAL
+ *  @brief HID Characteristic Boot Keyboard Input Report UUID value
+ */
+#define BT_UUID_HIDS_BOOT_KB_IN_REPORT_VAL 0x2a22
+/** @def BT_UUID_HIDS_BOOT_KB_IN_REPORT
+ *  @brief HID Characteristic Boot Keyboard Input Report
+ */
+#define BT_UUID_HIDS_BOOT_KB_IN_REPORT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_BOOT_KB_IN_REPORT_VAL)
+/** @def BT_UUID_DIS_SYSTEM_ID_VAL
+ *  @brief DIS Characteristic System ID UUID value
+ */
+#define BT_UUID_DIS_SYSTEM_ID_VAL 0x2a23
+/** @def BT_UUID_DIS_SYSTEM_ID
+ *  @brief DIS Characteristic System ID
+ */
+#define BT_UUID_DIS_SYSTEM_ID \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_SYSTEM_ID_VAL)
+/** @def BT_UUID_DIS_MODEL_NUMBER_VAL
+ *  @brief DIS Characteristic Model Number String UUID value
+ */
+#define BT_UUID_DIS_MODEL_NUMBER_VAL 0x2a24
+/** @def BT_UUID_DIS_MODEL_NUMBER
+ *  @brief DIS Characteristic Model Number String
+ */
+#define BT_UUID_DIS_MODEL_NUMBER \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_MODEL_NUMBER_VAL)
+/** @def BT_UUID_DIS_SERIAL_NUMBER_VAL
+ *  @brief DIS Characteristic Serial Number String UUID value
+ */
+#define BT_UUID_DIS_SERIAL_NUMBER_VAL 0x2a25
+/** @def BT_UUID_DIS_SERIAL_NUMBER
+ *  @brief DIS Characteristic Serial Number String
+ */
+#define BT_UUID_DIS_SERIAL_NUMBER \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_SERIAL_NUMBER_VAL)
+/** @def BT_UUID_DIS_FIRMWARE_REVISION_VAL
+ *  @brief DIS Characteristic Firmware Revision String UUID value
+ */
+#define BT_UUID_DIS_FIRMWARE_REVISION_VAL 0x2a26
+/** @def BT_UUID_DIS_FIRMWARE_REVISION
+ *  @brief DIS Characteristic Firmware Revision String
+ */
+#define BT_UUID_DIS_FIRMWARE_REVISION \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_FIRMWARE_REVISION_VAL)
+/** @def BT_UUID_DIS_HARDWARE_REVISION_VAL
+ *  @brief DIS Characteristic Hardware Revision String UUID value
+ */
+#define BT_UUID_DIS_HARDWARE_REVISION_VAL 0x2a27
+/** @def BT_UUID_DIS_HARDWARE_REVISION
+ *  @brief DIS Characteristic Hardware Revision String
+ */
+#define BT_UUID_DIS_HARDWARE_REVISION \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_HARDWARE_REVISION_VAL)
+/** @def BT_UUID_DIS_SOFTWARE_REVISION_VAL
+ *  @brief DIS Characteristic Software Revision String UUID value
+ */
+#define BT_UUID_DIS_SOFTWARE_REVISION_VAL 0x2a28
+/** @def BT_UUID_DIS_SOFTWARE_REVISION
+ *  @brief DIS Characteristic Software Revision String
+ */
+#define BT_UUID_DIS_SOFTWARE_REVISION \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_SOFTWARE_REVISION_VAL)
+/** @def BT_UUID_DIS_MANUFACTURER_NAME_VAL
+ *  @brief DIS Characteristic Manufacturer Name String UUID Value
+ */
+#define BT_UUID_DIS_MANUFACTURER_NAME_VAL 0x2a29
+/** @def BT_UUID_DIS_MANUFACTURER_NAME
+ *  @brief DIS Characteristic Manufacturer Name String
+ */
+#define BT_UUID_DIS_MANUFACTURER_NAME \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_MANUFACTURER_NAME_VAL)
+/** @def BT_UUID_DIS_PNP_ID_VAL
+ *  @brief DIS Characteristic PnP ID UUID value
+ */
+#define BT_UUID_DIS_PNP_ID_VAL 0x2a50
+/** @def BT_UUID_DIS_PNP_ID
+ *  @brief DIS Characteristic PnP ID
+ */
+#define BT_UUID_DIS_PNP_ID \
+	BT_UUID_DECLARE_16(BT_UUID_DIS_PNP_ID_VAL)
+/** @def BT_UUID_CTS_CURRENT_TIME_VAL
+ *  @brief CTS Characteristic Current Time UUID value
+ */
+#define BT_UUID_CTS_CURRENT_TIME_VAL 0x2a2b
+/** @def BT_UUID_CTS_CURRENT_TIME
+ *  @brief CTS Characteristic Current Time
+ */
+#define BT_UUID_CTS_CURRENT_TIME \
+	BT_UUID_DECLARE_16(BT_UUID_CTS_CURRENT_TIME_VAL)
+/** @def BT_UUID_MAGN_DECLINATION_VAL
+ *  @brief Magnetic Declination Characteristic UUID value
+ */
+#define BT_UUID_MAGN_DECLINATION_VAL 0x2a2c
+/** @def BT_UUID_MAGN_DECLINATION
+ *  @brief Magnetic Declination Characteristic
+ */
+#define BT_UUID_MAGN_DECLINATION \
+	BT_UUID_DECLARE_16(BT_UUID_MAGN_DECLINATION_VAL)
+/** @def BT_UUID_HIDS_BOOT_KB_OUT_REPORT_VAL
+ *  @brief HID Boot Keyboard Output Report Characteristic UUID value
+ */
+#define BT_UUID_HIDS_BOOT_KB_OUT_REPORT_VAL 0x2a32
+/** @def BT_UUID_HIDS_BOOT_KB_OUT_REPORT
+ *  @brief HID Boot Keyboard Output Report Characteristic
+ */
+#define BT_UUID_HIDS_BOOT_KB_OUT_REPORT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_BOOT_KB_OUT_REPORT_VAL)
+/** @def BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT_VAL
+ *  @brief HID Boot Mouse Input Report Characteristic UUID value
+ */
+#define BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT_VAL 0x2a33
+/** @def BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT
+ *  @brief HID Boot Mouse Input Report Characteristic
+ */
+#define BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_BOOT_MOUSE_IN_REPORT_VAL)
+/** @def BT_UUID_HRS_MEASUREMENT_VAL
+ *  @brief HRS Characteristic Measurement Interval UUID value
+ */
+#define BT_UUID_HRS_MEASUREMENT_VAL 0x2a37
+/** @def BT_UUID_HRS_MEASUREMENT
+ *  @brief HRS Characteristic Measurement Interval
+ */
+#define BT_UUID_HRS_MEASUREMENT \
+	BT_UUID_DECLARE_16(BT_UUID_HRS_MEASUREMENT_VAL)
+/** @def BT_UUID_HRS_BODY_SENSOR
+ *  @brief HRS Characteristic Body Sensor Location
+ */
+#define BT_UUID_HRS_BODY_SENSOR_VAL 0x2a38
+/** @def BT_UUID_HRS_CONTROL_POINT
+ *  @brief HRS Characteristic Control Point
+ */
+#define BT_UUID_HRS_BODY_SENSOR \
+	BT_UUID_DECLARE_16(BT_UUID_HRS_BODY_SENSOR_VAL)
+/** @def BT_UUID_HRS_CONTROL_POINT_VAL
+ *  @brief HRS Characteristic Control Point UUID value
+ */
+#define BT_UUID_HRS_CONTROL_POINT_VAL 0x2a39
+/** @def BT_UUID_HRS_CONTROL_POINT
+ *  @brief HRS Characteristic Control Point
+ */
+#define BT_UUID_HRS_CONTROL_POINT \
+	BT_UUID_DECLARE_16(BT_UUID_HRS_CONTROL_POINT_VAL)
+/** @def BT_UUID_HIDS_INFO_VAL
+ *  @brief HID Information Characteristic UUID value
+ */
+#define BT_UUID_HIDS_INFO_VAL 0x2a4a
+/** @def BT_UUID_HIDS_INFO
+ *  @brief HID Information Characteristic
+ */
+#define BT_UUID_HIDS_INFO \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_INFO_VAL)
+/** @def BT_UUID_HIDS_REPORT_MAP_VAL
+ *  @brief HID Report Map Characteristic UUID value
+ */
+#define BT_UUID_HIDS_REPORT_MAP_VAL 0x2a4b
+/** @def BT_UUID_HIDS_REPORT_MAP
+ *  @brief HID Report Map Characteristic
+ */
+#define BT_UUID_HIDS_REPORT_MAP \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_REPORT_MAP_VAL)
+/** @def BT_UUID_HIDS_CTRL_POINT_VAL
+ *  @brief HID Control Point Characteristic UUID value
+ */
+#define BT_UUID_HIDS_CTRL_POINT_VAL 0x2a4c
+/** @def BT_UUID_HIDS_CTRL_POINT
+ *  @brief HID Control Point Characteristic
+ */
+#define BT_UUID_HIDS_CTRL_POINT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_CTRL_POINT_VAL)
+/** @def BT_UUID_HIDS_REPORT_VAL
+ *  @brief HID Report Characteristic UUID value
+ */
+#define BT_UUID_HIDS_REPORT_VAL 0x2a4d
+/** @def BT_UUID_HIDS_REPORT
+ *  @brief HID Report Characteristic
+ */
+#define BT_UUID_HIDS_REPORT \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_REPORT_VAL)
+/** @def BT_UUID_HIDS_PROTOCOL_MODE_VAL
+ *  @brief HID Protocol Mode Characteristic UUID value
+ */
+#define BT_UUID_HIDS_PROTOCOL_MODE_VAL 0x2a4e
+/** @def BT_UUID_HIDS_PROTOCOL_MODE
+ *  @brief HID Protocol Mode Characteristic
+ */
+#define BT_UUID_HIDS_PROTOCOL_MODE \
+	BT_UUID_DECLARE_16(BT_UUID_HIDS_PROTOCOL_MODE_VAL)
+/** @def BT_UUID_CSC_MEASUREMENT_VAL
+ *  @brief CSC Measurement Characteristic UUID value
+ */
+#define BT_UUID_CSC_MEASUREMENT_VAL 0x2a5b
+/** @def BT_UUID_CSC_MEASUREMENT
+ *  @brief CSC Measurement Characteristic
+ */
+#define BT_UUID_CSC_MEASUREMENT \
+	BT_UUID_DECLARE_16(BT_UUID_CSC_MEASUREMENT_VAL)
+/** @def BT_UUID_CSC_FEATURE_VAL
+ *  @brief CSC Feature Characteristic UUID value
+ */
+#define BT_UUID_CSC_FEATURE_VAL 0x2a5c
+/** @def BT_UUID_CSC_FEATURE
+ *  @brief CSC Feature Characteristic
+ */
+#define BT_UUID_CSC_FEATURE \
+	BT_UUID_DECLARE_16(BT_UUID_CSC_FEATURE_VAL)
+/** @def BT_UUID_SENSOR_LOCATION_VAL
+ *  @brief Sensor Location Characteristic UUID value
+ */
+#define BT_UUID_SENSOR_LOCATION_VAL 0x2a5d
+/** @def BT_UUID_SENSOR_LOCATION
+ *  @brief Sensor Location Characteristic
+ */
+#define BT_UUID_SENSOR_LOCATION \
+	BT_UUID_DECLARE_16(BT_UUID_SENSOR_LOCATION_VAL)
+/** @def BT_UUID_SC_CONTROL_POINT_VAL
+ *  @brief SC Control Point Characteristic UUID value
+ */
+#define BT_UUID_SC_CONTROL_POINT_VAL 0x2a55
+/** @def BT_UUID_SC_CONTROL_POINT
+ *  @brief SC Control Point Characteristic
+ */
+#define BT_UUID_SC_CONTROL_POINT \
+	BT_UUID_DECLARE_16(BT_UUID_SC_CONTROL_POINT_VAL)
+/** @def BT_UUID_ELEVATION_VAL
+ *  @brief Elevation Characteristic UUID value
+ */
+#define BT_UUID_ELEVATION_VAL 0x2a6c
+/** @def BT_UUID_ELEVATION
+ *  @brief Elevation Characteristic
+ */
+#define BT_UUID_ELEVATION \
+	BT_UUID_DECLARE_16(BT_UUID_ELEVATION_VAL)
+/** @def BT_UUID_PRESSURE_VAL
+ *  @brief Pressure Characteristic UUID value
+ */
+#define BT_UUID_PRESSURE_VAL 0x2a6d
+/** @def BT_UUID_PRESSURE
+ *  @brief Pressure Characteristic
+ */
+#define BT_UUID_PRESSURE \
+	BT_UUID_DECLARE_16(BT_UUID_PRESSURE_VAL)
+/** @def BT_UUID_TEMPERATURE_VAL
+ *  @brief Temperature Characteristic UUID value
+ */
+#define BT_UUID_TEMPERATURE_VAL 0x2a6e
+/** @def BT_UUID_TEMPERATURE
+ *  @brief Temperature Characteristic
+ */
+#define BT_UUID_TEMPERATURE \
+	BT_UUID_DECLARE_16(BT_UUID_TEMPERATURE_VAL)
+/** @def BT_UUID_HUMIDITY_VAL
+ *  @brief Humidity Characteristic UUID value
+ */
+#define BT_UUID_HUMIDITY_VAL 0x2a6f
+/** @def BT_UUID_HUMIDITY
+ *  @brief Humidity Characteristic
+ */
+#define BT_UUID_HUMIDITY \
+	BT_UUID_DECLARE_16(BT_UUID_HUMIDITY_VAL)
+/** @def BT_UUID_TRUE_WIND_SPEED_VAL
+ *  @brief True Wind Speed Characteristic UUID value
+ */
+#define BT_UUID_TRUE_WIND_SPEED_VAL 0x2a70
+/** @def BT_UUID_TRUE_WIND_SPEED
+ *  @brief True Wind Speed Characteristic
+ */
+#define BT_UUID_TRUE_WIND_SPEED \
+	BT_UUID_DECLARE_16(BT_UUID_TRUE_WIND_SPEED_VAL)
+/** @def BT_UUID_TRUE_WIND_DIR_VAL
+ *  @brief True Wind Direction Characteristic UUID value
+ */
+#define BT_UUID_TRUE_WIND_DIR_VAL 0x2a71
+/** @def BT_UUID_TRUE_WIND_DIR
+ *  @brief True Wind Direction Characteristic
+ */
+#define BT_UUID_TRUE_WIND_DIR \
+	BT_UUID_DECLARE_16(BT_UUID_TRUE_WIND_DIR_VAL)
+/** @def BT_UUID_APPARENT_WIND_SPEED_VAL
+ *  @brief Apparent Wind Speed Characteristic UUID value
+ */
+#define BT_UUID_APPARENT_WIND_SPEED_VAL 0x2a72
+/** @def BT_UUID_APPARENT_WIND_SPEED
+ *  @brief Apparent Wind Speed Characteristic
+ */
+#define BT_UUID_APPARENT_WIND_SPEED \
+	BT_UUID_DECLARE_16(BT_UUID_APPARENT_WIND_SPEED_VAL)
+/** @def BT_UUID_APPARENT_WIND_DIR_VAL
+ *  @brief Apparent Wind Direction Characteristic UUID value
+ */
+#define BT_UUID_APPARENT_WIND_DIR_VAL 0x2a73
+/** @def BT_UUID_APPARENT_WIND_DIR
+ *  @brief Apparent Wind Direction Characteristic
+ */
+#define BT_UUID_APPARENT_WIND_DIR \
+	BT_UUID_DECLARE_16(BT_UUID_APPARENT_WIND_DIR_VAL)
+/** @def BT_UUID_GUST_FACTOR_VAL
+ *  @brief Gust Factor Characteristic UUID value
+ */
+#define BT_UUID_GUST_FACTOR_VAL 0x2a74
+/** @def BT_UUID_GUST_FACTOR
+ *  @brief Gust Factor Characteristic
+ */
+#define BT_UUID_GUST_FACTOR \
+	BT_UUID_DECLARE_16(BT_UUID_GUST_FACTOR_VAL)
+/** @def BT_UUID_POLLEN_CONCENTRATION_VAL
+ *  @brief Pollen Concentration Characteristic UUID value
+ */
+#define BT_UUID_POLLEN_CONCENTRATION_VAL 0x2a75
+/** @def BT_UUID_POLLEN_CONCENTRATION
+ *  @brief Pollen Concentration Characteristic
+ */
+#define BT_UUID_POLLEN_CONCENTRATION \
+	BT_UUID_DECLARE_16(BT_UUID_POLLEN_CONCENTRATION_VAL)
+/** @def BT_UUID_UV_INDEX_VAL
+ *  @brief UV Index Characteristic UUID value
+ */
+#define BT_UUID_UV_INDEX_VAL 0x2a76
+/** @def BT_UUID_UV_INDEX
+ *  @brief UV Index Characteristic
+ */
+#define BT_UUID_UV_INDEX \
+	BT_UUID_DECLARE_16(BT_UUID_UV_INDEX_VAL)
+/** @def BT_UUID_IRRADIANCE_VAL
+ *  @brief Irradiance Characteristic UUID value
+ */
+#define BT_UUID_IRRADIANCE_VAL 0x2a77
+/** @def BT_UUID_IRRADIANCE
+ *  @brief Irradiance Characteristic
+ */
+#define BT_UUID_IRRADIANCE \
+	BT_UUID_DECLARE_16(BT_UUID_IRRADIANCE_VAL)
+/** @def BT_UUID_RAINFALL_VAL
+ *  @brief Rainfall Characteristic UUID value
+ */
+#define BT_UUID_RAINFALL_VAL 0x2a78
+/** @def BT_UUID_RAINFALL
+ *  @brief Rainfall Characteristic
+ */
+#define BT_UUID_RAINFALL \
+	BT_UUID_DECLARE_16(BT_UUID_RAINFALL_VAL)
+/** @def BT_UUID_WIND_CHILL_VAL
+ *  @brief Wind Chill Characteristic UUID value
+ */
+#define BT_UUID_WIND_CHILL_VAL 0x2a79
+/** @def BT_UUID_WIND_CHILL
+ *  @brief Wind Chill Characteristic
+ */
+#define BT_UUID_WIND_CHILL \
+	BT_UUID_DECLARE_16(BT_UUID_WIND_CHILL_VAL)
+/** @def BT_UUID_HEAT_INDEX_VAL
+ *  @brief Heat Index Characteristic UUID value
+ */
+#define BT_UUID_HEAT_INDEX_VAL 0x2a7a
+/** @def BT_UUID_HEAT_INDEX
+ *  @brief Heat Index Characteristic
+ */
+#define BT_UUID_HEAT_INDEX \
+	BT_UUID_DECLARE_16(BT_UUID_HEAT_INDEX_VAL)
+/** @def BT_UUID_DEW_POINT_VAL
+ *  @brief Dew Point Characteristic UUID value
+ */
+#define BT_UUID_DEW_POINT_VAL 0x2a7b
+/** @def BT_UUID_DEW_POINT
+ *  @brief Dew Point Characteristic
+ */
+#define BT_UUID_DEW_POINT \
+	BT_UUID_DECLARE_16(BT_UUID_DEW_POINT_VAL)
+/** @def BT_UUID_DESC_VALUE_CHANGED_VAL
+ *  @brief Descriptor Value Changed Characteristic UUID value
+ */
+#define BT_UUID_DESC_VALUE_CHANGED_VAL 0x2a7d
+/** @def BT_UUID_DESC_VALUE_CHANGED
+ *  @brief Descriptor Value Changed Characteristic
+ */
+#define BT_UUID_DESC_VALUE_CHANGED \
+	BT_UUID_DECLARE_16(BT_UUID_DESC_VALUE_CHANGED_VAL)
+/** @def BT_UUID_MAGN_FLUX_DENSITY_2D_VAL
+ *  @brief Magnetic Flux Density - 2D Characteristic UUID value
+ */
+#define BT_UUID_MAGN_FLUX_DENSITY_2D_VAL 0x2aa0
+/** @def BT_UUID_MAGN_FLUX_DENSITY_2D
+ *  @brief Magnetic Flux Density - 2D Characteristic
+ */
+#define BT_UUID_MAGN_FLUX_DENSITY_2D \
+	BT_UUID_DECLARE_16(BT_UUID_MAGN_FLUX_DENSITY_2D_VAL)
+/** @def BT_UUID_MAGN_FLUX_DENSITY_3D_VAL
+ *  @brief Magnetic Flux Density - 3D Characteristic UUID value
+ */
+#define BT_UUID_MAGN_FLUX_DENSITY_3D_VAL 0x2aa1
+/** @def BT_UUID_MAGN_FLUX_DENSITY_3D
+ *  @brief Magnetic Flux Density - 3D Characteristic
+ */
+#define BT_UUID_MAGN_FLUX_DENSITY_3D \
+	BT_UUID_DECLARE_16(BT_UUID_MAGN_FLUX_DENSITY_3D_VAL)
+/** @def BT_UUID_BAR_PRESSURE_TREND_VAL
+ *  @brief Barometric Pressure Trend Characteristic UUID value
+ */
+#define BT_UUID_BAR_PRESSURE_TREND_VAL 0x2aa3
+/** @def BT_UUID_BAR_PRESSURE_TREND
+ *  @brief Barometric Pressure Trend Characteristic
+ */
+#define BT_UUID_BAR_PRESSURE_TREND \
+	BT_UUID_DECLARE_16(BT_UUID_BAR_PRESSURE_TREND_VAL)
+/** @def BT_UUID_BMS_CONTROL_POINT_VAL
+ *  @brief Bond Management Control Point UUID value
+ */
+#define BT_UUID_BMS_CONTROL_POINT_VAL 0x2aa4
+/** @def BT_UUID_BMS_CONTROL_POINT
+ *  @brief Bond Management Control Point
+ */
+#define BT_UUID_BMS_CONTROL_POINT \
+	BT_UUID_DECLARE_16(BT_UUID_BMS_CONTROL_POINT_VAL)
+/** @def BT_UUID_BMS_FEATURE_VAL
+ *  @brief Bond Management Feature UUID value
+ */
+#define BT_UUID_BMS_FEATURE_VAL 0x2aa5
+/** @def BT_UUID_BMS_FEATURE
+ *  @brief Bond Management Feature
+ */
+#define BT_UUID_BMS_FEATURE \
+	BT_UUID_DECLARE_16(BT_UUID_BMS_FEATURE_VAL)
+/** @def BT_UUID_CENTRAL_ADDR_RES_VAL
+ *  @brief Central Address Resolution Characteristic UUID value
+ */
+#define BT_UUID_CENTRAL_ADDR_RES_VAL 0x2aa6
+/** @def BT_UUID_CENTRAL_ADDR_RES
+ *  @brief Central Address Resolution Characteristic
+ */
+#define BT_UUID_CENTRAL_ADDR_RES \
+	BT_UUID_DECLARE_16(BT_UUID_CENTRAL_ADDR_RES_VAL)
+/** @def BT_UUID_OTS_FEATURE_VAL
+ *  @brief OTS Feature Characteristic UUID value
+ */
+#define BT_UUID_OTS_FEATURE_VAL 0x2abd
+/** @def BT_UUID_OTS_FEATURE
+ *  @brief OTS Feature Characteristic
+ */
+#define BT_UUID_OTS_FEATURE \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_FEATURE_VAL)
+/** @def BT_UUID_OTS_NAME_VAL
+ *  @brief OTS Object Name Characteristic UUID value
+ */
+#define BT_UUID_OTS_NAME_VAL 0x2abe
+/** @def BT_UUID_OTS_NAME
+ *  @brief OTS Object Name Characteristic
+ */
+#define BT_UUID_OTS_NAME \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_NAME_VAL)
+/** @def BT_UUID_OTS_TYPE_VAL
+ *  @brief OTS Object Type Characteristic UUID value
+ */
+#define BT_UUID_OTS_TYPE_VAL 0x2abf
+/** @def BT_UUID_OTS_TYPE
+ *  @brief OTS Object Type Characteristic
+ */
+#define BT_UUID_OTS_TYPE \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_TYPE_VAL)
+/** @def BT_UUID_OTS_SIZE_VAL
+ *  @brief OTS Object Size Characteristic UUID value
+ */
+#define BT_UUID_OTS_SIZE_VAL 0x2ac0
+/** @def BT_UUID_OTS_SIZE
+ *  @brief OTS Object Size Characteristic
+ */
+#define BT_UUID_OTS_SIZE \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_SIZE_VAL)
+/** @def BT_UUID_OTS_FIRST_CREATED_VAL
+ *  @brief OTS Object First-Created Characteristic UUID value
+ */
+#define BT_UUID_OTS_FIRST_CREATED_VAL 0x2ac1
+/** @def BT_UUID_OTS_FIRST_CREATED
+ *  @brief OTS Object First-Created Characteristic
+ */
+#define BT_UUID_OTS_FIRST_CREATED \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_FIRST_CREATED_VAL)
+/** @def BT_UUID_OTS_LAST_MODIFIED_VAL
+ *  @brief OTS Object Last-Modified Characteristic UUI value
+ */
+#define BT_UUID_OTS_LAST_MODIFIED_VAL 0x2ac2
+/** @def BT_UUID_OTS_LAST_MODIFIED
+ *  @brief OTS Object Last-Modified Characteristic
+ */
+#define BT_UUID_OTS_LAST_MODIFIED \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_LAST_MODIFIED_VAL)
+/** @def BT_UUID_OTS_ID_VAL
+ *  @brief OTS Object ID Characteristic UUID value
+ */
+#define BT_UUID_OTS_ID_VAL 0x2ac3
+/** @def BT_UUID_OTS_ID
+ *  @brief OTS Object ID Characteristic
+ */
+#define BT_UUID_OTS_ID \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_ID_VAL)
+/** @def BT_UUID_OTS_PROPERTIES_VAL
+ *  @brief OTS Object Properties Characteristic UUID value
+ */
+#define BT_UUID_OTS_PROPERTIES_VAL 0x2ac4
+/** @def BT_UUID_OTS_PROPERTIES
+ *  @brief OTS Object Properties Characteristic
+ */
+#define BT_UUID_OTS_PROPERTIES \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_PROPERTIES_VAL)
+/** @def BT_UUID_OTS_ACTION_CP_VAL
+ *  @brief OTS Object Action Control Point Characteristic UUID value
+ */
+#define BT_UUID_OTS_ACTION_CP_VAL 0x2ac5
+/** @def BT_UUID_OTS_ACTION_CP
+ *  @brief OTS Object Action Control Point Characteristic
+ */
+#define BT_UUID_OTS_ACTION_CP \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_ACTION_CP_VAL)
+/** @def BT_UUID_OTS_LIST_CP_VAL
+ *  @brief OTS Object List Control Point Characteristic UUID value
+ */
+#define BT_UUID_OTS_LIST_CP_VAL 0x2ac6
+/** @def BT_UUID_OTS_LIST_CP
+ *  @brief OTS Object List Control Point Characteristic
+ */
+#define BT_UUID_OTS_LIST_CP \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_LIST_CP_VAL)
+/** @def BT_UUID_OTS_LIST_FILTER_VAL
+ *  @brief OTS Object List Filter Characteristic UUID value
+ */
+#define BT_UUID_OTS_LIST_FILTER_VAL 0x2ac7
+/** @def BT_UUID_OTS_LIST_FILTER
+ *  @brief OTS Object List Filter Characteristic
+ */
+#define BT_UUID_OTS_LIST_FILTER \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_LIST_FILTER_VAL)
+/** @def BT_UUID_OTS_CHANGED_VAL
+ *  @brief OTS Object Changed Characteristic UUID value
+ */
+#define BT_UUID_OTS_CHANGED_VAL 0x2ac8
+/** @def BT_UUID_OTS_CHANGED
+ *  @brief OTS Object Changed Characteristic
+ */
+#define BT_UUID_OTS_CHANGED \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_CHANGED_VAL)
+/** @def BT_UUID_OTS_TYPE_UNSPECIFIED_VAL
+ *  @brief OTS Unspecified Object Type UUID value
+ */
+#define BT_UUID_OTS_TYPE_UNSPECIFIED_VAL 0x2aca
+/** @def BT_UUID_OTS_TYPE_UNSPECIFIED
+ *  @brief OTS Unspecified Object Type
+ */
+#define BT_UUID_OTS_TYPE_UNSPECIFIED \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_TYPE_UNSPECIFIED_VAL)
+/** @def BT_UUID_OTS_DIRECTORY_LISTING_VAL
+ *  @brief OTS Directory Listing UUID value
+ */
+#define BT_UUID_OTS_DIRECTORY_LISTING_VAL 0x2acb
+/** @def BT_UUID_OTS_DIRECTORY_LISTING
+ *  @brief OTS Directory Listing
+ */
+#define BT_UUID_OTS_DIRECTORY_LISTING \
+	BT_UUID_DECLARE_16(BT_UUID_OTS_DIRECTORY_LISTING_VAL)
+/** @def BT_UUID_MESH_PROV_DATA_IN_VAL
+ *  @brief Mesh Provisioning Data In UUID value
+ */
+#define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb
+/** @def BT_UUID_MESH_PROV_DATA_IN
+ *  @brief Mesh Provisioning Data In
+ */
+#define BT_UUID_MESH_PROV_DATA_IN \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROV_DATA_IN_VAL)
+/** @def BT_UUID_MESH_PROV_DATA_OUT_VAL
+ *  @brief Mesh Provisioning Data Out UUID value
+ */
+#define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc
+/** @def BT_UUID_MESH_PROV_DATA_OUT
+ *  @brief Mesh Provisioning Data Out
+ */
+#define BT_UUID_MESH_PROV_DATA_OUT \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROV_DATA_OUT_VAL)
+/** @def BT_UUID_MESH_PROXY_DATA_IN_VAL
+ *  @brief Mesh Proxy Data In UUID value
+ */
+#define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add
+/** @def BT_UUID_MESH_PROXY_DATA_IN
+ *  @brief Mesh Proxy Data In
+ */
+#define BT_UUID_MESH_PROXY_DATA_IN \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROXY_DATA_IN_VAL)
+/** @def BT_UUID_MESH_PROXY_DATA_OUT_VAL
+ *  @brief Mesh Proxy Data Out UUID value
+ */
+#define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade
+/** @def BT_UUID_MESH_PROXY_DATA_OUT
+ *  @brief Mesh Proxy Data Out
+ */
+#define BT_UUID_MESH_PROXY_DATA_OUT \
+	BT_UUID_DECLARE_16(BT_UUID_MESH_PROXY_DATA_OUT_VAL)
+/** @def BT_UUID_GATT_CLIENT_FEATURES_VAL
+ *  @brief Client Supported Features UUID value
+ */
+#define BT_UUID_GATT_CLIENT_FEATURES_VAL 0x2b29
+/** @def BT_UUID_GATT_CLIENT_FEATURES
+ *  @brief Client Supported Features
+ */
+#define BT_UUID_GATT_CLIENT_FEATURES \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_CLIENT_FEATURES_VAL)
+/** @def BT_UUID_GATT_DB_HASH_VAL
+ *  @brief Database Hash UUID value
+ */
+#define BT_UUID_GATT_DB_HASH_VAL 0x2b2a
+/** @def BT_UUID_GATT_DB_HASH
+ *  @brief Database Hash
+ */
+#define BT_UUID_GATT_DB_HASH \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_DB_HASH_VAL)
+
+/** @def BT_UUID_GATT_SERVER_FEATURES_VAL
+ *  @brief Server Supported Features UUID value
+ */
+#define BT_UUID_GATT_SERVER_FEATURES_VAL  0x2b3a
+/** @def BT_UUID_GATT_SERVER_FEATURES
+ *  @brief Server Supported Features
+ */
+#define BT_UUID_GATT_SERVER_FEATURES      \
+	BT_UUID_DECLARE_16(BT_UUID_GATT_SERVER_FEATURES_VAL)
+
+/*
+ * Protocol UUIDs
+ */
+#define BT_UUID_SDP_VAL               0x0001
+#define BT_UUID_SDP                   BT_UUID_DECLARE_16(BT_UUID_SDP_VAL)
+#define BT_UUID_UDP_VAL               0x0002
+#define BT_UUID_UDP                   BT_UUID_DECLARE_16(BT_UUID_UDP_VAL)
+#define BT_UUID_RFCOMM_VAL            0x0003
+#define BT_UUID_RFCOMM                BT_UUID_DECLARE_16(BT_UUID_RFCOMM_VAL)
+#define BT_UUID_TCP_VAL               0x0004
+#define BT_UUID_TCP                   BT_UUID_DECLARE_16(BT_UUID_TCP_VAL)
+#define BT_UUID_TCS_BIN_VAL           0x0005
+#define BT_UUID_TCS_BIN               BT_UUID_DECLARE_16(BT_UUID_TCS_BIN_VAL)
+#define BT_UUID_TCS_AT_VAL            0x0006
+#define BT_UUID_TCS_AT                BT_UUID_DECLARE_16(BT_UUID_TCS_AT_VAL)
+#define BT_UUID_ATT_VAL               0x0007
+#define BT_UUID_ATT                   BT_UUID_DECLARE_16(BT_UUID_ATT_VAL)
+#define BT_UUID_OBEX_VAL              0x0008
+#define BT_UUID_OBEX                  BT_UUID_DECLARE_16(BT_UUID_OBEX_VAL)
+#define BT_UUID_IP_VAL                0x0009
+#define BT_UUID_IP                    BT_UUID_DECLARE_16(BT_UUID_IP_VAL)
+#define BT_UUID_FTP_VAL               0x000a
+#define BT_UUID_FTP                   BT_UUID_DECLARE_16(BT_UUID_FTP_VAL)
+#define BT_UUID_HTTP_VAL              0x000c
+#define BT_UUID_HTTP                  BT_UUID_DECLARE_16(BT_UUID_HTTP_VAL)
+#define BT_UUID_BNEP_VAL              0x000f
+#define BT_UUID_BNEP                  BT_UUID_DECLARE_16(BT_UUID_BNEP_VAL)
+#define BT_UUID_UPNP_VAL              0x0010
+#define BT_UUID_UPNP                  BT_UUID_DECLARE_16(BT_UUID_UPNP_VAL)
+#define BT_UUID_HIDP_VAL              0x0011
+#define BT_UUID_HIDP                  BT_UUID_DECLARE_16(BT_UUID_HIDP_VAL)
+#define BT_UUID_HCRP_CTRL_VAL         0x0012
+#define BT_UUID_HCRP_CTRL             BT_UUID_DECLARE_16(BT_UUID_HCRP_CTRL_VAL)
+#define BT_UUID_HCRP_DATA_VAL         0x0014
+#define BT_UUID_HCRP_DATA             BT_UUID_DECLARE_16(BT_UUID_HCRP_DATA_VAL)
+#define BT_UUID_HCRP_NOTE_VAL         0x0016
+#define BT_UUID_HCRP_NOTE             BT_UUID_DECLARE_16(BT_UUID_HCRP_NOTE_VAL)
+#define BT_UUID_AVCTP_VAL             0x0017
+#define BT_UUID_AVCTP                 BT_UUID_DECLARE_16(BT_UUID_AVCTP_VAL)
+#define BT_UUID_AVDTP_VAL             0x0019
+#define BT_UUID_AVDTP                 BT_UUID_DECLARE_16(BT_UUID_AVDTP_VAL)
+#define BT_UUID_CMTP_VAL              0x001b
+#define BT_UUID_CMTP                  BT_UUID_DECLARE_16(BT_UUID_CMTP_VAL)
+#define BT_UUID_UDI_VAL               0x001d
+#define BT_UUID_UDI                   BT_UUID_DECLARE_16(BT_UUID_UDI_VAL)
+#define BT_UUID_MCAP_CTRL_VAL         0x001e
+#define BT_UUID_MCAP_CTRL             BT_UUID_DECLARE_16(BT_UUID_MCAP_CTRL_VAL)
+#define BT_UUID_MCAP_DATA_VAL         0x001f
+#define BT_UUID_MCAP_DATA             BT_UUID_DECLARE_16(BT_UUID_MCAP_DATA_VAL)
+#define BT_UUID_L2CAP_VAL             0x0100
+#define BT_UUID_L2CAP                 BT_UUID_DECLARE_16(BT_UUID_L2CAP_VAL)
+
+
+/** @brief Compare Bluetooth UUIDs.
+ *
+ *  Compares 2 Bluetooth UUIDs, if the types are different both UUIDs are
+ *  first converted to 128 bits format before comparing.
+ *
+ *  @param u1 First Bluetooth UUID to compare
+ *  @param u2 Second Bluetooth UUID to compare
+ *
+ *  @return negative value if @a u1 < @a u2, 0 if @a u1 == @a u2, else positive
+ */
+int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2);
+
+/** @brief Create a bt_uuid from a little-endian data buffer.
+ *
+ *  Create a bt_uuid from a little-endian data buffer. The data_len parameter
+ *  is used to determine whether the UUID is in 16, 32 or 128 bit format
+ *  (length 2, 4 or 16). Note: 32 bit format is not allowed over the air.
+ *
+ *  @param uuid Pointer to the bt_uuid variable
+ *  @param data pointer to UUID stored in little-endian data buffer
+ *  @param data_len length of the UUID in the data buffer
+ *
+ *  @return true if the data was valid and the UUID was successfully created.
+ */
+bool bt_uuid_create(struct bt_uuid *uuid, const uint8_t *data, uint8_t data_len);
+
+/** @brief Convert Bluetooth UUID to string.
+ *
+ *  Converts Bluetooth UUID to string.
+ *  UUID can be in any format, 16-bit, 32-bit or 128-bit.
+ *
+ *  @param uuid Bluetooth UUID
+ *  @param str pointer where to put converted string
+ *  @param len length of str
+ *
+ *  @return N/A
+ */
+void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_UUID_H_ */
Index: ModuleDemo/BLE/CM0/User/include/cache.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/cache.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/cache.h	(working copy)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_CACHE_H_
+#define ZEPHYR_INCLUDE_CACHE_H_
+
+#include <kernel.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void arch_dcache_flush(void *addr, size_t size);
+void arch_dcache_invd(void *addr, size_t size);
+
+/**
+ *
+ * @brief Flush d-cache lines to main memory
+ *
+ * No alignment is required for either addr or size, but since
+ * sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for
+ * both is optimal.
+ *
+ * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
+ * kconfig option or it is detected at runtime.
+ *
+ * @param addr the pointer to start the multi-line flush
+ * @param size the number of bytes that are to be flushed
+ *
+ * @return N/A
+ */
+__syscall void sys_cache_flush(void *addr, size_t size);
+
+static inline void z_impl_sys_cache_flush(void *addr, size_t size)
+{
+	if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) {
+		arch_dcache_flush(addr, size);
+	}
+}
+
+/**
+ *
+ * @brief Invalidate d-cache lines
+ *
+ * No alignment is required for either addr or size, but since
+ * sys_cache_invd() iterates on the d-cache lines, a d-cache line alignment for
+ * both is optimal.
+ *
+ * The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
+ * kconfig option or it is detected at runtime.
+ *
+ * @param addr the pointer to start address
+ * @param size the number of bytes that are to be invalidated
+ *
+ * @return N/A
+ */
+__syscall void sys_cache_invd(void *addr, size_t size);
+
+static inline void z_impl_sys_cache_invd(void *addr, size_t size)
+{
+	if (IS_ENABLED(CONFIG_CACHE_FLUSHING)) {
+		arch_dcache_invd(addr, size);
+	}
+}
+
+/**
+ *
+ * @brief Get the d-cache line size.
+ *
+ * The API is provided to get the cache line size.
+ *
+ * @return size of the cache line or 0 if the cache is not enabled.
+ */
+static inline size_t sys_cache_line_size_get(void)
+{
+#ifdef CONFIG_CACHE_FLUSHING
+#ifdef CONFIG_CACHE_LINE_SIZE
+	return CONFIG_CACHE_LINE_SIZE;
+#else
+	return arch_cache_line_size_get();
+#endif /* CONFIG_CACHE_LINE_SIZE */
+#else
+	return 0;
+#endif /* CONFIG_CACHE_FLUSHING */
+}
+
+#include <syscalls/cache.h>
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_CACHE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/config.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/config.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/config.h	(working copy)
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_CONFIG_H_
+#define ZEPHYR_INCLUDE_CONFIG_H_
+
+#include <types.h>
+#include <toolchain/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __ORDER_BIG_ENDIAN__
+#define __ORDER_BIG_ENDIAN__            (1)
+#endif
+
+#ifndef __ORDER_LITTLE_ENDIAN__
+#define __ORDER_LITTLE_ENDIAN__         (2)
+#endif
+
+#define __BYTE_ORDER__                  __ORDER_LITTLE_ENDIAN__
+#define __CHAR_BIT__ 8
+#define __SIZEOF_LONG__ 4
+
+
+#ifndef __fallthrough
+#if __GNUC__ >= 7
+#define __fallthrough        __attribute__((fallthrough))
+#else
+#define __fallthrough
+#endif	/* __GNUC__ >= 7 */
+#endif
+
+#ifndef __packed
+#define __packed        __attribute__((__packed__))
+#endif
+#ifndef __aligned
+#define __aligned(x)	__attribute__((__aligned__(x)))
+#endif
+#define __may_alias     __attribute__((__may_alias__))
+#ifndef __printf_like
+#define __printf_like(f, a)   __attribute__((format (printf, f, a)))
+#endif
+#define __used		__attribute__((__used__))
+#define __deprecated	
+#ifndef __deprecated
+#define __deprecated	__attribute__((deprecated))
+#endif
+#define ARG_UNUSED(x) (void)(x)
+
+#define likely(x)   __builtin_expect((bool)!!(x), true)
+#define unlikely(x) __builtin_expect((bool)!!(x), false)
+
+#define popcount(x) __builtin_popcount(x)
+
+#ifndef __no_optimization
+#define __no_optimization __attribute__((optimize("-O0")))
+#endif
+
+#ifndef __weak
+#define __weak __attribute__((__weak__))
+#endif
+#define __unused __attribute__((__unused__))
+
+#define __builtin_unreachable() do { __ASSERT(false, "Unreachable code"); } \
+	while (true)
+	
+#define CODE_UNREACHABLE __builtin_unreachable()
+
+#define FUNC_NORETURN    __attribute__((__noreturn__))
+
+
+
+#ifndef errno
+#define errno (*z_errno())
+#endif
+
+/*
+ * POSIX Error codes
+ */
+
+#define EPERM 1		/* Not owner */
+#define ENOENT 2	/* No such file or directory */
+#define ESRCH 3		/* No such context */
+#define EINTR 4		/* Interrupted system call */
+#define EIO 5		/* I/O error */
+#define ENXIO 6		/* No such device or address */
+#define E2BIG 7		/* Arg list too long */
+#define ENOEXEC 8       /* Exec format error */
+#define EBADF 9		/* Bad file number */
+#define ECHILD 10       /* No children */
+#define EAGAIN 11       /* No more contexts */
+#define ENOMEM 12       /* Not enough core */
+#define EACCES 13       /* Permission denied */
+#define EFAULT 14       /* Bad address */
+#define ENOTEMPTY 15    /* Directory not empty */
+#define EBUSY 16	/* Mount device busy */
+#define EEXIST 17       /* File exists */
+#define EXDEV 18	/* Cross-device link */
+#define ENODEV 19       /* No such device */
+#define ENOTDIR 20      /* Not a directory */
+#define EISDIR 21       /* Is a directory */
+#define EINVAL 22       /* Invalid argument */
+#define ENFILE 23       /* File table overflow */
+#define EMFILE 24       /* Too many open files */
+#define ENOTTY 25       /* Not a typewriter */
+#define ENAMETOOLONG 26 /* File name too long */
+#define EFBIG 27	/* File too large */
+#define ENOSPC 28       /* No space left on device */
+#define ESPIPE 29       /* Illegal seek */
+#define EROFS 30	/* Read-only file system */
+#define EMLINK 31       /* Too many links */
+#define EPIPE 32	/* Broken pipe */
+#define EDEADLK 33      /* Resource deadlock avoided */
+#define ENOLCK 34       /* No locks available */
+#define ENOTSUP 35      /* Unsupported value */
+#define EMSGSIZE 36     /* Message size */
+
+/* ANSI math software */
+#define EDOM 37   /* Argument too large */
+#define ERANGE 38 /* Result too large */
+
+/* ipc/network software */
+
+/* argument errors */
+#define EDESTADDRREQ 40    /* Destination address required */
+#define EPROTOTYPE 41      /* Protocol wrong type for socket */
+#define ENOPROTOOPT 42     /* Protocol not available */
+#define EPROTONOSUPPORT 43 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
+#define EOPNOTSUPP 45      /* Operation not supported on socket */
+#define EPFNOSUPPORT 46    /* Protocol family not supported */
+#define EAFNOSUPPORT 47    /* Addr family not supported */
+#define EADDRINUSE 48      /* Address already in use */
+#define EADDRNOTAVAIL 49   /* Can't assign requested address */
+#define ENOTSOCK 50	/* Socket operation on non-socket */
+
+/* operational errors */
+#define ENETUNREACH 51  /* Network is unreachable */
+#define ENETRESET 52    /* Network dropped connection on reset */
+#define ECONNABORTED 53 /* Software caused connection abort */
+#define ECONNRESET 54   /* Connection reset by peer */
+#define ENOBUFS 55      /* No buffer space available */
+#define EISCONN 56      /* Socket is already connected */
+#define ENOTCONN 57     /* Socket is not connected */
+#define ESHUTDOWN 58    /* Can't send after socket shutdown */
+#define ETOOMANYREFS 59 /* Too many references: can't splice */
+#define ETIMEDOUT 60    /* Connection timed out */
+#define ECONNREFUSED 61 /* Connection refused */
+#define ENETDOWN 62     /* Network is down */
+#define ETXTBSY 63      /* Text file busy */
+#define ELOOP 64	/* Too many levels of symbolic links */
+#define EHOSTUNREACH 65 /* No route to host */
+#define ENOTBLK 66      /* Block device required */
+#define EHOSTDOWN 67    /* Host is down */
+
+/* non-blocking and interrupt i/o */
+#define EINPROGRESS 68 /* Operation now in progress */
+#define EALREADY 69    /* Operation already in progress */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+
+#define ENOSYS 71 /* Function not implemented */
+
+/* aio errors (should be under posix) */
+#define ECANCELED 72 /* Operation canceled */
+
+#define ERRMAX 81
+
+/* specific STREAMS errno values */
+
+#define ENOSR 74   /* Insufficient memory */
+#define ENOSTR 75  /* STREAMS device required */
+#define EPROTO 76  /* Generic STREAMS error */
+#define EBADMSG 77 /* Invalid STREAMS message */
+#define ENODATA 78 /* Missing expected message data */
+#define ETIME 79   /* STREAMS timeout occurred */
+#define ENOMSG 80  /* Unexpected message type */
+
+#define EILSEQ 138 /* Illegal byte sequence */
+
+#define irq_lock() 0 
+#define irq_unlock(key) 
+
+/* Unaligned access */
+#define UNALIGNED_GET(p)						\
+__extension__ ({							\
+	struct  __attribute__((__packed__)) {				\
+		__typeof__(*(p)) __v;					\
+	} *__p = (__typeof__(__p)) (p);					\
+	__p->__v;							\
+})
+    
+#define ___in_section(a, b, c) \
+        __attribute__((section("." Z_STRINGIFY(a)           \
+                    "." Z_STRINGIFY(b)          \
+                    "." Z_STRINGIFY(c))))
+#define __in_section(a, b, c) ___in_section(a, b, c)
+    
+#define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__)
+
+
+#if !defined(_ASMLANGUAGE)
+
+#define __noinit		__in_section_unique(_NOINIT_SECTION_NAME)
+#define __irq_vector_table	Z_GENERIC_SECTION(_IRQ_VECTOR_TABLE_SECTION_NAME)
+#define __sw_isr_table		Z_GENERIC_SECTION(_SW_ISR_TABLE_SECTION_NAME)
+
+#if defined(CONFIG_ARM)
+#define __kinetis_flash_config_section __in_section_unique(_KINETIS_FLASH_CONFIG_SECTION_NAME)
+#define __ti_ccfg_section Z_GENERIC_SECTION(_TI_CCFG_SECTION_NAME)
+#define __ccm_data_section Z_GENERIC_SECTION(_CCM_DATA_SECTION_NAME)
+#define __ccm_bss_section Z_GENERIC_SECTION(_CCM_BSS_SECTION_NAME)
+#define __ccm_noinit_section Z_GENERIC_SECTION(_CCM_NOINIT_SECTION_NAME)
+#define __dtcm_data_section Z_GENERIC_SECTION(_DTCM_DATA_SECTION_NAME)
+#define __dtcm_bss_section Z_GENERIC_SECTION(_DTCM_BSS_SECTION_NAME)
+#define __dtcm_noinit_section Z_GENERIC_SECTION(_DTCM_NOINIT_SECTION_NAME)
+#define __imx_boot_conf_section Z_GENERIC_SECTION(_IMX_BOOT_CONF_SECTION_NAME)
+#define __imx_boot_data_section Z_GENERIC_SECTION(_IMX_BOOT_DATA_SECTION_NAME)
+#define __imx_boot_ivt_section Z_GENERIC_SECTION(_IMX_BOOT_IVT_SECTION_NAME)
+#define __imx_boot_dcd_section Z_GENERIC_SECTION(_IMX_BOOT_DCD_SECTION_NAME)
+#endif /* CONFIG_ARM */
+
+#if defined(CONFIG_NOCACHE_MEMORY)
+#define __nocache __in_section_unique(_NOCACHE_SECTION_NAME)
+#else
+#define __nocache
+#endif /* CONFIG_NOCACHE_MEMORY */
+
+#endif /* !_ASMLANGUAGE */
+
+
+/**
+ * Function used to read the data from the settings storage in
+ * h_set handler implementations.
+ *
+ * @param[in] cb_arg  arguments for the read function. Appropriate cb_arg is
+ *                    transferred to h_set handler implementation by
+ *                    the backend.
+ * @param[out] data  the destination buffer
+ * @param[in] len    length of read
+ *
+ * @return positive: Number of bytes read, 0: key-value pair is deleted.
+ *                   On error returns -ERRNO code.
+ */
+typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len);
+
+
+
+/* number of nsec per usec */
+#define NSEC_PER_USEC 1000U
+
+/* number of microseconds per millisecond */
+#define USEC_PER_MSEC 1000U
+
+/* number of milliseconds per second */
+#define MSEC_PER_SEC 1000U
+
+/* number of microseconds per second */
+#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC))
+
+/* number of nanoseconds per second */
+#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC))
+
+
+
+
+
+#define CONFIG_LOG 1
+#define CONFIG_LOG_MINIMAL 1
+#define CONFIG_PRINTK 1
+
+#define CONFIG_NET_BUF_LOG 1
+#define CONFIG_NET_BUF_SIMPLE_LOG 1
+
+
+#define CONFIG_BT_DEBUG 1
+#define CONFIG_BT_DEBUG_CONN 1
+
+
+#define CONFIG_BT_DEBUG_HCI_DRIVER 1
+#define CONFIG_NET_BUF_USER_DATA_SIZE 1
+
+#define CONFIG_BT_ID_MAX (1)
+#define CONFIG_BT_HCI_CMD_COUNT (6)
+#define CONFIG_BT_RX_BUF_COUNT (6)
+#define CONFIG_BT_RX_BUF_LEN (400)
+#define CONFIG_BT_HCI_RESERVE (4)
+
+#define CONFIG_BT_MAX_CONN (1)
+#define CONFIG_BT_MAX_PAIRED (1)
+#define CONFIG_BT_CONN_TX_MAX (6)
+#define ATT_CHAN_MAX (4)
+
+
+
+#define CONFIG_BT_L2CAP_TX_BUF_COUNT (6)
+#define CONFIG_BT_L2CAP_TX_MTU (1024)
+#define CONFIG_BT_L2CAP_RX_MTU (1024)
+#define CONFIG_BT_ATT_TX_MAX (6)
+
+#define CONFIG_BT_L2CAP_FIXED_CHAN_SIZE (2)
+
+
+#define CONFIG_BT_CREATE_CONN_TIMEOUT (1024)
+
+
+
+#define CONFIG_BT_BACKGROUND_SCAN_INTERVAL (100)
+#define CONFIG_BT_BACKGROUND_SCAN_WINDOW (100)
+
+#define CONFIG_BT_DEVICE_APPEARANCE (0x12)
+
+#define CONFIG_BT_DEVICE_NAME "ZephyrTest"
+
+#define CONFIG_BT_CONN      1
+//#define CONFIG_BT_EXT_ADV (FALSE)
+#define CONFIG_BT_EXT_ADV_MAX_ADV_SET       1
+
+
+#define CONFIG_BT_GATT_CLIENT       1
+
+//#define CONFIG_BT_ISO 0
+//#define CONFIG_BT_L2CAP_DYNAMIC_CHANNEL (TRUE)
+#define CONFIG_BT_CENTRAL       1
+//#define CONFIG_BT_WHITELIST (FALSE)
+#define CONFIG_BT_BROADCASTER       1
+//#define CONFIG_BT_PRIVACY (FALSE)
+#define CONFIG_BT_OBSERVER      1
+//#define CONFIG_BT_SCAN_WITH_IDENTITY (FALSE)
+//#define CONFIG_BT_HCI_VS_EXT (FALSE)
+//#define CONFIG_BT_TINYCRYPT_ECC (FALSE)
+//#define CONFIG_BT_HOST_CRYPTO (FALSE)
+//#define CONFIG_BT_PER_ADV_SYNC (FALSE)
+//#define CONFIG_BT_SMP (FALSE)
+//#define CONFIG_BT_DATA_LEN_UPDATE (FALSE)
+//#define CONFIG_BT_PHY_UPDATE (FALSE)
+//#define CONFIG_BT_ECC (FALSE)
+//#define CONFIG_BT_AUTO_DATA_LEN_UPDATE (FALSE)
+//#define CONFIG_BT_BREDR (FALSE)
+//#define CONFIG_BT_SETTINGS (FALSE)
+//#define CONFIG_BT_SETTINGS (FALSE)
+//#define CONFIG_BT_SETTINGS (FALSE)
+//#define CONFIG_BT_SETTINGS (FALSE)
+//#define CONFIG_BT_SETTINGS (FALSE)
+
+
+#if 0
+enum {
+	hci_cmd_pool = 0,
+	hci_rx_pool,
+	num_complete_pool,
+	discardable_pool,
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_CONFIG_H_ */
Index: ModuleDemo/BLE/CM0/User/include/drivers/bluetooth/hci_driver.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/drivers/bluetooth/hci_driver.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/drivers/bluetooth/hci_driver.h	(working copy)
@@ -0,0 +1,261 @@
+/** @file
+ *  @brief Bluetooth HCI driver API.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_H_
+#define ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_H_
+
+/**
+ * @brief HCI drivers
+ * @defgroup bt_hci_driver HCI drivers
+ * @ingroup bluetooth
+ * @{
+ */
+
+#include <stdbool.h>
+#include <net/buf.h>
+#include <bluetooth/buf.h>
+#include <bluetooth/hci_vs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+	/* The host should never send HCI_Reset */
+	BT_QUIRK_NO_RESET = BIT(0),
+	/* The controller does not auto-initiate a DLE procedure when the
+	 * initial connection data length parameters are not equal to the
+	 * default data length parameters. Therefore the host should initiate
+	 * the DLE procedure after connection establishment. */
+	BT_QUIRK_NO_AUTO_DLE = BIT(1),
+};
+
+#define IS_BT_QUIRK_NO_AUTO_DLE(bt_dev) ((bt_dev)->drv->quirks & BT_QUIRK_NO_AUTO_DLE)
+
+/* @brief The HCI event shall be given to bt_recv_prio */
+#define BT_HCI_EVT_FLAG_RECV_PRIO BIT(0)
+/* @brief  The HCI event shall be given to bt_recv. */
+#define BT_HCI_EVT_FLAG_RECV      BIT(1)
+
+/** @brief Get HCI event flags.
+ *
+ * Helper for the HCI driver to get HCI event flags that describes rules that.
+ * must be followed.
+ *
+ * When CONFIG_BT_RECV_IS_RX_THREAD is enabled the flags
+ * BT_HCI_EVT_FLAG_RECV and BT_HCI_EVT_FLAG_RECV_PRIO indicates if the event
+ * should be given to bt_recv or bt_recv_prio.
+ *
+ * @param evt HCI event code.
+ *
+ * @return HCI event flags for the specified event.
+ */
+static inline uint8_t bt_hci_evt_get_flags(uint8_t evt)
+{
+	switch (evt) {
+	case BT_HCI_EVT_DISCONN_COMPLETE:
+		return BT_HCI_EVT_FLAG_RECV | BT_HCI_EVT_FLAG_RECV_PRIO;
+		/* fallthrough */
+#if defined(CONFIG_BT_CONN)
+	case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
+	case BT_HCI_EVT_DATA_BUF_OVERFLOW:
+		__fallthrough;
+#endif /* defined(CONFIG_BT_CONN) */
+	case BT_HCI_EVT_CMD_COMPLETE:
+	case BT_HCI_EVT_CMD_STATUS:
+		return BT_HCI_EVT_FLAG_RECV_PRIO;
+	default:
+		return BT_HCI_EVT_FLAG_RECV;
+	}
+}
+
+/**
+ * @brief Receive data from the controller/HCI driver.
+ *
+ * This is the main function through which the HCI driver provides the
+ * host with data from the controller. The buffer needs to have its type
+ * set with the help of bt_buf_set_type() before calling this API.
+ *
+ * When CONFIG_BT_RECV_IS_RX_THREAD is defined then this API should not be used
+ * for so-called high priority HCI events, which should instead be delivered to
+ * the host stack through bt_recv_prio().
+ *
+ * @param buf Network buffer containing data from the controller.
+ *
+ * @return 0 on success or negative error number on failure.
+ */
+int bt_recv(struct net_buf *buf);
+
+/**
+ * @brief Receive high priority data from the controller/HCI driver.
+ *
+ * This is the same as bt_recv(), except that it should be used for
+ * so-called high priority HCI events. There's a separate
+ * bt_hci_evt_get_flags() helper that can be used to identify which events
+ * have the BT_HCI_EVT_FLAG_RECV_PRIO flag set.
+ *
+ * As with bt_recv(), the buffer needs to have its type set with the help of
+ * bt_buf_set_type() before calling this API. The only exception is so called
+ * high priority HCI events which should be delivered to the host stack through
+ * bt_recv_prio() instead.
+ *
+ * @param buf Network buffer containing data from the controller.
+ *
+ * @return 0 on success or negative error number on failure.
+ */
+int bt_recv_prio(struct net_buf *buf);
+
+/** @brief Read static addresses from the controller.
+ *
+ *  @param addrs  Random static address and Identity Root (IR) array.
+ *  @param size   Size of array.
+ *
+ *  @return Number of addresses read.
+ */
+uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size);
+
+/** Possible values for the 'bus' member of the bt_hci_driver struct */
+enum bt_hci_driver_bus {
+	BT_HCI_DRIVER_BUS_VIRTUAL       = 0,
+	BT_HCI_DRIVER_BUS_USB           = 1,
+	BT_HCI_DRIVER_BUS_PCCARD        = 2,
+	BT_HCI_DRIVER_BUS_UART          = 3,
+	BT_HCI_DRIVER_BUS_RS232         = 4,
+	BT_HCI_DRIVER_BUS_PCI           = 5,
+	BT_HCI_DRIVER_BUS_SDIO          = 6,
+	BT_HCI_DRIVER_BUS_SPI           = 7,
+	BT_HCI_DRIVER_BUS_I2C           = 8,
+	BT_HCI_DRIVER_BUS_IPM           = 9,
+};
+
+/**
+ * @brief Abstraction which represents the HCI transport to the controller.
+ *
+ * This struct is used to represent the HCI transport to the Bluetooth
+ * controller.
+ */
+struct bt_hci_driver {
+	/** Name of the driver */
+	const char *name;
+
+	/** Bus of the transport (BT_HCI_DRIVER_BUS_*) */
+	enum bt_hci_driver_bus bus;
+
+	/** Specific controller quirks. These are set by the HCI driver
+	 *  and acted upon by the host. They can either be statically
+	 *  set at buildtime, or set at runtime before the HCI driver's
+	 *  open() callback returns.
+	 */
+	uint32_t quirks;
+
+	/**
+	 * @brief Open the HCI transport.
+	 *
+	 * Opens the HCI transport for operation. This function must not
+	 * return until the transport is ready for operation, meaning it
+	 * is safe to start calling the send() handler.
+	 *
+	 * If the driver uses its own RX thread, i.e.
+	 * CONFIG_BT_RECV_IS_RX_THREAD is set, then this
+	 * function is expected to start that thread.
+	 *
+	 * @return 0 on success or negative error number on failure.
+	 */
+	int (*open)(void);
+
+	/**
+	 * @brief Send HCI buffer to controller.
+	 *
+	 * Send an HCI command or ACL data to the controller. The exact
+	 * type of the data can be checked with the help of bt_buf_get_type().
+	 *
+	 * @note This function must only be called from a cooperative thread.
+	 *
+	 * @param buf Buffer containing data to be sent to the controller.
+	 *
+	 * @return 0 on success or negative error number on failure.
+	 */
+	int (*send)(struct net_buf *buf);
+};
+
+/**
+ * @brief Register a new HCI driver to the Bluetooth stack.
+ *
+ * This needs to be called before any application code runs. The bt_enable()
+ * API will fail if there is no driver registered.
+ *
+ * @param drv A bt_hci_driver struct representing the driver.
+ *
+ * @return 0 on success or negative error number on failure.
+ */
+int bt_hci_driver_register(const struct bt_hci_driver *drv);
+
+/**
+ * @brief Setup the HCI transport, which usually means to reset the
+ * Bluetooth IC.
+ *
+ * @note A weak version of this function is included in the H4 driver, so
+ *       defining it is optional per board.
+ *
+ * @param dev The device structure for the bus connecting to the IC
+ *
+ * @return 0 on success, negative error value on failure
+ */
+//int bt_hci_transport_setup(const struct device *dev);
+
+/** Allocate an HCI event buffer.
+ *
+ * This function allocates a new buffer for an HCI event. It is given the
+ * avent code and the total length of the parameters. Upon successful return
+ * the buffer is ready to have the parameters encoded into it.
+ *
+ * @param evt        Event OpCode.
+ * @param len        Length of event parameters.
+ *
+ * @return Newly allocated buffer.
+ */
+struct net_buf *bt_hci_evt_create(uint8_t evt, uint8_t len);
+
+/** Allocate an HCI Command Complete event buffer.
+ *
+ * This function allocates a new buffer for HCI Command Complete event.
+ * It is given the OpCode (encoded e.g. using the BT_OP macro) and the total
+ * length of the parameters. Upon successful return the buffer is ready to have
+ * the parameters encoded into it.
+ *
+ * @param op         Command OpCode.
+ * @param plen       Length of command parameters.
+ *
+ * @return Newly allocated buffer.
+ */
+struct net_buf *bt_hci_cmd_complete_create(uint16_t op, uint8_t plen);
+
+/** Allocate an HCI Command Status event buffer.
+ *
+ * This function allocates a new buffer for HCI Command Status event.
+ * It is given the OpCode (encoded e.g. using the BT_OP macro) and the status
+ * code. Upon successful return the buffer is ready to have the parameters
+ * encoded into it.
+ *
+ * @param op         Command OpCode.
+ * @param status     Status code.
+ *
+ * @return Newly allocated buffer.
+ */
+struct net_buf *bt_hci_cmd_status_create(uint16_t op, uint8_t status);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_H_ */
Index: ModuleDemo/BLE/CM0/User/include/ec_host_cmd.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/ec_host_cmd.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/ec_host_cmd.h	(working copy)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2020 Google LLC
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_EC_HOST_CMD_H_
+#define ZEPHYR_INCLUDE_EC_HOST_CMD_H_
+
+/**
+ * @brief EC Host Command Interface
+ * @defgroup ec_host_cmd_periph_interface EC Host Command Interface
+ * @ingroup io_interfaces
+ * @{
+ */
+
+#include <stdint.h>
+
+/**
+ * @brief Arguments passed into every installed host command handler
+ */
+struct ec_host_cmd_handler_args {
+	/** The incoming data that can be cast to the handlers request type. */
+	const void *const input_buf;
+	/** The number of valid bytes that can be read from @a input_buf. */
+	const uint16_t input_buf_size;
+	/** The data written to this buffer will be send to the host. */
+	void *const output_buf;
+	/** [in/out] Upon entry, this is the maximum number of bytes that can
+	 *  be written to the @a output_buf. Upon exit, this should be
+	 *  the number of bytes of @a output_buf to send to the host.
+	 */
+	uint16_t output_buf_size;
+	/** The version of the host command that is being requested. This will
+	 *  be a value that has been static registered as valid for the handler.
+	 */
+	const uint8_t version;
+};
+
+typedef enum ec_host_cmd_status (*ec_host_cmd_handler_cb)(
+	struct ec_host_cmd_handler_args *args);
+/**
+ * @brief Structure use for statically registering host command handlers
+ */
+struct ec_host_cmd_handler {
+	/** Callback routine to process commands that match @a id. */
+	ec_host_cmd_handler_cb handler;
+	/** The numberical command id used as the lookup for commands. */
+	uint16_t id;
+	/** The bitfield of all versions that the @a handler supports, where
+	 *  each bit value represents that the @a handler supports that version.
+	 *  E.g. BIT(0) corresponse to version 0.
+	 */
+	uint16_t version_mask;
+	/** The minimum @a input_buf_size enforced by the framework before
+	 *  passing to the handler.
+	 */
+	uint16_t min_rqt_size;
+	/** The minimum @a output_buf_size enforced by the framework before
+	 *  passing to the handler.
+	 */
+	uint16_t min_rsp_size;
+};
+
+/**
+ * @def EC_HOST_CMD_HANDLER
+ * @brief Statically define and register a host command handler.
+ *
+ * Helper macro to statically define and register a host command handler that
+ * has a compile-time-fixed sizes for its both request and response structures.
+ *
+ * @param _function Name of handler function.
+ * @param _id Id of host command to handle request for.
+ * @param _version_mask The bitfield of all versions that the @a _function
+ *        supports. E.g. BIT(0) corresponse to version 0.
+ * @param _request_type The datatype of the request parameters for @a _function.
+ * @param _response_type The datatype of the response parameters for
+ *        @a _function.
+ */
+#define EC_HOST_CMD_HANDLER(_function, _id, _version_mask, _request_type,      \
+			    _response_type)                                    \
+	const Z_STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = {   \
+		.id = _id,                                                     \
+		.handler = _function,                                          \
+		.version_mask = _version_mask,                                 \
+		.min_rqt_size = sizeof(_request_type),                         \
+		.min_rsp_size = sizeof(_response_type),                        \
+	}
+
+/**
+ * @def EC_HOST_CMD_HANDLER_UNBOUND
+ * @brief Statically define and register a host command handler without sizes.
+ *
+ * Helper macro to statically define and register a host command handler whose
+ * request or response structure size is not known as compile time.
+ *
+ * @param _function Name of handler function.
+ * @param _id Id of host command to handle request for.
+ * @param _version_mask The bitfield of all versions that the @a _function
+ *        supports. E.g. BIT(0) corresponse to version 0.
+ */
+#define EC_HOST_CMD_HANDLER_UNBOUND(_function, _id, _version_mask)             \
+	const Z_STRUCT_SECTION_ITERABLE(ec_host_cmd_handler, __cmd##_id) = {   \
+		.id = _id,                                                     \
+		.handler = _function,                                          \
+		.version_mask = _version_mask,                                 \
+		.min_rqt_size = 0,                                             \
+		.min_rsp_size = 0,                                             \
+	}
+
+/**
+ * @brief Header for requests from host to embedded controller
+ *
+ * Represent the over-the-wire header in LE format for host command requests.
+ * This represent version 3 of the host command header. The requests are always
+ * sent from host to embedded controller.
+ */
+struct ec_host_cmd_request_header {
+	/** Should be 3. The EC will return EC_HOST_CMD_INVALID_HEADER if it
+	 *  receives a header with a version it doesn't know how to parse.
+	 */
+	uint8_t prtcl_ver;
+	/** Checksum of response and data; sum of all bytes including checksum.
+	 *  Should total to 0.
+	 */
+	uint8_t checksum;
+	/** Id of command that is being sent. */
+	uint16_t cmd_id;
+	/** Version of the specific @a cmd_id being requested. Valid
+	 *  versions start at 0.
+	 */
+	uint8_t cmd_ver;
+	/** Unused byte in current protocol version; set to 0. */
+	uint8_t reserved;
+	/** Length of data which follows this header. */
+	uint16_t data_len;
+} __packed;
+
+/**
+ * @brief Header for responses from embedded controller to host
+ *
+ * Represent the over-the-wire header in LE format for host command responses.
+ * This represent version 3 of the host command header. Responses are always
+ * sent from embedded controller to host.
+ */
+struct ec_host_cmd_response_header {
+	/** Should be 3. */
+	uint8_t prtcl_ver;
+	/** Checksum of response and data; sum of all bytes including checksum.
+	 *  Should total to 0.
+	 */
+	uint8_t checksum;
+	/** A @a ec_host_cmd_status response code for specific command. */
+	uint16_t result;
+	/** Length of data which follows this header. */
+	uint16_t data_len;
+	/** Unused bytes in current protocol version; set to 0. */
+	uint16_t reserved;
+} __packed;
+
+/*
+ * Host command response codes (16-bit).
+ */
+enum ec_host_cmd_status {
+	/** Host command was successful. */
+	EC_HOST_CMD_SUCCESS = 0,
+	/** The specified command id is not recognized or supported. */
+	EC_HOST_CMD_INVALID_COMMAND = 1,
+	/** Generic Error. */
+	EC_HOST_CMD_ERROR = 2,
+	/** One of more of the input request parameters is invalid. */
+	EC_HOST_CMD_INVALID_PARAM = 3,
+	/** Host command is not permitted. */
+	EC_HOST_CMD_ACCESS_DENIED = 4,
+	/** Response was invalid (e.g. not version 3 of header). */
+	EC_HOST_CMD_INVALID_RESPONSE = 5,
+	/** Host command id version unsupported. */
+	EC_HOST_CMD_INVALID_VERSION = 6,
+	/** Checksum did not match */
+	EC_HOST_CMD_INVALID_CHECKSUM = 7,
+	/** A host command is currently being processed. */
+	EC_HOST_CMD_IN_PROGRESS = 8,
+	/** Requested information is currently unavailable. */
+	EC_HOST_CMD_UNAVAILABLE = 9,
+	/** Timeout during processing. */
+	EC_HOST_CMD_TIMEOUT = 10,
+	/** Data or table overflow. */
+	EC_HOST_CMD_OVERFLOW = 11,
+	/** Header is invalid or unsupported (e.g. not version 3 of header). */
+	EC_HOST_CMD_INVALID_HEADER = 12,
+	/** Did not receive all expected request data. */
+	EC_HOST_CMD_REQUEST_TRUNCATED = 13,
+	/** Response was too big to send within one response packet. */
+	EC_HOST_CMD_RESPONSE_TOO_BIG = 14,
+	/** Error on underlying communication bus. */
+	EC_HOST_CMD_BUS_ERROR = 15,
+	/** System busy. Should retry later. */
+	EC_HOST_CMD_BUSY = 16,
+
+	EC_HOST_CMD_MAX = UINT16_MAX /* Force enum to be 16 bits */
+} __packed;
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_EC_HOST_CMD_H_ */
Index: ModuleDemo/BLE/CM0/User/include/emul.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/emul.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/emul.h	(working copy)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright 2020 Google LLC
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_EMUL_H_
+#define ZEPHYR_INCLUDE_EMUL_H_
+
+/**
+ * @brief Emulators used to test drivers and higher-level code that uses them
+ * @defgroup io_emulators Emulator interface
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct device;
+struct emul;
+
+/**
+ * Structure uniquely identifying a device to be emulated
+ *
+ * Currently this uses the device node label, but that will go away by 2.5.
+ */
+struct emul_link_for_bus {
+	const char *label;
+};
+
+/** List of emulators attached to a bus */
+struct emul_list_for_bus {
+	/** Identifiers for children of the node */
+	const struct emul_link_for_bus *children;
+	/** Number of children of the node */
+	unsigned int num_children;
+};
+
+/**
+ * Standard callback for emulator initialisation providing the initialiser
+ * record and the device that calls the emulator functions.
+ *
+ * @param emul Emulator to init
+ * @param parent Parent device that is using the emulator
+ */
+typedef int (*emul_init_t)(const struct emul *emul,
+			   const struct device *parent);
+
+/** An emulator instance */
+struct emul {
+	/** function used to initialise the emulator state */
+	emul_init_t init;
+	/** handle to the device for which this provides low-level emulation */
+	const char *dev_label;
+	/** Emulator-specific configuration data */
+	const void *cfg;
+};
+
+/**
+ * Emulators are aggregated into an array at link time, from which emulating
+ * devices can find the emulators that they are to use.
+ */
+extern const struct emul __emul_list_start[];
+extern const struct emul __emul_list_end[];
+
+/* Use the devicetree node identifier as a unique name. */
+#define EMUL_REG_NAME(node_id) (_CONCAT(__emulreg_, node_id))
+
+/**
+ * Define a new emulator
+ *
+ * This adds a new struct emul to the linker list of emulations. This is
+ * typically used in your emulator's DT_INST_FOREACH_STATUS_OKAY() clause.
+ *
+ * @param init_ptr function to call to initialise the emulator (see emul_init
+ *	typedef)
+ * @param node_id Node ID of the driver to emulate (e.g. DT_DRV_INST(n))
+ * @param cfg_ptr emulator-specific configuration data
+ */
+#define EMUL_DEFINE(init_ptr, node_id, cfg_ptr)			\
+	static struct emul EMUL_REG_NAME(node_id)		\
+	__attribute__((__section__(".emulators"))) __used = {	\
+		.init = (init_ptr),				\
+		.dev_label = DT_LABEL(node_id),			\
+		.cfg = (cfg_ptr),				\
+	};
+
+/**
+ * Set up a list of emulators
+ *
+ * @param dev Device the emulators are attached to (e.g. an I2C controller)
+ * @param list List of devices to set up
+ * @return 0 if OK
+ * @return negative value on error
+ */
+int emul_init_for_bus_from_list(const struct device *dev,
+				const struct emul_list_for_bus *list);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_EMUL_H_ */
Index: ModuleDemo/BLE/CM0/User/include/exc_handle.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/exc_handle.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/exc_handle.h	(working copy)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_EXC_HANDLE_H_
+#define ZEPHYR_INCLUDE_EXC_HANDLE_H_
+
+/*
+ * This is used by some architectures to define code ranges which may
+ * perform operations that could generate a CPU exception that should not
+ * be fatal. Instead, the exception should return but set the program
+ * counter to a 'fixup' memory address which will gracefully error out.
+ *
+ * For example, in the case where user mode passes in a C string via
+ * system call, the length of that string needs to be measured. A specially
+ * written assembly language version of strlen (arch_user_string_len)
+ * defines start and end symbols where the memory in the string is examined;
+ * if this generates a fault, jumping to the fixup symbol within the same
+ * function will return an error result to the caller.
+ *
+ * To ensure precise control of the state of registers and the stack pointer,
+ * these functions need to be written in assembly.
+ *
+ * The arch-specific fault handling code will define an array of these
+ * z_exc_handle structures and return from the exception with the PC updated
+ * to the fixup address if a match is found.
+ */
+
+struct z_exc_handle {
+	void *start;
+	void *end;
+	void *fixup;
+};
+
+#define Z_EXC_HANDLE(name) \
+	{ name ## _fault_start, name ## _fault_end, name ## _fixup }
+
+#define Z_EXC_DECLARE(name)          \
+	void name ## _fault_start(void); \
+	void name ## _fault_end(void);   \
+	void name ## _fixup(void)
+
+#endif /* ZEPHYR_INCLUDE_EXC_HANDLE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/generated_dts_board.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/generated_dts_board.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/generated_dts_board.h	(working copy)
@@ -0,0 +1,2 @@
+#warning "generated_dts_board.h has been renamed to devicetree.h. Please include that instead."
+#include <devicetree.h>
Index: ModuleDemo/BLE/CM0/User/include/init.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/init.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/init.h	(working copy)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_INIT_H_
+#define ZEPHYR_INCLUDE_INIT_H_
+
+#include <toolchain.h>
+#include <kernel.h>
+#include <types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * System initialization levels. The PRE_KERNEL_1 and PRE_KERNEL_2 levels are
+ * executed in the kernel's initialization context, which uses the interrupt
+ * stack. The remaining levels are executed in the kernel's main task.
+ */
+
+#define _SYS_INIT_LEVEL_PRE_KERNEL_1	0
+#define _SYS_INIT_LEVEL_PRE_KERNEL_2	1
+#define _SYS_INIT_LEVEL_POST_KERNEL	2
+#define _SYS_INIT_LEVEL_APPLICATION	3
+
+#ifdef CONFIG_SMP
+#define _SYS_INIT_LEVEL_SMP		4
+#endif
+
+struct device;
+
+/**
+ * @brief Static init entry structure for each device driver or services
+ *
+ * @param init init function for the init entry which will take the dev
+ * attribute as parameter. See below.
+ * @param dev pointer to a device driver instance structure. Can be NULL
+ * if the init entry is not used for a device driver but a service.
+ */
+struct init_entry {
+	/** Initialization function for the init entry which will take
+	 * the dev attribute as parameter. See below.
+	 */
+	int (*init)(const struct device *dev);
+	/** Pointer to a device driver instance structure. Can be NULL
+	 * if the init entry is not used for a device driver but a services.
+	 */
+	const struct device *dev;
+};
+
+void z_sys_init_run_level(int32_t _level);
+
+/* A counter is used to avoid issues when two or more system devices
+ * are declared in the same C file with the same init function.
+ */
+#define Z_SYS_NAME(_init_fn) _CONCAT(_CONCAT(sys_init_, _init_fn), __COUNTER__)
+
+/**
+ * @def Z_INIT_ENTRY_DEFINE
+ *
+ * @brief Create an init entry object and set it up for boot time initialization
+ *
+ * @details This macro defines an init entry object that will be automatically
+ * configured by the kernel during system initialization. Note that
+ * init entries will not be accessible from user mode. Also this macro should
+ * not be used directly, use relevant macro such as SYS_INIT() or
+ * DEVICE_AND_API_INIT() instead.
+ *
+ * @param _entry_name Init entry name. It is the name this instance exposes to
+ * the system.
+ *
+ * @param _init_fn Address to the init function of the entry.
+ *
+ * @param _device A device driver instance pointer or NULL
+ *
+ * @param _level The initialization level at which configuration
+ * occurs.  See SYS_INIT().
+ *
+ * @param prio The initialization priority of the object, relative to
+ * other objects of the same initialization level. See SYS_INIT().
+ */
+#define Z_INIT_ENTRY_DEFINE(_entry_name, _init_fn, _device, _level, _prio)	\
+	static const Z_DECL_ALIGN(struct init_entry)			\
+		_CONCAT(__init_, _entry_name) __used			\
+	__attribute__((__section__(".init_" #_level STRINGIFY(_prio)))) = { \
+		.init = (_init_fn),					\
+		.dev = (_device),					\
+	}
+
+/**
+ * @def SYS_INIT
+ *
+ * @ingroup device_model
+ *
+ * @brief Run an initialization function at boot at specified priority
+ *
+ * @details This macro lets you run a function at system boot.
+ *
+ * @param _init_fn Pointer to the boot function to run
+ *
+ * @param _level The initialization level at which configuration occurs.
+ * Must be one of the following symbols, which are listed in the order
+ * they are performed by the kernel:
+ * \n
+ * \li PRE_KERNEL_1: Used for initialization objects that have no dependencies,
+ * such as those that rely solely on hardware present in the processor/SOC.
+ * These objects cannot use any kernel services during configuration, since
+ * they are not yet available.
+ * \n
+ * \li PRE_KERNEL_2: Used for initialization objects that rely on objects
+ * initialized as part of the PRE_KERNEL_1 level. These objects cannot use any
+ * kernel services during configuration, since they are not yet available.
+ * \n
+ * \li POST_KERNEL: Used for initialization objects that require kernel services
+ * during configuration.
+ * \n
+ * \li POST_KERNEL_SMP: Used for initialization objects that require kernel
+ * services during configuration after SMP initialization.
+ * \n
+ * \li APPLICATION: Used for application components (i.e. non-kernel components)
+ * that need automatic configuration. These objects can use all services
+ * provided by the kernel during configuration.
+ *
+ * @param _prio The initialization priority of the object, relative to
+ * other objects of the same initialization level. Specified as an integer
+ * value in the range 0 to 99; lower values indicate earlier initialization.
+ * Must be a decimal integer literal without leading zeroes or sign (e.g. 32),
+ * or an equivalent symbolic name (e.g. \#define MY_INIT_PRIO 32); symbolic
+ * expressions are *not* permitted
+ * (e.g. CONFIG_KERNEL_INIT_PRIORITY_DEFAULT + 5).
+ */
+#define SYS_INIT(_init_fn, _level, _prio)					\
+	Z_INIT_ENTRY_DEFINE(Z_SYS_NAME(_init_fn), _init_fn, NULL, _level, _prio)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_INIT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/kernel.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel.h	(working copy)
@@ -0,0 +1,1582 @@
+/*
+ * Copyright (c) 2016, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief Public kernel APIs.
+ */
+
+#ifndef ZEPHYR_INCLUDE_KERNEL_H_
+#define ZEPHYR_INCLUDE_KERNEL_H_
+
+#if !defined(_ASMLANGUAGE)
+#include <kernel_includes.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <toolchain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define K_PRIO_COOP(x) (-(_NUM_COOP_PRIO - (x)))
+#define K_PRIO_PREEMPT(x) (x)
+
+#define K_ANY NULL
+#define K_END NULL
+
+
+#ifdef CONFIG_PREEMPT_ENABLED
+#define K_LOWEST_THREAD_PRIO CONFIG_NUM_PREEMPT_PRIORITIES
+#else
+#define K_LOWEST_THREAD_PRIO -1
+#endif
+
+#define K_IDLE_PRIO K_LOWEST_THREAD_PRIO
+
+#define K_HIGHEST_APPLICATION_THREAD_PRIO (K_HIGHEST_THREAD_PRIO)
+#define K_LOWEST_APPLICATION_THREAD_PRIO (K_LOWEST_THREAD_PRIO - 1)
+
+#ifdef CONFIG_OBJECT_TRACING
+#define _OBJECT_TRACING_NEXT_PTR(type) struct type *__next;
+#define _OBJECT_TRACING_LINKED_FLAG uint8_t __linked;
+#define _OBJECT_TRACING_INIT \
+	.__next = NULL,	     \
+	.__linked = 0,
+#else
+#define _OBJECT_TRACING_INIT
+#define _OBJECT_TRACING_NEXT_PTR(type)
+#define _OBJECT_TRACING_LINKED_FLAG
+#endif
+
+#ifdef CONFIG_POLL
+#define _POLL_EVENT_OBJ_INIT(obj) \
+	.poll_events = SYS_DLIST_STATIC_INIT(&obj.poll_events),
+#define _POLL_EVENT sys_dlist_t poll_events
+#else
+#define _POLL_EVENT_OBJ_INIT(obj)
+#define _POLL_EVENT
+#endif
+
+struct k_queue;
+struct k_fifo;
+struct k_lifo;
+struct k_mem_pool;
+struct k_poll_event;
+struct k_poll_signal;
+struct k_futex;
+
+/**
+ * @typedef k_thread_entry_t
+ * @brief Thread entry point function type.
+ *
+ * A thread's entry point function is invoked when the thread starts executing.
+ * Up to 3 argument values can be passed to the function.
+ *
+ * The thread terminates execution permanently if the entry point function
+ * returns. The thread is responsible for releasing any shared resources
+ * it may own (such as mutexes and dynamically allocated memory), prior to
+ * returning.
+ *
+ * @param p1 First argument.
+ * @param p2 Second argument.
+ * @param p3 Third argument.
+ *
+ * @return N/A
+ */
+
+#ifdef CONFIG_THREAD_MONITOR
+struct __thread_entry {
+	k_thread_entry_t pEntry;
+	void *parameter1;
+	void *parameter2;
+	void *parameter3;
+};
+#endif
+
+
+/*
+ * Thread user options. May be needed by assembly code. Common part uses low
+ * bits, arch-specific use high bits.
+ */
+
+/**
+ * @brief system thread that must not abort
+ * */
+#define K_ESSENTIAL (BIT(0))
+
+#if defined(CONFIG_FPU_SHARING)
+/**
+ * @brief thread uses floating point registers
+ */
+#define K_FP_REGS (BIT(1))
+#endif
+
+/**
+ * @brief user mode thread
+ *
+ * This thread has dropped from supervisor mode to user mode and consequently
+ * has additional restrictions
+ */
+#define K_USER (BIT(2))
+
+/**
+ * @brief Inherit Permissions
+ *
+ * @details
+ * Indicates that the thread being created should inherit all kernel object
+ * permissions from the thread that created it. No effect if
+ * @option{CONFIG_USERSPACE} is not enabled.
+ */
+#define K_INHERIT_PERMS (BIT(3))
+
+#ifdef CONFIG_X86
+/* x86 Bitmask definitions for threads user options */
+
+#if defined(CONFIG_FPU_SHARING) && defined(CONFIG_SSE)
+/* thread uses SSEx (and also FP) registers */
+#define K_SSE_REGS (BIT(7))
+#endif
+#endif
+
+/* end - thread options */
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup clock_apis
+ * @{
+ */
+
+
+#ifdef CONFIG_TIMEOUT_64BIT
+
+/**
+ * @brief Generates an absolute/uptime timeout value from system ticks
+ *
+ * This macro generates a timeout delay that represents an expiration
+ * at the absolute uptime value specified, in system ticks.  That is, the
+ * timeout will expire immediately after the system uptime reaches the
+ * specified tick count.
+ *
+ * @param t Tick uptime value
+ * @return Timeout delay value
+ */
+#define K_TIMEOUT_ABS_TICKS(t) Z_TIMEOUT_TICKS(Z_TICK_ABS(MAX(t, 0)))
+
+/**
+ * @brief Generates an absolute/uptime timeout value from milliseconds
+ *
+ * This macro generates a timeout delay that represents an expiration
+ * at the absolute uptime value specified, in milliseconds.  That is,
+ * the timeout will expire immediately after the system uptime reaches
+ * the specified tick count.
+ *
+ * @param t Millisecond uptime value
+ * @return Timeout delay value
+ */
+#define K_TIMEOUT_ABS_MS(t) K_TIMEOUT_ABS_TICKS(k_ms_to_ticks_ceil64(t))
+
+/**
+ * @brief Generates an absolute/uptime timeout value from microseconds
+ *
+ * This macro generates a timeout delay that represents an expiration
+ * at the absolute uptime value specified, in microseconds.  That is,
+ * the timeout will expire immediately after the system uptime reaches
+ * the specified time.  Note that timer precision is limited by the
+ * system tick rate and not the requested timeout value.
+ *
+ * @param t Microsecond uptime value
+ * @return Timeout delay value
+ */
+#define K_TIMEOUT_ABS_US(t) K_TIMEOUT_ABS_TICKS(k_us_to_ticks_ceil64(t))
+
+/**
+ * @brief Generates an absolute/uptime timeout value from nanoseconds
+ *
+ * This macro generates a timeout delay that represents an expiration
+ * at the absolute uptime value specified, in nanoseconds.  That is,
+ * the timeout will expire immediately after the system uptime reaches
+ * the specified time.  Note that timer precision is limited by the
+ * system tick rate and not the requested timeout value.
+ *
+ * @param t Nanosecond uptime value
+ * @return Timeout delay value
+ */
+#define K_TIMEOUT_ABS_NS(t) K_TIMEOUT_ABS_TICKS(k_ns_to_ticks_ceil64(t))
+
+/**
+ * @brief Generates an absolute/uptime timeout value from system cycles
+ *
+ * This macro generates a timeout delay that represents an expiration
+ * at the absolute uptime value specified, in cycles.  That is, the
+ * timeout will expire immediately after the system uptime reaches the
+ * specified time.  Note that timer precision is limited by the system
+ * tick rate and not the requested timeout value.
+ *
+ * @param t Cycle uptime value
+ * @return Timeout delay value
+ */
+#define K_TIMEOUT_ABS_CYC(t) K_TIMEOUT_ABS_TICKS(k_cyc_to_ticks_ceil64(t))
+
+#endif
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+
+struct k_queue {
+	sys_sflist_t data_q;
+
+	_OBJECT_TRACING_NEXT_PTR(k_queue)
+	_OBJECT_TRACING_LINKED_FLAG
+};
+
+#define Z_QUEUE_INITIALIZER(obj) \
+	{ \
+	.data_q = SYS_SFLIST_STATIC_INIT(&obj.data_q), \
+	_POLL_EVENT_OBJ_INIT(obj)		\
+	_OBJECT_TRACING_INIT \
+	}
+
+extern void *z_queue_node_peek(sys_sfnode_t *node, bool needs_free);
+
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @defgroup queue_apis Queue APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Initialize a queue.
+ *
+ * This routine initializes a queue object, prior to its first use.
+ *
+ * @param queue Address of the queue.
+ *
+ * @return N/A
+ */
+static inline void k_queue_init(struct k_queue *queue)
+{
+    sys_sflist_init(&queue->data_q);
+}
+/**
+ * @brief Cancel waiting on a queue.
+ *
+ * This routine causes first thread pending on @a queue, if any, to
+ * return from k_queue_get() call with NULL value (as if timeout expired).
+ * If the queue is being waited on by k_poll(), it will return with
+ * -EINTR and K_POLL_STATE_CANCELLED state (and per above, subsequent
+ * k_queue_get() will return NULL).
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ *
+ * @return N/A
+ */
+__syscall void k_queue_cancel_wait(struct k_queue *queue);
+
+/**
+ * @brief Append an element to the end of a queue.
+ *
+ * This routine appends a data item to @a queue. A queue data item must be
+ * aligned on a word boundary, and the first word of the item is reserved
+ * for the kernel's use.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @return N/A
+ */
+extern void k_queue_append(struct k_queue *queue, void *data);
+
+/**
+ * @brief Append an element to a queue.
+ *
+ * This routine appends a data item to @a queue. There is an implicit memory
+ * allocation to create an additional temporary bookkeeping data structure from
+ * the calling thread's resource pool, which is automatically freed when the
+ * item is removed. The data itself is not copied.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @retval 0 on success
+ * @retval -ENOMEM if there isn't sufficient RAM in the caller's resource pool
+ */
+__syscall int32_t k_queue_alloc_append(struct k_queue *queue, void *data);
+
+/**
+ * @brief Prepend an element to a queue.
+ *
+ * This routine prepends a data item to @a queue. A queue data item must be
+ * aligned on a word boundary, and the first word of the item is reserved
+ * for the kernel's use.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @return N/A
+ */
+extern void k_queue_prepend(struct k_queue *queue, void *data);
+
+/**
+ * @brief Prepend an element to a queue.
+ *
+ * This routine prepends a data item to @a queue. There is an implicit memory
+ * allocation to create an additional temporary bookkeeping data structure from
+ * the calling thread's resource pool, which is automatically freed when the
+ * item is removed. The data itself is not copied.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @retval 0 on success
+ * @retval -ENOMEM if there isn't sufficient RAM in the caller's resource pool
+ */
+__syscall int32_t k_queue_alloc_prepend(struct k_queue *queue, void *data);
+
+/**
+ * @brief Inserts an element to a queue.
+ *
+ * This routine inserts a data item to @a queue after previous item. A queue
+ * data item must be aligned on a word boundary, and the first word of
+ * the item is reserved for the kernel's use.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param prev Address of the previous data item.
+ * @param data Address of the data item.
+ *
+ * @return N/A
+ */
+extern void k_queue_insert(struct k_queue *queue, void *prev, void *data);
+
+/**
+ * @brief Atomically append a list of elements to a queue.
+ *
+ * This routine adds a list of data items to @a queue in one operation.
+ * The data items must be in a singly-linked list, with the first word
+ * in each data item pointing to the next data item; the list must be
+ * NULL-terminated.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param head Pointer to first node in singly-linked list.
+ * @param tail Pointer to last node in singly-linked list.
+ *
+ * @retval 0 on success
+ * @retval -EINVAL on invalid supplied data
+ *
+ */
+extern int k_queue_append_list(struct k_queue *queue, void *head, void *tail);
+
+/**
+ * @brief Atomically add a list of elements to a queue.
+ *
+ * This routine adds a list of data items to @a queue in one operation.
+ * The data items must be in a singly-linked list implemented using a
+ * sys_slist_t object. Upon completion, the original list is empty.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ * @param list Pointer to sys_slist_t object.
+ *
+ * @retval 0 on success
+ * @retval -EINVAL on invalid data
+ */
+extern int k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list);
+
+/**
+ * @brief Get an element from a queue.
+ *
+ * This routine removes first data item from @a queue. The first word of the
+ * data item is reserved for the kernel's use.
+ *
+ * @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
+ *
+ * @param queue Address of the queue.
+ * @param timeout Non-negative waiting period to obtain a data item
+ *                or one of the special values K_NO_WAIT and
+ *                K_FOREVER.
+ *
+ * @return Address of the data item if successful; NULL if returned
+ * without waiting, or waiting period timed out.
+ */
+void *k_queue_get(struct k_queue *queue, k_timeout_t timeout);
+
+/**
+ * @brief Remove an element from a queue.
+ *
+ * This routine removes data item from @a queue. The first word of the
+ * data item is reserved for the kernel's use. Removing elements from k_queue
+ * rely on sys_slist_find_and_remove which is not a constant time operation.
+ *
+ * @note Can be called by ISRs
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @return true if data item was removed
+ */
+static inline bool k_queue_remove(struct k_queue *queue, void *data)
+{
+	return sys_sflist_find_and_remove(&queue->data_q, (sys_sfnode_t *)data);
+}
+
+/**
+ * @brief Append an element to a queue only if it's not present already.
+ *
+ * This routine appends data item to @a queue. The first word of the data
+ * item is reserved for the kernel's use. Appending elements to k_queue
+ * relies on sys_slist_is_node_in_list which is not a constant time operation.
+ *
+ * @note Can be called by ISRs
+ *
+ * @param queue Address of the queue.
+ * @param data Address of the data item.
+ *
+ * @return true if data item was added, false if not
+ */
+static inline bool k_queue_unique_append(struct k_queue *queue, void *data)
+{
+	sys_sfnode_t *test;
+
+	SYS_SFLIST_FOR_EACH_NODE(&queue->data_q, test) {
+		if (test == (sys_sfnode_t *) data) {
+			return false;
+		}
+	}
+
+	k_queue_append(queue, data);
+	return true;
+}
+
+/**
+ * @brief Query a queue to see if it has data available.
+ *
+ * Note that the data might be already gone by the time this function returns
+ * if other threads are also trying to read from the queue.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param queue Address of the queue.
+ *
+ * @return Non-zero if the queue is empty.
+ * @return 0 if data is available.
+ */
+static inline int z_impl_k_queue_is_empty(struct k_queue *queue)
+{
+	return (int)sys_sflist_is_empty(&queue->data_q);
+}
+
+static inline int k_queue_is_empty(struct k_queue *queue)
+{
+    return z_impl_k_queue_is_empty(queue);
+}
+
+/**
+ * @brief Peek element at the head of queue.
+ *
+ * Return element from the head of queue without removing it.
+ *
+ * @param queue Address of the queue.
+ *
+ * @return Head element, or NULL if queue is empty.
+ */
+__syscall void *k_queue_peek_head(struct k_queue *queue);
+
+static inline void *z_impl_k_queue_peek_head(struct k_queue *queue)
+{
+	return z_queue_node_peek(sys_sflist_peek_head(&queue->data_q), false);
+}
+
+/**
+ * @brief Peek element at the tail of queue.
+ *
+ * Return element from the tail of queue without removing it.
+ *
+ * @param queue Address of the queue.
+ *
+ * @return Tail element, or NULL if queue is empty.
+ */
+__syscall void *k_queue_peek_tail(struct k_queue *queue);
+
+static inline void *z_impl_k_queue_peek_tail(struct k_queue *queue)
+{
+	return z_queue_node_peek(sys_sflist_peek_tail(&queue->data_q), false);
+}
+
+/**
+ * @brief Statically define and initialize a queue.
+ *
+ * The queue can be accessed outside the module where it is defined using:
+ *
+ * @code extern struct k_queue <name>; @endcode
+ *
+ * @param name Name of the queue.
+ */
+#define K_QUEUE_DEFINE(name) \
+	Z_STRUCT_SECTION_ITERABLE(k_queue, name) = \
+		Z_QUEUE_INITIALIZER(name)
+
+/** @} */
+
+#ifdef CONFIG_USERSPACE
+/**
+ * @brief futex structure
+ *
+ * A k_futex is a lightweight mutual exclusion primitive designed
+ * to minimize kernel involvement. Uncontended operation relies
+ * only on atomic access to shared memory. k_futex are tracked as
+ * kernel objects and can live in user memory so any access bypass
+ * the kernel object permission management mechanism.
+ */
+struct k_futex {
+	atomic_t val;
+};
+
+/**
+ * @brief futex kernel data structure
+ *
+ * z_futex_data are the helper data structure for k_futex to complete
+ * futex contended operation on kernel side, structure z_futex_data
+ * of every futex object is invisible in user mode.
+ */
+struct z_futex_data {
+	_wait_q_t wait_q;
+	struct k_spinlock lock;
+};
+
+#define Z_FUTEX_DATA_INITIALIZER(obj) \
+	{ \
+	.wait_q = Z_WAIT_Q_INIT(&obj.wait_q) \
+	}
+
+/**
+ * @defgroup futex_apis FUTEX APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Pend the current thread on a futex
+ *
+ * Tests that the supplied futex contains the expected value, and if so,
+ * goes to sleep until some other thread calls k_futex_wake() on it.
+ *
+ * @param futex Address of the futex.
+ * @param expected Expected value of the futex, if it is different the caller
+ *		   will not wait on it.
+ * @param timeout Non-negative waiting period on the futex, or
+ *		  one of the special values K_NO_WAIT or K_FOREVER.
+ * @retval -EACCES Caller does not have read access to futex address.
+ * @retval -EAGAIN If the futex value did not match the expected parameter.
+ * @retval -EINVAL Futex parameter address not recognized by the kernel.
+ * @retval -ETIMEDOUT Thread woke up due to timeout and not a futex wakeup.
+ * @retval 0 if the caller went to sleep and was woken up. The caller
+ *	     should check the futex's value on wakeup to determine if it needs
+ *	     to block again.
+ */
+__syscall int k_futex_wait(struct k_futex *futex, int expected,
+			   k_timeout_t timeout);
+
+/**
+ * @brief Wake one/all threads pending on a futex
+ *
+ * Wake up the highest priority thread pending on the supplied futex, or
+ * wakeup all the threads pending on the supplied futex, and the behavior
+ * depends on wake_all.
+ *
+ * @param futex Futex to wake up pending threads.
+ * @param wake_all If true, wake up all pending threads; If false,
+ *                 wakeup the highest priority thread.
+ * @retval -EACCES Caller does not have access to the futex address.
+ * @retval -EINVAL Futex parameter address not recognized by the kernel.
+ * @retval Number of threads that were woken up.
+ */
+__syscall int k_futex_wake(struct k_futex *futex, bool wake_all);
+
+/** @} */
+#endif
+
+struct k_fifo {
+	struct k_queue _queue;
+};
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+#define Z_FIFO_INITIALIZER(obj) \
+	{ \
+	._queue = Z_QUEUE_INITIALIZER(obj._queue) \
+	}
+
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @defgroup fifo_apis FIFO APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Initialize a FIFO queue.
+ *
+ * This routine initializes a FIFO queue, prior to its first use.
+ *
+ * @param fifo Address of the FIFO queue.
+ *
+ * @return N/A
+ */
+#define k_fifo_init(fifo) \
+	k_queue_init(&(fifo)->_queue)
+
+/**
+ * @brief Cancel waiting on a FIFO queue.
+ *
+ * This routine causes first thread pending on @a fifo, if any, to
+ * return from k_fifo_get() call with NULL value (as if timeout
+ * expired).
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO queue.
+ *
+ * @return N/A
+ */
+#define k_fifo_cancel_wait(fifo) \
+	k_queue_cancel_wait(&(fifo)->_queue)
+
+/**
+ * @brief Add an element to a FIFO queue.
+ *
+ * This routine adds a data item to @a fifo. A FIFO data item must be
+ * aligned on a word boundary, and the first word of the item is reserved
+ * for the kernel's use.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO.
+ * @param data Address of the data item.
+ *
+ * @return N/A
+ */
+#define k_fifo_put(fifo, data) \
+	k_queue_append(&(fifo)->_queue, data)
+
+/**
+ * @brief Add an element to a FIFO queue.
+ *
+ * This routine adds a data item to @a fifo. There is an implicit memory
+ * allocation to create an additional temporary bookkeeping data structure from
+ * the calling thread's resource pool, which is automatically freed when the
+ * item is removed. The data itself is not copied.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO.
+ * @param data Address of the data item.
+ *
+ * @retval 0 on success
+ * @retval -ENOMEM if there isn't sufficient RAM in the caller's resource pool
+ */
+#define k_fifo_alloc_put(fifo, data) \
+	k_queue_alloc_append(&(fifo)->_queue, data)
+
+/**
+ * @brief Atomically add a list of elements to a FIFO.
+ *
+ * This routine adds a list of data items to @a fifo in one operation.
+ * The data items must be in a singly-linked list, with the first word of
+ * each data item pointing to the next data item; the list must be
+ * NULL-terminated.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO queue.
+ * @param head Pointer to first node in singly-linked list.
+ * @param tail Pointer to last node in singly-linked list.
+ *
+ * @return N/A
+ */
+#define k_fifo_put_list(fifo, head, tail) \
+	k_queue_append_list(&(fifo)->_queue, head, tail)
+
+/**
+ * @brief Atomically add a list of elements to a FIFO queue.
+ *
+ * This routine adds a list of data items to @a fifo in one operation.
+ * The data items must be in a singly-linked list implemented using a
+ * sys_slist_t object. Upon completion, the sys_slist_t object is invalid
+ * and must be re-initialized via sys_slist_init().
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO queue.
+ * @param list Pointer to sys_slist_t object.
+ *
+ * @return N/A
+ */
+#define k_fifo_put_slist(fifo, list) \
+	k_queue_merge_slist(&(fifo)->_queue, list)
+
+/**
+ * @brief Get an element from a FIFO queue.
+ *
+ * This routine removes a data item from @a fifo in a "first in, first out"
+ * manner. The first word of the data item is reserved for the kernel's use.
+ *
+ * @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
+ *
+ * @param fifo Address of the FIFO queue.
+ * @param timeout Waiting period to obtain a data item,
+ *                or one of the special values K_NO_WAIT and K_FOREVER.
+ *
+ * @return Address of the data item if successful; NULL if returned
+ * without waiting, or waiting period timed out.
+ */
+#define k_fifo_get(fifo, timeout) \
+	k_queue_get(&(fifo)->_queue, timeout)
+
+/**
+ * @brief Query a FIFO queue to see if it has data available.
+ *
+ * Note that the data might be already gone by the time this function returns
+ * if other threads is also trying to read from the FIFO.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param fifo Address of the FIFO queue.
+ *
+ * @return Non-zero if the FIFO queue is empty.
+ * @return 0 if data is available.
+ */
+#define k_fifo_is_empty(fifo) \
+	k_queue_is_empty(&(fifo)->_queue)
+
+/**
+ * @brief Peek element at the head of a FIFO queue.
+ *
+ * Return element from the head of FIFO queue without removing it. A usecase
+ * for this is if elements of the FIFO object are themselves containers. Then
+ * on each iteration of processing, a head container will be peeked,
+ * and some data processed out of it, and only if the container is empty,
+ * it will be completely remove from the FIFO queue.
+ *
+ * @param fifo Address of the FIFO queue.
+ *
+ * @return Head element, or NULL if the FIFO queue is empty.
+ */
+#define k_fifo_peek_head(fifo) \
+	k_queue_peek_head(&(fifo)->_queue)
+
+/**
+ * @brief Peek element at the tail of FIFO queue.
+ *
+ * Return element from the tail of FIFO queue (without removing it). A usecase
+ * for this is if elements of the FIFO queue are themselves containers. Then
+ * it may be useful to add more data to the last container in a FIFO queue.
+ *
+ * @param fifo Address of the FIFO queue.
+ *
+ * @return Tail element, or NULL if a FIFO queue is empty.
+ */
+#define k_fifo_peek_tail(fifo) \
+	k_queue_peek_tail(&(fifo)->_queue)
+
+/**
+ * @brief Statically define and initialize a FIFO queue.
+ *
+ * The FIFO queue can be accessed outside the module where it is defined using:
+ *
+ * @code extern struct k_fifo <name>; @endcode
+ *
+ * @param name Name of the FIFO queue.
+ */
+#define K_FIFO_DEFINE(name) \
+	Z_STRUCT_SECTION_ITERABLE_ALTERNATE(k_queue, k_fifo, name) = \
+		Z_FIFO_INITIALIZER(name)
+
+/** @} */
+
+struct k_lifo {
+	struct k_queue _queue;
+};
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+
+#define Z_LIFO_INITIALIZER(obj) \
+	{ \
+	._queue = Z_QUEUE_INITIALIZER(obj._queue) \
+	}
+
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @defgroup lifo_apis LIFO APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Initialize a LIFO queue.
+ *
+ * This routine initializes a LIFO queue object, prior to its first use.
+ *
+ * @param lifo Address of the LIFO queue.
+ *
+ * @return N/A
+ */
+#define k_lifo_init(lifo) \
+	k_queue_init(&(lifo)->_queue)
+
+/**
+ * @brief Add an element to a LIFO queue.
+ *
+ * This routine adds a data item to @a lifo. A LIFO queue data item must be
+ * aligned on a word boundary, and the first word of the item is
+ * reserved for the kernel's use.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param lifo Address of the LIFO queue.
+ * @param data Address of the data item.
+ *
+ * @return N/A
+ */
+#define k_lifo_put(lifo, data) \
+	k_queue_prepend(&(lifo)->_queue, data)
+
+/**
+ * @brief Add an element to a LIFO queue.
+ *
+ * This routine adds a data item to @a lifo. There is an implicit memory
+ * allocation to create an additional temporary bookkeeping data structure from
+ * the calling thread's resource pool, which is automatically freed when the
+ * item is removed. The data itself is not copied.
+ *
+ * @note Can be called by ISRs.
+ *
+ * @param lifo Address of the LIFO.
+ * @param data Address of the data item.
+ *
+ * @retval 0 on success
+ * @retval -ENOMEM if there isn't sufficient RAM in the caller's resource pool
+ */
+#define k_lifo_alloc_put(lifo, data) \
+	k_queue_alloc_prepend(&(lifo)->_queue, data)
+
+/**
+ * @brief Get an element from a LIFO queue.
+ *
+ * This routine removes a data item from @a LIFO in a "last in, first out"
+ * manner. The first word of the data item is reserved for the kernel's use.
+ *
+ * @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
+ *
+ * @param lifo Address of the LIFO queue.
+ * @param timeout Waiting period to obtain a data item,
+ *                or one of the special values K_NO_WAIT and K_FOREVER.
+ *
+ * @return Address of the data item if successful; NULL if returned
+ * without waiting, or waiting period timed out.
+ */
+#define k_lifo_get(lifo, timeout) \
+	k_queue_get(&(lifo)->_queue, timeout)
+
+/**
+ * @brief Statically define and initialize a LIFO queue.
+ *
+ * The LIFO queue can be accessed outside the module where it is defined using:
+ *
+ * @code extern struct k_lifo <name>; @endcode
+ *
+ * @param name Name of the fifo.
+ */
+#define K_LIFO_DEFINE(name) \
+	Z_STRUCT_SECTION_ITERABLE_ALTERNATE(k_queue, k_lifo, name) = \
+		Z_LIFO_INITIALIZER(name)
+
+/** @} */
+
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+
+struct k_mem_slab {
+	uint32_t num_blocks;
+	size_t block_size;
+	char *buffer;
+	char *free_list;
+	uint32_t num_used;
+
+};
+
+#define Z_MEM_SLAB_INITIALIZER(obj, slab_buffer, slab_block_size, \
+			       slab_num_blocks) \
+	{ \
+	.num_blocks = slab_num_blocks, \
+	.block_size = slab_block_size, \
+	.buffer = slab_buffer, \
+	.free_list = NULL, \
+	.num_used = 0, \
+	}
+
+
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @defgroup mem_slab_apis Memory Slab APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Statically define and initialize a memory slab.
+ *
+ * The memory slab's buffer contains @a slab_num_blocks memory blocks
+ * that are @a slab_block_size bytes long. The buffer is aligned to a
+ * @a slab_align -byte boundary. To ensure that each memory block is similarly
+ * aligned to this boundary, @a slab_block_size must also be a multiple of
+ * @a slab_align.
+ *
+ * The memory slab can be accessed outside the module where it is defined
+ * using:
+ *
+ * @code extern struct k_mem_slab <name>; @endcode
+ *
+ * @param name Name of the memory slab.
+ * @param slab_block_size Size of each memory block (in bytes).
+ * @param slab_num_blocks Number memory blocks.
+ * @param slab_align Alignment of the memory slab's buffer (power of 2).
+ */
+#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \
+	char __noinit __aligned(WB_UP(slab_align)) \
+	   _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \
+	Z_STRUCT_SECTION_ITERABLE(k_mem_slab, name) = \
+		Z_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \
+					WB_UP(slab_block_size), slab_num_blocks)
+
+/**
+ * @brief Initialize a memory slab.
+ *
+ * Initializes a memory slab, prior to its first use.
+ *
+ * The memory slab's buffer contains @a slab_num_blocks memory blocks
+ * that are @a slab_block_size bytes long. The buffer must be aligned to an
+ * N-byte boundary matching a word boundary, where N is a power of 2
+ * (i.e. 4 on 32-bit systems, 8, 16, ...).
+ * To ensure that each memory block is similarly aligned to this boundary,
+ * @a slab_block_size must also be a multiple of N.
+ *
+ * @param slab Address of the memory slab.
+ * @param buffer Pointer to buffer used for the memory blocks.
+ * @param block_size Size of each memory block (in bytes).
+ * @param num_blocks Number of memory blocks.
+ *
+ * @retval 0 on success
+ * @retval -EINVAL invalid data supplied
+ *
+ */
+extern int k_mem_slab_init(struct k_mem_slab *slab, void *buffer,
+			   size_t block_size, uint32_t num_blocks);
+
+/**
+ * @brief Allocate memory from a memory slab.
+ *
+ * This routine allocates a memory block from a memory slab.
+ *
+ * @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
+ *
+ * @param slab Address of the memory slab.
+ * @param mem Pointer to block address area.
+ * @param timeout Non-negative waiting period to wait for operation to complete.
+ *        Use K_NO_WAIT to return without waiting,
+ *        or K_FOREVER to wait as long as necessary.
+ *
+ * @retval 0 Memory allocated. The block address area pointed at by @a mem
+ *         is set to the starting address of the memory block.
+ * @retval -ENOMEM Returned without waiting.
+ * @retval -EAGAIN Waiting period timed out.
+ * @retval -EINVAL Invalid data supplied
+ */
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem,
+			    k_timeout_t timeout);
+
+/**
+ * @brief Free memory allocated from a memory slab.
+ *
+ * This routine releases a previously allocated memory block back to its
+ * associated memory slab.
+ *
+ * @param slab Address of the memory slab.
+ * @param mem Pointer to block address area (as set by k_mem_slab_alloc()).
+ *
+ * @return N/A
+ */
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
+
+/**
+ * @brief Get the number of used blocks in a memory slab.
+ *
+ * This routine gets the number of memory blocks that are currently
+ * allocated in @a slab.
+ *
+ * @param slab Address of the memory slab.
+ *
+ * @return Number of allocated memory blocks.
+ */
+static inline uint32_t k_mem_slab_num_used_get(struct k_mem_slab *slab)
+{
+	return slab->num_used;
+}
+
+/**
+ * @brief Get the number of unused blocks in a memory slab.
+ *
+ * This routine gets the number of memory blocks that are currently
+ * unallocated in @a slab.
+ *
+ * @param slab Address of the memory slab.
+ *
+ * @return Number of unallocated memory blocks.
+ */
+static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
+{
+	return slab->num_blocks - slab->num_used;
+}
+
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup heap_apis Heap Memory Pool APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Allocate memory from heap.
+ *
+ * This routine provides traditional malloc() semantics. Memory is
+ * allocated from the heap memory pool.
+ *
+ * @param size Amount of memory requested (in bytes).
+ *
+ * @return Address of the allocated memory if successful; otherwise NULL.
+ */
+extern void *k_malloc(size_t size);
+
+/**
+ * @brief Free memory allocated from heap.
+ *
+ * This routine provides traditional free() semantics. The memory being
+ * returned must have been allocated from the heap memory pool or
+ * k_mem_pool_malloc().
+ *
+ * If @a ptr is NULL, no operation is performed.
+ *
+ * @param ptr Pointer to previously allocated memory.
+ *
+ * @return N/A
+ */
+extern void k_free(void *ptr);
+
+/**
+ * @brief Allocate memory from heap, array style
+ *
+ * This routine provides traditional calloc() semantics. Memory is
+ * allocated from the heap memory pool and zeroed.
+ *
+ * @param nmemb Number of elements in the requested array
+ * @param size Size of each array element (in bytes).
+ *
+ * @return Address of the allocated memory if successful; otherwise NULL.
+ */
+extern void *k_calloc(size_t nmemb, size_t size);
+
+/** @} */
+
+/* polling API - PRIVATE */
+
+#ifdef CONFIG_POLL
+#define _INIT_OBJ_POLL_EVENT(obj) do { (obj)->poll_event = NULL; } while (false)
+#else
+#define _INIT_OBJ_POLL_EVENT(obj) do { } while (false)
+#endif
+
+/* private - types bit positions */
+enum _poll_types_bits {
+	/* can be used to ignore an event */
+	_POLL_TYPE_IGNORE,
+
+	/* to be signaled by k_poll_signal_raise() */
+	_POLL_TYPE_SIGNAL,
+
+	/* semaphore availability */
+	_POLL_TYPE_SEM_AVAILABLE,
+
+	/* queue/FIFO/LIFO data availability */
+	_POLL_TYPE_DATA_AVAILABLE,
+
+	_POLL_NUM_TYPES
+};
+
+#define Z_POLL_TYPE_BIT(type) (1U << ((type) - 1U))
+
+/* private - states bit positions */
+enum _poll_states_bits {
+	/* default state when creating event */
+	_POLL_STATE_NOT_READY,
+
+	/* signaled by k_poll_signal_raise() */
+	_POLL_STATE_SIGNALED,
+
+	/* semaphore is available */
+	_POLL_STATE_SEM_AVAILABLE,
+
+	/* data is available to read on queue/FIFO/LIFO */
+	_POLL_STATE_DATA_AVAILABLE,
+
+	/* queue/FIFO/LIFO wait was cancelled */
+	_POLL_STATE_CANCELLED,
+
+	_POLL_NUM_STATES
+};
+
+#define Z_POLL_STATE_BIT(state) (1U << ((state) - 1U))
+
+#define _POLL_EVENT_NUM_UNUSED_BITS \
+	(32 - (0 \
+	       + 8 /* tag */ \
+	       + _POLL_NUM_TYPES \
+	       + _POLL_NUM_STATES \
+	       + 1 /* modes */ \
+	      ))
+
+/* end of polling API - PRIVATE */
+
+
+/**
+ * @defgroup poll_apis Async polling APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/* Public polling API */
+
+/* public - values for k_poll_event.type bitfield */
+#define K_POLL_TYPE_IGNORE 0
+#define K_POLL_TYPE_SIGNAL Z_POLL_TYPE_BIT(_POLL_TYPE_SIGNAL)
+#define K_POLL_TYPE_SEM_AVAILABLE Z_POLL_TYPE_BIT(_POLL_TYPE_SEM_AVAILABLE)
+#define K_POLL_TYPE_DATA_AVAILABLE Z_POLL_TYPE_BIT(_POLL_TYPE_DATA_AVAILABLE)
+#define K_POLL_TYPE_FIFO_DATA_AVAILABLE K_POLL_TYPE_DATA_AVAILABLE
+
+/* public - polling modes */
+enum k_poll_modes {
+	/* polling thread does not take ownership of objects when available */
+	K_POLL_MODE_NOTIFY_ONLY = 0,
+
+	K_POLL_NUM_MODES
+};
+
+/* public - values for k_poll_event.state bitfield */
+#define K_POLL_STATE_NOT_READY 0
+#define K_POLL_STATE_SIGNALED Z_POLL_STATE_BIT(_POLL_STATE_SIGNALED)
+#define K_POLL_STATE_SEM_AVAILABLE Z_POLL_STATE_BIT(_POLL_STATE_SEM_AVAILABLE)
+#define K_POLL_STATE_DATA_AVAILABLE Z_POLL_STATE_BIT(_POLL_STATE_DATA_AVAILABLE)
+#define K_POLL_STATE_FIFO_DATA_AVAILABLE K_POLL_STATE_DATA_AVAILABLE
+#define K_POLL_STATE_CANCELLED Z_POLL_STATE_BIT(_POLL_STATE_CANCELLED)
+
+/* public - poll signal object */
+struct k_poll_signal {
+	/** PRIVATE - DO NOT TOUCH */
+	sys_dlist_t poll_events;
+
+	/**
+	 * 1 if the event has been signaled, 0 otherwise. Stays set to 1 until
+	 * user resets it to 0.
+	 */
+	unsigned int signaled;
+
+	/** custom result value passed to k_poll_signal_raise() if needed */
+	int result;
+};
+
+#define K_POLL_SIGNAL_INITIALIZER(obj) \
+	{ \
+	.poll_events = SYS_DLIST_STATIC_INIT(&obj.poll_events), \
+	.signaled = 0, \
+	.result = 0, \
+	}
+/**
+ * @brief Poll Event
+ *
+ */
+struct k_poll_event {
+	/** PRIVATE - DO NOT TOUCH */
+	sys_dnode_t _node;
+
+	/** PRIVATE - DO NOT TOUCH */
+	struct _poller *poller;
+
+	/** optional user-specified tag, opaque, untouched by the API */
+	uint32_t tag:8;
+
+	/** bitfield of event types (bitwise-ORed K_POLL_TYPE_xxx values) */
+	uint32_t type:_POLL_NUM_TYPES;
+
+	/** bitfield of event states (bitwise-ORed K_POLL_STATE_xxx values) */
+	uint32_t state:_POLL_NUM_STATES;
+
+	/** mode of operation, from enum k_poll_modes */
+	uint32_t mode:1;
+
+	/** unused bits in 32-bit word */
+	uint32_t unused:_POLL_EVENT_NUM_UNUSED_BITS;
+
+	/** per-type data */
+	union {
+		void *obj;
+		struct k_poll_signal *signal;
+		struct k_sem *sem;
+		struct k_fifo *fifo;
+		struct k_queue *queue;
+	};
+};
+
+#define K_POLL_EVENT_INITIALIZER(_event_type, _event_mode, _event_obj) \
+	{ \
+	.poller = NULL, \
+	.type = _event_type, \
+	.state = K_POLL_STATE_NOT_READY, \
+	.mode = _event_mode, \
+	.unused = 0, \
+	.obj = _event_obj, \
+	}
+
+#define K_POLL_EVENT_STATIC_INITIALIZER(_event_type, _event_mode, _event_obj, \
+					event_tag) \
+	{ \
+	.tag = event_tag, \
+	.type = _event_type, \
+	.state = K_POLL_STATE_NOT_READY, \
+	.mode = _event_mode, \
+	.unused = 0, \
+	.obj = _event_obj, \
+	}
+
+/**
+ * @brief Initialize one struct k_poll_event instance
+ *
+ * After this routine is called on a poll event, the event it ready to be
+ * placed in an event array to be passed to k_poll().
+ *
+ * @param event The event to initialize.
+ * @param type A bitfield of the types of event, from the K_POLL_TYPE_xxx
+ *             values. Only values that apply to the same object being polled
+ *             can be used together. Choosing K_POLL_TYPE_IGNORE disables the
+ *             event.
+ * @param mode Future. Use K_POLL_MODE_NOTIFY_ONLY.
+ * @param obj Kernel object or poll signal.
+ *
+ * @return N/A
+ */
+
+extern void k_poll_event_init(struct k_poll_event *event, uint32_t type,
+			      int mode, void *obj);
+
+/**
+ * @brief Wait for one or many of multiple poll events to occur
+ *
+ * This routine allows a thread to wait concurrently for one or many of
+ * multiple poll events to have occurred. Such events can be a kernel object
+ * being available, like a semaphore, or a poll signal event.
+ *
+ * When an event notifies that a kernel object is available, the kernel object
+ * is not "given" to the thread calling k_poll(): it merely signals the fact
+ * that the object was available when the k_poll() call was in effect. Also,
+ * all threads trying to acquire an object the regular way, i.e. by pending on
+ * the object, have precedence over the thread polling on the object. This
+ * means that the polling thread will never get the poll event on an object
+ * until the object becomes available and its pend queue is empty. For this
+ * reason, the k_poll() call is more effective when the objects being polled
+ * only have one thread, the polling thread, trying to acquire them.
+ *
+ * When k_poll() returns 0, the caller should loop on all the events that were
+ * passed to k_poll() and check the state field for the values that were
+ * expected and take the associated actions.
+ *
+ * Before being reused for another call to k_poll(), the user has to reset the
+ * state field to K_POLL_STATE_NOT_READY.
+ *
+ * When called from user mode, a temporary memory allocation is required from
+ * the caller's resource pool.
+ *
+ * @param events An array of events to be polled for.
+ * @param num_events The number of events in the array.
+ * @param timeout Waiting period for an event to be ready,
+ *                or one of the special values K_NO_WAIT and K_FOREVER.
+ *
+ * @retval 0 One or more events are ready.
+ * @retval -EAGAIN Waiting period timed out.
+ * @retval -EINTR Polling has been interrupted, e.g. with
+ *         k_queue_cancel_wait(). All output events are still set and valid,
+ *         cancelled event(s) will be set to K_POLL_STATE_CANCELLED. In other
+ *         words, -EINTR status means that at least one of output events is
+ *         K_POLL_STATE_CANCELLED.
+ * @retval -ENOMEM Thread resource pool insufficient memory (user mode only)
+ * @retval -EINVAL Bad parameters (user mode only)
+ */
+
+__syscall int k_poll(struct k_poll_event *events, int num_events,
+		     k_timeout_t timeout)
+{
+    return 0;
+}
+
+/**
+ * @brief Initialize a poll signal object.
+ *
+ * Ready a poll signal object to be signaled via k_poll_signal_raise().
+ *
+ * @param signal A poll signal.
+ *
+ * @return N/A
+ */
+
+__syscall void k_poll_signal_init(struct k_poll_signal *signal);
+
+/*
+ * @brief Reset a poll signal object's state to unsignaled.
+ *
+ * @param signal A poll signal object
+ */
+__syscall void k_poll_signal_reset(struct k_poll_signal *signal);
+
+static inline void z_impl_k_poll_signal_reset(struct k_poll_signal *signal)
+{
+	signal->signaled = 0U;
+}
+
+/**
+ * @brief Fetch the signaled state and result value of a poll signal
+ *
+ * @param signal A poll signal object
+ * @param signaled An integer buffer which will be written nonzero if the
+ *		   object was signaled
+ * @param result An integer destination buffer which will be written with the
+ *		   result value if the object was signaled, or an undefined
+ *		   value if it was not.
+ */
+__syscall void k_poll_signal_check(struct k_poll_signal *signal,
+				   unsigned int *signaled, int *result);
+
+/**
+ * @brief Signal a poll signal object.
+ *
+ * This routine makes ready a poll signal, which is basically a poll event of
+ * type K_POLL_TYPE_SIGNAL. If a thread was polling on that event, it will be
+ * made ready to run. A @a result value can be specified.
+ *
+ * The poll signal contains a 'signaled' field that, when set by
+ * k_poll_signal_raise(), stays set until the user sets it back to 0 with
+ * k_poll_signal_reset(). It thus has to be reset by the user before being
+ * passed again to k_poll() or k_poll() will consider it being signaled, and
+ * will return immediately.
+ *
+ * @note The result is stored and the 'signaled' field is set even if
+ * this function returns an error indicating that an expiring poll was
+ * not notified.  The next k_poll() will detect the missed raise.
+ *
+ * @param signal A poll signal.
+ * @param result The value to store in the result field of the signal.
+ *
+ * @retval 0 The signal was delivered successfully.
+ * @retval -EAGAIN The polling thread's timeout is in the process of expiring.
+ */
+
+__syscall int k_poll_signal_raise(struct k_poll_signal *signal, int result);
+
+/**
+ * @internal
+ */
+extern void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state);
+
+/** @} */
+
+
+/**
+ * @brief Generate null timeout delay.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * not to wait if the requested operation cannot be performed immediately.
+ *
+ * @return Timeout delay value.
+ */
+#define K_NO_WAIT 0//Z_TIMEOUT_NO_WAIT
+
+/**
+ * @brief Generate timeout delay from nanoseconds.
+ *
+ * This macro generates a timeout delay that instructs a kernel API to
+ * wait up to @a t nanoseconds to perform the requested operation.
+ * Note that timer precision is limited to the tick rate, not the
+ * requested value.
+ *
+ * @param t Duration in nanoseconds.
+ *
+ * @return Timeout delay value.
+ */
+#define K_NSEC(t)     0//Z_TIMEOUT_NS(t)
+
+/**
+ * @brief Generate timeout delay from microseconds.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a t microseconds to perform the requested operation.
+ * Note that timer precision is limited to the tick rate, not the
+ * requested value.
+ *
+ * @param t Duration in microseconds.
+ *
+ * @return Timeout delay value.
+ */
+#define K_USEC(t)     0//Z_TIMEOUT_US(t)
+
+/**
+ * @brief Generate timeout delay from cycles.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a t cycles to perform the requested operation.
+ *
+ * @param t Duration in cycles.
+ *
+ * @return Timeout delay value.
+ */
+#define K_CYC(t)     0//Z_TIMEOUT_CYC(t)
+
+/**
+ * @brief Generate timeout delay from system ticks.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a t ticks to perform the requested operation.
+ *
+ * @param t Duration in system ticks.
+ *
+ * @return Timeout delay value.
+ */
+#define K_TICKS(t)     0//Z_TIMEOUT_TICKS(t)
+
+/**
+ * @brief Generate timeout delay from milliseconds.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a ms milliseconds to perform the requested operation.
+ *
+ * @param ms Duration in milliseconds.
+ *
+ * @return Timeout delay value.
+ */
+#define K_MSEC(ms)     0//Z_TIMEOUT_MS(ms)
+
+/**
+ * @brief Generate timeout delay from seconds.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a s seconds to perform the requested operation.
+ *
+ * @param s Duration in seconds.
+ *
+ * @return Timeout delay value.
+ */
+#define K_SECONDS(s)   0//K_MSEC((s) * MSEC_PER_SEC)
+
+/**
+ * @brief Generate timeout delay from minutes.
+
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a m minutes to perform the requested operation.
+ *
+ * @param m Duration in minutes.
+ *
+ * @return Timeout delay value.
+ */
+#define K_MINUTES(m)  0// K_SECONDS((m) * 60)
+
+/**
+ * @brief Generate timeout delay from hours.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait up to @a h hours to perform the requested operation.
+ *
+ * @param h Duration in hours.
+ *
+ * @return Timeout delay value.
+ */
+#define K_HOURS(h)    0// K_MINUTES((h) * 60)
+
+/**
+ * @brief Generate infinite timeout delay.
+ *
+ * This macro generates a timeout delay that instructs a kernel API
+ * to wait as long as necessary to perform the requested operation.
+ *
+ * @return Timeout delay value.
+ */
+#define K_FOREVER 0//Z_FOREVER
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_ASMLANGUAGE */
+
+#endif /* ZEPHYR_INCLUDE_KERNEL_H_ */
Index: ModuleDemo/BLE/CM0/User/include/kernel_includes.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel_includes.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel_includes.h	(working copy)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief Header files included by kernel.h.
+ */
+
+#ifndef ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_
+#define ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_
+
+#include <stddef.h>
+#include <types.h>
+#include <limits.h>
+#include <toolchain.h>
+//#include <linker/sections.h>
+#include <sys/atomic.h>
+#include <sys/__assert.h>
+#include <sched_priq.h>
+#include <sys/dlist.h>
+#include <sys/slist.h>
+#include <sys/sflist.h>
+#include <sys/util.h>
+#include <sys/mempool_base.h>
+//#include <kernel_structs.h>
+#ifdef CONFIG_MEM_POOL_HEAP_BACKEND
+#include <mempool_heap.h>
+#else
+#include <mempool_sys.h>
+#endif
+#include <kernel_version.h>
+//#include <arch/cpu.h>
+#include <sys/rb.h>
+
+#endif /* ZEPHYR_INCLUDE_KERNEL_INCLUDES_H_ */
Index: ModuleDemo/BLE/CM0/User/include/kernel_version.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel_version.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/kernel_version.h	(working copy)
@@ -0,0 +1,57 @@
+/* kernel version support */
+
+/*
+ * Copyright (c) 2015 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_KERNEL_VERSION_H_
+#define ZEPHYR_INCLUDE_KERNEL_VERSION_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup version_apis Version APIs
+ * @ingroup kernel_apis
+ * @{
+ *
+ * The kernel version has been converted from a string to a four-byte
+ * quantity that is divided into two parts.
+ *
+ * Part 1: The three most significant bytes represent the kernel's
+ * numeric version, x.y.z. These fields denote:
+ *       x -- major release
+ *       y -- minor release
+ *       z -- patchlevel release
+ * Each of these elements must therefore be in the range 0 to 255, inclusive.
+ *
+ * Part 2: The least significant byte is reserved for future use.
+ */
+#define SYS_KERNEL_VER_MAJOR(ver) (((ver) >> 24) & 0xFF)
+#define SYS_KERNEL_VER_MINOR(ver) (((ver) >> 16) & 0xFF)
+#define SYS_KERNEL_VER_PATCHLEVEL(ver) (((ver) >> 8) & 0xFF)
+
+/* kernel version routines */
+
+/**
+ * @brief Return the kernel version of the present build
+ *
+ * The kernel version is a four-byte value, whose format is described in the
+ * file "kernel_version.h".
+ *
+ * @return kernel version
+ */
+extern uint32_t sys_kernel_version_get(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_KERNEL_VERSION_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log.h	(working copy)
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_H_
+
+#include <logging/log_instance.h>
+#include <logging/log_core.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Logging
+ * @defgroup logging Logging
+ * @{
+ * @}
+ */
+
+/**
+ * @brief Logger API
+ * @defgroup log_api Logging API
+ * @ingroup logger
+ * @{
+ */
+
+/**
+ * @brief Writes an ERROR level message to the log.
+ *
+ * @details It's meant to report severe errors, such as those from which it's
+ * not possible to recover.
+ *
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_ERR(...)    Z_LOG(LOG_LEVEL_ERR, __VA_ARGS__)
+
+/**
+ * @brief Writes a WARNING level message to the log.
+ *
+ * @details It's meant to register messages related to unusual situations that
+ * are not necessarily errors.
+ *
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_WRN(...)   Z_LOG(LOG_LEVEL_WRN, __VA_ARGS__)
+
+/**
+ * @brief Writes an INFO level message to the log.
+ *
+ * @details It's meant to write generic user oriented messages.
+ *
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_INF(...)   Z_LOG(LOG_LEVEL_INF, __VA_ARGS__)
+
+/**
+ * @brief Writes a DEBUG level message to the log.
+ *
+ * @details It's meant to write developer oriented information.
+ *
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_DBG(...)    Z_LOG(LOG_LEVEL_DBG, __VA_ARGS__)
+
+/**
+ * @brief Writes an ERROR level message associated with the instance to the log.
+ *
+ * Message is associated with specific instance of the module which has
+ * independent filtering settings (if runtime filtering is enabled) and
+ * message prefix (\<module_name\>.\<instance_name\>). It's meant to report
+ * severe errors, such as those from which it's not possible to recover.
+ *
+ * @param _log_inst Pointer to the log structure associated with the instance.
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_INST_ERR(_log_inst, ...) \
+	Z_LOG_INSTANCE(LOG_LEVEL_ERR, _log_inst, __VA_ARGS__)
+
+/**
+ * @brief Writes a WARNING level message associated with the instance to the
+ *        log.
+ *
+ * Message is associated with specific instance of the module which has
+ * independent filtering settings (if runtime filtering is enabled) and
+ * message prefix (\<module_name\>.\<instance_name\>). It's meant to register
+ * messages related to unusual situations that are not necessarily errors.
+ *
+ * @param _log_inst Pointer to the log structure associated with the instance.
+ * @param ...       A string optionally containing printk valid conversion
+ *                  specifier, followed by as many values as specifiers.
+ */
+#define LOG_INST_WRN(_log_inst, ...) \
+	Z_LOG_INSTANCE(LOG_LEVEL_WRN, _log_inst, __VA_ARGS__)
+
+/**
+ * @brief Writes an INFO level message associated with the instance to the log.
+ *
+ * Message is associated with specific instance of the module which has
+ * independent filtering settings (if runtime filtering is enabled) and
+ * message prefix (\<module_name\>.\<instance_name\>). It's meant to write
+ * generic user oriented messages.
+ *
+ * @param _log_inst Pointer to the log structure associated with the instance.
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_INST_INF(_log_inst, ...) \
+	Z_LOG_INSTANCE(LOG_LEVEL_INF, _log_inst, __VA_ARGS__)
+
+/**
+ * @brief Writes a DEBUG level message associated with the instance to the log.
+ *
+ * Message is associated with specific instance of the module which has
+ * independent filtering settings (if runtime filtering is enabled) and
+ * message prefix (\<module_name\>.\<instance_name\>). It's meant to write
+ * developer oriented information.
+ *
+ * @param _log_inst Pointer to the log structure associated with the instance.
+ * @param ... A string optionally containing printk valid conversion specifier,
+ * followed by as many values as specifiers.
+ */
+#define LOG_INST_DBG(_log_inst, ...) \
+	Z_LOG_INSTANCE(LOG_LEVEL_DBG, _log_inst, __VA_ARGS__)
+
+/**
+ * @brief Writes an ERROR level hexdump message to the log.
+ *
+ * @details It's meant to report severe errors, such as those from which it's
+ * not possible to recover.
+ *
+ * @param _data   Pointer to the data to be logged.
+ * @param _length Length of data (in bytes).
+ * @param _str    Persistent, raw string.
+ */
+#define LOG_HEXDUMP_ERR(_data, _length, _str) \
+	Z_LOG_HEXDUMP(LOG_LEVEL_ERR, _data, _length, _str)
+
+/**
+ * @brief Writes a WARNING level message to the log.
+ *
+ * @details It's meant to register messages related to unusual situations that
+ * are not necessarily errors.
+ *
+ * @param _data   Pointer to the data to be logged.
+ * @param _length Length of data (in bytes).
+ * @param _str    Persistent, raw string.
+ */
+#define LOG_HEXDUMP_WRN(_data, _length, _str) \
+	Z_LOG_HEXDUMP(LOG_LEVEL_WRN, _data, _length, _str)
+
+/**
+ * @brief Writes an INFO level message to the log.
+ *
+ * @details It's meant to write generic user oriented messages.
+ *
+ * @param _data   Pointer to the data to be logged.
+ * @param _length Length of data (in bytes).
+ * @param _str    Persistent, raw string.
+ */
+#define LOG_HEXDUMP_INF(_data, _length, _str) \
+	Z_LOG_HEXDUMP(LOG_LEVEL_INF, _data, _length, _str)
+
+/**
+ * @brief Writes a DEBUG level message to the log.
+ *
+ * @details It's meant to write developer oriented information.
+ *
+ * @param _data   Pointer to the data to be logged.
+ * @param _length Length of data (in bytes).
+ * @param _str    Persistent, raw string.
+ */
+#define LOG_HEXDUMP_DBG(_data, _length, _str) \
+	Z_LOG_HEXDUMP(LOG_LEVEL_DBG, _data, _length, _str)
+
+/**
+ * @brief Writes an ERROR hexdump message associated with the instance to the
+ *        log.
+ *
+ * Message is associated with specific instance of the module which has
+ * independent filtering settings (if runtime filtering is enabled) and
+ * message prefix (\<module_name\>.\<instance_name\>). It's meant to report
+ * severe errors, such as those from which it's not possible to recover.
+ *
+ * @param _log_inst   Pointer to the log structure associated with the instance.
+ * @param _data       Pointer to the data to be logged.
+ * @param _length     Length of data (in bytes).
+ * @param _str        Persistent, raw string.
+ */
+#define LOG_INST_HEXDUMP_ERR(_log_inst, _data, _length, _str) \
+	Z_LOG_HEXDUMP_INSTANCE(LOG_LEVEL_ERR, _log_inst, _data, _length, _str)
+
+/**
+ * @brief Writes a WARNING level hexdump message associated with the instance to
+ *        the log.
+ *
+ * @details It's meant to register messages related to unusual situations that
+ * are not necessarily errors.
+ *
+ * @param _log_inst   Pointer to the log structure associated with the instance.
+ * @param _data       Pointer to the data to be logged.
+ * @param _length     Length of data (in bytes).
+ * @param _str        Persistent, raw string.
+ */
+#define LOG_INST_HEXDUMP_WRN(_log_inst, _data, _length, _str) \
+	Z_LOG_HEXDUMP_INSTANCE(LOG_LEVEL_WRN, _log_inst, _data, _length, _str)
+
+/**
+ * @brief Writes an INFO level hexdump message associated with the instance to
+ *        the log.
+ *
+ * @details It's meant to write generic user oriented messages.
+ *
+ * @param _log_inst   Pointer to the log structure associated with the instance.
+ * @param _data       Pointer to the data to be logged.
+ * @param _length     Length of data (in bytes).
+ * @param _str        Persistent, raw string.
+ */
+#define LOG_INST_HEXDUMP_INF(_log_inst, _data, _length, _str) \
+	Z_LOG_HEXDUMP_INSTANCE(LOG_LEVEL_INF, _log_inst, _data, _length, _str)
+
+/**
+ * @brief Writes a DEBUG level hexdump message associated with the instance to
+ *        the log.
+ *
+ * @details It's meant to write developer oriented information.
+ *
+ * @param _log_inst   Pointer to the log structure associated with the instance.
+ * @param _data       Pointer to the data to be logged.
+ * @param _length     Length of data (in bytes).
+ * @param _str        Persistent, raw string.
+ */
+#define LOG_INST_HEXDUMP_DBG(_log_inst, _data, _length, _str)	\
+	Z_LOG_HEXDUMP_INSTANCE(LOG_LEVEL_DBG, _log_inst, _data, _length, _str)
+
+#ifndef CONFIG_LOG_MINIMAL
+/**
+ * @brief Writes an formatted string to the log.
+ *
+ * @details Conditionally compiled (see CONFIG_LOG_PRINTK). Function provides
+ * printk functionality. It is inefficient compared to standard logging
+ * because string formatting is performed in the call context and not deferred
+ * to the log processing context (@ref log_process).
+ *
+ * @param fmt Formatted string to output.
+ * @param ap  Variable parameters.
+ */
+void log_printk(const char *fmt, va_list ap);
+
+/** @brief Copy transient string to a buffer from internal, logger pool.
+ *
+ * Function should be used when transient string is intended to be logged.
+ * Logger allocates a buffer and copies input string returning a pointer to the
+ * copy. Logger ensures that buffer is freed when logger message is freed.
+ *
+ * Depending on configuration, this function may do nothing and just pass
+ * along the supplied string pointer. Do not rely on this function to always
+ * make a copy!
+ *
+ * @param str Transient string.
+ *
+ * @return Copy of the string or default string if buffer could not be
+ *	   allocated. String may be truncated if input string does not fit in
+ *	   a buffer from the pool (see CONFIG_LOG_STRDUP_MAX_STRING). In
+ *	   some configurations, the original string pointer is returned.
+ */
+char *log_strdup(const char *str);
+#else
+static inline void log_printk(const char *fmt, va_list ap)
+{
+	vprintk(fmt, ap);
+}
+
+static inline char *log_strdup(const char *str)
+{
+	return (char *)str;
+}
+#endif /* CONFIG_LOG_MINIMAL */
+
+#ifdef __cplusplus
+}
+#define LOG_IN_CPLUSPLUS 1
+#endif
+/* Macro expects that optionally on second argument local log level is provided.
+ * If provided it is returned, otherwise default log level is returned or
+ * LOG_LEVEL, if it was locally defined.
+ */
+#if !defined(CONFIG_LOG)
+#define _LOG_LEVEL_RESOLVE(...) LOG_LEVEL_NONE
+#else
+#define _LOG_LEVEL_RESOLVE(...) \
+	Z_LOG_EVAL(LOG_LEVEL, \
+		  (GET_ARG_N(2, __VA_ARGS__, LOG_LEVEL)), \
+		  (GET_ARG_N(2, __VA_ARGS__, CONFIG_LOG_DEFAULT_LEVEL)))
+#endif
+
+/* Return first argument */
+#define _LOG_ARG1(arg1, ...) arg1
+
+#define _LOG_MODULE_CONST_DATA_CREATE(_name, _level)			     \
+	IF_ENABLED(LOG_IN_CPLUSPLUS, (extern))				     \
+	const struct log_source_const_data LOG_ITEM_CONST_DATA(_name)	     \
+	__attribute__ ((section("." STRINGIFY(LOG_ITEM_CONST_DATA(_name))))) \
+	__attribute__((used)) = {					     \
+		.name = STRINGIFY(_name),				     \
+		.level = _level						     \
+	}
+
+#define _LOG_MODULE_DYNAMIC_DATA_CREATE(_name)				\
+	struct log_source_dynamic_data LOG_ITEM_DYNAMIC_DATA(_name)	\
+	__attribute__ ((section("." STRINGIFY(				\
+				     LOG_ITEM_DYNAMIC_DATA(_name))))	\
+				     )					\
+	__attribute__((used))
+
+#define _LOG_MODULE_DYNAMIC_DATA_COND_CREATE(_name)		\
+	IF_ENABLED(CONFIG_LOG_RUNTIME_FILTERING,		\
+		  (_LOG_MODULE_DYNAMIC_DATA_CREATE(_name);))
+
+#define _LOG_MODULE_DATA_CREATE(_name, _level)			\
+	_LOG_MODULE_CONST_DATA_CREATE(_name, _level);		\
+	_LOG_MODULE_DYNAMIC_DATA_COND_CREATE(_name)
+
+/**
+ * @brief Create module-specific state and register the module with Logger.
+ *
+ * This macro normally must be used after including <logging/log.h> to
+ * complete the initialization of the module.
+ *
+ * Module registration can be skipped in two cases:
+ *
+ * - The module consists of more than one file, and another file
+ *   invokes this macro. (LOG_MODULE_DECLARE() should be used instead
+ *   in all of the module's other files.)
+ * - Instance logging is used and there is no need to create module entry. In
+ *   that case LOG_LEVEL_SET() should be used to set log level used within the
+ *   file.
+ *
+ * Macro accepts one or two parameters:
+ * - module name
+ * - optional log level. If not provided then default log level is used in
+ *  the file.
+ *
+ * Example usage:
+ * - LOG_MODULE_REGISTER(foo, CONFIG_FOO_LOG_LEVEL)
+ * - LOG_MODULE_REGISTER(foo)
+ *
+ *
+ * @note The module's state is defined, and the module is registered,
+ *       only if LOG_LEVEL for the current source file is non-zero or
+ *       it is not defined and CONFIG_LOG_DEFAULT_LEVEL is non-zero.
+ *       In other cases, this macro has no effect.
+ * @see LOG_MODULE_DECLARE
+ */
+
+#define LOG_MODULE_REGISTER(...)					\
+	Z_LOG_EVAL(							\
+		_LOG_LEVEL_RESOLVE(__VA_ARGS__),			\
+		(_LOG_MODULE_DATA_CREATE(GET_ARG_N(1, __VA_ARGS__),	\
+				      _LOG_LEVEL_RESOLVE(__VA_ARGS__))),\
+		()/*Empty*/						\
+	)								\
+	LOG_MODULE_DECLARE(__VA_ARGS__)
+
+/**
+ * @brief Macro for declaring a log module (not registering it).
+ *
+ * Modules which are split up over multiple files must have exactly
+ * one file use LOG_MODULE_REGISTER() to create module-specific state
+ * and register the module with the logger core.
+ *
+ * The other files in the module should use this macro instead to
+ * declare that same state. (Otherwise, LOG_INF() etc. will not be
+ * able to refer to module-specific state variables.)
+ *
+ * Macro accepts one or two parameters:
+ * - module name
+ * - optional log level. If not provided then default log level is used in
+ *  the file.
+ *
+ * Example usage:
+ * - LOG_MODULE_DECLARE(foo, CONFIG_FOO_LOG_LEVEL)
+ * - LOG_MODULE_DECLARE(foo)
+ *
+ * @note The module's state is declared only if LOG_LEVEL for the
+ *       current source file is non-zero or it is not defined and
+ *       CONFIG_LOG_DEFAULT_LEVEL is non-zero.  In other cases,
+ *       this macro has no effect.
+ * @see LOG_MODULE_REGISTER
+ */
+#define LOG_MODULE_DECLARE(...)						      \
+	extern const struct log_source_const_data			      \
+			LOG_ITEM_CONST_DATA(GET_ARG_N(1, __VA_ARGS__));	      \
+	extern struct log_source_dynamic_data				      \
+			LOG_ITEM_DYNAMIC_DATA(GET_ARG_N(1, __VA_ARGS__));     \
+									      \
+	static const struct log_source_const_data *			      \
+		__log_current_const_data __unused =			      \
+			_LOG_LEVEL_RESOLVE(__VA_ARGS__) ?		      \
+			&LOG_ITEM_CONST_DATA(GET_ARG_N(1, __VA_ARGS__)) :     \
+			NULL;						      \
+									      \
+	static struct log_source_dynamic_data *				      \
+		__log_current_dynamic_data __unused =			      \
+			(_LOG_LEVEL_RESOLVE(__VA_ARGS__) &&		      \
+			IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) ?	      \
+			&LOG_ITEM_DYNAMIC_DATA(GET_ARG_N(1, __VA_ARGS__)) :   \
+			NULL;						      \
+									      \
+	static const uint32_t __log_level __unused =			      \
+					_LOG_LEVEL_RESOLVE(__VA_ARGS__)
+
+/**
+ * @brief Macro for setting log level in the file or function where instance
+ * logging API is used.
+ *
+ * @param level Level used in file or in function.
+ *
+ */
+#define LOG_LEVEL_SET(level) static const uint32_t __log_level __unused = \
+				Z_LOG_RESOLVED_LEVEL(level, 0)
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_backend.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_backend.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_backend.h	(working copy)
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_
+
+#include <logging/log_msg.h>
+#include <stdarg.h>
+#include <sys/__assert.h>
+#include <sys/util.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Logger backend interface
+ * @defgroup log_backend Logger backend interface
+ * @ingroup logger
+ * @{
+ */
+
+/* Forward declaration of the log_backend type. */
+struct log_backend;
+
+/**
+ * @brief Logger backend API.
+ */
+struct log_backend_api {
+	void (*put)(const struct log_backend *const backend,
+		    struct log_msg *msg);
+	void (*put_sync_string)(const struct log_backend *const backend,
+			 struct log_msg_ids src_level, uint32_t timestamp,
+			 const char *fmt, va_list ap);
+	void (*put_sync_hexdump)(const struct log_backend *const backend,
+			 struct log_msg_ids src_level, uint32_t timestamp,
+			 const char *metadata, const uint8_t *data, uint32_t len);
+
+	void (*dropped)(const struct log_backend *const backend, uint32_t cnt);
+	void (*panic)(const struct log_backend *const backend);
+	void (*init)(void);
+};
+
+/**
+ * @brief Logger backend control block.
+ */
+struct log_backend_control_block {
+	void *ctx;
+	uint8_t id;
+	bool active;
+};
+
+/**
+ * @brief Logger backend structure.
+ */
+struct log_backend {
+	const struct log_backend_api *api;
+	struct log_backend_control_block *cb;
+	const char *name;
+	bool autostart;
+};
+
+extern const struct log_backend __log_backends_start[];
+extern const struct log_backend __log_backends_end[];
+
+/**
+ * @brief Macro for creating a logger backend instance.
+ *
+ * @param _name		Name of the backend instance.
+ * @param _api		Logger backend API.
+ * @param _autostart	If true backend is initialized and activated together
+ *			with the logger subsystem.
+ */
+#define LOG_BACKEND_DEFINE(_name, _api, _autostart)			       \
+	static struct log_backend_control_block UTIL_CAT(backend_cb_, _name) = \
+	{								       \
+		.id = 0,						       \
+		.active = false,					       \
+	};								       \
+	static const Z_STRUCT_SECTION_ITERABLE(log_backend, _name) =	       \
+	{								       \
+		.api = &_api,						       \
+		.cb = &UTIL_CAT(backend_cb_, _name),			       \
+		.name = STRINGIFY(_name),				       \
+		.autostart = _autostart					       \
+	}
+
+
+/**
+ * @brief Put message with log entry to the backend.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ * @param[in] msg      Pointer to message with log entry.
+ */
+static inline void log_backend_put(const struct log_backend *const backend,
+				   struct log_msg *msg)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	__ASSERT_NO_MSG(msg != NULL);
+	backend->api->put(backend, msg);
+}
+
+/**
+ * @brief Synchronously process log message.
+ *
+ * @param[in] backend   Pointer to the backend instance.
+ * @param[in] src_level Message details.
+ * @param[in] timestamp Timestamp.
+ * @param[in] fmt       Log string.
+ * @param[in] ap        Log string arguments.
+ */
+static inline void log_backend_put_sync_string(
+					const struct log_backend *const backend,
+					struct log_msg_ids src_level,
+					uint32_t timestamp, const char *fmt,
+					va_list ap)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+
+	if (backend->api->put_sync_string) {
+		backend->api->put_sync_string(backend, src_level,
+					      timestamp, fmt, ap);
+	}
+}
+
+/**
+ * @brief Synchronously process log hexdump_message.
+ *
+ * @param[in] backend   Pointer to the backend instance.
+ * @param[in] src_level Message details.
+ * @param[in] timestamp Timestamp.
+ * @param[in] metadata  Raw string associated with the data.
+ * @param[in] data      Data.
+ * @param[in] len       Data length.
+ */
+static inline void log_backend_put_sync_hexdump(
+					const struct log_backend *const backend,
+					struct log_msg_ids src_level,
+					uint32_t timestamp, const char *metadata,
+					const uint8_t *data, uint32_t len)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+
+	if (backend->api->put_sync_hexdump) {
+		backend->api->put_sync_hexdump(backend, src_level, timestamp,
+					       metadata, data, len);
+	}
+}
+
+/**
+ * @brief Notify backend about dropped log messages.
+ *
+ * Function is optional.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ * @param[in] cnt      Number of dropped logs since last notification.
+ */
+static inline void log_backend_dropped(const struct log_backend *const backend,
+				       uint32_t cnt)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+
+	if (backend->api->dropped != NULL) {
+		backend->api->dropped(backend, cnt);
+	}
+}
+
+/**
+ * @brief Reconfigure backend to panic mode.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ */
+static inline void log_backend_panic(const struct log_backend *const backend)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	backend->api->panic(backend);
+}
+
+/**
+ * @brief Set backend id.
+ *
+ * @note It is used internally by the logger.
+ *
+ * @param backend  Pointer to the backend instance.
+ * @param id       ID.
+ */
+static inline void log_backend_id_set(const struct log_backend *const backend,
+				      uint8_t id)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	backend->cb->id = id;
+}
+
+/**
+ * @brief Get backend id.
+ *
+ * @note It is used internally by the logger.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ * @return    Id.
+ */
+static inline uint8_t log_backend_id_get(const struct log_backend *const backend)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	return backend->cb->id;
+}
+
+/**
+ * @brief Get backend.
+ *
+ * @param[in] idx  Pointer to the backend instance.
+ *
+ * @return    Pointer to the backend instance.
+ */
+static inline const struct log_backend *log_backend_get(uint32_t idx)
+{
+	return &__log_backends_start[idx];
+}
+
+/**
+ * @brief Get number of backends.
+ *
+ * @return Number of backends.
+ */
+static inline int log_backend_count_get(void)
+{
+	return __log_backends_end - __log_backends_start;
+}
+
+/**
+ * @brief Activate backend.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ * @param[in] ctx      User context.
+ */
+static inline void log_backend_activate(const struct log_backend *const backend,
+					void *ctx)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	backend->cb->ctx = ctx;
+	backend->cb->active = true;
+}
+
+/**
+ * @brief Deactivate backend.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ */
+static inline void log_backend_deactivate(
+				const struct log_backend *const backend)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	backend->cb->active = false;
+}
+
+/**
+ * @brief Check state of the backend.
+ *
+ * @param[in] backend  Pointer to the backend instance.
+ *
+ * @return True if backend is active, false otherwise.
+ */
+static inline bool log_backend_is_active(
+				const struct log_backend *const backend)
+{
+	__ASSERT_NO_MSG(backend != NULL);
+	return backend->cb->active;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_core.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_core.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_core.h	(working copy)
@@ -0,0 +1,788 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_
+
+#include <logging/log_msg.h>
+#include <logging/log_instance.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/util.h>
+#include <sys/printk.h>
+
+#define LOG_LEVEL_NONE 0U
+#define LOG_LEVEL_ERR  1U
+#define LOG_LEVEL_WRN  2U
+#define LOG_LEVEL_INF  3U
+#define LOG_LEVEL_DBG  4U
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CONFIG_LOG
+#define CONFIG_LOG_DEFAULT_LEVEL 0U
+#define CONFIG_LOG_MAX_LEVEL 0U
+#endif
+
+#if !defined(CONFIG_LOG) || defined(CONFIG_LOG_MINIMAL)
+#define CONFIG_LOG_DOMAIN_ID 0U
+#endif
+
+#define LOG_FUNCTION_PREFIX_MASK \
+	(((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_ERR) << \
+	  LOG_LEVEL_ERR) | \
+	 ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_WRN) << \
+	  LOG_LEVEL_WRN) | \
+	 ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_INF) << \
+	  LOG_LEVEL_INF) | \
+	 ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_DBG) << LOG_LEVEL_DBG))
+
+/** @brief Macro for returning local level value if defined or default.
+ *
+ * Check @ref IS_ENABLED macro for detailed explanation of the trick.
+ */
+#define Z_LOG_RESOLVED_LEVEL(_level, _default) \
+	Z_LOG_RESOLVED_LEVEL1(_level, _default)
+
+#define Z_LOG_RESOLVED_LEVEL1(_level, _default) \
+	__COND_CODE(_LOG_XXXX##_level, (_level), (_default))
+
+#define _LOG_XXXX0  _LOG_YYYY,
+#define _LOG_XXXX0U _LOG_YYYY,
+#define _LOG_XXXX1  _LOG_YYYY,
+#define _LOG_XXXX1U _LOG_YYYY,
+#define _LOG_XXXX2  _LOG_YYYY,
+#define _LOG_XXXX2U _LOG_YYYY,
+#define _LOG_XXXX3  _LOG_YYYY,
+#define _LOG_XXXX3U _LOG_YYYY,
+#define _LOG_XXXX4  _LOG_YYYY,
+#define _LOG_XXXX4U _LOG_YYYY,
+
+/**
+ * @brief Macro for conditional code generation if provided log level allows.
+ *
+ * Macro behaves similarly to standard \#if \#else \#endif clause. The
+ * difference is that it is evaluated when used and not when header file is
+ * included.
+ *
+ * @param _eval_level Evaluated level. If level evaluates to one of existing log
+ *		      log level (1-4) then macro evaluates to _iftrue.
+ * @param _iftrue     Code that should be inserted when evaluated to true. Note,
+ *		      that parameter must be provided in brackets.
+ * @param _iffalse    Code that should be inserted when evaluated to false.
+ *		      Note, that parameter must be provided in brackets.
+ */
+#define Z_LOG_EVAL(_eval_level, _iftrue, _iffalse) \
+	Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse)
+
+#define Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse) \
+	__COND_CODE(_LOG_ZZZZ##_eval_level, _iftrue, _iffalse)
+
+#define _LOG_ZZZZ1  _LOG_YYYY,
+#define _LOG_ZZZZ1U _LOG_YYYY,
+#define _LOG_ZZZZ2  _LOG_YYYY,
+#define _LOG_ZZZZ2U _LOG_YYYY,
+#define _LOG_ZZZZ3  _LOG_YYYY,
+#define _LOG_ZZZZ3U _LOG_YYYY,
+#define _LOG_ZZZZ4  _LOG_YYYY,
+#define _LOG_ZZZZ4U _LOG_YYYY,
+
+/** @brief Macro for getting log level for given module.
+ *
+ * It is evaluated to LOG_LEVEL if defined. Otherwise CONFIG_LOG_DEFAULT_LEVEL
+ * is used.
+ */
+#define _LOG_LEVEL() Z_LOG_RESOLVED_LEVEL(LOG_LEVEL, CONFIG_LOG_DEFAULT_LEVEL)
+
+/**
+ *  @def LOG_CONST_ID_GET
+ *  @brief Macro for getting ID of the element of the section.
+ *
+ *  @param _addr Address of the element.
+ */
+#define LOG_CONST_ID_GET(_addr) \
+	Z_LOG_EVAL(\
+	  CONFIG_LOG,\
+	  (__log_level ? \
+	  log_const_source_id((const struct log_source_const_data *)_addr) : \
+	  0),\
+	  (0)\
+	)
+
+/**
+ * @def LOG_CURRENT_MODULE_ID
+ * @brief Macro for getting ID of current module.
+ */
+#define LOG_CURRENT_MODULE_ID() (__log_level != 0 ? \
+	log_const_source_id(__log_current_const_data) : 0U)
+
+/**
+ * @def LOG_CURRENT_DYNAMIC_DATA_ADDR
+ * @brief Macro for getting address of dynamic structure of current module.
+ */
+#define LOG_CURRENT_DYNAMIC_DATA_ADDR()	(__log_level ? \
+	__log_current_dynamic_data : (struct log_source_dynamic_data *)0U)
+
+/** @brief Macro for getting ID of the element of the section.
+ *
+ *  @param _addr Address of the element.
+ */
+#define LOG_DYNAMIC_ID_GET(_addr) \
+	Z_LOG_EVAL(\
+	  CONFIG_LOG,\
+	  (__log_level ? \
+	  log_dynamic_source_id((struct log_source_dynamic_data *)_addr) : 0),\
+	  (0)\
+	)
+
+/**
+ * @brief Macro for optional injection of function name as first argument of
+ *	  formatted string. COND_CODE_0() macro is used to handle no arguments
+ *	  case.
+ *
+ *	  The purpose of this macro is to prefix string literal with format
+ *	  specifier for function name and inject function name as first
+ *	  argument. In order to handle string with no arguments _LOG_Z_EVAL is
+ *	  used.
+ */
+
+#define Z_LOG_STR(...) "%s: " GET_ARG_N(1, __VA_ARGS__), __func__\
+		COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__),\
+			    (),\
+			    (, GET_ARGS_LESS_N(1, __VA_ARGS__))\
+			   )
+
+
+/******************************************************************************/
+/****************** Internal macros for log frontend **************************/
+/******************************************************************************/
+/**@brief Second stage for Z_LOG_NARGS_POSTFIX */
+#define _LOG_NARGS_POSTFIX_IMPL(				\
+	_ignored,						\
+	_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,		\
+	_11, _12, _13, _14, N, ...) N
+
+/**@brief Macro to get the postfix for further log message processing.
+ *
+ * Logs with more than 3 arguments are processed in a generic way.
+ *
+ * param[in]    ...     List of arguments
+ *
+ * @retval  Postfix, number of arguments or _LONG when more than 3 arguments.
+ */
+#define Z_LOG_NARGS_POSTFIX(...) \
+	_LOG_NARGS_POSTFIX_IMPL(__VA_ARGS__, LONG, LONG, LONG, LONG, LONG, \
+			LONG, LONG, LONG, LONG, LONG, LONG, LONG, 3, 2, 1, 0, ~)
+
+#define Z_LOG_INTERNAL_X(N, ...)  UTIL_CAT(_LOG_INTERNAL_, N)(__VA_ARGS__)
+
+#define __LOG_INTERNAL(is_user_context, _src_level, ...)		 \
+	do {								 \
+		if (is_user_context) {					 \
+			log_from_user(_src_level, __VA_ARGS__);		 \
+		} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) {		 \
+			log_string_sync(_src_level, __VA_ARGS__);	 \
+		} else {						 \
+			Z_LOG_INTERNAL_X(Z_LOG_NARGS_POSTFIX(__VA_ARGS__), \
+						_src_level, __VA_ARGS__);\
+		}							 \
+	} while (false)
+
+#define _LOG_INTERNAL_0(_src_level, _str) \
+	log_0(_str, _src_level)
+
+#define _LOG_INTERNAL_1(_src_level, _str, _arg0) \
+	log_1(_str, (log_arg_t)(_arg0), _src_level)
+
+#define _LOG_INTERNAL_2(_src_level, _str, _arg0, _arg1)	\
+	log_2(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), _src_level)
+
+#define _LOG_INTERNAL_3(_src_level, _str, _arg0, _arg1, _arg2) \
+	log_3(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), (log_arg_t)(_arg2), _src_level)
+
+#define __LOG_ARG_CAST(_x) (log_arg_t)(_x)
+
+#define __LOG_ARGUMENTS(...) FOR_EACH(__LOG_ARG_CAST, (,), __VA_ARGS__)
+
+#define _LOG_INTERNAL_LONG(_src_level, _str, ...)		  \
+	do {							  \
+		log_arg_t args[] = {__LOG_ARGUMENTS(__VA_ARGS__)};\
+		log_n(_str, args, ARRAY_SIZE(args), _src_level);  \
+	} while (false)
+
+#define Z_LOG_LEVEL_CHECK(_level, _check_level, _default_level) \
+	(_level <= Z_LOG_RESOLVED_LEVEL(_check_level, _default_level))
+
+#define Z_LOG_CONST_LEVEL_CHECK(_level)					    \
+	(IS_ENABLED(CONFIG_LOG) &&					    \
+	(Z_LOG_LEVEL_CHECK(_level, CONFIG_LOG_OVERRIDE_LEVEL, LOG_LEVEL_NONE) \
+	||								    \
+	((IS_ENABLED(CONFIG_LOG_OVERRIDE_LEVEL) == false) &&		    \
+	(_level <= __log_level) &&					    \
+	(_level <= CONFIG_LOG_MAX_LEVEL)				    \
+	)								    \
+	))
+
+/******************************************************************************/
+/****************** Defiinitions used by minimal logging **********************/
+/******************************************************************************/
+void log_minimal_hexdump_print(int level, const void *data, size_t size);
+
+#define Z_LOG_TO_PRINTK(_level, fmt, ...) do {				     \
+		printk("%c: " fmt "\n", z_log_minimal_level_to_char(_level), \
+			##__VA_ARGS__);					     \
+	} while (false)
+
+static inline char z_log_minimal_level_to_char(int level)
+{
+	switch (level) {
+	case LOG_LEVEL_ERR:
+		return 'E';
+	case LOG_LEVEL_WRN:
+		return 'W';
+	case LOG_LEVEL_INF:
+		return 'I';
+	case LOG_LEVEL_DBG:
+		return 'D';
+	default:
+		return '?';
+	}
+}
+/******************************************************************************/
+/****************** Macros for standard logging *******************************/
+/******************************************************************************/
+#define __LOG(_level, _name, _level_thod, ...)				       \
+	do {						       \
+			Z_LOG_TO_PRINTK(_level, __VA_ARGS__);	       \
+	} while (false)
+
+#define Z_LOG(_level, ...)			       \
+	__LOG(_level,				       \
+	      __VA_ARGS__)
+
+#define Z_LOG_INSTANCE(_level, _inst, ...)		 \
+	do {						       \
+	} while (false)
+	
+
+
+/******************************************************************************/
+/****************** Macros for hexdump logging ********************************/
+/******************************************************************************/
+#define __LOG_HEXDUMP(_level, _id, _filter, _data, _length, _str)	       \
+	do {								       \
+		if (Z_LOG_CONST_LEVEL_CHECK(_level)) {			       \
+			bool is_user_context = _is_user_context();	       \
+									       \
+			if (IS_ENABLED(CONFIG_LOG_MINIMAL)) {		       \
+				Z_LOG_TO_PRINTK(_level, "%s", _str);	       \
+				log_minimal_hexdump_print(_level,	       \
+							  (const char *)_data, \
+							  _length);	       \
+			} else if (LOG_CHECK_CTX_LVL_FILTER(is_user_context,\
+					_level, _filter)) {  \
+				struct log_msg_ids src_level = {	       \
+					.level = _level,		       \
+					.domain_id = CONFIG_LOG_DOMAIN_ID,     \
+					.source_id = _id,		       \
+				};					       \
+									       \
+				if (is_user_context) {			       \
+					log_hexdump_from_user(src_level, _str, \
+							      (const char *)_data, \
+							      _length);	       \
+				} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
+					log_hexdump_sync(src_level, _str,      \
+							 (const char *)_data,  \
+							  _length);	       \
+				} else {				       \
+					log_hexdump(_str, (const char *)_data, \
+						    _length,		       \
+						    src_level);		       \
+				}					       \
+			} else {				       \
+			}						       \
+		}							       \
+	} while (false)
+
+#define Z_LOG_HEXDUMP(_level, _data, _length, _str)	       \
+	__LOG_HEXDUMP(_level,				       \
+		      (uint16_t)LOG_CURRENT_MODULE_ID(),	       \
+		      LOG_CURRENT_DYNAMIC_DATA_ADDR(),	       \
+		      _data, _length, _str)
+
+#define Z_LOG_HEXDUMP_INSTANCE(_level, _inst, _data, _length, _str) \
+	__LOG_HEXDUMP(_level,					   \
+		      IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ?   \
+		      LOG_DYNAMIC_ID_GET(_inst) :		   \
+		      LOG_CONST_ID_GET(_inst),			   \
+		      _inst,					   \
+		      _data,					   \
+		      _length,					   \
+		      _str)
+
+/******************************************************************************/
+/****************** Filtering macros ******************************************/
+/******************************************************************************/
+
+/** @brief Number of bits used to encode log level. */
+#define LOG_LEVEL_BITS 3U
+
+/** @brief Filter slot size. */
+#define LOG_FILTER_SLOT_SIZE LOG_LEVEL_BITS
+
+/** @brief Number of slots in one word. */
+#define LOG_FILTERS_NUM_OF_SLOTS (32 / LOG_FILTER_SLOT_SIZE)
+
+/** @brief Slot mask. */
+#define LOG_FILTER_SLOT_MASK (BIT(LOG_FILTER_SLOT_SIZE) - 1U)
+
+/** @brief Bit offset of a slot.
+ *
+ *  @param _id Slot ID.
+ */
+#define LOG_FILTER_SLOT_SHIFT(_id) (LOG_FILTER_SLOT_SIZE * (_id))
+
+#define LOG_FILTER_SLOT_GET(_filters, _id) \
+	((*(_filters) >> LOG_FILTER_SLOT_SHIFT(_id)) & LOG_FILTER_SLOT_MASK)
+
+#define LOG_FILTER_SLOT_SET(_filters, _id, _filter)		     \
+	do {							     \
+		*(_filters) &= ~(LOG_FILTER_SLOT_MASK <<	     \
+				 LOG_FILTER_SLOT_SHIFT(_id));	     \
+		*(_filters) |= ((_filter) & LOG_FILTER_SLOT_MASK) << \
+			       LOG_FILTER_SLOT_SHIFT(_id);	     \
+	} while (false)
+
+#define LOG_FILTER_AGGR_SLOT_IDX 0
+
+#define LOG_FILTER_AGGR_SLOT_GET(_filters) \
+	LOG_FILTER_SLOT_GET(_filters, LOG_FILTER_AGGR_SLOT_IDX)
+
+#define LOG_FILTER_FIRST_BACKEND_SLOT_IDX 1
+
+#ifdef CONFIG_LOG_RUNTIME_FILTERING
+#define LOG_CHECK_CTX_LVL_FILTER(ctx, _level, _filter) \
+	(ctx || (_level <= LOG_RUNTIME_FILTER(_filter)))
+#define LOG_RUNTIME_FILTER(_filter) \
+	LOG_FILTER_SLOT_GET(&(_filter)->filters, LOG_FILTER_AGGR_SLOT_IDX)
+#else
+#define LOG_CHECK_CTX_LVL_FILTER(ctx, _level, _filter) (true)
+#define LOG_RUNTIME_FILTER(_filter) LOG_LEVEL_DBG
+#endif
+
+/** @brief Log level value used to indicate log entry that should not be
+ *	   formatted (raw string).
+ */
+#define LOG_LEVEL_INTERNAL_RAW_STRING LOG_LEVEL_NONE
+
+extern struct log_source_const_data __log_const_start[];
+extern struct log_source_const_data __log_const_end[];
+
+/** @brief Enum with possible actions for strdup operation. */
+enum log_strdup_action {
+	LOG_STRDUP_SKIP,     /**< None RAM string duplication. */
+	LOG_STRDUP_EXEC,     /**< Always duplicate RAM strings. */
+	LOG_STRDUP_CHECK_EXEC/**< Duplicate RAM strings, if not dupl. before.*/
+};
+
+/** @brief Get name of the log source.
+ *
+ * @param source_id Source ID.
+ * @return Name.
+ */
+static inline const char *log_name_get(uint32_t source_id)
+{
+	return __log_const_start[source_id].name;
+}
+
+/** @brief Get compiled level of the log source.
+ *
+ * @param source_id Source ID.
+ * @return Level.
+ */
+static inline uint8_t log_compiled_level_get(uint32_t source_id)
+{
+	return __log_const_start[source_id].level;
+}
+
+/** @brief Get index of the log source based on the address of the constant data
+ *         associated with the source.
+ *
+ * @param data Address of the constant data.
+ *
+ * @return Source ID.
+ */
+static inline uint32_t log_const_source_id(
+				const struct log_source_const_data *data)
+{
+	return ((uint8_t *)data - (uint8_t *)__log_const_start)/
+			sizeof(struct log_source_const_data);
+}
+
+/** @brief Get number of registered sources. */
+static inline uint32_t log_sources_count(void)
+{
+	return log_const_source_id(__log_const_end);
+}
+
+extern struct log_source_dynamic_data __log_dynamic_start[];
+extern struct log_source_dynamic_data __log_dynamic_end[];
+
+/** @brief Creates name of variable and section for runtime log data.
+ *
+ *  @param _name Name.
+ */
+#define LOG_ITEM_DYNAMIC_DATA(_name) UTIL_CAT(log_dynamic_, _name)
+
+#define LOG_INSTANCE_DYNAMIC_DATA(_module_name, _inst) \
+	LOG_ITEM_DYNAMIC_DATA(LOG_INSTANCE_FULL_NAME(_module_name, _inst))
+
+/** @brief Get pointer to the filter set of the log source.
+ *
+ * @param source_id Source ID.
+ *
+ * @return Pointer to the filter set.
+ */
+static inline uint32_t *log_dynamic_filters_get(uint32_t source_id)
+{
+	return &__log_dynamic_start[source_id].filters;
+}
+
+/** @brief Get index of the log source based on the address of the dynamic data
+ *         associated with the source.
+ *
+ * @param data Address of the dynamic data.
+ *
+ * @return Source ID.
+ */
+static inline uint32_t log_dynamic_source_id(struct log_source_dynamic_data *data)
+{
+	return ((uint8_t *)data - (uint8_t *)__log_dynamic_start)/
+			sizeof(struct log_source_dynamic_data);
+}
+
+/** @brief Dummy function to trigger log messages arguments type checking. */
+static inline __printf_like(1, 2)
+void log_printf_arg_checker(const char *fmt, ...)
+{
+	ARG_UNUSED(fmt);
+}
+
+/** @brief Standard log with no arguments.
+ *
+ * @param str           String.
+ * @param src_level	Log identification.
+ */
+void log_0(const char *str, struct log_msg_ids src_level);
+
+/** @brief Standard log with one argument.
+ *
+ * @param str           String.
+ * @param arg1	        First argument.
+ * @param src_level	Log identification.
+ */
+void log_1(const char *str,
+	   log_arg_t arg1,
+	   struct log_msg_ids src_level);
+
+/** @brief Standard log with two arguments.
+ *
+ * @param str           String.
+ * @param arg1	        First argument.
+ * @param arg2	        Second argument.
+ * @param src_level	Log identification.
+ */
+void log_2(const char *str,
+	   log_arg_t arg1,
+	   log_arg_t arg2,
+	   struct log_msg_ids src_level);
+
+/** @brief Standard log with three arguments.
+ *
+ * @param str           String.
+ * @param arg1	        First argument.
+ * @param arg2	        Second argument.
+ * @param arg3	        Third argument.
+ * @param src_level	Log identification.
+ */
+void log_3(const char *str,
+	   log_arg_t arg1,
+	   log_arg_t arg2,
+	   log_arg_t arg3,
+	   struct log_msg_ids src_level);
+
+/** @brief Standard log with arguments list.
+ *
+ * @param str		String.
+ * @param args		Array with arguments.
+ * @param narg		Number of arguments in the array.
+ * @param src_level	Log identification.
+ */
+void log_n(const char *str,
+	   log_arg_t *args,
+	   uint32_t narg,
+	   struct log_msg_ids src_level);
+
+/** @brief Hexdump log.
+ *
+ * @param str		String.
+ * @param data		Data.
+ * @param length	Data length.
+ * @param src_level	Log identification.
+ */
+void log_hexdump(const char *str, const void *data, uint32_t length,
+		 struct log_msg_ids src_level);
+
+/** @brief Process log message synchronously.
+ *
+ * @param src_level	Log message details.
+ * @param fmt		String to format.
+ * @param ...		Variable list of arguments.
+ */
+void log_string_sync(struct log_msg_ids src_level, const char *fmt, ...);
+
+/** @brief Process log hexdump message synchronously.
+ *
+ * @param src_level	Log message details.
+ * @param metadata	Raw string associated with the data.
+ * @param data		Data.
+ * @param len		Data length.
+ */
+void log_hexdump_sync(struct log_msg_ids src_level, const char *metadata,
+		      const void *data, uint32_t len);
+
+/**
+ * @brief Writes a generic log message to the log.
+ *
+ * @note This function is intended to be used when porting other log systems.
+ *
+ * @param src_level      Log identification.
+ * @param fmt            String to format.
+ * @param ap             Poiner to arguments list.
+ * @param strdup_action  Manages strdup activity.
+ */
+void log_generic(struct log_msg_ids src_level, const char *fmt, va_list ap,
+		 enum log_strdup_action strdup_action);
+
+/**
+ * @brief Returns number of arguments visible from format string.
+ *
+ * @note This function is intended to be used when porting other log systems.
+ *
+ * @param fmt     Format string.
+ *
+ * @return        Number of arguments.
+ */
+uint32_t log_count_args(const char *fmt);
+
+/**
+ * @brief Writes a generic log message to the log from user mode.
+ *
+ * @note This function is intended to be used internally
+ *	 by the logging subsystem.
+ */
+void log_generic_from_user(struct log_msg_ids src_level,
+			   const char *fmt, va_list ap);
+
+/** @brief Check if address belongs to the memory pool used for transient.
+ *
+ * @param buf Buffer.
+ *
+ * @return True if address within the pool, false otherwise.
+ */
+bool log_is_strdup(const void *buf);
+
+/** @brief Free allocated buffer.
+ *
+ * @param buf Buffer.
+ */
+void log_free(void *buf);
+
+/**
+ * @brief Get maximal number of simultaneously allocated buffers for string
+ *	  duplicates.
+ *
+ * Value can be used to determine pool size.
+ */
+uint32_t log_get_strdup_pool_utilization(void);
+
+/**
+ * @brief Get length of the longest string duplicated.
+ *
+ * Value can be used to determine buffer size in the string duplicates pool.
+ */
+uint32_t log_get_strdup_longest_string(void);
+
+/** @brief Indicate to the log core that one log message has been dropped.
+ */
+void log_dropped(void);
+
+/** @brief Log a message from user mode context.
+ *
+ * @note This function is intended to be used internally
+ *	 by the logging subsystem.
+ *
+ * @param src_level    Log identification.
+ * @param fmt          String to format.
+ * @param ...          Variable list of arguments.
+ */
+void __printf_like(2, 3) log_from_user(struct log_msg_ids src_level,
+				       const char *fmt, ...);
+
+/**
+ * @brief Create mask with occurences of a string format specifiers (%s).
+ *
+ * Result is stored as the mask (argument n is n'th bit). Bit is set if string
+ * format specifier was found.
+ *
+ * @param str String.
+ * @param nargs Number of arguments in the string.
+ *
+ * @return Mask with %s format specifiers found.
+ */
+uint32_t z_log_get_s_mask(const char *str, uint32_t nargs);
+
+/* Internal function used by log_from_user(). */
+__syscall void z_log_string_from_user(uint32_t src_level_val, const char *str);
+
+/** @brief Log binary data (displayed as hexdump) from user mode context.
+ *
+ * @note This function is intended to be used internally
+ *	 by the logging subsystem.
+ *
+ * @param src_level	Log identification.
+ * @param metadata	Raw string associated with the data.
+ * @param data		Data.
+ * @param len		Data length.
+ */
+void log_hexdump_from_user(struct log_msg_ids src_level, const char *metadata,
+			   const void *data, uint32_t len);
+
+/* Internal function used by log_hexdump_from_user(). */
+__syscall void z_log_hexdump_from_user(uint32_t src_level_val,
+				       const char *metadata,
+				       const uint8_t *data, uint32_t len);
+
+/******************************************************************************/
+/********** Mocros _VA operate on var-args parameters.          ***************/
+/*********  Intended to be used when porting other log systems. ***************/
+/*********  Shall be used in the log entry interface function.  ***************/
+/*********  Speed optimized for up to three arguments number.   ***************/
+/******************************************************************************/
+#define Z_LOG_VA(_level, _str, _valist, _argnum, _strdup_action)\
+	__LOG_VA(_level,					\
+		  (uint16_t)LOG_CURRENT_MODULE_ID(),		\
+		  LOG_CURRENT_DYNAMIC_DATA_ADDR(),		\
+		  _str, _valist, _argnum, _strdup_action)
+
+#define __LOG_VA(_level, _id, _filter, _str, _valist, _argnum, _strdup_action) \
+	do {								       \
+		if (Z_LOG_CONST_LEVEL_CHECK(_level)) {			       \
+			bool is_user_context = _is_user_context();	       \
+									       \
+			if (IS_ENABLED(CONFIG_LOG_MINIMAL)) {		       \
+				if (IS_ENABLED(CONFIG_LOG_PRINTK)) {	       \
+					log_printk(_str, _valist);	       \
+				} else {				       \
+					vprintk(_str, _valist);		       \
+				}					       \
+			} else if (LOG_CHECK_CTX_LVL_FILTER(is_user_context, \
+					_level, _filter)) {  \
+				struct log_msg_ids src_level = {	       \
+					.level = _level,		       \
+					.domain_id = CONFIG_LOG_DOMAIN_ID,     \
+					.source_id = _id		       \
+				};					       \
+				__LOG_INTERNAL_VA(is_user_context,	       \
+						src_level,		       \
+						_str, _valist, _argnum,        \
+						_strdup_action);	       \
+			} else {				       \
+			}						       \
+		}							       \
+	} while (false)
+
+/**
+ * @brief Inline function to perform strdup, used in __LOG_INTERNAL_VA macro
+ *
+ * @note This function is intended to be used when porting other log systems.
+ *
+ * @param msk	  Bitmask marking all %s arguments.
+ * @param idx	  Index of actually processed argument.
+ * @param param   Value of actually processed argument.
+ * @param action  Action for strdup operation.
+ *
+ * @return	  Duplicated string or not changed param.
+ */
+static inline log_arg_t z_log_do_strdup(uint32_t msk, uint32_t idx,
+					log_arg_t param,
+					enum log_strdup_action action)
+{
+#ifndef CONFIG_LOG_MINIMAL
+	char *log_strdup(const char *str);
+
+	if (msk & (1 << idx)) {
+		const char *str = (const char *)param;
+		/* is_rodata(str) is not checked,
+		 * because log_strdup does it.
+		 * Hence, we will do only optional check
+		 * if already not duplicated.
+		 */
+		if (action == LOG_STRDUP_EXEC || !log_is_strdup(str)) {
+			param = (log_arg_t)log_strdup(str);
+		}
+	}
+#endif
+	return param;
+}
+
+#define __LOG_INTERNAL_VA(is_user_context, _src_level, _str, _valist,	       \
+						_argnum, _strdup_action)       \
+do {									       \
+	if (is_user_context) {						       \
+		log_generic_from_user(_src_level, _str, _valist);	       \
+	} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) {			       \
+		log_generic(_src_level, _str, _valist, _strdup_action);        \
+	} else if (_argnum == 0) {					       \
+		_LOG_INTERNAL_0(_src_level, _str);			       \
+	} else {							       \
+		uint32_t mask = (_strdup_action != LOG_STRDUP_SKIP) ?	       \
+			z_log_get_s_mask(_str, _argnum) 		       \
+			: 0;						       \
+									       \
+		if (_argnum == 1) {					       \
+			_LOG_INTERNAL_1(_src_level, _str,		       \
+				z_log_do_strdup(mask, 0,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action));\
+		} else if (_argnum == 2) {				       \
+			_LOG_INTERNAL_2(_src_level, _str,		       \
+				z_log_do_strdup(mask, 0,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action), \
+				z_log_do_strdup(mask, 1,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action));\
+		} else if (_argnum == 3) {				       \
+			_LOG_INTERNAL_3(_src_level, _str,		       \
+				z_log_do_strdup(mask, 0,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action), \
+				z_log_do_strdup(mask, 1,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action), \
+				z_log_do_strdup(mask, 2,		       \
+				  va_arg(_valist, log_arg_t), _strdup_action));\
+		} else {						       \
+			log_generic(_src_level, _str, _valist, _strdup_action);\
+		}							       \
+	}								       \
+} while (false)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_ctrl.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_ctrl.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_ctrl.h	(working copy)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_CTRL_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_CTRL_H_
+
+#include <logging/log_backend.h>
+#include <kernel.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Logger
+ * @defgroup logger Logger system
+ * @ingroup logging
+ * @{
+ * @}
+ */
+
+/**
+ * @brief Logger control API
+ * @defgroup log_ctrl Logger control API
+ * @ingroup logger
+ * @{
+ */
+
+typedef uint32_t (*timestamp_get_t)(void);
+
+/** @brief Function system initialization of the logger.
+ *
+ * Function is called during start up to allow logging before user can
+ * explicitly initialize the logger.
+ */
+void log_core_init(void);
+
+/**
+ * @brief Function for user initialization of the logger.
+ *
+ */
+void log_init(void);
+
+/**
+ * @brief Function for providing thread which is processing logs.
+ *
+ * See CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD.
+ *
+ * @note Function has asserts and has no effect when CONFIG_LOG_PROCESS_THREAD is set.
+ *
+ * @param process_tid Process thread id. Used to wake up the thread.
+ */
+void log_thread_set(k_tid_t process_tid);
+
+/**
+ * @brief Function for providing timestamp function.
+ *
+ * @param timestamp_getter	Timestamp function.
+ * @param freq			Timestamping frequency.
+ *
+ * @return 0 on success or error.
+ */
+int log_set_timestamp_func(timestamp_get_t timestamp_getter, uint32_t freq);
+
+/**
+ * @brief Switch the logger subsystem to the panic mode.
+ *
+ * Returns immediately if the logger is already in the panic mode.
+ *
+ * @details On panic the logger subsystem informs all backends about panic mode.
+ *          Backends must switch to blocking mode or halt. All pending logs
+ *          are flushed after switching to panic mode. In panic mode, all log
+ *          messages must be processed in the context of the call.
+ */
+__syscall void log_panic(void);
+
+/**
+ * @brief Process one pending log message.
+ *
+ * @param bypass If true message is released without being processed.
+ *
+ * @retval true There is more messages pending to be processed.
+ * @retval false No messages pending.
+ */
+__syscall bool log_process(bool bypass);
+
+/**
+ * @brief Return number of buffered log messages.
+ *
+ * @return Number of currently buffered log messages.
+ */
+__syscall uint32_t log_buffered_cnt(void);
+
+/** @brief Get number of independent logger sources (modules and instances)
+ *
+ * @param domain_id Domain ID.
+ *
+ * @return Number of sources.
+ */
+uint32_t log_src_cnt_get(uint32_t domain_id);
+
+
+/** @brief Get name of the source (module or instance).
+ *
+ * @param domain_id Domain ID.
+ * @param src_id    Source ID.
+ *
+ * @return Source name or NULL if invalid arguments.
+ */
+const char *log_source_name_get(uint32_t domain_id, uint32_t src_id);
+
+/** @brief Get name of the domain.
+ *
+ * @param domain_id Domain ID.
+ *
+ * @return Domain name.
+ */
+const char *log_domain_name_get(uint32_t domain_id);
+
+/**
+ * @brief Get source filter for the provided backend.
+ *
+ * @param backend	Backend instance.
+ * @param domain_id	ID of the domain.
+ * @param src_id	Source (module or instance) ID.
+ * @param runtime	True for runtime filter or false for compiled in.
+ *
+ * @return		Severity level.
+ */
+uint32_t log_filter_get(struct log_backend const *const backend,
+		     uint32_t domain_id, uint32_t src_id, bool runtime);
+
+/**
+ * @brief Set filter on given source for the provided backend.
+ *
+ * @param backend	Backend instance. NULL for all backends.
+ * @param domain_id	ID of the domain.
+ * @param src_id	Source (module or instance) ID.
+ * @param level		Severity level.
+ *
+ * @return Actual level set which may be limited by compiled level. If filter
+ *	   was set for all backends then maximal level that was set is returned.
+ */
+__syscall uint32_t log_filter_set(struct log_backend const *const backend,
+			       uint32_t domain_id,
+			       uint32_t src_id,
+			       uint32_t level);
+
+/**
+ *
+ * @brief Enable backend with initial maximum filtering level.
+ *
+ * @param backend	Backend instance.
+ * @param ctx		User context.
+ * @param level		Severity level.
+ */
+void log_backend_enable(struct log_backend const *const backend,
+			void *ctx,
+			uint32_t level);
+
+/**
+ *
+ * @brief Disable backend.
+ *
+ * @param backend	Backend instance.
+ */
+void log_backend_disable(struct log_backend const *const backend);
+
+#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MINIMAL)
+#define LOG_CORE_INIT() log_core_init()
+#define LOG_INIT() log_init()
+#define LOG_PANIC() log_panic()
+#define LOG_PROCESS() log_process(false)
+#else
+#define LOG_CORE_INIT() do { } while (false)
+#define LOG_INIT() 0
+#define LOG_PANIC() /* Empty */
+#define LOG_PROCESS() false
+#endif
+
+#include <syscalls/log_ctrl.h>
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_CTRL_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_frontend.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_frontend.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_frontend.h	(working copy)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef LOG_FRONTEND_H_
+#define LOG_FRONTEND_H_
+
+#include <logging/log_core.h>
+
+/** @brief Initialize frontend.
+ */
+void log_frontend_init(void);
+
+/** @brief Standard log with no arguments.
+ *
+ * @param str		String.
+ * @param src_level	Log identification.
+ */
+void log_frontend_0(const char *str, struct log_msg_ids src_level);
+
+/** @brief Standard log with one argument.
+ *
+ * @param str		String.
+ * @param arg0		First argument.
+ * @param src_level	Log identification.
+ */
+void log_frontend_1(const char *str,
+		    log_arg_t arg0,
+		    struct log_msg_ids src_level);
+
+/** @brief Standard log with two arguments.
+ *
+ * @param str		String.
+ * @param arg0		First argument.
+ * @param arg1		Second argument.
+ * @param src_level	Log identification.
+ */
+void log_frontend_2(const char *str,
+		    log_arg_t arg0,
+		    log_arg_t arg1,
+		    struct log_msg_ids src_level);
+
+/** @brief Standard log with three arguments.
+ *
+ * @param str		String.
+ * @param arg0		First argument.
+ * @param arg1		Second argument.
+ * @param arg2		Third argument.
+ * @param src_level	Log identification.
+ */
+void log_frontend_3(const char *str,
+		    log_arg_t arg0,
+		    log_arg_t arg1,
+		    log_arg_t arg2,
+		    struct log_msg_ids src_level);
+
+/** @brief Standard log with arguments list.
+ *
+ * @param str		String.
+ * @param args		Array with arguments.
+ * @param narg		Number of arguments in the array.
+ * @param src_level	Log identification.
+ */
+void log_frontend_n(const char *str,
+		    log_arg_t *args,
+		    uint32_t narg,
+		    struct log_msg_ids src_level);
+
+/** @brief Hexdump log.
+ *
+ * @param str		String.
+ * @param data		Data.
+ * @param length	Data length.
+ * @param src_level	Log identification.
+ */
+void log_frontend_hexdump(const char *str,
+			  const uint8_t *data,
+			  uint32_t length,
+			  struct log_msg_ids src_level);
+
+
+#endif /* LOG_FRONTEND_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_instance.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_instance.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_instance.h	(working copy)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_INSTANCE_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_INSTANCE_H_
+
+#include <types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @brief Constant data associated with the source of log messages. */
+struct log_source_const_data {
+	const char *name;
+	uint8_t level;
+#ifdef CONFIG_NIOS2
+	/* Workaround alert! Dummy data to ensure that structure is >8 bytes.
+	 * Nios2 uses global pointer register for structures <=8 bytes and
+	 * apparently does not handle well variables placed in custom sections.
+	 */
+	uint32_t dummy;
+#endif
+};
+
+/** @brief Dynamic data associated with the source of log messages. */
+struct log_source_dynamic_data {
+	uint32_t filters;
+#ifdef CONFIG_NIOS2
+	/* Workaround alert! Dummy data to ensure that structure is >8 bytes.
+	 * Nios2 uses global pointer register for structures <=8 bytes and
+	 * apparently does not handle well variables placed in custom sections.
+	 */
+	uint32_t dummy[2];
+#endif
+};
+
+/** @brief Creates name of variable and section for constant log data.
+ *
+ *  @param _name Name.
+ */
+#define LOG_ITEM_CONST_DATA(_name) UTIL_CAT(log_const_, _name)
+
+#define Z_LOG_CONST_ITEM_REGISTER(_name, _str_name, _level)		     \
+	const struct log_source_const_data LOG_ITEM_CONST_DATA(_name)	     \
+	__attribute__ ((section("." STRINGIFY(LOG_ITEM_CONST_DATA(_name))))) \
+	__attribute__((used)) = {					     \
+		.name = _str_name,					     \
+		.level  = (_level),					     \
+	}
+
+/** @def LOG_INSTANCE_PTR_DECLARE
+ * @brief Macro for declaring a logger instance pointer in the module structure.
+ */
+
+/** @def LOG_INSTANCE_REGISTER
+ * @brief Macro for registering instance for logging with independent filtering.
+ *
+ * Module instance provides filtering of logs on instance level instead of
+ * module level.
+ */
+
+/** @def LOG_INSTANCE_PTR_INIT
+ * @brief Macro for initializing a pointer to the logger instance.
+ */
+
+#ifdef CONFIG_LOG
+
+#define LOG_INSTANCE_FULL_NAME(_module_name, _inst_name) \
+	UTIL_CAT(_module_name, UTIL_CAT(_, _inst_name))
+
+#if defined(CONFIG_LOG_RUNTIME_FILTERING)
+#define LOG_INSTANCE_PTR_DECLARE(_name)	\
+	struct log_source_dynamic_data *_name
+
+#define LOG_INSTANCE_REGISTER(_module_name, _inst_name, _level)		   \
+	Z_LOG_CONST_ITEM_REGISTER(					   \
+		LOG_INSTANCE_FULL_NAME(_module_name, _inst_name),	   \
+		STRINGIFY(_module_name._inst_name),			   \
+		_level);						   \
+	struct log_source_dynamic_data LOG_INSTANCE_DYNAMIC_DATA(	   \
+						_module_name, _inst_name)  \
+		__attribute__ ((section("." STRINGIFY(			   \
+				LOG_INSTANCE_DYNAMIC_DATA(_module_name,	   \
+						       _inst_name)	   \
+				)					   \
+		))) __attribute__((used))
+
+#define LOG_INSTANCE_PTR_INIT(_name, _module_name, _inst_name)	   \
+	._name = &LOG_ITEM_DYNAMIC_DATA(			   \
+		LOG_INSTANCE_FULL_NAME(_module_name, _inst_name)),
+
+#else /* CONFIG_LOG_RUNTIME_FILTERING */
+#define LOG_INSTANCE_PTR_DECLARE(_name)	\
+	const struct log_source_const_data *_name
+
+#define LOG_INSTANCE_REGISTER(_module_name, _inst_name, _level)	  \
+	Z_LOG_CONST_ITEM_REGISTER(				  \
+		LOG_INSTANCE_FULL_NAME(_module_name, _inst_name), \
+		STRINGIFY(_module_name._inst_name),		  \
+		_level)
+
+
+#define LOG_INSTANCE_PTR_INIT(_name, _module_name, _inst_name) \
+	._name = &LOG_ITEM_CONST_DATA(			       \
+		LOG_INSTANCE_FULL_NAME(_module_name, _inst_name)),
+
+#endif /* CONFIG_LOG_RUNTIME_FILTERING */
+#else /* CONFIG_LOG */
+#define LOG_INSTANCE_PTR_DECLARE(_name) /* empty */
+#define LOG_INSTANCE_REGISTER(_module_name, _inst_name,  _level)    /* empty */
+#define LOG_INSTANCE_PTR_INIT(_name, _module_name, _inst_name)      /* empty */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_INSTANCE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_msg.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_msg.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_msg.h	(working copy)
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
+
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Log message API
+ * @defgroup log_msg Log message API
+ * @ingroup logger
+ * @{
+ */
+
+/** @brief Log argument type.
+ *
+ * Should preferably be equivalent to a native word size.
+ */
+typedef unsigned long log_arg_t;
+
+/** @brief Maximum number of arguments in the standard log entry.
+ *
+ * It is limited by 4 bit nargs field in the log message.
+ */
+#define LOG_MAX_NARGS 15
+
+/** @brief Number of arguments in the log entry which fits in one chunk.*/
+#ifdef CONFIG_64BIT
+#define LOG_MSG_NARGS_SINGLE_CHUNK 4U
+#else
+#define LOG_MSG_NARGS_SINGLE_CHUNK 3U
+#endif
+
+/** @brief Number of arguments in the head of extended standard log message..*/
+#define LOG_MSG_NARGS_HEAD_CHUNK \
+	(LOG_MSG_NARGS_SINGLE_CHUNK - (sizeof(void *)/sizeof(log_arg_t)))
+
+/** @brief Maximal amount of bytes in the hexdump entry which fits in one chunk.
+ */
+#define LOG_MSG_HEXDUMP_BYTES_SINGLE_CHUNK \
+	(LOG_MSG_NARGS_SINGLE_CHUNK * sizeof(log_arg_t))
+
+/** @brief Number of bytes in the first chunk of hexdump message if message
+ *         consists of more than one chunk.
+ */
+#define LOG_MSG_HEXDUMP_BYTES_HEAD_CHUNK \
+	(LOG_MSG_HEXDUMP_BYTES_SINGLE_CHUNK - sizeof(void *))
+
+/** @brief Number of bytes that can be stored in chunks following head chunk
+ *         in hexdump log message.
+ */
+#define HEXDUMP_BYTES_CONT_MSG \
+	(sizeof(struct log_msg) - sizeof(void *))
+
+#define ARGS_CONT_MSG (HEXDUMP_BYTES_CONT_MSG / sizeof(log_arg_t))
+
+/** @brief Flag indicating standard log message. */
+#define LOG_MSG_TYPE_STD 0U
+
+/** @brief Flag indicating hexdump log message. */
+#define LOG_MSG_TYPE_HEXDUMP 1
+
+/** @brief Common part of log message header. */
+#define COMMON_PARAM_HDR() \
+	uint16_t type : 1;	   \
+	uint16_t ext : 1
+
+/** @brief Number of bits used for storing length of hexdump log message. */
+#define LOG_MSG_HEXDUMP_LENGTH_BITS 14
+
+/** @brief Maximum length of log hexdump message. */
+#define LOG_MSG_HEXDUMP_MAX_LENGTH (BIT(LOG_MSG_HEXDUMP_LENGTH_BITS) - 1)
+
+/** @brief Part of log message header identifying source and level. */
+struct log_msg_ids {
+	uint16_t level     : 3;    /*!< Severity. */
+	uint16_t domain_id : 3;    /*!< Originating domain. */
+	uint16_t source_id : 10;   /*!< Source ID. */
+};
+
+/** Part of log message header common to standard and hexdump log message. */
+struct log_msg_generic_hdr {
+	COMMON_PARAM_HDR();
+	uint16_t reserved : 14;
+};
+
+/** Part of log message header specific to standard log message. */
+struct log_msg_std_hdr {
+	COMMON_PARAM_HDR();
+	uint16_t reserved : 10;
+	uint16_t nargs    : 4;
+};
+
+/** Part of log message header specific to hexdump log message. */
+struct log_msg_hexdump_hdr {
+	COMMON_PARAM_HDR();
+	uint16_t length     : LOG_MSG_HEXDUMP_LENGTH_BITS;
+};
+
+/** Log message header structure */
+struct log_msg_hdr {
+	atomic_t ref_cnt; /*!< Reference counter for tracking message users. */
+	union log_msg_hdr_params {
+		struct log_msg_generic_hdr generic;
+		struct log_msg_std_hdr std;
+		struct log_msg_hexdump_hdr hexdump;
+		uint16_t raw;
+	} params;
+	struct log_msg_ids ids; /*!< Identification part of the message.*/
+	uint32_t timestamp;        /*!< Timestamp. */
+};
+
+/** @brief Data part of log message. */
+union log_msg_head_data {
+	log_arg_t args[LOG_MSG_NARGS_SINGLE_CHUNK];
+	uint8_t bytes[LOG_MSG_HEXDUMP_BYTES_SINGLE_CHUNK];
+};
+
+/** @brief Data part of extended log message. */
+struct log_msg_ext_head_data {
+	struct log_msg_cont *next;
+	union log_msg_ext_head_data_data {
+		log_arg_t args[LOG_MSG_NARGS_HEAD_CHUNK];
+		uint8_t bytes[LOG_MSG_HEXDUMP_BYTES_HEAD_CHUNK];
+	} data;
+};
+
+/** @brief Log message structure. */
+struct log_msg {
+	struct log_msg *next;   /*!< Used by logger core list.*/
+	struct log_msg_hdr hdr; /*!< Message header. */
+	const char *str;
+	union log_msg_data {
+		union log_msg_head_data single;
+		struct log_msg_ext_head_data ext;
+	} payload;                 /*!< Message data. */
+};
+
+/** @brief Chunks following message head when message is extended. */
+struct log_msg_cont {
+	struct log_msg_cont *next; /*!< Pointer to the next chunk. */
+	union log_msg_cont_data {
+		log_arg_t args[ARGS_CONT_MSG];
+		uint8_t bytes[HEXDUMP_BYTES_CONT_MSG];
+	} payload;
+};
+
+/** @brief Log message */
+union log_msg_chunk {
+	struct log_msg head;
+	struct log_msg_cont cont;
+};
+
+/** @brief Function for initialization of the log message pool. */
+void log_msg_pool_init(void);
+
+/** @brief Function for indicating that message is in use.
+ *
+ *  @details Message can be used (read) by multiple users. Internal reference
+ *           counter is atomically increased. See @ref log_msg_put.
+ *
+ *  @param msg Message.
+ */
+void log_msg_get(struct log_msg *msg);
+
+/** @brief Function for indicating that message is no longer in use.
+ *
+ *  @details Internal reference counter is atomically decreased. If reference
+ *           counter equals 0 message is freed.
+ *
+ *  @param msg Message.
+ */
+void log_msg_put(struct log_msg *msg);
+
+/** @brief Get domain ID of the message.
+ *
+ * @param msg Message
+ *
+ * @return Domain ID.
+ */
+static inline uint32_t log_msg_domain_id_get(struct log_msg *msg)
+{
+	return msg->hdr.ids.domain_id;
+}
+
+/** @brief Get source ID (module or instance) of the message.
+ *
+ * @param msg Message
+ *
+ * @return Source ID.
+ */
+static inline uint32_t log_msg_source_id_get(struct log_msg *msg)
+{
+	return msg->hdr.ids.source_id;
+}
+
+/** @brief Get severity level of the message.
+ *
+ * @param msg Message
+ *
+ * @return Severity message.
+ */
+static inline uint32_t log_msg_level_get(struct log_msg *msg)
+{
+	return msg->hdr.ids.level;
+}
+
+/** @brief Get timestamp of the message.
+ *
+ * @param msg Message
+ *
+ * @return Timestamp value.
+ */
+static inline uint32_t log_msg_timestamp_get(struct log_msg *msg)
+{
+	return msg->hdr.timestamp;
+}
+
+/** @brief Check if message is of standard type.
+ *
+ * @param msg Message
+ *
+ * @retval true  Standard message.
+ * @retval false Hexdump message.
+ */
+static inline bool log_msg_is_std(struct log_msg *msg)
+{
+	return  (msg->hdr.params.generic.type == LOG_MSG_TYPE_STD);
+}
+
+/** @brief Returns number of arguments in standard log message.
+ *
+ * @param msg Standard log message.
+ *
+ * @return Number of arguments.
+ */
+uint32_t log_msg_nargs_get(struct log_msg *msg);
+
+/** @brief Gets argument from standard log message.
+ *
+ * @param msg		Standard log message.
+ * @param arg_idx	Argument index.
+ *
+ * @return Argument value or 0 if arg_idx exceeds number of arguments in the
+ *	   message.
+ */
+log_arg_t log_msg_arg_get(struct log_msg *msg, uint32_t arg_idx);
+
+
+/** @brief Gets pointer to the unformatted string from standard log message.
+ *
+ * @param msg Standard log message.
+ *
+ * @return Pointer to the string.
+ */
+const char *log_msg_str_get(struct log_msg *msg);
+
+/** @brief Allocates chunks for hexdump message and copies the data.
+ *
+ *  @details Function resets header and sets following fields:
+ *		- message type
+ *		- length
+ *
+ *  @note Allocation and partial filling is combined for performance reasons.
+ *
+ * @param str		String.
+ * @param data		Data.
+ * @param length	Data length.
+ *
+ * @return Pointer to allocated head of the message or NULL
+ */
+struct log_msg *log_msg_hexdump_create(const char *str,
+				       const uint8_t *data,
+				       uint32_t length);
+
+/** @brief Put data into hexdump log message.
+ *
+ * @param[in]		msg      Message.
+ * @param[in]		data	 Data to be copied.
+ * @param[in, out]	length   Input: requested amount. Output: actual amount.
+ * @param[in]		offset   Offset.
+ */
+void log_msg_hexdump_data_put(struct log_msg *msg,
+			      uint8_t *data,
+			      size_t *length,
+			      size_t offset);
+
+/** @brief Get data from hexdump log message.
+ *
+ * @param[in]		msg      Message.
+ * @param[in]		data	 Buffer for data.
+ * @param[in, out]	length   Input: requested amount. Output: actual amount.
+ * @param[in]		offset   Offset.
+ */
+void log_msg_hexdump_data_get(struct log_msg *msg,
+			      uint8_t *data,
+			      size_t *length,
+			      size_t offset);
+
+union log_msg_chunk *log_msg_no_space_handle(void);
+
+/** @brief Allocate single chunk from the pool.
+ *
+ * @return Pointer to the allocated chunk or NULL if failed to allocate.
+ */
+union log_msg_chunk *log_msg_chunk_alloc(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_ */
Index: ModuleDemo/BLE/CM0/User/include/logging/log_output.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_output.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/logging/log_output.h	(working copy)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_H_
+#define ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_H_
+
+#include <logging/log_msg.h>
+#include <sys/util.h>
+#include <stdarg.h>
+#include <sys/atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Log output API
+ * @defgroup log_output Log output API
+ * @ingroup logger
+ * @{
+ */
+
+/** @brief Flag forcing ANSI escape code colors, red (errors), yellow
+ *         (warnings).
+ */
+#define LOG_OUTPUT_FLAG_COLORS			BIT(0)
+
+/** @brief Flag forcing timestamp */
+#define LOG_OUTPUT_FLAG_TIMESTAMP		BIT(1)
+
+/** @brief Flag forcing timestamp formatting. */
+#define LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP	BIT(2)
+
+/** @brief Flag forcing severity level prefix. */
+#define LOG_OUTPUT_FLAG_LEVEL			BIT(3)
+
+/** @brief Flag preventing the logger from adding CR and LF characters. */
+#define LOG_OUTPUT_FLAG_CRLF_NONE		BIT(4)
+
+/** @brief Flag forcing a single LF character for line breaks. */
+#define LOG_OUTPUT_FLAG_CRLF_LFONLY		BIT(5)
+
+/** @brief Flag forcing syslog format specified in RFC 5424
+ */
+#define LOG_OUTPUT_FLAG_FORMAT_SYSLOG		BIT(6)
+
+/** @brief Flag forcing syslog format specified in mipi sys-t
+ */
+#define LOG_OUTPUT_FLAG_FORMAT_SYST		BIT(7)
+
+/**
+ * @brief Prototype of the function processing output data.
+ *
+ * @param data Data.
+ * @param length Data length.
+ * @param ctx  User context.
+ *
+ * @return Number of bytes processed, dropped or discarded.
+ *
+ * @note If the log output function cannot process all of the data, it is
+ *       its responsibility to mark them as dropped or discarded by returning
+ *       the corresponding number of bytes dropped or discarded to the caller.
+ */
+typedef int (*log_output_func_t)(uint8_t *buf, size_t size, void *ctx);
+
+/* @brief Control block structure for log_output instance.  */
+struct log_output_control_block {
+	atomic_t offset;
+	void *ctx;
+	const char *hostname;
+};
+
+/** @brief Log_output instance structure. */
+struct log_output {
+	log_output_func_t func;
+	struct log_output_control_block *control_block;
+	uint8_t *buf;
+	size_t size;
+};
+
+/** @brief Create log_output instance.
+ *
+ * @param _name Instance name.
+ * @param _func Function for processing output data.
+ * @param _buf  Pointer to the output buffer.
+ * @param _size Size of the output buffer.
+ */
+#define LOG_OUTPUT_DEFINE(_name, _func, _buf, _size)			\
+	static struct log_output_control_block _name##_control_block;	\
+	static const struct log_output _name = {			\
+		.func = _func,						\
+		.control_block = &_name##_control_block,		\
+		.buf = _buf,						\
+		.size = _size,						\
+	}
+
+/** @brief Process log messages to readable strings.
+ *
+ * Function is using provided context with the buffer and output function to
+ * process formatted string and output the data.
+ *
+ * @param log_output Pointer to the log output instance.
+ * @param msg Log message.
+ * @param flags Optional flags.
+ */
+void log_output_msg_process(const struct log_output *log_output,
+			    struct log_msg *msg,
+			    uint32_t flags);
+
+/** @brief Process log string
+ *
+ * Function is formatting provided string adding optional prefixes and
+ * postfixes.
+ *
+ * @param log_output Pointer to log_output instance.
+ * @param src_level  Log source and level structure.
+ * @param timestamp  Timestamp.
+ * @param fmt        String.
+ * @param ap         String arguments.
+ * @param flags      Optional flags.
+ *
+ */
+void log_output_string(const struct log_output *log_output,
+		       struct log_msg_ids src_level, uint32_t timestamp,
+		       const char *fmt, va_list ap, uint32_t flags);
+
+/** @brief Process log hexdump
+ *
+ * Function is formatting provided hexdump adding optional prefixes and
+ * postfixes.
+ *
+ * @param log_output Pointer to log_output instance.
+ * @param src_level  Log source and level structure.
+ * @param timestamp  Timestamp.
+ * @param metadata   String.
+ * @param data       Data.
+ * @param length     Data length.
+ * @param flags      Optional flags.
+ *
+ */
+void log_output_hexdump(const struct log_output *log_output,
+			     struct log_msg_ids src_level, uint32_t timestamp,
+			     const char *metadata, const uint8_t *data,
+			     uint32_t length, uint32_t flags);
+
+/** @brief Process dropped messages indication.
+ *
+ * Function prints error message indicating lost log messages.
+ *
+ * @param log_output Pointer to the log output instance.
+ * @param cnt        Number of dropped messages.
+ */
+void log_output_dropped_process(const struct log_output *log_output, uint32_t cnt);
+
+/** @brief Flush output buffer.
+ *
+ * @param log_output Pointer to the log output instance.
+ */
+void log_output_flush(const struct log_output *log_output);
+
+/** @brief Function for setting user context passed to the output function.
+ *
+ * @param log_output	Pointer to the log output instance.
+ * @param ctx		User context.
+ */
+static inline void log_output_ctx_set(const struct log_output *log_output,
+				      void *ctx)
+{
+	log_output->control_block->ctx = ctx;
+}
+
+/** @brief Function for setting hostname of this device
+ *
+ * @param log_output	Pointer to the log output instance.
+ * @param hostname	Hostname of this device
+ */
+static inline void log_output_hostname_set(const struct log_output *log_output,
+					   const char *hostname)
+{
+	log_output->control_block->hostname = hostname;
+}
+
+/** @brief Set timestamp frequency.
+ *
+ * @param freq Frequency in Hz.
+ */
+void log_output_timestamp_freq_set(uint32_t freq);
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/mempool_heap.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/mempool_heap.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/mempool_heap.h	(working copy)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_MEMPOOL_HEAP_H_
+
+/* Compatibility implementation of a k_mem_pool backend in terms of a
+ * k_heap
+ */
+
+/* The "ID" of a k_heap-based mempool is just the tuple of the data
+ * block pointer and the heap that allocated it
+ */
+struct k_mem_block_id {
+	void *data;
+	struct k_heap *heap;
+};
+
+/* Note the data pointer gets unioned with the same value stored in
+ * the ID field to save space.
+ */
+struct k_mem_block {
+	union {
+		void *data;
+		struct k_mem_block_id id;
+	};
+};
+
+struct k_mem_pool {
+	struct k_heap *heap;
+};
+
+/* Sizing is a heuristic, as k_mem_pool made promises about layout
+ * that k_heap does not.  We make space for the number of maximum
+ * objects defined, and include extra so there's enough metadata space
+ * available for the maximum number of minimum-sized objects to be
+ * stored: 8 bytes for each desired chunk header, and a 15 word block
+ * to reserve room for a "typical" set of bucket list heads and the heap
+ * footer(this size was picked more to conform with existing test
+ * expectations than any rigorous theory -- we have tests that rely on being
+ * able to allocate the blocks promised and ones that make assumptions about
+ * when memory will run out).
+ */
+#define Z_MEM_POOL_DEFINE(name, minsz, maxsz, nmax, align)		\
+		K_HEAP_DEFINE(poolheap_##name,				\
+			      ((maxsz) * (nmax))			\
+			      + 8 * ((maxsz) * (nmax) / (minsz))	\
+			      + 15 * sizeof(void *));			\
+		struct k_mem_pool name = {				\
+			.heap = &poolheap_##name			\
+		}
+
+
+#endif /* ZEPHYR_INCLUDE_MEMPOOL_HEAP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/mempool_sys.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/mempool_sys.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/mempool_sys.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_MEMPOOL_SYS_H_
+
+#endif /* ZEPHYR_INCLUDE_MEMPOOL_SYS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/bt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/bt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/bt.h	(working copy)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Bluetooth L2 stack public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_BT_H_
+#define ZEPHYR_INCLUDE_NET_BT_H_
+
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Management part definitions */
+
+#define _NET_BT_LAYER	NET_MGMT_LAYER_L2
+#define _NET_BT_CODE	0x155
+#define _NET_BT_BASE	(NET_MGMT_IFACE_BIT |			\
+			 NET_MGMT_LAYER(_NET_BT_LAYER) |	\
+			 NET_MGMT_LAYER_CODE(_NET_BT_CODE))
+#define _NET_BT_EVENT	(_NET_BT_BASE | NET_MGMT_EVENT_BIT)
+
+enum net_request_bt_cmd {
+	NET_REQUEST_BT_CMD_ADVERTISE = 1,
+	NET_REQUEST_BT_CMD_CONNECT,
+	NET_REQUEST_BT_CMD_SCAN,
+	NET_REQUEST_BT_CMD_DISCONNECT,
+};
+
+#define NET_REQUEST_BT_ADVERTISE				\
+	(_NET_BT_BASE | NET_REQUEST_BT_CMD_ADVERTISE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_BT_ADVERTISE);
+
+#define NET_REQUEST_BT_CONNECT					\
+	(_NET_BT_BASE | NET_REQUEST_BT_CMD_CONNECT)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_BT_CONNECT);
+
+#define NET_REQUEST_BT_SCAN					\
+	(_NET_BT_BASE | NET_REQUEST_BT_CMD_SCAN)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_BT_SCAN);
+
+enum net_event_bt_cmd {
+	NET_EVENT_BT_CMD_SCAN_RESULT = 1,
+};
+
+#define NET_EVENT_BT_SCAN_RESULT				\
+	(_NET_BT_EVENT | NET_EVENT_BT_CMD_SCAN_RESULT)
+
+#define NET_REQUEST_BT_DISCONNECT				\
+	(_NET_BT_BASE | NET_REQUEST_BT_CMD_DISCONNECT)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_BT_DISCONNECT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_BT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/buf.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/buf.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/buf.h	(working copy)
@@ -0,0 +1,1982 @@
+/** @file
+ *  @brief Buffer management.
+ */
+
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_NET_BUF_H_
+#define ZEPHYR_INCLUDE_NET_BUF_H_
+
+#include <stddef.h>
+#include <types.h>
+#include <sys/util.h>
+#include <sys/slist.h>
+#include <zephyr.h>
+#include <kernel.h>
+
+#ifndef CONFIG_NET_BUF_USER_DATA_SIZE
+#define CONFIG_NET_BUF_USER_DATA_SIZE 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network buffer library
+ * @defgroup net_buf Network Buffer Library
+ * @ingroup networking
+ * @{
+ */
+
+/* Alignment needed for various parts of the buffer definition */
+#define __net_buf_align __aligned(sizeof(void *))
+
+/**
+ *  @def NET_BUF_SIMPLE_DEFINE
+ *  @brief Define a net_buf_simple stack variable.
+ *
+ *  This is a helper macro which is used to define a net_buf_simple object
+ *  on the stack.
+ *
+ *  @param _name Name of the net_buf_simple object.
+ *  @param _size Maximum data storage for the buffer.
+ */
+#define NET_BUF_SIMPLE_DEFINE(_name, _size)     \
+	uint8_t net_buf_data_##_name[_size];       \
+	struct net_buf_simple _name = {         \
+		.data   = net_buf_data_##_name, \
+		.len    = 0,                    \
+		.size   = _size,                \
+		.__buf  = net_buf_data_##_name, \
+	}
+
+/**
+ * @def NET_BUF_SIMPLE_DEFINE_STATIC
+ * @brief Define a static net_buf_simple variable.
+ *
+ * This is a helper macro which is used to define a static net_buf_simple
+ * object.
+ *
+ * @param _name Name of the net_buf_simple object.
+ * @param _size Maximum data storage for the buffer.
+ */
+#define NET_BUF_SIMPLE_DEFINE_STATIC(_name, _size)        \
+	static __noinit uint8_t net_buf_data_##_name[_size]; \
+	static struct net_buf_simple _name = {            \
+		.data   = net_buf_data_##_name,           \
+		.len    = 0,                              \
+		.size   = _size,                          \
+		.__buf  = net_buf_data_##_name,           \
+	}
+
+/**
+ * @brief Simple network buffer representation.
+ *
+ * This is a simpler variant of the net_buf object (in fact net_buf uses
+ * net_buf_simple internally). It doesn't provide any kind of reference
+ * counting, user data, dynamic allocation, or in general the ability to
+ * pass through kernel objects such as FIFOs.
+ *
+ * The main use of this is for scenarios where the meta-data of the normal
+ * net_buf isn't needed and causes too much overhead. This could be e.g.
+ * when the buffer only needs to be allocated on the stack or when the
+ * access to and lifetime of the buffer is well controlled and constrained.
+ */
+struct net_buf_simple {
+	/** Pointer to the start of data in the buffer. */
+	uint8_t *data;
+
+	/** Length of the data behind the data pointer. */
+	uint16_t len;
+
+	/** Amount of data that this buffer can store. */
+	uint16_t size;
+
+	/** Start of the data storage. Not to be accessed directly
+	 *  (the data pointer should be used instead).
+	 */
+	uint8_t *__buf;
+};
+
+/**
+ * @def NET_BUF_SIMPLE
+ * @brief Define a net_buf_simple stack variable and get a pointer to it.
+ *
+ * This is a helper macro which is used to define a net_buf_simple object on
+ * the stack and the get a pointer to it as follows:
+ *
+ * struct net_buf_simple *my_buf = NET_BUF_SIMPLE(10);
+ *
+ * After creating the object it needs to be initialized by calling
+ * net_buf_simple_init().
+ *
+ * @param _size Maximum data storage for the buffer.
+ *
+ * @return Pointer to stack-allocated net_buf_simple object.
+ */
+#define NET_BUF_SIMPLE(_size)                        \
+	((struct net_buf_simple *)(&(struct {        \
+		struct net_buf_simple buf;           \
+		uint8_t data[_size];                 \
+	}) {                                         \
+		.buf.size = _size,                   \
+	}))
+
+/**
+ * @brief Initialize a net_buf_simple object.
+ *
+ * This needs to be called after creating a net_buf_simple object using
+ * the NET_BUF_SIMPLE macro.
+ *
+ * @param buf Buffer to initialize.
+ * @param reserve_head Headroom to reserve.
+ */
+static inline void net_buf_simple_init(struct net_buf_simple *buf,
+				       size_t reserve_head)
+{
+	if (!buf->__buf) {
+		buf->__buf = (uint8_t *)buf + sizeof(*buf);
+	}
+
+	buf->data = buf->__buf + reserve_head;
+	buf->len = 0U;
+}
+
+/**
+ * @brief Initialize a net_buf_simple object with data.
+ *
+ * Initialized buffer object with external data.
+ *
+ * @param buf Buffer to initialize.
+ * @param data External data pointer
+ * @param size Amount of data the pointed data buffer if able to fit.
+ */
+void net_buf_simple_init_with_data(struct net_buf_simple *buf,
+				   void *data, size_t size);
+
+/**
+ * @brief Reset buffer
+ *
+ * Reset buffer data so it can be reused for other purposes.
+ *
+ * @param buf Buffer to reset.
+ */
+static inline void net_buf_simple_reset(struct net_buf_simple *buf)
+{
+	buf->len  = 0U;
+	buf->data = buf->__buf;
+}
+
+/**
+ * Clone buffer state, using the same data buffer.
+ *
+ * Initializes a buffer to point to the same data as an existing buffer.
+ * Allows operations on the same data without altering the length and
+ * offset of the original.
+ *
+ * @param original Buffer to clone.
+ * @param clone The new clone.
+ */
+void net_buf_simple_clone(const struct net_buf_simple *original,
+			  struct net_buf_simple *clone);
+
+/**
+ * @brief Prepare data to be added at the end of the buffer
+ *
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to increment the length with.
+ *
+ * @return The original tail of the buffer.
+ */
+void *net_buf_simple_add(struct net_buf_simple *buf, size_t len);
+
+/**
+ * @brief Copy given number of bytes from memory to the end of the buffer
+ *
+ * Increments the data length of the  buffer to account for more data at the
+ * end.
+ *
+ * @param buf Buffer to update.
+ * @param mem Location of data to be added.
+ * @param len Length of data to be added
+ *
+ * @return The original tail of the buffer.
+ */
+void *net_buf_simple_add_mem(struct net_buf_simple *buf, const void *mem,
+			     size_t len);
+
+/**
+ * @brief Add (8-bit) byte at the end of the buffer
+ *
+ * Increments the data length of the  buffer to account for more data at the
+ * end.
+ *
+ * @param buf Buffer to update.
+ * @param val byte value to be added.
+ *
+ * @return Pointer to the value added
+ */
+uint8_t *net_buf_simple_add_u8(struct net_buf_simple *buf, uint8_t val);
+
+/**
+ * @brief Add 16-bit value at the end of the buffer
+ *
+ * Adds 16-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be added.
+ */
+void net_buf_simple_add_le16(struct net_buf_simple *buf, uint16_t val);
+
+/**
+ * @brief Add 16-bit value at the end of the buffer
+ *
+ * Adds 16-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be added.
+ */
+void net_buf_simple_add_be16(struct net_buf_simple *buf, uint16_t val);
+
+/**
+ * @brief Add 24-bit value at the end of the buffer
+ *
+ * Adds 24-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be added.
+ */
+void net_buf_simple_add_le24(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Add 24-bit value at the end of the buffer
+ *
+ * Adds 24-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be added.
+ */
+void net_buf_simple_add_be24(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Add 32-bit value at the end of the buffer
+ *
+ * Adds 32-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be added.
+ */
+void net_buf_simple_add_le32(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Add 32-bit value at the end of the buffer
+ *
+ * Adds 32-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be added.
+ */
+void net_buf_simple_add_be32(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Add 48-bit value at the end of the buffer
+ *
+ * Adds 48-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be added.
+ */
+void net_buf_simple_add_le48(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Add 48-bit value at the end of the buffer
+ *
+ * Adds 48-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be added.
+ */
+void net_buf_simple_add_be48(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Add 64-bit value at the end of the buffer
+ *
+ * Adds 64-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be added.
+ */
+void net_buf_simple_add_le64(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Add 64-bit value at the end of the buffer
+ *
+ * Adds 64-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be added.
+ */
+void net_buf_simple_add_be64(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Push data to the beginning of the buffer.
+ *
+ * Modifies the data pointer and buffer length to account for more data
+ * in the beginning of the buffer.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to add to the beginning.
+ *
+ * @return The new beginning of the buffer data.
+ */
+void *net_buf_simple_push(struct net_buf_simple *buf, size_t len);
+
+/**
+ * @brief Push 16-bit value to the beginning of the buffer
+ *
+ * Adds 16-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_le16(struct net_buf_simple *buf, uint16_t val);
+
+/**
+ * @brief Push 16-bit value to the beginning of the buffer
+ *
+ * Adds 16-bit value in big endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_be16(struct net_buf_simple *buf, uint16_t val);
+
+/**
+ * @brief Push 8-bit value to the beginning of the buffer
+ *
+ * Adds 8-bit value the beginning of the buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 8-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_u8(struct net_buf_simple *buf, uint8_t val);
+
+/**
+ * @brief Push 24-bit value to the beginning of the buffer
+ *
+ * Adds 24-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_le24(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Push 24-bit value to the beginning of the buffer
+ *
+ * Adds 24-bit value in big endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_be24(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Push 32-bit value to the beginning of the buffer
+ *
+ * Adds 32-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_le32(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Push 32-bit value to the beginning of the buffer
+ *
+ * Adds 32-bit value in big endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_be32(struct net_buf_simple *buf, uint32_t val);
+
+/**
+ * @brief Push 48-bit value to the beginning of the buffer
+ *
+ * Adds 48-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_le48(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Push 48-bit value to the beginning of the buffer
+ *
+ * Adds 48-bit value in big endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_be48(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Push 64-bit value to the beginning of the buffer
+ *
+ * Adds 64-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_le64(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Push 64-bit value to the beginning of the buffer
+ *
+ * Adds 64-bit value in big endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be pushed to the buffer.
+ */
+void net_buf_simple_push_be64(struct net_buf_simple *buf, uint64_t val);
+
+/**
+ * @brief Remove data from the beginning of the buffer.
+ *
+ * Removes data from the beginning of the buffer by modifying the data
+ * pointer and buffer length.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to remove.
+ *
+ * @return New beginning of the buffer data.
+ */
+void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len);
+
+/**
+ * @brief Remove data from the beginning of the buffer.
+ *
+ * Removes data from the beginning of the buffer by modifying the data
+ * pointer and buffer length.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to remove.
+ *
+ * @return Pointer to the old location of the buffer data.
+ */
+void *net_buf_simple_pull_mem(struct net_buf_simple *buf, size_t len);
+
+/**
+ * @brief Remove a 8-bit value from the beginning of the buffer
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 8-bit values.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return The 8-bit removed value
+ */
+uint8_t net_buf_simple_pull_u8(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 16 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 16-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 16-bit value converted from little endian to host endian.
+ */
+uint16_t net_buf_simple_pull_le16(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 16 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 16-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 16-bit value converted from big endian to host endian.
+ */
+uint16_t net_buf_simple_pull_be16(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 24 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 24-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 24-bit value converted from little endian to host endian.
+ */
+uint32_t net_buf_simple_pull_le24(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 24 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 24-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 24-bit value converted from big endian to host endian.
+ */
+uint32_t net_buf_simple_pull_be24(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 32 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 32-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 32-bit value converted from little endian to host endian.
+ */
+uint32_t net_buf_simple_pull_le32(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 32 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 32-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 32-bit value converted from big endian to host endian.
+ */
+uint32_t net_buf_simple_pull_be32(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 48 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 48-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 48-bit value converted from little endian to host endian.
+ */
+uint64_t net_buf_simple_pull_le48(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 48 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 48-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 48-bit value converted from big endian to host endian.
+ */
+uint64_t net_buf_simple_pull_be48(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 64 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 64-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 64-bit value converted from little endian to host endian.
+ */
+uint64_t net_buf_simple_pull_le64(struct net_buf_simple *buf);
+
+/**
+ * @brief Remove and convert 64 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_simple_pull(), but a helper for operating
+ * on 64-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 64-bit value converted from big endian to host endian.
+ */
+uint64_t net_buf_simple_pull_be64(struct net_buf_simple *buf);
+
+/**
+ * @brief Get the tail pointer for a buffer.
+ *
+ * Get a pointer to the end of the data in a buffer.
+ *
+ * @param buf Buffer.
+ *
+ * @return Tail pointer for the buffer.
+ */
+static inline uint8_t *net_buf_simple_tail(struct net_buf_simple *buf)
+{
+	return buf->data + buf->len;
+}
+
+/**
+ * @brief Check buffer headroom.
+ *
+ * Check how much free space there is in the beginning of the buffer.
+ *
+ * buf A valid pointer on a buffer
+ *
+ * @return Number of bytes available in the beginning of the buffer.
+ */
+size_t net_buf_simple_headroom(struct net_buf_simple *buf);
+
+/**
+ * @brief Check buffer tailroom.
+ *
+ * Check how much free space there is at the end of the buffer.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return Number of bytes available at the end of the buffer.
+ */
+size_t net_buf_simple_tailroom(struct net_buf_simple *buf);
+
+/**
+ * @brief Parsing state of a buffer.
+ *
+ * This is used for temporarily storing the parsing state of a buffer
+ * while giving control of the parsing to a routine which we don't
+ * control.
+ */
+struct net_buf_simple_state {
+	/** Offset of the data pointer from the beginning of the storage */
+	uint16_t offset;
+	/** Length of data */
+	uint16_t len;
+};
+
+/**
+ * @brief Save the parsing state of a buffer.
+ *
+ * Saves the parsing state of a buffer so it can be restored later.
+ *
+ * @param buf Buffer from which the state should be saved.
+ * @param state Storage for the state.
+ */
+static inline void net_buf_simple_save(struct net_buf_simple *buf,
+				       struct net_buf_simple_state *state)
+{
+	state->offset = net_buf_simple_headroom(buf);
+	state->len = buf->len;
+}
+
+/**
+ * @brief Restore the parsing state of a buffer.
+ *
+ * Restores the parsing state of a buffer from a state previously stored
+ * by net_buf_simple_save().
+ *
+ * @param buf Buffer to which the state should be restored.
+ * @param state Stored state.
+ */
+static inline void net_buf_simple_restore(struct net_buf_simple *buf,
+					  struct net_buf_simple_state *state)
+{
+	buf->data = buf->__buf + state->offset;
+	buf->len = state->len;
+}
+
+/**
+ * Flag indicating that the buffer has associated fragments. Only used
+ * internally by the buffer handling code while the buffer is inside a
+ * FIFO, meaning this never needs to be explicitly set or unset by the
+ * net_buf API user. As long as the buffer is outside of a FIFO, i.e.
+ * in practice always for the user for this API, the buf->frags pointer
+ * should be used instead.
+ */
+#define NET_BUF_FRAGS        BIT(0)
+/**
+ * Flag indicating that the buffer's associated data pointer, points to
+ * externally allocated memory. Therefore once ref goes down to zero, the
+ * pointed data will not need to be deallocated. This never needs to be
+ * explicitly set or unet by the net_buf API user. Such net_buf is
+ * exclusively instantiated via net_buf_alloc_with_data() function.
+ * Reference count mechanism however will behave the same way, and ref
+ * count going to 0 will free the net_buf but no the data pointer in it.
+ */
+#define NET_BUF_EXTERNAL_DATA  BIT(1)
+
+/**
+ * @brief Network buffer representation.
+ *
+ * This struct is used to represent network buffers. Such buffers are
+ * normally defined through the NET_BUF_POOL_*_DEFINE() APIs and allocated
+ * using the net_buf_alloc() API.
+ */
+struct net_buf {
+	union {
+		/** Allow placing the buffer into sys_slist_t */
+		sys_snode_t node;
+
+		/** Fragments associated with this buffer. */
+		struct net_buf *frags;
+	};
+
+	/** Reference count. */
+	uint8_t ref;
+
+	/** Bit-field of buffer flags. */
+	uint8_t flags;
+
+	/** Where the buffer should go when freed up. */
+	struct net_buf_pool *pool_id;
+
+	/* Union for convenience access to the net_buf_simple members, also
+	 * preserving the old API.
+	 */
+	union {
+		/* The ABI of this struct must match net_buf_simple */
+		struct {
+			/** Pointer to the start of data in the buffer. */
+			uint8_t *data;
+
+			/** Length of the data behind the data pointer. */
+			uint16_t len;
+
+			/** Amount of data that this buffer can store. */
+			uint16_t size;
+
+			/** Start of the data storage. Not to be accessed
+			 *  directly (the data pointer should be used
+			 *  instead).
+			 */
+			uint8_t *__buf;
+		};
+
+		struct net_buf_simple b;
+	};
+
+	/** System metadata for this buffer. */
+	uint8_t user_data[CONFIG_NET_BUF_USER_DATA_SIZE];// __net_buf_align ;
+};
+
+struct net_buf_data_cb {
+	uint8_t * (*alloc)(struct net_buf *buf, size_t *size,
+			   k_timeout_t timeout);
+	uint8_t * (*ref)(struct net_buf *buf, uint8_t *data);
+	void   (*unref)(struct net_buf *buf, uint8_t *data);
+};
+
+struct net_buf_data_alloc {
+	const struct net_buf_data_cb *cb;
+	void *alloc_data;
+};
+
+/**
+ * @brief Network buffer pool representation.
+ *
+ * This struct is used to represent a pool of network buffers.
+ */
+struct net_buf_pool {
+	/** LIFO to place the buffer into when free */
+	struct k_lifo free;
+
+	/** Number of buffers in pool */
+	const uint16_t buf_count;
+
+	/** Number of uninitialized buffers */
+	uint16_t uninit_count;
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	/** Amount of available buffers in the pool. */
+	int16_t avail_count;
+
+	/** Total size of the pool. */
+	const uint16_t pool_size;
+
+	/** Name of the pool. Used when printing pool information. */
+	const char *name;
+#endif /* CONFIG_NET_BUF_POOL_USAGE */
+
+	/** Optional destroy callback when buffer is freed. */
+	void (*const destroy)(struct net_buf *buf);
+
+	/** Data allocation handlers. */
+	const struct net_buf_data_alloc *alloc;
+
+	/** Start of buffer storage array */
+	struct net_buf * const __bufs;
+};
+
+/** @cond INTERNAL_HIDDEN */
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+#define NET_BUF_POOL_INITIALIZER(_pool, _alloc, _bufs, _count, _destroy) \
+	{                                                                    \
+		.free = Z_LIFO_INITIALIZER(_pool.free),                      \
+		.buf_count = _count,                                         \
+		.uninit_count = _count,                                      \
+		.avail_count = _count,                                       \
+		.name = STRINGIFY(_pool),                                    \
+		.destroy = _destroy,                                         \
+		.alloc = _alloc,                                             \
+		.__bufs = _bufs,                                             \
+	}
+#else
+#define NET_BUF_POOL_INITIALIZER(_pool, _alloc, _bufs, _count, _destroy)     \
+	{                                                                    \
+		.free = Z_LIFO_INITIALIZER(_pool.free),                      \
+		.buf_count = _count,                                         \
+		.uninit_count = _count,                                      \
+		.destroy = _destroy,                                         \
+		.alloc = _alloc,                                             \
+		.__bufs = _bufs,                                             \
+	}
+#endif /* CONFIG_NET_BUF_POOL_USAGE */
+
+extern const struct net_buf_data_alloc net_buf_heap_alloc;
+/** @endcond */
+
+/**
+ * @def NET_BUF_POOL_HEAP_DEFINE
+ * @brief Define a new pool for buffers using the heap for the data.
+ *
+ * Defines a net_buf_pool struct and the necessary memory storage (array of
+ * structs) for the needed amount of buffers. After this, the buffers can be
+ * accessed from the pool through net_buf_alloc. The pool is defined as a
+ * static variable, so if it needs to be exported outside the current module
+ * this needs to happen with the help of a separate pointer rather than an
+ * extern declaration.
+ *
+ * The data payload of the buffers will be allocated from the heap using
+ * k_malloc, so CONFIG_HEAP_MEM_POOL_SIZE must be set to a positive value.
+ * This kind of pool does not support blocking on the data allocation, so
+ * the timeout passed to net_buf_alloc will be always treated as K_NO_WAIT
+ * when trying to allocate the data. This means that allocation failures,
+ * i.e. NULL returns, must always be handled cleanly.
+ *
+ * If provided with a custom destroy callback, this callback is
+ * responsible for eventually calling net_buf_destroy() to complete the
+ * process of returning the buffer to the pool.
+ *
+ * @param _name      Name of the pool variable.
+ * @param _count     Number of buffers in the pool.
+ * @param _destroy   Optional destroy callback when buffer is freed.
+ */
+#define NET_BUF_POOL_HEAP_DEFINE(_name, _count, _destroy)                     \
+	static struct net_buf net_buf_##_name[_count] __noinit;               \
+	static struct net_buf_pool _name __net_buf_align                      \
+			__in_section(_net_buf_pool, static, _name) =          \
+		NET_BUF_POOL_INITIALIZER(_name, &net_buf_heap_alloc,          \
+					 net_buf_##_name, _count, _destroy)
+
+struct net_buf_pool_fixed {
+	size_t data_size;
+	uint8_t *data_pool;
+};
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct net_buf_data_cb net_buf_fixed_cb;
+/** @endcond */
+
+/**
+ * @def NET_BUF_POOL_FIXED_DEFINE
+ * @brief Define a new pool for buffers based on fixed-size data
+ *
+ * Defines a net_buf_pool struct and the necessary memory storage (array of
+ * structs) for the needed amount of buffers. After this, the buffers can be
+ * accessed from the pool through net_buf_alloc. The pool is defined as a
+ * static variable, so if it needs to be exported outside the current module
+ * this needs to happen with the help of a separate pointer rather than an
+ * extern declaration.
+ *
+ * The data payload of the buffers will be allocated from a byte array
+ * of fixed sized chunks. This kind of pool does not support blocking on
+ * the data allocation, so the timeout passed to net_buf_alloc will be
+ * always treated as K_NO_WAIT when trying to allocate the data. This means
+ * that allocation failures, i.e. NULL returns, must always be handled
+ * cleanly.
+ *
+ * If provided with a custom destroy callback, this callback is
+ * responsible for eventually calling net_buf_destroy() to complete the
+ * process of returning the buffer to the pool.
+ *
+ * @param _name      Name of the pool variable.
+ * @param _count     Number of buffers in the pool.
+ * @param _data_size Maximum data payload per buffer.
+ * @param _destroy   Optional destroy callback when buffer is freed.
+ */
+#define NET_BUF_POOL_FIXED_DEFINE(_name, _count, _data_size, _destroy)        \
+	static struct net_buf net_buf_##_name[_count];               \
+	static uint8_t net_buf_data_##_name[_count][_data_size];     \
+	static const struct net_buf_pool_fixed net_buf_fixed_##_name = {      \
+		.data_size = _data_size,                                      \
+		.data_pool = (uint8_t *)net_buf_data_##_name,                 \
+	};                                                                    \
+	static const struct net_buf_data_alloc net_buf_fixed_alloc_##_name = {\
+		.cb = &net_buf_fixed_cb,                                      \
+		.alloc_data = (void *)&net_buf_fixed_##_name,                 \
+	};                                                                    \
+	static struct net_buf_pool _name __net_buf_align =                     \
+		NET_BUF_POOL_INITIALIZER(_name, &net_buf_fixed_alloc_##_name, \
+					 net_buf_##_name, _count, _destroy)
+
+/** @cond INTERNAL_HIDDEN */
+extern const struct net_buf_data_cb net_buf_var_cb;
+/** @endcond */
+
+/**
+ * @def NET_BUF_POOL_VAR_DEFINE
+ * @brief Define a new pool for buffers with variable size payloads
+ *
+ * Defines a net_buf_pool struct and the necessary memory storage (array of
+ * structs) for the needed amount of buffers. After this, the buffers can be
+ * accessed from the pool through net_buf_alloc. The pool is defined as a
+ * static variable, so if it needs to be exported outside the current module
+ * this needs to happen with the help of a separate pointer rather than an
+ * extern declaration.
+ *
+ * The data payload of the buffers will be based on a memory pool from which
+ * variable size payloads may be allocated.
+ *
+ * If provided with a custom destroy callback, this callback is
+ * responsible for eventually calling net_buf_destroy() to complete the
+ * process of returning the buffer to the pool.
+ *
+ * @param _name      Name of the pool variable.
+ * @param _count     Number of buffers in the pool.
+ * @param _data_size Total amount of memory available for data payloads.
+ * @param _destroy   Optional destroy callback when buffer is freed.
+ */
+#define NET_BUF_POOL_VAR_DEFINE(_name, _count, _data_size, _destroy)          \
+	static struct net_buf _net_buf_##_name[_count] __noinit;              \
+	K_MEM_POOL_DEFINE(net_buf_mem_pool_##_name, 16, _data_size, 1, 4);    \
+	static const struct net_buf_data_alloc net_buf_data_alloc_##_name = { \
+		.cb = &net_buf_var_cb,                                        \
+		.alloc_data = &net_buf_mem_pool_##_name,                      \
+	};                                                                    \
+	static struct net_buf_pool _name __net_buf_align                      \
+			__in_section(_net_buf_pool, static, _name) =          \
+		NET_BUF_POOL_INITIALIZER(_name, &net_buf_data_alloc_##_name,  \
+					 _net_buf_##_name, _count, _destroy)
+
+/**
+ * @def NET_BUF_POOL_DEFINE
+ * @brief Define a new pool for buffers
+ *
+ * Defines a net_buf_pool struct and the necessary memory storage (array of
+ * structs) for the needed amount of buffers. After this,the buffers can be
+ * accessed from the pool through net_buf_alloc. The pool is defined as a
+ * static variable, so if it needs to be exported outside the current module
+ * this needs to happen with the help of a separate pointer rather than an
+ * extern declaration.
+ *
+ * If provided with a custom destroy callback this callback is
+ * responsible for eventually calling net_buf_destroy() to complete the
+ * process of returning the buffer to the pool.
+ *
+ * @param _name     Name of the pool variable.
+ * @param _count    Number of buffers in the pool.
+ * @param _size     Maximum data size for each buffer.
+ * @param _ud_size  Amount of user data space to reserve.
+ * @param _destroy  Optional destroy callback when buffer is freed.
+ */
+//#define NET_BUF_POOL_DEFINE(_name, _count, _size, _ud_size, _destroy)        \
+//	BUILD_ASSERT(_ud_size <= CONFIG_NET_BUF_USER_DATA_SIZE);             \
+//	NET_BUF_POOL_FIXED_DEFINE(_name, _count, _size, _destroy)
+#define NET_BUF_POOL_DEFINE(_name, _count, _size, _ud_size, _destroy)        \
+	NET_BUF_POOL_FIXED_DEFINE(_name, _count, _size, _destroy)
+
+/**
+ * @brief Looks up a pool based on its ID.
+ *
+ * @param id Pool ID (e.g. from buf->pool_id).
+ *
+ * @return Pointer to pool.
+ */
+struct net_buf_pool *net_buf_pool_get(int id);
+
+/**
+ * @brief Get a zero-based index for a buffer.
+ *
+ * This function will translate a buffer into a zero-based index,
+ * based on its placement in its buffer pool. This can be useful if you
+ * want to associate an external array of meta-data contexts with the
+ * buffers of a pool.
+ *
+ * @param buf  Network buffer.
+ *
+ * @return Zero-based index for the buffer.
+ */
+int net_buf_id(struct net_buf *buf);
+
+/**
+ * @brief Allocate a new fixed buffer from a pool.
+ *
+ * @param pool Which pool to allocate the buffer from.
+ * @param timeout Affects the action taken should the pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait until the specified
+ *        timeout. Note that some types of data allocators do not support
+ *        blocking (such as the HEAP type). In this case it's still possible
+ *        for net_buf_alloc() to fail (return NULL) even if it was given
+ *        K_FOREVER.
+ *
+ * @return New buffer or NULL if out of buffers.
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool,
+					  k_timeout_t timeout, const char *func,
+					  int line);
+#define net_buf_alloc_fixed(_pool, _timeout) \
+	net_buf_alloc_fixed_debug(_pool, _timeout, __func__, __LINE__)
+#else
+struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool,
+				    k_timeout_t timeout);
+#endif
+
+/**
+ * @def net_buf_alloc
+ *
+ * @copydetails net_buf_alloc_fixed
+ */
+#define net_buf_alloc(pool, timeout) net_buf_alloc_fixed(pool, timeout)
+
+/**
+ * @brief Allocate a new variable length buffer from a pool.
+ *
+ * @param pool Which pool to allocate the buffer from.
+ * @param size Amount of data the buffer must be able to fit.
+ * @param timeout Affects the action taken should the pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait until the specified
+ *        timeout. Note that some types of data allocators do not support
+ *        blocking (such as the HEAP type). In this case it's still possible
+ *        for net_buf_alloc() to fail (return NULL) even if it was given
+ *        K_FOREVER.
+ *
+ * @return New buffer or NULL if out of buffers.
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_len_debug(struct net_buf_pool *pool, size_t size,
+					k_timeout_t timeout, const char *func,
+					int line);
+#define net_buf_alloc_len(_pool, _size, _timeout) \
+	net_buf_alloc_len_debug(_pool, _size, _timeout, __func__, __LINE__)
+#else
+struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size,
+				  k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate a new buffer from a pool but with external data pointer.
+ *
+ * Allocate a new buffer from a pool, where the data pointer comes from the
+ * user and not from the pool.
+ *
+ * @param pool Which pool to allocate the buffer from.
+ * @param data External data pointer
+ * @param size Amount of data the pointed data buffer if able to fit.
+ * @param timeout Affects the action taken should the pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait until the specified
+ *        timeout. Note that some types of data allocators do not support
+ *        blocking (such as the HEAP type). In this case it's still possible
+ *        for net_buf_alloc() to fail (return NULL) even if it was given
+ *        K_FOREVER.
+ *
+ * @return New buffer or NULL if out of buffers.
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_with_data_debug(struct net_buf_pool *pool,
+					      void *data, size_t size,
+					      k_timeout_t timeout,
+					      const char *func, int line);
+#define net_buf_alloc_with_data(_pool, _data_, _size, _timeout)		\
+	net_buf_alloc_with_data_debug(_pool, _data_, _size, _timeout,	\
+				      __func__, __LINE__)
+#else
+struct net_buf *net_buf_alloc_with_data(struct net_buf_pool *pool,
+					void *data, size_t size,
+					k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Get a buffer from a FIFO.
+ *
+ * @param fifo Which FIFO to take the buffer from.
+ * @param timeout Affects the action taken should the FIFO be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as
+ *        long as necessary. Otherwise, wait until the specified timeout.
+ *
+ * @return New buffer or NULL if the FIFO is empty.
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_get_debug(struct k_fifo *fifo, k_timeout_t timeout,
+				  const char *func, int line);
+#define	net_buf_get(_fifo, _timeout) \
+	net_buf_get_debug(_fifo, _timeout, __func__, __LINE__)
+#else
+struct net_buf *net_buf_get(struct k_fifo *fifo, k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Destroy buffer from custom destroy callback
+ *
+ * This helper is only intended to be used from custom destroy callbacks.
+ * If no custom destroy callback is given to NET_BUF_POOL_*_DEFINE() then
+ * there is no need to use this API.
+ *
+ * @param buf Buffer to destroy.
+ */
+static inline void net_buf_destroy(struct net_buf *buf)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	k_lifo_put(&pool->free, buf);
+}
+
+/**
+ * @brief Reset buffer
+ *
+ * Reset buffer data and flags so it can be reused for other purposes.
+ *
+ * @param buf Buffer to reset.
+ */
+void net_buf_reset(struct net_buf *buf);
+
+/**
+ * @brief Initialize buffer with the given headroom.
+ *
+ * The buffer is not expected to contain any data when this API is called.
+ *
+ * @param buf Buffer to initialize.
+ * @param reserve How much headroom to reserve.
+ */
+void net_buf_simple_reserve(struct net_buf_simple *buf, size_t reserve);
+
+/**
+ * @brief Put a buffer into a list
+ *
+ * If the buffer contains follow-up fragments this function will take care of
+ * inserting them as well into the list.
+ *
+ * @param list Which list to append the buffer to.
+ * @param buf Buffer.
+ */
+void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf);
+
+/**
+ * @brief Get a buffer from a list.
+ *
+ * If the buffer had any fragments, these will automatically be recovered from
+ * the list as well and be placed to the buffer's fragment list.
+ *
+ * @param list Which list to take the buffer from.
+ *
+ * @return New buffer or NULL if the FIFO is empty.
+ */
+struct net_buf *net_buf_slist_get(sys_slist_t *list);
+
+/**
+ * @brief Put a buffer to the end of a FIFO.
+ *
+ * If the buffer contains follow-up fragments this function will take care of
+ * inserting them as well into the FIFO.
+ *
+ * @param fifo Which FIFO to put the buffer to.
+ * @param buf Buffer.
+ */
+void net_buf_put(struct k_fifo *fifo, struct net_buf *buf);
+
+/**
+ * @brief Decrements the reference count of a buffer.
+ *
+ * The buffer is put back into the pool if the reference count reaches zero.
+ *
+ * @param buf A valid pointer on a buffer
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+void net_buf_unref_debug(struct net_buf *buf, const char *func, int line);
+#define	net_buf_unref(_buf) \
+	net_buf_unref_debug(_buf, __func__, __LINE__)
+#else
+void net_buf_unref(struct net_buf *buf);
+#endif
+
+/**
+ * @brief Increment the reference count of a buffer.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return the buffer newly referenced
+ */
+struct net_buf *net_buf_ref(struct net_buf *buf);
+
+/**
+ * @brief Clone buffer
+ *
+ * Duplicate given buffer including any data and headers currently stored.
+ *
+ * @param buf A valid pointer on a buffer
+ * @param timeout Affects the action taken should the pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait until the specified
+ *        timeout.
+ *
+ * @return Cloned buffer or NULL if out of buffers.
+ */
+struct net_buf *net_buf_clone(struct net_buf *buf, k_timeout_t timeout);
+
+/**
+ * @brief Get a pointer to the user data of a buffer.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return Pointer to the user data of the buffer.
+ */
+static inline void *net_buf_user_data(const struct net_buf *buf)
+{
+	return (void *)buf->user_data;
+}
+
+/**
+ * @def net_buf_reserve
+ * @brief Initialize buffer with the given headroom.
+ *
+ * The buffer is not expected to contain any data when this API is called.
+ *
+ * @param buf Buffer to initialize.
+ * @param reserve How much headroom to reserve.
+ */
+#define net_buf_reserve(buf, reserve) net_buf_simple_reserve(&(buf)->b, \
+							     reserve)
+
+/**
+ * @def net_buf_add
+ * @brief Prepare data to be added at the end of the buffer
+ *
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to increment the length with.
+ *
+ * @return The original tail of the buffer.
+ */
+#define net_buf_add(buf, len) net_buf_simple_add(&(buf)->b, len)
+
+/**
+ * @def net_buf_add_mem
+ * @brief Copies the given number of bytes to the end of the buffer
+ *
+ * Increments the data length of the  buffer to account for more data at
+ * the end.
+ *
+ * @param buf Buffer to update.
+ * @param mem Location of data to be added.
+ * @param len Length of data to be added
+ *
+ * @return The original tail of the buffer.
+ */
+#define net_buf_add_mem(buf, mem, len) net_buf_simple_add_mem(&(buf)->b, \
+							      mem, len)
+
+/**
+ * @def net_buf_add_u8
+ * @brief Add (8-bit) byte at the end of the buffer
+ *
+ * Increments the data length of the  buffer to account for more data at
+ * the end.
+ *
+ * @param buf Buffer to update.
+ * @param val byte value to be added.
+ *
+ * @return Pointer to the value added
+ */
+#define net_buf_add_u8(buf, val) net_buf_simple_add_u8(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_le16
+ * @brief Add 16-bit value at the end of the buffer
+ *
+ * Adds 16-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be added.
+ */
+#define net_buf_add_le16(buf, val) net_buf_simple_add_le16(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_be16
+ * @brief Add 16-bit value at the end of the buffer
+ *
+ * Adds 16-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be added.
+ */
+#define net_buf_add_be16(buf, val) net_buf_simple_add_be16(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_le24
+ * @brief Add 24-bit value at the end of the buffer
+ *
+ * Adds 24-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be added.
+ */
+#define net_buf_add_le24(buf, val) net_buf_simple_add_le24(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_be24
+ * @brief Add 24-bit value at the end of the buffer
+ *
+ * Adds 24-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be added.
+ */
+#define net_buf_add_be24(buf, val) net_buf_simple_add_be24(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_le32
+ * @brief Add 32-bit value at the end of the buffer
+ *
+ * Adds 32-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be added.
+ */
+#define net_buf_add_le32(buf, val) net_buf_simple_add_le32(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_be32
+ * @brief Add 32-bit value at the end of the buffer
+ *
+ * Adds 32-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be added.
+ */
+#define net_buf_add_be32(buf, val) net_buf_simple_add_be32(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_le48
+ * @brief Add 48-bit value at the end of the buffer
+ *
+ * Adds 48-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be added.
+ */
+#define net_buf_add_le48(buf, val) net_buf_simple_add_le48(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_be48
+ * @brief Add 48-bit value at the end of the buffer
+ *
+ * Adds 48-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be added.
+ */
+#define net_buf_add_be48(buf, val) net_buf_simple_add_be48(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_le64
+ * @brief Add 64-bit value at the end of the buffer
+ *
+ * Adds 64-bit value in little endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be added.
+ */
+#define net_buf_add_le64(buf, val) net_buf_simple_add_le64(&(buf)->b, val)
+
+/**
+ * @def net_buf_add_be64
+ * @brief Add 64-bit value at the end of the buffer
+ *
+ * Adds 64-bit value in big endian format at the end of buffer.
+ * Increments the data length of a buffer to account for more data
+ * at the end.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be added.
+ */
+#define net_buf_add_be64(buf, val) net_buf_simple_add_be64(&(buf)->b, val)
+
+/**
+ * @def net_buf_push
+ * @brief Push data to the beginning of the buffer.
+ *
+ * Modifies the data pointer and buffer length to account for more data
+ * in the beginning of the buffer.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to add to the beginning.
+ *
+ * @return The new beginning of the buffer data.
+ */
+#define net_buf_push(buf, len) net_buf_simple_push(&(buf)->b, len)
+
+/**
+ * @def net_buf_push_le16
+ * @brief Push 16-bit value to the beginning of the buffer
+ *
+ * Adds 16-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_le16(buf, val) net_buf_simple_push_le16(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_be16
+ * @brief Push 16-bit value to the beginning of the buffer
+ *
+ * Adds 16-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 16-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_be16(buf, val) net_buf_simple_push_be16(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_u8
+ * @brief Push 8-bit value to the beginning of the buffer
+ *
+ * Adds 8-bit value the beginning of the buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 8-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_u8(buf, val) net_buf_simple_push_u8(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_le24
+ * @brief Push 24-bit value to the beginning of the buffer
+ *
+ * Adds 24-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_le24(buf, val) net_buf_simple_push_le24(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_be24
+ * @brief Push 24-bit value to the beginning of the buffer
+ *
+ * Adds 24-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 24-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_be24(buf, val) net_buf_simple_push_be24(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_le32
+ * @brief Push 32-bit value to the beginning of the buffer
+ *
+ * Adds 32-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_le32(buf, val) net_buf_simple_push_le32(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_be32
+ * @brief Push 32-bit value to the beginning of the buffer
+ *
+ * Adds 32-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 32-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_be32(buf, val) net_buf_simple_push_be32(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_le48
+ * @brief Push 48-bit value to the beginning of the buffer
+ *
+ * Adds 48-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_le48(buf, val) net_buf_simple_push_le48(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_be48
+ * @brief Push 48-bit value to the beginning of the buffer
+ *
+ * Adds 48-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 48-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_be48(buf, val) net_buf_simple_push_be48(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_le64
+ * @brief Push 64-bit value to the beginning of the buffer
+ *
+ * Adds 64-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_le64(buf, val) net_buf_simple_push_le64(&(buf)->b, val)
+
+/**
+ * @def net_buf_push_be64
+ * @brief Push 64-bit value to the beginning of the buffer
+ *
+ * Adds 64-bit value in little endian format to the beginning of the
+ * buffer.
+ *
+ * @param buf Buffer to update.
+ * @param val 64-bit value to be pushed to the buffer.
+ */
+#define net_buf_push_be64(buf, val) net_buf_simple_push_be64(&(buf)->b, val)
+
+/**
+ * @def net_buf_pull
+ * @brief Remove data from the beginning of the buffer.
+ *
+ * Removes data from the beginning of the buffer by modifying the data
+ * pointer and buffer length.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to remove.
+ *
+ * @return New beginning of the buffer data.
+ */
+#define net_buf_pull(buf, len) net_buf_simple_pull(&(buf)->b, len)
+
+/**
+ * @def net_buf_pull_mem
+ * @brief Remove data from the beginning of the buffer.
+ *
+ * Removes data from the beginning of the buffer by modifying the data
+ * pointer and buffer length.
+ *
+ * @param buf Buffer to update.
+ * @param len Number of bytes to remove.
+ *
+ * @return Pointer to the old beginning of the buffer data.
+ */
+#define net_buf_pull_mem(buf, len) net_buf_simple_pull_mem(&(buf)->b, len)
+
+/**
+ * @def net_buf_pull_u8
+ * @brief Remove a 8-bit value from the beginning of the buffer
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 8-bit values.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return The 8-bit removed value
+ */
+#define net_buf_pull_u8(buf) net_buf_simple_pull_u8(&(buf)->b)
+
+/**
+ * @def net_buf_pull_le16
+ * @brief Remove and convert 16 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 16-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 16-bit value converted from little endian to host endian.
+ */
+#define net_buf_pull_le16(buf) net_buf_simple_pull_le16(&(buf)->b)
+
+/**
+ * @def net_buf_pull_be16
+ * @brief Remove and convert 16 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 16-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 16-bit value converted from big endian to host endian.
+ */
+#define net_buf_pull_be16(buf) net_buf_simple_pull_be16(&(buf)->b)
+
+/**
+ * @def net_buf_pull_le24
+ * @brief Remove and convert 24 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 24-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 24-bit value converted from little endian to host endian.
+ */
+#define net_buf_pull_le24(buf) net_buf_simple_pull_le24(&(buf)->b)
+
+/**
+ * @def net_buf_pull_be24
+ * @brief Remove and convert 24 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 24-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 24-bit value converted from big endian to host endian.
+ */
+#define net_buf_pull_be24(buf) net_buf_simple_pull_be24(&(buf)->b)
+
+/**
+ * @def net_buf_pull_le32
+ * @brief Remove and convert 32 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 32-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 32-bit value converted from little endian to host endian.
+ */
+#define net_buf_pull_le32(buf) net_buf_simple_pull_le32(&(buf)->b)
+
+/**
+ * @def net_buf_pull_be32
+ * @brief Remove and convert 32 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 32-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return 32-bit value converted from big endian to host endian.
+ */
+#define net_buf_pull_be32(buf) net_buf_simple_pull_be32(&(buf)->b)
+
+/**
+ * @def net_buf_pull_le48
+ * @brief Remove and convert 48 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 48-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 48-bit value converted from little endian to host endian.
+ */
+#define net_buf_pull_le48(buf) net_buf_simple_pull_le48(&(buf)->b)
+
+/**
+ * @def net_buf_pull_be48
+ * @brief Remove and convert 48 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 48-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return 48-bit value converted from big endian to host endian.
+ */
+#define net_buf_pull_be48(buf) net_buf_simple_pull_be48(&(buf)->b)
+
+/**
+ * @def net_buf_pull_le64
+ * @brief Remove and convert 64 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 64-bit little endian data.
+ *
+ * @param buf A valid pointer on a buffer.
+ *
+ * @return 64-bit value converted from little endian to host endian.
+ */
+#define net_buf_pull_le64(buf) net_buf_simple_pull_le64(&(buf)->b)
+
+/**
+ * @def net_buf_pull_be64
+ * @brief Remove and convert 64 bits from the beginning of the buffer.
+ *
+ * Same idea as with net_buf_pull(), but a helper for operating on
+ * 64-bit big endian data.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return 64-bit value converted from big endian to host endian.
+ */
+#define net_buf_pull_be64(buf) net_buf_simple_pull_be64(&(buf)->b)
+
+/**
+ * @def net_buf_tailroom
+ * @brief Check buffer tailroom.
+ *
+ * Check how much free space there is at the end of the buffer.
+ *
+ * @param buf A valid pointer on a buffer
+ *
+ * @return Number of bytes available at the end of the buffer.
+ */
+#define net_buf_tailroom(buf) net_buf_simple_tailroom(&(buf)->b)
+
+/**
+ * @def net_buf_headroom
+ * @brief Check buffer headroom.
+ *
+ * Check how much free space there is in the beginning of the buffer.
+ *
+ * buf A valid pointer on a buffer
+ *
+ * @return Number of bytes available in the beginning of the buffer.
+ */
+#define net_buf_headroom(buf) net_buf_simple_headroom(&(buf)->b)
+
+/**
+ * @def net_buf_tail
+ * @brief Get the tail pointer for a buffer.
+ *
+ * Get a pointer to the end of the data in a buffer.
+ *
+ * @param buf Buffer.
+ *
+ * @return Tail pointer for the buffer.
+ */
+#define net_buf_tail(buf) net_buf_simple_tail(&(buf)->b)
+
+/**
+ * @brief Find the last fragment in the fragment list.
+ *
+ * @return Pointer to last fragment in the list.
+ */
+struct net_buf *net_buf_frag_last(struct net_buf *frags);
+
+/**
+ * @brief Insert a new fragment to a chain of bufs.
+ *
+ * Insert a new fragment into the buffer fragments list after the parent.
+ *
+ * Note: This function takes ownership of the fragment reference so the
+ * caller is not required to unref.
+ *
+ * @param parent Parent buffer/fragment.
+ * @param frag Fragment to insert.
+ */
+void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag);
+
+/**
+ * @brief Add a new fragment to the end of a chain of bufs.
+ *
+ * Append a new fragment into the buffer fragments list.
+ *
+ * Note: This function takes ownership of the fragment reference so the
+ * caller is not required to unref.
+ *
+ * @param head Head of the fragment chain.
+ * @param frag Fragment to add.
+ *
+ * @return New head of the fragment chain. Either head (if head
+ *         was non-NULL) or frag (if head was NULL).
+ */
+struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag);
+
+/**
+ * @brief Delete existing fragment from a chain of bufs.
+ *
+ * @param parent Parent buffer/fragment, or NULL if there is no parent.
+ * @param frag Fragment to delete.
+ *
+ * @return Pointer to the buffer following the fragment, or NULL if it
+ *         had no further fragments.
+ */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_frag_del_debug(struct net_buf *parent,
+				       struct net_buf *frag,
+				       const char *func, int line);
+#define net_buf_frag_del(_parent, _frag) \
+	net_buf_frag_del_debug(_parent, _frag, __func__, __LINE__)
+#else
+struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag);
+#endif
+
+/**
+ * @brief Copy bytes from net_buf chain starting at offset to linear buffer
+ *
+ * Copy (extract) @a len bytes from @a src net_buf chain, starting from @a
+ * offset in it, to a linear buffer @a dst. Return number of bytes actually
+ * copied, which may be less than requested, if net_buf chain doesn't have
+ * enough data, or destination buffer is too small.
+ *
+ * @param dst Destination buffer
+ * @param dst_len Destination buffer length
+ * @param src Source net_buf chain
+ * @param offset Starting offset to copy from
+ * @param len Number of bytes to copy
+ * @return number of bytes actually copied
+ */
+size_t net_buf_linearize(void *dst, size_t dst_len,
+			 struct net_buf *src, size_t offset, size_t len);
+
+/**
+ * @typedef net_buf_allocator_cb
+ * @brief Network buffer allocator callback.
+ *
+ * @details The allocator callback is called when net_buf_append_bytes
+ * needs to allocate a new net_buf.
+ *
+ * @param timeout Affects the action taken should the net buf pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait until the specified
+ *        timeout.
+ * @param user_data The user data given in net_buf_append_bytes call.
+ * @return pointer to allocated net_buf or NULL on error.
+ */
+typedef struct net_buf *(*net_buf_allocator_cb)(k_timeout_t timeout,
+						void *user_data);
+
+/**
+ * @brief Append data to a list of net_buf
+ *
+ * @details Append data to a net_buf. If there is not enough space in the
+ * net_buf then more net_buf will be added, unless there are no free net_buf
+ * and timeout occurs.
+ *
+ * @param buf Network buffer.
+ * @param len Total length of input data
+ * @param value Data to be added
+ * @param timeout Timeout is passed to the net_buf allocator callback.
+ * @param allocate_cb When a new net_buf is required, use this callback.
+ * @param user_data A user data pointer to be supplied to the allocate_cb.
+ *        This pointer is can be anything from a mem_pool or a net_pkt, the
+ *        logic is left up to the allocate_cb function.
+ *
+ * @return Length of data actually added. This may be less than input
+ *         length if other timeout than K_FOREVER was used, and there
+ *         were no free fragments in a pool to accommodate all data.
+ */
+size_t net_buf_append_bytes(struct net_buf *buf, size_t len,
+			    const void *value, k_timeout_t timeout,
+			    net_buf_allocator_cb allocate_cb, void *user_data);
+
+/**
+ * @brief Skip N number of bytes in a net_buf
+ *
+ * @details Skip N number of bytes starting from fragment's offset. If the total
+ * length of data is placed in multiple fragments, this function will skip from
+ * all fragments until it reaches N number of bytes.  Any fully skipped buffers
+ * are removed from the net_buf list.
+ *
+ * @param buf Network buffer.
+ * @param len Total length of data to be skipped.
+ *
+ * @return Pointer to the fragment or
+ *         NULL and pos is 0 after successful skip,
+ *         NULL and pos is 0xffff otherwise.
+ */
+static inline struct net_buf *net_buf_skip(struct net_buf *buf, size_t len)
+{
+	while (buf && len--) {
+		net_buf_pull_u8(buf);
+		if (!buf->len) {
+			buf = net_buf_frag_del(NULL, buf);
+		}
+	}
+
+	return buf;
+}
+
+/**
+ * @brief Calculate amount of bytes stored in fragments.
+ *
+ * Calculates the total amount of data stored in the given buffer and the
+ * fragments linked to it.
+ *
+ * @param buf Buffer to start off with.
+ *
+ * @return Number of bytes in the buffer and its fragments.
+ */
+static inline size_t net_buf_frags_len(struct net_buf *buf)
+{
+	size_t bytes = 0;
+
+	while (buf) {
+		bytes += buf->len;
+		buf = buf->frags;
+	}
+
+	return bytes;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_BUF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/can.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/can.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/can.h	(working copy)
@@ -0,0 +1,236 @@
+/** @file
+ * @brief IPv6 Networking over CAN definitions.
+ *
+ * Definitions for IPv6 Networking over CAN support.
+ */
+
+/*
+ * Copyright (c) 2019 Alexander Wachter
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_CAN_H_
+#define ZEPHYR_INCLUDE_NET_CAN_H_
+
+#include <zephyr/types.h>
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <drivers/can.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief IPv6 over CAN library
+ * @defgroup net_can Network Core Library
+ * @ingroup networking
+ * @{
+ */
+
+/**
+ * CAN L2 driver API. Used by 6loCAN.
+ */
+
+/*
+ * Abbreviations
+ * BS      Block Size
+ * CAN_DL  CAN LL data size
+ * CF      Consecutive Frame
+ * CTS     Continue to send
+ * DLC     Data length code
+ * FC      Flow Control
+ * FF      First Frame
+ * FS      Flow Status
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+#define NET_CAN_DL 8
+#define NET_CAN_MTU 0x0FFF
+
+/* 0x3DFF - bit 4 to 10 must not be zero. Also prevent stuffing bit*/
+#define NET_CAN_MULTICAST_ADDR      0x3DFF
+#define NET_CAN_DAD_ADDR            0x3DFE
+#define NET_CAN_ETH_TRANSLATOR_ADDR 0x3DF0
+#define NET_CAN_MAX_ADDR            0x3DEF
+#define NET_CAN_MIN_ADDR            0x0100
+
+#define CAN_NET_IF_ADDR_MASK       0x3FFF
+#define CAN_NET_IF_ADDR_BYTE_LEN   2U
+#define CAN_NET_IF_ADDR_DEST_POS   14U
+#define CAN_NET_IF_ADDR_DEST_MASK  (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS)
+#define CAN_NET_IF_ADDR_SRC_POS    0U
+#define CAN_NET_IF_ADDR_SRC_MASK   (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_SRC_POS)
+#define CAN_NET_IF_ADDR_MCAST_POS  28U
+#define CAN_NET_IF_ADDR_MCAST_MASK (1UL << CAN_NET_IF_ADDR_MCAST_POS)
+
+#define CAN_NET_IF_IS_MCAST_BIT    (1U << 14)
+
+#define CAN_NET_FILTER_NOT_SET -1
+
+/** @endcond */
+
+/*
+ *             +-----------+           +-----------+
+ *             |           |           |           |
+ *             |   IPv6    |           |   IPv6    |
+ *             |  6LoCAN   |           |  6LoCAN   |
+ *             |           |           |           |
+ *             +----+-+----+           +----+-+----+
+ *                  | |                     | |                   +---+
+ *  +----+          | |                     | |                  /     \   +-+
+ *  |    |          | |                     | |          +--+   /       \_/   \
+ * +++   +---+   +--+----+   +-------+   +--+----+   +--/    \_/               \
+ * | |        \ /     |   \ /         \ /     |   \ /  /                       |
+ * | |         X      |    X    CAN    X      |    X  |         Internet       |
+ * | |        / \     |   / \         / \     |   / \  \                       /
+ * +++   +---+   +----+--+   +-------+   +----+--+   +--+                     /
+ *  |    |                                               +-------------------+
+ *  +----+
+ */
+struct net_can_api {
+	/**
+	 * The net_if_api must be placed in first position in this
+	 * struct so that we are compatible with network interface API.
+	 */
+	struct net_if_api iface_api;
+
+	/** Send a single CAN frame */
+	int (*send)(const struct device *dev, const struct zcan_frame *frame,
+		    can_tx_callback_t cb, void *cb_arg, k_timeout_t timeout);
+	/** Attach a filter with it's callback */
+	int (*attach_filter)(const struct device *dev, can_rx_callback_t cb,
+			     void *cb_arg, const struct zcan_filter *filter);
+	/** Detach a filter */
+	void (*detach_filter)(const struct device *dev, int filter_id);
+	/** Enable or disable the reception of frames for net CAN */
+	int (*enable)(const struct device *dev, bool enable);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * net_can_api struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct net_can_api, iface_api) == 0);
+
+/** @cond INTERNAL_HIDDEN */
+
+#define CANBUS_L2_CTX_TYPE	struct net_canbus_context *
+
+/**
+ * Context for canbus net device.
+ */
+struct canbus_net_ctx {
+	/** Filter ID for link layer duplicate address detection. */
+	int dad_filter_id;
+	/** Work item for responding to link layer DAD requests. */
+	struct k_work dad_work;
+	/** The interface associated with this device */
+	struct net_if *iface;
+	/** The link layer address chosen for this interface */
+	uint16_t ll_addr;
+};
+
+/**
+ * Canbus link layer addresses have a length of 14 bit for source and destination.
+ * Both together are 28 bit to fit a CAN extended identifier with 29 bit length.
+ */
+struct net_canbus_lladdr {
+	uint16_t addr : 14;
+};
+
+/**
+ * STmin is split in two valid ranges:
+ *   0-127: 0ms-127ms
+ * 128-240: Reserved
+ * 241-249: 100us-900us (multiples of 100us)
+ * 250-   : Reserved
+ */
+struct canbus_fc_opts {
+	/** Block size. Number of CF PDUs before next CF is sent */
+	uint8_t bs;
+	/**< Minimum separation time. Min time between frames */
+	uint8_t stmin;
+};
+
+/**
+ * Context for a transmission of messages that didn't fit in a single frame.
+ * These messages Start with a FF (First Frame) that is in case of unicast
+ * acknowledged by a FC (Frame Control). After that, one or more CF
+ * (Consecutive frames) carry the rest of the message.
+ */
+struct canbus_isotp_tx_ctx {
+	/** Pkt containing the data to transmit */
+	struct net_pkt *pkt;
+	/** Timeout for TX Timeout and separation time */
+	struct _timeout timeout;
+	/** Frame Control options received from FC frame */
+	struct canbus_fc_opts opts;
+	/** CAN destination address */
+	struct net_canbus_lladdr dest_addr;
+	/** Remaining data to transmit in bytes */
+	uint16_t rem_len;
+	/** Number of bytes in the tx queue */
+	int8_t tx_backlog;
+	/** State of the transmission */
+	uint8_t state;
+	/** Actual block number that is transmitted. Counts from BS to 0 */
+	uint8_t act_block_nr;
+	/** Number of WAIT frames received */
+	uint8_t wft;
+	/** Sequence number that is added to CF */
+	uint8_t sn : 4;
+	/** Transmission is multicast */
+	uint8_t is_mcast : 1;
+};
+
+/**
+ * Context for reception of messages that are not single frames.
+ * This is the counterpart of the canbus_isotp_tx_ctx.
+ */
+struct canbus_isotp_rx_ctx {
+	/** Pkt that is large enough to hold the entire message */
+	struct net_pkt *pkt;
+	/** Timeout for RX timeout*/
+	struct _timeout timeout;
+	/** Remaining data to receive. Goes from message length to zero */
+	uint16_t rem_len;
+	/** State of the reception */
+	uint8_t state;
+	/** Number of frames received in this block. Counts from BS to 0 */
+	uint8_t act_block_nr;
+	/** Number of WAIT frames transmitted */
+	uint8_t wft;
+	/** Expected sequence number in CF */
+	uint8_t sn : 4;
+};
+
+/**
+ * Initialization of the canbus L2.
+ *
+ * This function starts the TX workqueue and does some initialization.
+ */
+void net_6locan_init(struct net_if *iface);
+
+/**
+ * Ethernet frame input function for Ethernet to 6LoCAN translation
+ *
+ * This function checks the destination link layer address for addresses
+ * that has to be forwarded. Frames that need to be forwarded are forwarded here.
+ */
+enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface,
+						struct net_pkt *pkt);
+
+/** @endcond */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/coap.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/coap.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/coap.h	(working copy)
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief CoAP implementation for Zephyr.
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_COAP_H_
+#define ZEPHYR_INCLUDE_NET_COAP_H_
+
+/**
+ * @brief COAP library
+ * @defgroup coap COAP Library
+ * @ingroup networking
+ * @{
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <net/net_ip.h>
+
+#include <sys/slist.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Set of CoAP packet options we are aware of.
+ *
+ * Users may add options other than these to their packets, provided
+ * they know how to format them correctly. The only restriction is
+ * that all options must be added to a packet in numeric order.
+ *
+ * Refer to RFC 7252, section 12.2 for more information.
+ */
+enum coap_option_num {
+	COAP_OPTION_IF_MATCH = 1,
+	COAP_OPTION_URI_HOST = 3,
+	COAP_OPTION_ETAG = 4,
+	COAP_OPTION_IF_NONE_MATCH = 5,
+	COAP_OPTION_OBSERVE = 6,
+	COAP_OPTION_URI_PORT = 7,
+	COAP_OPTION_LOCATION_PATH = 8,
+	COAP_OPTION_URI_PATH = 11,
+	COAP_OPTION_CONTENT_FORMAT = 12,
+	COAP_OPTION_MAX_AGE = 14,
+	COAP_OPTION_URI_QUERY = 15,
+	COAP_OPTION_ACCEPT = 17,
+	COAP_OPTION_LOCATION_QUERY = 20,
+	COAP_OPTION_BLOCK2 = 23,
+	COAP_OPTION_BLOCK1 = 27,
+	COAP_OPTION_SIZE2 = 28,
+	COAP_OPTION_PROXY_URI = 35,
+	COAP_OPTION_PROXY_SCHEME = 39,
+	COAP_OPTION_SIZE1 = 60,
+};
+
+/**
+ * @brief Available request methods.
+ *
+ * To be used when creating a request or a response.
+ */
+enum coap_method {
+	COAP_METHOD_GET = 1,
+	COAP_METHOD_POST = 2,
+	COAP_METHOD_PUT = 3,
+	COAP_METHOD_DELETE = 4,
+};
+
+#define COAP_REQUEST_MASK 0x07
+
+/**
+ * @brief CoAP packets may be of one of these types.
+ */
+enum coap_msgtype {
+	/**
+	 * Confirmable message.
+	 *
+	 * The packet is a request or response the destination end-point must
+	 * acknowledge.
+	 */
+	COAP_TYPE_CON = 0,
+	/**
+	 * Non-confirmable message.
+	 *
+	 * The packet is a request or response that doesn't
+	 * require acknowledgements.
+	 */
+	COAP_TYPE_NON_CON = 1,
+	/**
+	 * Acknowledge.
+	 *
+	 * Response to a confirmable message.
+	 */
+	COAP_TYPE_ACK = 2,
+	/**
+	 * Reset.
+	 *
+	 * Rejecting a packet for any reason is done by sending a message
+	 * of this type.
+	 */
+	COAP_TYPE_RESET = 3
+};
+
+#define coap_make_response_code(class, det) ((class << 5) | (det))
+
+/**
+ * @brief Set of response codes available for a response packet.
+ *
+ * To be used when creating a response.
+ */
+enum coap_response_code {
+	COAP_RESPONSE_CODE_OK = coap_make_response_code(2, 0),
+	COAP_RESPONSE_CODE_CREATED = coap_make_response_code(2, 1),
+	COAP_RESPONSE_CODE_DELETED = coap_make_response_code(2, 2),
+	COAP_RESPONSE_CODE_VALID = coap_make_response_code(2, 3),
+	COAP_RESPONSE_CODE_CHANGED = coap_make_response_code(2, 4),
+	COAP_RESPONSE_CODE_CONTENT = coap_make_response_code(2, 5),
+	COAP_RESPONSE_CODE_CONTINUE = coap_make_response_code(2, 31),
+	COAP_RESPONSE_CODE_BAD_REQUEST = coap_make_response_code(4, 0),
+	COAP_RESPONSE_CODE_UNAUTHORIZED = coap_make_response_code(4, 1),
+	COAP_RESPONSE_CODE_BAD_OPTION = coap_make_response_code(4, 2),
+	COAP_RESPONSE_CODE_FORBIDDEN = coap_make_response_code(4, 3),
+	COAP_RESPONSE_CODE_NOT_FOUND = coap_make_response_code(4, 4),
+	COAP_RESPONSE_CODE_NOT_ALLOWED = coap_make_response_code(4, 5),
+	COAP_RESPONSE_CODE_NOT_ACCEPTABLE = coap_make_response_code(4, 6),
+	COAP_RESPONSE_CODE_INCOMPLETE = coap_make_response_code(4, 8),
+	COAP_RESPONSE_CODE_PRECONDITION_FAILED = coap_make_response_code(4, 12),
+	COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = coap_make_response_code(4, 13),
+	COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT =
+						coap_make_response_code(4, 15),
+	COAP_RESPONSE_CODE_INTERNAL_ERROR = coap_make_response_code(5, 0),
+	COAP_RESPONSE_CODE_NOT_IMPLEMENTED = coap_make_response_code(5, 1),
+	COAP_RESPONSE_CODE_BAD_GATEWAY = coap_make_response_code(5, 2),
+	COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = coap_make_response_code(5, 3),
+	COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = coap_make_response_code(5, 4),
+	COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED =
+						coap_make_response_code(5, 5)
+};
+
+#define COAP_CODE_EMPTY (0)
+
+/* block option helper */
+#define GET_BLOCK_NUM(v)        ((v) >> 4)
+#define GET_BLOCK_SIZE(v)       (((v) & 0x7))
+#define GET_MORE(v)             (!!((v) & 0x08))
+
+struct coap_observer;
+struct coap_packet;
+struct coap_pending;
+struct coap_reply;
+struct coap_resource;
+
+/**
+ * @typedef coap_method_t
+ * @brief Type of the callback being called when a resource's method is
+ * invoked by the remote entity.
+ */
+typedef int (*coap_method_t)(struct coap_resource *resource,
+			     struct coap_packet *request,
+			     struct sockaddr *addr, socklen_t addr_len);
+
+/**
+ * @typedef coap_notify_t
+ * @brief Type of the callback being called when a resource's has observers
+ * to be informed when an update happens.
+ */
+typedef void (*coap_notify_t)(struct coap_resource *resource,
+			      struct coap_observer *observer);
+
+/**
+ * @brief Description of CoAP resource.
+ *
+ * CoAP servers often want to register resources, so that clients can act on
+ * them, by fetching their state or requesting updates to them.
+ */
+struct coap_resource {
+	/** Which function to be called for each CoAP method */
+	coap_method_t get, post, put, del;
+	coap_notify_t notify;
+	const char * const *path;
+	void *user_data;
+	sys_slist_t observers;
+	int age;
+};
+
+/**
+ * @brief Represents a remote device that is observing a local resource.
+ */
+struct coap_observer {
+	sys_snode_t list;
+	struct sockaddr addr;
+	uint8_t token[8];
+	uint8_t tkl;
+};
+
+/**
+ * @brief Representation of a CoAP Packet.
+ */
+struct coap_packet {
+	uint8_t *data; /* User allocated buffer */
+	uint16_t offset; /* CoAP lib maintains offset while adding data */
+	uint16_t max_len; /* Max CoAP packet data length */
+	uint8_t hdr_len; /* CoAP header length */
+	uint16_t opt_len; /* Total options length (delta + len + value) */
+	uint16_t delta; /* Used for delta calculation in CoAP packet */
+};
+
+struct coap_option {
+	uint16_t delta;
+#if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN)
+	uint16_t len;
+	uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE];
+#else
+	uint8_t len;
+	uint8_t value[12];
+#endif
+};
+
+/**
+ * @typedef coap_reply_t
+ * @brief Helper function to be called when a response matches the
+ * a pending request.
+ */
+typedef int (*coap_reply_t)(const struct coap_packet *response,
+			    struct coap_reply *reply,
+			    const struct sockaddr *from);
+
+/**
+ * @brief Represents a request awaiting for an acknowledgment (ACK).
+ */
+struct coap_pending {
+	struct sockaddr addr;
+	uint32_t t0;
+	uint32_t timeout;
+	uint16_t id;
+	uint8_t *data;
+	uint16_t len;
+};
+
+/**
+ * @brief Represents the handler for the reply of a request, it is
+ * also used when observing resources.
+ */
+struct coap_reply {
+	coap_reply_t reply;
+	void *user_data;
+	int age;
+	uint16_t id;
+	uint8_t token[8];
+	uint8_t tkl;
+};
+
+/**
+ * @brief Returns the version present in a CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ *
+ * @return the CoAP version in packet
+ */
+uint8_t coap_header_get_version(const struct coap_packet *cpkt);
+
+/**
+ * @brief Returns the type of the CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ *
+ * @return the type of the packet
+ */
+uint8_t coap_header_get_type(const struct coap_packet *cpkt);
+
+/**
+ * @brief Returns the token (if any) in the CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ * @param token Where to store the token
+ *
+ * @return Token length in the CoAP packet.
+ */
+uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token);
+
+/**
+ * @brief Returns the code of the CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ *
+ * @return the code present in the packet
+ */
+uint8_t coap_header_get_code(const struct coap_packet *cpkt);
+
+/**
+ * @brief Returns the message id associated with the CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ *
+ * @return the message id present in the packet
+ */
+uint16_t coap_header_get_id(const struct coap_packet *cpkt);
+
+/**
+ * @brief Returns the data pointer and length of the CoAP packet.
+ *
+ * @param cpkt CoAP packet representation
+ * @param len Total length of CoAP payload
+ *
+ * @return data pointer and length if payload exists
+ *         NULL pointer and length set to 0 in case there is no payload
+ */
+const uint8_t *coap_packet_get_payload(const struct coap_packet *cpkt,
+				       uint16_t *len);
+
+/**
+ * @brief Parses the CoAP packet in data, validating it and
+ * initializing @a cpkt. @a data must remain valid while @a cpkt is used.
+ *
+ * @param cpkt Packet to be initialized from received @a data.
+ * @param data Data containing a CoAP packet, its @a data pointer is
+ * positioned on the start of the CoAP packet.
+ * @param len Length of the data
+ * @param options Parse options and cache its details.
+ * @param opt_num Number of options
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_packet_parse(struct coap_packet *cpkt, uint8_t *data, uint16_t len,
+		      struct coap_option *options, uint8_t opt_num);
+
+/**
+ * @brief Creates a new CoAP Packet from input data.
+ *
+ * @param cpkt New packet to be initialized using the storage from @a data.
+ * @param data Data that will contain a CoAP packet information
+ * @param max_len Maximum allowable length of data
+ * @param ver CoAP header version
+ * @param type CoAP header type
+ * @param token_len CoAP header token length
+ * @param token CoAP header token
+ * @param code CoAP header code
+ * @param id CoAP header message id
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_packet_init(struct coap_packet *cpkt, uint8_t *data, uint16_t max_len,
+		     uint8_t ver, uint8_t type, uint8_t token_len,
+		     uint8_t *token, uint8_t code, uint16_t id);
+
+/**
+ * @brief Returns a randomly generated array of 8 bytes, that can be
+ * used as a message's token.
+ *
+ * @return a 8-byte pseudo-random token.
+ */
+uint8_t *coap_next_token(void);
+
+/**
+ * @brief Helper to generate message ids
+ *
+ * @return a new message id
+ */
+uint16_t coap_next_id(void);
+
+/**
+ * @brief Return the values associated with the option of value @a
+ * code.
+ *
+ * @param cpkt CoAP packet representation
+ * @param code Option number to look for
+ * @param options Array of #coap_option where to store the value
+ * of the options found
+ * @param veclen Number of elements in the options array
+ *
+ * @return The number of options found in packet matching code,
+ * negative on error.
+ */
+int coap_find_options(const struct coap_packet *cpkt, uint16_t code,
+		      struct coap_option *options, uint16_t veclen);
+
+/**
+ * @brief Appends an option to the packet.
+ *
+ * Note: options must be added in numeric order of their codes. Otherwise
+ * error will be returned.
+ * TODO: Add support for placing options according to its delta value.
+ *
+ * @param cpkt Packet to be updated
+ * @param code Option code to add to the packet, see #coap_option_num
+ * @param value Pointer to the value of the option, will be copied to the
+ * packet
+ * @param len Size of the data to be added
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_packet_append_option(struct coap_packet *cpkt, uint16_t code,
+			      const uint8_t *value, uint16_t len);
+
+/**
+ * @brief Converts an option to its integer representation.
+ *
+ * Assumes that the number is encoded in the network byte order in the
+ * option.
+ *
+ * @param option Pointer to the option value, retrieved by
+ * coap_find_options()
+ *
+ * @return The integer representation of the option
+ */
+unsigned int coap_option_value_to_int(const struct coap_option *option);
+
+/**
+ * @brief Appends an integer value option to the packet.
+ *
+ * The option must be added in numeric order of their codes, and the
+ * least amount of bytes will be used to encode the value.
+ *
+ * @param cpkt Packet to be updated
+ * @param code Option code to add to the packet, see #coap_option_num
+ * @param val Integer value to be added
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_append_option_int(struct coap_packet *cpkt, uint16_t code,
+			   unsigned int val);
+
+/**
+ * @brief Append payload marker to CoAP packet
+ *
+ * @param cpkt Packet to append the payload marker (0xFF)
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_packet_append_payload_marker(struct coap_packet *cpkt);
+
+/**
+ * @brief Append payload to CoAP packet
+ *
+ * @param cpkt Packet to append the payload
+ * @param payload CoAP packet payload
+ * @param payload_len CoAP packet payload len
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_packet_append_payload(struct coap_packet *cpkt, uint8_t *payload,
+			       uint16_t payload_len);
+
+/**
+ * @brief When a request is received, call the appropriate methods of
+ * the matching resources.
+ *
+ * @param cpkt Packet received
+ * @param resources Array of known resources
+ * @param options Parsed options from coap_packet_parse()
+ * @param opt_num Number of options
+ * @param addr Peer address
+ * @param addr_len Peer address length
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_handle_request(struct coap_packet *cpkt,
+			struct coap_resource *resources,
+			struct coap_option *options,
+			uint8_t opt_num,
+			struct sockaddr *addr, socklen_t addr_len);
+
+/**
+ * Represents the size of each block that will be transferred using
+ * block-wise transfers [RFC7959]:
+ *
+ * Each entry maps directly to the value that is used in the wire.
+ *
+ * https://tools.ietf.org/html/rfc7959
+ */
+enum coap_block_size {
+	COAP_BLOCK_16,
+	COAP_BLOCK_32,
+	COAP_BLOCK_64,
+	COAP_BLOCK_128,
+	COAP_BLOCK_256,
+	COAP_BLOCK_512,
+	COAP_BLOCK_1024,
+};
+
+/**
+ * @brief Helper for converting the enumeration to the size expressed
+ * in bytes.
+ *
+ * @param block_size The block size to be converted
+ *
+ * @return The size in bytes that the block_size represents
+ */
+static inline uint16_t coap_block_size_to_bytes(
+	enum coap_block_size block_size)
+{
+	return (1 << (block_size + 4));
+}
+
+/**
+ * @brief Represents the current state of a block-wise transaction.
+ */
+struct coap_block_context {
+	size_t total_size;
+	size_t current;
+	enum coap_block_size block_size;
+};
+
+/**
+ * @brief Initializes the context of a block-wise transfer.
+ *
+ * @param ctx The context to be initialized
+ * @param block_size The size of the block
+ * @param total_size The total size of the transfer, if known
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_block_transfer_init(struct coap_block_context *ctx,
+			     enum coap_block_size block_size,
+			     size_t total_size);
+
+/**
+ * @brief Append BLOCK1 option to the packet.
+ *
+ * @param cpkt Packet to be updated
+ * @param ctx Block context from which to retrieve the
+ * information for the Block1 option
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_append_block1_option(struct coap_packet *cpkt,
+			      struct coap_block_context *ctx);
+
+/**
+ * @brief Append BLOCK2 option to the packet.
+ *
+ * @param cpkt Packet to be updated
+ * @param ctx Block context from which to retrieve the
+ * information for the Block2 option
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_append_block2_option(struct coap_packet *cpkt,
+			      struct coap_block_context *ctx);
+
+/**
+ * @brief Append SIZE1 option to the packet.
+ *
+ * @param cpkt Packet to be updated
+ * @param ctx Block context from which to retrieve the
+ * information for the Size1 option
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_append_size1_option(struct coap_packet *cpkt,
+			     struct coap_block_context *ctx);
+
+/**
+ * @brief Append SIZE2 option to the packet.
+ *
+ * @param cpkt Packet to be updated
+ * @param ctx Block context from which to retrieve the
+ * information for the Size2 option
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_append_size2_option(struct coap_packet *cpkt,
+			     struct coap_block_context *ctx);
+
+/**
+ * @brief Get the integer representation of a CoAP option.
+ *
+ * @param cpkt Packet to be inspected
+ * @param code CoAP option code
+ *
+ * @return Integer value >= 0 in case of success or negative in case
+ * of error.
+ */
+int coap_get_option_int(const struct coap_packet *cpkt, uint16_t code);
+
+/**
+ * @brief Retrieves BLOCK{1,2} and SIZE{1,2} from @a cpkt and updates
+ * @a ctx accordingly.
+ *
+ * @param cpkt Packet in which to look for block-wise transfers options
+ * @param ctx Block context to be updated
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_update_from_block(const struct coap_packet *cpkt,
+			   struct coap_block_context *ctx);
+
+/**
+ * @brief Updates @a ctx so after this is called the current entry
+ * indicates the correct offset in the body of data being
+ * transferred.
+ *
+ * @param cpkt Packet in which to look for block-wise transfers options
+ * @param ctx Block context to be updated
+ *
+ * @return The offset in the block-wise transfer, 0 if the transfer
+ * has finished.
+ */
+size_t coap_next_block(const struct coap_packet *cpkt,
+		       struct coap_block_context *ctx);
+
+/**
+ * @brief Indicates that the remote device referenced by @a addr, with
+ * @a request, wants to observe a resource.
+ *
+ * @param observer Observer to be initialized
+ * @param request Request on which the observer will be based
+ * @param addr Address of the remote device
+ */
+void coap_observer_init(struct coap_observer *observer,
+			const struct coap_packet *request,
+			const struct sockaddr *addr);
+
+/**
+ * @brief After the observer is initialized, associate the observer
+ * with an resource.
+ *
+ * @param resource Resource to add an observer
+ * @param observer Observer to be added
+ *
+ * @return true if this is the first observer added to this resource.
+ */
+bool coap_register_observer(struct coap_resource *resource,
+			    struct coap_observer *observer);
+
+/**
+ * @brief Remove this observer from the list of registered observers
+ * of that resource.
+ *
+ * @param resource Resource in which to remove the observer
+ * @param observer Observer to be removed
+ */
+void coap_remove_observer(struct coap_resource *resource,
+			  struct coap_observer *observer);
+
+/**
+ * @brief Returns the observer that matches address @a addr.
+ *
+ * @param observers Pointer to the array of observers
+ * @param len Size of the array of observers
+ * @param addr Address of the endpoint observing a resource
+ *
+ * @return A pointer to a observer if a match is found, NULL
+ * otherwise.
+ */
+struct coap_observer *coap_find_observer_by_addr(
+	struct coap_observer *observers, size_t len,
+	const struct sockaddr *addr);
+
+/**
+ * @brief Returns the next available observer representation.
+ *
+ * @param observers Pointer to the array of observers
+ * @param len Size of the array of observers
+ *
+ * @return A pointer to a observer if there's an available observer,
+ * NULL otherwise.
+ */
+struct coap_observer *coap_observer_next_unused(
+	struct coap_observer *observers, size_t len);
+
+/**
+ * @brief Indicates that a reply is expected for @a request.
+ *
+ * @param reply Reply structure to be initialized
+ * @param request Request from which @a reply will be based
+ */
+void coap_reply_init(struct coap_reply *reply,
+		     const struct coap_packet *request);
+
+/**
+ * @brief Initialize a pending request with a request.
+ *
+ * The request's fields are copied into the pending struct, so @a
+ * request doesn't have to live for as long as the pending struct
+ * lives, but "data" that needs to live for at least that long.
+ *
+ * @param pending Structure representing the waiting for a
+ * confirmation message, initialized with data from @a request
+ * @param request Message waiting for confirmation
+ * @param addr Address to send the retransmission
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_pending_init(struct coap_pending *pending,
+		      const struct coap_packet *request,
+		      const struct sockaddr *addr);
+
+/**
+ * @brief Returns the next available pending struct, that can be used
+ * to track the retransmission status of a request.
+ *
+ * @param pendings Pointer to the array of #coap_pending structures
+ * @param len Size of the array of #coap_pending structures
+ *
+ * @return pointer to a free #coap_pending structure, NULL in case
+ * none could be found.
+ */
+struct coap_pending *coap_pending_next_unused(
+	struct coap_pending *pendings, size_t len);
+
+/**
+ * @brief Returns the next available reply struct, so it can be used
+ * to track replies and notifications received.
+ *
+ * @param replies Pointer to the array of #coap_reply structures
+ * @param len Size of the array of #coap_reply structures
+ *
+ * @return pointer to a free #coap_reply structure, NULL in case
+ * none could be found.
+ */
+struct coap_reply *coap_reply_next_unused(
+	struct coap_reply *replies, size_t len);
+
+/**
+ * @brief After a response is received, returns if there is any
+ * matching pending request exits. User has to clear all pending
+ * retransmissions related to that response by calling
+ * coap_pending_clear().
+ *
+ * @param response The received response
+ * @param pendings Pointer to the array of #coap_reply structures
+ * @param len Size of the array of #coap_reply structures
+ *
+ * @return pointer to the associated #coap_pending structure, NULL in
+ * case none could be found.
+ */
+struct coap_pending *coap_pending_received(
+	const struct coap_packet *response,
+	struct coap_pending *pendings, size_t len);
+
+/**
+ * @brief After a response is received, call coap_reply_t handler
+ * registered in #coap_reply structure
+ *
+ * @param response A response received
+ * @param from Address from which the response was received
+ * @param replies Pointer to the array of #coap_reply structures
+ * @param len Size of the array of #coap_reply structures
+ *
+ * @return Pointer to the reply matching the packet received, NULL if
+ * none could be found.
+ */
+struct coap_reply *coap_response_received(
+	const struct coap_packet *response,
+	const struct sockaddr *from,
+	struct coap_reply *replies, size_t len);
+
+/**
+ * @brief Returns the next pending about to expire, pending->timeout
+ * informs how many ms to next expiration.
+ *
+ * @param pendings Pointer to the array of #coap_pending structures
+ * @param len Size of the array of #coap_pending structures
+ *
+ * @return The next #coap_pending to expire, NULL if none is about to
+ * expire.
+ */
+struct coap_pending *coap_pending_next_to_expire(
+	struct coap_pending *pendings, size_t len);
+
+/**
+ * @brief After a request is sent, user may want to cycle the pending
+ * retransmission so the timeout is updated.
+ *
+ * @param pending Pending representation to have its timeout updated
+ *
+ * @return false if this is the last retransmission.
+ */
+bool coap_pending_cycle(struct coap_pending *pending);
+
+/**
+ * @brief Cancels the pending retransmission, so it again becomes
+ * available.
+ *
+ * @param pending Pending representation to be canceled
+ */
+void coap_pending_clear(struct coap_pending *pending);
+
+/**
+ * @brief Cancels all pending retransmissions, so they become
+ * available again.
+ *
+ * @param pendings Pointer to the array of #coap_pending structures
+ * @param len Size of the array of #coap_pending structures
+ */
+void coap_pendings_clear(struct coap_pending *pendings, size_t len);
+
+/**
+ * @brief Cancels awaiting for this reply, so it becomes available
+ * again. User responsibility to free the memory associated with data.
+ *
+ * @param reply The reply to be canceled
+ */
+void coap_reply_clear(struct coap_reply *reply);
+
+/**
+ * @brief Cancels all replies, so they become available again.
+ *
+ * @param replies Pointer to the array of #coap_reply structures
+ * @param len Size of the array of #coap_reply structures
+ */
+void coap_replies_clear(struct coap_reply *replies, size_t len);
+
+/**
+ * @brief Indicates that this resource was updated and that the @a
+ * notify callback should be called for every registered observer.
+ *
+ * @param resource Resource that was updated
+ *
+ * @return 0 in case of success or negative in case of error.
+ */
+int coap_resource_notify(struct coap_resource *resource);
+
+/**
+ * @brief Returns if this request is enabling observing a resource.
+ *
+ * @param request Request to be checked
+ *
+ * @return True if the request is enabling observing a resource, False
+ * otherwise
+ */
+bool coap_request_is_observe(const struct coap_packet *request);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_COAP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/coap_link_format.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/coap_link_format.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/coap_link_format.h	(working copy)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief CoAP implementation for Zephyr.
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_COAP_LINK_FORMAT_H_
+#define ZEPHYR_INCLUDE_NET_COAP_LINK_FORMAT_H_
+
+/**
+ * @addtogroup coap COAP Library
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This resource should be added before all other resources that should be
+ * included in the responses of the .well-known/core resource.
+ */
+#define COAP_WELL_KNOWN_CORE_PATH \
+	((const char * const[]) { ".well-known", "core", NULL })
+
+int coap_well_known_core_get(struct coap_resource *resource,
+			     struct coap_packet *request,
+			     struct coap_packet *response,
+			     uint8_t *data, uint16_t len);
+
+/**
+ * In case you want to add attributes to the resources included in the
+ * 'well-known/core' "virtual" resource, the 'user_data' field should point
+ * to a valid coap_core_metadata structure.
+ */
+struct coap_core_metadata {
+	const char * const *attributes;
+	void *user_data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_COAP_LINK_FORMAT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/dhcpv4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dhcpv4.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dhcpv4.h	(working copy)
@@ -0,0 +1,88 @@
+/** @file
+ *  @brief DHCPv4 Client Handler
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_DHCPV4_H_
+#define ZEPHYR_INCLUDE_NET_DHCPV4_H_
+
+#include <sys/slist.h>
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief DHCPv4
+ * @defgroup dhcpv4 DHCPv4
+ * @ingroup networking
+ * @{
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+/** Current state of DHCPv4 client address negotiation.
+ *
+ * Additions removals and reorders in this definition must be
+ * reflected within corresponding changes to net_dhcpv4_state_name.
+ */
+enum net_dhcpv4_state {
+	NET_DHCPV4_DISABLED,
+	NET_DHCPV4_INIT,
+	NET_DHCPV4_SELECTING,
+	NET_DHCPV4_REQUESTING,
+	NET_DHCPV4_RENEWING,
+	NET_DHCPV4_REBINDING,
+	NET_DHCPV4_BOUND,
+} __packed;
+
+/** @endcond */
+
+/**
+ *  @brief Start DHCPv4 client on an iface
+ *
+ *  @details Start DHCPv4 client on a given interface. DHCPv4 client
+ *  will start negotiation for IPv4 address. Once the negotiation is
+ *  success IPv4 address details will be added to interface.
+ *
+ *  @param iface A valid pointer on an interface
+ */
+void net_dhcpv4_start(struct net_if *iface);
+
+/**
+ *  @brief Stop DHCPv4 client on an iface
+ *
+ *  @details Stop DHCPv4 client on a given interface. DHCPv4 client
+ *  will remove all configuration obtained from a DHCP server from the
+ *  interface and stop any further negotiation with the server.
+ *
+ *  @param iface A valid pointer on an interface
+ */
+void net_dhcpv4_stop(struct net_if *iface);
+
+/** @cond INTERNAL_HIDDEN */
+
+/**
+ *  @brief DHCPv4 state name
+ *
+ *  @internal
+ */
+const char *net_dhcpv4_state_name(enum net_dhcpv4_state state);
+
+/** @endcond */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_DHCPV4_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/dns_resolve.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dns_resolve.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dns_resolve.h	(working copy)
@@ -0,0 +1,424 @@
+/** @file
+ * @brief DNS resolving library
+ *
+ * An API for applications to resolve a DNS name.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_
+#define ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_
+
+#include <net/net_ip.h>
+#include <net/net_context.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief DNS resolving library
+ * @defgroup dns_resolve DNS Resolve Library
+ * @ingroup networking
+ * @{
+ */
+
+/**
+ * DNS query type enum
+ */
+enum dns_query_type {
+	/** IPv4 query */
+	DNS_QUERY_TYPE_A = 1,
+	/** IPv6 query */
+	DNS_QUERY_TYPE_AAAA = 28
+};
+
+/** Max size of the resolved name. */
+#ifndef DNS_MAX_NAME_SIZE
+#define DNS_MAX_NAME_SIZE 20
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Make sure that we can compile things even if CONFIG_DNS_RESOLVER
+ * is not enabled.
+ */
+#if !defined(CONFIG_DNS_RESOLVER_MAX_SERVERS)
+#define CONFIG_DNS_RESOLVER_MAX_SERVERS 1
+#endif
+#if !defined(CONFIG_DNS_NUM_CONCUR_QUERIES)
+#define CONFIG_DNS_NUM_CONCUR_QUERIES 1
+#endif
+
+/* If mDNS is enabled, then add some extra well known multicast servers to the
+ * server list.
+ */
+#if defined(CONFIG_MDNS_RESOLVER)
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+#define MDNS_SERVER_COUNT 2
+#else
+#define MDNS_SERVER_COUNT 1
+#endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#else
+#define MDNS_SERVER_COUNT 0
+#endif /* CONFIG_MDNS_RESOLVER */
+
+/* If LLMNR is enabled, then add some extra well known multicast servers to the
+ * server list.
+ */
+#if defined(CONFIG_LLMNR_RESOLVER)
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+#define LLMNR_SERVER_COUNT 2
+#else
+#define LLMNR_SERVER_COUNT 1
+#endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#else
+#define LLMNR_SERVER_COUNT 0
+#endif /* CONFIG_MDNS_RESOLVER */
+
+#define DNS_MAX_MCAST_SERVERS (MDNS_SERVER_COUNT + LLMNR_SERVER_COUNT)
+
+/** @endcond */
+
+/**
+ * Address info struct is passed to callback that gets all the results.
+ */
+struct dns_addrinfo {
+	struct sockaddr ai_addr;
+	socklen_t       ai_addrlen;
+	uint8_t            ai_family;
+	char            ai_canonname[DNS_MAX_NAME_SIZE + 1];
+};
+
+/**
+ * Status values for the callback.
+ */
+enum dns_resolve_status {
+	/** Invalid value for `ai_flags' field */
+	DNS_EAI_BADFLAGS    = -1,
+	/** NAME or SERVICE is unknown */
+	DNS_EAI_NONAME      = -2,
+	/** Temporary failure in name resolution */
+	DNS_EAI_AGAIN       = -3,
+	/** Non-recoverable failure in name res */
+	DNS_EAI_FAIL        = -4,
+	/** No address associated with NAME */
+	DNS_EAI_NODATA      = -5,
+	/** `ai_family' not supported */
+	DNS_EAI_FAMILY      = -6,
+	/** `ai_socktype' not supported */
+	DNS_EAI_SOCKTYPE    = -7,
+	/** SRV not supported for `ai_socktype' */
+	DNS_EAI_SERVICE     = -8,
+	/** Address family for NAME not supported */
+	DNS_EAI_ADDRFAMILY  = -9,
+	/** Memory allocation failure */
+	DNS_EAI_MEMORY      = -10,
+	/** System error returned in `errno' */
+	DNS_EAI_SYSTEM      = -11,
+	/** Argument buffer overflow */
+	DNS_EAI_OVERFLOW    = -12,
+	/** Processing request in progress */
+	DNS_EAI_INPROGRESS  = -100,
+	/** Request canceled */
+	DNS_EAI_CANCELED    = -101,
+	/** Request not canceled */
+	DNS_EAI_NOTCANCELED = -102,
+	/** All requests done */
+	DNS_EAI_ALLDONE     = -103,
+	/** IDN encoding failed */
+	DNS_EAI_IDN_ENCODE  = -105,
+};
+
+/**
+ * @typedef dns_resolve_cb_t
+ * @brief DNS resolve callback
+ *
+ * @details The DNS resolve callback is called after a successful
+ * DNS resolving. The resolver can call this callback multiple times, one
+ * for each resolved address.
+ *
+ * @param status The status of the query:
+ *  DNS_EAI_INPROGRESS returned for each resolved address
+ *  DNS_EAI_ALLDONE    mark end of the resolving, info is set to NULL in
+ *                     this case
+ *  DNS_EAI_CANCELED   if the query was canceled manually or timeout happened
+ *  DNS_EAI_FAIL       if the name cannot be resolved by the server
+ *  DNS_EAI_NODATA     if there is no such name
+ *  other values means that an error happened.
+ * @param info Query results are stored here.
+ * @param user_data The user data given in dns_resolve_name() call.
+ */
+typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status,
+				 struct dns_addrinfo *info,
+				 void *user_data);
+
+/**
+ * DNS resolve context structure.
+ */
+struct dns_resolve_context {
+	struct {
+		/** DNS server information */
+		struct sockaddr dns_server;
+
+		/** Connection to the DNS server */
+		struct net_context *net_ctx;
+
+		/** Is this server mDNS one */
+		uint8_t is_mdns : 1;
+
+		/** Is this server LLMNR one */
+		uint8_t is_llmnr : 1;
+	} servers[CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS];
+
+	/** This timeout is also used when a buffer is required from the
+	 * buffer pools.
+	 */
+	k_timeout_t buf_timeout;
+
+	/** Result callbacks. We have multiple callbacks here so that it is
+	 * possible to do multiple queries at the same time.
+	 */
+	struct dns_pending_query {
+		/** Timeout timer */
+		struct k_delayed_work timer;
+
+		/** Back pointer to ctx, needed in timeout handler */
+		struct dns_resolve_context *ctx;
+
+		/** Result callback */
+		dns_resolve_cb_t cb;
+
+		/** User data */
+		void *user_data;
+
+		/** TX timeout */
+		k_timeout_t timeout;
+
+		/** String containing the thing to resolve like www.example.com
+		 */
+		const char *query;
+
+		/** Query type */
+		enum dns_query_type query_type;
+
+		/** DNS id of this query */
+		uint16_t id;
+
+		/** Hash of the DNS name + query type we are querying.
+		 * This hash is calculated so we can match the response that
+		 * we are receiving. This is needed mainly for mDNS which is
+		 * setting the DNS id to 0, which means that the id alone
+		 * cannot be used to find correct pending query.
+		 */
+		uint16_t query_hash;
+	} queries[CONFIG_DNS_NUM_CONCUR_QUERIES];
+
+	/** Is this context in use */
+	bool is_used;
+};
+
+/**
+ * @brief Init DNS resolving context.
+ *
+ * @details This function sets the DNS server address and initializes the
+ * DNS context that is used by the actual resolver. DNS server addresses
+ * can be specified either in textual form, or as struct sockaddr (or both).
+ * Note that the recommended way to resolve DNS names is to use
+ * the dns_get_addr_info() API. In that case user does not need to
+ * call dns_resolve_init() as the DNS servers are already setup by the system.
+ *
+ * @param ctx DNS context. If the context variable is allocated from
+ * the stack, then the variable needs to be valid for the whole duration of
+ * the resolving. Caller does not need to fill the variable beforehand or
+ * edit the context afterwards.
+ * @param dns_servers_str DNS server addresses using textual strings. The
+ * array is NULL terminated. The port number can be given in the string.
+ * Syntax for the server addresses with or without port numbers:
+ *    IPv4        : 10.0.9.1
+ *    IPv4 + port : 10.0.9.1:5353
+ *    IPv6        : 2001:db8::22:42
+ *    IPv6 + port : [2001:db8::22:42]:5353
+ * @param dns_servers_sa DNS server addresses as struct sockaddr. The array
+ * is NULL terminated. Port numbers are optional in struct sockaddr, the
+ * default will be used if set to 0.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int dns_resolve_init(struct dns_resolve_context *ctx,
+		     const char *dns_servers_str[],
+		     const struct sockaddr *dns_servers_sa[]);
+
+/**
+ * @brief Close DNS resolving context.
+ *
+ * @details This releases DNS resolving context and marks the context unusable.
+ * Caller must call the dns_resolve_init() again to make context usable.
+ *
+ * @param ctx DNS context
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int dns_resolve_close(struct dns_resolve_context *ctx);
+
+/**
+ * @brief Cancel a pending DNS query.
+ *
+ * @details This releases DNS resources used by a pending query.
+ *
+ * @param ctx DNS context
+ * @param dns_id DNS id of the pending query
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int dns_resolve_cancel(struct dns_resolve_context *ctx,
+		       uint16_t dns_id);
+
+/**
+ * @brief Cancel a pending DNS query using id, name and type.
+ *
+ * @details This releases DNS resources used by a pending query.
+ *
+ * @param ctx DNS context
+ * @param dns_id DNS id of the pending query
+ * @param query_name Name of the resource we are trying to query (hostname)
+ * @param query_type Type of the query (A or AAAA)
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx,
+				 uint16_t dns_id,
+				 const char *query_name,
+				 enum dns_query_type query_type);
+
+/**
+ * @brief Resolve DNS name.
+ *
+ * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
+ * Note that this is asynchronous call, the function will return immediately
+ * and system will call the callback after resolving has finished or timeout
+ * has occurred.
+ * We might send the query to multiple servers (if there are more than one
+ * server configured), but we only use the result of the first received
+ * response.
+ *
+ * @param ctx DNS context
+ * @param query What the caller wants to resolve.
+ * @param type What kind of data the caller wants to get.
+ * @param dns_id DNS id is returned to the caller. This is needed if one
+ * wishes to cancel the query. This can be set to NULL if there is no need
+ * to cancel the query.
+ * @param cb Callback to call after the resolving has finished or timeout
+ * has happened.
+ * @param user_data The user data.
+ * @param timeout The timeout value for the query. Possible values:
+ * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
+ *            manually if it takes too long time to finish
+ * >0: start the query and let the system timeout it after specified ms
+ *
+ * @return 0 if resolving was started ok, < 0 otherwise
+ */
+int dns_resolve_name(struct dns_resolve_context *ctx,
+		     const char *query,
+		     enum dns_query_type type,
+		     uint16_t *dns_id,
+		     dns_resolve_cb_t cb,
+		     void *user_data,
+		     int32_t timeout);
+
+/**
+ * @brief Get default DNS context.
+ *
+ * @details The system level DNS context uses DNS servers that are
+ * defined in project config file. If no DNS servers are defined by the
+ * user, then resolving DNS names using default DNS context will do nothing.
+ * The configuration options are described in subsys/net/lib/dns/Kconfig file.
+ *
+ * @return Default DNS context.
+ */
+struct dns_resolve_context *dns_resolve_get_default(void);
+
+/**
+ * @brief Get IP address info from DNS.
+ *
+ * @details This function can be used to resolve e.g., IPv4 or IPv6 address.
+ * Note that this is asynchronous call, the function will return immediately
+ * and system will call the callback after resolving has finished or timeout
+ * has occurred.
+ * We might send the query to multiple servers (if there are more than one
+ * server configured), but we only use the result of the first received
+ * response.
+ * This variant uses system wide DNS servers.
+ *
+ * @param query What the caller wants to resolve.
+ * @param type What kind of data the caller wants to get.
+ * @param dns_id DNS id is returned to the caller. This is needed if one
+ * wishes to cancel the query. This can be set to NULL if there is no need
+ * to cancel the query.
+ * @param cb Callback to call after the resolving has finished or timeout
+ * has happened.
+ * @param user_data The user data.
+ * @param timeout The timeout value for the connection. Possible values:
+ * SYS_FOREVER_MS: the query is tried forever, user needs to cancel it
+ *            manually if it takes too long time to finish
+ * >0: start the query and let the system timeout it after specified ms
+ *
+ * @return 0 if resolving was started ok, < 0 otherwise
+ */
+static inline int dns_get_addr_info(const char *query,
+				    enum dns_query_type type,
+				    uint16_t *dns_id,
+				    dns_resolve_cb_t cb,
+				    void *user_data,
+				    int32_t timeout)
+{
+	return dns_resolve_name(dns_resolve_get_default(),
+				query,
+				type,
+				dns_id,
+				cb,
+				user_data,
+				timeout);
+}
+
+/**
+ * @brief Cancel a pending DNS query.
+ *
+ * @details This releases DNS resources used by a pending query.
+ *
+ * @param dns_id DNS id of the pending query
+ *
+ * @return 0 if ok, <0 if error.
+ */
+static inline int dns_cancel_addr_info(uint16_t dns_id)
+{
+	return dns_resolve_cancel(dns_resolve_get_default(), dns_id);
+}
+
+/**
+ * @}
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+/**
+ * @brief Initialize DNS subsystem.
+ */
+#if defined(CONFIG_DNS_RESOLVER)
+void dns_init_resolver(void);
+
+#else
+#define dns_init_resolver(...)
+#endif /* CONFIG_DNS_RESOLVER */
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/dummy.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dummy.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/dummy.h	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#ifndef ZEPHYR_INCLUDE_NET_DUMMY_H_
+#define ZEPHYR_INCLUDE_NET_DUMMY_H_
+
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Dummy L2/driver support functions
+ * @defgroup dummy Dummy L2/driver Support Functions
+ * @ingroup networking
+ * @{
+ */
+
+struct dummy_api {
+	/**
+	 * The net_if_api must be placed in first position in this
+	 * struct so that we are compatible with network interface API.
+	 */
+	struct net_if_api iface_api;
+
+	/** Send a network packet */
+	int (*send)(const struct device *dev, struct net_pkt *pkt);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * dummy API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct dummy_api, iface_api) == 0);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_DUMMY_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ethernet.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet.h	(working copy)
@@ -0,0 +1,746 @@
+/** @file
+ @brief Ethernet
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_ETHERNET_H_
+#define ZEPHYR_INCLUDE_NET_ETHERNET_H_
+
+#include <kernel.h>
+#include <zephyr/types.h>
+#include <stdbool.h>
+#include <sys/atomic.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+
+#if defined(CONFIG_NET_LLDP)
+#include <net/lldp.h>
+#endif
+
+#include <sys/util.h>
+#include <net/net_if.h>
+#include <net/ethernet_vlan.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Ethernet support functions
+ * @defgroup ethernet Ethernet Support Functions
+ * @ingroup networking
+ * @{
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+struct net_eth_addr {
+	uint8_t addr[6];
+};
+
+#define NET_ETH_HDR(pkt) ((struct net_eth_hdr *)net_pkt_data(pkt))
+
+#define NET_ETH_PTYPE_ARP		0x0806
+#define NET_ETH_PTYPE_IP		0x0800
+#define NET_ETH_PTYPE_TSN		0x22f0 /* TSN (IEEE 1722) packet */
+#define NET_ETH_PTYPE_IPV6		0x86dd
+#define NET_ETH_PTYPE_VLAN		0x8100
+#define NET_ETH_PTYPE_PTP		0x88f7
+#define NET_ETH_PTYPE_LLDP		0x88cc
+#define NET_ETH_PTYPE_ALL               0x0003 /* from linux/if_ether.h */
+
+#if !defined(ETH_P_ALL)
+#define ETH_P_ALL	NET_ETH_PTYPE_ALL
+#endif
+#if !defined(ETH_P_IP)
+#define ETH_P_IP	NET_ETH_PTYPE_IP
+#endif
+#if !defined(ETH_P_ARP)
+#define ETH_P_ARP	NET_ETH_PTYPE_ARP
+#endif
+#if !defined(ETH_P_IPV6)
+#define ETH_P_IPV6	NET_ETH_PTYPE_IPV6
+#endif
+#if !defined(ETH_P_8021Q)
+#define ETH_P_8021Q	NET_ETH_PTYPE_VLAN
+#endif
+#if !defined(ETH_P_TSN)
+#define ETH_P_TSN	NET_ETH_PTYPE_TSN
+#endif
+
+#define NET_ETH_MINIMAL_FRAME_SIZE	60
+#define NET_ETH_MTU			1500
+#define NET_ETH_MAX_FRAME_SIZE	(NET_ETH_MTU + sizeof(struct net_eth_hdr))
+
+#define NET_ETH_VLAN_HDR_SIZE	4
+
+/** @endcond */
+
+/** Ethernet hardware capabilities */
+enum ethernet_hw_caps {
+	/** TX Checksum offloading supported for all of IPv4, UDP, TCP */
+	ETHERNET_HW_TX_CHKSUM_OFFLOAD	= BIT(0),
+
+	/** RX Checksum offloading supported for all of IPv4, UDP, TCP */
+	ETHERNET_HW_RX_CHKSUM_OFFLOAD	= BIT(1),
+
+	/** VLAN supported */
+	ETHERNET_HW_VLAN		= BIT(2),
+
+	/** Enabling/disabling auto negotiation supported */
+	ETHERNET_AUTO_NEGOTIATION_SET	= BIT(3),
+
+	/** 10 Mbits link supported */
+	ETHERNET_LINK_10BASE_T		= BIT(4),
+
+	/** 100 Mbits link supported */
+	ETHERNET_LINK_100BASE_T		= BIT(5),
+
+	/** 1 Gbits link supported */
+	ETHERNET_LINK_1000BASE_T	= BIT(6),
+
+	/** Changing duplex (half/full) supported */
+	ETHERNET_DUPLEX_SET		= BIT(7),
+
+	/** IEEE 802.1AS (gPTP) clock supported */
+	ETHERNET_PTP			= BIT(8),
+
+	/** IEEE 802.1Qav (credit-based shaping) supported */
+	ETHERNET_QAV			= BIT(9),
+
+	/** Promiscuous mode supported */
+	ETHERNET_PROMISC_MODE		= BIT(10),
+
+	/** Priority queues available */
+	ETHERNET_PRIORITY_QUEUES	= BIT(11),
+
+	/** MAC address filtering supported */
+	ETHERNET_HW_FILTERING		= BIT(12),
+
+	/** Link Layer Discovery Protocol supported */
+	ETHERNET_LLDP			= BIT(13),
+
+	/** VLAN Tag stripping */
+	ETHERNET_HW_VLAN_TAG_STRIP	= BIT(14),
+};
+
+/** @cond INTERNAL_HIDDEN */
+
+enum ethernet_config_type {
+	ETHERNET_CONFIG_TYPE_AUTO_NEG,
+	ETHERNET_CONFIG_TYPE_LINK,
+	ETHERNET_CONFIG_TYPE_DUPLEX,
+	ETHERNET_CONFIG_TYPE_MAC_ADDRESS,
+	ETHERNET_CONFIG_TYPE_QAV_PARAM,
+	ETHERNET_CONFIG_TYPE_PROMISC_MODE,
+	ETHERNET_CONFIG_TYPE_PRIORITY_QUEUES_NUM,
+	ETHERNET_CONFIG_TYPE_FILTER,
+};
+
+enum ethernet_qav_param_type {
+	ETHERNET_QAV_PARAM_TYPE_DELTA_BANDWIDTH,
+	ETHERNET_QAV_PARAM_TYPE_IDLE_SLOPE,
+	ETHERNET_QAV_PARAM_TYPE_OPER_IDLE_SLOPE,
+	ETHERNET_QAV_PARAM_TYPE_TRAFFIC_CLASS,
+	ETHERNET_QAV_PARAM_TYPE_STATUS,
+};
+
+/** @endcond */
+
+struct ethernet_qav_param {
+	/** ID of the priority queue to use */
+	int queue_id;
+	/** Type of Qav parameter */
+	enum ethernet_qav_param_type type;
+	union {
+		/** True if Qav is enabled for queue */
+		bool enabled;
+		/** Delta Bandwidth (percentage of bandwidth) */
+		unsigned int delta_bandwidth;
+		/** Idle Slope (bits per second) */
+		unsigned int idle_slope;
+		/** Oper Idle Slope (bits per second) */
+		unsigned int oper_idle_slope;
+		/** Traffic class the queue is bound to */
+		unsigned int traffic_class;
+	};
+};
+
+/** @cond INTERNAL_HIDDEN */
+
+enum ethernet_filter_type {
+	ETHERNET_FILTER_TYPE_SRC_MAC_ADDRESS,
+	ETHERNET_FILTER_TYPE_DST_MAC_ADDRESS,
+};
+
+/** @endcond */
+
+struct ethernet_filter {
+	/** Type of filter */
+	enum ethernet_filter_type type;
+	/** MAC address to filter */
+	struct net_eth_addr mac_address;
+	/** Set (true) or unset (false) the filter */
+	bool set;
+};
+
+/** @cond INTERNAL_HIDDEN */
+struct ethernet_config {
+	union {
+		bool auto_negotiation;
+		bool full_duplex;
+		bool promisc_mode;
+
+		struct {
+			bool link_10bt;
+			bool link_100bt;
+			bool link_1000bt;
+		} l;
+
+		struct net_eth_addr mac_address;
+
+		struct ethernet_qav_param qav_param;
+
+		int priority_queues_num;
+
+		struct ethernet_filter filter;
+	};
+};
+/** @endcond */
+
+struct ethernet_api {
+	/**
+	 * The net_if_api must be placed in first position in this
+	 * struct so that we are compatible with network interface API.
+	 */
+	struct net_if_api iface_api;
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET)
+	/** Collect optional ethernet specific statistics. This pointer
+	 * should be set by driver if statistics needs to be collected
+	 * for that driver.
+	 */
+	struct net_stats_eth *(*get_stats)(const struct device *dev);
+#endif
+
+	/** Start the device */
+	int (*start)(const struct device *dev);
+
+	/** Stop the device */
+	int (*stop)(const struct device *dev);
+
+	/** Get the device capabilities */
+	enum ethernet_hw_caps (*get_capabilities)(const struct device *dev);
+
+	/** Set specific hardware configuration */
+	int (*set_config)(const struct device *dev,
+			  enum ethernet_config_type type,
+			  const struct ethernet_config *config);
+
+	/** Get hardware specific configuration */
+	int (*get_config)(const struct device *dev,
+			  enum ethernet_config_type type,
+			  struct ethernet_config *config);
+
+#if defined(CONFIG_NET_VLAN)
+	/** The IP stack will call this function when a VLAN tag is enabled
+	 * or disabled. If enable is set to true, then the VLAN tag was added,
+	 * if it is false then the tag was removed. The driver can utilize
+	 * this information if needed.
+	 */
+	int (*vlan_setup)(const struct device *dev, struct net_if *iface,
+			  uint16_t tag, bool enable);
+#endif /* CONFIG_NET_VLAN */
+
+#if defined(CONFIG_PTP_CLOCK)
+	/** Return ptp_clock device that is tied to this ethernet device */
+	const struct device *(*get_ptp_clock)(const struct device *dev);
+#endif /* CONFIG_PTP_CLOCK */
+
+	/** Send a network packet */
+	int (*send)(const struct device *dev, struct net_pkt *pkt);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * Ethernet API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct ethernet_api, iface_api) == 0);
+
+/** @cond INTERNAL_HIDDEN */
+struct net_eth_hdr {
+	struct net_eth_addr dst;
+	struct net_eth_addr src;
+	uint16_t type;
+} __packed;
+
+struct ethernet_vlan {
+	/** Network interface that has VLAN enabled */
+	struct net_if *iface;
+
+	/** VLAN tag */
+	uint16_t tag;
+};
+
+#if defined(CONFIG_NET_VLAN_COUNT)
+#define NET_VLAN_MAX_COUNT CONFIG_NET_VLAN_COUNT
+#else
+/* Even thou there are no VLAN support, the minimum count must be set to 1.
+ */
+#define NET_VLAN_MAX_COUNT 1
+#endif
+
+/** @endcond */
+
+#if defined(CONFIG_NET_LLDP)
+struct ethernet_lldp {
+	/** Used for track timers */
+	sys_snode_t node;
+
+	/** LLDP Data Unit mandatory TLVs for the interface. */
+	const struct net_lldpdu *lldpdu;
+
+	/** LLDP Data Unit optional TLVs for the interface */
+	const uint8_t *optional_du;
+
+	/** Length of the optional Data Unit TLVs */
+	size_t optional_len;
+
+	/** Network interface that has LLDP supported. */
+	struct net_if *iface;
+
+	/** LLDP TX timer start time */
+	int64_t tx_timer_start;
+
+	/** LLDP TX timeout */
+	uint32_t tx_timer_timeout;
+
+	/** LLDP RX callback function */
+	net_lldp_recv_cb_t cb;
+};
+#endif /* CONFIG_NET_LLDP */
+
+/** Ethernet L2 context that is needed for VLAN */
+struct ethernet_context {
+#if defined(CONFIG_NET_VLAN)
+	struct ethernet_vlan vlan[NET_VLAN_MAX_COUNT];
+
+	/** Array that will help when checking if VLAN is enabled for
+	 * some specific network interface. Requires that VLAN count
+	 * NET_VLAN_MAX_COUNT is not smaller than the actual number
+	 * of network interfaces.
+	 */
+	ATOMIC_DEFINE(interfaces, NET_VLAN_MAX_COUNT);
+#endif
+
+	struct {
+		/** Carrier ON/OFF handler worker. This is used to create
+		 * network interface UP/DOWN event when ethernet L2 driver
+		 * notices carrier ON/OFF situation. We must not create another
+		 * network management event from inside management handler thus
+		 * we use worker thread to trigger the UP/DOWN event.
+		 */
+		struct k_work work;
+
+		/** Network interface that is detecting carrier ON/OFF event.
+		 */
+		struct net_if *iface;
+	} carrier_mgmt;
+
+#if defined(CONFIG_NET_LLDP)
+	struct ethernet_lldp lldp[NET_VLAN_MAX_COUNT];
+#endif
+
+	/**
+	 * This tells what L2 features does ethernet support.
+	 */
+	enum net_l2_flags ethernet_l2_flags;
+
+#if defined(CONFIG_NET_GPTP)
+	/** The gPTP port number for this network device. We need to store the
+	 * port number here so that we do not need to fetch it for every
+	 * incoming gPTP packet.
+	 */
+	int port;
+#endif
+
+#if defined(CONFIG_NET_VLAN)
+	/** Flag that tells whether how many VLAN tags are enabled for this
+	 * context. The same information can be dug from the vlan array but
+	 * this saves some time in RX path.
+	 */
+	int8_t vlan_enabled;
+#endif
+
+	/** Is this context already initialized */
+	bool is_init;
+};
+
+/**
+ * @brief Initialize Ethernet L2 stack for a given interface
+ *
+ * @param iface A valid pointer to a network interface
+ */
+void ethernet_init(struct net_if *iface);
+
+/** @cond INTERNAL_HIDDEN */
+
+#define ETHERNET_L2_CTX_TYPE	struct ethernet_context
+
+/* Separate header for VLAN as some of device interfaces might not
+ * support VLAN.
+ */
+struct net_eth_vlan_hdr {
+	struct net_eth_addr dst;
+	struct net_eth_addr src;
+	struct {
+		uint16_t tpid; /* tag protocol id  */
+		uint16_t tci;  /* tag control info */
+	} vlan;
+	uint16_t type;
+} __packed;
+
+
+static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr)
+{
+	if (addr->addr[0] == 0xff &&
+	    addr->addr[1] == 0xff &&
+	    addr->addr[2] == 0xff &&
+	    addr->addr[3] == 0xff &&
+	    addr->addr[4] == 0xff &&
+	    addr->addr[5] == 0xff) {
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool net_eth_is_addr_unspecified(struct net_eth_addr *addr)
+{
+	if (addr->addr[0] == 0x00 &&
+	    addr->addr[1] == 0x00 &&
+	    addr->addr[2] == 0x00 &&
+	    addr->addr[3] == 0x00 &&
+	    addr->addr[4] == 0x00 &&
+	    addr->addr[5] == 0x00) {
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool net_eth_is_addr_multicast(struct net_eth_addr *addr)
+{
+#if defined(CONFIG_NET_IPV6)
+	if (addr->addr[0] == 0x33 &&
+	    addr->addr[1] == 0x33) {
+		return true;
+	}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+	if (addr->addr[0] == 0x01 &&
+	    addr->addr[1] == 0x00 &&
+	    addr->addr[2] == 0x5e) {
+		return true;
+	}
+#endif
+
+	return false;
+}
+
+static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr)
+{
+#if defined(CONFIG_NET_GPTP) || defined(CONFIG_NET_LLDP)
+	if (addr->addr[0] == 0x01 &&
+	    addr->addr[1] == 0x80 &&
+	    addr->addr[2] == 0xc2 &&
+	    addr->addr[3] == 0x00 &&
+	    addr->addr[4] == 0x00 &&
+	    addr->addr[5] == 0x0e) {
+		return true;
+	}
+#endif
+
+	return false;
+}
+
+const struct net_eth_addr *net_eth_broadcast_addr(void);
+
+/** @endcond */
+
+/**
+ * @brief Convert IPv6 multicast address to Ethernet address.
+ *
+ * @param ipv6_addr IPv6 multicast address
+ * @param mac_addr Output buffer for Ethernet address
+ */
+void net_eth_ipv6_mcast_to_mac_addr(const struct in6_addr *ipv6_addr,
+				    struct net_eth_addr *mac_addr);
+
+/**
+ * @brief Return ethernet device hardware capability information.
+ *
+ * @param iface Network interface
+ *
+ * @return Hardware capabilities
+ */
+static inline
+enum ethernet_hw_caps net_eth_get_hw_capabilities(struct net_if *iface)
+{
+	const struct ethernet_api *eth =
+		(struct ethernet_api *)net_if_get_device(iface)->api;
+
+	if (!eth->get_capabilities) {
+		return (enum ethernet_hw_caps)0;
+	}
+
+	return eth->get_capabilities(net_if_get_device(iface));
+}
+
+/**
+ * @brief Add VLAN tag to the interface.
+ *
+ * @param iface Interface to use.
+ * @param tag VLAN tag to add
+ *
+ * @return 0 if ok, <0 if error
+ */
+#if defined(CONFIG_NET_VLAN)
+int net_eth_vlan_enable(struct net_if *iface, uint16_t tag);
+#else
+static inline int net_eth_vlan_enable(struct net_if *iface, uint16_t tag)
+{
+	return -EINVAL;
+}
+#endif
+
+/**
+ * @brief Remove VLAN tag from the interface.
+ *
+ * @param iface Interface to use.
+ * @param tag VLAN tag to remove
+ *
+ * @return 0 if ok, <0 if error
+ */
+#if defined(CONFIG_NET_VLAN)
+int net_eth_vlan_disable(struct net_if *iface, uint16_t tag);
+#else
+static inline int net_eth_vlan_disable(struct net_if *iface, uint16_t tag)
+{
+	return -EINVAL;
+}
+#endif
+
+/**
+ * @brief Return VLAN tag specified to network interface
+ *
+ * @param iface Network interface.
+ *
+ * @return VLAN tag for this interface or NET_VLAN_TAG_UNSPEC if VLAN
+ * is not configured for that interface.
+ */
+#if defined(CONFIG_NET_VLAN)
+uint16_t net_eth_get_vlan_tag(struct net_if *iface);
+#else
+static inline uint16_t net_eth_get_vlan_tag(struct net_if *iface)
+{
+	return NET_VLAN_TAG_UNSPEC;
+}
+#endif
+
+/**
+ * @brief Return network interface related to this VLAN tag
+ *
+ * @param iface Master network interface. This is used to get the
+ *        pointer to ethernet L2 context
+ * @param tag VLAN tag
+ *
+ * @return Network interface related to this tag or NULL if no such interface
+ * exists.
+ */
+#if defined(CONFIG_NET_VLAN)
+struct net_if *net_eth_get_vlan_iface(struct net_if *iface, uint16_t tag);
+#else
+static inline
+struct net_if *net_eth_get_vlan_iface(struct net_if *iface, uint16_t tag)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Check if VLAN is enabled for a specific network interface.
+ *
+ * @param ctx Ethernet context
+ * @param iface Network interface
+ *
+ * @return True if VLAN is enabled for this network interface, false if not.
+ */
+#if defined(CONFIG_NET_VLAN)
+bool net_eth_is_vlan_enabled(struct ethernet_context *ctx,
+			     struct net_if *iface);
+#else
+static inline bool net_eth_is_vlan_enabled(struct ethernet_context *ctx,
+					   struct net_if *iface)
+{
+	return false;
+}
+#endif
+
+/**
+ * @brief Get VLAN status for a given network interface (enabled or not).
+ *
+ * @param iface Network interface
+ *
+ * @return True if VLAN is enabled for this network interface, false if not.
+ */
+#if defined(CONFIG_NET_VLAN)
+bool net_eth_get_vlan_status(struct net_if *iface);
+#else
+static inline bool net_eth_get_vlan_status(struct net_if *iface)
+{
+	return false;
+}
+#endif
+
+/**
+ * @def ETH_NET_DEVICE_INIT
+ *
+ * @brief Create an Ethernet network interface and bind it to network device.
+ *
+ * @param dev_name Network device name.
+ * @param drv_name The name this instance of the driver exposes to
+ * the system.
+ * @param init_fn Address to the init function of the driver.
+ * @param pm_control_fn Pointer to device_pm_control function.
+ * Can be empty function (device_pm_control_nop) if not implemented.
+ * @param data Pointer to the device's private data.
+ * @param cfg The address to the structure containing the
+ * configuration information for this instance of the driver.
+ * @param prio The initialization level at which configuration occurs.
+ * @param api Provides an initial pointer to the API function struct
+ * used by the driver. Can be NULL.
+ * @param mtu Maximum transfer unit in bytes for this network interface.
+ */
+#if defined(CONFIG_NET_VLAN)
+#define ETH_NET_DEVICE_INIT(dev_name, drv_name, init_fn, pm_control_fn,	\
+			    data, cfg, prio, api, mtu)			\
+	DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, data,	\
+		      cfg, POST_KERNEL, prio, api);			\
+	NET_L2_DATA_INIT(dev_name, 0, NET_L2_GET_CTX_TYPE(ETHERNET_L2)); \
+	NET_IF_INIT(dev_name, 0, ETHERNET_L2, mtu, NET_VLAN_MAX_COUNT)
+
+#else /* CONFIG_NET_VLAN */
+
+#define ETH_NET_DEVICE_INIT(dev_name, drv_name, init_fn, pm_control_fn,	\
+			    data, cfg, prio, api, mtu)			\
+	NET_DEVICE_INIT(dev_name, drv_name, init_fn, pm_control_fn,	\
+			data, cfg, prio, api, ETHERNET_L2,		\
+			NET_L2_GET_CTX_TYPE(ETHERNET_L2), mtu)
+
+#endif /* CONFIG_NET_VLAN */
+
+/**
+ * @brief Inform ethernet L2 driver that ethernet carrier is detected.
+ * This happens when cable is connected.
+ *
+ * @param iface Network interface
+ */
+void net_eth_carrier_on(struct net_if *iface);
+
+/**
+ * @brief Inform ethernet L2 driver that ethernet carrier was lost.
+ * This happens when cable is disconnected.
+ *
+ * @param iface Network interface
+ */
+void net_eth_carrier_off(struct net_if *iface);
+
+/**
+ * @brief Set promiscuous mode either ON or OFF.
+ *
+ * @param iface Network interface
+ *
+ * @param enable on (true) or off (false)
+ *
+ * @return 0 if mode set or unset was successful, <0 otherwise.
+ */
+int net_eth_promisc_mode(struct net_if *iface, bool enable);
+
+/**
+ * @brief Return PTP clock that is tied to this ethernet network interface.
+ *
+ * @param iface Network interface
+ *
+ * @return Pointer to PTP clock if found, NULL if not found or if this
+ * ethernet interface does not support PTP.
+ */
+#if defined(CONFIG_PTP_CLOCK)
+const struct device *net_eth_get_ptp_clock(struct net_if *iface);
+#else
+static inline const struct device *net_eth_get_ptp_clock(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Return PTP clock that is tied to this ethernet network interface
+ * index.
+ *
+ * @param index Network interface index
+ *
+ * @return Pointer to PTP clock if found, NULL if not found or if this
+ * ethernet interface index does not support PTP.
+ */
+__syscall const struct device *net_eth_get_ptp_clock_by_index(int index);
+
+/**
+ * @brief Return gPTP port number attached to this interface.
+ *
+ * @param iface Network interface
+ *
+ * @return Port number, no such port if < 0
+ */
+#if defined(CONFIG_NET_GPTP)
+int net_eth_get_ptp_port(struct net_if *iface);
+#else
+static inline int net_eth_get_ptp_port(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+
+	return -ENODEV;
+}
+#endif /* CONFIG_NET_GPTP */
+
+/**
+ * @brief Set gPTP port number attached to this interface.
+ *
+ * @param iface Network interface
+ * @param port Port number to set
+ */
+#if defined(CONFIG_NET_GPTP)
+void net_eth_set_ptp_port(struct net_if *iface, int port);
+#endif /* CONFIG_NET_GPTP */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/ethernet.h>
+
+#endif /* ZEPHYR_INCLUDE_NET_ETHERNET_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ethernet_mgmt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet_mgmt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet_mgmt.h	(working copy)
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Ethernet Management interface public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_ETHERNET_MGMT_H_
+#define ZEPHYR_INCLUDE_NET_ETHERNET_MGMT_H_
+
+#include <net/ethernet.h>
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Ethernet library
+ * @defgroup ethernet_mgmt Ethernet Library
+ * @ingroup networking
+ * @{
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+#define _NET_ETHERNET_LAYER	NET_MGMT_LAYER_L2
+#define _NET_ETHERNET_CODE	0x208
+#define _NET_ETHERNET_BASE	(NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_ETHERNET_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_ETHERNET_CODE))
+#define _NET_ETHERNET_EVENT	(_NET_ETHERNET_BASE | NET_MGMT_EVENT_BIT)
+
+enum net_request_ethernet_cmd {
+	NET_REQUEST_ETHERNET_CMD_SET_AUTO_NEGOTIATION = 1,
+	NET_REQUEST_ETHERNET_CMD_SET_LINK,
+	NET_REQUEST_ETHERNET_CMD_SET_DUPLEX,
+	NET_REQUEST_ETHERNET_CMD_SET_MAC_ADDRESS,
+	NET_REQUEST_ETHERNET_CMD_SET_QAV_PARAM,
+	NET_REQUEST_ETHERNET_CMD_SET_PROMISC_MODE,
+	NET_REQUEST_ETHERNET_CMD_GET_PRIORITY_QUEUES_NUM,
+	NET_REQUEST_ETHERNET_CMD_GET_QAV_PARAM,
+};
+
+#define NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION			\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_AUTO_NEGOTIATION)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION);
+
+#define NET_REQUEST_ETHERNET_SET_LINK					\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_LINK)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_LINK);
+
+#define NET_REQUEST_ETHERNET_SET_DUPLEX					\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_DUPLEX)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_DUPLEX);
+
+#define NET_REQUEST_ETHERNET_SET_MAC_ADDRESS				\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_MAC_ADDRESS)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS);
+
+#define NET_REQUEST_ETHERNET_SET_QAV_PARAM				\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_QAV_PARAM)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_QAV_PARAM);
+
+#define NET_REQUEST_ETHERNET_SET_PROMISC_MODE				\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_SET_PROMISC_MODE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_PROMISC_MODE);
+
+#define NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM			\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_GET_PRIORITY_QUEUES_NUM)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM);
+
+#define NET_REQUEST_ETHERNET_GET_QAV_PARAM				\
+	(_NET_ETHERNET_BASE | NET_REQUEST_ETHERNET_CMD_GET_QAV_PARAM)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_ETHERNET_GET_QAV_PARAM);
+
+struct net_eth_addr;
+struct ethernet_qav_param;
+
+struct ethernet_req_params {
+	union {
+		bool auto_negotiation;
+		bool full_duplex;
+		bool promisc_mode;
+
+		struct {
+			bool link_10bt;
+			bool link_100bt;
+			bool link_1000bt;
+		} l;
+
+		struct net_eth_addr mac_address;
+
+		struct ethernet_qav_param qav_param;
+
+		int priority_queues_num;
+	};
+};
+
+enum net_event_ethernet_cmd {
+	NET_EVENT_ETHERNET_CMD_CARRIER_ON = 1,
+	NET_EVENT_ETHERNET_CMD_CARRIER_OFF,
+	NET_EVENT_ETHERNET_CMD_VLAN_TAG_ENABLED,
+	NET_EVENT_ETHERNET_CMD_VLAN_TAG_DISABLED,
+};
+
+#define NET_EVENT_ETHERNET_CARRIER_ON					\
+	(_NET_ETHERNET_EVENT | NET_EVENT_ETHERNET_CMD_CARRIER_ON)
+
+#define NET_EVENT_ETHERNET_CARRIER_OFF					\
+	(_NET_ETHERNET_EVENT | NET_EVENT_ETHERNET_CMD_CARRIER_OFF)
+
+#define NET_EVENT_ETHERNET_VLAN_TAG_ENABLED				\
+	(_NET_ETHERNET_EVENT | NET_EVENT_ETHERNET_CMD_VLAN_TAG_ENABLED)
+
+#define NET_EVENT_ETHERNET_VLAN_TAG_DISABLED				\
+	(_NET_ETHERNET_EVENT | NET_EVENT_ETHERNET_CMD_VLAN_TAG_DISABLED)
+
+struct net_if;
+
+/** @endcond */
+
+/**
+ * @brief Raise CARRIER_ON event when Ethernet is connected.
+ *
+ * @param iface Ethernet network interface.
+ */
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+void ethernet_mgmt_raise_carrier_on_event(struct net_if *iface);
+#else
+static inline void ethernet_mgmt_raise_carrier_on_event(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif
+
+/**
+ * @brief Raise CARRIER_OFF event when Ethernet is disconnected.
+ *
+ * @param iface Ethernet network interface.
+ */
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+void ethernet_mgmt_raise_carrier_off_event(struct net_if *iface);
+#else
+static inline void ethernet_mgmt_raise_carrier_off_event(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif
+
+/**
+ * @brief Raise VLAN_ENABLED event when VLAN is enabled.
+ *
+ * @param iface Ethernet network interface.
+ * @param tag VLAN tag which is enabled.
+ */
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+void ethernet_mgmt_raise_vlan_enabled_event(struct net_if *iface, uint16_t tag);
+#else
+static inline void ethernet_mgmt_raise_vlan_enabled_event(struct net_if *iface,
+							  uint16_t tag)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(tag);
+}
+#endif
+
+/**
+ * @brief Raise VLAN_DISABLED event when VLAN is disabled.
+ *
+ * @param iface Ethernet network interface.
+ * @param tag VLAN tag which is disabled.
+ */
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+void ethernet_mgmt_raise_vlan_disabled_event(struct net_if *iface,
+					     uint16_t tag);
+#else
+static inline void ethernet_mgmt_raise_vlan_disabled_event(struct net_if *iface,
+							   uint16_t tag)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(tag);
+}
+#endif
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_ETHERNET_MGMT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ethernet_vlan.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet_vlan.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ethernet_vlan.h	(working copy)
@@ -0,0 +1,116 @@
+/** @file
+ * @brief VLAN specific definitions.
+ *
+ * Virtual LAN specific definitions.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_ETHERNET_VLAN_H_
+#define ZEPHYR_INCLUDE_NET_ETHERNET_VLAN_H_
+
+/**
+ * @brief VLAN definitions and helpers
+ * @defgroup vlan_api Virtual LAN definitions and helpers
+ * @ingroup networking
+ * @{
+ */
+
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Unspecified VLAN tag value */
+#define NET_VLAN_TAG_UNSPEC 0x0fff
+
+/**
+ * @brief Get VLAN identifier from TCI.
+ *
+ * @param tci VLAN tag control information.
+ *
+ * @return VLAN identifier.
+ */
+static inline uint16_t net_eth_vlan_get_vid(uint16_t tci)
+{
+	return tci & 0x0fff;
+}
+
+/**
+ * @brief Get Drop Eligible Indicator from TCI.
+ *
+ * @param tci VLAN tag control information.
+ *
+ * @return Drop eligible indicator.
+ */
+static inline uint8_t net_eth_vlan_get_dei(uint16_t tci)
+{
+	return (tci >> 12) & 0x01;
+}
+
+/**
+ * @brief Get Priority Code Point from TCI.
+ *
+ * @param tci VLAN tag control information.
+ *
+ * @return Priority code point.
+ */
+static inline uint8_t net_eth_vlan_get_pcp(uint16_t tci)
+{
+	return (tci >> 13) & 0x07;
+}
+
+/**
+ * @brief Set VLAN identifier to TCI.
+ *
+ * @param tci VLAN tag control information.
+ * @param vid VLAN identifier.
+ *
+ * @return New TCI value.
+ */
+static inline uint16_t net_eth_vlan_set_vid(uint16_t tci, uint16_t vid)
+{
+	return (tci & 0xf000) | (vid & 0x0fff);
+}
+
+/**
+ * @brief Set Drop Eligible Indicator to TCI.
+ *
+ * @param tci VLAN tag control information.
+ * @param dei Drop eligible indicator.
+ *
+ * @return New TCI value.
+ */
+static inline uint16_t net_eth_vlan_set_dei(uint16_t tci, bool dei)
+{
+	return (tci & 0xefff) | ((!!dei) << 12);
+}
+
+/**
+ * @brief Set Priority Code Point to TCI.
+ *
+ * @param tci VLAN tag control information.
+ * @param pcp Priority code point.
+ *
+ * @return New TCI value.
+ */
+static inline uint16_t net_eth_vlan_set_pcp(uint16_t tci, uint8_t pcp)
+{
+	return (tci & 0x1fff) | ((pcp & 0x07) << 13);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+
+#endif /* ZEPHYR_INCLUDE_NET_ETHERNET_VLAN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/gptp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/gptp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/gptp.h	(working copy)
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public functions for the Precision Time Protocol Stack.
+ *
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_GPTP_H_
+#define ZEPHYR_INCLUDE_NET_GPTP_H_
+
+/**
+ * @brief generic Precision Time Protocol (gPTP) support
+ * @defgroup gptp gPTP support
+ * @ingroup networking
+ * @{
+ */
+
+#include <net/net_core.h>
+#include <net/ptp_time.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+
+#define GPTP_OFFSET_SCALED_LOG_VAR_UNKNOWN 0x436A
+
+#define GPTP_PRIORITY1_NON_GM_CAPABLE      255
+#define GPTP_PRIORITY1_GM_CAPABLE          248
+
+#if defined(CONFIG_NET_GPTP_BMCA_PRIORITY2)
+#define GPTP_PRIORITY2_DEFAULT             CONFIG_NET_GPTP_BMCA_PRIORITY2
+#else
+#define GPTP_PRIORITY2_DEFAULT             248
+#endif
+
+/** @endcond */
+
+/**
+ * @brief Scaled Nanoseconds.
+ */
+struct gptp_scaled_ns {
+	/** High half. */
+	int32_t high;
+
+	/** Low half. */
+	int64_t low;
+} __packed;
+
+/**
+ * @brief UScaled Nanoseconds.
+ */
+struct gptp_uscaled_ns {
+	/** High half. */
+	uint32_t high;
+
+	/** Low half. */
+	uint64_t low;
+} __packed;
+
+/** @cond INTERNAL_HIDDEN */
+
+#if defined(CONFIG_NEWLIB_LIBC)
+#include <math.h>
+
+#define GPTP_POW2(exp) pow(2, exp)
+#else
+
+static inline double gptp_pow2(int exp)
+{
+	double res;
+
+	if (exp >= 0) {
+		res = 1 << exp;
+	} else {
+		res = 1.0;
+
+		while (exp++) {
+			res /= 2;
+		}
+	}
+
+	return res;
+}
+
+#define GPTP_POW2(exp) gptp_pow2(exp)
+#endif
+
+/* Pre-calculated constants */
+/* 2^16 */
+#define GPTP_POW2_16	65536.0
+/* 2^41 */
+#define GPTP_POW2_41	2199023255552.0
+
+/* Message types. Event messages have BIT(3) set to 0, and general messages
+ * have that bit set to 1. IEEE 802.1AS chapter 10.5.2.2.2
+ */
+#define GPTP_SYNC_MESSAGE                0x00
+#define GPTP_DELAY_REQ_MESSAGE           0x01
+#define GPTP_PATH_DELAY_REQ_MESSAGE      0x02
+#define GPTP_PATH_DELAY_RESP_MESSAGE     0x03
+#define GPTP_FOLLOWUP_MESSAGE            0x08
+#define GPTP_DELAY_RESP_MESSAGE          0x09
+#define GPTP_PATH_DELAY_FOLLOWUP_MESSAGE 0x0a
+#define GPTP_ANNOUNCE_MESSAGE            0x0b
+#define GPTP_SIGNALING_MESSAGE           0x0c
+#define GPTP_MANAGEMENT_MESSAGE          0x0d
+
+#define GPTP_IS_EVENT_MSG(msg_type)      (!((msg_type) & BIT(3)))
+
+#define GPTP_CLOCK_ID_LEN                8
+
+/** @endcond */
+
+/**
+ * @brief Port Identity.
+ */
+struct gptp_port_identity {
+	/** Clock identity of the port. */
+	uint8_t clk_id[GPTP_CLOCK_ID_LEN];
+
+	/** Number of the port. */
+	uint16_t port_number;
+} __packed;
+
+struct gptp_flags {
+	union {
+		/** Byte access. */
+		uint8_t octets[2];
+
+		/** Whole field access. */
+		uint16_t all;
+	};
+} __packed;
+
+struct gptp_hdr {
+	/** Type of the message. */
+	uint8_t message_type:4;
+
+	/** Transport specific, always 1. */
+	uint8_t transport_specific:4;
+
+	/** Version of the PTP, always 2. */
+	uint8_t ptp_version:4;
+
+	/** Reserved field. */
+	uint8_t reserved0:4;
+
+	/** Total length of the message from the header to the last TLV. */
+	uint16_t message_length;
+
+	/** Domain number, always 0. */
+	uint8_t domain_number;
+
+	/** Reserved field. */
+	uint8_t reserved1;
+
+	/** Message flags. */
+	struct gptp_flags flags;
+
+	/** Correction Field. The content depends of the message type. */
+	int64_t correction_field;
+
+	/** Reserved field. */
+	uint32_t reserved2;
+
+	/** Port Identity of the sender. */
+	struct gptp_port_identity port_id;
+
+	/** Sequence Id. */
+	uint16_t sequence_id;
+
+	/** Control value. Sync: 0, Follow-up: 2, Others: 5. */
+	uint8_t control;
+
+	/** Message Interval in Log2 for Sync and Announce messages. */
+	int8_t log_msg_interval;
+} __packed;
+
+/** @cond INTERNAL_HIDDEN */
+
+#define GPTP_GET_CURRENT_TIME_USCALED_NS(port, uscaled_ns_ptr)		\
+	do {								\
+		(uscaled_ns_ptr)->low =					\
+			gptp_get_current_time_nanosecond(port) << 16;	\
+		(uscaled_ns_ptr)->high = 0;				\
+	} while (false)
+
+/** @endcond */
+
+/**
+ * @typedef gptp_phase_dis_callback_t
+ * @brief Define callback that is called after a phase discontinuity has been
+ *        sent by the grandmaster.
+ * @param "uint8_t *gm_identity" A pointer to first element of a
+ *        ClockIdentity array. The size of the array is GPTP_CLOCK_ID_LEN.
+ * @param "uint16_t *gm_time_base" A pointer to the value of timeBaseIndicator
+ *        of the current grandmaster.
+ * @param "struct scaled_ns *last_gm_ph_change" A pointer to the value of
+ *        lastGmPhaseChange received from grandmaster.
+ * @param "double *last_gm_freq_change" A pointer to the value of
+ *        lastGmFreqChange received from the grandmaster.
+ */
+typedef void (*gptp_phase_dis_callback_t)(
+	uint8_t *gm_identity,
+	uint16_t *time_base,
+	struct gptp_scaled_ns *last_gm_ph_change,
+	double *last_gm_freq_change);
+
+/**
+ * @brief Phase discontinuity callback structure.
+ *
+ * Stores the phase discontinuity callback information. Caller must make sure
+ * that the variable pointed by this is valid during the lifetime of
+ * registration. Typically this means that the variable cannot be
+ * allocated from stack.
+ */
+struct gptp_phase_dis_cb {
+	/** Node information for the slist. */
+	sys_snode_t node;
+
+	/** Phase discontinuity callback. */
+	gptp_phase_dis_callback_t cb;
+};
+
+/**
+ * @brief ClockSourceTime.invoke function parameters
+ *
+ * Parameters passed by ClockSourceTime.invoke function.
+ */
+struct gptp_clk_src_time_invoke_params {
+	/** Frequency change on the last Time Base Indicator Change. */
+	double last_gm_freq_change;
+
+	/** The time this function is invoked. */
+	struct net_ptp_extended_time src_time;
+
+	/** Phase change on the last Time Base Indicator Change. */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Time Base - changed only if Phase or Frequency changes. */
+	uint16_t time_base_indicator;
+};
+
+/**
+ * @brief Register a phase discontinuity callback.
+ *
+ * @param phase_dis Caller specified handler for the callback.
+ * @param cb Callback to register.
+ */
+void gptp_register_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis,
+				gptp_phase_dis_callback_t cb);
+
+/**
+ * @brief Unregister a phase discontinuity callback.
+ *
+ * @param phase_dis Caller specified handler for the callback.
+ */
+void gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis);
+
+/**
+ * @brief Call a phase discontinuity callback function.
+ */
+void gptp_call_phase_dis_cb(void);
+
+/**
+ * @brief Get gPTP time.
+ *
+ * @param slave_time A pointer to structure where timestamp will be saved.
+ * @param gm_present A pointer to a boolean where status of the
+ *        presence of a grand master will be saved.
+ *
+ * @return Error code. 0 if no error.
+ */
+int gptp_event_capture(struct net_ptp_time *slave_time, bool *gm_present);
+
+/**
+ * @brief Utility function to print clock id to a user supplied buffer.
+ *
+ * @param clk_id Clock id
+ * @param output Output buffer
+ * @param output_len Output buffer len
+ *
+ * @return Pointer to output buffer
+ */
+char *gptp_sprint_clock_id(const uint8_t *clk_id, char *output,
+			   size_t output_len);
+
+/**
+ * @typedef gptp_port_cb_t
+ * @brief Callback used while iterating over gPTP ports
+ *
+ * @param port Port number
+ * @param iface Pointer to network interface
+ * @param user_data A valid pointer to user data or NULL
+ */
+typedef void (*gptp_port_cb_t)(int port, struct net_if *iface,
+			       void *user_data);
+
+/**
+ * @brief Go through all the gPTP ports and call callback for each of them.
+ *
+ * @param cb User-supplied callback function to call
+ * @param user_data User specified data
+ */
+void gptp_foreach_port(gptp_port_cb_t cb, void *user_data);
+
+/**
+ * @brief Get gPTP domain.
+ * @details This contains all the configuration / status of the gPTP domain.
+ *
+ * @return Pointer to domain or NULL if not found.
+ */
+struct gptp_domain *gptp_get_domain(void);
+
+/**
+ * @brief This interface is used by the ClockSource entity to provide time to
+ *        the ClockMaster entity of a time-aware system.
+ *
+ * @param arg Current state and parameters of the ClockSource entity.
+ */
+void gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params *arg);
+
+/**
+ * @brief Return pointer to gPTP packet header in network packet.
+ *
+ * @param pkt Network packet (received or sent)
+ *
+ * @return Pointer to gPTP header.
+ */
+struct gptp_hdr *gptp_get_hdr(struct net_pkt *pkt);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_GPTP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/hostname.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/hostname.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/hostname.h	(working copy)
@@ -0,0 +1,84 @@
+/** @file
+ * @brief Hostname configuration definitions
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_HOSTNAME_H_
+#define ZEPHYR_INCLUDE_NET_HOSTNAME_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network hostname configuration library
+ * @defgroup net_hostname Network Hostname Library
+ * @ingroup networking
+ * @{
+ */
+
+/**
+ * @brief Get the device hostname
+ *
+ * @details Return pointer to device hostname.
+ *
+ * @return Pointer to hostname or NULL if not set.
+ */
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+const char *net_hostname_get(void);
+#else
+static inline const char *net_hostname_get(void)
+{
+	return "zephyr";
+}
+#endif /* CONFIG_NET_HOSTNAME_ENABLE */
+
+/**
+ * @brief Initialize and set the device hostname.
+ *
+ */
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+void net_hostname_init(void);
+#else
+static inline void net_hostname_init(void)
+{
+}
+#endif /* CONFIG_NET_HOSTNAME_ENABLE */
+
+/**
+ * @brief Set the device hostname postfix
+ *
+ * @details Set the device hostname to some value. This is only used if
+ * CONFIG_NET_HOSTNAME_UNIQUE is set.
+ *
+ * @param hostname_postfix Usually link address. The function will convert this
+ * to a string.
+ * @param postfix_len Length of the hostname_postfix array.
+ *
+ * @return 0 if ok, <0 if error
+ */
+#if defined(CONFIG_NET_HOSTNAME_UNIQUE)
+int net_hostname_set_postfix(const uint8_t *hostname_postfix,
+			      int postfix_len);
+#else
+static inline int net_hostname_set_postfix(const uint8_t *hostname_postfix,
+					   int postfix_len)
+{
+	return -EMSGSIZE;
+}
+#endif /* CONFIG_NET_HOSTNAME_UNIQUE */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_HOSTNAME_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/http_client.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_client.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_client.h	(working copy)
@@ -0,0 +1,296 @@
+/** @file
+ * @brief HTTP client API
+ *
+ * An API for applications do HTTP requests
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_
+#define ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_
+
+/**
+ * @brief HTTP client API
+ * @defgroup http_client HTTP client API
+ * @ingroup networking
+ * @{
+ */
+
+#include <kernel.h>
+#include <net/net_ip.h>
+#include <net/http_parser.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(HTTP_CRLF)
+#define HTTP_CRLF "\r\n"
+#endif
+
+#if !defined(HTTP_STATUS_STR_SIZE)
+#define HTTP_STATUS_STR_SIZE	32
+#endif
+
+/* Is there more data to come */
+enum http_final_call {
+	HTTP_DATA_MORE = 0,
+	HTTP_DATA_FINAL = 1,
+};
+
+struct http_request;
+struct http_response;
+
+/**
+ * @typedef http_payload_cb_t
+ * @brief Callback used when data needs to be sent to the server.
+ *
+ * @param sock Socket id of the connection
+ * @param req HTTP request information
+ * @param user_data User specified data specified in http_client_req()
+ *
+ * @return >=0 amount of data sent, in this case http_client_req() should
+ *             continue sending data,
+ *         <0  if http_client_req() should return the error code to the
+ *             caller.
+ */
+typedef int (*http_payload_cb_t)(int sock,
+				 struct http_request *req,
+				 void *user_data);
+
+/**
+ * @typedef http_header_cb_t
+ * @brief Callback can be used if application wants to construct additional
+ * HTTP headers when the HTTP request is sent. Usage of this is optional.
+ *
+ * @param sock Socket id of the connection
+ * @param req HTTP request information
+ * @param user_data User specified data specified in http_client_req()
+ *
+ * @return >=0 amount of data sent, in this case http_client_req() should
+ *             continue sending data,
+ *         <0  if http_client_req() should return the error code to the
+ *             caller.
+ */
+typedef int (*http_header_cb_t)(int sock,
+				struct http_request *req,
+				void *user_data);
+
+/**
+ * @typedef http_response_cb_t
+ * @brief Callback used when data is received from the server.
+ *
+ * @param rsp HTTP response information
+ * @param final_data Does this data buffer contain all the data or
+ *        is there still more data to come.
+ * @param user_data User specified data specified in http_client_req()
+ */
+typedef void (*http_response_cb_t)(struct http_response *rsp,
+				   enum http_final_call final_data,
+				   void *user_data);
+
+/**
+ * HTTP response from the server.
+ */
+struct http_response {
+	/** HTTP parser settings for the application usage */
+	const struct http_parser_settings *http_cb;
+
+	/** User provided HTTP response callback which is
+	 * called when a response is received to a sent HTTP
+	 * request.
+	 */
+	http_response_cb_t cb;
+
+	/** Where the body starts */
+	uint8_t *body_start;
+
+	/** Where the response is stored, this is to be
+	 * provided by the user.
+	 */
+	uint8_t *recv_buf;
+
+	/** Response buffer maximum length */
+	size_t recv_buf_len;
+
+	/** Length of the data in the result buf. If the value
+	 * is larger than recv_buf_len, then it means that
+	 * the data is truncated and could not be fully copied
+	 * into recv_buf. This can only happen if the user
+	 * did not set the response callback. If the callback
+	 * is set, then the HTTP client API will call response
+	 * callback many times so that all the data is
+	 * delivered to the user.
+	 */
+	size_t data_len;
+
+	/** HTTP Content-Length field value */
+	size_t content_length;
+
+	/** Content length parsed. This should be the same as
+	 * the content_length field if parsing was ok.
+	 */
+	size_t processed;
+
+	/* https://tools.ietf.org/html/rfc7230#section-3.1.2
+	 * The status-code element is a 3-digit integer code
+	 *
+	 * The reason-phrase element exists for the sole
+	 * purpose of providing a textual description
+	 * associated with the numeric status code. A client
+	 * SHOULD ignore the reason-phrase content.
+	 */
+	char http_status[HTTP_STATUS_STR_SIZE];
+
+	uint8_t cl_present : 1;
+	uint8_t body_found : 1;
+	uint8_t message_complete : 1;
+};
+
+/** HTTP client internal data that the application should not touch
+ */
+struct http_client_internal_data {
+	/** Work for handling timeout */
+	struct k_delayed_work work;
+
+	/** HTTP parser context */
+	struct http_parser parser;
+
+	/** HTTP parser settings */
+	struct http_parser_settings parser_settings;
+
+	/** HTTP response specific data (filled by http_client_req() when
+	 * data is received)
+	 */
+	struct http_response response;
+
+	/** User data */
+	void *user_data;
+
+	/** HTTP socket */
+	int sock;
+
+	/** Request timeout */
+	k_timeout_t timeout;
+};
+
+/**
+ * HTTP client request. This contains all the data that is needed when doing
+ * a HTTP request.
+ */
+struct http_request {
+	/** HTTP client request internal data */
+	struct http_client_internal_data internal;
+
+	/* User should fill in following parameters */
+
+	/** The HTTP method: GET, HEAD, OPTIONS, POST, ... */
+	enum http_method method;
+
+	/** User supplied callback function to call when response is
+	 * received.
+	 */
+	http_response_cb_t response;
+
+	/** User supplied list of HTTP callback functions if the
+	 * calling application wants to know the parsing status or the HTTP
+	 * fields. This is optional and normally not needed.
+	 */
+	const struct http_parser_settings *http_cb;
+
+	/** User supplied buffer where received data is stored */
+	uint8_t *recv_buf;
+
+	/** Length of the user supplied receive buffer */
+	size_t recv_buf_len;
+
+	/** The URL for this request, for example: /index.html */
+	const char *url;
+
+	/** The HTTP protocol, for example "HTTP/1.1" */
+	const char *protocol;
+
+	/** The HTTP header fields (application specific)
+	 * The Content-Type may be specified here or in the next field.
+	 * Depending on your application, the Content-Type may vary, however
+	 * some header fields may remain constant through the application's
+	 * life cycle. This is a NULL terminated list of header fields.
+	 */
+	const char **header_fields;
+
+	/** The value of the Content-Type header field, may be NULL */
+	const char *content_type_value;
+
+	/** Hostname to be used in the request */
+	const char *host;
+
+	/** Port number to be used in the request */
+	const char *port;
+
+	/** User supplied callback function to call when payload
+	 * needs to be sent. This can be NULL in which case the payload field
+	 * in http_request is used. The idea of this payload callback is to
+	 * allow user to send more data that is practical to store in allocated
+	 * memory.
+	 */
+	http_payload_cb_t payload_cb;
+
+	/** Payload, may be NULL */
+	const char *payload;
+
+	/** Payload length is used to calculate Content-Length. Set to 0
+	 * for chunked transfers.
+	 */
+	size_t payload_len;
+
+	/** User supplied callback function to call when optional headers need
+	 * to be sent. This can be NULL, in which case the optional_headers
+	 * field in http_request is used. The idea of this optional_headers
+	 * callback is to allow user to send more HTTP header data that is
+	 * practical to store in allocated memory.
+	 */
+	http_header_cb_t optional_headers_cb;
+
+	/** A NULL terminated list of any optional headers that
+	 * should be added to the HTTP request. May be NULL.
+	 * If the optional_headers_cb is specified, then this field is ignored.
+	 * Note that there are two similar fields that contain headers,
+	 * the header_fields above and this optional_headers. This is done
+	 * like this to support Websocket use case where Websocket will use
+	 * header_fields variable and any optional application specific
+	 * headers will be placed into this field.
+	 */
+	const char **optional_headers;
+};
+
+/**
+ * @brief Do a HTTP request. The callback is called when data is received
+ * from the HTTP server. The caller must have created a connection to the
+ * server before calling this function so connect() call must have be done
+ * successfully for the socket.
+ *
+ * @param sock Socket id of the connection.
+ * @param req HTTP request information
+ * @param timeout Max timeout to wait for the data. The timeout value cannot be
+ *        0 as there would be no time to receive the data.
+ *        The timeout value is in milliseconds.
+ * @param user_data User specified data that is passed to the callback.
+ *
+ * @return <0 if error, >=0 amount of data sent to the server
+ */
+int http_client_req(int sock, struct http_request *req,
+		    int32_t timeout, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/http_parser.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser.h	(working copy)
@@ -0,0 +1,294 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef ZEPHYR_INCLUDE_NET_HTTP_PARSER_H_
+#define ZEPHYR_INCLUDE_NET_HTTP_PARSER_H_
+
+/* Also update SONAME in the Makefile whenever you change these. */
+#define HTTP_PARSER_VERSION_MAJOR 2
+#define HTTP_PARSER_VERSION_MINOR 7
+#define HTTP_PARSER_VERSION_PATCH 1
+
+#include <sys/types.h>
+#if defined(_WIN32) && !defined(__MINGW32__) && \
+	(!defined(_MSC_VER) || _MSC_VER < 1600) && !defined(__WINE__)
+#include <BaseTsd.h>
+#include <stddef.h>
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <zephyr/types.h>
+#include <stddef.h>
+#endif
+#include <net/http_parser_state.h>
+#include <net/http_parser_url.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maximium header size allowed. If the macro is not defined
+ * before including this header then the default is used. To
+ * change the maximum header size, define the macro in the build
+ * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
+ * the effective limit on the size of the header, define the macro
+ * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
+ */
+#ifndef HTTP_MAX_HEADER_SIZE
+# define HTTP_MAX_HEADER_SIZE (80 * 1024)
+#endif
+
+struct http_parser;
+struct http_parser_settings;
+
+
+/* Callbacks should return non-zero to indicate an error. The parser will
+ * then halt execution.
+ *
+ * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
+ * returning '1' from on_headers_complete will tell the parser that it
+ * should not expect a body. This is used when receiving a response to a
+ * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
+ * chunked' headers that indicate the presence of a body.
+ *
+ * Returning `2` from on_headers_complete will tell parser that it should not
+ * expect neither a body nor any further responses on this connection. This is
+ * useful for handling responses to a CONNECT request which may not contain
+ * `Upgrade` or `Connection: upgrade` headers.
+ *
+ * http_data_cb does not return data chunks. It will be called arbitrarily
+ * many times for each string. E.G. you might get 10 callbacks for "on_url"
+ * each providing just a few characters more data.
+ */
+typedef int (*http_data_cb)(struct http_parser *, const char *at,
+			    size_t length);
+typedef int (*http_cb)(struct http_parser *);
+
+enum http_method {
+	HTTP_DELETE = 0,
+	HTTP_GET = 1,
+	HTTP_HEAD = 2,
+	HTTP_POST = 3,
+	HTTP_PUT = 4,
+	HTTP_CONNECT = 5,
+	HTTP_OPTIONS = 6,
+	HTTP_TRACE = 7,
+	HTTP_COPY = 8,
+	HTTP_LOCK = 9,
+	HTTP_MKCOL = 10,
+	HTTP_MOVE = 11,
+	HTTP_PROPFIND = 12,
+	HTTP_PROPPATCH = 13,
+	HTTP_SEARCH = 14,
+	HTTP_UNLOCK = 15,
+	HTTP_BIND = 16,
+	HTTP_REBIND = 17,
+	HTTP_UNBIND = 18,
+	HTTP_ACL = 19,
+	HTTP_REPORT = 20,
+	HTTP_MKACTIVITY = 21,
+	HTTP_CHECKOUT = 22,
+	HTTP_MERGE = 23,
+	HTTP_MSEARCH = 24,
+	HTTP_NOTIFY = 25,
+	HTTP_SUBSCRIBE = 26,
+	HTTP_UNSUBSCRIBE = 27,
+	HTTP_PATCH = 28,
+	HTTP_PURGE = 29,
+	HTTP_MKCALENDAR = 30,
+	HTTP_LINK = 31,
+	HTTP_UNLINK = 32
+};
+
+enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
+
+/* Flag values for http_parser.flags field */
+enum flags {
+	F_CHUNKED               = 1 << 0,
+	F_CONNECTION_KEEP_ALIVE = 1 << 1,
+	F_CONNECTION_CLOSE      = 1 << 2,
+	F_CONNECTION_UPGRADE    = 1 << 3,
+	F_TRAILING              = 1 << 4,
+	F_UPGRADE               = 1 << 5,
+	F_SKIPBODY              = 1 << 6,
+	F_CONTENTLENGTH         = 1 << 7
+};
+
+enum http_errno {
+	HPE_OK,
+	HPE_CB_message_begin,
+	HPE_CB_url,
+	HPE_CB_header_field,
+	HPE_CB_header_value,
+	HPE_CB_headers_complete,
+	HPE_CB_body,
+	HPE_CB_message_complete,
+	HPE_CB_status,
+	HPE_CB_chunk_header,
+	HPE_CB_chunk_complete,
+	HPE_INVALID_EOF_STATE,
+	HPE_HEADER_OVERFLOW,
+	HPE_CLOSED_CONNECTION,
+	HPE_INVALID_VERSION,
+	HPE_INVALID_STATUS,
+	HPE_INVALID_METHOD,
+	HPE_INVALID_URL,
+	HPE_INVALID_HOST,
+	HPE_INVALID_PORT,
+	HPE_INVALID_PATH,
+	HPE_INVALID_QUERY_STRING,
+	HPE_INVALID_FRAGMENT,
+	HPE_LF_EXPECTED,
+	HPE_INVALID_HEADER_TOKEN,
+	HPE_INVALID_CONTENT_LENGTH,
+	HPE_UNEXPECTED_CONTENT_LENGTH,
+	HPE_INVALID_CHUNK_SIZE,
+	HPE_INVALID_CONSTANT,
+	HPE_INVALID_INTERNAL_STATE,
+	HPE_STRICT,
+	HPE_PAUSED,
+	HPE_UNKNOWN
+};
+
+/* Get an http_errno value from an http_parser */
+#define HTTP_PARSER_ERRNO(p)            ((enum http_errno) (p)->http_errno)
+
+
+struct http_parser {
+	/** PRIVATE **/
+	unsigned int type : 2;         /* enum http_parser_type */
+	unsigned int flags : 8;		/* F_xxx values from 'flags' enum;
+					 * semi-public
+					 */
+	unsigned int state : 7;        /* enum state from http_parser.c */
+	unsigned int header_state : 7; /* enum header_state from http_parser.c
+					*/
+	unsigned int index : 7;        /* index into current matcher */
+	unsigned int lenient_http_headers : 1;
+
+	uint32_t nread;          /* # bytes read in various scenarios */
+	uint64_t content_length; /* # bytes in body (0 if no Content-Length
+				  * header)
+				  */
+	/** READ-ONLY **/
+	unsigned short http_major;
+	unsigned short http_minor;
+	unsigned int status_code : 16; /* responses only */
+	unsigned int method : 8;       /* requests only */
+	unsigned int http_errno : 7;
+
+	/* 1 = Upgrade header was present and the parser has exited because of
+	 * that.
+	 * 0 = No upgrade header present.
+	 * Should be checked when http_parser_execute() returns in addition to
+	 * error checking.
+	 */
+	unsigned int upgrade : 1;
+
+	/** PUBLIC **/
+	void *data; /* A pointer to get hook to the "connection" or "socket"
+		     * object
+		     */
+
+	/* Remote socket address of http connection, where parser can initiate
+	 * replies if necessary.
+	 */
+	const struct sockaddr *addr;
+};
+
+
+struct http_parser_settings {
+	http_cb      on_message_begin;
+	http_data_cb on_url;
+	http_data_cb on_status;
+	http_data_cb on_header_field;
+	http_data_cb on_header_value;
+	http_cb      on_headers_complete;
+	http_data_cb on_body;
+	http_cb      on_message_complete;
+	/* When on_chunk_header is called, the current chunk length is stored
+	 * in parser->content_length.
+	 */
+	http_cb      on_chunk_header;
+	http_cb      on_chunk_complete;
+};
+
+
+/* Returns the library version. Bits 16-23 contain the major version number,
+ * bits 8-15 the minor version number and bits 0-7 the patch level.
+ * Usage example:
+ *
+ *   unsigned long version = http_parser_version();
+ *   unsigned major = (version >> 16) & 255;
+ *   unsigned minor = (version >> 8) & 255;
+ *   unsigned patch = version & 255;
+ *   printf("http_parser v%u.%u.%u\n", major, minor, patch);
+ */
+unsigned long http_parser_version(void);
+
+void http_parser_init(struct http_parser *parser, enum http_parser_type type);
+
+
+/* Initialize http_parser_settings members to 0
+ */
+void http_parser_settings_init(struct http_parser_settings *settings);
+
+
+/* Executes the parser. Returns number of parsed bytes. Sets
+ * `parser->http_errno` on error.
+ */
+
+size_t http_parser_execute(struct http_parser *parser,
+			   const struct http_parser_settings *settings,
+			   const char *data, size_t len);
+
+/* If http_should_keep_alive() in the on_headers_complete or
+ * on_message_complete callback returns 0, then this should be
+ * the last message on the connection.
+ * If you are the server, respond with the "Connection: close" header.
+ * If you are the client, close the connection.
+ */
+int http_should_keep_alive(const struct http_parser *parser);
+
+/* Returns a string version of the HTTP method. */
+const char *http_method_str(enum http_method m);
+
+/* Return a string name of the given error */
+const char *http_errno_name(enum http_errno err);
+
+/* Return a string description of the given error */
+const char *http_errno_description(enum http_errno err);
+
+/* Pause or un-pause the parser; a nonzero value pauses */
+void http_parser_pause(struct http_parser *parser, int paused);
+
+/* Checks if this is the final chunk of the body. */
+int http_body_is_final(const struct http_parser *parser);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: ModuleDemo/BLE/CM0/User/include/net/http_parser_state.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser_state.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser_state.h	(working copy)
@@ -0,0 +1,99 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef ZEPHYR_INCLUDE_NET_HTTP_PARSER_STATE_H_
+#define ZEPHYR_INCLUDE_NET_HTTP_PARSER_STATE_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum state {
+	s_dead = 1, /* important that this is > 0 */
+	s_start_req_or_res,
+	s_res_or_resp_H,
+	s_start_res,
+	s_res_H,
+	s_res_HT,
+	s_res_HTT,
+	s_res_HTTP,
+	s_res_first_http_major,
+	s_res_http_major,
+	s_res_first_http_minor,
+	s_res_http_minor,
+	s_res_first_status_code,
+	s_res_status_code,
+	s_res_status_start,
+	s_res_status,
+	s_res_line_almost_done,
+	s_start_req,
+	s_req_method,
+	s_req_spaces_before_url,
+	s_req_schema,
+	s_req_schema_slash,
+	s_req_schema_slash_slash,
+	s_req_server_start,
+	s_req_server,
+	s_req_server_with_at,
+	s_req_path,
+	s_req_query_string_start,
+	s_req_query_string,
+	s_req_fragment_start,
+	s_req_fragment,
+	s_req_http_start,
+	s_req_http_H,
+	s_req_http_HT,
+	s_req_http_HTT,
+	s_req_http_HTTP,
+	s_req_first_http_major,
+	s_req_http_major,
+	s_req_first_http_minor,
+	s_req_http_minor,
+	s_req_line_almost_done,
+	s_header_field_start,
+	s_header_field,
+	s_header_value_discard_ws,
+	s_header_value_discard_ws_almost_done,
+	s_header_value_discard_lws,
+	s_header_value_start,
+	s_header_value,
+	s_header_value_lws,
+	s_header_almost_done,
+	s_chunk_size_start,
+	s_chunk_size,
+	s_chunk_parameters,
+	s_chunk_size_almost_done,
+	s_headers_almost_done,
+	s_headers_done,
+	/* Important: 's_headers_done' must be the last 'header' state. All
+	 * states beyond this must be 'body' states. It is used for overflow
+	 * checking. See the PARSING_HEADER() macro.
+	 */
+	s_chunk_data,
+	s_chunk_data_almost_done,
+	s_chunk_data_done,
+	s_body_identity,
+	s_body_identity_eof,
+	s_message_done
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: ModuleDemo/BLE/CM0/User/include/net/http_parser_url.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser_url.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/http_parser_url.h	(working copy)
@@ -0,0 +1,75 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef ZEPHYR_INCLUDE_NET_HTTP_PARSER_URL_H_
+#define ZEPHYR_INCLUDE_NET_HTTP_PARSER_URL_H_
+
+#include <sys/types.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <net/http_parser_state.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum http_parser_url_fields {
+	  UF_SCHEMA           = 0
+	, UF_HOST             = 1
+	, UF_PORT             = 2
+	, UF_PATH             = 3
+	, UF_QUERY            = 4
+	, UF_FRAGMENT         = 5
+	, UF_USERINFO         = 6
+	, UF_MAX              = 7
+};
+
+/* Result structure for http_parser_url_fields().
+ *
+ * Callers should index into field_data[] with UF_* values iff field_set
+ * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
+ * because we probably have padding left over), we convert any port to
+ * a uint16_t.
+ */
+struct http_parser_url {
+	uint16_t field_set;           /* Bitmask of (1 << UF_*) values */
+	uint16_t port;                /* Converted UF_PORT string */
+
+	struct {
+		uint16_t off;               /* Offset into buffer in which field
+					  * starts
+					  */
+		uint16_t len;               /* Length of run in buffer */
+	} field_data[UF_MAX];
+};
+
+enum state parse_url_char(enum state s, const char ch);
+
+/* Initialize all http_parser_url members to 0 */
+void http_parser_url_init(struct http_parser_url *u);
+
+/* Parse a URL; return nonzero on failure */
+int http_parser_parse_url(const char *buf, size_t buflen,
+			  int is_connect, struct http_parser_url *u);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: ModuleDemo/BLE/CM0/User/include/net/ieee802154.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154.h	(working copy)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief IEEE 802.15.4 L2 stack public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_H_
+#define ZEPHYR_INCLUDE_NET_IEEE802154_H_
+
+#include <limits.h>
+#include <net/net_mgmt.h>
+#include <crypto/cipher_structs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief IEEE 802.15.4 library
+ * @defgroup ieee802154 IEEE 802.15.4 Library
+ * @ingroup networking
+ * @{
+ */
+
+#define IEEE802154_MAX_ADDR_LENGTH	8
+#define IEEE802154_NO_CHANNEL		USHRT_MAX
+
+struct ieee802154_security_ctx {
+	uint32_t frame_counter;
+	struct cipher_ctx enc;
+	struct cipher_ctx dec;
+	uint8_t key[16];
+	uint8_t key_len;
+	uint8_t level	: 3;
+	uint8_t key_mode	: 2;
+	uint8_t _unused	: 3;
+};
+
+/* This not meant to be used by any code but 802.15.4 L2 stack */
+struct ieee802154_context {
+	enum net_l2_flags flags;
+	uint16_t pan_id;
+	uint16_t channel;
+	struct k_sem ack_lock;
+	uint16_t short_addr;
+	uint8_t ext_addr[IEEE802154_MAX_ADDR_LENGTH];
+#ifdef CONFIG_NET_L2_IEEE802154_MGMT
+	struct ieee802154_req_params *scan_ctx;
+	union {
+		struct k_sem res_lock;
+		struct k_sem req_lock;
+	};
+	union {
+		uint8_t ext_addr[IEEE802154_MAX_ADDR_LENGTH];
+		uint16_t short_addr;
+	} coord;
+	uint8_t coord_addr_len;
+#endif
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	struct ieee802154_security_ctx sec_ctx;
+#endif
+	int16_t tx_power;
+	uint8_t sequence;
+	uint8_t ack_seq;
+	uint8_t ack_received	: 1;
+	uint8_t ack_requested	: 1;
+	uint8_t associated		: 1;
+	uint8_t _unused		: 5;
+};
+
+#define IEEE802154_L2_CTX_TYPE	struct ieee802154_context
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ieee802154_mgmt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154_mgmt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154_mgmt.h	(working copy)
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief IEEE 802.15.4 Management interface public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_MGMT_H_
+#define ZEPHYR_INCLUDE_NET_IEEE802154_MGMT_H_
+
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief IEEE 802.15.4 library
+ * @defgroup ieee802154_mgmt IEEE 802.15.4 Library
+ * @ingroup networking
+ * @{
+ */
+
+
+#define IEEE802154_MAX_ADDR_LENGTH	8
+
+
+#define _NET_IEEE802154_LAYER	NET_MGMT_LAYER_L2
+#define _NET_IEEE802154_CODE	0x154
+#define _NET_IEEE802154_BASE	(NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_IEEE802154_LAYER) |\
+				 NET_MGMT_LAYER_CODE(_NET_IEEE802154_CODE))
+#define _NET_IEEE802154_EVENT	(_NET_IEEE802154_BASE | NET_MGMT_EVENT_BIT)
+
+enum net_request_ieee802154_cmd {
+	NET_REQUEST_IEEE802154_CMD_SET_ACK = 1,
+	NET_REQUEST_IEEE802154_CMD_UNSET_ACK,
+	NET_REQUEST_IEEE802154_CMD_PASSIVE_SCAN,
+	NET_REQUEST_IEEE802154_CMD_ACTIVE_SCAN,
+	NET_REQUEST_IEEE802154_CMD_CANCEL_SCAN,
+	NET_REQUEST_IEEE802154_CMD_ASSOCIATE,
+	NET_REQUEST_IEEE802154_CMD_DISASSOCIATE,
+	NET_REQUEST_IEEE802154_CMD_SET_CHANNEL,
+	NET_REQUEST_IEEE802154_CMD_GET_CHANNEL,
+	NET_REQUEST_IEEE802154_CMD_SET_PAN_ID,
+	NET_REQUEST_IEEE802154_CMD_GET_PAN_ID,
+	NET_REQUEST_IEEE802154_CMD_SET_EXT_ADDR,
+	NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR,
+	NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR,
+	NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR,
+	NET_REQUEST_IEEE802154_CMD_GET_TX_POWER,
+	NET_REQUEST_IEEE802154_CMD_SET_TX_POWER,
+	NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS,
+	NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS,
+};
+
+
+#define NET_REQUEST_IEEE802154_SET_ACK					\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_ACK)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_ACK);
+
+#define NET_REQUEST_IEEE802154_UNSET_ACK				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_UNSET_ACK)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_UNSET_ACK);
+
+#define NET_REQUEST_IEEE802154_PASSIVE_SCAN				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_PASSIVE_SCAN)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_PASSIVE_SCAN);
+
+#define NET_REQUEST_IEEE802154_ACTIVE_SCAN				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_ACTIVE_SCAN)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ACTIVE_SCAN);
+
+#define NET_REQUEST_IEEE802154_CANCEL_SCAN				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_CANCEL_SCAN)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_CANCEL_SCAN);
+
+#define NET_REQUEST_IEEE802154_ASSOCIATE				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_ASSOCIATE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ASSOCIATE);
+
+#define NET_REQUEST_IEEE802154_DISASSOCIATE				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_DISASSOCIATE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_DISASSOCIATE);
+
+#define NET_REQUEST_IEEE802154_SET_CHANNEL				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_CHANNEL)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_CHANNEL);
+
+#define NET_REQUEST_IEEE802154_GET_CHANNEL				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_CHANNEL)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_CHANNEL);
+
+#define NET_REQUEST_IEEE802154_SET_PAN_ID				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_PAN_ID)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_PAN_ID);
+
+#define NET_REQUEST_IEEE802154_GET_PAN_ID				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_PAN_ID)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_PAN_ID);
+
+#define NET_REQUEST_IEEE802154_SET_EXT_ADDR				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_EXT_ADDR)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_EXT_ADDR);
+
+#define NET_REQUEST_IEEE802154_GET_EXT_ADDR				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_EXT_ADDR);
+
+#define NET_REQUEST_IEEE802154_SET_SHORT_ADDR				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SHORT_ADDR);
+
+#define NET_REQUEST_IEEE802154_GET_SHORT_ADDR				\
+	(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SHORT_ADDR);
+
+#define NET_REQUEST_IEEE802154_GET_TX_POWER				\
+	(_NET_IEEE802154_BASE |						\
+	 NET_REQUEST_IEEE802154_CMD_GET_TX_POWER)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_TX_POWER);
+
+#define NET_REQUEST_IEEE802154_SET_TX_POWER				\
+	(_NET_IEEE802154_BASE |						\
+	 NET_REQUEST_IEEE802154_CMD_SET_TX_POWER)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_TX_POWER);
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+
+#define NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS			\
+	(_NET_IEEE802154_BASE |						\
+	 NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS);
+
+#define NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS			\
+	(_NET_IEEE802154_BASE |						\
+	 NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS);
+
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+enum net_event_ieee802154_cmd {
+	NET_EVENT_IEEE802154_CMD_SCAN_RESULT = 1,
+};
+
+#define NET_EVENT_IEEE802154_SCAN_RESULT				\
+	(_NET_IEEE802154_EVENT | NET_EVENT_IEEE802154_CMD_SCAN_RESULT)
+
+
+#define IEEE802154_IS_CHAN_SCANNED(_channel_set, _chan)	\
+	(_channel_set & BIT(_chan - 1))
+#define IEEE802154_IS_CHAN_UNSCANNED(_channel_set, _chan)	\
+	(!IEEE802154_IS_CHAN_SCANNED(_channel_set, _chan))
+
+/* Useful define to request all channels to be scanned,
+ * from 11 to 26 included.
+ */
+#define IEEE802154_ALL_CHANNELS	(0x03FFFC00)
+
+/**
+ * @brief Scanning parameters
+ *
+ * Used to request a scan and get results as well
+ */
+struct ieee802154_req_params {
+	/** The set of channels to scan, use above macros to manage it */
+	uint32_t channel_set;
+
+	/** Duration of scan, per-channel, in milliseconds */
+	uint32_t duration;
+
+	/** Current channel in use as a result */
+	uint16_t channel;
+	/** Current pan_id in use as a result */
+	uint16_t pan_id;
+
+	/** Result address */
+	union {
+		uint8_t addr[IEEE802154_MAX_ADDR_LENGTH];
+		uint16_t short_addr;
+	};
+
+	/** length of address */
+	uint8_t len;
+	/** Link quality information, between 0 and 255 */
+	uint8_t lqi;
+};
+
+/**
+ * @brief Security parameters
+ *
+ * Used to setup the link-layer security settings
+ */
+struct ieee802154_security_params {
+	uint8_t key[16];
+	uint8_t key_len;
+	uint8_t key_mode	: 2;
+	uint8_t level	: 3;
+	uint8_t _unused	: 3;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_MGMT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ieee802154_radio.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154_radio.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ieee802154_radio.h	(working copy)
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public IEEE 802.15.4 Radio API
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_
+#define ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_
+
+#include <device.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/ieee802154.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup ieee802154
+ * @{
+ */
+
+enum ieee802154_hw_caps {
+	IEEE802154_HW_FCS	  = BIT(0), /* Frame Check-Sum supported */
+	IEEE802154_HW_PROMISC	  = BIT(1), /* Promiscuous mode supported */
+	IEEE802154_HW_FILTER	  = BIT(2), /* Filter PAN ID, long/short addr */
+	IEEE802154_HW_CSMA	  = BIT(3), /* CSMA-CA supported */
+	IEEE802154_HW_2_4_GHZ	  = BIT(4), /* 2.4Ghz radio supported */
+	IEEE802154_HW_TX_RX_ACK	  = BIT(5), /* Handles ACK request on TX */
+	IEEE802154_HW_SUB_GHZ	  = BIT(6), /* Sub-GHz radio supported */
+	IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */
+	IEEE802154_HW_TXTIME	  = BIT(8), /* TX at specified time supported */
+	IEEE802154_HW_SLEEP_TO_TX = BIT(9), /* TX directly from sleep supported */
+};
+
+enum ieee802154_filter_type {
+	IEEE802154_FILTER_TYPE_IEEE_ADDR,
+	IEEE802154_FILTER_TYPE_SHORT_ADDR,
+	IEEE802154_FILTER_TYPE_PAN_ID,
+	IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
+	IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
+};
+
+enum ieee802154_event {
+	IEEE802154_EVENT_TX_STARTED, /* Data transmission started */
+	IEEE802154_EVENT_RX_FAILED   /* Data reception failed */
+};
+
+enum ieee802154_rx_fail_reason {
+	IEEE802154_RX_FAIL_NOT_RECEIVED,  /* Nothing received */
+	IEEE802154_RX_FAIL_INVALID_FCS,   /* Frame had invalid checksum */
+	IEEE802154_RX_FAIL_ADDR_FILTERED, /* Address did not match */
+	IEEE802154_RX_FAIL_OTHER	  /* General reason */
+};
+
+typedef void (*energy_scan_done_cb_t)(const struct device *dev,
+				      int16_t max_ed);
+
+typedef void (*ieee802154_event_cb_t)(const struct device *dev,
+				      enum ieee802154_event evt,
+				      void *event_params);
+
+struct ieee802154_filter {
+/** @cond ignore */
+	union {
+		uint8_t *ieee_addr;
+		uint16_t short_addr;
+		uint16_t pan_id;
+	};
+/* @endcond */
+};
+
+/** IEEE802.15.4 Transmission mode. */
+enum ieee802154_tx_mode {
+	/** Transmit packet immediately, no CCA. */
+	IEEE802154_TX_MODE_DIRECT,
+
+	/** Perform CCA before packet transmission. */
+	IEEE802154_TX_MODE_CCA,
+
+	/** Perform full CSMA CA procedure before packet transmission. */
+	IEEE802154_TX_MODE_CSMA_CA,
+
+	/** Transmit packet in the future, at specified time, no CCA. */
+	IEEE802154_TX_MODE_TXTIME,
+
+	/** Transmit packet in the future, perform CCA before transmission. */
+	IEEE802154_TX_MODE_TXTIME_CCA,
+};
+
+/** IEEE802.15.4 Frame Pending Bit table address matching mode. */
+enum ieee802154_fpb_mode {
+	/** The pending bit shall be set only for addresses found in the list.
+	 */
+	IEEE802154_FPB_ADDR_MATCH_THREAD,
+
+	/** The pending bit shall be cleared for short addresses found in
+	 *  the list.
+	 */
+	IEEE802154_FPB_ADDR_MATCH_ZIGBEE,
+};
+
+/** IEEE802.15.4 driver configuration types. */
+enum ieee802154_config_type {
+	/** Indicates how radio driver should set Frame Pending bit in ACK
+	 *  responses for Data Requests. If enabled, radio driver should
+	 *  determine whether to set the bit or not based on the information
+	 *  provided with ``IEEE802154_CONFIG_ACK_FPB`` config and FPB address
+	 *  matching mode specified. Otherwise, Frame Pending bit should be set
+	 *  to ``1``(see IEEE Std 802.15.4-2006, 7.2.2.3.1).
+	 */
+	IEEE802154_CONFIG_AUTO_ACK_FPB,
+
+	/** Indicates whether to set ACK Frame Pending bit for specific address
+	 *  or not. Disabling the Frame Pending bit with no address provided
+	 *  (NULL pointer) should disable it for all enabled addresses.
+	 */
+	IEEE802154_CONFIG_ACK_FPB,
+
+	/** Indicates whether the device is a PAN coordinator. */
+	IEEE802154_CONFIG_PAN_COORDINATOR,
+
+	/** Enable/disable promiscuous mode. */
+	IEEE802154_CONFIG_PROMISCUOUS,
+
+	/** Specifies new radio event handler. Specifying NULL as a handler
+	 *  will disable radio events notification.
+	 */
+	IEEE802154_CONFIG_EVENT_HANDLER
+};
+
+/** IEEE802.15.4 driver configuration data. */
+struct ieee802154_config {
+	/** Configuration data. */
+	union {
+		/** ``IEEE802154_CONFIG_AUTO_ACK_FPB`` */
+		struct {
+			bool enabled;
+			enum ieee802154_fpb_mode mode;
+		} auto_ack_fpb;
+
+		/** ``IEEE802154_CONFIG_ACK_FPB`` */
+		struct {
+			uint8_t *addr;
+			bool extended;
+			bool enabled;
+		} ack_fpb;
+
+		/** ``IEEE802154_CONFIG_PAN_COORDINATOR`` */
+		bool pan_coordinator;
+
+		/** ``IEEE802154_CONFIG_PROMISCUOUS`` */
+		bool promiscuous;
+
+		/** ``IEEE802154_CONFIG_EVENT_HANDLER`` */
+		ieee802154_event_cb_t event_handler;
+	};
+};
+
+/**
+ * @brief IEEE 802.15.4 radio interface API.
+ *
+ */
+struct ieee802154_radio_api {
+	/**
+	 * Mandatory to get in first position.
+	 * A network device should indeed provide a pointer on such
+	 * net_if_api structure. So we make current structure pointer
+	 * that can be casted to a net_if_api structure pointer.
+	 */
+	struct net_if_api iface_api;
+
+	/** Get the device capabilities */
+	enum ieee802154_hw_caps (*get_capabilities)(const struct device *dev);
+
+	/** Clear Channel Assesment - Check channel's activity */
+	int (*cca)(const struct device *dev);
+
+	/** Set current channel */
+	int (*set_channel)(const struct device *dev, uint16_t channel);
+
+	/** Set/Unset filters (for IEEE802154_HW_FILTER ) */
+	int (*filter)(const struct device *dev,
+		      bool set,
+		      enum ieee802154_filter_type type,
+		      const struct ieee802154_filter *filter);
+
+	/** Set TX power level in dbm */
+	int (*set_txpower)(const struct device *dev, int16_t dbm);
+
+	/** Transmit a packet fragment */
+	int (*tx)(const struct device *dev, enum ieee802154_tx_mode mode,
+		  struct net_pkt *pkt, struct net_buf *frag);
+
+	/** Start the device */
+	int (*start)(const struct device *dev);
+
+	/** Stop the device */
+	int (*stop)(const struct device *dev);
+
+	/** Set specific radio driver configuration. */
+	int (*configure)(const struct device *dev,
+			 enum ieee802154_config_type type,
+			 const struct ieee802154_config *config);
+
+#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
+	/** Get the available amount of Sub-GHz channels */
+	uint16_t (*get_subg_channel_count)(const struct device *dev);
+#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
+
+	/** Run an energy detection scan.
+	 *  Note: channel must be set prior to request this function.
+	 *  duration parameter is in ms.
+	 */
+	int (*ed_scan)(const struct device *dev,
+		       uint16_t duration,
+		       energy_scan_done_cb_t done_cb);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * IEEE 802154 radio API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct ieee802154_radio_api, iface_api) == 0);
+
+#define IEEE802154_AR_FLAG_SET (0x20)
+
+/**
+ * @brief Check if AR flag is set on the frame inside given net_pkt
+ *
+ * @param frag A valid pointer on a net_buf structure, must not be NULL,
+ *        and its length should be at least made of 1 byte (ACK frames
+ *        are the smallest frames on 15.4 and made of 3 bytes, not
+ *        not counting the FCS part).
+ *
+ * @return True if AR flag is set, False otherwise
+ */
+static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag)
+{
+	return (*frag->data & IEEE802154_AR_FLAG_SET);
+}
+
+/**
+ * @brief Radio driver ACK handling function that hw drivers should use
+ *
+ * @details ACK handling requires fast handling and thus such function
+ *          helps to hook directly the hw drivers to the radio driver.
+ *
+ * @param iface A valid pointer on a network interface that received the packet
+ * @param pkt A valid pointer on a packet to check
+ *
+ * @return NET_OK if it was handled, NET_CONTINUE otherwise
+ */
+#ifndef CONFIG_IEEE802154_RAW_MODE
+extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
+						    struct net_pkt *pkt);
+#else /* CONFIG_IEEE802154_RAW_MODE */
+
+static inline enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
+							   struct net_pkt *pkt)
+{
+	return NET_CONTINUE;
+}
+#endif /* CONFIG_IEEE802154_RAW_MODE */
+
+/**
+ * @brief Initialize L2 stack for a given interface
+ *
+ * @param iface A valid pointer on a network interface
+ */
+#ifndef CONFIG_IEEE802154_RAW_MODE
+void ieee802154_init(struct net_if *iface);
+#else
+#define ieee802154_init(_iface_)
+#endif /* CONFIG_IEEE802154_RAW_MODE */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ipv4_autoconf.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ipv4_autoconf.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ipv4_autoconf.h	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Matthias Boesl
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief IPv4 Autoconfiguration
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_IPV4_AUTOCONF_H_
+#define ZEPHYR_INCLUDE_NET_IPV4_AUTOCONF_H_
+
+/** Current state of IPv4 Autoconfiguration */
+enum net_ipv4_autoconf_state {
+	NET_IPV4_AUTOCONF_INIT,
+	NET_IPV4_AUTOCONF_PROBE,
+	NET_IPV4_AUTOCONF_ANNOUNCE,
+	NET_IPV4_AUTOCONF_ASSIGNED,
+	NET_IPV4_AUTOCONF_RENEW,
+};
+
+/**
+ * @brief Initialize IPv4 auto configuration engine.
+ */
+#if defined(CONFIG_NET_IPV4_AUTO)
+void net_ipv4_autoconf_init(void);
+#else
+#define net_ipv4_autoconf_init(...)
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_IPV4_AUTOCONF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/lldp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/lldp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/lldp.h	(working copy)
@@ -0,0 +1,268 @@
+/** @file
+ @brief LLDP definitions and handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_LLDP_H_
+#define ZEPHYR_INCLUDE_NET_LLDP_H_
+
+/**
+ * @brief LLDP definitions and helpers
+ * @defgroup lldp Link Layer Discovery Protocol definitions and helpers
+ * @ingroup networking
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+
+#define LLDP_TLV_GET_LENGTH(type_length)	(type_length & BIT_MASK(9))
+#define LLDP_TLV_GET_TYPE(type_length)		((uint8_t)(type_length >> 9))
+
+/* LLDP Definitions */
+
+/* According to the spec, End of LLDPDU TLV value is constant. */
+#define NET_LLDP_END_LLDPDU_VALUE 0x0000
+
+/*
+ * For the Chassis ID TLV Value, if subtype is a MAC address then we must
+ * use values from CONFIG_NET_LLDP_CHASSIS_ID_MAC0 through
+ * CONFIG_NET_LLDP_CHASSIS_ID_MAC5. If not, we use CONFIG_NET_LLDP_CHASSIS_ID.
+ *
+ * FIXME: implement a similar scheme for subtype 5 (network address).
+ */
+#if defined(CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE)
+#if (CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE == 4)
+#define NET_LLDP_CHASSIS_ID_VALUE		\
+	{					\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC0,	\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC1,	\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC2,	\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC3,	\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC4,	\
+	  CONFIG_NET_LLDP_CHASSIS_ID_MAC5 	\
+	}
+
+#define NET_LLDP_CHASSIS_ID_VALUE_LEN (6)
+#else
+#define NET_LLDP_CHASSIS_ID_VALUE CONFIG_NET_LLDP_CHASSIS_ID
+#define NET_LLDP_CHASSIS_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_CHASSIS_ID) - 1)
+#endif
+#else
+#define NET_LLDP_CHASSIS_ID_VALUE 0
+#define NET_LLDP_CHASSIS_ID_VALUE_LEN 0
+#endif
+
+/*
+ * For the Port ID TLV Value, if subtype is a MAC address then we must
+ * use values from CONFIG_NET_LLDP_PORT_ID_MAC0 through
+ * CONFIG_NET_LLDP_PORT_ID_MAC5. If not, we use CONFIG_NET_LLDP_PORT_ID.
+ *
+ * FIXME: implement a similar scheme for subtype 4 (network address).
+ */
+#if defined(CONFIG_NET_LLDP_PORT_ID_SUBTYPE)
+#if (CONFIG_NET_LLDP_PORT_ID_SUBTYPE == 3)
+#define NET_LLDP_PORT_ID_VALUE		\
+	{				\
+	  CONFIG_NET_LLDP_PORT_ID_MAC0,	\
+	  CONFIG_NET_LLDP_PORT_ID_MAC1, \
+	  CONFIG_NET_LLDP_PORT_ID_MAC2, \
+	  CONFIG_NET_LLDP_PORT_ID_MAC3, \
+	  CONFIG_NET_LLDP_PORT_ID_MAC4, \
+	  CONFIG_NET_LLDP_PORT_ID_MAC5  \
+	}
+
+#define NET_LLDP_PORT_ID_VALUE_LEN (6)
+#else
+#define NET_LLDP_PORT_ID_VALUE CONFIG_NET_LLDP_PORT_ID
+#define NET_LLDP_PORT_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_PORT_ID) - 1)
+#endif
+#else
+#define NET_LLDP_PORT_ID_VALUE 0
+#define NET_LLDP_PORT_ID_VALUE_LEN 0
+#endif
+
+/*
+ * TLVs Length.
+ * Note that TLVs that have a subtype must have a byte added to their length.
+ */
+#define NET_LLDP_CHASSIS_ID_TLV_LEN (NET_LLDP_CHASSIS_ID_VALUE_LEN + 1)
+#define NET_LLDP_PORT_ID_TLV_LEN (NET_LLDP_PORT_ID_VALUE_LEN + 1)
+#define NET_LLDP_TTL_TLV_LEN (2)
+
+/*
+ * Time to Live value.
+ * Calculate based on section 9.2.5.22 from LLDP spec.
+ *
+ * FIXME: when the network interface is about to be â€کdisabledâ€™ TTL shall be set
+ * to zero so LLDP Rx agents can invalidate the entry related to this node.
+ */
+#if defined(CONFIG_NET_LLDP_TX_INTERVAL) && defined(CONFIG_NET_LLDP_TX_HOLD)
+#define NET_LLDP_TTL \
+	MIN((CONFIG_NET_LLDP_TX_INTERVAL * CONFIG_NET_LLDP_TX_HOLD) + 1, 65535)
+#endif
+
+
+struct net_if;
+
+/** @endcond */
+
+/** TLV Types. Please refer to table 8-1 from IEEE 802.1AB standard. */
+enum net_lldp_tlv_type {
+	LLDP_TLV_END_LLDPDU          = 0, /**< End Of LLDPDU (optional)      */
+	LLDP_TLV_CHASSIS_ID          = 1, /**< Chassis ID (mandatory)        */
+	LLDP_TLV_PORT_ID             = 2, /**< Port ID (mandatory)           */
+	LLDP_TLV_TTL                 = 3, /**< Time To Live (mandatory)      */
+	LLDP_TLV_PORT_DESC           = 4, /**< Port Description (optional)   */
+	LLDP_TLV_SYSTEM_NAME         = 5, /**< System Name (optional)        */
+	LLDP_TLV_SYSTEM_DESC         = 6, /**< System Description (optional) */
+	LLDP_TLV_SYSTEM_CAPABILITIES = 7, /**< System Capability (optional)  */
+	LLDP_TLV_MANAGEMENT_ADDR     = 8, /**< Management Address (optional) */
+	/* Types 9 - 126 are reserved. */
+	LLDP_TLV_ORG_SPECIFIC       = 127, /**< Org specific TLVs (optional) */
+};
+
+/** Chassis ID TLV, see chapter 8.5.2 in IEEE 802.1AB */
+struct net_lldp_chassis_tlv {
+	/** 7 bits for type, 9 bits for length */
+	uint16_t type_length;
+	/** ID subtype */
+	uint8_t subtype;
+	/** Chassis ID value */
+	uint8_t value[NET_LLDP_CHASSIS_ID_VALUE_LEN];
+} __packed;
+
+/** Port ID TLV, see chapter 8.5.3 in IEEE 802.1AB */
+struct net_lldp_port_tlv {
+	/** 7 bits for type, 9 bits for length */
+	uint16_t type_length;
+	/** ID subtype */
+	uint8_t subtype;
+	/** Port ID value */
+	uint8_t value[NET_LLDP_PORT_ID_VALUE_LEN];
+} __packed;
+
+/** Time To Live TLV, see chapter 8.5.4 in IEEE 802.1AB */
+struct net_lldp_time_to_live_tlv {
+	/** 7 bits for type, 9 bits for length */
+	uint16_t type_length;
+	/** Time To Live (TTL) value */
+	uint16_t ttl;
+} __packed;
+
+/**
+ * LLDP Data Unit (LLDPDU) shall contain the following ordered TLVs
+ * as stated in "8.2 LLDPDU format" from the IEEE 802.1AB
+ */
+struct net_lldpdu {
+	struct net_lldp_chassis_tlv chassis_id;	/**< Mandatory Chassis TLV */
+	struct net_lldp_port_tlv port_id;	/**< Mandatory Port TLV */
+	struct net_lldp_time_to_live_tlv ttl;	/**< Mandatory TTL TLV */
+} __packed;
+
+/**
+ * @brief Set the LLDP data unit for a network interface.
+ *
+ * @param iface Network interface
+ * @param lldpdu LLDP data unit struct
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_lldp_config(struct net_if *iface, const struct net_lldpdu *lldpdu);
+
+/**
+ * @brief Set the Optional LLDP TLVs for a network interface.
+ *
+ * @param iface Network interface
+ * @param tlv LLDP optional TLVs following mandatory part
+ * @param len Length of the optional TLVs
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_lldp_config_optional(struct net_if *iface, const uint8_t *tlv,
+			     size_t len);
+
+/**
+ * @brief Initialize LLDP engine.
+ */
+void net_lldp_init(void);
+
+/**
+ * @brief LLDP Receive packet callback
+ *
+ * Callback gets called upon receiving packet. It is responsible for
+ * freeing packet or indicating to the stack that it needs to free packet
+ * by returning correct net_verdict.
+ *
+ * Returns:
+ *  - NET_DROP, if packet was invalid, rejected or we want the stack to free it.
+ *    In this case the core stack will free the packet.
+ *  - NET_OK, if the packet was accepted, in this case the ownership of the
+ *    net_pkt goes to callback and core network stack will forget it.
+ */
+typedef enum net_verdict (*net_lldp_recv_cb_t)(struct net_if *iface,
+					       struct net_pkt *pkt);
+
+/**
+ * @brief Register LLDP Rx callback function
+ *
+ * @param iface Network interface
+ * @param cb Callback function
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_lldp_register_callback(struct net_if *iface, net_lldp_recv_cb_t cb);
+
+/**
+ * @brief Parse LLDP packet
+ *
+ * @param iface Network interface
+ * @param pkt Network packet
+ *
+ * @return Return the policy for network buffer
+ */
+enum net_verdict net_lldp_recv(struct net_if *iface, struct net_pkt *pkt);
+
+/**
+ * @brief Set LLDP protocol data unit (LLDPDU) for the network interface.
+ *
+ * @param iface Network interface
+ *
+ * @return <0 if error, index in lldp array if iface is found there
+ */
+#if defined(CONFIG_NET_LLDP)
+int net_lldp_set_lldpdu(struct net_if *iface);
+#else
+#define net_lldp_set_lldpdu(iface)
+#endif
+
+/**
+ * @brief Unset LLDP protocol data unit (LLDPDU) for the network interface.
+ *
+ * @param iface Network interface
+ */
+#if defined(CONFIG_NET_LLDP)
+void net_lldp_unset_lldpdu(struct net_if *iface);
+#else
+#define net_lldp_unset_lldpdu(iface)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_LLDP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/lwm2m.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/lwm2m.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/lwm2m.h	(working copy)
@@ -0,0 +1,904 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2017-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file lwm2m.h
+ *
+ * @defgroup lwm2m_api LwM2M high-level API
+ * @ingroup networking
+ * @{
+ * @brief LwM2M high-level API
+ *
+ * @details
+ * LwM2M high-level interface is defined in this header.
+ *
+ * @note The implementation assumes UDP module is enabled.
+ *
+ * @note LwM2M 1.0.x is currently the only supported version.
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_LWM2M_H_
+#define ZEPHYR_INCLUDE_NET_LWM2M_H_
+
+#include <kernel.h>
+#include <sys/mutex.h>
+#include <net/coap.h>
+
+/**
+ * @brief LwM2M Objects managed by OMA for LwM2M tech specification.  Objects
+ * in this range have IDs from 0 to 1023.
+ * For more information refer to Technical Specification
+ * OMA-TS-LightweightM2M-V1_0_2-20180209-A
+ */
+
+#define LWM2M_OBJECT_SECURITY_ID			0
+#define LWM2M_OBJECT_SERVER_ID				1
+#define LWM2M_OBJECT_ACCESS_CONTROL_ID			2
+#define LWM2M_OBJECT_DEVICE_ID				3
+#define LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID		4
+#define LWM2M_OBJECT_FIRMWARE_ID			5
+#define LWM2M_OBJECT_LOCATION_ID			6
+#define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID		7
+
+/**
+ * @brief LwM2M Objects produced by 3rd party Standards Development
+ * Organizations.  Objects in this range have IDs from 2048 to 10240
+ * Refer to the OMA LightweightM2M (LwM2M) Object and Resource Registry:
+ * http://www.openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html
+ */
+
+/* clang-format off */
+#define IPSO_OBJECT_GENERIC_SENSOR_ID       3300
+#define IPSO_OBJECT_TEMP_SENSOR_ID          3303
+#define IPSO_OBJECT_HUMIDITY_SENSOR_ID      3304
+#define IPSO_OBJECT_LIGHT_CONTROL_ID        3311
+#define IPSO_OBJECT_ACCELEROMETER_ID        3313
+#define IPSO_OBJECT_PRESSURE_ID             3323
+#define IPSO_OBJECT_BUZZER_ID               3338
+#define IPSO_OBJECT_TIMER_ID                3340
+#define IPSO_OBJECT_ONOFF_SWITCH_ID         3342
+#define IPSO_OBJECT_PUSH_BUTTON_ID          3347
+/* clang-format on */
+
+/**
+ * @brief LwM2M context structure to maintain information for a single
+ * LwM2M connection.
+ */
+struct lwm2m_ctx {
+	/** Destination address storage */
+	struct sockaddr remote_addr;
+
+	/** Private CoAP and networking structures */
+	struct coap_pending pendings[CONFIG_LWM2M_ENGINE_MAX_PENDING];
+	struct coap_reply replies[CONFIG_LWM2M_ENGINE_MAX_REPLIES];
+	struct k_delayed_work retransmit_work;
+	struct sys_mutex send_lock;
+
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+	/** TLS tag is set by client as a reference used when the
+	 *  LwM2M engine calls tls_credential_(add|delete)
+	 */
+	int tls_tag;
+
+	/** Client can set load_credentials function as a way of overriding
+	 *  the default behavior of load_tls_credential() in lwm2m_engine.c
+	 */
+	int (*load_credentials)(struct lwm2m_ctx *client_ctx);
+#endif
+	/** Flag to indicate if context should use DTLS.
+	 *  Enabled via the use of coaps:// protocol prefix in connection
+	 *  information.
+	 *  NOTE: requires CONFIG_LWM2M_DTLS_SUPPORT=y
+	 */
+	bool use_dtls;
+
+	/** Current index of Security Object used for server credentials */
+	int sec_obj_inst;
+
+	/** Current index of Server Object used in this context. */
+	int srv_obj_inst;
+
+	/** Flag to enable BOOTSTRAP interface.  See Section 5.2
+	 *  "Bootstrap Interface" of LwM2M Technical Specification 1.0.2
+	 *  for more information.
+	 */
+	bool bootstrap_mode;
+
+	/** This flag enables the context to handle an initial ACK after
+	 *  requesting a block of data, but a follow-up packet will contain
+	 *  actual data block.
+	 *  NOTE: This is required for CoAP proxy use-case.
+	 */
+	bool handle_separate_response;
+
+	/** Socket File Descriptor */
+	int sock_fd;
+};
+
+
+/**
+ * @brief Asynchronous callback to get a resource buffer and length.
+ *
+ * Prior to accessing the data buffer of a resource, the engine can
+ * use this callback to get the buffer pointer and length instead
+ * of using the resource's data buffer.
+ *
+ * The client or LwM2M objects can register a function of this type via:
+ * lwm2m_engine_register_read_callback()
+ * lwm2m_engine_register_pre_write_callback()
+ *
+ * @param[in] obj_inst_id Object instance ID generating the callback.
+ * @param[in] res_id Resource ID generating the callback.
+ * @param[in] res_inst_id Resource instance ID generating the callback
+ *                        (typically 0 for non-multi instance resources).
+ * @param[out] data_len Length of the data buffer.
+ *
+ * @return Callback returns a pointer to the data buffer or NULL for failure.
+ */
+typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id,
+					    uint16_t res_id,
+					    uint16_t res_inst_id,
+					    size_t *data_len);
+
+/**
+ * @brief Asynchronous callback when data has been set to a resource buffer.
+ *
+ * After changing the data of a resource buffer, the LwM2M engine can
+ * make use of this callback to pass the data back to the client or LwM2M
+ * objects.
+ *
+ * A function of this type can be registered via:
+ * lwm2m_engine_register_post_write_callback()
+ *
+ * @param[in] obj_inst_id Object instance ID generating the callback.
+ * @param[in] res_id Resource ID generating the callback.
+ * @param[in] res_inst_id Resource instance ID generating the callback
+ *                        (typically 0 for non-multi instance resources).
+ * @param[in] data Pointer to data.
+ * @param[in] data_len Length of the data.
+ * @param[in] last_block Flag used during block transfer to indicate the last
+ *                       block of data. For non-block transfers this is always
+ *                       false.
+ * @param[in] total_size Expected total size of data for a block transfer.
+ *                       For non-block transfers this is 0.
+ *
+ * @return Callback returns a negative error code (errno.h) indicating
+ *         reason of failure or 0 for success.
+ */
+typedef int (*lwm2m_engine_set_data_cb_t)(uint16_t obj_inst_id,
+					  uint16_t res_id, uint16_t res_inst_id,
+					  uint8_t *data, uint16_t data_len,
+					  bool last_block, size_t total_size);
+
+/**
+ * @brief Asynchronous event notification callback.
+ *
+ * Various object instance and resource-based events in the LwM2M engine
+ * can trigger a callback of this function type: object instance create,
+ * object instance delete and resource execute.
+ *
+ * Register a function of this type via:
+ * lwm2m_engine_register_exec_callback()
+ * lwm2m_engine_register_create_callback()
+ * lwm2m_engine_register_delete_callback()
+ *
+ * @param[in] obj_inst_id Object instance ID generating the callback.
+ *
+ * @return Callback returns a negative error code (errno.h) indicating
+ *         reason of failure or 0 for success.
+ */
+typedef int (*lwm2m_engine_user_cb_t)(uint16_t obj_inst_id);
+
+/**
+ * @brief Power source types used for the "Available Power Sources" resource of
+ * the LwM2M Device object.
+ */
+#define LWM2M_DEVICE_PWR_SRC_TYPE_DC_POWER	0
+#define LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT	1
+#define LWM2M_DEVICE_PWR_SRC_TYPE_BAT_EXT	2
+#define LWM2M_DEVICE_PWR_SRC_TYPE_UNUSED	3
+#define LWM2M_DEVICE_PWR_SRC_TYPE_PWR_OVER_ETH	4
+#define LWM2M_DEVICE_PWR_SRC_TYPE_USB		5
+#define LWM2M_DEVICE_PWR_SRC_TYPE_AC_POWER	6
+#define LWM2M_DEVICE_PWR_SRC_TYPE_SOLAR		7
+#define LWM2M_DEVICE_PWR_SRC_TYPE_MAX		8
+
+/**
+ * @brief Error codes used for the "Error Code" resource of the LwM2M Device
+ * object.  An LwM2M client can register one of the following error codes via
+ * the lwm2m_device_add_err() function.
+ */
+#define LWM2M_DEVICE_ERROR_NONE			0
+#define LWM2M_DEVICE_ERROR_LOW_POWER		1
+#define LWM2M_DEVICE_ERROR_EXT_POWER_SUPPLY_OFF	2
+#define LWM2M_DEVICE_ERROR_GPS_FAILURE		3
+#define LWM2M_DEVICE_ERROR_LOW_SIGNAL_STRENGTH	4
+#define LWM2M_DEVICE_ERROR_OUT_OF_MEMORY	5
+#define LWM2M_DEVICE_ERROR_SMS_FAILURE		6
+#define LWM2M_DEVICE_ERROR_NETWORK_FAILURE	7
+#define LWM2M_DEVICE_ERROR_PERIPHERAL_FAILURE	8
+
+/**
+ * @brief Battery status codes used for the "Battery Status" resource (3/0/20)
+ *        of the LwM2M Device object.  As the battery status changes, an LwM2M
+ *        client can set one of the following codes via:
+ *        lwm2m_engine_set_u8("3/0/20", [battery status])
+ */
+#define LWM2M_DEVICE_BATTERY_STATUS_NORMAL	0
+#define LWM2M_DEVICE_BATTERY_STATUS_CHARGING	1
+#define LWM2M_DEVICE_BATTERY_STATUS_CHARGE_COMP	2
+#define LWM2M_DEVICE_BATTERY_STATUS_DAMAGED	3
+#define LWM2M_DEVICE_BATTERY_STATUS_LOW		4
+#define LWM2M_DEVICE_BATTERY_STATUS_NOT_INST	5
+#define LWM2M_DEVICE_BATTERY_STATUS_UNKNOWN	6
+
+/**
+ * @brief Register a new error code with LwM2M Device object.
+ *
+ * @param[in] error_code New error code.
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_device_add_err(uint8_t error_code);
+
+
+/**
+ * @brief LWM2M Firmware Update object states
+ *
+ * An LwM2M client or the LwM2M Firmware Update object use the following codes
+ * to represent the LwM2M Firmware Update state (5/0/3).
+ */
+#define STATE_IDLE		0
+#define STATE_DOWNLOADING	1
+#define STATE_DOWNLOADED	2
+#define STATE_UPDATING		3
+
+/**
+ * @brief LWM2M Firmware Update object result codes
+ *
+ * After processing a firmware update, the client sets the result via one of
+ * the following codes via lwm2m_engine_set_u8("5/0/5", [result code])
+ */
+#define RESULT_DEFAULT		0
+#define RESULT_SUCCESS		1
+#define RESULT_NO_STORAGE	2
+#define RESULT_OUT_OF_MEM	3
+#define RESULT_CONNECTION_LOST	4
+#define RESULT_INTEGRITY_FAILED	5
+#define RESULT_UNSUP_FW		6
+#define RESULT_INVALID_URI	7
+#define RESULT_UPDATE_FAILED	8
+#define RESULT_UNSUP_PROTO	9
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
+/**
+ * @brief Set data callback for firmware block transfer.
+ *
+ * LwM2M clients use this function to register a callback for receiving the
+ * block transfer data when performing a firmware update.
+ *
+ * @param[in] cb A callback function to receive the block transfer data
+ */
+void lwm2m_firmware_set_write_cb(lwm2m_engine_set_data_cb_t cb);
+
+/**
+ * @brief Get the data callback for firmware block transfer writes.
+ *
+ * @return A registered callback function to receive the block transfer data
+ */
+lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb(void);
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT)
+/**
+ * @brief Set data callback to handle firmware update execute events.
+ *
+ * LwM2M clients use this function to register a callback for receiving the
+ * update resource "execute" operation on the LwM2M Firmware Update object.
+ *
+ * @param[in] cb A callback function to receive the execute event.
+ */
+void lwm2m_firmware_set_update_cb(lwm2m_engine_user_cb_t cb);
+
+/**
+ * @brief Get the event callback for firmware update execute events.
+ *
+ * @return A registered callback function to receive the execute event.
+ */
+lwm2m_engine_user_cb_t lwm2m_firmware_get_update_cb(void);
+
+/**
+ * @brief Get the block context of the current firmware block.
+ *
+ * @param[out] ctx A buffer to store the block context.
+ */
+struct coap_block_context *lwm2m_firmware_get_block_context();
+#endif
+#endif
+
+/**
+ * @brief Data structure used to represent the LwM2M float type:
+ * val1 is the whole number portion of the decimal
+ * val2 is the decimal portion *1000000 for 32bit, *1000000000 for 64bit
+ * Example: 123.456 == val1: 123, val2:456000
+ * Example: 123.000456 = val1: 123, val2:456
+ */
+
+/**
+ * @brief Maximum precision value for 32-bit LwM2M float val2
+ */
+#define LWM2M_FLOAT32_DEC_MAX 1000000
+
+/**
+ * @brief 32-bit variant of the LwM2M float structure
+ */
+typedef struct float32_value {
+	int32_t val1;
+	int32_t val2;
+} float32_value_t;
+
+/**
+ * @brief Maximum precision value for 64-bit LwM2M float val2
+ */
+#define LWM2M_FLOAT64_DEC_MAX 1000000000LL
+
+/**
+ * @brief 32-bit variant of the LwM2M float structure
+ */
+typedef struct float64_value {
+	int64_t val1;
+	int64_t val2;
+} float64_value_t;
+
+/**
+ * @brief Maximum value for ObjLnk resource fields
+ */
+#define LWM2M_OBJLNK_MAX_ID USHRT_MAX
+
+/**
+ * @brief LWM2M ObjLnk resource type structure
+ */
+struct lwm2m_objlnk {
+	uint16_t obj_id;
+	uint16_t obj_inst;
+};
+
+/**
+ * @brief Create an LwM2M object instance.
+ *
+ * LwM2M clients use this function to create non-default LwM2M objects:
+ * Example to create first temperature sensor object:
+ * lwm2m_engine_create_obj_inst("3303/0");
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst"
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_create_obj_inst(char *pathstr);
+
+/**
+ * @brief Set resource (instance) value (opaque buffer)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] data_ptr Data buffer
+ * @param[in] data_len Length of buffer
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_opaque(char *pathstr, char *data_ptr, uint16_t data_len);
+
+/**
+ * @brief Set resource (instance) value (string)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] data_ptr NULL terminated char buffer
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_string(char *pathstr, char *data_ptr);
+
+/**
+ * @brief Set resource (instance) value (u8)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value u8 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_u8(char *pathstr, uint8_t value);
+
+/**
+ * @brief Set resource (instance) value (u16)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value u16 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_u16(char *pathstr, uint16_t value);
+
+/**
+ * @brief Set resource (instance) value (u32)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value u32 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_u32(char *pathstr, uint32_t value);
+
+/**
+ * @brief Set resource (instance) value (u64)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value u64 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_u64(char *pathstr, uint64_t value);
+
+/**
+ * @brief Set resource (instance) value (s8)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value s8 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_s8(char *pathstr, int8_t value);
+
+/**
+ * @brief Set resource (instance) value (s16)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value s16 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_s16(char *pathstr, int16_t value);
+
+/**
+ * @brief Set resource (instance) value (s32)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value s32 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_s32(char *pathstr, int32_t value);
+
+/**
+ * @brief Set resource (instance) value (s64)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value s64 value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_s64(char *pathstr, int64_t value);
+
+/**
+ * @brief Set resource (instance) value (bool)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value bool value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_bool(char *pathstr, bool value);
+
+/**
+ * @brief Set resource (instance) value (32-bit float structure)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value 32-bit float value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value);
+
+/**
+ * @brief Set resource (instance) value (64-bit float structure)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value 64-bit float value
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value);
+
+/**
+ * @brief Set resource (instance) value (ObjLnk)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] value pointer to the lwm2m_objlnk structure
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value);
+
+/**
+ * @brief Get resource (instance) value (opaque buffer)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] buf Data buffer to copy data into
+ * @param[in] buflen Length of buffer
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_opaque(char *pathstr, void *buf, uint16_t buflen);
+
+/**
+ * @brief Get resource (instance) value (string)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] str String buffer to copy data into
+ * @param[in] strlen Length of buffer
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_string(char *pathstr, void *str, uint16_t strlen);
+
+/**
+ * @brief Get resource (instance) value (u8)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value u8 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_u8(char *pathstr, uint8_t *value);
+
+/**
+ * @brief Get resource (instance) value (u16)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value u16 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_u16(char *pathstr, uint16_t *value);
+
+/**
+ * @brief Get resource (instance) value (u32)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value u32 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_u32(char *pathstr, uint32_t *value);
+
+/**
+ * @brief Get resource (instance) value (u64)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value u64 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_u64(char *pathstr, uint64_t *value);
+
+/**
+ * @brief Get resource (instance) value (s8)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value s8 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_s8(char *pathstr, int8_t *value);
+
+/**
+ * @brief Get resource (instance) value (s16)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value s16 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_s16(char *pathstr, int16_t *value);
+
+/**
+ * @brief Get resource (instance) value (s32)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value s32 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_s32(char *pathstr, int32_t *value);
+
+/**
+ * @brief Get resource (instance) value (s64)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value s64 buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_s64(char *pathstr, int64_t *value);
+
+/**
+ * @brief Get resource (instance) value (bool)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] value bool buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_bool(char *pathstr, bool *value);
+
+/**
+ * @brief Get resource (instance) value (32-bit float structure)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] buf 32-bit float buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf);
+
+/**
+ * @brief Get resource (instance) value (64-bit float structure)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] buf 64-bit float buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf);
+
+/**
+ * @brief Get resource (instance) value (ObjLnk)
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] buf lwm2m_objlnk buffer to copy data into
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf);
+
+
+/**
+ * @brief Set resource (instance) read callback
+ *
+ * LwM2M clients can use this to set the callback function for resource reads.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] cb Read resource callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_read_callback(char *pathstr,
+					lwm2m_engine_get_data_cb_t cb);
+
+/**
+ * @brief Set resource (instance) pre-write callback
+ *
+ * This callback is triggered before setting the value of a resource.  It
+ * can pass a special data buffer to the engine so that the actual resource
+ * value can be calculated later, etc.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] cb Pre-write resource callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_pre_write_callback(char *pathstr,
+					     lwm2m_engine_get_data_cb_t cb);
+
+/**
+ * @brief Set resource (instance) post-write callback
+ *
+ * This callback is triggered after setting the value of a resource to the
+ * resource data buffer.
+ *
+ * It allows an LwM2M client or object to post-process the value of a resource
+ * or trigger other related resource calculations.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] cb Post-write resource callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_post_write_callback(char *pathstr,
+					      lwm2m_engine_set_data_cb_t cb);
+
+/**
+ * @brief Set resource execute event callback
+ *
+ * This event is triggered when the execute method of a resource is enabled.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res"
+ * @param[in] cb Execute resource callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_exec_callback(char *pathstr,
+					lwm2m_engine_user_cb_t cb);
+
+/**
+ * @brief Set object instance create event callback
+ *
+ * This event is triggered when an object instance is created.
+ *
+ * @param[in] obj_id LwM2M object id
+ * @param[in] cb Create object instance callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_create_callback(uint16_t obj_id,
+					  lwm2m_engine_user_cb_t cb);
+
+/**
+ * @brief Set object instance delete event callback
+ *
+ * This event is triggered when an object instance is deleted.
+ *
+ * @param[in] obj_id LwM2M object id
+ * @param[in] cb Delete object instance callback
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_register_delete_callback(uint16_t obj_id,
+					  lwm2m_engine_user_cb_t cb);
+
+/**
+ * @brief Resource read-only value bit
+ */
+#define LWM2M_RES_DATA_READ_ONLY	0
+
+/**
+ * @brief Resource read-only flag
+ */
+#define LWM2M_RES_DATA_FLAG_RO		BIT(LWM2M_RES_DATA_READ_ONLY)
+
+/**
+ * @brief Read resource flags helper macro
+ */
+#define LWM2M_HAS_RES_FLAG(res, f)	((res->data_flags & f) == f)
+
+/**
+ * @brief Set data buffer for a resource
+ *
+ * Use this function to set the data buffer and flags for the specified LwM2M
+ * resource.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[in] data_ptr Data buffer pointer
+ * @param[in] data_len Length of buffer
+ * @param[in] data_flags Data buffer flags (such as read-only, etc)
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, uint16_t data_len,
+			      uint8_t data_flags);
+
+/**
+ * @brief Get data buffer for a resource
+ *
+ * Use this function to get the data buffer information for the specified LwM2M
+ * resource.
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)"
+ * @param[out] data_ptr Data buffer pointer
+ * @param[out] data_len Length of buffer
+ * @param[out] data_flags Data buffer flags (such as read-only, etc)
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr,
+			      uint16_t *data_len, uint8_t *data_flags);
+
+/**
+ * @brief Create a resource instance
+ *
+ * LwM2M clients use this function to create multi-resource instances:
+ * Example to create 0 instance of device available power sources:
+ * lwm2m_engine_create_res_inst("3/0/6/0");
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res/res-inst"
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_create_res_inst(char *pathstr);
+
+/**
+ * @brief Delete a resource instance
+ *
+ * Use this function to remove an existing resource instance
+ *
+ * @param[in] pathstr LwM2M path string "obj/obj-inst/res/res-inst"
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_delete_res_inst(char *pathstr);
+
+/**
+ * @brief Start the LwM2M engine
+ *
+ * LwM2M clients normally do not need to call this function as it is called
+ * by lwm2m_rd_client_start().  However, if the client does not use the RD
+ * client implementation, it will need to be called manually.
+ *
+ * @param[in] client_ctx LwM2M context
+ *
+ * @return 0 for success or negative in case of error.
+ */
+int lwm2m_engine_start(struct lwm2m_ctx *client_ctx);
+
+/**
+ * @brief LwM2M RD client events
+ *
+ * LwM2M client events are passed back to the event_cb function in
+ * lwm2m_rd_client_start()
+ */
+enum lwm2m_rd_client_event {
+	LWM2M_RD_CLIENT_EVENT_NONE,
+	LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE,
+	LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE,
+	LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE,
+	LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE,
+	LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE,
+	LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE,
+	LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE,
+	LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE,
+	LWM2M_RD_CLIENT_EVENT_DISCONNECT,
+	LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF,
+};
+
+/*
+ * LwM2M RD client flags, used to configure LwM2M session.
+ */
+
+/**
+ * @brief Run bootstrap procedure in current session.
+ */
+#define LWM2M_RD_CLIENT_FLAG_BOOTSTRAP BIT(0)
+
+/**
+ * @brief Asynchronous RD client event callback
+ *
+ * @param[in] ctx LwM2M context generating the event
+ * @param[in] event LwM2M RD client event code
+ */
+typedef void (*lwm2m_ctx_event_cb_t)(struct lwm2m_ctx *ctx,
+				     enum lwm2m_rd_client_event event);
+
+/**
+ * @brief Start the LwM2M RD (Registration / Discovery) Client
+ *
+ * The RD client sits just above the LwM2M engine and performs the necessary
+ * actions to implement the "Registration interface".
+ * For more information see Section 5.3 "Client Registration Interface" of the
+ * LwM2M Technical Specification.
+ *
+ * NOTE: lwm2m_engine_start() is called automatically by this function.
+ *
+ * @param[in] client_ctx LwM2M context
+ * @param[in] ep_name Registered endpoint name
+ * @param[in] flags Flags used to configure current LwM2M session.
+ * @param[in] event_cb Client event callback function
+ */
+void lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, const char *ep_name,
+			   uint32_t flags, lwm2m_ctx_event_cb_t event_cb);
+
+/**
+ * @brief Stop the LwM2M RD (De-register) Client
+ *
+ * The RD client sits just above the LwM2M engine and performs the necessary
+ * actions to implement the "Registration interface".
+ * For more information see Section 5.3 "Client Registration Interface" of the
+ * LwM2M Technical Specification.
+ *
+ * @param[in] client_ctx LwM2M context
+ * @param[in] event_cb Client event callback function
+ */
+void lwm2m_rd_client_stop(struct lwm2m_ctx *client_ctx,
+			  lwm2m_ctx_event_cb_t event_cb);
+
+#endif	/* ZEPHYR_INCLUDE_NET_LWM2M_H_ */
+/**@}  */
Index: ModuleDemo/BLE/CM0/User/include/net/mii.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/mii.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/mii.h	(working copy)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016 Piotr Mienkowski
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief Definitions for IEEE 802.3, Section 2 MII compatible PHY transceivers
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_MII_H_
+#define ZEPHYR_INCLUDE_NET_MII_H_
+
+/**
+ * @brief Ethernet MII (media independent interface) functions
+ * @defgroup ethernet_mii Ethernet MII Support Functions
+ * @ingroup ethernet
+ * @{
+ */
+
+/* MII management registers */
+/** Basic Mode Control Register */
+#define MII_BMCR       0x0
+/** Basic Mode Status Register */
+#define MII_BMSR       0x1
+/** PHY ID 1 Register */
+#define MII_PHYID1R    0x2
+/** PHY ID 2 Register */
+#define MII_PHYID2R    0x3
+/** Auto-Negotiation Advertisement Register */
+#define MII_ANAR       0x4
+/** Auto-Negotiation Link Partner Ability Reg */
+#define MII_ANLPAR     0x5
+/** Auto-Negotiation Expansion Register */
+#define MII_ANER       0x6
+/** Auto-Negotiation Next Page Transmit Register */
+#define MII_ANNPTR     0x7
+/** Auto-Negotiation Link Partner Received Next Page Reg */
+#define MII_ANLPRNPR   0x8
+/** MMD Access Control Register */
+#define MII_MMD_ACR    0xd
+/** MMD Access Address Data Register */
+#define MII_MMD_AADR   0xe
+/** Extended Status Register */
+#define MII_ESTAT      0xf
+
+/* Basic Mode Control Register (BMCR) bit definitions */
+/** PHY reset */
+#define MII_BMCR_RESET             (1 << 15)
+/** enable loopback mode */
+#define MII_BMCR_LOOPBACK          (1 << 14)
+/** 10=1000Mbps 01=100Mbps; 00=10Mbps */
+#define MII_BMCR_SPEED_LSB         (1 << 13)
+/** Auto-Negotiation enable */
+#define MII_BMCR_AUTONEG_ENABLE    (1 << 12)
+/** power down mode */
+#define MII_BMCR_POWER_DOWN        (1 << 11)
+/** isolate electrically PHY from MII */
+#define MII_BMCR_ISOLATE           (1 << 10)
+/** restart auto-negotiation */
+#define MII_BMCR_AUTONEG_RESTART   (1 << 9)
+/** full duplex mode */
+#define MII_BMCR_DUPLEX_MODE       (1 << 8)
+/** 10=1000Mbps 01=100Mbps; 00=10Mbps */
+#define MII_BMCR_SPEED_MSB         (1 << 6)
+/** Link Speed Field */
+#define   MII_BMCR_SPEED_MASK      (1 << 6 | 1 << 13)
+/** select speed 10 Mb/s */
+#define   MII_BMCR_SPEED_10        (0 << 6 | 0 << 13)
+/** select speed 100 Mb/s */
+#define   MII_BMCR_SPEED_100       (0 << 6 | 1 << 13)
+/** select speed 1000 Mb/s */
+#define   MII_BMCR_SPEED_1000      (1 << 6 | 0 << 13)
+
+/* Basic Mode Status Register (BMSR) bit definitions */
+/** 100BASE-T4 capable */
+#define MII_BMSR_100BASE_T4        (1 << 15)
+/** 100BASE-X full duplex capable */
+#define MII_BMSR_100BASE_X_FULL    (1 << 14)
+/** 100BASE-X half duplex capable */
+#define MII_BMSR_100BASE_X_HALF    (1 << 13)
+/** 10 Mb/s full duplex capable */
+#define MII_BMSR_10_FULL           (1 << 12)
+/** 10 Mb/s half duplex capable */
+#define MII_BMSR_10_HALF           (1 << 11)
+/** 100BASE-T2 full duplex capable */
+#define MII_BMSR_100BASE_T2_FULL   (1 << 10)
+/** 100BASE-T2 half duplex capable */
+#define MII_BMSR_100BASE_T2_HALF   (1 << 9)
+/** extend status information in reg 15 */
+#define MII_BMSR_EXTEND_STATUS     (1 << 8)
+/** PHY accepts management frames with preamble suppressed */
+#define MII_BMSR_MF_PREAMB_SUPPR   (1 << 6)
+/** Auto-negotiation process completed */
+#define MII_BMSR_AUTONEG_COMPLETE  (1 << 5)
+/** remote fault detected */
+#define MII_BMSR_REMOTE_FAULT      (1 << 4)
+/** PHY is able to perform Auto-Negotiation */
+#define MII_BMSR_AUTONEG_ABILITY   (1 << 3)
+/** link is up */
+#define MII_BMSR_LINK_STATUS       (1 << 2)
+/** jabber condition detected */
+#define MII_BMSR_JABBER_DETECT     (1 << 1)
+/** extended register capabilities */
+#define MII_BMSR_EXTEND_CAPAB      (1 << 0)
+
+/* Auto-negotiation Advertisement Register (ANAR) bit definitions */
+/* Auto-negotiation Link Partner Ability Register (ANLPAR) bit definitions */
+/** next page */
+#define MII_ADVERTISE_NEXT_PAGE    (1 << 15)
+/** link partner acknowledge response */
+#define MII_ADVERTISE_LPACK        (1 << 14)
+/** remote fault */
+#define MII_ADVERTISE_REMOTE_FAULT (1 << 13)
+/** try for asymmetric pause */
+#define MII_ADVERTISE_ASYM_PAUSE   (1 << 11)
+/** try for pause */
+#define MII_ADVERTISE_PAUSE        (1 << 10)
+/** try for 100BASE-T4 support */
+#define MII_ADVERTISE_100BASE_T4   (1 << 9)
+/** try for 100BASE-X full duplex support */
+#define MII_ADVERTISE_100_FULL     (1 << 8)
+/** try for 100BASE-X support */
+#define MII_ADVERTISE_100_HALF     (1 << 7)
+/** try for 10 Mb/s full duplex support */
+#define MII_ADVERTISE_10_FULL      (1 << 6)
+/** try for 10 Mb/s half duplex support */
+#define MII_ADVERTISE_10_HALF      (1 << 5)
+/** Selector Field */
+#define MII_ADVERTISE_SEL_MASK     (0x1F << 0)
+#define MII_ADVERTISE_SEL_IEEE_802_3   0x01
+
+#define MII_ADVERTISE_ALL (MII_ADVERTISE_10_HALF | MII_ADVERTISE_10_FULL |\
+			   MII_ADVERTISE_100_HALF | MII_ADVERTISE_100_FULL |\
+			   MII_ADVERTISE_SEL_IEEE_802_3)
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_MII_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/mqtt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/mqtt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/mqtt.h	(working copy)
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt.h
+ *
+ * @defgroup mqtt_socket MQTT Client library
+ * @ingroup networking
+ * @{
+ * @brief MQTT Client Implementation
+ *
+ * @details
+ * MQTT Client's Application interface is defined in this header.
+ *
+ * @note The implementation assumes TCP module is enabled.
+ *
+ * @note By default the implementation uses MQTT version 3.1.1.
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_MQTT_H_
+#define ZEPHYR_INCLUDE_NET_MQTT_H_
+
+#include <stddef.h>
+
+#include <zephyr.h>
+#include <zephyr/types.h>
+#include <net/tls_credentials.h>
+#include <net/net_ip.h>
+#include <sys/mutex.h>
+#include <net/websocket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief MQTT Asynchronous Events notified to the application from the module
+ *        through the callback registered by the application.
+ */
+enum mqtt_evt_type {
+	/** Acknowledgment of connection request. Event result accompanying
+	 *  the event indicates whether the connection failed or succeeded.
+	 */
+	MQTT_EVT_CONNACK,
+
+	/** Disconnection Event. MQTT Client Reference is no longer valid once
+	 *  this event is received for the client.
+	 */
+	MQTT_EVT_DISCONNECT,
+
+	/** Publish event received when message is published on a topic client
+	 *  is subscribed to.
+	 *
+	 * @note PUBLISH event structure only contains payload size, the payload
+	 *       data parameter should be ignored. Payload content has to be
+	 *       read manually with @ref mqtt_read_publish_payload function.
+	 */
+	MQTT_EVT_PUBLISH,
+
+	/** Acknowledgment for published message with QoS 1. */
+	MQTT_EVT_PUBACK,
+
+	/** Reception confirmation for published message with QoS 2. */
+	MQTT_EVT_PUBREC,
+
+	/** Release of published message with QoS 2. */
+	MQTT_EVT_PUBREL,
+
+	/** Confirmation to a publish release message with QoS 2. */
+	MQTT_EVT_PUBCOMP,
+
+	/** Acknowledgment to a subscribe request. */
+	MQTT_EVT_SUBACK,
+
+	/** Acknowledgment to a unsubscribe request. */
+	MQTT_EVT_UNSUBACK,
+
+	/** Ping Response from server. */
+	MQTT_EVT_PINGRESP,
+};
+
+/** @brief MQTT version protocol level. */
+enum mqtt_version {
+	MQTT_VERSION_3_1_0 = 3, /**< Protocol level for 3.1.0. */
+	MQTT_VERSION_3_1_1 = 4  /**< Protocol level for 3.1.1. */
+};
+
+/** @brief MQTT Quality of Service types. */
+enum mqtt_qos {
+	/** Lowest Quality of Service, no acknowledgment needed for published
+	 *  message.
+	 */
+	MQTT_QOS_0_AT_MOST_ONCE = 0x00,
+
+	/** Medium Quality of Service, if acknowledgment expected for published
+	 *  message, duplicate messages permitted.
+	 */
+	MQTT_QOS_1_AT_LEAST_ONCE = 0x01,
+
+	/** Highest Quality of Service, acknowledgment expected and message
+	 *  shall be published only once. Message not published to interested
+	 *  parties unless client issues a PUBREL.
+	 */
+	MQTT_QOS_2_EXACTLY_ONCE  = 0x02
+};
+
+/** @brief MQTT CONNACK return codes. */
+enum mqtt_conn_return_code {
+	/** Connection accepted. */
+	MQTT_CONNECTION_ACCEPTED                = 0x00,
+
+	/** The Server does not support the level of the MQTT protocol
+	 * requested by the Client.
+	 */
+	MQTT_UNACCEPTABLE_PROTOCOL_VERSION      = 0x01,
+
+	/** The Client identifier is correct UTF-8 but not allowed by the
+	 *  Server.
+	 */
+	MQTT_IDENTIFIER_REJECTED                = 0x02,
+
+	/** The Network Connection has been made but the MQTT service is
+	 *  unavailable.
+	 */
+	MQTT_SERVER_UNAVAILABLE                 = 0x03,
+
+	/** The data in the user name or password is malformed. */
+	MQTT_BAD_USER_NAME_OR_PASSWORD          = 0x04,
+
+	/** The Client is not authorized to connect. */
+	MQTT_NOT_AUTHORIZED                     = 0x05
+};
+
+/** @brief MQTT SUBACK return codes. */
+enum mqtt_suback_return_code {
+	/** Subscription with QoS 0 succeeded. */
+	MQTT_SUBACK_SUCCESS_QoS_0 = 0x00,
+
+	/** Subscription with QoS 1 succeeded. */
+	MQTT_SUBACK_SUCCESS_QoS_1 = 0x01,
+
+	/** Subscription with QoS 2 succeeded. */
+	MQTT_SUBACK_SUCCESS_QoS_2 = 0x02,
+
+	/** Subscription for a topic failed. */
+	MQTT_SUBACK_FAILURE = 0x80
+};
+
+/** @brief Abstracts UTF-8 encoded strings. */
+struct mqtt_utf8 {
+	const uint8_t *utf8;       /**< Pointer to UTF-8 string. */
+	uint32_t size;             /**< Size of UTF string, in bytes. */
+};
+
+/**
+ * @brief Initialize UTF-8 encoded string from C literal string.
+ *
+ * Use it as follows:
+ *
+ * struct mqtt_utf8 password = MQTT_UTF8_LITERAL("my_pass");
+ *
+ * @param[in] literal Literal string from which to generate mqtt_utf8 object.
+ */
+#define MQTT_UTF8_LITERAL(literal)				\
+	((struct mqtt_utf8) {literal, sizeof(literal) - 1})
+
+/** @brief Abstracts binary strings. */
+struct mqtt_binstr {
+	uint8_t *data;             /**< Pointer to binary stream. */
+	uint32_t len;              /**< Length of binary stream. */
+};
+
+/** @brief Abstracts MQTT UTF-8 encoded topic that can be subscribed
+ *         to or published.
+ */
+struct mqtt_topic {
+	/** Topic on to be published or subscribed to. */
+	struct mqtt_utf8 topic;
+
+	/** Quality of service requested for the subscription.
+	 *  @ref mqtt_qos for details.
+	 */
+	uint8_t qos;
+};
+
+/** @brief Parameters for a publish message. */
+struct mqtt_publish_message {
+	struct mqtt_topic topic;     /**< Topic on which data was published. */
+	struct mqtt_binstr payload; /**< Payload on the topic published. */
+};
+
+/** @brief Parameters for a connection acknowledgment (CONNACK). */
+struct mqtt_connack_param {
+	/** The Session Present flag enables a Client to establish whether
+	 *  the Client and Server have a consistent view about whether there
+	 *  is already stored Session state.
+	 */
+	uint8_t session_present_flag;
+
+	/** The appropriate non-zero Connect return code indicates if the Server
+	 *  is unable to process a connection request for some reason.
+	 */
+	enum mqtt_conn_return_code return_code;
+};
+
+/** @brief Parameters for MQTT publish acknowledgment (PUBACK). */
+struct mqtt_puback_param {
+	uint16_t message_id;
+};
+
+/** @brief Parameters for MQTT publish receive (PUBREC). */
+struct mqtt_pubrec_param {
+	uint16_t message_id;
+};
+
+/** @brief Parameters for MQTT publish release (PUBREL). */
+struct mqtt_pubrel_param {
+	uint16_t message_id;
+};
+
+/** @brief Parameters for MQTT publish complete (PUBCOMP). */
+struct mqtt_pubcomp_param {
+	uint16_t message_id;
+};
+
+/** @brief Parameters for MQTT subscription acknowledgment (SUBACK). */
+struct mqtt_suback_param {
+	uint16_t message_id;
+	struct mqtt_binstr return_codes;
+};
+
+/** @brief Parameters for MQTT unsubscribe acknowledgment (UNSUBACK). */
+struct mqtt_unsuback_param {
+	uint16_t message_id;
+};
+
+/** @brief Parameters for a publish message. */
+struct mqtt_publish_param {
+	/** Messages including topic, QoS and its payload (if any)
+	 *  to be published.
+	 */
+	struct mqtt_publish_message message;
+
+	/** Message id used for the publish message. Redundant for QoS 0. */
+	uint16_t message_id;
+
+	/** Duplicate flag. If 1, it indicates the message is being
+	 *  retransmitted. Has no meaning with QoS 0.
+	 */
+	uint8_t dup_flag : 1;
+
+	/** Retain flag. If 1, the message shall be stored persistently
+	 *  by the broker.
+	 */
+	uint8_t retain_flag : 1;
+};
+
+/** @brief List of topics in a subscription request. */
+struct mqtt_subscription_list {
+	/** Array containing topics along with QoS for each. */
+	struct mqtt_topic *list;
+
+	/** Number of topics in the subscription list */
+	uint16_t list_count;
+
+	/** Message id used to identify subscription request. */
+	uint16_t message_id;
+};
+
+/**
+ * @brief Defines event parameters notified along with asynchronous events
+ *        to the application.
+ */
+union mqtt_evt_param {
+	/** Parameters accompanying MQTT_EVT_CONNACK event. */
+	struct mqtt_connack_param connack;
+
+	/** Parameters accompanying MQTT_EVT_PUBLISH event.
+	 *
+	 * @note PUBLISH event structure only contains payload size, the payload
+	 *       data parameter should be ignored. Payload content has to be
+	 *       read manually with @ref mqtt_read_publish_payload function.
+	 */
+	struct mqtt_publish_param publish;
+
+	/** Parameters accompanying MQTT_EVT_PUBACK event. */
+	struct mqtt_puback_param puback;
+
+	/** Parameters accompanying MQTT_EVT_PUBREC event. */
+	struct mqtt_pubrec_param pubrec;
+
+	/** Parameters accompanying MQTT_EVT_PUBREL event. */
+	struct mqtt_pubrel_param pubrel;
+
+	/** Parameters accompanying MQTT_EVT_PUBCOMP event. */
+	struct mqtt_pubcomp_param pubcomp;
+
+	/** Parameters accompanying MQTT_EVT_SUBACK event. */
+	struct mqtt_suback_param suback;
+
+	/** Parameters accompanying MQTT_EVT_UNSUBACK event. */
+	struct mqtt_unsuback_param unsuback;
+};
+
+/** @brief Defines MQTT asynchronous event notified to the application. */
+struct mqtt_evt {
+	/** Identifies the event. */
+	enum mqtt_evt_type type;
+
+	/** Contains parameters (if any) accompanying the event. */
+	union mqtt_evt_param param;
+
+	/** Event result. 0 or a negative error code (errno.h) indicating
+	 *  reason of failure.
+	 */
+	int result;
+};
+
+struct mqtt_client;
+
+/**
+ * @brief Asynchronous event notification callback registered by the
+ *        application.
+ *
+ * @param[in] client Identifies the client for which the event is notified.
+ * @param[in] evt Event description along with result and associated
+ *                parameters (if any).
+ */
+typedef void (*mqtt_evt_cb_t)(struct mqtt_client *client,
+			      const struct mqtt_evt *evt);
+
+/** @brief TLS configuration for secure MQTT transports. */
+struct mqtt_sec_config {
+	/** Indicates the preference for peer verification. */
+	int peer_verify;
+
+	/** Indicates the number of entries in the cipher list. */
+	uint32_t cipher_count;
+
+	/** Indicates the list of ciphers to be used for the session.
+	 *  May be NULL to use the default ciphers.
+	 */
+	int *cipher_list;
+
+	/** Indicates the number of entries in the sec tag list. */
+	uint32_t sec_tag_count;
+
+	/** Indicates the list of security tags to be used for the session. */
+	sec_tag_t *sec_tag_list;
+
+	/** Peer hostname for ceritificate verification.
+	 *  May be NULL to skip hostname verification.
+	 */
+	const char *hostname;
+};
+
+/** @brief MQTT transport type. */
+enum mqtt_transport_type {
+	/** Use non secure TCP transport for MQTT connection. */
+	MQTT_TRANSPORT_NON_SECURE,
+
+#if defined(CONFIG_MQTT_LIB_TLS)
+	/** Use secure TCP transport (TLS) for MQTT connection. */
+	MQTT_TRANSPORT_SECURE,
+#endif /* CONFIG_MQTT_LIB_TLS */
+
+#if defined(CONFIG_MQTT_LIB_WEBSOCKET)
+	/** Use non secure Websocket transport for MQTT connection. */
+	MQTT_TRANSPORT_NON_SECURE_WEBSOCKET,
+#if defined(CONFIG_MQTT_LIB_TLS)
+	/** Use secure Websocket transport (TLS) for MQTT connection. */
+	MQTT_TRANSPORT_SECURE_WEBSOCKET,
+#endif
+#endif /* CONFIG_MQTT_LIB_WEBSOCKET */
+
+	/** Shall not be used as a transport type.
+	 *  Indicator of maximum transport types possible.
+	 */
+	MQTT_TRANSPORT_NUM
+};
+
+/** @brief MQTT transport specific data. */
+struct mqtt_transport {
+	/** Transport type selection for client instance.
+	 *  @ref mqtt_transport_type for possible values. MQTT_TRANSPORT_MAX
+	 *  is not a valid type.
+	 */
+	enum mqtt_transport_type type;
+
+	union {
+		/* TCP socket transport for MQTT */
+		struct {
+			/** Socket descriptor. */
+			int sock;
+		} tcp;
+
+#if defined(CONFIG_MQTT_LIB_TLS)
+		/* TLS socket transport for MQTT */
+		struct {
+			/** Socket descriptor. */
+			int sock;
+
+			/** TLS configuration. See @ref mqtt_sec_config for
+			 *  details.
+			 */
+			struct mqtt_sec_config config;
+		} tls;
+#endif /* CONFIG_MQTT_LIB_TLS */
+	};
+
+#if defined(CONFIG_MQTT_LIB_WEBSOCKET)
+	/** Websocket transport for MQTT */
+	struct {
+		/** Websocket configuration. */
+		struct websocket_request config;
+
+		/** Socket descriptor */
+		int sock;
+
+		/** Websocket timeout, in milliseconds. */
+		int32_t timeout;
+	} websocket;
+#endif
+
+#if defined(CONFIG_SOCKS)
+	struct {
+		struct sockaddr addr;
+		socklen_t addrlen;
+	} proxy;
+#endif
+};
+
+/** @brief MQTT internal state. */
+struct mqtt_internal {
+	/** Internal. Mutex to protect access to the client instance. */
+	struct sys_mutex mutex;
+
+	/** Internal. Wall clock value (in milliseconds) of the last activity
+	 *  that occurred. Needed for periodic PING.
+	 */
+	uint32_t last_activity;
+
+	/** Internal. Client's state in the connection. */
+	uint32_t state;
+
+	/** Internal.  Packet length read so far. */
+	uint32_t rx_buf_datalen;
+
+	/** Internal. Remaining payload length to read. */
+	uint32_t remaining_payload;
+};
+
+/**
+ * @brief MQTT Client definition to maintain information relevant to the
+ *        client.
+ */
+struct mqtt_client {
+	/** MQTT client internal state. */
+	struct mqtt_internal internal;
+
+	/** MQTT transport configuration and data. */
+	struct mqtt_transport transport;
+
+	/** Unique client identification to be used for the connection. */
+	struct mqtt_utf8 client_id;
+
+	/** Broker details, for example, address, port. Address type should
+	 *  be compatible with transport used.
+	 */
+	const void *broker;
+
+	/** User name (if any) to be used for the connection. NULL indicates
+	 *  no user name.
+	 */
+	struct mqtt_utf8 *user_name;
+
+	/** Password (if any) to be used for the connection. Note that if
+	 *  password is provided, user name shall also be provided. NULL
+	 *  indicates no password.
+	 */
+	struct mqtt_utf8 *password;
+
+	/** Will topic and QoS. Can be NULL. */
+	struct mqtt_topic *will_topic;
+
+	/** Will message. Can be NULL. Non NULL value valid only if will topic
+	 *  is not NULL.
+	 */
+	struct mqtt_utf8 *will_message;
+
+	/** Application callback registered with the module to get MQTT events.
+	 */
+	mqtt_evt_cb_t evt_cb;
+
+	/** Receive buffer used for MQTT packet reception in RX path. */
+	uint8_t *rx_buf;
+
+	/** Size of receive buffer. */
+	uint32_t rx_buf_size;
+
+	/** Transmit buffer used for creating MQTT packet in TX path. */
+	uint8_t *tx_buf;
+
+	/** Size of transmit buffer. */
+	uint32_t tx_buf_size;
+
+	/** Keepalive interval for this client in seconds.
+	 *  Default is CONFIG_MQTT_KEEPALIVE.
+	 */
+	uint16_t keepalive;
+
+	/** MQTT protocol version. */
+	uint8_t protocol_version;
+
+	/** Unanswered PINGREQ count on this connection. */
+	int8_t unacked_ping;
+
+	/** Will retain flag, 1 if will message shall be retained persistently.
+	 */
+	uint8_t will_retain : 1;
+
+	/** Clean session flag indicating a fresh (1) or a retained session (0).
+	 *  Default is CONFIG_MQTT_CLEAN_SESSION.
+	 */
+	uint8_t clean_session : 1;
+};
+
+/**
+ * @brief Initializes the client instance.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ *
+ * @note Shall be called to initialize client structure, before setting any
+ *       client parameters and before connecting to broker.
+ */
+void mqtt_client_init(struct mqtt_client *client);
+
+#if defined(CONFIG_SOCKS)
+/*
+ * @brief Set proxy server details
+ *
+ * @param[in] client Client instance for which the procedure is requested,
+ *                   Shall not be NULL.
+ * @param[in] proxy_addr Proxy server address.
+ * @param[in] addrlen Proxy server address length.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ *
+ * @note Must be called before calling mqtt_connect().
+ */
+int mqtt_client_set_proxy(struct mqtt_client *client,
+			  struct sockaddr *proxy_addr,
+			  socklen_t addrlen);
+#endif
+
+/**
+ * @brief API to request new MQTT client connection.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ *
+ * @note This memory is assumed to be resident until mqtt_disconnect is called.
+ * @note Any subsequent changes to parameters like broker address, user name,
+ *       device id, etc. have no effect once MQTT connection is established.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ *
+ * @note Default protocol revision used for connection request is 3.1.1. Please
+ *       set client.protocol_version = MQTT_VERSION_3_1_0 to use protocol 3.1.0.
+ * @note
+ *       Please modify @option{CONFIG_MQTT_KEEPALIVE} time to override default
+ *       of 1 minute.
+ */
+int mqtt_connect(struct mqtt_client *client);
+
+/**
+ * @brief API to publish messages on topics.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[in] param Parameters to be used for the publish message.
+ *                  Shall not be NULL.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_publish(struct mqtt_client *client,
+		 const struct mqtt_publish_param *param);
+
+/**
+ * @brief API used by client to send acknowledgment on receiving QoS1 publish
+ *        message. Should be called on reception of @ref MQTT_EVT_PUBLISH with
+ *        QoS level @ref MQTT_QOS_1_AT_LEAST_ONCE.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[in] param Identifies message being acknowledged.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_publish_qos1_ack(struct mqtt_client *client,
+			  const struct mqtt_puback_param *param);
+
+/**
+ * @brief API used by client to send acknowledgment on receiving QoS2 publish
+ *        message. Should be called on reception of @ref MQTT_EVT_PUBLISH with
+ *        QoS level @ref MQTT_QOS_2_EXACTLY_ONCE.
+ *
+ * @param[in] client Identifies client instance for which the procedure is
+ *                   requested. Shall not be NULL.
+ * @param[in] param Identifies message being acknowledged.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_publish_qos2_receive(struct mqtt_client *client,
+			      const struct mqtt_pubrec_param *param);
+
+/**
+ * @brief API used by client to request release of QoS2 publish message.
+ *        Should be called on reception of @ref MQTT_EVT_PUBREC.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[in] param Identifies message being released.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_publish_qos2_release(struct mqtt_client *client,
+			      const struct mqtt_pubrel_param *param);
+
+/**
+ * @brief API used by client to send acknowledgment on receiving QoS2 publish
+ *        release message. Should be called on reception of
+ *        @ref MQTT_EVT_PUBREL.
+ *
+ * @param[in] client Identifies client instance for which the procedure is
+ *                   requested. Shall not be NULL.
+ * @param[in] param Identifies message being completed.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_publish_qos2_complete(struct mqtt_client *client,
+			       const struct mqtt_pubcomp_param *param);
+
+/**
+ * @brief API to request subscription of one or more topics on the connection.
+ *
+ * @param[in] client Identifies client instance for which the procedure
+ *                   is requested. Shall not be NULL.
+ * @param[in] param Subscription parameters. Shall not be NULL.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_subscribe(struct mqtt_client *client,
+		   const struct mqtt_subscription_list *param);
+
+/**
+ * @brief API to request unsubscription of one or more topics on the connection.
+ *
+ * @param[in] client Identifies client instance for which the procedure is
+ *                   requested. Shall not be NULL.
+ * @param[in] param Parameters describing topics being unsubscribed from.
+ *                  Shall not be NULL.
+ *
+ * @note QoS included in topic description is unused in this API.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_unsubscribe(struct mqtt_client *client,
+		     const struct mqtt_subscription_list *param);
+
+/**
+ * @brief API to send MQTT ping. The use of this API is optional, as the library
+ *        handles the connection keep-alive on it's own, see @ref mqtt_live.
+ *
+ * @param[in] client Identifies client instance for which procedure is
+ *                   requested.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_ping(struct mqtt_client *client);
+
+/**
+ * @brief API to disconnect MQTT connection.
+ *
+ * @param[in] client Identifies client instance for which procedure is
+ *                   requested.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_disconnect(struct mqtt_client *client);
+
+/**
+ * @brief API to abort MQTT connection. This will close the corresponding
+ *        transport without closing the connection gracefully at the MQTT level
+ *        (with disconnect message).
+ *
+ * @param[in] client Identifies client instance for which procedure is
+ *                   requested.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_abort(struct mqtt_client *client);
+
+/**
+ * @brief This API should be called periodically for the client to be able
+ *        to keep the connection alive by sending Ping Requests if need be.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ *
+ * @note  Application shall ensure that the periodicity of calling this function
+ *        makes it possible to respect the Keep Alive time agreed with the
+ *        broker on connection. @ref mqtt_connect for details on Keep Alive
+ *        time.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_live(struct mqtt_client *client);
+
+/**
+ * @brief Helper function to determine when next keep alive message should be
+ *        sent. Can be used for instance as a source for `poll` timeout.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *
+ * @return Time in milliseconds until next keep alive message is expected to
+ *         be sent. Function will return UINT32_MAX if keep alive messages are
+ *         not enabled.
+ */
+uint32_t mqtt_keepalive_time_left(const struct mqtt_client *client);
+
+/**
+ * @brief Receive an incoming MQTT packet. The registered callback will be
+ *        called with the packet content.
+ *
+ * @note In case of PUBLISH message, the payload has to be read separately with
+ *       @ref mqtt_read_publish_payload function. The size of the payload to
+ *       read is provided in the publish event structure.
+ *
+ * @note This is a non-blocking call.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ *
+ * @return 0 or a negative error code (errno.h) indicating reason of failure.
+ */
+int mqtt_input(struct mqtt_client *client);
+
+/**
+ * @brief Read the payload of the received PUBLISH message. This function should
+ *        be called within the MQTT event handler, when MQTT PUBLISH message is
+ *        notified.
+ *
+ * @note This is a non-blocking call.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[out] buffer Buffer where payload should be stored.
+ * @param[in] length Length of the buffer, in bytes.
+ *
+ * @return Number of bytes read or a negative error code (errno.h) indicating
+ *         reason of failure.
+ */
+int mqtt_read_publish_payload(struct mqtt_client *client, void *buffer,
+			      size_t length);
+
+/**
+ * @brief Blocking version of @ref mqtt_read_publish_payload function.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[out] buffer Buffer where payload should be stored.
+ * @param[in] length Length of the buffer, in bytes.
+ *
+ * @return Number of bytes read or a negative error code (errno.h) indicating
+ *         reason of failure.
+ */
+int mqtt_read_publish_payload_blocking(struct mqtt_client *client, void *buffer,
+				       size_t length);
+
+/**
+ * @brief Blocking version of @ref mqtt_read_publish_payload function which
+ *        runs until the required number of bytes are read.
+ *
+ * @param[in] client Client instance for which the procedure is requested.
+ *                   Shall not be NULL.
+ * @param[out] buffer Buffer where payload should be stored.
+ * @param[in] length Number of bytes to read.
+ *
+ * @return 0 if success, otherwise a negative error code (errno.h) indicating
+ *         reason of failure.
+ */
+int mqtt_readall_publish_payload(struct mqtt_client *client, uint8_t *buffer,
+				 size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_MQTT_H_ */
+
+/**@}  */
Index: ModuleDemo/BLE/CM0/User/include/net/net_config.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_config.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_config.h	(working copy)
@@ -0,0 +1,107 @@
+/** @file
+ * @brief Routines for network subsystem initialization.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_CONFIG_H_
+#define ZEPHYR_INCLUDE_NET_NET_CONFIG_H_
+
+#include <zephyr/types.h>
+#include <device.h>
+#include <net/net_if.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network configuration library
+ * @defgroup net_config Network Configuration Library
+ * @ingroup networking
+ * @{
+ */
+
+/* Flags that tell what kind of functionality is needed by the client. */
+/**
+ * @brief Application needs routers to be set so that connectivity to remote
+ * network is possible. For IPv6 networks, this means that the device should
+ * receive IPv6 router advertisement message before continuing.
+ */
+#define NET_CONFIG_NEED_ROUTER 0x00000001
+
+/**
+ * @brief Application needs IPv6 subsystem configured and initialized.
+ * Typically this means that the device has IPv6 address set.
+ */
+#define NET_CONFIG_NEED_IPV6   0x00000002
+
+/**
+ * @brief Application needs IPv4 subsystem configured and initialized.
+ * Typically this means that the device has IPv4 address set.
+ */
+#define NET_CONFIG_NEED_IPV4   0x00000004
+
+/**
+ * @brief Initialize this network application.
+ *
+ * @details This will call net_config_init_by_iface() with NULL network
+ *          interface.
+ *
+ * @param app_info String describing this application.
+ * @param flags Flags related to services needed by the client.
+ * @param timeout How long to wait the network setup before continuing
+ * the startup.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int net_config_init(const char *app_info, uint32_t flags, int32_t timeout);
+
+/**
+ * @brief Initialize this network application using a specific network
+ * interface.
+ *
+ * @details If network interface is set to NULL, then the default one
+ *          is used in the configuration.
+ *
+ * @param iface Initialize networking using this network interface.
+ * @param app_info String describing this application.
+ * @param flags Flags related to services needed by the client.
+ * @param timeout How long to wait the network setup before continuing
+ * the startup.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int net_config_init_by_iface(struct net_if *iface, const char *app_info,
+			     uint32_t flags, int32_t timeout);
+
+/**
+ * @brief Initialize this network application.
+ *
+ * @details If CONFIG_NET_CONFIG_AUTO_INIT is set, then this function is called
+ *          automatically when the device boots. If that is not desired, unset
+ *          the config option and call the function manually when the
+ *          application starts.
+ *
+ * @param device Network device to use. The function will figure out what
+ *        network interface to use based on the device. If the device is NULL,
+ *        then default network interface is used by the function.
+ * @param app_info String describing this application.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int net_config_init_app(const struct device *device, const char *app_info);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_CONFIG_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_conn_mgr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_conn_mgr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_conn_mgr.h	(working copy)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_CONN_MGR_H_
+#define ZEPHYR_INCLUDE_NET_CONN_MGR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_NET_CONNECTION_MANAGER)
+
+void net_conn_mgr_resend_status(void);
+
+#else
+
+#define net_conn_mgr_resend_status(...)
+
+#endif /* CONFIG_NET_CONNECTION_MANAGER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_CONN_MGR_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_context.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_context.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_context.h	(working copy)
@@ -0,0 +1,1136 @@
+/** @file
+ * @brief Network context definitions
+ *
+ * An API for applications to define a network connection.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_CONTEXT_H_
+#define ZEPHYR_INCLUDE_NET_NET_CONTEXT_H_
+
+/**
+ * @brief Application network context
+ * @defgroup net_context Application network context
+ * @ingroup networking
+ * @{
+ */
+
+#include <kernel.h>
+#include <sys/atomic.h>
+
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <net/net_stats.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Is this context used or not */
+#define NET_CONTEXT_IN_USE BIT(0)
+
+/** State of the context (bits 1 & 2 in the flags) */
+enum net_context_state {
+	NET_CONTEXT_IDLE = 0,
+	NET_CONTEXT_UNCONNECTED = 0,
+	NET_CONTEXT_CONFIGURING = 1,
+	NET_CONTEXT_CONNECTING = 1,
+	NET_CONTEXT_READY = 2,
+	NET_CONTEXT_CONNECTED = 2,
+	NET_CONTEXT_LISTENING = 3,
+};
+
+/**
+ * The address family, connection type and IP protocol are
+ * stored into a bit field to save space.
+ */
+/** Protocol family of this connection */
+#define NET_CONTEXT_FAMILY (BIT(3) | BIT(4) | BIT(5))
+
+/** Type of the connection (datagram / stream / raw) */
+#define NET_CONTEXT_TYPE   (BIT(6) | BIT(7))
+
+/** Remote address set */
+#define NET_CONTEXT_REMOTE_ADDR_SET  BIT(8)
+
+/** Is the socket accepting connections */
+#define NET_CONTEXT_ACCEPTING_SOCK  BIT(9)
+
+/** Is the socket closing / closed */
+#define NET_CONTEXT_CLOSING_SOCK  BIT(10)
+
+struct net_context;
+
+/**
+ * @typedef net_context_recv_cb_t
+ * @brief Network data receive callback.
+ *
+ * @details The recv callback is called after a network data packet is
+ * received. This callback is called by RX thread so its stack and execution
+ * context is used here. Keep processing in the callback minimal to reduce the
+ * time spent blocked while handling packets.
+ *
+ * @param context The context to use.
+ * @param pkt Network buffer that is received. If the pkt is not NULL,
+ * then the callback will own the buffer and it needs to to unref the pkt
+ * as soon as it has finished working with it.  On EOF, pkt will be NULL.
+ * @param ip_hdr a pointer to relevant IP (v4 or v6) header.
+ * @param proto_hdr a pointer to relevant protocol (udp or tcp) header.
+ * @param status Value is set to 0 if some data or the connection is
+ * at EOF, <0 if there was an error receiving data, in this case the
+ * pkt parameter is set to NULL.
+ * @param user_data The user data given in net_recv() call.
+ */
+typedef void (*net_context_recv_cb_t)(struct net_context *context,
+				      struct net_pkt *pkt,
+				      union net_ip_header *ip_hdr,
+				      union net_proto_header *proto_hdr,
+				      int status,
+				      void *user_data);
+
+/**
+ * @typedef net_context_send_cb_t
+ * @brief Network data send callback.
+ *
+ * @details The send callback is called after a network data packet is sent.
+ * This callback is called by TX thread so its stack and execution context is
+ * used here. Keep processing in the callback minimal to reduce the time spent
+ * blocked while handling packets.
+ *
+ * @param context The context to use.
+ * @param status Value is set to >= 0: amount of data that was sent,
+ * < 0 there was an error sending data.
+ * @param user_data The user data given in net_send() call.
+ */
+typedef void (*net_context_send_cb_t)(struct net_context *context,
+				      int status,
+				      void *user_data);
+
+/**
+ * @typedef net_tcp_accept_cb_t
+ * @brief Accept callback
+ *
+ * @details The accept callback is called after a successful connection was
+ * established or if there was an error while we were waiting for a connection
+ * attempt. This callback is called by RX thread so its stack and execution
+ * context is used here. Keep processing in the callback minimal to reduce the
+ * time spent blocked while handling packets.
+ *
+ * @param context The context to use.
+ * @param addr The peer address.
+ * @param addrlen Length of the peer address.
+ * @param status The status code, 0 on success, < 0 otherwise
+ * @param user_data The user data given in net_context_accept() call.
+ */
+typedef void (*net_tcp_accept_cb_t)(struct net_context *new_context,
+				    struct sockaddr *addr,
+				    socklen_t addrlen,
+				    int status,
+				    void *user_data);
+
+/**
+ * @typedef net_context_connect_cb_t
+ * @brief Connection callback.
+ *
+ * @details The connect callback is called after a connection is being
+ * established.
+ * For TCP connections, this callback is called by RX thread so its stack and
+ * execution context is used here. The callback is called after the TCP
+ * connection was established or if the connection failed. Keep processing in
+ * the callback minimal to reduce the time spent blocked while handling
+ * packets.
+ * For UDP connections, this callback is called immediately by
+ * net_context_connect() function. UDP is a connectionless protocol so the
+ * connection can be thought of being established immediately.
+ *
+ * @param context The context to use.
+ * @param status Status of the connection establishment. This is 0
+ * if the connection was established successfully, <0 if there was an
+ * error.
+ * @param user_data The user data given in net_context_connect() call.
+ */
+typedef void (*net_context_connect_cb_t)(struct net_context *context,
+					 int status,
+					 void *user_data);
+
+/* The net_pkt_get_slab_func_t is here in order to avoid circular
+ * dependency between net_pkt.h and net_context.h
+ */
+/**
+ * @typedef net_pkt_get_slab_func_t
+ *
+ * @brief Function that is called to get the slab that is used
+ * for net_pkt allocations.
+ *
+ * @return Pointer to valid struct k_mem_slab instance.
+ */
+typedef struct k_mem_slab *(*net_pkt_get_slab_func_t)(void);
+
+/* The net_pkt_get_pool_func_t is here in order to avoid circular
+ * dependency between net_pkt.h and net_context.h
+ */
+/**
+ * @typedef net_pkt_get_pool_func_t
+ *
+ * @brief Function that is called to get the pool that is used
+ * for net_buf allocations.
+ *
+ * @return Pointer to valid struct net_buf_pool instance.
+ */
+typedef struct net_buf_pool *(*net_pkt_get_pool_func_t)(void);
+
+struct net_tcp;
+
+struct net_conn_handle;
+
+/**
+ * Note that we do not store the actual source IP address in the context
+ * because the address is already be set in the network interface struct.
+ * If there is no such source address there, the packet cannot be sent
+ * anyway. This saves 12 bytes / context in IPv6.
+ */
+__net_socket struct net_context {
+	/** User data.
+	 *
+	 *  First member of the structure to let users either have user data
+	 *  associated with a context, or put contexts into a FIFO.
+	 */
+	void *user_data;
+
+	/** Reference count
+	 */
+	atomic_t refcount;
+
+	/** Internal lock for protecting this context from multiple access.
+	 */
+	struct k_mutex lock;
+
+	/** Local endpoint address. Note that the values are in network byte
+	 * order.
+	 */
+	struct sockaddr_ptr local;
+
+	/** Remote endpoint address. Note that the values are in network byte
+	 * order.
+	 */
+	struct sockaddr remote;
+
+	/** Connection handle */
+	struct net_conn_handle *conn_handler;
+
+	/** Receive callback to be called when desired packet
+	 * has been received.
+	 */
+	net_context_recv_cb_t recv_cb;
+
+	/** Send callback to be called when the packet has been sent
+	 * successfully.
+	 */
+	net_context_send_cb_t send_cb;
+
+	/** Connect callback to be called when a connection has been
+	 *  established.
+	 */
+	net_context_connect_cb_t connect_cb;
+
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+	/** Get TX net_buf pool for this context.
+	 */
+	net_pkt_get_slab_func_t tx_slab;
+
+	/** Get DATA net_buf pool for this context.
+	 */
+	net_pkt_get_pool_func_t data_pool;
+#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
+
+#if defined(CONFIG_NET_TCP1)
+	/** TCP connection information */
+	struct net_tcp *tcp;
+#endif /* CONFIG_NET_TCP1 */
+
+#if defined(CONFIG_NET_TCP2)
+	/** TCP connection information */
+	void *tcp;
+#endif /* CONFIG_NET_TCP2 */
+
+#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
+	/**
+	 * Semaphore to signal synchronous recv call completion.
+	 */
+	struct k_sem recv_data_wait;
+#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
+
+#if defined(CONFIG_NET_SOCKETS)
+	/** BSD socket private data */
+	void *socket_data;
+
+	/** Per-socket packet or connection queues */
+	union {
+		struct k_fifo recv_q;
+		struct k_fifo accept_q;
+	};
+
+#endif /* CONFIG_NET_SOCKETS */
+
+#if defined(CONFIG_NET_OFFLOAD)
+	/** context for use by offload drivers */
+	void *offload_context;
+#endif /* CONFIG_NET_OFFLOAD */
+
+#if defined(CONFIG_NET_SOCKETS_CAN)
+	int can_filter_id;
+#endif /* CONFIG_NET_SOCKETS_CAN */
+
+	/** Option values */
+	struct {
+#if defined(CONFIG_NET_CONTEXT_PRIORITY)
+		/** Priority of the network data sent via this net_context */
+		uint8_t priority;
+#endif
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+		bool timestamp;
+#endif
+#if defined(CONFIG_NET_CONTEXT_TXTIME)
+		bool txtime;
+#endif
+#if defined(CONFIG_SOCKS)
+		struct {
+			struct sockaddr addr;
+			socklen_t addrlen;
+		} proxy;
+#endif
+	} options;
+
+	/** Protocol (UDP, TCP or IEEE 802.3 protocol value) */
+	uint16_t proto;
+
+	/** Flags for the context */
+	uint16_t flags;
+
+	/** Network interface assigned to this context */
+	int8_t iface;
+
+	/** IPv6 hop limit or IPv4 ttl for packets sent via this context. */
+	union {
+		uint8_t ipv6_hop_limit;
+		uint8_t ipv4_ttl;
+	};
+
+#if defined(CONFIG_SOCKS)
+	bool proxy_enabled;
+#endif
+
+};
+
+static inline bool net_context_is_used(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return context->flags & NET_CONTEXT_IN_USE;
+}
+
+/**
+ * @brief Is this context is accepting data now.
+ *
+ * @param context Network context.
+ *
+ * @return True if the context is accepting connections, False otherwise.
+ */
+static inline bool net_context_is_accepting(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return context->flags & NET_CONTEXT_ACCEPTING_SOCK;
+}
+
+/**
+ * @brief Set this context to accept data now.
+ *
+ * @param context Network context.
+ * @param accepting True if accepting, False if not
+ */
+static inline void net_context_set_accepting(struct net_context *context,
+					     bool accepting)
+{
+	NET_ASSERT(context);
+
+	if (accepting) {
+		context->flags |= NET_CONTEXT_ACCEPTING_SOCK;
+	} else {
+		context->flags &= ~NET_CONTEXT_ACCEPTING_SOCK;
+	}
+}
+
+/**
+ * @brief Is this context closing.
+ *
+ * @param context Network context.
+ *
+ * @return True if the context is closing, False otherwise.
+ */
+static inline bool net_context_is_closing(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return context->flags & NET_CONTEXT_CLOSING_SOCK;
+}
+
+/**
+ * @brief Set this context to closing.
+ *
+ * @param context Network context.
+ * @param closing True if closing, False if not
+ */
+static inline void net_context_set_closing(struct net_context *context,
+					   bool closing)
+{
+	NET_ASSERT(context);
+
+	if (closing) {
+		context->flags |= NET_CONTEXT_CLOSING_SOCK;
+	} else {
+		context->flags &= ~NET_CONTEXT_CLOSING_SOCK;
+	}
+}
+
+#define NET_CONTEXT_STATE_SHIFT 1
+#define NET_CONTEXT_STATE_MASK 0x03
+
+/**
+ * @brief Get state for this network context.
+ *
+ * @details This function returns the state of the context.
+ *
+ * @param context Network context.
+ *
+ * @return Network state.
+ */
+static inline
+enum net_context_state net_context_get_state(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return (enum net_context_state)
+		((context->flags >> NET_CONTEXT_STATE_SHIFT) &
+		NET_CONTEXT_STATE_MASK);
+}
+
+/**
+ * @brief Set state for this network context.
+ *
+ * @details This function sets the state of the context.
+ *
+ * @param context Network context.
+ * @param state New network context state.
+ */
+static inline void net_context_set_state(struct net_context *context,
+					 enum net_context_state state)
+{
+	NET_ASSERT(context);
+
+	context->flags &= ~(NET_CONTEXT_STATE_MASK << NET_CONTEXT_STATE_SHIFT);
+	context->flags |= ((state & NET_CONTEXT_STATE_MASK) <<
+			   NET_CONTEXT_STATE_SHIFT);
+}
+
+/**
+ * @brief Get address family for this network context.
+ *
+ * @details This function returns the address family (IPv4 or IPv6)
+ * of the context.
+ *
+ * @param context Network context.
+ *
+ * @return Network state.
+ */
+static inline sa_family_t net_context_get_family(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return ((context->flags & NET_CONTEXT_FAMILY) >> 3);
+}
+
+/**
+ * @brief Set address family for this network context.
+ *
+ * @details This function sets the address family (IPv4, IPv6 or AF_PACKET)
+ * of the context.
+ *
+ * @param context Network context.
+ * @param family Address family (AF_INET, AF_INET6, AF_PACKET, AF_CAN)
+ */
+static inline void net_context_set_family(struct net_context *context,
+					  sa_family_t family)
+{
+	uint8_t flag = 0U;
+
+	NET_ASSERT(context);
+
+	if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6 ||
+	    family == AF_PACKET || family == AF_CAN) {
+		/* Family is in BIT(4), BIT(5) and BIT(6) */
+		flag = family << 3;
+	}
+
+	context->flags |= flag;
+}
+
+/**
+ * @brief Get context type for this network context.
+ *
+ * @details This function returns the context type (stream, datagram or raw)
+ * of the context.
+ *
+ * @param context Network context.
+ *
+ * @return Network context type.
+ */
+static inline
+enum net_sock_type net_context_get_type(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return (enum net_sock_type)((context->flags & NET_CONTEXT_TYPE) >> 6);
+}
+
+/**
+ * @brief Set context type for this network context.
+ *
+ * @details This function sets the context type (stream or datagram)
+ * of the context.
+ *
+ * @param context Network context.
+ * @param type Context type (SOCK_STREAM or SOCK_DGRAM)
+ */
+static inline void net_context_set_type(struct net_context *context,
+					enum net_sock_type type)
+{
+	uint16_t flag = 0U;
+
+	NET_ASSERT(context);
+
+	if (type == SOCK_DGRAM || type == SOCK_STREAM || type == SOCK_RAW) {
+		/* Type is in BIT(6) and BIT(7)*/
+		flag = type << 6;
+	}
+
+	context->flags |= flag;
+}
+
+/**
+ * @brief Set CAN filter id for this network context.
+ *
+ * @details This function sets the CAN filter id of the context.
+ *
+ * @param context Network context.
+ * @param filter_id CAN filter id
+ */
+#if defined(CONFIG_NET_SOCKETS_CAN)
+static inline void net_context_set_filter_id(struct net_context *context,
+					     int filter_id)
+{
+	NET_ASSERT(context);
+
+	context->can_filter_id = filter_id;
+}
+#else
+static inline void net_context_set_filter_id(struct net_context *context,
+					     int filter_id)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(filter_id);
+}
+#endif
+
+/**
+ * @brief Get CAN filter id for this network context.
+ *
+ * @details This function gets the CAN filter id of the context.
+ *
+ * @param context Network context.
+ *
+ * @return Filter id of this network context
+ */
+#if defined(CONFIG_NET_SOCKETS_CAN)
+static inline int net_context_get_filter_id(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return context->can_filter_id;
+}
+#else
+static inline int net_context_get_filter_id(struct net_context *context)
+{
+	ARG_UNUSED(context);
+
+	return -1;
+}
+#endif
+
+/**
+ * @brief Get context IP protocol for this network context.
+ *
+ * @details This function returns the IP protocol (UDP / TCP /
+ * IEEE 802.3 protocol value) of the context.
+ *
+ * @param context Network context.
+ *
+ * @return Network context IP protocol.
+ */
+static inline uint16_t net_context_get_ip_proto(struct net_context *context)
+{
+	return context->proto;
+}
+
+/**
+ * @brief Set context IP protocol for this network context.
+ *
+ * @details This function sets the context IP protocol (UDP / TCP)
+ * of the context.
+ *
+ * @param context Network context.
+ * @param proto Context IP protocol (IPPROTO_UDP, IPPROTO_TCP or IEEE 802.3
+ * protocol value)
+ */
+static inline void net_context_set_ip_proto(struct net_context *context,
+					    uint16_t proto)
+{
+	context->proto = proto;
+}
+
+/**
+ * @brief Get network interface for this context.
+ *
+ * @details This function returns the used network interface.
+ *
+ * @param context Network context.
+ *
+ * @return Context network interface if context is bind to interface,
+ * NULL otherwise.
+ */
+static inline
+struct net_if *net_context_get_iface(struct net_context *context)
+{
+	NET_ASSERT(context);
+
+	return net_if_get_by_index(context->iface);
+}
+
+/**
+ * @brief Set network interface for this context.
+ *
+ * @details This function binds network interface to this context.
+ *
+ * @param context Network context.
+ * @param iface Network interface.
+ */
+static inline void net_context_set_iface(struct net_context *context,
+					 struct net_if *iface)
+{
+	NET_ASSERT(iface);
+
+	context->iface = net_if_get_by_iface(iface);
+}
+
+static inline uint8_t net_context_get_ipv4_ttl(struct net_context *context)
+{
+	return context->ipv4_ttl;
+}
+
+static inline void net_context_set_ipv4_ttl(struct net_context *context,
+					    uint8_t ttl)
+{
+	context->ipv4_ttl = ttl;
+}
+
+static inline uint8_t net_context_get_ipv6_hop_limit(struct net_context *context)
+{
+	return context->ipv6_hop_limit;
+}
+
+static inline void net_context_set_ipv6_hop_limit(struct net_context *context,
+						  uint8_t hop_limit)
+{
+	context->ipv6_hop_limit = hop_limit;
+}
+
+#if defined(CONFIG_SOCKS)
+static inline void net_context_set_proxy_enabled(struct net_context *context,
+						 bool enable)
+{
+	context->proxy_enabled = enable;
+}
+
+static inline bool net_context_is_proxy_enabled(struct net_context *context)
+{
+	return context->proxy_enabled;
+}
+#else
+static inline void net_context_set_proxy_enabled(struct net_context *context,
+						 bool enable)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(enable);
+}
+
+static inline bool net_context_is_proxy_enabled(struct net_context *context)
+{
+	return false;
+}
+#endif
+
+/**
+ * @brief Get network context.
+ *
+ * @details Network context is used to define the connection 5-tuple
+ * (protocol, remote address, remote port, source address and source
+ * port). Random free port number will be assigned to source port when
+ * context is created. This is similar as BSD socket() function.
+ * The context will be created with a reference count of 1.
+ *
+ * @param family IP address family (AF_INET or AF_INET6)
+ * @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
+ * @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP. For raw socket
+ * access, the value is the L2 protocol value from IEEE 802.3 (see ethernet.h)
+ * @param context The allocated context is returned to the caller.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_get(sa_family_t family,
+		    enum net_sock_type type,
+		    uint16_t ip_proto,
+		    struct net_context **context);
+
+/**
+ * @brief Close and unref a network context.
+ *
+ * @details This releases the context. It is not possible to send or
+ * receive data via this context after this call.  This is similar as
+ * BSD shutdown() function.  For legacy compatibility, this function
+ * will implicitly decrement the reference count and possibly destroy
+ * the context either now or when it reaches a final state.
+ *
+ * @param context The context to be closed.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_put(struct net_context *context);
+
+/**
+ * @brief Take a reference count to a net_context, preventing destruction
+ *
+ * @details Network contexts are not recycled until their reference
+ * count reaches zero.  Note that this does not prevent any "close"
+ * behavior that results from errors or net_context_put.  It simply
+ * prevents the context from being recycled for further use.
+ *
+ * @param context The context on which to increment the reference count
+ *
+ * @return The new reference count
+ */
+int net_context_ref(struct net_context *context);
+
+/**
+ * @brief Decrement the reference count to a network context
+ *
+ * @details Decrements the refcount.  If it reaches zero, the context
+ * will be recycled.  Note that this does not cause any
+ * network-visible "close" behavior (i.e. future packets to this
+ * connection may see TCP RST or ICMP port unreachable responses).  See
+ * net_context_put() for that.
+ *
+ * @param context The context on which to decrement the reference count
+ *
+ * @return The new reference count, zero if the context was destroyed
+ */
+int net_context_unref(struct net_context *context);
+
+/**
+ * @brief Create IPv4 packet in provided net_pkt from context
+ *
+ * @param context Network context for a connection
+ * @param pkt Network packet
+ * @param src Source address, or NULL to choose a default
+ * @param dst Destination IPv4 address
+ *
+ * @return Return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_IPV4)
+int net_context_create_ipv4_new(struct net_context *context,
+				struct net_pkt *pkt,
+				const struct in_addr *src,
+				const struct in_addr *dst);
+#else
+static inline int net_context_create_ipv4_new(struct net_context *context,
+					      struct net_pkt *pkt,
+					      const struct in_addr *src,
+					      const struct in_addr *dst)
+{
+	return -1;
+}
+#endif /* CONFIG_NET_IPV4 */
+
+/**
+ * @brief Create IPv6 packet in provided net_pkt from context
+ *
+ * @param context Network context for a connection
+ * @param pkt Network packet
+ * @param src Source address, or NULL to choose a default from context
+ * @param dst Destination IPv6 address
+ *
+ * @return Return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_IPV6)
+int net_context_create_ipv6_new(struct net_context *context,
+				struct net_pkt *pkt,
+				const struct in6_addr *src,
+				const struct in6_addr *dst);
+#else
+static inline int net_context_create_ipv6_new(struct net_context *context,
+					      struct net_pkt *pkt,
+					      const struct in6_addr *src,
+					      const struct in6_addr *dst)
+{
+	return -1;
+}
+#endif /* CONFIG_NET_IPV6 */
+
+/**
+ * @brief Assign a socket a local address.
+ *
+ * @details This is similar as BSD bind() function.
+ *
+ * @param context The context to be assigned.
+ * @param addr Address to assigned.
+ * @param addrlen Length of the address.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_bind(struct net_context *context,
+		     const struct sockaddr *addr,
+		     socklen_t addrlen);
+
+/**
+ * @brief Mark the context as a listening one.
+ *
+ * @details This is similar as BSD listen() function.
+ *
+ * @param context The context to use.
+ * @param backlog The size of the pending connections backlog.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_listen(struct net_context *context,
+		       int backlog);
+
+/**
+ * @brief            Create a network connection.
+ *
+ * @details          The net_context_connect function creates a network
+ *                   connection to the host specified by addr. After the
+ *                   connection is established, the user-supplied callback (cb)
+ *                   is executed. cb is called even if the timeout was set to
+ *                   K_FOREVER. cb is not called if the timeout expires.
+ *                   For datagram sockets (SOCK_DGRAM), this function only sets
+ *                   the peer address.
+ *                   This function is similar to the BSD connect() function.
+ *
+ * @param context    The network context.
+ * @param addr       The peer address to connect to.
+ * @param addrlen    Peer address length.
+ * @param cb         Callback function. Set to NULL if not required.
+ * @param timeout    The timeout value for the connection. Possible values:
+ *                   * K_NO_WAIT: this function will return immediately,
+ *                   * K_FOREVER: this function will block until the
+ *                                      connection is established,
+ *                   * >0: this function will wait the specified ms.
+ * @param user_data  Data passed to the callback function.
+ *
+ * @return           0 on success.
+ * @return           -EINVAL if an invalid parameter is passed as an argument.
+ * @return           -ENOTSUP if the operation is not supported or implemented.
+ * @return           -ETIMEDOUT if the connect operation times out.
+ */
+int net_context_connect(struct net_context *context,
+			const struct sockaddr *addr,
+			socklen_t addrlen,
+			net_context_connect_cb_t cb,
+			k_timeout_t timeout,
+			void *user_data);
+
+/**
+ * @brief Accept a network connection attempt.
+ *
+ * @details Accept a connection being established. This function
+ * will return immediately if the timeout is set to K_NO_WAIT.
+ * In this case the context will call the supplied callback when ever
+ * there is a connection established to this context. This is "a register
+ * handler and forget" type of call (async).
+ * If the timeout is set to K_FOREVER, the function will wait
+ * until the connection is established. Timeout value > 0, will wait as
+ * many ms.
+ * After the connection is established a caller-supplied callback is called.
+ * The callback is called even if timeout was set to K_FOREVER, the
+ * callback is called before this function will return in this case.
+ * The callback is not called if the timeout expires.
+ * This is similar as BSD accept() function.
+ *
+ * @param context The context to use.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Timeout for the connection. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_accept(struct net_context *context,
+		       net_tcp_accept_cb_t cb,
+		       k_timeout_t timeout,
+		       void *user_data);
+
+/**
+ * @brief Send data to a peer.
+ *
+ * @details This function can be used to send network data to a peer
+ * connection. After the network buffer is sent, a caller-supplied
+ * callback is called. Note that the callback might be called after this
+ * function has returned. For context of type SOCK_DGRAM, the destination
+ * address must have been set by the call to net_context_connect().
+ * This is similar as BSD send() function.
+ *
+ * @param context The network context to use.
+ * @param buf The data buffer to send
+ * @param len Length of the buffer
+ * @param cb Caller-supplied callback function.
+ * @param timeout Currently this value is not used.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_send(struct net_context *context,
+		     const void *buf,
+		     size_t len,
+		     net_context_send_cb_t cb,
+		     k_timeout_t timeout,
+		     void *user_data);
+
+/**
+ * @brief Send data to a peer specified by address.
+ *
+ * @details This function can be used to send network data to a peer
+ * specified by address. This variant can only be used for datagram
+ * connections of type SOCK_DGRAM. After the network buffer is sent,
+ * a caller-supplied callback is called. Note that the callback might be
+ * called after this function has returned.
+ * This is similar as BSD sendto() function.
+ *
+ * @param context The network context to use.
+ * @param buf The data buffer to send
+ * @param len Length of the buffer
+ * @param dst_addr Destination address.
+ * @param addrlen Length of the address.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Currently this value is not used.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return numbers of bytes sent on success, a negative errno otherwise
+ */
+int net_context_sendto(struct net_context *context,
+		       const void *buf,
+		       size_t len,
+		       const struct sockaddr *dst_addr,
+		       socklen_t addrlen,
+		       net_context_send_cb_t cb,
+		       k_timeout_t timeout,
+		       void *user_data);
+
+/**
+ * @brief Send data in iovec to a peer specified in msghdr struct.
+ *
+ * @details This function has similar semantics as Posix sendmsg() call.
+ * For unconnected socket, the msg_name field in msghdr must be set. For
+ * connected socket the msg_name should be set to NULL, and msg_namelen to 0.
+ * After the network buffer is sent, a caller-supplied callback is called.
+ * Note that the callback might be called after this function has returned.
+ *
+ * @param context The network context to use.
+ * @param msghdr The data to send
+ * @param flags Flags for the sending.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Currently this value is not used.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return numbers of bytes sent on success, a negative errno otherwise
+ */
+int net_context_sendmsg(struct net_context *context,
+			const struct msghdr *msghdr,
+			int flags,
+			net_context_send_cb_t cb,
+			k_timeout_t timeout,
+			void *user_data);
+
+/**
+ * @brief Receive network data from a peer specified by context.
+ *
+ * @details This function can be used to register a callback function
+ * that is called by the network stack when network data has been received
+ * for this context. As this function registers a callback, then there
+ * is no need to call this function multiple times if timeout is set to
+ * K_NO_WAIT.
+ * If callback function or user data changes, then the function can be called
+ * multiple times to register new values.
+ * This function will return immediately if the timeout is set to K_NO_WAIT.
+ * If the timeout is set to K_FOREVER, the function will wait until the
+ * network buffer is received. Timeout value > 0 will wait as many ms.
+ * After the network buffer is received, a caller-supplied callback is
+ * called. The callback is called even if timeout was set to K_FOREVER,
+ * the callback is called before this function will return in this case.
+ * The callback is not called if the timeout expires. The timeout functionality
+ * can be compiled out if synchronous behavior is not needed. The sync call
+ * logic requires some memory that can be saved if only async way of call is
+ * used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
+ * value is ignored.
+ * This is similar as BSD recv() function.
+ * Note that net_context_bind() should be called before net_context_recv().
+ * Default random port number is assigned to local port. Only bind() will
+ * update connection information from context. If recv() is called before
+ * bind() call, it may refuse to bind to a context which already has
+ * a connection associated.
+ *
+ * @param context The network context to use.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Caller-supplied timeout. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_recv(struct net_context *context,
+		     net_context_recv_cb_t cb,
+		     k_timeout_t timeout,
+		     void *user_data);
+
+/**
+ * @brief Update TCP receive window for context.
+ *
+ * @details This function should be used by an application which
+ * doesn't fully process incoming data in its receive callback,
+ * but for example, queues it. In this case, receive callback
+ * should decrease the window (call this function with a negative
+ * value) by the size of queued data, and function(s) which dequeue
+ * data - with positive value corresponding to the dequeued size.
+ * For example, if receive callback gets a packet with the data
+ * size of 256 and queues it, it should call this function with
+ * delta of -256. If a function extracts 10 bytes of the queued
+ * data, it should call it with delta of 10.
+ *
+ * @param context The TCP network context to use.
+ * @param delta Size, in bytes, by which to increase TCP receive
+ * window (negative value to decrease).
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_context_update_recv_wnd(struct net_context *context,
+				int32_t delta);
+
+enum net_context_option {
+	NET_OPT_PRIORITY	= 1,
+	NET_OPT_TIMESTAMP	= 2,
+	NET_OPT_TXTIME		= 3,
+	NET_OPT_SOCKS5		= 4,
+};
+
+/**
+ * @brief Set an connection option for this context.
+ *
+ * @param context The network context to use.
+ * @param option Option to set
+ * @param value Option value
+ * @param len Option length
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_context_set_option(struct net_context *context,
+			   enum net_context_option option,
+			   const void *value, size_t len);
+
+/**
+ * @brief Get connection option value for this context.
+ *
+ * @param context The network context to use.
+ * @param option Option to set
+ * @param value Option value
+ * @param len Option length (returned to caller)
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_context_get_option(struct net_context *context,
+			   enum net_context_option option,
+			   void *value, size_t *len);
+
+/**
+ * @typedef net_context_cb_t
+ * @brief Callback used while iterating over network contexts
+ *
+ * @param context A valid pointer on current network context
+ * @param user_data A valid pointer on some user data or NULL
+ */
+typedef void (*net_context_cb_t)(struct net_context *context, void *user_data);
+
+/**
+ * @brief Go through all the network connections and call callback
+ * for each network context.
+ *
+ * @param cb User-supplied callback function to call.
+ * @param user_data User specified data.
+ */
+void net_context_foreach(net_context_cb_t cb, void *user_data);
+
+/**
+ * @brief Set custom network buffer pools for context send operations
+ *
+ * Set custom network buffer pools used by the IP stack to allocate
+ * network buffers used by the context when sending data to the
+ * network. Using dedicated buffers may help make send operations on
+ * a given context more reliable, e.g. not be subject to buffer
+ * starvation due to operations on other network contexts. Buffer pools
+ * are set per context, but several contexts may share the same buffers.
+ * Note that there's no support for per-context custom receive packet
+ * pools.
+ *
+ * @param context Context that will use the given net_buf pools.
+ * @param tx_pool Pointer to the function that will return TX pool
+ * to the caller. The TX pool is used when sending data to network.
+ * There is one TX net_pkt for each network packet that is sent.
+ * @param data_pool Pointer to the function that will return DATA pool
+ * to the caller. The DATA pool is used to store data that is sent to
+ * the network.
+ */
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+static inline void net_context_setup_pools(struct net_context *context,
+					   net_pkt_get_slab_func_t tx_slab,
+					   net_pkt_get_pool_func_t data_pool)
+{
+	NET_ASSERT(context);
+
+	context->tx_slab = tx_slab;
+	context->data_pool = data_pool;
+}
+#else
+#define net_context_setup_pools(context, tx_pool, data_pool)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_CONTEXT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_core.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_core.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_core.h	(working copy)
@@ -0,0 +1,157 @@
+/** @file
+ * @brief Network core definitions
+ *
+ * Definitions for networking support.
+ */
+
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_CORE_H_
+#define ZEPHYR_INCLUDE_NET_NET_CORE_H_
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <logging/log.h>
+#include <sys/__assert.h>
+#include <kernel.h>
+
+#include <net/net_timeout.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Networking
+ * @defgroup networking Networking
+ * @{
+ * @}
+ */
+
+/**
+ * @brief Network core library
+ * @defgroup net_core Network Core Library
+ * @ingroup networking
+ * @{
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Network subsystem logging helpers */
+#ifdef CONFIG_THREAD_NAME
+#define NET_DBG(fmt, ...) LOG_DBG("(%s): " fmt,				\
+			log_strdup(k_thread_name_get(k_current_get())), \
+			##__VA_ARGS__)
+#else
+#define NET_DBG(fmt, ...) LOG_DBG("(%p): " fmt, k_current_get(),	\
+				  ##__VA_ARGS__)
+#endif /* CONFIG_THREAD_NAME */
+#define NET_ERR(fmt, ...) LOG_ERR(fmt, ##__VA_ARGS__)
+#define NET_WARN(fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__)
+#define NET_INFO(fmt, ...) LOG_INF(fmt,  ##__VA_ARGS__)
+
+#define NET_ASSERT(cond, ...) __ASSERT(cond, "" __VA_ARGS__)
+
+/* This needs to be here in order to avoid circular include dependency between
+ * net_pkt.h and net_if.h
+ */
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
+	defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+#if !defined(NET_PKT_DETAIL_STATS_COUNT)
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+#define NET_PKT_DETAIL_STATS_COUNT 4
+#else
+#define NET_PKT_DETAIL_STATS_COUNT 3
+#endif /* CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+#else
+#define NET_PKT_DETAIL_STATS_COUNT 4
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL */
+
+#endif /* !NET_PKT_DETAIL_STATS_COUNT */
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
+	  CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+/** @endcond */
+
+struct net_buf;
+struct net_pkt;
+struct net_context;
+struct net_if;
+
+/**
+ * @brief Net Verdict
+ */
+enum net_verdict {
+	/** Packet has been taken care of. */
+	NET_OK,
+	/** Packet has not been touched, other part should decide about its
+	 * fate.
+	 */
+	NET_CONTINUE,
+	/** Packet must be dropped. */
+	NET_DROP,
+};
+
+/**
+ * @brief Called by lower network stack or network device driver when
+ * a network packet has been received. The function will push the packet up in
+ * the network stack for further processing.
+ *
+ * @param iface Network interface where the packet was received.
+ * @param pkt Network packet data.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int net_recv_data(struct net_if *iface, struct net_pkt *pkt);
+
+/**
+ * @brief Send data to network.
+ *
+ * @details Send data to network. This should not be used normally by
+ * applications as it requires that the network packet is properly
+ * constructed.
+ *
+ * @param pkt Network packet.
+ *
+ * @return 0 if ok, <0 if error. If <0 is returned, then the caller needs
+ * to unref the pkt in order to avoid memory leak.
+ */
+int net_send_data(struct net_pkt *pkt);
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Some helper defines for traffic class support */
+#if defined(CONFIG_NET_TC_TX_COUNT) && defined(CONFIG_NET_TC_RX_COUNT)
+#define NET_TC_TX_COUNT CONFIG_NET_TC_TX_COUNT
+#define NET_TC_RX_COUNT CONFIG_NET_TC_RX_COUNT
+
+#if NET_TC_TX_COUNT > NET_TC_RX_COUNT
+#define NET_TC_COUNT NET_TC_TX_COUNT
+#else
+#define NET_TC_COUNT NET_TC_RX_COUNT
+#endif
+#else /* CONFIG_NET_TC_TX_COUNT && CONFIG_NET_TC_RX_COUNT */
+#define NET_TC_TX_COUNT 1
+#define NET_TC_RX_COUNT 1
+#define NET_TC_COUNT 1
+#endif /* CONFIG_NET_TC_TX_COUNT && CONFIG_NET_TC_RX_COUNT */
+
+/* @endcond */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_CORE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_event.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_event.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_event.h	(working copy)
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Network Events code public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_EVENT_H_
+#define ZEPHYR_INCLUDE_NET_NET_EVENT_H_
+
+#include <net/net_ip.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup net_mgmt
+ * @{
+ */
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Network Interface events */
+#define _NET_IF_LAYER		NET_MGMT_LAYER_L2
+#define _NET_IF_CORE_CODE	0x001
+#define _NET_EVENT_IF_BASE	(NET_MGMT_EVENT_BIT |			\
+				 NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_IF_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_IF_CORE_CODE))
+
+enum net_event_if_cmd {
+	NET_EVENT_IF_CMD_DOWN = 1,
+	NET_EVENT_IF_CMD_UP,
+};
+
+#define NET_EVENT_IF_DOWN				\
+	(_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_DOWN)
+
+#define NET_EVENT_IF_UP					\
+	(_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_UP)
+
+/* IPv6 Events */
+#define _NET_IPV6_LAYER		NET_MGMT_LAYER_L3
+#define _NET_IPV6_CORE_CODE	0x060
+#define _NET_EVENT_IPV6_BASE	(NET_MGMT_EVENT_BIT |			\
+				 NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_IPV6_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_IPV6_CORE_CODE))
+
+enum net_event_ipv6_cmd {
+	NET_EVENT_IPV6_CMD_ADDR_ADD	= 1,
+	NET_EVENT_IPV6_CMD_ADDR_DEL,
+	NET_EVENT_IPV6_CMD_MADDR_ADD,
+	NET_EVENT_IPV6_CMD_MADDR_DEL,
+	NET_EVENT_IPV6_CMD_PREFIX_ADD,
+	NET_EVENT_IPV6_CMD_PREFIX_DEL,
+	NET_EVENT_IPV6_CMD_MCAST_JOIN,
+	NET_EVENT_IPV6_CMD_MCAST_LEAVE,
+	NET_EVENT_IPV6_CMD_ROUTER_ADD,
+	NET_EVENT_IPV6_CMD_ROUTER_DEL,
+	NET_EVENT_IPV6_CMD_ROUTE_ADD,
+	NET_EVENT_IPV6_CMD_ROUTE_DEL,
+	NET_EVENT_IPV6_CMD_DAD_SUCCEED,
+	NET_EVENT_IPV6_CMD_DAD_FAILED,
+	NET_EVENT_IPV6_CMD_NBR_ADD,
+	NET_EVENT_IPV6_CMD_NBR_DEL,
+};
+
+#define NET_EVENT_IPV6_ADDR_ADD					\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD)
+
+#define NET_EVENT_IPV6_ADDR_DEL					\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_ADDR_DEL)
+
+#define NET_EVENT_IPV6_MADDR_ADD				\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_MADDR_ADD)
+
+#define NET_EVENT_IPV6_MADDR_DEL				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_DEL)
+
+#define NET_EVENT_IPV6_PREFIX_ADD				\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_PREFIX_ADD)
+
+#define NET_EVENT_IPV6_PREFIX_DEL				\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_PREFIX_DEL)
+
+#define NET_EVENT_IPV6_MCAST_JOIN				\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_MCAST_JOIN)
+
+#define NET_EVENT_IPV6_MCAST_LEAVE				\
+	(_NET_EVENT_IPV6_BASE |	NET_EVENT_IPV6_CMD_MCAST_LEAVE)
+
+#define NET_EVENT_IPV6_ROUTER_ADD				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_ADD)
+
+#define NET_EVENT_IPV6_ROUTER_DEL				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_DEL)
+
+#define NET_EVENT_IPV6_ROUTE_ADD				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_ADD)
+
+#define NET_EVENT_IPV6_ROUTE_DEL				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_DEL)
+
+#define NET_EVENT_IPV6_DAD_SUCCEED				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_SUCCEED)
+
+#define NET_EVENT_IPV6_DAD_FAILED				\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_FAILED)
+
+#define NET_EVENT_IPV6_NBR_ADD					\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_ADD)
+
+#define NET_EVENT_IPV6_NBR_DEL					\
+	(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_DEL)
+
+/* IPv4 Events*/
+#define _NET_IPV4_LAYER		NET_MGMT_LAYER_L3
+#define _NET_IPV4_CORE_CODE	0x004
+#define _NET_EVENT_IPV4_BASE	(NET_MGMT_EVENT_BIT |			\
+				 NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_IPV4_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE))
+
+enum net_event_ipv4_cmd {
+	NET_EVENT_IPV4_CMD_ADDR_ADD	= 1,
+	NET_EVENT_IPV4_CMD_ADDR_DEL,
+	NET_EVENT_IPV4_CMD_ROUTER_ADD,
+	NET_EVENT_IPV4_CMD_ROUTER_DEL,
+	NET_EVENT_IPV4_CMD_DHCP_START,
+	NET_EVENT_IPV4_CMD_DHCP_BOUND,
+	NET_EVENT_IPV4_CMD_DHCP_STOP,
+};
+
+#define NET_EVENT_IPV4_ADDR_ADD					\
+	(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_ADD)
+
+#define NET_EVENT_IPV4_ADDR_DEL					\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_ADDR_DEL)
+
+#define NET_EVENT_IPV4_ROUTER_ADD				\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_ROUTER_ADD)
+
+#define NET_EVENT_IPV4_ROUTER_DEL				\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_ROUTER_DEL)
+
+#define NET_EVENT_IPV4_DHCP_START				\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_DHCP_START)
+
+#define NET_EVENT_IPV4_DHCP_BOUND				\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_DHCP_BOUND)
+
+#define NET_EVENT_IPV4_DHCP_STOP				\
+	(_NET_EVENT_IPV4_BASE |	NET_EVENT_IPV4_CMD_DHCP_STOP)
+
+
+/* L4 network events */
+#define _NET_L4_LAYER		NET_MGMT_LAYER_L4
+#define _NET_L4_CORE_CODE	0x114
+#define _NET_EVENT_L4_BASE	(NET_MGMT_EVENT_BIT |			\
+				 NET_MGMT_IFACE_BIT |			\
+				 NET_MGMT_LAYER(_NET_L4_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_L4_CORE_CODE))
+
+enum net_event_l4_cmd {
+	NET_EVENT_L4_CMD_CONNECTED = 1,
+	NET_EVENT_L4_CMD_DISCONNECTED,
+	NET_EVENT_L4_CMD_DNS_SERVER_ADD,
+	NET_EVENT_L4_CMD_DNS_SERVER_DEL,
+};
+
+#define NET_EVENT_L4_CONNECTED				\
+	(_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CONNECTED)
+
+#define NET_EVENT_L4_DISCONNECTED			\
+	(_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DISCONNECTED)
+
+#define NET_EVENT_DNS_SERVER_ADD			\
+	(_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_ADD)
+
+#define NET_EVENT_DNS_SERVER_DEL			\
+	(_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_DEL)
+
+/** @endcond */
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+/**
+ * @brief Network Management event information structure
+ * Used to pass information on network events like
+ *   NET_EVENT_IPV6_ADDR_ADD,
+ *   NET_EVENT_IPV6_ADDR_DEL,
+ *   NET_EVENT_IPV6_MADDR_ADD and
+ *   NET_EVENT_IPV6_MADDR_DEL
+ * when CONFIG_NET_MGMT_EVENT_INFO enabled and event generator pass the
+ * information.
+ */
+struct net_event_ipv6_addr {
+	struct in6_addr addr;
+};
+
+/**
+ * @brief Network Management event information structure
+ * Used to pass information on network events like
+ *   NET_EVENT_IPV6_NBR_ADD and
+ *   NET_EVENT_IPV6_NBR_DEL
+ * when CONFIG_NET_MGMT_EVENT_INFO enabled and event generator pass the
+ * information.
+ * @Note: idx will be '-1' in case of NET_EVENT_IPV6_NBR_DEL event.
+ */
+struct net_event_ipv6_nbr {
+	struct in6_addr addr;
+	int idx; /* NBR index*/
+};
+
+/**
+ * @brief Network Management event information structure
+ * Used to pass information on network events like
+ *   NET_EVENT_IPV6_ROUTE_ADD and
+ *   NET_EVENT_IPV6_ROUTE_DEL
+ * when CONFIG_NET_MGMT_EVENT_INFO enabled and event generator pass the
+ * information.
+ */
+struct net_event_ipv6_route {
+	struct in6_addr nexthop;
+	struct in6_addr addr; /* addr/prefix */
+	uint8_t prefix_len;
+};
+
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_EVENT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_if.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_if.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_if.h	(working copy)
@@ -0,0 +1,2314 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public API for network interface
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_IF_H_
+#define ZEPHYR_INCLUDE_NET_NET_IF_H_
+
+/**
+ * @brief Network Interface abstraction layer
+ * @defgroup net_if Network Interface abstraction layer
+ * @ingroup networking
+ * @{
+ */
+
+#include <device.h>
+#include <sys/slist.h>
+
+#include <net/net_core.h>
+#include <net/hostname.h>
+#include <net/net_linkaddr.h>
+#include <net/net_ip.h>
+#include <net/net_l2.h>
+#include <net/net_stats.h>
+#include <net/net_timeout.h>
+
+#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+#include <net/dhcpv4.h>
+#endif
+#if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4)
+#include <net/ipv4_autoconf.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network Interface unicast IP addresses
+ *
+ * Stores the unicast IP addresses assigned to this network interface.
+ */
+struct net_if_addr {
+	/** IP address */
+	struct net_addr address;
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	struct net_timeout lifetime;
+#endif
+
+#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6)
+	/** Duplicate address detection (DAD) timer */
+	sys_snode_t dad_node;
+	uint32_t dad_start;
+#endif
+	/** How the IP address was set */
+	enum net_addr_type addr_type;
+
+	/** What is the current state of the address */
+	enum net_addr_state addr_state;
+
+#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6)
+	/** How many times we have done DAD */
+	uint8_t dad_count;
+#endif
+
+	/** Is the IP address valid forever */
+	uint8_t is_infinite : 1;
+
+	/** Is this IP address used or not */
+	uint8_t is_used : 1;
+
+	/** Is this IP address usage limited to the subnet (mesh) or not */
+	uint8_t is_mesh_local : 1;
+
+	uint8_t _unused : 5;
+};
+
+/**
+ * @brief Network Interface multicast IP addresses
+ *
+ * Stores the multicast IP addresses assigned to this network interface.
+ */
+struct net_if_mcast_addr {
+	/** IP address */
+	struct net_addr address;
+
+	/** Is this multicast IP address used or not */
+	uint8_t is_used : 1;
+
+	/** Did we join to this group */
+	uint8_t is_joined : 1;
+
+	uint8_t _unused : 6;
+};
+
+/**
+ * @brief Network Interface IPv6 prefixes
+ *
+ * Stores the multicast IP addresses assigned to this network interface.
+ */
+struct net_if_ipv6_prefix {
+	/** Prefix lifetime */
+	struct net_timeout lifetime;
+
+	/** IPv6 prefix */
+	struct in6_addr prefix;
+
+	/** Backpointer to network interface where this prefix is used */
+	struct net_if *iface;
+
+	/** Prefix length */
+	uint8_t len;
+
+	/** Is the IP prefix valid forever */
+	uint8_t is_infinite : 1;
+
+	/** Is this prefix used or not */
+	uint8_t is_used : 1;
+
+	uint8_t _unused : 6;
+};
+
+/**
+ * @brief Information about routers in the system.
+ *
+ * Stores the router information.
+ */
+struct net_if_router {
+	/** Slist lifetime timer node */
+	sys_snode_t node;
+
+	/** IP address */
+	struct net_addr address;
+
+	/** Network interface the router is connected to */
+	struct net_if *iface;
+
+	/** Router life timer start */
+	uint32_t life_start;
+
+	/** Router lifetime */
+	uint16_t lifetime;
+
+	/** Is this router used or not */
+	uint8_t is_used : 1;
+
+	/** Is default router */
+	uint8_t is_default : 1;
+
+	/** Is the router valid forever */
+	uint8_t is_infinite : 1;
+
+	uint8_t _unused : 5;
+};
+
+enum net_if_flag {
+	/** Interface is up/ready to receive and transmit */
+	NET_IF_UP,
+
+	/** Interface is pointopoint */
+	NET_IF_POINTOPOINT,
+
+	/** Interface is in promiscuous mode */
+	NET_IF_PROMISC,
+
+	/** Do not start the interface immediately after initialization.
+	 * This requires that either the device driver or some other entity
+	 * will need to manually take the interface up when needed.
+	 * For example for Ethernet this will happen when the driver calls
+	 * the net_eth_carrier_on() function.
+	 */
+	NET_IF_NO_AUTO_START,
+
+	/** Power management specific: interface is being suspended */
+	NET_IF_SUSPENDED,
+
+	/** Flag defines if received multicasts of other interface are
+	 * forwarded on this interface. This activates multicast
+	 * routing / forwarding for this interface.
+	 */
+	NET_IF_FORWARD_MULTICASTS,
+
+/** @cond INTERNAL_HIDDEN */
+	/* Total number of flags - must be at the end of the enum */
+	NET_IF_NUM_FLAGS
+/** @endcond */
+};
+
+#if defined(CONFIG_NET_OFFLOAD)
+struct net_offload;
+#endif /* CONFIG_NET_OFFLOAD */
+
+/** @cond INTERNAL_HIDDEN */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+#define NET_IF_MAX_IPV6_ADDR CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT
+#define NET_IF_MAX_IPV6_MADDR CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT
+#define NET_IF_MAX_IPV6_PREFIX CONFIG_NET_IF_IPV6_PREFIX_COUNT
+#else
+#define NET_IF_MAX_IPV6_ADDR 0
+#define NET_IF_MAX_IPV6_MADDR 0
+#define NET_IF_MAX_IPV6_PREFIX 0
+#endif
+/* @endcond */
+
+struct net_if_ipv6 {
+	/** Unicast IP addresses */
+	struct net_if_addr unicast[NET_IF_MAX_IPV6_ADDR];
+
+	/** Multicast IP addresses */
+	struct net_if_mcast_addr mcast[NET_IF_MAX_IPV6_MADDR];
+
+	/** Prefixes */
+	struct net_if_ipv6_prefix prefix[NET_IF_MAX_IPV6_PREFIX];
+
+	/** Default reachable time (RFC 4861, page 52) */
+	uint32_t base_reachable_time;
+
+	/** Reachable time (RFC 4861, page 20) */
+	uint32_t reachable_time;
+
+	/** Retransmit timer (RFC 4861, page 52) */
+	uint32_t retrans_timer;
+#if defined(CONFIG_NET_IPV6_ND) && defined(CONFIG_NET_NATIVE_IPV6)
+	/** Router solicitation timer node */
+	sys_snode_t rs_node;
+
+	/* RS start time */
+	uint32_t rs_start;
+
+	/** RS count */
+	uint8_t rs_count;
+#endif
+
+	/** IPv6 hop limit */
+	uint8_t hop_limit;
+};
+
+/** @cond INTERNAL_HIDDEN */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+#define NET_IF_MAX_IPV4_ADDR CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT
+#define NET_IF_MAX_IPV4_MADDR CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT
+#else
+#define NET_IF_MAX_IPV4_ADDR 0
+#define NET_IF_MAX_IPV4_MADDR 0
+#endif
+/** @endcond */
+
+struct net_if_ipv4 {
+	/** Unicast IP addresses */
+	struct net_if_addr unicast[NET_IF_MAX_IPV4_ADDR];
+
+	/** Multicast IP addresses */
+	struct net_if_mcast_addr mcast[NET_IF_MAX_IPV4_MADDR];
+
+	/** Gateway */
+	struct in_addr gw;
+
+	/** Netmask */
+	struct in_addr netmask;
+
+	/** IPv4 time-to-live */
+	uint8_t ttl;
+};
+
+#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+struct net_if_dhcpv4 {
+	/** Used for timer lists */
+	sys_snode_t node;
+
+	/** Timer start */
+	int64_t timer_start;
+
+	/** Time for INIT, DISCOVER, REQUESTING, RENEWAL */
+	uint32_t request_time;
+
+	uint32_t xid;
+
+	/** IP address Lease time */
+	uint32_t lease_time;
+
+	/** IP address Renewal time */
+	uint32_t renewal_time;
+
+	/** IP address Rebinding time */
+	uint32_t rebinding_time;
+
+	/** Server ID */
+	struct in_addr server_id;
+
+	/** Requested IP addr */
+	struct in_addr requested_ip;
+
+	/**
+	 *  DHCPv4 client state in the process of network
+	 *  address allocation.
+	 */
+	enum net_dhcpv4_state state;
+
+	/** Number of attempts made for REQUEST and RENEWAL messages */
+	uint8_t attempts;
+};
+#endif /* CONFIG_NET_DHCPV4 */
+
+#if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4)
+struct net_if_ipv4_autoconf {
+	/** Used for timer lists */
+	sys_snode_t node;
+
+	/** Backpointer to correct network interface */
+	struct net_if *iface;
+
+	/** Timer start */
+	int64_t timer_start;
+
+	/** Time for INIT, DISCOVER, REQUESTING, RENEWAL */
+	uint32_t timer_timeout;
+
+	/** Current IP addr */
+	struct in_addr current_ip;
+
+	/** Requested IP addr */
+	struct in_addr requested_ip;
+
+	/** IPV4 Autoconf state in the process of network address allocation.
+	 */
+	enum net_ipv4_autoconf_state state;
+
+	/** Number of sent probe requests */
+	uint8_t probe_cnt;
+
+	/** Number of sent announcements */
+	uint8_t announce_cnt;
+
+	/** Incoming conflict count */
+	uint8_t conflict_cnt;
+};
+#endif /* CONFIG_NET_IPV4_AUTO */
+
+/** @cond INTERNAL_HIDDEN */
+/* We always need to have at least one IP config */
+#define NET_IF_MAX_CONFIGS 1
+/** @endcond */
+
+/**
+ * @brief Network interface IP address configuration.
+ */
+struct net_if_ip {
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	struct net_if_ipv6 *ipv6;
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_NATIVE_IPV4)
+	struct net_if_ipv4 *ipv4;
+#endif /* CONFIG_NET_IPV4 */
+};
+
+/**
+ * @brief IP and other configuration related data for network interface.
+ */
+struct net_if_config {
+	/** IP address configuration setting */
+	struct net_if_ip ip;
+
+#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+	struct net_if_dhcpv4 dhcpv4;
+#endif /* CONFIG_NET_DHCPV4 */
+
+#if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4)
+	struct net_if_ipv4_autoconf ipv4auto;
+#endif /* CONFIG_NET_IPV4_AUTO */
+};
+
+/**
+ * @brief Network traffic class.
+ *
+ * Traffic classes are used when sending or receiving data that is classified
+ * with different priorities. So some traffic can be marked as high priority
+ * and it will be sent or received first. There is always at least one work
+ * queue in the system for Rx and Tx. Each network packet that is transmitted
+ * or received goes through a work queue thread that will transmit it.
+ */
+struct net_traffic_class {
+	/** Work queue for handling this Tx or Rx packet */
+	struct k_work_q work_q;
+
+	/** Stack for this work queue */
+	k_thread_stack_t *stack;
+};
+
+/**
+ * @brief Network Interface Device structure
+ *
+ * Used to handle a network interface on top of a device driver instance.
+ * There can be many net_if_dev instance against the same device.
+ *
+ * Such interface is mainly to be used by the link layer, but is also tight
+ * to a network context: it then makes the relation with a network context
+ * and the network device.
+ *
+ * Because of the strong relationship between a device driver and such
+ * network interface, each net_if_dev should be instantiated by
+ */
+struct net_if_dev {
+	/** The actually device driver instance the net_if is related to */
+	const struct device *dev;
+
+	/** Interface's L2 layer */
+	const struct net_l2 * const l2;
+
+	/** Interface's private L2 data pointer */
+	void *l2_data;
+
+	/* For internal use */
+	ATOMIC_DEFINE(flags, NET_IF_NUM_FLAGS);
+
+	/** The hardware link address */
+	struct net_linkaddr link_addr;
+
+#if defined(CONFIG_NET_OFFLOAD)
+	/** TCP/IP Offload functions.
+	 * If non-NULL, then the TCP/IP stack is located
+	 * in the communication chip that is accessed via this
+	 * network interface.
+	 */
+	struct net_offload *offload;
+#endif /* CONFIG_NET_OFFLOAD */
+
+	/** The hardware MTU */
+	uint16_t mtu;
+
+#if defined(CONFIG_NET_SOCKETS_OFFLOAD)
+	/** Indicate whether interface is offloaded at socket level. */
+	bool offloaded;
+#endif /* CONFIG_NET_SOCKETS_OFFLOAD */
+};
+
+/**
+ * @brief Network Interface structure
+ *
+ * Used to handle a network interface on top of a net_if_dev instance.
+ * There can be many net_if instance against the same net_if_dev instance.
+ *
+ */
+struct net_if {
+	/** The net_if_dev instance the net_if is related to */
+	struct net_if_dev *if_dev;
+
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+	/** Network statistics related to this network interface */
+	struct net_stats stats;
+#endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */
+
+	/** Network interface instance configuration */
+	struct net_if_config config;
+
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	/** Keep track of packets pending in traffic queues. This is
+	 * needed to avoid putting network device driver to sleep if
+	 * there are packets waiting to be sent.
+	 */
+	int tx_pending;
+#endif
+};
+
+/**
+ * @brief Set a value in network interface flags
+ *
+ * @param iface Pointer to network interface
+ * @param value Flag value
+ */
+static inline void net_if_flag_set(struct net_if *iface,
+				   enum net_if_flag value)
+{
+	NET_ASSERT(iface);
+
+	atomic_set_bit(iface->if_dev->flags, value);
+}
+
+/**
+ * @brief Test and set a value in network interface flags
+ *
+ * @param iface Pointer to network interface
+ * @param value Flag value
+ *
+ * @return true if the bit was set, false if it wasn't.
+ */
+static inline bool net_if_flag_test_and_set(struct net_if *iface,
+					    enum net_if_flag value)
+{
+	NET_ASSERT(iface);
+
+	return atomic_test_and_set_bit(iface->if_dev->flags, value);
+}
+
+/**
+ * @brief Clear a value in network interface flags
+ *
+ * @param iface Pointer to network interface
+ * @param value Flag value
+ */
+static inline void net_if_flag_clear(struct net_if *iface,
+				     enum net_if_flag value)
+{
+	NET_ASSERT(iface);
+
+	atomic_clear_bit(iface->if_dev->flags, value);
+}
+
+/**
+ * @brief Check if a value in network interface flags is set
+ *
+ * @param iface Pointer to network interface
+ * @param value Flag value
+ *
+ * @return True if the value is set, false otherwise
+ */
+static inline bool net_if_flag_is_set(struct net_if *iface,
+				      enum net_if_flag value)
+{
+	NET_ASSERT(iface);
+
+	return atomic_test_bit(iface->if_dev->flags, value);
+}
+
+/**
+ * @brief Send a packet through a net iface
+ *
+ * @param iface Pointer to a network interface structure
+ * @param pkt Pointer to a net packet to send
+ *
+ * return verdict about the packet
+ */
+enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt);
+
+/**
+ * @brief Get a pointer to the interface L2
+ *
+ * @param iface a valid pointer to a network interface structure
+ *
+ * @return a pointer to the iface L2
+ */
+static inline const struct net_l2 * const net_if_l2(struct net_if *iface)
+{
+	if (!iface || !iface->if_dev) {
+		return NULL;
+	}
+
+	return iface->if_dev->l2;
+}
+
+/**
+ * @brief Input a packet through a net iface
+ *
+ * @param iface Pointer to a network interface structure
+ * @param pkt Pointer to a net packet to input
+ *
+ * @return verdict about the packet
+ */
+enum net_verdict net_if_recv_data(struct net_if *iface, struct net_pkt *pkt);
+
+/**
+ * @brief Get a pointer to the interface L2 private data
+ *
+ * @param iface a valid pointer to a network interface structure
+ *
+ * @return a pointer to the iface L2 data
+ */
+static inline void *net_if_l2_data(struct net_if *iface)
+{
+	return iface->if_dev->l2_data;
+}
+
+/**
+ * @brief Get an network interface's device
+ *
+ * @param iface Pointer to a network interface structure
+ *
+ * @return a pointer to the device driver instance
+ */
+static inline const struct device *net_if_get_device(struct net_if *iface)
+{
+	return iface->if_dev->dev;
+}
+
+/**
+ * @brief Queue a packet to the net interface TX queue
+ *
+ * @param iface Pointer to a network interface structure
+ * @param pkt Pointer to a net packet to queue
+ */
+void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt);
+
+/**
+ * @brief Return the IP offload status
+ *
+ * @param iface Network interface
+ *
+ * @return True if IP offlining is active, false otherwise.
+ */
+static inline bool net_if_is_ip_offloaded(struct net_if *iface)
+{
+#if defined(CONFIG_NET_OFFLOAD)
+	return (iface->if_dev->offload != NULL);
+#else
+	ARG_UNUSED(iface);
+
+	return false;
+#endif
+}
+
+/**
+ * @brief Return the IP offload plugin
+ *
+ * @param iface Network interface
+ *
+ * @return NULL if there is no offload plugin defined, valid pointer otherwise
+ */
+static inline struct net_offload *net_if_offload(struct net_if *iface)
+{
+#if defined(CONFIG_NET_OFFLOAD)
+	return iface->if_dev->offload;
+#else
+	return NULL;
+#endif
+}
+
+/**
+ * @brief Return the socket offload status
+ *
+ * @param iface Network interface
+ *
+ * @return True if socket offloading is active, false otherwise.
+ */
+static inline bool net_if_is_socket_offloaded(struct net_if *iface)
+{
+#if defined(CONFIG_NET_SOCKETS_OFFLOAD)
+	return iface->if_dev->offloaded;
+#else
+	ARG_UNUSED(iface);
+
+	return false;
+#endif
+}
+
+/**
+ * @brief Get an network interface's link address
+ *
+ * @param iface Pointer to a network interface structure
+ *
+ * @return a pointer to the network link address
+ */
+static inline struct net_linkaddr *net_if_get_link_addr(struct net_if *iface)
+{
+	return &iface->if_dev->link_addr;
+}
+
+/**
+ * @brief Return network configuration for this network interface
+ *
+ * @param iface Pointer to a network interface structure
+ *
+ * @return Pointer to configuration
+ */
+static inline struct net_if_config *net_if_get_config(struct net_if *iface)
+{
+	return &iface->config;
+}
+
+/**
+ * @brief Start duplicate address detection procedure.
+ *
+ * @param iface Pointer to a network interface structure
+ */
+#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6)
+void net_if_start_dad(struct net_if *iface);
+#else
+static inline void net_if_start_dad(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif
+
+/**
+ * @brief Start neighbor discovery and send router solicitation message.
+ *
+ * @param iface Pointer to a network interface structure
+ */
+void net_if_start_rs(struct net_if *iface);
+
+
+/**
+ * @brief Stop neighbor discovery.
+ *
+ * @param iface Pointer to a network interface structure
+ */
+#if defined(CONFIG_NET_IPV6_ND) && defined(CONFIG_NET_NATIVE_IPV6)
+void net_if_stop_rs(struct net_if *iface);
+#else
+static inline void net_if_stop_rs(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif /* CONFIG_NET_IPV6_ND */
+
+/**
+ * @brief Set a network interface's link address
+ *
+ * @param iface Pointer to a network interface structure
+ * @param addr A pointer to a uint8_t buffer representing the address.
+ *             The buffer must remain valid throughout interface lifetime.
+ * @param len length of the address buffer
+ * @param type network bearer type of this link address
+ *
+ * @return 0 on success
+ */
+static inline int net_if_set_link_addr(struct net_if *iface,
+				       uint8_t *addr, uint8_t len,
+				       enum net_link_type type)
+{
+	if (net_if_flag_is_set(iface, NET_IF_UP)) {
+		return -EPERM;
+	}
+
+	net_if_get_link_addr(iface)->addr = addr;
+	net_if_get_link_addr(iface)->len = len;
+	net_if_get_link_addr(iface)->type = type;
+
+	net_hostname_set_postfix(addr, len);
+
+	return 0;
+}
+
+/**
+ * @brief Get an network interface's MTU
+ *
+ * @param iface Pointer to a network interface structure
+ *
+ * @return the MTU
+ */
+static inline uint16_t net_if_get_mtu(struct net_if *iface)
+{
+	return iface->if_dev->mtu;
+}
+
+/**
+ * @brief Set an network interface's MTU
+ *
+ * @param iface Pointer to a network interface structure
+ * @param mtu New MTU, note that we store only 16 bit mtu value.
+ */
+static inline void net_if_set_mtu(struct net_if *iface,
+				  uint16_t mtu)
+{
+	iface->if_dev->mtu = mtu;
+}
+
+/**
+ * @brief Set the infinite status of the network interface address
+ *
+ * @param ifaddr IP address for network interface
+ * @param is_infinite Infinite status
+ */
+static inline void net_if_addr_set_lf(struct net_if_addr *ifaddr,
+				      bool is_infinite)
+{
+	ifaddr->is_infinite = is_infinite;
+}
+
+/**
+ * @brief Get an interface according to link layer address.
+ *
+ * @param ll_addr Link layer address.
+ *
+ * @return Network interface or NULL if not found.
+ */
+struct net_if *net_if_get_by_link_addr(struct net_linkaddr *ll_addr);
+
+/**
+ * @brief Find an interface from it's related device
+ *
+ * @param dev A valid struct device pointer to relate with an interface
+ *
+ * @return a valid struct net_if pointer on success, NULL otherwise
+ */
+struct net_if *net_if_lookup_by_dev(const struct device *dev);
+
+/**
+ * @brief Get network interface IP config
+ *
+ * @param iface Interface to use.
+ *
+ * @return NULL if not found or pointer to correct config settings.
+ */
+static inline struct net_if_config *net_if_config_get(struct net_if *iface)
+{
+	return &iface->config;
+}
+
+/**
+ * @brief Remove a router from the system
+ *
+ * @param router Pointer to existing router
+ */
+static inline void net_if_router_rm(struct net_if_router *router)
+{
+	router->is_used = false;
+
+	/* FIXME - remove timer */
+}
+
+/**
+ * @brief Get the default network interface.
+ *
+ * @return Default interface or NULL if no interfaces are configured.
+ */
+struct net_if *net_if_get_default(void);
+
+/**
+ * @brief Get the first network interface according to its type.
+ *
+ * @param l2 Layer 2 type of the network interface.
+ *
+ * @return First network interface of a given type or NULL if no such
+ * interfaces was found.
+ */
+struct net_if *net_if_get_first_by_type(const struct net_l2 *l2);
+
+#if defined(CONFIG_NET_L2_IEEE802154)
+/**
+ * @brief Get the first IEEE 802.15.4 network interface.
+ *
+ * @return First IEEE 802.15.4 network interface or NULL if no such
+ * interfaces was found.
+ */
+static inline struct net_if *net_if_get_ieee802154(void)
+{
+	return net_if_get_first_by_type(&NET_L2_GET_NAME(IEEE802154));
+}
+#endif /* CONFIG_NET_L2_IEEE802154 */
+
+/**
+ * @brief Allocate network interface IPv6 config.
+ *
+ * @details This function will allocate new IPv6 config.
+ *
+ * @param iface Interface to use.
+ * @param ipv6 Pointer to allocated IPv6 struct is returned to caller.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_if_config_ipv6_get(struct net_if *iface,
+			   struct net_if_ipv6 **ipv6);
+
+/**
+ * @brief Release network interface IPv6 config.
+ *
+ * @param iface Interface to use.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_if_config_ipv6_put(struct net_if *iface);
+
+/**
+ * @brief Check if this IPv6 address belongs to one of the interfaces.
+ *
+ * @param addr IPv6 address
+ * @param iface Pointer to interface is returned
+ *
+ * @return Pointer to interface address, NULL if not found.
+ */
+struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
+					    struct net_if **iface);
+
+/**
+ * @brief Check if this IPv6 address belongs to this specific interfaces.
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ *
+ * @return Pointer to interface address, NULL if not found.
+ */
+struct net_if_addr *net_if_ipv6_addr_lookup_by_iface(struct net_if *iface,
+						     struct in6_addr *addr);
+
+/**
+ * @brief Check if this IPv6 address belongs to one of the interface indices.
+ *
+ * @param addr IPv6 address
+ *
+ * @return >0 if address was found in given network interface index,
+ * all other values mean address was not found
+ */
+__syscall int net_if_ipv6_addr_lookup_by_index(const struct in6_addr *addr);
+
+/**
+ * @brief Add a IPv6 address to an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ * @param addr_type IPv6 address type
+ * @param vlifetime Validity time for this address
+ *
+ * @return Pointer to interface address, NULL if cannot be added
+ */
+struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
+					 struct in6_addr *addr,
+					 enum net_addr_type addr_type,
+					 uint32_t vlifetime);
+
+/**
+ * @brief Add a IPv6 address to an interface by index
+ *
+ * @param index Network interface index
+ * @param addr IPv6 address
+ * @param addr_type IPv6 address type
+ * @param vlifetime Validity time for this address
+ *
+ * @return True if ok, false if address could not be added
+ */
+__syscall bool net_if_ipv6_addr_add_by_index(int index,
+					     struct in6_addr *addr,
+					     enum net_addr_type addr_type,
+					     uint32_t vlifetime);
+
+/**
+ * @brief Update validity lifetime time of an IPv6 address.
+ *
+ * @param ifaddr Network IPv6 address
+ * @param vlifetime Validity time for this address
+ */
+void net_if_ipv6_addr_update_lifetime(struct net_if_addr *ifaddr,
+				      uint32_t vlifetime);
+
+/**
+ * @brief Remove an IPv6 address from an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr);
+
+/**
+ * @brief Remove an IPv6 address from an interface by index
+ *
+ * @param index Network interface index
+ * @param addr IPv6 address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+__syscall bool net_if_ipv6_addr_rm_by_index(int index,
+					    const struct in6_addr *addr);
+
+/**
+ * @brief Add a IPv6 multicast address to an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 multicast address
+ *
+ * @return Pointer to interface multicast address, NULL if cannot be added
+ */
+struct net_if_mcast_addr *net_if_ipv6_maddr_add(struct net_if *iface,
+						const struct in6_addr *addr);
+
+/**
+ * @brief Remove an IPv6 multicast address from an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 multicast address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv6_maddr_rm(struct net_if *iface, const struct in6_addr *addr);
+
+/**
+ * @brief Check if this IPv6 multicast address belongs to a specific interface
+ * or one of the interfaces.
+ *
+ * @param addr IPv6 address
+ * @param iface If *iface is null, then pointer to interface is returned,
+ * otherwise the *iface value needs to be matched.
+ *
+ * @return Pointer to interface multicast address, NULL if not found.
+ */
+struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr,
+						   struct net_if **iface);
+
+/**
+ * @typedef net_if_mcast_callback_t
+
+ * @brief Define callback that is called whenever IPv6 multicast address group
+ * is joined or left.
+
+ * @param "struct net_if *iface" A pointer to a struct net_if to which the
+ *        multicast address is attached.
+ * @param "const struct in6_addr *addr" IPv6 multicast address.
+ * @param "bool is_joined" True if the address is joined, false if left.
+ */
+typedef void (*net_if_mcast_callback_t)(struct net_if *iface,
+					const struct in6_addr *addr,
+					bool is_joined);
+
+/**
+ * @brief Multicast monitor handler struct.
+ *
+ * Stores the multicast callback information. Caller must make sure that
+ * the variable pointed by this is valid during the lifetime of
+ * registration. Typically this means that the variable cannot be
+ * allocated from stack.
+ */
+struct net_if_mcast_monitor {
+	/** Node information for the slist. */
+	sys_snode_t node;
+
+	/** Network interface */
+	struct net_if *iface;
+
+	/** Multicast callback */
+	net_if_mcast_callback_t cb;
+};
+
+/**
+ * @brief Register a multicast monitor
+ *
+ * @param mon Monitor handle. This is a pointer to a monitor storage structure
+ * which should be allocated by caller, but does not need to be initialized.
+ * @param iface Network interface
+ * @param cb Monitor callback
+ */
+void net_if_mcast_mon_register(struct net_if_mcast_monitor *mon,
+			       struct net_if *iface,
+			       net_if_mcast_callback_t cb);
+
+/**
+ * @brief Unregister a multicast monitor
+ *
+ * @param mon Monitor handle
+ */
+void net_if_mcast_mon_unregister(struct net_if_mcast_monitor *mon);
+
+/**
+ * @brief Call registered multicast monitors
+ *
+ * @param iface Network interface
+ * @param addr Multicast address
+ * @param is_joined Is this multicast address joined (true) or not (false)
+ */
+void net_if_mcast_monitor(struct net_if *iface, const struct in6_addr *addr,
+			  bool is_joined);
+
+/**
+ * @brief Mark a given multicast address to be joined.
+ *
+ * @param addr IPv6 multicast address
+ */
+static inline void net_if_ipv6_maddr_join(struct net_if_mcast_addr *addr)
+{
+	NET_ASSERT(addr);
+
+	addr->is_joined = true;
+}
+
+/**
+ * @brief Check if given multicast address is joined or not.
+ *
+ * @param addr IPv6 multicast address
+ *
+ * @return True if address is joined, False otherwise.
+ */
+static inline bool net_if_ipv6_maddr_is_joined(struct net_if_mcast_addr *addr)
+{
+	NET_ASSERT(addr);
+
+	return addr->is_joined;
+}
+
+/**
+ * @brief Mark a given multicast address to be left.
+ *
+ * @param addr IPv6 multicast address
+ */
+static inline void net_if_ipv6_maddr_leave(struct net_if_mcast_addr *addr)
+{
+	NET_ASSERT(addr);
+
+	addr->is_joined = false;
+}
+
+/**
+ * @brief Return prefix that corresponds to this IPv6 address.
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ *
+ * @return Pointer to prefix, NULL if not found.
+ */
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface,
+						  struct in6_addr *addr);
+
+/**
+ * @brief Check if this IPv6 prefix belongs to this interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ * @param len Prefix length
+ *
+ * @return Pointer to prefix, NULL if not found.
+ */
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_lookup(struct net_if *iface,
+						     struct in6_addr *addr,
+						     uint8_t len);
+
+/**
+ * @brief Add a IPv6 prefix to an network interface.
+ *
+ * @param iface Network interface
+ * @param prefix IPv6 address
+ * @param len Prefix length
+ * @param lifetime Prefix lifetime in seconds
+ *
+ * @return Pointer to prefix, NULL if the prefix was not added.
+ */
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_add(struct net_if *iface,
+						  struct in6_addr *prefix,
+						  uint8_t len,
+						  uint32_t lifetime);
+
+/**
+ * @brief Remove an IPv6 prefix from an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv6 prefix address
+ * @param len Prefix length
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv6_prefix_rm(struct net_if *iface, struct in6_addr *addr,
+			   uint8_t len);
+
+/**
+ * @brief Set the infinite status of the prefix
+ *
+ * @param prefix IPv6 address
+ * @param is_infinite Infinite status
+ */
+static inline void net_if_ipv6_prefix_set_lf(struct net_if_ipv6_prefix *prefix,
+					     bool is_infinite)
+{
+	prefix->is_infinite = is_infinite;
+}
+
+/**
+ * @brief Set the prefix lifetime timer.
+ *
+ * @param prefix IPv6 address
+ * @param lifetime Prefix lifetime in seconds
+ */
+void net_if_ipv6_prefix_set_timer(struct net_if_ipv6_prefix *prefix,
+				  uint32_t lifetime);
+
+/**
+ * @brief Unset the prefix lifetime timer.
+ *
+ * @param prefix IPv6 address
+ */
+void net_if_ipv6_prefix_unset_timer(struct net_if_ipv6_prefix *prefix);
+
+/**
+ * @brief Check if this IPv6 address is part of the subnet of our
+ * network interface.
+ *
+ * @param iface Network interface. This is returned to the caller.
+ * The iface can be NULL in which case we check all the interfaces.
+ * @param addr IPv6 address
+ *
+ * @return True if address is part of our subnet, false otherwise
+ */
+bool net_if_ipv6_addr_onlink(struct net_if **iface, struct in6_addr *addr);
+
+/**
+ * @brief Get the IPv6 address of the given router
+ * @param router a network router
+ *
+ * @return pointer to the IPv6 address, or NULL if none
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+static inline struct in6_addr *net_if_router_ipv6(struct net_if_router *router)
+{
+	return &router->address.in6_addr;
+}
+#else
+static inline struct in6_addr *net_if_router_ipv6(struct net_if_router *router)
+{
+	static struct in6_addr addr;
+
+	ARG_UNUSED(router);
+
+	return &addr;
+}
+#endif
+
+/**
+ * @brief Check if IPv6 address is one of the routers configured
+ * in the system.
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ *
+ * @return Pointer to router information, NULL if cannot be found
+ */
+struct net_if_router *net_if_ipv6_router_lookup(struct net_if *iface,
+						struct in6_addr *addr);
+
+/**
+ * @brief Find default router for this IPv6 address.
+ *
+ * @param iface Network interface. This can be NULL in which case we
+ * go through all the network interfaces to find a suitable router.
+ * @param addr IPv6 address
+ *
+ * @return Pointer to router information, NULL if cannot be found
+ */
+struct net_if_router *net_if_ipv6_router_find_default(struct net_if *iface,
+						      struct in6_addr *addr);
+
+/**
+ * @brief Update validity lifetime time of a router.
+ *
+ * @param router Network IPv6 address
+ * @param lifetime Lifetime of this router.
+ */
+void net_if_ipv6_router_update_lifetime(struct net_if_router *router,
+					uint16_t lifetime);
+
+/**
+ * @brief Add IPv6 router to the system.
+ *
+ * @param iface Network interface
+ * @param addr IPv6 address
+ * @param router_lifetime Lifetime of the router
+ *
+ * @return Pointer to router information, NULL if could not be added
+ */
+struct net_if_router *net_if_ipv6_router_add(struct net_if *iface,
+					     struct in6_addr *addr,
+					     uint16_t router_lifetime);
+
+/**
+ * @brief Remove IPv6 router from the system.
+ *
+ * @param router Router information.
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv6_router_rm(struct net_if_router *router);
+
+/**
+ * @brief Get IPv6 hop limit specified for a given interface. This is the
+ * default value but can be overridden by the user.
+ *
+ * @param iface Network interface
+ *
+ * @return Hop limit
+ */
+static inline uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return 0;
+	}
+
+	return iface->config.ip.ipv6->hop_limit;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Set the default IPv6 hop limit of a given interface.
+ *
+ * @param iface Network interface
+ * @param hop_limit New hop limit
+ */
+static inline void net_ipv6_set_hop_limit(struct net_if *iface,
+					  uint8_t hop_limit)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return;
+	}
+
+	iface->config.ip.ipv6->hop_limit = hop_limit;
+#endif
+}
+
+/**
+ * @brief Set IPv6 reachable time for a given interface
+ *
+ * @param iface Network interface
+ * @param reachable_time New reachable time
+ */
+static inline void net_if_ipv6_set_base_reachable_time(struct net_if *iface,
+						       uint32_t reachable_time)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return;
+	}
+
+	iface->config.ip.ipv6->base_reachable_time = reachable_time;
+#endif
+}
+
+/**
+ * @brief Get IPv6 reachable timeout specified for a given interface
+ *
+ * @param iface Network interface
+ *
+ * @return Reachable timeout
+ */
+static inline uint32_t net_if_ipv6_get_reachable_time(struct net_if *iface)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return 0;
+	}
+
+	return iface->config.ip.ipv6->reachable_time;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Calculate next reachable time value for IPv6 reachable time
+ *
+ * @param ipv6 IPv6 address configuration
+ *
+ * @return Reachable time
+ */
+uint32_t net_if_ipv6_calc_reachable_time(struct net_if_ipv6 *ipv6);
+
+/**
+ * @brief Set IPv6 reachable time for a given interface. This requires
+ * that base reachable time is set for the interface.
+ *
+ * @param ipv6 IPv6 address configuration
+ */
+static inline void net_if_ipv6_set_reachable_time(struct net_if_ipv6 *ipv6)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	ipv6->reachable_time = net_if_ipv6_calc_reachable_time(ipv6);
+#endif
+}
+
+/**
+ * @brief Set IPv6 retransmit timer for a given interface
+ *
+ * @param iface Network interface
+ * @param retrans_timer New retransmit timer
+ */
+static inline void net_if_ipv6_set_retrans_timer(struct net_if *iface,
+						 uint32_t retrans_timer)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return;
+	}
+
+	iface->config.ip.ipv6->retrans_timer = retrans_timer;
+#endif
+}
+
+/**
+ * @brief Get IPv6 retransmit timer specified for a given interface
+ *
+ * @param iface Network interface
+ *
+ * @return Retransmit timer
+ */
+static inline uint32_t net_if_ipv6_get_retrans_timer(struct net_if *iface)
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	if (!iface->config.ip.ipv6) {
+		return 0;
+	}
+
+	return iface->config.ip.ipv6->retrans_timer;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Get a IPv6 source address that should be used when sending
+ * network data to destination.
+ *
+ * @param iface Interface that was used when packet was received.
+ * If the interface is not known, then NULL can be given.
+ * @param dst IPv6 destination address
+ *
+ * @return Pointer to IPv6 address to use, NULL if no IPv6 address
+ * could be found.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *iface,
+						   const struct in6_addr *dst);
+#else
+static inline const struct in6_addr *net_if_ipv6_select_src_addr(
+	struct net_if *iface, const struct in6_addr *dst)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(dst);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Get a network interface that should be used when sending
+ * IPv6 network data to destination.
+ *
+ * @param dst IPv6 destination address
+ *
+ * @return Pointer to network interface to use, NULL if no suitable interface
+ * could be found.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+struct net_if *net_if_ipv6_select_src_iface(const struct in6_addr *dst);
+#else
+static inline struct net_if *net_if_ipv6_select_src_iface(
+	const struct in6_addr *dst)
+{
+	ARG_UNUSED(dst);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Get a IPv6 link local address in a given state.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr_state IPv6 address state (preferred, tentative, deprecated)
+ *
+ * @return Pointer to link local IPv6 address, NULL if no proper IPv6 address
+ * could be found.
+ */
+struct in6_addr *net_if_ipv6_get_ll(struct net_if *iface,
+				    enum net_addr_state addr_state);
+
+/**
+ * @brief Return link local IPv6 address from the first interface that has
+ * a link local address matching give state.
+ *
+ * @param state IPv6 address state (ANY, TENTATIVE, PREFERRED, DEPRECATED)
+ * @param iface Pointer to interface is returned
+ *
+ * @return Pointer to IPv6 address, NULL if not found.
+ */
+struct in6_addr *net_if_ipv6_get_ll_addr(enum net_addr_state state,
+					 struct net_if **iface);
+
+/**
+ * @brief Stop IPv6 Duplicate Address Detection (DAD) procedure if
+ * we find out that our IPv6 address is already in use.
+ *
+ * @param iface Interface where the DAD was running.
+ * @param addr IPv6 address that failed DAD
+ */
+void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr);
+
+/**
+ * @brief Return global IPv6 address from the first interface that has
+ * a global IPv6 address matching the given state.
+ *
+ * @param state IPv6 address state (ANY, TENTATIVE, PREFERRED, DEPRECATED)
+ * @param iface Caller can give an interface to check. If iface is set to NULL,
+ * then all the interfaces are checked. Pointer to interface where the IPv6
+ * address is defined is returned to the caller.
+ *
+ * @return Pointer to IPv6 address, NULL if not found.
+ */
+struct in6_addr *net_if_ipv6_get_global_addr(enum net_addr_state state,
+					     struct net_if **iface);
+
+/**
+ * @brief Allocate network interface IPv4 config.
+ *
+ * @details This function will allocate new IPv4 config.
+ *
+ * @param iface Interface to use.
+ * @param ipv4 Pointer to allocated IPv4 struct is returned to caller.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_if_config_ipv4_get(struct net_if *iface,
+			   struct net_if_ipv4 **ipv4);
+
+/**
+ * @brief Release network interface IPv4 config.
+ *
+ * @param iface Interface to use.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_if_config_ipv4_put(struct net_if *iface);
+
+/**
+ * @brief Get IPv4 time-to-live value specified for a given interface
+ *
+ * @param iface Network interface
+ *
+ * @return Time-to-live
+ */
+static inline uint8_t net_if_ipv4_get_ttl(struct net_if *iface)
+{
+#if defined(CONFIG_NET_NATIVE_IPV4)
+	if (!iface->config.ip.ipv4) {
+		return 0;
+	}
+
+	return iface->config.ip.ipv4->ttl;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Check if this IPv4 address belongs to one of the interfaces.
+ *
+ * @param addr IPv4 address
+ * @param iface Interface is returned
+ *
+ * @return Pointer to interface address, NULL if not found.
+ */
+struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
+					    struct net_if **iface);
+
+/**
+ * @brief Add a IPv4 address to an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv4 address
+ * @param addr_type IPv4 address type
+ * @param vlifetime Validity time for this address
+ *
+ * @return Pointer to interface address, NULL if cannot be added
+ */
+struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
+					 struct in_addr *addr,
+					 enum net_addr_type addr_type,
+					 uint32_t vlifetime);
+
+/**
+ * @brief Remove a IPv4 address from an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv4 address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv4_addr_rm(struct net_if *iface, const struct in_addr *addr);
+
+/**
+ * @brief Check if this IPv4 address belongs to one of the interface indices.
+ *
+ * @param addr IPv4 address
+ *
+ * @return >0 if address was found in given network interface index,
+ * all other values mean address was not found
+ */
+__syscall int net_if_ipv4_addr_lookup_by_index(const struct in_addr *addr);
+
+/**
+ * @brief Add a IPv4 address to an interface by network interface index
+ *
+ * @param index Network interface index
+ * @param addr IPv4 address
+ * @param addr_type IPv4 address type
+ * @param vlifetime Validity time for this address
+ *
+ * @return True if ok, false if the address could not be added
+ */
+__syscall bool net_if_ipv4_addr_add_by_index(int index,
+					     struct in_addr *addr,
+					     enum net_addr_type addr_type,
+					     uint32_t vlifetime);
+
+/**
+ * @brief Remove a IPv4 address from an interface by interface index
+ *
+ * @param index Network interface index
+ * @param addr IPv4 address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+__syscall bool net_if_ipv4_addr_rm_by_index(int index,
+					    const struct in_addr *addr);
+
+/**
+ * @brief Add a IPv4 multicast address to an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv4 multicast address
+ *
+ * @return Pointer to interface multicast address, NULL if cannot be added
+ */
+struct net_if_mcast_addr *net_if_ipv4_maddr_add(struct net_if *iface,
+						const struct in_addr *addr);
+
+/**
+ * @brief Remove an IPv4 multicast address from an interface
+ *
+ * @param iface Network interface
+ * @param addr IPv4 multicast address
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv4_maddr_rm(struct net_if *iface, const struct in_addr *addr);
+
+/**
+ * @brief Check if this IPv4 multicast address belongs to a specific interface
+ * or one of the interfaces.
+ *
+ * @param addr IPv4 address
+ * @param iface If *iface is null, then pointer to interface is returned,
+ * otherwise the *iface value needs to be matched.
+ *
+ * @return Pointer to interface multicast address, NULL if not found.
+ */
+struct net_if_mcast_addr *net_if_ipv4_maddr_lookup(const struct in_addr *addr,
+						   struct net_if **iface);
+
+/**
+ * @brief Get the IPv4 address of the given router
+ * @param router a network router
+ *
+ * @return pointer to the IPv4 address, or NULL if none
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+static inline struct in_addr *net_if_router_ipv4(struct net_if_router *router)
+{
+	return &router->address.in_addr;
+}
+#else
+static inline struct in_addr *net_if_router_ipv4(struct net_if_router *router)
+{
+	static struct in_addr addr;
+
+	ARG_UNUSED(router);
+
+	return &addr;
+}
+#endif
+
+/**
+ * @brief Check if IPv4 address is one of the routers configured
+ * in the system.
+ *
+ * @param iface Network interface
+ * @param addr IPv4 address
+ *
+ * @return Pointer to router information, NULL if cannot be found
+ */
+struct net_if_router *net_if_ipv4_router_lookup(struct net_if *iface,
+						struct in_addr *addr);
+
+/**
+ * @brief Find default router for this IPv4 address.
+ *
+ * @param iface Network interface. This can be NULL in which case we
+ * go through all the network interfaces to find a suitable router.
+ * @param addr IPv4 address
+ *
+ * @return Pointer to router information, NULL if cannot be found
+ */
+struct net_if_router *net_if_ipv4_router_find_default(struct net_if *iface,
+						      struct in_addr *addr);
+/**
+ * @brief Add IPv4 router to the system.
+ *
+ * @param iface Network interface
+ * @param addr IPv4 address
+ * @param is_default Is this router the default one
+ * @param router_lifetime Lifetime of the router
+ *
+ * @return Pointer to router information, NULL if could not be added
+ */
+struct net_if_router *net_if_ipv4_router_add(struct net_if *iface,
+					     struct in_addr *addr,
+					     bool is_default,
+					     uint16_t router_lifetime);
+
+/**
+ * @brief Remove IPv4 router from the system.
+ *
+ * @param router Router information.
+ *
+ * @return True if successfully removed, false otherwise
+ */
+bool net_if_ipv4_router_rm(struct net_if_router *router);
+
+/**
+ * @brief Check if the given IPv4 address belongs to local subnet.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr IPv4 address
+ *
+ * @return True if address is part of local subnet, false otherwise.
+ */
+bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
+			       const struct in_addr *addr);
+
+/**
+ * @brief Check if the given IPv4 address is a broadcast address.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr IPv4 address, this should be in network byte order
+ *
+ * @return True if address is a broadcast address, false otherwise.
+ */
+bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
+			       const struct in_addr *addr);
+
+/**
+ * @brief Get a network interface that should be used when sending
+ * IPv4 network data to destination.
+ *
+ * @param dst IPv4 destination address
+ *
+ * @return Pointer to network interface to use, NULL if no suitable interface
+ * could be found.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+struct net_if *net_if_ipv4_select_src_iface(const struct in_addr *dst);
+#else
+static inline struct net_if *net_if_ipv4_select_src_iface(
+	const struct in_addr *dst)
+{
+	ARG_UNUSED(dst);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Get a IPv4 source address that should be used when sending
+ * network data to destination.
+ *
+ * @param iface Interface to use when sending the packet.
+ * If the interface is not known, then NULL can be given.
+ * @param dst IPv4 destination address
+ *
+ * @return Pointer to IPv4 address to use, NULL if no IPv4 address
+ * could be found.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+const struct in_addr *net_if_ipv4_select_src_addr(struct net_if *iface,
+						  const struct in_addr *dst);
+#else
+static inline const struct in_addr *net_if_ipv4_select_src_addr(
+	struct net_if *iface, const struct in_addr *dst)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(dst);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Get a IPv4 link local address in a given state.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr_state IPv4 address state (preferred, tentative, deprecated)
+ *
+ * @return Pointer to link local IPv4 address, NULL if no proper IPv4 address
+ * could be found.
+ */
+struct in_addr *net_if_ipv4_get_ll(struct net_if *iface,
+				   enum net_addr_state addr_state);
+
+/**
+ * @brief Get a IPv4 global address in a given state.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr_state IPv4 address state (preferred, tentative, deprecated)
+ *
+ * @return Pointer to link local IPv4 address, NULL if no proper IPv4 address
+ * could be found.
+ */
+struct in_addr *net_if_ipv4_get_global_addr(struct net_if *iface,
+					    enum net_addr_state addr_state);
+
+/**
+ * @brief Set IPv4 netmask for an interface.
+ *
+ * @param iface Interface to use.
+ * @param netmask IPv4 netmask
+ */
+void net_if_ipv4_set_netmask(struct net_if *iface,
+			     const struct in_addr *netmask);
+
+/**
+ * @brief Set IPv4 netmask for an interface index.
+ *
+ * @param index Network interface index
+ * @param netmask IPv4 netmask
+ *
+ * @return True if netmask was added, false otherwise.
+ */
+__syscall bool net_if_ipv4_set_netmask_by_index(int index,
+						const struct in_addr *netmask);
+
+/**
+ * @brief Set IPv4 gateway for an interface.
+ *
+ * @param iface Interface to use.
+ * @param gw IPv4 address of an gateway
+ */
+void net_if_ipv4_set_gw(struct net_if *iface, const struct in_addr *gw);
+
+/**
+ * @brief Set IPv4 gateway for an interface index.
+ *
+ * @param index Network interface index
+ * @param gw IPv4 address of an gateway
+ *
+ * @return True if gateway was added, false otherwise.
+ */
+__syscall bool net_if_ipv4_set_gw_by_index(int index, const struct in_addr *gw);
+
+/**
+ * @brief Get a network interface that should be used when sending
+ * IPv6 or IPv4 network data to destination.
+ *
+ * @param dst IPv6 or IPv4 destination address
+ *
+ * @return Pointer to network interface to use. Note that the function
+ * will return the default network interface if the best network interface
+ * is not found.
+ */
+struct net_if *net_if_select_src_iface(const struct sockaddr *dst);
+
+/**
+ * @typedef net_if_link_callback_t
+ * @brief Define callback that is called after a network packet
+ *        has been sent.
+ * @param "struct net_if *iface" A pointer to a struct net_if to which the
+ *        the net_pkt was sent to.
+ * @param "struct net_linkaddr *dst" Link layer address of the destination
+ *        where the network packet was sent.
+ * @param "int status" Send status, 0 is ok, < 0 error.
+ */
+typedef void (*net_if_link_callback_t)(struct net_if *iface,
+				       struct net_linkaddr *dst,
+				       int status);
+
+/**
+ * @brief Link callback handler struct.
+ *
+ * Stores the link callback information. Caller must make sure that
+ * the variable pointed by this is valid during the lifetime of
+ * registration. Typically this means that the variable cannot be
+ * allocated from stack.
+ */
+struct net_if_link_cb {
+	/** Node information for the slist. */
+	sys_snode_t node;
+
+	/** Link callback */
+	net_if_link_callback_t cb;
+};
+
+/**
+ * @brief Register a link callback.
+ *
+ * @param link Caller specified handler for the callback.
+ * @param cb Callback to register.
+ */
+void net_if_register_link_cb(struct net_if_link_cb *link,
+			     net_if_link_callback_t cb);
+
+/**
+ * @brief Unregister a link callback.
+ *
+ * @param link Caller specified handler for the callback.
+ */
+void net_if_unregister_link_cb(struct net_if_link_cb *link);
+
+/**
+ * @brief Call a link callback function.
+ *
+ * @param iface Network interface.
+ * @param lladdr Destination link layer address
+ * @param status 0 is ok, < 0 error
+ */
+void net_if_call_link_cb(struct net_if *iface, struct net_linkaddr *lladdr,
+			 int status);
+
+/**
+ * @brief Check if received network packet checksum calculation can be avoided
+ * or not. For example many ethernet devices support network packet offloading
+ * in which case the IP stack does not need to calculate the checksum.
+ *
+ * @param iface Network interface
+ *
+ * @return True if checksum needs to be calculated, false otherwise.
+ */
+bool net_if_need_calc_rx_checksum(struct net_if *iface);
+
+/**
+ * @brief Check if network packet checksum calculation can be avoided or not
+ * when sending the packet. For example many ethernet devices support network
+ * packet offloading in which case the IP stack does not need to calculate the
+ * checksum.
+ *
+ * @param iface Network interface
+ *
+ * @return True if checksum needs to be calculated, false otherwise.
+ */
+bool net_if_need_calc_tx_checksum(struct net_if *iface);
+
+/**
+ * @brief Get interface according to index
+ *
+ * @details This is a syscall only to provide access to the object for purposes
+ *          of assigning permissions.
+ *
+ * @param index Interface index
+ *
+ * @return Pointer to interface or NULL if not found.
+ */
+__syscall struct net_if *net_if_get_by_index(int index);
+
+/**
+ * @brief Get interface index according to pointer
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return Interface index
+ */
+int net_if_get_by_iface(struct net_if *iface);
+
+/**
+ * @typedef net_if_cb_t
+ * @brief Callback used while iterating over network interfaces
+ *
+ * @param iface Pointer to current network interface
+ * @param user_data A valid pointer to user data or NULL
+ */
+typedef void (*net_if_cb_t)(struct net_if *iface, void *user_data);
+
+/**
+ * @brief Go through all the network interfaces and call callback
+ * for each interface.
+ *
+ * @param cb User-supplied callback function to call
+ * @param user_data User specified data
+ */
+void net_if_foreach(net_if_cb_t cb, void *user_data);
+
+/**
+ * @brief Bring interface up
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return 0 on success
+ */
+int net_if_up(struct net_if *iface);
+
+/**
+ * @brief Check if interface is up.
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return True if interface is up, False if it is down.
+ */
+static inline bool net_if_is_up(struct net_if *iface)
+{
+	NET_ASSERT(iface);
+
+	return net_if_flag_is_set(iface, NET_IF_UP);
+}
+
+/**
+ * @brief Bring interface down
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return 0 on success
+ */
+int net_if_down(struct net_if *iface);
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP) && defined(CONFIG_NET_NATIVE)
+/**
+ * @typedef net_if_timestamp_callback_t
+ * @brief Define callback that is called after a network packet
+ *        has been timestamped.
+ * @param "struct net_pkt *pkt" A pointer on a struct net_pkt which has
+ *        been timestamped after being sent.
+ */
+typedef void (*net_if_timestamp_callback_t)(struct net_pkt *pkt);
+
+/**
+ * @brief Timestamp callback handler struct.
+ *
+ * Stores the timestamp callback information. Caller must make sure that
+ * the variable pointed by this is valid during the lifetime of
+ * registration. Typically this means that the variable cannot be
+ * allocated from stack.
+ */
+struct net_if_timestamp_cb {
+	/** Node information for the slist. */
+	sys_snode_t node;
+
+	/** Packet for which the callback is needed.
+	 *  A NULL value means all packets.
+	 */
+	struct net_pkt *pkt;
+
+	/** Net interface for which the callback is needed.
+	 *  A NULL value means all interfaces.
+	 */
+	struct net_if *iface;
+
+	/** Timestamp callback */
+	net_if_timestamp_callback_t cb;
+};
+
+/**
+ * @brief Register a timestamp callback.
+ *
+ * @param handle Caller specified handler for the callback.
+ * @param pkt Net packet for which the callback is registered. NULL for all
+ * 	      packets.
+ * @param iface Net interface for which the callback is. NULL for all
+ *		interfaces.
+ * @param cb Callback to register.
+ */
+void net_if_register_timestamp_cb(struct net_if_timestamp_cb *handle,
+				  struct net_pkt *pkt,
+				  struct net_if *iface,
+				  net_if_timestamp_callback_t cb);
+
+/**
+ * @brief Unregister a timestamp callback.
+ *
+ * @param handle Caller specified handler for the callback.
+ */
+void net_if_unregister_timestamp_cb(struct net_if_timestamp_cb *handle);
+
+/**
+ * @brief Call a timestamp callback function.
+ *
+ * @param pkt Network buffer.
+ */
+void net_if_call_timestamp_cb(struct net_pkt *pkt);
+
+/*
+ * @brief Add timestamped TX buffer to be handled
+ *
+ * @param pkt Timestamped buffer
+ */
+void net_if_add_tx_timestamp(struct net_pkt *pkt);
+#endif /* CONFIG_NET_PKT_TIMESTAMP */
+
+/**
+ * @brief Set network interface into promiscuous mode
+ *
+ * @details Note that not all network technologies will support this.
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return 0 on success, <0 if error
+ */
+int net_if_set_promisc(struct net_if *iface);
+
+/**
+ * @brief Set network interface into normal mode
+ *
+ * @param iface Pointer to network interface
+ */
+void net_if_unset_promisc(struct net_if *iface);
+
+/**
+ * @brief Check if promiscuous mode is set or not.
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return True if interface is in promisc mode,
+ *         False if interface is not in in promiscuous mode.
+ */
+bool net_if_is_promisc(struct net_if *iface);
+
+/**
+ * @brief Check if there are any pending TX network data for a given network
+ *        interface.
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return True if there are pending TX network packets for this network
+ *         interface, False otherwise.
+ */
+static inline bool net_if_are_pending_tx_packets(struct net_if *iface)
+{
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	return !!iface->tx_pending;
+#else
+	ARG_UNUSED(iface);
+
+	return false;
+#endif
+}
+
+#ifdef CONFIG_NET_POWER_MANAGEMENT
+/**
+ * @brief Suspend a network interface from a power management perspective
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return 0 on success, or -EALREADY/-EBUSY as possible errors.
+ */
+int net_if_suspend(struct net_if *iface);
+
+/**
+ * @brief Resume a network interface from a power management perspective
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return 0 on success, or -EALREADY as a possible error.
+ */
+int net_if_resume(struct net_if *iface);
+
+/**
+ * @brief Check if the network interface is suspended or not.
+ *
+ * @param iface Pointer to network interface
+ *
+ * @return True if interface is suspended, False otherwise.
+ */
+bool net_if_is_suspended(struct net_if *iface);
+#endif /* CONFIG_NET_POWER_MANAGEMENT */
+
+/** @cond INTERNAL_HIDDEN */
+struct net_if_api {
+	void (*init)(struct net_if *iface);
+};
+
+#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+#define NET_IF_DHCPV4_INIT .dhcpv4.state = NET_DHCPV4_DISABLED,
+#else
+#define NET_IF_DHCPV4_INIT
+#endif
+
+#define NET_IF_CONFIG_INIT				\
+	.config = {					\
+		.ip = {					\
+		},					\
+		NET_IF_DHCPV4_INIT			\
+	}
+
+#define NET_IF_GET_NAME(dev_name, sfx) __net_if_##dev_name##_##sfx
+#define NET_IF_DEV_GET_NAME(dev_name, sfx) __net_if_dev_##dev_name##_##sfx
+
+#define NET_IF_GET(dev_name, sfx)					\
+	((struct net_if *)&NET_IF_GET_NAME(dev_name, sfx))
+
+#define NET_IF_INIT(dev_name, sfx, _l2, _mtu, _num_configs)		\
+	static Z_STRUCT_SECTION_ITERABLE(net_if_dev,			\
+				NET_IF_DEV_GET_NAME(dev_name, sfx)) = { \
+		.dev = &(DEVICE_NAME_GET(dev_name)),			\
+		.l2 = &(NET_L2_GET_NAME(_l2)),				\
+		.l2_data = &(NET_L2_GET_DATA(dev_name, sfx)),		\
+		.mtu = _mtu,						\
+	};								\
+	static Z_DECL_ALIGN(struct net_if)				\
+		       NET_IF_GET_NAME(dev_name, sfx)[_num_configs]	\
+		       __used __in_section(_net_if, static, net_if) = {	\
+		[0 ... (_num_configs - 1)] = {				\
+			.if_dev = &(NET_IF_DEV_GET_NAME(dev_name, sfx)), \
+			NET_IF_CONFIG_INIT				\
+		}							\
+	}
+
+#define NET_IF_OFFLOAD_INIT(dev_name, sfx, _mtu)			\
+	static Z_STRUCT_SECTION_ITERABLE(net_if_dev,			\
+				NET_IF_DEV_GET_NAME(dev_name, sfx)) = {	\
+		.dev = &(DEVICE_NAME_GET(dev_name)),			\
+		.mtu = _mtu,						\
+	};								\
+	static Z_DECL_ALIGN(struct net_if)				\
+		NET_IF_GET_NAME(dev_name, sfx)[NET_IF_MAX_CONFIGS]	\
+		       __used __in_section(_net_if, static, net_if) = {	\
+		[0 ... (NET_IF_MAX_CONFIGS - 1)] = {			\
+			.if_dev = &(NET_IF_DEV_GET_NAME(dev_name, sfx)), \
+			NET_IF_CONFIG_INIT				\
+		}							\
+	}
+
+/** @endcond */
+
+/* Network device initialization macros */
+
+/**
+ * @def NET_DEVICE_INIT
+ *
+ * @brief Create a network interface and bind it to network device.
+ *
+ * @param dev_name Network device name.
+ * @param drv_name The name this instance of the driver exposes to
+ * the system.
+ * @param init_fn Address to the init function of the driver.
+ * @param pm_control_fn Pointer to device_pm_control function.
+ * Can be empty function (device_pm_control_nop) if not implemented.
+ * @param data Pointer to the device's private data.
+ * @param cfg The address to the structure containing the
+ * configuration information for this instance of the driver.
+ * @param prio The initialization level at which configuration occurs.
+ * @param api Provides an initial pointer to the API function struct
+ * used by the driver. Can be NULL.
+ * @param l2 Network L2 layer for this network interface.
+ * @param l2_ctx_type Type of L2 context data.
+ * @param mtu Maximum transfer unit in bytes for this network interface.
+ */
+#define NET_DEVICE_INIT(dev_name, drv_name, init_fn, pm_control_fn,	\
+			data, cfg, prio, api, l2,			\
+			l2_ctx_type, mtu)				\
+	DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, data, \
+		      cfg, POST_KERNEL, prio, api);			\
+	NET_L2_DATA_INIT(dev_name, 0, l2_ctx_type);			\
+	NET_IF_INIT(dev_name, 0, l2, mtu, NET_IF_MAX_CONFIGS)
+
+/**
+ * @def NET_DEVICE_INIT_INSTANCE
+ *
+ * @brief Create multiple network interfaces and bind them to network device.
+ * If your network device needs more than one instance of a network interface,
+ * use this macro below and provide a different instance suffix each time
+ * (0, 1, 2, ... or a, b, c ... whatever works for you)
+ *
+ * @param dev_name Network device name.
+ * @param drv_name The name this instance of the driver exposes to
+ * the system.
+ * @param instance Instance identifier.
+ * @param init_fn Address to the init function of the driver.
+ * @param pm_control_fn Pointer to device_pm_control function.
+ * Can be empty function (device_pm_control_nop) if not implemented.
+ * @param data Pointer to the device's private data.
+ * @param cfg The address to the structure containing the
+ * configuration information for this instance of the driver.
+ * @param prio The initialization level at which configuration occurs.
+ * @param api Provides an initial pointer to the API function struct
+ * used by the driver. Can be NULL.
+ * @param l2 Network L2 layer for this network interface.
+ * @param l2_ctx_type Type of L2 context data.
+ * @param mtu Maximum transfer unit in bytes for this network interface.
+ */
+#define NET_DEVICE_INIT_INSTANCE(dev_name, drv_name, instance, init_fn,	\
+				 pm_control_fn, data, cfg, prio,	\
+				 api, l2, l2_ctx_type, mtu)		\
+	DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, data,	\
+		      cfg, POST_KERNEL, prio, api);			\
+	NET_L2_DATA_INIT(dev_name, instance, l2_ctx_type);		\
+	NET_IF_INIT(dev_name, instance, l2, mtu, NET_IF_MAX_CONFIGS)
+
+/**
+ * @def NET_DEVICE_OFFLOAD_INIT
+ *
+ * @brief Create a offloaded network interface and bind it to network device.
+ * The offloaded network interface is implemented by a device vendor HAL or
+ * similar.
+ *
+ * @param dev_name Network device name.
+ * @param drv_name The name this instance of the driver exposes to
+ * the system.
+ * @param init_fn Address to the init function of the driver.
+ * @param pm_control_fn Pointer to device_pm_control function.
+ * Can be empty function (device_pm_control_nop) if not implemented.
+ * @param data Pointer to the device's private data.
+ * @param cfg The address to the structure containing the
+ * configuration information for this instance of the driver.
+ * @param prio The initialization level at which configuration occurs.
+ * @param api Provides an initial pointer to the API function struct
+ * used by the driver. Can be NULL.
+ * @param mtu Maximum transfer unit in bytes for this network interface.
+ */
+#define NET_DEVICE_OFFLOAD_INIT(dev_name, drv_name, init_fn,		\
+				pm_control_fn, data, cfg, prio,		\
+				api, mtu)				\
+	DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, data,	\
+		      cfg, POST_KERNEL, prio, api);			\
+	NET_IF_OFFLOAD_INIT(dev_name, 0, mtu)
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/net_if.h>
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_IF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_ip.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_ip.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_ip.h	(working copy)
@@ -0,0 +1,1537 @@
+/** @file
+ * @brief IPv6 and IPv4 definitions
+ *
+ * Generic IPv6 and IPv4 address definitions.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_IP_H_
+#define ZEPHYR_INCLUDE_NET_NET_IP_H_
+
+/**
+ * @brief IPv4/IPv6 primitives and helpers
+ * @defgroup ip_4_6 IPv4/IPv6 primitives and helpers
+ * @ingroup networking
+ * @{
+ */
+
+#include <string.h>
+#include <zephyr/types.h>
+#include <stdbool.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+#include <toolchain.h>
+
+#include <net/net_linkaddr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+/* Specifying VLAN tag here in order to avoid circular dependencies */
+#define NET_VLAN_TAG_UNSPEC 0x0fff
+/** @endcond */
+
+/* Protocol families. */
+#define PF_UNSPEC       0          /**< Unspecified protocol family.  */
+#define PF_INET         1          /**< IP protocol family version 4. */
+#define PF_INET6        2          /**< IP protocol family version 6. */
+#define PF_PACKET       3          /**< Packet family.                */
+#define PF_CAN          4          /**< Controller Area Network.      */
+#define PF_NET_MGMT     5          /**< Network management info.      */
+#define PF_LOCAL        6          /**< Inter-process communication   */
+#define PF_UNIX         PF_LOCAL   /**< Inter-process communication   */
+
+/* Address families. */
+#define AF_UNSPEC      PF_UNSPEC   /**< Unspecified address family.   */
+#define AF_INET        PF_INET     /**< IP protocol family version 4. */
+#define AF_INET6       PF_INET6    /**< IP protocol family version 6. */
+#define AF_PACKET      PF_PACKET   /**< Packet family.                */
+#define AF_CAN         PF_CAN      /**< Controller Area Network.      */
+#define AF_NET_MGMT    PF_NET_MGMT /**< Network management info.      */
+#define AF_LOCAL       PF_LOCAL    /**< Inter-process communication   */
+#define AF_UNIX        PF_UNIX     /**< Inter-process communication   */
+
+/** Protocol numbers from IANA/BSD */
+enum net_ip_protocol {
+	IPPROTO_IP = 0,            /**< IP protocol (pseudo-val for setsockopt() */
+	IPPROTO_ICMP = 1,          /**< ICMP protocol   */
+	IPPROTO_TCP = 6,           /**< TCP protocol    */
+	IPPROTO_UDP = 17,          /**< UDP protocol    */
+	IPPROTO_IPV6 = 41,         /**< IPv6 protocol   */
+	IPPROTO_ICMPV6 = 58,       /**< ICMPv6 protocol */
+	IPPROTO_RAW = 255,         /**< RAW IP packets  */
+};
+
+/** Protocol numbers for TLS protocols */
+enum net_ip_protocol_secure {
+	IPPROTO_TLS_1_0 = 256,     /**< TLS 1.0 protocol */
+	IPPROTO_TLS_1_1 = 257,     /**< TLS 1.1 protocol */
+	IPPROTO_TLS_1_2 = 258,     /**< TLS 1.2 protocol */
+	IPPROTO_DTLS_1_0 = 272,    /**< DTLS 1.0 protocol */
+	IPPROTO_DTLS_1_2 = 273,    /**< DTLS 1.2 protocol */
+};
+
+/** Socket type */
+enum net_sock_type {
+	SOCK_STREAM = 1,           /**< Stream socket type   */
+	SOCK_DGRAM,                /**< Datagram socket type */
+	SOCK_RAW                   /**< RAW socket type      */
+};
+
+/** @brief Convert 16-bit value from network to host byte order.
+ *
+ * @param x The network byte order value to convert.
+ *
+ * @return Host byte order value.
+ */
+#define ntohs(x) sys_be16_to_cpu(x)
+
+/** @brief Convert 32-bit value from network to host byte order.
+ *
+ * @param x The network byte order value to convert.
+ *
+ * @return Host byte order value.
+ */
+#define ntohl(x) sys_be32_to_cpu(x)
+
+/** @brief Convert 64-bit value from network to host byte order.
+ *
+ * @param x The network byte order value to convert.
+ *
+ * @return Host byte order value.
+ */
+#define ntohll(x) sys_be64_to_cpu(x)
+
+/** @brief Convert 16-bit value from host to network byte order.
+ *
+ * @param x The host byte order value to convert.
+ *
+ * @return Network byte order value.
+ */
+#define htons(x) sys_cpu_to_be16(x)
+
+/** @brief Convert 32-bit value from host to network byte order.
+ *
+ * @param x The host byte order value to convert.
+ *
+ * @return Network byte order value.
+ */
+#define htonl(x) sys_cpu_to_be32(x)
+
+/** @brief Convert 64-bit value from host to network byte order.
+ *
+ * @param x The host byte order value to convert.
+ *
+ * @return Network byte order value.
+ */
+#define htonll(x) sys_cpu_to_be64(x)
+
+/** IPv6 address struct */
+struct in6_addr {
+	union {
+		uint8_t s6_addr[16];
+		uint16_t s6_addr16[8]; /* In big endian */
+		uint32_t s6_addr32[4]; /* In big endian */
+	};
+};
+
+/** IPv4 address struct */
+struct in_addr {
+	union {
+		uint8_t s4_addr[4];
+		uint16_t s4_addr16[2]; /* In big endian */
+		uint32_t s4_addr32[1]; /* In big endian */
+		uint32_t s_addr; /* In big endian, for POSIX compatibility. */
+	};
+};
+
+/** Socket address family type */
+typedef unsigned short int sa_family_t;
+
+/** Length of a socket address */
+typedef size_t socklen_t;
+
+/*
+ * Note that the sin_port and sin6_port are in network byte order
+ * in various sockaddr* structs.
+ */
+
+/** Socket address struct for IPv6. */
+struct sockaddr_in6 {
+	sa_family_t		sin6_family;   /* AF_INET6               */
+	uint16_t		sin6_port;     /* Port number            */
+	struct in6_addr		sin6_addr;     /* IPv6 address           */
+	uint8_t			sin6_scope_id; /* interfaces for a scope */
+};
+
+struct sockaddr_in6_ptr {
+	sa_family_t		sin6_family;   /* AF_INET6               */
+	uint16_t		sin6_port;     /* Port number            */
+	struct in6_addr		*sin6_addr;    /* IPv6 address           */
+	uint8_t			sin6_scope_id; /* interfaces for a scope */
+};
+
+/** Socket address struct for IPv4. */
+struct sockaddr_in {
+	sa_family_t		sin_family;    /* AF_INET      */
+	uint16_t		sin_port;      /* Port number  */
+	struct in_addr		sin_addr;      /* IPv4 address */
+};
+
+struct sockaddr_in_ptr {
+	sa_family_t		sin_family;    /* AF_INET      */
+	uint16_t		sin_port;      /* Port number  */
+	struct in_addr		*sin_addr;     /* IPv4 address */
+};
+
+/** Socket address struct for packet socket. */
+struct sockaddr_ll {
+	sa_family_t sll_family;   /* Always AF_PACKET        */
+	uint16_t    sll_protocol; /* Physical-layer protocol */
+	int         sll_ifindex;  /* Interface number        */
+	uint16_t    sll_hatype;   /* ARP hardware type       */
+	uint8_t     sll_pkttype;  /* Packet type             */
+	uint8_t     sll_halen;    /* Length of address       */
+	uint8_t     sll_addr[8];  /* Physical-layer address  */
+};
+
+struct sockaddr_ll_ptr {
+	sa_family_t sll_family;   /* Always AF_PACKET        */
+	uint16_t    sll_protocol; /* Physical-layer protocol */
+	int         sll_ifindex;  /* Interface number        */
+	uint16_t    sll_hatype;   /* ARP hardware type       */
+	uint8_t     sll_pkttype;  /* Packet type             */
+	uint8_t     sll_halen;    /* Length of address       */
+	uint8_t     *sll_addr;    /* Physical-layer address  */
+};
+
+struct sockaddr_can_ptr {
+	sa_family_t can_family;
+	int         can_ifindex;
+};
+
+#if !defined(HAVE_IOVEC)
+struct iovec {
+	void  *iov_base;
+	size_t iov_len;
+};
+#endif
+
+struct msghdr {
+	void         *msg_name;       /* optional socket address */
+	socklen_t     msg_namelen;    /* size of socket address */
+	struct iovec *msg_iov;        /* scatter/gather array */
+	size_t        msg_iovlen;     /* number of elements in msg_iov */
+	void         *msg_control;    /* ancillary data */
+	size_t        msg_controllen; /* ancillary data buffer len */
+	int           msg_flags;      /* flags on received message */
+};
+
+struct cmsghdr {
+	socklen_t cmsg_len;    /* Number of bytes, including header */
+	int       cmsg_level;  /* Originating protocol */
+	int       cmsg_type;   /* Protocol-specific type */
+	/* Followed by unsigned char cmsg_data[]; */
+};
+
+/* Alignment for headers and data. These are arch specific but define
+ * them here atm if not found alredy.
+ */
+#if !defined(ALIGN_H)
+#define ALIGN_H(x) WB_UP(x)
+#endif
+#if !defined(ALIGN_D)
+#define ALIGN_D(x) WB_UP(x)
+#endif
+
+#if !defined(CMSG_FIRSTHDR)
+#define CMSG_FIRSTHDR(msghdr)					\
+	((msghdr)->msg_controllen >= sizeof(struct cmsghdr) ?	\
+	 (struct cmsghdr *)((msghdr)->msg_control) : NULL)
+#endif
+
+#if !defined(CMSG_NXTHDR)
+#define CMSG_NXTHDR(msghdr, cmsg)					 \
+	(((cmsg) == NULL) ? CMSG_FIRSTHDR(msghdr) :			 \
+	 (((uint8_t *)(cmsg) + ALIGN_H((cmsg)->cmsg_len) +		 \
+	   ALIGN_D(sizeof(struct cmsghdr)) >				 \
+	   (uint8_t *)((msghdr)->msg_control) + (msghdr)->msg_controllen) ? \
+	  NULL :							 \
+	  (struct cmsghdr *)((uint8_t *)(cmsg) +			 \
+			     ALIGN_H((cmsg)->cmsg_len))))
+#endif
+
+#if !defined(CMSG_DATA)
+#define CMSG_DATA(cmsg) ((uint8_t *)(cmsg) + ALIGN_D(sizeof(struct cmsghdr)))
+#endif
+
+#if !defined(CMSG_SPACE)
+#define CMSG_SPACE(length) (ALIGN_D(sizeof(struct cmsghdr)) + ALIGN_H(length))
+#endif
+
+#if !defined(CMSG_LEN)
+#define CMSG_LEN(length) (ALIGN_D(sizeof(struct cmsghdr)) + length)
+#endif
+
+/** @cond INTERNAL_HIDDEN */
+
+/* Packet types.  */
+#define PACKET_HOST         0     /* To us            */
+#define PACKET_BROADCAST    1     /* To all           */
+#define PACKET_MULTICAST    2     /* To group         */
+#define PACKET_OTHERHOST    3     /* To someone else  */
+#define PACKET_OUTGOING     4     /* Originated by us */
+#define PACKET_LOOPBACK     5
+#define PACKET_FASTROUTE    6
+
+/* Note: These macros are defined in a specific order.
+ * The largest sockaddr size is the last one.
+ */
+#if defined(CONFIG_NET_IPV4)
+#undef NET_SOCKADDR_MAX_SIZE
+#undef NET_SOCKADDR_PTR_MAX_SIZE
+#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in))
+#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in_ptr))
+#endif
+
+#if defined(CONFIG_NET_SOCKETS_PACKET)
+#undef NET_SOCKADDR_MAX_SIZE
+#undef NET_SOCKADDR_PTR_MAX_SIZE
+#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_ll))
+#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_ll_ptr))
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+#undef NET_SOCKADDR_MAX_SIZE
+#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
+#if !defined(CONFIG_NET_SOCKETS_PACKET)
+#undef NET_SOCKADDR_PTR_MAX_SIZE
+#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
+#endif
+#endif
+
+#if !defined(CONFIG_NET_IPV4)
+#if !defined(CONFIG_NET_IPV6)
+#if !defined(CONFIG_NET_SOCKETS_PACKET)
+#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
+#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
+#endif
+#endif
+#endif
+
+/** @endcond */
+
+/** Generic sockaddr struct. Must be cast to proper type. */
+struct sockaddr {
+	sa_family_t sa_family;
+	char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
+};
+
+/** @cond INTERNAL_HIDDEN */
+
+struct sockaddr_ptr {
+	sa_family_t family;
+	char data[NET_SOCKADDR_PTR_MAX_SIZE - sizeof(sa_family_t)];
+};
+
+/* Same as sockaddr in our case */
+struct sockaddr_storage {
+	sa_family_t ss_family;
+	char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
+};
+
+/* Socket address struct for UNIX domain sockets */
+struct sockaddr_un {
+	sa_family_t sun_family;    /* AF_UNIX */
+	char        sun_path[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
+};
+
+struct net_addr {
+	sa_family_t family;
+	union {
+		struct in6_addr in6_addr;
+		struct in_addr in_addr;
+	};
+};
+
+#define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+				0, 0, 0, 0, 0, 0, 0 } } }
+#define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \
+				0, 0, 0, 0, 0, 0, 0, 0, 1 } } }
+
+extern const struct in6_addr in6addr_any;
+extern const struct in6_addr in6addr_loopback;
+
+/** @endcond */
+
+/** Max length of the IPv4 address as a string. Defined by POSIX. */
+#define INET_ADDRSTRLEN 16
+/** Max length of the IPv6 address as a string. Takes into account possible
+ * mapped IPv4 addresses.
+ */
+#define INET6_ADDRSTRLEN 46
+
+/** @cond INTERNAL_HIDDEN */
+
+/* These are for internal usage of the stack */
+#define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
+#define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx")
+
+#define INADDR_ANY 0
+#define INADDR_ANY_INIT { { { INADDR_ANY } } }
+
+/** @endcond */
+
+enum net_ip_mtu {
+	/** IPv6 MTU length. We must be able to receive this size IPv6 packet
+	 * without fragmentation.
+	 */
+	NET_IPV6_MTU = 1280,
+
+	/** IPv4 MTU length. We must be able to receive this size IPv4 packet
+	 * without fragmentation.
+	 */
+	NET_IPV4_MTU = 576,
+};
+
+/** Network packet priority settings described in IEEE 802.1Q Annex I.1 */
+enum net_priority {
+	NET_PRIORITY_BK = 1, /**< Background (lowest)                */
+	NET_PRIORITY_BE = 0, /**< Best effort (default)              */
+	NET_PRIORITY_EE = 2, /**< Excellent effort                   */
+	NET_PRIORITY_CA = 3, /**< Critical applications (highest)    */
+	NET_PRIORITY_VI = 4, /**< Video, < 100 ms latency and jitter */
+	NET_PRIORITY_VO = 5, /**< Voice, < 10 ms latency and jitter  */
+	NET_PRIORITY_IC = 6, /**< Internetwork control               */
+	NET_PRIORITY_NC = 7  /**< Network control                    */
+} __packed;
+
+/** IPv6/IPv4 network connection tuple */
+struct net_tuple {
+	struct net_addr *remote_addr;  /**< IPv6/IPv4 remote address */
+	struct net_addr *local_addr;   /**< IPv6/IPv4 local address  */
+	uint16_t remote_port;          /**< UDP/TCP remote port      */
+	uint16_t local_port;           /**< UDP/TCP local port       */
+	enum net_ip_protocol ip_proto; /**< IP protocol              */
+};
+
+/** What is the current state of the network address */
+enum net_addr_state {
+	NET_ADDR_ANY_STATE = -1, /**< Default (invalid) address type */
+	NET_ADDR_TENTATIVE = 0,  /**< Tentative address              */
+	NET_ADDR_PREFERRED,      /**< Preferred address              */
+	NET_ADDR_DEPRECATED,     /**< Deprecated address             */
+} __packed;
+
+/** How the network address is assigned to network interface */
+enum net_addr_type {
+	/** Default value. This is not a valid value. */
+	NET_ADDR_ANY = 0,
+	/** Auto configured address */
+	NET_ADDR_AUTOCONF,
+	/** Address is from DHCP */
+	NET_ADDR_DHCP,
+	/** Manually set address */
+	NET_ADDR_MANUAL,
+	/** Manually set address which is overridable by DHCP */
+	NET_ADDR_OVERRIDABLE,
+} __packed;
+
+/** @cond INTERNAL_HIDDEN */
+
+struct net_ipv6_hdr {
+	uint8_t vtc;
+	uint8_t tcflow;
+	uint16_t flow;
+	uint16_t len;
+	uint8_t nexthdr;
+	uint8_t hop_limit;
+	struct in6_addr src;
+	struct in6_addr dst;
+} __packed;
+
+struct net_ipv6_frag_hdr {
+	uint8_t nexthdr;
+	uint8_t reserved;
+	uint16_t offset;
+	uint32_t id;
+} __packed;
+
+struct net_ipv4_hdr {
+	uint8_t vhl;
+	uint8_t tos;
+	uint16_t len;
+	uint8_t id[2];
+	uint8_t offset[2];
+	uint8_t ttl;
+	uint8_t proto;
+	uint16_t chksum;
+	struct in_addr src;
+	struct in_addr dst;
+} __packed;
+
+struct net_icmp_hdr {
+	uint8_t type;
+	uint8_t code;
+	uint16_t chksum;
+} __packed;
+
+struct net_udp_hdr {
+	uint16_t src_port;
+	uint16_t dst_port;
+	uint16_t len;
+	uint16_t chksum;
+} __packed;
+
+struct net_tcp_hdr {
+	uint16_t src_port;
+	uint16_t dst_port;
+	uint8_t seq[4];
+	uint8_t ack[4];
+	uint8_t offset;
+	uint8_t flags;
+	uint8_t wnd[2];
+	uint16_t chksum;
+	uint8_t urg[2];
+	uint8_t optdata[0];
+} __packed;
+
+static inline const char *net_addr_type2str(enum net_addr_type type)
+{
+	switch (type) {
+	case NET_ADDR_AUTOCONF:
+		return "AUTO";
+	case NET_ADDR_DHCP:
+		return "DHCP";
+	case NET_ADDR_MANUAL:
+		return "MANUAL";
+	case NET_ADDR_OVERRIDABLE:
+		return "OVERRIDE";
+	case NET_ADDR_ANY:
+	default:
+		break;
+	}
+
+	return "<unknown>";
+}
+
+/* IPv6 extension headers types */
+#define NET_IPV6_NEXTHDR_HBHO        0
+#define NET_IPV6_NEXTHDR_DESTO       60
+#define NET_IPV6_NEXTHDR_ROUTING     43
+#define NET_IPV6_NEXTHDR_FRAG        44
+#define NET_IPV6_NEXTHDR_NONE        59
+
+/**
+ * This 2 unions are here temporarily, as long as net_context.h will
+ * be still public and not part of the core only.
+ */
+union net_ip_header {
+	struct net_ipv4_hdr *ipv4;
+	struct net_ipv6_hdr *ipv6;
+};
+
+union net_proto_header {
+	struct net_udp_hdr *udp;
+	struct net_tcp_hdr *tcp;
+};
+
+#define NET_UDPH_LEN	8			/* Size of UDP header */
+#define NET_TCPH_LEN	20			/* Size of TCP header */
+#define NET_ICMPH_LEN	4			/* Size of ICMP header */
+
+#define NET_IPV6H_LEN	   40			/* Size of IPv6 header */
+#define NET_ICMPV6H_LEN	   NET_ICMPH_LEN	/* Size of ICMPv6 header */
+#define NET_IPV6UDPH_LEN   (NET_UDPH_LEN + NET_IPV6H_LEN) /* IPv6 + UDP */
+#define NET_IPV6TCPH_LEN   (NET_TCPH_LEN + NET_IPV6H_LEN) /* IPv6 + TCP */
+#define NET_IPV6ICMPH_LEN  (NET_IPV6H_LEN + NET_ICMPH_LEN) /* ICMPv6 + IPv6 */
+#define NET_IPV6_FRAGH_LEN 8
+
+#define NET_IPV4H_LEN	   20			/* Size of IPv4 header */
+#define NET_ICMPV4H_LEN	   NET_ICMPH_LEN	/* Size of ICMPv4 header */
+#define NET_IPV4UDPH_LEN   (NET_UDPH_LEN + NET_IPV4H_LEN) /* IPv4 + UDP */
+#define NET_IPV4TCPH_LEN   (NET_TCPH_LEN + NET_IPV4H_LEN) /* IPv4 + TCP */
+#define NET_IPV4ICMPH_LEN  (NET_IPV4H_LEN + NET_ICMPH_LEN) /* ICMPv4 + IPv4 */
+
+/** @endcond */
+
+/**
+ * @brief Check if the IPv6 address is a loopback address (::1).
+ *
+ * @param addr IPv6 address
+ *
+ * @return True if address is a loopback address, False otherwise.
+ */
+static inline bool net_ipv6_is_addr_loopback(struct in6_addr *addr)
+{
+	return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
+		UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
+		UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
+		ntohl(UNALIGNED_GET(&addr->s6_addr32[3])) == 1;
+}
+
+/**
+ * @brief Check if the IPv6 address is a multicast address.
+ *
+ * @param addr IPv6 address
+ *
+ * @return True if address is multicast address, False otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast(const struct in6_addr *addr)
+{
+	return addr->s6_addr[0] == 0xFF;
+}
+
+struct net_if;
+struct net_if_config;
+
+extern struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
+						   struct net_if **iface);
+
+/**
+ * @brief Check if IPv6 address is found in one of the network interfaces.
+ *
+ * @param addr IPv6 address
+ *
+ * @return True if address was found, False otherwise.
+ */
+static inline bool net_ipv6_is_my_addr(struct in6_addr *addr)
+{
+	return net_if_ipv6_addr_lookup(addr, NULL) != NULL;
+}
+
+extern struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(
+	const struct in6_addr *addr, struct net_if **iface);
+
+/**
+ * @brief Check if IPv6 multicast address is found in one of the
+ * network interfaces.
+ *
+ * @param maddr Multicast IPv6 address
+ *
+ * @return True if address was found, False otherwise.
+ */
+static inline bool net_ipv6_is_my_maddr(struct in6_addr *maddr)
+{
+	return net_if_ipv6_maddr_lookup(maddr, NULL) != NULL;
+}
+
+/**
+ * @brief Check if two IPv6 addresses are same when compared after prefix mask.
+ *
+ * @param addr1 First IPv6 address.
+ * @param addr2 Second IPv6 address.
+ * @param length Prefix length (max length is 128).
+ *
+ * @return True if IPv6 prefixes are the same, False otherwise.
+ */
+static inline bool net_ipv6_is_prefix(const uint8_t *addr1,
+				      const uint8_t *addr2,
+				      uint8_t length)
+{
+	uint8_t bits = 128 - length;
+	uint8_t bytes = length / 8U;
+	uint8_t remain = bits % 8;
+	uint8_t mask;
+
+	if (length > 128) {
+		return false;
+	}
+
+	if (memcmp(addr1, addr2, bytes)) {
+		return false;
+	}
+
+	if (!remain) {
+		/* No remaining bits, the prefixes are the same as first
+		 * bytes are the same.
+		 */
+		return true;
+	}
+
+	/* Create a mask that has remaining most significant bits set */
+	mask = ((0xff << (8 - remain)) ^ 0xff) << remain;
+
+	return (addr1[bytes] & mask) == (addr2[bytes] & mask);
+}
+
+/**
+ * @brief Check if the IPv4 address is a loopback address (127.0.0.0/8).
+ *
+ * @param addr IPv4 address
+ *
+ * @return True if address is a loopback address, False otherwise.
+ */
+static inline bool net_ipv4_is_addr_loopback(struct in_addr *addr)
+{
+	return addr->s4_addr[0] == 127U;
+}
+
+/**
+ *  @brief Check if the IPv4 address is unspecified (all bits zero)
+ *
+ *  @param addr IPv4 address.
+ *
+ *  @return True if the address is unspecified, false otherwise.
+ */
+static inline bool net_ipv4_is_addr_unspecified(const struct in_addr *addr)
+{
+	return UNALIGNED_GET(&addr->s_addr) == 0;
+}
+
+/**
+ * @brief Check if the IPv4 address is a multicast address.
+ *
+ * @param addr IPv4 address
+ *
+ * @return True if address is multicast address, False otherwise.
+ */
+static inline bool net_ipv4_is_addr_mcast(const struct in_addr *addr)
+{
+	return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xF0000000) == 0xE0000000;
+}
+
+/**
+ * @brief Check if the given IPv4 address is a link local address.
+ *
+ * @param addr A valid pointer on an IPv4 address
+ *
+ * @return True if it is, false otherwise.
+ */
+static inline bool net_ipv4_is_ll_addr(const struct in_addr *addr)
+{
+	return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xA9FE0000) == 0xA9FE0000;
+}
+
+/**
+ *  @def net_ipaddr_copy
+ *  @brief Copy an IPv4 or IPv6 address
+ *
+ *  @param dest Destination IP address.
+ *  @param src Source IP address.
+ *
+ *  @return Destination address.
+ */
+#define net_ipaddr_copy(dest, src) \
+	UNALIGNED_PUT(UNALIGNED_GET(src), dest)
+
+/**
+ *  @brief Compare two IPv4 addresses
+ *
+ *  @param addr1 Pointer to IPv4 address.
+ *  @param addr2 Pointer to IPv4 address.
+ *
+ *  @return True if the addresses are the same, false otherwise.
+ */
+static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
+				     const struct in_addr *addr2)
+{
+	return UNALIGNED_GET(&addr1->s_addr) == UNALIGNED_GET(&addr2->s_addr);
+}
+
+/**
+ *  @brief Compare two IPv6 addresses
+ *
+ *  @param addr1 Pointer to IPv6 address.
+ *  @param addr2 Pointer to IPv6 address.
+ *
+ *  @return True if the addresses are the same, false otherwise.
+ */
+static inline bool net_ipv6_addr_cmp(const struct in6_addr *addr1,
+				     const struct in6_addr *addr2)
+{
+	return !memcmp(addr1, addr2, sizeof(struct in6_addr));
+}
+
+/**
+ * @brief Check if the given IPv6 address is a link local address.
+ *
+ * @param addr A valid pointer on an IPv6 address
+ *
+ * @return True if it is, false otherwise.
+ */
+static inline bool net_ipv6_is_ll_addr(const struct in6_addr *addr)
+{
+	return UNALIGNED_GET(&addr->s6_addr16[0]) == htons(0xFE80);
+}
+
+/**
+ * @brief Return pointer to any (all bits zeros) IPv6 address.
+ *
+ * @return Any IPv6 address.
+ */
+const struct in6_addr *net_ipv6_unspecified_address(void);
+
+/**
+ * @brief Return pointer to any (all bits zeros) IPv4 address.
+ *
+ * @return Any IPv4 address.
+ */
+const struct in_addr *net_ipv4_unspecified_address(void);
+
+/**
+ * @brief Return pointer to broadcast (all bits ones) IPv4 address.
+ *
+ * @return Broadcast IPv4 address.
+ */
+const struct in_addr *net_ipv4_broadcast_address(void);
+
+struct net_if;
+extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
+				      const struct in_addr *addr);
+
+/**
+ * @brief Check if the given address belongs to same subnet that
+ * has been configured for the interface.
+ *
+ * @param iface A valid pointer on an interface
+ * @param addr IPv4 address
+ *
+ * @return True if address is in same subnet, false otherwise.
+ */
+static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
+					  const struct in_addr *addr)
+{
+	return net_if_ipv4_addr_mask_cmp(iface, addr);
+}
+
+extern bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
+				      const struct in_addr *addr);
+
+/**
+ * @brief Check if the given IPv4 address is a broadcast address.
+ *
+ * @param iface Interface to use. Must be a valid pointer to an interface.
+ * @param addr IPv4 address
+ *
+ * @return True if address is a broadcast address, false otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+static inline bool net_ipv4_is_addr_bcast(struct net_if *iface,
+					  const struct in_addr *addr)
+{
+	if (net_ipv4_addr_cmp(addr, net_ipv4_broadcast_address())) {
+		return true;
+	}
+
+	return net_if_ipv4_is_addr_bcast(iface, addr);
+}
+#else
+static inline bool net_ipv4_is_addr_bcast(struct net_if *iface,
+					  const struct in_addr *addr)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(addr);
+
+	return false;
+}
+#endif
+
+extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
+						   struct net_if **iface);
+
+/**
+ * @brief Check if the IPv4 address is assigned to any network interface
+ * in the system.
+ *
+ * @param addr A valid pointer on an IPv4 address
+ *
+ * @return True if IPv4 address is found in one of the network interfaces,
+ * False otherwise.
+ */
+static inline bool net_ipv4_is_my_addr(const struct in_addr *addr)
+{
+	bool ret;
+
+	ret = net_if_ipv4_addr_lookup(addr, NULL) != NULL;
+	if (!ret) {
+		ret = net_ipv4_is_addr_bcast(NULL, addr);
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief Check if the IPv6 address is unspecified (all bits zero)
+ *
+ *  @param addr IPv6 address.
+ *
+ *  @return True if the address is unspecified, false otherwise.
+ */
+static inline bool net_ipv6_is_addr_unspecified(const struct in6_addr *addr)
+{
+	return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
+		UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
+		UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
+		UNALIGNED_GET(&addr->s6_addr32[3]) == 0;
+}
+
+/**
+ *  @brief Check if the IPv6 address is solicited node multicast address
+ *  FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
+ *
+ *  @param addr IPv6 address.
+ *
+ *  @return True if the address is solicited node address, false otherwise.
+ */
+static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr)
+{
+	return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
+		UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
+		UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0x00000001) &&
+		((UNALIGNED_GET(&addr->s6_addr32[3]) & htonl(0xff000000)) ==
+		 htonl(0xff000000));
+}
+
+/**
+ * @brief Check if the IPv6 address is a given scope multicast
+ * address (FFyx::).
+ *
+ * @param addr IPv6 address
+ * @param scope Scope to check
+ *
+ * @return True if the address is in given scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_scope(const struct in6_addr *addr,
+						int scope)
+{
+	return (addr->s6_addr[0] == 0xff) && (addr->s6_addr[1] == scope);
+}
+
+/**
+ * @brief Check if the IPv6 addresses have the same multicast scope (FFyx::).
+ *
+ * @param addr_1 IPv6 address 1
+ * @param addr_2 IPv6 address 2
+ *
+ * @return True if both addresses have same multicast scope,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_same_mcast_scope(const struct in6_addr *addr_1,
+						const struct in6_addr *addr_2)
+{
+	return (addr_1->s6_addr[0] == 0xff) && (addr_2->s6_addr[0] == 0xff) &&
+			(addr_1->s6_addr[1] == addr_2->s6_addr[1]);
+}
+
+/**
+ * @brief Check if the IPv6 address is a global multicast address (FFxE::/16).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is global multicast address, false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_global(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x0e);
+}
+
+/**
+ * @brief Check if the IPv6 address is a interface scope multicast
+ * address (FFx1::).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a interface scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_iface(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x01);
+}
+
+/**
+ * @brief Check if the IPv6 address is a link local scope multicast
+ * address (FFx2::).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a link local scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_link(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x02);
+}
+
+/**
+ * @brief Check if the IPv6 address is a mesh-local scope multicast
+ * address (FFx3::).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a mesh-local scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_mesh(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x03);
+}
+
+/**
+ * @brief Check if the IPv6 address is a site scope multicast
+ * address (FFx5::).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a site scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_site(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x05);
+}
+
+/**
+ * @brief Check if the IPv6 address is an organization scope multicast
+ * address (FFx8::).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is an organization scope multicast address,
+ * false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_org(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_scope(addr, 0x08);
+}
+
+/**
+ * @brief Check if the IPv6 address belongs to certain multicast group
+ *
+ * @param addr IPv6 address.
+ * @param group Group id IPv6 address, the values must be in network
+ * byte order
+ *
+ * @return True if the IPv6 multicast address belongs to given multicast
+ * group, false otherwise.
+ */
+static inline bool net_ipv6_is_addr_mcast_group(const struct in6_addr *addr,
+						const struct in6_addr *group)
+{
+	return UNALIGNED_GET(&addr->s6_addr16[1]) == group->s6_addr16[1] &&
+		UNALIGNED_GET(&addr->s6_addr16[2]) == group->s6_addr16[2] &&
+		UNALIGNED_GET(&addr->s6_addr16[3]) == group->s6_addr16[3] &&
+		UNALIGNED_GET(&addr->s6_addr32[1]) == group->s6_addr32[1] &&
+		UNALIGNED_GET(&addr->s6_addr32[2]) == group->s6_addr32[1] &&
+		UNALIGNED_GET(&addr->s6_addr32[3]) == group->s6_addr32[3];
+}
+
+/**
+ * @brief Check if the IPv6 address belongs to the all nodes multicast group
+ *
+ * @param addr IPv6 address
+ *
+ * @return True if the IPv6 multicast address belongs to the all nodes multicast
+ * group, false otherwise
+ */
+static inline bool
+net_ipv6_is_addr_mcast_all_nodes_group(const struct in6_addr *addr)
+{
+	static const struct in6_addr all_nodes_mcast_group = {
+		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		    0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
+	};
+
+	return net_ipv6_is_addr_mcast_group(addr, &all_nodes_mcast_group);
+}
+
+/**
+ * @brief Check if the IPv6 address is a interface scope all nodes multicast
+ * address (FF01::1).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a interface scope all nodes multicast address,
+ * false otherwise.
+ */
+static inline bool
+net_ipv6_is_addr_mcast_iface_all_nodes(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_iface(addr) &&
+	       net_ipv6_is_addr_mcast_all_nodes_group(addr);
+}
+
+/**
+ * @brief Check if the IPv6 address is a link local scope all nodes multicast
+ * address (FF02::1).
+ *
+ * @param addr IPv6 address.
+ *
+ * @return True if the address is a link local scope all nodes multicast
+ * address, false otherwise.
+ */
+static inline bool
+net_ipv6_is_addr_mcast_link_all_nodes(const struct in6_addr *addr)
+{
+	return net_ipv6_is_addr_mcast_link(addr) &&
+	       net_ipv6_is_addr_mcast_all_nodes_group(addr);
+}
+
+/**
+ *  @brief Create solicited node IPv6 multicast address
+ *  FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
+ *
+ *  @param src IPv6 address.
+ *  @param dst IPv6 address.
+ */
+static inline
+void net_ipv6_addr_create_solicited_node(const struct in6_addr *src,
+					 struct in6_addr *dst)
+{
+	dst->s6_addr[0]   = 0xFF;
+	dst->s6_addr[1]   = 0x02;
+	UNALIGNED_PUT(0, &dst->s6_addr16[1]);
+	UNALIGNED_PUT(0, &dst->s6_addr16[2]);
+	UNALIGNED_PUT(0, &dst->s6_addr16[3]);
+	UNALIGNED_PUT(0, &dst->s6_addr16[4]);
+	dst->s6_addr[10]  = 0U;
+	dst->s6_addr[11]  = 0x01;
+	dst->s6_addr[12]  = 0xFF;
+	dst->s6_addr[13]  = src->s6_addr[13];
+	UNALIGNED_PUT(UNALIGNED_GET(&src->s6_addr16[7]), &dst->s6_addr16[7]);
+}
+
+/** @brief Construct an IPv6 address from eight 16-bit words.
+ *
+ *  @param addr IPv6 address
+ *  @param addr0 16-bit word which is part of the address
+ *  @param addr1 16-bit word which is part of the address
+ *  @param addr2 16-bit word which is part of the address
+ *  @param addr3 16-bit word which is part of the address
+ *  @param addr4 16-bit word which is part of the address
+ *  @param addr5 16-bit word which is part of the address
+ *  @param addr6 16-bit word which is part of the address
+ *  @param addr7 16-bit word which is part of the address
+ */
+static inline void net_ipv6_addr_create(struct in6_addr *addr,
+					uint16_t addr0, uint16_t addr1,
+					uint16_t addr2, uint16_t addr3,
+					uint16_t addr4, uint16_t addr5,
+					uint16_t addr6, uint16_t addr7)
+{
+	UNALIGNED_PUT(htons(addr0), &addr->s6_addr16[0]);
+	UNALIGNED_PUT(htons(addr1), &addr->s6_addr16[1]);
+	UNALIGNED_PUT(htons(addr2), &addr->s6_addr16[2]);
+	UNALIGNED_PUT(htons(addr3), &addr->s6_addr16[3]);
+	UNALIGNED_PUT(htons(addr4), &addr->s6_addr16[4]);
+	UNALIGNED_PUT(htons(addr5), &addr->s6_addr16[5]);
+	UNALIGNED_PUT(htons(addr6), &addr->s6_addr16[6]);
+	UNALIGNED_PUT(htons(addr7), &addr->s6_addr16[7]);
+}
+
+/**
+ *  @brief Create link local allnodes multicast IPv6 address
+ *
+ *  @param addr IPv6 address
+ */
+static inline void net_ipv6_addr_create_ll_allnodes_mcast(struct in6_addr *addr)
+{
+	net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
+}
+
+/**
+ *  @brief Create link local allrouters multicast IPv6 address
+ *
+ *  @param addr IPv6 address
+ */
+static inline void net_ipv6_addr_create_ll_allrouters_mcast(struct in6_addr *addr)
+{
+	net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0002);
+}
+
+/**
+ *  @brief Create IPv6 address interface identifier
+ *
+ *  @param addr IPv6 address
+ *  @param lladdr Link local address
+ */
+static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
+					    struct net_linkaddr *lladdr)
+{
+	addr->s6_addr[0] = 0xfe;
+	addr->s6_addr[1] = 0x80;
+	UNALIGNED_PUT(0, &addr->s6_addr16[1]);
+	UNALIGNED_PUT(0, &addr->s6_addr32[1]);
+
+	switch (lladdr->len) {
+	case 2:
+		/* The generated IPv6 shall not toggle the
+		 * Universal/Local bit. RFC 6282 ch 3.2.2
+		 */
+		if (lladdr->type == NET_LINK_IEEE802154 ||
+		    lladdr->type == NET_LINK_CANBUS) {
+			UNALIGNED_PUT(0, &addr->s6_addr32[2]);
+			addr->s6_addr[11] = 0xff;
+			addr->s6_addr[12] = 0xfe;
+			addr->s6_addr[13] = 0U;
+			addr->s6_addr[14] = lladdr->addr[0];
+			addr->s6_addr[15] = lladdr->addr[1];
+		}
+
+		break;
+	case 6:
+		/* We do not toggle the Universal/Local bit
+		 * in Bluetooth. See RFC 7668 ch 3.2.2
+		 */
+		memcpy(&addr->s6_addr[8], lladdr->addr, 3);
+		addr->s6_addr[11] = 0xff;
+		addr->s6_addr[12] = 0xfe;
+		memcpy(&addr->s6_addr[13], lladdr->addr + 3, 3);
+
+#if defined(CONFIG_NET_L2_BT_ZEP1656)
+		/* Workaround against older Linux kernel BT IPSP code.
+		 * This will be removed eventually.
+		 */
+		if (lladdr->type == NET_LINK_BLUETOOTH) {
+			addr->s6_addr[8] ^= 0x02;
+		}
+#endif
+
+		if (lladdr->type == NET_LINK_ETHERNET) {
+			addr->s6_addr[8] ^= 0x02;
+		}
+
+		break;
+	case 8:
+		memcpy(&addr->s6_addr[8], lladdr->addr, lladdr->len);
+		addr->s6_addr[8] ^= 0x02;
+		break;
+	}
+}
+
+/**
+ *  @brief Check if given address is based on link layer address
+ *
+ *  @return True if it is, False otherwise
+ */
+static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
+					     const struct net_linkaddr *lladdr)
+{
+	if (!addr || !lladdr) {
+		return false;
+	}
+
+	switch (lladdr->len) {
+	case 2:
+		if (!memcmp(&addr->s6_addr[14], lladdr->addr, lladdr->len) &&
+		    addr->s6_addr[8]  == 0U &&
+		    addr->s6_addr[9]  == 0U &&
+		    addr->s6_addr[10] == 0U &&
+		    addr->s6_addr[11] == 0xff &&
+		    addr->s6_addr[12] == 0xfe) {
+			return true;
+		}
+
+		break;
+	case 6:
+		if (lladdr->type == NET_LINK_ETHERNET) {
+			if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
+			    !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
+			    addr->s6_addr[11] == 0xff &&
+			    addr->s6_addr[12] == 0xfe &&
+			    (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
+				return true;
+			}
+		} else if (lladdr->type == NET_LINK_BLUETOOTH) {
+			if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
+			    !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
+			    addr->s6_addr[11] == 0xff &&
+			    addr->s6_addr[12] == 0xfe
+#if defined(CONFIG_NET_L2_BT_ZEP1656)
+			    /* Workaround against older Linux kernel BT IPSP
+			     * code. This will be removed eventually.
+			     */
+			    && (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]
+#endif
+			    ) {
+				return true;
+			}
+		}
+
+		break;
+	case 8:
+		if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1],
+			    lladdr->len - 1) &&
+		    (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
+			return true;
+		}
+
+		break;
+	}
+
+	return false;
+}
+
+/**
+ * @brief Get sockaddr_in6 from sockaddr. This is a helper so that
+ * the code calling this function can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to IPv6 socket address
+ */
+static inline struct sockaddr_in6 *net_sin6(const struct sockaddr *addr)
+{
+	return (struct sockaddr_in6 *)addr;
+}
+
+/**
+ * @brief Get sockaddr_in from sockaddr. This is a helper so that
+ * the code calling this function can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to IPv4 socket address
+ */
+static inline struct sockaddr_in *net_sin(const struct sockaddr *addr)
+{
+	return (struct sockaddr_in *)addr;
+}
+
+/**
+ * @brief Get sockaddr_in6_ptr from sockaddr_ptr. This is a helper so that
+ * the code calling this function can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to IPv6 socket address
+ */
+static inline
+struct sockaddr_in6_ptr *net_sin6_ptr(const struct sockaddr_ptr *addr)
+{
+	return (struct sockaddr_in6_ptr *)addr;
+}
+
+/**
+ * @brief Get sockaddr_in_ptr from sockaddr_ptr. This is a helper so that
+ * the code calling this function can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to IPv4 socket address
+ */
+static inline
+struct sockaddr_in_ptr *net_sin_ptr(const struct sockaddr_ptr *addr)
+{
+	return (struct sockaddr_in_ptr *)addr;
+}
+
+/**
+ * @brief Get sockaddr_ll_ptr from sockaddr_ptr. This is a helper so that
+ * the code calling this function can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to linklayer socket address
+ */
+static inline
+struct sockaddr_ll_ptr *net_sll_ptr(const struct sockaddr_ptr *addr)
+{
+	return (struct sockaddr_ll_ptr *)addr;
+}
+
+/**
+ * @brief Get sockaddr_can_ptr from sockaddr_ptr. This is a helper so that
+ * the code needing this functionality can be made shorter.
+ *
+ * @param addr Socket address
+ *
+ * @return Pointer to CAN socket address
+ */
+static inline
+struct sockaddr_can_ptr *net_can_ptr(const struct sockaddr_ptr *addr)
+{
+	return (struct sockaddr_can_ptr *)addr;
+}
+
+/**
+ * @brief Convert a string to IP address.
+ *
+ * @param family IP address family (AF_INET or AF_INET6)
+ * @param src IP address in a null terminated string
+ * @param dst Pointer to struct in_addr if family is AF_INET or
+ * pointer to struct in6_addr if family is AF_INET6
+ *
+ * @note This function doesn't do precise error checking,
+ * do not use for untrusted strings.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+__syscall int net_addr_pton(sa_family_t family, const char *src, void *dst);
+
+/**
+ * @brief Convert IP address to string form.
+ *
+ * @param family IP address family (AF_INET or AF_INET6)
+ * @param src Pointer to struct in_addr if family is AF_INET or
+ *        pointer to struct in6_addr if family is AF_INET6
+ * @param dst Buffer for IP address as a null terminated string
+ * @param size Number of bytes available in the buffer
+ *
+ * @return dst pointer if ok, NULL if error
+ */
+__syscall char *net_addr_ntop(sa_family_t family, const void *src,
+			      char *dst, size_t size);
+
+/**
+ * @brief Parse a string that contains either IPv4 or IPv6 address
+ * and optional port, and store the information in user supplied
+ * sockaddr struct.
+ *
+ * @details Syntax of the IP address string:
+ *   192.0.2.1:80
+ *   192.0.2.42
+ *   [2001:db8::1]:8080
+ *   [2001:db8::2]
+ *   2001:db::42
+ * Note that the str_len parameter is used to restrict the amount of
+ * characters that are checked. If the string does not contain port
+ * number, then the port number in sockaddr is not modified.
+ *
+ * @param str String that contains the IP address.
+ * @param str_len Length of the string to be parsed.
+ * @param addr Pointer to user supplied struct sockaddr.
+ *
+ * @return True if parsing could be done, false otherwise.
+ */
+bool net_ipaddr_parse(const char *str, size_t str_len,
+		      struct sockaddr *addr);
+
+/**
+ * @brief Compare TCP sequence numbers.
+ *
+ * @details This function compares TCP sequence numbers,
+ *          accounting for wraparound effects.
+ *
+ * @param seq1 First sequence number
+ * @param seq2 Seconds sequence number
+ *
+ * @return < 0 if seq1 < seq2, 0 if seq1 == seq2, > 0 if seq > seq2
+ */
+static inline int32_t net_tcp_seq_cmp(uint32_t seq1, uint32_t seq2)
+{
+	return (int32_t)(seq1 - seq2);
+}
+
+/**
+ * @brief Check that one TCP sequence number is greater.
+ *
+ * @details This is convenience function on top of net_tcp_seq_cmp().
+ *
+ * @param seq1 First sequence number
+ * @param seq2 Seconds sequence number
+ *
+ * @return True if seq > seq2
+ */
+static inline bool net_tcp_seq_greater(uint32_t seq1, uint32_t seq2)
+{
+	return net_tcp_seq_cmp(seq1, seq2) > 0;
+}
+
+/**
+ * @brief Convert a string of hex values to array of bytes.
+ *
+ * @details The syntax of the string is "ab:02:98:fa:42:01"
+ *
+ * @param buf Pointer to memory where the bytes are written.
+ * @param buf_len Length of the memory area.
+ * @param src String of bytes.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src);
+
+/**
+ * @brief Convert Tx network packet priority to traffic class so we can place
+ * the packet into correct Tx queue.
+ *
+ * @param prio Network priority
+ *
+ * @return Tx traffic class that handles that priority network traffic.
+ */
+int net_tx_priority2tc(enum net_priority prio);
+
+/**
+ * @brief Convert Rx network packet priority to traffic class so we can place
+ * the packet into correct Rx queue.
+ *
+ * @param prio Network priority
+ *
+ * @return Rx traffic class that handles that priority network traffic.
+ */
+int net_rx_priority2tc(enum net_priority prio);
+
+/**
+ * @brief Convert network packet VLAN priority to network packet priority so we
+ * can place the packet into correct queue.
+ *
+ * @param priority VLAN priority
+ *
+ * @return Network priority
+ */
+static inline enum net_priority net_vlan2priority(uint8_t priority)
+{
+	/* Map according to IEEE 802.1Q */
+	static const uint8_t vlan2priority[] = {
+		NET_PRIORITY_BE,
+		NET_PRIORITY_BK,
+		NET_PRIORITY_EE,
+		NET_PRIORITY_CA,
+		NET_PRIORITY_VI,
+		NET_PRIORITY_VO,
+		NET_PRIORITY_IC,
+		NET_PRIORITY_NC
+	};
+
+	if (priority >= ARRAY_SIZE(vlan2priority)) {
+		/* Use Best Effort as the default priority */
+		return NET_PRIORITY_BE;
+	}
+
+	return (enum net_priority)vlan2priority[priority];
+}
+
+/**
+ * @brief Convert network packet priority to network packet VLAN priority.
+ *
+ * @param priority Packet priority
+ *
+ * @return VLAN priority (PCP)
+ */
+static inline uint8_t net_priority2vlan(enum net_priority priority)
+{
+	/* The conversion works both ways */
+	return (uint8_t)net_vlan2priority(priority);
+}
+
+/**
+ * @brief Return network address family value as a string. This is only usable
+ * for debugging.
+ *
+ * @param family Network address family code
+ *
+ * @return Network address family as a string, or NULL if family is unknown.
+ */
+const char *net_family2str(sa_family_t family);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/net_ip.h>
+
+/**
+ * @}
+ */
+
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_IP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_l2.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_l2.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_l2.h	(working copy)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public API for network L2 interface
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_L2_H_
+#define ZEPHYR_INCLUDE_NET_NET_L2_H_
+
+#include <net/buf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network Layer 2 abstraction layer
+ * @defgroup net_l2 Network L2 Abstraction Layer
+ * @ingroup networking
+ * @{
+ */
+
+struct net_if;
+
+/** L2 flags */
+enum net_l2_flags {
+	/** IP multicast supported */
+	NET_L2_MULTICAST			= BIT(0),
+
+	/** Do not joint solicited node multicast group */
+	NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE	= BIT(1),
+
+	/** Is promiscuous mode supported */
+	NET_L2_PROMISC_MODE			= BIT(2),
+
+	/** Is this L2 point-to-point with tunneling so no need to have
+	 * IP address etc to network interface.
+	 */
+	NET_L2_POINT_TO_POINT			= BIT(3),
+} __packed;
+
+/**
+ * @brief Network L2 structure
+ *
+ * Used to provide an interface to lower network stack.
+ */
+struct net_l2 {
+	/**
+	 * This function is used by net core to get iface's L2 layer parsing
+	 * what's relevant to itself.
+	 */
+	enum net_verdict (*recv)(struct net_if *iface, struct net_pkt *pkt);
+
+	/**
+	 * This function is used by net core to push a packet to lower layer
+	 * (interface's L2), which in turn might work on the packet relevantly.
+	 * (adding proper header etc...)
+	 * Returns a negative error code, or the number of bytes sent otherwise.
+	 */
+	int (*send)(struct net_if *iface, struct net_pkt *pkt);
+
+	/**
+	 * This function is used to enable/disable traffic over a network
+	 * interface. The function returns <0 if error and >=0 if no error.
+	 */
+	int (*enable)(struct net_if *iface, bool state);
+
+	/**
+	 * Return L2 flags for the network interface.
+	 */
+	enum net_l2_flags (*get_flags)(struct net_if *iface);
+};
+
+/** @cond INTERNAL_HIDDEN */
+#define NET_L2_GET_NAME(_name) _net_l2_##_name
+#define NET_L2_DECLARE_PUBLIC(_name)					\
+	extern const struct net_l2 NET_L2_GET_NAME(_name)
+#define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE
+
+#ifdef CONFIG_NET_L2_DUMMY
+#define DUMMY_L2		DUMMY
+#define DUMMY_L2_CTX_TYPE	void*
+NET_L2_DECLARE_PUBLIC(DUMMY_L2);
+#endif /* CONFIG_NET_L2_DUMMY */
+
+#ifdef CONFIG_NET_L2_ETHERNET
+#define ETHERNET_L2		ETHERNET
+NET_L2_DECLARE_PUBLIC(ETHERNET_L2);
+#endif /* CONFIG_NET_L2_ETHERNET */
+
+#ifdef CONFIG_NET_L2_PPP
+#define PPP_L2			PPP
+NET_L2_DECLARE_PUBLIC(PPP_L2);
+#endif /* CONFIG_NET_L2_PPP */
+
+#ifdef CONFIG_NET_L2_IEEE802154
+#define IEEE802154_L2		IEEE802154
+NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
+#endif /* CONFIG_NET_L2_IEEE802154 */
+
+#ifdef CONFIG_NET_L2_BT
+#define BLUETOOTH_L2		BLUETOOTH
+#define BLUETOOTH_L2_CTX_TYPE	void*
+NET_L2_DECLARE_PUBLIC(BLUETOOTH_L2);
+#endif /* CONFIG_NET_L2_BT */
+
+#ifdef CONFIG_NET_L2_OPENTHREAD
+#define OPENTHREAD_L2		OPENTHREAD
+NET_L2_DECLARE_PUBLIC(OPENTHREAD_L2);
+#endif /* CONFIG_NET_L2_OPENTHREAD */
+
+#ifdef CONFIG_NET_L2_CANBUS_RAW
+#define CANBUS_RAW_L2		CANBUS_RAW
+#define CANBUS_RAW_L2_CTX_TYPE	void*
+NET_L2_DECLARE_PUBLIC(CANBUS_RAW_L2);
+#endif /* CONFIG_NET_L2_CANBUS_RAW */
+
+#ifdef CONFIG_NET_L2_CANBUS
+#define CANBUS_L2		CANBUS
+NET_L2_DECLARE_PUBLIC(CANBUS_L2);
+#endif /* CONFIG_NET_L2_CANBUS */
+
+#define NET_L2_INIT(_name, _recv_fn, _send_fn, _enable_fn, _get_flags_fn) \
+	const Z_STRUCT_SECTION_ITERABLE(net_l2,				\
+					NET_L2_GET_NAME(_name)) = {	\
+		.recv = (_recv_fn),					\
+		.send = (_send_fn),					\
+		.enable = (_enable_fn),					\
+		.get_flags = (_get_flags_fn),				\
+	}
+
+#define NET_L2_GET_DATA(name, sfx) _net_l2_data_##name##sfx
+
+#define NET_L2_DATA_INIT(name, sfx, ctx_type)				\
+	static ctx_type NET_L2_GET_DATA(name, sfx) __used;
+
+/** @endcond */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_L2_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_linkaddr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_linkaddr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_linkaddr.h	(working copy)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public API for network link address
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_
+#define ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_
+
+#include <zephyr/types.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network link address library
+ * @defgroup net_linkaddr Network Link Address Library
+ * @ingroup networking
+ * @{
+ */
+
+/** Maximum length of the link address */
+#ifdef CONFIG_NET_L2_IEEE802154
+#define NET_LINK_ADDR_MAX_LENGTH 8
+#else
+#ifdef CONFIG_NET_L2_PPP
+#define NET_LINK_ADDR_MAX_LENGTH 8
+#else
+#define NET_LINK_ADDR_MAX_LENGTH 6
+#endif
+#endif
+
+/**
+ * Type of the link address. This indicates the network technology that this
+ * address is used in. Note that in order to save space we store the value
+ * into a uint8_t variable, so please do not introduce any values > 255 in
+ * this enum.
+ */
+enum net_link_type {
+	/** Unknown link address type. */
+	NET_LINK_UNKNOWN = 0,
+	/** IEEE 802.15.4 link address. */
+	NET_LINK_IEEE802154,
+	/** Bluetooth IPSP link address. */
+	NET_LINK_BLUETOOTH,
+	/** Ethernet link address. */
+	NET_LINK_ETHERNET,
+	/** Dummy link address. Used in testing apps and loopback support. */
+	NET_LINK_DUMMY,
+	/** CANBUS link address. */
+	NET_LINK_CANBUS_RAW,
+	/** 6loCAN link address. */
+	NET_LINK_CANBUS,
+} __packed;
+
+/**
+ *  @brief Hardware link address structure
+ *
+ *  Used to hold the link address information
+ */
+struct net_linkaddr {
+	/** The array of byte representing the address */
+	uint8_t *addr;
+
+	/** Length of that address array */
+	uint8_t len;
+
+	/** What kind of address is this for */
+	uint8_t type;
+};
+
+/**
+ *  @brief Hardware link address structure
+ *
+ *  Used to hold the link address information. This variant is needed
+ *  when we have to store the link layer address.
+ *
+ *  Note that you cannot cast this to net_linkaddr as uint8_t * is
+ *  handled differently than uint8_t addr[] and the fields are purposely
+ *  in different order.
+ */
+struct net_linkaddr_storage {
+	/** What kind of address is this for */
+	uint8_t type;
+
+	/** The real length of the ll address. */
+	uint8_t len;
+
+	/** The array of bytes representing the address */
+	uint8_t addr[NET_LINK_ADDR_MAX_LENGTH];
+};
+
+/**
+ * @brief Compare two link layer addresses.
+ *
+ * @param lladdr1 Pointer to a link layer address
+ * @param lladdr2 Pointer to a link layer address
+ *
+ * @return True if the addresses are the same, false otherwise.
+ */
+static inline bool net_linkaddr_cmp(struct net_linkaddr *lladdr1,
+				    struct net_linkaddr *lladdr2)
+{
+	if (!lladdr1 || !lladdr2) {
+		return false;
+	}
+
+	if (lladdr1->len != lladdr2->len) {
+		return false;
+	}
+
+	return !memcmp(lladdr1->addr, lladdr2->addr, lladdr1->len);
+}
+
+/**
+ *
+ * @brief Set the member data of a link layer address storage structure.
+ *
+ * @param lladdr_store The link address storage structure to change.
+ * @param new_addr Array of bytes containing the link address.
+ * @param new_len Length of the link address array.
+ * This value should always be <= NET_LINK_ADDR_MAX_LENGTH.
+ */
+static inline int net_linkaddr_set(struct net_linkaddr_storage *lladdr_store,
+				   uint8_t *new_addr, uint8_t new_len)
+{
+	if (!lladdr_store || !new_addr) {
+		return -EINVAL;
+	}
+
+	if (new_len > NET_LINK_ADDR_MAX_LENGTH) {
+		return -EMSGSIZE;
+	}
+
+	lladdr_store->len = new_len;
+	memcpy(lladdr_store->addr, new_addr, new_len);
+
+	return 0;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_LINKADDR_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_mgmt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_mgmt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_mgmt.h	(working copy)
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Network Management API public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_MGMT_H_
+#define ZEPHYR_INCLUDE_NET_NET_MGMT_H_
+
+#include <sys/__assert.h>
+#include <net/net_core.h>
+#include <net/net_event.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network Management
+ * @defgroup net_mgmt Network Management
+ * @ingroup networking
+ * @{
+ */
+
+struct net_if;
+
+/** @cond INTERNAL_HIDDEN */
+/**
+ * @brief NET MGMT event mask basics, normalizing parts of bit fields
+ */
+#define NET_MGMT_EVENT_MASK		0x80000000
+#define NET_MGMT_ON_IFACE_MASK		0x40000000
+#define NET_MGMT_LAYER_MASK		0x30000000
+#define NET_MGMT_SYNC_EVENT_MASK	0x08000000
+#define NET_MGMT_LAYER_CODE_MASK	0x07FF0000
+#define NET_MGMT_COMMAND_MASK		0x0000FFFF
+
+#define NET_MGMT_EVENT_BIT		BIT(31)
+#define NET_MGMT_IFACE_BIT		BIT(30)
+#define NET_MGMT_SYNC_EVENT_BIT		BIT(27)
+
+#define NET_MGMT_LAYER(_layer)		(_layer << 28)
+#define NET_MGMT_LAYER_CODE(_code)	(_code << 16)
+
+#define NET_MGMT_EVENT(mgmt_request)		\
+	(mgmt_request & NET_MGMT_EVENT_MASK)
+
+#define NET_MGMT_ON_IFACE(mgmt_request)		\
+	(mgmt_request & NET_MGMT_ON_IFACE_MASK)
+
+#define NET_MGMT_EVENT_SYNCHRONOUS(mgmt_request)	\
+	(mgmt_request & NET_MGMT_SYNC_EVENT_MASK)
+
+#define NET_MGMT_GET_LAYER(mgmt_request)	\
+	((mgmt_request & NET_MGMT_LAYER_MASK) >> 28)
+
+#define NET_MGMT_GET_LAYER_CODE(mgmt_request)	\
+	((mgmt_request & NET_MGMT_LAYER_CODE_MASK) >> 16)
+
+#define NET_MGMT_GET_COMMAND(mgmt_request)	\
+	(mgmt_request & NET_MGMT_COMMAND_MASK)
+
+
+/* Useful generic definitions */
+#define NET_MGMT_LAYER_L2		1
+#define NET_MGMT_LAYER_L3		2
+#define NET_MGMT_LAYER_L4		3
+
+/** @endcond */
+
+
+/**
+ * @typedef net_mgmt_request_handler_t
+ * @brief Signature which all Net MGMT request handler need to follow
+ * @param mgmt_request The exact request value the handler is being called
+ *        through
+ * @param iface A valid pointer on struct net_if if the request is meant
+ *        to be tight to a network interface. NULL otherwise.
+ * @param data A valid pointer on a data understood by the handler.
+ *        NULL otherwise.
+ * @param len Length in byte of the memory pointed by data.
+ */
+typedef int (*net_mgmt_request_handler_t)(uint32_t mgmt_request,
+					  struct net_if *iface,
+					  void *data, size_t len);
+
+#define net_mgmt(_mgmt_request, _iface, _data, _len)			\
+	net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len)
+
+#define NET_MGMT_DEFINE_REQUEST_HANDLER(_mgmt_request)			\
+	extern int net_mgmt_##_mgmt_request(uint32_t mgmt_request,	\
+					    struct net_if *iface,	\
+					    void *data, size_t len)
+
+#define NET_MGMT_REGISTER_REQUEST_HANDLER(_mgmt_request, _func)	\
+	FUNC_ALIAS(_func, net_mgmt_##_mgmt_request, int)
+
+struct net_mgmt_event_callback;
+
+/**
+ * @typedef net_mgmt_event_handler_t
+ * @brief Define the user's callback handler function signature
+ * @param "struct net_mgmt_event_callback *cb"
+ *        Original struct net_mgmt_event_callback owning this handler.
+ * @param "uint32_t mgmt_event" The network event being notified.
+ * @param "struct net_if *iface" A pointer on a struct net_if to which the
+ *        the event belongs to, if it's an event on an iface. NULL otherwise.
+ */
+typedef void (*net_mgmt_event_handler_t)(struct net_mgmt_event_callback *cb,
+					 uint32_t mgmt_event,
+					 struct net_if *iface);
+
+/**
+ * @brief Network Management event callback structure
+ * Used to register a callback into the network management event part, in order
+ * to let the owner of this struct to get network event notification based on
+ * given event mask.
+ */
+struct net_mgmt_event_callback {
+	/** Meant to be used internally, to insert the callback into a list.
+	 * So nobody should mess with it.
+	 */
+	sys_snode_t node;
+
+	union {
+		/** Actual callback function being used to notify the owner
+		 */
+		net_mgmt_event_handler_t handler;
+		/** Semaphore meant to be used internaly for the synchronous
+		 * net_mgmt_event_wait() function.
+		 */
+		struct k_sem *sync_call;
+	};
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+	const void *info;
+	size_t info_length;
+#endif
+
+	/** A mask of network events on which the above handler should be
+	 * called in case those events come. Such mask can be modified
+	 * whenever necessary by the owner, and thus will affect the handler
+	 * being called or not.
+	 */
+	union {
+		/** A mask of network events on which the above handler should
+		 * be called in case those events come.
+		 * Note that only the command part is treated as a mask,
+		 * matching one to several commands. Layer and layer code will
+		 * be made of an exact match. This means that in order to
+		 * receive events from multiple layers, one must have multiple
+		 * listeners registered, one for each layer being listened.
+		 */
+		uint32_t event_mask;
+		/** Internal place holder when a synchronous event wait is
+		 * successfully unlocked on a event.
+		 */
+		uint32_t raised_event;
+	};
+};
+
+/**
+ * @brief Helper to initialize a struct net_mgmt_event_callback properly
+ * @param cb A valid application's callback structure pointer.
+ * @param handler A valid handler function pointer.
+ * @param mgmt_event_mask A mask of relevant events for the handler
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+static inline
+void net_mgmt_init_event_callback(struct net_mgmt_event_callback *cb,
+				  net_mgmt_event_handler_t handler,
+				  uint32_t mgmt_event_mask)
+{
+	__ASSERT(cb, "Callback pointer should not be NULL");
+	__ASSERT(handler, "Handler pointer should not be NULL");
+
+	cb->handler = handler;
+	cb->event_mask = mgmt_event_mask;
+};
+#else
+#define net_mgmt_init_event_callback(...)
+#endif
+
+/**
+ * @brief Add a user callback
+ * @param cb A valid pointer on user's callback to add.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+void net_mgmt_add_event_callback(struct net_mgmt_event_callback *cb);
+#else
+#define net_mgmt_add_event_callback(...)
+#endif
+
+/**
+ * @brief Delete a user callback
+ * @param cb A valid pointer on user's callback to delete.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb);
+#else
+#define net_mgmt_del_event_callback(...)
+#endif
+
+/**
+ * @brief Used by the system to notify an event.
+ * @param mgmt_event The actual network event code to notify
+ * @param iface a valid pointer on a struct net_if if only the event is
+ *        based on an iface. NULL otherwise.
+ * @param info a valid pointer on the information you want to pass along
+ *        with the event. NULL otherwise. Note the data pointed there is
+ *        normalized by the related event.
+ * @param length size of the data pointed by info pointer.
+ *
+ * Note: info and length are disabled if CONFIG_NET_MGMT_EVENT_INFO
+ *       is not defined.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+void net_mgmt_event_notify_with_info(uint32_t mgmt_event, struct net_if *iface,
+				     const void *info, size_t length);
+
+static inline void net_mgmt_event_notify(uint32_t mgmt_event,
+					 struct net_if *iface)
+{
+	net_mgmt_event_notify_with_info(mgmt_event, iface, NULL, 0);
+}
+#else
+#define net_mgmt_event_notify(...)
+#define net_mgmt_event_notify_with_info(...)
+#endif
+
+/**
+ * @brief Used to wait synchronously on an event mask
+ * @param mgmt_event_mask A mask of relevant events to wait on.
+ * @param raised_event a pointer on a uint32_t to get which event from
+ *        the mask generated the event. Can be NULL if the caller is not
+ *        interested in that information.
+ * @param iface a pointer on a place holder for the iface on which the
+ *        event has originated from. This is valid if only the event mask
+ *        has bit NET_MGMT_IFACE_BIT set relevantly, depending on events
+ *        the caller wants to listen to.
+ * @param info a valid pointer if user wants to get the information the
+ *        event might bring along. NULL otherwise.
+ * @param info_length tells how long the info memory area is. Only valid if
+ *        the info is not NULL.
+ * @param timeout A timeout delay. K_FOREVER can be used to wait indefinitely.
+ *
+ * @return 0 on success, a negative error code otherwise. -ETIMEDOUT will
+ *         be specifically returned if the timeout kick-in instead of an
+ *         actual event.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+int net_mgmt_event_wait(uint32_t mgmt_event_mask,
+			uint32_t *raised_event,
+			struct net_if **iface,
+			const void **info,
+			size_t *info_length,
+			k_timeout_t timeout);
+#else
+static inline int net_mgmt_event_wait(uint32_t mgmt_event_mask,
+				      uint32_t *raised_event,
+				      struct net_if **iface,
+				      const void **info,
+				      size_t *info_length,
+				      k_timeout_t timeout)
+{
+	return 0;
+}
+#endif
+
+/**
+ * @brief Used to wait synchronously on an event mask for a specific iface
+ * @param iface a pointer on a valid network interface to listen event to
+ * @param mgmt_event_mask A mask of relevant events to wait on. Listened
+ *        to events should be relevant to iface events and thus have the bit
+ *        NET_MGMT_IFACE_BIT set.
+ * @param raised_event a pointer on a uint32_t to get which event from
+ *        the mask generated the event. Can be NULL if the caller is not
+ *        interested in that information.
+ * @param info a valid pointer if user wants to get the information the
+ *        event might bring along. NULL otherwise.
+ * @param info_length tells how long the info memory area is. Only valid if
+ *        the info is not NULL.
+ * @param timeout A timeout delay. K_FOREVER can be used to wait indefinitely.
+ *
+ * @return 0 on success, a negative error code otherwise. -ETIMEDOUT will
+ *         be specifically returned if the timeout kick-in instead of an
+ *         actual event.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+int net_mgmt_event_wait_on_iface(struct net_if *iface,
+				 uint32_t mgmt_event_mask,
+				 uint32_t *raised_event,
+				 const void **info,
+				 size_t *info_length,
+				 k_timeout_t timeout);
+#else
+static inline int net_mgmt_event_wait_on_iface(struct net_if *iface,
+					       uint32_t mgmt_event_mask,
+					       uint32_t *raised_event,
+					       const void **info,
+					       size_t *info_length,
+					       k_timeout_t timeout)
+{
+	return 0;
+}
+#endif
+
+/**
+ * @brief Used by the core of the network stack to initialize the network
+ *        event processing.
+ */
+#ifdef CONFIG_NET_MGMT_EVENT
+void net_mgmt_event_init(void);
+#else
+#define net_mgmt_event_init(...)
+#endif /* CONFIG_NET_MGMT_EVENT */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_MGMT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_offload.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_offload.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_offload.h	(working copy)
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public API for offloading IP stack
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_
+#define ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_
+
+/**
+ * @brief Network offloading interface
+ * @defgroup net_offload Network Offloading Interface
+ * @ingroup networking
+ * @{
+ */
+
+#include <net/buf.h>
+#include <net/net_ip.h>
+#include <net/net_context.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_NET_OFFLOAD)
+
+/** For return parameters and return values of the elements in this
+ * struct, see similarly named functions in net_context.h
+ */
+struct net_offload {
+	/**
+	 * This function is called when the socket is to be opened.
+	 */
+	int (*get)(sa_family_t family,
+		   enum net_sock_type type,
+		   enum net_ip_protocol ip_proto,
+		   struct net_context **context);
+
+	/**
+	 * This function is called when user wants to bind to local IP address.
+	 */
+	int (*bind)(struct net_context *context,
+		    const struct sockaddr *addr,
+		    socklen_t addrlen);
+
+	/**
+	 * This function is called when user wants to mark the socket
+	 * to be a listening one.
+	 */
+	int (*listen)(struct net_context *context, int backlog);
+
+	/**
+	 * This function is called when user wants to create a connection
+	 * to a peer host.
+	 */
+	int (*connect)(struct net_context *context,
+		       const struct sockaddr *addr,
+		       socklen_t addrlen,
+		       net_context_connect_cb_t cb,
+		       int32_t timeout,
+		       void *user_data);
+
+	/**
+	 * This function is called when user wants to accept a connection
+	 * being established.
+	 */
+	int (*accept)(struct net_context *context,
+		      net_tcp_accept_cb_t cb,
+		      int32_t timeout,
+		      void *user_data);
+
+	/**
+	 * This function is called when user wants to send data to peer host.
+	 */
+	int (*send)(struct net_pkt *pkt,
+		    net_context_send_cb_t cb,
+		    int32_t timeout,
+		    void *user_data);
+
+	/**
+	 * This function is called when user wants to send data to peer host.
+	 */
+	int (*sendto)(struct net_pkt *pkt,
+		      const struct sockaddr *dst_addr,
+		      socklen_t addrlen,
+		      net_context_send_cb_t cb,
+		      int32_t timeout,
+		      void *user_data);
+
+	/**
+	 * This function is called when user wants to receive data from peer
+	 * host.
+	 */
+	int (*recv)(struct net_context *context,
+		    net_context_recv_cb_t cb,
+		    int32_t timeout,
+		    void *user_data);
+
+	/**
+	 * This function is called when user wants to close the socket.
+	 */
+	int (*put)(struct net_context *context);
+};
+
+/**
+ * @brief Get a network socket/context from the offloaded IP stack.
+ *
+ * @details Network socket is used to define the connection
+ * 5-tuple (protocol, remote address, remote port, source
+ * address and source port). This is similar as BSD socket()
+ * function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param family IP address family (AF_INET or AF_INET6)
+ * @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
+ * @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
+ * @param context The allocated context is returned to the caller.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_get(struct net_if *iface,
+				  sa_family_t family,
+				  enum net_sock_type type,
+				  enum net_ip_protocol ip_proto,
+				  struct net_context **context)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->get);
+
+	return net_if_offload(iface)->get(family, type, ip_proto, context);
+}
+
+/**
+ * @brief Assign a socket a local address.
+ *
+ * @details This is similar as BSD bind() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param context The context to be assigned.
+ * @param addr Address to assigned.
+ * @param addrlen Length of the address.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_bind(struct net_if *iface,
+				   struct net_context *context,
+				   const struct sockaddr *addr,
+				   socklen_t addrlen)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->bind);
+
+	return net_if_offload(iface)->bind(context, addr, addrlen);
+}
+
+/**
+ * @brief Mark the context as a listening one.
+ *
+ * @details This is similar as BSD listen() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param context The context to use.
+ * @param backlog The size of the pending connections backlog.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_listen(struct net_if *iface,
+				     struct net_context *context,
+				     int backlog)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->listen);
+
+	return net_if_offload(iface)->listen(context, backlog);
+}
+
+/**
+ * @brief            Create a network connection.
+ *
+ * @details          The net_context_connect function creates a network
+ *                   connection to the host specified by addr. After the
+ *                   connection is established, the user-supplied callback (cb)
+ *                   is executed. cb is called even if the timeout was set to
+ *                   K_FOREVER. cb is not called if the timeout expires.
+ *                   For datagram sockets (SOCK_DGRAM), this function only sets
+ *                   the peer address.
+ *                   This function is similar to the BSD connect() function.
+ *
+ * @param iface      Network interface where the offloaded IP stack can be
+ *                   reached.
+ * @param context    The network context.
+ * @param addr       The peer address to connect to.
+ * @param addrlen    Peer address length.
+ * @param cb         Callback function. Set to NULL if not required.
+ * @param timeout    The timeout value for the connection. Possible values:
+ *                   * K_NO_WAIT: this function will return immediately,
+ *                   * K_FOREVER: this function will block until the
+ *                                      connection is established,
+ *                   * >0: this function will wait the specified ms.
+ * @param user_data  Data passed to the callback function.
+ *
+ * @return           0 on success.
+ * @return           -EINVAL if an invalid parameter is passed as an argument.
+ * @return           -ENOTSUP if the operation is not supported or implemented.
+ */
+static inline int net_offload_connect(struct net_if *iface,
+				      struct net_context *context,
+				      const struct sockaddr *addr,
+				      socklen_t addrlen,
+				      net_context_connect_cb_t cb,
+				      k_timeout_t timeout,
+				      void *user_data)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->connect);
+
+	return net_if_offload(iface)->connect(
+		context, addr, addrlen, cb,
+#ifdef CONFIG_LEGACY_TIMEOUT_API
+		Z_TIMEOUT_MS(timeout),
+#else
+		k_ticks_to_ms_floor64(timeout.ticks),
+#endif
+		user_data);
+}
+
+/**
+ * @brief Accept a network connection attempt.
+ *
+ * @details Accept a connection being established. This function
+ * will return immediately if the timeout is set to K_NO_WAIT.
+ * In this case the context will call the supplied callback when ever
+ * there is a connection established to this context. This is "a register
+ * handler and forget" type of call (async).
+ * If the timeout is set to K_FOREVER, the function will wait
+ * until the connection is established. Timeout value > 0, will wait as
+ * many ms.
+ * After the connection is established a caller-supplied callback is called.
+ * The callback is called even if timeout was set to K_FOREVER, the
+ * callback is called before this function will return in this case.
+ * The callback is not called if the timeout expires.
+ * This is similar as BSD accept() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param context The context to use.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Timeout for the connection. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_accept(struct net_if *iface,
+				     struct net_context *context,
+				     net_tcp_accept_cb_t cb,
+				     k_timeout_t timeout,
+				     void *user_data)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->accept);
+
+	return net_if_offload(iface)->accept(
+		context, cb,
+#ifdef CONFIG_LEGACY_TIMEOUT_API
+		Z_TIMEOUT_MS(timeout),
+#else
+		k_ticks_to_ms_floor64(timeout.ticks),
+#endif
+		user_data);
+}
+
+/**
+ * @brief Send a network packet to a peer.
+ *
+ * @details This function can be used to send network data to a peer
+ * connection. This function will return immediately if the timeout
+ * is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
+ * will wait until the network packet is sent. Timeout value > 0 will
+ * wait as many ms. After the network packet is sent,
+ * a caller-supplied callback is called. The callback is called even
+ * if timeout was set to K_FOREVER, the callback is called
+ * before this function will return in this case. The callback is not
+ * called if the timeout expires. For context of type SOCK_DGRAM,
+ * the destination address must have been set by the call to
+ * net_context_connect().
+ * This is similar as BSD send() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param pkt The network packet to send.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Timeout for the connection. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_send(struct net_if *iface,
+				   struct net_pkt *pkt,
+				   net_context_send_cb_t cb,
+				   k_timeout_t timeout,
+				   void *user_data)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->send);
+
+	return net_if_offload(iface)->send(
+		pkt, cb,
+#ifdef CONFIG_LEGACY_TIMEOUT_API
+		Z_TIMEOUT_MS(timeout),
+#else
+		k_ticks_to_ms_floor64(timeout.ticks),
+#endif
+		user_data);
+}
+
+/**
+ * @brief Send a network packet to a peer specified by address.
+ *
+ * @details This function can be used to send network data to a peer
+ * specified by address. This variant can only be used for datagram
+ * connections of type SOCK_DGRAM. This function will return immediately
+ * if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
+ * the function will wait until the network packet is sent. Timeout
+ * value > 0 will wait as many ms. After the network packet
+ * is sent, a caller-supplied callback is called. The callback is called
+ * even if timeout was set to K_FOREVER, the callback is called
+ * before this function will return. The callback is not called if the
+ * timeout expires.
+ * This is similar as BSD sendto() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param pkt The network packet to send.
+ * @param dst_addr Destination address. This will override the address
+ * already set in network packet.
+ * @param addrlen Length of the address.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Timeout for the connection. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_sendto(struct net_if *iface,
+				     struct net_pkt *pkt,
+				     const struct sockaddr *dst_addr,
+				     socklen_t addrlen,
+				     net_context_send_cb_t cb,
+				     k_timeout_t timeout,
+				     void *user_data)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->sendto);
+
+	return net_if_offload(iface)->sendto(
+		pkt, dst_addr, addrlen, cb,
+#ifdef CONFIG_LEGACY_TIMEOUT_API
+		Z_TIMEOUT_MS(timeout),
+#else
+		k_ticks_to_ms_floor64(timeout.ticks),
+#endif
+		user_data);
+}
+
+/**
+ * @brief Receive network data from a peer specified by context.
+ *
+ * @details This function can be used to register a callback function
+ * that is called by the network stack when network data has been received
+ * for this context. As this function registers a callback, then there
+ * is no need to call this function multiple times if timeout is set to
+ * K_NO_WAIT.
+ * If callback function or user data changes, then the function can be called
+ * multiple times to register new values.
+ * This function will return immediately if the timeout is set to K_NO_WAIT.
+ * If the timeout is set to K_FOREVER, the function will wait until the
+ * network packet is received. Timeout value > 0 will wait as many ms.
+ * After the network packet is received, a caller-supplied callback is
+ * called. The callback is called even if timeout was set to K_FOREVER,
+ * the callback is called before this function will return in this case.
+ * The callback is not called if the timeout expires. The timeout functionality
+ * can be compiled out if synchronous behavior is not needed. The sync call
+ * logic requires some memory that can be saved if only async way of call is
+ * used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
+ * value is ignored.
+ * This is similar as BSD recv() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param context The network context to use.
+ * @param cb Caller-supplied callback function.
+ * @param timeout Caller-supplied timeout. Possible values
+ * are K_FOREVER, K_NO_WAIT, >0.
+ * @param user_data Caller-supplied user data.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_recv(struct net_if *iface,
+				   struct net_context *context,
+				   net_context_recv_cb_t cb,
+				   k_timeout_t timeout,
+				   void *user_data)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->recv);
+
+	return net_if_offload(iface)->recv(
+		context, cb,
+#ifdef CONFIG_LEGACY_TIMEOUT_API
+		Z_TIMEOUT_MS(timeout),
+#else
+		k_ticks_to_ms_floor64(timeout.ticks),
+#endif
+		user_data);
+}
+
+/**
+ * @brief Free/close a network context.
+ *
+ * @details This releases the context. It is not possible to
+ * send or receive data via this context after this call.
+ * This is similar as BSD shutdown() function.
+ *
+ * @param iface Network interface where the offloaded IP stack can be
+ * reached.
+ * @param context The context to be closed.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+static inline int net_offload_put(struct net_if *iface,
+				  struct net_context *context)
+{
+	NET_ASSERT(iface);
+	NET_ASSERT(net_if_offload(iface));
+	NET_ASSERT(net_if_offload(iface)->put);
+
+	return net_if_offload(iface)->put(context);
+}
+
+#else
+
+/** @cond INTERNAL_HIDDEN */
+
+static inline int net_offload_get(struct net_if *iface,
+				  sa_family_t family,
+				  enum net_sock_type type,
+				  enum net_ip_protocol ip_proto,
+				  struct net_context **context)
+{
+	return 0;
+}
+
+static inline int net_offload_bind(struct net_if *iface,
+				   struct net_context *context,
+				   const struct sockaddr *addr,
+				   socklen_t addrlen)
+{
+	return 0;
+}
+
+static inline int net_offload_listen(struct net_if *iface,
+				     struct net_context *context,
+				     int backlog)
+{
+	return 0;
+}
+
+static inline int net_offload_connect(struct net_if *iface,
+				      struct net_context *context,
+				      const struct sockaddr *addr,
+				      socklen_t addrlen,
+				      net_context_connect_cb_t cb,
+				      k_timeout_t timeout,
+				      void *user_data)
+{
+	return 0;
+}
+
+static inline int net_offload_accept(struct net_if *iface,
+				     struct net_context *context,
+				     net_tcp_accept_cb_t cb,
+				     k_timeout_t timeout,
+				     void *user_data)
+{
+	return 0;
+}
+
+static inline int net_offload_send(struct net_if *iface,
+				   struct net_pkt *pkt,
+				   net_context_send_cb_t cb,
+				   k_timeout_t timeout,
+				   void *user_data)
+{
+	return 0;
+}
+
+static inline int net_offload_sendto(struct net_if *iface,
+				     struct net_pkt *pkt,
+				     const struct sockaddr *dst_addr,
+				     socklen_t addrlen,
+				     net_context_send_cb_t cb,
+				     k_timeout_t timeout,
+				     void *user_data)
+{
+	return 0;
+}
+
+static inline int net_offload_recv(struct net_if *iface,
+				   struct net_context *context,
+				   net_context_recv_cb_t cb,
+				   k_timeout_t timeout,
+				   void *user_data)
+{
+	return 0;
+}
+
+static inline int net_offload_put(struct net_if *iface,
+				  struct net_context *context)
+{
+	return 0;
+}
+
+/** @endcond */
+
+#endif /* CONFIG_NET_OFFLOAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_pkt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_pkt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_pkt.h	(working copy)
@@ -0,0 +1,1983 @@
+/** @file
+ * @brief Network packet buffer descriptor API
+ *
+ * Network data is passed between different parts of the stack via
+ * net_buf struct.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Data buffer API - used for all data to/from net */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_PKT_H_
+#define ZEPHYR_INCLUDE_NET_NET_PKT_H_
+
+#include <zephyr/types.h>
+#include <stdbool.h>
+
+#include <net/buf.h>
+
+#include <net/net_core.h>
+#include <net/net_linkaddr.h>
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <net/net_context.h>
+#include <net/ethernet_vlan.h>
+#include <net/ptp_time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network packet management library
+ * @defgroup net_pkt Network Packet Library
+ * @ingroup networking
+ * @{
+ */
+
+struct net_context;
+struct canbus_net_isotp_tx_ctx;
+struct canbus_net_isotp_rx_ctx;
+
+
+/* buffer cursor used in net_pkt */
+struct net_pkt_cursor {
+	/** Current net_buf pointer by the cursor */
+	struct net_buf *buf;
+	/** Current position in the data buffer of the net_buf */
+	uint8_t *pos;
+};
+
+/**
+ * @brief Network packet.
+ *
+ * Note that if you add new fields into net_pkt, remember to update
+ * net_pkt_clone() function.
+ */
+struct net_pkt {
+	union {
+		/** Internal variable that is used when packet is sent
+		 * or received.
+		 */
+		struct k_work work;
+		/** Socket layer will queue received net_pkt into a k_fifo.
+		 * Since this happens after consuming net_pkt's k_work on
+		 * RX path, it is then fine to have both attributes sharing
+		 * the same memory area.
+		 */
+		intptr_t sock_recv_fifo;
+	};
+
+	/** Slab pointer from where it belongs to */
+	struct k_mem_slab *slab;
+
+	/** buffer holding the packet */
+	union {
+		struct net_buf *frags;
+		struct net_buf *buffer;
+	};
+
+	/** Internal buffer iterator used for reading/writing */
+	struct net_pkt_cursor cursor;
+
+	/** Network connection context */
+	struct net_context *context;
+
+	/** Network interface */
+	struct net_if *iface;
+
+	/** @cond ignore */
+
+#if defined(CONFIG_NET_ROUTING)
+	struct net_if *orig_iface; /* Original network interface */
+#endif
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP) || \
+				defined(CONFIG_NET_PKT_RXTIME_STATS) ||	\
+				defined(CONFIG_NET_PKT_TXTIME_STATS)
+	struct {
+		/** Timestamp if available. */
+		struct net_ptp_time timestamp;
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
+	defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+		/** Collect extra statistics for net_pkt processing
+		 * from various points in the IP stack. See networking
+		 * documentation where these points are located and how
+		 * to interpret the results.
+		 */
+		struct {
+			uint32_t stat[NET_PKT_DETAIL_STATS_COUNT];
+			int count;
+		} detail;
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
+	  CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+	};
+#endif /* CONFIG_NET_PKT_TIMESTAMP */
+
+#if defined(CONFIG_NET_PKT_TXTIME)
+	/** Network packet TX time in the future (in nanoseconds) */
+	uint64_t txtime;
+#endif /* CONFIG_NET_PKT_TXTIME */
+
+	/** Reference counter */
+	atomic_t atomic_ref;
+
+	/* Filled by layer 2 when network packet is received. */
+	struct net_linkaddr lladdr_src;
+	struct net_linkaddr lladdr_dst;
+
+#if defined(CONFIG_NET_TCP1) || defined(CONFIG_NET_TCP2)
+	union {
+		sys_snode_t sent_list;
+
+		/** Allow placing the packet into sys_slist_t */
+		sys_snode_t next;
+	};
+#endif
+
+	uint8_t ip_hdr_len;	/* pre-filled in order to avoid func call */
+
+	uint8_t overwrite  : 1;	/* Is packet content being overwritten? */
+
+	uint8_t sent_or_eof: 1;	/* For outgoing packet: is this sent or not
+				 * For incoming packet of a socket: last
+				 * packet before EOF
+				 * Used only if defined(CONFIG_NET_TCP)
+				 */
+	union {
+		uint8_t pkt_queued: 1; /* For outgoing packet: is this packet
+				     * queued to be sent but has not reached
+				     * the driver yet.
+				     * Used only if defined(CONFIG_NET_TCP)
+				     */
+		uint8_t gptp_pkt: 1; /* For outgoing packet: is this packet
+				   * a GPTP packet.
+				   * Used only if defined (CONFIG_NET_GPTP)
+				   */
+	};
+
+	uint8_t forwarding : 1;	/* Are we forwarding this pkt
+				 * Used only if defined(CONFIG_NET_ROUTE)
+				 */
+	uint8_t family     : 3;	/* IPv4 vs IPv6 */
+
+	union {
+		uint8_t ipv4_auto_arp_msg : 1; /* Is this pkt IPv4 autoconf ARP
+					     * message. Used only if
+					     * defined(CONFIG_NET_IPV4_AUTO).
+					     * Note: family needs to be
+					     * AF_INET.
+					     */
+		uint8_t lldp_pkt          : 1; /* Is this pkt an LLDP message.
+					     * Used only if
+					     * defined(CONFIG_NET_LLDP).
+					     * Note: family needs to be
+					     * AF_UNSPEC.
+					     */
+		uint8_t ppp_msg           : 1; /* This is a PPP message */
+	};
+
+#if defined(CONFIG_NET_TCP)
+	uint8_t tcp_first_msg     : 1; /* Is this the first time this pkt is
+					* sent, or is this a resend of a TCP
+					* segment.
+					*/
+#endif
+
+	union {
+		/* IPv6 hop limit or IPv4 ttl for this network packet.
+		 * The value is shared between IPv6 and IPv4.
+		 */
+		uint8_t ipv6_hop_limit;
+		uint8_t ipv4_ttl;
+	};
+
+	union {
+#if defined(CONFIG_NET_IPV4)
+		uint8_t ipv4_opts_len; /* Length if IPv4 Header Options */
+#endif
+#if defined(CONFIG_NET_IPV6)
+		uint16_t ipv6_ext_len; /* length of extension headers */
+#endif
+	};
+
+	/** Network packet priority, can be left out in which case packet
+	 * is not prioritised.
+	 */
+	uint8_t priority;
+
+#if defined(CONFIG_NET_VLAN)
+	/* VLAN TCI (Tag Control Information). This contains the Priority
+	 * Code Point (PCP), Drop Eligible Indicator (DEI) and VLAN
+	 * Identifier (VID, called more commonly VLAN tag). This value is
+	 * kept in host byte order.
+	 */
+	uint16_t vlan_tci;
+#endif /* CONFIG_NET_VLAN */
+
+#if defined(CONFIG_NET_IPV6)
+	/* Where is the start of the last header before payload data
+	 * in IPv6 packet. This is offset value from start of the IPv6
+	 * packet. Note that this value should be updated by who ever
+	 * adds IPv6 extension headers to the network packet.
+	 */
+	uint16_t ipv6_prev_hdr_start;
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+	uint16_t ipv6_fragment_offset;	/* Fragment offset of this packet */
+	uint32_t ipv6_fragment_id;	/* Fragment id */
+	uint16_t ipv6_frag_hdr_start;	/* Where starts the fragment header */
+#endif /* CONFIG_NET_IPV6_FRAGMENT */
+
+	uint8_t ipv6_ext_opt_len; /* IPv6 ND option length */
+	uint8_t ipv6_next_hdr;	/* What is the very first next header */
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_IEEE802154)
+	uint8_t ieee802154_rssi; /* Received Signal Strength Indication */
+	uint8_t ieee802154_lqi;  /* Link Quality Indicator */
+	uint8_t ieee802154_ack_fpb : 1; /* Frame Pending Bit was set in the ACK */
+#endif
+#if defined(CONFIG_NET_L2_CANBUS)
+	union {
+		struct canbus_isotp_tx_ctx *canbus_tx_ctx;
+		struct canbus_isotp_rx_ctx *canbus_rx_ctx;
+	};
+#endif
+	/* @endcond */
+};
+
+/** @cond ignore */
+
+static inline struct k_work *net_pkt_work(struct net_pkt *pkt)
+{
+	return &pkt->work;
+}
+
+/* The interface real ll address */
+static inline struct net_linkaddr *net_pkt_lladdr_if(struct net_pkt *pkt)
+{
+	return net_if_get_link_addr(pkt->iface);
+}
+
+static inline struct net_context *net_pkt_context(struct net_pkt *pkt)
+{
+	return pkt->context;
+}
+
+static inline void net_pkt_set_context(struct net_pkt *pkt,
+				       struct net_context *ctx)
+{
+	pkt->context = ctx;
+}
+
+static inline struct net_if *net_pkt_iface(struct net_pkt *pkt)
+{
+	return pkt->iface;
+}
+
+static inline void net_pkt_set_iface(struct net_pkt *pkt, struct net_if *iface)
+{
+	pkt->iface = iface;
+
+	/* If the network interface is set in pkt, then also set the type of
+	 * the network address that is stored in pkt. This is done here so
+	 * that the address type is properly set and is not forgotten.
+	 */
+	if (iface) {
+		pkt->lladdr_src.type = net_if_get_link_addr(iface)->type;
+		pkt->lladdr_dst.type = net_if_get_link_addr(iface)->type;
+	}
+}
+
+static inline struct net_if *net_pkt_orig_iface(struct net_pkt *pkt)
+{
+#if defined(CONFIG_NET_ROUTING)
+	return pkt->orig_iface;
+#else
+	return pkt->iface;
+#endif
+}
+
+static inline void net_pkt_set_orig_iface(struct net_pkt *pkt,
+					  struct net_if *iface)
+{
+#if defined(CONFIG_NET_ROUTING)
+	pkt->orig_iface = iface;
+#endif
+}
+
+static inline uint8_t net_pkt_family(struct net_pkt *pkt)
+{
+	return pkt->family;
+}
+
+static inline void net_pkt_set_family(struct net_pkt *pkt, uint8_t family)
+{
+	pkt->family = family;
+}
+
+static inline bool net_pkt_is_gptp(struct net_pkt *pkt)
+{
+	return !!(pkt->gptp_pkt);
+}
+
+static inline void net_pkt_set_gptp(struct net_pkt *pkt, bool is_gptp)
+{
+	pkt->gptp_pkt = is_gptp;
+}
+
+static inline uint8_t net_pkt_ip_hdr_len(struct net_pkt *pkt)
+{
+	return pkt->ip_hdr_len;
+}
+
+static inline void net_pkt_set_ip_hdr_len(struct net_pkt *pkt, uint8_t len)
+{
+	pkt->ip_hdr_len = len;
+}
+
+static inline uint8_t net_pkt_sent(struct net_pkt *pkt)
+{
+	return pkt->sent_or_eof;
+}
+
+static inline void net_pkt_set_sent(struct net_pkt *pkt, bool sent)
+{
+	pkt->sent_or_eof = sent;
+}
+
+static inline uint8_t net_pkt_queued(struct net_pkt *pkt)
+{
+	return pkt->pkt_queued;
+}
+
+static inline void net_pkt_set_queued(struct net_pkt *pkt, bool send)
+{
+	pkt->pkt_queued = send;
+}
+
+static inline uint8_t net_pkt_tcp_1st_msg(struct net_pkt *pkt)
+{
+#if defined(CONFIG_NET_TCP)
+	return pkt->tcp_first_msg;
+#else
+	return true;
+#endif
+}
+
+static inline void net_pkt_set_tcp_1st_msg(struct net_pkt *pkt, bool is_1st)
+{
+#if defined(CONFIG_NET_TCP)
+	pkt->tcp_first_msg = is_1st;
+#else
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(is_1st);
+#endif
+}
+
+#if defined(CONFIG_NET_SOCKETS)
+static inline uint8_t net_pkt_eof(struct net_pkt *pkt)
+{
+	return pkt->sent_or_eof;
+}
+
+static inline void net_pkt_set_eof(struct net_pkt *pkt, bool eof)
+{
+	pkt->sent_or_eof = eof;
+}
+#endif
+
+#if defined(CONFIG_NET_ROUTE)
+static inline bool net_pkt_forwarding(struct net_pkt *pkt)
+{
+	return pkt->forwarding;
+}
+
+static inline void net_pkt_set_forwarding(struct net_pkt *pkt, bool forward)
+{
+	pkt->forwarding = forward;
+}
+#else
+static inline bool net_pkt_forwarding(struct net_pkt *pkt)
+{
+	return false;
+}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+static inline uint8_t net_pkt_ipv4_ttl(struct net_pkt *pkt)
+{
+	return pkt->ipv4_ttl;
+}
+
+static inline void net_pkt_set_ipv4_ttl(struct net_pkt *pkt,
+					uint8_t ttl)
+{
+	pkt->ipv4_ttl = ttl;
+}
+
+static inline uint8_t net_pkt_ipv4_opts_len(struct net_pkt *pkt)
+{
+	return pkt->ipv4_opts_len;
+}
+
+static inline void net_pkt_set_ipv4_opts_len(struct net_pkt *pkt,
+					     uint8_t opts_len)
+{
+	pkt->ipv4_opts_len = opts_len;
+}
+#else
+static inline uint8_t net_pkt_ipv4_ttl(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv4_ttl(struct net_pkt *pkt,
+					uint8_t ttl)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(ttl);
+}
+
+static inline uint8_t net_pkt_ipv4_opts_len(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+	return 0;
+}
+
+static inline void net_pkt_set_ipv4_opts_len(struct net_pkt *pkt,
+					     uint8_t opts_len)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(opts_len);
+}
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+static inline uint8_t net_pkt_ipv6_ext_opt_len(struct net_pkt *pkt)
+{
+	return pkt->ipv6_ext_opt_len;
+}
+
+static inline void net_pkt_set_ipv6_ext_opt_len(struct net_pkt *pkt,
+						uint8_t len)
+{
+	pkt->ipv6_ext_opt_len = len;
+}
+
+static inline uint8_t net_pkt_ipv6_next_hdr(struct net_pkt *pkt)
+{
+	return pkt->ipv6_next_hdr;
+}
+
+static inline void net_pkt_set_ipv6_next_hdr(struct net_pkt *pkt,
+					     uint8_t next_hdr)
+{
+	pkt->ipv6_next_hdr = next_hdr;
+}
+
+static inline uint16_t net_pkt_ipv6_ext_len(struct net_pkt *pkt)
+{
+	return pkt->ipv6_ext_len;
+}
+
+static inline void net_pkt_set_ipv6_ext_len(struct net_pkt *pkt, uint16_t len)
+{
+	pkt->ipv6_ext_len = len;
+}
+
+static inline uint16_t net_pkt_ipv6_hdr_prev(struct net_pkt *pkt)
+{
+	return pkt->ipv6_prev_hdr_start;
+}
+
+static inline void net_pkt_set_ipv6_hdr_prev(struct net_pkt *pkt,
+					     uint16_t offset)
+{
+	pkt->ipv6_prev_hdr_start = offset;
+}
+
+static inline uint8_t net_pkt_ipv6_hop_limit(struct net_pkt *pkt)
+{
+	return pkt->ipv6_hop_limit;
+}
+
+static inline void net_pkt_set_ipv6_hop_limit(struct net_pkt *pkt,
+					      uint8_t hop_limit)
+{
+	pkt->ipv6_hop_limit = hop_limit;
+}
+#else /* CONFIG_NET_IPV6 */
+static inline uint8_t net_pkt_ipv6_ext_opt_len(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_ext_opt_len(struct net_pkt *pkt,
+						uint8_t len)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(len);
+}
+
+static inline uint8_t net_pkt_ipv6_next_hdr(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_next_hdr(struct net_pkt *pkt,
+					     uint8_t next_hdr)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(next_hdr);
+}
+
+static inline uint16_t net_pkt_ipv6_ext_len(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_ext_len(struct net_pkt *pkt, uint16_t len)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(len);
+}
+
+static inline uint16_t net_pkt_ipv6_hdr_prev(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_hdr_prev(struct net_pkt *pkt,
+					     uint16_t offset)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(offset);
+}
+
+static inline uint8_t net_pkt_ipv6_hop_limit(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_hop_limit(struct net_pkt *pkt,
+					      uint8_t hop_limit)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(hop_limit);
+}
+#endif /* CONFIG_NET_IPV6 */
+
+static inline uint16_t net_pkt_ip_opts_len(struct net_pkt *pkt)
+{
+#if defined(CONFIG_NET_IPV6)
+	return pkt->ipv6_ext_len;
+#elif defined(CONFIG_NET_IPV4)
+	return pkt->ipv4_opts_len;
+#else
+	ARG_UNUSED(pkt);
+
+	return 0;
+#endif
+}
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+static inline uint16_t net_pkt_ipv6_fragment_start(struct net_pkt *pkt)
+{
+	return pkt->ipv6_frag_hdr_start;
+}
+
+static inline void net_pkt_set_ipv6_fragment_start(struct net_pkt *pkt,
+						   uint16_t start)
+{
+	pkt->ipv6_frag_hdr_start = start;
+}
+
+static inline uint16_t net_pkt_ipv6_fragment_offset(struct net_pkt *pkt)
+{
+	return pkt->ipv6_fragment_offset;
+}
+
+static inline void net_pkt_set_ipv6_fragment_offset(struct net_pkt *pkt,
+						    uint16_t offset)
+{
+	pkt->ipv6_fragment_offset = offset;
+}
+
+static inline uint32_t net_pkt_ipv6_fragment_id(struct net_pkt *pkt)
+{
+	return pkt->ipv6_fragment_id;
+}
+
+static inline void net_pkt_set_ipv6_fragment_id(struct net_pkt *pkt,
+						uint32_t id)
+{
+	pkt->ipv6_fragment_id = id;
+}
+#else /* CONFIG_NET_IPV6_FRAGMENT */
+static inline uint16_t net_pkt_ipv6_fragment_start(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_fragment_start(struct net_pkt *pkt,
+						   uint16_t start)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(start);
+}
+
+static inline uint16_t net_pkt_ipv6_fragment_offset(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_fragment_offset(struct net_pkt *pkt,
+						    uint16_t offset)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(offset);
+}
+
+static inline uint32_t net_pkt_ipv6_fragment_id(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_ipv6_fragment_id(struct net_pkt *pkt,
+						uint32_t id)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(id);
+}
+#endif /* CONFIG_NET_IPV6_FRAGMENT */
+
+static inline uint8_t net_pkt_priority(struct net_pkt *pkt)
+{
+	return pkt->priority;
+}
+
+static inline void net_pkt_set_priority(struct net_pkt *pkt,
+					uint8_t priority)
+{
+	pkt->priority = priority;
+}
+
+#if defined(CONFIG_NET_VLAN)
+static inline uint16_t net_pkt_vlan_tag(struct net_pkt *pkt)
+{
+	return net_eth_vlan_get_vid(pkt->vlan_tci);
+}
+
+static inline void net_pkt_set_vlan_tag(struct net_pkt *pkt, uint16_t tag)
+{
+	pkt->vlan_tci = net_eth_vlan_set_vid(pkt->vlan_tci, tag);
+}
+
+static inline uint8_t net_pkt_vlan_priority(struct net_pkt *pkt)
+{
+	return net_eth_vlan_get_pcp(pkt->vlan_tci);
+}
+
+static inline void net_pkt_set_vlan_priority(struct net_pkt *pkt,
+					     uint8_t priority)
+{
+	pkt->vlan_tci = net_eth_vlan_set_pcp(pkt->vlan_tci, priority);
+}
+
+static inline bool net_pkt_vlan_dei(struct net_pkt *pkt)
+{
+	return net_eth_vlan_get_dei(pkt->vlan_tci);
+}
+
+static inline void net_pkt_set_vlan_dei(struct net_pkt *pkt, bool dei)
+{
+	pkt->vlan_tci = net_eth_vlan_set_dei(pkt->vlan_tci, dei);
+}
+
+static inline void net_pkt_set_vlan_tci(struct net_pkt *pkt, uint16_t tci)
+{
+	pkt->vlan_tci = tci;
+}
+
+static inline uint16_t net_pkt_vlan_tci(struct net_pkt *pkt)
+{
+	return pkt->vlan_tci;
+}
+#else
+static inline uint16_t net_pkt_vlan_tag(struct net_pkt *pkt)
+{
+	return NET_VLAN_TAG_UNSPEC;
+}
+
+static inline void net_pkt_set_vlan_tag(struct net_pkt *pkt, uint16_t tag)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(tag);
+}
+
+static inline uint8_t net_pkt_vlan_priority(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+	return 0;
+}
+
+static inline bool net_pkt_vlan_dei(struct net_pkt *pkt)
+{
+	return false;
+}
+
+static inline void net_pkt_set_vlan_dei(struct net_pkt *pkt, bool dei)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(dei);
+}
+
+static inline uint16_t net_pkt_vlan_tci(struct net_pkt *pkt)
+{
+	return NET_VLAN_TAG_UNSPEC; /* assumes priority is 0 */
+}
+
+static inline void net_pkt_set_vlan_tci(struct net_pkt *pkt, uint16_t tci)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(tci);
+}
+#endif
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP)
+static inline struct net_ptp_time *net_pkt_timestamp(struct net_pkt *pkt)
+{
+	return &pkt->timestamp;
+}
+
+static inline void net_pkt_set_timestamp(struct net_pkt *pkt,
+					 struct net_ptp_time *timestamp)
+{
+	pkt->timestamp.second = timestamp->second;
+	pkt->timestamp.nanosecond = timestamp->nanosecond;
+}
+#else
+static inline struct net_ptp_time *net_pkt_timestamp(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return NULL;
+}
+
+static inline void net_pkt_set_timestamp(struct net_pkt *pkt,
+					 struct net_ptp_time *timestamp)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(timestamp);
+}
+#endif /* CONFIG_NET_PKT_TIMESTAMP */
+
+#if defined(CONFIG_NET_PKT_TXTIME)
+static inline uint64_t net_pkt_txtime(struct net_pkt *pkt)
+{
+	return pkt->txtime;
+}
+
+static inline void net_pkt_set_txtime(struct net_pkt *pkt, uint64_t txtime)
+{
+	pkt->txtime = txtime;
+}
+#else
+static inline uint64_t net_pkt_txtime(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_set_txtime(struct net_pkt *pkt, uint64_t txtime)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(txtime);
+}
+#endif /* CONFIG_NET_PKT_TXTIME */
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
+	defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+static inline uint32_t *net_pkt_stats_tick(struct net_pkt *pkt)
+{
+	return pkt->detail.stat;
+}
+
+static inline int net_pkt_stats_tick_count(struct net_pkt *pkt)
+{
+	return pkt->detail.count;
+}
+
+static inline void net_pkt_stats_tick_reset(struct net_pkt *pkt)
+{
+	memset(&pkt->detail, 0, sizeof(pkt->detail));
+}
+
+static ALWAYS_INLINE void net_pkt_set_stats_tick(struct net_pkt *pkt,
+						 uint32_t tick)
+{
+	if (pkt->detail.count >= NET_PKT_DETAIL_STATS_COUNT) {
+		NET_ERR("Detail stats count overflow (%d >= %d)",
+			pkt->detail.count, NET_PKT_DETAIL_STATS_COUNT);
+		return;
+	}
+
+	pkt->detail.stat[pkt->detail.count++] = tick;
+}
+
+#define net_pkt_set_tx_stats_tick(pkt, tick) net_pkt_set_stats_tick(pkt, tick)
+#define net_pkt_set_rx_stats_tick(pkt, tick) net_pkt_set_stats_tick(pkt, tick)
+#else
+static inline uint32_t *net_pkt_stats_tick(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return NULL;
+}
+
+static inline int net_pkt_stats_tick_count(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+
+static inline void net_pkt_stats_tick_reset(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+}
+
+static inline void net_pkt_set_stats_tick(struct net_pkt *pkt, uint32_t tick)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(tick);
+}
+
+#define net_pkt_set_tx_stats_tick(pkt, tick)
+#define net_pkt_set_rx_stats_tick(pkt, tick)
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
+	  CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+static inline size_t net_pkt_get_len(struct net_pkt *pkt)
+{
+	return net_buf_frags_len(pkt->frags);
+}
+
+static inline uint8_t *net_pkt_data(struct net_pkt *pkt)
+{
+	return pkt->frags->data;
+}
+
+static inline uint8_t *net_pkt_ip_data(struct net_pkt *pkt)
+{
+	return pkt->frags->data;
+}
+
+static inline bool net_pkt_is_empty(struct net_pkt *pkt)
+{
+	return !pkt->buffer || !net_pkt_data(pkt) || pkt->buffer->len == 0;
+}
+
+static inline struct net_linkaddr *net_pkt_lladdr_src(struct net_pkt *pkt)
+{
+	return &pkt->lladdr_src;
+}
+
+static inline struct net_linkaddr *net_pkt_lladdr_dst(struct net_pkt *pkt)
+{
+	return &pkt->lladdr_dst;
+}
+
+static inline void net_pkt_lladdr_swap(struct net_pkt *pkt)
+{
+	uint8_t *addr = net_pkt_lladdr_src(pkt)->addr;
+
+	net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_dst(pkt)->addr;
+	net_pkt_lladdr_dst(pkt)->addr = addr;
+}
+
+static inline void net_pkt_lladdr_clear(struct net_pkt *pkt)
+{
+	net_pkt_lladdr_src(pkt)->addr = NULL;
+	net_pkt_lladdr_src(pkt)->len = 0U;
+}
+
+#if defined(CONFIG_IEEE802154) || defined(CONFIG_IEEE802154_RAW_MODE)
+static inline uint8_t net_pkt_ieee802154_rssi(struct net_pkt *pkt)
+{
+	return pkt->ieee802154_rssi;
+}
+
+static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt,
+					       uint8_t rssi)
+{
+	pkt->ieee802154_rssi = rssi;
+}
+
+static inline uint8_t net_pkt_ieee802154_lqi(struct net_pkt *pkt)
+{
+	return pkt->ieee802154_lqi;
+}
+
+static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt,
+					      uint8_t lqi)
+{
+	pkt->ieee802154_lqi = lqi;
+}
+
+static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt)
+{
+	return pkt->ieee802154_ack_fpb;
+}
+
+static inline void net_pkt_set_ieee802154_ack_fpb(struct net_pkt *pkt,
+						  bool fpb)
+{
+	pkt->ieee802154_ack_fpb = fpb;
+}
+#endif
+
+#if defined(CONFIG_NET_IPV4_AUTO)
+static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt)
+{
+	return pkt->ipv4_auto_arp_msg;
+}
+
+static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt,
+					 bool is_auto_arp_msg)
+{
+	pkt->ipv4_auto_arp_msg = is_auto_arp_msg;
+}
+#else /* CONFIG_NET_IPV4_AUTO */
+static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return false;
+}
+
+static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt,
+					 bool is_auto_arp_msg)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(is_auto_arp_msg);
+}
+#endif /* CONFIG_NET_IPV4_AUTO */
+
+#if defined(CONFIG_NET_LLDP)
+static inline bool net_pkt_is_lldp(struct net_pkt *pkt)
+{
+	return pkt->lldp_pkt;
+}
+
+static inline void net_pkt_set_lldp(struct net_pkt *pkt, bool is_lldp)
+{
+	pkt->lldp_pkt = is_lldp;
+}
+#else
+static inline bool net_pkt_is_lldp(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return false;
+}
+
+static inline void net_pkt_set_lldp(struct net_pkt *pkt, bool is_lldp)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(is_lldp);
+}
+#endif /* CONFIG_NET_LLDP */
+
+#if defined(CONFIG_NET_PPP)
+static inline bool net_pkt_is_ppp(struct net_pkt *pkt)
+{
+	return pkt->ppp_msg;
+}
+
+static inline void net_pkt_set_ppp(struct net_pkt *pkt,
+				   bool is_ppp_msg)
+{
+	pkt->ppp_msg = is_ppp_msg;
+}
+#else /* CONFIG_NET_PPP */
+static inline bool net_pkt_is_ppp(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return false;
+}
+
+static inline void net_pkt_set_ppp(struct net_pkt *pkt,
+				   bool is_ppp_msg)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(is_ppp_msg);
+}
+#endif /* CONFIG_NET_PPP */
+
+#define NET_IPV6_HDR(pkt) ((struct net_ipv6_hdr *)net_pkt_ip_data(pkt))
+#define NET_IPV4_HDR(pkt) ((struct net_ipv4_hdr *)net_pkt_ip_data(pkt))
+
+static inline void net_pkt_set_src_ipv6_addr(struct net_pkt *pkt)
+{
+	net_if_ipv6_select_src_addr(net_context_get_iface(
+					    net_pkt_context(pkt)),
+				    &NET_IPV6_HDR(pkt)->src);
+}
+
+static inline void net_pkt_set_overwrite(struct net_pkt *pkt, bool overwrite)
+{
+	pkt->overwrite = overwrite;
+}
+
+static inline bool net_pkt_is_being_overwritten(struct net_pkt *pkt)
+{
+	return pkt->overwrite;
+}
+
+/* @endcond */
+
+/**
+ * @brief Create a net_pkt slab
+ *
+ * A net_pkt slab is used to store meta-information about
+ * network packets. It must be coupled with a data fragment pool
+ * (:c:macro:`NET_PKT_DATA_POOL_DEFINE`) used to store the actual
+ * packet data. The macro can be used by an application to define
+ * additional custom per-context TX packet slabs (see
+ * :c:func:`net_context_setup_pools`).
+ *
+ * @param name Name of the slab.
+ * @param count Number of net_pkt in this slab.
+ */
+#define NET_PKT_SLAB_DEFINE(name, count)				\
+	K_MEM_SLAB_DEFINE(name, sizeof(struct net_pkt), count, 4)
+
+/* Backward compatibility macro */
+#define NET_PKT_TX_SLAB_DEFINE(name, count) NET_PKT_SLAB_DEFINE(name, count)
+
+/**
+ * @brief Create a data fragment net_buf pool
+ *
+ * A net_buf pool is used to store actual data for
+ * network packets. It must be coupled with a net_pkt slab
+ * (:c:macro:`NET_PKT_SLAB_DEFINE`) used to store the packet
+ * meta-information. The macro can be used by an application to
+ * define additional custom per-context TX packet pools (see
+ * :c:func:`net_context_setup_pools`).
+ *
+ * @param name Name of the pool.
+ * @param count Number of net_buf in this pool.
+ */
+#define NET_PKT_DATA_POOL_DEFINE(name, count)				\
+	NET_BUF_POOL_DEFINE(name, count, CONFIG_NET_BUF_DATA_SIZE,	\
+			    CONFIG_NET_BUF_USER_DATA_SIZE, NULL)
+
+/** @cond INTERNAL_HIDDEN */
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) || \
+	(CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG)
+#define NET_PKT_DEBUG_ENABLED
+#endif
+
+#if defined(NET_PKT_DEBUG_ENABLED)
+
+/* Debug versions of the net_pkt functions that are used when tracking
+ * buffer usage.
+ */
+
+struct net_buf *net_pkt_get_reserve_data_debug(struct net_buf_pool *pool,
+					       k_timeout_t timeout,
+					       const char *caller,
+					       int line);
+
+#define net_pkt_get_reserve_data(pool, timeout)				\
+	net_pkt_get_reserve_data_debug(pool, timeout, __func__, __LINE__)
+
+struct net_buf *net_pkt_get_reserve_rx_data_debug(k_timeout_t timeout,
+						  const char *caller,
+						  int line);
+#define net_pkt_get_reserve_rx_data(timeout)				\
+	net_pkt_get_reserve_rx_data_debug(timeout, __func__, __LINE__)
+
+struct net_buf *net_pkt_get_reserve_tx_data_debug(k_timeout_t timeout,
+						  const char *caller,
+						  int line);
+#define net_pkt_get_reserve_tx_data(timeout)				\
+	net_pkt_get_reserve_tx_data_debug(timeout, __func__, __LINE__)
+
+struct net_buf *net_pkt_get_frag_debug(struct net_pkt *pkt,
+				       k_timeout_t timeout,
+				       const char *caller, int line);
+#define net_pkt_get_frag(pkt, timeout)					\
+	net_pkt_get_frag_debug(pkt, timeout, __func__, __LINE__)
+
+void net_pkt_unref_debug(struct net_pkt *pkt, const char *caller, int line);
+#define net_pkt_unref(pkt) net_pkt_unref_debug(pkt, __func__, __LINE__)
+
+struct net_pkt *net_pkt_ref_debug(struct net_pkt *pkt, const char *caller,
+				  int line);
+#define net_pkt_ref(pkt) net_pkt_ref_debug(pkt, __func__, __LINE__)
+
+struct net_buf *net_pkt_frag_ref_debug(struct net_buf *frag,
+				       const char *caller, int line);
+#define net_pkt_frag_ref(frag) net_pkt_frag_ref_debug(frag, __func__, __LINE__)
+
+void net_pkt_frag_unref_debug(struct net_buf *frag,
+			      const char *caller, int line);
+#define net_pkt_frag_unref(frag)				\
+	net_pkt_frag_unref_debug(frag, __func__, __LINE__)
+
+struct net_buf *net_pkt_frag_del_debug(struct net_pkt *pkt,
+				       struct net_buf *parent,
+				       struct net_buf *frag,
+				       const char *caller, int line);
+#define net_pkt_frag_del(pkt, parent, frag)				\
+	net_pkt_frag_del_debug(pkt, parent, frag, __func__, __LINE__)
+
+void net_pkt_frag_add_debug(struct net_pkt *pkt, struct net_buf *frag,
+			    const char *caller, int line);
+#define net_pkt_frag_add(pkt, frag)				\
+	net_pkt_frag_add_debug(pkt, frag, __func__, __LINE__)
+
+void net_pkt_frag_insert_debug(struct net_pkt *pkt, struct net_buf *frag,
+			       const char *caller, int line);
+#define net_pkt_frag_insert(pkt, frag)					\
+	net_pkt_frag_insert_debug(pkt, frag, __func__, __LINE__)
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC ||
+	* CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	*/
+/** @endcond */
+
+/**
+ * @brief Print fragment list and the fragment sizes
+ *
+ * @details Only available if debugging is activated.
+ *
+ * @param pkt Network pkt.
+ */
+#if defined(NET_PKT_DEBUG_ENABLED)
+void net_pkt_print_frags(struct net_pkt *pkt);
+#else
+#define net_pkt_print_frags(pkt)
+#endif
+
+/**
+ * @brief Get RX DATA buffer from pool.
+ * Normally you should use net_pkt_get_frag() instead.
+ *
+ * @details Normally this version is not useful for applications
+ * but is mainly used by network fragmentation code.
+ *
+ * @param timeout Affects the action taken should the net buf pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait up to the specified time.
+ *
+ * @return Network buffer if successful, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_buf *net_pkt_get_reserve_rx_data(k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Get TX DATA buffer from pool.
+ * Normally you should use net_pkt_get_frag() instead.
+ *
+ * @details Normally this version is not useful for applications
+ * but is mainly used by network fragmentation code.
+ *
+ * @param timeout Affects the action taken should the net buf pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait up to the specified time.
+ *
+ * @return Network buffer if successful, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_buf *net_pkt_get_reserve_tx_data(k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Get a data fragment that might be from user specific
+ * buffer pool or from global DATA pool.
+ *
+ * @param pkt Network packet.
+ * @param timeout Affects the action taken should the net buf pool be empty.
+ *        If K_NO_WAIT, then return immediately. If K_FOREVER, then
+ *        wait as long as necessary. Otherwise, wait up to the specified time.
+ *
+ * @return Network buffer if successful, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_buf *net_pkt_get_frag(struct net_pkt *pkt, k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Place packet back into the available packets slab
+ *
+ * @details Releases the packet to other use. This needs to be
+ * called by application after it has finished with the packet.
+ *
+ * @param pkt Network packet to release.
+ *
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+void net_pkt_unref(struct net_pkt *pkt);
+#endif
+
+/**
+ * @brief Increase the packet ref count
+ *
+ * @details Mark the packet to be used still.
+ *
+ * @param pkt Network packet to ref.
+ *
+ * @return Network packet if successful, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_ref(struct net_pkt *pkt);
+#endif
+
+/**
+ * @brief Increase the packet fragment ref count
+ *
+ * @details Mark the fragment to be used still.
+ *
+ * @param frag Network fragment to ref.
+ *
+ * @return a pointer on the referenced Network fragment.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_buf *net_pkt_frag_ref(struct net_buf *frag);
+#endif
+
+/**
+ * @brief Decrease the packet fragment ref count
+ *
+ * @param frag Network fragment to unref.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+void net_pkt_frag_unref(struct net_buf *frag);
+#endif
+
+/**
+ * @brief Delete existing fragment from a packet
+ *
+ * @param pkt Network packet from which frag belongs to.
+ * @param parent parent fragment of frag, or NULL if none.
+ * @param frag Fragment to delete.
+ *
+ * @return Pointer to the following fragment, or NULL if it had no
+ *         further fragments.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_buf *net_pkt_frag_del(struct net_pkt *pkt,
+				 struct net_buf *parent,
+				 struct net_buf *frag);
+#endif
+
+/**
+ * @brief Add a fragment to a packet at the end of its fragment list
+ *
+ * @param pkt pkt Network packet where to add the fragment
+ * @param frag Fragment to add
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+void net_pkt_frag_add(struct net_pkt *pkt, struct net_buf *frag);
+#endif
+
+/**
+ * @brief Insert a fragment to a packet at the beginning of its fragment list
+ *
+ * @param pkt pkt Network packet where to insert the fragment
+ * @param frag Fragment to insert
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+void net_pkt_frag_insert(struct net_pkt *pkt, struct net_buf *frag);
+#endif
+
+/**
+ * @brief Compact the fragment list of a packet.
+ *
+ * @details After this there is no more any free space in individual fragments.
+ * @param pkt Network packet.
+ *
+ * @return True if compact success, False otherwise.
+ */
+bool net_pkt_compact(struct net_pkt *pkt);
+
+/**
+ * @brief Get information about predefined RX, TX and DATA pools.
+ *
+ * @param rx Pointer to RX pool is returned.
+ * @param tx Pointer to TX pool is returned.
+ * @param rx_data Pointer to RX DATA pool is returned.
+ * @param tx_data Pointer to TX DATA pool is returned.
+ */
+void net_pkt_get_info(struct k_mem_slab **rx,
+		      struct k_mem_slab **tx,
+		      struct net_buf_pool **rx_data,
+		      struct net_buf_pool **tx_data);
+
+/** @cond INTERNAL_HIDDEN */
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+/**
+ * @brief Debug helper to print out the buffer allocations
+ */
+void net_pkt_print(void);
+
+typedef void (*net_pkt_allocs_cb_t)(struct net_pkt *pkt,
+				    struct net_buf *buf,
+				    const char *func_alloc,
+				    int line_alloc,
+				    const char *func_free,
+				    int line_free,
+				    bool in_use,
+				    void *user_data);
+
+void net_pkt_allocs_foreach(net_pkt_allocs_cb_t cb, void *user_data);
+
+const char *net_pkt_slab2str(struct k_mem_slab *slab);
+const char *net_pkt_pool2str(struct net_buf_pool *pool);
+
+#else
+#define net_pkt_print(...)
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
+
+/* New allocator, and API are defined below.
+ * This will be simpler when time will come to get rid of former API above.
+ */
+#if defined(NET_PKT_DEBUG_ENABLED)
+
+struct net_pkt *net_pkt_alloc_debug(k_timeout_t timeout,
+				    const char *caller, int line);
+#define net_pkt_alloc(_timeout)					\
+	net_pkt_alloc_debug(_timeout, __func__, __LINE__)
+
+struct net_pkt *net_pkt_alloc_from_slab_debug(struct k_mem_slab *slab,
+					      k_timeout_t timeout,
+					      const char *caller, int line);
+#define net_pkt_alloc_from_slab(_slab, _timeout)			\
+	net_pkt_alloc_from_slab_debug(_slab, _timeout, __func__, __LINE__)
+
+struct net_pkt *net_pkt_rx_alloc_debug(k_timeout_t timeout,
+				       const char *caller, int line);
+#define net_pkt_rx_alloc(_timeout)				\
+	net_pkt_rx_alloc_debug(_timeout, __func__, __LINE__)
+
+struct net_pkt *net_pkt_alloc_on_iface_debug(struct net_if *iface,
+					     k_timeout_t timeout,
+					     const char *caller,
+					     int line);
+#define net_pkt_alloc_on_iface(_iface, _timeout)			\
+	net_pkt_alloc_on_iface_debug(_iface, _timeout, __func__, __LINE__)
+
+struct net_pkt *net_pkt_rx_alloc_on_iface_debug(struct net_if *iface,
+						k_timeout_t timeout,
+						const char *caller,
+						int line);
+#define net_pkt_rx_alloc_on_iface(_iface, _timeout)			\
+	net_pkt_rx_alloc_on_iface_debug(_iface, _timeout,		\
+					__func__, __LINE__)
+
+int net_pkt_alloc_buffer_debug(struct net_pkt *pkt,
+			       size_t size,
+			       enum net_ip_protocol proto,
+			       k_timeout_t timeout,
+			       const char *caller, int line);
+#define net_pkt_alloc_buffer(_pkt, _size, _proto, _timeout)		\
+	net_pkt_alloc_buffer_debug(_pkt, _size, _proto, _timeout,	\
+				   __func__, __LINE__)
+
+struct net_pkt *net_pkt_alloc_with_buffer_debug(struct net_if *iface,
+						size_t size,
+						sa_family_t family,
+						enum net_ip_protocol proto,
+						k_timeout_t timeout,
+						const char *caller,
+						int line);
+#define net_pkt_alloc_with_buffer(_iface, _size, _family,		\
+				  _proto, _timeout)			\
+	net_pkt_alloc_with_buffer_debug(_iface, _size, _family,		\
+					_proto, _timeout,		\
+					__func__, __LINE__)
+
+struct net_pkt *net_pkt_rx_alloc_with_buffer_debug(struct net_if *iface,
+						   size_t size,
+						   sa_family_t family,
+						   enum net_ip_protocol proto,
+						   k_timeout_t timeout,
+						   const char *caller,
+						   int line);
+#define net_pkt_rx_alloc_with_buffer(_iface, _size, _family,		\
+				     _proto, _timeout)			\
+	net_pkt_rx_alloc_with_buffer_debug(_iface, _size, _family,	\
+					   _proto, _timeout,		\
+					   __func__, __LINE__)
+#endif /* NET_PKT_DEBUG_ENABLED */
+/** @endcond */
+
+/**
+ * @brief Allocate an initialized net_pkt
+ *
+ * @details for the time being, 2 pools are used. One for TX and one for RX.
+ *          This allocator has to be used for TX.
+ *
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return a pointer to a newly allocated net_pkt on success, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_alloc(k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate an initialized net_pkt from a specific slab
+ *
+ * @details unlike net_pkt_alloc() which uses core slabs, this one will use
+ *          an external slab (see NET_PKT_SLAB_DEFINE()).
+ *          Do _not_ use it unless you know what you are doing. Basically, only
+ *          net_context should be using this, in order to allocate packet and
+ *          then buffer on its local slab/pool (if any).
+ *
+ * @param slab    The slab to use for allocating the packet
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return a pointer to a newly allocated net_pkt on success, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_alloc_from_slab(struct k_mem_slab *slab,
+					k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate an initialized net_pkt for RX
+ *
+ * @details for the time being, 2 pools are used. One for TX and one for RX.
+ *          This allocator has to be used for RX.
+ *
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return a pointer to a newly allocated net_pkt on success, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate a network packet for a specific network interface.
+ *
+ * @param iface The network interface the packet is supposed to go through.
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return a pointer to a newly allocated net_pkt on success, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface,
+				       k_timeout_t timeout);
+
+/* Same as above but specifically for RX packet */
+struct net_pkt *net_pkt_rx_alloc_on_iface(struct net_if *iface,
+					  k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate buffer for a net_pkt
+ *
+ * @details: such allocator will take into account space necessary for headers,
+ *           MTU, and existing buffer (if any). Beware that, due to all these
+ *           criteria, the allocated size might be smaller/bigger than
+ *           requested one.
+ *
+ * @param pkt     The network packet requiring buffer to be allocated.
+ * @param size    The size of buffer being requested.
+ * @param proto   The IP protocol type (can be 0 for none).
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+int net_pkt_alloc_buffer(struct net_pkt *pkt,
+			 size_t size,
+			 enum net_ip_protocol proto,
+			 k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Allocate a network packet and buffer at once
+ *
+ * @param iface   The network interface the packet is supposed to go through.
+ * @param size    The size of buffer.
+ * @param family  The family to which the packet belongs.
+ * @param proto   The IP protocol type (can be 0 for none).
+ * @param timeout Maximum time to wait for an allocation.
+ *
+ * @return a pointer to a newly allocated net_pkt on success, NULL otherwise.
+ */
+#if !defined(NET_PKT_DEBUG_ENABLED)
+struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface,
+					  size_t size,
+					  sa_family_t family,
+					  enum net_ip_protocol proto,
+					  k_timeout_t timeout);
+
+/* Same as above but specifically for RX packet */
+struct net_pkt *net_pkt_rx_alloc_with_buffer(struct net_if *iface,
+					     size_t size,
+					     sa_family_t family,
+					     enum net_ip_protocol proto,
+					     k_timeout_t timeout);
+#endif
+
+/**
+ * @brief Append a buffer in packet
+ *
+ * @param pkt    Network packet where to append the buffer
+ * @param buffer Buffer to append
+ */
+void net_pkt_append_buffer(struct net_pkt *pkt, struct net_buf *buffer);
+
+/**
+ * @brief Get available buffer space from a pkt
+ *
+ * @param pkt The net_pkt which buffer availability should be evaluated
+ *
+ * @return the amount of buffer available
+ */
+size_t net_pkt_available_buffer(struct net_pkt *pkt);
+
+/**
+ * @brief Get available buffer space for payload from a pkt
+ *
+ * @details Unlike net_pkt_available_buffer(), this will take into account
+ *          the headers space.
+ *
+ * @param pkt   The net_pkt which payload buffer availability should
+ *              be evaluated
+ * @param proto The IP protocol type (can be 0 for none).
+ *
+ * @return the amount of buffer available for payload
+ */
+size_t net_pkt_available_payload_buffer(struct net_pkt *pkt,
+					enum net_ip_protocol proto);
+
+/**
+ * @brief Trim net_pkt buffer
+ *
+ * @details This will basically check for unused buffers and deallocates
+ *          them relevantly
+ *
+ * @param pkt The net_pkt which buffer will be trimmed
+ */
+void net_pkt_trim_buffer(struct net_pkt *pkt);
+
+/**
+ * @brief Initialize net_pkt cursor
+ *
+ * @details This will initialize the net_pkt cursor from its buffer.
+ *
+ * @param pkt The net_pkt whose cursor is going to be initialized
+ */
+void net_pkt_cursor_init(struct net_pkt *pkt);
+
+/**
+ * @brief Backup net_pkt cursor
+ *
+ * @param pkt    The net_pkt whose cursor is going to be backed up
+ * @param backup The cursor where to backup net_pkt cursor
+ */
+static inline void net_pkt_cursor_backup(struct net_pkt *pkt,
+					 struct net_pkt_cursor *backup)
+{
+	backup->buf = pkt->cursor.buf;
+	backup->pos = pkt->cursor.pos;
+}
+
+/**
+ * @brief Restore net_pkt cursor from a backup
+ *
+ * @param pkt    The net_pkt whose cursor is going to be restored
+ * @param backup The cursor from where to restore net_pkt cursor
+ */
+static inline void net_pkt_cursor_restore(struct net_pkt *pkt,
+					  struct net_pkt_cursor *backup)
+{
+	pkt->cursor.buf = backup->buf;
+	pkt->cursor.pos = backup->pos;
+}
+
+/**
+ * @brief Returns current position of the cursor
+ *
+ * @param pkt The net_pkt whose cursor position is going to be returned
+ *
+ * @return cursor's position
+ */
+static inline void *net_pkt_cursor_get_pos(struct net_pkt *pkt)
+{
+	return pkt->cursor.pos;
+}
+
+/**
+ * @brief Skip some data from a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized
+ *          Cursor position will be updated after the operation.
+ *          Depending on the value of pkt->overwrite bit, this function
+ *          will affect the buffer length or not. If it's true, it will
+ *          advance the cursor to the requested length. If it's false,
+ *          it will do the same but if the cursor was already also at the
+ *          end of existing data, it will increment the buffer length.
+ *          So in this case, its behavior is just like net_pkt_write or
+ *          net_pkt_memset, difference being that it will not affect the
+ *          buffer content itself (which may be just garbage then).
+ *
+ * @param pkt    The net_pkt whose cursor will be updated to skip given
+ *               amount of data from the buffer.
+ * @param length Amount of data to skip in the buffer
+ *
+ * @return 0 in success, negative errno code otherwise.
+ */
+int net_pkt_skip(struct net_pkt *pkt, size_t length);
+
+/**
+ * @brief Memset some data in a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt    The net_pkt whose buffer to fill starting at the current
+ *               cursor position.
+ * @param byte   The byte to write in memory
+ * @param length Amount of data to memset with given byte
+ *
+ * @return 0 in success, negative errno code otherwise.
+ */
+int net_pkt_memset(struct net_pkt *pkt, int byte, size_t length);
+
+/**
+ * @brief Copy data from a packet into another one.
+ *
+ * @details Both net_pkt cursors should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          The cursors will be updated after the operation.
+ *
+ * @param pkt_dst Destination network packet.
+ * @param pkt_src Source network packet.
+ * @param length  Length of data to be copied.
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_copy(struct net_pkt *pkt_dst,
+		 struct net_pkt *pkt_src,
+		 size_t length);
+
+/**
+ * @brief Clone pkt and its buffer.
+ *
+ * @param pkt Original pkt to be cloned
+ * @param timeout Timeout to wait for free buffer
+ *
+ * @return NULL if error, cloned packet otherwise.
+ */
+struct net_pkt *net_pkt_clone(struct net_pkt *pkt, k_timeout_t timeout);
+
+/**
+ * @brief Clone pkt and increase the refcount of its buffer.
+ *
+ * @param pkt Original pkt to be shallow cloned
+ * @param timeout Timeout to wait for free packet
+ *
+ * @return NULL if error, cloned packet otherwise.
+ */
+struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt,
+				      k_timeout_t timeout);
+
+/**
+ * @brief Read some data from a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt    The network packet from where to read some data
+ * @param data   The destination buffer where to copy the data
+ * @param length The amount of data to copy
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_read(struct net_pkt *pkt, void *data, size_t length);
+
+/* Read uint8_t data data a net_pkt */
+static inline int net_pkt_read_u8(struct net_pkt *pkt, uint8_t *data)
+{
+	return net_pkt_read(pkt, data, 1);
+}
+
+/**
+ * @brief Read uint16_t big endian data from a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt  The network packet from where to read
+ * @param data The destination uint16_t where to copy the data
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_read_be16(struct net_pkt *pkt, uint16_t *data);
+
+/**
+ * @brief Read uint16_t little endian data from a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt  The network packet from where to read
+ * @param data The destination uint16_t where to copy the data
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_read_le16(struct net_pkt *pkt, uint16_t *data);
+
+/**
+ * @brief Read uint32_t big endian data from a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt  The network packet from where to read
+ * @param data The destination uint32_t where to copy the data
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data);
+
+/**
+ * @brief Write data into a net_pkt
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt    The network packet where to write
+ * @param data   Data to be written
+ * @param length Length of the data to be written
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length);
+
+/* Write uint8_t data into a net_pkt. */
+static inline int net_pkt_write_u8(struct net_pkt *pkt, uint8_t data)
+{
+	return net_pkt_write(pkt, &data, sizeof(uint8_t));
+}
+
+/* Write uint16_t big endian data into a net_pkt. */
+static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data)
+{
+	uint16_t data_be16 = htons(data);
+
+	return net_pkt_write(pkt, &data_be16, sizeof(uint16_t));
+}
+
+/* Write uint32_t big endian data into a net_pkt. */
+static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data)
+{
+	uint32_t data_be32 = htonl(data);
+
+	return net_pkt_write(pkt, &data_be32, sizeof(uint32_t));
+}
+
+/* Write uint32_t little endian data into a net_pkt. */
+static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data)
+{
+	uint32_t data_le32 = sys_cpu_to_le32(data);
+
+	return net_pkt_write(pkt, &data_le32, sizeof(uint32_t));
+}
+
+/* Write uint16_t little endian data into a net_pkt. */
+static inline int net_pkt_write_le16(struct net_pkt *pkt, uint16_t data)
+{
+	uint16_t data_le16 = sys_cpu_to_le16(data);
+
+	return net_pkt_write(pkt, &data_le16, sizeof(uint16_t));
+}
+
+/**
+ * @brief Get the amount of data which can be read from current cursor position
+ *
+ * @param pkt Network packet
+ *
+ * @return Amount of data which can be read from current pkt cursor
+ */
+size_t net_pkt_remaining_data(struct net_pkt *pkt);
+
+/**
+ * @brief Update the overall length of a packet
+ *
+ * @details Unlike net_pkt_pull() below, this does not take packet cursor
+ *          into account. It's mainly a helper dedicated for ipv4 and ipv6
+ *          input functions. It shrinks the overall length by given parameter.
+ *
+ * @param pkt    Network packet
+ * @param length The new length of the packet
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_update_length(struct net_pkt *pkt, size_t length);
+
+/**
+ * @brief Remove data from the packet at current location
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          eventually, properly positioned using net_pkt_skip/read/write.
+ *          Note that net_pkt's cursor is reset by this function.
+ *
+ * @param pkt    Network packet
+ * @param length Number of bytes to be removed
+ *
+ * @return 0 on success, negative errno code otherwise.
+ */
+int net_pkt_pull(struct net_pkt *pkt, size_t length);
+
+/**
+ * @brief Get the actual offset in the packet from its cursor
+ *
+ * @param pkt Network packet.
+ *
+ * @return a valid offset on success, 0 otherwise as there is nothing that
+ *         can be done to evaluate the offset.
+ */
+uint16_t net_pkt_get_current_offset(struct net_pkt *pkt);
+
+/**
+ * @brief Check if a data size could fit contiguously
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *
+ * @param pkt  Network packet.
+ * @param size The size to check for contiguity
+ *
+ * @return true if that is the case, false otherwise.
+ */
+bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size);
+
+struct net_pkt_data_access {
+#if !defined(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)
+	void *data;
+#endif
+	const size_t size;
+};
+
+#if defined(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)
+#define NET_PKT_DATA_ACCESS_DEFINE(_name, _type)		\
+	struct net_pkt_data_access _name = {			\
+		.size = sizeof(_type),				\
+	}
+
+#define NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(_name, _type)	\
+	NET_PKT_DATA_ACCESS_DEFINE(_name, _type)
+
+#else
+#define NET_PKT_DATA_ACCESS_DEFINE(_name, _type)		\
+	_type _hdr_##_name;					\
+	struct net_pkt_data_access _name = {			\
+		.data = &_hdr_##_name,				\
+		.size = sizeof(_type),				\
+	}
+
+#define NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(_name, _type)	\
+	struct net_pkt_data_access _name = {			\
+		.data = NULL,					\
+		.size = sizeof(_type),				\
+	}
+
+#endif /* CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS */
+
+/**
+ * @brief Get data from a network packet in a contiguous way
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt    The network packet from where to get the data.
+ * @param access A pointer to a valid net_pkt_data_access describing the
+ *        data to get in a contiguous way.
+ *
+ * @return a pointer to the requested contiguous data, NULL otherwise.
+ */
+void *net_pkt_get_data(struct net_pkt *pkt,
+		       struct net_pkt_data_access *access);
+
+/**
+ * @brief Set contiguous data into a network packet
+ *
+ * @details net_pkt's cursor should be properly initialized and,
+ *          if needed, positioned using net_pkt_skip.
+ *          Cursor position will be updated after the operation.
+ *
+ * @param pkt    The network packet to where the data should be set.
+ * @param access A pointer to a valid net_pkt_data_access describing the
+ *        data to set.
+ *
+ * @return 0 on success, a negative errno otherwise.
+ */
+int net_pkt_set_data(struct net_pkt *pkt,
+		     struct net_pkt_data_access *access);
+
+/**
+ * Acknowledge previously contiguous data taken from a network packet
+ * Packet needs to be set to overwrite mode.
+ */
+static inline int net_pkt_acknowledge_data(struct net_pkt *pkt,
+					   struct net_pkt_data_access *access)
+{
+	return net_pkt_skip(pkt, access->size);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_PKT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_stats.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_stats.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_stats.h	(working copy)
@@ -0,0 +1,564 @@
+/** @file
+ * @brief Network statistics
+ *
+ * Network statistics data. This should only be enabled when
+ * debugging as it consumes memory.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_STATS_H_
+#define ZEPHYR_INCLUDE_NET_NET_STATS_H_
+
+#include <zephyr/types.h>
+#include <net/net_core.h>
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Network statistics library
+ * @defgroup net_stats Network Statistics Library
+ * @ingroup networking
+ * @{
+ */
+
+/**
+ * @typedef net_stats_t
+ * @brief Network statistics counter
+ */
+typedef uint32_t net_stats_t;
+
+/**
+ * @brief Number of bytes sent and received.
+ */
+struct net_stats_bytes {
+	/** Number of bytes sent */
+	net_stats_t sent;
+	/** Number of bytes received */
+	net_stats_t received;
+};
+
+/**
+ * @brief Number of network packets sent and received.
+ */
+struct net_stats_pkts {
+	/** Number of packets sent */
+	net_stats_t tx;
+	/** Number of packets received */
+	net_stats_t rx;
+};
+
+/**
+ * @brief IP layer statistics
+ */
+struct net_stats_ip {
+	/** Number of received packets at the IP layer. */
+	net_stats_t recv;
+
+	/** Number of sent packets at the IP layer. */
+	net_stats_t sent;
+
+	/** Number of forwarded packets at the IP layer. */
+	net_stats_t forwarded;
+
+	/** Number of dropped packets at the IP layer. */
+	net_stats_t drop;
+};
+
+/**
+ * @brief IP layer error statistics
+ */
+struct net_stats_ip_errors {
+	/** Number of packets dropped due to wrong IP version
+	 * or header length.
+	 */
+	net_stats_t vhlerr;
+
+	 /** Number of packets dropped due to wrong IP length, high byte. */
+	net_stats_t hblenerr;
+
+	/** Number of packets dropped due to wrong IP length, low byte. */
+	net_stats_t lblenerr;
+
+	/** Number of packets dropped because they were IP fragments. */
+	net_stats_t fragerr;
+
+	/** Number of packets dropped due to IP checksum errors. */
+	net_stats_t chkerr;
+
+	/** Number of packets dropped because they were neither ICMP,
+	 * UDP nor TCP.
+	 */
+	net_stats_t protoerr;
+};
+
+/**
+ * @brief ICMP statistics
+ */
+struct net_stats_icmp {
+	/** Number of received ICMP packets. */
+	net_stats_t recv;
+
+	/** Number of sent ICMP packets. */
+	net_stats_t sent;
+
+	/** Number of dropped ICMP packets. */
+	net_stats_t drop;
+
+	/** Number of ICMP packets with a wrong type. */
+	net_stats_t typeerr;
+
+	/** Number of ICMP packets with a bad checksum. */
+	net_stats_t chkerr;
+};
+
+/**
+ * @brief TCP statistics
+ */
+struct net_stats_tcp {
+	/** Amount of received and sent TCP application data. */
+	struct net_stats_bytes bytes;
+
+	/** Amount of retransmitted data. */
+	net_stats_t resent;
+
+	/** Number of received TCP segments. */
+	net_stats_t recv;
+
+	/** Number of sent TCP segments. */
+	net_stats_t sent;
+
+	/** Number of dropped TCP segments. */
+	net_stats_t drop;
+
+	/** Number of TCP segments with a bad checksum. */
+	net_stats_t chkerr;
+
+	/** Number of received TCP segments with a bad ACK number. */
+	net_stats_t ackerr;
+
+	/** Number of received bad TCP RST (reset) segments. */
+	net_stats_t rsterr;
+
+	/** Number of received TCP RST (reset) segments. */
+	net_stats_t rst;
+
+	/** Number of retransmitted TCP segments. */
+	net_stats_t rexmit;
+
+	/** Number of dropped connection attempts because too few connections
+	 * were available.
+	 */
+	net_stats_t conndrop;
+
+	/** Number of connection attempts for closed ports, triggering a RST. */
+	net_stats_t connrst;
+};
+
+/**
+ * @brief UDP statistics
+ */
+struct net_stats_udp {
+	/** Number of dropped UDP segments. */
+	net_stats_t drop;
+
+	/** Number of received UDP segments. */
+	net_stats_t recv;
+
+	/** Number of sent UDP segments. */
+	net_stats_t sent;
+
+	/** Number of UDP segments with a bad checksum. */
+	net_stats_t chkerr;
+};
+
+/**
+ * @brief IPv6 neighbor discovery statistics
+ */
+struct net_stats_ipv6_nd {
+	net_stats_t drop;
+	net_stats_t recv;
+	net_stats_t sent;
+};
+
+/**
+ * @brief IPv6 multicast listener daemon statistics
+ */
+struct net_stats_ipv6_mld {
+	/** Number of received IPv6 MLD queries */
+	net_stats_t recv;
+
+	/** Number of sent IPv6 MLD reports */
+	net_stats_t sent;
+
+	/** Number of dropped IPv6 MLD packets */
+	net_stats_t drop;
+};
+
+/**
+ * @brief Network packet transfer times for calculating average TX time
+ */
+struct net_stats_tx_time {
+	uint64_t sum;
+	net_stats_t count;
+};
+
+/**
+ * @brief Network packet receive times for calculating average RX time
+ */
+struct net_stats_rx_time {
+	uint64_t sum;
+	net_stats_t count;
+};
+
+/**
+ * @brief Traffic class statistics
+ */
+struct net_stats_tc {
+	struct {
+		struct net_stats_tx_time tx_time;
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+		struct net_stats_tx_time
+				tx_time_detail[NET_PKT_DETAIL_STATS_COUNT];
+#endif
+		net_stats_t pkts;
+		net_stats_t bytes;
+		uint8_t priority;
+	} sent[NET_TC_TX_COUNT];
+
+	struct {
+		struct net_stats_rx_time rx_time;
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+		struct net_stats_rx_time
+				rx_time_detail[NET_PKT_DETAIL_STATS_COUNT];
+#endif
+		net_stats_t pkts;
+		net_stats_t bytes;
+		uint8_t priority;
+	} recv[NET_TC_RX_COUNT];
+};
+
+
+/**
+ * @brief Power management statistics
+ */
+struct net_stats_pm {
+	uint64_t overall_suspend_time;
+	net_stats_t suspend_count;
+	uint32_t last_suspend_time;
+	uint32_t start_time;
+};
+
+
+/**
+ * @brief All network statistics in one struct.
+ */
+struct net_stats {
+	/** Count of malformed packets or packets we do not have handler for */
+	net_stats_t processing_error;
+
+	/**
+	 * This calculates amount of data transferred through all the
+	 * network interfaces.
+	 */
+	struct net_stats_bytes bytes;
+
+	/** IP layer errors */
+	struct net_stats_ip_errors ip_errors;
+
+#if defined(CONFIG_NET_STATISTICS_IPV6)
+	/** IPv6 statistics */
+	struct net_stats_ip ipv6;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_IPV4)
+	/** IPv4 statistics */
+	struct net_stats_ip ipv4;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_ICMP)
+	/** ICMP statistics */
+	struct net_stats_icmp icmp;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_TCP)
+	/** TCP statistics */
+	struct net_stats_tcp tcp;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_UDP)
+	/** UDP statistics */
+	struct net_stats_udp udp;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+	/** IPv6 neighbor discovery statistics */
+	struct net_stats_ipv6_nd ipv6_nd;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_MLD)
+	/** IPv6 MLD statistics */
+	struct net_stats_ipv6_mld ipv6_mld;
+#endif
+
+#if NET_TC_COUNT > 1
+	/** Traffic class statistics */
+	struct net_stats_tc tc;
+#endif
+
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && \
+	defined(CONFIG_NET_PKT_TXTIME_STATS)
+#error \
+"Cannot define both CONFIG_NET_CONTEXT_TIMESTAMP and CONFIG_NET_PKT_TXTIME_STATS"
+#endif
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
+					defined(CONFIG_NET_PKT_TXTIME_STATS)
+	/** Network packet TX time statistics */
+	struct net_stats_tx_time tx_time;
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+	/** Network packet TX time detail statistics */
+	struct net_stats_tx_time tx_time_detail[NET_PKT_DETAIL_STATS_COUNT];
+#endif
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+	/** Network packet RX time detail statistics */
+	struct net_stats_tx_time rx_time_detail[NET_PKT_DETAIL_STATS_COUNT];
+#endif
+#endif
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS)
+	/** Network packet RX time statistics */
+	struct net_stats_rx_time rx_time;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+	struct net_stats_pm pm;
+#endif
+};
+
+/**
+ * @brief Ethernet error statistics
+ */
+struct net_stats_eth_errors {
+	net_stats_t rx_length_errors;
+	net_stats_t rx_over_errors;
+	net_stats_t rx_crc_errors;
+	net_stats_t rx_frame_errors;
+	net_stats_t rx_no_buffer_count;
+	net_stats_t rx_missed_errors;
+	net_stats_t rx_long_length_errors;
+	net_stats_t rx_short_length_errors;
+	net_stats_t rx_align_errors;
+	net_stats_t rx_dma_failed;
+	net_stats_t rx_buf_alloc_failed;
+
+	net_stats_t tx_aborted_errors;
+	net_stats_t tx_carrier_errors;
+	net_stats_t tx_fifo_errors;
+	net_stats_t tx_heartbeat_errors;
+	net_stats_t tx_window_errors;
+	net_stats_t tx_dma_failed;
+
+	net_stats_t uncorr_ecc_errors;
+	net_stats_t corr_ecc_errors;
+};
+
+/**
+ * @brief Ethernet flow control statistics
+ */
+struct net_stats_eth_flow {
+	net_stats_t rx_flow_control_xon;
+	net_stats_t rx_flow_control_xoff;
+	net_stats_t tx_flow_control_xon;
+	net_stats_t tx_flow_control_xoff;
+};
+
+/**
+ * @brief Ethernet checksum statistics
+ */
+struct net_stats_eth_csum {
+	net_stats_t rx_csum_offload_good;
+	net_stats_t rx_csum_offload_errors;
+};
+
+/**
+ * @brief Ethernet hardware timestamp statistics
+ */
+struct net_stats_eth_hw_timestamp {
+	net_stats_t rx_hwtstamp_cleared;
+	net_stats_t tx_hwtstamp_timeouts;
+	net_stats_t tx_hwtstamp_skipped;
+};
+
+#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
+/**
+ * @brief Ethernet vendor specific statistics
+ */
+struct net_stats_eth_vendor {
+	const char * const key;
+	uint32_t value;
+};
+#endif
+
+/**
+ * @brief All Ethernet specific statistics
+ */
+struct net_stats_eth {
+	struct net_stats_bytes bytes;
+	struct net_stats_pkts pkts;
+	struct net_stats_pkts broadcast;
+	struct net_stats_pkts multicast;
+	struct net_stats_pkts errors;
+	struct net_stats_eth_errors error_details;
+	struct net_stats_eth_flow flow_control;
+	struct net_stats_eth_csum csum;
+	struct net_stats_eth_hw_timestamp hw_timestamp;
+	net_stats_t collisions;
+	net_stats_t tx_dropped;
+	net_stats_t tx_timeout_count;
+	net_stats_t tx_restart_queue;
+#ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR
+	/** Array is terminated with an entry containing a NULL key */
+	struct net_stats_eth_vendor *vendor;
+#endif
+};
+
+/**
+ * @brief All PPP specific statistics
+ */
+struct net_stats_ppp {
+	struct net_stats_bytes bytes;
+	struct net_stats_pkts pkts;
+
+	/** Number of received and dropped PPP frames. */
+	net_stats_t drop;
+
+	/** Number of received PPP frames with a bad checksum. */
+	net_stats_t chkerr;
+};
+
+#if defined(CONFIG_NET_STATISTICS_USER_API)
+/* Management part definitions */
+
+#define _NET_STATS_LAYER	NET_MGMT_LAYER_L3
+#define _NET_STATS_CODE		0x101
+#define _NET_STATS_BASE		(NET_MGMT_LAYER(_NET_STATS_LAYER) |	\
+				 NET_MGMT_LAYER_CODE(_NET_STATS_CODE))
+
+enum net_request_stats_cmd {
+	NET_REQUEST_STATS_CMD_GET_ALL = 1,
+	NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR,
+	NET_REQUEST_STATS_CMD_GET_BYTES,
+	NET_REQUEST_STATS_CMD_GET_IP_ERRORS,
+	NET_REQUEST_STATS_CMD_GET_IPV4,
+	NET_REQUEST_STATS_CMD_GET_IPV6,
+	NET_REQUEST_STATS_CMD_GET_IPV6_ND,
+	NET_REQUEST_STATS_CMD_GET_ICMP,
+	NET_REQUEST_STATS_CMD_GET_UDP,
+	NET_REQUEST_STATS_CMD_GET_TCP,
+	NET_REQUEST_STATS_CMD_GET_ETHERNET,
+	NET_REQUEST_STATS_CMD_GET_PPP,
+	NET_REQUEST_STATS_CMD_GET_PM
+};
+
+#define NET_REQUEST_STATS_GET_ALL				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ALL)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL);
+
+#define NET_REQUEST_STATS_GET_PROCESSING_ERROR				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR);
+
+#define NET_REQUEST_STATS_GET_BYTES				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_BYTES)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES);
+
+#define NET_REQUEST_STATS_GET_IP_ERRORS				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IP_ERRORS)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS);
+
+#if defined(CONFIG_NET_STATISTICS_IPV4)
+#define NET_REQUEST_STATS_GET_IPV4				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV4)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV4);
+#endif /* CONFIG_NET_STATISTICS_IPV4 */
+
+#if defined(CONFIG_NET_STATISTICS_IPV6)
+#define NET_REQUEST_STATS_GET_IPV6				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6);
+#endif /* CONFIG_NET_STATISTICS_IPV6 */
+
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+#define NET_REQUEST_STATS_GET_IPV6_ND				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6_ND)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6_ND);
+#endif /* CONFIG_NET_STATISTICS_IPV6_ND */
+
+#if defined(CONFIG_NET_STATISTICS_ICMP)
+#define NET_REQUEST_STATS_GET_ICMP				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ICMP)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ICMP);
+#endif /* CONFIG_NET_STATISTICS_ICMP */
+
+#if defined(CONFIG_NET_STATISTICS_UDP)
+#define NET_REQUEST_STATS_GET_UDP				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_UDP)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_UDP);
+#endif /* CONFIG_NET_STATISTICS_UDP */
+
+#if defined(CONFIG_NET_STATISTICS_TCP)
+#define NET_REQUEST_STATS_GET_TCP				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_TCP)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_TCP);
+#endif /* CONFIG_NET_STATISTICS_TCP */
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET)
+#define NET_REQUEST_STATS_GET_ETHERNET				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ETHERNET)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ETHERNET);
+#endif /* CONFIG_NET_STATISTICS_ETHERNET */
+
+#if defined(CONFIG_NET_STATISTICS_PPP)
+#define NET_REQUEST_STATS_GET_PPP				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PPP)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PPP);
+#endif /* CONFIG_NET_STATISTICS_PPP */
+
+#endif /* CONFIG_NET_STATISTICS_USER_API */
+
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+#define NET_REQUEST_STATS_GET_PM				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PM)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM);
+#endif /* CONFIG_NET_STATISTICS_POWER_MANAGEMENT */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_STATS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/net_timeout.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_timeout.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/net_timeout.h	(working copy)
@@ -0,0 +1,67 @@
+/** @file
+ * @brief Network timer with wrap around
+ *
+ * Timer that runs longer than about 49 days needs to calculate wraps.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_
+#define ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_
+
+/**
+ * @brief Network long timeout primitives and helpers
+ * @defgroup net_timeout Network long timeout primitives and helpers
+ * @ingroup networking
+ * @{
+ */
+
+#include <string.h>
+#include <zephyr/types.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Let the max timeout be 100 ms lower because of
+ * possible rounding in delayed work implementation.
+ */
+#define NET_TIMEOUT_MAX_VALUE ((uint32_t)(INT32_MAX - 100))
+
+/** Generic struct for handling network timeouts */
+struct net_timeout {
+	/** Used to track timers */
+	sys_snode_t node;
+
+	/** Address lifetime timer start time */
+	uint32_t timer_start;
+
+	/** Address lifetime timer timeout in milliseconds. Note that this
+	 * value is signed as k_delayed_work_submit() only supports signed
+	 * delay value.
+	 */
+	int32_t timer_timeout;
+
+	/** Timer wrap count. Used if the timer timeout is larger than
+	 * about 24 days. The reason we need to track wrap arounds, is
+	 * that the timer timeout used in k_delayed_work_submit() is
+	 * 32-bit signed value and the resolution is 1ms.
+	 */
+	int32_t wrap_counter;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+
+#endif /* ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/openthread.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/openthread.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/openthread.h	(working copy)
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief OpenThread l2 stack public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_OPENTHREAD_H_
+#define ZEPHYR_INCLUDE_NET_OPENTHREAD_H_
+
+/**
+ * @brief OpenThread l2 stack api
+ * @defgroup OpenThread l2 layer
+ * @ingroup networking
+ * @{
+ */
+
+#include <kernel.h>
+
+#include <net/net_if.h>
+
+#include <openthread/instance.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+/**
+ * @brief Type of pkt_list
+ */
+struct pkt_list_elem {
+	struct net_pkt *pkt;
+};
+
+/**
+ * @brief OpenThread l2 private data.
+ */
+struct openthread_context {
+	/** Pointer to OpenThread stack instance */
+	otInstance *instance;
+
+	/** Pointer to OpenThread network interface */
+	struct net_if *iface;
+
+	/** Index indicates the head of pkt_list ring buffer */
+	uint16_t pkt_list_in_idx;
+
+	/** Index indicates the tail of pkt_list ring buffer */
+	uint16_t pkt_list_out_idx;
+
+	/** Flag indicates that pkt_list is full */
+	uint8_t pkt_list_full;
+
+	/** Array for storing net_pkt for OpenThread internal usage */
+	struct pkt_list_elem pkt_list[CONFIG_OPENTHREAD_PKT_LIST_SIZE];
+
+	/** A mutex to protect API calls from being preempted. */
+	struct k_mutex api_lock;
+};
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @brief Sets function which will be called when certain configuration or state
+ * changes within OpenThread.
+ *
+ * @param cb function to call in callback procedure.
+ */
+void openthread_set_state_changed_cb(otStateChangedCallback cb);
+
+/**
+ * @brief Get OpenThread thread identification.
+ */
+k_tid_t openthread_thread_id_get(void);
+
+/**
+ * @brief Get pointer to default OpenThread context.
+ *
+ * @retval !NULL On success.
+ * @retval NULL  On failure.
+ */
+struct openthread_context *openthread_get_default_context(void);
+
+/**
+ * @brief Get pointer to default OpenThread instance.
+ *
+ * @retval !NULL On success.
+ * @retval NULL  On failure.
+ */
+struct otInstance *openthread_get_default_instance(void);
+
+/**
+ * @brief Starts the OpenThread network.
+ *
+ * @details Depends on active settings: it uses stored network configuration,
+ * start joining procedure or uses default network configuration. Additionally
+ * when the device is MTD, it sets the SED mode to properly attach the network.
+ *
+ * @param ot_context
+ */
+int openthread_start(struct openthread_context *ot_context);
+
+/**
+ * @brief Lock internal mutex before accessing OT API.
+ *
+ * @details OpenThread API is not thread-safe, therefore before accessing any
+ * API function, it's needed to lock the internal mutex, to prevent the
+ * OpenThread thread from prempting the API call.
+ *
+ * @param ot_context Context to lock.
+ */
+void openthread_api_mutex_lock(struct openthread_context *ot_context);
+
+/**
+ * @brief Unlock internal mutex after accessing OT API.
+ *
+ * @param ot_context Context to unlock.
+ */
+void openthread_api_mutex_unlock(struct openthread_context *ot_context);
+
+#define OPENTHREAD_L2_CTX_TYPE struct openthread_context
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_OPENTHREAD_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ppp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ppp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ppp.h	(working copy)
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#ifndef ZEPHYR_INCLUDE_NET_PPP_H_
+#define ZEPHYR_INCLUDE_NET_PPP_H_
+
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Point-to-point (PPP) L2/driver support functions
+ * @defgroup ppp PPP L2/driver Support Functions
+ * @ingroup networking
+ * @{
+ */
+
+/** PPP maximum receive unit (MRU) */
+#define PPP_MRU 1500
+
+/** PPP maximum transfer unit (MTU) */
+#define PPP_MTU PPP_MRU
+
+/** Max length of terminate description string */
+#define PPP_MAX_TERMINATE_REASON_LEN 32
+
+/** Length of network interface identifier */
+#define PPP_INTERFACE_IDENTIFIER_LEN 8
+
+/** PPP L2 API */
+struct ppp_api {
+	/**
+	 * The net_if_api must be placed in first position in this
+	 * struct so that we are compatible with network interface API.
+	 */
+	struct net_if_api iface_api;
+
+	/** Start the device */
+	int (*start)(const struct device *dev);
+
+	/** Stop the device */
+	int (*stop)(const struct device *dev);
+
+	/** Send a network packet */
+	int (*send)(const struct device *dev, struct net_pkt *pkt);
+
+#if defined(CONFIG_NET_STATISTICS_PPP)
+	/** Collect optional PPP specific statistics. This pointer
+	 * should be set by driver if statistics needs to be collected
+	 * for that driver.
+	 */
+	struct net_stats_ppp *(*get_stats)(const struct device *dev);
+#endif
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * PPP API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct ppp_api, iface_api) == 0);
+
+/**
+ * PPP protocol types.
+ * See https://www.iana.org/assignments/ppp-numbers/ppp-numbers.xhtml
+ * for details.
+ */
+enum ppp_protocol_type {
+	PPP_IP     = 0x0021, /**< RFC 1332 */
+	PPP_IPV6   = 0x0057, /**< RFC 5072 */
+	PPP_IPCP   = 0x8021, /**< RFC 1332 */
+	PPP_ECP    = 0x8053, /**< RFC 1968 */
+	PPP_IPV6CP = 0x8057, /**< RFC 5072 */
+	PPP_CCP    = 0x80FD, /**< RFC 1962 */
+	PPP_LCP    = 0xc021, /**< RFC 1661 */
+	PPP_PAP    = 0xc023, /**< RFC 1334 */
+	PPP_CHAP   = 0xc223, /**< RFC 1334 */
+	PPP_EAP    = 0xc227, /**< RFC 2284 */
+};
+
+/**
+ * PPP phases
+ */
+enum ppp_phase {
+	/** Physical-layer not ready */
+	PPP_DEAD,
+	/** Link is being established */
+	PPP_ESTABLISH,
+	/** Link authentication with peer */
+	PPP_AUTH,
+	/** Network connection establishment */
+	PPP_NETWORK,
+	/** Network running */
+	PPP_RUNNING,
+	/** Link termination */
+	PPP_TERMINATE,
+};
+
+/**
+ * PPP states, RFC 1661 ch. 4.2
+ */
+enum ppp_state {
+	PPP_INITIAL,
+	PPP_STARTING,
+	PPP_CLOSED,
+	PPP_STOPPED,
+	PPP_CLOSING,
+	PPP_STOPPING,
+	PPP_REQUEST_SENT,
+	PPP_ACK_RECEIVED,
+	PPP_ACK_SENT,
+	PPP_OPENED
+};
+
+/**
+ * PPP protocol operations from RFC 1661
+ */
+enum ppp_packet_type {
+	PPP_CONFIGURE_REQ  = 1,
+	PPP_CONFIGURE_ACK  = 2,
+	PPP_CONFIGURE_NACK = 3,
+	PPP_CONFIGURE_REJ  = 4,
+	PPP_TERMINATE_REQ  = 5,
+	PPP_TERMINATE_ACK  = 6,
+	PPP_CODE_REJ       = 7,
+	PPP_PROTOCOL_REJ   = 8,
+	PPP_ECHO_REQ       = 9,
+	PPP_ECHO_REPLY     = 10,
+	PPP_DISCARD_REQ    = 11
+};
+
+/**
+ * LCP option types from RFC 1661 ch. 6
+ */
+enum lcp_option_type {
+	LCP_OPTION_RESERVED = 0,
+
+	/** Maximum-Receive-Unit */
+	LCP_OPTION_MRU = 1,
+
+	/** Async-Control-Character-Map */
+	LCP_OPTION_ASYNC_CTRL_CHAR_MAP = 2,
+
+	/** Authentication-Protocol */
+	LCP_OPTION_AUTH_PROTO = 3,
+
+	/** Quality-Protocol */
+	LCP_OPTION_QUALITY_PROTO = 4,
+
+	/** Magic-Number */
+	LCP_OPTION_MAGIC_NUMBER = 5,
+
+	/** Protocol-Field-Compression */
+	LCP_OPTION_PROTO_COMPRESS = 7,
+
+	/** Address-and-Control-Field-Compression */
+	LCP_OPTION_ADDR_CTRL_COMPRESS = 8
+} __packed;
+
+/**
+ * IPCP option types from RFC 1332
+ */
+enum ipcp_option_type {
+	IPCP_OPTION_RESERVED = 0,
+
+	/** IP Addresses */
+	IPCP_OPTION_IP_ADDRESSES = 1,
+
+	/** IP Compression Protocol */
+	IPCP_OPTION_IP_COMP_PROTO = 2,
+
+	/** IP Address */
+	IPCP_OPTION_IP_ADDRESS = 3,
+
+	/* RFC 1877 */
+
+	/** Primary DNS Server Address */
+	IPCP_OPTION_DNS1 = 129,
+
+	/** Primary NBNS Server Address */
+	IPCP_OPTION_NBNS1 = 130,
+
+	/** Secondary DNS Server Address */
+	IPCP_OPTION_DNS2 = 131,
+
+	/** Secondary NBNS Server Address */
+	IPCP_OPTION_NBNS2 = 132,
+} __packed;
+
+/**
+ * IPV6CP option types from RFC 5072
+ */
+enum ipv6cp_option_type {
+	IPV6CP_OPTION_RESERVED = 0,
+
+	/** Interface identifier */
+	IPV6CP_OPTION_INTERFACE_IDENTIFIER = 1,
+} __packed;
+
+/**
+ * @typedef net_ppp_lcp_echo_reply_cb_t
+ * @brief A callback function that can be called if a Echo-Reply needs to
+ *        be received.
+ * @param user_data User settable data that is passed to the callback
+ *        function.
+ * @param user_data_len Length of the user data.
+ */
+typedef void (*net_ppp_lcp_echo_reply_cb_t)(void *user_data,
+					    size_t user_data_len);
+
+struct ppp_my_option_data;
+struct ppp_my_option_info;
+
+/**
+ * Generic PPP Finite State Machine
+ */
+struct ppp_fsm {
+	/** Timeout timer */
+	struct k_delayed_work timer;
+
+	struct {
+		/** Acknowledge Configuration Information */
+		int (*config_info_ack)(struct ppp_fsm *fsm,
+				       struct net_pkt *pkt,
+				       uint16_t length);
+
+		/** Add Configuration Information */
+		struct net_pkt *(*config_info_add)(struct ppp_fsm *fsm);
+
+		/** Length of Configuration Information */
+		int  (*config_info_len)(struct ppp_fsm *fsm);
+
+		/** Negative Acknowledge Configuration Information */
+		int (*config_info_nack)(struct ppp_fsm *fsm,
+					struct net_pkt *pkt,
+					uint16_t length,
+					bool rejected);
+
+		/** Request peer's Configuration Information */
+		int (*config_info_req)(struct ppp_fsm *fsm,
+				       struct net_pkt *pkt,
+				       uint16_t length,
+				       struct net_pkt *ret_pkt);
+
+		/** Reject Configuration Information */
+		int (*config_info_rej)(struct ppp_fsm *fsm,
+				       struct net_pkt *pkt,
+				       uint16_t length);
+
+		/** Reset Configuration Information */
+		void (*config_info_reset)(struct ppp_fsm *fsm);
+
+		/** FSM goes to OPENED state */
+		void (*up)(struct ppp_fsm *fsm);
+
+		/** FSM leaves OPENED state */
+		void (*down)(struct ppp_fsm *fsm);
+
+		/** Starting this protocol */
+		void (*starting)(struct ppp_fsm *fsm);
+
+		/** Quitting this protocol */
+		void (*finished)(struct ppp_fsm *fsm);
+
+		/** We received Protocol-Reject */
+		void (*proto_reject)(struct ppp_fsm *fsm);
+
+		/** Retransmit */
+		void (*retransmit)(struct ppp_fsm *fsm);
+
+		/** Any code that is not understood by PPP is passed to
+		 * this FSM for further processing.
+		 */
+		enum net_verdict (*proto_extension)(struct ppp_fsm *fsm,
+						    enum ppp_packet_type code,
+						    uint8_t id,
+						    struct net_pkt *pkt);
+	} cb;
+
+	struct {
+		/** Options information */
+		const struct ppp_my_option_info *info;
+
+		/** Options negotiation data */
+		struct ppp_my_option_data *data;
+
+		/** Number of negotiated options */
+		size_t count;
+	} my_options;
+
+	/** Option bits */
+	uint32_t flags;
+
+	/** Number of re-transmissions left */;
+	uint32_t retransmits;
+
+	/** Number of NACK loops since last ACK */
+	uint32_t nack_loops;
+
+	/** Number of NACKs received */
+	uint32_t recv_nack_loops;
+
+	/** Reason for closing protocol */
+	char terminate_reason[PPP_MAX_TERMINATE_REASON_LEN];
+
+	/** PPP protocol number for this FSM */
+	uint16_t protocol;
+
+	/** Current state of PPP link */
+	enum ppp_state state;
+
+	/** Protocol/layer name of this FSM (for debugging) */
+	const char *name;
+
+	/** Current id */
+	uint8_t id;
+
+	/** Current request id */
+	uint8_t req_id;
+
+	/** Have received valid Ack, Nack or Reject to a Request */
+	uint8_t ack_received : 1;
+};
+
+#define PPP_MY_OPTION_ACKED	BIT(0)
+#define PPP_MY_OPTION_REJECTED	BIT(1)
+
+struct ppp_my_option_data {
+	uint32_t flags;
+};
+
+struct lcp_options {
+	/** Magic number */
+	uint32_t magic;
+
+	/** Async char map */
+	uint32_t async_map;
+
+	/** Maximum Receive Unit value */
+	uint16_t mru;
+
+	/** Which authentication protocol was negotiated (0 means none) */
+	uint16_t auth_proto;
+};
+
+struct ipcp_options {
+	/** IPv4 address */
+	struct in_addr address;
+	struct in_addr dns1_address;
+	struct in_addr dns2_address;
+};
+
+#define IPCP_NUM_MY_OPTIONS	3
+
+struct ipv6cp_options {
+	/** Interface identifier */
+	uint8_t iid[PPP_INTERFACE_IDENTIFIER_LEN];
+};
+
+#define IPV6CP_NUM_MY_OPTIONS	1
+
+/** PPP L2 context specific to certain network interface */
+struct ppp_context {
+	/** PPP startup worker. */
+	struct k_delayed_work startup;
+
+	struct {
+		/** Carrier ON/OFF handler worker. This is used to create
+		 * network interface UP/DOWN event when PPP L2 driver
+		 * notices carrier ON/OFF situation. We must not create another
+		 * network management event from inside management handler thus
+		 * we use worker thread to trigger the UP/DOWN event.
+		 */
+		struct k_work work;
+
+		/** Is the carrier enabled already */
+		bool enabled;
+	} carrier_mgmt;
+
+	struct {
+		/** Finite state machine for LCP */
+		struct ppp_fsm fsm;
+
+		/** Options that we want to request */
+		struct lcp_options my_options;
+
+		/** Options that peer want to request */
+		struct lcp_options peer_options;
+
+		/** Magic-Number value */
+		uint32_t magic;
+	} lcp;
+
+#if defined(CONFIG_NET_IPV4)
+	struct {
+		/** Finite state machine for IPCP */
+		struct ppp_fsm fsm;
+
+		/** Options that we want to request */
+		struct ipcp_options my_options;
+
+		/** Options that peer want to request */
+		struct ipcp_options peer_options;
+
+		/** My options runtime data */
+		struct ppp_my_option_data my_options_data[IPCP_NUM_MY_OPTIONS];
+	} ipcp;
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+	struct {
+		/** Finite state machine for IPV6CP */
+		struct ppp_fsm fsm;
+
+		/** Options that we want to request */
+		struct ipv6cp_options my_options;
+
+		/** Options that peer want to request */
+		struct ipv6cp_options peer_options;
+
+		/** My options runtime data */
+		struct ppp_my_option_data my_options_data[IPV6CP_NUM_MY_OPTIONS];
+	} ipv6cp;
+#endif
+
+#if defined(CONFIG_NET_L2_PPP_PAP)
+	struct {
+		/** Finite state machine for PAP */
+		struct ppp_fsm fsm;
+	} pap;
+#endif
+
+#if defined(CONFIG_NET_SHELL)
+	struct {
+		struct {
+			/** Callback to be called when Echo-Reply is received.
+			 */
+			net_ppp_lcp_echo_reply_cb_t cb;
+
+			/** User specific data for the callback */
+			void *user_data;
+
+			/** User data length */
+			size_t user_data_len;
+		} echo_reply;
+
+		/** Used when waiting Echo-Reply */
+		struct k_sem wait_echo_reply;
+
+		/** Echo-Req data value */
+		uint32_t echo_req_data;
+
+		/** Echo-Reply data value */
+		uint32_t echo_reply_data;
+	} shell;
+#endif
+
+	/** Network interface related to this PPP connection */
+	struct net_if *iface;
+
+	/** Current phase of PPP link */
+	enum ppp_phase phase;
+
+	/** This tells what features the PPP supports. */
+	enum net_l2_flags ppp_l2_flags;
+
+	/** This tells how many network protocols are open */
+	int network_protos_open;
+
+	/** This tells how many network protocols are up */
+	int network_protos_up;
+
+	/** Is PPP ready to receive packets */
+	uint16_t is_ready_to_serve : 1;
+
+	/** Is PPP L2 enabled or not */
+	uint16_t is_enabled : 1;
+
+	/** PPP startup pending */
+	uint16_t is_startup_pending : 1;
+
+	/** PPP enable pending */
+	uint16_t is_enable_done : 1;
+
+	/** IPCP status (up / down) */
+	uint16_t is_ipcp_up : 1;
+
+	/** IPCP open status (open / closed) */
+	uint16_t is_ipcp_open : 1;
+
+	/** IPV6CP status (up / down) */
+	uint16_t is_ipv6cp_up : 1;
+
+	/** IPV6CP open status (open / closed) */
+	uint16_t is_ipv6cp_open : 1;
+
+	/** PAP status (up / down) */
+	uint16_t is_pap_up : 1;
+
+	/** PAP open status (open / closed) */
+	uint16_t is_pap_open : 1;
+};
+
+/**
+ * @brief Inform PPP L2 driver that carrier is detected.
+ * This happens when cable is connected etc.
+ *
+ * @param iface Network interface
+ */
+void net_ppp_carrier_on(struct net_if *iface);
+
+/**
+ * @brief Inform PPP L2 driver that carrier was lost.
+ * This happens when cable is disconnected etc.
+ *
+ * @param iface Network interface
+ */
+void net_ppp_carrier_off(struct net_if *iface);
+
+/**
+ * @brief Initialize PPP L2 stack for a given interface
+ *
+ * @param iface A valid pointer to a network interface
+ */
+void net_ppp_init(struct net_if *iface);
+
+/* Management API for PPP */
+
+/** @cond INTERNAL_HIDDEN */
+
+#define PPP_L2_CTX_TYPE	struct ppp_context
+
+#define _NET_PPP_LAYER	NET_MGMT_LAYER_L2
+#define _NET_PPP_CODE	0x209
+#define _NET_PPP_BASE	(NET_MGMT_IFACE_BIT |				\
+			 NET_MGMT_LAYER(_NET_PPP_LAYER) |		\
+			 NET_MGMT_LAYER_CODE(_NET_PPP_CODE))
+#define _NET_PPP_EVENT	(_NET_PPP_BASE | NET_MGMT_EVENT_BIT)
+
+enum net_event_ppp_cmd {
+	NET_EVENT_PPP_CMD_CARRIER_ON = 1,
+	NET_EVENT_PPP_CMD_CARRIER_OFF,
+};
+
+#define NET_EVENT_PPP_CARRIER_ON					\
+	(_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_ON)
+
+#define NET_EVENT_PPP_CARRIER_OFF					\
+	(_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_OFF)
+
+struct net_if;
+
+/** @endcond */
+
+/**
+ * @brief Raise CARRIER_ON event when PPP is connected.
+ *
+ * @param iface PPP network interface.
+ */
+#if defined(CONFIG_NET_L2_PPP_MGMT)
+void ppp_mgmt_raise_carrier_on_event(struct net_if *iface);
+#else
+static inline void ppp_mgmt_raise_carrier_on_event(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif
+
+/**
+ * @brief Raise CARRIER_OFF event when PPP is disconnected.
+ *
+ * @param iface PPP network interface.
+ */
+#if defined(CONFIG_NET_L2_PPP_MGMT)
+void ppp_mgmt_raise_carrier_off_event(struct net_if *iface);
+#else
+static inline void ppp_mgmt_raise_carrier_off_event(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+}
+#endif
+
+/**
+ * @brief Send PPP Echo-Request to peer. We expect to receive Echo-Reply back.
+ *
+ * @param idx PPP network interface index
+ * @param timeout Amount of time to wait Echo-Reply. The value is in
+ * milliseconds.
+ *
+ * @return 0 if Echo-Reply was received, < 0 if there is a timeout or network
+ * index is not a valid PPP network index.
+ */
+#if defined(CONFIG_NET_L2_PPP)
+int net_ppp_ping(int idx, int32_t timeout);
+#else
+static inline int net_ppp_ping(int idx, int32_t timeout)
+{
+	ARG_UNUSED(idx);
+	ARG_UNUSED(timeout);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Get PPP context information. This is only used by net-shell to
+ * print information about PPP.
+ *
+ * @param idx PPP network interface index
+ *
+ * @return PPP context or NULL if idx is invalid.
+ */
+#if defined(CONFIG_NET_L2_PPP) && defined(CONFIG_NET_SHELL)
+struct ppp_context *net_ppp_context_get(int idx);
+#else
+static inline struct ppp_context *net_ppp_context_get(int idx)
+{
+	ARG_UNUSED(idx);
+
+	return NULL;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_PPP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/promiscuous.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/promiscuous.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/promiscuous.h	(working copy)
@@ -0,0 +1,93 @@
+/** @file
+ * @brief Network interface promiscuous mode support
+ *
+ * An API for applications to start listening network traffic.
+ * This requires support from network device driver and from application.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_PROMISCUOUS_H_
+#define ZEPHYR_INCLUDE_NET_PROMISCUOUS_H_
+
+/**
+ * @brief Promiscuous mode support.
+ * @defgroup promiscuous Promiscuous mode
+ * @ingroup networking
+ * @{
+ */
+
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Start to wait received network packets.
+ *
+ * @param timeout How long to wait before returning.
+ *
+ * @return Received net_pkt, NULL if not received any packet.
+ */
+#if defined(CONFIG_NET_PROMISCUOUS_MODE)
+struct net_pkt *net_promisc_mode_wait_data(k_timeout_t timeout);
+#else
+static inline struct net_pkt *net_promisc_mode_wait_data(k_timeout_t timeout)
+{
+	ARG_UNUSED(timeout);
+
+	return NULL;
+}
+#endif /* CONFIG_NET_PROMISCUOUS_MODE */
+
+/**
+ * @brief Enable promiscuous mode for a given network interface.
+ *
+ * @param iface Network interface
+ *
+ * @return 0 if ok, <0 if error
+ */
+#if defined(CONFIG_NET_PROMISCUOUS_MODE)
+int net_promisc_mode_on(struct net_if *iface);
+#else
+static inline int net_promisc_mode_on(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+
+	return -ENOTSUP;
+}
+#endif /* CONFIG_NET_PROMISCUOUS_MODE */
+
+/**
+ * @brief Disable promiscuous mode for a given network interface.
+ *
+ * @param iface Network interface
+ *
+ * @return 0 if ok, <0 if error
+ */
+#if defined(CONFIG_NET_PROMISCUOUS_MODE)
+int net_promisc_mode_off(struct net_if *iface);
+#else
+static inline int net_promisc_mode_off(struct net_if *iface)
+{
+	ARG_UNUSED(iface);
+
+	return -ENOTSUP;
+}
+#endif /* CONFIG_NET_PROMISCUOUS_MODE */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_PROMISCUOUS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/ptp_time.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ptp_time.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/ptp_time.h	(working copy)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public functions for the Precision Time Protocol time specification.
+ *
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_PTP_TIME_H_
+#define ZEPHYR_INCLUDE_NET_PTP_TIME_H_
+
+/**
+ * @brief Precision Time Protocol time specification
+ * @defgroup ptp_time PTP time
+ * @ingroup networking
+ * @{
+ */
+
+#include <net/net_core.h>
+#include <toolchain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Precision Time Protocol Timestamp format.
+ *
+ * This structure represents a timestamp according
+ * to the Precision Time Protocol standard.
+ *
+ * Seconds are encoded as a 48 bits unsigned integer.
+ * Nanoseconds are encoded as a 32 bits unsigned integer.
+ */
+struct net_ptp_time {
+	/** Seconds encoded on 48 bits. */
+	union {
+		struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+			uint32_t low;
+			uint16_t high;
+			uint16_t unused;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+			uint16_t unused;
+			uint16_t high;
+			uint32_t low;
+#else
+#error "Unknown byte order"
+#endif
+		} _sec;
+		uint64_t second;
+	};
+
+	/** Nanoseconds. */
+	uint32_t nanosecond;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @brief Precision Time Protocol Extended Timestamp format.
+ *
+ * This structure represents an extended timestamp according
+ * to the Precision Time Protocol standard.
+ *
+ * Seconds are encoded as 48 bits unsigned integer.
+ * Fractional nanoseconds are encoded as 48 bits, their unit
+ * is 2*(-16) ns.
+ */
+struct net_ptp_extended_time {
+	/** Seconds encoded on 48 bits. */
+	union {
+		struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+			uint32_t low;
+			uint16_t high;
+			uint16_t unused;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+			uint16_t unused;
+			uint16_t high;
+			uint32_t low;
+#else
+#error "Unknown byte order"
+#endif
+		} _sec;
+		uint64_t second;
+	};
+
+	/** Fractional nanoseconds on 48 bits. */
+	union {
+		struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+			uint32_t low;
+			uint16_t high;
+			uint16_t unused;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+			uint16_t unused;
+			uint16_t high;
+			uint32_t low;
+#else
+#error "Unknown byte order"
+#endif
+		} _fns;
+		uint64_t fract_nsecond;
+	};
+} __packed;
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_PTP_TIME_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/sntp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/sntp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/sntp.h	(working copy)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SNTP_H_
+#define ZEPHYR_INCLUDE_NET_SNTP_H_
+
+#ifdef CONFIG_NET_SOCKETS_POSIX_NAMES
+#include <net/socket.h>
+#else
+#include <posix/sys/socket.h>
+#include <posix/unistd.h>
+#include <posix/poll.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Simple Network Time Protocol API
+ * @defgroup sntp SNTP
+ * @ingroup networking
+ * @{
+ */
+
+/** SNTP context */
+struct sntp_ctx {
+	struct {
+		struct pollfd fds[1];
+		int nfds;
+		int fd;
+	} sock;
+
+	/** Timestamp when the request was sent from client to server.
+	 *  This is used to check if the originated timestamp in the server
+	 *  reply matches the one in client request.
+	 */
+	uint32_t expected_orig_ts;
+};
+
+/** Time as returned by SNTP API, fractional seconds since 1 Jan 1970 */
+struct sntp_time {
+	uint64_t seconds;
+	uint32_t fraction;
+};
+
+/**
+ * @brief Initialize SNTP context
+ *
+ * @param ctx Address of sntp context.
+ * @param addr IP address of NTP/SNTP server.
+ * @param addr_len IP address length of NTP/SNTP server.
+ *
+ * @return 0 if ok, <0 if error.
+ */
+int sntp_init(struct sntp_ctx *ctx, struct sockaddr *addr,
+	      socklen_t addr_len);
+
+/**
+ * @brief Perform SNTP query
+ *
+ * @param ctx Address of sntp context.
+ * @param timeout Timeout of waiting for sntp response (in milliseconds).
+ * @param time Timestamp including integer and fractional seconds since
+ * 1 Jan 1970 (output).
+ *
+ * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
+ */
+int sntp_query(struct sntp_ctx *ctx, uint32_t timeout,
+	       struct sntp_time *time);
+
+/**
+ * @brief Release SNTP context
+ *
+ * @param ctx Address of sntp context.
+ */
+void sntp_close(struct sntp_ctx *ctx);
+
+/**
+ * @brief Convenience function to query SNTP in one-shot fashion
+ *
+ * Convenience wrapper which calls getaddrinfo(), sntp_init(),
+ * sntp_query(), and sntp_close().
+ *
+ * @param server Address of server in format addr[:port]
+ * @param timeout Query timeout
+ * @param time Timestamp including integer and fractional seconds since
+ * 1 Jan 1970 (output).
+ *
+ * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
+ */
+int sntp_simple(const char *server, uint32_t timeout,
+		struct sntp_time *time);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/net/socket.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket.h	(working copy)
@@ -0,0 +1,847 @@
+/**
+ * @file
+ * @brief BSD Sockets compatible API definitions
+ *
+ * An API for applications to use BSD Sockets like API.
+ */
+
+/*
+ * Copyright (c) 2017-2018 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKET_H_
+#define ZEPHYR_INCLUDE_NET_SOCKET_H_
+
+/**
+ * @brief BSD Sockets compatible API
+ * @defgroup bsd_sockets BSD Sockets compatible API
+ * @ingroup networking
+ * @{
+ */
+
+#include <sys/types.h>
+#include <zephyr/types.h>
+#include <net/net_ip.h>
+#include <net/dns_resolve.h>
+#include <net/socket_select.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct zsock_pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+/* ZSOCK_POLL* values are compatible with Linux */
+/** zsock_poll: Poll for readability */
+#define ZSOCK_POLLIN 1
+/** zsock_poll: Compatibility value, ignored */
+#define ZSOCK_POLLPRI 2
+/** zsock_poll: Poll for writability */
+#define ZSOCK_POLLOUT 4
+/** zsock_poll: Poll results in error condition (output value only) */
+#define ZSOCK_POLLERR 8
+/** zsock_poll: Poll detected closed connection (output value only) */
+#define ZSOCK_POLLHUP 0x10
+/** zsock_poll: Invalid socket (output value only) */
+#define ZSOCK_POLLNVAL 0x20
+
+/** zsock_recv: Read data without removing it from socket input queue */
+#define ZSOCK_MSG_PEEK 0x02
+/** zsock_recv/zsock_send: Override operation to non-blocking */
+#define ZSOCK_MSG_DONTWAIT 0x40
+
+/* Well-known values, e.g. from Linux man 2 shutdown:
+ * "The constants SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2,
+ * respectively". Some software uses numeric values.
+ */
+/** zsock_shutdown: Shut down for reading */
+#define ZSOCK_SHUT_RD 0
+/** zsock_shutdown: Shut down for writing */
+#define ZSOCK_SHUT_WR 1
+/** zsock_shutdown: Shut down for both reading and writing */
+#define ZSOCK_SHUT_RDWR 2
+
+/** Protocol level for TLS.
+ *  Here, the same socket protocol level for TLS as in Linux was used.
+ */
+#define SOL_TLS 282
+
+/**
+ *  @defgroup secure_sockets_options Socket options for TLS
+ *  @{
+ */
+
+/** Socket option to select TLS credentials to use. It accepts and returns an
+ *  array of sec_tag_t that indicate which TLS credentials should be used with
+ *  specific socket.
+ */
+#define TLS_SEC_TAG_LIST 1
+/** Write-only socket option to set hostname. It accepts a string containing
+ *  the hostname (may be NULL to disable hostname verification). By default,
+ *  hostname check is enforced for TLS clients.
+ */
+#define TLS_HOSTNAME 2
+/** Socket option to select ciphersuites to use. It accepts and returns an array
+ *  of integers with IANA assigned ciphersuite identifiers.
+ *  If not set, socket will allow all ciphersuites available in the system
+ *  (mebdTLS default behavior).
+ */
+#define TLS_CIPHERSUITE_LIST 3
+/** Read-only socket option to read a ciphersuite chosen during TLS handshake.
+ *  It returns an integer containing an IANA assigned ciphersuite identifier
+ *  of chosen ciphersuite.
+ */
+#define TLS_CIPHERSUITE_USED 4
+/** Write-only socket option to set peer verification level for TLS connection.
+ *  This option accepts an integer with a peer verification level, compatible
+ *  with mbedTLS values:
+ *    - 0 - none
+ *    - 1 - optional
+ *    - 2 - required
+ *
+ *  If not set, socket will use mbedTLS defaults (none for servers, required
+ *  for clients).
+ */
+#define TLS_PEER_VERIFY 5
+/** Write-only socket option to set role for DTLS connection. This option
+ *  is irrelevant for TLS connections, as for them role is selected based on
+ *  connect()/listen() usage. By default, DTLS will assume client role.
+ *  This option accepts an integer with a TLS role, compatible with
+ *  mbedTLS values:
+ *    - 0 - client
+ *    - 1 - server
+ */
+#define TLS_DTLS_ROLE 6
+
+/** @} */
+
+/* Valid values for TLS_PEER_VERIFY option */
+#define TLS_PEER_VERIFY_NONE 0     /**< Peer verification disabled. */
+#define TLS_PEER_VERIFY_OPTIONAL 1 /**< Peer verification optional. */
+#define TLS_PEER_VERIFY_REQUIRED 2 /**< Peer verification required. */
+
+/* Valid values for TLS_DTLS_ROLE option */
+#define TLS_DTLS_ROLE_CLIENT 0 /**< Client role in a DTLS session. */
+#define TLS_DTLS_ROLE_SERVER 1 /**< Server role in a DTLS session. */
+
+struct zsock_addrinfo {
+	struct zsock_addrinfo *ai_next;
+	int ai_flags;
+	int ai_family;
+	int ai_socktype;
+	int ai_protocol;
+	socklen_t ai_addrlen;
+	struct sockaddr *ai_addr;
+	char *ai_canonname;
+
+	struct sockaddr _ai_addr;
+	char _ai_canonname[DNS_MAX_NAME_SIZE + 1];
+};
+
+/**
+ * @brief Obtain a file descriptor's associated net context
+ *
+ * With CONFIG_USERSPACE enabled, the kernel's object permission system
+ * must apply to socket file descriptors. When a socket is opened, by default
+ * only the caller has permission, access by other threads will fail unless
+ * they have been specifically granted permission.
+ *
+ * This is achieved by tagging data structure definitions that implement the
+ * underlying object associated with a network socket file descriptor with
+ * '__net_socket`. All pointers to instances of these will be known to the
+ * kernel as kernel objects with type K_OBJ_NET_SOCKET.
+ *
+ * This API is intended for threads that need to grant access to the object
+ * associated with a particular file descriptor to another thread. The
+ * returned pointer represents the underlying K_OBJ_NET_SOCKET  and
+ * may be passed to APIs like k_object_access_grant().
+ *
+ * In a system like Linux which has the notion of threads running in processes
+ * in a shared virtual address space, this sort of management is unnecessary as
+ * the scope of file descriptors is implemented at the process level.
+ *
+ * However in Zephyr the file descriptor scope is global, and MPU-based systems
+ * are not able to implement a process-like model due to the lack of memory
+ * virtualization hardware. They use discrete object permissions and memory
+ * domains instead to define thread access scope.
+ *
+ * User threads will have no direct access to the returned object
+ * and will fault if they try to access its memory; the pointer can only be
+ * used to make permission assignment calls, which follow exactly the rules
+ * for other kernel objects like device drivers and IPC.
+ *
+ * @param sock file descriptor
+ * @return pointer to associated network socket object, or NULL if the
+ *         file descriptor wasn't valid or the caller had no access permission
+ */
+__syscall void *zsock_get_context_object(int sock);
+
+/**
+ * @brief Create a network socket
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html>`__
+ * for normative description.
+ * This function is also exposed as ``socket()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ *
+ * If CONFIG_USERSPACE is enabled, the caller will be granted access to the
+ * context object associated with the returned file descriptor.
+ * @see zsock_get_context_object()
+ *
+ */
+__syscall int zsock_socket(int family, int type, int proto);
+
+/**
+ * @brief Create an unnamed pair of connected sockets
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <https://pubs.opengroup.org/onlinepubs/009695399/functions/socketpair.html>`__
+ * for normative description.
+ * This function is also exposed as ``socketpair()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_socketpair(int family, int type, int proto, int *sv);
+
+/**
+ * @brief Close a network socket
+ *
+ * @details
+ * @rst
+ * Close a network socket.
+ * This function is also exposed as ``close()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined (in which case it
+ * may conflict with generic POSIX ``close()`` function).
+ * @endrst
+ */
+__syscall int zsock_close(int sock);
+
+/**
+ * @brief Shutdown socket send/receive operations
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html>`__
+ * for normative description, but currently this function has no effect in
+ * Zephyr and provided solely for compatibility with existing code.
+ * This function is also exposed as ``shutdown()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_shutdown(int sock, int how);
+
+/**
+ * @brief Bind a socket to a local network address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html>`__
+ * for normative description.
+ * This function is also exposed as ``bind()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_bind(int sock, const struct sockaddr *addr,
+			 socklen_t addrlen);
+
+/**
+ * @brief Connect a socket to a peer network address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html>`__
+ * for normative description.
+ * This function is also exposed as ``connect()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_connect(int sock, const struct sockaddr *addr,
+			    socklen_t addrlen);
+
+/**
+ * @brief Set up a STREAM socket to accept peer connections
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html>`__
+ * for normative description.
+ * This function is also exposed as ``listen()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_listen(int sock, int backlog);
+
+/**
+ * @brief Accept a connection on listening socket
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html>`__
+ * for normative description.
+ * This function is also exposed as ``accept()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_accept(int sock, struct sockaddr *addr, socklen_t *addrlen);
+
+/**
+ * @brief Send data to an arbitrary network address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html>`__
+ * for normative description.
+ * This function is also exposed as ``sendto()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall ssize_t zsock_sendto(int sock, const void *buf, size_t len,
+			       int flags, const struct sockaddr *dest_addr,
+			       socklen_t addrlen);
+
+/**
+ * @brief Send data to a connected peer
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html>`__
+ * for normative description.
+ * This function is also exposed as ``send()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+static inline ssize_t zsock_send(int sock, const void *buf, size_t len,
+				 int flags)
+{
+	return zsock_sendto(sock, buf, len, flags, NULL, 0);
+}
+
+/**
+ * @brief Send data to an arbitrary network address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html>`__
+ * for normative description.
+ * This function is also exposed as ``sendmsg()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall ssize_t zsock_sendmsg(int sock, const struct msghdr *msg,
+				int flags);
+
+/**
+ * @brief Receive data from an arbitrary network address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html>`__
+ * for normative description.
+ * This function is also exposed as ``recvfrom()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall ssize_t zsock_recvfrom(int sock, void *buf, size_t max_len,
+				 int flags, struct sockaddr *src_addr,
+				 socklen_t *addrlen);
+
+/**
+ * @brief Receive data from a connected peer
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html>`__
+ * for normative description.
+ * This function is also exposed as ``recv()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+static inline ssize_t zsock_recv(int sock, void *buf, size_t max_len,
+				 int flags)
+{
+	return zsock_recvfrom(sock, buf, max_len, flags, NULL, NULL);
+}
+
+/**
+ * @brief Control blocking/non-blocking mode of a socket
+ *
+ * @details
+ * @rst
+ * This functions allow to (only) configure a socket for blocking or
+ * non-blocking operation (O_NONBLOCK).
+ * This function is also exposed as ``fcntl()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined (in which case
+ * it may conflict with generic POSIX ``fcntl()`` function).
+ * @endrst
+ */
+__syscall int zsock_fcntl(int sock, int cmd, int flags);
+
+/**
+ * @brief Efficiently poll multiple sockets for events
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html>`__
+ * for normative description. (In Zephyr this function works only with
+ * sockets, not arbitrary file descriptors.)
+ * This function is also exposed as ``poll()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined (in which case
+ * it may conflict with generic POSIX ``poll()`` function).
+ * @endrst
+ */
+__syscall int zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout);
+
+/**
+ * @brief Get various socket options
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html>`__
+ * for normative description. In Zephyr this function supports a subset of
+ * socket options described by POSIX, but also some additional options
+ * available in Linux (some options are dummy and provided to ease porting
+ * of existing code).
+ * This function is also exposed as ``getsockopt()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_getsockopt(int sock, int level, int optname,
+			       void *optval, socklen_t *optlen);
+
+/**
+ * @brief Set various socket options
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html>`__
+ * for normative description. In Zephyr this function supports a subset of
+ * socket options described by POSIX, but also some additional options
+ * available in Linux (some options are dummy and provided to ease porting
+ * of existing code).
+ * This function is also exposed as ``setsockopt()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_setsockopt(int sock, int level, int optname,
+			       const void *optval, socklen_t optlen);
+
+/**
+ * @brief Get socket name
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html>`__
+ * for normative description.
+ * This function is also exposed as ``getsockname()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_getsockname(int sock, struct sockaddr *addr,
+				socklen_t *addrlen);
+
+/**
+ * @brief Get local host name
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html>`__
+ * for normative description.
+ * This function is also exposed as ``gethostname()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_gethostname(char *buf, size_t len);
+
+/**
+ * @brief Convert network address from internal to numeric ASCII form
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/inet_ntop.html>`__
+ * for normative description.
+ * This function is also exposed as ``inet_ntop()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+static inline char *zsock_inet_ntop(sa_family_t family, const void *src,
+				    char *dst, size_t size)
+{
+	return net_addr_ntop(family, src, dst, size);
+}
+
+/**
+ * @brief Convert network address from numeric ASCII form to internal representation
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/inet_pton.html>`__
+ * for normative description.
+ * This function is also exposed as ``inet_pton()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+__syscall int zsock_inet_pton(sa_family_t family, const char *src, void *dst);
+
+/** @cond INTERNAL_HIDDEN */
+__syscall int z_zsock_getaddrinfo_internal(const char *host,
+					   const char *service,
+					   const struct zsock_addrinfo *hints,
+					   struct zsock_addrinfo *res);
+/** @endcond */
+
+/* Flags for getaddrinfo() hints. */
+
+/** Address for bind() (vs for connect()) */
+#define AI_PASSIVE 0x1
+/** Fill in ai_canonname */
+#define AI_CANONNAME 0x2
+/** Assume host address is in numeric notation, don't DNS lookup */
+#define AI_NUMERICHOST 0x4
+/** May return IPv4 mapped address for IPv6  */
+#define AI_V4MAPPED 0x8
+/** May return both native IPv6 and mapped IPv4 address for IPv6 */
+#define AI_ALL 0x10
+/** IPv4/IPv6 support depends on local system config */
+#define AI_ADDRCONFIG 0x20
+/** Assume service (port) is numeric */
+#define AI_NUMERICSERV 0x400
+
+/**
+ * @brief Resolve a domain name to one or more network addresses
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html>`__
+ * for normative description.
+ * This function is also exposed as ``getaddrinfo()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+int zsock_getaddrinfo(const char *host, const char *service,
+		      const struct zsock_addrinfo *hints,
+		      struct zsock_addrinfo **res);
+
+/**
+ * @brief Free results returned by zsock_getaddrinfo()
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html>`__
+ * for normative description.
+ * This function is also exposed as ``freeaddrinfo()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+void zsock_freeaddrinfo(struct zsock_addrinfo *ai);
+
+/**
+ * @brief Convert zsock_getaddrinfo() error code to textual message
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/gai_strerror.html>`__
+ * for normative description.
+ * This function is also exposed as ``gai_strerror()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+const char *zsock_gai_strerror(int errcode);
+
+/** zsock_getnameinfo(): Resolve to numeric address. */
+#define NI_NUMERICHOST 1
+/** zsock_getnameinfo(): Resolve to numeric port number. */
+#define NI_NUMERICSERV 2
+/** zsock_getnameinfo(): Return only hostname instead of FQDN */
+#define NI_NOFQDN 4
+/** zsock_getnameinfo(): Dummy option for compatibility */
+#define NI_NAMEREQD 8
+/** zsock_getnameinfo(): Dummy option for compatibility */
+#define NI_DGRAM 16
+
+/* POSIX extensions */
+
+/** zsock_getnameinfo(): Max supported hostname length */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 64
+#endif
+
+/**
+ * @brief Resolve a network address to a domain name or ASCII address
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getnameinfo.html>`__
+ * for normative description.
+ * This function is also exposed as ``getnameinfo()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+int zsock_getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
+		      char *host, socklen_t hostlen,
+		      char *serv, socklen_t servlen, int flags);
+
+#if defined(CONFIG_NET_SOCKETS_POSIX_NAMES)
+
+#define pollfd zsock_pollfd
+
+static inline int socket(int family, int type, int proto)
+{
+	return zsock_socket(family, type, proto);
+}
+
+static inline int socketpair(int family, int type, int proto, int sv[2])
+{
+	return zsock_socketpair(family, type, proto, sv);
+}
+
+static inline int close(int sock)
+{
+	return zsock_close(sock);
+}
+
+static inline int shutdown(int sock, int how)
+{
+	return zsock_shutdown(sock, how);
+}
+
+static inline int bind(int sock, const struct sockaddr *addr, socklen_t addrlen)
+{
+	return zsock_bind(sock, addr, addrlen);
+}
+
+static inline int connect(int sock, const struct sockaddr *addr,
+			  socklen_t addrlen)
+{
+	return zsock_connect(sock, addr, addrlen);
+}
+
+static inline int listen(int sock, int backlog)
+{
+	return zsock_listen(sock, backlog);
+}
+
+static inline int accept(int sock, struct sockaddr *addr, socklen_t *addrlen)
+{
+	return zsock_accept(sock, addr, addrlen);
+}
+
+static inline ssize_t send(int sock, const void *buf, size_t len, int flags)
+{
+	return zsock_send(sock, buf, len, flags);
+}
+
+static inline ssize_t recv(int sock, void *buf, size_t max_len, int flags)
+{
+	return zsock_recv(sock, buf, max_len, flags);
+}
+
+/* This conflicts with fcntl.h, so code must include fcntl.h before socket.h: */
+#define fcntl zsock_fcntl
+
+static inline ssize_t sendto(int sock, const void *buf, size_t len, int flags,
+			     const struct sockaddr *dest_addr,
+			     socklen_t addrlen)
+{
+	return zsock_sendto(sock, buf, len, flags, dest_addr, addrlen);
+}
+
+static inline ssize_t sendmsg(int sock, const struct msghdr *message,
+			      int flags)
+{
+	return zsock_sendmsg(sock, message, flags);
+}
+
+static inline ssize_t recvfrom(int sock, void *buf, size_t max_len, int flags,
+			       struct sockaddr *src_addr, socklen_t *addrlen)
+{
+	return zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen);
+}
+
+static inline int poll(struct zsock_pollfd *fds, int nfds, int timeout)
+{
+	return zsock_poll(fds, nfds, timeout);
+}
+
+static inline int getsockopt(int sock, int level, int optname,
+			     void *optval, socklen_t *optlen)
+{
+	return zsock_getsockopt(sock, level, optname, optval, optlen);
+}
+
+static inline int setsockopt(int sock, int level, int optname,
+			     const void *optval, socklen_t optlen)
+{
+	return zsock_setsockopt(sock, level, optname, optval, optlen);
+}
+
+static inline int getsockname(int sock, struct sockaddr *addr,
+			      socklen_t *addrlen)
+{
+	return zsock_getsockname(sock, addr, addrlen);
+}
+
+static inline int getaddrinfo(const char *host, const char *service,
+			      const struct zsock_addrinfo *hints,
+			      struct zsock_addrinfo **res)
+{
+	return zsock_getaddrinfo(host, service, hints, res);
+}
+
+static inline void freeaddrinfo(struct zsock_addrinfo *ai)
+{
+	zsock_freeaddrinfo(ai);
+}
+
+static inline const char *gai_strerror(int errcode)
+{
+	return zsock_gai_strerror(errcode);
+}
+
+static inline int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
+			      char *host, socklen_t hostlen,
+			      char *serv, socklen_t servlen, int flags)
+{
+	return zsock_getnameinfo(addr, addrlen, host, hostlen,
+				 serv, servlen, flags);
+}
+
+#define addrinfo zsock_addrinfo
+
+static inline int gethostname(char *buf, size_t len)
+{
+	return zsock_gethostname(buf, len);
+}
+
+static inline int inet_pton(sa_family_t family, const char *src, void *dst)
+{
+	return zsock_inet_pton(family, src, dst);
+}
+
+static inline char *inet_ntop(sa_family_t family, const void *src, char *dst,
+			      size_t size)
+{
+	return zsock_inet_ntop(family, src, dst, size);
+}
+
+#define POLLIN ZSOCK_POLLIN
+#define POLLOUT ZSOCK_POLLOUT
+#define POLLERR ZSOCK_POLLERR
+#define POLLHUP ZSOCK_POLLHUP
+#define POLLNVAL ZSOCK_POLLNVAL
+
+#define MSG_PEEK ZSOCK_MSG_PEEK
+#define MSG_DONTWAIT ZSOCK_MSG_DONTWAIT
+
+#define SHUT_RD ZSOCK_SHUT_RD
+#define SHUT_WR ZSOCK_SHUT_WR
+#define SHUT_RDWR ZSOCK_SHUT_RDWR
+
+#define EAI_BADFLAGS DNS_EAI_BADFLAGS
+#define EAI_NONAME DNS_EAI_NONAME
+#define EAI_AGAIN DNS_EAI_AGAIN
+#define EAI_FAIL DNS_EAI_FAIL
+#define EAI_NODATA DNS_EAI_NODATA
+#define EAI_MEMORY DNS_EAI_MEMORY
+#define EAI_SYSTEM DNS_EAI_SYSTEM
+#define EAI_SERVICE DNS_EAI_SERVICE
+#endif /* defined(CONFIG_NET_SOCKETS_POSIX_NAMES) */
+
+/** sockopt: Socket-level option */
+#define SOL_SOCKET 1
+
+/* Socket options for SOL_SOCKET level */
+/** sockopt: Enable server address reuse (ignored, for compatibility) */
+#define SO_REUSEADDR 2
+/** sockopt: Async error (ignored, for compatibility) */
+#define SO_ERROR 4
+
+/** sockopt: Timestamp TX packets */
+#define SO_TIMESTAMPING 37
+
+/* Socket options for IPPROTO_TCP level */
+/** sockopt: Disable TCP buffering (ignored, for compatibility) */
+#define TCP_NODELAY 1
+
+/* Socket options for IPPROTO_IPV6 level */
+/** sockopt: Don't support IPv4 access (ignored, for compatibility) */
+#define IPV6_V6ONLY 26
+
+/** sockopt: Socket priority */
+#define SO_PRIORITY 12
+
+/** sockopt: Socket TX time (when the data should be sent) */
+#define SO_TXTIME 61
+#define SCM_TXTIME SO_TXTIME
+
+/* Socket options for SOCKS5 proxy */
+/** sockopt: Enable SOCKS5 for Socket */
+#define SO_SOCKS5 60
+
+/** @cond INTERNAL_HIDDEN */
+/**
+ * @brief Registration information for a given BSD socket family.
+ */
+struct net_socket_register {
+	int family;
+	bool (*is_supported)(int family, int type, int proto);
+	int (*handler)(int family, int type, int proto);
+};
+
+#define NET_SOCKET_GET_NAME(socket_name)	\
+	(__net_socket_register_##socket_name)
+
+#define NET_SOCKET_REGISTER(socket_name, _family, _is_supported, _handler) \
+	static const Z_STRUCT_SECTION_ITERABLE(net_socket_register,	\
+			NET_SOCKET_GET_NAME(socket_name)) = {		\
+		.family = _family,					\
+		.is_supported = _is_supported,				\
+		.handler = _handler,					\
+	}
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/socket.h>
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKET_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/socket_can.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_can.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_can.h	(working copy)
@@ -0,0 +1,95 @@
+/** @file
+ * @brief Socket CAN definitions.
+ *
+ * Definitions for socket CAN support.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKET_CAN_H_
+#define ZEPHYR_INCLUDE_NET_SOCKET_CAN_H_
+
+#include <zephyr/types.h>
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <drivers/can.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Socket CAN library
+ * @defgroup socket_can Network Core Library
+ * @ingroup networking
+ * @{
+ */
+
+/* Protocols of the protocol family PF_CAN */
+#define CAN_RAW 1
+
+/* Socket CAN options */
+#define SOL_CAN_BASE 100
+#define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW)
+
+enum {
+	CAN_RAW_FILTER = 1,
+};
+
+/* Socket CAN MTU size */
+#define CAN_MTU		CAN_MAX_DLEN
+
+/**
+ * struct sockaddr_can - The sockaddr structure for CAN sockets
+ *
+ */
+struct sockaddr_can {
+	sa_family_t can_family;
+	int         can_ifindex;
+};
+
+/**
+ * CAN L2 driver API. Used by socket CAN.
+ */
+struct canbus_api {
+	/**
+	 * The net_if_api must be placed in first position in this
+	 * struct so that we are compatible with network interface API.
+	 */
+	struct net_if_api iface_api;
+
+	/** Send a CAN packet by socket */
+	int (*send)(const struct device *dev, struct net_pkt *pkt);
+
+	/** Close the related CAN socket */
+	void (*close)(const struct device *dev, int filter_id);
+
+	/** Set socket CAN option */
+	int (*setsockopt)(const struct device *dev, void *obj, int level,
+			  int optname,
+			  const void *optval, socklen_t optlen);
+
+	/** Get socket CAN option */
+	int (*getsockopt)(const struct device *dev, void *obj, int level,
+			  int optname,
+			  const void *optval, socklen_t *optlen);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * CANBUS API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct canbus_api, iface_api) == 0);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKET_CAN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/socket_net_mgmt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_net_mgmt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_net_mgmt.h	(working copy)
@@ -0,0 +1,107 @@
+/** @file
+ * @brief NET_MGMT socket definitions.
+ *
+ * Definitions for NET_MGMT socket support.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKET_NET_MGMT_H_
+#define ZEPHYR_INCLUDE_NET_SOCKET_NET_MGMT_H_
+
+#include <zephyr/types.h>
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Socket NET_MGMT library
+ * @defgroup socket_net_mgmt Network Core Library
+ * @ingroup networking
+ * @{
+ */
+
+/* Protocols of the protocol family PF_NET_MGMT */
+#define NET_MGMT_EVENT_PROTO 0x01
+
+/* Socket NET_MGMT options */
+#define SOL_NET_MGMT_BASE 100
+#define SOL_NET_MGMT_RAW (SOL_NET_MGMT_BASE + 1)
+
+/**
+ * struct sockaddr_nm - The sockaddr structure for NET_MGMT sockets
+ *
+ * Similar concepts are used as in Linux AF_NETLINK. The NETLINK name is not
+ * used in order to avoid confusion between Zephyr and Linux as the
+ * implementations are different.
+ *
+ * The socket domain (address family) is AF_NET_MGMT, and the type of socket
+ * is either SOCK_RAW or SOCK_DGRAM, because this is a datagram-oriented
+ * service.
+ *
+ * The protocol (protocol type) selects for which feature the socket is used.
+ *
+ * When used with bind(), the nm_pid field of the sockaddr_nm can be
+ * filled with the calling thread' own id. The nm_pid serves here as the local
+ * address of this net_mgmt socket. The application is responsible for picking
+ * a unique integer value to fill in nm_pid.
+ */
+struct sockaddr_nm {
+	/** AF_NET_MGMT address family. */
+	sa_family_t nm_family;
+
+	/** Network interface related to this address */
+	int nm_ifindex;
+
+	/** Thread id or similar that is used to separate the different
+	 * sockets. Application can decide how the pid is constructed.
+	 */
+	uintptr_t nm_pid;
+
+	/** net_mgmt mask */
+	uint32_t nm_mask;
+};
+
+
+/**
+ * Each network management message is prefixed with this header.
+ */
+struct net_mgmt_msghdr {
+	/** Network management version */
+	uint32_t nm_msg_version;
+
+	/** Length of the data */
+	uint32_t nm_msg_len;
+
+	/** The actual message data follows */
+	uint8_t nm_msg[];
+};
+
+/**
+ * Version of the message is placed to the header. Currently we have
+ * following versions.
+ *
+ * Network management message versions:
+ *
+ *  0x0001 : The net_mgmt event info message follows directly
+ *           after the header.
+ */
+#define NET_MGMT_SOCKET_VERSION_1 0x0001
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKET_NET_MGMT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/socket_offload.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_offload.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_offload.h	(working copy)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Linaro Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Socket Offload Redirect API
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKET_OFFLOAD_H_
+#define ZEPHYR_INCLUDE_NET_SOCKET_OFFLOAD_H_
+
+#include <net/net_ip.h>
+#include <net/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief An offloaded Socket DNS API interface
+ *
+ * It is assumed that these offload functions follow the
+ * POSIX socket API standard for arguments, return values and setting of errno.
+ */
+struct socket_dns_offload {
+	int (*getaddrinfo)(const char *node, const char *service,
+			   const struct zsock_addrinfo *hints,
+			   struct zsock_addrinfo **res);
+	void (*freeaddrinfo)(struct zsock_addrinfo *res);
+};
+
+/**
+ * @brief Register an offloaded socket DNS API interface.
+ *
+ * @param ops A pointer to the offloaded socket DNS API interface.
+ */
+void socket_offload_dns_register(const struct socket_dns_offload *ops);
+
+int socket_offload_getaddrinfo(const char *node, const char *service,
+			       const struct zsock_addrinfo *hints,
+			       struct zsock_addrinfo **res);
+
+void socket_offload_freeaddrinfo(struct zsock_addrinfo *res);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKET_OFFLOAD_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/socket_select.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_select.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socket_select.h	(working copy)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_
+#define ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_
+
+/**
+ * @brief BSD Sockets compatible API
+ * @defgroup bsd_sockets BSD Sockets compatible API
+ * @ingroup networking
+ * @{
+ */
+
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct zsock_timeval {
+	/* Using longs, as many (?) implementations seem to use it. */
+	long tv_sec;
+	long tv_usec;
+};
+
+typedef struct zsock_fd_set {
+	uint32_t bitset[(CONFIG_POSIX_MAX_FDS + 31) / 32];
+} zsock_fd_set;
+
+
+/**
+ * @brief Legacy function to poll multiple sockets for events
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html>`__
+ * for normative description. This function is provided to ease porting of
+ * existing code and not recommended for usage due to its inefficiency,
+ * use :c:func:`zsock_poll()` instead. In Zephyr this function works only with
+ * sockets, not arbitrary file descriptors.
+ * This function is also exposed as ``select()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined (in which case
+ * it may conflict with generic POSIX ``select()`` function).
+ * @endrst
+ */
+int zsock_select(int nfds, zsock_fd_set *readfds, zsock_fd_set *writefds,
+		 zsock_fd_set *exceptfds, struct zsock_timeval *timeout);
+
+/** Number of file descriptors which can be added to zsock_fd_set */
+#define ZSOCK_FD_SETSIZE (sizeof(((zsock_fd_set *)0)->bitset) * 8)
+
+/**
+ * @brief Initialize (clear) fd_set
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html>`__
+ * for normative description.
+ * This function is also exposed as ``FD_ZERO()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+void ZSOCK_FD_ZERO(zsock_fd_set *set);
+
+/**
+ * @brief Check whether socket is a member of fd_set
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html>`__
+ * for normative description.
+ * This function is also exposed as ``FD_ISSET()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+int ZSOCK_FD_ISSET(int fd, zsock_fd_set *set);
+
+/**
+ * @brief Remove socket from fd_set
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html>`__
+ * for normative description.
+ * This function is also exposed as ``FD_CLR()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+void ZSOCK_FD_CLR(int fd, zsock_fd_set *set);
+
+/**
+ * @brief Add socket to fd_set
+ *
+ * @details
+ * @rst
+ * See `POSIX.1-2017 article
+ * <http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html>`__
+ * for normative description.
+ * This function is also exposed as ``FD_SET()``
+ * if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
+ * @endrst
+ */
+void ZSOCK_FD_SET(int fd, zsock_fd_set *set);
+
+#ifdef CONFIG_NET_SOCKETS_POSIX_NAMES
+
+#define fd_set zsock_fd_set
+#define timeval zsock_timeval
+#define FD_SETSIZE ZSOCK_FD_SETSIZE
+
+static inline int select(int nfds, zsock_fd_set *readfds,
+			 zsock_fd_set *writefds, zsock_fd_set *exceptfds,
+			 struct timeval *timeout)
+{
+	return zsock_select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+static inline void FD_ZERO(zsock_fd_set *set)
+{
+	ZSOCK_FD_ZERO(set);
+}
+
+static inline int FD_ISSET(int fd, zsock_fd_set *set)
+{
+	return ZSOCK_FD_ISSET(fd, set);
+}
+
+static inline void FD_CLR(int fd, zsock_fd_set *set)
+{
+	ZSOCK_FD_CLR(fd, set);
+}
+
+static inline void FD_SET(int fd, zsock_fd_set *set)
+{
+	ZSOCK_FD_SET(fd, set);
+}
+
+#endif /* CONFIG_NET_SOCKETS_POSIX_NAMES */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/socketutils.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socketutils.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/socketutils.h	(working copy)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef CONFIG_NET_SOCKETS_POSIX_NAMES
+#include <net/socket.h>
+#else
+#include <posix/netdb.h>
+#endif
+
+/**
+ * @brief Find port in addr:port string.
+ *
+ * @param addr_str String of addr[:port] format
+ *
+ * @return Pointer to "port" part, or NULL is none.
+ */
+const char *net_addr_str_find_port(const char *addr_str);
+
+/**
+ * @brief Call getaddrinfo() on addr:port string
+ *
+ * Convenience function to split addr[:port] string into address vs port
+ * components (or use default port number), and call getaddrinfo() on the
+ * result.
+ *
+ * @param addr_str String of addr[:port] format
+ * @param def_port Default port number to use if addr_str doesn't contain it
+ * @param hints getaddrinfo() hints
+ * @param res Result of getaddrinfo() (freeaddrinfo() should be called on it
+ *            as usual.
+ *
+ * @return Result of getaddrinfo() call.
+ */
+int net_getaddrinfo_addr_str(const char *addr_str, const char *def_port,
+			     const struct addrinfo *hints,
+			     struct addrinfo **res);
Index: ModuleDemo/BLE/CM0/User/include/net/tftp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/tftp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/tftp.h	(working copy)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 InnBlue
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file tftp.h
+ *
+ *  @brief Zephyr TFTP Implementation
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_TFTP_H_
+#define ZEPHYR_INCLUDE_NET_TFTP_H_
+
+#include <zephyr.h>
+#include <net/socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct tftpc {
+	uint8_t   *user_buf;
+	uint32_t  user_buf_size;
+};
+
+/* TFTP Client Error codes. */
+#define TFTPC_SUCCESS             0
+#define TFTPC_DUPLICATE_DATA     -1
+#define TFTPC_BUFFER_OVERFLOW    -2
+#define TFTPC_UNKNOWN_FAILURE    -3
+#define TFTPC_REMOTE_ERROR       -4
+#define TFTPC_RETRIES_EXHAUSTED  -5
+
+/* @brief This function gets "file" from the remote server.
+ *
+ * @param server      Control Block that represents the remote server.
+ * @param client      Client Buffer Information.
+ * @param remote_file Name of the remote file to get.
+ * @param mode        TFTP Client "mode" setting
+ *
+ * @return TFTPC_SUCCESS if the operation completed successfully.
+ *         TFTPC_BUFFER_OVERFLOW if the file is larger than the user buffer.
+ *         TFTPC_REMOTE_ERROR if the server failed to process our request.
+ *         TFTPC_RETRIES_EXHAUSTED if the client timed out waiting for server.
+ */
+int tftp_get(struct sockaddr *server, struct tftpc *client,
+	     const char *remote_file, const char *mode);
+
+#endif /* ZEPHYR_INCLUDE_NET_TFTP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/tls_credentials.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/tls_credentials.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/tls_credentials.h	(working copy)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief TLS credentials management
+ *
+ * An API for applications to configure TLS credentials.
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_TLS_CREDENTIALS_H_
+#define ZEPHYR_INCLUDE_NET_TLS_CREDENTIALS_H_
+
+/**
+ * @brief TLS credentials management
+ * @defgroup tls_credentials TLS credentials management
+ * @ingroup networking
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** TLS credential types */
+enum tls_credential_type {
+	/** Unspecified credential. */
+	TLS_CREDENTIAL_NONE,
+
+	/** A trusted CA certificate. Use this to authenticate remote servers.
+	 *  Used with certificate-based ciphersuites.
+	 */
+	TLS_CREDENTIAL_CA_CERTIFICATE,
+
+	/** A public server certificate. Use this to register your own server
+	 *  certificate. Should be registered together with a corresponding
+	 *  private key. Used with certificate-based ciphersuites.
+	 */
+	TLS_CREDENTIAL_SERVER_CERTIFICATE,
+
+	/** Private key. Should be registered together with a corresponding
+	 *  public certificate. Used with certificate-based ciphersuites.
+	 */
+	TLS_CREDENTIAL_PRIVATE_KEY,
+
+	/** Pre-shared key. Should be registered together with a corresponding
+	 *  PSK identity. Used with PSK-based ciphersuites.
+	 */
+	TLS_CREDENTIAL_PSK,
+
+	/** Pre-shared key identity. Should be registered together with a
+	 *  corresponding PSK. Used with PSK-based ciphersuites.
+	 */
+	TLS_CREDENTIAL_PSK_ID
+};
+
+/** Secure tag, a reference to TLS credential
+ *
+ * Secure tag can be used to reference credential after it was registered
+ * in the system.
+ *
+ * @note Some TLS credentials come in pairs:
+ *    - TLS_CREDENTIAL_SERVER_CERTIFICATE with TLS_CREDENTIAL_PRIVATE_KEY,
+ *    - TLS_CREDENTIAL_PSK with TLS_CREDENTIAL_PSK_ID.
+ *    Such pairs of credentials must be assigned the same secure tag to be
+ *    correctly handled in the system.
+ */
+typedef int sec_tag_t;
+
+/**
+ * @brief Add a TLS credential.
+ *
+ * @details This function adds a TLS credential, that can be used
+ *          by TLS/DTLS for authentication.
+ *
+ * @param tag     A security tag that credential will be referenced with.
+ * @param type    A TLS/DTLS credential type.
+ * @param cred    A TLS/DTLS credential.
+ * @param credlen A TLS/DTLS credential length.
+ *
+ * @retval 0 TLS credential successfully added.
+ * @retval -EACCES Access to the TLS credential subsystem was denied.
+ * @retval -ENOMEM Not enough memory to add new TLS credential.
+ * @retval -EEXIST TLS credential of specific tag and type already exists.
+ */
+int tls_credential_add(sec_tag_t tag, enum tls_credential_type type,
+		       const void *cred, size_t credlen);
+
+/**
+ * @brief Get a TLS credential.
+ *
+ * @details This function gets an already registered TLS credential,
+ *          referenced by @p tag secure tag of @p type.
+ *
+ * @param tag     A security tag of requested credential.
+ * @param type    A TLS/DTLS credential type of requested credential.
+ * @param cred    A buffer for TLS/DTLS credential.
+ * @param credlen A buffer size on input. TLS/DTLS credential length on output.
+ *
+ * @retval 0 TLS credential successfully obtained.
+ * @retval -EACCES Access to the TLS credential subsystem was denied.
+ * @retval -ENOENT Requested TLS credential was not found.
+ * @retval -EFBIG Requested TLS credential does not fit in the buffer provided.
+ */
+int tls_credential_get(sec_tag_t tag, enum tls_credential_type type,
+		       void *cred, size_t *credlen);
+
+/**
+ * @brief Delete a TLS credential.
+ *
+ * @details This function removes a TLS credential, referenced by @p tag
+ *          secure tag of @p type.
+ *
+ * @param tag  A security tag corresponding to removed credential.
+ * @param type A TLS/DTLS credential type of removed credential.
+ *
+ * @retval 0 TLS credential successfully deleted.
+ * @retval -EACCES Access to the TLS credential subsystem was denied.
+ * @retval -ENOENT Requested TLS credential was not found.
+ */
+int tls_credential_delete(sec_tag_t tag, enum tls_credential_type type);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_TLS_CREDENTIALS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/trickle.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/trickle.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/trickle.h	(working copy)
@@ -0,0 +1,149 @@
+/** @file
+ * @brief Trickle timer library
+ *
+ * This implements Trickle timer as specified in RFC 6206
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_TRICKLE_H_
+#define ZEPHYR_INCLUDE_NET_TRICKLE_H_
+
+#include <stdbool.h>
+#include <zephyr/types.h>
+
+#include <kernel.h>
+#include <net/net_core.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Trickle algorithm library
+ * @defgroup trickle Trickle Algorithm Library
+ * @ingroup networking
+ * @{
+ */
+
+struct net_trickle;
+
+/**
+ * @typedef net_trickle_cb_t
+ * @brief Trickle timer callback.
+ *
+ * @details The callback is called after Trickle timeout expires.
+ *
+ * @param trickle The trickle context to use.
+ * @param do_suppress Is TX allowed (true) or not (false).
+ * @param user_data The user data given in net_trickle_start() call.
+ */
+typedef void (*net_trickle_cb_t)(struct net_trickle *trickle,
+				 bool do_suppress, void *user_data);
+
+/**
+ * The variable names are taken directly from RFC 6206 when applicable.
+ * Note that the struct members should not be accessed directly but
+ * only via the Trickle API.
+ */
+struct net_trickle {
+	uint32_t Imin;		/**< Min interval size in ms */
+	uint8_t Imax;		/**< Max number of doublings */
+	uint8_t k;		/**< Redundancy constant */
+
+	uint32_t I;		/**< Current interval size */
+	uint32_t Istart;	/**< Start of the interval in ms */
+	uint8_t c;		/**< Consistency counter */
+
+	uint32_t Imax_abs;	/**< Max interval size in ms (not doublings) */
+
+	struct k_delayed_work timer;
+	net_trickle_cb_t cb;	/**< Callback to be called when timer expires */
+	void *user_data;
+};
+
+/** @cond INTERNAL_HIDDEN */
+#define NET_TRICKLE_INFINITE_REDUNDANCY 0
+/** @endcond */
+
+/**
+ * @brief Create a Trickle timer.
+ *
+ * @param trickle Pointer to Trickle struct.
+ * @param Imin Imin configuration parameter in ms.
+ * @param Imax Max number of doublings.
+ * @param k Redundancy constant parameter. See RFC 6206 for details.
+ *
+ * @return Return 0 if ok and <0 if error.
+ */
+int net_trickle_create(struct net_trickle *trickle,
+		       uint32_t Imin,
+		       uint8_t Imax,
+		       uint8_t k);
+
+/**
+ * @brief Start a Trickle timer.
+ *
+ * @param trickle Pointer to Trickle struct.
+ * @param cb User callback to call at time T within the current trickle
+ * interval
+ * @param user_data User pointer that is passed to callback.
+ *
+ * @return Return 0 if ok and <0 if error.
+ */
+int net_trickle_start(struct net_trickle *trickle,
+		      net_trickle_cb_t cb,
+		      void *user_data);
+
+/**
+ * @brief Stop a Trickle timer.
+ *
+ * @param trickle Pointer to Trickle struct.
+ *
+ * @return Return 0 if ok and <0 if error.
+ */
+int net_trickle_stop(struct net_trickle *trickle);
+
+/**
+ * @brief To be called by the protocol handler when it hears a consistent
+ * network transmission.
+ *
+ * @param trickle Pointer to Trickle struct.
+ */
+void net_trickle_consistency(struct net_trickle *trickle);
+
+/**
+ * @brief To be called by the protocol handler when it hears an inconsistent
+ * network transmission.
+ *
+ * @param trickle Pointer to Trickle struct.
+ */
+void net_trickle_inconsistency(struct net_trickle *trickle);
+
+/**
+ * @brief Check if the Trickle timer is running or not.
+ *
+ * @param trickle Pointer to Trickle struct.
+ *
+ * @return Return True if timer is running and False if not.
+ */
+static inline bool net_trickle_is_running(struct net_trickle *trickle)
+{
+	NET_ASSERT(trickle);
+
+	return trickle->I != 0U;
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_TRICKLE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/udp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/udp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/udp.h	(working copy)
@@ -0,0 +1,100 @@
+/** @file
+ @brief UDP utility functions
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_UDP_H_
+#define ZEPHYR_INCLUDE_NET_UDP_H_
+
+#include <zephyr/types.h>
+
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These APIs are mostly meant for Zephyr internal use so do not generate
+ * documentation for them.
+ */
+/** @cond INTERNAL_HIDDEN */
+
+/**
+ * @brief UDP library
+ * @defgroup udp UDP Library
+ * @ingroup networking
+ * @{
+ */
+
+/**
+ * @brief Get UDP packet header data from net_pkt.
+ *
+ * @details The values in the returned header are in network byte order.
+ * Note that you must access the UDP header values by the returned pointer,
+ * the hdr parameter is just a placeholder for the header data and it might
+ * not contain anything if the header fits properly in the first fragment of
+ * the network packet.
+ *
+ * @param pkt Network packet
+ * @param hdr Where to place the header if it does not fit in first fragment
+ * of the network packet. This might not be populated if UDP header fits in
+ * net_buf fragment.
+ *
+ * @return Return pointer to header or NULL if something went wrong.
+ *         Always use the returned pointer to access the UDP header.
+ */
+#if defined(CONFIG_NET_UDP)
+struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
+				    struct net_udp_hdr *hdr);
+#else
+static inline struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
+						  struct net_udp_hdr *hdr)
+{
+	return NULL;
+}
+#endif /* CONFIG_NET_UDP */
+
+/**
+ * @brief Set UDP packet header data in net_pkt.
+ *
+ * @details The values in the header must be in network byte order.
+ * This function is normally called after a call to net_udp_get_hdr().
+ * The hdr parameter value should be the same that is returned by function
+ * net_udp_get_hdr() call. Note that if the UDP header fits in first net_pkt
+ * fragment, then this function will not do anything as your hdr parameter
+ * was pointing directly to net_pkt.
+ *
+ * @param pkt Network packet
+ * @param hdr Header data pointer that was returned by net_udp_get_hdr().
+ *
+ * @return Return pointer to header or NULL if something went wrong.
+ */
+#if defined(CONFIG_NET_UDP)
+struct net_udp_hdr *net_udp_set_hdr(struct net_pkt *pkt,
+				    struct net_udp_hdr *hdr);
+#else
+static inline struct net_udp_hdr *net_udp_set_hdr(struct net_pkt *pkt,
+						  struct net_udp_hdr *hdr)
+{
+	return NULL;
+}
+#endif /* CONFIG_NET_UDP */
+
+/**
+ * @}
+ */
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_UDP_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/websocket.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/websocket.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/websocket.h	(working copy)
@@ -0,0 +1,201 @@
+/** @file
+ * @brief Websocket API
+ *
+ * An API for applications to setup websocket connections
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_WEBSOCKET_H_
+#define ZEPHYR_INCLUDE_NET_WEBSOCKET_H_
+
+#include <kernel.h>
+
+#include <net/net_ip.h>
+#include <net/http_parser.h>
+#include <net/http_client.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Websocket API
+ * @defgroup websocket Websocket API
+ * @ingroup networking
+ * @{
+ */
+
+/** Message type values. Returned in websocket_recv_msg() */
+#define WEBSOCKET_FLAG_FINAL  0x00000001 /**< Final frame        */
+#define WEBSOCKET_FLAG_TEXT   0x00000002 /**< Textual data       */
+#define WEBSOCKET_FLAG_BINARY 0x00000004 /**< Binary data        */
+#define WEBSOCKET_FLAG_CLOSE  0x00000008 /**< Closing connection */
+#define WEBSOCKET_FLAG_PING   0x00000010 /**< Ping message       */
+#define WEBSOCKET_FLAG_PONG   0x00000020 /**< Pong message       */
+
+enum websocket_opcode  {
+	WEBSOCKET_OPCODE_CONTINUE     = 0x00,
+	WEBSOCKET_OPCODE_DATA_TEXT    = 0x01,
+	WEBSOCKET_OPCODE_DATA_BINARY  = 0x02,
+	WEBSOCKET_OPCODE_CLOSE        = 0x08,
+	WEBSOCKET_OPCODE_PING         = 0x09,
+	WEBSOCKET_OPCODE_PONG         = 0x0A,
+};
+
+/**
+ * @typedef websocket_connect_cb_t
+ * @brief Callback called after Websocket connection is established.
+ *
+ * @param sock Websocket id
+ * @param req HTTP handshake request
+ * @param user_data A valid pointer on some user data or NULL
+ *
+ * @return 0 if ok, <0 if there is an error and connection should be aborted
+ */
+typedef int (*websocket_connect_cb_t)(int ws_sock, struct http_request *req,
+				      void *user_data);
+
+/**
+ * Websocket client connection request. This contains all the data that is
+ * needed when doing a Websocket connection request.
+ */
+struct websocket_request {
+	/** Host of the Websocket server when doing HTTP handshakes. */
+	const char *host;
+
+	/** URL of the Websocket. */
+	const char *url;
+
+	/** User supplied callback function to call when optional headers need
+	 * to be sent. This can be NULL, in which case the optional_headers
+	 * field in http_request is used. The idea of this optional_headers
+	 * callback is to allow user to send more HTTP header data that is
+	 * practical to store in allocated memory.
+	 */
+	http_header_cb_t optional_headers_cb;
+
+	/** A NULL terminated list of any optional headers that
+	 * should be added to the HTTP request. May be NULL.
+	 * If the optional_headers_cb is specified, then this field is ignored.
+	 */
+	const char **optional_headers;
+
+	/** User supplied callback function to call when a connection is
+	 * established.
+	 */
+	websocket_connect_cb_t cb;
+
+	/** User supplied list of callback functions if the calling application
+	 * wants to know the parsing status or the HTTP fields during the
+	 * handshake. This is optional parameter and normally not needed but
+	 * is useful if the caller wants to know something about
+	 * the fields that the server is sending.
+	 */
+	const struct http_parser_settings *http_cb;
+
+	/** User supplied buffer where HTTP connection data is stored */
+	uint8_t *tmp_buf;
+
+	/** Length of the user supplied temp buffer */
+	size_t tmp_buf_len;
+};
+
+/**
+ * @brief Connect to a server that provides Websocket service. The callback is
+ * called after connection is established. The returned value is a new socket
+ * descriptor that can be used to send / receive data using the BSD socket API.
+ *
+ * @param http_sock Socket id to the server. Note that this socket is used to do
+ *        HTTP handshakes etc. The actual Websocket connectivity is done via the
+ *        returned websocket id. Note that the http_sock must not be closed
+ *        after this function returns as it is used to deliver the Websocket
+ *        packets to the Websocket server.
+ * @param req Websocket request. User should allocate and fill the request
+ *        data.
+ * @param timeout Max timeout to wait for the connection. The timeout value is
+ *        in milliseconds. Value SYS_FOREVER_MS means to wait forever.
+ * @param user_data User specified data that is passed to the callback.
+ *
+ * @return Websocket id to be used when sending/receiving Websocket data.
+ */
+int websocket_connect(int http_sock, struct websocket_request *req,
+		      int32_t timeout, void *user_data);
+
+/**
+ * @brief Send websocket msg to peer.
+ *
+ * @details The function will automatically add websocket header to the
+ * message.
+ *
+ * @param ws_sock Websocket id returned by websocket_connect().
+ * @param payload Websocket data to send.
+ * @param payload_len Length of the data to be sent.
+ * @param opcode Operation code (text, binary, ping, pong, close)
+ * @param mask Mask the data, see RFC 6455 for details
+ * @param final Is this final message for this message send. If final == false,
+ *        then the first message must have valid opcode and subsequent messages
+ *        must have opcode WEBSOCKET_OPCODE_CONTINUE. If final == true and this
+ *        is the only message, then opcode should have proper opcode (text or
+ *        binary) set.
+ * @param timeout How long to try to send the message. The value is in
+ *        milliseconds. Value SYS_FOREVER_MS means to wait forever.
+ *
+ * @return <0 if error, >=0 amount of bytes sent
+ */
+int websocket_send_msg(int ws_sock, const uint8_t *payload, size_t payload_len,
+		       enum websocket_opcode opcode, bool mask, bool final,
+		       int32_t timeout);
+
+/**
+ * @brief Receive websocket msg from peer.
+ *
+ * @details The function will automatically remove websocket header from the
+ * message.
+ *
+ * @param ws_sock Websocket id returned by websocket_connect().
+ * @param buf Buffer where websocket data is read.
+ * @param buf_len Length of the data buffer.
+ * @param message_type Type of the message.
+ * @param remaining How much there is data left in the message after this read.
+ * @param timeout How long to try to receive the message.
+ *        The value is in milliseconds. Value SYS_FOREVER_MS means to wait
+ *        forever.
+ *
+ * @return <0 if error, >=0 amount of bytes received
+ */
+int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len,
+		       uint32_t *message_type, uint64_t *remaining,
+		       int32_t timeout);
+
+/**
+ * @brief Close websocket.
+ *
+ * @details One must call websocket_connect() after this call to re-establish
+ * the connection.
+ *
+ * @param ws_sock Websocket id returned by websocket_connect().
+ */
+int websocket_disconnect(int ws_sock);
+
+#if defined(CONFIG_WEBSOCKET_CLIENT)
+void websocket_init(void);
+#else
+static inline void websocket_init(void)
+{
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_NET_WEBSOCKET_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/wifi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/wifi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/wifi.h	(working copy)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018 Texas Instruments, Incorporated
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief General WiFi Definitions
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_WIFI_H_
+#define ZEPHYR_INCLUDE_NET_WIFI_H_
+
+enum wifi_security_type {
+	WIFI_SECURITY_TYPE_NONE = 0,
+	WIFI_SECURITY_TYPE_PSK,
+};
+
+#define WIFI_SSID_MAX_LEN 32
+#define WIFI_PSK_MAX_LEN 64
+
+#define WIFI_CHANNEL_MAX 14
+#define WIFI_CHANNEL_ANY 255
+
+#endif /* ZEPHYR_INCLUDE_NET_WIFI_H_ */
Index: ModuleDemo/BLE/CM0/User/include/net/wifi_mgmt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/wifi_mgmt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/net/wifi_mgmt.h	(working copy)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief WiFi L2 stack public header
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_WIFI_MGMT_H_
+#define ZEPHYR_INCLUDE_NET_WIFI_MGMT_H_
+
+#include <net/net_mgmt.h>
+#include <net/wifi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Management part definitions */
+
+#define _NET_WIFI_LAYER	NET_MGMT_LAYER_L2
+#define _NET_WIFI_CODE	0x156
+#define _NET_WIFI_BASE	(NET_MGMT_IFACE_BIT |			\
+			 NET_MGMT_LAYER(_NET_WIFI_LAYER) |	\
+			 NET_MGMT_LAYER_CODE(_NET_WIFI_CODE))
+#define _NET_WIFI_EVENT	(_NET_WIFI_BASE | NET_MGMT_EVENT_BIT)
+
+enum net_request_wifi_cmd {
+	NET_REQUEST_WIFI_CMD_SCAN = 1,
+	NET_REQUEST_WIFI_CMD_CONNECT,
+	NET_REQUEST_WIFI_CMD_DISCONNECT,
+	NET_REQUEST_WIFI_CMD_AP_ENABLE,
+	NET_REQUEST_WIFI_CMD_AP_DISABLE,
+};
+
+#define NET_REQUEST_WIFI_SCAN					\
+	(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_SCAN)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN);
+
+#define NET_REQUEST_WIFI_CONNECT				\
+	(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CONNECT)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT);
+
+#define NET_REQUEST_WIFI_DISCONNECT				\
+	(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_DISCONNECT)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT);
+
+#define NET_REQUEST_WIFI_AP_ENABLE				\
+	(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_ENABLE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE);
+
+#define NET_REQUEST_WIFI_AP_DISABLE				\
+	(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_DISABLE)
+
+NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE);
+
+enum net_event_wifi_cmd {
+	NET_EVENT_WIFI_CMD_SCAN_RESULT = 1,
+	NET_EVENT_WIFI_CMD_SCAN_DONE,
+	NET_EVENT_WIFI_CMD_CONNECT_RESULT,
+	NET_EVENT_WIFI_CMD_DISCONNECT_RESULT,
+};
+
+#define NET_EVENT_WIFI_SCAN_RESULT				\
+	(_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_RESULT)
+
+#define NET_EVENT_WIFI_SCAN_DONE				\
+	(_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_DONE)
+
+#define NET_EVENT_WIFI_CONNECT_RESULT				\
+	(_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_CONNECT_RESULT)
+
+#define NET_EVENT_WIFI_DISCONNECT_RESULT			\
+	(_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_RESULT)
+
+
+/* Each result is provided to the net_mgmt_event_callback
+ * via its info attribute (see net_mgmt.h)
+ */
+struct wifi_scan_result {
+	uint8_t ssid[WIFI_SSID_MAX_LEN];
+	uint8_t ssid_length;
+
+	uint8_t channel;
+	enum wifi_security_type security;
+	int8_t rssi;
+};
+
+struct wifi_connect_req_params {
+	uint8_t *ssid;
+	uint8_t ssid_length; /* Max 32 */
+
+	uint8_t *psk;
+	uint8_t psk_length; /* Min 8 - Max 64 */
+
+	uint8_t channel;
+	enum wifi_security_type security;
+};
+
+struct wifi_status {
+	int status;
+};
+
+#include <net/net_if.h>
+
+typedef void (*scan_result_cb_t)(struct net_if *iface, int status,
+				 struct wifi_scan_result *entry);
+
+struct net_wifi_mgmt_offload {
+	/**
+	 * Mandatory to get in first position.
+	 * A network device should indeed provide a pointer on such
+	 * net_if_api structure. So we make current structure pointer
+	 * that can be casted to a net_if_api structure pointer.
+	 */
+	struct net_if_api iface_api;
+
+	/* cb parameter is the cb that should be called for each
+	 * result by the driver. The wifi mgmt part will take care of
+	 * raising the necessary event etc...
+	 */
+	int (*scan)(const struct device *dev, scan_result_cb_t cb);
+	int (*connect)(const struct device *dev,
+		       struct wifi_connect_req_params *params);
+	int (*disconnect)(const struct device *dev);
+	int (*ap_enable)(const struct device *dev,
+			 struct wifi_connect_req_params *params);
+	int (*ap_disable)(const struct device *dev);
+};
+
+/* Make sure that the network interface API is properly setup inside
+ * Wifi mgmt offload API struct (it is the first one).
+ */
+BUILD_ASSERT(offsetof(struct net_wifi_mgmt_offload, iface_api) == 0);
+
+#ifdef CONFIG_WIFI_OFFLOAD
+
+void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status);
+void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status);
+
+#endif /* CONFIG_WIFI_OFFLOAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_WIFI_MGMT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/ptp_clock.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/ptp_clock.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/ptp_clock.h	(working copy)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_PTP_CLOCK_H_
+#define ZEPHYR_INCLUDE_PTP_CLOCK_H_
+
+#include <kernel.h>
+#include <stdint.h>
+#include <device.h>
+#include <sys/util.h>
+#include <net/ptp_time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name of the PTP clock driver */
+#if !defined(PTP_CLOCK_NAME)
+#define PTP_CLOCK_NAME "PTP_CLOCK"
+#endif
+
+__subsystem struct ptp_clock_driver_api {
+	int (*set)(const struct device *dev, struct net_ptp_time *tm);
+	int (*get)(const struct device *dev, struct net_ptp_time *tm);
+	int (*adjust)(const struct device *dev, int increment);
+	int (*rate_adjust)(const struct device *dev, float ratio);
+};
+
+/**
+ * @brief Set the time of the PTP clock.
+ *
+ * @param dev PTP clock device
+ * @param tm Time to set
+ *
+ * @return 0 if ok, <0 if error
+ */
+static inline int ptp_clock_set(const struct device *dev,
+				struct net_ptp_time *tm)
+{
+	const struct ptp_clock_driver_api *api =
+		(const struct ptp_clock_driver_api *)dev->api;
+
+	return api->set(dev, tm);
+}
+
+/**
+ * @brief Get the time of the PTP clock.
+ *
+ * @param dev PTP clock device
+ * @param tm Where to store the current time.
+ *
+ * @return 0 if ok, <0 if error
+ */
+__syscall int ptp_clock_get(const struct device *dev, struct net_ptp_time *tm);
+
+static inline int z_impl_ptp_clock_get(const struct device *dev,
+				       struct net_ptp_time *tm)
+{
+	const struct ptp_clock_driver_api *api =
+		(const struct ptp_clock_driver_api *)dev->api;
+
+	return api->get(dev, tm);
+}
+
+/**
+ * @brief Adjust the PTP clock time.
+ *
+ * @param dev PTP clock device
+ * @param increment Increment of the clock in nanoseconds
+ *
+ * @return 0 if ok, <0 if error
+ */
+static inline int ptp_clock_adjust(const struct device *dev, int increment)
+{
+	const struct ptp_clock_driver_api *api =
+		(const struct ptp_clock_driver_api *)dev->api;
+
+	return api->adjust(dev, increment);
+}
+
+/**
+ * @brief Adjust the PTP clock time change rate when compared to its neighbor.
+ *
+ * @param dev PTP clock device
+ * @param rate Rate of the clock time change
+ *
+ * @return 0 if ok, <0 if error
+ */
+static inline int ptp_clock_rate_adjust(const struct device *dev, float rate)
+{
+	const struct ptp_clock_driver_api *api =
+		(const struct ptp_clock_driver_api *)dev->api;
+
+	return api->rate_adjust(dev, rate);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/ptp_clock.h>
+
+#endif /* ZEPHYR_INCLUDE_PTP_CLOCK_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sched_priq.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sched_priq.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sched_priq.h	(working copy)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_SCHED_PRIQ_H_
+#define ZEPHYR_INCLUDE_SCHED_PRIQ_H_
+
+#include <sys/util.h>
+#include <sys/dlist.h>
+#include <sys/rb.h>
+
+/* Two abstractions are defined here for "thread priority queues".
+ *
+ * One is a "dumb" list implementation appropriate for systems with
+ * small numbers of threads and sensitive to code size.  It is stored
+ * in sorted order, taking an O(N) cost every time a thread is added
+ * to the list.  This corresponds to the way the original _wait_q_t
+ * abstraction worked and is very fast as long as the number of
+ * threads is small.
+ *
+ * The other is a balanced tree "fast" implementation with rather
+ * larger code size (due to the data structure itself, the code here
+ * is just stubs) and higher constant-factor performance overhead, but
+ * much better O(logN) scaling in the presence of large number of
+ * threads.
+ *
+ * Each can be used for either the wait_q or system ready queue,
+ * configurable at build time.
+ */
+
+struct k_thread;
+
+struct k_thread *z_priq_dumb_best(sys_dlist_t *pq);
+void z_priq_dumb_remove(sys_dlist_t *pq, struct k_thread *thread);
+void z_priq_dumb_add(sys_dlist_t *pq, struct k_thread *thread);
+
+struct _priq_rb {
+	struct rbtree tree;
+	int next_order_key;
+};
+
+void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *thread);
+void z_priq_rb_remove(struct _priq_rb *pq, struct k_thread *thread);
+struct k_thread *z_priq_rb_best(struct _priq_rb *pq);
+
+/* Traditional/textbook "multi-queue" structure.  Separate lists for a
+ * small number (max 32 here) of fixed priorities.  This corresponds
+ * to the original Zephyr scheduler.  RAM requirements are
+ * comparatively high, but performance is very fast.  Won't work with
+ * features like deadline scheduling which need large priority spaces
+ * to represent their requirements.
+ */
+struct _priq_mq {
+	sys_dlist_t queues[32];
+	unsigned int bitmask; /* bit 1<<i set if queues[i] is non-empty */
+};
+
+void z_priq_mq_add(struct _priq_mq *pq, struct k_thread *thread);
+void z_priq_mq_remove(struct _priq_mq *pq, struct k_thread *thread);
+struct k_thread *z_priq_mq_best(struct _priq_mq *pq);
+
+#endif /* ZEPHYR_INCLUDE_SCHED_PRIQ_H_ */
Index: ModuleDemo/BLE/CM0/User/include/shared_irq.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/shared_irq.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/shared_irq.h	(working copy)
@@ -0,0 +1,103 @@
+/* shared_irq - Shared interrupt driver */
+
+/*
+ * Copyright (c) 2015 Intel corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SHARED_IRQ_H_
+#define ZEPHYR_INCLUDE_SHARED_IRQ_H_
+
+#include <autoconf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*isr_t)(const struct device *dev);
+
+/* driver API definition */
+typedef int (*shared_irq_register_t)(const struct device *dev,
+				     isr_t isr_func,
+				     const struct device *isr_dev);
+typedef int (*shared_irq_enable_t)(const struct device *dev,
+				   const struct device *isr_dev);
+typedef int (*shared_irq_disable_t)(const struct device *dev,
+				    const struct device *isr_dev);
+
+struct shared_irq_driver_api {
+	shared_irq_register_t isr_register;
+	shared_irq_enable_t enable;
+	shared_irq_disable_t disable;
+};
+
+extern int shared_irq_initialize(const struct device *port);
+
+typedef void (*shared_irq_config_irq_t)(void);
+
+struct shared_irq_config {
+	uint32_t irq_num;
+	shared_irq_config_irq_t config;
+	uint32_t client_count;
+};
+
+struct shared_irq_client {
+	const struct device *isr_dev;
+	isr_t isr_func;
+	uint32_t enabled;
+};
+
+struct shared_irq_runtime {
+	struct shared_irq_client client[CONFIG_SHARED_IRQ_NUM_CLIENTS];
+};
+
+/**
+ *  @brief Register a device ISR
+ *  @param dev Pointer to device structure for SHARED_IRQ driver instance.
+ *  @param isr_func Pointer to the ISR function for the device.
+ *  @param isr_dev Pointer to the device that will service the interrupt.
+ */
+static inline int shared_irq_isr_register(const struct device *dev,
+					  isr_t isr_func,
+					  const struct device *isr_dev)
+{
+	const struct shared_irq_driver_api *api =
+		(const struct shared_irq_driver_api *)dev->api;
+
+	return api->isr_register(dev, isr_func, isr_dev);
+}
+
+/**
+ *  @brief Enable ISR for device
+ *  @param dev Pointer to device structure for SHARED_IRQ driver instance.
+ *  @param isr_dev Pointer to the device that will service the interrupt.
+ */
+static inline int shared_irq_enable(const struct device *dev,
+				    const struct device *isr_dev)
+{
+	const struct shared_irq_driver_api *api =
+		(const struct shared_irq_driver_api *)dev->api;
+
+	return api->enable(dev, isr_dev);
+}
+
+/**
+ *  @brief Disable ISR for device
+ *  @param dev Pointer to device structure for SHARED_IRQ driver instance.
+ *  @param isr_dev Pointer to the device that will service the interrupt.
+ */
+static inline int shared_irq_disable(const struct device *dev,
+				     const struct device *isr_dev)
+{
+	const struct shared_irq_driver_api *api =
+		(const struct shared_irq_driver_api *)dev->api;
+
+	return api->disable(dev, isr_dev);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SHARED_IRQ_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sw_isr_table.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sw_isr_table.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sw_isr_table.h	(working copy)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Software-managed ISR table
+ *
+ * Data types for a software-managed ISR table, with a parameter per-ISR.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
+#define ZEPHYR_INCLUDE_SW_ISR_TABLE_H_
+
+#if !defined(_ASMLANGUAGE)
+#include <zephyr/types.h>
+#include <toolchain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Note the order: arg first, then ISR. This allows a table entry to be
+ * loaded arg -> r0, isr -> r3 in _isr_wrapper with one ldmia instruction,
+ * on ARM Cortex-M (Thumb2).
+ */
+struct _isr_table_entry {
+	const void *arg;
+	void (*isr)(const void *);
+};
+
+/* The software ISR table itself, an array of these structures indexed by the
+ * irq line
+ */
+extern struct _isr_table_entry _sw_isr_table[];
+
+/*
+ * Data structure created in a special binary .intlist section for each
+ * configured interrupt. gen_irq_tables.py pulls this out of the binary and
+ * uses it to create the IRQ vector table and the _sw_isr_table.
+ *
+ * More discussion in include/linker/intlist.ld
+ */
+struct _isr_list {
+	/** IRQ line number */
+	int32_t irq;
+	/** Flags for this IRQ, see ISR_FLAG_* definitions */
+	int32_t flags;
+	/** ISR to call */
+	void *func;
+	/** Parameter for non-direct IRQs */
+	const void *param;
+};
+
+/** This interrupt gets put directly in the vector table */
+#define ISR_FLAG_DIRECT BIT(0)
+
+#define _MK_ISR_NAME(x, y) __MK_ISR_NAME(x, y)
+#define __MK_ISR_NAME(x, y) __isr_ ## x ## _irq_ ## y
+
+/* Create an instance of struct _isr_list which gets put in the .intList
+ * section. This gets consumed by gen_isr_tables.py which creates the vector
+ * and/or SW ISR tables.
+ */
+#define Z_ISR_DECLARE(irq, flags, func, param) \
+	static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList) \
+		__used _MK_ISR_NAME(func, __COUNTER__) = \
+			{irq, flags, (void *)&func, (const void *)param}
+
+#define IRQ_TABLE_SIZE (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR)
+
+#ifdef CONFIG_DYNAMIC_INTERRUPTS
+void z_isr_install(unsigned int irq, void (*routine)(const void *),
+		   const void *param);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ASMLANGUAGE */
+
+#endif /* ZEPHYR_INCLUDE_SW_ISR_TABLE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/__assert.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/__assert.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/__assert.h	(working copy)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011-2014 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS___ASSERT_H_
+#define ZEPHYR_INCLUDE_SYS___ASSERT_H_
+
+#include <stdbool.h>
+
+#ifdef CONFIG_ASSERT
+#ifndef __ASSERT_ON
+#define __ASSERT_ON CONFIG_ASSERT_LEVEL
+#endif
+#endif
+
+#ifdef CONFIG_FORCE_NO_ASSERT
+#undef __ASSERT_ON
+#define __ASSERT_ON 0
+#endif
+
+#if defined(CONFIG_ASSERT_VERBOSE)
+#define __ASSERT_PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__)
+#else /* CONFIG_ASSERT_VERBOSE */
+#define __ASSERT_PRINT(fmt, ...)
+#endif /* CONFIG_ASSERT_VERBOSE */
+
+#ifdef CONFIG_ASSERT_NO_MSG_INFO
+#define __ASSERT_MSG_INFO(fmt, ...)
+#else  /* CONFIG_ASSERT_NO_MSG_INFO */
+#define __ASSERT_MSG_INFO(fmt, ...) __ASSERT_PRINT("\t" fmt "\n", ##__VA_ARGS__)
+#endif /* CONFIG_ASSERT_NO_MSG_INFO */
+
+#if !defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
+#define __ASSERT_LOC(test)                              \
+	__ASSERT_PRINT("ASSERTION FAIL [%s] @ %s:%d\n", \
+		Z_STRINGIFY(test),                      \
+		__FILE__, __LINE__)
+#endif
+
+#if defined(CONFIG_ASSERT_NO_COND_INFO) && !defined(CONFIG_ASSERT_NO_FILE_INFO)
+#define __ASSERT_LOC(test)                         \
+	__ASSERT_PRINT("ASSERTION FAIL @ %s:%d\n", \
+		__FILE__, __LINE__)
+#endif
+
+#if !defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
+#define __ASSERT_LOC(test)                      \
+	__ASSERT_PRINT("ASSERTION FAIL [%s]\n", \
+		Z_STRINGIFY(test))
+#endif
+
+#if defined(CONFIG_ASSERT_NO_COND_INFO) && defined(CONFIG_ASSERT_NO_FILE_INFO)
+#define __ASSERT_LOC(test)                 \
+	__ASSERT_PRINT("ASSERTION FAIL\n")
+#endif
+
+#ifdef __ASSERT_ON
+#if (__ASSERT_ON < 0) || (__ASSERT_ON > 2)
+#error "Invalid __ASSERT() level: must be between 0 and 2"
+#endif
+
+#if __ASSERT_ON
+
+#include <sys/printk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIG_ASSERT_NO_FILE_INFO
+void assert_post_action(void);
+#define __ASSERT_POST_ACTION() assert_post_action()
+#else  /* CONFIG_ASSERT_NO_FILE_INFO */
+void assert_post_action(const char *file, unsigned int line);
+#define __ASSERT_POST_ACTION() assert_post_action(__FILE__, __LINE__)
+#endif /* CONFIG_ASSERT_NO_FILE_INFO */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define __ASSERT_NO_MSG(test)                                             \
+	do {                                                              \
+		if (!(test)) {                                            \
+			__ASSERT_LOC(test);                               \
+			__ASSERT_POST_ACTION();                           \
+		}                                                         \
+	} while (false)
+
+#define __ASSERT(test, fmt, ...)                                          \
+	do {                                                              \
+		if (!(test)) {                                            \
+			__ASSERT_LOC(test);                               \
+			__ASSERT_MSG_INFO(fmt, ##__VA_ARGS__);            \
+			__ASSERT_POST_ACTION();                           \
+		}                                                         \
+	} while (false)
+
+#define __ASSERT_EVAL(expr1, expr2, test, fmt, ...)                \
+	do {                                                       \
+		expr2;                                             \
+		__ASSERT(test, fmt, ##__VA_ARGS__);                \
+	} while (false)
+
+#if (__ASSERT_ON == 1)
+#warning "__ASSERT() statements are ENABLED"
+#endif
+#else
+#define __ASSERT(test, fmt, ...) { }
+#define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
+#define __ASSERT_NO_MSG(test) { }
+#endif
+#else
+#define __ASSERT(test, fmt, ...) { }
+#define __ASSERT_EVAL(expr1, expr2, test, fmt, ...) expr1
+#define __ASSERT_NO_MSG(test) { }
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS___ASSERT_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/arch_interface.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/arch_interface.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/arch_interface.h	(working copy)
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @defgroup arch-interface Architecture Interface
+ * @brief Internal kernel APIs with public scope
+ *
+ * Any public kernel APIs that are implemented as inline functions and need to
+ * call architecture-specific API so will have the prototypes for the
+ * architecture-specific APIs here. Architecture APIs that aren't used in this
+ * way go in kernel/include/kernel_arch_interface.h.
+ *
+ * The set of architecture-specific APIs used internally by public macros and
+ * inline functions in public headers are also specified and documented.
+ *
+ * For all macros and inline function prototypes described herein, <arch/cpu.h>
+ * must eventually pull in full definitions for all of them (the actual macro
+ * defines and inline function bodies)
+ *
+ * include/kernel.h and other public headers depend on definitions in this
+ * header.
+ */
+#ifndef ZEPHYR_INCLUDE_SYS_ARCH_INTERFACE_H_
+#define ZEPHYR_INCLUDE_SYS_ARCH_INTERFACE_H_
+
+#ifndef _ASMLANGUAGE
+#include <toolchain.h>
+#include <stddef.h>
+#include <zephyr/types.h>
+#include <arch/cpu.h>
+#include <irq_offload.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: We cannot pull in kernel.h here, need some forward declarations  */
+struct k_thread;
+struct k_mem_domain;
+
+typedef struct z_thread_stack_element k_thread_stack_t;
+
+typedef void (*k_thread_entry_t)(void *p1, void *p2, void *p3);
+
+/**
+ * @defgroup arch-timing Architecture timing APIs
+ * @ingroup arch-interface
+ * @{
+ */
+
+/**
+ * Obtain the current cycle count, in units that are hardware-specific
+ *
+ * @see k_cycle_get_32()
+ */
+static inline uint32_t arch_k_cycle_get_32(void);
+
+/** @} */
+
+
+/**
+ * @addtogroup arch-threads
+ * @{
+ */
+
+/**
+ * @def ARCH_THREAD_STACK_RESERVED
+ *
+ * @see K_THREAD_STACK_RESERVED
+ */
+
+/**
+ * @def ARCH_STACK_PTR_ALIGN
+ *
+ * Required alignment of the CPU's stack pointer register value, dictated by
+ * hardware constraints and the ABI calling convention.
+ *
+ * @see Z_STACK_PTR_ALIGN
+ */
+
+/**
+ * @def ARCH_THREAD_STACK_OBJ_ALIGN(size)
+ *
+ * Required alignment of the lowest address of a stack object.
+ *
+ * Optional definition.
+ *
+ * @see Z_THREAD_STACK_OBJ_ALIGN
+ */
+
+/**
+ * @def ARCH_THREAD_STACK_SIZE_ADJUST(size)
+ * @brief Round up a stack buffer size to alignment constraints
+ *
+ * Adjust a requested stack buffer size to the true size of its underlying
+ * buffer, defined as the area usable for thread stack context and thread-
+ * local storage.
+ *
+ * The size value passed here does not include storage reserved for platform
+ * data.
+ *
+ * The returned value is either the same size provided (if already properly
+ * aligned), or rounded up to satisfy alignment constraints.  Calculations
+ * performed here *must* be idempotent.
+ *
+ * Optional definition. If undefined, stack buffer sizes are either:
+ * - Rounded up to the next power of two if user mode is enabled on an arch
+ *   with an MPU that requires such alignment
+ * - Rounded up to ARCH_STACK_PTR_ALIGN
+ *
+ * @see Z_THREAD_STACK_SIZE_ADJUST
+ */
+
+/**
+ * @def ARCH_KERNEL_STACK_RESERVED
+ * @brief MPU guard size for kernel-only stacks
+ *
+ * If MPU stack guards are used to catch stack overflows, specify the
+ * amount of space reserved in kernel stack objects. If guard sizes are
+ * context dependent, this should be in the minimum guard size, with
+ * remaining space carved out if needed.
+ *
+ * Optional definition, defaults to 0.
+ *
+ * @see K_KERNEL_STACK_RESERVED
+ */
+
+/**
+ * @def ARCH_KERNEL_STACK_OBJ_ALIGN
+ * @brief Required alignment of the lowest address of a kernel-only stack.
+ */
+
+/** @} */
+
+/**
+ * @addtogroup arch-pm
+ * @{
+ */
+
+/**
+ * @brief Power save idle routine
+ *
+ * This function will be called by the kernel idle loop or possibly within
+ * an implementation of z_sys_power_save_idle in the kernel when the
+ * '_sys_power_save_flag' variable is non-zero.
+ *
+ * Architectures that do not implement power management instructions may
+ * immediately return, otherwise a power-saving instruction should be
+ * issued to wait for an interrupt.
+ *
+ * @note The function is expected to return after the interrupt that has
+ * caused the CPU to exit power-saving mode has been serviced, although
+ * this is not a firm requirement.
+ *
+ * @see k_cpu_idle()
+ */
+void arch_cpu_idle(void);
+
+/**
+ * @brief Atomically re-enable interrupts and enter low power mode
+ *
+ * The requirements for arch_cpu_atomic_idle() are as follows:
+ *
+ * -# Enabling interrupts and entering a low-power mode needs to be
+ *    atomic, i.e. there should be no period of time where interrupts are
+ *    enabled before the processor enters a low-power mode.  See the comments
+ *    in k_lifo_get(), for example, of the race condition that
+ *    occurs if this requirement is not met.
+ *
+ * -# After waking up from the low-power mode, the interrupt lockout state
+ *    must be restored as indicated in the 'key' input parameter.
+ *
+ * @see k_cpu_atomic_idle()
+ *
+ * @param key Lockout key returned by previous invocation of arch_irq_lock()
+ */
+void arch_cpu_atomic_idle(unsigned int key);
+
+/** @} */
+
+
+/**
+ * @addtogroup arch-smp
+ * @{
+ */
+
+/**
+ * Per-cpu entry function
+ *
+ * @param context parameter, implementation specific
+ */
+typedef FUNC_NORETURN void (*arch_cpustart_t)(void *data);
+
+/**
+ * @brief Start a numbered CPU on a MP-capable system
+ *
+ * This starts and initializes a specific CPU.  The main thread on startup is
+ * running on CPU zero, other processors are numbered sequentially.  On return
+ * from this function, the CPU is known to have begun operating and will enter
+ * the provided function.  Its interrupts will be initialized but disabled such
+ * that irq_unlock() with the provided key will work to enable them.
+ *
+ * Normally, in SMP mode this function will be called by the kernel
+ * initialization and should not be used as a user API.  But it is defined here
+ * for special-purpose apps which want Zephyr running on one core and to use
+ * others for design-specific processing.
+ *
+ * @param cpu_num Integer number of the CPU
+ * @param stack Stack memory for the CPU
+ * @param sz Stack buffer size, in bytes
+ * @param fn Function to begin running on the CPU.
+ * @param arg Untyped argument to be passed to "fn"
+ */
+void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
+		    arch_cpustart_t fn, void *arg);
+/** @} */
+
+
+/**
+ * @addtogroup arch-irq
+ * @{
+ */
+
+/**
+ * Lock interrupts on the current CPU
+ *
+ * @see irq_lock()
+ */
+static inline unsigned int arch_irq_lock(void);
+
+/**
+ * Unlock interrupts on the current CPU
+ *
+ * @see irq_unlock()
+ */
+static inline void arch_irq_unlock(unsigned int key);
+
+/**
+ * Test if calling arch_irq_unlock() with this key would unlock irqs
+ *
+ * @param key value returned by arch_irq_lock()
+ * @return true if interrupts were unlocked prior to the arch_irq_lock()
+ * call that produced the key argument.
+ */
+static inline bool arch_irq_unlocked(unsigned int key);
+
+/**
+ * Disable the specified interrupt line
+ *
+ * @see irq_disable()
+ */
+void arch_irq_disable(unsigned int irq);
+
+/**
+ * Enable the specified interrupt line
+ *
+ * @see irq_enable()
+ */
+void arch_irq_enable(unsigned int irq);
+
+/**
+ * Test if an interrupt line is enabled
+ *
+ * @see irq_is_enabled()
+ */
+int arch_irq_is_enabled(unsigned int irq);
+
+/**
+ * Arch-specific hook to install a dynamic interrupt.
+ *
+ * @param irq IRQ line number
+ * @param priority Interrupt priority
+ * @param routine Interrupt service routine
+ * @param parameter ISR parameter
+ * @param flags Arch-specific IRQ configuration flag
+ *
+ * @return The vector assigned to this interrupt
+ */
+int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
+			     void (*routine)(const void *parameter),
+			     const void *parameter, uint32_t flags);
+
+/**
+ * @def ARCH_IRQ_CONNECT(irq, pri, isr, arg, flags)
+ *
+ * @see IRQ_CONNECT()
+ */
+
+/**
+ * @def ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p)
+ *
+ * @see IRQ_DIRECT_CONNECT()
+ */
+
+/**
+ * @def ARCH_ISR_DIRECT_PM()
+ *
+ * @see ISR_DIRECT_PM()
+ */
+
+/**
+ * @def ARCH_ISR_DIRECT_HEADER()
+ *
+ * @see ISR_DIRECT_HEADER()
+ */
+
+/**
+ * @def ARCH_ISR_DIRECT_FOOTER(swap)
+ *
+ * @see ISR_DIRECT_FOOTER()
+ */
+
+/**
+ * @def ARCH_ISR_DIRECT_DECLARE(name)
+ *
+ * @see ISR_DIRECT_DECLARE()
+ */
+
+/**
+ * @def ARCH_EXCEPT(reason_p)
+ *
+ * Generate a software induced fatal error.
+ *
+ * If the caller is running in user mode, only K_ERR_KERNEL_OOPS or
+ * K_ERR_STACK_CHK_FAIL may be induced.
+ *
+ * This should ideally generate a software trap, with exception context
+ * indicating state when this was invoked. General purpose register state at
+ * the time of trap should not be disturbed from the calling context.
+ *
+ * @param reason_p K_ERR_ scoped reason code for the fatal error.
+ */
+
+#ifdef CONFIG_IRQ_OFFLOAD
+/**
+ * Run a function in interrupt context.
+ *
+ * Implementations should invoke an exception such that the kernel goes through
+ * its interrupt handling dispatch path, to include switching to the interrupt
+ * stack, and runs the provided routine and parameter.
+ *
+ * The only intended use-case for this function is for test code to simulate
+ * the correctness of kernel APIs in interrupt handling context. This API
+ * is not intended for real applications.
+ *
+ * @see irq_offload()
+ *
+ * @param routine Function to run in interrupt context
+ * @param parameter Value to pass to the function when invoked
+ */
+void arch_irq_offload(irq_offload_routine_t routine, const void *parameter);
+#endif /* CONFIG_IRQ_OFFLOAD */
+
+/** @} */
+
+
+/**
+ * @defgroup arch-smp Architecture-specific SMP APIs
+ * @ingroup arch-interface
+ * @{
+ */
+#ifdef CONFIG_SMP
+/** Return the CPU struct for the currently executing CPU */
+static inline struct _cpu *arch_curr_cpu(void);
+
+/**
+ * Broadcast an interrupt to all CPUs
+ *
+ * This will invoke z_sched_ipi() on other CPUs in the system.
+ */
+void arch_sched_ipi(void);
+#endif /* CONFIG_SMP */
+
+/** @} */
+
+
+/**
+ * @defgroup arch-userspace Architecture-specific userspace APIs
+ * @ingroup arch-interface
+ * @{
+ */
+
+#ifdef CONFIG_USERSPACE
+/**
+ * Invoke a system call with 0 arguments.
+ *
+ * No general-purpose register state other than return value may be preserved
+ * when transitioning from supervisor mode back down to user mode for
+ * security reasons.
+ *
+ * It is required that all arguments be stored in registers when elevating
+ * privileges from user to supervisor mode.
+ *
+ * Processing of the syscall takes place on a separate kernel stack. Interrupts
+ * should be enabled when invoking the system call marshallers from the
+ * dispatch table. Thread preemption may occur when handling system calls.
+ *
+ * Call ids are untrusted and must be bounds-checked, as the value is used to
+ * index the system call dispatch table, containing function pointers to the
+ * specific system call code.
+ *
+ * @param call_id System call ID
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id);
+
+/**
+ * Invoke a system call with 1 argument.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1,
+					     uintptr_t call_id);
+
+/**
+ * Invoke a system call with 2 arguments.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param arg2 Second argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
+					     uintptr_t call_id);
+
+/**
+ * Invoke a system call with 3 arguments.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param arg2 Second argument to the system call.
+ * @param arg3 Third argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
+					     uintptr_t arg3,
+					     uintptr_t call_id);
+
+/**
+ * Invoke a system call with 4 arguments.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param arg2 Second argument to the system call.
+ * @param arg3 Third argument to the system call.
+ * @param arg4 Fourth argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
+					     uintptr_t arg3, uintptr_t arg4,
+					     uintptr_t call_id);
+
+/**
+ * Invoke a system call with 5 arguments.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param arg2 Second argument to the system call.
+ * @param arg3 Third argument to the system call.
+ * @param arg4 Fourth argument to the system call.
+ * @param arg5 Fifth argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
+					     uintptr_t arg3, uintptr_t arg4,
+					     uintptr_t arg5,
+					     uintptr_t call_id);
+
+/**
+ * Invoke a system call with 6 arguments.
+ *
+ * @see arch_syscall_invoke0()
+ *
+ * @param arg1 First argument to the system call.
+ * @param arg2 Second argument to the system call.
+ * @param arg3 Third argument to the system call.
+ * @param arg4 Fourth argument to the system call.
+ * @param arg5 Fifth argument to the system call.
+ * @param arg6 Sixth argument to the system call.
+ * @param call_id System call ID, will be bounds-checked and used to reference
+ *	          kernel-side dispatch table
+ * @return Return value of the system call. Void system calls return 0 here.
+ */
+static inline uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2,
+					     uintptr_t arg3, uintptr_t arg4,
+					     uintptr_t arg5, uintptr_t arg6,
+					     uintptr_t call_id);
+
+/**
+ * Indicate whether we are currently running in user mode
+ *
+ * @return true if the CPU is currently running with user permissions
+ */
+static inline bool arch_is_user_context(void);
+
+/**
+ * @brief Get the maximum number of partitions for a memory domain
+ *
+ * @return Max number of partitions, or -1 if there is no limit
+ */
+int arch_mem_domain_max_partitions_get(void);
+
+#ifdef CONFIG_ARCH_MEM_DOMAIN_DATA
+/**
+ *
+ * @brief Architecture-specific hook for memory domain initialization
+ *
+ * Perform any tasks needed to initialize architecture-specific data within
+ * the memory domain, such as reserving memory for page tables. All members
+ * of the provided memory domain aside from `arch` will be initialized when
+ * this is called, but no threads will be a assigned yet.
+ *
+ * This function may fail if initializing the memory domain requires allocation,
+ * such as for page tables.
+ *
+ * @param domain The memory domain to initialize
+ * @retval 0 Success
+ * @retval -ENOMEM Insufficient memory
+ */
+int arch_mem_domain_init(struct k_mem_domain *domain);
+#endif /* CONFIG_ARCH_MEM_DOMAIN_DATA */
+
+#ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API
+/**
+ * @brief Add a thread to a memory domain (arch-specific)
+ *
+ * Architecture-specific hook to manage internal data structures or hardware
+ * state when the provided thread has been added to a memory domain.
+ *
+ * The thread's memory domain pointer will be set to the domain to be added
+ * to.
+ *
+ * @param thread Thread which needs to be configured.
+ */
+void arch_mem_domain_thread_add(struct k_thread *thread);
+
+/**
+ * @brief Remove a thread from a memory domain (arch-specific)
+ *
+ * Architecture-specific hook to manage internal data structures or hardware
+ * state when the provided thread has been removed from a memory domain.
+ *
+ * The thread's memory domain pointer will be the domain that the thread
+ * is being removed from.
+ *
+ * @param thread Thread being removed from its memory domain
+ */
+void arch_mem_domain_thread_remove(struct k_thread *thread);
+
+/**
+ * @brief Remove a partition from the memory domain (arch-specific)
+ *
+ * Architecture-specific hook to manage internal data structures or hardware
+ * state when a memory domain has had a partition removed.
+ *
+ * The partition index data, and the number of partitions configured, are not
+ * respectively cleared and decremented in the domain until after this function
+ * runs.
+ *
+ * @param domain The memory domain structure
+ * @param partition_id The partition index that needs to be deleted
+ */
+void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
+				      uint32_t partition_id);
+
+/**
+ * @brief Add a partition to the memory domain
+ *
+ * Architecture-specific hook to manage internal data structures or hardware
+ * state when a memory domain has a partition added.
+ *
+ * @param domain The memory domain structure
+ * @param partition_id The partition that needs to be added
+ */
+void arch_mem_domain_partition_add(struct k_mem_domain *domain,
+				   uint32_t partition_id);
+
+/**
+ * @brief Remove the memory domain
+ *
+ * Architecture-specific hook to manage internal data structures or hardware
+ * state when a memory domain has been destroyed.
+ *
+ * Thread assignments to the memory domain are only cleared after this function
+ * runs.
+ *
+ * @param domain The memory domain structure which needs to be deleted.
+ */
+void arch_mem_domain_destroy(struct k_mem_domain *domain);
+#endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */
+
+/**
+ * @brief Check memory region permissions
+ *
+ * Given a memory region, return whether the current memory management hardware
+ * configuration would allow a user thread to read/write that region. Used by
+ * system calls to validate buffers coming in from userspace.
+ *
+ * Notes:
+ * The function is guaranteed to never return validation success, if the entire
+ * buffer area is not user accessible.
+ *
+ * The function is guaranteed to correctly validate the permissions of the
+ * supplied buffer, if the user access permissions of the entire buffer are
+ * enforced by a single, enabled memory management region.
+ *
+ * In some architectures the validation will always return failure
+ * if the supplied memory buffer spans multiple enabled memory management
+ * regions (even if all such regions permit user access).
+ *
+ * @warning 0 size buffer has undefined behavior.
+ *
+ * @param addr start address of the buffer
+ * @param size the size of the buffer
+ * @param write If nonzero, additionally check if the area is writable.
+ *	  Otherwise, just check if the memory can be read.
+ *
+ * @return nonzero if the permissions don't match.
+ */
+int arch_buffer_validate(void *addr, size_t size, int write);
+
+/**
+ * Perform a one-way transition from supervisor to kernel mode.
+ *
+ * Implementations of this function must do the following:
+ *
+ * - Reset the thread's stack pointer to a suitable initial value. We do not
+ *   need any prior context since this is a one-way operation.
+ * - Set up any kernel stack region for the CPU to use during privilege
+ *   elevation
+ * - Put the CPU in whatever its equivalent of user mode is
+ * - Transfer execution to arch_new_thread() passing along all the supplied
+ *   arguments, in user mode.
+ *
+ * @param user_entry Entry point to start executing as a user thread
+ * @param p1 1st parameter to user thread
+ * @param p2 2nd parameter to user thread
+ * @param p3 3rd parameter to user thread
+ */
+FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
+					void *p1, void *p2, void *p3);
+
+/**
+ * @brief Induce a kernel oops that appears to come from a specific location
+ *
+ * Normally, k_oops() generates an exception that appears to come from the
+ * call site of the k_oops() itself.
+ *
+ * However, when validating arguments to a system call, if there are problems
+ * we want the oops to appear to come from where the system call was invoked
+ * and not inside the validation function.
+ *
+ * @param ssf System call stack frame pointer. This gets passed as an argument
+ *            to _k_syscall_handler_t functions and its contents are completely
+ *            architecture specific.
+ */
+FUNC_NORETURN void arch_syscall_oops(void *ssf);
+
+/**
+ * @brief Safely take the length of a potentially bad string
+ *
+ * This must not fault, instead the err parameter must have -1 written to it.
+ * This function otherwise should work exactly like libc strnlen(). On success
+ * *err should be set to 0.
+ *
+ * @param s String to measure
+ * @param maxsize Max length of the string
+ * @param err Error value to write
+ * @return Length of the string, not counting NULL byte, up to maxsize
+ */
+size_t arch_user_string_nlen(const char *s, size_t maxsize, int *err);
+#endif /* CONFIG_USERSPACE */
+
+/** @} */
+
+/**
+ * @defgroup arch-gdbstub Architecture-specific gdbstub APIs
+ * @ingroup arch-interface
+ * @{
+ */
+
+/**
+ * @def ARCH_GDB_NUM_REGISTERS
+ *
+ * ARCH_GDB_NUM_REGISTERS is architecure specific and
+ * this symbol must be defined in architecure specific header
+ */
+
+#ifdef CONFIG_GDBSTUB
+/**
+ * @brief Architecture layer debug start
+ *
+ * This function is called by @c gdb_init()
+ */
+void arch_gdb_init(void);
+
+/**
+ * @brief Continue running program
+ *
+ * Continue software execution.
+ */
+void arch_gdb_continue(void);
+
+/**
+ * @brief Continue with one step
+ *
+ * Continue software execution until reaches the next statement.
+ */
+void arch_gdb_step(void);
+
+#endif
+/** @} */
+
+/**
+ * @defgroup arch_cache Architecture-specific cache functions
+ * @ingroup arch-interface
+ * @{
+ */
+
+#ifdef CONFIG_CACHE_FLUSHING
+/**
+ *
+ * @brief Flush d-cache lines to main memory
+ *
+ * @see sys_cache_flush
+ */
+void arch_dcache_flush(void *addr, size_t size);
+
+/**
+ *
+ * @brief Invalidate d-cache lines
+ *
+ * @see sys_cache_invd
+ */
+void arch_dcache_invd(void *addr, size_t size);
+
+#ifndef CONFIG_CACHE_LINE_SIZE
+/**
+ *
+ * @brief Get d-cache line size
+ *
+ * @see sys_cache_line_size_get
+ */
+size_t arch_cache_line_size_get(void);
+#endif
+#endif
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include <arch/arch_inlines.h>
+
+#endif /* _ASMLANGUAGE */
+
+#endif /* ZEPHYR_INCLUDE_SYS_ARCH_INTERFACE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/atomic.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/atomic.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/atomic.h	(working copy)
@@ -0,0 +1,606 @@
+/* atomic operations */
+
+/*
+ * Copyright (c) 1997-2015, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_ATOMIC_H_
+#define ZEPHYR_INCLUDE_SYS_ATOMIC_H_
+
+#include <stdbool.h>
+#include <toolchain.h>
+#include <stddef.h>
+
+#include <types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int atomic_t;
+typedef atomic_t atomic_val_t;
+typedef void *atomic_ptr_t;
+
+/**
+ * @defgroup atomic_apis Atomic Services APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Atomic compare-and-set.
+ *
+ * This routine performs an atomic compare-and-set on @a target. If the current
+ * value of @a target equals @a old_value, @a target is set to @a new_value.
+ * If the current value of @a target does not equal @a old_value, @a target
+ * is left unchanged.
+ *
+ * @param target Address of atomic variable.
+ * @param old_value Original value to compare against.
+ * @param new_value New value to store.
+ * @return true if @a new_value is written, false otherwise.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
+			  atomic_val_t new_value)
+{
+	return __atomic_compare_exchange_n(target, &old_value, new_value,
+					   0, __ATOMIC_SEQ_CST,
+					   __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall bool atomic_cas(atomic_t *target, atomic_val_t old_value,
+			 atomic_val_t new_value);
+
+#else
+static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
+		      atomic_val_t new_value)
+{
+    atomic_t oldVal = *target;
+    if(oldVal == old_value)
+    {
+        *target = new_value;
+        return 1;
+    }
+
+    return 0;
+}
+#endif
+
+/**
+ * @brief Atomic compare-and-set with pointer values
+ *
+ * This routine performs an atomic compare-and-set on @a target. If the current
+ * value of @a target equals @a old_value, @a target is set to @a new_value.
+ * If the current value of @a target does not equal @a old_value, @a target
+ * is left unchanged.
+ *
+ * @param target Address of atomic variable.
+ * @param old_value Original value to compare against.
+ * @param new_value New value to store.
+ * @return true if @a new_value is written, false otherwise.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
+				  void *new_value)
+{
+	return __atomic_compare_exchange_n(target, &old_value, new_value,
+					   0, __ATOMIC_SEQ_CST,
+					   __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
+			      void *new_value);
+#else
+extern bool atomic_ptr_cas(atomic_ptr_t *target, void *old_value,
+			   void *new_value);
+#endif
+
+/**
+ *
+ * @brief Atomic addition.
+ *
+ * This routine performs an atomic addition on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to add.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_add(atomic_t *target, atomic_val_t value);
+#else
+extern atomic_val_t atomic_add(atomic_t *target, atomic_val_t value);
+#endif
+
+/**
+ *
+ * @brief Atomic subtraction.
+ *
+ * This routine performs an atomic subtraction on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to subtract.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value);
+#else
+extern atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value);
+#endif
+
+/**
+ *
+ * @brief Atomic increment.
+ *
+ * This routine performs an atomic increment by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+#if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
+static inline atomic_val_t atomic_inc(atomic_t *target)
+{
+	return atomic_add(target, 1);
+}
+#else
+static inline atomic_val_t atomic_inc(atomic_t *target) 
+{
+    atomic_t oldVal = *target;
+    (*target) = (*target)++;
+    return oldVal;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic decrement.
+ *
+ * This routine performs an atomic decrement by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+#if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
+static inline atomic_val_t atomic_dec(atomic_t *target)
+{
+	return atomic_sub(target, 1);
+}
+#else
+static inline atomic_val_t atomic_dec(atomic_t *target)
+{
+    atomic_t oldVal = *target;
+    (*target) = (*target)--;
+    return oldVal;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic get.
+ *
+ * This routine performs an atomic read on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_get(const atomic_t *target)
+{
+	return __atomic_load_n(target, __ATOMIC_SEQ_CST);
+}
+#else
+static inline atomic_val_t atomic_get(const atomic_t *target)
+{
+    return *target;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic get a pointer value
+ *
+ * This routine performs an atomic read on @a target.
+ *
+ * @param target Address of pointer variable.
+ *
+ * @return Value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline void *atomic_ptr_get(const atomic_ptr_t *target)
+{
+	return __atomic_load_n(target, __ATOMIC_SEQ_CST);
+}
+#else
+extern void *atomic_ptr_get(const atomic_ptr_t *target);
+#endif
+
+/**
+ *
+ * @brief Atomic get-and-set.
+ *
+ * This routine atomically sets @a target to @a value and returns
+ * the previous value of @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to write to @a target.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
+{
+	/* This builtin, as described by Intel, is not a traditional
+	 * test-and-set operation, but rather an atomic exchange operation. It
+	 * writes value into *ptr, and returns the previous contents of *ptr.
+	 */
+	return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_set(atomic_t *target, atomic_val_t value);
+#else
+static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
+{
+    atomic_t oldVal = *target;
+    *target = value;
+    return oldVal;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic get-and-set for pointer values
+ *
+ * This routine atomically sets @a target to @a value and returns
+ * the previous value of @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to write to @a target.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline void *atomic_ptr_set(atomic_ptr_t *target, void *value)
+{
+	return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall void *atomic_ptr_set(atomic_ptr_t *target, void *value);
+#else
+extern void *atomic_ptr_set(atomic_ptr_t *target, void *value);
+#endif
+
+/**
+ *
+ * @brief Atomic clear.
+ *
+ * This routine atomically sets @a target to zero and returns its previous
+ * value. (Hence, it is equivalent to atomic_set(target, 0).)
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+#if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
+static inline atomic_val_t atomic_clear(atomic_t *target)
+{
+	return atomic_set(target, 0);
+}
+#else
+static inline atomic_val_t atomic_clear(atomic_t *target)
+{
+	return atomic_set(target, 0);
+}
+#endif
+
+/**
+ *
+ * @brief Atomic clear of a pointer value
+ *
+ * This routine atomically sets @a target to zero and returns its previous
+ * value. (Hence, it is equivalent to atomic_set(target, 0).)
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+#if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || \
+	defined (CONFIG_ATOMIC_OPERATIONS_C)
+static inline void *atomic_ptr_clear(atomic_ptr_t *target)
+{
+	return atomic_ptr_set(target, NULL);
+}
+#else
+extern void *atomic_ptr_clear(atomic_ptr_t *target);
+#endif
+
+/**
+ *
+ * @brief Atomic bitwise inclusive OR.
+ *
+ * This routine atomically sets @a target to the bitwise inclusive OR of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to OR.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_or(atomic_t *target, atomic_val_t value);
+
+#else
+static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
+{
+    atomic_t oldVal = *target;
+    *target = oldVal | value;
+    return oldVal;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic bitwise exclusive OR (XOR).
+ *
+ * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to XOR
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value);
+#else
+extern atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value);
+#endif
+
+/**
+ *
+ * @brief Atomic bitwise AND.
+ *
+ * This routine atomically sets @a target to the bitwise AND of @a target
+ * and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to AND.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_and(atomic_t *target, atomic_val_t value);
+#else
+static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
+{
+    atomic_t oldVal = *target;
+    *target = oldVal & value;
+    return oldVal;
+}
+#endif
+
+/**
+ *
+ * @brief Atomic bitwise NAND.
+ *
+ * This routine atomically sets @a target to the bitwise NAND of @a target
+ * and @a value. (This operation is equivalent to target = ~(target & value).)
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to NAND.
+ *
+ * @return Previous value of @a target.
+ */
+#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
+static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
+{
+	return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
+}
+#elif defined(CONFIG_ATOMIC_OPERATIONS_C)
+__syscall atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value);
+#else
+extern atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value);
+#endif
+
+
+/**
+ * @brief Initialize an atomic variable.
+ *
+ * This macro can be used to initialize an atomic variable. For example,
+ * @code atomic_t my_var = ATOMIC_INIT(75); @endcode
+ *
+ * @param i Value to assign to atomic variable.
+ */
+#define ATOMIC_INIT(i) (i)
+
+/**
+ * @cond INTERNAL_HIDDEN
+ */
+
+#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
+#define ATOMIC_MASK(bit) (1U << ((uint32_t)(bit) & (ATOMIC_BITS - 1U)))
+#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
+
+/**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+/**
+ * @brief Define an array of atomic variables.
+ *
+ * This macro defines an array of atomic variables containing at least
+ * @a num_bits bits.
+ *
+ * @note
+ * If used from file scope, the bits of the array are initialized to zero;
+ * if used from within a function, the bits are left uninitialized.
+ *
+ * @param name Name of array of atomic variables.
+ * @param num_bits Number of bits needed.
+ */
+#define ATOMIC_DEFINE(name, num_bits) \
+	atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
+
+/**
+ * @brief Atomically test a bit.
+ *
+ * This routine tests whether bit number @a bit of @a target is set or not.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return true if the bit was set, false if it wasn't.
+ */
+static inline bool atomic_test_bit(const atomic_t *target, int bit)
+{
+	atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
+
+	return (1 & (val >> (bit & (ATOMIC_BITS - 1)))) != 0;
+}
+
+/**
+ * @brief Atomically test and clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return true if the bit was set, false if it wasn't.
+ */
+static inline bool atomic_test_and_clear_bit(atomic_t *target, int bit)
+{
+	atomic_val_t mask = ATOMIC_MASK(bit);
+	atomic_val_t old;
+
+	old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+
+	return (old & mask) != 0;
+}
+
+/**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return true if the bit was set, false if it wasn't.
+ */
+static inline bool atomic_test_and_set_bit(atomic_t *target, int bit)
+{
+	atomic_val_t mask = ATOMIC_MASK(bit);
+	atomic_val_t old;
+
+	old = atomic_or(ATOMIC_ELEM(target, bit), mask);
+
+	return (old & mask) != 0;
+}
+
+/**
+ * @brief Atomically clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+static inline void atomic_clear_bit(atomic_t *target, int bit)
+{
+	atomic_val_t mask = ATOMIC_MASK(bit);
+
+	(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+}
+
+/**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+static inline void atomic_set_bit(atomic_t *target, int bit)
+{
+	atomic_val_t mask = ATOMIC_MASK(bit);
+
+	(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
+}
+
+/**
+ * @brief Atomically set a bit to a given value.
+ *
+ * Atomically set bit number @a bit of @a target to value @a val.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ * @param val true for 1, false for 0.
+ *
+ * @return N/A
+ */
+static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
+{
+	atomic_val_t mask = ATOMIC_MASK(bit);
+
+	if (val) {
+		(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
+	} else {
+		(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+	}
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef CONFIG_ATOMIC_OPERATIONS_C
+#include <syscalls/atomic.h>
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/base64.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/base64.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/base64.h	(working copy)
@@ -0,0 +1,79 @@
+/*
+ * RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2018, Nordic Semiconductor ASA
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Adapted for Zephyr by Carles Cufi (carles.cufi@nordicsemi.no)
+ *  - Removed mbedtls_ prefixes
+ *  - Reworked coding style
+ */
+#ifndef ZEPHYR_INCLUDE_SYS_BASE64_H_
+#define ZEPHYR_INCLUDE_SYS_BASE64_H_
+
+#include <stddef.h>
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief          Encode a buffer into base64 format
+ *
+ * @param dst      destination buffer
+ * @param dlen     size of the destination buffer
+ * @param olen     number of bytes written
+ * @param src      source buffer
+ * @param slen     amount of data to be encoded
+ *
+ * @return         0 if successful, or -ENOMEM if the buffer is too small.
+ *                 *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *                 If that length cannot be represented, then no data is
+ *                 written to the buffer and *olen is set to the maximum
+ *                 length representable as a size_t.
+ *
+ * @note           Call this function with dlen = 0 to obtain the
+ *                 required buffer size in *olen
+ */
+int base64_encode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src,
+		  size_t slen);
+
+/**
+ * @brief          Decode a base64-formatted buffer
+ *
+ * @param dst      destination buffer (can be NULL for checking size)
+ * @param dlen     size of the destination buffer
+ * @param olen     number of bytes written
+ * @param src      source buffer
+ * @param slen     amount of data to be decoded
+ *
+ * @return         0 if successful, -ENOMEM, or -EINVAL if the input data is
+ *                 not correct. *olen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * @note           Call this function with *dst = NULL or dlen = 0 to obtain
+ *                 the required buffer size in *olen
+ */
+int base64_decode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src,
+		  size_t slen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_BASE64_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/byteorder.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/byteorder.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/byteorder.h	(working copy)
@@ -0,0 +1,568 @@
+/** @file
+ *  @brief Byte order helpers.
+ */
+
+/*
+ * Copyright (c) 2015-2016, Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_BYTEORDER_H_
+#define ZEPHYR_INCLUDE_SYS_BYTEORDER_H_
+
+#include <types.h>
+#include <stddef.h>
+#include <sys/__assert.h>
+#include <toolchain.h>
+
+/* Internal helpers only used by the sys_* APIs further below */
+#define __bswap_16(x) ((uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
+#define __bswap_24(x) ((uint32_t) ((((x) >> 16) & 0xff) | \
+				   (((x)) & 0xff00) | \
+				   (((x) & 0xff) << 16)))
+#define __bswap_32(x) ((uint32_t) ((((x) >> 24) & 0xff) | \
+				   (((x) >> 8) & 0xff00) | \
+				   (((x) & 0xff00) << 8) | \
+				   (((x) & 0xff) << 24)))
+#define __bswap_48(x) ((uint64_t) ((((x) >> 40) & 0xff) | \
+				   (((x) >> 24) & 0xff00) | \
+				   (((x) >> 8) & 0xff0000) | \
+				   (((x) & 0xff0000) << 8) | \
+				   (((x) & 0xff00) << 24) | \
+				   (((x) & 0xff) << 40)))
+#define __bswap_64(x) ((uint64_t) ((((x) >> 56) & 0xff) | \
+				   (((x) >> 40) & 0xff00) | \
+				   (((x) >> 24) & 0xff0000) | \
+				   (((x) >> 8) & 0xff000000) | \
+				   (((x) & 0xff000000) << 8) | \
+				   (((x) & 0xff0000) << 24) | \
+				   (((x) & 0xff00) << 40) | \
+				   (((x) & 0xff) << 56)))
+
+/** @def sys_le16_to_cpu
+ *  @brief Convert 16-bit integer from little-endian to host endianness.
+ *
+ *  @param val 16-bit integer in little-endian format.
+ *
+ *  @return 16-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_le16
+ *  @brief Convert 16-bit integer from host endianness to little-endian.
+ *
+ *  @param val 16-bit integer in host endianness.
+ *
+ *  @return 16-bit integer in little-endian format.
+ */
+
+/** @def sys_le24_to_cpu
+ *  @brief Convert 24-bit integer from little-endian to host endianness.
+ *
+ *  @param val 24-bit integer in little-endian format.
+ *
+ *  @return 24-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_le24
+ *  @brief Convert 24-bit integer from host endianness to little-endian.
+ *
+ *  @param val 24-bit integer in host endianness.
+ *
+ *  @return 24-bit integer in little-endian format.
+ */
+
+/** @def sys_le32_to_cpu
+ *  @brief Convert 32-bit integer from little-endian to host endianness.
+ *
+ *  @param val 32-bit integer in little-endian format.
+ *
+ *  @return 32-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_le32
+ *  @brief Convert 32-bit integer from host endianness to little-endian.
+ *
+ *  @param val 32-bit integer in host endianness.
+ *
+ *  @return 32-bit integer in little-endian format.
+ */
+
+/** @def sys_le48_to_cpu
+ *  @brief Convert 48-bit integer from little-endian to host endianness.
+ *
+ *  @param val 48-bit integer in little-endian format.
+ *
+ *  @return 48-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_le48
+ *  @brief Convert 48-bit integer from host endianness to little-endian.
+ *
+ *  @param val 48-bit integer in host endianness.
+ *
+ *  @return 48-bit integer in little-endian format.
+ */
+
+/** @def sys_be16_to_cpu
+ *  @brief Convert 16-bit integer from big-endian to host endianness.
+ *
+ *  @param val 16-bit integer in big-endian format.
+ *
+ *  @return 16-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_be16
+ *  @brief Convert 16-bit integer from host endianness to big-endian.
+ *
+ *  @param val 16-bit integer in host endianness.
+ *
+ *  @return 16-bit integer in big-endian format.
+ */
+
+/** @def sys_be24_to_cpu
+ *  @brief Convert 24-bit integer from big-endian to host endianness.
+ *
+ *  @param val 24-bit integer in big-endian format.
+ *
+ *  @return 24-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_be24
+ *  @brief Convert 24-bit integer from host endianness to big-endian.
+ *
+ *  @param val 24-bit integer in host endianness.
+ *
+ *  @return 24-bit integer in big-endian format.
+ */
+
+/** @def sys_be32_to_cpu
+ *  @brief Convert 32-bit integer from big-endian to host endianness.
+ *
+ *  @param val 32-bit integer in big-endian format.
+ *
+ *  @return 32-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_be32
+ *  @brief Convert 32-bit integer from host endianness to big-endian.
+ *
+ *  @param val 32-bit integer in host endianness.
+ *
+ *  @return 32-bit integer in big-endian format.
+ */
+
+/** @def sys_be48_to_cpu
+ *  @brief Convert 48-bit integer from big-endian to host endianness.
+ *
+ *  @param val 48-bit integer in big-endian format.
+ *
+ *  @return 48-bit integer in host endianness.
+ */
+
+/** @def sys_cpu_to_be48
+ *  @brief Convert 48-bit integer from host endianness to big-endian.
+ *
+ *  @param val 48-bit integer in host endianness.
+ *
+ *  @return 48-bit integer in big-endian format.
+ */
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define sys_le16_to_cpu(val) (val)
+#define sys_cpu_to_le16(val) (val)
+#define sys_le24_to_cpu(val) (val)
+#define sys_cpu_to_le24(val) (val)
+#define sys_le32_to_cpu(val) (val)
+#define sys_cpu_to_le32(val) (val)
+#define sys_le48_to_cpu(val) (val)
+#define sys_cpu_to_le48(val) (val)
+#define sys_le64_to_cpu(val) (val)
+#define sys_cpu_to_le64(val) (val)
+#define sys_be16_to_cpu(val) __bswap_16(val)
+#define sys_cpu_to_be16(val) __bswap_16(val)
+#define sys_be24_to_cpu(val) __bswap_24(val)
+#define sys_cpu_to_be24(val) __bswap_24(val)
+#define sys_be32_to_cpu(val) __bswap_32(val)
+#define sys_cpu_to_be32(val) __bswap_32(val)
+#define sys_be48_to_cpu(val) __bswap_48(val)
+#define sys_cpu_to_be48(val) __bswap_48(val)
+#define sys_be64_to_cpu(val) __bswap_64(val)
+#define sys_cpu_to_be64(val) __bswap_64(val)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define sys_le16_to_cpu(val) __bswap_16(val)
+#define sys_cpu_to_le16(val) __bswap_16(val)
+#define sys_le24_to_cpu(val) __bswap_24(val)
+#define sys_cpu_to_le24(val) __bswap_24(val)
+#define sys_le32_to_cpu(val) __bswap_32(val)
+#define sys_cpu_to_le32(val) __bswap_32(val)
+#define sys_le48_to_cpu(val) __bswap_48(val)
+#define sys_cpu_to_le48(val) __bswap_48(val)
+#define sys_le64_to_cpu(val) __bswap_64(val)
+#define sys_cpu_to_le64(val) __bswap_64(val)
+#define sys_be16_to_cpu(val) (val)
+#define sys_cpu_to_be16(val) (val)
+#define sys_be24_to_cpu(val) (val)
+#define sys_cpu_to_be24(val) (val)
+#define sys_be32_to_cpu(val) (val)
+#define sys_cpu_to_be32(val) (val)
+#define sys_be48_to_cpu(val) (val)
+#define sys_cpu_to_be48(val) (val)
+#define sys_be64_to_cpu(val) (val)
+#define sys_cpu_to_be64(val) (val)
+#else
+#error "Unknown byte order"
+#endif
+
+/**
+ *  @brief Put a 16-bit integer as big-endian to arbitrary location.
+ *
+ *  Put a 16-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in big-endian format.
+ *
+ *  @param val 16-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_be16(uint16_t val, uint8_t dst[2])
+{
+	dst[0] = val >> 8;
+	dst[1] = val;
+}
+
+/**
+ *  @brief Put a 24-bit integer as big-endian to arbitrary location.
+ *
+ *  Put a 24-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in big-endian format.
+ *
+ *  @param val 24-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_be24(uint32_t val, uint8_t dst[3])
+{
+	dst[0] = val >> 16;
+	sys_put_be16(val, &dst[1]);
+}
+
+/**
+ *  @brief Put a 32-bit integer as big-endian to arbitrary location.
+ *
+ *  Put a 32-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in big-endian format.
+ *
+ *  @param val 32-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_be32(uint32_t val, uint8_t dst[4])
+{
+	sys_put_be16(val >> 16, dst);
+	sys_put_be16(val, &dst[2]);
+}
+
+/**
+ *  @brief Put a 48-bit integer as big-endian to arbitrary location.
+ *
+ *  Put a 48-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in big-endian format.
+ *
+ *  @param val 48-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_be48(uint64_t val, uint8_t dst[6])
+{
+	sys_put_be16(val >> 32, dst);
+	sys_put_be32(val, &dst[2]);
+}
+
+/**
+ *  @brief Put a 64-bit integer as big-endian to arbitrary location.
+ *
+ *  Put a 64-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in big-endian format.
+ *
+ *  @param val 64-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_be64(uint64_t val, uint8_t dst[8])
+{
+	sys_put_be32(val >> 32, dst);
+	sys_put_be32(val, &dst[4]);
+}
+
+/**
+ *  @brief Put a 16-bit integer as little-endian to arbitrary location.
+ *
+ *  Put a 16-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in little-endian format.
+ *
+ *  @param val 16-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_le16(uint16_t val, uint8_t dst[2])
+{
+	dst[0] = val;
+	dst[1] = val >> 8;
+}
+
+/**
+ *  @brief Put a 24-bit integer as little-endian to arbitrary location.
+ *
+ *  Put a 24-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in littel-endian format.
+ *
+ *  @param val 24-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_le24(uint32_t val, uint8_t dst[3])
+{
+	sys_put_le16(val, dst);
+	dst[2] = val >> 16;
+}
+
+/**
+ *  @brief Put a 32-bit integer as little-endian to arbitrary location.
+ *
+ *  Put a 32-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in little-endian format.
+ *
+ *  @param val 32-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_le32(uint32_t val, uint8_t dst[4])
+{
+	sys_put_le16(val, dst);
+	sys_put_le16(val >> 16, &dst[2]);
+}
+
+/**
+ *  @brief Put a 48-bit integer as little-endian to arbitrary location.
+ *
+ *  Put a 48-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in little-endian format.
+ *
+ *  @param val 48-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_le48(uint64_t val, uint8_t dst[6])
+{
+	sys_put_le32(val, dst);
+	sys_put_le16(val >> 32, &dst[4]);
+}
+
+/**
+ *  @brief Put a 64-bit integer as little-endian to arbitrary location.
+ *
+ *  Put a 64-bit integer, originally in host endianness, to a
+ *  potentially unaligned memory location in little-endian format.
+ *
+ *  @param val 64-bit integer in host endianness.
+ *  @param dst Destination memory address to store the result.
+ */
+static inline void sys_put_le64(uint64_t val, uint8_t dst[8])
+{
+	sys_put_le32(val, dst);
+	sys_put_le32(val >> 32, &dst[4]);
+}
+
+/**
+ *  @brief Get a 16-bit integer stored in big-endian format.
+ *
+ *  Get a 16-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 16-bit integer to get.
+ *
+ *  @return 16-bit integer in host endianness.
+ */
+static inline uint16_t sys_get_be16(const uint8_t src[2])
+{
+	return ((uint16_t)src[0] << 8) | src[1];
+}
+
+/**
+ *  @brief Get a 24-bit integer stored in big-endian format.
+ *
+ *  Get a 24-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 24-bit integer to get.
+ *
+ *  @return 24-bit integer in host endianness.
+ */
+static inline uint32_t sys_get_be24(const uint8_t src[3])
+{
+	return ((uint32_t)src[0] << 16) | sys_get_be16(&src[1]);
+}
+
+/**
+ *  @brief Get a 32-bit integer stored in big-endian format.
+ *
+ *  Get a 32-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 32-bit integer to get.
+ *
+ *  @return 32-bit integer in host endianness.
+ */
+static inline uint32_t sys_get_be32(const uint8_t src[4])
+{
+	return ((uint32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
+}
+
+/**
+ *  @brief Get a 48-bit integer stored in big-endian format.
+ *
+ *  Get a 48-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 48-bit integer to get.
+ *
+ *  @return 48-bit integer in host endianness.
+ */
+static inline uint64_t sys_get_be48(const uint8_t src[6])
+{
+	return ((uint64_t)sys_get_be32(&src[0]) << 16) | sys_get_be16(&src[4]);
+}
+
+/**
+ *  @brief Get a 64-bit integer stored in big-endian format.
+ *
+ *  Get a 64-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 64-bit integer to get.
+ *
+ *  @return 64-bit integer in host endianness.
+ */
+static inline uint64_t sys_get_be64(const uint8_t src[8])
+{
+	return ((uint64_t)sys_get_be32(&src[0]) << 32) | sys_get_be32(&src[4]);
+}
+
+/**
+ *  @brief Get a 16-bit integer stored in little-endian format.
+ *
+ *  Get a 16-bit integer, stored in little-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the little-endian 16-bit integer to get.
+ *
+ *  @return 16-bit integer in host endianness.
+ */
+static inline uint16_t sys_get_le16(const uint8_t src[2])
+{
+	return ((uint16_t)src[1] << 8) | src[0];
+}
+
+/**
+ *  @brief Get a 24-bit integer stored in big-endian format.
+ *
+ *  Get a 24-bit integer, stored in big-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the big-endian 24-bit integer to get.
+ *
+ *  @return 24-bit integer in host endianness.
+ */
+static inline uint32_t sys_get_le24(const uint8_t src[3])
+{
+	return ((uint32_t)src[2] << 16) | sys_get_le16(&src[0]);
+}
+
+/**
+ *  @brief Get a 32-bit integer stored in little-endian format.
+ *
+ *  Get a 32-bit integer, stored in little-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the little-endian 32-bit integer to get.
+ *
+ *  @return 32-bit integer in host endianness.
+ */
+static inline uint32_t sys_get_le32(const uint8_t src[4])
+{
+	return ((uint32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
+}
+
+/**
+ *  @brief Get a 48-bit integer stored in little-endian format.
+ *
+ *  Get a 48-bit integer, stored in little-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the little-endian 48-bit integer to get.
+ *
+ *  @return 48-bit integer in host endianness.
+ */
+static inline uint64_t sys_get_le48(const uint8_t src[6])
+{
+	return ((uint64_t)sys_get_le32(&src[2]) << 16) | sys_get_le16(&src[0]);
+}
+
+/**
+ *  @brief Get a 64-bit integer stored in little-endian format.
+ *
+ *  Get a 64-bit integer, stored in little-endian format in a potentially
+ *  unaligned memory location, and convert it to the host endianness.
+ *
+ *  @param src Location of the little-endian 64-bit integer to get.
+ *
+ *  @return 64-bit integer in host endianness.
+ */
+static inline uint64_t sys_get_le64(const uint8_t src[8])
+{
+	return ((uint64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
+}
+
+/**
+ * @brief Swap one buffer content into another
+ *
+ * Copy the content of src buffer into dst buffer in reversed order,
+ * i.e.: src[n] will be put in dst[end-n]
+ * Where n is an index and 'end' the last index in both arrays.
+ * The 2 memory pointers must be pointing to different areas, and have
+ * a minimum size of given length.
+ *
+ * @param dst A valid pointer on a memory area where to copy the data in
+ * @param src A valid pointer on a memory area where to copy the data from
+ * @param length Size of both dst and src memory areas
+ */
+static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
+{
+	uint8_t *pdst = (uint8_t *)dst;
+	const uint8_t *psrc = (const uint8_t *)src;
+
+	__ASSERT(((psrc < pdst && (psrc + length) <= pdst) ||
+		  (psrc > pdst && (pdst + length) <= psrc)),
+		 "Source and destination buffers must not overlap");
+
+	psrc += length - 1;
+
+	for (; length > 0; length--) {
+		*pdst++ = *psrc--;
+	}
+}
+
+/**
+ * @brief Swap buffer content
+ *
+ * In-place memory swap, where final content will be reversed.
+ * I.e.: buf[n] will be put in buf[end-n]
+ * Where n is an index and 'end' the last index of buf.
+ *
+ * @param buf A valid pointer on a memory area to swap
+ * @param length Size of buf memory area
+ */
+static inline void sys_mem_swap(void *buf, size_t length)
+{
+	size_t i;
+
+	for (i = 0; i < (length/2); i++) {
+		uint8_t tmp = ((uint8_t *)buf)[i];
+
+		((uint8_t *)buf)[i] = ((uint8_t *)buf)[length - 1 - i];
+		((uint8_t *)buf)[length - 1 - i] = tmp;
+	}
+}
+
+#endif /* ZEPHYR_INCLUDE_SYS_BYTEORDER_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/check.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/check.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/check.h	(working copy)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#ifndef ZEPHYR_INCLUDE_SYS_CHECK_H_
+#define ZEPHYR_INCLUDE_SYS_CHECK_H_
+
+#include <sys/__assert.h>
+
+#if defined(CONFIG_ASSERT_ON_ERRORS)
+#define CHECKIF(expr) \
+	__ASSERT_NO_MSG(!(expr));   \
+	if (0)
+#elif defined(CONFIG_NO_RUNTIME_CHECKS)
+#define CHECKIF(...) \
+	if (0)
+#else
+#define CHECKIF(expr) \
+	if (expr)
+#endif
+
+
+#endif /* ZEPHYR_INCLUDE_SYS_CHECK_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/crc.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/crc.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/crc.h	(working copy)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2018 Workaround GmbH.
+ * Copyright (c) 2017 Intel Corporation.
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015 Runtime Inc
+ * Copyright (c) 2018 Google LLC.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+/** @file
+ * @brief CRC computation function
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_CRC_H_
+#define ZEPHYR_INCLUDE_SYS_CRC_H_
+
+#include <zephyr/types.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initial value expected to be used at the beginning of the crc8_ccitt
+ * computation.
+ */
+#define CRC8_CCITT_INITIAL_VALUE 0xFF
+
+/**
+ * @defgroup checksum Checksum
+ */
+
+/**
+ * @defgroup crc CRC
+ * @ingroup checksum
+ * @{
+ */
+
+/**
+ * @brief Generic function for computing CRC 16
+ *
+ * Compute CRC 16 by passing in the address of the input, the input length
+ * and polynomial used in addition to the initial value.
+ *
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ * @param polynomial The polynomial to use omitting the leading x^16
+ *        coefficient
+ * @param initial_value Initial value for the CRC computation
+ * @param pad Adds padding with zeros at the end of input bytes
+ *
+ * @return The computed CRC16 value
+ */
+uint16_t crc16(const uint8_t *src, size_t len, uint16_t polynomial,
+	    uint16_t initial_value, bool pad);
+
+/**
+ * @brief Generic function for computing CRC 8
+ *
+ * Compute CRC 8 by passing in the address of the input, the input length
+ * and polynomial used in addition to the initial value.
+ *
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ * @param polynomial The polynomial to use omitting the leading x^8
+ *        coefficient
+ * @param initial_value Initial value for the CRC computation
+ * @param reversed Should we use reflected/reversed values or not
+ *
+ * @return The computed CRC8 value
+ */
+uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
+	  bool reversed);
+
+/**
+ * @brief Compute the CRC-16/CCITT checksum of a buffer.
+ *
+ * See ITU-T Recommendation V.41 (November 1988).  Uses 0x1021 as the
+ * polynomial, reflects the input, and reflects the output.
+ *
+ * To calculate the CRC across non-contiguous blocks use the return
+ * value from block N-1 as the seed for block N.
+ *
+ * For CRC-16/CCITT, use 0 as the initial seed.  Other checksums in
+ * the same family can be calculated by changing the seed and/or
+ * XORing the final value.  Examples include:
+ *
+ * - X-25 (used in PPP): seed=0xffff, xor=0xffff, residual=0xf0b8
+ *
+ * @note API changed in Zephyr 1.11.
+ *
+ * @param seed Value to seed the CRC with
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ *
+ * @return The computed CRC16 value
+ */
+uint16_t crc16_ccitt(uint16_t seed, const uint8_t *src, size_t len);
+
+/**
+ * @brief Compute the CRC-16/XMODEM checksum of a buffer.
+ *
+ * The MSB first version of ITU-T Recommendation V.41 (November 1988).
+ * Uses 0x1021 as the polynomial with no reflection.
+ *
+ * To calculate the CRC across non-contiguous blocks use the return
+ * value from block N-1 as the seed for block N.
+ *
+ * For CRC-16/XMODEM, use 0 as the initial seed.  Other checksums in
+ * the same family can be calculated by changing the seed and/or
+ * XORing the final value.  Examples include:
+ *
+ * - CCIITT-FALSE: seed=0xffff
+ * - GSM: seed=0, xorout=0xffff, residue=0x1d0f
+ *
+ * @param seed Value to seed the CRC with
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ *
+ * @return The computed CRC16 value
+ */
+uint16_t crc16_itu_t(uint16_t seed, const uint8_t *src, size_t len);
+
+/**
+ * @brief Compute ANSI variant of CRC 16
+ *
+ * ANSI variant of CRC 16 is using 0x8005 as its polynomial with the initial
+ * value set to 0xffff.
+ *
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ *
+ * @return The computed CRC16 value
+ */
+static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
+{
+	return crc16(src, len, 0x8005, 0xffff, true);
+}
+
+/**
+ * @brief Generate IEEE conform CRC32 checksum.
+ *
+ * @param  *data        Pointer to data on which the CRC should be calculated.
+ * @param  len          Data length.
+ *
+ * @return CRC32 value.
+ *
+ */
+uint32_t crc32_ieee(const uint8_t *data, size_t len);
+
+/**
+ * @brief Update an IEEE conforming CRC32 checksum.
+ *
+ * @param crc   CRC32 checksum that needs to be updated.
+ * @param *data Pointer to data on which the CRC should be calculated.
+ * @param len   Data length.
+ *
+ * @return CRC32 value.
+ *
+ */
+uint32_t crc32_ieee_update(uint32_t crc, const uint8_t *data, size_t len);
+
+/**
+ * @brief Compute CCITT variant of CRC 8
+ *
+ * Normal CCITT variant of CRC 8 is using 0x07.
+ *
+ * @param initial_value Initial value for the CRC computation
+ * @param buf Input bytes for the computation
+ * @param len Length of the input in bytes
+ *
+ * @return The computed CRC8 value
+ */
+uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
+
+/**
+ * @brief Compute the CRC-7 checksum of a buffer.
+ *
+ * See JESD84-A441.  Used by the MMC protocol.  Uses 0x09 as the
+ * polynomial with no reflection.  The CRC is left
+ * justified, so bit 7 of the result is bit 6 of the CRC.
+ *
+ * @param seed Value to seed the CRC with
+ * @param src Input bytes for the computation
+ * @param len Length of the input in bytes
+ *
+ * @return The computed CRC7 value
+ */
+uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/sys/dlist.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/dlist.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/dlist.h	(working copy)
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2013-2015 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Doubly-linked list implementation
+ *
+ * Doubly-linked list implementation using inline macros/functions.
+ * This API is not thread safe, and thus if a list is used across threads,
+ * calls to functions must be protected with synchronization primitives.
+ *
+ * The lists are expected to be initialized such that both the head and tail
+ * pointers point to the list itself.  Initializing the lists in such a fashion
+ * simplifies the adding and removing of nodes to/from the list.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_DLIST_H_
+#define ZEPHYR_INCLUDE_SYS_DLIST_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <toolchain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _dnode {
+	union {
+		struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
+		struct _dnode *next; /* ptr to next node    (sys_dnode_t) */
+	};
+	union {
+		struct _dnode *tail; /* ptr to tail of list (sys_dlist_t) */
+		struct _dnode *prev; /* ptr to previous node (sys_dnode_t) */
+	};
+};
+
+typedef struct _dnode sys_dlist_t;
+typedef struct _dnode sys_dnode_t;
+
+/**
+ * @brief Provide the primitive to iterate on a list
+ * Note: the loop is unsafe and thus __dn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_DLIST_FOR_EACH_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_DLIST_*() macros are not thread safe.
+ *
+ * @param __dl A pointer on a sys_dlist_t to iterate on
+ * @param __dn A sys_dnode_t pointer to peek each node of the list
+ */
+#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn)				\
+	for (__dn = sys_dlist_peek_head(__dl); __dn != NULL;		\
+	     __dn = sys_dlist_peek_next(__dl, __dn))
+
+/**
+ * @brief Provide the primitive to iterate on a list, from a node in the list
+ * Note: the loop is unsafe and thus __dn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_DLIST_ITERATE_FROM_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * Like SYS_DLIST_FOR_EACH_NODE(), but __dn already contains a node in the list
+ * where to start searching for the next entry from. If NULL, it starts from
+ * the head.
+ *
+ * This and other SYS_DLIST_*() macros are not thread safe.
+ *
+ * @param __dl A pointer on a sys_dlist_t to iterate on
+ * @param __dn A sys_dnode_t pointer to peek each node of the list;
+ *             it contains the starting node, or NULL to start from the head
+ */
+#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \
+	for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \
+			 : sys_dlist_peek_head(__dl); \
+	     __dn != NULL; \
+	     __dn = sys_dlist_peek_next(__dl, __dn))
+
+/**
+ * @brief Provide the primitive to safely iterate on a list
+ * Note: __dn can be removed, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_DLIST_FOR_EACH_NODE_SAFE(l, n, s) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_DLIST_*() macros are not thread safe.
+ *
+ * @param __dl A pointer on a sys_dlist_t to iterate on
+ * @param __dn A sys_dnode_t pointer to peek each node of the list
+ * @param __dns A sys_dnode_t pointer for the loop to run safely
+ */
+#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns)			\
+	for (__dn = sys_dlist_peek_head(__dl),				\
+		     __dns = sys_dlist_peek_next(__dl, __dn);		\
+	     __dn != NULL; __dn = __dns,				\
+		     __dns = sys_dlist_peek_next(__dl, __dn))
+
+/*
+ * @brief Provide the primitive to resolve the container of a list node
+ * Note: it is safe to use with NULL pointer nodes
+ *
+ * @param __dn A pointer on a sys_dnode_t to get its container
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_dnode_t within the container struct
+ */
+#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \
+	((__dn != NULL) ? CONTAINER_OF(__dn, __typeof__(*__cn), __n) : NULL)
+/*
+ * @brief Provide the primitive to peek container of the list head
+ *
+ * @param __dl A pointer on a sys_dlist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_dnode_t within the container struct
+ */
+#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \
+	SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek the next container
+ *
+ * @param __dl A pointer on a sys_dlist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_dnode_t within the container struct
+ */
+#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \
+	((__cn != NULL) ? \
+	 SYS_DLIST_CONTAINER(sys_dlist_peek_next(__dl, &(__cn->__n)),	\
+				      __cn, __n) : NULL)
+
+/**
+ * @brief Provide the primitive to iterate on a list under a container
+ * Note: the loop is unsafe and thus __cn should not be detached
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_DLIST_FOR_EACH_CONTAINER(l, c, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __dl A pointer on a sys_dlist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __n The field name of sys_dnode_t within the container struct
+ */
+#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n)			\
+	for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n);     \
+	     __cn != NULL;                                              \
+	     __cn = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
+
+/**
+ * @brief Provide the primitive to safely iterate on a list under a container
+ * Note: __cn can be detached, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_DLIST_FOR_EACH_CONTAINER_SAFE(l, c, cn, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __dl A pointer on a sys_dlist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __cns A pointer for the loop to run safely
+ * @param __n The field name of sys_dnode_t within the container struct
+ */
+#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n)	\
+	for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n),	\
+	     __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n);    \
+	     __cn != NULL; __cn = __cns,				\
+	     __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
+
+/**
+ * @brief initialize list to its empty state
+ *
+ * @param list the doubly-linked list
+ *
+ * @return N/A
+ */
+
+static inline void sys_dlist_init(sys_dlist_t *list)
+{
+	list->head = (sys_dnode_t *)list;
+	list->tail = (sys_dnode_t *)list;
+}
+
+#define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} }
+
+/**
+ * @brief initialize node to its state when not in a list
+ *
+ * @param node the node
+ *
+ * @return N/A
+ */
+
+static inline void sys_dnode_init(sys_dnode_t *node)
+{
+	node->next = NULL;
+	node->prev = NULL;
+}
+
+/**
+ * @brief check if a node is a member of any list
+ *
+ * @param node the node
+ *
+ * @return true if node is linked into a list, false if it is not
+ */
+
+static inline bool sys_dnode_is_linked(const sys_dnode_t *node)
+{
+	return node->next != NULL;
+}
+
+/**
+ * @brief check if a node is the list's head
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node to check
+ *
+ * @return true if node is the head, false otherwise
+ */
+
+static inline bool sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)
+{
+	return list->head == node;
+}
+
+/**
+ * @brief check if a node is the list's tail
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node to check
+ *
+ * @return true if node is the tail, false otherwise
+ */
+
+static inline bool sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node)
+{
+	return list->tail == node;
+}
+
+/**
+ * @brief check if the list is empty
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return true if empty, false otherwise
+ */
+
+static inline bool sys_dlist_is_empty(sys_dlist_t *list)
+{
+	return list->head == list;
+}
+
+/**
+ * @brief check if more than one node present
+ *
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return true if multiple nodes, false otherwise
+ */
+
+static inline bool sys_dlist_has_multiple_nodes(sys_dlist_t *list)
+{
+	return list->head != list->tail;
+}
+
+/**
+ * @brief get a reference to the head item in the list
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return a pointer to the head element, NULL if list is empty
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_head(sys_dlist_t *list)
+{
+	return sys_dlist_is_empty(list) ? NULL : list->head;
+}
+
+/**
+ * @brief get a reference to the head item in the list
+ *
+ * The list must be known to be non-empty.
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return a pointer to the head element
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_head_not_empty(sys_dlist_t *list)
+{
+	return list->head;
+}
+
+/**
+ * @brief get a reference to the next item in the list, node is not NULL
+ *
+ * Faster than sys_dlist_peek_next() if node is known not to be NULL.
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node from which to get the next element in the list
+ *
+ * @return a pointer to the next element from a node, NULL if node is the tail
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_next_no_check(sys_dlist_t *list,
+							sys_dnode_t *node)
+{
+	return (node == list->tail) ? NULL : node->next;
+}
+
+/**
+ * @brief get a reference to the next item in the list
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node from which to get the next element in the list
+ *
+ * @return a pointer to the next element from a node, NULL if node is the tail
+ * or NULL (when node comes from reading the head of an empty list).
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_next(sys_dlist_t *list,
+					       sys_dnode_t *node)
+{
+	return (node != NULL) ? sys_dlist_peek_next_no_check(list, node) : NULL;
+}
+
+/**
+ * @brief get a reference to the previous item in the list, node is not NULL
+ *
+ * Faster than sys_dlist_peek_prev() if node is known not to be NULL.
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node from which to get the previous element in the list
+ *
+ * @return a pointer to the previous element from a node, NULL if node is the
+ *	   tail
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_prev_no_check(sys_dlist_t *list,
+							sys_dnode_t *node)
+{
+	return (node == list->head) ? NULL : node->prev;
+}
+
+/**
+ * @brief get a reference to the previous item in the list
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the node from which to get the previous element in the list
+ *
+ * @return a pointer to the previous element from a node, NULL if node is the
+ * 	   tail or NULL (when node comes from reading the head of an empty
+ * 	   list).
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_prev(sys_dlist_t *list,
+					       sys_dnode_t *node)
+{
+	return (node != NULL) ? sys_dlist_peek_prev_no_check(list, node) : NULL;
+}
+
+/**
+ * @brief get a reference to the tail item in the list
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return a pointer to the tail element, NULL if list is empty
+ */
+
+static inline sys_dnode_t *sys_dlist_peek_tail(sys_dlist_t *list)
+{
+	return sys_dlist_is_empty(list) ? NULL : list->tail;
+}
+
+/**
+ * @brief add node to tail of list
+ *
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the element to append
+ *
+ * @return N/A
+ */
+
+static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
+{
+	node->next = list;
+	node->prev = list->tail;
+
+	list->tail->next = node;
+	list->tail = node;
+}
+
+/**
+ * @brief add node to head of list
+ *
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the element to append
+ *
+ * @return N/A
+ */
+
+static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
+{
+	node->next = list->head;
+	node->prev = list;
+
+	list->head->prev = node;
+	list->head = node;
+}
+
+/**
+ * @brief Insert a node into a list
+ *
+ * Insert a node before a specified node in a dlist.
+ *
+ * @param successor the position before which "node" will be inserted
+ * @param node the element to insert
+ */
+static inline void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
+{
+	node->prev = successor->prev;
+	node->next = successor;
+	successor->prev->next = node;
+	successor->prev = node;
+}
+
+/**
+ * @brief insert node at position
+ *
+ * Insert a node in a location depending on a external condition. The cond()
+ * function checks if the node is to be inserted _before_ the current node
+ * against which it is checked.
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param list the doubly-linked list to operate on
+ * @param node the element to insert
+ * @param cond a function that determines if the current node is the correct
+ *             insert point
+ * @param data parameter to cond()
+ *
+ * @return N/A
+ */
+
+static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node,
+	int (*cond)(sys_dnode_t *node, void *data), void *data)
+{
+	if (sys_dlist_is_empty(list)) {
+		sys_dlist_append(list, node);
+	} else {
+		sys_dnode_t *pos = sys_dlist_peek_head(list);
+
+		while ((pos != NULL) && (cond(pos, data) == 0)) {
+			pos = sys_dlist_peek_next(list, pos);
+		}
+		if (pos != NULL) {
+			sys_dlist_insert(pos, node);
+		} else {
+			sys_dlist_append(list, node);
+		}
+	}
+}
+
+/**
+ * @brief remove a specific node from a list
+ *
+ * The list is implicit from the node. The node must be part of a list.
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param node the node to remove
+ *
+ * @return N/A
+ */
+
+static inline void sys_dlist_remove(sys_dnode_t *node)
+{
+	node->prev->next = node->next;
+	node->next->prev = node->prev;
+	sys_dnode_init(node);
+}
+
+/**
+ * @brief get the first node in a list
+ *
+ * This and other sys_dlist_*() functions are not thread safe.
+ *
+ * @param list the doubly-linked list to operate on
+ *
+ * @return the first node in the list, NULL if list is empty
+ */
+
+static inline sys_dnode_t *sys_dlist_get(sys_dlist_t *list)
+{
+	sys_dnode_t *node = NULL;
+
+	if (!sys_dlist_is_empty(list)) {
+		node = list->head;
+		sys_dlist_remove(node);
+	}
+
+	return node;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_DLIST_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/errno_private.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/errno_private.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/errno_private.h	(working copy)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_
+#define ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_
+
+#include <toolchain.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: located here to avoid include dependency loops between errno.h
+ * and kernel.h
+ */
+
+/**
+ * return a pointer to a memory location containing errno
+ *
+ * errno is thread-specific, and can't just be a global. This pointer
+ * is guaranteed to be read/writable from user mode.
+ *
+ * @return Memory location of errno data for current thread
+ */
+__syscall int *z_errno(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <syscalls/errno_private.h>
+
+#endif /* ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/fdtable.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/fdtable.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/fdtable.h	(working copy)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_SYS_FDTABLE_H_
+#define ZEPHYR_INCLUDE_SYS_FDTABLE_H_
+
+#include <stdarg.h>
+#include <sys/types.h>
+/* FIXME: For native_posix ssize_t, off_t. */
+#include <fs/fs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * File descriptor virtual method table.
+ * Currently all operations beyond read/write/close go thru ioctl method.
+ */
+struct fd_op_vtable {
+	ssize_t (*read)(void *obj, void *buf, size_t sz);
+	ssize_t (*write)(void *obj, const void *buf, size_t sz);
+	int (*close)(void *obj);
+	int (*ioctl)(void *obj, unsigned int request, va_list args);
+};
+
+/**
+ * @brief Reserve file descriptor.
+ *
+ * This function allows to reserve a space for file descriptor entry in
+ * the underlying table, and thus allows caller to fail fast if no free
+ * descriptor is available. If this function succeeds, z_finalize_fd()
+ * or z_free_fd() must be called mandatorily.
+ *
+ * @return Allocated file descriptor, or -1 in case of error (errno is set)
+ */
+int z_reserve_fd(void);
+
+/**
+ * @brief Finalize creation of file descriptor.
+ *
+ * This function should be called exactly once after z_reserve_fd(), and
+ * should not be called in any other case.
+ *
+ * @param fd File descriptor previously returned by z_reserve_fd()
+ * @param obj pointer to I/O object structure
+ * @param vtable pointer to I/O operation implementations for the object
+ */
+void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable);
+
+/**
+ * @brief Allocate file descriptor for underlying I/O object.
+ *
+ * This function combines operations of z_reserve_fd() and z_finalize_fd()
+ * in one step, and provided for convenience.
+ *
+ * @param obj pointer to I/O object structure
+ * @param vtable pointer to I/O operation implementations for the object
+ *
+ * @return Allocated file descriptor, or -1 in case of error (errno is set)
+ */
+int z_alloc_fd(void *obj, const struct fd_op_vtable *vtable);
+
+/**
+ * @brief Release reserved file descriptor.
+ *
+ * This function may be called once after z_reserve_fd(), and should
+ * not be called in any other case.
+ *
+ * @param fd File descriptor previously returned by z_reserve_fd()
+ */
+void z_free_fd(int fd);
+
+/**
+ * @brief Get underlying object pointer from file descriptor.
+ *
+ * This function is useful for functions other than read/write/ioctl
+ * to look up underlying I/O object by fd, optionally checking its
+ * type (using vtable reference). If fd refers to invalid entry,
+ * NULL will be returned with errno set to EBADF. If fd is valid,
+ * but vtable param is not NULL and doesn't match object's vtable,
+ * NULL is returned and errno set to err param.
+ *
+ * @param fd File descriptor previously returned by z_reserve_fd()
+ * @param vtable Expected object vtable or NULL
+ * @param err errno value to set if object vtable doesn't match
+ *
+ * @return Object pointer or NULL, with errno set
+ */
+void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err);
+
+/**
+ * @brief Get underlying object pointer and vtable pointer from file descriptor.
+ *
+ * @param fd File descriptor previously returned by z_reserve_fd()
+ * @param vtable A pointer to a pointer variable to store the vtable
+ *
+ * @return Object pointer or NULL, with errno set
+ */
+void *z_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable);
+
+/**
+ * @brief Call ioctl vmethod on an object using varargs.
+ *
+ * We need this helper function because ioctl vmethod is declared to
+ * take va_list and the only portable way to construct va_list is from
+ * function's ... parameters.
+ *
+ * @param vtable vtable containing ioctl function pointer
+ * @param obj Object to call ioctl on
+ * @param request ioctl request number
+ * @param ... Variadic arguments to ioctl
+ */
+static inline int z_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj,
+				       unsigned long request, ...)
+{
+	va_list args;
+	int res;
+
+	va_start(args, request);
+	res = vtable->ioctl(obj, request, args);
+	va_end(args);
+
+	return res;
+}
+
+/**
+ * Request codes for fd_op_vtable.ioctl().
+ *
+ * Note that these codes are internal Zephyr numbers, for internal
+ * Zephyr operations (and subject to change without notice, not part
+ * of "stable ABI"). These are however expected to co-exist with
+ * "well-known" POSIX/Linux ioctl numbers, and not clash with them.
+ */
+enum {
+	/* Codes below 0x100 are reserved for fcntl() codes. */
+	ZFD_IOCTL_FSYNC = 0x100,
+	ZFD_IOCTL_LSEEK,
+	ZFD_IOCTL_POLL_PREPARE,
+	ZFD_IOCTL_POLL_UPDATE,
+	ZFD_IOCTL_POLL_OFFLOAD,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_FDTABLE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/kobject.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/kobject.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/kobject.h	(working copy)
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_SYS_KOBJECT_H
+#define ZEPHYR_INCLUDE_SYS_KOBJECT_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct k_thread;
+struct k_mutex;
+struct z_futex_data;
+
+/**
+ * @brief Kernel Object Types
+ *
+ * This enumeration needs to be kept in sync with the lists of kernel objects
+ * and subsystems in scripts/gen_kobject_list.py, as well as the otype_to_str()
+ * function in kernel/userspace.c
+ */
+enum k_objects {
+	K_OBJ_ANY,
+
+	/** @cond
+	 *  Doxygen should ignore this build-time generated include file
+	 *  when genrating API documentation.  Enumeration values are
+	 *  generated during build by gen_kobject_list.py.  It includes
+	 *  basic kernel objects (e.g.  pipes and mutexes) and driver types.
+	 */
+#include <kobj-types-enum.h>
+	/** @endcond
+	 */
+
+	K_OBJ_LAST
+};
+/**
+ * @defgroup usermode_apis User Mode APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+#ifdef CONFIG_USERSPACE
+#ifdef CONFIG_GEN_PRIV_STACKS
+/* Metadata struct for K_OBJ_THREAD_STACK_ELEMENT */
+struct z_stack_data {
+	/* Size of the entire stack object, including reserved areas */
+	size_t size;
+
+	/* Stack buffer for privilege mode elevations */
+	uint8_t *priv;
+};
+#endif /* CONFIG_GEN_PRIV_STACKS */
+
+/* Object extra data. Only some objects use this, determined by object type */
+union z_object_data {
+	/* Backing mutex for K_OBJ_SYS_MUTEX */
+	struct k_mutex *mutex;
+
+	/* Numerical thread ID for K_OBJ_THREAD */
+	unsigned int thread_id;
+
+#ifdef CONFIG_GEN_PRIV_STACKS
+	/* Metadata for K_OBJ_THREAD_STACK_ELEMENT */
+	struct z_stack_data *stack_data;
+#else
+	/* Stack buffer size for K_OBJ_THREAD_STACK_ELEMENT */
+	size_t stack_size;
+#endif /* CONFIG_GEN_PRIV_STACKS */
+
+	/* Futex wait queue and spinlock for K_OBJ_FUTEX */
+	struct z_futex_data *futex_data;
+
+	/* All other objects */
+	int unused;
+};
+
+/* Table generated by gperf, these objects are retrieved via
+ * z_object_find() */
+struct z_object {
+	void *name;
+	uint8_t perms[CONFIG_MAX_THREAD_BYTES];
+	uint8_t type;
+	uint8_t flags;
+	union z_object_data data;
+} __packed __aligned(4);
+
+struct z_object_assignment {
+	struct k_thread *thread;
+	void * const *objects;
+};
+
+/**
+ * @brief Grant a static thread access to a list of kernel objects
+ *
+ * For threads declared with K_THREAD_DEFINE(), grant the thread access to
+ * a set of kernel objects. These objects do not need to be in an initialized
+ * state. The permissions will be granted when the threads are initialized
+ * in the early boot sequence.
+ *
+ * All arguments beyond the first must be pointers to kernel objects.
+ *
+ * @param name_ Name of the thread, as passed to K_THREAD_DEFINE()
+ */
+#define K_THREAD_ACCESS_GRANT(name_, ...) \
+	static void * const _CONCAT(_object_list_, name_)[] = \
+		{ __VA_ARGS__, NULL }; \
+	static const Z_STRUCT_SECTION_ITERABLE(z_object_assignment, \
+					_CONCAT(_object_access_, name_)) = \
+			{ (&_k_thread_obj_ ## name_), \
+			  (_CONCAT(_object_list_, name_)) }
+
+/** Object initialized */
+#define K_OBJ_FLAG_INITIALIZED	BIT(0)
+/** Object is Public */
+#define K_OBJ_FLAG_PUBLIC	BIT(1)
+/** Object allocated */
+#define K_OBJ_FLAG_ALLOC	BIT(2)
+/** Driver Object */
+#define K_OBJ_FLAG_DRIVER	BIT(3)
+
+/**
+ * Lookup a kernel object and init its metadata if it exists
+ *
+ * Calling this on an object will make it usable from userspace.
+ * Intended to be called as the last statement in kernel object init
+ * functions.
+ *
+ * @param obj Address of the kernel object
+ */
+void z_object_init(const void *obj);
+#else
+/* LCOV_EXCL_START */
+#define K_THREAD_ACCESS_GRANT(thread, ...)
+
+/**
+ * @internal
+ */
+static inline void z_object_init(const void *obj)
+{
+	ARG_UNUSED(obj);
+}
+
+/**
+ * @internal
+ */
+static inline void z_impl_k_object_access_grant(const void *object,
+						struct k_thread *thread)
+{
+	ARG_UNUSED(object);
+	ARG_UNUSED(thread);
+}
+
+/**
+ * @internal
+ */
+static inline void k_object_access_revoke(const void *object,
+					  struct k_thread *thread)
+{
+	ARG_UNUSED(object);
+	ARG_UNUSED(thread);
+}
+
+/**
+ * @internal
+ */
+static inline void z_impl_k_object_release(const void *object)
+{
+	ARG_UNUSED(object);
+}
+
+static inline void k_object_access_all_grant(const void *object)
+{
+	ARG_UNUSED(object);
+}
+/* LCOV_EXCL_STOP */
+#endif /* !CONFIG_USERSPACE */
+
+/**
+ * Grant a thread access to a kernel object
+ *
+ * The thread will be granted access to the object if the caller is from
+ * supervisor mode, or the caller is from user mode AND has permissions
+ * on both the object and the thread whose access is being granted.
+ *
+ * @param object Address of kernel object
+ * @param thread Thread to grant access to the object
+ */
+__syscall void k_object_access_grant(const void *object,
+				     struct k_thread *thread);
+
+/**
+ * Revoke a thread's access to a kernel object
+ *
+ * The thread will lose access to the object if the caller is from
+ * supervisor mode, or the caller is from user mode AND has permissions
+ * on both the object and the thread whose access is being revoked.
+ *
+ * @param object Address of kernel object
+ * @param thread Thread to remove access to the object
+ */
+void k_object_access_revoke(const void *object, struct k_thread *thread);
+
+/**
+ * @brief Release an object
+ *
+ * Allows user threads to drop their own permission on an object
+ * Their permissions are automatically cleared when a thread terminates.
+ *
+ * @param object The object to be released
+ *
+ */
+__syscall void k_object_release(const void *object);
+
+/**
+ * Grant all present and future threads access to an object
+ *
+ * If the caller is from supervisor mode, or the caller is from user mode and
+ * have sufficient permissions on the object, then that object will have
+ * permissions granted to it for *all* current and future threads running in
+ * the system, effectively becoming a public kernel object.
+ *
+ * Use of this API should be avoided on systems that are running untrusted code
+ * as it is possible for such code to derive the addresses of kernel objects
+ * and perform unwanted operations on them.
+ *
+ * It is not possible to revoke permissions on public objects; once public,
+ * any thread may use it.
+ *
+ * @param object Address of kernel object
+ */
+void k_object_access_all_grant(const void *object);
+
+/**
+ * Allocate a kernel object of a designated type
+ *
+ * This will instantiate at runtime a kernel object of the specified type,
+ * returning a pointer to it. The object will be returned in an uninitialized
+ * state, with the calling thread being granted permission on it. The memory
+ * for the object will be allocated out of the calling thread's resource pool.
+ *
+ * Currently, allocation of thread stacks is not supported.
+ *
+ * @param otype Requested kernel object type
+ * @return A pointer to the allocated kernel object, or NULL if memory wasn't
+ * available
+ */
+__syscall void *k_object_alloc(enum k_objects otype);
+
+#ifdef CONFIG_DYNAMIC_OBJECTS
+/**
+ * Allocate memory and install as a generic kernel object
+ *
+ * This is a low-level function to allocate some memory, and register that
+ * allocated memory in the kernel object lookup tables with type K_OBJ_ANY.
+ * Initialization state and thread permissions will be cleared. The
+ * returned z_object's data value will be uninitialized.
+ *
+ * Most users will want to use k_object_alloc() instead.
+ *
+ * Memory allocated will be drawn from the calling thread's reasource pool
+ * and may be freed later by passing the actual object pointer (found
+ * in the returned z_object's 'name' member) to k_object_free().
+ *
+ * @param size Size of the allocated object
+ * @return NULL on insufficient memory
+ * @return A pointer to the associated z_object that is installed in the
+ *	kernel object tables
+ */
+struct z_object *z_dynamic_object_create(size_t size);
+
+/**
+ * Free a kernel object previously allocated with k_object_alloc()
+ *
+ * This will return memory for a kernel object back to resource pool it was
+ * allocated from.  Care must be exercised that the object will not be used
+ * during or after when this call is made.
+ *
+ * @param obj Pointer to the kernel object memory address.
+ */
+void k_object_free(void *obj);
+#else
+/* LCOV_EXCL_START */
+static inline void *z_impl_k_object_alloc(enum k_objects otype)
+{
+	ARG_UNUSED(otype);
+
+	return NULL;
+}
+
+static inline struct z_object *z_dynamic_object_create(size_t size)
+{
+	ARG_UNUSED(size);
+
+	return NULL;
+}
+
+/**
+ * @brief Free an object
+ *
+ * @param obj
+ */
+static inline void k_object_free(void *obj)
+{
+	ARG_UNUSED(obj);
+}
+/* LCOV_EXCL_STOP */
+#endif /* CONFIG_DYNAMIC_OBJECTS */
+
+/** @} */
+
+#include <syscalls/kobject.h>
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/sys/libc-hooks.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/libc-hooks.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/libc-hooks.h	(working copy)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_LIBC_HOOKS_H_
+#define ZEPHYR_INCLUDE_SYS_LIBC_HOOKS_H_
+
+#include <toolchain.h>
+#include <stdio.h>
+#include <stddef.h>
+
+/*
+ * Private header for specifying accessory functions to the C library internals
+ * that need to call into the kernel as system calls
+ */
+
+#ifdef CONFIG_NEWLIB_LIBC
+
+/* syscall generation ignores preprocessor, ensure this is defined to ensure
+ * we don't have compile errors
+ */
+#define _MLIBC_RESTRICT
+
+__syscall int z_zephyr_read_stdin(char *buf, int nbytes);
+
+__syscall int z_zephyr_write_stdout(const void *buf, int nbytes);
+
+#else
+/* Minimal libc */
+
+__syscall int zephyr_fputc(int c, FILE * stream);
+
+__syscall size_t zephyr_fwrite(const void *_MLIBC_RESTRICT ptr, size_t size,
+				size_t nitems, FILE *_MLIBC_RESTRICT stream);
+#endif /* CONFIG_NEWLIB_LIBC */
+
+#ifdef CONFIG_USERSPACE
+#if defined(CONFIG_NEWLIB_LIBC)
+/* If we are using newlib, the heap arena is in one of two areas:
+ *  - If we have an MPU that requires power of two alignment, the heap bounds
+ *    must be specified in Kconfig via CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE.
+ *  - Otherwise, the heap arena on most arches starts at a suitably
+ *    aligned base addreess after the `_end` linker symbol, through to the end
+ *    of system RAM.
+ */
+#if (!defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) || \
+     (defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) && \
+      CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE))
+#define Z_MALLOC_PARTITION_EXISTS 1
+extern struct k_mem_partition z_malloc_partition;
+#endif
+#elif defined(CONFIG_MINIMAL_LIBC)
+#if (CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0)
+/* Minimal libc by default has no malloc arena, its size must be set in
+ * Kconfig via CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE
+ */
+#define Z_MALLOC_PARTITION_EXISTS 1
+#endif /* CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0 */
+#endif /* CONFIG_MINIMAL_LIBC */
+
+#ifdef Z_MALLOC_PARTITION_EXISTS
+/* Memory partition containing the libc malloc arena. Configuration controls
+ * whether this is available, and an arena size may need to be set.
+ */
+extern struct k_mem_partition z_malloc_partition;
+#endif
+
+#if defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_STACK_CANARIES)
+/* Minimal libc has no globals. We do put the stack canary global in the
+ * libc partition since it is not worth placing in a partition of its own.
+ */
+#define Z_LIBC_PARTITION_EXISTS 1
+
+/* C library globals, except the malloc arena */
+extern struct k_mem_partition z_libc_partition;
+#endif
+#endif /* CONFIG_USERSPACE */
+
+#include <syscalls/libc-hooks.h>
+
+#endif /* ZEPHYR_INCLUDE_SYS_LIBC_HOOKS_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/list_gen.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/list_gen.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/list_gen.h	(working copy)
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_LIST_GEN_H_
+#define ZEPHYR_INCLUDE_SYS_LIST_GEN_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/util.h>
+
+#define Z_GENLIST_FOR_EACH_NODE(__lname, __l, __sn)			\
+	for (__sn = sys_ ## __lname ## _peek_head(__l); __sn != NULL;	\
+	     __sn = sys_ ## __lname ## _peek_next(__sn))
+
+
+#define Z_GENLIST_ITERATE_FROM_NODE(__lname, __l, __sn)			\
+	for (__sn = __sn ? sys_ ## __lname ## _peek_next_no_check(__sn)	\
+			 : sys_ ## __lname ## _peek_head(__l);		\
+	     __sn != NULL;						\
+	     __sn = sys_ ## __lname ## _peek_next(__sn))
+
+#define Z_GENLIST_FOR_EACH_NODE_SAFE(__lname, __l, __sn, __sns)		\
+	for (__sn = sys_ ## __lname ## _peek_head(__l),			\
+		     __sns = sys_ ## __lname ## _peek_next(__sn);	\
+	     __sn != NULL ; __sn = __sns,				\
+		     __sns = sys_ ## __lname ## _peek_next(__sn))
+
+#define Z_GENLIST_CONTAINER(__ln, __cn, __n)				\
+	((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)
+
+#define Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n)		\
+	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_head(__l), __cn, __n)
+
+#define Z_GENLIST_PEEK_TAIL_CONTAINER(__lname, __l, __cn, __n)		\
+	Z_GENLIST_CONTAINER(sys_ ## __lname ## _peek_tail(__l), __cn, __n)
+
+#define Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n)		\
+	((__cn) ? Z_GENLIST_CONTAINER(					\
+			sys_ ## __lname ## _peek_next(&((__cn)->__n)),	\
+			__cn, __n) : NULL)
+
+#define Z_GENLIST_FOR_EACH_CONTAINER(__lname, __l, __cn, __n)		\
+	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn,	\
+						  __n);			\
+	     __cn != NULL;						\
+	     __cn = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))
+
+#define Z_GENLIST_FOR_EACH_CONTAINER_SAFE(__lname, __l, __cn, __cns, __n)     \
+	for (__cn = Z_GENLIST_PEEK_HEAD_CONTAINER(__lname, __l, __cn, __n),   \
+	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n); \
+	     __cn != NULL; __cn = __cns,				\
+	     __cns = Z_GENLIST_PEEK_NEXT_CONTAINER(__lname, __cn, __n))
+
+#define Z_GENLIST_IS_EMPTY(__lname)					\
+	static inline bool						\
+	sys_ ## __lname ## _is_empty(sys_ ## __lname ## _t *list)	\
+	{								\
+		return (sys_ ## __lname ## _peek_head(list) == NULL);	\
+	}
+
+#define Z_GENLIST_PEEK_NEXT_NO_CHECK(__lname, __nname)			    \
+	static inline sys_ ## __nname ## _t *				    \
+	sys_ ## __lname ## _peek_next_no_check(sys_ ## __nname ## _t *node) \
+	{								    \
+		return z_ ## __nname ## _next_peek(node);		    \
+	}
+
+#define Z_GENLIST_PEEK_NEXT(__lname, __nname)				     \
+	static inline sys_ ## __nname ## _t *				     \
+	sys_ ## __lname ## _peek_next(sys_ ## __nname ## _t *node)	     \
+	{								     \
+		return node != NULL ?                                        \
+			sys_ ## __lname ## _peek_next_no_check(node) :       \
+			      NULL;					     \
+	}
+
+#define Z_GENLIST_PREPEND(__lname, __nname)				      \
+	static inline void						      \
+	sys_ ## __lname ## _prepend(sys_ ## __lname ## _t *list,	      \
+				    sys_ ## __nname ## _t *node)	      \
+	{								      \
+		z_ ## __nname ## _next_set(node,			      \
+					sys_ ## __lname ## _peek_head(list)); \
+		z_ ## __lname ## _head_set(list, node);			      \
+									      \
+		if (sys_ ## __lname ## _peek_tail(list) == NULL) {	      \
+			z_ ## __lname ## _tail_set(list,		      \
+					sys_ ## __lname ## _peek_head(list)); \
+		}							      \
+	}
+
+#define Z_GENLIST_APPEND(__lname, __nname)				\
+	static inline void						\
+	sys_ ## __lname ## _append(sys_ ## __lname ## _t *list,		\
+				   sys_ ## __nname ## _t *node)		\
+	{								\
+		z_ ## __nname ## _next_set(node, NULL);			\
+									\
+		if (sys_ ## __lname ## _peek_tail(list) == NULL) {	\
+			z_ ## __lname ## _tail_set(list, node);		\
+			z_ ## __lname ## _head_set(list, node);		\
+		} else {						\
+			z_ ## __nname ## _next_set(			\
+				sys_ ## __lname ## _peek_tail(list),	\
+				node);					\
+			z_ ## __lname ## _tail_set(list, node);		\
+		}							\
+	}
+
+#define Z_GENLIST_APPEND_LIST(__lname, __nname)				\
+	static inline void						\
+	sys_ ## __lname ## _append_list(sys_ ## __lname ## _t *list,	\
+					void *head, void *tail)		\
+{									\
+	if (sys_ ## __lname ## _peek_tail(list) == NULL) {		\
+		z_ ## __lname ## _head_set(list,			\
+					(sys_ ## __nname ## _t *)head); \
+	} else {							\
+		z_ ## __nname ## _next_set(				\
+			sys_ ## __lname ## _peek_tail(list),		\
+			(sys_ ## __nname ## _t *)head);			\
+	}								\
+	z_ ## __lname ## _tail_set(list,				\
+				     (sys_ ## __nname ## _t *)tail);	\
+}
+
+#define Z_GENLIST_MERGE_LIST(__lname, __nname)				\
+	static inline void						\
+	sys_ ## __lname ## _merge_ ## __lname (				\
+				sys_ ## __lname ## _t *list,		\
+				sys_ ## __lname ## _t *list_to_append)	\
+	{								\
+		sys_ ## __nname ## _t *head, *tail;			\
+		head = sys_ ## __lname ## _peek_head(list_to_append);	\
+		tail = sys_ ## __lname ## _peek_tail(list_to_append);	\
+		sys_ ## __lname ## _append_list(list, head, tail);	\
+		sys_ ## __lname ## _init(list_to_append);		\
+	}
+
+#define Z_GENLIST_INSERT(__lname, __nname)				\
+	static inline void						\
+	sys_ ## __lname ## _insert(sys_ ## __lname ## _t *list,		\
+				   sys_ ## __nname ## _t *prev,		\
+				   sys_ ## __nname ## _t *node)		\
+	{								\
+		if (prev == NULL) {					\
+			sys_ ## __lname ## _prepend(list, node);	\
+		} else if (z_ ## __nname ## _next_peek(prev) == NULL) {	\
+			sys_ ## __lname ## _append(list, node);		\
+		} else {						\
+			z_ ## __nname ## _next_set(node,		\
+				z_ ## __nname ## _next_peek(prev));	\
+			z_ ## __nname ## _next_set(prev, node);		\
+		}							\
+	}
+
+#define Z_GENLIST_GET_NOT_EMPTY(__lname, __nname)			\
+	static inline sys_ ## __nname ## _t *				\
+	sys_ ## __lname ## _get_not_empty(sys_ ## __lname ## _t *list)	\
+	{								\
+		sys_ ## __nname ## _t *node =				\
+				sys_ ## __lname ## _peek_head(list);	\
+									\
+		z_ ## __lname ## _head_set(list,			\
+				z_ ## __nname ## _next_peek(node));	\
+		if (sys_ ## __lname ## _peek_tail(list) == node) {	\
+			z_ ## __lname ## _tail_set(list,		\
+				sys_ ## __lname ## _peek_head(list));	\
+		}							\
+									\
+		return node;						\
+	}
+
+#define Z_GENLIST_GET(__lname, __nname)					\
+	static inline sys_ ## __nname ## _t *				\
+	sys_ ## __lname ## _get(sys_ ## __lname ## _t *list)		\
+	{								\
+		return sys_ ## __lname ## _is_empty(list) ? NULL :	\
+			sys_ ## __lname ## _get_not_empty(list);	\
+	}
+
+#define Z_GENLIST_REMOVE(__lname, __nname)				      \
+	static inline void						      \
+	sys_ ## __lname ## _remove(sys_ ## __lname ## _t *list,		      \
+				   sys_ ## __nname ## _t *prev_node,	      \
+				   sys_ ## __nname ## _t *node)		      \
+	{								      \
+		if (prev_node == NULL) {				      \
+			z_ ## __lname ## _head_set(list,		      \
+				z_ ## __nname ## _next_peek(node));	      \
+									      \
+			/* Was node also the tail? */			      \
+			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
+				z_ ## __lname ## _tail_set(list,	      \
+					sys_ ## __lname ## _peek_head(list)); \
+			}						      \
+		} else {						      \
+			z_ ## __nname ## _next_set(prev_node,		      \
+				z_ ## __nname ## _next_peek(node));	      \
+									      \
+			/* Was node the tail? */			      \
+			if (sys_ ## __lname ## _peek_tail(list) == node) {    \
+				z_ ## __lname ## _tail_set(list,	      \
+							     prev_node);      \
+			}						      \
+		}							      \
+									      \
+		z_ ## __nname ## _next_set(node, NULL);			      \
+	}
+
+#define Z_GENLIST_FIND_AND_REMOVE(__lname, __nname)			 \
+	static inline bool						 \
+	sys_ ## __lname ## _find_and_remove(sys_ ## __lname ## _t *list, \
+					    sys_ ## __nname ## _t *node) \
+	{								 \
+		sys_ ## __nname ## _t *prev = NULL;			 \
+		sys_ ## __nname ## _t *test;				 \
+									 \
+		Z_GENLIST_FOR_EACH_NODE(__lname, list, test) {		 \
+			if (test == node) {				 \
+				sys_ ## __lname ## _remove(list, prev,	 \
+							   node);	 \
+				return true;				 \
+			}						 \
+									 \
+			prev = test;					 \
+		}							 \
+									 \
+		return false;						 \
+	}
+
+#endif /* ZEPHYR_INCLUDE_SYS_LIST_GEN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/mem_manage.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mem_manage.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mem_manage.h	(working copy)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H
+#define ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H
+
+#include <sys/util.h>
+
+/*
+ * Caching mode definitions. These are mutually exclusive.
+ */
+
+/** No caching. Most drivers want this. */
+#define K_MEM_CACHE_NONE	0
+
+/** Write-through caching. Used by certain drivers. */
+#define K_MEM_CACHE_WT		1
+
+/** Full write-back caching. Any RAM mapped wants this. */
+#define K_MEM_CACHE_WB		2
+
+/** Reserved bits for cache modes in k_map() flags argument */
+#define K_MEM_CACHE_MASK	(BIT(3) - 1)
+
+/*
+ * Region permission attributes. Default is read-only, no user, no exec
+ */
+
+/** Region will have read/write access (and not read-only) */
+#define K_MEM_PERM_RW		BIT(3)
+
+/** Region will be executable (normally forbidden) */
+#define K_MEM_PERM_EXEC		BIT(4)
+
+/** Region will be accessible to user mode (normally supervisor-only) */
+#define K_MEM_PERM_USER		BIT(5)
+
+#ifndef _ASMLANGUAGE
+#include <stdint.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <sys/__assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Map a physical memory region into the kernel's virtual address space
+ *
+ * Given a physical address and a size, return a linear address
+ * representing the base of where the physical region is mapped in
+ * the virtual address space for the Zephyr kernel.
+ *
+ * This function alters the active page tables in the area reserved
+ * for the kernel. This function will choose the virtual address
+ * and return it to the caller.
+ *
+ * Portable code should never assume that phys_addr and linear_addr will
+ * be equal.
+ *
+ * Once created, mappings are permanent.
+ *
+ * Caching and access properties are controlled by the 'flags' parameter.
+ * Unused bits in 'flags' are reserved for future expansion.
+ * A caching mode must be selected. By default, the region is read-only
+ * with user access and code execution forbidden. This policy is changed
+ * by passing K_MEM_CACHE_* and K_MEM_PERM_* macros into the 'flags' parameter.
+ *
+ * If there is insufficient virtual address space for the mapping, or
+ * bad flags are passed in, or if additional memory is needed to update
+ * page tables that is not available, this will generate a kernel panic.
+ *
+ * This API is only available if CONFIG_MMU is enabled.
+ *
+ * This API is part of infrastructure still under development and may
+ * change.
+ *
+ * @param linear_addr [out] Output linear address storage location
+ * @param phys_addr Physical address base of the memory region
+ * @param size Size of the memory region
+ * @param flags Caching mode and access flags, see K_MAP_* macros
+ */
+void z_mem_map(uint8_t **linear_addr, uintptr_t phys_addr, size_t size,
+	       uint32_t flags);
+
+/**
+ * Given an arbitrary region, provide a aligned region that covers it
+ *
+ * The returned region will have both its base address and size aligned
+ * to the provided alignment value.
+ *
+ * @param aligned_addr [out] Aligned address
+ * @param aligned_size [out] Aligned region size
+ * @param addr Region base address
+ * @param size Region size
+ * @param align What to align the address and size to
+ * @retval offset between aligned_addr and addr
+ */
+size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size,
+			  uintptr_t addr, size_t size, size_t align);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_ASMLANGUAGE */
+#endif /* ZEPHYR_INCLUDE_SYS_MEM_MANAGE_H */
Index: ModuleDemo/BLE/CM0/User/include/sys/mempool.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mempool.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mempool.h	(working copy)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_MEMPOOL_H_
+#define ZEPHYR_INCLUDE_SYS_MEMPOOL_H_
+
+#include <kernel.h>
+#include <sys/mempool_base.h>
+#include <sys/mutex.h>
+
+struct sys_mem_pool {
+	struct sys_mem_pool_base base;
+	struct sys_mutex mutex;
+};
+
+struct sys_mem_pool_block {
+	struct sys_mem_pool *pool;
+	uint32_t level : 4;
+	uint32_t block : 28;
+};
+
+/**
+ * @brief Statically define system memory pool
+ *
+ * The memory pool's buffer contains @a n_max blocks that are @a max_size bytes
+ * long. The memory pool allows blocks to be repeatedly partitioned into
+ * quarters, down to blocks of @a min_size bytes long. The buffer is aligned
+ * to a @a align -byte boundary.
+ *
+ * If the pool is to be accessed outside the module where it is defined, it
+ * can be declared via
+ *
+ * @code extern struct sys_mem_pool <name>; @endcode
+ *
+ * This pool will not be in an initialized state. You will still need to
+ * run sys_mem_pool_init() on it before using any other APIs.
+ *
+ * @param name Name of the memory pool.
+ * @param ignored ignored, any value
+ * @param minsz Size of the smallest blocks in the pool (in bytes).
+ * @param maxsz Size of the largest blocks in the pool (in bytes).
+ * @param nmax Number of maximum sized blocks in the pool.
+ * @param align Alignment of the pool's buffer (power of 2).
+ * @param section Destination binary section for pool data
+ */
+#define SYS_MEM_POOL_DEFINE(name, ignored, minsz, maxsz, nmax, align, section) \
+	char __aligned(WB_UP(align)) Z_GENERIC_SECTION(section)		\
+		_mpool_buf_##name[WB_UP(maxsz) * nmax			\
+				  + _MPOOL_BITS_SIZE(maxsz, minsz, nmax)]; \
+	struct sys_mem_pool_lvl Z_GENERIC_SECTION(section)		\
+		_mpool_lvls_##name[Z_MPOOL_LVLS(maxsz, minsz)];		\
+	Z_GENERIC_SECTION(section) struct sys_mem_pool name = {		\
+		.base = {						\
+			.buf = _mpool_buf_##name,			\
+			.max_sz = WB_UP(maxsz),				\
+			.n_max = nmax,					\
+			.n_levels = Z_MPOOL_LVLS(maxsz, minsz),		\
+			.levels = _mpool_lvls_##name,			\
+			.flags = SYS_MEM_POOL_USER			\
+		}							\
+	};								\
+	BUILD_ASSERT(WB_UP(maxsz) >= _MPOOL_MINBLK)
+
+/**
+ * @brief Initialize a memory pool
+ *
+ * This is intended to complete initialization of memory pools that have been
+ * declared with SYS_MEM_POOL_DEFINE().
+ *
+ * @param p Memory pool to initialize
+ */
+static inline void sys_mem_pool_init(struct sys_mem_pool *p)
+{
+	z_sys_mem_pool_base_init(&p->base);
+}
+
+/**
+ * @brief Allocate a block of memory
+ *
+ * Allocate a chunk of memory from a memory pool. This cannot be called from
+ * interrupt context.
+ *
+ * @param p Address of the memory pool
+ * @param size Requested size of the memory block
+ * @return A pointer to the requested memory, or NULL if none is available
+ */
+void *sys_mem_pool_alloc(struct sys_mem_pool *p, size_t size);
+
+/**
+ * @brief Free memory allocated from a memory pool
+ *
+ * Free memory previously allocated by sys_mem_pool_alloc().
+ * It is safe to pass NULL to this function, in which case it is a no-op.
+ *
+ * @param ptr Pointer to previously allocated memory
+ */
+void sys_mem_pool_free(void *ptr);
+
+/**
+ * @brief Try to perform in-place expansion of memory allocated from a pool
+ *
+ * Return 0 if memory previously allocated by sys_mem_pool_alloc()
+ * can accommodate a new size, otherwise return the size of data that
+ * needs to be copied over to new memory.
+ *
+ * @param ptr Pointer to previously allocated memory
+ * @param new_size New size requested for the memory block
+ * @return A 0 if OK, or size of data to copy elsewhere
+ */
+size_t sys_mem_pool_try_expand_inplace(void *ptr, size_t new_size);
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/sys/mempool_base.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mempool_base.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/mempool_base.h	(working copy)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_MEMPOOL_BASE_H_
+#define ZEPHYR_INCLUDE_SYS_MEMPOOL_BASE_H_
+
+#include <types.h>
+#include <stddef.h>
+
+/*
+ * Definitions and macros used by both the IRQ-safe k_mem_pool and user-mode
+ * compatible sys_mem_pool implementations
+ */
+
+struct sys_mem_pool_lvl {
+	union {
+		uint32_t *bits_p;
+		uint32_t bits[sizeof(uint32_t *)/4];
+	};
+	sys_dlist_t free_list;
+};
+
+#define SYS_MEM_POOL_KERNEL	BIT(0)
+#define SYS_MEM_POOL_USER	BIT(1)
+
+struct sys_mem_pool_base {
+	void *buf;
+	size_t max_sz;
+	uint16_t n_max;
+	uint8_t n_levels;
+	int8_t max_inline_level;
+	struct sys_mem_pool_lvl *levels;
+	uint8_t flags;
+};
+
+#define _MPOOL_MINBLK sizeof(sys_dnode_t)
+
+#define Z_MPOOL_HAVE_LVL(maxsz, minsz, l) \
+	(((maxsz) >> (2*(l))) >= MAX((minsz), _MPOOL_MINBLK) ? 1 : 0)
+
+#define Z_MPOOL_LVLS(maxsz, minsz)		\
+	(Z_MPOOL_HAVE_LVL((maxsz), (minsz), 0) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 1) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 2) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 3) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 4) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 5) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 6) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 7) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 8) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 9) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 10) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 11) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 12) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 13) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 14) +	\
+	Z_MPOOL_HAVE_LVL((maxsz), (minsz), 15))
+
+/* Rounds the needed bits up to integer multiples of uint32_t */
+#define Z_MPOOL_LBIT_WORDS_UNCLAMPED(n_max, l) \
+	((((n_max) << (2*(l))) + 31) / 32)
+
+/* One or two 32-bit words gets stored free unioned with the pointer,
+ * otherwise the calculated unclamped value
+ */
+#define Z_MPOOL_LBIT_WORDS(n_max, l)					 \
+	(Z_MPOOL_LBIT_WORDS_UNCLAMPED(n_max, l) <= sizeof(uint32_t *)/4 ? 0 \
+	 : Z_MPOOL_LBIT_WORDS_UNCLAMPED(n_max, l))
+
+/* How many bytes for the bitfields of a single level? */
+#define Z_MPOOL_LBIT_BYTES(maxsz, minsz, l, n_max)	\
+	(Z_MPOOL_HAVE_LVL((maxsz), (minsz), (l)) ?	\
+	 4 * Z_MPOOL_LBIT_WORDS((n_max), l) : 0)
+
+/* Size of the bitmap array that follows the buffer in allocated memory */
+#define _MPOOL_BITS_SIZE(maxsz, minsz, n_max) \
+	(Z_MPOOL_LBIT_BYTES(maxsz, minsz, 0, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 1, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 2, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 3, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 4, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 5, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 6, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 7, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 8, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 9, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 10, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 11, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 12, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 13, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 14, n_max) +	\
+	Z_MPOOL_LBIT_BYTES(maxsz, minsz, 15, n_max))
+
+
+void z_sys_mem_pool_base_init(struct sys_mem_pool_base *p);
+
+int z_sys_mem_pool_block_alloc(struct sys_mem_pool_base *p, size_t size,
+			      uint32_t *level_p, uint32_t *block_p, void **data_p);
+
+void z_sys_mem_pool_block_free(struct sys_mem_pool_base *p, uint32_t level,
+			      uint32_t block);
+
+#endif /* ZEPHYR_INCLUDE_SYS_MEMPOOL_BASE_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/notify.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/notify.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/notify.h	(working copy)
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2019 Peter Bigot Consulting, LLC
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_NOTIFY_H_
+#define ZEPHYR_INCLUDE_SYS_NOTIFY_H_
+
+#include <kernel.h>
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sys_notify;
+
+/*
+ * Flag value that overwrites the method field when the operation has
+ * completed.
+ */
+#define SYS_NOTIFY_METHOD_COMPLETED 0
+
+/*
+ * Indicates that no notification will be provided.
+ *
+ * Callers must check for completions using
+ * sys_notify_fetch_result().
+ *
+ * See sys_notify_init_spinwait().
+ */
+#define SYS_NOTIFY_METHOD_SPINWAIT 1
+
+/*
+ * Select notification through @ref k_poll signal
+ *
+ * See sys_notify_init_signal().
+ */
+#define SYS_NOTIFY_METHOD_SIGNAL 2
+
+/*
+ * Select notification through a user-provided callback.
+ *
+ * See sys_notify_init_callback().
+ */
+#define SYS_NOTIFY_METHOD_CALLBACK 3
+
+#define SYS_NOTIFY_METHOD_MASK 0x03U
+#define SYS_NOTIFY_METHOD_POS 0
+
+/**
+ * @brief Identify the region of sys_notify flags available for
+ * containing services.
+ *
+ * Bits of the flags field of the sys_notify structure at and above
+ * this position may be used by extensions to the sys_notify
+ * structure.
+ *
+ * These bits are intended for use by containing service
+ * implementations to record client-specific information.  The bits
+ * are cleared by sys_notify_validate().  Use of these does not
+ * imply that the flags field becomes public API.
+ */
+#define SYS_NOTIFY_EXTENSION_POS 2
+
+/*
+ * Mask isolating the bits of sys_notify::flags that are available
+ * for extension.
+ */
+#define SYS_NOTIFY_EXTENSION_MASK (~BIT_MASK(SYS_NOTIFY_EXTENSION_POS))
+
+/**
+ * @defgroup sys_notify_apis Asynchronous Notification APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Generic signature used to notify of result completion by
+ * callback.
+ *
+ * Functions with this role may be invoked from any context including
+ * pre-kernel, ISR, or cooperative or pre-emptible threads.
+ * Compatible functions must be isr-ok and not sleep.
+ *
+ * Parameters that should generally be passed to such functions include:
+ *
+ * * a pointer to a specific client request structure, i.e. the one
+ *   that contains the sys_notify structure.
+ * * the result of the operation, either as passed to
+ *   sys_notify_finalize() or extracted afterwards using
+ *   sys_notify_fetch_result().  Expected values are
+ *   service-specific, but the value shall be non-negative if the
+ *   operation succeeded, and negative if the operation failed.
+ */
+typedef void (*sys_notify_generic_callback)();
+
+/**
+ * @brief State associated with notification for an asynchronous
+ * operation.
+ *
+ * Objects of this type are allocated by a client, which must use an
+ * initialization function (e.g. sys_notify_init_signal()) to
+ * configure them.  Generally the structure is a member of a
+ * service-specific client structure, such as onoff_client.
+ *
+ * Control of the containing object transfers to the service provider
+ * when a pointer to the object is passed to a service function that
+ * is documented to take control of the object, such as
+ * onoff_service_request().  While the service provider controls the
+ * object the client must not change any object fields.  Control
+ * reverts to the client:
+ * * if the call to the service API returns an error;
+ * * when operation completion is posted.  This may occur before the
+ *   call to the service API returns.
+ *
+ * Operation completion is technically posted when the flags field is
+ * updated so that sys_notify_fetch_result() returns success.  This
+ * will happen before the signal is posted or callback is invoked.
+ * Note that although the manager will no longer reference the
+ * sys_notify object past this point, the containing object may have
+ * state that will be referenced within the callback.  Where callbacks
+ * are used control of the containing object does not revert to the
+ * client until the callback has been invoked.  (Re-use within the
+ * callback is explicitly permitted.)
+ *
+ * After control has reverted to the client the notify object must be
+ * reinitialized for the next operation.
+ *
+ * The content of this structure is not public API to clients: all
+ * configuration and inspection should be done with functions like
+ * sys_notify_init_callback() and sys_notify_fetch_result().
+ * However, services that use this structure may access certain
+ * fields directly.
+ */
+struct sys_notify {
+	union method {
+		/* Pointer to signal used to notify client.
+		 *
+		 * The signal value corresponds to the res parameter
+		 * of sys_notify_callback.
+		 */
+		struct k_poll_signal *signal;
+
+		/* Generic callback function for callback notification. */
+		sys_notify_generic_callback callback;
+	} method;
+
+	/*
+	 * Flags recording information about the operation.
+	 *
+	 * Bits below SYS_NOTIFY_EXTENSION_POS are initialized by
+	 * async notify API init functions like
+	 * sys_notify_init_callback(), and must not by modified by
+	 * extensions or client code.
+	 *
+	 * Bits at and above SYS_NOTIFY_EXTENSION_POS are available
+	 * for use by service extensions while the containing object
+	 * is managed by the service.  They are not for client use,
+	 * are zeroed by the async notify API init functions, and will
+	 * be zeroed by sys_notify_finalize().
+	 */
+	uint32_t volatile flags;
+
+	/*
+	 * The result of the operation.
+	 *
+	 * This is the value that was (or would be) passed to the
+	 * async infrastructure.  This field is the sole record of
+	 * success or failure for spin-wait synchronous operations.
+	 */
+	int volatile result;
+};
+
+/** @internal */
+static inline uint32_t sys_notify_get_method(const struct sys_notify *notify)
+{
+	uint32_t method = notify->flags >> SYS_NOTIFY_METHOD_POS;
+
+	return method & SYS_NOTIFY_METHOD_MASK;
+}
+
+/**
+ * @brief Validate and initialize the notify structure.
+ *
+ * This should be invoked at the start of any service-specific
+ * configuration validation.  It ensures that the basic asynchronous
+ * notification configuration is consistent, and clears the result.
+ *
+ * Note that this function does not validate extension bits (zeroed by
+ * async notify API init functions like sys_notify_init_callback()).
+ * It may fail to recognize that an uninitialized structure has been
+ * passed because only method bits of flags are tested against method
+ * settings.  To reduce the chance of accepting an uninititalized
+ * operation service validation of structures that contain an
+ * sys_notify instance should confirm that the extension bits are
+ * set or cleared as expected.
+ *
+ * @retval 0 on successful validation and reinitialization
+ * @retval -EINVAL if the configuration is not valid.
+ */
+int sys_notify_validate(struct sys_notify *notify);
+
+/**
+ * @brief Record and signal the operation completion.
+ *
+ * @param notify pointer to the notification state structure.
+ *
+ * @param res the result of the operation.  Expected values are
+ * service-specific, but the value shall be non-negative if the
+ * operation succeeded, and negative if the operation failed.
+ *
+ * @return If the notification is to be done by callback this returns
+ * the generic version of the function to be invoked.  The caller must
+ * immediately invoke that function with whatever arguments are
+ * expected by the callback.  If notification is by spin-wait or
+ * signal, the notification has been completed by the point this
+ * function returns, and a null pointer is returned.
+ */
+sys_notify_generic_callback sys_notify_finalize(struct sys_notify *notify,
+						    int res);
+
+/**
+ * @brief Check for and read the result of an asynchronous operation.
+ *
+ * @param notify pointer to the object used to specify asynchronous
+ * function behavior and store completion information.
+ *
+ * @param result pointer to storage for the result of the operation.
+ * The result is stored only if the operation has completed.
+ *
+ * @retval 0 if the operation has completed.
+ * @retval -EAGAIN if the operation has not completed.
+ */
+static inline int sys_notify_fetch_result(const struct sys_notify *notify,
+					    int *result)
+{
+	__ASSERT_NO_MSG(notify != NULL);
+	__ASSERT_NO_MSG(result != NULL);
+	int rv = -EAGAIN;
+
+	if (sys_notify_get_method(notify) == SYS_NOTIFY_METHOD_COMPLETED) {
+		rv = 0;
+		*result = notify->result;
+	}
+
+	return rv;
+}
+
+/**
+ * @brief Initialize a notify object for spin-wait notification.
+ *
+ * Clients that use this initialization receive no asynchronous
+ * notification, and instead must periodically check for completion
+ * using sys_notify_fetch_result().
+ *
+ * On completion of the operation the client object must be
+ * reinitialized before it can be re-used.
+ *
+ * @param notify pointer to the notification configuration object.
+ */
+static inline void sys_notify_init_spinwait(struct sys_notify *notify)
+{
+	__ASSERT_NO_MSG(notify != NULL);
+
+	*notify = (struct sys_notify){
+		.flags = SYS_NOTIFY_METHOD_SPINWAIT,
+	};
+}
+
+/**
+ * @brief Initialize a notify object for (k_poll) signal notification.
+ *
+ * Clients that use this initialization will be notified of the
+ * completion of operations through the provided signal.
+ *
+ * On completion of the operation the client object must be
+ * reinitialized before it can be re-used.
+ *
+ * @note
+ *   This capability is available only when @option{CONFIG_POLL} is
+ *   selected.
+ *
+ * @param notify pointer to the notification configuration object.
+ *
+ * @param sigp pointer to the signal to use for notification.  The
+ * value must not be null.  The signal must be reset before the client
+ * object is passed to the on-off service API.
+ */
+static inline void sys_notify_init_signal(struct sys_notify *notify,
+					    struct k_poll_signal *sigp)
+{
+	__ASSERT_NO_MSG(notify != NULL);
+	__ASSERT_NO_MSG(sigp != NULL);
+
+	*notify = (struct sys_notify){
+		.method = {
+			.signal = sigp,
+		},
+		.flags = SYS_NOTIFY_METHOD_SIGNAL,
+	};
+}
+
+/**
+ * @brief Initialize a notify object for callback notification.
+ *
+ * Clients that use this initialization will be notified of the
+ * completion of operations through the provided callback.  Note that
+ * callbacks may be invoked from various contexts depending on the
+ * specific service; see @ref sys_notify_generic_callback.
+ *
+ * On completion of the operation the client object must be
+ * reinitialized before it can be re-used.
+ *
+ * @param notify pointer to the notification configuration object.
+ *
+ * @param handler a function pointer to use for notification.
+ */
+static inline void sys_notify_init_callback(struct sys_notify *notify,
+					      sys_notify_generic_callback handler)
+{
+	__ASSERT_NO_MSG(notify != NULL);
+	__ASSERT_NO_MSG(handler != NULL);
+
+	*notify = (struct sys_notify){
+		.method = {
+			.callback = handler,
+		},
+		.flags = SYS_NOTIFY_METHOD_CALLBACK,
+	};
+}
+
+/**
+ * @brief Detect whether a particular notification uses a callback.
+ *
+ * The generic handler does not capture the signature expected by the
+ * callback, and the translation to a service-specific callback must
+ * be provided by the service.  This check allows abstracted services
+ * to reject callback notification requests when the service doesn't
+ * provide a translation function.
+ *
+ * @return true if and only if a callback is to be used for notification.
+ */
+static inline bool sys_notify_uses_callback(const struct sys_notify *notify)
+{
+	__ASSERT_NO_MSG(notify != NULL);
+
+	return sys_notify_get_method(notify) == SYS_NOTIFY_METHOD_CALLBACK;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_NOTIFY_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/onoff.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/onoff.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/onoff.h	(working copy)
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2019 Peter Bigot Consulting, LLC
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_ONOFF_H_
+#define ZEPHYR_INCLUDE_SYS_ONOFF_H_
+
+#include <kernel.h>
+#include <zephyr/types.h>
+#include <sys/notify.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup resource_mgmt_onoff_apis On-Off Service APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Flag indicating an error state.
+ *
+ * Error states are cleared using onoff_reset().
+ */
+#define ONOFF_FLAG_ERROR BIT(0)
+
+/** @internal */
+#define ONOFF_FLAG_ONOFF BIT(1)
+/** @internal */
+#define ONOFF_FLAG_TRANSITION BIT(2)
+
+/**
+ * @brief Mask used to isolate bits defining the service state.
+ *
+ * Mask a value with this then test for ONOFF_FLAG_ERROR to determine
+ * whether the machine has an unfixed error, or compare against
+ * ONOFF_STATE_ON, ONOFF_STATE_OFF, ONOFF_STATE_TO_ON,
+ * ONOFF_STATE_TO_OFF, or ONOFF_STATE_RESETTING.
+ */
+#define ONOFF_STATE_MASK (ONOFF_FLAG_ERROR   \
+			  | ONOFF_FLAG_ONOFF \
+			  | ONOFF_FLAG_TRANSITION)
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when service is off.
+ */
+#define ONOFF_STATE_OFF 0U
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when service is on.
+ */
+#define ONOFF_STATE_ON ONOFF_FLAG_ONOFF
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when the service is in an
+ * error state (and not in the process of resetting its state).
+ */
+#define ONOFF_STATE_ERROR ONOFF_FLAG_ERROR
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when service is
+ * transitioning to on.
+ */
+#define ONOFF_STATE_TO_ON (ONOFF_FLAG_TRANSITION | ONOFF_STATE_ON)
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when service is
+ * transitioning to off.
+ */
+#define ONOFF_STATE_TO_OFF (ONOFF_FLAG_TRANSITION | ONOFF_STATE_OFF)
+
+/**
+ * @brief Value exposed by ONOFF_STATE_MASK when service is in the
+ * process of resetting.
+ */
+#define ONOFF_STATE_RESETTING (ONOFF_FLAG_TRANSITION | ONOFF_STATE_ERROR)
+
+/* Forward declarations */
+struct onoff_manager;
+struct onoff_monitor;
+
+/**
+ * @brief Signature used to notify an on-off manager that a transition
+ * has completed.
+ *
+ * Functions of this type are passed to service-specific transition
+ * functions to be used to report the completion of the operation.
+ * The functions may be invoked from any context.
+ *
+ * @param mgr the manager for which transition was requested.
+ *
+ * @param res the result of the transition.  This shall be
+ * non-negative on success, or a negative error code.  If an error is
+ * indicated the service shall enter an error state.
+ */
+typedef void (*onoff_notify_fn)(struct onoff_manager *mgr,
+				int res);
+
+/**
+ * @brief Signature used by service implementations to effect a
+ * transition.
+ *
+ * Service definitions use two required function pointers of this type
+ * to be notified that a transition is required, and a third optional
+ * one to reset the service when it is in an error state.
+ *
+ * The start function will be called only from the off state.
+ *
+ * The stop function will be called only from the on state.
+ *
+ * The reset function (where supported) will be called only when
+ * onoff_has_error() returns true.
+ *
+ * @note All transitions functions must be isr-ok.
+ *
+ * @param mgr the manager for which transition was requested.
+ *
+ * @param notify the function to be invoked when the transition has
+ * completed.  If the transition is synchronous, notify shall be
+ * invoked by the implementation before the transition function
+ * returns.  Otherwise the implementation shall capture this parameter
+ * and invoke it when the transition completes.
+ */
+typedef void (*onoff_transition_fn)(struct onoff_manager *mgr,
+				    onoff_notify_fn notify);
+
+/** @brief On-off service transition functions. */
+struct onoff_transitions {
+	/* Function to invoke to transition the service to on. */
+	onoff_transition_fn start;
+
+	/* Function to invoke to transition the service to off. */
+	onoff_transition_fn stop;
+
+	/* Function to force the service state to reset, where
+	 * supported.
+	 */
+	onoff_transition_fn reset;
+};
+
+/**
+ * @brief State associated with an on-off manager.
+ *
+ * No fields in this structure are intended for use by service
+ * providers or clients.  The state is to be initialized once, using
+ * onoff_manager_init(), when the service provider is initialized.  In
+ * case of error it may be reset through the onoff_reset() API.
+ */
+struct onoff_manager {
+	/* List of clients waiting for request or reset completion
+	 * notifications.
+	 */
+	sys_slist_t clients;
+
+	/* List of monitors to be notified of state changes including
+	 * errors and transition completion.
+	 */
+	sys_slist_t monitors;
+
+	/* Transition functions. */
+	const struct onoff_transitions *transitions;
+
+	/* Mutex protection for other fields. */
+	struct k_spinlock lock;
+
+	/* The result of the last transition. */
+	int last_res;
+
+	/* Flags identifying the service state. */
+	uint16_t flags;
+
+	/* Number of active clients for the service. */
+	uint16_t refs;
+};
+
+/** @brief Initializer for a onoff_transitions object.
+ *
+ * @param _start a function used to transition from off to on state.
+ *
+ * @param _stop a function used to transition from on to off state.
+ *
+ * @param _reset a function used to clear errors and force the service
+ * to an off state. Can be null.
+ */
+#define ONOFF_TRANSITIONS_INITIALIZER(_start, _stop, _reset) { \
+		.start = _start,			       \
+		.stop = _stop,				       \
+		.reset = _reset,			       \
+}
+
+/** @internal */
+#define ONOFF_MANAGER_INITIALIZER(_transitions) { \
+		.transitions = _transitions,	  \
+}
+
+/**
+ * @brief Initialize an on-off service to off state.
+ *
+ * This function must be invoked exactly once per service instance, by
+ * the infrastructure that provides the service, and before any other
+ * on-off service API is invoked on the service.
+ *
+ * This function should never be invoked by clients of an on-off
+ * service.
+ *
+ * @param mgr the manager definition object to be initialized.
+ *
+ * @param transitions pointer to a structure providing transition
+ * functions.  The referenced object must persist as long as the
+ * manager can be referenced.
+ *
+ * @retval 0 on success
+ * @retval -EINVAL if start, stop, or flags are invalid
+ */
+int onoff_manager_init(struct onoff_manager *mgr,
+		       const struct onoff_transitions *transitions);
+
+/* Forward declaration */
+struct onoff_client;
+
+/**
+ * @brief Signature used to notify an on-off service client of the
+ * completion of an operation.
+ *
+ * These functions may be invoked from any context including
+ * pre-kernel, ISR, or cooperative or pre-emptible threads.
+ * Compatible functions must be isr-ok and not sleep.
+ *
+ * @param mgr the manager for which the operation was initiated.  This may be
+ * null if the on-off service uses synchronous transitions.
+ *
+ * @param cli the client structure passed to the function that
+ * initiated the operation.
+ *
+ * @param state the state of the machine at the time of completion,
+ * restricted by ONOFF_STATE_MASK.  ONOFF_FLAG_ERROR must be checked
+ * independently of whether res is negative as a machine error may
+ * indicate that all future operations except onoff_reset() will fail.
+ *
+ * @param res the result of the operation.  Expected values are
+ * service-specific, but the value shall be non-negative if the
+ * operation succeeded, and negative if the operation failed.  If res
+ * is negative ONOFF_FLAG_ERROR will be set in state, but if res is
+ * non-negative ONOFF_FLAG_ERROR may still be set in state.
+ */
+typedef void (*onoff_client_callback)(struct onoff_manager *mgr,
+				      struct onoff_client *cli,
+				      uint32_t state,
+				      int res);
+
+/**
+ * @brief State associated with a client of an on-off service.
+ *
+ * Objects of this type are allocated by a client, which is
+ * responsible for zero-initializing the node field and invoking the
+ * approprite sys_notify init function to configure notification.
+ *
+ * Control of the object content transfers to the service provider
+ * when a pointer to the object is passed to any on-off manager
+ * function.  While the service provider controls the object the
+ * client must not change any object fields.  Control reverts to the
+ * client concurrent with release of the owned sys_notify structure,
+ * or when indicated by an onoff_cancel() return value.
+ *
+ * After control has reverted to the client the notify field must be
+ * reinitialized for the next operation.
+ */
+struct onoff_client {
+	/** @internal
+	 *
+	 * Links the client into the set of waiting service users.
+	 * Applications must ensure this field is zero-initialized
+	 * before use.
+	 */
+	sys_snode_t node;
+
+	/** @brief Notification configuration. */
+	struct sys_notify notify;
+};
+
+/**
+ * @brief Identify region of sys_notify flags available for
+ * containing services.
+ *
+ * Bits of the flags field of the sys_notify structure contained
+ * within the queued_operation structure at and above this position
+ * may be used by extensions to the onoff_client structure.
+ *
+ * These bits are intended for use by containing service
+ * implementations to record client-specific information and are
+ * subject to other conditions of use specified on the sys_notify API.
+ */
+#define ONOFF_CLIENT_EXTENSION_POS SYS_NOTIFY_EXTENSION_POS
+
+/**
+ * @brief Test whether an on-off service has recorded an error.
+ *
+ * This function can be used to determine whether the service has
+ * recorded an error.  Errors may be cleared by invoking
+ * onoff_reset().
+ *
+ * This is an unlocked convenience function suitable for use only when
+ * it is known that no other process might invoke an operation that
+ * transitions the service between an error and non-error state.
+ *
+ * @return true if and only if the service has an uncleared error.
+ */
+static inline bool onoff_has_error(const struct onoff_manager *mgr)
+{
+	return (mgr->flags & ONOFF_FLAG_ERROR) != 0;
+}
+
+/**
+ * @brief Request a reservation to use an on-off service.
+ *
+ * The return value indicates the success or failure of an attempt to
+ * initiate an operation to request the resource be made available.
+ * If initiation of the operation succeeds the result of the request
+ * operation is provided through the configured client notification
+ * method, possibly before this call returns.
+ *
+ * Note that the call to this function may succeed in a case where the
+ * actual request fails.  Always check the operation completion
+ * result.
+ *
+ * @param mgr the manager that will be used.
+ *
+ * @param cli a non-null pointer to client state providing
+ * instructions on synchronous expectations and how to notify the
+ * client when the request completes.  Behavior is undefined if client
+ * passes a pointer object associated with an incomplete service
+ * operation.
+ *
+ * @retval non-negative the observed state of the machine at the time
+ * the request was processed, if successful.
+ * @retval -EIO if service has recorded an an error.
+ * @retval -EINVAL if the parameters are invalid.
+ * @retval -EAGAIN if the reference count would overflow.
+ */
+int onoff_request(struct onoff_manager *mgr,
+		  struct onoff_client *cli);
+
+/**
+ * @brief Release a reserved use of an on-off service.
+ *
+ * This synchronously releases the caller's previous request.  If the
+ * last request is released the manager will initiate a transition to
+ * off, which can be observed by registering an onoff_monitor.
+ *
+ * @note Behavior is undefined if this is not paired with a preceding
+ * onoff_request() call that completed successfully.
+ *
+ * @param mgr the manager for which a request was successful.
+ *
+ * @retval non-negative the observed state (ONOFF_STATE_ON) of the
+ * machine at the time of the release, if the release succeeds.
+ * @retval -EIO if service has recorded an an error.
+ * @retval -ENOTSUP if the machine is not in a state that permits
+ * release.
+ */
+int onoff_release(struct onoff_manager *mgr);
+
+/**
+ * @brief Attempt to cancel an in-progress client operation.
+ *
+ * It may be that a client has initiated an operation but needs to
+ * shut down before the operation has completed.  For example, when a
+ * request was made and the need is no longer present.
+ *
+ * Cancelling is supported only for onoff_request() and onoff_reset()
+ * operations, and is a synchronous operation.  Be aware that any
+ * transition that was initiated on behalf of the client will continue
+ * to progress to completion: it is only notification of transition
+ * completion that may be eliminated.  If there are no active requests
+ * when a transition to on completes the manager will initiate a
+ * transition to off.
+ *
+ * Client notification does not occur for cancelled operations.
+ *
+ * @param mgr the manager for which an operation is to be cancelled.
+ *
+ * @param cli a pointer to the same client state that was provided
+ * when the operation to be cancelled was issued.
+ *
+ * @retval non-negative the observed state of the machine at the time
+ * of the cancellation, if the cancellation succeeds.  On successful
+ * cancellation ownership of @c *cli reverts to the client.
+ * @retval -EINVAL if the parameters are invalid.
+ * @retval -EALREADY if cli was not a record of an uncompleted
+ * notification at the time the cancellation was processed.  This
+ * likely indicates that the operation and client notification had
+ * already completed.
+ */
+int onoff_cancel(struct onoff_manager *mgr,
+		 struct onoff_client *cli);
+
+/**
+ * @brief Helper function to safely cancel a request.
+ *
+ * Some applications may want to issue requests on an asynchronous
+ * event (such as connection to a USB bus) and to release on a paired
+ * event (such as loss of connection to a USB bus).  Applications
+ * cannot precisely determine that an in-progress request is still
+ * pending without using onoff_monitor and carefully avoiding race
+ * conditions.
+ *
+ * This function is a helper that attempts to cancel the operation and
+ * issues a release if cancellation fails because the request was
+ * completed.  This synchronously ensures that ownership of the client
+ * data reverts to the client so is available for a future request.
+ *
+ * @param mgr the manager for which an operation is to be cancelled.
+ *
+ * @param cli a pointer to the same client state that was provided
+ * when onoff_request() was invoked.  Behavior is undefined if this is
+ * a pointer to client data associated with an onoff_reset() request.
+ *
+ * @retval ONOFF_STATE_TO_ON if the cancellation occurred before the
+ * transition completed.
+ *
+ * @retval ONOFF_STATE_ON if the cancellation occurred after the
+ * transition completed.
+ *
+ * @retval -EINVAL if the parameters are invalid.
+ *
+ * @retval negative other errors produced by onoff_release().
+ */
+static inline int onoff_cancel_or_release(struct onoff_manager *mgr,
+					  struct onoff_client *cli)
+{
+	int rv = onoff_cancel(mgr, cli);
+
+	if (rv == -EALREADY) {
+		rv = onoff_release(mgr);
+	}
+	return rv;
+}
+
+/**
+ * @brief Clear errors on an on-off service and reset it to its off
+ * state.
+ *
+ * A service can only be reset when it is in an error state as
+ * indicated by onoff_has_error().
+ *
+ * The return value indicates the success or failure of an attempt to
+ * initiate an operation to reset the resource.  If initiation of the
+ * operation succeeds the result of the reset operation itself is
+ * provided through the configured client notification method,
+ * possibly before this call returns.  Multiple clients may request a
+ * reset; all are notified when it is complete.
+ *
+ * Note that the call to this function may succeed in a case where the
+ * actual reset fails.  Always check the operation completion result.
+ *
+ * @note Due to the conditions on state transition all incomplete
+ * asynchronous operations will have been informed of the error when
+ * it occurred.  There need be no concern about dangling requests left
+ * after a reset completes.
+ *
+ * @param mgr the manager to be reset.
+ *
+ * @param cli pointer to client state, including instructions on how
+ * to notify the client when reset completes.  Behavior is undefined
+ * if cli references an object associated with an incomplete service
+ * operation.
+ *
+ * @retval non-negative the observed state of the machine at the time
+ * of the reset, if the reset succeeds.
+ * @retval -ENOTSUP if reset is not supported by the service.
+ * @retval -EINVAL if the parameters are invalid.
+ * @retval -EALREADY if the service does not have a recorded error.
+ */
+int onoff_reset(struct onoff_manager *mgr,
+		struct onoff_client *cli);
+
+/**
+ * @brief Signature used to notify a monitor of an onoff service of
+ * errors or completion of a state transition.
+ *
+ * This is similar to onoff_client_callback but provides information
+ * about all transitions, not just ones associated with a specific
+ * client.  Monitor callbacks are invoked before any completion
+ * notifications associated with the state change are made.
+ *
+ * These functions may be invoked from any context including
+ * pre-kernel, ISR, or cooperative or pre-emptible threads.
+ * Compatible functions must be isr-ok and not sleep.
+ *
+ * The callback is permitted to unregister itself from the manager,
+ * but must not register or unregister any other monitors.
+ *
+ * @param mgr the manager for which a transition has completed.
+ *
+ * @param mon the monitor instance through which this notification
+ * arrived.
+ *
+ * @param state the state of the machine at the time of completion,
+ * restricted by ONOFF_STATE_MASK.  All valid states may be observed.
+ *
+ * @param res the result of the operation.  Expected values are
+ * service- and state-specific, but the value shall be non-negative if
+ * the operation succeeded, and negative if the operation failed.
+ */
+typedef void (*onoff_monitor_callback)(struct onoff_manager *mgr,
+				       struct onoff_monitor *mon,
+				       uint32_t state,
+				       int res);
+
+/**
+ * @brief Registration state for notifications of onoff service
+ * transitions.
+ *
+ * Any given onoff_monitor structure can be associated with at most
+ * one onoff_manager instance.
+ */
+struct onoff_monitor {
+	/* Links the client into the set of waiting service users.
+	 *
+	 * This must be zero-initialized.
+	 */
+	sys_snode_t node;
+
+	/** @brief Callback to be invoked on state change.
+	 *
+	 * This must not be null.
+	 */
+	onoff_monitor_callback callback;
+};
+
+/**
+ * @brief Add a monitor of state changes for a manager.
+ *
+ * @param mgr the manager for which a state changes are to be monitored.
+ *
+ * @param mon a linkable node providing a non-null callback to be
+ * invoked on state changes.
+ *
+ * @return non-negative on successful addition, or a negative error
+ * code.
+ */
+int onoff_monitor_register(struct onoff_manager *mgr,
+			   struct onoff_monitor *mon);
+
+/**
+ * @brief Remove a monitor of state changes from a manager.
+ *
+ * @param mgr the manager for which a state changes are to be monitored.
+ *
+ * @param mon a linkable node providing the callback to be invoked on
+ * state changes.
+ *
+ * @return non-negative on successful removal, or a negative error
+ * code.
+ */
+int onoff_monitor_unregister(struct onoff_manager *mgr,
+			     struct onoff_monitor *mon);
+
+/**
+ * @brief State used when a driver uses the on-off service API for synchronous
+ * operations.
+ *
+ * This is useful when a subsystem API uses the on-off API to support
+ * asynchronous operations but the transitions required by a
+ * particular driver are isr-ok and not sleep.  It serves as a
+ * substitute for #onoff_manager, with locking and persisted state
+ * updates supported by onoff_sync_lock() and onoff_sync_finalize().
+ */
+struct onoff_sync_service {
+	/* Mutex protection for other fields. */
+	struct k_spinlock lock;
+
+	/* Negative is error, non-negative is reference count. */
+	int32_t count;
+};
+
+/**
+ * @brief Lock a synchronous onoff service and provide its state.
+ *
+ * @note If an error state is returned it is the caller's responsibility to
+ * decide whether to preserve it (finalize with the same error state) or clear
+ * the error (finalize with a non-error result).
+ *
+ * @param srv pointer to the synchronous service state.
+ *
+ * @param keyp pointer to where the lock key should be stored
+ *
+ * @return negative if the service is in an error state, otherwise the
+ * number of active requests at the time the lock was taken.  The lock
+ * is held on return regardless of whether a negative state is
+ * returned.
+ */
+int onoff_sync_lock(struct onoff_sync_service *srv,
+		    k_spinlock_key_t *keyp);
+
+/**
+ * @brief Process the completion of a transition in a synchronous
+ * service and release lock.
+ *
+ * This function updates the service state on the @p res and @p on parameters
+ * then releases the lock.  If @p cli is not null it finalizes the client
+ * notification using @p res.
+ *
+ * If the service was in an error state when locked, and @p res is non-negative
+ * when finalized, the count is reset to zero before completing finalization.
+ *
+ * @param srv pointer to the synchronous service state
+ *
+ * @param key the key returned by the preceding invocation of onoff_sync_lock().
+ *
+ * @param cli pointer to the onoff client through which completion
+ * information is returned.  If a null pointer is passed only the
+ * state of the service is updated.  For compatibility with the
+ * behavior of callbacks used with the manager API @p cli must be null
+ * when @p on is false (the manager does not support callbacks when
+ * turning off devices).
+ *
+ * @param res the result of the transition.  A negative value places the service
+ * into an error state.  A non-negative value increments or decrements the
+ * reference count as specified by @p on.
+ *
+ * @param on Only when @p res is non-negative, the service reference count will
+ * be incremented if@p on is @c true, and decremented if @p on is @c false.
+ *
+ * @return negative if the service is left or put into an error state, otherwise
+ * the number of active requests at the time the lock was released.
+ */
+int onoff_sync_finalize(struct onoff_sync_service *srv,
+			 k_spinlock_key_t key,
+			 struct onoff_client *cli,
+			 int res,
+			 bool on);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_ONOFF_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/printk.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/printk.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/printk.h	(working copy)
@@ -0,0 +1,76 @@
+/* printk.h - low-level debug output */
+
+/*
+ * Copyright (c) 2010-2012, 2014 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_INCLUDE_SYS_PRINTK_H_
+#define ZEPHYR_INCLUDE_SYS_PRINTK_H_
+
+#include <toolchain.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *
+ * @brief Print kernel debugging message.
+ *
+ * This routine prints a kernel debugging message to the system console.
+ * Output is send immediately, without any mutual exclusion or buffering.
+ *
+ * A basic set of conversion specifier characters are supported:
+ *   - signed decimal: \%d, \%i
+ *   - unsigned decimal: \%u
+ *   - unsigned hexadecimal: \%x (\%X is treated as \%x)
+ *   - pointer: \%p
+ *   - string: \%s
+ *   - character: \%c
+ *   - percent: \%\%
+ *
+ * Field width (with or without leading zeroes) is supported.
+ * Length attributes h, hh, l, ll and z are supported. However, integral
+ * values with %lld and %lli are only printed if they fit in a long
+ * otherwise 'ERR' is printed. Full 64-bit values may be printed with %llx.
+ * Flags and precision attributes are not supported.
+ *
+ * @param fmt Format string.
+ * @param ... Optional list of format arguments.
+ *
+ * @return N/A
+ */
+#ifdef CONFIG_PRINTK
+extern __printf_like(1, 2) void printk(const char *fmt, ...);
+extern __printf_like(1, 0) void vprintk(const char *fmt, va_list ap);
+#else
+static inline __printf_like(1, 2) void printk(const char *fmt, ...)
+{
+	ARG_UNUSED(fmt);
+}
+
+static inline __printf_like(1, 0) void vprintk(const char *fmt, va_list ap)
+{
+	ARG_UNUSED(fmt);
+	ARG_UNUSED(ap);
+}
+#endif
+
+extern __printf_like(3, 4) int snprintk(char *str, size_t size,
+					const char *fmt, ...);
+extern __printf_like(3, 0) int vsnprintk(char *str, size_t size,
+					  const char *fmt, va_list ap);
+
+extern __printf_like(3, 0) void z_vprintk(int (*out)(int f, void *c), void *ctx,
+					 const char *fmt, va_list ap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/sys/rb.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/rb.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/rb.h	(working copy)
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Our SDK/toolchains integration seems to be inconsistent about
+ * whether they expose alloca.h or not.  On gcc it's a moot point as
+ * it's always builtin.
+ */
+#ifdef __GNUC__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#include <alloca.h>
+#endif
+
+/**
+ * @file
+ * @brief Red/Black balanced tree data structure
+ *
+ * This implements an intrusive balanced tree that guarantees
+ * O(log2(N)) runtime for all operations and amortized O(1) behavior
+ * for creation and destruction of whole trees.  The algorithms and
+ * naming are conventional per existing academic and didactic
+ * implementations, c.f.:
+ *
+ * https://en.wikipedia.org/wiki/Red%E2%80%93black_tree
+ *
+ * The implementation is size-optimized to prioritize runtime memory
+ * usage.  The data structure is intrusive, which is to say the struct
+ * rbnode handle is intended to be placed in a separate struct the
+ * same way other such structures (e.g. Zephyr's dlist list) and
+ * requires no data pointer to be stored in the node.  The color bit
+ * is unioned with a pointer (fairly common for such libraries).  Most
+ * notably, there is no "parent" pointer stored in the node, the upper
+ * structure of the tree being generated dynamically via a stack as
+ * the tree is recursed.  So the overall memory overhead of a node is
+ * just two pointers, identical with a doubly-linked list.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_RB_H_
+#define ZEPHYR_INCLUDE_SYS_RB_H_
+
+#include <stdbool.h>
+
+struct rbnode {
+	struct rbnode *children[2];
+};
+
+/* Theoretical maximum depth of tree based on pointer size. If memory
+ * is filled with 2-pointer nodes, and the tree can be twice as a
+ * packed binary tree, plus root...  Works out to 59 entries for 32
+ * bit pointers and 121 at 64 bits.
+ */
+#define Z_TBITS(t) ((sizeof(t)) < 8 ? 2 : 3)
+#define Z_PBITS(t) (8 * sizeof(t))
+#define Z_MAX_RBTREE_DEPTH (2 * (Z_PBITS(int *) - Z_TBITS(int *) - 1) + 1)
+
+/**
+ * @typedef rb_lessthan_t
+ * @brief Red/black tree comparison predicate
+ *
+ * Compares the two nodes and returns true if node A is strictly less
+ * than B according to the tree's sorting criteria, false otherwise.
+ *
+ * Note that during insert, the new node being inserted will always be
+ * "A", where "B" is the existing node within the tree against which
+ * it is being compared.  This trait can be used (with care!) to
+ * implement "most/least recently added" semantics between nodes which
+ * would otherwise compare as equal.
+ */
+typedef bool (*rb_lessthan_t)(struct rbnode *a, struct rbnode *b);
+
+struct rbtree {
+	struct rbnode *root;
+	rb_lessthan_t lessthan_fn;
+	int max_depth;
+#ifdef CONFIG_MISRA_SANE
+	struct rbnode *iter_stack[Z_MAX_RBTREE_DEPTH];
+	unsigned char iter_left[Z_MAX_RBTREE_DEPTH];
+#endif
+};
+
+typedef void (*rb_visit_t)(struct rbnode *node, void *cookie);
+
+struct rbnode *z_rb_child(struct rbnode *node, int side);
+int z_rb_is_black(struct rbnode *node);
+#ifndef CONFIG_MISRA_SANE
+void z_rb_walk(struct rbnode *node, rb_visit_t visit_fn, void *cookie);
+#endif
+struct rbnode *z_rb_get_minmax(struct rbtree *tree, int side);
+
+/**
+ * @brief Insert node into tree
+ */
+void rb_insert(struct rbtree *tree, struct rbnode *node);
+
+/**
+ * @brief Remove node from tree
+ */
+void rb_remove(struct rbtree *tree, struct rbnode *node);
+
+/**
+ * @brief Returns the lowest-sorted member of the tree
+ */
+static inline struct rbnode *rb_get_min(struct rbtree *tree)
+{
+	return z_rb_get_minmax(tree, 0);
+}
+
+/**
+ * @brief Returns the highest-sorted member of the tree
+ */
+static inline struct rbnode *rb_get_max(struct rbtree *tree)
+{
+	return z_rb_get_minmax(tree, 1);
+}
+
+/**
+ * @brief Returns true if the given node is part of the tree
+ *
+ * Note that this does not internally dereference the node pointer
+ * (though the tree's lessthan callback might!), it just tests it for
+ * equality with items in the tree.  So it's feasible to use this to
+ * implement a "set" construct by simply testing the pointer value
+ * itself.
+ */
+bool rb_contains(struct rbtree *tree, struct rbnode *node);
+
+#ifndef CONFIG_MISRA_SANE
+/**
+ * @brief Walk/enumerate a rbtree
+ *
+ * Very simple recursive enumeration.  Low code size, but requiring a
+ * separate function can be clumsy for the user and there is no way to
+ * break out of the loop early.  See RB_FOR_EACH for an iterative
+ * implementation.
+ */
+static inline void rb_walk(struct rbtree *tree, rb_visit_t visit_fn,
+			   void *cookie)
+{
+	z_rb_walk(tree->root, visit_fn, cookie);
+}
+#endif
+
+struct _rb_foreach {
+	struct rbnode **stack;
+	char *is_left;
+	int top;
+};
+
+#ifdef CONFIG_MISRA_SANE
+#define _RB_FOREACH_INIT(tree, node) {					\
+	.stack   = &(tree)->iter_stack[0],				\
+	.is_left = &(tree)->iter_left[0],				\
+	.top     = -1							\
+}
+#else
+#define _RB_FOREACH_INIT(tree, node) {					\
+	.stack   = (struct rbnode **)					\
+			alloca((tree)->max_depth * sizeof(struct rbnode *)), \
+	.is_left = (char *)alloca((tree)->max_depth * sizeof(char)),		\
+	.top     = -1							\
+}
+#endif
+
+struct rbnode *z_rb_foreach_next(struct rbtree *tree, struct _rb_foreach *f);
+
+/**
+ * @brief Walk a tree in-order without recursing
+ *
+ * While @ref rb_walk() is very simple, recursing on the C stack can
+ * be clumsy for some purposes and on some architectures wastes
+ * significant memory in stack frames.  This macro implements a
+ * non-recursive "foreach" loop that can iterate directly on the tree,
+ * at a moderate cost in code size.
+ *
+ * Note that the resulting loop is not safe against modifications to
+ * the tree.  Changes to the tree structure during the loop will
+ * produce incorrect results, as nodes may be skipped or duplicated.
+ * Unlike linked lists, no _SAFE variant exists.
+ *
+ * Note also that the macro expands its arguments multiple times, so
+ * they should not be expressions with side effects.
+ *
+ * @param tree A pointer to a struct rbtree to walk
+ * @param node The symbol name of a local struct rbnode* variable to
+ *             use as the iterator
+ */
+#define RB_FOR_EACH(tree, node) \
+	for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node);	\
+	     (node = z_rb_foreach_next(tree, &__f));			\
+	     /**/)
+
+/**
+ * @brief Loop over rbtree with implicit container field logic
+ *
+ * As for RB_FOR_EACH(), but "node" can have an arbitrary type
+ * containing a struct rbnode.
+ *
+ * @param tree A pointer to a struct rbtree to walk
+ * @param node The symbol name of a local iterator
+ * @param field The field name of a struct rbnode inside node
+ */
+#define RB_FOR_EACH_CONTAINER(tree, node, field)		           \
+	for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node);	   \
+			({struct rbnode *n = z_rb_foreach_next(tree, &__f); \
+			 node = n ? CONTAINER_OF(n, __typeof__(*(node)),   \
+					 field) : NULL; }) != NULL;        \
+			 /**/)
+
+#endif /* ZEPHYR_INCLUDE_SYS_RB_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/ring_buffer.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/ring_buffer.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/ring_buffer.h	(working copy)
@@ -0,0 +1,416 @@
+/* ring_buffer.h: Simple ring buffer API */
+
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+/** @file */
+
+#ifndef ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
+#define ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
+
+#include <kernel.h>
+#include <sys/util.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SIZE32_OF(x) (sizeof((x))/sizeof(uint32_t))
+
+/**
+ * @brief A structure to represent a ring buffer
+ */
+struct ring_buf {
+	uint32_t head;	 /**< Index in buf for the head element */
+	uint32_t tail;	 /**< Index in buf for the tail element */
+	union ring_buf_misc {
+		struct ring_buf_misc_item_mode {
+			uint32_t dropped_put_count; /**< Running tally of the
+						   * number of failed put
+						   * attempts.
+						   */
+		} item_mode;
+		struct ring_buf_misc_byte_mode {
+			uint32_t tmp_tail;
+			uint32_t tmp_head;
+		} byte_mode;
+	} misc;
+	uint32_t size;   /**< Size of buf in 32-bit chunks */
+
+	union ring_buf_buffer {
+		uint32_t *buf32;	 /**< Memory region for stored entries */
+		uint8_t *buf8;
+	} buf;
+	uint32_t mask;   /**< Modulo mask if size is a power of 2 */
+};
+
+/**
+ * @defgroup ring_buffer_apis Ring Buffer APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Statically define and initialize a high performance ring buffer.
+ *
+ * This macro establishes a ring buffer whose size must be a power of 2;
+ * that is, the ring buffer contains 2^pow 32-bit words, where @a pow is
+ * the specified ring buffer size exponent. A high performance ring buffer
+ * doesn't require the use of modulo arithmetic operations to maintain itself.
+ *
+ * The ring buffer can be accessed outside the module where it is defined
+ * using:
+ *
+ * @code extern struct ring_buf <name>; @endcode
+ *
+ * @param name Name of the ring buffer.
+ * @param pow Ring buffer size exponent.
+ */
+#define RING_BUF_ITEM_DECLARE_POW2(name, pow) \
+	static uint32_t _ring_buffer_data_##name[BIT(pow)]; \
+	struct ring_buf name = { \
+		.size = (BIT(pow)),	  \
+		.mask = (BIT(pow)) - 1, \
+		.buf = { .buf32 = _ring_buffer_data_##name } \
+	}
+
+/**
+ * @brief Statically define and initialize a standard ring buffer.
+ *
+ * This macro establishes a ring buffer of an arbitrary size. A standard
+ * ring buffer uses modulo arithmetic operations to maintain itself.
+ *
+ * The ring buffer can be accessed outside the module where it is defined
+ * using:
+ *
+ * @code extern struct ring_buf <name>; @endcode
+ *
+ * @param name Name of the ring buffer.
+ * @param size32 Size of ring buffer (in 32-bit words).
+ */
+#define RING_BUF_ITEM_DECLARE_SIZE(name, size32) \
+	static uint32_t _ring_buffer_data_##name[size32]; \
+	struct ring_buf name = { \
+		.size = size32, \
+		.buf = { .buf32 = _ring_buffer_data_##name} \
+	}
+
+/**
+ * @brief Statically define and initialize a ring buffer for byte data.
+ *
+ * This macro establishes a ring buffer of an arbitrary size.
+ *
+ * The ring buffer can be accessed outside the module where it is defined
+ * using:
+ *
+ * @code extern struct ring_buf <name>; @endcode
+ *
+ * @param name  Name of the ring buffer.
+ * @param size8 Size of ring buffer (in bytes).
+ */
+#define RING_BUF_DECLARE(name, size8) \
+	static uint8_t _ring_buffer_data_##name[size8]; \
+	struct ring_buf name = { \
+		.size = size8, \
+		.buf = { .buf8 = _ring_buffer_data_##name} \
+	}
+
+
+/**
+ * @brief Initialize a ring buffer.
+ *
+ * This routine initializes a ring buffer, prior to its first use. It is only
+ * used for ring buffers not defined using RING_BUF_DECLARE,
+ * RING_BUF_ITEM_DECLARE_POW2 or RING_BUF_ITEM_DECLARE_SIZE.
+ *
+ * Setting @a size to a power of 2 establishes a high performance ring buffer
+ * that doesn't require the use of modulo arithmetic operations to maintain
+ * itself.
+ *
+ * @param buf Address of ring buffer.
+ * @param size Ring buffer size (in 32-bit words or bytes).
+ * @param data Ring buffer data area (uint32_t data[size] or uint8_t data[size] for
+ *	       bytes mode).
+ */
+static inline void ring_buf_init(struct ring_buf *buf, uint32_t size, void *data)
+{
+	memset(buf, 0, sizeof(struct ring_buf));
+	buf->size = size;
+	buf->buf.buf32 = (uint32_t *)data;
+	if (is_power_of_two(size)) {
+		buf->mask = size - 1U;
+	} else {
+		buf->mask = 0U;
+	}
+}
+
+/** @brief Determine free space based on ring buffer parameters.
+ *
+ * @note Function for internal use.
+ *
+ * @param size Ring buffer size.
+ * @param head Ring buffer head.
+ * @param tail Ring buffer tail.
+ *
+ *  @return Ring buffer free space (in 32-bit words or bytes).
+ */
+static inline uint32_t z_ring_buf_custom_space_get(uint32_t size, uint32_t head,
+					      uint32_t tail)
+{
+	if (tail < head) {
+		return head - tail - 1U;
+	}
+
+	/* buf->tail > buf->head */
+	return (size - tail) + head - 1U;
+}
+
+/**
+ * @brief Determine if a ring buffer is empty.
+ *
+ * @param buf Address of ring buffer.
+ *
+ * @return 1 if the ring buffer is empty, or 0 if not.
+ */
+static inline int ring_buf_is_empty(struct ring_buf *buf)
+{
+	return (buf->head == buf->tail);
+}
+
+/**
+ * @brief Reset ring buffer state.
+ *
+ * @param buf Address of ring buffer.
+ */
+static inline void ring_buf_reset(struct ring_buf *buf)
+{
+	buf->head = 0;
+	buf->tail = 0;
+	memset(&buf->misc, 0, sizeof(buf->misc));
+}
+
+/**
+ * @brief Determine free space in a ring buffer.
+ *
+ * @param buf Address of ring buffer.
+ *
+ * @return Ring buffer free space (in 32-bit words or bytes).
+ */
+static inline uint32_t ring_buf_space_get(struct ring_buf *buf)
+{
+	return z_ring_buf_custom_space_get(buf->size, buf->head, buf->tail);
+}
+
+/**
+ * @brief Return ring buffer capacity.
+ *
+ * @param buf Address of ring buffer.
+ *
+ * @return Ring buffer capacity (in 32-bit words or bytes).
+ */
+static inline uint32_t ring_buf_capacity_get(struct ring_buf *buf)
+{
+	/* One element is used to distinguish between empty and full state. */
+	return buf->size - 1;
+}
+
+/**
+ * @brief Write a data item to a ring buffer.
+ *
+ * This routine writes a data item to ring buffer @a buf. The data item
+ * is an array of 32-bit words (from zero to 1020 bytes in length),
+ * coupled with a 16-bit type identifier and an 8-bit integer value.
+ *
+ * @warning
+ * Use cases involving multiple writers to the ring buffer must prevent
+ * concurrent write operations, either by preventing all writers from
+ * being preempted or by using a mutex to govern writes to the ring buffer.
+ *
+ * @param buf Address of ring buffer.
+ * @param type Data item's type identifier (application specific).
+ * @param value Data item's integer value (application specific).
+ * @param data Address of data item.
+ * @param size32 Data item size (number of 32-bit words).
+ *
+ * @retval 0 Data item was written.
+ * @retval -EMSGSIZE Ring buffer has insufficient free space.
+ */
+int ring_buf_item_put(struct ring_buf *buf, uint16_t type, uint8_t value,
+		      uint32_t *data, uint8_t size32);
+
+/**
+ * @brief Read a data item from a ring buffer.
+ *
+ * This routine reads a data item from ring buffer @a buf. The data item
+ * is an array of 32-bit words (up to 1020 bytes in length),
+ * coupled with a 16-bit type identifier and an 8-bit integer value.
+ *
+ * @warning
+ * Use cases involving multiple reads of the ring buffer must prevent
+ * concurrent read operations, either by preventing all readers from
+ * being preempted or by using a mutex to govern reads to the ring buffer.
+ *
+ * @param buf Address of ring buffer.
+ * @param type Area to store the data item's type identifier.
+ * @param value Area to store the data item's integer value.
+ * @param data Area to store the data item.
+ * @param size32 Size of the data item storage area (number of 32-bit chunks).
+ *
+ * @retval 0 Data item was fetched; @a size32 now contains the number of
+ *         32-bit words read into data area @a data.
+ * @retval -EAGAIN Ring buffer is empty.
+ * @retval -EMSGSIZE Data area @a data is too small; @a size32 now contains
+ *         the number of 32-bit words needed.
+ */
+int ring_buf_item_get(struct ring_buf *buf, uint16_t *type, uint8_t *value,
+		      uint32_t *data, uint8_t *size32);
+
+/**
+ * @brief Allocate buffer for writing data to a ring buffer.
+ *
+ * With this routine, memory copying can be reduced since internal ring buffer
+ * can be used directly by the user. Once data is written to allocated area
+ * number of bytes written can be confirmed (see @ref ring_buf_put_finish).
+ *
+ * @warning
+ * Use cases involving multiple writers to the ring buffer must prevent
+ * concurrent write operations, either by preventing all writers from
+ * being preempted or by using a mutex to govern writes to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and item access
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param[in]  buf  Address of ring buffer.
+ * @param[out] data Pointer to the address. It is set to a location within
+ *		    ring buffer.
+ * @param[in]  size Requested allocation size (in bytes).
+ *
+ * @return Size of allocated buffer which can be smaller than requested if
+ *	   there is not enough free space or buffer wraps.
+ */
+uint32_t ring_buf_put_claim(struct ring_buf *buf, uint8_t **data, uint32_t size);
+
+/**
+ * @brief Indicate number of bytes written to allocated buffers.
+ *
+ * @warning
+ * Use cases involving multiple writers to the ring buffer must prevent
+ * concurrent write operations, either by preventing all writers from
+ * being preempted or by using a mutex to govern writes to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and item access
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param  buf  Address of ring buffer.
+ * @param  size Number of valid bytes in the allocated buffers.
+ *
+ * @retval 0 Successful operation.
+ * @retval -EINVAL Provided @a size exceeds free space in the ring buffer.
+ */
+int ring_buf_put_finish(struct ring_buf *buf, uint32_t size);
+
+/**
+ * @brief Write (copy) data to a ring buffer.
+ *
+ * This routine writes data to a ring buffer @a buf.
+ *
+ * @warning
+ * Use cases involving multiple writers to the ring buffer must prevent
+ * concurrent write operations, either by preventing all writers from
+ * being preempted or by using a mutex to govern writes to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and item access
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param buf Address of ring buffer.
+ * @param data Address of data.
+ * @param size Data size (in bytes).
+ *
+ * @retval Number of bytes written.
+ */
+uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size);
+
+/**
+ * @brief Get address of a valid data in a ring buffer.
+ *
+ * With this routine, memory copying can be reduced since internal ring buffer
+ * can be used directly by the user. Once data is processed it can be freed
+ * using @ref ring_buf_get_finish.
+ *
+ * @warning
+ * Use cases involving multiple reads of the ring buffer must prevent
+ * concurrent read operations, either by preventing all readers from
+ * being preempted or by using a mutex to govern reads to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and item access
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param[in]  buf  Address of ring buffer.
+ * @param[out] data Pointer to the address. It is set to a location within
+ *		    ring buffer.
+ * @param[in]  size Requested size (in bytes).
+ *
+ * @return Number of valid bytes in the provided buffer which can be smaller
+ *	   than requested if there is not enough free space or buffer wraps.
+ */
+uint32_t ring_buf_get_claim(struct ring_buf *buf, uint8_t **data, uint32_t size);
+
+/**
+ * @brief Indicate number of bytes read from claimed buffer.
+ *
+ * @warning
+ * Use cases involving multiple reads of the ring buffer must prevent
+ * concurrent read operations, either by preventing all readers from
+ * being preempted or by using a mutex to govern reads to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and  item mode
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param  buf  Address of ring buffer.
+ * @param  size Number of bytes that can be freed.
+ *
+ * @retval 0 Successful operation.
+ * @retval -EINVAL Provided @a size exceeds valid bytes in the ring buffer.
+ */
+int ring_buf_get_finish(struct ring_buf *buf, uint32_t size);
+
+/**
+ * @brief Read data from a ring buffer.
+ *
+ * This routine reads data from a ring buffer @a buf.
+ *
+ * @warning
+ * Use cases involving multiple reads of the ring buffer must prevent
+ * concurrent read operations, either by preventing all readers from
+ * being preempted or by using a mutex to govern reads to the ring buffer.
+ *
+ * @warning
+ * Ring buffer instance should not mix byte access and  item mode
+ * (calls prefixed with ring_buf_item_).
+ *
+ * @param buf  Address of ring buffer.
+ * @param data Address of the output buffer.
+ * @param size Data size (in bytes).
+ *
+ * @retval Number of bytes written to the output buffer.
+ */
+uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/sem.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/sem.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/sem.h	(working copy)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief public sys_sem APIs.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_SEM_H_
+#define ZEPHYR_INCLUDE_SYS_SEM_H_
+
+/*
+ * sys_sem exists in user memory working as counter semaphore for
+ * user mode thread when user mode enabled. When user mode isn't
+ * enabled, sys_sem behaves like k_sem.
+ */
+
+#include <kernel.h>
+#include <sys/atomic.h>
+#include <zephyr/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * sys_sem structure
+ */
+struct sys_sem {
+#ifdef CONFIG_USERSPACE
+	struct k_futex futex;
+	int limit;
+#else
+	struct k_sem kernel_sem;
+#endif
+};
+
+/**
+ * @defgroup user_semaphore_apis User mode semaphore APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Statically define and initialize a sys_sem
+ *
+ * The semaphore can be accessed outside the module where it is defined using:
+ *
+ * @code extern struct sys_sem <name>; @endcode
+ *
+ * Route this to memory domains using K_APP_DMEM().
+ *
+ * @param _name Name of the semaphore.
+ * @param _initial_count Initial semaphore count.
+ * @param _count_limit Maximum permitted semaphore count.
+ */
+#ifdef CONFIG_USERSPACE
+#define SYS_SEM_DEFINE(_name, _initial_count, _count_limit) \
+	struct sys_sem _name = { \
+		.futex = { _initial_count }, \
+		.limit = _count_limit \
+	}; \
+	BUILD_ASSERT(((_count_limit) != 0) && \
+		     ((_initial_count) <= (_count_limit)))
+#else
+/* Stuff this in the section with the rest of the k_sem objects, since they
+ * are identical and can be treated as a k_sem in the boot initialization code
+ */
+#define SYS_SEM_DEFINE(_name, _initial_count, _count_limit) \
+	Z_STRUCT_SECTION_ITERABLE_ALTERNATE(k_sem, sys_sem, _name) = { \
+		.kernel_sem = Z_SEM_INITIALIZER(_name.kernel_sem, \
+						_initial_count, _count_limit) \
+	}; \
+	BUILD_ASSERT(((_count_limit) != 0) && \
+		     ((_initial_count) <= (_count_limit)))
+#endif
+
+/**
+ * @brief Initialize a semaphore.
+ *
+ * This routine initializes a semaphore instance, prior to its first use.
+ *
+ * @param sem Address of the semaphore.
+ * @param initial_count Initial semaphore count.
+ * @param limit Maximum permitted semaphore count.
+ *
+ * @retval 0 Initial success.
+ * @retval -EINVAL Bad parameters, the value of limit should be located in
+ *         (0, INT_MAX] and initial_count shouldn't be greater than limit.
+ */
+int sys_sem_init(struct sys_sem *sem, unsigned int initial_count,
+		unsigned int limit);
+
+/**
+ * @brief Give a semaphore.
+ *
+ * This routine gives @a sem, unless the semaphore is already at its
+ * maximum permitted count.
+ *
+ * @param sem Address of the semaphore.
+ *
+ * @retval 0 Semaphore given.
+ * @retval -EINVAL Parameter address not recognized.
+ * @retval -EACCES Caller does not have enough access.
+ * @retval -EAGAIN Count reached Maximum permitted count and try again.
+ */
+int sys_sem_give(struct sys_sem *sem);
+
+/**
+ * @brief Take a sys_sem.
+ *
+ * This routine takes @a sem.
+ *
+ * @param sem Address of the sys_sem.
+ * @param timeout Waiting period to take the sys_sem,
+ *                or one of the special values K_NO_WAIT and K_FOREVER.
+ *
+ * @retval 0 sys_sem taken.
+ * @retval -EINVAL Parameter address not recognized.
+ * @retval -ETIMEDOUT Waiting period timed out.
+ * @retval -EACCES Caller does not have enough access.
+ */
+int sys_sem_take(struct sys_sem *sem, k_timeout_t timeout);
+
+/**
+ * @brief Get sys_sem's value
+ *
+ * This routine returns the current value of @a sem.
+ *
+ * @param sem Address of the sys_sem.
+ *
+ * @return Current value of sys_sem.
+ */
+unsigned int sys_sem_count_get(struct sys_sem *sem);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: ModuleDemo/BLE/CM0/User/include/sys/sflist.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/sflist.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/sflist.h	(working copy)
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief Single-linked list implementation
+ *
+ * Single-linked list implementation using inline macros/functions.
+ * This API is not thread safe, and thus if a list is used across threads,
+ * calls to functions must be protected with synchronization primitives.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_SFLIST_H_
+#define ZEPHYR_INCLUDE_SYS_SFLIST_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "list_gen.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __LP64__
+typedef uint64_t unative_t;
+#else
+typedef uint32_t unative_t;
+#endif
+
+struct _sfnode {
+	unative_t next_and_flags;
+};
+
+typedef struct _sfnode sys_sfnode_t;
+
+struct _sflist {
+	sys_sfnode_t *head;
+	sys_sfnode_t *tail;
+};
+
+typedef struct _sflist sys_sflist_t;
+
+
+/**
+ * @brief Provide the primitive to iterate on a list
+ * Note: the loop is unsafe and thus __sn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SFLIST_FOR_EACH_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_SFLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_sflist_t to iterate on
+ * @param __sn A sys_sfnode_t pointer to peek each node of the list
+ */
+#define SYS_SFLIST_FOR_EACH_NODE(__sl, __sn)				\
+	Z_GENLIST_FOR_EACH_NODE(sflist, __sl, __sn)
+
+/**
+ * @brief Provide the primitive to iterate on a list, from a node in the list
+ * Note: the loop is unsafe and thus __sn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SFLIST_ITERATE_FROM_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * Like SYS_SFLIST_FOR_EACH_NODE(), but __dn already contains a node in the list
+ * where to start searching for the next entry from. If NULL, it starts from
+ * the head.
+ *
+ * This and other SYS_SFLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_sflist_t to iterate on
+ * @param __sn A sys_sfnode_t pointer to peek each node of the list
+ *             it contains the starting node, or NULL to start from the head
+ */
+#define SYS_SFLIST_ITERATE_FROM_NODE(__sl, __sn)				\
+	Z_GENLIST_ITERATE_FROM_NODE(sflist, __sl, __sn)
+
+/**
+ * @brief Provide the primitive to safely iterate on a list
+ * Note: __sn can be removed, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SFLIST_FOR_EACH_NODE_SAFE(l, n, s) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_SFLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_sflist_t to iterate on
+ * @param __sn A sys_sfnode_t pointer to peek each node of the list
+ * @param __sns A sys_sfnode_t pointer for the loop to run safely
+ */
+#define SYS_SFLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns)			\
+	Z_GENLIST_FOR_EACH_NODE_SAFE(sflist, __sl, __sn, __sns)
+
+/*
+ * @brief Provide the primitive to resolve the container of a list node
+ * Note: it is safe to use with NULL pointer nodes
+ *
+ * @param __ln A pointer on a sys_sfnode_t to get its container
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_CONTAINER(__ln, __cn, __n) \
+	Z_GENLIST_CONTAINER(__ln, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek container of the list head
+ *
+ * @param __sl A pointer on a sys_sflist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
+	Z_GENLIST_PEEK_HEAD_CONTAINER(sflist, __sl, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek container of the list tail
+ *
+ * @param __sl A pointer on a sys_sflist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
+	Z_GENLIST_PEEK_TAIL_CONTAINER(sflist, __sl, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek the next container
+ *
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
+	Z_GENLIST_PEEK_NEXT_CONTAINER(sflist, __cn, __n)
+
+/**
+ * @brief Provide the primitive to iterate on a list under a container
+ * Note: the loop is unsafe and thus __cn should not be detached
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SFLIST_FOR_EACH_CONTAINER(l, c, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __sl A pointer on a sys_sflist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_FOR_EACH_CONTAINER(__sl, __cn, __n)			\
+	Z_GENLIST_FOR_EACH_CONTAINER(sflist, __sl, __cn, __n)
+
+/**
+ * @brief Provide the primitive to safely iterate on a list under a container
+ * Note: __cn can be detached, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SFLIST_FOR_EACH_NODE_SAFE(l, c, cn, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __sl A pointer on a sys_sflist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __cns A pointer for the loop to run safely
+ * @param __n The field name of sys_sfnode_t within the container struct
+ */
+#define SYS_SFLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n)	\
+	Z_GENLIST_FOR_EACH_CONTAINER_SAFE(sflist, __sl, __cn, __cns, __n)
+
+
+/*
+ * Required function definitions for the list_gen.h interface
+ *
+ * These are the only functions that do not treat the list/node pointers
+ * as completely opaque types.
+ */
+
+/**
+ * @brief Initialize a list
+ *
+ * @param list A pointer on the list to initialize
+ */
+static inline void sys_sflist_init(sys_sflist_t *list)
+{
+	list->head = NULL;
+	list->tail = NULL;
+}
+
+#define SYS_SFLIST_STATIC_INIT(ptr_to_list) {NULL, NULL}
+#define SYS_SFLIST_FLAGS_MASK	0x3UL
+
+static inline sys_sfnode_t *z_sfnode_next_peek(sys_sfnode_t *node)
+{
+	return (sys_sfnode_t *)(node->next_and_flags & ~SYS_SFLIST_FLAGS_MASK);
+}
+
+static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node);
+
+static inline void z_sfnode_next_set(sys_sfnode_t *parent,
+				       sys_sfnode_t *child)
+{
+	uint8_t cur_flags = sys_sfnode_flags_get(parent);
+
+	parent->next_and_flags = cur_flags | (unative_t)child;
+}
+
+static inline void z_sflist_head_set(sys_sflist_t *list, sys_sfnode_t *node)
+{
+	list->head = node;
+}
+
+static inline void z_sflist_tail_set(sys_sflist_t *list, sys_sfnode_t *node)
+{
+	list->tail = node;
+}
+
+/**
+ * @brief Peek the first node from the list
+ *
+ * @param list A point on the list to peek the first node from
+ *
+ * @return A pointer on the first node of the list (or NULL if none)
+ */
+static inline sys_sfnode_t *sys_sflist_peek_head(sys_sflist_t *list)
+{
+	return list->head;
+}
+
+/**
+ * @brief Peek the last node from the list
+ *
+ * @param list A point on the list to peek the last node from
+ *
+ * @return A pointer on the last node of the list (or NULL if none)
+ */
+static inline sys_sfnode_t *sys_sflist_peek_tail(sys_sflist_t *list)
+{
+	return list->tail;
+}
+
+/*
+ * APIs specific to sflist type
+ */
+
+/**
+ * @brief Fetch flags value for a particular sfnode
+ *
+ * @param node A pointer to the node to fetch flags from
+ * @return The value of flags, which will be between 0 and 3
+ */
+static inline uint8_t sys_sfnode_flags_get(sys_sfnode_t *node)
+{
+	return node->next_and_flags & SYS_SFLIST_FLAGS_MASK;
+}
+
+/**
+ * @brief Initialize an sflist node
+ *
+ * Set an initial flags value for this slist node, which can be a value between
+ * 0 and 3. These flags will persist even if the node is moved around
+ * within a list, removed, or transplanted to a different slist.
+ *
+ * This is ever so slightly faster than sys_sfnode_flags_set() and should
+ * only be used on a node that hasn't been added to any list.
+ *
+ * @param node A pointer to the node to set the flags on
+ * @param flags A value between 0 and 3 to set the flags value
+ */
+static inline void sys_sfnode_init(sys_sfnode_t *node, uint8_t flags)
+{
+	__ASSERT((flags & ~SYS_SFLIST_FLAGS_MASK) == 0UL, "flags too large");
+	node->next_and_flags = flags;
+}
+
+/**
+ * @brief Set flags value for an sflist node
+ *
+ * Set a flags value for this slist node, which can be a value between
+ * 0 and 3. These flags will persist even if the node is moved around
+ * within a list, removed, or transplanted to a different slist.
+ *
+ * @param node A pointer to the node to set the flags on
+ * @param flags A value between 0 and 3 to set the flags value
+ */
+static inline void sys_sfnode_flags_set(sys_sfnode_t *node, uint8_t flags)
+{
+	__ASSERT((flags & ~SYS_SFLIST_FLAGS_MASK) == 0UL, "flags too large");
+	node->next_and_flags = (unative_t)(z_sfnode_next_peek(node)) | flags;
+}
+
+/*
+ * Derived, generated APIs
+ */
+
+/**
+ * @brief Test if the given list is empty
+ *
+ * @param list A pointer on the list to test
+ *
+ * @return a boolean, true if it's empty, false otherwise
+ */
+static inline bool sys_sflist_is_empty(sys_sflist_t *list);
+
+Z_GENLIST_IS_EMPTY(sflist)
+
+/**
+ * @brief Peek the next node from current node, node is not NULL
+ *
+ * Faster then sys_sflist_peek_next() if node is known not to be NULL.
+ *
+ * @param node A pointer on the node where to peek the next node
+ *
+ * @return a pointer on the next node (or NULL if none)
+ */
+static inline sys_sfnode_t *sys_sflist_peek_next_no_check(sys_sfnode_t *node);
+
+Z_GENLIST_PEEK_NEXT_NO_CHECK(sflist, sfnode)
+
+/**
+ * @brief Peek the next node from current node
+ *
+ * @param node A pointer on the node where to peek the next node
+ *
+ * @return a pointer on the next node (or NULL if none)
+ */
+static inline sys_sfnode_t *sys_sflist_peek_next(sys_sfnode_t *node);
+
+Z_GENLIST_PEEK_NEXT(sflist, sfnode)
+
+/**
+ * @brief Prepend a node to the given list
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to prepend
+ */
+static inline void sys_sflist_prepend(sys_sflist_t *list,
+				      sys_sfnode_t *node);
+
+Z_GENLIST_PREPEND(sflist, sfnode)
+
+/**
+ * @brief Append a node to the given list
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to append
+ */
+static inline void sys_sflist_append(sys_sflist_t *list,
+				     sys_sfnode_t *node);
+
+Z_GENLIST_APPEND(sflist, sfnode)
+
+/**
+ * @brief Append a list to the given list
+ *
+ * Append a singly-linked, NULL-terminated list consisting of nodes containing
+ * the pointer to the next node as the first element of a node, to @a list.
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * FIXME: Why are the element parameters void *?
+ *
+ * @param list A pointer on the list to affect
+ * @param head A pointer to the first element of the list to append
+ * @param tail A pointer to the last element of the list to append
+ */
+static inline void sys_sflist_append_list(sys_sflist_t *list,
+					  void *head, void *tail);
+
+Z_GENLIST_APPEND_LIST(sflist, sfnode)
+
+/**
+ * @brief merge two sflists, appending the second one to the first
+ *
+ * When the operation is completed, the appending list is empty.
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param list_to_append A pointer to the list to append.
+ */
+static inline void sys_sflist_merge_sflist(sys_sflist_t *list,
+					   sys_sflist_t *list_to_append);
+
+Z_GENLIST_MERGE_LIST(sflist, sfnode)
+
+/**
+ * @brief Insert a node to the given list
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param prev A pointer on the previous node
+ * @param node A pointer on the node to insert
+ */
+static inline void sys_sflist_insert(sys_sflist_t *list,
+				     sys_sfnode_t *prev,
+				     sys_sfnode_t *node);
+
+Z_GENLIST_INSERT(sflist, sfnode)
+
+/**
+ * @brief Fetch and remove the first node of the given list
+ *
+ * List must be known to be non-empty.
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ *
+ * @return A pointer to the first node of the list
+ */
+static inline sys_sfnode_t *sys_sflist_get_not_empty(sys_sflist_t *list);
+
+Z_GENLIST_GET_NOT_EMPTY(sflist, sfnode)
+
+/**
+ * @brief Fetch and remove the first node of the given list
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ *
+ * @return A pointer to the first node of the list (or NULL if empty)
+ */
+static inline sys_sfnode_t *sys_sflist_get(sys_sflist_t *list);
+
+Z_GENLIST_GET(sflist, sfnode)
+
+/**
+ * @brief Remove a node
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param prev_node A pointer on the previous node
+ *        (can be NULL, which means the node is the list's head)
+ * @param node A pointer on the node to remove
+ */
+static inline void sys_sflist_remove(sys_sflist_t *list,
+				     sys_sfnode_t *prev_node,
+				     sys_sfnode_t *node);
+
+Z_GENLIST_REMOVE(sflist, sfnode)
+
+/**
+ * @brief Find and remove a node from a list
+ *
+ * This and other sys_sflist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to remove from the list
+ *
+ * @return true if node was removed
+ */
+static inline bool sys_sflist_find_and_remove(sys_sflist_t *list,
+					      sys_sfnode_t *node);
+
+Z_GENLIST_FIND_AND_REMOVE(sflist, sfnode)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_SFLIST_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/slist.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/slist.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/slist.h	(working copy)
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief Single-linked list implementation
+ *
+ * Single-linked list implementation using inline macros/functions.
+ * This API is not thread safe, and thus if a list is used across threads,
+ * calls to functions must be protected with synchronization primitives.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_SLIST_H_
+#define ZEPHYR_INCLUDE_SYS_SLIST_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "list_gen.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct _snode {
+	struct _snode *next;
+};
+
+typedef struct _snode sys_snode_t;
+
+struct _slist {
+	sys_snode_t *head;
+	sys_snode_t *tail;
+};
+
+typedef struct _slist sys_slist_t;
+
+/**
+ * @brief Provide the primitive to iterate on a list
+ * Note: the loop is unsafe and thus __sn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SLIST_FOR_EACH_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_SLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_slist_t to iterate on
+ * @param __sn A sys_snode_t pointer to peek each node of the list
+ */
+#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn)				\
+	Z_GENLIST_FOR_EACH_NODE(slist, __sl, __sn)
+
+/**
+ * @brief Provide the primitive to iterate on a list, from a node in the list
+ * Note: the loop is unsafe and thus __sn should not be removed
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SLIST_ITERATE_FROM_NODE(l, n) {
+ *         <user code>
+ *     }
+ *
+ * Like SYS_SLIST_FOR_EACH_NODE(), but __dn already contains a node in the list
+ * where to start searching for the next entry from. If NULL, it starts from
+ * the head.
+ *
+ * This and other SYS_SLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_slist_t to iterate on
+ * @param __sn A sys_snode_t pointer to peek each node of the list
+ *             it contains the starting node, or NULL to start from the head
+ */
+#define SYS_SLIST_ITERATE_FROM_NODE(__sl, __sn)				\
+	Z_GENLIST_ITERATE_FROM_NODE(slist, __sl, __sn)
+
+/**
+ * @brief Provide the primitive to safely iterate on a list
+ * Note: __sn can be removed, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SLIST_FOR_EACH_NODE_SAFE(l, n, s) {
+ *         <user code>
+ *     }
+ *
+ * This and other SYS_SLIST_*() macros are not thread safe.
+ *
+ * @param __sl A pointer on a sys_slist_t to iterate on
+ * @param __sn A sys_snode_t pointer to peek each node of the list
+ * @param __sns A sys_snode_t pointer for the loop to run safely
+ */
+#define SYS_SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns)			\
+	Z_GENLIST_FOR_EACH_NODE_SAFE(slist, __sl, __sn, __sns)
+
+/*
+ * @brief Provide the primitive to resolve the container of a list node
+ * Note: it is safe to use with NULL pointer nodes
+ *
+ * @param __ln A pointer on a sys_node_t to get its container
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_CONTAINER(__ln, __cn, __n) \
+	Z_GENLIST_CONTAINER(__ln, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek container of the list head
+ *
+ * @param __sl A pointer on a sys_slist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
+	Z_GENLIST_PEEK_HEAD_CONTAINER(slist, __sl, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek container of the list tail
+ *
+ * @param __sl A pointer on a sys_slist_t to peek
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
+	Z_GENLIST_PEEK_TAIL_CONTAINER(slist, __sl, __cn, __n)
+
+/*
+ * @brief Provide the primitive to peek the next container
+ *
+ * @param __cn Container struct type pointer
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
+	Z_GENLIST_PEEK_NEXT_CONTAINER(slist, __cn, __n)
+
+/**
+ * @brief Provide the primitive to iterate on a list under a container
+ * Note: the loop is unsafe and thus __cn should not be detached
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SLIST_FOR_EACH_CONTAINER(l, c, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __sl A pointer on a sys_slist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_FOR_EACH_CONTAINER(__sl, __cn, __n)			\
+	Z_GENLIST_FOR_EACH_CONTAINER(slist, __sl, __cn, __n)
+
+/**
+ * @brief Provide the primitive to safely iterate on a list under a container
+ * Note: __cn can be detached, it will not break the loop.
+ *
+ * User _MUST_ add the loop statement curly braces enclosing its own code:
+ *
+ *     SYS_SLIST_FOR_EACH_NODE_SAFE(l, c, cn, n) {
+ *         <user code>
+ *     }
+ *
+ * @param __sl A pointer on a sys_slist_t to iterate on
+ * @param __cn A pointer to peek each entry of the list
+ * @param __cns A pointer for the loop to run safely
+ * @param __n The field name of sys_node_t within the container struct
+ */
+#define SYS_SLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n)	\
+	Z_GENLIST_FOR_EACH_CONTAINER_SAFE(slist, __sl, __cn, __cns, __n)
+
+
+/*
+ * Required function definitions for the list_gen.h interface
+ *
+ * These are the only functions that do not treat the list/node pointers
+ * as completely opaque types.
+ */
+
+/**
+ * @brief Initialize a list
+ *
+ * @param list A pointer on the list to initialize
+ */
+static inline void sys_slist_init(sys_slist_t *list)
+{
+	list->head = NULL;
+	list->tail = NULL;
+}
+
+#define SYS_SLIST_STATIC_INIT(ptr_to_list) {NULL, NULL}
+
+static inline sys_snode_t *z_snode_next_peek(sys_snode_t *node)
+{
+	return node->next;
+}
+
+static inline void z_snode_next_set(sys_snode_t *parent, sys_snode_t *child)
+{
+	parent->next = child;
+}
+
+static inline void z_slist_head_set(sys_slist_t *list, sys_snode_t *node)
+{
+	list->head = node;
+}
+
+static inline void z_slist_tail_set(sys_slist_t *list, sys_snode_t *node)
+{
+	list->tail = node;
+}
+
+/**
+ * @brief Peek the first node from the list
+ *
+ * @param list A point on the list to peek the first node from
+ *
+ * @return A pointer on the first node of the list (or NULL if none)
+ */
+static inline sys_snode_t *sys_slist_peek_head(sys_slist_t *list)
+{
+	return list->head;
+}
+
+/**
+ * @brief Peek the last node from the list
+ *
+ * @param list A point on the list to peek the last node from
+ *
+ * @return A pointer on the last node of the list (or NULL if none)
+ */
+static inline sys_snode_t *sys_slist_peek_tail(sys_slist_t *list)
+{
+	return list->tail;
+}
+
+/*
+ * Derived, generated APIs
+ */
+
+/**
+ * @brief Test if the given list is empty
+ *
+ * @param list A pointer on the list to test
+ *
+ * @return a boolean, true if it's empty, false otherwise
+ */
+static inline bool sys_slist_is_empty(sys_slist_t *list);
+
+Z_GENLIST_IS_EMPTY(slist)
+
+/**
+ * @brief Peek the next node from current node, node is not NULL
+ *
+ * Faster then sys_slist_peek_next() if node is known not to be NULL.
+ *
+ * @param node A pointer on the node where to peek the next node
+ *
+ * @return a pointer on the next node (or NULL if none)
+ */
+static inline sys_snode_t *sys_slist_peek_next_no_check(sys_snode_t *node);
+
+Z_GENLIST_PEEK_NEXT_NO_CHECK(slist, snode)
+
+/**
+ * @brief Peek the next node from current node
+ *
+ * @param node A pointer on the node where to peek the next node
+ *
+ * @return a pointer on the next node (or NULL if none)
+ */
+static inline sys_snode_t *sys_slist_peek_next(sys_snode_t *node);
+
+Z_GENLIST_PEEK_NEXT(slist, snode)
+
+/**
+ * @brief Prepend a node to the given list
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to prepend
+ */
+static inline void sys_slist_prepend(sys_slist_t *list,
+				     sys_snode_t *node);
+
+Z_GENLIST_PREPEND(slist, snode)
+
+/**
+ * @brief Append a node to the given list
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to append
+ */
+static inline void sys_slist_append(sys_slist_t *list,
+				    sys_snode_t *node);
+
+Z_GENLIST_APPEND(slist, snode)
+
+/**
+ * @brief Append a list to the given list
+ *
+ * Append a singly-linked, NULL-terminated list consisting of nodes containing
+ * the pointer to the next node as the first element of a node, to @a list.
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * FIXME: Why are the element parameters void *?
+ *
+ * @param list A pointer on the list to affect
+ * @param head A pointer to the first element of the list to append
+ * @param tail A pointer to the last element of the list to append
+ */
+static inline void sys_slist_append_list(sys_slist_t *list,
+					 void *head, void *tail);
+
+Z_GENLIST_APPEND_LIST(slist, snode)
+
+/**
+ * @brief merge two slists, appending the second one to the first
+ *
+ * When the operation is completed, the appending list is empty.
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param list_to_append A pointer to the list to append.
+ */
+static inline void sys_slist_merge_slist(sys_slist_t *list,
+					 sys_slist_t *list_to_append);
+
+Z_GENLIST_MERGE_LIST(slist, snode)
+
+/**
+ * @brief Insert a node to the given list
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param prev A pointer on the previous node
+ * @param node A pointer on the node to insert
+ */
+static inline void sys_slist_insert(sys_slist_t *list,
+				    sys_snode_t *prev,
+				    sys_snode_t *node);
+
+Z_GENLIST_INSERT(slist, snode)
+
+/**
+ * @brief Fetch and remove the first node of the given list
+ *
+ * List must be known to be non-empty.
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ *
+ * @return A pointer to the first node of the list
+ */
+static inline sys_snode_t *sys_slist_get_not_empty(sys_slist_t *list);
+
+Z_GENLIST_GET_NOT_EMPTY(slist, snode)
+
+/**
+ * @brief Fetch and remove the first node of the given list
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ *
+ * @return A pointer to the first node of the list (or NULL if empty)
+ */
+static inline sys_snode_t *sys_slist_get(sys_slist_t *list);
+
+Z_GENLIST_GET(slist, snode)
+
+/**
+ * @brief Remove a node
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param prev_node A pointer on the previous node
+ *        (can be NULL, which means the node is the list's head)
+ * @param node A pointer on the node to remove
+ */
+static inline void sys_slist_remove(sys_slist_t *list,
+				    sys_snode_t *prev_node,
+				    sys_snode_t *node);
+
+Z_GENLIST_REMOVE(slist, snode)
+
+/**
+ * @brief Find and remove a node from a list
+ *
+ * This and other sys_slist_*() functions are not thread safe.
+ *
+ * @param list A pointer on the list to affect
+ * @param node A pointer on the node to remove from the list
+ *
+ * @return true if node was removed
+ */
+static inline bool sys_slist_find_and_remove(sys_slist_t *list,
+					     sys_snode_t *node);
+
+Z_GENLIST_FIND_AND_REMOVE(slist, snode)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_SLIST_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/util.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/util.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/util.h	(working copy)
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 2011-2014, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Misc utilities
+ *
+ * Misc utilities usable by the kernel and application code.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_UTIL_H_
+#define ZEPHYR_INCLUDE_SYS_UTIL_H_
+
+/* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn
+ * into '1' and '0' for asm or linker scripts
+ */
+#include <stdbool.h>
+#include <config.h>
+
+/*
+ * Most of the eldritch implementation details for all the macrobatics
+ * below (APIs like IS_ENABLED(), COND_CODE_1(), etc.) are hidden away
+ * in this file.
+ */
+#include "util_internal.h"
+
+#ifndef _ASMLANGUAGE
+
+//#include <zephyr/types.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup sys-util Zephyr utilities
+ * @{
+ */
+
+/** @brief Cast @p x, a pointer, to an unsigned integer. */
+#define POINTER_TO_UINT(x) ((uintptr_t) (x))
+/** @brief Cast @p x, an unsigned integer, to a <tt>void*</tt>. */
+#define UINT_TO_POINTER(x) ((void *) (uintptr_t) (x))
+/** @brief Cast @p x, a pointer, to a signed integer. */
+#define POINTER_TO_INT(x)  ((intptr_t) (x))
+/** @brief Cast @p x, a signed integer, to a <tt>void*</tt>. */
+#define INT_TO_POINTER(x)  ((void *) (intptr_t) (x))
+
+#if !(defined(__CHAR_BIT__) && defined(__SIZEOF_LONG__))
+#	error Missing required predefined macros for BITS_PER_LONG calculation
+#endif
+
+/** Number of bits in a long int. */
+#define BITS_PER_LONG	(__CHAR_BIT__ * __SIZEOF_LONG__)
+
+/**
+ * @brief Create a contiguous bitmask starting at bit position @p l
+ *        and ending at position @p h.
+ */
+#define GENMASK(h, l) \
+	(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+/** @brief 0 if @p cond is true-ish; causes a compile error otherwise. */
+#define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1)
+
+#if defined(__cplusplus)
+
+/* The built-in function used below for type checking in C is not
+ * supported by GNU C++.
+ */
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
+#else /* __cplusplus */
+
+/**
+ * @brief Zero if @p array has an array type, a compile error otherwise
+ *
+ * This macro is available only from C, not C++.
+ */
+#define IS_ARRAY(array) \
+	ZERO_OR_COMPILE_ERROR( \
+		!__builtin_types_compatible_p(__typeof__(array), \
+					      __typeof__(&(array)[0])))
+
+/**
+ * @brief Number of elements in the given @p array
+ *
+ * In C++, due to language limitations, this will accept as @p array
+ * any type that implements <tt>operator[]</tt>. The results may not be
+ * particulary meaningful in this case.
+ *
+ * In C, passing a pointer as @p array causes a compile error.
+ */
+#define ARRAY_SIZE(array) \
+	((long) (IS_ARRAY(array) + (sizeof(array) / sizeof((array)[0]))))
+
+#endif /* __cplusplus */
+
+/**
+ * @brief Check if a pointer @p ptr lies within @p array.
+ *
+ * In C but not C++, this causes a compile error if @p array is not an array
+ * (e.g. if @p ptr and @p array are mixed up).
+ *
+ * @param ptr a pointer
+ * @param array an array
+ * @return 1 if @p ptr is part of @p array, 0 otherwise
+ */
+#define PART_OF_ARRAY(array, ptr) \
+	((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)]))
+
+/**
+ * @brief Get a pointer to a container structure from an element
+ *
+ * Example:
+ *
+ *	struct foo {
+ *		int bar;
+ *	};
+ *
+ *	struct foo my_foo;
+ *	int *ptr = &my_foo.bar;
+ *
+ *	struct foo *container = CONTAINER_OF(ptr, struct foo, bar);
+ *
+ * Above, @p container points at @p my_foo.
+ *
+ * @param ptr pointer to a structure element
+ * @param type name of the type that @p ptr is an element of
+ * @param field the name of the field within the struct @p ptr points to
+ * @return a pointer to the structure that contains @p ptr
+ */
+#define CONTAINER_OF(ptr, type, field) \
+	((type *)(((char *)(ptr)) - offsetof(type, field)))
+
+/**
+ * @brief Value of @p x rounded up to the next multiple of @p align,
+ *        which must be a power of 2.
+ */
+#define ROUND_UP(x, align)                                   \
+	(((unsigned long)(x) + ((unsigned long)(align) - 1)) & \
+	 ~((unsigned long)(align) - 1))
+
+/**
+ * @brief Value of @p x rounded down to the previous multiple of @p
+ *        align, which must be a power of 2.
+ */
+#define ROUND_DOWN(x, align)                                 \
+	((unsigned long)(x) & ~((unsigned long)(align) - 1))
+
+/** @brief Value of @p x rounded up to the next word boundary. */
+#define WB_UP(x) ROUND_UP(x, sizeof(void *))
+
+/** @brief Value of @p x rounded down to the previous word boundary. */
+#define WB_DN(x) ROUND_DOWN(x, sizeof(void *))
+
+/**
+ * @brief Ceiling function applied to @p numerator / @p divider as a fraction.
+ */
+#define ceiling_fraction(numerator, divider) \
+	(((numerator) + ((divider) - 1)) / (divider))
+
+/**
+ * @def MAX
+ * @brief The larger value between @p a and @p b.
+ * @note Arguments are evaluated twice.
+ */
+#ifndef MAX
+/* Use Z_MAX for a GCC-only, single evaluation version */
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/**
+ * @def MIN
+ * @brief The smaller value between @p a and @p b.
+ * @note Arguments are evaluated twice.
+ */
+#ifndef MIN
+/* Use Z_MIN for a GCC-only, single evaluation version */
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/**
+ * @brief Is @p x a power of two?
+ * @param x value to check
+ * @return true if @p x is a power of two, false otherwise
+ */
+static inline bool is_power_of_two(unsigned int x)
+{
+	return (x != 0U) && ((x & (x - 1U)) == 0U);
+}
+
+/**
+ * @brief Arithmetic shift right
+ * @param value value to shift
+ * @param shift number of bits to shift
+ * @return @p value shifted right by @p shift; opened bit positions are
+ *         filled with the sign bit
+ */
+static inline int64_t arithmetic_shift_right(int64_t value, uint8_t shift)
+{
+	int64_t sign_ext;
+
+	if (shift == 0U) {
+		return value;
+	}
+
+	/* extract sign bit */
+	sign_ext = (value >> 63) & 1;
+
+	/* make all bits of sign_ext be the same as the value's sign bit */
+	sign_ext = -sign_ext;
+
+	/* shift value and fill opened bit positions with sign bit */
+	return (value >> shift) | (sign_ext << (64 - shift));
+}
+
+/**
+ * @brief      Convert a single character into a hexadecimal nibble.
+ *
+ * @param c     The character to convert
+ * @param x     The address of storage for the converted number.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int char2hex(char c, uint8_t *x);
+
+/**
+ * @brief      Convert a single hexadecimal nibble into a character.
+ *
+ * @param c     The number to convert
+ * @param x     The address of storage for the converted character.
+ *
+ *  @return Zero on success or (negative) error code otherwise.
+ */
+int hex2char(uint8_t x, char *c);
+
+/**
+ * @brief      Convert a binary array into string representation.
+ *
+ * @param buf     The binary array to convert
+ * @param buflen  The length of the binary array to convert
+ * @param hex     Address of where to store the string representation.
+ * @param hexlen  Size of the storage area for string representation.
+ *
+ * @return     The length of the converted string, or 0 if an error occurred.
+ */
+size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen);
+
+/**
+ * @brief      Convert a hexadecimal string into a binary array.
+ *
+ * @param hex     The hexadecimal string to convert
+ * @param hexlen  The length of the hexadecimal string to convert.
+ * @param buf     Address of where to store the binary data
+ * @param buflen  Size of the storage area for binary data
+ *
+ * @return     The length of the binary array, or 0 if an error occurred.
+ */
+size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen);
+
+/**
+ * @brief      Convert a uint8_t into a decimal string representation.
+ *
+ * Convert a uint8_t value into its ASCII decimal string representation.
+ * The string is terminated if there is enough space in buf.
+ *
+ * @param buf     Address of where to store the string representation.
+ * @param buflen  Size of the storage area for string representation.
+ * @param value   The value to convert to decimal string
+ *
+ * @return     The length of the converted string (excluding terminator if
+ *             any), or 0 if an error occurred.
+ */
+uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value);
+
+#endif /* !_ASMLANGUAGE */
+
+/** @brief Number of bytes in @p x kibibytes */
+#ifdef _LINKER
+/* This is used in linker scripts so need to avoid type casting there */
+#define KB(x) ((x) << 10)
+#else
+#define KB(x) (((size_t)x) << 10)
+#endif
+/** @brief Number of bytes in @p x mebibytes */
+#define MB(x) (KB(x) << 10)
+/** @brief Number of bytes in @p x gibibytes */
+#define GB(x) (MB(x) << 10)
+
+/** @brief Number of Hz in @p x kHz */
+#define KHZ(x) ((x) * 1000)
+/** @brief Number of Hz in @p x MHz */
+#define MHZ(x) (KHZ(x) * 1000)
+
+#ifndef BIT
+#if defined(_ASMLANGUAGE)
+#define BIT(n)  (1 << (n))
+#else
+/**
+ * @brief Unsigned integer with bit position @p n set (signed in
+ * assembly language).
+ */
+#define BIT(n)  (1UL << (n))
+#endif
+#endif
+
+/** @brief 64-bit unsigned integer with bit position @p _n set. */
+#define BIT64(_n) (1ULL << (_n))
+
+/**
+ * @brief Set or clear a bit depending on a boolean value
+ *
+ * The argument @p var is a variable whose value is written to as a
+ * side effect.
+ *
+ * @param var Variable to be altered
+ * @param bit Bit number
+ * @param set if 0, clears @p bit in @p var; any other value sets @p bit
+ */
+#define WRITE_BIT(var, bit, set) \
+	((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit)))
+
+/**
+ * @brief Bit mask with bits 0 through <tt>n-1</tt> (inclusive) set,
+ * or 0 if @p n is 0.
+ */
+#define BIT_MASK(n) (BIT(n) - 1)
+
+/* IS_ENABLED() helpers */
+
+/* This is called from IS_ENABLED(), and sticks on a "_XXXX" prefix,
+ * it will now be "_XXXX1" if config_macro is "1", or just "_XXXX" if it's
+ * undefined.
+ *   ENABLED:   Z_IS_ENABLED2(_XXXX1)
+ *   DISABLED   Z_IS_ENABLED2(_XXXX)
+ */
+#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro)
+
+/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
+ * with a trailing comma), so it has the effect of making this a
+ * two-argument tuple to the preprocessor only in the case where the
+ * value is defined to "1"
+ *   ENABLED:    _YYYY,    <--- note comma!
+ *   DISABLED:   _XXXX
+ */
+#define _XXXX1 _YYYY,
+
+/* Then we append an extra argument to fool the gcc preprocessor into
+ * accepting it as a varargs macro.
+ *                         arg1   arg2  arg3
+ *   ENABLED:   Z_IS_ENABLED3(_YYYY,    1,    0)
+ *   DISABLED   Z_IS_ENABLED3(_XXXX 1,  0)
+ */
+#define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args 1, 0)
+
+/* And our second argument is thus now cooked to be 1 in the case
+ * where the value is defined to 1, and 0 if not:
+ */
+#define Z_IS_ENABLED3(ignore_this, val, ...) val
+/**
+ * @brief Check for macro definition in compiler-visible expressions
+ *
+ * This trick was pioneered in Linux as the config_enabled() macro. It
+ * has the effect of taking a macro value that may be defined to "1"
+ * or may not be defined at all and turning it into a literal
+ * expression that can be handled by the C compiler instead of just
+ * the preprocessor. It is often used with a @p CONFIG_FOO macro which
+ * may be defined to 1 via Kconfig, or left undefined.
+ *
+ * That is, it works similarly to <tt>\#if defined(CONFIG_FOO)</tt>
+ * except that its expansion is a C expression. Thus, much <tt>\#ifdef</tt>
+ * usage can be replaced with equivalents like:
+ *
+ *     if (IS_ENABLED(CONFIG_FOO)) {
+ *             do_something_with_foo
+ *     }
+ *
+ * This is cleaner since the compiler can generate errors and warnings
+ * for @p do_something_with_foo even when @p CONFIG_FOO is undefined.
+ *
+ * @param config_macro Macro to check
+ * @return 1 if @p config_macro is defined to 1, 0 otherwise (including
+ *         if @p config_macro is not defined)
+ */
+//#define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro)
+#define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro)
+/* INTERNAL: the first pass above is just to expand any existing
+ * macros, we need the macro value to be e.g. a literal "1" at
+ * expansion time in the next macro, not "(1)", etc... Standard
+ * recursive expansion does not work.
+ */
+
+/**
+ * @brief Insert code depending on whether @p _flag expands to 1 or not.
+ *
+ * This relies on similar tricks as IS_ENABLED(), but as the result of
+ * @p _flag expansion, results in either @p _if_1_code or @p
+ * _else_code is expanded.
+ *
+ * To prevent the preprocessor from treating commas as argument
+ * separators, the @p _if_1_code and @p _else_code expressions must be
+ * inside brackets/parentheses: <tt>()</tt>. These are stripped away
+ * during macro expansion.
+ *
+ * Example:
+ *
+ *     COND_CODE_1(CONFIG_FLAG, (uint32_t x;), (there_is_no_flag();))
+ *
+ * If @p CONFIG_FLAG is defined to 1, this expands to:
+ *
+ *     uint32_t x;
+ *
+ * It expands to <tt>there_is_no_flag();</tt> otherwise.
+ *
+ * This could be used as an alternative to:
+ *
+ *     #if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1)
+ *     #define MAYBE_DECLARE(x) uint32_t x
+ *     #else
+ *     #define MAYBE_DECLARE(x) there_is_no_flag()
+ *     #endif
+ *
+ *     MAYBE_DECLARE(x);
+ *
+ * However, the advantage of COND_CODE_1() is that code is resolved in
+ * place where it is used, while the @p \#if method defines @p
+ * MAYBE_DECLARE on two lines and requires it to be invoked again on a
+ * separate line. This makes COND_CODE_1() more concise and also
+ * sometimes more useful when used within another macro's expansion.
+ *
+ * @note @p _flag can be the result of preprocessor expansion, e.g.
+ *	 an expression involving <tt>NUM_VA_ARGS_LESS_1(...)</tt>.
+ *	 However, @p _if_1_code is only expanded if @p _flag expands
+ *	 to the integer literal 1. Integer expressions that evaluate
+ *	 to 1, e.g. after doing some arithmetic, will not work.
+ *
+ * @param _flag evaluated flag
+ * @param _if_1_code result if @p _flag expands to 1; must be in parentheses
+ * @param _else_code result otherwise; must be in parentheses
+ */
+#define COND_CODE_1(_flag, _if_1_code, _else_code) \
+	Z_COND_CODE_1(_flag, _if_1_code, _else_code)
+
+/**
+ * @brief Like COND_CODE_1() except tests if @p _flag is 0.
+ *
+ * This is like COND_CODE_1(), except that it tests whether @p _flag
+ * expands to the integer literal 0. It expands to @p _if_0_code if
+ * so, and @p _else_code otherwise; both of these must be enclosed in
+ * parentheses.
+ *
+ * @param _flag evaluated flag
+ * @param _if_0_code result if @p _flag expands to 0; must be in parentheses
+ * @param _else_code result otherwise; must be in parentheses
+ * @see COND_CODE_1()
+ */
+#define COND_CODE_0(_flag, _if_0_code, _else_code) \
+	Z_COND_CODE_0(_flag, _if_0_code, _else_code)
+
+/**
+ * @brief Insert code if @p _flag is defined and equals 1.
+ *
+ * Like COND_CODE_1(), this expands to @p _code if @p _flag is defined to 1;
+ * it expands to nothing otherwise.
+ *
+ * Example:
+ *
+ *     IF_ENABLED(CONFIG_FLAG, (uint32_t foo;))
+ *
+ * If @p CONFIG_FLAG is defined to 1, this expands to:
+ *
+ *     uint32_t foo;
+ *
+ * and to nothing otherwise.
+ *
+ * It can be considered as a more compact alternative to:
+ *
+ *     #if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1)
+ *     uint32_t foo;
+ *     #endif
+ *
+ * @param _flag evaluated flag
+ * @param _code result if @p _flag expands to 1; must be in parentheses
+ */
+#define IF_ENABLED(_flag, _code) \
+	COND_CODE_1(_flag, _code, ())
+
+/**
+ * @brief Check if a macro has a replacement expression
+ *
+ * If @p a is a macro defined to a nonempty value, this will return
+ * true, otherwise it will return false. It only works with defined
+ * macros, so an additional @p \#ifdef test may be needed in some cases.
+ *
+ * This macro may be used with COND_CODE_1() and COND_CODE_0() while
+ * processing <tt>__VA_ARGS__</tt> to avoid processing empty arguments.
+ *
+ * Note that this macro is intended to check macro names that evaluate
+ * to replacement lists being empty or containing numbers or macro name
+ * like tokens.
+ *
+ * @note Not all arguments are accepted by this macro and compilation will fail
+ *	 if argument cannot be concatenated with literal constant. That will
+ *	 happen if argument does not start with letter or number. Example
+ *	 arguments that will fail during compilation: .arg, (arg), "arg", {arg}.
+ *
+ * Example:
+ *
+ *	#define EMPTY
+ *	#define NON_EMPTY	1
+ *	#undef  UNDEFINED
+ *	IS_EMPTY(EMPTY)
+ *	IS_EMPTY(NON_EMPTY)
+ *	IS_EMPTY(UNDEFINED)
+ *	#if defined(EMPTY) && IS_EMPTY(EMPTY) == true
+ *	some_conditional_code
+ *	#endif
+ *
+ * In above examples, the invocations of IS_EMPTY(...) return @p true,
+ * @p false, and @p true; @p some_conditional_code is included.
+ *
+ * @param a macro to check for emptiness
+ */
+#define IS_EMPTY(a) Z_IS_EMPTY_(a, 1, 0,)
+
+/**
+ * @brief Remove empty arguments from list.
+ *
+ * During macro expansion, <tt>__VA_ARGS__</tt> and other preprocessor
+ * generated lists may contain empty elements, e.g.:
+ *
+ *	#define LIST ,a,b,,d,
+ *
+ * Using EMPTY to show each empty element, LIST contains:
+ *
+ *      EMPTY, a, b, EMPTY, d
+ *
+ * When processing such lists, e.g. using FOR_EACH(), all empty elements
+ * will be processed, and may require filtering out.
+ * To make that process easier, it is enough to invoke LIST_DROP_EMPTY
+ * which will remove all empty elements.
+ *
+ * Example:
+ *
+ *	LIST_DROP_EMPTY(LIST)
+ *
+ * expands to:
+ *
+ *	a, b, d
+ *
+ * @param ... list to be processed
+ */
+#define LIST_DROP_EMPTY(...) \
+	Z_LIST_DROP_FIRST(FOR_EACH(Z_LIST_NO_EMPTIES, (), __VA_ARGS__))
+
+/**
+ * @brief Macro with an empty expansion
+ *
+ * This trivial definition is provided for readability when a macro
+ * should expand to an empty result, which e.g. is sometimes needed to
+ * silence checkpatch.
+ *
+ * Example:
+ *
+ *	#define LIST_ITEM(n) , item##n
+ *
+ * The above would cause checkpatch to complain, but:
+ *
+ *	#define LIST_ITEM(n) EMPTY, item##n
+ *
+ * would not.
+ */
+#define EMPTY
+
+/**
+ * @brief Macro that expands to its argument
+ *
+ * This is useful in macros like @c FOR_EACH() when there is no
+ * transformation required on the list elements.
+ *
+ * @param V any value
+ */
+#define IDENTITY(V) V
+
+/**
+ * @brief Get nth argument from argument list.
+ *
+ * @param N Argument index to fetch. Counter from 1.
+ * @param ... Variable list of argments from which one argument is returned.
+ *
+ * @return Nth argument.
+ */
+#define GET_ARG_N(N, ...) _Z_GET_ARG_N(N, 1, __VA_ARGS__)
+
+/**
+ * @brief Strips n first arguments from the argument list.
+ *
+ * @param N Number of arguments to discard.
+ * @param ... Variable list of argments.
+ *
+ * @return argument list without N first arguments.
+ */
+#define GET_ARGS_LESS_N(N, ...) _Z_GET_ARG_N(UTIL_INC(N), 0, __VA_ARGS__)
+
+/** Expands to the first argument.
+ *
+ * @deprecated Use GET_ARG_N instead.
+ */
+#define GET_ARG1(...) GET_ARG_N(1, __VA_ARGS__)
+
+/** Expands to the second argument.
+ *
+ * @deprecated Use GET_ARG_N instead.
+ */
+#define GET_ARG2(...) __DEPRECATED GET_ARG_N(2, __VA_ARGS__)
+
+/** Expands to all arguments except the first one.
+ *
+ * @deprecated Use GET_ARGS_LESS_N instead.
+ */
+#define GET_ARGS_LESS_1(...) __DEPRECATED GET_ARGS_LESS_N(1, __VA_ARGS__)
+
+/**
+ * @brief Like <tt>a || b</tt>, but does evaluation and
+ * short-circuiting at C preprocessor time.
+ *
+ * This is not the same as the binary @p || operator; in particular,
+ * @p a should expand to an integer literal 0 or 1. However, @p b
+ * can be any value.
+ *
+ * This can be useful when @p b is an expression that would cause a
+ * build error when @p a is 1.
+ */
+#define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
+
+/**
+ * @brief Like <tt>a && b</tt>, but does evaluation and
+ * short-circuiting at C preprocessor time.
+ *
+ * This is not the same as the binary @p &&, however; in particular,
+ * @p a should expand to an integer literal 0 or 1. However, @p b
+ * can be any value.
+ *
+ * This can be useful when @p b is an expression that would cause a
+ * build error when @p a is 0.
+ */
+#define UTIL_AND(a, b) COND_CODE_1(UTIL_BOOL(a), (b), (0))
+
+/**
+ * @brief Generates a sequence of code.
+ *
+ * Example:
+ *
+ *     #define FOO(i, _) MY_PWM ## i ,
+ *     { UTIL_LISTIFY(PWM_COUNT, FOO) }
+ *
+ * The above two lines expand to:
+ *
+ *    { MY_PWM0 , MY_PWM1 , }
+ *
+ * @param LEN The length of the sequence. Must be an integer literal less
+ *            than 255.
+ * @param F A macro function that accepts at least two arguments:
+ *          <tt>F(i, ...)</tt>. @p F is called repeatedly in the expansion.
+ *          Its first argument @p i is the index in the sequence, and
+ *          the variable list of arguments passed to UTIL_LISTIFY are passed
+ *          through to @p F.
+ *
+ * @note Calling UTIL_LISTIFY with undefined arguments has undefined
+ * behavior.
+ */
+#define UTIL_LISTIFY(LEN, F, ...) UTIL_EVAL(UTIL_REPEAT(LEN, F, __VA_ARGS__))
+
+/**
+ * @brief Call a macro @p F on each provided argument with a given
+ *        separator between each call.
+ *
+ * Example:
+ *
+ *     #define F(x) int a##x
+ *     FOR_EACH(F, (;), 4, 5, 6);
+ *
+ * This expands to:
+ *
+ *     int a4;
+ *     int a5;
+ *     int a6;
+ *
+ * @param F Macro to invoke
+ * @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
+ *            this is required to enable providing a comma as separator.
+ * @param ... Variable argument list. The macro @p F is invoked as
+ *            <tt>F(element)</tt> for each element in the list.
+ */
+#define FOR_EACH(F, sep, ...) \
+	Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
+			0, Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG, sep, \
+			F, 0, __VA_ARGS__)
+
+/**
+ * @brief Like FOR_EACH(), but with a terminator instead of a separator,
+ *        and drops empty elements from the argument list
+ *
+ * The @p sep argument to <tt>FOR_EACH(F, (sep), a, b)</tt> is a
+ * separator which is placed between calls to @p F, like this:
+ *
+ *     FOR_EACH(F, (sep), a, b) // F(a) sep F(b)
+ *                              //               ^^^ no sep here!
+ *
+ * By contrast, the @p term argument to <tt>FOR_EACH_NONEMPTY_TERM(F, (term),
+ * a, b)</tt> is added after each time @p F appears in the expansion:
+ *
+ *     FOR_EACH_NONEMPTY_TERM(F, (term), a, b) // F(a) term F(b) term
+ *                                             //                ^^^^
+ *
+ * Further, any empty elements are dropped:
+ *
+ *     FOR_EACH_NONEMPTY_TERM(F, (term), a, EMPTY, b) // F(a) term F(b) term
+ *
+ * This is more convenient in some cases, because FOR_EACH_NONEMPTY_TERM()
+ * expands to nothing when given an empty argument list, and it's
+ * often cumbersome to write a macro @p F that does the right thing
+ * even when given an empty argument.
+ *
+ * One example is when <tt>__VA_ARGS__</tt> may or may not be empty,
+ * and the results are embedded in a larger initializer:
+ *
+ *     #define SQUARE(x) ((x)*(x))
+ *
+ *     int my_array[] = {
+ *             FOR_EACH_NONEMPTY_TERM(SQUARE, (,), FOO(...))
+ *             FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAR(...))
+ *             FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAZ(...))
+ *     };
+ *
+ * This is more convenient than:
+ *
+ * 1. figuring out whether the @p FOO, @p BAR, and @p BAZ expansions
+ *    are empty and adding a comma manually (or not) between FOR_EACH()
+ *    calls
+ * 2. rewriting SQUARE so it reacts appropriately when "x" is empty
+ *    (which would be necessary if e.g. @p FOO expands to nothing)
+ *
+ * @param F Macro to invoke on each nonempty element of the variable
+ *          arguments
+ * @param term Terminator (e.g. comma or semicolon) placed after each
+ *             invocation of F. Must be in parentheses; this is required
+ *             to enable providing a comma as separator.
+ * @param ... Variable argument list. The macro @p F is invoked as
+ *            <tt>F(element)</tt> for each nonempty element in the list.
+ */
+#define FOR_EACH_NONEMPTY_TERM(F, term, ...)				\
+	COND_CODE_0(							\
+		/* are there zero non-empty arguments ? */		\
+		NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)),	\
+		/* if so, expand to nothing */				\
+		(),							\
+		/* otherwise, expand to: */				\
+		(/* FOR_EACH() on nonempty elements, */		\
+			FOR_EACH(F, term, LIST_DROP_EMPTY(__VA_ARGS__))	\
+			/* plus a final terminator */			\
+			__DEBRACKET term				\
+		))
+
+/**
+ * @brief Call macro @p F on each provided argument, with the argument's index
+ *        as an additional parameter.
+ *
+ * This is like FOR_EACH(), except @p F should be a macro which takes two
+ * arguments: <tt>F(index, variable_arg)</tt>.
+ *
+ * Example:
+ *
+ *     #define F(idx, x) int a##idx = x
+ *     FOR_EACH_IDX(F, (;), 4, 5, 6);
+ *
+ * This expands to:
+ *
+ *     int a0 = 4;
+ *     int a1 = 5;
+ *     int a2 = 6;
+ *
+ * @param F Macro to invoke
+ * @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
+ *            this is required to enable providing a comma as separator.
+ * @param ... Variable argument list. The macro @p F is invoked as
+ *            <tt>F(index, element)</tt> for each element in the list.
+ */
+#define FOR_EACH_IDX(F, sep, ...) \
+	Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
+			0, Z_FOR_EACH_SWALLOW_FIXED_ARG, sep, \
+			F, 0, __VA_ARGS__)
+
+/**
+ * @brief Call macro @p F on each provided argument, with an additional fixed
+ *	  argument as a parameter.
+ *
+ * This is like FOR_EACH(), except @p F should be a macro which takes two
+ * arguments: <tt>F(variable_arg, fixed_arg)</tt>.
+ *
+ * Example:
+ *
+ *     static void func(int val, void *dev);
+ *     FOR_EACH_FIXED_ARG(func, (;), dev, 4, 5, 6);
+ *
+ * This expands to:
+ *
+ *     func(4, dev);
+ *     func(5, dev);
+ *     func(6, dev);
+ *
+ * @param F Macro to invoke
+ * @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
+ *            this is required to enable providing a comma as separator.
+ * @param fixed_arg Fixed argument passed to @p F as the second macro parameter.
+ * @param ... Variable argument list. The macro @p F is invoked as
+ *            <tt>F(element, fixed_arg)</tt> for each element in the list.
+ */
+#define FOR_EACH_FIXED_ARG(F, sep, fixed_arg, ...) \
+	Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
+			0, Z_FOR_EACH_SWALLOW_INDEX, sep, \
+			F, fixed_arg, __VA_ARGS__)
+
+/**
+ * @brief Calls macro @p F for each variable argument with an index and fixed
+ *        argument
+ *
+ * This is like the combination of FOR_EACH_IDX() with FOR_EACH_FIXED_ARG().
+ *
+ * Example:
+ *
+ *     #define F(idx, x, fixed_arg) int fixed_arg##idx = x
+ *     FOR_EACH_IDX_FIXED_ARG(F, (;), a, 4, 5, 6);
+ *
+ * This expands to:
+ *
+ *     int a0 = 4;
+ *     int a1 = 5;
+ *     int a2 = 6;
+ *
+ * @param F Macro to invoke
+ * @param sep Separator (e.g. comma or semicolon). Must be in parentheses;
+ *            This is required to enable providing a comma as separator.
+ * @param fixed_arg Fixed argument passed to @p F as the third macro parameter.
+ * @param ... Variable list of arguments. The macro @p F is invoked as
+ *            <tt>F(index, element, fixed_arg)</tt> for each element in
+ *            the list.
+ */
+#define FOR_EACH_IDX_FIXED_ARG(F, sep, fixed_arg, ...) \
+	Z_FOR_EACH_IDX2(NUM_VA_ARGS_LESS_1(__VA_ARGS__, _), \
+			0, Z_FOR_EACH_SWALLOW_NOTHING, sep, \
+			F, fixed_arg, __VA_ARGS__)
+
+/**
+ * @brief Number of arguments in the variable arguments list minus one.
+ *
+ * @param ... List of arguments
+ * @return  Number of variadic arguments in the argument list, minus one
+ */
+#define NUM_VA_ARGS_LESS_1(...) \
+	NUM_VA_ARGS_LESS_1_IMPL(__VA_ARGS__, 63, 62, 61, \
+	60, 59, 58, 57, 56, 55, 54, 53, 52, 51,		 \
+	50, 49, 48, 47, 46, 45, 44, 43, 42, 41,		 \
+	40, 39, 38, 37, 36, 35, 34, 33, 32, 31,		 \
+	30, 29, 28, 27, 26, 25, 24, 23, 22, 21,		 \
+	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,		 \
+	10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~)
+
+/**
+ * @brief Mapping macro that pastes results together
+ *
+ * This is similar to FOR_EACH() in that it invokes a macro repeatedly
+ * on each element of <tt>__VA_ARGS__</tt>. However, unlike FOR_EACH(),
+ * MACRO_MAP_CAT() pastes the results together into a single token.
+ *
+ * For example, with this macro FOO:
+ *
+ *     #define FOO(x) item_##x##_
+ *
+ * <tt>MACRO_MAP_CAT(FOO, a, b, c),</tt> expands to the token:
+ *
+ *     item_a_item_b_item_c_
+ *
+ * @param ... Macro to expand on each argument, followed by its
+ *            arguments. (The macro should take exactly one argument.)
+ * @return The results of expanding the macro on each argument, all pasted
+ *         together
+ */
+#define MACRO_MAP_CAT(...) MACRO_MAP_CAT_(__VA_ARGS__)
+
+/**
+ * @brief Mapping macro that pastes a fixed number of results together
+ *
+ * Similar to @ref MACRO_MAP_CAT(), but expects a fixed number of
+ * arguments. If more arguments are given than are expected, the rest
+ * are ignored.
+ *
+ * @param N   Number of arguments to map
+ * @param ... Macro to expand on each argument, followed by its
+ *            arguments. (The macro should take exactly one argument.)
+ * @return The results of expanding the macro on each argument, all pasted
+ *         together
+ */
+#define MACRO_MAP_CAT_N(N, ...) MACRO_MAP_CAT_N_(N, __VA_ARGS__)
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_SYS_UTIL_H_ */
Index: ModuleDemo/BLE/CM0/User/include/sys/util_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/util_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/sys/util_internal.h	(working copy)
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2011-2014, Wind River Systems, Inc.
+ * Copyright (c) 2020, Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Misc utilities
+ *
+ * Repetitive or obscure helper macros needed by sys/util.h.
+ */
+
+#ifndef ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
+#define ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_
+
+/* IS_ENABLED() helpers */
+
+/* This is called from IS_ENABLED(), and sticks on a "_XXXX" prefix,
+ * it will now be "_XXXX1" if config_macro is "1", or just "_XXXX" if it's
+ * undefined.
+ *   ENABLED:   Z_IS_ENABLED2(_XXXX1)
+ *   DISABLED   Z_IS_ENABLED2(_XXXX)
+ */
+#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro)
+
+/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
+ * with a trailing comma), so it has the effect of making this a
+ * two-argument tuple to the preprocessor only in the case where the
+ * value is defined to "1"
+ *   ENABLED:    _YYYY,    <--- note comma!
+ *   DISABLED:   _XXXX
+ */
+#define _XXXX1 _YYYY,
+
+/* Then we append an extra argument to fool the gcc preprocessor into
+ * accepting it as a varargs macro.
+ *                         arg1   arg2  arg3
+ *   ENABLED:   Z_IS_ENABLED3(_YYYY,    1,    0)
+ *   DISABLED   Z_IS_ENABLED3(_XXXX 1,  0)
+ */
+#define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args 1, 0)
+
+/* And our second argument is thus now cooked to be 1 in the case
+ * where the value is defined to 1, and 0 if not:
+ */
+#define Z_IS_ENABLED3(ignore_this, val, ...) val
+
+/* Used internally by COND_CODE_1 and COND_CODE_0. */
+#define Z_COND_CODE_1(_flag, _if_1_code, _else_code) \
+	__COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
+#define Z_COND_CODE_0(_flag, _if_0_code, _else_code) \
+	__COND_CODE(_ZZZZ##_flag, _if_0_code, _else_code)
+#define _ZZZZ0 _YYYY,
+#define __COND_CODE(one_or_two_args, _if_code, _else_code) \
+	__GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
+
+/* Gets second argument and removes brackets around that argument. It
+ * is expected that the parameter is provided in brackets/parentheses.
+ */
+#define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
+
+/* Used to remove brackets from around a single argument. */
+#define __DEBRACKET(...) __VA_ARGS__
+
+/* Used by IS_EMPTY() */
+#define Z_IS_EMPTY_(...) Z_IS_EMPTY__(__VA_ARGS__)
+#define Z_IS_EMPTY__(a, ...) Z_IS_EMPTY___(_ZZ##a##ZZ0, __VA_ARGS__)
+#define Z_IS_EMPTY___(...) GET_ARG_N(3, __VA_ARGS__)
+
+/* Used by LIST_DROP_EMPTY() */
+/* Adding ',' after each element would add empty element at the end of
+ * list, which is hard to remove, so instead precede each element with ',',
+ * this way first element is empty, and this one is easy to drop.
+ */
+#define Z_LIST_ADD_ELEM(e) EMPTY, e
+#define Z_LIST_DROP_FIRST(...) GET_ARGS_LESS_N(1, __VA_ARGS__)
+#define Z_LIST_NO_EMPTIES(e) \
+	COND_CODE_1(IS_EMPTY(e), (), (Z_LIST_ADD_ELEM(e)))
+
+/*
+ * Macros for doing code-generation with the preprocessor as if we
+ * could do recursive macro expansion.
+ *
+ * Generally it is better to generate code with the preprocessor than
+ * to copy-paste code or to generate code with the build system /
+ * python script's etc.
+ *
+ * http://stackoverflow.com/a/12540675
+ */
+
+#define UTIL_EMPTY(...)
+#define UTIL_DEFER(...) __VA_ARGS__ UTIL_EMPTY()
+#define UTIL_OBSTRUCT(...) __VA_ARGS__ UTIL_DEFER(UTIL_EMPTY)()
+#define UTIL_EXPAND(...) __VA_ARGS__
+
+#define UTIL_EVAL(...)  UTIL_EVAL1(UTIL_EVAL1(UTIL_EVAL1(__VA_ARGS__)))
+#define UTIL_EVAL1(...) UTIL_EVAL2(UTIL_EVAL2(UTIL_EVAL2(__VA_ARGS__)))
+#define UTIL_EVAL2(...) UTIL_EVAL3(UTIL_EVAL3(UTIL_EVAL3(__VA_ARGS__)))
+#define UTIL_EVAL3(...) UTIL_EVAL4(UTIL_EVAL4(UTIL_EVAL4(__VA_ARGS__)))
+#define UTIL_EVAL4(...) UTIL_EVAL5(UTIL_EVAL5(UTIL_EVAL5(__VA_ARGS__)))
+#define UTIL_EVAL5(...) __VA_ARGS__
+
+#define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
+#define UTIL_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__
+
+/*
+ * UTIL_INC(x) for an integer literal x from 0 to 255 expands to an
+ * integer literal whose value is x+1.
+ *
+ * Similarly, UTIL_DEC(x) is (x-1) as an integer literal.
+ */
+#define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x)
+#define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x)
+
+#define UTIL_INC_0 1
+#define UTIL_INC_1 2
+#define UTIL_INC_2 3
+#define UTIL_INC_3 4
+#define UTIL_INC_4 5
+#define UTIL_INC_5 6
+#define UTIL_INC_6 7
+#define UTIL_INC_7 8
+#define UTIL_INC_8 9
+#define UTIL_INC_9 10
+#define UTIL_INC_10 11
+#define UTIL_INC_11 12
+#define UTIL_INC_12 13
+#define UTIL_INC_13 14
+#define UTIL_INC_14 15
+#define UTIL_INC_15 16
+#define UTIL_INC_16 17
+#define UTIL_INC_17 18
+#define UTIL_INC_18 19
+#define UTIL_INC_19 20
+#define UTIL_INC_20 21
+#define UTIL_INC_21 22
+#define UTIL_INC_22 23
+#define UTIL_INC_23 24
+#define UTIL_INC_24 25
+#define UTIL_INC_25 26
+#define UTIL_INC_26 27
+#define UTIL_INC_27 28
+#define UTIL_INC_28 29
+#define UTIL_INC_29 30
+#define UTIL_INC_30 31
+#define UTIL_INC_31 32
+#define UTIL_INC_32 33
+#define UTIL_INC_33 34
+#define UTIL_INC_34 35
+#define UTIL_INC_35 36
+#define UTIL_INC_36 37
+#define UTIL_INC_37 38
+#define UTIL_INC_38 39
+#define UTIL_INC_39 40
+#define UTIL_INC_40 41
+#define UTIL_INC_41 42
+#define UTIL_INC_42 43
+#define UTIL_INC_43 44
+#define UTIL_INC_44 45
+#define UTIL_INC_45 46
+#define UTIL_INC_46 47
+#define UTIL_INC_47 48
+#define UTIL_INC_48 49
+#define UTIL_INC_49 50
+#define UTIL_INC_50 51
+#define UTIL_INC_51 52
+#define UTIL_INC_52 53
+#define UTIL_INC_53 54
+#define UTIL_INC_54 55
+#define UTIL_INC_55 56
+#define UTIL_INC_56 57
+#define UTIL_INC_57 58
+#define UTIL_INC_58 59
+#define UTIL_INC_59 60
+#define UTIL_INC_50 51
+#define UTIL_INC_51 52
+#define UTIL_INC_52 53
+#define UTIL_INC_53 54
+#define UTIL_INC_54 55
+#define UTIL_INC_55 56
+#define UTIL_INC_56 57
+#define UTIL_INC_57 58
+#define UTIL_INC_58 59
+#define UTIL_INC_59 60
+#define UTIL_INC_60 61
+#define UTIL_INC_61 62
+#define UTIL_INC_62 63
+#define UTIL_INC_63 64
+#define UTIL_INC_64 65
+#define UTIL_INC_65 66
+#define UTIL_INC_66 67
+#define UTIL_INC_67 68
+#define UTIL_INC_68 69
+#define UTIL_INC_69 70
+#define UTIL_INC_70 71
+#define UTIL_INC_71 72
+#define UTIL_INC_72 73
+#define UTIL_INC_73 74
+#define UTIL_INC_74 75
+#define UTIL_INC_75 76
+#define UTIL_INC_76 77
+#define UTIL_INC_77 78
+#define UTIL_INC_78 79
+#define UTIL_INC_79 80
+#define UTIL_INC_80 81
+#define UTIL_INC_81 82
+#define UTIL_INC_82 83
+#define UTIL_INC_83 84
+#define UTIL_INC_84 85
+#define UTIL_INC_85 86
+#define UTIL_INC_86 87
+#define UTIL_INC_87 88
+#define UTIL_INC_88 89
+#define UTIL_INC_89 90
+#define UTIL_INC_90 91
+#define UTIL_INC_91 92
+#define UTIL_INC_92 93
+#define UTIL_INC_93 94
+#define UTIL_INC_94 95
+#define UTIL_INC_95 96
+#define UTIL_INC_96 97
+#define UTIL_INC_97 98
+#define UTIL_INC_98 99
+#define UTIL_INC_99 100
+#define UTIL_INC_100 101
+#define UTIL_INC_101 102
+#define UTIL_INC_102 103
+#define UTIL_INC_103 104
+#define UTIL_INC_104 105
+#define UTIL_INC_105 106
+#define UTIL_INC_106 107
+#define UTIL_INC_107 108
+#define UTIL_INC_108 109
+#define UTIL_INC_109 110
+#define UTIL_INC_110 111
+#define UTIL_INC_111 112
+#define UTIL_INC_112 113
+#define UTIL_INC_113 114
+#define UTIL_INC_114 115
+#define UTIL_INC_115 116
+#define UTIL_INC_116 117
+#define UTIL_INC_117 118
+#define UTIL_INC_118 119
+#define UTIL_INC_119 120
+#define UTIL_INC_120 121
+#define UTIL_INC_121 122
+#define UTIL_INC_122 123
+#define UTIL_INC_123 124
+#define UTIL_INC_124 125
+#define UTIL_INC_125 126
+#define UTIL_INC_126 127
+#define UTIL_INC_127 128
+#define UTIL_INC_128 129
+#define UTIL_INC_129 130
+#define UTIL_INC_130 131
+#define UTIL_INC_131 132
+#define UTIL_INC_132 133
+#define UTIL_INC_133 134
+#define UTIL_INC_134 135
+#define UTIL_INC_135 136
+#define UTIL_INC_136 137
+#define UTIL_INC_137 138
+#define UTIL_INC_138 139
+#define UTIL_INC_139 140
+#define UTIL_INC_140 141
+#define UTIL_INC_141 142
+#define UTIL_INC_142 143
+#define UTIL_INC_143 144
+#define UTIL_INC_144 145
+#define UTIL_INC_145 146
+#define UTIL_INC_146 147
+#define UTIL_INC_147 148
+#define UTIL_INC_148 149
+#define UTIL_INC_149 150
+#define UTIL_INC_150 151
+#define UTIL_INC_151 152
+#define UTIL_INC_152 153
+#define UTIL_INC_153 154
+#define UTIL_INC_154 155
+#define UTIL_INC_155 156
+#define UTIL_INC_156 157
+#define UTIL_INC_157 158
+#define UTIL_INC_158 159
+#define UTIL_INC_159 160
+#define UTIL_INC_160 161
+#define UTIL_INC_161 162
+#define UTIL_INC_162 163
+#define UTIL_INC_163 164
+#define UTIL_INC_164 165
+#define UTIL_INC_165 166
+#define UTIL_INC_166 167
+#define UTIL_INC_167 168
+#define UTIL_INC_168 169
+#define UTIL_INC_169 170
+#define UTIL_INC_170 171
+#define UTIL_INC_171 172
+#define UTIL_INC_172 173
+#define UTIL_INC_173 174
+#define UTIL_INC_174 175
+#define UTIL_INC_175 176
+#define UTIL_INC_176 177
+#define UTIL_INC_177 178
+#define UTIL_INC_178 179
+#define UTIL_INC_179 180
+#define UTIL_INC_180 181
+#define UTIL_INC_181 182
+#define UTIL_INC_182 183
+#define UTIL_INC_183 184
+#define UTIL_INC_184 185
+#define UTIL_INC_185 186
+#define UTIL_INC_186 187
+#define UTIL_INC_187 188
+#define UTIL_INC_188 189
+#define UTIL_INC_189 190
+#define UTIL_INC_190 191
+#define UTIL_INC_191 192
+#define UTIL_INC_192 193
+#define UTIL_INC_193 194
+#define UTIL_INC_194 195
+#define UTIL_INC_195 196
+#define UTIL_INC_196 197
+#define UTIL_INC_197 198
+#define UTIL_INC_198 199
+#define UTIL_INC_199 200
+#define UTIL_INC_200 201
+#define UTIL_INC_201 202
+#define UTIL_INC_202 203
+#define UTIL_INC_203 204
+#define UTIL_INC_204 205
+#define UTIL_INC_205 206
+#define UTIL_INC_206 207
+#define UTIL_INC_207 208
+#define UTIL_INC_208 209
+#define UTIL_INC_209 210
+#define UTIL_INC_210 211
+#define UTIL_INC_211 212
+#define UTIL_INC_212 213
+#define UTIL_INC_213 214
+#define UTIL_INC_214 215
+#define UTIL_INC_215 216
+#define UTIL_INC_216 217
+#define UTIL_INC_217 218
+#define UTIL_INC_218 219
+#define UTIL_INC_219 220
+#define UTIL_INC_220 221
+#define UTIL_INC_221 222
+#define UTIL_INC_222 223
+#define UTIL_INC_223 224
+#define UTIL_INC_224 225
+#define UTIL_INC_225 226
+#define UTIL_INC_226 227
+#define UTIL_INC_227 228
+#define UTIL_INC_228 229
+#define UTIL_INC_229 230
+#define UTIL_INC_230 231
+#define UTIL_INC_231 232
+#define UTIL_INC_232 233
+#define UTIL_INC_233 234
+#define UTIL_INC_234 235
+#define UTIL_INC_235 236
+#define UTIL_INC_236 237
+#define UTIL_INC_237 238
+#define UTIL_INC_238 239
+#define UTIL_INC_239 240
+#define UTIL_INC_240 241
+#define UTIL_INC_241 242
+#define UTIL_INC_242 243
+#define UTIL_INC_243 244
+#define UTIL_INC_244 245
+#define UTIL_INC_245 246
+#define UTIL_INC_246 247
+#define UTIL_INC_247 248
+#define UTIL_INC_248 249
+#define UTIL_INC_249 250
+#define UTIL_INC_250 251
+#define UTIL_INC_251 252
+#define UTIL_INC_252 253
+#define UTIL_INC_253 254
+#define UTIL_INC_254 255
+#define UTIL_INC_255 256
+#define UTIL_INC_256 257
+
+#define UTIL_DEC_0 0
+#define UTIL_DEC_1 0
+#define UTIL_DEC_2 1
+#define UTIL_DEC_3 2
+#define UTIL_DEC_4 3
+#define UTIL_DEC_5 4
+#define UTIL_DEC_6 5
+#define UTIL_DEC_7 6
+#define UTIL_DEC_8 7
+#define UTIL_DEC_9 8
+#define UTIL_DEC_10 9
+#define UTIL_DEC_11 10
+#define UTIL_DEC_12 11
+#define UTIL_DEC_13 12
+#define UTIL_DEC_14 13
+#define UTIL_DEC_15 14
+#define UTIL_DEC_16 15
+#define UTIL_DEC_17 16
+#define UTIL_DEC_18 17
+#define UTIL_DEC_19 18
+#define UTIL_DEC_20 19
+#define UTIL_DEC_21 20
+#define UTIL_DEC_22 21
+#define UTIL_DEC_23 22
+#define UTIL_DEC_24 23
+#define UTIL_DEC_25 24
+#define UTIL_DEC_26 25
+#define UTIL_DEC_27 26
+#define UTIL_DEC_28 27
+#define UTIL_DEC_29 28
+#define UTIL_DEC_30 29
+#define UTIL_DEC_31 30
+#define UTIL_DEC_32 31
+#define UTIL_DEC_33 32
+#define UTIL_DEC_34 33
+#define UTIL_DEC_35 34
+#define UTIL_DEC_36 35
+#define UTIL_DEC_37 36
+#define UTIL_DEC_38 37
+#define UTIL_DEC_39 38
+#define UTIL_DEC_40 39
+#define UTIL_DEC_41 40
+#define UTIL_DEC_42 41
+#define UTIL_DEC_43 42
+#define UTIL_DEC_44 43
+#define UTIL_DEC_45 44
+#define UTIL_DEC_46 45
+#define UTIL_DEC_47 46
+#define UTIL_DEC_48 47
+#define UTIL_DEC_49 48
+#define UTIL_DEC_50 49
+#define UTIL_DEC_51 50
+#define UTIL_DEC_52 51
+#define UTIL_DEC_53 52
+#define UTIL_DEC_54 53
+#define UTIL_DEC_55 54
+#define UTIL_DEC_56 55
+#define UTIL_DEC_57 56
+#define UTIL_DEC_58 57
+#define UTIL_DEC_59 58
+#define UTIL_DEC_60 59
+#define UTIL_DEC_61 60
+#define UTIL_DEC_62 61
+#define UTIL_DEC_63 62
+#define UTIL_DEC_64 63
+#define UTIL_DEC_65 64
+#define UTIL_DEC_66 65
+#define UTIL_DEC_67 66
+#define UTIL_DEC_68 67
+#define UTIL_DEC_69 68
+#define UTIL_DEC_70 69
+#define UTIL_DEC_71 70
+#define UTIL_DEC_72 71
+#define UTIL_DEC_73 72
+#define UTIL_DEC_74 73
+#define UTIL_DEC_75 74
+#define UTIL_DEC_76 75
+#define UTIL_DEC_77 76
+#define UTIL_DEC_78 77
+#define UTIL_DEC_79 78
+#define UTIL_DEC_80 79
+#define UTIL_DEC_81 80
+#define UTIL_DEC_82 81
+#define UTIL_DEC_83 82
+#define UTIL_DEC_84 83
+#define UTIL_DEC_85 84
+#define UTIL_DEC_86 85
+#define UTIL_DEC_87 86
+#define UTIL_DEC_88 87
+#define UTIL_DEC_89 88
+#define UTIL_DEC_90 89
+#define UTIL_DEC_91 90
+#define UTIL_DEC_92 91
+#define UTIL_DEC_93 92
+#define UTIL_DEC_94 93
+#define UTIL_DEC_95 94
+#define UTIL_DEC_96 95
+#define UTIL_DEC_97 96
+#define UTIL_DEC_98 97
+#define UTIL_DEC_99 98
+#define UTIL_DEC_100 99
+#define UTIL_DEC_101 100
+#define UTIL_DEC_102 101
+#define UTIL_DEC_103 102
+#define UTIL_DEC_104 103
+#define UTIL_DEC_105 104
+#define UTIL_DEC_106 105
+#define UTIL_DEC_107 106
+#define UTIL_DEC_108 107
+#define UTIL_DEC_109 108
+#define UTIL_DEC_110 109
+#define UTIL_DEC_111 110
+#define UTIL_DEC_112 111
+#define UTIL_DEC_113 112
+#define UTIL_DEC_114 113
+#define UTIL_DEC_115 114
+#define UTIL_DEC_116 115
+#define UTIL_DEC_117 116
+#define UTIL_DEC_118 117
+#define UTIL_DEC_119 118
+#define UTIL_DEC_120 119
+#define UTIL_DEC_121 120
+#define UTIL_DEC_122 121
+#define UTIL_DEC_123 122
+#define UTIL_DEC_124 123
+#define UTIL_DEC_125 124
+#define UTIL_DEC_126 125
+#define UTIL_DEC_127 126
+#define UTIL_DEC_128 127
+#define UTIL_DEC_129 128
+#define UTIL_DEC_130 129
+#define UTIL_DEC_131 130
+#define UTIL_DEC_132 131
+#define UTIL_DEC_133 132
+#define UTIL_DEC_134 133
+#define UTIL_DEC_135 134
+#define UTIL_DEC_136 135
+#define UTIL_DEC_137 136
+#define UTIL_DEC_138 137
+#define UTIL_DEC_139 138
+#define UTIL_DEC_140 139
+#define UTIL_DEC_141 140
+#define UTIL_DEC_142 141
+#define UTIL_DEC_143 142
+#define UTIL_DEC_144 143
+#define UTIL_DEC_145 144
+#define UTIL_DEC_146 145
+#define UTIL_DEC_147 146
+#define UTIL_DEC_148 147
+#define UTIL_DEC_149 148
+#define UTIL_DEC_150 149
+#define UTIL_DEC_151 150
+#define UTIL_DEC_152 151
+#define UTIL_DEC_153 152
+#define UTIL_DEC_154 153
+#define UTIL_DEC_155 154
+#define UTIL_DEC_156 155
+#define UTIL_DEC_157 156
+#define UTIL_DEC_158 157
+#define UTIL_DEC_159 158
+#define UTIL_DEC_160 159
+#define UTIL_DEC_161 160
+#define UTIL_DEC_162 161
+#define UTIL_DEC_163 162
+#define UTIL_DEC_164 163
+#define UTIL_DEC_165 164
+#define UTIL_DEC_166 165
+#define UTIL_DEC_167 166
+#define UTIL_DEC_168 167
+#define UTIL_DEC_169 168
+#define UTIL_DEC_170 169
+#define UTIL_DEC_171 170
+#define UTIL_DEC_172 171
+#define UTIL_DEC_173 172
+#define UTIL_DEC_174 173
+#define UTIL_DEC_175 174
+#define UTIL_DEC_176 175
+#define UTIL_DEC_177 176
+#define UTIL_DEC_178 177
+#define UTIL_DEC_179 178
+#define UTIL_DEC_180 179
+#define UTIL_DEC_181 180
+#define UTIL_DEC_182 181
+#define UTIL_DEC_183 182
+#define UTIL_DEC_184 183
+#define UTIL_DEC_185 184
+#define UTIL_DEC_186 185
+#define UTIL_DEC_187 186
+#define UTIL_DEC_188 187
+#define UTIL_DEC_189 188
+#define UTIL_DEC_190 189
+#define UTIL_DEC_191 190
+#define UTIL_DEC_192 191
+#define UTIL_DEC_193 192
+#define UTIL_DEC_194 193
+#define UTIL_DEC_195 194
+#define UTIL_DEC_196 195
+#define UTIL_DEC_197 196
+#define UTIL_DEC_198 197
+#define UTIL_DEC_199 198
+#define UTIL_DEC_200 199
+#define UTIL_DEC_201 200
+#define UTIL_DEC_202 201
+#define UTIL_DEC_203 202
+#define UTIL_DEC_204 203
+#define UTIL_DEC_205 204
+#define UTIL_DEC_206 205
+#define UTIL_DEC_207 206
+#define UTIL_DEC_208 207
+#define UTIL_DEC_209 208
+#define UTIL_DEC_210 209
+#define UTIL_DEC_211 210
+#define UTIL_DEC_212 211
+#define UTIL_DEC_213 212
+#define UTIL_DEC_214 213
+#define UTIL_DEC_215 214
+#define UTIL_DEC_216 215
+#define UTIL_DEC_217 216
+#define UTIL_DEC_218 217
+#define UTIL_DEC_219 218
+#define UTIL_DEC_220 219
+#define UTIL_DEC_221 220
+#define UTIL_DEC_222 221
+#define UTIL_DEC_223 222
+#define UTIL_DEC_224 223
+#define UTIL_DEC_225 224
+#define UTIL_DEC_226 225
+#define UTIL_DEC_227 226
+#define UTIL_DEC_228 227
+#define UTIL_DEC_229 228
+#define UTIL_DEC_230 229
+#define UTIL_DEC_231 230
+#define UTIL_DEC_232 231
+#define UTIL_DEC_233 232
+#define UTIL_DEC_234 233
+#define UTIL_DEC_235 234
+#define UTIL_DEC_236 235
+#define UTIL_DEC_237 236
+#define UTIL_DEC_238 237
+#define UTIL_DEC_239 238
+#define UTIL_DEC_240 239
+#define UTIL_DEC_241 240
+#define UTIL_DEC_242 241
+#define UTIL_DEC_243 242
+#define UTIL_DEC_244 243
+#define UTIL_DEC_245 244
+#define UTIL_DEC_246 245
+#define UTIL_DEC_247 246
+#define UTIL_DEC_248 247
+#define UTIL_DEC_249 248
+#define UTIL_DEC_250 249
+#define UTIL_DEC_251 250
+#define UTIL_DEC_252 251
+#define UTIL_DEC_253 252
+#define UTIL_DEC_254 253
+#define UTIL_DEC_255 254
+#define UTIL_DEC_256 255
+
+#define UTIL_CHECK_N(x, n, ...) n
+#define UTIL_CHECK(...) UTIL_CHECK_N(__VA_ARGS__, 0,)
+#define UTIL_NOT(x) UTIL_CHECK(UTIL_PRIMITIVE_CAT(UTIL_NOT_, x))
+#define UTIL_NOT_0 ~, 1,
+#define UTIL_COMPL(b) UTIL_PRIMITIVE_CAT(UTIL_COMPL_, b)
+#define UTIL_COMPL_0 1
+#define UTIL_COMPL_1 0
+#define UTIL_BOOL(x) UTIL_COMPL(UTIL_NOT(x))
+#define UTIL_IIF(c) UTIL_PRIMITIVE_CAT(UTIL_IIF_, c)
+#define UTIL_IIF_0(t, ...) __VA_ARGS__
+#define UTIL_IIF_1(t, ...) t
+#define UTIL_IF(c) UTIL_IIF(UTIL_BOOL(c))
+
+#define UTIL_EAT(...)
+#define UTIL_WHEN(c) UTIL_IF(c)(UTIL_EXPAND, UTIL_EAT)
+
+#define UTIL_REPEAT(count, macro, ...)			    \
+	UTIL_WHEN(count)				    \
+	(						    \
+		UTIL_OBSTRUCT(UTIL_REPEAT_INDIRECT) ()	    \
+		(					    \
+			UTIL_DEC(count), macro, __VA_ARGS__ \
+		)					    \
+		UTIL_OBSTRUCT(macro)			    \
+		(					    \
+			UTIL_DEC(count), __VA_ARGS__	    \
+		)					    \
+	)
+#define UTIL_REPEAT_INDIRECT() UTIL_REPEAT
+
+/* Internal macros used by FOR_EACH, FOR_EACH_IDX, etc. */
+
+#define Z_FOR_EACH_IDX(count, n, macro, sep, fixed_arg0, fixed_arg1, ...)\
+	UTIL_WHEN(count)						\
+	(								\
+		UTIL_OBSTRUCT(macro)					\
+		(							\
+			fixed_arg0, fixed_arg1, n, Z_GET_ARG1(__VA_ARGS__)\
+		) COND_CODE_1(count, (), (__DEBRACKET sep))		\
+		UTIL_OBSTRUCT(Z_FOR_EACH_IDX_INDIRECT) ()		\
+		(							\
+			UTIL_DEC(count), UTIL_INC(n), macro, sep,	\
+			fixed_arg0, fixed_arg1,				\
+			Z_GET_ARGS_LESS_1(__VA_ARGS__)			\
+		)							\
+	)
+
+#define Z_GET_ARG1(arg1, ...) arg1
+#define Z_GET_ARGS_LESS_1(arg1, ...) __VA_ARGS__
+
+#define Z_FOR_EACH_IDX_INDIRECT() Z_FOR_EACH_IDX
+
+#define Z_FOR_EACH_IDX2(count, iter, macro, sc, fixed_arg0, fixed_arg1, ...) \
+	UTIL_EVAL(Z_FOR_EACH_IDX(count, iter, macro, sc,\
+				 fixed_arg0, fixed_arg1, __VA_ARGS__))
+
+#define Z_FOR_EACH_SWALLOW_NOTHING(F, fixed_arg, index, arg) \
+	F(index, arg, fixed_arg)
+
+#define Z_FOR_EACH_SWALLOW_FIXED_ARG(F, fixed_arg, index, arg) F(index, arg)
+
+#define Z_FOR_EACH_SWALLOW_INDEX_FIXED_ARG(F, fixed_arg, index, arg) F(arg)
+#define Z_FOR_EACH_SWALLOW_INDEX(F, fixed_arg, index, arg) F(arg, fixed_arg)
+
+/* This is a workaround to enable mixing GET_ARG_N with FOR_EACH macros. If
+ * same UTIL_EVAL macro is used then macro is incorrectly resolved.
+ */
+#define Z_GET_ARG_N_EVAL(...) \
+	Z_GET_ARG_N_EVAL1(Z_GET_ARG_N_EVAL1(Z_GET_ARG_N_EVAL1(__VA_ARGS__)))
+#define Z_GET_ARG_N_EVAL1(...) \
+	Z_GET_ARG_N_EVAL2(Z_GET_ARG_N_EVAL2(Z_GET_ARG_N_EVAL2(__VA_ARGS__)))
+#define Z_GET_ARG_N_EVAL2(...) \
+	Z_GET_ARG_N_EVAL3(Z_GET_ARG_N_EVAL3(Z_GET_ARG_N_EVAL3(__VA_ARGS__)))
+#define Z_GET_ARG_N_EVAL3(...) \
+	Z_GET_ARG_N_EVAL4(Z_GET_ARG_N_EVAL4(Z_GET_ARG_N_EVAL4(__VA_ARGS__)))
+#define Z_GET_ARG_N_EVAL4(...) \
+	Z_GET_ARG_N_EVAL5(Z_GET_ARG_N_EVAL5(Z_GET_ARG_N_EVAL5(__VA_ARGS__)))
+#define Z_GET_ARG_N_EVAL5(...) __VA_ARGS__
+
+/* Set of internal macros used for GET_ARG_N of macros. */
+#define Z_GET_ARG_N(count, single_arg, ...)				\
+	UTIL_WHEN(count)						\
+	(								\
+		IF_ENABLED(count, (UTIL_OBSTRUCT(__DEBRACKET)		\
+		(							\
+			COND_CODE_1(single_arg,				\
+				(Z_GET_ARG1(__VA_ARGS__)), (__VA_ARGS__))\
+		)))							\
+		UTIL_OBSTRUCT(Z_GET_ARG_N_INDIRECT) ()			\
+		(							\
+			UTIL_DEC(count), single_arg,			\
+			Z_GET_ARGS_LESS_1(__VA_ARGS__)			\
+		)							\
+	)
+
+#define Z_GET_ARG_N_INDIRECT() Z_GET_ARG_N
+
+#define _Z_GET_ARG_N(N, single_arg, ...) \
+	Z_GET_ARG_N_EVAL(Z_GET_ARG_N(N, single_arg, __VA_ARGS__))
+
+/* Implementation details for NUM_VA_ARGS_LESS_1 */
+#define NUM_VA_ARGS_LESS_1_IMPL(				\
+	_ignored,						\
+	_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,		\
+	_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,	\
+	_21, _22, _23, _24, _25, _26, _27, _28, _29, _30,	\
+	_31, _32, _33, _34, _35, _36, _37, _38, _39, _40,	\
+	_41, _42, _43, _44, _45, _46, _47, _48, _49, _50,	\
+	_51, _52, _53, _54, _55, _56, _57, _58, _59, _60,	\
+	_61, _62, N, ...) N
+
+/* Used by MACRO_MAP_CAT */
+#define MACRO_MAP_CAT_(...)						\
+	/* To make sure it works also for 2 arguments in total */	\
+	MACRO_MAP_CAT_N(NUM_VA_ARGS_LESS_1(__VA_ARGS__), __VA_ARGS__)
+#define MACRO_MAP_CAT_N_(N, ...) UTIL_CAT(MACRO_MC_, N)(__VA_ARGS__,)
+#define MACRO_MC_0(...)
+#define MACRO_MC_1(m, a, ...)  m(a)
+#define MACRO_MC_2(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_1(m, __VA_ARGS__,))
+#define MACRO_MC_3(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_2(m, __VA_ARGS__,))
+#define MACRO_MC_4(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_3(m, __VA_ARGS__,))
+#define MACRO_MC_5(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_4(m, __VA_ARGS__,))
+#define MACRO_MC_6(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_5(m, __VA_ARGS__,))
+#define MACRO_MC_7(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_6(m, __VA_ARGS__,))
+#define MACRO_MC_8(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_7(m, __VA_ARGS__,))
+#define MACRO_MC_9(m, a, ...)  UTIL_CAT(m(a), MACRO_MC_8(m, __VA_ARGS__,))
+#define MACRO_MC_10(m, a, ...) UTIL_CAT(m(a), MACRO_MC_9(m, __VA_ARGS__,))
+#define MACRO_MC_11(m, a, ...) UTIL_CAT(m(a), MACRO_MC_10(m, __VA_ARGS__,))
+#define MACRO_MC_12(m, a, ...) UTIL_CAT(m(a), MACRO_MC_11(m, __VA_ARGS__,))
+#define MACRO_MC_13(m, a, ...) UTIL_CAT(m(a), MACRO_MC_12(m, __VA_ARGS__,))
+#define MACRO_MC_14(m, a, ...) UTIL_CAT(m(a), MACRO_MC_13(m, __VA_ARGS__,))
+#define MACRO_MC_15(m, a, ...) UTIL_CAT(m(a), MACRO_MC_14(m, __VA_ARGS__,))
+
+#endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/include/toolchain.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/toolchain.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/toolchain.h	(working copy)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010-2014, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Macros to abstract toolchain specific capabilities
+ *
+ * This file contains various macros to abstract compiler capabilities that
+ * utilize toolchain specific attributes and/or pragmas.
+ */
+
+#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_
+#define ZEPHYR_INCLUDE_TOOLCHAIN_H_
+
+/**
+ * @def HAS_BUILTIN(x)
+ * @brief Check if the compiler supports the built-in function \a x.
+ *
+ * This macro is for use with conditional compilation to enable code using a
+ * builtin function that may not be available in every compiler.
+ */
+#ifdef __has_builtin
+#define HAS_BUILTIN(x) __has_builtin(x)
+#else
+/*
+ * The compiler doesn't provide the __has_builtin() macro, so instead we depend
+ * on the toolchain-specific headers to define HAS_BUILTIN_x for the builtins
+ * supported.
+ */
+#define HAS_BUILTIN(x) HAS_BUILTIN_##x
+#endif
+
+
+
+#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_H_ */
Index: ModuleDemo/BLE/CM0/User/include/toolchain/common.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/toolchain/common.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/toolchain/common.h	(working copy)
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2010-2014 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_
+#define ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_
+/**
+ * @file
+ * @brief Common toolchain abstraction
+ *
+ * Macros to abstract compiler capabilities (common to all toolchains).
+ */
+
+/* Abstract use of extern keyword for compatibility between C and C++ */
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C extern
+#endif
+
+/* Use TASK_ENTRY_CPP to tag task entry points defined in C++ files. */
+
+#ifdef __cplusplus
+#define TASK_ENTRY_CPP  extern "C"
+#endif
+
+/*
+ * Generate a reference to an external symbol.
+ * The reference indicates to the linker that the symbol is required
+ * by the module containing the reference and should be included
+ * in the image if the module is in the image.
+ *
+ * The assembler directive ".set" is used to define a local symbol.
+ * No memory is allocated, and the local symbol does not appear in
+ * the symbol table.
+ */
+
+#ifdef _ASMLANGUAGE
+  #define REQUIRES(sym) .set sym ## _Requires, sym
+#else
+  #define REQUIRES(sym) __asm__ (".set " # sym "_Requires, " # sym "\n\t");
+#endif
+
+#ifdef _ASMLANGUAGE
+  #define SECTION .section
+#endif
+
+/*
+ * If the project is being built for speed (i.e. not for minimum size) then
+ * align functions and branches in executable sections to improve performance.
+ */
+
+#ifdef _ASMLANGUAGE
+
+  #if defined(CONFIG_X86)
+
+    #ifdef PERF_OPT
+      #define PERFOPT_ALIGN .balign 16
+    #else
+      #define PERFOPT_ALIGN .balign  1
+    #endif
+
+  #elif defined(CONFIG_ARM)
+
+    #define PERFOPT_ALIGN .balign  4
+
+  #elif defined(CONFIG_ARC)
+
+    /* .align assembler directive is supposed by all ARC toolchains and it is
+     * implemented in a same way across ARC toolchains.
+     */
+    #define PERFOPT_ALIGN .align  4
+
+  #elif defined(CONFIG_NIOS2) || defined(CONFIG_RISCV) || \
+	  defined(CONFIG_XTENSA)
+    #define PERFOPT_ALIGN .balign 4
+
+  #elif defined(CONFIG_ARCH_POSIX)
+
+  #else
+
+    #error Architecture unsupported
+
+  #endif
+
+  #define GC_SECTION(sym) SECTION .text.##sym, "ax"
+
+#endif /* _ASMLANGUAGE */
+
+/* force inlining a function */
+
+#if !defined(_ASMLANGUAGE)
+  #ifdef CONFIG_COVERAGE
+    /*
+     * The always_inline attribute forces a function to be inlined,
+     * even ignoring -fno-inline. So for code coverage, do not
+     * force inlining of these functions to keep their bodies around
+     * so their number of executions can be counted.
+     *
+     * Note that "inline" is kept here for kobject_hash.c and
+     * priv_stacks_hash.c. These are built without compiler flags
+     * used for coverage. ALWAYS_INLINE cannot be empty as compiler
+     * would complain about unused functions. Attaching unused
+     * attribute would result in their text sections ballon more than
+     * 10 times in size, as those functions are kept in text section.
+     * So just keep "inline" here.
+     */
+    #define ALWAYS_INLINE inline
+  #else
+    #define ALWAYS_INLINE inline __attribute__((always_inline))
+  #endif
+#endif
+
+#define Z_STRINGIFY(x) #x
+#define STRINGIFY(s) Z_STRINGIFY(s)
+
+/* concatenate the values of the arguments into one */
+#define _DO_CONCAT(x, y) x ## y
+#define _CONCAT(x, y) _DO_CONCAT(x, y)
+
+/* Additionally used as a sentinel by gen_syscalls.py to identify what
+ * functions are system calls
+ *
+ * Note POSIX unit tests don't still generate the system call stubs, so
+ * until https://github.com/zephyrproject-rtos/zephyr/issues/5006 is
+ * fixed via possibly #4174, we introduce this hack -- which will
+ * disallow us to test system calls in POSIX unit testing (currently
+ * not used).
+ */
+#ifndef ZTEST_UNITTEST
+#define __syscall static inline
+#else
+#define __syscall
+#endif /* #ifndef ZTEST_UNITTEST */
+
+/* Definitions for struct declaration tags. These are sentinel values used by
+ * parse_syscalls.py to gather a list of names of struct declarations that
+ * have these tags applied for them.
+ */
+
+/* Indicates this is a driver subsystem */
+#define __subsystem
+
+/* Indicates this is a network socket object */
+#define __net_socket
+
+#ifndef BUILD_ASSERT
+/* Compile-time assertion that makes the build to fail.
+ * Common implementation swallows the message.
+ */
+#define BUILD_ASSERT(EXPR, MSG...) \
+	enum _CONCAT(__build_assert_enum, __COUNTER__) { \
+		_CONCAT(__build_assert, __COUNTER__) = 1 / !!(EXPR) \
+	}
+#endif
+
+#ifndef BUILD_ASSERT_MSG
+#define BUILD_ASSERT_MSG(EXPR, MSG) __DEPRECATED_MACRO BUILD_ASSERT(EXPR, MSG)
+#endif
+
+/*
+ * This is meant to be used in conjunction with __in_section() and similar
+ * where scattered structure instances are concatened together by the linker
+ * and walked by the code at run time just like a contiguous array of such
+ * structures.
+ *
+ * Assemblers and linkers may insert alignment padding by default whose
+ * size is larger than the natural alignment for those structures when
+ * gathering various section segments together, messing up the array walk.
+ * To prevent this, we need to provide an explicit alignment not to rely
+ * on the default that might just work by luck.
+ *
+ * Alignment statements in  linker scripts are not sufficient as
+ * the assembler may add padding by itself to each segment when switching
+ * between sections within the same file even if it merges many such segments
+ * into a single section in the end.
+ */
+#define Z_DECL_ALIGN(type) __aligned(__alignof(type)) type
+
+/*
+ * Convenience helper combining __in_section() and Z_DECL_ALIGN().
+ * The section name is the struct type prepended with an underscore.
+ * The subsection is "static" and the subsubsection is the variable name.
+ *
+ * In the linker script, create output sections for these using
+ * Z_ITERABLE_SECTION_ROM or Z_ITERABLE_SECTION_RAM.
+ */
+#define Z_STRUCT_SECTION_ITERABLE(struct_type, name) \
+	Z_DECL_ALIGN(struct struct_type) name \
+	__in_section(_##struct_type, static, name) __used
+
+/* Special variant of Z_STRUCT_SECTION_ITERABLE, for placing alternate
+ * data types within the iterable section of a specific data type. The
+ * data type sizes and semantics must be equivalent!
+ */
+#define Z_STRUCT_SECTION_ITERABLE_ALTERNATE(out_type, struct_type, name) \
+	Z_DECL_ALIGN(struct struct_type) name \
+	__in_section(_##out_type, static, name) __used
+
+/*
+ * Itterator for structure instances gathered by Z_STRUCT_SECTION_ITERABLE().
+ * The linker must provide a _<struct_type>_list_start symbol and a
+ * _<struct_type>_list_end symbol to mark the start and the end of the
+ * list of struct objects to iterate over.
+ */
+#define Z_STRUCT_SECTION_FOREACH(struct_type, iterator) \
+	extern struct struct_type _CONCAT(_##struct_type, _list_start)[]; \
+	extern struct struct_type _CONCAT(_##struct_type, _list_end)[]; \
+	for (struct struct_type *iterator = \
+			_CONCAT(_##struct_type, _list_start); \
+	     ({ __ASSERT(iterator <= _CONCAT(_##struct_type, _list_end), \
+			 "unexpected list end location"); \
+		iterator < _CONCAT(_##struct_type, _list_end); }); \
+	     iterator++)
+        
+#define Z_STRUCT_SECTION_LIST_VAR_DEFINE(struct_type, num) \
+                    struct struct_type _CONCAT(_##struct_type, _list)[num];
+
+#define Z_STRUCT_SECTION_LIST_VAR(struct_type, index, item) \
+                        extern struct struct_type item; \
+                        _CONCAT(_##struct_type, _list)[index] = item;
+
+
+#define Z_STRUCT_SECTION_FOREACH_NEW(struct_type, iterator,num) \
+                        extern struct struct_type _CONCAT(_##struct_type, _list)[num]; \
+                        for (struct struct_type *iterator = \
+                                _CONCAT(_##struct_type, _list); \
+                             (iterator < (_CONCAT(_##struct_type, _list) + num)); \
+                             iterator++)
+
+#if 0
+                    struct struct_type* _CONCAT(_##struct_type, _list_start); \
+                    struct struct_type* _CONCAT(_##struct_type, _list_end);
+    
+#define Z_STRUCT_SECTION_LIST_VAR(struct_type, index, item) \
+                        extern struct struct_type item; \
+                        _CONCAT(_##struct_type, _list)[index] = item;
+                        
+#define Z_STRUCT_SECTION_LIST_VAR_INITIAL(struct_type) \
+                        *_CONCAT(_##struct_type, _list_start) = (_CONCAT(_##struct_type, _list)[0]); \
+                        *_CONCAT(_##struct_type, _list_end) = (_CONCAT(_##struct_type, _list)[sizeof(_CONCAT(_##struct_type, _list))]);
+                            
+#endif
+
+
+
+#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_ */
Index: ModuleDemo/BLE/CM0/User/include/types.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/types.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/types.h	(working copy)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_TYPES_H_
+#define ZEPHYR_INCLUDE_TYPES_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__ssize_t_defined)
+#define __ssize_t_defined
+
+#define unsigned signed
+typedef __SIZE_TYPE__ ssize_t;
+#undef unsigned
+
+#endif
+
+
+typedef unsigned char 		uint8_t;
+typedef unsigned short  	uint16_t;
+typedef unsigned int 		uint32_t;
+typedef unsigned long long	uint64_t;
+typedef unsigned char       byte;
+typedef unsigned short      word;
+
+
+typedef signed char 		int8_t;
+typedef signed short     	int16_t;
+typedef signed int 		    int32_t;
+typedef signed long long	int64_t;
+
+typedef unsigned char 		BOOL;
+
+typedef unsigned int  k_timeout_t;
+
+
+#ifndef Boolean
+#ifndef IS_BOOLEAN
+typedef enum {FALSE = 0, TRUE =1} Boolean;
+#define IS_BOOLEAN(bool) ((bool == FALSE) || (bool == TRUE))
+#endif
+#endif
+
+
+#ifndef FunctionalState
+#ifndef IS_FUNCTIONAL_STATE
+typedef enum {DISABLE = 0, ENABLE =1} FunctionalState;
+#define IS_FUNCTIONAL_STATE(state) ((state== DISABLE) || (state == ENABLE))
+#endif
+#endif
+
+//#ifndef FunctionalState
+//typedef enum {ERROR = 0, SUCCESS = 1} ErrorStatus;
+//#define IS_ERROR_STATE(status) ((status== ERROR) || (status == SUCCESS))
+//#endif
+
+#ifndef FlagStatus
+#ifndef IS_FLAG_STATUS_RESET
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
+#define IS_FLAG_STATUS_RESET(state) ((state== RESET) || (state == RESET))
+#endif
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_TYPES_H_ */
Index: ModuleDemo/BLE/CM0/User/include/wait_q.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/wait_q.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/wait_q.h	(working copy)
@@ -0,0 +1,61 @@
+/* wait queue for multiple threads on kernel objects */
+
+/*
+ * Copyright (c) 2015 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_KERNEL_INCLUDE_WAIT_Q_H_
+#define ZEPHYR_KERNEL_INCLUDE_WAIT_Q_H_
+
+#include <sys/dlist.h>
+#include <sys/rb.h>
+#include <sched_priq.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIG_WAITQ_SCALABLE
+
+#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
+	RB_FOR_EACH_CONTAINER(&(wq)->waitq.tree, thread_ptr, base.qnode_rb)
+
+static inline void z_waitq_init(_wait_q_t *w)
+{
+	w->waitq = (struct _priq_rb) {
+		.tree = {
+			.lessthan_fn = z_priq_rb_lessthan
+		}
+	};
+}
+
+static inline struct k_thread *z_waitq_head(_wait_q_t *w)
+{
+	return (struct k_thread *)rb_get_min(&w->waitq.tree);
+}
+
+#else /* !CONFIG_WAITQ_SCALABLE: */
+
+#define _WAIT_Q_FOR_EACH(wq, thread_ptr) \
+	SYS_DLIST_FOR_EACH_CONTAINER(&((wq)->waitq), thread_ptr, \
+				     base.qnode_dlist)
+
+static inline void z_waitq_init(_wait_q_t *w)
+{
+	sys_dlist_init(&w->waitq);
+}
+
+static inline struct k_thread *z_waitq_head(_wait_q_t *w)
+{
+	return (struct k_thread *)sys_dlist_peek_head(&w->waitq);
+}
+
+#endif /* !CONFIG_WAITQ_SCALABLE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_KERNEL_INCLUDE_WAIT_Q_H_ */
Index: ModuleDemo/BLE/CM0/User/include/zephyr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/zephyr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/include/zephyr.h	(working copy)
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_ZEPHYR_H_
+#define ZEPHYR_INCLUDE_ZEPHYR_H_
+
+/*
+ * Applications can identify whether they are built for Zephyr by
+ * macro below. (It may be already defined by a makefile or toolchain.)
+ */
+#ifndef __ZEPHYR__
+#define __ZEPHYR__
+#endif
+
+
+#endif /* ZEPHYR_INCLUDE_ZEPHYR_H_ */
Index: ModuleDemo/BLE/CM0/User/main.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/main.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/main.c	(working copy)
@@ -0,0 +1,551 @@
+#include <stdarg.h>
+#include "yc11xx.h"
+#include "type.h"
+//#include "yc11xx_uart.h"
+#include "yc11xx_gpio.h"
+#include "btreg.h"
+#include "yc_debug.h"
+#include "ipc.h"
+#include "yc11xx_dev_bt.h"
+#include "nvic.h"
+#include "yc11xx_wdt.h"
+#include "yc_drv_common.h"
+#include "yc11xx.h"
+
+#include <common/log.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+#include <sys/byteorder.h>
+
+#define LPM_ENABLE    HWRITE(mem_lpm_mode,1);
+#define sleep_500ms	HWRITEW(mem_lpm_interval,800);		//*0.625ms	
+#define POWER_OFF	 IPC_TxControlCmd(BT_CMD_ENTER_HIBERNATE);
+tIPCHandleCb gTIPCHandleCb[IPC_TYPE_NUM]=
+{
+	0,
+	IpcDefaultCallBack,//cmd
+	Bt_EvtCallBack,//evt
+	IpcDefaultCallBack,//hid
+	//Bt_SPPCallBack,//spp
+	IpcDefaultCallBack,
+	IpcDefaultCallBack,//ble
+	IpcDefaultCallBack,//24g
+	IpcDefaultCallBack,//mesh
+	IpcDefaultCallBack,//mesh
+	IpcDefaultCallBack,//mesh
+	Bt_DataBufferCallBack,//a2dp
+	IpcDefaultCallBack,//hfp
+	IpcDefaultCallBack,//tws
+};
+WDT_InitTypeDef  gWdtInit =
+{
+	.WDTx =WDT2,
+	.mode =RESET_MODE,
+	.setload =WDT_timer_1_5s,
+
+};
+
+#define GPIO_0_5_ADC_DATA	HREADW(mem_0_5_adc_io_data)
+#define GPIO_1V_ADC_DATA	HREADW(mem_1v_adc_io_data)
+#define HVIN_3V_ADC_DATA	HREADW(mem_3v_adc_hvin_data)
+#define HVIN_5V_ADC_DATA	HREADW(mem_5v_adc_hvin_data)
+
+#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
+#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
+
+#define NAME_LEN 30
+
+
+#define BT_UUID_VENDOR \
+	BT_UUID_DECLARE_16(0x8899)
+
+
+struct bt_conn *default_conn;
+
+static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
+static struct bt_gatt_discover_params discover_params;
+static struct bt_gatt_subscribe_params subscribe_params;
+
+/*
+ * Set Advertisement data. Based on the Eddystone specification:
+ * https://github.com/google/eddystone/blob/master/protocol-specification.md
+ * https://github.com/google/eddystone/tree/master/eddystone-url
+ */
+static const struct bt_data ad[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
+	BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe),
+	BT_DATA_BYTES(BT_DATA_SVC_DATA16,
+		      0xaa, 0xfe, /* Eddystone UUID */
+		      0x10, /* Eddystone-URL frame type */
+		      0x00, /* Calibrated Tx power at 0m */
+		      0x00, /* URL Scheme Prefix http://www. */
+		      'z', 'e', 'p', 'h', 'y', 'r',
+		      'p', 'r', 'o', 'j', 'e', 'c', 't',
+		      0x08) /* .org */
+};
+
+/* Set Scan Response data */
+static const struct bt_data sd[] = {
+	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
+};
+
+bt_addr_le_t *current_addr;
+
+static uint8_t notify_func(struct bt_conn *conn,
+			   struct bt_gatt_subscribe_params *params,
+			   const void *data, uint16_t length)
+{
+	if (!data) {
+		printk("[UNSUBSCRIBED]\n");
+		params->value_handle = 0U;
+		return BT_GATT_ITER_STOP;
+	}
+
+	printk("[NOTIFICATION] data %p length %u\n", data, length);
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+#if 1
+static uint8_t discover_func(struct bt_conn *conn,
+			     const struct bt_gatt_attr *attr,
+			     struct bt_gatt_discover_params *params)
+{
+	int err;
+
+	if (!attr) {
+		printk("discover_func, Discover complete\n");
+		(void)memset(params, 0, sizeof(*params));
+		return BT_GATT_ITER_STOP;
+	}
+
+	printk("discover_func, [ATTRIBUTE] handle %u\n", attr->handle);
+
+	if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_HRS)) {
+		memcpy(&uuid, BT_UUID_HRS_MEASUREMENT, sizeof(uuid));
+		discover_params.uuid = &uuid.uuid;
+		discover_params.start_handle = attr->handle + 1;
+		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
+
+		err = bt_gatt_discover(conn, &discover_params);
+		if (err) {
+			printk("discover_func, Discover failed (err %d)\n", err);
+		}
+	} else if (!bt_uuid_cmp(discover_params.uuid,
+				BT_UUID_HRS_MEASUREMENT)) {
+		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
+		discover_params.uuid = &uuid.uuid;
+		discover_params.start_handle = attr->handle + 2;
+		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
+		subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
+
+		err = bt_gatt_discover(conn, &discover_params);
+		if (err) {
+			printk("discover_func, Discover failed (err %d)\n", err);
+		}
+	} else {
+		subscribe_params.notify = notify_func;
+		subscribe_params.value = BT_GATT_CCC_NOTIFY;
+		subscribe_params.ccc_handle = attr->handle;
+
+		err = bt_gatt_subscribe(conn, &subscribe_params);
+		if (err && err != -EALREADY) {
+			printk("discover_func, Subscribe failed (err %d)\n", err);
+		} else {
+			printk("discover_func, [SUBSCRIBED]\n");
+		}
+
+		return BT_GATT_ITER_STOP;
+	}
+
+	return BT_GATT_ITER_STOP;
+}
+#endif
+#if 0
+static void print_chrc_props(uint8_t properties)
+{
+	printk("print_chrc_props, Properties: \n");
+
+	if (properties & BT_GATT_CHRC_BROADCAST) {
+		printk("print_chrc_props, [bcast]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_READ) {
+		printk("print_chrc_props, [read]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_WRITE) {
+		printk("print_chrc_props, [write]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
+		printk("print_chrc_props, [write w/w rsp]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_NOTIFY) {
+		printk("print_chrc_props, [notify]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_INDICATE) {
+		printk("print_chrc_props, [indicate]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_AUTH) {
+		printk("print_chrc_props, [auth]\n");
+	}
+
+	if (properties & BT_GATT_CHRC_EXT_PROP) {
+		printk("print_chrc_props, [ext prop]\n");
+	}
+
+	printk("\n");
+}
+
+static uint8_t discover_func(struct bt_conn *conn,
+			     const struct bt_gatt_attr *attr,
+			     struct bt_gatt_discover_params *params)
+{
+	struct bt_gatt_service_val *gatt_service;
+	struct bt_gatt_chrc *gatt_chrc;
+	struct bt_gatt_include *gatt_include;
+	char str[BT_UUID_STR_LEN];
+
+	if (!attr) {
+		printk("discover_func, Discover complete\n");
+		(void)memset(params, 0, sizeof(*params));
+		return BT_GATT_ITER_STOP;
+	}
+
+	switch (params->type) {
+	case BT_GATT_DISCOVER_SECONDARY:
+	case BT_GATT_DISCOVER_PRIMARY:
+		gatt_service = attr->user_data;
+		bt_uuid_to_str(gatt_service->uuid, str, sizeof(str));
+		printk("discover_func, Service %s found: start handle %x, "
+			    "end_handle %x\n", str, attr->handle,
+			    gatt_service->end_handle);
+		break;
+	case BT_GATT_DISCOVER_CHARACTERISTIC:
+		gatt_chrc = attr->user_data;
+		bt_uuid_to_str(gatt_chrc->uuid, str, sizeof(str));
+		printk("discover_func, Characteristic %s found: handle %x\n",
+			    str, attr->handle);
+		print_chrc_props(gatt_chrc->properties);
+		break;
+	case BT_GATT_DISCOVER_INCLUDE:
+		gatt_include = attr->user_data;
+		bt_uuid_to_str(gatt_include->uuid, str, sizeof(str));
+		printk("discover_func, Include %s found: handle %x, start %x, "
+			    "end %x\n", str, attr->handle,
+			    gatt_include->start_handle,
+			    gatt_include->end_handle);
+		break;
+	default:
+		bt_uuid_to_str(attr->uuid, str, sizeof(str));
+		printk("discover_func, Descriptor %s found: handle %x\n", str,
+			    attr->handle);
+		break;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+#endif
+
+static bool data_cb(struct bt_data *data, void *user_data)
+{
+    char *name = user_data;
+
+    switch (data->type) {
+    case BT_DATA_NAME_SHORTENED:
+    case BT_DATA_NAME_COMPLETE:
+        memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
+        return true;
+    case BT_DATA_UUID16_ALL:
+        {      
+            struct bt_le_conn_param *param;
+            struct bt_uuid *uuid;
+            uint16_t u16;
+            int err;
+            
+            memcpy(&u16, data->data, sizeof(u16));
+            printk("data_cb, u16: 0x%x\n", u16);
+			uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
+			if (bt_uuid_cmp(uuid, BT_UUID_VENDOR)) {
+                return false;
+			}
+            
+            err = bt_le_scan_stop();
+            if (err) {
+                printk("Stop LE scan failed (err %d)\n", err);
+                return false;
+            }
+            
+            param = BT_LE_CONN_PARAM_DEFAULT;
+            err = bt_conn_le_create(current_addr, BT_CONN_LE_CREATE_CONN,
+                        param, &default_conn);
+            if (err) {
+                printk("Create conn failed (err %d)\n", err);
+                //start_scan();
+            }
+         }
+        return false;
+    default:
+        return true;
+    }
+}
+
+static void scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
+            struct net_buf_simple *buf)
+{
+	char le_addr[BT_ADDR_LE_STR_LEN];
+	char name[NAME_LEN];
+
+	(void)memset(name, 0, sizeof(name));
+	printk("scan_cb, adv_raw: %s\n"
+		    , bt_hex(buf->data, buf->len));
+
+    current_addr = addr;
+	bt_data_parse(buf, data_cb, name);
+
+	bt_addr_le_to_str(addr, le_addr, sizeof(le_addr));
+    
+	printk("[DEVICE]: %s [%s], AD evt type %u, RSSI %d\n"
+		    , name, le_addr, adv_type, rssi);
+
+}
+            
+static void start_scan(void)
+{
+    int err;
+
+    /* Use active scanning and disable duplicate filtering to handle any
+     * devices that might update their advertising data at runtime. */
+    struct bt_le_scan_param scan_param = {
+        .type       = BT_HCI_LE_SCAN_ACTIVE,
+        .options    = BT_LE_SCAN_OPT_NONE,
+        .interval   = 0x0040,
+        .window     = 0x0020,
+    };
+
+
+    err = bt_le_scan_start(&scan_param, scan_cb);
+    if (err) {
+        printk("Scanning failed to start (err %d)\n", err);
+        return;
+    }
+
+    printk("Scanning successfully started\n");
+}
+
+static void connected(struct bt_conn *conn, uint8_t conn_err)
+{
+    char addr[BT_ADDR_LE_STR_LEN];
+    int err;
+
+    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+    if (conn_err) {
+        printk("Failed to connect to %s (%u)\n", addr, conn_err);
+
+        bt_conn_unref(default_conn);
+        default_conn = NULL;
+
+        start_scan();
+        return;
+    }
+
+    printk("Connected: %s\n", addr);
+
+    if (conn == default_conn) {
+#if 0
+        //memcpy(&uuid, BT_UUID_VENDOR, sizeof(uuid));
+        //discover_params.uuid = &uuid.uuid;
+#else
+        memcpy(&uuid, BT_UUID_HRS, sizeof(uuid));
+        discover_params.uuid = &uuid.uuid;
+#endif
+        discover_params.func = discover_func;
+        discover_params.start_handle = 0x0001;
+        discover_params.end_handle = 0xffff;
+        discover_params.type = BT_GATT_DISCOVER_PRIMARY;
+
+        err = bt_gatt_discover(default_conn, &discover_params);
+        if (err) {
+            printk("Discover failed(err %d)\n", err);
+            return;
+        }
+    }
+}
+
+static void disconnected(struct bt_conn *conn, uint8_t reason)
+{
+    char addr[BT_ADDR_LE_STR_LEN];
+
+    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+    printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
+
+    if (default_conn != conn) {
+        return;
+    }
+
+    bt_conn_unref(default_conn);
+    default_conn = NULL;
+
+    start_scan();
+}
+
+static struct bt_conn_cb conn_callbacks = {
+    .connected = connected,
+    .disconnected = disconnected,
+};
+
+static void bt_ready(int err)
+{
+	printk("Bluetooth initialized\n");
+
+	char addr_s[BT_ADDR_LE_STR_LEN];
+	bt_addr_le_t addr = {0};
+	size_t count = 1;
+
+	if (err) {
+		printk("Bluetooth init failed (err %d)\n", err);
+		return;
+	}
+
+	bt_conn_cb_register(&conn_callbacks);
+#if 0
+	/* Start advertising */
+	err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad),
+			      sd, ARRAY_SIZE(sd));
+	if (err) {
+		printk("Advertising failed to start (err %d)\n", err);
+		return;
+	}
+
+	/* For connectable advertising you would use
+	 * bt_le_oob_get_local().  For non-connectable non-identity
+	 * advertising an non-resolvable private address is used;
+	 * there is no API to retrieve that.
+	 */
+
+	bt_id_get(&addr, &count);
+	bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));
+
+	printk("Beacon started, advertising as %s\n", addr_s);
+#endif
+
+    start_scan();
+}
+
+
+int main(void)
+{
+	*(volatile byte*)(reg_map_m0(0x1f000)) = 0x1c;//Enable cm0 debug
+	SYS_TimerInit(CLOCK_48M_multiple);
+	IPC_init(&gTIPCHandleCb);
+	
+	DEBUG_INIT();
+	DEBUG_LOG(LOG_LEVEL_CORE, "IPC" ,"Bt_EvtCallBack: 0x%04X", LOG_POINT_9010, gBRState.topState);
+
+#ifdef FUNCTION_WATCH_DOG
+	WDT_Start(&gWdtInit);
+#endif
+	//h4_init();
+    ipc_bt_hci_init();
+    bt_enable(bt_ready);
+
+	sleep_500ms;
+//	LPM_ENABLE;
+//	POWER_OFF;
+	while (1)
+	{
+#ifdef FUNCTION_WATCH_DOG
+		WDT_Kick();
+#endif
+		//For respin log print
+		
+
+		switch (HREAD(IPC_MCU_STATE))
+		{
+			case IPC_MCU_STATE_RUNNING:
+				//always first init bt
+				IPC_HandleRxPacket();
+				bt_polling_work();
+				//Bt_watchdog();
+				if (gBRState.topState != BR_POWER_OFF)
+				{
+					DEBUG_POLLING_PRINT();
+					SYS_timerPolling();
+
+					//h4_polling_rx();
+				}
+				Lpm_unLockLpm(M0_LPM_FLAG);
+				break;
+			case IPC_MCU_STATE_LMP:
+				if (IPC_IsTxBuffEmpty()
+					&& DEBUG_LOG_BUFFER_IS_EMPTY())
+				{
+					OS_ENTER_CRITICAL();
+					Bt_ActionBeforeLpm();
+					HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
+				}
+				else
+				{
+					HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_RUNNING);
+				}
+				break;
+			case IPC_MCU_STATE_HIBERNATE:
+				OS_ENTER_CRITICAL();
+				Bt_ActionBeforeHibernate();
+				HWRITE(IPC_MCU_STATE,IPC_MCU_STATE_STOP);
+				break;
+			case IPC_MCU_STATE_STOP:
+				break;
+		}
+		//hw_delay();
+	};
+}
+
+
+
+void SCO_NVIC_Config(void)
+{
+	NVIC_SetPriority(timer6_handler_IRQn, 0);
+	NVIC_EnableIRQ(timer6_handler_IRQn);
+}
+
+void SCO_NVIC_DeConfig(void)
+{
+	NVIC_SetPriority(timer6_handler_IRQn, 0);
+	NVIC_DisableIRQ(timer6_handler_IRQn);
+}
+
+
+
+
+void TIMER6_IRQHandler(void)
+{
+//	Bt_SCODataProcess();
+}
+
+
+/**
+  * @brief  Systick interrupt service function.
+  * @param  None
+  * @retval None
+  */
+void SysTick_Handler(void)
+{
+	SYStick_handle();
+}
+
+void _assert_handler(const char* file, int line,const char* func)
+{
+	while(1);
+}
+
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/CMakeLists.txt	(working copy)
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources(dummy.c)
+zephyr_library_sources(log.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_RPA   rpa.c)
+
+zephyr_library_link_libraries(subsys__bluetooth)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/Kconfig	(working copy)
@@ -0,0 +1,151 @@
+# Bluetooth common configuration options
+
+# Copyright (c) 2017 Nordic Semiconductor ASA
+# Copyright (c) 2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config BT_HAS_HCI_VS
+	bool
+	help
+	  This option is set by the Bluetooth controller to indicate support
+	  for the Zephyr HCI Vendor-Specific Commands and Event.
+
+config BT_HCI_VS
+	bool "Zephyr HCI Vendor-Specific Commands"
+	depends on BT_HAS_HCI_VS || !BT_CTLR
+	default y if BT_HAS_HCI_VS
+	help
+	  Enable support for the Zephyr HCI Vendor-Specific Commands in the
+	  Host and/or Controller. This enables Set Version Information,
+	  Supported Commands, Supported Features vendor commands.
+
+config BT_HCI_VS_EXT
+	bool "Zephyr HCI Vendor-Specific Extensions"
+	depends on BT_HCI_VS
+	default y
+	help
+	  Enable support for the Zephyr HCI Vendor-Specific Extensions in the
+	  Host and/or Controller. This enables  Write BD_ADDR, Read Build Info,
+	  Read Static Addresses and Read Key Hierarchy Roots vendor commands.
+
+config BT_HCI_VS_EXT_DETECT
+	bool "Use heuristics to guess HCI vendor extensions support in advance"
+	depends on BT_HCI_VS_EXT && !BT_CTLR
+	default y if BOARD_QEMU_X86 || BOARD_QEMU_CORTEX_M3 || BOARD_NATIVE_POSIX
+	help
+	  Use some heuristics to try to guess in advance whether the controller
+	  supports the HCI vendor extensions in advance, in order to prevent
+	  sending vendor commands to controller which may interpret them in
+	  completely different ways.
+
+config BT_HCI_MESH_EXT
+	bool "Mesh HCI Command support"
+	depends on BT_BROADCASTER && BT_OBSERVER && !BT_LL_SW_SPLIT
+	help
+	  Enable support for the Bluetooth Mesh HCI Commands.
+
+config BT_WAIT_NOP
+	bool "Wait for \"NOP\" Command Complete event during init"
+	help
+	  Emit a Command Complete event from the Controller (and wait for it
+	  from the Host) for the NOP opcode to indicate that the Controller is
+	  ready to receive commands.
+
+config BT_RPA
+	bool
+	select TINYCRYPT
+	select TINYCRYPT_AES
+
+config BT_ASSERT
+	bool "Custom Bluetooth assert implementation"
+	default y
+	help
+	  Use a custom Bluetooth assert implementation instead of the
+	  kernel-wide __ASSERT() when CONFIG_ASSERT is disabled.
+
+if BT_ASSERT
+
+config BT_ASSERT_VERBOSE
+	bool "Print out an assert string when using BT_ASSERT"
+	default y
+	help
+	  When CONFIG_BT_ASSERT is enabled, this option turns on printing the
+	  cause of the assert to the console using printk().
+
+config BT_ASSERT_PANIC
+	bool "Use k_panic() instead of k_oops()"
+	help
+	  When CONFIG_BT_ASSERT is enabled, this option makes the code call
+	  k_panic() instead of k_oops() when an assertion is triggered.
+
+endif # BT_ASSERT
+
+config BT_DEBUG
+	# Hidden option to make the conditions more intuitive
+	bool
+
+choice
+	prompt "Bluetooth debug type"
+	default BT_DEBUG_NONE
+
+config BT_DEBUG_NONE
+	bool "No debug log"
+	help
+	  Select this to disable all Bluetooth debug logs.
+
+config BT_DEBUG_LOG
+	bool "Normal printf-style to console"
+	select BT_DEBUG
+	select LOG
+	help
+	  This option enables Bluetooth debug going to standard
+	  serial console.
+
+config BT_DEBUG_MONITOR
+	bool "Monitor protocol over UART"
+	select BT_DEBUG
+	select LOG
+	select CONSOLE_HAS_DRIVER
+	help
+	  Use a custom logging protocol over the console UART
+	  instead of plain-text output. Requires a special application
+	  on the host side that can decode this protocol. Currently
+	  the 'btmon' tool from BlueZ is capable of doing this.
+
+	  If the target board has two or more external UARTs it is
+	  possible to keep using UART_CONSOLE together with this option,
+	  however if there is only a single external UART then
+	  UART_CONSOLE needs to be disabled (in which case printk/printf
+	  will get encoded into the monitor protocol).
+
+endchoice
+
+if BT_DEBUG
+
+# Workaround for not being able to have commas in macro arguments
+DT_CHOSEN_Z_BT_MON_UART := zephyr,bt-mon-uart
+
+config BT_MONITOR_ON_DEV_NAME
+	string "Device Name of Bluetooth monitor logging UART"
+	depends on BT_DEBUG_MONITOR
+	default "$(dt_chosen_label,$(DT_CHOSEN_Z_BT_MON_UART))" if HAS_DTS
+	default "UART_0"
+	help
+	  This option specifies the name of UART device to be used
+	  for the Bluetooth monitor logging.
+
+config BT_DEBUG_HCI_DRIVER
+	bool "Bluetooth HCI driver debug"
+	help
+	  This option enables debug support for the active
+	  Bluetooth HCI driver, including the Controller-side HCI layer
+	  when included in the build.
+
+config BT_DEBUG_RPA
+	bool "Bluetooth Resolvable Private Address (RPA) debug"
+	depends on BT_RPA
+	help
+	  This option enables debug support for the Bluetooth
+	  Resolvable Private Address (RPA) generation and resolution.
+
+endif # BT_DEBUG
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/dummy.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/dummy.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/dummy.c	(working copy)
@@ -0,0 +1,49 @@
+/**
+ * @file dummy.c
+ * Static compilation checks.
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+
+#if defined(CONFIG_BT_HCI_HOST)
+/* The Bluetooth subsystem requires the Tx thread to execute at higher priority
+ * than the Rx thread as the Tx thread needs to process the acknowledgements
+ * before new Rx data is processed. This is a necessity to correctly detect
+ * transaction violations in ATT and SMP protocols.
+ */
+BUILD_ASSERT(CONFIG_BT_HCI_TX_PRIO < CONFIG_BT_RX_PRIO);
+
+/* The Bluetooth subsystem requires that higher priority events shall be given
+ * in a priority higher than the Bluetooth Host's Tx and the Controller's
+ * receive thread priority.
+ * This is required in order to dispatch Number of Completed Packets event
+ * before any new data arrives on a connection to the Host threads.
+ */
+BUILD_ASSERT(CONFIG_BT_DRIVER_RX_HIGH_PRIO < CONFIG_BT_HCI_TX_PRIO);
+#endif /* defined(CONFIG_BT_HCI_HOST) */
+
+#if (defined(CONFIG_LOG_BACKEND_RTT) &&                     \
+     (defined(CONFIG_SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) || \
+      defined(CONFIG_LOG_BACKEND_RTT_MODE_BLOCK))) ||       \
+    defined(CONFIG_LOG_BACKEND_NET) ||                      \
+    defined(CONFIG_LOG_IMMEDIATE_CLEAN_OUTPUT)
+#define INCOMPATIBLE_IMMEDIATE_LOG_BACKEND 1
+#endif
+
+/* Immediate logging on most backend is not supported
+ * with the software-based Link Layer since it introduces ISR latency
+ * due to outputting log messages with interrupts disabled.
+ */
+#if !defined(CONFIG_TEST) && !defined(CONFIG_ARCH_POSIX) && \
+    defined(CONFIG_BT_LL_SW_SPLIT) &&                       \
+    defined(INCOMPATIBLE_IMMEDIATE_LOG_BACKEND)
+BUILD_ASSERT(!IS_ENABLED(CONFIG_LOG_IMMEDIATE), "Immediate logging "
+	     "on selected backend(s) not "
+	     "supported with the software Link Layer");
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.h	(working copy)
@@ -0,0 +1,106 @@
+/** @file
+ *  @brief Bluetooth subsystem logging helpers.
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __BT_LOG_H
+#define __BT_LOG_H
+
+#include <zephyr.h>
+#include <logging/log.h>
+#include <sys/__assert.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/hci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(BT_DBG_ENABLED)
+#define BT_DBG_ENABLED 1
+#endif
+
+#if BT_DBG_ENABLED
+#define LOG_LEVEL LOG_LEVEL_DBG
+#else
+#define LOG_LEVEL CONFIG_BT_LOG_LEVEL
+#endif
+
+//LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL);
+
+#define BT_DBG(fmt, ...) LOG_DBG(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define BT_ERR(fmt, ...) LOG_ERR(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define BT_WARN(fmt, ...) LOG_WRN(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define BT_INFO(fmt, ...) LOG_INF(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+
+#if defined(CONFIG_BT_ASSERT_VERBOSE)
+#define BT_ASSERT_PRINT(test) __ASSERT_LOC(test)
+#define BT_ASSERT_PRINT_MSG(fmt, ...) __ASSERT_MSG_INFO(fmt, ##__VA_ARGS__)
+#else
+#define BT_ASSERT_PRINT(test)
+#define BT_ASSERT_PRINT_MSG(fmt, ...)
+#endif /* CONFIG_BT_ASSERT_VERBOSE */
+
+#if defined(CONFIG_BT_ASSERT_PANIC)
+#define BT_ASSERT_DIE k_panic
+#else
+#define BT_ASSERT_DIE k_oops
+#endif /* CONFIG_BT_ASSERT_PANIC */
+
+#if defined(CONFIG_BT_ASSERT)
+#define BT_ASSERT(cond)                          \
+	do {                                     \
+		if (!(cond)) {                   \
+			BT_ASSERT_PRINT(cond);   \
+			BT_ASSERT_DIE();         \
+		}                                \
+	} while (0)
+
+#define BT_ASSERT_MSG(cond, fmt, ...)                              \
+	do {                                                       \
+		if (!(cond)) {                                     \
+			BT_ASSERT_PRINT(cond);                     \
+			BT_ASSERT_PRINT_MSG(fmt, ##__VA_ARGS__);   \
+			BT_ASSERT_DIE();                           \
+		}                                                  \
+	} while (0)
+#else
+#define BT_ASSERT(cond) __ASSERT_NO_MSG(cond)
+#define BT_ASSERT_MSG(cond, msg, ...) __ASSERT(cond, msg, ##__VA_ARGS__)
+#endif/* CONFIG_BT_ASSERT*/
+
+#define BT_HEXDUMP_DBG(_data, _length, _str) \
+		LOG_HEXDUMP_DBG((const uint8_t *)_data, _length, _str)
+
+/* NOTE: These helper functions always encodes into the same buffer storage.
+ * It is the responsibility of the user of this function to copy the information
+ * in this string if needed.
+ *
+ * NOTE: These functions are not thread-safe!
+ */
+const char *bt_hex_real(const void *buf, size_t len);
+const char *bt_addr_str_real(const bt_addr_t *addr);
+const char *bt_addr_le_str_real(const bt_addr_le_t *addr);
+const char *bt_uuid_str_real(const struct bt_uuid *uuid);
+
+/* NOTE: log_strdup does not guarantee a duplication of the string.
+ * It is therefore still the responsibility of the user to handle the
+ * restrictions in the underlying function call.
+ */
+#define bt_hex(buf, len) log_strdup(bt_hex_real(buf, len))
+#define bt_addr_str(addr) log_strdup(bt_addr_str_real(addr))
+#define bt_addr_le_str(addr) log_strdup(bt_addr_le_str_real(addr))
+#define bt_uuid_str(uuid) log_strdup(bt_uuid_str_real(uuid))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BT_LOG_H */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/log.c	(working copy)
@@ -0,0 +1,66 @@
+/* log.c - logging helpers */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Helper for printk parameters to convert from binary to hex.
+ * We declare multiple buffers so the helper can be used multiple times
+ * in a single printk call.
+ */
+
+#include <stddef.h>
+#include <zephyr.h>
+#include <sys/util.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/hci.h>
+
+const char *bt_hex_real(const void *buf, size_t len)
+{
+	static const char hex[] = "0123456789abcdef";
+	static char str[129];
+	const uint8_t *b = buf;
+	size_t i;
+
+	len = MIN(len, (sizeof(str) - 1) / 2);
+
+	for (i = 0; i < len; i++) {
+		str[i * 2]     = hex[b[i] >> 4];
+		str[i * 2 + 1] = hex[b[i] & 0xf];
+	}
+
+	str[i * 2] = '\0';
+
+	return str;
+}
+
+const char *bt_addr_str_real(const bt_addr_t *addr)
+{
+	static char str[BT_ADDR_STR_LEN];
+
+	bt_addr_to_str(addr, str, sizeof(str));
+
+	return str;
+}
+
+const char *bt_addr_le_str_real(const bt_addr_le_t *addr)
+{
+	static char str[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(addr, str, sizeof(str));
+
+	return str;
+}
+
+const char *bt_uuid_str_real(const struct bt_uuid *uuid)
+{
+	static char str[BT_UUID_STR_LEN];
+
+	bt_uuid_to_str(uuid, str, sizeof(str));
+
+	return str;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.h	(working copy)
@@ -0,0 +1,16 @@
+/* rpa.h - Bluetooth Resolvable Private Addresses (RPA) generation and
+ * resolution
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+bool bt_rpa_irk_matches(const uint8_t irk[16], const bt_addr_t *addr);
+int bt_rpa_create(const uint8_t irk[16], bt_addr_t *rpa);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/common/rpa.c	(working copy)
@@ -0,0 +1,125 @@
+/**
+ * @file rpa.c
+ * Resolvable Private Address Generation and Resolution
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <stddef.h>
+#include <errno.h>
+#include <string.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_RPA)
+#define LOG_MODULE_NAME bt_rpa
+#include "common/log.h"
+
+#include <bluetooth/crypto.h>
+
+#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO)
+#include "../controller/util/util.h"
+#include "../controller/hal/ecb.h"
+#endif /* defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) */
+
+#if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY)
+static int internal_rand(void *buf, size_t len)
+{
+/* Force using controller rand function. */
+#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO)
+	return lll_csrand_get(buf, len);
+#else
+	return bt_rand(buf, len);
+#endif
+}
+#endif /* defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY) */
+
+static int internal_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
+			       uint8_t enc_data[16])
+{
+/* Force using controller encrypt function if supported. */
+#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) && \
+    defined(CONFIG_BT_CTLR_LE_ENC)
+	ecb_encrypt(key, plaintext, enc_data, NULL);
+	return 0;
+#else
+	return bt_encrypt_le(key, plaintext, enc_data);
+#endif
+}
+
+static int ah(const uint8_t irk[16], const uint8_t r[3], uint8_t out[3])
+{
+	uint8_t res[16];
+	int err;
+
+	BT_DBG("irk %s", bt_hex(irk, 16));
+	BT_DBG("r %s", bt_hex(r, 3));
+
+	/* r' = padding || r */
+	memcpy(res, r, 3);
+	(void)memset(res + 3, 0, 13);
+
+	err = internal_encrypt_le(irk, res, res);
+	if (err) {
+		return err;
+	}
+
+	/* The output of the random address function ah is:
+	 *      ah(h, r) = e(k, r') mod 2^24
+	 * The output of the security function e is then truncated to 24 bits
+	 * by taking the least significant 24 bits of the output of e as the
+	 * result of ah.
+	 */
+	memcpy(out, res, 3);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CTLR_PRIVACY)
+bool bt_rpa_irk_matches(const uint8_t irk[16], const bt_addr_t *addr)
+{
+	uint8_t hash[3];
+	int err;
+
+	BT_DBG("IRK %s bdaddr %s", bt_hex(irk, 16), bt_addr_str(addr));
+
+	err = ah(irk, addr->val + 3, hash);
+	if (err) {
+		return false;
+	}
+
+	return !memcmp(addr->val, hash, 3);
+}
+#endif
+
+#if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY)
+int bt_rpa_create(const uint8_t irk[16], bt_addr_t *rpa)
+{
+	int err;
+
+	err = internal_rand(rpa->val + 3, 3);
+	if (err) {
+		return err;
+	}
+
+	BT_ADDR_SET_RPA(rpa);
+
+	err = ah(irk, rpa->val + 3, rpa->val);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("Created RPA %s", bt_addr_str((bt_addr_t *)rpa->val));
+
+	return 0;
+}
+#else
+int bt_rpa_create(const uint8_t irk[16], bt_addr_t *rpa)
+{
+	return -ENOTSUP;
+}
+#endif /* CONFIG_BT_PRIVACY */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/CMakeLists.txt	(working copy)
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_sources(
+  util/mem.c
+  util/memq.c
+  util/mayfly.c
+  util/util.c
+  ticker/ticker.c
+  ll_sw/ll_addr.c
+  ll_sw/ll_tx_pwr.c
+  hci/hci_driver.c
+  hci/hci.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_BT_CTLR_CRYPTO
+  crypto/crypto.c
+  )
+
+if(CONFIG_BT_LL_SW_SPLIT)
+  zephyr_library_sources(
+    ll_sw/ull.c
+    )
+  if(CONFIG_BT_BROADCASTER)
+    zephyr_library_sources(
+      ll_sw/ull_adv.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_EXT
+      ll_sw/ull_adv_aux.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_PERIODIC
+      ll_sw/ull_adv_sync.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_ISO
+      ll_sw/ull_adv_iso.c
+      )
+  endif()
+  if(CONFIG_BT_OBSERVER)
+    zephyr_library_sources(
+      ll_sw/ull_scan.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_EXT
+      ll_sw/ull_scan_aux.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_SYNC_PERIODIC
+      ll_sw/ull_sync.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_SYNC_ISO
+      ll_sw/ull_sync_iso.c
+      )
+  endif()
+  if(CONFIG_BT_CONN)
+    zephyr_library_sources(
+      ll_sw/ull_conn.c
+      )
+    if(CONFIG_BT_PERIPHERAL)
+      zephyr_library_sources(
+        ll_sw/ull_slave.c
+      )
+    endif()
+    if(CONFIG_BT_CENTRAL)
+      zephyr_library_sources(
+        ll_sw/ull_master.c
+        )
+    endif()
+    if(CONFIG_BT_CTLR_SCHED_ADVANCED)
+      zephyr_library_sources(
+        ll_sw/ull_sched.c
+      )
+    endif()
+  endif()
+  if(CONFIG_BT_CONN OR
+     CONFIG_BT_CTLR_ADV_PERIODIC OR
+     CONFIG_BT_CTLR_SYNC_PERIODIC)
+    zephyr_library_sources(
+      ll_sw/ull_chan.c
+      ll_sw/lll_chan.c
+      )
+  endif()
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_CTLR_FILTER
+    ll_sw/ull_filter.c
+    )
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_HCI_MESH_EXT
+    ll_sw/ll_mesh.c
+    )
+endif()
+
+if(CONFIG_SOC_COMPATIBLE_NRF)
+  include(ll_sw/nrf.cmake)
+elseif(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
+  include(ll_sw/openisa.cmake)
+endif()
+
+zephyr_library_sources_ifdef(
+  CONFIG_BT_CTLR_SETTINGS
+  ll_sw/ll_settings.c
+)
+
+zephyr_library_include_directories(
+  .
+  include
+  ll_sw
+  )
+
+zephyr_library_compile_options_ifdef(
+  CONFIG_BT_CTLR_OPTIMIZE_FOR_SPEED
+  ${OPTIMIZE_FOR_SPEED_FLAG}
+  )
+
+zephyr_library_link_libraries(subsys__bluetooth)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig	(working copy)
@@ -0,0 +1,524 @@
+# Bluetooth Controller configuration options
+
+# Copyright (c) 2016-2017 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+comment "BLE Controller support"
+
+# The following symbols are enabled depending if the controller actually
+# supports the respective features.
+
+config BT_CTLR_LE_ENC_SUPPORT
+	bool
+
+config BT_CTLR_CONN_PARAM_REQ_SUPPORT
+	bool
+
+config BT_CTLR_EXT_REJ_IND_SUPPORT
+	bool
+
+config BT_CTLR_SLAVE_FEAT_REQ_SUPPORT
+	bool
+
+config BT_CTLR_DATA_LEN_UPDATE_SUPPORT
+	bool
+
+config BT_CTLR_PRIVACY_SUPPORT
+	bool
+
+config BT_CTLR_EXT_SCAN_FP_SUPPORT
+	bool
+
+config BT_CTLR_PHY_UPDATE_SUPPORT
+	bool
+
+config BT_CTLR_PHY_2M_SUPPORT
+	bool
+
+config BT_CTLR_PHY_CODED_SUPPORT
+	bool
+
+config BT_CTLR_ADV_EXT_SUPPORT
+	bool
+
+config BT_CTLR_ADV_PERIODIC_SUPPORT
+	depends on BT_CTLR_ADV_EXT_SUPPORT
+	bool
+
+config BT_CTLR_SYNC_PERIODIC_SUPPORT
+	depends on BT_CTLR_ADV_EXT_SUPPORT
+	bool
+
+config BT_CTLR_ADV_ISO_SUPPORT
+	depends on BT_CTLR_ADV_PERIODIC_SUPPORT
+	bool
+
+config BT_CTLR_SYNC_ISO_SUPPORT
+	depends on BT_CTLR_SYNC_PERIODIC_SUPPORT
+	bool
+
+config BT_CTLR_CHAN_SEL_2_SUPPORT
+	bool
+
+config BT_CTLR_MIN_USED_CHAN_SUPPORT
+	bool
+
+config BT_CTLR_DTM_HCI_SUPPORT
+	bool
+
+config BT_CTLR_SMI_SUPPORT
+	bool
+
+config BT_CTLR_CONN_RSSI_SUPPORT
+	bool
+
+config BT_CTLR
+	bool "Bluetooth Controller"
+	help
+	  Enables support for SoC native controller implementations.
+
+if BT_CTLR
+
+choice BT_LL_CHOICE
+	prompt "Bluetooth Link Layer Selection"
+	help
+	  Select the Bluetooth Link Layer to compile.
+
+config BT_LL_SW_SPLIT
+	bool "Software-based BLE Link Layer"
+	select BT_RECV_IS_RX_THREAD
+	select ENTROPY_GENERATOR
+	help
+	  Use Zephyr software BLE Link Layer ULL LLL split implementation.
+
+endchoice
+
+comment "BLE Controller configuration"
+
+config BT_CTLR_CRYPTO
+	bool "Enable crypto functions in Controller"
+	default y
+	select ENTROPY_GENERATOR
+	help
+	  Use random number generation and AES encryption support functions
+	  provided by the controller.
+
+config BT_CTLR_HCI_VS_BUILD_INFO
+	string "Zephyr HCI VS Build Info string"
+	default ""
+	depends on BT_HCI_VS_EXT
+	help
+	  User-defined string that will be returned by the Zephyr VS Read Build
+	  Information command after the Zephyr version and build time. When
+	  setting this to a value different from an empty string, a space
+	  character is required at the beginning to separate it from the
+	  already included information.
+
+config BT_CTLR_HCI_ADV_HANDLE_MAPPING
+	bool "Enable advertising set handle mapping between HCI and LL"
+	depends on BT_CTLR_ADV_EXT
+	default y if BT_HCI_RAW
+	help
+	  Enable mapping of advertising set handles between HCI and LL when
+	  using external host since it can use arbitrary numbers as set handles
+	  (as defined by Core specification) as opposed to LL which always uses
+	  zero-based numbering. When using with Zephyr host this option can be
+	  disabled to remove extra mapping logic.
+
+config BT_CTLR_DUP_FILTER_LEN
+	int "Number of addresses in the scan duplicate filter"
+	depends on BT_OBSERVER
+	default 16
+	help
+	  Set the number of unique BLE addresses that can be filtered as
+	  duplicates while scanning.
+
+config BT_CTLR_MESH_SCAN_FILTERS
+	int "Number of Mesh scan filters"
+	depends on BT_HCI_MESH_EXT
+	default 1
+	range 1 15
+	help
+	  Set the number of unique Mesh Scan Filters available as part of
+	  the Intel Mesh Vendor Specific Extensions.
+
+config BT_CTLR_MESH_SF_PATTERNS
+	int "Number of Mesh scan filter patterns"
+	depends on BT_HCI_MESH_EXT
+	default 15
+	range 1 15
+	help
+	  Set the number of unique Mesh Scan Filter patterns available per
+	  Scan Filter as part of the Intel Mesh Vendor Specific Extensions.
+
+config BT_CTLR_RX_BUFFERS
+	int "Number of Rx buffers"
+	default 6 if BT_HCI_RAW
+	default 1
+	range 1 18
+	help
+	  Set the number of Rx PDUs to be buffered in the controller. In a 7.5ms
+	  connection interval and 2M PHY, maximum 18 packets with L2CAP payload
+	  size of 1 byte can be received.
+
+config BT_CTLR_TX_BUFFERS
+	int "Number of Tx buffers"
+	default 7 if BT_HCI_RAW
+	default 3
+	range 1 19
+	help
+	  Set the number of Tx PDUs to be queued for transmission in the
+	  controller. In a 7.5ms connection interval and 2M PHY, maximum 19
+	  packets can be enqueued, with 18 packets with L2CAP payload size of 1
+	  byte can be acknowledged.
+
+config BT_CTLR_TX_BUFFER_SIZE
+	int "Tx buffer size"
+	range 27 251
+	default 27
+	help
+	  Size of the Tx buffers and the value returned in HCI LE Read Buffer
+	  Size command response. If this size if greater than effective PDU size
+	  then controller will perform fragmentation before transmitting on the
+	  the packet on air.
+	  Maximum is set to 251 due to implementation limitations (use of
+	  uint8_t for length field in PDU buffer structure).
+
+choice BT_CTLR_TX_PWR
+	prompt "Tx Power"
+	default BT_CTLR_TX_PWR_0
+	help
+	  Select the supported BLE Radio transmit power level in dBm.
+
+config BT_CTLR_TX_PWR_PLUS_8
+	bool "+8 dBm"
+	depends on SOC_NRF52840
+
+config BT_CTLR_TX_PWR_PLUS_7
+	bool "+7 dBm"
+	depends on SOC_NRF52840
+
+config BT_CTLR_TX_PWR_PLUS_6
+	bool "+6 dBm"
+	depends on SOC_NRF52840
+
+config BT_CTLR_TX_PWR_PLUS_5
+	bool "+5 dBm"
+	depends on SOC_NRF52840
+
+config BT_CTLR_TX_PWR_PLUS_4
+	bool "+4 dBm"
+	depends on SOC_SERIES_NRF51X || SOC_COMPATIBLE_NRF52X
+
+config BT_CTLR_TX_PWR_PLUS_3
+	bool "+3 dBm"
+	depends on SOC_COMPATIBLE_NRF52X
+
+config BT_CTLR_TX_PWR_PLUS_2
+	bool "+2 dBm"
+	depends on SOC_NRF52840
+
+config BT_CTLR_TX_PWR_0
+	bool "0 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_4
+	bool "-4 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_8
+	bool "-8 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_12
+	bool "-12 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_16
+	bool "-16 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_20
+	bool "-20 dBm"
+
+config BT_CTLR_TX_PWR_MINUS_30
+	bool "-30 dBm"
+	depends on SOC_SERIES_NRF51X
+
+config BT_CTLR_TX_PWR_MINUS_40
+	bool "-40 dBm"
+	depends on SOC_COMPATIBLE_NRF52X
+
+endchoice
+
+config BT_CTLR_TX_PWR_DYNAMIC_CONTROL
+	bool "Tx Power Dynamic Control"
+	depends on BT_HCI_VS_EXT
+	help
+	  Enable dynamic control of Tx power per role/connection.
+	  Provides HCI VS commands to set and get the current Tx
+	  power on an individual role/connection basis.
+
+comment "BLE Controller features"
+
+if BT_CONN
+
+config BT_CTLR_LE_ENC
+	bool "LE Encryption"
+	depends on BT_CTLR_LE_ENC_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth v4.0 LE Encryption feature in the
+	  Controller.
+
+config BT_CTLR_CONN_PARAM_REQ
+	bool "Connection Parameter Request"
+	depends on BT_CTLR_CONN_PARAM_REQ_SUPPORT
+	select BT_CTLR_EXT_REJ_IND
+	default y
+	help
+	  Enable support for Bluetooth v4.1 Connection Parameter Request feature
+	  in the Controller.
+
+config BT_CTLR_EXT_REJ_IND
+	bool "Extended Reject Indication"
+	depends on BT_CTLR_EXT_REJ_IND_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth v4.1 Extended Reject Indication feature
+	  in the Controller.
+
+config BT_CTLR_SLAVE_FEAT_REQ
+	bool "Slave-initiated Features Exchange"
+	depends on BT_CTLR_SLAVE_FEAT_REQ_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth v4.1 Slave-initiated Features Exchange
+	  feature in the Controller.
+
+config BT_CTLR_LE_PING
+	bool "LE Ping"
+	depends on BT_CTLR_LE_ENC
+	default y
+	help
+	  Enable support for Bluetooth v4.1 LE Ping feature in the Controller.
+
+config BT_CTLR_DATA_LENGTH
+	# Hidden option to enable support for Bluetooth v4.2 LE Data Length
+	# Update procedure in the Controller.
+	bool
+	depends on BT_DATA_LEN_UPDATE && BT_CTLR_DATA_LEN_UPDATE_SUPPORT
+	default y
+
+config BT_CTLR_DATA_LENGTH_MAX
+	int "Maximum data length supported"
+	depends on BT_CTLR_DATA_LENGTH
+	default 27
+	range 27 251
+	help
+	  Set the maximum data length of PDU supported in the Controller.
+
+config BT_CTLR_PHY
+	# Hidden option to enable support for Bluetooth 5.0 PHY Update
+	# Procedure in the Controller.
+	bool
+	depends on BT_PHY_UPDATE && BT_CTLR_PHY_UPDATE_SUPPORT
+	select BT_CTLR_EXT_REJ_IND
+	default y
+
+config BT_CTLR_MIN_USED_CHAN
+	bool "Minimum Number of Used Channels"
+	depends on BT_CTLR_MIN_USED_CHAN_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth 5.0 Minimum Number of Used Channels
+	  Procedure in the Controller.
+
+config BT_CTLR_CONN_RSSI
+	bool "Connection RSSI"
+	depends on BT_CTLR_CONN_RSSI_SUPPORT
+	default y if BT_HCI_RAW
+	help
+	  Enable connection RSSI measurement.
+
+endif # BT_CONN
+
+config BT_CTLR_FILTER
+	bool "Device Whitelist Support"
+	default y
+	help
+	  Enable support for controller device whitelist feature
+
+config BT_CTLR_PRIVACY
+	bool "LE Controller-based Privacy"
+	depends on BT_CTLR_PRIVACY_SUPPORT
+	default y
+	select BT_CTLR_FILTER if BT_LL_SW_SPLIT
+	select BT_RPA
+	help
+	  Enable support for Bluetooth v4.2 LE Controller-based Privacy feature
+	  in the Controller.
+
+config BT_CTLR_RL_SIZE
+	int "LE Controller-based Privacy Resolving List size"
+	depends on BT_CTLR_PRIVACY
+	default 8
+	range 1 8 if SOC_COMPATIBLE_NRF
+	range 1 8 if SOC_OPENISA_RV32M1_RISCV32
+	help
+	  Set the size of the Resolving List for LE Controller-based Privacy.
+	  On nRF5x-based controllers, the hardware imposes a limit of 8 devices.
+	  On OpenISA-based controllers, the hardware imposes a limit of 8 devices.
+
+config BT_CTLR_EXT_SCAN_FP
+	bool "LE Extended Scanner Filter Policies"
+	depends on BT_OBSERVER && BT_CTLR_EXT_SCAN_FP_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth v4.2 LE Extended Scanner Filter Policies
+	  in the Controller.
+
+config BT_CTLR_PHY_2M
+	bool "2Mbps PHY Support"
+	depends on (BT_CTLR_PHY || BT_CTLR_ADV_EXT) && BT_CTLR_PHY_2M_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth 5.0 2Mbps PHY in the Controller.
+
+config BT_CTLR_PHY_CODED
+	bool "Coded PHY Support"
+	depends on (BT_CTLR_PHY || BT_CTLR_ADV_EXT) && BT_CTLR_PHY_CODED_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth 5.0 Coded PHY in the Controller.
+
+config BT_CTLR_CHAN_SEL_2
+	bool "Channel Selection Algorithm #2"
+	depends on (BT_CONN || BT_CTLR_ADV_PERIODIC || BT_CTLR_SYNC_PERIODIC) && BT_CTLR_CHAN_SEL_2_SUPPORT
+	default y
+	help
+	  Enable support for Bluetooth 5.0 LE Channel Selection Algorithm #2 in
+	  the Controller.
+
+config BT_CTLR_ADV_EXT
+	bool "LE Advertising Extensions" if !BT_LL_SW_SPLIT
+	depends on BT_CTLR_ADV_EXT_SUPPORT
+	select BT_CTLR_SCAN_REQ_NOTIFY if BT_LL_SW_SPLIT && BT_BROADCASTER
+	# Enable by default for BT_LL_SW_SPLIT when "LE Advertising Set Terminated event" is implemented
+	default y if BT_EXT_ADV && !BT_LL_SW_SPLIT
+	help
+	  Enable support for Bluetooth 5.0 LE Advertising Extensions in the
+	  Controller.
+
+config BT_CTLR_ADV_EXT
+	prompt "LE Advertising Extensions [EXPERIMENTAL]" if BT_LL_SW_SPLIT
+
+if BT_CTLR_ADV_EXT
+
+config BT_CTLR_ADV_SET
+	int "LE Advertising Extensions Sets"
+	depends on BT_BROADCASTER
+	range 1 64
+	default BT_EXT_ADV_MAX_ADV_SET if BT_EXT_ADV
+	help
+	  Maximum supported advertising sets.
+
+config BT_CTLR_ADV_PERIODIC
+	bool "LE Periodic Advertising in Advertising State" if !BT_LL_SW_SPLIT
+	depends on BT_BROADCASTER && BT_CTLR_ADV_PERIODIC_SUPPORT
+	select BT_CTLR_CHAN_SEL_2
+	default y if BT_PER_ADV
+	help
+	  Enable support for Bluetooth 5.0 LE Periodic Advertising in the
+	  Controller.
+
+config BT_CTLR_ADV_PERIODIC
+	bool "LE Periodic Advertising in Advertising State [EXPERIMENTAL]" if BT_LL_SW_SPLIT
+
+config BT_CTLR_SYNC_PERIODIC
+	bool "LE Periodic Advertising in Synchronization State" if !BT_LL_SW_SPLIT
+	depends on BT_OBSERVER && BT_CTLR_SYNC_PERIODIC_SUPPORT
+	select BT_CTLR_CHAN_SEL_2
+	default y if BT_PER_ADV_SYNC
+	help
+	  Enable support for Bluetooth 5.0 LE Periodic Advertising in
+	  Synchronization state in the Controller.
+
+config BT_CTLR_SYNC_PERIODIC
+	bool "LE Periodic Advertising in Synchronization State [EXPERIMENTAL]" if BT_LL_SW_SPLIT
+
+config BT_CTLR_ADV_ISO
+	bool "LE Broadcast Isochronous Channel advertising" if !BT_LL_SW_SPLIT
+	depends on BT_BROADCASTER && BT_CTLR_ADV_ISO_SUPPORT
+	select BT_CTLR_ADV_PERIODIC
+	help
+	  Enable support for Bluetooth 5.2 LE Isochronous Advertising in the
+	  Controller.
+
+config BT_CTLR_ADV_ISO
+	bool "LE Broadcast Isochronous Channel advertising [EXPERIMENTAL]" if BT_LL_SW_SPLIT
+
+config BT_CTLR_SYNC_ISO
+	bool "LE Broadcast Isochronous Channel advertising sync" if !BT_LL_SW_SPLIT
+	depends on BT_BROADCASTER && BT_CTLR_ADV_ISO_SUPPORT
+	select BT_CTLR_SYNC_PERIODIC
+	help
+	  Enable support for Bluetooth 5.2 LE Isochronous Advertising sync in
+	  the Controller.
+
+config BT_CTLR_SYNC_ISO
+	bool "LE Broadcast Isochronous Channel advertising sync [EXPERIMENTAL]" if BT_LL_SW_SPLIT
+
+config BT_CTLR_ADV_DATA_LEN_MAX
+	int "Maximum Advertising Data Length"
+	range 31 1650
+	help
+	  Maximum Extended Advertising Data Length.
+
+endif # BT_CTLR_ADV_EXT
+
+config BT_CTLR_DTM
+	bool
+	help
+	  Enable support for Direct Test Mode in the Controller.
+
+config BT_CTLR_DTM_HCI
+	bool "Direct Test Mode over HCI"
+	depends on BT_CTLR_DTM_HCI_SUPPORT
+	select BT_CTLR_DTM
+	help
+	  Enable support for Direct Test Mode over the HCI transport.
+
+config BT_CTLR_SMI_RX
+	bool "Stable modulation index - Receiver"
+	depends on BT_CTLR_SMI_SUPPORT
+	help
+	  Enable support for Bluetooth 5.0 SMI RX in the Controller.
+
+config BT_CTLR_SMI_TX
+	bool "Stable modulation index - Transmitter"
+	depends on BT_CTLR_SMI_SUPPORT
+	help
+	  Enable support for Bluetooth 5.0 SMI TX in the Controller.
+
+config BT_CTLR_SMI_TX_SETTING
+	bool "Stable modulation index - Transmitter as setting"
+	depends on BT_CTLR_SMI_TX && BT_CTLR_SETTINGS
+	help
+	  Enable support for Bluetooth 5.0 SMI TX through a system setting.
+
+source "subsys/bluetooth/controller/Kconfig.ll_sw_split"
+
+config BT_CTLR_ASSERT_HANDLER
+	bool "Application Defined Assertion Handler"
+	help
+	  This option enables an application-defined sink for the
+	  controller assertion mechanism. This must be defined in
+	  application code as void \"bt_ctlr_assert_handle(char \*, int)\"
+	  and will be invoked whenever the controller code encounters
+	  an unrecoverable error.
+
+endif # BT_CTLR
+
+config BT_CTLR_DEBUG_PINS_CPUAPP
+	bool "Bluetooth Controller Debug Pins"
+	depends on BOARD_NRF5340PDK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP
+	help
+	  Route debug GPIO toggling for the BLE Controller. Enable this when
+	  using Bluetooth Controller Debug Pins in co-processor and the main
+	  processor needs to setup and/or route the signals.
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig.ll_sw_split
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig.ll_sw_split	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/Kconfig.ll_sw_split	(working copy)
@@ -0,0 +1,611 @@
+# Zephyr Bluetooth Controller configuration options
+
+# Copyright (c) 2016-2017 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+if BT_LL_SW_SPLIT
+
+config BT_LLL_VENDOR_NORDIC
+	bool "Use Nordic LLL"
+	depends on SOC_COMPATIBLE_NRF
+	select BT_HAS_HCI_VS
+	select ENTROPY_NRF5_RNG
+	select ENTROPY_NRF5_BIAS_CORRECTION
+	select BT_CTLR_LE_ENC_SUPPORT if !BT_CTLR_DATA_LENGTH_CLEAR && \
+					 !BT_CTLR_PHY_2M_NRF
+	select BT_CTLR_CONN_PARAM_REQ_SUPPORT
+	select BT_CTLR_EXT_REJ_IND_SUPPORT
+	select BT_CTLR_SLAVE_FEAT_REQ_SUPPORT
+	select BT_CTLR_DATA_LEN_UPDATE_SUPPORT if HAS_HW_NRF_CCM_LFLEN_8BIT || \
+						  BT_CTLR_DATA_LENGTH_CLEAR
+	select BT_CTLR_PRIVACY_SUPPORT if !SOC_SERIES_NRF51X
+	select BT_CTLR_EXT_SCAN_FP_SUPPORT
+
+	select BT_CTLR_PHY_2M_SUPPORT if HAS_HW_NRF_RADIO_BLE_2M || \
+					 BT_CTLR_PHY_2M_NRF
+	select BT_CTLR_PHY_CODED_SUPPORT if HAS_HW_NRF_RADIO_BLE_CODED
+	select BT_CTLR_PHY_UPDATE_SUPPORT if BT_CTLR_PHY_2M_SUPPORT || \
+					     BT_CTLR_PHY_CODED_SUPPORT
+	select BT_CTLR_ADV_EXT_SUPPORT
+	select BT_CTLR_ADV_PERIODIC_SUPPORT
+	select BT_CTLR_SYNC_PERIODIC_SUPPORT
+	select BT_CTLR_CHAN_SEL_2_SUPPORT
+	select BT_CTLR_MIN_USED_CHAN_SUPPORT
+	select BT_CTLR_DTM_HCI_SUPPORT
+	select BT_CTLR_CONN_RSSI_SUPPORT
+
+	select BT_CTLR_XTAL_ADVANCED_SUPPORT
+	select BT_CTLR_SCHED_ADVANCED_SUPPORT
+	select BT_CTLR_TIFS_HW_SUPPORT
+	default y
+	help
+	  Use Nordic Lower Link Layer implementation.
+
+config BT_LLL_VENDOR_OPENISA
+	bool "Use OpenISA LLL"
+	depends on SOC_OPENISA_RV32M1_RISCV32
+	select BT_CTLR_PHY_UPDATE_SUPPORT
+	select BT_CTLR_EXT_REJ_IND_SUPPORT
+	select BT_HAS_HCI_VS
+	select BT_CTLR_LE_ENC_SUPPORT if !BT_CTLR_DATA_LENGTH_CLEAR
+	select BT_CTLR_PRIVACY_SUPPORT
+	default y
+	help
+	  Use OpenISA Lower Link Layer implementation.
+
+config BT_CTLR_XTAL_ADVANCED_SUPPORT
+	bool
+
+config BT_CTLR_SCHED_ADVANCED_SUPPORT
+	bool
+
+config BT_CTLR_TIFS_HW_SUPPORT
+	bool
+
+config BT_CTLR_RX_PRIO_STACK_SIZE
+	# Controller's Co-Operative high priority Rx thread stack size.
+	int "High priority Rx thread stack size"
+	default 448
+
+config BT_CTLR_SETTINGS
+	bool "Settings System"
+	depends on SETTINGS
+	help
+	  Enable use of settings system in controller.
+
+config BT_CTLR_VERSION_SETTINGS
+	bool "Version Settings"
+	depends on BT_CTLR_SETTINGS
+	help
+	  Make the controller's Company Id and Subversion Number configurable
+	  through settings system.
+
+config BT_CTLR_COMPANY_ID
+	hex "Controller Company Id"
+	default BT_COMPANY_ID
+	range 0x0000 0xFFFF
+	help
+	  Set the Bluetooth Company Identifier that will be used in
+	  the VERSION_IND PDU. Uses BT_COMPANY_ID by default, although
+	  silicon vendors and hardware manufacturers can set their own
+	  Company Identifier for the controller. The full list of Bluetooth
+	  Company Identifiers can be found here:
+	  https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
+
+config BT_CTLR_SUBVERSION_NUMBER
+	hex "Subversion Number"
+	default 0xFFFF
+	range 0x0000 0xFFFF
+	help
+	  Set the Subversion Number that will be used in VERSION_IND PDU.
+
+config BT_CTLR_ADVANCED_FEATURES
+	bool "Show advanced features"
+	help
+	  Makes advanced features visible to controller developers.
+
+menu "Advanced features"
+	visible if BT_CTLR_ADVANCED_FEATURES
+
+config BT_CTLR_SW_DEFERRED_PRIVACY
+	bool "LE Controller-based Software Privacy"
+	depends on BT_CTLR_PRIVACY
+	help
+	  Enable support for software based deferred privacy calculations.
+
+config BT_CTLR_RPA_CACHE_SIZE
+	int "LE Controller-based Software Privacy Resolving List size"
+	depends on BT_CTLR_SW_DEFERRED_PRIVACY
+	default 8
+	range 1 64
+	help
+	  Set the size of the Known Unknown Resolving List for LE
+	  Controller-based Software deferred Privacy.
+
+config BT_CTLR_DATA_LENGTH_CLEAR
+	bool "Data Length Support (Cleartext only)"
+	depends on SOC_SERIES_NRF51X
+	help
+	  Enable support for Bluetooth v4.2 LE Data Length Update procedure, up to
+	  251 byte cleartext payloads in the Controller. Encrypted connections
+	  are not supported.
+
+
+config BT_CTLR_PHY_2M_NRF
+	bool "2Mbps Nordic Semiconductor PHY Support (Cleartext only)"
+	depends on SOC_SERIES_NRF51X
+	select BT_CTLR_PHY_2M
+	help
+	  Enable support for Nordic Semiconductor proprietary 2Mbps PHY in the
+	  Controller. Encrypted connections are not supported.
+
+config BT_CTLR_ADV_AUX_SET
+	int "LE Extended Advertising Auxiliary Sets"
+	depends on BT_BROADCASTER && BT_CTLR_ADV_EXT
+	range 1 BT_CTLR_ADV_SET if BT_CTLR_ADV_PERIODIC
+	range 0 BT_CTLR_ADV_SET
+	default 1 if BT_CTLR_ADV_PERIODIC
+	default BT_CTLR_ADV_SET
+	help
+	  Maximum supported advertising auxiliary channel sets.
+
+config BT_CTLR_ADV_SYNC_SET
+	int "LE Periodic Advertising Sets"
+	depends on BT_CTLR_ADV_PERIODIC
+	range 1 BT_CTLR_ADV_AUX_SET
+	default 1
+	help
+	  Maximum supported periodic advertising sets.
+
+config BT_CTRL_ADV_ADI_IN_SCAN_RSP
+	bool "Include ADI in AUX_SCAN_RSP PDU"
+	depends on BT_BROADCASTER && BT_CTLR_ADV_EXT
+	help
+	  Enable ADI field in AUX_SCAN_RSP PDU
+
+config BT_CTLR_SCAN_AUX_SET
+	int "LE Extended Scanning Auxiliary Sets"
+	depends on BT_OBSERVER && BT_CTLR_ADV_EXT
+	range 1 64
+	default 1
+	help
+	  Maximum supported auxiliary channel scan sets.
+
+config BT_CTLR_SCAN_SYNC_SET
+	int "LE Periodic Sync Sets"
+	depends on BT_CTLR_SYNC_PERIODIC
+	range 1 64
+	default 1
+	help
+	  Maximum supported periodic sync sets.
+
+config BT_CTLR_ZLI
+	bool "Use Zero Latency IRQs"
+	depends on ZERO_LATENCY_IRQS
+	help
+	  Enable support for use of Zero Latency IRQ feature. Note, applications
+	  shall not use Zero Latency IRQ themselves when this option is selected,
+	  else will impact controller stability.
+
+config BT_CTLR_OPTIMIZE_FOR_SPEED
+	prompt "Optimize for Speed" if !(SOC_SERIES_NRF51X && BT_CTLR_LE_ENC)
+	bool
+	default y if BT_CTLR_LE_ENC
+	help
+	  Optimize compilation of controller for execution speed.
+
+config BT_CTLR_XTAL_ADVANCED
+	bool "Advanced event preparation"
+	depends on BT_CTLR_XTAL_ADVANCED_SUPPORT
+	default y
+	help
+	  Enables advanced event preparation offset ahead of radio tx/rx, taking
+	  into account predictive processing time requirements in preparation to
+	  the event, like control procedure handling and CPU execution speeds.
+	  Crystal oscillator is retained between closely spaced consecutive
+	  radio events to reduce the overall number of crystal settling current
+	  consumptions.
+
+	  This feature maximizes radio utilization in an average role event
+	  timeslice when they are closely spaced by using a reduced offset
+	  between preparation and radio event.
+
+	  By disabling this feature, the controller will use a constant offset
+	  between the preparation and radio event. The controller will toggle
+	  crystal oscillator between two closely spaced radio events leading to
+	  higher average current due to increased number of crystal settling
+	  current consumptions.
+
+config BT_CTLR_XTAL_THRESHOLD
+	int "Crystal shutdown threshold in uS"
+	depends on BT_CTLR_XTAL_ADVANCED
+	default 1500
+	help
+	  Configure the optimal delta in micro seconds between two consecutive
+	  radio events, event done to next preparation, below which (active
+	  clock) crystal will be retained. This value is board dependent.
+
+config BT_CTLR_SCHED_ADVANCED
+	bool "Advanced scheduling"
+	depends on (BT_MAX_CONN != 0) && BT_CTLR_SCHED_ADVANCED_SUPPORT
+	default y if !(BT_PERIPHERAL && !BT_CENTRAL)
+	help
+	  Enable non-overlapping placement of observer, initiator and master
+	  roles in timespace. Uses window offset in connection updates and uses
+	  connection parameter request in slave role to negotiate
+	  non-overlapping placement with active master roles to avoid slave
+	  roles drifting into active master roles in the local controller.
+
+	  This feature maximizes the average data transmission amongst active
+	  concurrent master and slave connections while other observer,
+	  initiator, master or slave roles are active in the local controller.
+
+	  Disabling this feature will lead to overlapping role in timespace
+	  leading to skipped events amongst active roles.
+
+config BT_CTLR_LLL_PRIO
+	int "Lower Link Layer (Radio) IRQ priority"
+	range 0 3 if SOC_SERIES_NRF51X
+	range 0 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X)
+	default 0
+	help
+	  The interrupt priority for event preparation and radio IRQ.
+
+config BT_CTLR_ULL_HIGH_PRIO
+	int "Upper Link Layer High IRQ priority"
+	range BT_CTLR_LLL_PRIO 3 if SOC_SERIES_NRF51X
+	range BT_CTLR_LLL_PRIO 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X)
+	default BT_CTLR_LLL_PRIO
+	help
+	  The interrupt priority for Ticker's Worker IRQ and Upper Link Layer
+	  higher priority functions.
+
+config BT_CTLR_ULL_LOW_PRIO
+	int "Upper Link Layer Low IRQ priority"
+	range BT_CTLR_ULL_HIGH_PRIO 3 if SOC_SERIES_NRF51X
+	range BT_CTLR_ULL_HIGH_PRIO 6 if (SOC_SERIES_NRF52X || SOC_SERIES_NRF53X)
+	default BT_CTLR_ULL_HIGH_PRIO
+	help
+	  The interrupt priority for Ticker's Job IRQ and Upper Link Layer
+	  lower priority functions.
+
+config BT_CTLR_LOW_LAT
+	bool "Low latency non-negotiating event preemption"
+	default y if SOC_SERIES_NRF51X
+	help
+	  Use low latency non-negotiating event preemption. This reduces
+	  Radio ISR latencies by the controller event scheduling framework.
+	  Consequently, this reduces on-air radio utilization due to redundant
+	  radio state switches.
+
+config BT_CTLR_LOW_LAT_ULL
+	prompt "Low latency ULL"
+	bool
+	depends on BT_CTLR_LOW_LAT
+	default y
+	help
+	  Low latency ULL implementation that uses tailchaining instead of while
+	  loop to demux rx messages from LLL.
+
+config BT_CTLR_CONN_META
+	prompt "Enable connection meta data extension"
+	bool
+	help
+	  Enables vendor specific per-connection meta data as part of the
+	  LLL connection object.
+
+config BT_CTLR_RX_PDU_META
+	prompt "Enable RX pdu meta data"
+	bool
+
+config BT_CTLR_RADIO_ENABLE_FAST
+	bool "Use tTXEN/RXEN,FAST ramp-up"
+	depends on SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X
+	default y
+	help
+	  Enable use of fast radio ramp-up mode.
+
+config BT_CTLR_TIFS_HW
+	bool "H/w Accelerated tIFS Trx switching"
+	depends on !BT_CTLR_RADIO_ENABLE_FAST && BT_CTLR_TIFS_HW_SUPPORT
+	default y
+	help
+	  Enable use of hardware accelerated tIFS Trx switching.
+
+config BT_CTLR_SW_SWITCH_SINGLE_TIMER
+	bool "Single TIMER tIFS Trx SW switching"
+	depends on (!BT_CTLR_TIFS_HW) && (SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X)
+	help
+	  Implement the tIFS Trx SW switch with the same TIMER
+	  instance, as the one used for BLE event timing. Requires
+	  SW switching be enabled. Using a single TIMER:
+	  (+) frees up one TIMER instance
+	  (+) removes jitter for HCTO implementation
+	  (-) introduces drifting to the absolute time inside BLE
+	  events, that increases linearly with the number of
+	  packets exchanged in the event
+	  (-) makes it impossible to use most of the pre-programmed
+	  PPI channels for the controller, resulting in 4 channels
+	  less left for other uses
+
+config BT_CTLR_PARAM_CHECK
+	bool "Enable HCI Command Parameter checking"
+	default y if BT_HCI_RAW
+	help
+	  Enable code checking HCI Command Parameters. This is not needed in
+	  combined host plus controller builds, saving some code space.
+
+if BT_CONN
+
+config BT_CTLR_FAST_ENC
+	bool "Fast Encryption Setup"
+	depends on BT_CTLR_LE_ENC
+	default y if BT_HCI_RAW
+	help
+	  Enable connection encryption setup in 3 connection intervals.
+	  Peripheral will respond to Encryption Request with Encryption Response
+	  in the same connection interval, and also, will respond with Start
+	  Encryption Response PDU in the 3rd connection interval, hence
+	  completing encryption setup in 3 connection intervals. Encrypted data
+	  would be transmitted as fast as in 3rd connection interval from the
+	  connection establishment.
+	  Maximum CPU time in Radio ISR will increase if this feature is
+	  selected.
+
+config BT_CTLR_LLCP_CONN
+	int "Number of connections with worst-case overlapping procedures"
+	default BT_MAX_CONN
+	range 1 BT_MAX_CONN
+	help
+	  Set the number connections for which worst-case buffer requirements
+	  for LLCP procedures must be met. Executing LLCP procedures on
+	  more than this number of connections simultaneously may cause
+	  instabilities.
+
+config BT_CTLR_LLID_DATA_START_EMPTY
+	bool "Handle zero length L2CAP start frame"
+	default y if BT_HCI_RAW
+	help
+	  Handle zero length L2CAP start frame.
+
+config BT_CTLR_RX_ENQUEUE_HOLD
+	bool "Procedure Complete after on-air instant"
+	default y if BT_HCI_RAW
+	help
+	  Hold enqueue of Procedure Complete events with instant until after the
+	  on-air instant is reached.
+
+config BT_CTLR_TX_RETRY_DISABLE
+	bool "Disable Tx Retry"
+	help
+	  Avoid retransmission of a PDU if peer device Nack-ed a transmission
+	  in the current connection event, close the connection event so as to
+	  save current consumption on retries (in case peer has no buffers to
+	  receive new PDUs).
+
+	  Enabling this will lower power consumption, but increase transmission
+	  latencies by one connection interval as the next attempt to send a PDU
+	  would happen in the next connection event instead of repeated retries
+	  in the current connection event.
+
+config BT_CTLR_THROUGHPUT
+	bool "Measure incoming Tx throughput"
+	help
+	  Measure incoming Tx throughput and log the results.
+
+config BT_CTLR_FORCE_MD_COUNT
+	int "Forced MD bit count" if !BT_CTLR_FORCE_MD_AUTO
+	range 0 255
+	default 1 if BT_CTLR_FORCE_MD_AUTO
+	default 0
+	help
+	  No. of times to force MD bit to be set in Tx PDU after a successful
+	  transmission of non-empty PDU.
+
+	  This will prolong the connection event to from being closed in cases
+	  where applications want to send data in same connection event but are
+	  slow in providing new Tx data.
+
+config BT_CTLR_FORCE_MD_AUTO
+	bool "Forced MD bit automatic calculation"
+	select BT_CTLR_THROUGHPUT
+	default y if BT_HCI_RAW
+	help
+	  Force MD bit in transmitted PDU based on runtime incoming transmit
+	  data throughput.
+
+config BT_CTLR_CONN_RSSI_EVENT
+	bool "Connection RSSI event"
+	depends on BT_CTLR_CONN_RSSI
+	help
+	  Generate events for connection RSSI measurement.
+
+endif # BT_CONN
+
+config BT_CTLR_ADV_INDICATION
+	bool "Advertisement indications"
+	depends on BT_BROADCASTER
+	help
+	  Generate events indicating on air advertisement events.
+
+config BT_CTLR_SCAN_REQ_NOTIFY
+	bool "Scan Request Notifications"
+	depends on BT_BROADCASTER
+	help
+	  Generate events notifying the on air scan requests received.
+
+config BT_CTLR_SCAN_REQ_RSSI
+	bool "Measure Scan Request RSSI"
+	depends on BT_CTLR_SCAN_REQ_NOTIFY
+	help
+	  Measure RSSI of the on air scan requests received.
+
+config BT_CTLR_SCAN_INDICATION
+	bool "Scanner indications"
+	depends on BT_OBSERVER
+	help
+	  Generate events indicating on air scanner events.
+
+config BT_CTLR_SCAN_UNRESERVED
+	bool "Unreserved scan window"
+	depends on BT_OBSERVER
+	default y if BT_MESH
+	help
+	  Scanner will not use time space reservation for scan window when in
+	  continuous scan mode.
+
+config BT_MAYFLY_YIELD_AFTER_CALL
+	bool "Yield from mayfly thread after first call"
+	default y
+	help
+	  Only process one mayfly callback per invocation (legacy behavior).
+	  If set to 'n', all pending mayflies for callee are executed before
+	  yielding
+
+config BT_TICKER_COMPATIBILITY_MODE
+	bool "Ticker compatibility mode"
+	default y if SOC_SERIES_NRF51X
+	help
+	  This option enables legacy ticker scheduling which defers overlapping
+	  ticker node timeouts and thereby prevents ticker interrupts during
+	  radio RX/TX. Enabling this option disables the ticker priority- and
+	  'must expire' features.
+
+config BT_TICKER_EXT
+	bool "Ticker extensions"
+	depends on !BT_TICKER_COMPATIBILITY_MODE
+	default y
+	help
+	  This option enables ticker extensions such as re-scheduling of
+	  ticker nodes with slot_window set to non-zero. Ticker extensions
+	  are invoked by using available '_ext' versions of ticker interface
+	  functions.
+
+config BT_CTLR_USER_EXT
+	prompt "Enable proprietary extensions in Controller"
+	bool
+	help
+	  Catch-all for enabling proprietary event types in Controller behavior.
+
+config BT_CTLR_USER_EVT_RANGE
+	int "Range of event constants reserved for proprietary event types"
+	depends on BT_CTLR_USER_EXT
+	default 5
+	range 0 10
+	help
+	  Number of event types reserved for proprietary use. The range
+	  is typically used when BT_CTLR_USER_EXT is in use.
+
+config BT_CTLR_USER_TICKER_ID_RANGE
+	int "Range of ticker id constants reserved for proprietary ticker nodes"
+	depends on BT_CTLR_USER_EXT
+	default 0
+	range 0 10
+	help
+	  Number of ticker ids reserved for proprietary use. The range
+	  is typically used when BT_CTLR_USER_EXT is in use.
+
+config BT_RX_USER_PDU_LEN
+	int "Maximum supported proprietary PDU buffer length"
+	depends on BT_CTLR_USER_EXT
+	default 2
+	range 2 255
+	help
+	  Maximum data size for each proprietary PDU. This size includes link layer
+	  header and payload. It does not account for HCI event headers as these
+	  PDUs are assumed to not go across HCI.
+
+endmenu
+
+comment "BLE Controller hardware configuration"
+
+menuconfig BT_CTLR_GPIO_PA
+	bool "Power Amplifier GPIO interface"
+	depends on !SOC_SERIES_NRF51X
+	help
+	  Enable GPIO interface to a Power Amplifier. This allows hardware
+	  designs using PA to let the Controller toggle their state based on
+	  radio activity.
+
+if BT_CTLR_GPIO_PA
+
+config BT_CTLR_GPIO_PA_PIN
+	int "Power Amplifier GPIO pin number"
+	range 0 47 if SOC_NRF52840
+	range 0 31
+	help
+	  GPIO Pin number connected to a Power Amplifier.
+
+config BT_CTLR_GPIO_PA_POL_INV
+	bool "Inverted polarity for the PA pin"
+	help
+	  Enable inverted polarity (active low) for the PA pin.
+
+config BT_CTLR_GPIO_PA_OFFSET
+	int "Time from PA ON to Tx ready"
+	default 5
+	range 0 10
+	help
+	  Time before Tx ready to turn on PA.
+
+endif # BT_CTLR_GPIO_PA
+
+menuconfig BT_CTLR_GPIO_LNA
+	bool "Low Noise Amplifier GPIO interface"
+	depends on !SOC_SERIES_NRF51X
+	help
+	  Enable GPIO interface to a Low Noise Amplifier. This allows hardware
+	  designs using LNAs to let the Controller toggle their state based on
+	  radio activity.
+
+if BT_CTLR_GPIO_LNA
+
+config BT_CTLR_GPIO_LNA_PIN
+	int "Low Noise Amplifier GPIO pin number"
+	range 0 47 if SOC_NRF52840
+	range 0 31
+	help
+	  GPIO Pin number connected to a Low Noise Amplifier.
+
+config BT_CTLR_GPIO_LNA_POL_INV
+	bool "Inverted polarity for the LNA pin"
+	help
+	  Enable inverted polarity (active low) for the LNA pin.
+
+config BT_CTLR_GPIO_LNA_OFFSET
+	int "Time from LNA ON to Rx ready"
+	default 5
+	range 0 10
+	help
+	  Time before Rx ready to turn on LNA.
+
+endif # BT_CTLR_GPIO_LNA
+
+config BT_CTLR_PA_LNA_GPIOTE_CHAN
+	# Hidden "nRF5 GPIO PA/LNA GPIOTE Channel"
+	int
+	depends on SOC_FAMILY_NRF && (BT_CTLR_GPIO_PA || BT_CTLR_GPIO_LNA)
+	default 3 if PWM_NRF5_SW
+	default 0
+	help
+	  Select the nRF5 GPIOTE channel to use for PA/LNA GPIO feature.
+
+comment "BLE Controller debug configuration"
+
+config BT_CTLR_PROFILE_ISR
+	bool "Profile radio ISR"
+	help
+	  Turn on measurement of radio ISR latency, CPU usage and generation of
+	  controller event with these profiling data. The controller event
+	  contains current, minimum and maximum ISR entry latencies; and
+	  current, minimum and maximum ISR CPU use in micro-seconds.
+
+config BT_CTLR_DEBUG_PINS
+	bool "Bluetooth Controller Debug Pins"
+	depends on BOARD_NRF51DK_NRF51422 || BOARD_NRF52DK_NRF52832 || BOARD_NRF52DK_NRF52810 || BOARD_NRF52840DK_NRF52840 || BOARD_NRF5340PDK_NRF5340_CPUNET || BOARD_NRF5340DK_NRF5340_CPUNET || BOARD_RV32M1_VEGA
+	help
+	  Turn on debug GPIO toggling for the BLE Controller. This is useful
+	  when debugging with a logic analyzer or profiling certain sections of
+	  the code.
+
+endif # BT_LL_SW_SPLIT
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/crypto/crypto.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/crypto/crypto.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/crypto/crypto.c	(working copy)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_crypto
+#include "common/log.h"
+
+#include "util/memq.h"
+
+#include "hal/ecb.h"
+#include "lll.h"
+
+int bt_rand(void *buf, size_t len)
+{
+	return lll_csrand_get(buf, len);
+}
+
+int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16])
+{
+	BT_DBG("key %s", bt_hex(key, 16));
+	BT_DBG("plaintext %s", bt_hex(plaintext, 16));
+
+	ecb_encrypt(key, plaintext, enc_data, NULL);
+
+	BT_DBG("enc_data %s", bt_hex(enc_data, 16));
+
+	return 0;
+}
+
+int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16])
+{
+	BT_DBG("key %s", bt_hex(key, 16));
+	BT_DBG("plaintext %s", bt_hex(plaintext, 16));
+
+	ecb_encrypt_be(key, plaintext, enc_data);
+
+	BT_DBG("enc_data %s", bt_hex(enc_data, 16));
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ccm.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ccm.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ccm.h	(working copy)
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct ccm {
+	uint8_t  key[16];
+	uint64_t counter;
+	uint8_t  direction:1;
+	uint8_t  resv1:7;
+	uint8_t  iv[8];
+} __packed;
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cntr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cntr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cntr.h	(working copy)
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void cntr_init(void);
+uint32_t cntr_start(void);
+uint32_t cntr_stop(void);
+uint32_t cntr_cnt_get(void);
+void cntr_cmp_set(uint8_t cmp, uint32_t value);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cpu.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cpu.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/cpu.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/cpu_vendor_hal.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/debug.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/debug.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/debug.h	(working copy)
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef CONFIG_BT_CTLR_ASSERT_HANDLER
+void bt_ctlr_assert_handle(char *file, uint32_t line);
+#define LL_ASSERT(cond) if (!(cond)) { \
+				bt_ctlr_assert_handle(__FILE__, \
+						      __LINE__); \
+			}
+#else
+#define LL_ASSERT(cond) BT_ASSERT(cond)
+#endif
+
+#include "hal/debug_vendor_hal.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ecb.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ecb.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ecb.h	(working copy)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+typedef void (*ecb_fp) (uint32_t status, uint8_t *cipher_be, void *context);
+
+struct ecb {
+	uint8_t   in_key_be[16];
+	uint8_t   in_clear_text_be[16];
+	uint8_t   out_cipher_text_be[16];
+	/* if not null reverse copy into in_key_be */
+	uint8_t   *in_key_le;
+	/* if not null reverse copy into in_clear_text_be */
+	uint8_t   *in_clear_text_le;
+	ecb_fp fp_ecb;
+	void   *context;
+};
+
+void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
+		    uint8_t * const cipher_text_be);
+void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
+		 uint8_t * const cipher_text_le, uint8_t * const cipher_text_be);
+uint32_t ecb_encrypt_nonblocking(struct ecb *ecb);
+void isr_ecb(void *param);
+
+uint32_t ecb_ut(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/radio.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/radio.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/radio.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/radio_vendor_hal.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/swi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/swi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/swi.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/swi_vendor_hal.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ticker.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ticker.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hal/ticker.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/ticker_vendor_hal.h"
+
+uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id);
+void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+				void *instance);
+void hal_ticker_instance0_trigger_set(uint32_t value);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci.c	(working copy)
@@ -0,0 +1,4832 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <zephyr/types.h>
+#include <string.h>
+#include <version.h>
+
+#include <soc.h>
+#include <toolchain.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_vs.h>
+#include <bluetooth/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <drivers/bluetooth/hci_driver.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include "util/util.h"
+#include "util/memq.h"
+#include "hal/ecb.h"
+#include "hal/ccm.h"
+#include "ll_sw/pdu.h"
+#include "ll_sw/lll.h"
+#include "ll_sw/lll_scan.h"
+#include "ll_sw/lll_sync.h"
+#include "ll_sw/lll_conn.h"
+#include "ll_sw/ull_scan_types.h"
+#include "ll_sw/ull_sync_types.h"
+#include "ll_sw/ull_conn_types.h"
+#include "ll.h"
+#include "ll_feat.h"
+#include "ll_settings.h"
+#include "hci_internal.h"
+#include "hci_vendor.h"
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+#include "ll_sw/ll_mesh.h"
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_DTM_HCI)
+#include "ll_sw/ll_test.h"
+#endif /* CONFIG_BT_CTLR_DTM_HCI */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+#include "hci_user_ext.h"
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hci
+#include "common/log.h"
+#include "hal/debug.h"
+
+/* opcode of the HCI command currently being processed. The opcode is stored
+ * by hci_cmd_handle() and then used during the creation of cmd complete and
+ * cmd status events to avoid passing it up the call chain.
+ */
+static uint16_t _opcode;
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+/* Scan duplicate filter */
+struct dup {
+	uint8_t         mask;
+	bt_addr_le_t addr;
+};
+static struct dup dup_filter[CONFIG_BT_CTLR_DUP_FILTER_LEN];
+static int32_t dup_count;
+static uint32_t dup_curr;
+#endif
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+struct scan_filter {
+	uint8_t count;
+	uint8_t lengths[CONFIG_BT_CTLR_MESH_SF_PATTERNS];
+	uint8_t patterns[CONFIG_BT_CTLR_MESH_SF_PATTERNS]
+		     [BT_HCI_MESH_PATTERN_LEN_MAX];
+};
+
+static struct scan_filter scan_filters[CONFIG_BT_CTLR_MESH_SCAN_FILTERS];
+static uint8_t sf_curr;
+#endif
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+int32_t    hci_hbuf_total;
+uint32_t    hci_hbuf_sent;
+uint32_t    hci_hbuf_acked;
+uint16_t    hci_hbuf_pend[CONFIG_BT_MAX_CONN];
+atomic_t hci_state_mask;
+static struct k_poll_signal *hbuf_signal;
+#endif
+
+#if defined(CONFIG_BT_CONN)
+static uint32_t conn_count;
+#endif
+
+#define DEFAULT_EVENT_MASK           0x1fffffffffff
+#define DEFAULT_EVENT_MASK_PAGE_2    0x0
+#define DEFAULT_LE_EVENT_MASK 0x1f
+
+static uint64_t event_mask = DEFAULT_EVENT_MASK;
+static uint64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
+static uint64_t le_event_mask = DEFAULT_LE_EVENT_MASK;
+
+static struct net_buf *cmd_complete_status(uint8_t status);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static int adv_cmds_legacy_check(struct net_buf **cc_evt)
+{
+	int err;
+
+#if defined(CONFIG_BT_HCI_RAW)
+	err = ll_adv_cmds_set(LL_ADV_CMDS_LEGACY);
+	if (err && cc_evt) {
+		*cc_evt = cmd_complete_status(BT_HCI_ERR_CMD_DISALLOWED);
+	}
+#else
+	if (cc_evt) {
+		*cc_evt = cmd_complete_status(BT_HCI_ERR_CMD_DISALLOWED);
+	}
+
+	err = -EINVAL;
+#endif /* CONFIG_BT_HCI_RAW */
+
+	return err;
+}
+
+static int adv_cmds_ext_check(struct net_buf **cc_evt)
+{
+	int err;
+
+#if defined(CONFIG_BT_HCI_RAW)
+	err = ll_adv_cmds_set(LL_ADV_CMDS_EXT);
+	if (err && cc_evt) {
+		*cc_evt = cmd_complete_status(BT_HCI_ERR_CMD_DISALLOWED);
+	}
+#else
+	err = 0;
+#endif /* CONFIG_BT_HCI_RAW */
+
+	return err;
+}
+#else
+static inline int adv_cmds_legacy_check(struct net_buf **cc_evt)
+{
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CONN)
+static void le_conn_complete(struct pdu_data *pdu_data, uint16_t handle,
+			     struct net_buf *buf);
+#endif /* CONFIG_BT_CONN */
+
+static void hci_evt_create(struct net_buf *buf, uint8_t evt, uint8_t len)
+{
+	struct bt_hci_evt_hdr *hdr;
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->evt = evt;
+	hdr->len = len;
+}
+
+void *hci_cmd_complete(struct net_buf **buf, uint8_t plen)
+{
+	*buf = bt_hci_cmd_complete_create(_opcode, plen);
+
+	return net_buf_add(*buf, plen);
+}
+
+static struct net_buf *cmd_status(uint8_t status)
+{
+	return bt_hci_cmd_status_create(_opcode, status);
+}
+
+static struct net_buf *cmd_complete_status(uint8_t status)
+{
+	struct net_buf *buf;
+	struct bt_hci_evt_cc_status *ccst;
+
+	buf = bt_hci_cmd_complete_create(_opcode, sizeof(*ccst));
+	ccst = net_buf_add(buf, sizeof(*ccst));
+	ccst->status = status;
+
+	return buf;
+}
+
+static void *meta_evt(struct net_buf *buf, uint8_t subevt, uint8_t melen)
+{
+	struct bt_hci_evt_le_meta_event *me;
+
+	hci_evt_create(buf, BT_HCI_EVT_LE_META_EVENT, sizeof(*me) + melen);
+	me = net_buf_add(buf, sizeof(*me));
+	me->subevent = subevt;
+
+	return net_buf_add(buf, melen);
+}
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+static void *mesh_evt(struct net_buf *buf, uint8_t subevt, uint8_t melen)
+{
+	struct bt_hci_evt_mesh *me;
+
+	hci_evt_create(buf, BT_HCI_EVT_VENDOR, sizeof(*me) + melen);
+	me = net_buf_add(buf, sizeof(*me));
+	me->prefix = BT_HCI_MESH_EVT_PREFIX;
+	me->subevent = subevt;
+
+	return net_buf_add(buf, melen);
+}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CONN)
+static void disconnect(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_disconnect *cmd = (void *)buf->data;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_terminate_ind_send(handle, cmd->reason);
+
+	*evt = cmd_status(status);
+}
+
+static void read_remote_ver_info(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_read_remote_version_info *cmd = (void *)buf->data;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_version_ind_send(handle);
+
+	*evt = cmd_status(status);
+}
+#endif /* CONFIG_BT_CONN */
+
+static int link_control_cmd_handle(uint16_t  ocf, struct net_buf *cmd,
+				   struct net_buf **evt)
+{
+	switch (ocf) {
+#if defined(CONFIG_BT_CONN)
+	case BT_OCF(BT_HCI_OP_DISCONNECT):
+		disconnect(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_READ_REMOTE_VERSION_INFO):
+		read_remote_ver_info(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CONN */
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void set_event_mask(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data;
+
+	event_mask = sys_get_le64(cmd->events);
+
+	*evt = cmd_complete_status(0x00);
+}
+
+static void set_event_mask_page_2(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_set_event_mask_page_2 *cmd = (void *)buf->data;
+
+	event_mask_page_2 = sys_get_le64(cmd->events_page_2);
+
+	*evt = cmd_complete_status(0x00);
+}
+
+static void reset(struct net_buf *buf, struct net_buf **evt)
+{
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(scan_filters); i++) {
+		scan_filters[i].count = 0U;
+	}
+	sf_curr = 0xFF;
+#endif
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	dup_count = -1;
+#endif
+
+	/* reset event masks */
+	event_mask = DEFAULT_EVENT_MASK;
+	event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
+	le_event_mask = DEFAULT_LE_EVENT_MASK;
+
+	if (buf) {
+		ll_reset();
+		*evt = cmd_complete_status(0x00);
+	}
+
+#if defined(CONFIG_BT_CONN)
+	conn_count = 0U;
+#endif
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	hci_hbuf_total = 0;
+	hci_hbuf_sent = 0U;
+	hci_hbuf_acked = 0U;
+	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
+	if (buf) {
+		atomic_set_bit(&hci_state_mask, HCI_STATE_BIT_RESET);
+		k_poll_signal_raise(hbuf_signal, 0x0);
+	}
+#endif
+}
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+static void set_ctl_to_host_flow(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_set_ctl_to_host_flow *cmd = (void *)buf->data;
+	uint8_t flow_enable = cmd->flow_enable;
+	struct bt_hci_evt_cc_status *ccst;
+
+	ccst = hci_cmd_complete(evt, sizeof(*ccst));
+
+	/* require host buffer size before enabling flow control, and
+	 * disallow if any connections are up
+	 */
+	if (!hci_hbuf_total || conn_count) {
+		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
+		return;
+	} else {
+		ccst->status = 0x00;
+	}
+
+	switch (flow_enable) {
+	case BT_HCI_CTL_TO_HOST_FLOW_DISABLE:
+		if (hci_hbuf_total < 0) {
+			/* already disabled */
+			return;
+		}
+		break;
+	case BT_HCI_CTL_TO_HOST_FLOW_ENABLE:
+		if (hci_hbuf_total > 0) {
+			/* already enabled */
+			return;
+		}
+		break;
+	default:
+		ccst->status = BT_HCI_ERR_INVALID_PARAM;
+		return;
+	}
+
+	hci_hbuf_sent = 0U;
+	hci_hbuf_acked = 0U;
+	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
+	hci_hbuf_total = -hci_hbuf_total;
+}
+
+static void host_buffer_size(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_host_buffer_size *cmd = (void *)buf->data;
+	uint16_t acl_pkts = sys_le16_to_cpu(cmd->acl_pkts);
+	uint16_t acl_mtu = sys_le16_to_cpu(cmd->acl_mtu);
+	struct bt_hci_evt_cc_status *ccst;
+
+	ccst = hci_cmd_complete(evt, sizeof(*ccst));
+
+	if (hci_hbuf_total) {
+		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
+		return;
+	}
+	/* fragmentation from controller to host not supported, require
+	 * ACL MTU to be at least the LL MTU
+	 */
+	if (acl_mtu < LL_LENGTH_OCTETS_RX_MAX) {
+		ccst->status = BT_HCI_ERR_INVALID_PARAM;
+		return;
+	}
+
+	BT_DBG("FC: host buf size: %d", acl_pkts);
+	hci_hbuf_total = -acl_pkts;
+}
+
+static void host_num_completed_packets(struct net_buf *buf,
+				       struct net_buf **evt)
+{
+	struct bt_hci_cp_host_num_completed_packets *cmd = (void *)buf->data;
+	struct bt_hci_evt_cc_status *ccst;
+	uint32_t count = 0U;
+	int i;
+
+	/* special case, no event returned except for error conditions */
+	if (hci_hbuf_total <= 0) {
+		ccst = hci_cmd_complete(evt, sizeof(*ccst));
+		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
+		return;
+	} else if (!conn_count) {
+		ccst = hci_cmd_complete(evt, sizeof(*ccst));
+		ccst->status = BT_HCI_ERR_INVALID_PARAM;
+		return;
+	}
+
+	/* leave *evt == NULL so no event is generated */
+	for (i = 0; i < cmd->num_handles; i++) {
+		uint16_t h = sys_le16_to_cpu(cmd->h[i].handle);
+		uint16_t c = sys_le16_to_cpu(cmd->h[i].count);
+
+		if ((h >= ARRAY_SIZE(hci_hbuf_pend)) ||
+		    (c > hci_hbuf_pend[h])) {
+			ccst = hci_cmd_complete(evt, sizeof(*ccst));
+			ccst->status = BT_HCI_ERR_INVALID_PARAM;
+			return;
+		}
+
+		hci_hbuf_pend[h] -= c;
+		count += c;
+	}
+
+	BT_DBG("FC: acked: %d", count);
+	hci_hbuf_acked += count;
+	k_poll_signal_raise(hbuf_signal, 0x0);
+}
+#endif
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+static void read_auth_payload_timeout(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_read_auth_payload_timeout *cmd = (void *)buf->data;
+	struct bt_hci_rp_read_auth_payload_timeout *rp;
+	uint16_t auth_payload_timeout;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	status = ll_apto_get(handle, &auth_payload_timeout);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+	rp->auth_payload_timeout = sys_cpu_to_le16(auth_payload_timeout);
+}
+
+static void write_auth_payload_timeout(struct net_buf *buf,
+				       struct net_buf **evt)
+{
+	struct bt_hci_cp_write_auth_payload_timeout *cmd = (void *)buf->data;
+	struct bt_hci_rp_write_auth_payload_timeout *rp;
+	uint16_t auth_payload_timeout;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	auth_payload_timeout = sys_le16_to_cpu(cmd->auth_payload_timeout);
+
+	status = ll_apto_set(handle, auth_payload_timeout);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CONN)
+static void read_tx_power_level(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_read_tx_power_level *cmd = (void *)buf->data;
+	struct bt_hci_rp_read_tx_power_level *rp;
+	uint16_t handle;
+	uint8_t status;
+	uint8_t type;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	type = cmd->type;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	status = ll_tx_pwr_lvl_get(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
+				   handle, type, &rp->tx_power_level);
+
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CONN */
+
+static int ctrl_bb_cmd_handle(uint16_t  ocf, struct net_buf *cmd,
+			      struct net_buf **evt)
+{
+	switch (ocf) {
+	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK):
+		set_event_mask(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_RESET):
+		reset(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK_PAGE_2):
+		set_event_mask_page_2(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CONN)
+	case BT_OCF(BT_HCI_OP_READ_TX_POWER_LEVEL):
+		read_tx_power_level(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	case BT_OCF(BT_HCI_OP_SET_CTL_TO_HOST_FLOW):
+		set_ctl_to_host_flow(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_HOST_BUFFER_SIZE):
+		host_buffer_size(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS):
+		host_num_completed_packets(cmd, evt);
+		break;
+#endif
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	case BT_OCF(BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT):
+		read_auth_payload_timeout(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT):
+		write_auth_payload_timeout(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void read_local_version_info(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_read_local_version_info *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	rp->hci_version = LL_VERSION_NUMBER;
+	rp->hci_revision = sys_cpu_to_le16(0);
+	rp->lmp_version = LL_VERSION_NUMBER;
+	rp->manufacturer = sys_cpu_to_le16(ll_settings_company_id());
+	rp->lmp_subversion = sys_cpu_to_le16(ll_settings_subversion_number());
+}
+
+static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_read_supported_commands *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	(void)memset(&rp->commands[0], 0, sizeof(rp->commands));
+
+#if defined(CONFIG_BT_REMOTE_VERSION)
+	/* Read Remote Version Info. */
+	rp->commands[2] |= BIT(7);
+#endif
+	/* Set Event Mask, and Reset. */
+	rp->commands[5] |= BIT(6) | BIT(7);
+	/* Read TX Power Level. */
+	rp->commands[10] |= BIT(2);
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	/* Set FC, Host Buffer Size and Host Num Completed */
+	rp->commands[10] |= BIT(5) | BIT(6) | BIT(7);
+#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
+
+	/* Read Local Version Info, Read Local Supported Features. */
+	rp->commands[14] |= BIT(3) | BIT(5);
+	/* Read BD ADDR. */
+	rp->commands[15] |= BIT(1);
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	/* Read RSSI. */
+	rp->commands[15] |= BIT(5);
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+	/* Set Event Mask Page 2 */
+	rp->commands[22] |= BIT(2);
+	/* LE Set Event Mask, LE Read Buffer Size, LE Read Local Supp Feats,
+	 * Set Random Addr
+	 */
+	rp->commands[25] |= BIT(0) | BIT(1) | BIT(2) | BIT(4);
+
+#if defined(CONFIG_BT_CTLR_FILTER)
+	/* LE Read WL Size, LE Clear WL */
+	rp->commands[26] |= BIT(6) | BIT(7);
+	/* LE Add Dev to WL, LE Remove Dev from WL */
+	rp->commands[27] |= BIT(0) | BIT(1);
+#endif /* CONFIG_BT_CTLR_FILTER */
+
+	/* LE Encrypt, LE Rand */
+	rp->commands[27] |= BIT(6) | BIT(7);
+	/* LE Read Supported States */
+	rp->commands[28] |= BIT(3);
+
+#if defined(CONFIG_BT_BROADCASTER)
+	/* LE Set Adv Params, LE Read Adv Channel TX Power, LE Set Adv Data */
+	rp->commands[25] |= BIT(5) | BIT(6) | BIT(7);
+	/* LE Set Scan Response Data, LE Set Adv Enable */
+	rp->commands[26] |= BIT(0) | BIT(1);
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	/* LE Set Scan Params, LE Set Scan Enable */
+	rp->commands[26] |= BIT(2) | BIT(3);
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+	/* LE Create Connection, LE Create Connection Cancel */
+	rp->commands[26] |= BIT(4) | BIT(5);
+	/* Set Host Channel Classification */
+	rp->commands[27] |= BIT(3);
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	/* LE Start Encryption */
+	rp->commands[28] |= BIT(0);
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	/* LE LTK Request Reply, LE LTK Request Negative Reply */
+	rp->commands[28] |= BIT(1) | BIT(2);
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	/* Disconnect. */
+	rp->commands[0] |= BIT(5);
+	/* LE Connection Update, LE Read Channel Map, LE Read Remote Features */
+	rp->commands[27] |= BIT(2) | BIT(4) | BIT(5);
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	/* LE Remote Conn Param Req and Neg Reply */
+	rp->commands[33] |= BIT(4) | BIT(5);
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	/* Read and Write authenticated payload timeout */
+	rp->commands[32] |= BIT(4) | BIT(5);
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	/* LE Set Data Length, and LE Read Suggested Data Length. */
+	rp->commands[33] |= BIT(6) | BIT(7);
+	/* LE Write Suggested Data Length. */
+	rp->commands[34] |= BIT(0);
+	/* LE Read Maximum Data Length. */
+	rp->commands[35] |= BIT(3);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	/* LE Read PHY Command. */
+	rp->commands[35] |= BIT(4);
+	/* LE Set Default PHY Command. */
+	rp->commands[35] |= BIT(5);
+	/* LE Set PHY Command. */
+	rp->commands[35] |= BIT(6);
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_DTM_HCI)
+	/* LE RX Test, LE TX Test, LE Test End */
+	rp->commands[28] |= BIT(4) | BIT(5) | BIT(6);
+	/* LE Enhanced RX Test. */
+	rp->commands[35] |= BIT(7);
+	/* LE Enhanced TX Test. */
+	rp->commands[36] |= BIT(0);
+#endif /* CONFIG_BT_CTLR_DTM_HCI */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* LE resolving list commands, LE Read Peer RPA */
+	rp->commands[34] |= BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7);
+	/* LE Read Local RPA, LE Set AR Enable, Set RPA Timeout */
+	rp->commands[35] |= BIT(0) | BIT(1) | BIT(2);
+	/* LE Set Privacy Mode */
+	rp->commands[39] |= BIT(2);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+#if defined(CONFIG_BT_HCI_RAW) && defined(CONFIG_BT_TINYCRYPT_ECC)
+	/* LE Read Local P256 Public Key and LE Generate DH Key*/
+	rp->commands[34] |= BIT(1) | BIT(2);
+#endif /* CONFIG_BT_HCI_RAW && CONFIG_BT_TINYCRYPT_ECC */
+
+	/* LE Read TX Power. */
+	rp->commands[38] |= BIT(7);
+}
+
+static void read_local_features(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_read_local_features *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	(void)memset(&rp->features[0], 0x00, sizeof(rp->features));
+	/* BR/EDR not supported and LE supported */
+	rp->features[4] = (1 << 5) | (1 << 6);
+}
+
+static void read_bd_addr(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_read_bd_addr *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+
+	ll_addr_get(0, &rp->bdaddr.val[0]);
+}
+
+static int info_cmd_handle(uint16_t  ocf, struct net_buf *cmd,
+			   struct net_buf **evt)
+{
+	switch (ocf) {
+	case BT_OCF(BT_HCI_OP_READ_LOCAL_VERSION_INFO):
+		read_local_version_info(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_READ_SUPPORTED_COMMANDS):
+		read_supported_commands(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_READ_LOCAL_FEATURES):
+		read_local_features(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_READ_BD_ADDR):
+		read_bd_addr(cmd, evt);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+static void read_rssi(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_read_rssi *cmd = (void *)buf->data;
+	struct bt_hci_rp_read_rssi *rp;
+	uint16_t handle;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = ll_rssi_get(handle, &rp->rssi);
+
+	rp->handle = sys_cpu_to_le16(handle);
+	/* The Link Layer currently returns RSSI as an absolute value */
+	rp->rssi = (!rp->status) ? -rp->rssi : 127;
+}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+static int status_cmd_handle(uint16_t  ocf, struct net_buf *cmd,
+			     struct net_buf **evt)
+{
+	switch (ocf) {
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	case BT_OCF(BT_HCI_OP_READ_RSSI):
+		read_rssi(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void le_set_event_mask(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data;
+
+	le_event_mask = sys_get_le64(cmd->events);
+
+	*evt = cmd_complete_status(0x00);
+}
+
+static void le_read_buffer_size(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_buffer_size *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+
+	rp->le_max_len = sys_cpu_to_le16(CONFIG_BT_CTLR_TX_BUFFER_SIZE);
+	rp->le_max_num = CONFIG_BT_CTLR_TX_BUFFERS;
+}
+
+static void le_read_local_features(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_local_features *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+
+	(void)memset(&rp->features[0], 0x00, sizeof(rp->features));
+	sys_put_le24(LL_FEAT, rp->features);
+}
+
+static void le_set_random_address(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_random_address *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_addr_set(1, &cmd->bdaddr.val[0]);
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_FILTER)
+static void le_read_wl_size(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_wl_size *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+
+	rp->wl_size = ll_wl_size_get();
+}
+
+static void le_clear_wl(struct net_buf *buf, struct net_buf **evt)
+{
+	uint8_t status;
+
+	status = ll_wl_clear();
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_add_dev_to_wl(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_add_dev_to_wl *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_wl_add(&cmd->addr);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_rem_dev_from_wl(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_rem_dev_from_wl *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_wl_remove(&cmd->addr);
+
+	*evt = cmd_complete_status(status);
+}
+#endif /* CONFIG_BT_CTLR_FILTER */
+
+static void le_encrypt(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_encrypt *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_encrypt *rp;
+	uint8_t enc_data[16];
+
+	ecb_encrypt(cmd->key, cmd->plaintext, enc_data, NULL);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	memcpy(rp->enc_data, enc_data, 16);
+}
+
+static void le_rand(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_rand *rp;
+	uint8_t count = sizeof(rp->rand);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+
+	lll_csrand_get(rp->rand, count);
+}
+
+static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_supp_states *rp;
+	uint64_t states = 0U;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+
+#define ST_ADV (BIT64(0)  | BIT64(1)  | BIT64(8)  | BIT64(9)  | BIT64(12) | \
+		BIT64(13) | BIT64(16) | BIT64(17) | BIT64(18) | BIT64(19) | \
+		BIT64(20) | BIT64(21))
+
+#define ST_SCA (BIT64(4)  | BIT64(5)  | BIT64(8)  | BIT64(9)  | BIT64(10) | \
+		BIT64(11) | BIT64(12) | BIT64(13) | BIT64(14) | BIT64(15) | \
+		BIT64(22) | BIT64(23) | BIT64(24) | BIT64(25) | BIT64(26) | \
+		BIT64(27) | BIT64(30) | BIT64(31))
+
+#define ST_SLA (BIT64(2)  | BIT64(3)  | BIT64(7)  | BIT64(10) | BIT64(11) | \
+		BIT64(14) | BIT64(15) | BIT64(20) | BIT64(21) | BIT64(26) | \
+		BIT64(27) | BIT64(29) | BIT64(30) | BIT64(31) | BIT64(32) | \
+		BIT64(33) | BIT64(34) | BIT64(35) | BIT64(36) | BIT64(37) | \
+		BIT64(38) | BIT64(39) | BIT64(40) | BIT64(41))
+
+#define ST_MAS (BIT64(6)  | BIT64(16) | BIT64(17) | BIT64(18) | BIT64(19) | \
+		BIT64(22) | BIT64(23) | BIT64(24) | BIT64(25) | BIT64(28) | \
+		BIT64(32) | BIT64(33) | BIT64(34) | BIT64(35) | BIT64(36) | \
+		BIT64(37) | BIT64(41))
+
+#if defined(CONFIG_BT_BROADCASTER)
+	states |= ST_ADV;
+#else
+	states &= ~ST_ADV;
+#endif
+#if defined(CONFIG_BT_OBSERVER)
+	states |= ST_SCA;
+#else
+	states &= ~ST_SCA;
+#endif
+#if defined(CONFIG_BT_PERIPHERAL)
+	states |= ST_SLA;
+#else
+	states &= ~ST_SLA;
+#endif
+#if defined(CONFIG_BT_CENTRAL)
+	states |= ST_MAS;
+#else
+	states &= ~ST_MAS;
+#endif
+	/* All states and combinations supported except:
+	 * Initiating State + Passive Scanning
+	 * Initiating State + Active Scanning
+	 */
+	states &= ~(BIT64(22) | BIT64(23));
+	BT_DBG("states: 0x%08x%08x", (uint32_t)(states >> 32),
+				     (uint32_t)(states & 0xffffffff));
+	sys_put_le64(states, rp->le_states);
+}
+
+#if defined(CONFIG_BT_BROADCASTER)
+static void le_set_adv_param(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_adv_param *cmd = (void *)buf->data;
+	uint16_t min_interval;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+	min_interval = sys_le16_to_cpu(cmd->min_interval);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK) &&
+	    (cmd->type != BT_HCI_ADV_DIRECT_IND)) {
+		uint16_t max_interval = sys_le16_to_cpu(cmd->max_interval);
+
+		if ((min_interval > max_interval) ||
+		    (min_interval < 0x0020) ||
+		    (max_interval > 0x4000)) {
+			*evt = cmd_complete_status(BT_HCI_ERR_INVALID_PARAM);
+			return;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	status = ll_adv_params_set(0, 0, min_interval, cmd->type,
+				   cmd->own_addr_type, cmd->direct_addr.type,
+				   &cmd->direct_addr.a.val[0], cmd->channel_map,
+				   cmd->filter_policy, 0, 0, 0, 0, 0, 0);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	status = ll_adv_params_set(min_interval, cmd->type,
+				   cmd->own_addr_type, cmd->direct_addr.type,
+				   &cmd->direct_addr.a.val[0], cmd->channel_map,
+				   cmd->filter_policy);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_read_adv_chan_tx_power(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_chan_tx_power *rp;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+
+	rp->tx_power_level = 0;
+}
+
+static void le_set_adv_data(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_adv_data *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	status = ll_adv_data_set(0, cmd->len, &cmd->data[0]);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	status = ll_adv_data_set(cmd->len, &cmd->data[0]);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_scan_rsp_data(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_scan_rsp_data *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	status = ll_adv_scan_rsp_set(0, cmd->len, &cmd->data[0]);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	status = ll_adv_scan_rsp_set(cmd->len, &cmd->data[0]);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_adv_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_adv_enable *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	status = ll_adv_enable(0, cmd->enable, 0, 0, 0, 0, 0);
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+	status = ll_adv_enable(0, cmd->enable, 0, 0);
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+	status = ll_adv_enable(cmd->enable);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO)
+static void le_create_big(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_create_big *cmd = (void *)buf->data;
+	uint8_t status;
+	uint32_t sdu_interval;
+	uint16_t max_sdu;
+	uint16_t max_latency;
+
+	sdu_interval = sys_get_le24(cmd->sdu_interval);
+	max_sdu = sys_le16_to_cpu(cmd->max_sdu);
+	max_latency = sys_le16_to_cpu(cmd->max_latency);
+
+	status = ll_big_create(cmd->big_handle, cmd->adv_handle, cmd->num_bis,
+			       sdu_interval, max_sdu, max_latency, cmd->rtn,
+			       cmd->phy, cmd->packing, cmd->framing,
+			       cmd->encryption, cmd->bcode);
+
+	*evt = cmd_status(status);
+}
+
+static void le_create_big_test(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_create_big_test *cmd = (void *)buf->data;
+	uint8_t status;
+	uint32_t sdu_interval;
+	uint16_t iso_interval;
+	uint16_t max_sdu;
+	uint16_t max_pdu;
+
+	sdu_interval = sys_get_le24(cmd->sdu_interval);
+	iso_interval = sys_le16_to_cpu(cmd->iso_interval);
+	max_sdu = sys_le16_to_cpu(cmd->max_sdu);
+	max_pdu = sys_le16_to_cpu(cmd->max_pdu);
+
+	status = ll_big_test_create(cmd->big_handle, cmd->adv_handle,
+				    cmd->num_bis, sdu_interval, iso_interval,
+				    cmd->nse, max_sdu, max_pdu, cmd->phy,
+				    cmd->packing, cmd->framing, cmd->bn,
+				    cmd->irc, cmd->pto, cmd->encryption,
+				    cmd->bcode);
+
+	*evt = cmd_status(status);
+}
+
+static void le_terminate_big(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_terminate_big *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_big_terminate(cmd->big_handle, cmd->reason);
+
+	*evt = cmd_status(status);
+}
+#endif /* CONFIG_BT_CTLR_ADV_ISO */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+static void le_set_scan_param(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_scan_param *cmd = (void *)buf->data;
+	uint16_t interval;
+	uint16_t window;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+	interval = sys_le16_to_cpu(cmd->interval);
+	window = sys_le16_to_cpu(cmd->window);
+
+	status = ll_scan_params_set(cmd->scan_type, interval, window,
+				    cmd->addr_type, cmd->filter_policy);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_scan_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_scan_enable *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(evt)) {
+		return;
+	}
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	/* initialize duplicate filtering */
+	if (cmd->enable && cmd->filter_dup) {
+		dup_count = 0;
+		dup_curr = 0U;
+	} else {
+		dup_count = -1;
+	}
+#endif
+
+	status = ll_scan_enable(cmd->enable);
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_SYNC_ISO)
+static void le_big_create_sync(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_big_create_sync *cmd = (void *)buf->data;
+	uint8_t status;
+	uint16_t sync_handle;
+	uint16_t sync_timeout;
+
+	sync_handle = sys_le16_to_cpu(cmd->sync_handle);
+	sync_timeout = sys_le16_to_cpu(cmd->sync_timeout);
+
+	status = ll_big_sync_create(cmd->big_handle, sync_handle,
+				    cmd->encryption, cmd->bcode, cmd->mse,
+				    sync_timeout, cmd->num_bis, cmd->bis);
+
+	*evt = cmd_status(status);
+}
+
+
+static void le_big_terminate_sync(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_big_terminate_sync *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_big_sync_terminate(cmd->big_handle);
+
+	*evt = cmd_complete_status(status);
+}
+#endif /* CONFIG_BT_CTLR_ADV_ISO */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+static void le_create_connection(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_create_conn *cmd = (void *)buf->data;
+	uint16_t supervision_timeout;
+	uint16_t conn_interval_max;
+	uint16_t scan_interval;
+	uint16_t conn_latency;
+	uint16_t scan_window;
+	uint8_t status;
+
+	if (adv_cmds_legacy_check(NULL)) {
+		*evt = cmd_status(BT_HCI_ERR_CMD_DISALLOWED);
+		return;
+	}
+
+	scan_interval = sys_le16_to_cpu(cmd->scan_interval);
+	scan_window = sys_le16_to_cpu(cmd->scan_window);
+	conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
+	conn_latency = sys_le16_to_cpu(cmd->conn_latency);
+	supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	status = ll_create_connection(scan_interval, scan_window,
+				      cmd->filter_policy,
+				      cmd->peer_addr.type,
+				      &cmd->peer_addr.a.val[0],
+				      cmd->own_addr_type, conn_interval_max,
+				      conn_latency, supervision_timeout,
+				      PHY_LEGACY);
+	if (status) {
+		*evt = cmd_status(status);
+		return;
+	}
+
+	status = ll_connect_enable(0U);
+
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	status = ll_create_connection(scan_interval, scan_window,
+				      cmd->filter_policy,
+				      cmd->peer_addr.type,
+				      &cmd->peer_addr.a.val[0],
+				      cmd->own_addr_type, conn_interval_max,
+				      conn_latency, supervision_timeout);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	*evt = cmd_status(status);
+}
+
+static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt,
+				  void **node_rx)
+{
+	uint8_t status;
+
+	status = ll_connect_disable(node_rx);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_host_chan_classif(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_host_chan_classif *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_chm_update(&cmd->ch_map[0]);
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static void le_start_encryption(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_start_encryption *cmd = (void *)buf->data;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_enc_req_send(handle,
+				 (uint8_t *)&cmd->rand,
+				 (uint8_t *)&cmd->ediv,
+				 &cmd->ltk[0]);
+
+	*evt = cmd_status(status);
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static void le_ltk_req_reply(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_ltk_req_reply *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_ltk_req_reply *rp;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_start_enc_req_send(handle, 0x00, &cmd->ltk[0]);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+
+static void le_ltk_req_neg_reply(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_ltk_req_neg_reply *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_ltk_req_neg_reply *rp;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_start_enc_req_send(handle, BT_HCI_ERR_PIN_OR_KEY_MISSING,
+				       NULL);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_le16_to_cpu(handle);
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static void le_read_remote_features(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_read_remote_features *cmd = (void *)buf->data;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_feature_req_send(handle);
+
+	*evt = cmd_status(status);
+}
+
+static void le_read_chan_map(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_read_chan_map *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_read_chan_map *rp;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	status = ll_chm_get(handle, rp->ch_map);
+
+	rp->status = status;
+	rp->handle = sys_le16_to_cpu(handle);
+}
+
+static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
+{
+	struct hci_cp_le_conn_update *cmd = (void *)buf->data;
+	uint16_t supervision_timeout;
+	uint16_t conn_interval_min;
+	uint16_t conn_interval_max;
+	uint16_t conn_latency;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	conn_interval_min = sys_le16_to_cpu(cmd->conn_interval_min);
+	conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
+	conn_latency = sys_le16_to_cpu(cmd->conn_latency);
+	supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
+
+	status = ll_conn_update(handle, 0, 0, conn_interval_min,
+				conn_interval_max, conn_latency,
+				supervision_timeout);
+
+	*evt = cmd_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_conn_param_req_reply *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_conn_param_req_reply *rp;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	interval_min = sys_le16_to_cpu(cmd->interval_min);
+	interval_max = sys_le16_to_cpu(cmd->interval_max);
+	latency = sys_le16_to_cpu(cmd->latency);
+	timeout = sys_le16_to_cpu(cmd->timeout);
+
+	status = ll_conn_update(handle, 2, 0, interval_min, interval_max,
+				latency, timeout);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+
+static void le_conn_param_req_neg_reply(struct net_buf *buf,
+					struct net_buf **evt)
+{
+	struct bt_hci_cp_le_conn_param_req_neg_reply *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_conn_param_req_neg_reply *rp;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0, 0);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static void le_set_data_len(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_data_len *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_set_data_len *rp;
+	uint16_t tx_octets;
+	uint16_t tx_time;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	tx_octets = sys_le16_to_cpu(cmd->tx_octets);
+	tx_time = sys_le16_to_cpu(cmd->tx_time);
+	status = ll_length_req_send(handle, tx_octets, tx_time);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+
+static void le_read_default_data_len(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_default_data_len *rp;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	ll_length_default_get(&max_tx_octets, &max_tx_time);
+
+	rp->max_tx_octets = sys_cpu_to_le16(max_tx_octets);
+	rp->max_tx_time = sys_cpu_to_le16(max_tx_time);
+	rp->status = 0x00;
+}
+
+static void le_write_default_data_len(struct net_buf *buf,
+				      struct net_buf **evt)
+{
+	struct bt_hci_cp_le_write_default_data_len *cmd = (void *)buf->data;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint8_t status;
+
+	max_tx_octets = sys_le16_to_cpu(cmd->max_tx_octets);
+	max_tx_time = sys_le16_to_cpu(cmd->max_tx_time);
+	status = ll_length_default_set(max_tx_octets, max_tx_time);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_read_max_data_len(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_max_data_len *rp;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	ll_length_max_get(&max_tx_octets, &max_tx_time,
+			  &max_rx_octets, &max_rx_time);
+
+	rp->max_tx_octets = sys_cpu_to_le16(max_tx_octets);
+	rp->max_tx_time = sys_cpu_to_le16(max_tx_time);
+	rp->max_rx_octets = sys_cpu_to_le16(max_rx_octets);
+	rp->max_rx_time = sys_cpu_to_le16(max_rx_time);
+	rp->status = 0x00;
+}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static void le_read_phy(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_read_phy *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_read_phy *rp;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	status = ll_phy_get(handle, &rp->tx_phy, &rp->rx_phy);
+
+	rp->status = status;
+	rp->handle = sys_cpu_to_le16(handle);
+	rp->tx_phy = find_lsb_set(rp->tx_phy);
+	rp->rx_phy = find_lsb_set(rp->rx_phy);
+}
+
+static void le_set_default_phy(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_default_phy *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
+		cmd->tx_phys = 0x07;
+	}
+	if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
+		cmd->rx_phys = 0x07;
+	}
+
+	status = ll_phy_default_set(cmd->tx_phys, cmd->rx_phys);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_phy(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_phy *cmd = (void *)buf->data;
+	uint16_t phy_opts;
+	uint8_t mask_phys;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+	phy_opts = sys_le16_to_cpu(cmd->phy_opts);
+
+	mask_phys = 0x01;
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_2M)) {
+		mask_phys |= BIT(1);
+	}
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		mask_phys |= BIT(2);
+	}
+
+	if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
+		cmd->tx_phys |= mask_phys;
+	}
+	if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
+		cmd->rx_phys |= mask_phys;
+	}
+
+	if ((cmd->tx_phys | cmd->rx_phys) & ~mask_phys) {
+		*evt = cmd_status(BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
+
+		return;
+	}
+
+	if (!(cmd->tx_phys & 0x07) ||
+	    !(cmd->rx_phys & 0x07)) {
+		*evt = cmd_status(BT_HCI_ERR_INVALID_PARAM);
+
+		return;
+	}
+
+	if (phy_opts & 0x03) {
+		phy_opts -= 1U;
+		phy_opts &= 1;
+	} else {
+		phy_opts = 0U;
+	}
+
+	status = ll_phy_req_send(handle, cmd->tx_phys, phy_opts,
+				 cmd->rx_phys);
+
+	*evt = cmd_status(status);
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+static void le_add_dev_to_rl(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_add_dev_to_rl *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_rl_add(&cmd->peer_id_addr, cmd->peer_irk, cmd->local_irk);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_rem_dev_from_rl(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_rem_dev_from_rl *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_rl_remove(&cmd->peer_id_addr);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_clear_rl(struct net_buf *buf, struct net_buf **evt)
+{
+	uint8_t status;
+
+	status = ll_rl_clear();
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_read_rl_size(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_rl_size *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->rl_size = ll_rl_size_get();
+	rp->status = 0x00;
+}
+
+static void le_read_peer_rpa(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_read_peer_rpa *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_read_peer_rpa *rp;
+	bt_addr_le_t peer_id_addr;
+
+	bt_addr_le_copy(&peer_id_addr, &cmd->peer_id_addr);
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = ll_rl_crpa_get(&peer_id_addr, &rp->peer_rpa);
+}
+
+static void le_read_local_rpa(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_read_local_rpa *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_read_local_rpa *rp;
+	bt_addr_le_t peer_id_addr;
+
+	bt_addr_le_copy(&peer_id_addr, &cmd->peer_id_addr);
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = ll_rl_lrpa_get(&peer_id_addr, &rp->local_rpa);
+}
+
+static void le_set_addr_res_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_addr_res_enable *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_rl_enable(cmd->enable);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_rpa_timeout(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_rpa_timeout *cmd = (void *)buf->data;
+	uint16_t timeout = sys_le16_to_cpu(cmd->rpa_timeout);
+
+	ll_rl_timeout_set(timeout);
+
+	*evt = cmd_complete_status(0x00);
+}
+
+static void le_set_privacy_mode(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_privacy_mode *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_priv_mode_set(&cmd->id_addr, cmd->mode);
+
+	*evt = cmd_complete_status(status);
+}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+static void le_read_tx_power(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_tx_power *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+	ll_tx_pwr_get(&rp->min_tx_power, &rp->max_tx_power);
+}
+
+#if defined(CONFIG_BT_CTLR_DTM_HCI)
+static void le_rx_test(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_rx_test *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_test_rx(cmd->rx_ch, 0x01, 0);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_tx_test(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_tx_test *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_test_tx(cmd->tx_ch, cmd->test_data_len, cmd->pkt_payload,
+			    0x01);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_test_end(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_test_end *rp;
+	uint16_t rx_pkt_count;
+
+	ll_test_end(&rx_pkt_count);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+	rp->rx_pkt_count = sys_cpu_to_le16(rx_pkt_count);
+}
+
+static void le_enh_rx_test(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_enh_rx_test *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_test_rx(cmd->rx_ch, cmd->phy, cmd->mod_index);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_enh_tx_test(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_enh_tx_test *cmd = (void *)buf->data;
+	uint8_t status;
+
+	status = ll_test_tx(cmd->tx_ch, cmd->test_data_len, cmd->pkt_payload,
+			    cmd->phy);
+
+	*evt = cmd_complete_status(status);
+}
+#endif /* CONFIG_BT_CTLR_DTM_HCI */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_BROADCASTER)
+
+static void le_set_adv_set_random_addr(struct net_buf *buf,
+				       struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_adv_set_random_addr *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_aux_random_addr_set(handle, &cmd->bdaddr.val[0]);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_ext_adv_param(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_adv_param *cmd = (void *)buf->data;
+	struct bt_hci_rp_le_set_ext_adv_param *rp;
+	uint32_t min_interval;
+	uint16_t evt_prop;
+	uint8_t tx_pwr;
+	uint8_t status;
+	uint8_t phy_p;
+	uint8_t phy_s;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	if (cmd->handle > BT_HCI_LE_ADV_HANDLE_MAX) {
+		*evt = cmd_complete_status(BT_HCI_ERR_INVALID_PARAM);
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get_or_new(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	evt_prop = sys_le16_to_cpu(cmd->props);
+	min_interval = sys_get_le24(cmd->prim_min_interval);
+	tx_pwr = cmd->tx_power;
+	phy_p = BIT(cmd->prim_adv_phy - 1);
+	phy_s = BIT(cmd->sec_adv_phy - 1);
+
+	status = ll_adv_params_set(handle, evt_prop, min_interval,
+				   PDU_ADV_TYPE_EXT_IND, cmd->own_addr_type,
+				   cmd->peer_addr.type, cmd->peer_addr.a.val,
+				   cmd->prim_channel_map, cmd->filter_policy,
+				   &tx_pwr, phy_p, cmd->sec_adv_max_skip, phy_s,
+				   cmd->sid, cmd->scan_req_notify_enable);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->tx_power = tx_pwr;
+}
+
+static void le_set_ext_adv_data(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_adv_data *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_aux_ad_data_set(handle, cmd->op, cmd->frag_pref,
+					cmd->len, cmd->data);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_ext_scan_rsp_data(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_scan_rsp_data *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_aux_sr_data_set(handle, cmd->op, cmd->frag_pref,
+					cmd->len, cmd->data);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_ext_adv_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_adv_enable *cmd = (void *)buf->data;
+	struct bt_hci_ext_adv_set *s;
+	uint8_t set_num;
+	uint8_t enable;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	set_num = cmd->set_num;
+	if (!set_num) {
+		if (cmd->enable) {
+			*evt = cmd_complete_status(BT_HCI_ERR_INVALID_PARAM);
+			return;
+		}
+
+		/* FIXME: Implement disable of all advertising sets */
+		*evt = cmd_complete_status(BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
+
+		return;
+	}
+
+	s = (void *) cmd->s;
+	enable = cmd->enable;
+	do {
+		status = ll_adv_set_by_hci_handle_get(s->handle, &handle);
+		if (status) {
+			break;
+		}
+
+		/* TODO: duration and events parameter use. */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+		status = ll_adv_enable(handle, cmd->enable, 0, 0, 0, 0, 0);
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+		status = ll_adv_enable(handle, cmd->enable,
+				       s->duration, s->max_ext_adv_evts);
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+		if (status) {
+			/* TODO: how to handle succeeded ones before this
+			 * error.
+			 */
+			break;
+		}
+
+		s++;
+	} while (--set_num);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_read_max_adv_data_len(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_max_adv_data_len *rp;
+	uint16_t max_adv_data_len;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	max_adv_data_len = ll_adv_aux_max_data_length_get();
+
+	rp->max_adv_data_len = sys_cpu_to_le16(max_adv_data_len);
+	rp->status = 0x00;
+}
+
+static void le_read_num_adv_sets(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_le_read_num_adv_sets *rp;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->num_sets = ll_adv_aux_set_count_get();
+	rp->status = 0x00;
+}
+
+static void le_remove_adv_set(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_remove_adv_set *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_aux_set_remove(handle);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_clear_adv_sets(struct net_buf *buf, struct net_buf **evt)
+{
+	uint8_t status;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_aux_set_clear();
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+static void le_set_per_adv_param(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_per_adv_param *cmd = (void *)buf->data;
+	uint16_t interval;
+	uint16_t flags;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	interval = sys_le16_to_cpu(cmd->max_interval);
+	flags = sys_le16_to_cpu(cmd->props);
+
+	status = ll_adv_sync_param_set(handle, interval, flags);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_per_adv_data(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_per_adv_data *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_sync_ad_data_set(handle, cmd->op, cmd->len,
+					 cmd->data);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_per_adv_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_per_adv_enable *cmd = (void *)buf->data;
+	uint8_t status;
+	uint8_t handle;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	status = ll_adv_set_by_hci_handle_get(cmd->handle, &handle);
+	if (status) {
+		*evt = cmd_complete_status(status);
+		return;
+	}
+
+	status = ll_adv_sync_enable(handle, cmd->enable);
+
+	*evt = cmd_complete_status(status);
+}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+static void le_set_ext_scan_param(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_scan_param *cmd = (void *)buf->data;
+	struct bt_hci_ext_scan_phy *p;
+	uint8_t own_addr_type;
+	uint8_t filter_policy;
+	uint8_t phys_bitmask;
+	uint8_t status;
+	uint8_t phys;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+	/* TODO: add parameter checks */
+
+	own_addr_type = cmd->own_addr_type;
+	filter_policy = cmd->filter_policy;
+	phys = cmd->phys;
+	p = cmd->p;
+
+	/* Number of bits set indicate scan sets to be configured by calling
+	 * ll_scan_params_set function.
+	 */
+	phys_bitmask = BT_HCI_LE_EXT_SCAN_PHY_1M;
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		phys_bitmask |= BT_HCI_LE_EXT_SCAN_PHY_CODED;
+	}
+
+	/* Irrespective of enabled PHYs to scan for, ll_scan_params_set needs
+	 * to be called to initialise the scan sets.
+	 * Passing interval and window as 0, disable the particular scan set
+	 * from being enabled.
+	 */
+	do {
+		uint16_t interval;
+		uint16_t window;
+		uint8_t type;
+		uint8_t phy;
+
+		/* Get single PHY bit from the loop bitmask */
+		phy = BIT(find_lsb_set(phys_bitmask) - 1);
+
+		/* Pass the PHY (1M or Coded) of scan set in MSbits of type
+		 * parameter
+		 */
+		type = (phy << 1);
+
+		/* If current PHY is one of the PHY in the Scanning_PHYs,
+		 * pick the supplied scan type, interval and window.
+		 */
+		if (phys & phy) {
+			type |= (p->type & 0x01);
+			interval = sys_le16_to_cpu(p->interval);
+			window = sys_le16_to_cpu(p->window);
+			p++;
+		} else {
+			interval = 0U;
+			window = 0U;
+		}
+
+		status = ll_scan_params_set(type, interval, window,
+					    own_addr_type, filter_policy);
+		if (status) {
+			break;
+		}
+
+		phys_bitmask &= (phys_bitmask - 1);
+	} while (phys_bitmask);
+
+	*evt = cmd_complete_status(status);
+}
+
+static void le_set_ext_scan_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_ext_scan_enable *cmd = (void *)buf->data;
+	uint8_t status;
+
+	if (adv_cmds_ext_check(evt)) {
+		return;
+	}
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	/* initialize duplicate filtering */
+	if (cmd->enable && cmd->filter_dup) {
+		dup_count = 0;
+		dup_curr = 0U;
+	} else {
+		dup_count = -1;
+	}
+#endif
+
+	/* FIXME: Add implementation to use duration and period parameters. */
+	status = ll_scan_enable(cmd->enable);
+
+	*evt = cmd_complete_status(status);
+}
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+static void le_per_adv_create_sync(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_per_adv_create_sync *cmd = (void *)buf->data;
+	uint16_t sync_timeout;
+	uint8_t status;
+	uint16_t skip;
+
+	skip = sys_le16_to_cpu(cmd->skip);
+	sync_timeout = sys_le16_to_cpu(cmd->sync_timeout);
+
+	status = ll_sync_create(cmd->options, cmd->sid, cmd->addr.type,
+				cmd->addr.a.val, skip, sync_timeout,
+				cmd->cte_type);
+
+	*evt = cmd_status(status);
+}
+
+static void le_per_adv_create_sync_cancel(struct net_buf *buf,
+					  struct net_buf **evt, void **node_rx)
+{
+	struct bt_hci_evt_cc_status *ccst;
+	uint8_t status;
+
+	status = ll_sync_create_cancel(node_rx);
+
+	ccst = hci_cmd_complete(evt, sizeof(*ccst));
+	ccst->status = status;
+}
+
+static void le_per_adv_terminate_sync(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_per_adv_terminate_sync *cmd = (void *)buf->data;
+	struct bt_hci_evt_cc_status *ccst;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	status = ll_sync_terminate(handle);
+
+	ccst = hci_cmd_complete(evt, sizeof(*ccst));
+	ccst->status = status;
+}
+
+static void le_per_adv_recv_enable(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_set_per_adv_recv_enable *cmd = (void *)buf->data;
+	struct bt_hci_evt_cc_status *ccst;
+	uint16_t handle;
+	uint8_t status;
+
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	status = ll_sync_recv_enable(handle, cmd->enable);
+
+	ccst = hci_cmd_complete(evt, sizeof(*ccst));
+	ccst->status = status;
+}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CENTRAL)
+static void le_ext_create_connection(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_le_ext_create_conn *cmd = (void *)buf->data;
+	struct bt_hci_ext_conn_phy *p;
+	uint8_t peer_addr_type;
+	uint8_t own_addr_type;
+	uint8_t filter_policy;
+	uint8_t phys_bitmask;
+	uint8_t *peer_addr;
+	uint8_t status;
+	uint8_t phys;
+
+	if (adv_cmds_ext_check(NULL)) {
+		*evt = cmd_status(BT_HCI_ERR_CMD_DISALLOWED);
+		return;
+	}
+
+	/* TODO: add parameter checks */
+
+	filter_policy = cmd->filter_policy;
+	own_addr_type = cmd->own_addr_type;
+	peer_addr_type = cmd->peer_addr.type;
+	peer_addr = cmd->peer_addr.a.val;
+	phys = cmd->phys;
+	p = cmd->p;
+
+	/* Number of bits set indicate scan sets to be configured by calling
+	 * ll_create_connection function.
+	 */
+	phys_bitmask = BT_HCI_LE_EXT_SCAN_PHY_1M;
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		phys_bitmask |= BT_HCI_LE_EXT_SCAN_PHY_CODED;
+	}
+
+	do {
+		uint16_t supervision_timeout;
+		uint16_t conn_interval_max;
+		uint16_t scan_interval;
+		uint16_t conn_latency;
+		uint16_t scan_window;
+		uint8_t phy;
+
+		phy = BIT(find_lsb_set(phys_bitmask) - 1);
+
+		if (phys & phy) {
+			scan_interval = sys_le16_to_cpu(p->scan_interval);
+			scan_window = sys_le16_to_cpu(p->scan_window);
+			conn_interval_max =
+				sys_le16_to_cpu(p->conn_interval_max);
+			conn_latency = sys_le16_to_cpu(p->conn_latency);
+			supervision_timeout =
+				sys_le16_to_cpu(p->supervision_timeout);
+
+			status = ll_create_connection(scan_interval,
+						      scan_window,
+						      filter_policy,
+						      peer_addr_type,
+						      peer_addr,
+						      own_addr_type,
+						      conn_interval_max,
+						      conn_latency,
+						      supervision_timeout,
+						      phy);
+			if (status) {
+				*evt = cmd_status(status);
+				return;
+			}
+
+			p++;
+		}
+
+		phys_bitmask &= (phys_bitmask - 1);
+	} while (phys_bitmask);
+
+	status = ll_connect_enable(phys & BT_HCI_LE_EXT_SCAN_PHY_CODED);
+
+	*evt = cmd_status(status);
+}
+#endif /* CONFIG_BT_CENTRAL */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+static int controller_cmd_handle(uint16_t  ocf, struct net_buf *cmd,
+				 struct net_buf **evt, void **node_rx)
+{
+	switch (ocf) {
+	case BT_OCF(BT_HCI_OP_LE_SET_EVENT_MASK):
+		le_set_event_mask(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_BUFFER_SIZE):
+		le_read_buffer_size(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_LOCAL_FEATURES):
+		le_read_local_features(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_RANDOM_ADDRESS):
+		le_set_random_address(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_FILTER)
+	case BT_OCF(BT_HCI_OP_LE_READ_WL_SIZE):
+		le_read_wl_size(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_CLEAR_WL):
+		le_clear_wl(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_ADD_DEV_TO_WL):
+		le_add_dev_to_wl(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_REM_DEV_FROM_WL):
+		le_rem_dev_from_wl(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_FILTER */
+
+	case BT_OCF(BT_HCI_OP_LE_ENCRYPT):
+		le_encrypt(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_RAND):
+		le_rand(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_SUPP_STATES):
+		le_read_supp_states(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_BROADCASTER)
+	case BT_OCF(BT_HCI_OP_LE_SET_ADV_PARAM):
+		le_set_adv_param(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER):
+		le_read_adv_chan_tx_power(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_ADV_DATA):
+		le_set_adv_data(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_SCAN_RSP_DATA):
+		le_set_scan_rsp_data(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_ADV_ENABLE):
+		le_set_adv_enable(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_ADV_ISO)
+	case BT_OCF(BT_HCI_OP_LE_CREATE_BIG):
+		le_create_big(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_CREATE_BIG_TEST):
+		le_create_big_test(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_TERMINATE_BIG):
+		le_terminate_big(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_ADV_ISO */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	case BT_OCF(BT_HCI_OP_LE_SET_SCAN_PARAM):
+		le_set_scan_param(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_SCAN_ENABLE):
+		le_set_scan_enable(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_SYNC_ISO)
+	case BT_OCF(BT_HCI_OP_LE_BIG_CREATE_SYNC):
+		le_big_create_sync(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_BIG_TERMINATE_SYNC):
+		le_big_terminate_sync(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_SYNC_ISO */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+	case BT_OCF(BT_HCI_OP_LE_CREATE_CONN):
+		le_create_connection(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_CREATE_CONN_CANCEL):
+		le_create_conn_cancel(cmd, evt, node_rx);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF):
+		le_set_host_chan_classif(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case BT_OCF(BT_HCI_OP_LE_START_ENCRYPTION):
+		le_start_encryption(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case BT_OCF(BT_HCI_OP_LE_LTK_REQ_REPLY):
+		le_ltk_req_reply(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY):
+		le_ltk_req_neg_reply(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	case BT_OCF(BT_HCI_OP_LE_READ_CHAN_MAP):
+		le_read_chan_map(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_REMOTE_FEATURES):
+		le_read_remote_features(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_CONN_UPDATE):
+		le_conn_update(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	case BT_OCF(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY):
+		le_conn_param_req_reply(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY):
+		le_conn_param_req_neg_reply(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	case BT_OCF(BT_HCI_OP_LE_SET_DATA_LEN):
+		le_set_data_len(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN):
+		le_read_default_data_len(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN):
+		le_write_default_data_len(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_MAX_DATA_LEN):
+		le_read_max_data_len(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case BT_OCF(BT_HCI_OP_LE_READ_PHY):
+		le_read_phy(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_DEFAULT_PHY):
+		le_set_default_phy(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_PHY):
+		le_set_phy(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_BROADCASTER)
+	case BT_OCF(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR):
+		le_set_adv_set_random_addr(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_ADV_PARAM):
+		le_set_ext_adv_param(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_ADV_DATA):
+		le_set_ext_adv_data(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA):
+		le_set_ext_scan_rsp_data(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE):
+		le_set_ext_adv_enable(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN):
+		le_read_max_adv_data_len(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_READ_NUM_ADV_SETS):
+		le_read_num_adv_sets(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_REMOVE_ADV_SET):
+		le_remove_adv_set(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_CLEAR_ADV_SETS):
+		le_clear_adv_sets(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	case BT_OCF(BT_HCI_OP_LE_SET_PER_ADV_PARAM):
+		le_set_per_adv_param(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_PER_ADV_DATA):
+		le_set_per_adv_data(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_PER_ADV_ENABLE):
+		le_set_per_adv_enable(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_SCAN_PARAM):
+		le_set_ext_scan_param(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE):
+		le_set_ext_scan_enable(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	case BT_OCF(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC):
+		le_per_adv_create_sync(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL):
+		le_per_adv_create_sync_cancel(cmd, evt, node_rx);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC):
+		le_per_adv_terminate_sync(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE):
+		le_per_adv_recv_enable(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+	case BT_OCF(BT_HCI_OP_LE_EXT_CREATE_CONN):
+		le_ext_create_connection(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CENTRAL */
+#endif /* CONFIG_BT_CONN */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	case BT_OCF(BT_HCI_OP_LE_ADD_DEV_TO_RL):
+		le_add_dev_to_rl(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_REM_DEV_FROM_RL):
+		le_rem_dev_from_rl(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_CLEAR_RL):
+		le_clear_rl(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_READ_RL_SIZE):
+		le_read_rl_size(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_READ_PEER_RPA):
+		le_read_peer_rpa(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_READ_LOCAL_RPA):
+		le_read_local_rpa(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE):
+		le_set_addr_res_enable(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_SET_RPA_TIMEOUT):
+		le_set_rpa_timeout(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_SET_PRIVACY_MODE):
+		le_set_privacy_mode(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	case BT_OCF(BT_HCI_OP_LE_READ_TX_POWER):
+		le_read_tx_power(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_DTM_HCI)
+	case BT_OCF(BT_HCI_OP_LE_RX_TEST):
+		le_rx_test(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_TX_TEST):
+		le_tx_test(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_TEST_END):
+		le_test_end(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_ENH_RX_TEST):
+		le_enh_rx_test(cmd, evt);
+		break;
+	case BT_OCF(BT_HCI_OP_LE_ENH_TX_TEST):
+		le_enh_tx_test(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_DTM_HCI */
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_HCI_VS)
+static void vs_read_version_info(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_version_info *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	rp->hw_platform = sys_cpu_to_le16(BT_HCI_VS_HW_PLAT);
+	rp->hw_variant = sys_cpu_to_le16(BT_HCI_VS_HW_VAR);
+
+	rp->fw_variant = 0U;
+	rp->fw_version = (KERNEL_VERSION_MAJOR & 0xff);
+	rp->fw_revision = sys_cpu_to_le16(KERNEL_VERSION_MINOR);
+	rp->fw_build = sys_cpu_to_le32(KERNEL_PATCHLEVEL & 0xffff);
+}
+
+static void vs_read_supported_commands(struct net_buf *buf,
+				       struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_supported_commands *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	(void)memset(&rp->commands[0], 0, sizeof(rp->commands));
+
+	/* Set Version Information, Supported Commands, Supported Features. */
+	rp->commands[0] |= BIT(0) | BIT(1) | BIT(2);
+#if defined(CONFIG_BT_HCI_VS_EXT)
+	/* Write BD_ADDR, Read Build Info */
+	rp->commands[0] |= BIT(5) | BIT(7);
+	/* Read Static Addresses, Read Key Hierarchy Roots */
+	rp->commands[1] |= BIT(0) | BIT(1);
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	/* Write Tx Power, Read Tx Power */
+	rp->commands[1] |= BIT(5) | BIT(6);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+#if defined(CONFIG_USB_DEVICE_BLUETOOTH_VS_H4)
+	/* Read Supported USB Transport Modes */
+	rp->commands[1] |= BIT(7);
+	/* Set USB Transport Mode */
+	rp->commands[2] |= BIT(0);
+#endif /* USB_DEVICE_BLUETOOTH_VS_H4 */
+#endif /* CONFIG_BT_HCI_VS_EXT */
+}
+
+static void vs_read_supported_features(struct net_buf *buf,
+				       struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_supported_features *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	(void)memset(&rp->features[0], 0x00, sizeof(rp->features));
+}
+
+uint8_t __weak hci_vendor_read_static_addr(struct bt_hci_vs_static_addr addrs[],
+					uint8_t size)
+{
+	ARG_UNUSED(addrs);
+	ARG_UNUSED(size);
+
+	return 0;
+}
+
+/* If Zephyr VS HCI commands are not enabled provide this functionality directly
+ */
+#if !defined(CONFIG_BT_HCI_VS_EXT)
+uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size)
+{
+	return hci_vendor_read_static_addr(addrs, size);
+}
+#endif /* !defined(CONFIG_BT_HCI_VS_EXT) */
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+static void vs_write_bd_addr(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_vs_write_bd_addr *cmd = (void *)buf->data;
+
+	ll_addr_set(0, &cmd->bdaddr.val[0]);
+
+	*evt = cmd_complete_status(0x00);
+}
+
+static void vs_read_build_info(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_build_info *rp;
+
+#define HCI_VS_BUILD_INFO "Zephyr OS v" \
+	KERNEL_VERSION_STRING CONFIG_BT_CTLR_HCI_VS_BUILD_INFO
+
+	const char build_info[] = HCI_VS_BUILD_INFO;
+
+#define BUILD_INFO_EVT_LEN (sizeof(struct bt_hci_evt_hdr) + \
+			    sizeof(struct bt_hci_evt_cmd_complete) + \
+			    sizeof(struct bt_hci_rp_vs_read_build_info) + \
+			    sizeof(build_info))
+
+	BUILD_ASSERT(CONFIG_BT_RX_BUF_LEN >= BUILD_INFO_EVT_LEN);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp) + sizeof(build_info));
+	rp->status = 0x00;
+	memcpy(rp->info, build_info, sizeof(build_info));
+}
+
+void __weak hci_vendor_read_key_hierarchy_roots(uint8_t ir[16], uint8_t er[16])
+{
+	/* Mark IR as invalid */
+	(void)memset(ir, 0x00, 16);
+
+	/* Mark ER as invalid */
+	(void)memset(er, 0x00, 16);
+}
+
+static void vs_read_static_addrs(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_static_addrs *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp) +
+				   sizeof(struct bt_hci_vs_static_addr));
+	rp->status = 0x00;
+	rp->num_addrs = hci_vendor_read_static_addr(rp->a, 1);
+}
+
+static void vs_read_key_hierarchy_roots(struct net_buf *buf,
+					struct net_buf **evt)
+{
+	struct bt_hci_rp_vs_read_key_hierarchy_roots *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = 0x00;
+	hci_vendor_read_key_hierarchy_roots(rp->ir, rp->er);
+}
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+static void vs_write_tx_power_level(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_vs_write_tx_power_level *cmd = (void *)buf->data;
+	struct bt_hci_rp_vs_write_tx_power_level *rp;
+	uint8_t handle_type;
+	uint16_t handle;
+	uint8_t status;
+
+	handle_type = cmd->handle_type;
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->selected_tx_power = cmd->tx_power_level;
+
+	status = ll_tx_pwr_lvl_set(handle_type, handle, &rp->selected_tx_power);
+
+	rp->status = status;
+	rp->handle_type = handle_type;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+
+static void vs_read_tx_power_level(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_vs_read_tx_power_level *cmd = (void *)buf->data;
+	struct bt_hci_rp_vs_read_tx_power_level *rp;
+	uint8_t handle_type;
+	uint16_t handle;
+	uint8_t status;
+
+	handle_type = cmd->handle_type;
+	handle = sys_le16_to_cpu(cmd->handle);
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	status = ll_tx_pwr_lvl_get(handle_type, handle, 0, &rp->tx_power_level);
+
+	rp->status = status;
+	rp->handle_type = handle_type;
+	rp->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+#endif /* CONFIG_BT_HCI_VS_EXT */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+static void mesh_get_opts(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_rp_mesh_get_opts *rp;
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+
+	rp->status = 0x00;
+	rp->opcode = BT_HCI_OC_MESH_GET_OPTS;
+
+	rp->revision = BT_HCI_MESH_REVISION;
+	rp->ch_map = 0x7;
+	/*@todo: nRF51 only */
+	rp->min_tx_power = -30;
+	/*@todo: nRF51 only */
+	rp->max_tx_power = 4;
+	rp->max_scan_filter = CONFIG_BT_CTLR_MESH_SCAN_FILTERS;
+	rp->max_filter_pattern = CONFIG_BT_CTLR_MESH_SF_PATTERNS;
+	rp->max_adv_slot = 1U;
+	rp->evt_prefix_len = 0x01;
+	rp->evt_prefix = BT_HCI_MESH_EVT_PREFIX;
+}
+
+static void mesh_set_scan_filter(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_mesh_set_scan_filter *cmd = (void *)buf->data;
+	struct bt_hci_rp_mesh_set_scan_filter *rp;
+	uint8_t filter = cmd->scan_filter - 1;
+	struct scan_filter *f;
+	uint8_t status = 0x00;
+	uint8_t i;
+
+	if (filter > ARRAY_SIZE(scan_filters) ||
+	    cmd->num_patterns > CONFIG_BT_CTLR_MESH_SF_PATTERNS) {
+		status = BT_HCI_ERR_INVALID_PARAM;
+		goto exit;
+	}
+
+	if (filter == sf_curr) {
+		status = BT_HCI_ERR_CMD_DISALLOWED;
+		goto exit;
+	}
+
+	/* duplicate filtering not supported yet */
+	if (cmd->filter_dup) {
+		status = BT_HCI_ERR_INVALID_PARAM;
+		goto exit;
+	}
+
+	f = &scan_filters[filter];
+	for (i = 0U; i < cmd->num_patterns; i++) {
+		if (!cmd->patterns[i].pattern_len ||
+		    cmd->patterns[i].pattern_len >
+		    BT_HCI_MESH_PATTERN_LEN_MAX) {
+			status = BT_HCI_ERR_INVALID_PARAM;
+			goto exit;
+		}
+		f->lengths[i] = cmd->patterns[i].pattern_len;
+		memcpy(f->patterns[i], cmd->patterns[i].pattern, f->lengths[i]);
+	}
+
+	f->count = cmd->num_patterns;
+
+exit:
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->opcode = BT_HCI_OC_MESH_SET_SCAN_FILTER;
+	rp->scan_filter = filter + 1;
+}
+
+static void mesh_advertise(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_mesh_advertise *cmd = (void *)buf->data;
+	struct bt_hci_rp_mesh_advertise *rp;
+	uint8_t adv_slot = cmd->adv_slot;
+	uint8_t status;
+
+	status = ll_mesh_advertise(adv_slot,
+				   cmd->own_addr_type, cmd->random_addr.val,
+				   cmd->ch_map, cmd->tx_power,
+				   cmd->min_tx_delay, cmd->max_tx_delay,
+				   cmd->retx_count, cmd->retx_interval,
+				   cmd->scan_duration, cmd->scan_delay,
+				   cmd->scan_filter, cmd->data_len, cmd->data);
+	if (!status) {
+		/* Yields 0xFF if no scan filter selected */
+		sf_curr = cmd->scan_filter - 1;
+	}
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->opcode = BT_HCI_OC_MESH_ADVERTISE;
+	rp->adv_slot = adv_slot;
+}
+
+static void mesh_advertise_cancel(struct net_buf *buf, struct net_buf **evt)
+{
+	struct bt_hci_cp_mesh_advertise_cancel *cmd = (void *)buf->data;
+	struct bt_hci_rp_mesh_advertise_cancel *rp;
+	uint8_t adv_slot = cmd->adv_slot;
+	uint8_t status;
+
+	status = ll_mesh_advertise_cancel(adv_slot);
+	if (!status) {
+		/* Yields 0xFF if no scan filter selected */
+		sf_curr = 0xFF;
+	}
+
+	rp = hci_cmd_complete(evt, sizeof(*rp));
+	rp->status = status;
+	rp->opcode = BT_HCI_OC_MESH_ADVERTISE_CANCEL;
+	rp->adv_slot = adv_slot;
+}
+
+static int mesh_cmd_handle(struct net_buf *cmd, struct net_buf **evt)
+{
+	struct bt_hci_cp_mesh *cp_mesh;
+	uint8_t mesh_op;
+
+	if (cmd->len < sizeof(*cp_mesh)) {
+		BT_ERR("No HCI VSD Command header");
+		return -EINVAL;
+	}
+
+	cp_mesh = net_buf_pull_mem(cmd, sizeof(*cp_mesh));
+	mesh_op = cp_mesh->opcode;
+
+	switch (mesh_op) {
+	case BT_HCI_OC_MESH_GET_OPTS:
+		mesh_get_opts(cmd, evt);
+		break;
+
+	case BT_HCI_OC_MESH_SET_SCAN_FILTER:
+		mesh_set_scan_filter(cmd, evt);
+		break;
+
+	case BT_HCI_OC_MESH_ADVERTISE:
+		mesh_advertise(cmd, evt);
+		break;
+
+	case BT_HCI_OC_MESH_ADVERTISE_CANCEL:
+		mesh_advertise_cancel(cmd, evt);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+int hci_vendor_cmd_handle_common(uint16_t ocf, struct net_buf *cmd,
+				 struct net_buf **evt)
+{
+	switch (ocf) {
+	case BT_OCF(BT_HCI_OP_VS_READ_VERSION_INFO):
+		vs_read_version_info(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS):
+		vs_read_supported_commands(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_READ_SUPPORTED_FEATURES):
+		vs_read_supported_features(cmd, evt);
+		break;
+
+#if defined(CONFIG_USB_DEVICE_BLUETOOTH_VS_H4)
+	case BT_OCF(BT_HCI_OP_VS_READ_USB_TRANSPORT_MODE):
+		break;
+	case BT_OCF(BT_HCI_OP_VS_SET_USB_TRANSPORT_MODE):
+		reset(cmd, evt);
+		break;
+#endif /* CONFIG_USB_DEVICE_BLUETOOTH_VS_H4 */
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+	case BT_OCF(BT_HCI_OP_VS_READ_BUILD_INFO):
+		vs_read_build_info(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_WRITE_BD_ADDR):
+		vs_write_bd_addr(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_READ_STATIC_ADDRS):
+		vs_read_static_addrs(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS):
+		vs_read_key_hierarchy_roots(cmd, evt);
+		break;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	case BT_OCF(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL):
+		vs_write_tx_power_level(cmd, evt);
+		break;
+
+	case BT_OCF(BT_HCI_OP_VS_READ_TX_POWER_LEVEL):
+		vs_read_tx_power_level(cmd, evt);
+		break;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+#endif /* CONFIG_BT_HCI_VS_EXT */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	case BT_OCF(BT_HCI_OP_VS_MESH):
+		mesh_cmd_handle(cmd, evt);
+		break;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
+struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx)
+{
+	struct bt_hci_cmd_hdr *chdr;
+	struct net_buf *evt = NULL;
+	uint16_t ocf;
+	int err;
+
+	if (cmd->len < sizeof(*chdr)) {
+		BT_ERR("No HCI Command header");
+		return NULL;
+	}
+
+	chdr = net_buf_pull_mem(cmd, sizeof(*chdr));
+	if (cmd->len < chdr->param_len) {
+		BT_ERR("Invalid HCI CMD packet length");
+		return NULL;
+	}
+
+	/* store in a global for later CC/CS event creation */
+	_opcode = sys_le16_to_cpu(chdr->opcode);
+
+	ocf = BT_OCF(_opcode);
+
+	switch (BT_OGF(_opcode)) {
+	case BT_OGF_LINK_CTRL:
+		err = link_control_cmd_handle(ocf, cmd, &evt);
+		break;
+	case BT_OGF_BASEBAND:
+		err = ctrl_bb_cmd_handle(ocf, cmd, &evt);
+		break;
+	case BT_OGF_INFO:
+		err = info_cmd_handle(ocf, cmd, &evt);
+		break;
+	case BT_OGF_STATUS:
+		err = status_cmd_handle(ocf, cmd, &evt);
+		break;
+	case BT_OGF_LE:
+		err = controller_cmd_handle(ocf, cmd, &evt, node_rx);
+		break;
+#if defined(CONFIG_BT_HCI_VS)
+	case BT_OGF_VS:
+		err = hci_vendor_cmd_handle(ocf, cmd, &evt);
+		break;
+#endif
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	if (err == -EINVAL) {
+		evt = cmd_status(BT_HCI_ERR_UNKNOWN_CMD);
+	}
+
+	return evt;
+}
+
+#if defined(CONFIG_BT_CONN)
+static void data_buf_overflow(struct net_buf **buf)
+{
+	struct bt_hci_evt_data_buf_overflow *ep;
+
+	if (!(event_mask & BT_EVT_MASK_DATA_BUFFER_OVERFLOW)) {
+		return;
+	}
+
+	*buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
+	hci_evt_create(*buf, BT_HCI_EVT_DATA_BUF_OVERFLOW, sizeof(*ep));
+	ep = net_buf_add(*buf, sizeof(*ep));
+
+	ep->link_type = BT_OVERFLOW_LINK_ACL;
+}
+
+int hci_acl_handle(struct net_buf *buf, struct net_buf **evt)
+{
+	struct node_tx *node_tx;
+	struct bt_hci_acl_hdr *acl;
+	struct pdu_data *pdu_data;
+	uint16_t handle;
+	uint8_t flags;
+	uint16_t len;
+
+	*evt = NULL;
+
+	if (buf->len < sizeof(*acl)) {
+		BT_ERR("No HCI ACL header");
+		return -EINVAL;
+	}
+
+	acl = net_buf_pull_mem(buf, sizeof(*acl));
+	len = sys_le16_to_cpu(acl->len);
+	handle = sys_le16_to_cpu(acl->handle);
+
+	if (buf->len < len) {
+		BT_ERR("Invalid HCI ACL packet length");
+		return -EINVAL;
+	}
+
+	/* assigning flags first because handle will be overwritten */
+	flags = bt_acl_flags(handle);
+	handle = bt_acl_handle(handle);
+
+	node_tx = ll_tx_mem_acquire();
+	if (!node_tx) {
+		BT_ERR("Tx Buffer Overflow");
+		data_buf_overflow(evt);
+		return -ENOBUFS;
+	}
+
+	pdu_data = (void *)node_tx->pdu;
+
+	if (bt_acl_flags_bc(flags) != BT_ACL_POINT_TO_POINT) {
+		return -EINVAL;
+	}
+
+	switch (bt_acl_flags_pb(flags)) {
+	case BT_ACL_START_NO_FLUSH:
+		pdu_data->ll_id = PDU_DATA_LLID_DATA_START;
+		break;
+	case BT_ACL_CONT:
+		pdu_data->ll_id = PDU_DATA_LLID_DATA_CONTINUE;
+		break;
+	default:
+		/* BT_ACL_START and BT_ACL_COMPLETE not allowed on LE-U
+		 * from Host to Controller
+		 */
+		return -EINVAL;
+	}
+
+	pdu_data->len = len;
+	memcpy(&pdu_data->lldata[0], buf->data, len);
+
+	if (ll_tx_mem_enqueue(handle, node_tx)) {
+		BT_ERR("Invalid Tx Enqueue");
+		ll_tx_mem_release(node_tx);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CONN */
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+static inline bool dup_found(struct pdu_adv *adv)
+{
+	/* check for duplicate filtering */
+	if (dup_count >= 0) {
+		int i;
+
+		for (i = 0; i < dup_count; i++) {
+			if (!memcmp(&adv->adv_ind.addr[0],
+				    &dup_filter[i].addr.a.val[0],
+				    sizeof(bt_addr_t)) &&
+			    adv->tx_addr == dup_filter[i].addr.type) {
+
+				if (dup_filter[i].mask & BIT(adv->type)) {
+					/* duplicate found */
+					return true;
+				}
+				/* report different adv types */
+				dup_filter[i].mask |= BIT(adv->type);
+				return false;
+			}
+		}
+
+		/* insert into the duplicate filter */
+		memcpy(&dup_filter[dup_curr].addr.a.val[0],
+		       &adv->adv_ind.addr[0], sizeof(bt_addr_t));
+		dup_filter[dup_curr].addr.type = adv->tx_addr;
+		dup_filter[dup_curr].mask = BIT(adv->type);
+
+		if (dup_count < CONFIG_BT_CTLR_DUP_FILTER_LEN) {
+			dup_count++;
+			dup_curr = dup_count;
+		} else {
+			dup_curr++;
+		}
+
+		if (dup_curr == CONFIG_BT_CTLR_DUP_FILTER_LEN) {
+			dup_curr = 0U;
+		}
+	}
+
+	return false;
+}
+#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
+
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+static inline void le_dir_adv_report(struct pdu_adv *adv, struct net_buf *buf,
+				     int8_t rssi, uint8_t rl_idx)
+{
+	struct bt_hci_evt_le_direct_adv_report *drp;
+	struct bt_hci_evt_le_direct_adv_info *dir_info;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_DIRECT_ADV_REPORT)) {
+		return;
+	}
+
+	LL_ASSERT(adv->type == PDU_ADV_TYPE_DIRECT_IND);
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	if (dup_found(adv)) {
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
+
+	drp = meta_evt(buf, BT_HCI_EVT_LE_DIRECT_ADV_REPORT,
+		       sizeof(*drp) + sizeof(*dir_info));
+
+	drp->num_reports = 1U;
+	dir_info = (void *)(((uint8_t *)drp) + sizeof(*drp));
+
+	/* Directed Advertising */
+	dir_info->evt_type = BT_HCI_ADV_DIRECT_IND;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (rl_idx < ll_rl_size_get()) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &dir_info->addr.type,
+				  &dir_info->addr.a.val[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		dir_info->addr.type += 2U;
+	} else {
+#else
+	if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		dir_info->addr.type = adv->tx_addr;
+		memcpy(&dir_info->addr.a.val[0], &adv->direct_ind.adv_addr[0],
+		       sizeof(bt_addr_t));
+	}
+
+	dir_info->dir_addr.type = adv->rx_addr;
+	memcpy(&dir_info->dir_addr.a.val[0],
+	       &adv->direct_ind.tgt_addr[0], sizeof(bt_addr_t));
+
+	dir_info->rssi = rssi;
+}
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+#if defined(CONFIG_BT_OBSERVER)
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+static inline bool scan_filter_apply(uint8_t filter, uint8_t *data, uint8_t len)
+{
+	struct scan_filter *f = &scan_filters[filter];
+	int i;
+
+	/* No patterns means filter out all advertising packets */
+	for (i = 0; i < f->count; i++) {
+		/* Require at least the length of the pattern */
+		if (len >= f->lengths[i] &&
+		    !memcmp(data, f->patterns[i], f->lengths[i])) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static inline void le_mesh_scan_report(struct pdu_adv *adv,
+				       struct node_rx_pdu *node_rx,
+				       struct net_buf *buf, int8_t rssi)
+{
+	uint8_t data_len = (adv->len - BDADDR_SIZE);
+	struct bt_hci_evt_mesh_scanning_report *mep;
+	struct bt_hci_evt_mesh_scan_report *sr;
+	uint32_t instant;
+	uint8_t chan;
+
+	LL_ASSERT(adv->type == PDU_ADV_TYPE_NONCONN_IND);
+
+	/* Filter based on currently active Scan Filter */
+	if (sf_curr < ARRAY_SIZE(scan_filters) &&
+	    !scan_filter_apply(sf_curr, &adv->adv_ind.data[0], data_len)) {
+		/* Drop the report */
+		return;
+	}
+
+	chan = node_rx->hdr.rx_ftr.chan;
+	instant = node_rx->hdr.rx_ftr.anchor_ticks;
+
+	mep = mesh_evt(buf, BT_HCI_EVT_MESH_SCANNING_REPORT,
+			    sizeof(*mep) + sizeof(*sr));
+
+	mep->num_reports = 1U;
+	sr = (void *)(((uint8_t *)mep) + sizeof(*mep));
+	sr->addr.type = adv->tx_addr;
+	memcpy(&sr->addr.a.val[0], &adv->adv_ind.addr[0], sizeof(bt_addr_t));
+	sr->chan = chan;
+	sr->rssi = rssi;
+	sys_put_le32(instant, (uint8_t *)&sr->instant);
+
+	sr->data_len = data_len;
+	memcpy(&sr->data[0], &adv->adv_ind.data[0], data_len);
+}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+static void le_advertising_report(struct pdu_data *pdu_data,
+				  struct node_rx_pdu *node_rx,
+				  struct net_buf *buf)
+{
+	const uint8_t c_adv_type[] = { 0x00, 0x01, 0x03, 0xff, 0x04,
+				    0xff, 0x02 };
+	struct bt_hci_evt_le_advertising_report *sep;
+	struct pdu_adv *adv = (void *)pdu_data;
+	struct bt_hci_evt_le_advertising_info *adv_info;
+	uint8_t data_len;
+	uint8_t info_len;
+	int8_t rssi;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	uint8_t direct;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+	int8_t *prssi;
+
+	rssi = -(node_rx->hdr.rx_ftr.rssi);
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	rl_idx = node_rx->hdr.rx_ftr.rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	direct = node_rx->hdr.rx_ftr.direct;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (adv->tx_addr) {
+		/* Update current RPA */
+		ll_rl_crpa_set(0x00, NULL, rl_idx, &adv->adv_ind.addr[0]);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	if (direct) {
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		le_dir_adv_report(adv, buf, rssi, rl_idx);
+#else
+		le_dir_adv_report(adv, buf, rssi, 0xFF);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
+		le_mesh_scan_report(adv, node_rx, buf, rssi);
+		return;
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_ADVERTISING_REPORT)) {
+		return;
+	}
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	if (dup_found(adv)) {
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
+
+	if (adv->type != PDU_ADV_TYPE_DIRECT_IND) {
+		data_len = (adv->len - BDADDR_SIZE);
+	} else {
+		data_len = 0U;
+	}
+	info_len = sizeof(struct bt_hci_evt_le_advertising_info) + data_len +
+		   sizeof(*prssi);
+	sep = meta_evt(buf, BT_HCI_EVT_LE_ADVERTISING_REPORT,
+		       sizeof(*sep) + info_len);
+
+	sep->num_reports = 1U;
+	adv_info = (void *)(((uint8_t *)sep) + sizeof(*sep));
+
+	adv_info->evt_type = c_adv_type[adv->type];
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (rl_idx < ll_rl_size_get()) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
+				  &adv_info->addr.a.val[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		adv_info->addr.type += 2U;
+	} else {
+#else
+	if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		adv_info->addr.type = adv->tx_addr;
+		memcpy(&adv_info->addr.a.val[0], &adv->adv_ind.addr[0],
+		       sizeof(bt_addr_t));
+	}
+
+	adv_info->length = data_len;
+	memcpy(&adv_info->data[0], &adv->adv_ind.data[0], data_len);
+	/* RSSI */
+	prssi = &adv_info->data[0] + data_len;
+	*prssi = rssi;
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static void le_ext_adv_legacy_report(struct pdu_data *pdu_data,
+				     struct node_rx_pdu *node_rx,
+				     struct net_buf *buf)
+{
+	/* Lookup event type based on pdu_adv_type set by LLL */
+	const uint8_t evt_type_lookup[] = {
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY | BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+		 BT_HCI_LE_ADV_EVT_TYPE_CONN),   /* ADV_IND */
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY | BT_HCI_LE_ADV_EVT_TYPE_DIRECT |
+		 BT_HCI_LE_ADV_EVT_TYPE_CONN),   /* DIRECT_IND */
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY), /* NONCONN_IND */
+		0xff,                            /* Invalid index lookup */
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY |
+		 BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP |
+		 BT_HCI_LE_ADV_EVT_TYPE_SCAN),   /* SCAN_RSP to an ADV_SCAN_IND
+						  */
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY |
+		 BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP |
+		 BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+		 BT_HCI_LE_ADV_EVT_TYPE_CONN), /* SCAN_RSP to an ADV_IND,
+						* NOTE: LLL explicitly sets
+						* adv_type to
+						* PDU_ADV_TYPE_ADV_IND_SCAN_RSP
+						*/
+		(BT_HCI_LE_ADV_EVT_TYPE_LEGACY |
+		 BT_HCI_LE_ADV_EVT_TYPE_SCAN)    /* SCAN_IND */
+	};
+	struct bt_hci_evt_le_ext_advertising_info *adv_info;
+	struct bt_hci_evt_le_ext_advertising_report *sep;
+	struct pdu_adv *adv = (void *)pdu_data;
+	uint8_t data_len;
+	uint8_t info_len;
+	int8_t rssi;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	uint8_t direct;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT)) {
+		return;
+	}
+
+	/* The Link Layer currently returns RSSI as an absolute value */
+	rssi = -(node_rx->hdr.rx_ftr.rssi);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	rl_idx = node_rx->hdr.rx_ftr.rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	direct = node_rx->hdr.rx_ftr.direct;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (adv->tx_addr) {
+		/* Update current RPA */
+		ll_rl_crpa_set(0x00, NULL, rl_idx, &adv->adv_ind.addr[0]);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
+	if (dup_found(adv)) {
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
+
+	if (adv->type != PDU_ADV_TYPE_DIRECT_IND) {
+		data_len = (adv->len - BDADDR_SIZE);
+	} else {
+		data_len = 0U;
+	}
+
+	info_len = sizeof(struct bt_hci_evt_le_ext_advertising_info) +
+		   data_len;
+	sep = meta_evt(buf, BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT,
+		       sizeof(*sep) + info_len);
+
+	sep->num_reports = 1U;
+	adv_info = (void *)(((uint8_t *)sep) + sizeof(*sep));
+
+	adv_info->evt_type = evt_type_lookup[adv->type];
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (rl_idx < ll_rl_size_get()) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
+				  &adv_info->addr.a.val[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		adv_info->addr.type += 2U;
+	} else
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	{
+		adv_info->addr.type = adv->tx_addr;
+		memcpy(&adv_info->addr.a.val[0], &adv->adv_ind.addr[0],
+		       sizeof(bt_addr_t));
+	}
+
+	adv_info->prim_phy = BT_HCI_LE_EXT_SCAN_PHY_1M;
+	adv_info->sec_phy = 0U;
+	adv_info->sid = 0xff;
+	adv_info->tx_power = 0x7f;
+	adv_info->rssi = rssi;
+	adv_info->interval = 0U;
+
+	adv_info->direct_addr.type = adv->rx_addr;
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	if (direct) {
+		memcpy(&adv_info->direct_addr.a.val[0],
+		       &adv->direct_ind.tgt_addr[0], sizeof(bt_addr_t));
+	} else
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+	{
+		memset(&adv_info->direct_addr.a.val[0], 0, sizeof(bt_addr_t));
+	}
+
+	adv_info->length = data_len;
+	memcpy(&adv_info->data[0], &adv->adv_ind.data[0], data_len);
+}
+
+static void le_ext_adv_report(struct pdu_data *pdu_data,
+			      struct node_rx_pdu *node_rx,
+			      struct net_buf *buf, uint8_t phy)
+{
+	struct bt_hci_evt_le_ext_advertising_info *adv_info;
+	struct bt_hci_evt_le_ext_advertising_report *sep;
+	struct pdu_adv *adv = (void *)pdu_data;
+	struct node_rx_pdu *node_rx_curr;
+	struct node_rx_pdu *node_rx_next;
+	struct pdu_adv_adi *adi = NULL;
+	uint8_t direct_addr_type = 0U;
+	uint8_t *direct_addr = NULL;
+	uint8_t total_data_len = 0U;
+	uint16_t interval_le16 = 0U;
+	uint8_t adv_addr_type = 0U;
+	uint8_t *adv_addr = NULL;
+	uint8_t data_status = 0U;
+	uint8_t data_len = 0U;
+	uint8_t evt_type = 0U;
+	int8_t tx_pwr = 0x7f;
+	uint8_t *data = NULL;
+	uint8_t sec_phy = 0U;
+	int8_t rssi = 0x7f;
+	uint8_t info_len;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT)) {
+		return;
+	}
+
+	node_rx_curr = node_rx;
+	node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
+	do {
+		struct pdu_adv_adi *adi_curr = NULL;
+		uint8_t direct_addr_type_curr = 0U;
+		struct pdu_adv_com_ext_adv *p;
+		uint8_t *direct_addr_curr = NULL;
+		uint8_t adv_addr_type_curr = 0U;
+		uint8_t *adv_addr_curr = NULL;
+		uint8_t data_len_curr = 0U;
+		uint8_t *data_curr = NULL;
+		struct pdu_adv_hdr *h;
+		uint8_t sec_phy_curr = 0U;
+		uint8_t evt_type_curr;
+		uint8_t *ptr;
+
+		/* The Link Layer currently returns RSSI as an absolute value */
+		rssi = -(node_rx_curr->hdr.rx_ftr.rssi);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		rl_idx = node_rx_curr->hdr.rx_ftr.rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		BT_DBG("phy= 0x%x, type= 0x%x, len= %u, tat= %u, rat= %u,"
+		       " rssi=%d dB", phy, adv->type, adv->len, adv->tx_addr,
+		       adv->rx_addr, rssi);
+
+		p = (void *)&adv->adv_ext_ind;
+		h = (void *)p->ext_hdr_adi_adv_data;
+		ptr = (uint8_t *)h + sizeof(*h);
+
+		BT_DBG("    Ext. adv mode= 0x%x, hdr len= %u", p->adv_mode,
+		       p->ext_hdr_len);
+
+		evt_type_curr = p->adv_mode;
+
+		if (!p->ext_hdr_len) {
+			goto no_ext_hdr;
+		}
+
+		if (h->adv_addr) {
+			bt_addr_le_t addr;
+
+			adv_addr_type_curr = adv->tx_addr;
+			adv_addr_curr = ptr;
+
+			addr.type = adv->tx_addr;
+			memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
+			ptr += BDADDR_SIZE;
+
+			BT_DBG("    AdvA: %s", bt_addr_le_str(&addr));
+		}
+
+		if (h->tgt_addr) {
+			bt_addr_le_t addr;
+
+			direct_addr_type_curr = adv->rx_addr;
+			direct_addr_curr = ptr;
+
+			addr.type = adv->rx_addr;
+			memcpy(&addr.a.val[0], ptr, sizeof(bt_addr_t));
+			ptr += BDADDR_SIZE;
+
+			BT_DBG("    TgtA: %s", bt_addr_le_str(&addr));
+		}
+
+		if (h->adi) {
+			adi_curr = (void *)ptr;
+
+			ptr += sizeof(*adi);
+
+			BT_DBG("    AdvDataInfo DID = 0x%x, SID = 0x%x",
+			       adi->did, adi->sid);
+		}
+
+		if (h->aux_ptr) {
+			struct pdu_adv_aux_ptr *aux;
+			uint8_t aux_phy;
+
+			aux = (void *)ptr;
+			ptr += sizeof(*aux);
+
+			sec_phy_curr = aux->phy + 1;
+
+			aux_phy = BIT(aux->phy);
+
+			BT_DBG("    AuxPtr chan_idx = %u, ca = %u, offs_units "
+			       "= %u offs = 0x%x, phy = 0x%x", aux->chan_idx,
+			       aux->ca, aux->offs_units, aux->offs, aux_phy);
+		}
+
+		if (h->sync_info) {
+			struct pdu_adv_sync_info *si;
+
+			si = (void *)ptr;
+			ptr += sizeof(*si);
+
+			interval_le16 = si->interval;
+
+			BT_DBG("    SyncInfo offs = %u, offs_unit = 0x%x, "
+			       "interval = 0x%x, sca = 0x%x, "
+			       "chan map = 0x%x 0x%x 0x%x 0x%x 0x%x, "
+			       "AA = 0x%x, CRC = 0x%x 0x%x 0x%x, "
+			       "evt cntr = 0x%x",
+			       sys_le16_to_cpu(si->offs),
+			       si->offs_units,
+			       sys_le16_to_cpu(si->interval),
+			       (si->sca_chm[4] >> 5),
+			       si->sca_chm[0], si->sca_chm[1], si->sca_chm[2],
+			       si->sca_chm[3], (si->sca_chm[4] & 0x3F),
+			       sys_le32_to_cpu(si->aa),
+			       si->crc_init[0], si->crc_init[1],
+			       si->crc_init[2], sys_le16_to_cpu(si->evt_cntr));
+		}
+
+		if (h->tx_pwr) {
+			tx_pwr = *(int8_t *)ptr;
+			ptr++;
+
+			BT_DBG("    Tx pwr= %d dB", tx_pwr);
+		}
+
+		uint8_t len = ptr - (uint8_t *)p;
+		uint8_t hdr_len = len - offsetof(struct pdu_adv_com_ext_adv,
+					      ext_hdr_adi_adv_data);
+		if (hdr_len > p->ext_hdr_len) {
+			BT_WARN("    Header length %u/%u, INVALID.", hdr_len,
+				p->ext_hdr_len);
+		} else {
+			uint8_t acad_len = p->ext_hdr_len - hdr_len;
+
+			if (acad_len) {
+				ptr += acad_len;
+				len += acad_len;
+
+				BT_DBG("ACAD: <todo>");
+			}
+
+			if (len < adv->len) {
+				data_len_curr = adv->len - len;
+				data_curr = ptr;
+
+				BT_DBG("    AD Data (%u): <todo>", data_len);
+			}
+		}
+
+no_ext_hdr:
+		if (node_rx_curr == node_rx) {
+			evt_type = evt_type_curr;
+			adv_addr_type = adv_addr_type_curr;
+			adv_addr = adv_addr_curr;
+			direct_addr_type = direct_addr_type_curr;
+			direct_addr = direct_addr_curr;
+			adi = adi_curr;
+			sec_phy = sec_phy_curr;
+			data_len = data_len_curr;
+			total_data_len = data_len;
+			data = data_curr;
+		} else {
+			/* TODO: Validate current value with previous, also
+			 * detect the scan response in the list of node_rx.
+			 */
+
+			if (!adv_addr) {
+				adv_addr_type = adv_addr_type_curr;
+				adv_addr = adv_addr_curr;
+			}
+
+			if (!direct_addr) {
+				direct_addr_type = direct_addr_type_curr;
+				direct_addr = direct_addr_curr;
+			}
+
+			if (!data) {
+				data_len = data_len_curr;
+				total_data_len = data_len;
+				data = data_curr;
+			} else {
+				total_data_len += data_len_curr;
+
+				/* TODO: construct new HCI event for this
+				 * fragment.
+				 */
+			}
+		}
+
+		if (!node_rx_next) {
+			if (sec_phy_curr) {
+				data_status = BIT(1);
+			}
+
+			break;
+		}
+
+		node_rx_curr = node_rx_next;
+		node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
+		adv = (void *)node_rx_curr->pdu;
+	} while (1);
+
+	/* FIXME: move most of below into above loop to dispatch fragments of
+	 * data in HCI event.
+	 */
+
+	/* If data complete */
+	if (!data_status) {
+		uint8_t data_max_len;
+
+		data_max_len = CONFIG_BT_DISCARDABLE_BUF_SIZE -
+			       BT_HCI_ACL_HDR_SIZE - sizeof(*sep) -
+			       sizeof(*adv_info);
+
+		/* if data cannot fit the event, mark it as incomplete */
+		if (data_len > data_max_len) {
+			data_len = data_max_len;
+			data_status = BIT(0);
+		}
+	} else {
+		/* Data incomplete and no more to come */
+		if (!(adv_addr || (adi && ((tx_pwr != 0x7f) || data)))) {
+			goto le_ext_adv_report_invalid;
+		}
+	}
+
+	/* Start constructing the event */
+	info_len = sizeof(struct bt_hci_evt_le_ext_advertising_info) +
+		   data_len;
+	sep = meta_evt(buf, BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT,
+		       sizeof(*sep) + info_len);
+
+	sep->num_reports = 1U;
+	adv_info = (void *)(((uint8_t *)sep) + sizeof(*sep));
+
+	/* Set directed advertising bit */
+	if ((evt_type == BT_HCI_LE_ADV_EVT_TYPE_CONN) && direct_addr) {
+		evt_type |= BIT(2);
+	}
+
+	/* TODO: Set scan response bit */
+
+	/* set data status bits */
+	evt_type |= (data_status << 5);
+
+	adv_info->evt_type = evt_type;
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	} else if (rl_idx < ll_rl_size_get()) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
+				  &adv_info->addr.a.val[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		adv_info->addr.type += 2U;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	} else if (adv_addr) {
+		adv_info->addr.type = adv_addr_type;
+		memcpy(&adv_info->addr.a.val[0], adv_addr, sizeof(bt_addr_t));
+	} else {
+		adv_info->addr.type = 0U;
+		memset(&adv_info->addr.a.val[0], 0, sizeof(bt_addr_t));
+	}
+
+	adv_info->prim_phy = find_lsb_set(phy);
+	adv_info->sec_phy = sec_phy;
+	adv_info->sid = (adi) ? adi->sid : 0U;
+	adv_info->tx_power = tx_pwr;
+	adv_info->rssi = rssi;
+	adv_info->interval = interval_le16;
+
+	if (evt_type & BT_HCI_LE_ADV_EVT_TYPE_DIRECT) {
+		adv_info->direct_addr.type = direct_addr_type;
+		memcpy(&adv_info->direct_addr.a.val[0], direct_addr,
+		       sizeof(bt_addr_t));
+	} else {
+		adv_info->direct_addr.type = 0U;
+		memset(&adv_info->direct_addr.a.val[0], 0, sizeof(bt_addr_t));
+	}
+
+	adv_info->length = data_len;
+	memcpy(&adv_info->data[0], data, data_len);
+
+le_ext_adv_report_invalid:
+	/* Free the node_rx list */
+	node_rx_next = node_rx->hdr.rx_ftr.extra;
+	while (node_rx_next) {
+		node_rx_curr = node_rx_next;
+		node_rx_next = node_rx_curr->hdr.rx_ftr.extra;
+
+		node_rx_curr->hdr.next = NULL;
+		ll_rx_mem_release((void **)&node_rx_curr);
+	}
+}
+
+static void le_adv_ext_report(struct pdu_data *pdu_data,
+			      struct node_rx_pdu *node_rx,
+			      struct net_buf *buf, uint8_t phy)
+{
+	struct pdu_adv *adv = (void *)pdu_data;
+
+	if ((adv->type == PDU_ADV_TYPE_EXT_IND) && adv->len) {
+		le_ext_adv_report(pdu_data, node_rx, buf, phy);
+	} else {
+		le_ext_adv_legacy_report(pdu_data, node_rx, buf);
+	}
+}
+
+static void le_adv_ext_1M_report(struct pdu_data *pdu_data,
+				 struct node_rx_pdu *node_rx,
+				 struct net_buf *buf)
+{
+	le_adv_ext_report(pdu_data, node_rx, buf, BIT(0));
+}
+
+static void le_adv_ext_2M_report(struct pdu_data *pdu_data,
+				 struct node_rx_pdu *node_rx,
+				 struct net_buf *buf)
+{
+	le_adv_ext_report(pdu_data, node_rx, buf, BIT(1));
+}
+
+static void le_adv_ext_coded_report(struct pdu_data *pdu_data,
+				    struct node_rx_pdu *node_rx,
+				    struct net_buf *buf)
+{
+	le_adv_ext_report(pdu_data, node_rx, buf, BIT(2));
+}
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+static void le_per_adv_sync_established(struct pdu_data *pdu_data,
+					struct node_rx_pdu *node_rx,
+					struct net_buf *buf)
+{
+	struct bt_hci_evt_le_per_adv_sync_established *sep;
+	struct ll_scan_set *scan;
+	struct node_rx_sync *se;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED,
+		       sizeof(*sep));
+
+	se = (void *)pdu_data;
+	sep->status = se->status;
+	sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);
+
+	if (sep->status) {
+		return;
+	}
+
+	scan = node_rx->hdr.rx_ftr.param;
+
+	sep->sid = scan->per_scan.sid;
+	/* FIXME: fill based on filter_policy options */
+	sep->adv_addr.type = scan->per_scan.adv_addr_type;
+	memcpy(&sep->adv_addr.a.val[0], scan->per_scan.adv_addr, BDADDR_SIZE);
+	sep->phy = find_lsb_set(se->phy);
+	sep->interval = sys_cpu_to_le16(se->interval);
+	sep->clock_accuracy = se->sca;
+}
+
+static void le_per_adv_sync_lost(struct pdu_data *pdu_data,
+				 struct node_rx_pdu *node_rx,
+				 struct net_buf *buf)
+{
+	struct bt_hci_evt_le_per_adv_sync_lost *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_PER_ADV_SYNC_LOST)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_PER_ADV_SYNC_LOST, sizeof(*sep));
+	sep->handle = sys_cpu_to_le16(node_rx->hdr.handle);
+}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_BROADCASTER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static void le_adv_ext_terminate(struct pdu_data *pdu_data,
+				    struct node_rx_pdu *node_rx,
+				    struct net_buf *buf)
+{
+	struct bt_hci_evt_le_adv_set_terminated *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_ADV_SET_TERMINATED)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_ADV_SET_TERMINATED, sizeof(*sep));
+	sep->status = node_rx->hdr.rx_ftr.param_adv_term.status;
+	sep->adv_handle = node_rx->hdr.handle & 0xff;
+	sep->conn_handle =
+		sys_cpu_to_le16(node_rx->hdr.rx_ftr.param_adv_term.conn_handle);
+	sep->num_completed_ext_adv_evts =
+		node_rx->hdr.rx_ftr.param_adv_term.num_events;
+}
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+static void le_scan_req_received(struct pdu_data *pdu_data,
+				 struct node_rx_pdu *node_rx,
+				 struct net_buf *buf)
+{
+	struct pdu_adv *adv = (void *)pdu_data;
+	struct bt_hci_evt_le_scan_req_received *sep;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx;
+#endif
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_SCAN_REQ_RECEIVED)) {
+		bt_addr_le_t addr;
+		uint8_t handle;
+		int8_t rssi;
+
+		handle = node_rx->hdr.handle & 0xff;
+		addr.type = adv->tx_addr;
+		memcpy(&addr.a.val[0], &adv->scan_req.scan_addr[0],
+		       sizeof(bt_addr_t));
+
+		/* The Link Layer currently returns RSSI as an absolute value */
+		rssi = -(node_rx->hdr.rx_ftr.rssi);
+
+		BT_DBG("handle: %d, addr: %s, rssi: %d dB.",
+		       handle, bt_addr_le_str(&addr), rssi);
+
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_SCAN_REQ_RECEIVED, sizeof(*sep));
+	sep->handle = node_rx->hdr.handle & 0xff;
+	sep->addr.type = adv->tx_addr;
+	memcpy(&sep->addr.a.val[0], &adv->scan_req.scan_addr[0],
+	       sizeof(bt_addr_t));
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	rl_idx = node_rx->hdr.rx_ftr.rl_idx;
+	if (rl_idx < ll_rl_size_get()) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &sep->addr.type,
+				  &sep->addr.a.val[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		sep->addr.type += 2U;
+	} else {
+#else
+	if (1) {
+#endif
+		sep->addr.type = adv->tx_addr;
+		memcpy(&sep->addr.a.val[0], &adv->adv_ind.addr[0],
+		       sizeof(bt_addr_t));
+	}
+}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CONN)
+static void le_conn_complete(struct pdu_data *pdu_data, uint16_t handle,
+			     struct net_buf *buf)
+{
+	struct node_rx_cc *node_rx = (void *)pdu_data;
+	struct bt_hci_evt_le_conn_complete *lecc;
+	uint8_t status = node_rx->status;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (!status) {
+		/* Update current RPA */
+		ll_rl_crpa_set(node_rx->peer_addr_type,
+			       &node_rx->peer_addr[0], 0xff,
+			       &node_rx->peer_rpa[0]);
+	}
+#endif
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    (!(le_event_mask & BT_EVT_MASK_LE_CONN_COMPLETE) &&
+#if defined(CONFIG_BT_CTLR_PRIVACY) || defined(CONFIG_BT_CTLR_ADV_EXT)
+	     !(le_event_mask & BT_EVT_MASK_LE_ENH_CONN_COMPLETE))) {
+#else
+	     1)) {
+#endif /* CONFIG_BT_CTLR_PRIVACY || CONFIG_BT_CTLR_ADV_EXT */
+		return;
+	}
+
+	if (!status) {
+		conn_count++;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY) || defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (le_event_mask & BT_EVT_MASK_LE_ENH_CONN_COMPLETE) {
+		struct bt_hci_evt_le_enh_conn_complete *leecc;
+
+		leecc = meta_evt(buf, BT_HCI_EVT_LE_ENH_CONN_COMPLETE,
+				 sizeof(*leecc));
+
+		if (status) {
+			(void)memset(leecc, 0x00, sizeof(*leecc));
+			leecc->status = status;
+			return;
+		}
+
+		leecc->status = 0x00;
+		leecc->handle = sys_cpu_to_le16(handle);
+		leecc->role = node_rx->role;
+
+		leecc->peer_addr.type = node_rx->peer_addr_type;
+		memcpy(&leecc->peer_addr.a.val[0], &node_rx->peer_addr[0],
+		       BDADDR_SIZE);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		memcpy(&leecc->local_rpa.val[0], &node_rx->local_rpa[0],
+		       BDADDR_SIZE);
+		memcpy(&leecc->peer_rpa.val[0], &node_rx->peer_rpa[0],
+		       BDADDR_SIZE);
+#else /* !CONFIG_BT_CTLR_PRIVACY */
+		memset(&leecc->local_rpa.val[0], 0, BDADDR_SIZE);
+		memset(&leecc->peer_rpa.val[0], 0, BDADDR_SIZE);
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+		leecc->interval = sys_cpu_to_le16(node_rx->interval);
+		leecc->latency = sys_cpu_to_le16(node_rx->latency);
+		leecc->supv_timeout = sys_cpu_to_le16(node_rx->timeout);
+		leecc->clock_accuracy = node_rx->sca;
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY || CONFIG_BT_CTLR_ADV_EXT */
+
+	lecc = meta_evt(buf, BT_HCI_EVT_LE_CONN_COMPLETE, sizeof(*lecc));
+
+	if (status) {
+		(void)memset(lecc, 0x00, sizeof(*lecc));
+		lecc->status = status;
+		return;
+	}
+
+	lecc->status = 0x00;
+	lecc->handle = sys_cpu_to_le16(handle);
+	lecc->role = node_rx->role;
+	lecc->peer_addr.type = node_rx->peer_addr_type & 0x1;
+	memcpy(&lecc->peer_addr.a.val[0], &node_rx->peer_addr[0], BDADDR_SIZE);
+	lecc->interval = sys_cpu_to_le16(node_rx->interval);
+	lecc->latency = sys_cpu_to_le16(node_rx->latency);
+	lecc->supv_timeout = sys_cpu_to_le16(node_rx->timeout);
+	lecc->clock_accuracy = node_rx->sca;
+}
+
+void hci_disconn_complete_encode(struct pdu_data *pdu_data, uint16_t handle,
+				 struct net_buf *buf)
+{
+	struct bt_hci_evt_disconn_complete *ep;
+
+	if (!(event_mask & BT_EVT_MASK_DISCONN_COMPLETE)) {
+		return;
+	}
+
+	hci_evt_create(buf, BT_HCI_EVT_DISCONN_COMPLETE, sizeof(*ep));
+	ep = net_buf_add(buf, sizeof(*ep));
+
+	ep->status = 0x00;
+	ep->handle = sys_cpu_to_le16(handle);
+	ep->reason = *((uint8_t *)pdu_data);
+}
+
+void hci_disconn_complete_process(uint16_t handle)
+{
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	/* Clear any pending packets upon disconnection */
+	/* Note: This requires linear handle values starting from 0 */
+	LL_ASSERT(handle < ARRAY_SIZE(hci_hbuf_pend));
+	hci_hbuf_acked += hci_hbuf_pend[handle];
+	hci_hbuf_pend[handle] = 0U;
+#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
+	conn_count--;
+}
+
+static void le_conn_update_complete(struct pdu_data *pdu_data, uint16_t handle,
+				    struct net_buf *buf)
+{
+	struct bt_hci_evt_le_conn_update_complete *sep;
+	struct node_rx_cu *cu;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, sizeof(*sep));
+
+	cu = (void *)pdu_data;
+	sep->status = cu->status;
+	sep->handle = sys_cpu_to_le16(handle);
+	sep->interval = sys_cpu_to_le16(cu->interval);
+	sep->latency = sys_cpu_to_le16(cu->latency);
+	sep->supv_timeout = sys_cpu_to_le16(cu->timeout);
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static void enc_refresh_complete(struct pdu_data *pdu_data, uint16_t handle,
+				 struct net_buf *buf)
+{
+	struct bt_hci_evt_encrypt_key_refresh_complete *ep;
+
+	if (!(event_mask & BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE)) {
+		return;
+	}
+
+	hci_evt_create(buf, BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE,
+		       sizeof(*ep));
+	ep = net_buf_add(buf, sizeof(*ep));
+
+	ep->status = 0x00;
+	ep->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+static void auth_payload_timeout_exp(struct pdu_data *pdu_data, uint16_t handle,
+				     struct net_buf *buf)
+{
+	struct bt_hci_evt_auth_payload_timeout_exp *ep;
+
+	if (!(event_mask_page_2 & BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP)) {
+		return;
+	}
+
+	hci_evt_create(buf, BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP, sizeof(*ep));
+	ep = net_buf_add(buf, sizeof(*ep));
+
+	ep->handle = sys_cpu_to_le16(handle);
+}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+static void le_chan_sel_algo(struct pdu_data *pdu_data, uint16_t handle,
+			     struct net_buf *buf)
+{
+	struct bt_hci_evt_le_chan_sel_algo *sep;
+	struct node_rx_cs *cs;
+
+	cs = (void *)pdu_data;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_CHAN_SEL_ALGO)) {
+		BT_DBG("handle: 0x%04x, CSA: %x.", handle, cs->csa);
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_CHAN_SEL_ALGO, sizeof(*sep));
+
+	sep->handle = sys_cpu_to_le16(handle);
+	sep->chan_sel_algo = cs->csa;
+}
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static void le_phy_upd_complete(struct pdu_data *pdu_data, uint16_t handle,
+				struct net_buf *buf)
+{
+	struct bt_hci_evt_le_phy_update_complete *sep;
+	struct node_rx_pu *pu;
+
+	pu = (void *)pdu_data;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE)) {
+		BT_WARN("handle: 0x%04x, status: %x, tx: %x, rx: %x.", handle,
+			pu->status,
+			find_lsb_set(pu->tx),
+			find_lsb_set(pu->rx));
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE, sizeof(*sep));
+
+	sep->status = pu->status;
+	sep->handle = sys_cpu_to_le16(handle);
+	sep->tx_phy = find_lsb_set(pu->tx);
+	sep->rx_phy = find_lsb_set(pu->rx);
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+static void mesh_adv_cplt(struct pdu_data *pdu_data,
+			  struct node_rx_pdu *node_rx,
+			  struct net_buf *buf)
+{
+	struct bt_hci_evt_mesh_adv_complete *mep;
+
+	mep = mesh_evt(buf, BT_HCI_EVT_MESH_ADV_COMPLETE, sizeof(*mep));
+	mep->adv_slot = ((uint8_t *)pdu_data)[0];
+}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+/**
+ * @brief Encode a control-PDU into an HCI buffer
+ * @details Execution context: Host thread
+ *
+ * @param node_rx_pdu[in] RX node containing header and PDU
+ * @param pdu_data[in]    PDU. Same as node_rx_pdu->pdu, but more convenient
+ * @param net_buf[out]    Upwards-going HCI buffer to fill
+ */
+static void encode_control(struct node_rx_pdu *node_rx,
+			   struct pdu_data *pdu_data, struct net_buf *buf)
+{
+	uint16_t handle;
+
+	handle = node_rx->hdr.handle;
+
+	switch (node_rx->hdr.type) {
+#if defined(CONFIG_BT_OBSERVER)
+	case NODE_RX_TYPE_REPORT:
+		le_advertising_report(pdu_data, node_rx, buf);
+		break;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	case NODE_RX_TYPE_EXT_1M_REPORT:
+		le_adv_ext_1M_report(pdu_data, node_rx, buf);
+		break;
+
+	case NODE_RX_TYPE_EXT_2M_REPORT:
+		le_adv_ext_2M_report(pdu_data, node_rx, buf);
+		break;
+
+	case NODE_RX_TYPE_EXT_CODED_REPORT:
+		le_adv_ext_coded_report(pdu_data, node_rx, buf);
+		break;
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	case NODE_RX_TYPE_SYNC:
+		le_per_adv_sync_established(pdu_data, node_rx, buf);
+		break;
+	case NODE_RX_TYPE_SYNC_LOST:
+		le_per_adv_sync_lost(pdu_data, node_rx, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_BROADCASTER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	case NODE_RX_TYPE_EXT_ADV_TERMINATE:
+		le_adv_ext_terminate(pdu_data, node_rx, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	case NODE_RX_TYPE_SCAN_REQ:
+		le_scan_req_received(pdu_data, node_rx, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CONN)
+	case NODE_RX_TYPE_CONNECTION:
+		le_conn_complete(pdu_data, handle, buf);
+		break;
+
+	case NODE_RX_TYPE_TERMINATE:
+		hci_disconn_complete_encode(pdu_data, handle, buf);
+		break;
+
+	case NODE_RX_TYPE_CONN_UPDATE:
+		le_conn_update_complete(pdu_data, handle, buf);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case NODE_RX_TYPE_ENC_REFRESH:
+		enc_refresh_complete(pdu_data, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	case NODE_RX_TYPE_APTO:
+		auth_payload_timeout_exp(pdu_data, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+	case NODE_RX_TYPE_CHAN_SEL_ALGO:
+		le_chan_sel_algo(pdu_data, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case NODE_RX_TYPE_PHY_UPDATE:
+		le_phy_upd_complete(pdu_data, handle, buf);
+		return;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+	case NODE_RX_TYPE_RSSI:
+		BT_INFO("handle: 0x%04x, rssi: -%d dB.", handle,
+			pdu_data->rssi);
+		return;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	case NODE_RX_TYPE_ADV_INDICATION:
+		BT_INFO("Advertised.");
+		return;
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	case NODE_RX_TYPE_SCAN_INDICATION:
+		BT_INFO("Scanned.");
+		return;
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	case NODE_RX_TYPE_PROFILE:
+		BT_INFO("l: %d, %d, %d; t: %d, %d, %d.",
+			pdu_data->profile.lcur,
+			pdu_data->profile.lmin,
+			pdu_data->profile.lmax,
+			pdu_data->profile.cur,
+			pdu_data->profile.min,
+			pdu_data->profile.max);
+		return;
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	case NODE_RX_TYPE_MESH_ADV_CPLT:
+		mesh_adv_cplt(pdu_data, node_rx, buf);
+		return;
+
+	case NODE_RX_TYPE_MESH_REPORT:
+		le_advertising_report(pdu_data, node_rx, buf);
+		return;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	case NODE_RX_TYPE_USER_START ... NODE_RX_TYPE_USER_END:
+		hci_user_ext_encode_control(node_rx, pdu_data, buf);
+		return;
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+	default:
+		LL_ASSERT(0);
+		return;
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static void le_ltk_request(struct pdu_data *pdu_data, uint16_t handle,
+			   struct net_buf *buf)
+{
+	struct bt_hci_evt_le_ltk_request *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_LTK_REQUEST)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_LTK_REQUEST, sizeof(*sep));
+
+	sep->handle = sys_cpu_to_le16(handle);
+	memcpy(&sep->rand, pdu_data->llctrl.enc_req.rand, sizeof(uint64_t));
+	memcpy(&sep->ediv, pdu_data->llctrl.enc_req.ediv, sizeof(uint16_t));
+}
+
+static void encrypt_change(uint8_t err, uint16_t handle,
+			   struct net_buf *buf)
+{
+	struct bt_hci_evt_encrypt_change *ep;
+
+	if (!(event_mask & BT_EVT_MASK_ENCRYPT_CHANGE)) {
+		return;
+	}
+
+	hci_evt_create(buf, BT_HCI_EVT_ENCRYPT_CHANGE, sizeof(*ep));
+	ep = net_buf_add(buf, sizeof(*ep));
+
+	ep->status = err;
+	ep->handle = sys_cpu_to_le16(handle);
+	ep->encrypt = !err ? 1 : 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static void le_remote_feat_complete(uint8_t status, struct pdu_data *pdu_data,
+				    uint16_t handle, struct net_buf *buf)
+{
+	struct bt_hci_evt_le_remote_feat_complete *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE, sizeof(*sep));
+
+	sep->status = status;
+	sep->handle = sys_cpu_to_le16(handle);
+	if (!status) {
+		memcpy(&sep->features[0],
+		       &pdu_data->llctrl.feature_rsp.features[0],
+		       sizeof(sep->features));
+	} else {
+		(void)memset(&sep->features[0], 0x00, sizeof(sep->features));
+	}
+}
+
+static void le_unknown_rsp(struct pdu_data *pdu_data, uint16_t handle,
+			   struct net_buf *buf)
+{
+
+	switch (pdu_data->llctrl.unknown_rsp.type) {
+	case PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ:
+		le_remote_feat_complete(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE,
+					    NULL, handle, buf);
+		break;
+
+	default:
+		BT_WARN("type: 0x%02x",	pdu_data->llctrl.unknown_rsp.type);
+		break;
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle,
+			      struct net_buf *buf)
+{
+	struct bt_hci_evt_le_conn_param_req *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_CONN_PARAM_REQ)) {
+		/* event masked, reject the conn param req */
+		ll_conn_update(handle, 2, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, 0,
+			       0, 0, 0);
+
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_PARAM_REQ, sizeof(*sep));
+
+	sep->handle = sys_cpu_to_le16(handle);
+	sep->interval_min = pdu_data->llctrl.conn_param_req.interval_min;
+	sep->interval_max = pdu_data->llctrl.conn_param_req.interval_max;
+	sep->latency = pdu_data->llctrl.conn_param_req.latency;
+	sep->timeout = pdu_data->llctrl.conn_param_req.timeout;
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static void le_data_len_change(struct pdu_data *pdu_data, uint16_t handle,
+			       struct net_buf *buf)
+{
+	struct bt_hci_evt_le_data_len_change *sep;
+
+	if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
+	    !(le_event_mask & BT_EVT_MASK_LE_DATA_LEN_CHANGE)) {
+		return;
+	}
+
+	sep = meta_evt(buf, BT_HCI_EVT_LE_DATA_LEN_CHANGE, sizeof(*sep));
+
+	sep->handle = sys_cpu_to_le16(handle);
+	sep->max_tx_octets = pdu_data->llctrl.length_rsp.max_tx_octets;
+	sep->max_tx_time = pdu_data->llctrl.length_rsp.max_tx_time;
+	sep->max_rx_octets = pdu_data->llctrl.length_rsp.max_rx_octets;
+	sep->max_rx_time = pdu_data->llctrl.length_rsp.max_rx_time;
+}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_REMOTE_VERSION)
+static void remote_version_info_encode(struct pdu_data *pdu_data,
+				       uint16_t handle, struct net_buf *buf)
+{
+	struct pdu_data_llctrl_version_ind *ver_ind;
+	struct bt_hci_evt_remote_version_info *ep;
+
+	if (!(event_mask & BT_EVT_MASK_REMOTE_VERSION_INFO)) {
+		return;
+	}
+
+	hci_evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep));
+	ep = net_buf_add(buf, sizeof(*ep));
+
+	ver_ind = &pdu_data->llctrl.version_ind;
+	ep->status = 0x00;
+	ep->handle = sys_cpu_to_le16(handle);
+	ep->version = ver_ind->version_number;
+	ep->manufacturer = ver_ind->company_id;
+	ep->subversion = ver_ind->sub_version_number;
+}
+#endif /* CONFIG_BT_REMOTE_VERSION */
+
+static void encode_data_ctrl(struct node_rx_pdu *node_rx,
+			     struct pdu_data *pdu_data, struct net_buf *buf)
+{
+	uint16_t handle = node_rx->hdr.handle;
+
+	switch (pdu_data->llctrl.opcode) {
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
+		le_ltk_request(pdu_data, handle, buf);
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_START_ENC_RSP:
+		encrypt_change(0x00, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_REMOTE_VERSION)
+	case PDU_DATA_LLCTRL_TYPE_VERSION_IND:
+		remote_version_info_encode(pdu_data, handle, buf);
+		break;
+#endif /* defined(CONFIG_BT_REMOTE_VERSION) */
+
+	case PDU_DATA_LLCTRL_TYPE_FEATURE_RSP:
+		le_remote_feat_complete(0x00, pdu_data, handle, buf);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
+		encrypt_change(pdu_data->llctrl.reject_ind.error_code, handle,
+			       buf);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	case PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ:
+		le_conn_param_req(pdu_data, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_RSP:
+		le_data_len_change(pdu_data, handle, buf);
+		break;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+	case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
+		le_unknown_rsp(pdu_data, handle, buf);
+		break;
+
+	default:
+		LL_ASSERT(0);
+		return;
+	}
+}
+
+#if defined(CONFIG_BT_CONN)
+void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf)
+{
+	struct pdu_data *pdu_data = (void *)node_rx->pdu;
+	struct bt_hci_acl_hdr *acl;
+	uint16_t handle_flags;
+	uint16_t handle;
+	uint8_t *data;
+
+	handle = node_rx->hdr.handle;
+
+	switch (pdu_data->ll_id) {
+	case PDU_DATA_LLID_DATA_CONTINUE:
+	case PDU_DATA_LLID_DATA_START:
+		acl = (void *)net_buf_add(buf, sizeof(*acl));
+		if (pdu_data->ll_id == PDU_DATA_LLID_DATA_START) {
+			handle_flags = bt_acl_handle_pack(handle, BT_ACL_START);
+		} else {
+			handle_flags = bt_acl_handle_pack(handle, BT_ACL_CONT);
+		}
+		acl->handle = sys_cpu_to_le16(handle_flags);
+		acl->len = sys_cpu_to_le16(pdu_data->len);
+		data = (void *)net_buf_add(buf, pdu_data->len);
+		memcpy(data, pdu_data->lldata, pdu_data->len);
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+		if (hci_hbuf_total > 0) {
+			LL_ASSERT((hci_hbuf_sent - hci_hbuf_acked) <
+				  hci_hbuf_total);
+			hci_hbuf_sent++;
+			/* Note: This requires linear handle values starting
+			 * from 0
+			 */
+			LL_ASSERT(handle < ARRAY_SIZE(hci_hbuf_pend));
+			hci_hbuf_pend[handle]++;
+		}
+#endif
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+#endif /* CONFIG_BT_CONN */
+
+void hci_evt_encode(struct node_rx_pdu *node_rx, struct net_buf *buf)
+{
+	struct pdu_data *pdu_data = (void *)node_rx->pdu;
+
+	if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU) {
+		encode_control(node_rx, pdu_data, buf);
+	} else if (IS_ENABLED(CONFIG_BT_CONN)) {
+		encode_data_ctrl(node_rx, pdu_data, buf);
+	}
+}
+
+#if defined(CONFIG_BT_CONN)
+void hci_num_cmplt_encode(struct net_buf *buf, uint16_t handle, uint8_t num)
+{
+	struct bt_hci_evt_num_completed_packets *ep;
+	struct bt_hci_handle_count *hc;
+	uint8_t num_handles;
+	uint8_t len;
+
+	num_handles = 1U;
+
+	len = (sizeof(*ep) + (sizeof(*hc) * num_handles));
+	hci_evt_create(buf, BT_HCI_EVT_NUM_COMPLETED_PACKETS, len);
+
+	ep = net_buf_add(buf, len);
+	ep->num_handles = num_handles;
+	hc = &ep->h[0];
+	hc->handle = sys_cpu_to_le16(handle);
+	hc->count = sys_cpu_to_le16(num);
+}
+#endif /* CONFIG_BT_CONN */
+
+uint8_t hci_get_class(struct node_rx_pdu *node_rx)
+{
+#if defined(CONFIG_BT_CONN)
+	struct pdu_data *pdu_data = (void *)node_rx->pdu;
+#endif
+
+	if (node_rx->hdr.type != NODE_RX_TYPE_DC_PDU) {
+
+		switch (node_rx->hdr.type) {
+#if defined(CONFIG_BT_OBSERVER) || \
+	defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) || \
+	defined(CONFIG_BT_CTLR_ADV_INDICATION) || \
+	defined(CONFIG_BT_CTLR_SCAN_INDICATION) || \
+	defined(CONFIG_BT_CTLR_PROFILE_ISR)
+#if defined(CONFIG_BT_OBSERVER)
+		case NODE_RX_TYPE_REPORT:
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+			__fallthrough;
+		case NODE_RX_TYPE_EXT_1M_REPORT:
+		case NODE_RX_TYPE_EXT_2M_REPORT:
+		case NODE_RX_TYPE_EXT_CODED_REPORT:
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+		case NODE_RX_TYPE_SCAN_REQ:
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+		case NODE_RX_TYPE_ADV_INDICATION:
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+		case NODE_RX_TYPE_SCAN_INDICATION:
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+		case NODE_RX_TYPE_PROFILE:
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+			return HCI_CLASS_EVT_DISCARDABLE;
+#endif
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+		case NODE_RX_TYPE_MESH_ADV_CPLT:
+		case NODE_RX_TYPE_MESH_REPORT:
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+			__fallthrough;
+		case NODE_RX_TYPE_SYNC:
+		case NODE_RX_TYPE_SYNC_LOST:
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+#if defined(CONFIG_BT_BROADCASTER)
+		case NODE_RX_TYPE_EXT_ADV_TERMINATE:
+#endif /* CONFIG_BT_BROADCASTER */
+
+			return HCI_CLASS_EVT_REQUIRED;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CONN)
+		case NODE_RX_TYPE_CONNECTION:
+			return HCI_CLASS_EVT_REQUIRED;
+
+		case NODE_RX_TYPE_TERMINATE:
+		case NODE_RX_TYPE_CONN_UPDATE:
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		case NODE_RX_TYPE_ENC_REFRESH:
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+		case NODE_RX_TYPE_RSSI:
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		case NODE_RX_TYPE_APTO:
+#endif /* CONFIG_BT_CTLR_LE_PING */
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+		case NODE_RX_TYPE_CHAN_SEL_ALGO:
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
+#if defined(CONFIG_BT_CTLR_PHY)
+		case NODE_RX_TYPE_PHY_UPDATE:
+#endif /* CONFIG_BT_CTLR_PHY */
+			return HCI_CLASS_EVT_CONNECTION;
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+		case NODE_RX_TYPE_USER_START ... NODE_RX_TYPE_USER_END:
+			return hci_user_ext_get_class(node_rx);
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+		default:
+			return HCI_CLASS_NONE;
+		}
+
+#if defined(CONFIG_BT_CONN)
+	} else if (pdu_data->ll_id == PDU_DATA_LLID_CTRL) {
+		return HCI_CLASS_EVT_LLCP;
+	} else {
+		return HCI_CLASS_ACL_DATA;
+	}
+#else
+	} else {
+		return HCI_CLASS_NONE;
+	}
+#endif
+}
+
+void hci_init(struct k_poll_signal *signal_host_buf)
+{
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	hbuf_signal = signal_host_buf;
+#endif
+	reset(NULL, NULL);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_driver.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_driver.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_driver.c	(working copy)
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <init.h>
+#include <device.h>
+#include <drivers/clock_control.h>
+#include <sys/atomic.h>
+
+#include <sys/util.h>
+#include <debug/stack.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#ifdef CONFIG_CLOCK_CONTROL_NRF
+#include <drivers/clock_control/nrf_clock_control.h>
+#endif
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hci_driver
+#include "common/log.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "hal/ccm.h"
+
+#if defined(CONFIG_SOC_FAMILY_NRF)
+#include "hal/radio.h"
+#endif /* CONFIG_SOC_FAMILY_NRF */
+
+#include "ll_sw/pdu.h"
+#include "ll_sw/lll.h"
+#include "ll.h"
+
+#include "hci_internal.h"
+
+#include "hal/debug.h"
+
+static K_SEM_DEFINE(sem_prio_recv, 0, UINT_MAX);
+static K_FIFO_DEFINE(recv_fifo);
+
+struct k_thread prio_recv_thread_data;
+static K_KERNEL_STACK_DEFINE(prio_recv_thread_stack,
+			     CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE);
+struct k_thread recv_thread_data;
+static K_KERNEL_STACK_DEFINE(recv_thread_stack, CONFIG_BT_RX_STACK_SIZE);
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+static struct k_poll_signal hbuf_signal =
+		K_POLL_SIGNAL_INITIALIZER(hbuf_signal);
+static sys_slist_t hbuf_pend;
+static int32_t hbuf_count;
+#endif
+
+static struct net_buf *process_prio_evt(struct node_rx_pdu *node_rx,
+					uint8_t *evt_flags)
+{
+#if defined(CONFIG_BT_CONN)
+	if (node_rx->hdr.user_meta == HCI_CLASS_EVT_CONNECTION) {
+		uint16_t handle;
+		struct pdu_data *pdu_data = (void *)node_rx->pdu;
+
+		handle = node_rx->hdr.handle;
+		if (node_rx->hdr.type == NODE_RX_TYPE_TERMINATE) {
+			struct net_buf *buf;
+
+			buf = bt_buf_get_evt(BT_HCI_EVT_DISCONN_COMPLETE, false,
+					     K_FOREVER);
+			hci_disconn_complete_encode(pdu_data, handle, buf);
+			hci_disconn_complete_process(handle);
+			*evt_flags = BT_HCI_EVT_FLAG_RECV_PRIO | BT_HCI_EVT_FLAG_RECV;
+			return buf;
+		}
+	}
+#endif /* CONFIG_BT_CONN */
+
+	*evt_flags = BT_HCI_EVT_FLAG_RECV;
+	return NULL;
+}
+
+/**
+ * @brief Handover from Controller thread to Host thread
+ * @details Execution context: Controller thread
+ *   Pull from memq_ll_rx and push up to Host thread recv_thread() via recv_fifo
+ * @param p1  Unused. Required to conform with Zephyr thread protoype
+ * @param p2  Unused. Required to conform with Zephyr thread protoype
+ * @param p3  Unused. Required to conform with Zephyr thread protoype
+ */
+static void prio_recv_thread(void *p1, void *p2, void *p3)
+{
+	while (1) {
+		struct node_rx_pdu *node_rx;
+		struct net_buf *buf;
+		uint8_t num_cmplt;
+		uint16_t handle;
+
+		/* While there are completed rx nodes */
+		while ((num_cmplt = ll_rx_get((void *)&node_rx, &handle))) {
+#if defined(CONFIG_BT_CONN)
+
+			buf = bt_buf_get_evt(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
+					     false, K_FOREVER);
+			hci_num_cmplt_encode(buf, handle, num_cmplt);
+			BT_DBG("Num Complete: 0x%04x:%u", handle, num_cmplt);
+			bt_recv_prio(buf);
+			k_yield();
+#endif
+		}
+
+		if (node_rx) {
+			uint8_t evt_flags;
+
+			/* Until now we've only peeked, now we really do
+			 * the handover
+			 */
+			ll_rx_dequeue();
+
+			/* Find out and store the class for this node */
+			node_rx->hdr.user_meta = hci_get_class(node_rx);
+
+			buf = process_prio_evt(node_rx, &evt_flags);
+			if (buf) {
+				BT_DBG("Priority event");
+				if (!(evt_flags & BT_HCI_EVT_FLAG_RECV)) {
+					node_rx->hdr.next = NULL;
+					ll_rx_mem_release((void **)&node_rx);
+				}
+
+				bt_recv_prio(buf);
+				/* bt_recv_prio would not release normal evt
+				 * buf.
+				 */
+				if (evt_flags & BT_HCI_EVT_FLAG_RECV) {
+					net_buf_unref(buf);
+				}
+			}
+
+			if (evt_flags & BT_HCI_EVT_FLAG_RECV) {
+				/* Send the rx node up to Host thread,
+				 * recv_thread()
+				 */
+				BT_DBG("RX node enqueue");
+				k_fifo_put(&recv_fifo, node_rx);
+			}
+
+			/* There may still be completed nodes, continue
+			 * pushing all those up to Host before waiting
+			 * for ULL mayfly
+			 */
+			continue;
+
+		}
+
+		BT_DBG("sem take...");
+		/* Wait until ULL mayfly has something to give us.
+		 * Blocking-take of the semaphore; we take it once ULL mayfly
+		 * has let it go in ll_rx_sched().
+		 */
+		k_sem_take(&sem_prio_recv, K_FOREVER);
+		/* Now, ULL mayfly has something to give to us */
+		BT_DBG("sem taken");
+	}
+}
+
+static inline struct net_buf *encode_node(struct node_rx_pdu *node_rx,
+					  int8_t class)
+{
+	struct net_buf *buf = NULL;
+
+	/* Check if we need to generate an HCI event or ACL data */
+	switch (class) {
+	case HCI_CLASS_EVT_DISCARDABLE:
+	case HCI_CLASS_EVT_REQUIRED:
+	case HCI_CLASS_EVT_CONNECTION:
+	case HCI_CLASS_EVT_LLCP:
+		if (class == HCI_CLASS_EVT_DISCARDABLE) {
+			buf = bt_buf_get_evt(BT_HCI_EVT_UNKNOWN, true,
+					     K_NO_WAIT);
+		} else {
+			buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
+		}
+		if (buf) {
+			hci_evt_encode(node_rx, buf);
+		}
+		break;
+#if defined(CONFIG_BT_CONN)
+	case HCI_CLASS_ACL_DATA:
+		/* generate ACL data */
+		buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
+		hci_acl_encode(node_rx, buf);
+		break;
+#endif
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	node_rx->hdr.next = NULL;
+	ll_rx_mem_release((void **)&node_rx);
+
+	return buf;
+}
+
+static inline struct net_buf *process_node(struct node_rx_pdu *node_rx)
+{
+	uint8_t class = node_rx->hdr.user_meta;
+	struct net_buf *buf = NULL;
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	if (hbuf_count != -1) {
+		bool pend = !sys_slist_is_empty(&hbuf_pend);
+
+		/* controller to host flow control enabled */
+		switch (class) {
+		case HCI_CLASS_EVT_DISCARDABLE:
+		case HCI_CLASS_EVT_REQUIRED:
+			break;
+		case HCI_CLASS_EVT_CONNECTION:
+		case HCI_CLASS_EVT_LLCP:
+			/* for conn-related events, only pend is relevant */
+			hbuf_count = 1;
+			__fallthrough;
+		case HCI_CLASS_ACL_DATA:
+			if (pend || !hbuf_count) {
+				sys_slist_append(&hbuf_pend, (void *)node_rx);
+				BT_DBG("FC: Queuing item: %d", class);
+				return NULL;
+			}
+			break;
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+	}
+#endif
+
+	/* process regular node from radio */
+	buf = encode_node(node_rx, class);
+
+	return buf;
+}
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+static inline struct net_buf *process_hbuf(struct node_rx_pdu *n)
+{
+	/* shadow total count in case of preemption */
+	struct node_rx_pdu *node_rx = NULL;
+	int32_t hbuf_total = hci_hbuf_total;
+	struct net_buf *buf = NULL;
+	uint8_t class;
+	int reset;
+
+	reset = atomic_test_and_clear_bit(&hci_state_mask, HCI_STATE_BIT_RESET);
+	if (reset) {
+		/* flush queue, no need to free, the LL has already done it */
+		sys_slist_init(&hbuf_pend);
+	}
+
+	if (hbuf_total <= 0) {
+		hbuf_count = -1;
+		return NULL;
+	}
+
+	/* available host buffers */
+	hbuf_count = hbuf_total - (hci_hbuf_sent - hci_hbuf_acked);
+
+	/* host acked ACL packets, try to dequeue from hbuf */
+	node_rx = (void *)sys_slist_peek_head(&hbuf_pend);
+	if (!node_rx) {
+		return NULL;
+	}
+
+	/* Return early if this iteration already has a node to process */
+	class = node_rx->hdr.user_meta;
+	if (n) {
+		if (class == HCI_CLASS_EVT_CONNECTION ||
+		    class == HCI_CLASS_EVT_LLCP ||
+		    (class == HCI_CLASS_ACL_DATA && hbuf_count)) {
+			/* node to process later, schedule an iteration */
+			BT_DBG("FC: signalling");
+			k_poll_signal_raise(&hbuf_signal, 0x0);
+		}
+		return NULL;
+	}
+
+	switch (class) {
+	case HCI_CLASS_EVT_CONNECTION:
+	case HCI_CLASS_EVT_LLCP:
+		BT_DBG("FC: dequeueing event");
+		(void) sys_slist_get(&hbuf_pend);
+		break;
+	case HCI_CLASS_ACL_DATA:
+		if (hbuf_count) {
+			BT_DBG("FC: dequeueing ACL data");
+			(void) sys_slist_get(&hbuf_pend);
+		} else {
+			/* no buffers, HCI will signal */
+			node_rx = NULL;
+		}
+		break;
+	case HCI_CLASS_EVT_DISCARDABLE:
+	case HCI_CLASS_EVT_REQUIRED:
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	if (node_rx) {
+		buf = encode_node(node_rx, class);
+		/* Update host buffers after encoding */
+		hbuf_count = hbuf_total - (hci_hbuf_sent - hci_hbuf_acked);
+		/* next node */
+		node_rx = (void *)sys_slist_peek_head(&hbuf_pend);
+		if (node_rx) {
+			class = node_rx->hdr.user_meta;
+
+			if (class == HCI_CLASS_EVT_CONNECTION ||
+			    class == HCI_CLASS_EVT_LLCP ||
+			    (class == HCI_CLASS_ACL_DATA && hbuf_count)) {
+				/* more to process, schedule an
+				 * iteration
+				 */
+				BT_DBG("FC: signalling");
+				k_poll_signal_raise(&hbuf_signal, 0x0);
+			}
+		}
+	}
+
+	return buf;
+}
+#endif
+
+/**
+ * @brief Blockingly pull from Controller thread's recv_fifo
+ * @details Execution context: Host thread
+ */
+static void recv_thread(void *p1, void *p2, void *p3)
+{
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	/* @todo: check if the events structure really needs to be static */
+	static struct k_poll_event events[2] = {
+		K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SIGNAL,
+						K_POLL_MODE_NOTIFY_ONLY,
+						&hbuf_signal, 0),
+		K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+						K_POLL_MODE_NOTIFY_ONLY,
+						&recv_fifo, 0),
+	};
+#endif
+
+	while (1) {
+		struct node_rx_pdu *node_rx = NULL;
+		struct net_buf *buf = NULL;
+
+		BT_DBG("blocking");
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+		int err;
+
+		err = k_poll(events, 2, K_FOREVER);
+		LL_ASSERT(err == 0);
+		if (events[0].state == K_POLL_STATE_SIGNALED) {
+			events[0].signal->signaled = 0U;
+		} else if (events[1].state ==
+			   K_POLL_STATE_FIFO_DATA_AVAILABLE) {
+			node_rx = k_fifo_get(events[1].fifo, K_NO_WAIT);
+		}
+
+		events[0].state = K_POLL_STATE_NOT_READY;
+		events[1].state = K_POLL_STATE_NOT_READY;
+
+		/* process host buffers first if any */
+		buf = process_hbuf(node_rx);
+
+#else
+		node_rx = k_fifo_get(&recv_fifo, K_FOREVER);
+#endif
+		BT_DBG("unblocked");
+
+		if (node_rx && !buf) {
+			/* process regular node from radio */
+			buf = process_node(node_rx);
+		}
+
+		if (buf) {
+			if (buf->len) {
+				BT_DBG("Packet in: type:%u len:%u",
+					bt_buf_get_type(buf), buf->len);
+				bt_recv(buf);
+			} else {
+				net_buf_unref(buf);
+			}
+		}
+
+		k_yield();
+	}
+}
+
+static int cmd_handle(struct net_buf *buf)
+{
+	struct node_rx_pdu *node_rx = NULL;
+	struct net_buf *evt;
+
+	evt = hci_cmd_handle(buf, (void **) &node_rx);
+	if (evt) {
+		BT_DBG("Replying with event of %u bytes", evt->len);
+		bt_recv_prio(evt);
+
+		if (node_rx) {
+			BT_DBG("RX node enqueue");
+			node_rx->hdr.user_meta = hci_get_class(node_rx);
+			k_fifo_put(&recv_fifo, node_rx);
+		}
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CONN)
+static int acl_handle(struct net_buf *buf)
+{
+	struct net_buf *evt;
+	int err;
+
+	err = hci_acl_handle(buf, &evt);
+	if (evt) {
+		BT_DBG("Replying with event of %u bytes", evt->len);
+		bt_recv_prio(evt);
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_CONN */
+
+static int hci_driver_send(struct net_buf *buf)
+{
+	uint8_t type;
+	int err;
+
+	BT_DBG("enter");
+
+	if (!buf->len) {
+		BT_ERR("Empty HCI packet");
+		return -EINVAL;
+	}
+
+	type = bt_buf_get_type(buf);
+	switch (type) {
+#if defined(CONFIG_BT_CONN)
+	case BT_BUF_ACL_OUT:
+		err = acl_handle(buf);
+		break;
+#endif /* CONFIG_BT_CONN */
+	case BT_BUF_CMD:
+		err = cmd_handle(buf);
+		break;
+	default:
+		BT_ERR("Unknown HCI type %u", type);
+		return -EINVAL;
+	}
+
+	if (!err) {
+		net_buf_unref(buf);
+	}
+
+	BT_DBG("exit: %d", err);
+
+	return err;
+}
+
+static int hci_driver_open(void)
+{
+	uint32_t err;
+
+	DEBUG_INIT();
+
+	err = ll_init(&sem_prio_recv);
+	if (err) {
+		BT_ERR("LL initialization failed: %d", err);
+		return err;
+	}
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	hci_init(&hbuf_signal);
+#else
+	hci_init(NULL);
+#endif
+
+	k_thread_create(&prio_recv_thread_data, prio_recv_thread_stack,
+			K_KERNEL_STACK_SIZEOF(prio_recv_thread_stack),
+			prio_recv_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT);
+	k_thread_name_set(&prio_recv_thread_data, "BT RX pri");
+
+	k_thread_create(&recv_thread_data, recv_thread_stack,
+			K_KERNEL_STACK_SIZEOF(recv_thread_stack),
+			recv_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT);
+	k_thread_name_set(&recv_thread_data, "BT RX");
+
+	BT_DBG("Success.");
+
+	return 0;
+}
+
+static const struct bt_hci_driver drv = {
+	.name	= "Controller",
+	.bus	= BT_HCI_DRIVER_BUS_VIRTUAL,
+	.quirks = BT_QUIRK_NO_AUTO_DLE,
+	.open	= hci_driver_open,
+	.send	= hci_driver_send,
+};
+
+static int hci_driver_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	bt_hci_driver_register(&drv);
+
+	return 0;
+}
+
+SYS_INIT(hci_driver_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_internal.h	(working copy)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+extern int32_t    hci_hbuf_total;
+extern uint32_t    hci_hbuf_sent;
+extern uint32_t    hci_hbuf_acked;
+extern atomic_t hci_state_mask;
+
+#define HCI_STATE_BIT_RESET 0
+#endif
+
+#define HCI_CLASS_NONE            0 /* Invalid class */
+#define HCI_CLASS_EVT_REQUIRED    1 /* Mesh and connection-{established,
+				     * disconnected}
+				     */
+#define HCI_CLASS_EVT_DISCARDABLE 2 /* Best-effort reporting. Discardable
+				     * over HCI in case of overflow
+				     */
+#define HCI_CLASS_EVT_CONNECTION  3 /* Connection management; e.g.
+				     * terminate, update, encryption
+				     */
+#define HCI_CLASS_EVT_LLCP        4 /* LL Control Procedures */
+#define HCI_CLASS_ACL_DATA        5 /* Asynchronous Connection Less (general
+				     * data)
+				     */
+
+void hci_init(struct k_poll_signal *signal_host_buf);
+struct net_buf *hci_cmd_handle(struct net_buf *cmd, void **node_rx);
+void hci_evt_encode(struct node_rx_pdu *node_rx, struct net_buf *buf);
+uint8_t hci_get_class(struct node_rx_pdu *node_rx);
+void hci_disconn_complete_encode(struct pdu_data *pdu_data, uint16_t handle,
+				 struct net_buf *buf);
+void hci_disconn_complete_process(uint16_t handle);
+#if defined(CONFIG_BT_CONN)
+int hci_acl_handle(struct net_buf *acl, struct net_buf **evt);
+void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf);
+void hci_num_cmplt_encode(struct net_buf *buf, uint16_t handle, uint8_t num);
+#endif
+int hci_vendor_cmd_handle(uint16_t ocf, struct net_buf *cmd,
+			  struct net_buf **evt);
+uint8_t hci_vendor_read_static_addr(struct bt_hci_vs_static_addr addrs[],
+				 uint8_t size);
+void hci_vendor_read_key_hierarchy_roots(uint8_t ir[16], uint8_t er[16]);
+int hci_vendor_cmd_handle_common(uint16_t ocf, struct net_buf *cmd,
+			     struct net_buf **evt);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_user_ext.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_user_ext.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/hci_user_ext.h	(working copy)
@@ -0,0 +1,12 @@
+/** @file
+ *  @brief HCI controller user extensions
+ */
+
+/*
+ * Copyright (c) 2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int8_t hci_user_ext_get_class(struct node_rx_pdu *node_rx);
+void hci_user_ext_encode_control(struct node_rx_pdu *node_rx, struct pdu_data *pdu_data, struct net_buf *buf);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.h	(working copy)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_SOC_COMPATIBLE_NRF)
+#define BT_HCI_VS_HW_PLAT BT_HCI_VS_HW_PLAT_NORDIC
+#if defined(CONFIG_SOC_SERIES_NRF51X)
+#define BT_HCI_VS_HW_VAR  BT_HCI_VS_HW_VAR_NORDIC_NRF51X
+#elif defined(CONFIG_SOC_COMPATIBLE_NRF52X)
+#define BT_HCI_VS_HW_VAR  BT_HCI_VS_HW_VAR_NORDIC_NRF52X
+#elif defined(CONFIG_SOC_SERIES_NRF53X)
+#define BT_HCI_VS_HW_VAR  BT_HCI_VS_HW_VAR_NORDIC_NRF53X
+#endif
+#else
+#define BT_HCI_VS_HW_PLAT 0
+#define BT_HCI_VS_HW_VAR  0
+#endif /* CONFIG_SOC_COMPATIBLE_NRF */
+
+/* Map vendor command handler directly to common implementation */
+inline int hci_vendor_cmd_handle(uint16_t ocf, struct net_buf *cmd,
+				 struct net_buf **evt)
+{
+	return hci_vendor_cmd_handle_common(ocf, cmd, evt);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/nordic/hci_vendor.c	(working copy)
@@ -0,0 +1,76 @@
+/* Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/addr.h>
+#include <bluetooth/hci_vs.h>
+
+#include <nrf.h>
+
+uint8_t hci_vendor_read_static_addr(struct bt_hci_vs_static_addr addrs[],
+				 uint8_t size)
+{
+	/* only one supported */
+	ARG_UNUSED(size);
+
+	if (((NRF_FICR->DEVICEADDR[0] != UINT32_MAX) ||
+	    ((NRF_FICR->DEVICEADDR[1] & UINT16_MAX) != UINT16_MAX)) &&
+	     (NRF_FICR->DEVICEADDRTYPE & 0x01)) {
+		sys_put_le32(NRF_FICR->DEVICEADDR[0], &addrs[0].bdaddr.val[0]);
+		sys_put_le16(NRF_FICR->DEVICEADDR[1], &addrs[0].bdaddr.val[4]);
+
+		/* The FICR value is a just a random number, with no knowledge
+		 * of the Bluetooth Specification requirements for random
+		 * static addresses.
+		 */
+		BT_ADDR_SET_STATIC(&addrs[0].bdaddr);
+
+		/* If no public address is provided and a static address is
+		 * available, then it is recommended to return an identity root
+		 * key (if available) from this command.
+		 */
+		if ((NRF_FICR->IR[0] != UINT32_MAX) &&
+		    (NRF_FICR->IR[1] != UINT32_MAX) &&
+		    (NRF_FICR->IR[2] != UINT32_MAX) &&
+		    (NRF_FICR->IR[3] != UINT32_MAX)) {
+			sys_put_le32(NRF_FICR->IR[0], &addrs[0].ir[0]);
+			sys_put_le32(NRF_FICR->IR[1], &addrs[0].ir[4]);
+			sys_put_le32(NRF_FICR->IR[2], &addrs[0].ir[8]);
+			sys_put_le32(NRF_FICR->IR[3], &addrs[0].ir[12]);
+		} else {
+			/* Mark IR as invalid */
+			(void)memset(addrs[0].ir, 0x00, sizeof(addrs[0].ir));
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
+void hci_vendor_read_key_hierarchy_roots(uint8_t ir[16], uint8_t er[16])
+{
+	/* Mark IR as invalid.
+	 * No public address is available, and static address IR should be read
+	 * using Read Static Addresses command.
+	 */
+	(void)memset(ir, 0x00, 16);
+
+	/* Fill in ER if present */
+	if ((NRF_FICR->ER[0] != UINT32_MAX) &&
+	    (NRF_FICR->ER[1] != UINT32_MAX) &&
+	    (NRF_FICR->ER[2] != UINT32_MAX) &&
+	    (NRF_FICR->ER[3] != UINT32_MAX)) {
+		sys_put_le32(NRF_FICR->ER[0], &er[0]);
+		sys_put_le32(NRF_FICR->ER[1], &er[4]);
+		sys_put_le32(NRF_FICR->ER[2], &er[8]);
+		sys_put_le32(NRF_FICR->ER[3], &er[12]);
+	} else {
+		/* Mark ER as invalid */
+		(void)memset(er, 0x00, 16);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/openisa/hci_vendor.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/openisa/hci_vendor.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/hci/openisa/hci_vendor.h	(working copy)
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_HCI_VS_HW_PLAT 0
+#define BT_HCI_VS_HW_VAR  0
+
+/* Map vendor command handler directly to common implementation */
+inline int hci_vendor_cmd_handle(uint16_t ocf, struct net_buf *cmd,
+				 struct net_buf **evt)
+{
+	return hci_vendor_cmd_handle_common(ocf, cmd, evt);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll.h	(working copy)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LL_VERSION_NUMBER BT_HCI_VERSION_5_2
+
+#define LL_ADV_CMDS_ANY    0 /* Any advertising cmd/evt allowed */
+#define LL_ADV_CMDS_LEGACY 1 /* Only legacy advertising cmd/evt allowed */
+#define LL_ADV_CMDS_EXT    2 /* Only extended advertising cmd/evt allowed */
+
+int ll_init(struct k_sem *sem_rx);
+void ll_reset(void);
+
+uint8_t *ll_addr_get(uint8_t addr_type, uint8_t *p_bdaddr);
+uint8_t ll_addr_set(uint8_t addr_type, uint8_t const *const p_bdaddr);
+
+#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING)
+uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle);
+uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle,
+					    uint8_t *handle);
+#else
+static inline uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle,
+						   uint8_t *handle)
+{
+	*handle = hci_handle;
+	return 0;
+}
+
+static inline uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle,
+							  uint8_t *handle)
+{
+	*handle = hci_handle;
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_HCI_RAW)
+int ll_adv_cmds_set(uint8_t adv_cmds);
+int ll_adv_cmds_is_ext(void);
+#else
+static inline int ll_adv_cmds_is_ext(void)
+{
+	return 1;
+}
+#endif /* CONFIG_BT_HCI_RAW */
+
+uint8_t ll_adv_params_set(uint8_t handle, uint16_t evt_prop, uint32_t interval,
+		       uint8_t adv_type, uint8_t own_addr_type,
+		       uint8_t direct_addr_type, uint8_t const *const direct_addr,
+		       uint8_t chan_map, uint8_t filter_policy,
+		       uint8_t *const tx_pwr, uint8_t phy_p, uint8_t skip,
+		       uint8_t phy_s, uint8_t sid, uint8_t sreq);
+uint8_t ll_adv_data_set(uint8_t handle, uint8_t len,
+			uint8_t const *const p_data);
+uint8_t ll_adv_scan_rsp_set(uint8_t handle, uint8_t len,
+			    uint8_t const *const p_data);
+uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t const *const addr);
+uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
+			       uint8_t len, uint8_t const *const data);
+uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
+			       uint8_t len, uint8_t const *const data);
+uint16_t ll_adv_aux_max_data_length_get(void);
+uint8_t ll_adv_aux_set_count_get(void);
+uint8_t ll_adv_aux_set_remove(uint8_t handle);
+uint8_t ll_adv_aux_set_clear(void);
+uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval,
+			      uint16_t flags);
+uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
+				uint8_t const *const data);
+uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
+		       uint8_t own_addr_type, uint8_t direct_addr_type,
+		       uint8_t const *const direct_addr, uint8_t chan_map,
+		       uint8_t filter_policy);
+uint8_t ll_adv_data_set(uint8_t len, uint8_t const *const p_data);
+uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const p_data);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
+		   uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry,
+		   uint8_t scan_window, uint8_t scan_delay);
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
+		   uint16_t duration, uint8_t max_ext_adv_evts);
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+uint8_t ll_adv_enable(uint8_t enable);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+
+uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
+		      uint32_t sdu_interval, uint16_t max_sdu,
+		      uint16_t max_latency, uint8_t rtn, uint8_t phy,
+		      uint8_t packing, uint8_t framing, uint8_t encryption,
+		      uint8_t *bcode);
+uint8_t ll_big_test_create(uint8_t big_handle, uint8_t adv_handle,
+			   uint8_t num_bis, uint32_t sdu_interval,
+			   uint16_t iso_interval, uint8_t nse, uint16_t max_sdu,
+			   uint16_t max_pdu, uint8_t phy, uint8_t packing,
+			   uint8_t framing, uint8_t bn, uint8_t irc,
+			   uint8_t pto, uint8_t encryption, uint8_t *bcode);
+uint8_t ll_big_terminate(uint8_t big_handle, uint8_t reason);
+
+uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window,
+		uint8_t own_addr_type, uint8_t filter_policy);
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_scan_enable(uint8_t enable); /* TODO: add duration and period */
+uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
+		       uint8_t *adv_addr, uint16_t skip,
+		       uint16_t sync_timeout, uint8_t sync_cte_type);
+uint8_t ll_sync_create_cancel(void **rx);
+uint8_t ll_sync_terminate(uint16_t handle);
+uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable);
+uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
+			   uint8_t encryption, uint8_t *bcode, uint8_t mse,
+			   uint16_t sync_timeout, uint8_t num_bis,
+			   uint8_t *bis);
+uint8_t ll_big_sync_terminate(uint8_t big_handle);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_scan_enable(uint8_t enable);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+uint8_t ll_wl_size_get(void);
+uint8_t ll_wl_clear(void);
+uint8_t ll_wl_add(bt_addr_le_t *addr);
+uint8_t ll_wl_remove(bt_addr_le_t *addr);
+
+void ll_rl_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type, uint8_t *id_addr);
+uint8_t ll_rl_size_get(void);
+uint8_t ll_rl_clear(void);
+uint8_t ll_rl_add(bt_addr_le_t *id_addr, const uint8_t pirk[16],
+		const uint8_t lirk[16]);
+uint8_t ll_rl_remove(bt_addr_le_t *id_addr);
+void ll_rl_crpa_set(uint8_t id_addr_type, uint8_t *id_addr, uint8_t rl_idx, uint8_t *crpa);
+uint8_t ll_rl_crpa_get(bt_addr_le_t *id_addr, bt_addr_t *crpa);
+uint8_t ll_rl_lrpa_get(bt_addr_le_t *id_addr, bt_addr_t *lrpa);
+uint8_t ll_rl_enable(uint8_t enable);
+void  ll_rl_timeout_set(uint16_t timeout);
+uint8_t ll_priv_mode_set(bt_addr_le_t *id_addr, uint8_t mode);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
+			  uint8_t filter_policy, uint8_t peer_addr_type,
+			  uint8_t const *const peer_addr, uint8_t own_addr_type,
+			  uint16_t interval, uint16_t latency, uint16_t timeout,
+			  uint8_t phy);
+uint8_t ll_connect_enable(uint8_t is_coded_included);
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
+			  uint8_t filter_policy, uint8_t peer_addr_type,
+			  uint8_t const *const peer_addr, uint8_t own_addr_type,
+			  uint16_t interval, uint16_t latency, uint16_t timeout);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_connect_disable(void **rx);
+uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min,
+		    uint16_t interval_max, uint16_t latency, uint16_t timeout);
+uint8_t ll_chm_update(uint8_t const *const chm);
+uint8_t ll_chm_get(uint16_t handle, uint8_t *const chm);
+uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand,
+		     uint8_t const *const ediv, uint8_t const *const ltk);
+uint8_t ll_start_enc_req_send(uint16_t handle, uint8_t err_code,
+			   uint8_t const *const ltk);
+uint8_t ll_feature_req_send(uint16_t handle);
+uint8_t ll_version_ind_send(uint16_t handle);
+uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason);
+uint8_t ll_rssi_get(uint16_t handle, uint8_t *const rssi);
+uint8_t ll_tx_pwr_lvl_get(uint8_t handle_type,
+		       uint16_t handle, uint8_t type, int8_t *const tx_pwr_lvl);
+void ll_tx_pwr_get(int8_t *const min, int8_t *const max);
+uint8_t ll_tx_pwr_lvl_set(uint8_t handle_type, uint16_t handle,
+			  int8_t *const tx_pwr_lvl);
+
+uint8_t ll_apto_get(uint16_t handle, uint16_t *const apto);
+uint8_t ll_apto_set(uint16_t handle, uint16_t apto);
+
+uint32_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_time);
+void ll_length_default_get(uint16_t *const max_tx_octets,
+			   uint16_t *const max_tx_time);
+uint32_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time);
+void ll_length_max_get(uint16_t *const max_tx_octets,
+		       uint16_t *const max_tx_time,
+		       uint16_t *const max_rx_octets,
+		       uint16_t *const max_rx_time);
+
+uint8_t ll_phy_get(uint16_t handle, uint8_t *const tx, uint8_t *const rx);
+uint8_t ll_phy_default_set(uint8_t tx, uint8_t rx);
+uint8_t ll_phy_req_send(uint16_t handle, uint8_t tx, uint8_t flags, uint8_t rx);
+
+/* Downstream - Data */
+void *ll_tx_mem_acquire(void);
+void ll_tx_mem_release(void *node_tx);
+int ll_tx_mem_enqueue(uint16_t handle, void *node_tx);
+
+/* Upstream - Num. Completes, Events and Data */
+uint8_t ll_rx_get(void **node_rx, uint16_t *handle);
+void ll_rx_dequeue(void);
+void ll_rx_mem_release(void **node_rx);
+
+/* External co-operation */
+void ll_timeslice_ticker_id_get(uint8_t * const instance_index, uint8_t * const user_id);
+void ll_radio_state_abort(void);
+uint32_t ll_radio_state_is_idle(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_feat.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_feat.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_feat.h	(working copy)
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BIT64
+#define BIT64(n) (1ULL << (n))
+#endif
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+#define LL_FEAT_BIT_ENC BIT64(BT_LE_FEAT_BIT_ENC)
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+#define LL_FEAT_BIT_ENC 0
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+#define LL_FEAT_BIT_CONN_PARAM_REQ BIT64(BT_LE_FEAT_BIT_CONN_PARAM_REQ)
+#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+#define LL_FEAT_BIT_CONN_PARAM_REQ 0
+#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_EXT_REJ_IND)
+#define LL_FEAT_BIT_EXT_REJ_IND BIT64(BT_LE_FEAT_BIT_EXT_REJ_IND)
+#else /* !CONFIG_BT_CTLR_EXT_REJ_IND */
+#define LL_FEAT_BIT_EXT_REJ_IND 0
+#endif /* !CONFIG_BT_CTLR_EXT_REJ_IND */
+
+#if defined(CONFIG_BT_CTLR_SLAVE_FEAT_REQ)
+#define LL_FEAT_BIT_SLAVE_FEAT_REQ BIT64(BT_LE_FEAT_BIT_SLAVE_FEAT_REQ)
+#else /* !CONFIG_BT_CTLR_SLAVE_FEAT_REQ */
+#define LL_FEAT_BIT_SLAVE_FEAT_REQ 0
+#endif /* !CONFIG_BT_CTLR_SLAVE_FEAT_REQ */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+#define LL_FEAT_BIT_PING BIT64(BT_LE_FEAT_BIT_PING)
+#else /* !CONFIG_BT_CTLR_LE_PING */
+#define LL_FEAT_BIT_PING 0
+#endif /* !CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX)
+#define LL_FEAT_BIT_DLE BIT64(BT_LE_FEAT_BIT_DLE)
+#define LL_LENGTH_OCTETS_RX_MAX CONFIG_BT_CTLR_DATA_LENGTH_MAX
+#else
+#define LL_FEAT_BIT_DLE 0
+#define LL_LENGTH_OCTETS_RX_MAX 27
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH_MAX */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#define LL_FEAT_BIT_PRIVACY BIT64(BT_LE_FEAT_BIT_PRIVACY)
+#else /* !CONFIG_BT_CTLR_PRIVACY */
+#define LL_FEAT_BIT_PRIVACY 0
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+#define LL_FEAT_BIT_EXT_SCAN BIT64(BT_LE_FEAT_BIT_EXT_SCAN)
+#else /* !CONFIG_BT_CTLR_EXT_SCAN_FP */
+#define LL_FEAT_BIT_EXT_SCAN 0
+#endif /* !CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+#define LL_FEAT_BIT_CHAN_SEL_2 BIT64(BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2)
+#else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+#define LL_FEAT_BIT_CHAN_SEL_2 0
+#endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+
+#if defined(CONFIG_BT_CTLR_MIN_USED_CHAN)
+#define LL_FEAT_BIT_MIN_USED_CHAN \
+		BIT64(BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC)
+#else /* !CONFIG_BT_CTLR_MIN_USED_CHAN */
+#define LL_FEAT_BIT_MIN_USED_CHAN 0
+#endif /* !CONFIG_BT_CTLR_MIN_USED_CHAN */
+
+#if defined(CONFIG_BT_CTLR_PHY_2M)
+#define LL_FEAT_BIT_PHY_2M BIT64(BT_LE_FEAT_BIT_PHY_2M)
+#else /* !CONFIG_BT_CTLR_PHY_2M */
+#define LL_FEAT_BIT_PHY_2M 0
+#endif /* !CONFIG_BT_CTLR_PHY_2M */
+
+#if defined(CONFIG_BT_CTLR_SMI_TX)
+#if defined(CONFIG_BT_CTLR_SMI_TX_SETTING)
+#define LL_FEAT_BIT_SMI_TX (ll_settings_smi_tx() ? \
+			    BIT64(BT_LE_FEAT_BIT_SMI_TX) : 0)
+#else /* !CONFIG_BT_CTLR_SMI_TX_SETTING */
+#define LL_FEAT_BIT_SMI_TX BIT64(BT_LE_FEAT_BIT_SMI_TX)
+#endif /* !CONFIG_BT_CTLR_SMI_TX_SETTING */
+#else /* !CONFIG_BT_CTLR_SMI_TX */
+#define LL_FEAT_BIT_SMI_TX 0
+#endif /* !CONFIG_BT_CTLR_SMI_TX */
+
+#if defined(CONFIG_BT_CTLR_SMI_RX)
+#define LL_FEAT_BIT_SMI_RX BIT64(BT_LE_FEAT_BIT_SMI_RX)
+#else /* !CONFIG_BT_CTLR_SMI_RX */
+#define LL_FEAT_BIT_SMI_RX 0
+#endif /* !CONFIG_BT_CTLR_SMI_RX */
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#define LL_FEAT_BIT_PHY_CODED BIT64(BT_LE_FEAT_BIT_PHY_CODED)
+#else /* !CONFIG_BT_CTLR_PHY_CODED */
+#define LL_FEAT_BIT_PHY_CODED 0
+#endif /* !CONFIG_BT_CTLR_PHY_CODED */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#define LL_FEAT_BIT_EXT_ADV BIT64(BT_LE_FEAT_BIT_EXT_ADV)
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+#define LL_FEAT_BIT_EXT_ADV 0
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC) || \
+	defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+#define LL_FEAT_BIT_PER_ADV BIT64(BT_LE_FEAT_BIT_PER_ADV)
+#else /* !CONFIG_BT_CTLR_ADV_PERIODIC && !CONFIG_BT_CTLR_SYNC_PERIODIC */
+#define LL_FEAT_BIT_PER_ADV 0
+#endif /* !CONFIG_BT_CTLR_ADV_PERIODIC && !CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+#define LL_FEAT_BIT_MASK         0x1FFFF
+#define LL_FEAT_BIT_MASK_VALID   0x1CF2F
+#define LL_FEAT_FILTER_OCTET0    0x1FF00
+#define LL_FEAT                  (LL_FEAT_BIT_ENC | \
+				  LL_FEAT_BIT_CONN_PARAM_REQ | \
+				  LL_FEAT_BIT_EXT_REJ_IND | \
+				  LL_FEAT_BIT_SLAVE_FEAT_REQ | \
+				  LL_FEAT_BIT_PING | \
+				  LL_FEAT_BIT_DLE | \
+				  LL_FEAT_BIT_PRIVACY | \
+				  LL_FEAT_BIT_EXT_SCAN | \
+				  LL_FEAT_BIT_PHY_2M | \
+				  LL_FEAT_BIT_SMI_TX | \
+				  LL_FEAT_BIT_SMI_RX | \
+				  LL_FEAT_BIT_PHY_CODED | \
+				  LL_FEAT_BIT_EXT_ADV | \
+				  LL_FEAT_BIT_PER_ADV | \
+				  LL_FEAT_BIT_CHAN_SEL_2 | \
+				  LL_FEAT_BIT_MIN_USED_CHAN)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_settings.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_settings.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/include/ll_settings.h	(working copy)
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_CTLR_VERSION_SETTINGS)
+
+uint16_t ll_settings_company_id(void);
+uint16_t ll_settings_subversion_number(void);
+
+#else
+
+static inline uint16_t ll_settings_company_id(void)
+{
+	return CONFIG_BT_CTLR_COMPANY_ID;
+}
+static inline uint16_t ll_settings_subversion_number(void)
+{
+	return CONFIG_BT_CTLR_SUBVERSION_NUMBER;
+}
+
+#endif /* CONFIG_BT_CTLR_VERSION_SETTINGS */
+
+bool ll_settings_smi_tx(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_addr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_addr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_addr.c	(working copy)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stddef.h>
+#include <string.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/controller.h>
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "hal/cpu.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "lll.h"
+
+#include "lll_adv.h"
+#include "lll_scan.h"
+
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_adv_internal.h"
+#include "ull_scan_internal.h"
+
+static uint8_t pub_addr[BDADDR_SIZE];
+static uint8_t rnd_addr[BDADDR_SIZE];
+
+uint8_t *ll_addr_get(uint8_t addr_type, uint8_t *bdaddr)
+{
+	if (addr_type > 1) {
+		return NULL;
+	}
+
+	if (addr_type) {
+		if (bdaddr) {
+			memcpy(bdaddr, rnd_addr, BDADDR_SIZE);
+		}
+
+		return rnd_addr;
+	}
+
+	if (bdaddr) {
+		memcpy(bdaddr, pub_addr, BDADDR_SIZE);
+	}
+
+	return pub_addr;
+}
+
+uint8_t ll_addr_set(uint8_t addr_type, uint8_t const *const bdaddr)
+{
+	if (IS_ENABLED(CONFIG_BT_BROADCASTER)) {
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		if (ull_adv_is_enabled(0) && !ll_adv_cmds_is_ext()) {
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+		if (ull_adv_is_enabled(0)) {
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_OBSERVER) &&
+	    (ull_scan_is_enabled(0) & (BIT(1) | BIT(2)))) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	if (addr_type) {
+		memcpy(rnd_addr, bdaddr, BDADDR_SIZE);
+	} else {
+		memcpy(pub_addr, bdaddr, BDADDR_SIZE);
+	}
+
+	return 0;
+}
+
+void bt_ctlr_set_public_addr(const uint8_t *addr)
+{
+    (void)memcpy(pub_addr, addr, sizeof(pub_addr));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_settings.c	(working copy)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <string.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/bluetooth.h>
+#include "ll_settings.h"
+
+#define LOG_MODULE_NAME bt_ctlr_ll_settings
+#include "common/log.h"
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_CTLR_VERSION_SETTINGS)
+
+static uint16_t company_id = CONFIG_BT_CTLR_COMPANY_ID;
+static uint16_t subversion = CONFIG_BT_CTLR_SUBVERSION_NUMBER;
+
+uint16_t ll_settings_company_id(void)
+{
+	return company_id;
+}
+uint16_t ll_settings_subversion_number(void)
+{
+	return subversion;
+}
+
+#endif /* CONFIG_BT_CTLR_VERSION_SETTINGS */
+
+#if defined(CONFIG_BT_CTLR_SMI_TX_SETTING)
+
+static uint8_t smi_tx;
+
+bool ll_settings_smi_tx(void)
+{
+	return smi_tx;
+}
+
+#endif /* CONFIG_BT_CTLR_SMI_TX_SETTING */
+
+static int ctlr_set(const char *name, size_t len_rd,
+		    settings_read_cb read_cb, void *store)
+{
+	ssize_t len;
+	int nlen;
+	const char *next;
+
+	nlen = settings_name_next(name, &next);
+
+#if defined(CONFIG_BT_CTLR_VERSION_SETTINGS)
+	if (!strncmp(name, "company", nlen)) {
+		len = read_cb(store, &company_id, sizeof(company_id));
+		if (len < 0) {
+			BT_ERR("Failed to read Company Id from storage"
+			       " (err %zd)", len);
+		} else {
+			BT_DBG("Company Id set to %04x", company_id);
+		}
+		return 0;
+	}
+	if (!strncmp(name, "subver", nlen)) {
+		len = read_cb(store, &subversion, sizeof(subversion));
+		if (len < 0) {
+			BT_ERR("Failed to read Subversion from storage"
+			       " (err %zd)", len);
+		} else {
+			BT_DBG("Subversion set to %04x", subversion);
+		}
+		return 0;
+	}
+#endif /* CONFIG_BT_CTLR_VERSION_SETTINGS */
+
+#if defined(CONFIG_BT_CTLR_SMI_TX_SETTING)
+	if (!strncmp(name, "smi_tx", nlen)) {
+		len = read_cb(store, &smi_tx, sizeof(smi_tx));
+		if (len < 0) {
+			BT_ERR("Failed to read SMI TX flag from storage"
+			       " (err %zd)", len);
+		} else {
+			BT_DBG("SMI TX flag set to %04x", smi_tx);
+		}
+		return 0;
+	}
+#endif /* CONFIG_BT_CTLR_SMI_TX_SETTING */
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_ctlr, "bt/ctlr", NULL, ctlr_set, NULL, NULL);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_test.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_test.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_test.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+uint32_t ll_test_tx(uint8_t chan, uint8_t len, uint8_t type, uint8_t phy);
+uint32_t ll_test_rx(uint8_t chan, uint8_t phy, uint8_t mod_idx);
+uint32_t ll_test_end(uint16_t *num_rx);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c	(working copy)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2016-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_vs.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "ll.h"
+#include "lll.h"
+
+#include "lll_scan.h"
+#include "ull_scan_types.h"
+#include "ull_scan_internal.h"
+
+#include "lll_adv.h"
+#include "ull_adv_types.h"
+#include "ull_adv_internal.h"
+
+#include "lll_conn.h"
+#include "ull_conn_types.h"
+#include "ull_conn_internal.h"
+
+uint8_t ll_tx_pwr_lvl_get(uint8_t handle_type,
+		       uint16_t handle, uint8_t type, int8_t *tx_pwr_lvl)
+{
+	switch (handle_type) {
+#if defined(CONFIG_BT_BROADCASTER) &&\
+	defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): {
+			struct ll_adv_set *adv;
+
+#if !defined(CONFIG_BT_CTLR_ADV_EXT)
+			/* Ignore handle if AE not enabled */
+			handle = 0;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+			/* Allow the app to get Tx power
+			 * when advertising is off
+			 */
+			adv = ull_adv_set_get(handle);
+			if (!adv) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+			*tx_pwr_lvl = adv->lll.tx_pwr_lvl;
+			break;
+		}
+#endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+#if defined(CONFIG_BT_OBSERVER) &&\
+	defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): {
+			struct ll_scan_set *scan;
+
+			/* Ignore handle in case of scanner
+			 * as for mesh extensions and scanning
+			 * sets this control  is handled
+			 * at a lower-level in the stack.
+			 */
+			handle = 0;
+			/* Allow the app to get Tx power
+			 * when scanning is off
+			 */
+			scan = ull_scan_set_get(handle);
+			if (!scan) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+			*tx_pwr_lvl = scan->lll.tx_pwr_lvl;
+			break;
+		}
+#endif /* CONFIG_BT_OBSERVER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL*/
+#if defined(CONFIG_BT_CONN)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): {
+			struct ll_conn *conn;
+
+			conn = ll_connected_get(handle);
+			if (!conn) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+
+			if (type) {
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+				/* Level desired is maximum available */
+				*tx_pwr_lvl = lll_radio_tx_pwr_max_get();
+#else  /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+				/* Return default if not multiple TXP */
+				*tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+			} else {
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+				/* Current level is requested */
+				*tx_pwr_lvl = conn->lll.tx_pwr_lvl;
+#else  /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+				/* Return default if not multiple TXP */
+				*tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+			}
+			break;
+		}
+#endif /* CONFIG_BT_CONN */
+		default: {
+			return BT_HCI_ERR_UNKNOWN_CMD;
+		}
+	}
+
+	return BT_HCI_ERR_SUCCESS;
+}
+
+
+uint8_t ll_tx_pwr_lvl_set(uint8_t handle_type, uint16_t handle,
+			  int8_t *const tx_pwr_lvl)
+{
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	if (*tx_pwr_lvl == BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF) {
+		/* If no preference selected, then use default Tx power */
+		*tx_pwr_lvl = RADIO_TXP_DEFAULT;
+	}
+
+	/**
+	 * Check that desired Tx power matches the achievable transceiver
+	 * Tx power capabilities by flooring - if selected power matches than
+	 * is used, otherwise next smaller power available is used.
+	 */
+	*tx_pwr_lvl = lll_radio_tx_pwr_floor(*tx_pwr_lvl);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	switch (handle_type) {
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+#if defined(CONFIG_BT_BROADCASTER)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): {
+			struct ll_adv_set *adv;
+
+#if !defined(CONFIG_BT_CTLR_ADV_EXT)
+			/* Ignore handle if AE not enabled */
+			handle = 0;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+			/* Allow the app to set Tx power
+			 * prior to advertising
+			 */
+			adv = ull_adv_set_get(handle);
+			if (!adv) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+			adv->lll.tx_pwr_lvl = *tx_pwr_lvl;
+			break;
+		}
+#endif /* CONFIG_BT_BROADCASTER */
+#if defined(CONFIG_BT_OBSERVER)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): {
+			struct ll_scan_set *scan;
+
+			/* Ignore handle in case of scanner
+			 * as for mesh extensions and scanning
+			 * sets this control is handled
+			 * at a lower-level in the stack.
+			 */
+			handle = 0;
+			/* Allow the app to set Tx power
+			 * prior to scanning
+			 */
+			scan = ull_scan_set_get(handle);
+			if (!scan) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+			scan->lll.tx_pwr_lvl = *tx_pwr_lvl;
+			break;
+		}
+#endif /* CONFIG_BT_OBSERVER */
+#if defined(CONFIG_BT_CONN)
+		case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): {
+			struct ll_conn *conn;
+
+			conn = ll_connected_get(handle);
+			if (!conn) {
+				return BT_HCI_ERR_UNKNOWN_CONN_ID;
+			}
+			conn->lll.tx_pwr_lvl = *tx_pwr_lvl;
+			break;
+		}
+#endif /* CONFIG_BT_CONN */
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+		default: {
+			return BT_HCI_ERR_UNKNOWN_CMD;
+		}
+	}
+
+	return BT_HCI_ERR_SUCCESS;
+}
+
+void ll_tx_pwr_get(int8_t *min, int8_t *max)
+{
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	*min = lll_radio_tx_pwr_min_get();
+	*max = lll_radio_tx_pwr_max_get();
+#else
+	*min = RADIO_TXP_DEFAULT;
+	*max = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll.h	(working copy)
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#if defined(CONFIG_BT_CTLR_RX_PDU_META)
+#include "lll_meta.h"
+#endif /* CONFIG_BT_CTLR_RX_PDU_META */
+
+#define TICKER_INSTANCE_ID_CTLR 0
+#define TICKER_USER_ID_LLL      MAYFLY_CALL_ID_0
+#define TICKER_USER_ID_ULL_HIGH MAYFLY_CALL_ID_1
+#define TICKER_USER_ID_ULL_LOW  MAYFLY_CALL_ID_2
+#define TICKER_USER_ID_THREAD   MAYFLY_CALL_ID_PROGRAM
+
+#define EVENT_PIPELINE_MAX 7
+#define EVENT_DONE_MAX 3
+
+#define HDR_ULL(p)     ((void *)((uint8_t *)(p) + sizeof(struct evt_hdr)))
+#define HDR_ULL2LLL(p) ((struct lll_hdr *)((uint8_t *)(p) + \
+					   sizeof(struct ull_hdr)))
+#define HDR_LLL2EVT(p) ((struct evt_hdr *)((struct lll_hdr *)(p))->parent)
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+#define XON_BITMASK BIT(31) /* XTAL has been retained from previous prepare */
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+
+#if defined(CONFIG_BT_OBSERVER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#define BT_CTLR_SCAN_SET 2
+#else /* !CONFIG_BT_CTLR_PHY_CODED */
+#define BT_CTLR_SCAN_SET 1
+#endif /* !CONFIG_BT_CTLR_PHY_CODED */
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+#define BT_CTLR_SCAN_SET 1
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+enum {
+	TICKER_ID_LLL_PREEMPT = 0,
+
+#if defined(CONFIG_BT_BROADCASTER)
+	TICKER_ID_ADV_STOP,
+	TICKER_ID_ADV_BASE,
+#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
+	TICKER_ID_ADV_LAST = ((TICKER_ID_ADV_BASE) +
+			      (CONFIG_BT_CTLR_ADV_SET) - 1),
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+	TICKER_ID_ADV_AUX_BASE,
+	TICKER_ID_ADV_AUX_LAST = ((TICKER_ID_ADV_AUX_BASE) +
+				  (CONFIG_BT_CTLR_ADV_AUX_SET) - 1),
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	TICKER_ID_ADV_SYNC_BASE,
+	TICKER_ID_ADV_SYNC_LAST = ((TICKER_ID_ADV_SYNC_BASE) +
+				   (CONFIG_BT_CTLR_ADV_SYNC_SET) - 1),
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	TICKER_ID_SCAN_STOP,
+	TICKER_ID_SCAN_BASE,
+	TICKER_ID_SCAN_LAST = ((TICKER_ID_SCAN_BASE) + (BT_CTLR_SCAN_SET) - 1),
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	TICKER_ID_SCAN_AUX_BASE,
+	TICKER_ID_SCAN_AUX_LAST = ((TICKER_ID_SCAN_AUX_BASE) +
+				   (CONFIG_BT_CTLR_SCAN_AUX_SET) - 1),
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	TICKER_ID_SCAN_SYNC_BASE,
+	TICKER_ID_SCAN_SYNC_LAST = ((TICKER_ID_SCAN_SYNC_BASE) +
+				    (CONFIG_BT_CTLR_SCAN_SYNC_SET) - 1),
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+	TICKER_ID_CONN_BASE,
+	TICKER_ID_CONN_LAST = ((TICKER_ID_CONN_BASE) + (CONFIG_BT_MAX_CONN) -
+			       1),
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT) && \
+	(CONFIG_BT_CTLR_USER_TICKER_ID_RANGE > 0)
+	TICKER_ID_USER_BASE,
+	TICKER_ID_USER_LAST = (TICKER_ID_USER_BASE +
+			       CONFIG_BT_CTLR_USER_TICKER_ID_RANGE - 1),
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+	TICKER_ID_MAX,
+};
+
+#if defined(CONFIG_BT_BROADCASTER) && !defined(CONFIG_BT_CTLR_ADV_EXT) && \
+	!defined(CONFIG_BT_HCI_MESH_EXT)
+#define TICKER_ID_ADV_LAST TICKER_ID_ADV_BASE
+#endif
+
+#define TICKER_ID_ULL_BASE ((TICKER_ID_LLL_PREEMPT) + 1)
+
+enum ull_status {
+	ULL_STATUS_SUCCESS,
+	ULL_STATUS_FAILURE,
+	ULL_STATUS_BUSY,
+};
+
+struct evt_hdr {
+	uint32_t ticks_xtal_to_start;
+	uint32_t ticks_active_to_start;
+	uint32_t ticks_preempt_to_start;
+	uint32_t ticks_slot;
+};
+
+struct ull_hdr {
+	uint8_t volatile ref;  /* Number of ongoing (between Prepare and Done)
+				* events
+				*/
+	void (*disabled_cb)(void *param);
+	void *disabled_param;
+};
+
+struct lll_hdr {
+	void *parent;
+	uint8_t is_stop:1;
+};
+
+struct lll_prepare_param {
+	uint32_t ticks_at_expire;
+	uint32_t remainder;
+	uint16_t lazy;
+	void  *param;
+};
+
+typedef int (*lll_prepare_cb_t)(struct lll_prepare_param *prepare_param);
+typedef int (*lll_is_abort_cb_t)(void *next, int prio, void *curr,
+				 lll_prepare_cb_t *resume_cb, int *resume_prio);
+typedef void (*lll_abort_cb_t)(struct lll_prepare_param *prepare_param,
+			       void *param);
+
+struct lll_event {
+	struct lll_prepare_param prepare_param;
+	lll_prepare_cb_t         prepare_cb;
+	lll_is_abort_cb_t        is_abort_cb;
+	lll_abort_cb_t           abort_cb;
+	int                      prio;
+	uint8_t                     is_resume:1;
+	uint8_t                     is_aborted:1;
+};
+
+enum node_rx_type {
+	/* Unused */
+	NODE_RX_TYPE_NONE = 0x00,
+	/* Signals completion of RX event */
+	NODE_RX_TYPE_EVENT_DONE = 0x01,
+	/* Signals arrival of RX Data Channel payload */
+	NODE_RX_TYPE_DC_PDU = 0x02,
+	/* Signals release of RX Data Channel payload */
+	NODE_RX_TYPE_DC_PDU_RELEASE = 0x03,
+
+#if defined(CONFIG_BT_OBSERVER)
+	/* Advertisement report from scanning */
+	NODE_RX_TYPE_REPORT = 0x04,
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_OBSERVER)
+	NODE_RX_TYPE_EXT_1M_REPORT = 0x05,
+	NODE_RX_TYPE_EXT_2M_REPORT = 0x06,
+	NODE_RX_TYPE_EXT_CODED_REPORT = 0x07,
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	NODE_RX_TYPE_SYNC = 0x08,
+	NODE_RX_TYPE_SYNC_LOST = 0x09,
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_OBSERVER */
+#if defined(CONFIG_BT_BROADCASTER)
+	NODE_RX_TYPE_EXT_ADV_TERMINATE = 0x0a,
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	NODE_RX_TYPE_SCAN_REQ = 0x0b,
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CONN)
+	NODE_RX_TYPE_CONNECTION = 0x0c,
+	NODE_RX_TYPE_TERMINATE = 0x0d,
+	NODE_RX_TYPE_CONN_UPDATE = 0x0e,
+	NODE_RX_TYPE_ENC_REFRESH = 0x0f,
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	NODE_RX_TYPE_APTO = 0x10,
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	NODE_RX_TYPE_CHAN_SEL_ALGO = 0x11,
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	NODE_RX_TYPE_PHY_UPDATE = 0x12,
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	NODE_RX_TYPE_RSSI = 0x13,
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	NODE_RX_TYPE_PROFILE = 0x14,
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	NODE_RX_TYPE_ADV_INDICATION = 0x15,
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	NODE_RX_TYPE_SCAN_INDICATION = 0x16,
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	NODE_RX_TYPE_MESH_ADV_CPLT = 0x17,
+	NODE_RX_TYPE_MESH_REPORT = 0x18,
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+/* Following proprietary defines must be at end of enum range */
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	NODE_RX_TYPE_USER_START = 0x18,
+	NODE_RX_TYPE_USER_END = NODE_RX_TYPE_USER_START +
+				CONFIG_BT_CTLR_USER_EVT_RANGE,
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+};
+
+/* Footer of node_rx_hdr */
+struct node_rx_ftr {
+	union {
+		void *param;
+		struct {
+			uint8_t  status;
+			uint8_t  num_events;
+			uint16_t conn_handle;
+		} param_adv_term;
+	};
+	void     *extra;
+	uint32_t ticks_anchor;
+	uint32_t radio_end_us;
+	uint8_t  rssi;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  lrpa_used:1;
+	uint8_t  rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	uint8_t  direct;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	uint8_t  chan_idx;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+};
+
+
+/* Header of node_rx_pdu */
+struct node_rx_hdr {
+	union {
+		void        *next;    /* For slist, by hci module */
+		memq_link_t *link;    /* Supply memq_link from ULL to LLL */
+		uint8_t     ack_last; /* Tx ack queue index at this node rx */
+	};
+
+	enum node_rx_type type;
+	uint8_t           user_meta; /* User metadata */
+	uint16_t          handle;    /* State/Role instance handle */
+
+	union {
+#if defined(CONFIG_BT_CTLR_RX_PDU_META)
+		lll_rx_pdu_meta_t  rx_pdu_meta;
+#endif /* CONFIG_BT_CTLR_RX_PDU_META */
+		struct node_rx_ftr rx_ftr;
+	};
+};
+
+struct node_rx_pdu {
+	struct node_rx_hdr hdr;
+	uint8_t               pdu[0];
+};
+
+enum {
+	EVENT_DONE_EXTRA_TYPE_NONE,
+
+#if defined(CONFIG_BT_CONN)
+	EVENT_DONE_EXTRA_TYPE_CONN,
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	EVENT_DONE_EXTRA_TYPE_ADV,
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_OBSERVER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	EVENT_DONE_EXTRA_TYPE_SCAN_AUX,
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	EVENT_DONE_EXTRA_TYPE_SYNC,
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+/* Following proprietary defines must be at end of enum range */
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	EVENT_DONE_EXTRA_TYPE_USER_START,
+	EVENT_DONE_EXTRA_TYPE_USER_END = EVENT_DONE_EXTRA_TYPE_USER_START +
+		CONFIG_BT_CTLR_USER_EVT_RANGE,
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+};
+
+struct event_done_extra_drift {
+	uint32_t start_to_address_actual_us;
+	uint32_t window_widening_event_us;
+	uint32_t preamble_to_addr_us;
+};
+
+struct event_done_extra {
+	uint8_t type;
+	union {
+		struct {
+			uint16_t trx_cnt;
+			uint8_t  crc_valid;
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			uint8_t  mic_state;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#if defined(CONFIG_BT_PERIPHERAL) || defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+			union {
+				struct event_done_extra_drift drift;
+			};
+#endif /* CONFIG_BT_PERIPHERAL || CONFIG_BT_CTLR_SYNC_PERIODIC */
+		};
+	};
+};
+
+struct node_rx_event_done {
+	struct node_rx_hdr      hdr;
+	void                    *param;
+	struct event_done_extra extra;
+};
+
+static inline void lll_hdr_init(void *lll, void *parent)
+{
+	struct lll_hdr *hdr = lll;
+
+	hdr->parent = parent;
+	hdr->is_stop = 0U;
+}
+
+static inline int lll_stop(void *lll)
+{
+	struct lll_hdr *hdr = lll;
+	int ret = !!hdr->is_stop;
+
+	hdr->is_stop = 1U;
+
+	return ret;
+}
+
+int lll_init(void);
+int lll_reset(void);
+void lll_resume(void *param);
+void lll_disable(void *param);
+uint32_t lll_radio_is_idle(void);
+uint32_t lll_radio_tx_ready_delay_get(uint8_t phy, uint8_t flags);
+uint32_t lll_radio_rx_ready_delay_get(uint8_t phy, uint8_t flags);
+int8_t lll_radio_tx_pwr_min_get(void);
+int8_t lll_radio_tx_pwr_max_get(void);
+int8_t lll_radio_tx_pwr_floor(int8_t tx_pwr_lvl);
+
+int lll_csrand_get(void *buf, size_t len);
+int lll_csrand_isr_get(void *buf, size_t len);
+int lll_rand_get(void *buf, size_t len);
+int lll_rand_isr_get(void *buf, size_t len);
+
+int ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb,
+			       lll_abort_cb_t abort_cb,
+			       struct lll_prepare_param *prepare_param,
+			       lll_prepare_cb_t prepare_cb, int prio,
+			       uint8_t is_resume);
+void *ull_prepare_dequeue_get(void);
+void *ull_prepare_dequeue_iter(uint8_t *idx);
+void *ull_pdu_rx_alloc_peek(uint8_t count);
+void *ull_pdu_rx_alloc_peek_iter(uint8_t *idx);
+void *ull_pdu_rx_alloc(void);
+void ull_rx_put(memq_link_t *link, void *rx);
+void ull_rx_sched(void);
+void *ull_event_done_extra_get(void);
+void *ull_event_done(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.h	(working copy)
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+uint8_t lll_chan_sel_1(uint8_t *chan_use, uint8_t hop, uint16_t latency, uint8_t *chan_map,
+		    uint8_t chan_count);
+uint8_t lll_chan_sel_2(uint16_t counter, uint16_t chan_id, uint8_t *chan_map,
+		    uint8_t chan_count);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_chan.c	(working copy)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_chan
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index);
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+static uint16_t chan_prn(uint16_t counter, uint16_t chan_id);
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
+
+#if defined(CONFIG_BT_CONN)
+uint8_t lll_chan_sel_1(uint8_t *chan_use, uint8_t hop, uint16_t latency, uint8_t *chan_map,
+		    uint8_t chan_count)
+{
+	uint8_t chan_next;
+
+	chan_next = ((*chan_use) + (hop * (1 + latency))) % 37;
+	*chan_use = chan_next;
+
+	if ((chan_map[chan_next >> 3] & (1 << (chan_next % 8))) == 0U) {
+		uint8_t chan_index;
+
+		chan_index = chan_next % chan_count;
+		chan_next = chan_sel_remap(chan_map, chan_index);
+
+	} else {
+		/* channel can be used, return it */
+	}
+
+	return chan_next;
+}
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+uint8_t lll_chan_sel_2(uint16_t counter, uint16_t chan_id, uint8_t *chan_map,
+		    uint8_t chan_count)
+{
+	uint8_t chan_next;
+	uint16_t prn_e;
+
+	prn_e = chan_prn(counter, chan_id);
+	chan_next = prn_e % 37;
+
+	if ((chan_map[chan_next >> 3] & (1 << (chan_next % 8))) == 0U) {
+		uint8_t chan_index;
+
+		chan_index = ((uint32_t)chan_count * prn_e) >> 16;
+		chan_next = chan_sel_remap(chan_map, chan_index);
+
+	} else {
+		/* channel can be used, return it */
+	}
+
+	return chan_next;
+}
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
+
+static uint8_t chan_sel_remap(uint8_t *chan_map, uint8_t chan_index)
+{
+	uint8_t chan_next;
+	uint8_t byte_count;
+
+	chan_next = 0U;
+	byte_count = 5U;
+	while (byte_count--) {
+		uint8_t bite;
+		uint8_t bit_count;
+
+		bite = *chan_map;
+		bit_count = 8U;
+		while (bit_count--) {
+			if (bite & 0x01) {
+				if (chan_index == 0U) {
+					break;
+				}
+				chan_index--;
+			}
+			chan_next++;
+			bite >>= 1;
+		}
+
+		if (bit_count < 8) {
+			break;
+		}
+
+		chan_map++;
+	}
+
+	return chan_next;
+}
+
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+#if defined(RADIO_UNIT_TEST)
+void lll_chan_sel_2_ut(void)
+{
+	uint8_t chan_map_1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F};
+	uint8_t chan_map_2[] = {0x00, 0x06, 0xE0, 0x00, 0x1E};
+	uint8_t m;
+
+	m = chan_sel_2(1, 0x305F, chan_map_1, 37);
+	LL_ASSERT(m == 20U);
+
+	m = chan_sel_2(2, 0x305F, chan_map_1, 37);
+	LL_ASSERT(m == 6U);
+
+	m = chan_sel_2(3, 0x305F, chan_map_1, 37);
+	LL_ASSERT(m == 21U);
+
+	m = chan_sel_2(6, 0x305F, chan_map_2, 9);
+	LL_ASSERT(m == 23U);
+
+	m = chan_sel_2(7, 0x305F, chan_map_2, 9);
+	LL_ASSERT(m == 9U);
+
+	m = chan_sel_2(8, 0x305F, chan_map_2, 9);
+	LL_ASSERT(m == 34U);
+}
+#endif /* RADIO_UNIT_TEST */
+
+/* Attribution:
+ * http://graphics.stanford.edu/%7Eseander/bithacks.html#ReverseByteWith32Bits
+ */
+static uint8_t chan_rev_8(uint8_t b)
+{
+	b = (((uint32_t)b * 0x0802LU & 0x22110LU) |
+	     ((uint32_t)b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
+
+	return b;
+}
+
+static uint16_t chan_perm(uint16_t i)
+{
+	return (chan_rev_8((i >> 8) & 0xFF) << 8) | chan_rev_8(i & 0xFF);
+}
+
+static uint16_t chan_mam(uint16_t a, uint16_t b)
+{
+	return ((uint32_t)a * 17U + b) & 0xFFFF;
+}
+
+static uint16_t chan_prn(uint16_t counter, uint16_t chan_id)
+{
+	uint8_t iterate;
+	uint16_t prn_e;
+
+	prn_e = counter ^ chan_id;
+
+	for (iterate = 0U; iterate < 3; iterate++) {
+		prn_e = chan_perm(prn_e);
+		prn_e = chan_mam(prn_e, chan_id);
+	}
+
+	prn_e ^= chan_id;
+
+	return prn_e;
+}
+#endif /* CONFIG_BT_CTLR_CHAN_SEL_2 */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_clock.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_clock.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_clock.h	(working copy)
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_clock_init(void);
+int lll_clock_wait(void);
+int lll_hfclock_on(void);
+int lll_hfclock_on_wait(void);
+int lll_hfclock_off(void);
+uint8_t lll_clock_sca_local_get(void);
+uint32_t lll_clock_ppm_local_get(void);
+uint32_t lll_clock_ppm_get(uint8_t sca);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_conn.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_conn.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_conn.h	(working copy)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#if defined(CONFIG_BT_CTLR_CONN_META)
+#include "lll_conn_meta.h"
+#endif /* CONFIG_BT_CTLR_CONN_META */
+
+#define LLL_CONN_RSSI_SAMPLE_COUNT 10
+#define LLL_CONN_RSSI_THRESHOLD    4
+
+#define LLL_CONN_MIC_NONE 0
+#define LLL_CONN_MIC_PASS 1
+#define LLL_CONN_MIC_FAIL 2
+
+struct lll_tx {
+	uint16_t handle;
+	void *node;
+};
+
+struct node_tx {
+	union {
+		void        *next;
+		memq_link_t *link;
+	};
+
+	uint8_t pdu[];
+};
+
+struct lll_conn {
+	struct lll_hdr hdr;
+
+	uint8_t access_addr[4];
+	uint8_t crc_init[3];
+
+	uint16_t handle;
+	uint16_t interval;
+	uint16_t latency;
+
+	uint16_t latency_prepare;
+	uint16_t latency_event;
+	uint16_t event_counter;
+
+	uint8_t data_chan_map[5];
+	uint8_t data_chan_count:6;
+	uint8_t data_chan_sel:1;
+	uint8_t role:1;
+
+	union {
+		struct {
+			uint8_t data_chan_hop;
+			uint8_t data_chan_use;
+		};
+
+		uint16_t data_chan_id;
+	};
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	struct {
+		uint8_t  latency_enabled:1;
+		uint32_t window_widening_periodic_us;
+		uint32_t window_widening_max_us;
+		uint32_t window_widening_prepare_us;
+		uint32_t window_widening_event_us;
+		uint32_t window_size_prepare_us;
+		uint32_t window_size_event_us;
+	} slave;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	uint16_t max_tx_octets;
+	uint16_t max_rx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	uint16_t max_tx_time;
+	uint16_t max_rx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	uint8_t phy_tx:3;
+	uint8_t phy_flags:1;
+	uint8_t phy_tx_time:3;
+	uint8_t phy_rx:3;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	MEMQ_DECLARE(tx);
+	memq_link_t link_tx;
+	memq_link_t *link_tx_free;
+	uint8_t  packet_tx_head_len;
+	uint8_t  packet_tx_head_offset;
+
+	uint8_t sn:1;
+	uint8_t nesn:1;
+	uint8_t empty:1;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	uint8_t enc_rx:1;
+	uint8_t enc_tx:1;
+
+	struct ccm ccm_rx;
+	struct ccm ccm_tx;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	uint8_t  rssi_latest;
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+	uint8_t  rssi_reported;
+	uint8_t  rssi_sample_count;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_CONN_META)
+	struct lll_conn_meta conn_meta;
+#endif /* CONFIG_BT_CTLR_CONN_META */
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif
+};
+
+int lll_conn_init(void);
+int lll_conn_reset(void);
+void lll_conn_flush(uint16_t handle, struct lll_conn *lll);
+
+void lll_conn_prepare_reset(void);
+void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param);
+void lll_conn_isr_rx(void *param);
+void lll_conn_isr_tx(void *param);
+void lll_conn_rx_pkt_set(struct lll_conn *lll);
+void lll_conn_tx_pkt_set(struct lll_conn *lll, struct pdu_data *pdu_data_tx);
+void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx);
+uint8_t lll_conn_force_md_cnt_set(uint8_t force_md_cnt);
+
+extern void ull_conn_lll_ack_enqueue(uint16_t handle, struct node_tx *tx);
+extern uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_filter.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_filter.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_filter.h	(working copy)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define WL_SIZE            8
+#define FILTER_IDX_NONE    0xFF
+
+struct lll_filter {
+	uint8_t  enable_bitmask;
+	uint8_t  addr_type_bitmask;
+	uint8_t  bdaddr[WL_SIZE][BDADDR_SIZE];
+};
+
+/* Whitelist peer list */
+struct lll_whitelist {
+	uint8_t      taken:1;
+	uint8_t      id_addr_type:1;
+	uint8_t      rl_idx;
+	bt_addr_t id_addr;
+};
+
+struct lll_resolvelist {
+	uint8_t      taken:1;
+	uint8_t      rpas_ready:1;
+	uint8_t      pirk:1;
+	uint8_t      lirk:1;
+	uint8_t      dev:1;
+	uint8_t      wl:1;
+
+	uint8_t      id_addr_type:1;
+	bt_addr_t id_addr;
+
+	uint8_t      local_irk[16];
+	uint8_t      pirk_idx;
+	bt_addr_t curr_rpa;
+	bt_addr_t peer_rpa;
+	bt_addr_t *local_rpa;
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+	bt_addr_t target_rpa;
+#endif
+};
+
+bool ull_filter_lll_lrpa_used(uint8_t rl_idx);
+extern bt_addr_t *ull_filter_lll_lrpa_get(uint8_t rl_idx);
+extern uint8_t *ull_filter_lll_irks_get(uint8_t *count);
+extern uint8_t ull_filter_lll_rl_idx(bool whitelist, uint8_t devmatch_id);
+extern uint8_t ull_filter_lll_rl_irk_idx(uint8_t irkmatch_id);
+extern bool ull_filter_lll_irk_whitelisted(uint8_t rl_idx);
+extern struct lll_filter *ull_filter_lll_get(bool whitelist);
+extern struct lll_whitelist *ull_filter_lll_whitelist_get(void);
+extern struct lll_resolvelist *ull_filter_lll_resolvelist_get(void);
+extern bool ull_filter_lll_rl_idx_allowed(uint8_t irkmatch_ok, uint8_t rl_idx);
+extern bool ull_filter_lll_rl_addr_allowed(uint8_t id_addr_type, uint8_t *id_addr,
+					   uint8_t *rl_idx);
+extern bool ull_filter_lll_rl_addr_resolve(uint8_t id_addr_type, uint8_t *id_addr,
+					   uint8_t rl_idx);
+extern bool ull_filter_lll_rl_enabled(void);
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+typedef void (*resolve_callback_t)(void *param);
+extern uint8_t ull_filter_deferred_resolve(bt_addr_t *rpa,
+					resolve_callback_t cb);
+extern uint8_t ull_filter_deferred_targeta_resolve(bt_addr_t *rpa,
+						uint8_t rl_idx,
+						resolve_callback_t cb);
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_scan.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_scan.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_scan.h	(working copy)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct lll_scan {
+	struct lll_hdr hdr;
+
+#if defined(CONFIG_BT_CENTRAL)
+	/* NOTE: conn context has to be after lll_hdr */
+	struct lll_conn *conn;
+	uint32_t conn_ticks_slot;
+	uint32_t conn_win_offset_us;
+	uint16_t conn_timeout;
+#endif /* CONFIG_BT_CENTRAL */
+
+	uint8_t  state:1;
+	uint8_t  chan:2;
+	uint8_t  filter_policy:2;
+	uint8_t  adv_addr_type:1;
+	uint8_t  init_addr_type:1;
+	uint8_t  type:1;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint8_t  phy:3;
+	uint8_t  is_adv_ind:1;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  rpa_gen:1;
+	/* initiator only */
+	uint8_t rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	uint8_t  init_addr[BDADDR_SIZE];
+	uint8_t  adv_addr[BDADDR_SIZE];
+
+	uint16_t interval;
+	uint32_t ticks_window;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+};
+
+struct lll_scan_aux {
+	struct lll_hdr hdr;
+
+	uint8_t chan:6;
+
+	uint8_t phy:3;
+
+	uint32_t window_size_us;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+};
+
+int lll_scan_init(void);
+int lll_scan_reset(void);
+
+void lll_scan_prepare(void *param);
+
+extern uint8_t ull_scan_lll_handle_get(struct lll_scan *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_sync.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_sync.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/lll_sync.h	(working copy)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct lll_sync {
+	struct lll_hdr hdr;
+
+	uint8_t access_addr[4];
+	uint8_t crc_init[3];
+
+	uint16_t skip_prepare;
+	uint16_t skip_event;
+	uint16_t event_counter;
+
+	uint8_t data_chan_map[5];
+	uint8_t data_chan_count:6;
+	uint16_t data_chan_id;
+
+	uint32_t window_widening_periodic_us;
+	uint32_t window_widening_max_us;
+	uint32_t window_widening_prepare_us;
+	uint32_t window_widening_event_us;
+	uint32_t window_size_event_us;
+
+	uint8_t phy:3;
+	uint8_t is_enabled:1;
+};
+
+int lll_sync_init(void);
+int lll_sync_reset(void);
+void lll_sync_prepare(void *param);
+
+extern uint16_t ull_sync_lll_handle_get(struct lll_sync *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/cpu_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/cpu_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/cpu_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/nrf5/cpu.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/debug_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/debug_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/debug_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/nrf5/debug.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c	(working copy)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+
+#include <nrfx/hal/nrf_rtc.h>
+
+#include "hal/cntr.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hal_cntr
+#include "common/log.h"
+#include "hal/debug.h"
+
+#ifndef NRF_RTC
+#define NRF_RTC NRF_RTC0
+#endif
+
+static uint8_t _refcount;
+
+void cntr_init(void)
+{
+	NRF_RTC->PRESCALER = 0;
+	nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE0_Msk);
+	nrf_rtc_int_enable(NRF_RTC, RTC_INTENSET_COMPARE0_Msk);
+}
+
+uint32_t cntr_start(void)
+{
+	if (_refcount++) {
+		return 1;
+	}
+
+	nrf_rtc_task_trigger(NRF_RTC, NRF_RTC_TASK_START);
+
+	return 0;
+}
+
+uint32_t cntr_stop(void)
+{
+	LL_ASSERT(_refcount);
+
+	if (--_refcount) {
+		return 1;
+	}
+
+	nrf_rtc_task_trigger(NRF_RTC, NRF_RTC_TASK_STOP);
+
+	return 0;
+}
+
+uint32_t cntr_cnt_get(void)
+{
+	return nrf_rtc_counter_get(NRF_RTC);
+}
+
+void cntr_cmp_set(uint8_t cmp, uint32_t value)
+{
+	nrf_rtc_cc_set(NRF_RTC, cmp, value);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cpu.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cpu.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cpu.h	(working copy)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016-2020 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+static inline void cpu_sleep(void)
+{
+#if defined(CONFIG_CPU_CORTEX_M0) || \
+	defined(CONFIG_CPU_CORTEX_M4) || \
+	defined(CONFIG_CPU_CORTEX_M33)
+	__WFE();
+	__SEV();
+	__WFE();
+#endif
+}
+
+static inline void cpu_dsb(void)
+{
+#if defined(CONFIG_CPU_CORTEX_M0) || defined(CONFIG_ARCH_POSIX)
+	/* No need of data synchronization barrier */
+#elif defined(CONFIG_CPU_CORTEX_M4) || defined(CONFIG_CPU_CORTEX_M33)
+	__DSB();
+#else
+#error "Unsupported CPU."
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/debug.h	(working copy)
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2016-2020 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_CTLR_DEBUG_PINS) || \
+	defined(CONFIG_BT_CTLR_DEBUG_PINS_CPUAPP)
+#if defined(CONFIG_BOARD_NRF5340PDK_NRF5340_CPUAPP) || \
+	defined(CONFIG_BOARD_NRF5340PDK_NRF5340_CPUNET) || \
+	defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) || \
+	defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET)
+#define DEBUG_PORT       NRF_P1
+#define DEBUG_PIN_IDX0   0
+#define DEBUG_PIN_IDX1   1
+#define DEBUG_PIN_IDX2   4
+#define DEBUG_PIN_IDX3   5
+#define DEBUG_PIN_IDX4   6
+#define DEBUG_PIN_IDX5   7
+#define DEBUG_PIN_IDX6   8
+#define DEBUG_PIN_IDX7   9
+#define DEBUG_PIN_IDX8   10
+#define DEBUG_PIN_IDX9   11
+#define DEBUG_PIN0       BIT(DEBUG_PIN_IDX0)
+#define DEBUG_PIN1       BIT(DEBUG_PIN_IDX1)
+#define DEBUG_PIN2       BIT(DEBUG_PIN_IDX2)
+#define DEBUG_PIN3       BIT(DEBUG_PIN_IDX3)
+#define DEBUG_PIN4       BIT(DEBUG_PIN_IDX4)
+#define DEBUG_PIN5       BIT(DEBUG_PIN_IDX5)
+#define DEBUG_PIN6       BIT(DEBUG_PIN_IDX6)
+#define DEBUG_PIN7       BIT(DEBUG_PIN_IDX7)
+#define DEBUG_PIN8       BIT(DEBUG_PIN_IDX8)
+#define DEBUG_PIN9       BIT(DEBUG_PIN_IDX9)
+#if defined(CONFIG_BOARD_NRF5340PDK_NRF5340_CPUAPP) || \
+	defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP)
+#define DEBUG_SETUP() \
+	do { \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX0] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX1] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX2] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX3] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX4] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX5] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX6] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX7] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX8] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+		DEBUG_PORT->PIN_CNF[DEBUG_PIN_IDX9] = \
+			(GPIO_PIN_CNF_MCUSEL_NetworkMCU << \
+			 GPIO_PIN_CNF_MCUSEL_Pos); \
+	} while (0)
+#endif /* CONFIG_BOARD_NRF5340PDK_NRF5340_CPUAPP */
+#elif defined(CONFIG_BOARD_NRF52840DK_NRF52840)
+#define DEBUG_PORT       NRF_P1
+#define DEBUG_PIN0       BIT(1)
+#define DEBUG_PIN1       BIT(2)
+#define DEBUG_PIN2       BIT(3)
+#define DEBUG_PIN3       BIT(4)
+#define DEBUG_PIN4       BIT(5)
+#define DEBUG_PIN5       BIT(6)
+#define DEBUG_PIN6       BIT(7)
+#define DEBUG_PIN7       BIT(8)
+#define DEBUG_PIN8       BIT(10)
+#define DEBUG_PIN9       BIT(11)
+#elif defined(CONFIG_BOARD_NRF52DK_NRF52832) || \
+	defined(CONFIG_BOARD_NRF52DK_NRF52810)
+#define DEBUG_PORT       NRF_GPIO
+#define DEBUG_PIN0       BIT(11)
+#define DEBUG_PIN1       BIT(12)
+#define DEBUG_PIN2       BIT(13)
+#define DEBUG_PIN3       BIT(14)
+#define DEBUG_PIN4       BIT(15)
+#define DEBUG_PIN5       BIT(16)
+#define DEBUG_PIN6       BIT(17)
+#define DEBUG_PIN7       BIT(18)
+#define DEBUG_PIN8       BIT(19)
+#define DEBUG_PIN9       BIT(20)
+#elif defined(CONFIG_BOARD_NRF51DK_NRF51422)
+#define DEBUG_PORT       NRF_GPIO
+#define DEBUG_PIN0       BIT(12)
+#define DEBUG_PIN1       BIT(13)
+#define DEBUG_PIN2       BIT(14)
+#define DEBUG_PIN3       BIT(15)
+#define DEBUG_PIN4       BIT(16)
+#define DEBUG_PIN5       BIT(17)
+#define DEBUG_PIN6       BIT(18)
+#define DEBUG_PIN7       BIT(19)
+#define DEBUG_PIN8       BIT(20)
+#define DEBUG_PIN9       BIT(23)
+#else
+#error BT_CTLR_DEBUG_PINS not supported on this board.
+#endif
+
+#define DEBUG_PIN_MASK   (DEBUG_PIN0 | DEBUG_PIN1 | DEBUG_PIN2 | DEBUG_PIN3 | \
+			  DEBUG_PIN4 | DEBUG_PIN5 | DEBUG_PIN6 | DEBUG_PIN7 | \
+			  DEBUG_PIN8 | DEBUG_PIN9)
+#define DEBUG_CLOSE_MASK (DEBUG_PIN3 | DEBUG_PIN4 | DEBUG_PIN5 | DEBUG_PIN6)
+
+/* below are some interesting macros referenced by controller
+ * which can be defined to SoC's GPIO toggle to observe/debug the
+ * controller's runtime behavior.
+ */
+#define DEBUG_INIT() \
+	do { \
+		DEBUG_PORT->DIRSET = DEBUG_PIN_MASK; \
+		DEBUG_PORT->OUTCLR = DEBUG_PIN_MASK; \
+	} while (0)
+
+#define DEBUG_CPU_SLEEP(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN0; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN0; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN0; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN0; \
+		} \
+	} while (0)
+
+#define DEBUG_TICKER_ISR(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN1; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN1; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN1; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN1; \
+		} \
+	} while (0)
+
+#define DEBUG_TICKER_TASK(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN1; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN1; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN1; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN1; \
+		} \
+	} while (0)
+
+#define DEBUG_TICKER_JOB(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN2; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN2; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN2; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN2; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_ISR(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN7; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN7; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN7; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN7; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_XTAL(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN8; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN8; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN8; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN8; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_ACTIVE(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN9; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN9; \
+		} else { \
+			DEBUG_PORT->OUTSET = DEBUG_PIN9; \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN9; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_CLOSE(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = 0x00000000; \
+			DEBUG_PORT->OUTSET = 0x00000000; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_CLOSE_MASK; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_PREPARE_A(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN3; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN3; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN3; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN3; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_START_A(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN3; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN3; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN3; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN3; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_CLOSE_A(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = 0x00000000; \
+			DEBUG_PORT->OUTSET = 0x00000000; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN3; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_PREPARE_S(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN4; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN4; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN4; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN4; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_START_S(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN4; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN4; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN4; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN4; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_CLOSE_S(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = 0x00000000; \
+			DEBUG_PORT->OUTSET = 0x00000000; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN4; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_PREPARE_O(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN5; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN5; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN5; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN5; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_START_O(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN5; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN5; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN5; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN5; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_CLOSE_O(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = 0x00000000; \
+			DEBUG_PORT->OUTSET = 0x00000000; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN5; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_PREPARE_M(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN6; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN6; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN6; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN6; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_START_M(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN6; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN6; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN6; \
+			DEBUG_PORT->OUTSET = DEBUG_PIN6; \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_CLOSE_M(flag) \
+	do { \
+		if (flag) { \
+			DEBUG_PORT->OUTCLR = 0x00000000; \
+			DEBUG_PORT->OUTSET = 0x00000000; \
+		} else { \
+			DEBUG_PORT->OUTCLR = DEBUG_PIN6; \
+		} \
+	} while (0)
+
+#else
+#define DEBUG_INIT()
+#define DEBUG_CPU_SLEEP(flag)
+#define DEBUG_TICKER_ISR(flag)
+#define DEBUG_TICKER_TASK(flag)
+#define DEBUG_TICKER_JOB(flag)
+#define DEBUG_RADIO_ISR(flag)
+#define DEBUG_RADIO_HCTO(flag)
+#define DEBUG_RADIO_XTAL(flag)
+#define DEBUG_RADIO_ACTIVE(flag)
+#define DEBUG_RADIO_CLOSE(flag)
+#define DEBUG_RADIO_PREPARE_A(flag)
+#define DEBUG_RADIO_START_A(flag)
+#define DEBUG_RADIO_CLOSE_A(flag)
+#define DEBUG_RADIO_PREPARE_S(flag)
+#define DEBUG_RADIO_START_S(flag)
+#define DEBUG_RADIO_CLOSE_S(flag)
+#define DEBUG_RADIO_PREPARE_O(flag)
+#define DEBUG_RADIO_START_O(flag)
+#define DEBUG_RADIO_CLOSE_O(flag)
+#define DEBUG_RADIO_PREPARE_M(flag)
+#define DEBUG_RADIO_START_M(flag)
+#define DEBUG_RADIO_CLOSE_M(flag)
+#endif /* CONFIG_BT_CTLR_DEBUG_PINS */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ecb.c	(working copy)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+
+#include <nrfx/hal/nrf_ecb.h>
+
+#include "util/mem.h"
+#include "hal/ecb.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hal_ecb
+#include "common/log.h"
+#include "hal/debug.h"
+
+struct ecb_param {
+	uint8_t key[16];
+	uint8_t clear_text[16];
+	uint8_t cipher_text[16];
+} __packed;
+
+static void do_ecb(struct ecb_param *ecb)
+{
+	do {
+		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
+		NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+		NRF_ECB->EVENTS_ENDECB = 0;
+		NRF_ECB->EVENTS_ERRORECB = 0;
+		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
+		while ((NRF_ECB->EVENTS_ENDECB == 0) &&
+		       (NRF_ECB->EVENTS_ERRORECB == 0) &&
+		       (NRF_ECB->ECBDATAPTR != 0)) {
+#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
+			k_busy_wait(10);
+#else
+			/*__WFE();*/
+#endif
+		}
+		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
+	} while ((NRF_ECB->EVENTS_ERRORECB != 0) || (NRF_ECB->ECBDATAPTR == 0));
+
+	NRF_ECB->ECBDATAPTR = 0;
+}
+
+void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
+		    uint8_t * const cipher_text_be)
+{
+	struct ecb_param ecb;
+
+	memcpy(&ecb.key[0], key_be, sizeof(ecb.key));
+	memcpy(&ecb.clear_text[0], clear_text_be, sizeof(ecb.clear_text));
+
+	do_ecb(&ecb);
+
+	memcpy(cipher_text_be, &ecb.cipher_text[0], sizeof(ecb.cipher_text));
+}
+
+void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
+		 uint8_t * const cipher_text_le, uint8_t * const cipher_text_be)
+{
+	struct ecb_param ecb;
+
+	mem_rcopy(&ecb.key[0], key_le, sizeof(ecb.key));
+	mem_rcopy(&ecb.clear_text[0], clear_text_le, sizeof(ecb.clear_text));
+
+	do_ecb(&ecb);
+
+	if (cipher_text_le) {
+		mem_rcopy(cipher_text_le, &ecb.cipher_text[0],
+			  sizeof(ecb.cipher_text));
+	}
+
+	if (cipher_text_be) {
+		memcpy(cipher_text_be, &ecb.cipher_text[0],
+			 sizeof(ecb.cipher_text));
+	}
+}
+
+uint32_t ecb_encrypt_nonblocking(struct ecb *ecb)
+{
+	/* prepare to be used in a BE AES h/w */
+	if (ecb->in_key_le) {
+		mem_rcopy(&ecb->in_key_be[0], ecb->in_key_le,
+			  sizeof(ecb->in_key_be));
+	}
+	if (ecb->in_clear_text_le) {
+		mem_rcopy(&ecb->in_clear_text_be[0],
+			  ecb->in_clear_text_le,
+			  sizeof(ecb->in_clear_text_be));
+	}
+
+	/* setup the encryption h/w */
+	NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
+	NRF_ECB->EVENTS_ENDECB = 0;
+	NRF_ECB->EVENTS_ERRORECB = 0;
+	nrf_ecb_int_enable(NRF_ECB, ECB_INTENSET_ERRORECB_Msk
+				    | ECB_INTENSET_ENDECB_Msk);
+
+	/* enable interrupt */
+	NVIC_ClearPendingIRQ(ECB_IRQn);
+	irq_enable(ECB_IRQn);
+
+	/* start the encryption h/w */
+	nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
+
+	return 0;
+}
+
+static void ecb_cleanup(void)
+{
+	/* stop h/w */
+	NRF_ECB->TASKS_STOPECB = 1;
+	nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
+
+	/* cleanup interrupt */
+	irq_disable(ECB_IRQn);
+}
+
+void isr_ecb(void *param)
+{
+	ARG_UNUSED(param);
+
+	if (NRF_ECB->EVENTS_ERRORECB) {
+		struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
+
+		ecb_cleanup();
+
+		ecb->fp_ecb(1, NULL, ecb->context);
+	}
+
+	else if (NRF_ECB->EVENTS_ENDECB) {
+		struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
+
+		ecb_cleanup();
+
+		ecb->fp_ecb(0, &ecb->out_cipher_text_be[0],
+			      ecb->context);
+	}
+
+	else {
+		LL_ASSERT(0);
+	}
+}
+
+struct ecb_ut_context {
+	uint32_t volatile done;
+	uint32_t status;
+	uint8_t  cipher_text[16];
+};
+
+static void ecb_cb(uint32_t status, uint8_t *cipher_be, void *context)
+{
+	struct ecb_ut_context *ecb_ut_context =
+		(struct ecb_ut_context *)context;
+
+	ecb_ut_context->done = 1U;
+	ecb_ut_context->status = status;
+	if (!status) {
+		mem_rcopy(ecb_ut_context->cipher_text, cipher_be,
+			  sizeof(ecb_ut_context->cipher_text));
+	}
+}
+
+uint32_t ecb_ut(void)
+{
+	uint8_t key[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+	uint8_t clear_text[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+				0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44,
+				0x55 };
+	uint8_t cipher_text[16];
+	uint32_t status = 0U;
+	struct ecb ecb;
+	struct ecb_ut_context context;
+
+	ecb_encrypt(key, clear_text, cipher_text, NULL);
+
+	context.done = 0U;
+	ecb.in_key_le = key;
+	ecb.in_clear_text_le = clear_text;
+	ecb.fp_ecb = ecb_cb;
+	ecb.context = &context;
+	status = ecb_encrypt_nonblocking(&ecb);
+	do {
+		__WFE();
+		__SEV();
+		__WFE();
+	} while (!context.done);
+
+	if (context.status != 0U) {
+		return context.status;
+	}
+
+	status = memcmp(cipher_text, context.cipher_text, sizeof(cipher_text));
+	if (status) {
+		return status;
+	}
+
+	return status;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/mayfly.c	(working copy)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <soc.h>
+
+#include "hal/nrf5/swi.h"
+
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ll_sw/lll.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hal_mayfly
+#include "common/log.h"
+#include "hal/debug.h"
+
+#define MAYFLY_CALL_ID_LLL    TICKER_USER_ID_LLL
+#define MAYFLY_CALL_ID_WORKER TICKER_USER_ID_ULL_HIGH
+#define MAYFLY_CALL_ID_JOB    TICKER_USER_ID_ULL_LOW
+
+void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
+{
+	(void)caller_id;
+
+	LL_ASSERT(callee_id == MAYFLY_CALL_ID_JOB);
+
+	if (enable) {
+		irq_enable(HAL_SWI_JOB_IRQ);
+	} else {
+		irq_disable(HAL_SWI_JOB_IRQ);
+	}
+}
+
+uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id)
+{
+	(void)caller_id;
+
+	switch (callee_id) {
+	case MAYFLY_CALL_ID_LLL:
+		return irq_is_enabled(HAL_SWI_RADIO_IRQ);
+
+	case MAYFLY_CALL_ID_WORKER:
+		return irq_is_enabled(HAL_SWI_WORKER_IRQ);
+
+	case MAYFLY_CALL_ID_JOB:
+		return irq_is_enabled(HAL_SWI_JOB_IRQ);
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	return 0;
+}
+
+uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id)
+{
+	return (caller_id == callee_id) ||
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_LLL) &&
+		(callee_id == MAYFLY_CALL_ID_WORKER)) ||
+	       ((caller_id == MAYFLY_CALL_ID_WORKER) &&
+		(callee_id == MAYFLY_CALL_ID_LLL)) ||
+#endif
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_LLL) &&
+		(callee_id == MAYFLY_CALL_ID_JOB)) ||
+	       ((caller_id == MAYFLY_CALL_ID_JOB) &&
+		(callee_id == MAYFLY_CALL_ID_LLL)) ||
+#endif
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_WORKER) &&
+		(callee_id == MAYFLY_CALL_ID_JOB)) ||
+	       ((caller_id == MAYFLY_CALL_ID_JOB) &&
+		(callee_id == MAYFLY_CALL_ID_WORKER)) ||
+#endif
+	       0;
+}
+
+void mayfly_pend(uint8_t caller_id, uint8_t callee_id)
+{
+	(void)caller_id;
+
+	switch (callee_id) {
+	case MAYFLY_CALL_ID_LLL:
+		hal_swi_lll_pend();
+		break;
+
+	case MAYFLY_CALL_ID_WORKER:
+		hal_swi_worker_pend();
+		break;
+
+	case MAYFLY_CALL_ID_JOB:
+		hal_swi_job_pend();
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h	(working copy)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+typedef void (*radio_isr_cb_t) (void *param);
+
+void isr_radio(void);
+void radio_isr_set(radio_isr_cb_t cb, void *param);
+
+void radio_setup(void);
+void radio_reset(void);
+void radio_phy_set(uint8_t phy, uint8_t flags);
+void radio_tx_power_set(int8_t power);
+void radio_tx_power_max_set(void);
+int8_t radio_tx_power_min_get(void);
+int8_t radio_tx_power_max_get(void);
+int8_t radio_tx_power_floor(int8_t power);
+void radio_freq_chan_set(uint32_t chan);
+void radio_whiten_iv_set(uint32_t iv);
+void radio_aa_set(uint8_t *aa);
+void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags);
+void radio_pkt_rx_set(void *rx_packet);
+void radio_pkt_tx_set(void *tx_packet);
+uint32_t radio_tx_ready_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_tx_chain_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_rx_ready_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags);
+void radio_rx_enable(void);
+void radio_tx_enable(void);
+void radio_disable(void);
+
+void radio_status_reset(void);
+uint32_t radio_is_ready(void);
+uint32_t radio_is_done(void);
+uint32_t radio_has_disabled(void);
+uint32_t radio_is_idle(void);
+
+void radio_crc_configure(uint32_t polynomial, uint32_t iv);
+uint32_t radio_crc_is_valid(void);
+
+void *radio_pkt_empty_get(void);
+void *radio_pkt_scratch_get(void);
+void *radio_pkt_decrypt_get(void);
+
+void radio_switch_complete_and_rx(uint8_t phy_rx);
+void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, uint8_t phy_tx,
+				  uint8_t flags_tx);
+void radio_switch_complete_and_disable(void);
+
+void radio_rssi_measure(void);
+uint32_t radio_rssi_get(void);
+void radio_rssi_status_reset(void);
+uint32_t radio_rssi_is_ready(void);
+
+void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type,
+			    uint8_t *bdaddr);
+void radio_filter_disable(void);
+void radio_filter_status_reset(void);
+uint32_t radio_filter_has_match(void);
+uint32_t radio_filter_match_get(void);
+
+void radio_bc_configure(uint32_t n);
+void radio_bc_status_reset(void);
+uint32_t radio_bc_has_match(void);
+
+void radio_tmr_status_reset(void);
+void radio_tmr_tifs_set(uint32_t tifs);
+uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder);
+uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick);
+void radio_tmr_start_us(uint8_t trx, uint32_t us);
+uint32_t radio_tmr_start_now(uint8_t trx);
+uint32_t radio_tmr_start_get(void);
+void radio_tmr_stop(void);
+void radio_tmr_hcto_configure(uint32_t hcto);
+void radio_tmr_aa_capture(void);
+uint32_t radio_tmr_aa_get(void);
+void radio_tmr_aa_save(uint32_t aa);
+uint32_t radio_tmr_aa_restore(void);
+uint32_t radio_tmr_ready_get(void);
+void radio_tmr_end_capture(void);
+uint32_t radio_tmr_end_get(void);
+uint32_t radio_tmr_tifs_base_get(void);
+void radio_tmr_sample(void);
+uint32_t radio_tmr_sample_get(void);
+
+void radio_gpio_pa_setup(void);
+void radio_gpio_lna_setup(void);
+void radio_gpio_lna_on(void);
+void radio_gpio_lna_off(void);
+void radio_gpio_pa_lna_enable(uint32_t trx_us);
+void radio_gpio_pa_lna_disable(void);
+
+void *radio_ccm_rx_pkt_set(struct ccm *ccm, uint8_t phy, void *pkt);
+void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt);
+uint32_t radio_ccm_is_done(void);
+uint32_t radio_ccm_mic_is_valid(void);
+
+void radio_ar_configure(uint32_t nirk, void *irk);
+uint32_t radio_ar_match_get(void);
+void radio_ar_status_reset(void);
+uint32_t radio_ar_has_match(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c	(working copy)
@@ -0,0 +1,1211 @@
+/*
+ * Copyright (c) 2016 - 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+#include <toolchain.h>
+
+#include <nrfx/hal/nrf_radio.h>
+#include <nrfx/hal/nrf_rtc.h>
+#include <nrfx/hal/nrf_timer.h>
+#include <nrfx/hal/nrf_ccm.h>
+
+#include "util/mem.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+#include "ll_sw/pdu.h"
+#include "radio_nrf5.h"
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+#if ((CONFIG_BT_CTLR_GPIO_PA_PIN) > 31)
+#define NRF_GPIO_PA     NRF_P1
+#define NRF_GPIO_PA_PIN ((CONFIG_BT_CTLR_GPIO_PA_PIN) - 32)
+#else
+#define NRF_GPIO_PA     NRF_GPIO
+#define NRF_GPIO_PA_PIN CONFIG_BT_CTLR_GPIO_PA_PIN
+#endif
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+#if ((CONFIG_BT_CTLR_GPIO_LNA_PIN) > 31)
+#define NRF_GPIO_LNA     NRF_P1
+#define NRF_GPIO_LNA_PIN ((CONFIG_BT_CTLR_GPIO_LNA_PIN) - 32)
+#else
+#define NRF_GPIO_LNA     NRF_GPIO
+#define NRF_GPIO_LNA_PIN CONFIG_BT_CTLR_GPIO_LNA_PIN
+#endif
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+/* The following two constants are used in nrfx_glue.h for marking these PPI
+ * channels and groups as occupied and thus unavailable to other modules.
+ */
+const uint32_t z_bt_ctlr_used_nrf_ppi_channels = HAL_USED_PPI_CHANNELS;
+const uint32_t z_bt_ctlr_used_nrf_ppi_groups   = HAL_USED_PPI_GROUPS;
+
+static radio_isr_cb_t isr_cb;
+static void           *isr_cb_param;
+
+void isr_radio(void)
+{
+	if (radio_has_disabled()) {
+		isr_cb(isr_cb_param);
+	}
+}
+
+void radio_isr_set(radio_isr_cb_t cb, void *param)
+{
+	irq_disable(RADIO_IRQn);
+
+	isr_cb_param = param;
+	isr_cb = cb;
+
+	nrf_radio_int_enable(NRF_RADIO,
+			     0 |
+				/* RADIO_INTENSET_READY_Msk |
+				 * RADIO_INTENSET_ADDRESS_Msk |
+				 * RADIO_INTENSET_PAYLOAD_Msk |
+				 * RADIO_INTENSET_END_Msk |
+				 */
+				RADIO_INTENSET_DISABLED_Msk
+				/* | RADIO_INTENSET_RSSIEND_Msk |
+				 */
+	    );
+
+	NVIC_ClearPendingIRQ(RADIO_IRQn);
+	irq_enable(RADIO_IRQn);
+}
+
+void radio_setup(void)
+{
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	NRF_GPIO_PA->DIRSET = BIT(NRF_GPIO_PA_PIN);
+#if defined(CONFIG_BT_CTLR_GPIO_PA_POL_INV)
+	NRF_GPIO_PA->OUTSET = BIT(NRF_GPIO_PA_PIN);
+#else
+	NRF_GPIO_PA->OUTCLR = BIT(NRF_GPIO_PA_PIN);
+#endif
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	NRF_GPIO_LNA->DIRSET = BIT(NRF_GPIO_LNA_PIN);
+
+	radio_gpio_lna_off();
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	hal_radio_ram_prio_setup();
+}
+
+void radio_reset(void)
+{
+	irq_disable(RADIO_IRQn);
+
+	nrf_radio_power_set(
+		NRF_RADIO,
+		(RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos) &
+			RADIO_POWER_POWER_Msk);
+	nrf_radio_power_set(
+		NRF_RADIO,
+		(RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos) &
+			RADIO_POWER_POWER_Msk);
+
+	hal_radio_reset();
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+	hal_radio_sw_switch_ppi_group_setup();
+#endif
+}
+
+void radio_phy_set(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	mode = hal_radio_phy_mode_get(phy, flags);
+
+	NRF_RADIO->MODE = (mode << RADIO_MODE_MODE_Pos) & RADIO_MODE_MODE_Msk;
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+	NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast <<
+				RADIO_MODECNF0_RU_Pos) &
+			       RADIO_MODECNF0_RU_Msk;
+#endif /* CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+}
+
+void radio_tx_power_set(int8_t power)
+{
+	/* NOTE: valid value range is passed by Kconfig define. */
+	NRF_RADIO->TXPOWER = (uint32_t)power;
+}
+
+void radio_tx_power_max_set(void)
+{
+	NRF_RADIO->TXPOWER = hal_radio_tx_power_max_get();
+}
+
+int8_t radio_tx_power_min_get(void)
+{
+	return (int8_t)hal_radio_tx_power_min_get();
+}
+
+int8_t radio_tx_power_max_get(void)
+{
+	return (int8_t)hal_radio_tx_power_max_get();
+}
+
+int8_t radio_tx_power_floor(int8_t power)
+{
+	return (int8_t)hal_radio_tx_power_floor(power);
+}
+
+void radio_freq_chan_set(uint32_t chan)
+{
+	NRF_RADIO->FREQUENCY = chan;
+}
+
+void radio_whiten_iv_set(uint32_t iv)
+{
+	NRF_RADIO->DATAWHITEIV = iv;
+
+	NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk;
+	NRF_RADIO->PCNF1 |= ((1UL) << RADIO_PCNF1_WHITEEN_Pos) &
+			    RADIO_PCNF1_WHITEEN_Msk;
+}
+
+void radio_aa_set(uint8_t *aa)
+{
+	NRF_RADIO->TXADDRESS =
+	    (((0UL) << RADIO_TXADDRESS_TXADDRESS_Pos) &
+	     RADIO_TXADDRESS_TXADDRESS_Msk);
+	NRF_RADIO->RXADDRESSES =
+	    ((RADIO_RXADDRESSES_ADDR0_Enabled) << RADIO_RXADDRESSES_ADDR0_Pos);
+	NRF_RADIO->PREFIX0 = aa[3];
+	NRF_RADIO->BASE0 = (aa[2] << 24) | (aa[1] << 16) | (aa[0] << 8);
+}
+
+void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags)
+{
+	uint8_t dc = flags & 0x01; /* Adv or Data channel */
+	uint32_t extra;
+	uint8_t phy;
+
+#if defined(CONFIG_SOC_SERIES_NRF51X)
+	ARG_UNUSED(phy);
+
+	extra = 0U;
+
+	/* nRF51 supports only 27 byte PDU when using h/w CCM for encryption. */
+	if (!IS_ENABLED(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR) && dc) {
+		bits_len = 5U;
+	}
+#elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \
+	defined(CONFIG_SOC_SERIES_NRF53X)
+	extra = 0U;
+
+	phy = (flags >> 1) & 0x07; /* phy */
+	switch (phy) {
+	case BIT(0):
+	default:
+		extra |= (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) &
+			 RADIO_PCNF0_PLEN_Msk;
+		break;
+
+	case BIT(1):
+		extra |= (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) &
+			 RADIO_PCNF0_PLEN_Msk;
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+	case BIT(2):
+		extra |= (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) &
+			 RADIO_PCNF0_PLEN_Msk;
+		extra |= (2UL << RADIO_PCNF0_CILEN_Pos) & RADIO_PCNF0_CILEN_Msk;
+		extra |= (3UL << RADIO_PCNF0_TERMLEN_Pos) &
+			 RADIO_PCNF0_TERMLEN_Msk;
+		break;
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	/* To use same Data Channel PDU structure with nRF5 specific overhead
+	 * byte, include the S1 field in radio packet configuration.
+	 */
+	if (dc) {
+		extra |= (RADIO_PCNF0_S1INCL_Include <<
+			  RADIO_PCNF0_S1INCL_Pos) & RADIO_PCNF0_S1INCL_Msk;
+	}
+#endif /* CONFIG_SOC_COMPATIBLE_NRF52X */
+
+	NRF_RADIO->PCNF0 = (((1UL) << RADIO_PCNF0_S0LEN_Pos) &
+			    RADIO_PCNF0_S0LEN_Msk) |
+			   ((((uint32_t)bits_len) << RADIO_PCNF0_LFLEN_Pos) &
+			    RADIO_PCNF0_LFLEN_Msk) |
+			   ((((uint32_t)8-bits_len) << RADIO_PCNF0_S1LEN_Pos) &
+			    RADIO_PCNF0_S1LEN_Msk) |
+			   extra;
+
+	NRF_RADIO->PCNF1 &= ~(RADIO_PCNF1_MAXLEN_Msk | RADIO_PCNF1_STATLEN_Msk |
+			      RADIO_PCNF1_BALEN_Msk | RADIO_PCNF1_ENDIAN_Msk);
+	NRF_RADIO->PCNF1 |= ((((uint32_t)max_len) << RADIO_PCNF1_MAXLEN_Pos) &
+			     RADIO_PCNF1_MAXLEN_Msk) |
+			    (((0UL) << RADIO_PCNF1_STATLEN_Pos) &
+			     RADIO_PCNF1_STATLEN_Msk) |
+			    (((3UL) << RADIO_PCNF1_BALEN_Pos) &
+			     RADIO_PCNF1_BALEN_Msk) |
+			    (((RADIO_PCNF1_ENDIAN_Little) <<
+			      RADIO_PCNF1_ENDIAN_Pos) &
+			     RADIO_PCNF1_ENDIAN_Msk);
+}
+
+void radio_pkt_rx_set(void *rx_packet)
+{
+	NRF_RADIO->PACKETPTR = (uint32_t)rx_packet;
+}
+
+void radio_pkt_tx_set(void *tx_packet)
+{
+	NRF_RADIO->PACKETPTR = (uint32_t)tx_packet;
+}
+
+uint32_t radio_tx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return hal_radio_tx_ready_delay_us_get(phy, flags);
+}
+
+uint32_t radio_tx_chain_delay_get(uint8_t phy, uint8_t flags)
+{
+	return hal_radio_tx_chain_delay_us_get(phy, flags);
+}
+
+uint32_t radio_rx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return hal_radio_rx_ready_delay_us_get(phy, flags);
+}
+
+uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags)
+{
+	return hal_radio_rx_chain_delay_us_get(phy, flags);
+}
+
+void radio_rx_enable(void)
+{
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_SOC_SERIES_NRF53X)
+	/* NOTE: Timer clear DPPI configuration is needed only for nRF53
+	 *       because of calls to radio_disable() and
+	 *       radio_switch_complete_and_disable() inside a radio event call
+	 *       hal_radio_sw_switch_disable(), which in the case of nRF53
+	 *       cancels the task subscription.
+	 */
+	/* FIXME: hal_sw_switch_timer_clear_ppi_config() sets both task and
+	 *        event. Consider a new interface to only set the task, or
+	 *        change the design to not clear task subscription inside a
+	 *        radio event but when the radio event is done.
+	 */
+	hal_sw_switch_timer_clear_ppi_config();
+#endif /* CONFIG_SOC_SERIES_NRF53X */
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN);
+}
+
+void radio_tx_enable(void)
+{
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_SOC_SERIES_NRF53X)
+	/* NOTE: Timer clear DPPI configuration is needed only for nRF53
+	 *       because of calls to radio_disable() and
+	 *       radio_switch_complete_and_disable() inside a radio event call
+	 *       hal_radio_sw_switch_disable(), which in the case of nRF53
+	 *       cancels the task subscription.
+	 */
+	/* FIXME: hal_sw_switch_timer_clear_ppi_config() sets both task and
+	 *        event. Consider a new interface to only set the task, or
+	 *        change the design to not clear task subscription inside a
+	 *        radio event but when the radio event is done.
+	 */
+	hal_sw_switch_timer_clear_ppi_config();
+#endif /* CONFIG_SOC_SERIES_NRF53X */
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN);
+}
+
+void radio_disable(void)
+{
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+	hal_radio_sw_switch_cleanup();
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	NRF_RADIO->SHORTS = 0;
+	nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
+}
+
+void radio_status_reset(void)
+{
+	/* NOTE: Only EVENTS_* registers read (checked) by software needs reset
+	 *       between Radio IRQs. In PPI use, irrespective of stored EVENT_*
+	 *       register value, PPI task will be triggered. Hence, other
+	 *       EVENT_* registers are not reset to save code and CPU time.
+	 */
+	NRF_RADIO->EVENTS_READY = 0;
+	NRF_RADIO->EVENTS_END = 0;
+	NRF_RADIO->EVENTS_DISABLED = 0;
+}
+
+uint32_t radio_is_ready(void)
+{
+	return (NRF_RADIO->EVENTS_READY != 0);
+}
+
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+static uint32_t last_pdu_end_us;
+
+uint32_t radio_is_done(void)
+{
+	if (NRF_RADIO->EVENTS_END != 0) {
+		/* On packet END event increment last packet end time value.
+		 * Note: this depends on the function being called exactly once
+		 * in the ISR function.
+		 */
+		last_pdu_end_us += EVENT_TIMER->CC[2];
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+uint32_t radio_is_done(void)
+{
+	return (NRF_RADIO->EVENTS_END != 0);
+}
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+uint32_t radio_has_disabled(void)
+{
+	return (NRF_RADIO->EVENTS_DISABLED != 0);
+}
+
+uint32_t radio_is_idle(void)
+{
+	return (NRF_RADIO->STATE == 0);
+}
+
+void radio_crc_configure(uint32_t polynomial, uint32_t iv)
+{
+	NRF_RADIO->CRCCNF =
+	    (((RADIO_CRCCNF_SKIPADDR_Skip) << RADIO_CRCCNF_SKIPADDR_Pos) &
+	     RADIO_CRCCNF_SKIPADDR_Msk) |
+	    (((RADIO_CRCCNF_LEN_Three) << RADIO_CRCCNF_LEN_Pos) &
+	       RADIO_CRCCNF_LEN_Msk);
+	NRF_RADIO->CRCPOLY = polynomial;
+	NRF_RADIO->CRCINIT = iv;
+}
+
+uint32_t radio_crc_is_valid(void)
+{
+	return (NRF_RADIO->CRCSTATUS != 0);
+}
+
+static uint8_t MALIGN(4) _pkt_empty[PDU_EM_LL_SIZE_MAX];
+static uint8_t MALIGN(4) _pkt_scratch[MAX((HAL_RADIO_PDU_LEN_MAX + 3),
+				       PDU_AC_LL_SIZE_MAX)];
+
+void *radio_pkt_empty_get(void)
+{
+	return _pkt_empty;
+}
+
+void *radio_pkt_scratch_get(void)
+{
+	return _pkt_scratch;
+}
+
+#if defined(CONFIG_SOC_COMPATIBLE_NRF52832) && \
+	defined(CONFIG_BT_CTLR_LE_ENC) && \
+	(!defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX) || \
+	 (CONFIG_BT_CTLR_DATA_LENGTH_MAX < (HAL_RADIO_PDU_LEN_MAX - 4)))
+static uint8_t MALIGN(4) _pkt_decrypt[MAX((HAL_RADIO_PDU_LEN_MAX + 3),
+				       PDU_AC_LL_SIZE_MAX)];
+
+void *radio_pkt_decrypt_get(void)
+{
+	return _pkt_decrypt;
+}
+#endif
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+static uint8_t sw_tifs_toggle;
+
+static void sw_switch(uint8_t dir, uint8_t phy_curr, uint8_t flags_curr, uint8_t phy_next,
+		      uint8_t flags_next)
+{
+	uint8_t ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(sw_tifs_toggle);
+	uint8_t cc = SW_SWITCH_TIMER_EVTS_COMP(sw_tifs_toggle);
+	uint32_t delay;
+
+	hal_radio_sw_switch_setup(cc, ppi, sw_tifs_toggle);
+
+	if (dir) {
+		/* TX */
+
+		/* Calculate delay with respect to current (RX) and next
+		 * (TX) PHY. If RX PHY is LE Coded, assume S8 coding scheme.
+		 */
+		delay = HAL_RADIO_NS2US_ROUND(
+		    hal_radio_tx_ready_delay_ns_get(phy_next, flags_next) +
+		    hal_radio_rx_chain_delay_ns_get(phy_curr, 1));
+
+		hal_radio_txen_on_sw_switch(ppi);
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+		uint8_t ppi_en =
+		    HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(sw_tifs_toggle);
+		uint8_t ppi_dis =
+			HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(
+			    sw_tifs_toggle);
+
+		if (phy_curr & BIT(2)) {
+			/* Switching to TX after RX on LE Coded PHY. */
+
+			uint8_t cc_s2 =
+			    SW_SWITCH_TIMER_S2_EVTS_COMP(sw_tifs_toggle);
+
+			uint32_t delay_s2;
+
+			/* Calculate assuming reception on S2 coding scheme. */
+			delay_s2 = HAL_RADIO_NS2US_ROUND(
+				hal_radio_tx_ready_delay_ns_get(
+					phy_next, flags_next) +
+				hal_radio_rx_chain_delay_ns_get(phy_curr, 0));
+
+			SW_SWITCH_TIMER->CC[cc_s2] =
+				SW_SWITCH_TIMER->CC[cc];
+
+			if (delay_s2 < SW_SWITCH_TIMER->CC[cc_s2]) {
+				SW_SWITCH_TIMER->CC[cc_s2] -= delay_s2;
+			} else {
+				SW_SWITCH_TIMER->CC[cc_s2] = 1;
+			}
+
+			hal_radio_sw_switch_coded_tx_config_set(ppi_en, ppi_dis,
+				cc_s2, sw_tifs_toggle);
+		} else {
+			/* Switching to TX after RX on LE 1M/2M PHY */
+
+			hal_radio_sw_switch_coded_config_clear(ppi_en,
+				ppi_dis, cc, sw_tifs_toggle);
+		}
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	} else {
+		/* RX */
+		delay = HAL_RADIO_NS2US_CEIL(
+			hal_radio_rx_ready_delay_ns_get(phy_next, flags_next) -
+			hal_radio_tx_chain_delay_ns_get(phy_curr, flags_curr));
+
+		hal_radio_rxen_on_sw_switch(ppi);
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+		if (1) {
+			uint8_t ppi_en =
+				HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(
+					sw_tifs_toggle);
+			uint8_t ppi_dis =
+				HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(
+					sw_tifs_toggle);
+
+			hal_radio_sw_switch_coded_config_clear(ppi_en,
+				ppi_dis, cc, sw_tifs_toggle);
+		}
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	if (delay <
+		SW_SWITCH_TIMER->CC[cc]) {
+		nrf_timer_cc_set(SW_SWITCH_TIMER, cc,
+				 SW_SWITCH_TIMER->CC[cc] - delay);
+	} else {
+		nrf_timer_cc_set(SW_SWITCH_TIMER, cc, 1);
+	}
+
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
+				BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI));
+
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	/* Since the event timer is cleared on END, we
+	 * always need to capture the PDU END time-stamp.
+	 */
+	radio_tmr_end_capture();
+#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+	sw_tifs_toggle += 1U;
+	sw_tifs_toggle &= 1;
+}
+#endif /* CONFIG_BT_CTLR_TIFS_HW */
+
+void radio_switch_complete_and_rx(uint8_t phy_rx)
+{
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+	NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk |
+			    RADIO_SHORTS_END_DISABLE_Msk |
+			    RADIO_SHORTS_DISABLED_RXEN_Msk;
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+	NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk |
+			    RADIO_SHORTS_END_DISABLE_Msk;
+	sw_switch(0, 0, 0, phy_rx, 0);
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+}
+
+void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, uint8_t phy_tx,
+				  uint8_t flags_tx)
+{
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+	NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk |
+			    RADIO_SHORTS_END_DISABLE_Msk |
+			    RADIO_SHORTS_DISABLED_TXEN_Msk;
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+	NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk |
+			    RADIO_SHORTS_END_DISABLE_Msk;
+	sw_switch(1, phy_rx, flags_rx, phy_tx, flags_tx);
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+}
+
+void radio_switch_complete_and_disable(void)
+{
+	NRF_RADIO->SHORTS =
+	    (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk);
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+	hal_radio_sw_switch_disable();
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+}
+
+void radio_rssi_measure(void)
+{
+	NRF_RADIO->SHORTS |=
+	    (RADIO_SHORTS_ADDRESS_RSSISTART_Msk |
+	     RADIO_SHORTS_DISABLED_RSSISTOP_Msk);
+}
+
+uint32_t radio_rssi_get(void)
+{
+	return NRF_RADIO->RSSISAMPLE;
+}
+
+void radio_rssi_status_reset(void)
+{
+	NRF_RADIO->EVENTS_RSSIEND = 0;
+}
+
+uint32_t radio_rssi_is_ready(void)
+{
+	return (NRF_RADIO->EVENTS_RSSIEND != 0);
+}
+
+void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type,
+			    uint8_t *bdaddr)
+{
+	uint8_t index;
+
+	for (index = 0U; index < 8; index++) {
+		NRF_RADIO->DAB[index] = ((uint32_t)bdaddr[3] << 24) |
+			((uint32_t)bdaddr[2] << 16) |
+			((uint32_t)bdaddr[1] << 8) |
+			bdaddr[0];
+		NRF_RADIO->DAP[index] = ((uint32_t)bdaddr[5] << 8) | bdaddr[4];
+		bdaddr += 6;
+	}
+
+	NRF_RADIO->DACNF = ((uint32_t)bitmask_addr_type << 8) | bitmask_enable;
+}
+
+void radio_filter_disable(void)
+{
+	NRF_RADIO->DACNF &= ~(0x000000FF);
+}
+
+void radio_filter_status_reset(void)
+{
+	NRF_RADIO->EVENTS_DEVMATCH = 0;
+}
+
+uint32_t radio_filter_has_match(void)
+{
+	return (NRF_RADIO->EVENTS_DEVMATCH != 0);
+}
+
+uint32_t radio_filter_match_get(void)
+{
+	return NRF_RADIO->DAI;
+}
+
+void radio_bc_configure(uint32_t n)
+{
+	nrf_radio_bcc_set(NRF_RADIO, n);
+	NRF_RADIO->SHORTS |= RADIO_SHORTS_ADDRESS_BCSTART_Msk;
+}
+
+void radio_bc_status_reset(void)
+{
+	NRF_RADIO->EVENTS_BCMATCH = 0;
+}
+
+uint32_t radio_bc_has_match(void)
+{
+	return (NRF_RADIO->EVENTS_BCMATCH != 0);
+}
+
+void radio_tmr_status_reset(void)
+{
+	nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk);
+
+	hal_radio_nrf_ppi_channels_disable(
+			BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) |
+			BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI) |
+			BIT(HAL_EVENT_TIMER_START_PPI) |
+			BIT(HAL_RADIO_READY_TIME_CAPTURE_PPI) |
+			BIT(HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI) |
+			BIT(HAL_RADIO_DISABLE_ON_HCTO_PPI) |
+			BIT(HAL_RADIO_END_TIME_CAPTURE_PPI) |
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+			BIT(HAL_TRIGGER_RATEOVERRIDE_PPI) |
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+			BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI) |
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+			BIT(HAL_TRIGGER_CRYPT_PPI));
+}
+
+void radio_tmr_tifs_set(uint32_t tifs)
+{
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+	NRF_RADIO->TIFS = tifs;
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+	nrf_timer_cc_set(SW_SWITCH_TIMER,
+			 SW_SWITCH_TIMER_EVTS_COMP(sw_tifs_toggle), tifs);
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+}
+
+uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
+{
+	if ((!(remainder / 1000000UL)) || (remainder & 0x80000000)) {
+		ticks_start--;
+		remainder += 30517578UL;
+	}
+	remainder /= 1000000UL;
+
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR);
+	EVENT_TIMER->MODE = 0;
+	EVENT_TIMER->PRESCALER = 4;
+	EVENT_TIMER->BITMODE = 2;	/* 24 - bit */
+
+	nrf_timer_cc_set(EVENT_TIMER, 0, remainder);
+
+	nrf_rtc_cc_set(NRF_RTC0, 2, ticks_start);
+	nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE2_Msk);
+
+	hal_event_timer_start_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI));
+
+	hal_radio_enable_on_tick_ppi_config_and_enable(trx);
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	last_pdu_end_us = 0U;
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+	nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_CLEAR);
+	SW_SWITCH_TIMER->MODE = 0;
+	SW_SWITCH_TIMER->PRESCALER = 4;
+	SW_SWITCH_TIMER->BITMODE = 0; /* 16 bit */
+	/* FIXME: start alongwith EVENT_TIMER, to save power */
+	nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_START);
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+	hal_sw_switch_timer_clear_ppi_config();
+
+#if !defined(CONFIG_BT_CTLR_PHY_CODED) || \
+	!defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+
+	hal_radio_group_task_disable_ppi_setup();
+
+#else /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+	/* PPI setup needs to be configured at every sw_switch()
+	 * as they depend on the actual PHYs used in TX/RX mode.
+	 */
+#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	return remainder;
+}
+
+uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick)
+{
+	uint32_t remainder_us;
+
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_STOP);
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR);
+
+	/* Setup compare event with min. 1 us offset */
+	remainder_us = 1;
+	nrf_timer_cc_set(EVENT_TIMER, 0, remainder_us);
+
+	nrf_rtc_cc_set(NRF_RTC0, 2, tick);
+	nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE2_Msk);
+
+	hal_event_timer_start_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI));
+
+	hal_radio_enable_on_tick_ppi_config_and_enable(trx);
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	last_pdu_end_us = 0U;
+#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#if defined(CONFIG_SOC_SERIES_NRF53X)
+	/* NOTE: Timer clear DPPI configuration is needed only for nRF53
+	 *       because of calls to radio_disable() and
+	 *       radio_switch_complete_and_disable() inside a radio event call
+	 *       hal_radio_sw_switch_disable(), which in the case of nRF53
+	 *       cancels the task subscription.
+	 */
+	/* FIXME: hal_sw_switch_timer_clear_ppi_config() sets both task and
+	 *        event. Consider a new interface to only set the task, or
+	 *        change the design to not clear task subscription inside a
+	 *        radio event but when the radio event is done.
+	 */
+	hal_sw_switch_timer_clear_ppi_config();
+#endif /* CONFIG_SOC_SERIES_NRF53X */
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	return remainder_us;
+}
+
+void radio_tmr_start_us(uint8_t trx, uint32_t us)
+{
+	nrf_timer_cc_set(EVENT_TIMER, 0, us);
+
+	hal_radio_enable_on_tick_ppi_config_and_enable(trx);
+}
+
+uint32_t radio_tmr_start_now(uint8_t trx)
+{
+	uint32_t now, start;
+
+	hal_radio_enable_on_tick_ppi_config_and_enable(trx);
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_SOC_SERIES_NRF53X)
+	/* NOTE: Timer clear DPPI configuration is needed only for nRF53
+	 *       because of calls to radio_disable() and
+	 *       radio_switch_complete_and_disable() inside a radio event call
+	 *       hal_radio_sw_switch_disable(), which in the case of nRF53
+	 *       cancels the task subscription.
+	 */
+	/* FIXME: hal_sw_switch_timer_clear_ppi_config() sets both task and
+	 *        event. Consider a new interface to only set the task, or
+	 *        change the design to not clear task subscription inside a
+	 *        radio event but when the radio event is done.
+	 */
+	hal_sw_switch_timer_clear_ppi_config();
+#endif /* CONFIG_SOC_SERIES_NRF53X */
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+	/* Capture the current time */
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CAPTURE1);
+	now = EVENT_TIMER->CC[1];
+	start = now;
+
+	/* Setup PPI while determining the latency in doing so */
+	do {
+		/* Set start to be, now plus the determined latency */
+		start = (now << 1) - start;
+
+		/* Setup compare event with min. 1 us offset */
+		nrf_timer_cc_set(EVENT_TIMER, 0, start + 1);
+
+		/* Capture the current time */
+		nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CAPTURE1);
+
+		now = EVENT_TIMER->CC[1];
+	} while (now > start);
+
+	return start + 1;
+}
+
+uint32_t radio_tmr_start_get(void)
+{
+	return nrf_rtc_cc_get(NRF_RTC0, 2);
+}
+
+void radio_tmr_stop(void)
+{
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_STOP);
+	nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_SHUTDOWN);
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+	nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_STOP);
+	nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_SHUTDOWN);
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+}
+
+void radio_tmr_hcto_configure(uint32_t hcto)
+{
+	nrf_timer_cc_set(EVENT_TIMER, 1, hcto);
+
+	hal_radio_recv_timeout_cancel_ppi_config();
+	hal_radio_disable_on_hcto_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(
+		BIT(HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI) |
+		BIT(HAL_RADIO_DISABLE_ON_HCTO_PPI));
+}
+
+void radio_tmr_aa_capture(void)
+{
+	hal_radio_ready_time_capture_ppi_config();
+	hal_radio_recv_timeout_cancel_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(
+		BIT(HAL_RADIO_READY_TIME_CAPTURE_PPI) |
+		BIT(HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI));
+}
+
+uint32_t radio_tmr_aa_get(void)
+{
+	return EVENT_TIMER->CC[1];
+}
+
+static uint32_t radio_tmr_aa;
+
+void radio_tmr_aa_save(uint32_t aa)
+{
+	radio_tmr_aa = aa;
+}
+
+uint32_t radio_tmr_aa_restore(void)
+{
+	/* NOTE: we dont need to restore for now, but return the saved value. */
+	return radio_tmr_aa;
+}
+
+uint32_t radio_tmr_ready_get(void)
+{
+	return EVENT_TIMER->CC[0];
+}
+
+void radio_tmr_end_capture(void)
+{
+	hal_radio_end_time_capture_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_RADIO_END_TIME_CAPTURE_PPI));
+}
+
+uint32_t radio_tmr_end_get(void)
+{
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	return last_pdu_end_us;
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+	return EVENT_TIMER->CC[2];
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+}
+
+uint32_t radio_tmr_tifs_base_get(void)
+{
+	return radio_tmr_end_get();
+}
+
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+static uint32_t tmr_sample_val;
+#endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+void radio_tmr_sample(void)
+{
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	uint32_t cc;
+
+	cc = EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET];
+	nrf_timer_task_trigger(EVENT_TIMER, HAL_EVENT_TIMER_SAMPLE_TASK);
+
+	tmr_sample_val = EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET];
+	EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET] = cc;
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+	nrf_timer_task_trigger(EVENT_TIMER, HAL_EVENT_TIMER_SAMPLE_TASK);
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+}
+
+uint32_t radio_tmr_sample_get(void)
+{
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+	return tmr_sample_val;
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+	return EVENT_TIMER->CC[HAL_EVENT_TIMER_SAMPLE_CC_OFFSET];
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+}
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || \
+    defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+void radio_gpio_pa_setup(void)
+{
+	/* NOTE: With GPIO Pins above 31, left shift of
+	 *       CONFIG_BT_CTLR_GPIO_PA_PIN by GPIOTE_CONFIG_PSEL_Pos will
+	 *       set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
+	 */
+	NRF_GPIOTE->CONFIG[CONFIG_BT_CTLR_PA_LNA_GPIOTE_CHAN] =
+		(GPIOTE_CONFIG_MODE_Task <<
+		 GPIOTE_CONFIG_MODE_Pos) |
+		(CONFIG_BT_CTLR_GPIO_PA_PIN <<
+		 GPIOTE_CONFIG_PSEL_Pos) |
+		(GPIOTE_CONFIG_POLARITY_Toggle <<
+		 GPIOTE_CONFIG_POLARITY_Pos) |
+#if defined(CONFIG_BT_CTLR_GPIO_PA_POL_INV)
+		(GPIOTE_CONFIG_OUTINIT_High <<
+		 GPIOTE_CONFIG_OUTINIT_Pos);
+#else
+		(GPIOTE_CONFIG_OUTINIT_Low <<
+		 GPIOTE_CONFIG_OUTINIT_Pos);
+#endif
+}
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+void radio_gpio_lna_setup(void)
+{
+	/* NOTE: With GPIO Pins above 31, left shift of
+	 *       CONFIG_BT_CTLR_GPIO_LNA_PIN by GPIOTE_CONFIG_PSEL_Pos will
+	 *       set the NRF_GPIOTE->CONFIG[n].PORT to 1 (P1 port).
+	 */
+	NRF_GPIOTE->CONFIG[CONFIG_BT_CTLR_PA_LNA_GPIOTE_CHAN] =
+		(GPIOTE_CONFIG_MODE_Task <<
+		 GPIOTE_CONFIG_MODE_Pos) |
+		(CONFIG_BT_CTLR_GPIO_LNA_PIN <<
+		 GPIOTE_CONFIG_PSEL_Pos) |
+		(GPIOTE_CONFIG_POLARITY_Toggle <<
+		 GPIOTE_CONFIG_POLARITY_Pos) |
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_POL_INV)
+		(GPIOTE_CONFIG_OUTINIT_High <<
+		 GPIOTE_CONFIG_OUTINIT_Pos);
+#else
+		(GPIOTE_CONFIG_OUTINIT_Low <<
+		 GPIOTE_CONFIG_OUTINIT_Pos);
+#endif
+}
+
+void radio_gpio_lna_on(void)
+{
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_POL_INV)
+	NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
+#else
+	NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
+#endif
+}
+
+void radio_gpio_lna_off(void)
+{
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_POL_INV)
+	NRF_GPIO_LNA->OUTSET = BIT(NRF_GPIO_LNA_PIN);
+#else
+	NRF_GPIO_LNA->OUTCLR = BIT(NRF_GPIO_LNA_PIN);
+#endif
+}
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+void radio_gpio_pa_lna_enable(uint32_t trx_us)
+{
+	nrf_timer_cc_set(EVENT_TIMER, 2, trx_us);
+
+	hal_enable_palna_ppi_config();
+	hal_disable_palna_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_ENABLE_PALNA_PPI) |
+				BIT(HAL_DISABLE_PALNA_PPI));
+}
+
+void radio_gpio_pa_lna_disable(void)
+{
+	hal_radio_nrf_ppi_channels_disable(BIT(HAL_ENABLE_PALNA_PPI) |
+				 BIT(HAL_DISABLE_PALNA_PPI));
+}
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN || CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+static uint8_t MALIGN(4) _ccm_scratch[(HAL_RADIO_PDU_LEN_MAX - 4) + 16];
+
+void *radio_ccm_rx_pkt_set(struct ccm *ccm, uint8_t phy, void *pkt)
+{
+	uint32_t mode;
+
+	NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
+	NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled;
+	mode = (CCM_MODE_MODE_Decryption << CCM_MODE_MODE_Pos) &
+	       CCM_MODE_MODE_Msk;
+
+#if !defined(CONFIG_SOC_SERIES_NRF51X)
+	/* Enable CCM support for 8-bit length field PDUs. */
+	mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) &
+		CCM_MODE_LENGTH_Msk;
+
+	/* Select CCM data rate based on current PHY in use. */
+	switch (phy) {
+	default:
+	case BIT(0):
+		mode |= (CCM_MODE_DATARATE_1Mbit <<
+			 CCM_MODE_DATARATE_Pos) &
+			CCM_MODE_DATARATE_Msk;
+		break;
+
+	case BIT(1):
+		mode |= (CCM_MODE_DATARATE_2Mbit <<
+			 CCM_MODE_DATARATE_Pos) &
+			CCM_MODE_DATARATE_Msk;
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+	case BIT(2):
+		mode |= (CCM_MODE_DATARATE_125Kbps <<
+			 CCM_MODE_DATARATE_Pos) &
+			CCM_MODE_DATARATE_Msk;
+
+		NRF_CCM->RATEOVERRIDE =
+			(CCM_RATEOVERRIDE_RATEOVERRIDE_500Kbps <<
+			 CCM_RATEOVERRIDE_RATEOVERRIDE_Pos) &
+			CCM_RATEOVERRIDE_RATEOVERRIDE_Msk;
+
+		hal_trigger_rateoverride_ppi_config();
+		hal_radio_nrf_ppi_channels_enable(
+			BIT(HAL_TRIGGER_RATEOVERRIDE_PPI));
+		break;
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+#if !defined(CONFIG_SOC_COMPATIBLE_NRF52832) && \
+	(!defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX) || \
+	 (CONFIG_BT_CTLR_DATA_LENGTH_MAX < ((HAL_RADIO_PDU_LEN_MAX) - 4)))
+	uint8_t max_len = (NRF_RADIO->PCNF1 & RADIO_PCNF1_MAXLEN_Msk) >>
+			RADIO_PCNF1_MAXLEN_Pos;
+
+	NRF_CCM->MAXPACKETSIZE = max_len;
+#endif
+#endif /* !CONFIG_SOC_SERIES_NRF51X */
+
+	NRF_CCM->MODE = mode;
+	NRF_CCM->CNFPTR = (uint32_t)ccm;
+	NRF_CCM->INPTR = (uint32_t)_pkt_scratch;
+	NRF_CCM->OUTPTR = (uint32_t)pkt;
+	NRF_CCM->SCRATCHPTR = (uint32_t)_ccm_scratch;
+	NRF_CCM->SHORTS = 0;
+	NRF_CCM->EVENTS_ENDCRYPT = 0;
+	NRF_CCM->EVENTS_ERROR = 0;
+
+	hal_trigger_crypt_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_CRYPT_PPI));
+
+	nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
+
+	return _pkt_scratch;
+}
+
+void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt)
+{
+	uint32_t mode;
+
+	NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled;
+	NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled;
+	mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) &
+	       CCM_MODE_MODE_Msk;
+#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X)
+	/* Enable CCM support for 8-bit length field PDUs. */
+	mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) &
+		CCM_MODE_LENGTH_Msk;
+
+	/* NOTE: use fastest data rate as tx data needs to be prepared before
+	 * radio Tx on any PHY.
+	 */
+	mode |= (CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos) &
+		CCM_MODE_DATARATE_Msk;
+#endif
+	NRF_CCM->MODE = mode;
+	NRF_CCM->CNFPTR = (uint32_t)ccm;
+	NRF_CCM->INPTR = (uint32_t)pkt;
+	NRF_CCM->OUTPTR = (uint32_t)_pkt_scratch;
+	NRF_CCM->SCRATCHPTR = (uint32_t)_ccm_scratch;
+	NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
+	NRF_CCM->EVENTS_ENDCRYPT = 0;
+	NRF_CCM->EVENTS_ERROR = 0;
+
+	nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
+
+	return _pkt_scratch;
+}
+
+uint32_t radio_ccm_is_done(void)
+{
+	nrf_ccm_int_enable(NRF_CCM, CCM_INTENSET_ENDCRYPT_Msk);
+	while (NRF_CCM->EVENTS_ENDCRYPT == 0) {
+		__WFE();
+		__SEV();
+		__WFE();
+	}
+	nrf_ccm_int_disable(NRF_CCM, CCM_INTENCLR_ENDCRYPT_Msk);
+	NVIC_ClearPendingIRQ(nrfx_get_irq_number(NRF_CCM));
+
+	return (NRF_CCM->EVENTS_ERROR == 0);
+}
+
+uint32_t radio_ccm_mic_is_valid(void)
+{
+	return (NRF_CCM->MICSTATUS != 0);
+}
+
+static uint8_t MALIGN(4) _aar_scratch[3];
+
+void radio_ar_configure(uint32_t nirk, void *irk)
+{
+	NRF_AAR->ENABLE = (AAR_ENABLE_ENABLE_Enabled << AAR_ENABLE_ENABLE_Pos) &
+			  AAR_ENABLE_ENABLE_Msk;
+	NRF_AAR->NIRK = nirk;
+	NRF_AAR->IRKPTR = (uint32_t)irk;
+	NRF_AAR->ADDRPTR = (uint32_t)NRF_RADIO->PACKETPTR - 1;
+	NRF_AAR->SCRATCHPTR = (uint32_t)&_aar_scratch[0];
+
+	NRF_AAR->EVENTS_END = 0;
+	NRF_AAR->EVENTS_RESOLVED = 0;
+	NRF_AAR->EVENTS_NOTRESOLVED = 0;
+
+	radio_bc_configure(64);
+	radio_bc_status_reset();
+
+	hal_trigger_aar_ppi_config();
+	hal_radio_nrf_ppi_channels_enable(BIT(HAL_TRIGGER_AAR_PPI));
+}
+
+uint32_t radio_ar_match_get(void)
+{
+	return NRF_AAR->STATUS;
+}
+
+void radio_ar_status_reset(void)
+{
+	radio_bc_status_reset();
+
+	NRF_AAR->ENABLE = (AAR_ENABLE_ENABLE_Disabled << AAR_ENABLE_ENABLE_Pos) &
+			  AAR_ENABLE_ENABLE_Msk;
+}
+
+uint32_t radio_ar_has_match(void)
+{
+	return (radio_bc_has_match() &&
+		NRF_AAR->EVENTS_END &&
+		NRF_AAR->EVENTS_RESOLVED &&
+		!NRF_AAR->EVENTS_NOTRESOLVED);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h	(working copy)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define HAL_RADIO_NS2US_CEIL(ns)  ((ns + 999)/1000)
+#define HAL_RADIO_NS2US_ROUND(ns) ((ns + 500)/1000)
+
+/* Use the timer instance ID, not NRF_TIMERx directly, so that it can be checked
+ * in radio_nrf5_ppi.h by the preprocessor.
+ */
+#define EVENT_TIMER_ID 0
+#define EVENT_TIMER    _CONCAT(NRF_TIMER, EVENT_TIMER_ID)
+
+/* EVENTS_TIMER capture register used for sampling TIMER time-stamps. */
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3
+
+#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
+#include "radio_sim_nrfxx.h"
+#elif defined(CONFIG_SOC_SERIES_NRF51X)
+#include "radio_nrf51.h"
+#elif defined(CONFIG_SOC_NRF52805)
+#include "radio_nrf52805.h"
+#elif defined(CONFIG_SOC_NRF52810)
+#include "radio_nrf52810.h"
+#elif defined(CONFIG_SOC_NRF52811)
+#include "radio_nrf52811.h"
+#elif defined(CONFIG_SOC_NRF52820)
+#include "radio_nrf52820.h"
+#elif defined(CONFIG_SOC_NRF52832)
+#include "radio_nrf52832.h"
+#elif defined(CONFIG_SOC_NRF52833)
+#include "radio_nrf52833.h"
+#elif defined(CONFIG_SOC_NRF52840)
+#include "radio_nrf52840.h"
+#elif defined(CONFIG_SOC_NRF5340_CPUNET)
+#include "radio_nrf5340.h"
+#endif
+
+#include "radio_nrf5_ppi.h"
+#include "radio_nrf5_txp.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h	(working copy)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+/* TXEN->TXIDLE + TXIDLE->TX in microseconds. */
+#define HAL_RADIO_NRF51_TXEN_TXIDLE_TX_US 140
+#define HAL_RADIO_NRF51_TXEN_TXIDLE_TX_NS 140000
+/* RXEN->RXIDLE + RXIDLE->RX in microseconds. */
+#define HAL_RADIO_NRF51_RXEN_RXIDLE_RX_US 138
+#define HAL_RADIO_NRF51_RXEN_RXIDLE_RX_NS 138000
+
+#define HAL_RADIO_NRF51_TX_CHAIN_DELAY_US 1 /* ceil(1.0) */
+#define HAL_RADIO_NRF51_TX_CHAIN_DELAY_NS 1000 /* 1.0 */
+#define HAL_RADIO_NRF51_RX_CHAIN_DELAY_US 3 /* ceil(3.0) */
+#define HAL_RADIO_NRF51_RX_CHAIN_DELAY_NS 3000 /* 3.0 */
+
+static inline void hal_radio_reset(void)
+{
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Nrf_2Mbit;
+		break;
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg30dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_TXEN_TXIDLE_TX_US;
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_RXEN_RXIDLE_RX_US;
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_RX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_TXEN_TXIDLE_TX_NS;
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_RXEN_RXIDLE_RX_NS;
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_TX_CHAIN_DELAY_NS;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+	return HAL_RADIO_NRF51_RX_CHAIN_DELAY_NS;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h	(working copy)
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_FAST_NS 41050 /* 40.1 + 0.95 */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NS 141050 /*140.1 + 0.95*/
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.95 */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 129950
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144500 /* 144.6 - 0.1 */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 - 0.1 */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 128900
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /* 144.6 + 0.2 */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL(\
+		HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52805_TX_CHAIN_DELAY_NS     600 /* 0.6 */
+#define HAL_RADIO_NRF52805_TX_CHAIN_DELAY_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_TX_CHAIN_DELAY_NS)
+
+#define HAL_RADIO_NRF52805_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52805_RX_CHAIN_DELAY_1M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RX_CHAIN_DELAY_1M_NS)
+
+#define HAL_RADIO_NRF52805_RX_CHAIN_DELAY_2M_NS  5450 /* 5.0 + 0.45 */
+#define HAL_RADIO_NRF52805_RX_CHAIN_DELAY_2M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52805_RX_CHAIN_DELAY_2M_NS)
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 4
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52805_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_RX_CHAIN_DELAY_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_TXEN_TXIDLE_TX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_RXEN_RXIDLE_RX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52805_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52805_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52805_RX_CHAIN_DELAY_2M_NS;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h	(working copy)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_FAST_NS 41050 /* 40.1 + 0.95 */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NS 141050 /*140.1 + 0.95*/
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.95 */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 129950
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144500 /* 144.6 - 0.1 */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 - 0.1 */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 128900
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /* 144.6 + 0.2 */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL(\
+		HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52810_TX_CHAIN_DELAY_NS     600 /* 0.6 */
+#define HAL_RADIO_NRF52810_TX_CHAIN_DELAY_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_TX_CHAIN_DELAY_NS)
+
+#define HAL_RADIO_NRF52810_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52810_RX_CHAIN_DELAY_1M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RX_CHAIN_DELAY_1M_NS)
+
+#define HAL_RADIO_NRF52810_RX_CHAIN_DELAY_2M_NS  5450 /* 5.0 + 0.45 */
+#define HAL_RADIO_NRF52810_RX_CHAIN_DELAY_2M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52810_RX_CHAIN_DELAY_2M_NS)
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 4
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+			uint32_t volatile SERIAL2;
+			uint32_t volatile NFCT;
+			uint32_t volatile I2S;
+			uint32_t volatile PDM;
+			uint32_t volatile PWM;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL2 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.NFCT    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.I2S     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PDM     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PWM     = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52810_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_RX_CHAIN_DELAY_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_TXEN_TXIDLE_TX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_RXEN_RXIDLE_RX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52810_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52810_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52810_RX_CHAIN_DELAY_2M_NS;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h	(working copy)
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+ /* 129.5 + 0.8 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 - 0.1 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S2].
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S2].
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2].
+ */
+/* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S8].
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_FAST_NS)
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S8].
+ */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8].
+ */
+ /* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_1M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_1M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_2M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_2M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S2_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S2_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S8_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S8_NS  600 /* 0.6 */
+
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_1M_US  10 /* ceil(9.4) */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_2M_US  5 /* ceil(5.0) */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_2M_NS  5000 /* 5.0 */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S2_US  25 /* ceil(24.6) */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S2_NS  24600 /* 24.6 */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S8_US  30 /* ceil(29.6) */
+#define HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S8_NS  29600 /* 29.6 */
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_FAST_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_FAST_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_FAST_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_FAST_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_FAST_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 5
+#undef HAL_EVENT_TIMER_SAMPLE_CC_OFFSET
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2
+#undef HAL_EVENT_TIMER_SAMPLE_TASK
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 2
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+	/* Anomalies 102, 106 and 107 */
+	*(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) &
+					 0xfffffffe) | 0x01000000;
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+			uint32_t volatile SERIAL2;
+			uint32_t volatile NFCT;
+			uint32_t volatile I2S;
+			uint32_t volatile PDM;
+			uint32_t volatile PWM;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL2 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.NFCT    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.I2S     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PDM     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PWM     = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		/* Workaround: nRF52811 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c &= ~0x80000000;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		/* Workaround: nRF52811 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c &= ~0x80000000;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+		} else {
+			mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+		}
+
+		/* Workaround: nRF52811 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c |= 0x80000000;
+		*(volatile uint32_t *)0x4000173c =
+				((*(volatile uint32_t *)0x4000173c) & 0xFFFFFF00) |
+				0x5C;
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52811_TXEN_TXIDLE_TX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52811_RXEN_RXIDLE_RX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52811_TX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52811_RX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h	(working copy)
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+ /* 129.5 + 0.8 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 - 0.1 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S2].
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S2].
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2].
+ */
+/* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S8].
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_FAST_NS)
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S8].
+ */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8].
+ */
+ /* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_1M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_1M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_2M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_2M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S2_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S2_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S8_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S8_NS  600 /* 0.6 */
+
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_1M_US  10 /* ceil(9.4) */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_2M_US  5 /* ceil(5.0) */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_2M_NS  5000 /* 5.0 */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S2_US  25 /* ceil(19.6) */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S2_NS  24600 /* 19.6 */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S8_US  30 /* ceil(29.6) */
+#define HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S8_NS  29600 /* 29.6 */
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_FAST_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_FAST_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_FAST_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_FAST_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_FAST_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 5
+#undef HAL_EVENT_TIMER_SAMPLE_CC_OFFSET
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2
+#undef HAL_EVENT_TIMER_SAMPLE_TASK
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 2
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile reserved;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+		} else {
+			mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos7dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos6dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos5dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos2dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52820_TXEN_TXIDLE_TX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52820_RXEN_RXIDLE_RX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52820_TX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52820_RX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h	(working copy)
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS 41050 /* 40.1 + 0.95 */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS 141050 /*140.1 + 0.95*/
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.95 */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 129950
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144500 /* 144.6 - 0.1 */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 - 0.1 */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 128900
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /* 144.6 + 0.2 */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129 + 0.2 */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129200
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL(\
+		HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52832_TX_CHAIN_DELAY_NS     600 /* 0.6 */
+#define HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_TX_CHAIN_DELAY_NS)
+
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS)
+
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS  5450 /* 5.0 + 0.45 */
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS)
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 4
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+	/* Anomalies 102, 106 and 107 */
+	*(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) &
+					 0xfffffffe) | 0x01000000;
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+			uint32_t volatile SERIAL2;
+			uint32_t volatile NFCT;
+			uint32_t volatile I2S;
+			uint32_t volatile PDM;
+			uint32_t volatile PWM;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL2 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.NFCT    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.I2S     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PDM     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PWM     = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h	(working copy)
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+ /* 129.5 + 0.8 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 - 0.1 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S2].
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S2].
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2].
+ */
+/* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S8].
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_FAST_NS)
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S8].
+ */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8].
+ */
+ /* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_1M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_1M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_2M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_2M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S2_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S2_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S8_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S8_NS  600 /* 0.6 */
+
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_1M_US  10 /* ceil(9.4) */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_2M_US  5 /* ceil(5.0) */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_2M_NS  5000 /* 5.0 */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S2_US  25 /* ceil(19.6) */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S2_NS  24600 /* 19.6 */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S8_US  30 /* ceil(29.6) */
+#define HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S8_NS  29600 /* 29.6 */
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_FAST_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_FAST_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_FAST_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_FAST_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_FAST_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 5
+#undef HAL_EVENT_TIMER_SAMPLE_CC_OFFSET
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2
+#undef HAL_EVENT_TIMER_SAMPLE_TASK
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 2
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+			uint32_t volatile SERIAL2;
+			uint32_t volatile NFCT;
+			uint32_t volatile I2S;
+			uint32_t volatile PDM;
+			uint32_t volatile PWM;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL2 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.NFCT    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.I2S     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PDM     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PWM     = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+		} else {
+			mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos7dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos6dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos5dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos2dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52833_TXEN_TXIDLE_TX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52833_RXEN_RXIDLE_RX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52833_TX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52833_RX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h	(working copy)
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+ /* 129.5 + 0.8 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 - 0.1 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S2].
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S2].
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2].
+ */
+/* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S8].
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_FAST_NS)
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S8].
+ */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8].
+ */
+ /* 129.5 + 2.2 */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_1M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_1M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_2M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_2M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S2_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S2_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S8_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S8_NS  600 /* 0.6 */
+
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_1M_US  10 /* ceil(9.4) */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_2M_US  5 /* ceil(5.0) */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_2M_NS  5000 /* 5.0 */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S2_US  25 /* ceil(24.6) */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S2_NS  24600 /* 24.6 */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S8_US  30 /* ceil(29.6) */
+#define HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S8_NS  29600 /* 29.6 */
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_FAST_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_FAST_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_FAST_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_FAST_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_FAST_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_FAST_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 4
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 5
+#undef HAL_EVENT_TIMER_SAMPLE_CC_OFFSET
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2
+#undef HAL_EVENT_TIMER_SAMPLE_TASK
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 2
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+	/* Anomalies 102, 106 and 107 */
+	*(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) &
+					 0xfffffffe) | 0x01000000;
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	struct {
+		uint32_t volatile reserved_0[0x5a0 >> 2];
+		uint32_t volatile bridge_type;
+		uint32_t volatile reserved_1[((0xe00 - 0x5a0) >> 2) - 1];
+		struct {
+			uint32_t volatile CPU0;
+			uint32_t volatile SPIS1;
+			uint32_t volatile RADIO;
+			uint32_t volatile ECB;
+			uint32_t volatile CCM;
+			uint32_t volatile AAR;
+			uint32_t volatile SAADC;
+			uint32_t volatile UARTE;
+			uint32_t volatile SERIAL0;
+			uint32_t volatile SERIAL2;
+			uint32_t volatile NFCT;
+			uint32_t volatile I2S;
+			uint32_t volatile PDM;
+			uint32_t volatile PWM;
+		} RAMPRI;
+	} volatile *NRF_AMLI = (void volatile *)0x40000000UL;
+
+	NRF_AMLI->RAMPRI.CPU0    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SPIS1   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.RADIO   = 0x00000000UL;
+	NRF_AMLI->RAMPRI.ECB     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.CCM     = 0x00000000UL;
+	NRF_AMLI->RAMPRI.AAR     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SAADC   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.UARTE   = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL0 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.SERIAL2 = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.NFCT    = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.I2S     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PDM     = 0xFFFFFFFFUL;
+	NRF_AMLI->RAMPRI.PWM     = 0xFFFFFFFFUL;
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		/* Workaround: nRF52840 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c &= ~0x80000000;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		/* Workaround: nRF52840 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c &= ~0x80000000;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+		} else {
+			mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+		}
+
+		/* Workaround: nRF52840 Engineering A Errata ID 164 */
+		*(volatile uint32_t *)0x4000173c |= 0x80000000;
+		*(volatile uint32_t *)0x4000173c =
+				((*(volatile uint32_t *)0x4000173c) & 0xFFFFFF00) |
+				0x5C;
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos7dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos6dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos5dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos2dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_US;
+		} else {
+			return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52840_TXEN_TXIDLE_TX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52840_RXEN_RXIDLE_RX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52840_TX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF52840_RX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h	(working copy)
@@ -0,0 +1,624 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ * Copyright (c) 2019 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+ /* 129.5 + 0.8 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 - 0.1 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S2].
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S2].
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2].
+ */
+/* 129.5 + 2.2 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE CODED PHY [S8].
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_FAST_NS)
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY [S8].
+ */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8].
+ */
+ /* 129.5 + 2.2 */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S2].
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE Coded PHY [S8].
+ */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8].
+ */
+/* 129.5 + 0.2 */
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_1M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_1M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_2M_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_2M_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S2_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S2_NS  600 /* 0.6 */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S8_US  1 /* ceil(0.6) */
+#define HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S8_NS  600 /* 0.6 */
+
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_US  10 /* ceil(9.4) */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_NS  9400 /* 9.4 */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_US  5 /* ceil(5.0) */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_NS  5000 /* 5.0 */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S2_US  25 /* ceil(19.6) */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S2_NS  24600 /* 19.6 */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S8_US  30 /* ceil(29.6) */
+#define HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S8_NS  29600 /* 29.6 */
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_FAST_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_FAST_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_FAST_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_FAST_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_FAST_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_FAST_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_FAST_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_US \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_NS \
+	HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_US \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_NS \
+	HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER_ID
+#define EVENT_TIMER_ID 0
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 3
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 5
+#undef HAL_EVENT_TIMER_SAMPLE_CC_OFFSET
+#define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2
+#undef HAL_EVENT_TIMER_SAMPLE_TASK
+#define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#define SW_SWITCH_TIMER_EVTS_COMP_S2_BASE 2
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+	/* TODO */
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+	/* TODO */
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+		} else {
+			mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+		}
+
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_0dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg1dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg2dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg5dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg6dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg7dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	/* Note: The -30 dBm power level is deprecated so ignore it! */
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_US;
+		} else {
+			return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_US;
+		} else {
+			return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_US;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S8_US;
+		} else {
+			return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S2_US;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF5340_TXEN_TXIDLE_TX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S8_NS;
+		} else {
+			return HAL_RADIO_NRF5340_RXEN_RXIDLE_RX_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF5340_TX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_2M_NS;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (flags & 0x01) {
+			return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S8_NS;
+		} else {
+			return HAL_RADIO_NRF5340_RX_CHAIN_DELAY_S2_NS;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_ppi.h	(working copy)
@@ -0,0 +1,1489 @@
+/*
+ * Copyright (c) 2018 - 2019 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_COMPATIBLE_NRF52X)
+
+#include <nrfx/hal/nrf_ppi.h>
+
+static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask)
+{
+	nrf_ppi_channels_enable(NRF_PPI, mask);
+}
+
+static inline void hal_radio_nrf_ppi_channels_disable(uint32_t mask)
+{
+	nrf_ppi_channels_disable(NRF_PPI, mask);
+}
+
+/*******************************************************************************
+ * Enable Radio on Event Timer tick:
+ * wire the EVENT_TIMER EVENTS_COMPARE[0] event to RADIO TASKS_TXEN/RXEN task.
+ *
+ * Use the pre-programmed PPI channels if possible (if TIMER0 is used as the
+ * EVENT_TIMER).
+ */
+#if (EVENT_TIMER_ID == 0)
+
+/* PPI channel 20 is pre-programmed with the following fixed settings:
+ *   EEP: TIMER0->EVENTS_COMPARE[0]
+ *   TEP: RADIO->TASKS_TXEN
+ */
+#define HAL_RADIO_ENABLE_TX_ON_TICK_PPI 20
+/* PPI channel 21 is pre-programmed with the following fixed settings:
+ *   EEP: TIMER0->EVENTS_COMPARE[0]
+ *   TEP: RADIO->TASKS_RXEN
+ */
+#define HAL_RADIO_ENABLE_RX_ON_TICK_PPI 21
+
+static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
+{
+	/* No need to configure anything for the pre-programmed channels.
+	 * Just enable and disable them accordingly.
+	 */
+	nrf_ppi_channels_disable(
+		NRF_PPI,
+		trx ? BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI)
+		    : BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
+	nrf_ppi_channels_enable(
+		NRF_PPI,
+		trx ? BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI)
+		    : BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
+}
+
+#else
+
+#define HAL_RADIO_ENABLE_ON_TICK_PPI 1
+#define HAL_RADIO_ENABLE_TX_ON_TICK_PPI HAL_RADIO_ENABLE_ON_TICK_PPI
+#define HAL_RADIO_ENABLE_RX_ON_TICK_PPI HAL_RADIO_ENABLE_ON_TICK_PPI
+
+static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
+{
+	uint32_t event_address = (trx ? (uint32_t)&(NRF_RADIO->TASKS_TXEN)
+				   : (uint32_t)&(NRF_RADIO->TASKS_RXEN));
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_ENABLE_ON_TICK_PPI,
+		(uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[0]),
+		event_address);
+	nrf_ppi_channels_enable(NRF_PPI, BIT(HAL_RADIO_ENABLE_ON_TICK_PPI));
+}
+
+#endif /* (EVENT_TIMER_ID == 0) */
+
+/*******************************************************************************
+ * Capture event timer on Address reception:
+ * wire the RADIO EVENTS_ADDRESS event to the
+ * EVENT_TIMER TASKS_CAPTURE[<address timer>] task.
+ *
+ * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
+ * EVENT_TIMER).
+ */
+#if (EVENT_TIMER_ID == 0)
+
+/* PPI channel 26 is pre-programmed with the following fixed settings:
+ *   EEP: RADIO->EVENTS_ADDRESS
+ *   TEP: TIMER0->TASKS_CAPTURE[1]
+ */
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI 26
+
+static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
+{
+	/* No need to configure anything for the pre-programmed channel. */
+}
+
+#else
+
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI 2
+
+static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
+		(uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[1]));
+}
+
+#endif /* (EVENT_TIMER_ID == 0) */
+
+/*******************************************************************************
+ * Disable Radio on HCTO:
+ * wire the EVENT_TIMER EVENTS_COMPARE[<HCTO timer>] event
+ * to the RADIO TASKS_DISABLE task.
+ *
+ * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
+ * EVENT_TIMER).
+ */
+#if (EVENT_TIMER_ID == 0)
+
+/* PPI channel 22 is pre-programmed with the following fixed settings:
+ *   EEP: TIMER0->EVENTS_COMPARE[1]
+ *   TEP: RADIO->TASKS_DISABLE
+ */
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI 22
+
+static inline void hal_radio_disable_on_hcto_ppi_config(void)
+{
+	/* No need to configure anything for the pre-programmed channel. */
+}
+
+#else
+
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI 3
+
+static inline void hal_radio_disable_on_hcto_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_DISABLE_ON_HCTO_PPI,
+		(uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[1]),
+		(uint32_t)&(NRF_RADIO->TASKS_DISABLE));
+}
+
+#endif /* (EVENT_TIMER_ID == 0) */
+
+/*******************************************************************************
+ * Capture event timer on Radio end:
+ * wire the RADIO EVENTS_END event to the
+ * EVENT_TIMER TASKS_CAPTURE[<radio end timer>] task.
+ *
+ * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
+ * EVENT_TIMER).
+ */
+#if (EVENT_TIMER_ID == 0)
+
+/* PPI channel 27 is pre-programmed with the following fixed settings:
+ *   EEP: RADIO->EVENTS_END
+ *   TEP: TIMER0->TASKS_CAPTURE[2]
+ */
+#define HAL_RADIO_END_TIME_CAPTURE_PPI 27
+
+static inline void hal_radio_end_time_capture_ppi_config(void)
+{
+	/* No need to configure anything for the pre-programmed channel. */
+}
+
+#else
+
+#define HAL_RADIO_END_TIME_CAPTURE_PPI 4
+
+static inline void hal_radio_end_time_capture_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_END_TIME_CAPTURE_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_END),
+		(uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[2]));
+}
+
+#endif /* (EVENT_TIMER_ID == 0) */
+
+/*******************************************************************************
+ * Start event timer on RTC tick:
+ * wire the RTC0 EVENTS_COMPARE[2] event to EVENT_TIMER  TASKS_START task.
+ */
+#define HAL_EVENT_TIMER_START_PPI 5
+
+static inline void hal_event_timer_start_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_EVENT_TIMER_START_PPI,
+		(uint32_t)&(NRF_RTC0->EVENTS_COMPARE[2]),
+		(uint32_t)&(EVENT_TIMER->TASKS_START));
+}
+
+/*******************************************************************************
+ * Capture event timer on Radio ready:
+ * wire the RADIO EVENTS_READY event to the
+ * EVENT_TIMER TASKS_CAPTURE[<radio ready timer>] task.
+ */
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI 6
+
+static inline void hal_radio_ready_time_capture_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_READY_TIME_CAPTURE_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_READY),
+		(uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[0]));
+}
+
+/*******************************************************************************
+ * Trigger encryption task upon address reception:
+ * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task.
+ *
+ * PPI channel 25 is pre-programmed with the following fixed settings:
+ *   EEP: RADIO->EVENTS_ADDRESS
+ *   TEP: CCM->TASKS_CRYPT
+ */
+#define HAL_TRIGGER_CRYPT_PPI 25
+
+static inline void hal_trigger_crypt_ppi_config(void)
+{
+	/* No need to configure anything for the pre-programmed channel. */
+}
+
+/*******************************************************************************
+ * Trigger automatic address resolution on Bit counter match:
+ * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task.
+ *
+ * PPI channel 23 is pre-programmed with the following fixed settings:
+ *   EEP: RADIO->EVENTS_BCMATCH
+ *   TEP: AAR->TASKS_START
+ */
+#define HAL_TRIGGER_AAR_PPI 23
+
+static inline void hal_trigger_aar_ppi_config(void)
+{
+	/* No need to configure anything for the pre-programmed channel. */
+}
+
+/*******************************************************************************
+ * Trigger Radio Rate override upon Rateboost event.
+ */
+#if defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+
+#define HAL_TRIGGER_RATEOVERRIDE_PPI 13
+
+static inline void hal_trigger_rateoverride_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_TRIGGER_RATEOVERRIDE_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST),
+		(uint32_t)&(NRF_CCM->TASKS_RATEOVERRIDE));
+}
+
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+
+/******************************************************************************/
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+
+#define HAL_ENABLE_PALNA_PPI 14
+
+static inline void hal_enable_palna_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_ENABLE_PALNA_PPI,
+		(uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[2]),
+		(uint32_t)&(NRF_GPIOTE->TASKS_OUT[
+				CONFIG_BT_CTLR_PA_LNA_GPIOTE_CHAN]));
+}
+
+#define HAL_DISABLE_PALNA_PPI 15
+
+static inline void hal_disable_palna_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_DISABLE_PALNA_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_DISABLED),
+		(uint32_t)&(NRF_GPIOTE->TASKS_OUT[
+				CONFIG_BT_CTLR_PA_LNA_GPIOTE_CHAN]));
+}
+
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN || CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+/******************************************************************************/
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+/* PPI setup used for SW-based auto-switching during TIFS. */
+
+#if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+
+/* Clear SW-switch timer on packet end:
+ * wire the RADIO EVENTS_END event to SW_SWITCH_TIMER TASKS_CLEAR task.
+ *
+ * Note: this PPI is not needed if we use a single TIMER instance in radio.c
+ */
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI 7
+
+static inline void hal_sw_switch_timer_clear_ppi_config(void)
+{
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_SW_SWITCH_TIMER_CLEAR_PPI,
+		(uint32_t)&(NRF_RADIO->EVENTS_END),
+		(uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
+}
+
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+/* Clear event timer (sw-switch timer) on Radio end:
+ * wire the RADIO EVENTS_END event to the
+ * EVENT_TIMER TASKS_CLEAR task.
+ *
+ * Note: in nRF52X this PPI channel is forked for both capturing and clearing
+ * timer on RADIO EVENTS_END.
+ */
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI HAL_RADIO_END_TIME_CAPTURE_PPI
+
+static inline void hal_sw_switch_timer_clear_ppi_config(void)
+{
+	nrf_ppi_fork_endpoint_setup(
+		NRF_PPI,
+		HAL_RADIO_END_TIME_CAPTURE_PPI,
+		(uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
+}
+
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+/* The 2 adjacent PPI groups used for implementing SW_SWITCH_TIMER-based
+ * auto-switch for TIFS. 'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_TASK_GROUP(index) \
+	(SW_SWITCH_TIMER_TASK_GROUP_BASE + index)
+
+/* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
+ * SW_SWITCH_TIMER-based auto-switch for TIFS. 'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_EVTS_COMP(index) \
+	(SW_SWITCH_TIMER_EVTS_COMP_BASE + index)
+
+/* Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
+ * to a PPI GROUP TASK DISABLE task (PPI group with index <index>).
+ * 2 adjacent PPIs (8 & 9) and 2 adjacent PPI groups are used for this wiring;
+ * <index> must be 0 or 1. <offset> must be a valid TIMER CC register offset.
+ */
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE 8
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \
+	(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE + index)
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE \
+	BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0))
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE \
+	BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1))
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(chan) \
+	NRF_PPI->CH[chan].EEP
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_offset) \
+	((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(chan) \
+	NRF_PPI->CH[chan].TEP
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(index) \
+	((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].DIS))
+
+/* Wire the RADIO EVENTS_END event to one of the PPI GROUP TASK ENABLE task.
+ * 2 adjacent PPI groups are used for this wiring. 'index' must be 0 or 1.
+ */
+#if defined(CONFIG_SOC_NRF52805)
+/* Because nRF52805 has limited number of programmable PPI channels,
+ * tIFS Trx SW switching on this SoC can be used only when pre-programmed
+ * PPI channels are also in use, i.e. when TIMER0 is the event timer.
+ */
+#if (EVENT_TIMER_ID == 0)
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI 2
+#else
+#error "tIFS Trx SW switch can be used on this SoC only with TIMER0 as the event timer"
+#endif
+#else /* -> !defined(CONFIG_SOC_NRF52805) */
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI 10
+#endif
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \
+	((uint32_t)&(NRF_RADIO->EVENTS_END))
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(index) \
+	((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN))
+
+/*Enable Radio at specific time-stamp:
+ * wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
+ * to RADIO TASKS_TXEN/RXEN task.
+ * 2 adjacent PPIs (11 & 12) are used for this wiring; <index> must be 0 or 1.
+ * <offset> must be a valid TIMER CC register offset.
+ */
+#if defined(CONFIG_SOC_NRF52805)
+#if (EVENT_TIMER_ID == 0)
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE 3
+#else
+#error "tIFS Trx SW switch can be used on this SoC only with TIMER0 as the event timer"
+#endif
+#else /* -> !defined(CONFIG_SOC_NRF52805) */
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE 11
+#endif
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI(index) \
+	(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + index)
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(chan) \
+	NRF_PPI->CH[chan].EEP
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_offset) \
+	((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK(chan) \
+	NRF_PPI->CH[chan].TEP
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX \
+	((uint32_t)&(NRF_RADIO->TASKS_TXEN))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX \
+	((uint32_t)&(NRF_RADIO->TASKS_RXEN))
+
+static inline void hal_radio_sw_switch_setup(
+		uint8_t compare_reg,
+		uint8_t radio_enable_ppi,
+		uint8_t ppi_group_index)
+{
+	/* Set up software switch mechanism for next Radio switch. */
+
+	/* Wire RADIO END event to PPI Group[<index>] enable task,
+	 * over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
+	 */
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI,
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT,
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(ppi_group_index));
+
+	/* Wire SW Switch timer event <compare_reg> to the
+	 * PPI[<radio_enable_ppi>] for enabling Radio. Do
+	 * not wire the task; it is done by the caller of
+	 * the function depending on the desired direction
+	 * (TX/RX).
+	 */
+	nrf_ppi_event_endpoint_setup(
+		NRF_PPI,
+		radio_enable_ppi,
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg));
+}
+
+static inline void hal_radio_txen_on_sw_switch(uint8_t ppi)
+{
+	nrf_ppi_task_endpoint_setup(
+		NRF_PPI,
+		ppi,
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
+}
+
+static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi)
+{
+	nrf_ppi_task_endpoint_setup(
+		NRF_PPI,
+		ppi,
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX);
+}
+
+static inline void hal_radio_sw_switch_disable(void)
+{
+	/* Disable the following PPI channels that implement SW Switch:
+	 * - Clearing SW SWITCH TIMER on RADIO END event
+	 * - Enabling SW SWITCH PPI Group on RADIO END event
+	 */
+	nrf_ppi_channels_disable(
+		NRF_PPI,
+		BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
+		BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI));
+}
+
+static inline void hal_radio_sw_switch_cleanup(void)
+{
+	hal_radio_sw_switch_disable();
+	nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(0));
+	nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(1));
+}
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED) && \
+	defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+/* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
+ * SW_SWITCH_TIMER-based auto-switch for TIFS, when receiving in LE Coded PHY.
+ *  'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \
+	(SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + index)
+
+/* Wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
+ * to RADIO TASKS_TXEN/RXEN task.
+ */
+#define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE 16
+#define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(index) \
+	(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE + index)
+#define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_0_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(0))
+#define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_1_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(1))
+
+/* Cancel the SW switch timer running considering S8 timing:
+ * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task.
+ */
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI 18
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT \
+	NRF_PPI->CH[HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI].EEP
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT \
+	((uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST))
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_TASK \
+	NRF_PPI->CH[HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI].TEP
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(index) \
+	((uint32_t)&(SW_SWITCH_TIMER->TASKS_CAPTURE[index]))
+
+static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,
+	uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
+{
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(ppi_en) =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_s2);
+
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK(ppi_en) =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX;
+
+	/* Wire the Group task disable
+	 * to the S2 EVENTS_COMPARE.
+	 */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
+	    ppi_dis)	=
+	    HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_s2);
+
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(
+	    ppi_dis) =
+	    HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(
+	    group_index);
+
+	/* Capture CC to cancel the timer that has assumed
+	 * S8 reception, if packet will be received in S2.
+	 */
+	HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT =
+		HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT;
+	HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_TASK =
+		HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(
+			group_index);
+
+	nrf_ppi_channels_enable(
+		NRF_PPI,
+		BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI));
+}
+
+static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
+	uint8_t ppi_dis, uint8_t cc_reg, uint8_t group_index)
+{
+	/* Invalidate PPI used when RXing on LE Coded PHY. */
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(
+		ppi_en) = 0;
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK(
+		ppi_en) = 0;
+
+	/* Wire the Group task disable to the default EVENTS_COMPARE. */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
+		ppi_dis) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_reg);
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(
+		ppi_dis) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(
+			group_index);
+}
+
+#else
+
+static inline void hal_radio_group_task_disable_ppi_setup(void)
+{
+	/* Wire SW SWITCH TIMER EVENTS COMPARE event <cc index-0> to
+	 * PPI Group TASK [<index-0>] DISABLE task, over PPI<index-0>.
+	 */
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0),
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
+			SW_SWITCH_TIMER_EVTS_COMP(0)),
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(0));
+
+	/* Wire SW SWITCH TIMER event <compare index-1> to
+	 * PPI Group[<index-1>] Disable Task, over PPI<index-1>.
+	 */
+	nrf_ppi_channel_endpoint_setup(
+		NRF_PPI,
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1),
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
+			SW_SWITCH_TIMER_EVTS_COMP(1)),
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(1));
+}
+#endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+
+static inline void hal_radio_sw_switch_ppi_group_setup(void)
+{
+	/* Include the appropriate PPI channels in the two PPI Groups. */
+#if !defined(CONFIG_BT_CTLR_PHY_CODED) || \
+	!defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
+	NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE |
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE;
+	NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE |
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE;
+#else
+	NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE |
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE |
+		HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_0_INCLUDE;
+	NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE |
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE |
+		HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_1_INCLUDE;
+#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
+}
+
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+/******************************************************************************/
+
+#define HAL_USED_PPI_CHANNELS \
+	(BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) | \
+	 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI) | \
+	 BIT(HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI) | \
+	 BIT(HAL_RADIO_DISABLE_ON_HCTO_PPI) | \
+	 BIT(HAL_RADIO_END_TIME_CAPTURE_PPI) | \
+	 BIT(HAL_EVENT_TIMER_START_PPI) | \
+	 BIT(HAL_RADIO_READY_TIME_CAPTURE_PPI) | \
+	 BIT(HAL_TRIGGER_CRYPT_PPI) | \
+	 BIT(HAL_TRIGGER_AAR_PPI) | \
+	 HAL_USED_PPI_CHANNELS_2 | HAL_USED_PPI_CHANNELS_3 | \
+	 HAL_USED_PPI_CHANNELS_4 | HAL_USED_PPI_CHANNELS_5)
+
+#if defined(HAL_TRIGGER_RATEOVERRIDE_PPI)
+#define HAL_USED_PPI_CHANNELS_2 \
+	BIT(HAL_TRIGGER_RATEOVERRIDE_PPI)
+#else
+#define HAL_USED_PPI_CHANNELS_2 0
+#endif
+
+#if defined(HAL_ENABLE_PALNA_PPI)
+#define HAL_USED_PPI_CHANNELS_3 \
+	(BIT(HAL_ENABLE_PALNA_PPI) | \
+	 BIT(HAL_DISABLE_PALNA_PPI))
+#else
+#define HAL_USED_PPI_CHANNELS_3 0
+#endif
+
+#if defined(HAL_SW_SWITCH_TIMER_CLEAR_PPI)
+#define HAL_USED_PPI_CHANNELS_4 \
+	(BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE+1) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE+1))
+#else
+#define HAL_USED_PPI_CHANNELS_4 0
+#endif
+
+#if defined(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE)
+#define HAL_USED_PPI_CHANNELS_5 \
+	(BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE+1) | \
+	 BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI))
+#else
+#define HAL_USED_PPI_CHANNELS_5 0
+#endif
+
+#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
+/* When the build is targeting an NRF board simulated with BabbleSim,
+ * nrfx_glue.h is not processed and the following symbol is not defined.
+ */
+#define NRFX_PPI_CHANNELS_USED_BY_PWM_SW  0
+#endif
+BUILD_ASSERT(
+	(HAL_USED_PPI_CHANNELS & NRFX_PPI_CHANNELS_USED_BY_PWM_SW) == 0,
+	"PPI channels used by the Bluetooth controller overlap with those "
+	"assigned to the pwm_nrf5_sw driver.");
+
+#if defined(SW_SWITCH_TIMER_TASK_GROUP_BASE)
+#define HAL_USED_PPI_GROUPS \
+	(BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE) | \
+	 BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE+1))
+#else
+#define HAL_USED_PPI_GROUPS 0
+#endif
+
+#elif defined(CONFIG_SOC_NRF5340_CPUNET)
+
+#include <nrfx/hal/nrf_dppi.h>
+
+static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask)
+{
+	nrf_dppi_channels_enable(NRF_DPPIC, mask);
+}
+
+static inline void hal_radio_nrf_ppi_channels_disable(uint32_t mask)
+{
+	nrf_dppi_channels_disable(NRF_DPPIC, mask);
+}
+
+/*******************************************************************************
+ * Enable Radio on Event Timer tick:
+ * wire the EVENT_TIMER EVENTS_COMPARE[0] event to RADIO TASKS_TXEN/RXEN task.
+ */
+#define HAL_RADIO_ENABLE_ON_TICK_PPI 0
+#define HAL_RADIO_ENABLE_TX_ON_TICK_PPI HAL_RADIO_ENABLE_ON_TICK_PPI
+#define HAL_RADIO_ENABLE_RX_ON_TICK_PPI HAL_RADIO_ENABLE_ON_TICK_PPI
+
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_EVT \
+	EVENT_TIMER->PUBLISH_COMPARE[0]
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_EVT \
+	(((HAL_RADIO_ENABLE_ON_TICK_PPI << TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
+		& TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
+	((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
+		& TIMER_PUBLISH_COMPARE_EN_Msk))
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_TX \
+	NRF_RADIO->SUBSCRIBE_TXEN
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_RX \
+	NRF_RADIO->SUBSCRIBE_RXEN
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_TASK_TX_SET \
+	(((HAL_RADIO_ENABLE_ON_TICK_PPI << RADIO_SUBSCRIBE_TXEN_CHIDX_Pos) \
+		& RADIO_SUBSCRIBE_TXEN_CHIDX_Msk) | \
+	((RADIO_SUBSCRIBE_TXEN_EN_Enabled << \
+			RADIO_SUBSCRIBE_TXEN_EN_Pos) \
+		& RADIO_SUBSCRIBE_TXEN_EN_Msk))
+#define HAL_RADIO_ENABLE_ON_TICK_PPI_TASK_RX_SET \
+	(((HAL_RADIO_ENABLE_ON_TICK_PPI << RADIO_SUBSCRIBE_RXEN_CHIDX_Pos) \
+		& RADIO_SUBSCRIBE_RXEN_CHIDX_Msk) | \
+	((RADIO_SUBSCRIBE_RXEN_EN_Enabled << RADIO_SUBSCRIBE_RXEN_EN_Pos) \
+		& RADIO_SUBSCRIBE_RXEN_EN_Msk))
+
+static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
+{
+	HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_EVT =
+		HAL_RADIO_ENABLE_ON_TICK_PPI_EVT;
+
+	if (trx) {
+		HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_TX =
+			HAL_RADIO_ENABLE_ON_TICK_PPI_TASK_TX_SET;
+
+		/* Address nRF5340 Engineering A Errata 16 */
+		if (IS_ENABLED(CONFIG_BT_CTLR_TIFS_HW)) {
+			HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_RX = 0;
+		}
+	} else {
+		HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_RX =
+			HAL_RADIO_ENABLE_ON_TICK_PPI_TASK_RX_SET;
+
+		/* Address nRF5340 Engineering A Errata 16 */
+		if (IS_ENABLED(CONFIG_BT_CTLR_TIFS_HW)) {
+			HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_TX = 0;
+		}
+	}
+
+	nrf_dppi_channels_enable(
+		NRF_DPPIC, BIT(HAL_RADIO_ENABLE_ON_TICK_PPI));
+}
+
+/*******************************************************************************
+ * Capture event timer on Address reception:
+ * wire the RADIO EVENTS_ADDRESS event to the
+ * EVENT_TIMER TASKS_CAPTURE[<address timer>] task.
+ */
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI 3
+
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_REGISTER_EVT \
+		NRF_RADIO->PUBLISH_ADDRESS
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_EVT \
+	(((HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI << \
+			RADIO_PUBLISH_ADDRESS_CHIDX_Pos) \
+		& RADIO_PUBLISH_ADDRESS_CHIDX_Msk) | \
+	((RADIO_PUBLISH_ADDRESS_EN_Enabled << RADIO_PUBLISH_ADDRESS_EN_Pos) \
+		& RADIO_PUBLISH_ADDRESS_EN_Msk))
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_REGISTER_TASK \
+	EVENT_TIMER->SUBSCRIBE_CAPTURE[1]
+#define HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_TASK \
+	(((HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI << \
+			TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_CAPTURE_EN_Enabled << \
+			TIMER_SUBSCRIBE_CAPTURE_EN_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_EN_Msk))
+
+static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
+{
+	HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_REGISTER_EVT =
+		HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_EVT;
+
+	HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_REGISTER_TASK =
+		HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Disable Radio on HCTO:
+ * wire the EVENT_TIMER EVENTS_COMPARE[<HCTO timer>] event
+ * to the RADIO TASKS_DISABLE task.
+ */
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI 4
+
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI_REGISTER_EVT \
+	EVENT_TIMER->PUBLISH_COMPARE[1]
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI_EVT \
+	(((HAL_RADIO_DISABLE_ON_HCTO_PPI << \
+		TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
+		& TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
+	((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
+		& TIMER_PUBLISH_COMPARE_EN_Msk))
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI_REGISTER_TASK \
+	NRF_RADIO->SUBSCRIBE_DISABLE
+#define HAL_RADIO_DISABLE_ON_HCTO_PPI_TASK \
+	(((HAL_RADIO_DISABLE_ON_HCTO_PPI << \
+		RADIO_SUBSCRIBE_DISABLE_CHIDX_Pos) \
+		& RADIO_SUBSCRIBE_DISABLE_CHIDX_Msk) | \
+	((RADIO_SUBSCRIBE_DISABLE_EN_Enabled << \
+		RADIO_SUBSCRIBE_DISABLE_EN_Pos) \
+		& RADIO_SUBSCRIBE_DISABLE_EN_Msk))
+
+static inline void hal_radio_disable_on_hcto_ppi_config(void)
+{
+	HAL_RADIO_DISABLE_ON_HCTO_PPI_REGISTER_EVT =
+		HAL_RADIO_DISABLE_ON_HCTO_PPI_EVT;
+
+	HAL_RADIO_DISABLE_ON_HCTO_PPI_REGISTER_TASK =
+		HAL_RADIO_DISABLE_ON_HCTO_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Capture event timer on Radio end:
+ * wire the RADIO EVENTS_END event to the
+ * EVENT_TIMER TASKS_CAPTURE[<radio end timer>] task.
+ */
+#define HAL_RADIO_END_TIME_CAPTURE_PPI 5
+
+#define HAL_RADIO_END_TIME_CAPTURE_PPI_REGISTER_EVT \
+	(NRF_RADIO->PUBLISH_END)
+#define HAL_RADIO_END_TIME_CAPTURE_PPI_EVT \
+	(((HAL_RADIO_END_TIME_CAPTURE_PPI << RADIO_PUBLISH_END_CHIDX_Pos) \
+		& RADIO_PUBLISH_END_CHIDX_Msk) | \
+	((RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos) \
+		& RADIO_PUBLISH_END_EN_Msk))
+#define HAL_RADIO_END_TIME_CAPTURE_PPI_REGISTER_TASK \
+	(EVENT_TIMER->SUBSCRIBE_CAPTURE[2])
+#define HAL_RADIO_END_TIME_CAPTURE_PPI_TASK \
+	(((HAL_RADIO_END_TIME_CAPTURE_PPI << \
+			TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_CAPTURE_EN_Enabled << \
+			TIMER_SUBSCRIBE_CAPTURE_EN_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_EN_Msk))
+
+static inline void hal_radio_end_time_capture_ppi_config(void)
+{
+	HAL_RADIO_END_TIME_CAPTURE_PPI_REGISTER_EVT =
+		HAL_RADIO_END_TIME_CAPTURE_PPI_EVT;
+
+	HAL_RADIO_END_TIME_CAPTURE_PPI_REGISTER_TASK =
+		HAL_RADIO_END_TIME_CAPTURE_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Start event timer on RTC tick:
+ * wire the RTC0 EVENTS_COMPARE[2] event to EVENT_TIMER  TASKS_START task.
+ */
+#define HAL_EVENT_TIMER_START_PPI 1
+
+#define HAL_EVENT_TIMER_START_PPI_REGISTER_EVT \
+	NRF_RTC0->PUBLISH_COMPARE[2]
+#define HAL_EVENT_TIMER_START_PPI_EVT \
+	(((HAL_EVENT_TIMER_START_PPI << RTC_PUBLISH_COMPARE_CHIDX_Pos) \
+		& RTC_PUBLISH_COMPARE_CHIDX_Msk) | \
+	((RTC_PUBLISH_COMPARE_EN_Enabled << RTC_PUBLISH_COMPARE_EN_Pos) \
+		& RTC_PUBLISH_COMPARE_EN_Msk))
+#define HAL_EVENT_TIMER_START_PPI_REGISTER_TASK \
+	EVENT_TIMER->SUBSCRIBE_START
+#define HAL_EVENT_TIMER_START_PPI_TASK \
+	(((HAL_EVENT_TIMER_START_PPI << TIMER_SUBSCRIBE_START_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_START_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_START_EN_Enabled << TIMER_SUBSCRIBE_START_EN_Pos) \
+		& TIMER_SUBSCRIBE_START_EN_Msk))
+
+static inline void hal_event_timer_start_ppi_config(void)
+{
+	HAL_EVENT_TIMER_START_PPI_REGISTER_EVT =
+		HAL_EVENT_TIMER_START_PPI_EVT;
+
+	HAL_EVENT_TIMER_START_PPI_REGISTER_TASK =
+		HAL_EVENT_TIMER_START_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Capture event timer on Radio ready:
+ * wire the RADIO EVENTS_READY event to the
+ * EVENT_TIMER TASKS_CAPTURE[<radio ready timer>] task.
+ */
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI 2
+
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI_REGISTER_EVT \
+	NRF_RADIO->PUBLISH_READY
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI_EVT \
+	(((HAL_RADIO_READY_TIME_CAPTURE_PPI << \
+		RADIO_PUBLISH_READY_CHIDX_Pos) \
+		& RADIO_PUBLISH_READY_CHIDX_Msk) | \
+	((RADIO_PUBLISH_READY_EN_Enabled << RADIO_PUBLISH_READY_EN_Pos) \
+		& RADIO_PUBLISH_READY_EN_Msk))
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI_REGISTER_TASK \
+	EVENT_TIMER->SUBSCRIBE_CAPTURE[0]
+#define HAL_RADIO_READY_TIME_CAPTURE_PPI_TASK \
+	(((HAL_RADIO_READY_TIME_CAPTURE_PPI << \
+			TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_CAPTURE_EN_Enabled << \
+			TIMER_SUBSCRIBE_CAPTURE_EN_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_EN_Msk))
+
+static inline void hal_radio_ready_time_capture_ppi_config(void)
+{
+	HAL_RADIO_READY_TIME_CAPTURE_PPI_REGISTER_EVT =
+		HAL_RADIO_READY_TIME_CAPTURE_PPI_EVT;
+
+	HAL_RADIO_READY_TIME_CAPTURE_PPI_REGISTER_TASK =
+		HAL_RADIO_READY_TIME_CAPTURE_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Trigger encryption task upon address reception:
+ * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task.
+ *
+ * Note: we do not need an additional PPI, since we have already set up
+ * a PPI to publish RADIO ADDRESS event.
+ */
+#define HAL_TRIGGER_CRYPT_PPI HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI
+
+#define HAL_TRIGGER_CRYPT_PPI_REGISTER_EVT \
+	NRF_RADIO->PUBLISH_ADDRESS
+#define HAL_TRIGGER_CRYPT_PPI_EVT \
+	(((HAL_TRIGGER_CRYPT_PPI << RADIO_PUBLISH_ADDRESS_CHIDX_Pos) \
+		&	RADIO_PUBLISH_ADDRESS_CHIDX_Msk) | \
+	((RADIO_PUBLISH_ADDRESS_EN_Enabled << RADIO_PUBLISH_ADDRESS_EN_Pos) \
+		& RADIO_PUBLISH_ADDRESS_EN_Msk))
+#define HAL_TRIGGER_CRYPT_PPI_REGISTER_TASK \
+	NRF_CCM->SUBSCRIBE_CRYPT
+#define HAL_TRIGGER_CRYPT_PPI_TASK \
+	(((HAL_TRIGGER_CRYPT_PPI <<	CCM_SUBSCRIBE_CRYPT_CHIDX_Pos) \
+		& CCM_SUBSCRIBE_CRYPT_CHIDX_Msk) | \
+	((CCM_SUBSCRIBE_CRYPT_EN_Enabled << CCM_SUBSCRIBE_CRYPT_EN_Pos) \
+		& CCM_SUBSCRIBE_CRYPT_EN_Msk))
+
+static inline void hal_trigger_crypt_ppi_config(void)
+{
+	HAL_TRIGGER_CRYPT_PPI_REGISTER_EVT =
+		HAL_TRIGGER_CRYPT_PPI_EVT;
+
+	HAL_TRIGGER_CRYPT_PPI_REGISTER_TASK =
+		HAL_TRIGGER_CRYPT_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Trigger automatic address resolution on Bit counter match:
+ * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task.
+ */
+#define HAL_TRIGGER_AAR_PPI 6
+
+#define HAL_TRIGGER_AAR_PPI_REGISTER_EVT \
+		NRF_RADIO->PUBLISH_BCMATCH
+#define HAL_TRIGGER_AAR_PPI_EVT \
+	(((HAL_TRIGGER_AAR_PPI << RADIO_PUBLISH_BCMATCH_CHIDX_Pos) \
+		& RADIO_PUBLISH_BCMATCH_CHIDX_Msk) | \
+	((RADIO_PUBLISH_BCMATCH_EN_Enabled << RADIO_PUBLISH_BCMATCH_EN_Pos) \
+		& RADIO_PUBLISH_BCMATCH_EN_Msk))
+#define HAL_TRIGGER_AAR_PPI_REGISTER_TASK \
+	NRF_AAR->SUBSCRIBE_START
+#define HAL_TRIGGER_AAR_PPI_TASK \
+	(((HAL_TRIGGER_AAR_PPI << AAR_SUBSCRIBE_START_CHIDX_Pos) \
+		& AAR_SUBSCRIBE_START_CHIDX_Msk) | \
+	((AAR_SUBSCRIBE_START_EN_Enabled << AAR_SUBSCRIBE_START_EN_Pos) \
+		& AAR_SUBSCRIBE_START_EN_Msk))
+
+static inline void hal_trigger_aar_ppi_config(void)
+{
+	HAL_TRIGGER_AAR_PPI_REGISTER_EVT =
+		HAL_TRIGGER_AAR_PPI_EVT;
+
+	HAL_TRIGGER_AAR_PPI_REGISTER_TASK =
+		HAL_TRIGGER_AAR_PPI_TASK;
+}
+
+/*******************************************************************************
+ * Trigger Radio Rate override upon Rateboost event.
+ */
+#define HAL_TRIGGER_RATEOVERRIDE_PPI 13
+
+#define HAL_TRIGGER_RATEOVERRIDE_PPI_REGISTER_EVT \
+	NRF_RADIO->PUBLISH_RATEBOOST
+#define HAL_TRIGGER_RATEOVERRIDE_PPI_EVT \
+	(((HAL_TRIGGER_RATEOVERRIDE_PPI << \
+			RADIO_PUBLISH_RATEBOOST_CHIDX_Pos) \
+		& RADIO_PUBLISH_RATEBOOST_CHIDX_Msk) | \
+	((RADIO_PUBLISH_RATEBOOST_EN_Enabled << \
+			RADIO_PUBLISH_RATEBOOST_EN_Pos) \
+		& RADIO_PUBLISH_RATEBOOST_EN_Msk))
+#define HAL_TRIGGER_RATEOVERRIDE_PPI_REGISTER_TASK \
+	NRF_CCM->SUBSCRIBE_RATEOVERRIDE
+#define HAL_TRIGGER_RATEOVERRIDE_PPI_TASK \
+	(((HAL_TRIGGER_RATEOVERRIDE_PPI << \
+			CCM_SUBSCRIBE_RATEOVERRIDE_CHIDX_Pos) \
+		& CCM_SUBSCRIBE_RATEOVERRIDE_CHIDX_Msk) | \
+	((CCM_SUBSCRIBE_RATEOVERRIDE_EN_Enabled << \
+			CCM_SUBSCRIBE_RATEOVERRIDE_EN_Pos) \
+		& CCM_SUBSCRIBE_RATEOVERRIDE_EN_Msk))
+
+static inline void hal_trigger_rateoverride_ppi_config(void)
+{
+	HAL_TRIGGER_RATEOVERRIDE_PPI_REGISTER_EVT =
+		HAL_TRIGGER_RATEOVERRIDE_PPI_EVT;
+
+	HAL_TRIGGER_RATEOVERRIDE_PPI_REGISTER_TASK =
+		HAL_TRIGGER_RATEOVERRIDE_PPI_TASK;
+}
+
+/******************************************************************************/
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+/* DPPI setup used for SW-based auto-switching during TIFS. */
+
+/* Clear SW-switch timer on packet end:
+ * wire the RADIO EVENTS_END event to SW_SWITCH_TIMER TASKS_CLEAR task.
+ *
+ * Note: we do not need an additional PPI, since we have already set up
+ * a PPI to publish RADIO END event.
+ */
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI HAL_RADIO_END_TIME_CAPTURE_PPI
+
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_EVT \
+	(NRF_RADIO->PUBLISH_END)
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI_EVT \
+	(((HAL_SW_SWITCH_TIMER_CLEAR_PPI << RADIO_PUBLISH_END_CHIDX_Pos) \
+		& RADIO_PUBLISH_END_CHIDX_Msk) | \
+	((RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos) \
+		& RADIO_PUBLISH_END_EN_Msk))
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_TASK \
+	(SW_SWITCH_TIMER->SUBSCRIBE_CLEAR)
+#define HAL_SW_SWITCH_TIMER_CLEAR_PPI_TASK \
+	(((HAL_SW_SWITCH_TIMER_CLEAR_PPI << TIMER_SUBSCRIBE_CLEAR_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_CLEAR_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_CLEAR_EN_Enabled << TIMER_SUBSCRIBE_CLEAR_EN_Pos) \
+		& TIMER_SUBSCRIBE_CLEAR_EN_Msk))
+
+static inline void hal_sw_switch_timer_clear_ppi_config(void)
+{
+	HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_EVT =
+		HAL_SW_SWITCH_TIMER_CLEAR_PPI_EVT;
+	HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_TASK =
+		HAL_SW_SWITCH_TIMER_CLEAR_PPI_TASK;
+}
+
+/* The 2 adjacent PPI groups used for implementing SW_SWITCH_TIMER-based
+ * auto-switch for TIFS. 'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_TASK_GROUP(index) \
+	(SW_SWITCH_TIMER_TASK_GROUP_BASE + index)
+
+/* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
+ * SW_SWITCH_TIMER-based auto-switch for TIFS. 'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_EVTS_COMP(index) \
+	(SW_SWITCH_TIMER_EVTS_COMP_BASE + index)
+
+/* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
+ * SW_SWITCH_TIMER-based auto-switch for TIFS, when receiving on LE Coded
+ * PHY. 'index' must be 0 or 1.
+ */
+#define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \
+	(SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + index)
+
+/* Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
+ * to a PPI GROUP TASK DISABLE task (PPI group with index <index>).
+ * 2 adjacent PPIs (8 & 9) and 2 adjacent PPI groups are used for this wiring;
+ * <index> must be 0 or 1. <offset> must be a valid TIMER CC register offset.
+ */
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE 8
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \
+	(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE + index)
+
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE \
+	BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0))
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE \
+	BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1))
+
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(cc_offset) \
+	SW_SWITCH_TIMER->PUBLISH_COMPARE[cc_offset]
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(chan) \
+	(((chan << TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
+		& TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
+	((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
+		& TIMER_PUBLISH_COMPARE_EN_Msk))
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index) \
+	NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].DIS
+#define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(chan) \
+	(((chan << DPPIC_SUBSCRIBE_CHG_DIS_CHIDX_Pos) \
+		& DPPIC_SUBSCRIBE_CHG_DIS_CHIDX_Msk) | \
+	((DPPIC_SUBSCRIBE_CHG_DIS_EN_Enabled << \
+			DPPIC_SUBSCRIBE_CHG_DIS_EN_Pos) \
+		& DPPIC_SUBSCRIBE_CHG_DIS_EN_Msk))
+
+/* Enable the SW Switch PPI Group on RADIO END Event.
+ *
+ * Note: we do not need an additional PPI, since we have already set up
+ * a PPI to publish RADIO END event.
+ */
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI HAL_SW_SWITCH_TIMER_CLEAR_PPI
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT \
+	(NRF_RADIO->PUBLISH_END)
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \
+	(((HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI << \
+		RADIO_PUBLISH_END_CHIDX_Pos) \
+		&	RADIO_PUBLISH_END_CHIDX_Msk) | \
+	((RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos) \
+		& RADIO_PUBLISH_END_EN_Msk))
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(index) \
+	(NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN)
+#define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK \
+	(((HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI << \
+			DPPIC_SUBSCRIBE_CHG_EN_CHIDX_Pos) \
+		&	DPPIC_SUBSCRIBE_CHG_EN_CHIDX_Msk) | \
+	((DPPIC_SUBSCRIBE_CHG_EN_EN_Enabled << \
+		DPPIC_SUBSCRIBE_CHG_EN_EN_Pos) \
+		& DPPIC_SUBSCRIBE_CHG_EN_EN_Msk))
+
+/* Enable Radio on SW Switch timer event.
+ * Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
+ * to a RADIO Enable task (TX or RX).
+ *
+ * Note:
+ * We use the same PPI as for disabling the SW Switch PPI groups,
+ * since we need to listen for the same event (SW Switch event).
+ *
+ * We use the same PPI for the alternative SW Switch Timer compare
+ * event.
+ */
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE 8
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI(index) \
+	(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + index)
+
+#define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(index) \
+	(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + index)
+
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE \
+	BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1))
+
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(cc_offset) \
+	SW_SWITCH_TIMER->PUBLISH_COMPARE[cc_offset]
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(chan) \
+	(((chan << TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
+		& TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
+	((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
+		& TIMER_PUBLISH_COMPARE_EN_Msk))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_TX \
+	NRF_RADIO->SUBSCRIBE_TXEN
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_RX \
+	NRF_RADIO->SUBSCRIBE_RXEN
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX_SET(chan) \
+	(((chan << RADIO_SUBSCRIBE_TXEN_CHIDX_Pos) \
+		& RADIO_SUBSCRIBE_TXEN_CHIDX_Msk) | \
+	((RADIO_SUBSCRIBE_TXEN_EN_Enabled << \
+			RADIO_SUBSCRIBE_TXEN_EN_Pos) \
+		& RADIO_SUBSCRIBE_TXEN_EN_Msk))
+#define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX_SET(chan) \
+	(((chan << RADIO_SUBSCRIBE_RXEN_CHIDX_Pos) \
+		&	RADIO_SUBSCRIBE_RXEN_CHIDX_Msk) | \
+	((RADIO_SUBSCRIBE_RXEN_EN_Enabled << RADIO_SUBSCRIBE_RXEN_EN_Pos) \
+		&	RADIO_SUBSCRIBE_RXEN_EN_Msk))
+
+/* Cancel the SW switch timer running considering S8 timing:
+ * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task.
+ *
+ * Note: We already have a PPI where we publish the RATEBOOST event.
+ */
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI HAL_TRIGGER_RATEOVERRIDE_PPI
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT \
+	NRF_RADIO->PUBLISH_RATEBOOST
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT \
+	(((HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI << \
+		RADIO_PUBLISH_RATEBOOST_CHIDX_Pos) \
+	& RADIO_PUBLISH_RATEBOOST_CHIDX_Msk) | \
+	((RADIO_PUBLISH_RATEBOOST_EN_Enabled << \
+		RADIO_PUBLISH_RATEBOOST_EN_Pos) \
+	& RADIO_PUBLISH_RATEBOOST_EN_Msk))
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_TASK(cc_reg) \
+	SW_SWITCH_TIMER->SUBSCRIBE_CAPTURE[cc_reg]
+#define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK \
+	(((HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI << \
+		TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_CHIDX_Msk) | \
+	((TIMER_SUBSCRIBE_CAPTURE_EN_Enabled << \
+		TIMER_SUBSCRIBE_CAPTURE_EN_Pos) \
+		& TIMER_SUBSCRIBE_CAPTURE_EN_Msk))
+
+
+static inline void hal_radio_sw_switch_setup(
+		uint8_t compare_reg,
+		uint8_t radio_enable_ppi,
+		uint8_t ppi_group_index)
+{
+	/* Set up software switch mechanism for next Radio switch. */
+
+	/* Wire RADIO END event to PPI Group[<index>] enable task,
+	 * over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
+	 */
+	HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT =
+	    HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT;
+	HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(ppi_group_index) =
+	    HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK;
+
+	/* Sanity build-time check that
+	 * - SW SWITCH Timer Clear
+	 * - Radio End Capture, and
+	 * - Group Enable
+	 *  tasks are all going to be subscribed on the same PPI.
+	 */
+	BUILD_ASSERT(
+		&HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT ==
+			&HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_EVT,
+		"SW SWitch Timer Clear and Group Disable"
+		" not on the same PPI channel.");
+	BUILD_ASSERT(
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT ==
+			HAL_SW_SWITCH_TIMER_CLEAR_PPI_EVT,
+		"SW SWitch Timer Clear and Group Disable"
+		" not on the same PPI channel.");
+	BUILD_ASSERT(
+		&HAL_RADIO_END_TIME_CAPTURE_PPI_REGISTER_EVT ==
+			&HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_EVT,
+		"Radio End Timer Capture and Group Disable"
+		" not on the same PPI channel.");
+	BUILD_ASSERT(
+		HAL_RADIO_END_TIME_CAPTURE_PPI_EVT ==
+			HAL_SW_SWITCH_TIMER_CLEAR_PPI_EVT,
+		"Radio End Timer Capture and Group Disable"
+		" not on the same PPI channel.");
+
+	/* We need to un-subscribe the other group from the PPI channel. */
+	if (ppi_group_index == 0) {
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(1)	= 0;
+	} else if (ppi_group_index == 1) {
+		HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(0)	= 0;
+	}
+
+	/* Wire SW Switch timer event <compare_reg> to the
+	 * PPI[<radio_enable_ppi>] for enabling Radio. Do
+	 * not wire the task; it is done by the caller of
+	 * the function depending on the desired direction
+	 * (TX/RX).
+	 */
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg) =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
+}
+
+static inline void hal_radio_txen_on_sw_switch(uint8_t ppi)
+{
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_TX =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX_SET(ppi);
+}
+
+static inline void hal_radio_rxen_on_sw_switch(uint8_t ppi)
+{
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_TASK_RX =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX_SET(ppi);
+}
+
+
+static inline void hal_radio_sw_switch_disable(void)
+{
+	/* We cannot deactivate the PPI channels, as other tasks
+	 * are subscribed to RADIO_END event, i.e on the same channel.
+	 * So we simply cancel the task subscription.
+	 */
+	HAL_SW_SWITCH_TIMER_CLEAR_PPI_REGISTER_TASK = 0;
+	HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(0) = 0;
+	HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_TASK(1) = 0;
+}
+
+static inline void hal_radio_sw_switch_cleanup(void)
+{
+	hal_radio_sw_switch_disable();
+	nrf_dppi_channels_disable(NRF_DPPIC,
+				  (BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
+				   BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI)));
+	nrf_dppi_group_disable(NRF_DPPIC, SW_SWITCH_TIMER_TASK_GROUP(0));
+	nrf_dppi_group_disable(NRF_DPPIC, SW_SWITCH_TIMER_TASK_GROUP(1));
+}
+
+static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,
+	uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
+{
+	/* Publish the SW Switch Timer Compare event for S2 timing
+	 * to the PPI that will be used to trigger Radio enable.
+	 */
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(cc_s2) =
+		HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(ppi_en);
+
+	/* The Radio Enable Task is already subscribed to the channel. */
+
+	/* Wire the Group task disable to the S2 EVENTS_COMPARE. */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(cc_s2) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(ppi_dis);
+
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(group_index) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(ppi_dis);
+
+	/* Capture CC to cancel the timer that has assumed
+	 * S8 reception, if packet will be received in S2.
+	 */
+	HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT =
+		HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT;
+	HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_TASK(
+		SW_SWITCH_TIMER_EVTS_COMP(group_index)) =
+		HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK;
+
+	nrf_dppi_channels_enable(NRF_DPPIC,
+		BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI));
+}
+
+static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
+	uint8_t ppi_dis, uint8_t cc_reg, uint8_t group_index)
+{
+	/* Invalidate subscription of S2 timer Compare used when
+	 * RXing on LE Coded PHY.
+	 *
+	 * Note: we do not un-subscribe the Radio enable task because
+	 * we use the same PPI for both SW Switch Timer compare events.
+	 */
+	HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(
+		SW_SWITCH_TIMER_S2_EVTS_COMP(group_index)) = 0;
+
+	/* Wire the Group[group_index] task disable to the default
+	 * SW Switch Timer EVENTS_COMPARE.
+	 */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
+		cc_reg) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
+			ppi_dis);
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(
+		group_index) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(
+			ppi_dis);
+}
+
+static inline void hal_radio_sw_switch_ppi_group_setup(void)
+{
+	/* Include the appropriate PPI channels in the two PPI Groups, used for
+	 * SW-based TIFS.
+	 *
+	 * Note that this needs to be done before any SUBSCRIBE task
+	 * registers are written, therefore, we clear the task registers
+	 * here.
+	 */
+	NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].EN = 0;
+	NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].DIS = 0;
+	NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].EN = 0;
+	NRF_DPPIC->SUBSCRIBE_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].DIS = 0;
+
+	NRF_DPPIC->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(0)].DIS = 1;
+	NRF_DPPIC->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(1)].DIS = 1;
+
+	/* Include the appropriate PPI channels in the two PPI Groups. */
+	NRF_DPPIC->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE |
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE;
+	NRF_DPPIC->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE |
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE;
+
+	/* Sanity build-time check that RADIO Enable and Group Disable
+	 * tasks are going to be subscribed on the same PPIs.
+	 */
+	BUILD_ASSERT(
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE ==
+			BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)),
+		"Radio enable and Group disable not on the right PPI channel.");
+	BUILD_ASSERT(
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE ==
+			BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)),
+		"Radio enable and Group disable not on the right PPI channel.");
+	BUILD_ASSERT(
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_0_INCLUDE ==
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_0_INCLUDE,
+		"Radio enable and Group disable not on the same PPI channel.");
+	BUILD_ASSERT(
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_1_INCLUDE ==
+			HAL_SW_SWITCH_RADIO_ENABLE_PPI_1_INCLUDE,
+		"Radio enable and Group disable not on the same PPI channel.");
+
+	/* Address nRF5340 Engineering A Errata 16 */
+	HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_TX = 0;
+	HAL_RADIO_ENABLE_ON_TICK_PPI_REGISTER_TASK_RX = 0;
+}
+
+static inline void hal_radio_group_task_disable_ppi_setup(void)
+{
+
+	/* Wire SW SWITCH TIMER EVENTS COMPARE event <cc index-0> to
+	 * PPI Group TASK [<index-0>] DISABLE task, over PPI<index-0>.
+	 */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
+		SW_SWITCH_TIMER_EVTS_COMP(0)) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
+			HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0));
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(0) =
+			HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(
+				HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0));
+
+	/* Wire SW SWITCH TIMER event <compare index-1> to
+	 * PPI Group[<index-1>] Disable Task, over PPI<index-1>.
+	 */
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
+		SW_SWITCH_TIMER_EVTS_COMP(1)) =
+		HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
+			HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1));
+	HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(1) =
+			HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(
+				HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1));
+}
+
+#endif
+
+#define HAL_USED_PPI_CHANNELS \
+	(BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) | \
+	 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI) | \
+	 BIT(HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI) | \
+	 BIT(HAL_RADIO_DISABLE_ON_HCTO_PPI) | \
+	 BIT(HAL_RADIO_END_TIME_CAPTURE_PPI) | \
+	 BIT(HAL_EVENT_TIMER_START_PPI) | \
+	 BIT(HAL_RADIO_READY_TIME_CAPTURE_PPI) | \
+	 BIT(HAL_TRIGGER_CRYPT_PPI) | \
+	 BIT(HAL_TRIGGER_AAR_PPI) | \
+	 HAL_USED_PPI_CHANNELS_2 | HAL_USED_PPI_CHANNELS_3 | \
+	 HAL_USED_PPI_CHANNELS_4 | HAL_USED_PPI_CHANNELS_5)
+
+#if defined(HAL_TRIGGER_RATEOVERRIDE_PPI)
+#define HAL_USED_PPI_CHANNELS_2 \
+	BIT(HAL_TRIGGER_RATEOVERRIDE_PPI)
+#else
+#define HAL_USED_PPI_CHANNELS_2 0
+#endif
+
+#if defined(HAL_ENABLE_PALNA_PPI)
+#define HAL_USED_PPI_CHANNELS_3 \
+	(BIT(HAL_ENABLE_PALNA_PPI) | \
+	 BIT(HAL_DISABLE_PALNA_PPI))
+#else
+#define HAL_USED_PPI_CHANNELS_3 0
+#endif
+
+#if defined(HAL_SW_SWITCH_TIMER_CLEAR_PPI)
+#define HAL_USED_PPI_CHANNELS_4 \
+	(BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE+1) | \
+	 BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE+1))
+#else
+#define HAL_USED_PPI_CHANNELS_4 0
+#endif
+
+#if defined(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE)
+#define HAL_USED_PPI_CHANNELS_5 \
+	(BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE) | \
+	 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE+1) | \
+	 BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI))
+#else
+#define HAL_USED_PPI_CHANNELS_5 0
+#endif
+#if defined(SW_SWITCH_TIMER_TASK_GROUP_BASE)
+#define HAL_USED_PPI_GROUPS \
+	(BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE) | \
+	 BIT(SW_SWITCH_TIMER_TASK_GROUP_BASE+1))
+#else
+#define HAL_USED_PPI_GROUPS 0
+#endif
+
+#endif /* CONFIG_SOC_SERIES_NRF51X || CONFIG_SOC_COMPATIBLE_NRF52X */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_txp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_txp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_txp.h	(working copy)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_PLUS_8)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos8dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_7)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos7dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_6)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos6dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_5)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos5dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_4)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos4dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_3)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos3dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_PLUS_2)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Pos2dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_0)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_0dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_4)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg4dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_8)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg8dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_12)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg12dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_16)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg16dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_20)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg20dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_30)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg30dBm
+#elif defined(CONFIG_BT_CTLR_TX_PWR_MINUS_40)
+#define RADIO_TXP_DEFAULT RADIO_TXPOWER_TXPOWER_Neg40dBm
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrfxx.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrfxx.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrfxx.h	(working copy)
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2018 Ioannis Glaropoulos
+ * Copyright (c) 2018 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * This header needs lots of types and macros, instead of relaying on
+ * good inclusion order let's pull them through soc.h
+ */
+#include "soc.h"
+
+/* NRF Radio HW timing constants
+ * - provided in US and NS (for higher granularity)
+ * - based on empirical measurements and sniffer logs
+ */
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS 41000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS 141000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS 40000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS 140000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS)
+
+/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode
+ * and no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129000
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_ROUND( \
+		HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS 40000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 1M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL( \
+		HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS 40000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode)
+ * in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS 140000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS)
+
+/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and
+ * no HW TIFS auto-switch) in microseconds for LE 2M PHY.
+ */
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129000
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \
+	HAL_RADIO_NS2US_CEIL(\
+		HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS)
+
+#define HAL_RADIO_NRF52832_TX_CHAIN_DELAY_NS     1000
+#define HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_TX_CHAIN_DELAY_NS)
+
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS  9000
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS)
+
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS  5000
+#define HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_US \
+	HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS)
+
+#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST)
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_FAST_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_FAST_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_FAST_NS
+
+#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+#if defined(CONFIG_BT_CTLR_TIFS_HW)
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NS
+
+#else /* !CONFIG_BT_CTLR_TIFS_HW */
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS \
+	HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS
+
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US
+#define HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS \
+	HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */
+
+#if !defined(CONFIG_BT_CTLR_TIFS_HW)
+#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
+#undef EVENT_TIMER
+#define EVENT_TIMER NRF_TIMER0
+#define SW_SWITCH_TIMER EVENT_TIMER
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+#define SW_SWITCH_TIMER NRF_TIMER1
+#define SW_SWITCH_TIMER_EVTS_COMP_BASE 0
+#endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
+
+#define SW_SWITCH_TIMER_TASK_GROUP_BASE 0
+#endif /* !CONFIG_BT_CTLR_TIFS_HW */
+
+static inline void hal_radio_reset(void)
+{
+}
+
+static inline void hal_radio_ram_prio_setup(void)
+{
+
+}
+
+static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+	uint32_t mode;
+
+	switch (phy) {
+	case BIT(0):
+	default:
+		mode = RADIO_MODE_MODE_Ble_1Mbit;
+		break;
+
+	case BIT(1):
+		mode = RADIO_MODE_MODE_Ble_2Mbit;
+		break;
+	}
+
+	return mode;
+}
+
+static inline uint32_t hal_radio_tx_power_min_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_max_get(void)
+{
+	return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+}
+
+static inline uint32_t hal_radio_tx_power_floor(int8_t tx_power_lvl)
+{
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) {
+		return RADIO_TXPOWER_TXPOWER_Pos3dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) {
+		return RADIO_TXPOWER_TXPOWER_0dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg4dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg8dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg12dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg16dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg20dBm;
+	}
+
+	if (tx_power_lvl >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg30dBm) {
+		return RADIO_TXPOWER_TXPOWER_Neg30dBm;
+	}
+
+	return RADIO_TXPOWER_TXPOWER_Neg40dBm;
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_US;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_US;
+	}
+}
+
+static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_TXEN_TXIDLE_TX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RXEN_RXIDLE_RX_2M_NS;
+	}
+}
+
+static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(phy);
+	ARG_UNUSED(flags);
+
+	return HAL_RADIO_NRF52832_TX_CHAIN_DELAY_US;
+}
+
+static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	switch (phy) {
+	default:
+	case BIT(0):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_1M_NS;
+	case BIT(1):
+		return HAL_RADIO_NRF52832_RX_CHAIN_DELAY_2M_NS;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h	(working copy)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_COMPATIBLE_NRF52X)
+
+#define HAL_SWI_RADIO_IRQ  SWI4_IRQn
+#define HAL_SWI_WORKER_IRQ RTC0_IRQn
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+#define HAL_SWI_JOB_IRQ    HAL_SWI_WORKER_IRQ
+#else
+#define HAL_SWI_JOB_IRQ    SWI5_IRQn
+#endif
+
+#elif defined(CONFIG_SOC_SERIES_NRF53X)
+
+#if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET)
+
+#define HAL_SWI_RADIO_IRQ  SWI2_IRQn
+#define HAL_SWI_WORKER_IRQ RTC0_IRQn
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+#define HAL_SWI_JOB_IRQ    HAL_SWI_WORKER_IRQ
+#else
+#define HAL_SWI_JOB_IRQ    SWI3_IRQn
+#endif
+
+#elif defined(CONFIG_BOARD_NRF5340PDK_NRF5340_CPUNET)
+
+#define HAL_SWI_RADIO_IRQ  EGU0_IRQn
+#define HAL_SWI_WORKER_IRQ RTC0_IRQn
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+#define HAL_SWI_JOB_IRQ    HAL_SWI_WORKER_IRQ
+#else
+#error "Use an unused IRQ line to implement a second SW IRQ."
+#endif
+
+#endif /* CONFIG_BOARD_NRF5340PDK_NRF5340_CPUNET */
+
+#endif /* CONFIG_SOC_SERIES_NRF53X */
+
+static inline void hal_swi_init(void)
+{
+	/* No platform-specific initialization required. */
+}
+
+static inline void hal_swi_lll_pend(void)
+{
+	NVIC_SetPendingIRQ(HAL_SWI_RADIO_IRQ);
+}
+
+static inline void hal_swi_worker_pend(void)
+{
+	NVIC_SetPendingIRQ(HAL_SWI_WORKER_IRQ);
+}
+
+static inline void hal_swi_job_pend(void)
+{
+	NVIC_SetPendingIRQ(HAL_SWI_JOB_IRQ);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.h	(working copy)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U
+
+/* Macro defining the minimum counter compare offset */
+#define HAL_TICKER_CNTR_CMP_OFFSET_MIN 3
+
+/* Macro defining the max. counter update latency in ticks */
+#define HAL_TICKER_CNTR_SET_LATENCY 0
+
+/* Macro to translate microseconds to tick units.
+ * NOTE: This returns the floor value.
+ */
+#define HAL_TICKER_US_TO_TICKS(x) \
+	( \
+		((uint32_t)(((uint64_t) (x) * 1000000000UL) / 30517578125UL)) \
+		& HAL_TICKER_CNTR_MASK \
+	)
+
+/* Macro returning remainder in nanoseconds */
+#define HAL_TICKER_REMAINDER(x) \
+	( \
+		( \
+			((uint64_t) (x) * 1000000000UL) \
+			- ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * 30517578125UL) \
+		) \
+		/ 1000UL \
+	)
+
+/* Macro to translate tick units to microseconds. */
+#define HAL_TICKER_TICKS_TO_US(x) \
+	((uint32_t)(((uint64_t)(x) * 30517578125UL) / 1000000000UL))
+
+/* Macro defines the h/w supported most significant bit */
+#define HAL_TICKER_CNTR_MSBIT 23
+
+/* Macro defining the HW supported counter bits */
+#define HAL_TICKER_CNTR_MASK 0x00FFFFFF
+
+/* Macro defining the remainder resolution/range
+ * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1)
+ */
+#define HAL_TICKER_REMAINDER_RANGE \
+	HAL_TICKER_TICKS_TO_US(1000000)
+
+/* Macro defining the margin for positioning re-scheduled nodes */
+#define HAL_TICKER_RESCHEDULE_MARGIN \
+	HAL_TICKER_US_TO_TICKS(150)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/ticker.c	(working copy)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+
+#include "hal/cntr.h"
+
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "ll_sw/lll.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_hal_ticker
+#include "common/log.h"
+#include "hal/debug.h"
+
+#define TICKER_MAYFLY_CALL_ID_ISR     TICKER_USER_ID_LLL
+#define TICKER_MAYFLY_CALL_ID_TRIGGER TICKER_USER_ID_ULL_HIGH
+#define TICKER_MAYFLY_CALL_ID_WORKER  TICKER_USER_ID_ULL_HIGH
+#define TICKER_MAYFLY_CALL_ID_JOB     TICKER_USER_ID_ULL_LOW
+#define TICKER_MAYFLY_CALL_ID_PROGRAM TICKER_USER_ID_THREAD
+
+static uint8_t const caller_id_lut[] = {
+	TICKER_CALL_ID_ISR,
+	TICKER_CALL_ID_WORKER,
+	TICKER_CALL_ID_JOB,
+	TICKER_CALL_ID_PROGRAM
+};
+
+uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id)
+{
+	uint8_t caller_id;
+
+	LL_ASSERT(user_id < sizeof(caller_id_lut));
+
+	caller_id = caller_id_lut[user_id];
+	LL_ASSERT(caller_id != TICKER_CALL_ID_NONE);
+
+	return caller_id;
+}
+
+void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+				void *instance)
+{
+	/* return value not checked as we allow multiple calls to schedule
+	 * before being actually needing the work to complete before new
+	 * schedule.
+	 */
+	switch (caller_id) {
+	case TICKER_CALL_ID_ISR:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			/* TODO: scheduler lock, if preemptive threads used */
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_ISR,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_TRIGGER:
+		switch (callee_id) {
+		case TICKER_CALL_ID_WORKER:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_worker};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
+				       TICKER_MAYFLY_CALL_ID_WORKER,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_WORKER:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_JOB:
+		switch (callee_id) {
+		case TICKER_CALL_ID_WORKER:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_worker};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
+				       TICKER_MAYFLY_CALL_ID_WORKER,
+				       chain,
+				       &m);
+		}
+		break;
+
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_PROGRAM:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			/* TODO: scheduler lock, if preemptive threads used */
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+
+void hal_ticker_instance0_trigger_set(uint32_t value)
+{
+	cntr_cmp_set(0, value);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/radio_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/radio_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/radio_vendor_hal.h	(working copy)
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_SOC_SERIES_NRF51X)
+#define HAL_RADIO_PDU_LEN_MAX (BIT(5) - 1)
+#else
+#define HAL_RADIO_PDU_LEN_MAX (BIT(8) - 1)
+#endif
+
+#include "hal/nrf5/radio/radio.h"
+#include "hal/nrf5/radio/radio_nrf5_txp.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/swi_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/swi_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/swi_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/nrf5/swi.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/ticker_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/ticker_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/hal/ticker_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/nrf5/ticker.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c	(working copy)
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <device.h>
+#include <drivers/entropy.h>
+#include <drivers/clock_control.h>
+#include <drivers/clock_control/nrf_clock_control.h>
+
+#include <soc.h>
+
+#include "hal/swi.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll
+#include "common/log.h"
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_CTLR_ZLI)
+#define IRQ_CONNECT_FLAGS IRQ_ZERO_LATENCY
+#else
+#define IRQ_CONNECT_FLAGS 0
+#endif
+
+static struct {
+	struct {
+		void              *param;
+		lll_is_abort_cb_t is_abort_cb;
+		lll_abort_cb_t    abort_cb;
+	} curr;
+} event;
+
+/* Entropy device */
+static const struct device *dev_entropy;
+
+static int init_reset(void);
+static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		   lll_prepare_cb_t prepare_cb, int prio,
+		   struct lll_prepare_param *prepare_param, uint8_t is_resume);
+static int resume_enqueue(lll_prepare_cb_t resume_cb, int resume_prio);
+static void isr_race(void *param);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+static void ticker_stop_op_cb(uint32_t status, void *param);
+static void ticker_start_op_cb(uint32_t status, void *param);
+static void preempt_ticker_start(struct lll_prepare_param *prepare_param);
+static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			      uint16_t lazy, void *param);
+static void preempt(void *param);
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void mfy_ticker_job_idle_get(void *param);
+static void ticker_op_job_disable(uint32_t status, void *op_context);
+#endif
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+ISR_DIRECT_DECLARE(radio_nrf5_isr)
+{
+	DEBUG_RADIO_ISR(1);
+
+	isr_radio();
+
+	ISR_DIRECT_PM();
+
+	DEBUG_RADIO_ISR(0);
+	return 1;
+}
+
+static void rtc0_nrf5_isr(const void *arg)
+{
+	DEBUG_TICKER_ISR(1);
+
+	/* On compare0 run ticker worker instance0 */
+	if (NRF_RTC0->EVENTS_COMPARE[0]) {
+		NRF_RTC0->EVENTS_COMPARE[0] = 0;
+
+		ticker_trigger(0);
+	}
+
+	mayfly_run(TICKER_USER_ID_ULL_HIGH);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	mayfly_run(TICKER_USER_ID_ULL_LOW);
+#endif
+
+	DEBUG_TICKER_ISR(0);
+}
+
+static void swi_lll_nrf5_isr(const void *arg)
+{
+	DEBUG_RADIO_ISR(1);
+
+	mayfly_run(TICKER_USER_ID_LLL);
+
+	DEBUG_RADIO_ISR(0);
+}
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void swi_ull_low_nrf5_isr(const void *arg)
+{
+	DEBUG_TICKER_JOB(1);
+
+	mayfly_run(TICKER_USER_ID_ULL_LOW);
+
+	DEBUG_TICKER_JOB(0);
+}
+#endif
+
+int lll_init(void)
+{
+	int err;
+
+	/* Get reference to entropy device */
+	dev_entropy = device_get_binding(DT_LABEL(DT_NODELABEL(rng)));
+	if (!dev_entropy) {
+		return -ENODEV;
+	}
+
+	/* Initialise LLL internals */
+	event.curr.abort_cb = NULL;
+
+	/* Initialize Clocks */
+	err = lll_clock_init();
+	if (err < 0) {
+		return err;
+	}
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	/* Initialize SW IRQ structure */
+	hal_swi_init();
+
+	/* Connect ISRs */
+	IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO,
+			   radio_nrf5_isr, IRQ_CONNECT_FLAGS);
+	IRQ_CONNECT(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO,
+		    rtc0_nrf5_isr, NULL, 0);
+	IRQ_CONNECT(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO,
+		    swi_lll_nrf5_isr, NULL, IRQ_CONNECT_FLAGS);
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	IRQ_CONNECT(HAL_SWI_JOB_IRQ, CONFIG_BT_CTLR_ULL_LOW_PRIO,
+		    swi_ull_low_nrf5_isr, NULL, 0);
+#endif
+
+	/* Enable IRQs */
+	irq_enable(RADIO_IRQn);
+	irq_enable(RTC0_IRQn);
+	irq_enable(HAL_SWI_RADIO_IRQ);
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	irq_enable(HAL_SWI_JOB_IRQ);
+#endif
+
+	return 0;
+}
+
+int lll_csrand_get(void *buf, size_t len)
+{
+	return entropy_get_entropy(dev_entropy, buf, len);
+}
+
+int lll_csrand_isr_get(void *buf, size_t len)
+{
+	return entropy_get_entropy_isr(dev_entropy, buf, len, 0);
+}
+
+int lll_rand_get(void *buf, size_t len)
+{
+	return entropy_get_entropy(dev_entropy, buf, len);
+}
+
+int lll_rand_isr_get(void *buf, size_t len)
+{
+	return entropy_get_entropy_isr(dev_entropy, buf, len, 0);
+}
+
+int lll_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		lll_prepare_cb_t prepare_cb, int prio,
+		struct lll_prepare_param *prepare_param)
+{
+	return prepare(is_abort_cb, abort_cb, prepare_cb, prio, prepare_param,
+		       0);
+}
+
+void lll_resume(void *param)
+{
+	struct lll_event *next;
+	int ret;
+
+	next = param;
+	ret = prepare(next->is_abort_cb, next->abort_cb, next->prepare_cb,
+		      next->prio, &next->prepare_param, next->is_resume);
+	LL_ASSERT(!ret || ret == -EINPROGRESS);
+}
+
+void lll_disable(void *param)
+{
+	/* LLL disable of current event, done is generated */
+	if (!param || (param == event.curr.param)) {
+		if (event.curr.abort_cb && event.curr.param) {
+			event.curr.abort_cb(NULL, event.curr.param);
+		} else {
+			LL_ASSERT(!param);
+		}
+	}
+	{
+		struct lll_event *next;
+		uint8_t idx;
+
+		idx = UINT8_MAX;
+		next = ull_prepare_dequeue_iter(&idx);
+		while (next) {
+			if (!next->is_aborted &&
+			    (!param || (param == next->prepare_param.param))) {
+				next->is_aborted = 1;
+				next->abort_cb(&next->prepare_param,
+					       next->prepare_param.param);
+			}
+
+			next = ull_prepare_dequeue_iter(&idx);
+		}
+	}
+}
+
+int lll_prepare_done(void *param)
+{
+#if defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	    (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, mfy_ticker_job_idle_get};
+	uint32_t ret;
+
+	ret = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW,
+			     1, &mfy);
+	if (ret) {
+		return -EFAULT;
+	}
+
+	return 0;
+#else
+	return 0;
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+}
+
+int lll_done(void *param)
+{
+	struct lll_event *next;
+	struct ull_hdr *ull;
+	void *evdone;
+	int ret = 0;
+
+	/* Assert if param supplied without a pending prepare to cancel. */
+	next = ull_prepare_dequeue_get();
+	LL_ASSERT(!param || next);
+
+	/* check if current LLL event is done */
+	ull = NULL;
+	if (!param) {
+		/* Reset current event instance */
+		LL_ASSERT(event.curr.abort_cb);
+		event.curr.abort_cb = NULL;
+
+		param = event.curr.param;
+		event.curr.param = NULL;
+
+		if (param) {
+			ull = HDR_ULL(((struct lll_hdr *)param)->parent);
+		}
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) &&
+		    (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)) {
+			mayfly_enable(TICKER_USER_ID_LLL,
+				      TICKER_USER_ID_ULL_LOW,
+				      1);
+		}
+
+		DEBUG_RADIO_CLOSE(0);
+	} else {
+		ull = HDR_ULL(((struct lll_hdr *)param)->parent);
+	}
+
+	/* Let ULL know about LLL event done */
+	evdone = ull_event_done(ull);
+	LL_ASSERT(evdone);
+
+	return ret;
+}
+
+bool lll_is_done(void *param)
+{
+	/* FIXME: use param to check */
+	return !event.curr.abort_cb;
+}
+
+int lll_is_abort_cb(void *next, int prio, void *curr,
+			 lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+	return -ECANCELED;
+}
+
+void lll_abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(lll_isr_done, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(param);
+}
+
+uint32_t lll_evt_offset_get(struct evt_hdr *evt)
+{
+	if (0) {
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+	} else if (evt->ticks_xtal_to_start & XON_BITMASK) {
+		return MAX(evt->ticks_active_to_start,
+			   evt->ticks_preempt_to_start);
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	} else {
+		return MAX(evt->ticks_active_to_start,
+			   evt->ticks_xtal_to_start);
+	}
+}
+
+uint32_t lll_preempt_calc(struct evt_hdr *evt, uint8_t ticker_id,
+		       uint32_t ticks_at_event)
+{
+	uint32_t ticks_now;
+	uint32_t diff;
+
+	ticks_now = ticker_ticks_now_get();
+	diff = ticker_ticks_diff_get(ticks_now, ticks_at_event);
+	diff += HAL_TICKER_CNTR_CMP_OFFSET_MIN;
+	if (!(diff & BIT(HAL_TICKER_CNTR_MSBIT)) &&
+	    (diff > HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US))) {
+		/* TODO: for Low Latency Feature with Advanced XTAL feature.
+		 * 1. Release retained HF clock.
+		 * 2. Advance the radio event to accommodate normal prepare
+		 *    duration.
+		 * 3. Increase the preempt to start ticks for future events.
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+void lll_chan_set(uint32_t chan)
+{
+	switch (chan) {
+	case 37:
+		radio_freq_chan_set(2);
+		break;
+
+	case 38:
+		radio_freq_chan_set(26);
+		break;
+
+	case 39:
+		radio_freq_chan_set(80);
+		break;
+
+	default:
+		if (chan < 11) {
+			radio_freq_chan_set(4 + (chan * 2U));
+		} else if (chan < 40) {
+			radio_freq_chan_set(28 + ((chan - 11) * 2U));
+		} else {
+			LL_ASSERT(0);
+		}
+		break;
+	}
+
+	radio_whiten_iv_set(chan);
+}
+
+
+uint32_t lll_radio_is_idle(void)
+{
+	return radio_is_idle();
+}
+
+uint32_t lll_radio_tx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return radio_tx_ready_delay_get(phy, flags);
+}
+
+uint32_t lll_radio_rx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return radio_rx_ready_delay_get(phy, flags);
+}
+
+int8_t lll_radio_tx_pwr_min_get(void)
+{
+	return radio_tx_power_min_get();
+}
+
+int8_t lll_radio_tx_pwr_max_get(void)
+{
+	return radio_tx_power_max_get();
+}
+
+int8_t lll_radio_tx_pwr_floor(int8_t tx_pwr_lvl)
+{
+	return radio_tx_power_floor(tx_pwr_lvl);
+}
+
+void lll_isr_tx_status_reset(void)
+{
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+}
+
+void lll_isr_rx_status_reset(void)
+{
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+}
+
+void lll_isr_status_reset(void)
+{
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+}
+
+inline void lll_isr_abort(void *param)
+{
+	lll_isr_status_reset();
+	lll_isr_cleanup(param);
+}
+
+void lll_isr_done(void *param)
+{
+	lll_isr_abort(param);
+}
+
+void lll_isr_cleanup(void *param)
+{
+	int err;
+
+	radio_isr_set(isr_race, param);
+	if (!radio_is_idle()) {
+		radio_disable();
+	}
+
+	radio_tmr_stop();
+
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(NULL);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		   lll_prepare_cb_t prepare_cb, int prio,
+		   struct lll_prepare_param *prepare_param, uint8_t is_resume)
+{
+	struct lll_event *p;
+	uint8_t idx;
+	int err;
+
+	/* Find the ready prepare in the pipeline */
+	idx = UINT8_MAX;
+	p = ull_prepare_dequeue_iter(&idx);
+	while (p && (p->is_aborted || p->is_resume)) {
+		p = ull_prepare_dequeue_iter(&idx);
+	}
+
+	/* Current event active or another prepare is ready in the pipeline */
+	if (event.curr.abort_cb || (p && is_resume)) {
+#if defined(CONFIG_BT_CTLR_LOW_LAT)
+		lll_prepare_cb_t resume_cb;
+		struct lll_event *next;
+		int resume_prio;
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) && event.curr.param) {
+			/* early abort */
+			event.curr.abort_cb(NULL, event.curr.param);
+		}
+
+		/* Store the next prepare for deferred call */
+		err = ull_prepare_enqueue(is_abort_cb, abort_cb, prepare_param,
+					  prepare_cb, prio, is_resume);
+		LL_ASSERT(!err);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+		if (is_resume) {
+			return -EINPROGRESS;
+		}
+
+		preempt_ticker_start(prepare_param);
+
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+		next = NULL;
+		while (p) {
+			if (!p->is_aborted) {
+				if (event.curr.param ==
+				    p->prepare_param.param) {
+					p->is_aborted = 1;
+					p->abort_cb(&p->prepare_param,
+						    p->prepare_param.param);
+				} else {
+					next = p;
+				}
+			}
+
+			p = ull_prepare_dequeue_iter(&idx);
+		}
+
+		if (next) {
+			/* check if resume requested by curr */
+			err = event.curr.is_abort_cb(NULL, 0, event.curr.param,
+						     &resume_cb, &resume_prio);
+			LL_ASSERT(err);
+
+			if (err == -EAGAIN) {
+				err = resume_enqueue(resume_cb, resume_prio);
+				LL_ASSERT(!err);
+			} else {
+				LL_ASSERT(err == -ECANCELED);
+			}
+		}
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+		return -EINPROGRESS;
+	}
+
+	event.curr.param = prepare_param->param;
+	event.curr.is_abort_cb = is_abort_cb;
+	event.curr.abort_cb = abort_cb;
+
+	err = prepare_cb(prepare_param);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+	uint32_t ret;
+
+	/* Stop any scheduled preempt ticker */
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR,
+			  TICKER_USER_ID_LLL,
+			  TICKER_ID_LLL_PREEMPT,
+			  ticker_stop_op_cb, NULL);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_FAILURE) ||
+		  (ret == TICKER_STATUS_BUSY));
+#endif /* !CONFIG_BT_CTLR_LOW_LAT */
+
+	return err;
+}
+
+static int resume_enqueue(lll_prepare_cb_t resume_cb, int resume_prio)
+{
+	struct lll_prepare_param prepare_param;
+
+	prepare_param.param = event.curr.param;
+	event.curr.param = NULL;
+
+	return ull_prepare_enqueue(event.curr.is_abort_cb, event.curr.abort_cb,
+				   &prepare_param, resume_cb, resume_prio, 1);
+}
+
+static void isr_race(void *param)
+{
+	/* NOTE: lll_disable could have a race with ... */
+	radio_status_reset();
+}
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+static void ticker_stop_op_cb(uint32_t status, void *param)
+{
+	/* NOTE: this callback is present only for addition of debug messages
+	 * when needed, else can be dispensed with.
+	 */
+	ARG_UNUSED(param);
+
+	LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
+		  (status == TICKER_STATUS_FAILURE));
+}
+
+static void ticker_start_op_cb(uint32_t status, void *param)
+{
+	/* NOTE: this callback is present only for addition of debug messages
+	 * when needed, else can be dispensed with.
+	 */
+	ARG_UNUSED(param);
+
+	LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
+		  (status == TICKER_STATUS_FAILURE));
+}
+
+static void preempt_ticker_start(struct lll_prepare_param *prepare_param)
+{
+	uint32_t preempt_anchor;
+	struct evt_hdr *evt;
+	uint32_t preempt_to;
+	uint32_t ret;
+
+	/* Calc the preempt timeout */
+	evt = HDR_LLL2EVT(prepare_param->param);
+	preempt_anchor = prepare_param->ticks_at_expire;
+	preempt_to = MAX(evt->ticks_active_to_start,
+			 evt->ticks_xtal_to_start) -
+			 evt->ticks_preempt_to_start;
+
+	/* Setup pre empt timeout */
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+			   TICKER_USER_ID_LLL,
+			   TICKER_ID_LLL_PREEMPT,
+			   preempt_anchor,
+			   preempt_to,
+			   TICKER_NULL_PERIOD,
+			   TICKER_NULL_REMAINDER,
+			   TICKER_NULL_LAZY,
+			   TICKER_NULL_SLOT,
+			   preempt_ticker_cb, NULL,
+			   ticker_start_op_cb, NULL);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_FAILURE) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			       uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, preempt};
+	uint32_t ret;
+
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!ret);
+}
+
+static void preempt(void *param)
+{
+	lll_prepare_cb_t resume_cb;
+	struct lll_event *next;
+	int resume_prio;
+	uint8_t idx;
+	int ret;
+
+	if (!event.curr.abort_cb || !event.curr.param) {
+		return;
+	}
+
+	idx = UINT8_MAX;
+	next = ull_prepare_dequeue_iter(&idx);
+	if (!next) {
+		return;
+	}
+
+	while (next && (next->is_aborted || next->is_resume)) {
+		next = ull_prepare_dequeue_iter(&idx);
+	}
+
+	if (!next) {
+		return;
+	}
+
+	ret = event.curr.is_abort_cb(next->prepare_param.param, next->prio,
+				     event.curr.param,
+				     &resume_cb, &resume_prio);
+	if (!ret) {
+		/* Let LLL know about the cancelled prepare */
+		next->is_aborted = 1;
+		next->abort_cb(&next->prepare_param, next->prepare_param.param);
+
+		goto preempt_next;
+	}
+
+	event.curr.abort_cb(NULL, event.curr.param);
+
+	if (ret == -EAGAIN) {
+		struct lll_event *iter;
+		uint8_t iter_idx;
+
+		iter_idx = UINT8_MAX;
+		iter = ull_prepare_dequeue_iter(&iter_idx);
+		while (iter) {
+			if (!iter->is_aborted &&
+			    event.curr.param == iter->prepare_param.param) {
+				iter->is_aborted = 1;
+				iter->abort_cb(&iter->prepare_param,
+					       iter->prepare_param.param);
+			}
+
+			iter = ull_prepare_dequeue_iter(&iter_idx);
+		}
+
+		ret = resume_enqueue(resume_cb, resume_prio);
+		LL_ASSERT(!ret);
+	} else {
+		LL_ASSERT(ret == -ECANCELED);
+	}
+
+preempt_next:
+	do {
+		next = ull_prepare_dequeue_iter(&idx);
+		if (!next) {
+			return;
+		}
+	} while (next->is_aborted || next->is_resume);
+
+	preempt_ticker_start(&next->prepare_param);
+}
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void mfy_ticker_job_idle_get(void *param)
+{
+	uint32_t ret;
+
+	/* Ticker Job Silence */
+	ret = ticker_job_idle_get(TICKER_INSTANCE_ID_CTLR,
+				  TICKER_USER_ID_ULL_LOW,
+				  ticker_op_job_disable, NULL);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+static void ticker_op_job_disable(uint32_t status, void *op_context)
+{
+	ARG_UNUSED(status);
+	ARG_UNUSED(op_context);
+
+	/* FIXME: */
+	if (1 /* _radio.state != STATE_NONE */) {
+		mayfly_enable(TICKER_USER_ID_ULL_LOW,
+			      TICKER_USER_ID_ULL_LOW, 0);
+	}
+}
+#endif
+
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h	(working copy)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct lll_adv_pdu {
+	uint8_t volatile first;
+	uint8_t          last;
+	/* TODO: use,
+	 * struct pdu_adv *pdu[DOUBLE_BUFFER_SIZE];
+	 */
+	uint8_t pdu[DOUBLE_BUFFER_SIZE][PDU_AC_LL_SIZE_MAX];
+};
+
+struct lll_adv_aux {
+	struct lll_hdr hdr;
+	struct lll_adv *adv;
+
+	uint32_t ticks_offset;
+
+	struct lll_adv_pdu data;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+};
+
+struct lll_adv_sync {
+	struct lll_hdr hdr;
+	struct lll_adv *adv;
+
+	uint8_t access_addr[4];
+	uint8_t crc_init[3];
+
+	uint16_t latency_prepare;
+	uint16_t latency_event;
+	uint16_t event_counter;
+
+	uint8_t data_chan_map[5];
+	uint8_t data_chan_count:6;
+	uint16_t data_chan_id;
+
+	uint32_t ticks_offset;
+
+	struct lll_adv_pdu data;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+};
+
+struct lll_adv {
+	struct lll_hdr hdr;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	/* NOTE: conn context has to be after lll_hdr */
+	struct lll_conn *conn;
+	uint8_t is_hdcd:1;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	uint8_t chan_map:3;
+	uint8_t chan_map_curr:3;
+	uint8_t filter_policy:2;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint8_t phy_p:3;
+	uint8_t phy_s:3;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	uint8_t scan_req_notify:1;
+#endif
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	uint8_t is_mesh:1;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	struct lll_adv_pdu adv_data;
+	struct lll_adv_pdu scan_rsp;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	struct lll_adv_aux *aux;
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	struct lll_adv_sync *sync;
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	int8_t tx_pwr_lvl;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	struct node_rx_hdr *node_rx_adv_term;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+};
+
+int lll_adv_init(void);
+int lll_adv_reset(void);
+
+void lll_adv_prepare(void *param);
+
+static inline struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu,
+						uint8_t *idx)
+{
+	uint8_t first, last;
+
+	first = pdu->first;
+	last = pdu->last;
+	if (first == last) {
+		last++;
+		if (last == DOUBLE_BUFFER_SIZE) {
+			last = 0U;
+		}
+	} else {
+		uint8_t first_latest;
+
+		pdu->last = first;
+		cpu_dsb();
+		first_latest = pdu->first;
+		if (first_latest != first) {
+			last++;
+			if (last == DOUBLE_BUFFER_SIZE) {
+				last = 0U;
+			}
+		}
+	}
+
+	*idx = last;
+
+	return (void *)pdu->pdu[last];
+}
+
+static inline void lll_adv_pdu_enqueue(struct lll_adv_pdu *pdu, uint8_t idx)
+{
+	pdu->last = idx;
+}
+
+static inline struct pdu_adv *lll_adv_data_alloc(struct lll_adv *lll, uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->adv_data, idx);
+}
+
+static inline void lll_adv_data_enqueue(struct lll_adv *lll, uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->adv_data, idx);
+}
+
+static inline struct pdu_adv *lll_adv_data_peek(struct lll_adv *lll)
+{
+	return (void *)lll->adv_data.pdu[lll->adv_data.last];
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_alloc(struct lll_adv *lll,
+						     uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->scan_rsp, idx);
+}
+
+static inline void lll_adv_scan_rsp_enqueue(struct lll_adv *lll, uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->scan_rsp, idx);
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_peek(struct lll_adv *lll)
+{
+	return (void *)lll->scan_rsp.pdu[lll->scan_rsp.last];
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static inline struct pdu_adv *lll_adv_aux_data_alloc(struct lll_adv_aux *lll,
+						     uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->data, idx);
+}
+
+static inline void lll_adv_aux_data_enqueue(struct lll_adv_aux *lll,
+					    uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->data, idx);
+}
+
+static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv_aux *lll)
+{
+	return (void *)lll->data.pdu[lll->data.last];
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+static inline struct pdu_adv *lll_adv_sync_data_alloc(struct lll_adv_sync *lll,
+						     uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->data, idx);
+}
+
+static inline void lll_adv_sync_data_enqueue(struct lll_adv_sync *lll,
+					     uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->data, idx);
+}
+
+static inline struct pdu_adv *lll_adv_sync_data_peek(struct lll_adv_sync *lll)
+{
+	return (void *)lll->data.pdu[lll->data.last];
+}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+extern uint16_t ull_adv_lll_handle_get(struct lll_adv *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c	(working copy)
@@ -0,0 +1,889 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_adv.h"
+#include "lll_adv_aux.h"
+#include "lll_conn.h"
+#include "lll_chan.h"
+#include "lll_filter.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_adv_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_adv
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio);
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
+static void isr_tx(void *param);
+static void isr_rx(void *param);
+static void isr_done(void *param);
+static void isr_abort(void *param);
+static struct pdu_adv *chan_prepare(struct lll_adv *lll);
+
+static inline int isr_rx_pdu(struct lll_adv *lll,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready);
+static bool isr_rx_sr_adva_check(uint8_t tx_addr, uint8_t *addr,
+				 struct pdu_adv *sr);
+
+
+static inline bool isr_rx_ci_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *ci, uint8_t devmatch_ok,
+				   uint8_t *rl_idx);
+static inline bool isr_rx_ci_tgta_check(struct lll_adv *lll,
+					struct pdu_adv *adv, struct pdu_adv *ci,
+					uint8_t rl_idx);
+static inline bool isr_rx_ci_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *ci);
+
+int lll_adv_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_adv_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_adv_prepare(void *param)
+{
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+bool lll_adv_scan_req_check(struct lll_adv *lll, struct pdu_adv *sr,
+			    uint8_t tx_addr, uint8_t *addr,
+			    uint8_t devmatch_ok, uint8_t *rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return ((((lll->filter_policy & 0x01) == 0) &&
+		 ull_filter_lll_rl_addr_allowed(sr->tx_addr,
+						sr->scan_req.scan_addr,
+						rl_idx)) ||
+		(((lll->filter_policy & 0x01) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(*rl_idx)))) &&
+		isr_rx_sr_adva_check(tx_addr, addr, sr);
+#else
+	return (((lll->filter_policy & 0x01) == 0U) || devmatch_ok) &&
+		isr_rx_sr_adva_check(tx_addr, addr, sr);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+int lll_adv_scan_req_report(struct lll_adv *lll, struct pdu_adv *pdu_adv_rx,
+			    uint8_t rl_idx, uint8_t rssi_ready)
+{
+	struct node_rx_pdu *node_rx;
+	struct pdu_adv *pdu_adv;
+	uint8_t pdu_len;
+
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (!node_rx) {
+		return -ENOBUFS;
+	}
+	ull_pdu_rx_alloc();
+
+	/* Prepare the report (scan req) */
+	node_rx->hdr.type = NODE_RX_TYPE_SCAN_REQ;
+	node_rx->hdr.handle = ull_adv_lll_handle_get(lll);
+
+	/* Make a copy of PDU into Rx node (as the received PDU is in the
+	 * scratch buffer), and save the RSSI value.
+	 */
+	pdu_adv = (void *)node_rx->pdu;
+	pdu_len = offsetof(struct pdu_adv, payload) + pdu_adv_rx->len;
+	memcpy(pdu_adv, pdu_adv_rx, pdu_len);
+
+	node_rx->hdr.rx_ftr.rssi = (rssi_ready) ? (radio_rssi_get() & 0x7f) :
+						  0x7f;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	node_rx->hdr.rx_ftr.rl_idx = rl_idx;
+#endif
+
+	ull_rx_put(node_rx->hdr.link, node_rx);
+	ull_rx_sched();
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	struct pdu_adv *pdu;
+	struct evt_hdr *evt;
+	struct lll_adv *lll;
+	uint32_t remainder;
+	uint32_t start_us;
+	uint32_t aa;
+
+	DEBUG_RADIO_START_A(1);
+
+	lll = p->param;
+
+	/* Check if stopped (on connection establishment race between LLL and
+	 * ULL.
+	 */
+	if (unlikely(lll_is_stop(lll))) {
+		int err;
+
+		err = lll_hfclock_off();
+		LL_ASSERT(err >= 0);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_CLOSE_A(0);
+		return 0;
+	}
+
+	radio_reset();
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	/* TODO: if coded we use S8? */
+	radio_phy_set(lll->phy_p, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy_p << 1));
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	radio_phy_set(0, 0);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, 0);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+
+	lll->chan_map_curr = lll->chan_map;
+
+	pdu = chan_prepare(lll);
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	_radio.mesh_adv_end_us = 0;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		struct lll_filter *filter =
+			ull_filter_lll_get(!!(lll->filter_policy));
+
+		radio_filter_configure(filter->enable_bitmask,
+				       filter->addr_type_bitmask,
+				       (uint8_t *)filter->bdaddr);
+	} else
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_FILTER) && lll->filter_policy) {
+		/* Setup Radio Filter */
+		struct lll_filter *wl = ull_filter_lll_get(true);
+
+
+		radio_filter_configure(wl->enable_bitmask,
+				       wl->addr_type_bitmask,
+				       (uint8_t *)wl->bdaddr);
+	}
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	start_us = radio_tmr_start(1, ticks_at_start, remainder);
+
+	/* capture end of Tx-ed PDU, used to calculate HCTO. */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(start_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_ADV_BASE +
+				   ull_adv_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_A(1);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static int resume_prepare_cb(struct lll_prepare_param *p)
+{
+	struct evt_hdr *evt;
+
+	evt = HDR_LLL2EVT(p->param);
+	p->ticks_at_expire = ticker_ticks_now_get() - lll_evt_offset_get(evt);
+	p->remainder = 0;
+	p->lazy = 0;
+
+	return prepare_cb(p);
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+#if defined(CONFIG_BT_PERIPHERAL)
+	struct lll_adv *lll = curr;
+	struct pdu_adv *pdu;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	/* TODO: prio check */
+	if (next != curr) {
+		if (0) {
+#if defined(CONFIG_BT_PERIPHERAL)
+		} else if (lll->is_hdcd) {
+			int err;
+
+			/* wrap back after the pre-empter */
+			*resume_cb = resume_prepare_cb;
+			*resume_prio = 0; /* TODO: */
+
+			/* Retain HF clk */
+			err = lll_hfclock_on();
+			LL_ASSERT(err >= 0);
+
+			return -EAGAIN;
+#endif /* CONFIG_BT_PERIPHERAL */
+		} else {
+			return -ECANCELED;
+		}
+	}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	pdu = lll_adv_data_curr_get(lll);
+	if (pdu->type == PDU_ADV_TYPE_DIRECT_IND) {
+		return 0;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return -ECANCELED;
+}
+
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_abort, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(param);
+}
+
+static void isr_tx(void *param)
+{
+	uint32_t hcto;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Clear radio tx status and events */
+	lll_isr_tx_status_reset();
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	radio_pkt_rx_set(radio_pkt_scratch_get());
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_cputime_capture();
+	}
+
+	radio_isr_set(isr_rx, param);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 + 1;
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+	radio_tmr_hcto_configure(hcto);
+
+	/* capture end of CONNECT_IND PDU, used for calculating first
+	 * slave event.
+	 */
+	radio_tmr_end_capture();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_SCAN_REQ_RSSI) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_CONN_RSSI)) {
+		radio_rssi_measure();
+	}
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* PA/LNA enable is overwriting packet end used in ISR
+		 * profiling, hence back it up for later use.
+		 */
+		lll_prof_radio_end_backup();
+	}
+
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* NOTE: as scratch packet is used to receive, it is safe to
+		 * generate profile event using rx nodes.
+		 */
+		lll_prof_send();
+	}
+}
+
+static void isr_rx(void *param)
+{
+	uint8_t devmatch_ok;
+	uint8_t devmatch_id;
+	uint8_t irkmatch_ok;
+	uint8_t irkmatch_id;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t crc_ok;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		devmatch_ok = radio_filter_has_match();
+		devmatch_id = radio_filter_match_get();
+		irkmatch_ok = radio_ar_has_match();
+		irkmatch_id = radio_ar_match_get();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = devmatch_ok = irkmatch_ok = rssi_ready = 0U;
+		devmatch_id = irkmatch_id = 0xFF;
+	}
+
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	/* No Rx */
+	if (!trx_done) {
+		goto isr_rx_do_close;
+	}
+
+	if (crc_ok) {
+		int err;
+
+		err = isr_rx_pdu(param, devmatch_ok, devmatch_id, irkmatch_ok,
+				 irkmatch_id, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(isr_done, param);
+	radio_disable();
+}
+
+static void isr_done(void *param)
+{
+	struct node_rx_hdr *node_rx;
+	struct lll_adv *lll;
+
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (_radio.advertiser.is_mesh &&
+	    !_radio.mesh_adv_end_us) {
+		_radio.mesh_adv_end_us = radio_tmr_end_get();
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+	lll = param;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) && lll->is_hdcd &&
+	    !lll->chan_map_curr) {
+		lll->chan_map_curr = lll->chan_map;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	if (lll->chan_map_curr) {
+		struct pdu_adv *pdu;
+		uint32_t start_us;
+
+		pdu = chan_prepare(lll);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || defined(CONFIG_BT_CTLR_ADV_EXT)
+		start_us = radio_tmr_start_now(1);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		if (lll->aux) {
+			ull_adv_aux_lll_offset_fill(lll->aux->ticks_offset,
+						    start_us, pdu);
+		}
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+		ARG_UNUSED(pdu);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(start_us +
+					 radio_tx_ready_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+#else /* !(CONFIG_BT_CTLR_GPIO_PA_PIN || defined(CONFIG_BT_CTLR_ADV_EXT)) */
+		ARG_UNUSED(start_us);
+
+		radio_tx_enable();
+#endif /* !(CONFIG_BT_CTLR_GPIO_PA_PIN || defined(CONFIG_BT_CTLR_ADV_EXT)) */
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+
+		return;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(BT_CTLR_ADV_EXT_PBACK)
+	} else {
+		struct pdu_adv_com_ext_adv *p;
+		struct pdu_adv_hdr *h;
+		struct pdu_adv *pdu;
+
+		pdu = lll_adv_data_curr_get(lll);
+		p = (void *)&pdu->adv_ext_ind;
+		h = (void *)p->ext_hdr_adi_adv_data;
+
+		if ((pdu->type == PDU_ADV_TYPE_EXT_IND) && h->aux_ptr) {
+			radio_filter_disable();
+
+			lll_adv_aux_pback_prepare(lll);
+
+			return;
+		}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	}
+
+	radio_filter_disable();
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!lll->is_hdcd)
+#endif /* CONFIG_BT_PERIPHERAL */
+	{
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+		if (_radio.advertiser.is_mesh) {
+			uint32_t err;
+
+			err = isr_close_adv_mesh();
+			if (err) {
+				return 0;
+			}
+		}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (node_rx) {
+		ull_pdu_rx_alloc();
+
+		/* TODO: add other info by defining a payload struct */
+		node_rx->type = NODE_RX_TYPE_ADV_INDICATION;
+
+		ull_rx_put(node_rx->link, node_rx);
+		ull_rx_sched();
+	}
+#else /* !CONFIG_BT_CTLR_ADV_INDICATION */
+	ARG_UNUSED(node_rx);
+#endif /* !CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	struct event_done_extra *extra;
+
+	extra = ull_event_done_extra_get();
+	LL_ASSERT(extra);
+
+	extra->type = EVENT_DONE_EXTRA_TYPE_ADV;
+#endif  /* CONFIG_BT_CTLR_ADV_EXT */
+
+	lll_isr_cleanup(param);
+}
+
+static void isr_abort(void *param)
+{
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	radio_filter_disable();
+
+	lll_isr_cleanup(param);
+}
+
+static struct pdu_adv *chan_prepare(struct lll_adv *lll)
+{
+	struct pdu_adv *pdu;
+	uint8_t chan;
+	uint8_t upd;
+
+	chan = find_lsb_set(lll->chan_map_curr);
+	LL_ASSERT(chan);
+
+	lll->chan_map_curr &= (lll->chan_map_curr - 1);
+
+	lll_chan_set(36 + chan);
+
+	/* FIXME: get latest only when primary PDU without Aux PDUs */
+	upd = 0U;
+	pdu = lll_adv_data_latest_get(lll, &upd);
+
+	radio_pkt_tx_set(pdu);
+
+	if ((pdu->type != PDU_ADV_TYPE_NONCONN_IND) &&
+	    (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) ||
+	     (pdu->type != PDU_ADV_TYPE_EXT_IND))) {
+		struct pdu_adv *scan_pdu;
+
+		scan_pdu = lll_adv_scan_rsp_latest_get(lll, &upd);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		if (upd) {
+			/* Copy the address from the adv packet we will send
+			 * into the scan response.
+			 */
+			memcpy(&scan_pdu->scan_rsp.addr[0],
+			       &pdu->adv_ind.addr[0], BDADDR_SIZE);
+		}
+#else
+		ARG_UNUSED(scan_pdu);
+		ARG_UNUSED(upd);
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+		radio_isr_set(isr_tx, lll);
+		radio_tmr_tifs_set(EVENT_IFS_US);
+		radio_switch_complete_and_rx(0);
+	} else {
+		radio_isr_set(isr_done, lll);
+		radio_switch_complete_and_disable();
+	}
+
+	return pdu;
+}
+
+static inline int isr_rx_pdu(struct lll_adv *lll,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready)
+{
+	struct pdu_adv *pdu_adv;
+	struct pdu_adv *pdu_rx;
+	uint8_t tx_addr;
+	uint8_t *addr;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* An IRK match implies address resolution enabled */
+	uint8_t rl_idx = irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
+				    FILTER_IDX_NONE;
+#else
+	uint8_t rl_idx = FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	pdu_rx = (void *)radio_pkt_scratch_get();
+	pdu_adv = lll_adv_data_curr_get(lll);
+
+	addr = pdu_adv->adv_ind.addr;
+	tx_addr = pdu_adv->tx_addr;
+
+	if ((pdu_rx->type == PDU_ADV_TYPE_SCAN_REQ) &&
+	    (pdu_rx->len == sizeof(struct pdu_adv_scan_req)) &&
+	    (pdu_adv->type != PDU_ADV_TYPE_DIRECT_IND) &&
+	    lll_adv_scan_req_check(lll, pdu_rx, tx_addr, addr, devmatch_ok,
+				    &rl_idx)) {
+		radio_isr_set(isr_done, lll);
+		radio_switch_complete_and_disable();
+		radio_pkt_tx_set(lll_adv_scan_rsp_curr_get(lll));
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+		if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) ||
+		    lll->scan_req_notify) {
+			uint32_t err;
+
+			/* Generate the scan request event */
+			err = lll_adv_scan_req_report(lll, pdu_rx, rl_idx,
+						      rssi_ready);
+			if (err) {
+				/* Scan Response will not be transmitted */
+				return err;
+			}
+		}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end used in ISR
+			 * profiling, hence back it up for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+		return 0;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	} else if ((pdu_rx->type == PDU_ADV_TYPE_CONNECT_IND) &&
+		   (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
+		   isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
+				   &rl_idx) &&
+		   lll->conn) {
+		struct node_rx_ftr *ftr;
+		struct node_rx_pdu *rx;
+		int ret;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			rx = ull_pdu_rx_alloc_peek(4);
+		} else {
+			rx = ull_pdu_rx_alloc_peek(3);
+		}
+
+		if (!rx) {
+			return -ENOBUFS;
+		}
+
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+
+		/* assert if radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		if (rssi_ready) {
+			lll->conn->rssi_latest =  radio_rssi_get();
+		}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+		/* Stop further LLL radio events */
+		ret = lll_stop(lll);
+		LL_ASSERT(!ret);
+
+		rx = ull_pdu_rx_alloc();
+
+		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+		rx->hdr.handle = 0xffff;
+
+		memcpy(rx->pdu, pdu_rx, (offsetof(struct pdu_adv, connect_ind) +
+					 sizeof(struct pdu_adv_connect_ind)));
+
+		ftr = &(rx->hdr.rx_ftr);
+		ftr->param = lll;
+		ftr->ticks_anchor = radio_tmr_start_get();
+		ftr->radio_end_us = radio_tmr_end_get() -
+				    radio_tx_chain_delay_get(0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			ftr->extra = ull_pdu_rx_alloc();
+		}
+
+		ull_rx_put(rx->hdr.link, rx);
+		ull_rx_sched();
+
+		return 0;
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+
+	return -EINVAL;
+}
+
+static bool isr_rx_sr_adva_check(uint8_t tx_addr, uint8_t *addr,
+				 struct pdu_adv *sr)
+{
+	return (tx_addr == sr->rx_addr) &&
+		!memcmp(addr, sr->scan_req.adv_addr, BDADDR_SIZE);
+}
+
+static inline bool isr_rx_ci_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *ci, uint8_t devmatch_ok,
+				   uint8_t *rl_idx)
+{
+	/* LL 4.3.2: filter policy shall be ignored for directed adv */
+	if (adv->type == PDU_ADV_TYPE_DIRECT_IND) {
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		return ull_filter_lll_rl_addr_allowed(ci->tx_addr,
+						      ci->connect_ind.init_addr,
+						      rl_idx) &&
+#else
+		return (1) &&
+#endif
+		       isr_rx_ci_adva_check(adv, ci) &&
+		       isr_rx_ci_tgta_check(lll, adv, ci, *rl_idx);
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return ((((lll->filter_policy & 0x02) == 0) &&
+		 ull_filter_lll_rl_addr_allowed(ci->tx_addr,
+						ci->connect_ind.init_addr,
+						rl_idx)) ||
+		(((lll->filter_policy & 0x02) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(*rl_idx)))) &&
+	       isr_rx_ci_adva_check(adv, ci);
+#else
+	return (((lll->filter_policy & 0x02) == 0) ||
+		(devmatch_ok)) &&
+	       isr_rx_ci_adva_check(adv, ci);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+static inline bool isr_rx_ci_tgta_check(struct lll_adv *lll,
+					struct pdu_adv *adv, struct pdu_adv *ci,
+					uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (rl_idx != FILTER_IDX_NONE && lll->rl_idx != FILTER_IDX_NONE) {
+		return rl_idx == lll->rl_idx;
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	return (adv->rx_addr == ci->tx_addr) &&
+	       !memcmp(adv->direct_ind.tgt_addr, ci->connect_ind.init_addr,
+		       BDADDR_SIZE);
+}
+
+static inline bool isr_rx_ci_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *ci)
+{
+	return (adv->tx_addr == ci->rx_addr) &&
+		(((adv->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		 !memcmp(adv->direct_ind.adv_addr, ci->connect_ind.adv_addr,
+			 BDADDR_SIZE)) ||
+		 (!memcmp(adv->adv_ind.addr, ci->connect_ind.adv_addr,
+			  BDADDR_SIZE)));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.h	(working copy)
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_adv_aux_init(void);
+int lll_adv_aux_reset(void);
+void lll_adv_aux_prepare(void *param);
+
+extern uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll);
+extern struct pdu_adv_aux_ptr *
+ull_adv_aux_lll_offset_fill(uint32_t ticks_offset, uint32_t start_us,
+			    struct pdu_adv *pdu);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_aux.c	(working copy)
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <sys/byteorder.h>
+#include <bluetooth/hci.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_chan.h"
+#include "lll_adv.h"
+#include "lll_adv_aux.h"
+#include "lll_filter.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_adv_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_adv_aux
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+static void isr_tx(void *param);
+static void isr_rx(void *param);
+static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready);
+
+int lll_adv_aux_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_adv_aux_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_adv_aux_prepare(void *param)
+{
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0, param);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+void lll_adv_aux_pback_prepare(void *param)
+{
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	struct pdu_adv_com_ext_adv *pri_com_hdr;
+	uint32_t ticks_at_event, ticks_at_start;
+	struct pdu_adv *pri_pdu, *sec_pdu;
+	struct pdu_adv_aux_ptr *aux_ptr;
+	struct pdu_adv_hdr *pri_hdr;
+	struct lll_adv_aux *lll;
+	struct lll_adv *lll_adv;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+	uint32_t start_us;
+	uint8_t *pri_dptr;
+	uint8_t phy_s;
+	uint8_t upd;
+	uint32_t aa;
+
+	DEBUG_RADIO_START_A(1);
+
+#if !defined(BT_CTLR_ADV_EXT_PBACK)
+	/* Set up Radio H/W */
+	radio_reset();
+#endif  /* !BT_CTLR_ADV_EXT_PBACK */
+
+	lll = p->param;
+
+	/* FIXME: get latest only when primary PDU without Aux PDUs */
+	sec_pdu = lll_adv_aux_data_latest_get(lll, &upd);
+
+	/* Get reference to primary PDU */
+	lll_adv = lll->adv;
+	pri_pdu = lll_adv_data_curr_get(lll_adv);
+	LL_ASSERT(pri_pdu->type == PDU_ADV_TYPE_EXT_IND);
+
+	/* Get reference to extended header */
+	pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
+	pri_hdr = (void *)pri_com_hdr->ext_hdr_adi_adv_data;
+	pri_dptr = (uint8_t *)pri_hdr + sizeof(*pri_hdr);
+
+	/* traverse through adv_addr, if present */
+	if (pri_hdr->adv_addr) {
+		pri_dptr += BDADDR_SIZE;
+	}
+
+	/* traverse through adi, if present */
+	if (pri_hdr->adi) {
+		pri_dptr += sizeof(struct pdu_adv_adi);
+	}
+
+	aux_ptr = (void *)pri_dptr;
+
+	/* Abort if no aux_ptr filled */
+	if (unlikely(!pri_hdr->aux_ptr || !aux_ptr->offs)) {
+		int err;
+
+		err = lll_hfclock_off();
+		LL_ASSERT(err >= 0);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_CLOSE_A(0);
+		return 0;
+	}
+
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	phy_s = lll_adv->phy_s;
+
+	/* TODO: if coded we use S8? */
+	radio_phy_set(phy_s, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (phy_s << 1));
+
+#if !defined(BT_CTLR_ADV_EXT_PBACK)
+	/* Access address and CRC */
+	aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+#endif  /* !BT_CTLR_ADV_EXT_PBACK */
+
+	/* Use channel idx in aux_ptr */
+	lll_chan_set(aux_ptr->chan_idx);
+
+	/* Set the Radio Tx Packet */
+	radio_pkt_tx_set(sec_pdu);
+
+	/* Switch to Rx if connectable or scannable */
+	if (pri_com_hdr->adv_mode & (BT_HCI_LE_ADV_PROP_CONN |
+				     BT_HCI_LE_ADV_PROP_SCAN)) {
+
+		struct pdu_adv *scan_pdu;
+
+		scan_pdu = lll_adv_scan_rsp_latest_get(lll_adv, &upd);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		if (upd) {
+			/* Copy the address from the adv packet we will send
+			 * into the scan response.
+			 */
+			memcpy(&scan_pdu->adv_ext_ind.ext_hdr_adi_adv_data[1],
+			       &sec_pdu->adv_ext_ind.ext_hdr_adi_adv_data[1],
+			       BDADDR_SIZE);
+		}
+#else
+		ARG_UNUSED(scan_pdu);
+		ARG_UNUSED(upd);
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+		radio_isr_set(isr_tx, lll);
+		radio_tmr_tifs_set(EVENT_IFS_US);
+		radio_switch_complete_and_rx(phy_s);
+	} else {
+		radio_isr_set(lll_isr_done, lll);
+		radio_switch_complete_and_disable();
+	}
+
+#if defined(BT_CTLR_ADV_EXT_PBACK)
+	start_us = 1000;
+	radio_tmr_start_us(1, start_us);
+#else /* !BT_CTLR_ADV_EXT_PBACK */
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	start_us = radio_tmr_start(1, ticks_at_start, remainder);
+#endif /* !BT_CTLR_ADV_EXT_PBACK */
+
+	/* capture end of Tx-ed PDU, used to calculate HCTO. */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(phy_s, 1) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(start_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_ADV_AUX_BASE +
+				   ull_adv_aux_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(lll_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_A(1);
+
+	return 0;
+}
+
+static void isr_tx(void *param)
+{
+	struct lll_adv_aux *lll_aux;
+	struct lll_adv *lll;
+	uint32_t hcto;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Clear radio tx status and events */
+	lll_isr_tx_status_reset();
+
+	lll_aux = param;
+	lll = lll_aux->adv;
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(lll->phy_s, 0, lll->phy_s, 0);
+
+	radio_pkt_rx_set(radio_pkt_scratch_get());
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_cputime_capture();
+	}
+
+	radio_isr_set(isr_rx, param);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 + 1;
+	hcto += radio_rx_chain_delay_get(lll->phy_s, 1);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(lll->phy_s, 0);
+	radio_tmr_hcto_configure(hcto);
+
+	/* capture end of CONNECT_IND PDU, used for calculating first
+	 * slave event.
+	 */
+	radio_tmr_end_capture();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_SCAN_REQ_RSSI) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_CONN_RSSI)) {
+		radio_rssi_measure();
+	}
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* PA/LNA enable is overwriting packet end used in ISR
+		 * profiling, hence back it up for later use.
+		 */
+		lll_prof_radio_end_backup();
+	}
+
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* NOTE: as scratch packet is used to receive, it is safe to
+		 * generate profile event using rx nodes.
+		 */
+		lll_prof_send();
+	}
+}
+
+static void isr_rx(void *param)
+{
+	uint8_t devmatch_ok;
+	uint8_t devmatch_id;
+	uint8_t irkmatch_ok;
+	uint8_t irkmatch_id;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t crc_ok;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		devmatch_ok = radio_filter_has_match();
+		devmatch_id = radio_filter_match_get();
+		irkmatch_ok = radio_ar_has_match();
+		irkmatch_id = radio_ar_match_get();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = devmatch_ok = irkmatch_ok = rssi_ready = 0U;
+		devmatch_id = irkmatch_id = 0xFF;
+	}
+
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	/* No Rx */
+	if (!trx_done) {
+		goto isr_rx_do_close;
+	}
+
+	if (crc_ok) {
+		int err;
+
+		err = isr_rx_pdu(param, devmatch_ok, devmatch_id,
+				 irkmatch_ok, irkmatch_id, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(lll_isr_done, param);
+	radio_disable();
+}
+
+static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready)
+{
+	struct pdu_adv *pdu_adv;
+	struct pdu_adv *pdu_aux;
+	struct pdu_adv *pdu_rx;
+	struct lll_adv *lll;
+	uint8_t tx_addr;
+	uint8_t *addr;
+	uint8_t upd;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* An IRK match implies address resolution enabled */
+	uint8_t rl_idx = irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
+				    FILTER_IDX_NONE;
+#else
+	uint8_t rl_idx = FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	lll = lll_aux->adv;
+
+	pdu_rx = (void *)radio_pkt_scratch_get();
+	pdu_adv = lll_adv_data_curr_get(lll);
+	pdu_aux = lll_adv_aux_data_latest_get(lll_aux, &upd);
+
+	if (pdu_adv->type == PDU_ADV_TYPE_EXT_IND) {
+		/* AdvA is placed at 2nd byte of ext hdr data */
+		addr = &pdu_aux->adv_ext_ind.ext_hdr_adi_adv_data[1];
+		tx_addr = pdu_aux->tx_addr;
+	} else {
+		addr = pdu_adv->adv_ind.addr;
+		tx_addr = pdu_adv->tx_addr;
+	}
+
+	if ((pdu_rx->type == PDU_ADV_TYPE_AUX_SCAN_REQ) &&
+	    (pdu_rx->len == sizeof(struct pdu_adv_scan_req)) &&
+	    lll_adv_scan_req_check(lll, pdu_rx, tx_addr, addr, devmatch_ok,
+				   &rl_idx)) {
+		radio_isr_set(lll_isr_done, lll);
+		radio_switch_complete_and_disable();
+		radio_pkt_tx_set(lll_adv_scan_rsp_curr_get(lll));
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+		if (lll->scan_req_notify) {
+			uint32_t err;
+
+			/* Generate the scan request event */
+			err = lll_adv_scan_req_report(lll, pdu_rx, rl_idx,
+						      rssi_ready);
+			if (err) {
+				/* Scan Response will not be transmitted */
+				return err;
+			}
+		}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end used in ISR
+			 * profiling, hence back it up for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+		return 0;
+	}
+
+	/* TODO: add handling for AUX_CONNECT_REQ */
+
+	return -EINVAL;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_internal.h	(working copy)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+static inline struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu,
+						     uint8_t *is_modified)
+{
+	uint8_t first;
+
+	first = pdu->first;
+	if (first != pdu->last) {
+		first += 1U;
+		if (first == DOUBLE_BUFFER_SIZE) {
+			first = 0U;
+		}
+		pdu->first = first;
+		*is_modified = 1U;
+	}
+
+	return (void *)pdu->pdu[first];
+}
+
+static inline struct pdu_adv *lll_adv_data_latest_get(struct lll_adv *lll,
+						      uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->adv_data, is_modified);
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_latest_get(struct lll_adv *lll,
+							  uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->scan_rsp, is_modified);
+}
+
+static inline struct pdu_adv *lll_adv_data_curr_get(struct lll_adv *lll)
+{
+	return (void *)lll->adv_data.pdu[lll->adv_data.first];
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_curr_get(struct lll_adv *lll)
+{
+	return (void *)lll->scan_rsp.pdu[lll->scan_rsp.first];
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static inline struct pdu_adv *
+lll_adv_aux_data_latest_get(struct lll_adv_aux *lll, uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->data, is_modified);
+}
+
+static inline struct pdu_adv *lll_adv_aux_data_curr_get(struct lll_adv_aux *lll)
+{
+	return (void *)lll->data.pdu[lll->data.first];
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+static inline struct pdu_adv *
+lll_adv_sync_data_latest_get(struct lll_adv_sync *lll, uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->data, is_modified);
+}
+
+static inline struct pdu_adv *
+lll_adv_sync_data_curr_get(struct lll_adv_sync *lll)
+{
+	return (void *)lll->data.pdu[lll->data.first];
+}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+bool lll_adv_scan_req_check(struct lll_adv *lll, struct pdu_adv *sr,
+			    uint8_t tx_addr, uint8_t *addr,
+			    uint8_t devmatch_ok, uint8_t *rl_idx);
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+int lll_adv_scan_req_report(struct lll_adv *lll, struct pdu_adv *pdu_adv_rx,
+			    uint8_t rl_idx, uint8_t rssi_ready);
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_adv_sync_init(void);
+int lll_adv_sync_reset(void);
+void lll_adv_sync_prepare(void *param);
+
+extern uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_sync.c	(working copy)
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+
+#include <zephyr.h>
+#include <soc.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_chan.h"
+#include "lll_adv.h"
+#include "lll_adv_sync.h"
+
+#include "lll_internal.h"
+#include "lll_adv_internal.h"
+#include "lll_tim_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_adv_sync
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+
+int lll_adv_sync_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_adv_sync_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_adv_sync_prepare(void *param)
+{
+	struct lll_prepare_param *p;
+	struct lll_adv_sync *lll;
+	uint16_t elapsed;
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	p = param;
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	lll = p->param;
+
+	/* Save the (latency + 1) for use in event */
+	lll->latency_prepare += elapsed;
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	struct lll_adv_sync *lll;
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	uint16_t event_counter;
+	uint8_t data_chan_use;
+	struct pdu_adv *pdu;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+	uint32_t start_us;
+	uint8_t phy_s;
+	uint8_t upd;
+
+	DEBUG_RADIO_START_A(1);
+
+	lll = p->param;
+
+	/* Deduce the latency */
+	lll->latency_event = lll->latency_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->latency_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->latency_prepare;
+
+	/* Reset accumulated latencies */
+	lll->latency_prepare = 0;
+
+	/* Calculate the radio channel to use */
+	data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+				       &lll->data_chan_map[0],
+				       lll->data_chan_count);
+
+	/* Start setting up of Radio h/w */
+	radio_reset();
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif
+
+	phy_s = lll->adv->phy_s;
+
+	/* TODO: if coded we use S8? */
+	radio_phy_set(phy_s, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (phy_s << 1));
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+	lll_chan_set(data_chan_use);
+
+	pdu = lll_adv_sync_data_latest_get(lll, &upd);
+	radio_pkt_tx_set(pdu);
+
+	/* TODO: chaining */
+	radio_isr_set(lll_isr_done, lll);
+	radio_switch_complete_and_disable();
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	start_us = radio_tmr_start(1, ticks_at_start, remainder);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+
+	radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(phy_s, 1) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(start_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_ADV_SYNC_BASE +
+				   ull_adv_sync_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(lll_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_A(1);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_clock.c	(working copy)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <soc.h>
+#include <device.h>
+#include <drivers/clock_control.h>
+#include <drivers/clock_control/nrf_clock_control.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_clock
+#include "common/log.h"
+#include "hal/debug.h"
+
+/* Clock setup timeouts are unlikely, below values are experimental */
+#define LFCLOCK_TIMEOUT_MS 500
+#define HFCLOCK_TIMEOUT_MS 2
+
+static uint16_t const sca_ppm_lut[] = {500, 250, 150, 100, 75, 50, 30, 20};
+
+struct lll_clock_state {
+	struct onoff_client cli;
+	struct k_sem sem;
+};
+
+static struct onoff_client lf_cli;
+static atomic_val_t hf_refcnt;
+
+static void clock_ready(struct onoff_manager *mgr, struct onoff_client *cli,
+			uint32_t state, int res)
+{
+	struct lll_clock_state *clk_state =
+		CONTAINER_OF(cli, struct lll_clock_state, cli);
+
+	k_sem_give(&clk_state->sem);
+}
+
+static int blocking_on(struct onoff_manager *mgr, uint32_t timeout)
+{
+
+	struct lll_clock_state state;
+	int err;
+
+	k_sem_init(&state.sem, 0, 1);
+	sys_notify_init_callback(&state.cli.notify, clock_ready);
+	err = onoff_request(mgr, &state.cli);
+	if (err < 0) {
+		return err;
+	}
+
+	return k_sem_take(&state.sem, K_MSEC(timeout));
+}
+
+int lll_clock_init(void)
+{
+	struct onoff_manager *mgr =
+		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
+
+	sys_notify_init_spinwait(&lf_cli.notify);
+
+	return onoff_request(mgr, &lf_cli);
+}
+
+int lll_clock_wait(void)
+{
+	struct onoff_manager *mgr =
+		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
+
+	return blocking_on(mgr, LFCLOCK_TIMEOUT_MS);
+}
+
+int lll_hfclock_on(void)
+{
+	if (atomic_inc(&hf_refcnt) > 0) {
+		return 0;
+	}
+
+	z_nrf_clock_bt_ctlr_hf_request();
+	DEBUG_RADIO_XTAL(1);
+
+	return 0;
+}
+
+int lll_hfclock_on_wait(void)
+{
+	struct onoff_manager *mgr =
+		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
+	int err;
+
+	atomic_inc(&hf_refcnt);
+
+	err = blocking_on(mgr, HFCLOCK_TIMEOUT_MS);
+	if (err >= 0) {
+		DEBUG_RADIO_XTAL(1);
+	}
+
+	return err;
+}
+
+int lll_hfclock_off(void)
+{
+	if (hf_refcnt < 1) {
+		return -EALREADY;
+	}
+
+	if (atomic_dec(&hf_refcnt) > 1) {
+		return 0;
+	}
+
+	z_nrf_clock_bt_ctlr_hf_release();
+	DEBUG_RADIO_XTAL(0);
+
+	return 0;
+}
+
+uint8_t lll_clock_sca_local_get(void)
+{
+	return CLOCK_CONTROL_NRF_K32SRC_ACCURACY;
+}
+
+uint32_t lll_clock_ppm_local_get(void)
+{
+	return sca_ppm_lut[CLOCK_CONTROL_NRF_K32SRC_ACCURACY];
+}
+
+uint32_t lll_clock_ppm_get(uint8_t sca)
+{
+	return sca_ppm_lut[sca];
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c	(working copy)
@@ -0,0 +1,838 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+#include <drivers/clock_control/nrf_clock_control.h>
+
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mfifo.h"
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_clock.h"
+#include "lll_conn.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_conn
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static void isr_done(void *param);
+static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
+			     uint8_t *is_rx_enqueue,
+			     struct node_tx **tx_release, uint8_t *is_done);
+static void empty_tx_init(void);
+
+static uint8_t crc_expire;
+static uint8_t crc_valid;
+static uint16_t trx_cnt;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static uint8_t mic_state;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_COUNT) && \
+	(CONFIG_BT_CTLR_FORCE_MD_COUNT > 0)
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+static uint8_t force_md_cnt_reload;
+#define BT_CTLR_FORCE_MD_COUNT force_md_cnt_reload
+#else
+#define BT_CTLR_FORCE_MD_COUNT CONFIG_BT_CTLR_FORCE_MD_COUNT
+#endif
+static uint8_t force_md_cnt;
+
+#define FORCE_MD_CNT_INIT() \
+		{ \
+			force_md_cnt = 0U; \
+		}
+
+#define FORCE_MD_CNT_DEC() \
+		do { \
+			if (force_md_cnt) { \
+				force_md_cnt--; \
+			} \
+		} while (0)
+
+#define FORCE_MD_CNT_GET() force_md_cnt
+
+#define FORCE_MD_CNT_SET() \
+		do { \
+			if (force_md_cnt || \
+			    (trx_cnt >= ((CONFIG_BT_CTLR_TX_BUFFERS) - 1))) { \
+				force_md_cnt = BT_CTLR_FORCE_MD_COUNT; \
+			} \
+		} while (0)
+
+#else /* !CONFIG_BT_CTLR_FORCE_MD_COUNT */
+#define FORCE_MD_CNT_INIT()
+#define FORCE_MD_CNT_DEC()
+#define FORCE_MD_CNT_GET() 0
+#define FORCE_MD_CNT_SET()
+#endif /* !CONFIG_BT_CTLR_FORCE_MD_COUNT */
+
+int lll_conn_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	empty_tx_init();
+
+	return 0;
+}
+
+int lll_conn_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	FORCE_MD_CNT_INIT();
+
+	return 0;
+}
+
+void lll_conn_flush(uint16_t handle, struct lll_conn *lll)
+{
+	/* Nothing to be flushed */
+}
+
+void lll_conn_prepare_reset(void)
+{
+	trx_cnt = 0U;
+	crc_valid = 0U;
+	crc_expire = 0U;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	mic_state = LLL_CONN_MIC_NONE;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+}
+
+void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_done, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(param);
+}
+
+void lll_conn_isr_rx(void *param)
+{
+	uint8_t is_empty_pdu_tx_retry;
+	struct pdu_data *pdu_data_rx;
+	struct pdu_data *pdu_data_tx;
+	struct node_rx_pdu *node_rx;
+	struct node_tx *tx_release;
+	uint8_t is_rx_enqueue;
+	struct lll_conn *lll;
+	uint8_t rssi_ready;
+	uint8_t is_ull_rx;
+	uint8_t trx_done;
+	uint8_t is_done;
+	uint8_t crc_ok;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = rssi_ready = 0U;
+	}
+
+	/* Clear radio rx status and events */
+	lll_isr_rx_status_reset();
+
+	/* No Rx */
+	if (!trx_done) {
+		radio_isr_set(isr_done, param);
+		radio_disable();
+
+		return;
+	}
+
+	trx_cnt++;
+
+	is_done = 0U;
+	tx_release = NULL;
+	is_rx_enqueue = 0U;
+
+	lll = param;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	pdu_data_rx = (void *)node_rx->pdu;
+
+	if (crc_ok) {
+		uint32_t err;
+
+		err = isr_rx_pdu(lll, pdu_data_rx, &is_rx_enqueue, &tx_release,
+				 &is_done);
+		if (err) {
+			goto lll_conn_isr_rx_exit;
+		}
+
+		/* Reset CRC expiry counter */
+		crc_expire = 0U;
+
+		/* CRC valid flag used to detect supervision timeout */
+		crc_valid = 1U;
+	} else {
+		/* Start CRC error countdown, if not already started */
+		if (crc_expire == 0U) {
+			crc_expire = 2U;
+		}
+
+		/* CRC error countdown */
+		crc_expire--;
+		is_done = (crc_expire == 0U);
+	}
+
+	/* prepare tx packet */
+	is_empty_pdu_tx_retry = lll->empty;
+	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
+
+	/* Decide on event continuation and hence Radio Shorts to use */
+	is_done = is_done || ((crc_ok) && (pdu_data_rx->md == 0) &&
+			      (pdu_data_tx->md == 0) &&
+			      (pdu_data_tx->len == 0));
+
+	if (is_done) {
+		radio_isr_set(isr_done, param);
+
+		if (0) {
+#if defined(CONFIG_BT_CENTRAL)
+		/* Event done for master */
+		} else if (!lll->role) {
+			radio_disable();
+
+			/* assert if radio packet ptr is not set and radio
+			 * started tx.
+			 */
+			LL_ASSERT(!radio_is_ready());
+
+			/* Restore state if last transmitted was empty PDU */
+			lll->empty = is_empty_pdu_tx_retry;
+
+			goto lll_conn_isr_rx_exit;
+#endif /* CONFIG_BT_CENTRAL */
+#if defined(CONFIG_BT_PERIPHERAL)
+		/* Event done for slave */
+		} else {
+			radio_switch_complete_and_disable();
+#endif /* CONFIG_BT_PERIPHERAL */
+		}
+	} else {
+		radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		radio_switch_complete_and_rx(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+		radio_switch_complete_and_rx(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+		radio_isr_set(lll_conn_isr_tx, param);
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+	}
+
+	/* Fill sn and nesn */
+	pdu_data_tx->sn = lll->sn;
+	pdu_data_tx->nesn = lll->nesn;
+
+	/* setup the radio tx packet buffer */
+	lll_conn_tx_pkt_set(lll, pdu_data_tx);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	/* PA enable is overwriting packet end used in ISR profiling, hence
+	 * back it up for later use.
+	 */
+	lll_prof_radio_end_backup();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+	radio_gpio_pa_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US -
+				 radio_rx_chain_delay_get(lll->phy_rx, 1) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US -
+				 radio_rx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* assert if radio packet ptr is not set and radio started tx */
+	LL_ASSERT(!radio_is_ready());
+
+lll_conn_isr_rx_exit:
+	/* Save the AA captured for the first Rx in connection event */
+	if (!radio_tmr_aa_restore()) {
+		radio_tmr_aa_save(radio_tmr_aa_get());
+	}
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	lll_prof_cputime_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+	is_ull_rx = 0U;
+
+	if (tx_release) {
+		LL_ASSERT(lll->handle != 0xFFFF);
+
+		ull_conn_lll_ack_enqueue(lll->handle, tx_release);
+
+		is_ull_rx = 1U;
+	}
+
+	if (is_rx_enqueue) {
+#if defined(CONFIG_SOC_COMPATIBLE_NRF52832) && \
+	defined(CONFIG_BT_CTLR_LE_ENC) && \
+	(!defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX) || \
+	 (CONFIG_BT_CTLR_DATA_LENGTH_MAX < (HAL_RADIO_PDU_LEN_MAX - 4)))
+		if (lll->enc_rx) {
+			uint8_t *pkt_decrypt_data;
+
+			pkt_decrypt_data = (uint8_t *)radio_pkt_decrypt_get() +
+					   offsetof(struct pdu_data, lldata);
+			memcpy((void *)pdu_data_rx->lldata,
+			       (void *)pkt_decrypt_data, pdu_data_rx->len);
+		}
+#endif
+
+		ull_pdu_rx_alloc();
+
+		node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+		node_rx->hdr.handle = lll->handle;
+
+		ull_rx_put(node_rx->hdr.link, node_rx);
+		is_ull_rx = 1U;
+	}
+
+	if (is_ull_rx) {
+		ull_rx_sched();
+	}
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	/* Collect RSSI for connection */
+	if (rssi_ready) {
+		uint8_t rssi = radio_rssi_get();
+
+		lll->rssi_latest = rssi;
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+		if (((lll->rssi_reported - rssi) & 0xFF) >
+		    LLL_CONN_RSSI_THRESHOLD) {
+			if (lll->rssi_sample_count) {
+				lll->rssi_sample_count--;
+			}
+		} else {
+			lll->rssi_sample_count = LLL_CONN_RSSI_SAMPLE_COUNT;
+		}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+	}
+#else /* !CONFIG_BT_CTLR_CONN_RSSI */
+	ARG_UNUSED(rssi_ready);
+#endif /* !CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	lll_prof_send();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+}
+
+void lll_conn_isr_tx(void *param)
+{
+	struct lll_conn *lll;
+	uint32_t hcto;
+
+	/* Clear radio tx status and events */
+	lll_isr_tx_status_reset();
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+	lll = param;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_tx(lll->phy_rx, 0,
+				     lll->phy_tx,
+				     lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	lll_conn_rx_pkt_set(lll);
+
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 +
+		RANGE_DELAY_US + 1;
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
+	hcto += addr_us_get(lll->phy_rx);
+	hcto -= radio_tx_chain_delay_get(lll->phy_tx, lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CONN_RSSI)
+	if (!trx_cnt && !lll->role) {
+		radio_rssi_measure();
+	}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
+	defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_tmr_end_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(lll->phy_tx,
+							  lll->phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	radio_isr_set(lll_conn_isr_rx, param);
+}
+
+void lll_conn_rx_pkt_set(struct lll_conn *lll)
+{
+	struct node_rx_pdu *node_rx;
+	uint16_t max_rx_octets;
+	uint8_t phy;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	max_rx_octets = lll->max_rx_octets;
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	phy = lll->phy_rx;
+#else /* !CONFIG_BT_CTLR_PHY */
+	phy = 0U;
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_phy_set(phy, 0);
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	} else if (lll->enc_rx) {
+		radio_pkt_configure(8, (max_rx_octets + 4), (phy << 1) | 0x01);
+
+#if defined(CONFIG_SOC_COMPATIBLE_NRF52832) && \
+	(!defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX) || \
+	 (CONFIG_BT_CTLR_DATA_LENGTH_MAX < (HAL_RADIO_PDU_LEN_MAX - 4)))
+		radio_pkt_rx_set(radio_ccm_rx_pkt_set(&lll->ccm_rx, phy,
+						      radio_pkt_decrypt_get()));
+#else
+		radio_pkt_rx_set(radio_ccm_rx_pkt_set(&lll->ccm_rx, phy,
+						      node_rx->pdu));
+#endif
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+	} else {
+		radio_pkt_configure(8, max_rx_octets, (phy << 1) | 0x01);
+
+		radio_pkt_rx_set(node_rx->pdu);
+	}
+}
+
+void lll_conn_tx_pkt_set(struct lll_conn *lll, struct pdu_data *pdu_data_tx)
+{
+	uint16_t max_tx_octets;
+	uint8_t phy, flags;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	max_tx_octets = lll->max_tx_octets;
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	phy = lll->phy_tx;
+	flags = lll->phy_flags;
+#else /* !CONFIG_BT_CTLR_PHY */
+	phy = 0U;
+	flags = 0U;
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_phy_set(phy, flags);
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	} else if (lll->enc_tx) {
+		radio_pkt_configure(8, (max_tx_octets + 4U),
+				    (phy << 1) | 0x01);
+
+		radio_pkt_tx_set(radio_ccm_tx_pkt_set(&lll->ccm_tx,
+						      pdu_data_tx));
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+	} else {
+		radio_pkt_configure(8, max_tx_octets, (phy << 1) | 0x01);
+
+		radio_pkt_tx_set(pdu_data_tx);
+	}
+}
+
+void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx)
+{
+	struct node_tx *tx;
+	struct pdu_data *p;
+	memq_link_t *link;
+
+	link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail, (void **)&tx);
+	if (lll->empty || !link) {
+		lll->empty = 1U;
+
+		p = (void *)radio_pkt_empty_get();
+		if (link || FORCE_MD_CNT_GET()) {
+			p->md = 1U;
+		} else {
+			p->md = 0U;
+		}
+	} else {
+		uint16_t max_tx_octets;
+
+		p = (void *)(tx->pdu + lll->packet_tx_head_offset);
+
+		if (!lll->packet_tx_head_len) {
+			lll->packet_tx_head_len = p->len;
+		}
+
+		if (lll->packet_tx_head_offset) {
+			p->ll_id = PDU_DATA_LLID_DATA_CONTINUE;
+		}
+
+		p->len = lll->packet_tx_head_len - lll->packet_tx_head_offset;
+
+		max_tx_octets = ull_conn_lll_max_tx_octets_get(lll);
+
+		if (p->len > max_tx_octets) {
+			p->len = max_tx_octets;
+			p->md = 1U;
+		} else if ((link->next != lll->memq_tx.tail) ||
+			   FORCE_MD_CNT_GET()) {
+			p->md = 1U;
+		} else {
+			p->md = 0U;
+		}
+
+		p->rfu = 0U;
+
+#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
+		p->resv = 0U;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */
+	}
+
+	*pdu_data_tx = p;
+}
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+uint8_t lll_conn_force_md_cnt_set(uint8_t force_md_cnt)
+{
+	uint8_t previous;
+
+	previous = force_md_cnt_reload;
+	force_md_cnt_reload = force_md_cnt;
+
+	return previous;
+}
+#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static void isr_done(void *param)
+{
+	struct event_done_extra *e;
+
+	lll_isr_status_reset();
+
+	e = ull_event_done_extra_get();
+	LL_ASSERT(e);
+
+	e->type = EVENT_DONE_EXTRA_TYPE_CONN;
+	e->trx_cnt = trx_cnt;
+	e->crc_valid = crc_valid;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	e->mic_state = mic_state;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (trx_cnt) {
+		struct lll_conn *lll = param;
+
+		if (lll->role) {
+			uint32_t preamble_to_addr_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+			preamble_to_addr_us =
+				addr_us_get(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+			preamble_to_addr_us =
+				addr_us_get(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+			e->drift.start_to_address_actual_us =
+				radio_tmr_aa_restore() - radio_tmr_ready_get();
+			e->drift.window_widening_event_us =
+				lll->slave.window_widening_event_us;
+			e->drift.preamble_to_addr_us = preamble_to_addr_us;
+
+			/* Reset window widening, as anchor point sync-ed */
+			lll->slave.window_widening_event_us = 0;
+			lll->slave.window_size_event_us = 0;
+		}
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	lll_isr_cleanup(param);
+}
+
+static inline bool ctrl_pdu_len_check(uint8_t len)
+{
+	return len <= (offsetof(struct pdu_data, llctrl) +
+		       sizeof(struct pdu_data_llctrl));
+
+}
+
+static inline int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
+			     uint8_t *is_rx_enqueue,
+			     struct node_tx **tx_release, uint8_t *is_done)
+{
+#if defined(CONFIG_SOC_COMPATIBLE_NRF52832) && \
+	defined(CONFIG_BT_CTLR_LE_ENC) && \
+	(!defined(CONFIG_BT_CTLR_DATA_LENGTH_MAX) || \
+	 (CONFIG_BT_CTLR_DATA_LENGTH_MAX < (HAL_RADIO_PDU_LEN_MAX - 4)))
+	if (lll->enc_rx) {
+		uint8_t *pkt_decrypt;
+
+		pkt_decrypt = radio_pkt_decrypt_get();
+		memcpy((void *)pdu_data_rx, (void *)pkt_decrypt,
+		       offsetof(struct pdu_data, lldata));
+	}
+#endif
+
+	/* Ack for tx-ed data */
+	if (pdu_data_rx->nesn != lll->sn) {
+		struct pdu_data *pdu_data_tx;
+		struct node_tx *tx;
+		memq_link_t *link;
+
+		/* Increment sequence number */
+		lll->sn++;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		/* First ack (and redundantly any other ack) enable use of
+		 * slave latency.
+		 */
+		if (lll->role) {
+			lll->slave.latency_enabled = 1;
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+		FORCE_MD_CNT_DEC();
+
+		if (!lll->empty) {
+			link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail,
+					 (void **)&tx);
+		} else {
+			lll->empty = 0;
+
+			pdu_data_tx = (void *)radio_pkt_empty_get();
+			if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role) {
+				*is_done = !pdu_data_tx->md;
+			}
+
+			link = NULL;
+		}
+
+		if (link) {
+			uint8_t pdu_data_tx_len;
+			uint8_t offset;
+
+			pdu_data_tx = (void *)(tx->pdu +
+					       lll->packet_tx_head_offset);
+
+			pdu_data_tx_len = pdu_data_tx->len;
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			if (pdu_data_tx_len != 0U) {
+				/* if encrypted increment tx counter */
+				if (lll->enc_tx) {
+					lll->ccm_tx.counter++;
+				}
+			}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+			offset = lll->packet_tx_head_offset + pdu_data_tx_len;
+			if (offset < lll->packet_tx_head_len) {
+				lll->packet_tx_head_offset = offset;
+			} else if (offset == lll->packet_tx_head_len) {
+				lll->packet_tx_head_len = 0;
+				lll->packet_tx_head_offset = 0;
+
+				memq_dequeue(lll->memq_tx.tail,
+					     &lll->memq_tx.head, NULL);
+
+				/* TX node UPSTREAM, i.e. Tx node ack path */
+				link->next = tx->next; /* Indicates ctrl or data
+							* pool.
+							*/
+				tx->next = link;
+
+				*tx_release = tx;
+
+				FORCE_MD_CNT_SET();
+			}
+
+			if (IS_ENABLED(CONFIG_BT_CENTRAL) && !lll->role) {
+				*is_done = !pdu_data_tx->md;
+			}
+		}
+	}
+
+	/* process received data */
+	if ((pdu_data_rx->sn == lll->nesn) &&
+	    /* check so that we will NEVER use the rx buffer reserved for empty
+	     * packet and internal control enqueue
+	     */
+	    (ull_pdu_rx_alloc_peek(3) != 0)) {
+		/* Increment next expected serial number */
+		lll->nesn++;
+
+		if (pdu_data_rx->len != 0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			/* If required, wait for CCM to finish
+			 */
+			if (lll->enc_rx) {
+				uint32_t done;
+
+				done = radio_ccm_is_done();
+				LL_ASSERT(done);
+
+				bool mic_failure = !radio_ccm_mic_is_valid();
+
+				if (mic_failure &&
+				    lll->ccm_rx.counter == 0 &&
+				    (pdu_data_rx->ll_id ==
+				     PDU_DATA_LLID_CTRL)) {
+					/* Received an LL control packet in the
+					 * middle of the LL encryption procedure
+					 * with MIC failure.
+					 * This could be an unencrypted packet
+					 */
+					struct pdu_data *scratch_pkt =
+						radio_pkt_scratch_get();
+
+					if (ctrl_pdu_len_check(
+						scratch_pkt->len)) {
+						memcpy(pdu_data_rx,
+						       scratch_pkt,
+						       scratch_pkt->len +
+						       offsetof(struct pdu_data,
+							llctrl));
+						mic_failure = false;
+						lll->ccm_rx.counter--;
+					}
+				}
+
+				if (mic_failure) {
+					/* Record MIC invalid */
+					mic_state = LLL_CONN_MIC_FAIL;
+
+					return -EINVAL;
+				}
+
+				/* Increment counter */
+				lll->ccm_rx.counter++;
+
+				/* Record MIC valid */
+				mic_state = LLL_CONN_MIC_PASS;
+			}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+			/* Enqueue non-empty PDU */
+			*is_rx_enqueue = 1U;
+		}
+	}
+
+	return 0;
+}
+
+static void empty_tx_init(void)
+{
+	struct pdu_data *p;
+
+	p = (void *)radio_pkt_empty_get();
+	p->ll_id = PDU_DATA_LLID_DATA_CONTINUE;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn_meta.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn_meta.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn_meta.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2019 Demant
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#if defined(CONFIG_BT_CTLR_CONN_META)
+/*
+ * struct lll_conn_meta { };
+ */
+#error Please define struct lll_conn_meta when enabling BT_CTLR_CONN_META
+#endif /* CONFIG_BT_CTLR_CONN_META */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_internal.h	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		lll_prepare_cb_t prepare_cb, int prio,
+		struct lll_prepare_param *prepare_param);
+int lll_prepare_done(void *param);
+int lll_done(void *param);
+bool lll_is_done(void *param);
+int lll_is_abort_cb(void *next, int prio, void *curr,
+			 lll_prepare_cb_t *resume_cb, int *resume_prio);
+void lll_abort_cb(struct lll_prepare_param *prepare_param, void *param);
+
+static inline int lll_is_stop(void *lll)
+{
+	struct lll_hdr *hdr = lll;
+
+	return !!hdr->is_stop;
+}
+uint32_t lll_evt_offset_get(struct evt_hdr *evt);
+uint32_t lll_preempt_calc(struct evt_hdr *evt, uint8_t ticker_id,
+		uint32_t ticks_at_event);
+void lll_chan_set(uint32_t chan);
+void lll_isr_tx_status_reset(void);
+void lll_isr_rx_status_reset(void);
+void lll_isr_status_reset(void);
+void lll_isr_abort(void *param);
+void lll_isr_done(void *param);
+void lll_isr_cleanup(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_master_init(void);
+int lll_master_reset(void);
+void lll_master_prepare(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c	(working copy)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_conn.h"
+#include "lll_master.h"
+#include "lll_chan.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_master
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+
+int lll_master_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_master_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_master_prepare(void *param)
+{
+	struct lll_prepare_param *p;
+	struct lll_conn *lll;
+	uint16_t elapsed;
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	p = param;
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	lll = p->param;
+
+	/* Save the (latency + 1) for use in event */
+	lll->latency_prepare += elapsed;
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	struct pdu_data *pdu_data_tx;
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	uint16_t event_counter;
+	uint32_t remainder_us;
+	uint8_t data_chan_use;
+	struct lll_conn *lll;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+
+	DEBUG_RADIO_START_M(1);
+
+	lll = p->param;
+
+	/* Check if stopped (on disconnection between prepare and pre-empt)
+	 */
+	if (unlikely(lll->handle == 0xFFFF)) {
+		int err;
+
+		err = lll_hfclock_off();
+		LL_ASSERT(err >= 0);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_CLOSE_M(0);
+		return 0;
+	}
+
+	/* Reset connection event global variables */
+	lll_conn_prepare_reset();
+
+	/* Deduce the latency */
+	lll->latency_event = lll->latency_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->latency_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->latency_prepare;
+
+	/* Reset accumulated latencies */
+	lll->latency_prepare = 0;
+
+	if (lll->data_chan_sel) {
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+#else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+		data_chan_use = 0;
+		LL_ASSERT(0);
+#endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+	} else {
+		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
+					       lll->data_chan_hop,
+					       lll->latency_event,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+	}
+
+	/* Prepare the Tx PDU */
+	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
+	pdu_data_tx->sn = lll->sn;
+	pdu_data_tx->nesn = lll->nesn;
+
+	/* Start setting up of Radio h/w */
+	radio_reset();
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif
+
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+	lll_chan_set(data_chan_use);
+
+	/* setup the radio tx packet buffer */
+	lll_conn_tx_pkt_set(lll, pdu_data_tx);
+
+	radio_isr_set(lll_conn_isr_tx, lll);
+
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_rx(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_rx(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
+
+	/* capture end of Tx-ed PDU, used to calculate HCTO. */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_tx_ready_delay_get(lll->phy_tx,
+							  lll->phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_tx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_CONN_BASE + lll->handle),
+			     ticks_at_event)) {
+		radio_isr_set(lll_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_M(1);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_meta.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_meta.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_meta.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_CTLR_RX_PDU_META)
+/*
+ * typedef struct { } lll_rx_pdu_meta_t;
+ */
+#error Please define typedef struct lll_rx_pdu_meta_t when enabling \
+	CONFIG_BT_CTLR_RX_PDU_META
+#endif /* CONFIG_BT_CTLR_RX_PDU_META */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof.c	(working copy)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+
+static uint8_t latency_min = (uint8_t) -1;
+static uint8_t latency_max;
+static uint8_t latency_prev;
+static uint8_t cputime_min = (uint8_t) -1;
+static uint8_t cputime_max;
+static uint8_t cputime_prev;
+static uint32_t timestamp_latency;
+
+void lll_prof_latency_capture(void)
+{
+	/* sample the packet timer, use it to calculate ISR latency
+	 * and generate the profiling event at the end of the ISR.
+	 */
+	radio_tmr_sample();
+}
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+static uint32_t timestamp_radio_end;
+
+uint32_t lll_prof_radio_end_backup(void)
+{
+	/* PA enable is overwriting packet end used in ISR profiling, hence
+	 * back it up for later use.
+	 */
+	timestamp_radio_end = radio_tmr_end_get();
+
+	return timestamp_radio_end;
+}
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+void lll_prof_cputime_capture(void)
+{
+	/* get the ISR latency sample */
+	timestamp_latency = radio_tmr_sample_get();
+
+	/* sample the packet timer again, use it to calculate ISR execution time
+	 * and use it in profiling event
+	 */
+	radio_tmr_sample();
+}
+
+void lll_prof_send(void)
+{
+	uint8_t latency, cputime, prev;
+	uint8_t chg = 0U;
+
+	/* calculate the elapsed time in us since on-air radio packet end
+	 * to ISR entry
+	 */
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	latency = timestamp_latency - timestamp_radio_end;
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	latency = timestamp_latency - radio_tmr_end_get();
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* check changes in min, avg and max of latency */
+	if (latency > latency_max) {
+		latency_max = latency;
+		chg = 1U;
+	}
+	if (latency < latency_min) {
+		latency_min = latency;
+		chg = 1U;
+	}
+
+	/* check for +/- 1us change */
+	prev = ((uint16_t)latency_prev + latency) >> 1;
+	if (prev != latency_prev) {
+		latency_prev = latency;
+		chg = 1U;
+	}
+
+	/* calculate the elapsed time in us since ISR entry */
+	cputime = radio_tmr_sample_get() - timestamp_latency;
+
+	/* check changes in min, avg and max */
+	if (cputime > cputime_max) {
+		cputime_max = cputime;
+		chg = 1U;
+	}
+
+	if (cputime < cputime_min) {
+		cputime_min = cputime;
+		chg = 1U;
+	}
+
+	/* check for +/- 1us change */
+	prev = ((uint16_t)cputime_prev + cputime) >> 1;
+	if (prev != cputime_prev) {
+		cputime_prev = cputime;
+		chg = 1U;
+	}
+
+	/* generate event if any change */
+	if (chg) {
+		struct node_rx_pdu *rx;
+
+		/* NOTE: enqueue only if rx buffer available, else ignore */
+		rx = ull_pdu_rx_alloc_peek(3);
+		if (rx) {
+			struct pdu_data *pdu;
+			struct profile *p;
+
+			ull_pdu_rx_alloc();
+
+			rx->hdr.type = NODE_RX_TYPE_PROFILE;
+			rx->hdr.handle = 0xFFFF;
+
+			pdu = (void *)rx->pdu;
+			p = &pdu->profile;
+			p->lcur = latency;
+			p->lmin = latency_min;
+			p->lmax = latency_max;
+			p->cur = cputime;
+			p->min = cputime_min;
+			p->max = cputime_max;
+
+			ull_rx_put(rx->hdr.link, rx);
+			ull_rx_sched();
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_prof_internal.h	(working copy)
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void lll_prof_latency_capture(void);
+void lll_prof_radio_end_backup(void);
+void lll_prof_cputime_capture(void);
+void lll_prof_send(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c	(working copy)
@@ -0,0 +1,1172 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <toolchain.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+#include <soc.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_chan.h"
+#include "lll_filter.h"
+#include "lll_sched.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_scan
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio);
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			   void *param);
+static void ticker_op_start_cb(uint32_t status, void *param);
+static void isr_rx(void *param);
+static void isr_tx(void *param);
+static void isr_done(void *param);
+static void isr_window(void *param);
+static void isr_abort(void *param);
+static void isr_cleanup(void *param);
+
+static inline bool isr_rx_scan_check(struct lll_scan *lll, uint8_t irkmatch_ok,
+				     uint8_t devmatch_ok, uint8_t rl_idx);
+static inline int isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
+			     uint8_t devmatch_id, uint8_t irkmatch_ok,
+			     uint8_t irkmatch_id, uint8_t rl_idx,
+			     uint8_t rssi_ready);
+static inline bool isr_scan_init_check(struct lll_scan *lll,
+				       struct pdu_adv *pdu, uint8_t rl_idx);
+static inline bool isr_scan_init_adva_check(struct lll_scan *lll,
+					    struct pdu_adv *pdu, uint8_t rl_idx);
+static inline bool isr_scan_tgta_check(struct lll_scan *lll, bool init,
+				       struct pdu_adv *pdu, uint8_t rl_idx,
+				       bool *dir_report);
+static inline bool isr_scan_tgta_rpa_check(struct lll_scan *lll,
+					   struct pdu_adv *pdu,
+					   bool *dir_report);
+static inline bool isr_scan_rsp_adva_matches(struct pdu_adv *srsp);
+static int isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
+			      uint8_t rl_idx, bool dir_report);
+
+int lll_scan_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_scan_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_scan_prepare(void *param)
+{
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, param);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	uint32_t ticks_at_event, ticks_at_start;
+	struct node_rx_pdu *node_rx;
+	uint32_t remainder_us;
+	struct lll_scan *lll;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+	uint32_t aa;
+
+	DEBUG_RADIO_START_O(1);
+
+	lll = p->param;
+
+	/* Check if stopped (on connection establishment race between LLL and
+	 * ULL.
+	 */
+	if (unlikely(lll_is_stop(lll))) {
+		int err;
+
+		err = lll_hfclock_off();
+		LL_ASSERT(err >= 0);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_CLOSE_O(0);
+		return 0;
+	}
+
+	lll->state = 0U;
+
+	radio_reset();
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	/* TODO: if coded we use S8? */
+	radio_phy_set(lll->phy, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy << 1));
+
+	lll->is_adv_ind = 0U;
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	radio_phy_set(0, 0);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, 0);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	radio_pkt_rx_set(node_rx->pdu);
+
+	aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+
+	lll_chan_set(37 + lll->chan);
+
+	radio_isr_set(isr_rx, lll);
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		struct lll_filter *filter =
+			ull_filter_lll_get(!!(lll->filter_policy & 0x1));
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_filter_configure(filter->enable_bitmask,
+				       filter->addr_type_bitmask,
+				       (uint8_t *)filter->bdaddr);
+
+		radio_ar_configure(count, irks);
+	} else
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_FILTER) && lll->filter_policy) {
+		/* Setup Radio Filter */
+		struct lll_filter *wl = ull_filter_lll_get(true);
+
+		radio_filter_configure(wl->enable_bitmask,
+				       wl->addr_type_bitmask,
+				       (uint8_t *)wl->bdaddr);
+	}
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event or extended scan to schedule auxiliary channel
+	 * reception.
+	 */
+	radio_tmr_end_capture();
+
+	/* scanner always measures RSSI */
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_SCAN_BASE +
+				   ull_scan_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		if (lll->ticks_window) {
+			/* start window close timeout */
+			ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+					   TICKER_USER_ID_LLL,
+					   TICKER_ID_SCAN_STOP,
+					   ticks_at_event, lll->ticks_window,
+					   TICKER_NULL_PERIOD,
+					   TICKER_NULL_REMAINDER,
+					   TICKER_NULL_LAZY, TICKER_NULL_SLOT,
+					   ticker_stop_cb, lll,
+					   ticker_op_start_cb,
+					   (void *)__LINE__);
+			LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+				  (ret == TICKER_STATUS_BUSY));
+		}
+
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+		/* calc next group in us for the anchor where first connection
+		 * event to be placed.
+		 */
+		if (lll->conn) {
+			static memq_link_t link;
+			static struct mayfly mfy_after_mstr_offset_get = {
+				0, 0, &link, NULL,
+				ull_sched_mfy_after_mstr_offset_get};
+			uint32_t retval;
+
+			mfy_after_mstr_offset_get.param = p;
+
+			retval = mayfly_enqueue(TICKER_USER_ID_LLL,
+						TICKER_USER_ID_ULL_LOW, 1,
+						&mfy_after_mstr_offset_get);
+			LL_ASSERT(!retval);
+		}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_O(1);
+
+	return 0;
+}
+
+static int resume_prepare_cb(struct lll_prepare_param *p)
+{
+	struct evt_hdr *evt;
+
+	evt = HDR_LLL2EVT(p->param);
+	p->ticks_at_expire = ticker_ticks_now_get() - lll_evt_offset_get(evt);
+	p->remainder = 0;
+	p->lazy = 0;
+
+	return prepare_cb(p);
+}
+
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+	struct lll_scan *lll = curr;
+
+	/* TODO: check prio */
+	if (next != curr) {
+		int err;
+
+		/* wrap back after the pre-empter */
+		*resume_cb = resume_prepare_cb;
+		*resume_prio = 0; /* TODO: */
+
+		/* Retain HF clock */
+		err = lll_hfclock_on();
+		LL_ASSERT(err >= 0);
+
+		return -EAGAIN;
+	}
+
+	radio_isr_set(isr_window, lll);
+	radio_disable();
+
+	if (++lll->chan == 3U) {
+		lll->chan = 0U;
+	}
+
+	lll_chan_set(37 + lll->chan);
+
+	return 0;
+}
+
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) && lll_is_stop(param)) {
+			while (!radio_has_disabled()) {
+				cpu_sleep();
+			}
+		} else {
+			radio_isr_set(isr_abort, param);
+			radio_disable();
+		}
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(param);
+}
+
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			   void *param)
+{
+	radio_isr_set(isr_cleanup, param);
+	radio_disable();
+}
+
+static void ticker_op_start_cb(uint32_t status, void *param)
+{
+	ARG_UNUSED(param);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void isr_rx(void *param)
+{
+	struct lll_scan *lll;
+	uint8_t devmatch_ok;
+	uint8_t devmatch_id;
+	uint8_t irkmatch_ok;
+	uint8_t irkmatch_id;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t crc_ok;
+	uint8_t rl_idx;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		devmatch_ok = radio_filter_has_match();
+		devmatch_id = radio_filter_match_get();
+		irkmatch_ok = radio_ar_has_match();
+		irkmatch_id = radio_ar_match_get();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = devmatch_ok = irkmatch_ok = rssi_ready = 0U;
+		devmatch_id = irkmatch_id = 0xFF;
+	}
+
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	lll = param;
+
+	/* No Rx */
+	if (!trx_done) {
+		goto isr_rx_do_close;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	rl_idx = devmatch_ok ?
+		 ull_filter_lll_rl_idx(!!(lll->filter_policy & 0x01),
+				       devmatch_id) :
+		 irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
+			       FILTER_IDX_NONE;
+#else
+	rl_idx = FILTER_IDX_NONE;
+#endif
+	if (crc_ok && isr_rx_scan_check(lll, irkmatch_ok, devmatch_ok,
+					rl_idx)) {
+		int err;
+
+		err = isr_rx_pdu(lll, devmatch_ok, devmatch_id, irkmatch_ok,
+				 irkmatch_id, rl_idx, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(isr_done, lll);
+	radio_disable();
+}
+
+static void isr_tx(void *param)
+{
+	struct node_rx_pdu *node_rx;
+	uint32_t hcto;
+
+	/* Clear radio status and events */
+	lll_isr_tx_status_reset();
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+	radio_pkt_rx_set(node_rx->pdu);
+
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 + 1;
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+
+	radio_tmr_hcto_configure(hcto);
+
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	radio_isr_set(isr_rx, param);
+}
+
+static void isr_common_done(void *param)
+{
+	struct node_rx_pdu *node_rx;
+
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+	radio_pkt_rx_set(node_rx->pdu);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	radio_rssi_measure();
+
+	radio_isr_set(isr_rx, param);
+}
+
+static void isr_done(void *param)
+{
+	struct lll_scan *lll;
+	uint32_t start_us;
+
+	isr_common_done(param);
+
+	lll = param;
+	lll->state = 0U;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	lll->is_adv_ind = 0U;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	start_us = radio_tmr_start_now(0);
+
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(start_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(start_us);
+
+	radio_rx_enable();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event.
+	 */
+	radio_tmr_end_capture();
+}
+
+static void isr_window(void *param)
+{
+	uint32_t ticks_at_start;
+	uint32_t remainder_us;
+
+	isr_common_done(param);
+
+	ticks_at_start = ticker_ticks_now_get() +
+			 HAL_TICKER_CNTR_CMP_OFFSET_MIN;
+	remainder_us = radio_tmr_start_tick(0, ticks_at_start);
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event.
+	 */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+}
+
+static void isr_abort(void *param)
+{
+	/* Clear radio status and events */
+	lll_isr_status_reset();
+
+	/* Scanner stop can expire while here in this ISR.
+	 * Deferred attempt to stop can fail as it would have
+	 * expired, hence ignore failure.
+	 */
+	ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_LLL,
+		    TICKER_ID_SCAN_STOP, NULL, NULL);
+
+	/* Under race conditions, radio could get started while entering ISR */
+	radio_disable();
+
+	isr_cleanup(param);
+}
+
+static void isr_cleanup(void *param)
+{
+	struct node_rx_hdr *node_rx;
+	struct lll_scan *lll;
+
+	if (lll_is_done(param)) {
+		return;
+	}
+
+	radio_filter_disable();
+
+	lll = param;
+	if (++lll->chan == 3U) {
+		lll->chan = 0U;
+	}
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (_radio.advertiser.is_enabled && _radio.advertiser.is_mesh &&
+	    !_radio.advertiser.retry) {
+		mayfly_mesh_stop(NULL);
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (node_rx) {
+		ull_pdu_rx_alloc();
+
+		/* TODO: add other info by defining a payload struct */
+		node_rx->type = NODE_RX_TYPE_SCAN_INDICATION;
+
+		ull_rx_put(node_rx->link, node_rx);
+		ull_rx_sched();
+	}
+#else /* !CONFIG_BT_CTLR_SCAN_INDICATION */
+	ARG_UNUSED(node_rx);
+#endif /* !CONFIG_BT_CTLR_SCAN_INDICATION */
+
+	lll_isr_cleanup(param);
+}
+
+static inline bool isr_rx_scan_check(struct lll_scan *lll, uint8_t irkmatch_ok,
+				     uint8_t devmatch_ok, uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return (((lll->filter_policy & 0x01) == 0) &&
+		 (!devmatch_ok || ull_filter_lll_rl_idx_allowed(irkmatch_ok,
+								rl_idx))) ||
+		(((lll->filter_policy & 0x01) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(rl_idx)));
+#else
+	return ((lll->filter_policy & 0x01) == 0U) ||
+		devmatch_ok;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+static inline int isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
+			     uint8_t devmatch_id, uint8_t irkmatch_ok,
+			     uint8_t irkmatch_id, uint8_t rl_idx,
+			     uint8_t rssi_ready)
+{
+	struct node_rx_pdu *node_rx;
+	struct pdu_adv *pdu_adv_rx;
+	bool dir_report = false;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	pdu_adv_rx = (void *)node_rx->pdu;
+
+	if (0) {
+#if defined(CONFIG_BT_CENTRAL)
+	/* Initiator */
+	} else if ((lll->conn) &&
+		   isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
+		struct lll_conn *lll_conn;
+		struct node_rx_ftr *ftr;
+		struct node_rx_pdu *rx;
+		struct pdu_adv *pdu_tx;
+		uint32_t conn_interval_us;
+		uint32_t conn_offset_us;
+		uint32_t conn_space_us;
+		struct evt_hdr *evt;
+		uint32_t pdu_end_us;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		bt_addr_t *lrpa;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		int ret;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			rx = ull_pdu_rx_alloc_peek(4);
+		} else {
+			rx = ull_pdu_rx_alloc_peek(3);
+		}
+
+		if (!rx) {
+			return -ENOBUFS;
+		}
+
+		pdu_end_us = radio_tmr_end_get();
+		if (!lll->ticks_window) {
+			uint32_t scan_interval_us;
+
+			/* FIXME: is this correct for continuous scanning? */
+			scan_interval_us = lll->interval * 625U;
+			pdu_end_us %= scan_interval_us;
+		}
+		evt = HDR_LLL2EVT(lll);
+		if (pdu_end_us > (HAL_TICKER_TICKS_TO_US(evt->ticks_slot) -
+				  EVENT_IFS_US - 352 - EVENT_OVERHEAD_START_US -
+				  EVENT_TICKER_RES_MARGIN_US)) {
+			return -ETIME;
+		}
+
+		radio_switch_complete_and_disable();
+
+		/* Acquire the connection context */
+		lll_conn = lll->conn;
+
+		/* Tx the connect request packet */
+		pdu_tx = (void *)radio_pkt_scratch_get();
+		pdu_tx->type = PDU_ADV_TYPE_CONNECT_IND;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			pdu_tx->chan_sel = 1;
+		} else {
+			pdu_tx->chan_sel = 0;
+		}
+
+		pdu_tx->rx_addr = pdu_adv_rx->tx_addr;
+		pdu_tx->len = sizeof(struct pdu_adv_connect_ind);
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		lrpa = ull_filter_lll_lrpa_get(rl_idx);
+		if (lll->rpa_gen && lrpa) {
+			pdu_tx->tx_addr = 1;
+			memcpy(&pdu_tx->connect_ind.init_addr[0], lrpa->val,
+			       BDADDR_SIZE);
+		} else {
+#else
+		if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+			pdu_tx->tx_addr = lll->init_addr_type;
+			memcpy(&pdu_tx->connect_ind.init_addr[0],
+			       &lll->init_addr[0], BDADDR_SIZE);
+		}
+		memcpy(&pdu_tx->connect_ind.adv_addr[0],
+		       &pdu_adv_rx->adv_ind.addr[0], BDADDR_SIZE);
+		memcpy(&pdu_tx->connect_ind.access_addr[0],
+		       &lll_conn->access_addr[0], 4);
+		memcpy(&pdu_tx->connect_ind.crc_init[0],
+		       &lll_conn->crc_init[0], 3);
+		pdu_tx->connect_ind.win_size = 1;
+
+		conn_interval_us = (uint32_t)lll_conn->interval * 1250U;
+		conn_offset_us = radio_tmr_end_get() + 502 + 1250;
+
+		if (!IS_ENABLED(CONFIG_BT_CTLR_SCHED_ADVANCED) ||
+		    lll->conn_win_offset_us == 0U) {
+			conn_space_us = conn_offset_us;
+			pdu_tx->connect_ind.win_offset = sys_cpu_to_le16(0);
+		} else {
+			conn_space_us = lll->conn_win_offset_us;
+			while ((conn_space_us & ((uint32_t)1 << 31)) ||
+			       (conn_space_us < conn_offset_us)) {
+				conn_space_us += conn_interval_us;
+			}
+			pdu_tx->connect_ind.win_offset =
+				sys_cpu_to_le16((conn_space_us -
+						 conn_offset_us) / 1250U);
+			pdu_tx->connect_ind.win_size++;
+		}
+
+		pdu_tx->connect_ind.interval =
+			sys_cpu_to_le16(lll_conn->interval);
+		pdu_tx->connect_ind.latency =
+			sys_cpu_to_le16(lll_conn->latency);
+		pdu_tx->connect_ind.timeout =
+			sys_cpu_to_le16(lll->conn_timeout);
+		memcpy(&pdu_tx->connect_ind.chan_map[0],
+		       &lll_conn->data_chan_map[0],
+		       sizeof(pdu_tx->connect_ind.chan_map));
+		pdu_tx->connect_ind.hop = lll_conn->data_chan_hop;
+		pdu_tx->connect_ind.sca = lll_clock_sca_local_get();
+
+		radio_pkt_tx_set(pdu_tx);
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+		radio_isr_set(isr_cleanup, lll);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end
+			 * used in ISR profiling, hence back it up
+			 * for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		if (rssi_ready) {
+			lll_conn->rssi_latest =  radio_rssi_get();
+		}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+		/* block CPU so that there is no CRC error on pdu tx,
+		 * this is only needed if we want the CPU to sleep.
+		 * while(!radio_has_disabled())
+		 * {cpu_sleep();}
+		 * radio_status_reset();
+		 */
+
+		/* Stop further LLL radio events */
+		ret = lll_stop(lll);
+		LL_ASSERT(!ret);
+
+		rx = ull_pdu_rx_alloc();
+
+		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+		rx->hdr.handle = 0xffff;
+
+		uint8_t pdu_adv_rx_chan_sel = pdu_adv_rx->chan_sel;
+		memcpy(rx->pdu, pdu_tx, (offsetof(struct pdu_adv, connect_ind) +
+					  sizeof(struct pdu_adv_connect_ind)));
+
+		/* Overwrite the sent chan sel with received chan sel, when
+		 * giving this PDU to the higher layer. */
+		pdu_adv_rx = (void *)rx->pdu;
+		pdu_adv_rx->chan_sel = pdu_adv_rx_chan_sel;
+
+		ftr = &(rx->hdr.rx_ftr);
+
+		ftr->param = lll;
+		ftr->ticks_anchor = radio_tmr_start_get();
+		ftr->radio_end_us = conn_space_us -
+				    radio_tx_chain_delay_get(0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
+		ftr->lrpa_used = lll->rpa_gen && lrpa;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			ftr->extra = ull_pdu_rx_alloc();
+		}
+
+		ull_rx_put(rx->hdr.link, rx);
+		ull_rx_sched();
+
+		return 0;
+#endif /* CONFIG_BT_CENTRAL */
+
+	/* Active scanner */
+	} else if (((pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND)) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_adv_ind)) &&
+		   lll->type &&
+#if defined(CONFIG_BT_CENTRAL)
+		   !lll->conn) {
+#else /* !CONFIG_BT_CENTRAL */
+		   1) {
+#endif /* !CONFIG_BT_CENTRAL */
+		struct pdu_adv *pdu_tx;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		bt_addr_t *lrpa;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		int err;
+
+		/* setup tIFS switching */
+		radio_tmr_tifs_set(EVENT_IFS_US);
+		radio_switch_complete_and_rx(0);
+
+		/* save the adv packet */
+		err = isr_rx_scan_report(lll, rssi_ready,
+					 irkmatch_ok ? rl_idx : FILTER_IDX_NONE,
+					 false);
+		if (err) {
+			return err;
+		}
+
+		/* prepare the scan request packet */
+		pdu_tx = (void *)radio_pkt_scratch_get();
+		pdu_tx->type = PDU_ADV_TYPE_SCAN_REQ;
+		pdu_tx->rx_addr = pdu_adv_rx->tx_addr;
+		pdu_tx->len = sizeof(struct pdu_adv_scan_req);
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		lrpa = ull_filter_lll_lrpa_get(rl_idx);
+		if (lll->rpa_gen && lrpa) {
+			pdu_tx->tx_addr = 1;
+			memcpy(&pdu_tx->scan_req.scan_addr[0], lrpa->val,
+			       BDADDR_SIZE);
+		} else {
+#else
+		if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+			pdu_tx->tx_addr = lll->init_addr_type;
+			memcpy(&pdu_tx->scan_req.scan_addr[0],
+			       &lll->init_addr[0], BDADDR_SIZE);
+		}
+		memcpy(&pdu_tx->scan_req.adv_addr[0],
+		       &pdu_adv_rx->adv_ind.addr[0], BDADDR_SIZE);
+
+		radio_pkt_tx_set(pdu_tx);
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+
+		}
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end
+			 * used in ISR profiling, hence back it up
+			 * for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+		/* switch scanner state to active */
+		lll->state = 1U;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		if (pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) {
+			lll->is_adv_ind = 1U;
+		}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+		radio_isr_set(isr_tx, lll);
+
+		return 0;
+	}
+	/* Passive scanner or scan responses */
+	else if (((((pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_NONCONN_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND)) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_adv_ind))) ||
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		   (pdu_adv_rx->len == sizeof(struct pdu_adv_direct_ind)) &&
+		   (/* allow directed adv packets addressed to this device */
+		    isr_scan_tgta_check(lll, false, pdu_adv_rx, rl_idx,
+					&dir_report))) ||
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_EXT_IND) &&
+		   (lll->phy)) ||
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_RSP) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_scan_rsp)) &&
+		   (lll->state != 0U) &&
+		   isr_scan_rsp_adva_matches(pdu_adv_rx))) &&
+		 (pdu_adv_rx->len != 0) &&
+#if defined(CONFIG_BT_CENTRAL)
+		   !lll->conn) {
+#else /* !CONFIG_BT_CENTRAL */
+		   1) {
+#endif /* !CONFIG_BT_CENTRAL */
+		uint32_t err;
+
+		/* save the scan response packet */
+		err = isr_rx_scan_report(lll, rssi_ready,
+					 irkmatch_ok ? rl_idx :
+						       FILTER_IDX_NONE,
+					 dir_report);
+		if (err) {
+			return err;
+		}
+	}
+	/* invalid PDU */
+	else {
+		/* ignore and close this rx/tx chain ( code below ) */
+		return -EINVAL;
+	}
+
+	return -ECANCELED;
+}
+
+static inline bool isr_scan_init_check(struct lll_scan *lll,
+				       struct pdu_adv *pdu, uint8_t rl_idx)
+{
+	return ((((lll->filter_policy & 0x01) != 0U) ||
+		 isr_scan_init_adva_check(lll, pdu, rl_idx)) &&
+		(((pdu->type == PDU_ADV_TYPE_ADV_IND) &&
+		  (pdu->len <= sizeof(struct pdu_adv_adv_ind))) ||
+		 ((pdu->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		  (pdu->len == sizeof(struct pdu_adv_direct_ind)) &&
+		  (/* allow directed adv packets addressed to this device */
+		   isr_scan_tgta_check(lll, true, pdu, rl_idx, NULL)))));
+}
+
+static inline bool isr_scan_init_adva_check(struct lll_scan *lll,
+					    struct pdu_adv *pdu, uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* Only applies to initiator with no whitelist */
+	if (rl_idx != FILTER_IDX_NONE) {
+		return (rl_idx == lll->rl_idx);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	return ((lll->adv_addr_type == pdu->tx_addr) &&
+		!memcmp(lll->adv_addr, &pdu->adv_ind.addr[0], BDADDR_SIZE));
+}
+
+static inline bool isr_scan_tgta_check(struct lll_scan *lll, bool init,
+				       struct pdu_adv *pdu, uint8_t rl_idx,
+				       bool *dir_report)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_addr_resolve(pdu->rx_addr,
+					   pdu->direct_ind.tgt_addr, rl_idx)) {
+		return true;
+	} else if (init && lll->rpa_gen &&
+		   ull_filter_lll_lrpa_get(rl_idx)) {
+		/* Initiator generating RPAs, and could not resolve TargetA:
+		 * discard
+		 */
+		return false;
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	return (((lll->init_addr_type == pdu->rx_addr) &&
+		!memcmp(lll->init_addr, pdu->direct_ind.tgt_addr,
+			BDADDR_SIZE))) ||
+		  /* allow directed adv packets where TargetA address
+		   * is resolvable private address (scanner only)
+		   */
+	       isr_scan_tgta_rpa_check(lll, pdu, dir_report);
+}
+
+static inline bool isr_scan_tgta_rpa_check(struct lll_scan *lll,
+					   struct pdu_adv *pdu,
+					   bool *dir_report)
+{
+	if (((lll->filter_policy & 0x02) != 0U) &&
+	    (pdu->rx_addr != 0) &&
+	    ((pdu->direct_ind.tgt_addr[5] & 0xc0) == 0x40)) {
+
+		if (dir_report) {
+			*dir_report = true;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool isr_scan_rsp_adva_matches(struct pdu_adv *srsp)
+{
+	struct pdu_adv *sreq = (void *)radio_pkt_scratch_get();
+
+	return ((sreq->rx_addr == srsp->tx_addr) &&
+		(memcmp(&sreq->scan_req.adv_addr[0],
+			&srsp->scan_rsp.addr[0], BDADDR_SIZE) == 0));
+}
+
+static int isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
+				uint8_t rl_idx, bool dir_report)
+{
+	struct node_rx_pdu *node_rx;
+
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (!node_rx) {
+		return -ENOBUFS;
+	}
+	ull_pdu_rx_alloc();
+
+	/* Prepare the report (adv or scan resp) */
+	node_rx->hdr.handle = 0xffff;
+	if (0) {
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	} else if (_radio.advertiser.is_enabled &&
+		   _radio.advertiser.is_mesh) {
+		node_rx->hdr.type = NODE_RX_TYPE_MESH_REPORT;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	} else if (lll->phy) {
+		struct pdu_adv *pdu_adv_rx;
+
+		switch (lll->phy) {
+		case BIT(0):
+			node_rx->hdr.type = NODE_RX_TYPE_EXT_1M_REPORT;
+			break;
+
+		case BIT(2):
+			node_rx->hdr.type = NODE_RX_TYPE_EXT_CODED_REPORT;
+			break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+
+		pdu_adv_rx = (void *)node_rx->pdu;
+		switch (pdu_adv_rx->type) {
+		case PDU_ADV_TYPE_SCAN_RSP:
+			if (lll->is_adv_ind) {
+				pdu_adv_rx->type =
+					PDU_ADV_TYPE_ADV_IND_SCAN_RSP;
+			}
+			break;
+
+		case PDU_ADV_TYPE_EXT_IND:
+			{
+				struct node_rx_ftr *ftr;
+
+				ftr = &(node_rx->hdr.rx_ftr);
+				ftr->param = lll;
+				ftr->ticks_anchor = radio_tmr_start_get();
+				ftr->radio_end_us =
+					radio_tmr_end_get() -
+					radio_rx_chain_delay_get(lll->phy, 1);
+			}
+			break;
+		}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	} else {
+		node_rx->hdr.type = NODE_RX_TYPE_REPORT;
+	}
+
+	node_rx->hdr.rx_ftr.rssi = (rssi_ready) ?
+				   (radio_rssi_get() & 0x7f)
+				   : 0x7f;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* save the resolving list index. */
+	node_rx->hdr.rx_ftr.rl_idx = rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	/* save the directed adv report flag */
+	node_rx->hdr.rx_ftr.direct = dir_report;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
+		/* save channel and anchor point ticks. */
+		node_rx->hdr.rx_ftr.chan = _radio.scanner.chan - 1;
+		node_rx->hdr.rx_ftr.ticks_anchor = _radio.ticks_anchor;
+	}
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+	ull_rx_put(node_rx->hdr.link, node_rx);
+	ull_rx_sched();
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_scan_aux_init(void);
+int lll_scan_aux_reset(void);
+void lll_scan_aux_prepare(void *param);
+
+extern uint8_t ull_scan_aux_lll_handle_get(struct lll_scan_aux *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan_aux.c	(working copy)
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_filter.h"
+#include "lll_scan.h"
+#include "lll_scan_aux.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_scan_aux
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
+static void isr_rx(void *param);
+static int isr_rx_pdu(struct lll_scan_aux *lll, uint8_t rssi_ready);
+static void isr_done(void *param);
+
+static uint16_t trx_cnt; /* TODO: move to a union in lll.c, common to all roles
+			  */
+
+int lll_scan_aux_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_scan_aux_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_scan_aux_prepare(void *param)
+{
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, param);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	struct node_rx_pdu *node_rx;
+	struct lll_scan_aux *lll;
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	struct evt_hdr *evt;
+	uint32_t remainder_us;
+	uint32_t remainder;
+	uint32_t hcto;
+	uint32_t aa;
+
+	DEBUG_RADIO_START_O(1);
+
+	/* Start setting up Radio h/w */
+	radio_reset();
+
+	/* Reset Tx/rx count */
+	trx_cnt = 0U;
+
+	lll = p->param;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif
+
+	radio_phy_set(lll->phy, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy << 1));
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	radio_pkt_rx_set(node_rx->pdu);
+
+	aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+
+	lll_chan_set(lll->chan);
+
+	radio_isr_set(isr_rx, lll);
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_tx(lll->phy, 0, lll->phy, 1);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	/* TODO: privacy */
+
+	/* Calculate event timings, coarse and fine */
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	hcto = remainder_us + lll->window_size_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_ready_delay_get(lll->phy, 1);
+	hcto += addr_us_get(lll->phy);
+	hcto += radio_rx_chain_delay_get(lll->phy, 1);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_ready_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto += radio_rx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+
+	/* capture end of Rx-ed PDU, extended scan to schedule auxiliary
+	 * channel chaining or to create periodic sync.
+	 */
+	radio_tmr_end_capture();
+
+	/* scanner always measures RSSI */
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(lll->phy, 1) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_SCAN_AUX_BASE +
+				   ull_scan_aux_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(isr_done, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_O(1);
+
+	return 0;
+}
+
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_done, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	lll_done(param);
+}
+
+static void isr_rx(void *param)
+{
+	struct lll_scan_aux *lll;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t crc_ok;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = rssi_ready = 0U;
+	}
+
+	/* Clear radio rx status and events */
+	lll_isr_rx_status_reset();
+
+	lll = param;
+
+	/* No Rx */
+	if (!trx_done) {
+		/*آ TODO: Combine the early exit with above if-then-else block
+		 */
+		goto isr_rx_do_close;
+	}
+
+	if (crc_ok) {
+		int err;
+
+		err = isr_rx_pdu(lll, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(isr_done, lll);
+	radio_disable();
+}
+
+static int isr_rx_pdu(struct lll_scan_aux *lll, uint8_t rssi_ready)
+{
+	struct node_rx_pdu *node_rx;
+	struct node_rx_ftr *ftr;
+	struct pdu_adv *pdu;
+
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (!node_rx) {
+		return -ENOBUFS;
+	}
+
+	pdu = (void *)node_rx->pdu;
+	if ((pdu->type != PDU_ADV_TYPE_EXT_IND) || !pdu->len) {
+		return -EINVAL;
+	}
+
+	ull_pdu_rx_alloc();
+
+	trx_cnt++;
+
+	switch (lll->phy) {
+	case BIT(0):
+		node_rx->hdr.type = NODE_RX_TYPE_EXT_1M_REPORT;
+		break;
+
+	case BIT(1):
+		node_rx->hdr.type = NODE_RX_TYPE_EXT_2M_REPORT;
+		break;
+
+	case BIT(2):
+		node_rx->hdr.type = NODE_RX_TYPE_EXT_CODED_REPORT;
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	ftr = &(node_rx->hdr.rx_ftr);
+	ftr->param = lll;
+	ftr->ticks_anchor = radio_tmr_start_get();
+	ftr->radio_end_us = radio_tmr_end_get() -
+			    radio_rx_chain_delay_get(lll->phy, 1);
+
+	ftr->rssi = (rssi_ready) ? (radio_rssi_get() & 0x7f) : 0x7f;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* TODO: Use correct rl_idx value when privacy support is added */
+	ftr->rl_idx = FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	ull_rx_put(node_rx->hdr.link, node_rx);
+	ull_rx_sched();
+
+	return -ECANCELED;
+}
+
+static void isr_done(void *param)
+{
+	struct event_done_extra *e;
+
+	lll_isr_status_reset();
+
+	if (!trx_cnt) {
+		e = ull_event_done_extra_get();
+		LL_ASSERT(e);
+
+		e->type = EVENT_DONE_EXTRA_TYPE_SCAN_AUX;
+	}
+
+	lll_isr_cleanup(param);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sched.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sched.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sched.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+extern void ull_sched_mfy_after_mstr_offset_get(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_slave_init(void);
+int lll_slave_reset(void);
+void lll_slave_prepare(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c	(working copy)
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_conn.h"
+#include "lll_slave.h"
+#include "lll_chan.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_slave
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+
+int lll_slave_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_slave_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_slave_prepare(void *param)
+{
+	struct lll_prepare_param *p;
+	struct lll_conn *lll;
+	uint16_t elapsed;
+	int err;
+
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	p = param;
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	lll = p->param;
+
+	/* Save the (latency + 1) for use in event */
+	lll->latency_prepare += elapsed;
+
+	/* Accumulate window widening */
+	lll->slave.window_widening_prepare_us +=
+	    lll->slave.window_widening_periodic_us * elapsed;
+	if (lll->slave.window_widening_prepare_us >
+	    lll->slave.window_widening_max_us) {
+		lll->slave.window_widening_prepare_us =
+			lll->slave.window_widening_max_us;
+	}
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	uint16_t event_counter;
+	uint32_t remainder_us;
+	uint8_t data_chan_use;
+	struct lll_conn *lll;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+	uint32_t hcto;
+
+	DEBUG_RADIO_START_S(1);
+
+	lll = p->param;
+
+	/* Check if stopped (on disconnection between prepare and pre-empt)
+	 */
+	if (unlikely(lll->handle == 0xFFFF)) {
+		int err;
+
+		err = lll_hfclock_off();
+		LL_ASSERT(err >= 0);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_CLOSE_S(0);
+		return 0;
+	}
+
+	/* Reset connection event global variables */
+	lll_conn_prepare_reset();
+
+	/* Deduce the latency */
+	lll->latency_event = lll->latency_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->latency_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->latency_prepare;
+
+	/* Reset accumulated latencies */
+	lll->latency_prepare = 0;
+
+	if (lll->data_chan_sel) {
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+#else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+		data_chan_use = 0;
+		LL_ASSERT(0);
+#endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+	} else {
+		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
+					       lll->data_chan_hop,
+					       lll->latency_event,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+	}
+
+	/* current window widening */
+	lll->slave.window_widening_event_us +=
+		lll->slave.window_widening_prepare_us;
+	lll->slave.window_widening_prepare_us = 0;
+	if (lll->slave.window_widening_event_us >
+	    lll->slave.window_widening_max_us) {
+		lll->slave.window_widening_event_us =
+			lll->slave.window_widening_max_us;
+	}
+
+	/* current window size */
+	lll->slave.window_size_event_us +=
+		lll->slave.window_size_prepare_us;
+	lll->slave.window_size_prepare_us = 0;
+
+	/* Start setting up Radio h/w */
+	radio_reset();
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	lll_conn_rx_pkt_set(lll);
+
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+
+	lll_chan_set(data_chan_use);
+
+	radio_isr_set(lll_conn_isr_rx, lll);
+
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx,
+				     lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	radio_tmr_aa_capture();
+	radio_tmr_aa_save(0);
+
+	hcto = remainder_us +
+	       ((EVENT_JITTER_US + EVENT_TICKER_RES_MARGIN_US +
+		 lll->slave.window_widening_event_us) << 1) +
+	       lll->slave.window_size_event_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_ready_delay_get(lll->phy_rx, 1);
+	hcto += addr_us_get(lll->phy_rx);
+	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_ready_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto += radio_rx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(lll->phy_rx, 1) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
+	defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_tmr_end_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	radio_rssi_measure();
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_CONN_BASE + lll->handle),
+			     ticks_at_event)) {
+		radio_isr_set(lll_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_S(1);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c	(working copy)
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+
+#include <toolchain.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_chan.h"
+#include "lll_sync.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_sync
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *p);
+static void isr_rx(void *param);
+
+int lll_sync_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_sync_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_sync_prepare(void *param)
+{
+	struct lll_prepare_param *p;
+	struct lll_sync *lll;
+	uint16_t elapsed;
+	int err;
+
+	/* Request to start HF Clock */
+	err = lll_hfclock_on();
+	LL_ASSERT(err >= 0);
+
+	p = param;
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	lll = p->param;
+
+	/* Save the (skip + 1) for use in event */
+	lll->skip_prepare += elapsed;
+
+	/* Accumulate window widening */
+	lll->window_widening_prepare_us += lll->window_widening_periodic_us *
+					   elapsed;
+	if (lll->window_widening_prepare_us > lll->window_widening_max_us) {
+		lll->window_widening_prepare_us = lll->window_widening_max_us;
+	}
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *p)
+{
+	struct node_rx_pdu *node_rx;
+	uint32_t ticks_at_event;
+	uint32_t ticks_at_start;
+	uint16_t event_counter;
+	uint32_t remainder_us;
+	uint8_t data_chan_use;
+	struct lll_sync *lll;
+	struct evt_hdr *evt;
+	uint32_t remainder;
+	uint32_t hcto;
+
+	DEBUG_RADIO_START_O(1);
+
+	lll = p->param;
+
+	/* Deduce the skip */
+	lll->skip_event = lll->skip_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->skip_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->skip_prepare;
+
+	/* Reset accumulated latencies */
+	lll->skip_prepare = 0;
+
+	/* Current window widening */
+	lll->window_widening_event_us += lll->window_widening_prepare_us;
+	lll->window_widening_prepare_us = 0;
+	if (lll->window_widening_event_us > lll->window_widening_max_us) {
+		lll->window_widening_event_us =	lll->window_widening_max_us;
+	}
+
+	/* Calculate the radio channel to use */
+	data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+				       &lll->data_chan_map[0],
+				       lll->data_chan_count);
+
+	/* Start setting up Radio h/w */
+	radio_reset();
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	radio_tx_power_set(lll->tx_pwr_lvl);
+#else
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	radio_phy_set(lll->phy, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy << 1));
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	radio_pkt_rx_set(node_rx->pdu);
+
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+
+	lll_chan_set(data_chan_use);
+
+	radio_isr_set(isr_rx, lll);
+
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+	radio_switch_complete_and_disable();
+
+	ticks_at_event = p->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = p->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	radio_tmr_aa_capture();
+
+	hcto = remainder_us +
+	       ((EVENT_JITTER_US + EVENT_TICKER_RES_MARGIN_US +
+		 lll->window_widening_event_us) << 1) +
+	       lll->window_size_event_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_ready_delay_get(lll->phy, 1);
+	hcto += addr_us_get(lll->phy);
+	hcto += radio_rx_chain_delay_get(lll->phy, 1);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_ready_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto += radio_rx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+	radio_tmr_end_capture();
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(lll->phy_rx, 1) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_SCAN_SYNC_BASE +
+				   ull_sync_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(lll_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_O(1);
+	return 0;
+}
+
+static void isr_rx(void *param)
+{
+	struct event_done_extra *e;
+	struct lll_sync *lll;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t trx_cnt;
+	uint8_t crc_ok;
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = rssi_ready = 0U;
+	}
+
+	/* Clear radio rx status and events */
+	lll_isr_rx_status_reset();
+
+	lll = param;
+
+	/* No Rx */
+	trx_cnt = 0U;
+	if (!trx_done) {
+		/*آ TODO: Combine the early exit with above if-then-else block
+		 */
+		goto isr_rx_done;
+	}
+
+	/* Rx-ed */
+	trx_cnt = 1U;
+
+	/* Check CRC and generate Periodic Advertising Report */
+	if (crc_ok) {
+		/* TODO: */
+		BT_INFO("CRC OK, Periodic event sync-ed, report generation"
+			" is unsupported, work in progress.");
+	}
+
+isr_rx_done:
+	/* Calculate and place the drift information in done event */
+	e = ull_event_done_extra_get();
+	LL_ASSERT(e);
+
+	e->type = EVENT_DONE_EXTRA_TYPE_SYNC;
+	e->trx_cnt = trx_cnt;
+	e->crc_valid = crc_ok;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
+#else /* !CONFIG_BT_CTLR_PHY */
+	e->drift.preamble_to_addr_us = addr_us_get(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	e->drift.start_to_address_actual_us = radio_tmr_aa_get() -
+					      radio_tmr_ready_get();
+	e->drift.window_widening_event_us = lll->window_widening_event_us;
+
+	/* Reset window widening, as anchor point sync-ed */
+	lll->window_widening_event_us = 0U;
+	lll->window_size_event_us = 0U;
+
+	lll_isr_cleanup(param);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_test.c	(working copy)
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2017-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <soc.h>
+#include <drivers/clock_control.h>
+
+#include "hal/cpu.h"
+#include "hal/cntr.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "util/memq.h"
+
+#include "lll.h"
+#include "lll_clock.h"
+#include "lll_internal.h"
+
+#include "ll_test.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_lll_test
+#include "common/log.h"
+#include "hal/debug.h"
+
+#define CNTR_MIN_DELTA 3
+
+static const uint32_t test_sync_word = 0x71764129;
+static uint8_t        test_phy;
+static uint8_t        test_phy_flags;
+static uint16_t       test_num_rx;
+static bool        started;
+
+/* NOTE: The PRBS9 sequence used as packet payload.
+ * The bytes in the sequence are in the right order, but the bits of each byte
+ * in the array are reverse from that found by running the PRBS9 algorithm. This
+ * is done to transmit MSbit first on air.
+ */
+
+static const uint8_t prbs9[] = {
+	0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B,
+	0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23,
+	0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B,
+	0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA,
+	0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A,
+	0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE,
+	0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E,
+	0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87,
+	0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5,
+	0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11,
+	0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D,
+	0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65,
+	0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D,
+	0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F,
+	0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF,
+	0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3,
+	0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2,
+	0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88,
+	0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E,
+	0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32,
+	0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6,
+	0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF,
+	0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7,
+	0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1,
+	0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1,
+	0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44,
+	0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27,
+	0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99,
+	0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3,
+	0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57,
+	0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB,
+	0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7};
+
+/* TODO: fill correct prbs15 */
+static const uint8_t prbs15[255] = { 0x00, };
+
+static uint8_t tx_req;
+static uint8_t volatile tx_ack;
+
+static void isr_tx(void *param)
+{
+	uint32_t l, i, s, t;
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_lna_disable();
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* Exit if radio disabled */
+	if (((tx_req - tx_ack) & 0x01) == 0U) {
+		tx_ack = tx_req;
+
+		return;
+	}
+
+	/* LE Test Packet Interval */
+	l = radio_tmr_end_get() - radio_tmr_ready_get();
+	i = ((l + 249 + 624) / 625) * 625U;
+	t = radio_tmr_end_get() - l + i;
+	t -= radio_tx_ready_delay_get(test_phy, test_phy_flags);
+
+	/* Set timer capture in the future. */
+	radio_tmr_sample();
+	s = radio_tmr_sample_get();
+	while (t < s) {
+		t += 625U;
+	}
+
+	/* Setup next Tx */
+	radio_switch_complete_and_disable();
+	radio_tmr_start_us(1, t);
+	radio_tmr_aa_capture();
+	radio_tmr_end_capture();
+
+	/* TODO: check for probable stale timer capture being set */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(t + radio_tx_ready_delay_get(test_phy,
+							      test_phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+}
+
+static void isr_rx(void *param)
+{
+	uint8_t crc_ok = 0U;
+	uint8_t trx_done;
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+	/* Exit if radio disabled */
+	if (!trx_done) {
+		return;
+	}
+
+	/* Setup next Rx */
+	radio_switch_complete_and_rx(test_phy);
+
+	/* Count Rx-ed packets */
+	if (crc_ok) {
+		test_num_rx++;
+	}
+}
+
+static uint32_t init(uint8_t chan, uint8_t phy, void (*isr)(void *))
+{
+	int err;
+
+	if (started) {
+		return 1;
+	}
+
+	/* start coarse timer */
+	cntr_start();
+
+	/* Setup resources required by Radio */
+	err = lll_hfclock_on_wait();
+
+	/* Reset Radio h/w */
+	radio_reset();
+	radio_isr_set(isr, NULL);
+
+	/* Store value needed in Tx/Rx ISR */
+	if (phy < 0x04) {
+		test_phy = BIT(phy - 1);
+		test_phy_flags = 1U;
+	} else {
+		test_phy = BIT(2);
+		test_phy_flags = 0U;
+	}
+
+	/* Setup Radio in Tx/Rx */
+	/* NOTE: No whitening in test mode. */
+	radio_phy_set(test_phy, test_phy_flags);
+	radio_tmr_tifs_set(150);
+	radio_tx_power_max_set();
+	radio_freq_chan_set((chan << 1) + 2);
+	radio_aa_set((uint8_t *)&test_sync_word);
+	radio_crc_configure(0x65b, 0x555555);
+	radio_pkt_configure(8, 255, (test_phy << 1));
+
+	return 0;
+}
+
+uint32_t ll_test_tx(uint8_t chan, uint8_t len, uint8_t type, uint8_t phy)
+{
+	uint32_t start_us;
+	uint8_t *payload;
+	uint8_t *pdu;
+	uint32_t err;
+
+	if ((type > 0x07) || !phy || (phy > 0x04)) {
+		return 1;
+	}
+
+	err = init(chan, phy, isr_tx);
+	if (err) {
+		return err;
+	}
+
+	tx_req++;
+
+	pdu = radio_pkt_scratch_get();
+	payload = &pdu[2];
+
+	switch (type) {
+	case 0x00:
+		memcpy(payload, prbs9, len);
+		break;
+
+	case 0x01:
+		memset(payload, 0x0f, len);
+		break;
+
+	case 0x02:
+		memset(payload, 0x55, len);
+		break;
+
+	case 0x03:
+		memcpy(payload, prbs15, len);
+		break;
+
+	case 0x04:
+		memset(payload, 0xff, len);
+		break;
+
+	case 0x05:
+		memset(payload, 0x00, len);
+		break;
+
+	case 0x06:
+		memset(payload, 0xf0, len);
+		break;
+
+	case 0x07:
+		memset(payload, 0xaa, len);
+		break;
+	}
+
+	pdu[0] = type;
+	pdu[1] = len;
+
+	radio_pkt_tx_set(pdu);
+	radio_switch_complete_and_disable();
+	start_us = radio_tmr_start(1, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
+	radio_tmr_aa_capture();
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(start_us +
+				 radio_tx_ready_delay_get(test_phy,
+							  test_phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(start_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	started = true;
+
+	return 0;
+}
+
+uint32_t ll_test_rx(uint8_t chan, uint8_t phy, uint8_t mod_idx)
+{
+	uint32_t err;
+
+	if (!phy || (phy > 0x03)) {
+		return 1;
+	}
+
+	err = init(chan, phy, isr_rx);
+	if (err) {
+		return err;
+	}
+
+	radio_pkt_rx_set(radio_pkt_scratch_get());
+	radio_switch_complete_and_rx(test_phy);
+	radio_tmr_start(0, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_on();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	started = true;
+
+	return 0;
+}
+
+uint32_t ll_test_end(uint16_t *num_rx)
+{
+	int err;
+	uint8_t ack;
+
+	if (!started) {
+		return 1;
+	}
+
+	/* Return packets Rx-ed/Completed */
+	*num_rx = test_num_rx;
+	test_num_rx = 0U;
+
+	/* Disable Radio, if in Rx test */
+	ack = tx_ack;
+	if (tx_req == ack) {
+		radio_disable();
+	} else {
+		/* Wait for Tx to complete */
+		tx_req = ack + 2;
+		while (tx_req != tx_ack) {
+			cpu_sleep();
+		}
+	}
+
+	/* Stop packet timer */
+	radio_tmr_stop();
+
+	/* Release resources acquired for Radio */
+	err = lll_hfclock_off();
+	LL_ASSERT(err >= 0);
+
+	/* Stop coarse timer */
+	cntr_stop();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_off();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	started = false;
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_tim_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_tim_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_tim_internal.h	(working copy)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Range Delay
+ * Refer to BT Spec v5.1 Vol.6, Part B, Section 4.2.3 Range Delay
+ * "4 / 1000" is an approximation of the propagation time in us of the
+ * signal to travel 1 meter.
+ */
+#define RANGE_DISTANCE 1000 /* meters */
+#define RANGE_DELAY_US (2 * RANGE_DISTANCE * 4 / 1000)
+
+static inline uint32_t addr_us_get(uint8_t phy)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return 40;
+	case BIT(1):
+		return 24;
+	case BIT(2):
+		return 376;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_vendor.h	(working copy)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define EVENT_OVERHEAD_XTAL_US        1500
+#define EVENT_OVERHEAD_PREEMPT_US     0    /* if <= min, then dynamic preempt */
+#define EVENT_OVERHEAD_PREEMPT_MIN_US 0
+#define EVENT_OVERHEAD_PREEMPT_MAX_US EVENT_OVERHEAD_XTAL_US
+#define EVENT_OVERHEAD_START_US       300
+/* Worst-case time margin needed after event end-time in the air
+ * (done/preempt race margin + power-down/chain delay)
+ */
+#define EVENT_OVERHEAD_END_US         40
+#define EVENT_JITTER_US               16
+/* Inter-Event Space (IES) */
+#define EVENT_TIES_US                 625
+/* Ticker resolution margin
+ * Needed due to the lack of fine timing resolution in ticker_start
+ * and ticker_update. Set to 32 us, which is ~1 tick with 32768 Hz
+ * clock.
+ */
+#define EVENT_TICKER_RES_MARGIN_US    32
+
+#define EVENT_RX_JITTER_US(phy) 16    /* Radio Rx timing uncertainty */
+#define EVENT_RX_TO_US(phy) ((((((phy)&0x03) + 4)<<3)/BIT((((phy)&0x3)>>1))) + \
+				  EVENT_RX_JITTER_US(phy))
+
+/* TODO - fix up numbers re. HW */
+#define EVENT_RX_TX_TURNAROUND(phy)  ((phy) == 1?100:((phy) == 2 ? 80:900))
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nrf.cmake
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nrf.cmake	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/nrf.cmake	(working copy)
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: Apache-2.0
+
+if(CONFIG_BT_LL_SW_SPLIT)
+  zephyr_library_sources(
+    ll_sw/nordic/lll/lll.c
+    ll_sw/nordic/lll/lll_clock.c
+    )
+  if(CONFIG_BT_BROADCASTER)
+    zephyr_library_sources(
+      ll_sw/nordic/lll/lll_adv.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_EXT
+      ll_sw/nordic/lll/lll_adv_aux.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_PERIODIC
+      ll_sw/nordic/lll/lll_adv_sync.c
+      )
+  endif()
+  if(CONFIG_BT_OBSERVER)
+    zephyr_library_sources(
+      ll_sw/nordic/lll/lll_scan.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_ADV_EXT
+      ll_sw/nordic/lll/lll_scan_aux.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CTLR_SYNC_PERIODIC
+      ll_sw/nordic/lll/lll_sync.c
+      )
+  endif()
+  if(CONFIG_BT_CONN)
+    zephyr_library_sources(
+      ll_sw/nordic/lll/lll_conn.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_PERIPHERAL
+      ll_sw/nordic/lll/lll_slave.c
+      )
+    zephyr_library_sources_ifdef(
+      CONFIG_BT_CENTRAL
+      ll_sw/nordic/lll/lll_master.c
+      )
+  endif()
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_CTLR_DTM
+    ll_sw/nordic/lll/lll_test.c
+    )
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_CTLR_PROFILE_ISR
+    ll_sw/nordic/lll/lll_prof.c
+    )
+  zephyr_library_include_directories(
+    ll_sw/nordic/lll
+    )
+endif()
+
+zephyr_library_sources(
+  ll_sw/nordic/hal/nrf5/cntr.c
+  ll_sw/nordic/hal/nrf5/ecb.c
+  ll_sw/nordic/hal/nrf5/radio/radio.c
+  ll_sw/nordic/hal/nrf5/mayfly.c
+  ll_sw/nordic/hal/nrf5/ticker.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_SOC_FAMILY_NRF
+  hci/nordic/hci_vendor.c
+  )
+
+zephyr_library_include_directories(
+  ll_sw/nordic
+  hci/nordic
+)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa.cmake
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa.cmake	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa.cmake	(working copy)
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: Apache-2.0
+
+if(CONFIG_BT_LL_SW_SPLIT)
+  zephyr_library_sources(
+    ll_sw/openisa/lll/lll.c
+    )
+  if(CONFIG_BT_BROADCASTER)
+    zephyr_library_sources(
+      ll_sw/openisa/lll/lll_adv.c
+      )
+  endif()
+  if(CONFIG_BT_OBSERVER)
+    zephyr_library_sources(
+      ll_sw/openisa/lll/lll_scan.c
+      )
+  endif()
+  if(CONFIG_BT_CONN)
+    zephyr_library_sources(
+      ll_sw/openisa/lll/lll_clock.c
+      ll_sw/openisa/lll/lll_conn.c
+    )
+    if(CONFIG_BT_PERIPHERAL)
+      zephyr_library_sources(
+        ll_sw/openisa/lll/lll_slave.c
+      )
+    endif()
+    if(CONFIG_BT_CENTRAL)
+      zephyr_library_sources(
+        ll_sw/openisa/lll/lll_master.c
+      )
+    endif()
+  endif()
+    zephyr_library_include_directories(
+      ll_sw/openisa/lll
+    )
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_CTLR_DTM
+    ll_sw/openisa/lll/lll_test.c
+  )
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_CTLR_PROFILE_ISR
+    ll_sw/openisa/lll/lll_test.c
+  )
+endif()
+
+zephyr_library_sources_ifdef(
+  CONFIG_SOC_OPENISA_RV32M1_RISCV32
+  ll_sw/openisa/hal/RV32M1/cntr.c
+  ll_sw/openisa/hal/RV32M1/ecb.c
+  ll_sw/openisa/hal/RV32M1/radio/radio.c
+  ll_sw/openisa/hal/RV32M1/mayfly.c
+  ll_sw/openisa/hal/RV32M1/ticker.c
+  )
+
+if(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
+  zephyr_library_include_directories(
+    ll_sw/openisa
+    hci/openisa
+    )
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/cntr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/cntr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/cntr.c	(working copy)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+
+#include "hal/cntr.h"
+
+#define LOG_MODULE_NAME bt_ctlr_cntr
+#include "common/log.h"
+#include "hal/debug.h"
+#include <dt-bindings/interrupt-controller/openisa-intmux.h>
+#include "ll_irqs.h"
+
+
+#define PCS_SOURCE_RTC 2
+
+void cntr_init(void)
+{
+	/* RTC config */
+	/*
+	 * Reset all RTC registers except for the SWR bit
+	 * and the RTC_WAR and RTC_RAR
+	 */
+	RTC->CR |= RTC_CR_SWR_MASK;
+	RTC->CR &= ~RTC_CR_SWR_MASK;
+
+	/*
+	 * Set TSR register to 0x1 to avoid the timer invalid (TIF) bit being
+	 * set in the SR register
+	 */
+	RTC->TSR = 1;
+
+	/* Enable the RTC 32.768 kHz oscillator and clock on RTC_CLKOUT  */
+	RTC->CR |= (RTC_CR_CPS(1) | RTC_CR_OSCE(1));
+
+	/* LPTMR config */
+	/* Disable the timer and clear any pending IRQ. */
+	LPTMR1->CSR = LPTMR_CSR_TEN(0);
+
+	/*
+	 * TMS = 0: time counter mode, not pulse counter
+	 * TFC = 1: reset counter on overflow
+	 * TIE = 1: enable interrupt
+	 */
+	LPTMR1->CSR = (LPTMR_CSR_TFC(1) | LPTMR_CSR_TIE(1));
+
+	/*
+	 * PCS = 2: clock source is RTC - 32 kHz clock (SoC dependent)
+	 * PBYP = 1: bypass the prescaler
+	 */
+	LPTMR1->PSR = (LPTMR_PSR_PBYP(1) | LPTMR_PSR_PCS(PCS_SOURCE_RTC));
+
+	irq_enable(LL_RTC0_IRQn_2nd_lvl);
+}
+
+static uint8_t refcount;
+static uint32_t cnt_diff;
+
+uint32_t cntr_start(void)
+{
+	if (refcount++) {
+		return 1;
+	}
+
+	LPTMR1->CMR = 0xFFFFFFFF;
+	LPTMR1->CSR |= LPTMR_CSR_TEN(1);
+
+	return 0;
+}
+
+uint32_t cntr_stop(void)
+{
+	LL_ASSERT(refcount);
+
+	if (--refcount) {
+		return 1;
+	}
+
+	cnt_diff = cntr_cnt_get();
+	/*
+	 * When TEN is clear, it resets the LPTMR internal logic,
+	 * including the CNR and TCF.
+	 */
+	LPTMR1->CSR &= ~LPTMR_CSR_TEN_MASK;
+
+	return 0;
+}
+
+uint32_t cntr_cnt_get(void)
+{
+	/*
+	 * On each read of the CNR,
+	 * software must first write to the CNR with any value.
+	 */
+	LPTMR1->CNR = 0;
+	return (LPTMR1->CNR + cnt_diff);
+}
+
+void cntr_cmp_set(uint8_t cmp, uint32_t value)
+{
+	/*
+	 * When the LPTMR is enabled, the first increment will take an
+	 * additional one or two prescaler clock cycles due to
+	 * synchronization logic.
+	 */
+	cnt_diff = cntr_cnt_get() + 1;
+	LPTMR1->CSR &= ~LPTMR_CSR_TEN_MASK;
+
+	value -= cnt_diff;
+	/*
+	 * If the CMR is 0, the hardware trigger will remain asserted until
+	 * the LPTMR is disabled. If the LPTMR is enabled, the CMR must be
+	 * altered only when TCF is set.
+	 */
+	if (value == 0)
+		value = 1;
+
+	LPTMR1->CMR = value;
+	LPTMR1->CSR |= LPTMR_CSR_TEN(1);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/debug.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/debug.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/debug.h	(working copy)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* CONFIG_BT_CTLR_DEBUG_PINS */
+/* CONFIG_BT_CTLR_DEBUG_PINS */
+/*
+ * The BLE SW link layer defines 10 GPIO pins for debug related
+ * information (but really only uses 7 pins). Zephyr has a block of
+ * 10 GPIOs routed to J2 odd pins 1-19 (inside bank of J2).
+ *
+ * Mapping:
+ *
+ * J2.1  : DEBUG_CPU_SLEEP
+ * J2.3  : DEBUG_TICKER_ISR, DEBUG_TICKER_TASK
+ * J2.5  : DEBUG_TICKER_JOB
+ * J2.7  : DEBUG_RADIO_PREPARE_A, DEBUG_RADIO_CLOSE_A
+ * J2.9  : DEBUG_RADIO_PREPARE_S, DEBUG_RADIO_START_S, DEBUG_RADIO_CLOSE_S
+ * J2.11 : DEBUG_RADIO_PREPARE_O, DEBUG_RADIO_START_O, DEBUG_RADIO_CLOSE_O
+ * J2.13 : DEBUG_RADIO_PREPARE_M, DEBUG_RADIO_START_M, DEBUG_RADIO_CLOSE_M
+ * J2.15 : DEBUG_RADIO_ISR
+ * J2.17 : DEBUG_RADIO_XTAL
+ * J2.19 : DEBUG_RADIO_ACTIVE
+ *
+ */
+#ifdef CONFIG_BT_CTLR_DEBUG_PINS
+
+#include <drivers/gpio.h>
+
+extern const struct device *vega_debug_portb;
+extern const struct device *vega_debug_portc;
+extern const struct device *vega_debug_portd;
+
+#define DEBUG0_PIN       5
+#define DEBUG0_PORT		 vega_debug_portd
+
+#define DEBUG1_PIN       4
+#define DEBUG1_PORT		 vega_debug_portd
+
+#define DEBUG2_PIN       3
+#define DEBUG2_PORT		 vega_debug_portd
+
+#define DEBUG3_PIN       2
+#define DEBUG3_PORT		 vega_debug_portd
+
+#define DEBUG4_PIN       1
+#define DEBUG4_PORT		 vega_debug_portd
+
+#define DEBUG5_PIN       0
+#define DEBUG5_PORT		 vega_debug_portd
+
+#define DEBUG6_PIN       30
+#define DEBUG6_PORT		 vega_debug_portc
+
+#define DEBUG7_PIN       29
+#define DEBUG7_PORT		 vega_debug_portc
+
+#define DEBUG8_PIN       28
+#define DEBUG8_PORT		 vega_debug_portc
+
+#define DEBUG9_PIN       29
+#define DEBUG9_PORT		 vega_debug_portb
+
+
+
+/* below are some interesting macros referenced by controller
+ * which can be defined to SoC's GPIO toggle to observe/debug the
+ * controller's runtime behavior.
+ *
+ * The ULL/LLL has defined 10 bits for doing debug output to be captured
+ * by a logic analyzer (i.e. minimally invasive). Vega board has some
+ * GPIO routed to the headers. Unfortunately they are spread across
+ * ports if you want to implement the 10 unique bits.
+ *
+ * portd
+ *
+ */
+#define DEBUG_INIT() \
+	do { \
+		vega_debug_portb = device_get_binding(DT_LABEL(DT_NODELABEL(gpiob))); \
+		vega_debug_portc = device_get_binding(DT_LABEL(DT_NODELABEL(gpioc))); \
+		vega_debug_portd = device_get_binding(DT_LABEL(DT_NODELABEL(gpiod))); \
+		\
+		gpio_pin_set(DEBUG0_PORT, DEBUG0_PIN, 1); \
+		gpio_pin_set(DEBUG0_PORT, DEBUG0_PIN, 0); \
+	} while (0)
+
+#define DEBUG_CPU_SLEEP(flag) gpio_pin_set(DEBUG0_PORT, DEBUG0_PIN, flag)
+
+#define DEBUG_TICKER_ISR(flag) gpio_pin_set(DEBUG1_PORT, DEBUG1_PIN, flag)
+
+#define DEBUG_TICKER_TASK(flag) gpio_pin_set(DEBUG1_PORT, DEBUG1_PIN, flag)
+
+#define DEBUG_TICKER_JOB(flag) gpio_pin_set(DEBUG2_PORT, DEBUG2_PIN, flag)
+
+#define DEBUG_RADIO_ISR(flag) gpio_pin_set(DEBUG7_PORT, DEBUG7_PIN, flag)
+
+#define DEBUG_RADIO_XTAL(flag) gpio_pin_set(DEBUG8_PORT, DEBUG8_PIN, flag)
+
+#define DEBUG_RADIO_ACTIVE(flag) gpio_pin_set(DEBUG9_PORT, DEBUG9_PIN, flag)
+
+#define DEBUG_RADIO_CLOSE(flag) \
+	do { \
+		if (!flag) { \
+			gpio_pin_set(DEBUG3_PORT, DEBUG3_PIN, flag); \
+			gpio_pin_set(DEBUG4_PORT, DEBUG4_PIN, flag); \
+			gpio_pin_set(DEBUG5_PORT, DEBUG5_PIN, flag); \
+			gpio_pin_set(DEBUG6_PORT, DEBUG6_PIN, flag); \
+		} \
+	} while (0)
+
+#define DEBUG_RADIO_PREPARE_A(flag) \
+		gpio_pin_set(DEBUG3_PORT, DEBUG3_PIN, flag)
+
+#define DEBUG_RADIO_START_A(flag) \
+		gpio_pin_set(DEBUG3_PORT, DEBUG3_PIN, flag)
+
+#define DEBUG_RADIO_CLOSE_A(flag) \
+		gpio_pin_set(DEBUG3_PORT, DEBUG3_PIN, flag)
+
+#define DEBUG_RADIO_PREPARE_S(flag) \
+		gpio_pin_set(DEBUG4_PORT, DEBUG4_PIN, flag)
+
+#define DEBUG_RADIO_START_S(flag) \
+		gpio_pin_set(DEBUG4_PORT, DEBUG4_PIN, flag)
+
+#define DEBUG_RADIO_CLOSE_S(flag) \
+		gpio_pin_set(DEBUG4_PORT, DEBUG4_PIN, flag)
+
+#define DEBUG_RADIO_PREPARE_O(flag) \
+		gpio_pin_set(DEBUG5_PORT, DEBUG5_PIN, flag)
+
+#define DEBUG_RADIO_START_O(flag) \
+		gpio_pin_set(DEBUG5_PORT, DEBUG5_PIN, flag)
+
+#define DEBUG_RADIO_CLOSE_O(flag) \
+		gpio_pin_set(DEBUG5_PORT, DEBUG5_PIN, flag)
+
+#define DEBUG_RADIO_PREPARE_M(flag) \
+		gpio_pin_set(DEBUG6_PORT, DEBUG6_PIN, flag)
+
+#define DEBUG_RADIO_START_M(flag) \
+		gpio_pin_set(DEBUG6_PORT, DEBUG6_PIN, flag)
+
+#define DEBUG_RADIO_CLOSE_M(flag) \
+		gpio_pin_set(DEBUG6_PORT, DEBUG6_PIN, flag)
+
+#else
+
+#define DEBUG_INIT()
+#define DEBUG_CPU_SLEEP(flag)
+#define DEBUG_TICKER_ISR(flag)
+#define DEBUG_TICKER_TASK(flag)
+#define DEBUG_TICKER_JOB(flag)
+#define DEBUG_RADIO_ISR(flag)
+#define DEBUG_RADIO_HCTO(flag)
+#define DEBUG_RADIO_XTAL(flag)
+#define DEBUG_RADIO_ACTIVE(flag)
+#define DEBUG_RADIO_CLOSE(flag)
+#define DEBUG_RADIO_PREPARE_A(flag)
+#define DEBUG_RADIO_START_A(flag)
+#define DEBUG_RADIO_CLOSE_A(flag)
+#define DEBUG_RADIO_PREPARE_S(flag)
+#define DEBUG_RADIO_START_S(flag)
+#define DEBUG_RADIO_CLOSE_S(flag)
+#define DEBUG_RADIO_PREPARE_O(flag)
+#define DEBUG_RADIO_START_O(flag)
+#define DEBUG_RADIO_CLOSE_O(flag)
+#define DEBUG_RADIO_PREPARE_M(flag)
+#define DEBUG_RADIO_START_M(flag)
+#define DEBUG_RADIO_CLOSE_M(flag)
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ecb.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ecb.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ecb.c	(working copy)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+#include <sys/byteorder.h>
+
+#include "hal/ecb.h"
+
+#define LOG_MODULE_NAME bt_ctlr_rv32m1_ecb
+#include "common/log.h"
+#include "hal/debug.h"
+#include "fsl_cau3_ble.h"
+
+void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
+		    uint8_t *const cipher_text_be)
+{
+	uint8_t keyAes[16] __aligned(4);
+	status_t status;
+
+	cau3_handle_t handle;
+
+	memcpy(&keyAes, key_be, sizeof(keyAes));
+
+	/* CAU3 driver supports 4 key slots. */
+	handle.keySlot = kCAU3_KeySlot1;
+
+	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
+	 * execute WFE() until CAU3 signals task done by setting the event.
+	 */
+	handle.taskDone = kCAU3_TaskDonePoll;
+
+	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
+	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
+	if (status != kStatus_Success) {
+		LOG_ERR("CAUv3 AES key set failed %d", status);
+		return;
+	}
+
+	status = CAU3_AES_Encrypt(CAU3, &handle, clear_text_be, cipher_text_be);
+	if (status != kStatus_Success) {
+		LOG_ERR("CAUv3 AES encrypt failed %d", status);
+		return;
+	}
+}
+
+void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
+		 uint8_t *const cipher_text_le, uint8_t *const cipher_text_be)
+{
+	uint8_t keyAes[16] __aligned(4);
+	uint8_t clear[16];
+	uint8_t cipher[16];
+	status_t status;
+
+	cau3_handle_t handle;
+
+	/* The security function e of the cryptographic toolbox in CAU as in STD
+	 * The most significant octet of key corresponds to key[0], the most
+	 * significant octet of plaintextData corresponds to in[0] and the most
+	 * significant octet of encryptedData corresponds to out[0] using the
+	 * notation specified in FIPS-197
+	 * Thus, reverse the input parameters that are LSB to MSB format (le)
+	 */
+	sys_memcpy_swap(&keyAes, key_le, sizeof(keyAes));
+	sys_memcpy_swap(&clear, clear_text_le, sizeof(clear));
+
+	/* CAU3 driver supports 4 key slots. */
+	handle.keySlot = kCAU3_KeySlot1;
+
+	/* After encrypt/decrypt req is sent to CAU3, the Host CPU will
+	 * execute WFE() until CAU3 signals task done by setting the event.
+	 */
+	handle.taskDone = kCAU3_TaskDonePoll;
+
+	/* Loads the key into CAU3's DMEM and expands the AES key schedule */
+	status = CAU3_AES_SetKey(CAU3, &handle, keyAes, sizeof(keyAes));
+	if (status != kStatus_Success) {
+		LOG_ERR("CAUv3 AES key set failed %d", status);
+		return;
+	}
+
+	status = CAU3_AES_Encrypt(CAU3, &handle, clear, cipher);
+	if (status != kStatus_Success) {
+		LOG_ERR("CAUv3 AES encrypt failed %d", status);
+		return;
+	}
+
+	if (cipher_text_le) {
+		/* STD e function outputs in MSB thus reverse for the (le) */
+		sys_memcpy_swap(cipher_text_le, &cipher[0], sizeof(cipher));
+	}
+
+	if (cipher_text_be) {
+		memcpy(cipher_text_be, &cipher, sizeof(cipher));
+	}
+}
+
+uint32_t ecb_encrypt_nonblocking(struct ecb *ecb)
+{
+	return 0;
+}
+
+void isr_ecb(void *param)
+{
+}
+
+/*
+ * Used by ULL as in this example:
+ * ltk[16] is copied from the HCI packet, preserving the LSO to MSO format
+ * skd[16] is copied from the PDU, preserving the LSO to MSO format
+ * calc the Session Key and retrieve the MSO to LSO format because that is how
+ * the PDU payload uses the encrypted data; MIC is also MSO to LSO.
+	ecb_encrypt(&conn->llcp_enc.ltk[0],
+		    &conn->llcp.encryption.skd[0], NULL,
+		    &lll->ccm_rx.key[0]);
+ */
+uint32_t ecb_ut(void)
+{
+	/*
+	 * LTK = 0x4C68384139F574D836BCF34E9DFB01BF (MSO to LSO)
+	 * SKD = SKDm || SKDs
+	 * SKD (LSO to MSO)
+	 * :0x13:0x02:0xF1:0xE0:0xDF:0xCE:0xBD:0xAC
+	 * :0x79:0x68:0x57:0x46:0x35:0x24:0x13:0x02
+	 * SK = Encrypt(LTK, SKD)
+	 * SK (LSO to MSO)
+	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
+	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
+	 */
+	static const uint8_t ltk_le[16] = {
+		0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
+		0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c
+	};
+	static const uint8_t skd_le[16] = {
+		0x13, 0x02, 0xF1, 0xE0, 0xDF, 0xCE, 0xBD, 0xAC,
+		0x79, 0x68, 0x57, 0x46, 0x35, 0x24, 0x13, 0x02
+	};
+	uint8_t key_le[16] = {};
+	uint8_t key_ref_le[16] = {
+		0x66, 0xC6, 0xC2, 0x27, 0x8E, 0x3B, 0x8E, 0x05,
+		0x3E, 0x7E, 0xA3, 0x26, 0x52, 0x1B, 0xAD, 0x99
+	};
+	uint32_t status = kStatus_Success;
+	uint8_t *key;
+
+	/* calc the Session Key and compare vs the ref_le in LSO format */
+	ecb_encrypt(ltk_le, skd_le, key = key_le, NULL);
+
+	if (memcmp(key_ref_le, key, 16)) {
+		printk("Failed session key unit test\n");
+		status = kStatus_Fail;
+	}
+
+	printk("Session key: %02x %02x %02x %02x %02x %02x %02x %02x "
+			"%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			key[0], key[1], key[2], key[3],
+			key[4], key[5], key[6], key[7],
+			key[8], key[9], key[10], key[11],
+			key[12], key[13], key[14], key[15]);
+
+	return status;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ll_irqs.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ll_irqs.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ll_irqs.h	(working copy)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+/* Needed for the DT_INST_* defines below */
+#include <devicetree.h>
+
+#define LL_SWI4_IRQn EMVSIM0_IRQn
+#define LL_SWI5_IRQn MUA_IRQn
+
+/*
+ * LPTMR1 -> INTMUX_CH2. We expect it to be the only IRQ source for this channel
+ * We'll use the INTMUX ISR for channel 2 instead of LPTMR1 ISR
+ */
+#define LL_RTC0_IRQn_1st_lvl DT_IRQN(DT_NODELABEL(intmux0_ch2))
+#define LL_RTC0_IRQn_2nd_lvl DT_IRQN(DT_NODELABEL(lptmr1))
+
+/*
+ * radio -> INTMUX_CH3. We expect it to be the only IRQ source for this channel
+ * We'll use the INTMUX ISR for channel 3 instead of radio ISR
+ */
+#define LL_RADIO_IRQn_1st_lvl DT_IRQN(DT_NODELABEL(intmux0_ch3))
+#define LL_RADIO_IRQn_2nd_lvl DT_IRQN(DT_NODELABEL(generic_fsk))
+
+#define LL_RTC0_IRQn LL_RTC0_IRQn_1st_lvl
+#define LL_RADIO_IRQn LL_RADIO_IRQn_1st_lvl
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/mayfly.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/mayfly.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/mayfly.c	(working copy)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <soc.h>
+
+#include "hal/RV32M1/swi.h"
+
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#define LOG_MODULE_NAME bt_ctlr_rv32m1_mayfly
+#include "common/log.h"
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+#include "ll_sw/lll.h"
+#define MAYFLY_CALL_ID_LLL    TICKER_USER_ID_LLL
+#define MAYFLY_CALL_ID_WORKER TICKER_USER_ID_ULL_HIGH
+#define MAYFLY_CALL_ID_JOB    TICKER_USER_ID_ULL_LOW
+#else
+#error Unknown LL variant.
+#endif
+
+void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
+{
+	(void)caller_id;
+
+	LL_ASSERT(callee_id == MAYFLY_CALL_ID_JOB);
+
+	if (enable) {
+		irq_enable(HAL_SWI_JOB_IRQ);
+	} else {
+		irq_disable(HAL_SWI_JOB_IRQ);
+	}
+}
+
+uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id)
+{
+	(void)caller_id;
+
+	switch (callee_id) {
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+	case MAYFLY_CALL_ID_LLL:
+		return irq_is_enabled(HAL_SWI_RADIO_IRQ);
+#endif /* CONFIG_BT_LL_SW_SPLIT */
+
+	case MAYFLY_CALL_ID_WORKER:
+		return irq_is_enabled(HAL_SWI_WORKER_IRQ);
+
+	case MAYFLY_CALL_ID_JOB:
+		return irq_is_enabled(HAL_SWI_JOB_IRQ);
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	return 0;
+}
+
+uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id)
+{
+	return (caller_id == callee_id) ||
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_LLL) &&
+		(callee_id == MAYFLY_CALL_ID_WORKER)) ||
+	       ((caller_id == MAYFLY_CALL_ID_WORKER) &&
+		(callee_id == MAYFLY_CALL_ID_LLL)) ||
+#endif
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_LLL) &&
+		(callee_id == MAYFLY_CALL_ID_JOB)) ||
+	       ((caller_id == MAYFLY_CALL_ID_JOB) &&
+		(callee_id == MAYFLY_CALL_ID_LLL)) ||
+#endif
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	       ((caller_id == MAYFLY_CALL_ID_WORKER) &&
+		(callee_id == MAYFLY_CALL_ID_JOB)) ||
+	       ((caller_id == MAYFLY_CALL_ID_JOB) &&
+		(callee_id == MAYFLY_CALL_ID_WORKER)) ||
+#endif
+#endif
+	       0;
+}
+
+void mayfly_pend(uint8_t caller_id, uint8_t callee_id)
+{
+	(void)caller_id;
+
+	switch (callee_id) {
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+	case MAYFLY_CALL_ID_LLL:
+		hal_swi_lll_pend();
+		break;
+#endif /* CONFIG_BT_LL_SW_SPLIT */
+
+	case MAYFLY_CALL_ID_WORKER:
+		hal_swi_worker_pend();
+		break;
+
+	case MAYFLY_CALL_ID_JOB:
+		hal_swi_job_pend();
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.h	(working copy)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define RADIO_TXP_DEFAULT 0
+
+
+typedef void (*radio_isr_cb_t) (void *param);
+
+void isr_radio(void *arg);
+void radio_isr_set(radio_isr_cb_t cb, void *param);
+
+void radio_setup(void);
+void radio_reset(void);
+void radio_phy_set(uint8_t phy, uint8_t flags);
+void radio_tx_power_set(uint32_t power);
+void radio_tx_power_max_set(void);
+void radio_freq_chan_set(uint32_t chan);
+void radio_whiten_iv_set(uint32_t iv);
+void radio_aa_set(uint8_t *aa);
+void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags);
+void radio_pkt_rx_set(void *rx_packet);
+void radio_pkt_tx_set(void *tx_packet);
+uint32_t radio_tx_ready_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_tx_chain_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_rx_ready_delay_get(uint8_t phy, uint8_t flags);
+uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags);
+void radio_rx_enable(void);
+void radio_tx_enable(void);
+void radio_disable(void);
+
+void radio_status_reset(void);
+uint32_t radio_is_ready(void);
+uint32_t radio_is_done(void);
+uint32_t radio_has_disabled(void);
+uint32_t radio_is_idle(void);
+
+void radio_crc_configure(uint32_t polynomial, uint32_t iv);
+uint32_t radio_crc_is_valid(void);
+
+void *radio_pkt_empty_get(void);
+void *radio_pkt_scratch_get(void);
+
+void radio_switch_complete_and_rx(uint8_t phy_rx);
+void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, uint8_t phy_tx,
+				  uint8_t flags_tx);
+void radio_switch_complete_and_disable(void);
+
+void radio_rssi_measure(void);
+uint32_t radio_rssi_get(void);
+void radio_rssi_status_reset(void);
+uint32_t radio_rssi_is_ready(void);
+
+void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type,
+			    uint8_t *bdaddr);
+void radio_filter_disable(void);
+void radio_filter_status_reset(void);
+uint32_t radio_filter_has_match(void);
+uint32_t radio_filter_match_get(void);
+
+void radio_bc_configure(uint32_t n);
+void radio_bc_status_reset(void);
+uint32_t radio_bc_has_match(void);
+
+void radio_tmr_status_reset(void);
+void radio_tmr_tifs_set(uint32_t tifs);
+uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder);
+uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick);
+void radio_tmr_start_us(uint8_t trx, uint32_t us);
+uint32_t radio_tmr_start_now(uint8_t trx);
+uint32_t radio_tmr_start_get(void);
+void radio_tmr_stop(void);
+void radio_tmr_hcto_configure(uint32_t hcto);
+void radio_tmr_aa_capture(void);
+uint32_t radio_tmr_aa_get(void);
+void radio_tmr_aa_save(uint32_t aa);
+uint32_t radio_tmr_aa_restore(void);
+uint32_t radio_tmr_ready_get(void);
+void radio_tmr_end_capture(void);
+uint32_t radio_tmr_end_get(void);
+uint32_t radio_tmr_tifs_base_get(void);
+void radio_tmr_sample(void);
+uint32_t radio_tmr_sample_get(void);
+
+void radio_gpio_pa_setup(void);
+void radio_gpio_lna_setup(void);
+void radio_gpio_lna_on(void);
+void radio_gpio_lna_off(void);
+void radio_gpio_pa_lna_enable(uint32_t trx_us);
+void radio_gpio_pa_lna_disable(void);
+
+void *radio_ccm_rx_pkt_set(struct ccm *ccm, uint8_t phy, void *pkt);
+void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt);
+uint32_t radio_ccm_is_done(void);
+uint32_t radio_ccm_mic_is_valid(void);
+uint32_t radio_ccm_is_available(void);
+
+void radio_ar_configure(uint32_t nirk, void *irk);
+uint32_t radio_ar_match_get(void);
+void radio_ar_status_reset(void);
+uint32_t radio_ar_has_match(void);
+
+uint32_t radio_sleep(void);
+uint32_t radio_wake(void);
+uint32_t radio_is_off(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/radio/radio.c	(working copy)
@@ -0,0 +1,1612 @@
+/*
+ * Copyright (c) 2016 - 2019 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ * Copyright 2019 - 2020 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <sys/printk.h>
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+#include <sys/byteorder.h>
+#include <bluetooth/addr.h>
+#include <toolchain.h>
+#include <irq.h>
+#include <errno.h>
+
+#include "util/mem.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "ll_sw/pdu.h"
+
+#include "fsl_xcvr.h"
+#include "hal/cntr.h"
+#include "hal/ticker.h"
+#include "hal/swi.h"
+#include "fsl_cau3_ble.h"	/* must be after irq.h */
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_openisa_radio
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static radio_isr_cb_t isr_cb;
+static void *isr_cb_param;
+
+#define RADIO_AESCCM_HDR_MASK 0xE3 /* AES-CCM: NESN, SN, MD bits masked to 0 */
+#define RADIO_PDU_LEN_MAX (BIT(8) - 1)
+#define BYTES_TO_USEC(bytes, bits_per_usec)	\
+		((bytes) * 8 >> (__builtin_ffs(bits_per_usec) - 1))
+
+/* us values */
+#define MIN_CMD_TIME 10		/* Minimum interval for a delayed radio cmd */
+#define RX_MARGIN 8
+#define TX_MARGIN 0
+#define RX_WTMRK 5		/* (AA + PDU header) - 1 */
+#define AA_OVHD_1MBPS 27	/* AA playback overhead for 1 Mbps PHY */
+#define AA_OVHD_2MBPS 10	/* AA playback overhead for 2 Mbps PHY */
+#define RX_OVHD 32		/* Rx overhead */
+
+#define PB_RX 544	/* half of PB (packet buffer) */
+
+/* The PDU in packet buffer starts after the Access Address which is 4 octets */
+#define PB_RX_PDU (PB_RX + 2)	/* Rx PDU offset (in halfwords) in PB */
+#define PB_TX_PDU 2		/* Tx PDU offset (in halfwords) in packet
+				 * buffer
+				 */
+
+#define RADIO_ACTIVE_MASK 0x1fff
+#define RADIO_DISABLE_TMR 4		/* us */
+
+/* Delay needed in order to enter Manual DSM.
+ * Must be at least 4 ticks ahead of DSM_TIMER (from RM).
+ */
+#define DSM_ENTER_DELAY_TICKS 6
+
+/* Delay needed in order to exit Manual DSM.
+ * Should be after radio_tmr_start() (2 ticks after lll_clk_on()).
+ * But less that 1.5ms (EVENT_OVERHEAD_XTAL_US) (ULL to LLL time offset).
+ * Must be at least 4 ticks ahead of DSM_TIMER (from RM).
+ */
+#define DSM_EXIT_DELAY_TICKS 30
+
+/* Mask to determine the state of DSM machine */
+#define MAN_DSM_ON (RSIM_DSM_CONTROL_MAN_DEEP_SLEEP_STATUS_MASK \
+		| RSIM_DSM_CONTROL_DSM_MAN_READY_MASK \
+		| RSIM_DSM_CONTROL_MAN_SLEEP_REQUEST_MASK) \
+
+static uint32_t dsm_ref; /* DSM reference counter */
+
+static uint8_t delayed_radio_start;
+static uint8_t delayed_trx;
+static uint32_t delayed_ticks_start;
+static uint32_t delayed_remainder;
+static uint8_t delayed_radio_stop;
+static uint32_t delayed_hcto;
+
+static uint32_t rtc_start;
+static uint32_t rtc_diff_start_us;
+
+static uint32_t tmr_aa;		/* AA (Access Address) timestamp saved value */
+static uint32_t tmr_aa_save;	/* save AA timestamp */
+static uint32_t tmr_ready;		/* radio ready for Tx/Rx timestamp */
+static uint32_t tmr_end;		/* Tx/Rx end timestamp saved value */
+static uint32_t tmr_end_save;	/* save Tx/Rx end timestamp */
+static uint32_t tmr_tifs;
+
+static uint32_t rx_wu;
+static uint32_t tx_wu;
+
+static uint8_t phy_mode;		/* Current PHY mode (DR_1MBPS or DR_2MBPS) */
+static uint8_t bits_per_usec;	/* This saves the # of bits per usec,
+				 * depending on the PHY mode
+				 */
+static uint8_t phy_aa_ovhd;	/* This saves the AA overhead, depending on the
+				 * PHY mode
+				 */
+
+static uint32_t isr_tmr_aa;
+static uint32_t isr_tmr_end;
+static uint32_t isr_latency;
+static uint32_t next_wu;
+static uint32_t next_radio_cmd;
+
+static uint32_t radio_trx;
+static uint32_t force_bad_crc;
+static uint32_t skip_hcto;
+
+static uint8_t *rx_pkt_ptr;
+static uint32_t payload_max_size;
+
+static uint8_t MALIGN(4) _pkt_empty[PDU_EM_LL_SIZE_MAX];
+static uint8_t MALIGN(4) _pkt_scratch[
+			((RADIO_PDU_LEN_MAX + 3) > PDU_AC_LL_SIZE_MAX) ?
+			(RADIO_PDU_LEN_MAX + 3) : PDU_AC_LL_SIZE_MAX];
+
+static int8_t rssi;
+
+static struct {
+	union {
+		uint64_t counter;
+		uint8_t bytes[CAU3_AES_BLOCK_SIZE - 1 - 2];
+	} nonce;	/* used by the B0 format but not in-situ */
+	struct pdu_data *rx_pkt_out;
+	struct pdu_data *rx_pkt_in;
+	uint8_t auth_mic_valid;
+	uint8_t empty_pdu_rxed;
+} ctx_ccm;
+
+#define RPA_NO_IRK_MATCH 0xFF	/* No IRK match in AR table */
+
+static struct {
+	uint8_t ar_enable;
+	uint32_t irk_idx;
+} radio_ar_ctx = {0U, RPA_NO_IRK_MATCH};
+
+static void tmp_cb(void *param)
+{
+	uint32_t tmr = GENFSK->EVENT_TMR & GENFSK_EVENT_TMR_EVENT_TMR_MASK;
+	uint32_t t2 = GENFSK->T2_CMP & GENFSK_T2_CMP_T2_CMP_MASK;
+
+	isr_latency = (tmr - t2) & GENFSK_EVENT_TMR_EVENT_TMR_MASK; /* 24bit */
+	/* Mark as done */
+	*(uint32_t *)param = 1;
+}
+
+static void get_isr_latency(void)
+{
+	volatile uint32_t tmp = 0;
+
+	radio_isr_set(tmp_cb, (void *)&tmp);
+
+	/* Reset TMR to zero */
+	GENFSK->EVENT_TMR = 0x1000000;
+
+	radio_disable();
+	while (!tmp) {
+	}
+	irq_disable(LL_RADIO_IRQn_2nd_lvl);
+}
+
+static uint32_t radio_tmr_start_hlp(uint8_t trx, uint32_t ticks_start, uint32_t remainder);
+static void radio_tmr_hcto_configure_hlp(uint32_t hcto);
+static void radio_config_after_wake(void)
+{
+	if (!delayed_radio_start) {
+		delayed_radio_stop = 0;
+		return;
+	}
+
+	delayed_radio_start = 0;
+	radio_tmr_start_hlp(delayed_trx, delayed_ticks_start,
+				delayed_remainder);
+
+	if (delayed_radio_stop) {
+		delayed_radio_stop = 0;
+
+		/* Adjust time out as remainder was in radio_tmr_start_hlp() */
+		delayed_hcto += rtc_diff_start_us;
+		radio_tmr_hcto_configure_hlp(delayed_hcto);
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+static void ar_execute(void *pkt)
+{
+	struct pdu_adv *pdu_adv = (struct pdu_adv *)pkt;
+	bt_addr_t *rpa = (bt_addr_t *)&pdu_adv->payload[0];
+
+	/* Perform address resolution when TxAdd=1 and address is resolvable */
+	if (pdu_adv->tx_addr && BT_ADDR_IS_RPA(rpa)) {
+		uint32_t *hash, *prand;
+		status_t status;
+
+		/* Use pointers to avoid breaking strict aliasing */
+		hash = (uint32_t *)(&rpa->val[0]);
+		prand = (uint32_t *)(&rpa->val[3]);
+
+		/* CAUv3 needs hash & prand in le format, right-justified */
+		status = CAU3_RPAtableSearch(CAU3, (*prand & 0xFFFFFF),
+					(*hash & 0xFFFFFF),
+					&radio_ar_ctx.irk_idx,
+					kCAU3_TaskDoneEvent);
+		if (status != kStatus_Success) {
+			radio_ar_ctx.irk_idx = RPA_NO_IRK_MATCH;
+			BT_ERR("CAUv3 RPA table search failed %d", status);
+			return;
+		}
+	}
+
+	radio_ar_ctx.ar_enable = 0U;
+}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+static void pkt_rx(void)
+{
+	uint32_t len, idx;
+	uint16_t *rxb = (uint16_t *)rx_pkt_ptr, tmp;
+	volatile uint16_t *pb = &GENFSK->PACKET_BUFFER[PB_RX_PDU];
+	volatile const uint32_t *sts = &GENFSK->XCVR_STS;
+
+	/* payload length */
+	len = (GENFSK->XCVR_CTRL & GENFSK_XCVR_CTRL_LENGTH_EXT_MASK) >>
+			GENFSK_XCVR_CTRL_LENGTH_EXT_SHIFT;
+
+	if (len > payload_max_size) {
+		/* Unexpected size */
+		force_bad_crc = 1;
+		next_radio_cmd = 0;
+		while (*sts & GENFSK_XCVR_STS_RX_IN_PROGRESS_MASK) {
+		}
+		return;
+	}
+
+	/* For Data Physical Channel PDU,
+	 * assume no CTEInfo field, CP=0 => 2 bytes header
+	 */
+	/* Add PDU header size */
+	len += 2;
+
+	/* Add to AA time, PDU + CRC time */
+	isr_tmr_end = isr_tmr_aa + BYTES_TO_USEC(len + 3, bits_per_usec);
+
+	/* If not enough time for warmup after we copy the PDU from
+	 * packet buffer, send delayed command now
+	 */
+	if (next_radio_cmd) {
+		/* Start Rx/Tx in TIFS */
+		idx = isr_tmr_end + tmr_tifs - next_wu;
+		GENFSK->XCVR_CTRL = next_radio_cmd;
+		GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(idx) |
+				 GENFSK_T1_CMP_T1_CMP_EN(1);
+		next_radio_cmd = 0;
+	}
+
+	/* Can't rely on data read from packet buffer while in Rx */
+	/* Wait for Rx to finish */
+	while (*sts & GENFSK_XCVR_STS_RX_IN_PROGRESS_MASK) {
+	}
+
+	if (ctx_ccm.rx_pkt_out) {
+		*(uint16_t *)ctx_ccm.rx_pkt_out = pb[0];
+		if (len < CAU3_BLE_MIC_SIZE) {
+			ctx_ccm.rx_pkt_out = 0;
+			ctx_ccm.rx_pkt_in = 0;
+			ctx_ccm.empty_pdu_rxed = 1;
+		}
+	}
+
+	/* Copy the PDU */
+	for (idx = 0; idx < len / 2; idx++) {
+		rxb[idx] = pb[idx];
+	}
+
+	/* Copy last byte */
+	if (len & 0x1) {
+		tmp = pb[len / 2];
+		rx_pkt_ptr[len - 1] =  ((uint8_t *)&tmp)[0];
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* Perform address resolution on this Rx */
+	if (radio_ar_ctx.ar_enable) {
+		ar_execute(rxb);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	force_bad_crc = 0;
+}
+
+#define IRQ_MASK ~(GENFSK_IRQ_CTRL_T2_IRQ_MASK | \
+		   GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK | \
+		   GENFSK_IRQ_CTRL_TX_IRQ_MASK | \
+		   GENFSK_IRQ_CTRL_WAKE_IRQ_MASK)
+void isr_radio(void *arg)
+{
+	ARG_UNUSED(arg);
+
+	uint32_t tmr = GENFSK->EVENT_TMR & GENFSK_EVENT_TMR_EVENT_TMR_MASK;
+	uint32_t irq = GENFSK->IRQ_CTRL;
+	uint32_t valid = 0;
+	/* We need to check for a valid IRQ source.
+	 * In theory, we could get to this ISR after the IRQ source was cleared.
+	 * This could happen due to the way LLL interacts with IRQs
+	 * (radio_isr_set(), radio_disable()) and their propagation path:
+	 * GENFSK -> INTMUX(does not latch pending source interrupts)
+	 * INTMUX -> EVENT_UNIT
+	 */
+
+	if (irq & GENFSK_IRQ_CTRL_WAKE_IRQ_MASK) {
+		/* Clear pending interrupts */
+		GENFSK->IRQ_CTRL &= 0xffffffff;
+
+		/* Disable DSM_TIMER */
+		RSIM->DSM_CONTROL &= ~RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
+
+		radio_config_after_wake();
+		return;
+	}
+
+	if (irq & GENFSK_IRQ_CTRL_TX_IRQ_MASK) {
+		valid = 1;
+		GENFSK->IRQ_CTRL &= (IRQ_MASK | GENFSK_IRQ_CTRL_TX_IRQ_MASK);
+		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
+
+		isr_tmr_end = tmr - isr_latency;
+		if (tmr_end_save) {
+			tmr_end = isr_tmr_end;
+		}
+		radio_trx = 1;
+	}
+
+	if (irq & GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK) {
+		valid = 1;
+		/* Disable Rx timeout */
+		/* 0b1010..RX Cancel -- Cancels pending RX events but do not
+		 *			abort a RX-in-progress
+		 */
+		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xa);
+		GENFSK->T2_CMP &= ~GENFSK_T2_CMP_T2_CMP_EN_MASK;
+
+		GENFSK->IRQ_CTRL &= (IRQ_MASK |
+				     GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_MASK);
+		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
+
+		/* Fix reported AA time */
+		isr_tmr_aa = GENFSK->TIMESTAMP - phy_aa_ovhd;
+
+		if (tmr_aa_save) {
+			tmr_aa = isr_tmr_aa;
+		}
+		/* Copy the PDU as it arrives, calculates Rx end */
+		pkt_rx();
+		if (tmr_end_save) {
+			tmr_end = isr_tmr_end;	/* from pkt_rx() */
+		}
+		radio_trx = 1;
+		rssi = (GENFSK->XCVR_STS & GENFSK_XCVR_STS_RSSI_MASK) >>
+					GENFSK_XCVR_STS_RSSI_SHIFT;
+	}
+
+	if (irq & GENFSK_IRQ_CTRL_T2_IRQ_MASK) {
+		valid = 1;
+		GENFSK->IRQ_CTRL &= (IRQ_MASK | GENFSK_IRQ_CTRL_T2_IRQ_MASK);
+		/* Disable both comparators */
+		GENFSK->T1_CMP &= ~GENFSK_T1_CMP_T1_CMP_EN_MASK;
+		GENFSK->T2_CMP &= ~GENFSK_T2_CMP_T2_CMP_EN_MASK;
+	}
+
+	if (radio_trx && next_radio_cmd) {
+		/* Start Rx/Tx in TIFS */
+		tmr = isr_tmr_end + tmr_tifs - next_wu;
+		GENFSK->XCVR_CTRL = next_radio_cmd;
+		GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(tmr) |
+				 GENFSK_T1_CMP_T1_CMP_EN(1);
+		next_radio_cmd = 0;
+	}
+
+	if (valid) {
+		isr_cb(isr_cb_param);
+	}
+}
+
+void radio_isr_set(radio_isr_cb_t cb, void *param)
+{
+	irq_disable(LL_RADIO_IRQn_2nd_lvl);
+	irq_disable(LL_RADIO_IRQn);
+
+	isr_cb_param = param;
+	isr_cb = cb;
+
+	/* Clear pending interrupts */
+	GENFSK->IRQ_CTRL &= 0xffffffff;
+	EVENT_UNIT->INTPTPENDCLEAR = (uint32_t)(1U << LL_RADIO_IRQn);
+
+	irq_enable(LL_RADIO_IRQn);
+	irq_enable(LL_RADIO_IRQn_2nd_lvl);
+}
+
+#define DISABLE_HPMCAL
+
+#ifdef DISABLE_HPMCAL
+#define WU_OPTIM            26  /* 34: quite ok, 36 few ok */
+#define USE_FIXED_HPMCAL    563
+
+static void hpmcal_disable(void)
+{
+#ifdef USE_FIXED_HPMCAL
+	uint32_t hpmcal = USE_FIXED_HPMCAL;
+#else
+	uint32_t hpmcal_vals[40];
+	uint32_t hpmcal;
+	int i;
+
+	GENFSK->TX_POWER = GENFSK_TX_POWER_TX_POWER(1);
+
+	/* TX warm-up at Channel Frequency = 2.44GHz */
+	for (i = 0; i < ARRAY_SIZE(hpmcal_vals); i++) {
+		GENFSK->CHANNEL_NUM = 2402 - 2360 + 2 * i;
+
+		/* Reset TMR to zero */
+		GENFSK->EVENT_TMR = 0x1000000;
+
+		/* TX Start Now */
+		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x1);
+
+		while ((GENFSK->EVENT_TMR & 0xffffff) < 1000)
+			;
+
+		/* Abort All */
+		GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xb);
+
+		/* Wait for XCVR to become idle. */
+		while (GENFSK->XCVR_CTRL & GENFSK_XCVR_CTRL_XCVR_BUSY_MASK)
+			;
+
+		hpmcal_vals[i] = (XCVR_PLL_DIG->HPMCAL_CTRL &
+				XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MASK) >>
+				XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_SHIFT;
+	}
+
+	hpmcal = hpmcal_vals[20];
+#endif
+
+	XCVR_PLL_DIG->HPMCAL_CTRL = (XCVR_PLL_DIG->HPMCAL_CTRL &
+			~XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MANUAL_MASK) +
+			XCVR_PLL_DIG_HPMCAL_CTRL_HPM_CAL_FACTOR_MANUAL(hpmcal) +
+			XCVR_PLL_DIG_HPMCAL_CTRL_HP_CAL_DISABLE_MASK +
+			0x00000000;
+
+	/* Move the sigma_delta_en signal to be 1us after pll_dig_en */
+	int pll_dig_en  = (XCVR_TSM->TIMING34 &
+			XCVR_TSM_TIMING34_PLL_DIG_EN_TX_HI_MASK) >>
+			XCVR_TSM_TIMING34_PLL_DIG_EN_TX_HI_SHIFT;
+
+	XCVR_TSM->TIMING38 = (XCVR_TSM->TIMING38 &
+			~XCVR_TSM_TIMING38_SIGMA_DELTA_EN_TX_HI_MASK) +
+			XCVR_TSM_TIMING38_SIGMA_DELTA_EN_TX_HI(pll_dig_en+1);
+			/* sigma_delta_en */
+
+	XCVR_TSM->TIMING19   -= B1(WU_OPTIM); /* sy_pd_filter_charge_en */
+	XCVR_TSM->TIMING24   -= B1(WU_OPTIM); /* sy_divn_cal_en */
+	XCVR_TSM->TIMING13   -= B1(WU_OPTIM); /* sy_vco_autotune_en */
+	XCVR_TSM->TIMING17   -= B0(WU_OPTIM); /* sy_lo_tx_buf_en */
+	XCVR_TSM->TIMING26   -= B0(WU_OPTIM); /* tx_pa_en */
+	XCVR_TSM->TIMING35   -= B0(WU_OPTIM); /* tx_dig_en */
+	XCVR_TSM->TIMING14   -= B0(WU_OPTIM); /* sy_pd_cycle_slip_ld_ft_en */
+
+	XCVR_TSM->END_OF_SEQ -= B1(WU_OPTIM) + B0(WU_OPTIM);
+}
+#endif
+
+void radio_setup(void)
+{
+	XCVR_Reset();
+
+#if defined(CONFIG_BT_CTLR_PRIVACY) || defined(CONFIG_BT_CTLR_LE_ENC)
+	CAU3_Init(CAU3);
+#endif /* CONFIG_BT_CTLR_PRIVACY || CONFIG_BT_CTLR_LE_ENC */
+
+	XCVR_Init(GFSK_BT_0p5_h_0p5, DR_1MBPS);
+	XCVR_SetXtalTrim(41);
+
+#ifdef DISABLE_HPMCAL
+	hpmcal_disable();
+#endif
+
+	/* Enable Deep Sleep Mode for GENFSK */
+	XCVR_MISC->XCVR_CTRL |= XCVR_CTRL_XCVR_CTRL_MAN_DSM_SEL(2);
+
+	/* Enable the CRC as it is disabled by default after reset */
+	XCVR_MISC->CRCW_CFG |= XCVR_CTRL_CRCW_CFG_CRCW_EN(1);
+
+	/* Assign Radio #0 Interrupt to GENERIC_FSK */
+	XCVR_MISC->XCVR_CTRL |= XCVR_CTRL_XCVR_CTRL_RADIO0_IRQ_SEL(3);
+
+	phy_mode = GENFSK->BITRATE = DR_1MBPS;
+	bits_per_usec = 1;
+	phy_aa_ovhd = AA_OVHD_1MBPS;
+
+	/*
+	 * Split the buffer in equal parts: first half for Tx,
+	 * second half for Rx
+	 */
+	GENFSK->PB_PARTITION = GENFSK_PB_PARTITION_PB_PARTITION(PB_RX);
+
+	/* Get warmpup times. They are used in TIFS calculations */
+	rx_wu = (XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK)
+				>> XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
+	tx_wu = (XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK)
+				>> XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT;
+
+	/* IRQ config, clear pending interrupts */
+	irq_disable(LL_RADIO_IRQn_2nd_lvl);
+	GENFSK->IRQ_CTRL = 0xffffffff;
+	GENFSK->IRQ_CTRL = GENFSK_IRQ_CTRL_GENERIC_FSK_IRQ_EN(1) |
+			   GENFSK_IRQ_CTRL_RX_WATERMARK_IRQ_EN(1) |
+			   GENFSK_IRQ_CTRL_TX_IRQ_EN(1) |
+			   GENFSK_IRQ_CTRL_T2_IRQ_EN(1) |
+			   GENFSK_IRQ_CTRL_WAKE_IRQ_EN(1);
+
+	/* Disable Rx recycle */
+	GENFSK->IRQ_CTRL |= GENFSK_IRQ_CTRL_CRC_IGNORE(1);
+	GENFSK->WHITEN_SZ_THR |= GENFSK_WHITEN_SZ_THR_REC_BAD_PKT(1);
+
+	/* Turn radio on to measure ISR latency */
+	if (radio_is_off()) {
+		dsm_ref = 0;
+		radio_wake();
+		while (radio_is_off()) {
+		}
+	} else {
+		dsm_ref = 1;
+	}
+
+	get_isr_latency();
+
+	/* Turn radio off */
+	radio_sleep();
+}
+
+void radio_reset(void)
+{
+	irq_disable(LL_RADIO_IRQn_2nd_lvl);
+	/* Vega radio is never disabled therefore doesn't require resetting */
+}
+
+void radio_phy_set(uint8_t phy, uint8_t flags)
+{
+	int err = 0;
+	ARG_UNUSED(flags);
+
+	/* This function sets one of two modes:
+	 * - BLE 1 Mbps
+	 * - BLE 2 Mbps
+	 * Coded BLE is not supported by VEGA
+	 */
+	switch (phy) {
+	case BIT(0):
+	default:
+		if (phy_mode == DR_1MBPS) {
+			break;
+		}
+
+		err = XCVR_ChangeMode(GFSK_BT_0p5_h_0p5, DR_1MBPS);
+		if (err) {
+			BT_ERR("Failed to change PHY to 1 Mbps");
+			BT_ASSERT(0);
+		}
+
+		phy_mode = GENFSK->BITRATE = DR_1MBPS;
+		bits_per_usec = 1;
+		phy_aa_ovhd = AA_OVHD_1MBPS;
+
+		break;
+
+	case BIT(1):
+		if (phy_mode == DR_2MBPS) {
+			break;
+		}
+
+		err = XCVR_ChangeMode(GFSK_BT_0p5_h_0p5, DR_2MBPS);
+		if (err) {
+			BT_ERR("Failed to change PHY to 2 Mbps");
+			BT_ASSERT(0);
+		}
+
+		phy_mode = GENFSK->BITRATE = DR_2MBPS;
+		bits_per_usec = 2;
+		phy_aa_ovhd = AA_OVHD_2MBPS;
+
+		break;
+	}
+}
+
+void radio_tx_power_set(uint32_t power)
+{
+	ARG_UNUSED(power);
+
+	/* tx_power_level should only have the values 1, 2, 4, 6, ... , 62.
+	 * Any value odd value (1, 3, ...) is not permitted and will result in
+	 * undefined behavior.
+	 * Those value have an associated db level that was not found in the
+	 * documentation.
+	 * Because of these inconsistencies for the moment this
+	 * function sets the power level to a known value.
+	 */
+	uint32_t tx_power_level = 62;
+
+	GENFSK->TX_POWER = GENFSK_TX_POWER_TX_POWER(tx_power_level);
+}
+
+void radio_tx_power_max_set(void)
+{
+	printk("%s\n", __func__);
+}
+
+void radio_freq_chan_set(uint32_t chan)
+{
+	/*
+	 * The channel number for vega radio is computed
+	 * as 2360 + ch_num [in MHz]
+	 * The LLL expects the channel number to be computed as 2400 + ch_num.
+	 * Therefore a compensation of 40 MHz has been provided.
+	 */
+	GENFSK->CHANNEL_NUM = GENFSK_CHANNEL_NUM_CHANNEL_NUM(40 + chan);
+}
+
+#define GENFSK_BLE_WHITEN_START			1	/* after H0 */
+#define GENFSK_BLE_WHITEN_END			1	/* at the end of CRC */
+#define GENFSK_BLE_WHITEN_POLY_TYPE		0	/* Galois poly type */
+#define GENFSK_BLE_WHITEN_SIZE			7	/* poly order */
+#define GENFSK_BLE_WHITEN_POLY			0x04
+
+void radio_whiten_iv_set(uint32_t iv)
+{
+	GENFSK->WHITEN_CFG &= ~(GENFSK_WHITEN_CFG_WHITEN_START_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_END_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_B4_CRC_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_POLY_TYPE_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_REF_IN_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_PAYLOAD_REINIT_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_SIZE_MASK |
+				GENFSK_WHITEN_CFG_MANCHESTER_EN_MASK |
+				GENFSK_WHITEN_CFG_MANCHESTER_INV_MASK |
+				GENFSK_WHITEN_CFG_MANCHESTER_START_MASK |
+				GENFSK_WHITEN_CFG_WHITEN_INIT_MASK);
+
+	GENFSK->WHITEN_CFG |=
+	    GENFSK_WHITEN_CFG_WHITEN_START(GENFSK_BLE_WHITEN_START) |
+	    GENFSK_WHITEN_CFG_WHITEN_END(GENFSK_BLE_WHITEN_END) |
+	    GENFSK_WHITEN_CFG_WHITEN_B4_CRC(0) |
+	    GENFSK_WHITEN_CFG_WHITEN_POLY_TYPE(GENFSK_BLE_WHITEN_POLY_TYPE) |
+	    GENFSK_WHITEN_CFG_WHITEN_REF_IN(0) |
+	    GENFSK_WHITEN_CFG_WHITEN_PAYLOAD_REINIT(0) |
+	    GENFSK_WHITEN_CFG_WHITEN_SIZE(GENFSK_BLE_WHITEN_SIZE) |
+	    GENFSK_WHITEN_CFG_MANCHESTER_EN(0) |
+	    GENFSK_WHITEN_CFG_MANCHESTER_INV(0) |
+	    GENFSK_WHITEN_CFG_MANCHESTER_START(0) |
+	    GENFSK_WHITEN_CFG_WHITEN_INIT(iv | 0x40);
+
+	GENFSK->WHITEN_POLY =
+		GENFSK_WHITEN_POLY_WHITEN_POLY(GENFSK_BLE_WHITEN_POLY);
+
+	GENFSK->WHITEN_SZ_THR &= ~GENFSK_WHITEN_SZ_THR_WHITEN_SZ_THR_MASK;
+	GENFSK->WHITEN_SZ_THR |= GENFSK_WHITEN_SZ_THR_WHITEN_SZ_THR(0);
+}
+
+void radio_aa_set(uint8_t *aa)
+{
+	/* Configure Access Address detection using NETWORK ADDRESS 0 */
+	GENFSK->NTW_ADR_0 = *((uint32_t *)aa);
+	GENFSK->NTW_ADR_CTRL &= ~(GENFSK_NTW_ADR_CTRL_NTW_ADR0_SZ_MASK |
+				  GENFSK_NTW_ADR_CTRL_NTW_ADR_THR0_MASK);
+	GENFSK->NTW_ADR_CTRL |= GENFSK_NTW_ADR_CTRL_NTW_ADR0_SZ(3) |
+				GENFSK_NTW_ADR_CTRL_NTW_ADR_THR0(0);
+
+	GENFSK->NTW_ADR_CTRL |= (uint32_t) ((1 << 0) <<
+			GENFSK_NTW_ADR_CTRL_NTW_ADR_EN_SHIFT);
+
+	/*
+	 * The Access Address must be written in the packet buffer
+	 * in front of the PDU
+	 */
+	GENFSK->PACKET_BUFFER[0] = (aa[1] << 8) + aa[0];
+	GENFSK->PACKET_BUFFER[1] = (aa[3] << 8) + aa[2];
+}
+
+#define GENFSK_BLE_CRC_SZ	3 /* 3 bytes */
+#define GENFSK_BLE_PREAMBLE_SZ	0 /* 1 byte of preamble, depends on PHY type */
+#define GENFSK_BLE_LEN_BIT_ORD	0 /* LSB */
+#define GENFSK_BLE_SYNC_ADDR_SZ	3 /* 4 bytes, Access Address */
+#define GENFSK_BLE_LEN_ADJ_SZ	GENFSK_BLE_CRC_SZ /* adjust length with CRC
+						   * size
+						   */
+#define GENFSK_BLE_H0_SZ	8 /* 8 bits */
+
+void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags)
+{
+	ARG_UNUSED(flags);
+
+	payload_max_size = max_len;
+
+	GENFSK->XCVR_CFG &= ~GENFSK_XCVR_CFG_PREAMBLE_SZ_MASK;
+	GENFSK->XCVR_CFG |=
+		GENFSK_XCVR_CFG_PREAMBLE_SZ(GENFSK_BLE_PREAMBLE_SZ);
+
+	GENFSK->PACKET_CFG &= ~(GENFSK_PACKET_CFG_LENGTH_SZ_MASK |
+			GENFSK_PACKET_CFG_LENGTH_BIT_ORD_MASK |
+			GENFSK_PACKET_CFG_SYNC_ADDR_SZ_MASK |
+			GENFSK_PACKET_CFG_LENGTH_ADJ_MASK |
+			GENFSK_PACKET_CFG_H0_SZ_MASK |
+			GENFSK_PACKET_CFG_H1_SZ_MASK);
+
+	GENFSK->PACKET_CFG |= GENFSK_PACKET_CFG_LENGTH_SZ(bits_len) |
+		GENFSK_PACKET_CFG_LENGTH_BIT_ORD(GENFSK_BLE_LEN_BIT_ORD) |
+		GENFSK_PACKET_CFG_SYNC_ADDR_SZ(GENFSK_BLE_SYNC_ADDR_SZ) |
+		GENFSK_PACKET_CFG_LENGTH_ADJ(GENFSK_BLE_LEN_ADJ_SZ) |
+		GENFSK_PACKET_CFG_H0_SZ(GENFSK_BLE_H0_SZ) |
+		GENFSK_PACKET_CFG_H1_SZ((8 - bits_len));
+
+	GENFSK->H0_CFG &= ~(GENFSK_H0_CFG_H0_MASK_MASK |
+			    GENFSK_H0_CFG_H0_MATCH_MASK);
+	GENFSK->H0_CFG |= GENFSK_H0_CFG_H0_MASK(0) |
+			  GENFSK_H0_CFG_H0_MATCH(0);
+
+	GENFSK->H1_CFG &= ~(GENFSK_H1_CFG_H1_MASK_MASK |
+			    GENFSK_H1_CFG_H1_MATCH_MASK);
+	GENFSK->H1_CFG |= GENFSK_H1_CFG_H1_MASK(0) |
+			  GENFSK_H1_CFG_H1_MATCH(0);
+
+	/* set Rx watermak to AA + PDU header */
+	GENFSK->RX_WATERMARK = GENFSK_RX_WATERMARK_RX_WATERMARK(RX_WTMRK);
+}
+
+void radio_pkt_rx_set(void *rx_packet)
+{
+	rx_pkt_ptr = rx_packet;
+}
+
+void radio_pkt_tx_set(void *tx_packet)
+{
+	/*
+	 * The GENERIC_FSK software must program the TX buffer
+	 * before commanding a TX operation, and must not access the RAM during
+	 * the transmission.
+	 */
+	uint16_t *pkt = tx_packet;
+	uint32_t cnt = 0, pkt_len = (((uint8_t *)tx_packet)[1] + 1) / 2 + 1;
+	volatile uint16_t *pkt_buffer = &GENFSK->PACKET_BUFFER[PB_TX_PDU];
+
+	for (; cnt < pkt_len; cnt++) {
+		pkt_buffer[cnt] = pkt[cnt];
+	}
+}
+
+uint32_t radio_tx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return tx_wu;
+}
+
+uint32_t radio_tx_chain_delay_get(uint8_t phy, uint8_t flags)
+{
+	return 0;
+}
+
+uint32_t radio_rx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return rx_wu;
+}
+
+uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags)
+{
+	/* RX_WTMRK = AA + PDU header, but AA time is already accounted for */
+	/* PDU header (assume 2 bytes) => 16us, depends on PHY type */
+	/* 2 * RX_OVHD = RX_WATERMARK_IRQ time - TIMESTAMP - isr_latency */
+	/* The rest is Rx margin that for now isn't well defined */
+	return BYTES_TO_USEC(2, bits_per_usec) + 2 * RX_OVHD +
+					RX_MARGIN + isr_latency +
+					RX_OVHD;
+}
+
+void radio_rx_enable(void)
+{
+	/* Wait for idle state */
+	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
+	}
+
+	/* 0b0101..RX Start Now */
+	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x5);
+}
+
+void radio_tx_enable(void)
+{
+	/* Wait for idle state */
+	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
+	}
+
+	/* 0b0001..TX Start Now */
+	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x1);
+}
+
+void radio_disable(void)
+{
+	/* Disable both comparators */
+	GENFSK->T1_CMP = 0;
+	GENFSK->T2_CMP = 0;
+
+	/*
+	 * 0b1011..Abort All - Cancels all pending events and abort any
+	 * sequence-in-progress
+	 */
+	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0xb);
+
+	/* Wait for idle state */
+	while (GENFSK->XCVR_STS & RADIO_ACTIVE_MASK) {
+	}
+
+	/* Clear pending interrupts */
+	GENFSK->IRQ_CTRL &= 0xffffffff;
+	EVENT_UNIT->INTPTPENDCLEAR = (uint32_t)(1U << LL_RADIO_IRQn);
+
+	next_radio_cmd = 0;
+	radio_trx = 0;
+
+	/* generate T2 interrupt to get into isr_radio() */
+	uint32_t tmr = GENFSK->EVENT_TMR + RADIO_DISABLE_TMR;
+
+	GENFSK->T2_CMP = GENFSK_T2_CMP_T2_CMP(tmr) | GENFSK_T2_CMP_T2_CMP_EN(1);
+}
+
+void radio_status_reset(void)
+{
+	radio_trx = 0;
+}
+
+uint32_t radio_is_ready(void)
+{
+	/* Always false. LLL expects the radio not to be in idle/Tx/Rx state */
+	return 0;
+}
+
+uint32_t radio_is_done(void)
+{
+	return radio_trx;
+}
+
+uint32_t radio_has_disabled(void)
+{
+	/* Not used */
+	return 0;
+}
+
+uint32_t radio_is_idle(void)
+{
+	/* Vega radio is never disabled */
+	return 1;
+}
+
+#define GENFSK_BLE_CRC_START_BYTE	4 /* After Access Address */
+#define GENFSK_BLE_CRC_BYTE_ORD		0 /* LSB */
+
+void radio_crc_configure(uint32_t polynomial, uint32_t iv)
+{
+	/* printk("%s poly: %08x, iv: %08x\n", __func__, polynomial, iv); */
+
+	GENFSK->CRC_CFG &= ~(GENFSK_CRC_CFG_CRC_SZ_MASK |
+			     GENFSK_CRC_CFG_CRC_START_BYTE_MASK |
+			     GENFSK_CRC_CFG_CRC_REF_IN_MASK |
+			     GENFSK_CRC_CFG_CRC_REF_OUT_MASK |
+			     GENFSK_CRC_CFG_CRC_BYTE_ORD_MASK);
+	GENFSK->CRC_CFG |= GENFSK_CRC_CFG_CRC_SZ(GENFSK_BLE_CRC_SZ) |
+		GENFSK_CRC_CFG_CRC_START_BYTE(GENFSK_BLE_CRC_START_BYTE) |
+		GENFSK_CRC_CFG_CRC_REF_IN(0) |
+		GENFSK_CRC_CFG_CRC_REF_OUT(0) |
+		GENFSK_CRC_CFG_CRC_BYTE_ORD(GENFSK_BLE_CRC_BYTE_ORD);
+
+	GENFSK->CRC_INIT = (iv << ((4U - GENFSK_BLE_CRC_SZ) << 3));
+	GENFSK->CRC_POLY = (polynomial << ((4U - GENFSK_BLE_CRC_SZ) << 3));
+	GENFSK->CRC_XOR_OUT = 0;
+
+	/*
+	 * Enable CRC in hardware; this is already done at startup but we do it
+	 * here anyways just to be sure.
+	 */
+	GENFSK->XCVR_CFG &= ~GENFSK_XCVR_CFG_SW_CRC_EN_MASK;
+}
+
+uint32_t radio_crc_is_valid(void)
+{
+	if (force_bad_crc)
+		return 0;
+
+	uint32_t radio_crc = (GENFSK->XCVR_STS & GENFSK_XCVR_STS_CRC_VALID_MASK) >>
+						GENFSK_XCVR_STS_CRC_VALID_SHIFT;
+	return radio_crc;
+}
+
+void *radio_pkt_empty_get(void)
+{
+	return _pkt_empty;
+}
+
+void *radio_pkt_scratch_get(void)
+{
+	return _pkt_scratch;
+}
+
+void radio_switch_complete_and_rx(uint8_t phy_rx)
+{
+	/*  0b0110..RX Start @ T1 Timer Compare Match (EVENT_TMR = T1_CMP) */
+	next_radio_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x6);
+
+	/* the margin is used to account for any overhead in radio switching */
+	next_wu = rx_wu + RX_MARGIN;
+}
+
+void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, uint8_t phy_tx,
+				  uint8_t flags_tx)
+{
+	/*  0b0010..TX Start @ T1 Timer Compare Match (EVENT_TMR = T1_CMP) */
+	next_radio_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x2);
+
+	/* the margin is used to account for any overhead in radio switching */
+	next_wu = tx_wu + TX_MARGIN;
+}
+
+void radio_switch_complete_and_disable(void)
+{
+	next_radio_cmd = 0;
+}
+
+void radio_rssi_measure(void)
+{
+	rssi = 0;
+}
+
+uint32_t radio_rssi_get(void)
+{
+	return (uint32_t)-rssi;
+}
+
+void radio_rssi_status_reset(void)
+{
+}
+
+uint32_t radio_rssi_is_ready(void)
+{
+	return (rssi != 0);
+}
+
+void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type,
+			    uint8_t *bdaddr)
+{
+	/* printk("%s\n", __func__); */
+}
+
+void radio_filter_disable(void)
+{
+	/* Nothing to do here */
+}
+
+void radio_filter_status_reset(void)
+{
+	/* printk("%s\n", __func__); */
+}
+
+uint32_t radio_filter_has_match(void)
+{
+	/* printk("%s\n", __func__); */
+	return 0;
+}
+
+uint32_t radio_filter_match_get(void)
+{
+	/* printk("%s\n", __func__); */
+	return 0;
+}
+
+void radio_bc_configure(uint32_t n)
+{
+	printk("%s\n", __func__);
+}
+
+void radio_bc_status_reset(void)
+{
+	printk("%s\n", __func__);
+}
+
+uint32_t radio_bc_has_match(void)
+{
+	printk("%s\n", __func__);
+	return 0;
+}
+
+void radio_tmr_status_reset(void)
+{
+	tmr_aa_save = 0;
+	tmr_end_save = 0;
+}
+
+void radio_tmr_tifs_set(uint32_t tifs)
+{
+	tmr_tifs = tifs;
+}
+
+/* Start the radio after ticks_start (ticks) + remainder (us) time */
+static uint32_t radio_tmr_start_hlp(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
+{
+	uint32_t radio_start_now_cmd = 0;
+
+	/* Disable both comparators */
+	GENFSK->T1_CMP = 0;
+	GENFSK->T2_CMP = 0;
+
+	/* Save it for later */
+	rtc_start = ticks_start;
+
+	/* Convert ticks to us and use just EVENT_TMR */
+	rtc_diff_start_us = HAL_TICKER_TICKS_TO_US(rtc_start - cntr_cnt_get());
+
+	skip_hcto = 0;
+	if (rtc_diff_start_us > GENFSK_T1_CMP_T1_CMP_MASK) {
+		/* ticks_start already passed. Don't start the radio */
+		rtc_diff_start_us = 0;
+
+		/* Ignore time out as well */
+		skip_hcto = 1;
+		return remainder;
+	}
+	remainder += rtc_diff_start_us;
+
+	if (trx) {
+		if (remainder <= MIN_CMD_TIME) {
+			/* 0b0001..TX Start Now */
+			radio_start_now_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x1);
+			remainder = 0;
+		} else {
+			/*
+			 * 0b0010..TX Start @ T1 Timer Compare Match
+			 *         (EVENT_TMR = T1_CMP)
+			 */
+			GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x2);
+			GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(remainder);
+		}
+		tmr_ready = remainder + tx_wu;
+	} else {
+		if (remainder <= MIN_CMD_TIME) {
+			/* 0b0101..RX Start Now */
+			radio_start_now_cmd = GENFSK_XCVR_CTRL_SEQCMD(0x5);
+			remainder = 0;
+		} else {
+			/*
+			 * 0b0110..RX Start @ T1 Timer Compare Match
+			 *         (EVENT_TMR = T1_CMP)
+			 */
+			GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x6);
+			GENFSK->T1_CMP = GENFSK_T1_CMP_T1_CMP(remainder);
+		}
+		tmr_ready = remainder + rx_wu;
+	}
+
+	/*
+	 * reset EVENT_TMR should be done after ticks_start.
+	 * We converted ticks to us, so we reset it now.
+	 * All tmr_* times are relative to EVENT_TMR reset.
+	 * rtc_diff_start_us is used to adjust them
+	 */
+	GENFSK->EVENT_TMR = GENFSK_EVENT_TMR_EVENT_TMR_LD(1);
+
+	if (radio_start_now_cmd) {
+		/* trigger Rx/Tx Start Now */
+		GENFSK->XCVR_CTRL = radio_start_now_cmd;
+	} else {
+		/* enable T1_CMP to trigger the SEQCMD */
+		GENFSK->T1_CMP |= GENFSK_T1_CMP_T1_CMP_EN(1);
+	}
+
+	return remainder;
+}
+
+uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder)
+{
+	if ((!(remainder / 1000000UL)) || (remainder & 0x80000000)) {
+		ticks_start--;
+		remainder += 30517578UL;
+	}
+	remainder /= 1000000UL;
+
+	if (radio_is_off()) {
+		delayed_radio_start = 1;
+		delayed_trx = trx;
+		delayed_ticks_start = ticks_start;
+		delayed_remainder = remainder;
+		return remainder;
+	}
+
+	delayed_radio_start = 0;
+	return radio_tmr_start_hlp(trx, ticks_start, remainder);
+}
+
+uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick)
+{
+	/* Setup compare event with min. 1 us offset */
+	uint32_t remainder_us = 1;
+
+	return radio_tmr_start_hlp(trx, tick, remainder_us);
+}
+
+void radio_tmr_start_us(uint8_t trx, uint32_t us)
+{
+	printk("%s\n", __func__);
+}
+
+uint32_t radio_tmr_start_now(uint8_t trx)
+{
+	printk("%s\n", __func__);
+	return 0;
+}
+
+uint32_t radio_tmr_start_get(void)
+{
+	return rtc_start;
+}
+
+void radio_tmr_stop(void)
+{
+}
+
+static void radio_tmr_hcto_configure_hlp(uint32_t hcto)
+{
+	if (skip_hcto) {
+		skip_hcto = 0;
+		return;
+	}
+
+	/* 0b1001..RX Stop @ T2 Timer Compare Match (EVENT_TMR = T2_CMP) */
+	GENFSK->XCVR_CTRL = GENFSK_XCVR_CTRL_SEQCMD(0x9);
+	GENFSK->T2_CMP = GENFSK_T2_CMP_T2_CMP(hcto) |
+			 GENFSK_T2_CMP_T2_CMP_EN(1);
+
+}
+
+/* Header completion time out */
+void radio_tmr_hcto_configure(uint32_t hcto)
+{
+	if (delayed_radio_start) {
+		delayed_radio_stop = 1;
+		delayed_hcto = hcto;
+		return;
+	}
+
+	delayed_radio_stop = 0;
+	radio_tmr_hcto_configure_hlp(hcto);
+}
+
+void radio_tmr_aa_capture(void)
+{
+	tmr_aa_save = 1;
+}
+
+uint32_t radio_tmr_aa_get(void)
+{
+	return tmr_aa - rtc_diff_start_us;
+}
+
+static uint32_t radio_tmr_aa;
+
+void radio_tmr_aa_save(uint32_t aa)
+{
+	radio_tmr_aa = aa;
+}
+
+uint32_t radio_tmr_aa_restore(void)
+{
+	return radio_tmr_aa;
+}
+
+uint32_t radio_tmr_ready_get(void)
+{
+	return tmr_ready - rtc_diff_start_us;
+}
+
+void radio_tmr_end_capture(void)
+{
+	tmr_end_save = 1;
+}
+
+uint32_t radio_tmr_end_get(void)
+{
+	return tmr_end - rtc_diff_start_us;
+}
+
+uint32_t radio_tmr_tifs_base_get(void)
+{
+	return radio_tmr_end_get() + rtc_diff_start_us;
+}
+
+void radio_tmr_sample(void)
+{
+	printk("%s\n", __func__);
+}
+
+uint32_t radio_tmr_sample_get(void)
+{
+	printk("%s\n", __func__);
+	return 0;
+}
+
+void *radio_ccm_rx_pkt_set_ut(struct ccm *ccm, uint8_t phy, void *pkt)
+{
+	/* Saved by LL as MSO to LSO in the ccm->key
+	 * SK (LSO to MSO)
+	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
+	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
+	 */
+	uint8_t key_local[16] __aligned(4) = {
+		0x99, 0xad, 0x1b, 0x52, 0x26, 0xa3, 0x7e, 0x3e,
+		0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
+	};
+	void *result;
+
+	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
+	memcpy(ccm->key, key_local, sizeof(key_local));
+
+	/* Input std sample data, vol 6, part C, ch 1 */
+	_pkt_scratch[0] = 0x0f;
+	_pkt_scratch[1] = 0x05;
+	_pkt_scratch[2] = 0x9f; /* cleartext = 0x06*/
+	_pkt_scratch[3] = 0xcd;
+	_pkt_scratch[4] = 0xa7;
+	_pkt_scratch[5] = 0xf4;
+	_pkt_scratch[6] = 0x48;
+
+	/* IV std sample data, vol 6, part C, ch 1, stored in LL in LSO format
+	 * IV (LSO to MSO)      :0x24:0xAB:0xDC:0xBA:0xBE:0xBA:0xAF:0xDE
+	 */
+	ccm->iv[0] = 0x24;
+	ccm->iv[1] = 0xAB;
+	ccm->iv[2] = 0xDC;
+	ccm->iv[3] = 0xBA;
+	ccm->iv[4] = 0xBE;
+	ccm->iv[5] = 0xBA;
+	ccm->iv[6] = 0xAF;
+	ccm->iv[7] = 0xDE;
+
+	result = radio_ccm_rx_pkt_set(ccm, phy, pkt);
+	radio_ccm_is_done();
+
+	if (ctx_ccm.auth_mic_valid == 1 && ((uint8_t *)pkt)[2] == 0x06) {
+		BT_INFO("Passed decrypt\n");
+	} else {
+		BT_INFO("Failed decrypt\n");
+	}
+
+	return result;
+}
+
+void *radio_ccm_rx_pkt_set(struct ccm *ccm, uint8_t phy, void *pkt)
+{
+	uint8_t key_local[16] __aligned(4);
+	status_t status;
+	cau3_handle_t handle = {
+			.keySlot = kCAU3_KeySlot2,
+			.taskDone = kCAU3_TaskDonePoll
+	};
+	ARG_UNUSED(phy);
+
+	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
+	memcpy(key_local, ccm->key, sizeof(key_local));
+	ctx_ccm.auth_mic_valid = 0;
+	ctx_ccm.empty_pdu_rxed = 0;
+	ctx_ccm.rx_pkt_in = (struct pdu_data *)_pkt_scratch;
+	ctx_ccm.rx_pkt_out = (struct pdu_data *)pkt;
+	ctx_ccm.nonce.counter = ccm->counter;	/* LSO to MSO, counter is LE */
+	/* The directionBit set to 1 for Data Physical Chan PDUs sent by
+	 * the master and set to 0 for Data Physical Chan PDUs sent by the slave
+	 */
+	ctx_ccm.nonce.bytes[4] |= ccm->direction << 7;
+	memcpy(&ctx_ccm.nonce.bytes[5], ccm->iv, 8); /* LSO to MSO */
+
+	/* Loads the key into CAU3's DMEM and expands the AES key schedule. */
+	status = CAU3_AES_SetKey(CAU3, &handle, key_local, 16);
+	if (status != kStatus_Success) {
+		BT_ERR("CAUv3 AES key set failed %d", status);
+		return NULL;
+	}
+
+	return _pkt_scratch;
+}
+
+void *radio_ccm_tx_pkt_set_ut(struct ccm *ccm, void *pkt)
+{
+	/* Clear:
+	 * 06 1b 17 00 37 36 35 34 33 32 31 30 41 42 43
+	 * 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51
+	 */
+	uint8_t data_in[29] = {
+		0x06, 0x1b, 0x17, 0x00, 0x37, 0x36, 0x35, 0x34,
+		0x33, 0x32, 0x31, 0x30, 0x41, 0x42, 0x43, 0x44,
+		0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+		0x4d, 0x4e, 0x4f, 0x50, 0x51
+	};
+	/* LL_DATA2:
+	 * 06 1f f3 88 81 e7 bd 94 c9 c3 69 b9 a6 68 46
+	 * dd 47 86 aa 8c 39 ce 54 0d 0d ae 3a dc df 89 b9 60 88
+	 */
+	uint8_t data_ref_out[33] = {
+		0x06, 0x1f, 0xf3, 0x88, 0x81, 0xe7, 0xbd, 0x94,
+		0xc9, 0xc3, 0x69, 0xb9, 0xa6, 0x68, 0x46, 0xdd,
+		0x47, 0x86, 0xaa, 0x8c, 0x39, 0xce, 0x54, 0x0d,
+		0x0d, 0xae, 0x3a, 0xdc, 0xdf,
+		0x89, 0xb9, 0x60, 0x88
+	};
+	/* Saved by LL as MSO to LSO in the ccm->key
+	 * SK (LSO to MSO)
+	 * :0x66:0xC6:0xC2:0x27:0x8E:0x3B:0x8E:0x05
+	 * :0x3E:0x7E:0xA3:0x26:0x52:0x1B:0xAD:0x99
+	 */
+	uint8_t key_local[16] __aligned(4) = {
+		0x99, 0xad, 0x1b, 0x52, 0x26, 0xa3, 0x7e, 0x3e,
+		0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
+	};
+	void *result;
+
+	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
+	memcpy(ccm->key, key_local, sizeof(key_local));
+	memcpy(pkt, data_in, sizeof(data_in));
+	/* IV std sample data, vol 6, part C, ch 1, stored in LL in LSO format
+	 * IV (LSO to MSO)      :0x24:0xAB:0xDC:0xBA:0xBE:0xBA:0xAF:0xDE
+	 */
+	ccm->iv[0] = 0x24;
+	ccm->iv[1] = 0xAB;
+	ccm->iv[2] = 0xDC;
+	ccm->iv[3] = 0xBA;
+	ccm->iv[4] = 0xBE;
+	ccm->iv[5] = 0xBA;
+	ccm->iv[6] = 0xAF;
+	ccm->iv[7] = 0xDE;
+	/* 4. Data packet2 (packet 1, S --> M) */
+	ccm->counter = 1;
+	ccm->direction = 0;
+
+	result = radio_ccm_tx_pkt_set(ccm, pkt);
+
+	if (memcmp(result, data_ref_out, sizeof(data_ref_out))) {
+		BT_INFO("Failed encrypt\n");
+	} else {
+		BT_INFO("Passed encrypt\n");
+	}
+
+	return result;
+}
+
+void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt)
+{
+	uint8_t key_local[16] __aligned(4);
+	uint8_t aad;
+	uint8_t *auth_mic;
+	status_t status;
+	cau3_handle_t handle = {
+			.keySlot = kCAU3_KeySlot2,
+			.taskDone = kCAU3_TaskDonePoll
+	};
+
+	/* Test for Empty PDU and bypass encryption */
+	if (((struct pdu_data *)pkt)->len == 0) {
+		return pkt;
+	}
+
+	/* ccm.key[16] is stored in MSO format, as retrieved from e function */
+	memcpy(key_local, ccm->key, sizeof(key_local));
+	ctx_ccm.nonce.counter = ccm->counter;	/* LSO to MSO, counter is LE */
+	/* The directionBit set to 1 for Data Physical Chan PDUs sent by
+	 * the master and set to 0 for Data Physical Chan PDUs sent by the slave
+	 */
+	ctx_ccm.nonce.bytes[4] |= ccm->direction << 7;
+	memcpy(&ctx_ccm.nonce.bytes[5], ccm->iv, 8); /* LSO to MSO */
+
+	/* Loads the key into CAU3's DMEM and expands the AES key schedule. */
+	status = CAU3_AES_SetKey(CAU3, &handle, key_local, 16);
+	if (status != kStatus_Success) {
+		BT_ERR("CAUv3 AES key set failed %d", status);
+		return NULL;
+	}
+
+	auth_mic = _pkt_scratch + 2 + ((struct pdu_data *)pkt)->len;
+	aad = *(uint8_t *)pkt & RADIO_AESCCM_HDR_MASK;
+
+	status = CAU3_AES_CCM_EncryptTag(CAU3, &handle,
+				 (uint8_t *)pkt + 2, ((struct pdu_data *)pkt)->len,
+				 _pkt_scratch + 2,
+				 ctx_ccm.nonce.bytes, 13,
+				 &aad, 1, auth_mic, CAU3_BLE_MIC_SIZE);
+	if (status != kStatus_Success) {
+		BT_ERR("CAUv3 AES CCM decrypt failed %d", status);
+		return 0;
+	}
+
+	_pkt_scratch[0] = *(uint8_t *)pkt;
+	_pkt_scratch[1] = ((struct pdu_data *)pkt)->len + CAU3_BLE_MIC_SIZE;
+
+	return _pkt_scratch;
+}
+
+uint32_t radio_ccm_is_done(void)
+{
+	status_t status;
+	uint8_t *auth_mic;
+	uint8_t aad;
+	cau3_handle_t handle = {
+			.keySlot = kCAU3_KeySlot2,
+			.taskDone = kCAU3_TaskDonePoll
+	};
+
+	if (ctx_ccm.rx_pkt_in->len > CAU3_BLE_MIC_SIZE) {
+		auth_mic = (uint8_t *)ctx_ccm.rx_pkt_in + 2 +
+				ctx_ccm.rx_pkt_in->len - CAU3_BLE_MIC_SIZE;
+		aad = *(uint8_t *)ctx_ccm.rx_pkt_in & RADIO_AESCCM_HDR_MASK;
+		status = CAU3_AES_CCM_DecryptTag(CAU3, &handle,
+				(uint8_t *)ctx_ccm.rx_pkt_in + 2,
+				(uint8_t *)ctx_ccm.rx_pkt_out + 2,
+				ctx_ccm.rx_pkt_in->len - CAU3_BLE_MIC_SIZE,
+				ctx_ccm.nonce.bytes, 13,
+				&aad, 1, auth_mic, CAU3_BLE_MIC_SIZE);
+		if (status != kStatus_Success) {
+			BT_ERR("CAUv3 AES CCM decrypt failed %d", status);
+			return 0;
+		}
+
+		ctx_ccm.auth_mic_valid = handle.micPassed;
+		ctx_ccm.rx_pkt_out->len -= 4;
+
+	} else if (ctx_ccm.rx_pkt_in->len == 0) {
+		/* Just copy input into output */
+		*ctx_ccm.rx_pkt_out = *ctx_ccm.rx_pkt_in;
+		ctx_ccm.auth_mic_valid = 1;
+		ctx_ccm.empty_pdu_rxed = 1;
+	} else {
+		return 0;   /* length only allowed 0, not 1,2,3,4 */
+	}
+
+	return 1;
+}
+
+uint32_t radio_ccm_mic_is_valid(void)
+{
+	return ctx_ccm.auth_mic_valid;
+}
+
+uint32_t radio_ccm_is_available(void)
+{
+	return ctx_ccm.empty_pdu_rxed;
+}
+
+void radio_ar_configure(uint32_t nirk, void *irk)
+{
+	status_t status;
+	uint8_t pirk[16];
+
+	/* Initialize CAUv3 RPA table */
+	status = CAU3_RPAtableInit(CAU3, kCAU3_TaskDoneEvent);
+	if (kStatus_Success != status) {
+		BT_ERR("CAUv3 RPA table init failed");
+		return;
+	}
+
+	/* CAUv3 RPA table is limited to CONFIG_BT_CTLR_RL_SIZE entries */
+	if (nirk > CONFIG_BT_CTLR_RL_SIZE) {
+		BT_WARN("Max CAUv3 RPA table size is %d",
+			CONFIG_BT_CTLR_RL_SIZE);
+		nirk = CONFIG_BT_CTLR_RL_SIZE;
+	}
+
+	/* Insert RPA keys(IRK) in table */
+	for (int i = 0; i < nirk; i++) {
+		/* CAUv3 needs IRK in le format */
+		sys_memcpy_swap(pirk, (uint8_t *)irk + i * 16, 16);
+		status = CAU3_RPAtableInsertKey(CAU3, (uint32_t *)&pirk,
+						kCAU3_TaskDoneEvent);
+		if (kStatus_Success != status) {
+			BT_ERR("CAUv3 RPA table insert failed");
+			return;
+		}
+	}
+
+	/* RPA Table was configured, it can be used for next Rx */
+	radio_ar_ctx.ar_enable = 1U;
+}
+
+uint32_t radio_ar_match_get(void)
+{
+	return radio_ar_ctx.irk_idx;
+}
+
+void radio_ar_status_reset(void)
+{
+	radio_ar_ctx.ar_enable = 0U;
+	radio_ar_ctx.irk_idx = RPA_NO_IRK_MATCH;
+}
+
+uint32_t radio_ar_has_match(void)
+{
+	return (radio_ar_ctx.irk_idx != RPA_NO_IRK_MATCH);
+}
+
+uint32_t radio_sleep(void)
+{
+
+	if (dsm_ref == 0) {
+		return -EALREADY;
+	}
+
+	uint32_t localref = --dsm_ref;
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO) && \
+	(CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* TODO:
+	 * These operations (decrement, check) should be atomic/critical section
+	 * since we turn radio on/off from different contexts/ISRs (LLL, radio).
+	 * It's fine for now as all the contexts have the same priority and
+	 * don't preempt each other.
+	 */
+#else
+#error "Missing atomic operation in radio_sleep()"
+#endif
+	if (localref == 0) {
+
+		uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
+
+		if (status) {
+			/* Already in sleep mode */
+			return 0;
+		}
+
+		/* Disable DSM_TIMER */
+		RSIM->DSM_CONTROL &= ~RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
+
+		/* Get current DSM_TIMER value */
+		uint32_t dsm_timer = RSIM->DSM_TIMER;
+
+		/* Set Sleep time after DSM_ENTER_DELAY */
+		RSIM->MAN_SLEEP = RSIM_MAN_SLEEP_MAN_SLEEP_TIME(dsm_timer +
+				DSM_ENTER_DELAY_TICKS);
+
+		/* Set Wake time to max, we use DSM early exit */
+		RSIM->MAN_WAKE = RSIM_MAN_WAKE_MAN_WAKE_TIME(dsm_timer - 1);
+
+		/* MAN wakeup request enable */
+		RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_MAN_WAKEUP_REQUEST_EN(1);
+
+		/* Enable DSM, sending a sleep request */
+		GENFSK->DSM_CTRL |= GENFSK_DSM_CTRL_GEN_SLEEP_REQUEST(1);
+
+		/* Enable DSM_TIMER */
+		RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_DSM_TIMER_EN(1);
+	}
+
+	return 0;
+}
+
+uint32_t radio_wake(void)
+{
+	uint32_t localref = ++dsm_ref;
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_HIGH_PRIO) && \
+	(CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* TODO:
+	 * These operations (increment, check) should be atomic/critical section
+	 * since we turn radio on/off from different contexts/ISRs (LLL, radio).
+	 * It's fine for now as all the contexts have the same priority and
+	 * don't preempt each other.
+	 */
+#else
+#error "Missing atomic operation in radio_wake()"
+#endif
+	if (localref == 1) {
+
+		uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
+
+		if (!status) {
+			/* Not in sleep mode */
+			return 0;
+		}
+
+		/* Get current DSM_TIMER value */
+		uint32_t dsm_timer = RSIM->DSM_TIMER;
+
+		/* Set Wake time after DSM_ENTER_DELAY */
+		RSIM->MAN_WAKE = RSIM_MAN_WAKE_MAN_WAKE_TIME(dsm_timer +
+				DSM_EXIT_DELAY_TICKS);
+	}
+
+	return 0;
+}
+
+uint32_t radio_is_off(void)
+{
+	uint32_t status = (RSIM->DSM_CONTROL & MAN_DSM_ON);
+
+	return status;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/swi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/swi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/swi.h	(working copy)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "ll_irqs.h"
+
+#define SetPendingIRQ(x) (EVENT_UNIT->INTPTPENDSET |= (uint32_t)(1 << (x)))
+
+static inline void hal_swi_init(void)
+{
+	/* No platform-specific initialization required. */
+}
+
+/* SW IRQs required for the SW defined BLE Controller on RV32M1. */
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+/* Split architecture uses max. two SWI */
+#define HAL_SWI_RADIO_IRQ  LL_SWI4_IRQn
+#define HAL_SWI_WORKER_IRQ LL_RTC0_IRQn
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+#define HAL_SWI_JOB_IRQ    HAL_SWI_WORKER_IRQ
+#else
+#define HAL_SWI_JOB_IRQ    LL_SWI5_IRQn
+#endif
+
+static inline void hal_swi_lll_pend(void)
+{
+	SetPendingIRQ(HAL_SWI_RADIO_IRQ);
+}
+
+#else
+#error "CTRL architecture not defined"
+#endif
+
+static inline void hal_swi_worker_pend(void)
+{
+	SetPendingIRQ(HAL_SWI_WORKER_IRQ);
+}
+
+static inline void hal_swi_job_pend(void)
+{
+	SetPendingIRQ(HAL_SWI_JOB_IRQ);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.h	(working copy)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define HAL_TICKER_CNTR_CLK_FREQ_HZ 32768U
+
+#define HAL_TICKER_CNTR_CMP_OFFSET_MIN 2
+
+#define HAL_TICKER_CNTR_SET_LATENCY 1
+/*
+ * When the LPTMR is enabled, the first increment will take an additional
+ * one or two prescaler clock cycles due to synchronization logic.
+ */
+
+#define HAL_TICKER_US_TO_TICKS(x) \
+	( \
+		((uint32_t)(((uint64_t) (x) * 1000000000UL) / 30517578125UL)) \
+		& HAL_TICKER_CNTR_MASK \
+	)
+
+#define HAL_TICKER_REMAINDER(x) \
+	( \
+		( \
+			((uint64_t) (x) * 1000000000UL) \
+			- ((uint64_t)HAL_TICKER_US_TO_TICKS(x) * 30517578125UL) \
+		) \
+		/ 1000UL \
+	)
+
+#define HAL_TICKER_TICKS_TO_US(x) \
+	((uint32_t)(((uint64_t)(x) * 30517578125UL) / 1000000000UL))
+
+#define HAL_TICKER_CNTR_MSBIT 31
+
+#define HAL_TICKER_CNTR_MASK 0xFFFFFFFF
+
+/* Macro defining the remainder resolution/range
+ * ~ 1000000 * HAL_TICKER_TICKS_TO_US(1)
+ */
+#define HAL_TICKER_REMAINDER_RANGE \
+	HAL_TICKER_TICKS_TO_US(1000000)
+
+/* Macro defining the margin for positioning re-scheduled nodes */
+#define HAL_TICKER_RESCHEDULE_MARGIN \
+	HAL_TICKER_US_TO_TICKS(150)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/RV32M1/ticker.c	(working copy)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <sys/dlist.h>
+#include <sys/mempool_base.h>
+
+#include "hal/cntr.h"
+
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#define LOG_MODULE_NAME bt_ctlr_rv32m1_ticker
+#include "common/log.h"
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+#include "ll_sw/lll.h"
+#define TICKER_MAYFLY_CALL_ID_ISR     TICKER_USER_ID_LLL
+#define TICKER_MAYFLY_CALL_ID_TRIGGER TICKER_USER_ID_ULL_HIGH
+#define TICKER_MAYFLY_CALL_ID_WORKER  TICKER_USER_ID_ULL_HIGH
+#define TICKER_MAYFLY_CALL_ID_JOB     TICKER_USER_ID_ULL_LOW
+#define TICKER_MAYFLY_CALL_ID_PROGRAM TICKER_USER_ID_THREAD
+static uint8_t const caller_id_lut[] = {
+	TICKER_CALL_ID_ISR,
+	TICKER_CALL_ID_WORKER,
+	TICKER_CALL_ID_JOB,
+	TICKER_CALL_ID_PROGRAM
+};
+#else
+#error Unknown LL variant.
+#endif
+
+uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id)
+{
+	uint8_t caller_id;
+
+	LL_ASSERT(user_id < sizeof(caller_id_lut));
+
+	caller_id = caller_id_lut[user_id];
+	LL_ASSERT(caller_id != TICKER_CALL_ID_NONE);
+
+	return caller_id;
+}
+
+void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+				void *instance)
+{
+	/* return value not checked as we allow multiple calls to schedule
+	 * before being actually needing the work to complete before new
+	 * schedule.
+	 */
+	switch (caller_id) {
+#if defined(CONFIG_BT_LL_SW_SPLIT)
+	case TICKER_CALL_ID_ISR:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			/* TODO: scheduler lock, if preemptive threads used */
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_ISR,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+#endif /* CONFIG_BT_LL_SW_SPLIT */
+
+	case TICKER_CALL_ID_TRIGGER:
+		switch (callee_id) {
+		case TICKER_CALL_ID_WORKER:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_worker};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
+				       TICKER_MAYFLY_CALL_ID_WORKER,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_WORKER:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_JOB:
+		switch (callee_id) {
+		case TICKER_CALL_ID_WORKER:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_worker};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
+				       TICKER_MAYFLY_CALL_ID_WORKER,
+				       chain,
+				       &m);
+		}
+		break;
+
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	case TICKER_CALL_ID_PROGRAM:
+		switch (callee_id) {
+		case TICKER_CALL_ID_JOB:
+		{
+			static memq_link_t link;
+			static struct mayfly m = {0, 0, &link, NULL,
+						  ticker_job};
+
+			m.param = instance;
+
+			/* TODO: scheduler lock, if preemptive threads used */
+			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
+				       TICKER_MAYFLY_CALL_ID_JOB,
+				       chain,
+				       &m);
+		}
+		break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+
+void hal_ticker_instance0_trigger_set(uint32_t value)
+{
+	cntr_cmp_set(0, value);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/cpu.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/cpu.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/cpu.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+static inline void cpu_sleep(void)
+{
+	__WFE();
+	/* __SEV(); */
+	__WFE();
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/debug_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/debug_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/debug_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/RV32M1/debug.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/radio_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/radio_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/radio_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/RV32M1/radio/radio.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/swi_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/swi_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/swi_vendor_hal.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "hal/RV32M1/swi.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/ticker_vendor_hal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/ticker_vendor_hal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/hal/ticker_vendor_hal.h	(working copy)
@@ -0,0 +1,6 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "hal/RV32M1/ticker.h"
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll.c	(working copy)
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <device.h>
+#include <drivers/entropy.h>
+#include <drivers/clock_control.h>
+
+#include <soc.h>
+
+#include "hal/swi.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll
+#include "common/log.h"
+
+#include "hal/debug.h"
+
+static struct {
+	struct {
+		void              *param;
+		lll_is_abort_cb_t is_abort_cb;
+		lll_abort_cb_t    abort_cb;
+	} curr;
+} event;
+
+static struct {
+	const struct device *clk;
+} lll;
+
+/* Entropy device */
+static const struct device *dev_entropy;
+
+static int init_reset(void);
+static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		   lll_prepare_cb_t prepare_cb, int prio,
+		   struct lll_prepare_param *prepare_param, uint8_t is_resume);
+static int resume_enqueue(lll_prepare_cb_t resume_cb, int resume_prio);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+static void ticker_start_op_cb(uint32_t status, void *param);
+static void preempt_ticker_start(struct lll_prepare_param *prepare_param);
+static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			      uint16_t lazy, void *param);
+static void preempt(void *param);
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void ticker_op_job_disable(uint32_t status, void *op_context);
+#endif
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+static void rtc0_rv32m1_isr(const void *arg)
+{
+	DEBUG_TICKER_ISR(1);
+
+	/* On compare0 run ticker worker instance0 */
+	if (LPTMR1->CSR & LPTMR_CSR_TCF(1)) {
+		LPTMR1->CSR |= LPTMR_CSR_TCF(1);
+
+		ticker_trigger(0);
+	}
+
+	mayfly_run(TICKER_USER_ID_ULL_HIGH);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	mayfly_run(TICKER_USER_ID_ULL_LOW);
+#endif
+
+	DEBUG_TICKER_ISR(0);
+}
+
+static void swi_lll_rv32m1_isr(const void *arg)
+{
+	DEBUG_RADIO_ISR(1);
+
+	mayfly_run(TICKER_USER_ID_LLL);
+
+	DEBUG_RADIO_ISR(0);
+}
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void swi_ull_low_rv32m1_isr(const void *arg)
+{
+	DEBUG_TICKER_JOB(1);
+
+	mayfly_run(TICKER_USER_ID_ULL_LOW);
+
+	DEBUG_TICKER_JOB(0);
+}
+#endif
+
+int lll_init(void)
+{
+	const struct device *clk_k32;
+	int err;
+
+	ARG_UNUSED(clk_k32);
+
+	/* Get reference to entropy device */
+	dev_entropy = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
+	if (!dev_entropy) {
+		return -ENODEV;
+	}
+
+	/* Initialise LLL internals */
+	event.curr.abort_cb = NULL;
+
+	/* Initialize HF CLK */
+	lll.clk = NULL;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	/* Initialize SW IRQ structure */
+	hal_swi_init();
+
+	/* Connect ISRs */
+	IRQ_CONNECT(LL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, isr_radio, NULL, 0);
+	IRQ_CONNECT(LL_RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO,
+		    rtc0_rv32m1_isr, NULL, 0);
+	IRQ_CONNECT(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO,
+		    swi_lll_rv32m1_isr, NULL, 0);
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	IRQ_CONNECT(HAL_SWI_JOB_IRQ, CONFIG_BT_CTLR_ULL_LOW_PRIO,
+		    swi_ull_low_rv32m1_isr, NULL, 0);
+#endif
+
+	/* Enable IRQs */
+	irq_enable(LL_RADIO_IRQn);
+	irq_enable(LL_RTC0_IRQn);
+	irq_enable(HAL_SWI_RADIO_IRQ);
+#if defined(CONFIG_BT_CTLR_LOW_LAT) || \
+	(CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	irq_enable(HAL_SWI_JOB_IRQ);
+#endif
+
+	/* Call it after IRQ enable to be able to measure ISR latency */
+	radio_setup();
+	return 0;
+}
+
+int lll_csrand_get(void *buf, size_t len)
+{
+	return entropy_get_entropy(dev_entropy, buf, len);
+}
+
+int lll_csrand_isr_get(void *buf, size_t len)
+{
+	return entropy_get_entropy_isr(dev_entropy, buf, len, 0);
+}
+
+int lll_rand_get(void *buf, size_t len)
+{
+	return 0;
+}
+
+int lll_rand_isr_get(void *buf, size_t len)
+{
+	return 0;
+}
+
+int lll_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		lll_prepare_cb_t prepare_cb, int prio,
+		struct lll_prepare_param *prepare_param)
+{
+	return prepare(is_abort_cb, abort_cb, prepare_cb, prio, prepare_param,
+		       0);
+}
+
+void lll_resume(void *param)
+{
+	struct lll_event *next = param;
+	int ret;
+
+	ret = prepare(next->is_abort_cb, next->abort_cb, next->prepare_cb,
+		      next->prio, &next->prepare_param, next->is_resume);
+	LL_ASSERT(!ret || ret == -EINPROGRESS);
+}
+
+void lll_disable(void *param)
+{
+	/* LLL disable of current event, done is generated */
+	if (!param || (param == event.curr.param)) {
+		if (event.curr.abort_cb && event.curr.param) {
+			event.curr.abort_cb(NULL, event.curr.param);
+		} else {
+			LL_ASSERT(!param);
+		}
+	}
+	{
+		struct lll_event *next;
+		uint8_t idx = UINT8_MAX;
+
+		next = ull_prepare_dequeue_iter(&idx);
+		while (next) {
+			if (!next->is_aborted &&
+			    (!param || (param == next->prepare_param.param))) {
+				next->is_aborted = 1;
+				next->abort_cb(&next->prepare_param,
+					       next->prepare_param.param);
+			}
+
+			next = ull_prepare_dequeue_iter(&idx);
+		}
+	}
+}
+
+int lll_prepare_done(void *param)
+{
+#if defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	    (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	uint32_t ret;
+
+	/* Ticker Job Silence */
+	ret = ticker_job_idle_get(TICKER_INSTANCE_ID_CTLR,
+				  TICKER_USER_ID_LLL,
+				  ticker_op_job_disable, NULL);
+
+	return ((ret == TICKER_STATUS_SUCCESS) ||
+		(ret == TICKER_STATUS_BUSY)) ? 0 : -EFAULT;
+#else
+	return 0;
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+}
+
+int lll_done(void *param)
+{
+	struct lll_event *next = ull_prepare_dequeue_get();
+	struct ull_hdr *ull = NULL;
+	void *evdone;
+	int ret = 0;
+
+	/* Assert if param supplied without a pending prepare to cancel. */
+	LL_ASSERT(!param || next);
+
+	/* check if current LLL event is done */
+	if (!param) {
+		/* Reset current event instance */
+		LL_ASSERT(event.curr.abort_cb);
+		event.curr.abort_cb = NULL;
+
+		param = event.curr.param;
+		event.curr.param = NULL;
+
+		if (param) {
+			ull = HDR_ULL(((struct lll_hdr *)param)->parent);
+		}
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) &&
+		    (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)) {
+			mayfly_enable(TICKER_USER_ID_LLL,
+				      TICKER_USER_ID_ULL_LOW,
+				      1);
+		}
+
+		DEBUG_RADIO_CLOSE(0);
+	} else {
+		ull = HDR_ULL(((struct lll_hdr *)param)->parent);
+	}
+
+	/* Let ULL know about LLL event done */
+	evdone = ull_event_done(ull);
+	LL_ASSERT(evdone);
+
+	return ret;
+}
+
+bool lll_is_done(void *param)
+{
+	/* FIXME: use param to check */
+	return !event.curr.abort_cb;
+}
+
+int lll_is_abort_cb(void *next, int prio, void *curr,
+			 lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+	return -ECANCELED;
+}
+
+int lll_clk_on(void)
+{
+	int err;
+
+	/* turn on radio clock in non-blocking mode. */
+	err = radio_wake();
+	if (!err) {
+		DEBUG_RADIO_XTAL(1);
+	}
+
+	return err;
+}
+
+int lll_clk_on_wait(void)
+{
+	int err;
+
+	/* turn on radio clock in blocking mode. */
+	err = radio_wake();
+
+	while (radio_is_off()) {
+		k_cpu_idle();
+	}
+
+	DEBUG_RADIO_XTAL(1);
+
+	return err;
+}
+
+int lll_clk_off(void)
+{
+	int err;
+
+	/* turn off radio clock in non-blocking mode. */
+	err = radio_sleep();
+	if (!err) {
+		DEBUG_RADIO_XTAL(0);
+	}
+
+	return err;
+}
+
+uint32_t lll_evt_offset_get(struct evt_hdr *evt)
+{
+	if (0) {
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+	} else if (evt->ticks_xtal_to_start & XON_BITMASK) {
+		return MAX(evt->ticks_active_to_start,
+			   evt->ticks_preempt_to_start);
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	} else {
+		return MAX(evt->ticks_active_to_start,
+			   evt->ticks_xtal_to_start);
+	}
+}
+
+uint32_t lll_preempt_calc(struct evt_hdr *evt, uint8_t ticker_id,
+		       uint32_t ticks_at_event)
+{
+	uint32_t ticks_now = ticker_ticks_now_get();
+	uint32_t diff;
+
+	diff = ticker_ticks_diff_get(ticks_now, ticks_at_event);
+	diff += HAL_TICKER_CNTR_CMP_OFFSET_MIN;
+	if (!(diff & BIT(HAL_TICKER_CNTR_MSBIT)) &&
+	    (diff > HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US))) {
+		/* TODO: for Low Latency Feature with Advanced XTAL feature.
+		 * 1. Release retained HF clock.
+		 * 2. Advance the radio event to accommodate normal prepare
+		 *    duration.
+		 * 3. Increase the preempt to start ticks for future events.
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+void lll_chan_set(uint32_t chan)
+{
+	switch (chan) {
+	case 37:
+		radio_freq_chan_set(2);
+		break;
+
+	case 38:
+		radio_freq_chan_set(26);
+		break;
+
+	case 39:
+		radio_freq_chan_set(80);
+		break;
+
+	default:
+		if (chan < 11) {
+			radio_freq_chan_set(4 + (chan * 2U));
+		} else if (chan < 40) {
+			radio_freq_chan_set(28 + ((chan - 11) * 2U));
+		} else {
+			LL_ASSERT(0);
+		}
+		break;
+	}
+
+	radio_whiten_iv_set(chan);
+}
+
+
+uint32_t lll_radio_is_idle(void)
+{
+	return radio_is_idle();
+}
+
+uint32_t lll_radio_tx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return radio_tx_ready_delay_get(phy, flags);
+}
+
+uint32_t lll_radio_rx_ready_delay_get(uint8_t phy, uint8_t flags)
+{
+	return radio_rx_ready_delay_get(phy, flags);
+}
+
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		   lll_prepare_cb_t prepare_cb, int prio,
+		   struct lll_prepare_param *prepare_param, uint8_t is_resume)
+{
+	uint8_t idx = UINT8_MAX;
+	struct lll_event *p;
+	int ret, err;
+
+	/* Find the ready prepare in the pipeline */
+	p = ull_prepare_dequeue_iter(&idx);
+	while (p && (p->is_aborted || p->is_resume)) {
+		p = ull_prepare_dequeue_iter(&idx);
+	}
+
+	/* Current event active or another prepare is ready in the pipeline */
+	if (event.curr.abort_cb || (p && is_resume)) {
+#if defined(CONFIG_BT_CTLR_LOW_LAT)
+		lll_prepare_cb_t resume_cb;
+		struct lll_event *next;
+		int resume_prio;
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) && event.curr.param) {
+			/* early abort */
+			event.curr.abort_cb(NULL, event.curr.param);
+		}
+
+		/* Store the next prepare for deferred call */
+		ret = ull_prepare_enqueue(is_abort_cb, abort_cb, prepare_param,
+					  prepare_cb, prio, is_resume);
+		LL_ASSERT(!ret);
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+		if (is_resume) {
+			return -EINPROGRESS;
+		}
+
+		preempt_ticker_start(prepare_param);
+
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+		next = NULL;
+		while (p) {
+			if (!p->is_aborted) {
+				if (event.curr.param ==
+				    p->prepare_param.param) {
+					p->is_aborted = 1;
+					p->abort_cb(&p->prepare_param,
+						    p->prepare_param.param);
+				} else {
+					next = p;
+				}
+			}
+
+			p = ull_prepare_dequeue_iter(&idx);
+		}
+
+		if (next) {
+			/* check if resume requested by curr */
+			ret = event.curr.is_abort_cb(NULL, 0, event.curr.param,
+						     &resume_cb, &resume_prio);
+			LL_ASSERT(ret);
+
+			if (ret == -EAGAIN) {
+				ret = resume_enqueue(resume_cb, resume_prio);
+				LL_ASSERT(!ret);
+			} else {
+				LL_ASSERT(ret == -ECANCELED);
+			}
+		}
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+		return -EINPROGRESS;
+	}
+
+	event.curr.param = prepare_param->param;
+	event.curr.is_abort_cb = is_abort_cb;
+	event.curr.abort_cb = abort_cb;
+
+	err = prepare_cb(prepare_param);
+
+	/* NOTE: Should the preempt timeout be stopped, check for any more
+	 *       in pipeline?
+	 */
+
+	return err;
+}
+
+static int resume_enqueue(lll_prepare_cb_t resume_cb, int resume_prio)
+{
+	struct lll_prepare_param prepare_param;
+
+	prepare_param.param = event.curr.param;
+	event.curr.param = NULL;
+
+	return ull_prepare_enqueue(event.curr.is_abort_cb, event.curr.abort_cb,
+				   &prepare_param, resume_cb, resume_prio, 1);
+}
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT)
+static void ticker_start_op_cb(uint32_t status, void *param)
+{
+	/* NOTE: this callback is present only for addition debug messages
+	 * when needed, else can be dispensed with.
+	 */
+	ARG_UNUSED(param);
+
+	LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
+		  (status == TICKER_STATUS_FAILURE));
+}
+
+static void preempt_ticker_start(struct lll_prepare_param *prepare_param)
+{
+	uint32_t preempt_anchor;
+	struct evt_hdr *evt;
+	uint32_t preempt_to;
+	int ret;
+
+	/* Calc the preempt timeout */
+	evt = HDR_LLL2EVT(prepare_param->param);
+	preempt_anchor = prepare_param->ticks_at_expire;
+	preempt_to = MAX(evt->ticks_active_to_start,
+			 evt->ticks_xtal_to_start) -
+			 evt->ticks_preempt_to_start;
+
+	/* Setup pre empt timeout */
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+			   TICKER_USER_ID_LLL,
+			   TICKER_ID_LLL_PREEMPT,
+			   preempt_anchor,
+			   preempt_to,
+			   TICKER_NULL_PERIOD,
+			   TICKER_NULL_REMAINDER,
+			   TICKER_NULL_LAZY,
+			   TICKER_NULL_SLOT,
+			   preempt_ticker_cb, NULL,
+			   ticker_start_op_cb, NULL);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_FAILURE) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			       uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, preempt};
+	uint32_t ret;
+
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!ret);
+}
+
+static void preempt(void *param)
+{
+	struct lll_event *next = ull_prepare_dequeue_get();
+	lll_prepare_cb_t resume_cb;
+	uint8_t idx = UINT8_MAX;
+	int resume_prio;
+	int ret;
+
+	if (!event.curr.abort_cb || !event.curr.param) {
+		return;
+	}
+
+	next = ull_prepare_dequeue_iter(&idx);
+	if (!next) {
+		return;
+	}
+
+	while (next && (next->is_aborted || next->is_resume)) {
+		next = ull_prepare_dequeue_iter(&idx);
+	}
+
+	if (!next) {
+		return;
+	}
+
+	ret = event.curr.is_abort_cb(next->prepare_param.param, next->prio,
+				     event.curr.param,
+				     &resume_cb, &resume_prio);
+	if (!ret) {
+		/* Let LLL know about the cancelled prepare */
+		next->is_aborted = 1;
+		next->abort_cb(&next->prepare_param, next->prepare_param.param);
+
+		goto preempt_next;
+	}
+
+	event.curr.abort_cb(NULL, event.curr.param);
+
+	if (ret == -EAGAIN) {
+		struct lll_event *iter;
+		uint8_t iter_idx = UINT8_MAX;
+
+		iter = ull_prepare_dequeue_iter(&iter_idx);
+		while (iter) {
+			if (!iter->is_aborted &&
+			    event.curr.param == iter->prepare_param.param) {
+				iter->is_aborted = 1;
+				iter->abort_cb(&iter->prepare_param,
+					       iter->prepare_param.param);
+			}
+
+			iter = ull_prepare_dequeue_iter(&iter_idx);
+		}
+
+		ret = resume_enqueue(resume_cb, resume_prio);
+		LL_ASSERT(!ret);
+	} else {
+		LL_ASSERT(ret == -ECANCELED);
+	}
+
+preempt_next:
+	do {
+		next = ull_prepare_dequeue_iter(&idx);
+		if (!next) {
+			return;
+		}
+	} while (next->is_aborted || next->is_resume);
+
+	preempt_ticker_start(&next->prepare_param);
+}
+#else /* CONFIG_BT_CTLR_LOW_LAT */
+
+#if (CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+static void ticker_op_job_disable(uint32_t status, void *op_context)
+{
+	ARG_UNUSED(status);
+	ARG_UNUSED(op_context);
+
+	/* FIXME: */
+	if (1 /* _radio.state != STATE_NONE */) {
+		mayfly_enable(TICKER_USER_ID_ULL_LOW,
+			      TICKER_USER_ID_ULL_LOW, 0);
+	}
+}
+#endif
+
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.h	(working copy)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct lll_adv_pdu {
+	uint8_t           first;
+	uint8_t           last;
+	/* TODO: use,
+	 * struct pdu_adv *pdu[DOUBLE_BUFFER_SIZE];
+	 */
+	uint8_t pdu[DOUBLE_BUFFER_SIZE][PDU_AC_LL_SIZE_MAX];
+};
+
+struct lll_adv {
+	struct lll_hdr hdr;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	/* NOTE: conn context has to be after lll_hdr */
+	struct lll_conn *conn;
+	uint8_t is_hdcd:1;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	uint8_t chan_map:3;
+	uint8_t chan_map_curr:3;
+	uint8_t filter_policy:2;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint8_t phy_p:3;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	uint8_t is_mesh:1;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	struct lll_adv_pdu adv_data;
+	struct lll_adv_pdu scan_rsp;
+};
+
+int lll_adv_init(void);
+int lll_adv_reset(void);
+
+void lll_adv_prepare(void *param);
+
+static inline struct pdu_adv *lll_adv_pdu_alloc(struct lll_adv_pdu *pdu,
+						uint8_t *idx)
+{
+	uint8_t last;
+
+	if (pdu->first == pdu->last) {
+		last = pdu->last + 1;
+		if (last == DOUBLE_BUFFER_SIZE) {
+			last = 0U;
+		}
+	} else {
+		last = pdu->last;
+	}
+
+	*idx = last;
+
+	return (void *)pdu->pdu[last];
+}
+
+static inline void lll_adv_pdu_enqueue(struct lll_adv_pdu *pdu, uint8_t idx)
+{
+	pdu->last = idx;
+}
+
+static inline struct pdu_adv *lll_adv_data_alloc(struct lll_adv *lll, uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->adv_data, idx);
+}
+
+static inline void lll_adv_data_enqueue(struct lll_adv *lll, uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->adv_data, idx);
+}
+
+static inline struct pdu_adv *lll_adv_data_peek(struct lll_adv *lll)
+{
+	return (void *)lll->adv_data.pdu[lll->adv_data.last];
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_alloc(struct lll_adv *lll,
+						     uint8_t *idx)
+{
+	return lll_adv_pdu_alloc(&lll->scan_rsp, idx);
+}
+
+static inline void lll_adv_scan_rsp_enqueue(struct lll_adv *lll, uint8_t idx)
+{
+	lll_adv_pdu_enqueue(&lll->scan_rsp, idx);
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_peek(struct lll_adv *lll)
+{
+	return (void *)lll->scan_rsp.pdu[lll->scan_rsp.last];
+}
+
+extern uint16_t ull_adv_lll_handle_get(struct lll_adv *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv.c	(working copy)
@@ -0,0 +1,879 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+
+#include <toolchain.h>
+#include <bluetooth/hci.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_adv.h"
+#include "lll_conn.h"
+#include "lll_chan.h"
+#include "lll_filter.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_adv_internal.h"
+#include "lll_prof_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_adv
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *prepare_param);
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio);
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
+static void isr_tx(void *param);
+static void isr_rx(void *param);
+static void isr_done(void *param);
+static void isr_abort(void *param);
+static void isr_cleanup(void *param);
+static void isr_race(void *param);
+static void chan_prepare(struct lll_adv *lll);
+static inline int isr_rx_pdu(struct lll_adv *lll,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready);
+static inline bool isr_rx_sr_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *sr, uint8_t devmatch_ok,
+				   uint8_t *rl_idx);
+static inline bool isr_rx_sr_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *sr);
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+static inline int isr_rx_sr_report(struct pdu_adv *pdu_adv_rx,
+				   uint8_t rssi_ready);
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+static inline bool isr_rx_ci_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *ci, uint8_t devmatch_ok,
+				   uint8_t *rl_idx);
+static inline bool isr_rx_ci_tgta_check(struct lll_adv *lll,
+					struct pdu_adv *adv, struct pdu_adv *ci,
+					uint8_t rl_idx);
+static inline bool isr_rx_ci_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *ci);
+
+int lll_adv_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_adv_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_adv_prepare(void *param)
+{
+	struct lll_prepare_param *p = param;
+	int err;
+
+	err = lll_clk_on();
+	LL_ASSERT(!err || err == -EINPROGRESS);
+
+	err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *prepare_param)
+{
+	struct lll_adv *lll = prepare_param->param;
+	uint32_t aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	uint32_t ticks_at_event, ticks_at_start;
+	struct evt_hdr *evt;
+	uint32_t remainder_us;
+	uint32_t remainder;
+
+	DEBUG_RADIO_START_A(1);
+
+	/* Check if stopped (on connection establishment race between LLL and
+	 * ULL.
+	 */
+	if (lll_is_stop(lll)) {
+		int err;
+
+		err = lll_clk_off();
+		LL_ASSERT(!err || err == -EBUSY);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_START_A(0);
+		return 0;
+	}
+
+	radio_reset();
+	/* TODO: other Tx Power settings */
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	/* TODO: if coded we use S8? */
+	radio_phy_set(lll->phy_p, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy_p << 1));
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	radio_phy_set(0, 0);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, 0);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+
+	lll->chan_map_curr = lll->chan_map;
+
+	chan_prepare(lll);
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	_radio.mesh_adv_end_us = 0;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		struct lll_filter *filter =
+			ull_filter_lll_get(!!(lll->filter_policy));
+
+		radio_filter_configure(filter->enable_bitmask,
+				       filter->addr_type_bitmask,
+				       (uint8_t *)filter->bdaddr);
+	} else
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_FILTER) && lll->filter_policy) {
+			/* Setup Radio Filter */
+			struct lll_filter *wl = ull_filter_lll_get(true);
+
+
+			radio_filter_configure(wl->enable_bitmask,
+					       wl->addr_type_bitmask,
+					       (uint8_t *)wl->bdaddr);
+		}
+
+	ticks_at_event = prepare_param->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = prepare_param->remainder;
+	remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
+
+	/* capture end of Tx-ed PDU, used to calculate HCTO. */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_tx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_ADV_BASE +
+				   ull_adv_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_A(1);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static int resume_prepare_cb(struct lll_prepare_param *p)
+{
+	struct evt_hdr *evt = HDR_LLL2EVT(p->param);
+
+	p->ticks_at_expire = ticker_ticks_now_get() - lll_evt_offset_get(evt);
+	p->remainder = 0;
+	p->lazy = 0;
+
+	return prepare_cb(p);
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+#if defined(CONFIG_BT_PERIPHERAL)
+	struct lll_adv *lll = curr;
+	struct pdu_adv *pdu;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	/* TODO: prio check */
+	if (next != curr) {
+		if (0) {
+#if defined(CONFIG_BT_PERIPHERAL)
+		} else if (lll->is_hdcd) {
+			int err;
+
+			/* wrap back after the pre-empter */
+			*resume_cb = resume_prepare_cb;
+			*resume_prio = 0; /* TODO: */
+
+			/* Retain HF clk */
+			err = lll_clk_on();
+			LL_ASSERT(!err || err == -EINPROGRESS);
+
+			return -EAGAIN;
+#endif /* CONFIG_BT_PERIPHERAL */
+		} else {
+			return -ECANCELED;
+		}
+	}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	pdu = lll_adv_data_curr_get(lll);
+	if (pdu->type == PDU_ADV_TYPE_DIRECT_IND) {
+		return 0;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return -ECANCELED;
+}
+
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_abort, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(param);
+}
+
+static void isr_tx(void *param)
+{
+	uint32_t hcto;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+	/* TODO: MOVE ^^ */
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	radio_pkt_rx_set(radio_pkt_scratch_get());
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_cputime_capture();
+	}
+
+	radio_isr_set(isr_rx, param);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 + 1;
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+	radio_tmr_hcto_configure(hcto);
+
+	/* capture end of CONNECT_IND PDU, used for calculating first
+	 * slave event.
+	 */
+	radio_tmr_end_capture();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_SCAN_REQ_RSSI) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_CONN_RSSI)) {
+		radio_rssi_measure();
+	}
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* PA/LNA enable is overwriting packet end used in ISR
+		 * profiling, hence back it up for later use.
+		 */
+		lll_prof_radio_end_backup();
+	}
+
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		/* NOTE: as scratch packet is used to receive, it is safe to
+		 * generate profile event using rx nodes.
+		 */
+		lll_prof_send();
+	}
+}
+
+static void isr_rx(void *param)
+{
+	uint8_t trx_done;
+	uint8_t crc_ok;
+	uint8_t devmatch_ok;
+	uint8_t devmatch_id;
+	uint8_t irkmatch_ok;
+	uint8_t irkmatch_id;
+	uint8_t rssi_ready;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		devmatch_ok = radio_filter_has_match();
+		devmatch_id = radio_filter_match_get();
+		irkmatch_ok = radio_ar_has_match();
+		irkmatch_id = radio_ar_match_get();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = devmatch_ok = irkmatch_ok = rssi_ready = 0U;
+		devmatch_id = irkmatch_id = 0xFF;
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+
+	if (!trx_done) {
+		goto isr_rx_do_close;
+	}
+
+	if (crc_ok) {
+		int err;
+
+		err = isr_rx_pdu(param, devmatch_ok, devmatch_id, irkmatch_ok,
+				 irkmatch_id, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(isr_done, param);
+	radio_disable();
+}
+
+static void isr_done(void *param)
+{
+	struct node_rx_hdr *node_rx;
+	struct lll_adv *lll = param;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+	/* TODO: MOVE ^^ */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (_radio.advertiser.is_mesh &&
+	    !_radio.mesh_adv_end_us) {
+		_radio.mesh_adv_end_us = radio_tmr_end_get();
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!lll->chan_map_curr && lll->is_hdcd) {
+		lll->chan_map_curr = lll->chan_map;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	if (lll->chan_map_curr) {
+		uint32_t start_us;
+
+		chan_prepare(lll);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		start_us = radio_tmr_start_now(1);
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(start_us +
+					 radio_tx_ready_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+		ARG_UNUSED(start_us);
+
+		radio_tx_enable();
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+
+		return;
+	}
+
+	radio_filter_disable();
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!lll->is_hdcd)
+#endif /* CONFIG_BT_PERIPHERAL */
+	{
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+		if (_radio.advertiser.is_mesh) {
+			uint32_t err;
+
+			err = isr_close_adv_mesh();
+			if (err) {
+				return 0;
+			}
+		}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (node_rx) {
+		ull_pdu_rx_alloc();
+
+		/* TODO: add other info by defining a payload struct */
+		node_rx->type = NODE_RX_TYPE_ADV_INDICATION;
+
+		ull_rx_put(node_rx->link, node_rx);
+		ull_rx_sched();
+	}
+#else /* !CONFIG_BT_CTLR_ADV_INDICATION */
+	ARG_UNUSED(node_rx);
+#endif /* !CONFIG_BT_CTLR_ADV_INDICATION */
+
+	isr_cleanup(param);
+}
+
+static void isr_abort(void *param)
+{
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+
+	radio_filter_disable();
+
+	isr_cleanup(param);
+}
+
+static void isr_cleanup(void *param)
+{
+	int err;
+
+	radio_isr_set(isr_race, param);
+	radio_tmr_stop();
+
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(NULL);
+}
+
+static void isr_race(void *param)
+{
+	/* NOTE: lll_disable could have a race with ... */
+	radio_status_reset();
+}
+
+static void chan_prepare(struct lll_adv *lll)
+{
+	struct pdu_adv *pdu;
+	struct pdu_adv *scan_pdu;
+	uint8_t chan;
+	uint8_t upd = 0U;
+
+	pdu = lll_adv_data_latest_get(lll, &upd);
+	scan_pdu = lll_adv_scan_rsp_latest_get(lll, &upd);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (upd) {
+		/* Copy the address from the adv packet we will send into the
+		 * scan response.
+		 */
+		memcpy(&scan_pdu->scan_rsp.addr[0],
+		       &pdu->adv_ind.addr[0], BDADDR_SIZE);
+	}
+#else
+	ARG_UNUSED(scan_pdu);
+	ARG_UNUSED(upd);
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+	radio_pkt_tx_set(pdu);
+
+	if ((pdu->type != PDU_ADV_TYPE_NONCONN_IND) &&
+	    (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) ||
+	     (pdu->type != PDU_ADV_TYPE_EXT_IND))) {
+		radio_isr_set(isr_tx, lll);
+		radio_tmr_tifs_set(EVENT_IFS_US);
+		radio_switch_complete_and_rx(0);
+	} else {
+		radio_isr_set(isr_done, lll);
+		radio_switch_complete_and_disable();
+	}
+
+	chan = find_lsb_set(lll->chan_map_curr);
+	LL_ASSERT(chan);
+
+	lll->chan_map_curr &= (lll->chan_map_curr - 1);
+
+	lll_chan_set(36 + chan);
+}
+
+static inline int isr_rx_pdu(struct lll_adv *lll,
+			     uint8_t devmatch_ok, uint8_t devmatch_id,
+			     uint8_t irkmatch_ok, uint8_t irkmatch_id,
+			     uint8_t rssi_ready)
+{
+	struct pdu_adv *pdu_rx, *pdu_adv;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* An IRK match implies address resolution enabled */
+	uint8_t rl_idx = irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
+				    FILTER_IDX_NONE;
+#else
+	uint8_t rl_idx = FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	pdu_rx = (void *)radio_pkt_scratch_get();
+	pdu_adv = lll_adv_data_curr_get(lll);
+
+	if ((pdu_rx->type == PDU_ADV_TYPE_SCAN_REQ) &&
+	    (pdu_rx->len == sizeof(struct pdu_adv_scan_req)) &&
+	    (pdu_adv->type != PDU_ADV_TYPE_DIRECT_IND) &&
+	    isr_rx_sr_check(lll, pdu_adv, pdu_rx, devmatch_ok, &rl_idx)) {
+		radio_isr_set(isr_done, lll);
+		radio_switch_complete_and_disable();
+		radio_pkt_tx_set(lll_adv_scan_rsp_curr_get(lll));
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+		if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) ||
+		    0 /* TODO: extended adv. scan req notification enabled */) {
+			uint32_t err;
+
+			/* Generate the scan request event */
+			err = isr_rx_sr_report(pdu_rx, rssi_ready);
+			if (err) {
+				/* Scan Response will not be transmitted */
+				return err;
+			}
+		}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end used in ISR
+			 * profiling, hence back it up for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+		return 0;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	} else if ((pdu_rx->type == PDU_ADV_TYPE_CONNECT_IND) &&
+		   (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
+		   isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
+				   &rl_idx) &&
+		   lll->conn) {
+		struct node_rx_ftr *ftr;
+		struct node_rx_pdu *rx;
+		int ret;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			rx = ull_pdu_rx_alloc_peek(4);
+		} else {
+			rx = ull_pdu_rx_alloc_peek(3);
+		}
+
+		if (!rx) {
+			return -ENOBUFS;
+		}
+
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+
+		/* assert if radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		if (rssi_ready) {
+			lll->conn->rssi_latest =  radio_rssi_get();
+		}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+		/* Stop further LLL radio events */
+		ret = lll_stop(lll);
+		LL_ASSERT(!ret);
+
+		rx = ull_pdu_rx_alloc();
+
+		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+		rx->hdr.handle = 0xffff;
+
+		memcpy(rx->pdu, pdu_rx, (offsetof(struct pdu_adv, connect_ind) +
+					 sizeof(struct pdu_adv_connect_ind)));
+
+		ftr = &(rx->hdr.rx_ftr);
+		ftr->param = lll;
+		ftr->ticks_anchor = radio_tmr_start_get();
+		ftr->radio_end_us = radio_tmr_end_get() -
+				    radio_tx_chain_delay_get(0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			ftr->extra = ull_pdu_rx_alloc();
+		}
+
+		ull_rx_put(rx->hdr.link, rx);
+		ull_rx_sched();
+
+		return 0;
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+
+	return -EINVAL;
+}
+
+static inline bool isr_rx_sr_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *sr, uint8_t devmatch_ok,
+				   uint8_t *rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return ((((lll->filter_policy & 0x01) == 0) &&
+		 ull_filter_lll_rl_addr_allowed(sr->tx_addr,
+						sr->scan_req.scan_addr,
+						rl_idx)) ||
+		(((lll->filter_policy & 0x01) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(*rl_idx)))) &&
+		isr_rx_sr_adva_check(adv, sr);
+#else
+	return (((lll->filter_policy & 0x01) == 0U) || devmatch_ok) &&
+		isr_rx_sr_adva_check(adv, sr);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+static inline bool isr_rx_sr_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *sr)
+{
+	return (adv->tx_addr == sr->rx_addr) &&
+		!memcmp(adv->adv_ind.addr, sr->scan_req.adv_addr, BDADDR_SIZE);
+}
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+static inline int isr_rx_sr_report(struct pdu_adv *pdu_adv_rx,
+				   uint8_t rssi_ready)
+{
+	struct node_rx_pdu *node_rx;
+	struct pdu_adv *pdu_adv;
+	uint8_t pdu_len;
+
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (!node_rx) {
+		return -ENOBUFS;
+	}
+	ull_pdu_rx_alloc();
+
+	/* Prepare the report (scan req) */
+	node_rx->hdr.type = NODE_RX_TYPE_SCAN_REQ;
+	node_rx->hdr.handle = 0xffff;
+
+	/* Make a copy of PDU into Rx node (as the received PDU is in the
+	 * scratch buffer), and save the RSSI value.
+	 */
+	pdu_adv = (void *)node_rx->pdu;
+	pdu_len = offsetof(struct pdu_adv, payload) + pdu_adv_rx->len;
+	memcpy(pdu_adv, pdu_adv_rx, pdu_len);
+
+	node_rx->hdr.rx_ftr.rssi = (rssi_ready) ? (radio_rssi_get() & 0x7f) :
+						  0x7f;
+
+	ull_rx_put(node_rx->hdr.link, node_rx);
+	ull_rx_sched();
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+static inline bool isr_rx_ci_check(struct lll_adv *lll, struct pdu_adv *adv,
+				   struct pdu_adv *ci, uint8_t devmatch_ok,
+				   uint8_t *rl_idx)
+{
+	/* LL 4.3.2: filter policy shall be ignored for directed adv */
+	if (adv->type == PDU_ADV_TYPE_DIRECT_IND) {
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		return ull_filter_lll_rl_addr_allowed(ci->tx_addr,
+						      ci->connect_ind.init_addr,
+						      rl_idx) &&
+#else
+		return (1) &&
+#endif
+		       isr_rx_ci_adva_check(adv, ci) &&
+		       isr_rx_ci_tgta_check(lll, adv, ci, *rl_idx);
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return ((((lll->filter_policy & 0x02) == 0) &&
+		 ull_filter_lll_rl_addr_allowed(ci->tx_addr,
+						ci->connect_ind.init_addr,
+						rl_idx)) ||
+		(((lll->filter_policy & 0x02) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(*rl_idx)))) &&
+	       isr_rx_ci_adva_check(adv, ci);
+#else
+	return (((lll->filter_policy & 0x02) == 0) ||
+		(devmatch_ok)) &&
+	       isr_rx_ci_adva_check(adv, ci);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+static inline bool isr_rx_ci_tgta_check(struct lll_adv *lll,
+					struct pdu_adv *adv, struct pdu_adv *ci,
+					uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (rl_idx != FILTER_IDX_NONE && lll->rl_idx != FILTER_IDX_NONE) {
+		return rl_idx == lll->rl_idx;
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	return (adv->rx_addr == ci->tx_addr) &&
+	       !memcmp(adv->direct_ind.tgt_addr, ci->connect_ind.init_addr,
+		       BDADDR_SIZE);
+}
+
+static inline bool isr_rx_ci_adva_check(struct pdu_adv *adv,
+					struct pdu_adv *ci)
+{
+	return (adv->tx_addr == ci->rx_addr) &&
+		(((adv->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		 !memcmp(adv->direct_ind.adv_addr, ci->connect_ind.adv_addr,
+			 BDADDR_SIZE)) ||
+		 (!memcmp(adv->adv_ind.addr, ci->connect_ind.adv_addr,
+			  BDADDR_SIZE)));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv_internal.h	(working copy)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+static inline struct pdu_adv *lll_adv_pdu_latest_get(struct lll_adv_pdu *pdu,
+						     uint8_t *is_modified)
+{
+	uint8_t first;
+
+	first = pdu->first;
+	if (first != pdu->last) {
+		first += 1U;
+		if (first == DOUBLE_BUFFER_SIZE) {
+			first = 0U;
+		}
+		pdu->first = first;
+		*is_modified = 1U;
+	}
+
+	return (void *)pdu->pdu[first];
+}
+
+static inline struct pdu_adv *lll_adv_data_latest_get(struct lll_adv *lll,
+						      uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->adv_data, is_modified);
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_latest_get(struct lll_adv *lll,
+							  uint8_t *is_modified)
+{
+	return lll_adv_pdu_latest_get(&lll->scan_rsp, is_modified);
+}
+
+static inline struct pdu_adv *lll_adv_data_curr_get(struct lll_adv *lll)
+{
+	return (void *)lll->adv_data.pdu[lll->adv_data.first];
+}
+
+static inline struct pdu_adv *lll_adv_scan_rsp_curr_get(struct lll_adv *lll)
+{
+	return (void *)lll->scan_rsp.pdu[lll->scan_rsp.first];
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_clock.c	(working copy)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <soc.h>
+#include <device.h>
+#include <drivers/clock_control.h>
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_clock
+#include "common/log.h"
+#include "hal/debug.h"
+
+static uint16_t const sca_ppm_lut[] = {500, 250, 150, 100, 75, 50, 30, 20};
+
+int lll_clock_wait(void)
+{
+	return 0;
+}
+
+uint8_t lll_clock_sca_local_get(void)
+{
+	return 0;
+}
+
+uint32_t lll_clock_ppm_local_get(void)
+{
+	return sca_ppm_lut[0];
+}
+
+uint32_t lll_clock_ppm_get(uint8_t sca)
+{
+	return sca_ppm_lut[sca];
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn.c	(working copy)
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mfifo.h"
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_conn.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_conn
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static void isr_done(void *param);
+static void isr_cleanup(void *param);
+static void isr_race(void *param);
+static int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
+		      struct node_tx **tx_release, uint8_t *is_rx_enqueue);
+static struct pdu_data *empty_tx_enqueue(struct lll_conn *lll);
+
+static uint8_t crc_expire;
+static uint8_t crc_valid;
+static uint16_t trx_cnt;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static uint8_t mic_state;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+int lll_conn_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_conn_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_conn_prepare_reset(void)
+{
+	trx_cnt = 0U;
+	crc_expire = 0U;
+	crc_valid = 0U;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	mic_state = LLL_CONN_MIC_NONE;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+}
+
+void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_done, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(param);
+}
+
+void lll_conn_isr_rx(void *param)
+{
+	struct node_tx *tx_release = NULL;
+	struct lll_conn *lll = param;
+	struct pdu_data *pdu_data_rx;
+	struct pdu_data *pdu_data_tx;
+	struct node_rx_pdu *node_rx;
+	uint8_t is_empty_pdu_tx_retry;
+	uint8_t is_crc_backoff = 0U;
+	uint8_t is_rx_enqueue = 0U;
+	uint8_t is_ull_rx = 0U;
+	uint8_t rssi_ready;
+	uint8_t trx_done;
+	uint8_t is_done;
+	uint8_t crc_ok;
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	lll_prof_latency_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = rssi_ready = 0U;
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_rssi_status_reset();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || \
+	defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_pa_lna_disable();
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN || CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	if (!trx_done) {
+		radio_isr_set(isr_done, param);
+		radio_disable();
+
+		return;
+	}
+
+	trx_cnt++;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	pdu_data_rx = (void *)node_rx->pdu;
+
+	if (crc_ok) {
+		uint32_t err;
+
+		err = isr_rx_pdu(lll, pdu_data_rx, &tx_release, &is_rx_enqueue);
+		if (err) {
+			goto lll_conn_isr_rx_exit;
+		}
+
+		/* Reset CRC expiry counter */
+		crc_expire = 0U;
+
+		/* CRC valid flag used to detect supervision timeout */
+		crc_valid = 1U;
+	} else {
+		/* Start CRC error countdown, if not already started */
+		if (crc_expire == 0U) {
+			crc_expire = 2U;
+		}
+
+		/* CRC error countdown */
+		crc_expire--;
+		is_crc_backoff = (crc_expire == 0U);
+	}
+
+	/* prepare tx packet */
+	is_empty_pdu_tx_retry = lll->empty;
+	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
+
+	/* Decide on event continuation and hence Radio Shorts to use */
+	is_done = is_crc_backoff || ((crc_ok) && (pdu_data_rx->md == 0) &&
+				     (pdu_data_tx->len == 0));
+
+	if (is_done) {
+		radio_isr_set(isr_done, param);
+
+		if (0) {
+#if defined(CONFIG_BT_CENTRAL)
+		/* Event done for master */
+		} else if (!lll->role) {
+			radio_disable();
+
+			/* assert if radio packet ptr is not set and radio
+			 * started tx.
+			 */
+			LL_ASSERT(!radio_is_ready());
+
+			/* Restore state if last transmitted was empty PDU */
+			lll->empty = is_empty_pdu_tx_retry;
+
+			goto lll_conn_isr_rx_exit;
+#endif /* CONFIG_BT_CENTRAL */
+#if defined(CONFIG_BT_PERIPHERAL)
+		/* Event done for slave */
+		} else {
+			radio_switch_complete_and_disable();
+#endif /* CONFIG_BT_PERIPHERAL */
+		}
+	} else {
+		radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		radio_switch_complete_and_rx(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+		radio_switch_complete_and_rx(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+		radio_isr_set(lll_conn_isr_tx, param);
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+	}
+
+	/* Fill sn and nesn */
+	pdu_data_tx->sn = lll->sn;
+	pdu_data_tx->nesn = lll->nesn;
+
+	/* setup the radio tx packet buffer */
+	lll_conn_tx_pkt_set(lll, pdu_data_tx);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	/* PA enable is overwriting packet end used in ISR profiling, hence
+	 * back it up for later use.
+	 */
+	lll_prof_radio_end_backup();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+	radio_gpio_pa_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US -
+				 radio_rx_chain_delay_get(lll->phy_rx, 1) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US -
+				 radio_rx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* assert if radio packet ptr is not set and radio started tx */
+	LL_ASSERT(!radio_is_ready());
+
+lll_conn_isr_rx_exit:
+	/* Save the AA captured for the first Rx in connection event */
+	if (!radio_tmr_aa_restore()) {
+		radio_tmr_aa_save(radio_tmr_aa_get());
+	}
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	lll_prof_cputime_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+	if (tx_release) {
+		LL_ASSERT(lll->handle != 0xFFFF);
+
+		ull_conn_lll_ack_enqueue(lll->handle, tx_release);
+
+		is_ull_rx = 1U;
+	}
+
+	if (is_rx_enqueue) {
+		ull_pdu_rx_alloc();
+
+		node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+		node_rx->hdr.handle = lll->handle;
+
+		ull_rx_put(node_rx->hdr.link, node_rx);
+		is_ull_rx = 1U;
+	}
+
+	if (is_ull_rx) {
+		ull_rx_sched();
+	}
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	/* Collect RSSI for connection */
+	if (rssi_ready) {
+		uint8_t rssi = radio_rssi_get();
+
+		lll->rssi_latest = rssi;
+
+		if (((lll->rssi_reported - rssi) & 0xFF) >
+		    LLL_CONN_RSSI_THRESHOLD) {
+			if (lll->rssi_sample_count) {
+				lll->rssi_sample_count--;
+			}
+		} else {
+			lll->rssi_sample_count = LLL_CONN_RSSI_SAMPLE_COUNT;
+		}
+	}
+#else /* !CONFIG_BT_CTLR_CONN_RSSI */
+	ARG_UNUSED(rssi_ready);
+#endif /* !CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	lll_prof_send();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+}
+
+void lll_conn_isr_tx(void *param)
+{
+	struct lll_conn *lll = (void *)param;
+	uint32_t hcto;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || \
+	defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_pa_lna_disable();
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN || CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	/* TODO: MOVE ^^ */
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_tx(lll->phy_rx, 0,
+				     lll->phy_tx,
+				     lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	lll_conn_rx_pkt_set(lll);
+
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 +
+		RANGE_DELAY_US + 1;
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
+	hcto += addr_us_get(lll->phy_rx);
+	hcto -= radio_tx_chain_delay_get(lll->phy_tx, lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_CONN_RSSI)
+	if (!trx_cnt && !lll->role) {
+		radio_rssi_measure();
+	}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
+	defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_tmr_end_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(lll->phy_tx,
+							  lll->phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	radio_isr_set(lll_conn_isr_rx, param);
+}
+
+void lll_conn_isr_abort(void *param)
+{
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+
+	isr_cleanup(param);
+}
+
+void lll_conn_rx_pkt_set(struct lll_conn *lll)
+{
+	struct node_rx_pdu *node_rx;
+	uint16_t max_rx_octets;
+	uint8_t phy;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	max_rx_octets = lll->max_rx_octets;
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	phy = lll->phy_rx;
+#else /* !CONFIG_BT_CTLR_PHY */
+	phy = 0U;
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_phy_set(phy, 0);
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	} else if (lll->enc_rx) {
+		radio_pkt_configure(8, (max_rx_octets + 4), (phy << 1) | 0x01);
+
+		radio_pkt_rx_set(radio_ccm_rx_pkt_set(&lll->ccm_rx, phy,
+						      node_rx->pdu));
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+	} else {
+		radio_pkt_configure(8, max_rx_octets, (phy << 1) | 0x01);
+
+		radio_pkt_rx_set(node_rx->pdu);
+	}
+}
+
+void lll_conn_tx_pkt_set(struct lll_conn *lll, struct pdu_data *pdu_data_tx)
+{
+	uint16_t max_tx_octets;
+	uint8_t phy, flags;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	max_tx_octets = lll->max_tx_octets;
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	phy = lll->phy_tx;
+	flags = lll->phy_flags;
+#else /* !CONFIG_BT_CTLR_PHY */
+	phy = 0U;
+	flags = 0U;
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_phy_set(phy, flags);
+
+	if (0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	} else if (lll->enc_tx) {
+		radio_pkt_configure(8, (max_tx_octets + 4U),
+				    (phy << 1) | 0x01);
+
+		radio_pkt_tx_set(radio_ccm_tx_pkt_set(&lll->ccm_tx,
+						      pdu_data_tx));
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+	} else {
+		radio_pkt_configure(8, max_tx_octets, (phy << 1) | 0x01);
+
+		radio_pkt_tx_set(pdu_data_tx);
+	}
+}
+
+void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx)
+{
+	struct node_tx *tx;
+	struct pdu_data *p;
+	memq_link_t *link;
+
+	if (lll->empty
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			|| (lll->enc_tx && !radio_ccm_is_available())
+			/* TODO: If CAUv3 is already used by the RX decrypt,
+			 * there is no time to use it for TX if the link
+			 * needs it, thus stall and send an empty packet w/ MD.
+			 */
+#endif
+			) {
+		*pdu_data_tx = empty_tx_enqueue(lll);
+		return;
+	}
+
+	link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail, (void **)&tx);
+	if (!link) {
+		p = empty_tx_enqueue(lll);
+	} else {
+		uint16_t max_tx_octets;
+
+		p = (void *)(tx->pdu + lll->packet_tx_head_offset);
+
+		if (!lll->packet_tx_head_len) {
+			lll->packet_tx_head_len = p->len;
+		}
+
+		if (lll->packet_tx_head_offset) {
+			p->ll_id = PDU_DATA_LLID_DATA_CONTINUE;
+		}
+
+		p->len = lll->packet_tx_head_len - lll->packet_tx_head_offset;
+		p->md = 0;
+
+		max_tx_octets = ull_conn_lll_max_tx_octets_get(lll);
+
+		if (p->len > max_tx_octets) {
+			p->len = max_tx_octets;
+			p->md = 1;
+		}
+
+		if (link->next != lll->memq_tx.tail) {
+			p->md = 1;
+		}
+	}
+
+	p->rfu = 0U;
+
+#if !defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
+#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
+	p->resv = 0U;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */
+#endif /* !CONFIG_SOC_OPENISA_RV32M1_RISCV32 */
+
+	*pdu_data_tx = p;
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static void isr_done(void *param)
+{
+	struct event_done_extra *e;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN) || \
+	defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_pa_lna_disable();
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN || CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	/* TODO: MOVE ^^ */
+
+	e = ull_event_done_extra_get();
+	LL_ASSERT(e);
+
+	e->type = EVENT_DONE_EXTRA_TYPE_CONN;
+	e->trx_cnt = trx_cnt;
+	e->crc_valid = crc_valid;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	e->mic_state = mic_state;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (trx_cnt) {
+		struct lll_conn *lll = param;
+
+		if (lll->role) {
+			uint32_t preamble_to_addr_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+			preamble_to_addr_us =
+				addr_us_get(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+			preamble_to_addr_us =
+				addr_us_get(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+			e->drift.start_to_address_actual_us =
+				radio_tmr_aa_restore() - radio_tmr_ready_get();
+			e->drift.window_widening_event_us =
+				lll->slave.window_widening_event_us;
+			e->drift.preamble_to_addr_us = preamble_to_addr_us;
+
+			/* Reset window widening, as anchor point sync-ed */
+			lll->slave.window_widening_event_us = 0;
+			lll->slave.window_size_event_us = 0;
+		}
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	isr_cleanup(param);
+}
+
+static void isr_cleanup(void *param)
+{
+	int err;
+
+	radio_isr_set(isr_race, param);
+	radio_tmr_stop();
+
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(NULL);
+}
+
+static void isr_race(void *param)
+{
+	/* NOTE: lll_disable could have a race with ... */
+	radio_status_reset();
+}
+
+static inline bool ctrl_pdu_len_check(uint8_t len)
+{
+	return len <= (offsetof(struct pdu_data, llctrl) +
+		       sizeof(struct pdu_data_llctrl));
+
+}
+
+static int isr_rx_pdu(struct lll_conn *lll, struct pdu_data *pdu_data_rx,
+		      struct node_tx **tx_release, uint8_t *is_rx_enqueue)
+{
+	/* Ack for tx-ed data */
+	if (pdu_data_rx->nesn != lll->sn) {
+		struct node_tx *tx;
+		memq_link_t *link;
+
+		/* Increment serial number */
+		lll->sn++;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		/* First ack (and redundantly any other ack) enable use of
+		 * slave latency.
+		 */
+		if (lll->role) {
+			lll->slave.latency_enabled = 1;
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+		if (!lll->empty) {
+			link = memq_peek(lll->memq_tx.head, lll->memq_tx.tail,
+					 (void **)&tx);
+		} else {
+			lll->empty = 0;
+			link = NULL;
+		}
+
+		if (link) {
+			struct pdu_data *pdu_data_tx;
+			uint8_t pdu_data_tx_len;
+			uint8_t offset;
+
+			pdu_data_tx = (void *)(tx->pdu +
+					       lll->packet_tx_head_offset);
+
+			pdu_data_tx_len = pdu_data_tx->len;
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			if (pdu_data_tx_len != 0U) {
+				/* if encrypted increment tx counter */
+				if (lll->enc_tx) {
+					lll->ccm_tx.counter++;
+				}
+			}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+			offset = lll->packet_tx_head_offset + pdu_data_tx_len;
+			if (offset < lll->packet_tx_head_len) {
+				lll->packet_tx_head_offset = offset;
+			} else if (offset == lll->packet_tx_head_len) {
+				lll->packet_tx_head_len = 0;
+				lll->packet_tx_head_offset = 0;
+
+				memq_dequeue(lll->memq_tx.tail,
+					     &lll->memq_tx.head, NULL);
+
+				/* TX node UPSTREAM, i.e. Tx node ack path */
+				link->next = tx->next; /* Indicates ctrl or data
+							* pool.
+							*/
+				tx->next = link;
+
+				*tx_release = tx;
+			}
+		}
+	}
+
+	/* process received data */
+	if ((pdu_data_rx->sn == lll->nesn) &&
+	    /* check so that we will NEVER use the rx buffer reserved for empty
+	     * packet and internal control enqueue
+	     */
+	    (ull_pdu_rx_alloc_peek(3) != 0)) {
+		/* Increment next expected serial number */
+		lll->nesn++;
+
+		if (pdu_data_rx->len != 0) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			/* If required, wait for CCM to finish
+			 */
+			if (lll->enc_rx) {
+				uint32_t done;
+
+				done = radio_ccm_is_done();
+				LL_ASSERT(done);
+
+				bool mic_failure = !radio_ccm_mic_is_valid();
+
+				if (mic_failure &&
+				    lll->ccm_rx.counter == 0 &&
+				    (pdu_data_rx->ll_id ==
+				     PDU_DATA_LLID_CTRL)) {
+					/* Received an LL control packet in the
+					 * middle of the LL encryption procedure
+					 * with MIC failure.
+					 * This could be an unencrypted packet
+					 */
+					struct pdu_data *scratch_pkt =
+						radio_pkt_scratch_get();
+
+					if (ctrl_pdu_len_check(
+						scratch_pkt->len)) {
+						memcpy(pdu_data_rx,
+						       scratch_pkt,
+						       scratch_pkt->len +
+						       offsetof(struct pdu_data,
+							llctrl));
+						mic_failure = false;
+						lll->ccm_rx.counter--;
+					}
+				}
+
+				if (mic_failure) {
+					/* Record MIC invalid */
+					mic_state = LLL_CONN_MIC_FAIL;
+
+					return -EINVAL;
+				}
+
+				/* Increment counter */
+				lll->ccm_rx.counter++;
+
+				/* Record MIC valid */
+				mic_state = LLL_CONN_MIC_PASS;
+			}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+			/* Enqueue non-empty PDU */
+			*is_rx_enqueue = 1U;
+		}
+	}
+
+	return 0;
+}
+
+static struct pdu_data *empty_tx_enqueue(struct lll_conn *lll)
+{
+	struct pdu_data *p;
+
+	lll->empty = 1;
+
+	p = (void *)radio_pkt_empty_get();
+	p->ll_id = PDU_DATA_LLID_DATA_CONTINUE;
+	p->len = 0;
+	if (memq_peek(lll->memq_tx.head, lll->memq_tx.tail, NULL)) {
+		p->md = 1;
+	} else {
+		p->md = 0;
+	}
+
+	return p;
+}
+
+void lll_conn_flush(uint16_t handle, struct lll_conn *lll)
+{
+	/* Nothing to be flushed */
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn_meta.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn_meta.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_conn_meta.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2019 Demant
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#if defined(CONFIG_BT_CTLR_CONN_META)
+/*
+ * struct lll_conn_meta { };
+ */
+#error Please define struct lll_conn_meta when enabling BT_CTLR_CONN_META
+#endif /* CONFIG_BT_CTLR_CONN_META */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_internal.h	(working copy)
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
+		lll_prepare_cb_t prepare_cb, int prio,
+		struct lll_prepare_param *prepare_param);
+int lll_prepare_done(void *param);
+int lll_done(void *param);
+bool lll_is_done(void *param);
+int lll_is_abort_cb(void *next, int prio, void *curr,
+			 lll_prepare_cb_t *resume_cb, int *resume_prio);
+void lll_abort_cb(struct lll_prepare_param *prepare_param, void *param);
+
+static inline int lll_is_stop(void *lll)
+{
+	struct lll_hdr *hdr = lll;
+
+	return !!hdr->is_stop;
+}
+
+int lll_clk_on(void);
+int lll_clk_on_wait(void);
+int lll_clk_off(void);
+uint32_t lll_evt_offset_get(struct evt_hdr *evt);
+uint32_t lll_preempt_calc(struct evt_hdr *evt, uint8_t ticker_id,
+		uint32_t ticks_at_event);
+void lll_chan_set(uint32_t chan);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_master_init(void);
+int lll_master_reset(void);
+void lll_master_prepare(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_master.c	(working copy)
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_conn.h"
+#include "lll_master.h"
+#include "lll_chan.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_master
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *prepare_param);
+
+int lll_master_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_master_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_master_prepare(void *param)
+{
+	struct lll_prepare_param *p = param;
+	struct lll_conn *lll = p->param;
+	uint16_t elapsed;
+	int err;
+
+	err = lll_clk_on();
+	LL_ASSERT(!err || err == -EINPROGRESS);
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	/* Save the (latency + 1) for use in event */
+	lll->latency_prepare += elapsed;
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *prepare_param)
+{
+	struct lll_conn *lll = prepare_param->param;
+	uint32_t ticks_at_event, ticks_at_start;
+	struct pdu_data *pdu_data_tx;
+	struct evt_hdr *evt;
+	uint16_t event_counter;
+	uint32_t remainder_us;
+	uint8_t data_chan_use;
+	uint32_t remainder;
+
+	DEBUG_RADIO_START_M(1);
+
+	/* Reset connection event global variables */
+	lll_conn_prepare_reset();
+
+	/* Deduce the latency */
+	lll->latency_event = lll->latency_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->latency_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->latency_prepare;
+
+	/* Reset accumulated latencies */
+	lll->latency_prepare = 0;
+
+	if (lll->data_chan_sel) {
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+#else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+		data_chan_use = 0;
+		LL_ASSERT(0);
+#endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+	} else {
+		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
+					       lll->data_chan_hop,
+					       lll->latency_event,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+	}
+
+	/* Prepare the Tx PDU */
+	lll_conn_pdu_tx_prep(lll, &pdu_data_tx);
+	pdu_data_tx->sn = lll->sn;
+	pdu_data_tx->nesn = lll->nesn;
+
+	/* Start setting up of Radio h/w */
+	radio_reset();
+	/* TODO: other Tx Power settings */
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+	lll_chan_set(data_chan_use);
+
+	/* setup the radio tx packet buffer */
+	lll_conn_tx_pkt_set(lll, pdu_data_tx);
+
+	radio_isr_set(lll_conn_isr_tx, lll);
+
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_rx(lll->phy_rx);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_rx(0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	ticks_at_event = prepare_param->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = prepare_param->remainder;
+	remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
+
+	/* capture end of Tx-ed PDU, used to calculate HCTO. */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_tx_ready_delay_get(lll->phy_tx,
+							  lll->phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_tx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_CONN_BASE + lll->handle),
+			     ticks_at_event)) {
+		radio_isr_set(lll_conn_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_M(1);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_meta.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_meta.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_meta.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_CTLR_RX_PDU_META)
+/*
+ * typedef struct { } lll_rx_pdu_meta_t;
+ */
+#error Please define typedef struct lll_rx_pdu_meta_t when enabling \
+	CONFIG_BT_CTLR_RX_PDU_META
+#endif /* CONFIG_BT_CTLR_RX_PDU_META */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof.c	(working copy)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+
+static uint8_t latency_min = (uint8_t) -1;
+static uint8_t latency_max;
+static uint8_t latency_prev;
+static uint8_t cputime_min = (uint8_t) -1;
+static uint8_t cputime_max;
+static uint8_t cputime_prev;
+static uint32_t timestamp_latency;
+
+void lll_prof_latency_capture(void)
+{
+	/* sample the packet timer, use it to calculate ISR latency
+	 * and generate the profiling event at the end of the ISR.
+	 */
+	radio_tmr_sample();
+}
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+static uint32_t timestamp_radio_end;
+
+uint32_t lll_prof_radio_end_backup(void)
+{
+	/* PA enable is overwriting packet end used in ISR profiling, hence
+	 * back it up for later use.
+	 */
+	timestamp_radio_end = radio_tmr_end_get();
+
+	return timestamp_radio_end;
+}
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+void lll_prof_cputime_capture(void)
+{
+	/* get the ISR latency sample */
+	timestamp_latency = radio_tmr_sample_get();
+
+	/* sample the packet timer again, use it to calculate ISR execution time
+	 * and use it in profiling event
+	 */
+	radio_tmr_sample();
+}
+
+void lll_prof_send(void)
+{
+	uint8_t latency, cputime, prev;
+	uint8_t chg = 0U;
+
+	/* calculate the elapsed time in us since on-air radio packet end
+	 * to ISR entry
+	 */
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	latency = timestamp_latency - timestamp_radio_end;
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	latency = timestamp_latency - radio_tmr_end_get();
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* check changes in min, avg and max of latency */
+	if (latency > latency_max) {
+		latency_max = latency;
+		chg = 1U;
+	}
+	if (latency < latency_min) {
+		latency_min = latency;
+		chg = 1U;
+	}
+
+	/* check for +/- 1us change */
+	prev = ((uint16_t)latency_prev + latency) >> 1;
+	if (prev != latency_prev) {
+		latency_prev = latency;
+		chg = 1U;
+	}
+
+	/* calculate the elapsed time in us since ISR entry */
+	cputime = radio_tmr_sample_get() - timestamp_latency;
+
+	/* check changes in min, avg and max */
+	if (cputime > cputime_max) {
+		cputime_max = cputime;
+		chg = 1U;
+	}
+
+	if (cputime < cputime_min) {
+		cputime_min = cputime;
+		chg = 1U;
+	}
+
+	/* check for +/- 1us change */
+	prev = ((uint16_t)cputime_prev + cputime) >> 1;
+	if (prev != cputime_prev) {
+		cputime_prev = cputime;
+		chg = 1U;
+	}
+
+	/* generate event if any change */
+	if (chg) {
+		struct node_rx_pdu *rx;
+
+		/* NOTE: enqueue only if rx buffer available, else ignore */
+		rx = ull_pdu_rx_alloc_peek(3);
+		if (rx) {
+			struct pdu_data *pdu;
+			struct profile *p;
+
+			ull_pdu_rx_alloc();
+
+			rx->hdr.type = NODE_RX_TYPE_PROFILE;
+			rx->hdr.handle = 0xFFFF;
+
+			pdu = (void *)rx->pdu;
+			p = &pdu->profile;
+			p->lcur = latency;
+			p->lmin = latency_min;
+			p->lmax = latency_max;
+			p->cur = cputime;
+			p->min = cputime_min;
+			p->max = cputime_max;
+
+			ull_rx_put(rx->hdr.link, rx);
+			ull_rx_sched();
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_prof_internal.h	(working copy)
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void lll_prof_latency_capture(void);
+void lll_prof_radio_end_backup(void);
+void lll_prof_cputime_capture(void);
+void lll_prof_send(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.h	(working copy)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct lll_scan {
+	struct lll_hdr hdr;
+
+#if defined(CONFIG_BT_CENTRAL)
+	/* NOTE: conn context has to be after lll_hdr */
+	struct lll_conn *conn;
+	uint32_t conn_ticks_slot;
+	uint32_t conn_win_offset_us;
+	uint16_t conn_timeout;
+#endif /* CONFIG_BT_CENTRAL */
+
+	uint8_t  state:1;
+	uint8_t  chan:2;
+	uint8_t  filter_policy:2;
+	uint8_t  adv_addr_type:1;
+	uint8_t  init_addr_type:1;
+	uint8_t  type:1;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint8_t  phy:3;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  rpa_gen:1;
+	/* initiator only */
+	uint8_t rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	uint8_t  init_addr[BDADDR_SIZE];
+	uint8_t  adv_addr[BDADDR_SIZE];
+
+	uint16_t interval;
+	uint32_t ticks_window;
+};
+
+struct lll_scan_aux {
+	struct lll_hdr hdr;
+};
+
+int lll_scan_init(void);
+int lll_scan_reset(void);
+
+void lll_scan_prepare(void *param);
+
+extern uint8_t ull_scan_lll_handle_get(struct lll_scan *lll);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_scan.c	(working copy)
@@ -0,0 +1,1141 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <toolchain.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_chan.h"
+#include "lll_filter.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+#include "lll_prof_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_scan
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *prepare_param);
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio);
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			   void *param);
+static void ticker_op_start_cb(uint32_t status, void *param);
+static void isr_rx(void *param);
+static void isr_tx(void *param);
+static void isr_done(void *param);
+static void isr_window(void *param);
+static void isr_abort(void *param);
+static void isr_cleanup(void *param);
+static void isr_race(void *param);
+
+static inline bool isr_rx_scan_check(struct lll_scan *lll, uint8_t irkmatch_ok,
+				     uint8_t devmatch_ok, uint8_t rl_idx);
+static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
+			       uint8_t devmatch_id, uint8_t irkmatch_ok,
+			       uint8_t irkmatch_id, uint8_t rl_idx, uint8_t rssi_ready);
+static inline bool isr_scan_init_check(struct lll_scan *lll,
+				       struct pdu_adv *pdu, uint8_t rl_idx);
+static inline bool isr_scan_init_adva_check(struct lll_scan *lll,
+					    struct pdu_adv *pdu, uint8_t rl_idx);
+static inline bool isr_scan_tgta_check(struct lll_scan *lll, bool init,
+				       struct pdu_adv *pdu, uint8_t rl_idx,
+				       bool *dir_report);
+static inline bool isr_scan_tgta_rpa_check(struct lll_scan *lll,
+					   struct pdu_adv *pdu,
+					   bool *dir_report);
+static inline bool isr_scan_rsp_adva_matches(struct pdu_adv *srsp);
+static uint32_t isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
+				uint8_t rl_idx, bool dir_report);
+
+
+int lll_scan_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_scan_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_scan_prepare(void *param)
+{
+	struct lll_prepare_param *p = param;
+	int err;
+
+	err = lll_clk_on();
+	LL_ASSERT(!err || err == -EINPROGRESS);
+
+	err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *prepare_param)
+{
+	struct lll_scan *lll = prepare_param->param;
+	uint32_t aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
+	uint32_t ticks_at_event, ticks_at_start;
+	struct node_rx_pdu *node_rx;
+	struct evt_hdr *evt;
+	uint32_t remainder_us;
+	uint32_t remainder;
+
+	DEBUG_RADIO_START_O(1);
+
+	/* Check if stopped (on connection establishment race between LLL and
+	 * ULL.
+	 */
+	if (lll_is_stop(lll)) {
+		int err;
+
+		err = lll_clk_off();
+		LL_ASSERT(!err || err == -EBUSY);
+
+		lll_done(NULL);
+
+		DEBUG_RADIO_START_O(0);
+		return 0;
+	}
+
+	radio_reset();
+	/* TODO: other Tx Power settings */
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	/* TODO: if coded we use S8? */
+	radio_phy_set(lll->phy, 1);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy << 1));
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	radio_phy_set(0, 0);
+	radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, 0);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+	radio_pkt_rx_set(node_rx->pdu);
+
+	radio_aa_set((uint8_t *)&aa);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    0x555555);
+
+	lll_chan_set(37 + lll->chan);
+
+	radio_isr_set(isr_rx, lll);
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		struct lll_filter *filter =
+			ull_filter_lll_get(!!(lll->filter_policy & 0x1));
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_filter_configure(filter->enable_bitmask,
+				       filter->addr_type_bitmask,
+				       (uint8_t *)filter->bdaddr);
+
+		radio_ar_configure(count, irks);
+	} else
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_FILTER) && lll->filter_policy) {
+			/* Setup Radio Filter */
+
+			struct lll_filter *wl = ull_filter_lll_get(true);
+
+			radio_filter_configure(wl->enable_bitmask,
+					       wl->addr_type_bitmask,
+					       (uint8_t *)wl->bdaddr);
+		}
+
+	ticks_at_event = prepare_param->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = prepare_param->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event.
+	 */
+	radio_tmr_end_capture();
+
+	/* scanner always measures RSSI */
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_SCAN_BASE +
+				   ull_scan_lll_handle_get(lll)),
+			     ticks_at_event)) {
+		radio_isr_set(isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		if (lll->ticks_window) {
+			/* start window close timeout */
+			ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+					   TICKER_USER_ID_LLL,
+					   TICKER_ID_SCAN_STOP,
+					   ticks_at_event, lll->ticks_window,
+					   TICKER_NULL_PERIOD,
+					   TICKER_NULL_REMAINDER,
+					   TICKER_NULL_LAZY, TICKER_NULL_SLOT,
+					   ticker_stop_cb, lll,
+					   ticker_op_start_cb,
+					   (void *)__LINE__);
+			LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+				  (ret == TICKER_STATUS_BUSY));
+		}
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_O(1);
+
+	return 0;
+}
+
+static int resume_prepare_cb(struct lll_prepare_param *p)
+{
+	struct evt_hdr *evt = HDR_LLL2EVT(p->param);
+
+	p->ticks_at_expire = ticker_ticks_now_get() - lll_evt_offset_get(evt);
+	p->remainder = 0;
+	p->lazy = 0;
+
+	return prepare_cb(p);
+}
+
+static int is_abort_cb(void *next, int prio, void *curr,
+		       lll_prepare_cb_t *resume_cb, int *resume_prio)
+{
+	struct lll_scan *lll = curr;
+
+	/* TODO: check prio */
+	if (next != curr) {
+		int err;
+
+		/* wrap back after the pre-empter */
+		*resume_cb = resume_prepare_cb;
+		*resume_prio = 0; /* TODO: */
+
+		/* Retain HF clk */
+		err = lll_clk_on();
+		LL_ASSERT(!err || err == -EINPROGRESS);
+
+		return -EAGAIN;
+	}
+
+	radio_isr_set(isr_window, lll);
+	radio_disable();
+
+	if (++lll->chan == 3U) {
+		lll->chan = 0U;
+	}
+
+	lll_chan_set(37 + lll->chan);
+
+	return 0;
+}
+
+static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
+{
+	int err;
+
+	/* NOTE: This is not a prepare being cancelled */
+	if (!prepare_param) {
+		/* Perform event abort here.
+		 * After event has been cleanly aborted, clean up resources
+		 * and dispatch event done.
+		 */
+		radio_isr_set(isr_abort, param);
+		radio_disable();
+		return;
+	}
+
+	/* NOTE: Else clean the top half preparations of the aborted event
+	 * currently in preparation pipeline.
+	 */
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(param);
+}
+
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			   void *param)
+{
+	radio_isr_set(isr_cleanup, param);
+	radio_disable();
+}
+
+static void ticker_op_start_cb(uint32_t status, void *param)
+{
+	ARG_UNUSED(param);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void isr_rx(void *param)
+{
+	struct lll_scan *lll = (void *)param;
+	uint8_t trx_done;
+	uint8_t crc_ok;
+	uint8_t devmatch_ok;
+	uint8_t devmatch_id;
+	uint8_t irkmatch_ok;
+	uint8_t irkmatch_id;
+	uint8_t rssi_ready;
+	uint8_t rl_idx;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+		lll_prof_latency_capture();
+	}
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+		devmatch_ok = radio_filter_has_match();
+		devmatch_id = radio_filter_match_get();
+		irkmatch_ok = radio_ar_has_match();
+		irkmatch_id = radio_ar_match_get();
+		rssi_ready = radio_rssi_is_ready();
+	} else {
+		crc_ok = devmatch_ok = irkmatch_ok = rssi_ready = 0U;
+		devmatch_id = irkmatch_id = 0xFF;
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+
+	if (!trx_done) {
+		goto isr_rx_do_close;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	rl_idx = devmatch_ok ?
+		 ull_filter_lll_rl_idx(!!(lll->filter_policy & 0x01),
+				       devmatch_id) :
+		 irkmatch_ok ? ull_filter_lll_rl_irk_idx(irkmatch_id) :
+			       FILTER_IDX_NONE;
+#else
+	rl_idx = FILTER_IDX_NONE;
+#endif
+	if (crc_ok && isr_rx_scan_check(lll, irkmatch_ok, devmatch_ok,
+					rl_idx)) {
+		uint32_t err;
+
+		err = isr_rx_pdu(lll, devmatch_ok, devmatch_id, irkmatch_ok,
+				 irkmatch_id, rl_idx, rssi_ready);
+		if (!err) {
+			if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+				lll_prof_send();
+			}
+
+			return;
+		}
+	}
+
+isr_rx_do_close:
+	radio_isr_set(isr_done, lll);
+	radio_disable();
+}
+
+static void isr_tx(void *param)
+{
+	struct node_rx_pdu *node_rx;
+	uint32_t hcto;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+	/* TODO: MOVE ^^ */
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+	radio_pkt_rx_set(node_rx->pdu);
+
+	/* assert if radio packet ptr is not set and radio started rx */
+	LL_ASSERT(!radio_is_ready());
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	/* +/- 2us active clock jitter, +1 us hcto compensation */
+	hcto = radio_tmr_tifs_base_get() + EVENT_IFS_US + 4 + 1;
+	hcto += radio_rx_chain_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto -= radio_tx_chain_delay_get(0, 0);
+
+	radio_tmr_hcto_configure(hcto);
+
+	radio_rssi_measure();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() + EVENT_IFS_US - 4 -
+				 radio_tx_chain_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	radio_isr_set(isr_rx, param);
+}
+
+static void isr_common_done(void *param)
+{
+	struct node_rx_pdu *node_rx;
+
+	/* TODO: MOVE to a common interface, isr_lll_radio_status? */
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+	/* TODO: MOVE ^^ */
+
+	/* setup tIFS switching */
+	radio_tmr_tifs_set(EVENT_IFS_US);
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+	radio_pkt_rx_set(node_rx->pdu);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_enabled()) {
+		uint8_t count, *irks = ull_filter_lll_irks_get(&count);
+
+		radio_ar_configure(count, irks);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	radio_rssi_measure();
+
+	radio_isr_set(isr_rx, param);
+}
+
+static void isr_done(void *param)
+{
+	uint32_t start_us;
+
+	isr_common_done(param);
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	start_us = radio_tmr_start_now(0);
+
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(start_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(start_us);
+
+	radio_rx_enable();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event.
+	 */
+	radio_tmr_end_capture();
+}
+
+static void isr_window(void *param)
+{
+	uint32_t ticks_at_start, remainder_us;
+
+	isr_common_done(param);
+
+	ticks_at_start = ticker_ticks_now_get() +
+			 HAL_TICKER_CNTR_CMP_OFFSET_MIN;
+	remainder_us = radio_tmr_start_tick(0, ticks_at_start);
+
+	/* capture end of Rx-ed PDU, for initiator to calculate first
+	 * master event.
+	 */
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+	ARG_UNUSED(remainder_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+}
+
+static void isr_abort(void *param)
+{
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+	radio_filter_status_reset();
+	radio_ar_status_reset();
+	radio_rssi_status_reset();
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_GPIO_PA_PIN) ||
+	    IS_ENABLED(CONFIG_BT_CTLR_GPIO_LNA_PIN)) {
+		radio_gpio_pa_lna_disable();
+	}
+
+	/* Scanner stop can expire while here in this ISR.
+	 * Deferred attempt to stop can fail as it would have
+	 * expired, hence ignore failure.
+	 */
+	ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_LLL,
+		    TICKER_ID_SCAN_STOP, NULL, NULL);
+
+	/* Under race conditions, radio could get started while entering ISR */
+	radio_disable();
+
+	isr_cleanup(param);
+}
+
+static void isr_cleanup(void *param)
+{
+	struct lll_scan *lll = param;
+	struct node_rx_hdr *node_rx;
+	int err;
+
+	if (lll_is_done(param)) {
+		return;
+	}
+
+	radio_filter_disable();
+
+	if (++lll->chan == 3U) {
+		lll->chan = 0U;
+	}
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (_radio.advertiser.is_enabled && _radio.advertiser.is_mesh &&
+	    !_radio.advertiser.retry) {
+		mayfly_mesh_stop(NULL);
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (node_rx) {
+		ull_pdu_rx_alloc();
+
+		/* TODO: add other info by defining a payload struct */
+		node_rx->type = NODE_RX_TYPE_SCAN_INDICATION;
+
+		ull_rx_put(node_rx->link, node_rx);
+		ull_rx_sched();
+	}
+#else /* !CONFIG_BT_CTLR_SCAN_INDICATION */
+	ARG_UNUSED(node_rx);
+#endif /* !CONFIG_BT_CTLR_SCAN_INDICATION */
+
+	radio_isr_set(isr_race, param);
+	radio_tmr_stop();
+
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	lll_done(NULL);
+}
+
+static void isr_race(void *param)
+{
+	/* NOTE: lll_disable could have a race with ... */
+	radio_status_reset();
+}
+
+static inline bool isr_rx_scan_check(struct lll_scan *lll, uint8_t irkmatch_ok,
+				     uint8_t devmatch_ok, uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return (((lll->filter_policy & 0x01) == 0) &&
+		 (!devmatch_ok || ull_filter_lll_rl_idx_allowed(irkmatch_ok,
+								rl_idx))) ||
+		(((lll->filter_policy & 0x01) != 0) &&
+		 (devmatch_ok || ull_filter_lll_irk_whitelisted(rl_idx)));
+#else
+	return ((lll->filter_policy & 0x01) == 0U) ||
+		devmatch_ok;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
+			       uint8_t devmatch_id, uint8_t irkmatch_ok,
+			       uint8_t irkmatch_id, uint8_t rl_idx, uint8_t rssi_ready)
+{
+	struct node_rx_pdu *node_rx;
+	struct pdu_adv *pdu_adv_rx;
+	bool dir_report = false;
+
+	node_rx = ull_pdu_rx_alloc_peek(1);
+	LL_ASSERT(node_rx);
+
+	pdu_adv_rx = (void *)node_rx->pdu;
+
+	if (0) {
+#if defined(CONFIG_BT_CENTRAL)
+	/* Initiator */
+	} else if ((lll->conn) &&
+		   isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
+		struct lll_conn *lll_conn;
+		struct node_rx_ftr *ftr;
+		struct node_rx_pdu *rx;
+		struct pdu_adv *pdu_tx;
+		uint32_t conn_interval_us;
+		uint32_t conn_offset_us;
+		uint32_t conn_space_us;
+		struct evt_hdr *evt;
+		uint32_t pdu_end_us;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		bt_addr_t *lrpa;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		int ret;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			rx = ull_pdu_rx_alloc_peek(4);
+		} else {
+			rx = ull_pdu_rx_alloc_peek(3);
+		}
+
+		if (!rx) {
+			return -ENOBUFS;
+		}
+
+		pdu_end_us = radio_tmr_end_get();
+		if (!lll->ticks_window) {
+			uint32_t scan_interval_us;
+
+			/* FIXME: is this correct for continuous scanning? */
+			scan_interval_us = lll->interval * 625U;
+			pdu_end_us %= scan_interval_us;
+		}
+		evt = HDR_LLL2EVT(lll);
+		if (pdu_end_us > (HAL_TICKER_TICKS_TO_US(evt->ticks_slot) -
+				  EVENT_IFS_US - 352 - EVENT_OVERHEAD_START_US -
+				  EVENT_TICKER_RES_MARGIN_US)) {
+			return -ETIME;
+		}
+
+		radio_switch_complete_and_disable();
+
+		/* Acquire the connection context */
+		lll_conn = lll->conn;
+
+		/* Tx the connect request packet */
+		pdu_tx = (void *)radio_pkt_scratch_get();
+		pdu_tx->type = PDU_ADV_TYPE_CONNECT_IND;
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			pdu_tx->chan_sel = 1;
+		} else {
+			pdu_tx->chan_sel = 0;
+		}
+
+		pdu_tx->rx_addr = pdu_adv_rx->tx_addr;
+		pdu_tx->len = sizeof(struct pdu_adv_connect_ind);
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		lrpa = ull_filter_lll_lrpa_get(rl_idx);
+		if (lll->rpa_gen && lrpa) {
+			pdu_tx->tx_addr = 1;
+			memcpy(&pdu_tx->connect_ind.init_addr[0], lrpa->val,
+			       BDADDR_SIZE);
+		} else {
+#else
+		if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+			pdu_tx->tx_addr = lll->init_addr_type;
+			memcpy(&pdu_tx->connect_ind.init_addr[0],
+			       &lll->init_addr[0], BDADDR_SIZE);
+		}
+		memcpy(&pdu_tx->connect_ind.adv_addr[0],
+		       &pdu_adv_rx->adv_ind.addr[0], BDADDR_SIZE);
+		memcpy(&pdu_tx->connect_ind.access_addr[0],
+		       &lll_conn->access_addr[0], 4);
+		memcpy(&pdu_tx->connect_ind.crc_init[0],
+		       &lll_conn->crc_init[0], 3);
+		pdu_tx->connect_ind.win_size = 1;
+
+		conn_interval_us = (uint32_t)lll_conn->interval * 1250U;
+		conn_offset_us = radio_tmr_end_get() + 502 + 1250;
+
+		if (!IS_ENABLED(CONFIG_BT_CTLR_SCHED_ADVANCED) ||
+		    lll->conn_win_offset_us == 0U) {
+			conn_space_us = conn_offset_us;
+			pdu_tx->connect_ind.win_offset = sys_cpu_to_le16(0);
+		} else {
+			conn_space_us = lll->conn_win_offset_us;
+			while ((conn_space_us & ((uint32_t)1 << 31)) ||
+			       (conn_space_us < conn_offset_us)) {
+				conn_space_us += conn_interval_us;
+			}
+			pdu_tx->connect_ind.win_offset =
+				sys_cpu_to_le16((conn_space_us -
+						 conn_offset_us) / 1250U);
+			pdu_tx->connect_ind.win_size++;
+		}
+
+		pdu_tx->connect_ind.interval =
+			sys_cpu_to_le16(lll_conn->interval);
+		pdu_tx->connect_ind.latency =
+			sys_cpu_to_le16(lll_conn->latency);
+		pdu_tx->connect_ind.timeout =
+			sys_cpu_to_le16(lll->conn_timeout);
+		memcpy(&pdu_tx->connect_ind.chan_map[0],
+		       &lll_conn->data_chan_map[0],
+		       sizeof(pdu_tx->connect_ind.chan_map));
+		pdu_tx->connect_ind.hop = lll_conn->data_chan_hop;
+		pdu_tx->connect_ind.sca = lll_clock_sca_local_get();
+
+		radio_pkt_tx_set(pdu_tx);
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+		}
+
+		radio_isr_set(isr_cleanup, lll);
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end
+			 * used in ISR profiling, hence back it up
+			 * for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		if (rssi_ready) {
+			lll_conn->rssi_latest =  radio_rssi_get();
+		}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+		/* block CPU so that there is no CRC error on pdu tx,
+		 * this is only needed if we want the CPU to sleep.
+		 * while(!radio_has_disabled())
+		 * {cpu_sleep();}
+		 * radio_status_reset();
+		 */
+
+		/* Stop further LLL radio events */
+		ret = lll_stop(lll);
+		LL_ASSERT(!ret);
+
+		rx = ull_pdu_rx_alloc();
+
+		rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+		rx->hdr.handle = 0xffff;
+
+		uint8_t pdu_adv_rx_chan_sel = pdu_adv_rx->chan_sel;
+
+		memcpy(rx->pdu, pdu_tx, (offsetof(struct pdu_adv, connect_ind) +
+					  sizeof(struct pdu_adv_connect_ind)));
+
+		/*
+		 * Overwrite the sent chan sel with received chan sel, when
+		 * giving this PDU to the higher layer.
+		 */
+		pdu_adv_rx = (void *)rx->pdu;
+		pdu_adv_rx->chan_sel = pdu_adv_rx_chan_sel;
+
+		ftr = &(rx->hdr.rx_ftr);
+
+		ftr->param = lll;
+		ftr->ticks_anchor = radio_tmr_start_get();
+		ftr->radio_end_us = conn_space_us -
+				    radio_tx_chain_delay_get(0, 0);
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		ftr->rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+			ftr->extra = ull_pdu_rx_alloc();
+		}
+
+		ull_rx_put(rx->hdr.link, rx);
+		ull_rx_sched();
+
+		return 0;
+#endif /* CONFIG_BT_CENTRAL */
+
+	/* Active scanner */
+	} else if (((pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND)) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_adv_ind)) &&
+		   lll->type &&
+#if defined(CONFIG_BT_CENTRAL)
+		   !lll->conn) {
+#else /* !CONFIG_BT_CENTRAL */
+		   1) {
+#endif /* !CONFIG_BT_CENTRAL */
+		struct pdu_adv *pdu_tx;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		bt_addr_t *lrpa;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		uint32_t err;
+
+		/* setup tIFS switching */
+		radio_tmr_tifs_set(EVENT_IFS_US);
+		radio_switch_complete_and_rx(0);
+
+		/* save the adv packet */
+		err = isr_rx_scan_report(lll, rssi_ready,
+					 irkmatch_ok ? rl_idx : FILTER_IDX_NONE,
+					 false);
+		if (err) {
+			return err;
+		}
+
+		/* prepare the scan request packet */
+		pdu_tx = (void *)radio_pkt_scratch_get();
+		pdu_tx->type = PDU_ADV_TYPE_SCAN_REQ;
+		pdu_tx->rx_addr = pdu_adv_rx->tx_addr;
+		pdu_tx->len = sizeof(struct pdu_adv_scan_req);
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		lrpa = ull_filter_lll_lrpa_get(rl_idx);
+		if (lll->rpa_gen && lrpa) {
+			pdu_tx->tx_addr = 1;
+			memcpy(&pdu_tx->scan_req.scan_addr[0], lrpa->val,
+			       BDADDR_SIZE);
+		} else {
+#else
+		if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+			pdu_tx->tx_addr = lll->init_addr_type;
+			memcpy(&pdu_tx->scan_req.scan_addr[0],
+			       &lll->init_addr[0], BDADDR_SIZE);
+		}
+		memcpy(&pdu_tx->scan_req.adv_addr[0],
+		       &pdu_adv_rx->adv_ind.addr[0], BDADDR_SIZE);
+
+		radio_pkt_tx_set(pdu_tx);
+
+		/* assert if radio packet ptr is not set and radio started tx */
+		LL_ASSERT(!radio_is_ready());
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			lll_prof_cputime_capture();
+
+		}
+
+		/* capture end of Tx-ed PDU, used to calculate HCTO. */
+		radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+		if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
+			/* PA/LNA enable is overwriting packet end
+			 * used in ISR profiling, hence back it up
+			 * for later use.
+			 */
+			lll_prof_radio_end_backup();
+		}
+
+		radio_gpio_pa_setup();
+		radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
+					 EVENT_IFS_US -
+					 radio_rx_chain_delay_get(0, 0) -
+					 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+		/* switch scanner state to active */
+		lll->state = 1U;
+		radio_isr_set(isr_tx, lll);
+
+		return 0;
+	}
+	/* Passive scanner or scan responses */
+	else if (((((pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_NONCONN_IND) ||
+		    (pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND)) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_adv_ind))) ||
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		   (pdu_adv_rx->len == sizeof(struct pdu_adv_direct_ind)) &&
+		   (/* allow directed adv packets addressed to this device */
+		    isr_scan_tgta_check(lll, false, pdu_adv_rx, rl_idx,
+					&dir_report))) ||
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_EXT_IND) &&
+		   (lll->phy)) ||
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+		  ((pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_RSP) &&
+		   (pdu_adv_rx->len <= sizeof(struct pdu_adv_scan_rsp)) &&
+		   (lll->state != 0U) &&
+		   isr_scan_rsp_adva_matches(pdu_adv_rx))) &&
+		 (pdu_adv_rx->len != 0) &&
+#if defined(CONFIG_BT_CENTRAL)
+		   !lll->conn) {
+#else /* !CONFIG_BT_CENTRAL */
+		   1) {
+#endif /* !CONFIG_BT_CENTRAL */
+		uint32_t err;
+
+		/* save the scan response packet */
+		err = isr_rx_scan_report(lll, rssi_ready,
+					 irkmatch_ok ? rl_idx :
+						       FILTER_IDX_NONE,
+					 dir_report);
+		if (err) {
+			return err;
+		}
+	}
+	/* invalid PDU */
+	else {
+		/* ignore and close this rx/tx chain ( code below ) */
+		return 1;
+	}
+
+	return 1;
+}
+
+static inline bool isr_scan_init_check(struct lll_scan *lll,
+				       struct pdu_adv *pdu, uint8_t rl_idx)
+{
+	return ((((lll->filter_policy & 0x01) != 0U) ||
+		 isr_scan_init_adva_check(lll, pdu, rl_idx)) &&
+		(((pdu->type == PDU_ADV_TYPE_ADV_IND) &&
+		  (pdu->len <= sizeof(struct pdu_adv_adv_ind))) ||
+		 ((pdu->type == PDU_ADV_TYPE_DIRECT_IND) &&
+		  (pdu->len == sizeof(struct pdu_adv_direct_ind)) &&
+		  (/* allow directed adv packets addressed to this device */
+		   isr_scan_tgta_check(lll, true, pdu, rl_idx, NULL)))));
+}
+
+static inline bool isr_scan_init_adva_check(struct lll_scan *lll,
+					    struct pdu_adv *pdu, uint8_t rl_idx)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* Only applies to initiator with no whitelist */
+	if (rl_idx != FILTER_IDX_NONE) {
+		return (rl_idx == lll->rl_idx);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	return ((lll->adv_addr_type == pdu->tx_addr) &&
+		!memcmp(lll->adv_addr, &pdu->adv_ind.addr[0], BDADDR_SIZE));
+}
+
+static inline bool isr_scan_tgta_check(struct lll_scan *lll, bool init,
+				       struct pdu_adv *pdu, uint8_t rl_idx,
+				       bool *dir_report)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (ull_filter_lll_rl_addr_resolve(pdu->rx_addr,
+					   pdu->direct_ind.tgt_addr, rl_idx)) {
+		return true;
+	} else if (init && lll->rpa_gen &&
+		   ull_filter_lll_lrpa_get(rl_idx)) {
+		/* Initiator generating RPAs, and could not resolve TargetA:
+		 * discard
+		 */
+		return false;
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	return (((lll->init_addr_type == pdu->rx_addr) &&
+		!memcmp(lll->init_addr, pdu->direct_ind.tgt_addr,
+			BDADDR_SIZE))) ||
+		  /* allow directed adv packets where TargetA address
+		   * is resolvable private address (scanner only)
+		   */
+	       isr_scan_tgta_rpa_check(lll, pdu, dir_report);
+}
+
+static inline bool isr_scan_tgta_rpa_check(struct lll_scan *lll,
+					   struct pdu_adv *pdu,
+					   bool *dir_report)
+{
+	if (((lll->filter_policy & 0x02) != 0U) &&
+	    (pdu->rx_addr != 0) &&
+	    ((pdu->direct_ind.tgt_addr[5] & 0xc0) == 0x40)) {
+
+		if (dir_report) {
+			*dir_report = true;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static inline bool isr_scan_rsp_adva_matches(struct pdu_adv *srsp)
+{
+	struct pdu_adv *sreq = (void *)radio_pkt_scratch_get();
+
+	return ((sreq->rx_addr == srsp->tx_addr) &&
+		(memcmp(&sreq->scan_req.adv_addr[0],
+			&srsp->scan_rsp.addr[0], BDADDR_SIZE) == 0));
+}
+
+static uint32_t isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
+				uint8_t rl_idx, bool dir_report)
+{
+	struct node_rx_pdu *node_rx;
+	struct pdu_adv *pdu_adv_rx;
+
+	node_rx = ull_pdu_rx_alloc_peek(3);
+	if (!node_rx) {
+		return 1;
+	}
+	ull_pdu_rx_alloc();
+
+	/* Prepare the report (adv or scan resp) */
+	node_rx->hdr.handle = 0xffff;
+	if (0) {
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	} else if (_radio.advertiser.is_enabled &&
+		   _radio.advertiser.is_mesh) {
+		node_rx->hdr.type = NODE_RX_TYPE_MESH_REPORT;
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	} else if (lll->phy) {
+		switch (lll->phy) {
+		case BIT(0):
+			node_rx->hdr.type = NODE_RX_TYPE_EXT_1M_REPORT;
+			break;
+
+		case BIT(2):
+			node_rx->hdr.type = NODE_RX_TYPE_EXT_CODED_REPORT;
+			break;
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	} else {
+		node_rx->hdr.type = NODE_RX_TYPE_REPORT;
+	}
+
+	pdu_adv_rx = (void *)node_rx->pdu;
+
+	node_rx->hdr.rx_ftr.rssi = (rssi_ready) ?
+				   (radio_rssi_get() & 0x7f)
+				   : 0x7f;
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	/* save the resolving list index. */
+	node_rx->hdr.rx_ftr.rl_idx = rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	/* save the directed adv report flag */
+	node_rx->hdr.rx_ftr.direct = dir_report;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
+		/* save channel and anchor point ticks. */
+		node_rx->hdr.rx_ftr.chan = _radio.scanner.chan - 1;
+		node_rx->hdr.rx_ftr.ticks_anchor = _radio.ticks_anchor;
+	}
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
+	ull_rx_put(node_rx->hdr.link, node_rx);
+	ull_rx_sched();
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int lll_slave_init(void);
+int lll_slave_reset(void);
+void lll_slave_prepare(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_slave.c	(working copy)
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_conn.h"
+#include "lll_slave.h"
+#include "lll_chan.h"
+
+#include "lll_internal.h"
+#include "lll_tim_internal.h"
+
+#define LOG_MODULE_NAME bt_ctlr_llsw_openisa_lll_slave
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static int prepare_cb(struct lll_prepare_param *prepare_param);
+
+int lll_slave_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int lll_slave_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void lll_slave_prepare(void *param)
+{
+	struct lll_prepare_param *p = param;
+	struct lll_conn *lll = p->param;
+	uint16_t elapsed;
+	int err;
+
+	err = lll_clk_on();
+	LL_ASSERT(!err || err == -EINPROGRESS);
+
+	/* Instants elapsed */
+	elapsed = p->lazy + 1;
+
+	/* Save the (latency + 1) for use in event */
+	lll->latency_prepare += elapsed;
+
+	/* Accumulate window widening */
+	lll->slave.window_widening_prepare_us +=
+	    lll->slave.window_widening_periodic_us * elapsed;
+	if (lll->slave.window_widening_prepare_us >
+	    lll->slave.window_widening_max_us) {
+		lll->slave.window_widening_prepare_us =
+			lll->slave.window_widening_max_us;
+	}
+
+	/* Invoke common pipeline handling of prepare */
+	err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
+	LL_ASSERT(!err || err == -EINPROGRESS);
+}
+
+static int init_reset(void)
+{
+	return 0;
+}
+
+static int prepare_cb(struct lll_prepare_param *prepare_param)
+{
+	struct lll_conn *lll = prepare_param->param;
+	uint32_t ticks_at_event, ticks_at_start;
+	struct evt_hdr *evt;
+	uint16_t event_counter;
+	uint32_t remainder_us;
+	uint8_t data_chan_use;
+	uint32_t remainder;
+	uint32_t hcto;
+
+	DEBUG_RADIO_START_S(1);
+
+	/* Reset connection event global variables */
+	lll_conn_prepare_reset();
+
+	/* Deduce the latency */
+	lll->latency_event = lll->latency_prepare - 1;
+
+	/* Calculate the current event counter value */
+	event_counter = lll->event_counter + lll->latency_event;
+
+	/* Update event counter to next value */
+	lll->event_counter = lll->event_counter + lll->latency_prepare;
+
+	/* Reset accumulated latencies */
+	lll->latency_prepare = 0;
+
+	if (lll->data_chan_sel) {
+#if defined(CONFIG_BT_CTLR_CHAN_SEL_2)
+		data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+#else /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+		data_chan_use = 0;
+		LL_ASSERT(0);
+#endif /* !CONFIG_BT_CTLR_CHAN_SEL_2 */
+	} else {
+		data_chan_use = lll_chan_sel_1(&lll->data_chan_use,
+					       lll->data_chan_hop,
+					       lll->latency_event,
+					       &lll->data_chan_map[0],
+					       lll->data_chan_count);
+	}
+
+	/* current window widening */
+	lll->slave.window_widening_event_us +=
+		lll->slave.window_widening_prepare_us;
+	lll->slave.window_widening_prepare_us = 0;
+	if (lll->slave.window_widening_event_us >
+	    lll->slave.window_widening_max_us) {
+		lll->slave.window_widening_event_us =
+			lll->slave.window_widening_max_us;
+	}
+
+	/* current window size */
+	lll->slave.window_size_event_us +=
+		lll->slave.window_size_prepare_us;
+	lll->slave.window_size_prepare_us = 0;
+
+	/* Start setting up Radio h/w */
+	radio_reset();
+	/* TODO: other Tx Power settings */
+	radio_tx_power_set(RADIO_TXP_DEFAULT);
+
+	lll_conn_rx_pkt_set(lll);
+
+	radio_aa_set(lll->access_addr);
+	radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
+			    (((uint32_t)lll->crc_init[2] << 16) |
+			     ((uint32_t)lll->crc_init[1] << 8) |
+			     ((uint32_t)lll->crc_init[0])));
+
+	lll_chan_set(data_chan_use);
+
+	radio_isr_set(lll_conn_isr_rx, lll);
+
+	radio_tmr_tifs_set(EVENT_IFS_US);
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_switch_complete_and_tx(lll->phy_rx, 0, lll->phy_tx,
+				     lll->phy_flags);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_switch_complete_and_tx(0, 0, 0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	ticks_at_event = prepare_param->ticks_at_expire;
+	evt = HDR_LLL2EVT(lll);
+	ticks_at_event += lll_evt_offset_get(evt);
+
+	ticks_at_start = ticks_at_event;
+	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
+
+	remainder = prepare_param->remainder;
+	remainder_us = radio_tmr_start(0, ticks_at_start, remainder);
+
+	radio_tmr_aa_capture();
+	radio_tmr_aa_save(0);
+
+	hcto = remainder_us + EVENT_JITTER_US + (EVENT_JITTER_US << 2) +
+	       (lll->slave.window_widening_event_us << 1) +
+	       lll->slave.window_size_event_us;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	hcto += radio_rx_ready_delay_get(lll->phy_rx, 1);
+	hcto += addr_us_get(lll->phy_rx);
+	hcto += radio_rx_chain_delay_get(lll->phy_rx, 1);
+#else /* !CONFIG_BT_CTLR_PHY */
+	hcto += radio_rx_ready_delay_get(0, 0);
+	hcto += addr_us_get(0);
+	hcto += radio_rx_chain_delay_get(0, 0);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	radio_tmr_hcto_configure(hcto);
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_setup();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(lll->phy_rx, 1) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#else /* !CONFIG_BT_CTLR_PHY */
+	radio_gpio_pa_lna_enable(remainder_us +
+				 radio_rx_ready_delay_get(0, 0) -
+				 CONFIG_BT_CTLR_GPIO_LNA_OFFSET);
+#endif /* !CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
+	defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_tmr_end_capture();
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	radio_rssi_measure();
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
+	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
+	/* check if preempt to start has changed */
+	if (lll_preempt_calc(evt, (TICKER_ID_CONN_BASE + lll->handle),
+			     ticks_at_event)) {
+		radio_isr_set(lll_conn_isr_abort, lll);
+		radio_disable();
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ret;
+
+		ret = lll_prepare_done(lll);
+		LL_ASSERT(!ret);
+	}
+
+	DEBUG_RADIO_START_S(1);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_test.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_test.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_test.c	(working copy)
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <soc.h>
+#include <drivers/clock_control.h>
+
+#include "hal/cpu.h"
+#include "hal/cntr.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+
+#include "util/memq.h"
+
+#include "lll.h"
+#include "lll_internal.h"
+
+#include "ll_test.h"
+
+#include "hal/debug.h"
+#include "common/log.h"
+
+#define CNTR_MIN_DELTA 3
+
+static const uint32_t test_sync_word = 0x71764129;
+static uint8_t        test_phy;
+static uint8_t        test_phy_flags;
+static uint16_t       test_num_rx;
+static bool        started;
+
+/* NOTE: The PRBS9 sequence used as packet payload.
+ * The bytes in the sequence are in the right order, but the bits of each byte
+ * in the array are reverse from that found by running the PRBS9 algorithm. This
+ * is done to transmit MSbit first on air.
+ */
+
+static const uint8_t prbs9[] = {
+	0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B,
+	0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23,
+	0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B,
+	0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA,
+	0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A,
+	0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE,
+	0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E,
+	0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87,
+	0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5,
+	0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11,
+	0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D,
+	0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65,
+	0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D,
+	0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F,
+	0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF,
+	0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3,
+	0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2,
+	0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88,
+	0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E,
+	0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32,
+	0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6,
+	0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF,
+	0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7,
+	0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1,
+	0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1,
+	0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44,
+	0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27,
+	0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99,
+	0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3,
+	0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57,
+	0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB,
+	0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7};
+
+/* TODO: fill correct prbs15 */
+static const uint8_t prbs15[255] = { 0x00, };
+
+static uint8_t tx_req;
+static uint8_t volatile tx_ack;
+
+static void isr_tx(void *param)
+{
+	uint32_t l, i, s, t;
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_lna_disable();
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	/* Exit if radio disabled */
+	if (((tx_req - tx_ack) & 0x01) == 0U) {
+		tx_ack = tx_req;
+
+		return;
+	}
+
+	/* LE Test Packet Interval */
+	l = radio_tmr_end_get() - radio_tmr_ready_get();
+	i = ((l + 249 + 624) / 625) * 625U;
+	t = radio_tmr_end_get() - l + i;
+	t -= radio_tx_ready_delay_get(test_phy, test_phy_flags);
+
+	/* Set timer capture in the future. */
+	radio_tmr_sample();
+	s = radio_tmr_sample_get();
+	while (t < s) {
+		t += 625U;
+	}
+
+	/* Setup next Tx */
+	radio_switch_complete_and_disable();
+	radio_tmr_start_us(1, t);
+	radio_tmr_aa_capture();
+	radio_tmr_end_capture();
+
+	/* TODO: check for probable stale timer capture being set */
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(t + radio_tx_ready_delay_get(test_phy,
+							      test_phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
+}
+
+static void isr_rx(void *param)
+{
+	uint8_t crc_ok = 0U;
+	uint8_t trx_done;
+
+	/* Read radio status and events */
+	trx_done = radio_is_done();
+	if (trx_done) {
+		crc_ok = radio_crc_is_valid();
+	}
+
+	/* Clear radio status and events */
+	radio_status_reset();
+	radio_tmr_status_reset();
+
+	/* Exit if radio disabled */
+	if (!trx_done) {
+		return;
+	}
+
+	/* Setup next Rx */
+	radio_switch_complete_and_rx(test_phy);
+
+	/* Count Rx-ed packets */
+	if (crc_ok) {
+		test_num_rx++;
+	}
+}
+
+static uint32_t init(uint8_t chan, uint8_t phy, void (*isr)(void *))
+{
+	int err;
+
+	if (started) {
+		return 1;
+	}
+
+	/* start coarse timer */
+	cntr_start();
+
+	/* Setup resources required by Radio */
+	err = lll_clk_on_wait();
+
+	/* Reset Radio h/w */
+	radio_reset();
+	radio_isr_set(isr, NULL);
+
+	/* Store value needed in Tx/Rx ISR */
+	if (phy < 0x04) {
+		test_phy = BIT(phy - 1);
+		test_phy_flags = 1U;
+	} else {
+		test_phy = BIT(2);
+		test_phy_flags = 0U;
+	}
+
+	/* Setup Radio in Tx/Rx */
+	/* NOTE: No whitening in test mode. */
+	radio_phy_set(test_phy, test_phy_flags);
+	radio_tmr_tifs_set(150);
+	radio_tx_power_max_set();
+	radio_freq_chan_set((chan << 1) + 2);
+	radio_aa_set((uint8_t *)&test_sync_word);
+	radio_crc_configure(0x65b, 0x555555);
+	radio_pkt_configure(8, 255, (test_phy << 1));
+
+	return 0;
+}
+
+uint32_t ll_test_tx(uint8_t chan, uint8_t len, uint8_t type, uint8_t phy)
+{
+	uint32_t start_us;
+	uint8_t *payload;
+	uint8_t *pdu;
+	uint32_t err;
+
+	if ((type > 0x07) || !phy || (phy > 0x04)) {
+		return 1;
+	}
+
+	err = init(chan, phy, isr_tx);
+	if (err) {
+		return err;
+	}
+
+	tx_req++;
+
+	pdu = radio_pkt_scratch_get();
+	payload = &pdu[2];
+
+	switch (type) {
+	case 0x00:
+		memcpy(payload, prbs9, len);
+		break;
+
+	case 0x01:
+		memset(payload, 0x0f, len);
+		break;
+
+	case 0x02:
+		memset(payload, 0x55, len);
+		break;
+
+	case 0x03:
+		memcpy(payload, prbs15, len);
+		break;
+
+	case 0x04:
+		memset(payload, 0xff, len);
+		break;
+
+	case 0x05:
+		memset(payload, 0x00, len);
+		break;
+
+	case 0x06:
+		memset(payload, 0xf0, len);
+		break;
+
+	case 0x07:
+		memset(payload, 0xaa, len);
+		break;
+	}
+
+	pdu[0] = type;
+	pdu[1] = len;
+
+	radio_pkt_tx_set(pdu);
+	radio_switch_complete_and_disable();
+	start_us = radio_tmr_start(1, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
+	radio_tmr_aa_capture();
+	radio_tmr_end_capture();
+
+#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
+	radio_gpio_pa_setup();
+	radio_gpio_pa_lna_enable(start_us +
+				 radio_tx_ready_delay_get(test_phy,
+							  test_phy_flags) -
+				 CONFIG_BT_CTLR_GPIO_PA_OFFSET);
+#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+	ARG_UNUSED(start_us);
+#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
+
+	started = true;
+
+	return 0;
+}
+
+uint32_t ll_test_rx(uint8_t chan, uint8_t phy, uint8_t mod_idx)
+{
+	uint32_t err;
+
+	if (!phy || (phy > 0x03)) {
+		return 1;
+	}
+
+	err = init(chan, phy, isr_rx);
+	if (err) {
+		return err;
+	}
+
+	radio_pkt_rx_set(radio_pkt_scratch_get());
+	radio_switch_complete_and_rx(test_phy);
+	radio_tmr_start(0, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_on();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	started = true;
+
+	return 0;
+}
+
+uint32_t ll_test_end(uint16_t *num_rx)
+{
+	int err;
+	uint8_t ack;
+
+	if (!started) {
+		return 1;
+	}
+
+	/* Return packets Rx-ed/Completed */
+	*num_rx = test_num_rx;
+	test_num_rx = 0U;
+
+	/* Disable Radio, if in Rx test */
+	ack = tx_ack;
+	if (tx_req == ack) {
+		radio_disable();
+	} else {
+		/* Wait for Tx to complete */
+		tx_req = ack + 2;
+		while (tx_req != tx_ack) {
+			cpu_sleep();
+		}
+	}
+
+	/* Stop packet timer */
+	radio_tmr_stop();
+
+	/* Release resources acquired for Radio */
+	err = lll_clk_off();
+	LL_ASSERT(!err || err == -EBUSY);
+
+	/* Stop coarse timer */
+	cntr_stop();
+
+#if defined(CONFIG_BT_CTLR_GPIO_LNA_PIN)
+	radio_gpio_lna_off();
+#endif /* !CONFIG_BT_CTLR_GPIO_LNA_PIN */
+
+	started = false;
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_tim_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_tim_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_tim_internal.h	(working copy)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Range Delay
+ * Refer to BT Spec v5.1 Vol.6, Part B, Section 4.2.3 Range Delay
+ * "4 / 1000" is an approximation of the propagation time in us of the
+ * signal to travel 1 meter.
+ */
+#define RANGE_DISTANCE 1000 /* meters */
+#define RANGE_DELAY_US (2 * RANGE_DISTANCE * 4 / 1000)
+
+static inline uint32_t addr_us_get(uint8_t phy)
+{
+	switch (phy) {
+	default:
+	case BIT(0):
+		return 40;
+	case BIT(1):
+		return 24;
+	case BIT(2):
+		return 376;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_vendor.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_vendor.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/openisa/lll/lll_vendor.h	(working copy)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define EVENT_OVERHEAD_XTAL_US        1500
+#define EVENT_OVERHEAD_PREEMPT_US     0    /* if <= min, then dynamic preempt */
+#define EVENT_OVERHEAD_PREEMPT_MIN_US 150
+#define EVENT_OVERHEAD_PREEMPT_MAX_US EVENT_OVERHEAD_XTAL_US
+#define EVENT_OVERHEAD_START_US       300
+/* Worst-case time margin needed after event end-time in the air
+ * (done/preempt race margin + power-down/chain delay)
+ */
+#define EVENT_OVERHEAD_END_US         40
+#define EVENT_JITTER_US               16
+/* Ticker resolution margin
+ * Needed due to the lack of fine timing resolution in ticker_start
+ * and ticker_update. Set to 32 us, which is ~1 tick with 32768 Hz
+ * clock.
+ */
+#define EVENT_TICKER_RES_MARGIN_US    32
+
+#define EVENT_RX_JITTER_US(phy) 16    /* Radio Rx timing uncertainty */
+#define EVENT_RX_TO_US(phy) ((((((phy)&0x03) + 4)<<3)/BIT((((phy)&0x3)>>1))) + \
+				  EVENT_RX_JITTER_US(phy))
+
+/* TODO - fix up numbers re. HW */
+#define EVENT_RX_TX_TURNAROUND(phy)  ((phy) == 1?100:((phy) == 2 ? 80:900))
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/pdu.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/pdu.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/pdu.h	(working copy)
@@ -0,0 +1,705 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <toolchain.h>
+
+/*
+ * PDU fields sizes
+ */
+
+#define PDU_PREAMBLE_SIZE(phy) (phy&0x3)
+#define PDU_ACCESS_ADDR_SIZE   4
+#define PDU_HEADER_SIZE        2
+#define PDU_MIC_SIZE           4
+#define PDU_CRC_SIZE           3
+#define PDU_OVERHEAD_SIZE(phy) (PDU_PREAMBLE_SIZE(phy) + \
+				PDU_ACCESS_ADDR_SIZE + \
+				PDU_HEADER_SIZE + \
+				PDU_CRC_SIZE)
+
+#define BDADDR_SIZE   6
+#define ADVA_SIZE     BDADDR_SIZE
+#define SCANA_SIZE    BDADDR_SIZE
+#define INITA_SIZE    BDADDR_SIZE
+#define TARGETA_SIZE  BDADDR_SIZE
+#define LLDATA_SIZE   22
+#define CTE_INFO_SIZE 1
+#define TX_PWR_SIZE   1
+#define ACAD_SIZE     0
+
+#define BYTES2US(bytes, phy) (((bytes)<<3)/BIT((phy&0x3)>>1))
+
+/* Advertisement channel maximum legacy payload size */
+#define PDU_AC_PAYLOAD_SIZE_MAX 37
+/* Advertisement channel maximum extended payload size */
+#define PDU_AC_EXT_PAYLOAD_SIZE_MAX 251
+/* Advertisement channel minimum extended payload size */
+#define PDU_AC_EXT_PAYLOAD_SIZE_MIN (offsetof(pdu_adv_com_ext_adv, \
+					      ext_hdr_adi_adv_data) + \
+				     ADVA_SIZE + \
+				     TARGETA_SIZE + \
+				     CTE_INFO_SIZE + \
+				     sizeof(struct pdu_adv_adi) + \
+				     sizeof(struct pdu_adv_aux_ptr) + \
+				     sizeof(struct pdu_adv_sync_info) + \
+				     TX_PWR_SIZE + \
+				     ACAD_SIZE)
+
+/* Link Layer header size of Adv PDU. Assumes pdu_adv is packed */
+#define PDU_AC_LL_HEADER_SIZE  (offsetof(struct pdu_adv, payload))
+
+/* Link Layer Advertisement channel maximum PDU buffer size */
+#define PDU_AC_LL_SIZE_MAX     (PDU_AC_LL_HEADER_SIZE + PDU_AC_PAYLOAD_SIZE_MAX)
+
+/* Advertisement channel Access Address */
+#define PDU_AC_ACCESS_ADDR     0x8e89bed6
+
+/* Data channel minimum payload size and time */
+#define PDU_DC_PAYLOAD_SIZE_MIN 27
+#define PDU_DC_PAYLOAD_TIME_MIN 328
+
+/* Link Layer header size of Data PDU. Assumes pdu_data is packed */
+#define PDU_DC_LL_HEADER_SIZE  (offsetof(struct pdu_data, lldata))
+
+/* Link Layer Max size of an empty PDU. TODO: Remove; only used in Nordic LLL */
+#define PDU_EM_LL_SIZE_MAX     (PDU_DC_LL_HEADER_SIZE)
+
+/* Event interframe timings */
+#define EVENT_IFS_US            150
+/* Standard allows 2 us timing uncertainty inside the event */
+#define EVENT_IFS_MAX_US        (EVENT_IFS_US + 2)
+/* Controller will layout extended adv with minimum separation */
+#define EVENT_MAFS_US           300
+/* Standard allows 2 us timing uncertainty inside the event */
+#define EVENT_MAFS_MAX_US       (EVENT_MAFS_US + 2)
+
+/* Offset Units field encoding */
+#define OFFS_UNIT_30_US         30
+#define OFFS_UNIT_300_US        300
+
+/*
+ * Macros to return correct Data Channel PDU time
+ * Note: formula is valid for 1M, 2M and Coded S8
+ * see BT spec Version 5.1 Vol 6. Part B, chapters 2.1 and 2.2
+ * for packet formats and thus lengths
+ */
+
+#define PHY_LEGACY 0
+#define PHY_1M     BIT(0)
+#define PHY_2M     BIT(1)
+#define PHY_CODED  BIT(2)
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+#define CODED_PHY_PREAMBLE_TIME_US       80
+#define CODED_PHY_ACCESS_ADDRESS_TIME_US 256
+#define CODED_PHY_CI_TIME_US             16
+#define CODED_PHY_TERM1_TIME_US          24
+#define CODED_PHY_CRC_SIZE               24
+#define CODED_PHY_TERM2_SIZE             3
+
+#define FEC_BLOCK1_TIME_US               ((CODED_PHY_ACCESS_ADDRESS_TIME_US) + \
+					  (CODED_PHY_CI_TIME_US) + \
+					  (CODED_PHY_TERM1_TIME_US))
+#define FEC_BLOCK2_TIME_US(octets, mic)  (((((PDU_HEADER_SIZE) + \
+					     (octets) + \
+					     (mic))<<3) + \
+					    (CODED_PHY_CRC_SIZE) + \
+					    (CODED_PHY_TERM2_SIZE))<<3)
+
+#define PKT_DC_US(octets, mic, phy) (((phy) & PHY_CODED) ? \
+				     ((CODED_PHY_PREAMBLE_TIME_US) + \
+				      (FEC_BLOCK1_TIME_US) + \
+				      FEC_BLOCK2_TIME_US((octets), (mic))) : \
+				     (((PDU_PREAMBLE_SIZE(phy) + \
+					(PDU_ACCESS_ADDR_SIZE) + \
+					(PDU_HEADER_SIZE) + \
+					(octets) + \
+					(mic) + \
+					(PDU_CRC_SIZE))<<3) / \
+				      BIT(((phy) & 0x03) >> 1)))
+
+#else /* !CONFIG_BT_CTLR_PHY_CODED */
+#define PKT_DC_US(octets, mic, phy) (((PDU_PREAMBLE_SIZE(phy) + \
+				       (PDU_ACCESS_ADDR_SIZE) + \
+				       (PDU_HEADER_SIZE) + \
+				       (octets) + \
+				       (mic) + \
+				       (PDU_CRC_SIZE))<<3) / \
+				     BIT(((phy) & 0x03) >> 1))
+#endif /* !CONFIG_BT_CTLR_PHY_CODED */
+
+#define PKT_US(octets, phy) PKT_DC_US((octets), (PDU_MIC_SIZE), (phy))
+
+#define PKT_AC_US(octets, mic, phy) PKT_DC_US((octets), (mic), (phy))
+
+/* Extra bytes for enqueued node_rx metadata: rssi (always), resolving
+ * index, directed adv report, and mesh channel and instant.
+ */
+#define PDU_AC_SIZE_RSSI 1
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#define PDU_AC_SIZE_PRIV 1
+#else
+#define PDU_AC_SIZE_PRIV 0
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+#define PDU_AC_SIZE_SCFP 1
+#else
+#define PDU_AC_SIZE_SCFP 0
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+#define PDU_AC_SIZE_MESH 5
+#else
+#define PDU_AC_SIZE_MESH 0
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#define PDU_AC_LL_SIZE_EXTRA (PDU_AC_SIZE_RSSI + \
+			      PDU_AC_SIZE_PRIV + \
+			      PDU_AC_SIZE_SCFP + \
+			      PDU_AC_SIZE_MESH)
+
+struct pdu_adv_adv_ind {
+	uint8_t addr[BDADDR_SIZE];
+	uint8_t data[31];
+} __packed;
+
+struct pdu_adv_direct_ind {
+	uint8_t adv_addr[BDADDR_SIZE];
+	uint8_t tgt_addr[BDADDR_SIZE];
+} __packed;
+
+struct pdu_adv_scan_rsp {
+	uint8_t addr[BDADDR_SIZE];
+	uint8_t data[31];
+} __packed;
+
+struct pdu_adv_scan_req {
+	uint8_t scan_addr[BDADDR_SIZE];
+	uint8_t adv_addr[BDADDR_SIZE];
+} __packed;
+
+struct pdu_adv_connect_ind {
+	uint8_t init_addr[BDADDR_SIZE];
+	uint8_t adv_addr[BDADDR_SIZE];
+	struct {
+		uint8_t  access_addr[4];
+		uint8_t  crc_init[3];
+		uint8_t  win_size;
+		uint16_t win_offset;
+		uint16_t interval;
+		uint16_t latency;
+		uint16_t timeout;
+		uint8_t  chan_map[5];
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+		uint8_t  hop:5;
+		uint8_t  sca:3;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+		uint8_t  sca:3;
+		uint8_t  hop:5;
+#else
+#error "Unsupported endianness"
+#endif
+
+	} __packed;
+} __packed;
+
+struct pdu_adv_com_ext_adv {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t ext_hdr_len:6;
+	uint8_t adv_mode:2;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t adv_mode:2;
+	uint8_t ext_hdr_len:6;
+#else
+#error "Unsupported endianness"
+#endif
+	uint8_t ext_hdr_adi_adv_data[254];
+} __packed;
+
+enum pdu_adv_mode {
+	EXT_ADV_MODE_NON_CONN_NON_SCAN = 0x00,
+	EXT_ADV_MODE_CONN_NON_SCAN = 0x01,
+	EXT_ADV_MODE_NON_CONN_SCAN = 0x02,
+};
+
+struct pdu_adv_hdr {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t adv_addr:1;
+	uint8_t tgt_addr:1;
+	uint8_t rfu0:1;
+	uint8_t adi:1;
+	uint8_t aux_ptr:1;
+	uint8_t sync_info:1;
+	uint8_t tx_pwr:1;
+	uint8_t rfu1:1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t rfu1:1;
+	uint8_t tx_pwr:1;
+	uint8_t sync_info:1;
+	uint8_t aux_ptr:1;
+	uint8_t adi:1;
+	uint8_t rfu0:1;
+	uint8_t tgt_addr:1;
+	uint8_t adv_addr:1;
+#else
+#error "Unsupported endianness"
+#endif
+} __packed;
+
+struct pdu_adv_adi {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint16_t did:12;
+	uint16_t sid:4;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint16_t sid:4;
+	uint16_t did:12;
+#else
+#error "Unsupported endianness"
+#endif
+} __packed;
+
+struct pdu_adv_aux_ptr {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t  chan_idx:6;
+	uint8_t  ca:1;
+	uint8_t  offs_units:1;
+	uint16_t offs:13;
+	uint16_t phy:3;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t  offs_units:1;
+	uint8_t  ca:1;
+	uint8_t  chan_idx:6;
+	uint16_t phy:3;
+	uint16_t offs:13;
+#else
+#error "Unsupported endianness"
+#endif
+} __packed;
+
+enum pdu_adv_aux_ptr_ca {
+	EXT_ADV_AUX_PTR_CA_500_PPM = 0x00,
+	EXT_ADV_AUX_PTR_CA_50_PPM  = 0x01,
+};
+
+enum pdu_adv_offs_units {
+	EXT_ADV_AUX_PTR_OFFS_UNITS_30  = 0x00,
+	EXT_ADV_AUX_PTR_OFFS_UNITS_300 = 0x01,
+};
+
+enum pdu_adv_aux_phy {
+	EXT_ADV_AUX_PHY_LE_1M  = 0x00,
+	EXT_ADV_AUX_PHY_LE_2M  = 0x01,
+	EXT_ADV_AUX_PHY_LE_COD = 0x02,
+};
+
+struct pdu_adv_sync_info {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint16_t offs:13;
+	uint16_t offs_units:1;
+	uint16_t rfu:2;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint16_t rfu:2;
+	uint16_t offs_units:1;
+	uint16_t offs:13;
+#else
+#error "Unsupported endianness"
+#endif
+	uint16_t interval;
+	uint8_t  sca_chm[5];
+	uint32_t aa;
+	uint8_t  crc_init[3];
+	uint16_t evt_cntr;
+} __packed;
+
+enum pdu_adv_type {
+	PDU_ADV_TYPE_ADV_IND = 0x00,
+	PDU_ADV_TYPE_DIRECT_IND = 0x01,
+	PDU_ADV_TYPE_NONCONN_IND = 0x02,
+	PDU_ADV_TYPE_SCAN_REQ = 0x03,
+	PDU_ADV_TYPE_AUX_SCAN_REQ = PDU_ADV_TYPE_SCAN_REQ,
+	PDU_ADV_TYPE_SCAN_RSP = 0x04,
+	PDU_ADV_TYPE_ADV_IND_SCAN_RSP = 0x05,
+	PDU_ADV_TYPE_CONNECT_IND = 0x05,
+	PDU_ADV_TYPE_AUX_CONNECT_REQ = PDU_ADV_TYPE_CONNECT_IND,
+	PDU_ADV_TYPE_SCAN_IND = 0x06,
+	PDU_ADV_TYPE_EXT_IND = 0x07,
+	PDU_ADV_TYPE_AUX_ADV_IND = PDU_ADV_TYPE_EXT_IND,
+	PDU_ADV_TYPE_AUX_SCAN_RSP = PDU_ADV_TYPE_EXT_IND,
+	PDU_ADV_TYPE_AUX_SYNC_IND = PDU_ADV_TYPE_EXT_IND,
+	PDU_ADV_TYPE_AUX_CHAIN_IND = PDU_ADV_TYPE_EXT_IND,
+	PDU_ADV_TYPE_AUX_CONNECT_RSP = 0x08,
+} __packed;
+
+struct pdu_adv {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t type:4;
+	uint8_t rfu:1;
+	uint8_t chan_sel:1;
+	uint8_t tx_addr:1;
+	uint8_t rx_addr:1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t rx_addr:1;
+	uint8_t tx_addr:1;
+	uint8_t chan_sel:1;
+	uint8_t rfu:1;
+	uint8_t type:4;
+#else
+#error "Unsupported endianness"
+#endif
+
+	uint8_t len;
+
+	union {
+		uint8_t   payload[0];
+		struct pdu_adv_adv_ind adv_ind;
+		struct pdu_adv_direct_ind direct_ind;
+		struct pdu_adv_scan_req scan_req;
+		struct pdu_adv_scan_rsp scan_rsp;
+		struct pdu_adv_connect_ind connect_ind;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		struct pdu_adv_com_ext_adv adv_ext_ind;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	} __packed;
+} __packed;
+
+enum pdu_data_llid {
+	PDU_DATA_LLID_RESV = 0x00,
+	PDU_DATA_LLID_DATA_CONTINUE = 0x01,
+	PDU_DATA_LLID_DATA_START = 0x02,
+	PDU_DATA_LLID_CTRL = 0x03,
+};
+
+enum pdu_data_llctrl_type {
+	PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND = 0x00,
+	PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND = 0x01,
+	PDU_DATA_LLCTRL_TYPE_TERMINATE_IND = 0x02,
+	PDU_DATA_LLCTRL_TYPE_ENC_REQ = 0x03,
+	PDU_DATA_LLCTRL_TYPE_ENC_RSP = 0x04,
+	PDU_DATA_LLCTRL_TYPE_START_ENC_REQ = 0x05,
+	PDU_DATA_LLCTRL_TYPE_START_ENC_RSP = 0x06,
+	PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP = 0x07,
+	PDU_DATA_LLCTRL_TYPE_FEATURE_REQ = 0x08,
+	PDU_DATA_LLCTRL_TYPE_FEATURE_RSP = 0x09,
+	PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ = 0x0A,
+	PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP = 0x0B,
+	PDU_DATA_LLCTRL_TYPE_VERSION_IND = 0x0C,
+	PDU_DATA_LLCTRL_TYPE_REJECT_IND = 0x0D,
+	PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ = 0x0E,
+	PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ = 0x0F,
+	PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP = 0x10,
+	PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND = 0x11,
+	PDU_DATA_LLCTRL_TYPE_PING_REQ = 0x12,
+	PDU_DATA_LLCTRL_TYPE_PING_RSP = 0x13,
+	PDU_DATA_LLCTRL_TYPE_LENGTH_REQ = 0x14,
+	PDU_DATA_LLCTRL_TYPE_LENGTH_RSP = 0x15,
+	PDU_DATA_LLCTRL_TYPE_PHY_REQ = 0x16,
+	PDU_DATA_LLCTRL_TYPE_PHY_RSP = 0x17,
+	PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND = 0x18,
+	PDU_DATA_LLCTRL_TYPE_MIN_USED_CHAN_IND = 0x19,
+};
+
+struct pdu_data_llctrl_conn_update_ind {
+	uint8_t  win_size;
+	uint16_t win_offset;
+	uint16_t interval;
+	uint16_t latency;
+	uint16_t timeout;
+	uint16_t instant;
+} __packed;
+
+struct pdu_data_llctrl_chan_map_ind {
+	uint8_t  chm[5];
+	uint16_t instant;
+} __packed;
+
+struct pdu_data_llctrl_terminate_ind {
+	uint8_t error_code;
+} __packed;
+
+struct pdu_data_llctrl_enc_req {
+	uint8_t rand[8];
+	uint8_t ediv[2];
+	uint8_t skdm[8];
+	uint8_t ivm[4];
+} __packed;
+
+struct pdu_data_llctrl_enc_rsp {
+	uint8_t skds[8];
+	uint8_t ivs[4];
+} __packed;
+
+struct pdu_data_llctrl_start_enc_req {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_start_enc_rsp {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_unknown_rsp {
+	uint8_t type;
+} __packed;
+
+struct pdu_data_llctrl_feature_req {
+	uint8_t features[8];
+} __packed;
+
+struct pdu_data_llctrl_feature_rsp {
+	uint8_t features[8];
+} __packed;
+
+struct pdu_data_llctrl_pause_enc_req {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_pause_enc_rsp {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_version_ind {
+	uint8_t  version_number;
+	uint16_t company_id;
+	uint16_t sub_version_number;
+} __packed;
+
+struct pdu_data_llctrl_reject_ind {
+	uint8_t error_code;
+} __packed;
+
+struct pdu_data_llctrl_slave_feature_req {
+	uint8_t features[8];
+} __packed;
+
+struct pdu_data_llctrl_conn_param_req {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint8_t  preferred_periodicity;
+	uint16_t reference_conn_event_count;
+	uint16_t offset0;
+	uint16_t offset1;
+	uint16_t offset2;
+	uint16_t offset3;
+	uint16_t offset4;
+	uint16_t offset5;
+} __packed;
+
+struct pdu_data_llctrl_conn_param_rsp {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t latency;
+	uint16_t timeout;
+	uint8_t  preferred_periodicity;
+	uint16_t reference_conn_event_count;
+	uint16_t offset0;
+	uint16_t offset1;
+	uint16_t offset2;
+	uint16_t offset3;
+	uint16_t offset4;
+	uint16_t offset5;
+} __packed;
+
+struct pdu_data_llctrl_reject_ext_ind {
+	uint8_t reject_opcode;
+	uint8_t error_code;
+} __packed;
+
+struct pdu_data_llctrl_ping_req {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_ping_rsp {
+	/* no members */
+} __packed;
+
+struct pdu_data_llctrl_length_req {
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+struct pdu_data_llctrl_length_rsp {
+	uint16_t max_rx_octets;
+	uint16_t max_rx_time;
+	uint16_t max_tx_octets;
+	uint16_t max_tx_time;
+} __packed;
+
+struct pdu_data_llctrl_phy_req {
+	uint8_t tx_phys;
+	uint8_t rx_phys;
+} __packed;
+
+struct pdu_data_llctrl_phy_rsp {
+	uint8_t tx_phys;
+	uint8_t rx_phys;
+} __packed;
+
+struct pdu_data_llctrl_phy_upd_ind {
+	uint8_t  m_to_s_phy;
+	uint8_t  s_to_m_phy;
+	uint16_t instant;
+} __packed;
+
+struct pdu_data_llctrl_min_used_chans_ind {
+	uint8_t phys;
+	uint8_t min_used_chans;
+} __packed;
+
+struct pdu_data_llctrl {
+	uint8_t opcode;
+	union {
+		struct pdu_data_llctrl_conn_update_ind conn_update_ind;
+		struct pdu_data_llctrl_chan_map_ind chan_map_ind;
+		struct pdu_data_llctrl_terminate_ind terminate_ind;
+		struct pdu_data_llctrl_enc_req enc_req;
+		struct pdu_data_llctrl_enc_rsp enc_rsp;
+		struct pdu_data_llctrl_start_enc_req start_enc_req;
+		struct pdu_data_llctrl_start_enc_rsp start_enc_rsp;
+		struct pdu_data_llctrl_unknown_rsp unknown_rsp;
+		struct pdu_data_llctrl_feature_req feature_req;
+		struct pdu_data_llctrl_feature_rsp feature_rsp;
+		struct pdu_data_llctrl_pause_enc_req pause_enc_req;
+		struct pdu_data_llctrl_pause_enc_rsp pause_enc_rsp;
+		struct pdu_data_llctrl_version_ind version_ind;
+		struct pdu_data_llctrl_reject_ind reject_ind;
+		struct pdu_data_llctrl_slave_feature_req slave_feature_req;
+		struct pdu_data_llctrl_conn_param_req conn_param_req;
+		struct pdu_data_llctrl_conn_param_rsp conn_param_rsp;
+		struct pdu_data_llctrl_reject_ext_ind reject_ext_ind;
+		struct pdu_data_llctrl_ping_req ping_req;
+		struct pdu_data_llctrl_ping_rsp ping_rsp;
+		struct pdu_data_llctrl_length_req length_req;
+		struct pdu_data_llctrl_length_rsp length_rsp;
+		struct pdu_data_llctrl_phy_req phy_req;
+		struct pdu_data_llctrl_phy_rsp phy_rsp;
+		struct pdu_data_llctrl_phy_upd_ind phy_upd_ind;
+		struct pdu_data_llctrl_min_used_chans_ind min_used_chans_ind;
+	} __packed;
+} __packed;
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+struct profile {
+	uint8_t lcur;
+	uint8_t lmin;
+	uint8_t lmax;
+	uint8_t cur;
+	uint8_t min;
+	uint8_t max;
+} __packed;
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+struct pdu_data {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t ll_id:2;
+	uint8_t nesn:1;
+	uint8_t sn:1;
+	uint8_t md:1;
+	uint8_t rfu:3;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t rfu:3;
+	uint8_t md:1;
+	uint8_t sn:1;
+	uint8_t nesn:1;
+	uint8_t ll_id:2;
+#else
+#error "Unsupported endianness"
+#endif
+
+	uint8_t len;
+
+#if !defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
+#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
+	uint8_t resv:8; /* TODO: remove nRF specific code */
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */
+#endif /* !CONFIG_SOC_OPENISA_RV32M1_RISCV32 */
+
+	union {
+		struct pdu_data_llctrl llctrl;
+		uint8_t                   lldata[0];
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		uint8_t                   rssi;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+		struct profile         profile;
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+	} __packed;
+} __packed;
+
+struct pdu_cis {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t ll_id:2;
+	uint8_t nesn:1;
+	uint8_t sn:1;
+	uint8_t cie:1;
+	uint8_t rfu0:1;
+	uint8_t npi:1;
+	uint8_t rfu1:1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t rfu1:1;
+	uint8_t npi:1;
+	uint8_t rfu0:1;
+	uint8_t cie:1;
+	uint8_t sn:1;
+	uint8_t nesn:1;
+	uint8_t ll_id:2;
+#else
+#error "Unsupported endianness"
+#endif /* __BYTE_ORDER__ */
+	uint8_t length;
+	uint8_t payload[0];
+} __packed;
+
+enum pdu_big_ctrl_type {
+	PDU_BIG_CTRL_TYPE_CHAN_MAP_IND = 0x00,
+	PDU_BIG_CTRL_TYPE_TERM_IND = 0x01,
+};
+
+struct pdu_big_ctrl_chan_map_ind {
+	uint8_t  chm[5];
+	uint16_t instant;
+} __packed;
+
+struct pdu_big_ctrl_term_ind {
+	uint8_t  reason;
+	uint16_t instant;
+} __packed;
+
+
+struct pdu_big_ctrl {
+	uint8_t opcode;
+	union {
+		uint8_t ctrl_data[0];
+		struct pdu_big_ctrl_chan_map_ind chan_map_ind;
+		struct pdu_big_ctrl_term_ind term_ind;
+	} __packed;
+} __packed;
+
+struct pdu_bis {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t ll_id:2;
+	uint8_t cssn:3;
+	uint8_t cstf:1;
+	uint8_t rfu:2;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t rfu:2;
+	uint8_t cstf:1;
+	uint8_t cssn:3;
+	uint8_t ll_id:2;
+#else
+#error "Unsupported endianness"
+#endif /* __BYTE_ORDER__ */
+	uint8_t length;
+	union {
+		uint8_t payload[0];
+		struct pdu_big_ctrl ctrl;
+	} __packed;
+} __packed;
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull.c	(working copy)
@@ -0,0 +1,2009 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <device.h>
+#include <drivers/entropy.h>
+#include <bluetooth/hci.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/cntr.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/mfifo.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "ll_feat.h"
+#include "ll_settings.h"
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_adv.h"
+#include "lll_scan.h"
+#include "lll_sync.h"
+#include "lll_conn.h"
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_sync_types.h"
+#include "ull_conn_types.h"
+#include "ull_filter.h"
+
+#include "ull_internal.h"
+#include "ull_adv_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_sync_internal.h"
+#include "ull_conn_internal.h"
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+#include "ull_vendor.h"
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull
+#include "common/log.h"
+#include "hal/debug.h"
+
+/* Define ticker nodes and user operations */
+#if defined(CONFIG_BT_CTLR_LOW_LAT) && \
+	(CONFIG_BT_CTLR_LLL_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+#define TICKER_USER_LLL_OPS      (3 + 1)
+#else
+#define TICKER_USER_LLL_OPS      (2 + 1)
+#endif /* CONFIG_BT_CTLR_LOW_LAT */
+
+#if !defined(TICKER_USER_ULL_HIGH_VENDOR_OPS)
+#define TICKER_USER_ULL_HIGH_VENDOR_OPS 0
+#endif /* TICKER_USER_ULL_HIGH_VENDOR_OPS */
+
+#define TICKER_USER_ULL_HIGH_OPS (3 + TICKER_USER_ULL_HIGH_VENDOR_OPS + 1)
+#define TICKER_USER_ULL_LOW_OPS  (1 + 1)
+#define TICKER_USER_THREAD_OPS   (1 + 1)
+
+#if defined(CONFIG_BT_BROADCASTER)
+#define BT_ADV_TICKER_NODES ((TICKER_ID_ADV_LAST) - (TICKER_ID_ADV_STOP) + 1)
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+#define BT_ADV_AUX_TICKER_NODES ((TICKER_ID_ADV_AUX_LAST) - \
+				 (TICKER_ID_ADV_AUX_BASE) + 1)
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+#define BT_ADV_SYNC_TICKER_NODES ((TICKER_ID_ADV_SYNC_LAST) - \
+				  (TICKER_ID_ADV_SYNC_BASE) + 1)
+#else /* !CONFIG_BT_CTLR_ADV_PERIODIC */
+#define BT_ADV_SYNC_TICKER_NODES 0
+#endif /* !CONFIG_BT_CTLR_ADV_PERIODIC */
+#else /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+#define BT_ADV_AUX_TICKER_NODES 0
+#define BT_ADV_SYNC_TICKER_NODES 0
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+#else /* !CONFIG_BT_BROADCASTER */
+#define BT_ADV_TICKER_NODES 0
+#define BT_ADV_AUX_TICKER_NODES 0
+#define BT_ADV_SYNC_TICKER_NODES 0
+#endif /* !CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+#define BT_SCAN_TICKER_NODES ((TICKER_ID_SCAN_LAST) - (TICKER_ID_SCAN_STOP) + 1)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#define BT_SCAN_AUX_TICKER_NODES ((TICKER_ID_SCAN_AUX_LAST) - \
+				  (TICKER_ID_SCAN_AUX_BASE) + 1)
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+#define BT_SCAN_SYNC_TICKER_NODES ((TICKER_ID_SCAN_SYNC_LAST) - \
+				   (TICKER_ID_SCAN_SYNC_BASE) + 1)
+#else /* !CONFIG_BT_CTLR_SYNC_PERIODIC */
+#define BT_SCAN_SYNC_TICKER_NODES 0
+#endif /* !CONFIG_BT_CTLR_SYNC_PERIODIC */
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+#define BT_SCAN_AUX_TICKER_NODES 0
+#define BT_SCAN_SYNC_TICKER_NODES 0
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+#else
+#define BT_SCAN_TICKER_NODES 0
+#define BT_SCAN_AUX_TICKER_NODES 0
+#define BT_SCAN_SYNC_TICKER_NODES 0
+#endif
+
+#if defined(CONFIG_BT_CONN)
+#define BT_CONN_TICKER_NODES ((TICKER_ID_CONN_LAST) - (TICKER_ID_CONN_BASE) + 1)
+#else
+#define BT_CONN_TICKER_NODES 0
+#endif
+
+#if defined(CONFIG_SOC_FLASH_NRF_RADIO_SYNC_TICKER)
+#define FLASH_TICKER_NODES        2 /* No. of tickers reserved for flashing */
+#define FLASH_TICKER_USER_APP_OPS 1 /* No. of additional ticker operations */
+#else
+#define FLASH_TICKER_NODES        0
+#define FLASH_TICKER_USER_APP_OPS 0
+#endif
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+#define USER_TICKER_NODES         CONFIG_BT_CTLR_USER_TICKER_ID_RANGE
+#else
+#define USER_TICKER_NODES         0
+#endif
+
+#define TICKER_NODES              (TICKER_ID_ULL_BASE + \
+				   BT_ADV_TICKER_NODES + \
+				   BT_ADV_AUX_TICKER_NODES + \
+				   BT_ADV_SYNC_TICKER_NODES + \
+				   BT_SCAN_TICKER_NODES + \
+				   BT_SCAN_AUX_TICKER_NODES + \
+				   BT_SCAN_SYNC_TICKER_NODES + \
+				   BT_CONN_TICKER_NODES + \
+				   FLASH_TICKER_NODES + \
+				   USER_TICKER_NODES)
+#define TICKER_USER_APP_OPS       (TICKER_USER_THREAD_OPS + \
+				   FLASH_TICKER_USER_APP_OPS)
+#define TICKER_USER_OPS           (TICKER_USER_LLL_OPS + \
+				   TICKER_USER_ULL_HIGH_OPS + \
+				   TICKER_USER_ULL_LOW_OPS + \
+				   TICKER_USER_THREAD_OPS + \
+				   FLASH_TICKER_USER_APP_OPS)
+
+/* Memory for ticker nodes/instances */
+static uint8_t MALIGN(4) ticker_nodes[TICKER_NODES][TICKER_NODE_T_SIZE];
+
+/* Memory for users/contexts operating on ticker module */
+static uint8_t MALIGN(4) ticker_users[MAYFLY_CALLER_COUNT][TICKER_USER_T_SIZE];
+
+/* Memory for user/context simultaneous API operations */
+static uint8_t MALIGN(4) ticker_user_ops[TICKER_USER_OPS][TICKER_USER_OP_T_SIZE];
+
+/* Semaphire to wakeup thread on ticker API callback */
+static struct k_sem sem_ticker_api_cb;
+
+/* Semaphore to wakeup thread on Rx-ed objects */
+static struct k_sem *sem_recv;
+
+/* Declare prepare-event FIFO: mfifo_prep.
+ * Queue of struct node_rx_event_done
+ */
+static MFIFO_DEFINE(prep, sizeof(struct lll_event), EVENT_PIPELINE_MAX);
+
+/* Declare done-event FIFO: mfifo_done.
+ * Queue of pointers to struct node_rx_event_done.
+ * The actual backing behind these pointers is mem_done
+ */
+static MFIFO_DEFINE(done, sizeof(struct node_rx_event_done *), EVENT_DONE_MAX);
+
+/* Backing storage for elements in mfifo_done */
+static struct {
+	void *free;
+	uint8_t pool[sizeof(struct node_rx_event_done) * EVENT_DONE_MAX];
+} mem_done;
+
+static struct {
+	void *free;
+	uint8_t pool[sizeof(memq_link_t) * EVENT_DONE_MAX];
+} mem_link_done;
+
+#if defined(CONFIG_BT_CTLR_PHY) && defined(CONFIG_BT_CTLR_DATA_LENGTH)
+#define LL_PDU_RX_CNT 3
+#else
+#define LL_PDU_RX_CNT 2
+#endif
+
+#define PDU_RX_CNT    (CONFIG_BT_CTLR_RX_BUFFERS + 3)
+#define RX_CNT        (PDU_RX_CNT + LL_PDU_RX_CNT)
+
+static MFIFO_DEFINE(pdu_rx_free, sizeof(void *), PDU_RX_CNT);
+
+#if defined(CONFIG_BT_RX_USER_PDU_LEN)
+#define PDU_RX_USER_PDU_OCTETS_MAX (CONFIG_BT_RX_USER_PDU_LEN)
+#else
+#define PDU_RX_USER_PDU_OCTETS_MAX 0
+#endif
+#define NODE_RX_HEADER_SIZE      (offsetof(struct node_rx_pdu, pdu))
+#define NODE_RX_STRUCT_OVERHEAD  (NODE_RX_HEADER_SIZE)
+
+#define PDU_ADVERTIZE_SIZE (PDU_AC_LL_SIZE_MAX + PDU_AC_LL_SIZE_EXTRA)
+#define PDU_DATA_SIZE      (PDU_DC_LL_HEADER_SIZE + LL_LENGTH_OCTETS_RX_MAX)
+
+#define PDU_RX_NODE_POOL_ELEMENT_SIZE                         \
+	MROUND(                                               \
+		NODE_RX_STRUCT_OVERHEAD                       \
+		+ MAX(MAX(PDU_ADVERTIZE_SIZE,                 \
+			  PDU_DATA_SIZE),                     \
+		      PDU_RX_USER_PDU_OCTETS_MAX)              \
+	)
+
+/* When both central and peripheral are supported, one each Rx node will be
+ * needed by connectable advertising and the initiator to generate connection
+ * complete event, hence conditionally set the count.
+ */
+#if defined(CONFIG_BT_MAX_CONN)
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PERIPHERAL)
+#define BT_CTLR_MAX_CONNECTABLE 2
+#else
+#define BT_CTLR_MAX_CONNECTABLE 1
+#endif
+#define BT_CTLR_MAX_CONN        CONFIG_BT_MAX_CONN
+#else
+#define BT_CTLR_MAX_CONNECTABLE 0
+#define BT_CTLR_MAX_CONN        0
+#endif
+
+#if defined(CONFIG_BT_CTLR_SCAN_SYNC_SET)
+#define BT_CTLR_SCAN_SYNC_SET CONFIG_BT_CTLR_SCAN_SYNC_SET
+#else
+#define BT_CTLR_SCAN_SYNC_SET 0
+#endif
+
+#define PDU_RX_POOL_SIZE (PDU_RX_NODE_POOL_ELEMENT_SIZE * \
+			  (RX_CNT + BT_CTLR_MAX_CONNECTABLE + \
+			   BT_CTLR_ADV_SET + BT_CTLR_SCAN_SYNC_SET))
+
+static struct {
+	void *free;
+	uint8_t pool[PDU_RX_POOL_SIZE];
+} mem_pdu_rx;
+
+/* NOTE: Two memq_link structures are reserved in the case of periodic sync,
+ * one each for sync established and sync lost respectively. Where as in
+ * comparison to a connection, the connection established uses incoming Rx-ed
+ * CONNECT_IND PDU to piggy back generation of connection complete, and hence
+ * only one is reserved for the generation of disconnection event (which can
+ * happen due to supervision timeout and other reasons that dont have an
+ * incoming Rx-ed PDU).
+ */
+#define LINK_RX_POOL_SIZE (sizeof(memq_link_t) * (RX_CNT + 2 + \
+						  BT_CTLR_MAX_CONN + \
+						  BT_CTLR_ADV_SET + \
+						  (BT_CTLR_SCAN_SYNC_SET * 2)))
+static struct {
+	uint8_t quota_pdu; /* Number of un-utilized buffers */
+
+	void *free;
+	uint8_t pool[LINK_RX_POOL_SIZE];
+} mem_link_rx;
+
+static MEMQ_DECLARE(ull_rx);
+static MEMQ_DECLARE(ll_rx);
+
+#if defined(CONFIG_BT_CONN)
+static MFIFO_DEFINE(ll_pdu_rx_free, sizeof(void *), LL_PDU_RX_CNT);
+static MFIFO_DEFINE(tx_ack, sizeof(struct lll_tx),
+		    CONFIG_BT_CTLR_TX_BUFFERS);
+
+static void *mark_update;
+#endif /* CONFIG_BT_CONN */
+
+static void *mark_disable;
+
+static inline int init_reset(void);
+static void perform_lll_reset(void *param);
+static inline void *mark_set(void **m, void *param);
+static inline void *mark_unset(void **m, void *param);
+static inline void *mark_get(void *m);
+static inline void done_alloc(void);
+static inline void rx_alloc(uint8_t max);
+static void rx_demux(void *param);
+#if defined(CONFIG_BT_CONN)
+static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last);
+static inline void rx_demux_conn_tx_ack(uint8_t ack_last, uint16_t handle,
+					memq_link_t *link,
+					struct node_tx *node_tx);
+#endif /* CONFIG_BT_CONN */
+static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx);
+static inline void rx_demux_event_done(memq_link_t *link,
+				       struct node_rx_hdr *rx);
+static inline void ll_rx_link_inc_quota(int8_t delta);
+static void disabled_cb(void *param);
+
+int ll_init(struct k_sem *sem_rx)
+{
+	int err;
+
+	/* Store the semaphore to be used to wakeup Thread context */
+	sem_recv = sem_rx;
+
+	/* Initialize counter */
+	/* TODO: Bind and use counter driver? */
+	cntr_init();
+
+	/* Initialize Mayfly */
+	mayfly_init();
+
+	/* Initialize Ticker */
+	ticker_users[MAYFLY_CALL_ID_0][0] = TICKER_USER_LLL_OPS;
+	ticker_users[MAYFLY_CALL_ID_1][0] = TICKER_USER_ULL_HIGH_OPS;
+	ticker_users[MAYFLY_CALL_ID_2][0] = TICKER_USER_ULL_LOW_OPS;
+	ticker_users[MAYFLY_CALL_ID_PROGRAM][0] = TICKER_USER_APP_OPS;
+
+	err = ticker_init(TICKER_INSTANCE_ID_CTLR,
+			  TICKER_NODES, &ticker_nodes[0],
+			  MAYFLY_CALLER_COUNT, &ticker_users[0],
+			  TICKER_USER_OPS, &ticker_user_ops[0],
+			  hal_ticker_instance0_caller_id_get,
+			  hal_ticker_instance0_sched,
+			  hal_ticker_instance0_trigger_set);
+	LL_ASSERT(!err);
+
+	/* Initialize semaphore for ticker API blocking wait */
+	k_sem_init(&sem_ticker_api_cb, 0, 1);
+
+	/* Initialize LLL */
+	err = lll_init();
+	if (err) {
+		return err;
+	}
+
+	/* Initialize ULL internals */
+	/* TODO: globals? */
+
+	/* Common to init and reset */
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+#if defined(CONFIG_BT_BROADCASTER)
+	err = lll_adv_init();
+	if (err) {
+		return err;
+	}
+
+	err = ull_adv_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	err = lll_scan_init();
+	if (err) {
+		return err;
+	}
+
+	err = ull_scan_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	err = lll_sync_init();
+	if (err) {
+		return err;
+	}
+
+	err = ull_sync_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+#if defined(CONFIG_BT_CONN)
+	err = lll_conn_init();
+	if (err) {
+		return err;
+	}
+
+	err = ull_conn_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	err = ull_user_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+	/* reset whitelist, resolving list and initialise RPA timeout*/
+	if (IS_ENABLED(CONFIG_BT_CTLR_FILTER)) {
+		ull_filter_reset(true);
+	}
+
+	return  0;
+}
+
+void ll_reset(void)
+{
+	int err;
+
+#if defined(CONFIG_BT_BROADCASTER)
+	/* Reset adv state */
+	err = ull_adv_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	/* Reset scan state */
+	err = ull_scan_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	/* Reset periodic sync sets */
+	err = ull_sync_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+	/* Reset initiator */
+	{
+		void *rx;
+
+		err = ll_connect_disable(&rx);
+		if (!err) {
+			struct ll_scan_set *scan;
+
+			scan = ull_scan_is_enabled_get(0);
+			LL_ASSERT(scan);
+
+			scan->is_enabled = 0U;
+			scan->lll.conn = NULL;
+		}
+
+		ARG_UNUSED(rx);
+	}
+#endif /* CONFIG_BT_CENTRAL */
+
+	/* Reset conn role */
+	err = ull_conn_reset();
+	LL_ASSERT(!err);
+
+	MFIFO_INIT(tx_ack);
+#endif /* CONFIG_BT_CONN */
+
+	/* reset whitelist and resolving list */
+	if (IS_ENABLED(CONFIG_BT_CTLR_FILTER)) {
+		ull_filter_reset(false);
+	}
+
+	/* Re-initialize ULL internals */
+
+	/* Re-initialize the prep mfifo */
+	MFIFO_INIT(prep);
+
+	/* Re-initialize the free done mfifo */
+	MFIFO_INIT(done);
+
+	/* Re-initialize the free rx mfifo */
+	MFIFO_INIT(pdu_rx_free);
+
+#if defined(CONFIG_BT_CONN)
+	/* Re-initialize the free ll rx mfifo */
+	MFIFO_INIT(ll_pdu_rx_free);
+#endif /* CONFIG_BT_CONN */
+
+	/* Reset LLL via mayfly */
+	{
+		static memq_link_t link;
+		static struct mayfly mfy = {0, 0, &link, NULL,
+					    perform_lll_reset};
+		uint32_t retval;
+
+		/* NOTE: If Zero Latency Interrupt is used, then LLL context
+		 *       will be the highest priority IRQ in the system, hence
+		 *       mayfly_enqueue will be done running the callee inline
+		 *       (vector to the callee function) in this function. Else
+		 *       we use semaphore to wait for perform_lll_reset to
+		 *       complete.
+		 */
+
+#if !defined(CONFIG_BT_CTLR_ZLI)
+		struct k_sem sem;
+
+		k_sem_init(&sem, 0, 1);
+		mfy.param = &sem;
+#endif /* !CONFIG_BT_CTLR_ZLI */
+
+		retval = mayfly_enqueue(TICKER_USER_ID_THREAD,
+					TICKER_USER_ID_LLL, 0, &mfy);
+		LL_ASSERT(!retval);
+
+#if !defined(CONFIG_BT_CTLR_ZLI)
+		/* LLL reset must complete before returning - wait for
+		 * reset completion in LLL mayfly thread
+		 */
+		k_sem_take(&sem, K_FOREVER);
+#endif /* !CONFIG_BT_CTLR_ZLI */
+	}
+
+	/* Common to init and reset */
+	err = init_reset();
+	LL_ASSERT(!err);
+}
+
+/**
+ * @brief Peek the next node_rx to send up to Host
+ * @details Tightly coupled with prio_recv_thread()
+ *   Execution context: Controller thread
+ *
+ * @param node_rx[out]   Pointer to rx node at head of queue
+ * @param handle[out]    Connection handle
+ * @return TX completed
+ */
+uint8_t ll_rx_get(void **node_rx, uint16_t *handle)
+{
+	struct node_rx_hdr *rx;
+	memq_link_t *link;
+	uint8_t cmplt = 0U;
+
+#if defined(CONFIG_BT_CONN)
+ll_rx_get_again:
+#endif /* CONFIG_BT_CONN */
+
+	*node_rx = NULL;
+
+	link = memq_peek(memq_ll_rx.head, memq_ll_rx.tail, (void **)&rx);
+	if (link) {
+#if defined(CONFIG_BT_CONN)
+		cmplt = tx_cmplt_get(handle, &mfifo_tx_ack.f, rx->ack_last);
+		if (!cmplt) {
+			uint8_t f, cmplt_prev, cmplt_curr;
+			uint16_t h;
+
+			cmplt_curr = 0U;
+			f = mfifo_tx_ack.f;
+			do {
+				cmplt_prev = cmplt_curr;
+				cmplt_curr = tx_cmplt_get(&h, &f,
+							  mfifo_tx_ack.l);
+			} while ((cmplt_prev != 0U) ||
+				 (cmplt_prev != cmplt_curr));
+
+			/* Do not send up buffers to Host thread that are
+			 * marked for release
+			 */
+			if (rx->type == NODE_RX_TYPE_DC_PDU_RELEASE) {
+				(void)memq_dequeue(memq_ll_rx.tail,
+						   &memq_ll_rx.head, NULL);
+				mem_release(link, &mem_link_rx.free);
+
+				ll_rx_link_inc_quota(1);
+
+				mem_release(rx, &mem_pdu_rx.free);
+
+				rx_alloc(1);
+
+				goto ll_rx_get_again;
+			}
+#endif /* CONFIG_BT_CONN */
+
+			*node_rx = rx;
+
+#if defined(CONFIG_BT_CONN)
+		}
+	} else {
+		cmplt = tx_cmplt_get(handle, &mfifo_tx_ack.f, mfifo_tx_ack.l);
+#endif /* CONFIG_BT_CONN */
+	}
+
+	return cmplt;
+}
+
+/**
+ * @brief Commit the dequeue from memq_ll_rx, where ll_rx_get() did the peek
+ * @details Execution context: Controller thread
+ */
+void ll_rx_dequeue(void)
+{
+	struct node_rx_hdr *rx = NULL;
+	memq_link_t *link;
+
+	link = memq_dequeue(memq_ll_rx.tail, &memq_ll_rx.head,
+			    (void **)&rx);
+	LL_ASSERT(link);
+
+	mem_release(link, &mem_link_rx.free);
+
+	/* handle object specific clean up */
+	switch (rx->type) {
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_OBSERVER)
+	case NODE_RX_TYPE_EXT_1M_REPORT:
+	case NODE_RX_TYPE_EXT_2M_REPORT:
+	case NODE_RX_TYPE_EXT_CODED_REPORT:
+	{
+		struct node_rx_hdr *rx_curr;
+		struct pdu_adv *adv;
+
+		adv = (void *)((struct node_rx_pdu *)rx)->pdu;
+		if (adv->type != PDU_ADV_TYPE_EXT_IND) {
+			break;
+		}
+
+		rx_curr = rx->rx_ftr.extra;
+		while (rx_curr) {
+			memq_link_t *link_free;
+
+			link_free = rx_curr->link;
+			rx_curr = rx_curr->rx_ftr.extra;
+
+			mem_release(link_free, &mem_link_rx.free);
+		}
+	}
+	break;
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_BROADCASTER)
+	case NODE_RX_TYPE_EXT_ADV_TERMINATE:
+	{
+		struct ll_adv_set *adv;
+
+		adv = ull_adv_set_get(rx->handle);
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		struct lll_conn *lll_conn = adv->lll.conn;
+
+		if (!lll_conn) {
+			adv->is_enabled = 0U;
+
+			break;
+		}
+
+		LL_ASSERT(!lll_conn->link_tx_free);
+
+		memq_link_t *link = memq_deinit(&lll_conn->memq_tx.head,
+						&lll_conn->memq_tx.tail);
+		LL_ASSERT(link);
+
+		lll_conn->link_tx_free = link;
+
+		struct ll_conn *conn = (void *)HDR_LLL2EVT(lll_conn);
+
+		ll_conn_release(conn);
+		adv->lll.conn = NULL;
+
+		ll_rx_release(adv->node_rx_cc_free);
+		adv->node_rx_cc_free = NULL;
+
+		ll_rx_link_release(adv->link_cc_free);
+		adv->link_cc_free = NULL;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+		adv->is_enabled = 0U;
+	}
+	break;
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CONN)
+	case NODE_RX_TYPE_CONNECTION:
+	{
+		struct node_rx_cc *cc = (void *)((struct node_rx_pdu *)rx)->pdu;
+		struct node_rx_ftr *ftr = &(rx->rx_ftr);
+
+		if (0) {
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		} else if ((cc->status == BT_HCI_ERR_ADV_TIMEOUT) || cc->role) {
+			struct lll_adv *lll = ftr->param;
+			struct ll_adv_set *adv = (void *)HDR_LLL2EVT(lll);
+
+			if (cc->status == BT_HCI_ERR_ADV_TIMEOUT) {
+				struct lll_conn *conn_lll;
+				struct ll_conn *conn;
+				memq_link_t *link;
+
+				conn_lll = lll->conn;
+				LL_ASSERT(conn_lll);
+				lll->conn = NULL;
+
+				LL_ASSERT(!conn_lll->link_tx_free);
+				link = memq_deinit(&conn_lll->memq_tx.head,
+						   &conn_lll->memq_tx.tail);
+				LL_ASSERT(link);
+				conn_lll->link_tx_free = link;
+
+				conn = (void *)HDR_LLL2EVT(conn_lll);
+				ll_conn_release(conn);
+			} else {
+				/* Release un-utilized node rx */
+				if (adv->node_rx_cc_free) {
+					void *rx_free;
+
+					rx_free = adv->node_rx_cc_free;
+					adv->node_rx_cc_free = NULL;
+
+					mem_release(rx_free, &mem_pdu_rx.free);
+				}
+			}
+
+			adv->is_enabled = 0U;
+#else /* !CONFIG_BT_PERIPHERAL */
+			ARG_UNUSED(cc);
+#endif /* !CONFIG_BT_PERIPHERAL */
+
+		} else if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+			struct lll_scan *lll = ftr->param;
+			struct ll_scan_set *scan = (void *)HDR_LLL2EVT(lll);
+
+			scan->is_enabled = 0U;
+		} else {
+			LL_ASSERT(0);
+		}
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_PRIVACY)) {
+			uint8_t bm;
+
+			/* FIXME: use the correct adv and scan set to get
+			 * enabled status bitmask
+			 */
+			bm = (IS_ENABLED(CONFIG_BT_OBSERVER) &&
+			      (ull_scan_is_enabled(0) << 1)) |
+			     (IS_ENABLED(CONFIG_BT_BROADCASTER) &&
+			      ull_adv_is_enabled(0));
+
+			if (!bm) {
+				ull_filter_adv_scan_state_cb(0);
+			}
+		}
+	}
+	break;
+
+	case NODE_RX_TYPE_TERMINATE:
+	case NODE_RX_TYPE_DC_PDU:
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_OBSERVER)
+	case NODE_RX_TYPE_REPORT:
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+		/* fall through */
+	case NODE_RX_TYPE_SYNC:
+	case NODE_RX_TYPE_SYNC_LOST:
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	case NODE_RX_TYPE_SCAN_REQ:
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CONN)
+	case NODE_RX_TYPE_CONN_UPDATE:
+	case NODE_RX_TYPE_ENC_REFRESH:
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	case NODE_RX_TYPE_APTO:
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	case NODE_RX_TYPE_CHAN_SEL_ALGO:
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case NODE_RX_TYPE_PHY_UPDATE:
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+	case NODE_RX_TYPE_RSSI:
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	case NODE_RX_TYPE_PROFILE:
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	case NODE_RX_TYPE_ADV_INDICATION:
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	case NODE_RX_TYPE_SCAN_INDICATION:
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	case NODE_RX_TYPE_MESH_ADV_CPLT:
+	case NODE_RX_TYPE_MESH_REPORT:
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	case NODE_RX_TYPE_USER_START ... NODE_RX_TYPE_USER_END:
+		__fallthrough;
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+	/* Ensure that at least one 'case' statement is present for this
+	 * code block.
+	 */
+	case NODE_RX_TYPE_NONE:
+		LL_ASSERT(rx->type != NODE_RX_TYPE_NONE);
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	/* FIXME: clean up when porting Mesh Ext. */
+	if (0) {
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	} else if (rx->type == NODE_RX_TYPE_MESH_ADV_CPLT) {
+		struct ll_adv_set *adv;
+		struct ll_scan_set *scan;
+
+		adv = ull_adv_is_enabled_get(0);
+		LL_ASSERT(adv);
+		adv->is_enabled = 0U;
+
+		scan = ull_scan_is_enabled_get(0);
+		LL_ASSERT(scan);
+
+		scan->is_enabled = 0U;
+
+		ll_adv_scan_state_cb(0);
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+	}
+}
+
+void ll_rx_mem_release(void **node_rx)
+{
+	struct node_rx_hdr *rx;
+
+	rx = *node_rx;
+	while (rx) {
+		struct node_rx_hdr *rx_free;
+
+		rx_free = rx;
+		rx = rx->next;
+
+		switch (rx_free->type) {
+#if defined(CONFIG_BT_BROADCASTER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		case NODE_RX_TYPE_EXT_ADV_TERMINATE:
+			mem_release(rx_free, &mem_pdu_rx.free);
+			break;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_CONN)
+		case NODE_RX_TYPE_CONNECTION:
+		{
+			struct node_rx_cc *cc =
+				(void *)((struct node_rx_pdu *)rx_free)->pdu;
+
+			if (0) {
+
+#if defined(CONFIG_BT_PERIPHERAL)
+			} else if (cc->status == BT_HCI_ERR_ADV_TIMEOUT) {
+				mem_release(rx_free, &mem_pdu_rx.free);
+
+				break;
+#endif /* !CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CENTRAL)
+			} else if (cc->status == BT_HCI_ERR_UNKNOWN_CONN_ID) {
+				struct node_rx_ftr *ftr = &rx_free->rx_ftr;
+				struct ll_scan_set *scan =
+					(void *)HDR_LLL2EVT(ftr->param);
+				struct lll_conn *conn_lll;
+				struct ll_conn *conn;
+				memq_link_t *link;
+
+				conn_lll = scan->lll.conn;
+				LL_ASSERT(conn_lll);
+				scan->lll.conn = NULL;
+
+				LL_ASSERT(!conn_lll->link_tx_free);
+				link = memq_deinit(&conn_lll->memq_tx.head,
+						   &conn_lll->memq_tx.tail);
+				LL_ASSERT(link);
+				conn_lll->link_tx_free = link;
+
+				conn = (void *)HDR_LLL2EVT(conn_lll);
+				ll_conn_release(conn);
+
+				scan->is_enabled = 0U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#if defined(CONFIG_BT_BROADCASTER)
+				if (!ull_adv_is_enabled_get(0))
+#endif /* CONFIG_BT_BROADCASTER */
+				{
+					ull_filter_adv_scan_state_cb(0);
+				}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+				break;
+#endif /* CONFIG_BT_CENTRAL */
+
+			} else {
+				LL_ASSERT(!cc->status);
+			}
+		}
+
+		__fallthrough;
+		case NODE_RX_TYPE_DC_PDU:
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_OBSERVER)
+		case NODE_RX_TYPE_REPORT:
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+			__fallthrough;
+		case NODE_RX_TYPE_EXT_1M_REPORT:
+		case NODE_RX_TYPE_EXT_2M_REPORT:
+		case NODE_RX_TYPE_EXT_CODED_REPORT:
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+		case NODE_RX_TYPE_SCAN_REQ:
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CONN)
+		case NODE_RX_TYPE_CONN_UPDATE:
+		case NODE_RX_TYPE_ENC_REFRESH:
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		case NODE_RX_TYPE_APTO:
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+		case NODE_RX_TYPE_CHAN_SEL_ALGO:
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		case NODE_RX_TYPE_PHY_UPDATE:
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+		case NODE_RX_TYPE_RSSI:
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+		case NODE_RX_TYPE_PROFILE:
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+		case NODE_RX_TYPE_ADV_INDICATION:
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+		case NODE_RX_TYPE_SCAN_INDICATION:
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+		case NODE_RX_TYPE_MESH_ADV_CPLT:
+		case NODE_RX_TYPE_MESH_REPORT:
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+		case NODE_RX_TYPE_USER_START ... NODE_RX_TYPE_USER_END:
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+		/* Ensure that at least one 'case' statement is present for this
+		 * code block.
+		 */
+		case NODE_RX_TYPE_NONE:
+			LL_ASSERT(rx_free->type != NODE_RX_TYPE_NONE);
+			ll_rx_link_inc_quota(1);
+			mem_release(rx_free, &mem_pdu_rx.free);
+			break;
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+		case NODE_RX_TYPE_SYNC:
+		{
+			struct node_rx_sync *se =
+				(void *)((struct node_rx_pdu *)rx_free)->pdu;
+
+			if (!se->status) {
+				mem_release(rx_free, &mem_pdu_rx.free);
+
+				break;
+			}
+		}
+		/* Pass through */
+
+		case NODE_RX_TYPE_SYNC_LOST:
+		{
+			struct ll_sync_set *sync =
+				(void *)rx_free->rx_ftr.param;
+
+			sync->timeout_reload = 0U;
+
+			ull_sync_release(sync);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+#if defined(CONFIG_BT_CONN)
+		case NODE_RX_TYPE_TERMINATE:
+		{
+			struct ll_conn *conn;
+			memq_link_t *link;
+
+			conn = ll_conn_get(rx_free->handle);
+
+			LL_ASSERT(!conn->lll.link_tx_free);
+			link = memq_deinit(&conn->lll.memq_tx.head,
+					   &conn->lll.memq_tx.tail);
+			LL_ASSERT(link);
+			conn->lll.link_tx_free = link;
+
+			ll_conn_release(conn);
+		}
+		break;
+#endif /* CONFIG_BT_CONN */
+
+		case NODE_RX_TYPE_EVENT_DONE:
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+	}
+
+	*node_rx = rx;
+
+	rx_alloc(UINT8_MAX);
+}
+
+static inline void ll_rx_link_inc_quota(int8_t delta)
+{
+	LL_ASSERT(delta <= 0 || mem_link_rx.quota_pdu < RX_CNT);
+	mem_link_rx.quota_pdu += delta;
+}
+
+void *ll_rx_link_alloc(void)
+{
+	return mem_acquire(&mem_link_rx.free);
+}
+
+void ll_rx_link_release(void *link)
+{
+	mem_release(link, &mem_link_rx.free);
+}
+
+void *ll_rx_alloc(void)
+{
+	return mem_acquire(&mem_pdu_rx.free);
+}
+
+void ll_rx_release(void *node_rx)
+{
+	mem_release(node_rx, &mem_pdu_rx.free);
+}
+
+void ll_rx_put(memq_link_t *link, void *rx)
+{
+	struct node_rx_hdr *rx_hdr = rx;
+
+	/* Serialize Tx ack with Rx enqueue by storing reference to
+	 * last element index in Tx ack FIFO.
+	 */
+#if defined(CONFIG_BT_CONN)
+	rx_hdr->ack_last = mfifo_tx_ack.l;
+#else /* !CONFIG_BT_CONN */
+	ARG_UNUSED(rx_hdr);
+#endif /* !CONFIG_BT_CONN */
+
+	/* Enqueue the Rx object */
+	memq_enqueue(link, rx, &memq_ll_rx.tail);
+}
+
+/**
+ * @brief Permit another loop in the controller thread (prio_recv_thread)
+ * @details Execution context: ULL mayfly
+ */
+void ll_rx_sched(void)
+{
+	/* sem_recv references the same semaphore (sem_prio_recv)
+	 * in prio_recv_thread
+	 */
+	k_sem_give(sem_recv);
+}
+
+#if defined(CONFIG_BT_CONN)
+void *ll_pdu_rx_alloc_peek(uint8_t count)
+{
+	if (count > MFIFO_AVAIL_COUNT_GET(ll_pdu_rx_free)) {
+		return NULL;
+	}
+
+	return MFIFO_DEQUEUE_PEEK(ll_pdu_rx_free);
+}
+
+void *ll_pdu_rx_alloc(void)
+{
+	return MFIFO_DEQUEUE(ll_pdu_rx_free);
+}
+
+void ll_tx_ack_put(uint16_t handle, struct node_tx *node_tx)
+{
+	struct lll_tx *tx;
+	uint8_t idx;
+
+	idx = MFIFO_ENQUEUE_GET(tx_ack, (void **)&tx);
+	LL_ASSERT(tx);
+
+	tx->handle = handle;
+	tx->node = node_tx;
+
+	MFIFO_ENQUEUE(tx_ack, idx);
+}
+#endif /* CONFIG_BT_CONN */
+
+void ll_timeslice_ticker_id_get(uint8_t * const instance_index,
+				uint8_t * const user_id)
+{
+	*instance_index = TICKER_INSTANCE_ID_CTLR;
+	*user_id = (TICKER_NODES - FLASH_TICKER_NODES);
+}
+
+void ll_radio_state_abort(void)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_disable};
+	uint32_t ret;
+
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL, 0,
+			     &mfy);
+	LL_ASSERT(!ret);
+}
+
+uint32_t ll_radio_state_is_idle(void)
+{
+	return lll_radio_is_idle();
+}
+
+void ull_ticker_status_give(uint32_t status, void *param)
+{
+	*((uint32_t volatile *)param) = status;
+
+	k_sem_give(&sem_ticker_api_cb);
+}
+
+uint32_t ull_ticker_status_take(uint32_t ret, uint32_t volatile *ret_cb)
+{
+	if (ret == TICKER_STATUS_BUSY) {
+		/* TODO: Enable ticker job in case of CONFIG_BT_CTLR_LOW_LAT */
+	} else {
+		/* Check for ticker operation enqueue failed, in which case
+		 * function return value (ret) will be TICKER_STATUS_FAILURE
+		 * and callback return value (ret_cb) will remain as
+		 * TICKER_STATUS_BUSY.
+		 * This assert check will avoid waiting forever to take the
+		 * semaphore that will never be given when the ticker operation
+		 * callback does not get called due to enqueue failure.
+		 */
+		LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+			  (*ret_cb != TICKER_STATUS_BUSY));
+	}
+
+	k_sem_take(&sem_ticker_api_cb, K_FOREVER);
+
+	return *ret_cb;
+}
+
+void *ull_disable_mark(void *param)
+{
+	return mark_set(&mark_disable, param);
+}
+
+void *ull_disable_unmark(void *param)
+{
+	return mark_unset(&mark_disable, param);
+}
+
+void *ull_disable_mark_get(void)
+{
+	return mark_get(mark_disable);
+}
+
+#if defined(CONFIG_BT_CONN)
+void *ull_update_mark(void *param)
+{
+	return mark_set(&mark_update, param);
+}
+
+void *ull_update_unmark(void *param)
+{
+	return mark_unset(&mark_update, param);
+}
+
+void *ull_update_mark_get(void)
+{
+	return mark_get(mark_update);
+}
+#endif /* CONFIG_BT_CONN */
+
+int ull_disable(void *lll)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_disable};
+	struct ull_hdr *hdr;
+	struct k_sem sem;
+	uint32_t ret;
+
+	hdr = HDR_ULL(((struct lll_hdr *)lll)->parent);
+	if (!hdr) {
+		return ULL_STATUS_SUCCESS;
+	}
+
+	k_sem_init(&sem, 0, 1);
+
+	hdr->disabled_param = &sem;
+	hdr->disabled_cb = disabled_cb;
+
+	if (!ull_ref_get(hdr)) {
+		return ULL_STATUS_SUCCESS;
+	}
+
+	mfy.param = lll;
+	ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0,
+			     &mfy);
+	LL_ASSERT(!ret);
+
+	return k_sem_take(&sem, K_FOREVER);
+}
+
+void *ull_pdu_rx_alloc_peek(uint8_t count)
+{
+	if (count > MFIFO_AVAIL_COUNT_GET(pdu_rx_free)) {
+		return NULL;
+	}
+
+	return MFIFO_DEQUEUE_PEEK(pdu_rx_free);
+}
+
+void *ull_pdu_rx_alloc_peek_iter(uint8_t *idx)
+{
+	return *(void **)MFIFO_DEQUEUE_ITER_GET(pdu_rx_free, idx);
+}
+
+void *ull_pdu_rx_alloc(void)
+{
+	return MFIFO_DEQUEUE(pdu_rx_free);
+}
+
+void ull_rx_put(memq_link_t *link, void *rx)
+{
+	struct node_rx_hdr *rx_hdr = rx;
+
+	/* Serialize Tx ack with Rx enqueue by storing reference to
+	 * last element index in Tx ack FIFO.
+	 */
+#if defined(CONFIG_BT_CONN)
+	rx_hdr->ack_last = ull_conn_ack_last_idx_get();
+#else
+	ARG_UNUSED(rx_hdr);
+#endif
+
+	/* Enqueue the Rx object */
+	memq_enqueue(link, rx, &memq_ull_rx.tail);
+}
+
+void ull_rx_sched(void)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, rx_demux};
+
+	/* Kick the ULL (using the mayfly, tailchain it) */
+	mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_HIGH, 1, &mfy);
+}
+
+int ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb,
+			lll_abort_cb_t abort_cb,
+			struct lll_prepare_param *prepare_param,
+			lll_prepare_cb_t prepare_cb, int prio,
+			uint8_t is_resume)
+{
+	struct lll_event *e;
+	uint8_t idx;
+
+	idx = MFIFO_ENQUEUE_GET(prep, (void **)&e);
+	if (!e) {
+		return -ENOBUFS;
+	}
+
+	memcpy(&e->prepare_param, prepare_param, sizeof(e->prepare_param));
+	e->prepare_cb = prepare_cb;
+	e->is_abort_cb = is_abort_cb;
+	e->abort_cb = abort_cb;
+	e->prio = prio;
+	e->is_resume = is_resume;
+	e->is_aborted = 0U;
+
+	MFIFO_ENQUEUE(prep, idx);
+
+	return 0;
+}
+
+void *ull_prepare_dequeue_get(void)
+{
+	return MFIFO_DEQUEUE_GET(prep);
+}
+
+void *ull_prepare_dequeue_iter(uint8_t *idx)
+{
+	return MFIFO_DEQUEUE_ITER_GET(prep, idx);
+}
+
+void *ull_event_done_extra_get(void)
+{
+	struct node_rx_event_done *evdone;
+
+	evdone = MFIFO_DEQUEUE_PEEK(done);
+	if (!evdone) {
+		return NULL;
+	}
+
+	return &evdone->extra;
+}
+
+void *ull_event_done(void *param)
+{
+	struct node_rx_event_done *evdone;
+	memq_link_t *link;
+
+	/* Obtain new node that signals "Done of an RX-event".
+	 * Obtain this by dequeuing from the global 'mfifo_done' queue.
+	 * Note that 'mfifo_done' is a queue of pointers, not of
+	 * struct node_rx_event_done
+	 */
+	evdone = MFIFO_DEQUEUE(done);
+	if (!evdone) {
+		/* Not fatal if we can not obtain node, though
+		 * we will loose the packets in software stack.
+		 * If this happens during Conn Upd, this could cause LSTO
+		 */
+		return NULL;
+	}
+
+	link = evdone->hdr.link;
+	evdone->hdr.link = NULL;
+
+	evdone->hdr.type = NODE_RX_TYPE_EVENT_DONE;
+	evdone->param = param;
+
+	ull_rx_put(link, evdone);
+	ull_rx_sched();
+
+	return evdone;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL) || defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+/**
+ * @brief Extract timing from completed event
+ *
+ * @param node_rx_event_done[in] Done event containing fresh timing information
+ * @param ticks_drift_plus[out]  Positive part of drift uncertainty window
+ * @param ticks_drift_minus[out] Negative part of drift uncertainty window
+ */
+void ull_drift_ticks_get(struct node_rx_event_done *done,
+			 uint32_t *ticks_drift_plus,
+			 uint32_t *ticks_drift_minus)
+{
+	uint32_t start_to_address_expected_us;
+	uint32_t start_to_address_actual_us;
+	uint32_t window_widening_event_us;
+	uint32_t preamble_to_addr_us;
+
+	start_to_address_actual_us =
+		done->extra.drift.start_to_address_actual_us;
+	window_widening_event_us =
+		done->extra.drift.window_widening_event_us;
+	preamble_to_addr_us =
+		done->extra.drift.preamble_to_addr_us;
+
+	start_to_address_expected_us = EVENT_JITTER_US +
+				       EVENT_TICKER_RES_MARGIN_US +
+				       window_widening_event_us +
+				       preamble_to_addr_us;
+
+	if (start_to_address_actual_us <= start_to_address_expected_us) {
+		*ticks_drift_plus =
+			HAL_TICKER_US_TO_TICKS(window_widening_event_us);
+		*ticks_drift_minus =
+			HAL_TICKER_US_TO_TICKS((start_to_address_expected_us -
+					       start_to_address_actual_us));
+	} else {
+		*ticks_drift_plus =
+			HAL_TICKER_US_TO_TICKS(start_to_address_actual_us);
+		*ticks_drift_minus =
+			HAL_TICKER_US_TO_TICKS(EVENT_JITTER_US +
+					       EVENT_TICKER_RES_MARGIN_US +
+					       preamble_to_addr_us);
+	}
+}
+#endif /* CONFIG_BT_PERIPHERAL || CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+static inline int init_reset(void)
+{
+	memq_link_t *link;
+
+	/* Initialize done pool. */
+	mem_init(mem_done.pool, sizeof(struct node_rx_event_done),
+		 EVENT_DONE_MAX, &mem_done.free);
+
+	/* Initialize done link pool. */
+	mem_init(mem_link_done.pool, sizeof(memq_link_t), EVENT_DONE_MAX,
+		 &mem_link_done.free);
+
+	/* Allocate done buffers */
+	done_alloc();
+
+	/* Initialize rx pool. */
+	mem_init(mem_pdu_rx.pool, (PDU_RX_NODE_POOL_ELEMENT_SIZE),
+		 sizeof(mem_pdu_rx.pool) / (PDU_RX_NODE_POOL_ELEMENT_SIZE),
+		 &mem_pdu_rx.free);
+
+	/* Initialize rx link pool. */
+	mem_init(mem_link_rx.pool, sizeof(memq_link_t),
+		 sizeof(mem_link_rx.pool) / sizeof(memq_link_t),
+		 &mem_link_rx.free);
+
+	/* Acquire a link to initialize ull rx memq */
+	link = mem_acquire(&mem_link_rx.free);
+	LL_ASSERT(link);
+
+	/* Initialize ull rx memq */
+	MEMQ_INIT(ull_rx, link);
+
+	/* Acquire a link to initialize ll rx memq */
+	link = mem_acquire(&mem_link_rx.free);
+	LL_ASSERT(link);
+
+	/* Initialize ll rx memq */
+	MEMQ_INIT(ll_rx, link);
+
+	/* Allocate rx free buffers */
+	mem_link_rx.quota_pdu = RX_CNT;
+	rx_alloc(UINT8_MAX);
+
+	return 0;
+}
+
+static void perform_lll_reset(void *param)
+{
+	int err;
+
+	/* Reset LLL */
+	err = lll_reset();
+	LL_ASSERT(!err);
+
+#if defined(CONFIG_BT_BROADCASTER)
+	/* Reset adv state */
+	err = lll_adv_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	/* Reset scan state */
+	err = lll_scan_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+	/* Reset conn role */
+	err = lll_conn_reset();
+	LL_ASSERT(!err);
+#endif /* CONFIG_BT_CONN */
+
+#if !defined(CONFIG_BT_CTLR_ZLI)
+	k_sem_give(param);
+#endif /* !CONFIG_BT_CTLR_ZLI */
+}
+
+static inline void *mark_set(void **m, void *param)
+{
+	if (!*m) {
+		*m = param;
+	}
+
+	return *m;
+}
+
+static inline void *mark_unset(void **m, void *param)
+{
+	if (*m && *m == param) {
+		*m = NULL;
+
+		return param;
+	}
+
+	return NULL;
+}
+
+static inline void *mark_get(void *m)
+{
+	return m;
+}
+
+/**
+ * @brief Allocate buffers for done events
+ */
+static inline void done_alloc(void)
+{
+	uint8_t idx;
+
+	/* mfifo_done is a queue of pointers */
+	while (MFIFO_ENQUEUE_IDX_GET(done, &idx)) {
+		memq_link_t *link;
+		struct node_rx_hdr *rx;
+
+		link = mem_acquire(&mem_link_done.free);
+		if (!link) {
+			break;
+		}
+
+		rx = mem_acquire(&mem_done.free);
+		if (!rx) {
+			mem_release(link, &mem_link_done.free);
+			break;
+		}
+
+		rx->link = link;
+
+		MFIFO_BY_IDX_ENQUEUE(done, idx, rx);
+	}
+}
+
+static inline void *done_release(memq_link_t *link,
+				 struct node_rx_event_done *done)
+{
+	uint8_t idx;
+
+	if (!MFIFO_ENQUEUE_IDX_GET(done, &idx)) {
+		return NULL;
+	}
+
+	done->hdr.link = link;
+
+	MFIFO_BY_IDX_ENQUEUE(done, idx, done);
+
+	return done;
+}
+
+static inline void rx_alloc(uint8_t max)
+{
+	uint8_t idx;
+
+#if defined(CONFIG_BT_CONN)
+	while (mem_link_rx.quota_pdu &&
+	       MFIFO_ENQUEUE_IDX_GET(ll_pdu_rx_free, &idx)) {
+		memq_link_t *link;
+		struct node_rx_hdr *rx;
+
+		link = mem_acquire(&mem_link_rx.free);
+		if (!link) {
+			break;
+		}
+
+		rx = mem_acquire(&mem_pdu_rx.free);
+		if (!rx) {
+			mem_release(link, &mem_link_rx.free);
+			break;
+		}
+
+		link->mem = NULL;
+		rx->link = link;
+
+		MFIFO_BY_IDX_ENQUEUE(ll_pdu_rx_free, idx, rx);
+
+		ll_rx_link_inc_quota(-1);
+	}
+#endif /* CONFIG_BT_CONN */
+
+	if (max > mem_link_rx.quota_pdu) {
+		max = mem_link_rx.quota_pdu;
+	}
+
+	while ((max--) && MFIFO_ENQUEUE_IDX_GET(pdu_rx_free, &idx)) {
+		memq_link_t *link;
+		struct node_rx_hdr *rx;
+
+		link = mem_acquire(&mem_link_rx.free);
+		if (!link) {
+			break;
+		}
+
+		rx = mem_acquire(&mem_pdu_rx.free);
+		if (!rx) {
+			mem_release(link, &mem_link_rx.free);
+			break;
+		}
+
+		rx->link = link;
+
+		MFIFO_BY_IDX_ENQUEUE(pdu_rx_free, idx, rx);
+
+		ll_rx_link_inc_quota(-1);
+	}
+}
+
+static void rx_demux(void *param)
+{
+	memq_link_t *link;
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+	do {
+#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+		struct node_rx_hdr *rx;
+
+		link = memq_peek(memq_ull_rx.head, memq_ull_rx.tail,
+				 (void **)&rx);
+		if (link) {
+#if defined(CONFIG_BT_CONN)
+			struct node_tx *node_tx;
+			memq_link_t *link_tx;
+			uint16_t handle; /* Handle to Ack TX */
+#endif /* CONFIG_BT_CONN */
+			int nack = 0;
+
+			LL_ASSERT(rx);
+
+#if defined(CONFIG_BT_CONN)
+			link_tx = ull_conn_ack_by_last_peek(rx->ack_last,
+							    &handle, &node_tx);
+			if (link_tx) {
+				rx_demux_conn_tx_ack(rx->ack_last, handle,
+						     link_tx, node_tx);
+			} else
+#endif /* CONFIG_BT_CONN */
+			{
+				nack = rx_demux_rx(link, rx);
+			}
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+			if (!nack) {
+				ull_rx_sched();
+			}
+#else /* !CONFIG_BT_CTLR_LOW_LAT_ULL */
+			if (nack) {
+				break;
+			}
+#endif /* !CONFIG_BT_CTLR_LOW_LAT_ULL */
+
+#if defined(CONFIG_BT_CONN)
+		} else {
+			struct node_tx *node_tx;
+			uint8_t ack_last;
+			uint16_t handle;
+
+			link = ull_conn_ack_peek(&ack_last, &handle, &node_tx);
+			if (link) {
+				rx_demux_conn_tx_ack(ack_last, handle,
+						      link, node_tx);
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+				ull_rx_sched();
+#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+
+			}
+#endif /* CONFIG_BT_CONN */
+		}
+
+#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+	} while (link);
+#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+}
+
+#if defined(CONFIG_BT_CONN)
+static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last)
+{
+	struct lll_tx *tx;
+	uint8_t cmplt;
+
+	tx = mfifo_dequeue_iter_get(mfifo_tx_ack.m, mfifo_tx_ack.s,
+				    mfifo_tx_ack.n, mfifo_tx_ack.f, last,
+				    first);
+	if (!tx) {
+		return 0;
+	}
+
+	*handle = tx->handle;
+	cmplt = 0U;
+	do {
+		struct node_tx *node_tx;
+		struct pdu_data *p;
+
+		node_tx = tx->node;
+		p = (void *)node_tx->pdu;
+		if (!node_tx || (node_tx == (void *)1) ||
+		    (((uint32_t)node_tx & ~3) &&
+		     (p->ll_id == PDU_DATA_LLID_DATA_START ||
+		      p->ll_id == PDU_DATA_LLID_DATA_CONTINUE))) {
+			/* data packet, hence count num cmplt */
+			tx->node = (void *)1;
+			cmplt++;
+		} else {
+			/* ctrl packet or flushed, hence dont count num cmplt */
+			tx->node = (void *)2;
+		}
+
+		if (((uint32_t)node_tx & ~3)) {
+			ll_tx_mem_release(node_tx);
+		}
+
+		tx = mfifo_dequeue_iter_get(mfifo_tx_ack.m, mfifo_tx_ack.s,
+					    mfifo_tx_ack.n, mfifo_tx_ack.f,
+					    last, first);
+	} while (tx && tx->handle == *handle);
+
+	return cmplt;
+}
+
+static inline void rx_demux_conn_tx_ack(uint8_t ack_last, uint16_t handle,
+					memq_link_t *link,
+					struct node_tx *node_tx)
+{
+#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+	do {
+#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+		/* Dequeue node */
+		ull_conn_ack_dequeue();
+
+		/* Process Tx ack */
+		ull_conn_tx_ack(handle, link, node_tx);
+
+		/* Release link mem */
+		ull_conn_link_tx_release(link);
+
+		/* check for more rx ack */
+		link = ull_conn_ack_by_last_peek(ack_last, &handle, &node_tx);
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
+		if (!link)
+#else /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+	} while (link);
+#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
+
+		{
+			/* trigger thread to call ll_rx_get() */
+			ll_rx_sched();
+		}
+}
+#endif /* CONFIG_BT_CONN */
+
+/**
+ * @brief Dispatch rx objects
+ * @details Rx objects are only peeked, not dequeued yet.
+ *   Execution context: ULL high priority Mayfly
+ */
+static inline int rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
+{
+	/* Demux Rx objects */
+	switch (rx->type) {
+	case NODE_RX_TYPE_EVENT_DONE:
+	{
+		memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
+		rx_demux_event_done(link, rx);
+	}
+	break;
+
+#if defined(CONFIG_BT_OBSERVER)
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	case NODE_RX_TYPE_EXT_1M_REPORT:
+	case NODE_RX_TYPE_EXT_2M_REPORT:
+	case NODE_RX_TYPE_EXT_CODED_REPORT:
+	{
+		struct pdu_adv *adv;
+		uint8_t phy = 0U;
+
+		memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
+
+		adv = (void *)((struct node_rx_pdu *)rx)->pdu;
+		if (adv->type != PDU_ADV_TYPE_EXT_IND) {
+			ll_rx_put(link, rx);
+			ll_rx_sched();
+			break;
+		}
+
+		switch (rx->type) {
+		case NODE_RX_TYPE_EXT_1M_REPORT:
+			phy = BIT(0);
+			break;
+		case NODE_RX_TYPE_EXT_2M_REPORT:
+			phy = BIT(1);
+			break;
+		case NODE_RX_TYPE_EXT_CODED_REPORT:
+			phy = BIT(2);
+			break;
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+
+		ull_scan_aux_setup(link, rx, phy);
+	}
+	break;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CONN)
+	case NODE_RX_TYPE_CONNECTION:
+	{
+		memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
+		ull_conn_setup(link, rx);
+	}
+	break;
+
+	case NODE_RX_TYPE_DC_PDU:
+	{
+		int nack;
+
+		nack = ull_conn_rx(link, (void *)&rx);
+		if (nack) {
+			return nack;
+		}
+
+		memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
+
+		if (rx) {
+			ll_rx_put(link, rx);
+			ll_rx_sched();
+		}
+	}
+	break;
+
+	case NODE_RX_TYPE_TERMINATE:
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_OBSERVER) || \
+	defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY) || \
+	defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
+	defined(CONFIG_BT_CTLR_ADV_INDICATION) || \
+	defined(CONFIG_BT_CTLR_SCAN_INDICATION) || \
+	defined(CONFIG_BT_CONN)
+
+#if defined(CONFIG_BT_OBSERVER)
+	case NODE_RX_TYPE_REPORT:
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	case NODE_RX_TYPE_SCAN_REQ:
+#endif /* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY */
+
+#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
+	case NODE_RX_TYPE_PROFILE:
+#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
+
+#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
+	case NODE_RX_TYPE_ADV_INDICATION:
+#endif /* CONFIG_BT_CTLR_ADV_INDICATION */
+
+#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
+	case NODE_RX_TYPE_SCAN_INDICATION:
+#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
+	{
+		memq_dequeue(memq_ull_rx.tail, &memq_ull_rx.head, NULL);
+		ll_rx_put(link, rx);
+		ll_rx_sched();
+	}
+	break;
+#endif /* CONFIG_BT_OBSERVER ||
+	* CONFIG_BT_CTLR_SCAN_REQ_NOTIFY ||
+	* CONFIG_BT_CTLR_PROFILE_ISR ||
+	* CONFIG_BT_CTLR_ADV_INDICATION ||
+	* CONFIG_BT_CTLR_SCAN_INDICATION ||
+	* CONFIG_BT_CONN
+	*/
+
+	default:
+	{
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+		/* Try proprietary demuxing */
+		rx_demux_rx_proprietary(link, rx, memq_ull_rx.tail,
+					&memq_ull_rx.head);
+#else
+		LL_ASSERT(0);
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+	}
+	break;
+	}
+
+	return 0;
+}
+
+static inline void rx_demux_event_done(memq_link_t *link,
+				       struct node_rx_hdr *rx)
+{
+	struct node_rx_event_done *done = (void *)rx;
+	struct ull_hdr *ull_hdr;
+	struct lll_event *next;
+	void *release;
+
+	/* Get the ull instance */
+	ull_hdr = done->param;
+
+	/* Process role dependent event done */
+	switch (done->extra.type) {
+#if defined(CONFIG_BT_CONN)
+	case EVENT_DONE_EXTRA_TYPE_CONN:
+		ull_conn_done(done);
+		break;
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_BROADCASTER)
+	case EVENT_DONE_EXTRA_TYPE_ADV:
+		ull_adv_done(done);
+		break;
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+		/* fallthrough checkpatch workaround! */
+	case EVENT_DONE_EXTRA_TYPE_SCAN_AUX:
+		ull_scan_aux_done(done);
+		break;
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	case EVENT_DONE_EXTRA_TYPE_SYNC:
+		ull_sync_done(done);
+		break;
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+#endif /* CONFIG_BT_OBSERVER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+	case EVENT_DONE_EXTRA_TYPE_USER_START
+		... EVENT_DONE_EXTRA_TYPE_USER_END:
+		ull_proprietary_done(done);
+		break;
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+	case EVENT_DONE_EXTRA_TYPE_NONE:
+		/* ignore */
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+
+	/* release done */
+	done->extra.type = 0U;
+	release = done_release(link, done);
+	LL_ASSERT(release == done);
+
+	/* dequeue prepare pipeline */
+	next = ull_prepare_dequeue_get();
+	while (next) {
+		uint8_t is_aborted = next->is_aborted;
+		uint8_t is_resume = next->is_resume;
+
+		if (!is_aborted) {
+			static memq_link_t link;
+			static struct mayfly mfy = {0, 0, &link, NULL,
+						    lll_resume};
+			uint32_t ret;
+
+			mfy.param = next;
+			ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+					     TICKER_USER_ID_LLL, 0, &mfy);
+			LL_ASSERT(!ret);
+		}
+
+		MFIFO_DEQUEUE(prep);
+
+		next = ull_prepare_dequeue_get();
+
+		if (!next || (!is_aborted && (!is_resume || next->is_resume))) {
+			break;
+		}
+	}
+
+	/* ull instance will resume, dont decrement ref */
+	if (!ull_hdr) {
+		return;
+	}
+
+	/* Decrement prepare reference */
+	LL_ASSERT(ull_ref_get(ull_hdr));
+	ull_ref_dec(ull_hdr);
+
+	/* If disable initiated, signal the semaphore */
+	if (!ull_ref_get(ull_hdr) && ull_hdr->disabled_cb) {
+		ull_hdr->disabled_cb(ull_hdr->disabled_param);
+	}
+}
+
+static void disabled_cb(void *param)
+{
+	k_sem_give(param);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv.c	(working copy)
@@ -0,0 +1,1890 @@
+/*
+ * Copyright (c) 2016-2020 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "ll_feat.h"
+#include "ll_settings.h"
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_adv.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_internal.h"
+#include "lll_filter.h"
+
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_conn_types.h"
+#include "ull_filter.h"
+
+#include "ull_adv_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_conn_internal.h"
+#include "ull_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_adv
+#include "common/log.h"
+#include "hal/debug.h"
+
+inline struct ll_adv_set *ull_adv_set_get(uint8_t handle);
+inline uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
+
+static int init_reset(void);
+static inline struct ll_adv_set *is_disabled_get(uint8_t handle);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param);
+static void ticker_op_update_cb(uint32_t status, void *params);
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			   uint16_t lazy, void *param);
+static void ticker_op_stop_cb(uint32_t status, void *params);
+static void disabled_cb(void *param);
+static void conn_release(struct ll_adv_set *adv);
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static void ticker_op_ext_stop_cb(uint32_t status, void *param);
+static void ext_disabled_cb(void *param);
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+static inline uint8_t disable(uint8_t handle);
+
+static struct ll_adv_set ll_adv[BT_CTLR_ADV_SET];
+
+#if defined(CONFIG_BT_TICKER_EXT)
+static struct ticker_ext ll_adv_ticker_ext[BT_CTLR_ADV_SET];
+#endif /* CONFIG_BT_TICKER_EXT */
+
+#if defined(CONFIG_BT_HCI_RAW) && defined(CONFIG_BT_CTLR_ADV_EXT)
+static uint8_t ll_adv_cmds;
+
+int ll_adv_cmds_set(uint8_t adv_cmds)
+{
+	if (!ll_adv_cmds) {
+		ll_adv_cmds = adv_cmds;
+
+		if (adv_cmds == LL_ADV_CMDS_LEGACY) {
+			struct ll_adv_set *adv = &ll_adv[0];
+
+#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING)
+			adv->hci_handle = 0;
+#endif
+			adv->is_created = 1;
+		}
+	}
+
+	if (ll_adv_cmds != adv_cmds) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int ll_adv_cmds_is_ext(void)
+{
+	return ll_adv_cmds == LL_ADV_CMDS_EXT;
+}
+#endif
+
+#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING)
+uint8_t ll_adv_set_by_hci_handle_get(uint8_t hci_handle, uint8_t *handle)
+{
+	struct ll_adv_set *adv;
+	uint8_t idx;
+
+	adv =  &ll_adv[0];
+
+	for (idx = 0U; idx < BT_CTLR_ADV_SET; idx++, adv++) {
+		if (adv->is_created && (adv->hci_handle == hci_handle)) {
+			*handle = idx;
+			return 0;
+		}
+	}
+
+	return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+}
+
+uint8_t ll_adv_set_by_hci_handle_get_or_new(uint8_t hci_handle, uint8_t *handle)
+{
+	struct ll_adv_set *adv, *adv_empty;
+	uint8_t idx;
+
+	adv =  &ll_adv[0];
+	adv_empty = NULL;
+
+	for (idx = 0U; idx < BT_CTLR_ADV_SET; idx++, adv++) {
+		if (adv->is_created) {
+			if (adv->hci_handle == hci_handle) {
+				*handle = idx;
+				return 0;
+			}
+		} else if (!adv_empty) {
+			adv_empty = adv;
+		}
+	}
+
+	if (adv_empty) {
+		adv_empty->hci_handle = hci_handle;
+		*handle = ull_adv_handle_get(adv_empty);
+		return 0;
+	}
+
+	return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+}
+#endif
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_adv_params_set(uint8_t handle, uint16_t evt_prop, uint32_t interval,
+		       uint8_t adv_type, uint8_t own_addr_type,
+		       uint8_t direct_addr_type, uint8_t const *const direct_addr,
+		       uint8_t chan_map, uint8_t filter_policy,
+		       uint8_t *const tx_pwr, uint8_t phy_p, uint8_t skip,
+		       uint8_t phy_s, uint8_t sid, uint8_t sreq)
+{
+	uint8_t const pdu_adv_type[] = {PDU_ADV_TYPE_ADV_IND,
+				     PDU_ADV_TYPE_DIRECT_IND,
+				     PDU_ADV_TYPE_SCAN_IND,
+				     PDU_ADV_TYPE_NONCONN_IND,
+				     PDU_ADV_TYPE_DIRECT_IND,
+				     PDU_ADV_TYPE_EXT_IND};
+	uint8_t is_pdu_type_changed = 0;
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
+		       uint8_t own_addr_type, uint8_t direct_addr_type,
+		       uint8_t const *const direct_addr, uint8_t chan_map,
+		       uint8_t filter_policy)
+{
+	uint8_t const pdu_adv_type[] = {PDU_ADV_TYPE_ADV_IND,
+				     PDU_ADV_TYPE_DIRECT_IND,
+				     PDU_ADV_TYPE_SCAN_IND,
+				     PDU_ADV_TYPE_NONCONN_IND,
+				     PDU_ADV_TYPE_DIRECT_IND};
+	uint8_t const handle = 0;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	struct ll_adv_set *adv;
+	struct pdu_adv *pdu;
+
+	adv = is_disabled_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	/* TODO: check and fail (0x12, invalid HCI cmd param) if invalid
+	 * evt_prop bits.
+	 */
+
+	/* extended adv param set */
+	if (adv_type == PDU_ADV_TYPE_EXT_IND) {
+		/* legacy */
+		if (evt_prop & BT_HCI_LE_ADV_PROP_LEGACY) {
+			/* lookup evt_prop to PDU type in  pdu_adv_type[] */
+			uint8_t const leg_adv_type[] = {
+				0x03, /* PDU_ADV_TYPE_NONCONN_IND */
+				0x04, /* PDU_ADV_TYPE_DIRECT_IND */
+				0x02, /* PDU_ADV_TYPE_SCAN_IND */
+				0x00  /* PDU_ADV_TYPE_ADV_IND */
+			};
+
+			adv_type = leg_adv_type[evt_prop & 0x03];
+
+			/* high duty cycle directed */
+			if (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN) {
+				adv_type = 0x01; /* PDU_ADV_TYPE_DIRECT_IND */
+			}
+
+			adv->lll.phy_p = PHY_1M;
+		} else {
+			/* - Connectable and scannable not allowed;
+			 * - High duty cycle directed connectable not allowed
+			 */
+			if (((evt_prop & (BT_HCI_LE_ADV_PROP_CONN |
+					 BT_HCI_LE_ADV_PROP_SCAN)) ==
+			     (BT_HCI_LE_ADV_PROP_CONN |
+			      BT_HCI_LE_ADV_PROP_SCAN)) ||
+			    (evt_prop & BT_HCI_LE_ADV_PROP_HI_DC_CONN)) {
+				return BT_HCI_ERR_INVALID_PARAM;
+			}
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET == 0)
+			/* Connectable or scannable requires aux */
+			if (evt_prop & (BT_HCI_LE_ADV_PROP_CONN |
+					BT_HCI_LE_ADV_PROP_SCAN)) {
+				return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+			}
+#endif
+
+			adv_type = 0x05; /* PDU_ADV_TYPE_EXT_IND in */
+					 /* pdu_adv_type array. */
+
+			adv->lll.phy_p = phy_p;
+		}
+	} else {
+		adv->lll.phy_p = PHY_1M;
+	}
+
+	adv->is_created = 1;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	/* remember params so that set adv/scan data and adv enable
+	 * interface can correctly update adv/scan data in the
+	 * double buffer between caller and controller context.
+	 */
+	/* Set interval for Undirected or Low Duty Cycle Directed Advertising */
+	if (adv_type != 0x01) {
+		adv->interval = interval;
+	} else {
+		adv->interval = 0;
+	}
+	adv->lll.chan_map = chan_map;
+	adv->lll.filter_policy = filter_policy;
+
+#if defined(CONFIG_BT_CTLR_SCAN_REQ_NOTIFY)
+	adv->lll.scan_req_notify = sreq;
+#endif
+
+	/* update the "current" primary adv data */
+	pdu = lll_adv_data_peek(&adv->lll);
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (pdu->type != pdu_adv_type[adv_type]) {
+		is_pdu_type_changed = 1;
+
+		if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
+			struct lll_adv_aux *lll_aux = adv->lll.aux;
+
+			if (lll_aux) {
+				struct ll_adv_aux_set *aux;
+
+				/* FIXME: copy AD data from auxiliary channel
+				 * PDU.
+				 */
+				pdu->len = 0;
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+				/* FIXME: release periodic adv set */
+				LL_ASSERT(!adv->lll.sync);
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+				/* Release auxiliary channel set */
+				aux = (void *)HDR_LLL2EVT(lll_aux);
+				ull_adv_aux_release(aux);
+
+				adv->lll.aux = NULL;
+			} else {
+				/* No previous AD data in auxiliary channel
+				 * PDU.
+				 */
+				pdu->len = 0;
+			}
+		}
+
+		pdu->type = pdu_adv_type[adv_type];
+
+		if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
+			/* TODO: Copy AD data from legacy PDU into auxiliary
+			 * PDU.
+			 */
+		}
+	}
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	pdu->type = pdu_adv_type[adv_type];
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+	pdu->rfu = 0;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2) &&
+	    ((pdu->type == PDU_ADV_TYPE_ADV_IND) ||
+	     (pdu->type == PDU_ADV_TYPE_DIRECT_IND))) {
+		pdu->chan_sel = 1;
+	} else {
+		pdu->chan_sel = 0;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	adv->own_addr_type = own_addr_type;
+	if (adv->own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
+	    adv->own_addr_type == BT_ADDR_LE_RANDOM_ID) {
+		adv->id_addr_type = direct_addr_type;
+		memcpy(&adv->id_addr, direct_addr, BDADDR_SIZE);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	if (pdu->type == PDU_ADV_TYPE_DIRECT_IND) {
+		pdu->tx_addr = own_addr_type & 0x1;
+		pdu->rx_addr = direct_addr_type;
+		memcpy(&pdu->direct_ind.tgt_addr[0], direct_addr, BDADDR_SIZE);
+		pdu->len = sizeof(struct pdu_adv_direct_ind);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	} else if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
+		struct pdu_adv_hdr *pri_hdr, pri_hdr_prev;
+		struct pdu_adv_com_ext_adv *pri_com_hdr;
+		uint8_t *pri_dptr_prev, *pri_dptr;
+		uint8_t len;
+
+		pri_com_hdr = (void *)&pdu->adv_ext_ind;
+		pri_hdr = (void *)pri_com_hdr->ext_hdr_adi_adv_data;
+		pri_dptr = (uint8_t *)pri_hdr + sizeof(*pri_hdr);
+		pri_dptr_prev = pri_dptr;
+
+		/* No ACAD and no AdvData */
+		pri_com_hdr->adv_mode = evt_prop & 0x03;
+
+		/* Zero-init header flags */
+		if (is_pdu_type_changed) {
+			*(uint8_t *)&pri_hdr_prev = 0;
+		} else {
+			*(uint8_t *)&pri_hdr_prev = *(uint8_t *)pri_hdr;
+		}
+		*(uint8_t *)pri_hdr = 0;
+
+		/* AdvA flag */
+		if (pri_hdr_prev.adv_addr) {
+			pri_dptr_prev += BDADDR_SIZE;
+		}
+		if (!pri_com_hdr->adv_mode &&
+		    (!pri_hdr_prev.aux_ptr ||
+		     (!(evt_prop & BT_HCI_LE_ADV_PROP_ANON) &&
+		      (phy_p != PHY_CODED)))) {
+			/* TODO: optional on 1M with Aux Ptr */
+			pri_hdr->adv_addr = 1;
+
+			/* NOTE: AdvA is filled at enable */
+			pdu->tx_addr = own_addr_type & 0x1;
+			pri_dptr += BDADDR_SIZE;
+		} else {
+			pdu->tx_addr = 0;
+		}
+		pdu->rx_addr = 0;
+
+		/* TODO: TargetA flag in primary channel PDU only for directed
+		 */
+
+		/* No CTEInfo flag in primary channel PDU */
+
+		/* ADI flag */
+		if (pri_hdr_prev.adi) {
+			pri_hdr->adi = 1;
+			pri_dptr += sizeof(struct pdu_adv_adi);
+		}
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+		/* AuxPtr flag */
+		/* Need aux for connectable or scannable extended advertising */
+		if (pri_hdr_prev.aux_ptr ||
+		    ((evt_prop & (BT_HCI_LE_ADV_PROP_CONN |
+				  BT_HCI_LE_ADV_PROP_SCAN)))) {
+			pri_hdr->aux_ptr = 1;
+			pri_dptr += sizeof(struct pdu_adv_aux_ptr);
+		}
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+		/* No SyncInfo flag in primary channel PDU */
+
+		/* Tx Power flag */
+		/* C1, Tx Power is optional on the LE 1M PHY, and reserved for
+		 * for future use on the LE Coded PHY.
+		 */
+		if ((evt_prop & BT_HCI_LE_ADV_PROP_TX_POWER) &&
+		    (!pri_hdr_prev.aux_ptr || (phy_p != PHY_CODED))) {
+			pri_hdr->tx_pwr = 1;
+			pri_dptr++;
+		}
+
+		/* Calc primary PDU len */
+		len = ull_adv_aux_hdr_len_get(pri_com_hdr, pri_dptr);
+		ull_adv_aux_hdr_len_fill(pri_com_hdr, len);
+
+		/* Set PDU length */
+		pdu->len = len;
+
+		/* Start filling primary PDU payload based on flags */
+
+		/* No AdvData in primary channel PDU */
+
+		/* No ACAD in primary channel PDU */
+
+		/* Tx Power */
+		if (pri_hdr->tx_pwr) {
+			uint8_t _tx_pwr;
+
+			_tx_pwr = 0;
+			if (tx_pwr) {
+				if (*tx_pwr != 0x7F) {
+					_tx_pwr = *tx_pwr;
+				} else {
+					*tx_pwr = _tx_pwr;
+				}
+			}
+
+			*--pri_dptr = _tx_pwr;
+		}
+
+		/* No SyncInfo in primary channel PDU */
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+		/* AuxPtr */
+		if (pri_hdr->aux_ptr) {
+			ull_adv_aux_ptr_fill(&pri_dptr, phy_s);
+		}
+		adv->lll.phy_s = phy_s;
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+		/* ADI */
+		if (pri_hdr->adi) {
+			struct pdu_adv_adi *adi;
+
+			pri_dptr -= sizeof(struct pdu_adv_adi);
+
+			/* NOTE: memcpy shall handle overlapping buffers */
+			memcpy(pri_dptr, pri_dptr_prev,
+			       sizeof(struct pdu_adv_adi));
+
+			adi = (void *)pri_dptr;
+			adi->sid = sid;
+		}
+		adv->sid = sid;
+
+		/* No CTEInfo field in primary channel PDU */
+
+		/* NOTE: TargetA, filled at enable and RPA timeout */
+
+		/* NOTE: AdvA, filled at enable and RPA timeout */
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+		/* Make sure aux is created if we have AuxPtr */
+		if (pri_hdr->aux_ptr) {
+			uint8_t err;
+
+			err = ull_adv_aux_hdr_set_clear(adv,
+							ULL_ADV_PDU_HDR_FIELD_ADVA,
+							0, &own_addr_type,
+							NULL);
+			if (err) {
+				/* TODO: cleanup? */
+				return err;
+			}
+		}
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	} else if (pdu->len == 0) {
+		pdu->tx_addr = own_addr_type & 0x1;
+		pdu->rx_addr = 0;
+		pdu->len = BDADDR_SIZE;
+	} else {
+		pdu->tx_addr = own_addr_type & 0x1;
+		pdu->rx_addr = 0;
+	}
+
+	/* update the current scan data */
+	pdu = lll_adv_scan_rsp_peek(&adv->lll);
+	pdu->type = PDU_ADV_TYPE_SCAN_RSP;
+	pdu->rfu = 0;
+	pdu->chan_sel = 0;
+	pdu->tx_addr = own_addr_type & 0x1;
+	pdu->rx_addr = 0;
+	if (pdu->len == 0) {
+		pdu->len = BDADDR_SIZE;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_adv_data_set(uint8_t handle, uint8_t len, uint8_t const *const data)
+{
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_adv_data_set(uint8_t len, uint8_t const *const data)
+{
+	const uint8_t handle = 0;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_set_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	return ull_adv_data_set(adv, len, data);
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_adv_scan_rsp_set(uint8_t handle, uint8_t len,
+			    uint8_t const *const data)
+{
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const data)
+{
+	const uint8_t handle = 0;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_set_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	return ull_scan_rsp_set(adv, len, data);
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
+		   uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry,
+		   uint8_t scan_window, uint8_t scan_delay)
+{
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
+		   uint16_t duration, uint8_t max_ext_adv_evts)
+{
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	struct ll_adv_sync_set *sync = NULL;
+	uint8_t sync_is_started = 0U;
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+	struct ll_adv_aux_set *aux = NULL;
+	uint8_t aux_is_started = 0U;
+	uint32_t ticks_anchor;
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+uint8_t ll_adv_enable(uint8_t enable)
+{
+	uint8_t const handle = 0;
+	uint32_t ticks_anchor;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
+	uint32_t ticks_slot_overhead;
+	uint32_t ticks_slot_offset;
+	uint32_t volatile ret_cb;
+	struct pdu_adv *pdu_scan;
+	struct pdu_adv *pdu_adv;
+	struct ll_adv_set *adv;
+	struct lll_adv *lll;
+	uint32_t ret;
+
+	if (!enable) {
+		return disable(handle);
+	}
+
+	adv = is_disabled_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	lll = &adv->lll;
+
+	pdu_adv = lll_adv_data_peek(lll);
+	pdu_scan = lll_adv_scan_rsp_peek(lll);
+
+	if (0) {
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	} else if (pdu_adv->type == PDU_ADV_TYPE_EXT_IND) {
+		struct pdu_adv_com_ext_adv *pri_com_hdr;
+		struct pdu_adv_hdr *pri_hdr;
+		uint8_t *pri_dptr;
+
+		pri_com_hdr = (void *)&pdu_adv->adv_ext_ind;
+		pri_hdr = (void *)pri_com_hdr->ext_hdr_adi_adv_data;
+		pri_dptr = (uint8_t *)pri_hdr + sizeof(*pri_hdr);
+
+		/* AdvA, fill here at enable */
+		if (pri_hdr->adv_addr) {
+			uint8_t const *tx_addr =
+					ll_adv_aux_random_addr_get(adv, NULL);
+
+			/* TODO: Privacy */
+
+			if (pdu_adv->tx_addr &&
+			    !mem_nz((void *)tx_addr, BDADDR_SIZE)) {
+				return BT_HCI_ERR_INVALID_PARAM;
+			}
+
+			memcpy(pri_dptr, tx_addr, BDADDR_SIZE);
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+		} else if (pri_hdr->aux_ptr) {
+			struct pdu_adv_com_ext_adv *sec_com_hdr;
+			struct pdu_adv_hdr *sec_hdr;
+			struct pdu_adv *sec_pdu;
+			uint8_t *sec_dptr;
+
+			sec_pdu = lll_adv_aux_data_peek(lll->aux);
+
+			sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
+			sec_hdr = (void *)sec_com_hdr->ext_hdr_adi_adv_data;
+			sec_dptr = (uint8_t *)sec_hdr + sizeof(*sec_hdr);
+
+			if (sec_hdr->adv_addr) {
+				uint8_t const *tx_addr =
+					ll_adv_aux_random_addr_get(adv,	NULL);
+
+				/* TODO: Privacy */
+
+				if (sec_pdu->tx_addr &&
+				    !mem_nz((void *)tx_addr, BDADDR_SIZE)) {
+					return BT_HCI_ERR_INVALID_PARAM;
+				}
+
+				memcpy(sec_dptr, tx_addr, BDADDR_SIZE);
+			}
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+		}
+
+		/* TODO: TargetA, fill here at enable */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	} else {
+		bool priv = false;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		lll->rl_idx = FILTER_IDX_NONE;
+
+		/* Prepare whitelist and optionally resolving list */
+		ull_filter_adv_update(lll->filter_policy);
+
+		if (adv->own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
+		    adv->own_addr_type == BT_ADDR_LE_RANDOM_ID) {
+			/* Look up the resolving list */
+			lll->rl_idx = ull_filter_rl_find(adv->id_addr_type,
+							 adv->id_addr, NULL);
+
+			if (lll->rl_idx != FILTER_IDX_NONE) {
+				/* Generate RPAs if required */
+				ull_filter_rpa_update(false);
+			}
+
+			ull_filter_adv_pdu_update(adv, pdu_adv);
+			ull_filter_adv_pdu_update(adv, pdu_scan);
+
+			priv = true;
+		}
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+		if (!priv) {
+			uint8_t const *tx_addr;
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+			if (ll_adv_cmds_is_ext() && pdu_adv->tx_addr) {
+				tx_addr = ll_adv_aux_random_addr_get(adv, NULL);
+			} else
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+			{
+				tx_addr = ll_addr_get(pdu_adv->tx_addr, NULL);
+			}
+
+			memcpy(&pdu_adv->adv_ind.addr[0], tx_addr,
+			       BDADDR_SIZE);
+			memcpy(&pdu_scan->scan_rsp.addr[0], tx_addr,
+			       BDADDR_SIZE);
+		}
+
+		/* In case the local IRK was not set or no match was
+		 * found the fallback address was used instead, check
+		 * that a valid address has been set.
+		 */
+		if (pdu_adv->tx_addr &&
+		    !mem_nz(pdu_adv->adv_ind.addr, BDADDR_SIZE)) {
+			return BT_HCI_ERR_INVALID_PARAM;
+		}
+	}
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (scan_delay) {
+		if (ull_scan_is_enabled(0)) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		lll->is_mesh = 1;
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	/* prepare connectable advertising */
+	if ((pdu_adv->type == PDU_ADV_TYPE_ADV_IND) ||
+	    (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND)) {
+		struct node_rx_pdu *node_rx;
+		struct ll_conn *conn;
+		struct lll_conn *conn_lll;
+		void *link;
+		int err;
+
+		if (lll->conn) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		link = ll_rx_link_alloc();
+		if (!link) {
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		node_rx = ll_rx_alloc();
+		if (!node_rx) {
+			ll_rx_link_release(link);
+
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		conn = ll_conn_acquire();
+		if (!conn) {
+			ll_rx_release(node_rx);
+			ll_rx_link_release(link);
+
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		conn_lll = &conn->lll;
+		conn_lll->handle = 0xFFFF;
+
+		if (!conn_lll->link_tx_free) {
+			conn_lll->link_tx_free = &conn_lll->link_tx;
+		}
+
+		memq_init(conn_lll->link_tx_free, &conn_lll->memq_tx.head,
+			  &conn_lll->memq_tx.tail);
+		conn_lll->link_tx_free = NULL;
+
+		conn_lll->packet_tx_head_len = 0;
+		conn_lll->packet_tx_head_offset = 0;
+
+		conn_lll->sn = 0;
+		conn_lll->nesn = 0;
+		conn_lll->empty = 0;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+		conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		/* Use the default 1M packet max time. Value of 0 is
+		 * equivalent to using BIT(0).
+		 */
+		conn_lll->max_tx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
+		conn_lll->max_rx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		conn_lll->phy_tx = BIT(0);
+		conn_lll->phy_flags = 0;
+		conn_lll->phy_tx_time = BIT(0);
+		conn_lll->phy_rx = BIT(0);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+		conn_lll->rssi_latest = 0x7F;
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+		conn_lll->rssi_reported = 0x7F;
+		conn_lll->rssi_sample_count = 0;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+		conn_lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+		/* FIXME: BEGIN: Move to ULL? */
+		conn_lll->role = 1;
+		conn_lll->data_chan_sel = 0;
+		conn_lll->data_chan_use = 0;
+		conn_lll->event_counter = 0;
+
+		conn_lll->latency_prepare = 0;
+		conn_lll->latency_event = 0;
+		conn_lll->slave.latency_enabled = 0;
+		conn_lll->slave.window_widening_prepare_us = 0;
+		conn_lll->slave.window_widening_event_us = 0;
+		conn_lll->slave.window_size_prepare_us = 0;
+		/* FIXME: END: Move to ULL? */
+#if defined(CONFIG_BT_CTLR_CONN_META)
+		memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
+#endif /* CONFIG_BT_CTLR_CONN_META */
+
+		conn->connect_expire = 6;
+		conn->supervision_expire = 0;
+		conn->procedure_expire = 0;
+
+		conn->common.fex_valid = 0;
+		conn->slave.latency_cancel = 0;
+
+		conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0;
+		conn->llcp_rx = NULL;
+		conn->llcp_cu.req = conn->llcp_cu.ack = 0;
+		conn->llcp_feature.req = conn->llcp_feature.ack = 0;
+		conn->llcp_feature.features_conn = LL_FEAT;
+		conn->llcp_feature.features_peer = 0;
+		conn->llcp_version.req = conn->llcp_version.ack = 0;
+		conn->llcp_version.tx = conn->llcp_version.rx = 0;
+		conn->llcp_terminate.reason_peer = 0;
+		/* NOTE: use allocated link for generating dedicated
+		 * terminate ind rx node
+		 */
+		conn->llcp_terminate.node_rx.hdr.link = link;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		conn_lll->enc_rx = conn_lll->enc_tx = 0U;
+		conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
+		conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
+		conn->llcp_enc.refresh = 0U;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		conn->llcp_conn_param.req = 0;
+		conn->llcp_conn_param.ack = 0;
+		conn->llcp_conn_param.disabled = 0;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		conn->llcp_length.req = conn->llcp_length.ack = 0U;
+		conn->llcp_length.disabled = 0U;
+		conn->llcp_length.cache.tx_octets = 0U;
+		conn->default_tx_octets = ull_conn_default_tx_octets_get();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		conn->default_tx_time = ull_conn_default_tx_time_get();
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		conn->llcp_phy.req = conn->llcp_phy.ack = 0;
+		conn->llcp_phy.disabled = 0U;
+		conn->llcp_phy.pause_tx = 0U;
+		conn->phy_pref_tx = ull_conn_default_phy_tx_get();
+		conn->phy_pref_rx = ull_conn_default_phy_rx_get();
+		conn->phy_pref_flags = 0;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		conn->tx_head = conn->tx_ctrl = conn->tx_ctrl_last =
+		conn->tx_data = conn->tx_data_last = 0;
+
+		/* NOTE: using same link as supplied for terminate ind */
+		adv->link_cc_free = link;
+		adv->node_rx_cc_free = node_rx;
+		lll->conn = conn_lll;
+
+		ull_hdr_init(&conn->ull);
+		lll_hdr_init(&conn->lll, conn);
+
+		/* wait for stable clocks */
+		err = lll_clock_wait();
+		if (err) {
+			conn_release(adv);
+
+			return BT_HCI_ERR_HW_FAILURE;
+		}
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (ll_adv_cmds_is_ext()) {
+		struct node_rx_pdu *node_rx_adv_term;
+		void *link_adv_term;
+
+		/* The alloc here used for ext adv termination event */
+		link_adv_term = ll_rx_link_alloc();
+		if (!link_adv_term) {
+#if defined(CONFIG_BT_PERIPHERAL)
+			if (adv->lll.conn) {
+				conn_release(adv);
+			}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+			/* TODO: figure out right return value */
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		node_rx_adv_term = ll_rx_alloc();
+		if (!node_rx_adv_term) {
+#if defined(CONFIG_BT_PERIPHERAL)
+			if (adv->lll.conn) {
+				conn_release(adv);
+			}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+			ll_rx_link_release(link_adv_term);
+
+			/* TODO: figure out right return value */
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		node_rx_adv_term->hdr.link = (void *)link_adv_term;
+		adv->lll.node_rx_adv_term = (void *)node_rx_adv_term;
+	}
+
+	const uint8_t phy = lll->phy_p;
+
+	adv->event_counter = 0;
+	adv->max_events = max_ext_adv_evts;
+	adv->ticks_remain_duration = HAL_TICKER_US_TO_TICKS((uint64_t)duration *
+							    10000);
+#else
+	/* Legacy ADV only supports LE_1M PHY */
+	const uint8_t phy = 1;
+#endif
+
+	/* For now we adv on all channels enabled in channel map */
+	uint8_t ch_map = lll->chan_map;
+	const uint8_t adv_chn_cnt = util_ones_count_get(&ch_map, sizeof(ch_map));
+	uint32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
+
+	if (adv_chn_cnt == 0) {
+		/* ADV needs at least one channel */
+		goto failure_cleanup;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (pdu_adv->type == PDU_ADV_TYPE_EXT_IND) {
+		/* FIXME: Calculate the slot_us */
+		slot_us += 1500;
+	} else
+#endif
+	{
+		uint32_t adv_size		= PDU_OVERHEAD_SIZE(phy) +
+					  ADVA_SIZE;
+		const uint16_t conn_ind_us =
+					BYTES2US((PDU_OVERHEAD_SIZE(PHY_1M) +
+						  INITA_SIZE + ADVA_SIZE +
+						  LLDATA_SIZE),
+						 phy);
+		const uint8_t scan_req_us  =
+					BYTES2US((PDU_OVERHEAD_SIZE(PHY_1M) +
+						  SCANA_SIZE + ADVA_SIZE),
+						 phy);
+		const uint16_t scan_rsp_us =
+					BYTES2US((PDU_OVERHEAD_SIZE(PHY_1M) +
+						  ADVA_SIZE + pdu_scan->len),
+						 phy);
+		const uint8_t rx_to_us	= EVENT_RX_TO_US(phy);
+		const uint8_t rxtx_turn_us = EVENT_RX_TX_TURNAROUND(phy);
+
+		if (phy != 0x01) {
+			/* Legacy ADV only supports LE_1M PHY */
+			goto failure_cleanup;
+		}
+
+		if (pdu_adv->type == PDU_ADV_TYPE_NONCONN_IND) {
+			adv_size += pdu_adv->len;
+			slot_us += BYTES2US(adv_size, phy) * adv_chn_cnt +
+				   rxtx_turn_us * (adv_chn_cnt - 1);
+		} else {
+			if (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND) {
+				adv_size += TARGETA_SIZE;
+				slot_us += conn_ind_us;
+			} else if (pdu_adv->type == PDU_ADV_TYPE_ADV_IND) {
+				adv_size += pdu_adv->len;
+				slot_us += MAX(scan_req_us + EVENT_IFS_MAX_US +
+						scan_rsp_us, conn_ind_us);
+			} else if (pdu_adv->type == PDU_ADV_TYPE_SCAN_IND) {
+				adv_size += pdu_adv->len;
+				slot_us += scan_req_us + EVENT_IFS_MAX_US +
+					   scan_rsp_us;
+			}
+
+			slot_us += (BYTES2US(adv_size, phy) + EVENT_IFS_MAX_US
+				  + rx_to_us + rxtx_turn_us) * (adv_chn_cnt-1)
+				  + BYTES2US(adv_size, phy) + EVENT_IFS_MAX_US;
+		}
+	}
+
+	uint16_t interval = adv->interval;
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (lll->is_mesh) {
+		uint16_t interval_min_us;
+
+		_radio.advertiser.retry = retry;
+		_radio.advertiser.scan_delay_ms = scan_delay;
+		_radio.advertiser.scan_window_ms = scan_window;
+
+		interval_min_us = slot_us + (scan_delay + scan_window) * 1000;
+		if ((interval * 625) < interval_min_us) {
+			interval = (interval_min_us + (625 - 1)) / 625;
+		}
+
+		/* passive scanning */
+		_radio.scanner.type = 0;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		/* TODO: Coded PHY support */
+		_radio.scanner.phy = 0;
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+		/* TODO: Privacy support */
+		_radio.scanner.rpa_gen = 0;
+		_radio.scanner.rl_idx = rl_idx;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+		_radio.scanner.filter_policy = filter_policy;
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+	ull_hdr_init(&adv->ull);
+	lll_hdr_init(lll, adv);
+
+	/* TODO: active_to_start feature port */
+	adv->evt.ticks_active_to_start = 0;
+	adv->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	adv->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	adv->evt.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
+
+	ticks_slot_offset = MAX(adv->evt.ticks_active_to_start,
+				adv->evt.ticks_xtal_to_start);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = ticks_slot_offset;
+	} else {
+		ticks_slot_overhead = 0;
+	}
+
+#if !defined(CONFIG_BT_HCI_MESH_EXT)
+	ticks_anchor = ticker_ticks_now_get();
+#else /* CONFIG_BT_HCI_MESH_EXT */
+	if (!at_anchor) {
+		ticks_anchor = ticker_ticks_now_get();
+	}
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+
+	/* High Duty Cycle Directed Advertising if interval is 0. */
+#if defined(CONFIG_BT_PERIPHERAL)
+	lll->is_hdcd = !interval && (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND);
+	if (lll->is_hdcd) {
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+				   TICKER_USER_ID_THREAD,
+				   (TICKER_ID_ADV_BASE + handle),
+				   ticks_anchor, 0,
+				   (adv->evt.ticks_slot + ticks_slot_overhead),
+				   TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
+				   (adv->evt.ticks_slot + ticks_slot_overhead),
+				   ticker_cb, adv,
+				   ull_ticker_status_give, (void *)&ret_cb);
+		ret = ull_ticker_status_take(ret, &ret_cb);
+		if (ret != TICKER_STATUS_SUCCESS) {
+			goto failure_cleanup;
+		}
+
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+				   TICKER_USER_ID_THREAD,
+				   TICKER_ID_ADV_STOP, ticks_anchor,
+				   HAL_TICKER_US_TO_TICKS(ticks_slot_offset +
+							  (1280 * 1000)),
+				   TICKER_NULL_PERIOD, TICKER_NULL_REMAINDER,
+				   TICKER_NULL_LAZY, TICKER_NULL_SLOT,
+				   ticker_stop_cb, adv,
+				   ull_ticker_status_give, (void *)&ret_cb);
+	} else
+#endif /* CONFIG_BT_PERIPHERAL */
+	{
+		const uint32_t ticks_slot = adv->evt.ticks_slot +
+					 ticks_slot_overhead;
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+		/* Add sync_info into auxiliary PDU */
+		if (lll->sync) {
+			sync = (void *)HDR_LLL2EVT(lll->sync);
+			if (sync->is_enabled && !sync->is_started) {
+				ret = ull_adv_aux_hdr_set_clear(adv,
+					ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
+					0, NULL, NULL);
+				if (ret) {
+					return ret;
+				}
+			} else {
+				/* Do not start periodic advertising */
+				sync = NULL;
+			}
+		}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+		if (lll->aux) {
+			struct lll_adv_aux *lll_aux = lll->aux;
+			uint32_t ticks_slot_overhead_aux;
+			uint32_t ticks_anchor_aux;
+
+			aux = (void *)HDR_LLL2EVT(lll_aux);
+
+			/* schedule auxiliary PDU after primary channel PDUs */
+			ticks_anchor_aux =
+				ticks_anchor + ticks_slot +
+				HAL_TICKER_US_TO_TICKS(EVENT_MAFS_US);
+
+			ticks_slot_overhead_aux = ull_adv_aux_evt_init(aux);
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+			/* Start periodic advertising if enabled and not already
+			 * started.
+			 */
+			if (sync) {
+				const uint32_t ticks_slot_aux =
+					aux->evt.ticks_slot +
+					ticks_slot_overhead_aux;
+				uint32_t ticks_anchor_sync =
+					ticks_anchor_aux +
+					ticks_slot_aux +
+					HAL_TICKER_US_TO_TICKS(EVENT_MAFS_US);
+
+				ull_hdr_init(&sync->ull);
+
+				ret = ull_adv_sync_start(sync,
+							 ticks_anchor_sync,
+							 &ret_cb);
+				if (ret) {
+					goto failure_cleanup;
+				}
+
+				sync_is_started = 1U;
+			}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+			/* Initialise ULL header */
+			ull_hdr_init(&aux->ull);
+
+			/* Keep aux interval equal or higher than primary PDU
+			 * interval.
+			 */
+			aux->interval =
+				adv->interval +
+				(HAL_TICKER_TICKS_TO_US(ULL_ADV_RANDOM_DELAY) /
+				 625U);
+
+			ret = ull_adv_aux_start(aux, ticks_anchor_aux,
+						ticks_slot_overhead_aux,
+						&ret_cb);
+			if (ret) {
+				goto failure_cleanup;
+			}
+
+			aux_is_started = 1U;
+		}
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+		ret_cb = TICKER_STATUS_BUSY;
+
+#if defined(CONFIG_BT_TICKER_EXT)
+		ll_adv_ticker_ext[handle].ticks_slot_window =
+			ULL_ADV_RANDOM_DELAY + ticks_slot;
+
+		ret = ticker_start_ext(
+#else
+		ret = ticker_start(
+#endif /* CONFIG_BT_TICKER_EXT */
+				   TICKER_INSTANCE_ID_CTLR,
+				   TICKER_USER_ID_THREAD,
+				   (TICKER_ID_ADV_BASE + handle),
+				   ticks_anchor, 0,
+				   HAL_TICKER_US_TO_TICKS((uint64_t)interval *
+							  625),
+				   TICKER_NULL_REMAINDER,
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE) && \
+	!defined(CONFIG_BT_CTLR_LOW_LAT)
+				   /* Force expiry to ensure timing update */
+				   TICKER_LAZY_MUST_EXPIRE,
+#else
+				   TICKER_NULL_LAZY,
+#endif
+				   ticks_slot,
+				   ticker_cb, adv,
+				   ull_ticker_status_give,
+				   (void *)&ret_cb
+#if defined(CONFIG_BT_TICKER_EXT)
+				   ,
+				   &ll_adv_ticker_ext[handle]
+#endif /* CONFIG_BT_TICKER_EXT */
+				   );
+	}
+
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret != TICKER_STATUS_SUCCESS) {
+		goto failure_cleanup;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (aux_is_started) {
+		aux->is_started = aux_is_started;
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+		if (sync_is_started) {
+			sync->is_started = sync_is_started;
+		}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+	}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	adv->is_enabled = 1;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	if (_radio.advertiser.is_mesh) {
+		_radio.scanner.is_enabled = 1;
+
+		ull_filter_adv_scan_state_cb(BIT(0) | BIT(1));
+	}
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+	if (IS_ENABLED(CONFIG_BT_OBSERVER) && !ull_scan_is_enabled_get(0)) {
+		ull_filter_adv_scan_state_cb(BIT(0));
+	}
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	return 0;
+
+failure_cleanup:
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+	if (aux_is_started) {
+		/* TODO: Stop extended advertising and release resources */
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	if (sync_is_started) {
+		/* TODO: Stop periodic advertising and release resources */
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (adv->lll.conn) {
+		conn_release(adv);
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+int ull_adv_init(void)
+{
+	int err;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_CTLR_ADV_AUX_SET)
+	if (CONFIG_BT_CTLR_ADV_AUX_SET > 0) {
+		err = ull_adv_aux_init();
+		if (err) {
+			return err;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	err = ull_adv_sync_init();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_AUX_SET */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_adv_reset(void)
+{
+	uint8_t handle;
+	int err;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+
+#if defined(CONFIG_BT_HCI_RAW)
+	ll_adv_cmds = LL_ADV_CMDS_ANY;
+#endif
+
+#if defined(CONFIG_BT_CTLR_ADV_AUX_SET)
+	if (CONFIG_BT_CTLR_ADV_AUX_SET > 0) {
+		err = ull_adv_aux_reset();
+		if (err) {
+			return err;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	err = ull_adv_sync_reset();
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_AUX_SET */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	for (handle = 0U; handle < BT_CTLR_ADV_SET; handle++) {
+		(void)disable(handle);
+	}
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+inline struct ll_adv_set *ull_adv_set_get(uint8_t handle)
+{
+	if (handle >= BT_CTLR_ADV_SET) {
+		return NULL;
+	}
+
+	return &ll_adv[handle];
+}
+
+inline uint16_t ull_adv_handle_get(struct ll_adv_set *adv)
+{
+	return ((uint8_t *)adv - (uint8_t *)ll_adv) / sizeof(*adv);
+}
+
+uint16_t ull_adv_lll_handle_get(struct lll_adv *lll)
+{
+	return ull_adv_handle_get((void *)HDR_LLL2EVT(lll));
+}
+
+inline struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_set_get(handle);
+	if (!adv || !adv->is_enabled) {
+		return NULL;
+	}
+
+	return adv;
+}
+
+int ull_adv_is_enabled(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_is_enabled_get(handle);
+
+	return adv != NULL;
+}
+
+uint32_t ull_adv_filter_pol_get(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_is_enabled_get(handle);
+	if (!adv) {
+		return 0;
+	}
+
+	return adv->lll.filter_policy;
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+struct ll_adv_set *ull_adv_is_created_get(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_set_get(handle);
+	if (!adv || !adv->is_created) {
+		return NULL;
+	}
+
+	return adv;
+}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+uint8_t ull_adv_data_set(struct ll_adv_set *adv, uint8_t len,
+			 uint8_t const *const data)
+{
+	struct pdu_adv *prev;
+	struct pdu_adv *pdu;
+	uint8_t idx;
+
+	/* Dont update data if directed or extended advertising. */
+	prev = lll_adv_data_peek(&adv->lll);
+	if ((prev->type == PDU_ADV_TYPE_DIRECT_IND) ||
+	    (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
+	     (prev->type == PDU_ADV_TYPE_EXT_IND))) {
+		/* TODO: remember data, to be used if type is changed using
+		 * parameter set function ll_adv_params_set afterwards.
+		 */
+		return 0;
+	}
+
+	/* update adv pdu fields. */
+	pdu = lll_adv_data_alloc(&adv->lll, &idx);
+
+	/* check for race condition with LLL ISR */
+	if (IS_ENABLED(CONFIG_ASSERT)) {
+		uint8_t idx_test;
+
+		lll_adv_data_alloc(&adv->lll, &idx_test);
+		__ASSERT((idx == idx_test), "Probable AD Data Corruption.\n");
+	}
+
+	pdu->type = prev->type;
+	pdu->rfu = 0U;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+		pdu->chan_sel = prev->chan_sel;
+	} else {
+		pdu->chan_sel = 0U;
+	}
+
+	pdu->tx_addr = prev->tx_addr;
+	pdu->rx_addr = prev->rx_addr;
+	memcpy(&pdu->adv_ind.addr[0], &prev->adv_ind.addr[0], BDADDR_SIZE);
+	memcpy(&pdu->adv_ind.data[0], data, len);
+	pdu->len = BDADDR_SIZE + len;
+
+	lll_adv_data_enqueue(&adv->lll, idx);
+
+	return 0;
+}
+
+uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
+			 uint8_t const *const data)
+{
+	struct pdu_adv *prev;
+	struct pdu_adv *pdu;
+	uint8_t idx;
+
+	/* update scan pdu fields. */
+	prev = lll_adv_scan_rsp_peek(&adv->lll);
+	pdu = lll_adv_scan_rsp_alloc(&adv->lll, &idx);
+	pdu->type = PDU_ADV_TYPE_SCAN_RSP;
+	pdu->rfu = 0;
+	pdu->chan_sel = 0;
+	pdu->tx_addr = prev->tx_addr;
+	pdu->rx_addr = 0;
+	pdu->len = BDADDR_SIZE + len;
+	memcpy(&pdu->scan_rsp.addr[0], &prev->scan_rsp.addr[0], BDADDR_SIZE);
+	memcpy(&pdu->scan_rsp.data[0], data, len);
+
+	lll_adv_scan_rsp_enqueue(&adv->lll, idx);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+void ull_adv_done(struct node_rx_event_done *done)
+{
+	struct lll_adv *lll = (void *)HDR_ULL2LLL(done->param);
+	struct ll_adv_set *adv = (void *)HDR_LLL2EVT(lll);
+	struct node_rx_hdr *rx_hdr;
+	uint8_t handle;
+	uint32_t ret;
+
+	if (adv->max_events && (adv->event_counter >= adv->max_events)) {
+		adv->max_events = 0;
+
+		rx_hdr = (void *)lll->node_rx_adv_term;
+		rx_hdr->rx_ftr.param_adv_term.status = BT_HCI_ERR_LIMIT_REACHED;
+	} else if (adv->ticks_remain_duration &&
+		   (adv->ticks_remain_duration <
+		    HAL_TICKER_US_TO_TICKS((uint64_t)adv->interval * 625U))) {
+		adv->ticks_remain_duration = 0;
+
+		rx_hdr = (void *)lll->node_rx_adv_term;
+		rx_hdr->rx_ftr.param_adv_term.status = BT_HCI_ERR_ADV_TIMEOUT;
+	} else {
+		return;
+	}
+
+	handle = ull_adv_handle_get(adv);
+	LL_ASSERT(handle < BT_CTLR_ADV_SET);
+
+	rx_hdr->type = NODE_RX_TYPE_EXT_ADV_TERMINATE;
+	rx_hdr->handle = handle;
+	rx_hdr->rx_ftr.param_adv_term.conn_handle = 0xffff;
+	rx_hdr->rx_ftr.param_adv_term.num_events = adv->event_counter;
+
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+			  (TICKER_ID_ADV_BASE + handle), ticker_op_ext_stop_cb,
+			  adv);
+
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+static int init_reset(void)
+{
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) && \
+	!defined(CONFIG_BT_CTLR_ADV_EXT)
+	ll_adv[0].lll.tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL && !CONFIG_BT_CTLR_ADV_EXT */
+
+	return 0;
+}
+
+static inline struct ll_adv_set *is_disabled_get(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_set_get(handle);
+	if (!adv || adv->is_enabled) {
+		return NULL;
+	}
+
+	return adv;
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+		      void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_prepare};
+	static struct lll_prepare_param p;
+	struct ll_adv_set *adv = param;
+	struct lll_adv *lll;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_A(1);
+
+	lll = &adv->lll;
+
+	if (IS_ENABLED(CONFIG_BT_TICKER_COMPATIBILITY_MODE) ||
+	    (lazy != TICKER_LAZY_MUST_EXPIRE)) {
+		/* Increment prepare reference count */
+		ref = ull_ref_inc(&adv->ull);
+		LL_ASSERT(ref);
+
+		/* Append timing parameters */
+		p.ticks_at_expire = ticks_at_expire;
+		p.remainder = remainder;
+		p.lazy = lazy;
+		p.param = lll;
+		mfy.param = &p;
+
+		/* Kick LLL prepare */
+		ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+				     TICKER_USER_ID_LLL, 0, &mfy);
+		LL_ASSERT(!ret);
+	}
+
+	/* Apply adv random delay */
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!lll->is_hdcd)
+#endif /* CONFIG_BT_PERIPHERAL */
+	{
+		uint32_t random_delay;
+		uint32_t ret;
+
+		lll_rand_isr_get(&random_delay, sizeof(random_delay));
+		random_delay %= ULL_ADV_RANDOM_DELAY;
+		random_delay += 1;
+
+		ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
+				    TICKER_USER_ID_ULL_HIGH,
+				    (TICKER_ID_ADV_BASE +
+				     ull_adv_handle_get(adv)),
+				    random_delay,
+				    0, 0, 0, 0, 0,
+				    ticker_op_update_cb, adv);
+		LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+			  (ret == TICKER_STATUS_BUSY));
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		adv->event_counter += (lazy + 1);
+
+		if (adv->ticks_remain_duration) {
+			uint32_t ticks_interval =
+				HAL_TICKER_US_TO_TICKS((uint64_t)adv->interval *
+						       625U);
+			if (adv->ticks_remain_duration > ticks_interval) {
+				adv->ticks_remain_duration -= ticks_interval;
+
+				if (adv->ticks_remain_duration > random_delay) {
+					adv->ticks_remain_duration -=
+						random_delay;
+				}
+			}
+		}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+	if (adv->lll.aux) {
+		ull_adv_aux_offset_get(adv);
+	}
+#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+	DEBUG_RADIO_PREPARE_A(1);
+}
+
+static void ticker_op_update_cb(uint32_t status, void *param)
+{
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
+		  param == ull_disable_mark_get());
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			   uint16_t lazy, void *param)
+{
+	struct ll_adv_set *adv = param;
+	uint8_t handle;
+	uint32_t ret;
+
+	handle = ull_adv_handle_get(adv);
+	LL_ASSERT(handle < BT_CTLR_ADV_SET);
+
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+			  TICKER_ID_ADV_BASE + handle,
+			  ticker_op_stop_cb, adv);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+static void ticker_op_stop_cb(uint32_t status, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, NULL};
+	struct ll_adv_set *adv;
+	struct ull_hdr *hdr;
+	uint32_t ret;
+
+	/* Ignore if race between thread and ULL */
+	if (status != TICKER_STATUS_SUCCESS) {
+		/* TODO: detect race */
+
+		return;
+	}
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	/* FIXME: why is this here for Mesh commands? */
+	if (params) {
+		return;
+	}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+
+	adv = param;
+	hdr = &adv->ull;
+	mfy.param = &adv->lll;
+	if (ull_ref_get(hdr)) {
+		LL_ASSERT(!hdr->disabled_cb);
+		hdr->disabled_param = mfy.param;
+		hdr->disabled_cb = disabled_cb;
+
+		mfy.fp = lll_disable;
+		ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
+				     TICKER_USER_ID_LLL, 0, &mfy);
+		LL_ASSERT(!ret);
+	} else {
+		mfy.fp = disabled_cb;
+		ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW,
+				     TICKER_USER_ID_ULL_HIGH, 0, &mfy);
+		LL_ASSERT(!ret);
+	}
+}
+
+static void disabled_cb(void *param)
+{
+	struct node_rx_ftr *ftr;
+	struct ll_adv_set *adv;
+	struct node_rx_pdu *rx;
+	struct node_rx_cc *cc;
+	memq_link_t *link;
+
+	adv = ((struct lll_hdr *)param)->parent;
+
+	LL_ASSERT(adv->link_cc_free);
+	link = adv->link_cc_free;
+	adv->link_cc_free = NULL;
+
+	LL_ASSERT(adv->node_rx_cc_free);
+	rx = adv->node_rx_cc_free;
+	adv->node_rx_cc_free = NULL;
+
+	rx->hdr.type = NODE_RX_TYPE_CONNECTION;
+	rx->hdr.handle = 0xffff;
+
+	cc = (void *)rx->pdu;
+	memset(cc, 0x00, sizeof(struct node_rx_cc));
+	cc->status = BT_HCI_ERR_ADV_TIMEOUT;
+
+	ftr = &(rx->hdr.rx_ftr);
+	ftr->param = param;
+
+	ll_rx_put(link, rx);
+	ll_rx_sched();
+}
+
+static void conn_release(struct ll_adv_set *adv)
+{
+	struct lll_conn *lll = adv->lll.conn;
+	memq_link_t *link;
+
+	LL_ASSERT(!lll->link_tx_free);
+	link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail);
+	LL_ASSERT(link);
+	lll->link_tx_free = link;
+
+	ll_conn_release(lll->hdr.parent);
+	adv->lll.conn = NULL;
+
+	ll_rx_release(adv->node_rx_cc_free);
+	adv->node_rx_cc_free = NULL;
+	ll_rx_link_release(adv->link_cc_free);
+	adv->link_cc_free = NULL;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+static void ticker_op_ext_stop_cb(uint32_t status, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, NULL};
+	struct ll_adv_set *adv;
+	uint32_t ret;
+
+	/* Ignore if race between thread and ULL */
+	if (status != TICKER_STATUS_SUCCESS) {
+		/* TODO: detect race */
+
+		return;
+	}
+
+	adv = param;
+	mfy.fp = ext_disabled_cb;
+	mfy.param = &adv->lll;
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH, 0,
+			     &mfy);
+	LL_ASSERT(!ret);
+}
+
+static void ext_disabled_cb(void *param)
+{
+	struct lll_adv *lll = (void *)param;
+	struct node_rx_hdr *rx_hdr = (void *)lll->node_rx_adv_term;
+
+	/* Under race condition, if a connection has been established then
+	 * node_rx is already utilized to send terminate event on connection */
+	if (!rx_hdr) {
+		return;
+	}
+
+	/* NOTE: parameters are already populated on disable, just enqueue here
+	 */
+	ll_rx_put(rx_hdr->link, rx_hdr);
+	ll_rx_sched();
+}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+static inline uint8_t disable(uint8_t handle)
+{
+	uint32_t volatile ret_cb;
+	struct ll_adv_set *adv;
+	void *mark;
+	uint32_t ret;
+
+	adv = ull_adv_is_enabled_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+	struct lll_adv_aux *lll_aux = adv->lll.aux;
+
+	if (lll_aux) {
+		struct ll_adv_aux_set *aux;
+		uint8_t err;
+
+		aux = (void *)HDR_LLL2EVT(lll_aux);
+
+		err = ull_adv_aux_stop(aux);
+		if (err) {
+			return err;
+		}
+	}
+#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+	mark = ull_disable_mark(adv);
+	LL_ASSERT(mark == adv);
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (adv->lll.is_hdcd) {
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_stop(TICKER_INSTANCE_ID_CTLR,
+				  TICKER_USER_ID_THREAD, TICKER_ID_ADV_STOP,
+				  ull_ticker_status_give, (void *)&ret_cb);
+		ret = ull_ticker_status_take(ret, &ret_cb);
+		if (ret) {
+			mark = ull_disable_unmark(adv);
+			LL_ASSERT(mark == adv);
+
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+#endif
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_ADV_BASE + handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret) {
+		mark = ull_disable_unmark(adv);
+		LL_ASSERT(mark == adv);
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	ret = ull_disable(&adv->lll);
+	LL_ASSERT(!ret);
+
+	mark = ull_disable_unmark(adv);
+	LL_ASSERT(mark == adv);
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (adv->lll.conn) {
+		conn_release(adv);
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	struct lll_adv *lll = &adv->lll;
+
+	if (lll->node_rx_adv_term) {
+		struct node_rx_pdu *node_rx_adv_term =
+			(void *)lll->node_rx_adv_term;
+
+		lll->node_rx_adv_term = NULL;
+
+		ll_rx_link_release(node_rx_adv_term->hdr.link);
+		ll_rx_release(node_rx_adv_term);
+	}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+	adv->is_enabled = 0U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (IS_ENABLED(CONFIG_BT_OBSERVER) && !ull_scan_is_enabled_get(0)) {
+		ull_filter_adv_scan_state_cb(0);
+	}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c	(working copy)
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (c) 2017-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "hal/cpu.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_adv.h"
+#include "lll_adv_aux.h"
+#include "lll_adv_internal.h"
+
+#include "ull_adv_types.h"
+
+#include "ull_internal.h"
+#include "ull_adv_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_adv_aux
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+static inline struct ll_adv_aux_set *aux_acquire(void);
+static inline void aux_release(struct ll_adv_aux_set *aux);
+static inline uint8_t aux_handle_get(struct ll_adv_aux_set *aux);
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+static inline void sync_info_fill(struct lll_adv_sync *lll_sync,
+				  uint8_t **dptr);
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+static void mfy_aux_offset_get(void *param);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param);
+static void ticker_op_cb(uint32_t status, void *param);
+
+static struct ll_adv_aux_set ll_adv_aux_pool[CONFIG_BT_CTLR_ADV_AUX_SET];
+static void *adv_aux_free;
+#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t const *const addr)
+{
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	/* TODO: Fail if connectable advertising is enabled */
+	if (0) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	memcpy(adv->rnd_addr, addr, BDADDR_SIZE);
+
+	return 0;
+}
+
+uint8_t const *ll_adv_aux_random_addr_get(struct ll_adv_set const *const adv,
+				       uint8_t *const addr)
+{
+	if (addr) {
+		memcpy(addr, adv->rnd_addr, BDADDR_SIZE);
+	}
+
+	return adv->rnd_addr;
+}
+
+uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len,
+			    uint8_t const *const data)
+{
+	struct ll_adv_set *adv;
+	uint8_t value[5];
+	uint8_t *val_ptr;
+	uint8_t err;
+
+	/* op param definitions:
+	 * 0x00 - Intermediate fragment of fragmented extended advertising data
+	 * 0x01 - First fragment of fragmented extended advertising data
+	 * 0x02 - Last fragemnt of fragemented extended advertising data
+	 * 0x03 - Complete extended advertising data
+	 * 0x04 - Unchanged data (just update the advertising data)
+	 * All other values, Reserved for future use
+	 */
+
+	/* TODO: handle other op values */
+	if ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) &&
+	    (op != BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
+		/* FIXME: error code */
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	/* Get the advertising set instance */
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	val_ptr = value;
+	*val_ptr++ = len;
+	sys_put_le32((uint32_t)data, val_ptr);
+	err = ull_adv_aux_hdr_set_clear(adv, ULL_ADV_PDU_HDR_FIELD_AD_DATA,
+					0, value, NULL);
+	if (err) {
+		return err;
+	}
+
+	if (adv->is_enabled && adv->lll.aux) {
+		struct ll_adv_aux_set *aux;
+
+		aux = (void *)HDR_LLL2EVT(adv->lll.aux);
+		if (!aux->is_started) {
+			uint32_t ticks_slot_overhead;
+			uint32_t volatile ret_cb;
+			uint32_t ticks_anchor;
+			uint32_t ret;
+
+			ull_hdr_init(&aux->ull);
+
+			aux->interval =	adv->interval +
+					(HAL_TICKER_TICKS_TO_US(
+						ULL_ADV_RANDOM_DELAY
+					) / 625U);
+
+			ticks_anchor = ticker_ticks_now_get();
+
+			ticks_slot_overhead = ull_adv_aux_evt_init(aux);
+
+			ret = ull_adv_aux_start(aux, ticks_anchor,
+						ticks_slot_overhead, &ret_cb);
+			ret = ull_ticker_status_take(ret, &ret_cb);
+			if (ret != TICKER_STATUS_SUCCESS) {
+				/* NOTE: This failure, to start an auxiliary
+				 * channel radio event shall not occur unless
+				 * a defect in the controller design.
+				 */
+				return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
+			}
+
+			aux->is_started = 1;
+		}
+	}
+
+	return 0;
+}
+
+uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, uint8_t len,
+			    uint8_t const *const data)
+{
+	struct pdu_adv_com_ext_adv *sr_com_hdr;
+	struct pdu_adv *pri_pdu_prev;
+	struct pdu_adv_hdr *sr_hdr;
+	struct pdu_adv_adi *sr_adi;
+	struct pdu_adv *sr_prev;
+	struct pdu_adv *aux_pdu;
+	struct ll_adv_set *adv;
+	struct pdu_adv *sr_pdu;
+	struct lll_adv *lll;
+	uint8_t ext_hdr_len;
+	uint8_t *sr_dptr;
+	uint8_t idx;
+	uint8_t err;
+
+	/* TODO: handle other op values */
+	if ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) &&
+	    (op != BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
+		return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
+	}
+
+	/* Get the advertising set instance */
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	lll = &adv->lll;
+
+	/* Do not use Common Extended Advertising Header Format if not extended
+	 * advertising.
+	 */
+	pri_pdu_prev = lll_adv_data_peek(lll);
+	if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
+		if ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) || (len > 31)) {
+			return BT_HCI_ERR_INVALID_PARAM;
+		}
+		return ull_scan_rsp_set(adv, len, data);
+	}
+
+	/* Can only set complete data and cannot discard data on enabled set */
+	if (adv->is_enabled && ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) ||
+				(len == 0))) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	LL_ASSERT(lll->aux);
+	aux_pdu = lll_adv_aux_data_peek(lll->aux);
+	sr_prev = lll_adv_scan_rsp_peek(lll);
+
+	/* Can only discard data on non-scannable instances */
+	if (!(aux_pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) && len) {
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	/* Update scan response PDU fields. */
+	sr_pdu = lll_adv_scan_rsp_alloc(lll, &idx);
+	sr_pdu->type = PDU_ADV_TYPE_AUX_SCAN_RSP;
+	sr_pdu->rfu = 0;
+	sr_pdu->chan_sel = 0;
+	sr_pdu->tx_addr = aux_pdu->tx_addr;
+	sr_pdu->rx_addr = 0;
+	sr_pdu->len = 0;
+
+	sr_com_hdr = &sr_pdu->adv_ext_ind;
+	sr_hdr = (void *)&sr_com_hdr->ext_hdr_adi_adv_data[0];
+	sr_dptr = (void *)sr_hdr;
+
+	/* Flags */
+	*sr_dptr = 0;
+	sr_hdr->adv_addr = 1;
+#if defined(CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP)
+	sr_hdr->adi = 1;
+#endif
+	sr_dptr++;
+
+	/* AdvA */
+	memcpy(sr_dptr, &sr_prev->adv_ext_ind.ext_hdr_adi_adv_data[1],
+	       BDADDR_SIZE);
+	sr_dptr += BDADDR_SIZE;
+
+#if defined(CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP)
+	/* ADI */
+	sr_adi = (void *)sr_dptr;
+	sr_dptr += sizeof(struct pdu_adv_adi);
+#else
+	sr_adi = NULL;
+#endif
+
+	/* Check if data will fit in remaining space */
+	/* TODO: need aux_chain_ind support */
+	ext_hdr_len = sr_dptr - &sr_com_hdr->ext_hdr_adi_adv_data[0];
+	if (sizeof(sr_com_hdr->ext_hdr_adi_adv_data) -
+	    sr_com_hdr->ext_hdr_len < len) {
+		return BT_HCI_ERR_PACKET_TOO_LONG;
+	}
+
+	/* Copy data */
+	memcpy(sr_dptr, data, len);
+	sr_dptr += len;
+
+	/* Finish Common ExtAdv Payload header */
+	sr_com_hdr->adv_mode = 0;
+	sr_com_hdr->ext_hdr_len = ext_hdr_len;
+
+	/* Finish PDU */
+	sr_pdu->len = sr_dptr - &sr_pdu->payload[0];
+
+	/* Trigger DID update */
+	err = ull_adv_aux_hdr_set_clear(adv, 0, 0, NULL, sr_adi);
+	if (err) {
+		return err;
+	}
+
+	lll_adv_scan_rsp_enqueue(&adv->lll, idx);
+
+	return 0;
+}
+
+uint16_t ll_adv_aux_max_data_length_get(void)
+{
+	return CONFIG_BT_CTLR_ADV_DATA_LEN_MAX;
+}
+
+uint8_t ll_adv_aux_set_count_get(void)
+{
+	return CONFIG_BT_CTLR_ADV_SET;
+}
+
+uint8_t ll_adv_aux_set_remove(uint8_t handle)
+{
+	struct ll_adv_set *adv;
+	struct lll_adv *lll;
+
+	/* Get the advertising set instance */
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	if (adv->is_enabled) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	lll = &adv->lll;
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	if (lll->sync) {
+		struct ll_adv_sync_set *sync;
+
+		sync = (void *)HDR_LLL2EVT(lll->sync);
+
+		if (sync->is_enabled) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+	/* Release auxiliary channel set */
+	if (lll->aux) {
+		struct ll_adv_aux_set *aux;
+
+		aux = (void *)HDR_LLL2EVT(lll->aux);
+
+		ull_adv_aux_release(aux);
+	}
+
+	adv->is_created = 0;
+
+	return BT_HCI_ERR_SUCCESS;
+}
+
+uint8_t ll_adv_aux_set_clear(void)
+{
+	uint8_t retval = BT_HCI_ERR_SUCCESS;
+	uint8_t handle;
+	uint8_t err;
+
+	for (handle = 0; handle < BT_CTLR_ADV_SET; ++handle) {
+		err = ll_adv_aux_set_remove(handle);
+		if (err == BT_HCI_ERR_CMD_DISALLOWED) {
+			retval = err;
+		}
+	}
+
+	return retval;
+}
+
+int ull_adv_aux_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_adv_aux_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
+				  uint16_t sec_hdr_add_fields,
+				  uint16_t sec_hdr_rem_fields,
+				  void *value, struct pdu_adv_adi *adi)
+{
+	struct pdu_adv_com_ext_adv *pri_com_hdr, *pri_com_hdr_prev;
+	struct pdu_adv_com_ext_adv *sec_com_hdr, *sec_com_hdr_prev;
+	struct pdu_adv_hdr *pri_hdr, pri_hdr_prev;
+	struct pdu_adv_hdr *sec_hdr, sec_hdr_prev;
+	struct pdu_adv *pri_pdu, *pri_pdu_prev;
+	struct pdu_adv *sec_pdu_prev, *sec_pdu;
+	uint8_t pri_len, sec_len, sec_len_prev;
+	uint8_t *pri_dptr, *pri_dptr_prev;
+	uint8_t *sec_dptr, *sec_dptr_prev;
+	uint8_t pri_idx, sec_idx, ad_len;
+	struct lll_adv_aux *lll_aux;
+	struct lll_adv *lll;
+	uint8_t is_aux_new;
+	uint8_t *ad_data;
+
+	lll = &adv->lll;
+
+	/* Can't have both flags set here since both use 'value' extra param */
+	LL_ASSERT(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) ||
+		  !(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA));
+
+	/* Get reference to previous primary PDU data */
+	pri_pdu_prev = lll_adv_data_peek(lll);
+	if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
+		if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
+			uint8_t *val_ptr = value;
+
+			ad_len = *val_ptr;
+			val_ptr++;
+
+			ad_data = (void *)*((uint32_t *)val_ptr);
+
+			return ull_adv_data_set(adv, ad_len, ad_data);
+		}
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	pri_com_hdr_prev = (void *)&pri_pdu_prev->adv_ext_ind;
+	pri_hdr = (void *)pri_com_hdr_prev->ext_hdr_adi_adv_data;
+	pri_hdr_prev = *pri_hdr;
+	pri_dptr_prev = (uint8_t *)pri_hdr + sizeof(*pri_hdr);
+
+	/* Advertising data are not supported by scannable instances */
+	if ((sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) &&
+	    (pri_com_hdr_prev->adv_mode & BT_HCI_LE_ADV_PROP_SCAN)) {
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	/* Get reference to new primary PDU data buffer */
+	pri_pdu = lll_adv_data_alloc(lll, &pri_idx);
+	pri_pdu->type = pri_pdu_prev->type;
+	pri_pdu->rfu = 0U;
+	pri_pdu->chan_sel = 0U;
+	pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
+	pri_com_hdr->adv_mode = pri_com_hdr_prev->adv_mode;
+	pri_hdr = (void *)pri_com_hdr->ext_hdr_adi_adv_data;
+	pri_dptr = (uint8_t *)pri_hdr + sizeof(*pri_hdr);
+	*(uint8_t *)pri_hdr = 0U;
+
+	/* Get the reference to aux instance */
+	lll_aux = lll->aux;
+	if (!lll_aux) {
+		struct ll_adv_aux_set *aux;
+
+		aux = ull_adv_aux_acquire(lll);
+		if (!aux) {
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		lll_aux = &aux->lll;
+
+		is_aux_new = 1U;
+	} else {
+		is_aux_new = 0U;
+	}
+
+	/* Get reference to previous secondary PDU data */
+	sec_pdu_prev = lll_adv_aux_data_peek(lll_aux);
+	sec_com_hdr_prev = (void *)&sec_pdu_prev->adv_ext_ind;
+	sec_hdr = (void *)sec_com_hdr_prev->ext_hdr_adi_adv_data;
+	if (!is_aux_new) {
+		sec_hdr_prev = *sec_hdr;
+	} else {
+		/* Initialize only those fields used to copy into new PDU
+		 * buffer.
+		 */
+		sec_pdu_prev->tx_addr = 0U;
+		sec_pdu_prev->rx_addr = 0U;
+		sec_pdu_prev->len = offsetof(struct pdu_adv_com_ext_adv,
+					     ext_hdr_adi_adv_data);
+		*(uint8_t *)&sec_hdr_prev = 0U;
+	}
+	sec_dptr_prev = (uint8_t *)sec_hdr + sizeof(*sec_hdr);
+
+	/* Get reference to new secondary PDU data buffer */
+	sec_pdu = lll_adv_aux_data_alloc(lll_aux, &sec_idx);
+	sec_pdu->type = pri_pdu->type;
+	sec_pdu->rfu = 0U;
+	sec_pdu->chan_sel = 0U;
+
+	sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
+	sec_pdu->rx_addr = sec_pdu_prev->rx_addr;
+
+	sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
+	sec_com_hdr->adv_mode = pri_com_hdr->adv_mode;
+	sec_hdr = (void *)sec_com_hdr->ext_hdr_adi_adv_data;
+	sec_dptr = (uint8_t *)sec_hdr + sizeof(*sec_hdr);
+	*(uint8_t *)sec_hdr = 0U;
+
+	/* AdvA flag */
+	/* NOTE: as we will use auxiliary packet, we remove AdvA in primary
+	 * channel, i.e. do nothing to not add AdvA in the primary PDU.
+	 * AdvA can be either set explicitly (i.e. needs own_addr_type to be
+	 * set), can be copied from primary PDU (i.e. adding AD to existing set)
+	 * or can be copied from previous secondary PDU.
+	 */
+	sec_hdr->adv_addr = 1;
+	if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
+		uint8_t own_addr_type = *(uint8_t *)value;
+
+		sec_pdu->tx_addr = own_addr_type & 0x1;
+	} else if (pri_hdr_prev.adv_addr) {
+		sec_pdu->tx_addr = pri_pdu_prev->tx_addr;
+	} else if (sec_hdr_prev.adv_addr) {
+		sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
+	} else {
+		/* We do not have valid address info, this should not happen */
+		return BT_HCI_ERR_UNSPECIFIED;
+	}
+	pri_pdu->tx_addr = 0U;
+	pri_pdu->rx_addr = 0U;
+
+	if (pri_hdr_prev.adv_addr) {
+		pri_dptr_prev += BDADDR_SIZE;
+	}
+	if (sec_hdr_prev.adv_addr) {
+		sec_dptr_prev += BDADDR_SIZE;
+	}
+	sec_dptr += BDADDR_SIZE;
+
+	/* No TargetA in primary and secondary channel for undirected */
+	/* No CTEInfo flag in primary and secondary channel PDU */
+
+	/* ADI flag */
+	if (pri_hdr_prev.adi) {
+		pri_dptr_prev += sizeof(struct pdu_adv_adi);
+	}
+	pri_hdr->adi = 1;
+	pri_dptr += sizeof(struct pdu_adv_adi);
+	if (sec_hdr_prev.adi) {
+		sec_dptr_prev += sizeof(struct pdu_adv_adi);
+	}
+	sec_hdr->adi = 1;
+	sec_dptr += sizeof(struct pdu_adv_adi);
+
+	/* AuxPtr flag */
+	if (pri_hdr_prev.aux_ptr) {
+		pri_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
+	}
+	pri_hdr->aux_ptr = 1;
+	pri_dptr += sizeof(struct pdu_adv_aux_ptr);
+	if (sec_hdr_prev.aux_ptr) {
+		sec_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
+
+		sec_hdr->aux_ptr = 1;
+		sec_dptr += sizeof(struct pdu_adv_aux_ptr);
+	}
+
+	/* No SyncInfo flag in primary channel PDU */
+	/* Add/Remove SyncInfo flag in secondary channel PDU */
+	if ((sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) ||
+	    (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) &&
+	     sec_hdr_prev.sync_info)) {
+		sec_hdr->sync_info = 1;
+	}
+	if (sec_hdr_prev.sync_info) {
+		sec_dptr_prev += sizeof(struct pdu_adv_sync_info);
+	}
+	if (sec_hdr->sync_info) {
+		sec_dptr += sizeof(struct pdu_adv_sync_info);
+	}
+
+	/* Tx Power flag */
+	if (pri_hdr_prev.tx_pwr) {
+		pri_dptr_prev++;
+
+		/* C1, Tx Power is optional on the LE 1M PHY, and
+		 * reserved for future use on the LE Coded PHY.
+		 */
+		if (lll->phy_p != PHY_CODED) {
+			pri_hdr->tx_pwr = 1;
+			pri_dptr++;
+		} else {
+			sec_hdr->tx_pwr = 1;
+		}
+	}
+	if (sec_hdr_prev.tx_pwr) {
+		sec_dptr_prev++;
+
+		sec_hdr->tx_pwr = 1;
+	}
+	if (sec_hdr->tx_pwr) {
+		sec_dptr++;
+	}
+
+	/* No ACAD in primary channel PDU */
+	/* TODO: ACAD in secondary channel PDU */
+
+	/* Calc primary PDU len */
+	pri_len = ull_adv_aux_hdr_len_get(pri_com_hdr, pri_dptr);
+	ull_adv_aux_hdr_len_fill(pri_com_hdr, pri_len);
+
+	/* set the primary PDU len */
+	pri_pdu->len = pri_len;
+
+	/* Calc previous secondary PDU len */
+	sec_len_prev = ull_adv_aux_hdr_len_get(sec_com_hdr_prev, sec_dptr_prev);
+
+	/* Did we parse beyond PDU length? */
+	if (sec_len_prev > sec_pdu_prev->len) {
+		/* we should not encounter invalid length */
+		/* FIXME: release allocations */
+		return BT_HCI_ERR_UNSPECIFIED;
+	}
+
+	/* Calc current secondary PDU len */
+	sec_len = ull_adv_aux_hdr_len_get(sec_com_hdr, sec_dptr);
+	ull_adv_aux_hdr_len_fill(sec_com_hdr, sec_len);
+
+	/* AD Data, add or remove */
+	if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
+		uint8_t *val_ptr = value;
+
+		ad_len = *val_ptr;
+		val_ptr++;
+
+		ad_data = (void *)sys_get_le32(val_ptr);
+	} else {
+		/* Calc the previous AD data length in auxiliary PDU */
+		ad_len = sec_pdu_prev->len - sec_len_prev;
+		ad_data = sec_dptr_prev;
+	}
+
+	/* set the secondary PDU len */
+	sec_pdu->len = sec_len + ad_len;
+
+	/* Check AdvData overflow */
+	if (sec_pdu->len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
+		/* FIXME: release allocations */
+		return BT_HCI_ERR_PACKET_TOO_LONG;
+	}
+
+	/* Start filling pri and sec PDU payload based on flags from here
+	 * ==============================================================
+	 */
+
+	/* No AdvData in primary channel PDU */
+	/* Fill AdvData in secondary PDU */
+	memcpy(sec_dptr, ad_data, ad_len);
+
+	/* No ACAD in primary channel PDU */
+	/* TODO: Fill ACAD in secondary channel PDU */
+
+	/* Tx Power */
+	if (pri_hdr->tx_pwr) {
+		*--pri_dptr = *--pri_dptr_prev;
+	} else if (sec_hdr->tx_pwr) {
+		*--sec_dptr = *--sec_dptr_prev;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	/* No SyncInfo in primary channel PDU */
+	/* Fill SyncInfo in secondary channel PDU */
+	if (sec_hdr_prev.sync_info) {
+		sec_dptr_prev -= sizeof(struct pdu_adv_sync_info);
+	}
+	if (sec_hdr->sync_info) {
+		sync_info_fill(lll->sync, &sec_dptr);
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+	/* AuxPtr */
+	if (pri_hdr_prev.aux_ptr) {
+		pri_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
+	}
+	ull_adv_aux_ptr_fill(&pri_dptr, lll->phy_s);
+
+	if (sec_hdr_prev.aux_ptr) {
+		sec_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
+
+		ull_adv_aux_ptr_fill(&sec_dptr, lll->phy_s);
+	}
+
+	/* ADI */
+	{
+		struct pdu_adv_adi *pri_adi, *sec_adi;
+		uint16_t did = UINT16_MAX;
+
+		pri_dptr -= sizeof(struct pdu_adv_adi);
+		sec_dptr -= sizeof(struct pdu_adv_adi);
+
+		pri_adi = (void *)pri_dptr;
+		sec_adi = (void *)sec_dptr;
+
+		if (pri_hdr_prev.adi) {
+			struct pdu_adv_adi *pri_adi_prev;
+
+			pri_dptr_prev -= sizeof(struct pdu_adv_adi);
+			sec_dptr_prev -= sizeof(struct pdu_adv_adi);
+
+			/* NOTE: memcpy shall handle overlapping buffers
+			 */
+			memcpy(pri_dptr, pri_dptr_prev,
+			       sizeof(struct pdu_adv_adi));
+			memcpy(sec_dptr, sec_dptr_prev,
+			       sizeof(struct pdu_adv_adi));
+
+			pri_adi_prev = (void *)pri_dptr_prev;
+			did = sys_le16_to_cpu(pri_adi_prev->did);
+		} else {
+			pri_adi->sid = adv->sid;
+			sec_adi->sid = adv->sid;
+		}
+
+		did++;
+
+		pri_adi->did = sys_cpu_to_le16(did);
+		sec_adi->did = sys_cpu_to_le16(did);
+
+		if (adi) {
+			*adi = *pri_adi;
+		}
+	}
+
+	/* No CTEInfo field in primary channel PDU */
+
+	/* No TargetA non-conn non-scan advertising  */
+
+	/* No AdvA in primary channel due to AuxPtr being added */
+
+	/* NOTE: AdvA in aux channel is also filled at enable and RPA
+	 * timeout
+	 */
+	if (sec_hdr->adv_addr) {
+		void *bdaddr;
+
+		if (sec_hdr_prev.adv_addr) {
+			sec_dptr_prev -= BDADDR_SIZE;
+			bdaddr = sec_dptr_prev;
+		} else {
+			pri_dptr_prev -= BDADDR_SIZE;
+			bdaddr = pri_dptr_prev;
+		}
+
+		sec_dptr -= BDADDR_SIZE;
+
+		memcpy(sec_dptr, bdaddr, BDADDR_SIZE);
+	}
+
+	lll_adv_aux_data_enqueue(lll_aux, sec_idx);
+	lll_adv_data_enqueue(lll, pri_idx);
+
+	return 0;
+}
+
+void ull_adv_aux_ptr_fill(uint8_t **dptr, uint8_t phy_s)
+{
+	struct pdu_adv_aux_ptr *aux_ptr;
+
+	*dptr -= sizeof(struct pdu_adv_aux_ptr);
+	aux_ptr = (void *)*dptr;
+
+	/* FIXME: implementation defined */
+	aux_ptr->chan_idx = 0U;
+	aux_ptr->ca = 0U;
+
+	/* NOTE: Aux Offset will be set in advertiser LLL event
+	 */
+	aux_ptr->offs_units = 0U;
+	aux_ptr->offs = 0U;
+
+	aux_ptr->phy = find_lsb_set(phy_s) - 1;
+}
+
+#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
+uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll)
+{
+	return aux_handle_get((void *)lll->hdr.parent);
+}
+
+uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux)
+{
+	uint32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
+	uint32_t ticks_slot_overhead;
+
+	/* TODO: Calc AUX_ADV_IND slot_us */
+	slot_us += 1000;
+
+	/* TODO: active_to_start feature port */
+	aux->evt.ticks_active_to_start = 0;
+	aux->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	aux->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	aux->evt.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = MAX(aux->evt.ticks_active_to_start,
+					  aux->evt.ticks_xtal_to_start);
+	} else {
+		ticks_slot_overhead = 0;
+	}
+
+	return ticks_slot_overhead;
+}
+
+uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
+			   uint32_t ticks_slot_overhead,
+			   uint32_t volatile *ret_cb)
+{
+	uint8_t aux_handle;
+	uint32_t ret;
+
+	aux_handle = aux_handle_get(aux);
+
+	*ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			   (TICKER_ID_ADV_AUX_BASE + aux_handle),
+			   ticks_anchor, 0,
+			   HAL_TICKER_US_TO_TICKS((uint64_t)aux->interval *
+						  625),
+			   TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
+			   (aux->evt.ticks_slot + ticks_slot_overhead),
+			   ticker_cb, aux,
+			   ull_ticker_status_give, (void *)ret_cb);
+
+	return ret;
+}
+
+uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux)
+{
+	uint32_t volatile ret_cb;
+	uint8_t aux_handle;
+	void *mark;
+	uint32_t ret;
+
+	mark = ull_disable_mark(aux);
+	LL_ASSERT(mark == aux);
+
+	aux_handle = aux_handle_get(aux);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_ADV_AUX_BASE + aux_handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret) {
+		mark = ull_disable_mark(aux);
+		LL_ASSERT(mark == aux);
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	ret = ull_disable(&aux->lll);
+	LL_ASSERT(!ret);
+
+	mark = ull_disable_unmark(aux);
+	LL_ASSERT(mark == aux);
+
+	aux->is_started = 0U;
+
+	return 0;
+}
+
+struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll)
+{
+	struct lll_adv_aux *lll_aux;
+	struct ll_adv_aux_set *aux;
+
+	aux = aux_acquire();
+	if (!aux) {
+		return aux;
+	}
+
+	lll_aux = &aux->lll;
+	lll->aux = lll_aux;
+	lll_aux->adv = lll;
+
+	/* NOTE: ull_hdr_init(&aux->ull); is done on start */
+	lll_hdr_init(lll_aux, aux);
+
+	aux->is_started = 0U;
+
+	return aux;
+}
+
+void ull_adv_aux_release(struct ll_adv_aux_set *aux)
+{
+	aux_release(aux);
+}
+
+void ull_adv_aux_offset_get(struct ll_adv_set *adv)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, mfy_aux_offset_get};
+	uint32_t ret;
+
+	mfy.param = adv;
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
+			     &mfy);
+	LL_ASSERT(!ret);
+}
+
+struct pdu_adv_aux_ptr *ull_adv_aux_lll_offset_fill(uint32_t ticks_offset,
+						    uint32_t start_us,
+						    struct pdu_adv *pdu)
+{
+	struct pdu_adv_com_ext_adv *pri_com_hdr;
+	struct pdu_adv_aux_ptr *aux;
+	struct pdu_adv_hdr *h;
+	uint32_t offs;
+	uint8_t *ptr;
+
+	pri_com_hdr = (void *)&pdu->adv_ext_ind;
+	h = (void *)pri_com_hdr->ext_hdr_adi_adv_data;
+	ptr = (uint8_t *)h + sizeof(*h);
+
+	if (h->adv_addr) {
+		ptr += BDADDR_SIZE;
+	}
+
+	if (h->adi) {
+		ptr += sizeof(struct pdu_adv_adi);
+	}
+
+	aux = (void *)ptr;
+	offs = HAL_TICKER_TICKS_TO_US(ticks_offset) - start_us;
+	offs = offs / OFFS_UNIT_30_US;
+	if (!!(offs >> 13)) {
+		aux->offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
+		aux->offs_units = 1U;
+	} else {
+		aux->offs = offs;
+		aux->offs_units = 0U;
+	}
+
+	return aux;
+}
+
+static int init_reset(void)
+{
+	/* Initialize adv aux pool. */
+	mem_init(ll_adv_aux_pool, sizeof(struct ll_adv_aux_set),
+		 sizeof(ll_adv_aux_pool) / sizeof(struct ll_adv_aux_set),
+		 &adv_aux_free);
+
+	return 0;
+}
+
+static inline struct ll_adv_aux_set *aux_acquire(void)
+{
+	return mem_acquire(&adv_aux_free);
+}
+
+static inline void aux_release(struct ll_adv_aux_set *aux)
+{
+	mem_release(aux, &adv_aux_free);
+}
+
+static inline uint8_t aux_handle_get(struct ll_adv_aux_set *aux)
+{
+	return mem_index_get(aux, ll_adv_aux_pool,
+			     sizeof(struct ll_adv_aux_set));
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+static inline void sync_info_fill(struct lll_adv_sync *lll_sync,
+				  uint8_t **dptr)
+{
+	struct ll_adv_sync_set *sync;
+	struct pdu_adv_sync_info *si;
+
+	*dptr -= sizeof(*si);
+	si = (void *)*dptr;
+
+	/* NOTE: sync offset and offset unit filled by secondary prepare */
+	si->offs_units = 0U;
+	si->offs = 0U;
+
+	sync = (void *)HDR_LLL2EVT(lll_sync);
+	si->interval = sys_cpu_to_le16(sync->interval);
+	memcpy(si->sca_chm, lll_sync->data_chan_map,
+	       sizeof(si->sca_chm));
+	si->sca_chm[4] &= 0x1f;
+	si->sca_chm[4] |= lll_clock_sca_local_get() << 5;
+	memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
+	memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));
+
+	si->evt_cntr = 0U; /* NOTE: Filled by secondary prepare */
+}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+static void mfy_aux_offset_get(void *param)
+{
+	struct ll_adv_set *adv = param;
+	struct ll_adv_aux_set *aux;
+	uint32_t ticks_to_expire;
+	uint32_t ticks_current;
+	struct pdu_adv *pdu;
+	uint8_t ticker_id;
+	uint8_t retry;
+	uint8_t id;
+
+	aux = (void *)HDR_LLL2EVT(adv->lll.aux);
+	ticker_id = TICKER_ID_ADV_AUX_BASE + aux_handle_get(aux);
+
+	id = TICKER_NULL;
+	ticks_to_expire = 0U;
+	ticks_current = 0U;
+	retry = 4U;
+	do {
+		uint32_t volatile ret_cb;
+		uint32_t ticks_previous;
+		uint32_t ret;
+
+		ticks_previous = ticks_current;
+
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR,
+					   TICKER_USER_ID_ULL_LOW,
+					   &id,
+					   &ticks_current, &ticks_to_expire,
+					   ticker_op_cb, (void *)&ret_cb);
+		if (ret == TICKER_STATUS_BUSY) {
+			while (ret_cb == TICKER_STATUS_BUSY) {
+				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
+						 TICKER_USER_ID_ULL_LOW);
+			}
+		}
+
+		LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
+
+		LL_ASSERT((ticks_current == ticks_previous) || retry--);
+
+		LL_ASSERT(id != TICKER_NULL);
+	} while (id != ticker_id);
+
+	/* Store the ticks offset for population in other advertising primary
+	 * channel PDUs.
+	 */
+	aux->lll.ticks_offset = ticks_to_expire;
+
+	/* NOTE: as remainder used in scheduling primary PDU not available,
+	 * compensate with a probable jitter of one ticker resolution unit that
+	 * would be included in the packet timer capture when scheduling next
+	 * advertising primary channel PDU.
+	 */
+	aux->lll.ticks_offset +=
+		HAL_TICKER_US_TO_TICKS(EVENT_TICKER_RES_MARGIN_US);
+
+	/* FIXME: we are in ULL_LOW context, fill offset in LLL context */
+	pdu = lll_adv_data_curr_get(&adv->lll);
+	ull_adv_aux_lll_offset_fill(ticks_to_expire, 0, pdu);
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_aux_prepare};
+	static struct lll_prepare_param p;
+	struct ll_adv_aux_set *aux = param;
+	struct lll_adv_aux *lll;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_A(1);
+
+	lll = &aux->lll;
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&aux->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+			     TICKER_USER_ID_LLL, 0, &mfy);
+	LL_ASSERT(!ret);
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+	struct ll_adv_set *adv;
+
+	adv = (void *)HDR_LLL2EVT(lll->adv);
+	if (adv->lll.sync) {
+		struct ll_adv_sync_set *sync;
+
+		sync  = (void *)HDR_LLL2EVT(adv->lll.sync);
+		if (sync->is_started) {
+			ull_adv_sync_offset_get(adv);
+		}
+	}
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+
+	DEBUG_RADIO_PREPARE_A(1);
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	*((uint32_t volatile *)param) = status;
+}
+#else /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
+
+static int init_reset(void)
+{
+	return 0;
+}
+#endif /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h	(working copy)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
+
+/* Bitmask value returned by ull_adv_is_enabled() */
+#define ULL_ADV_ENABLED_BITMASK_ENABLED  BIT(0)
+
+#if defined(CONFIG_BT_CTLR_ADV_SET)
+#define BT_CTLR_ADV_SET CONFIG_BT_CTLR_ADV_SET
+#else /* CONFIG_BT_CTLR_ADV_SET */
+#define BT_CTLR_ADV_SET 1
+#endif /* CONFIG_BT_CTLR_ADV_SET */
+
+/* Helper functions to initialise and reset ull_adv module */
+int ull_adv_init(void);
+int ull_adv_reset(void);
+
+/* Return ll_adv_set context (unconditional) */
+struct ll_adv_set *ull_adv_set_get(uint8_t handle);
+
+/* Return the adv set handle given the adv set instance */
+uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
+
+/* Return ll_adv_set context if enabled */
+struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle);
+
+/* Return enabled status of a set */
+int ull_adv_is_enabled(uint8_t handle);
+
+/* Return filter policy used */
+uint32_t ull_adv_filter_pol_get(uint8_t handle);
+
+/* Return ll_adv_set context if created */
+struct ll_adv_set *ull_adv_is_created_get(uint8_t handle);
+
+/* Helper function to construct AD data */
+uint8_t ull_adv_data_set(struct ll_adv_set *adv, uint8_t len,
+			 uint8_t const *const data);
+
+/* Helper function to construct SR data */
+uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
+			 uint8_t const *const data);
+
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+
+#define ULL_ADV_PDU_HDR_FIELD_ADVA      BIT(0)
+#define ULL_ADV_PDU_HDR_FIELD_SYNC_INFO BIT(5)
+#define ULL_ADV_PDU_HDR_FIELD_AD_DATA   BIT(8)
+
+/* helper function to handle adv done events */
+void ull_adv_done(struct node_rx_event_done *done);
+
+/* Helper functions to initialise and reset ull_adv_aux module */
+int ull_adv_aux_init(void);
+int ull_adv_aux_reset(void);
+
+/* Helper to read back random address */
+uint8_t const *ll_adv_aux_random_addr_get(struct ll_adv_set const *const adv,
+				       uint8_t *const addr);
+
+/* helper function to initialize event timings */
+uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux);
+
+/* helper function to start auxiliary advertising */
+uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
+			   uint32_t ticks_slot_overhead,
+			   uint32_t volatile *ret_cb);
+
+/* helper function to stop auxiliary advertising */
+uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux);
+
+/* helper function to acquire and initialize auxiliary advertising instance */
+struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll);
+
+/* helper function to release auxiliary advertising instance */
+void ull_adv_aux_release(struct ll_adv_aux_set *aux);
+
+/* helper function to schedule a mayfly to get aux offset */
+void ull_adv_aux_offset_get(struct ll_adv_set *adv);
+
+/* helper function to set/clear common extended header format fields */
+uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
+				  uint16_t sec_hdr_add_fields,
+				  uint16_t sec_hdr_rem_fields,
+				  void *value, struct pdu_adv_adi *adi);
+
+/* helper function to calculate common ext adv payload header length */
+static inline uint8_t
+ull_adv_aux_hdr_len_get(struct pdu_adv_com_ext_adv *com_hdr, uint8_t *dptr)
+{
+	uint8_t len;
+
+	len = dptr - (uint8_t *)com_hdr;
+	if (len <= (offsetof(struct pdu_adv_com_ext_adv, ext_hdr_adi_adv_data) +
+		    sizeof(struct pdu_adv_hdr))) {
+		len = offsetof(struct pdu_adv_com_ext_adv,
+			       ext_hdr_adi_adv_data);
+	}
+
+	return len;
+}
+
+/* helper function to fill common ext adv payload header length */
+static inline void
+ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv *com_hdr, uint8_t len)
+{
+	com_hdr->ext_hdr_len = len - offsetof(struct pdu_adv_com_ext_adv,
+					      ext_hdr_adi_adv_data);
+
+}
+
+/* helper function to fill the aux ptr structure in common ext adv payload */
+void ull_adv_aux_ptr_fill(uint8_t **dptr, uint8_t phy_s);
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+int ull_adv_sync_init(void);
+int ull_adv_sync_reset(void);
+
+/* helper function to start periodic advertising */
+uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
+			 uint32_t volatile *ret_cb);
+
+/* helper function to schedule a mayfly to get sync offset */
+void ull_adv_sync_offset_get(struct ll_adv_set *adv);
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c	(working copy)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_adv_iso
+#include "common/log.h"
+#include "hal/debug.h"
+
+uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
+		      uint32_t sdu_interval, uint16_t max_sdu,
+		      uint16_t max_latency, uint8_t rtn, uint8_t phy,
+		      uint8_t packing, uint8_t framing, uint8_t encryption,
+		      uint8_t *bcode)
+{
+	/* TODO: Implement */
+	ARG_UNUSED(big_handle);
+	ARG_UNUSED(adv_handle);
+	ARG_UNUSED(num_bis);
+	ARG_UNUSED(sdu_interval);
+	ARG_UNUSED(max_sdu);
+	ARG_UNUSED(max_latency);
+	ARG_UNUSED(rtn);
+	ARG_UNUSED(phy);
+	ARG_UNUSED(packing);
+	ARG_UNUSED(framing);
+	ARG_UNUSED(encryption);
+	ARG_UNUSED(bcode[16]);
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+uint8_t ll_big_test_create(uint8_t big_handle, uint8_t adv_handle,
+			   uint8_t num_bis, uint32_t sdu_interval,
+			   uint16_t iso_interval, uint8_t nse, uint16_t max_sdu,
+			   uint16_t max_pdu, uint8_t phy, uint8_t packing,
+			   uint8_t framing, uint8_t bn, uint8_t irc,
+			   uint8_t pto, uint8_t encryption, uint8_t *bcode)
+{
+	/* TODO: Implement */
+	ARG_UNUSED(big_handle);
+	ARG_UNUSED(adv_handle);
+	ARG_UNUSED(num_bis);
+	ARG_UNUSED(sdu_interval);
+	ARG_UNUSED(iso_interval);
+	ARG_UNUSED(nse);
+	ARG_UNUSED(max_sdu);
+	ARG_UNUSED(max_pdu);
+	ARG_UNUSED(phy);
+	ARG_UNUSED(packing);
+	ARG_UNUSED(framing);
+	ARG_UNUSED(bn);
+	ARG_UNUSED(irc);
+	ARG_UNUSED(pto);
+	ARG_UNUSED(encryption);
+	ARG_UNUSED(bcode);
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+uint8_t ll_big_terminate(uint8_t big_handle, uint8_t reason)
+{
+	/* TODO: Implement */
+	ARG_UNUSED(big_handle);
+	ARG_UNUSED(reason);
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c	(working copy)
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2017-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "hal/cpu.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_adv.h"
+#include "lll_adv_sync.h"
+#include "lll_adv_internal.h"
+
+#include "ull_adv_types.h"
+
+#include "ull_internal.h"
+#include "ull_chan_internal.h"
+#include "ull_adv_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_adv_sync
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static inline struct ll_adv_sync_set *sync_acquire(void);
+static inline void sync_release(struct ll_adv_sync_set *sync);
+static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
+static inline uint8_t sync_stop(struct ll_adv_sync_set *sync);
+static void mfy_sync_offset_get(void *param);
+static inline struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu);
+static inline void sync_info_offset_fill(struct pdu_adv_sync_info *si,
+					 uint32_t ticks_offset,
+					 uint32_t start_us);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param);
+static void ticker_op_cb(uint32_t status, void *param);
+
+static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
+static void *adv_sync_free;
+
+uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
+{
+	struct pdu_adv_hdr *ter_hdr, ter_hdr_prev;
+	struct pdu_adv_com_ext_adv *ter_com_hdr;
+	uint8_t *ter_dptr_prev, *ter_dptr;
+	struct lll_adv_sync *lll_sync;
+	struct ll_adv_sync_set *sync;
+	struct pdu_adv *ter_pdu;
+	struct ll_adv_set *adv;
+	uint8_t ter_len;
+
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	lll_sync = adv->lll.sync;
+	if (!lll_sync) {
+		struct lll_adv *lll;
+		int err;
+
+		sync = sync_acquire();
+		if (!sync) {
+			return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+		}
+
+		lll = &adv->lll;
+		lll_sync = &sync->lll;
+		lll->sync = lll_sync;
+		lll_sync->adv = lll;
+
+		/* NOTE: ull_hdr_init(&sync->ull); is done on start */
+		lll_hdr_init(lll_sync, sync);
+
+		err = util_aa_le32(lll_sync->access_addr);
+		LL_ASSERT(!err);
+
+		lll_csrand_get(lll_sync->crc_init, sizeof(lll_sync->crc_init));
+
+		lll_sync->latency_prepare = 0;
+		lll_sync->latency_event = 0;
+		lll_sync->event_counter = 0;
+
+		lll_sync->data_chan_count =
+			ull_chan_map_get(lll_sync->data_chan_map);
+		lll_sync->data_chan_id = 0;
+
+		sync->is_enabled = 0U;
+		sync->is_started = 0U;
+	} else {
+		sync = (void *)HDR_LLL2EVT(lll_sync);
+	}
+
+	sync->interval = interval;
+
+	ter_pdu = lll_adv_sync_data_peek(lll_sync);
+	ter_pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
+	ter_pdu->rfu = 0U;
+	ter_pdu->chan_sel = 0U;
+	ter_pdu->tx_addr = 0U;
+	ter_pdu->rx_addr = 0U;
+
+	ter_com_hdr = (void *)&ter_pdu->adv_ext_ind;
+	ter_hdr = (void *)ter_com_hdr->ext_hdr_adi_adv_data;
+	ter_dptr = (uint8_t *)ter_hdr + sizeof(*ter_hdr);
+	ter_hdr_prev = *ter_hdr;
+	*(uint8_t *)ter_hdr = 0U;
+	ter_dptr_prev = ter_dptr;
+
+	/* Non-connectable and Non-scannable adv mode */
+	ter_com_hdr->adv_mode = 0U;
+
+	/* No AdvA */
+	/* No TargetA */
+
+	/* TODO: CTEInfo */
+
+	/* No ADI */
+
+	/* TODO: AuxPtr */
+
+	/* No SyncInfo */
+
+	/* TODO: TxPower */
+	if (flags & BT_HCI_LE_ADV_PROP_TX_POWER) {
+		/* TODO: add/remove Tx Power in AUX_SYNC_IND PDU */
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	/* TODO: ACAD */
+
+	/* TODO: AdvData */
+
+	/* Calc tertiary PDU len */
+	ter_len = ull_adv_aux_hdr_len_get(ter_com_hdr, ter_dptr);
+	ull_adv_aux_hdr_len_fill(ter_com_hdr, ter_len);
+
+	ter_pdu->len = ter_len;
+
+	return 0;
+}
+
+uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
+				uint8_t const *const data)
+{
+	/* TODO */
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
+{
+	struct lll_adv_sync *lll_sync;
+	struct ll_adv_sync_set *sync;
+	struct ll_adv_set *adv;
+
+	adv = ull_adv_is_created_get(handle);
+	if (!adv) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	lll_sync = adv->lll.sync;
+	if (!lll_sync) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	sync = (void *)HDR_LLL2EVT(lll_sync);
+
+	if (!enable) {
+		uint8_t err;
+
+		if (!sync->is_enabled) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		if (!sync->is_started) {
+			sync->is_enabled = 0U;
+
+			return 0;
+		}
+
+		/* Remove sync_info from auxiliary PDU */
+		err = ull_adv_aux_hdr_set_clear(adv, 0,
+						ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
+						NULL, NULL);
+		if (err) {
+			return err;
+		}
+
+		err = sync_stop(sync);
+		if (err) {
+			return err;
+		}
+
+		sync->is_started = 0U;
+		sync->is_enabled = 0U;
+
+		return 0;
+	}
+
+	/* TODO: Check for periodic data being complete */
+
+	/* TODO: Check packet too long */
+
+	if (sync->is_enabled) {
+		/* TODO: Enabling an already enabled advertising changes its
+		 * random address.
+		 */
+	} else {
+		sync->is_enabled = 1U;
+	}
+
+	if (adv->is_enabled && !sync->is_started) {
+		volatile uint32_t ret_cb = TICKER_STATUS_BUSY;
+		uint32_t ticks_anc_sync;
+		uint8_t err;
+
+		/* FIXME: Find absolute ticks until after auxliary PDU on air
+		 *        to place the periodic advertising PDU.
+		 */
+		ticks_anc_sync = ticker_ticks_now_get();
+
+		/* Add sync_info into auxiliary PDU */
+		err = ull_adv_aux_hdr_set_clear(adv,
+						ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
+						0, NULL, NULL);
+		if (err) {
+			return err;
+		}
+
+		ull_hdr_init(&sync->ull);
+
+		err = ull_adv_sync_start(sync, ticks_anc_sync, &ret_cb);
+		if (err) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		sync->is_started = 1U;
+	}
+
+	return 0;
+}
+
+int ull_adv_sync_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_adv_sync_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll)
+{
+	return sync_handle_get((void *)lll->hdr.parent);
+}
+
+uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
+			 uint32_t volatile *ret_cb)
+{
+	uint32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
+	uint32_t ticks_slot_overhead;
+	uint32_t interval_us;
+	uint8_t sync_handle;
+	uint32_t ret;
+
+	/* TODO: Calc AUX_SYNC_IND slot_us */
+	slot_us += 1000;
+
+	/* TODO: active_to_start feature port */
+	sync->evt.ticks_active_to_start = 0;
+	sync->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	sync->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	sync->evt.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = MAX(sync->evt.ticks_active_to_start,
+					  sync->evt.ticks_xtal_to_start);
+	} else {
+		ticks_slot_overhead = 0;
+	}
+
+	interval_us = (uint32_t)sync->interval * 1250U;
+
+	sync_handle = sync_handle_get(sync);
+
+	*ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			   (TICKER_ID_ADV_SYNC_BASE + sync_handle),
+			   ticks_anchor, 0,
+			   HAL_TICKER_US_TO_TICKS(interval_us),
+			   HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
+			   (sync->evt.ticks_slot + ticks_slot_overhead),
+			   ticker_cb, sync,
+			   ull_ticker_status_give, (void *)ret_cb);
+
+	return ret;
+}
+
+void ull_adv_sync_offset_get(struct ll_adv_set *adv)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
+	uint32_t ret;
+
+	mfy.param = adv;
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
+			     &mfy);
+	LL_ASSERT(!ret);
+}
+
+static int init_reset(void)
+{
+	/* Initialize adv sync pool. */
+	mem_init(ll_adv_sync_pool, sizeof(struct ll_adv_sync_set),
+		 sizeof(ll_adv_sync_pool) / sizeof(struct ll_adv_sync_set),
+		 &adv_sync_free);
+
+	return 0;
+}
+
+static inline struct ll_adv_sync_set *sync_acquire(void)
+{
+	return mem_acquire(&adv_sync_free);
+}
+
+static inline void sync_release(struct ll_adv_sync_set *sync)
+{
+	mem_release(sync, &adv_sync_free);
+}
+
+static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync)
+{
+	return mem_index_get(sync, ll_adv_sync_pool,
+			     sizeof(struct ll_adv_sync_set));
+}
+
+static inline uint8_t sync_stop(struct ll_adv_sync_set *sync)
+{
+	uint32_t volatile ret_cb;
+	uint8_t sync_handle;
+	void *mark;
+	uint32_t ret;
+
+	mark = ull_disable_mark(sync);
+	LL_ASSERT(mark == sync);
+
+	sync_handle = sync_handle_get(sync);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_ADV_SYNC_BASE + sync_handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret) {
+		mark = ull_disable_mark(sync);
+		LL_ASSERT(mark == sync);
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	ret = ull_disable(&sync->lll);
+	LL_ASSERT(!ret);
+
+	mark = ull_disable_unmark(sync);
+	LL_ASSERT(mark == sync);
+
+	return 0;
+}
+
+static void mfy_sync_offset_get(void *param)
+{
+	struct ll_adv_set *adv = param;
+	struct lll_adv_sync *lll_sync;
+	struct ll_adv_sync_set *sync;
+	struct pdu_adv_sync_info *si;
+	uint32_t ticks_to_expire;
+	uint32_t ticks_current;
+	struct pdu_adv *pdu;
+	uint8_t ticker_id;
+	uint8_t retry;
+	uint8_t id;
+
+	lll_sync = adv->lll.sync;
+	sync = (void *)HDR_LLL2EVT(lll_sync);
+	ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
+
+	id = TICKER_NULL;
+	ticks_to_expire = 0U;
+	ticks_current = 0U;
+	retry = 4U;
+	do {
+		uint32_t volatile ret_cb;
+		uint32_t ticks_previous;
+		uint32_t ret;
+
+		ticks_previous = ticks_current;
+
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR,
+					   TICKER_USER_ID_ULL_LOW,
+					   &id,
+					   &ticks_current, &ticks_to_expire,
+					   ticker_op_cb, (void *)&ret_cb);
+		if (ret == TICKER_STATUS_BUSY) {
+			while (ret_cb == TICKER_STATUS_BUSY) {
+				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
+						 TICKER_USER_ID_ULL_LOW);
+			}
+		}
+
+		LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
+
+		LL_ASSERT((ticks_current == ticks_previous) || retry--);
+
+		LL_ASSERT(id != TICKER_NULL);
+	} while (id != ticker_id);
+
+	/* NOTE: as remainder not used in scheduling primary PDU
+	 * packet timer starts transmission after 1 tick hence the +1.
+	 */
+	lll_sync->ticks_offset = ticks_to_expire + 1;
+
+	pdu = lll_adv_aux_data_curr_get(adv->lll.aux);
+	si = sync_info_get(pdu);
+	sync_info_offset_fill(si, ticks_to_expire, 0);
+	si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare;
+}
+
+static inline struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu)
+{
+	struct pdu_adv_com_ext_adv *p;
+	struct pdu_adv_hdr *h;
+	uint8_t *ptr;
+
+	p = (void *)&pdu->adv_ext_ind;
+	h = (void *)p->ext_hdr_adi_adv_data;
+	ptr = (uint8_t *)h + sizeof(*h);
+
+	if (h->adv_addr) {
+		ptr += BDADDR_SIZE;
+	}
+
+	if (h->adi) {
+		ptr += sizeof(struct pdu_adv_adi);
+	}
+
+	if (h->aux_ptr) {
+		ptr += sizeof(struct pdu_adv_aux_ptr);
+	}
+
+	return (void *)ptr;
+}
+
+static inline void sync_info_offset_fill(struct pdu_adv_sync_info *si,
+					 uint32_t ticks_offset,
+					 uint32_t start_us)
+{
+	uint32_t offs;
+
+	offs = HAL_TICKER_TICKS_TO_US(ticks_offset) - start_us;
+	offs = offs / OFFS_UNIT_30_US;
+	if (!!(offs >> 13)) {
+		si->offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
+		si->offs_units = 1U;
+	} else {
+		si->offs = offs;
+		si->offs_units = 0U;
+	}
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_sync_prepare};
+	static struct lll_prepare_param p;
+	struct ll_adv_sync_set *sync = param;
+	struct lll_adv_sync *lll;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_A(1);
+
+	lll = &sync->lll;
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&sync->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+			     TICKER_USER_ID_LLL, 0, &mfy);
+	LL_ASSERT(!ret);
+
+	DEBUG_RADIO_PREPARE_A(1);
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	*((uint32_t volatile *)param) = status;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_types.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_types.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_adv_types.h	(working copy)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct ll_adv_set {
+	struct evt_hdr evt;
+	struct ull_hdr ull;
+	struct lll_adv lll;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	memq_link_t        *link_cc_free;
+	struct node_rx_pdu *node_rx_cc_free;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint32_t interval;
+	uint8_t  rnd_addr[BDADDR_SIZE];
+	uint8_t  sid:4;
+	uint8_t  is_created:1;
+#if defined(CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING)
+	uint8_t  hci_handle;
+#endif
+	uint16_t event_counter;
+	uint16_t max_events;
+	uint32_t ticks_remain_duration;
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	uint16_t interval;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	uint8_t is_enabled:1;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  own_addr_type:2;
+	uint8_t  id_addr_type:1;
+	uint8_t  id_addr[BDADDR_SIZE];
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+};
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+struct ll_adv_aux_set {
+	struct evt_hdr     evt;
+	struct ull_hdr     ull;
+	struct lll_adv_aux lll;
+
+	uint16_t interval;
+
+	uint8_t is_started:1;
+};
+
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+struct ll_adv_sync_set {
+	struct evt_hdr      evt;
+	struct ull_hdr      ull;
+	struct lll_adv_sync lll;
+
+	uint16_t interval;
+
+	uint8_t is_enabled:1;
+	uint8_t is_started:1;
+};
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan.c	(working copy)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <zephyr/types.h>
+
+#include "util/util.h"
+
+/* Initial channel map indicating Used and Unused data channels.
+ * The HCI LE Set Host Channel Classification command allows the Host to
+ * specify a channel classification for the data, secondary advertising,
+ * periodic, and isochronous physical channels based on its local information.
+ */
+static uint8_t map[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0x1F};
+static uint8_t count = 37U;
+
+int ull_chan_reset(void)
+{
+	/* initialise connection channel map */
+	map[0] = 0xFF;
+	map[1] = 0xFF;
+	map[2] = 0xFF;
+	map[3] = 0xFF;
+	map[4] = 0x1F;
+	count = 37U;
+
+	return 0;
+}
+
+uint8_t ull_chan_map_get(uint8_t *const chan_map)
+{
+	memcpy(chan_map, map, sizeof(map));
+
+	return count;
+}
+
+void ull_chan_map_set(uint8_t const *const chan_map)
+{
+	memcpy(map, chan_map, sizeof(map));
+	count = util_ones_count_get(map, sizeof(map));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_chan_internal.h	(working copy)
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int ull_chan_reset(void);
+uint8_t ull_chan_map_get(uint8_t *const chan_map);
+void ull_chan_map_set(uint8_t const *const chan_map);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn.c	(working copy)
@@ -0,0 +1,6348 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <zephyr.h>
+#include <device.h>
+#include <bluetooth/bluetooth.h>
+#include <sys/byteorder.h>
+
+#include "hal/ecb.h"
+#include "hal/ccm.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mfifo.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_clock.h"
+#include "lll_conn.h"
+#include "lll_tim_internal.h"
+
+#include "ull_conn_types.h"
+#include "ull_internal.h"
+#include "ull_sched_internal.h"
+#include "ull_chan_internal.h"
+#include "ull_conn_internal.h"
+#include "ull_slave_internal.h"
+#include "ull_master_internal.h"
+
+#include "ll.h"
+#include "ll_feat.h"
+#include "ll_settings.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_conn
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_CTLR_USER_EXT)
+#include "ull_vendor.h"
+#endif /* CONFIG_BT_CTLR_USER_EXT */
+
+inline void ull_conn_upd_curr_reset(void);
+
+static int init_reset(void);
+
+static void ticker_update_conn_op_cb(uint32_t status, void *param);
+static void ticker_stop_conn_op_cb(uint32_t status, void *param);
+static void ticker_start_conn_op_cb(uint32_t status, void *param);
+
+static inline void disable(uint16_t handle);
+static void conn_cleanup(struct ll_conn *conn, uint8_t reason);
+static void tx_demux(void *param);
+static struct node_tx *tx_ull_dequeue(struct ll_conn *conn, struct node_tx *tx);
+static void tx_ull_flush(struct ll_conn *conn);
+static void tx_lll_flush(void *param);
+
+#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
+static int empty_data_start_release(struct ll_conn *conn, struct node_tx *tx);
+#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
+
+static inline void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx);
+static inline void event_fex_prep(struct ll_conn *conn);
+static inline void event_vex_prep(struct ll_conn *conn);
+static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
+				      uint32_t ticks_at_expire);
+static inline void event_ch_map_prep(struct ll_conn *conn,
+				     uint16_t event_counter);
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static bool is_enc_req_pause_tx(struct ll_conn *conn);
+static inline void event_enc_prep(struct ll_conn *conn);
+static int enc_rsp_send(struct ll_conn *conn);
+static int start_enc_rsp_send(struct ll_conn *conn,
+			      struct pdu_data *pdu_ctrl_tx);
+static inline bool ctrl_is_unexpected(struct ll_conn *conn, uint8_t opcode);
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static inline void event_conn_param_prep(struct ll_conn *conn,
+					 uint16_t event_counter,
+					 uint32_t ticks_at_expire);
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+static inline void event_ping_prep(struct ll_conn *conn);
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static inline void event_len_prep(struct ll_conn *conn);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static inline void event_phy_req_prep(struct ll_conn *conn);
+static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
+					  uint16_t event_counter);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+static inline void ctrl_tx_pre_ack(struct ll_conn *conn,
+				   struct pdu_data *pdu_tx);
+static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
+			       struct pdu_data *pdu_tx);
+static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
+			  struct pdu_data *pdu_rx, struct ll_conn *conn);
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate);
+#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */
+
+#if !defined(BT_CTLR_USER_TX_BUFFER_OVERHEAD)
+#define BT_CTLR_USER_TX_BUFFER_OVERHEAD 0
+#endif /* BT_CTLR_USER_TX_BUFFER_OVERHEAD */
+
+#define CONN_TX_BUF_SIZE MROUND(offsetof(struct node_tx, pdu) + \
+				offsetof(struct pdu_data, lldata) + \
+				(CONFIG_BT_CTLR_TX_BUFFER_SIZE + \
+				BT_CTLR_USER_TX_BUFFER_OVERHEAD))
+
+/**
+ * One connection may take up to 4 TX buffers for procedures
+ * simultaneously, for example 2 for encryption, 1 for termination,
+ * and 1 one that is in flight and has not been returned to the pool
+ */
+#define CONN_TX_CTRL_BUFFERS (4 * CONFIG_BT_CTLR_LLCP_CONN)
+#define CONN_TX_CTRL_BUF_SIZE MROUND(offsetof(struct node_tx, pdu) + \
+				     offsetof(struct pdu_data, llctrl) + \
+				     sizeof(struct pdu_data_llctrl))
+
+static MFIFO_DEFINE(conn_tx, sizeof(struct lll_tx), CONFIG_BT_CTLR_TX_BUFFERS);
+static MFIFO_DEFINE(conn_ack, sizeof(struct lll_tx),
+		    (CONFIG_BT_CTLR_TX_BUFFERS + CONN_TX_CTRL_BUFFERS));
+
+
+static struct {
+	void *free;
+	uint8_t pool[CONN_TX_BUF_SIZE * CONFIG_BT_CTLR_TX_BUFFERS];
+} mem_conn_tx;
+
+static struct {
+	void *free;
+	uint8_t pool[CONN_TX_CTRL_BUF_SIZE * CONN_TX_CTRL_BUFFERS];
+} mem_conn_tx_ctrl;
+
+static struct {
+	void *free;
+	uint8_t pool[sizeof(memq_link_t) *
+		  (CONFIG_BT_CTLR_TX_BUFFERS + CONN_TX_CTRL_BUFFERS)];
+} mem_link_tx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static uint16_t default_tx_octets;
+static uint16_t default_tx_time;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static uint8_t default_phy_tx;
+static uint8_t default_phy_rx;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+static struct ll_conn conn_pool[CONFIG_BT_MAX_CONN];
+static struct ll_conn *conn_upd_curr;
+static void *conn_free;
+
+struct ll_conn *ll_conn_acquire(void)
+{
+	return mem_acquire(&conn_free);
+}
+
+void ll_conn_release(struct ll_conn *conn)
+{
+	mem_release(conn, &conn_free);
+}
+
+uint16_t ll_conn_handle_get(struct ll_conn *conn)
+{
+	return mem_index_get(conn, conn_pool, sizeof(struct ll_conn));
+}
+
+struct ll_conn *ll_conn_get(uint16_t handle)
+{
+	return mem_get(conn_pool, sizeof(struct ll_conn), handle);
+}
+
+struct ll_conn *ll_connected_get(uint16_t handle)
+{
+	struct ll_conn *conn;
+
+	if (handle >= CONFIG_BT_MAX_CONN) {
+		return NULL;
+	}
+
+	conn = ll_conn_get(handle);
+	if (conn->lll.handle != handle) {
+		return NULL;
+	}
+
+	return conn;
+}
+
+void *ll_tx_mem_acquire(void)
+{
+	return mem_acquire(&mem_conn_tx.free);
+}
+
+void ll_tx_mem_release(void *tx)
+{
+	mem_release(tx, &mem_conn_tx.free);
+}
+
+int ll_tx_mem_enqueue(uint16_t handle, void *tx)
+{
+#if defined(CONFIG_BT_CTLR_THROUGHPUT)
+#define BT_CTLR_THROUGHPUT_PERIOD 1000000000UL
+	static uint32_t tx_rate;
+	static uint32_t tx_cnt;
+#endif /* CONFIG_BT_CTLR_THROUGHPUT */
+	struct lll_tx *lll_tx;
+	struct ll_conn *conn;
+	uint8_t idx;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return -EINVAL;
+	}
+
+	idx = MFIFO_ENQUEUE_GET(conn_tx, (void **) &lll_tx);
+	if (!lll_tx) {
+		return -ENOBUFS;
+	}
+
+	lll_tx->handle = handle;
+	lll_tx->node = tx;
+
+	MFIFO_ENQUEUE(conn_tx, idx);
+
+	if (ull_ref_get(&conn->ull)) {
+		static memq_link_t link;
+		static struct mayfly mfy = {0, 0, &link, NULL, tx_demux};
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+		if (tx_cnt >= CONFIG_BT_CTLR_TX_BUFFERS) {
+			uint8_t previous, force_md_cnt;
+
+			force_md_cnt = force_md_cnt_calc(&conn->lll, tx_rate);
+			previous = lll_conn_force_md_cnt_set(force_md_cnt);
+			if (previous != force_md_cnt) {
+				BT_INFO("force_md_cnt: old= %u, new= %u.",
+					previous, force_md_cnt);
+			}
+		}
+#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */
+
+		mfy.param = conn;
+
+		mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH,
+			       0, &mfy);
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+	} else {
+		lll_conn_force_md_cnt_set(0U);
+#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+#if defined(CONFIG_BT_CTLR_THROUGHPUT)
+	static uint32_t last_cycle_stamp;
+	static uint32_t tx_len;
+	struct pdu_data *pdu;
+	uint32_t cycle_stamp;
+	uint64_t delta;
+
+	cycle_stamp = k_cycle_get_32();
+	delta = k_cyc_to_ns_floor64(cycle_stamp - last_cycle_stamp);
+	if (delta > BT_CTLR_THROUGHPUT_PERIOD) {
+		BT_INFO("incoming Tx: count= %u, len= %u, rate= %u bps.",
+			tx_cnt, tx_len, tx_rate);
+
+		last_cycle_stamp = cycle_stamp;
+		tx_cnt = 0U;
+		tx_len = 0U;
+	}
+
+	pdu = (void *)((struct node_tx *)tx)->pdu;
+	tx_len += pdu->len;
+	tx_rate = ((uint64_t)tx_len << 3) * BT_CTLR_THROUGHPUT_PERIOD / delta;
+	tx_cnt++;
+#endif /* CONFIG_BT_CTLR_THROUGHPUT */
+
+	return 0;
+}
+
+uint8_t ll_conn_update(uint16_t handle, uint8_t cmd, uint8_t status, uint16_t interval_min,
+		    uint16_t interval_max, uint16_t latency, uint16_t timeout)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (!cmd) {
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		if (!conn->llcp_conn_param.disabled &&
+		    (!conn->common.fex_valid ||
+		     (conn->llcp_feature.features_conn &
+		      BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
+			cmd++;
+		} else if (conn->lll.role) {
+			return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
+		}
+#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+		if (conn->lll.role) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+	}
+
+	if (!cmd) {
+		if (conn->llcp_cu.req != conn->llcp_cu.ack) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		conn->llcp_cu.win_size = 1U;
+		conn->llcp_cu.win_offset_us = 0U;
+		conn->llcp_cu.interval = interval_max;
+		conn->llcp_cu.latency = latency;
+		conn->llcp_cu.timeout = timeout;
+		conn->llcp_cu.state = LLCP_CUI_STATE_USE;
+		conn->llcp_cu.cmd = 1U;
+
+		conn->llcp_cu.req++;
+	} else {
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		cmd--;
+
+		if (cmd) {
+			if ((conn->llcp_conn_param.req ==
+			     conn->llcp_conn_param.ack) ||
+			    (conn->llcp_conn_param.state !=
+			     LLCP_CPR_STATE_APP_WAIT)) {
+				return BT_HCI_ERR_CMD_DISALLOWED;
+			}
+
+			conn->llcp_conn_param.status = status;
+			conn->llcp_conn_param.state = cmd;
+			conn->llcp_conn_param.cmd = 1U;
+		} else {
+			if (conn->llcp_conn_param.req !=
+			    conn->llcp_conn_param.ack) {
+				return BT_HCI_ERR_CMD_DISALLOWED;
+			}
+
+			conn->llcp_conn_param.status = 0U;
+			conn->llcp_conn_param.interval_min = interval_min;
+			conn->llcp_conn_param.interval_max = interval_max;
+			conn->llcp_conn_param.latency = latency;
+			conn->llcp_conn_param.timeout = timeout;
+			conn->llcp_conn_param.state = cmd;
+			conn->llcp_conn_param.cmd = 1U;
+			conn->llcp_conn_param.req++;
+
+			if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+			    conn->lll.role) {
+				ull_slave_latency_cancel(conn, handle);
+			}
+		}
+
+#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+		/* CPR feature not supported */
+		return BT_HCI_ERR_CMD_DISALLOWED;
+#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+	}
+
+	return 0;
+}
+
+uint8_t ll_chm_get(uint16_t handle, uint8_t *chm)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	/* Iterate until we are sure the ISR did not modify the value while
+	 * we were reading it from memory.
+	 */
+	do {
+		conn->chm_updated = 0U;
+		memcpy(chm, conn->lll.data_chan_map,
+		       sizeof(conn->lll.data_chan_map));
+	} while (conn->chm_updated);
+
+	return 0;
+}
+
+uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	conn->llcp_terminate.reason_own = reason;
+
+	conn->llcp_terminate.req++;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+	return 0;
+}
+
+uint8_t ll_feature_req_send(uint16_t handle)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (conn->llcp_feature.req != conn->llcp_feature.ack) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	conn->llcp_feature.req++;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    IS_ENABLED(CONFIG_BT_CTLR_SLAVE_FEAT_REQ) &&
+	    conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+	return 0;
+}
+
+uint8_t ll_version_ind_send(uint16_t handle)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (conn->llcp_version.req != conn->llcp_version.ack) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	conn->llcp_version.req++;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+uint32_t ll_length_req_send(uint16_t handle, uint16_t tx_octets, uint16_t tx_time)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (conn->llcp_length.disabled ||
+	    (conn->common.fex_valid &&
+	     !(conn->llcp_feature.features_conn & BIT(BT_LE_FEAT_BIT_DLE)))) {
+		return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
+	}
+
+	if (conn->llcp_length.req != conn->llcp_length.ack) {
+		switch (conn->llcp_length.state) {
+		case LLCP_LENGTH_STATE_RSP_ACK_WAIT:
+		case LLCP_LENGTH_STATE_RESIZE_RSP:
+		case LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT:
+			/* cached until peer procedure completes */
+			if (!conn->llcp_length.cache.tx_octets) {
+				conn->llcp_length.cache.tx_octets = tx_octets;
+#if defined(CONFIG_BT_CTLR_PHY)
+				conn->llcp_length.cache.tx_time = tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+				return 0;
+			}
+			__fallthrough;
+		default:
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+
+	/* TODO: parameter check tx_octets and tx_time */
+
+	conn->llcp_length.state = LLCP_LENGTH_STATE_REQ;
+	conn->llcp_length.tx_octets = tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	conn->llcp_length.tx_time = tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	conn->llcp_length.req++;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+	return 0;
+}
+
+void ll_length_default_get(uint16_t *max_tx_octets, uint16_t *max_tx_time)
+{
+	*max_tx_octets = default_tx_octets;
+	*max_tx_time = default_tx_time;
+}
+
+uint32_t ll_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time)
+{
+	/* TODO: parameter check (for BT 5.0 compliance) */
+
+	default_tx_octets = max_tx_octets;
+	default_tx_time = max_tx_time;
+
+	return 0;
+}
+
+void ll_length_max_get(uint16_t *max_tx_octets, uint16_t *max_tx_time,
+		       uint16_t *max_rx_octets, uint16_t *max_rx_time)
+{
+	*max_tx_octets = LL_LENGTH_OCTETS_RX_MAX;
+	*max_rx_octets = LL_LENGTH_OCTETS_RX_MAX;
+#if defined(CONFIG_BT_CTLR_PHY)
+	*max_tx_time = PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_CODED);
+	*max_rx_time = PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_CODED);
+#else /* !CONFIG_BT_CTLR_PHY */
+	/* Default is 1M packet timing */
+	*max_tx_time = PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_1M);
+	*max_rx_time = PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_1M);
+#endif /* !CONFIG_BT_CTLR_PHY */
+}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+uint8_t ll_phy_get(uint16_t handle, uint8_t *tx, uint8_t *rx)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	/* TODO: context safe read */
+	*tx = conn->lll.phy_tx;
+	*rx = conn->lll.phy_rx;
+
+	return 0;
+}
+
+uint8_t ll_phy_default_set(uint8_t tx, uint8_t rx)
+{
+	/* TODO: validate against supported phy */
+
+	default_phy_tx = tx;
+	default_phy_rx = rx;
+
+	return 0;
+}
+
+uint8_t ll_phy_req_send(uint16_t handle, uint8_t tx, uint8_t flags, uint8_t rx)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (conn->llcp_phy.disabled ||
+	    (conn->common.fex_valid &&
+	     !(conn->llcp_feature.features_conn & BIT(BT_LE_FEAT_BIT_PHY_2M)) &&
+	     !(conn->llcp_feature.features_conn &
+	       BIT(BT_LE_FEAT_BIT_PHY_CODED)))) {
+		return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
+	}
+
+	if ((conn->llcp_req != conn->llcp_ack) ||
+	    (conn->llcp_phy.req != conn->llcp_phy.ack)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	conn->llcp_phy.state = LLCP_PHY_STATE_REQ;
+	conn->llcp_phy.cmd = 1U;
+	conn->llcp_phy.tx = tx;
+	conn->llcp_phy.flags = flags;
+	conn->llcp_phy.rx = rx;
+	conn->llcp_phy.req++;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn->lll.role) {
+		ull_slave_latency_cancel(conn, handle);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+uint8_t ll_rssi_get(uint16_t handle, uint8_t *rssi)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	*rssi = conn->lll.rssi_latest;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+uint8_t ll_apto_get(uint16_t handle, uint16_t *apto)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	*apto = conn->apto_reload * conn->lll.interval * 125U / 1000;
+
+	return 0;
+}
+
+uint8_t ll_apto_set(uint16_t handle, uint16_t apto)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	conn->apto_reload = RADIO_CONN_EVENTS(apto * 10U * 1000U,
+					      conn->lll.interval * 1250);
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+int ull_conn_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_conn_reset(void)
+{
+	uint16_t handle;
+	int err;
+
+	for (handle = 0U; handle < CONFIG_BT_MAX_CONN; handle++) {
+		disable(handle);
+	}
+
+	/* Re-initialize the Tx mfifo */
+	MFIFO_INIT(conn_tx);
+
+	/* Re-initialize the Tx Ack mfifo */
+	MFIFO_INIT(conn_ack);
+
+	/* Reset the current conn update conn context pointer */
+	ull_conn_upd_curr_reset();
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+uint16_t ull_conn_default_tx_octets_get(void)
+{
+	return default_tx_octets;
+}
+
+#if defined(CONFIG_BT_CTLR_PHY)
+uint16_t ull_conn_default_tx_time_get(void)
+{
+	return default_tx_time;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+uint8_t ull_conn_default_phy_tx_get(void)
+{
+	return default_phy_tx;
+}
+
+uint8_t ull_conn_default_phy_rx_get(void)
+{
+	return default_phy_rx;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+void ull_conn_setup(memq_link_t *link, struct node_rx_hdr *rx)
+{
+	struct node_rx_ftr *ftr;
+	struct lll_conn *lll;
+
+	ftr = &(rx->rx_ftr);
+
+	lll = *((struct lll_conn **)((uint8_t *)ftr->param +
+				     sizeof(struct lll_hdr)));
+	switch (lll->role) {
+#if defined(CONFIG_BT_CENTRAL)
+	case 0:
+		ull_master_setup(link, rx, ftr, lll);
+		break;
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	case 1:
+		ull_slave_setup(link, rx, ftr, lll);
+		break;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+
+int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx)
+{
+	struct pdu_data *pdu_rx;
+	struct ll_conn *conn;
+
+	conn = ll_connected_get((*rx)->hdr.handle);
+	if (!conn) {
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return 0;
+	}
+
+	pdu_rx = (void *)(*rx)->pdu;
+
+	switch (pdu_rx->ll_id) {
+	case PDU_DATA_LLID_CTRL:
+	{
+		int nack;
+
+		nack = ctrl_rx(link, rx, pdu_rx, conn);
+		return nack;
+	}
+
+	case PDU_DATA_LLID_DATA_CONTINUE:
+	case PDU_DATA_LLID_DATA_START:
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		if (conn->llcp_enc.pause_rx) {
+			conn->llcp_terminate.reason_peer =
+				BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
+
+			/* Mark for buffer for release */
+			(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+		}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+		break;
+
+	case PDU_DATA_LLID_RESV:
+	default:
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		if (conn->llcp_enc.pause_rx) {
+			conn->llcp_terminate.reason_peer =
+				BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
+		}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+		/* Invalid LL id, drop it. */
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+	}
+
+
+	return 0;
+}
+
+int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
+{
+	/* Check if no other procedure with instant is requested and not in
+	 * Encryption setup.
+	 */
+	if ((conn->llcp_ack == conn->llcp_req) &&
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	    !conn->llcp_enc.pause_rx) {
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+	    1) {
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+
+		/* TODO: Optimize the checks below, maybe have common flag */
+
+		/* check if connection update procedure is requested */
+		if (conn->llcp_cu.ack != conn->llcp_cu.req) {
+			/* switch to LLCP_CONN_UPD state machine */
+			conn->llcp_type = LLCP_CONN_UPD;
+			conn->llcp_ack -= 2U;
+
+		/* check if feature exchange procedure is requested */
+		} else if (conn->llcp_feature.ack != conn->llcp_feature.req) {
+			/* handle feature exchange state machine */
+			event_fex_prep(conn);
+
+		/* check if version info procedure is requested */
+		} else if (conn->llcp_version.ack != conn->llcp_version.req) {
+			/* handle version info state machine */
+			event_vex_prep(conn);
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		/* check if CPR procedure is requested */
+		} else if (conn->llcp_conn_param.ack !=
+			   conn->llcp_conn_param.req) {
+			struct lll_conn *lll = &conn->lll;
+			uint16_t event_counter;
+
+			/* Calculate current event counter */
+			event_counter = lll->event_counter +
+					lll->latency_prepare + lazy;
+
+			/* handle CPR state machine */
+			event_conn_param_prep(conn, event_counter,
+					      ticks_at_expire);
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		/* check if DLE procedure is requested */
+		} else if (conn->llcp_length.ack != conn->llcp_length.req) {
+			/* handle DLU state machine */
+			event_len_prep(conn);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		/* check if PHY Req procedure is requested */
+		} else if (conn->llcp_phy.ack != conn->llcp_phy.req) {
+			/* handle PHY Upd state machine */
+			event_phy_req_prep(conn);
+#endif /* CONFIG_BT_CTLR_PHY */
+		}
+	}
+
+	/* Check if procedures with instant or encryption setup is requested or
+	 * active.
+	 */
+	if (((conn->llcp_req - conn->llcp_ack) & 0x03) == 0x02) {
+		/* Process parallel procedures that are active */
+		if (0) {
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		/* Check if DLE in progress */
+		} else if (conn->llcp_length.ack != conn->llcp_length.req) {
+			if ((conn->llcp_length.state ==
+			     LLCP_LENGTH_STATE_RESIZE) ||
+			    (conn->llcp_length.state ==
+			     LLCP_LENGTH_STATE_RESIZE_RSP)) {
+				/* handle DLU state machine */
+				event_len_prep(conn);
+			}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+		}
+
+		/* Process procedures with instants or encryption setup */
+		/* FIXME: Make LE Ping cacheable */
+		switch (conn->llcp_type) {
+		case LLCP_CONN_UPD:
+		{
+			if (event_conn_upd_prep(conn, lazy,
+						ticks_at_expire) == 0) {
+				return -ECANCELED;
+			}
+		}
+		break;
+
+		case LLCP_CHAN_MAP:
+		{
+			struct lll_conn *lll = &conn->lll;
+			uint16_t event_counter;
+
+			/* Calculate current event counter */
+			event_counter = lll->event_counter +
+					lll->latency_prepare + lazy;
+
+			event_ch_map_prep(conn, event_counter);
+		}
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		case LLCP_ENCRYPTION:
+			event_enc_prep(conn);
+			break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		case LLCP_PING:
+			event_ping_prep(conn);
+			break;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		case LLCP_PHY_UPD:
+		{
+			struct lll_conn *lll = &conn->lll;
+			uint16_t event_counter;
+
+			/* Calculate current event counter */
+			event_counter = lll->event_counter +
+					lll->latency_prepare + lazy;
+
+			event_phy_upd_ind_prep(conn, event_counter);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+	}
+
+	/* Terminate Procedure Request */
+	if (conn->llcp_terminate.ack != conn->llcp_terminate.req) {
+		struct node_tx *tx;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (tx) {
+			struct pdu_data *pdu_tx = (void *)tx->pdu;
+
+			/* Terminate Procedure acked */
+			conn->llcp_terminate.ack = conn->llcp_terminate.req;
+
+			/* place the terminate ind packet in tx queue */
+			pdu_tx->ll_id = PDU_DATA_LLID_CTRL;
+			pdu_tx->len = offsetof(struct pdu_data_llctrl,
+						    terminate_ind) +
+				sizeof(struct pdu_data_llctrl_terminate_ind);
+			pdu_tx->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_TERMINATE_IND;
+			pdu_tx->llctrl.terminate_ind.error_code =
+				conn->llcp_terminate.reason_own;
+
+			ctrl_tx_enqueue(conn, tx);
+		}
+
+		if (!conn->procedure_expire) {
+			/* Terminate Procedure timeout is started, will
+			 * replace any other timeout running
+			 */
+			conn->procedure_expire = conn->supervision_reload;
+
+			/* NOTE: if supervision timeout equals connection
+			 * interval, dont timeout in current event.
+			 */
+			if (conn->procedure_expire <= 1U) {
+				conn->procedure_expire++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void ull_conn_done(struct node_rx_event_done *done)
+{
+	struct lll_conn *lll = (void *)HDR_ULL2LLL(done->param);
+	struct ll_conn *conn = (void *)HDR_LLL2EVT(lll);
+	uint32_t ticks_drift_minus;
+	uint32_t ticks_drift_plus;
+	uint16_t latency_event;
+	uint16_t elapsed_event;
+	uint8_t reason_peer;
+	uint16_t lazy;
+	uint8_t force;
+
+	/* Skip if connection terminated by local host */
+	if (unlikely(lll->handle == 0xFFFF)) {
+		return;
+	}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	/* Check authenticated payload expiry or MIC failure */
+	switch (done->extra.mic_state) {
+	case LLL_CONN_MIC_NONE:
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		if (lll->enc_rx || conn->llcp_enc.pause_rx) {
+			uint16_t appto_reload_new;
+
+			/* check for change in apto */
+			appto_reload_new = (conn->apto_reload >
+					    (lll->latency + 6)) ?
+					   (conn->apto_reload -
+					    (lll->latency + 6)) :
+					   conn->apto_reload;
+			if (conn->appto_reload != appto_reload_new) {
+				conn->appto_reload = appto_reload_new;
+				conn->apto_expire = 0U;
+			}
+
+			/* start authenticated payload (pre) timeout */
+			if (conn->apto_expire == 0U) {
+				conn->appto_expire = conn->appto_reload;
+				conn->apto_expire = conn->apto_reload;
+			}
+		}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+		break;
+
+	case LLL_CONN_MIC_PASS:
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		conn->appto_expire = conn->apto_expire = 0U;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+		break;
+
+	case LLL_CONN_MIC_FAIL:
+		conn->llcp_terminate.reason_peer =
+			BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
+		break;
+	}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	/* Master transmitted ack for the received terminate ind or
+	 * Slave received terminate ind or MIC failure
+	 */
+	reason_peer = conn->llcp_terminate.reason_peer;
+	if (reason_peer && (
+#if defined(CONFIG_BT_PERIPHERAL)
+			    lll->role ||
+#else /* CONFIG_BT_PERIPHERAL */
+			    0 ||
+#endif /* CONFIG_BT_PERIPHERAL */
+#if defined(CONFIG_BT_CENTRAL)
+			    conn->master.terminate_ack ||
+			    (reason_peer == BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL)
+#else /* CONFIG_BT_CENTRAL */
+			    1
+#endif /* CONFIG_BT_CENTRAL */
+			    )) {
+		conn_cleanup(conn, reason_peer);
+
+		return;
+	}
+
+	/* Events elapsed used in timeout checks below */
+	latency_event = lll->latency_event;
+	elapsed_event = latency_event + 1;
+
+	/* Slave drift compensation calc and new latency or
+	 * master terminate acked
+	 */
+	ticks_drift_plus = 0U;
+	ticks_drift_minus = 0U;
+	if (done->extra.trx_cnt) {
+		if (0) {
+#if defined(CONFIG_BT_PERIPHERAL)
+		} else if (lll->role) {
+			ull_drift_ticks_get(done, &ticks_drift_plus,
+					    &ticks_drift_minus);
+
+			if (!conn->tx_head) {
+				ull_conn_tx_demux(UINT8_MAX);
+			}
+
+			if (conn->tx_head || memq_peek(lll->memq_tx.head,
+						       lll->memq_tx.tail,
+						       NULL)) {
+				lll->latency_event = 0;
+			} else if (lll->slave.latency_enabled) {
+				lll->latency_event = lll->latency;
+			}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CENTRAL)
+		} else if (reason_peer) {
+			conn->master.terminate_ack = 1;
+#endif /* CONFIG_BT_CENTRAL */
+
+		}
+
+		/* Reset connection failed to establish countdown */
+		conn->connect_expire = 0U;
+	}
+
+	/* Reset supervision countdown */
+	if (done->extra.crc_valid) {
+		conn->supervision_expire = 0U;
+	}
+
+	/* check connection failed to establish */
+	else if (conn->connect_expire) {
+		if (conn->connect_expire > elapsed_event) {
+			conn->connect_expire -= elapsed_event;
+		} else {
+			conn_cleanup(conn, BT_HCI_ERR_CONN_FAIL_TO_ESTAB);
+
+			return;
+		}
+	}
+
+	/* if anchor point not sync-ed, start supervision timeout, and break
+	 * latency if any.
+	 */
+	else {
+		/* Start supervision timeout, if not started already */
+		if (!conn->supervision_expire) {
+			conn->supervision_expire = conn->supervision_reload;
+		}
+	}
+
+	/* check supervision timeout */
+	force = 0U;
+	if (conn->supervision_expire) {
+		if (conn->supervision_expire > elapsed_event) {
+			conn->supervision_expire -= elapsed_event;
+
+			/* break latency */
+			lll->latency_event = 0U;
+
+			/* Force both master and slave when close to
+			 * supervision timeout.
+			 */
+			if (conn->supervision_expire <= 6U) {
+				force = 1U;
+			}
+#if defined(CONFIG_BT_PERIPHERAL)
+			/* use randomness to force slave role when anchor
+			 * points are being missed.
+			 */
+			else if (lll->role) {
+				if (latency_event) {
+					force = 1U;
+				} else {
+					force = conn->slave.force & 0x01;
+
+					/* rotate force bits */
+					conn->slave.force >>= 1U;
+					if (force) {
+						conn->slave.force |= BIT(31);
+					}
+				}
+			}
+#endif /* CONFIG_BT_PERIPHERAL */
+		} else {
+			conn_cleanup(conn, BT_HCI_ERR_CONN_TIMEOUT);
+
+			return;
+		}
+	}
+
+	/* check procedure timeout */
+	if (conn->procedure_expire != 0U) {
+		if (conn->procedure_expire > elapsed_event) {
+			conn->procedure_expire -= elapsed_event;
+		} else {
+			conn_cleanup(conn, BT_HCI_ERR_LL_RESP_TIMEOUT);
+
+			return;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	/* check apto */
+	if (conn->apto_expire != 0U) {
+		if (conn->apto_expire > elapsed_event) {
+			conn->apto_expire -= elapsed_event;
+		} else {
+			struct node_rx_hdr *rx;
+
+			rx = ll_pdu_rx_alloc();
+			if (rx) {
+				conn->apto_expire = 0U;
+
+				rx->handle = lll->handle;
+				rx->type = NODE_RX_TYPE_APTO;
+
+				/* enqueue apto event into rx queue */
+				ll_rx_put(rx->link, rx);
+				ll_rx_sched();
+			} else {
+				conn->apto_expire = 1U;
+			}
+		}
+	}
+
+	/* check appto */
+	if (conn->appto_expire != 0U) {
+		if (conn->appto_expire > elapsed_event) {
+			conn->appto_expire -= elapsed_event;
+		} else {
+			conn->appto_expire = 0U;
+
+			if ((conn->procedure_expire == 0U) &&
+			    (conn->llcp_req == conn->llcp_ack)) {
+				conn->llcp_type = LLCP_PING;
+				conn->llcp_ack -= 2U;
+			}
+		}
+	}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+	/* generate RSSI event */
+	if (lll->rssi_sample_count == 0U) {
+		struct node_rx_pdu *rx;
+		struct pdu_data *pdu_data_rx;
+
+		rx = ll_pdu_rx_alloc();
+		if (rx) {
+			lll->rssi_reported = lll->rssi_latest;
+			lll->rssi_sample_count = LLL_CONN_RSSI_SAMPLE_COUNT;
+
+			/* Prepare the rx packet structure */
+			rx->hdr.handle = lll->handle;
+			rx->hdr.type = NODE_RX_TYPE_RSSI;
+
+			/* prepare connection RSSI structure */
+			pdu_data_rx = (void *)rx->pdu;
+			pdu_data_rx->rssi = lll->rssi_reported;
+
+			/* enqueue connection RSSI structure into queue */
+			ll_rx_put(rx->hdr.link, rx);
+			ll_rx_sched();
+		}
+	}
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+
+	/* break latency based on ctrl procedure pending */
+	if (((((conn->llcp_req - conn->llcp_ack) & 0x03) == 0x02) &&
+	     ((conn->llcp_type == LLCP_CONN_UPD) ||
+	      (conn->llcp_type == LLCP_CHAN_MAP))) ||
+	    (conn->llcp_cu.req != conn->llcp_cu.ack)) {
+		lll->latency_event = 0U;
+	}
+
+	/* check if latency needs update */
+	lazy = 0U;
+	if ((force) || (latency_event != lll->latency_event)) {
+		lazy = lll->latency_event + 1U;
+	}
+
+	/* update conn ticker */
+	if (ticks_drift_plus || ticks_drift_minus || lazy || force) {
+		uint8_t ticker_id = TICKER_ID_CONN_BASE + lll->handle;
+		struct ll_conn *conn = lll->hdr.parent;
+		uint32_t ticker_status;
+
+		/* Call to ticker_update can fail under the race
+		 * condition where in the Slave role is being stopped but
+		 * at the same time it is preempted by Slave event that
+		 * gets into close state. Accept failure when Slave role
+		 * is being stopped.
+		 */
+		ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR,
+					      TICKER_USER_ID_ULL_HIGH,
+					      ticker_id,
+					      ticks_drift_plus,
+					      ticks_drift_minus, 0, 0,
+					      lazy, force,
+					      ticker_update_conn_op_cb,
+					      conn);
+		LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+			  (ticker_status == TICKER_STATUS_BUSY) ||
+			  ((void *)conn == ull_disable_mark_get()));
+	}
+}
+
+void ull_conn_tx_demux(uint8_t count)
+{
+	do {
+		struct lll_tx *lll_tx;
+		struct ll_conn *conn;
+
+		lll_tx = MFIFO_DEQUEUE_GET(conn_tx);
+		if (!lll_tx) {
+			break;
+		}
+
+		conn = ll_connected_get(lll_tx->handle);
+		if (conn) {
+			struct node_tx *tx = lll_tx->node;
+
+#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
+			if (empty_data_start_release(conn, tx)) {
+				goto ull_conn_tx_demux_release;
+			}
+#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
+
+			tx->next = NULL;
+			if (!conn->tx_data) {
+				conn->tx_data = tx;
+				if (!conn->tx_head) {
+					conn->tx_head = tx;
+					conn->tx_data_last = NULL;
+				}
+			}
+
+			if (conn->tx_data_last) {
+				conn->tx_data_last->next = tx;
+			}
+
+			conn->tx_data_last = tx;
+		} else {
+			struct node_tx *tx = lll_tx->node;
+			struct pdu_data *p = (void *)tx->pdu;
+
+			p->ll_id = PDU_DATA_LLID_RESV;
+			ll_tx_ack_put(0xFFFF, tx);
+		}
+
+#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
+ull_conn_tx_demux_release:
+#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
+
+		MFIFO_DEQUEUE(conn_tx);
+	} while (--count);
+}
+
+void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count)
+{
+	bool pause_tx = false;
+
+	while (conn->tx_head &&
+	       ((
+#if defined(CONFIG_BT_CTLR_PHY)
+		 !conn->llcp_phy.pause_tx &&
+#endif /* CONFIG_BT_CTLR_PHY */
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		 !conn->llcp_enc.pause_tx &&
+		 !(pause_tx = is_enc_req_pause_tx(conn)) &&
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+		 1) ||
+		(!pause_tx && (conn->tx_head == conn->tx_ctrl))) && count--) {
+		struct pdu_data *pdu_tx;
+		struct node_tx *tx;
+		memq_link_t *link;
+
+		tx = tx_ull_dequeue(conn, conn->tx_head);
+
+		pdu_tx = (void *)tx->pdu;
+		if (pdu_tx->ll_id == PDU_DATA_LLID_CTRL) {
+			ctrl_tx_pre_ack(conn, pdu_tx);
+		}
+
+		link = mem_acquire(&mem_link_tx.free);
+		LL_ASSERT(link);
+
+		memq_enqueue(link, tx, &conn->lll.memq_tx.tail);
+	}
+}
+
+void ull_conn_link_tx_release(void *link)
+{
+	mem_release(link, &mem_link_tx.free);
+}
+
+uint8_t ull_conn_ack_last_idx_get(void)
+{
+	return mfifo_conn_ack.l;
+}
+
+memq_link_t *ull_conn_ack_peek(uint8_t *ack_last, uint16_t *handle,
+			       struct node_tx **tx)
+{
+	struct lll_tx *lll_tx;
+
+	lll_tx = MFIFO_DEQUEUE_GET(conn_ack);
+	if (!lll_tx) {
+		return NULL;
+	}
+
+	*ack_last = mfifo_conn_ack.l;
+
+	*handle = lll_tx->handle;
+	*tx = lll_tx->node;
+
+	return (*tx)->link;
+}
+
+memq_link_t *ull_conn_ack_by_last_peek(uint8_t last, uint16_t *handle,
+				       struct node_tx **tx)
+{
+	struct lll_tx *lll_tx;
+
+	lll_tx = mfifo_dequeue_get(mfifo_conn_ack.m, mfifo_conn_ack.s,
+				   mfifo_conn_ack.f, last);
+	if (!lll_tx) {
+		return NULL;
+	}
+
+	*handle = lll_tx->handle;
+	*tx = lll_tx->node;
+
+	return (*tx)->link;
+}
+
+void *ull_conn_ack_dequeue(void)
+{
+	return MFIFO_DEQUEUE(conn_ack);
+}
+
+void ull_conn_lll_ack_enqueue(uint16_t handle, struct node_tx *tx)
+{
+	struct lll_tx *lll_tx;
+	uint8_t idx;
+
+	idx = MFIFO_ENQUEUE_GET(conn_ack, (void **)&lll_tx);
+	LL_ASSERT(lll_tx);
+
+	lll_tx->handle = handle;
+	lll_tx->node = tx;
+
+	MFIFO_ENQUEUE(conn_ack, idx);
+}
+
+void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx)
+{
+	struct pdu_data *pdu_tx;
+
+	pdu_tx = (void *)tx->pdu;
+	LL_ASSERT(pdu_tx->len);
+
+	if (pdu_tx->ll_id == PDU_DATA_LLID_CTRL) {
+		if (handle != 0xFFFF) {
+			struct ll_conn *conn = ll_conn_get(handle);
+
+			ctrl_tx_ack(conn, &tx, pdu_tx);
+		}
+
+		/* release ctrl mem if points to itself */
+		if (link->next == (void *)tx) {
+			LL_ASSERT(link->next);
+
+			mem_release(tx, &mem_conn_tx_ctrl.free);
+			return;
+		} else if (!tx) {
+			/* Tx Node re-used to enqueue new ctrl PDU */
+			return;
+		} else {
+			LL_ASSERT(!link->next);
+		}
+	} else if (handle == 0xFFFF) {
+		pdu_tx->ll_id = PDU_DATA_LLID_RESV;
+	} else {
+		LL_ASSERT(handle != 0xFFFF);
+	}
+
+	ll_tx_ack_put(handle, tx);
+
+	return;
+}
+
+uint8_t ull_conn_llcp_req(void *conn)
+{
+	struct ll_conn * const conn_hdr = conn;
+	if (conn_hdr->llcp_req != conn_hdr->llcp_ack) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	conn_hdr->llcp_req++;
+	if (((conn_hdr->llcp_req - conn_hdr->llcp_ack) & 0x03) != 1) {
+		conn_hdr->llcp_req--;
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	return 0;
+}
+
+uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll)
+{
+	uint16_t max_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+#if defined(CONFIG_BT_CTLR_PHY)
+	switch (lll->phy_tx_time) {
+	default:
+	case BIT(0):
+		/* 1M PHY, 1us = 1 bit, hence divide by 8.
+		 * Deduct 10 bytes for preamble (1), access address (4),
+		 * header (2), and CRC (3).
+		 */
+		max_tx_octets = (lll->max_tx_time >> 3) - 10;
+		break;
+
+	case BIT(1):
+		/* 2M PHY, 1us = 2 bits, hence divide by 4.
+		 * Deduct 11 bytes for preamble (2), access address (4),
+		 * header (2), and CRC (3).
+		 */
+		max_tx_octets = (lll->max_tx_time >> 2) - 11;
+		break;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	case BIT(2):
+		if (lll->phy_flags & 0x01) {
+			/* S8 Coded PHY, 8us = 1 bit, hence divide by
+			 * 64.
+			 * Subtract time for preamble (80), AA (256),
+			 * CI (16), TERM1 (24), CRC (192) and
+			 * TERM2 (24), total 592 us.
+			 * Subtract 2 bytes for header.
+			 */
+			max_tx_octets = ((lll->max_tx_time - 592) >>
+					  6) - 2;
+		} else {
+			/* S2 Coded PHY, 2us = 1 bit, hence divide by
+			 * 16.
+			 * Subtract time for preamble (80), AA (256),
+			 * CI (16), TERM1 (24), CRC (48) and
+			 * TERM2 (6), total 430 us.
+			 * Subtract 2 bytes for header.
+			 */
+			max_tx_octets = ((lll->max_tx_time - 430) >>
+					  4) - 2;
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	if (lll->enc_tx) {
+		/* deduct the MIC */
+		max_tx_octets -= 4U;
+	}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	if (max_tx_octets > lll->max_tx_octets) {
+		max_tx_octets = lll->max_tx_octets;
+	}
+#else /* !CONFIG_BT_CTLR_PHY */
+	max_tx_octets = lll->max_tx_octets;
+#endif /* !CONFIG_BT_CTLR_PHY */
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+	return max_tx_octets;
+}
+
+inline void ull_conn_upd_curr_reset(void)
+{
+	conn_upd_curr = NULL;
+}
+
+static int init_reset(void)
+{
+	/* Initialize conn pool. */
+	mem_init(conn_pool, sizeof(struct ll_conn),
+		 sizeof(conn_pool) / sizeof(struct ll_conn), &conn_free);
+
+	/* Initialize tx pool. */
+	mem_init(mem_conn_tx.pool, CONN_TX_BUF_SIZE, CONFIG_BT_CTLR_TX_BUFFERS,
+		 &mem_conn_tx.free);
+
+	/* Initialize tx ctrl pool. */
+	mem_init(mem_conn_tx_ctrl.pool, CONN_TX_CTRL_BUF_SIZE,
+		 CONN_TX_CTRL_BUFFERS, &mem_conn_tx_ctrl.free);
+
+	/* Initialize tx link pool. */
+	mem_init(mem_link_tx.pool, sizeof(memq_link_t),
+		 CONFIG_BT_CTLR_TX_BUFFERS + CONN_TX_CTRL_BUFFERS,
+		 &mem_link_tx.free);
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	/* Initialize the DLE defaults */
+	default_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+	default_tx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	/* Initialize the PHY defaults */
+	default_phy_tx = BIT(0);
+	default_phy_rx = BIT(0);
+
+#if defined(CONFIG_BT_CTLR_PHY_2M)
+	default_phy_tx |= BIT(1);
+	default_phy_rx |= BIT(1);
+#endif /* CONFIG_BT_CTLR_PHY_2M */
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	default_phy_tx |= BIT(2);
+	default_phy_rx |= BIT(2);
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	return 0;
+}
+
+static void ticker_update_conn_op_cb(uint32_t status, void *param)
+{
+	/* Slave drift compensation succeeds, or it fails in a race condition
+	 * when disconnecting or connection update (race between ticker_update
+	 * and ticker_stop calls).
+	 */
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
+		  param == ull_update_mark_get() ||
+		  param == ull_disable_mark_get());
+}
+
+static void ticker_stop_conn_op_cb(uint32_t status, void *param)
+{
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+
+	void *p = ull_update_mark(param);
+
+	LL_ASSERT(p == param);
+}
+
+static void ticker_start_conn_op_cb(uint32_t status, void *param)
+{
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+
+	void *p = ull_update_unmark(param);
+
+	LL_ASSERT(p == param);
+}
+
+static void ticker_op_stop_cb(uint32_t status, void *param)
+{
+	uint32_t retval;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, tx_lll_flush};
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+
+	mfy.param = param;
+
+	/* Flush pending tx PDUs in LLL (using a mayfly) */
+	retval = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_LLL, 0,
+				&mfy);
+	LL_ASSERT(!retval);
+}
+
+static inline void disable(uint16_t handle)
+{
+	uint32_t volatile ret_cb;
+	struct ll_conn *conn;
+	void *mark;
+	uint32_t ret;
+
+	conn = ll_conn_get(handle);
+
+	mark = ull_disable_mark(conn);
+	LL_ASSERT(mark == conn);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_CONN_BASE + handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (!ret) {
+		ret = ull_disable(&conn->lll);
+		LL_ASSERT(!ret);
+	}
+
+	conn->lll.link_tx_free = NULL;
+
+	mark = ull_disable_unmark(conn);
+	LL_ASSERT(mark == conn);
+}
+
+static void conn_cleanup(struct ll_conn *conn, uint8_t reason)
+{
+	struct lll_conn *lll = &conn->lll;
+	struct node_rx_pdu *rx;
+	uint32_t ticker_status;
+
+	/* Only termination structure is populated here in ULL context
+	 * but the actual enqueue happens in the LLL context in
+	 * tx_lll_flush. The reason being to avoid passing the reason
+	 * value and handle through the mayfly scheduling of the
+	 * tx_lll_flush.
+	 */
+	rx = (void *)&conn->llcp_terminate.node_rx;
+	rx->hdr.handle = conn->lll.handle;
+	rx->hdr.type = NODE_RX_TYPE_TERMINATE;
+	*((uint8_t *)rx->pdu) = reason;
+
+	/* release any llcp reserved rx node */
+	rx = conn->llcp_rx;
+	while (rx) {
+		struct node_rx_hdr *hdr;
+
+		/* traverse to next rx node */
+		hdr = &rx->hdr;
+		rx = hdr->link->mem;
+
+		/* Mark for buffer for release */
+		hdr->type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		/* enqueue rx node towards Thread */
+		ll_rx_put(hdr->link, hdr);
+	}
+
+	/* flush demux-ed Tx buffer still in ULL context */
+	tx_ull_flush(conn);
+
+	/* Stop Master or Slave role ticker */
+	ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
+				    TICKER_USER_ID_ULL_HIGH,
+				    TICKER_ID_CONN_BASE + lll->handle,
+				    ticker_op_stop_cb, (void *)lll);
+	LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+		  (ticker_status == TICKER_STATUS_BUSY));
+
+	/* Invalidate the connection context */
+	lll->handle = 0xFFFF;
+
+	/* Demux and flush Tx PDUs that remain enqueued in thread context */
+	ull_conn_tx_demux(UINT8_MAX);
+}
+
+static void tx_demux(void *param)
+{
+	ull_conn_tx_demux(1);
+
+	ull_conn_tx_lll_enqueue(param, 1);
+}
+
+static struct node_tx *tx_ull_dequeue(struct ll_conn *conn, struct node_tx *tx)
+{
+	if (!conn->tx_ctrl && (conn->tx_head != conn->tx_data)) {
+		struct pdu_data *pdu_data_tx;
+
+		pdu_data_tx = (void *)conn->tx_head->pdu;
+		if ((pdu_data_tx->ll_id != PDU_DATA_LLID_CTRL) ||
+		    ((pdu_data_tx->llctrl.opcode !=
+		      PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
+		     (pdu_data_tx->llctrl.opcode !=
+		      PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
+			conn->tx_ctrl = conn->tx_ctrl_last = conn->tx_head;
+		}
+	}
+
+	if (conn->tx_head == conn->tx_ctrl) {
+		conn->tx_head = conn->tx_head->next;
+		if (conn->tx_ctrl == conn->tx_ctrl_last) {
+			conn->tx_ctrl = NULL;
+			conn->tx_ctrl_last = NULL;
+		} else {
+			conn->tx_ctrl = conn->tx_head;
+		}
+
+		/* point to self to indicate a control PDU mem alloc */
+		tx->next = tx;
+	} else {
+		if (conn->tx_head == conn->tx_data) {
+			conn->tx_data = conn->tx_data->next;
+		}
+		conn->tx_head = conn->tx_head->next;
+
+		/* point to NULL to indicate a Data PDU mem alloc */
+		tx->next = NULL;
+	}
+
+	return tx;
+}
+
+static void tx_ull_flush(struct ll_conn *conn)
+{
+	while (conn->tx_head) {
+		struct node_tx *tx;
+		memq_link_t *link;
+
+		tx = tx_ull_dequeue(conn, conn->tx_head);
+
+		link = mem_acquire(&mem_link_tx.free);
+		LL_ASSERT(link);
+
+		memq_enqueue(link, tx, &conn->lll.memq_tx.tail);
+	}
+}
+
+static void tx_lll_flush(void *param)
+{
+	struct ll_conn *conn = (void *)HDR_LLL2EVT(param);
+	uint16_t handle = ll_conn_handle_get(conn);
+	struct lll_conn *lll = param;
+	struct node_rx_pdu *rx;
+	struct node_tx *tx;
+	memq_link_t *link;
+
+	lll_conn_flush(handle, lll);
+
+	link = memq_dequeue(lll->memq_tx.tail, &lll->memq_tx.head,
+			    (void **)&tx);
+	while (link) {
+		struct lll_tx *lll_tx;
+		uint8_t idx;
+
+		idx = MFIFO_ENQUEUE_GET(conn_ack, (void **)&lll_tx);
+		LL_ASSERT(lll_tx);
+
+		lll_tx->handle = 0xFFFF;
+		lll_tx->node = tx;
+
+		/* TX node UPSTREAM, i.e. Tx node ack path */
+		link->next = tx->next; /* Indicates ctrl pool or data pool */
+		tx->next = link;
+
+		MFIFO_ENQUEUE(conn_ack, idx);
+
+		link = memq_dequeue(lll->memq_tx.tail, &lll->memq_tx.head,
+				    (void **)&tx);
+	}
+
+	/* Get the terminate structure reserved in the connection context.
+	 * The terminate reason and connection handle should already be
+	 * populated before this mayfly function was scheduled.
+	 */
+	rx = (void *)&conn->llcp_terminate.node_rx;
+	LL_ASSERT(rx->hdr.link);
+	link = rx->hdr.link;
+	rx->hdr.link = NULL;
+
+	/* Enqueue the terminate towards ULL context */
+	ull_rx_put(link, rx);
+	ull_rx_sched();
+}
+
+#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
+static int empty_data_start_release(struct ll_conn *conn, struct node_tx *tx)
+{
+	struct pdu_data *p = (void *)tx->pdu;
+
+	if ((p->ll_id == PDU_DATA_LLID_DATA_START) && !p->len) {
+		conn->start_empty = 1U;
+
+		ll_tx_ack_put(conn->lll.handle, tx);
+
+		return -EINVAL;
+	} else if (p->len && conn->start_empty) {
+		conn->start_empty = 0U;
+
+		if (p->ll_id == PDU_DATA_LLID_DATA_CONTINUE) {
+			p->ll_id = PDU_DATA_LLID_DATA_START;
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
+
+static void ctrl_tx_last_enqueue(struct ll_conn *conn,
+				      struct node_tx *tx)
+{
+	tx->next = conn->tx_ctrl_last->next;
+	conn->tx_ctrl_last->next = tx;
+	conn->tx_ctrl_last = tx;
+}
+
+static inline void ctrl_tx_pause_enqueue(struct ll_conn *conn,
+					 struct node_tx *tx, bool pause)
+{
+	/* check if a packet was tx-ed and not acked by peer */
+	if (
+	    /* data/ctrl packet is in the head */
+	    conn->tx_head &&
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	    !conn->llcp_enc.pause_tx &&
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+#if defined(CONFIG_BT_CTLR_PHY)
+	    !conn->llcp_phy.pause_tx &&
+#endif /* CONFIG_BT_CTLR_PHY */
+	    1) {
+		/* data or ctrl may have been transmitted once, but not acked
+		 * by peer, hence place this new ctrl after head
+		 */
+
+		/* if data transmitted once, keep it at head of the tx list,
+		 * as we will insert a ctrl after it, hence advance the
+		 * data pointer
+		 */
+		if (conn->tx_head == conn->tx_data) {
+			conn->tx_data = conn->tx_data->next;
+		}
+
+		/* if no ctrl packet already queued, new ctrl added will be
+		 * the ctrl pointer and is inserted after head.
+		 */
+		if (!conn->tx_ctrl) {
+			tx->next = conn->tx_head->next;
+			conn->tx_head->next = tx;
+
+			/* If in Encryption Procedure, other control PDUs,
+			 * Feature Rsp and Version Ind, are placed before data
+			 * marker and after control last marker. Hence, if no
+			 * control marker i.e. this is the first control PDU and
+			 * to be paused, do not set the control marker. A valid
+			 * control PDU in Encryption Procedure that is not
+			 * implicitly paused, will set the control and control
+			 * last marker.
+			 */
+			if (!pause) {
+				conn->tx_ctrl = tx;
+				conn->tx_ctrl_last = tx;
+			}
+		} else {
+			/* ENC_REQ PDU is always allocated from data pool, hence
+			 * the head can not have the control marker, and pause
+			 * be true.
+			 */
+			LL_ASSERT(!pause);
+
+			ctrl_tx_last_enqueue(conn, tx);
+		}
+	} else {
+		/* No packet needing ACK. */
+
+		/* If first ctrl packet then add it as head else add it to the
+		 * tail of the ctrl packets.
+		 */
+		if (!conn->tx_ctrl) {
+			tx->next = conn->tx_head;
+			conn->tx_head = tx;
+			if (!pause) {
+				conn->tx_ctrl = tx;
+				conn->tx_ctrl_last = tx;
+			}
+		} else {
+			LL_ASSERT(!pause);
+
+			ctrl_tx_last_enqueue(conn, tx);
+		}
+	}
+
+	/* Update last pointer if ctrl added at end of tx list */
+	if (!tx->next) {
+		conn->tx_data_last = tx;
+	}
+}
+
+static inline void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx)
+{
+	ctrl_tx_pause_enqueue(conn, tx, false);
+}
+
+static void ctrl_tx_sec_enqueue(struct ll_conn *conn, struct node_tx *tx)
+{
+	bool pause = false;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	if (conn->llcp_enc.pause_tx) {
+		if (!conn->tx_ctrl) {
+			/* As data PDU tx is paused and no control PDU in queue,
+			 * its safe to add new control PDU at head.
+			 * Note, here the PDUs are stacked, not queued. Last In
+			 * First Out.
+			 */
+			tx->next = conn->tx_head;
+			conn->tx_head = tx;
+		} else {
+			/* As data PDU tx is paused and there are control PDUs
+			 * in the queue, add it after control PDUs last marker
+			 * and before the data start marker.
+			 * Note, here the PDUs are stacked, not queued. Last In
+			 * First Out.
+			 */
+			tx->next = conn->tx_ctrl_last->next;
+			conn->tx_ctrl_last->next = tx;
+		}
+
+		/* Update last pointer if ctrl added at end of tx list */
+		if (!tx->next) {
+			conn->tx_data_last = tx;
+		}
+	} else {
+		/* check if Encryption Request is at head, enqueue this control
+		 * PDU after control last marker and before data marker.
+		 * This way it is paused until Encryption Setup completes.
+		 */
+		if (conn->tx_head) {
+			struct pdu_data *pdu_data_tx;
+
+			pdu_data_tx = (void *)conn->tx_head->pdu;
+			if ((conn->llcp_req != conn->llcp_ack) &&
+			    (conn->llcp_type == LLCP_ENCRYPTION) &&
+			    (pdu_data_tx->ll_id == PDU_DATA_LLID_CTRL) &&
+			    ((pdu_data_tx->llctrl.opcode ==
+			      PDU_DATA_LLCTRL_TYPE_ENC_REQ) ||
+			     (pdu_data_tx->llctrl.opcode ==
+			      PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
+				pause = true;
+			}
+		}
+
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+	{
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+
+		ctrl_tx_pause_enqueue(conn, tx, pause);
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static bool is_enc_req_pause_tx(struct ll_conn *conn)
+{
+	struct pdu_data *pdu_data_tx;
+
+	pdu_data_tx = (void *)conn->tx_head->pdu;
+	if ((pdu_data_tx->ll_id == PDU_DATA_LLID_CTRL) &&
+	    ((pdu_data_tx->llctrl.opcode ==
+	      PDU_DATA_LLCTRL_TYPE_ENC_REQ) ||
+	     (pdu_data_tx->llctrl.opcode ==
+	      PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
+		if (((conn->llcp_req != conn->llcp_ack) &&
+		     (conn->llcp_type != LLCP_ENCRYPTION)) ||
+		    ((conn->llcp_req == conn->llcp_ack) &&
+		     ((conn->llcp_feature.ack != conn->llcp_feature.req) ||
+		      (conn->llcp_version.ack != conn->llcp_version.req) ||
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		      (conn->llcp_conn_param.ack !=
+		       conn->llcp_conn_param.req) ||
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		      (conn->llcp_length.ack != conn->llcp_length.req) ||
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+#if defined(CONFIG_BT_CTLR_PHY)
+		      (conn->llcp_phy.ack != conn->llcp_phy.req) ||
+#endif /* CONFIG_BT_CTLR_PHY */
+		      0))) {
+			struct node_tx *tx;
+
+			/* if we have control packets enqueued after this PDU
+			 * bring it ahead, and move the enc_req to last of
+			 * ctrl queue.
+			 */
+			tx = conn->tx_head;
+			if ((tx->next != NULL) &&
+			    (tx->next == conn->tx_ctrl)) {
+				conn->tx_head = tx->next;
+				tx->next = conn->tx_ctrl_last->next;
+				conn->tx_ctrl_last->next = tx;
+				conn->tx_data = tx;
+				if (!conn->tx_data_last) {
+					conn->tx_data_last = tx;
+				}
+
+				/* Head now contains a control packet permitted
+				 * to be transmitted to peer.
+				 */
+				return false;
+			}
+
+			/* Head contains ENC_REQ packet deferred due to another
+			 * control procedure in progress.
+			 */
+			return true;
+		}
+
+		if (conn->llcp_req == conn->llcp_ack) {
+			conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
+
+			conn->llcp_type = LLCP_ENCRYPTION;
+			conn->llcp_ack -= 2U;
+		} else {
+			LL_ASSERT(conn->llcp_type == LLCP_ENCRYPTION);
+		}
+	}
+
+	/* Head contains a permitted data or control packet. */
+	return false;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static inline void event_conn_upd_init(struct ll_conn *conn,
+				       uint16_t event_counter,
+				       uint32_t ticks_at_expire,
+				       struct pdu_data *pdu_ctrl_tx,
+				       struct mayfly *mfy_sched_offset,
+				       void (*fp_mfy_select_or_use)(void *))
+{
+	/* move to in progress */
+	conn->llcp_cu.state = LLCP_CUI_STATE_INPROG;
+
+	/* set instant */
+	conn->llcp.conn_upd.instant = event_counter + conn->lll.latency + 6;
+
+	/* place the conn update req packet as next in tx queue */
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, conn_update_ind) +
+			   sizeof(struct pdu_data_llctrl_conn_update_ind);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND;
+	pdu_ctrl_tx->llctrl.conn_update_ind.win_size = conn->llcp_cu.win_size;
+	pdu_ctrl_tx->llctrl.conn_update_ind.win_offset =
+		sys_cpu_to_le16(conn->llcp_cu.win_offset_us / 1250U);
+	pdu_ctrl_tx->llctrl.conn_update_ind.interval =
+		sys_cpu_to_le16(conn->llcp_cu.interval);
+	pdu_ctrl_tx->llctrl.conn_update_ind.latency =
+		sys_cpu_to_le16(conn->llcp_cu.latency);
+	pdu_ctrl_tx->llctrl.conn_update_ind.timeout =
+		sys_cpu_to_le16(conn->llcp_cu.timeout);
+	pdu_ctrl_tx->llctrl.conn_update_ind.instant =
+		sys_cpu_to_le16(conn->llcp.conn_upd.instant);
+
+#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+	{
+		uint32_t retval;
+
+		/* calculate window offset that places the connection in the
+		 * next available slot after existing masters.
+		 */
+		conn->llcp.conn_upd.ticks_anchor = ticks_at_expire;
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+		if (conn->evt.ticks_xtal_to_start & XON_BITMASK) {
+			uint32_t ticks_prepare_to_start =
+				MAX(conn->evt.ticks_active_to_start,
+				    conn->evt.ticks_preempt_to_start);
+
+			conn->llcp.conn_upd.ticks_anchor -=
+				(conn->evt.ticks_xtal_to_start &
+				 ~XON_BITMASK) - ticks_prepare_to_start;
+		}
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+
+		conn->llcp.conn_upd.pdu_win_offset = (uint16_t *)
+			&pdu_ctrl_tx->llctrl.conn_update_ind.win_offset;
+
+		mfy_sched_offset->fp = fp_mfy_select_or_use;
+		mfy_sched_offset->param = (void *)conn;
+
+		retval = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+					TICKER_USER_ID_ULL_LOW, 1,
+					mfy_sched_offset);
+		LL_ASSERT(!retval);
+	}
+#else /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+	ARG_UNUSED(ticks_at_expire);
+	ARG_UNUSED(mfy_sched_offset);
+	ARG_UNUSED(fp_mfy_select_or_use);
+#endif /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+}
+
+static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
+				      uint32_t ticks_at_expire)
+{
+	struct lll_conn *lll = &conn->lll;
+	struct ll_conn *conn_upd;
+	uint16_t instant_latency;
+	uint16_t event_counter;
+
+	conn_upd = conn_upd_curr;
+
+	/* set mutex */
+	if (!conn_upd) {
+		conn_upd_curr = conn;
+	}
+
+	/* Calculate current event counter */
+	event_counter = lll->event_counter + lll->latency_prepare + lazy;
+
+	instant_latency = (event_counter - conn->llcp.conn_upd.instant) &
+			  0xffff;
+	if (conn->llcp_cu.state != LLCP_CUI_STATE_INPROG) {
+#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+		static memq_link_t s_link;
+		static struct mayfly s_mfy_sched_offset = {0, 0,
+			&s_link, 0, 0 };
+		void (*fp_mfy_select_or_use)(void *) = NULL;
+#endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
+		struct pdu_data *pdu_ctrl_tx;
+		struct node_rx_pdu *rx;
+		struct node_tx *tx;
+
+		rx = ll_pdu_rx_alloc_peek(1);
+		if (!rx) {
+			return -ENOBUFS;
+		}
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+
+		(void)ll_pdu_rx_alloc();
+		rx->hdr.link->mem = conn->llcp_rx;
+		conn->llcp_rx = rx;
+
+		pdu_ctrl_tx = (void *)tx->pdu;
+
+#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+		switch (conn->llcp_cu.state) {
+		case LLCP_CUI_STATE_USE:
+			fp_mfy_select_or_use = ull_sched_mfy_win_offset_use;
+			break;
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		case LLCP_CUI_STATE_SELECT:
+			fp_mfy_select_or_use = ull_sched_mfy_win_offset_select;
+			break;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+		default:
+			LL_ASSERT(0);
+			break;
+		}
+
+		event_conn_upd_init(conn, event_counter, ticks_at_expire,
+				    pdu_ctrl_tx, &s_mfy_sched_offset,
+				    fp_mfy_select_or_use);
+#else /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+		event_conn_upd_init(conn, event_counter, ticks_at_expire,
+				    pdu_ctrl_tx, NULL, NULL);
+#endif /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+
+		ctrl_tx_enqueue(conn, tx);
+
+	} else if (instant_latency <= 0x7FFF) {
+		uint32_t ticks_win_offset = 0;
+		uint32_t ticks_slot_overhead;
+		uint16_t conn_interval_old;
+		uint16_t conn_interval_new;
+		uint32_t conn_interval_us;
+		struct node_rx_pdu *rx;
+		uint8_t ticker_id_conn;
+		uint32_t ticker_status;
+		uint32_t periodic_us;
+		uint16_t latency;
+
+		/* procedure request acked */
+		conn->llcp_cu.ack = conn->llcp_cu.req;
+		conn->llcp_ack = conn->llcp_req;
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		if ((conn->llcp_conn_param.req != conn->llcp_conn_param.ack) &&
+		    (conn->llcp_conn_param.state == LLCP_CPR_STATE_UPD)) {
+			conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+			/* Stop procedure timeout */
+			conn->procedure_expire = 0U;
+		}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+		/* reset mutex */
+		if (conn_upd_curr == conn) {
+			ull_conn_upd_curr_reset();
+		}
+
+		lll = &conn->lll;
+
+		/* Acquire Rx node */
+		rx = conn->llcp_rx;
+		LL_ASSERT(rx && rx->hdr.link);
+		conn->llcp_rx = rx->hdr.link->mem;
+
+		/* Prepare the rx packet structure */
+		if ((conn->llcp_cu.interval != lll->interval) ||
+		    (conn->llcp_cu.latency != lll->latency) ||
+		    (RADIO_CONN_EVENTS(conn->llcp_cu.timeout * 10000U,
+				       lll->interval * 1250) !=
+		     conn->supervision_reload)) {
+			struct node_rx_cu *cu;
+
+			rx->hdr.handle = lll->handle;
+			rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
+
+			/* prepare connection update complete structure */
+			cu = (void *)rx->pdu;
+			cu->status = 0x00;
+			cu->interval = conn->llcp_cu.interval;
+			cu->latency = conn->llcp_cu.latency;
+			cu->timeout = conn->llcp_cu.timeout;
+		} else {
+			/* Mark for buffer for release */
+			rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+		}
+
+		/* enqueue rx node towards Thread */
+		ll_rx_put(rx->hdr.link, rx);
+		ll_rx_sched();
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+		/* restore to normal prepare */
+		if (conn->evt.ticks_xtal_to_start & XON_BITMASK) {
+			uint32_t ticks_prepare_to_start =
+				MAX(conn->evt.ticks_active_to_start,
+				    conn->evt.ticks_preempt_to_start);
+
+			conn->evt.ticks_xtal_to_start &= ~XON_BITMASK;
+			ticks_at_expire -= (conn->evt.ticks_xtal_to_start -
+					    ticks_prepare_to_start);
+		}
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+
+		/* compensate for instant_latency due to laziness */
+		conn_interval_old = instant_latency * lll->interval;
+		latency = conn_interval_old / conn->llcp_cu.interval;
+		conn_interval_new = latency * conn->llcp_cu.interval;
+		if (conn_interval_new > conn_interval_old) {
+			ticks_at_expire += HAL_TICKER_US_TO_TICKS(
+				(conn_interval_new - conn_interval_old) * 1250U);
+		} else {
+			ticks_at_expire -= HAL_TICKER_US_TO_TICKS(
+				(conn_interval_old - conn_interval_new) * 1250U);
+		}
+		lll->latency_prepare += lazy;
+		lll->latency_prepare -= (instant_latency - latency);
+
+		/* calculate the offset */
+		if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+			ticks_slot_overhead =
+				MAX(conn->evt.ticks_active_to_start,
+				    conn->evt.ticks_xtal_to_start);
+
+		} else {
+			ticks_slot_overhead = 0U;
+		}
+
+		/* calculate the window widening and interval */
+		conn_interval_us = conn->llcp_cu.interval * 1250U;
+		periodic_us = conn_interval_us;
+
+		if (0) {
+#if defined(CONFIG_BT_PERIPHERAL)
+		} else if (lll->role) {
+			lll->slave.window_widening_prepare_us -=
+				lll->slave.window_widening_periodic_us *
+				instant_latency;
+
+			lll->slave.window_widening_periodic_us =
+				(((lll_clock_ppm_local_get() +
+				   lll_clock_ppm_get(conn->slave.sca)) *
+				  conn_interval_us) + (1000000 - 1)) / 1000000U;
+			lll->slave.window_widening_max_us =
+				(conn_interval_us >> 1) - EVENT_IFS_US;
+			lll->slave.window_size_prepare_us =
+				conn->llcp_cu.win_size * 1250U;
+			conn->slave.ticks_to_offset = 0U;
+
+			lll->slave.window_widening_prepare_us +=
+				lll->slave.window_widening_periodic_us *
+				latency;
+			if (lll->slave.window_widening_prepare_us >
+			    lll->slave.window_widening_max_us) {
+				lll->slave.window_widening_prepare_us =
+					lll->slave.window_widening_max_us;
+			}
+
+			ticks_at_expire -= HAL_TICKER_US_TO_TICKS(
+				lll->slave.window_widening_periodic_us *
+				latency);
+			ticks_win_offset = HAL_TICKER_US_TO_TICKS(
+				(conn->llcp_cu.win_offset_us / 1250U) * 1250U);
+			periodic_us -= lll->slave.window_widening_periodic_us;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CENTRAL)
+		} else if (!lll->role) {
+			ticks_win_offset = HAL_TICKER_US_TO_TICKS(
+				conn->llcp_cu.win_offset_us);
+
+			/* Workaround: Due to the missing remainder param in
+			 * ticker_start function for first interval; add a
+			 * tick so as to use the ceiled value.
+			 */
+			ticks_win_offset += 1U;
+#endif /* CONFIG_BT_CENTRAL */
+
+		} else {
+			LL_ASSERT(0);
+		}
+
+		lll->interval = conn->llcp_cu.interval;
+		lll->latency = conn->llcp_cu.latency;
+
+		conn->supervision_reload =
+			RADIO_CONN_EVENTS((conn->llcp_cu.timeout * 10U * 1000U),
+					  conn_interval_us);
+		conn->procedure_reload =
+			RADIO_CONN_EVENTS((40 * 1000 * 1000), conn_interval_us);
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+		/* APTO in no. of connection events */
+		conn->apto_reload = RADIO_CONN_EVENTS((30 * 1000 * 1000),
+						      conn_interval_us);
+		/* Dispatch LE Ping PDU 6 connection events (that peer would
+		 * listen to) before 30s timeout
+		 * TODO: "peer listens to" is greater than 30s due to latency
+		 */
+		conn->appto_reload = (conn->apto_reload > (lll->latency + 6)) ?
+				     (conn->apto_reload - (lll->latency + 6)) :
+				     conn->apto_reload;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+		if (conn->llcp_cu.cmd) {
+			conn->supervision_expire = 0U;
+		}
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+		/* disable ticker job, in order to chain stop and start
+		 * to avoid RTC being stopped if no tickers active.
+		 */
+		uint32_t mayfly_was_enabled =
+			mayfly_is_enabled(TICKER_USER_ID_ULL_HIGH,
+					  TICKER_USER_ID_ULL_LOW);
+		mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW,
+			      0);
+#endif
+
+		/* start slave/master with new timings */
+		ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn);
+		ticker_status =	ticker_stop(TICKER_INSTANCE_ID_CTLR,
+					    TICKER_USER_ID_ULL_HIGH,
+					    ticker_id_conn,
+					    ticker_stop_conn_op_cb,
+					    (void *)conn);
+		LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+			  (ticker_status == TICKER_STATUS_BUSY));
+		ticker_status =
+			ticker_start(TICKER_INSTANCE_ID_CTLR,
+				     TICKER_USER_ID_ULL_HIGH,
+				     ticker_id_conn,
+				     ticks_at_expire, ticks_win_offset,
+				     HAL_TICKER_US_TO_TICKS(periodic_us),
+				     HAL_TICKER_REMAINDER(periodic_us),
+#if defined(CONFIG_BT_CTLR_CONN_META)
+				     TICKER_LAZY_MUST_EXPIRE,
+#else
+				     TICKER_NULL_LAZY,
+#endif /* CONFIG_BT_CTLR_CONN_META */
+				     (ticks_slot_overhead +
+				      conn->evt.ticks_slot),
+#if defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CENTRAL)
+				     lll->role ? ull_slave_ticker_cb :
+						 ull_master_ticker_cb,
+#elif defined(CONFIG_BT_PERIPHERAL)
+				     ull_slave_ticker_cb,
+#else
+				     ull_master_ticker_cb,
+#endif
+				     conn, ticker_start_conn_op_cb,
+				     (void *)conn);
+		LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+			  (ticker_status == TICKER_STATUS_BUSY));
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+		/* enable ticker job, if disabled in this function */
+		if (mayfly_was_enabled) {
+			mayfly_enable(TICKER_USER_ID_ULL_HIGH,
+				      TICKER_USER_ID_ULL_LOW, 1);
+		}
+#endif
+
+		return 0;
+	}
+
+	return -EINPROGRESS;
+}
+
+static inline void event_ch_map_prep(struct ll_conn *conn,
+				     uint16_t event_counter)
+{
+	if (conn->llcp.chan_map.initiate) {
+		struct node_tx *tx;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (tx) {
+			struct pdu_data *pdu_ctrl_tx = (void *)tx->pdu;
+
+			/* reset initiate flag */
+			conn->llcp.chan_map.initiate = 0U;
+
+			/* set instant */
+			conn->llcp.chan_map.instant = event_counter +
+						      conn->lll.latency + 6;
+
+			/* place the channel map req packet as next in
+			 * tx queue
+			 */
+			pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+			pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl,
+						    chan_map_ind) +
+				sizeof(struct pdu_data_llctrl_chan_map_ind);
+			pdu_ctrl_tx->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND;
+			memcpy(&pdu_ctrl_tx->llctrl.chan_map_ind.chm[0],
+			       &conn->llcp.chan_map.chm[0],
+			       sizeof(pdu_ctrl_tx->llctrl.chan_map_ind.chm));
+			pdu_ctrl_tx->llctrl.chan_map_ind.instant =
+				sys_cpu_to_le16(conn->llcp.chan_map.instant);
+
+			ctrl_tx_enqueue(conn, tx);
+		}
+	} else if (((event_counter - conn->llcp.chan_map.instant) & 0xFFFF)
+			    <= 0x7FFF) {
+		struct lll_conn *lll = &conn->lll;
+
+		/* procedure request acked */
+		conn->llcp_ack = conn->llcp_req;
+
+		/* copy to active channel map */
+		memcpy(&lll->data_chan_map[0],
+		       &conn->llcp.chan_map.chm[0],
+		       sizeof(lll->data_chan_map));
+		lll->data_chan_count =
+			util_ones_count_get(&lll->data_chan_map[0],
+					    sizeof(lll->data_chan_map));
+		conn->chm_updated = 1U;
+	}
+
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static inline void event_enc_reject_prep(struct ll_conn *conn,
+					 struct pdu_data *pdu)
+{
+	pdu->ll_id = PDU_DATA_LLID_CTRL;
+
+	if (conn->common.fex_valid &&
+	    (conn->llcp_feature.features_conn &
+	     BIT(BT_LE_FEAT_BIT_EXT_REJ_IND))) {
+		struct pdu_data_llctrl_reject_ext_ind *p;
+
+		pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
+
+		p = (void *)&pdu->llctrl.reject_ext_ind;
+		p->reject_opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
+		p->error_code = conn->llcp.encryption.error_code;
+
+		pdu->len = sizeof(struct pdu_data_llctrl_reject_ext_ind);
+	} else {
+		struct pdu_data_llctrl_reject_ind *p;
+
+		pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_IND;
+
+		p = (void *)&pdu->llctrl.reject_ind;
+		p->error_code =	conn->llcp.encryption.error_code;
+
+		pdu->len = sizeof(struct pdu_data_llctrl_reject_ind);
+	}
+
+	pdu->len += offsetof(struct pdu_data_llctrl, reject_ind);
+
+	conn->llcp.encryption.error_code = 0U;
+}
+
+static inline void event_enc_prep(struct ll_conn *conn)
+{
+	struct lll_conn *lll = &conn->lll;
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	if (conn->llcp.encryption.state) {
+#if !defined(CONFIG_BT_CTLR_FAST_ENC)
+		if (lll->role &&
+		    (conn->llcp.encryption.state == LLCP_ENC_STATE_INIT)) {
+			struct node_rx_pdu *rx;
+			struct pdu_data *pdu;
+			uint8_t err;
+
+			/* TODO BT Spec. text: may finalize the sending
+			 * of additional data channel PDUs queued in the
+			 * controller.
+			 */
+			err = enc_rsp_send(conn);
+			if (err) {
+				return;
+			}
+
+			/* get a rx node for ULL->LL */
+			rx = ll_pdu_rx_alloc();
+			if (!rx) {
+				return;
+			}
+
+			/* prepare enc req structure */
+			rx->hdr.handle = conn->lll.handle;
+			rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+			pdu = (void *)rx->pdu;
+			pdu->ll_id = PDU_DATA_LLID_CTRL;
+			pdu->len = offsetof(struct pdu_data_llctrl, enc_req) +
+				   sizeof(struct pdu_data_llctrl_enc_req);
+			pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
+			memcpy(&pdu->llctrl.enc_req.rand[0],
+			       &conn->llcp_enc.rand[0],
+			       sizeof(pdu->llctrl.enc_req.rand));
+			pdu->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0];
+			pdu->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1];
+
+			/* enqueue enc req structure into rx queue */
+			ll_rx_put(rx->hdr.link, rx);
+			ll_rx_sched();
+
+			/* Wait for LTK reply */
+			conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
+		}
+#endif /* !CONFIG_BT_CTLR_FAST_ENC */
+
+		return;
+	}
+
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return;
+	}
+
+	pdu_ctrl_tx = (void *)tx->pdu;
+
+	/* master sends encrypted enc start rsp in control priority */
+	if (!lll->role) {
+		/* calc the Session Key */
+		ecb_encrypt(&conn->llcp_enc.ltk[0],
+			    &conn->llcp.encryption.skd[0], NULL,
+			    &lll->ccm_rx.key[0]);
+
+		/* copy the Session Key */
+		memcpy(&lll->ccm_tx.key[0], &lll->ccm_rx.key[0],
+		       sizeof(lll->ccm_tx.key));
+
+		/* copy the IV */
+		memcpy(&lll->ccm_tx.iv[0], &lll->ccm_rx.iv[0],
+		       sizeof(lll->ccm_tx.iv));
+
+		/* initialise counter */
+		lll->ccm_rx.counter = 0;
+		lll->ccm_tx.counter = 0;
+
+		/* set direction: slave to master = 0,
+		 * master to slave = 1
+		 */
+		lll->ccm_rx.direction = 0;
+		lll->ccm_tx.direction = 1;
+
+		/* enable receive encryption */
+		lll->enc_rx = 1;
+
+		/* send enc start resp */
+		start_enc_rsp_send(conn, pdu_ctrl_tx);
+
+		ctrl_tx_enqueue(conn, tx);
+	}
+
+	/* slave send reject ind or start enc req at control priority */
+
+#if defined(CONFIG_BT_CTLR_FAST_ENC)
+	else {
+#else /* !CONFIG_BT_CTLR_FAST_ENC */
+	else if (!lll->enc_rx) {
+#endif /* !CONFIG_BT_CTLR_FAST_ENC */
+
+		/* place the reject ind packet as next in tx queue */
+		if (conn->llcp.encryption.error_code) {
+			event_enc_reject_prep(conn, pdu_ctrl_tx);
+
+			ctrl_tx_enqueue(conn, tx);
+		}
+		/* place the start enc req packet as next in tx queue */
+		else {
+			/* calc the Session Key */
+			ecb_encrypt(&conn->llcp_enc.ltk[0],
+				    &conn->llcp.encryption.skd[0], NULL,
+				    &lll->ccm_rx.key[0]);
+
+			/* copy the Session Key */
+			memcpy(&lll->ccm_tx.key[0],
+			       &lll->ccm_rx.key[0],
+			       sizeof(lll->ccm_tx.key));
+
+			/* copy the IV */
+			memcpy(&lll->ccm_tx.iv[0], &lll->ccm_rx.iv[0],
+			       sizeof(lll->ccm_tx.iv));
+
+			/* initialise counter */
+			lll->ccm_rx.counter = 0U;
+			lll->ccm_tx.counter = 0U;
+
+			/* set direction: slave to master = 0,
+			 * master to slave = 1
+			 */
+			lll->ccm_rx.direction = 1U;
+			lll->ccm_tx.direction = 0U;
+
+			/* enable receive encryption (transmit turned
+			 * on when start enc resp from master is
+			 * received)
+			 */
+			lll->enc_rx = 1U;
+
+			/* prepare the start enc req */
+			pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+			pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl,
+						    start_enc_req) +
+				sizeof(struct pdu_data_llctrl_start_enc_req);
+			pdu_ctrl_tx->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_START_ENC_REQ;
+
+			ctrl_tx_enqueue(conn, tx);
+		}
+
+#if !defined(CONFIG_BT_CTLR_FAST_ENC)
+	} else {
+		start_enc_rsp_send(conn, pdu_ctrl_tx);
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* resume data packet rx and tx */
+		conn->llcp_enc.pause_rx = 0U;
+		conn->llcp_enc.pause_tx = 0U;
+#endif /* !CONFIG_BT_CTLR_FAST_ENC */
+	}
+
+	/* procedure request acked */
+	conn->llcp_ack = conn->llcp_req;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static inline void event_fex_prep(struct ll_conn *conn)
+{
+	struct node_tx *tx;
+
+	/* If waiting for response, do nothing */
+	if (!((conn->llcp_feature.ack - conn->llcp_feature.req) & 0x01)) {
+		return;
+	}
+
+	if (conn->common.fex_valid) {
+		struct node_rx_pdu *rx;
+		struct pdu_data *pdu;
+
+		/* get a rx node for ULL->LL */
+		rx = ll_pdu_rx_alloc();
+		if (!rx) {
+			return;
+		}
+
+		/* procedure request acked */
+		conn->llcp_feature.ack = conn->llcp_feature.req;
+
+		/* prepare feature rsp structure */
+		rx->hdr.handle = conn->lll.handle;
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+		pdu = (void *)rx->pdu;
+		pdu->ll_id = PDU_DATA_LLID_CTRL;
+		pdu->len = offsetof(struct pdu_data_llctrl, feature_rsp) +
+			   sizeof(struct pdu_data_llctrl_feature_rsp);
+		pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
+		(void)memset(&pdu->llctrl.feature_rsp.features[0], 0x00,
+			sizeof(pdu->llctrl.feature_rsp.features));
+		sys_put_le24(conn->llcp_feature.features_peer,
+			     pdu->llctrl.feature_req.features);
+
+		/* enqueue feature rsp structure into rx queue */
+		ll_rx_put(rx->hdr.link, rx);
+		ll_rx_sched();
+
+		return;
+	}
+
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (tx) {
+		struct pdu_data *pdu = (void *)tx->pdu;
+
+		/* procedure request acked, move to waiting state */
+		conn->llcp_feature.ack--;
+
+		/* use initial feature bitmap */
+		conn->llcp_feature.features_conn = LL_FEAT;
+
+		/* place the feature exchange req packet as next in tx queue */
+		pdu->ll_id = PDU_DATA_LLID_CTRL;
+		pdu->len = offsetof(struct pdu_data_llctrl, feature_req) +
+			   sizeof(struct pdu_data_llctrl_feature_req);
+		pdu->llctrl.opcode = !conn->lll.role ?
+				     PDU_DATA_LLCTRL_TYPE_FEATURE_REQ :
+				     PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ;
+		(void)memset(&pdu->llctrl.feature_req.features[0],
+			     0x00,
+			     sizeof(pdu->llctrl.feature_req.features));
+		sys_put_le24(conn->llcp_feature.features_conn,
+			     pdu->llctrl.feature_req.features);
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* Start Procedure Timeout (TODO: this shall not replace
+		 * terminate procedure)
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+	}
+
+}
+
+static inline void event_vex_prep(struct ll_conn *conn)
+{
+	/* If waiting for response, do nothing */
+	if (!((conn->llcp_version.ack - conn->llcp_version.req) & 0x01)) {
+		return;
+	}
+
+	if (conn->llcp_version.tx == 0U) {
+		struct node_tx *tx;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (tx) {
+			struct pdu_data *pdu = (void *)tx->pdu;
+			uint16_t cid;
+			uint16_t svn;
+
+			/* procedure request acked, move to waiting state  */
+			conn->llcp_version.ack--;
+
+			/* set version ind tx-ed flag */
+			conn->llcp_version.tx = 1U;
+
+			/* place the version ind packet as next in tx queue */
+			pdu->ll_id = PDU_DATA_LLID_CTRL;
+			pdu->len =
+				offsetof(struct pdu_data_llctrl, version_ind) +
+				sizeof(struct pdu_data_llctrl_version_ind);
+			pdu->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_VERSION_IND;
+			pdu->llctrl.version_ind.version_number =
+				LL_VERSION_NUMBER;
+			cid = sys_cpu_to_le16(ll_settings_company_id());
+			svn = sys_cpu_to_le16(ll_settings_subversion_number());
+			pdu->llctrl.version_ind.company_id = cid;
+			pdu->llctrl.version_ind.sub_version_number = svn;
+
+			ctrl_tx_enqueue(conn, tx);
+
+			/* Start Procedure Timeout (TODO: this shall not
+			 * replace terminate procedure)
+			 */
+			conn->procedure_expire = conn->procedure_reload;
+		}
+	} else if (conn->llcp_version.rx) {
+		struct node_rx_pdu *rx;
+		struct pdu_data *pdu;
+
+		/* get a rx node for ULL->LL */
+		rx = ll_pdu_rx_alloc();
+		if (!rx) {
+			return;
+		};
+
+		/* procedure request acked */
+		conn->llcp_version.ack = conn->llcp_version.req;
+
+		rx->hdr.handle = conn->lll.handle;
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+
+		/* prepare version ind structure */
+		pdu = (void *)rx->pdu;
+		pdu->ll_id = PDU_DATA_LLID_CTRL;
+		pdu->len = offsetof(struct pdu_data_llctrl, version_ind) +
+			   sizeof(struct pdu_data_llctrl_version_ind);
+		pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_VERSION_IND;
+		pdu->llctrl.version_ind.version_number =
+			conn->llcp_version.version_number;
+		pdu->llctrl.version_ind.company_id =
+			sys_cpu_to_le16(conn->llcp_version.company_id);
+		pdu->llctrl.version_ind.sub_version_number =
+			sys_cpu_to_le16(conn->llcp_version.sub_version_number);
+
+		/* enqueue version ind structure into rx queue */
+		ll_rx_put(rx->hdr.link, rx);
+		ll_rx_sched();
+	} else {
+		/* tx-ed but no rx, and new request placed */
+		LL_ASSERT(0);
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static inline void event_conn_param_req(struct ll_conn *conn,
+					uint16_t event_counter,
+					uint32_t ticks_at_expire)
+{
+	struct pdu_data_llctrl_conn_param_req *p;
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return;
+	}
+
+	/* move to wait for conn_update/rsp/rej */
+	conn->llcp_conn_param.state = LLCP_CPR_STATE_RSP_WAIT;
+
+	/* place the conn param req packet as next in tx queue */
+	pdu_ctrl_tx = (void *)tx->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, conn_param_req) +
+		sizeof(struct pdu_data_llctrl_conn_param_req);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
+	p = (void *)&pdu_ctrl_tx->llctrl.conn_param_req;
+	p->interval_min = sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
+	p->interval_max = sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
+	p->latency = sys_cpu_to_le16(conn->llcp_conn_param.latency);
+	p->timeout = sys_cpu_to_le16(conn->llcp_conn_param.timeout);
+	p->preferred_periodicity = 0U;
+	p->reference_conn_event_count = sys_cpu_to_le16(event_counter);
+	p->offset0 = sys_cpu_to_le16(0x0000);
+	p->offset1 = sys_cpu_to_le16(0xffff);
+	p->offset2 = sys_cpu_to_le16(0xffff);
+	p->offset3 = sys_cpu_to_le16(0xffff);
+	p->offset4 = sys_cpu_to_le16(0xffff);
+	p->offset5 = sys_cpu_to_le16(0xffff);
+
+	ctrl_tx_enqueue(conn, tx);
+
+	/* set CUI/CPR mutex */
+	conn_upd_curr = conn;
+
+	/* Start Procedure Timeout (TODO: this shall not replace
+	 * terminate procedure).
+	 */
+	conn->procedure_expire = conn->procedure_reload;
+
+#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+	{
+		static memq_link_t s_link;
+		static struct mayfly s_mfy_sched_offset = {0, 0, &s_link, NULL,
+			ull_sched_mfy_free_win_offset_calc};
+		uint32_t retval;
+
+		conn->llcp_conn_param.ticks_ref = ticks_at_expire;
+
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+		if (conn->evt.ticks_xtal_to_start & XON_BITMASK) {
+			uint32_t ticks_prepare_to_start =
+				MAX(conn->evt.ticks_active_to_start,
+				    conn->evt.ticks_preempt_to_start);
+
+			conn->llcp_conn_param.ticks_ref -=
+				(conn->evt.ticks_xtal_to_start &
+				 ~XON_BITMASK) - ticks_prepare_to_start;
+		}
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+
+		conn->llcp_conn_param.pdu_win_offset0 = (uint16_t *)&p->offset0;
+
+		s_mfy_sched_offset.param = (void *)conn;
+
+		retval = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+					TICKER_USER_ID_ULL_LOW, 1,
+					&s_mfy_sched_offset);
+		LL_ASSERT(!retval);
+	}
+#else /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+	ARG_UNUSED(ticks_at_expire);
+#endif /* !CONFIG_BT_CTLR_SCHED_ADVANCED */
+}
+
+static inline void event_conn_param_rsp(struct ll_conn *conn)
+{
+	struct pdu_data_llctrl_conn_param_rsp *rsp;
+	struct node_tx *tx;
+	struct pdu_data *pdu;
+
+	/* handle rejects */
+	if (conn->llcp_conn_param.status) {
+		struct pdu_data_llctrl_reject_ext_ind *rej;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return;
+		}
+
+		/* master/slave response with reject ext ind */
+		pdu = (void *)tx->pdu;
+		pdu->ll_id = PDU_DATA_LLID_CTRL;
+		pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
+		pdu->len = offsetof(struct pdu_data_llctrl, reject_ext_ind) +
+			   sizeof(struct pdu_data_llctrl_reject_ext_ind);
+
+		rej = (void *)&pdu->llctrl.reject_ext_ind;
+		rej->reject_opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
+		rej->error_code = conn->llcp_conn_param.status;
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* procedure request acked */
+		conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+		/* reset mutex */
+		ull_conn_upd_curr_reset();
+
+		return;
+	}
+
+	/* master respond with connection update */
+	if (!conn->lll.role) {
+		if (conn->llcp_cu.req != conn->llcp_cu.ack) {
+			return;
+		}
+
+		/* Move to waiting for connection update completion */
+		conn->llcp_conn_param.state = LLCP_CPR_STATE_UPD;
+
+		/* Initiate connection update procedure */
+		conn->llcp_cu.win_size = 1U;
+		conn->llcp_cu.win_offset_us = 0U;
+		if (conn->llcp_conn_param.preferred_periodicity) {
+			conn->llcp_cu.interval =
+				((conn->llcp_conn_param.interval_min /
+				  conn->llcp_conn_param.preferred_periodicity) +
+				 1) *
+				conn->llcp_conn_param.preferred_periodicity;
+		} else {
+			conn->llcp_cu.interval =
+				conn->llcp_conn_param.interval_max;
+		}
+		conn->llcp_cu.latency = conn->llcp_conn_param.latency;
+		conn->llcp_cu.timeout = conn->llcp_conn_param.timeout;
+		conn->llcp_cu.state = LLCP_CUI_STATE_SELECT;
+		conn->llcp_cu.cmd = conn->llcp_conn_param.cmd;
+		conn->llcp_cu.ack--;
+
+		return;
+	}
+
+	/* slave response with connection parameter response */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return;
+	}
+
+	/* place the conn param rsp packet as next in tx queue */
+	pdu = (void *)tx->pdu;
+	pdu->ll_id = PDU_DATA_LLID_CTRL;
+	pdu->len = offsetof(struct pdu_data_llctrl, conn_param_rsp) +
+		sizeof(struct pdu_data_llctrl_conn_param_rsp);
+	pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP;
+	rsp = (void *)&pdu->llctrl.conn_param_rsp;
+	rsp->interval_min =
+		sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
+	rsp->interval_max =
+		sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
+	rsp->latency =
+		sys_cpu_to_le16(conn->llcp_conn_param.latency);
+	rsp->timeout =
+		sys_cpu_to_le16(conn->llcp_conn_param.timeout);
+	rsp->preferred_periodicity =
+		conn->llcp_conn_param.preferred_periodicity;
+	rsp->reference_conn_event_count =
+		sys_cpu_to_le16(conn->llcp_conn_param.reference_conn_event_count);
+	rsp->offset0 = sys_cpu_to_le16(conn->llcp_conn_param.offset0);
+	rsp->offset1 = sys_cpu_to_le16(conn->llcp_conn_param.offset1);
+	rsp->offset2 = sys_cpu_to_le16(conn->llcp_conn_param.offset2);
+	rsp->offset3 = sys_cpu_to_le16(conn->llcp_conn_param.offset3);
+	rsp->offset4 = sys_cpu_to_le16(conn->llcp_conn_param.offset4);
+	rsp->offset5 = sys_cpu_to_le16(conn->llcp_conn_param.offset5);
+
+	ctrl_tx_enqueue(conn, tx);
+
+	/* procedure request acked */
+	conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+	/* reset mutex */
+	ull_conn_upd_curr_reset();
+}
+
+static inline void event_conn_param_app_req(struct ll_conn *conn)
+{
+	struct pdu_data_llctrl_conn_param_req *p;
+	struct node_rx_pdu *rx;
+	struct pdu_data *pdu;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	/* defer until encryption setup is complete */
+	if (conn->llcp_enc.pause_tx) {
+		return;
+	}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	/* wait for free rx buffer */
+	rx = ll_pdu_rx_alloc();
+	if (!rx) {
+		return;
+	}
+
+	/* move to wait for conn_update/rsp/rej */
+	conn->llcp_conn_param.state = LLCP_CPR_STATE_APP_WAIT;
+
+	/* Emulate as Rx-ed CPR data channel PDU */
+	rx->hdr.handle = conn->lll.handle;
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+
+	/* place the conn param req packet as next in rx queue */
+	pdu = (void *)rx->pdu;
+	pdu->ll_id = PDU_DATA_LLID_CTRL;
+	pdu->len = offsetof(struct pdu_data_llctrl, conn_param_req) +
+		sizeof(struct pdu_data_llctrl_conn_param_req);
+	pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
+	p = (void *) &pdu->llctrl.conn_param_req;
+	p->interval_min = sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
+	p->interval_max = sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
+	p->latency = sys_cpu_to_le16(conn->llcp_conn_param.latency);
+	p->timeout = sys_cpu_to_le16(conn->llcp_conn_param.timeout);
+
+	/* enqueue connection parameter request into rx queue */
+	ll_rx_put(rx->hdr.link, rx);
+	ll_rx_sched();
+}
+
+static inline void event_conn_param_prep(struct ll_conn *conn,
+					 uint16_t event_counter,
+					 uint32_t ticks_at_expire)
+{
+	struct ll_conn *conn_upd;
+
+	conn_upd = conn_upd_curr;
+	if (conn_upd && (conn_upd != conn)) {
+		return;
+	}
+
+	switch (conn->llcp_conn_param.state) {
+	case LLCP_CPR_STATE_REQ:
+		event_conn_param_req(conn, event_counter, ticks_at_expire);
+		break;
+
+	case LLCP_CPR_STATE_RSP:
+		event_conn_param_rsp(conn);
+		break;
+
+	case LLCP_CPR_STATE_APP_REQ:
+		event_conn_param_app_req(conn);
+		break;
+
+	case LLCP_CPR_STATE_APP_WAIT:
+	case LLCP_CPR_STATE_RSP_WAIT:
+	case LLCP_CPR_STATE_UPD:
+		/* Do nothing */
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+static inline void event_ping_prep(struct ll_conn *conn)
+{
+	struct node_tx *tx;
+
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (tx) {
+		struct pdu_data *pdu_ctrl_tx = (void *)tx->pdu;
+
+		/* procedure request acked */
+		conn->llcp_ack = conn->llcp_req;
+
+		/* place the ping req packet as next in tx queue */
+		pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, ping_req) +
+				   sizeof(struct pdu_data_llctrl_ping_req);
+		pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_PING_REQ;
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* Start Procedure Timeout (TODO: this shall not replace
+		 * terminate procedure)
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+	}
+
+}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static inline void dle_max_time_get(const struct ll_conn *conn,
+				    uint16_t *max_rx_time, uint16_t *max_tx_time)
+{
+	uint32_t feature_coded_phy = 0;
+	uint32_t feature_phy_2m = 0;
+	uint16_t rx_time = 0;
+	uint16_t tx_time = 0;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	feature_coded_phy = (conn->llcp_feature.features_conn &
+			     BIT(BT_LE_FEAT_BIT_PHY_CODED));
+#else
+	feature_coded_phy = 0;
+#endif
+
+#if defined(CONFIG_BT_CTLR_PHY_2M)
+	feature_phy_2m = (conn->llcp_feature.features_conn &
+			  BIT(BT_LE_FEAT_BIT_PHY_2M));
+#else
+	feature_phy_2m = 0;
+#endif
+#else
+	feature_coded_phy = 0;
+	feature_phy_2m = 0;
+#endif
+
+	if (!conn->common.fex_valid ||
+	    (!feature_coded_phy && !feature_phy_2m)) {
+		rx_time = PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_1M);
+#if defined(CONFIG_BT_CTLR_PHY)
+		tx_time = MAX(MIN(PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_1M),
+				  conn->default_tx_time),
+			      PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M));
+#else /* !CONFIG_BT_CTLR_PHY */
+		tx_time = PKT_US(conn->default_tx_octets, PHY_1M);
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	} else if (feature_coded_phy) {
+		rx_time = MAX(PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_CODED),
+			      PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_CODED));
+		tx_time = MIN(PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_CODED),
+			      conn->default_tx_time);
+		tx_time = MAX(PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M), tx_time);
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+#if defined(CONFIG_BT_CTLR_PHY_2M)
+	} else if (feature_phy_2m) {
+		rx_time = MAX(PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_2M),
+			      PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_2M));
+		tx_time = MAX(PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M),
+			      MIN(PKT_US(LL_LENGTH_OCTETS_RX_MAX, PHY_2M),
+				  conn->default_tx_time));
+#endif /* CONFIG_BT_CTLR_PHY_2M */
+#endif /* CONFIG_BT_CTLR_PHY */
+	}
+
+	/*
+	 * see Vol. 6 Part B chapter 4.5.10
+	 * minimum value for time is 328 us
+	 */
+	rx_time = MAX(PDU_DC_PAYLOAD_TIME_MIN, rx_time);
+	tx_time = MAX(PDU_DC_PAYLOAD_TIME_MIN, tx_time);
+
+	*max_rx_time = rx_time;
+	*max_tx_time = tx_time;
+}
+
+static inline void event_len_prep(struct ll_conn *conn)
+{
+	switch (conn->llcp_length.state) {
+	case LLCP_LENGTH_STATE_REQ:
+	{
+		struct pdu_data_llctrl_length_req *lr;
+		struct pdu_data *pdu_ctrl_tx;
+		struct node_tx *tx;
+		/*
+		 * initialize to 0 to eliminate compiler warnings
+		 */
+		uint16_t rx_time = 0;
+		uint16_t tx_time = 0;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return;
+		}
+
+		/* wait for resp before completing the procedure */
+		conn->llcp_length.state = LLCP_LENGTH_STATE_REQ_ACK_WAIT;
+
+		/* set the default tx octets/time to requested value */
+		conn->default_tx_octets = conn->llcp_length.tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		conn->default_tx_time = conn->llcp_length.tx_time;
+#endif
+
+		/* place the length req packet as next in tx queue */
+		pdu_ctrl_tx = (void *) tx->pdu;
+		pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_tx->len =
+			offsetof(struct pdu_data_llctrl, length_req) +
+			sizeof(struct pdu_data_llctrl_length_req);
+		pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_REQ;
+
+		lr = &pdu_ctrl_tx->llctrl.length_req;
+		lr->max_rx_octets = sys_cpu_to_le16(LL_LENGTH_OCTETS_RX_MAX);
+		lr->max_tx_octets = sys_cpu_to_le16(conn->default_tx_octets);
+
+		dle_max_time_get(conn, &rx_time, &tx_time);
+		lr->max_rx_time = sys_cpu_to_le16(rx_time);
+		lr->max_tx_time = sys_cpu_to_le16(tx_time);
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* Start Procedure Timeout (TODO: this shall not replace
+		 * terminate procedure).
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+	}
+	break;
+
+	case LLCP_LENGTH_STATE_RESIZE:
+	case LLCP_LENGTH_STATE_RESIZE_RSP:
+	{
+		struct pdu_data_llctrl_length_rsp *lr;
+		struct pdu_data *pdu_ctrl_rx;
+		struct node_rx_pdu *rx;
+		struct lll_conn *lll;
+		uint16_t tx_octets;
+
+		lll = &conn->lll;
+
+		/* Use the new rx octets/time in the connection */
+		lll->max_rx_octets = conn->llcp_length.rx_octets;
+
+		/* backup tx_octets */
+		tx_octets = conn->llcp_length.tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		/* Use the new rx time in the connection */
+		lll->max_rx_time = conn->llcp_length.rx_time;
+
+		/* backup tx time */
+		uint16_t tx_time = conn->llcp_length.tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		/* switch states, to wait for ack, to request cached values or
+		 * complete the procedure
+		 */
+		if (conn->llcp_length.state == LLCP_LENGTH_STATE_RESIZE) {
+			/* check cache */
+			if (!conn->llcp_length.cache.tx_octets) {
+				/* Procedure complete */
+				conn->llcp_length.ack = conn->llcp_length.req;
+				conn->procedure_expire = 0U;
+			} else {
+				/* Initiate cached procedure */
+				conn->llcp_length.tx_octets =
+					conn->llcp_length.cache.tx_octets;
+				conn->llcp_length.cache.tx_octets = 0;
+#if defined(CONFIG_BT_CTLR_PHY)
+				conn->llcp_length.tx_time =
+					conn->llcp_length.cache.tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+				conn->llcp_length.state = LLCP_LENGTH_STATE_REQ;
+			}
+		} else {
+			conn->llcp_length.state =
+				LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT;
+		}
+
+		/* Prepare the rx packet structure */
+		rx = conn->llcp_rx;
+		LL_ASSERT(rx && rx->hdr.link);
+		conn->llcp_rx = rx->hdr.link->mem;
+
+		rx->hdr.handle = conn->lll.handle;
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+
+		/* prepare length rsp structure */
+		pdu_ctrl_rx = (void *)rx->pdu;
+		pdu_ctrl_rx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_rx->len =
+			offsetof(struct pdu_data_llctrl, length_rsp) +
+			sizeof(struct pdu_data_llctrl_length_rsp);
+		pdu_ctrl_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP;
+
+		lr = &pdu_ctrl_rx->llctrl.length_rsp;
+		lr->max_rx_octets = sys_cpu_to_le16(lll->max_rx_octets);
+		lr->max_tx_octets = sys_cpu_to_le16(tx_octets);
+#if !defined(CONFIG_BT_CTLR_PHY)
+		lr->max_rx_time =
+			sys_cpu_to_le16(PKT_US(lll->max_rx_octets, PHY_1M));
+		lr->max_tx_time = sys_cpu_to_le16(PKT_US(tx_octets, PHY_1M));
+#else /* CONFIG_BT_CTLR_PHY */
+		lr->max_rx_time = sys_cpu_to_le16(lll->max_rx_time);
+		lr->max_tx_time = sys_cpu_to_le16(tx_time);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		/* enqueue rx node towards Thread */
+		ll_rx_put(rx->hdr.link, rx);
+		ll_rx_sched();
+	}
+	break;
+
+	case LLCP_LENGTH_STATE_REQ_ACK_WAIT:
+	case LLCP_LENGTH_STATE_RSP_WAIT:
+	case LLCP_LENGTH_STATE_RSP_ACK_WAIT:
+	case LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT:
+		/* no nothing */
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static uint16_t calc_eff_time(uint8_t max_octets, uint8_t phy, uint16_t default_time)
+{
+	uint16_t time = PKT_US(max_octets, phy);
+	uint16_t eff_time;
+
+	eff_time = MAX(PDU_DC_PAYLOAD_TIME_MIN, time);
+	eff_time = MIN(eff_time, default_time);
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	eff_time = MAX(eff_time, PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, phy));
+#endif
+
+	return eff_time;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static inline void event_phy_req_prep(struct ll_conn *conn)
+{
+	switch (conn->llcp_phy.state) {
+	case LLCP_PHY_STATE_REQ:
+	{
+		struct pdu_data_llctrl_phy_req *pr;
+		struct pdu_data *pdu_ctrl_tx;
+		struct node_tx *tx;
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			break;
+		}
+
+		conn->llcp_phy.state = LLCP_PHY_STATE_ACK_WAIT;
+
+		/* update preferred phy */
+		conn->phy_pref_tx = conn->llcp_phy.tx;
+		conn->phy_pref_rx = conn->llcp_phy.rx;
+		conn->phy_pref_flags = conn->llcp_phy.flags;
+
+		/* place the phy req packet as next in tx queue */
+		pdu_ctrl_tx = (void *)tx->pdu;
+		pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_tx->len =
+			offsetof(struct pdu_data_llctrl, phy_req) +
+			sizeof(struct pdu_data_llctrl_phy_req);
+		pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_PHY_REQ;
+
+		pr = &pdu_ctrl_tx->llctrl.phy_req;
+		pr->tx_phys = conn->llcp_phy.tx;
+		pr->rx_phys = conn->llcp_phy.rx;
+
+		ctrl_tx_enqueue(conn, tx);
+
+		/* Start Procedure Timeout (TODO: this shall not replace
+		 * terminate procedure).
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+	}
+	break;
+
+	case LLCP_PHY_STATE_UPD:
+	{
+		/* Defer if another procedure in progress */
+		if (conn->llcp_ack != conn->llcp_req) {
+			return;
+		}
+
+		/* Procedure complete */
+		conn->llcp_phy.ack = conn->llcp_phy.req;
+
+		/* select only one tx phy, prefer 2M */
+		if (conn->llcp_phy.tx & BIT(1)) {
+			conn->llcp_phy.tx = BIT(1);
+		} else if (conn->llcp_phy.tx & BIT(0)) {
+			conn->llcp_phy.tx = BIT(0);
+		} else if (conn->llcp_phy.tx & BIT(2)) {
+			conn->llcp_phy.tx = BIT(2);
+		} else {
+			conn->llcp_phy.tx = 0U;
+		}
+
+		/* select only one rx phy, prefer 2M */
+		if (conn->llcp_phy.rx & BIT(1)) {
+			conn->llcp_phy.rx = BIT(1);
+		} else if (conn->llcp_phy.rx & BIT(0)) {
+			conn->llcp_phy.rx = BIT(0);
+		} else if (conn->llcp_phy.rx & BIT(2)) {
+			conn->llcp_phy.rx = BIT(2);
+		} else {
+			conn->llcp_phy.rx = 0U;
+		}
+
+		/* Initiate PHY Update Ind */
+		if (conn->llcp_phy.tx != conn->lll.phy_tx) {
+			conn->llcp.phy_upd_ind.tx = conn->llcp_phy.tx;
+		} else {
+			conn->llcp.phy_upd_ind.tx = 0U;
+		}
+		if (conn->llcp_phy.rx != conn->lll.phy_rx) {
+			conn->llcp.phy_upd_ind.rx = conn->llcp_phy.rx;
+		} else {
+			conn->llcp.phy_upd_ind.rx = 0U;
+		}
+		/* conn->llcp.phy_upd_ind.instant = 0; */
+		conn->llcp.phy_upd_ind.initiate = 1U;
+		conn->llcp.phy_upd_ind.cmd = conn->llcp_phy.cmd;
+
+		conn->llcp_type = LLCP_PHY_UPD;
+		conn->llcp_ack -= 2U;
+	}
+	break;
+
+	case LLCP_PHY_STATE_ACK_WAIT:
+	case LLCP_PHY_STATE_RSP_WAIT:
+		/* no nothing */
+		break;
+
+	default:
+		LL_ASSERT(0);
+		break;
+	}
+}
+
+static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
+					  uint16_t event_counter)
+{
+	struct node_rx_pu *upd;
+
+	if (conn->llcp.phy_upd_ind.initiate) {
+		struct pdu_data_llctrl_phy_upd_ind *ind;
+		struct pdu_data *pdu_ctrl_tx;
+		struct node_rx_pdu *rx;
+		struct node_tx *tx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		rx = ll_pdu_rx_alloc_peek(2);
+#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
+		rx = ll_pdu_rx_alloc_peek(1);
+#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
+		if (!rx) {
+			return;
+		}
+
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return;
+		}
+
+		/* reset initiate flag */
+		conn->llcp.phy_upd_ind.initiate = 0U;
+
+		/* Check if both tx and rx PHY unchanged */
+		if (!((conn->llcp.phy_upd_ind.tx |
+		       conn->llcp.phy_upd_ind.rx) & 0x07)) {
+			/* Procedure complete */
+			conn->llcp_ack = conn->llcp_req;
+
+			/* 0 instant */
+			conn->llcp.phy_upd_ind.instant = 0U;
+
+			/* generate phy update event */
+			if (conn->llcp.phy_upd_ind.cmd) {
+				struct lll_conn *lll = &conn->lll;
+
+				(void)ll_pdu_rx_alloc();
+
+				rx->hdr.handle = lll->handle;
+				rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
+
+				upd = (void *)rx->pdu;
+				upd->status = 0U;
+				upd->tx = lll->phy_tx;
+				upd->rx = lll->phy_rx;
+
+				/* Enqueue Rx node */
+				ll_rx_put(rx->hdr.link, rx);
+				ll_rx_sched();
+			}
+		} else {
+			struct lll_conn *lll = &conn->lll;
+
+			/* set instant */
+			conn->llcp.phy_upd_ind.instant = event_counter +
+							 lll->latency +
+							 6;
+			/* reserve rx node for event generation at instant */
+			(void)ll_pdu_rx_alloc();
+			rx->hdr.link->mem = conn->llcp_rx;
+			conn->llcp_rx = rx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+			/* reserve rx node for DLE event generation */
+			rx = ll_pdu_rx_alloc();
+			rx->hdr.link->mem = conn->llcp_rx;
+			conn->llcp_rx = rx;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+		}
+
+		/* place the phy update ind packet as next in
+		 * tx queue
+		 */
+		pdu_ctrl_tx = (void *)tx->pdu;
+		pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_tx->len =
+			offsetof(struct pdu_data_llctrl, phy_upd_ind) +
+			sizeof(struct pdu_data_llctrl_phy_upd_ind);
+		pdu_ctrl_tx->llctrl.opcode =
+			PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND;
+		ind = &pdu_ctrl_tx->llctrl.phy_upd_ind;
+		ind->m_to_s_phy = conn->llcp.phy_upd_ind.tx;
+		ind->s_to_m_phy = conn->llcp.phy_upd_ind.rx;
+		ind->instant = sys_cpu_to_le16(conn->llcp.phy_upd_ind.instant);
+
+		ctrl_tx_enqueue(conn, tx);
+	} else if (((event_counter - conn->llcp.phy_upd_ind.instant) &
+		    0xFFFF) <= 0x7FFF) {
+		struct lll_conn *lll = &conn->lll;
+		struct node_rx_pdu *rx;
+		uint8_t old_tx, old_rx;
+
+		/* procedure request acked */
+		conn->llcp_ack = conn->llcp_req;
+
+		/* apply new phy */
+		old_tx = lll->phy_tx;
+		old_rx = lll->phy_rx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		uint16_t eff_tx_time = lll->max_tx_time;
+		uint16_t eff_rx_time = lll->max_rx_time;
+		uint16_t max_rx_time, max_tx_time;
+
+		dle_max_time_get(conn, &max_rx_time, &max_tx_time);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+		if (conn->llcp.phy_upd_ind.tx) {
+			lll->phy_tx = conn->llcp.phy_upd_ind.tx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+			eff_tx_time = calc_eff_time(lll->max_tx_octets,
+						    lll->phy_tx,
+						    max_tx_time);
+
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+		}
+		if (conn->llcp.phy_upd_ind.rx) {
+			lll->phy_rx = conn->llcp.phy_upd_ind.rx;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+			eff_rx_time =
+				calc_eff_time(lll->max_rx_octets, lll->phy_rx,
+					      max_rx_time);
+
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+		}
+		lll->phy_flags = conn->phy_pref_flags;
+
+		/* Acquire Rx node */
+		rx = conn->llcp_rx;
+		LL_ASSERT(rx && rx->hdr.link);
+		conn->llcp_rx = rx->hdr.link->mem;
+
+		/* generate event if phy changed or initiated by cmd */
+		if (!conn->llcp.phy_upd_ind.cmd && (lll->phy_tx == old_tx) &&
+		    (lll->phy_rx == old_rx)) {
+			/* Mark for buffer for release */
+			rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+			/* enqueue rx node towards Thread */
+			ll_rx_put(rx->hdr.link, rx);
+
+			if (IS_ENABLED(CONFIG_BT_CTLR_DATA_LENGTH)) {
+				/* get the DLE rx node reserved for ULL->LL */
+				rx = conn->llcp_rx;
+				LL_ASSERT(rx && rx->hdr.link);
+				conn->llcp_rx = rx->hdr.link->mem;
+
+				/* Mark for buffer for release */
+				rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+				/* enqueue rx node towards Thread */
+				ll_rx_put(rx->hdr.link, rx);
+			}
+
+			ll_rx_sched();
+
+			return;
+		}
+
+		rx->hdr.handle = lll->handle;
+		rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
+
+		upd = (void *)rx->pdu;
+		upd->status = 0U;
+		upd->tx = lll->phy_tx;
+		upd->rx = lll->phy_rx;
+
+		/* enqueue rx node towards Thread */
+		ll_rx_put(rx->hdr.link, rx);
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		/* get a rx node for ULL->LL */
+		rx = conn->llcp_rx;
+		LL_ASSERT(rx && rx->hdr.link);
+		conn->llcp_rx = rx->hdr.link->mem;
+
+		/* Update max tx and/or max rx if changed */
+		if ((eff_tx_time <= lll->max_tx_time) &&
+		    (lll->max_tx_time <= max_tx_time) &&
+		    (eff_rx_time <= lll->max_rx_time) &&
+		    (lll->max_rx_time <= max_rx_time)) {
+			/* Mark buffer for release */
+			rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+			/* enqueue rx node towards Thread */
+			ll_rx_put(rx->hdr.link, rx);
+			ll_rx_sched();
+			return;
+		}
+		lll->max_tx_time = eff_tx_time;
+		lll->max_rx_time = eff_rx_time;
+
+		/* prepare length rsp structure */
+		rx->hdr.handle = lll->handle;
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU;
+
+		struct pdu_data *pdu_rx = (void *)rx->pdu;
+
+		pdu_rx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_rx->len = offsetof(struct pdu_data_llctrl, length_rsp) +
+			      sizeof(struct pdu_data_llctrl_length_rsp);
+		pdu_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP;
+
+		struct pdu_data_llctrl_length_req *lr =
+			(void *)&pdu_rx->llctrl.length_rsp;
+
+		lr->max_rx_octets = sys_cpu_to_le16(lll->max_rx_octets);
+		lr->max_tx_octets = sys_cpu_to_le16(lll->max_tx_octets);
+		lr->max_rx_time = sys_cpu_to_le16(lll->max_rx_time);
+		lr->max_tx_time = sys_cpu_to_le16(lll->max_tx_time);
+
+		/* enqueue rx node towards Thread */
+		ll_rx_put(rx->hdr.link, rx);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+		ll_rx_sched();
+	}
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+static uint8_t conn_upd_recv(struct ll_conn *conn, memq_link_t *link,
+			  struct node_rx_pdu **rx, struct pdu_data *pdu)
+{
+	uint16_t instant;
+
+	instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
+	if (((instant - conn->lll.event_counter) & 0xFFFF) > 0x7FFF) {
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return BT_HCI_ERR_INSTANT_PASSED;
+	}
+
+	/* different transaction collision */
+	if (((conn->llcp_req - conn->llcp_ack) & 0x03) == 0x02) {
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return BT_HCI_ERR_DIFF_TRANS_COLLISION;
+	}
+
+	/* set mutex, if only not already set. As a master the mutex shall
+	 * be set, but a slave we accept it as new 'set' of mutex.
+	 */
+	if (!conn_upd_curr) {
+		LL_ASSERT(conn->lll.role);
+
+		conn_upd_curr = conn;
+	}
+
+	conn->llcp_cu.win_size = pdu->llctrl.conn_update_ind.win_size;
+	conn->llcp_cu.win_offset_us =
+		sys_le16_to_cpu(pdu->llctrl.conn_update_ind.win_offset) * 1250;
+	conn->llcp_cu.interval =
+		sys_le16_to_cpu(pdu->llctrl.conn_update_ind.interval);
+	conn->llcp_cu.latency =
+		sys_le16_to_cpu(pdu->llctrl.conn_update_ind.latency);
+	conn->llcp_cu.timeout =
+		sys_le16_to_cpu(pdu->llctrl.conn_update_ind.timeout);
+	conn->llcp.conn_upd.instant = instant;
+	conn->llcp_cu.state = LLCP_CUI_STATE_INPROG;
+	conn->llcp_cu.cmd = 1U;
+	conn->llcp_cu.ack--;
+
+	link->mem = conn->llcp_rx;
+	(*rx)->hdr.link = link;
+	conn->llcp_rx = *rx;
+	*rx = NULL;
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	if ((conn->llcp_conn_param.req != conn->llcp_conn_param.ack) &&
+	    (conn->llcp_conn_param.state == LLCP_CPR_STATE_RSP_WAIT)) {
+		conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+	}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+	return 0;
+}
+
+static uint8_t chan_map_upd_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
+			      struct pdu_data *pdu)
+{
+	uint8_t err = 0U;
+	uint16_t instant;
+
+	instant = sys_le16_to_cpu(pdu->llctrl.chan_map_ind.instant);
+	if (((instant - conn->lll.event_counter) & 0xffff) > 0x7fff) {
+		err = BT_HCI_ERR_INSTANT_PASSED;
+
+		goto chan_map_upd_recv_exit;
+	}
+
+	/* different transaction collision */
+	if (((conn->llcp_req - conn->llcp_ack) & 0x03) == 0x02) {
+		err = BT_HCI_ERR_DIFF_TRANS_COLLISION;
+
+		goto chan_map_upd_recv_exit;
+	}
+
+
+	memcpy(&conn->llcp.chan_map.chm[0], &pdu->llctrl.chan_map_ind.chm[0],
+	       sizeof(conn->llcp.chan_map.chm));
+	conn->llcp.chan_map.instant = instant;
+	conn->llcp.chan_map.initiate = 0U;
+
+	conn->llcp_type = LLCP_CHAN_MAP;
+	conn->llcp_ack -= 2U;
+
+chan_map_upd_recv_exit:
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return err;
+}
+
+static void terminate_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
+			      struct pdu_data *pdu)
+{
+	/* Ack and then terminate */
+	conn->llcp_terminate.reason_peer = pdu->llctrl.terminate_ind.error_code;
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static void enc_req_reused_send(struct ll_conn *conn, struct node_tx **tx)
+{
+	struct pdu_data *pdu_ctrl_tx;
+
+	pdu_ctrl_tx = (void *)(*tx)->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_req) +
+			   sizeof(struct pdu_data_llctrl_enc_req);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
+	memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0], &conn->llcp_enc.rand[0],
+	       sizeof(pdu_ctrl_tx->llctrl.enc_req.rand));
+	pdu_ctrl_tx->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0];
+	pdu_ctrl_tx->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1];
+
+	/*
+	 * Take advantage of the fact that ivm and skdm fields, which both have
+	 * to be filled with random data, are adjacent and use single call to
+	 * the entropy driver.
+	 */
+	BUILD_ASSERT(offsetof(__typeof(pdu_ctrl_tx->llctrl.enc_req), ivm) ==
+		     (offsetof(__typeof(pdu_ctrl_tx->llctrl.enc_req), skdm) +
+		     sizeof(pdu_ctrl_tx->llctrl.enc_req.skdm)));
+
+	/* NOTE: if not sufficient random numbers, ignore waiting */
+	lll_csrand_isr_get(pdu_ctrl_tx->llctrl.enc_req.skdm,
+			   sizeof(pdu_ctrl_tx->llctrl.enc_req.skdm) +
+			   sizeof(pdu_ctrl_tx->llctrl.enc_req.ivm));
+
+	ctrl_tx_enqueue(conn, *tx);
+
+	/* dont release ctrl PDU memory */
+	*tx = NULL;
+}
+
+static int enc_rsp_send(struct ll_conn *conn)
+{
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	/* acquire tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	pdu_ctrl_tx = (void *)tx->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_rsp) +
+			   sizeof(struct pdu_data_llctrl_enc_rsp);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_RSP;
+
+	/*
+	 * Take advantage of the fact that ivs and skds fields, which both have
+	 * to be filled with random data, are adjacent and use single call to
+	 * the entropy driver.
+	 */
+	BUILD_ASSERT(offsetof(__typeof(pdu_ctrl_tx->llctrl.enc_rsp), ivs) ==
+		     (offsetof(__typeof(pdu_ctrl_tx->llctrl.enc_rsp), skds) +
+		     sizeof(pdu_ctrl_tx->llctrl.enc_rsp.skds)));
+
+	/* NOTE: if not sufficient random numbers, ignore waiting */
+	lll_csrand_isr_get(pdu_ctrl_tx->llctrl.enc_rsp.skds,
+			   sizeof(pdu_ctrl_tx->llctrl.enc_rsp.skds) +
+			   sizeof(pdu_ctrl_tx->llctrl.enc_rsp.ivs));
+
+	/* things from slave stored for session key calculation */
+	memcpy(&conn->llcp.encryption.skd[8],
+	       &pdu_ctrl_tx->llctrl.enc_rsp.skds[0], 8);
+	memcpy(&conn->lll.ccm_rx.iv[4],
+	       &pdu_ctrl_tx->llctrl.enc_rsp.ivs[0], 4);
+
+	ctrl_tx_enqueue(conn, tx);
+
+	return 0;
+}
+
+static int start_enc_rsp_send(struct ll_conn *conn,
+			      struct pdu_data *pdu_ctrl_tx)
+{
+	struct node_tx *tx = NULL;
+
+	if (!pdu_ctrl_tx) {
+		/* acquire tx mem */
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+
+		pdu_ctrl_tx = (void *)tx->pdu;
+	}
+
+	/* enable transmit encryption */
+	conn->lll.enc_tx = 1;
+
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_rsp);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_START_ENC_RSP;
+
+	if (tx) {
+		ctrl_tx_enqueue(conn, tx);
+	}
+
+	return 0;
+}
+
+static inline bool ctrl_is_unexpected(struct ll_conn *conn, uint8_t opcode)
+{
+	return (!conn->lll.role &&
+		((!conn->llcp_enc.refresh &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_REQ) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) ||
+		 (conn->llcp_enc.refresh &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_REQ) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)))) ||
+	       (conn->lll.role &&
+		((!conn->llcp_enc.refresh &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) ||
+		 (conn->llcp_enc.refresh &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
+		  (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND))));
+}
+
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static int unknown_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			    uint8_t type)
+{
+	struct node_tx *tx;
+	struct pdu_data *pdu;
+
+	/* acquire ctrl tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	pdu = (void *)tx->pdu;
+	pdu->ll_id = PDU_DATA_LLID_CTRL;
+	pdu->len = offsetof(struct pdu_data_llctrl, unknown_rsp) +
+			   sizeof(struct pdu_data_llctrl_unknown_rsp);
+	pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP;
+	pdu->llctrl.unknown_rsp.type = type;
+
+	ctrl_tx_enqueue(conn, tx);
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+
+static inline uint32_t feat_get(uint8_t *features)
+{
+	uint32_t feat;
+
+	feat = ~LL_FEAT_BIT_MASK_VALID | features[0] |
+	       (features[1] << 8) | (features[2] << 16);
+	feat &= LL_FEAT_BIT_MASK;
+
+	return feat;
+}
+
+/*
+ * Perform a logical and on octet0 and keep the remaining bits of the
+ * first input parameter
+ */
+static inline uint32_t feat_land_octet0(uint32_t feat_to_keep, uint32_t feat_octet0)
+{
+	uint32_t feat_result;
+
+	feat_result = feat_to_keep & feat_octet0;
+	feat_result &= 0xFF;
+	feat_result |= feat_to_keep & LL_FEAT_FILTER_OCTET0;
+
+	return feat_result;
+}
+
+static int feature_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			    struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_feature_req *req;
+	struct node_tx *tx;
+	struct pdu_data *pdu_tx;
+	uint32_t feat;
+
+	/* acquire tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	/* AND the feature set to get Feature USED */
+	req = &pdu_rx->llctrl.feature_req;
+	conn->llcp_feature.features_conn &= feat_get(&req->features[0]);
+	/*
+	 * Get all the features of peer, except octet 0.
+	 * Octet 0 is the actual features used on the link
+	 * See BTCore V5.2, Vol. 6, Part B, chapter 5.1.4
+	 */
+	conn->llcp_feature.features_peer =
+		feat_land_octet0(feat_get(&req->features[0]), LL_FEAT);
+
+	/* features exchanged */
+	conn->common.fex_valid = 1U;
+
+	/* Enqueue feature response */
+	pdu_tx = (void *)tx->pdu;
+	pdu_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_tx->len = offsetof(struct pdu_data_llctrl, feature_rsp) +
+		sizeof(struct pdu_data_llctrl_feature_rsp);
+	pdu_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_FEATURE_RSP;
+	(void)memset(&pdu_tx->llctrl.feature_rsp.features[0], 0x00,
+		     sizeof(pdu_tx->llctrl.feature_rsp.features));
+	/*
+	 * On feature response we send the local supported features.
+	 * See BTCore V5.2 VOl 6 Part B, chapter 5.1.4
+	 */
+	feat = feat_land_octet0(LL_FEAT, conn->llcp_feature.features_conn);
+	sys_put_le24(feat, pdu_tx->llctrl.feature_rsp.features);
+
+	ctrl_tx_sec_enqueue(conn, tx);
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+
+static void feature_rsp_recv(struct ll_conn *conn, struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_feature_rsp *rsp;
+
+	rsp = &pdu_rx->llctrl.feature_rsp;
+
+	/* AND the feature set to get Feature USED */
+	conn->llcp_feature.features_conn &= feat_get(&rsp->features[0]);
+	/*
+	 * Get all the features of peer, except octet 0.
+	 * Octet 0 is the actual features used on the link
+	 * See BTCore V5.2, Vol. 6, Part B, chapter 5.1.4
+	 */
+	conn->llcp_feature.features_peer =
+		feat_land_octet0(feat_get(&rsp->features[0]), LL_FEAT);
+
+	/* features exchanged */
+	conn->common.fex_valid = 1U;
+
+	/* Procedure complete */
+	conn->llcp_feature.ack = conn->llcp_feature.req;
+	conn->procedure_expire = 0U;
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static int pause_enc_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			      uint8_t req)
+{
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	if (req) {
+		/* acquire tx mem */
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+
+		/* key refresh */
+		conn->llcp_enc.refresh = 1U;
+	} else if (!conn->lll.role) {
+		/* acquire tx mem */
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+
+		/* disable transmit encryption */
+		conn->lll.enc_tx = 0;
+	} else {
+		/* disable transmit encryption */
+		conn->lll.enc_tx = 0;
+
+		goto pause_enc_rsp_send_exit;
+	}
+
+	/* pause data packet rx */
+	conn->llcp_enc.pause_rx = 1U;
+
+	/* disable receive encryption */
+	conn->lll.enc_rx = 0;
+
+	/* Enqueue pause enc rsp */
+	pdu_ctrl_tx = (void *)tx->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_rsp);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP;
+
+	ctrl_tx_enqueue(conn, tx);
+
+pause_enc_rsp_send_exit:
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static int version_ind_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			    struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_version_ind *v;
+	struct pdu_data *pdu_tx;
+	struct node_tx *tx;
+
+	if (!conn->llcp_version.tx) {
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+		conn->llcp_version.tx = 1U;
+
+		pdu_tx = (void *)tx->pdu;
+		pdu_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_tx->len =
+			offsetof(struct pdu_data_llctrl, version_ind) +
+			sizeof(struct pdu_data_llctrl_version_ind);
+		pdu_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_VERSION_IND;
+		v = &pdu_tx->llctrl.version_ind;
+		v->version_number = LL_VERSION_NUMBER;
+		v->company_id =	sys_cpu_to_le16(ll_settings_company_id());
+		v->sub_version_number =
+			sys_cpu_to_le16(ll_settings_subversion_number());
+
+		ctrl_tx_sec_enqueue(conn, tx);
+
+		/* Mark for buffer for release */
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+	} else if (!conn->llcp_version.rx) {
+		/* procedure request acked */
+		conn->llcp_version.ack = conn->llcp_version.req;
+
+		/* Procedure complete */
+		conn->procedure_expire = 0U;
+	} else {
+		/* Tx-ed and Rx-ed before, ignore this invalid Rx. */
+
+		/* Mark for buffer for release */
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return 0;
+	}
+
+	v = &pdu_rx->llctrl.version_ind;
+	conn->llcp_version.version_number = v->version_number;
+	conn->llcp_version.company_id = sys_le16_to_cpu(v->company_id);
+	conn->llcp_version.sub_version_number =
+		sys_le16_to_cpu(v->sub_version_number);
+	conn->llcp_version.rx = 1U;
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) || defined(CONFIG_BT_CTLR_PHY)
+static int reject_ext_ind_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			       uint8_t reject_opcode, uint8_t error_code)
+{
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	/* acquire tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	pdu_ctrl_tx = (void *)tx->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, reject_ext_ind) +
+		sizeof(struct pdu_data_llctrl_reject_ext_ind);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
+	pdu_ctrl_tx->llctrl.reject_ext_ind.reject_opcode = reject_opcode;
+	pdu_ctrl_tx->llctrl.reject_ext_ind.error_code = error_code;
+
+	ctrl_tx_enqueue(conn, tx);
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ  || PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static inline int reject_ind_conn_upd_recv(struct ll_conn *conn,
+					   struct node_rx_pdu *rx,
+					   struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+	struct node_rx_cu *cu;
+	struct lll_conn *lll;
+
+	/* Unsupported remote feature */
+	lll = &conn->lll;
+	rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+	if (!lll->role && (rej_ext_ind->error_code ==
+			   BT_HCI_ERR_UNSUPP_REMOTE_FEATURE)) {
+		LL_ASSERT(conn->llcp_cu.req == conn->llcp_cu.ack);
+
+		conn->llcp_conn_param.state = LLCP_CPR_STATE_UPD;
+
+		conn->llcp_cu.win_size = 1U;
+		conn->llcp_cu.win_offset_us = 0U;
+		conn->llcp_cu.interval = conn->llcp_conn_param.interval_max;
+		conn->llcp_cu.latency = conn->llcp_conn_param.latency;
+		conn->llcp_cu.timeout = conn->llcp_conn_param.timeout;
+		conn->llcp_cu.state = LLCP_CUI_STATE_USE;
+		conn->llcp_cu.cmd = conn->llcp_conn_param.cmd;
+		conn->llcp_cu.ack--;
+
+		return -EINVAL;
+	}
+	/* FIXME: handle unsupported LL parameters error */
+	else if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
+#if defined(CONFIG_BT_PERIPHERAL)
+		/* update to next ticks offset */
+		if (lll->role) {
+			conn->slave.ticks_to_offset =
+			    conn->llcp_conn_param.ticks_to_offset_next;
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+
+	if (conn->llcp_conn_param.state == LLCP_CPR_STATE_RSP_WAIT) {
+		LL_ASSERT(conn_upd_curr == conn);
+
+		/* reset mutex */
+		ull_conn_upd_curr_reset();
+
+		/* Procedure complete */
+		conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+		/* Stop procedure timeout */
+		conn->procedure_expire = 0U;
+	}
+
+	/* skip event generation if not cmd initiated */
+	if (!conn->llcp_conn_param.cmd) {
+		return -EINVAL;
+	}
+
+	/* generate conn update complete event with error code */
+	rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
+
+	/* prepare connection update complete structure */
+	cu = (void *)pdu_rx;
+	cu->status = rej_ext_ind->error_code;
+	cu->interval = lll->interval;
+	cu->latency = lll->latency;
+	cu->timeout = conn->supervision_reload *
+		      lll->interval * 125U / 1000;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+static inline int reject_ind_dle_recv(struct ll_conn *conn,
+				      struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_length_req *lr;
+
+	/* Procedure complete */
+	conn->llcp_length.ack = conn->llcp_length.req;
+	conn->procedure_expire = 0U;
+
+	/* prepare length rsp structure */
+	pdu_rx->len = offsetof(struct pdu_data_llctrl, length_rsp) +
+		      sizeof(struct pdu_data_llctrl_length_rsp);
+	pdu_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP;
+
+	lr = (void *)&pdu_rx->llctrl.length_req;
+	lr->max_rx_octets = sys_cpu_to_le16(conn->lll.max_rx_octets);
+	lr->max_tx_octets = sys_cpu_to_le16(conn->lll.max_tx_octets);
+#if !defined(CONFIG_BT_CTLR_PHY)
+	lr->max_rx_time =
+		sys_cpu_to_le16(PKT_US(conn->lll.max_rx_octets, PHY_1M));
+	lr->max_tx_time =
+		sys_cpu_to_le16(PKT_US(conn->lll.max_tx_octets, PHY_1M));
+#else /* CONFIG_BT_CTLR_PHY */
+	lr->max_rx_time = sys_cpu_to_le16(conn->lll.max_rx_time);
+	lr->max_tx_time = sys_cpu_to_le16(conn->lll.max_tx_time);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static inline int reject_ind_phy_upd_recv(struct ll_conn *conn,
+					  struct node_rx_pdu *rx,
+					  struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+	struct node_rx_pu *p;
+
+	/* Same Procedure or Different Procedure Collision */
+
+	/* If not same procedure, stop procedure timeout, else
+	 * continue timer until phy upd ind is received.
+	 */
+	rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+	if (rej_ext_ind->error_code != BT_HCI_ERR_LL_PROC_COLLISION) {
+		/* Procedure complete */
+		conn->llcp_phy.ack = conn->llcp_phy.req;
+
+		/* Reset packet timing restrictions */
+		conn->lll.phy_tx_time = conn->lll.phy_tx;
+		conn->llcp_phy.pause_tx = 0U;
+
+		/* Stop procedure timeout */
+		conn->procedure_expire = 0U;
+	}
+
+	/* skip event generation if not cmd initiated */
+	if (!conn->llcp_phy.cmd) {
+		return -EINVAL;
+	}
+
+	/* generate phy update complete event with error code */
+	rx->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
+
+	p = (void *)pdu_rx;
+	p->status = rej_ext_ind->error_code;
+	p->tx = conn->lll.phy_tx;
+	p->rx = conn->lll.phy_rx;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+static inline int reject_ind_enc_recv(struct ll_conn *conn)
+{
+	/* resume data packet rx and tx */
+	conn->llcp_enc.pause_rx = 0U;
+	conn->llcp_enc.pause_tx = 0U;
+
+	/* Procedure complete */
+	conn->llcp_ack = conn->llcp_req;
+	conn->procedure_expire = 0U;
+
+	return 0;
+}
+
+static inline int reject_ext_ind_enc_recv(struct ll_conn *conn,
+					  struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+
+	reject_ind_enc_recv(conn);
+
+	/* enqueue as if it were a reject ind */
+	rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+	pdu_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_REJECT_IND;
+	pdu_rx->llctrl.reject_ind.error_code = rej_ext_ind->error_code;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static inline void reject_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
+				   struct pdu_data *pdu_rx)
+{
+	int err = -EINVAL;
+
+
+	if (0) {
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	} else if ((conn->llcp_ack != conn->llcp_req) &&
+		   (conn->llcp_type == LLCP_ENCRYPTION)) {
+		err = reject_ind_enc_recv(conn);
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	} else if (conn->llcp_phy.ack != conn->llcp_phy.req) {
+		struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+		struct pdu_data_llctrl_reject_ind *rej_ind;
+
+		rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+		rej_ind = (void *)&pdu_rx->llctrl.reject_ind;
+		/* NOTE: Do not modify reject_opcode field which overlap with
+		 *       error_code field in reject ind PDU structure. Only copy
+		 *       error_code from reject ind to reject ext ind PDU
+		 *       structure.
+		 */
+		rej_ext_ind->error_code = rej_ind->error_code;
+		err = reject_ind_phy_upd_recv(conn, rx, pdu_rx);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	} else if (conn->llcp_conn_param.ack != conn->llcp_conn_param.req) {
+		struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+		struct pdu_data_llctrl_reject_ind *rej_ind;
+
+		rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+		rej_ind = (void *)&pdu_rx->llctrl.reject_ind;
+		/* NOTE: Do not modify reject_opcode field which overlap with
+		 *       error_code field in reject ind PDU structure. Only copy
+		 *       error_code from reject ind to reject ext ind PDU
+		 *       structure.
+		 */
+		rej_ext_ind->error_code = rej_ind->error_code;
+		err = reject_ind_conn_upd_recv(conn, rx, pdu_rx);
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	} else if (conn->llcp_length.ack != conn->llcp_length.req) {
+		err = reject_ind_dle_recv(conn, pdu_rx);
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+	}
+
+	if (err) {
+		/* Mark for buffer for release */
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+	}
+}
+
+static inline void reject_ext_ind_recv(struct ll_conn *conn,
+				       struct node_rx_pdu *rx,
+				       struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
+	int err = -EINVAL;
+
+	rej_ext_ind = (void *)&pdu_rx->llctrl.reject_ext_ind;
+
+	switch (rej_ext_ind->reject_opcode) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
+		if ((conn->llcp_ack != conn->llcp_req) &&
+		    (conn->llcp_type == LLCP_ENCRYPTION)) {
+			err = reject_ext_ind_enc_recv(conn, pdu_rx);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case PDU_DATA_LLCTRL_TYPE_PHY_REQ:
+		if (conn->llcp_phy.ack != conn->llcp_phy.req) {
+			err = reject_ind_phy_upd_recv(conn, rx, pdu_rx);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	case PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ:
+		if (conn->llcp_conn_param.ack != conn->llcp_conn_param.req) {
+			err = reject_ind_conn_upd_recv(conn, rx, pdu_rx);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
+		if (conn->llcp_length.ack != conn->llcp_length.req) {
+			err = reject_ind_dle_recv(conn, pdu_rx);
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+	default:
+		/* Ignore */
+		break;
+	}
+
+	if (err) {
+		/* Mark for buffer for release */
+		rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+	}
+}
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+#if !defined(CONFIG_BT_CTLR_PHY)
+static void length_resp_send(struct ll_conn *conn, struct node_tx *tx,
+			     uint16_t eff_rx_octets, uint16_t eff_tx_octets)
+#else /* CONFIG_BT_CTLR_PHY */
+static void length_resp_send(struct ll_conn *conn, struct node_tx *tx,
+			     uint16_t eff_rx_octets, uint16_t eff_rx_time,
+			     uint16_t eff_tx_octets, uint16_t eff_tx_time)
+#endif /* CONFIG_BT_CTLR_PHY */
+{
+	struct pdu_data *pdu_tx;
+
+	pdu_tx = (void *)tx->pdu;
+	pdu_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_tx->len = offsetof(struct pdu_data_llctrl, length_rsp) +
+		sizeof(struct pdu_data_llctrl_length_rsp);
+	pdu_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP;
+	pdu_tx->llctrl.length_rsp.max_rx_octets =
+		sys_cpu_to_le16(eff_rx_octets);
+	pdu_tx->llctrl.length_rsp.max_tx_octets =
+		sys_cpu_to_le16(eff_tx_octets);
+
+#if !defined(CONFIG_BT_CTLR_PHY)
+	pdu_tx->llctrl.length_rsp.max_rx_time =
+		sys_cpu_to_le16(PKT_US(eff_rx_octets, PHY_1M));
+	pdu_tx->llctrl.length_rsp.max_tx_time =
+		sys_cpu_to_le16(PKT_US(eff_tx_octets, PHY_1M));
+#else /* CONFIG_BT_CTLR_PHY */
+	pdu_tx->llctrl.length_rsp.max_rx_time = sys_cpu_to_le16(eff_rx_time);
+	pdu_tx->llctrl.length_rsp.max_tx_time = sys_cpu_to_le16(eff_tx_time);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	ctrl_tx_sec_enqueue(conn, tx);
+}
+
+static inline int length_req_rsp_recv(struct ll_conn *conn, memq_link_t *link,
+				      struct node_rx_pdu **rx,
+				      struct pdu_data *pdu_rx)
+{
+	struct node_tx *tx = NULL;
+	uint16_t eff_rx_octets;
+	uint16_t eff_tx_octets;
+#if defined(CONFIG_BT_CTLR_PHY)
+	uint16_t eff_rx_time;
+	uint16_t eff_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	/* Check for free ctrl tx PDU */
+	if (pdu_rx->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_LENGTH_REQ) {
+		tx = mem_acquire(&mem_conn_tx_ctrl.free);
+		if (!tx) {
+			return -ENOBUFS;
+		}
+	}
+
+	eff_rx_octets = conn->lll.max_rx_octets;
+	eff_tx_octets = conn->lll.max_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	eff_rx_time = conn->lll.max_rx_time;
+	eff_tx_time = conn->lll.max_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	if (/* Local idle, and Peer request then complete the Peer procedure
+	     * with response.
+	     */
+	    ((conn->llcp_length.req == conn->llcp_length.ack) && tx) ||
+	    /* or Local has active... */
+	    ((conn->llcp_length.req != conn->llcp_length.ack) &&
+	     /* with Local requested and Peer request then complete the
+	      * Peer procedure with response.
+	      */
+	     ((((conn->llcp_length.state == LLCP_LENGTH_STATE_REQ) ||
+		(conn->llcp_length.state == LLCP_LENGTH_STATE_REQ_ACK_WAIT)) &&
+	       tx) ||
+	      /* with Local waiting for response, and Peer response then
+	       * complete the Local procedure or Peer request then complete the
+	       * Peer procedure with response.
+	       */
+	      (conn->llcp_length.state == LLCP_LENGTH_STATE_RSP_WAIT)))) {
+		struct pdu_data_llctrl_length_req *lr;
+		uint16_t max_rx_octets;
+		uint16_t max_tx_octets;
+
+		lr = &pdu_rx->llctrl.length_req;
+
+		/* use the minimal of our default_tx_octets and
+		 * peer max_rx_octets
+		 */
+		max_rx_octets = sys_le16_to_cpu(lr->max_rx_octets);
+		if (max_rx_octets >= PDU_DC_PAYLOAD_SIZE_MIN) {
+			eff_tx_octets = MIN(max_rx_octets,
+					    conn->default_tx_octets);
+		}
+
+		/* use the minimal of our max supported and
+		 * peer max_tx_octets
+		 */
+		max_tx_octets = sys_le16_to_cpu(lr->max_tx_octets);
+		if (max_tx_octets >= PDU_DC_PAYLOAD_SIZE_MIN) {
+			eff_rx_octets = MIN(max_tx_octets,
+					    LL_LENGTH_OCTETS_RX_MAX);
+		}
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		uint16_t max_rx_time;
+		uint16_t max_tx_time;
+		uint16_t lr_rx_time, lr_tx_time;
+
+		dle_max_time_get(conn, &max_rx_time, &max_tx_time);
+
+		/* use the minimal of our default_tx_time and
+		 * peer max_rx_time
+		 */
+
+		lr_rx_time = sys_le16_to_cpu(lr->max_rx_time);
+		lr_tx_time = sys_le16_to_cpu(lr->max_tx_time);
+
+		if (lr_rx_time >= PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M)) {
+			eff_tx_time = MIN(lr_rx_time, max_tx_time);
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+			eff_tx_time = MAX(eff_tx_time,
+					  PKT_US(PDU_DC_PAYLOAD_SIZE_MIN,
+						 conn->lll.phy_tx));
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		}
+
+		/* use the minimal of our max supported and
+		 * peer max_tx_time
+		 */
+		if (lr_tx_time >= PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M)) {
+			eff_rx_time = MIN(lr_tx_time, max_rx_time);
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+			eff_rx_time = MAX(eff_rx_time,
+					  PKT_US(PDU_DC_PAYLOAD_SIZE_MIN,
+						 conn->lll.phy_rx));
+#endif /* !CONFIG_BT_CTLR_PHY_CODED */
+		}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		/* check if change in rx octets */
+		if (eff_rx_octets != conn->lll.max_rx_octets) {
+			/* FIXME: If we want to resize Rx Pool, decide to
+			 *        nack as required when implementing. Also,
+			 *        closing the current event may be needed.
+			 */
+
+			/* trigger or retain the ctrl procedure so as
+			 * to resize the rx buffers.
+			 */
+			conn->llcp_length.rx_octets = eff_rx_octets;
+			conn->llcp_length.tx_octets = eff_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+			conn->llcp_length.rx_time = eff_rx_time;
+			conn->llcp_length.tx_time = eff_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+			conn->llcp_length.ack = conn->llcp_length.req - 1;
+
+			if (tx) {
+				conn->llcp_length.state =
+					LLCP_LENGTH_STATE_RESIZE_RSP;
+			} else {
+				/* accept the effective tx */
+				conn->lll.max_tx_octets = eff_tx_octets;
+#if defined(CONFIG_BT_CTLR_PHY)
+				/* accept the effective tx time */
+				conn->lll.max_tx_time = eff_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+				conn->llcp_length.state =
+					LLCP_LENGTH_STATE_RESIZE;
+			}
+
+			link->mem = conn->llcp_rx;
+			(*rx)->hdr.link = link;
+			conn->llcp_rx = *rx;
+			*rx = NULL;
+		} else {
+			/* Procedure complete */
+			conn->llcp_length.ack = conn->llcp_length.req;
+			conn->procedure_expire = 0U;
+
+			/* No change in effective octets or time */
+			if (eff_tx_octets == conn->lll.max_tx_octets &&
+#if defined(CONFIG_BT_CTLR_PHY)
+			    eff_tx_time == conn->lll.max_tx_time &&
+			    eff_rx_time == conn->lll.max_rx_time &&
+#endif /* CONFIG_BT_CTLR_PHY */
+			    (1)) {
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+				goto send_length_resp;
+			}
+
+#if defined(CONFIG_BT_CTLR_PHY)
+			/* accept the effective rx time */
+			conn->lll.max_rx_time = eff_rx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+			if (tx) {
+				/* trigger or retain the ctrl procedure so as
+				 * to resize the rx buffers.
+				 */
+				conn->llcp_length.rx_octets = eff_rx_octets;
+				conn->llcp_length.tx_octets = eff_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+				conn->llcp_length.rx_time = eff_rx_time;
+				conn->llcp_length.tx_time = eff_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+				/* Wait for rsp ack before tx change  */
+				conn->llcp_length.ack =
+					(conn->llcp_length.req - 1);
+				conn->llcp_length.state =
+					LLCP_LENGTH_STATE_RSP_ACK_WAIT;
+			} else {
+				/* accept the effective tx */
+				conn->lll.max_tx_octets = eff_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+				/* accept the effective tx time */
+				conn->lll.max_tx_time = eff_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+			}
+
+			/* prepare event params */
+			lr->max_rx_octets = sys_cpu_to_le16(eff_rx_octets);
+			lr->max_tx_octets = sys_cpu_to_le16(eff_tx_octets);
+
+#if !defined(CONFIG_BT_CTLR_PHY)
+			lr->max_rx_time =
+				sys_cpu_to_le16(PKT_US(eff_rx_octets, PHY_1M));
+			lr->max_tx_time =
+				sys_cpu_to_le16(PKT_US(eff_tx_octets, PHY_1M));
+#else /* CONFIG_BT_CTLR_PHY */
+			lr->max_rx_time = sys_cpu_to_le16(eff_rx_time);
+			lr->max_tx_time = sys_cpu_to_le16(eff_tx_time);
+#endif /* CONFIG_BT_CTLR_PHY */
+		}
+	} else {
+		/* Drop response with no Local initiated request and duplicate
+		 * requests.
+		 */
+		if (pdu_rx->llctrl.opcode != PDU_DATA_LLCTRL_TYPE_LENGTH_RSP) {
+			mem_release(tx, &mem_conn_tx_ctrl.free);
+
+			/* Defer new request if previous in resize state */
+			if (conn->llcp_length.state ==
+			    LLCP_LENGTH_STATE_RESIZE) {
+				return -EBUSY;
+			}
+		}
+
+		return 0;
+	}
+
+send_length_resp:
+	if (tx) {
+		/* FIXME: if nack-ing is implemented then release tx instead
+		 *        of sending resp.
+		 */
+#if !defined(CONFIG_BT_CTLR_PHY)
+		length_resp_send(conn, tx, eff_rx_octets,
+				 eff_tx_octets);
+#else /* CONFIG_BT_CTLR_PHY */
+		length_resp_send(conn, tx, eff_rx_octets,
+				 eff_rx_time, eff_tx_octets,
+				 eff_tx_time);
+#endif /* CONFIG_BT_CTLR_PHY */
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+static int ping_resp_send(struct ll_conn *conn, struct node_rx_pdu *rx)
+{
+	struct node_tx *tx;
+	struct pdu_data *pdu_tx;
+
+	/* acquire tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	pdu_tx = (void *)tx->pdu;
+	pdu_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_tx->len = offsetof(struct pdu_data_llctrl, ping_rsp) +
+		      sizeof(struct pdu_data_llctrl_ping_rsp);
+	pdu_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_PING_RSP;
+
+	ctrl_tx_sec_enqueue(conn, tx);
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+static int phy_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
+			struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_phy_req *p;
+	struct pdu_data *pdu_ctrl_tx;
+	struct node_tx *tx;
+
+	/* acquire tx mem */
+	tx = mem_acquire(&mem_conn_tx_ctrl.free);
+	if (!tx) {
+		return -ENOBUFS;
+	}
+
+	/* Wait for peer master to complete the procedure */
+	conn->llcp_phy.state = LLCP_PHY_STATE_RSP_WAIT;
+	if (conn->llcp_phy.ack ==
+	    conn->llcp_phy.req) {
+		conn->llcp_phy.ack--;
+
+		conn->llcp_phy.cmd = 0U;
+
+		conn->llcp_phy.tx =
+			conn->phy_pref_tx;
+		conn->llcp_phy.rx =
+			conn->phy_pref_rx;
+
+		/* Start Procedure Timeout (TODO: this shall not
+		 * replace terminate procedure).
+		 */
+		conn->procedure_expire =
+			conn->procedure_reload;
+	}
+
+	p = &pdu_rx->llctrl.phy_req;
+
+	conn->llcp_phy.tx &= p->rx_phys;
+	conn->llcp_phy.rx &= p->tx_phys;
+
+	pdu_ctrl_tx = (void *)tx->pdu;
+	pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+	pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, phy_rsp) +
+			   sizeof(struct pdu_data_llctrl_phy_rsp);
+	pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_PHY_RSP;
+	pdu_ctrl_tx->llctrl.phy_rsp.tx_phys = conn->phy_pref_tx;
+	pdu_ctrl_tx->llctrl.phy_rsp.rx_phys = conn->phy_pref_rx;
+
+	ctrl_tx_enqueue(conn, tx);
+
+	/* Mark for buffer for release */
+	rx->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+	return 0;
+}
+
+static inline uint8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link,
+				    struct node_rx_pdu **rx,
+				    struct pdu_data *pdu_rx)
+{
+	struct pdu_data_llctrl_phy_upd_ind *ind = &pdu_rx->llctrl.phy_upd_ind;
+	uint16_t instant;
+
+	/* Both tx and rx PHY unchanged */
+	if (!((ind->m_to_s_phy | ind->s_to_m_phy) & 0x07)) {
+		struct node_rx_pu *p;
+
+		/* Not in PHY Update Procedure or PDU in wrong state */
+		if ((conn->llcp_phy.ack == conn->llcp_phy.req) ||
+		    (conn->llcp_phy.state != LLCP_PHY_STATE_RSP_WAIT)) {
+			/* Mark for buffer for release */
+			(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+			return 0;
+		}
+
+		/* Procedure complete */
+		conn->llcp_phy.ack = conn->llcp_phy.req;
+		conn->llcp_phy.pause_tx = 0U;
+		conn->procedure_expire = 0U;
+
+		/* Reset packet timing restrictions */
+		conn->lll.phy_tx_time = conn->lll.phy_tx;
+
+		/* Ignore event generation if not local cmd initiated */
+		if (!conn->llcp_phy.cmd) {
+			/* Mark for buffer for release */
+			(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+			return 0;
+		}
+
+		/* generate phy update complete event */
+		(*rx)->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
+
+		p = (void *)pdu_rx;
+		p->status = 0U;
+		p->tx = conn->lll.phy_tx;
+		p->rx = conn->lll.phy_rx;
+
+		return 0;
+	}
+
+	/* instant passed */
+	instant = sys_le16_to_cpu(ind->instant);
+	if (((instant - conn->lll.event_counter) & 0xffff) > 0x7fff) {
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return BT_HCI_ERR_INSTANT_PASSED;
+	}
+
+	/* different transaction collision */
+	if (((conn->llcp_req - conn->llcp_ack) & 0x03) == 0x02) {
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return BT_HCI_ERR_DIFF_TRANS_COLLISION;
+	}
+
+	if ((conn->llcp_phy.ack != conn->llcp_phy.req) &&
+	    (conn->llcp_phy.state == LLCP_PHY_STATE_RSP_WAIT)) {
+		/* Procedure complete, just wait for instant */
+		conn->llcp_phy.ack = conn->llcp_phy.req;
+		conn->llcp_phy.pause_tx = 0U;
+		conn->procedure_expire = 0U;
+
+		conn->llcp.phy_upd_ind.cmd = conn->llcp_phy.cmd;
+	}
+
+	conn->llcp.phy_upd_ind.tx = ind->s_to_m_phy;
+	conn->llcp.phy_upd_ind.rx = ind->m_to_s_phy;
+	conn->llcp.phy_upd_ind.instant = instant;
+	conn->llcp.phy_upd_ind.initiate = 0U;
+
+	link->mem = conn->llcp_rx;
+	(*rx)->hdr.link = link;
+	conn->llcp_rx = *rx;
+	*rx = NULL;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	/* reserve rx node for DLE event generation */
+	struct node_rx_pdu *rx_dle = ll_pdu_rx_alloc();
+
+	LL_ASSERT(rx_dle);
+	rx_dle->hdr.link->mem = conn->llcp_rx;
+	conn->llcp_rx = rx_dle;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+	conn->llcp_type = LLCP_PHY_UPD;
+	conn->llcp_ack -= 2U;
+
+	if (conn->llcp.phy_upd_ind.tx) {
+		conn->lll.phy_tx_time = conn->llcp.phy_upd_ind.tx;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+static inline void ctrl_tx_pre_ack(struct ll_conn *conn,
+				   struct pdu_data *pdu_tx)
+{
+	switch (pdu_tx->llctrl.opcode) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP:
+		if (!conn->lll.role) {
+			break;
+		}
+		__fallthrough;
+
+	case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
+	case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ:
+		/* pause data packet tx */
+		conn->llcp_enc.pause_tx = 1U;
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case PDU_DATA_LLCTRL_TYPE_PHY_REQ:
+	case PDU_DATA_LLCTRL_TYPE_PHY_RSP:
+		/* pause data packet tx */
+		conn->llcp_phy.pause_tx = 1U;
+		break;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	default:
+		/* Do nothing for other ctrl packet ack */
+		break;
+	}
+}
+
+static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
+			       struct pdu_data *pdu_tx)
+{
+	switch (pdu_tx->llctrl.opcode) {
+	case PDU_DATA_LLCTRL_TYPE_TERMINATE_IND:
+	{
+		uint8_t reason = (pdu_tx->llctrl.terminate_ind.error_code ==
+			       BT_HCI_ERR_REMOTE_USER_TERM_CONN) ?
+			      BT_HCI_ERR_LOCALHOST_TERM_CONN :
+			      pdu_tx->llctrl.terminate_ind.error_code;
+
+		conn_cleanup(conn, reason);
+	}
+	break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
+		/* things from master stored for session key calculation */
+		memcpy(&conn->llcp.encryption.skd[0],
+		       &pdu_tx->llctrl.enc_req.skdm[0], 8);
+		memcpy(&conn->lll.ccm_rx.iv[0],
+		       &pdu_tx->llctrl.enc_req.ivm[0], 4);
+
+		/* pause data packet tx */
+		conn->llcp_enc.pause_tx = 1U;
+
+		/* Start Procedure Timeout (this will not replace terminate
+		 * procedure which always gets place before any packets
+		 * going out, hence safe by design).
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+
+		/* Reset enc req queued state */
+		conn->llcp_enc.ack = conn->llcp_enc.req;
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
+		/* pause data packet tx */
+		conn->llcp_enc.pause_tx = 1U;
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
+		/* Nothing to do.
+		 * Remember that we may have received encrypted START_ENC_RSP
+		 * alongwith this tx ack at this point in time.
+		 */
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ:
+		/* pause data packet tx */
+		conn->llcp_enc.pause_tx = 1U;
+
+		/* key refresh */
+		conn->llcp_enc.refresh = 1U;
+
+		/* Start Procedure Timeout (this will not replace terminate
+		 * procedure which always gets place before any packets
+		 * going out, hence safe by design).
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+
+		/* Reset enc req queued state */
+		conn->llcp_enc.ack = conn->llcp_enc.req;
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP:
+		if (!conn->lll.role) {
+			/* reused tx-ed PDU and send enc req */
+			enc_req_reused_send(conn, tx);
+		} else {
+			/* pause data packet tx */
+			conn->llcp_enc.pause_tx = 1U;
+		}
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
+		if (pdu_tx->llctrl.reject_ext_ind.reject_opcode !=
+		    PDU_DATA_LLCTRL_TYPE_ENC_REQ) {
+			break;
+		}
+		__fallthrough;
+
+	case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
+		/* resume data packet rx and tx */
+		conn->llcp_enc.pause_rx = 0U;
+		conn->llcp_enc.pause_tx = 0U;
+
+		/* Procedure complete */
+		conn->procedure_expire = 0U;
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
+		/* wait for response */
+		conn->llcp_length.state = LLCP_LENGTH_STATE_RSP_WAIT;
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_RSP:
+		if (conn->llcp_length.req != conn->llcp_length.ack) {
+			switch (conn->llcp_length.state) {
+			case LLCP_LENGTH_STATE_RSP_ACK_WAIT:
+			case LLCP_LENGTH_STATE_RESIZE_RSP:
+			case LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT:
+				/* accept the effective tx */
+				conn->lll.max_tx_octets =
+					conn->llcp_length.tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+				/* accept the effective tx time */
+				conn->lll.max_tx_time =
+					conn->llcp_length.tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+				if (conn->llcp_length.state ==
+				    LLCP_LENGTH_STATE_RESIZE_RSP) {
+					conn->llcp_length.state =
+						LLCP_LENGTH_STATE_RESIZE;
+
+					break;
+				}
+
+				/* check cache */
+				if (!conn->llcp_length.cache.tx_octets) {
+					/* Procedure complete */
+					conn->llcp_length.ack =
+						conn->llcp_length.req;
+					conn->procedure_expire = 0U;
+
+					break;
+				}
+
+				/* Initiate cached procedure */
+				conn->llcp_length.tx_octets =
+					conn->llcp_length.cache.tx_octets;
+				conn->llcp_length.cache.tx_octets = 0;
+#if defined(CONFIG_BT_CTLR_PHY)
+				conn->llcp_length.tx_time =
+					conn->llcp_length.cache.tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+				conn->llcp_length.state = LLCP_LENGTH_STATE_REQ;
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case PDU_DATA_LLCTRL_TYPE_PHY_REQ:
+		conn->llcp_phy.state = LLCP_PHY_STATE_RSP_WAIT;
+		__fallthrough;
+
+	case PDU_DATA_LLCTRL_TYPE_PHY_RSP:
+		if (conn->lll.role) {
+			/* select the probable PHY with longest Tx time, which
+			 * will be restricted to fit current
+			 * connEffectiveMaxTxTime.
+			 */
+			uint8_t phy_tx_time[8] = {BIT(0), BIT(0), BIT(1), BIT(0),
+					       BIT(2), BIT(2), BIT(2), BIT(2)};
+			struct lll_conn *lll = &conn->lll;
+			uint8_t phys;
+
+			phys = conn->llcp_phy.tx | lll->phy_tx;
+			lll->phy_tx_time = phy_tx_time[phys];
+		}
+
+		/* resume data packet tx */
+		conn->llcp_phy.pause_tx = 0U;
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND:
+		conn->lll.phy_tx_time = conn->llcp.phy_upd_ind.tx;
+		/* resume data packet tx */
+		conn->llcp_phy.pause_tx = 0U;
+		break;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	default:
+		/* Do nothing for other ctrl packet ack */
+		break;
+	}
+}
+
+static inline bool pdu_len_cmp(uint8_t opcode, uint8_t len)
+{
+	const uint8_t ctrl_len_lut[] = {
+		(offsetof(struct pdu_data_llctrl, conn_update_ind) +
+		 sizeof(struct pdu_data_llctrl_conn_update_ind)),
+		(offsetof(struct pdu_data_llctrl, chan_map_ind) +
+		 sizeof(struct pdu_data_llctrl_chan_map_ind)),
+		(offsetof(struct pdu_data_llctrl, terminate_ind) +
+		 sizeof(struct pdu_data_llctrl_terminate_ind)),
+		(offsetof(struct pdu_data_llctrl, enc_req) +
+		 sizeof(struct pdu_data_llctrl_enc_req)),
+		(offsetof(struct pdu_data_llctrl, enc_rsp) +
+		 sizeof(struct pdu_data_llctrl_enc_rsp)),
+		(offsetof(struct pdu_data_llctrl, start_enc_req) +
+		 sizeof(struct pdu_data_llctrl_start_enc_req)),
+		(offsetof(struct pdu_data_llctrl, start_enc_rsp) +
+		 sizeof(struct pdu_data_llctrl_start_enc_rsp)),
+		(offsetof(struct pdu_data_llctrl, unknown_rsp) +
+		 sizeof(struct pdu_data_llctrl_unknown_rsp)),
+		(offsetof(struct pdu_data_llctrl, feature_req) +
+		 sizeof(struct pdu_data_llctrl_feature_req)),
+		(offsetof(struct pdu_data_llctrl, feature_rsp) +
+		 sizeof(struct pdu_data_llctrl_feature_rsp)),
+		(offsetof(struct pdu_data_llctrl, pause_enc_req) +
+		 sizeof(struct pdu_data_llctrl_pause_enc_req)),
+		(offsetof(struct pdu_data_llctrl, pause_enc_rsp) +
+		 sizeof(struct pdu_data_llctrl_pause_enc_rsp)),
+		(offsetof(struct pdu_data_llctrl, version_ind) +
+		 sizeof(struct pdu_data_llctrl_version_ind)),
+		(offsetof(struct pdu_data_llctrl, reject_ind) +
+		 sizeof(struct pdu_data_llctrl_reject_ind)),
+		(offsetof(struct pdu_data_llctrl, slave_feature_req) +
+		 sizeof(struct pdu_data_llctrl_slave_feature_req)),
+		(offsetof(struct pdu_data_llctrl, conn_param_req) +
+		 sizeof(struct pdu_data_llctrl_conn_param_req)),
+		(offsetof(struct pdu_data_llctrl, conn_param_rsp) +
+		 sizeof(struct pdu_data_llctrl_conn_param_rsp)),
+		(offsetof(struct pdu_data_llctrl, reject_ext_ind) +
+		 sizeof(struct pdu_data_llctrl_reject_ext_ind)),
+		(offsetof(struct pdu_data_llctrl, ping_req) +
+		 sizeof(struct pdu_data_llctrl_ping_req)),
+		(offsetof(struct pdu_data_llctrl, ping_rsp) +
+		 sizeof(struct pdu_data_llctrl_ping_rsp)),
+		(offsetof(struct pdu_data_llctrl, length_req) +
+		 sizeof(struct pdu_data_llctrl_length_req)),
+		(offsetof(struct pdu_data_llctrl, length_rsp) +
+		 sizeof(struct pdu_data_llctrl_length_rsp)),
+		(offsetof(struct pdu_data_llctrl, phy_req) +
+		 sizeof(struct pdu_data_llctrl_phy_req)),
+		(offsetof(struct pdu_data_llctrl, phy_rsp) +
+		 sizeof(struct pdu_data_llctrl_phy_rsp)),
+		(offsetof(struct pdu_data_llctrl, phy_upd_ind) +
+		 sizeof(struct pdu_data_llctrl_phy_upd_ind)),
+		(offsetof(struct pdu_data_llctrl, min_used_chans_ind) +
+		 sizeof(struct pdu_data_llctrl_min_used_chans_ind)),
+	};
+
+	return ctrl_len_lut[opcode] == len;
+}
+
+static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
+			  struct pdu_data *pdu_rx, struct ll_conn *conn)
+{
+	int nack = 0;
+	uint8_t opcode;
+
+	opcode = pdu_rx->llctrl.opcode;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	/* FIXME: do check in individual case to reduce CPU time */
+	if (conn->llcp_enc.pause_rx && ctrl_is_unexpected(conn, opcode)) {
+		conn->llcp_terminate.reason_peer =
+			BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		return 0;
+	}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	switch (opcode) {
+	case PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND:
+	{
+		uint8_t err;
+
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		err = conn_upd_recv(conn, link, rx, pdu_rx);
+		if (err) {
+			conn->llcp_terminate.reason_peer = err;
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		} else {
+			/* conn param req procedure, if any, is complete */
+			conn->procedure_expire = 0U;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+		}
+	}
+	break;
+
+	case PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND:
+	{
+		uint8_t err;
+
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		err = chan_map_upd_recv(conn, *rx, pdu_rx);
+		if (err) {
+			conn->llcp_terminate.reason_peer = err;
+		}
+	}
+	break;
+
+	case PDU_DATA_LLCTRL_TYPE_TERMINATE_IND:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_TERMINATE_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		terminate_ind_recv(conn, *rx, pdu_rx);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_ENC_REQ, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+#if defined(CONFIG_BT_CTLR_FAST_ENC)
+		/* TODO: BT Spec. text: may finalize the sending of additional
+		 * data channel PDUs queued in the controller.
+		 */
+		nack = enc_rsp_send(conn);
+		if (nack) {
+			break;
+		}
+
+		/* Start Enc Req to be scheduled by LL api */
+		conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
+#else /* CONFIG_BT_CTLR_FAST_ENC */
+		/* back up rand and ediv for deferred generation of Enc Req */
+		memcpy(&conn->llcp_enc.rand[0],
+		       &pdu_rx->llctrl.enc_req.rand[0],
+		       sizeof(conn->llcp_enc.rand));
+		conn->llcp_enc.ediv[0] = pdu_rx->llctrl.enc_req.ediv[0];
+		conn->llcp_enc.ediv[1] = pdu_rx->llctrl.enc_req.ediv[1];
+
+		/* Enc rsp to be scheduled in master prepare */
+		conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+#endif /* CONFIG_BT_CTLR_FAST_ENC */
+
+		/* Enc Setup state machine active */
+		conn->llcp_type = LLCP_ENCRYPTION;
+		conn->llcp_ack -= 2U;
+
+		/* things from master stored for session key calculation */
+		memcpy(&conn->llcp.encryption.skd[0],
+		       &pdu_rx->llctrl.enc_req.skdm[0], 8);
+		memcpy(&conn->lll.ccm_rx.iv[0],
+		       &pdu_rx->llctrl.enc_req.ivm[0], 4);
+
+		/* pause rx data packets */
+		conn->llcp_enc.pause_rx = 1U;
+
+		/* Start Procedure Timeout (TODO: this shall not replace
+		 * terminate procedure).
+		 */
+		conn->procedure_expire = conn->procedure_reload;
+
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
+		if (conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_ENC_RSP, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		/* things sent by slave stored for session key calculation */
+		memcpy(&conn->llcp.encryption.skd[8],
+		       &pdu_rx->llctrl.enc_rsp.skds[0], 8);
+		memcpy(&conn->lll.ccm_rx.iv[4],
+		       &pdu_rx->llctrl.enc_rsp.ivs[0], 4);
+
+		/* pause rx data packets */
+		conn->llcp_enc.pause_rx = 1U;
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
+		if (conn->lll.role || (conn->llcp_req == conn->llcp_ack) ||
+		    (conn->llcp_type != LLCP_ENCRYPTION) ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		/* start enc rsp to be scheduled in master prepare */
+		conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_START_ENC_RSP:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_RSP,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		if (conn->lll.role) {
+#if !defined(CONFIG_BT_CTLR_FAST_ENC)
+			if ((conn->llcp_req != conn->llcp_ack) &&
+			    (conn->llcp_type != LLCP_ENCRYPTION)) {
+				goto ull_conn_rx_unknown_rsp_send;
+			}
+
+			/* start enc rsp to be scheduled in slave  prepare */
+			conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
+			if (conn->llcp_req == conn->llcp_ack) {
+				conn->llcp_type = LLCP_ENCRYPTION;
+				conn->llcp_ack -= 2U;
+			}
+
+#else /* CONFIG_BT_CTLR_FAST_ENC */
+			nack = start_enc_rsp_send(conn, NULL);
+			if (nack) {
+				break;
+			}
+
+			/* resume data packet rx and tx */
+			conn->llcp_enc.pause_rx = 0U;
+			conn->llcp_enc.pause_tx = 0U;
+#endif /* CONFIG_BT_CTLR_FAST_ENC */
+
+		} else {
+			/* resume data packet rx and tx */
+			conn->llcp_enc.pause_rx = 0U;
+			conn->llcp_enc.pause_tx = 0U;
+		}
+
+		/* enqueue the start enc resp (encryption change/refresh) */
+		if (conn->llcp_enc.refresh) {
+			conn->llcp_enc.refresh = 0U;
+
+			/* key refresh event */
+			(*rx)->hdr.type = NODE_RX_TYPE_ENC_REFRESH;
+		}
+
+		/* Procedure complete */
+		conn->procedure_expire = 0U;
+
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	case PDU_DATA_LLCTRL_TYPE_FEATURE_REQ:
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_FEATURE_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = feature_rsp_send(conn, *rx, pdu_rx);
+		break;
+
+#if defined(CONFIG_BT_CTLR_SLAVE_FEAT_REQ)
+	case PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ:
+		if (conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = feature_rsp_send(conn, *rx, pdu_rx);
+		break;
+#endif /* CONFIG_BT_CTLR_SLAVE_FEAT_REQ */
+
+	case PDU_DATA_LLCTRL_TYPE_FEATURE_RSP:
+		if ((!IS_ENABLED(CONFIG_BT_CTLR_SLAVE_FEAT_REQ) &&
+		     conn->lll.role) ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_FEATURE_RSP,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		feature_rsp_recv(conn, pdu_rx);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ:
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = pause_enc_rsp_send(conn, *rx, 1);
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = pause_enc_rsp_send(conn, *rx, 0);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	case PDU_DATA_LLCTRL_TYPE_VERSION_IND:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_VERSION_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = version_ind_send(conn, *rx, pdu_rx);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_REJECT_IND, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		reject_ind_recv(conn, *rx, pdu_rx);
+		break;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	case PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+
+		/* check CUI/CPR mutex for other connections having CPR in
+		 * progress.
+		 */
+		if (conn_upd_curr && (conn_upd_curr != conn)) {
+			/* Unsupported LL Parameter Value */
+			nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+					BT_HCI_ERR_UNSUPP_LL_PARAM_VAL);
+			break;
+		}
+
+		if (!conn->lll.role) {
+			if ((conn->llcp_conn_param.req !=
+					conn->llcp_conn_param.ack) &&
+			    ((conn->llcp_conn_param.state ==
+			      LLCP_CPR_STATE_REQ) ||
+			     (conn->llcp_conn_param.state ==
+			      LLCP_CPR_STATE_RSP_WAIT) ||
+			     (conn->llcp_conn_param.state ==
+			      LLCP_CPR_STATE_UPD))) {
+				/* Same procedure collision  */
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+					BT_HCI_ERR_LL_PROC_COLLISION);
+#if defined(CONFIG_BT_CTLR_PHY)
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			} else if (((((conn->llcp_req - conn->llcp_ack) &
+				      0x03) == 0x02) &&
+				    (conn->llcp_type != LLCP_ENCRYPTION)) ||
+				   (conn->llcp_phy.req != conn->llcp_phy.ack)) {
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+			} else if ((((conn->llcp_req - conn->llcp_ack) &
+				     0x03) == 0x02) &&
+				   (conn->llcp_phy.req != conn->llcp_phy.ack)) {
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+#else /* !CONFIG_BT_CTLR_PHY */
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			} else if ((((conn->llcp_req - conn->llcp_ack) &
+				     0x03) == 0x02) &&
+				   (conn->llcp_type != LLCP_ENCRYPTION)) {
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+			} else if (((conn->llcp_req - conn->llcp_ack) &
+				      0x03) == 0x02) {
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+#endif /* !CONFIG_BT_CTLR_PHY */
+				/* Different procedure collision */
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+					BT_HCI_ERR_DIFF_TRANS_COLLISION);
+			} else {
+				struct pdu_data_llctrl_conn_param_req *cpr = (void *)
+					&pdu_rx->llctrl.conn_param_req;
+				struct lll_conn *lll = &conn->lll;
+
+				/* Extract parameters */
+				uint16_t interval_min =
+					sys_le16_to_cpu(cpr->interval_min);
+				uint16_t interval_max =
+					sys_le16_to_cpu(cpr->interval_max);
+				uint16_t latency =
+					sys_le16_to_cpu(cpr->latency);
+				uint16_t timeout =
+					sys_le16_to_cpu(cpr->timeout);
+				uint16_t preferred_periodicity =
+					cpr->preferred_periodicity;
+
+				/* Invalid parameters */
+				if ((interval_min < 6) ||
+				    (interval_max > 3200) ||
+				    (interval_min > interval_max) ||
+				    (latency > 499) ||
+				    (timeout < 10) ||
+				    (timeout > 3200) ||
+				    ((timeout * 4U) <=
+				     ((latency + 1) * interval_max)) ||
+				    (preferred_periodicity > interval_max)) {
+					nack = reject_ext_ind_send(conn, *rx,
+						PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+						BT_HCI_ERR_INVALID_LL_PARAM);
+					break;
+				}
+
+				/* save parameters to be used to select offset
+				 */
+				conn->llcp_conn_param.interval_min =
+					interval_min;
+				conn->llcp_conn_param.interval_max =
+					interval_max;
+				conn->llcp_conn_param.latency =	latency;
+				conn->llcp_conn_param.timeout =	timeout;
+				conn->llcp_conn_param.preferred_periodicity =
+					preferred_periodicity;
+				conn->llcp_conn_param.reference_conn_event_count =
+					sys_le16_to_cpu(cpr->reference_conn_event_count);
+				conn->llcp_conn_param.offset0 =
+					sys_le16_to_cpu(cpr->offset0);
+				conn->llcp_conn_param.offset1 =
+					sys_le16_to_cpu(cpr->offset1);
+				conn->llcp_conn_param.offset2 =
+					sys_le16_to_cpu(cpr->offset2);
+				conn->llcp_conn_param.offset3 =
+					sys_le16_to_cpu(cpr->offset3);
+				conn->llcp_conn_param.offset4 =
+					sys_le16_to_cpu(cpr->offset4);
+				conn->llcp_conn_param.offset5 =
+					sys_le16_to_cpu(cpr->offset5);
+
+				/* enqueue the conn param req, if parameters
+				 * changed, else respond.
+				 */
+				if ((conn->llcp_conn_param.interval_max !=
+				     lll->interval) ||
+				    (conn->llcp_conn_param.latency !=
+				     lll->latency) ||
+				    (RADIO_CONN_EVENTS(conn->llcp_conn_param.timeout *
+						       10000U,
+						       lll->interval *
+						       1250) !=
+				     conn->supervision_reload)) {
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+					/* postpone CP request event if under
+					 * encryption setup
+					 */
+					if (conn->llcp_enc.pause_tx) {
+						conn->llcp_conn_param.state =
+							LLCP_CPR_STATE_APP_REQ;
+
+						/* Mark for buffer for release */
+						(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+					} else
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+					{
+						conn->llcp_conn_param.state =
+							LLCP_CPR_STATE_APP_WAIT;
+					}
+				} else {
+					conn->llcp_conn_param.status = 0U;
+					conn->llcp_conn_param.cmd = 0U;
+					conn->llcp_conn_param.state =
+						LLCP_CPR_STATE_RSP;
+
+					/* Mark for buffer for release */
+					(*rx)->hdr.type =
+						NODE_RX_TYPE_DC_PDU_RELEASE;
+				}
+
+				conn->llcp_conn_param.ack--;
+
+				/* set mutex */
+				if (!conn_upd_curr) {
+					conn_upd_curr = conn;
+				}
+			}
+		} else if ((conn->llcp_conn_param.req ==
+			    conn->llcp_conn_param.ack) ||
+			   (conn->llcp_conn_param.state ==
+			    LLCP_CPR_STATE_REQ) ||
+			   (conn->llcp_conn_param.state ==
+			    LLCP_CPR_STATE_RSP_WAIT)) {
+			struct pdu_data_llctrl_conn_param_req *cpr = (void *)
+				&pdu_rx->llctrl.conn_param_req;
+			struct lll_conn *lll = &conn->lll;
+
+			/* Extract parameters */
+			uint16_t interval_min = sys_le16_to_cpu(cpr->interval_min);
+			uint16_t interval_max = sys_le16_to_cpu(cpr->interval_max);
+			uint16_t latency = sys_le16_to_cpu(cpr->latency);
+			uint16_t timeout = sys_le16_to_cpu(cpr->timeout);
+			uint16_t preferred_periodicity =
+				cpr->preferred_periodicity;
+
+			/* Invalid parameters */
+			if ((interval_min < 6) ||
+			    (interval_max > 3200) ||
+			    (interval_min > interval_max) ||
+			    (latency > 499) ||
+			    (timeout < 10) || (timeout > 3200) ||
+			    ((timeout * 4U) <=
+			     ((latency + 1) * interval_max)) ||
+			    (preferred_periodicity > interval_max)) {
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
+					BT_HCI_ERR_INVALID_LL_PARAM);
+				break;
+			}
+
+			/* resp to be generated by app, for now save
+			 * parameters
+			 */
+			conn->llcp_conn_param.interval_min = interval_min;
+			conn->llcp_conn_param.interval_max = interval_max;
+			conn->llcp_conn_param.latency =	latency;
+			conn->llcp_conn_param.timeout =	timeout;
+			conn->llcp_conn_param.preferred_periodicity =
+				preferred_periodicity;
+			conn->llcp_conn_param.reference_conn_event_count =
+				sys_le16_to_cpu(cpr->reference_conn_event_count);
+			conn->llcp_conn_param.offset0 =
+				sys_le16_to_cpu(cpr->offset0);
+			conn->llcp_conn_param.offset1 =
+				sys_le16_to_cpu(cpr->offset1);
+			conn->llcp_conn_param.offset2 =
+				sys_le16_to_cpu(cpr->offset2);
+			conn->llcp_conn_param.offset3 =
+				sys_le16_to_cpu(cpr->offset3);
+			conn->llcp_conn_param.offset4 =
+				sys_le16_to_cpu(cpr->offset4);
+			conn->llcp_conn_param.offset5 =
+				sys_le16_to_cpu(cpr->offset5);
+
+			/* enqueue the conn param req, if parameters changed,
+			 * else respond
+			 */
+			if ((conn->llcp_conn_param.interval_max !=
+			     lll->interval) ||
+			    (conn->llcp_conn_param.latency != lll->latency) ||
+			    (RADIO_CONN_EVENTS(conn->llcp_conn_param.timeout *
+					       10000U,
+					       lll->interval *
+					       1250) !=
+			     conn->supervision_reload)) {
+				conn->llcp_conn_param.state =
+					LLCP_CPR_STATE_APP_WAIT;
+			} else {
+				conn->llcp_conn_param.status = 0U;
+				conn->llcp_conn_param.cmd = 0U;
+				conn->llcp_conn_param.state =
+					LLCP_CPR_STATE_RSP;
+
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+			}
+
+			conn->llcp_conn_param.ack--;
+
+			/* set mutex */
+			if (!conn_upd_curr) {
+				conn_upd_curr = conn;
+			}
+		} else {
+			LL_ASSERT(0);
+		}
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP:
+		if (conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		if (!conn->lll.role &&
+		    (conn->llcp_conn_param.req !=
+		     conn->llcp_conn_param.ack) &&
+		    (conn->llcp_conn_param.state ==
+		     LLCP_CPR_STATE_RSP_WAIT)) {
+			struct pdu_data_llctrl_conn_param_req *cpr = (void *)
+				&pdu_rx->llctrl.conn_param_req;
+
+			/* Extract parameters */
+			uint16_t interval_min = sys_le16_to_cpu(cpr->interval_min);
+			uint16_t interval_max = sys_le16_to_cpu(cpr->interval_max);
+			uint16_t latency = sys_le16_to_cpu(cpr->latency);
+			uint16_t timeout = sys_le16_to_cpu(cpr->timeout);
+			uint16_t preferred_periodicity =
+				cpr->preferred_periodicity;
+
+			/* Invalid parameters */
+			if ((interval_min < 6) ||
+			    (interval_max > 3200) ||
+			    (interval_min > interval_max) ||
+			    (latency > 499) ||
+			    (timeout < 10) || (timeout > 3200) ||
+			    ((timeout * 4U) <=
+			     ((latency + 1) * interval_max)) ||
+			    (preferred_periodicity > interval_max)) {
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP,
+					BT_HCI_ERR_INVALID_LL_PARAM);
+				break;
+			}
+
+			/* Stop procedure timeout */
+			conn->procedure_expire = 0U;
+
+			/* save parameters to be used to select offset
+			 */
+			conn->llcp_conn_param.interval_min = interval_min;
+			conn->llcp_conn_param.interval_max = interval_max;
+			conn->llcp_conn_param.latency =	latency;
+			conn->llcp_conn_param.timeout =	timeout;
+			conn->llcp_conn_param.preferred_periodicity =
+				preferred_periodicity;
+			conn->llcp_conn_param.reference_conn_event_count =
+				sys_le16_to_cpu(cpr->reference_conn_event_count);
+			conn->llcp_conn_param.offset0 =
+				sys_le16_to_cpu(cpr->offset0);
+			conn->llcp_conn_param.offset1 =
+				sys_le16_to_cpu(cpr->offset1);
+			conn->llcp_conn_param.offset2 =
+				sys_le16_to_cpu(cpr->offset2);
+			conn->llcp_conn_param.offset3 =
+				sys_le16_to_cpu(cpr->offset3);
+			conn->llcp_conn_param.offset4 =
+				sys_le16_to_cpu(cpr->offset4);
+			conn->llcp_conn_param.offset5 =
+				sys_le16_to_cpu(cpr->offset5);
+
+			/* Perform connection update */
+			conn->llcp_conn_param.state = LLCP_CPR_STATE_RSP;
+		}
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+	case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		reject_ext_ind_recv(conn, *rx, pdu_rx);
+		break;
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	case PDU_DATA_LLCTRL_TYPE_PING_REQ:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PING_REQ, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = ping_resp_send(conn, *rx);
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PING_RSP:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PING_RSP, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		/* Procedure complete */
+		conn->procedure_expire = 0U;
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		struct pdu_data_llctrl *llctrl = (void *)&pdu_rx->llctrl;
+
+		if (0) {
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+		} else if ((conn->llcp_conn_param.ack !=
+			    conn->llcp_conn_param.req) &&
+			   (llctrl->unknown_rsp.type ==
+			    PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ)) {
+			struct lll_conn *lll = &conn->lll;
+			struct node_rx_cu *cu;
+
+			/* Mark CPR as unsupported */
+			conn->llcp_conn_param.disabled = 1U;
+
+			/* TODO: check for unsupported remote feature reason */
+			if (!conn->lll.role) {
+				LL_ASSERT(conn->llcp_cu.req ==
+					  conn->llcp_cu.ack);
+
+				conn->llcp_conn_param.state =
+					LLCP_CPR_STATE_UPD;
+
+				conn->llcp_cu.win_size = 1U;
+				conn->llcp_cu.win_offset_us = 0U;
+				conn->llcp_cu.interval =
+					conn->llcp_conn_param.interval_max;
+				conn->llcp_cu.latency =
+					conn->llcp_conn_param.latency;
+				conn->llcp_cu.timeout =
+					conn->llcp_conn_param.timeout;
+				conn->llcp_cu.state = LLCP_CUI_STATE_USE;
+				conn->llcp_cu.cmd = conn->llcp_conn_param.cmd;
+				conn->llcp_cu.ack--;
+
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+				break;
+			}
+
+			LL_ASSERT(conn_upd_curr == conn);
+
+			/* reset mutex */
+			ull_conn_upd_curr_reset();
+
+			/* Procedure complete */
+			conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+			/* skip event generation if not cmd initiated */
+			if (!conn->llcp_conn_param.cmd) {
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+				break;
+			}
+
+			/* generate conn upd complete event with error code */
+			(*rx)->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
+
+			/* prepare connection update complete structure */
+			cu = (void *)pdu_rx;
+			cu->status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
+			cu->interval = lll->interval;
+			cu->latency = lll->latency;
+			cu->timeout = conn->supervision_reload *
+				      lll->interval * 125U / 1000;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+		} else if ((conn->llcp_length.req != conn->llcp_length.ack) &&
+			   (llctrl->unknown_rsp.type ==
+			    PDU_DATA_LLCTRL_TYPE_LENGTH_REQ)) {
+			/* Mark length update as unsupported */
+			conn->llcp_length.disabled = 1U;
+
+			/* Procedure complete */
+			conn->llcp_length.ack = conn->llcp_length.req;
+
+			/* propagate the data length procedure to
+			 * host
+			 */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		} else if ((conn->llcp_phy.req != conn->llcp_phy.ack) &&
+			   (llctrl->unknown_rsp.type ==
+			    PDU_DATA_LLCTRL_TYPE_PHY_REQ)) {
+			struct lll_conn *lll = &conn->lll;
+
+			/* Mark phy update as unsupported */
+			conn->llcp_phy.disabled = 1U;
+
+			/* Procedure complete */
+			conn->llcp_phy.ack = conn->llcp_phy.req;
+			conn->llcp_phy.pause_tx = 0U;
+
+			/* Reset packet timing restrictions */
+			lll->phy_tx_time = lll->phy_tx;
+
+			/* skip event generation is not cmd initiated */
+			if (conn->llcp_phy.cmd) {
+				struct node_rx_pu *p;
+
+				/* generate phy update complete event */
+				(*rx)->hdr.type = NODE_RX_TYPE_PHY_UPDATE;
+
+				p = (void *)pdu_rx;
+				p->status = 0U;
+				p->tx = lll->phy_tx;
+				p->rx = lll->phy_rx;
+			} else {
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+			}
+#endif /* CONFIG_BT_CTLR_PHY */
+
+		} else {
+			switch (llctrl->unknown_rsp.type) {
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+			case PDU_DATA_LLCTRL_TYPE_PING_REQ:
+				/* unknown rsp to LE Ping Req completes the
+				 * procedure; nothing to do here.
+				 */
+
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+				break;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+			default:
+				/* TODO: enqueue the error and let HCI handle
+				 *       it.
+				 */
+				break;
+			}
+		}
+
+		/* Procedure complete */
+		conn->procedure_expire = 0U;
+		break;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_RSP:
+	case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_LENGTH_REQ,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		nack = length_req_rsp_recv(conn, link, rx, pdu_rx);
+		break;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	case PDU_DATA_LLCTRL_TYPE_PHY_REQ:
+		if (!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PHY_REQ, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		if (!conn->lll.role) {
+			if ((conn->llcp_phy.ack !=
+			     conn->llcp_phy.req) &&
+			    ((conn->llcp_phy.state ==
+			      LLCP_PHY_STATE_ACK_WAIT) ||
+			     (conn->llcp_phy.state ==
+			      LLCP_PHY_STATE_RSP_WAIT) ||
+			     (conn->llcp_phy.state ==
+			      LLCP_PHY_STATE_UPD))) {
+				/* Same procedure collision  */
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_PHY_REQ,
+					BT_HCI_ERR_LL_PROC_COLLISION);
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			} else if (((((conn->llcp_req - conn->llcp_ack) &
+				      0x03) == 0x02) &&
+				    (conn->llcp_type !=
+				     LLCP_ENCRYPTION)) ||
+				   (conn->llcp_conn_param.req !=
+				    conn->llcp_conn_param.ack)) {
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+			} else if ((((conn->llcp_req - conn->llcp_ack) &
+				     0x03) == 0x02) &&
+				   (conn->llcp_conn_param.req !=
+				    conn->llcp_conn_param.ack)) {
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+			} else if ((((conn->llcp_req - conn->llcp_ack) &
+				     0x03) == 0x02) &&
+				   (conn->llcp_type !=
+				    LLCP_ENCRYPTION)) {
+#else /* !CONFIG_BT_CTLR_LE_ENC */
+			} else if (((conn->llcp_req - conn->llcp_ack) &
+				    0x03) == 0x02) {
+#endif /* !CONFIG_BT_CTLR_LE_ENC */
+#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
+				/* Different procedure collision */
+				nack = reject_ext_ind_send(conn, *rx,
+					PDU_DATA_LLCTRL_TYPE_PHY_REQ,
+					BT_HCI_ERR_DIFF_TRANS_COLLISION);
+			} else {
+				struct pdu_data_llctrl *c = &pdu_rx->llctrl;
+				struct pdu_data_llctrl_phy_req *p =
+					&c->phy_req;
+
+				conn->llcp_phy.state =
+					LLCP_PHY_STATE_UPD;
+
+				if (conn->llcp_phy.ack ==
+				    conn->llcp_phy.req) {
+					conn->llcp_phy.ack--;
+
+					conn->llcp_phy.cmd = 0U;
+
+					conn->llcp_phy.tx =
+						conn->phy_pref_tx;
+					conn->llcp_phy.rx =
+						conn->phy_pref_rx;
+				}
+
+				conn->llcp_phy.tx &= p->rx_phys;
+				conn->llcp_phy.rx &= p->tx_phys;
+
+				if (!conn->llcp_phy.tx || !conn->llcp_phy.rx) {
+					conn->llcp_phy.tx = 0;
+					conn->llcp_phy.rx = 0;
+				}
+
+				/* pause data packet tx */
+				conn->llcp_phy.pause_tx = 1U;
+
+				/* Mark for buffer for release */
+				(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+			}
+		} else {
+			nack = phy_rsp_send(conn, *rx, pdu_rx);
+		}
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PHY_RSP:
+		if (conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PHY_RSP, pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		if (!conn->lll.role &&
+		    (conn->llcp_phy.ack != conn->llcp_phy.req) &&
+		    (conn->llcp_phy.state == LLCP_PHY_STATE_RSP_WAIT)) {
+			struct pdu_data_llctrl_phy_rsp *p =
+				&pdu_rx->llctrl.phy_rsp;
+
+			conn->llcp_phy.state = LLCP_PHY_STATE_UPD;
+
+			conn->llcp_phy.tx &= p->rx_phys;
+			conn->llcp_phy.rx &= p->tx_phys;
+
+			if (!conn->llcp_phy.tx || !conn->llcp_phy.rx) {
+				conn->llcp_phy.tx = 0;
+				conn->llcp_phy.rx = 0;
+			}
+
+			/* pause data packet tx */
+			conn->llcp_phy.pause_tx = 1U;
+
+			/* Procedure timeout is stopped */
+			conn->procedure_expire = 0U;
+		}
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+
+	case PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND:
+	{
+		uint8_t err;
+
+		if (!conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		err = phy_upd_ind_recv(conn, link, rx, pdu_rx);
+		if (err) {
+			conn->llcp_terminate.reason_peer = err;
+		}
+	}
+	break;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_MIN_USED_CHAN)
+	case PDU_DATA_LLCTRL_TYPE_MIN_USED_CHAN_IND:
+		if (conn->lll.role ||
+		    !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_MIN_USED_CHAN_IND,
+				 pdu_rx->len)) {
+			goto ull_conn_rx_unknown_rsp_send;
+		}
+
+		if (!conn->lll.role) {
+			struct pdu_data_llctrl_min_used_chans_ind *p =
+				&pdu_rx->llctrl.min_used_chans_ind;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+			if (!(p->phys & (conn->lll.phy_tx |
+					 conn->lll.phy_rx))) {
+#else /* !CONFIG_BT_CTLR_PHY */
+			if (!(p->phys & 0x01)) {
+#endif /* !CONFIG_BT_CTLR_PHY */
+				break;
+			}
+
+			if (((conn->llcp_req - conn->llcp_ack) & 0x03) ==
+			    0x02) {
+				break;
+			}
+
+			ull_chan_map_get(conn->llcp.chan_map.chm);
+			/* conn->llcp.chan_map.instant     = 0; */
+			conn->llcp.chan_map.initiate = 1U;
+
+			conn->llcp_type = LLCP_CHAN_MAP;
+			conn->llcp_ack -= 2U;
+		}
+
+		/* Mark for buffer for release */
+		(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
+
+		break;
+#endif /* CONFIG_BT_CTLR_MIN_USED_CHAN */
+
+	default:
+ull_conn_rx_unknown_rsp_send:
+		nack = unknown_rsp_send(conn, *rx, opcode);
+		break;
+	}
+
+	return nack;
+}
+
+#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO)
+static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate)
+{
+	uint32_t time_incoming, time_outgoing;
+	uint8_t force_md_cnt;
+	uint8_t phy;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	phy = lll_conn->phy_tx;
+#else /* !CONFIG_BT_CTLR_PHY */
+	phy = PHY_1M;
+#endif /* !CONFIG_BT_CTLR_PHY */
+
+	time_incoming = (LL_LENGTH_OCTETS_RX_MAX << 3) *
+			1000000UL / tx_rate;
+	time_outgoing = PKT_DC_US(LL_LENGTH_OCTETS_RX_MAX,
+				  (PDU_MIC_SIZE * lll_conn->enc_tx), phy) +
+			PKT_DC_US(0U, 0U, phy) +
+			(EVENT_IFS_US << 1);
+
+	force_md_cnt = 0U;
+	if (time_incoming > time_outgoing) {
+		uint32_t delta;
+		uint32_t time_keep_alive;
+
+		delta = (time_incoming << 1) - time_outgoing;
+		time_keep_alive = (PKT_DC_US(0U, 0U, phy) + EVENT_IFS_US) << 1;
+		force_md_cnt = (delta + (time_keep_alive - 1)) /
+			       time_keep_alive;
+		BT_DBG("Time: incoming= %u, expected outgoing= %u, delta= %u, "
+		       "keepalive= %u, force_md_cnt = %u.",
+		       time_incoming, time_outgoing, delta, time_keep_alive,
+		       force_md_cnt);
+	}
+
+	return force_md_cnt;
+}
+#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h	(working copy)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct ll_conn *ll_conn_acquire(void);
+void ll_conn_release(struct ll_conn *conn);
+uint16_t ll_conn_handle_get(struct ll_conn *conn);
+struct ll_conn *ll_conn_get(uint16_t handle);
+struct ll_conn *ll_connected_get(uint16_t handle);
+void ll_tx_ack_put(uint16_t handle, struct node_tx *node_tx);
+int ull_conn_init(void);
+int ull_conn_reset(void);
+void ull_conn_chan_map_set(uint8_t *chan_map);
+uint16_t ull_conn_default_tx_octets_get(void);
+uint16_t ull_conn_default_tx_time_get(void);
+uint8_t ull_conn_default_phy_tx_get(void);
+uint8_t ull_conn_default_phy_rx_get(void);
+void ull_conn_setup(memq_link_t *link, struct node_rx_hdr *rx);
+int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx);
+int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy);
+void ull_conn_done(struct node_rx_event_done *done);
+void ull_conn_tx_demux(uint8_t count);
+void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count);
+void ull_conn_link_tx_release(void *link);
+uint8_t ull_conn_ack_last_idx_get(void);
+memq_link_t *ull_conn_ack_peek(uint8_t *ack_last, uint16_t *handle,
+			       struct node_tx **tx);
+memq_link_t *ull_conn_ack_by_last_peek(uint8_t last, uint16_t *handle,
+				       struct node_tx **tx);
+void *ull_conn_ack_dequeue(void);
+void ull_conn_tx_ack(uint16_t handle, memq_link_t *link, struct node_tx *tx);
+uint8_t ull_conn_llcp_req(void *conn);
+void ull_conn_upd_curr_reset(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_types.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_types.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_conn_types.h	(working copy)
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+enum llcp {
+	LLCP_NONE,
+	LLCP_CONN_UPD,
+	LLCP_CHAN_MAP,
+
+	/*
+	 * LLCP_TERMINATE,
+	 * LLCP_FEATURE_EXCHANGE,
+	 * LLCP_VERSION_EXCHANGE,
+	 */
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	LLCP_ENCRYPTION,
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+	LLCP_CONNECTION_PARAM_REQ,
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	LLCP_PING,
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	LLCP_PHY_UPD,
+#endif /* CONFIG_BT_CTLR_PHY */
+};
+
+struct ll_conn {
+	struct evt_hdr  evt;
+	struct ull_hdr  ull;
+	struct lll_conn lll;
+
+	uint16_t connect_expire;
+	uint16_t supervision_reload;
+	uint16_t supervision_expire;
+	uint16_t procedure_reload;
+	uint16_t procedure_expire;
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	uint16_t appto_reload;
+	uint16_t appto_expire;
+	uint16_t apto_reload;
+	uint16_t apto_expire;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	uint16_t default_tx_octets;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	uint16_t default_tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+	union {
+		struct {
+			uint8_t fex_valid:1;
+		} common;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		struct {
+			uint8_t  fex_valid:1;
+			uint8_t  latency_cancel:1;
+			uint8_t  sca:3;
+			uint32_t force;
+			uint32_t ticks_to_offset;
+		} slave;
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_CENTRAL)
+		struct {
+			uint8_t fex_valid:1;
+			uint8_t terminate_ack:1;
+		} master;
+#endif /* CONFIG_BT_CENTRAL */
+	};
+
+	uint8_t llcp_req;
+	uint8_t llcp_ack;
+	uint8_t llcp_type;
+
+	union {
+		struct {
+			uint16_t instant;
+			uint16_t *pdu_win_offset;
+			uint32_t ticks_anchor;
+		} conn_upd;
+
+		struct {
+			uint8_t  initiate:1;
+			uint8_t  chm[5];
+			uint16_t instant;
+		} chan_map;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+		struct {
+			uint8_t initiate:1;
+			uint8_t cmd:1;
+			uint8_t tx:3;
+			uint8_t rx:3;
+			uint16_t instant;
+		} phy_upd_ind;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+		struct {
+			enum {
+				LLCP_ENC_STATE_INPROG,
+				LLCP_ENC_STATE_INIT,
+				LLCP_ENC_STATE_LTK_WAIT,
+			} state:2 __packed;
+			uint8_t  error_code;
+			uint8_t  skd[16];
+		} encryption;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+	} llcp;
+
+	struct node_rx_pdu *llcp_rx;
+
+	struct {
+		uint8_t  req;
+		uint8_t  ack;
+		enum {
+			LLCP_CUI_STATE_INPROG,
+			LLCP_CUI_STATE_USE,
+			LLCP_CUI_STATE_SELECT
+		} state:2 __packed;
+		uint8_t  cmd:1;
+		uint16_t interval;
+		uint16_t latency;
+		uint16_t timeout;
+		uint32_t win_offset_us;
+		uint8_t  win_size;
+	} llcp_cu;
+
+	struct {
+		uint8_t  req;
+		uint8_t  ack;
+		uint32_t features_conn;
+		uint32_t features_peer;
+	} llcp_feature;
+
+	struct {
+		uint8_t  req;
+		uint8_t  ack;
+		uint8_t  tx:1;
+		uint8_t  rx:1;
+		uint8_t  version_number;
+		uint16_t company_id;
+		uint16_t sub_version_number;
+	} llcp_version;
+
+	struct {
+		uint8_t req;
+		uint8_t ack;
+		uint8_t reason_own;
+		uint8_t reason_peer;
+		struct {
+			struct node_rx_hdr hdr;
+			uint8_t reason;
+		} node_rx;
+	} llcp_terminate;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	struct {
+		uint8_t req;
+		uint8_t ack;
+		uint8_t pause_rx:1;
+		uint8_t pause_tx:1;
+		uint8_t refresh:1;
+		uint8_t ediv[2];
+		uint8_t rand[8];
+		uint8_t ltk[16];
+	} llcp_enc;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	struct {
+		uint8_t  req;
+		uint8_t  ack;
+		enum {
+			LLCP_CPR_STATE_REQ,
+			LLCP_CPR_STATE_RSP,
+			LLCP_CPR_STATE_APP_REQ,
+			LLCP_CPR_STATE_APP_WAIT,
+			LLCP_CPR_STATE_RSP_WAIT,
+			LLCP_CPR_STATE_UPD
+		} state:3 __packed;
+		uint8_t  cmd:1;
+		uint8_t  disabled:1;
+		uint8_t  status;
+		uint16_t interval_min;
+		uint16_t interval_max;
+		uint16_t latency;
+		uint16_t timeout;
+		uint8_t  preferred_periodicity;
+		uint16_t reference_conn_event_count;
+		uint16_t offset0;
+		uint16_t offset1;
+		uint16_t offset2;
+		uint16_t offset3;
+		uint16_t offset4;
+		uint16_t offset5;
+		uint16_t *pdu_win_offset0;
+		uint32_t ticks_ref;
+		uint32_t ticks_to_offset_next;
+	} llcp_conn_param;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	struct {
+		uint8_t  req;
+		uint8_t  ack;
+		uint8_t  state:3;
+#define LLCP_LENGTH_STATE_REQ                 0
+#define LLCP_LENGTH_STATE_REQ_ACK_WAIT        1
+#define LLCP_LENGTH_STATE_RSP_WAIT            2
+#define LLCP_LENGTH_STATE_RSP_ACK_WAIT        3
+#define LLCP_LENGTH_STATE_RESIZE              4
+#define LLCP_LENGTH_STATE_RESIZE_RSP          5
+#define LLCP_LENGTH_STATE_RESIZE_RSP_ACK_WAIT 6
+		uint8_t  disabled:1;
+		uint16_t rx_octets;
+		uint16_t tx_octets;
+#if defined(CONFIG_BT_CTLR_PHY)
+		uint16_t rx_time;
+		uint16_t tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+		struct {
+			uint16_t tx_octets;
+#if defined(CONFIG_BT_CTLR_PHY)
+			uint16_t tx_time;
+#endif /* CONFIG_BT_CTLR_PHY */
+		} cache;
+	} llcp_length;
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	struct {
+		uint8_t req;
+		uint8_t ack;
+		uint8_t state:2;
+#define LLCP_PHY_STATE_REQ      0
+#define LLCP_PHY_STATE_ACK_WAIT 1
+#define LLCP_PHY_STATE_RSP_WAIT 2
+#define LLCP_PHY_STATE_UPD      3
+		uint8_t tx:3;
+		uint8_t rx:3;
+		uint8_t pause_tx:1;
+		uint8_t flags:1;
+		uint8_t cmd:1;
+		uint8_t disabled:1;
+	} llcp_phy;
+
+	uint8_t phy_pref_tx:3;
+	uint8_t phy_pref_flags:1;
+	uint8_t phy_pref_rx:3;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_LLID_DATA_START_EMPTY)
+	/* Detect empty L2CAP start frame */
+	uint8_t  start_empty:1;
+#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
+
+	struct node_tx *tx_head;
+	struct node_tx *tx_ctrl;
+	struct node_tx *tx_ctrl_last;
+	struct node_tx *tx_data;
+	struct node_tx *tx_data_last;
+
+	uint8_t chm_updated;
+};
+
+struct node_rx_cc {
+	uint8_t  status;
+	uint8_t  role;
+	uint8_t  peer_addr_type;
+	uint8_t  peer_addr[BDADDR_SIZE];
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  peer_rpa[BDADDR_SIZE];
+	uint8_t  local_rpa[BDADDR_SIZE];
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	uint16_t interval;
+	uint16_t latency;
+	uint16_t timeout;
+	uint8_t  sca;
+};
+
+struct node_rx_cu {
+	uint8_t  status;
+	uint16_t interval;
+	uint16_t latency;
+	uint16_t timeout;
+};
+
+struct node_rx_cs {
+	uint8_t csa;
+};
+
+struct node_rx_pu {
+	uint8_t status;
+	uint8_t tx;
+	uint8_t rx;
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.h	(working copy)
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void ull_filter_adv_scan_state_cb(uint8_t bm);
+void ull_filter_adv_update(uint8_t adv_fp);
+void ull_filter_scan_update(uint8_t scan_fp);
+void ull_filter_rpa_update(bool timeout);
+void ull_filter_adv_pdu_update(struct ll_adv_set *adv, struct pdu_adv *pdu);
+uint8_t ull_filter_rl_find(uint8_t id_addr_type, uint8_t const *const id_addr,
+			uint8_t *const free);
+void ull_filter_reset(bool init);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_filter.c	(working copy)
@@ -0,0 +1,1248 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "pdu.h"
+#include "ll.h"
+
+#include "lll.h"
+#include "lll_adv.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_filter.h"
+
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_filter.h"
+
+#include "ull_internal.h"
+#include "ull_adv_internal.h"
+#include "ull_scan_internal.h"
+
+#define ADDR_TYPE_ANON 0xFF
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_filter
+#include "common/log.h"
+#include "hal/debug.h"
+
+/* Hardware whitelist */
+static struct lll_filter wl_filter;
+uint8_t wl_anon;
+
+#define IRK_SIZE 16
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#include "common/rpa.h"
+
+/* Whitelist peer list */
+static struct lll_whitelist wl[WL_SIZE];
+
+static uint8_t rl_enable;
+
+static struct lll_resolvelist rl[CONFIG_BT_CTLR_RL_SIZE];
+
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+/* Cache of known unknown peer RPAs */
+static uint8_t newest_prpa;
+static struct prpa_cache_dev {
+	uint8_t      taken:1;
+	bt_addr_t rpa;
+} prpa_cache[CONFIG_BT_CTLR_RPA_CACHE_SIZE];
+
+struct prpa_resolve_work {
+	struct k_work prpa_work;
+	bt_addr_t     rpa;
+	resolve_callback_t cb;
+};
+
+struct target_resolve_work {
+	struct k_work target_work;
+	bt_addr_t rpa;
+	uint8_t      idx;
+	resolve_callback_t cb;
+};
+#endif /* CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */
+
+static uint8_t peer_irks[CONFIG_BT_CTLR_RL_SIZE][IRK_SIZE];
+static uint8_t peer_irk_rl_ids[CONFIG_BT_CTLR_RL_SIZE];
+static uint8_t peer_irk_count;
+
+static bt_addr_t local_rpas[CONFIG_BT_CTLR_RL_SIZE];
+
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+static struct prpa_resolve_work resolve_work;
+static struct target_resolve_work t_work;
+
+BUILD_ASSERT(ARRAY_SIZE(prpa_cache) < FILTER_IDX_NONE);
+#endif /* CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */
+BUILD_ASSERT(ARRAY_SIZE(wl) < FILTER_IDX_NONE);
+BUILD_ASSERT(ARRAY_SIZE(rl) < FILTER_IDX_NONE);
+
+/* Hardware filter for the resolving list */
+static struct lll_filter rl_filter;
+
+#define DEFAULT_RPA_TIMEOUT_MS (900 * 1000)
+static uint32_t rpa_timeout_ms;
+static int64_t rpa_last_ms;
+
+static struct k_delayed_work rpa_work;
+
+#define LIST_MATCH(list, i, type, addr) (list[i].taken && \
+		    (list[i].id_addr_type == (type & 0x1)) && \
+		    !memcmp(list[i].id_addr.val, addr, BDADDR_SIZE))
+
+static void wl_clear(void);
+static uint8_t wl_find(uint8_t addr_type, uint8_t *addr, uint8_t *free);
+static uint32_t wl_add(bt_addr_le_t *id_addr);
+static uint32_t wl_remove(bt_addr_le_t *id_addr);
+static void wl_update(void);
+
+static void rl_clear(void);
+static void rl_update(void);
+static int rl_access_check(bool check_ar);
+
+#if defined(CONFIG_BT_BROADCASTER)
+static void rpa_adv_refresh(struct ll_adv_set *adv);
+#endif
+static void rpa_timeout(struct k_work *work);
+static void rpa_refresh_start(void);
+static void rpa_refresh_stop(void);
+#else /* !CONFIG_BT_CTLR_PRIVACY */
+static uint32_t filter_add(struct lll_filter *filter, uint8_t addr_type,
+			uint8_t *bdaddr);
+static uint32_t filter_remove(struct lll_filter *filter, uint8_t addr_type,
+			   uint8_t *bdaddr);
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+static void filter_insert(struct lll_filter *filter, int index, uint8_t addr_type,
+			   uint8_t *bdaddr);
+static void filter_clear(struct lll_filter *filter);
+
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+static void prpa_cache_clear(void);
+static uint8_t prpa_cache_find(bt_addr_t *prpa_cache_addr);
+static void prpa_cache_add(bt_addr_t *prpa_cache_addr);
+static uint8_t prpa_cache_try_resolve(bt_addr_t *rpa);
+static void prpa_cache_resolve(struct k_work *work);
+static void target_resolve(struct k_work *work);
+#endif /* CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */
+
+uint8_t ll_wl_size_get(void)
+{
+	return WL_SIZE;
+}
+
+uint8_t ll_wl_clear(void)
+{
+#if defined(CONFIG_BT_BROADCASTER)
+	if (ull_adv_filter_pol_get(0)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (ull_scan_filter_pol_get(0) & 0x1) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	wl_clear();
+#else
+	filter_clear(&wl_filter);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+	wl_anon = 0U;
+
+	return 0;
+}
+
+uint8_t ll_wl_add(bt_addr_le_t *addr)
+{
+#if defined(CONFIG_BT_BROADCASTER)
+	if (ull_adv_filter_pol_get(0)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (ull_scan_filter_pol_get(0) & 0x1) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	if (addr->type == ADDR_TYPE_ANON) {
+		wl_anon = 1U;
+		return 0;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return wl_add(addr);
+#else
+	return filter_add(&wl_filter, addr->type, addr->a.val);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+uint8_t ll_wl_remove(bt_addr_le_t *addr)
+{
+#if defined(CONFIG_BT_BROADCASTER)
+	if (ull_adv_filter_pol_get(0)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (ull_scan_filter_pol_get(0) & 0x1) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	if (addr->type == ADDR_TYPE_ANON) {
+		wl_anon = 0U;
+		return 0;
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	return wl_remove(addr);
+#else
+	return filter_remove(&wl_filter, addr->type, addr->a.val);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+void ll_rl_id_addr_get(uint8_t rl_idx, uint8_t *id_addr_type, uint8_t *id_addr)
+{
+	LL_ASSERT(rl_idx < CONFIG_BT_CTLR_RL_SIZE);
+	LL_ASSERT(rl[rl_idx].taken);
+
+	*id_addr_type = rl[rl_idx].id_addr_type;
+	memcpy(id_addr, rl[rl_idx].id_addr.val, BDADDR_SIZE);
+}
+
+uint8_t ll_rl_size_get(void)
+{
+	return CONFIG_BT_CTLR_RL_SIZE;
+}
+
+uint8_t ll_rl_clear(void)
+{
+	if (!rl_access_check(false)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	rl_clear();
+
+	return 0;
+}
+
+uint8_t ll_rl_add(bt_addr_le_t *id_addr, const uint8_t pirk[IRK_SIZE],
+	       const uint8_t lirk[IRK_SIZE])
+{
+	uint8_t i, j;
+
+	if (!rl_access_check(false)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	i = ull_filter_rl_find(id_addr->type, id_addr->a.val, &j);
+
+	/* Duplicate check */
+	if (i < ARRAY_SIZE(rl)) {
+		return BT_HCI_ERR_INVALID_PARAM;
+	} else if (j >= ARRAY_SIZE(rl)) {
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	/* Device not found but empty slot found */
+	i = j;
+
+	bt_addr_copy(&rl[i].id_addr, &id_addr->a);
+	rl[i].id_addr_type = id_addr->type & 0x1;
+	rl[i].pirk = mem_nz((uint8_t *)pirk, IRK_SIZE);
+	rl[i].lirk = mem_nz((uint8_t *)lirk, IRK_SIZE);
+	if (rl[i].pirk) {
+		/* cross-reference */
+		rl[i].pirk_idx = peer_irk_count;
+		peer_irk_rl_ids[peer_irk_count] = i;
+		/* AAR requires big-endian IRKs */
+		sys_memcpy_swap(peer_irks[peer_irk_count++], pirk, IRK_SIZE);
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+		/* a new key was added, invalidate the known/unknown list */
+		prpa_cache_clear();
+#endif
+	}
+	if (rl[i].lirk) {
+		memcpy(rl[i].local_irk, lirk, IRK_SIZE);
+		rl[i].local_rpa = NULL;
+	}
+	memset(rl[i].curr_rpa.val, 0x00, sizeof(rl[i].curr_rpa));
+	rl[i].rpas_ready = 0U;
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+	memset(rl[i].target_rpa.val, 0x00, sizeof(rl[i].target_rpa));
+#endif
+	/* Default to Network Privacy */
+	rl[i].dev = 0U;
+	/* Add reference to  a whitelist entry */
+	j = wl_find(id_addr->type, id_addr->a.val, NULL);
+	if (j < ARRAY_SIZE(wl)) {
+		wl[j].rl_idx = i;
+		rl[i].wl = 1U;
+	} else {
+		rl[i].wl = 0U;
+	}
+	rl[i].taken = 1U;
+
+	return 0;
+}
+
+uint8_t ll_rl_remove(bt_addr_le_t *id_addr)
+{
+	uint8_t i;
+
+	if (!rl_access_check(false)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	/* find the device and mark it as empty */
+	i = ull_filter_rl_find(id_addr->type, id_addr->a.val, NULL);
+	if (i < ARRAY_SIZE(rl)) {
+		uint8_t j, k;
+
+		if (rl[i].pirk) {
+			/* Swap with last item */
+			uint8_t pi = rl[i].pirk_idx, pj = peer_irk_count - 1;
+
+			if (pj && pi != pj) {
+				memcpy(peer_irks[pi], peer_irks[pj], IRK_SIZE);
+				for (k = 0U;
+				     k < CONFIG_BT_CTLR_RL_SIZE;
+				     k++) {
+
+					if (rl[k].taken && rl[k].pirk &&
+					    rl[k].pirk_idx == pj) {
+						rl[k].pirk_idx = pi;
+						peer_irk_rl_ids[pi] = k;
+						break;
+					}
+				}
+			}
+			peer_irk_count--;
+		}
+
+		/* Check if referenced by a whitelist entry */
+		j = wl_find(id_addr->type, id_addr->a.val, NULL);
+		if (j < ARRAY_SIZE(wl)) {
+			wl[j].rl_idx = FILTER_IDX_NONE;
+		}
+		rl[i].taken = 0U;
+		return 0;
+	}
+
+	return BT_HCI_ERR_UNKNOWN_CONN_ID;
+}
+
+void ll_rl_crpa_set(uint8_t id_addr_type, uint8_t *id_addr, uint8_t rl_idx, uint8_t *crpa)
+{
+	if ((crpa[5] & 0xc0) == 0x40) {
+
+		if (id_addr) {
+			/* find the device and return its RPA */
+			rl_idx = ull_filter_rl_find(id_addr_type, id_addr, NULL);
+		}
+
+		if (rl_idx < ARRAY_SIZE(rl) && rl[rl_idx].taken) {
+			memcpy(rl[rl_idx].curr_rpa.val, crpa,
+			       sizeof(bt_addr_t));
+		}
+	}
+}
+
+uint8_t ll_rl_crpa_get(bt_addr_le_t *id_addr, bt_addr_t *crpa)
+{
+	uint8_t i;
+
+	/* find the device and return its RPA */
+	i = ull_filter_rl_find(id_addr->type, id_addr->a.val, NULL);
+	if (i < ARRAY_SIZE(rl) &&
+	    mem_nz(rl[i].curr_rpa.val, sizeof(rl[i].curr_rpa.val))) {
+		bt_addr_copy(crpa, &rl[i].curr_rpa);
+		return 0;
+	}
+
+	return BT_HCI_ERR_UNKNOWN_CONN_ID;
+}
+
+uint8_t ll_rl_lrpa_get(bt_addr_le_t *id_addr, bt_addr_t *lrpa)
+{
+	uint8_t i;
+
+	/* find the device and return the local RPA */
+	i = ull_filter_rl_find(id_addr->type, id_addr->a.val, NULL);
+	if (i < ARRAY_SIZE(rl)) {
+		bt_addr_copy(lrpa, rl[i].local_rpa);
+		return 0;
+	}
+
+	return BT_HCI_ERR_UNKNOWN_CONN_ID;
+}
+
+uint8_t ll_rl_enable(uint8_t enable)
+{
+	if (!rl_access_check(false)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	switch (enable) {
+	case BT_HCI_ADDR_RES_DISABLE:
+		rl_enable = 0U;
+		break;
+	case BT_HCI_ADDR_RES_ENABLE:
+		rl_enable = 1U;
+		break;
+	default:
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	return 0;
+}
+
+void ll_rl_timeout_set(uint16_t timeout)
+{
+	rpa_timeout_ms = timeout * 1000U;
+}
+
+uint8_t ll_priv_mode_set(bt_addr_le_t *id_addr, uint8_t mode)
+{
+	uint8_t i;
+
+	if (!rl_access_check(false)) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	/* find the device and mark it as empty */
+	i = ull_filter_rl_find(id_addr->type, id_addr->a.val, NULL);
+	if (i < ARRAY_SIZE(rl)) {
+		switch (mode) {
+		case BT_HCI_LE_PRIVACY_MODE_NETWORK:
+			rl[i].dev = 0U;
+			break;
+		case BT_HCI_LE_PRIVACY_MODE_DEVICE:
+			rl[i].dev = 1U;
+			break;
+		default:
+			return BT_HCI_ERR_INVALID_PARAM;
+		}
+	} else {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	return 0;
+}
+
+void ull_filter_adv_scan_state_cb(uint8_t bm)
+{
+	if (bm) {
+		rpa_refresh_start();
+	} else {
+		rpa_refresh_stop();
+	}
+}
+
+void ull_filter_adv_update(uint8_t adv_fp)
+{
+	/* Clear before populating filter */
+	filter_clear(&wl_filter);
+
+	/* enabling advertising */
+	if (adv_fp &&
+	    (!IS_ENABLED(CONFIG_BT_OBSERVER) ||
+	     !(ull_scan_filter_pol_get(0) & 0x1))) {
+		/* whitelist not in use, update whitelist */
+		wl_update();
+	}
+
+	/* Clear before populating rl filter */
+	filter_clear(&rl_filter);
+
+	if (rl_enable &&
+	    (!IS_ENABLED(CONFIG_BT_OBSERVER) || !ull_scan_is_enabled(0))) {
+		/* rl not in use, update resolving list LUT */
+		rl_update();
+	}
+}
+
+void ull_filter_scan_update(uint8_t scan_fp)
+{
+	/* Clear before populating filter */
+	filter_clear(&wl_filter);
+
+	/* enabling advertising */
+	if ((scan_fp & 0x1) &&
+	    (!IS_ENABLED(CONFIG_BT_BROADCASTER) ||
+	     !ull_adv_filter_pol_get(0))) {
+		/* whitelist not in use, update whitelist */
+		wl_update();
+	}
+
+	/* Clear before populating rl filter */
+	filter_clear(&rl_filter);
+
+	if (rl_enable &&
+	    (!IS_ENABLED(CONFIG_BT_BROADCASTER) || !ull_adv_is_enabled(0))) {
+		/* rl not in use, update resolving list LUT */
+		rl_update();
+	}
+}
+
+void ull_filter_rpa_update(bool timeout)
+{
+	uint8_t i;
+	int err;
+	int64_t now = k_uptime_get();
+	bool all = timeout || (rpa_last_ms == -1) ||
+		   (now - rpa_last_ms >= rpa_timeout_ms);
+	BT_DBG("");
+
+	for (i = 0U; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		if ((rl[i].taken) && (all || !rl[i].rpas_ready)) {
+
+			if (rl[i].pirk) {
+				uint8_t irk[IRK_SIZE];
+
+				/* TODO: move this swap to the driver level */
+				sys_memcpy_swap(irk, peer_irks[rl[i].pirk_idx],
+						IRK_SIZE);
+				err = bt_rpa_create(irk, &rl[i].peer_rpa);
+				LL_ASSERT(!err);
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+				/* a new key was added,
+				 * invalidate the known/unknown peer RPA cache
+				 */
+				prpa_cache_clear();
+#endif
+			}
+
+			if (rl[i].lirk) {
+				bt_addr_t rpa;
+
+				err = bt_rpa_create(rl[i].local_irk, &rpa);
+				LL_ASSERT(!err);
+				/* pointer read/write assumed to be atomic
+				 * so that if ISR fires the local_rpa pointer
+				 * will always point to a valid full RPA
+				 */
+				rl[i].local_rpa = &rpa;
+				bt_addr_copy(&local_rpas[i], &rpa);
+				rl[i].local_rpa = &local_rpas[i];
+			}
+
+			rl[i].rpas_ready = 1U;
+		}
+	}
+
+	if (all) {
+		rpa_last_ms = now;
+	}
+
+	if (timeout) {
+#if defined(CONFIG_BT_BROADCASTER)
+		struct ll_adv_set *adv;
+
+		/* TODO: foreach adv set */
+		adv = ull_adv_is_enabled_get(0);
+		if (adv) {
+			rpa_adv_refresh(adv);
+		}
+#endif
+	}
+}
+
+#if defined(CONFIG_BT_BROADCASTER)
+void ull_filter_adv_pdu_update(struct ll_adv_set *adv, struct pdu_adv *pdu)
+{
+	uint8_t *adva = pdu->type == PDU_ADV_TYPE_SCAN_RSP ?
+				  &pdu->scan_rsp.addr[0] :
+				  &pdu->adv_ind.addr[0];
+	uint8_t idx = adv->lll.rl_idx;
+
+	/* AdvA */
+	if (idx < ARRAY_SIZE(rl) && rl[idx].lirk) {
+		LL_ASSERT(rl[idx].rpas_ready);
+		pdu->tx_addr = 1;
+		memcpy(adva, rl[idx].local_rpa->val, BDADDR_SIZE);
+	} else {
+		pdu->tx_addr = adv->own_addr_type & 0x1;
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+		if (ll_adv_cmds_is_ext() && pdu->tx_addr) {
+			ll_adv_aux_random_addr_get(adv, adva);
+		} else
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+		{
+			ll_addr_get(pdu->tx_addr, adva);
+		}
+	}
+
+	/* TargetA */
+	if (pdu->type == PDU_ADV_TYPE_DIRECT_IND) {
+		if (idx < ARRAY_SIZE(rl) && rl[idx].pirk) {
+			pdu->rx_addr = 1;
+			memcpy(&pdu->direct_ind.tgt_addr[0],
+			       rl[idx].peer_rpa.val, BDADDR_SIZE);
+		} else {
+			pdu->rx_addr = adv->id_addr_type;
+			memcpy(&pdu->direct_ind.tgt_addr[0],
+			       adv->id_addr, BDADDR_SIZE);
+		}
+	}
+}
+#endif /* CONFIG_BT_BROADCASTER */
+
+uint8_t ull_filter_rl_find(uint8_t id_addr_type, uint8_t const *const id_addr,
+			uint8_t *const free)
+{
+	uint8_t i;
+
+	if (free) {
+		*free = FILTER_IDX_NONE;
+	}
+
+	for (i = 0U; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		if (LIST_MATCH(rl, i, id_addr_type, id_addr)) {
+			return i;
+		} else if (free && !rl[i].taken && (*free == FILTER_IDX_NONE)) {
+			*free = i;
+		}
+	}
+
+	return FILTER_IDX_NONE;
+}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+void ull_filter_reset(bool init)
+{
+	wl_anon = 0U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	wl_clear();
+
+	rl_enable = 0U;
+	rpa_timeout_ms = DEFAULT_RPA_TIMEOUT_MS;
+	rpa_last_ms = -1;
+	rl_clear();
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+	prpa_cache_clear();
+#endif
+	if (init) {
+		k_delayed_work_init(&rpa_work, rpa_timeout);
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+		k_work_init(&(resolve_work.prpa_work), prpa_cache_resolve);
+		k_work_init(&(t_work.target_work), target_resolve);
+#endif
+	} else {
+		k_delayed_work_cancel(&rpa_work);
+	}
+#else
+	filter_clear(&wl_filter);
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+bool ull_filter_lll_lrpa_used(uint8_t rl_idx)
+{
+	return rl_idx < ARRAY_SIZE(rl) && rl[rl_idx].lirk;
+}
+
+bt_addr_t *ull_filter_lll_lrpa_get(uint8_t rl_idx)
+{
+	if ((rl_idx >= ARRAY_SIZE(rl)) || !rl[rl_idx].lirk ||
+	    !rl[rl_idx].rpas_ready) {
+		return NULL;
+	}
+
+	return rl[rl_idx].local_rpa;
+}
+
+uint8_t *ull_filter_lll_irks_get(uint8_t *count)
+{
+	*count = peer_irk_count;
+	return (uint8_t *)peer_irks;
+}
+
+uint8_t ull_filter_lll_rl_idx(bool whitelist, uint8_t devmatch_id)
+{
+	uint8_t i;
+
+	if (whitelist) {
+		LL_ASSERT(devmatch_id < ARRAY_SIZE(wl));
+		LL_ASSERT(wl[devmatch_id].taken);
+		i = wl[devmatch_id].rl_idx;
+	} else {
+		LL_ASSERT(devmatch_id < ARRAY_SIZE(rl));
+		i = devmatch_id;
+		LL_ASSERT(rl[i].taken);
+	}
+
+	return i;
+}
+
+uint8_t ull_filter_lll_rl_irk_idx(uint8_t irkmatch_id)
+{
+	uint8_t i;
+
+	LL_ASSERT(irkmatch_id < peer_irk_count);
+	i = peer_irk_rl_ids[irkmatch_id];
+	LL_ASSERT(i < CONFIG_BT_CTLR_RL_SIZE);
+	LL_ASSERT(rl[i].taken);
+
+	return i;
+}
+
+bool ull_filter_lll_irk_whitelisted(uint8_t rl_idx)
+{
+	if (rl_idx >= ARRAY_SIZE(rl)) {
+		return false;
+	}
+
+	LL_ASSERT(rl[rl_idx].taken);
+
+	return rl[rl_idx].wl;
+}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+struct lll_filter *ull_filter_lll_get(bool whitelist)
+{
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	if (whitelist) {
+		return &wl_filter;
+	}
+	return &rl_filter;
+#else
+	LL_ASSERT(whitelist);
+	return &wl_filter;
+#endif
+}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+struct lll_whitelist *ull_filter_lll_whitelist_get(void)
+{
+	return wl;
+}
+
+struct lll_resolvelist *ull_filter_lll_resolvelist_get(void)
+{
+	return rl;
+}
+
+bool ull_filter_lll_rl_idx_allowed(uint8_t irkmatch_ok, uint8_t rl_idx)
+{
+	/* If AR is disabled or we don't know the device or we matched an IRK
+	 * then we're all set.
+	 */
+	if (!rl_enable || rl_idx >= ARRAY_SIZE(rl) || irkmatch_ok) {
+		return true;
+	}
+
+	LL_ASSERT(rl_idx < CONFIG_BT_CTLR_RL_SIZE);
+	LL_ASSERT(rl[rl_idx].taken);
+
+	return !rl[rl_idx].pirk || rl[rl_idx].dev;
+}
+
+bool ull_filter_lll_rl_addr_allowed(uint8_t id_addr_type, uint8_t *id_addr, uint8_t *rl_idx)
+{
+	uint8_t i, j;
+
+	/* If AR is disabled or we matched an IRK then we're all set. No hw
+	 * filters are used in this case.
+	 */
+	if (!rl_enable || *rl_idx != FILTER_IDX_NONE) {
+		return true;
+	}
+
+	for (i = 0U; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		if (rl[i].taken && (rl[i].id_addr_type == id_addr_type)) {
+			uint8_t *addr = rl[i].id_addr.val;
+
+			for (j = 0U; j < BDADDR_SIZE; j++) {
+				if (addr[j] != id_addr[j]) {
+					break;
+				}
+			}
+
+			if (j == BDADDR_SIZE) {
+				*rl_idx = i;
+				return !rl[i].pirk || rl[i].dev;
+			}
+		}
+	}
+
+	return true;
+}
+
+bool ull_filter_lll_rl_addr_resolve(uint8_t id_addr_type, uint8_t *id_addr, uint8_t rl_idx)
+{
+	/* Unable to resolve if AR is disabled, no RL entry or no local IRK */
+	if (!rl_enable || rl_idx >= ARRAY_SIZE(rl) || !rl[rl_idx].lirk) {
+		return false;
+	}
+
+	if ((id_addr_type != 0U) && ((id_addr[5] & 0xc0) == 0x40)) {
+		return bt_rpa_irk_matches(rl[rl_idx].local_irk,
+					  (bt_addr_t *)id_addr);
+	}
+
+	return false;
+}
+
+bool ull_filter_lll_rl_enabled(void)
+{
+	return rl_enable;
+}
+
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+uint8_t ull_filter_deferred_resolve(bt_addr_t *rpa, resolve_callback_t cb)
+{
+	LL_ASSERT(rl_enable);
+
+	if (!k_work_pending(&(resolve_work.prpa_work))) {
+		/* copy input param to work variable */
+		memcpy(resolve_work.rpa.val, rpa->val, sizeof(bt_addr_t));
+		resolve_work.cb = cb;
+
+		k_work_submit(&(resolve_work.prpa_work));
+
+		return 1;
+	}
+
+	return 0;
+}
+
+uint8_t ull_filter_deferred_targeta_resolve(bt_addr_t *rpa, uint8_t rl_idx,
+					 resolve_callback_t cb)
+{
+	LL_ASSERT(rl_enable);
+
+	if (!k_work_pending(&(t_work.target_work))) {
+		/* copy input param to work variable */
+		memcpy(t_work.rpa.val, rpa->val, sizeof(bt_addr_t));
+		t_work.cb = cb;
+		t_work.idx = rl_idx;
+
+		k_work_submit(&(t_work.target_work));
+
+		return 1;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */
+
+static void wl_clear(void)
+{
+	for (int i = 0; i < WL_SIZE; i++) {
+		uint8_t j = wl[i].rl_idx;
+
+		if (j < ARRAY_SIZE(rl)) {
+			rl[j].wl = 0U;
+		}
+		wl[i].taken = 0U;
+	}
+}
+
+static uint8_t wl_find(uint8_t addr_type, uint8_t *addr, uint8_t *free)
+{
+	int i;
+
+	if (free) {
+		*free = FILTER_IDX_NONE;
+	}
+
+	for (i = 0; i < WL_SIZE; i++) {
+		if (LIST_MATCH(wl, i, addr_type, addr)) {
+			return i;
+		} else if (free && !wl[i].taken && (*free == FILTER_IDX_NONE)) {
+			*free = i;
+		}
+	}
+
+	return FILTER_IDX_NONE;
+}
+
+static uint32_t wl_add(bt_addr_le_t *id_addr)
+{
+	uint8_t i, j;
+
+	i = wl_find(id_addr->type, id_addr->a.val, &j);
+
+	/* Duplicate  check */
+	if (i < ARRAY_SIZE(wl)) {
+		return 0;
+	} else if (j >= ARRAY_SIZE(wl)) {
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	i = j;
+
+	wl[i].id_addr_type = id_addr->type & 0x1;
+	bt_addr_copy(&wl[i].id_addr, &id_addr->a);
+	/* Get index to Resolving List if applicable */
+	j = ull_filter_rl_find(id_addr->type, id_addr->a.val, NULL);
+	if (j < ARRAY_SIZE(rl)) {
+		wl[i].rl_idx = j;
+		rl[j].wl = 1U;
+	} else {
+		wl[i].rl_idx = FILTER_IDX_NONE;
+	}
+	wl[i].taken = 1U;
+
+	return 0;
+}
+
+static uint32_t wl_remove(bt_addr_le_t *id_addr)
+{
+	/* find the device and mark it as empty */
+	uint8_t i = wl_find(id_addr->type, id_addr->a.val, NULL);
+
+	if (i < ARRAY_SIZE(wl)) {
+		uint8_t j = wl[i].rl_idx;
+
+		if (j < ARRAY_SIZE(rl)) {
+			rl[j].wl = 0U;
+		}
+		wl[i].taken = 0U;
+		return 0;
+	}
+
+	return BT_HCI_ERR_UNKNOWN_CONN_ID;
+}
+
+static void wl_update(void)
+{
+	uint8_t i;
+
+	/* Populate filter from wl peers */
+	for (i = 0U; i < WL_SIZE; i++) {
+		uint8_t j;
+
+		if (!wl[i].taken) {
+			continue;
+		}
+
+		j = wl[i].rl_idx;
+
+		if (!rl_enable || j >= ARRAY_SIZE(rl) || !rl[j].pirk ||
+		    rl[j].dev) {
+			filter_insert(&wl_filter, i, wl[i].id_addr_type,
+				      wl[i].id_addr.val);
+		}
+	}
+}
+
+static void rl_update(void)
+{
+	uint8_t i;
+
+	/* Populate filter from rl peers */
+	for (i = 0U; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		if (rl[i].taken) {
+			filter_insert(&rl_filter, i, rl[i].id_addr_type,
+				      rl[i].id_addr.val);
+		}
+	}
+}
+
+#if defined(CONFIG_BT_BROADCASTER)
+static void rpa_adv_refresh(struct ll_adv_set *adv)
+{
+	struct pdu_adv *prev;
+	struct pdu_adv *pdu;
+	uint8_t idx;
+
+	if (adv->own_addr_type != BT_ADDR_LE_PUBLIC_ID &&
+	    adv->own_addr_type != BT_ADDR_LE_RANDOM_ID) {
+		return;
+	}
+
+	if (adv->lll.rl_idx >= ARRAY_SIZE(rl)) {
+		return;
+	}
+
+	prev = lll_adv_data_peek(&adv->lll);
+	pdu = lll_adv_data_alloc(&adv->lll, &idx);
+	pdu->type = prev->type;
+	pdu->rfu = 0;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+		pdu->chan_sel = prev->chan_sel;
+	} else {
+		pdu->chan_sel = 0;
+	}
+
+	ull_filter_adv_pdu_update(adv, pdu);
+
+	memcpy(&pdu->adv_ind.data[0], &prev->adv_ind.data[0],
+	       prev->len - BDADDR_SIZE);
+	pdu->len = prev->len;
+
+	lll_adv_data_enqueue(&adv->lll, idx);
+}
+#endif /* CONFIG_BT_BROADCASTER */
+
+static void rl_clear(void)
+{
+	for (uint8_t i = 0; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		rl[i].taken = 0U;
+	}
+
+	peer_irk_count = 0U;
+}
+
+static int rl_access_check(bool check_ar)
+{
+	if (check_ar) {
+		/* If address resolution is disabled, allow immediately */
+		if (!rl_enable) {
+			return -1;
+		}
+	}
+
+	return ((IS_ENABLED(CONFIG_BT_BROADCASTER) && ull_adv_is_enabled(0)) ||
+		(IS_ENABLED(CONFIG_BT_OBSERVER) && ull_scan_is_enabled(0)))
+		? 0 : 1;
+}
+
+static void rpa_timeout(struct k_work *work)
+{
+	ull_filter_rpa_update(true);
+	k_delayed_work_submit(&rpa_work, K_MSEC(rpa_timeout_ms));
+}
+
+static void rpa_refresh_start(void)
+{
+	BT_DBG("");
+	k_delayed_work_submit(&rpa_work, K_MSEC(rpa_timeout_ms));
+}
+
+static void rpa_refresh_stop(void)
+{
+	k_delayed_work_cancel(&rpa_work);
+}
+
+#else /* !CONFIG_BT_CTLR_PRIVACY */
+
+static uint32_t filter_add(struct lll_filter *filter, uint8_t addr_type,
+			uint8_t *bdaddr)
+{
+	int index;
+
+	if (filter->enable_bitmask == 0xFF) {
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	for (index = 0;
+	     (filter->enable_bitmask & BIT(index));
+	     index++) {
+	}
+
+	filter_insert(filter, index, addr_type, bdaddr);
+	return 0;
+}
+
+static uint32_t filter_remove(struct lll_filter *filter, uint8_t addr_type,
+			   uint8_t *bdaddr)
+{
+	int index;
+
+	if (!filter->enable_bitmask) {
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	index = 8;
+	while (index--) {
+		if ((filter->enable_bitmask & BIT(index)) &&
+		    (((filter->addr_type_bitmask >> index) & 0x01) ==
+		     (addr_type & 0x01)) &&
+		    !memcmp(filter->bdaddr[index], bdaddr, BDADDR_SIZE)) {
+			filter->enable_bitmask &= ~BIT(index);
+			filter->addr_type_bitmask &= ~BIT(index);
+			return 0;
+		}
+	}
+
+	return BT_HCI_ERR_INVALID_PARAM;
+}
+#endif /* !CONFIG_BT_CTLR_PRIVACY */
+
+static void filter_insert(struct lll_filter *filter, int index, uint8_t addr_type,
+			   uint8_t *bdaddr)
+{
+	filter->enable_bitmask |= BIT(index);
+	filter->addr_type_bitmask |= ((addr_type & 0x01) << index);
+	memcpy(&filter->bdaddr[index][0], bdaddr, BDADDR_SIZE);
+}
+
+static void filter_clear(struct lll_filter *filter)
+{
+	filter->enable_bitmask = 0;
+	filter->addr_type_bitmask = 0;
+}
+
+#if defined(CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY)
+static void target_resolve(struct k_work *work)
+{
+	uint8_t j, idx;
+	bt_addr_t *search_rpa;
+	struct target_resolve_work *twork;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, 0, NULL};
+
+	twork = CONTAINER_OF(work, struct target_resolve_work, target_work);
+	idx = twork->idx;
+	search_rpa = &(twork->rpa);
+
+	if (rl[idx].taken && !bt_addr_cmp(&(rl[idx].target_rpa), search_rpa)) {
+		j = idx;
+	} else {
+		/* No match - so not in list Need to see if we can resolve */
+		if (bt_rpa_irk_matches(rl[idx].local_irk, search_rpa)) {
+			/* Could resolve, store RPA */
+			memcpy(rl[idx].target_rpa.val, search_rpa->val,
+			       sizeof(bt_addr_t));
+			j = idx;
+		} else {
+			/* Could not resolve, and not in table */
+			j = FILTER_IDX_NONE;
+		}
+	}
+
+	/* Kick the callback in LLL (using the mayfly, tailchain it)
+	 * Pass param FILTER_IDX_NONE if RPA can not be resolved,
+	 * or index in cache if it can be resolved
+	 */
+	if (twork->cb) {
+		mfy.fp = twork->cb;
+		mfy.param = (void *) ((unsigned int) j);
+		mayfly_enqueue(TICKER_USER_ID_THREAD,
+			       TICKER_USER_ID_LLL, 1, &mfy);
+	}
+}
+
+static uint8_t prpa_cache_try_resolve(bt_addr_t *rpa)
+{
+	uint8_t pi;
+	uint8_t lpirk[IRK_SIZE];
+
+	for (uint8_t i = 0U; i < CONFIG_BT_CTLR_RL_SIZE; i++) {
+		if (rl[i].taken && rl[i].pirk) {
+			pi = rl[i].pirk_idx;
+			sys_memcpy_swap(lpirk, peer_irks[pi], IRK_SIZE);
+			if (bt_rpa_irk_matches(lpirk, rpa)) {
+				return i;
+			}
+		}
+	}
+
+	return FILTER_IDX_NONE;
+}
+
+static void prpa_cache_resolve(struct k_work *work)
+{
+	uint8_t i, j;
+	bt_addr_t *search_rpa;
+	struct prpa_resolve_work *rwork;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, 0, NULL};
+
+	rwork = CONTAINER_OF(work, struct prpa_resolve_work, prpa_work);
+	search_rpa = &(rwork->rpa);
+
+	i = prpa_cache_find(search_rpa);
+
+	if (i == FILTER_IDX_NONE) {
+		/* No match - so not in known unknown list
+		 * Need to see if we can resolve
+		 */
+		j = prpa_cache_try_resolve(search_rpa);
+
+		if (j == FILTER_IDX_NONE) {
+			/* No match - thus cannot resolve, we have an unknown
+			 * so insert in known unkonown list
+			 */
+			prpa_cache_add(search_rpa);
+		} else {
+			/* Address could be resolved, so update current RPA
+			 * in list
+			 */
+			memcpy(rl[j].curr_rpa.val, search_rpa->val,
+			       sizeof(bt_addr_t));
+		}
+
+	} else {
+		/* Found a known unknown - do nothing */
+		j = FILTER_IDX_NONE;
+	}
+
+	/* Kick the callback in LLL (using the mayfly, tailchain it)
+	 * Pass param FILTER_IDX_NONE if RPA can not be resolved,
+	 * or index in cache if it can be resolved
+	 */
+	if (rwork->cb) {
+		mfy.fp = rwork->cb;
+		mfy.param = (void *) ((unsigned int) j);
+		mayfly_enqueue(TICKER_USER_ID_THREAD,
+			       TICKER_USER_ID_LLL, 1, &mfy);
+	}
+}
+
+static void prpa_cache_clear(void)
+{
+	/* Note the first element will not be in use before wrap around
+	 * is reached.
+	 * The first element in actual use will be at index 1.
+	 * There is no element waisted with this implementation, as
+	 * element 0 will eventually be allocated.
+	 */
+	newest_prpa = 0U;
+
+	for (uint8_t i = 0; i < CONFIG_BT_CTLR_RPA_CACHE_SIZE; i++) {
+		prpa_cache[i].taken = 0U;
+	}
+}
+
+static void prpa_cache_add(bt_addr_t *rpa)
+{
+	newest_prpa = (newest_prpa + 1) % CONFIG_BT_CTLR_RPA_CACHE_SIZE;
+
+	memcpy(prpa_cache[newest_prpa].rpa.val, rpa->val, sizeof(bt_addr_t));
+	prpa_cache[newest_prpa].taken = 1U;
+}
+
+static uint8_t prpa_cache_find(bt_addr_t *rpa)
+{
+	for (uint8_t i = 0; i < CONFIG_BT_CTLR_RPA_CACHE_SIZE; i++) {
+		if (prpa_cache[i].taken &&
+		    !bt_addr_cmp(&(prpa_cache[i].rpa), rpa)) {
+			return i;
+		}
+	}
+	return FILTER_IDX_NONE;
+}
+#endif /* !CONFIG_BT_CTLR_SW_DEFERRED_PRIVACY */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_internal.h	(working copy)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Macro to convert time in us to connection interval units */
+#define RADIO_CONN_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y)))
+
+/* Macro to convert time in us to periodic advertising interval units */
+#define RADIO_SYNC_EVENTS(x, y) ((uint16_t)(((x) + (y) - 1) / (y)))
+
+static inline uint8_t ull_ref_get(struct ull_hdr *hdr)
+{
+	return hdr->ref;
+}
+
+static inline uint8_t ull_ref_inc(struct ull_hdr *hdr)
+{
+	return ++hdr->ref;
+}
+
+static inline uint8_t ull_ref_dec(struct ull_hdr *hdr)
+{
+	return hdr->ref--;
+}
+
+static inline void ull_hdr_init(struct ull_hdr *hdr)
+{
+	hdr->disabled_cb = hdr->disabled_param = NULL;
+}
+
+void *ll_rx_link_alloc(void);
+void ll_rx_link_release(void *link);
+void *ll_rx_alloc(void);
+void ll_rx_release(void *node_rx);
+void *ll_pdu_rx_alloc_peek(uint8_t count);
+void *ll_pdu_rx_alloc(void);
+void ll_rx_put(memq_link_t *link, void *rx);
+void ll_rx_sched(void);
+void ull_ticker_status_give(uint32_t status, void *param);
+uint32_t ull_ticker_status_take(uint32_t ret, uint32_t volatile *ret_cb);
+void *ull_disable_mark(void *param);
+void *ull_disable_unmark(void *param);
+void *ull_disable_mark_get(void);
+void *ull_update_mark(void *param);
+void *ull_update_unmark(void *param);
+void *ull_update_mark_get(void);
+int ull_disable(void *param);
+void ull_drift_ticks_get(struct node_rx_event_done *done,
+			 uint32_t *ticks_drift_plus,
+			 uint32_t *ticks_drift_minus);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master.c	(working copy)
@@ -0,0 +1,826 @@
+/*
+ * Copyright (c) 2018-2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "util/util.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+#include "ll_feat.h"
+#include "ll_settings.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_adv.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_master.h"
+#include "lll_filter.h"
+#include "lll_tim_internal.h"
+
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_conn_types.h"
+#include "ull_filter.h"
+
+#include "ull_internal.h"
+#include "ull_chan_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_conn_internal.h"
+#include "ull_master_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_master
+#include "common/log.h"
+#include "hal/debug.h"
+
+static void ticker_op_stop_scan_cb(uint32_t status, void *params);
+static void ticker_op_cb(uint32_t status, void *params);
+static inline void conn_release(struct ll_scan_set *scan);
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
+			  uint8_t filter_policy, uint8_t peer_addr_type,
+			  uint8_t const *const peer_addr, uint8_t own_addr_type,
+			  uint16_t interval, uint16_t latency, uint16_t timeout,
+			  uint8_t phy)
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
+			  uint8_t filter_policy, uint8_t peer_addr_type,
+			  uint8_t const *const peer_addr, uint8_t own_addr_type,
+			  uint16_t interval, uint16_t latency, uint16_t timeout)
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+{
+	struct lll_conn *conn_lll;
+	struct ll_scan_set *scan;
+	uint32_t conn_interval_us;
+	struct lll_scan *lll;
+	struct ll_conn *conn;
+	memq_link_t *link;
+	uint8_t hop;
+	int err;
+
+	scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
+	if (!scan) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	struct ll_scan_set *scan_coded;
+	struct lll_scan *lll_coded;
+
+	scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
+	if (!scan_coded) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	lll = &scan->lll;
+	lll_coded = &scan_coded->lll;
+
+	if (phy & BT_HCI_LE_EXT_SCAN_PHY_CODED) {
+		if (!lll_coded->conn) {
+			lll_coded->conn = lll->conn;
+		}
+		scan = scan_coded;
+		lll = lll_coded;
+	} else {
+		if (!lll->conn) {
+			lll->conn = lll_coded->conn;
+		}
+	}
+
+#else /* !CONFIG_BT_CTLR_PHY_CODED */
+	if (phy & ~BT_HCI_LE_EXT_SCAN_PHY_1M) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	lll = &scan->lll;
+
+#endif /* !CONFIG_BT_CTLR_PHY_CODED */
+
+	lll->phy = phy;
+
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	lll = &scan->lll;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	if (lll->conn) {
+		goto conn_is_valid;
+	}
+
+	link = ll_rx_link_alloc();
+	if (!link) {
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	conn = ll_conn_acquire();
+	if (!conn) {
+		ll_rx_link_release(link);
+
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	ull_scan_params_set(lll, 0, scan_interval, scan_window, filter_policy);
+
+	lll->adv_addr_type = peer_addr_type;
+	memcpy(lll->adv_addr, peer_addr, BDADDR_SIZE);
+	lll->conn_timeout = timeout;
+	lll->conn_ticks_slot = 0; /* TODO: */
+
+	conn_lll = &conn->lll;
+
+	err = util_aa_le32(conn_lll->access_addr);
+	LL_ASSERT(!err);
+
+	lll_csrand_get(conn_lll->crc_init, sizeof(conn_lll->crc_init));
+
+	conn_lll->handle = 0xFFFF;
+	conn_lll->interval = interval;
+	conn_lll->latency = latency;
+
+	if (!conn_lll->link_tx_free) {
+		conn_lll->link_tx_free = &conn_lll->link_tx;
+	}
+
+	memq_init(conn_lll->link_tx_free, &conn_lll->memq_tx.head,
+		  &conn_lll->memq_tx.tail);
+	conn_lll->link_tx_free = NULL;
+
+	conn_lll->packet_tx_head_len = 0;
+	conn_lll->packet_tx_head_offset = 0;
+
+	conn_lll->sn = 0;
+	conn_lll->nesn = 0;
+	conn_lll->empty = 0;
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+	conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	conn_lll->max_tx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
+	conn_lll->max_rx_time = PKT_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	conn_lll->phy_tx = BIT(0);
+	conn_lll->phy_flags = 0;
+	conn_lll->phy_tx_time = BIT(0);
+	conn_lll->phy_rx = BIT(0);
+#endif /* CONFIG_BT_CTLR_PHY */
+
+#if defined(CONFIG_BT_CTLR_CONN_RSSI)
+	conn_lll->rssi_latest = 0x7F;
+#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)
+	conn_lll->rssi_reported = 0x7F;
+	conn_lll->rssi_sample_count = 0;
+#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
+#endif /* CONFIG_BT_CTLR_CONN_RSSI */
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	conn_lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	/* FIXME: BEGIN: Move to ULL? */
+	conn_lll->latency_prepare = 0;
+	conn_lll->latency_event = 0;
+	conn_lll->event_counter = 0;
+
+	conn_lll->data_chan_count = ull_chan_map_get(conn_lll->data_chan_map);
+	lll_csrand_get(&hop, sizeof(uint8_t));
+	conn_lll->data_chan_hop = 5 + (hop % 12);
+	conn_lll->data_chan_sel = 0;
+	conn_lll->data_chan_use = 0;
+	conn_lll->role = 0;
+	/* FIXME: END: Move to ULL? */
+#if defined(CONFIG_BT_CTLR_CONN_META)
+	memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
+#endif /* CONFIG_BT_CTLR_CONN_META */
+
+	conn->connect_expire = 6U;
+	conn->supervision_expire = 0U;
+	conn_interval_us = (uint32_t)interval * 1250U;
+	conn->supervision_reload = RADIO_CONN_EVENTS(timeout * 10000U,
+							 conn_interval_us);
+
+	conn->procedure_expire = 0U;
+	conn->procedure_reload = RADIO_CONN_EVENTS(40000000,
+						       conn_interval_us);
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	conn->apto_expire = 0U;
+	/* APTO in no. of connection events */
+	conn->apto_reload = RADIO_CONN_EVENTS((30000000), conn_interval_us);
+	conn->appto_expire = 0U;
+	/* Dispatch LE Ping PDU 6 connection events (that peer would listen to)
+	 * before 30s timeout
+	 * TODO: "peer listens to" is greater than 30s due to latency
+	 */
+	conn->appto_reload = (conn->apto_reload > (conn_lll->latency + 6)) ?
+			     (conn->apto_reload - (conn_lll->latency + 6)) :
+			     conn->apto_reload;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	conn->common.fex_valid = 0U;
+	conn->master.terminate_ack = 0U;
+
+	conn->llcp_req = conn->llcp_ack = conn->llcp_type = 0U;
+	conn->llcp_rx = NULL;
+	conn->llcp_cu.req = conn->llcp_cu.ack = 0;
+	conn->llcp_feature.req = conn->llcp_feature.ack = 0;
+	conn->llcp_feature.features_conn = LL_FEAT;
+	conn->llcp_feature.features_peer = 0;
+	conn->llcp_version.req = conn->llcp_version.ack = 0;
+	conn->llcp_version.tx = conn->llcp_version.rx = 0U;
+	conn->llcp_terminate.reason_peer = 0U;
+	/* NOTE: use allocated link for generating dedicated
+	 * terminate ind rx node
+	 */
+	conn->llcp_terminate.node_rx.hdr.link = link;
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+	conn_lll->enc_rx = conn_lll->enc_tx = 0U;
+	conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
+	conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
+	conn->llcp_enc.refresh = 0U;
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+	conn->llcp_conn_param.req = 0U;
+	conn->llcp_conn_param.ack = 0U;
+	conn->llcp_conn_param.disabled = 0U;
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
+	conn->llcp_length.req = conn->llcp_length.ack = 0U;
+	conn->llcp_length.disabled = 0U;
+	conn->llcp_length.cache.tx_octets = 0U;
+	conn->default_tx_octets = ull_conn_default_tx_octets_get();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	conn->default_tx_time = ull_conn_default_tx_time_get();
+#endif /* CONFIG_BT_CTLR_PHY */
+#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	conn->llcp_phy.req = conn->llcp_phy.ack = 0U;
+	conn->llcp_phy.disabled = 0U;
+	conn->llcp_phy.pause_tx = 0U;
+	conn->phy_pref_tx = ull_conn_default_phy_tx_get();
+	conn->phy_pref_rx = ull_conn_default_phy_rx_get();
+	conn->phy_pref_flags = 0U;
+#endif /* CONFIG_BT_CTLR_PHY */
+
+	conn->tx_head = conn->tx_ctrl = conn->tx_ctrl_last =
+	conn->tx_data = conn->tx_data_last = 0;
+
+	lll->conn = conn_lll;
+
+	ull_hdr_init(&conn->ull);
+	lll_hdr_init(&conn->lll, conn);
+
+conn_is_valid:
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	ull_filter_scan_update(filter_policy);
+
+	lll->rl_idx = FILTER_IDX_NONE;
+	lll->rpa_gen = 0;
+	if (!filter_policy && ull_filter_lll_rl_enabled()) {
+		/* Look up the resolving list */
+		lll->rl_idx = ull_filter_rl_find(peer_addr_type, peer_addr,
+						 NULL);
+	}
+
+	if (own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
+	    own_addr_type == BT_ADDR_LE_RANDOM_ID) {
+
+		/* Generate RPAs if required */
+		ull_filter_rpa_update(false);
+		own_addr_type &= 0x1;
+		lll->rpa_gen = 1;
+	}
+#endif
+
+	scan->own_addr_type = own_addr_type;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	return 0;
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	/* wait for stable clocks */
+	err = lll_clock_wait();
+	if (err) {
+		conn_release(scan);
+
+		return BT_HCI_ERR_HW_FAILURE;
+	}
+
+	return ull_scan_enable(scan);
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+uint8_t ll_connect_enable(uint8_t is_coded_included)
+{
+	uint8_t err = BT_HCI_ERR_CMD_DISALLOWED;
+	struct ll_scan_set *scan;
+
+	scan = ull_scan_set_get(SCAN_HANDLE_1M);
+
+	/* wait for stable clocks */
+	err = lll_clock_wait();
+	if (err) {
+		conn_release(scan);
+
+		return BT_HCI_ERR_HW_FAILURE;
+	}
+
+	if (!is_coded_included ||
+	    (scan->lll.phy & BIT(0))) {
+		err = ull_scan_enable(scan);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) && is_coded_included) {
+		scan = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
+		err = ull_scan_enable(scan);
+		if (err) {
+			return err;
+		}
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+
+uint8_t ll_connect_disable(void **rx)
+{
+	struct lll_conn *conn_lll;
+	struct ll_scan_set *scan;
+	uint8_t status;
+
+	scan = ull_scan_is_enabled_get(0);
+	if (!scan) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	conn_lll = scan->lll.conn;
+	if (!conn_lll) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	status = ull_scan_disable(0, scan);
+	if (!status) {
+		struct ll_conn *conn = (void *)HDR_LLL2EVT(conn_lll);
+		struct node_rx_ftr *ftr;
+		struct node_rx_pdu *cc;
+		memq_link_t *link;
+
+		cc = (void *)&conn->llcp_terminate.node_rx;
+		link = cc->hdr.link;
+		LL_ASSERT(link);
+
+		/* free the memq link early, as caller could overwrite it */
+		ll_rx_link_release(link);
+
+		cc->hdr.type = NODE_RX_TYPE_CONNECTION;
+		cc->hdr.handle = 0xffff;
+		*((uint8_t *)cc->pdu) = BT_HCI_ERR_UNKNOWN_CONN_ID;
+
+		ftr = &(cc->hdr.rx_ftr);
+		ftr->param = &scan->lll;
+
+		*rx = cc;
+	}
+
+	return status;
+}
+
+/* FIXME: Refactor out this interface so that its usable by extended
+ * advertising channel classification, and also master role connections can
+ * perform channel map update control procedure.
+ */
+uint8_t ll_chm_update(uint8_t const *const chm)
+{
+	uint16_t handle;
+	uint8_t ret;
+
+	ull_chan_map_set(chm);
+
+	handle = CONFIG_BT_MAX_CONN;
+	while (handle--) {
+		struct ll_conn *conn;
+
+		conn = ll_connected_get(handle);
+		if (!conn || conn->lll.role) {
+			continue;
+		}
+
+		ret = ull_conn_llcp_req(conn);
+		if (ret) {
+			return ret;
+		}
+
+		memcpy(conn->llcp.chan_map.chm, chm,
+		       sizeof(conn->llcp.chan_map.chm));
+		/* conn->llcp.chan_map.instant     = 0; */
+		conn->llcp.chan_map.initiate = 1U;
+
+		conn->llcp_type = LLCP_CHAN_MAP;
+		conn->llcp_req++;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+uint8_t ll_enc_req_send(uint16_t handle, uint8_t const *const rand,
+		     uint8_t const *const ediv, uint8_t const *const ltk)
+{
+	struct ll_conn *conn;
+	struct node_tx *tx;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if ((conn->llcp_enc.req != conn->llcp_enc.ack) ||
+	    ((conn->llcp_req != conn->llcp_ack) &&
+	     (conn->llcp_type == LLCP_ENCRYPTION))) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	tx = ll_tx_mem_acquire();
+	if (tx) {
+		struct pdu_data *pdu_data_tx;
+
+		pdu_data_tx = (void *)tx->pdu;
+
+		memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
+
+		if (!conn->lll.enc_rx && !conn->lll.enc_tx) {
+			struct pdu_data_llctrl_enc_req *enc_req;
+
+			pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
+			pdu_data_tx->len =
+				offsetof(struct pdu_data_llctrl, enc_rsp) +
+				sizeof(struct pdu_data_llctrl_enc_req);
+			pdu_data_tx->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_ENC_REQ;
+			enc_req = (void *)
+				&pdu_data_tx->llctrl.enc_req;
+			memcpy(enc_req->rand, rand, sizeof(enc_req->rand));
+			enc_req->ediv[0] = ediv[0];
+			enc_req->ediv[1] = ediv[1];
+			lll_csrand_get(enc_req->skdm, sizeof(enc_req->skdm));
+			lll_csrand_get(enc_req->ivm, sizeof(enc_req->ivm));
+		} else if (conn->lll.enc_rx && conn->lll.enc_tx) {
+			memcpy(&conn->llcp_enc.rand[0], rand,
+			       sizeof(conn->llcp_enc.rand));
+
+			conn->llcp_enc.ediv[0] = ediv[0];
+			conn->llcp_enc.ediv[1] = ediv[1];
+
+			pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
+			pdu_data_tx->len = offsetof(struct pdu_data_llctrl,
+						    enc_req);
+			pdu_data_tx->llctrl.opcode =
+				PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ;
+		} else {
+			ll_tx_mem_release(tx);
+
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		if (ll_tx_mem_enqueue(handle, tx)) {
+			ll_tx_mem_release(tx);
+
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		conn->llcp_enc.req++;
+
+		return 0;
+	}
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
+		      struct node_rx_ftr *ftr, struct lll_conn *lll)
+{
+	uint32_t conn_offset_us, conn_interval_us;
+	uint8_t ticker_id_scan, ticker_id_conn;
+	uint8_t peer_addr[BDADDR_SIZE];
+	uint32_t ticks_slot_overhead;
+	struct ll_scan_set *scan;
+	uint32_t ticks_slot_offset;
+	struct pdu_adv *pdu_tx;
+	struct node_rx_cc *cc;
+	struct ll_conn *conn;
+	uint32_t ready_delay_us;
+	uint8_t peer_addr_type;
+	uint32_t ticker_status;
+	uint8_t chan_sel;
+
+	((struct lll_scan *)ftr->param)->conn = NULL;
+
+	scan = ((struct lll_scan *)ftr->param)->hdr.parent;
+	conn = lll->hdr.parent;
+
+	pdu_tx = (void *)((struct node_rx_pdu *)rx)->pdu;
+
+	peer_addr_type = pdu_tx->rx_addr;
+	memcpy(peer_addr, &pdu_tx->connect_ind.adv_addr[0], BDADDR_SIZE);
+
+	/* This is the chan sel bit from the received adv pdu */
+	chan_sel = pdu_tx->chan_sel;
+
+	cc = (void *)pdu_tx;
+	cc->status = 0U;
+	cc->role = 0U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx = ftr->rl_idx;
+
+	if (ftr->lrpa_used) {
+		memcpy(&cc->local_rpa[0], &pdu_tx->connect_ind.init_addr[0],
+		       BDADDR_SIZE);
+	} else {
+		memset(&cc->local_rpa[0], 0x0, BDADDR_SIZE);
+	}
+
+	if (rl_idx != FILTER_IDX_NONE) {
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &cc->peer_addr_type,
+				  &cc->peer_addr[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		cc->peer_addr_type += 2;
+
+		/* Store peer RPA */
+		memcpy(&cc->peer_rpa[0], &peer_addr[0], BDADDR_SIZE);
+	} else {
+		memset(&cc->peer_rpa[0], 0x0, BDADDR_SIZE);
+#else
+	if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		cc->peer_addr_type = peer_addr_type;
+		memcpy(cc->peer_addr, &peer_addr[0], BDADDR_SIZE);
+	}
+
+	cc->interval = lll->interval;
+	cc->latency = lll->latency;
+	cc->timeout = scan->lll.conn_timeout;
+	cc->sca = lll_clock_sca_local_get();
+
+	lll->handle = ll_conn_handle_get(conn);
+	rx->handle = lll->handle;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	/* Use Channel Selection Algorithm #2 if peer too supports it */
+	if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+		struct node_rx_pdu *rx_csa;
+		struct node_rx_cs *cs;
+
+		/* pick the rx node instance stored within the connection
+		 * rx node.
+		 */
+		rx_csa = (void *)ftr->extra;
+
+		/* Enqueue the connection event */
+		ll_rx_put(link, rx);
+
+		/* use the rx node for CSA event */
+		rx = (void *)rx_csa;
+		link = rx->link;
+
+		rx->handle = lll->handle;
+		rx->type = NODE_RX_TYPE_CHAN_SEL_ALGO;
+
+		cs = (void *)rx_csa->pdu;
+
+		if (chan_sel) {
+			uint16_t aa_ls = ((uint16_t)lll->access_addr[1] << 8) |
+				      lll->access_addr[0];
+			uint16_t aa_ms = ((uint16_t)lll->access_addr[3] << 8) |
+				      lll->access_addr[2];
+
+			lll->data_chan_sel = 1;
+			lll->data_chan_id = aa_ms ^ aa_ls;
+
+			cs->csa = 0x01;
+		} else {
+			cs->csa = 0x00;
+		}
+	}
+
+	ll_rx_put(link, rx);
+	ll_rx_sched();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	ready_delay_us = lll_radio_tx_ready_delay_get(lll->phy_tx,
+						      lll->phy_flags);
+#else
+	ready_delay_us = lll_radio_tx_ready_delay_get(0, 0);
+#endif
+
+	/* TODO: active_to_start feature port */
+	conn->evt.ticks_active_to_start = 0U;
+	conn->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	conn->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	conn->evt.ticks_slot =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
+				       ready_delay_us +
+				       328 + EVENT_IFS_US + 328);
+
+	ticks_slot_offset = MAX(conn->evt.ticks_active_to_start,
+				conn->evt.ticks_xtal_to_start);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = ticks_slot_offset;
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	conn_interval_us = lll->interval * 1250;
+	conn_offset_us = ftr->radio_end_us;
+	conn_offset_us += HAL_TICKER_TICKS_TO_US(1);
+	conn_offset_us -= EVENT_OVERHEAD_START_US;
+	conn_offset_us -= ready_delay_us;
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* disable ticker job, in order to chain stop and start to avoid RTC
+	 * being stopped if no tickers active.
+	 */
+	mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0);
+#endif
+
+	/* Stop Scanner */
+	ticker_id_scan = TICKER_ID_SCAN_BASE + ull_scan_handle_get(scan);
+	ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
+				    TICKER_USER_ID_ULL_HIGH,
+				    ticker_id_scan, ticker_op_stop_scan_cb,
+				    (void *)(uint32_t)ticker_id_scan);
+	ticker_op_stop_scan_cb(ticker_status, (void *)(uint32_t)ticker_id_scan);
+
+	/* Scanner stop can expire while here in this ISR.
+	 * Deferred attempt to stop can fail as it would have
+	 * expired, hence ignore failure.
+	 */
+	ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+		    TICKER_ID_SCAN_STOP, NULL, NULL);
+
+	/* Start master */
+	ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn);
+	ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR,
+				     TICKER_USER_ID_ULL_HIGH,
+				     ticker_id_conn,
+				     ftr->ticks_anchor - ticks_slot_offset,
+				     HAL_TICKER_US_TO_TICKS(conn_offset_us),
+				     HAL_TICKER_US_TO_TICKS(conn_interval_us),
+				     HAL_TICKER_REMAINDER(conn_interval_us),
+				     TICKER_NULL_LAZY,
+				     (conn->evt.ticks_slot +
+				      ticks_slot_overhead),
+				     ull_master_ticker_cb, conn, ticker_op_cb,
+				     (void *)__LINE__);
+	LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+		  (ticker_status == TICKER_STATUS_BUSY));
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* enable ticker job, irrespective of disabled in this function so
+	 * first connection event can be scheduled as soon as possible.
+	 */
+	mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1);
+#endif
+}
+
+void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			  void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_master_prepare};
+	static struct lll_prepare_param p;
+	struct ll_conn *conn;
+	uint32_t err;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_M(1);
+
+	conn = param;
+
+	/* Check if stopping ticker (on disconnection, race with ticker expiry)
+	 */
+	if (unlikely(conn->lll.handle == 0xFFFF)) {
+		DEBUG_RADIO_CLOSE_M(0);
+		return;
+	}
+
+	/* If this is a must-expire callback, LLCP state machine does not need
+	 * to know. Will be called with lazy > 0 when scheduled in air.
+	 */
+	if (!IS_ENABLED(CONFIG_BT_CTLR_CONN_META) ||
+	    (lazy != TICKER_LAZY_MUST_EXPIRE)) {
+		int ret;
+
+		/* Handle any LL Control Procedures */
+		ret = ull_conn_llcp(conn, ticks_at_expire, lazy);
+		if (ret) {
+			DEBUG_RADIO_CLOSE_M(0);
+			return;
+		}
+	}
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&conn->ull);
+	LL_ASSERT(ref);
+
+	/* De-mux 2 tx node from FIFO, sufficient to be able to set MD bit */
+	ull_conn_tx_demux(2);
+
+	/* Enqueue towards LLL */
+	ull_conn_tx_lll_enqueue(conn, 2);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = &conn->lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!err);
+
+	/* De-mux remaining tx nodes from FIFO */
+	ull_conn_tx_demux(UINT8_MAX);
+
+	/* Enqueue towards LLL */
+	ull_conn_tx_lll_enqueue(conn, UINT8_MAX);
+
+	DEBUG_RADIO_PREPARE_M(1);
+}
+
+static void ticker_op_stop_scan_cb(uint32_t status, void *params)
+{
+	/* TODO: */
+}
+
+static void ticker_op_cb(uint32_t status, void *params)
+{
+	ARG_UNUSED(params);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static inline void conn_release(struct ll_scan_set *scan)
+{
+	struct lll_conn *lll = scan->lll.conn;
+	struct node_rx_pdu *cc;
+	struct ll_conn *conn;
+	memq_link_t *link;
+
+	LL_ASSERT(!lll->link_tx_free);
+	link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail);
+	LL_ASSERT(link);
+	lll->link_tx_free = link;
+
+	conn = (void *)HDR_LLL2EVT(lll);
+
+	cc = (void *)&conn->llcp_terminate.node_rx;
+	link = cc->hdr.link;
+	LL_ASSERT(link);
+
+	ll_rx_link_release(link);
+
+	ll_conn_release(conn);
+	scan->lll.conn = NULL;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_master_internal.h	(working copy)
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx,
+		      struct node_rx_ftr *ftr, struct lll_conn *lll);
+void ull_master_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+			  void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan.c	(working copy)
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2016-2019 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_adv.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+#include "lll_filter.h"
+
+#include "ull_adv_types.h"
+#include "ull_scan_types.h"
+#include "ull_filter.h"
+
+#include "ull_internal.h"
+#include "ull_adv_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_sched_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_scan
+#include "common/log.h"
+#include "hal/debug.h"
+
+static int init_reset(void);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+		      void *param);
+static uint8_t disable(uint8_t handle);
+
+static struct ll_scan_set ll_scan[BT_CTLR_SCAN_SET];
+
+uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window,
+			uint8_t own_addr_type, uint8_t filter_policy)
+{
+	struct ll_scan_set *scan;
+	struct lll_scan *lll;
+
+	scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
+	if (!scan) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	uint8_t phy;
+
+	phy  = type >> 1;
+	if (phy & BT_HCI_LE_EXT_SCAN_PHY_CODED) {
+		struct ll_scan_set *scan_coded;
+
+		if (!IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
+		if (!scan_coded) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		scan = scan_coded;
+	}
+
+	lll = &scan->lll;
+
+	if (!interval) {
+		lll->phy = 0U;
+
+		return 0;
+	}
+
+	lll->phy = phy;
+
+#else /* !CONFIG_BT_CTLR_ADV_EXT */
+	lll = &scan->lll;
+#endif /* !CONFIG_BT_CTLR_ADV_EXT */
+
+	scan->own_addr_type = own_addr_type;
+
+	ull_scan_params_set(lll, type, interval, window, filter_policy);
+
+	return 0;
+}
+
+uint8_t ll_scan_enable(uint8_t enable)
+{
+	struct ll_scan_set *scan_coded = NULL;
+	struct ll_scan_set *scan;
+	uint8_t own_addr_type = 0U;
+	uint8_t is_coded_phy = 0U;
+	uint8_t err;
+
+	if (!enable) {
+		err = disable(SCAN_HANDLE_1M);
+
+		if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
+		    IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+			uint8_t err_coded;
+
+			err_coded = disable(SCAN_HANDLE_PHY_CODED);
+			if (!err_coded) {
+				err = 0U;
+			}
+		}
+
+		return err;
+	}
+
+	scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
+	if (!scan) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
+	scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
+	if (!scan_coded) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	own_addr_type = scan_coded->own_addr_type;
+	is_coded_phy = (scan_coded->lll.phy &
+			BT_HCI_LE_EXT_SCAN_PHY_CODED);
+#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && is_coded_phy &&
+	    ((own_addr_type & 0x1) ||
+	     (scan->own_addr_type & 0x1))) {
+		if (!mem_nz(ll_addr_get(1, NULL), BDADDR_SIZE)) {
+			return BT_HCI_ERR_INVALID_PARAM;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	struct lll_scan *lll;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && is_coded_phy) {
+		lll = &scan_coded->lll;
+
+		/* TODO: Privacy support in Advertising Extensions */
+	} else {
+		lll = &scan->lll;
+		own_addr_type = scan->own_addr_type;
+	}
+
+	ull_filter_scan_update(lll->filter_policy);
+
+	lll->rl_idx = FILTER_IDX_NONE;
+	lll->rpa_gen = 0;
+
+	if ((lll->type & 0x1) &&
+	    (own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
+	     own_addr_type == BT_ADDR_LE_RANDOM_ID)) {
+		/* Generate RPAs if required */
+		ull_filter_rpa_update(false);
+		lll->rpa_gen = 1;
+	}
+#endif
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_PHY_CODED)
+	if (!is_coded_phy || (scan->lll.phy & BT_HCI_LE_EXT_SCAN_PHY_1M))
+#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_CTLR_PHY_CODED */
+	{
+		err = ull_scan_enable(scan);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
+	    is_coded_phy) {
+		err = ull_scan_enable(scan_coded);
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+int ull_scan_init(void)
+{
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
+		err = ull_scan_aux_init();
+		if (err) {
+			return err;
+		}
+	}
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_scan_reset(void)
+{
+	uint8_t handle;
+	int err;
+
+	for (handle = 0U; handle < BT_CTLR_SCAN_SET; handle++) {
+		(void)disable(handle);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
+		err = ull_scan_aux_reset();
+		if (err) {
+			return err;
+		}
+	}
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void ull_scan_params_set(struct lll_scan *lll, uint8_t type, uint16_t interval,
+			 uint16_t window, uint8_t filter_policy)
+{
+	/* type value:
+	 * 0000b - legacy 1M passive
+	 * 0001b - legacy 1M active
+	 * 0010b - Ext. 1M passive
+	 * 0011b - Ext. 1M active
+	 * 0100b - invalid
+	 * 0101b - invalid
+	 * 0110b - invalid
+	 * 0111b - invalid
+	 * 1000b - Ext. Coded passive
+	 * 1001b - Ext. Coded active
+	 */
+	lll->type = type;
+	lll->filter_policy = filter_policy;
+	lll->interval = interval;
+	lll->ticks_window = HAL_TICKER_US_TO_TICKS((uint64_t)window * 625U);
+}
+
+uint8_t ull_scan_enable(struct ll_scan_set *scan)
+{
+	struct lll_scan *lll = &scan->lll;
+	uint32_t ticks_slot_overhead;
+	uint32_t volatile ret_cb;
+	uint32_t ticks_interval;
+	uint32_t ticks_anchor;
+	uint32_t ret;
+
+	lll->chan = 0;
+	lll->init_addr_type = scan->own_addr_type;
+	ll_addr_get(lll->init_addr_type, lll->init_addr);
+
+	ull_hdr_init(&scan->ull);
+	lll_hdr_init(lll, scan);
+
+	ticks_interval = HAL_TICKER_US_TO_TICKS((uint64_t)lll->interval * 625U);
+
+	/* TODO: active_to_start feature port */
+	scan->evt.ticks_active_to_start = 0U;
+	scan->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	scan->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	if ((lll->ticks_window +
+	     HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US)) <
+	    (ticks_interval -
+	     HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US))) {
+		scan->evt.ticks_slot =
+			(lll->ticks_window +
+			 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US));
+	} else {
+		if (IS_ENABLED(CONFIG_BT_CTLR_SCAN_UNRESERVED)) {
+			scan->evt.ticks_slot = 0U;
+		} else {
+			scan->evt.ticks_slot = ticks_interval -
+				HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+		}
+
+		lll->ticks_window = 0U;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = MAX(scan->evt.ticks_active_to_start,
+					  scan->evt.ticks_xtal_to_start);
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	ticks_anchor = ticker_ticks_now_get();
+
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
+	if (!lll->conn) {
+		uint32_t ticks_ref = 0U;
+		uint32_t offset_us = 0U;
+
+		ull_sched_after_mstr_slot_get(TICKER_USER_ID_THREAD,
+					      (scan->evt.ticks_slot +
+					       ticks_slot_overhead),
+					      &ticks_ref, &offset_us);
+
+		/* Use the ticks_ref as scanner's anchor if a free time space
+		 * after any master role is available (indicated by a non-zero
+		 * offset_us value).
+		 */
+		if (offset_us) {
+			ticks_anchor = ticks_ref +
+				       HAL_TICKER_US_TO_TICKS(offset_us);
+		}
+	}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */
+
+	uint8_t handle = ull_scan_handle_get(scan);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+			   TICKER_USER_ID_THREAD, TICKER_ID_SCAN_BASE + handle,
+			   ticks_anchor, 0, ticks_interval,
+			   HAL_TICKER_REMAINDER((uint64_t)lll->interval * 625U),
+			   TICKER_NULL_LAZY,
+			   (scan->evt.ticks_slot + ticks_slot_overhead),
+			   ticker_cb, scan,
+			   ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret != TICKER_STATUS_SUCCESS) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	scan->is_enabled = 1U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#if defined(CONFIG_BT_BROADCASTER)
+	if (!ull_adv_is_enabled_get(0))
+#endif
+	{
+		ull_filter_adv_scan_state_cb(BIT(1));
+	}
+#endif
+
+	return 0;
+}
+
+uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan)
+{
+	uint32_t volatile ret_cb;
+	void *mark;
+	uint32_t ret;
+
+	mark = ull_disable_mark(scan);
+	LL_ASSERT(mark == scan);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_SCAN_BASE + handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret) {
+		mark = ull_disable_unmark(scan);
+		LL_ASSERT(mark == scan);
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	ret = ull_disable(&scan->lll);
+	LL_ASSERT(!ret);
+
+	mark = ull_disable_unmark(scan);
+	LL_ASSERT(mark == scan);
+
+	return 0;
+}
+
+struct ll_scan_set *ull_scan_set_get(uint8_t handle)
+{
+	if (handle >= BT_CTLR_SCAN_SET) {
+		return NULL;
+	}
+
+	return &ll_scan[handle];
+}
+
+uint8_t ull_scan_handle_get(struct ll_scan_set *scan)
+{
+	return ((uint8_t *)scan - (uint8_t *)ll_scan) / sizeof(*scan);
+}
+
+uint8_t ull_scan_lll_handle_get(struct lll_scan *lll)
+{
+	return ull_scan_handle_get((void *)lll->hdr.parent);
+}
+
+struct ll_scan_set *ull_scan_is_enabled_get(uint8_t handle)
+{
+	struct ll_scan_set *scan;
+
+	scan = ull_scan_set_get(handle);
+	if (!scan || !scan->is_enabled) {
+		return NULL;
+	}
+
+	return scan;
+}
+
+struct ll_scan_set *ull_scan_is_disabled_get(uint8_t handle)
+{
+	struct ll_scan_set *scan;
+
+	scan = ull_scan_set_get(handle);
+	if (!scan || scan->is_enabled) {
+		return NULL;
+	}
+
+	return scan;
+}
+
+uint32_t ull_scan_is_enabled(uint8_t handle)
+{
+	struct ll_scan_set *scan;
+
+	scan = ull_scan_is_enabled_get(handle);
+	if (!scan) {
+		return 0;
+	}
+
+	/* NOTE: BIT(0) - passive scanning enabled
+	 *       BIT(1) - active scanning enabled
+	 *       BIT(2) - initiator enabled
+	 */
+	return (((uint32_t)scan->is_enabled << scan->lll.type) |
+#if defined(CONFIG_BT_CENTRAL)
+		(scan->lll.conn ? BIT(2) : 0) |
+#endif
+		0);
+}
+
+uint32_t ull_scan_filter_pol_get(uint8_t handle)
+{
+	struct ll_scan_set *scan;
+
+	scan = ull_scan_is_enabled_get(handle);
+	if (!scan) {
+		return 0;
+	}
+
+	return scan->lll.filter_policy;
+}
+
+static int init_reset(void)
+{
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) && \
+	!defined(CONFIG_BT_CTLR_ADV_EXT)
+	ll_scan[0].lll.tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL && !CONFIG_BT_CTLR_ADV_EXT */
+
+	return 0;
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
+		      void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_scan_prepare};
+	static struct lll_prepare_param p;
+	struct ll_scan_set *scan = param;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_O(1);
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&scan->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = &scan->lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!ret);
+
+	DEBUG_RADIO_PREPARE_O(1);
+}
+
+static uint8_t disable(uint8_t handle)
+{
+	struct ll_scan_set *scan;
+	uint8_t ret;
+
+	scan = ull_scan_is_enabled_get(handle);
+	if (!scan) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+#if defined(CONFIG_BT_CENTRAL)
+	if (scan->lll.conn) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+#endif
+
+	ret = ull_scan_disable(handle, scan);
+	if (ret) {
+		return ret;
+	}
+
+	scan->is_enabled = 0U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+#if defined(CONFIG_BT_BROADCASTER)
+	if (!ull_adv_is_enabled_get(0))
+#endif
+	{
+		ull_filter_adv_scan_state_cb(0);
+	}
+#endif
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_aux.c	(working copy)
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "hal/ticker.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_scan.h"
+#include "lll_scan_aux.h"
+#include "lll_sync.h"
+
+#include "ull_scan_types.h"
+#include "ull_sync_types.h"
+
+#include "ull_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_sync_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_scan_aux
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static inline struct ll_scan_aux_set *aux_acquire(void);
+static inline void aux_release(struct ll_scan_aux_set *aux);
+static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux);
+static void flush(struct ll_scan_aux_set *aux, struct node_rx_hdr *rx);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param);
+static void ticker_op_cb(uint32_t status, void *param);
+static void ticker_op_aux_failure(void *param);
+
+static struct ll_scan_aux_set ll_scan_aux_pool[CONFIG_BT_CTLR_SCAN_AUX_SET];
+static void *scan_aux_free;
+
+int ull_scan_aux_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_scan_aux_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx, uint8_t phy)
+{
+	struct pdu_adv_aux_ptr *aux_ptr;
+	struct pdu_adv_com_ext_adv *p;
+	uint32_t ticks_slot_overhead;
+	struct ll_scan_aux_set *aux;
+	uint32_t window_widening_us;
+	uint32_t ticks_slot_offset;
+	struct ll_scan_set *scan;
+	struct ll_sync_set *sync;
+	struct lll_scan_aux *lll;
+	struct pdu_adv_adi *adi;
+	struct node_rx_ftr *ftr;
+	uint32_t ready_delay_us;
+	uint32_t aux_offset_us;
+	uint32_t ticker_status;
+	struct pdu_adv_hdr *h;
+	struct pdu_adv *pdu;
+	uint8_t aux_handle;
+	uint8_t *ptr;
+
+	ftr = &rx->rx_ftr;
+	lll = ftr->param;
+	aux = (void *)HDR_LLL2EVT(lll);
+	if (((uint8_t *)aux < (uint8_t *)ll_scan_aux_pool) ||
+	    ((uint8_t *)aux > ((uint8_t *)ll_scan_aux_pool +
+			    (sizeof(struct ll_scan_aux_set) *
+			     (CONFIG_BT_CTLR_SCAN_AUX_SET - 1))))) {
+		/* NOTE: We are most probably ADV_EXT_IND on primary channel */
+		aux = NULL;
+	}
+
+	scan = NULL;
+	sync = NULL;
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	if (aux) {
+		struct lll_scan *lll_scan;
+
+		lll_scan = aux->rx_head->rx_ftr.param;
+		scan = (void *)HDR_LLL2EVT(lll_scan);
+	} else {
+		scan = (void *)HDR_LLL2EVT(ftr->param);
+	}
+
+	sync = scan->per_scan.sync;
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+	rx->link = link;
+	ftr->extra = NULL;
+
+	pdu = (void *)((struct node_rx_pdu *)rx)->pdu;
+	p = (void *)&pdu->adv_ext_ind;
+	if (!p->ext_hdr_len) {
+		goto ull_scan_aux_rx_flush;
+	}
+
+	h = (void *)p->ext_hdr_adi_adv_data;
+	if (!h->aux_ptr && !sync) {
+		goto ull_scan_aux_rx_flush;
+	}
+
+	ptr = (uint8_t *)h + sizeof(*h);
+
+	if (h->adv_addr) {
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+		if (sync && (pdu->tx_addr == scan->per_scan.adv_addr_type) &&
+		    !memcmp(ptr, scan->per_scan.adv_addr, BDADDR_SIZE)) {
+			scan->per_scan.state = LL_SYNC_STATE_ADDR_MATCH;
+		}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+		ptr += BDADDR_SIZE;
+	}
+
+	if (h->tgt_addr) {
+		ptr += BDADDR_SIZE;
+	}
+
+	adi = NULL;
+	if (h->adi) {
+		adi = (void *)ptr;
+		ptr += sizeof(*adi);
+	}
+
+	aux_ptr = NULL;
+	if (h->aux_ptr) {
+		aux_ptr = (void *)ptr;
+		ptr += sizeof(*aux_ptr);
+	}
+
+	if (h->sync_info) {
+		struct pdu_adv_sync_info *si;
+
+		si = (void *)ptr;
+		ptr += sizeof(*si);
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+		if (sync && adi && (adi->sid == scan->per_scan.sid) &&
+		    (scan->per_scan.state == LL_SYNC_STATE_ADDR_MATCH)) {
+			ull_sync_setup(scan, aux, rx, si);
+		}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+	}
+
+	if (!aux_ptr || !aux_ptr->offs) {
+		goto ull_scan_aux_rx_flush;
+	}
+
+	if (!aux) {
+		aux = aux_acquire();
+		if (!aux) {
+			goto ull_scan_aux_rx_flush;
+		}
+
+		aux->rx_last = NULL;
+		lll = &aux->lll;
+
+		ull_hdr_init(&aux->ull);
+		lll_hdr_init(lll, aux);
+	}
+
+	/* Enqueue the rx in aux context */
+	if (aux->rx_last) {
+		ftr = &aux->rx_last->rx_ftr;
+		ftr->extra = rx;
+	} else {
+		aux->rx_head = rx;
+	}
+	aux->rx_last = rx;
+
+	lll->chan = aux_ptr->chan_idx;
+	lll->phy = BIT(aux_ptr->phy);
+
+	aux_offset_us = ftr->radio_end_us - PKT_AC_US(pdu->len, 0, phy);
+	if (aux_ptr->offs_units) {
+		lll->window_size_us = 300U;
+	} else {
+		lll->window_size_us = 30U;
+	}
+	aux_offset_us += (uint32_t)aux_ptr->offs * lll->window_size_us;
+
+	if (aux_ptr->ca) {
+		window_widening_us = aux_offset_us / 2000U;
+	} else {
+		window_widening_us = aux_offset_us / 20000U;
+	}
+
+	lll->window_size_us += (EVENT_TICKER_RES_MARGIN_US +
+				((EVENT_JITTER_US + window_widening_us) << 1));
+
+	ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, 1);
+
+	aux_offset_us -= EVENT_OVERHEAD_START_US;
+	aux_offset_us -= EVENT_JITTER_US;
+	aux_offset_us -= ready_delay_us;
+	aux_offset_us -= window_widening_us;
+
+	/* TODO: active_to_start feature port */
+	aux->evt.ticks_active_to_start = 0;
+	aux->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	aux->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	aux->evt.ticks_slot =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
+				       ready_delay_us +
+				       PKT_AC_US(PDU_AC_EXT_PAYLOAD_SIZE_MAX,
+						 0, lll->phy) +
+				       EVENT_OVERHEAD_END_US);
+
+	ticks_slot_offset = MAX(aux->evt.ticks_active_to_start,
+				aux->evt.ticks_xtal_to_start);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = ticks_slot_offset;
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	/* TODO: unreserve the primary scan window ticks in ticker */
+
+	aux_handle = aux_handle_get(aux);
+
+	ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR,
+				     TICKER_USER_ID_ULL_HIGH,
+				     TICKER_ID_SCAN_AUX_BASE + aux_handle,
+				     ftr->ticks_anchor - ticks_slot_offset,
+				     HAL_TICKER_US_TO_TICKS(aux_offset_us),
+				     TICKER_NULL_PERIOD,
+				     TICKER_NULL_REMAINDER,
+				     TICKER_NULL_LAZY,
+				     (aux->evt.ticks_slot +
+				      ticks_slot_overhead),
+				     ticker_cb, aux, ticker_op_cb, aux);
+	LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+		  (ticker_status == TICKER_STATUS_BUSY));
+
+	return;
+
+ull_scan_aux_rx_flush:
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	if (sync) {
+		scan->per_scan.state = LL_SYNC_STATE_IDLE;
+	}
+#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
+
+	if (aux) {
+		flush(aux, rx);
+
+		return;
+	}
+
+	ll_rx_put(link, rx);
+	ll_rx_sched();
+}
+
+void ull_scan_aux_done(struct node_rx_event_done *done)
+{
+	struct lll_scan_aux *lll = (void *)HDR_ULL2LLL(done->param);
+	struct ll_scan_aux_set *aux = (void *)HDR_LLL2EVT(lll);
+
+	flush(aux, NULL);
+}
+
+uint8_t ull_scan_aux_lll_handle_get(struct lll_scan_aux *lll)
+{
+	return aux_handle_get((void *)lll->hdr.parent);
+}
+
+static int init_reset(void)
+{
+	/* Initialize adv aux pool. */
+	mem_init(ll_scan_aux_pool, sizeof(struct ll_scan_aux_set),
+		 sizeof(ll_scan_aux_pool) / sizeof(struct ll_scan_aux_set),
+		 &scan_aux_free);
+
+	return 0;
+}
+
+static inline struct ll_scan_aux_set *aux_acquire(void)
+{
+	return mem_acquire(&scan_aux_free);
+}
+
+static inline void aux_release(struct ll_scan_aux_set *aux)
+{
+	mem_release(aux, &scan_aux_free);
+}
+
+static inline uint8_t aux_handle_get(struct ll_scan_aux_set *aux)
+{
+	return mem_index_get(aux, ll_scan_aux_pool,
+			     sizeof(struct ll_scan_aux_set));
+}
+
+static void flush(struct ll_scan_aux_set *aux, struct node_rx_hdr *rx)
+{
+	if (aux->rx_last) {
+		if (rx) {
+			struct node_rx_ftr *ftr;
+
+			ftr = &aux->rx_last->rx_ftr;
+			ftr->extra = rx;
+		}
+
+		rx = aux->rx_head;
+
+		ll_rx_put(rx->link, rx);
+		ll_rx_sched();
+	} else if (rx) {
+		ll_rx_put(rx->link, rx);
+		ll_rx_sched();
+	}
+
+	aux_release(aux);
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_scan_aux_prepare};
+	struct ll_scan_aux_set *aux = param;
+	static struct lll_prepare_param p;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_O(1);
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&aux->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = 0; /* FIXME: remainder; */
+	p.lazy = lazy;
+	p.param = &aux->lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!ret);
+
+	DEBUG_RADIO_PREPARE_O(1);
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, ticker_op_aux_failure};
+	uint32_t ret;
+
+	if (status == TICKER_STATUS_SUCCESS) {
+		return;
+	}
+
+	mfy.param = param;
+
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH,
+			     0, &mfy);
+	LL_ASSERT(!ret);
+}
+
+static void ticker_op_aux_failure(void *param)
+{
+	flush(param, NULL);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_internal.h	(working copy)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* NOTE: Definitions used internal to ULL implementations */
+
+#define SCAN_HANDLE_1M        0
+#define SCAN_HANDLE_PHY_CODED 1
+
+int ull_scan_init(void);
+int ull_scan_reset(void);
+
+/* Set scan parameters */
+void ull_scan_params_set(struct lll_scan *lll, uint8_t type, uint16_t interval,
+			 uint16_t window, uint8_t filter_policy);
+
+/* Enable and start scanning/initiating role */
+uint8_t ull_scan_enable(struct ll_scan_set *scan);
+
+/* Disable scanning/initiating role */
+uint8_t ull_scan_disable(uint8_t handle, struct ll_scan_set *scan);
+
+/* Return ll_scan_set context (unconditional) */
+struct ll_scan_set *ull_scan_set_get(uint8_t handle);
+
+/* Return the scan set handle given the scan set instance */
+uint8_t ull_scan_handle_get(struct ll_scan_set *scan);
+
+/* Return ll_scan_set context if enabled */
+struct ll_scan_set *ull_scan_is_enabled_get(uint8_t handle);
+
+/* Return ll_scan_set contesst if disabled */
+struct ll_scan_set *ull_scan_is_disabled_get(uint8_t handle);
+
+/* Return flags if enabled */
+uint32_t ull_scan_is_enabled(uint8_t handle);
+
+/* Return filter policy used */
+uint32_t ull_scan_filter_pol_get(uint8_t handle);
+
+int ull_scan_aux_init(void);
+int ull_scan_aux_reset(void);
+
+/* Helper to setup scanning on auxiliary channel */
+void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx, uint8_t phy);
+
+/* Helper to clean up auxiliary channel scanning */
+void ull_scan_aux_done(struct node_rx_event_done *done);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_types.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_types.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_scan_types.h	(working copy)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct ll_scan_set {
+	struct evt_hdr  evt;
+	struct ull_hdr  ull;
+	struct lll_scan lll;
+
+	uint8_t is_enabled:1;
+	uint8_t own_addr_type:2;
+
+#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC)
+	struct {
+		uint8_t sid;
+
+		uint8_t adv_addr_type:1;
+		uint8_t filter_policy:1;
+		uint8_t state:2;
+
+		uint8_t adv_addr[BDADDR_SIZE];
+
+		struct node_rx_hdr *node_rx_estab;
+
+		/* Non-Null when creating sync, reset in ISR context on
+		 * synchronisation state and checked in Thread context when
+		 * cancelling sync create, hence the volatile keyword.
+		 */
+		struct ll_sync_set *volatile sync;
+	} per_scan;
+#endif
+};
+
+struct ll_scan_aux_set {
+	struct evt_hdr      evt;
+	struct ull_hdr      ull;
+	struct lll_scan_aux lll;
+
+	struct node_rx_hdr *rx_head;
+	struct node_rx_hdr *rx_last;
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched.c	(working copy)
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <toolchain.h>
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_scan.h"
+#include "lll_conn.h"
+
+#include "ull_scan_types.h"
+#include "ull_conn_types.h"
+
+#include "ull_internal.h"
+#include "ull_conn_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_sched
+#include "common/log.h"
+#include "hal/debug.h"
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
+			    uint32_t *ticks_to_offset_next,
+			    uint16_t conn_interval, uint8_t *offset_max,
+			    uint8_t *win_offset);
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+static void after_mstr_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
+				  uint32_t ticks_anchor,
+				  uint32_t *win_offset_us);
+static void ticker_op_cb(uint32_t status, void *param);
+
+void ull_sched_after_mstr_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
+				   uint32_t *ticks_anchor, uint32_t *us_offset)
+{
+	uint32_t ticks_to_expire_prev;
+	uint32_t ticks_slot_abs_prev;
+	uint32_t ticks_to_expire;
+	uint8_t ticker_id_prev;
+	uint8_t ticker_id;
+
+	ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_JITTER_US << 3);
+
+	ticker_id = ticker_id_prev = 0xff;
+	ticks_to_expire = ticks_to_expire_prev = *us_offset = 0U;
+	ticks_slot_abs_prev = 0U;
+	while (1) {
+		uint32_t volatile ret_cb;
+		struct ll_conn *conn;
+		uint32_t ret;
+
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id,
+					   &ticker_id, ticks_anchor,
+					   &ticks_to_expire, ticker_op_cb,
+					   (void *)&ret_cb);
+		if (ret == TICKER_STATUS_BUSY) {
+			while (ret_cb == TICKER_STATUS_BUSY) {
+				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
+						 user_id);
+			}
+		}
+
+		LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
+
+		if (ticker_id == 0xff) {
+			break;
+		}
+
+		if ((ticker_id < TICKER_ID_CONN_BASE) ||
+		    (ticker_id > TICKER_ID_CONN_LAST)) {
+			continue;
+		}
+
+		conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
+		if (conn && !conn->lll.role) {
+			uint32_t ticks_to_expire_normal = ticks_to_expire;
+			uint32_t ticks_slot_abs_curr = 0;
+#if defined(CONFIG_BT_CTLR_LOW_LAT)
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+			if (conn->evt.ticks_xtal_to_start & XON_BITMASK) {
+				uint32_t ticks_prepare_to_start =
+					MAX(conn->evt.ticks_active_to_start,
+					    conn->evt.ticks_preempt_to_start);
+
+				ticks_slot_abs_curr =
+					conn->evt.ticks_xtal_to_start &
+					~XON_BITMASK;
+				ticks_to_expire_normal -=
+					ticks_slot_abs_curr -
+					ticks_prepare_to_start;
+			} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+			{
+				uint32_t ticks_prepare_to_start =
+					MAX(conn->evt.ticks_active_to_start,
+					    conn->evt.ticks_xtal_to_start);
+
+				ticks_slot_abs_curr = ticks_prepare_to_start;
+			}
+#endif
+
+			ticks_slot_abs_curr +=
+				conn->evt.ticks_slot +
+				HAL_TICKER_US_TO_TICKS(EVENT_JITTER_US << 3);
+
+			if ((ticker_id_prev != 0xff) &&
+			    (ticker_ticks_diff_get(ticks_to_expire_normal,
+						   ticks_to_expire_prev) >
+			     (ticks_slot_abs_prev + ticks_slot_abs))) {
+				break;
+			}
+
+			ticker_id_prev = ticker_id;
+			ticks_to_expire_prev = ticks_to_expire_normal;
+			ticks_slot_abs_prev = ticks_slot_abs_curr;
+		}
+	}
+
+	if (ticker_id_prev != 0xff) {
+		*us_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire_prev +
+						    ticks_slot_abs_prev) +
+						    (EVENT_JITTER_US << 3);
+	}
+}
+
+void ull_sched_mfy_after_mstr_offset_get(void *param)
+{
+	struct lll_prepare_param *p = param;
+	struct lll_scan *lll = p->param;
+	struct evt_hdr *conn_evt = HDR_LLL2EVT(lll->conn);
+	uint32_t ticks_slot_overhead;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = MAX(conn_evt->ticks_active_to_start,
+					  conn_evt->ticks_xtal_to_start);
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	after_mstr_offset_get(lll->conn->interval,
+			      (ticks_slot_overhead + conn_evt->ticks_slot),
+			      p->ticks_at_expire, &lll->conn_win_offset_us);
+}
+
+void ull_sched_mfy_win_offset_use(void *param)
+{
+	struct ll_conn *conn = param;
+	uint32_t ticks_slot_overhead;
+	uint16_t win_offset;
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = MAX(conn->evt.ticks_active_to_start,
+					  conn->evt.ticks_xtal_to_start);
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	after_mstr_offset_get(conn->lll.interval,
+			      (ticks_slot_overhead + conn->evt.ticks_slot),
+			      conn->llcp.conn_upd.ticks_anchor,
+			      &conn->llcp_cu.win_offset_us);
+
+	win_offset = conn->llcp_cu.win_offset_us / 1250;
+
+	sys_put_le16(win_offset, (void *)conn->llcp.conn_upd.pdu_win_offset);
+}
+
+#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
+void ull_sched_mfy_free_win_offset_calc(void *param)
+{
+	uint32_t ticks_to_offset_default = 0U;
+	uint32_t *ticks_to_offset_next;
+	struct ll_conn *conn = param;
+	uint8_t offset_max = 6U;
+
+	ticks_to_offset_next = &ticks_to_offset_default;
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (conn->lll.role) {
+		conn->llcp_conn_param.ticks_to_offset_next =
+			conn->slave.ticks_to_offset;
+
+		ticks_to_offset_next =
+			&conn->llcp_conn_param.ticks_to_offset_next;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	win_offset_calc(conn, 0, ticks_to_offset_next,
+			conn->llcp_conn_param.interval_max, &offset_max,
+			(void *)conn->llcp_conn_param.pdu_win_offset0);
+}
+
+void ull_sched_mfy_win_offset_select(void *param)
+{
+#define OFFSET_S_MAX 6
+#define OFFSET_M_MAX 6
+	uint16_t win_offset_m[OFFSET_M_MAX] = {0, };
+	uint8_t offset_m_max = OFFSET_M_MAX;
+	struct ll_conn *conn = param;
+	uint8_t offset_index_s = 0U;
+	uint8_t has_offset_s = 0U;
+	uint32_t ticks_to_offset;
+	uint16_t win_offset_s;
+
+	ticks_to_offset = HAL_TICKER_US_TO_TICKS(conn->llcp_conn_param.offset0 *
+						 1250);
+
+	win_offset_calc(conn, 1, &ticks_to_offset,
+			conn->llcp_conn_param.interval_max, &offset_m_max,
+			(void *)win_offset_m);
+
+	while (offset_index_s < OFFSET_S_MAX) {
+		uint8_t offset_index_m = 0U;
+
+		win_offset_s =
+			sys_get_le16((uint8_t *)&conn->llcp_conn_param.offset0 +
+				     (sizeof(uint16_t) * offset_index_s));
+
+		while (offset_index_m < offset_m_max) {
+			if (win_offset_s != 0xffff) {
+				if (win_offset_s ==
+				    win_offset_m[offset_index_m]) {
+					break;
+				}
+
+				has_offset_s = 1U;
+			}
+
+			offset_index_m++;
+		}
+
+		if (offset_index_m < offset_m_max) {
+			break;
+		}
+
+		offset_index_s++;
+	}
+
+	if (offset_index_s < OFFSET_S_MAX) {
+		conn->llcp_cu.win_offset_us = win_offset_s * 1250;
+		sys_put_le16(win_offset_s,
+			     (void *)conn->llcp.conn_upd.pdu_win_offset);
+	} else if (!has_offset_s) {
+		conn->llcp_cu.win_offset_us = win_offset_m[0] * 1250;
+		sys_put_le16(win_offset_m[0],
+			     (void *)conn->llcp.conn_upd.pdu_win_offset);
+	} else {
+		struct pdu_data *pdu_ctrl_tx;
+
+		/* procedure request acked */
+		conn->llcp_ack = conn->llcp_req;
+
+		/* CPR request acked */
+		conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
+
+		/* reset mutex */
+		ull_conn_upd_curr_reset();
+
+		/* send reject_ind_ext */
+		pdu_ctrl_tx = (void *)
+			((uint8_t *)conn->llcp.conn_upd.pdu_win_offset -
+			 offsetof(struct pdu_data,
+				  llctrl.conn_update_ind.win_offset));
+		pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
+		pdu_ctrl_tx->len =
+			offsetof(struct pdu_data_llctrl, reject_ext_ind) +
+			sizeof(struct pdu_data_llctrl_reject_ext_ind);
+		pdu_ctrl_tx->llctrl.opcode =
+			PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND;
+		pdu_ctrl_tx->llctrl.reject_ext_ind.reject_opcode =
+			PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
+		pdu_ctrl_tx->llctrl.reject_ext_ind.error_code =
+			BT_HCI_ERR_UNSUPP_LL_PARAM_VAL;
+	}
+#undef OFFSET_S_MAX
+#undef OFFSET_M_MAX
+}
+
+static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
+			    uint32_t *ticks_to_offset_next,
+			    uint16_t conn_interval, uint8_t *offset_max,
+			    uint8_t *win_offset)
+{
+	uint32_t ticks_prepare_reduced = 0U;
+	uint32_t ticks_to_expire_prev;
+	uint32_t ticks_slot_abs_prev;
+	uint32_t ticks_slot_abs = 0U;
+	uint32_t ticks_anchor_prev;
+	uint32_t ticks_to_expire;
+	uint8_t ticker_id_other;
+	uint8_t ticker_id_prev;
+	uint32_t ticks_anchor;
+	uint8_t offset_index;
+	uint8_t ticker_id;
+	uint16_t offset;
+
+#if defined(CONFIG_BT_CTLR_LOW_LAT)
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+	if (conn_curr->evt.ticks_xtal_to_start & XON_BITMASK) {
+		uint32_t ticks_prepare_to_start =
+			MAX(conn_curr->evt.ticks_active_to_start,
+			    conn_curr->evt.ticks_preempt_to_start);
+
+		ticks_slot_abs = conn_curr->evt.ticks_xtal_to_start &
+				 ~XON_BITMASK;
+		ticks_prepare_reduced = ticks_slot_abs - ticks_prepare_to_start;
+	} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+	{
+		uint32_t ticks_prepare_to_start =
+			MAX(conn_curr->evt.ticks_active_to_start,
+			    conn_curr->evt.ticks_xtal_to_start);
+
+		ticks_slot_abs = ticks_prepare_to_start;
+	}
+#endif
+
+	ticks_slot_abs += conn_curr->evt.ticks_slot;
+
+	if (conn_curr->lll.role) {
+		ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_TIES_US);
+	}
+
+	ticker_id = ticker_id_prev = ticker_id_other = 0xff;
+	ticks_to_expire = ticks_to_expire_prev = ticks_anchor =
+		ticks_anchor_prev = offset_index = offset = 0U;
+	ticks_slot_abs_prev = 0U;
+	do {
+		uint32_t volatile ret_cb;
+		struct ll_conn *conn;
+		uint32_t ret;
+
+		ret_cb = TICKER_STATUS_BUSY;
+		ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR,
+					   TICKER_USER_ID_ULL_LOW,
+					   &ticker_id, &ticks_anchor,
+					   &ticks_to_expire, ticker_op_cb,
+					   (void *)&ret_cb);
+		if (ret == TICKER_STATUS_BUSY) {
+			while (ret_cb == TICKER_STATUS_BUSY) {
+				ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
+						 TICKER_USER_ID_ULL_LOW);
+			}
+		}
+
+		LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
+
+		if (ticker_id == 0xff) {
+			break;
+		}
+
+		/* ticks_anchor shall not change during this loop */
+		if ((ticker_id_prev != 0xff) &&
+		    (ticks_anchor != ticks_anchor_prev)) {
+			LL_ASSERT(0);
+		}
+
+		/* consider advertiser time as available. Any other time used by
+		 * tickers declared outside the controller is also available.
+		 */
+#if defined(CONFIG_BT_BROADCASTER)
+		if ((ticker_id < TICKER_ID_ADV_BASE) ||
+		    (ticker_id > TICKER_ID_CONN_LAST))
+#else /* !CONFIG_BT_BROADCASTER */
+		if ((ticker_id < TICKER_ID_SCAN_BASE) ||
+		    (ticker_id > TICKER_ID_CONN_LAST))
+#endif /* !CONFIG_BT_BROADCASTER */
+		{
+			continue;
+		}
+
+		if (ticker_id < TICKER_ID_CONN_BASE) {
+			/* non conn role found which could have preempted a
+			 * conn role, hence do not consider this free space
+			 * and any further as free slot for offset,
+			 */
+			ticker_id_other = ticker_id;
+			continue;
+		}
+
+		/* TODO: handle scanner; for now we exit with as much we
+		 * where able to fill (offsets).
+		 */
+		if (ticker_id_other != 0xff) {
+			break;
+		}
+
+		conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
+		if ((conn != conn_curr) && (is_select || !conn->lll.role)) {
+			uint32_t ticks_to_expire_normal =
+				ticks_to_expire + ticks_prepare_reduced;
+			uint32_t ticks_slot_margin = 0U;
+			uint32_t ticks_slot_abs_curr = 0U;
+#if defined(CONFIG_BT_CTLR_LOW_LAT)
+#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
+			if (conn->evt.ticks_xtal_to_start & XON_BITMASK) {
+				uint32_t ticks_prepare_to_start =
+					MAX(conn->evt.ticks_active_to_start,
+					    conn->evt.ticks_preempt_to_start);
+
+				ticks_slot_abs_curr =
+					conn->evt.ticks_xtal_to_start &
+					~XON_BITMASK;
+				ticks_to_expire_normal -=
+					ticks_slot_abs_curr -
+					ticks_prepare_to_start;
+			} else
+#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
+			{
+				uint32_t ticks_prepare_to_start =
+					MAX(conn->evt.ticks_active_to_start,
+					    conn->evt.ticks_xtal_to_start);
+
+				ticks_slot_abs_curr = ticks_prepare_to_start;
+			}
+#endif
+
+			ticks_slot_abs_curr += conn->evt.ticks_slot +
+					       HAL_TICKER_US_TO_TICKS(1250);
+
+			if (conn->lll.role) {
+				ticks_slot_margin =
+					HAL_TICKER_US_TO_TICKS(EVENT_TIES_US);
+				ticks_slot_abs_curr += ticks_slot_margin;
+			}
+
+			if (*ticks_to_offset_next < ticks_to_expire_normal) {
+				if (ticks_to_expire_prev <
+				    *ticks_to_offset_next) {
+					ticks_to_expire_prev =
+						*ticks_to_offset_next;
+				}
+
+				while ((offset_index < *offset_max) &&
+				       (ticker_ticks_diff_get(
+							ticks_to_expire_normal,
+							ticks_to_expire_prev) >=
+					(ticks_slot_abs_prev + ticks_slot_abs +
+					 ticks_slot_margin))) {
+					offset = HAL_TICKER_TICKS_TO_US(
+						ticks_to_expire_prev +
+						ticks_slot_abs_prev) / 1250;
+					if (offset >= conn_interval) {
+						ticks_to_expire_prev = 0U;
+
+						break;
+					}
+
+					sys_put_le16(offset,
+						     (win_offset +
+						      (sizeof(uint16_t) *
+						       offset_index)));
+					offset_index++;
+
+					ticks_to_expire_prev +=
+						HAL_TICKER_US_TO_TICKS(1250);
+				}
+
+				*ticks_to_offset_next = ticks_to_expire_prev;
+
+				if (offset >= conn_interval) {
+					break;
+				}
+			}
+
+			ticks_anchor_prev = ticks_anchor;
+			ticker_id_prev = ticker_id;
+			ticks_to_expire_prev = ticks_to_expire_normal;
+			ticks_slot_abs_prev = ticks_slot_abs_curr;
+		}
+	} while (offset_index < *offset_max);
+
+	if (ticker_id == 0xff) {
+		if (ticks_to_expire_prev < *ticks_to_offset_next) {
+			ticks_to_expire_prev = *ticks_to_offset_next;
+		}
+
+		while (offset_index < *offset_max) {
+			offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire_prev +
+							ticks_slot_abs_prev) /
+				 1250;
+			if (offset >= conn_interval) {
+				ticks_to_expire_prev = 0U;
+
+				break;
+			}
+
+			sys_put_le16(offset, (win_offset + (sizeof(uint16_t) *
+							    offset_index)));
+			offset_index++;
+
+			ticks_to_expire_prev += HAL_TICKER_US_TO_TICKS(1250);
+		}
+
+		*ticks_to_offset_next = ticks_to_expire_prev;
+	}
+
+	*offset_max = offset_index;
+}
+#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
+
+static void after_mstr_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
+				  uint32_t ticks_anchor,
+				  uint32_t *win_offset_us)
+{
+	uint32_t ticks_anchor_offset = ticks_anchor;
+
+	ull_sched_after_mstr_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot,
+				      &ticks_anchor_offset, win_offset_us);
+
+	if (!*win_offset_us) {
+		return;
+	}
+
+	if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) {
+		*win_offset_us -= HAL_TICKER_TICKS_TO_US(
+			ticker_ticks_diff_get(ticks_anchor,
+					      ticks_anchor_offset));
+	} else {
+		*win_offset_us += HAL_TICKER_TICKS_TO_US(
+			ticker_ticks_diff_get(ticks_anchor_offset,
+					      ticks_anchor));
+	}
+
+	if ((*win_offset_us & BIT(31)) == 0) {
+		uint32_t conn_interval_us = conn_interval * 1250;
+
+		while (*win_offset_us > conn_interval_us) {
+			*win_offset_us -= conn_interval_us;
+		}
+	}
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	*((uint32_t volatile *)param) = status;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sched_internal.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void ull_sched_after_mstr_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
+				   uint32_t *ticks_anchor, uint32_t *us_offset);
+void ull_sched_mfy_win_offset_use(void *param);
+void ull_sched_mfy_free_win_offset_calc(void *param);
+void ull_sched_mfy_win_offset_select(void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave.c	(working copy)
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <soc.h>
+#include <bluetooth/hci.h>
+#include <sys/byteorder.h>
+
+#include "util/util.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "hal/cpu.h"
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_adv.h"
+#include "lll_conn.h"
+#include "lll_slave.h"
+#include "lll_filter.h"
+#include "lll_tim_internal.h"
+
+#include "ull_adv_types.h"
+#include "ull_conn_types.h"
+#include "ull_filter.h"
+
+#include "ull_internal.h"
+#include "ull_adv_internal.h"
+#include "ull_conn_internal.h"
+#include "ull_slave_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_slave
+#include "common/log.h"
+#include "hal/debug.h"
+
+static void ticker_op_stop_adv_cb(uint32_t status, void *param);
+static void ticker_op_cb(uint32_t status, void *param);
+static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status,
+					       void *params);
+
+void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
+		     struct node_rx_ftr *ftr, struct lll_conn *lll)
+{
+	uint32_t conn_offset_us, conn_interval_us;
+	uint8_t ticker_id_adv, ticker_id_conn;
+	uint8_t peer_addr[BDADDR_SIZE];
+	uint32_t ticks_slot_overhead;
+	uint32_t ticks_slot_offset;
+	struct pdu_adv *pdu_adv;
+	struct ll_adv_set *adv;
+	struct node_rx_cc *cc;
+	struct ll_conn *conn;
+	uint32_t ready_delay_us;
+	uint32_t ticker_status;
+	uint8_t peer_addr_type;
+	uint16_t win_offset;
+	uint16_t timeout;
+	uint16_t interval;
+	uint8_t chan_sel;
+
+	adv = ((struct lll_adv *)ftr->param)->hdr.parent;
+	conn = lll->hdr.parent;
+
+	/* Populate the slave context */
+	pdu_adv = (void *)((struct node_rx_pdu *)rx)->pdu;
+	memcpy(&lll->crc_init[0], &pdu_adv->connect_ind.crc_init[0], 3);
+	memcpy(&lll->access_addr[0], &pdu_adv->connect_ind.access_addr[0], 4);
+	memcpy(&lll->data_chan_map[0], &pdu_adv->connect_ind.chan_map[0],
+	       sizeof(lll->data_chan_map));
+	lll->data_chan_count = util_ones_count_get(&lll->data_chan_map[0],
+			       sizeof(lll->data_chan_map));
+	if (lll->data_chan_count < 2) {
+		return;
+	}
+	lll->data_chan_hop = pdu_adv->connect_ind.hop;
+	if ((lll->data_chan_hop < 5) || (lll->data_chan_hop > 16)) {
+		return;
+	}
+
+	((struct lll_adv *)ftr->param)->conn = NULL;
+
+	interval = sys_le16_to_cpu(pdu_adv->connect_ind.interval);
+	lll->interval = interval;
+	lll->latency = sys_le16_to_cpu(pdu_adv->connect_ind.latency);
+
+	win_offset = sys_le16_to_cpu(pdu_adv->connect_ind.win_offset);
+	conn_interval_us = interval * 1250U;
+
+	/* calculate the window widening */
+	conn->slave.sca = pdu_adv->connect_ind.sca;
+	lll->slave.window_widening_periodic_us =
+		(((lll_clock_ppm_local_get() +
+		   lll_clock_ppm_get(conn->slave.sca)) *
+		  conn_interval_us) + (1000000 - 1)) / 1000000U;
+	lll->slave.window_widening_max_us = (conn_interval_us >> 1) -
+					    EVENT_IFS_US;
+	lll->slave.window_size_event_us = pdu_adv->connect_ind.win_size * 1250U;
+
+	/* procedure timeouts */
+	timeout = sys_le16_to_cpu(pdu_adv->connect_ind.timeout);
+	conn->supervision_reload =
+		RADIO_CONN_EVENTS((timeout * 10U * 1000U), conn_interval_us);
+	conn->procedure_reload =
+		RADIO_CONN_EVENTS((40 * 1000 * 1000), conn_interval_us);
+
+#if defined(CONFIG_BT_CTLR_LE_PING)
+	/* APTO in no. of connection events */
+	conn->apto_reload = RADIO_CONN_EVENTS((30 * 1000 * 1000),
+					      conn_interval_us);
+	/* Dispatch LE Ping PDU 6 connection events (that peer would
+	 * listen to) before 30s timeout
+	 * TODO: "peer listens to" is greater than 30s due to latency
+	 */
+	conn->appto_reload = (conn->apto_reload > (lll->latency + 6)) ?
+			     (conn->apto_reload - (lll->latency + 6)) :
+			     conn->apto_reload;
+#endif /* CONFIG_BT_CTLR_LE_PING */
+
+	memcpy((void *)&conn->slave.force, &lll->access_addr[0],
+	       sizeof(conn->slave.force));
+
+	peer_addr_type = pdu_adv->tx_addr;
+	memcpy(peer_addr, pdu_adv->connect_ind.init_addr, BDADDR_SIZE);
+
+	chan_sel = pdu_adv->chan_sel;
+
+	cc = (void *)pdu_adv;
+	cc->status = 0U;
+	cc->role = 1U;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t rl_idx = ftr->rl_idx;
+
+	if (ull_filter_lll_lrpa_used(adv->lll.rl_idx)) {
+		memcpy(&cc->local_rpa[0], &pdu_adv->connect_ind.adv_addr[0],
+		       BDADDR_SIZE);
+	} else {
+		memset(&cc->local_rpa[0], 0x0, BDADDR_SIZE);
+	}
+
+	if (rl_idx != FILTER_IDX_NONE) {
+		/* TODO: store rl_idx instead if safe */
+		/* Store identity address */
+		ll_rl_id_addr_get(rl_idx, &cc->peer_addr_type,
+				  &cc->peer_addr[0]);
+		/* Mark it as identity address from RPA (0x02, 0x03) */
+		cc->peer_addr_type += 2;
+
+		/* Store peer RPA */
+		memcpy(&cc->peer_rpa[0], &peer_addr[0], BDADDR_SIZE);
+	} else {
+		memset(&cc->peer_rpa[0], 0x0, BDADDR_SIZE);
+#else
+	if (1) {
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+		cc->peer_addr_type = peer_addr_type;
+		memcpy(cc->peer_addr, peer_addr, BDADDR_SIZE);
+	}
+
+	cc->interval = lll->interval;
+	cc->latency = lll->latency;
+	cc->timeout = timeout;
+	cc->sca = conn->slave.sca;
+
+	lll->handle = ll_conn_handle_get(conn);
+	rx->handle = lll->handle;
+
+#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
+	lll->tx_pwr_lvl = RADIO_TXP_DEFAULT;
+#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
+
+	/* Use Channel Selection Algorithm #2 if peer too supports it */
+	if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
+		struct node_rx_pdu *rx_csa;
+		struct node_rx_cs *cs;
+
+		/* pick the rx node instance stored within the connection
+		 * rx node.
+		 */
+		rx_csa = (void *)ftr->extra;
+
+		/* Enqueue the connection event */
+		ll_rx_put(link, rx);
+
+		/* use the rx node for CSA event */
+		rx = (void *)rx_csa;
+		link = rx->link;
+
+		rx->handle = lll->handle;
+		rx->type = NODE_RX_TYPE_CHAN_SEL_ALGO;
+
+		cs = (void *)rx_csa->pdu;
+
+		if (chan_sel) {
+			uint16_t aa_ls = ((uint16_t)lll->access_addr[1] << 8) |
+				      lll->access_addr[0];
+			uint16_t aa_ms = ((uint16_t)lll->access_addr[3] << 8) |
+				      lll->access_addr[2];
+
+			lll->data_chan_sel = 1;
+			lll->data_chan_id = aa_ms ^ aa_ls;
+
+			cs->csa = 0x01;
+		} else {
+			cs->csa = 0x00;
+		}
+	}
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	if (ll_adv_cmds_is_ext()) {
+		uint8_t handle;
+
+		/* Enqueue connection or CSA event */
+		ll_rx_put(link, rx);
+
+		/* use reserved link and node_rx to prepare
+		 * advertising terminate event
+		 */
+		rx = adv->lll.node_rx_adv_term;
+		link = rx->link;
+
+		handle = ull_adv_handle_get(adv);
+		LL_ASSERT(handle < BT_CTLR_ADV_SET);
+
+		rx->type = NODE_RX_TYPE_EXT_ADV_TERMINATE;
+		rx->handle = handle;
+		rx->rx_ftr.param_adv_term.status = 0U;
+		rx->rx_ftr.param_adv_term.conn_handle = lll->handle;
+		rx->rx_ftr.param_adv_term.num_events = 0U;
+	}
+#endif
+
+	ll_rx_put(link, rx);
+	ll_rx_sched();
+
+#if defined(CONFIG_BT_CTLR_PHY)
+	ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy_rx, 1);
+#else
+	ready_delay_us = lll_radio_rx_ready_delay_get(0, 0);
+#endif
+
+	/* TODO: active_to_start feature port */
+	conn->evt.ticks_active_to_start = 0U;
+	conn->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	conn->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	conn->evt.ticks_slot =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
+				       ready_delay_us +
+				       328 + EVENT_IFS_US + 328);
+
+	ticks_slot_offset = MAX(conn->evt.ticks_active_to_start,
+				conn->evt.ticks_xtal_to_start);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = ticks_slot_offset;
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	conn_interval_us -= lll->slave.window_widening_periodic_us;
+
+	conn_offset_us = ftr->radio_end_us;
+	conn_offset_us += ((uint64_t)win_offset + 1) * 1250U;
+	conn_offset_us -= EVENT_OVERHEAD_START_US;
+	conn_offset_us -= EVENT_TICKER_RES_MARGIN_US;
+	conn_offset_us -= EVENT_JITTER_US;
+	conn_offset_us -= ready_delay_us;
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* disable ticker job, in order to chain stop and start to avoid RTC
+	 * being stopped if no tickers active.
+	 */
+	mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 0);
+#endif
+
+	/* Stop Advertiser */
+	ticker_id_adv = TICKER_ID_ADV_BASE + ull_adv_handle_get(adv);
+	ticker_status = ticker_stop(TICKER_INSTANCE_ID_CTLR,
+				    TICKER_USER_ID_ULL_HIGH,
+				    ticker_id_adv, ticker_op_stop_adv_cb, adv);
+	ticker_op_stop_adv_cb(ticker_status, adv);
+
+	/* Stop Direct Adv Stop */
+	if (adv->lll.is_hdcd) {
+		/* Advertiser stop can expire while here in this ISR.
+		 * Deferred attempt to stop can fail as it would have
+		 * expired, hence ignore failure.
+		 */
+		ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+			    TICKER_ID_ADV_STOP, NULL, NULL);
+	}
+
+	/* Start Slave */
+	ticker_id_conn = TICKER_ID_CONN_BASE + ll_conn_handle_get(conn);
+	ticker_status = ticker_start(TICKER_INSTANCE_ID_CTLR,
+				     TICKER_USER_ID_ULL_HIGH,
+				     ticker_id_conn,
+				     ftr->ticks_anchor - ticks_slot_offset,
+				     HAL_TICKER_US_TO_TICKS(conn_offset_us),
+				     HAL_TICKER_US_TO_TICKS(conn_interval_us),
+				     HAL_TICKER_REMAINDER(conn_interval_us),
+#if defined(CONFIG_BT_CTLR_CONN_META)
+				     TICKER_LAZY_MUST_EXPIRE,
+#else
+				     TICKER_NULL_LAZY,
+#endif /* CONFIG_BT_CTLR_CONN_META */
+				     (conn->evt.ticks_slot +
+				      ticks_slot_overhead),
+				     ull_slave_ticker_cb, conn, ticker_op_cb,
+				     (void *)__LINE__);
+	LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+		  (ticker_status == TICKER_STATUS_BUSY));
+
+#if (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO)
+	/* enable ticker job, irrespective of disabled in this function so
+	 * first connection event can be scheduled as soon as possible.
+	 */
+	mayfly_enable(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1);
+#endif
+}
+
+void ull_slave_latency_cancel(struct ll_conn *conn, uint16_t handle)
+{
+	/* break peripheral latency */
+	if (conn->lll.latency_event && !conn->slave.latency_cancel) {
+		uint32_t ticker_status;
+
+		conn->slave.latency_cancel = 1U;
+
+		ticker_status =
+			ticker_update(TICKER_INSTANCE_ID_CTLR,
+				      TICKER_USER_ID_THREAD,
+				      (TICKER_ID_CONN_BASE + handle),
+				      0, 0, 0, 0, 1, 0,
+				      ticker_update_latency_cancel_op_cb,
+				      (void *)conn);
+		LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+			  (ticker_status == TICKER_STATUS_BUSY));
+	}
+}
+
+void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			 uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_slave_prepare};
+	static struct lll_prepare_param p;
+	struct ll_conn *conn;
+	uint32_t err;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_S(1);
+
+	conn = param;
+
+	/* Check if stopping ticker (on disconnection, race with ticker expiry)
+	 */
+	if (unlikely(conn->lll.handle == 0xFFFF)) {
+		DEBUG_RADIO_CLOSE_S(0);
+		return;
+	}
+
+	/* If this is a must-expire callback, LLCP state machine does not need
+	 * to know. Will be called with lazy > 0 when scheduled in air.
+	 */
+	if (!IS_ENABLED(CONFIG_BT_CTLR_CONN_META) ||
+	    (lazy != TICKER_LAZY_MUST_EXPIRE)) {
+		int ret;
+
+		/* Handle any LL Control Procedures */
+		ret = ull_conn_llcp(conn, ticks_at_expire, lazy);
+		if (ret) {
+			DEBUG_RADIO_CLOSE_S(0);
+			return;
+		}
+	}
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&conn->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = &conn->lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	err = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+			     0, &mfy);
+	LL_ASSERT(!err);
+
+	/* De-mux remaining tx nodes from FIFO */
+	ull_conn_tx_demux(UINT8_MAX);
+
+	/* Enqueue towards LLL */
+	ull_conn_tx_lll_enqueue(conn, UINT8_MAX);
+
+	DEBUG_RADIO_PREPARE_S(1);
+}
+
+#if defined(CONFIG_BT_CTLR_LE_ENC)
+uint8_t ll_start_enc_req_send(uint16_t handle, uint8_t error_code,
+			    uint8_t const *const ltk)
+{
+	struct ll_conn *conn;
+
+	conn = ll_connected_get(handle);
+	if (!conn) {
+		return BT_HCI_ERR_UNKNOWN_CONN_ID;
+	}
+
+	if (error_code) {
+		if (conn->llcp_enc.refresh == 0U) {
+			if ((conn->llcp_req == conn->llcp_ack) ||
+			     (conn->llcp_type != LLCP_ENCRYPTION)) {
+				return BT_HCI_ERR_CMD_DISALLOWED;
+			}
+
+			conn->llcp.encryption.error_code = error_code;
+			conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
+		} else {
+			if (conn->llcp_terminate.ack !=
+			    conn->llcp_terminate.req) {
+				return BT_HCI_ERR_CMD_DISALLOWED;
+			}
+
+			conn->llcp_terminate.reason_own = error_code;
+
+			conn->llcp_terminate.req++;
+		}
+	} else {
+		if ((conn->llcp_req == conn->llcp_ack) ||
+		     (conn->llcp_type != LLCP_ENCRYPTION)) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+
+		memcpy(&conn->llcp_enc.ltk[0], ltk,
+		       sizeof(conn->llcp_enc.ltk));
+
+		conn->llcp.encryption.error_code = 0U;
+		conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_LE_ENC */
+
+static void ticker_op_stop_adv_cb(uint32_t status, void *param)
+{
+	LL_ASSERT(status != TICKER_STATUS_FAILURE ||
+		  param == ull_disable_mark_get());
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	ARG_UNUSED(param);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void ticker_update_latency_cancel_op_cb(uint32_t ticker_status,
+					       void *params)
+{
+	struct ll_conn *conn = params;
+
+	LL_ASSERT(ticker_status == TICKER_STATUS_SUCCESS);
+
+	conn->slave.latency_cancel = 0U;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_slave_internal.h	(working copy)
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
+		     struct node_rx_ftr *ftr, struct lll_conn *lll);
+void ull_slave_latency_cancel(struct ll_conn *conn, uint16_t handle);
+void ull_slave_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+			 uint16_t lazy, void *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync.c	(working copy)
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <sys/byteorder.h>
+#include <bluetooth/hci.h>
+
+#include "util/util.h"
+#include "util/mem.h"
+#include "util/memq.h"
+#include "util/mayfly.h"
+
+#include "hal/ccm.h"
+#include "hal/radio.h"
+#include "hal/ticker.h"
+
+#include "ticker/ticker.h"
+
+#include "pdu.h"
+#include "ll.h"
+
+#include "lll.h"
+#include "lll_vendor.h"
+#include "lll_clock.h"
+#include "lll_scan.h"
+#include "lll_sync.h"
+
+#include "ull_scan_types.h"
+#include "ull_sync_types.h"
+
+#include "ull_internal.h"
+#include "ull_scan_internal.h"
+#include "ull_sync_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_sync
+#include "common/log.h"
+#include <soc.h>
+#include "hal/debug.h"
+
+static int init_reset(void);
+static inline struct ll_sync_set *sync_acquire(void);
+static struct ll_sync_set *is_enabled_get(uint16_t handle);
+static void timeout_cleanup(struct ll_sync_set *sync);
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param);
+static void ticker_op_cb(uint32_t status, void *param);
+static void ticker_update_sync_op_cb(uint32_t status, void *param);
+static void ticker_stop_op_cb(uint32_t status, void *param);
+static void sync_lost(void *param);
+
+static struct ll_sync_set ll_sync_pool[CONFIG_BT_CTLR_SCAN_SYNC_SET];
+static void *sync_free;
+
+uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type,
+			    uint8_t *adv_addr, uint16_t skip,
+			    uint16_t sync_timeout, uint8_t sync_cte_type)
+{
+	struct ll_scan_set *scan_coded;
+	memq_link_t *link_sync_estab;
+	memq_link_t *link_sync_lost;
+	struct node_rx_hdr *node_rx;
+	struct lll_sync *lll_sync;
+	struct ll_scan_set *scan;
+	struct ll_sync_set *sync;
+
+	scan = ull_scan_set_get(SCAN_HANDLE_1M);
+	if (!scan || scan->per_scan.sync) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
+		if (!scan_coded || scan_coded->per_scan.sync) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+
+	link_sync_estab = ll_rx_link_alloc();
+	if (!link_sync_estab) {
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	link_sync_lost = ll_rx_link_alloc();
+	if (!link_sync_lost) {
+		ll_rx_link_release(link_sync_estab);
+
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	node_rx = ll_rx_alloc();
+	if (!node_rx) {
+		ll_rx_link_release(link_sync_lost);
+		ll_rx_link_release(link_sync_estab);
+
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	sync = sync_acquire();
+	if (!sync) {
+		ll_rx_release(node_rx);
+		ll_rx_link_release(link_sync_lost);
+		ll_rx_link_release(link_sync_estab);
+
+		return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
+	}
+
+	scan->per_scan.filter_policy = options & BIT(0);
+	if (!scan->per_scan.filter_policy) {
+		scan->per_scan.sid = sid;
+		scan->per_scan.adv_addr_type = adv_addr_type;
+		memcpy(scan->per_scan.adv_addr, adv_addr, BDADDR_SIZE);
+	}
+
+	sync->skip = skip;
+	sync->timeout = sync_timeout;
+
+	/* TODO: Support for CTE type */
+
+	/* Initialize sync context */
+	sync->timeout_reload = 0U;
+	sync->timeout_expire = 0U;
+	lll_sync = &sync->lll;
+	lll_sync->skip_prepare = 0U;
+	lll_sync->skip_event = 0U;
+	lll_sync->data_chan_id = 0U;
+	lll_sync->window_widening_prepare_us = 0U;
+	lll_sync->window_widening_event_us = 0U;
+
+	/* Reporting initially enabled/disabled */
+	lll_sync->is_enabled = options & BIT(1);
+
+	/* Initialise state */
+	scan->per_scan.state = LL_SYNC_STATE_IDLE;
+
+	/* established and sync_lost node_rx */
+	node_rx->link = link_sync_estab;
+	scan->per_scan.node_rx_estab = node_rx;
+	sync->node_rx_lost.link = link_sync_lost;
+
+	/* Initialise ULL and LLL headers */
+	ull_hdr_init(&sync->ull);
+	lll_hdr_init(lll_sync, sync);
+
+	/* Enable scanner to create sync */
+	scan->per_scan.sync = sync;
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		scan_coded->per_scan.sync = sync;
+	}
+
+	return 0;
+}
+
+uint8_t ll_sync_create_cancel(void **rx)
+{
+	struct ll_scan_set *scan_coded;
+	memq_link_t *link_sync_estab;
+	memq_link_t *link_sync_lost;
+	struct node_rx_pdu *node_rx;
+	struct ll_scan_set *scan;
+	struct ll_sync_set *sync;
+	struct node_rx_sync *se;
+
+	scan = ull_scan_set_get(SCAN_HANDLE_1M);
+	if (!scan || !scan->per_scan.sync) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		scan_coded = ull_scan_set_get(SCAN_HANDLE_PHY_CODED);
+		if (!scan_coded || !scan_coded->per_scan.sync) {
+			return BT_HCI_ERR_CMD_DISALLOWED;
+		}
+	}
+
+	sync = scan->per_scan.sync;
+	scan->per_scan.sync = NULL;
+	if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED)) {
+		scan_coded->per_scan.sync = NULL;
+	}
+
+	/* Check for race condition where in sync is established when sync
+	 * context was set to NULL.
+	 */
+	if (!sync || sync->timeout_reload) {
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	node_rx = (void *)scan->per_scan.node_rx_estab;
+	link_sync_estab = node_rx->hdr.link;
+	link_sync_lost = sync->node_rx_lost.link;
+
+	ll_rx_link_release(link_sync_lost);
+	ll_rx_link_release(link_sync_estab);
+	ll_rx_release(node_rx);
+
+	node_rx = (void *)&sync->node_rx_lost;
+	node_rx->hdr.type = NODE_RX_TYPE_SYNC;
+	node_rx->hdr.handle = 0xffff;
+	node_rx->hdr.rx_ftr.param = sync;
+	se = (void *)node_rx->pdu;
+	se->status = BT_HCI_ERR_OP_CANCELLED_BY_HOST;
+
+	*rx = node_rx;
+
+	return 0;
+}
+
+uint8_t ll_sync_terminate(uint16_t handle)
+{
+	memq_link_t *link_sync_lost;
+	struct ll_sync_set *sync;
+	uint32_t volatile ret_cb;
+	uint32_t ret;
+	void *mark;
+
+	sync = is_enabled_get(handle);
+	if (!sync) {
+		return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
+	}
+
+	mark = ull_disable_mark(sync);
+	LL_ASSERT(mark == sync);
+
+	ret_cb = TICKER_STATUS_BUSY;
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
+			  TICKER_ID_SCAN_SYNC_BASE + handle,
+			  ull_ticker_status_give, (void *)&ret_cb);
+	ret = ull_ticker_status_take(ret, &ret_cb);
+	if (ret) {
+		mark = ull_disable_mark(sync);
+		LL_ASSERT(mark == sync);
+
+		return BT_HCI_ERR_CMD_DISALLOWED;
+	}
+
+	mark = ull_disable_unmark(sync);
+	LL_ASSERT(mark == sync);
+
+	link_sync_lost = sync->node_rx_lost.link;
+	ll_rx_link_release(link_sync_lost);
+
+	ull_sync_release(sync);
+
+	return 0;
+}
+
+uint8_t ll_sync_recv_enable(uint16_t handle, uint8_t enable)
+{
+	/* TODO: */
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+int ull_sync_init(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int ull_sync_reset(void)
+{
+	int err;
+
+	err = init_reset();
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+struct ll_sync_set *ull_sync_set_get(uint16_t handle)
+{
+	if (handle >= CONFIG_BT_CTLR_SCAN_SYNC_SET) {
+		return NULL;
+	}
+
+	return &ll_sync_pool[handle];
+}
+
+uint16_t ull_sync_handle_get(struct ll_sync_set *sync)
+{
+	return mem_index_get(sync, ll_sync_pool, sizeof(struct ll_sync_set));
+}
+
+uint16_t ull_sync_lll_handle_get(struct lll_sync *lll)
+{
+	return ull_sync_handle_get((void *)HDR_LLL2EVT(lll));
+}
+
+void ull_sync_release(struct ll_sync_set *sync)
+{
+	mem_release(sync, &sync_free);
+}
+
+void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
+		    struct node_rx_hdr *node_rx, struct pdu_adv_sync_info *si)
+{
+	uint32_t ticks_slot_overhead;
+	uint32_t ticks_slot_offset;
+	struct ll_sync_set *sync;
+	struct node_rx_sync *se;
+	struct node_rx_ftr *ftr;
+	uint32_t sync_offset_us;
+	uint32_t ready_delay_us;
+	struct node_rx_pdu *rx;
+	struct lll_sync *lll;
+	uint16_t sync_handle;
+	uint32_t interval_us;
+	struct pdu_adv *pdu;
+	uint16_t interval;
+	uint32_t ret;
+	uint8_t sca;
+
+	sync = scan->per_scan.sync;
+	scan->per_scan.sync = NULL;
+
+	lll = &sync->lll;
+	memcpy(lll->data_chan_map, si->sca_chm, sizeof(lll->data_chan_map));
+	lll->data_chan_map[4] &= ~0xE0;
+	lll->data_chan_count = util_ones_count_get(&lll->data_chan_map[0],
+						   sizeof(lll->data_chan_map));
+	if (lll->data_chan_count < 2) {
+		return;
+	}
+
+	memcpy(lll->access_addr, &si->aa, sizeof(lll->access_addr));
+	memcpy(lll->crc_init, si->crc_init, sizeof(lll->crc_init));
+	lll->event_counter = si->evt_cntr;
+	lll->phy = aux->lll.phy;
+
+	sca = si->sca_chm[4] >> 5;
+	interval = sys_le16_to_cpu(si->interval);
+	interval_us = interval * 1250U;
+
+	sync->timeout_reload = RADIO_SYNC_EVENTS((sync->timeout * 10U * 1000U),
+						 interval_us);
+
+	lll->window_widening_periodic_us =
+		(((lll_clock_ppm_local_get() + lll_clock_ppm_get(sca)) *
+		  interval_us) + (1000000 - 1)) / 1000000U;
+	lll->window_widening_max_us = (interval_us >> 1) - EVENT_IFS_US;
+	if (si->offs_units) {
+		lll->window_size_event_us = 300U;
+	} else {
+		lll->window_size_event_us = 30U;
+	}
+
+	sync_handle = ull_sync_handle_get(sync);
+
+	rx = (void *)scan->per_scan.node_rx_estab;
+	rx->hdr.type = NODE_RX_TYPE_SYNC;
+	rx->hdr.handle = sync_handle;
+	rx->hdr.rx_ftr.param = scan;
+	se = (void *)rx->pdu;
+	se->status = BT_HCI_ERR_SUCCESS;
+	se->interval = interval;
+	se->phy = lll->phy;
+	se->sca = sca;
+
+	ll_rx_put(rx->hdr.link, rx);
+	ll_rx_sched();
+
+	ftr = &node_rx->rx_ftr;
+	pdu = (void *)((struct node_rx_pdu *)node_rx)->pdu;
+
+	ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy, 1);
+
+	sync_offset_us = ftr->radio_end_us;
+	sync_offset_us += (uint32_t)si->offs * lll->window_size_event_us;
+	sync_offset_us -= PKT_AC_US(pdu->len, 0, lll->phy);
+	sync_offset_us -= EVENT_OVERHEAD_START_US;
+	sync_offset_us -= EVENT_JITTER_US;
+	sync_offset_us -= ready_delay_us;
+
+	interval_us -= lll->window_widening_periodic_us;
+
+	/* TODO: active_to_start feature port */
+	sync->evt.ticks_active_to_start = 0U;
+	sync->evt.ticks_xtal_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
+	sync->evt.ticks_preempt_to_start =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
+	sync->evt.ticks_slot =
+		HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US +
+				       ready_delay_us +
+				       PKT_AC_US(PDU_AC_EXT_PAYLOAD_SIZE_MAX,
+						 0, lll->phy) +
+				       EVENT_OVERHEAD_END_US);
+
+	ticks_slot_offset = MAX(sync->evt.ticks_active_to_start,
+				sync->evt.ticks_xtal_to_start);
+
+	if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
+		ticks_slot_overhead = ticks_slot_offset;
+	} else {
+		ticks_slot_overhead = 0U;
+	}
+
+	ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+			   (TICKER_ID_SCAN_SYNC_BASE + sync_handle),
+			   ftr->ticks_anchor - ticks_slot_offset,
+			   HAL_TICKER_US_TO_TICKS(sync_offset_us),
+			   HAL_TICKER_US_TO_TICKS(interval_us),
+			   HAL_TICKER_REMAINDER(interval_us),
+			   TICKER_NULL_LAZY,
+			   (sync->evt.ticks_slot + ticks_slot_overhead),
+			   ticker_cb, sync, ticker_op_cb, (void *)__LINE__);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+void ull_sync_done(struct node_rx_event_done *done)
+{
+	struct lll_sync *lll = (void *)HDR_ULL2LLL(done->param);
+	struct ll_sync_set *sync = (void *)HDR_LLL2EVT(lll);
+	uint32_t ticks_drift_minus;
+	uint32_t ticks_drift_plus;
+	uint16_t elapsed_event;
+	uint16_t skip_event;
+	uint16_t lazy;
+	uint8_t force;
+
+	/* Events elapsed used in timeout checks below */
+	skip_event = lll->skip_event;
+	elapsed_event = skip_event + 1;
+
+	/* Sync drift compensation and new skip calculation
+	 */
+	ticks_drift_plus = 0U;
+	ticks_drift_minus = 0U;
+	if (done->extra.trx_cnt) {
+		/* Calculate drift in ticks unit */
+		ull_drift_ticks_get(done, &ticks_drift_plus,
+				    &ticks_drift_minus);
+
+		/* Enforce skip */
+		lll->skip_event = sync->skip;
+	}
+
+	/* Reset supervision countdown */
+	if (done->extra.crc_valid) {
+		sync->timeout_expire = 0U;
+	}
+
+	/* if anchor point not sync-ed, start timeout countdown, and break
+	 * skip if any.
+	 */
+	else {
+		if (!sync->timeout_expire) {
+			sync->timeout_expire = sync->timeout_reload;
+		}
+	}
+
+	/* check timeout */
+	force = 0U;
+	if (sync->timeout_expire) {
+		if (sync->timeout_expire > elapsed_event) {
+			sync->timeout_expire -= elapsed_event;
+
+			/* break skip */
+			lll->skip_event = 0U;
+
+			if (skip_event) {
+				force = 1U;
+			}
+		} else {
+			timeout_cleanup(sync);
+
+			return;
+		}
+	}
+
+	/* check if skip needs update */
+	lazy = 0U;
+	if ((force) || (skip_event != lll->skip_event)) {
+		lazy = lll->skip_event + 1U;
+	}
+
+	/* Update Sync ticker instance */
+	if (ticks_drift_plus || ticks_drift_minus || lazy || force) {
+		uint16_t sync_handle = ull_sync_handle_get(sync);
+		uint32_t ticker_status;
+
+		/* Call to ticker_update can fail under the race
+		 * condition where in the periodic sync role is being stopped
+		 * but at the same time it is preempted by periodic sync event
+		 * that gets into close state. Accept failure when periodic sync
+		 * role is being stopped.
+		 */
+		ticker_status = ticker_update(TICKER_INSTANCE_ID_CTLR,
+					      TICKER_USER_ID_ULL_HIGH,
+					      (TICKER_ID_SCAN_SYNC_BASE +
+					       sync_handle),
+					      ticks_drift_plus,
+					      ticks_drift_minus, 0, 0,
+					      lazy, force,
+					      ticker_update_sync_op_cb, sync);
+		LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) ||
+			  (ticker_status == TICKER_STATUS_BUSY) ||
+			  ((void *)sync == ull_disable_mark_get()));
+	}
+}
+
+static int init_reset(void)
+{
+	/* Initialize sync pool. */
+	mem_init(ll_sync_pool, sizeof(struct ll_sync_set),
+		 sizeof(ll_sync_pool) / sizeof(struct ll_sync_set),
+		 &sync_free);
+
+	return 0;
+}
+
+static inline struct ll_sync_set *sync_acquire(void)
+{
+	return mem_acquire(&sync_free);
+}
+
+static struct ll_sync_set *is_enabled_get(uint16_t handle)
+{
+	struct ll_sync_set *sync;
+
+	sync = ull_sync_set_get(handle);
+	if (!sync || !sync->timeout_reload) {
+		return NULL;
+	}
+
+	return sync;
+}
+
+static void timeout_cleanup(struct ll_sync_set *sync)
+{
+	uint16_t sync_handle = ull_sync_handle_get(sync);
+	uint32_t ret;
+
+	/* Stop Periodic Sync Ticker */
+	ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_ULL_HIGH,
+			  TICKER_ID_SCAN_SYNC_BASE + sync_handle,
+			  ticker_stop_op_cb, (void *)sync);
+	LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+		  (ret == TICKER_STATUS_BUSY));
+}
+
+static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
+		      uint16_t lazy, void *param)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, lll_sync_prepare};
+	static struct lll_prepare_param p;
+	struct ll_sync_set *sync = param;
+	struct lll_sync *lll;
+	uint32_t ret;
+	uint8_t ref;
+
+	DEBUG_RADIO_PREPARE_O(1);
+
+	lll = &sync->lll;
+
+	/* Increment prepare reference count */
+	ref = ull_ref_inc(&sync->ull);
+	LL_ASSERT(ref);
+
+	/* Append timing parameters */
+	p.ticks_at_expire = ticks_at_expire;
+	p.remainder = remainder;
+	p.lazy = lazy;
+	p.param = lll;
+	mfy.param = &p;
+
+	/* Kick LLL prepare */
+	ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
+			     TICKER_USER_ID_LLL, 0, &mfy);
+	LL_ASSERT(!ret);
+
+	DEBUG_RADIO_PREPARE_O(1);
+}
+
+static void ticker_op_cb(uint32_t status, void *param)
+{
+	ARG_UNUSED(param);
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void ticker_update_sync_op_cb(uint32_t status, void *param)
+{
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
+		  param == ull_disable_mark_get());
+}
+
+static void ticker_stop_op_cb(uint32_t status, void *param)
+{
+	uint32_t retval;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, sync_lost};
+
+	LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+
+	mfy.param = param;
+
+	retval = mayfly_enqueue(TICKER_USER_ID_ULL_LOW, TICKER_USER_ID_ULL_HIGH,
+				0, &mfy);
+	LL_ASSERT(!retval);
+}
+
+static void sync_lost(void *param)
+{
+	struct ll_sync_set *sync = param;
+	struct node_rx_pdu *rx;
+
+	/* Generate Periodic advertising sync lost */
+	rx = (void *)&sync->node_rx_lost;
+	rx->hdr.handle = ull_sync_handle_get(sync);
+	rx->hdr.type = NODE_RX_TYPE_SYNC_LOST;
+	rx->hdr.rx_ftr.param = sync;
+
+	/* Enqueue the sync lost towards ULL context */
+	ll_rx_put(rx->hdr.link, rx);
+	ll_rx_sched();
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_internal.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int ull_sync_init(void);
+int ull_sync_reset(void);
+uint16_t ull_sync_handle_get(struct ll_sync_set *sync);
+void ull_sync_release(struct ll_sync_set *sync);
+void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
+		    struct node_rx_hdr *node_rx, struct pdu_adv_sync_info *si);
+void ull_sync_done(struct node_rx_event_done *done);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c	(working copy)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ull_sync_iso
+#include "common/log.h"
+#include "hal/debug.h"
+
+uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
+			   uint8_t encryption, uint8_t *bcode, uint8_t mse,
+			   uint16_t sync_timeout, uint8_t num_bis,
+			   uint8_t *bis)
+{
+	/* TODO: Implement */
+	ARG_UNUSED(big_handle);
+	ARG_UNUSED(sync_handle);
+	ARG_UNUSED(encryption);
+	ARG_UNUSED(bcode);
+	ARG_UNUSED(mse);
+	ARG_UNUSED(sync_timeout);
+	ARG_UNUSED(num_bis);
+	ARG_UNUSED(bis);
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
+
+
+uint8_t ll_big_sync_terminate(uint8_t big_handle)
+{
+	/* TODO: Implement */
+	ARG_UNUSED(big_handle);
+
+	return BT_HCI_ERR_CMD_DISALLOWED;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_types.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_types.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ll_sw/ull_sync_types.h	(working copy)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LL_SYNC_STATE_IDLE       0x00
+#define LL_SYNC_STATE_ADDR_MATCH 0x01
+#define LL_SYNC_STATE_CREATED    0x02
+
+struct ll_sync_set {
+	struct evt_hdr evt;
+	struct ull_hdr ull;
+	struct lll_sync lll;
+
+	uint16_t skip;
+	uint16_t timeout;
+	uint16_t volatile timeout_reload; /* Non-zero when sync established */
+	uint16_t timeout_expire;
+
+	struct node_rx_hdr node_rx_lost;
+};
+
+struct node_rx_sync {
+	uint8_t status;
+	uint8_t  phy;
+	uint16_t interval;
+	uint8_t  sca;
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.h	(working copy)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** \defgroup Timer API return codes.
+ *
+ * @{
+ */
+#define TICKER_STATUS_SUCCESS 0 /**< Success. */
+#define TICKER_STATUS_FAILURE 1 /**< Failure. */
+#define TICKER_STATUS_BUSY    2 /**< Busy, requested feature will
+				  * complete later in time as job is
+				  * disabled or at lower execution
+				  * priority than the caller.
+				  */
+/**
+ * @}
+ */
+
+/** \defgroup Timer API common defaults parameter values.
+ *
+ * @{
+ */
+#define TICKER_NULL             ((uint8_t)((uint8_t)0 - 1))
+#define TICKER_NULL_REMAINDER   0
+#define TICKER_NULL_PERIOD      0
+#define TICKER_NULL_SLOT        0
+#define TICKER_NULL_LAZY        0
+#define TICKER_NULL_MUST_EXPIRE 0
+/**
+ * @}
+ */
+
+/** \brief Timer node type size.
+ */
+#if defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+#define TICKER_NODE_T_SIZE      40
+#else
+#if defined(CONFIG_BT_TICKER_EXT)
+#define TICKER_NODE_T_SIZE      48
+#else
+#define TICKER_NODE_T_SIZE      44
+#endif /* CONFIG_BT_TICKER_EXT */
+#endif /* CONFIG_BT_TICKER_COMPATIBILITY_MODE*/
+
+/** \brief Timer user type size.
+ */
+#define TICKER_USER_T_SIZE      8
+
+/** \brief Timer user operation type size.
+ */
+#if defined(CONFIG_BT_TICKER_EXT)
+#define TICKER_USER_OP_T_SIZE   52
+#else
+#define TICKER_USER_OP_T_SIZE   48
+#endif /* CONFIG_BT_TICKER_EXT */
+
+#define TICKER_CALL_ID_NONE     0
+#define TICKER_CALL_ID_ISR      1
+#define TICKER_CALL_ID_TRIGGER  2
+#define TICKER_CALL_ID_WORKER   3
+#define TICKER_CALL_ID_JOB      4
+#define TICKER_CALL_ID_PROGRAM  5
+
+/* Use to ensure callback is invoked in all intervals, even when latencies
+ * occur
+ */
+#define TICKER_LAZY_MUST_EXPIRE 0xFFFF
+
+/* Set this priority to ensure ticker node is always scheduled. Only one
+ * ticker node can have priority TICKER_PRIORITY_CRITICAL at a time
+ */
+#define TICKER_PRIORITY_CRITICAL -128
+
+typedef uint8_t (*ticker_caller_id_get_cb_t)(uint8_t user_id);
+typedef void (*ticker_sched_cb_t)(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+				  void *instance);
+typedef void (*ticker_trigger_set_cb_t)(uint32_t value);
+
+/** \brief Timer timeout function type.
+ */
+typedef void (*ticker_timeout_func) (uint32_t ticks_at_expire, uint32_t remainder,
+				     uint16_t lazy, void *context);
+
+/** \brief Timer operation complete function type.
+ */
+typedef void (*ticker_op_func) (uint32_t status, void *op_context);
+
+#if defined(CONFIG_BT_TICKER_EXT)
+struct ticker_ext {
+	uint32_t ticks_slot_window; /* Window in which the slot
+				  * reservation may be re-scheduled
+				  * to avoid collision
+				  */
+	int32_t ticks_drift;	 /* Applied drift since last expiry */
+	uint8_t  reschedule_state;	 /* State of re-scheduling of the
+				  * node. See defines
+				  * TICKER_RESCHEDULE_STATE_XXX
+				  */
+};
+#endif /* CONFIG_BT_TICKER_EXT */
+
+/** \brief Timer module initialization.
+ *
+ * \param[in]  instance_index  Timer mode instance 0 or 1 (uses RTC0 CMP0 or
+ *				CMP1 respectively).
+ * \param[in]  count_node      Max. no. of ticker nodes to initialize.
+ * \param[in]  node
+ * \param[in]  count_user
+ * \param[in]  user
+ * \param[in]  count_op
+ * \param[in]  user_op
+ */
+uint32_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
+		  uint8_t count_user, void *user, uint8_t count_op, void *user_op,
+		  ticker_caller_id_get_cb_t caller_id_get_cb,
+		  ticker_sched_cb_t sched_cb,
+		  ticker_trigger_set_cb_t trigger_set_cb);
+bool ticker_is_initialized(uint8_t instance_index);
+void ticker_trigger(uint8_t instance_index);
+void ticker_worker(void *param);
+void ticker_job(void *param);
+uint32_t ticker_start(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		   uint32_t ticks_anchor, uint32_t ticks_first, uint32_t ticks_periodic,
+		   uint32_t remainder_periodic, uint16_t lazy, uint32_t ticks_slot,
+		   ticker_timeout_func fp_timeout_func, void *context,
+		   ticker_op_func fp_op_func, void *op_context);
+uint32_t ticker_update(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		    uint32_t ticks_drift_plus, uint32_t ticks_drift_minus,
+		    uint32_t ticks_slot_plus, uint32_t ticks_slot_minus, uint16_t lazy,
+		    uint8_t force, ticker_op_func fp_op_func, void *op_context);
+uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		  ticker_op_func fp_op_func, void *op_context);
+uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		      uint32_t ticks_at_stop, ticker_op_func fp_op_func,
+		      void *op_context);
+uint32_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
+			   uint8_t *ticker_id_head, uint32_t *ticks_current,
+			   uint32_t *ticks_to_expire,
+			   ticker_op_func fp_op_func, void *op_context);
+uint32_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
+			  ticker_op_func fp_op_func, void *op_context);
+void ticker_job_sched(uint8_t instance_index, uint8_t user_id);
+uint32_t ticker_ticks_now_get(void);
+uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old);
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+uint32_t ticker_priority_set(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+			  int8_t priority, ticker_op_func fp_op_func,
+			  void *op_context);
+#if defined(CONFIG_BT_TICKER_EXT)
+uint32_t ticker_start_ext(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		       uint32_t ticks_anchor, uint32_t ticks_first,
+		       uint32_t ticks_periodic, uint32_t remainder_periodic,
+		       uint16_t lazy, uint32_t ticks_slot,
+		       ticker_timeout_func fp_timeout_func, void *context,
+		       ticker_op_func fp_op_func, void *op_context,
+		       struct ticker_ext *ext_data);
+#endif /* CONFIG_BT_TICKER_EXT */
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/ticker/ticker.c	(working copy)
@@ -0,0 +1,2951 @@
+/*
+ * Copyright (c) 2016-2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <zephyr/types.h>
+#include <soc.h>
+
+#include "hal/cntr.h"
+#include "hal/ticker.h"
+
+#include "ticker.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
+#define LOG_MODULE_NAME bt_ctlr_ticker
+#include "common/log.h"
+#include "hal/debug.h"
+
+/*****************************************************************************
+ * Defines
+ ****************************************************************************/
+#define DOUBLE_BUFFER_SIZE 2
+
+/*****************************************************************************
+ * Types
+ ****************************************************************************/
+
+struct ticker_node {
+	uint8_t  next;			 /* Next ticker node */
+
+	uint8_t  req;			 /* Request counter */
+	uint8_t  ack;			 /* Acknowledge counter. Imbalance
+					  * between req and ack indicates
+					  * ongoing operation
+					  */
+	uint8_t  force;			 /* If non-zero, node timeout should
+					  * be forced at next expiration
+					  */
+	uint32_t ticks_periodic;		 /* If non-zero, interval
+					  * between expirations
+					  */
+	uint32_t ticks_to_expire;		 /* Ticks until expiration */
+	ticker_timeout_func timeout_func;/* User timeout function */
+	void  *context;			 /* Context delivered to timeout
+					  * function
+					  */
+	uint32_t ticks_to_expire_minus;	 /* Negative drift correction */
+	uint32_t ticks_slot;		 /* Air-time reservation for node */
+	uint16_t lazy_periodic;		 /* Number of timeouts to allow
+					  * skipping
+					  */
+	uint16_t lazy_current;		 /* Current number of timeouts
+					  * skipped = slave latency
+					  */
+	union {
+		uint32_t remainder_periodic;  /* Sub-microsecond tick remainder
+					       * for each period
+					       */
+		ticker_op_func fp_op_func; /* Operation completion callback */
+	};
+
+	union {
+		uint32_t remainder_current; /* Current sub-microsecond tick
+					  * remainder
+					  */
+		void  *op_context;       /* Context passed in completion
+					  * callback
+					  */
+	};
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+#if  defined(CONFIG_BT_TICKER_EXT)
+	struct ticker_ext *ext_data;	 /* Ticker extension data */
+#endif /* CONFIG_BT_TICKER_EXT */
+	uint8_t  must_expire;		 /* Node must expire, even if it
+					  * collides with other nodes
+					  */
+	int8_t  priority;			 /* Ticker node priority. 0 is default.
+					  * Lower value is higher priority
+					  */
+#endif /* CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+};
+
+/* Operations to be performed in ticker_job.
+ * Possible values for field "op" in struct ticker_user_op
+ */
+#define TICKER_USER_OP_TYPE_NONE         0
+#define TICKER_USER_OP_TYPE_IDLE_GET     1
+#define TICKER_USER_OP_TYPE_SLOT_GET     2
+#define TICKER_USER_OP_TYPE_PRIORITY_SET 3
+#define TICKER_USER_OP_TYPE_START        4
+#define TICKER_USER_OP_TYPE_UPDATE       5
+#define TICKER_USER_OP_TYPE_STOP         6
+#define TICKER_USER_OP_TYPE_STOP_ABS     7
+
+/* Slot window re-schedule states */
+#define TICKER_RESCHEDULE_STATE_NONE     0
+#define TICKER_RESCHEDULE_STATE_PENDING  1
+#define TICKER_RESCHEDULE_STATE_DONE     2
+
+#if defined(CONFIG_BT_TICKER_EXT)
+#define TICKER_RESCHEDULE_PENDING(_ticker) \
+	(_ticker->ext_data && (_ticker->ext_data->reschedule_state == \
+		TICKER_RESCHEDULE_STATE_PENDING))
+#else
+#define TICKER_RESCHEDULE_PENDING(_ticker) 0
+#endif
+
+/* User operation data structure for start opcode. Used for passing start
+ * requests to ticker_job
+ */
+struct ticker_user_op_start {
+	uint32_t ticks_at_start;		/* Anchor ticks (absolute) */
+	uint32_t ticks_first;		/* Initial timeout ticks */
+	uint32_t ticks_periodic;		/* Ticker period ticks */
+	uint32_t remainder_periodic;	/* Sub-microsecond tick remainder */
+	uint16_t lazy;			/* Periodic latency in number of
+					 * periods
+					 */
+	uint32_t ticks_slot;		/* Air-time reservation ticks */
+	ticker_timeout_func fp_timeout_func; /* Timeout callback function */
+	void  *context;			/* Context passed in timeout callback */
+#if defined(CONFIG_BT_TICKER_EXT)
+	struct ticker_ext *ext_data;	/* Ticker extension data instance */
+#endif /* CONFIG_BT_TICKER_EXT */
+};
+
+/* User operation data structure for update opcode. Used for passing update
+ * requests to ticker_job
+ */
+struct ticker_user_op_update {
+	uint32_t ticks_drift_plus;		/* Requested positive drift in ticks */
+	uint32_t ticks_drift_minus;	/* Requested negatice drift in ticks */
+	uint32_t ticks_slot_plus;		/* Number of ticks to add to slot
+					 * reservation (air-time)
+					 */
+	uint32_t ticks_slot_minus;		/* Number of ticks to subtract from
+					 * slot reservation (air-time)
+					 */
+	uint16_t lazy;			/* Slave latency:
+					 *  0: Do nothing
+					 *  1: latency = 0
+					 * >1: latency = lazy - 1
+					 */
+	uint8_t  force;			/* Force update */
+};
+
+/* User operation data structure for stop opcode. Used for passing stop
+ * requests with absolute tick to ticker_job
+ */
+struct ticker_user_op_stop {
+	uint32_t ticks_at_stop;            /* Anchor ticks (absolute) */
+};
+
+/* User operation data structure for slot_get opcode. Used for passing request
+ * to get next ticker with slot ticks via ticker_job
+ */
+struct ticker_user_op_slot_get {
+	uint8_t  *ticker_id;
+	uint32_t *ticks_current;
+	uint32_t *ticks_to_expire;
+};
+
+/* User operation data structure for priority_set opcode. Used for passing
+ * request to set ticker node priority via ticker_job
+ */
+struct ticker_user_op_priority_set {
+	int8_t priority;		   /* Node priority. Defaults to 0 */
+};
+
+/* User operation top level data structure. Used for passing requests to
+ * ticker_job
+ */
+struct ticker_user_op {
+	uint8_t op;		   /* User operation */
+	uint8_t id;		   /* Ticker node id */
+	union {
+		struct ticker_user_op_start        start;
+		struct ticker_user_op_update       update;
+		struct ticker_user_op_stop         stop;
+		struct ticker_user_op_slot_get     slot_get;
+		struct ticker_user_op_priority_set priority_set;
+	} params;		   /* User operation parameters */
+	uint32_t status;		   /* Operation result */
+	ticker_op_func fp_op_func; /* Operation completion callback */
+	void  *op_context;	   /* Context passed in completion callback */
+};
+
+/* User data structure for operations
+ */
+struct ticker_user {
+	uint8_t count_user_op;	   /* Number of user operation slots */
+	uint8_t first;		   /* Slot index of first user operation */
+	uint8_t middle;		   /* Slot index of last managed user op.
+				    * Updated by ticker_job_list_manage
+				    * for use in ticker_job_list_insert
+				    */
+	uint8_t last;		   /* Slot index of last user operation */
+	struct ticker_user_op *user_op; /* Pointer to user operation array */
+};
+
+/* Ticker instance
+ */
+struct ticker_instance {
+	struct ticker_node *nodes; /* Pointer to ticker nodes */
+	struct ticker_user *users; /* Pointer to user nodes */
+	uint8_t  count_node;	   /* Number of ticker nodes */
+	uint8_t  count_user;	   /* Number of user nodes */
+	uint8_t  ticks_elapsed_first; /* Index from which elapsed ticks count is
+				    * pulled
+				    */
+	uint8_t  ticks_elapsed_last;  /* Index to which elapsed ticks count is
+				    * pushed
+				    */
+	uint32_t ticks_elapsed[DOUBLE_BUFFER_SIZE]; /* Buffer for elapsed ticks */
+	uint32_t ticks_current;	   /* Absolute ticks elapsed at last
+				    * ticker_job
+				    */
+	uint32_t ticks_slot_previous; /* Number of ticks previously reserved by a
+				    * ticker node (active air-time)
+				    */
+	uint8_t  ticker_id_slot_previous; /* Id of previous slot reserving ticker
+					* node
+					*/
+	uint8_t  ticker_id_head;      /* Index of first ticker node (next to
+				    * expire)
+				    */
+	uint8_t  job_guard;	   /* Flag preventing ticker_worker from
+				    * running if ticker_job is active
+				    */
+	uint8_t  worker_trigger;	   /* Flag preventing ticker_job from starting
+				    * if ticker_worker was requested, and to
+				    * trigger ticker_worker at end of job, if
+				    * requested
+				    */
+
+	ticker_caller_id_get_cb_t caller_id_get_cb; /* Function for retrieving
+						     * the caller id from user
+						     * id
+						     */
+	ticker_sched_cb_t         sched_cb;	    /* Function for scheduling
+						     * ticker_worker and
+						     * ticker_job
+						     */
+	ticker_trigger_set_cb_t   trigger_set_cb;   /* Function for setting
+						     * the trigger (compare
+						     * value)
+						     */
+};
+
+BUILD_ASSERT(sizeof(struct ticker_node)    == TICKER_NODE_T_SIZE);
+BUILD_ASSERT(sizeof(struct ticker_user)    == TICKER_USER_T_SIZE);
+BUILD_ASSERT(sizeof(struct ticker_user_op) == TICKER_USER_OP_T_SIZE);
+
+/*****************************************************************************
+ * Global instances
+ ****************************************************************************/
+#define TICKER_INSTANCE_MAX 1
+static struct ticker_instance _instance[TICKER_INSTANCE_MAX];
+
+/*****************************************************************************
+ * Static Functions
+ ****************************************************************************/
+
+/**
+ * @brief Update elapsed index
+ *
+ * @param ticks_elapsed_index Pointer to current index
+ *
+ * @internal
+ */
+static inline void ticker_next_elapsed(uint8_t *ticks_elapsed_index)
+{
+	uint8_t idx = *ticks_elapsed_index + 1;
+
+	if (idx == DOUBLE_BUFFER_SIZE) {
+		idx = 0U;
+	}
+	*ticks_elapsed_index = idx;
+}
+
+#if defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+/**
+ * @brief Get ticker expiring in a specific slot
+ *
+ * @details Searches for a ticker which expires in a specific slot starting
+ * at 'ticks_slot'.
+ *
+ * @param node           Pointer to ticker node array
+ * @param ticker_id_head Id of initial ticker node
+ * @param ticks_slot     Ticks indicating slot to get
+ *
+ * @return Id of ticker expiring within slot or TICKER_NULL
+ * @internal
+ */
+static uint8_t ticker_by_slot_get(struct ticker_node *node, uint8_t ticker_id_head,
+			       uint32_t ticks_slot)
+{
+	while (ticker_id_head != TICKER_NULL) {
+		struct ticker_node *ticker;
+		uint32_t ticks_to_expire;
+
+		ticker = &node[ticker_id_head];
+		ticks_to_expire = ticker->ticks_to_expire;
+
+		if (ticks_slot <= ticks_to_expire) {
+			/* Next ticker expiration is outside the checked slot */
+			return TICKER_NULL;
+		}
+
+		if (ticker->ticks_slot) {
+			/* This ticker node has slot defined and expires within
+			 * checked slot
+			 */
+			break;
+		}
+
+		ticks_slot -= ticks_to_expire;
+		ticker_id_head = ticker->next;
+	}
+
+	return ticker_id_head;
+}
+#endif /* CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Get next ticker with slot ticks
+ *
+ * @details Gets the next ticker which has slot ticks specified and
+ * return the ticker id and accumulated ticks until expiration. If no
+ * ticker nodes have slot ticks, the next ticker node is returned.
+ * If no head id is provided (TICKER_NULL) the first node is returned.
+ *
+ * @param instance          Pointer to ticker instance
+ * @param ticker_id_head    Pointer to id of first ticker node [in/out]
+ * @param ticks_current     Pointer to current ticks count [in/out]
+ * @param ticks_to_expire   Pointer to ticks to expire [in/out]
+ *
+ * @internal
+ */
+static void ticker_by_next_slot_get(struct ticker_instance *instance,
+				    uint8_t *ticker_id_head, uint32_t *ticks_current,
+				    uint32_t *ticks_to_expire)
+{
+	struct ticker_node *ticker;
+	struct ticker_node *node;
+	uint32_t _ticks_to_expire;
+	uint8_t _ticker_id_head;
+
+	node = instance->nodes;
+
+	_ticker_id_head = *ticker_id_head;
+	_ticks_to_expire = *ticks_to_expire;
+	if ((_ticker_id_head == TICKER_NULL) ||
+	    (*ticks_current != instance->ticks_current)) {
+		/* Initialize with instance head */
+		_ticker_id_head = instance->ticker_id_head;
+		*ticks_current = instance->ticks_current;
+		_ticks_to_expire = 0U;
+	} else {
+		/* Get ticker id for next node */
+		ticker = &node[_ticker_id_head];
+		_ticker_id_head = ticker->next;
+	}
+
+	/* Find first ticker node with slot ticks */
+	while ((_ticker_id_head != TICKER_NULL) &&
+	       ((ticker = &node[_ticker_id_head])->ticks_slot == 0U)) {
+		/* Accumulate expire ticks */
+		_ticks_to_expire += ticker->ticks_to_expire;
+		_ticker_id_head = ticker->next;
+	}
+
+	if (_ticker_id_head != TICKER_NULL) {
+		/* Add ticks for found ticker */
+		_ticks_to_expire += ticker->ticks_to_expire;
+	}
+
+	*ticker_id_head = _ticker_id_head;
+	*ticks_to_expire = _ticks_to_expire;
+}
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+/**
+ * @brief Enqueue ticker node
+ *
+ * @details Finds insertion point for new ticker node and inserts the
+ * node in the linked node list.
+ *
+ * @param instance Pointer to ticker instance
+ * @param id       Ticker node id to enqueue
+ *
+ * @return Id of enqueued ticker node
+ * @internal
+ */
+static uint8_t ticker_enqueue(struct ticker_instance *instance, uint8_t id)
+{
+	struct ticker_node *ticker_current;
+	struct ticker_node *ticker_new;
+	uint32_t ticks_to_expire_current;
+	struct ticker_node *node;
+	uint32_t ticks_to_expire;
+	uint8_t previous;
+	uint8_t current;
+
+	node = &instance->nodes[0];
+	ticker_new = &node[id];
+	ticks_to_expire = ticker_new->ticks_to_expire;
+	current = instance->ticker_id_head;
+
+	/* Find insertion point for new ticker node and adjust ticks_to_expire
+	 * relative to insertion point
+	 */
+	previous = TICKER_NULL;
+
+	while ((current != TICKER_NULL) && (ticks_to_expire >=
+		(ticks_to_expire_current =
+		(ticker_current = &node[current])->ticks_to_expire))) {
+
+		ticks_to_expire -= ticks_to_expire_current;
+
+		/* Check for timeout in same tick - prioritize according to
+		 * latency
+		 */
+		if (ticks_to_expire == 0 && (ticker_new->lazy_current >
+					     ticker_current->lazy_current)) {
+			ticks_to_expire = ticks_to_expire_current;
+			break;
+		}
+
+		previous = current;
+		current = ticker_current->next;
+	}
+
+	/* Link in new ticker node and adjust ticks_to_expire to relative value
+	 */
+	ticker_new->ticks_to_expire = ticks_to_expire;
+	ticker_new->next = current;
+
+	if (previous == TICKER_NULL) {
+		instance->ticker_id_head = id;
+	} else {
+		node[previous].next = id;
+	}
+
+	if (current != TICKER_NULL) {
+		node[current].ticks_to_expire -= ticks_to_expire;
+	}
+
+	return id;
+}
+#else /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Enqueue ticker node
+ *
+ * @details Finds insertion point for new ticker node and inserts the
+ * node in the linked node list. However, if the new ticker node collides
+ * with an existing node or the expiration is inside the previous slot,
+ * the node is not inserted.
+ *
+ * @param instance Pointer to ticker instance
+ * @param id       Ticker node id to enqueue
+ *
+ * @return Id of enqueued ticker node, or id of previous- or colliding
+ * ticker node if new node was not enqueued
+ * @internal
+ */
+static uint8_t ticker_enqueue(struct ticker_instance *instance, uint8_t id)
+{
+	struct ticker_node *ticker_current;
+	struct ticker_node *ticker_new;
+	uint32_t ticks_to_expire_current;
+	uint8_t ticker_id_slot_previous;
+	uint32_t ticks_slot_previous;
+	struct ticker_node *node;
+	uint32_t ticks_to_expire;
+	uint8_t previous;
+	uint8_t current;
+	uint8_t collide;
+
+	node = &instance->nodes[0];
+	ticker_new = &node[id];
+	ticks_to_expire = ticker_new->ticks_to_expire;
+
+	collide = ticker_id_slot_previous = TICKER_NULL;
+	current = instance->ticker_id_head;
+	previous = current;
+	ticks_slot_previous = instance->ticks_slot_previous;
+
+	/* Find insertion point for new ticker node and adjust ticks_to_expire
+	 * relative to insertion point
+	 */
+	while ((current != TICKER_NULL) &&
+	       (ticks_to_expire >
+		(ticks_to_expire_current =
+		 (ticker_current = &node[current])->ticks_to_expire))) {
+		ticks_to_expire -= ticks_to_expire_current;
+
+		if (ticker_current->ticks_slot != 0U) {
+			ticks_slot_previous = ticker_current->ticks_slot;
+			ticker_id_slot_previous = current;
+		} else {
+			if (ticks_slot_previous > ticks_to_expire_current) {
+				ticks_slot_previous -= ticks_to_expire_current;
+			} else {
+				ticks_slot_previous = 0U;
+			}
+		}
+		previous = current;
+		current = ticker_current->next;
+	}
+
+	/* Check for collision for new ticker node at insertion point */
+	collide = ticker_by_slot_get(&node[0], current,
+				     ticks_to_expire + ticker_new->ticks_slot);
+
+	if ((ticker_new->ticks_slot == 0U) ||
+	    ((ticks_slot_previous <= ticks_to_expire) &&
+	     (collide == TICKER_NULL))) {
+		/* New ticker node has no slot ticks or there is no collision -
+		 * link it in and adjust ticks_to_expire to relative value
+		 */
+		ticker_new->ticks_to_expire = ticks_to_expire;
+		ticker_new->next = current;
+
+		if (previous == current) {
+			instance->ticker_id_head = id;
+		} else {
+			node[previous].next = id;
+		}
+
+		if (current != TICKER_NULL) {
+			node[current].ticks_to_expire -= ticks_to_expire;
+		}
+	} else {
+		/* Collision - no ticker node insertion, set id to that of
+		 * colliding node
+		 */
+		if (ticks_slot_previous > ticks_to_expire) {
+			id = ticker_id_slot_previous;
+		} else {
+			id = collide;
+		}
+	}
+
+	return id;
+}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Dequeue ticker node
+ *
+ * @details Finds extraction point for ticker node to be dequeued, unlinks
+ * the node and adjusts the links and ticks_to_expire. Returns the ticks
+ * until expiration for dequeued ticker node.
+ *
+ * @param instance Pointer to ticker instance
+ * @param id       Ticker node id to dequeue
+ *
+ * @return Total ticks until expiration for dequeued ticker node, or 0 if
+ * node was not found
+ * @internal
+ */
+static uint32_t ticker_dequeue(struct ticker_instance *instance, uint8_t id)
+{
+	struct ticker_node *ticker_current;
+	struct ticker_node *node;
+	uint8_t previous;
+	uint32_t timeout;
+	uint8_t current;
+	uint32_t total;
+
+	/* Find the ticker's position in ticker node list while accumulating
+	 * ticks_to_expire
+	 */
+	node = &instance->nodes[0];
+	previous = instance->ticker_id_head;
+	current = previous;
+	total = 0U;
+	ticker_current = 0;
+	while (current != TICKER_NULL) {
+		ticker_current = &node[current];
+
+		if (current == id) {
+			break;
+		}
+
+		total += ticker_current->ticks_to_expire;
+		previous = current;
+		current = ticker_current->next;
+	}
+
+	if (current == TICKER_NULL) {
+		/* Ticker not in active list */
+		return 0;
+	}
+
+	if (previous == current) {
+		/* Ticker is the first in the list */
+		instance->ticker_id_head = ticker_current->next;
+	}
+
+	/* Remaining timeout between next timeout */
+	timeout = ticker_current->ticks_to_expire;
+
+	/* Link previous ticker with next of this ticker
+	 * i.e. removing the ticker from list
+	 */
+	node[previous].next = ticker_current->next;
+
+	/* If this is not the last ticker, increment the
+	 * next ticker by this ticker timeout
+	 */
+	if (ticker_current->next != TICKER_NULL) {
+		node[ticker_current->next].ticks_to_expire += timeout;
+	}
+
+	return (total + timeout);
+}
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+/**
+ * @brief Resolve ticker node collision
+ *
+ * @details Evaluates the provided ticker node against other queued nodes
+ * and returns non-zero if the ticker node collides and should be skipped.
+ * The following rules are checked:
+ *   1) If the periodic latency is not yet exhausted, node is skipped
+ *   2) If the node has highest possible priority, node is never skipped
+ *   2) If the node will starve next node due to slot reservation
+ *      overlap, node is skipped if:
+ *      a) Next node has higher priority than current node
+ *      b) Next node has more accumulated latency than the current node
+ *      c) Next node is 'older' than current node and has same priority
+ *      d) Next node has force flag set, and the current does not
+ *
+ * @param nodes         Pointer to ticker node array
+ * @param ticker        Pointer to ticker to resolve
+ *
+ * @return 0 if no collision was detected. 1 if ticker node collides
+ * with other ticker node of higher composite priority
+ * @internal
+ */
+static uint8_t ticker_resolve_collision(struct ticker_node *nodes,
+				     struct ticker_node *ticker)
+{
+	if ((ticker->priority != TICKER_PRIORITY_CRITICAL) &&
+	    (ticker->next != TICKER_NULL)) {
+		int32_t lazy_current = ticker->lazy_current;
+
+		/* Check if this ticker node will starve next node which has
+		 * latency or higher priority
+		 */
+		if (lazy_current >= ticker->lazy_periodic) {
+			lazy_current -= ticker->lazy_periodic;
+		}
+		uint8_t  id_head = ticker->next;
+		uint32_t acc_ticks_to_expire = 0U;
+
+		/* Age is time since last expiry */
+		uint32_t current_age = ticker->ticks_periodic +
+				    (lazy_current * ticker->ticks_periodic);
+
+		while (id_head != TICKER_NULL) {
+			struct ticker_node *ticker_next = &nodes[id_head];
+
+			/* Accumulate ticks_to_expire for each node */
+			acc_ticks_to_expire += ticker_next->ticks_to_expire;
+			if (acc_ticks_to_expire > ticker->ticks_slot) {
+				break;
+			}
+
+			/* We only care about nodes with slot reservation */
+			if (ticker_next->ticks_slot == 0U) {
+				id_head = ticker_next->next;
+				continue;
+			}
+
+			int32_t lazy_next = ticker_next->lazy_current;
+			uint8_t  lazy_next_periodic_skip =
+				ticker_next->lazy_periodic > lazy_next;
+
+			if (!lazy_next_periodic_skip) {
+				lazy_next -= ticker_next->lazy_periodic;
+			}
+
+			/* Is the current and next node equal in priority? */
+			uint8_t equal_priority = ticker->priority ==
+				ticker_next->priority;
+
+			/* Age is time since last expiry */
+			uint32_t next_age = (ticker_next->ticks_periodic == 0U ?
+					  0U :
+					 (ticker_next->ticks_periodic -
+					  ticker_next->ticks_to_expire)) +
+					 (lazy_next *
+					  ticker_next->ticks_periodic);
+
+			/* Was the current node scheduled earlier? */
+			uint8_t current_is_older =
+				(ticker->ticks_periodic == 0U) ||
+				(current_age > next_age);
+			/* Was next node scheduled earlier (legacy priority)? */
+			uint8_t next_is_older =
+					(ticker->ticks_periodic != 0U) &&
+					(next_age > current_age);
+
+			/* Is force requested for next node (e.g. update) -
+			 * more so than for current node?
+			 */
+			uint8_t next_force = (ticker_next->force > ticker->force);
+
+			/* Does next node have critical priority and should
+			 * always be scheduled?
+			 */
+			uint8_t next_is_critical = ticker_next->priority ==
+				TICKER_PRIORITY_CRITICAL;
+
+			/* Does next node have higher priority? */
+			uint8_t next_has_priority =
+				(lazy_next - ticker_next->priority) >
+				(lazy_current - ticker->priority);
+
+			/* Check if next node is within this reservation slot
+			 * and wins conflict resolution
+			 */
+			if (!lazy_next_periodic_skip &&
+			    (next_force ||
+			     next_is_critical ||
+			     (next_has_priority && !current_is_older) ||
+			     (equal_priority && next_is_older))) {
+				/* This node must be skipped - check window */
+				return 1U;
+			}
+			id_head = ticker_next->next;
+		}
+	}
+
+	return 0U;
+}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Ticker worker
+ *
+ * @details Runs as upper half of ticker operation, triggered by a compare
+ * match from the underlaying counter HAL, via the ticker_trigger function.
+ * Traverses ticker nodes to find tickers expired since last job
+ * execution. Expired (requested) ticker nodes have their timeout callback
+ * functions called. Finally, a ticker job is enqueued. Invoked from the
+ * ticker worker mayfly context (TICKER_MAYFLY_CALL_ID_WORKER)
+ *
+ * @param param Pointer to ticker instance
+ *
+ */
+void ticker_worker(void *param)
+{
+	struct ticker_instance *instance = param;
+	struct ticker_node *node;
+	uint32_t ticks_elapsed;
+	uint32_t ticks_expired;
+	uint8_t ticker_id_head;
+
+	/* Defer worker if job running */
+	instance->worker_trigger = 1U;
+	if (instance->job_guard) {
+		return;
+	}
+
+	/* If no tickers queued (active), do nothing */
+	if (instance->ticker_id_head == TICKER_NULL) {
+		instance->worker_trigger = 0U;
+		return;
+	}
+
+	/* Get ticks elapsed since last job execution */
+	ticks_elapsed = ticker_ticks_diff_get(cntr_cnt_get(),
+					      instance->ticks_current);
+
+	/* Initialize actual elapsed ticks being consumed */
+	ticks_expired = 0U;
+
+	/* Auto variable containing the head of tickers expiring */
+	ticker_id_head = instance->ticker_id_head;
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+	/* Check if the previous ticker node which had air-time, is still
+	 * active and has this time slot reserved
+	 */
+	uint8_t slot_reserved = 0;
+
+	if (instance->ticker_id_slot_previous != TICKER_NULL) {
+		if (instance->ticks_slot_previous > ticks_elapsed) {
+			/* This node intersects reserved slot */
+			slot_reserved = 1;
+		}
+	}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+	/* Expire all tickers within ticks_elapsed and collect ticks_expired */
+	node = &instance->nodes[0];
+
+	while (ticker_id_head != TICKER_NULL) {
+		struct ticker_node *ticker;
+		uint32_t ticks_to_expire;
+		uint8_t must_expire_skip;
+
+		ticker = &node[ticker_id_head];
+
+		/* Stop if ticker did not expire */
+		ticks_to_expire = ticker->ticks_to_expire;
+		if (ticks_elapsed < ticks_to_expire) {
+			break;
+		}
+
+		/* Decrement ticks_elapsed and collect expired ticks */
+		ticks_elapsed -= ticks_to_expire;
+		ticks_expired += ticks_to_expire;
+
+		/* Move to next ticker node */
+		ticker_id_head = ticker->next;
+		must_expire_skip = 0U;
+
+		/* Skip if not scheduled to execute */
+		if (((ticker->req - ticker->ack) & 0xff) != 1U) {
+			continue;
+		}
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+		/* Check if node has slot reservation and resolve any collision
+		 * with other ticker nodes
+		 */
+		if (ticker->ticks_slot != 0U &&
+		   (slot_reserved || ticker_resolve_collision(node, ticker))) {
+#if defined(CONFIG_BT_TICKER_EXT)
+			struct ticker_ext *ext_data = ticker->ext_data;
+
+			if (ext_data &&
+			    ext_data->ticks_slot_window != 0U &&
+			    ext_data->reschedule_state ==
+			    TICKER_RESCHEDULE_STATE_NONE &&
+			   (ticker->lazy_periodic <= ticker->lazy_current)) {
+				/* Mark node for re-scheduling in ticker_job */
+				ext_data->reschedule_state =
+					TICKER_RESCHEDULE_STATE_PENDING;
+			} else if (ext_data) {
+				/* Mark node as not re-scheduling */
+				ext_data->reschedule_state =
+					TICKER_RESCHEDULE_STATE_NONE;
+			}
+#endif /* CONFIG_BT_TICKER_EXT */
+			ticker->lazy_current++;
+
+			if ((ticker->must_expire == 0U) ||
+			    (ticker->lazy_periodic >= ticker->lazy_current) ||
+			    TICKER_RESCHEDULE_PENDING(ticker)) {
+				/* Not a must-expire case, this is programmed
+				 * latency or pending re-schedule. Skip this
+				 * ticker node.
+				 */
+				continue;
+			}
+			/* Continue but perform shallow expiry */
+			must_expire_skip = 1U;
+		}
+
+#if defined(CONFIG_BT_TICKER_EXT)
+		if (ticker->ext_data) {
+			ticker->ext_data->ticks_drift = 0U;
+			/* Mark node as not re-scheduling */
+			ticker->ext_data->reschedule_state =
+				TICKER_RESCHEDULE_STATE_NONE;
+		}
+#endif /* CONFIG_BT_TICKER_EXT */
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+		/* Scheduled timeout is acknowledged to be complete */
+		ticker->ack--;
+
+		if (ticker->timeout_func) {
+			uint32_t ticks_at_expire;
+
+			ticks_at_expire = (instance->ticks_current +
+					   ticks_expired -
+					   ticker->ticks_to_expire_minus) &
+					   HAL_TICKER_CNTR_MASK;
+
+			DEBUG_TICKER_TASK(1);
+			/* Invoke the timeout callback */
+			ticker->timeout_func(ticks_at_expire,
+					     ticker->remainder_current,
+					     must_expire_skip ?
+					     TICKER_LAZY_MUST_EXPIRE :
+					     ticker->lazy_current,
+					     ticker->context);
+			DEBUG_TICKER_TASK(0);
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+			if (must_expire_skip == 0U) {
+				/* Reset latency to periodic offset */
+				ticker->lazy_current = 0U;
+				ticker->force = 0U;
+				if (ticker->ticks_slot != 0U) {
+					/* Any further nodes will be skipped */
+					slot_reserved = 1U;
+				}
+			}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+		}
+	}
+
+	/* Queue the elapsed ticks */
+	if (instance->ticks_elapsed_first == instance->ticks_elapsed_last) {
+		ticker_next_elapsed(&instance->ticks_elapsed_last);
+	}
+	instance->ticks_elapsed[instance->ticks_elapsed_last] = ticks_expired;
+
+	instance->worker_trigger = 0U;
+
+	/* Enqueue the ticker job with chain=1 (do not inline) */
+	instance->sched_cb(TICKER_CALL_ID_WORKER, TICKER_CALL_ID_JOB, 1,
+			   instance);
+}
+
+/**
+ * @brief Prepare ticker node expiration
+ *
+ * @details Calculates the number of ticks until next expiration, taking
+ * into consideration any negative drift correction.
+ *
+ * @param ticker         Pointer to ticker node
+ * @param ticks_current  Current number of ticks (elapsed)
+ * @param ticks_at_start Number of ticks at start (anchor)
+ *
+ * @internal
+ */
+static void ticks_to_expire_prep(struct ticker_node *ticker,
+				 uint32_t ticks_current, uint32_t ticks_at_start)
+{
+	uint32_t ticks_to_expire = ticker->ticks_to_expire;
+	uint32_t ticks_to_expire_minus = ticker->ticks_to_expire_minus;
+
+	/* Calculate ticks to expire for this new node */
+	if (!((ticks_at_start - ticks_current) & BIT(HAL_TICKER_CNTR_MSBIT))) {
+		/* Most significant bit is 0 so ticks_at_start lies ahead of
+		 * ticks_current: ticks_at_start >= ticks_current
+		 */
+		ticks_to_expire += ticker_ticks_diff_get(ticks_at_start,
+							 ticks_current);
+	} else {
+		/* ticks_current > ticks_at_start
+		 */
+		uint32_t delta_current_start;
+
+		delta_current_start = ticker_ticks_diff_get(ticks_current,
+							    ticks_at_start);
+		if (ticks_to_expire > delta_current_start) {
+			/* There's still time until expiration - subtract
+			 * elapsed time
+			 */
+			ticks_to_expire -= delta_current_start;
+		} else {
+			/* Ticker node should have expired (we're late).
+			 * Add 'lateness' to negative drift correction
+			 * (ticks_to_expire_minus) and set ticks_to_expire
+			 * to 0
+			 */
+			ticks_to_expire_minus +=
+			    (delta_current_start - ticks_to_expire);
+			ticks_to_expire = 0U;
+		}
+	}
+
+	/* Handle negative drift correction */
+	if (ticks_to_expire > ticks_to_expire_minus) {
+		ticks_to_expire -= ticks_to_expire_minus;
+		ticks_to_expire_minus = 0U;
+	} else {
+		ticks_to_expire_minus -= ticks_to_expire;
+		ticks_to_expire = 0U;
+	}
+
+	/* Update ticker */
+	ticker->ticks_to_expire = ticks_to_expire;
+	ticker->ticks_to_expire_minus = ticks_to_expire_minus;
+}
+
+/**
+ * @brief Increment remainder
+ *
+ * @details Calculates whether the remainder should increments expiration time
+ * for above-microsecond precision counter HW. The remainder enables improved
+ * ticker precision, but is disabled for for sub-microsecond precision
+ * configurations.
+ *
+ * @param ticker Pointer to ticker node
+ *
+ * @return Returns 1 to indicate increment is due, otherwise 0
+ * @internal
+ */
+static uint8_t ticker_remainder_inc(struct ticker_node *ticker)
+{
+#ifdef HAL_TICKER_REMAINDER_RANGE
+	ticker->remainder_current += ticker->remainder_periodic;
+	if ((ticker->remainder_current < BIT(31)) &&
+	    (ticker->remainder_current > (HAL_TICKER_REMAINDER_RANGE >> 1))) {
+		ticker->remainder_current -= HAL_TICKER_REMAINDER_RANGE;
+		return 1;
+	}
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Decrement remainder
+ *
+ * @details Calculates whether the remainder should decrements expiration time
+ * for above-microsecond precision counter HW. The remainder enables improved
+ * ticker precision, but is disabled for for sub-microsecond precision
+ * configurations.
+ *
+ * @param ticker Pointer to ticker node
+ *
+ * @return Returns 1 to indicate decrement is due, otherwise 0
+ * @internal
+ */
+static uint8_t ticker_remainder_dec(struct ticker_node *ticker)
+{
+#ifdef HAL_TICKER_REMAINDER_RANGE
+	uint8_t decrement = 0U;
+
+	if ((ticker->remainder_current >= BIT(31)) ||
+	    (ticker->remainder_current <= (HAL_TICKER_REMAINDER_RANGE >> 1))) {
+		decrement++;
+		ticker->remainder_current += HAL_TICKER_REMAINDER_RANGE;
+	}
+	ticker->remainder_current -= ticker->remainder_periodic;
+	return decrement;
+#else
+	return 0;
+#endif
+}
+
+/**
+ * @brief Invoke user operation callback
+ *
+ * @param user_op Pointer to user operation struct
+ * @param status  User operation status to pass to callback
+ *
+ * @internal
+ */
+static void ticker_job_op_cb(struct ticker_user_op *user_op, uint32_t status)
+{
+	user_op->op = TICKER_USER_OP_TYPE_NONE;
+	user_op->status = status;
+	if (user_op->fp_op_func) {
+		user_op->fp_op_func(user_op->status, user_op->op_context);
+	}
+}
+
+/**
+ * @brief Update and insert ticker node
+ *
+ * @details Update ticker node with parameters passed in user operation.
+ * After update, the ticker is inserted in front as new head.
+ *
+ * @param ticker	Pointer to ticker node
+ * @param user_op	Pointer to user operation
+ * @param ticks_current	Current ticker instance ticks
+ * @param ticks_elapsed	Expired ticks at time of call
+ * @param insert_head	Pointer to current head (id). Contains id
+ *			from user operation upon exit
+ * @internal
+ */
+static inline void ticker_job_node_update(struct ticker_node *ticker,
+					  struct ticker_user_op *user_op,
+					  uint32_t ticks_current,
+					  uint32_t ticks_elapsed,
+					  uint8_t *insert_head)
+{
+	uint32_t ticks_to_expire = ticker->ticks_to_expire;
+	uint32_t ticks_now;
+
+	ticks_now = cntr_cnt_get();
+	ticks_elapsed += ticker_ticks_diff_get(ticks_now, ticks_current);
+	if (ticks_to_expire > ticks_elapsed) {
+		ticks_to_expire -= ticks_elapsed;
+	} else {
+		ticker->ticks_to_expire_minus += ticks_elapsed -
+						 ticks_to_expire;
+		ticks_to_expire = 0U;
+	}
+
+	/* Update ticks_to_expire from latency (lazy) input */
+	if ((ticker->ticks_periodic != 0U) &&
+	    (user_op->params.update.lazy != 0U)) {
+		user_op->params.update.lazy--;
+		while ((ticks_to_expire > ticker->ticks_periodic) &&
+		       (ticker->lazy_current > user_op->params.update.lazy)) {
+			ticks_to_expire -= ticker->ticks_periodic +
+					   ticker_remainder_dec(ticker);
+			ticker->lazy_current--;
+		}
+
+		while (ticker->lazy_current < user_op->params.update.lazy) {
+			ticks_to_expire += ticker->ticks_periodic +
+					   ticker_remainder_inc(ticker);
+			ticker->lazy_current++;
+		}
+		ticker->lazy_periodic = user_op->params.update.lazy;
+	}
+
+	/* Update ticks_to_expire from drift input */
+	ticker->ticks_to_expire = ticks_to_expire +
+				  user_op->params.update.ticks_drift_plus;
+	ticker->ticks_to_expire_minus +=
+				user_op->params.update.ticks_drift_minus;
+
+#if defined(CONFIG_BT_TICKER_EXT)
+	/* TODO: An improvement on this could be to only consider the drift
+	 * (ADV => randomization) if re-sceduling fails. We would still store
+	 * the drift ticks here, but not actually update the node. That would
+	 * allow the ticker to use the full window for re-scheduling.
+	 */
+	struct ticker_ext *ext_data = ticker->ext_data;
+
+	if (ext_data && ext_data->ticks_slot_window != 0U) {
+		ext_data->ticks_drift =
+			user_op->params.update.ticks_drift_plus -
+			user_op->params.update.ticks_drift_minus;
+	}
+#endif /* CONFIG_BT_TICKER_EXT */
+
+	ticks_to_expire_prep(ticker, ticks_current, ticks_now);
+
+	/* Update ticks_slot parameter from plus/minus input */
+	ticker->ticks_slot += user_op->params.update.ticks_slot_plus;
+	if (ticker->ticks_slot > user_op->params.update.ticks_slot_minus) {
+		ticker->ticks_slot -= user_op->params.update.ticks_slot_minus;
+	} else {
+		ticker->ticks_slot = 0U;
+	}
+
+	/* Update force parameter */
+	if (user_op->params.update.force != 0U) {
+		ticker->force = user_op->params.update.force;
+	}
+
+	ticker->next = *insert_head;
+	*insert_head = user_op->id;
+}
+
+/**
+ * @brief Manage user update operation
+ *
+ * @details Called by ticker_job to execute an update request, or set node
+ * as done if request is not update. Invokes user operation callback before
+ * exit.
+ *
+ * @param instance	Pointer to ticker instance
+ * @param ticker	Pointer to ticker node
+ * @param user_op	Pointer to user operation
+ * @param ticks_elapsed Expired ticks at time of call
+ * @param insert_head	Pointer to current head (id). For update operation,
+ *			contains operation id upon exit
+ * @internal
+ */
+static inline void ticker_job_node_manage(struct ticker_instance *instance,
+					  struct ticker_node *ticker,
+					  struct ticker_user_op *user_op,
+					  uint32_t ticks_elapsed,
+					  uint8_t *insert_head)
+{
+	/* Remove ticker node from list */
+	ticker->ticks_to_expire = ticker_dequeue(instance, user_op->id);
+
+	/* Handle update of ticker by re-inserting it back. */
+	if (user_op->op == TICKER_USER_OP_TYPE_UPDATE) {
+		ticker_job_node_update(ticker, user_op, instance->ticks_current,
+				       ticks_elapsed, insert_head);
+
+		/* Set schedule status of node
+		 * as updating.
+		 */
+		ticker->req++;
+	} else {
+		/* Reset schedule status of node */
+		ticker->req = ticker->ack;
+
+		if (instance->ticker_id_slot_previous == user_op->id) {
+			uint32_t ticks_current;
+			uint32_t ticks_at_stop;
+			uint32_t ticks_used;
+
+			instance->ticker_id_slot_previous = TICKER_NULL;
+
+			if (user_op->op == TICKER_USER_OP_TYPE_STOP_ABS) {
+				ticks_at_stop =
+					user_op->params.stop.ticks_at_stop;
+			} else {
+				ticks_at_stop = cntr_cnt_get();
+			}
+
+			ticks_current = instance->ticks_current;
+			if (!((ticks_at_stop - ticks_current) &
+			      BIT(HAL_TICKER_CNTR_MSBIT))) {
+				ticks_used = ticks_elapsed +
+					ticker_ticks_diff_get(ticks_at_stop,
+							      ticks_current);
+			} else {
+				ticks_used =
+					ticker_ticks_diff_get(ticks_current,
+							      ticks_at_stop);
+				if (ticks_elapsed > ticks_used) {
+					ticks_used = ticks_elapsed -
+						     ticks_used;
+				} else {
+					ticks_used = 0;
+				}
+			}
+
+			if (instance->ticks_slot_previous > ticks_used) {
+				instance->ticks_slot_previous = ticks_used;
+			}
+		}
+	}
+
+	/* op success, @todo update may fail during
+	 * actual insert! need to design that yet.
+	 */
+	ticker_job_op_cb(user_op, TICKER_STATUS_SUCCESS);
+}
+
+/**
+ * @brief Manage user operations list
+ *
+ * @details Called by ticker_job to execute requested user operations. A
+ * number of operation may be queued since last ticker_job. Only update and
+ * stop operations are handled. Start is handled implicitly by inserting
+ * the ticker node in ticker_job_list_insert.
+ *
+ * @param instance	Pointer to ticker instance
+ * @param ticks_elapsed Expired ticks at time of call
+ * @param insert_head	Pointer to current head (id). For update operation,
+ *			contains operation id upon exit
+ * @return Returns 1 if operations is pending, 0 if all operations are done.
+ * @internal
+ */
+static inline uint8_t ticker_job_list_manage(struct ticker_instance *instance,
+					  uint32_t ticks_elapsed,
+					  uint8_t *insert_head)
+{
+	uint8_t pending;
+	struct ticker_node *node;
+	struct ticker_user *users;
+	uint8_t count_user;
+
+	pending = 0U;
+	node = &instance->nodes[0];
+	users = &instance->users[0];
+	count_user = instance->count_user;
+	/* Traverse users - highest id first */
+	while (count_user--) {
+		struct ticker_user *user;
+		struct ticker_user_op *user_ops;
+
+		user = &users[count_user];
+		user_ops = &user->user_op[0];
+		/* Traverse user operation queue - middle to last (with wrap).
+		 * This operation updates user->middle to be the past the last
+		 * processed user operation. This is used later by
+		 * ticker_job_list_insert, for handling user->first to middle.
+		 */
+		while (user->middle != user->last) {
+			struct ticker_user_op *user_op;
+			struct ticker_node *ticker;
+			uint8_t state;
+			uint8_t prev;
+			uint8_t middle;
+
+			user_op = &user_ops[user->middle];
+
+			/* Increment index and handle wrapping */
+			prev = user->middle;
+			middle = user->middle + 1;
+			if (middle == user->count_user_op) {
+				middle = 0U;
+			}
+			user->middle = middle;
+
+			ticker = &node[user_op->id];
+
+			/* if op is start, then skip update and stop ops */
+			if (user_op->op < TICKER_USER_OP_TYPE_UPDATE) {
+				continue;
+			}
+
+			/* determine the ticker state */
+			state = (ticker->req - ticker->ack) & 0xff;
+
+			/* if not started or update not required,
+			 * set status and continue.
+			 */
+			if ((user_op->op > TICKER_USER_OP_TYPE_STOP_ABS) ||
+			    (state == 0U) ||
+			    ((user_op->op == TICKER_USER_OP_TYPE_UPDATE) &&
+			     (user_op->params.update.ticks_drift_plus == 0U) &&
+			     (user_op->params.update.ticks_drift_minus == 0U) &&
+			     (user_op->params.update.ticks_slot_plus == 0U) &&
+			     (user_op->params.update.ticks_slot_minus == 0U) &&
+			     (user_op->params.update.lazy == 0U) &&
+			     (user_op->params.update.force == 0U))) {
+				ticker_job_op_cb(user_op,
+						 TICKER_STATUS_FAILURE);
+				continue;
+			}
+
+			/* Delete node, if not expired */
+			if (state == 1U) {
+				ticker_job_node_manage(instance, ticker,
+						       user_op, ticks_elapsed,
+						       insert_head);
+			} else {
+				/* Update on expired node requested, defering
+				 * update until bottom half finishes.
+				 */
+				/* sched job to run after worker bottom half.
+				 */
+				instance->sched_cb(TICKER_CALL_ID_JOB,
+						   TICKER_CALL_ID_JOB, 1,
+						   instance);
+
+				/* Update the index upto which management is
+				 * complete.
+				 */
+				user->middle = prev;
+
+				pending = 1U;
+				break;
+			}
+		}
+	}
+
+	return pending;
+}
+
+/**
+ * @brief Handle ticker node expirations
+ *
+ * @details Called by ticker_job to schedule next expirations. Expired ticker
+ * nodes are removed from the active list, and re-inserted if periodic.
+ *
+ * @param instance	 Pointer to ticker instance
+ * @param ticks_previous Absolute ticks at ticker_job start
+ * @param ticks_elapsed  Expired ticks at time of call
+ * @param insert_head	 Pointer to current head (id). Updated if nodes are
+ *			 re-inserted
+ * @internal
+ */
+static inline void ticker_job_worker_bh(struct ticker_instance *instance,
+					uint32_t ticks_previous,
+					uint32_t ticks_elapsed,
+					uint8_t *insert_head)
+{
+	struct ticker_node *node;
+	uint32_t ticks_expired;
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+	uint32_t ticks_latency;
+	uint32_t ticks_now;
+
+	ticks_now = cntr_cnt_get();
+	ticks_latency = ticker_ticks_diff_get(ticks_now, ticks_previous);
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+	node = &instance->nodes[0];
+	ticks_expired = 0U;
+	while (instance->ticker_id_head != TICKER_NULL) {
+		uint8_t is_must_expire_skip = 0U;
+		struct ticker_node *ticker;
+		uint32_t ticks_to_expire;
+		uint8_t id_expired;
+
+		/* auto variable for current ticker node */
+		id_expired = instance->ticker_id_head;
+		ticker = &node[id_expired];
+
+		/* Do nothing if ticker did not expire */
+		ticks_to_expire = ticker->ticks_to_expire;
+		if (ticks_elapsed < ticks_to_expire) {
+			ticker->ticks_to_expire -= ticks_elapsed;
+			break;
+		}
+
+		/* decrement ticks_elapsed and collect expired ticks */
+		ticks_elapsed -= ticks_to_expire;
+		ticks_expired += ticks_to_expire;
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+		ticks_latency -= ticks_to_expire;
+
+		is_must_expire_skip = (ticker->must_expire &&
+				       (ticker->lazy_current != 0U));
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+		/* decrement ticks_slot_previous */
+		if (instance->ticks_slot_previous > ticks_to_expire) {
+			instance->ticks_slot_previous -= ticks_to_expire;
+		} else {
+			instance->ticker_id_slot_previous = TICKER_NULL;
+			instance->ticks_slot_previous = 0U;
+		}
+
+		/* If a reschedule is set pending, we will need to keep
+		 * the slot_previous information
+		 */
+		if ((ticker->ticks_slot != 0U) &&
+		    (((ticker->req - ticker->ack) & 0xff) == 2U) &&
+		    !is_must_expire_skip &&
+		    !TICKER_RESCHEDULE_PENDING(ticker)) {
+			instance->ticker_id_slot_previous = id_expired;
+			instance->ticks_slot_previous = ticker->ticks_slot;
+		}
+
+		/* ticker expired, set ticks_to_expire zero */
+		ticker->ticks_to_expire = 0U;
+
+		/* remove the expired ticker from head */
+		instance->ticker_id_head = ticker->next;
+
+		/* Ticker will be restarted if periodic or to be re-scheduled */
+		if ((ticker->ticks_periodic != 0U) ||
+		    TICKER_RESCHEDULE_PENDING(ticker)) {
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+			if (TICKER_RESCHEDULE_PENDING(ticker)) {
+				/* Set the re-scheduled node to now. Will be
+				 * collision resolved after all nodes are
+				 * restarted
+				 */
+				ticker->ticks_to_expire = ticks_elapsed;
+
+				/* Reset ticker state, so that its put
+				 * back in requested state later down
+				 * in the code.
+				 */
+				ticker->req = ticker->ack;
+			} else {
+				uint16_t lazy_periodic;
+				uint32_t count;
+				uint16_t lazy;
+
+				/* If not skipped, apply lazy_periodic */
+				if (!ticker->lazy_current) {
+					lazy_periodic = ticker->lazy_periodic;
+				} else {
+					lazy_periodic = 0U;
+
+					/* Reset ticker state, so that its put
+					 * back in requested state later down
+					 * in the code.
+					 */
+					ticker->req = ticker->ack;
+				}
+
+				/* Reload ticks_to_expire with atleast one
+				 * period.
+				 */
+				ticks_to_expire = 0U;
+				count = 1 + lazy_periodic;
+				while (count--) {
+					ticks_to_expire +=
+						ticker->ticks_periodic;
+					ticks_to_expire +=
+						ticker_remainder_inc(ticker);
+				}
+
+				/* Skip intervals that have elapsed w.r.t.
+				 * current ticks.
+				 */
+				lazy = 0U;
+				if (!ticker->must_expire) {
+					while (ticks_to_expire <
+					       ticks_latency) {
+						ticks_to_expire +=
+							ticker->ticks_periodic;
+						ticks_to_expire +=
+						  ticker_remainder_inc(ticker);
+						lazy++;
+					}
+				}
+
+				/* Use the calculated ticks to expire and
+				 * laziness.
+				 */
+				ticker->ticks_to_expire = ticks_to_expire;
+				ticker->lazy_current += (lazy_periodic + lazy);
+			}
+
+			ticks_to_expire_prep(ticker, instance->ticks_current,
+					     (ticks_previous + ticks_expired));
+#else /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+			uint32_t count;
+
+			/* Prepare for next interval */
+			ticks_to_expire = 0U;
+			count = 1 + ticker->lazy_periodic;
+			while (count--) {
+				ticks_to_expire += ticker->ticks_periodic;
+				ticks_to_expire += ticker_remainder_inc(ticker);
+			}
+			ticker->ticks_to_expire = ticks_to_expire;
+
+			ticks_to_expire_prep(ticker, instance->ticks_current,
+					     (ticks_previous + ticks_expired));
+
+			/* Reset latency to periodic offset */
+			ticker->lazy_current = ticker->lazy_periodic;
+			ticker->force = 0U;
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+			/* Add to insert list */
+			ticker->next = *insert_head;
+			*insert_head = id_expired;
+
+			/* set schedule status of node as restarting. */
+			ticker->req++;
+		} else {
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+			if ((((ticker->req - ticker->ack) & 0xff) == 1U) &&
+			    ticker->fp_op_func) {
+				ticker->fp_op_func(TICKER_STATUS_FAILURE,
+						   ticker->op_context);
+			}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+			/* reset schedule status of node */
+			ticker->req = ticker->ack;
+		}
+	}
+}
+
+/**
+ * @brief Prepare ticker node start
+ *
+ * @details Called by ticker_job to prepare ticker node start operation.
+ *
+ * @param ticker	Pointer to ticker node
+ * @param user_op	Pointer to user operation
+ * @param ticks_current Expired ticks at time of call
+ *
+ * @internal
+ */
+static inline void ticker_job_op_start(struct ticker_node *ticker,
+				       struct ticker_user_op *user_op,
+				       uint32_t ticks_current)
+{
+	struct ticker_user_op_start *start = (void *)&user_op->params.start;
+
+#if defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+	/* Must expire is not supported in compatibility mode */
+	LL_ASSERT(start->lazy != TICKER_LAZY_MUST_EXPIRE);
+#else
+	ticker->must_expire = (start->lazy == TICKER_LAZY_MUST_EXPIRE) ? 1U :
+			       0U;
+#if defined(CONFIG_BT_TICKER_EXT)
+	ticker->ext_data = start->ext_data;
+#endif /* CONFIG_BT_TICKER_EXT */
+#endif /* CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+	ticker->ticks_periodic = start->ticks_periodic;
+	ticker->remainder_periodic = start->remainder_periodic;
+	ticker->lazy_periodic = (start->lazy == TICKER_LAZY_MUST_EXPIRE) ? 0U :
+				 start->lazy;
+	ticker->ticks_slot = start->ticks_slot;
+	ticker->timeout_func = start->fp_timeout_func;
+	ticker->context = start->context;
+	ticker->ticks_to_expire = start->ticks_first;
+	ticker->ticks_to_expire_minus = 0U;
+	ticks_to_expire_prep(ticker, ticks_current, start->ticks_at_start);
+	ticker->remainder_current = 0U;
+	ticker->lazy_current = 0U;
+	ticker->force = 1U;
+}
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+/**
+ * @brief Insert new ticker node
+ *
+ * @details Called by ticker_job to insert a new ticker node. If node collides
+ * with existing ticker nodes, either the new node is postponed, or colliding
+ * node is un-scheduled. Decision is based on latency and the force-state of
+ * individual nodes.
+ *
+ * @param instance    Pointer to ticker instance
+ * @param id_insert   Id of ticker to insert
+ * @param ticker      Pointer to ticker node to insert
+ * @param insert_head Pointer to current head. Updated if colliding nodes
+ *		      are un-scheduled
+ * @internal
+ */
+static inline uint32_t ticker_job_insert(struct ticker_instance *instance,
+				      uint8_t id_insert,
+				      struct ticker_node *ticker,
+				      uint8_t *insert_head)
+{
+	ARG_UNUSED(insert_head);
+
+	/* Prepare to insert */
+	ticker->next = TICKER_NULL;
+
+	/* Enqueue the ticker node */
+	(void)ticker_enqueue(instance, id_insert);
+
+	/* Inserted/Scheduled */
+	ticker->req = ticker->ack + 1;
+
+	return TICKER_STATUS_SUCCESS;
+}
+
+#if defined(CONFIG_BT_TICKER_EXT)
+/**
+ * @brief Re-schedule ticker nodes within slot_window
+ *
+ * @details This function is responsible for re-scheduling ticker nodes
+ * which have been marked for re-scheduling in ticker_worker. These nodes
+ * have a non-zero ticks_slot_window configuration, which indicates a
+ * valid range in which to re-schedule the node.
+ * The function iterates over nodes, and handles one re-schedule at a
+ * time. After a re-schedule, nodes are once again iterated until no more
+ * nodes are marked for re-scheduling.
+ *
+ * @param instance      Pointer to ticker instance
+ * @param ticks_elapsed Number of ticks elapsed since last ticker job
+ *
+ * @internal
+ */
+static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance,
+					    uint32_t ticks_elapsed)
+{
+	struct ticker_node *nodes;
+	struct ticker_node *ticker;
+	struct ticker_node *node;
+	struct ticker_ext  *ext_data;
+
+	uint32_t window_start_ticks;
+	uint32_t window_end_ticks;
+	uint32_t ticks_to_expire;
+	uint32_t ticks_start_offset;
+	uint32_t ticks_slot_window = 0;
+
+	uint8_t  ticker_id_head;
+	uint8_t  ticker_id_iter;
+	uint8_t  ticker_id_prev;
+
+	uint8_t  rescheduling = 1U;
+	uint8_t  rescheduled = 0U;
+
+	nodes = &instance->nodes[0];
+
+	/* Do until all pending re-schedules handled */
+	while (rescheduling) {
+		ticker_id_head = instance->ticker_id_head;
+		rescheduling = 0U;
+
+		ticks_start_offset = 0U;
+		window_start_ticks = 0U;
+		window_end_ticks   = 0U;
+		ticks_to_expire    = 0U;
+
+		/* Find first pending re-schedule */
+		while (ticker_id_head != TICKER_NULL) {
+			ticker = &nodes[ticker_id_head];
+			ext_data = ticker->ext_data;
+			if (ext_data && ext_data->reschedule_state ==
+			    TICKER_RESCHEDULE_STATE_PENDING) {
+				/* Pending reschedule found */
+				break;
+			}
+			ticker_id_head = ticker->next;
+		}
+		if (ticker_id_head == TICKER_NULL) {
+			/* Done */
+			break;
+		}
+
+		/* Check for intersection with already active node */
+		if (instance->ticker_id_slot_previous != TICKER_NULL &&
+			instance->ticks_slot_previous > ticks_elapsed) {
+			/* Active node intersects - window starts after end of
+			 * active slot
+			 */
+			window_start_ticks = instance->ticks_slot_previous -
+					     ticks_elapsed;
+		}
+
+		ticker_id_iter = nodes[ticker_id_head].next;
+		ticker_id_prev = TICKER_NULL;
+
+		/* If drift was applied to this node, this must be
+		 * taken into consideration. Reduce the window with
+		 * the amount of drift already applied.
+		 *
+		 * TODO: An improvement on this could be to only consider the
+		 * drift (ADV => randomization) if re-sceduling fails. Then the
+		 * ticker would have the best possible window to re-schedule in
+		 * and not be restricted to ticks_slot_window - ticks_drift.
+		 */
+		if (ext_data->ticks_drift < ext_data->ticks_slot_window) {
+			ticks_slot_window = ext_data->ticks_slot_window -
+					    ext_data->ticks_drift;
+		} else {
+			/* Window has been exhausted - we can't reschedule */
+			ticker_id_iter = TICKER_NULL;
+		}
+
+		/* Try to find available slot for re-scheduling */
+		while (ticker_id_iter != TICKER_NULL &&
+		       ticks_start_offset + ticker->ticks_slot <=
+		       ticks_slot_window) {
+
+			node = &nodes[ticker_id_iter];
+
+			if (node->ext_data &&
+			    node->ext_data->reschedule_state ==
+			    TICKER_RESCHEDULE_STATE_PENDING) {
+				/* Skip other pending re-schedule nodes */
+				ticker_id_iter = node->next;
+				continue;
+			}
+
+			/* Calculate end of window. Since window may be aligned
+			 * with expiry of next node, we add a margin
+			 */
+			if (node->ticks_to_expire >
+			    HAL_TICKER_RESCHEDULE_MARGIN) {
+				window_end_ticks =
+					MIN(ticks_slot_window,
+					    ticks_start_offset +
+					    node->ticks_to_expire -
+					    HAL_TICKER_RESCHEDULE_MARGIN);
+			} else {
+				/* Next expiry is too close - try the next
+				 * node
+				 */
+				window_end_ticks = 0;
+			}
+
+			/* Calculate new ticks_to_expire as end of window minus
+			 * slot size => place at end of window.
+			 */
+			if (window_end_ticks > ticks_start_offset +
+			    ticker->ticks_slot) {
+				ticks_to_expire = window_end_ticks -
+					ticker->ticks_slot;
+			} else {
+				/* No space in window - try the next node */
+				ticks_to_expire = 0;
+			}
+
+			/* Decide if the re-scheduling ticker node fits in the
+			 * slot found - break if it fits
+			 */
+			if (ticks_to_expire != 0U &&
+			    ticks_to_expire >= window_start_ticks &&
+			    ticks_to_expire <= window_end_ticks -
+			    ticker->ticks_slot) {
+				/* Re-scheduled node fits before this node */
+				break;
+			}
+
+			/* We din't find a valid slot for re-scheduling - try
+			 * the next node
+			 */
+			ticks_start_offset += node->ticks_to_expire;
+			window_start_ticks  = node->ticks_to_expire +
+					      node->ticks_slot;
+			ticks_to_expire     = ticks_slot_window -
+					      ticker->ticks_slot;
+
+			ticker_id_prev = ticker_id_iter;
+			ticker_id_iter = node->next;
+		}
+
+		ticker->ticks_to_expire = ticks_to_expire;
+		ticker_id_iter = nodes[ticker_id_head].next;
+		ticker_id_prev = TICKER_NULL;
+
+		/* Place the ticker node sorted by expiration time and adjust
+		 * delta times
+		 */
+		while (ticker_id_iter != TICKER_NULL) {
+			node = &nodes[ticker_id_iter];
+			if (ticker->ticks_to_expire > node->ticks_to_expire) {
+				/* Node is after this - adjust delta */
+				ticker->ticks_to_expire -=
+					node->ticks_to_expire;
+			} else {
+				/* Node is before this one */
+				node->ticks_to_expire -=
+					ticker->ticks_to_expire;
+				break;
+			}
+			ticker_id_prev = ticker_id_iter;
+			ticker_id_iter = node->next;
+		}
+
+		if (ticker_id_prev != TICKER_NULL) {
+			/* Node did not become the first - update head and
+			 * insert node after 'previous'
+			 */
+			instance->ticker_id_head = nodes[ticker_id_head].next;
+
+			/* Link inserted node */
+			nodes[ticker_id_head].next = nodes[ticker_id_prev].next;
+			nodes[ticker_id_prev].next = ticker_id_head;
+		}
+
+		/* Remove latency added in ticker_worker */
+		ticker->lazy_current--;
+
+		/* Prevent repeated re-scheduling */
+		ext_data->reschedule_state =
+			TICKER_RESCHEDULE_STATE_DONE;
+
+		/* Check for other pending re-schedules and set exit flag */
+		rescheduling = 1U;
+		rescheduled  = 1U;
+	}
+
+	return rescheduled;
+}
+#endif /* CONFIG_BT_TICKER_EXT */
+#else  /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Insert new ticker node
+ *
+ * @details Called by ticker_job to insert a new ticker node. If node collides
+ * with existing ticker nodes, either the new node is postponed, or colliding
+ * node is un-scheduled. Decision is based on latency and the force-state of
+ * individual nodes.
+ *
+ * @param instance    Pointer to ticker instance
+ * @param id_insert   Id of ticker to insert
+ * @param ticker      Pointer to ticker node to insert
+ * @param insert_head Pointer to current head. Updated if colliding nodes
+ *		      are un-scheduled
+ * @internal
+ */
+static inline uint32_t ticker_job_insert(struct ticker_instance *instance,
+				      uint8_t id_insert,
+				      struct ticker_node *ticker,
+				      uint8_t *insert_head)
+{
+	struct ticker_node *node = &instance->nodes[0];
+	uint8_t id_collide;
+	uint16_t skip;
+
+	/* Prepare to insert */
+	ticker->next = TICKER_NULL;
+
+	/* No. of times ticker has skipped its interval */
+	if (ticker->lazy_current > ticker->lazy_periodic) {
+		skip = ticker->lazy_current -
+		       ticker->lazy_periodic;
+	} else {
+		skip = 0U;
+	}
+
+	/* If insert collides, remove colliding or advance to next interval */
+	while (id_insert !=
+	       (id_collide = ticker_enqueue(instance, id_insert))) {
+		/* Check for collision */
+		if (id_collide != TICKER_NULL) {
+			struct ticker_node *ticker_collide = &node[id_collide];
+			uint16_t skip_collide;
+
+			/* No. of times colliding ticker has skipped its
+			 * interval.
+			 */
+			if (ticker_collide->lazy_current >
+			    ticker_collide->lazy_periodic) {
+				skip_collide = ticker_collide->lazy_current -
+					       ticker_collide->lazy_periodic;
+			} else {
+				skip_collide = 0U;
+			}
+
+			/* Check if colliding node should be un-scheduled */
+			if (ticker_collide->ticks_periodic &&
+			    skip_collide <= skip &&
+			    ticker_collide->force < ticker->force) {
+				/* Dequeue and get the reminder of ticks
+				 * to expire.
+				 */
+				ticker_collide->ticks_to_expire =
+					ticker_dequeue(instance, id_collide);
+				/* Unschedule node */
+				ticker_collide->req = ticker_collide->ack;
+
+				/* Enqueue for re-insertion */
+				ticker_collide->next = *insert_head;
+				*insert_head = id_collide;
+
+				continue;
+			}
+		}
+
+		/* occupied, try next interval */
+		if (ticker->ticks_periodic != 0U) {
+			ticker->ticks_to_expire += ticker->ticks_periodic +
+						   ticker_remainder_inc(ticker);
+			ticker->lazy_current++;
+
+			/* No. of times ticker has skipped its interval */
+			if (ticker->lazy_current > ticker->lazy_periodic) {
+				skip = ticker->lazy_current -
+				       ticker->lazy_periodic;
+			} else {
+				skip = 0U;
+			}
+
+			/* Remove any accumulated drift (possibly added due to
+			 * ticker job execution latencies).
+			 */
+			if (ticker->ticks_to_expire >
+			    ticker->ticks_to_expire_minus) {
+				ticker->ticks_to_expire -=
+					ticker->ticks_to_expire_minus;
+				ticker->ticks_to_expire_minus = 0U;
+			} else {
+				ticker->ticks_to_expire_minus -=
+					ticker->ticks_to_expire;
+				ticker->ticks_to_expire = 0U;
+			}
+		} else {
+			return TICKER_STATUS_FAILURE;
+		}
+	}
+
+	/* Inserted/Scheduled */
+	ticker->req = ticker->ack + 1;
+
+	return TICKER_STATUS_SUCCESS;
+}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Insert and start ticker nodes for all users
+ *
+ * @details Called by ticker_job to prepare, insert and start ticker nodes
+ * for all users. Specifying insert_head to other than TICKER_NULL causes
+ * that ticker node to be inserted first.
+ *
+ * @param instance    Pointer to ticker instance
+ * @param insert_head Id of ticker node to insert, or TICKER_NULL if only
+ *                    handle user operation inserts
+ * @internal
+ */
+static inline void ticker_job_list_insert(struct ticker_instance *instance,
+					  uint8_t insert_head)
+{
+	struct ticker_node *node;
+	struct ticker_user *users;
+	uint8_t count_user;
+
+	node = &instance->nodes[0];
+	users = &instance->users[0];
+	count_user = instance->count_user;
+
+	/* Iterate through all user ids */
+	while (count_user--) {
+		struct ticker_user_op *user_ops;
+		struct ticker_user *user;
+		uint8_t user_ops_first;
+
+		user = &users[count_user];
+		user_ops = (void *)&user->user_op[0];
+		user_ops_first = user->first;
+		/* Traverse user operation queue - first to middle (wrap) */
+		while ((insert_head != TICKER_NULL) ||
+		       (user_ops_first != user->middle)) {
+			struct ticker_user_op *user_op;
+			struct ticker_node *ticker;
+			uint8_t id_insert;
+			uint32_t status;
+
+			if (insert_head != TICKER_NULL) {
+				/* Prepare insert of ticker node specified by
+				 * insert_head
+				 */
+				id_insert = insert_head;
+				ticker = &node[id_insert];
+				insert_head = ticker->next;
+
+				user_op = NULL;
+			} else {
+				/* Prepare insert of any ticker nodes requested
+				 * via user operation TICKER_USER_OP_TYPE_START
+				 */
+				uint8_t first;
+
+				user_op = &user_ops[user_ops_first];
+				first = user_ops_first + 1;
+				if (first == user->count_user_op) {
+					first = 0U;
+				}
+				user_ops_first = first;
+
+				id_insert = user_op->id;
+				ticker = &node[id_insert];
+				if (user_op->op != TICKER_USER_OP_TYPE_START) {
+					/* User operation is not start - skip
+					 * to next operation
+					 */
+					continue;
+				}
+
+				if (((ticker->req -
+				      ticker->ack) & 0xff) != 0U) {
+					ticker_job_op_cb(user_op,
+							 TICKER_STATUS_FAILURE);
+					continue;
+				}
+
+				/* Prepare ticker for start */
+				ticker_job_op_start(ticker, user_op,
+						    instance->ticks_current);
+			}
+
+			/* Insert ticker node */
+			status = ticker_job_insert(instance, id_insert, ticker,
+						   &insert_head);
+
+			if (user_op) {
+				ticker_job_op_cb(user_op, status);
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+				if ((ticker->ticks_periodic == 0U) &&
+				    user_op) {
+					ticker->fp_op_func =
+						user_op->fp_op_func;
+					ticker->op_context =
+						user_op->op_context;
+				}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+			}
+		}
+	}
+}
+
+/**
+ * @brief Perform inquiry for specific user operation
+ *
+ * @param instance Pointer to ticker instance
+ * @param uop	   Pointer to user operation
+ *
+ * @internal
+ */
+static inline void ticker_job_op_inquire(struct ticker_instance *instance,
+					 struct ticker_user_op *uop)
+{
+	ticker_op_func fp_op_func;
+
+	fp_op_func = NULL;
+	switch (uop->op) {
+	case TICKER_USER_OP_TYPE_SLOT_GET:
+		ticker_by_next_slot_get(instance,
+					uop->params.slot_get.ticker_id,
+					uop->params.slot_get.ticks_current,
+					uop->params.slot_get.ticks_to_expire);
+		__fallthrough;
+	case TICKER_USER_OP_TYPE_IDLE_GET:
+		uop->status = TICKER_STATUS_SUCCESS;
+		fp_op_func = uop->fp_op_func;
+		break;
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+	case TICKER_USER_OP_TYPE_PRIORITY_SET:
+		if (uop->id < instance->count_node) {
+			struct ticker_node *node = instance->nodes;
+
+			node[uop->id].priority =
+				uop->params.priority_set.priority;
+			uop->status = TICKER_STATUS_SUCCESS;
+		} else {
+			uop->status = TICKER_STATUS_FAILURE;
+		}
+		fp_op_func = uop->fp_op_func;
+		break;
+#endif
+	default:
+		/* do nothing for other ops */
+		break;
+	}
+
+	if (fp_op_func) {
+		fp_op_func(uop->status, uop->op_context);
+	}
+}
+
+/**
+ * @brief Check for pending inquiries for all users
+ *
+ * @details Run through all user operation lists, checking for pending
+ * inquiries. Currently only two types of inquiries are supported:
+ * TICKER_USER_OP_TYPE_SLOT_GET and TICKER_USER_OP_TYPE_IDLE_GET. The
+ * function also supports user operation TICKER_USER_OP_TYPE_PRIORITY_SET.
+ * This operation modifies the user->first index, indicating user operations
+ * are complete.
+ *
+ * @param instance Pointer to ticker instance
+ *
+ * @internal
+ */
+static inline void ticker_job_list_inquire(struct ticker_instance *instance)
+{
+	struct ticker_user *users;
+	uint8_t count_user;
+
+	users = &instance->users[0];
+	count_user = instance->count_user;
+	/* Traverse user operation queue - first to last (with wrap) */
+	while (count_user--) {
+		struct ticker_user_op *user_op;
+		struct ticker_user *user;
+
+		user = &users[count_user];
+		user_op = &user->user_op[0];
+		while (user->first != user->last) {
+			uint8_t first;
+
+			ticker_job_op_inquire(instance, &user_op[user->first]);
+
+			first = user->first + 1;
+			if (first == user->count_user_op) {
+				first = 0U;
+			}
+			user->first = first;
+		}
+	}
+}
+
+/**
+ * @brief Update counter compare value (trigger)
+ *
+ * @details Updates trigger to the match next expiring ticker node. The
+ * function takes into consideration that it may be preempted in the process,
+ * and makes sure - by iteration - that compare value is set in the future
+ * (with a margin).
+ *
+ * @param instance           Pointer to ticker instance
+ * @param ticker_id_old_head Previous ticker_id_head
+ *
+ * @internal
+ */
+static inline void ticker_job_compare_update(struct ticker_instance *instance,
+					     uint8_t ticker_id_old_head)
+{
+	struct ticker_node *ticker;
+	uint32_t ticks_to_expire;
+	uint32_t ctr_post;
+	uint32_t ctr;
+	uint32_t cc;
+	uint32_t i;
+
+	if (instance->ticker_id_head == TICKER_NULL) {
+		if (cntr_stop() == 0) {
+			instance->ticks_slot_previous = 0U;
+			instance->ticks_current = cntr_cnt_get();
+		}
+		return;
+	}
+
+	/* Check if this is the first update. If so, start the counter */
+	if (ticker_id_old_head == TICKER_NULL) {
+		uint32_t ticks_current;
+
+		ticks_current = cntr_cnt_get();
+
+		if (cntr_start() == 0) {
+			instance->ticks_current = ticks_current;
+		}
+	}
+
+	ticker = &instance->nodes[instance->ticker_id_head];
+	ticks_to_expire = ticker->ticks_to_expire;
+
+	/* Iterate few times, if required, to ensure that compare is
+	 * correctly set to a future value. This is required in case
+	 * the operation is pre-empted and current h/w counter runs
+	 * ahead of compare value to be set.
+	 */
+	i = 10U;
+	do {
+		uint32_t ticks_elapsed;
+
+		LL_ASSERT(i);
+		i--;
+
+		ctr = cntr_cnt_get();
+		cc = instance->ticks_current;
+		ticks_elapsed = ticker_ticks_diff_get(ctr, cc) +
+				HAL_TICKER_CNTR_CMP_OFFSET_MIN +
+				HAL_TICKER_CNTR_SET_LATENCY;
+		cc += MAX(ticks_elapsed, ticks_to_expire);
+		cc &= HAL_TICKER_CNTR_MASK;
+		instance->trigger_set_cb(cc);
+
+		ctr_post = cntr_cnt_get();
+	} while ((ticker_ticks_diff_get(ctr_post, ctr) +
+		  HAL_TICKER_CNTR_CMP_OFFSET_MIN) >
+		  ticker_ticks_diff_get(cc, ctr));
+}
+
+/**
+ * @brief Ticker job
+ *
+ * @details Runs the bottom half of the ticker, after ticker nodes have elapsed
+ * or user operations requested. The ticker_job is responsible for removing and
+ * re-inserting ticker nodes, based on next elapsing and periodicity of the
+ * nodes. The ticker_job is also responsible for processing user operations,
+ * i.e. requests for start, update, stop etc.
+ * Invoked from the ticker job mayfly context (TICKER_MAYFLY_CALL_ID_JOB).
+ *
+ * @param param Pointer to ticker instance
+ *
+ * @internal
+ */
+void ticker_job(void *param)
+{
+	struct ticker_instance *instance = param;
+	uint8_t ticker_id_old_head;
+	uint8_t insert_head;
+	uint32_t ticks_elapsed;
+	uint32_t ticks_previous;
+	uint8_t flag_elapsed;
+	uint8_t pending;
+	uint8_t flag_compare_update;
+
+	DEBUG_TICKER_JOB(1);
+
+	/* Defer worker, as job is now running */
+	if (instance->worker_trigger) {
+		DEBUG_TICKER_JOB(0);
+		return;
+	}
+	instance->job_guard = 1U;
+
+	/* Back up the previous known tick */
+	ticks_previous = instance->ticks_current;
+
+	/* Update current tick with the elapsed value from queue, and dequeue */
+	if (instance->ticks_elapsed_first != instance->ticks_elapsed_last) {
+		ticker_next_elapsed(&instance->ticks_elapsed_first);
+
+		ticks_elapsed =
+		    instance->ticks_elapsed[instance->ticks_elapsed_first];
+
+		instance->ticks_current += ticks_elapsed;
+		instance->ticks_current &= HAL_TICKER_CNTR_MASK;
+
+		flag_elapsed = 1U;
+	} else {
+		/* No elapsed value in queue */
+		flag_elapsed = 0U;
+		ticks_elapsed = 0U;
+	}
+
+	/* Initialise internal re-insert list */
+	insert_head = TICKER_NULL;
+
+	/* Initialise flag used to update next compare value */
+	flag_compare_update = 0U;
+
+	/* Remember the old head, so as to decide if new compare needs to be
+	 * set.
+	 */
+	ticker_id_old_head = instance->ticker_id_head;
+
+	/* Manage user operations (updates and deletions) in ticker list */
+	pending = ticker_job_list_manage(instance, ticks_elapsed, &insert_head);
+
+	/* Detect change in head of the list */
+	if (instance->ticker_id_head != ticker_id_old_head) {
+		flag_compare_update = 1U;
+	}
+
+	/* Handle expired tickers */
+	if (flag_elapsed) {
+		ticker_job_worker_bh(instance, ticks_previous, ticks_elapsed,
+				     &insert_head);
+
+		/* Detect change in head of the list */
+		if (instance->ticker_id_head != ticker_id_old_head) {
+			flag_compare_update = 1U;
+		}
+
+		/* Handle insertions */
+		ticker_job_list_insert(instance, insert_head);
+
+#if defined(CONFIG_BT_TICKER_EXT)
+		/* Re-schedule any pending nodes with slot_window */
+		if (ticker_job_reschedule_in_window(instance, ticks_elapsed)) {
+			flag_compare_update = 1U;
+		}
+#endif /* CONFIG_BT_TICKER_EXT */
+	} else {
+		/* Handle insertions */
+		ticker_job_list_insert(instance, insert_head);
+	}
+
+	/* Detect change in head of the list */
+	if (instance->ticker_id_head != ticker_id_old_head) {
+		flag_compare_update = 1U;
+	}
+
+	/* Process any list inquiries */
+	if (!pending) {
+		/* Handle inquiries */
+		ticker_job_list_inquire(instance);
+	}
+
+	/* Permit worker job to run */
+	instance->job_guard = 0U;
+
+	/* update compare if head changed */
+	if (flag_compare_update) {
+		ticker_job_compare_update(instance, ticker_id_old_head);
+	}
+
+	/* trigger worker if deferred */
+	if (instance->worker_trigger) {
+		instance->sched_cb(TICKER_CALL_ID_JOB, TICKER_CALL_ID_WORKER, 1,
+				   instance);
+	}
+
+	DEBUG_TICKER_JOB(0);
+}
+
+/*****************************************************************************
+ * Public Interface
+ ****************************************************************************/
+
+/**
+ * @brief Initialize ticker instance
+ *
+ * @details Called by ticker instance client once to initialize the ticker.
+ *
+ * @param instance_index   Index of ticker instance
+ * @param count_node	   Number of ticker nodes in node array
+ * @param node		   Pointer to ticker node array
+ * @param count_user	   Number of users in user array
+ * @param user		   Pointer to user array of size count_user
+ * @param count_op	   Number of user operations in user_op array
+ * @param user_op	   Pointer to user operations array of size count_op
+ * @param caller_id_get_cb Pointer to function for retrieving caller_id from
+ *			   user id
+ * @param sched_cb	   Pointer to function for scheduling ticker_worker
+ *			   and ticker_job
+ * @param trigger_set_cb   Pointer to function for setting the compare trigger
+ *			   ticks value
+ *
+ * @return TICKER_STATUS_SUCCESS if initialization was successful, otherwise
+ * TICKER_STATUS_FAILURE
+ */
+uint32_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
+		  uint8_t count_user, void *user, uint8_t count_op, void *user_op,
+		  ticker_caller_id_get_cb_t caller_id_get_cb,
+		  ticker_sched_cb_t sched_cb,
+		  ticker_trigger_set_cb_t trigger_set_cb)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op_ = (void *)user_op;
+	struct ticker_user *users;
+
+	if (instance_index >= TICKER_INSTANCE_MAX) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	instance->count_node = count_node;
+	instance->nodes = node;
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+	while (count_node--) {
+		instance->nodes[count_node].priority = 0;
+	}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+	instance->count_user = count_user;
+	instance->users = user;
+
+	/** @todo check if enough ticker_user_op supplied */
+
+	users = &instance->users[0];
+	while (count_user--) {
+		users[count_user].user_op = user_op_;
+		user_op_ += users[count_user].count_user_op;
+		count_op -= users[count_user].count_user_op;
+	}
+
+	if (count_op) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	instance->caller_id_get_cb = caller_id_get_cb;
+	instance->sched_cb = sched_cb;
+	instance->trigger_set_cb = trigger_set_cb;
+
+	instance->ticker_id_head = TICKER_NULL;
+	instance->ticker_id_slot_previous = TICKER_NULL;
+	instance->ticks_slot_previous = 0U;
+	instance->ticks_current = 0U;
+	instance->ticks_elapsed_first = 0U;
+	instance->ticks_elapsed_last = 0U;
+
+	return TICKER_STATUS_SUCCESS;
+}
+
+/**
+ * @brief Check if ticker instance is initialized
+ *
+ * @param instance_index Index of ticker instance
+ *
+ * @return true if ticker instance is initialized, false otherwise
+ */
+bool ticker_is_initialized(uint8_t instance_index)
+{
+	return !!(_instance[instance_index].count_node);
+}
+
+/**
+ * @brief Trigger the ticker worker
+ *
+ * @details Schedules the ticker_worker upper half by invoking the
+ * corresponding mayfly.
+ *
+ * @param instance_index Index of ticker instance
+ */
+void ticker_trigger(uint8_t instance_index)
+{
+	struct ticker_instance *instance;
+
+	DEBUG_TICKER_ISR(1);
+
+	instance = &_instance[instance_index];
+	if (instance->sched_cb) {
+		instance->sched_cb(TICKER_CALL_ID_TRIGGER,
+				   TICKER_CALL_ID_WORKER, 1, instance);
+	}
+
+	DEBUG_TICKER_ISR(0);
+}
+
+/**
+ * @brief Start a ticker node
+ *
+ * @details Creates a new user operation of type TICKER_USER_OP_TYPE_START and
+ * schedules the ticker_job.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param ticker_id	     Id of ticker node
+ * @param ticks_anchor	     Absolute tick count as anchor point for
+ *			     ticks_first
+ * @param ticks_first	     Initial number of ticks before first timeout
+ * @param ticks_periodic     Number of ticks for a peridic ticker node. If 0,
+ *			     ticker node is treated as one-shot
+ * @param remainder_periodic Periodic ticks fraction
+ * @param lazy		     Number of periods to skip (latency). A value of 1
+ *			     causes skipping every other timeout
+ * @param ticks_slot	     Slot reservation ticks for node (air-time)
+ * @param ticks_slot_window  Window in which the slot reservation may be
+ *			     re-scheduled to avoid collision. Set to 0 for
+ *			     legacy behavior
+ * @param fp_timeout_func    Function pointer of function to call at timeout
+ * @param context	     Context passed in timeout call
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if start was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to
+ * run before exiting ticker_start
+ */
+#if defined(CONFIG_BT_TICKER_EXT)
+uint32_t ticker_start(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		   uint32_t ticks_anchor, uint32_t ticks_first, uint32_t ticks_periodic,
+		   uint32_t remainder_periodic, uint16_t lazy, uint32_t ticks_slot,
+		   ticker_timeout_func fp_timeout_func, void *context,
+		   ticker_op_func fp_op_func, void *op_context)
+{
+	return ticker_start_ext(instance_index, user_id, ticker_id,
+				ticks_anchor, ticks_first, ticks_periodic,
+				remainder_periodic, lazy, ticks_slot,
+				fp_timeout_func, context,
+				fp_op_func, op_context,
+				NULL);
+}
+
+uint32_t ticker_start_ext(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		       uint32_t ticks_anchor, uint32_t ticks_first,
+		       uint32_t ticks_periodic, uint32_t remainder_periodic,
+		       uint16_t lazy, uint32_t ticks_slot,
+		       ticker_timeout_func fp_timeout_func, void *context,
+		       ticker_op_func fp_op_func, void *op_context,
+		       struct ticker_ext *ext_data)
+#else
+uint32_t ticker_start(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		   uint32_t ticks_anchor, uint32_t ticks_first, uint32_t ticks_periodic,
+		   uint32_t remainder_periodic, uint16_t lazy, uint32_t ticks_slot,
+		   ticker_timeout_func fp_timeout_func, void *context,
+		   ticker_op_func fp_op_func, void *op_context)
+#endif
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_START;
+	user_op->id = ticker_id;
+	user_op->params.start.ticks_at_start = ticks_anchor;
+	user_op->params.start.ticks_first = ticks_first;
+	user_op->params.start.ticks_periodic = ticks_periodic;
+	user_op->params.start.remainder_periodic = remainder_periodic;
+	user_op->params.start.ticks_slot = ticks_slot;
+	user_op->params.start.lazy = lazy;
+#if defined(CONFIG_BT_TICKER_EXT)
+	user_op->params.start.ext_data = ext_data;
+#endif
+	user_op->params.start.fp_timeout_func = fp_timeout_func;
+	user_op->params.start.context = context;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+/**
+ * @brief Update a ticker node
+ *
+ * @details Creates a new user operation of type TICKER_USER_OP_TYPE_UPDATE and
+ * schedules the ticker_job.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param ticker_id	     Id of ticker node
+ * @param ticks_drift_plus   Number of ticks to add for drift compensation
+ * @param ticks_drift_minus  Number of ticks to subtract for drift compensation
+ * @param ticks_slot_plus    Number of ticks to add to slot reservation
+ * @param ticks_slot_minus   Number of ticks to add subtract from slot
+ *			     reservation
+ * @param lazy		     Number of periods to skip (latency). A value of 0
+ *			     means no action. 1 means no latency (normal). A
+ *			     value >1 means latency = lazy - 1
+ * @param force		     Force update to take effect immediately. With
+ *			     force = 0, update is scheduled to take effect as
+ *			     soon as possible
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if update was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_update
+ */
+uint32_t ticker_update(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		    uint32_t ticks_drift_plus, uint32_t ticks_drift_minus,
+		    uint32_t ticks_slot_plus, uint32_t ticks_slot_minus, uint16_t lazy,
+		    uint8_t force, ticker_op_func fp_op_func, void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_UPDATE;
+	user_op->id = ticker_id;
+	user_op->params.update.ticks_drift_plus = ticks_drift_plus;
+	user_op->params.update.ticks_drift_minus = ticks_drift_minus;
+	user_op->params.update.ticks_slot_plus = ticks_slot_plus;
+	user_op->params.update.ticks_slot_minus = ticks_slot_minus;
+	user_op->params.update.lazy = lazy;
+	user_op->params.update.force = force;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+/**
+ * @brief Stop a ticker node
+ *
+ * @details Creates a new user operation of type TICKER_USER_OP_TYPE_STOP and
+ * schedules the ticker_job.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if stop was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_stop
+ */
+uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		  ticker_op_func fp_op_func, void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_STOP;
+	user_op->id = ticker_id;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+/**
+ * @brief Stop a ticker node with supplied absolute ticks reference
+ *
+ * @details Creates a new user operation of type TICKER_USER_OP_TYPE_STOP_ABS
+ * and schedules the ticker_job.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param ticks_at_stop      Absolute tick count at ticker stop request
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if stop was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_stop
+ */
+uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+		  uint32_t ticks_at_stop, ticker_op_func fp_op_func,
+		  void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_STOP_ABS;
+	user_op->id = ticker_id;
+	user_op->params.stop.ticks_at_stop = ticks_at_stop;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+/**
+ * @brief Get next ticker node slot
+ *
+ * @details Gets the next ticker which has slot ticks specified and
+ * return the ticker id and accumulated ticks until expiration. If no
+ * ticker nodes have slot ticks, the next ticker node is returned.
+ * If no head id is provided (TICKER_NULL) the first node is returned.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param ticker_id	     Pointer to id of ticker node
+ * @param ticks_current	     Pointer to current ticks count
+ * @param ticks_to_expire    Pointer to ticks to expire
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if request was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_next_slot_get
+ */
+uint32_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id, uint8_t *ticker_id,
+			   uint32_t *ticks_current, uint32_t *ticks_to_expire,
+			   ticker_op_func fp_op_func, void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_SLOT_GET;
+	user_op->id = TICKER_NULL;
+	user_op->params.slot_get.ticker_id = ticker_id;
+	user_op->params.slot_get.ticks_current = ticks_current;
+	user_op->params.slot_get.ticks_to_expire = ticks_to_expire;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+/**
+ * @brief Get a callback at the end of ticker job execution
+ *
+ * @details Operation completion callback is called at the end of the
+ * ticker_job execution. The user operation is immutable.
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if request was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_job_idle_get
+ */
+uint32_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
+			  ticker_op_func fp_op_func, void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_IDLE_GET;
+	user_op->id = TICKER_NULL;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+
+#if !defined(CONFIG_BT_TICKER_COMPATIBILITY_MODE)
+/**
+ * @brief Set ticker node priority
+ *
+ * @param instance_index     Index of ticker instance
+ * @param user_id	     Ticker user id. Used for indexing user operations
+ *			     and mapping to mayfly caller id
+ * @param ticker_id	     Id of ticker node to set priority on
+ * @param priority	     Priority to set. Range [-128..127], default is 0.
+ *			     Lover value equals higher priority. Setting
+ *			     priority to -128 (TICKER_PRIORITY_CRITICAL) makes
+ *			     the node win all collision challenges. Only one
+ *			     node can have this priority assigned.
+ * @param fp_op_func	     Function pointer of user operation completion
+ *			     function
+ * @param op_context	     Context passed in operation completion call
+ *
+ * @return TICKER_STATUS_BUSY if request was successful but not yet completed.
+ * TICKER_STATUS_FAILURE is returned if there are no more user operations
+ * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
+ * before exiting ticker_priority_set
+ */
+uint32_t ticker_priority_set(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
+			  int8_t priority, ticker_op_func fp_op_func,
+			  void *op_context)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+	struct ticker_user_op *user_op;
+	struct ticker_user *user;
+	uint8_t last;
+
+	user = &instance->users[user_id];
+
+	last = user->last + 1;
+	if (last >= user->count_user_op) {
+		last = 0U;
+	}
+
+	if (last == user->first) {
+		return TICKER_STATUS_FAILURE;
+	}
+
+	user_op = &user->user_op[user->last];
+	user_op->op = TICKER_USER_OP_TYPE_PRIORITY_SET;
+	user_op->id = ticker_id;
+	user_op->params.priority_set.priority = priority;
+	user_op->status = TICKER_STATUS_BUSY;
+	user_op->fp_op_func = fp_op_func;
+	user_op->op_context = op_context;
+
+	user->last = last;
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+
+	return user_op->status;
+}
+#endif /* !CONFIG_BT_TICKER_COMPATIBILITY_MODE */
+
+/**
+ * @brief Schedule ticker job
+ *
+ * @param instance_index Index of ticker instance
+ * @param user_id	 Ticker user id. Maps to mayfly caller id
+ */
+void ticker_job_sched(uint8_t instance_index, uint8_t user_id)
+{
+	struct ticker_instance *instance = &_instance[instance_index];
+
+	instance->sched_cb(instance->caller_id_get_cb(user_id),
+			   TICKER_CALL_ID_JOB, 0, instance);
+}
+
+/**
+ * @brief Get current absolute tick count
+ *
+ * @return Absolute tick count
+ */
+uint32_t ticker_ticks_now_get(void)
+{
+	return cntr_cnt_get();
+}
+
+/**
+ * @brief Get diffence between two tick counts
+ *
+ * @details Subtract two counts and truncate to correct HW dependent counter
+ * bit width
+ *
+ * @param ticks_now Highest tick count (now)
+ * @param ticks_old Tick count to subtract from ticks_now
+ */
+uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old)
+{
+	return ((ticks_now - ticks_old) & HAL_TICKER_CNTR_MASK);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.h	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MAYFLY_CALL_ID_0       0
+#define MAYFLY_CALL_ID_1       1
+#define MAYFLY_CALL_ID_2       2
+#define MAYFLY_CALL_ID_PROGRAM 3
+#define MAYFLY_CALLER_COUNT    4
+#define MAYFLY_CALLEE_COUNT    4
+
+struct mayfly {
+	uint8_t volatile _req;
+	uint8_t _ack;
+	memq_link_t *_link;
+	void *param;
+	void (*fp)(void *);
+};
+
+void mayfly_init(void);
+void mayfly_enable(uint8_t caller_id, uint8_t callee_id, uint8_t enable);
+uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+		     struct mayfly *m);
+void mayfly_run(uint8_t callee_id);
+
+extern void mayfly_enable_cb(uint8_t caller_id, uint8_t callee_id, uint8_t enable);
+extern uint32_t mayfly_is_enabled(uint8_t caller_id, uint8_t callee_id);
+extern uint32_t mayfly_prio_is_equal(uint8_t caller_id, uint8_t callee_id);
+extern void mayfly_pend(uint8_t caller_id, uint8_t callee_id);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mayfly.c	(working copy)
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <zephyr/types.h>
+#include <sys/printk.h>
+#include "memq.h"
+#include "mayfly.h"
+
+static struct {
+	memq_link_t *head;
+	memq_link_t *tail;
+	uint8_t        enable_req;
+	uint8_t        enable_ack;
+	uint8_t        disable_req;
+	uint8_t        disable_ack;
+} mft[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT];
+
+static memq_link_t mfl[MAYFLY_CALLEE_COUNT][MAYFLY_CALLER_COUNT];
+static uint8_t mfp[MAYFLY_CALLEE_COUNT];
+
+#if defined(MAYFLY_UT)
+static uint8_t _state;
+#endif /* MAYFLY_UT */
+
+void mayfly_init(void)
+{
+	uint8_t callee_id;
+
+	callee_id = MAYFLY_CALLEE_COUNT;
+	while (callee_id--) {
+		uint8_t caller_id;
+
+		caller_id = MAYFLY_CALLER_COUNT;
+		while (caller_id--) {
+			memq_init(&mfl[callee_id][caller_id],
+				  &mft[callee_id][caller_id].head,
+				  &mft[callee_id][caller_id].tail);
+		}
+	}
+}
+
+void mayfly_enable(uint8_t caller_id, uint8_t callee_id, uint8_t enable)
+{
+	if (enable) {
+		if (mft[callee_id][caller_id].enable_req ==
+		    mft[callee_id][caller_id].enable_ack) {
+			mft[callee_id][caller_id].enable_req++;
+		}
+
+		mayfly_enable_cb(caller_id, callee_id, enable);
+	} else {
+		if (mft[callee_id][caller_id].disable_req ==
+		    mft[callee_id][caller_id].disable_ack) {
+			mft[callee_id][caller_id].disable_req++;
+
+			/* set mayfly callee pending */
+			mfp[callee_id] = 1U;
+
+			/* pend the callee for execution */
+			mayfly_pend(caller_id, callee_id);
+		}
+	}
+}
+
+uint32_t mayfly_enqueue(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
+			struct mayfly *m)
+{
+	uint8_t state;
+	uint8_t ack;
+
+	chain = chain || !mayfly_prio_is_equal(caller_id, callee_id) ||
+		!mayfly_is_enabled(caller_id, callee_id) ||
+		(mft[callee_id][caller_id].disable_req !=
+		 mft[callee_id][caller_id].disable_ack);
+
+	/* shadow the ack */
+	ack = m->_ack;
+
+	/* already in queue */
+	state = (m->_req - ack) & 0x03;
+	if (state != 0U) {
+		if (chain) {
+			if (state != 1U) {
+				/* mark as ready in queue */
+				m->_req = ack + 1;
+
+				goto mayfly_enqueue_pend;
+			}
+
+			/* already ready */
+			return 1;
+		}
+
+		/* mark as done in queue, and fall thru */
+		m->_req = ack + 2;
+	}
+
+	/* handle mayfly(s) that can be inline */
+	if (!chain) {
+		/* call fp */
+		m->fp(m->param);
+
+		return 0;
+	}
+
+	/* new, add as ready in the queue */
+	m->_req = ack + 1;
+	memq_enqueue(m->_link, m, &mft[callee_id][caller_id].tail);
+
+mayfly_enqueue_pend:
+	/* set mayfly callee pending */
+	mfp[callee_id] = 1U;
+
+	/* pend the callee for execution */
+	mayfly_pend(caller_id, callee_id);
+
+	return 0;
+}
+
+static void dequeue(uint8_t callee_id, uint8_t caller_id, memq_link_t *link,
+		    struct mayfly *m)
+{
+	uint8_t req;
+
+	req = m->_req;
+	if (((req - m->_ack) & 0x03) != 1U) {
+		uint8_t ack;
+
+#if defined(MAYFLY_UT)
+		uint32_t mayfly_ut_run_test(void);
+		void mayfly_ut_mfy(void *param);
+
+		if (_state && m->fp == mayfly_ut_mfy) {
+			static uint8_t single;
+
+			if (!single) {
+				single = 1U;
+				mayfly_ut_run_test();
+			}
+		}
+#endif /* MAYFLY_UT */
+
+		/* dequeue mayfly struct */
+		memq_dequeue(mft[callee_id][caller_id].tail,
+			     &mft[callee_id][caller_id].head,
+			     0);
+
+		/* release link into dequeued mayfly struct */
+		m->_link = link;
+
+		/* reset mayfly state to idle */
+		ack = m->_ack;
+		m->_ack = req;
+
+		/* re-insert, if re-pended by interrupt */
+		if (((m->_req - ack) & 0x03) == 1U) {
+#if defined(MAYFLY_UT)
+			printk("%s: RACE\n", __func__);
+#endif /* MAYFLY_UT */
+
+			m->_ack = ack;
+			memq_enqueue(link, m, &mft[callee_id][callee_id].tail);
+		}
+	}
+}
+
+void mayfly_run(uint8_t callee_id)
+{
+	uint8_t disable = 0U;
+	uint8_t enable = 0U;
+	uint8_t caller_id;
+
+	if (!mfp[callee_id]) {
+		return;
+	}
+	mfp[callee_id] = 0U;
+
+	/* iterate through each caller queue to this callee_id */
+	caller_id = MAYFLY_CALLER_COUNT;
+	while (caller_id--) {
+		memq_link_t *link;
+		struct mayfly *m = 0;
+
+		/* fetch mayfly in callee queue, if any */
+		link = memq_peek(mft[callee_id][caller_id].head,
+				 mft[callee_id][caller_id].tail,
+				 (void **)&m);
+		while (link) {
+			uint8_t state;
+
+#if defined(MAYFLY_UT)
+			_state = 0U;
+#endif /* MAYFLY_UT */
+
+			/* execute work if ready */
+			state = (m->_req - m->_ack) & 0x03;
+			if (state == 1U) {
+#if defined(MAYFLY_UT)
+				_state = 1U;
+#endif /* MAYFLY_UT */
+
+				/* mark mayfly as ran */
+				m->_ack--;
+
+				/* call the mayfly function */
+				m->fp(m->param);
+			}
+
+			/* dequeue if not re-pended */
+			dequeue(callee_id, caller_id, link, m);
+
+			/* fetch next mayfly in callee queue, if any */
+			link = memq_peek(mft[callee_id][caller_id].head,
+					 mft[callee_id][caller_id].tail,
+					 (void **)&m);
+
+/**
+ * When using cooperative thread implementation, an issue has been seen where
+ * pended mayflies are never executed in certain scenarios.
+ * This happens when mayflies with higher caller_id are constantly pended, in
+ * which case lower value caller ids never get to be executed.
+ * By allowing complete traversal of mayfly queues for all caller_ids, this
+ * does not happen, however this means that more than one mayfly function is
+ * potentially executed in a mayfly_run(), with added execution time as
+ * consequence.
+ */
+#if defined(CONFIG_BT_MAYFLY_YIELD_AFTER_CALL)
+			/* yield out of mayfly_run if a mayfly function was
+			 * called.
+			 */
+			if (state == 1U) {
+				/* pend callee (tailchain) if mayfly queue is
+				 * not empty or all caller queues are not
+				 * processed.
+				 */
+				if (caller_id || link) {
+					/* set mayfly callee pending */
+					mfp[callee_id] = 1U;
+
+					/* pend the callee for execution */
+					mayfly_pend(callee_id, callee_id);
+
+					return;
+				}
+			}
+#endif
+		}
+
+		if (mft[callee_id][caller_id].disable_req !=
+		    mft[callee_id][caller_id].disable_ack) {
+			disable = 1U;
+
+			mft[callee_id][caller_id].disable_ack =
+				mft[callee_id][caller_id].disable_req;
+		}
+
+		if (mft[callee_id][caller_id].enable_req !=
+		    mft[callee_id][caller_id].enable_ack) {
+			enable = 1U;
+
+			mft[callee_id][caller_id].enable_ack =
+				mft[callee_id][caller_id].enable_req;
+		}
+	}
+
+	if (disable && !enable) {
+		mayfly_enable_cb(callee_id, callee_id, 0);
+	}
+}
+
+#if defined(MAYFLY_UT)
+#define MAYFLY_CALL_ID_CALLER MAYFLY_CALL_ID_0
+#define MAYFLY_CALL_ID_CALLEE MAYFLY_CALL_ID_2
+
+void mayfly_ut_mfy(void *param)
+{
+	printk("%s: ran.\n", __func__);
+
+	(*((uint32_t *)param))++;
+}
+
+void mayfly_ut_test(void *param)
+{
+	static uint32_t *count;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, mayfly_ut_mfy};
+	uint32_t err;
+
+	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);
+
+	if (param) {
+		count = param;
+	}
+
+	mfy.param = count;
+
+	err = mayfly_enqueue(MAYFLY_CALL_ID_CALLER, MAYFLY_CALL_ID_CALLEE, 1,
+			     &mfy);
+	if (err) {
+		printk("%s: FAILED (%u).\n", __func__, err);
+	} else {
+		printk("%s: SUCCESS.\n", __func__);
+	}
+}
+
+uint32_t mayfly_ut_run_test(void)
+{
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, NULL, mayfly_ut_test};
+	uint32_t err;
+
+	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);
+
+	err = mayfly_enqueue(MAYFLY_CALL_ID_CALLEE, MAYFLY_CALL_ID_CALLER, 0,
+			     &mfy);
+
+	if (err) {
+		printk("%s: FAILED.\n", __func__);
+		return err;
+	}
+
+	printk("%s: SUCCESS.\n", __func__);
+
+	return 0;
+}
+
+uint32_t mayfly_ut(void)
+{
+	static uint32_t count;
+	static memq_link_t link;
+	static struct mayfly mfy = {0, 0, &link, &count, mayfly_ut_test};
+	uint32_t err;
+
+	printk("%s: req= %u, ack= %u\n", __func__, mfy._req, mfy._ack);
+
+	err = mayfly_enqueue(MAYFLY_CALL_ID_PROGRAM, MAYFLY_CALL_ID_CALLER, 0,
+			     &mfy);
+
+	if (err) {
+		printk("%s: FAILED.\n", __func__);
+		return err;
+	}
+
+	printk("%s: count = %u.\n", __func__, count);
+	printk("%s: SUCCESS.\n", __func__);
+	return 0;
+}
+#endif /* MAYFLY_UT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.h	(working copy)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef MALIGN
+/**
+ * @brief Force compiler to place memory at-least on a x-byte boundary
+ * @details Compiler extension. Supported by GCC and Clang
+ */
+#define MALIGN(x) __attribute__((aligned(x)))
+#endif
+
+#ifndef MROUND
+/**
+ * @brief Round up to nearest multiple of 4, for unsigned integers
+ * @details
+ *   The addition of 3 forces x into the next multiple of 4. This is responsible
+ *   for the rounding in the the next step, to be Up.
+ *   For ANDing of ~3: We observe y & (~3) == (y>>2)<<2, and we recognize
+ *   (y>>2) as a floored division, which is almost undone by the left-shift. The
+ *   flooring can't be undone so have achieved a rounding.
+ *
+ *   Examples:
+ *    MROUND( 0) =  0
+ *    MROUND( 1) =  4
+ *    MROUND( 2) =  4
+ *    MROUND( 3) =  4
+ *    MROUND( 4) =  4
+ *    MROUND( 5) =  8
+ *    MROUND( 8) =  8
+ *    MROUND( 9) = 12
+ *    MROUND(13) = 16
+ */
+#define MROUND(x) (((uint32_t)(x)+3) & (~((uint32_t)3)))
+#endif
+
+void mem_init(void *mem_pool, uint16_t mem_size, uint16_t mem_count, void **mem_head);
+void *mem_acquire(void **mem_head);
+void mem_release(void *mem, void **mem_head);
+
+uint16_t mem_free_count_get(void *mem_head);
+void *mem_get(void *mem_pool, uint16_t mem_size, uint16_t index);
+uint16_t mem_index_get(void *mem, void *mem_pool, uint16_t mem_size);
+
+void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len);
+uint8_t mem_nz(uint8_t *src, uint16_t len);
+
+uint32_t mem_ut(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mem.c	(working copy)
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <string.h>
+
+#include "util.h"
+
+#include "mem.h"
+
+void mem_init(void *mem_pool, uint16_t mem_size, uint16_t mem_count,
+	      void **mem_head)
+{
+	*mem_head = mem_pool;
+
+	/* Store free mem_count after the list's next pointer at an 32-bit
+	 * aligned memory location to ensure atomic read/write (in ARM for now).
+	 */
+	*((uint16_t *)MROUND((uint8_t *)mem_pool + sizeof(mem_pool))) = mem_count;
+
+	/* Initialize next pointers to form a free list,
+	 * next pointer is stored in the first 32-bit of each block
+	 */
+	(void)memset(((uint8_t *)mem_pool + (mem_size * (--mem_count))), 0,
+		     sizeof(mem_pool));
+	while (mem_count--) {
+		uint32_t next;
+
+		next = (uint32_t)((uint8_t *) mem_pool +
+			       (mem_size * (mem_count + 1)));
+		memcpy(((uint8_t *)mem_pool + (mem_size * mem_count)),
+		       (void *)&next, sizeof(next));
+	}
+}
+
+void *mem_acquire(void **mem_head)
+{
+	if (*mem_head) {
+		uint16_t free_count;
+		void *head;
+		void *mem;
+
+		/* Get the free count from the list and decrement it */
+		free_count = *((uint16_t *)MROUND((uint8_t *)*mem_head +
+					       sizeof(mem_head)));
+		free_count--;
+
+		mem = *mem_head;
+		memcpy(&head, mem, sizeof(head));
+
+		/* Store free mem_count after the list's next pointer */
+		if (head) {
+			*((uint16_t *)MROUND((uint8_t *)head + sizeof(head))) =
+				free_count;
+		}
+
+		*mem_head = head;
+		return mem;
+	}
+
+	return NULL;
+}
+
+void mem_release(void *mem, void **mem_head)
+{
+	uint16_t free_count = 0U;
+
+	/* Get the free count from the list and increment it */
+	if (*mem_head) {
+		free_count = *((uint16_t *)MROUND((uint8_t *)*mem_head +
+					       sizeof(mem_head)));
+	}
+	free_count++;
+
+	memcpy(mem, mem_head, sizeof(mem));
+
+	/* Store free mem_count after the list's next pointer */
+	*((uint16_t *)MROUND((uint8_t *)mem + sizeof(mem))) = free_count;
+
+	*mem_head = mem;
+}
+
+uint16_t mem_free_count_get(void *mem_head)
+{
+	uint16_t free_count = 0U;
+
+	/* Get the free count from the list */
+	if (mem_head) {
+		free_count = *((uint16_t *)MROUND((uint8_t *)mem_head +
+					       sizeof(mem_head)));
+	}
+
+	return free_count;
+}
+
+void *mem_get(void *mem_pool, uint16_t mem_size, uint16_t index)
+{
+	return ((void *)((uint8_t *)mem_pool + (mem_size * index)));
+}
+
+uint16_t mem_index_get(void *mem, void *mem_pool, uint16_t mem_size)
+{
+	return ((uint16_t)((uint8_t *)mem - (uint8_t *)mem_pool) / mem_size);
+}
+
+/**
+ * @brief  Copy bytes in reverse
+ * @details Example: [ 0x11 0x22 0x33 ] -> [ 0x33 0x22 0x11 ]
+ */
+void mem_rcopy(uint8_t *dst, uint8_t const *src, uint16_t len)
+{
+	src += len;
+	while (len--) {
+		*dst++ = *--src;
+	}
+}
+
+/**
+ * @brief Determine if src[0..len-1] contains one or more non-zero bytes
+ * @return 0 if all bytes are zero; otherwise 1
+ */
+uint8_t mem_nz(uint8_t *src, uint16_t len)
+{
+	while (len--) {
+		if (*src++) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * @brief Unit test
+ */
+uint32_t mem_ut(void)
+{
+#define BLOCK_SIZE  MROUND(10)
+#define BLOCK_COUNT 10
+	uint8_t MALIGN(4) pool[BLOCK_COUNT][BLOCK_SIZE];
+	void *mem_free;
+	void *mem_used;
+	uint16_t mem_free_count;
+	void *mem;
+
+	mem_init(pool, BLOCK_SIZE, BLOCK_COUNT, &mem_free);
+
+	mem_free_count = mem_free_count_get(mem_free);
+	if (mem_free_count != BLOCK_COUNT) {
+		return 1;
+	}
+
+	mem_used = 0;
+	while (mem_free_count--) {
+		uint16_t mem_free_count_current;
+
+		mem = mem_acquire(&mem_free);
+		mem_free_count_current = mem_free_count_get(mem_free);
+		if (mem_free_count != mem_free_count_current) {
+			return 2;
+		}
+
+		memcpy(mem, &mem_used, sizeof(mem));
+		mem_used = mem;
+	}
+
+	mem = mem_acquire(&mem_free);
+	if (mem) {
+		return 3;
+	}
+
+	while (++mem_free_count < BLOCK_COUNT) {
+		uint16_t mem_free_count_current;
+
+		mem = mem_used;
+		memcpy(&mem_used, mem, sizeof(void *));
+		mem_release(mem, &mem_free);
+
+		mem_free_count_current = mem_free_count_get(mem_free);
+		if ((mem_free_count + 1) != mem_free_count_current) {
+			return 4;
+		}
+	}
+
+	if (mem != mem_free) {
+		return 5;
+	}
+
+	if (mem_free_count_get(mem_free) != BLOCK_COUNT) {
+		return 6;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.h	(working copy)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @brief   Element of a memory-queue
+ * @details Elements form a linked list, and as payload carries a pointer
+ */
+struct _memq_link {
+	struct _memq_link *next; /* permit chaining */
+	void              *mem;  /* payload */
+};
+
+typedef struct _memq_link memq_link_t;
+
+#define MEMQ_DECLARE(name) \
+	struct { \
+		memq_link_t *head; \
+		memq_link_t *tail; \
+	} memq_##name
+
+memq_link_t *memq_init(memq_link_t *link, memq_link_t **head,
+		       memq_link_t **tail);
+
+#define MEMQ_INIT(name, link) \
+	memq_init(link, &memq_##name.head, &memq_##name.tail)
+
+memq_link_t *memq_deinit(memq_link_t **head, memq_link_t **tail);
+memq_link_t *memq_enqueue(memq_link_t *link, void *mem, memq_link_t **tail);
+memq_link_t *memq_peek(memq_link_t *head, memq_link_t *tail, void **mem);
+memq_link_t *memq_dequeue(memq_link_t *tail, memq_link_t **head, void **mem);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/memq.c	(working copy)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * FIFO-style "memory queue" permitting enqueue at tail and dequeue from head.
+ * Element's payload is a pointer to arbitrary memory.
+ *
+ * Implemented as a singly-linked list, with always one-more element.
+ * The linked list must always contain at least one link-element, as emptiness
+ * is given by head == tail.
+ * For a queue to be valid, it must be initialized with an initial link-element.
+ *
+ * Invariant: The tail element's mem pointer is DontCare.
+ *
+ * Note that at enqueue, memory is not coupled with its accompanying
+ * link-element, but the link-element before it!
+ *
+ * Call                    | State after call
+ * ------------------------+-------------------------------
+ * memq_init(I,H,T)        | H -> I[] <- T
+ * memq_enqueue(A,a,T);    | H -> I[a] -> A[] <- T
+ * memq_enqueue(B,b,T);    | H -> I[a] -> A[b] -> B[] <- T
+ * memq_dequeue(T,H,dest); | H -> A[b] -> B[] <- T  # I and a as return and dest
+ *
+ *   where H is the pointer to Head link-element (oldest element).
+ *   where T is the pointer to Tail link-element (newest element).
+ *   where I[]  means the initial link-element, whose mem pointer is DontCare.
+ *   where A[b] means the A'th link-element, whose mem pointer is b.
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+
+#include "memq.h"
+
+/**
+ * @brief Initialize a memory queue to be empty and valid.
+ *
+ * @param link[in]  Initial link-element. Not associated with any mem
+ * @param head[out] Head of queue. Will be updated
+ * @param tail[out] Tail of queue. Will be updated
+ * @return          Initial link-element
+ */
+memq_link_t *memq_init(memq_link_t *link, memq_link_t **head, memq_link_t **tail)
+{
+	/* Head and tail pointer to the initial link - forms an empty queue */
+	*head = *tail = link;
+
+	return link;
+}
+
+/**
+ * @brief De-initialize a memory queue to be empty and invalid.
+ *
+ * @param head[in,out] Head of queue. Will be updated
+ * @param tail[in,out] Tail of queue. Will be updated
+ * @return          Head of queue before invalidation; NULL if queue was empty
+ */
+memq_link_t *memq_deinit(memq_link_t **head, memq_link_t **tail)
+{
+	memq_link_t *old_head;
+
+	/* If head and tail are not equal, then queue is not empty */
+	if (*head != *tail) {
+		return NULL;
+	}
+
+	old_head = *head;
+	*head = *tail = NULL;
+
+	return old_head;
+}
+
+/**
+ * @brief Enqueue at the tail of the queue
+ * @details Enqueue is destructive so tail will change to new tail
+ * NOTE: The memory will not be associated with the link-element, but
+ *   rather the second-to-last link-element.
+ *
+ * @param link[in]     Element to be appended. Becomes new tail
+ * @param mem[in]      The memory payload to be enqueued. Pointed to by old tail
+ * @param tail[in,out] Tail of queue. Will be updated to point to link
+ * @return             New tail. Note: Does not point to the new mem
+ */
+memq_link_t *memq_enqueue(memq_link_t *link, void *mem, memq_link_t **tail)
+{
+	/* Let the old tail element point to the new tail element */
+	(*tail)->next = link;
+
+	/* Let the old tail element point the the new memory */
+	(*tail)->mem = mem;
+
+	/* Update the tail-pointer to point to the new tail element.
+	 * The new tail-element is not expected to point to anything sensible
+	 */
+	*tail = link;
+
+	return link;
+}
+
+/**
+ * @brief Non-destructive peek of head of queue.
+ *
+ * @param head[in] Pointer to head link-element of queue
+ * @param tail[in] Pointer to tail link-element of queue
+ * @param mem[out] The memory pointed to by head-element
+ * @return         head or NULL if queue is empty
+ */
+memq_link_t *memq_peek(memq_link_t *head, memq_link_t *tail, void **mem)
+{
+	/* If head and tail are equal, then queue empty */
+	if (head == tail) {
+		return NULL;
+	}
+
+	/* Extract the head link-element's memory */
+	if (mem) {
+		*mem = head->mem;
+	}
+
+	return head; /* queue was not empty */
+}
+
+/**
+ * @brief Remove and returns the head of queue.
+ * @details Dequeue is destructive so head will change to new head
+ *
+ * @param tail[in]     Pointer to tail link-element of queue
+ * @param head[in,out] Pointer to head link-element of queue. Will be updated
+ * @param mem[out]     The memory pointed to by head-element
+ * @return             head or NULL if queue is empty
+ */
+memq_link_t *memq_dequeue(memq_link_t *tail, memq_link_t **head, void **mem)
+{
+	memq_link_t *old_head;
+
+	/* Use memq peek to get the old head and its mem */
+	old_head = memq_peek(*head, tail, mem);
+	if (old_head == NULL) {
+		return NULL; /* queue is empty */
+	}
+
+	/* Update the head-pointer to point to the new head element */
+	*head = old_head->next;
+
+	return old_head;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mfifo.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mfifo.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/mfifo.h	(working copy)
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2018-2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * Memory FIFO permitting enqueue at tail (last) and dequeue from head (first).
+ *
+ * Implemented as a circular queue over buffers. Buffers lie contiguously in
+ * the backing storage.
+ *
+ * Enqueuing is a 2 step procedure: Alloc and commit. We say an allocated
+ * buffer yet to be committed, exists in a limbo state - until committed.
+ * It is only safe to write to a buffer while it is in limbo.
+ *
+ * Invariant: last-index refers to the buffer that is safe to write while in
+ * limbo-state. Outside limbo state, last-index refers one buffer ahead of what
+ * has been enqueued.
+ *
+ * There are essentially two APIs, distinguished by the buffer-type:
+ *  API 1 Value-type   : MFIFO_DEFINE(name1, sizeof(struct foo), cnt1);
+ *  API 2 Pointer-type : MFIFO_DEFINE(name2, sizeof(void *),     cnt2);
+ *
+ * Enqueuing is performed differently between APIs:
+ *         | Allocate               | Commit
+ *   ------+------------------------+----------------------
+ *   API 1 | MFIFO_ENQUEUE_GET      | MFIFO_ENQUEUE
+ *   API 2 | MFIFO_ENQUEUE_IDX_GET  | MFIFO_BY_IDX_ENQUEUE
+ *
+ * TODO: Reduce size: All functions except mfifo_enqueue should not be inline
+ */
+
+/**
+ * @brief   Define a Memory FIFO implemented as a circular queue.
+ * @details API 1 and 2.
+ *   Contains one-more buffer than needed.
+ *
+ * TODO: We can avoid string-concat macros below by setting type in
+ *       MFIFO_DEFINE struct or use a typedef. Yes the size of field 'm' may be
+ *       different, but it is trailing and sizeof is not applied here, so it can
+ *       be a flexible array member.
+ */
+#define MFIFO_DEFINE(name, sz, cnt)                                         \
+		struct {                                                    \
+			/* TODO: const, optimise RAM use */                 \
+			/* TODO: Separate s,n,f,l out into common struct */ \
+			uint8_t const s;         /* Stride between elements */ \
+			uint8_t const n;         /* Number of buffers */       \
+			uint8_t f;               /* First. Read index */       \
+			uint8_t l;               /* Last. Write index */       \
+			uint8_t MALIGN(4) m[MROUND(sz) * ((cnt) + 1)];         \
+		} mfifo_##name = {                                          \
+			.n = ((cnt) + 1),                                   \
+			.s = MROUND(sz),                                    \
+			.f = 0,                                             \
+			.l = 0,                                             \
+		}
+
+/**
+ * @brief   Initialize an MFIFO to be empty
+ * @details API 1 and 2. An MFIFO is empty if first == last
+ */
+#define MFIFO_INIT(name) \
+	mfifo_##name.f = mfifo_##name.l = 0
+
+/**
+ * @brief   Non-destructive: Allocate buffer from the queue's tail, by index
+ * @details API 2. Used internally by API 1.
+ *   Note that enqueue is split in 2 parts, allocation and commit:
+ *   1. Allocation: Buffer allocation from tail. May fail.
+ *   2. Commit:     If allocation was successful, the enqueue can be committed.
+ *   Committing can not fail, as only allocation can fail.
+ *   Allocation is non-destructive as operations are performed on index copies,
+ *   however the buffer remains in a state of limbo until committed.
+ *   Note: The limbo state opens up a potential race where successive
+ *   un-committed allocations returns the same buffer index.
+ *
+ * @param idx[out]  Index of newly allocated buffer
+ * @return  True if buffer could be allocated; otherwise false
+ */
+static inline bool mfifo_enqueue_idx_get(uint8_t count, uint8_t first, uint8_t last,
+					 uint8_t *idx)
+{
+	/* Non-destructive: Advance write-index modulo 'count' */
+	last = last + 1;
+	if (last == count) {
+		last = 0U;
+	}
+
+	/* Is queue full?
+	 * We want to maintain the invariant of emptiness defined by
+	 * first == last, but we just advanced a copy of the write-index before
+	 * and may have wrapped. So if first == last the queue is full and we
+	 * can not continue
+	 */
+	if (last == first) {
+		return false; /* Queue is full */
+	}
+
+	*idx = last; /* Emit the allocated buffer's index */
+	return true; /* Successfully allocated new buffer */
+}
+
+/**
+ * @brief   Non-destructive: Allocate buffer from named queue
+ * @details API 2.
+ * @param   i[out]  Index of newly allocated buffer
+ * @return  True if buffer could be allocated; otherwise false
+ */
+#define MFIFO_ENQUEUE_IDX_GET(name, i) \
+		mfifo_enqueue_idx_get(mfifo_##name.n, mfifo_##name.f, \
+				      mfifo_##name.l, (i))
+
+/**
+ * @brief   Commit a previously allocated buffer (=void-ptr)
+ * @details API 2
+ */
+static inline void mfifo_by_idx_enqueue(uint8_t *fifo, uint8_t size, uint8_t idx,
+					void *mem, uint8_t *last)
+{
+	/* API 2: fifo is array of void-ptrs */
+	void **p = (void **)(fifo + (*last) * size); /* buffer preceding idx */
+	*p = mem; /* store the payload which for API 2 is only a void-ptr */
+
+	*last = idx; /* Commit: Update write index */
+}
+
+/**
+ * @brief   Commit a previously allocated buffer (=void-ptr)
+ * @details API 2
+ */
+#define MFIFO_BY_IDX_ENQUEUE(name, i, mem) \
+		mfifo_by_idx_enqueue(mfifo_##name.m, mfifo_##name.s, (i), \
+				     (mem), &mfifo_##name.l)
+
+/**
+ * @brief   Non-destructive: Allocate buffer from named queue
+ * @details API 1.
+ *   The allocated buffer exists in limbo until committed.
+ *   To commit the enqueue process, mfifo_enqueue() must be called afterwards
+ * @return  Index of newly allocated buffer; only valid if mem != NULL
+ */
+static inline uint8_t mfifo_enqueue_get(uint8_t *fifo, uint8_t size, uint8_t count,
+				     uint8_t first, uint8_t last, void **mem)
+{
+	uint8_t idx;
+
+	/* Attempt to allocate new buffer (idx) */
+	if (!mfifo_enqueue_idx_get(count, first, last, &idx)) {
+		/* Buffer could not be allocated */
+		*mem = NULL; /* Signal the failure */
+		return 0;    /* DontCare */
+	}
+
+	/* We keep idx as the always-one-free, so we return preceding
+	 * buffer (last). Recall that last has not been updated,
+	 * so idx != last
+	 */
+	*mem = (void *)(fifo + last * size); /* preceding buffer */
+
+	return idx;
+}
+
+/**
+ * @brief   Non-destructive: Allocate buffer from named queue
+ * @details API 1.
+ *   The allocated buffer exists in limbo until committed.
+ *   To commit the enqueue process, MFIFO_ENQUEUE() must be called afterwards
+ * @param mem[out] Pointer to newly allocated buffer; NULL if allocation failed
+ * @return Index to the buffer one-ahead of allocated buffer
+ */
+#define MFIFO_ENQUEUE_GET(name, mem) \
+		mfifo_enqueue_get(mfifo_##name.m, mfifo_##name.s, \
+				  mfifo_##name.n, mfifo_##name.f, \
+				  mfifo_##name.l, (mem))
+
+/**
+ * @brief   Atomically commit a previously allocated buffer
+ * @details API 1.
+ *   Destructive update: Update the queue, bringing the allocated buffer out of
+ *   limbo state -- thus completing its enqueue.
+ *   Can not fail.
+ *   The buffer must have been allocated using mfifo_enqueue_idx_get() or
+ *   mfifo_enqueue_get().
+ *
+ * @param idx[in]   Index one-ahead of previously allocated buffer
+ * @param last[out] Write-index
+ */
+static inline void mfifo_enqueue(uint8_t idx, uint8_t *last)
+{
+	*last = idx; /* Commit: Update write index */
+}
+
+/**
+ * @brief   Atomically commit a previously allocated buffer
+ * @details API 1
+ *   The buffer should have been allocated using MFIFO_ENQUEUE_GET
+ * @param idx[in]  Index one-ahead of previously allocated buffer
+ */
+#define MFIFO_ENQUEUE(name, idx) \
+		mfifo_enqueue((idx), &mfifo_##name.l)
+
+/**
+ * @brief Number of available buffers
+ * @details API 1 and 2
+ *   Empty if first == last
+ */
+static inline uint8_t mfifo_avail_count_get(uint8_t count, uint8_t first, uint8_t last)
+{
+	if (last >= first) {
+		return last - first;
+	} else {
+		return count - first + last;
+	}
+}
+
+/**
+ * @brief Number of available buffers
+ * @details API 1 and 2
+ */
+#define MFIFO_AVAIL_COUNT_GET(name) \
+		mfifo_avail_count_get(mfifo_##name.n, mfifo_##name.f, \
+				      mfifo_##name.l)
+
+/**
+ * @brief Non-destructive peek
+ * @details API 1
+ */
+static inline void *mfifo_dequeue_get(uint8_t *fifo, uint8_t size, uint8_t first,
+				      uint8_t last)
+{
+	if (first == last) {
+		return NULL;
+	}
+
+	/* API 1: fifo is array of some value type */
+	return (void *)(fifo + first * size);
+}
+
+/**
+ * @details API 1
+ */
+#define MFIFO_DEQUEUE_GET(name) \
+		mfifo_dequeue_get(mfifo_##name.m, mfifo_##name.s, \
+				   mfifo_##name.f, mfifo_##name.l)
+
+/**
+ * @brief Non-destructive: Peek at head (oldest) buffer
+ * @details API 2
+ */
+static inline void *mfifo_dequeue_peek(uint8_t *fifo, uint8_t size, uint8_t first,
+				       uint8_t last)
+{
+	if (first == last) {
+		return NULL; /* Queue is empty */
+	}
+
+	/* API 2: fifo is array of void-ptrs */
+	return *((void **)(fifo + first * size));
+}
+
+/**
+ * @brief Non-destructive: Peek at head (oldest) buffer
+ * @details API 2
+ */
+#define MFIFO_DEQUEUE_PEEK(name) \
+		mfifo_dequeue_peek(mfifo_##name.m, mfifo_##name.s, \
+				   mfifo_##name.f, mfifo_##name.l)
+
+static inline void *mfifo_dequeue_iter_get(uint8_t *fifo, uint8_t size, uint8_t count,
+					   uint8_t first, uint8_t last, uint8_t *idx)
+{
+	void *p;
+	uint8_t i;
+
+	if (*idx >= count) {
+		*idx = first;
+	}
+
+	if (*idx == last) {
+		return NULL;
+	}
+
+	i = *idx + 1;
+	if (i == count) {
+		i = 0U;
+	}
+
+	p = (void *)(fifo + (*idx) * size);
+
+	*idx = i;
+
+	return p;
+}
+
+#define MFIFO_DEQUEUE_ITER_GET(name, idx) \
+		mfifo_dequeue_iter_get(mfifo_##name.m, mfifo_##name.s, \
+				       mfifo_##name.n, mfifo_##name.f, \
+				       mfifo_##name.l, (idx))
+
+/**
+ * @brief Dequeue head-buffer from queue of buffers
+ *
+ * @param fifo[in]      Contigous memory holding the circular queue
+ * @param size[in]      Size of each buffer in circular queue
+ * @param count[in]     Number of buffers in circular queue
+ * @param last[in]      Tail index, Span: [0 .. count-1]
+ * @param first[in,out] Head index, Span: [0 .. count-1]. Will be updated
+ * @return              Head buffer; or NULL if queue was empty
+ */
+static inline void *mfifo_dequeue(uint8_t *fifo, uint8_t size, uint8_t count,
+				  uint8_t last, uint8_t *first)
+{
+	uint8_t _first = *first; /* Copy read-index */
+	void *mem;
+
+	/* Queue is empty if first == last */
+	if (_first == last) {
+		return NULL;
+	}
+
+	/* Obtain address of head buffer.
+	 * API 2: fifo is array of void-ptrs
+	 */
+	mem = *((void **)(fifo + _first * size));
+
+	/* Circular buffer increment read-index modulo 'count' */
+	_first += 1U;
+	if (_first == count) {
+		_first = 0U;
+	}
+
+	*first = _first; /* Write back read-index */
+
+	return mem;
+}
+
+/**
+ * @brief   Dequeue head-buffer from named queue of buffers
+ *
+ * @param name[in]  Name-fragment of circular queue
+ * @return          Head buffer; or NULL if queue was empty
+ */
+#define MFIFO_DEQUEUE(name) \
+		mfifo_dequeue(mfifo_##name.m, mfifo_##name.s, \
+			      mfifo_##name.n, mfifo_##name.l, \
+			      &mfifo_##name.f)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.h	(working copy)
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016-2020 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+
+#ifndef DOUBLE_BUFFER_SIZE
+#define DOUBLE_BUFFER_SIZE 2
+#endif
+
+#ifndef TRIPLE_BUFFER_SIZE
+#define TRIPLE_BUFFER_SIZE 3
+#endif
+
+uint8_t util_ones_count_get(uint8_t *octets, uint8_t octets_len);
+int util_aa_le32(uint8_t *dst);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/controller/util/util.c	(working copy)
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2016 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Vinayak Kariappa Chettimada
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <drivers/entropy.h>
+
+#include "util.h"
+#include "util/memq.h"
+#include "lll.h"
+
+#include "pdu.h"
+
+/**
+ * @brief Population count: Count the number of bits set to 1
+ * @details
+ * TODO: Faster methods available at [1].
+ * [1] http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ *
+ * @param octets     Data to count over
+ * @param octets_len Must not be bigger than 255/8 = 31 bytes
+ *
+ * @return popcnt of 'octets'
+ */
+uint8_t util_ones_count_get(uint8_t *octets, uint8_t octets_len)
+{
+	uint8_t one_count = 0U;
+
+	while (octets_len--) {
+		uint8_t bite;
+
+		bite = *octets;
+		while (bite) {
+			bite &= (bite - 1);
+			one_count++;
+		}
+		octets++;
+	}
+
+	return one_count;
+}
+
+/** @brief Prepare access address as per BT Spec.
+ *
+ * - It shall have no more than six consecutive zeros or ones.
+ * - It shall not be the advertising channel packets' Access Address.
+ * - It shall not be a sequence that differs from the advertising channel
+ *   packets Access Address by only one bit.
+ * - It shall not have all four octets equal.
+ * - It shall have no more than 24 transitions.
+ * - It shall have a minimum of two transitions in the most significant six
+ *   bits.
+ *
+ * LE Coded PHY requirements:
+ * - It shall have at least three ones in the least significant 8 bits.
+ * - It shall have no more than eleven transitions in the least significant 16
+ *   bits.
+ */
+int util_aa_le32(uint8_t *dst)
+{
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	uint8_t transitions_lsb16;
+	uint8_t ones_count_lsb8;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	uint8_t consecutive_cnt;
+	uint8_t consecutive_bit;
+	uint32_t adv_aa_check;
+	uint32_t aa;
+	uint8_t transitions;
+	uint8_t bit_idx;
+	uint8_t retry;
+
+	retry = 3U;
+again:
+	if (!retry) {
+		return -EFAULT;
+	}
+	retry--;
+
+	lll_csrand_get(dst, sizeof(uint32_t));
+	aa = sys_get_le32(dst);
+
+	bit_idx = 31U;
+	transitions = 0U;
+	consecutive_cnt = 1U;
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+	ones_count_lsb8 = 0U;
+	transitions_lsb16 = 0U;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+	consecutive_bit = (aa >> bit_idx) & 0x01;
+	while (bit_idx--) {
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		uint8_t transitions_lsb16_prev = transitions_lsb16;
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		uint8_t consecutive_cnt_prev = consecutive_cnt;
+		uint8_t transitions_prev = transitions;
+		uint8_t bit;
+
+		bit = (aa >> bit_idx) & 0x01;
+		if (bit == consecutive_bit) {
+			consecutive_cnt++;
+		} else {
+			consecutive_cnt = 1U;
+			consecutive_bit = bit;
+			transitions++;
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+			if (bit_idx < 15) {
+				transitions_lsb16++;
+			}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		}
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		if ((bit_idx < 8) && consecutive_bit) {
+			ones_count_lsb8++;
+		}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+
+		/* It shall have no more than six consecutive zeros or ones. */
+		/* It shall have a minimum of two transitions in the most
+		 * significant six bits.
+		 */
+		if ((consecutive_cnt > 6) ||
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		    (!consecutive_bit && (((bit_idx < 6) &&
+					   (ones_count_lsb8 < 1)) ||
+					  ((bit_idx < 5) &&
+					   (ones_count_lsb8 < 2)) ||
+					  ((bit_idx < 4) &&
+					   (ones_count_lsb8 < 3)))) ||
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		    ((consecutive_cnt < 6) &&
+		     (((bit_idx < 29) && (transitions < 1)) ||
+		      ((bit_idx < 28) && (transitions < 2))))) {
+			if (consecutive_bit) {
+				consecutive_bit = 0U;
+				aa &= ~BIT(bit_idx);
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+				if (bit_idx < 8) {
+					ones_count_lsb8--;
+				}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+			} else {
+				consecutive_bit = 1U;
+				aa |= BIT(bit_idx);
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+				if (bit_idx < 8) {
+					ones_count_lsb8++;
+				}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+			}
+
+			if (transitions != transitions_prev) {
+				consecutive_cnt = consecutive_cnt_prev;
+				transitions = transitions_prev;
+			} else {
+				consecutive_cnt = 1U;
+				transitions++;
+			}
+
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+			if (bit_idx < 15) {
+				if (transitions_lsb16 !=
+				    transitions_lsb16_prev) {
+					transitions_lsb16 =
+						transitions_lsb16_prev;
+				} else {
+					transitions_lsb16++;
+				}
+			}
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		}
+
+		/* It shall have no more than 24 transitions
+		 * It shall have no more than eleven transitions in the least
+		 * significant 16 bits.
+		 */
+		if ((transitions > 24) ||
+#if defined(CONFIG_BT_CTLR_PHY_CODED)
+		    (transitions_lsb16 > 11) ||
+#endif /* CONFIG_BT_CTLR_PHY_CODED */
+		    0) {
+			if (consecutive_bit) {
+				aa &= ~(BIT(bit_idx + 1) - 1);
+			} else {
+				aa |= (BIT(bit_idx + 1) - 1);
+			}
+
+			break;
+		}
+	}
+
+	/* It shall not be the advertising channel packets Access Address.
+	 * It shall not be a sequence that differs from the advertising channel
+	 * packets Access Address by only one bit.
+	 */
+	adv_aa_check = aa ^ PDU_AC_ACCESS_ADDR;
+	if (util_ones_count_get((uint8_t *)&adv_aa_check,
+				sizeof(adv_aa_check)) <= 1) {
+		goto again;
+	}
+
+	/* It shall not have all four octets equal. */
+	if (!((aa & 0xFFFF) ^ (aa >> 16)) &&
+	    !((aa & 0xFF) ^ (aa >> 24))) {
+		goto again;
+	}
+
+	sys_put_le32(aa, dst);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/CMakeLists.txt	(working copy)
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_link_libraries(subsys__bluetooth)
+
+zephyr_library_sources_ifdef(CONFIG_BT_HCI_RAW          hci_raw.c hci_common.c)
+zephyr_library_sources_ifdef(CONFIG_BT_DEBUG_MONITOR    monitor.c)
+zephyr_library_sources_ifdef(CONFIG_BT_TINYCRYPT_ECC    hci_ecc.c)
+zephyr_library_sources_ifdef(CONFIG_BT_A2DP             a2dp.c)
+zephyr_library_sources_ifdef(CONFIG_BT_AVDTP            avdtp.c)
+zephyr_library_sources_ifdef(CONFIG_BT_RFCOMM           rfcomm.c)
+zephyr_library_sources_ifdef(CONFIG_BT_TESTING          testing.c)
+zephyr_library_sources_ifdef(CONFIG_BT_SETTINGS         settings.c)
+zephyr_library_sources_ifdef(CONFIG_BT_HOST_CCM         aes_ccm.c)
+
+zephyr_library_sources_ifdef(
+  CONFIG_BT_BREDR
+  keys_br.c
+  l2cap_br.c
+  sdp.c
+  ssp.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_BT_HFP_HF
+  hfp_hf.c
+  at.c
+  )
+
+if(CONFIG_BT_HCI_HOST)
+  zephyr_library_sources(
+    uuid.c
+    hci_core.c
+    hci_common.c
+    )
+  zephyr_library_sources_ifdef(
+    CONFIG_BT_HOST_CRYPTO
+    crypto.c
+    )
+
+  if(CONFIG_BT_CONN)
+    zephyr_library_sources(
+      conn.c
+      l2cap.c
+      att.c
+      gatt.c
+      )
+
+    if(CONFIG_BT_SMP)
+      zephyr_library_sources(
+        smp.c
+        keys.c
+        )
+    else()
+      zephyr_library_sources(
+        smp_null.c
+        )
+    endif()
+  endif()
+endif()
+
+if(CONFIG_BT_DEBUG_SMP OR CONFIG_BT_DEBUG_KEYS)
+  message(WARNING "One or both these options are enabled:
+  CONFIG_BT_DEBUG_SMP CONFIG_BT_DEBUG_KEYS.
+  Private security keys such as the LTK will be printed out, do not use in
+  production."
+    )
+endif()
+if(CONFIG_BT_OOB_DATA_FIXED)
+  message(WARNING "CONFIG_BT_OOB_DATA_FIXED is enabled.
+  A hardcoded OOB data set will be stored in the image, do not use in
+  production."
+    )
+endif()
+if(CONFIG_BT_USE_DEBUG_KEYS OR CONFIG_BT_STORE_DEBUG_KEYS)
+  message(WARNING "One or both these options are enabled:
+  CONFIG_BT_USE_DEBUG_KEYS CONFIG_BT_STORE_DEBUG_KEYS.
+  A predefined, publicly available keypair intended for testing will be used.
+  Do not use in production."
+    )
+endif()
+if(CONFIG_BT_CONN_DISABLE_SECURITY)
+  message(WARNING "CONFIG_BT_CONN_DISABLE_SECURITY is enabled.
+  Security is disabled for incoming requests for GATT attributes and L2CAP
+  channels that would otherwise require encryption/authentication in order to
+  be accessed.
+  Do not use in production."
+    )
+endif()
+
+add_subdirectory_ifdef(CONFIG_BT_AUDIO audio)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig	(working copy)
@@ -0,0 +1,819 @@
+# Bluetooth LE stack configuration options
+
+# Copyright (c) 2016-2020 Nordic Semiconductor ASA
+# Copyright (c) 2015-2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+comment "Host Stack Configuration"
+
+config BT_HCI_HOST
+	# Hidden option to make the conditions more intuitive
+	bool
+	default y
+	depends on !BT_HCI_RAW
+	select POLL
+
+config BT_HCI_CMD_COUNT
+	int "Number of HCI command buffers"
+	default 2
+	range 2 64
+	help
+	  Number of buffers available for HCI commands.
+
+config BT_RX_BUF_COUNT
+	int "Number of HCI RX buffers"
+	default NET_BUF_RX_COUNT if NET_L2_BT
+	default 3 if BT_RECV_IS_RX_THREAD
+	default 20 if (BT_MESH && !(BT_DISCARDABLE_BUF_COUNT > 0))
+	default 10
+	range 2 255
+	help
+	  Number of buffers available for incoming ACL packets or HCI events
+	  from the controller.
+
+config BT_RX_BUF_LEN
+	int "Maximum supported HCI RX buffer length"
+	default 264 if BT_BREDR
+	default 258 if BT_EXT_ADV
+	default 77 if BT_MESH_PROXY
+	default 76
+	range 73 2000
+	help
+	  Maximum data size for each HCI RX buffer. This size includes
+	  everything starting with the ACL or HCI event headers. Note that
+	  buffer sizes are always rounded up to the nearest multiple of 4,
+	  so if this Kconfig value is something else then there will be some
+	  wasted space. The minimum of 73 has been taken for LE SC which has
+	  an L2CAP MTU of 65 bytes. On top of this there's the L2CAP header
+	  (4 bytes) and the ACL header (also 4 bytes) which yields 73 bytes.
+
+config BT_DISCARDABLE_BUF_COUNT
+	int "Number of discardable event buffers"
+	range 1 255
+	default 20 if BT_MESH
+	default 3
+	depends on BT_H4 || BT_RPMSG || BT_CTLR
+	help
+	  Number of buffers in a separate buffer pool for events which
+	  the HCI driver considers discardable. Examples of such events
+	  could be e.g. Advertising Reports. The benefit of having such
+	  a pool means that the if there is a heavy inflow of such events
+	  it will not cause the allocation for other critical events to
+	  block and may even eliminate deadlocks in some cases.
+
+config BT_DISCARDABLE_BUF_SIZE
+	int "Size of discardable event buffers"
+	range 45 257
+	default 257 if BT_BREDR || BT_EXT_ADV
+	default 45
+	help
+	  Size of buffers in the separate discardable event buffer pool.
+	  The minimum size is set based on the Advertising Report. Setting
+	  the buffer size different than BT_RX_BUF_LEN can save memory.
+
+config BT_HCI_TX_STACK_SIZE
+	# NOTE: This value is derived from other symbols and should only be
+	# changed if required by architecture
+	int
+	prompt "HCI Tx thread stack size" if BT_HCI_TX_STACK_SIZE_WITH_PROMPT
+	default 512 if BT_H4
+	default 512 if BT_H5
+	default 416 if BT_SPI
+	default 940 if BT_CTLR && BT_LL_SW_SPLIT && NO_OPTIMIZATIONS
+	default 1024 if BT_CTLR && BT_LL_SW_SPLIT && BT_CENTRAL
+	default 640 if BT_CTLR && BT_LL_SW_SPLIT
+	default 512 if BT_USERCHAN
+	default 640 if BT_STM32_IPM
+	# Even if no driver is selected the following default is still
+	# needed e.g. for unit tests. This default will also server as
+	# the worst-case stack size if an out-of-tree controller is used.
+	default 1024
+	help
+	  Stack size needed for executing bt_send with specified driver.
+	  NOTE: This is an advanced setting and should not be changed unless
+	  absolutely necessary
+
+config BT_HCI_TX_STACK_SIZE_WITH_PROMPT
+	bool "Override HCI Tx thread stack size"
+
+config BT_HCI_ECC_STACK_SIZE
+	# NOTE: This value is derived from other symbols and should only be
+	# changed if required by architecture
+	int "HCI ECC thread stack size"
+	default 1100
+	help
+	  NOTE: This is an advanced setting and should not be changed unless
+	  absolutely necessary
+
+config BT_HCI_TX_PRIO
+	# Hidden option for Co-Operative Tx thread priority
+	int
+	default 7
+
+config BT_HCI_RESERVE
+	int
+	default 0 if BT_H4
+	default 1 if BT_H5
+	default 1 if BT_RPMSG
+	default 1 if BT_SPI
+	default 1 if BT_STM32_IPM
+	default 1 if BT_USERCHAN
+	# Even if no driver is selected the following default is still
+	# needed e.g. for unit tests.
+	default 0
+	help
+	  Headroom that the driver needs for sending and receiving buffers. Add a
+	  new 'default' entry for each new driver.
+
+config BT_RECV_IS_RX_THREAD
+	# Hidden option set by the HCI driver to indicate that there's
+	# no need for the host to have its own RX thread.
+	# If this option has been enabled it is then the responsibility of the
+	# HCI driver to call bt_recv_prio from a higher priority context than
+	# bt_recv in order to avoid deadlocks.
+	# If this option is disabled then only bt_recv should be called.
+	bool
+	prompt "bt_recv is called from RX thread" if BT_NO_DRIVER
+
+config BT_RX_STACK_SIZE
+	int "Size of the receiving thread stack"
+	depends on BT_HCI_HOST || BT_RECV_IS_RX_THREAD
+	default 512 if BT_HCI_RAW
+	default 2048 if BT_MESH
+	default 2200 if BT_SETTINGS
+	default 1024
+	range 512 65536 if BT_HCI_RAW
+	range 1100 65536 if BT_MESH
+	range 1024 65536
+	help
+	  Size of the receiving thread stack. This is the context from
+	  which all event callbacks to the application occur. The
+	  default value is sufficient for basic operation, but if the
+	  application needs to do advanced things in its callbacks that
+	  require extra stack space, this value can be increased to
+	  accommodate for that.
+
+config BT_RX_PRIO
+	# Hidden option for Co-Operative Rx thread priority
+	int
+	depends on BT_HCI_HOST || BT_RECV_IS_RX_THREAD
+	default 8
+
+config BT_DRIVER_RX_HIGH_PRIO
+	# Hidden option for Co-Operative HCI driver RX thread priority
+	int
+	default 6
+
+if BT_HCI_HOST
+
+source "subsys/bluetooth/host/audio/Kconfig"
+
+config BT_HOST_CRYPTO
+	# Hidden option that compiles in random number generation and AES
+	# encryption support using TinyCrypt library if this is not provided
+	# by the controller implementation.
+	bool
+	default y if !BT_CTLR_CRYPTO
+	select TINYCRYPT
+	select TINYCRYPT_AES
+	select TINYCRYPT_SHA256
+	select TINYCRYPT_SHA256_HMAC
+	select TINYCRYPT_SHA256_HMAC_PRNG
+
+config BT_SETTINGS
+	bool "Store Bluetooth state and configuration persistently"
+	depends on SETTINGS
+	select MPU_ALLOW_FLASH_WRITE if ARM_MPU
+	help
+	  When selected, the Bluetooth stack will take care of storing
+	  (and restoring) the Bluetooth state (e.g. pairing keys) and
+	  configuration persistently in flash.
+
+	  When this option has been enabled, it's important that the
+	  application makes a call to settings_load() after having done
+	  all necessary initialization (e.g. calling bt_enable). The
+	  reason settings_load() is handled externally to the stack, is
+	  that there may be other subsystems using the settings API, in
+	  which case it's more efficient to load all settings in one go,
+	  instead of each subsystem doing it independently.
+
+if BT_SETTINGS
+config BT_SETTINGS_CCC_LAZY_LOADING
+	bool "Load CCC values from settings when peer connects"
+	default y
+	help
+	  Load Client Configuration Characteristic setting right after a bonded
+	  device connects.
+	  Disabling this option will increase memory usage as CCC values for all
+	  bonded devices will be loaded when calling settings_load.
+
+config BT_SETTINGS_CCC_STORE_ON_WRITE
+	bool "Store CCC value immediately after it has been written"
+	help
+	  Store Client Configuration Characteristic value right after it has
+	  been updated.
+
+	  By default, CCC is only stored on disconnection.
+	  Choosing this option is safer for battery-powered devices or devices
+	  that expect to be reset suddenly. However, it requires additional
+	  workqueue stack space.
+
+config BT_SETTINGS_USE_PRINTK
+	bool "Use snprintk to encode Bluetooth settings key strings"
+	depends on SETTINGS && PRINTK
+	default y
+	help
+	  When selected, Bluetooth settings will use snprintk to encode
+	  key strings.
+	  When not selected, Bluetooth settings will use a faster builtin
+	  function to encode the key string. The drawback is that if
+	  printk is enabled then the program memory footprint will be larger.
+endif # BT_SETTINGS
+
+config BT_WHITELIST
+	bool "Enable whitelist support"
+	help
+	  This option enables the whitelist API. This takes advantage of the
+	  whitelisting feature of a BLE controller.
+	  The whitelist is a global list and the same whitelist is used
+	  by both scanner and advertiser. The whitelist cannot be modified while
+	  it is in use.
+
+	  An Advertiser can whitelist which peers can connect or request scan
+	  response data.
+	  A scanner can whitelist advertiser for which it will generate
+	  advertising reports.
+	  Connections can be established automatically for whitelisted peers.
+
+	  This options deprecates the bt_le_set_auto_conn API in favor of the
+	  bt_conn_create_aute_le API.
+
+if BT_CONN
+
+config BT_ACL_RX_COUNT
+	int "Number of incoming ACL data buffers"
+	default BT_CTLR_RX_BUFFERS if BT_CTLR
+	default NET_BUF_RX_COUNT if NET_L2_BT
+	default 6
+	range 1 64
+	depends on BT_HCI_ACL_FLOW_CONTROL
+	help
+	  Number of buffers available for incoming ACL data.
+
+config BT_CONN_TX_MAX
+	int "Maximum number of pending TX buffers with a callback"
+	default BT_L2CAP_TX_BUF_COUNT
+	range BT_L2CAP_TX_BUF_COUNT 255
+	help
+	  Maximum number of pending TX buffers that have an associated
+	  callback. Normally this can be left to the default value, which
+	  is equal to the number of TX buffers in the stack-internal pool.
+
+config BT_USER_PHY_UPDATE
+	bool "User control of PHY Update Procedure"
+	depends on BT_PHY_UPDATE
+	help
+	  Enable application access to initiate the PHY Update Procedure.
+	  The application can also register a callback to be notified about PHY
+	  changes on the connection. The current PHY info is available in the
+	  connection info.
+
+config BT_AUTO_PHY_UPDATE
+	bool "Auto-initiate PHY Update Procedure"
+	depends on BT_PHY_UPDATE
+	default y if !BT_USER_PHY_UPDATE
+	help
+	  Initiate PHY Update Procedure on connection establishment.
+
+	  Disable this if you want the PHY Update Procedure feature supported
+	  but want to rely on the remote device to initiate the procedure at its
+	  discretion or want to initiate manually.
+
+config BT_USER_DATA_LEN_UPDATE
+	bool "User control of Data Length Update Procedure"
+	depends on BT_DATA_LEN_UPDATE
+	help
+	  Enable application access to initiate the Data Length Update
+	  Procedure. The application can also a register callback to be notified
+	  about Data Length changes on the connection. The current Data Length
+	  info is available in the connection info.
+
+config BT_AUTO_DATA_LEN_UPDATE
+	bool "Auto-initiate Data Length Update procedure"
+	depends on BT_DATA_LEN_UPDATE
+	default y if !BT_USER_DATA_LEN_UPDATE
+	help
+	  Initiate Data Length Update Procedure on connection establishment.
+
+	  Disable this if you want the Data Length Update Procedure feature
+	  supported but want to rely on the remote device to initiate the
+	  procedure at its discretion or want to initiate manually.
+
+config BT_REMOTE_INFO
+	bool "Enable application access to remote information"
+	help
+	  Enable application access to the remote information available in the
+	  stack. The remote information is retrieved once a connection has been
+	  established and the application will be notified when this information
+	  is available through the remote_version_available connection callback.
+
+config BT_REMOTE_VERSION
+	bool "Enable remote version information"
+	depends on BT_REMOTE_INFO
+	help
+	  Enable this to get access to the remote version through
+	  the remote_version_available callback. The host will automatically ask
+	  the remote device after the connection has been established.
+
+config BT_SMP
+	bool "Security Manager Protocol support"
+	select TINYCRYPT
+	select TINYCRYPT_AES
+	select TINYCRYPT_AES_CMAC
+	select BT_RPA
+	help
+	  This option enables support for the Security Manager Protocol
+	  (SMP), making it possible to pair devices over LE.
+
+if BT_SMP
+config BT_PRIVACY
+	bool "Privacy Feature"
+	help
+	  Enable local Privacy Feature support. This makes it possible
+	  to use Resolvable Private Addresses (RPAs).
+
+config BT_RPA_TIMEOUT
+	int "Resolvable Private Address timeout"
+	depends on BT_PRIVACY
+	default 900
+	range 1 65535
+	help
+	  This option defines how often resolvable private address is rotated.
+	  Value is provided in seconds and defaults to 900 seconds (15 minutes).
+
+config BT_SIGNING
+	bool "Data signing support"
+	help
+	  This option enables data signing which is used for transferring
+	  authenticated data in an unencrypted connection.
+
+config BT_SMP_APP_PAIRING_ACCEPT
+	bool "Accept or reject pairing initiative"
+	help
+	  When receiving pairing request or pairing response query the
+	  application whether to accept to proceed with pairing or not. This is
+	  for pairing over SMP and does not affect SSP, which will continue
+	  pairing without querying the application.
+	  The application can return an error code, which is translated into
+	  a SMP return value if the pairing is not allowed.
+
+config BT_SMP_SC_PAIR_ONLY
+	bool "Disable legacy pairing"
+	help
+	  This option disables LE legacy pairing and forces LE secure connection
+	  pairing. All Security Mode 1 levels can be used with legacy pairing
+	  disabled, but pairing with devices that do not support secure
+	  connections pairing will not be supported.
+	  To force a higher security level use "Secure Connections Only Mode"
+
+config BT_SMP_SC_ONLY
+	bool "Secure Connections Only Mode"
+	select BT_SMP_SC_PAIR_ONLY
+	help
+	  This option enables support for Secure Connection Only Mode. In this
+	  mode device shall only use Security Mode 1 Level 4 with exception
+	  for services that only require Security Mode 1 Level 1 (no security).
+	  Security Mode 1 Level 4 stands for authenticated LE Secure Connections
+	  pairing with encryption. Enabling this option disables legacy pairing.
+
+config BT_SMP_OOB_LEGACY_PAIR_ONLY
+	bool "Force Out Of Band Legacy pairing"
+	depends on !(BT_SMP_SC_PAIR_ONLY || BT_SMP_SC_ONLY)
+	help
+	  This option disables Legacy and LE SC pairing and forces legacy OOB.
+
+config BT_SMP_DISABLE_LEGACY_JW_PASSKEY
+	bool "Forbid usage of insecure legacy pairing methods"
+	depends on !(BT_SMP_SC_PAIR_ONLY || BT_SMP_SC_ONLY || \
+		     BT_SMP_OOB_LEGACY_PAIR_ONLY)
+	help
+	  This option disables Just Works and Passkey legacy pairing methods to
+	  increase security.
+
+config BT_SMP_ALLOW_UNAUTH_OVERWRITE
+	bool "Allow unauthenticated pairing for paired device"
+	help
+	  This option allows all unauthenticated pairing attempts made by the
+	  peer where an unauthenticated bond already exists.
+	  This would enable cases where an attacker could copy the peer device
+	  address to connect and start an unauthenticated pairing procedure
+	  to replace the existing bond. When this option is disabled in order
+	  to create a new bond the old bond has to be explicitly deleted with
+	  bt_unpair.
+
+config BT_SMP_USB_HCI_CTLR_WORKAROUND
+	bool "Workaround for USB HCI controller out-of-order events"
+	depends on BT_TESTING
+	help
+	  This option enables support for USB HCI controllers that sometimes
+	  send out-of-order HCI events and ACL Data due to using different USB
+	  endpoints.
+	  Enabling this option will make the master role not require the
+	  encryption-change event to be received before accepting key-distribution
+	  data.
+	  It opens up for a potential vulnerability as the master cannot detect
+	  if the keys are distributed over an encrypted link.
+
+config BT_FIXED_PASSKEY
+	bool "Use a fixed passkey for pairing"
+	help
+	  With this option enabled, the application will be able to call the
+	  bt_passkey_set() API to set a fixed passkey. If set, the
+	  pairing_confim() callback will be called for all incoming pairings.
+
+config BT_USE_DEBUG_KEYS
+	bool "Enable Security Manager Debug Mode"
+	depends on BT_TINYCRYPT_ECC
+	help
+	  This option places Security Manager in a Debug Mode. In this mode
+	  predefined Diffie-Hellman private/public key pair is used as described
+	  in Core Specification Vol. 3, Part H, 2.3.5.6.1.
+
+	  WARNING: This option enables anyone to decrypt on-air traffic.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_BONDABLE
+	bool "Bondable Mode"
+	default y
+	help
+	  This option enables support for Bondable Mode. In this mode,
+	  Bonding flag in AuthReq of SMP Pairing Request/Response will be set
+	  indicating the support for this mode.
+
+config BT_BONDING_REQUIRED
+	bool "Always require bonding"
+	depends on BT_BONDABLE
+	help
+	  When this option is enabled remote devices are required to always
+	  set the bondable flag in their pairing request. Any other kind of
+	  requests will be rejected.
+
+config BT_STORE_DEBUG_KEYS
+	bool "Store Debug Mode bonds"
+	help
+	  This option enables support for storing bonds where either of devices
+	  is using the predefined Diffie-Hellman private/public key pair as
+	  described in the Core Specification Vol 3, Part H, 2.3.5.6.1.
+
+	  WARNING: This option potentially enables anyone to decrypt on-air
+	  traffic.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_SMP_ENFORCE_MITM
+	bool "Enforce MITM protection"
+	default y
+	help
+	  With this option enabled, the Security Manager will set MITM option in
+	  the Authentication Requirements Flags whenever local IO Capabilities
+	  allow the generated key to be authenticated.
+
+config BT_OOB_DATA_FIXED
+	bool "Use a fixed random number for LESC OOB pairing"
+	depends on BT_TESTING
+	help
+	  With this option enabled, the application will be able to perform LESC
+	  pairing with OOB data that consists of fixed random number and confirm
+	  value.
+
+	  WARNING: This option stores a hardcoded Out-of-Band value in the image.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_KEYS_OVERWRITE_OLDEST
+	bool "Overwrite oldest keys with new ones if key storage is full"
+	help
+	  With this option enabled, if a pairing attempt occurs and the key storage
+	  is full, then the oldest keys in storage will be removed to free space
+	  for the new pairing keys.
+
+config BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING
+	bool "Store aging counter every time a successful paring occurs"
+	depends on BT_SETTINGS && BT_KEYS_OVERWRITE_OLDEST
+	help
+	  With this option enabled, aging counter will be stored in settings every
+	  time a successful pairing occurs. This increases flash wear out but offers
+	  a more correct finding of the oldest unused pairing info.
+
+endif # BT_SMP
+
+source "subsys/bluetooth/host/Kconfig.l2cap"
+source "subsys/bluetooth/host/Kconfig.gatt"
+
+config BT_MAX_PAIRED
+	int "Maximum number of paired devices"
+	default 0 if !BT_SMP
+	default 1
+	range 0 128
+	help
+	  Maximum number of paired Bluetooth devices. The minimum (and
+	  default) number is 1.
+
+config BT_CREATE_CONN_TIMEOUT
+	int "Timeout for pending LE Create Connection command in seconds"
+	default 3
+	range 1 BT_RPA_TIMEOUT if BT_PRIVACY && (BT_RPA_TIMEOUT < 655)
+	range 1 655
+
+config BT_CONN_PARAM_UPDATE_TIMEOUT
+	int "Peripheral connection parameter update timeout in milliseconds"
+	default 5000
+	range 1 65535
+
+	help
+	  The value is a timeout used by peripheral device to wait until it
+	  starts the connection parameters update procedure to change default
+	  connection parameters. The default value is set to 5s, to comply
+	  with BT protocol specification: Core 4.2 Vol 3, Part C, 9.3.12.2
+
+endif # BT_CONN
+
+if BT_OBSERVER
+config BT_BACKGROUND_SCAN_INTERVAL
+	int "Scan interval used for background scanning in 0.625 ms units"
+	default 2048
+	range 4 16384
+config BT_BACKGROUND_SCAN_WINDOW
+	int "Scan window used for background scanning in 0.625 ms units"
+	default 18
+	range 4 16384
+endif # BT_OBSERVER
+
+config BT_SCAN_WITH_IDENTITY
+	bool "Perform active scanning using local identity address"
+	depends on !BT_PRIVACY && (BT_CENTRAL || BT_OBSERVER)
+	help
+	  Enable this if you want to perform active scanning using the local
+	  identity address as the scanner address. By default the stack will
+	  always use a non-resolvable private address (NRPA) in order to avoid
+	  disclosing local identity information. By not scanning with the
+	  identity address the scanner will receive directed advertise reports
+	  for for the local identity. If this use case is required, then enable
+	  this option.
+
+config BT_DEVICE_NAME_DYNAMIC
+	bool "Allow to set Bluetooth device name on runtime"
+	help
+	  Enabling this option allows for runtime configuration of Bluetooth
+	  device name.
+
+config BT_DEVICE_NAME_MAX
+	int "Maximum size in bytes for device name"
+	depends on BT_DEVICE_NAME_DYNAMIC
+	default 28
+	range 2 248
+	help
+	  Bluetooth device name storage size. Storage can be up to 248 bytes
+	  long (excluding NULL termination).
+
+config BT_DEVICE_NAME
+	string "Bluetooth device name"
+	default "Zephyr"
+	help
+	  Bluetooth device name. Name can be up to 248 bytes long (excluding
+	  NULL termination). Can be empty string.
+
+config BT_DEVICE_APPEARANCE
+	int "Bluetooth device appearance"
+	range 0 65535
+	default 0
+	help
+	  Bluetooth device appearance. For the list of possible values please
+	  consult the following link:
+	  https://www.bluetooth.com/specifications/assigned-numbers
+
+config BT_ID_MAX
+	int "Maximum number of local identities"
+	range 1 10
+	default 1
+	help
+	  Maximum number of supported local identity addresses. For most
+	  products this is safe to leave as the default value (1).
+
+endif # BT_HCI_HOST
+
+config BT_ECC
+	bool "Enable ECDH key generation support"
+	default y if BT_MESH_PROV || (BT_SMP && !BT_SMP_OOB_LEGACY_PAIR_ONLY)
+	help
+	  This option adds support for ECDH HCI commands.
+
+config BT_TINYCRYPT_ECC
+	bool "Use TinyCrypt library for ECDH"
+	select TINYCRYPT
+	select TINYCRYPT_ECC_DH
+	depends on BT_ECC && (BT_HCI_RAW || BT_HCI_HOST)
+	default y if BT_CTLR
+	help
+	  If this option is set TinyCrypt library is used for emulating the
+	  ECDH HCI commands and events needed by e.g. LE Secure Connections.
+	  In builds including the BLE Host, if not set the controller crypto is
+	  used for ECDH and if the controller doesn't support the required HCI
+	  commands the LE Secure Connections support will be disabled.
+	  In builds including the HCI Raw interface and the BLE Controller, this
+	  option injects support for the 2 HCI commands required for LE Secure
+	  Connections so that Hosts can make use of those. The option defaults
+	  to enabled for a combined build with Zephyr's own controller, since it
+	  does not have any special ECC support itself (at least not currently).
+
+config BT_HOST_CCM
+	bool "Enable host side AES-CCM module"
+	help
+	  Enables the software based AES-CCM engine in the host. Will use the
+	  controller's AES encryption functions if available, or BT_HOST_CRYPTO
+	  otherwise.
+
+if BT_DEBUG
+config BT_DEBUG_SETTINGS
+	bool "Bluetooth storage debug"
+	depends on BT_SETTINGS
+	help
+	  This option enables debug support for Bluetooth storage.
+
+config BT_DEBUG_HCI_CORE
+	bool "Bluetooth HCI core debug"
+	help
+	  This option enables debug support for Bluetooth HCI
+	  core.
+
+config BT_DEBUG_CONN
+	bool "Bluetooth connection debug"
+	depends on BT_CONN
+	help
+	  This option enables debug support for Bluetooth
+	  connection handling.
+
+config BT_DEBUG_KEYS
+	bool "Bluetooth security keys debug"
+	depends on BT_HCI_HOST
+	depends on BT_SMP
+	help
+	  This option enables debug support for the handling of
+	  Bluetooth security keys.
+
+	  WARNING: This option prints out private security keys such as
+	  the Long Term Key.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_DEBUG_SMP
+	bool "Bluetooth Security Manager Protocol (SMP) debug"
+	depends on BT_HCI_HOST
+	depends on BT_SMP
+	help
+	  This option enables debug support for the Bluetooth
+	  Security Manager Protocol (SMP).
+
+	  WARNING: This option prints out private security keys such as
+	  the Long Term Key.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_SMP_SELFTEST
+	bool "Bluetooth SMP self tests executed on init"
+	depends on BT_DEBUG_SMP
+	help
+	  This option enables SMP self-tests executed on startup
+	  to verify security and crypto functions.
+
+config BT_SMP_FORCE_BREDR
+	bool "Force Bluetooth SMP over BR/EDR"
+	depends on BT_DEBUG_SMP
+	help
+	  This option enables SMP over BR/EDR even if controller is not
+	  supporting BR/EDR Secure Connections. This option is solely for
+	  testing and should never be enabled on production devices.
+
+config BT_DEBUG_RFCOMM
+	bool "Bluetooth RFCOMM debug"
+	depends on BT_RFCOMM
+	help
+	  This option enables debug support for the Bluetooth
+	  RFCOMM layer.
+
+config BT_DEBUG_HFP_HF
+	bool "Bluetooth Hands Free Profile (HFP) debug"
+	depends on BT_HFP_HF
+	help
+	  This option enables debug support for the Bluetooth
+	  Hands Free Profile (HFP).
+
+config BT_DEBUG_AVDTP
+	bool "Bluetooth AVDTP debug"
+	depends on BT_AVDTP
+	help
+	  This option enables debug support for the Bluetooth AVDTP.
+
+config BT_DEBUG_A2DP
+	bool "Bluetooth A2DP debug"
+	depends on BT_A2DP
+	help
+	  This option enables debug support for the Bluetooth
+	  A2DP profile.
+
+config BT_DEBUG_SDP
+	bool "Bluetooth Service Discovery Protocol (SDP) debug"
+	depends on BT_BREDR
+	help
+	  This option enables debug support for the Bluetooth
+	  Service Discovery Protocol (SDP).
+
+config BT_DEBUG_SERVICE
+	bool "Bluetooth Services debug"
+	depends on BT_CONN
+	help
+	  This option enables debug support for the Bluetooth
+	  Services.
+
+endif # BT_DEBUG
+
+config BT_TESTING
+	bool "Bluetooth Testing"
+	help
+	  This option enables custom Bluetooth testing interface.
+	  Shall only be used for testing purposes.
+
+config BT_CONN_DISABLE_SECURITY
+	bool "Disable security"
+	depends on BT_TESTING
+	help
+	  This option disables security checks for incoming requests enabling
+	  to test accessing GATT attributes and L2CAP channels that would
+	  otherwise require encryption/authentication in order to be accessed.
+
+	  WARNING: This option enables anyone to snoop on-air traffic.
+	  Use of this feature in production is strongly discouraged.
+
+config BT_BREDR
+	bool "Bluetooth BR/EDR support [EXPERIMENTAL]"
+	depends on BT_HCI_HOST
+	select BT_PERIPHERAL
+	select BT_CENTRAL
+	select BT_SMP
+	select BT_L2CAP_DYNAMIC_CHANNEL
+	help
+	  This option enables Bluetooth BR/EDR support
+
+if BT_BREDR
+config BT_MAX_SCO_CONN
+	int "Maximum number of simultaneous SCO connections"
+	default 1
+	range 1 3
+	help
+	  Maximum number of simultaneous Bluetooth synchronous connections
+	  supported. The minimum (and default) number is 1.
+
+config BT_RFCOMM
+	bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]"
+	help
+	  This option enables Bluetooth RFCOMM support
+
+config BT_RFCOMM_L2CAP_MTU
+	int "L2CAP MTU for RFCOMM frames"
+	default BT_L2CAP_RX_MTU if BT_HCI_ACL_FLOW_CONTROL
+	default BT_RX_BUF_LEN
+	depends on BT_RFCOMM
+	range BT_L2CAP_RX_MTU 32767 if BT_HCI_ACL_FLOW_CONTROL
+	range BT_RX_BUF_LEN 32767
+	help
+	  Maximum size of L2CAP PDU for RFCOMM frames.
+
+config BT_HFP_HF
+	bool "Bluetooth Handsfree profile HF Role support [EXPERIMENTAL]"
+	depends on PRINTK
+	select BT_RFCOMM
+	help
+	  This option enables Bluetooth HF support
+
+config BT_AVDTP
+	bool "Bluetooth AVDTP protocol support [EXPERIMENTAL]"
+	help
+	  This option enables Bluetooth AVDTP support
+
+config BT_A2DP
+	bool "Bluetooth A2DP Profile [EXPERIMENTAL]"
+	select BT_AVDTP
+	help
+	  This option enables the A2DP profile
+
+config BT_PAGE_TIMEOUT
+	hex "Bluetooth Page Timeout"
+	default 0x2000
+	range 0x0001 0xffff
+	help
+	  This option sets the page timeout value. Value is selected as
+	  (N * 0.625) ms.
+
+endif # BT_BREDR
+
+config BT_HCI_VS_EVT_USER
+	bool "User Vendor-Specific event handling"
+	help
+	  Enable registering a callback for delegating to the user the handling of
+	  VS events that are not known to the stack
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.gatt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.gatt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.gatt	(working copy)
@@ -0,0 +1,221 @@
+# Bluetooth ATT/GATT configuration options
+
+# Copyright (c) 2019 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menu "ATT and GATT Options"
+
+config BT_ATT_ENFORCE_FLOW
+	bool "Enforce strict flow control semantics for incoming PDUs"
+	default y if !(BOARD_QEMU_CORTEX_M3 || BOARD_QEMU_X86 || ARCH_POSIX)
+	help
+	  Enforce flow control rules on incoming PDUs, preventing a peer
+	  from sending new requests until a previous one has been responded
+	  or sending a new indication until a previous one has been
+	  confirmed. This may need to be disabled to avoid potential race
+	  conditions arising from a USB based HCI transport that splits
+	  HCI events and ACL data to separate endpoints.
+
+config BT_ATT_PREPARE_COUNT
+	int "Number of ATT prepare write buffers"
+	default 0
+	range 0 64
+	help
+	  Number of buffers available for ATT prepare write, setting
+	  this to 0 disables GATT long/reliable writes.
+
+config BT_ATT_TX_MAX
+	int "Maximum number of queued outgoing ATT PDUs"
+	default BT_L2CAP_TX_BUF_COUNT
+	range 1 BT_L2CAP_TX_BUF_COUNT
+	help
+	  Number of ATT PDUs that can be at a single moment queued for
+	  transmission. If the application tries to send more than this
+	  amount the calls will block until an existing queued PDU gets
+	  sent.
+
+config BT_EATT
+	bool "Enhanced ATT Bearers support [EXPERIMENTAL]"
+	depends on BT_L2CAP_DYNAMIC_CHANNEL
+	help
+	  This option enables support for Enhanced ATT bearers support. When
+	  enabled additional L2CAP channels can be connected as bearers enabling
+	  multiple outstanding request.
+
+if BT_EATT
+
+config BT_EATT_MAX
+	int "Maximum number of Enhanced ATT bearers"
+	default 3
+	range 1 16
+
+	help
+	  Number of Enhanced ATT bearers available.
+
+config BT_EATT_RX_MTU
+	int "Maximum supported Enhanced ATT MTU for incoming data"
+	default 70
+	range 70 519
+	depends on BT_EATT
+	help
+	  Maximum size incoming PDUs on EATT bearers, value shall include L2CAP
+	  headers and SDU length, maximum is limited to 512 bytes payload, which
+	  is the maximum size for a GATT attribute, plus 1 byte for ATT opcode.
+	  This option influences the stack buffer size and by that may also
+	  limit the outgoing MTU.
+
+config BT_EATT_SEC_LEVEL
+	int "Enhanced ATT bearer security level"
+	default 1
+	range 1 4
+	help
+	  L2CAP server required security level of EATT bearers:
+	  Level 1 (BT_SECURITY_L1) = No encryption or authentication required
+	  Level 2 (BT_SECURITY_L2) = Only encryption required
+	  Level 3 (BT_SECURITY_L3) = Encryption and authentication required
+	  Level 4 (BT_SECURITY_L4) = Secure connection required
+
+endif # BT_EATT
+
+config BT_GATT_SERVICE_CHANGED
+	bool "GATT Service Changed support"
+	default y
+	help
+	  This option enables support for the service changed characteristic.
+
+config BT_GATT_DYNAMIC_DB
+	bool "GATT dynamic database support"
+	depends on BT_GATT_SERVICE_CHANGED
+	help
+	  This option enables registering/unregistering services at runtime.
+
+config BT_GATT_CACHING
+	bool "GATT Caching support"
+	default y
+	depends on BT_GATT_SERVICE_CHANGED
+	select TINYCRYPT
+	select TINYCRYPT_AES
+	select TINYCRYPT_AES_CMAC
+	help
+	  This option enables support for GATT Caching. When enabled the stack
+	  will register Client Supported Features and Database Hash
+	  characteristics which can be used by clients to detect if anything has
+	  changed on the GATT database.
+
+if BT_GATT_CACHING
+
+config BT_GATT_NOTIFY_MULTIPLE
+	bool "GATT Notify Multiple Characteristic Values support"
+	depends on BT_GATT_CACHING
+	help
+	  This option enables support for the GATT Notify Multiple
+	  Characteristic Values procedure.
+
+config BT_GATT_ENFORCE_CHANGE_UNAWARE
+	bool "GATT Enforce change-unaware state"
+	depends on BT_GATT_CACHING
+	help
+	  When enable this option blocks notification and indications to client
+	  to conform to the following statement from the Bluetooth 5.1
+	  specification:
+	  '...the server shall not send notifications and indications to such
+	  a client until it becomes change-aware."
+	  In case the service cannot deal with sudden errors (-EAGAIN) then it
+	  shall not use this option.
+
+endif # BT_GATT_CACHING
+
+config BT_GATT_CLIENT
+	bool "GATT client support"
+	help
+	  This option enables support for the GATT Client role.
+
+config BT_GATT_READ_MULTIPLE
+	bool "GATT Read Multiple Characteristic Values support"
+	default y
+	help
+	  This option enables support for the GATT Read Multiple Characteristic
+	  Values procedure.
+
+config BT_GATT_AUTO_DISCOVER_CCC
+	bool "Support to automatic discover the CCC handles of characteristics"
+	depends on BT_GATT_CLIENT
+	help
+	  This option enables support for GATT to initiate discovery for CCC
+	  handles if the CCC handle is unknown by the application.
+
+config BT_GAP_AUTO_UPDATE_CONN_PARAMS
+	bool "Automatic Update of Connection Parameters"
+	default y
+	depends on BT_PERIPHERAL
+	help
+	  This option if enabled allows automatically sending request for connection
+	  parameters update after GAP recommended 5 seconds of connection as
+	  peripheral.
+
+config BT_GAP_PERIPHERAL_PREF_PARAMS
+	bool "Configure peripheral preferred connection parameters"
+	default y
+	depends on BT_PERIPHERAL
+	help
+	  This allows to configure peripheral preferred connection parameters.
+	  Enabling this option results in adding PPCP characteristic in GAP.
+	  If disabled it is up to application to set expected connection parameters.
+
+if BT_GAP_PERIPHERAL_PREF_PARAMS
+config BT_PERIPHERAL_PREF_MIN_INT
+	int "Peripheral preferred minimum connection interval in 1.25ms units"
+	default 24
+	range 6 65535
+	help
+	  Range 3200 to 65534 is invalid. 65535 represents no specific value.
+
+config BT_PERIPHERAL_PREF_MAX_INT
+	int "Peripheral preferred maximum connection interval in 1.25ms units"
+	default 40
+	range 6 65535
+	help
+	  Range 3200 to 65534 is invalid. 65535 represents no specific value.
+
+config BT_PERIPHERAL_PREF_SLAVE_LATENCY
+	int "Peripheral preferred slave latency in Connection Intervals"
+	default 0
+	range 0 499
+
+config BT_PERIPHERAL_PREF_TIMEOUT
+	int "Peripheral preferred supervision timeout in 10ms units"
+	default 42
+	range 10 65535
+	help
+	  It is up to user to provide valid timeout which pass required minimum
+	  value: in milliseconds it shall be larger than
+	  "(1+ Conn_Latency) * Conn_Interval_Max * 2"
+	  where Conn_Interval_Max is given in milliseconds.
+	  Range 3200 to 65534 is invalid. 65535 represents no specific value.
+endif # BT_GAP_PERIPHERAL_PREF_PARAMS
+
+config BT_DEVICE_NAME_GATT_WRITABLE
+	bool "Allow to write name by remote GATT clients"
+	depends on BT_DEVICE_NAME_DYNAMIC
+	default y
+	help
+	  Enabling this option allows remote GATT clients to write to device
+	  name GAP characteristic.
+
+if BT_DEBUG
+
+config BT_DEBUG_ATT
+	bool "Bluetooth Attribute Protocol (ATT) debug"
+	help
+	  This option enables debug support for the Bluetooth
+	  Attribute Protocol (ATT).
+
+config BT_DEBUG_GATT
+	bool "Bluetooth Generic Attribute Profile (GATT) debug"
+	help
+	  This option enables debug support for the Bluetooth
+	  Generic Attribute Profile (GATT).
+
+endif # BT_DEBUG
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.l2cap
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.l2cap	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/Kconfig.l2cap	(working copy)
@@ -0,0 +1,66 @@
+# Bluetooth ATT/GATT configuration options
+
+# Copyright (c) 2019 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menu "L2CAP Options"
+
+config BT_L2CAP_RX_MTU
+	int "Maximum supported L2CAP MTU for incoming data"
+	default 200 if BT_BREDR
+	default BT_EATT_RX_MTU if BT_EATT
+	default 65 if BT_SMP
+	default 23
+	range 70 1300 if BT_EATT
+	range 65 1300 if BT_SMP
+	range 23 1300
+	help
+	  Maximum size of each incoming L2CAP PDU.
+
+config BT_L2CAP_TX_BUF_COUNT
+	int "Number of L2CAP TX buffers"
+	default NET_BUF_TX_COUNT if NET_L2_BT
+	default BT_CTLR_TX_BUFFERS if BT_CTLR
+	default 3
+	range 2 255
+	help
+	  Number of buffers available for outgoing L2CAP packets.
+
+config BT_L2CAP_TX_FRAG_COUNT
+	int "Number of L2CAP TX fragment buffers"
+	default NET_BUF_TX_COUNT if NET_L2_BT
+	default 2
+	range 0 255
+	help
+	  Number of buffers available for fragments of TX buffers. Warning:
+	  setting this to 0 means that the application must ensure that
+	  queued TX buffers never need to be fragmented, i.e. that the
+	  controller's buffer size is large enough. If this is not ensured,
+	  and there are no dedicated fragment buffers, a deadlock may occur.
+	  In most cases the default value of 2 is a safe bet.
+
+config BT_L2CAP_TX_MTU
+	int "Maximum supported L2CAP MTU for L2CAP TX buffers"
+	default 253 if BT_BREDR
+	default 65 if BT_SMP
+	default 23
+	range 65 2000 if BT_SMP
+	range 23 2000
+	help
+	  Maximum L2CAP MTU for L2CAP TX buffers.
+
+config BT_L2CAP_DYNAMIC_CHANNEL
+	bool "L2CAP Dynamic Channel support"
+	depends on BT_SMP
+	help
+	  This option enables support for LE Connection oriented Channels,
+	  allowing the creation of dynamic L2CAP Channels.
+
+config BT_DEBUG_L2CAP
+	bool "Bluetooth L2CAP debug"
+	depends on BT_DEBUG
+	help
+	  This option enables debug support for the Bluetooth
+	  L2ACP layer.
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp.c	(working copy)
@@ -0,0 +1,161 @@
+/** @file
+ * @brief Advance Audio Distribution Profile.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <sys/printk.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/avdtp.h>
+#include <bluetooth/a2dp.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_A2DP)
+#define LOG_MODULE_NAME bt_a2dp
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "avdtp_internal.h"
+#include "a2dp_internal.h"
+
+#define A2DP_NO_SPACE (-1)
+
+struct bt_a2dp {
+	struct bt_avdtp session;
+};
+
+/* Connections */
+static struct bt_a2dp connection[CONFIG_BT_MAX_CONN];
+
+void a2d_reset(struct bt_a2dp *a2dp_conn)
+{
+	(void)memset(a2dp_conn, 0, sizeof(struct bt_a2dp));
+}
+
+struct bt_a2dp *get_new_connection(struct bt_conn *conn)
+{
+	int8_t i, free;
+
+	free = A2DP_NO_SPACE;
+
+	if (!conn) {
+		BT_ERR("Invalid Input (err: %d)", -EINVAL);
+		return NULL;
+	}
+
+	/* Find a space */
+	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		if (connection[i].session.br_chan.chan.conn == conn) {
+			BT_DBG("Conn already exists");
+			return NULL;
+		}
+
+		if (!connection[i].session.br_chan.chan.conn &&
+		    free == A2DP_NO_SPACE) {
+			free = i;
+		}
+	}
+
+	if (free == A2DP_NO_SPACE) {
+		BT_DBG("More connection cannot be supported");
+		return NULL;
+	}
+
+	/* Clean the memory area before returning */
+	a2d_reset(&connection[free]);
+
+	return &connection[free];
+}
+
+int a2dp_accept(struct bt_conn *conn, struct bt_avdtp **session)
+{
+	struct bt_a2dp *a2dp_conn;
+
+	a2dp_conn = get_new_connection(conn);
+	if (!a2dp_conn) {
+		return -ENOMEM;
+	}
+
+	*session = &(a2dp_conn->session);
+	BT_DBG("session: %p", &(a2dp_conn->session));
+
+	return 0;
+}
+
+/* Callback for incoming requests */
+static struct bt_avdtp_ind_cb cb_ind = {
+	/*TODO*/
+};
+
+/* The above callback structures need to be packed and passed to AVDTP */
+static struct bt_avdtp_event_cb avdtp_cb = {
+	.ind = &cb_ind,
+	.accept = a2dp_accept
+};
+
+int bt_a2dp_init(void)
+{
+	int err;
+
+	/* Register event handlers with AVDTP */
+	err = bt_avdtp_register(&avdtp_cb);
+	if (err < 0) {
+		BT_ERR("A2DP registration failed");
+		return err;
+	}
+
+	BT_DBG("A2DP Initialized successfully.");
+	return 0;
+}
+
+struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn)
+{
+	struct bt_a2dp *a2dp_conn;
+	int err;
+
+	a2dp_conn = get_new_connection(conn);
+	if (!a2dp_conn) {
+		BT_ERR("Cannot allocate memory");
+		return NULL;
+	}
+
+	err = bt_avdtp_connect(conn, &(a2dp_conn->session));
+	if (err < 0) {
+		/* If error occurs, undo the saving and return the error */
+		a2d_reset(a2dp_conn);
+		BT_DBG("AVDTP Connect failed");
+		return NULL;
+	}
+
+	BT_DBG("Connect request sent");
+	return a2dp_conn;
+}
+
+int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint,
+			      uint8_t media_type, uint8_t role)
+{
+	int err;
+
+	BT_ASSERT(endpoint);
+
+	err = bt_avdtp_register_sep(media_type, role, &(endpoint->info));
+	if (err < 0) {
+		return err;
+	}
+
+	/* TODO: Register SDP record */
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/a2dp_internal.h	(working copy)
@@ -0,0 +1,12 @@
+/** @file
+ * @brief Advance Audio Distribution Profile Internal header.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* To be called when first SEP is being registered */
+int bt_a2dp_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/aes_ccm.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/aes_ccm.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/aes_ccm.c	(working copy)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+
+#include <zephyr.h>
+#include <sys/byteorder.h>
+#include <bluetooth/crypto.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_aes_ccm
+#include "common/log.h"
+
+static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
+{
+	dst[0] = a[0] ^ b[0];
+	dst[1] = a[1] ^ b[1];
+	dst[2] = a[2] ^ b[2];
+	dst[3] = a[3] ^ b[3];
+	dst[4] = a[4] ^ b[4];
+	dst[5] = a[5] ^ b[5];
+	dst[6] = a[6] ^ b[6];
+	dst[7] = a[7] ^ b[7];
+	dst[8] = a[8] ^ b[8];
+	dst[9] = a[9] ^ b[9];
+	dst[10] = a[10] ^ b[10];
+	dst[11] = a[11] ^ b[11];
+	dst[12] = a[12] ^ b[12];
+	dst[13] = a[13] ^ b[13];
+	dst[14] = a[14] ^ b[14];
+	dst[15] = a[15] ^ b[15];
+}
+
+/* pmsg is assumed to have the nonce already present in bytes 1-13 */
+static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
+			    size_t mic_size, uint8_t msg_len, uint8_t b[16],
+			    uint8_t X0[16])
+{
+	int i, j, err;
+
+	/* X_0 = e(AppKey, flags || nonce || length) */
+	b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
+
+	sys_put_be16(msg_len, b + 14);
+
+	err = bt_encrypt_be(key, b, X0);
+	if (err) {
+		return err;
+	}
+
+	/* If AAD is being used to authenticate, include it here */
+	if (aad_len) {
+		sys_put_be16(aad_len, b);
+
+		for (i = 0; i < sizeof(uint16_t); i++) {
+			b[i] = X0[i] ^ b[i];
+		}
+
+		j = 0;
+		aad_len += sizeof(uint16_t);
+		while (aad_len > 16) {
+			do {
+				b[i] = X0[i] ^ aad[j];
+				i++, j++;
+			} while (i < 16);
+
+			aad_len -= 16;
+			i = 0;
+
+			err = bt_encrypt_be(key, b, X0);
+			if (err) {
+				return err;
+			}
+		}
+
+		for (; i < aad_len; i++, j++) {
+			b[i] = X0[i] ^ aad[j];
+		}
+
+		for (i = aad_len; i < 16; i++) {
+			b[i] = X0[i];
+		}
+
+		err = bt_encrypt_be(key, b, X0);
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
+		    const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
+		    size_t aad_len, uint8_t *mic, size_t mic_size)
+{
+	uint8_t b[16], Xn[16], s0[16];
+	uint16_t blk_cnt, last_blk;
+	int err, j, i;
+
+	last_blk = msg_len % 16;
+	blk_cnt = (msg_len + 15) / 16;
+	if (!last_blk) {
+		last_blk = 16U;
+	}
+
+	b[0] = 0x01;
+	memcpy(b + 1, nonce, 13);
+
+	/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
+	sys_put_be16(0x0000, &b[14]);
+
+	err = bt_encrypt_be(key, b, s0);
+	if (err) {
+		return err;
+	}
+
+	ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
+
+	for (j = 0; j < blk_cnt; j++) {
+		/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
+		if (j + 1 == blk_cnt) {
+			for (i = 0; i < last_blk; i++) {
+				b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
+			}
+
+			memcpy(&b[i], &Xn[i], 16 - i);
+		} else {
+			xor16(b, Xn, &cleartext_msg[j * 16]);
+		}
+
+		err = bt_encrypt_be(key, b, Xn);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* MIC = C_mic ^ X_1 */
+	for (i = 0; i < mic_size; i++) {
+		mic[i] = s0[i] ^ Xn[i];
+	}
+
+	return 0;
+}
+
+static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
+		     const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
+{
+	uint8_t a_i[16], s_i[16];
+	uint16_t last_blk, blk_cnt;
+	size_t i, j;
+	int err;
+
+	last_blk = msg_len % 16;
+	blk_cnt = (msg_len + 15) / 16;
+	if (!last_blk) {
+		last_blk = 16U;
+	}
+
+	a_i[0] = 0x01;
+	memcpy(&a_i[1], nonce, 13);
+
+	for (j = 0; j < blk_cnt; j++) {
+		/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
+		sys_put_be16(j + 1, &a_i[14]);
+
+		err = bt_encrypt_be(key, a_i, s_i);
+		if (err) {
+			return err;
+		}
+
+		/* Encrypted = Payload[0-15] ^ C_1 */
+		if (j < blk_cnt - 1) {
+			xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
+		} else {
+			for (i = 0; i < last_blk; i++) {
+				out_msg[(j * 16) + i] =
+					in_msg[(j * 16) + i] ^ s_i[i];
+			}
+		}
+	}
+	return 0;
+}
+
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
+		   size_t msg_len, const uint8_t *aad, size_t aad_len,
+		   uint8_t *out_msg, size_t mic_size)
+{
+	uint8_t mic[16];
+
+	if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
+		return -EINVAL;
+	}
+
+	ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
+
+	ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+	if (memcmp(mic, enc_msg + msg_len, mic_size)) {
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
+		   size_t msg_len, const uint8_t *aad, size_t aad_len,
+		   uint8_t *out_msg, size_t mic_size)
+{
+	uint8_t *mic = out_msg + msg_len;
+
+	BT_DBG("key %s", bt_hex(key, 16));
+	BT_DBG("nonce %s", bt_hex(nonce, 13));
+	BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
+	BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
+
+	/* Unsupported AAD size */
+	if (aad_len >= 0xff00 || mic_size > 16) {
+		return -EINVAL;
+	}
+
+	ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+	ccm_crypt(key, nonce, msg, out_msg, msg_len);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.h	(working copy)
@@ -0,0 +1,118 @@
+/** @file at.h
+ *  @brief Internal APIs for AT command handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+enum at_result {
+	AT_RESULT_OK,
+	AT_RESULT_ERROR,
+	AT_RESULT_CME_ERROR
+};
+
+enum at_cme {
+	CME_ERROR_AG_FAILURE                    = 0,
+	CME_ERROR_NO_CONNECTION_TO_PHONE        = 1,
+	CME_ERROR_OPERATION_NOT_ALLOWED         = 3,
+	CME_ERROR_OPERATION_NOT_SUPPORTED       = 4,
+	CME_ERROR_PH_SIM_PIN_REQUIRED           = 5,
+	CME_ERROR_SIM_NOT_INSERTED              = 10,
+	CME_ERROR_SIM_PIN_REQUIRED              = 11,
+	CME_ERROR_SIM_PUK_REQUIRED              = 12,
+	CME_ERROR_SIM_FAILURE                   = 13,
+	CME_ERROR_SIM_BUSY                      = 14,
+	CME_ERROR_INCORRECT_PASSWORD            = 16,
+	CME_ERROR_SIM_PIN2_REQUIRED             = 17,
+	CME_ERROR_SIM_PUK2_REQUIRED             = 18,
+	CME_ERROR_MEMORY_FULL                   = 20,
+	CME_ERROR_INVALID_INDEX                 = 21,
+	CME_ERROR_MEMORY_FAILURE                = 23,
+	CME_ERROR_TEXT_STRING_TOO_LONG          = 24,
+	CME_ERROR_INVALID_CHARS_IN_TEXT_STRING  = 25,
+	CME_ERROR_DIAL_STRING_TO_LONG           = 26,
+	CME_ERROR_INVALID_CHARS_IN_DIAL_STRING  = 27,
+	CME_ERROR_NO_NETWORK_SERVICE            = 30,
+	CME_ERROR_NETWORK_TIMEOUT               = 31,
+	CME_ERROR_NETWORK_NOT_ALLOWED           = 32,
+	CME_ERROR_UNKNOWN                       = 33,
+};
+
+enum at_state {
+	AT_STATE_START,
+	AT_STATE_START_CR,
+	AT_STATE_START_LF,
+	AT_STATE_GET_CMD_STRING,
+	AT_STATE_PROCESS_CMD,
+	AT_STATE_GET_RESULT_STRING,
+	AT_STATE_PROCESS_RESULT,
+	AT_STATE_PROCESS_AG_NW_ERR,
+	AT_STATE_UNSOLICITED_CMD,
+	AT_STATE_END
+};
+
+enum at_cmd_state {
+	AT_CMD_START,
+	AT_CMD_GET_VALUE,
+	AT_CMD_PROCESS_VALUE,
+	AT_CMD_STATE_END_LF,
+	AT_CMD_STATE_END
+};
+
+enum at_cmd_type {
+	AT_CMD_TYPE_NORMAL,
+	AT_CMD_TYPE_UNSOLICITED,
+	AT_CMD_TYPE_OTHER
+};
+
+struct at_client;
+
+/* Callback at_resp_cb_t used to parse response value received for the
+ * particular AT command. Eg: +CIND=<value>
+ */
+typedef int (*at_resp_cb_t)(struct at_client *at, struct net_buf *buf);
+
+/* Callback at_finish_cb used to monitor the success or failure of the AT
+ * command received from server.
+ * Argument 'cme_err' is valid only when argument 'result' is equal to
+ * AT_RESULT_CME_ERROR
+ */
+typedef int (*at_finish_cb_t)(struct at_client *at, enum at_result result,
+			      enum at_cme cme_err);
+typedef int (*parse_val_t)(struct at_client *at);
+typedef int (*handle_parse_input_t)(struct at_client *at, struct net_buf *buf);
+typedef int (*handle_cmd_input_t)(struct at_client *at, struct net_buf *buf,
+				  const char *prefix, parse_val_t func,
+				  enum at_cmd_type type);
+
+struct at_client {
+	char *buf;
+	uint8_t pos;
+	uint8_t buf_max_len;
+	uint8_t state;
+	uint8_t cmd_state;
+	at_resp_cb_t resp;
+	at_resp_cb_t unsolicited;
+	at_finish_cb_t finish;
+};
+
+/* Register the callback functions */
+void at_register(struct at_client *at, at_resp_cb_t resp,
+		 at_finish_cb_t finish);
+void at_register_unsolicited(struct at_client *at, at_resp_cb_t unsolicited);
+int at_get_number(struct at_client *at, uint32_t *val);
+/* This parsing will only works for non-fragmented net_buf */
+int at_parse_input(struct at_client *at, struct net_buf *buf);
+/* This command parsing will only works for non-fragmented net_buf */
+int at_parse_cmd_input(struct at_client *at, struct net_buf *buf,
+		       const char *prefix, parse_val_t func,
+		       enum at_cmd_type type);
+int at_check_byte(struct net_buf *buf, char check_byte);
+int at_list_get_range(struct at_client *at, uint32_t *min, uint32_t *max);
+int at_list_get_string(struct at_client *at, char *name, uint8_t len);
+int at_close_list(struct at_client *at);
+int at_open_list(struct at_client *at);
+int at_has_next_list(struct at_client *at);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/at.c	(working copy)
@@ -0,0 +1,537 @@
+/**
+ * @file at.c
+ * Generic AT command handling library implementation
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <net/buf.h>
+
+#include "at.h"
+
+static void next_list(struct at_client *at)
+{
+	if (at->buf[at->pos] == ',') {
+		at->pos++;
+	}
+}
+
+int at_check_byte(struct net_buf *buf, char check_byte)
+{
+	const unsigned char *str = buf->data;
+
+	if (*str != check_byte) {
+		return -EINVAL;
+	}
+	net_buf_pull(buf, 1);
+
+	return 0;
+}
+
+static void skip_space(struct at_client *at)
+{
+	while (at->buf[at->pos] == ' ') {
+		at->pos++;
+	}
+}
+
+int at_get_number(struct at_client *at, uint32_t *val)
+{
+	uint32_t i;
+
+	skip_space(at);
+
+	for (i = 0U, *val = 0U;
+	     isdigit((unsigned char)at->buf[at->pos]);
+	     at->pos++, i++) {
+		*val = *val * 10U + at->buf[at->pos] - '0';
+	}
+
+	if (i == 0U) {
+		return -ENODATA;
+	}
+
+	next_list(at);
+	return 0;
+}
+
+static bool str_has_prefix(const char *str, const char *prefix)
+{
+	if (strncmp(str, prefix, strlen(prefix)) != 0) {
+		return false;
+	}
+
+	return true;
+}
+
+static int at_parse_result(const char *str, struct net_buf *buf,
+			   enum at_result *result)
+{
+	/* Map the result and check for end lf */
+	if ((!strncmp(str, "OK", 2)) && (at_check_byte(buf, '\n') == 0)) {
+		*result = AT_RESULT_OK;
+		return 0;
+	}
+
+	if ((!strncmp(str, "ERROR", 5)) && (at_check_byte(buf, '\n')) == 0) {
+		*result = AT_RESULT_ERROR;
+		return 0;
+	}
+
+	return -ENOMSG;
+}
+
+static int get_cmd_value(struct at_client *at, struct net_buf *buf,
+			 char stop_byte, enum at_cmd_state cmd_state)
+{
+	int cmd_len = 0;
+	uint8_t pos = at->pos;
+	const char *str = (char *)buf->data;
+
+	while (cmd_len < buf->len && at->pos != at->buf_max_len) {
+		if (*str != stop_byte) {
+			at->buf[at->pos++] = *str;
+			cmd_len++;
+			str++;
+			pos = at->pos;
+		} else {
+			cmd_len++;
+			at->buf[at->pos] = '\0';
+			at->pos = 0U;
+			at->cmd_state = cmd_state;
+			break;
+		}
+	}
+	net_buf_pull(buf, cmd_len);
+
+	if (pos == at->buf_max_len) {
+		return -ENOBUFS;
+	}
+
+	return 0;
+}
+
+static int get_response_string(struct at_client *at, struct net_buf *buf,
+			       char stop_byte, enum at_state state)
+{
+	int cmd_len = 0;
+	uint8_t pos = at->pos;
+	const char *str = (char *)buf->data;
+
+	while (cmd_len < buf->len && at->pos != at->buf_max_len) {
+		if (*str != stop_byte) {
+			at->buf[at->pos++] = *str;
+			cmd_len++;
+			str++;
+			pos = at->pos;
+		} else {
+			cmd_len++;
+			at->buf[at->pos] = '\0';
+			at->pos = 0U;
+			at->state = state;
+			break;
+		}
+	}
+	net_buf_pull(buf, cmd_len);
+
+	if (pos == at->buf_max_len) {
+		return -ENOBUFS;
+	}
+
+	return 0;
+}
+
+static void reset_buffer(struct at_client *at)
+{
+	(void)memset(at->buf, 0, at->buf_max_len);
+	at->pos = 0U;
+}
+
+static int at_state_start(struct at_client *at, struct net_buf *buf)
+{
+	int err;
+
+	err = at_check_byte(buf, '\r');
+	if (err < 0) {
+		return err;
+	}
+	at->state = AT_STATE_START_CR;
+
+	return 0;
+}
+
+static int at_state_start_cr(struct at_client *at, struct net_buf *buf)
+{
+	int err;
+
+	err = at_check_byte(buf, '\n');
+	if (err < 0) {
+		return err;
+	}
+	at->state = AT_STATE_START_LF;
+
+	return 0;
+}
+
+static int at_state_start_lf(struct at_client *at, struct net_buf *buf)
+{
+	reset_buffer(at);
+	if (at_check_byte(buf, '+') == 0) {
+		at->state = AT_STATE_GET_CMD_STRING;
+		return 0;
+	} else if (isalpha(*buf->data)) {
+		at->state = AT_STATE_GET_RESULT_STRING;
+		return 0;
+	}
+
+	return -ENODATA;
+}
+
+static int at_state_get_cmd_string(struct at_client *at, struct net_buf *buf)
+{
+	return get_response_string(at, buf, ':', AT_STATE_PROCESS_CMD);
+}
+
+static bool is_cmer(struct at_client *at)
+{
+	if (strncmp(at->buf, "CME ERROR", 9) == 0) {
+		return true;
+	}
+
+	return false;
+}
+
+static int at_state_process_cmd(struct at_client *at, struct net_buf *buf)
+{
+	if (is_cmer(at)) {
+		at->state = AT_STATE_PROCESS_AG_NW_ERR;
+		return 0;
+	}
+
+	if (at->resp) {
+		at->resp(at, buf);
+		at->resp = NULL;
+		return 0;
+	}
+	at->state = AT_STATE_UNSOLICITED_CMD;
+	return 0;
+}
+
+static int at_state_get_result_string(struct at_client *at, struct net_buf *buf)
+{
+	return get_response_string(at, buf, '\r', AT_STATE_PROCESS_RESULT);
+}
+
+static bool is_ring(struct at_client *at)
+{
+	if (strncmp(at->buf, "RING", 4) == 0) {
+		return true;
+	}
+
+	return false;
+}
+
+static int at_state_process_result(struct at_client *at, struct net_buf *buf)
+{
+	enum at_cme cme_err;
+	enum at_result result;
+
+	if (is_ring(at)) {
+		at->state = AT_STATE_UNSOLICITED_CMD;
+		return 0;
+	}
+
+	if (at_parse_result(at->buf, buf, &result) == 0) {
+		if (at->finish) {
+			/* cme_err is 0 - Is invalid until result is
+			 * AT_RESULT_CME_ERROR
+			 */
+			cme_err = 0;
+			at->finish(at, result, cme_err);
+		}
+	}
+
+	/* Reset the state to process unsolicited response */
+	at->cmd_state = AT_CMD_START;
+	at->state = AT_STATE_START;
+
+	return 0;
+}
+
+int cme_handle(struct at_client *at)
+{
+	enum at_cme cme_err;
+	uint32_t val;
+
+	if (!at_get_number(at, &val) && val <= CME_ERROR_NETWORK_NOT_ALLOWED) {
+		cme_err = val;
+	} else {
+		cme_err = CME_ERROR_UNKNOWN;
+	}
+
+	if (at->finish) {
+		at->finish(at, AT_RESULT_CME_ERROR, cme_err);
+	}
+
+	return 0;
+}
+
+static int at_state_process_ag_nw_err(struct at_client *at, struct net_buf *buf)
+{
+	at->cmd_state = AT_CMD_GET_VALUE;
+	return at_parse_cmd_input(at, buf, NULL, cme_handle,
+				  AT_CMD_TYPE_NORMAL);
+}
+
+static int at_state_unsolicited_cmd(struct at_client *at, struct net_buf *buf)
+{
+	if (at->unsolicited) {
+		return at->unsolicited(at, buf);
+	}
+
+	return -ENODATA;
+}
+
+/* The order of handler function should match the enum at_state */
+static handle_parse_input_t parser_cb[] = {
+	at_state_start, /* AT_STATE_START */
+	at_state_start_cr, /* AT_STATE_START_CR */
+	at_state_start_lf, /* AT_STATE_START_LF */
+	at_state_get_cmd_string, /* AT_STATE_GET_CMD_STRING */
+	at_state_process_cmd, /* AT_STATE_PROCESS_CMD */
+	at_state_get_result_string, /* AT_STATE_GET_RESULT_STRING */
+	at_state_process_result, /* AT_STATE_PROCESS_RESULT */
+	at_state_process_ag_nw_err, /* AT_STATE_PROCESS_AG_NW_ERR */
+	at_state_unsolicited_cmd /* AT_STATE_UNSOLICITED_CMD */
+};
+
+int at_parse_input(struct at_client *at, struct net_buf *buf)
+{
+	int ret;
+
+	while (buf->len) {
+		if (at->state < AT_STATE_START || at->state >= AT_STATE_END) {
+			return -EINVAL;
+		}
+		ret = parser_cb[at->state](at, buf);
+		if (ret < 0) {
+			/* Reset the state in case of error */
+			at->cmd_state = AT_CMD_START;
+			at->state = AT_STATE_START;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int at_cmd_start(struct at_client *at, struct net_buf *buf,
+			const char *prefix, parse_val_t func,
+			enum at_cmd_type type)
+{
+	if (!str_has_prefix(at->buf, prefix)) {
+		if (type == AT_CMD_TYPE_NORMAL) {
+			at->state = AT_STATE_UNSOLICITED_CMD;
+		}
+		return -ENODATA;
+	}
+
+	if (type == AT_CMD_TYPE_OTHER) {
+		/* Skip for Other type such as ..RING.. which does not have
+		 * values to get processed.
+		 */
+		at->cmd_state = AT_CMD_PROCESS_VALUE;
+	} else {
+		at->cmd_state = AT_CMD_GET_VALUE;
+	}
+
+	return 0;
+}
+
+static int at_cmd_get_value(struct at_client *at, struct net_buf *buf,
+			    const char *prefix, parse_val_t func,
+			    enum at_cmd_type type)
+{
+	/* Reset buffer before getting the values */
+	reset_buffer(at);
+	return get_cmd_value(at, buf, '\r', AT_CMD_PROCESS_VALUE);
+}
+
+static int at_cmd_process_value(struct at_client *at, struct net_buf *buf,
+				const char *prefix, parse_val_t func,
+				enum at_cmd_type type)
+{
+	int ret;
+
+	ret = func(at);
+	at->cmd_state = AT_CMD_STATE_END_LF;
+
+	return ret;
+}
+
+static int at_cmd_state_end_lf(struct at_client *at, struct net_buf *buf,
+			       const char *prefix, parse_val_t func,
+			       enum at_cmd_type type)
+{
+	int err;
+
+	err = at_check_byte(buf, '\n');
+	if (err < 0) {
+		return err;
+	}
+
+	at->cmd_state = AT_CMD_START;
+	at->state = AT_STATE_START;
+	return 0;
+}
+
+/* The order of handler function should match the enum at_cmd_state */
+static handle_cmd_input_t cmd_parser_cb[] = {
+	at_cmd_start, /* AT_CMD_START */
+	at_cmd_get_value, /* AT_CMD_GET_VALUE */
+	at_cmd_process_value, /* AT_CMD_PROCESS_VALUE */
+	at_cmd_state_end_lf /* AT_CMD_STATE_END_LF */
+};
+
+int at_parse_cmd_input(struct at_client *at, struct net_buf *buf,
+		       const char *prefix, parse_val_t func,
+		       enum at_cmd_type type)
+{
+	int ret;
+
+	while (buf->len) {
+		if (at->cmd_state < AT_CMD_START ||
+		    at->cmd_state >= AT_CMD_STATE_END) {
+			return -EINVAL;
+		}
+		ret = cmd_parser_cb[at->cmd_state](at, buf, prefix, func, type);
+		if (ret < 0) {
+			return ret;
+		}
+		/* Check for main state, the end of cmd parsing and return. */
+		if (at->state == AT_STATE_START) {
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+int at_has_next_list(struct at_client *at)
+{
+	return at->buf[at->pos] != '\0';
+}
+
+int at_open_list(struct at_client *at)
+{
+	skip_space(at);
+
+	/* The list shall start with '(' open parenthesis */
+	if (at->buf[at->pos] != '(') {
+		return -ENODATA;
+	}
+	at->pos++;
+
+	return 0;
+}
+
+int at_close_list(struct at_client *at)
+{
+	skip_space(at);
+
+	if (at->buf[at->pos] != ')') {
+		return -ENODATA;
+	}
+	at->pos++;
+
+	next_list(at);
+
+	return 0;
+}
+
+int at_list_get_string(struct at_client *at, char *name, uint8_t len)
+{
+	int i = 0;
+
+	skip_space(at);
+
+	if (at->buf[at->pos] != '"') {
+		return -ENODATA;
+	}
+	at->pos++;
+
+	while (at->buf[at->pos] != '\0' && at->buf[at->pos] != '"') {
+		if (i == len) {
+			return -ENODATA;
+		}
+		name[i++] = at->buf[at->pos++];
+	}
+
+	if (i == len) {
+		return -ENODATA;
+	}
+
+	name[i] = '\0';
+
+	if (at->buf[at->pos] != '"') {
+		return -ENODATA;
+	}
+	at->pos++;
+
+	skip_space(at);
+	next_list(at);
+
+	return 0;
+}
+
+int at_list_get_range(struct at_client *at, uint32_t *min, uint32_t *max)
+{
+	uint32_t low, high;
+	int ret;
+
+	ret = at_get_number(at, &low);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (at->buf[at->pos] == '-') {
+		at->pos++;
+		goto out;
+	}
+
+	if (!isdigit((unsigned char)at->buf[at->pos])) {
+		return -ENODATA;
+	}
+out:
+	ret = at_get_number(at, &high);
+	if (ret < 0) {
+		return ret;
+	}
+
+	*min = low;
+	*max = high;
+
+	next_list(at);
+
+	return 0;
+}
+
+void at_register_unsolicited(struct at_client *at, at_resp_cb_t unsolicited)
+{
+	at->unsolicited = unsolicited;
+}
+
+void at_register(struct at_client *at, at_resp_cb_t resp, at_finish_cb_t finish)
+{
+	at->resp = resp;
+	at->finish = finish;
+	at->state = AT_STATE_START;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att.c	(working copy)
@@ -0,0 +1,3096 @@
+/* att.c - Attribute protocol handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_ATT)
+#define LOG_MODULE_NAME bt_att
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "smp.h"
+#include "att_internal.h"
+#include "gatt_internal.h"
+
+#define ATT_CHAN(_ch) CONTAINER_OF(_ch, struct bt_att_chan, chan.chan)
+#define ATT_REQ(_node) CONTAINER_OF(_node, struct bt_att_req, node)
+
+#define ATT_CMD_MASK				0x40
+
+#if defined(CONFIG_BT_EATT)
+#define ATT_CHAN_MAX				(CONFIG_BT_EATT_MAX + 1)
+#else
+#define ATT_CHAN_MAX				1
+#endif /* CONFIG_BT_EATT */
+
+typedef enum __packed {
+		ATT_COMMAND,
+		ATT_REQUEST,
+		ATT_RESPONSE,
+		ATT_NOTIFICATION,
+		ATT_CONFIRMATION,
+		ATT_INDICATION,
+		ATT_UNKNOWN,
+} att_type_t;
+
+static att_type_t att_op_get_type(uint8_t op);
+
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+struct bt_attr_data {
+	uint16_t handle;
+	uint16_t offset;
+};
+
+/* Pool for incoming ATT packets */
+NET_BUF_POOL_DEFINE(prep_pool, CONFIG_BT_ATT_PREPARE_COUNT, BT_ATT_MTU,
+		    sizeof(struct bt_attr_data), NULL);
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
+
+K_MEM_SLAB_DEFINE(req_slab, sizeof(struct bt_att_req),
+		  CONFIG_BT_ATT_TX_MAX, 16);
+
+enum {
+	ATT_PENDING_RSP,
+	ATT_PENDING_CFM,
+	ATT_DISCONNECTED,
+	ATT_ENHANCED,
+	ATT_PENDING_SENT,
+
+	/* Total number of flags - must be at the end of the enum */
+	ATT_NUM_FLAGS,
+};
+
+/* ATT channel specific data */
+struct bt_att_chan {
+	/* Connection this channel is associated with */
+	struct bt_att		*att;
+	struct bt_l2cap_le_chan	chan;
+	ATOMIC_DEFINE(flags, ATT_NUM_FLAGS);
+	struct bt_att_req	*req;
+	struct k_fifo		tx_queue;
+	//struct k_delayed_work	timeout_work;
+	//struct k_sem            tx_sem;
+	void (*sent)(struct bt_att_chan *chan);
+	sys_snode_t		node;
+};
+
+/* ATT connection specific data */
+struct bt_att {
+	struct bt_conn		*conn;
+	/* Shared request queue */
+	sys_slist_t		reqs;
+	struct k_fifo		tx_queue;
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+	struct k_fifo		prep_queue;
+#endif
+	/* Contains bt_att_chan instance(s) */
+	sys_slist_t		chans;
+};
+
+K_MEM_SLAB_DEFINE(att_slab, sizeof(struct bt_att),
+		  CONFIG_BT_MAX_CONN, 16);
+K_MEM_SLAB_DEFINE(chan_slab, sizeof(struct bt_att_chan),
+		  CONFIG_BT_MAX_CONN * ATT_CHAN_MAX, 16);
+static struct bt_att_req cancel;
+
+static void att_req_destroy(struct bt_att_req *req)
+{
+	BT_DBG("req %p", req);
+
+	if (req->buf) {
+		net_buf_unref(req->buf);
+	}
+
+	if (req->destroy) {
+		req->destroy(req);
+	}
+
+	bt_att_req_free(req);
+}
+
+typedef void (*bt_att_chan_sent_t)(struct bt_att_chan *chan);
+
+static bt_att_chan_sent_t chan_cb(struct net_buf *buf);
+static bt_conn_tx_cb_t att_cb(bt_att_chan_sent_t cb);
+
+void att_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *chan = user_data;
+
+	BT_DBG("conn %p chan %p", conn, chan);
+
+	if (chan->ops->sent) {
+		chan->ops->sent(chan);
+	}
+}
+
+static int chan_send(struct bt_att_chan *chan, struct net_buf *buf,
+		     bt_att_chan_sent_t cb)
+{
+	struct bt_att_hdr *hdr;
+	struct net_buf_simple_state state;
+	int err;
+
+	hdr = (void *)buf->data;
+
+	BT_DBG("chan_send, code 0x%02x", hdr->code);
+
+	if (IS_ENABLED(CONFIG_BT_EATT) &&
+	    atomic_test_bit(chan->flags, ATT_ENHANCED)) {
+		/* Check if sent is pending already, if it does it cannot be
+		 * modified so the operation will need to be queued.
+		 */
+		if (atomic_test_and_set_bit(chan->flags, ATT_PENDING_SENT)) {
+			return -EAGAIN;
+		}
+
+		chan->sent = cb ? cb : chan_cb(buf);
+
+		if (hdr->code == BT_ATT_OP_SIGNED_WRITE_CMD) {
+			return -ENOTSUP;
+		}
+
+		/* Check if the channel is ready to send in case of a request */
+		if (att_op_get_type(hdr->code) == ATT_REQUEST &&
+		    !atomic_test_bit(chan->chan.chan.status,
+				     BT_L2CAP_STATUS_OUT)) {
+			return -EAGAIN;
+		}
+
+		/* bt_l2cap_chan_send does actually return the number of bytes
+		 * that could be sent immediatelly.
+		 */
+		err = bt_l2cap_chan_send(&chan->chan.chan, buf);
+		if (err < 0) {
+			return err;
+		}
+
+		return 0;
+	}
+
+	if (hdr->code == BT_ATT_OP_SIGNED_WRITE_CMD) {
+		int err;
+
+		//err = bt_smp_sign(chan->att->conn, buf);
+		if (err) {
+			BT_ERR("Error signing data");
+			net_buf_unref(buf);
+			return err;
+		}
+	}
+
+	net_buf_simple_save(&buf->b, &state);
+
+	chan->sent = cb ? cb : chan_cb(buf);
+
+	/* Take a ref since bt_l2cap_send_cb takes ownership of the buffer */
+	err = bt_l2cap_send_cb(chan->att->conn, BT_L2CAP_CID_ATT,
+				net_buf_ref(buf), att_cb(chan->sent),
+				&chan->chan.chan);
+	if (!err) {
+		net_buf_unref(buf);
+		return 0;
+	}
+
+	net_buf_simple_restore(&buf->b, &state);
+
+	return err;
+
+}
+
+static int process_queue(struct bt_att_chan *chan, struct k_fifo *queue)
+{
+	struct net_buf *buf;
+	int err;
+
+	buf = net_buf_get(queue, K_NO_WAIT);
+	if (buf) {
+		err = chan_send(chan, buf, NULL);
+		if (err) {
+			/* Push it back if it could not be send */
+			k_queue_prepend(&queue->_queue, buf);
+			return err;
+		}
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+/* Send requests without taking tx_sem */
+static int chan_req_send(struct bt_att_chan *chan, struct bt_att_req *req)
+{
+	int err;
+
+	if (chan->chan.tx.mtu < net_buf_frags_len(req->buf)) {
+		return -EMSGSIZE;
+	}
+
+	BT_DBG("chan %p req %p len %zu", chan, req,
+	       net_buf_frags_len(req->buf));
+
+	chan->req = req;
+
+	/* Save request state so it can be resent */
+	net_buf_simple_save(&req->buf->b, &req->state);
+
+	/* Keep a reference for resending the req in case the security
+	 * needs to be changed.
+	 */
+	err = chan_send(chan, net_buf_ref(req->buf), NULL);
+	if (err) {
+		/* Drop the extra reference if buffer could not be sent but
+		 * don't reset the buffer as it will likelly be pushed back to
+		 * request queue to be send later.
+		 */
+		net_buf_unref(req->buf);
+	}
+
+	return err;
+}
+
+static void bt_att_sent(struct bt_l2cap_chan *ch)
+{
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+	struct bt_att *att = chan->att;
+	int err;
+
+	BT_DBG("chan %p", chan);
+
+	if (chan->sent) {
+		chan->sent(chan);
+	}
+
+	atomic_clear_bit(chan->flags, ATT_PENDING_SENT);
+
+	/* Process pending requests first since they require a response they
+	 * can only be processed one at time while if other queues were
+	 * processed before they may always contain a buffer starving the
+	 * request queue.
+	 */
+	if (!chan->req && !sys_slist_is_empty(&att->reqs)) {
+		sys_snode_t *node = sys_slist_get(&att->reqs);
+
+		if (chan_req_send(chan, ATT_REQ(node)) >= 0) {
+			return;
+		}
+
+		/* Prepend back to the list as it could not be sent */
+		sys_slist_prepend(&att->reqs, node);
+	}
+
+	/* Process channel queue */
+	err = process_queue(chan, &chan->tx_queue);
+	if (!err) {
+		return;
+	}
+
+	/* Process global queue */
+	err = process_queue(chan, &att->tx_queue);
+	if (!err) {
+		return;
+	}
+
+	//k_sem_give(&chan->tx_sem);
+}
+
+static void chan_cfm_sent(struct bt_att_chan *chan)
+{
+	BT_DBG("chan %p", chan);
+
+	if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) {
+		atomic_clear_bit(chan->flags, ATT_PENDING_CFM);
+	}
+}
+
+static void chan_rsp_sent(struct bt_att_chan *chan)
+{
+	BT_DBG("chan %p", chan);
+
+	if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) {
+		atomic_clear_bit(chan->flags, ATT_PENDING_RSP);
+	}
+}
+
+static void chan_req_sent(struct bt_att_chan *chan)
+{
+	BT_DBG("chan %p chan->req %p", chan, chan->req);
+
+	/* Start timeout work */
+	if (chan->req) {
+		//k_delayed_work_submit(&chan->timeout_work, BT_ATT_TIMEOUT);
+	}
+}
+
+static bt_att_chan_sent_t chan_cb(struct net_buf *buf)
+{
+	switch (att_op_get_type(buf->data[0])) {
+	case ATT_RESPONSE:
+		return chan_rsp_sent;
+	case ATT_CONFIRMATION:
+		return chan_cfm_sent;
+	case ATT_REQUEST:
+	case ATT_INDICATION:
+		return chan_req_sent;
+	default:
+		return NULL;
+	}
+}
+
+static void att_cfm_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *ch = user_data;
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+
+	BT_DBG("conn %p chan %p", conn, chan);
+
+	chan->sent = chan_cfm_sent;
+
+	att_sent(conn, user_data);
+}
+
+static void att_rsp_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *ch = user_data;
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+
+	BT_DBG("conn %p chan %p", conn, chan);
+
+	chan->sent = chan_rsp_sent;
+
+	att_sent(conn, user_data);
+}
+
+static void att_req_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *ch = user_data;
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+
+	BT_DBG("att_req_sent, conn %p chan %p", conn, chan);
+
+	chan->sent = chan_req_sent;
+
+	att_sent(conn, user_data);
+}
+
+static bt_conn_tx_cb_t att_cb(bt_att_chan_sent_t cb)
+{
+	if (cb == chan_rsp_sent) {
+		return att_rsp_sent;
+	} else if (cb == chan_cfm_sent) {
+		return att_cfm_sent;
+	} else if (cb == chan_req_sent) {
+		return att_req_sent;
+	} else {
+		return att_sent;
+	}
+}
+
+struct net_buf *bt_att_chan_create_pdu(struct bt_att_chan *chan, uint8_t op,
+				       size_t len)
+{
+	struct bt_att_hdr *hdr;
+	struct net_buf *buf;
+
+	if (len + sizeof(op) > chan->chan.tx.mtu) {
+		BT_WARN("ATT MTU exceeded, max %u, wanted %zu",
+			chan->chan.tx.mtu, len + sizeof(op));
+		return NULL;
+	}
+
+	switch (att_op_get_type(op)) {
+	case ATT_RESPONSE:
+	case ATT_CONFIRMATION:
+		/* Use a timeout only when responding/confirming */
+		buf = bt_l2cap_create_pdu_timeout(NULL, 0, BT_ATT_TIMEOUT);
+		break;
+	default:
+		buf = bt_l2cap_create_pdu(NULL, 0);
+	}
+
+	if (!buf) {
+		BT_ERR("Unable to allocate buffer for op 0x%02x", op);
+		return NULL;
+	}
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = op;
+
+	return buf;
+}
+
+static inline bool att_chan_is_connected(struct bt_att_chan *chan)
+{
+	return (chan->att->conn->state != BT_CONN_CONNECTED ||
+		!atomic_test_bit(chan->flags, ATT_DISCONNECTED));
+}
+
+static int bt_att_chan_send(struct bt_att_chan *chan, struct net_buf *buf,
+			    bt_att_chan_sent_t cb)
+{
+	struct bt_att_hdr *hdr;
+
+	hdr = (void *)buf->data;
+
+	BT_DBG("bt_att_chan_send, chan %p flags %u code 0x%02x", chan, atomic_get(chan->flags),
+	       hdr->code);
+
+	/* Don't use tx_sem if caller has set it own callback */
+	if (!cb) {
+		//if (k_sem_take(&chan->tx_sem, K_NO_WAIT) < 0) {
+		//	return -EAGAIN;
+		//}
+	}
+
+	return chan_send(chan, buf, cb);
+}
+
+static void bt_att_chan_send_rsp(struct bt_att_chan *chan, struct net_buf *buf,
+				 bt_att_chan_sent_t cb)
+{
+	int err;
+
+	err = bt_att_chan_send(chan, buf, cb);
+	if (err) {
+		/* Responses need to be sent back using the same channel */
+		net_buf_put(&chan->tx_queue, buf);
+	}
+}
+
+static void send_err_rsp(struct bt_att_chan *chan, uint8_t req, uint16_t handle,
+			 uint8_t err)
+{
+	struct bt_att_error_rsp *rsp;
+	struct net_buf *buf;
+
+	/* Ignore opcode 0x00 */
+	if (!req) {
+		return;
+	}
+
+	buf = bt_att_chan_create_pdu(chan, BT_ATT_OP_ERROR_RSP, sizeof(*rsp));
+	if (!buf) {
+		return;
+	}
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->request = req;
+	rsp->handle = sys_cpu_to_le16(handle);
+	rsp->error = err;
+
+	bt_att_chan_send_rsp(chan, buf, chan_rsp_sent);
+}
+
+static uint8_t att_mtu_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_conn *conn = chan->att->conn;
+	struct bt_att_exchange_mtu_req *req;
+	struct bt_att_exchange_mtu_rsp *rsp;
+	struct net_buf *pdu;
+	uint16_t mtu_client, mtu_server;
+
+	/* Exchange MTU sub-procedure shall only be supported on the
+	 * LE Fixed Channel Unenhanced ATT bearer.
+	 */
+	if (atomic_test_bit(chan->flags, ATT_ENHANCED)) {
+		return BT_ATT_ERR_NOT_SUPPORTED;
+	}
+
+	req = (void *)buf->data;
+
+	mtu_client = sys_le16_to_cpu(req->mtu);
+
+	BT_DBG("Client MTU %u", mtu_client);
+
+	/* Check if MTU is valid */
+	if (mtu_client < BT_ATT_DEFAULT_LE_MTU) {
+		return BT_ATT_ERR_INVALID_PDU;
+	}
+
+	pdu = bt_att_create_pdu(conn, BT_ATT_OP_MTU_RSP, sizeof(*rsp));
+	if (!pdu) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	mtu_server = BT_ATT_MTU;
+
+	BT_DBG("Server MTU %u", mtu_server);
+
+	rsp = net_buf_add(pdu, sizeof(*rsp));
+	rsp->mtu = sys_cpu_to_le16(mtu_server);
+
+	bt_att_chan_send_rsp(chan, pdu, chan_rsp_sent);
+
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part F] page 484:
+	 *
+	 * A device's Exchange MTU Request shall contain the same MTU as the
+	 * device's Exchange MTU Response (i.e. the MTU shall be symmetric).
+	 */
+	chan->chan.rx.mtu = MIN(mtu_client, mtu_server);
+	chan->chan.tx.mtu = chan->chan.rx.mtu;
+
+	BT_DBG("Negotiated MTU %u", chan->chan.rx.mtu);
+	return 0;
+}
+
+static int bt_att_chan_req_send(struct bt_att_chan *chan,
+				struct bt_att_req *req)
+{
+	int err;
+
+	__ASSERT_NO_MSG(chan);
+	__ASSERT_NO_MSG(req);
+	__ASSERT_NO_MSG(req->func);
+	__ASSERT_NO_MSG(!chan->req);
+
+	BT_DBG("req %p", req);
+
+	//if (k_sem_take(&chan->tx_sem, K_NO_WAIT) < 0) {
+	//	return -EAGAIN;
+	//}
+
+	err = chan_req_send(chan, req);
+	if (err < 0) {
+		//k_sem_give(&chan->tx_sem);
+	}
+
+	return err;
+}
+
+static void att_process(struct bt_att *att)
+{
+	sys_snode_t *node;
+	struct bt_att_chan *chan, *tmp;
+
+	/* Pull next request from the list */
+	node = sys_slist_get(&att->reqs);
+	if (!node) {
+		return;
+	}
+
+	BT_DBG("req %p", ATT_REQ(node));
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		/* If there is nothing pending use the channel */
+		if (!chan->req) {
+			if (bt_att_chan_req_send(chan, ATT_REQ(node)) >= 0) {
+				return;
+			}
+		}
+	}
+
+	/* Prepend back to the list as it could not be sent */
+	sys_slist_prepend(&att->reqs, node);
+}
+
+static uint8_t att_handle_rsp(struct bt_att_chan *chan, void *pdu, uint16_t len,
+			   uint8_t err)
+{
+	bt_att_func_t func = NULL;
+	void *params;
+
+	BT_DBG("chan %p err 0x%02x len %u: %s", chan, err, len,
+	       bt_hex(pdu, len));
+
+	/* Cancel timeout if ongoing */
+	//k_delayed_work_cancel(&chan->timeout_work);
+
+	if (!chan->req) {
+		BT_WARN("No pending ATT request");
+		goto process;
+	}
+
+	/* Check if request has been cancelled */
+	if (chan->req == &cancel) {
+		chan->req = NULL;
+		goto process;
+	}
+
+	/* Release original buffer */
+	if (chan->req->buf) {
+		net_buf_unref(chan->req->buf);
+		chan->req->buf = NULL;
+	}
+
+	/* Reset func so it can be reused by the callback */
+	func = chan->req->func;
+	chan->req->func = NULL;
+	params = chan->req->user_data;
+
+	/* free allocated request so its memory can be reused */
+	att_req_destroy(chan->req);
+	chan->req = NULL;
+
+process:
+	/* Process pending requests */
+	att_process(chan->att);
+	if (func) {
+		func(chan->att->conn, err, pdu, len, params);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+static uint8_t att_mtu_rsp(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_exchange_mtu_rsp *rsp;
+	uint16_t mtu;
+
+	rsp = (void *)buf->data;
+
+	mtu = sys_le16_to_cpu(rsp->mtu);
+
+	BT_DBG("Server MTU %u", mtu);
+
+	/* Check if MTU is valid */
+	if (mtu < BT_ATT_DEFAULT_LE_MTU) {
+		return att_handle_rsp(chan, NULL, 0, BT_ATT_ERR_INVALID_PDU);
+	}
+
+	chan->chan.rx.mtu = MIN(mtu, BT_ATT_MTU);
+
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part F] page 484:
+	 *
+	 * A device's Exchange MTU Request shall contain the same MTU as the
+	 * device's Exchange MTU Response (i.e. the MTU shall be symmetric).
+	 */
+	chan->chan.tx.mtu = chan->chan.rx.mtu;
+
+	BT_DBG("Negotiated MTU %u", chan->chan.rx.mtu);
+
+	return att_handle_rsp(chan, rsp, buf->len, 0);
+}
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+static bool range_is_valid(uint16_t start, uint16_t end, uint16_t *err)
+{
+	/* Handle 0 is invalid */
+	if (!start || !end) {
+		if (err) {
+			*err = 0U;
+		}
+		return false;
+	}
+
+	/* Check if range is valid */
+	if (start > end) {
+		if (err) {
+			*err = start;
+		}
+		return false;
+	}
+
+	return true;
+}
+
+struct find_info_data {
+	struct bt_att_chan *chan;
+	struct net_buf *buf;
+	struct bt_att_find_info_rsp *rsp;
+	union {
+		struct bt_att_info_16 *info16;
+		struct bt_att_info_128 *info128;
+	};
+};
+
+static uint8_t find_info_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			    void *user_data)
+{
+	struct find_info_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/* Initialize rsp at first entry */
+	if (!data->rsp) {
+		data->rsp = net_buf_add(data->buf, sizeof(*data->rsp));
+		data->rsp->format = (attr->uuid->type == BT_UUID_TYPE_16) ?
+				    BT_ATT_INFO_16 : BT_ATT_INFO_128;
+	}
+
+	switch (data->rsp->format) {
+	case BT_ATT_INFO_16:
+		if (attr->uuid->type != BT_UUID_TYPE_16) {
+			return BT_GATT_ITER_STOP;
+		}
+
+		/* Fast forward to next item position */
+		data->info16 = net_buf_add(data->buf, sizeof(*data->info16));
+		data->info16->handle = sys_cpu_to_le16(handle);
+		data->info16->uuid = sys_cpu_to_le16(BT_UUID_16(attr->uuid)->val);
+
+		if (chan->chan.tx.mtu - data->buf->len >
+		    sizeof(*data->info16)) {
+			return BT_GATT_ITER_CONTINUE;
+		}
+
+		break;
+	case BT_ATT_INFO_128:
+		if (attr->uuid->type != BT_UUID_TYPE_128) {
+			return BT_GATT_ITER_STOP;
+		}
+
+		/* Fast forward to next item position */
+		data->info128 = net_buf_add(data->buf, sizeof(*data->info128));
+		data->info128->handle = sys_cpu_to_le16(handle);
+		memcpy(data->info128->uuid, BT_UUID_128(attr->uuid)->val,
+		       sizeof(data->info128->uuid));
+
+		if (chan->chan.tx.mtu - data->buf->len >
+		    sizeof(*data->info128)) {
+			return BT_GATT_ITER_CONTINUE;
+		}
+	}
+
+	return BT_GATT_ITER_STOP;
+}
+
+static uint8_t att_find_info_rsp(struct bt_att_chan *chan, uint16_t start_handle,
+			      uint16_t end_handle)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct find_info_data data;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_INFO_RSP, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+	bt_gatt_foreach_attr(start_handle, end_handle, find_info_cb, &data);
+
+	if (!data.rsp) {
+		net_buf_unref(data.buf);
+		/* Respond since handle is set */
+		send_err_rsp(chan, BT_ATT_OP_FIND_INFO_REQ, start_handle,
+			     BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+static uint8_t att_find_info_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_find_info_req *req;
+	uint16_t start_handle, end_handle, err_handle;
+
+	req = (void *)buf->data;
+
+	start_handle = sys_le16_to_cpu(req->start_handle);
+	end_handle = sys_le16_to_cpu(req->end_handle);
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x", start_handle,
+	       end_handle);
+
+	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
+		send_err_rsp(chan, BT_ATT_OP_FIND_INFO_REQ, err_handle,
+			     BT_ATT_ERR_INVALID_HANDLE);
+		return 0;
+	}
+
+	return att_find_info_rsp(chan, start_handle, end_handle);
+}
+
+struct find_type_data {
+	struct bt_att_chan *chan;
+	struct net_buf *buf;
+	struct bt_att_handle_group *group;
+	const void *value;
+	uint8_t value_len;
+	uint8_t err;
+};
+
+static uint8_t find_type_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			    void *user_data)
+{
+	struct find_type_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+	struct bt_conn *conn = chan->chan.chan.conn;
+	int read;
+	uint8_t uuid[16];
+	struct net_buf *frag;
+	size_t len;
+
+	/* Skip secondary services */
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
+		goto skip;
+	}
+
+	/* Update group end_handle if not a primary service */
+	if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY)) {
+		if (data->group &&
+		    handle > sys_le16_to_cpu(data->group->end_handle)) {
+			data->group->end_handle = sys_cpu_to_le16(handle);
+		}
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/* stop if there is no space left */
+	if (chan->chan.tx.mtu - net_buf_frags_len(data->buf) <
+	    sizeof(*data->group)) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	frag = net_buf_frag_last(data->buf);
+
+	len = MIN(chan->chan.tx.mtu - net_buf_frags_len(data->buf),
+		  net_buf_tailroom(frag));
+	if (!len) {
+		frag = net_buf_alloc(net_buf_pool_get(data->buf->pool_id),
+				     K_NO_WAIT);
+		/* If not buffer can be allocated immediately stop */
+		if (!frag) {
+			return BT_GATT_ITER_STOP;
+		}
+
+		net_buf_frag_add(data->buf, frag);
+	}
+
+	/* Read attribute value and store in the buffer */
+	read = attr->read(conn, attr, uuid, sizeof(uuid), 0);
+	if (read < 0) {
+		/*
+		 * Since we don't know if it is the service with requested UUID,
+		 * we cannot respond with an error to this request.
+		 */
+		goto skip;
+	}
+
+	/* Check if data matches */
+	if (read != data->value_len) {
+		/* Use bt_uuid_cmp() to compare UUIDs of different form. */
+		struct bt_uuid_128 ref_uuid;
+		struct bt_uuid_128 recvd_uuid;
+
+		if (!bt_uuid_create(&recvd_uuid.uuid, data->value, data->value_len)) {
+			BT_WARN("Unable to create UUID: size %u", data->value_len);
+			goto skip;
+		}
+		if (!bt_uuid_create(&ref_uuid.uuid, uuid, read)) {
+			BT_WARN("Unable to create UUID: size %d", read);
+			goto skip;
+		}
+		if (bt_uuid_cmp(&recvd_uuid.uuid, &ref_uuid.uuid)) {
+			goto skip;
+		}
+	} else if (memcmp(data->value, uuid, read)) {
+		goto skip;
+	}
+
+	/* If service has been found, error should be cleared */
+	data->err = 0x00;
+
+	/* Fast forward to next item position */
+	data->group = net_buf_add(frag, sizeof(*data->group));
+	data->group->start_handle = sys_cpu_to_le16(handle);
+	data->group->end_handle = sys_cpu_to_le16(handle);
+
+	/* continue to find the end_handle */
+	return BT_GATT_ITER_CONTINUE;
+
+skip:
+	data->group = NULL;
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_find_type_rsp(struct bt_att_chan *chan, uint16_t start_handle,
+			      uint16_t end_handle, const void *value,
+			      uint8_t value_len)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct find_type_data data;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_TYPE_RSP, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+	data.group = NULL;
+	data.value = value;
+	data.value_len = value_len;
+
+	/* Pre-set error in case no service will be found */
+	data.err = BT_ATT_ERR_ATTRIBUTE_NOT_FOUND;
+
+	bt_gatt_foreach_attr(start_handle, end_handle, find_type_cb, &data);
+
+	/* If error has not been cleared, no service has been found */
+	if (data.err) {
+		net_buf_unref(data.buf);
+		/* Respond since handle is set */
+		send_err_rsp(chan, BT_ATT_OP_FIND_TYPE_REQ, start_handle,
+			     data.err);
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+static uint8_t att_find_type_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_find_type_req *req;
+	uint16_t start_handle, end_handle, err_handle, type;
+	uint8_t *value;
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+
+	start_handle = sys_le16_to_cpu(req->start_handle);
+	end_handle = sys_le16_to_cpu(req->end_handle);
+	type = sys_le16_to_cpu(req->type);
+	value = buf->data;
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %u", start_handle,
+	       end_handle, type);
+
+	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
+		send_err_rsp(chan, BT_ATT_OP_FIND_TYPE_REQ, err_handle,
+			     BT_ATT_ERR_INVALID_HANDLE);
+		return 0;
+	}
+
+	/* The Attribute Protocol Find By Type Value Request shall be used with
+	 * the Attribute Type parameter set to the UUID for "Primary Service"
+	 * and the Attribute Value set to the 16-bit Bluetooth UUID or 128-bit
+	 * UUID for the specific primary service.
+	 */
+	if (bt_uuid_cmp(BT_UUID_DECLARE_16(type), BT_UUID_GATT_PRIMARY)) {
+		send_err_rsp(chan, BT_ATT_OP_FIND_TYPE_REQ, start_handle,
+			     BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
+		return 0;
+	}
+
+	return att_find_type_rsp(chan, start_handle, end_handle, value,
+				 buf->len);
+}
+
+static uint8_t err_to_att(int err)
+{
+	BT_DBG("%d", err);
+
+	if (err < 0 && err >= -0xff) {
+		return -err;
+	}
+
+	return BT_ATT_ERR_UNLIKELY;
+}
+
+struct read_type_data {
+	struct bt_att_chan *chan;
+	struct bt_uuid *uuid;
+	struct net_buf *buf;
+	struct bt_att_read_type_rsp *rsp;
+	struct bt_att_data *item;
+	uint8_t err;
+};
+
+typedef bool (*attr_read_cb)(struct net_buf *buf, ssize_t read,
+			     void *user_data);
+
+static bool attr_read_type_cb(struct net_buf *frag, ssize_t read,
+			      void *user_data)
+{
+	struct read_type_data *data = user_data;
+
+	if (!data->rsp->len) {
+		/* Set len to be the first item found */
+		data->rsp->len = read + sizeof(*data->item);
+	} else if (data->rsp->len != read + sizeof(*data->item)) {
+		/* All items should have the same size */
+		frag->len -= sizeof(*data->item);
+		data->item = NULL;
+		return false;
+	}
+
+	return true;
+}
+
+static ssize_t att_chan_read(struct bt_att_chan *chan,
+			     const struct bt_gatt_attr *attr,
+			     struct net_buf *buf, uint16_t offset,
+			     attr_read_cb cb, void *user_data)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	ssize_t read;
+	struct net_buf *frag;
+	size_t len, total = 0;
+
+	if (chan->chan.tx.mtu <= net_buf_frags_len(buf)) {
+		return 0;
+	}
+
+	frag = net_buf_frag_last(buf);
+
+	/* Create necessary fragments if MTU is bigger than what a buffer can
+	 * hold.
+	 */
+	do {
+		len = MIN(chan->chan.tx.mtu - net_buf_frags_len(buf),
+			  net_buf_tailroom(frag));
+		if (!len) {
+			frag = net_buf_alloc(net_buf_pool_get(buf->pool_id),
+					     K_NO_WAIT);
+			/* If not buffer can be allocated immediately return */
+			if (!frag) {
+				return total;
+			}
+
+			net_buf_frag_add(buf, frag);
+
+			len = MIN(chan->chan.tx.mtu - net_buf_frags_len(buf),
+				  net_buf_tailroom(frag));
+		}
+
+		read = attr->read(conn, attr, frag->data + frag->len, len,
+				  offset);
+		if (read < 0) {
+			if (total) {
+				return total;
+			}
+
+			return read;
+		}
+
+		if (cb && !cb(frag, read, user_data)) {
+			break;
+		}
+
+		net_buf_add(frag, read);
+		total += read;
+		offset += read;
+	} while (chan->chan.tx.mtu > net_buf_frags_len(buf) && read == len);
+
+	return total;
+}
+
+static uint8_t read_type_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			    void *user_data)
+{
+	struct read_type_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+	struct bt_conn *conn = chan->chan.chan.conn;
+	ssize_t read;
+
+	/* Skip if doesn't match */
+	if (bt_uuid_cmp(attr->uuid, data->uuid)) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/*
+	 * If an attribute in the set of requested attributes would cause an
+	 * Error Response then this attribute cannot be included in a
+	 * Read By Type Response and the attributes before this attribute
+	 * shall be returned
+	 *
+	 * If the first attribute in the set of requested attributes would
+	 * cause an Error Response then no other attributes in the requested
+	 * attributes can be considered.
+	 */
+	data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK);
+	if (data->err) {
+		if (data->rsp->len) {
+			data->err = 0x00;
+		}
+		return BT_GATT_ITER_STOP;
+	}
+
+	/*
+	 * If any attribute is founded in handle range it means that error
+	 * should be changed from pre-set: attr not found error to no error.
+	 */
+	data->err = 0x00;
+
+	/* Fast foward to next item position */
+	data->item = net_buf_add(net_buf_frag_last(data->buf),
+				 sizeof(*data->item));
+	data->item->handle = sys_cpu_to_le16(handle);
+
+	read = att_chan_read(chan, attr, data->buf, 0, attr_read_type_cb, data);
+	if (read < 0) {
+		data->err = err_to_att(read);
+		return BT_GATT_ITER_STOP;
+	}
+
+	if (!data->item) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* continue only if there are still space for more items */
+	return chan->chan.tx.mtu - net_buf_frags_len(data->buf) >
+	       data->rsp->len ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP;
+}
+
+static uint8_t att_read_type_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid,
+			      uint16_t start_handle, uint16_t end_handle)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct read_type_data data;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_TYPE_RSP,
+				     sizeof(*data.rsp));
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+	data.uuid = uuid;
+	data.rsp = net_buf_add(data.buf, sizeof(*data.rsp));
+	data.rsp->len = 0U;
+
+	/* Pre-set error if no attr will be found in handle */
+	data.err = BT_ATT_ERR_ATTRIBUTE_NOT_FOUND;
+
+	bt_gatt_foreach_attr(start_handle, end_handle, read_type_cb, &data);
+
+	if (data.err) {
+		net_buf_unref(data.buf);
+		/* Response here since handle is set */
+		send_err_rsp(chan, BT_ATT_OP_READ_TYPE_REQ, start_handle,
+			     data.err);
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+static uint8_t att_read_type_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_read_type_req *req;
+	uint16_t start_handle, end_handle, err_handle;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+	uint8_t uuid_len = buf->len - sizeof(*req);
+
+	/* Type can only be UUID16 or UUID128 */
+	if (uuid_len != 2 && uuid_len != 16) {
+		return BT_ATT_ERR_INVALID_PDU;
+	}
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+
+	start_handle = sys_le16_to_cpu(req->start_handle);
+	end_handle = sys_le16_to_cpu(req->end_handle);
+	if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %s",
+	       start_handle, end_handle, bt_uuid_str(&u.uuid));
+
+	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
+		send_err_rsp(chan, BT_ATT_OP_READ_TYPE_REQ, err_handle,
+			     BT_ATT_ERR_INVALID_HANDLE);
+		return 0;
+	}
+
+	return att_read_type_rsp(chan, &u.uuid, start_handle, end_handle);
+}
+
+struct read_data {
+	struct bt_att_chan *chan;
+	uint16_t offset;
+	struct net_buf *buf;
+	uint8_t err;
+};
+
+static uint8_t read_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+		       void *user_data)
+{
+	struct read_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+	struct bt_conn *conn = chan->chan.chan.conn;
+	int ret;
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/*
+	 * If any attribute is founded in handle range it means that error
+	 * should be changed from pre-set: invalid handle error to no error.
+	 */
+	data->err = 0x00;
+
+	/* Check attribute permissions */
+	data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK);
+	if (data->err) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Read attribute value and store in the buffer */
+	ret = att_chan_read(chan, attr, data->buf, data->offset, NULL, NULL);
+	if (ret < 0) {
+		data->err = err_to_att(ret);
+		return BT_GATT_ITER_STOP;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_read_rsp(struct bt_att_chan *chan, uint8_t op, uint8_t rsp,
+			 uint16_t handle, uint16_t offset)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct read_data data;
+
+	if (!bt_gatt_change_aware(conn, true)) {
+		return BT_ATT_ERR_DB_OUT_OF_SYNC;
+	}
+
+	if (!handle) {
+		return BT_ATT_ERR_INVALID_HANDLE;
+	}
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, rsp, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+	data.offset = offset;
+
+	/* Pre-set error if no attr will be found in handle */
+	data.err = BT_ATT_ERR_INVALID_HANDLE;
+
+	bt_gatt_foreach_attr(handle, handle, read_cb, &data);
+
+	/* In case of error discard data and respond with an error */
+	if (data.err) {
+		net_buf_unref(data.buf);
+		/* Respond here since handle is set */
+		send_err_rsp(chan, op, handle, data.err);
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+static uint8_t att_read_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_read_req *req;
+	uint16_t handle;
+
+	req = (void *)buf->data;
+
+	handle = sys_le16_to_cpu(req->handle);
+
+	BT_DBG("handle 0x%04x", handle);
+
+	return att_read_rsp(chan, BT_ATT_OP_READ_REQ, BT_ATT_OP_READ_RSP,
+			    handle, 0);
+}
+
+static uint8_t att_read_blob_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_read_blob_req *req;
+	uint16_t handle, offset;
+
+	req = (void *)buf->data;
+
+	handle = sys_le16_to_cpu(req->handle);
+	offset = sys_le16_to_cpu(req->offset);
+
+	BT_DBG("handle 0x%04x offset %u", handle, offset);
+
+	return att_read_rsp(chan, BT_ATT_OP_READ_BLOB_REQ,
+			    BT_ATT_OP_READ_BLOB_RSP, handle, offset);
+}
+
+#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
+static uint8_t att_read_mult_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct read_data data;
+	uint16_t handle;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_RSP, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+
+	while (buf->len >= sizeof(uint16_t)) {
+		handle = net_buf_pull_le16(buf);
+
+		BT_DBG("handle 0x%04x ", handle);
+
+		/* An Error Response shall be sent by the server in response to
+		 * the Read Multiple Request [....] if a read operation is not
+		 * permitted on any of the Characteristic Values.
+		 *
+		 * If handle is not valid then return invalid handle error.
+		 * If handle is found error will be cleared by read_cb.
+		 */
+		data.err = BT_ATT_ERR_INVALID_HANDLE;
+
+		bt_gatt_foreach_attr(handle, handle, read_cb, &data);
+
+		/* Stop reading in case of error */
+		if (data.err) {
+			net_buf_unref(data.buf);
+			/* Respond here since handle is set */
+			send_err_rsp(chan, BT_ATT_OP_READ_MULT_REQ, handle,
+				     data.err);
+			return 0;
+		}
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_EATT)
+static uint8_t read_vl_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	struct read_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct bt_att_read_mult_vl_rsp *rsp;
+	int read;
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/*
+	 * If any attribute is founded in handle range it means that error
+	 * should be changed from pre-set: invalid handle error to no error.
+	 */
+	data->err = 0x00;
+
+	/* Check attribute permissions */
+	data->err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_READ_MASK);
+	if (data->err) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* The Length Value Tuple List may be truncated within the first two
+	 * octets of a tuple due to the size limits of the current ATT_MTU.
+	 */
+	if (chan->chan.tx.mtu - data->buf->len < 2) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	rsp = net_buf_add(data->buf, sizeof(*rsp));
+
+	read = att_chan_read(chan, attr, data->buf, data->offset, NULL, NULL);
+	if (read < 0) {
+		data->err = err_to_att(read);
+		return BT_GATT_ITER_STOP;
+	}
+
+	rsp->len = read;
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_read_mult_vl_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct read_data data;
+	uint16_t handle;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_VL_RSP, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+
+	while (buf->len >= sizeof(uint16_t)) {
+		handle = net_buf_pull_le16(buf);
+
+		BT_DBG("handle 0x%04x ", handle);
+
+		/* If handle is not valid then return invalid handle error.
+		 * If handle is found error will be cleared by read_cb.
+		 */
+		data.err = BT_ATT_ERR_INVALID_HANDLE;
+
+		bt_gatt_foreach_attr(handle, handle, read_vl_cb, &data);
+
+		/* Stop reading in case of error */
+		if (data.err) {
+			net_buf_unref(data.buf);
+			/* Respond here since handle is set */
+			send_err_rsp(chan, BT_ATT_OP_READ_MULT_VL_REQ, handle,
+				     data.err);
+			return 0;
+		}
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
+
+struct read_group_data {
+	struct bt_att_chan *chan;
+	struct bt_uuid *uuid;
+	struct net_buf *buf;
+	struct bt_att_read_group_rsp *rsp;
+	struct bt_att_group_data *group;
+};
+
+static bool attr_read_group_cb(struct net_buf *frag, ssize_t read,
+			       void *user_data)
+{
+	struct read_group_data *data = user_data;
+
+	if (!data->rsp->len) {
+		/* Set len to be the first group found */
+		data->rsp->len = read + sizeof(*data->group);
+	} else if (data->rsp->len != read + sizeof(*data->group)) {
+		/* All groups entries should have the same size */
+		data->buf->len -= sizeof(*data->group);
+		data->group = NULL;
+		return false;
+	}
+
+	return true;
+}
+
+static uint8_t read_group_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			     void *user_data)
+{
+	struct read_group_data *data = user_data;
+	struct bt_att_chan *chan = data->chan;
+	int read;
+
+	/* Update group end_handle if attribute is not a service */
+	if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) &&
+	    bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
+		if (data->group &&
+		    handle > sys_le16_to_cpu(data->group->end_handle)) {
+			data->group->end_handle = sys_cpu_to_le16(handle);
+		}
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	/* If Group Type don't match skip */
+	if (bt_uuid_cmp(attr->uuid, data->uuid)) {
+		data->group = NULL;
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/* Stop if there is no space left */
+	if (data->rsp->len &&
+	    chan->chan.tx.mtu - data->buf->len < data->rsp->len) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Fast forward to next group position */
+	data->group = net_buf_add(data->buf, sizeof(*data->group));
+
+	/* Initialize group handle range */
+	data->group->start_handle = sys_cpu_to_le16(handle);
+	data->group->end_handle = sys_cpu_to_le16(handle);
+
+	/* Read attribute value and store in the buffer */
+	read = att_chan_read(chan, attr, data->buf, 0, attr_read_group_cb,
+			     data);
+	if (read < 0) {
+		/* TODO: Handle read errors */
+		return BT_GATT_ITER_STOP;
+	}
+
+	if (!data->group) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* continue only if there are still space for more items */
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_read_group_rsp(struct bt_att_chan *chan, struct bt_uuid *uuid,
+			       uint16_t start_handle, uint16_t end_handle)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct read_group_data data;
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_GROUP_RSP,
+				     sizeof(*data.rsp));
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	data.chan = chan;
+	data.uuid = uuid;
+	data.rsp = net_buf_add(data.buf, sizeof(*data.rsp));
+	data.rsp->len = 0U;
+	data.group = NULL;
+
+	bt_gatt_foreach_attr(start_handle, end_handle, read_group_cb, &data);
+
+	if (!data.rsp->len) {
+		net_buf_unref(data.buf);
+		/* Respond here since handle is set */
+		send_err_rsp(chan, BT_ATT_OP_READ_GROUP_REQ, start_handle,
+			     BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+
+static uint8_t att_read_group_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_read_group_req *req;
+	uint16_t start_handle, end_handle, err_handle;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+	uint8_t uuid_len = buf->len - sizeof(*req);
+
+	/* Type can only be UUID16 or UUID128 */
+	if (uuid_len != 2 && uuid_len != 16) {
+		return BT_ATT_ERR_INVALID_PDU;
+	}
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+
+	start_handle = sys_le16_to_cpu(req->start_handle);
+	end_handle = sys_le16_to_cpu(req->end_handle);
+
+	if (!bt_uuid_create(&u.uuid, req->uuid, uuid_len)) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %s",
+	       start_handle, end_handle, bt_uuid_str(&u.uuid));
+
+	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
+		send_err_rsp(chan, BT_ATT_OP_READ_GROUP_REQ, err_handle,
+			     BT_ATT_ERR_INVALID_HANDLE);
+		return 0;
+	}
+
+	/* Core v4.2, Vol 3, sec 2.5.3 Attribute Grouping:
+	 * Not all of the grouping attributes can be used in the ATT
+	 * Read By Group Type Request. The "Primary Service" and "Secondary
+	 * Service" grouping types may be used in the Read By Group Type
+	 * Request. The "Characteristic" grouping type shall not be used in
+	 * the ATT Read By Group Type Request.
+	 */
+	if (bt_uuid_cmp(&u.uuid, BT_UUID_GATT_PRIMARY) &&
+	    bt_uuid_cmp(&u.uuid, BT_UUID_GATT_SECONDARY)) {
+		send_err_rsp(chan, BT_ATT_OP_READ_GROUP_REQ, start_handle,
+			     BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE);
+		return 0;
+	}
+
+	return att_read_group_rsp(chan, &u.uuid, start_handle, end_handle);
+}
+
+struct write_data {
+	struct bt_conn *conn;
+	struct net_buf *buf;
+	uint8_t req;
+	const void *value;
+	uint16_t len;
+	uint16_t offset;
+	uint8_t err;
+};
+
+static uint8_t write_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			void *user_data)
+{
+	struct write_data *data = user_data;
+	int write;
+	uint8_t flags = 0U;
+
+	BT_DBG("handle 0x%04x offset %u", handle, data->offset);
+
+	/* Check attribute permissions */
+	data->err = bt_gatt_check_perm(data->conn, attr,
+				       BT_GATT_PERM_WRITE_MASK);
+	if (data->err) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Set command flag if not a request */
+	if (!data->req) {
+		flags |= BT_GATT_WRITE_FLAG_CMD;
+	}
+
+	/* Write attribute value */
+	write = attr->write(data->conn, attr, data->value, data->len,
+			    data->offset, flags);
+	if (write < 0 || write != data->len) {
+		data->err = err_to_att(write);
+		return BT_GATT_ITER_STOP;
+	}
+
+	data->err = 0U;
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_write_rsp(struct bt_att_chan *chan, uint8_t req, uint8_t rsp,
+			  uint16_t handle, uint16_t offset, const void *value,
+			  uint16_t len)
+{
+	struct write_data data;
+
+	if (!bt_gatt_change_aware(chan->att->conn, req ? true : false)) {
+		return BT_ATT_ERR_DB_OUT_OF_SYNC;
+	}
+
+	if (!handle) {
+		return BT_ATT_ERR_INVALID_HANDLE;
+	}
+
+	(void)memset(&data, 0, sizeof(data));
+
+	/* Only allocate buf if required to respond */
+	if (rsp) {
+		data.buf = bt_att_chan_create_pdu(chan, rsp, 0);
+		if (!data.buf) {
+			return BT_ATT_ERR_UNLIKELY;
+		}
+	}
+
+	data.conn = chan->att->conn;
+	data.req = req;
+	data.offset = offset;
+	data.value = value;
+	data.len = len;
+	data.err = BT_ATT_ERR_INVALID_HANDLE;
+
+	bt_gatt_foreach_attr(handle, handle, write_cb, &data);
+
+	if (data.err) {
+		/* In case of error discard data and respond with an error */
+		if (rsp) {
+			net_buf_unref(data.buf);
+			/* Respond here since handle is set */
+			send_err_rsp(chan, req, handle, data.err);
+		}
+		return req == BT_ATT_OP_EXEC_WRITE_REQ ? data.err : 0;
+	}
+
+	if (data.buf) {
+		bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+	}
+
+	return 0;
+}
+
+static uint8_t att_write_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	uint16_t handle;
+
+	handle = net_buf_pull_le16(buf);
+
+	BT_DBG("handle 0x%04x", handle);
+
+	return att_write_rsp(chan, BT_ATT_OP_WRITE_REQ, BT_ATT_OP_WRITE_RSP,
+			     handle, 0, buf->data, buf->len);
+}
+
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+struct prep_data {
+	struct bt_conn *conn;
+	struct net_buf *buf;
+	const void *value;
+	uint16_t len;
+	uint16_t offset;
+	uint8_t err;
+};
+
+static uint8_t prep_write_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			     void *user_data)
+{
+	struct prep_data *data = user_data;
+	struct bt_attr_data *attr_data;
+	int write;
+
+	BT_DBG("handle 0x%04x offset %u", handle, data->offset);
+
+	/* Check attribute permissions */
+	data->err = bt_gatt_check_perm(data->conn, attr,
+				       BT_GATT_PERM_WRITE_MASK);
+	if (data->err) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Check if attribute requires handler to accept the data */
+	if (!(attr->perm & BT_GATT_PERM_PREPARE_WRITE)) {
+		goto append;
+	}
+
+	/* Write attribute value to check if device is authorized */
+	write = attr->write(data->conn, attr, data->value, data->len,
+			    data->offset, BT_GATT_WRITE_FLAG_PREPARE);
+	if (write != 0) {
+		data->err = err_to_att(write);
+		return BT_GATT_ITER_STOP;
+	}
+
+append:
+	/* Copy data into the outstanding queue */
+	data->buf = net_buf_alloc(&prep_pool, K_NO_WAIT);
+	if (!data->buf) {
+		data->err = BT_ATT_ERR_PREPARE_QUEUE_FULL;
+		return BT_GATT_ITER_STOP;
+	}
+
+	attr_data = net_buf_user_data(data->buf);
+	attr_data->handle = handle;
+	attr_data->offset = data->offset;
+
+	net_buf_add_mem(data->buf, data->value, data->len);
+
+	data->err = 0U;
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t att_prep_write_rsp(struct bt_att_chan *chan, uint16_t handle,
+			       uint16_t offset, const void *value, uint8_t len)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct prep_data data;
+	struct bt_att_prepare_write_rsp *rsp;
+
+	if (!bt_gatt_change_aware(conn, true)) {
+		return BT_ATT_ERR_DB_OUT_OF_SYNC;
+	}
+
+	if (!handle) {
+		return BT_ATT_ERR_INVALID_HANDLE;
+	}
+
+	(void)memset(&data, 0, sizeof(data));
+
+	data.conn = conn;
+	data.offset = offset;
+	data.value = value;
+	data.len = len;
+	data.err = BT_ATT_ERR_INVALID_HANDLE;
+
+	bt_gatt_foreach_attr(handle, handle, prep_write_cb, &data);
+
+	if (data.err) {
+		/* Respond here since handle is set */
+		send_err_rsp(chan, BT_ATT_OP_PREPARE_WRITE_REQ, handle,
+			     data.err);
+		return 0;
+	}
+
+	BT_DBG("buf %p handle 0x%04x offset %u", data.buf, handle, offset);
+
+	/* Store buffer in the outstanding queue */
+	net_buf_put(&chan->att->prep_queue, data.buf);
+
+	/* Generate response */
+	data.buf = bt_att_create_pdu(conn, BT_ATT_OP_PREPARE_WRITE_RSP, 0);
+	if (!data.buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	rsp = net_buf_add(data.buf, sizeof(*rsp));
+	rsp->handle = sys_cpu_to_le16(handle);
+	rsp->offset = sys_cpu_to_le16(offset);
+	net_buf_add(data.buf, len);
+	memcpy(rsp->value, value, len);
+
+	bt_att_chan_send_rsp(chan, data.buf, chan_rsp_sent);
+
+	return 0;
+}
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
+
+static uint8_t att_prepare_write_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+#if CONFIG_BT_ATT_PREPARE_COUNT == 0
+	return BT_ATT_ERR_NOT_SUPPORTED;
+#else
+	struct bt_att_prepare_write_req *req;
+	uint16_t handle, offset;
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+
+	handle = sys_le16_to_cpu(req->handle);
+	offset = sys_le16_to_cpu(req->offset);
+
+	BT_DBG("handle 0x%04x offset %u", handle, offset);
+
+	return att_prep_write_rsp(chan, handle, offset, buf->data, buf->len);
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
+}
+
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+static uint8_t att_exec_write_rsp(struct bt_att_chan *chan, uint8_t flags)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct net_buf *buf;
+	uint8_t err = 0U;
+
+	while ((buf = net_buf_get(&chan->att->prep_queue, K_NO_WAIT))) {
+		struct bt_attr_data *data = net_buf_user_data(buf);
+
+		BT_DBG("buf %p handle 0x%04x offset %u", buf, data->handle,
+		       data->offset);
+
+		/* Just discard the data if an error was set */
+		if (!err && flags == BT_ATT_FLAG_EXEC) {
+			err = att_write_rsp(chan, BT_ATT_OP_EXEC_WRITE_REQ, 0,
+					    data->handle, data->offset,
+					    buf->data, buf->len);
+			if (err) {
+				/* Respond here since handle is set */
+				send_err_rsp(chan, BT_ATT_OP_EXEC_WRITE_REQ,
+					     data->handle, err);
+			}
+		}
+
+		net_buf_unref(buf);
+	}
+
+	if (err) {
+		return 0;
+	}
+
+	/* Generate response */
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_EXEC_WRITE_RSP, 0);
+	if (!buf) {
+		return BT_ATT_ERR_UNLIKELY;
+	}
+
+	bt_att_chan_send_rsp(chan, buf, chan_rsp_sent);
+
+	return 0;
+}
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
+
+
+static uint8_t att_exec_write_req(struct bt_att_chan *chan, struct net_buf *buf)
+{
+#if CONFIG_BT_ATT_PREPARE_COUNT == 0
+	return BT_ATT_ERR_NOT_SUPPORTED;
+#else
+	struct bt_att_exec_write_req *req;
+
+	req = (void *)buf->data;
+
+	BT_DBG("flags 0x%02x", req->flags);
+
+	return att_exec_write_rsp(chan, req->flags);
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT */
+}
+
+static uint8_t att_write_cmd(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	uint16_t handle;
+
+	handle = net_buf_pull_le16(buf);
+
+	BT_DBG("handle 0x%04x", handle);
+
+	return att_write_rsp(chan, 0, 0, handle, 0, buf->data, buf->len);
+}
+
+#if defined(CONFIG_BT_SIGNING)
+static uint8_t att_signed_write_cmd(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_conn *conn = chan->chan.chan.conn;
+	struct bt_att_signed_write_cmd *req;
+	uint16_t handle;
+	int err;
+
+	req = (void *)buf->data;
+
+	handle = sys_le16_to_cpu(req->handle);
+
+	BT_DBG("handle 0x%04x", handle);
+
+	/* Verifying data requires full buffer including attribute header */
+	net_buf_push(buf, sizeof(struct bt_att_hdr));
+	//err = bt_smp_sign_verify(conn, buf);
+	if (err) {
+		BT_ERR("Error verifying data");
+		/* No response for this command */
+		return 0;
+	}
+
+	net_buf_pull(buf, sizeof(struct bt_att_hdr));
+	net_buf_pull(buf, sizeof(*req));
+
+	return att_write_rsp(chan, 0, 0, handle, 0, buf->data,
+			     buf->len - sizeof(struct bt_att_signature));
+}
+#endif /* CONFIG_BT_SIGNING */
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+#if defined(CONFIG_BT_SMP)
+static int att_change_security(struct bt_conn *conn, uint8_t err)
+{
+	bt_security_t sec;
+
+	switch (err) {
+	case BT_ATT_ERR_INSUFFICIENT_ENCRYPTION:
+		if (conn->sec_level >= BT_SECURITY_L2)
+			return -EALREADY;
+		sec = BT_SECURITY_L2;
+		break;
+	case BT_ATT_ERR_AUTHENTICATION:
+		if (conn->sec_level < BT_SECURITY_L2) {
+			/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C]
+			 * page 375:
+			 *
+			 * If an LTK is not available, the service request
+			 * shall be rejected with the error code 'Insufficient
+			 * Authentication'.
+			 * Note: When the link is not encrypted, the error code
+			 * "Insufficient Authentication" does not indicate that
+			 * MITM protection is required.
+			 */
+			sec = BT_SECURITY_L2;
+		} else if (conn->sec_level < BT_SECURITY_L3) {
+			/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C]
+			 * page 375:
+			 *
+			 * If an authenticated pairing is required but only an
+			 * unauthenticated pairing has occurred and the link is
+			 * currently encrypted, the service request shall be
+			 * rejected with the error code 'Insufficient
+			 * Authentication'.
+			 * Note: When unauthenticated pairing has occurred and
+			 * the link is currently encrypted, the error code
+			 * 'Insufficient Authentication' indicates that MITM
+			 * protection is required.
+			 */
+			sec = BT_SECURITY_L3;
+		} else if (conn->sec_level < BT_SECURITY_L4) {
+			/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part C]
+			 * page 375:
+			 *
+			 * If LE Secure Connections authenticated pairing is
+			 * required but LE legacy pairing has occurred and the
+			 * link is currently encrypted, the service request
+			 * shall be rejected with the error code ''Insufficient
+			 * Authentication'.
+			 */
+			sec = BT_SECURITY_L4;
+		} else {
+			return -EALREADY;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return bt_conn_set_security(conn, sec);
+}
+#endif /* CONFIG_BT_SMP */
+
+static uint8_t att_error_rsp(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_error_rsp *rsp;
+	uint8_t err;
+
+	rsp = (void *)buf->data;
+
+	BT_DBG("request 0x%02x handle 0x%04x error 0x%02x", rsp->request,
+	       sys_le16_to_cpu(rsp->handle), rsp->error);
+
+	/* Don't retry if there is no req pending or it has been cancelled */
+	if (!chan->req || chan->req == &cancel) {
+		err = BT_ATT_ERR_UNLIKELY;
+		goto done;
+	}
+
+	if (chan->req->buf) {
+		/* Restore state to be resent */
+		net_buf_simple_restore(&chan->req->buf->b, &chan->req->state);
+	}
+
+	err = rsp->error;
+#if defined(CONFIG_BT_SMP)
+	if (chan->req->retrying) {
+		goto done;
+	}
+
+	/* Check if security needs to be changed */
+	if (!att_change_security(chan->chan.chan.conn, err)) {
+		chan->req->retrying = true;
+		/* Wait security_changed: TODO: Handle fail case */
+		return 0;
+	}
+#endif /* CONFIG_BT_SMP */
+
+done:
+	return att_handle_rsp(chan, NULL, 0, err);
+}
+
+static uint8_t att_handle_find_info_rsp(struct bt_att_chan *chan,
+				     struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_find_type_rsp(struct bt_att_chan *chan,
+				     struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_read_type_rsp(struct bt_att_chan *chan,
+				     struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_read_rsp(struct bt_att_chan *chan,
+				struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_read_blob_rsp(struct bt_att_chan *chan,
+				     struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
+static uint8_t att_handle_read_mult_rsp(struct bt_att_chan *chan,
+				     struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+#if defined(CONFIG_BT_EATT)
+static uint8_t att_handle_read_mult_vl_rsp(struct bt_att_chan *chan,
+					struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
+
+static uint8_t att_handle_read_group_rsp(struct bt_att_chan *chan,
+				      struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_write_rsp(struct bt_att_chan *chan,
+				 struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_prepare_write_rsp(struct bt_att_chan *chan,
+					 struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_handle_exec_write_rsp(struct bt_att_chan *chan,
+				      struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static uint8_t att_notify(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	uint16_t handle;
+
+	handle = net_buf_pull_le16(buf);
+
+	BT_DBG("chan %p handle 0x%04x", chan, handle);
+
+	bt_gatt_notification(chan->att->conn, handle, buf->data, buf->len);
+
+	return 0;
+}
+
+static uint8_t att_indicate(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	uint16_t handle;
+
+	handle = net_buf_pull_le16(buf);
+
+	BT_DBG("chan %p handle 0x%04x", chan, handle);
+
+	bt_gatt_notification(chan->att->conn, handle, buf->data, buf->len);
+
+	buf = bt_att_chan_create_pdu(chan, BT_ATT_OP_CONFIRM, 0);
+	if (!buf) {
+		return 0;
+	}
+
+	bt_att_chan_send_rsp(chan, buf, chan_cfm_sent);
+
+	return 0;
+}
+
+static uint8_t att_notify_mult(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	BT_DBG("chan %p", chan);
+
+	bt_gatt_mult_notification(chan->att->conn, buf->data, buf->len);
+
+	return 0;
+}
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+static uint8_t att_confirm(struct bt_att_chan *chan, struct net_buf *buf)
+{
+	BT_DBG("");
+
+	return att_handle_rsp(chan, buf->data, buf->len, 0);
+}
+
+static const struct att_handler {
+	uint8_t       op;
+	uint8_t       expect_len;
+	att_type_t type;
+	uint8_t       (*func)(struct bt_att_chan *chan, struct net_buf *buf);
+} handlers[] = {
+	{ BT_ATT_OP_MTU_REQ,
+		sizeof(struct bt_att_exchange_mtu_req),
+		ATT_REQUEST,
+		att_mtu_req },
+	{ BT_ATT_OP_FIND_INFO_REQ,
+		sizeof(struct bt_att_find_info_req),
+		ATT_REQUEST,
+		att_find_info_req },
+	{ BT_ATT_OP_FIND_TYPE_REQ,
+		sizeof(struct bt_att_find_type_req),
+		ATT_REQUEST,
+		att_find_type_req },
+	{ BT_ATT_OP_READ_TYPE_REQ,
+		sizeof(struct bt_att_read_type_req),
+		ATT_REQUEST,
+		att_read_type_req },
+	{ BT_ATT_OP_READ_REQ,
+		sizeof(struct bt_att_read_req),
+		ATT_REQUEST,
+		att_read_req },
+	{ BT_ATT_OP_READ_BLOB_REQ,
+		sizeof(struct bt_att_read_blob_req),
+		ATT_REQUEST,
+		att_read_blob_req },
+#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
+	{ BT_ATT_OP_READ_MULT_REQ,
+		BT_ATT_READ_MULT_MIN_LEN_REQ,
+		ATT_REQUEST,
+		att_read_mult_req },
+#if defined(CONFIG_BT_EATT)
+	{ BT_ATT_OP_READ_MULT_VL_REQ,
+		BT_ATT_READ_MULT_MIN_LEN_REQ,
+		ATT_REQUEST,
+		att_read_mult_vl_req },
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
+	{ BT_ATT_OP_READ_GROUP_REQ,
+		sizeof(struct bt_att_read_group_req),
+		ATT_REQUEST,
+		att_read_group_req },
+	{ BT_ATT_OP_WRITE_REQ,
+		sizeof(struct bt_att_write_req),
+		ATT_REQUEST,
+		att_write_req },
+	{ BT_ATT_OP_PREPARE_WRITE_REQ,
+		sizeof(struct bt_att_prepare_write_req),
+		ATT_REQUEST,
+		att_prepare_write_req },
+	{ BT_ATT_OP_EXEC_WRITE_REQ,
+		sizeof(struct bt_att_exec_write_req),
+		ATT_REQUEST,
+		att_exec_write_req },
+	{ BT_ATT_OP_CONFIRM,
+		0,
+		ATT_CONFIRMATION,
+		att_confirm },
+	{ BT_ATT_OP_WRITE_CMD,
+		sizeof(struct bt_att_write_cmd),
+		ATT_COMMAND,
+		att_write_cmd },
+#if defined(CONFIG_BT_SIGNING)
+	{ BT_ATT_OP_SIGNED_WRITE_CMD,
+		(sizeof(struct bt_att_write_cmd) +
+		 sizeof(struct bt_att_signature)),
+		ATT_COMMAND,
+		att_signed_write_cmd },
+#endif /* CONFIG_BT_SIGNING */
+#if defined(CONFIG_BT_GATT_CLIENT)
+	{ BT_ATT_OP_ERROR_RSP,
+		sizeof(struct bt_att_error_rsp),
+		ATT_RESPONSE,
+		att_error_rsp },
+	{ BT_ATT_OP_MTU_RSP,
+		sizeof(struct bt_att_exchange_mtu_rsp),
+		ATT_RESPONSE,
+		att_mtu_rsp },
+	{ BT_ATT_OP_FIND_INFO_RSP,
+		sizeof(struct bt_att_find_info_rsp),
+		ATT_RESPONSE,
+		att_handle_find_info_rsp },
+	{ BT_ATT_OP_FIND_TYPE_RSP,
+		sizeof(struct bt_att_handle_group),
+		ATT_RESPONSE,
+		att_handle_find_type_rsp },
+	{ BT_ATT_OP_READ_TYPE_RSP,
+		sizeof(struct bt_att_read_type_rsp),
+		ATT_RESPONSE,
+		att_handle_read_type_rsp },
+	{ BT_ATT_OP_READ_RSP,
+		0,
+		ATT_RESPONSE,
+		att_handle_read_rsp },
+	{ BT_ATT_OP_READ_BLOB_RSP,
+		0,
+		ATT_RESPONSE,
+		att_handle_read_blob_rsp },
+#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
+	{ BT_ATT_OP_READ_MULT_RSP,
+		0,
+		ATT_RESPONSE,
+		att_handle_read_mult_rsp },
+#if defined(CONFIG_BT_EATT)
+	{ BT_ATT_OP_READ_MULT_VL_RSP,
+		sizeof(struct bt_att_read_mult_vl_rsp),
+		ATT_RESPONSE,
+		att_handle_read_mult_vl_rsp },
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
+	{ BT_ATT_OP_READ_GROUP_RSP,
+		sizeof(struct bt_att_read_group_rsp),
+		ATT_RESPONSE,
+		att_handle_read_group_rsp },
+	{ BT_ATT_OP_WRITE_RSP,
+		0,
+		ATT_RESPONSE,
+		att_handle_write_rsp },
+	{ BT_ATT_OP_PREPARE_WRITE_RSP,
+		sizeof(struct bt_att_prepare_write_rsp),
+		ATT_RESPONSE,
+		att_handle_prepare_write_rsp },
+	{ BT_ATT_OP_EXEC_WRITE_RSP,
+		0,
+		ATT_RESPONSE,
+		att_handle_exec_write_rsp },
+	{ BT_ATT_OP_NOTIFY,
+		sizeof(struct bt_att_notify),
+		ATT_NOTIFICATION,
+		att_notify },
+	{ BT_ATT_OP_INDICATE,
+		sizeof(struct bt_att_indicate),
+		ATT_INDICATION,
+		att_indicate },
+	{ BT_ATT_OP_NOTIFY_MULT,
+		sizeof(struct bt_att_notify_mult),
+		ATT_NOTIFICATION,
+		att_notify_mult },
+#endif /* CONFIG_BT_GATT_CLIENT */
+};
+
+static att_type_t att_op_get_type(uint8_t op)
+{
+	switch (op) {
+	case BT_ATT_OP_MTU_REQ:
+	case BT_ATT_OP_FIND_INFO_REQ:
+	case BT_ATT_OP_FIND_TYPE_REQ:
+	case BT_ATT_OP_READ_TYPE_REQ:
+	case BT_ATT_OP_READ_REQ:
+	case BT_ATT_OP_READ_BLOB_REQ:
+	case BT_ATT_OP_READ_MULT_REQ:
+	case BT_ATT_OP_READ_GROUP_REQ:
+	case BT_ATT_OP_WRITE_REQ:
+	case BT_ATT_OP_PREPARE_WRITE_REQ:
+	case BT_ATT_OP_EXEC_WRITE_REQ:
+		return ATT_REQUEST;
+	case BT_ATT_OP_CONFIRM:
+		return ATT_CONFIRMATION;
+	case BT_ATT_OP_WRITE_CMD:
+	case BT_ATT_OP_SIGNED_WRITE_CMD:
+		return ATT_COMMAND;
+	case BT_ATT_OP_ERROR_RSP:
+	case BT_ATT_OP_MTU_RSP:
+	case BT_ATT_OP_FIND_INFO_RSP:
+	case BT_ATT_OP_FIND_TYPE_RSP:
+	case BT_ATT_OP_READ_TYPE_RSP:
+	case BT_ATT_OP_READ_RSP:
+	case BT_ATT_OP_READ_BLOB_RSP:
+	case BT_ATT_OP_READ_MULT_RSP:
+	case BT_ATT_OP_READ_GROUP_RSP:
+	case BT_ATT_OP_WRITE_RSP:
+	case BT_ATT_OP_PREPARE_WRITE_RSP:
+	case BT_ATT_OP_EXEC_WRITE_RSP:
+		return ATT_RESPONSE;
+	case BT_ATT_OP_NOTIFY:
+		return ATT_NOTIFICATION;
+	case BT_ATT_OP_INDICATE:
+		return ATT_INDICATION;
+	}
+
+	if (op & ATT_CMD_MASK) {
+		return ATT_COMMAND;
+	}
+
+	return ATT_UNKNOWN;
+}
+
+static int bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_att_chan *att_chan = ATT_CHAN(chan);
+	struct bt_att_hdr *hdr;
+	const struct att_handler *handler;
+	uint8_t err;
+	size_t i;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small ATT PDU received");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	BT_DBG("Received ATT chan %p code 0x%02x len %zu", att_chan, hdr->code,
+	       net_buf_frags_len(buf));
+
+	for (i = 0, handler = NULL; i < ARRAY_SIZE(handlers); i++) {
+		if (hdr->code == handlers[i].op) {
+			handler = &handlers[i];
+			break;
+		}
+	}
+
+	if (!handler) {
+		BT_WARN("Unhandled ATT code 0x%02x", hdr->code);
+		if (att_op_get_type(hdr->code) != ATT_COMMAND) {
+			send_err_rsp(att_chan, hdr->code, 0,
+				     BT_ATT_ERR_NOT_SUPPORTED);
+		}
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_ATT_ENFORCE_FLOW)) {
+		if (handler->type == ATT_REQUEST &&
+		    atomic_test_and_set_bit(att_chan->flags, ATT_PENDING_RSP)) {
+			BT_WARN("Ignoring unexpected request");
+			return 0;
+		} else if (handler->type == ATT_INDICATION &&
+			   atomic_test_and_set_bit(att_chan->flags,
+						   ATT_PENDING_CFM)) {
+			BT_WARN("Ignoring unexpected indication");
+			return 0;
+		}
+	}
+
+	if (buf->len < handler->expect_len) {
+		BT_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code);
+		err = BT_ATT_ERR_INVALID_PDU;
+	} else {
+		err = handler->func(att_chan, buf);
+	}
+
+	if (handler->type == ATT_REQUEST && err) {
+		BT_DBG("ATT error 0x%02x", err);
+		send_err_rsp(att_chan, hdr->code, 0, err);
+	}
+
+	return 0;
+}
+
+static struct bt_att *att_get(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+	struct bt_att_chan *att_chan;
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		BT_WARN("Not connected");
+		return NULL;
+	}
+
+	chan = bt_l2cap_le_lookup_rx_cid(conn, BT_L2CAP_CID_ATT);
+	if (!chan) {
+		BT_ERR("Unable to find ATT channel");
+		return NULL;
+	}
+
+	att_chan = ATT_CHAN(chan);
+	if (atomic_test_bit(att_chan->flags, ATT_DISCONNECTED)) {
+		BT_WARN("ATT channel flagged as disconnected");
+		return NULL;
+	}
+
+	return att_chan->att;
+}
+
+struct net_buf *bt_att_create_pdu(struct bt_conn *conn, uint8_t op, size_t len)
+{
+	struct bt_att *att;
+	struct bt_att_chan *chan, *tmp;
+
+	att = att_get(conn);
+	if (!att) {
+		return NULL;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		if (len + sizeof(op) > chan->chan.tx.mtu) {
+			continue;
+		}
+
+		return bt_att_chan_create_pdu(chan, op, len);
+	}
+
+	BT_WARN("No ATT channel for MTU %zu", len + sizeof(op));
+
+	return NULL;
+}
+
+static void att_reset(struct bt_att *att)
+{
+	struct bt_att_req *req, *tmp;
+	struct net_buf *buf;
+
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+	/* Discard queued buffers */
+	while ((buf = net_buf_get(&att->prep_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+#endif /* CONFIG_BT_ATT_PREPARE_COUNT > 0 */
+
+	while ((buf = net_buf_get(&att->tx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	att->conn = NULL;
+
+	/* Notify pending requests */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->reqs, req, tmp, node) {
+		if (req->func) {
+			req->func(NULL, BT_ATT_ERR_UNLIKELY, NULL, 0,
+				  req->user_data);
+		}
+
+		att_req_destroy(req);
+	}
+
+	k_mem_slab_free(&att_slab, (void **)&att);
+}
+
+static void att_chan_detach(struct bt_att_chan *chan)
+{
+	struct net_buf *buf;
+	int i;
+
+	BT_DBG("chan %p", chan);
+
+	sys_slist_find_and_remove(&chan->att->chans, &chan->node);
+
+	/* Ensure that any waiters are woken up */
+	//for (i = 0; i < CONFIG_BT_ATT_TX_MAX; i++) {
+	//	k_sem_give(&chan->tx_sem);
+	//}
+
+	/* Release pending buffers */
+	while ((buf = net_buf_get(&chan->tx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	if (chan->req) {
+		/* Notify outstanding request */
+		att_handle_rsp(chan, NULL, 0, BT_ATT_ERR_UNLIKELY);
+	}
+
+	chan->att = NULL;
+}
+
+static void att_timeout(struct k_work *work)
+{
+	struct bt_att_chan *chan = NULL;//CONTAINER_OF(work, struct bt_att_chan,
+						//timeout_work);
+	struct bt_att *att = chan->att;
+	struct bt_l2cap_le_chan *ch = &chan->chan;
+
+	BT_ERR("ATT Timeout");
+
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part F] page 480:
+	 *
+	 * A transaction not completed within 30 seconds shall time out. Such a
+	 * transaction shall be considered to have failed and the local higher
+	 * layers shall be informed of this failure. No more attribute protocol
+	 * requests, commands, indications or notifications shall be sent to the
+	 * target device on this ATT Bearer.
+	 */
+	att_chan_detach(chan);
+
+	/* Don't notify if there are still channels to be used */
+	if (!sys_slist_is_empty(&att->chans)) {
+		return;
+	}
+
+	att_reset(att);
+
+	/* Consider the channel disconnected */
+	bt_gatt_disconnected(ch->chan.conn);
+	ch->chan.conn = NULL;
+}
+
+static struct bt_att_chan *att_get_fixed_chan(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+
+	chan = bt_l2cap_le_lookup_tx_cid(conn, BT_L2CAP_CID_ATT);
+	__ASSERT(chan, "No ATT channel found");
+
+	return ATT_CHAN(chan);
+}
+
+static void att_chan_attach(struct bt_att *att, struct bt_att_chan *chan)
+{
+	BT_DBG("att_chan_attach att %p chan %p flags %u", att, chan, atomic_get(chan->flags));
+
+	if (sys_slist_is_empty(&att->chans)) {
+		/* Init general queues when attaching the first channel */
+		k_fifo_init(&att->tx_queue);
+#if CONFIG_BT_ATT_PREPARE_COUNT > 0
+		k_fifo_init(&att->prep_queue);
+#endif
+	}
+
+	sys_slist_prepend(&att->chans, &chan->node);
+}
+
+static void bt_att_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_att_chan *att_chan = att_get_fixed_chan(chan->conn);
+	struct bt_att *att = att_chan->att;
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+
+	BT_DBG("bt_att_connected chan %p cid 0x%04x", ch, ch->tx.cid);
+
+	att_chan = ATT_CHAN(chan);
+
+	att_chan_attach(att, att_chan);
+
+	if (!atomic_test_bit(att_chan->flags, ATT_ENHANCED)) {
+		ch->tx.mtu = BT_ATT_DEFAULT_LE_MTU;
+		ch->rx.mtu = BT_ATT_DEFAULT_LE_MTU;
+	}
+
+	//k_delayed_work_init(&att_chan->timeout_work, att_timeout);
+}
+
+static void bt_att_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_att_chan *att_chan = ATT_CHAN(chan);
+	struct bt_att *att = att_chan->att;
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+
+	BT_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
+
+	att_chan_detach(att_chan);
+
+	/* Don't reset if there are still channels to be used */
+	if (!sys_slist_is_empty(&att->chans)) {
+		return;
+	}
+
+	att_reset(att);
+
+	bt_gatt_disconnected(ch->chan.conn);
+}
+
+#if defined(CONFIG_BT_SMP)
+static void bt_att_encrypt_change(struct bt_l2cap_chan *chan,
+				  uint8_t hci_status)
+{
+	struct bt_att_chan *att_chan = ATT_CHAN(chan);
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	struct bt_conn *conn = ch->chan.conn;
+
+	BT_DBG("chan %p conn %p handle %u sec_level 0x%02x status 0x%02x", ch,
+	       conn, conn->handle, conn->sec_level, hci_status);
+
+	/*
+	 * If status (HCI status of security procedure) is non-zero, notify
+	 * outstanding request about security failure.
+	 */
+	if (hci_status) {
+		if (att_chan->req) {
+			att_handle_rsp(att_chan, NULL, 0,
+				       BT_ATT_ERR_AUTHENTICATION);
+		}
+
+		return;
+	}
+
+	bt_gatt_encrypt_change(conn);
+
+	if (conn->sec_level == BT_SECURITY_L1) {
+		return;
+	}
+
+	if (!att_chan->req || !att_chan->req->retrying) {
+		return;
+	}
+
+	BT_DBG("Retrying");
+
+	/* Resend buffer */
+	bt_att_chan_send_rsp(att_chan, att_chan->req->buf,
+			     chan_cb(att_chan->req->buf));
+
+	att_chan->req->buf = NULL;
+}
+#endif /* CONFIG_BT_SMP */
+
+static void bt_att_status(struct bt_l2cap_chan *ch, atomic_t *status)
+{
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+	sys_snode_t *node;
+
+	BT_DBG("chan %p status %p", ch, status);
+
+	if (!atomic_test_bit(status, BT_L2CAP_STATUS_OUT)) {
+		return;
+	}
+
+	/* If there is a request pending don't attempt to send */
+	if (chan->req) {
+		return;
+	}
+
+	/* Pull next request from the list */
+	node = sys_slist_get(&chan->att->reqs);
+	if (!node) {
+		return;
+	}
+
+	if (bt_att_chan_req_send(chan, ATT_REQ(node)) >= 0) {
+		return;
+	}
+
+	/* Prepend back to the list as it could not be sent */
+	sys_slist_prepend(&chan->att->reqs, node);
+}
+
+static void bt_att_released(struct bt_l2cap_chan *ch)
+{
+	struct bt_att_chan *chan = ATT_CHAN(ch);
+
+	BT_DBG("chan %p", chan);
+
+	k_mem_slab_free(&chan_slab, (void **)&chan);
+}
+
+static struct bt_att_chan *att_chan_new(struct bt_att *att, atomic_val_t flags)
+{
+	int quota = 0;
+	static struct bt_l2cap_chan_ops ops = {
+		.connected = bt_att_connected,
+		.disconnected = bt_att_disconnected,
+		.recv = bt_att_recv,
+		.sent = bt_att_sent,
+		.status = bt_att_status,
+	#if defined(CONFIG_BT_SMP)
+		.encrypt_change = bt_att_encrypt_change,
+	#endif /* CONFIG_BT_SMP */
+		.released = bt_att_released,
+	};
+	struct bt_att_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) {
+		if (chan->att == att) {
+			quota++;
+		}
+
+		if (quota == ATT_CHAN_MAX) {
+			BT_ERR("Maximum number of channels reached: %d", quota);
+			return NULL;
+		}
+	}
+
+	if (k_mem_slab_alloc(&chan_slab, (void **)&chan, K_NO_WAIT)) {
+		BT_ERR("No available ATT channel for conn %p", att->conn);
+		return NULL;
+	}
+
+	(void)memset(chan, 0, sizeof(*chan));
+	chan->chan.chan.ops = &ops;
+	k_fifo_init(&chan->tx_queue);
+	//k_sem_init(&chan->tx_sem, CONFIG_BT_ATT_TX_MAX, CONFIG_BT_ATT_TX_MAX);
+	atomic_set(chan->flags, flags);
+	chan->att = att;
+
+	return chan;
+}
+
+int bt_att_accept(struct bt_conn *conn, struct bt_l2cap_chan **ch)
+{
+	struct bt_att *att;
+	struct bt_att_chan *chan;
+
+	BT_DBG("bt_att_accept conn %p handle %u", conn, conn->handle);
+
+	if (k_mem_slab_alloc(&att_slab, (void **)&att, K_NO_WAIT)) {
+		BT_ERR("No available ATT context for conn %p", conn);
+		return -ENOMEM;
+	}
+
+	(void)memset(att, 0, sizeof(*att));
+	att->conn = conn;
+	sys_slist_init(&att->reqs);
+	sys_slist_init(&att->chans);
+
+	chan = att_chan_new(att, 0);
+	if (!chan) {
+		return -ENOMEM;
+	}
+
+	*ch = &chan->chan.chan;
+
+	return 0;
+}
+
+BT_L2CAP_CHANNEL_DEFINE(att_fixed_chan, BT_L2CAP_CID_ATT, bt_att_accept, NULL);
+
+#if defined(CONFIG_BT_EATT)
+int bt_eatt_connect(struct bt_conn *conn, uint8_t num_channels)
+{
+	struct bt_att_chan *att_chan = att_get_fixed_chan(conn);
+	struct bt_att *att = att_chan->att;
+	struct bt_l2cap_chan *chan[CONFIG_BT_EATT_MAX] = {};
+	int i = 0;
+
+	if (num_channels > CONFIG_BT_EATT_MAX) {
+		return -EINVAL;
+	}
+
+	while (num_channels--) {
+		att_chan = att_chan_new(att, BIT(ATT_ENHANCED));
+		if (!att_chan) {
+			break;
+		}
+
+		chan[i] = &att_chan->chan.chan;
+		i++;
+	}
+
+	if (!i) {
+		return -ENOMEM;
+	}
+
+	return bt_l2cap_ecred_chan_connect(conn, chan, BT_EATT_PSM);
+}
+
+int bt_eatt_disconnect(struct bt_conn *conn)
+{
+	struct bt_att_chan *chan = att_get_fixed_chan(conn);
+	struct bt_att *att = chan->att;
+	int err = -ENOTCONN;
+
+	if (!conn) {
+		return -EINVAL;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&att->chans, chan, node) {
+		if (atomic_test_bit(chan->flags, ATT_ENHANCED)) {
+			err = bt_l2cap_chan_disconnect(&chan->chan.chan);
+		}
+	}
+
+	return err;
+}
+
+#endif /* CONFIG_BT_EATT */
+
+static int bt_eatt_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	struct bt_att_chan *att_chan = att_get_fixed_chan(conn);
+	struct bt_att *att = att_chan->att;
+
+	BT_DBG("conn %p handle %u", conn, conn->handle);
+
+	att_chan = att_chan_new(att, BIT(ATT_ENHANCED));
+	if (att_chan) {
+		*chan = &att_chan->chan.chan;
+		return 0;
+	}
+
+	return -ENOMEM;
+}
+
+static void bt_eatt_init(void)
+{
+	int err;
+	static struct bt_l2cap_server eatt_l2cap = {
+		.psm = BT_EATT_PSM,
+#if defined(CONFIG_BT_EATT_SEC_LEVEL)
+		.sec_level = CONFIG_BT_EATT_SEC_LEVEL,
+#endif
+		.accept = bt_eatt_accept,
+	};
+
+	BT_DBG("");
+
+	//err = bt_l2cap_server_register(&eatt_l2cap);
+	if (err < 0) {
+		BT_ERR("EATT Server registration failed %d", err);
+	}
+}
+
+void bt_att_init(void)
+{
+    create_free_list(&att_slab);
+    create_free_list(&chan_slab);
+    create_free_list(&req_slab);
+
+	bt_gatt_init();
+
+	if (IS_ENABLED(CONFIG_BT_EATT)) {
+		bt_eatt_init();
+	}
+}
+
+uint16_t bt_att_get_mtu(struct bt_conn *conn)
+{
+	struct bt_att_chan *chan, *tmp;
+	struct bt_att *att;
+	uint16_t mtu = 0;
+
+	att = att_get(conn);
+	if (!att) {
+		return 0;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		if (chan->chan.tx.mtu > mtu) {
+			mtu = chan->chan.tx.mtu;
+		}
+	}
+
+	return mtu;
+}
+
+struct bt_att_req *bt_att_req_alloc(k_timeout_t timeout)
+{
+	struct bt_att_req *req = NULL;
+
+	/* Reserve space for request */
+	if (k_mem_slab_alloc(&req_slab, (void **)&req, timeout)) {
+		return NULL;
+	}
+
+	BT_DBG("bt_att_req_alloc, req %p", req);
+
+	memset(req, 0, sizeof(*req));
+
+	return req;
+}
+
+void bt_att_req_free(struct bt_att_req *req)
+{
+	BT_DBG("bt_att_req_free, req %p", req);
+
+	k_mem_slab_free(&req_slab, (void **)&req);
+}
+
+int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
+		void *user_data)
+{
+	struct bt_att_chan *chan, *tmp;
+	struct bt_att *att;
+	int ret;
+
+	__ASSERT_NO_MSG(conn);
+	__ASSERT_NO_MSG(buf);
+
+	att = att_get(conn);
+	if (!att) {
+		net_buf_unref(buf);
+		return -ENOTCONN;
+	}
+
+	/* If callback is set use the fixed channel since bt_l2cap_chan_send
+	 * cannot be used with a custom user_data.
+	 */
+	if (cb) {
+		return bt_l2cap_send_cb(conn, BT_L2CAP_CID_ATT, buf, cb,
+					user_data);
+	}
+
+	ret = 0;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		ret = bt_att_chan_send(chan, buf, NULL);
+		if (ret >= 0) {
+			break;
+		}
+	}
+
+	if (ret < 0) {
+		/* Queue buffer to be send later */
+		BT_DBG("Queueing buffer %p", buf);
+		net_buf_put(&att->tx_queue, buf);
+	}
+
+	return 0;
+}
+
+int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req)
+{
+	struct bt_att *att;
+	struct bt_att_chan *chan, *tmp;
+
+	BT_DBG("bt_att_req_send, conn %p req %p", conn, req);
+
+	__ASSERT_NO_MSG(conn);
+	__ASSERT_NO_MSG(req);
+
+	att = att_get(conn);
+	if (!att) {
+		net_buf_unref(req->buf);
+		req->buf = NULL;
+		return -ENOTCONN;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		/* If there is nothing pending use the channel */
+		if (!chan->req) {
+			int ret;
+
+			ret = bt_att_chan_req_send(chan, req);
+			if (ret >= 0) {
+				return ret;
+			}
+		}
+	}
+
+	/* Queue the request to be send later */
+	sys_slist_append(&att->reqs, &req->node);
+
+	BT_DBG("bt_att_req_send, req %p queued", req);
+
+	return 0;
+}
+
+static bool bt_att_chan_req_cancel(struct bt_att_chan *chan,
+				   struct bt_att_req *req)
+{
+	if (chan->req != req) {
+		return false;
+	}
+
+	chan->req = &cancel;
+
+	att_req_destroy(req);
+
+	return true;
+}
+
+void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req)
+{
+	struct bt_att *att;
+	struct bt_att_chan *chan, *tmp;
+
+	BT_DBG("req %p", req);
+
+	if (!conn || !req) {
+		return;
+	}
+
+	att = att_get(conn);
+	if (!att) {
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&att->chans, chan, tmp, node) {
+		/* Check if request is outstanding */
+		if (bt_att_chan_req_cancel(chan, req)) {
+			return;
+		}
+	}
+
+	/* Remove request from the list */
+	sys_slist_find_and_remove(&att->reqs, &req->node);
+
+	att_req_destroy(req);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/att_internal.h	(working copy)
@@ -0,0 +1,307 @@
+/* att_internal.h - Attribute protocol handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_EATT_PSM		0x27
+#define BT_ATT_DEFAULT_LE_MTU	23
+#define BT_ATT_TIMEOUT		K_SECONDS(30)
+
+/* ATT MTU must be equal for RX and TX, so select the smallest value */
+#if CONFIG_BT_L2CAP_RX_MTU < CONFIG_BT_L2CAP_TX_MTU
+#define BT_ATT_MTU CONFIG_BT_L2CAP_RX_MTU
+#else
+#define BT_ATT_MTU CONFIG_BT_L2CAP_TX_MTU
+#endif
+
+struct bt_att_hdr {
+	uint8_t  code;
+} __packed;
+
+#define BT_ATT_OP_ERROR_RSP			0x01
+struct bt_att_error_rsp {
+	uint8_t  request;
+	uint16_t handle;
+	uint8_t  error;
+} __packed;
+
+#define BT_ATT_OP_MTU_REQ			0x02
+struct bt_att_exchange_mtu_req {
+	uint16_t mtu;
+} __packed;
+
+#define BT_ATT_OP_MTU_RSP			0x03
+struct bt_att_exchange_mtu_rsp {
+	uint16_t mtu;
+} __packed;
+
+/* Find Information Request */
+#define BT_ATT_OP_FIND_INFO_REQ			0x04
+struct bt_att_find_info_req {
+	uint16_t start_handle;
+	uint16_t end_handle;
+} __packed;
+
+/* Format field values for BT_ATT_OP_FIND_INFO_RSP */
+#define BT_ATT_INFO_16				0x01
+#define BT_ATT_INFO_128				0x02
+
+struct bt_att_info_16 {
+	uint16_t handle;
+	uint16_t uuid;
+} __packed;
+
+struct bt_att_info_128 {
+	uint16_t handle;
+	uint8_t  uuid[16];
+} __packed;
+
+/* Find Information Response */
+#define BT_ATT_OP_FIND_INFO_RSP			0x05
+struct bt_att_find_info_rsp {
+	uint8_t  format;
+	uint8_t  info[0];
+} __packed;
+
+/* Find By Type Value Request */
+#define BT_ATT_OP_FIND_TYPE_REQ			0x06
+struct bt_att_find_type_req {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint16_t type;
+	uint8_t  value[0];
+} __packed;
+
+struct bt_att_handle_group {
+	uint16_t start_handle;
+	uint16_t end_handle;
+} __packed;
+
+/* Find By Type Value Response */
+#define BT_ATT_OP_FIND_TYPE_RSP			0x07
+struct bt_att_find_type_rsp {
+	struct bt_att_handle_group list[0];
+} __packed;
+
+/* Read By Type Request */
+#define BT_ATT_OP_READ_TYPE_REQ			0x08
+struct bt_att_read_type_req {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint8_t  uuid[0];
+} __packed;
+
+struct bt_att_data {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Read By Type Response */
+#define BT_ATT_OP_READ_TYPE_RSP			0x09
+struct bt_att_read_type_rsp {
+	uint8_t  len;
+	struct bt_att_data data[0];
+} __packed;
+
+/* Read Request */
+#define BT_ATT_OP_READ_REQ			0x0a
+struct bt_att_read_req {
+	uint16_t handle;
+} __packed;
+
+/* Read Response */
+#define BT_ATT_OP_READ_RSP			0x0b
+struct bt_att_read_rsp {
+	uint8_t  value[0];
+} __packed;
+
+/* Read Blob Request */
+#define BT_ATT_OP_READ_BLOB_REQ			0x0c
+struct bt_att_read_blob_req {
+	uint16_t handle;
+	uint16_t offset;
+} __packed;
+
+/* Read Blob Response */
+#define BT_ATT_OP_READ_BLOB_RSP			0x0d
+struct bt_att_read_blob_rsp {
+	uint8_t  value[0];
+} __packed;
+
+/* Read Multiple Request */
+#define BT_ATT_READ_MULT_MIN_LEN_REQ		0x04
+
+#define BT_ATT_OP_READ_MULT_REQ			0x0e
+struct bt_att_read_mult_req {
+	uint16_t handles[0];
+} __packed;
+
+/* Read Multiple Response */
+#define BT_ATT_OP_READ_MULT_RSP			0x0f
+struct bt_att_read_mult_rsp {
+	uint8_t  value[0];
+} __packed;
+
+/* Read by Group Type Request */
+#define BT_ATT_OP_READ_GROUP_REQ		0x10
+struct bt_att_read_group_req {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint8_t  uuid[0];
+} __packed;
+
+struct bt_att_group_data {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Read by Group Type Response */
+#define BT_ATT_OP_READ_GROUP_RSP		0x11
+struct bt_att_read_group_rsp {
+	uint8_t  len;
+	struct bt_att_group_data data[0];
+} __packed;
+
+/* Write Request */
+#define BT_ATT_OP_WRITE_REQ			0x12
+struct bt_att_write_req {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Write Response */
+#define BT_ATT_OP_WRITE_RSP			0x13
+
+/* Prepare Write Request */
+#define BT_ATT_OP_PREPARE_WRITE_REQ		0x16
+struct bt_att_prepare_write_req {
+	uint16_t handle;
+	uint16_t offset;
+	uint8_t  value[0];
+} __packed;
+
+/* Prepare Write Respond */
+#define BT_ATT_OP_PREPARE_WRITE_RSP		0x17
+struct bt_att_prepare_write_rsp {
+	uint16_t handle;
+	uint16_t offset;
+	uint8_t  value[0];
+} __packed;
+
+/* Execute Write Request */
+#define BT_ATT_FLAG_CANCEL			0x00
+#define BT_ATT_FLAG_EXEC			0x01
+
+#define BT_ATT_OP_EXEC_WRITE_REQ		0x18
+struct bt_att_exec_write_req {
+	uint8_t  flags;
+} __packed;
+
+/* Execute Write Response */
+#define BT_ATT_OP_EXEC_WRITE_RSP		0x19
+
+/* Handle Value Notification */
+#define BT_ATT_OP_NOTIFY			0x1b
+struct bt_att_notify {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Handle Value Indication */
+#define BT_ATT_OP_INDICATE			0x1d
+struct bt_att_indicate {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Handle Value Confirm */
+#define BT_ATT_OP_CONFIRM			0x1e
+
+struct bt_att_signature {
+	uint8_t  value[12];
+} __packed;
+
+#define BT_ATT_OP_READ_MULT_VL_REQ		0x20
+struct bt_att_read_mult_vl_req {
+	uint16_t handles[0];
+} __packed;
+
+/* Read Multiple Respose */
+#define BT_ATT_OP_READ_MULT_VL_RSP		0x21
+struct bt_att_read_mult_vl_rsp {
+	uint16_t len;
+	uint8_t  value[0];
+} __packed;
+
+/* Handle Multiple Value Notification */
+#define BT_ATT_OP_NOTIFY_MULT			0x23
+struct bt_att_notify_mult {
+	uint16_t handle;
+	uint16_t len;
+	uint8_t  value[0];
+} __packed;
+
+/* Write Command */
+#define BT_ATT_OP_WRITE_CMD			0x52
+struct bt_att_write_cmd {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+/* Signed Write Command */
+#define BT_ATT_OP_SIGNED_WRITE_CMD		0xd2
+struct bt_att_signed_write_cmd {
+	uint16_t handle;
+	uint8_t  value[0];
+} __packed;
+
+typedef void (*bt_att_func_t)(struct bt_conn *conn, uint8_t err,
+			      const void *pdu, uint16_t length,
+			      void *user_data);
+typedef void (*bt_att_destroy_t)(void *user_data);
+
+/* ATT request context */
+struct bt_att_req {
+	sys_snode_t node;
+	bt_att_func_t func;
+	bt_att_destroy_t destroy;
+	struct net_buf_simple_state state;
+	struct net_buf *buf;
+#if defined(CONFIG_BT_SMP)
+	bool retrying;
+#endif /* CONFIG_BT_SMP */
+	void *user_data;
+};
+
+void att_sent(struct bt_conn *conn, void *user_data);
+
+void bt_att_init(void);
+uint16_t bt_att_get_mtu(struct bt_conn *conn);
+struct net_buf *bt_att_create_pdu(struct bt_conn *conn, uint8_t op,
+				  size_t len);
+
+/* Allocate a new request */
+struct bt_att_req *bt_att_req_alloc(k_timeout_t timeout);
+
+/* Free a request */
+void bt_att_req_free(struct bt_att_req *req);
+
+/* Send ATT PDU over a connection */
+int bt_att_send(struct bt_conn *conn, struct net_buf *buf, bt_conn_tx_cb_t cb,
+		void *user_data);
+
+/* Send ATT Request over a connection */
+int bt_att_req_send(struct bt_conn *conn, struct bt_att_req *req);
+
+/* Cancel ATT request */
+void bt_att_req_cancel(struct bt_conn *conn, struct bt_att_req *req);
+
+/* Connect EATT channels */
+int bt_eatt_connect(struct bt_conn *conn, uint8_t num_channels);
+
+/* Disconnect EATT channels */
+int bt_eatt_disconnect(struct bt_conn *conn);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/CMakeLists.txt	(working copy)
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_link_libraries(subsys__bluetooth)
+
+zephyr_library_sources_ifdef(CONFIG_BT_ISO iso.c)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/Kconfig	(working copy)
@@ -0,0 +1,107 @@
+# Bluetooth Audio configuration options
+
+#
+# Copyright (c) 2020 Intel Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+menuconfig BT_AUDIO
+	bool "Bluetooth Audio support [Experimental]"
+	help
+	  This option enables Bluetooth Audio support. The specific
+	  features that are available may depend on other features
+	  that have been enabled in the stack, such as Periodic
+	  Advertisement for Broadcast and L2CAP Dynamic Channel
+	  for Unicast.
+
+if BT_AUDIO
+
+config BT_ISO
+	bool
+
+if BT_CONN
+
+config BT_AUDIO_UNICAST
+	bool "Bluetooth Unicast Audio Support"
+	select BT_SMP
+	select BT_L2CAP_DYNAMIC_CHANNEL
+	select BT_ISO
+	select BT_GATT_DYNAMIC_DB
+	select BT_GATT_CACHING
+	select BT_EATT
+	help
+	  This option enables support for Bluetooth Unicast Audio using
+	  Isochronous channels.
+
+if BT_AUDIO_UNICAST
+
+config BT_MAX_ISO_CONN
+	int "Maximum number of simultaneous ISO connections"
+	depends on BT_ISO
+	default BT_MAX_CONN
+	range 1 64
+	help
+	  Maximum number of simultaneous Bluetooth isochronous connections
+	  supported.
+
+config BT_ISO_TX_BUF_COUNT
+	int "Numer of Isochronous TX buffers"
+	default 1
+	range 1 255
+	help
+	  Number of buffers available for outgoing Isochronous channel packets.
+
+config BT_ISO_TX_FRAG_COUNT
+	int "Number of ISO TX fragment buffers"
+	default 2
+	range 0 255
+	help
+	  Number of buffers available for fragments of TX buffers. Warning:
+	  setting this to 0 means that the application must ensure that
+	  queued TX buffers never need to be fragmented, i.e. that the
+	  controller's buffer size is large enough. If this is not ensured,
+	  and there are no dedicated fragment buffers, a deadlock may occur.
+	  In most cases the default value of 2 is a safe bet.
+
+config BT_ISO_TX_MTU
+	int "Maximum supported MTU for Isochronous TX buffers"
+	default 251
+	range 23 2000
+	help
+	  Maximum MTU for Isochronous channels TX buffers.
+
+config BT_ISO_RX_BUF_COUNT
+	int "Numer of Isochronous RX buffers"
+	default 1
+	range 1 255
+	help
+	  Number of buffers available for incoming Isochronous channel packets.
+
+config BT_ISO_RX_MTU
+	int "Maximum supported MTU for Isochronous RX buffers"
+	default 251
+	range 23 2000
+	help
+	  Maximum MTU for Isochronous channels RX buffers.
+
+endif # BT_AUDIO_UNICAST
+endif # BT_CONN
+
+config BT_AUDIO_DEBUG
+	bool "Enable debug logs"
+	depends on BT_DEBUG
+	help
+	  Use this option to enable debug logs for the Bluetooth
+	  Audio functionality.
+
+if BT_AUDIO_DEBUG
+
+config BT_AUDIO_DEBUG_ISO
+	bool "ISO channel debug"
+	help
+	  Use this option to enable ISO channels debug logs for the
+	  Bluetooth Audio functionality.
+
+endif # BT_AUDIO_DEBUG
+endif # BT_AUDIO
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso.c	(working copy)
@@ -0,0 +1,1091 @@
+/*  Bluetooth ISO */
+
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/iso.h>
+
+#include "host/hci_core.h"
+#include "host/conn_internal.h"
+#include "iso_internal.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_AUDIO_DEBUG_ISO)
+#define LOG_MODULE_NAME bt_iso
+#include "common/log.h"
+
+NET_BUF_POOL_FIXED_DEFINE(iso_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
+			  CONFIG_BT_ISO_TX_MTU, NULL);
+NET_BUF_POOL_FIXED_DEFINE(iso_rx_pool, CONFIG_BT_ISO_RX_BUF_COUNT,
+			  CONFIG_BT_ISO_RX_MTU, NULL);
+
+#if CONFIG_BT_ISO_TX_FRAG_COUNT > 0
+NET_BUF_POOL_FIXED_DEFINE(iso_frag_pool, CONFIG_BT_ISO_TX_FRAG_COUNT,
+			  CONFIG_BT_ISO_TX_MTU, NULL);
+#endif /* CONFIG_BT_ISO_TX_FRAG_COUNT > 0 */
+
+/* TODO: Allow more than one server? */
+static struct bt_iso_server *iso_server;
+struct bt_conn iso_conns[CONFIG_BT_MAX_ISO_CONN];
+
+/* Audio Data Path direction */
+enum {
+	BT_ISO_CHAN_HOST_TO_CTRL,
+	BT_ISO_CHAN_CTRL_TO_HOST,
+};
+
+struct bt_iso_data_path {
+	/* Data Path direction */
+	uint8_t dir;
+	/* Data Path ID */
+	uint8_t pid;
+	/* Data Path param reference */
+	struct bt_iso_chan_path *path;
+};
+
+
+struct net_buf *bt_iso_get_rx(k_timeout_t timeout)
+{
+	struct net_buf *buf = net_buf_alloc(&iso_rx_pool, timeout);
+
+	if (buf) {
+		net_buf_reserve(buf, BT_BUF_RESERVE);
+		bt_buf_set_type(buf, BT_BUF_ISO_IN);
+	}
+
+	return buf;
+}
+
+void hci_iso(struct net_buf *buf)
+{
+	struct bt_hci_iso_hdr *hdr;
+	uint16_t handle, len;
+	struct bt_conn *conn;
+	uint8_t flags;
+
+	BT_DBG("buf %p", buf);
+
+	BT_ASSERT(buf->len >= sizeof(*hdr));
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	len = sys_le16_to_cpu(hdr->len);
+	handle = sys_le16_to_cpu(hdr->handle);
+	flags = bt_iso_flags(handle);
+
+	iso(buf)->handle = bt_iso_handle(handle);
+	iso(buf)->index = BT_CONN_INDEX_INVALID;
+
+	BT_DBG("handle %u len %u flags %u", iso(buf)->handle, len, flags);
+
+	if (buf->len != len) {
+		BT_ERR("ISO data length mismatch (%u != %u)", buf->len, len);
+		net_buf_unref(buf);
+		return;
+	}
+
+	conn = bt_conn_lookup_handle(iso(buf)->handle);
+	if (!conn) {
+		BT_ERR("Unable to find conn for handle %u", iso(buf)->handle);
+		net_buf_unref(buf);
+		return;
+	}
+
+	iso(buf)->index = bt_conn_index(conn);
+
+	bt_conn_recv(conn, buf, flags);
+	bt_conn_unref(conn);
+}
+
+void hci_le_cis_estabilished(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_cis_established *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->conn_handle);
+	struct bt_conn *conn;
+
+	BT_DBG("status %u handle %u", evt->status, handle);
+
+	/* ISO connection handles are already assigned at this point */
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("No connection found for handle %u", handle);
+		return;
+	}
+
+	__ASSERT(conn->type == BT_CONN_TYPE_ISO, "Invalid connection type");
+
+	if (!evt->status) {
+		/* TODO: Add CIG sync delay */
+		bt_conn_set_state(conn, BT_CONN_CONNECTED);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	conn->err = evt->status;
+	bt_iso_disconnected(conn);
+	bt_conn_unref(conn);
+}
+
+int hci_le_reject_cis(uint16_t handle, uint8_t reason)
+{
+	struct bt_hci_cp_le_reject_cis *cp;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REJECT_CIS, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(handle);
+	cp->reason = reason;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REJECT_CIS, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int hci_le_accept_cis(uint16_t handle)
+{
+	struct bt_hci_cp_le_accept_cis *cp;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_ACCEPT_CIS, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(handle);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_ACCEPT_CIS, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+void hci_le_cis_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_cis_req *evt = (void *)buf->data;
+	uint16_t acl_handle = sys_le16_to_cpu(evt->acl_handle);
+	uint16_t cis_handle = sys_le16_to_cpu(evt->cis_handle);
+	struct bt_conn *conn, *iso;
+	int err;
+
+	BT_DBG("acl_handle %u cis_handle %u cig_id %u cis %u",
+		acl_handle, cis_handle, evt->cig_id, evt->cis_id);
+
+	/* Lookup existing connection with same handle */
+	iso = bt_conn_lookup_handle(cis_handle);
+	if (iso) {
+		BT_ERR("Invalid ISO handle %d", cis_handle);
+		hci_le_reject_cis(cis_handle, BT_HCI_ERR_CONN_LIMIT_EXCEEDED);
+		bt_conn_unref(iso);
+		return;
+	}
+
+	/* Lookup ACL connection to attach */
+	conn = bt_conn_lookup_handle(acl_handle);
+	if (!conn) {
+		BT_ERR("Invalid ACL handle %d", acl_handle);
+		hci_le_reject_cis(cis_handle, BT_HCI_ERR_UNKNOWN_CONN_ID);
+		return;
+	}
+
+	/* Add ISO connection */
+	iso = bt_conn_add_iso(conn);
+
+	bt_conn_unref(conn);
+
+	if (!iso) {
+		hci_le_reject_cis(cis_handle,
+				  BT_HCI_ERR_INSUFFICIENT_RESOURCES);
+		return;
+	}
+
+	/* Request application to accept */
+	err = bt_iso_accept(iso);
+	if (err) {
+		bt_iso_cleanup(iso);
+		hci_le_reject_cis(cis_handle,
+				  BT_HCI_ERR_INSUFFICIENT_RESOURCES);
+		return;
+	}
+
+	iso->handle = cis_handle;
+	iso->role = BT_HCI_ROLE_SLAVE;
+	bt_conn_set_state(iso, BT_CONN_CONNECT);
+
+	hci_le_accept_cis(cis_handle);
+}
+
+int hci_le_remove_cig(uint8_t cig_id)
+{
+	struct bt_hci_cp_le_remove_cig *req;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_CIG, sizeof(*req));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	memset(req, 0, sizeof(*req));
+
+	req->cig_id = cig_id;
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_REMOVE_CIG, buf, NULL);
+}
+
+void bt_iso_cleanup(struct bt_conn *conn)
+{
+	int i;
+
+	bt_conn_unref(conn->iso.acl);
+	conn->iso.acl = NULL;
+
+	/* Check if conn is last of CIG */
+	for (i = 0; i < CONFIG_BT_MAX_ISO_CONN; i++) {
+		if (conn == &iso_conns[i]) {
+			continue;
+		}
+
+		if (atomic_get(&iso_conns[i].ref) &&
+		    iso_conns[i].iso.cig_id == conn->iso.cig_id) {
+			break;
+		}
+	}
+
+	if (i == CONFIG_BT_MAX_ISO_CONN) {
+		hci_le_remove_cig(conn->iso.cig_id);
+	}
+
+	bt_conn_unref(conn);
+
+}
+
+struct bt_conn *iso_new(void)
+{
+	return bt_conn_new(iso_conns, ARRAY_SIZE(iso_conns));
+}
+
+struct bt_conn *bt_conn_add_iso(struct bt_conn *acl)
+{
+	struct bt_conn *conn = iso_new();
+
+	if (!conn) {
+		return NULL;
+	}
+
+	conn->iso.acl = bt_conn_ref(acl);
+	conn->type = BT_CONN_TYPE_ISO;
+	sys_slist_init(&conn->channels);
+
+	return conn;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_iso_create_pdu_timeout_debug(struct net_buf_pool *pool,
+						size_t reserve,
+						k_timeout_t timeout,
+						const char *func, int line)
+#else
+struct net_buf *bt_iso_create_pdu_timeout(struct net_buf_pool *pool,
+					  size_t reserve, k_timeout_t timeout)
+#endif
+{
+	if (!pool) {
+		pool = &iso_tx_pool;
+	}
+
+	reserve += sizeof(struct bt_hci_iso_data_hdr);
+
+#if defined(CONFIG_NET_BUF_LOG)
+	return bt_conn_create_pdu_timeout_debug(pool, reserve, timeout, func,
+						line);
+#else
+	return bt_conn_create_pdu_timeout(pool, reserve, timeout);
+#endif
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_iso_create_frag_timeout_debug(size_t reserve,
+						 k_timeout_t timeout,
+						 const char *func, int line)
+#else
+struct net_buf *bt_iso_create_frag_timeout(size_t reserve, k_timeout_t timeout)
+#endif
+{
+	struct net_buf_pool *pool = NULL;
+
+#if CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0
+	pool = &iso_frag_pool;
+#endif
+
+#if defined(CONFIG_NET_BUF_LOG)
+	return bt_conn_create_pdu_timeout_debug(pool, reserve, timeout, func,
+						line);
+#else
+	return bt_conn_create_pdu_timeout(pool, reserve, timeout);
+#endif
+}
+
+static struct net_buf *hci_le_set_cig_params(struct bt_iso_create_param *param)
+{
+	struct bt_hci_cis_params *cis;
+	struct bt_hci_cp_le_set_cig_params *req;
+	struct net_buf *buf;
+	struct net_buf *rsp;
+	int i, err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CIG_PARAMS,
+				sizeof(*req) + sizeof(*cis) * param->num_conns);
+	if (!buf) {
+		return NULL;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	memset(req, 0, sizeof(*req));
+
+	req->cig_id = param->conns[0]->iso.cig_id;
+	sys_put_le24(param->chans[0]->qos->interval, req->m_interval);
+	sys_put_le24(param->chans[0]->qos->interval, req->s_interval);
+	req->sca = param->chans[0]->qos->sca;
+	req->packing = param->chans[0]->qos->packing;
+	req->framing = param->chans[0]->qos->framing;
+	req->m_latency = sys_cpu_to_le16(param->chans[0]->qos->latency);
+	req->s_latency = sys_cpu_to_le16(param->chans[0]->qos->latency);
+	req->num_cis = param->num_conns;
+
+	/* Program the cis parameters */
+	for (i = 0; i < param->num_conns; i++) {
+		cis = net_buf_add(buf, sizeof(*cis));
+
+		memset(cis, 0, sizeof(*cis));
+
+		cis->cis_id = param->conns[i]->iso.cis_id;
+
+		switch (param->chans[i]->qos->dir) {
+		case BT_ISO_CHAN_QOS_IN:
+			cis->m_sdu = param->chans[i]->qos->sdu;
+			break;
+		case BT_ISO_CHAN_QOS_OUT:
+			cis->s_sdu = param->chans[i]->qos->sdu;
+			break;
+		case BT_ISO_CHAN_QOS_INOUT:
+			cis->m_sdu = param->chans[i]->qos->sdu;
+			cis->s_sdu = param->chans[i]->qos->sdu;
+			break;
+		}
+
+		cis->m_phy = param->chans[i]->qos->phy;
+		cis->s_phy = param->chans[i]->qos->phy;
+		cis->m_rtn = param->chans[i]->qos->rtn;
+		cis->s_rtn = param->chans[i]->qos->rtn;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CIG_PARAMS, buf, &rsp);
+	if (err) {
+		return NULL;
+	}
+
+	return rsp;
+}
+
+int bt_conn_bind_iso(struct bt_iso_create_param *param)
+{
+	struct bt_conn *conn;
+	struct net_buf *rsp;
+	struct bt_hci_rp_le_set_cig_params *cig_rsp;
+	int i, err;
+
+	/* Check if controller is ISO capable */
+	if (!BT_FEAT_LE_CIS_MASTER(bt_dev.le.features)) {
+		return -ENOTSUP;
+	}
+
+	if (!param->num_conns || param->num_conns > CONFIG_BT_MAX_ISO_CONN) {
+		return -EINVAL;
+	}
+
+	/* Assign ISO connections to each LE connection */
+	for (i = 0; i < param->num_conns; i++) {
+		conn = param->conns[i];
+
+		if (conn->type != BT_CONN_TYPE_LE) {
+			err = -EINVAL;
+			goto failed;
+		}
+
+		conn = bt_conn_add_iso(conn);
+		if (!conn) {
+			err = -ENOMEM;
+			goto failed;
+		}
+
+		conn->iso.cig_id = param->id;
+		conn->iso.cis_id = bt_conn_index(conn);
+
+		param->conns[i] = conn;
+	}
+
+	rsp = hci_le_set_cig_params(param);
+	if (!rsp) {
+		err = -EIO;
+		goto failed;
+	}
+
+	cig_rsp = (void *)rsp->data;
+
+	if (rsp->len < sizeof(cig_rsp) ||
+	    cig_rsp->num_handles != param->num_conns) {
+		BT_WARN("Unexpected response to hci_le_set_cig_params");
+		err = -EIO;
+	}
+
+	for (i = 0; i < cig_rsp->num_handles; i++) {
+		/* Assign the connection handle */
+		param->conns[i]->handle = cig_rsp->handle[i];
+	}
+
+	net_buf_unref(rsp);
+
+	return 0;
+
+failed:
+	for (i = 0; i < param->num_conns; i++) {
+		conn = param->conns[i];
+
+		if (conn->type == BT_CONN_TYPE_ISO) {
+			bt_iso_cleanup(conn);
+		}
+	}
+
+	return err;
+}
+
+static int hci_le_create_cis(struct bt_conn **conn, uint8_t num_conns)
+{
+	struct bt_hci_cis *cis;
+	struct bt_hci_cp_le_create_cis *req;
+	struct net_buf *buf;
+	int i;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CIS,
+				sizeof(*req) + sizeof(*cis) * num_conns);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	memset(req, 0, sizeof(*req));
+
+	req->num_cis = num_conns;
+
+	/* Program the cis parameters */
+	for (i = 0; i < num_conns; i++) {
+		cis = net_buf_add(buf, sizeof(*cis));
+
+		memset(cis, 0, sizeof(*cis));
+
+		cis->cis_handle = sys_cpu_to_le16(conn[i]->handle);
+		cis->acl_handle = sys_cpu_to_le16(conn[i]->iso.acl->handle);
+	}
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CIS, buf, NULL);
+}
+
+int bt_conn_connect_iso(struct bt_conn **conns, uint8_t num_conns)
+{
+	int i, err;
+
+	/* Check if controller is ISO capable */
+	if (!BT_FEAT_LE_CIS_MASTER(bt_dev.le.features)) {
+		return -ENOTSUP;
+	}
+
+	if (num_conns > CONFIG_BT_MAX_ISO_CONN) {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_conns; i++) {
+		if (conns[i]->type != BT_CONN_TYPE_ISO) {
+			return -EINVAL;
+		}
+	}
+
+	err = hci_le_create_cis(conns, num_conns);
+	if (err) {
+		return err;
+	}
+
+	/* Set connection state */
+	for (i = 0; i < num_conns; i++) {
+		bt_conn_set_state(conns[i], BT_CONN_CONNECT);
+	}
+
+	return 0;
+}
+
+static int hci_le_setup_iso_data_path(struct bt_conn *conn,
+				      struct bt_iso_data_path *path)
+{
+	struct bt_hci_cp_le_setup_iso_path *cp;
+	struct bt_hci_rp_le_setup_iso_path *rp;
+	struct net_buf *buf, *rsp;
+	uint8_t *cc;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SETUP_ISO_PATH, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+	cp->path_dir = path->dir;
+	cp->path_id = path->pid;
+	cp->coding_format = path->path->format;
+	cp->company_id = sys_cpu_to_le16(path->path->cid);
+	cp->vendor_id = sys_cpu_to_le16(path->path->vid);
+	sys_put_le24(path->path->delay, cp->controller_delay);
+	cp->codec_config_len = path->path->cc_len;
+	cc = net_buf_add(buf, cp->codec_config_len);
+	memcpy(cc, path->path->cc, cp->codec_config_len);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SETUP_ISO_PATH, buf, &rsp);
+	if (err) {
+		return err;
+	}
+
+	rp = (void *)rsp->data;
+	if (rp->status || (rp->handle != conn->handle)) {
+		err = -EIO;
+	}
+
+	net_buf_unref(rsp);
+
+	return err;
+}
+
+static int hci_le_remove_iso_data_path(struct bt_conn *conn, uint8_t dir)
+{
+	struct bt_hci_cp_le_remove_iso_path *cp;
+	struct bt_hci_rp_le_remove_iso_path *rp;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_ISO_PATH, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = conn->handle;
+	cp->path_dir = dir;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REMOVE_ISO_PATH, buf, &rsp);
+	if (err) {
+		return err;
+	}
+
+	rp = (void *)rsp->data;
+	if (rp->status || (rp->handle != conn->handle)) {
+		err = -EIO;
+	}
+
+	net_buf_unref(rsp);
+
+	return err;
+}
+
+static void bt_iso_chan_add(struct bt_conn *conn, struct bt_iso_chan *chan)
+{
+	/* Attach channel to the connection */
+	sys_slist_append(&conn->channels, &chan->node);
+	chan->conn = conn;
+
+	BT_DBG("conn %p chan %p", conn, chan);
+}
+
+int bt_iso_accept(struct bt_conn *conn)
+{
+	struct bt_iso_chan *chan;
+	int err;
+
+	__ASSERT_NO_MSG(conn->type == BT_CONN_TYPE_ISO);
+
+	BT_DBG("%p", conn);
+
+	if (!iso_server) {
+		return -ENOMEM;
+	}
+
+	err = iso_server->accept(conn, &chan);
+	if (err < 0) {
+		BT_ERR("err %d", err);
+		return err;
+	}
+
+	bt_iso_chan_add(conn, chan);
+	bt_iso_chan_set_state(chan, BT_ISO_BOUND);
+
+	return 0;
+}
+
+static int bt_iso_setup_data_path(struct bt_conn *conn)
+{
+	int err;
+	struct bt_iso_chan *chan;
+	struct bt_iso_chan_path path = {};
+	struct bt_iso_data_path out_path = { .dir = BT_ISO_CHAN_CTRL_TO_HOST };
+	struct bt_iso_data_path in_path = { .dir = BT_ISO_CHAN_HOST_TO_CTRL };
+
+	chan = SYS_SLIST_PEEK_HEAD_CONTAINER(&conn->channels, chan, node);
+	if (!chan) {
+		return -EINVAL;
+	}
+
+	in_path.path = chan->path ? chan->path : &path;
+	out_path.path = chan->path ? chan->path : &path;
+
+	switch (chan->qos->dir) {
+	case BT_ISO_CHAN_QOS_IN:
+		in_path.pid = in_path.path->pid;
+		out_path.pid = BT_ISO_DATA_PATH_DISABLED;
+		break;
+	case BT_ISO_CHAN_QOS_OUT:
+		in_path.pid = BT_ISO_DATA_PATH_DISABLED;
+		out_path.pid = out_path.path->pid;
+		break;
+	case BT_ISO_CHAN_QOS_INOUT:
+		in_path.pid = in_path.path->pid;
+		out_path.pid = out_path.path->pid;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = hci_le_setup_iso_data_path(conn, &in_path);
+	if (err) {
+		return err;
+	}
+
+	return hci_le_setup_iso_data_path(conn, &out_path);
+}
+
+void bt_iso_connected(struct bt_conn *conn)
+{
+	struct bt_iso_chan *chan;
+
+	__ASSERT_NO_MSG(conn->type == BT_CONN_TYPE_ISO);
+
+	BT_DBG("%p", conn);
+
+	if (bt_iso_setup_data_path(conn)) {
+		BT_ERR("Unable to setup data path");
+		bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (chan->ops->connected) {
+			chan->ops->connected(chan);
+		}
+
+		bt_iso_chan_set_state(chan, BT_ISO_CONNECTED);
+	}
+}
+
+static void bt_iso_remove_data_path(struct bt_conn *conn)
+{
+	BT_DBG("%p", conn);
+
+	/* Remove both directions */
+	hci_le_remove_iso_data_path(conn, BT_ISO_CHAN_CTRL_TO_HOST);
+	hci_le_remove_iso_data_path(conn, BT_ISO_CHAN_HOST_TO_CTRL);
+}
+
+void bt_iso_disconnected(struct bt_conn *conn)
+{
+	struct bt_iso_chan *chan, *next;
+
+	__ASSERT_NO_MSG(conn->type == BT_CONN_TYPE_ISO);
+
+	BT_DBG("%p", conn);
+
+	if (sys_slist_is_empty(&conn->channels)) {
+		return;
+	}
+
+	bt_iso_remove_data_path(conn);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->channels, chan, next, node) {
+		if (chan->ops->disconnected) {
+			chan->ops->disconnected(chan);
+		}
+
+		bt_conn_unref(chan->conn);
+		chan->conn = NULL;
+		bt_iso_chan_set_state(chan, BT_ISO_DISCONNECTED);
+	}
+}
+
+int bt_iso_server_register(struct bt_iso_server *server)
+{
+	__ASSERT_NO_MSG(server);
+
+	/* Check if controller is ISO capable */
+	if (!BT_FEAT_LE_CIS_SLAVE(bt_dev.le.features)) {
+		return -ENOTSUP;
+	}
+
+	if (iso_server) {
+		return -EADDRINUSE;
+	}
+
+	if (!server->accept) {
+		return -EINVAL;
+	}
+
+	if (server->sec_level > BT_SECURITY_L3) {
+		return -EINVAL;
+	} else if (server->sec_level < BT_SECURITY_L1) {
+		/* Level 0 is only applicable for BR/EDR */
+		server->sec_level = BT_SECURITY_L1;
+	}
+
+	BT_DBG("%p", server);
+
+	iso_server = server;
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_AUDIO_DEBUG_ISO)
+const char *bt_iso_chan_state_str(uint8_t state)
+{
+	switch (state) {
+	case BT_ISO_DISCONNECTED:
+		return "disconnected";
+	case BT_ISO_BOUND:
+		return "bound";
+	case BT_ISO_CONNECT:
+		return "connect";
+	case BT_ISO_CONNECTED:
+		return "connected";
+	case BT_ISO_DISCONNECT:
+		return "disconnect";
+	default:
+		return "unknown";
+	}
+}
+
+void bt_iso_chan_set_state_debug(struct bt_iso_chan *chan, uint8_t state,
+				 const char *func, int line)
+{
+	BT_DBG("chan %p conn %p %s -> %s", chan, chan->conn,
+	       bt_iso_chan_state_str(chan->state),
+	       bt_iso_chan_state_str(state));
+
+	/* check transitions validness */
+	switch (state) {
+	case BT_ISO_DISCONNECTED:
+		/* regardless of old state always allows this state */
+		break;
+	case BT_ISO_BOUND:
+		if (chan->state != BT_ISO_DISCONNECTED) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_ISO_CONNECT:
+		if (chan->state != BT_ISO_BOUND) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_ISO_CONNECTED:
+		if (chan->state != BT_ISO_BOUND &&
+		    chan->state != BT_ISO_CONNECT) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_ISO_DISCONNECT:
+		if (chan->state != BT_ISO_CONNECTED) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	default:
+		BT_ERR("%s()%d: unknown (%u) state was set", func, line, state);
+		return;
+	}
+
+	chan->state = state;
+}
+#else
+void bt_iso_chan_set_state(struct bt_iso_chan *chan, uint8_t state)
+{
+	chan->state = state;
+}
+#endif /* CONFIG_BT_AUDIO_DEBUG_ISO */
+
+void bt_iso_chan_remove(struct bt_conn *conn, struct bt_iso_chan *chan)
+{
+	struct bt_iso_chan *c;
+	sys_snode_t *prev = NULL;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, c, node) {
+		if (c == chan) {
+			sys_slist_remove(&conn->channels, prev, &chan->node);
+			return;
+		}
+
+		prev = &chan->node;
+	}
+}
+
+int bt_iso_chan_bind(struct bt_conn **conns, uint8_t num_conns,
+		     struct bt_iso_chan **chans)
+{
+	struct bt_iso_create_param param;
+	int i, err;
+	static uint8_t id;
+
+	__ASSERT_NO_MSG(conns);
+	__ASSERT_NO_MSG(num_conns);
+	__ASSERT_NO_MSG(chans);
+
+	memset(&param, 0, sizeof(param));
+
+	param.id = id++;
+	param.num_conns = num_conns;
+	param.conns = conns;
+	param.chans = chans;
+
+	err = bt_conn_bind_iso(&param);
+	if (err) {
+		return err;
+	}
+
+	/* Bind respective connection to channel */
+	for (i = 0; i < num_conns; i++) {
+		bt_iso_chan_add(conns[i], chans[i]);
+		bt_iso_chan_set_state(chans[i], BT_ISO_BOUND);
+	}
+
+	return 0;
+}
+
+int bt_iso_chan_connect(struct bt_iso_chan **chans, uint8_t num_chans)
+{
+	struct bt_conn *conns[CONFIG_BT_MAX_ISO_CONN];
+	int i, err;
+
+	__ASSERT_NO_MSG(chans);
+	__ASSERT_NO_MSG(num_chans);
+
+	for (i = 0; i < num_chans; i++) {
+		if (!chans[i]->conn) {
+			return -ENOTCONN;
+		}
+
+		conns[i] = chans[i]->conn;
+	}
+
+	err = bt_conn_connect_iso(conns, num_chans);
+	if (err) {
+		return err;
+	}
+
+	for (i = 0; i < num_chans; i++) {
+		bt_iso_chan_set_state(chans[i], BT_ISO_CONNECT);
+	}
+
+	return 0;
+}
+
+int bt_iso_chan_disconnect(struct bt_iso_chan *chan)
+{
+	__ASSERT_NO_MSG(chan);
+
+	if (!chan->conn) {
+		return -ENOTCONN;
+	}
+
+	if (chan->state == BT_ISO_BOUND) {
+		bt_iso_chan_set_state(chan, BT_ISO_DISCONNECTED);
+		bt_conn_unref(chan->conn);
+		chan->conn = NULL;
+		return 0;
+	}
+
+	return bt_conn_disconnect(chan->conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+}
+
+void bt_iso_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)
+{
+	struct bt_hci_iso_data_hdr *hdr;
+	struct bt_iso_chan *chan;
+	uint8_t pb, ts;
+	uint16_t len;
+
+	pb = bt_iso_flags_pb(flags);
+	ts = bt_iso_flags_ts(flags);
+
+	BT_DBG("handle %u len %u flags 0x%02x pb 0x%02x ts 0x%02x",
+	       conn->handle, buf->len, flags, pb, ts);
+
+	/* When the PB_Flag does not equal 0b00, the fields Time_Stamp,
+	 * Packet_Sequence_Number, Packet_Status_Flag and ISO_SDU_Length
+	 * are omitted from the HCI ISO Data packet.
+	 */
+	switch (pb) {
+	case BT_ISO_START:
+	case BT_ISO_SINGLE:
+		/* The ISO_Data_Load field contains either the first fragment
+		 * of an SDU or a complete SDU.
+		 */
+		if (ts) {
+			struct bt_hci_iso_ts_data_hdr *ts_hdr;
+
+			ts_hdr = net_buf_pull_mem(buf, sizeof(*ts_hdr));
+			iso(buf)->ts = sys_le32_to_cpu(ts_hdr->ts);
+
+			hdr = &ts_hdr->data;
+		} else {
+			hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+			/* TODO: Generate a timestamp? */
+			iso(buf)->ts = 0x00000000;
+		}
+
+		len = sys_le16_to_cpu(hdr->slen);
+		flags = bt_iso_pkt_flags(len);
+		len = bt_iso_pkt_len(len);
+
+		/* TODO: Drop the packet if NOP? */
+
+		BT_DBG("%s, len %u total %u flags 0x%02x timestamp %u",
+		       pb == BT_ISO_START ? "Start" : "Single", buf->len, len,
+		       flags, iso(buf)->ts);
+
+		if (conn->rx_len) {
+			BT_ERR("Unexpected ISO %s fragment",
+			       pb == BT_ISO_START ? "Start" : "Single");
+			bt_conn_reset_rx_state(conn);
+		}
+
+		conn->rx_len = len - buf->len;
+		if (conn->rx_len) {
+			if (pb == BT_ISO_SINGLE) {
+				BT_ERR("Unexpected ISO single fragment");
+				bt_conn_reset_rx_state(conn);
+			}
+			conn->rx = buf;
+			return;
+		}
+		break;
+
+	case BT_ISO_CONT:
+		/* The ISO_Data_Load field contains a continuation fragment of
+		 * an SDU.
+		 */
+		if (!conn->rx_len) {
+			BT_ERR("Unexpected ISO continuation fragment");
+			bt_conn_reset_rx_state(conn);
+			net_buf_unref(buf);
+			return;
+		}
+
+		BT_DBG("Cont, len %u rx_len %u", buf->len, conn->rx_len);
+
+		if (buf->len > net_buf_tailroom(conn->rx)) {
+			BT_ERR("Not enough buffer space for ISO data");
+			bt_conn_reset_rx_state(conn);
+			net_buf_unref(buf);
+			return;
+		}
+
+		net_buf_add_mem(conn->rx, buf->data, buf->len);
+		conn->rx_len -= buf->len;
+		net_buf_unref(buf);
+		return;
+
+	case BT_ISO_END:
+		/* The ISO_Data_Load field contains the last fragment of an
+		 * SDU.
+		 */
+		BT_DBG("End, len %u rx_len %u", buf->len, conn->rx_len);
+
+		if (buf->len > net_buf_tailroom(conn->rx)) {
+			BT_ERR("Not enough buffer space for ISO data");
+			bt_conn_reset_rx_state(conn);
+			net_buf_unref(buf);
+			return;
+		}
+
+		net_buf_add_mem(conn->rx, buf->data, buf->len);
+		conn->rx_len -= buf->len;
+		net_buf_unref(buf);
+
+		if (conn->rx_len) {
+			BT_ERR("Unexpected ISO end fragment");
+			return;
+		}
+
+		buf = conn->rx;
+		conn->rx = NULL;
+		conn->rx_len = 0U;
+
+		break;
+	default:
+		BT_ERR("Unexpected ISO pb flags (0x%02x)", pb);
+		bt_conn_reset_rx_state(conn);
+		net_buf_unref(buf);
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (chan->ops->recv) {
+			chan->ops->recv(chan, buf);
+		}
+	}
+}
+
+int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf)
+{
+	struct bt_hci_iso_data_hdr *hdr;
+	static uint16_t sn;
+
+	__ASSERT_NO_MSG(chan);
+	__ASSERT_NO_MSG(buf);
+
+	BT_DBG("chan %p len %zu", chan, net_buf_frags_len(buf));
+
+	if (!chan->conn) {
+		return -ENOTCONN;
+	}
+
+	hdr = net_buf_push(buf, sizeof(*hdr));
+	hdr->sn = sys_cpu_to_le16(sn++);
+	hdr->slen = sys_cpu_to_le16(bt_iso_pkt_len_pack(net_buf_frags_len(buf)
+							- sizeof(*hdr),
+							BT_ISO_DATA_VALID));
+
+	return bt_conn_send(chan->conn, buf);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/audio/iso_internal.h	(working copy)
@@ -0,0 +1,110 @@
+/** @file
+ *  @brief Internal APIs for Bluetooth ISO handling.
+ */
+
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <bluetooth/iso.h>
+
+#define BT_ISO_DATA_PATH_DISABLED			0xFF
+
+struct iso_data {
+	/** BT_BUF_ISO_IN */
+	uint8_t  type;
+
+	/* Index into the bt_conn storage array */
+	uint8_t  index;
+
+	/** ISO connection handle */
+	uint16_t handle;
+
+	/** ISO timestamp */
+	uint32_t ts;
+};
+
+#define iso(buf) ((struct iso_data *)net_buf_user_data(buf))
+
+#if defined(CONFIG_BT_MAX_ISO_CONN)
+extern struct bt_conn iso_conns[CONFIG_BT_MAX_ISO_CONN];
+#endif
+
+/* Process ISO buffer */
+void hci_iso(struct net_buf *buf);
+
+/* Allocates RX buffer */
+struct net_buf *bt_iso_get_rx(k_timeout_t timeout);
+
+/* Create new ISO connecting */
+struct bt_conn *iso_new(void);
+
+/* Process CIS Estabilished event */
+void hci_le_cis_estabilished(struct net_buf *buf);
+
+/* Process CIS Request event */
+void hci_le_cis_req(struct net_buf *buf);
+
+/* Notify ISO channels of a new connection */
+int bt_iso_accept(struct bt_conn *conn);
+
+/* Notify ISO channels of a new connection */
+void bt_iso_connected(struct bt_conn *conn);
+
+/* Notify ISO channels of a disconnect event */
+void bt_iso_disconnected(struct bt_conn *conn);
+
+/* Allocate ISO PDU */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_iso_create_pdu_timeout_debug(struct net_buf_pool *pool,
+						size_t reserve,
+						k_timeout_t timeout,
+						const char *func, int line);
+#define bt_iso_create_pdu_timeout(_pool, _reserve, _timeout) \
+	bt_iso_create_pdu_timeout_debug(_pool, _reserve, _timeout, \
+					__func__, __LINE__)
+
+#define bt_iso_create_pdu(_pool, _reserve) \
+	bt_iso_create_pdu_timeout_debug(_pool, _reserve, K_FOREVER, \
+					__func__, __line__)
+#else
+struct net_buf *bt_iso_create_pdu_timeout(struct net_buf_pool *pool,
+					  size_t reserve, k_timeout_t timeout);
+
+#define bt_iso_create_pdu(_pool, _reserve) \
+	bt_iso_create_pdu_timeout(_pool, _reserve, K_FOREVER)
+#endif
+
+/* Allocate ISO Fragment */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_iso_create_frag_timeout_debug(size_t reserve,
+						 k_timeout_t timeout,
+						 const char *func, int line);
+
+#define bt_iso_create_frag_timeout(_reserve, _timeout) \
+	bt_iso_create_frag_timeout_debug(_reserve, _timeout, \
+					 __func__, __LINE__)
+
+#define bt_iso_create_frag(_reserve) \
+	bt_iso_create_frag_timeout_debug(_reserve, K_FOREVER, \
+					 __func__, __LINE__)
+#else
+struct net_buf *bt_iso_create_frag_timeout(size_t reserve, k_timeout_t timeout);
+
+#define bt_iso_create_frag(_reserve) \
+	bt_iso_create_frag_timeout(_reserve, K_FOREVER)
+#endif
+
+#if defined(CONFIG_BT_AUDIO_DEBUG_ISO)
+void bt_iso_chan_set_state_debug(struct bt_iso_chan *chan, uint8_t state,
+				 const char *func, int line);
+#define bt_iso_chan_set_state(_chan, _state) \
+	bt_iso_chan_set_state_debug(_chan, _state, __func__, __LINE__)
+#else
+void bt_iso_chan_set_state(struct bt_iso_chan *chan, uint8_t state);
+#endif /* CONFIG_BT_AUDIO_DEBUG_ISO */
+
+/* Process incoming data for a connection */
+void bt_iso_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp.c	(working copy)
@@ -0,0 +1,329 @@
+/*
+ * Audio Video Distribution Protocol
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/avdtp.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_AVDTP)
+#define LOG_MODULE_NAME bt_avdtp
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "avdtp_internal.h"
+
+#define AVDTP_MSG_POISTION 0x00
+#define AVDTP_PKT_POSITION 0x02
+#define AVDTP_TID_POSITION 0x04
+#define AVDTP_SIGID_MASK 0x3f
+
+#define AVDTP_GET_TR_ID(hdr) ((hdr & 0xf0) >> AVDTP_TID_POSITION)
+#define AVDTP_GET_MSG_TYPE(hdr) (hdr & 0x03)
+#define AVDTP_GET_PKT_TYPE(hdr) ((hdr & 0x0c) >> AVDTP_PKT_POSITION)
+#define AVDTP_GET_SIG_ID(s) (s & AVDTP_SIGID_MASK)
+
+static struct bt_avdtp_event_cb *event_cb;
+
+static struct bt_avdtp_seid_lsep *lseps;
+
+#define AVDTP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_avdtp, br_chan.chan)
+
+#define AVDTP_KWORK(_work) CONTAINER_OF(_work, struct bt_avdtp_req,\
+					timeout_work)
+
+#define AVDTP_TIMEOUT K_SECONDS(6)
+
+static const struct {
+	uint8_t sig_id;
+	void (*func)(struct bt_avdtp *session, struct net_buf *buf,
+		     uint8_t msg_type);
+} handler[] = {
+};
+
+static int avdtp_send(struct bt_avdtp *session,
+		      struct net_buf *buf, struct bt_avdtp_req *req)
+{
+	int result;
+	struct bt_avdtp_single_sig_hdr *hdr;
+
+	hdr = (struct bt_avdtp_single_sig_hdr *)buf->data;
+
+	result = bt_l2cap_chan_send(&session->br_chan.chan, buf);
+	if (result < 0) {
+		BT_ERR("Error:L2CAP send fail - result = %d", result);
+		return result;
+	}
+
+	/*Save the sent request*/
+	req->sig = AVDTP_GET_SIG_ID(hdr->signal_id);
+	req->tid = AVDTP_GET_TR_ID(hdr->hdr);
+	BT_DBG("sig 0x%02X, tid 0x%02X", req->sig, req->tid);
+
+	session->req = req;
+	/* Start timeout work */
+	k_delayed_work_submit(&session->req->timeout_work, AVDTP_TIMEOUT);
+	return result;
+}
+
+static struct net_buf *avdtp_create_pdu(uint8_t msg_type,
+					uint8_t pkt_type,
+					uint8_t sig_id)
+{
+	struct net_buf *buf;
+	static uint8_t tid;
+	struct bt_avdtp_single_sig_hdr *hdr;
+
+	BT_DBG("");
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+
+	hdr->hdr = (msg_type | pkt_type << AVDTP_PKT_POSITION |
+		    tid++ << AVDTP_TID_POSITION);
+	tid %= 16; /* Loop for 16*/
+	hdr->signal_id = sig_id & AVDTP_SIGID_MASK;
+
+	BT_DBG("hdr = 0x%02X, Signal_ID = 0x%02X", hdr->hdr, hdr->signal_id);
+	return buf;
+}
+
+/* Timeout handler */
+static void avdtp_timeout(struct k_work *work)
+{
+	BT_DBG("Failed Signal_id = %d", (AVDTP_KWORK(work))->sig);
+
+	/* Gracefully Disconnect the Signalling and streaming L2cap chann*/
+
+}
+
+/* L2CAP Interface callbacks */
+void bt_avdtp_l2cap_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_avdtp *session;
+
+	if (!chan) {
+		BT_ERR("Invalid AVDTP chan");
+		return;
+	}
+
+	session = AVDTP_CHAN(chan);
+	BT_DBG("chan %p session %p", chan, session);
+	/* Init the timer */
+	k_delayed_work_init(&session->req->timeout_work, avdtp_timeout);
+
+}
+
+void bt_avdtp_l2cap_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_avdtp *session = AVDTP_CHAN(chan);
+
+	BT_DBG("chan %p session %p", chan, session);
+	session->br_chan.chan.conn = NULL;
+	/* Clear the Pending req if set*/
+}
+
+void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, uint8_t status)
+{
+	BT_DBG("");
+}
+
+int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_avdtp_single_sig_hdr *hdr;
+	struct bt_avdtp *session = AVDTP_CHAN(chan);
+	uint8_t i, msgtype, sigid, tid;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Recvd Wrong AVDTP Header");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	msgtype = AVDTP_GET_MSG_TYPE(hdr->hdr);
+	sigid = AVDTP_GET_SIG_ID(hdr->signal_id);
+	tid = AVDTP_GET_TR_ID(hdr->hdr);
+
+	BT_DBG("msg_type[0x%02x] sig_id[0x%02x] tid[0x%02x]",
+		msgtype, sigid, tid);
+
+	/* validate if there is an outstanding resp expected*/
+	if (msgtype != BT_AVDTP_CMD) {
+		if (session->req == NULL) {
+			BT_DBG("Unexpected peer response");
+			return 0;
+		}
+
+		if (session->req->sig != sigid ||
+		    session->req->tid != tid) {
+			BT_DBG("Peer mismatch resp, expected sig[0x%02x]"
+				"tid[0x%02x]", session->req->sig,
+				session->req->tid);
+			return 0;
+		}
+	}
+
+	for (i = 0U; i < ARRAY_SIZE(handler); i++) {
+		if (sigid == handler[i].sig_id) {
+			handler[i].func(session, buf, msgtype);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+/*A2DP Layer interface */
+int bt_avdtp_connect(struct bt_conn *conn, struct bt_avdtp *session)
+{
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = bt_avdtp_l2cap_connected,
+		.disconnected = bt_avdtp_l2cap_disconnected,
+		.encrypt_change = bt_avdtp_l2cap_encrypt_changed,
+		.recv = bt_avdtp_l2cap_recv
+	};
+
+	if (!session) {
+		return -EINVAL;
+	}
+
+	session->br_chan.chan.ops = &ops;
+	session->br_chan.chan.required_sec_level = BT_SECURITY_L2;
+
+	return bt_l2cap_chan_connect(conn, &session->br_chan.chan,
+				     BT_L2CAP_PSM_AVDTP);
+}
+
+int bt_avdtp_disconnect(struct bt_avdtp *session)
+{
+	if (!session) {
+		return -EINVAL;
+	}
+
+	BT_DBG("session %p", session);
+
+	return bt_l2cap_chan_disconnect(&session->br_chan.chan);
+}
+
+int bt_avdtp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	struct bt_avdtp *session = NULL;
+	int result;
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = bt_avdtp_l2cap_connected,
+		.disconnected = bt_avdtp_l2cap_disconnected,
+		.recv = bt_avdtp_l2cap_recv,
+	};
+
+	BT_DBG("conn %p", conn);
+	/* Get the AVDTP session from upper layer */
+	result = event_cb->accept(conn, &session);
+	if (result < 0) {
+		return result;
+	}
+	session->br_chan.chan.ops = &ops;
+	session->br_chan.rx.mtu = BT_AVDTP_MAX_MTU;
+	*chan = &session->br_chan.chan;
+	return 0;
+}
+
+/* Application will register its callback */
+int bt_avdtp_register(struct bt_avdtp_event_cb *cb)
+{
+	BT_DBG("");
+
+	if (event_cb) {
+		return -EALREADY;
+	}
+
+	event_cb = cb;
+
+	return 0;
+}
+
+int bt_avdtp_register_sep(uint8_t media_type, uint8_t role,
+			  struct bt_avdtp_seid_lsep *lsep)
+{
+	BT_DBG("");
+
+	static uint8_t bt_avdtp_seid = BT_AVDTP_MIN_SEID;
+
+	if (!lsep) {
+		return -EIO;
+	}
+
+	if (bt_avdtp_seid == BT_AVDTP_MAX_SEID) {
+		return -EIO;
+	}
+
+	lsep->sep.id = bt_avdtp_seid++;
+	lsep->sep.inuse = 0U;
+	lsep->sep.media_type = media_type;
+	lsep->sep.tsep = role;
+
+	lsep->next = lseps;
+	lseps = lsep;
+
+	return 0;
+}
+
+/* init function */
+int bt_avdtp_init(void)
+{
+	int err;
+	static struct bt_l2cap_server avdtp_l2cap = {
+		.psm = BT_L2CAP_PSM_AVDTP,
+		.sec_level = BT_SECURITY_L2,
+		.accept = bt_avdtp_l2cap_accept,
+	};
+
+	BT_DBG("");
+
+	/* Register AVDTP PSM with L2CAP */
+	err = bt_l2cap_br_server_register(&avdtp_l2cap);
+	if (err < 0) {
+		BT_ERR("AVDTP L2CAP Registration failed %d", err);
+	}
+
+	return err;
+}
+
+/* AVDTP Discover Request */
+int bt_avdtp_discover(struct bt_avdtp *session,
+		      struct bt_avdtp_discover_params *param)
+{
+	struct net_buf *buf;
+
+	BT_DBG("");
+	if (!param || !session) {
+		BT_DBG("Error: Callback/Session not valid");
+		return -EINVAL;
+	}
+
+	buf = avdtp_create_pdu(BT_AVDTP_CMD,
+			       BT_AVDTP_PACKET_TYPE_SINGLE,
+			       BT_AVDTP_DISCOVER);
+	if (!buf) {
+		BT_ERR("Error: No Buff available");
+		return -ENOMEM;
+	}
+
+	/* Body of the message */
+
+	return avdtp_send(session, buf, &param->req);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/avdtp_internal.h	(working copy)
@@ -0,0 +1,170 @@
+/*
+ * avdtp_internal.h - avdtp handling
+
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <bluetooth/avdtp.h>
+
+/* @brief A2DP ROLE's */
+#define A2DP_SRC_ROLE 0x00
+#define A2DP_SNK_ROLE 0x01
+
+/* @brief AVDTP Role */
+#define BT_AVDTP_INT 0x00
+#define BT_AVDTP_ACP 0x01
+
+#define BT_L2CAP_PSM_AVDTP 0x0019
+
+/* AVDTP SIGNAL HEADER - Packet Type*/
+#define BT_AVDTP_PACKET_TYPE_SINGLE   0x00
+#define BT_AVDTP_PACKET_TYPE_START    0x01
+#define BT_AVDTP_PACKET_TYPE_CONTINUE 0x02
+#define BT_AVDTP_PACKET_TYPE_END      0x03
+
+/* AVDTP SIGNAL HEADER - MESSAGE TYPE */
+#define BT_AVDTP_CMD        0x00
+#define BT_AVDTP_GEN_REJECT 0x01
+#define BT_AVDTP_ACCEPT     0x02
+#define BT_AVDTP_REJECT     0x03
+
+/* @brief AVDTP SIGNAL HEADER - Signal Identifier */
+#define BT_AVDTP_DISCOVER             0x01
+#define BT_AVDTP_GET_CAPABILITIES     0x02
+#define BT_AVDTP_SET_CONFIGURATION    0x03
+#define BT_AVDTP_GET_CONFIGURATION    0x04
+#define BT_AVDTP_RECONFIGURE          0x05
+#define BT_AVDTP_OPEN                 0x06
+#define BT_AVDTP_START                0x07
+#define BT_AVDTP_CLOSE                0x08
+#define BT_AVDTP_SUSPEND              0x09
+#define BT_AVDTP_ABORT                0x0a
+#define BT_AVDTP_SECURITY_CONTROL     0x0b
+#define BT_AVDTP_GET_ALL_CAPABILITIES 0x0c
+#define BT_AVDTP_DELAYREPORT          0x0d
+
+/* @brief AVDTP STREAM STATE */
+#define BT_AVDTP_STREAM_STATE_IDLE        0x01
+#define BT_AVDTP_STREAM_STATE_CONFIGURED  0x02
+#define BT_AVDTP_STREAM_STATE_OPEN        0x03
+#define BT_AVDTP_STREAM_STATE_STREAMING   0x04
+#define BT_AVDTP_STREAM_STATE_CLOSING     0x05
+
+/* @brief AVDTP Media TYPE */
+#define BT_AVDTP_SERVICE_CAT_MEDIA_TRANSPORT    0x01
+#define BT_AVDTP_SERVICE_CAT_REPORTING          0x02
+#define BT_AVDTP_SERVICE_CAT_RECOVERY           0x03
+#define BT_AVDTP_SERVICE_CAT_CONTENT_PROTECTION 0x04
+#define BT_AVDTP_SERVICE_CAT_HDR_COMPRESSION    0x05
+#define BT_AVDTP_SERVICE_CAT_MULTIPLEXING       0x06
+#define BT_AVDTP_SERVICE_CAT_MEDIA_CODEC        0x07
+#define BT_AVDTP_SERVICE_CAT_DELAYREPORTING     0x08
+
+/* AVDTP Error Codes */
+#define BT_AVDTP_SUCCESS                        0x00
+#define BT_AVDTP_ERR_BAD_HDR_FORMAT             0x01
+#define BT_AVDTP_ERR_BAD_LENGTH                 0x11
+#define BT_AVDTP_ERR_BAD_ACP_SEID               0x12
+#define BT_AVDTP_ERR_SEP_IN_USE                 0x13
+#define BT_AVDTP_ERR_SEP_NOT_IN_USE             0x14
+#define BT_AVDTP_ERR_BAD_SERV_CATEGORY          0x17
+#define BT_AVDTP_ERR_BAD_PAYLOAD_FORMAT         0x18
+#define BT_AVDTP_ERR_NOT_SUPPORTED_COMMAND      0x19
+#define BT_AVDTP_ERR_INVALID_CAPABILITIES       0x1a
+#define BT_AVDTP_ERR_BAD_RECOVERY_TYPE          0x22
+#define BT_AVDTP_ERR_BAD_MEDIA_TRANSPORT_FORMAT 0x23
+#define BT_AVDTP_ERR_BAD_RECOVERY_FORMAT        0x25
+#define BT_AVDTP_ERR_BAD_ROHC_FORMAT            0x26
+#define BT_AVDTP_ERR_BAD_CP_FORMAT              0x27
+#define BT_AVDTP_ERR_BAD_MULTIPLEXING_FORMAT    0x28
+#define BT_AVDTP_ERR_UNSUPPORTED_CONFIGURAION   0x29
+#define BT_AVDTP_ERR_BAD_STATE                  0x31
+
+#define BT_AVDTP_MAX_MTU CONFIG_BT_L2CAP_RX_MTU
+
+#define BT_AVDTP_MIN_SEID 0x01
+#define BT_AVDTP_MAX_SEID 0x3E
+
+struct bt_avdtp;
+struct bt_avdtp_req;
+
+typedef int (*bt_avdtp_func_t)(struct bt_avdtp *session,
+			       struct bt_avdtp_req *req);
+
+struct bt_avdtp_req {
+	uint8_t sig;
+	uint8_t tid;
+	bt_avdtp_func_t func;
+	//struct k_delayed_work timeout_work;
+};
+
+struct bt_avdtp_single_sig_hdr {
+	uint8_t hdr;
+	uint8_t signal_id;
+} __packed;
+
+#define BT_AVDTP_SIG_HDR_LEN sizeof(struct bt_avdtp_single_sig_hdr)
+
+struct bt_avdtp_ind_cb {
+	/*
+	 * discovery_ind;
+	 * get_capabilities_ind;
+	 * set_configuration_ind;
+	 * open_ind;
+	 * start_ind;
+	 * suspend_ind;
+	 * close_ind;
+	 */
+};
+
+struct bt_avdtp_cap {
+	uint8_t cat;
+	uint8_t len;
+	uint8_t data[0];
+};
+
+struct bt_avdtp_sep {
+	uint8_t seid;
+	uint8_t len;
+	struct bt_avdtp_cap caps[0];
+};
+
+struct bt_avdtp_discover_params {
+	struct bt_avdtp_req req;
+	uint8_t status;
+	struct bt_avdtp_sep *caps;
+};
+
+/** @brief Global AVDTP session structure. */
+struct bt_avdtp {
+	struct bt_l2cap_br_chan br_chan;
+	struct bt_avdtp_stream *streams; /* List of AV streams */
+	struct bt_avdtp_req *req;
+};
+
+struct bt_avdtp_event_cb {
+	struct bt_avdtp_ind_cb *ind;
+	int (*accept)(struct bt_conn *conn, struct bt_avdtp **session);
+};
+
+/* Initialize AVDTP layer*/
+int bt_avdtp_init(void);
+
+/* Application register with AVDTP layer */
+int bt_avdtp_register(struct bt_avdtp_event_cb *cb);
+
+/* AVDTP connect */
+int bt_avdtp_connect(struct bt_conn *conn, struct bt_avdtp *session);
+
+/* AVDTP disconnect */
+int bt_avdtp_disconnect(struct bt_avdtp *session);
+
+/* AVDTP SEP register function */
+int bt_avdtp_register_sep(uint8_t media_type, uint8_t role,
+				struct bt_avdtp_seid_lsep *sep);
+
+/* AVDTP Discover Request */
+int bt_avdtp_discover(struct bt_avdtp *session,
+		      struct bt_avdtp_discover_params *param);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn.c	(working copy)
@@ -0,0 +1,2715 @@
+/* conn.c - Bluetooth connection handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <sys/slist.h>
+#include <sys/__assert.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <drivers/bluetooth/hci_driver.h>
+#include <bluetooth/att.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_CONN)
+#define LOG_MODULE_NAME bt_conn
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "keys.h"
+#include "smp.h"
+#include "ssp.h"
+#include "att_internal.h"
+#include "gatt_internal.h"
+#include "audio/iso_internal.h"
+
+Z_STRUCT_SECTION_LIST_VAR_DEFINE(bt_l2cap_fixed_chan, CONFIG_BT_L2CAP_FIXED_CHAN_SIZE);
+
+struct tx_meta {
+	struct bt_conn_tx *tx;
+};
+
+#define tx_data(buf) ((struct tx_meta *)net_buf_user_data(buf))
+
+NET_BUF_POOL_DEFINE(acl_tx_pool, CONFIG_BT_L2CAP_TX_BUF_COUNT,
+		    BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU),
+		    sizeof(struct tx_meta), NULL);
+
+#if CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0
+
+#if defined(CONFIG_BT_CTLR_TX_BUFFER_SIZE)
+#define FRAG_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BT_CTLR_TX_BUFFER_SIZE - 4)
+#else
+#define FRAG_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU)
+#endif
+
+/* Dedicated pool for fragment buffers in case queued up TX buffers don't
+ * fit the controllers buffer size. We can't use the acl_tx_pool for the
+ * fragmentation, since it's possible that pool is empty and all buffers
+ * are queued up in the TX queue. In such a situation, trying to allocate
+ * another buffer from the acl_tx_pool would result in a deadlock.
+ */
+NET_BUF_POOL_FIXED_DEFINE(frag_pool, CONFIG_BT_L2CAP_TX_FRAG_COUNT, FRAG_SIZE,
+			  NULL);
+
+#endif /* CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0 */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+const struct bt_conn_auth_cb *bt_auth;
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+static struct bt_conn acl_conns[CONFIG_BT_MAX_CONN];
+static struct bt_conn_cb *callback_list;
+
+static struct bt_conn_tx conn_tx[CONFIG_BT_CONN_TX_MAX];
+K_FIFO_DEFINE(free_tx);
+
+#if defined(CONFIG_BT_BREDR)
+static struct bt_conn sco_conns[CONFIG_BT_MAX_SCO_CONN];
+#endif /* CONFIG_BT_BREDR */
+
+struct k_sem *bt_conn_get_pkts(struct bt_conn *conn)
+{
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR || !bt_dev.le.acl_mtu) {
+		return &bt_dev.br.pkts;
+	}
+#endif /* CONFIG_BT_BREDR */
+#if defined(CONFIG_BT_ISO)
+	if (conn->type == BT_CONN_TYPE_ISO || bt_dev.le.iso_mtu) {
+		if (bt_dev.le.iso_pkts.limit) {
+			return &bt_dev.le.iso_pkts;
+		}
+	}
+#endif /* CONFIG_BT_ISO */
+	//return &bt_dev.le.acl_pkts;
+	return NULL;
+}
+
+static inline const char *state2str(bt_conn_state_t state)
+{
+	switch (state) {
+	case BT_CONN_DISCONNECTED:
+		return "disconnected";
+	case BT_CONN_DISCONNECT_COMPLETE:
+		return "disconnect-complete";
+	case BT_CONN_CONNECT_SCAN:
+		return "connect-scan";
+	case BT_CONN_CONNECT_DIR_ADV:
+		return "connect-dir-adv";
+	case BT_CONN_CONNECT_ADV:
+		return "connect-adv";
+	case BT_CONN_CONNECT_AUTO:
+		return "connect-auto";
+	case BT_CONN_CONNECT:
+		return "connect";
+	case BT_CONN_CONNECTED:
+		return "connected";
+	case BT_CONN_DISCONNECT:
+		return "disconnect";
+	default:
+		return "(unknown)";
+	}
+}
+
+static void notify_connected(struct bt_conn *conn)
+{
+	struct bt_conn_cb *cb;
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->connected) {
+			cb->connected(conn, conn->err);
+		}
+	}
+
+	if (!conn->err) {
+		bt_gatt_connected(conn);
+	}
+}
+
+static void notify_disconnected(struct bt_conn *conn)
+{
+	struct bt_conn_cb *cb;
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->disconnected) {
+			cb->disconnected(conn, conn->err);
+		}
+	}
+}
+
+#if defined(CONFIG_BT_REMOTE_INFO)
+void notify_remote_info(struct bt_conn *conn)
+{
+	struct bt_conn_remote_info remote_info;
+	struct bt_conn_cb *cb;
+	int err;
+
+	err = bt_conn_get_remote_info(conn, &remote_info);
+	if (err) {
+		BT_DBG("Notify remote info failed %d", err);
+		return;
+	}
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->remote_info_available) {
+			cb->remote_info_available(conn, &remote_info);
+		}
+	}
+}
+#endif /* defined(CONFIG_BT_REMOTE_INFO) */
+
+void notify_le_param_updated(struct bt_conn *conn)
+{
+	struct bt_conn_cb *cb;
+
+	/* If new connection parameters meet requirement of pending
+	 * parameters don't send slave conn param request anymore on timeout
+	 */
+	if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET) &&
+	    conn->le.interval >= conn->le.interval_min &&
+	    conn->le.interval <= conn->le.interval_max &&
+	    conn->le.latency == conn->le.pending_latency &&
+	    conn->le.timeout == conn->le.pending_timeout) {
+		atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
+	}
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->le_param_updated) {
+			cb->le_param_updated(conn, conn->le.interval,
+					     conn->le.latency,
+					     conn->le.timeout);
+		}
+	}
+}
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+void notify_le_data_len_updated(struct bt_conn *conn)
+{
+	struct bt_conn_cb *cb;
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->le_data_len_updated) {
+			cb->le_data_len_updated(conn, &conn->le.data_len);
+		}
+	}
+}
+#endif
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+void notify_le_phy_updated(struct bt_conn *conn)
+{
+	struct bt_conn_cb *cb;
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->le_phy_updated) {
+			cb->le_phy_updated(conn, &conn->le.phy);
+		}
+	}
+}
+#endif
+
+bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
+{
+	struct bt_conn_cb *cb;
+
+	if (!bt_le_conn_params_valid(param)) {
+		return false;
+	}
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (!cb->le_param_req) {
+			continue;
+		}
+
+		if (!cb->le_param_req(conn, param)) {
+			return false;
+		}
+
+		/* The callback may modify the parameters so we need to
+		 * double-check that it returned valid parameters.
+		 */
+		if (!bt_le_conn_params_valid(param)) {
+			return false;
+		}
+	}
+
+	/* Default to accepting if there's no app callback */
+	return true;
+}
+
+static int send_conn_le_param_update(struct bt_conn *conn,
+				const struct bt_le_conn_param *param)
+{
+	BT_DBG("conn %p features 0x%02x params (%d-%d %d %d)", conn,
+	       conn->le.features[0], param->interval_min,
+	       param->interval_max, param->latency, param->timeout);
+
+	/* Proceed only if connection parameters contains valid values*/
+	if (!bt_le_conn_params_valid(param)) {
+		return -EINVAL;
+	}
+
+	/* Use LE connection parameter request if both local and remote support
+	 * it; or if local role is master then use LE connection update.
+	 */
+	if ((BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features) &&
+	     BT_FEAT_LE_CONN_PARAM_REQ_PROC(conn->le.features) &&
+	     !atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_L2CAP)) ||
+	     (conn->role == BT_HCI_ROLE_MASTER)) {
+		int rc;
+
+		rc = bt_conn_le_conn_update(conn, param);
+
+		/* store those in case of fallback to L2CAP */
+		if (rc == 0) {
+			conn->le.pending_latency = param->latency;
+			conn->le.pending_timeout = param->timeout;
+		}
+
+		return rc;
+	}
+
+	/* If remote master does not support LL Connection Parameters Request
+	 * Procedure
+	 */
+	return bt_l2cap_update_conn_param(conn, param);
+}
+
+static void tx_free(struct bt_conn_tx *tx)
+{
+    BT_INFO("tx_free, tx: %p", tx);
+	tx->cb = NULL;
+	tx->user_data = NULL;
+	tx->pending_no_cb = 0U;
+	k_fifo_put(&free_tx, tx);
+}
+
+static void tx_notify(struct bt_conn *conn)
+{
+	BT_DBG("tx_notify, conn %p", conn);
+
+	while (1) {
+		struct bt_conn_tx *tx;
+		unsigned int key;
+		bt_conn_tx_cb_t cb;
+		void *user_data;
+
+		key = irq_lock();
+		if (sys_slist_is_empty(&conn->tx_complete)) {
+			irq_unlock(key);
+			break;
+		}
+
+		tx = (void *)sys_slist_get_not_empty(&conn->tx_complete);
+		irq_unlock(key);
+
+		BT_DBG("tx %p cb %p user_data %p", tx, tx->cb, tx->user_data);
+
+		/* Copy over the params */
+		cb = tx->cb;
+		user_data = tx->user_data;
+
+		/* Free up TX notify since there may be user waiting */
+		tx_free(tx);
+
+		/* Run the callback, at this point it should be safe to
+		 * allocate new buffers since the TX should have been
+		 * unblocked by tx_free.
+		 */
+		cb(conn, user_data);
+	}
+}
+
+static void tx_complete_polling(struct bt_conn *conn)
+{
+
+	{
+		struct bt_conn_tx *tx;
+		bt_conn_tx_cb_t cb;
+		void *user_data;
+
+		if (sys_slist_is_empty(&conn->tx_complete)) 
+        {
+			return;
+		}
+
+		tx = (void *)sys_slist_get_not_empty(&conn->tx_complete);
+
+		BT_DBG("tx_complete_polling, tx %p cb %p user_data %p", tx, tx->cb, tx->user_data);
+
+		/* Copy over the params */
+		cb = tx->cb;
+		user_data = tx->user_data;
+
+		/* Free up TX notify since there may be user waiting */
+		tx_free(tx);
+
+		/* Run the callback, at this point it should be safe to
+		 * allocate new buffers since the TX should have been
+		 * unblocked by tx_free.
+		 */
+		cb(conn, user_data);
+	}
+}
+
+static void tx_complete_work(struct k_work *work)
+{
+	struct bt_conn *conn = NULL;//CONTAINER_OF(work, struct bt_conn,
+					   //tx_complete_work);
+
+	BT_DBG("tx_complete_work, conn %p", conn);
+
+	tx_notify(conn);
+}
+
+static void conn_update_timeout(struct k_work *work)
+{
+	struct bt_conn *conn = NULL;//CONTAINER_OF(work, struct bt_conn, update_work);
+	const struct bt_le_conn_param *param;
+
+	BT_DBG("conn %p", conn);
+
+	if (conn->state == BT_CONN_DISCONNECTED) {
+		bt_l2cap_disconnected(conn);
+		notify_disconnected(conn);
+
+		/* Release the reference we took for the very first
+		 * state transition.
+		 */
+		bt_conn_unref(conn);
+		return;
+	}
+
+	if (conn->type != BT_CONN_TYPE_LE) {
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_CONN_ROLE_MASTER) {
+		/* we don't call bt_conn_disconnect as it would also clear
+		 * auto connect flag if it was set, instead just cancel
+		 * connection directly
+		 */
+		bt_le_create_conn_cancel();
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS)) {
+		/* if application set own params use those, otherwise
+		 * use defaults.
+		 */
+		if (atomic_test_and_clear_bit(conn->flags,
+					      BT_CONN_SLAVE_PARAM_SET)) {
+			param = BT_LE_CONN_PARAM(conn->le.interval_min,
+						conn->le.interval_max,
+						conn->le.pending_latency,
+						conn->le.pending_timeout);
+			send_conn_le_param_update(conn, param);
+		} else {
+#if defined(CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
+			param = BT_LE_CONN_PARAM(
+					CONFIG_BT_PERIPHERAL_PREF_MIN_INT,
+					CONFIG_BT_PERIPHERAL_PREF_MAX_INT,
+					CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY,
+					CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
+			send_conn_le_param_update(conn, param);
+#endif
+		}
+	}
+
+	atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE);
+}
+
+struct bt_conn *bt_conn_new(struct bt_conn *conns, size_t size)
+{
+	struct bt_conn *conn = NULL;
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (!atomic_get(&conns[i].ref)) {
+			conn = &conns[i];
+			break;
+		}
+	}
+
+	if (!conn) {
+		return NULL;
+	}
+
+	(void)memset(conn, 0, sizeof(*conn));
+
+	atomic_set(&conn->ref, 1);
+
+	return conn;
+}
+
+static struct bt_conn *acl_conn_new(void)
+{
+	struct bt_conn *conn;
+
+	conn = bt_conn_new(acl_conns, ARRAY_SIZE(acl_conns));
+	if (!conn) {
+		return conn;
+	}
+
+	//k_delayed_work_init(&conn->update_work, conn_update_timeout);
+
+	//k_work_init(&conn->tx_complete_work, tx_complete_work);
+
+	return conn;
+}
+
+#if defined(CONFIG_BT_BREDR)
+void bt_sco_cleanup(struct bt_conn *sco_conn)
+{
+	bt_conn_unref(sco_conn->sco.acl);
+	sco_conn->sco.acl = NULL;
+	bt_conn_unref(sco_conn);
+}
+
+static struct bt_conn *sco_conn_new(void)
+{
+	return bt_conn_new(sco_conns, ARRAY_SIZE(sco_conns));
+}
+
+struct bt_conn *bt_conn_create_br(const bt_addr_t *peer,
+				  const struct bt_br_conn_param *param)
+{
+	struct bt_hci_cp_connect *cp;
+	struct bt_conn *conn;
+	struct net_buf *buf;
+
+	conn = bt_conn_lookup_addr_br(peer);
+	if (conn) {
+		switch (conn->state) {
+		case BT_CONN_CONNECT:
+		case BT_CONN_CONNECTED:
+			return conn;
+		default:
+			bt_conn_unref(conn);
+			return NULL;
+		}
+	}
+
+	conn = bt_conn_add_br(peer);
+	if (!conn) {
+		return NULL;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT, sizeof(*cp));
+	if (!buf) {
+		bt_conn_unref(conn);
+		return NULL;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	(void)memset(cp, 0, sizeof(*cp));
+
+	memcpy(&cp->bdaddr, peer, sizeof(cp->bdaddr));
+	cp->packet_type = sys_cpu_to_le16(0xcc18); /* DM1 DH1 DM3 DH5 DM5 DH5 */
+	cp->pscan_rep_mode = 0x02; /* R2 */
+	cp->allow_role_switch = param->allow_role_switch ? 0x01 : 0x00;
+	cp->clock_offset = 0x0000; /* TODO used cached clock offset */
+
+	if (bt_hci_cmd_send_sync(BT_HCI_OP_CONNECT, buf, NULL) < 0) {
+		bt_conn_unref(conn);
+		return NULL;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_CONNECT);
+	conn->role = BT_CONN_ROLE_MASTER;
+
+	return conn;
+}
+
+struct bt_conn *bt_conn_create_sco(const bt_addr_t *peer)
+{
+	struct bt_hci_cp_setup_sync_conn *cp;
+	struct bt_conn *sco_conn;
+	struct net_buf *buf;
+	int link_type;
+
+	sco_conn = bt_conn_lookup_addr_sco(peer);
+	if (sco_conn) {
+		switch (sco_conn->state) {
+		case BT_CONN_CONNECT:
+		case BT_CONN_CONNECTED:
+			return sco_conn;
+		default:
+			bt_conn_unref(sco_conn);
+			return NULL;
+		}
+	}
+
+	if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) {
+		link_type = BT_HCI_ESCO;
+	} else {
+		link_type = BT_HCI_SCO;
+	}
+
+	sco_conn = bt_conn_add_sco(peer, link_type);
+	if (!sco_conn) {
+		return NULL;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_SETUP_SYNC_CONN, sizeof(*cp));
+	if (!buf) {
+		bt_sco_cleanup(sco_conn);
+		return NULL;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	(void)memset(cp, 0, sizeof(*cp));
+
+	BT_ERR("handle : %x", sco_conn->sco.acl->handle);
+
+	cp->handle = sco_conn->sco.acl->handle;
+	cp->pkt_type = sco_conn->sco.pkt_type;
+	cp->tx_bandwidth = 0x00001f40;
+	cp->rx_bandwidth = 0x00001f40;
+	cp->max_latency = 0x0007;
+	cp->retrans_effort = 0x01;
+	cp->content_format = BT_VOICE_CVSD_16BIT;
+
+	if (bt_hci_cmd_send_sync(BT_HCI_OP_SETUP_SYNC_CONN, buf,
+				 NULL) < 0) {
+		bt_sco_cleanup(sco_conn);
+		return NULL;
+	}
+
+	bt_conn_set_state(sco_conn, BT_CONN_CONNECT);
+
+	return sco_conn;
+}
+
+struct bt_conn *bt_conn_lookup_addr_sco(const bt_addr_t *peer)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sco_conns); i++) {
+		if (!atomic_get(&sco_conns[i].ref)) {
+			continue;
+		}
+
+		if (sco_conns[i].type != BT_CONN_TYPE_SCO) {
+			continue;
+		}
+
+		if (!bt_addr_cmp(peer, &sco_conns[i].sco.acl->br.dst)) {
+			return bt_conn_ref(&sco_conns[i]);
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+		if (!atomic_get(&acl_conns[i].ref)) {
+			continue;
+		}
+
+		if (acl_conns[i].type != BT_CONN_TYPE_BR) {
+			continue;
+		}
+
+		if (!bt_addr_cmp(peer, &acl_conns[i].br.dst)) {
+			return bt_conn_ref(&acl_conns[i]);
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type)
+{
+	struct bt_conn *sco_conn = sco_conn_new();
+
+	if (!sco_conn) {
+		return NULL;
+	}
+
+	sco_conn->sco.acl = bt_conn_lookup_addr_br(peer);
+	sco_conn->type = BT_CONN_TYPE_SCO;
+
+	if (link_type == BT_HCI_SCO) {
+		if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) {
+			sco_conn->sco.pkt_type = (bt_dev.br.esco_pkt_type &
+						  ESCO_PKT_MASK);
+		} else {
+			sco_conn->sco.pkt_type = (bt_dev.br.esco_pkt_type &
+						  SCO_PKT_MASK);
+		}
+	} else if (link_type == BT_HCI_ESCO) {
+		sco_conn->sco.pkt_type = (bt_dev.br.esco_pkt_type &
+					  ~EDR_ESCO_PKT_MASK);
+	}
+
+	return sco_conn;
+}
+
+struct bt_conn *bt_conn_add_br(const bt_addr_t *peer)
+{
+	struct bt_conn *conn = acl_conn_new();
+
+	if (!conn) {
+		return NULL;
+	}
+
+	bt_addr_copy(&conn->br.dst, peer);
+	conn->type = BT_CONN_TYPE_BR;
+
+	return conn;
+}
+
+static int bt_hci_connect_br_cancel(struct bt_conn *conn)
+{
+	struct bt_hci_cp_connect_cancel *cp;
+	struct bt_hci_rp_connect_cancel *rp;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT_CANCEL, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	memcpy(&cp->bdaddr, &conn->br.dst, sizeof(cp->bdaddr));
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_CONNECT_CANCEL, buf, &rsp);
+	if (err) {
+		return err;
+	}
+
+	rp = (void *)rsp->data;
+
+	err = rp->status ? -EIO : 0;
+
+	net_buf_unref(rsp);
+
+	return err;
+}
+
+#endif /* CONFIG_BT_BREDR */
+
+#if defined(CONFIG_BT_SMP)
+void bt_conn_identity_resolved(struct bt_conn *conn)
+{
+	const bt_addr_le_t *rpa;
+	struct bt_conn_cb *cb;
+
+	if (conn->role == BT_HCI_ROLE_MASTER) {
+		rpa = &conn->le.resp_addr;
+	} else {
+		rpa = &conn->le.init_addr;
+	}
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->identity_resolved) {
+			cb->identity_resolved(conn, rpa, &conn->le.dst);
+		}
+	}
+}
+
+int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8],
+				uint8_t ediv[2], const uint8_t *ltk, size_t len)
+{
+	struct bt_hci_cp_le_start_encryption *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_START_ENCRYPTION, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+	memcpy(&cp->rand, rand, sizeof(cp->rand));
+	memcpy(&cp->ediv, ediv, sizeof(cp->ediv));
+
+	memcpy(cp->ltk, ltk, len);
+	if (len < sizeof(cp->ltk)) {
+		(void)memset(cp->ltk + len, 0, sizeof(cp->ltk) - len);
+	}
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_START_ENCRYPTION, buf, NULL);
+}
+#endif /* CONFIG_BT_SMP */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+uint8_t bt_conn_enc_key_size(struct bt_conn *conn)
+{
+	if (!conn->encrypt) {
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		struct bt_hci_cp_read_encryption_key_size *cp;
+		struct bt_hci_rp_read_encryption_key_size *rp;
+		struct net_buf *buf;
+		struct net_buf *rsp;
+		uint8_t key_size;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
+					sizeof(*cp));
+		if (!buf) {
+			return 0;
+		}
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->handle = sys_cpu_to_le16(conn->handle);
+
+		if (bt_hci_cmd_send_sync(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
+					buf, &rsp)) {
+			return 0;
+		}
+
+		rp = (void *)rsp->data;
+
+		key_size = rp->status ? 0 : rp->key_size;
+
+		net_buf_unref(rsp);
+
+		return key_size;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		return conn->le.keys ? conn->le.keys->enc_size : 0;
+	}
+
+	return 0;
+}
+
+static void reset_pairing(struct bt_conn *conn)
+{
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR) {
+		atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING);
+		atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
+		atomic_clear_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE);
+	}
+#endif /* CONFIG_BT_BREDR */
+
+	/* Reset required security level to current operational */
+	conn->required_sec_level = conn->sec_level;
+}
+
+void bt_conn_security_changed(struct bt_conn *conn, uint8_t hci_err,
+			      enum bt_security_err err)
+{
+	struct bt_conn_cb *cb;
+
+	reset_pairing(conn);
+	bt_l2cap_security_changed(conn, hci_err);
+
+	for (cb = callback_list; cb; cb = cb->_next) {
+		if (cb->security_changed) {
+			cb->security_changed(conn, conn->sec_level, err);
+		}
+	}
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+	if (!err && conn->sec_level >= BT_SECURITY_L2) {
+		if (conn->type == BT_CONN_TYPE_LE) {
+			bt_keys_update_usage(conn->id, bt_conn_get_dst(conn));
+		}
+
+#if defined(CONFIG_BT_BREDR)
+		if (conn->type == BT_CONN_TYPE_BR) {
+			bt_keys_link_key_update_usage(&conn->br.dst);
+		}
+#endif /* CONFIG_BT_BREDR */
+
+	}
+#endif
+}
+
+static int start_security(struct bt_conn *conn)
+{
+	if (IS_ENABLED(CONFIG_BT_BREDR) && conn->type == BT_CONN_TYPE_BR) {
+		return bt_ssp_start_security(conn);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		return bt_smp_start_security(conn);
+	}
+
+	return -EINVAL;
+}
+
+int bt_conn_set_security(struct bt_conn *conn, bt_security_t sec)
+{
+	int err;
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_SC_ONLY)) {
+		sec = BT_SECURITY_L4;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
+		sec = BT_SECURITY_L3;
+	}
+
+	/* nothing to do */
+	if (conn->sec_level >= sec || conn->required_sec_level >= sec) {
+		return 0;
+	}
+
+	atomic_set_bit_to(conn->flags, BT_CONN_FORCE_PAIR,
+			  sec & BT_SECURITY_FORCE_PAIR);
+	conn->required_sec_level = sec & ~BT_SECURITY_FORCE_PAIR;
+
+	err = start_security(conn);
+
+	/* reset required security level in case of error */
+	if (err) {
+		conn->required_sec_level = conn->sec_level;
+	}
+
+	return err;
+}
+
+bt_security_t bt_conn_get_security(struct bt_conn *conn)
+{
+	return conn->sec_level;
+}
+#else
+bt_security_t bt_conn_get_security(struct bt_conn *conn)
+{
+	return BT_SECURITY_L1;
+}
+#endif /* CONFIG_BT_SMP */
+
+void bt_conn_cb_register(struct bt_conn_cb *cb)
+{
+	cb->_next = callback_list;
+	callback_list = cb;
+}
+
+void bt_conn_reset_rx_state(struct bt_conn *conn)
+{
+	if (!conn->rx) {
+		return;
+	}
+
+	net_buf_unref(conn->rx);
+	conn->rx = NULL;
+}
+
+void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)
+{
+	uint16_t acl_total_len;
+	/* Make sure we notify any pending TX callbacks before processing
+	 * new data for this connection.
+	 */
+	tx_notify(conn);
+
+	BT_DBG("bt_conn_recv, handle %u len %u flags %02x", conn->handle, buf->len, flags);
+
+	if (IS_ENABLED(CONFIG_BT_ISO) &&
+	    conn->type == BT_CONN_TYPE_ISO) {
+		bt_iso_recv(conn, buf, flags);
+		return;
+	}
+
+	/* Check packet boundary flags */
+	switch (flags) {
+	case BT_ACL_START:
+		if (conn->rx) {
+			BT_ERR("Unexpected first L2CAP frame");
+			bt_conn_reset_rx_state(conn);
+		}
+
+		BT_DBG("First, len %u final %u", buf->len,
+		       (buf->len < sizeof(uint16_t)) ?
+		       0 : sys_get_le16(buf->data));
+
+		conn->rx = buf;
+		break;
+	case BT_ACL_CONT:
+		if (!conn->rx) {
+			BT_ERR("Unexpected L2CAP continuation");
+			bt_conn_reset_rx_state(conn);
+			net_buf_unref(buf);
+			return;
+		}
+
+		if (!buf->len) {
+			BT_DBG("Empty ACL_CONT");
+			net_buf_unref(buf);
+			return;
+		}
+
+		if (buf->len > net_buf_tailroom(conn->rx)) {
+			BT_ERR("Not enough buffer space for L2CAP data");
+			bt_conn_reset_rx_state(conn);
+			net_buf_unref(buf);
+			return;
+		}
+
+		net_buf_add_mem(conn->rx, buf->data, buf->len);
+		net_buf_unref(buf);
+		break;
+	default:
+		/* BT_ACL_START_NO_FLUSH and BT_ACL_COMPLETE are not allowed on
+		 * LE-U from Controller to Host.
+		 * Only BT_ACL_POINT_TO_POINT is supported.
+		 */
+		BT_ERR("Unexpected ACL flags (0x%02x)", flags);
+		bt_conn_reset_rx_state(conn);
+		net_buf_unref(buf);
+		return;
+	}
+
+	if (conn->rx->len < sizeof(uint16_t)) {
+		/* Still not enough data recieved to retrieve the L2CAP header
+		 * length field.
+		 */
+		return;
+	}
+
+	acl_total_len = sys_get_le16(conn->rx->data) + sizeof(struct bt_l2cap_hdr);
+
+	if (conn->rx->len < acl_total_len) {
+		/* L2CAP frame not complete. */
+		return;
+	}
+
+	if (conn->rx->len > acl_total_len) {
+		BT_ERR("ACL len mismatch (%u > %u)",
+		       conn->rx->len, acl_total_len);
+		bt_conn_reset_rx_state(conn);
+		return;
+	}
+
+	/* L2CAP frame complete. */
+	buf = conn->rx;
+	conn->rx = NULL;
+
+	BT_DBG("Successfully parsed %u byte L2CAP packet", buf->len);
+	bt_l2cap_recv(conn, buf);
+}
+
+static struct bt_conn_tx *conn_tx_alloc(void)
+{
+	/* The TX context always get freed in the system workqueue,
+	 * so if we're in the same workqueue but there are no immediate
+	 * contexts available, there's no chance we'll get one by waiting.
+	 */
+	//if (k_current_get() == &k_sys_work_q.thread) {
+	//	return k_fifo_get(&free_tx, K_NO_WAIT);
+	//}
+
+	if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
+		struct bt_conn_tx *tx = k_fifo_get(&free_tx, K_NO_WAIT);
+
+		BT_WARN("conn_tx_alloc, tx: %p", tx);
+
+		if (tx) {
+			return tx;
+		}
+
+		BT_WARN("Unable to get an immediate free conn_tx");
+	}
+
+	return k_fifo_get(&free_tx, K_FOREVER);
+}
+
+int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf,
+		    bt_conn_tx_cb_t cb, void *user_data)
+{
+	struct bt_conn_tx *tx;
+
+	BT_DBG("bt_conn_send_cb, conn handle %u buf len %u cb %p user_data %p", conn->handle,
+	       buf->len, cb, user_data);
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		BT_ERR("not connected!");
+		net_buf_unref(buf);
+		return -ENOTCONN;
+	}
+
+	if (cb) {
+		tx = conn_tx_alloc();
+		if (!tx) {
+			BT_ERR("Unable to allocate TX context");
+			net_buf_unref(buf);
+			return -ENOBUFS;
+		}
+
+		/* Verify that we're still connected after blocking */
+		if (conn->state != BT_CONN_CONNECTED) {
+			BT_WARN("Disconnected while allocating context");
+			net_buf_unref(buf);
+			tx_free(tx);
+			return -ENOTCONN;
+		}
+
+		tx->cb = cb;
+		tx->user_data = user_data;
+		tx->pending_no_cb = 0U;
+
+		tx_data(buf)->tx = tx;
+	} else {
+		tx_data(buf)->tx = NULL;
+	}
+
+	net_buf_put(&conn->tx_queue, buf);
+	return 0;
+}
+
+enum {
+	FRAG_START,
+	FRAG_CONT,
+	FRAG_SINGLE,
+	FRAG_END
+};
+
+static int send_acl(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)
+{
+	struct bt_hci_acl_hdr *hdr;
+
+	switch (flags) {
+	case FRAG_START:
+	case FRAG_SINGLE:
+		flags = BT_ACL_START_NO_FLUSH;
+		break;
+	case FRAG_CONT:
+	case FRAG_END:
+		flags = BT_ACL_CONT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	hdr = net_buf_push(buf, sizeof(*hdr));
+	hdr->handle = sys_cpu_to_le16(bt_acl_handle_pack(conn->handle, flags));
+	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
+
+	bt_buf_set_type(buf, BT_BUF_ACL_OUT);
+
+	return bt_send(buf);
+}
+
+static int send_iso(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)
+{
+	struct bt_hci_iso_hdr *hdr;
+
+	switch (flags) {
+	case FRAG_START:
+		flags = BT_ISO_START;
+		break;
+	case FRAG_CONT:
+		flags = BT_ISO_CONT;
+		break;
+	case FRAG_SINGLE:
+		flags = BT_ISO_SINGLE;
+		break;
+	case FRAG_END:
+		flags = BT_ISO_END;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	hdr = net_buf_push(buf, sizeof(*hdr));
+	hdr->handle = sys_cpu_to_le16(bt_iso_handle_pack(conn->handle, flags,
+							 0));
+	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
+
+	bt_buf_set_type(buf, BT_BUF_ISO_OUT);
+
+	return bt_send(buf);
+}
+
+static bool send_frag(struct bt_conn *conn, struct net_buf *buf, uint8_t flags,
+		      bool always_consume)
+{
+	struct bt_conn_tx *tx = tx_data(buf)->tx;
+	uint32_t *pending_no_cb;
+	unsigned int key;
+	int err;
+
+	BT_DBG("conn %p buf %p len %u flags 0x%02x", conn, buf, buf->len,
+	       flags);
+
+	/* Wait until the controller can accept ACL packets */
+	//k_sem_take(bt_conn_get_pkts(conn), K_FOREVER);
+
+	/* Check for disconnection while waiting for pkts_sem */
+	if (conn->state != BT_CONN_CONNECTED) {
+		goto fail;
+	}
+
+	/* Add to pending, it must be done before bt_buf_set_type */
+	key = irq_lock();
+	if (tx) {
+		sys_slist_append(&conn->tx_pending, &tx->node);
+	} else {
+		struct bt_conn_tx *tail_tx;
+
+		tail_tx = (void *)sys_slist_peek_tail(&conn->tx_pending);
+		if (tail_tx) {
+			pending_no_cb = &tail_tx->pending_no_cb;
+		} else {
+			pending_no_cb = &conn->pending_no_cb;
+		}
+
+		(*pending_no_cb)++;
+	}
+	irq_unlock(key);
+
+	if (IS_ENABLED(CONFIG_BT_ISO) && conn->type == BT_CONN_TYPE_ISO) {
+		err = send_iso(conn, buf, flags);
+	} else {
+		err = send_acl(conn, buf, flags);
+	}
+
+	if (err) {
+		BT_ERR("Unable to send to driver (err %d)", err);
+		key = irq_lock();
+		/* Roll back the pending TX info */
+		if (tx) {
+			sys_slist_find_and_remove(&conn->tx_pending, &tx->node);
+		} else {
+			__ASSERT_NO_MSG(*pending_no_cb > 0);
+			(*pending_no_cb)--;
+		}
+		irq_unlock(key);
+		goto fail;
+	}
+
+	return true;
+
+fail:
+	//k_sem_give(bt_conn_get_pkts(conn));
+	if (tx) {
+		tx_free(tx);
+	}
+
+	if (always_consume) {
+		net_buf_unref(buf);
+	}
+	return false;
+}
+
+static inline uint16_t conn_mtu(struct bt_conn *conn)
+{
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR || !bt_dev.le.acl_mtu) {
+		return bt_dev.br.mtu;
+	}
+#endif /* CONFIG_BT_BREDR */
+#if defined(CONFIG_BT_ISO)
+	if (conn->type == BT_CONN_TYPE_ISO && bt_dev.le.iso_mtu) {
+		return bt_dev.le.iso_mtu;
+	}
+#endif /* CONFIG_BT_ISO */
+	return bt_dev.le.acl_mtu;
+}
+
+static struct net_buf *create_frag(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct net_buf *frag;
+	uint16_t frag_len;
+
+	switch (conn->type) {
+#if defined(CONFIG_BT_ISO)
+	case BT_CONN_TYPE_ISO:
+		frag = bt_iso_create_frag(0);
+		break;
+#endif
+	default:
+		frag = bt_conn_create_frag(0);
+	}
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		net_buf_unref(frag);
+		return NULL;
+	}
+
+	/* Fragments never have a TX completion callback */
+	tx_data(frag)->tx = NULL;
+
+	frag_len = MIN(conn_mtu(conn), net_buf_tailroom(frag));
+
+	net_buf_add_mem(frag, buf->data, frag_len);
+	net_buf_pull(buf, frag_len);
+
+	return frag;
+}
+
+static bool send_buf(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct net_buf *frag;
+
+	BT_DBG("conn %p buf %p len %u", conn, buf, buf->len);
+
+	/* Send directly if the packet fits the ACL MTU */
+	if (buf->len <= conn_mtu(conn)) {
+		return send_frag(conn, buf, FRAG_SINGLE, false);
+	}
+
+	/* Create & enqueue first fragment */
+	frag = create_frag(conn, buf);
+	if (!frag) {
+		return false;
+	}
+
+	if (!send_frag(conn, frag, FRAG_START, true)) {
+		return false;
+	}
+
+	/*
+	 * Send the fragments. For the last one simply use the original
+	 * buffer (which works since we've used net_buf_pull on it.
+	 */
+	while (buf->len > conn_mtu(conn)) {
+		frag = create_frag(conn, buf);
+		if (!frag) {
+			return false;
+		}
+
+		if (!send_frag(conn, frag, FRAG_CONT, true)) {
+			return false;
+		}
+	}
+
+	return send_frag(conn, buf, FRAG_END, false);
+}
+
+static struct k_poll_signal conn_change =
+		K_POLL_SIGNAL_INITIALIZER(conn_change);
+
+static void conn_cleanup(struct bt_conn *conn)
+{
+	struct net_buf *buf;
+
+	/* Give back any allocated buffers */
+	while ((buf = net_buf_get(&conn->tx_queue, K_NO_WAIT))) {
+		if (tx_data(buf)->tx) {
+			tx_free(tx_data(buf)->tx);
+		}
+
+		net_buf_unref(buf);
+	}
+
+	__ASSERT(sys_slist_is_empty(&conn->tx_pending), "Pending TX packets");
+	__ASSERT_NO_MSG(conn->pending_no_cb == 0);
+
+	bt_conn_reset_rx_state(conn);
+
+	//k_delayed_work_submit(&conn->update_work, K_NO_WAIT);
+}
+
+static int conn_prepare_events(struct bt_conn *conn,
+			       struct k_poll_event *events)
+{
+	if (!atomic_get(&conn->ref)) {
+		return -ENOTCONN;
+	}
+
+	if (conn->state == BT_CONN_DISCONNECTED &&
+	    atomic_test_and_clear_bit(conn->flags, BT_CONN_CLEANUP)) {
+		conn_cleanup(conn);
+		return -ENOTCONN;
+	}
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	BT_DBG("Adding conn %p to poll list", conn);
+
+	//k_poll_event_init(&events[0],
+	//		K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+	//		K_POLL_MODE_NOTIFY_ONLY,
+	//		&conn->tx_queue);
+	events[0].tag = BT_EVENT_CONN_TX_QUEUE;
+
+	return 0;
+}
+
+int bt_conn_prepare_events(struct k_poll_event events[])
+{
+	int i, ev_count = 0;
+	struct bt_conn *conn;
+
+	BT_DBG("");
+
+	conn_change.signaled = 0U;
+	//k_poll_event_init(&events[ev_count++], K_POLL_TYPE_SIGNAL,
+	//		  K_POLL_MODE_NOTIFY_ONLY, &conn_change);
+
+	for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+		conn = &acl_conns[i];
+
+		if (!conn_prepare_events(conn, &events[ev_count])) {
+			ev_count++;
+		}
+	}
+
+#if defined(CONFIG_BT_ISO)
+	for (i = 0; i < ARRAY_SIZE(iso_conns); i++) {
+		conn = &iso_conns[i];
+
+		if (!conn_prepare_events(conn, &events[ev_count])) {
+			ev_count++;
+		}
+	}
+#endif
+
+	return ev_count;
+}
+
+void bt_conn_process_tx(struct bt_conn *conn)
+{
+	struct net_buf *buf;
+
+	BT_DBG("conn %p", conn);
+
+	if (conn->state == BT_CONN_DISCONNECTED &&
+	    atomic_test_and_clear_bit(conn->flags, BT_CONN_CLEANUP)) {
+		BT_DBG("handle %u disconnected - cleaning up", conn->handle);
+		conn_cleanup(conn);
+		return;
+	}
+
+	/* Get next ACL packet for connection */
+	buf = net_buf_get(&conn->tx_queue, K_NO_WAIT);
+	BT_ASSERT(buf);
+	if (!send_buf(conn, buf)) {
+		net_buf_unref(buf);
+	}
+}
+
+bool bt_conn_exists_le(uint8_t id, const bt_addr_le_t *peer)
+{
+	struct bt_conn *conn = bt_conn_lookup_addr_le(id, peer);
+
+	if (conn) {
+		/* Connection object already exists.
+		 * If the connection state is not "disconnected",then the
+		 * connection was created but has not yet been disconnected.
+		 * If the connection state is "disconnected" then the connection
+		 * still has valid references. The last reference of the stack
+		 * is released after the disconnected callback.
+		 */
+		BT_WARN("Found valid connection in %s state",
+			state2str(conn->state));
+		bt_conn_unref(conn);
+		return true;
+	}
+
+	return false;
+}
+
+struct bt_conn *bt_conn_add_le(uint8_t id, const bt_addr_le_t *peer)
+{
+	struct bt_conn *conn = acl_conn_new();
+
+	if (!conn) {
+		return NULL;
+	}
+
+	conn->id = id;
+	bt_addr_le_copy(&conn->le.dst, peer);
+#if defined(CONFIG_BT_SMP)
+	conn->sec_level = BT_SECURITY_L1;
+	conn->required_sec_level = BT_SECURITY_L1;
+#endif /* CONFIG_BT_SMP */
+	conn->type = BT_CONN_TYPE_LE;
+	conn->le.interval_min = BT_GAP_INIT_CONN_INT_MIN;
+	conn->le.interval_max = BT_GAP_INIT_CONN_INT_MAX;
+
+	return conn;
+}
+
+static void process_unack_tx(struct bt_conn *conn)
+{
+	/* Return any unacknowledged packets */
+	while (1) {
+		struct bt_conn_tx *tx;
+		sys_snode_t *node;
+		unsigned int key;
+
+		key = irq_lock();
+
+		if (conn->pending_no_cb) {
+			conn->pending_no_cb--;
+			irq_unlock(key);
+			//k_sem_give(bt_conn_get_pkts(conn));
+			continue;
+		}
+
+		node = sys_slist_get(&conn->tx_pending);
+		irq_unlock(key);
+
+		if (!node) {
+			break;
+		}
+
+		tx = CONTAINER_OF(node, struct bt_conn_tx, node);
+
+		key = irq_lock();
+		conn->pending_no_cb = tx->pending_no_cb;
+		tx->pending_no_cb = 0U;
+		irq_unlock(key);
+
+		tx_free(tx);
+
+		//k_sem_give(bt_conn_get_pkts(conn));
+	}
+}
+
+struct bt_conn *conn_lookup_handle(struct bt_conn *conns, size_t size,
+				   uint16_t handle)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (!atomic_get(&conns[i].ref)) {
+			continue;
+		}
+
+		/* We only care about connections with a valid handle */
+		if (!bt_conn_is_handle_valid(&conns[i])) {
+			continue;
+		}
+
+		if (conns[i].handle == handle) {
+			return bt_conn_ref(&conns[i]);
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_conn *conn_lookup_iso(struct bt_conn *conn)
+{
+#if defined(CONFIG_BT_ISO)
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(iso_conns); i++) {
+		if (!atomic_get(&iso_conns[i].ref)) {
+			continue;
+		}
+
+		if (&iso_conns[i] == conn) {
+			return bt_conn_ref(conn);
+		}
+
+		if (iso_conns[i].iso.acl == conn) {
+			return bt_conn_ref(&iso_conns[i]);
+		}
+	}
+
+	return NULL;
+#else
+	return NULL;
+#endif /* CONFIG_BT_ISO */
+}
+
+void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
+{
+	bt_conn_state_t old_state;
+
+	BT_DBG("bt_conn_set_state %s -> %s", state2str(conn->state), state2str(state));
+
+	if (conn->state == state) {
+		BT_WARN("no transition %s", state2str(state));
+		return;
+	}
+
+	old_state = conn->state;
+	conn->state = state;
+
+	/* Actions needed for exiting the old state */
+	switch (old_state) {
+	case BT_CONN_DISCONNECTED:
+		/* Take a reference for the first state transition after
+		 * bt_conn_add_le() and keep it until reaching DISCONNECTED
+		 * again.
+		 */
+		bt_conn_ref(conn);
+		break;
+	case BT_CONN_CONNECT:
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    conn->type == BT_CONN_TYPE_LE) {
+			//k_delayed_work_cancel(&conn->update_work);
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* Actions needed for entering the new state */
+	switch (conn->state) {
+	case BT_CONN_CONNECTED:
+		if (conn->type == BT_CONN_TYPE_SCO) {
+			/* TODO: Notify sco connected */
+			break;
+		}
+		k_fifo_init(&conn->tx_queue);
+		//k_poll_signal_raise(&conn_change, 0);
+
+		if (IS_ENABLED(CONFIG_BT_ISO) &&
+		    conn->type == BT_CONN_TYPE_ISO) {
+			bt_iso_connected(conn);
+			break;
+		}
+
+		sys_slist_init(&conn->channels);
+
+		bt_l2cap_connected(conn);
+		notify_connected(conn);
+		break;
+	case BT_CONN_DISCONNECTED:
+		if (conn->type == BT_CONN_TYPE_SCO) {
+			/* TODO: Notify sco disconnected */
+			bt_conn_unref(conn);
+			break;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_ISO)) {
+			struct bt_conn *iso;
+
+			iso = conn_lookup_iso(conn);
+			if (iso) {
+				bt_iso_disconnected(iso);
+				bt_iso_cleanup(iso);
+				bt_conn_unref(iso);
+				break;
+			}
+		}
+
+		/* Notify disconnection and queue a dummy buffer to wake
+		 * up and stop the tx thread for states where it was
+		 * running.
+		 */
+		switch (old_state) {
+		case BT_CONN_DISCONNECT_COMPLETE:
+			tx_notify(conn);
+
+			/* Cancel Connection Update if it is pending */
+			if (conn->type == BT_CONN_TYPE_LE) {
+				//k_delayed_work_cancel(&conn->update_work);
+			}
+
+			atomic_set_bit(conn->flags, BT_CONN_CLEANUP);
+			//k_poll_signal_raise(&conn_change, 0);
+			/* The last ref will be dropped during cleanup */
+			break;
+		case BT_CONN_CONNECT:
+			/* LE Create Connection command failed. This might be
+			 * directly from the API, don't notify application in
+			 * this case.
+			 */
+			if (conn->err) {
+				notify_connected(conn);
+			}
+
+			bt_conn_unref(conn);
+			break;
+		case BT_CONN_CONNECT_SCAN:
+			/* this indicate LE Create Connection with peer address
+			 * has been stopped. This could either be triggered by
+			 * the application through bt_conn_disconnect or by
+			 * timeout set by bt_conn_le_create_param.timeout.
+			 */
+			if (conn->err) {
+				notify_connected(conn);
+			}
+
+			bt_conn_unref(conn);
+			break;
+		case BT_CONN_CONNECT_DIR_ADV:
+			/* this indicate Directed advertising stopped */
+			if (conn->err) {
+				notify_connected(conn);
+			}
+
+			bt_conn_unref(conn);
+			break;
+		case BT_CONN_CONNECT_AUTO:
+			/* this indicates LE Create Connection with filter
+			 * policy has been stopped. This can only be triggered
+			 * by the application, so don't notify.
+			 */
+			bt_conn_unref(conn);
+			break;
+		case BT_CONN_CONNECT_ADV:
+			/* This can only happen when application stops the
+			 * advertiser, conn->err is never set in this case.
+			 */
+			bt_conn_unref(conn);
+			break;
+		case BT_CONN_CONNECTED:
+		case BT_CONN_DISCONNECT:
+		case BT_CONN_DISCONNECTED:
+			/* Cannot happen. */
+			BT_WARN("Invalid (%u) old state", state);
+			break;
+		}
+		break;
+	case BT_CONN_CONNECT_AUTO:
+		break;
+	case BT_CONN_CONNECT_ADV:
+		break;
+	case BT_CONN_CONNECT_SCAN:
+		break;
+	case BT_CONN_CONNECT_DIR_ADV:
+		break;
+	case BT_CONN_CONNECT:
+		if (conn->type == BT_CONN_TYPE_SCO) {
+			break;
+		}
+		/*
+		 * Timer is needed only for LE. For other link types controller
+		 * will handle connection timeout.
+		 */
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    conn->type == BT_CONN_TYPE_LE) {
+			//k_delayed_work_submit(&conn->update_work,
+				K_MSEC(10 * bt_dev.create_param.timeout);
+		}
+
+		break;
+	case BT_CONN_DISCONNECT:
+		break;
+	case BT_CONN_DISCONNECT_COMPLETE:
+		process_unack_tx(conn);
+		break;
+	default:
+		BT_WARN("no valid (%u) state was set", state);
+
+		break;
+	}
+}
+
+struct bt_conn *bt_conn_lookup_handle(uint16_t handle)
+{
+	struct bt_conn *conn;
+
+	conn = conn_lookup_handle(acl_conns, ARRAY_SIZE(acl_conns), handle);
+	if (conn) {
+		return conn;
+	}
+
+#if defined(CONFIG_BT_ISO)
+	conn = conn_lookup_handle(iso_conns, ARRAY_SIZE(iso_conns), handle);
+	if (conn) {
+		return conn;
+	}
+#endif
+
+ #if defined(CONFIG_BT_BREDR)
+	conn = conn_lookup_handle(sco_conns, ARRAY_SIZE(sco_conns), handle);
+	if (conn) {
+		return conn;
+	}
+#endif
+
+	return NULL;
+}
+
+bool bt_conn_is_peer_addr_le(const struct bt_conn *conn, uint8_t id,
+			     const bt_addr_le_t *peer)
+{
+	if (id != conn->id) {
+		return false;
+	}
+
+	/* Check against conn dst address as it may be the identity address */
+	if (!bt_addr_le_cmp(peer, &conn->le.dst)) {
+		return true;
+	}
+
+	/* Check against initial connection address */
+	if (conn->role == BT_HCI_ROLE_MASTER) {
+		return bt_addr_le_cmp(peer, &conn->le.resp_addr) == 0;
+	}
+
+	return bt_addr_le_cmp(peer, &conn->le.init_addr) == 0;
+}
+
+struct bt_conn *bt_conn_lookup_addr_le(uint8_t id, const bt_addr_le_t *peer)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+		if (!atomic_get(&acl_conns[i].ref)) {
+			continue;
+		}
+
+		if (acl_conns[i].type != BT_CONN_TYPE_LE) {
+			continue;
+		}
+
+		if (bt_conn_is_peer_addr_le(&acl_conns[i], id, peer)) {
+			return bt_conn_ref(&acl_conns[i]);
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_conn *bt_conn_lookup_state_le(uint8_t id, const bt_addr_le_t *peer,
+					const bt_conn_state_t state)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+		if (!atomic_get(&acl_conns[i].ref)) {
+			continue;
+		}
+
+		if (acl_conns[i].type != BT_CONN_TYPE_LE) {
+			continue;
+		}
+
+		if (peer && !bt_conn_is_peer_addr_le(&acl_conns[i], id, peer)) {
+			continue;
+		}
+
+		if (acl_conns[i].state == state && acl_conns[i].id == id) {
+			return bt_conn_ref(&acl_conns[i]);
+		}
+	}
+
+	return NULL;
+}
+
+void bt_conn_foreach(int type, void (*func)(struct bt_conn *conn, void *data),
+		     void *data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+		if (!atomic_get(&acl_conns[i].ref)) {
+			continue;
+		}
+
+		if (!(acl_conns[i].type & type)) {
+			continue;
+		}
+
+		func(&acl_conns[i], data);
+	}
+#if defined(CONFIG_BT_BREDR)
+	if (type & BT_CONN_TYPE_SCO) {
+		for (i = 0; i < ARRAY_SIZE(sco_conns); i++) {
+			if (!atomic_get(&sco_conns[i].ref)) {
+				continue;
+			}
+
+			func(&sco_conns[i], data);
+		}
+	}
+#endif /* defined(CONFIG_BT_BREDR) */
+
+#if defined(CONFIG_BT_ISO)
+	if (type & BT_CONN_TYPE_ISO) {
+		for (i = 0; i < ARRAY_SIZE(iso_conns); i++) {
+			if (!atomic_get(&iso_conns[i].ref)) {
+				continue;
+			}
+
+			func(&iso_conns[i], data);
+		}
+	}
+#endif /* defined(CONFIG_BT_ISO) */
+}
+
+struct bt_conn *bt_conn_ref(struct bt_conn *conn)
+{
+	atomic_val_t old = atomic_inc(&conn->ref);
+
+	BT_DBG("handle %u ref %u -> %u", conn->handle, old,
+	       atomic_get(&conn->ref));
+
+	return conn;
+}
+
+void bt_conn_unref(struct bt_conn *conn)
+{
+	atomic_val_t old = atomic_dec(&conn->ref);
+
+	BT_DBG("bt_conn_unref handle %u ref %u -> %u", conn->handle, old,
+	       atomic_get(&conn->ref));
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_get(&conn->ref) == 0) {
+		bt_le_adv_resume();
+	}
+}
+
+const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn)
+{
+	return &conn->le.dst;
+}
+
+int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
+{
+	info->type = conn->type;
+	info->role = conn->role;
+	info->id = conn->id;
+
+	switch (conn->type) {
+	case BT_CONN_TYPE_LE:
+		info->le.dst = &conn->le.dst;
+		info->le.src = &bt_dev.id_addr[conn->id];
+		if (conn->role == BT_HCI_ROLE_MASTER) {
+			info->le.local = &conn->le.init_addr;
+			info->le.remote = &conn->le.resp_addr;
+		} else {
+			info->le.local = &conn->le.resp_addr;
+			info->le.remote = &conn->le.init_addr;
+		}
+		info->le.interval = conn->le.interval;
+		info->le.latency = conn->le.latency;
+		info->le.timeout = conn->le.timeout;
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+		info->le.phy = &conn->le.phy;
+#endif
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+		info->le.data_len = &conn->le.data_len;
+#endif
+		return 0;
+#if defined(CONFIG_BT_BREDR)
+	case BT_CONN_TYPE_BR:
+		info->br.dst = &conn->br.dst;
+		return 0;
+#endif
+	}
+
+	return -EINVAL;
+}
+
+int bt_conn_get_remote_info(struct bt_conn *conn,
+			    struct bt_conn_remote_info *remote_info)
+{
+	if (!atomic_test_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH) ||
+	    (IS_ENABLED(CONFIG_BT_REMOTE_VERSION) &&
+	     !atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO))) {
+		return -EBUSY;
+	}
+
+	remote_info->type = conn->type;
+#if defined(CONFIG_BT_REMOTE_VERSION)
+	/* The conn->rv values will be just zeroes if the operation failed */
+	remote_info->version = conn->rv.version;
+	remote_info->manufacturer = conn->rv.manufacturer;
+	remote_info->subversion = conn->rv.subversion;
+#else
+	remote_info->version = 0;
+	remote_info->manufacturer = 0;
+	remote_info->subversion = 0;
+#endif
+
+	switch (conn->type) {
+	case BT_CONN_TYPE_LE:
+		remote_info->le.features = conn->le.features;
+		return 0;
+#if defined(CONFIG_BT_BREDR)
+	case BT_CONN_TYPE_BR:
+		/* TODO: Make sure the HCI commands to read br features and
+		*  extended features has finished. */
+		return -ENOTSUP;
+#endif
+	default:
+		return -EINVAL;
+	}
+}
+
+static int conn_disconnect(struct bt_conn *conn, uint8_t reason)
+{
+	int err;
+
+	err = bt_hci_disconnect(conn->handle, reason);
+	if (err) {
+		return err;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_DISCONNECT);
+
+	return 0;
+}
+
+int bt_conn_le_param_update(struct bt_conn *conn,
+			    const struct bt_le_conn_param *param)
+{
+	BT_DBG("conn %p features 0x%02x params (%d-%d %d %d)", conn,
+	       conn->le.features[0], param->interval_min,
+	       param->interval_max, param->latency, param->timeout);
+
+	/* Check if there's a need to update conn params */
+	if (conn->le.interval >= param->interval_min &&
+	    conn->le.interval <= param->interval_max &&
+	    conn->le.latency == param->latency &&
+	    conn->le.timeout == param->timeout) {
+		atomic_clear_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_CONN_ROLE_MASTER) {
+		return send_conn_le_param_update(conn, param);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		/* if slave conn param update timer expired just send request */
+		if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) {
+			return send_conn_le_param_update(conn, param);
+		}
+
+		/* store new conn params to be used by update timer */
+		conn->le.interval_min = param->interval_min;
+		conn->le.interval_max = param->interval_max;
+		conn->le.pending_latency = param->latency;
+		conn->le.pending_timeout = param->timeout;
+		atomic_set_bit(conn->flags, BT_CONN_SLAVE_PARAM_SET);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+int bt_conn_le_data_len_update(struct bt_conn *conn,
+			       const struct bt_conn_le_data_len_param *param)
+{
+	if (conn->le.data_len.tx_max_len == param->tx_max_len &&
+	    conn->le.data_len.tx_max_time == param->tx_max_time) {
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE) &&
+	    !atomic_test_bit(conn->flags, BT_CONN_AUTO_DATA_LEN_COMPLETE)) {
+		return -EAGAIN;
+	}
+
+	return bt_le_set_data_len(conn, param->tx_max_len, param->tx_max_time);
+}
+#endif
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+int bt_conn_le_phy_update(struct bt_conn *conn,
+			  const struct bt_conn_le_phy_param *param)
+{
+	uint8_t phy_opts, all_phys;
+
+	if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
+	    !atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE)) {
+		return -EAGAIN;
+	}
+
+	if ((param->options & BT_CONN_LE_PHY_OPT_CODED_S2) &&
+	    (param->options & BT_CONN_LE_PHY_OPT_CODED_S8)) {
+		phy_opts = BT_HCI_LE_PHY_CODED_ANY;
+	} else if (param->options & BT_CONN_LE_PHY_OPT_CODED_S2) {
+		phy_opts = BT_HCI_LE_PHY_CODED_S2;
+	} else if (param->options & BT_CONN_LE_PHY_OPT_CODED_S8) {
+		phy_opts = BT_HCI_LE_PHY_CODED_S8;
+	} else {
+		phy_opts = BT_HCI_LE_PHY_CODED_ANY;
+	}
+
+	all_phys = 0U;
+	if (param->pref_tx_phy == BT_GAP_LE_PHY_NONE) {
+		all_phys |= BT_HCI_LE_PHY_TX_ANY;
+	}
+
+	if (param->pref_rx_phy == BT_GAP_LE_PHY_NONE) {
+		all_phys |= BT_HCI_LE_PHY_RX_ANY;
+	}
+
+	return bt_le_set_phy(conn, all_phys, param->pref_tx_phy,
+			     param->pref_rx_phy, phy_opts);
+}
+#endif
+
+int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason)
+{
+	/* Disconnection is initiated by us, so auto connection shall
+	 * be disabled. Otherwise the passive scan would be enabled
+	 * and we could send LE Create Connection as soon as the remote
+	 * starts advertising.
+	 */
+#if !defined(CONFIG_BT_WHITELIST)
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->type == BT_CONN_TYPE_LE) {
+		bt_le_set_auto_conn(&conn->le.dst, NULL);
+	}
+#endif /* !defined(CONFIG_BT_WHITELIST) */
+
+	switch (conn->state) {
+	case BT_CONN_CONNECT_SCAN:
+		conn->err = reason;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+			bt_le_scan_update(false);
+		}
+		return 0;
+	case BT_CONN_CONNECT_DIR_ADV:
+		BT_WARN("Deprecated: Use bt_le_adv_stop instead");
+		conn->err = reason;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+			/* User should unref connection object when receiving
+			 * error in connection callback.
+			 */
+			return bt_le_adv_stop();
+		}
+		return 0;
+	case BT_CONN_CONNECT:
+#if defined(CONFIG_BT_BREDR)
+		if (conn->type == BT_CONN_TYPE_BR) {
+			return bt_hci_connect_br_cancel(conn);
+		}
+#endif /* CONFIG_BT_BREDR */
+
+		if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+			//k_delayed_work_cancel(&conn->update_work);
+			return bt_le_create_conn_cancel();
+		}
+
+		return 0;
+	case BT_CONN_CONNECTED:
+		return conn_disconnect(conn, reason);
+	case BT_CONN_DISCONNECT:
+		return 0;
+	case BT_CONN_DISCONNECTED:
+	default:
+		return -ENOTCONN;
+	}
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static void bt_conn_set_param_le(struct bt_conn *conn,
+				 const struct bt_le_conn_param *param)
+{
+	conn->le.interval_min = param->interval_min;
+	conn->le.interval_max = param->interval_max;
+	conn->le.latency = param->latency;
+	conn->le.timeout = param->timeout;
+}
+
+static bool create_param_validate(const struct bt_conn_le_create_param *param)
+{
+#if defined(CONFIG_BT_PRIVACY)
+	/* Initiation timeout cannot be greater than the RPA timeout */
+	const uint32_t timeout_max = (MSEC_PER_SEC / 10) * CONFIG_BT_RPA_TIMEOUT;
+
+	if (param->timeout > timeout_max) {
+		return false;
+	}
+#endif
+
+	return true;
+}
+
+static void create_param_setup(const struct bt_conn_le_create_param *param)
+{
+	bt_dev.create_param = *param;
+
+	bt_dev.create_param.timeout =
+		(bt_dev.create_param.timeout != 0) ?
+		bt_dev.create_param.timeout :
+		(MSEC_PER_SEC / 10) * CONFIG_BT_CREATE_CONN_TIMEOUT;
+
+	bt_dev.create_param.interval_coded =
+		(bt_dev.create_param.interval_coded != 0) ?
+		bt_dev.create_param.interval_coded :
+		bt_dev.create_param.interval;
+
+	bt_dev.create_param.window_coded =
+		(bt_dev.create_param.window_coded != 0) ?
+		bt_dev.create_param.window_coded :
+		bt_dev.create_param.window;
+}
+
+#if defined(CONFIG_BT_WHITELIST)
+int bt_conn_le_create_auto(const struct bt_conn_le_create_param *create_param,
+			   const struct bt_le_conn_param *param)
+{
+	struct bt_conn *conn;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (!bt_le_conn_params_valid(param)) {
+		return -EINVAL;
+	}
+
+	conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE,
+				       BT_CONN_CONNECT_AUTO);
+	if (conn) {
+		bt_conn_unref(conn);
+		return -EALREADY;
+	}
+
+	/* Scanning either to connect or explicit scan, either case scanner was
+	 * started by application and should not be stopped.
+	 */
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+		return -EINVAL;
+	}
+
+	if (!bt_le_scan_random_addr_check()) {
+		return -EINVAL;
+	}
+
+	conn = bt_conn_add_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE);
+	if (!conn) {
+		return -ENOMEM;
+	}
+
+	bt_conn_set_param_le(conn, param);
+	create_param_setup(create_param);
+
+	atomic_set_bit(conn->flags, BT_CONN_AUTO_CONNECT);
+	bt_conn_set_state(conn, BT_CONN_CONNECT_AUTO);
+
+	err = bt_le_create_conn(conn);
+	if (err) {
+		BT_ERR("Failed to start whitelist scan");
+		conn->err = 0;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		bt_conn_unref(conn);
+		return err;
+	}
+
+	/* Since we don't give the application a reference to manage in
+	 * this case, we need to release this reference here.
+	 */
+	bt_conn_unref(conn);
+	return 0;
+}
+
+int bt_conn_create_auto_stop(void)
+{
+	struct bt_conn *conn;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EINVAL;
+	}
+
+	conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, BT_ADDR_LE_NONE,
+				       BT_CONN_CONNECT_AUTO);
+	if (!conn) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+		return -EINVAL;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+	bt_conn_unref(conn);
+
+	err = bt_le_create_conn_cancel();
+	if (err) {
+		BT_ERR("Failed to stop initiator");
+		return err;
+	}
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_WHITELIST) */
+
+int bt_conn_le_create(const bt_addr_le_t *peer,
+		      const struct bt_conn_le_create_param *create_param,
+		      const struct bt_le_conn_param *conn_param,
+		      struct bt_conn **ret_conn)
+{
+	struct bt_conn *conn;
+	bt_addr_le_t dst;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (!bt_le_conn_params_valid(conn_param)) {
+		return -EINVAL;
+	}
+
+	if (!create_param_validate(create_param)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+		return -EALREADY;
+	}
+
+	if (!bt_le_scan_random_addr_check()) {
+		return -EINVAL;
+	}
+
+	if (bt_conn_exists_le(BT_ID_DEFAULT, peer)) {
+		return -EINVAL;
+	}
+
+	if (peer->type == BT_ADDR_LE_PUBLIC_ID ||
+	    peer->type == BT_ADDR_LE_RANDOM_ID) {
+		bt_addr_le_copy(&dst, peer);
+		dst.type -= BT_ADDR_LE_PUBLIC_ID;
+	} else {
+		bt_addr_le_copy(&dst, bt_lookup_id_addr(BT_ID_DEFAULT, peer));
+	}
+
+	/* Only default identity supported for now */
+	conn = bt_conn_add_le(BT_ID_DEFAULT, &dst);
+	if (!conn) {
+		return -ENOMEM;
+	}
+
+	bt_conn_set_param_le(conn, conn_param);
+	create_param_setup(create_param);
+
+#if defined(CONFIG_BT_SMP)
+	if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) {
+		bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
+
+		err = bt_le_scan_update(true);
+		if (err) {
+			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+			bt_conn_unref(conn);
+
+			return err;
+		}
+
+		*ret_conn = conn;
+		return 0;
+	}
+#endif
+
+	bt_conn_set_state(conn, BT_CONN_CONNECT);
+
+	err = bt_le_create_conn(conn);
+	if (err) {
+		conn->err = 0;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		bt_conn_unref(conn);
+
+		bt_le_scan_update(false);
+		return err;
+	}
+
+	*ret_conn = conn;
+	return 0;
+}
+
+#if !defined(CONFIG_BT_WHITELIST)
+int bt_le_set_auto_conn(const bt_addr_le_t *addr,
+			const struct bt_le_conn_param *param)
+{
+	struct bt_conn *conn;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (param && !bt_le_conn_params_valid(param)) {
+		return -EINVAL;
+	}
+
+	if (!bt_le_scan_random_addr_check()) {
+		return -EINVAL;
+	}
+
+	/* Only default identity is supported */
+	conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
+	if (!conn) {
+		conn = bt_conn_add_le(BT_ID_DEFAULT, addr);
+		if (!conn) {
+			return -ENOMEM;
+		}
+	}
+
+	if (param) {
+		bt_conn_set_param_le(conn, param);
+
+		if (!atomic_test_and_set_bit(conn->flags,
+					     BT_CONN_AUTO_CONNECT)) {
+			bt_conn_ref(conn);
+		}
+	} else {
+		if (atomic_test_and_clear_bit(conn->flags,
+					      BT_CONN_AUTO_CONNECT)) {
+			bt_conn_unref(conn);
+			if (conn->state == BT_CONN_CONNECT_SCAN) {
+				bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+			}
+		}
+	}
+
+	if (conn->state == BT_CONN_DISCONNECTED &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		if (param) {
+			bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
+		}
+		bt_le_scan_update(false);
+	}
+
+	bt_conn_unref(conn);
+
+	return 0;
+}
+#endif /* !defined(CONFIG_BT_WHITELIST) */
+#endif /* CONFIG_BT_CENTRAL */
+
+int bt_conn_le_conn_update(struct bt_conn *conn,
+			   const struct bt_le_conn_param *param)
+{
+	struct hci_cp_le_conn_update *conn_update;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_UPDATE,
+				sizeof(*conn_update));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	conn_update = net_buf_add(buf, sizeof(*conn_update));
+	(void)memset(conn_update, 0, sizeof(*conn_update));
+	conn_update->handle = sys_cpu_to_le16(conn->handle);
+	conn_update->conn_interval_min = sys_cpu_to_le16(param->interval_min);
+	conn_update->conn_interval_max = sys_cpu_to_le16(param->interval_max);
+	conn_update->conn_latency = sys_cpu_to_le16(param->latency);
+	conn_update->supervision_timeout = sys_cpu_to_le16(param->timeout);
+
+	return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_UPDATE, buf);
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_conn_create_frag_timeout_debug(size_t reserve,
+						  k_timeout_t timeout,
+						  const char *func, int line)
+#else
+struct net_buf *bt_conn_create_frag_timeout(size_t reserve, k_timeout_t timeout)
+#endif
+{
+	struct net_buf_pool *pool = NULL;
+
+#if CONFIG_BT_L2CAP_TX_FRAG_COUNT > 0
+	pool = &frag_pool;
+#endif
+
+#if defined(CONFIG_NET_BUF_LOG)
+	return bt_conn_create_pdu_timeout_debug(pool, reserve, timeout,
+						func, line);
+#else
+	return bt_conn_create_pdu_timeout(pool, reserve, timeout);
+#endif /* CONFIG_NET_BUF_LOG */
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_conn_create_pdu_timeout_debug(struct net_buf_pool *pool,
+						 size_t reserve,
+						 k_timeout_t timeout,
+						 const char *func, int line)
+#else
+struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
+					   size_t reserve, k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf;
+
+	/*
+	 * PDU must not be allocated from ISR as we block with 'K_FOREVER'
+	 * during the allocation
+	 */
+	__ASSERT_NO_MSG(!k_is_in_isr());
+    
+    BT_INFO("bt_conn_create_pdu_timeout with pool: %p", pool);
+
+	if (!pool) {
+		pool = &acl_tx_pool;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
+#if defined(CONFIG_NET_BUF_LOG)
+		buf = net_buf_alloc_fixed_debug(pool, K_NO_WAIT, func, line);
+#else
+		buf = net_buf_alloc(pool, K_NO_WAIT);
+#endif
+		if (!buf) {
+			BT_WARN("Unable to allocate buffer with K_NO_WAIT");
+#if defined(CONFIG_NET_BUF_LOG)
+			buf = net_buf_alloc_fixed_debug(pool, timeout, func,
+							line);
+#else
+			buf = net_buf_alloc(pool, timeout);
+#endif
+		}
+	} else {
+#if defined(CONFIG_NET_BUF_LOG)
+		buf = net_buf_alloc_fixed_debug(pool, timeout, func,
+							line);
+#else
+		buf = net_buf_alloc(pool, timeout);
+#endif
+	}
+
+	if (!buf) {
+		BT_WARN("Unable to allocate buffer within timeout");
+		return NULL;
+	}
+    BT_INFO("bt_conn_create_pdu_timeout alloc success, buf: %p", buf);
+
+	reserve += sizeof(struct bt_hci_acl_hdr) + BT_BUF_RESERVE;
+	net_buf_reserve(buf, reserve);
+
+	return buf;
+}
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+int bt_conn_auth_cb_register(const struct bt_conn_auth_cb *cb)
+{
+	if (!cb) {
+		bt_auth = NULL;
+		return 0;
+	}
+
+	if (bt_auth) {
+		return -EALREADY;
+	}
+
+	/* The cancel callback must always be provided if the app provides
+	 * interactive callbacks.
+	 */
+	if (!cb->cancel &&
+	    (cb->passkey_display || cb->passkey_entry || cb->passkey_confirm ||
+#if defined(CONFIG_BT_BREDR)
+	     cb->pincode_entry ||
+#endif
+	     cb->pairing_confirm)) {
+		return -EINVAL;
+	}
+
+	bt_auth = cb;
+	return 0;
+}
+
+int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
+{
+	if (!bt_auth) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) {
+		bt_smp_auth_passkey_entry(conn, passkey);
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) && conn->type == BT_CONN_TYPE_BR) {
+		return bt_ssp_auth_passkey_entry(conn, passkey);
+	}
+
+	return -EINVAL;
+}
+
+int bt_conn_auth_passkey_confirm(struct bt_conn *conn)
+{
+	if (!bt_auth) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) &&
+	    conn->type == BT_CONN_TYPE_LE) {
+		return bt_smp_auth_passkey_confirm(conn);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		return bt_ssp_auth_passkey_confirm(conn);
+	}
+
+	return -EINVAL;
+}
+
+int bt_conn_auth_cancel(struct bt_conn *conn)
+{
+	if (!bt_auth) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) && conn->type == BT_CONN_TYPE_LE) {
+		return bt_smp_auth_cancel(conn);
+	}
+
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR) {
+		return bt_ssp_auth_cancel(conn);
+	}
+#endif /* CONFIG_BT_BREDR */
+
+	return -EINVAL;
+}
+
+int bt_conn_auth_pairing_confirm(struct bt_conn *conn)
+{
+	if (!bt_auth) {
+		return -EINVAL;
+	}
+
+	switch (conn->type) {
+#if defined(CONFIG_BT_SMP)
+	case BT_CONN_TYPE_LE:
+		return bt_smp_auth_pairing_confirm(conn);
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_BREDR)
+	case BT_CONN_TYPE_BR:
+		return bt_ssp_auth_pairing_confirm(conn);
+#endif /* CONFIG_BT_BREDR */
+	default:
+		return -EINVAL;
+	}
+}
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+uint8_t bt_conn_index(struct bt_conn *conn)
+{
+	uint8_t index;
+
+	switch (conn->type) {
+#if defined(CONFIG_BT_ISO)
+	case BT_CONN_TYPE_ISO:
+		index = conn - iso_conns;
+		__ASSERT(index < CONFIG_BT_MAX_ISO_CONN,
+			"Invalid bt_conn pointer");
+		break;
+#endif
+#if defined(CONFIG_BT_BREDR)
+	case BT_CONN_TYPE_SCO:
+		index = conn - sco_conns;
+		__ASSERT(index < CONFIG_BT_MAX_SCO_CONN,
+			"Invalid bt_conn pointer");
+		break;
+#endif
+	default:
+		index = conn - acl_conns;
+		__ASSERT(index < CONFIG_BT_MAX_CONN, "Invalid bt_conn pointer");
+		break;
+	}
+
+	return index;
+}
+
+struct bt_conn *bt_conn_lookup_index(uint8_t index)
+{
+	struct bt_conn *conn;
+
+	if (index >= ARRAY_SIZE(acl_conns)) {
+		return NULL;
+	}
+
+	conn = &acl_conns[index];
+
+	if (!atomic_get(&conn->ref)) {
+		return NULL;
+	}
+
+	return bt_conn_ref(conn);
+}
+
+int bt_conn_init(void)
+{
+	int err, i;
+    Z_STRUCT_SECTION_LIST_VAR(bt_l2cap_fixed_chan, 0, le_fixed_chan);
+    Z_STRUCT_SECTION_LIST_VAR(bt_l2cap_fixed_chan, 1, att_fixed_chan);
+    //Z_STRUCT_SECTION_LIST_VAR_INITIAL(bt_l2cap_fixed_chan);
+
+	for (i = 0; i < ARRAY_SIZE(conn_tx); i++) {
+		k_fifo_put(&free_tx, &conn_tx[i]);
+	}
+    
+    BT_DBG("bt_conn_init, free_tx cnt %d", ARRAY_SIZE(conn_tx));
+
+	bt_att_init();
+
+	//err = bt_smp_init();
+	//if (err) {
+	//	return err;
+	//}
+
+	bt_l2cap_init();
+
+	/* Initialize background scan */
+	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+		for (i = 0; i < ARRAY_SIZE(acl_conns); i++) {
+			struct bt_conn *conn = &acl_conns[i];
+
+			if (!atomic_get(&conn->ref)) {
+				continue;
+			}
+
+#if !defined(CONFIG_BT_WHITELIST)
+			if (atomic_test_bit(conn->flags,
+					    BT_CONN_AUTO_CONNECT)) {
+				/* Only the default identity is supported */
+				conn->id = BT_ID_DEFAULT;
+				bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
+			}
+#endif /* !defined(CONFIG_BT_WHITELIST) */
+		}
+	}
+
+	return 0;
+}
+
+
+
+void bt_conn_tx_polling(void)
+{
+	int i;
+    
+    for (i = 0; i < ARRAY_SIZE(acl_conns); i++) 
+    {
+        struct bt_conn *conn = &acl_conns[i];
+    
+        if(!net_buf_is_empty(&conn->tx_queue))
+        {
+            bt_conn_process_tx(conn);
+        }
+        tx_complete_polling(conn);
+    }
+}
+
+
+
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/conn_internal.h	(working copy)
@@ -0,0 +1,366 @@
+/** @file
+ *  @brief Internal APIs for Bluetooth connection handling.
+ */
+
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+typedef enum __packed {
+	BT_CONN_DISCONNECTED,
+	BT_CONN_DISCONNECT_COMPLETE,
+	BT_CONN_CONNECT_SCAN,
+	BT_CONN_CONNECT_AUTO,
+	BT_CONN_CONNECT_ADV,
+	BT_CONN_CONNECT_DIR_ADV,
+	BT_CONN_CONNECT,
+	BT_CONN_CONNECTED,
+	BT_CONN_DISCONNECT,
+} bt_conn_state_t;
+
+/* bt_conn flags: the flags defined here represent connection parameters */
+enum {
+	BT_CONN_AUTO_CONNECT,
+	BT_CONN_BR_LEGACY_SECURE,	/* 16 digits legacy PIN tracker */
+	BT_CONN_USER,			/* user I/O when pairing */
+	BT_CONN_BR_PAIRING,		/* BR connection in pairing context */
+	BT_CONN_BR_NOBOND,		/* SSP no bond pairing tracker */
+	BT_CONN_BR_PAIRING_INITIATOR,	/* local host starts authentication */
+	BT_CONN_CLEANUP,                /* Disconnected, pending cleanup */
+	BT_CONN_AUTO_PHY_UPDATE,        /* Auto-update PHY */
+	BT_CONN_SLAVE_PARAM_UPDATE,	/* If slave param update timer fired */
+	BT_CONN_SLAVE_PARAM_SET,	/* If slave param were set from app */
+	BT_CONN_SLAVE_PARAM_L2CAP,	/* If should force L2CAP for CPUP */
+	BT_CONN_FORCE_PAIR,             /* Pairing even with existing keys. */
+
+	BT_CONN_AUTO_PHY_COMPLETE,      /* Auto-initiated PHY procedure done */
+	BT_CONN_AUTO_FEATURE_EXCH,	/* Auto-initiated LE Feat done */
+	BT_CONN_AUTO_VERSION_INFO,      /* Auto-initiated LE version done */
+
+	/* Auto-initiated Data Length done. Auto-initiated Data Length Update
+	 * is only needed for controllers with BT_QUIRK_NO_AUTO_DLE. */
+	BT_CONN_AUTO_DATA_LEN_COMPLETE,
+
+	/* Total number of flags - must be at the end of the enum */
+	BT_CONN_NUM_FLAGS,
+};
+
+struct bt_conn_le {
+	bt_addr_le_t		dst;
+
+	bt_addr_le_t		init_addr;
+	bt_addr_le_t		resp_addr;
+
+	uint16_t			interval;
+	uint16_t			interval_min;
+	uint16_t			interval_max;
+
+	uint16_t			latency;
+	uint16_t			timeout;
+	uint16_t			pending_latency;
+	uint16_t			pending_timeout;
+
+	uint8_t			features[8];
+
+	struct bt_keys		*keys;
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	struct bt_conn_le_phy_info      phy;
+#endif
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	struct bt_conn_le_data_len_info data_len;
+#endif
+};
+
+#if defined(CONFIG_BT_BREDR)
+/* For now reserve space for 2 pages of LMP remote features */
+#define LMP_MAX_PAGES 2
+
+struct bt_conn_br {
+	bt_addr_t		dst;
+	uint8_t			remote_io_capa;
+	uint8_t			remote_auth;
+	uint8_t			pairing_method;
+	/* remote LMP features pages per 8 bytes each */
+	uint8_t			features[LMP_MAX_PAGES][8];
+
+	struct bt_keys_link_key	*link_key;
+};
+
+struct bt_conn_sco {
+	/* Reference to ACL Connection */
+	struct bt_conn          *acl;
+	uint16_t                pkt_type;
+};
+#endif
+
+struct bt_conn_iso {
+	/* Reference to ACL Connection */
+	struct bt_conn          *acl;
+	/* CIG ID */
+	uint8_t			cig_id;
+	/* CIS ID */
+	uint8_t			cis_id;
+};
+
+typedef void (*bt_conn_tx_cb_t)(struct bt_conn *conn, void *user_data);
+
+struct bt_conn_tx {
+	sys_snode_t node;
+
+	bt_conn_tx_cb_t cb;
+	void *user_data;
+
+	/* Number of pending packets without a callback after this one */
+	uint32_t pending_no_cb;
+};
+
+struct bt_conn {
+	uint16_t			handle;
+	uint8_t			type;
+	uint8_t			role;
+
+	ATOMIC_DEFINE(flags, BT_CONN_NUM_FLAGS);
+
+	/* Which local identity address this connection uses */
+	uint8_t                    id;
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	bt_security_t		sec_level;
+	bt_security_t		required_sec_level;
+	uint8_t			encrypt;
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+	/* Connection error or reason for disconnect */
+	uint8_t			err;
+
+	bt_conn_state_t		state;
+	uint16_t rx_len;
+	struct net_buf		*rx;
+
+	/* Sent but not acknowledged TX packets with a callback */
+	sys_slist_t		tx_pending;
+	/* Sent but not acknowledged TX packets without a callback before
+	 * the next packet (if any) in tx_pending.
+	 */
+	uint32_t                   pending_no_cb;
+
+	/* Completed TX for which we need to call the callback */
+	sys_slist_t		tx_complete;
+	//struct k_work           tx_complete_work;
+
+
+	/* Queue for outgoing ACL data */
+	struct k_fifo		tx_queue;
+
+	/* Active L2CAP/ISO channels */
+	sys_slist_t		channels;
+
+	atomic_t		ref;
+
+	/* Delayed work for connection update and other deferred tasks */
+	//struct k_delayed_work	update_work;
+
+	union {
+		struct bt_conn_le	le;
+#if defined(CONFIG_BT_BREDR)
+		struct bt_conn_br	br;
+		struct bt_conn_sco	sco;
+#endif
+#if defined(CONFIG_BT_AUDIO)
+		struct bt_conn_iso	iso;
+#endif
+	};
+
+#if defined(CONFIG_BT_REMOTE_VERSION)
+	struct bt_conn_rv {
+		uint8_t  version;
+		uint16_t manufacturer;
+		uint16_t subversion;
+	} rv;
+#endif
+};
+
+void bt_conn_reset_rx_state(struct bt_conn *conn);
+
+/* Process incoming data for a connection */
+void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags);
+
+/* Send data over a connection */
+int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf,
+		    bt_conn_tx_cb_t cb, void *user_data);
+
+static inline int bt_conn_send(struct bt_conn *conn, struct net_buf *buf)
+{
+	return bt_conn_send_cb(conn, buf, NULL, NULL);
+}
+
+/* Check if a connection object with the peer already exists */
+bool bt_conn_exists_le(uint8_t id, const bt_addr_le_t *peer);
+
+/* Add a new LE connection */
+struct bt_conn *bt_conn_add_le(uint8_t id, const bt_addr_le_t *peer);
+
+/** Connection parameters for ISO connections */
+struct bt_iso_create_param {
+	uint8_t			id;
+	uint8_t			num_conns;
+	struct bt_conn		**conns;
+	struct bt_iso_chan	**chans;
+};
+
+/* Bind ISO connections parameters */
+int bt_conn_bind_iso(struct bt_iso_create_param *param);
+
+/* Connect ISO connections */
+int bt_conn_connect_iso(struct bt_conn **conns, uint8_t num_conns);
+
+/* Add a new ISO connection */
+struct bt_conn *bt_conn_add_iso(struct bt_conn *acl);
+
+/* Cleanup ISO references */
+void bt_iso_cleanup(struct bt_conn *iso_conn);
+
+/* Add a new BR/EDR connection */
+struct bt_conn *bt_conn_add_br(const bt_addr_t *peer);
+
+/* Add a new SCO connection */
+struct bt_conn *bt_conn_add_sco(const bt_addr_t *peer, int link_type);
+
+/* Cleanup SCO references */
+void bt_sco_cleanup(struct bt_conn *sco_conn);
+
+/* Look up an existing sco connection by BT address */
+struct bt_conn *bt_conn_lookup_addr_sco(const bt_addr_t *peer);
+
+/* Look up an existing connection by BT address */
+struct bt_conn *bt_conn_lookup_addr_br(const bt_addr_t *peer);
+
+void bt_conn_disconnect_all(uint8_t id);
+
+/* Allocate new connection object */
+struct bt_conn *bt_conn_new(struct bt_conn *conns, size_t size);
+
+/* Look up an existing connection */
+struct bt_conn *bt_conn_lookup_handle(uint16_t handle);
+
+static inline bool bt_conn_is_handle_valid(struct bt_conn *conn)
+{
+	switch (conn->state) {
+	case BT_CONN_CONNECTED:
+	case BT_CONN_DISCONNECT:
+	case BT_CONN_DISCONNECT_COMPLETE:
+		return true;
+	case BT_CONN_CONNECT:
+		/* ISO connection handle assigned at connect state */
+		if (IS_ENABLED(CONFIG_BT_ISO) &&
+		    conn->type == BT_CONN_TYPE_ISO) {
+			return true;
+		}
+	__fallthrough;
+	default:
+		return false;
+	}
+}
+
+/* Check if the connection is with the given peer. */
+bool bt_conn_is_peer_addr_le(const struct bt_conn *conn, uint8_t id,
+			     const bt_addr_le_t *peer);
+
+/* Helpers for identifying & looking up connections based on the the index to
+ * the connection list. This is useful for O(1) lookups, but can't be used
+ * e.g. as the handle since that's assigned to us by the controller.
+ */
+#define BT_CONN_INDEX_INVALID 0xff
+struct bt_conn *bt_conn_lookup_index(uint8_t index);
+
+/* Look up a connection state. For BT_ADDR_LE_ANY, returns the first connection
+ * with the specific state
+ */
+struct bt_conn *bt_conn_lookup_state_le(uint8_t id, const bt_addr_le_t *peer,
+					const bt_conn_state_t state);
+
+/* Set connection object in certain state and perform action related to state */
+void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state);
+
+int bt_conn_le_conn_update(struct bt_conn *conn,
+			   const struct bt_le_conn_param *param);
+
+void notify_remote_info(struct bt_conn *conn);
+
+void notify_le_param_updated(struct bt_conn *conn);
+
+void notify_le_data_len_updated(struct bt_conn *conn);
+
+void notify_le_phy_updated(struct bt_conn *conn);
+
+bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
+
+#if defined(CONFIG_BT_SMP)
+/* rand and ediv should be in BT order */
+int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8],
+				uint8_t ediv[2], const uint8_t *ltk, size_t len);
+
+/* Notify higher layers that RPA was resolved */
+void bt_conn_identity_resolved(struct bt_conn *conn);
+#endif /* CONFIG_BT_SMP */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+/* Notify higher layers that connection security changed */
+void bt_conn_security_changed(struct bt_conn *conn, uint8_t hci_err,
+			      enum bt_security_err err);
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+/* Prepare a PDU to be sent over a connection */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_conn_create_pdu_timeout_debug(struct net_buf_pool *pool,
+						 size_t reserve,
+						 k_timeout_t timeout,
+						 const char *func, int line);
+#define bt_conn_create_pdu_timeout(_pool, _reserve, _timeout) \
+	bt_conn_create_pdu_timeout_debug(_pool, _reserve, _timeout, \
+					 __func__, __LINE__)
+
+#define bt_conn_create_pdu(_pool, _reserve) \
+	bt_conn_create_pdu_timeout_debug(_pool, _reserve, K_FOREVER, \
+					 __func__, __line__)
+#else
+struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
+					   size_t reserve, k_timeout_t timeout);
+
+#define bt_conn_create_pdu(_pool, _reserve) \
+	bt_conn_create_pdu_timeout(_pool, _reserve, K_FOREVER)
+#endif
+
+/* Prepare a PDU to be sent over a connection */
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *bt_conn_create_frag_timeout_debug(size_t reserve,
+						  k_timeout_t timeout,
+						  const char *func, int line);
+
+#define bt_conn_create_frag_timeout(_reserve, _timeout) \
+	bt_conn_create_frag_timeout_debug(_reserve, _timeout, \
+					  __func__, __LINE__)
+
+#define bt_conn_create_frag(_reserve) \
+	bt_conn_create_frag_timeout_debug(_reserve, K_FOREVER, \
+					  __func__, __LINE__)
+#else
+struct net_buf *bt_conn_create_frag_timeout(size_t reserve,
+					    k_timeout_t timeout);
+
+#define bt_conn_create_frag(_reserve) \
+	bt_conn_create_frag_timeout(_reserve, K_FOREVER)
+#endif
+
+/* Initialize connection management */
+int bt_conn_init(void);
+
+/* Selects based on connecton type right semaphore for ACL packets */
+struct k_sem *bt_conn_get_pkts(struct bt_conn *conn);
+
+/* k_poll related helpers for the TX thread */
+int bt_conn_prepare_events(struct k_poll_event events[]);
+void bt_conn_process_tx(struct bt_conn *conn);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.h	(working copy)
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2016-2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int prng_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/crypto.c	(working copy)
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include <zephyr.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/crypto.h>
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/hmac_prng.h>
+#include <tinycrypt/aes.h>
+#include <tinycrypt/utils.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_crypto
+#include "common/log.h"
+
+#include "hci_core.h"
+
+static struct tc_hmac_prng_struct prng;
+
+static int prng_reseed(struct tc_hmac_prng_struct *h)
+{
+	uint8_t seed[32];
+	int64_t extra;
+	size_t i;
+	int ret;
+
+	for (i = 0; i < (sizeof(seed) / 8); i++) {
+		struct bt_hci_rp_le_rand *rp;
+		struct net_buf *rsp;
+
+		ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
+		if (ret) {
+			return ret;
+		}
+
+		rp = (void *)rsp->data;
+		memcpy(&seed[i * 8], rp->rand, 8);
+
+		net_buf_unref(rsp);
+	}
+
+	extra = k_uptime_get();
+
+	ret = tc_hmac_prng_reseed(h, seed, sizeof(seed), (uint8_t *)&extra,
+				  sizeof(extra));
+	if (ret == TC_CRYPTO_FAIL) {
+		BT_ERR("Failed to re-seed PRNG");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int prng_init(void)
+{
+	struct bt_hci_rp_le_rand *rp;
+	struct net_buf *rsp;
+	int ret;
+
+	/* Check first that HCI_LE_Rand is supported */
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 7)) {
+		return -ENOTSUP;
+	}
+
+	ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
+	if (ret) {
+		return ret;
+	}
+
+	rp = (void *)rsp->data;
+
+	ret = tc_hmac_prng_init(&prng, rp->rand, sizeof(rp->rand));
+
+	net_buf_unref(rsp);
+
+	if (ret == TC_CRYPTO_FAIL) {
+		BT_ERR("Failed to initialize PRNG");
+		return -EIO;
+	}
+
+	/* re-seed is needed after init */
+	return prng_reseed(&prng);
+}
+
+int bt_rand(void *buf, size_t len)
+{
+	int ret;
+
+	ret = tc_hmac_prng_generate(buf, len, &prng);
+	if (ret == TC_HMAC_PRNG_RESEED_REQ) {
+		ret = prng_reseed(&prng);
+		if (ret) {
+			return ret;
+		}
+
+		ret = tc_hmac_prng_generate(buf, len, &prng);
+	}
+
+	if (ret == TC_CRYPTO_SUCCESS) {
+		return 0;
+	}
+
+	return -EIO;
+}
+
+int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16])
+{
+	struct tc_aes_key_sched_struct s;
+	uint8_t tmp[16];
+
+	BT_DBG("key %s", bt_hex(key, 16));
+	BT_DBG("plaintext %s", bt_hex(plaintext, 16));
+
+	sys_memcpy_swap(tmp, key, 16);
+
+	if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
+		return -EINVAL;
+	}
+
+	sys_memcpy_swap(tmp, plaintext, 16);
+
+	if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
+		return -EINVAL;
+	}
+
+	sys_mem_swap(enc_data, 16);
+
+	BT_DBG("enc_data %s", bt_hex(enc_data, 16));
+
+	return 0;
+}
+
+int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
+		  uint8_t enc_data[16])
+{
+	struct tc_aes_key_sched_struct s;
+
+	BT_DBG("key %s", bt_hex(key, 16));
+	BT_DBG("plaintext %s", bt_hex(plaintext, 16));
+
+	if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
+		return -EINVAL;
+	}
+
+	if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
+		return -EINVAL;
+	}
+
+	BT_DBG("enc_data %s", bt_hex(enc_data, 16));
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ecc.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ecc.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ecc.h	(working copy)
@@ -0,0 +1,63 @@
+/* ecc.h - ECDH helpers */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*  @brief Container for public key callback */
+struct bt_pub_key_cb {
+	/** @brief Callback type for Public Key generation.
+	 *
+	 *  Used to notify of the local public key or that the local key is not
+	 *  available (either because of a failure to read it or because it is
+	 *  being regenerated).
+	 *
+	 *  @param key The local public key, or NULL in case of no key.
+	 */
+	void (*func)(const uint8_t key[64]);
+
+	struct bt_pub_key_cb *_next;
+};
+
+/*  @brief Generate a new Public Key.
+ *
+ *  Generate a new ECC Public Key. The callback will persist even after the
+ *  key has been generated, and will be used to notify of new generation
+ *  processes (NULL as key).
+ *
+ *  @param cb Callback to notify the new key, or NULL to request an update
+ *            without registering any new callback.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_pub_key_gen(struct bt_pub_key_cb *cb);
+
+/*  @brief Get the current Public Key.
+ *
+ *  Get the current ECC Public Key.
+ *
+ *  @return Current key, or NULL if not available.
+ */
+const uint8_t *bt_pub_key_get(void);
+
+/*  @typedef bt_dh_key_cb_t
+ *  @brief Callback type for DH Key calculation.
+ *
+ *  Used to notify of the calculated DH Key.
+ *
+ *  @param key The DH Key, or NULL in case of failure.
+ */
+typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]);
+
+/*  @brief Calculate a DH Key from a remote Public Key.
+ *
+ *  Calculate a DH Key from the remote Public Key.
+ *
+ *  @param remote_pk Remote Public Key.
+ *  @param cb Callback to notify the calculated key.
+ *
+ *  @return Zero on success or negative error code otherwise
+ */
+int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt.c	(working copy)
@@ -0,0 +1,5082 @@
+/* gatt.c - Generic Attribute Profile handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+
+#if defined(CONFIG_BT_GATT_CACHING)
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/aes.h>
+#include <tinycrypt/cmac_mode.h>
+#include <tinycrypt/ccm_mode.h>
+#endif /* CONFIG_BT_GATT_CACHING */
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_GATT)
+#define LOG_MODULE_NAME bt_gatt
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "keys.h"
+#include "l2cap_internal.h"
+#include "att_internal.h"
+#include "smp.h"
+#include "settings.h"
+#include "gatt_internal.h"
+
+#define SC_TIMEOUT	K_MSEC(10)
+#define CCC_STORE_DELAY	K_SECONDS(1)
+
+#define DB_HASH_TIMEOUT	K_MSEC(10)
+
+static uint16_t last_static_handle;
+
+/* Persistent storage format for GATT CCC */
+struct ccc_store {
+	uint16_t handle;
+	uint16_t value;
+};
+
+struct gatt_sub {
+	uint8_t id;
+	bt_addr_le_t peer;
+	sys_slist_t list;
+};
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+#define SUB_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
+#else
+#define SUB_MAX 0
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+static struct gatt_sub subscriptions[SUB_MAX];
+
+static const uint16_t gap_appearance = CONFIG_BT_DEVICE_APPEARANCE;
+
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+static sys_slist_t db;
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+
+static atomic_t init;
+
+static ssize_t read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 void *buf, uint16_t len, uint16_t offset)
+{
+	const char *name = bt_get_name();
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, name,
+				 strlen(name));
+}
+
+#if defined(CONFIG_BT_DEVICE_NAME_GATT_WRITABLE)
+
+static ssize_t write_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 const void *buf, uint16_t len, uint16_t offset,
+			 uint8_t flags)
+{
+	char value[CONFIG_BT_DEVICE_NAME_MAX] = {};
+
+	if (offset) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	if (len >= sizeof(value)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
+	}
+
+	memcpy(value, buf, len);
+
+	bt_set_name(value);
+
+	return len;
+}
+
+#endif /* CONFIG_BT_DEVICE_NAME_GATT_WRITABLE */
+
+static ssize_t read_appearance(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, void *buf,
+			       uint16_t len, uint16_t offset)
+{
+	uint16_t appearance = sys_cpu_to_le16(gap_appearance);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance,
+				 sizeof(appearance));
+}
+
+#if defined (CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
+/* This checks if the range entered is valid */
+BUILD_ASSERT(!(CONFIG_BT_PERIPHERAL_PREF_MIN_INT > 3200 &&
+	     CONFIG_BT_PERIPHERAL_PREF_MIN_INT < 0xffff));
+BUILD_ASSERT(!(CONFIG_BT_PERIPHERAL_PREF_MAX_INT > 3200 &&
+	     CONFIG_BT_PERIPHERAL_PREF_MAX_INT < 0xffff));
+BUILD_ASSERT(!(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT > 3200 &&
+	     CONFIG_BT_PERIPHERAL_PREF_TIMEOUT < 0xffff));
+BUILD_ASSERT((CONFIG_BT_PERIPHERAL_PREF_MIN_INT == 0xffff) ||
+	     (CONFIG_BT_PERIPHERAL_PREF_MIN_INT <=
+	     CONFIG_BT_PERIPHERAL_PREF_MAX_INT));
+
+static ssize_t read_ppcp(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 void *buf, uint16_t len, uint16_t offset)
+{
+	struct __packed {
+		uint16_t min_int;
+		uint16_t max_int;
+		uint16_t latency;
+		uint16_t timeout;
+	} ppcp;
+
+	ppcp.min_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MIN_INT);
+	ppcp.max_int = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_MAX_INT);
+	ppcp.latency = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_SLAVE_LATENCY);
+	ppcp.timeout = sys_cpu_to_le16(CONFIG_BT_PERIPHERAL_PREF_TIMEOUT);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &ppcp,
+				 sizeof(ppcp));
+}
+#endif
+
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PRIVACY)
+static ssize_t read_central_addr_res(struct bt_conn *conn,
+				     const struct bt_gatt_attr *attr, void *buf,
+				     uint16_t len, uint16_t offset)
+{
+	uint8_t central_addr_res = BT_GATT_CENTRAL_ADDR_RES_SUPP;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset,
+				 &central_addr_res, sizeof(central_addr_res));
+}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_PRIVACY */
+
+BT_GATT_SERVICE_DEFINE(_2_gap_svc,
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_GAP),
+#if defined(CONFIG_BT_DEVICE_NAME_GATT_WRITABLE)
+	/* Require pairing for writes to device name */
+	BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME,
+			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
+			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT,
+			       read_name, write_name, bt_dev.name),
+#else
+	BT_GATT_CHARACTERISTIC(BT_UUID_GAP_DEVICE_NAME, BT_GATT_CHRC_READ,
+			       BT_GATT_PERM_READ, read_name, NULL, NULL),
+#endif /* CONFIG_BT_DEVICE_NAME_GATT_WRITABLE */
+	BT_GATT_CHARACTERISTIC(BT_UUID_GAP_APPEARANCE, BT_GATT_CHRC_READ,
+			       BT_GATT_PERM_READ, read_appearance, NULL, NULL),
+#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PRIVACY)
+	BT_GATT_CHARACTERISTIC(BT_UUID_CENTRAL_ADDR_RES,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_central_addr_res, NULL, NULL),
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_PRIVACY */
+#if defined(CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS)
+	BT_GATT_CHARACTERISTIC(BT_UUID_GAP_PPCP, BT_GATT_CHRC_READ,
+			       BT_GATT_PERM_READ, read_ppcp, NULL, NULL),
+#endif
+);
+
+struct sc_data {
+	uint16_t start;
+	uint16_t end;
+} __packed;
+
+struct gatt_sc_cfg {
+	uint8_t		id;
+	bt_addr_le_t	peer;
+	struct {
+		uint16_t		start;
+		uint16_t		end;
+	} data;
+};
+
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+#define SC_CFG_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
+#else
+#define SC_CFG_MAX 0
+#endif
+static struct gatt_sc_cfg sc_cfg[SC_CFG_MAX];
+BUILD_ASSERT(sizeof(struct sc_data) == sizeof(sc_cfg[0].data));
+
+static struct gatt_sc_cfg *find_sc_cfg(uint8_t id, bt_addr_le_t *addr)
+{
+	BT_DBG("id: %u, addr: %s", id, bt_addr_le_str(addr));
+
+	for (size_t i = 0; i < ARRAY_SIZE(sc_cfg); i++) {
+		if (id == sc_cfg[i].id &&
+		    !bt_addr_le_cmp(&sc_cfg[i].peer, addr)) {
+			return &sc_cfg[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void sc_store(struct gatt_sc_cfg *cfg)
+{
+	char key[BT_SETTINGS_KEY_MAX];
+	int err;
+
+	if (cfg->id) {
+		char id_str[4];
+
+		//u8_to_dec(id_str, sizeof(id_str), cfg->id);
+		//bt_settings_encode_key(key, sizeof(key), "sc",
+		//		       &cfg->peer, id_str);
+	} else {
+		//bt_settings_encode_key(key, sizeof(key), "sc",
+		//		       &cfg->peer, NULL);
+	}
+
+	//err = settings_save_one(key, (char *)&cfg->data, sizeof(cfg->data));
+	if (err) {
+		BT_ERR("failed to store SC (err %d)", err);
+		return;
+	}
+
+	BT_DBG("stored SC for %s (%s, 0x%04x-0x%04x)",
+	       bt_addr_le_str(&cfg->peer), log_strdup(key), cfg->data.start,
+	       cfg->data.end);
+}
+
+static void clear_sc_cfg(struct gatt_sc_cfg *cfg)
+{
+	memset(cfg, 0, sizeof(*cfg));
+}
+
+static int bt_gatt_clear_sc(uint8_t id, const bt_addr_le_t *addr)
+{
+
+	struct gatt_sc_cfg *cfg;
+
+	cfg = find_sc_cfg(id, (bt_addr_le_t *)addr);
+	if (!cfg) {
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		char key[BT_SETTINGS_KEY_MAX];
+		int err;
+
+		if (cfg->id) {
+			char id_str[4];
+
+			//u8_to_dec(id_str, sizeof(id_str), cfg->id);
+			//bt_settings_encode_key(key, sizeof(key), "sc",
+			//		       &cfg->peer, id_str);
+		} else {
+			//bt_settings_encode_key(key, sizeof(key), "sc",
+			//		       &cfg->peer, NULL);
+		}
+
+		err = settings_delete(key);
+		if (err) {
+			BT_ERR("failed to delete SC (err %d)", err);
+		} else {
+			BT_DBG("deleted SC for %s (%s)",
+			       bt_addr_le_str(&cfg->peer),
+			       log_strdup(key));
+		}
+	}
+
+	clear_sc_cfg(cfg);
+
+	return 0;
+}
+
+static void sc_clear(struct bt_conn *conn)
+{
+	if (bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		int err;
+
+		err = bt_gatt_clear_sc(conn->id, &conn->le.dst);
+		if (err) {
+			BT_ERR("Failed to clear SC %d", err);
+		}
+	} else {
+		struct gatt_sc_cfg *cfg;
+
+		cfg = find_sc_cfg(conn->id, &conn->le.dst);
+		if (cfg) {
+			clear_sc_cfg(cfg);
+		}
+	}
+}
+
+static void sc_reset(struct gatt_sc_cfg *cfg)
+{
+	BT_DBG("peer %s", bt_addr_le_str(&cfg->peer));
+
+	memset(&cfg->data, 0, sizeof(cfg->data));
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		sc_store(cfg);
+	}
+}
+
+static bool update_range(uint16_t *start, uint16_t *end, uint16_t new_start,
+			 uint16_t new_end)
+{
+	BT_DBG("start 0x%04x end 0x%04x new_start 0x%04x new_end 0x%04x",
+	       *start, *end, new_start, new_end);
+
+	/* Check if inside existing range */
+	if (new_start >= *start && new_end <= *end) {
+		return false;
+	}
+
+	/* Update range */
+	if (*start > new_start) {
+		*start = new_start;
+	}
+
+	if (*end < new_end) {
+		*end = new_end;
+	}
+
+	return true;
+}
+
+static void sc_save(uint8_t id, bt_addr_le_t *peer, uint16_t start, uint16_t end)
+{
+	struct gatt_sc_cfg *cfg;
+	bool modified = false;
+
+	BT_DBG("peer %s start 0x%04x end 0x%04x", bt_addr_le_str(peer), start,
+	       end);
+
+	cfg = find_sc_cfg(id, peer);
+	if (!cfg) {
+		/* Find and initialize a free sc_cfg entry */
+		cfg = find_sc_cfg(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
+		if (!cfg) {
+			BT_ERR("unable to save SC: no cfg left");
+			return;
+		}
+
+		cfg->id = id;
+		bt_addr_le_copy(&cfg->peer, peer);
+	}
+
+	/* Check if there is any change stored */
+	if (!(cfg->data.start || cfg->data.end)) {
+		cfg->data.start = start;
+		cfg->data.end = end;
+		modified = true;
+		goto done;
+	}
+
+	modified = update_range(&cfg->data.start, &cfg->data.end, start, end);
+
+done:
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+	    modified && bt_addr_le_is_bonded(cfg->id, &cfg->peer)) {
+		sc_store(cfg);
+	}
+}
+
+static ssize_t sc_ccc_cfg_write(struct bt_conn *conn,
+				const struct bt_gatt_attr *attr, uint16_t value)
+{
+	BT_DBG("value 0x%04x", value);
+
+	if (value == BT_GATT_CCC_INDICATE) {
+		/* Create a new SC configuration entry if subscribed */
+		sc_save(conn->id, &conn->le.dst, 0, 0);
+	} else {
+		sc_clear(conn);
+	}
+
+	return sizeof(value);
+}
+
+static struct _bt_gatt_ccc sc_ccc = BT_GATT_CCC_INITIALIZER(NULL,
+							    sc_ccc_cfg_write,
+							    NULL);
+
+enum {
+	CF_CHANGE_AWARE,	/* Client is changed aware */
+	CF_OUT_OF_SYNC,		/* Client is out of sync */
+
+	/* Total number of flags - must be at the end of the enum */
+	CF_NUM_FLAGS,
+};
+
+#define CF_BIT_ROBUST_CACHING	0
+#define CF_BIT_EATT		1
+#define CF_BIT_NOTIFY_MULTI	2
+#define CF_BIT_LAST		CF_BIT_NOTIFY_MULTI
+
+#define CF_BYTE_LAST		(CF_BIT_LAST % 8)
+
+#define CF_ROBUST_CACHING(_cfg) (_cfg->data[0] & BIT(CF_BIT_ROBUST_CACHING))
+#define CF_EATT(_cfg) (_cfg->data[0] & BIT(CF_BIT_EATT))
+#define CF_NOTIFY_MULTI(_cfg) (_cfg->data[0] & BIT(CF_BIT_NOTIFY_MULTI))
+
+struct gatt_cf_cfg {
+	uint8_t                    id;
+	bt_addr_le_t		peer;
+	uint8_t			data[1];
+	ATOMIC_DEFINE(flags, CF_NUM_FLAGS);
+};
+
+#if defined(CONFIG_BT_GATT_CACHING)
+#define CF_CFG_MAX (CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN)
+#else
+#define CF_CFG_MAX 0
+#endif /* CONFIG_BT_GATT_CACHING */
+
+static struct gatt_cf_cfg cf_cfg[CF_CFG_MAX] = {};
+
+static void clear_cf_cfg(struct gatt_cf_cfg *cfg)
+{
+	bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY);
+	memset(cfg->data, 0, sizeof(cfg->data));
+	atomic_set(cfg->flags, 0);
+}
+
+#if defined(CONFIG_BT_GATT_CACHING)
+static struct gatt_cf_cfg *find_cf_cfg(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cf_cfg); i++) {
+		struct gatt_cf_cfg *cfg = &cf_cfg[i];
+
+		if (!conn) {
+			if (!bt_addr_le_cmp(&cfg->peer, BT_ADDR_LE_ANY)) {
+				return cfg;
+			}
+		} else if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) {
+			return cfg;
+		}
+	}
+
+	return NULL;
+}
+
+static ssize_t cf_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+		       void *buf, uint16_t len, uint16_t offset)
+{
+	struct gatt_cf_cfg *cfg;
+	uint8_t data[1] = {};
+
+	cfg = find_cf_cfg(conn);
+	if (cfg) {
+		memcpy(data, cfg->data, sizeof(data));
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, data,
+				 sizeof(data));
+}
+
+static bool cf_set_value(struct gatt_cf_cfg *cfg, const uint8_t *value, uint16_t len)
+{
+	uint16_t i;
+	uint8_t last_byte = CF_BYTE_LAST;
+	uint8_t last_bit = CF_BIT_LAST;
+
+	/* Validate the bits */
+	for (i = 0U; i < len && i <= last_byte; i++) {
+		uint8_t chg_bits = value[i] ^ cfg->data[i];
+		uint8_t bit;
+
+		for (bit = 0U; bit <= last_bit; bit++) {
+			/* A client shall never clear a bit it has set */
+			if ((BIT(bit) & chg_bits) &&
+			    (BIT(bit) & cfg->data[i])) {
+				return false;
+			}
+		}
+	}
+
+	/* Set the bits for each octect */
+	for (i = 0U; i < len && i < last_byte; i++) {
+		cfg->data[i] |= value[i] & (BIT(last_bit + 1) - 1);
+		BT_DBG("byte %u: data 0x%02x value 0x%02x", i, cfg->data[i],
+		       value[i]);
+	}
+
+	return true;
+}
+
+static ssize_t cf_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
+{
+	struct gatt_cf_cfg *cfg;
+	const uint8_t *value = buf;
+
+	if (offset > sizeof(cfg->data)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	if (offset + len > sizeof(cfg->data)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
+	}
+
+	cfg = find_cf_cfg(conn);
+	if (!cfg) {
+		cfg = find_cf_cfg(NULL);
+	}
+
+	if (!cfg) {
+		BT_WARN("No space to store Client Supported Features");
+		return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
+	}
+
+	BT_DBG("handle 0x%04x len %u", attr->handle, len);
+
+	if (!cf_set_value(cfg, value, len)) {
+		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
+	}
+
+	bt_addr_le_copy(&cfg->peer, &conn->le.dst);
+	cfg->id = conn->id;
+	atomic_set_bit(cfg->flags, CF_CHANGE_AWARE);
+
+	return len;
+}
+
+static uint8_t db_hash[16];
+struct k_delayed_work db_hash_work;
+
+struct gen_hash_state {
+	struct tc_cmac_struct state;
+	int err;
+};
+
+static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	struct gen_hash_state *state = user_data;
+	struct bt_uuid_16 *u16;
+	uint8_t data[16];
+	ssize_t len;
+	uint16_t value;
+
+	if (attr->uuid->type != BT_UUID_TYPE_16)
+		return BT_GATT_ITER_CONTINUE;
+
+	u16 = (struct bt_uuid_16 *)attr->uuid;
+
+	switch (u16->val) {
+	/* Attributes to hash: handle + UUID + value */
+	case 0x2800: /* GATT Primary Service */
+	case 0x2801: /* GATT Secondary Service */
+	case 0x2802: /* GATT Include Service */
+	case 0x2803: /* GATT Characteristic */
+	case 0x2900: /* GATT Characteristic Extended Properties */
+		value = sys_cpu_to_le16(handle);
+		if (tc_cmac_update(&state->state, (uint8_t *)&value,
+				   sizeof(handle)) == TC_CRYPTO_FAIL) {
+			state->err = -EINVAL;
+			return BT_GATT_ITER_STOP;
+		}
+
+		value = sys_cpu_to_le16(u16->val);
+		if (tc_cmac_update(&state->state, (uint8_t *)&value,
+				   sizeof(u16->val)) == TC_CRYPTO_FAIL) {
+			state->err = -EINVAL;
+			return BT_GATT_ITER_STOP;
+		}
+
+		len = attr->read(NULL, attr, data, sizeof(data), 0);
+		if (len < 0) {
+			state->err = len;
+			return BT_GATT_ITER_STOP;
+		}
+
+		if (tc_cmac_update(&state->state, data, len) ==
+		    TC_CRYPTO_FAIL) {
+			state->err = -EINVAL;
+			return BT_GATT_ITER_STOP;
+		}
+
+		break;
+	/* Attributes to hash: handle + UUID */
+	case 0x2901: /* GATT Characteristic User Descriptor */
+	case 0x2902: /* GATT Client Characteristic Configuration */
+	case 0x2903: /* GATT Server Characteristic Configuration */
+	case 0x2904: /* GATT Characteristic Presentation Format */
+	case 0x2905: /* GATT Characteristic Aggregated Format */
+		value = sys_cpu_to_le16(handle);
+		if (tc_cmac_update(&state->state, (uint8_t *)&value,
+				   sizeof(handle)) == TC_CRYPTO_FAIL) {
+			state->err = -EINVAL;
+			return BT_GATT_ITER_STOP;
+		}
+
+		value = sys_cpu_to_le16(u16->val);
+		if (tc_cmac_update(&state->state, (uint8_t *)&value,
+				   sizeof(u16->val)) == TC_CRYPTO_FAIL) {
+			state->err = -EINVAL;
+			return BT_GATT_ITER_STOP;
+		}
+		break;
+	default:
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static void db_hash_store(void)
+{
+	int err;
+
+	//err = settings_save_one("bt/hash", &db_hash, sizeof(db_hash));
+	if (err) {
+		BT_ERR("Failed to save Database Hash (err %d)", err);
+	}
+
+	BT_DBG("Database Hash stored");
+}
+
+/* Once the db_hash work has started we cannot cancel it anymore, so the
+ * assumption is made that the in-progress work cannot be pre-empted.
+ * This assumption should hold as long as calculation does not make any calls
+ * that would make it unready.
+ * If this assumption is no longer true we will have to solve the case where
+ * k_delayed_work_cancel failed because the work was in-progress but pre-empted.
+ */
+static void db_hash_gen(bool store)
+{
+	uint8_t key[16] = {};
+	struct tc_aes_key_sched_struct sched;
+	struct gen_hash_state state;
+
+	if (tc_cmac_setup(&state.state, key, &sched) == TC_CRYPTO_FAIL) {
+		BT_ERR("Unable to setup AES CMAC");
+		return;
+	}
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, gen_hash_m, &state);
+
+	if (tc_cmac_final(db_hash, &state.state) == TC_CRYPTO_FAIL) {
+		BT_ERR("Unable to calculate hash");
+		return;
+	}
+
+	/**
+	 * Core 5.1 does not state the endianess of the hash.
+	 * However Vol 3, Part F, 3.3.1 says that multi-octet Characteristic
+	 * Values shall be LE unless otherwise defined. PTS expects hash to be
+	 * in little endianess as well. bt_smp_aes_cmac calculates the hash in
+	 * big endianess so we have to swap.
+	 */
+	sys_mem_swap(db_hash, sizeof(db_hash));
+
+	BT_HEXDUMP_DBG(db_hash, sizeof(db_hash), "Hash: ");
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		db_hash_store();
+	}
+}
+
+static void db_hash_process(struct k_work *work)
+{
+	db_hash_gen(true);
+}
+
+static ssize_t db_hash_read(struct bt_conn *conn,
+			    const struct bt_gatt_attr *attr,
+			    void *buf, uint16_t len, uint16_t offset)
+{
+	int err;
+
+	/* Check if db_hash is already pending in which case it shall be
+	 * generated immediately instead of waiting for the work to complete.
+	 */
+	err = k_delayed_work_cancel(&db_hash_work);
+	if (!err) {
+		db_hash_gen(true);
+	}
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2347:
+	 * 2.5.2.1 Robust Caching
+	 * A connected client becomes change-aware when...
+	 * The client reads the Database Hash characteristic and then the server
+	 * receives another ATT request from the client.
+	 */
+	bt_gatt_change_aware(conn, true);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, db_hash,
+				 sizeof(db_hash));
+}
+
+static void remove_cf_cfg(struct bt_conn *conn)
+{
+	struct gatt_cf_cfg *cfg;
+
+	cfg = find_cf_cfg(conn);
+	if (!cfg) {
+		return;
+	}
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2405:
+	 * For clients with a trusted relationship, the characteristic value
+	 * shall be persistent across connections. For clients without a
+	 * trusted relationship the characteristic value shall be set to the
+	 * default value at each connection.
+	 */
+	if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		clear_cf_cfg(cfg);
+	} else {
+		/* Update address in case it has changed */
+		bt_addr_le_copy(&cfg->peer, &conn->le.dst);
+		atomic_clear_bit(cfg->flags, CF_OUT_OF_SYNC);
+	}
+}
+
+#if defined(CONFIG_BT_EATT)
+#define SF_BIT_EATT	0
+#define SF_BIT_LAST	SF_BIT_EATT
+
+static ssize_t sf_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+		       void *buf, uint16_t len, uint16_t offset)
+{
+	uint8_t value = BIT(SF_BIT_EATT);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &value,
+				 sizeof(value));
+}
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_CACHING */
+
+BT_GATT_SERVICE_DEFINE(_1_gatt_svc,
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_GATT),
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+	/* Bluetooth 5.0, Vol3 Part G:
+	 * The Service Changed characteristic Attribute Handle on the server
+	 * shall not change if the server has a trusted relationship with any
+	 * client.
+	 */
+	BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SC, BT_GATT_CHRC_INDICATE,
+			       BT_GATT_PERM_NONE, NULL, NULL, NULL),
+	BT_GATT_CCC_MANAGED(&sc_ccc, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+#if defined(CONFIG_BT_GATT_CACHING)
+	BT_GATT_CHARACTERISTIC(BT_UUID_GATT_CLIENT_FEATURES,
+			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
+			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
+			       cf_read, cf_write, NULL),
+	BT_GATT_CHARACTERISTIC(BT_UUID_GATT_DB_HASH,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       db_hash_read, NULL, NULL),
+#if defined(CONFIG_BT_EATT)
+	BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SERVER_FEATURES,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       sf_read, NULL, NULL),
+#endif /* CONFIG_BT_EATT */
+#endif /* CONFIG_BT_GATT_CACHING */
+#endif /* CONFIG_BT_GATT_SERVICE_CHANGED */
+);
+
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+static uint8_t found_attr(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	const struct bt_gatt_attr **found = user_data;
+
+	*found = attr;
+
+	return BT_GATT_ITER_STOP;
+}
+
+static const struct bt_gatt_attr *find_attr(uint16_t handle)
+{
+	const struct bt_gatt_attr *attr = NULL;
+
+	bt_gatt_foreach_attr(handle, handle, found_attr, &attr);
+
+	return attr;
+}
+
+static void gatt_insert(struct bt_gatt_service *svc, uint16_t last_handle)
+{
+	struct bt_gatt_service *tmp, *prev = NULL;
+
+	if (last_handle == 0 || svc->attrs[0].handle > last_handle) {
+		sys_slist_append(&db, &svc->node);
+		return;
+	}
+
+	/* DB shall always have its service in ascending order */
+	SYS_SLIST_FOR_EACH_CONTAINER(&db, tmp, node) {
+		if (tmp->attrs[0].handle > svc->attrs[0].handle) {
+			if (prev) {
+				sys_slist_insert(&db, &prev->node, &svc->node);
+			} else {
+				sys_slist_prepend(&db, &svc->node);
+			}
+			return;
+		}
+
+		prev = tmp;
+	}
+}
+
+static int gatt_register(struct bt_gatt_service *svc)
+{
+	struct bt_gatt_service *last;
+	uint16_t handle, last_handle;
+	struct bt_gatt_attr *attrs = svc->attrs;
+	uint16_t count = svc->attr_count;
+
+	if (sys_slist_is_empty(&db)) {
+		handle = last_static_handle;
+		last_handle = 0;
+		goto populate;
+	}
+
+	last = SYS_SLIST_PEEK_TAIL_CONTAINER(&db, last, node);
+	handle = last->attrs[last->attr_count - 1].handle;
+	last_handle = handle;
+
+populate:
+	/* Populate the handles and append them to the list */
+	for (; attrs && count; attrs++, count--) {
+		if (!attrs->handle) {
+			/* Allocate handle if not set already */
+			attrs->handle = ++handle;
+		} else if (attrs->handle > handle) {
+			/* Use existing handle if valid */
+			handle = attrs->handle;
+		} else if (find_attr(attrs->handle)) {
+			/* Service has conflicting handles */
+			BT_ERR("Unable to register handle 0x%04x",
+			       attrs->handle);
+			return -EINVAL;
+		}
+
+		BT_DBG("attr %p handle 0x%04x uuid %s perm 0x%02x",
+		       attrs, attrs->handle, bt_uuid_str(attrs->uuid),
+		       attrs->perm);
+	}
+
+	gatt_insert(svc, last_handle);
+
+	return 0;
+}
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+
+enum {
+	SC_RANGE_CHANGED,    /* SC range changed */
+	SC_INDICATE_PENDING, /* SC indicate pending */
+
+	/* Total number of flags - must be at the end of the enum */
+	SC_NUM_FLAGS,
+};
+
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+static struct gatt_sc {
+	struct bt_gatt_indicate_params params;
+	uint16_t start;
+	uint16_t end;
+	struct k_delayed_work work;
+	ATOMIC_DEFINE(flags, SC_NUM_FLAGS);
+} gatt_sc;
+#endif /* defined(CONFIG_BT_GATT_SERVICE_CHANGED) */
+
+static inline void sc_work_submit(k_timeout_t timeout)
+{
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+	k_delayed_work_submit(&gatt_sc.work, timeout);
+#endif
+}
+
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+static void sc_indicate_rsp(struct bt_conn *conn,
+			    const struct bt_gatt_attr *attr, uint8_t err)
+{
+#if defined(CONFIG_BT_GATT_CACHING)
+	struct gatt_cf_cfg *cfg;
+#endif
+
+	BT_DBG("err 0x%02x", err);
+
+	atomic_clear_bit(gatt_sc.flags, SC_INDICATE_PENDING);
+
+	/* Check if there is new change in the meantime */
+	if (atomic_test_bit(gatt_sc.flags, SC_RANGE_CHANGED)) {
+		/* Reschedule without any delay since it is waiting already */
+		sc_work_submit(K_NO_WAIT);
+	}
+
+#if defined(CONFIG_BT_GATT_CACHING)
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2347:
+	 * 2.5.2.1 Robust Caching
+	 * A connected client becomes change-aware when...
+	 * The client receives and confirms a Service Changed indication.
+	 */
+	cfg = find_cf_cfg(conn);
+	if (cfg && CF_ROBUST_CACHING(cfg)) {
+		atomic_set_bit(cfg->flags, CF_CHANGE_AWARE);
+		BT_DBG("%s change-aware", bt_addr_le_str(&cfg->peer));
+	}
+#endif
+}
+
+static void sc_process(struct k_work *work)
+{
+	struct gatt_sc *sc = CONTAINER_OF(work, struct gatt_sc, work);
+	uint16_t sc_range[2];
+
+	__ASSERT(!atomic_test_bit(sc->flags, SC_INDICATE_PENDING),
+		 "Indicate already pending");
+
+	BT_DBG("start 0x%04x end 0x%04x", sc->start, sc->end);
+
+	sc_range[0] = sys_cpu_to_le16(sc->start);
+	sc_range[1] = sys_cpu_to_le16(sc->end);
+
+	atomic_clear_bit(sc->flags, SC_RANGE_CHANGED);
+	sc->start = 0U;
+	sc->end = 0U;
+
+	sc->params.attr = &_1_gatt_svc.attrs[2];
+	sc->params.func = sc_indicate_rsp;
+	sc->params.data = &sc_range[0];
+	sc->params.len = sizeof(sc_range);
+
+	if (bt_gatt_indicate(NULL, &sc->params)) {
+		/* No connections to indicate */
+		return;
+	}
+
+	atomic_set_bit(sc->flags, SC_INDICATE_PENDING);
+}
+#endif /* defined(CONFIG_BT_GATT_SERVICE_CHANGED) */
+
+static void clear_ccc_cfg(struct bt_gatt_ccc_cfg *cfg)
+{
+	bt_addr_le_copy(&cfg->peer, BT_ADDR_LE_ANY);
+	cfg->id = 0U;
+	cfg->value = 0U;
+}
+
+#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE)
+static struct gatt_ccc_store {
+	struct bt_conn *conn_list[CONFIG_BT_MAX_CONN];
+	struct k_delayed_work work;
+} gatt_ccc_store;
+
+static bool gatt_ccc_conn_is_queued(struct bt_conn *conn)
+{
+	return (conn == gatt_ccc_store.conn_list[bt_conn_index(conn)]);
+}
+
+static void gatt_ccc_conn_unqueue(struct bt_conn *conn)
+{
+	uint8_t index = bt_conn_index(conn);
+
+	if (gatt_ccc_store.conn_list[index] != NULL) {
+		bt_conn_unref(gatt_ccc_store.conn_list[index]);
+		gatt_ccc_store.conn_list[index] = NULL;
+	}
+}
+
+static void gatt_ccc_conn_enqueue(struct bt_conn *conn)
+{
+	if ((!gatt_ccc_conn_is_queued(conn)) &&
+	    bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		/* Store the connection with the same index it has in
+		 * the conns array
+		 */
+		gatt_ccc_store.conn_list[bt_conn_index(conn)] =
+			bt_conn_ref(conn);
+
+		k_delayed_work_submit(&gatt_ccc_store.work, CCC_STORE_DELAY);
+	}
+}
+
+static bool gatt_ccc_conn_queue_is_empty(void)
+{
+	for (size_t i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		if (gatt_ccc_store.conn_list[i]) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static void ccc_delayed_store(struct k_work *work)
+{
+	struct gatt_ccc_store *ccc_store =
+		CONTAINER_OF(work, struct gatt_ccc_store, work);
+
+	for (size_t i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		struct bt_conn *conn = ccc_store->conn_list[i];
+
+		if (!conn) {
+			continue;
+		}
+
+		if (bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+			ccc_store->conn_list[i] = NULL;
+			bt_gatt_store_ccc(conn->id, &conn->le.dst);
+			bt_conn_unref(conn);
+		}
+	}
+}
+#endif
+
+void bt_gatt_init(void)
+{
+	if (!atomic_cas(&init, 0, 1)) {
+		return;
+	}
+#if 0
+	Z_STRUCT_SECTION_FOREACH(bt_gatt_service_static, svc) {
+		last_static_handle += svc->attr_count;
+	}
+#endif
+#if defined(CONFIG_BT_GATT_CACHING)
+	k_delayed_work_init(&db_hash_work, db_hash_process);
+
+	/* Submit work to Generate initial hash as there could be static
+	 * services already in the database.
+	 */
+	k_delayed_work_submit(&db_hash_work, DB_HASH_TIMEOUT);
+#endif /* CONFIG_BT_GATT_CACHING */
+
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+	k_delayed_work_init(&gatt_sc.work, sc_process);
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		/* Make sure to not send SC indications until SC
+		 * settings are loaded
+		 */
+		atomic_set_bit(gatt_sc.flags, SC_INDICATE_PENDING);
+	}
+#endif /* defined(CONFIG_BT_GATT_SERVICE_CHANGED) */
+
+#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE)
+	k_delayed_work_init(&gatt_ccc_store.work, ccc_delayed_store);
+#endif
+}
+
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB) || \
+    (defined(CONFIG_BT_GATT_CACHING) && defined(CONFIG_BT_SETTINGS))
+static void sc_indicate(uint16_t start, uint16_t end)
+{
+	BT_DBG("start 0x%04x end 0x%04x", start, end);
+
+	if (!atomic_test_and_set_bit(gatt_sc.flags, SC_RANGE_CHANGED)) {
+		gatt_sc.start = start;
+		gatt_sc.end = end;
+		goto submit;
+	}
+
+	if (!update_range(&gatt_sc.start, &gatt_sc.end, start, end)) {
+		return;
+	}
+
+submit:
+	if (atomic_test_bit(gatt_sc.flags, SC_INDICATE_PENDING)) {
+		BT_DBG("indicate pending, waiting until complete...");
+		return;
+	}
+
+	/* Reschedule since the range has changed */
+	sc_work_submit(SC_TIMEOUT);
+}
+#endif /* BT_GATT_DYNAMIC_DB || (BT_GATT_CACHING && BT_SETTINGS) */
+
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+static void db_changed(void)
+{
+#if defined(CONFIG_BT_GATT_CACHING)
+	int i;
+
+	k_delayed_work_submit(&db_hash_work, DB_HASH_TIMEOUT);
+
+	for (i = 0; i < ARRAY_SIZE(cf_cfg); i++) {
+		struct gatt_cf_cfg *cfg = &cf_cfg[i];
+
+		if (!bt_addr_le_cmp(&cfg->peer, BT_ADDR_LE_ANY)) {
+			continue;
+		}
+
+		if (CF_ROBUST_CACHING(cfg)) {
+			/* Core Spec 5.1 | Vol 3, Part G, 2.5.2.1 Robust Caching
+			 *... the database changes again before the client
+			 * becomes change-aware in which case the error response
+			 * shall be sent again.
+			 */
+			atomic_clear_bit(cfg->flags, CF_OUT_OF_SYNC);
+			if (atomic_test_and_clear_bit(cfg->flags,
+						      CF_CHANGE_AWARE)) {
+				BT_DBG("%s change-unaware",
+				       bt_addr_le_str(&cfg->peer));
+			}
+		}
+	}
+#endif
+}
+
+static void gatt_unregister_ccc(struct _bt_gatt_ccc *ccc)
+{
+	ccc->value = 0;
+
+	for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+
+		if (bt_addr_le_cmp(&cfg->peer, BT_ADDR_LE_ANY)) {
+			struct bt_conn *conn;
+			bool store = true;
+
+			conn = bt_conn_lookup_addr_le(cfg->id, &cfg->peer);
+			if (conn) {
+				if (conn->state == BT_CONN_CONNECTED) {
+#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE)
+					gatt_ccc_conn_enqueue(conn);
+#endif
+					store = false;
+				}
+
+				bt_conn_unref(conn);
+			}
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS) && store &&
+			    bt_addr_le_is_bonded(cfg->id, &cfg->peer)) {
+				bt_gatt_store_ccc(cfg->id, &cfg->peer);
+			}
+
+			clear_ccc_cfg(cfg);
+		}
+	}
+}
+
+static int gatt_unregister(struct bt_gatt_service *svc)
+{
+	if (!sys_slist_find_and_remove(&db, &svc->node)) {
+		return -ENOENT;
+	}
+
+	for (uint16_t i = 0; i < svc->attr_count; i++) {
+		struct bt_gatt_attr *attr = &svc->attrs[i];
+
+		if (attr->write == bt_gatt_attr_write_ccc) {
+			gatt_unregister_ccc(attr->user_data);
+		}
+	}
+
+	return 0;
+}
+
+int bt_gatt_service_register(struct bt_gatt_service *svc)
+{
+	int err;
+
+	__ASSERT(svc, "invalid parameters\n");
+	__ASSERT(svc->attrs, "invalid parameters\n");
+	__ASSERT(svc->attr_count, "invalid parameters\n");
+
+	/* Init GATT core services */
+	bt_gatt_init();
+
+	/* Do no allow to register mandatory services twice */
+	if (!bt_uuid_cmp(svc->attrs[0].uuid, BT_UUID_GAP) ||
+	    !bt_uuid_cmp(svc->attrs[0].uuid, BT_UUID_GATT)) {
+		return -EALREADY;
+	}
+
+	err = gatt_register(svc);
+	if (err < 0) {
+		return err;
+	}
+
+	sc_indicate(svc->attrs[0].handle,
+		    svc->attrs[svc->attr_count - 1].handle);
+
+	db_changed();
+
+	return 0;
+}
+
+int bt_gatt_service_unregister(struct bt_gatt_service *svc)
+{
+	int err;
+
+	__ASSERT(svc, "invalid parameters\n");
+
+	err = gatt_unregister(svc);
+	if (err) {
+		return err;
+	}
+
+	sc_indicate(svc->attrs[0].handle,
+		    svc->attrs[svc->attr_count - 1].handle);
+
+	db_changed();
+
+	return 0;
+}
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+
+ssize_t bt_gatt_attr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			  void *buf, uint16_t buf_len, uint16_t offset,
+			  const void *value, uint16_t value_len)
+{
+	uint16_t len;
+
+	if (offset > value_len) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	len = MIN(buf_len, value_len - offset);
+
+	BT_DBG("handle 0x%04x offset %u length %u", attr->handle, offset,
+	       len);
+
+	memcpy(buf, (uint8_t *)value + offset, len);
+
+	return len;
+}
+
+ssize_t bt_gatt_attr_read_service(struct bt_conn *conn,
+				  const struct bt_gatt_attr *attr,
+				  void *buf, uint16_t len, uint16_t offset)
+{
+	struct bt_uuid *uuid = attr->user_data;
+
+	if (uuid->type == BT_UUID_TYPE_16) {
+		uint16_t uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val);
+
+		return bt_gatt_attr_read(conn, attr, buf, len, offset,
+					 &uuid16, 2);
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset,
+				 BT_UUID_128(uuid)->val, 16);
+}
+
+struct gatt_incl {
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint16_t uuid16;
+} __packed;
+
+static uint8_t get_service_handles(const struct bt_gatt_attr *attr,
+				   uint16_t handle, void *user_data)
+{
+	struct gatt_incl *include = user_data;
+
+	/* Stop if attribute is a service */
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) ||
+	    !bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	include->end_handle = handle;
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+uint16_t bt_gatt_attr_get_handle(const struct bt_gatt_attr *attr)
+{
+	uint16_t handle = 1;
+
+	if (!attr) {
+		return 0;
+	}
+
+	if (attr->handle) {
+		return attr->handle;
+	}
+    
+#if 0
+	Z_STRUCT_SECTION_FOREACH(bt_gatt_service_static, static_svc) {
+		/* Skip ahead if start is not within service attributes array */
+		if ((attr < &static_svc->attrs[0]) ||
+		    (attr > &static_svc->attrs[static_svc->attr_count - 1])) {
+			handle += static_svc->attr_count;
+			continue;
+		}
+
+		for (size_t i = 0; i < static_svc->attr_count; i++, handle++) {
+			if (attr == &static_svc->attrs[i]) {
+				return handle;
+			}
+		}
+	}
+#endif
+	return 0;
+}
+
+ssize_t bt_gatt_attr_read_included(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   void *buf, uint16_t len, uint16_t offset)
+{
+	struct bt_gatt_attr *incl = attr->user_data;
+	uint16_t handle = bt_gatt_attr_get_handle(incl);
+	struct bt_uuid *uuid = incl->user_data;
+	struct gatt_incl pdu;
+	uint8_t value_len;
+
+	/* first attr points to the start handle */
+	pdu.start_handle = sys_cpu_to_le16(handle);
+	value_len = sizeof(pdu.start_handle) + sizeof(pdu.end_handle);
+
+	/*
+	 * Core 4.2, Vol 3, Part G, 3.2,
+	 * The Service UUID shall only be present when the UUID is a
+	 * 16-bit Bluetooth UUID.
+	 */
+	if (uuid->type == BT_UUID_TYPE_16) {
+		pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(uuid)->val);
+		value_len += sizeof(pdu.uuid16);
+	}
+
+	/* Lookup for service end handle */
+	bt_gatt_foreach_attr(handle + 1, 0xffff, get_service_handles, &pdu);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len);
+}
+
+struct gatt_chrc {
+	uint8_t properties;
+	uint16_t value_handle;
+	union {
+		uint16_t uuid16;
+		uint8_t  uuid[16];
+	};
+} __packed;
+
+uint16_t bt_gatt_attr_value_handle(const struct bt_gatt_attr *attr)
+{
+	uint16_t handle = 0;
+
+	if (attr != NULL && bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC) == 0) {
+		struct bt_gatt_chrc *chrc = attr->user_data;
+
+		handle = chrc->value_handle;
+		if (handle == 0) {
+			/* Fall back to Zephyr value handle policy */
+			handle = bt_gatt_attr_get_handle(attr) + 1U;
+		}
+	}
+
+	return handle;
+}
+
+ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, void *buf,
+			       uint16_t len, uint16_t offset)
+{
+	struct bt_gatt_chrc *chrc = attr->user_data;
+	struct gatt_chrc pdu;
+	uint8_t value_len;
+
+	pdu.properties = chrc->properties;
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 534:
+	 * 3.3.2 Characteristic Value Declaration
+	 * The Characteristic Value declaration contains the value of the
+	 * characteristic. It is the first Attribute after the characteristic
+	 * declaration. All characteristic definitions shall have a
+	 * Characteristic Value declaration.
+	 */
+	pdu.value_handle = sys_cpu_to_le16(bt_gatt_attr_value_handle(attr));
+
+	value_len = sizeof(pdu.properties) + sizeof(pdu.value_handle);
+
+	if (chrc->uuid->type == BT_UUID_TYPE_16) {
+		pdu.uuid16 = sys_cpu_to_le16(BT_UUID_16(chrc->uuid)->val);
+		value_len += 2U;
+	} else {
+		memcpy(pdu.uuid, BT_UUID_128(chrc->uuid)->val, 16);
+		value_len += 16U;
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &pdu, value_len);
+}
+
+static uint8_t gatt_foreach_iter(const struct bt_gatt_attr *attr,
+				 uint16_t handle, uint16_t start_handle,
+				 uint16_t end_handle,
+				 const struct bt_uuid *uuid,
+				 const void *attr_data, uint16_t *num_matches,
+				 bt_gatt_attr_func_t func, void *user_data)
+{
+	uint8_t result;
+
+	/* Stop if over the requested range */
+	if (handle > end_handle) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Check if attribute handle is within range */
+	if (handle < start_handle) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	/* Match attribute UUID if set */
+	if (uuid && bt_uuid_cmp(uuid, attr->uuid)) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	/* Match attribute user_data if set */
+	if (attr_data && attr_data != attr->user_data) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	*num_matches -= 1;
+
+	result = func(attr, handle, user_data);
+
+	if (!*num_matches) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	return result;
+}
+
+static void foreach_attr_type_dyndb(uint16_t start_handle, uint16_t end_handle,
+				    const struct bt_uuid *uuid,
+				    const void *attr_data, uint16_t num_matches,
+				    bt_gatt_attr_func_t func, void *user_data)
+{
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+	size_t i;
+	struct bt_gatt_service *svc;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&db, svc, node) {
+		struct bt_gatt_service *next;
+
+		next = SYS_SLIST_PEEK_NEXT_CONTAINER(svc, node);
+		if (next) {
+			/* Skip ahead if start is not within service handles */
+			if (next->attrs[0].handle <= start_handle) {
+				continue;
+			}
+		}
+
+		for (i = 0; i < svc->attr_count; i++) {
+			struct bt_gatt_attr *attr = &svc->attrs[i];
+
+			if (gatt_foreach_iter(attr, attr->handle,
+					      start_handle,
+					      end_handle,
+					      uuid, attr_data,
+					      &num_matches,
+					      func, user_data) ==
+			    BT_GATT_ITER_STOP) {
+				return;
+			}
+		}
+	}
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+}
+
+void bt_gatt_foreach_attr_type(uint16_t start_handle, uint16_t end_handle,
+			       const struct bt_uuid *uuid,
+			       const void *attr_data, uint16_t num_matches,
+			       bt_gatt_attr_func_t func, void *user_data)
+{
+	size_t i;
+
+	if (!num_matches) {
+		num_matches = UINT16_MAX;
+	}
+
+	if (start_handle <= last_static_handle) {
+		uint16_t handle = 1;
+        
+#if 0
+		Z_STRUCT_SECTION_FOREACH(bt_gatt_service_static, static_svc) {
+			/* Skip ahead if start is not within service handles */
+			if (handle + static_svc->attr_count < start_handle) {
+				handle += static_svc->attr_count;
+				continue;
+			}
+
+			for (i = 0; i < static_svc->attr_count; i++, handle++) {
+				if (gatt_foreach_iter(&static_svc->attrs[i],
+						      handle, start_handle,
+						      end_handle, uuid,
+						      attr_data, &num_matches,
+						      func, user_data) ==
+				    BT_GATT_ITER_STOP) {
+					return;
+				}
+			}
+		}
+#endif
+	}
+
+	/* Iterate over dynamic db */
+	foreach_attr_type_dyndb(start_handle, end_handle, uuid, attr_data,
+				num_matches, func, user_data);
+}
+
+static uint8_t find_next(const struct bt_gatt_attr *attr, uint16_t handle,
+			 void *user_data)
+{
+	struct bt_gatt_attr **next = user_data;
+
+	*next = (struct bt_gatt_attr *)attr;
+
+	return BT_GATT_ITER_STOP;
+}
+
+struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr)
+{
+	struct bt_gatt_attr *next = NULL;
+	uint16_t handle = bt_gatt_attr_get_handle(attr);
+
+	bt_gatt_foreach_attr(handle + 1, handle + 1, find_next, &next);
+
+	return next;
+}
+
+static struct bt_gatt_ccc_cfg *find_ccc_cfg(const struct bt_conn *conn,
+					    struct _bt_gatt_ccc *ccc)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+
+		if (conn) {
+			if (bt_conn_is_peer_addr_le(conn, cfg->id,
+						    &cfg->peer)) {
+				return cfg;
+			}
+		} else if (!bt_addr_le_cmp(&cfg->peer, BT_ADDR_LE_ANY)) {
+			return cfg;
+		}
+	}
+
+	return NULL;
+}
+
+ssize_t bt_gatt_attr_read_ccc(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset)
+{
+	struct _bt_gatt_ccc *ccc = attr->user_data;
+	const struct bt_gatt_ccc_cfg *cfg;
+	uint16_t value;
+
+	cfg = find_ccc_cfg(conn, ccc);
+	if (cfg) {
+		value = sys_cpu_to_le16(cfg->value);
+	} else {
+		/* Default to disable if there is no cfg for the peer */
+		value = 0x0000;
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &value,
+				 sizeof(value));
+}
+
+static void gatt_ccc_changed(const struct bt_gatt_attr *attr,
+			     struct _bt_gatt_ccc *ccc)
+{
+	int i;
+	uint16_t value = 0x0000;
+
+	for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		if (ccc->cfg[i].value > value) {
+			value = ccc->cfg[i].value;
+		}
+	}
+
+	BT_DBG("ccc %p value 0x%04x", ccc, value);
+
+	if (value != ccc->value) {
+		ccc->value = value;
+		if (ccc->cfg_changed) {
+			ccc->cfg_changed(attr, value);
+		}
+	}
+}
+
+ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, const void *buf,
+			       uint16_t len, uint16_t offset, uint8_t flags)
+{
+	struct _bt_gatt_ccc *ccc = attr->user_data;
+	struct bt_gatt_ccc_cfg *cfg;
+	uint16_t value;
+
+	if (offset) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	if (!len || len > sizeof(uint16_t)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
+	}
+
+	if (len < sizeof(uint16_t)) {
+		value = *(uint8_t *)buf;
+	} else {
+		value = sys_get_le16(buf);
+	}
+
+	cfg = find_ccc_cfg(conn, ccc);
+	if (!cfg) {
+		/* If there's no existing entry, but the new value is zero,
+		 * we don't need to do anything, since a disabled CCC is
+		 * behavioraly the same as no written CCC.
+		 */
+		if (!value) {
+			return len;
+		}
+
+		cfg = find_ccc_cfg(NULL, ccc);
+		if (!cfg) {
+			BT_WARN("No space to store CCC cfg");
+			return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
+		}
+
+		bt_addr_le_copy(&cfg->peer, &conn->le.dst);
+		cfg->id = conn->id;
+	}
+
+	/* Confirm write if cfg is managed by application */
+	if (ccc->cfg_write) {
+		ssize_t write = ccc->cfg_write(conn, attr, value);
+
+		if (write < 0) {
+			return write;
+		}
+
+		/* Accept size=1 for backwards compatibility */
+		if (write != sizeof(value) && write != 1) {
+			return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
+		}
+	}
+
+	cfg->value = value;
+
+	BT_DBG("handle 0x%04x value %u", attr->handle, cfg->value);
+
+	/* Update cfg if don't match */
+	if (cfg->value != ccc->value) {
+		gatt_ccc_changed(attr, ccc);
+
+#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE)
+		gatt_ccc_conn_enqueue(conn);
+#endif
+	}
+
+	/* Disabled CCC is the same as no configured CCC, so clear the entry */
+	if (!value) {
+		clear_ccc_cfg(cfg);
+	}
+
+	return len;
+}
+
+ssize_t bt_gatt_attr_read_cep(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset)
+{
+	const struct bt_gatt_cep *value = attr->user_data;
+	uint16_t props = sys_cpu_to_le16(value->properties);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &props,
+				 sizeof(props));
+}
+
+ssize_t bt_gatt_attr_read_cud(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset)
+{
+	const char *value = attr->user_data;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+				 strlen(value));
+}
+
+ssize_t bt_gatt_attr_read_cpf(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, void *buf,
+			      uint16_t len, uint16_t offset)
+{
+	const struct bt_gatt_cpf *value = attr->user_data;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+				 sizeof(*value));
+}
+
+struct notify_data {
+	const struct bt_gatt_attr *attr;
+	uint16_t handle;
+	int err;
+	uint16_t type;
+	union {
+		struct bt_gatt_notify_params *nfy_params;
+		struct bt_gatt_indicate_params *ind_params;
+	};
+};
+
+#if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE)
+
+struct nfy_mult_data {
+	bt_gatt_complete_func_t func;
+	void *user_data;
+};
+
+#define nfy_mult_user_data(buf) \
+	((struct nfy_mult_data *)net_buf_user_data(buf))
+#define nfy_mult_data_match(buf, _func, _user_data) \
+	((nfy_mult_user_data(buf)->func == _func) && \
+	(nfy_mult_user_data(buf)->user_data == _user_data))
+
+static struct net_buf *nfy_mult[CONFIG_BT_MAX_CONN];
+
+static int gatt_notify_mult_send(struct bt_conn *conn, struct net_buf **buf)
+{
+	struct nfy_mult_data *data = nfy_mult_user_data(*buf);
+	int ret;
+
+	ret = bt_att_send(conn, *buf, data->func, data->user_data);
+	if (ret < 0) {
+		net_buf_unref(*buf);
+	}
+
+	*buf = NULL;
+
+	return ret;
+}
+
+static void notify_mult_process(struct k_work *work)
+{
+	int i;
+
+	/* Send to any connection with an allocated buffer */
+	for (i = 0; i < ARRAY_SIZE(nfy_mult); i++) {
+		struct net_buf **buf = &nfy_mult[i];
+
+		if (*buf) {
+			struct bt_conn *conn = bt_conn_lookup_index(i);
+
+			gatt_notify_mult_send(conn, buf);
+			bt_conn_unref(conn);
+		}
+	}
+}
+
+K_WORK_DEFINE(nfy_mult_work, notify_mult_process);
+
+static bool gatt_cf_notify_multi(struct bt_conn *conn)
+{
+	struct gatt_cf_cfg *cfg;
+
+	cfg = find_cf_cfg(conn);
+	if (!cfg) {
+		return false;
+	}
+
+	return CF_NOTIFY_MULTI(cfg);
+}
+
+static int gatt_notify_mult(struct bt_conn *conn, uint16_t handle,
+			    struct bt_gatt_notify_params *params)
+{
+	struct net_buf **buf = &nfy_mult[bt_conn_index(conn)];
+	struct bt_att_notify_mult *nfy;
+
+	/* Check if we can fit more data into it, in case it doesn't fit send
+	 * the existing buffer and proceed to create a new one
+	 */
+	if (*buf && ((net_buf_tailroom(*buf) < sizeof(*nfy) + params->len) ||
+	    !nfy_mult_data_match(*buf, params->func, params->user_data))) {
+		int ret;
+
+		ret = gatt_notify_mult_send(conn, buf);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	if (!*buf) {
+		*buf = bt_att_create_pdu(conn, BT_ATT_OP_NOTIFY_MULT,
+					 sizeof(*nfy) + params->len);
+		if (!*buf) {
+			return -ENOMEM;
+		}
+		/* Set user_data so it can be restored when sending */
+		nfy_mult_user_data(*buf)->func = params->func;
+		nfy_mult_user_data(*buf)->user_data = params->user_data;
+	}
+
+	BT_DBG("handle 0x%04x len %u", handle, params->len);
+
+	nfy = net_buf_add(*buf, sizeof(*nfy));
+	nfy->handle = sys_cpu_to_le16(handle);
+	nfy->len = sys_cpu_to_le16(params->len);
+
+	net_buf_add(*buf, params->len);
+	memcpy(nfy->value, params->data, params->len);
+
+	k_work_submit(&nfy_mult_work);
+
+	return 0;
+}
+#endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
+
+static int gatt_notify(struct bt_conn *conn, uint16_t handle,
+		       struct bt_gatt_notify_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_notify *nfy;
+
+#if defined(CONFIG_BT_GATT_ENFORCE_CHANGE_UNAWARE)
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2350:
+	 * Except for the Handle Value indication, the  server shall not send
+	 * notifications and indications to such a client until it becomes
+	 * change-aware.
+	 */
+	if (!bt_gatt_change_aware(conn, false)) {
+		return -EAGAIN;
+	}
+#endif
+
+#if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE)
+	if (gatt_cf_notify_multi(conn)) {
+		int err;
+
+		err = gatt_notify_mult(conn, handle, params);
+		if (err && err != -ENOMEM) {
+			return err;
+		}
+	}
+#endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_NOTIFY,
+				sizeof(*nfy) + params->len);
+	if (!buf) {
+		BT_WARN("No buffer available to send notification");
+		return -ENOMEM;
+	}
+
+	BT_DBG("conn %p handle 0x%04x", conn, handle);
+
+	nfy = net_buf_add(buf, sizeof(*nfy));
+	nfy->handle = sys_cpu_to_le16(handle);
+
+	net_buf_add(buf, params->len);
+	memcpy(nfy->value, params->data, params->len);
+
+	return bt_att_send(conn, buf, params->func, params->user_data);
+}
+
+static void gatt_indicate_rsp(struct bt_conn *conn, uint8_t err,
+			      const void *pdu, uint16_t length, void *user_data)
+{
+	struct bt_gatt_indicate_params *params = user_data;
+
+	params->func(conn, params->attr, err);
+}
+
+static int gatt_send(struct bt_conn *conn, struct net_buf *buf,
+		     bt_att_func_t func, void *params,
+		     bt_att_destroy_t destroy)
+{
+	int err;
+
+	if (params) {
+		struct bt_att_req *req;
+
+		/* Allocate new request */
+		req = bt_att_req_alloc(BT_ATT_TIMEOUT);
+		if (!req) {
+			return -ENOMEM;
+		}
+
+		req->buf = buf;
+		req->func = func;
+		req->destroy = destroy;
+		req->user_data = params;
+
+		err = bt_att_req_send(conn, req);
+		if (err) {
+			bt_att_req_free(req);
+		}
+	} else {
+		err = bt_att_send(conn, buf, NULL, NULL);
+	}
+
+	if (err) {
+		BT_ERR("Error sending ATT PDU: %d", err);
+	}
+
+	return err;
+}
+
+static int gatt_indicate(struct bt_conn *conn, uint16_t handle,
+			 struct bt_gatt_indicate_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_indicate *ind;
+
+#if defined(CONFIG_BT_GATT_ENFORCE_CHANGE_UNAWARE)
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2350:
+	 * Except for the Handle Value indication, the  server shall not send
+	 * notifications and indications to such a client until it becomes
+	 * change-aware.
+	 */
+	if (!(params->func && (params->func == sc_indicate_rsp ||
+	    params->func == sc_restore_rsp)) &&
+	    !bt_gatt_change_aware(conn, false)) {
+		return -EAGAIN;
+	}
+#endif
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_INDICATE,
+				sizeof(*ind) + params->len);
+	if (!buf) {
+		BT_WARN("No buffer available to send indication");
+		return -ENOMEM;
+	}
+
+	BT_DBG("conn %p handle 0x%04x", conn, handle);
+
+	ind = net_buf_add(buf, sizeof(*ind));
+	ind->handle = sys_cpu_to_le16(handle);
+
+	net_buf_add(buf, params->len);
+	memcpy(ind->value, params->data, params->len);
+
+	if (!params->func) {
+		return gatt_send(conn, buf, NULL, NULL, NULL);
+	}
+
+	return gatt_send(conn, buf, gatt_indicate_rsp, params, NULL);
+}
+
+static uint8_t notify_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			 void *user_data)
+{
+	struct notify_data *data = user_data;
+	struct _bt_gatt_ccc *ccc;
+	size_t i;
+
+	/* Check attribute user_data must be of type struct _bt_gatt_ccc */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	/* Save Service Changed data if peer is not connected */
+	if (IS_ENABLED(CONFIG_BT_GATT_SERVICE_CHANGED) && ccc == &sc_ccc) {
+		for (i = 0; i < ARRAY_SIZE(sc_cfg); i++) {
+			struct gatt_sc_cfg *cfg = &sc_cfg[i];
+			struct bt_conn *conn;
+
+			if (!bt_addr_le_cmp(&cfg->peer, BT_ADDR_LE_ANY)) {
+				continue;
+			}
+
+			conn = bt_conn_lookup_state_le(cfg->id, &cfg->peer,
+						       BT_CONN_CONNECTED);
+			if (!conn) {
+				struct sc_data *sc;
+
+				sc = (struct sc_data *)data->ind_params->data;
+				sc_save(cfg->id, &cfg->peer,
+					sys_le16_to_cpu(sc->start),
+					sys_le16_to_cpu(sc->end));
+				continue;
+			}
+
+			bt_conn_unref(conn);
+		}
+	}
+
+	/* Notify all peers configured */
+	for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+		struct bt_conn *conn;
+		int err;
+
+		/* Check if config value matches data type since consolidated
+		 * value may be for a different peer.
+		 */
+		if (cfg->value != data->type) {
+			continue;
+		}
+
+		conn = bt_conn_lookup_addr_le(cfg->id, &cfg->peer);
+		if (!conn) {
+			continue;
+		}
+
+		if (conn->state != BT_CONN_CONNECTED) {
+			bt_conn_unref(conn);
+			continue;
+		}
+
+		/* Confirm match if cfg is managed by application */
+		if (ccc->cfg_match && !ccc->cfg_match(conn, attr)) {
+			bt_conn_unref(conn);
+			continue;
+		}
+
+		/* Use the Characteristic Value handle discovered since the
+		 * Client Characteristic Configuration descriptor may occur
+		 * in any position within the characteristic definition after
+		 * the Characteristic Value.
+		 */
+		if (data->type == BT_GATT_CCC_INDICATE) {
+			err = gatt_indicate(conn, data->handle,
+					    data->ind_params);
+		} else {
+			err = gatt_notify(conn, data->handle, data->nfy_params);
+		}
+
+		bt_conn_unref(conn);
+
+		if (err < 0) {
+			return BT_GATT_ITER_STOP;
+		}
+
+		data->err = 0;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t match_uuid(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	struct notify_data *data = user_data;
+
+	data->attr = attr;
+	data->handle = handle;
+
+	return BT_GATT_ITER_STOP;
+}
+
+static bool gatt_find_by_uuid(struct notify_data *found,
+			      const struct bt_uuid *uuid)
+{
+	found->attr = NULL;
+
+	bt_gatt_foreach_attr_type(found->handle, 0xffff, uuid, NULL, 1,
+				  match_uuid, found);
+
+	return found->attr ? true : false;
+}
+
+int bt_gatt_notify_cb(struct bt_conn *conn,
+		      struct bt_gatt_notify_params *params)
+{
+	struct notify_data data;
+
+	__ASSERT(params, "invalid parameters\n");
+	__ASSERT(params->attr, "invalid parameters\n");
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	data.attr = params->attr;
+
+	if (conn && conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	data.handle = bt_gatt_attr_get_handle(data.attr);
+	if (!data.handle) {
+		return -ENOENT;
+	}
+
+	/* Lookup UUID if it was given */
+	if (params->uuid) {
+		if (!gatt_find_by_uuid(&data, params->uuid)) {
+			return -ENOENT;
+		}
+	}
+
+	/* Check if attribute is a characteristic then adjust the handle */
+	if (!bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC)) {
+		struct bt_gatt_chrc *chrc = data.attr->user_data;
+
+		if (!(chrc->properties & BT_GATT_CHRC_NOTIFY)) {
+			return -EINVAL;
+		}
+
+		data.handle = bt_gatt_attr_value_handle(data.attr);
+	}
+
+	if (conn) {
+		return gatt_notify(conn, data.handle, params);
+	}
+
+	data.err = -ENOTCONN;
+	data.type = BT_GATT_CCC_NOTIFY;
+	data.nfy_params = params;
+
+	bt_gatt_foreach_attr_type(data.handle, 0xffff, BT_UUID_GATT_CCC, NULL,
+				  1, notify_cb, &data);
+
+	return data.err;
+}
+
+#if defined(CONFIG_BT_GATT_NOTIFY_MULTIPLE)
+int bt_gatt_notify_multiple(struct bt_conn *conn, uint16_t num_params,
+			    struct bt_gatt_notify_params *params)
+{
+	int i, ret;
+
+	__ASSERT(params, "invalid parameters\n");
+	__ASSERT(num_params, "invalid parameters\n");
+	__ASSERT(params->attr, "invalid parameters\n");
+
+	for (i = 0; i < num_params; i++) {
+		ret = bt_gatt_notify_cb(conn, &params[i]);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_GATT_NOTIFY_MULTIPLE */
+
+int bt_gatt_indicate(struct bt_conn *conn,
+		     struct bt_gatt_indicate_params *params)
+{
+	struct notify_data data;
+
+	__ASSERT(params, "invalid parameters\n");
+	__ASSERT(params->attr, "invalid parameters\n");
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	data.attr = params->attr;
+
+	if (conn && conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	data.handle = bt_gatt_attr_get_handle(data.attr);
+	if (!data.handle) {
+		return -ENOENT;
+	}
+
+	/* Lookup UUID if it was given */
+	if (params->uuid) {
+		if (!gatt_find_by_uuid(&data, params->uuid)) {
+			return -ENOENT;
+		}
+	}
+
+	/* Check if attribute is a characteristic then adjust the handle */
+	if (!bt_uuid_cmp(data.attr->uuid, BT_UUID_GATT_CHRC)) {
+		struct bt_gatt_chrc *chrc = data.attr->user_data;
+
+		if (!(chrc->properties & BT_GATT_CHRC_INDICATE)) {
+			return -EINVAL;
+		}
+
+		data.handle = bt_gatt_attr_value_handle(data.attr);
+	}
+
+	if (conn) {
+		return gatt_indicate(conn, data.handle, params);
+	}
+
+	data.err = -ENOTCONN;
+	data.type = BT_GATT_CCC_INDICATE;
+	data.ind_params = params;
+
+	bt_gatt_foreach_attr_type(data.handle, 0xffff, BT_UUID_GATT_CCC, NULL,
+				  1, notify_cb, &data);
+
+	return data.err;
+}
+
+uint16_t bt_gatt_get_mtu(struct bt_conn *conn)
+{
+	return bt_att_get_mtu(conn);
+}
+
+uint8_t bt_gatt_check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			uint8_t mask)
+{
+	if ((mask & BT_GATT_PERM_READ) &&
+	    (!(attr->perm & BT_GATT_PERM_READ_MASK) || !attr->read)) {
+		return BT_ATT_ERR_READ_NOT_PERMITTED;
+	}
+
+	if ((mask & BT_GATT_PERM_WRITE) &&
+	    (!(attr->perm & BT_GATT_PERM_WRITE_MASK) || !attr->write)) {
+		return BT_ATT_ERR_WRITE_NOT_PERMITTED;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN_DISABLE_SECURITY)) {
+		return 0;
+	}
+
+	mask &= attr->perm;
+	if (mask & BT_GATT_PERM_AUTHEN_MASK) {
+		if (bt_conn_get_security(conn) < BT_SECURITY_L3) {
+			return BT_ATT_ERR_AUTHENTICATION;
+		}
+	}
+
+	if ((mask & BT_GATT_PERM_ENCRYPT_MASK)) {
+#if defined(CONFIG_BT_SMP)
+		if (!conn->encrypt) {
+			return BT_ATT_ERR_INSUFFICIENT_ENCRYPTION;
+		}
+#else
+		return BT_ATT_ERR_INSUFFICIENT_ENCRYPTION;
+#endif /* CONFIG_BT_SMP */
+	}
+
+	return 0;
+}
+
+static void sc_restore_rsp(struct bt_conn *conn,
+			   const struct bt_gatt_attr *attr, uint8_t err)
+{
+#if defined(CONFIG_BT_GATT_CACHING)
+	struct gatt_cf_cfg *cfg;
+#endif
+
+	BT_DBG("err 0x%02x", err);
+
+#if defined(CONFIG_BT_GATT_CACHING)
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2347:
+	 * 2.5.2.1 Robust Caching
+	 * A connected client becomes change-aware when...
+	 * The client receives and confirms a Service Changed indication.
+	 */
+	cfg = find_cf_cfg(conn);
+	if (cfg && CF_ROBUST_CACHING(cfg)) {
+		atomic_set_bit(cfg->flags, CF_CHANGE_AWARE);
+		BT_DBG("%s change-aware", bt_addr_le_str(&cfg->peer));
+	}
+#endif
+}
+
+static struct bt_gatt_indicate_params sc_restore_params[CONFIG_BT_MAX_CONN];
+
+static void sc_restore(struct bt_conn *conn)
+{
+	struct gatt_sc_cfg *cfg;
+	uint16_t sc_range[2];
+	uint8_t index;
+
+	cfg = find_sc_cfg(conn->id, &conn->le.dst);
+	if (!cfg) {
+		BT_DBG("no SC data found");
+		return;
+	}
+
+	if (!(cfg->data.start || cfg->data.end)) {
+		return;
+	}
+
+	BT_DBG("peer %s start 0x%04x end 0x%04x", bt_addr_le_str(&cfg->peer),
+	       cfg->data.start, cfg->data.end);
+
+	sc_range[0] = sys_cpu_to_le16(cfg->data.start);
+	sc_range[1] = sys_cpu_to_le16(cfg->data.end);
+
+	index = bt_conn_index(conn);
+	sc_restore_params[index].attr = &_1_gatt_svc.attrs[2];
+	sc_restore_params[index].func = sc_restore_rsp;
+	sc_restore_params[index].data = &sc_range[0];
+	sc_restore_params[index].len = sizeof(sc_range);
+
+	if (bt_gatt_indicate(conn, &sc_restore_params[index])) {
+		BT_ERR("SC restore indication failed");
+	}
+
+	/* Reset config data */
+	sc_reset(cfg);
+}
+
+struct conn_data {
+	struct bt_conn *conn;
+	bt_security_t sec;
+};
+
+static uint8_t update_ccc(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	struct conn_data *data = user_data;
+	struct bt_conn *conn = data->conn;
+	struct _bt_gatt_ccc *ccc;
+	size_t i;
+	uint8_t err;
+
+	/* Check attribute user_data must be of type struct _bt_gatt_ccc */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+
+		/* Ignore configuration for different peer or not active */
+		if (!cfg->value ||
+		    !bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) {
+			continue;
+		}
+
+		/* Check if attribute requires encryption/authentication */
+		err = bt_gatt_check_perm(conn, attr, BT_GATT_PERM_WRITE_MASK);
+		if (err) {
+			bt_security_t sec;
+
+			if (err == BT_ATT_ERR_WRITE_NOT_PERMITTED) {
+				BT_WARN("CCC %p not writable", attr);
+				continue;
+			}
+
+			sec = BT_SECURITY_L2;
+
+			if (err == BT_ATT_ERR_AUTHENTICATION) {
+				sec = BT_SECURITY_L3;
+			}
+
+			/* Check if current security is enough */
+			if (IS_ENABLED(CONFIG_BT_SMP) &&
+			    bt_conn_get_security(conn) < sec) {
+				if (data->sec < sec) {
+					data->sec = sec;
+				}
+				continue;
+			}
+		}
+
+		gatt_ccc_changed(attr, ccc);
+
+		if (IS_ENABLED(CONFIG_BT_GATT_SERVICE_CHANGED) &&
+		    ccc == &sc_ccc) {
+			sc_restore(conn);
+		}
+
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+			       void *user_data)
+{
+	struct bt_conn *conn = user_data;
+	struct _bt_gatt_ccc *ccc;
+	bool value_used;
+	size_t i;
+
+	/* Check attribute user_data must be of type struct _bt_gatt_ccc */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	/* If already disabled skip */
+	if (!ccc->value) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	/* Checking if all values are disabled */
+	value_used = false;
+
+	for (i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+
+		/* Ignore configurations with disabled value */
+		if (!cfg->value) {
+			continue;
+		}
+
+		if (!bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer)) {
+			struct bt_conn *tmp;
+
+			/* Skip if there is another peer connected */
+			tmp = bt_conn_lookup_addr_le(cfg->id, &cfg->peer);
+			if (tmp) {
+				if (tmp->state == BT_CONN_CONNECTED) {
+					value_used = true;
+				}
+
+				bt_conn_unref(tmp);
+			}
+		} else {
+			/* Clear value if not paired */
+			if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+				if (ccc == &sc_ccc) {
+					sc_clear(conn);
+				}
+
+				clear_ccc_cfg(cfg);
+			} else {
+				/* Update address in case it has changed */
+				bt_addr_le_copy(&cfg->peer, &conn->le.dst);
+			}
+		}
+	}
+
+	/* If all values are now disabled, reset value while disconnected */
+	if (!value_used) {
+		ccc->value = 0U;
+		if (ccc->cfg_changed) {
+			ccc->cfg_changed(attr, ccc->value);
+		}
+
+		BT_DBG("ccc %p reseted", ccc);
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+bool bt_gatt_is_subscribed(struct bt_conn *conn,
+			   const struct bt_gatt_attr *attr, uint16_t ccc_value)
+{
+	const struct _bt_gatt_ccc *ccc;
+
+	__ASSERT(conn, "invalid parameter\n");
+	__ASSERT(attr, "invalid parameter\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return false;
+	}
+
+	/* Check if attribute is a characteristic declaration */
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
+		struct bt_gatt_chrc *chrc = attr->user_data;
+
+		if (!(chrc->properties &
+			(BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_INDICATE))) {
+			/* Characteristic doesn't support subscription */
+			return false;
+		}
+
+		attr = bt_gatt_attr_next(attr);
+	}
+
+	/* Check if attribute is a characteristic value */
+	if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) {
+		attr = bt_gatt_attr_next(attr);
+	}
+
+	/* Check if the attribute is the CCC Descriptor */
+	if (bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) != 0) {
+		return false;
+	}
+
+	ccc = attr->user_data;
+
+	/* Check if the connection is subscribed */
+	for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) {
+		const struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
+
+		if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer) &&
+		    (ccc_value & ccc->cfg[i].value)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void gatt_sub_remove(struct bt_conn *conn, struct gatt_sub *sub,
+			    sys_snode_t *prev,
+			    struct bt_gatt_subscribe_params *params)
+{
+	if (params) {
+		/* Remove subscription from the list*/
+		sys_slist_remove(&sub->list, prev, &params->node);
+		/* Notify removal */
+		params->notify(conn, params, NULL, 0);
+	}
+
+	if (sys_slist_is_empty(&sub->list)) {
+		/* Reset address if there are no subscription left */
+		bt_addr_le_copy(&sub->peer, BT_ADDR_LE_ANY);
+	}
+}
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+static struct gatt_sub *gatt_sub_find(struct bt_conn *conn)
+{
+	for (int i = 0; i < ARRAY_SIZE(subscriptions); i++) {
+		struct gatt_sub *sub = &subscriptions[i];
+
+		if (!conn) {
+			if (!bt_addr_le_cmp(&sub->peer, BT_ADDR_LE_ANY)) {
+				return sub;
+			}
+		} else if (bt_conn_is_peer_addr_le(conn, sub->id, &sub->peer)) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static struct gatt_sub *gatt_sub_add(struct bt_conn *conn)
+{
+	struct gatt_sub *sub;
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		sub = gatt_sub_find(NULL);
+		if (sub) {
+			bt_addr_le_copy(&sub->peer, &conn->le.dst);
+			sub->id = conn->id;
+		}
+	}
+
+	return sub;
+}
+
+static struct gatt_sub *gatt_sub_find_by_addr(uint8_t id,
+					      const bt_addr_le_t *addr)
+{
+	for (int i = 0; i < ARRAY_SIZE(subscriptions); i++) {
+		struct gatt_sub *sub = &subscriptions[i];
+
+		if (id == sub->id && !bt_addr_le_cmp(&sub->peer, addr)) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static struct gatt_sub *gatt_sub_add_by_addr(uint8_t id,
+					     const bt_addr_le_t *addr)
+{
+	struct gatt_sub *sub;
+
+	sub = gatt_sub_find_by_addr(id, addr);
+	if (!sub) {
+		sub = gatt_sub_find(NULL);
+		if (sub) {
+			bt_addr_le_copy(&sub->peer, addr);
+			sub->id = id;
+		}
+	}
+
+	return sub;
+}
+
+void bt_gatt_notification(struct bt_conn *conn, uint16_t handle,
+			  const void *data, uint16_t length)
+{
+	struct bt_gatt_subscribe_params *params, *tmp;
+	struct gatt_sub *sub;
+
+	BT_DBG("handle 0x%04x length %u", handle, length);
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp, node) {
+		if (handle != params->value_handle) {
+			continue;
+		}
+
+		if (params->notify(conn, params, data, length) ==
+		    BT_GATT_ITER_STOP) {
+			bt_gatt_unsubscribe(conn, params);
+		}
+	}
+}
+
+void bt_gatt_mult_notification(struct bt_conn *conn, const void *data,
+			       uint16_t length)
+{
+	struct bt_gatt_subscribe_params *params, *tmp;
+	const struct bt_att_notify_mult *nfy;
+	struct net_buf_simple buf;
+	struct gatt_sub *sub;
+
+	BT_DBG("length %u", length);
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		return;
+	}
+
+	/* This is fine since there no write operation to the buffer.  */
+	net_buf_simple_init_with_data(&buf, (void *)data, length);
+
+	while (buf.len > sizeof(*nfy)) {
+		uint16_t handle;
+		uint16_t len;
+
+		nfy = net_buf_simple_pull_mem(&buf, sizeof(*nfy));
+		handle = sys_cpu_to_le16(nfy->handle);
+		len = sys_cpu_to_le16(nfy->len);
+
+		BT_DBG("handle 0x%02x len %u", handle, len);
+
+		if (len > buf.len) {
+			BT_ERR("Invalid data len %u > %u", len, length);
+			return;
+		}
+
+		SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp,
+						  node) {
+			if (handle != params->value_handle) {
+				continue;
+			}
+
+			if (params->notify(conn, params, nfy->value, len) ==
+			    BT_GATT_ITER_STOP) {
+				bt_gatt_unsubscribe(conn, params);
+			}
+		}
+
+		net_buf_simple_pull_mem(&buf, len);
+	}
+}
+
+static void gatt_sub_update(struct bt_conn *conn, struct gatt_sub *sub)
+{
+	if (sub->peer.type == BT_ADDR_LE_PUBLIC) {
+		return;
+	}
+
+	/* Update address */
+	bt_addr_le_copy(&sub->peer, &conn->le.dst);
+}
+
+static void remove_subscriptions(struct bt_conn *conn)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *params, *tmp;
+	sys_snode_t *prev = NULL;
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		return;
+	}
+
+	/* Lookup existing subscriptions */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp, node) {
+		if (!bt_addr_le_is_bonded(conn->id, &conn->le.dst) ||
+		    (atomic_test_bit(params->flags,
+				     BT_GATT_SUBSCRIBE_FLAG_VOLATILE))) {
+			/* Remove subscription */
+			params->value = 0U;
+			gatt_sub_remove(conn, sub, prev, params);
+		} else {
+			gatt_sub_update(conn, sub);
+			prev = &params->node;
+		}
+	}
+}
+
+static void gatt_mtu_rsp(struct bt_conn *conn, uint8_t err, const void *pdu,
+			 uint16_t length, void *user_data)
+{
+	struct bt_gatt_exchange_params *params = user_data;
+
+	params->func(conn, err, params);
+}
+
+int bt_gatt_exchange_mtu(struct bt_conn *conn,
+			 struct bt_gatt_exchange_params *params)
+{
+	struct bt_att_exchange_mtu_req *req;
+	struct net_buf *buf;
+	uint16_t mtu;
+
+	__ASSERT(conn, "invalid parameter\n");
+	__ASSERT(params && params->func, "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_MTU_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	mtu = BT_ATT_MTU;
+
+	BT_DBG("Client MTU %u", mtu);
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->mtu = sys_cpu_to_le16(mtu);
+
+	return gatt_send(conn, buf, gatt_mtu_rsp, params, NULL);
+}
+
+static void gatt_discover_next(struct bt_conn *conn, uint16_t last_handle,
+			       struct bt_gatt_discover_params *params)
+{
+	/* Skip if last_handle is not set */
+	if (!last_handle)
+		goto discover;
+
+	/* Continue from the last found handle */
+	params->start_handle = last_handle;
+	if (params->start_handle < UINT16_MAX) {
+		params->start_handle++;
+	} else {
+		goto done;
+	}
+
+	/* Stop if over the range or the requests */
+	if (params->start_handle > params->end_handle) {
+		goto done;
+	}
+
+discover:
+	/* Discover next range */
+	if (!bt_gatt_discover(conn, params)) {
+		return;
+	}
+
+done:
+	params->func(conn, NULL, params);
+}
+
+static void gatt_find_type_rsp(struct bt_conn *conn, uint8_t err,
+			       const void *pdu, uint16_t length,
+			       void *user_data)
+{
+	const struct bt_att_handle_group *rsp = pdu;
+	struct bt_gatt_discover_params *params = user_data;
+	uint8_t count;
+	uint16_t end_handle = 0U, start_handle;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err || (length % sizeof(struct bt_att_handle_group) != 0)) {
+		goto done;
+	}
+
+	count = length / sizeof(struct bt_att_handle_group);
+
+	/* Parse attributes found */
+	for (uint8_t i = 0U; i < count; i++) {
+		struct bt_uuid_16 uuid_svc;
+		struct bt_gatt_attr attr;
+		struct bt_gatt_service_val value;
+
+		start_handle = sys_le16_to_cpu(rsp[i].start_handle);
+		end_handle = sys_le16_to_cpu(rsp[i].end_handle);
+
+		BT_DBG("start_handle 0x%04x end_handle 0x%04x", start_handle,
+		       end_handle);
+
+		uuid_svc.uuid.type = BT_UUID_TYPE_16;
+		if (params->type == BT_GATT_DISCOVER_PRIMARY) {
+			uuid_svc.val = BT_UUID_GATT_PRIMARY_VAL;
+		} else {
+			uuid_svc.val = BT_UUID_GATT_SECONDARY_VAL;
+		}
+
+		value.end_handle = end_handle;
+		value.uuid = params->uuid;
+
+		attr = (struct bt_gatt_attr)BT_GATT_ATTRIBUTE(&uuid_svc.uuid, 0,
+							      NULL, NULL,
+							      &value);
+		attr.handle = start_handle;
+
+		if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+			return;
+		}
+	}
+
+	gatt_discover_next(conn, end_handle, params);
+
+	return;
+done:
+	params->func(conn, NULL, params);
+}
+
+static int gatt_find_type(struct bt_conn *conn,
+			 struct bt_gatt_discover_params *params)
+{
+	uint16_t uuid_val;
+	struct net_buf *buf;
+	struct bt_att_find_type_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_TYPE_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->start_handle = sys_cpu_to_le16(params->start_handle);
+	req->end_handle = sys_cpu_to_le16(params->end_handle);
+
+	if (params->type == BT_GATT_DISCOVER_PRIMARY) {
+		uuid_val = BT_UUID_GATT_PRIMARY_VAL;
+	} else {
+		uuid_val = BT_UUID_GATT_SECONDARY_VAL;
+	}
+
+	req->type = sys_cpu_to_le16(uuid_val);
+
+	BT_DBG("gatt_find_type, uuid %s start_handle 0x%04x end_handle 0x%04x",
+	       bt_uuid_str(params->uuid), params->start_handle,
+	       params->end_handle);
+
+	switch (params->uuid->type) {
+	case BT_UUID_TYPE_16:
+		net_buf_add_le16(buf, BT_UUID_16(params->uuid)->val);
+		break;
+	case BT_UUID_TYPE_128:
+		net_buf_add_mem(buf, BT_UUID_128(params->uuid)->val, 16);
+		break;
+	default:
+		BT_ERR("Unknown UUID type %u", params->uuid->type);
+		net_buf_unref(buf);
+		return -EINVAL;
+	}
+
+	return gatt_send(conn, buf, gatt_find_type_rsp, params, NULL);
+}
+
+static void read_included_uuid_cb(struct bt_conn *conn, uint8_t err,
+				  const void *pdu, uint16_t length,
+				  void *user_data)
+{
+	struct bt_gatt_discover_params *params = user_data;
+	struct bt_gatt_include value;
+	struct bt_gatt_attr attr;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_128 u128;
+	} u;
+
+	if (length != 16U) {
+		BT_ERR("Invalid data len %u", length);
+		params->func(conn, NULL, params);
+		return;
+	}
+
+	value.start_handle = params->_included.start_handle;
+	value.end_handle = params->_included.end_handle;
+	value.uuid = &u.uuid;
+	u.uuid.type = BT_UUID_TYPE_128;
+	memcpy(u.u128.val, pdu, length);
+
+	BT_DBG("handle 0x%04x uuid %s start_handle 0x%04x "
+	       "end_handle 0x%04x\n", params->_included.attr_handle,
+	       bt_uuid_str(&u.uuid), value.start_handle, value.end_handle);
+
+	/* Skip if UUID is set but doesn't match */
+	if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) {
+		goto next;
+	}
+
+	attr = (struct bt_gatt_attr)BT_GATT_ATTRIBUTE(
+		BT_UUID_GATT_INCLUDE, 0, NULL, NULL, &value);
+	attr.handle = params->_included.attr_handle;
+
+	if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+		return;
+	}
+next:
+	gatt_discover_next(conn, params->start_handle, params);
+
+	return;
+}
+
+static int read_included_uuid(struct bt_conn *conn,
+			      struct bt_gatt_discover_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(params->_included.start_handle);
+
+	BT_DBG("handle 0x%04x", params->_included.start_handle);
+
+	return gatt_send(conn, buf, read_included_uuid_cb, params, NULL);
+}
+
+static uint16_t parse_include(struct bt_conn *conn, const void *pdu,
+			   struct bt_gatt_discover_params *params,
+			   uint16_t length)
+{
+	const struct bt_att_read_type_rsp *rsp = pdu;
+	uint16_t handle = 0U;
+	struct bt_gatt_include value;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+
+	/* Data can be either in UUID16 or UUID128 */
+	switch (rsp->len) {
+	case 8: /* UUID16 */
+		u.uuid.type = BT_UUID_TYPE_16;
+		break;
+	case 6: /* UUID128 */
+		/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] page 550
+		 * To get the included service UUID when the included service
+		 * uses a 128-bit UUID, the Read Request is used.
+		 */
+		u.uuid.type = BT_UUID_TYPE_128;
+		break;
+	default:
+		BT_ERR("Invalid data len %u", rsp->len);
+		goto done;
+	}
+
+	/* Parse include found */
+	for (length--, pdu = rsp->data; length >= rsp->len;
+	     length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
+		struct bt_gatt_attr attr;
+		const struct bt_att_data *data = pdu;
+		struct gatt_incl *incl = (void *)data->value;
+
+		handle = sys_le16_to_cpu(data->handle);
+		/* Handle 0 is invalid */
+		if (!handle) {
+			goto done;
+		}
+
+		/* Convert include data, bt_gatt_incl and gatt_incl
+		 * have different formats so the conversion have to be done
+		 * field by field.
+		 */
+		value.start_handle = sys_le16_to_cpu(incl->start_handle);
+		value.end_handle = sys_le16_to_cpu(incl->end_handle);
+
+		switch (u.uuid.type) {
+		case BT_UUID_TYPE_16:
+			value.uuid = &u.uuid;
+			u.u16.val = sys_le16_to_cpu(incl->uuid16);
+			break;
+		case BT_UUID_TYPE_128:
+			params->_included.attr_handle = handle;
+			params->_included.start_handle = value.start_handle;
+			params->_included.end_handle = value.end_handle;
+
+			return read_included_uuid(conn, params);
+		}
+
+		BT_DBG("handle 0x%04x uuid %s start_handle 0x%04x "
+		       "end_handle 0x%04x\n", handle, bt_uuid_str(&u.uuid),
+		       value.start_handle, value.end_handle);
+
+		/* Skip if UUID is set but doesn't match */
+		if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) {
+			continue;
+		}
+
+		attr = (struct bt_gatt_attr)BT_GATT_ATTRIBUTE(
+			BT_UUID_GATT_INCLUDE, 0, NULL, NULL, &value);
+		attr.handle = handle;
+
+		if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+			return 0;
+		}
+	}
+
+	/* Whole PDU read without error */
+	if (length == 0U && handle) {
+		return handle;
+	}
+
+done:
+	params->func(conn, NULL, params);
+	return 0;
+}
+
+static uint16_t parse_characteristic(struct bt_conn *conn, const void *pdu,
+				  struct bt_gatt_discover_params *params,
+				  uint16_t length)
+{
+	const struct bt_att_read_type_rsp *rsp = pdu;
+	uint16_t handle = 0U;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+
+	/* Data can be either in UUID16 or UUID128 */
+	switch (rsp->len) {
+	case 7: /* UUID16 */
+		u.uuid.type = BT_UUID_TYPE_16;
+		break;
+	case 21: /* UUID128 */
+		u.uuid.type = BT_UUID_TYPE_128;
+		break;
+	default:
+		BT_ERR("Invalid data len %u", rsp->len);
+		goto done;
+	}
+
+	/* Parse characteristics found */
+	for (length--, pdu = rsp->data; length >= rsp->len;
+	     length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
+		struct bt_gatt_attr attr;
+		struct bt_gatt_chrc value;
+		const struct bt_att_data *data = pdu;
+		struct gatt_chrc *chrc = (void *)data->value;
+
+		handle = sys_le16_to_cpu(data->handle);
+		/* Handle 0 is invalid */
+		if (!handle) {
+			goto done;
+		}
+
+		switch (u.uuid.type) {
+		case BT_UUID_TYPE_16:
+			u.u16.val = sys_le16_to_cpu(chrc->uuid16);
+			break;
+		case BT_UUID_TYPE_128:
+			memcpy(u.u128.val, chrc->uuid, sizeof(chrc->uuid));
+			break;
+		}
+
+		BT_DBG("handle 0x%04x uuid %s properties 0x%02x", handle,
+		       bt_uuid_str(&u.uuid), chrc->properties);
+
+		/* Skip if UUID is set but doesn't match */
+		if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) {
+			continue;
+		}
+
+		value = (struct bt_gatt_chrc)BT_GATT_CHRC_INIT(
+			&u.uuid, chrc->value_handle, chrc->properties);
+		attr = (struct bt_gatt_attr)BT_GATT_ATTRIBUTE(
+			BT_UUID_GATT_CHRC, 0, NULL, NULL, &value);
+		attr.handle = handle;
+
+		if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+			return 0;
+		}
+	}
+
+	/* Whole PDU read without error */
+	if (length == 0U && handle) {
+		return handle;
+	}
+
+done:
+	params->func(conn, NULL, params);
+	return 0;
+}
+
+static void gatt_read_type_rsp(struct bt_conn *conn, uint8_t err,
+			       const void *pdu, uint16_t length,
+			       void *user_data)
+{
+	struct bt_gatt_discover_params *params = user_data;
+	uint16_t handle;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err) {
+		params->func(conn, NULL, params);
+		return;
+	}
+
+	if (params->type == BT_GATT_DISCOVER_INCLUDE) {
+		handle = parse_include(conn, pdu, params, length);
+	} else {
+		handle = parse_characteristic(conn, pdu, params, length);
+	}
+
+	if (!handle) {
+		return;
+	}
+
+	gatt_discover_next(conn, handle, params);
+}
+
+static int gatt_read_type(struct bt_conn *conn,
+			  struct bt_gatt_discover_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_type_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_TYPE_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->start_handle = sys_cpu_to_le16(params->start_handle);
+	req->end_handle = sys_cpu_to_le16(params->end_handle);
+
+	if (params->type == BT_GATT_DISCOVER_INCLUDE) {
+		net_buf_add_le16(buf, BT_UUID_GATT_INCLUDE_VAL);
+	} else {
+		net_buf_add_le16(buf, BT_UUID_GATT_CHRC_VAL);
+	}
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
+	       params->end_handle);
+
+	return gatt_send(conn, buf, gatt_read_type_rsp, params, NULL);
+}
+
+static uint16_t parse_service(struct bt_conn *conn, const void *pdu,
+				  struct bt_gatt_discover_params *params,
+				  uint16_t length)
+{
+	const struct bt_att_read_group_rsp *rsp = pdu;
+	uint16_t start_handle, end_handle = 0U;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+
+	/* Data can be either in UUID16 or UUID128 */
+	switch (rsp->len) {
+	case 6: /* UUID16 */
+		u.uuid.type = BT_UUID_TYPE_16;
+		break;
+	case 20: /* UUID128 */
+		u.uuid.type = BT_UUID_TYPE_128;
+		break;
+	default:
+		BT_ERR("Invalid data len %u", rsp->len);
+		goto done;
+	}
+
+	/* Parse services found */
+	for (length--, pdu = rsp->data; length >= rsp->len;
+	     length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
+		struct bt_uuid_16 uuid_svc;
+		struct bt_gatt_attr attr = {};
+		struct bt_gatt_service_val value;
+		const struct bt_att_group_data *data = pdu;
+
+		start_handle = sys_le16_to_cpu(data->start_handle);
+		if (!start_handle) {
+			goto done;
+		}
+
+		end_handle = sys_le16_to_cpu(data->end_handle);
+		if (!end_handle || end_handle < start_handle) {
+			goto done;
+		}
+
+		switch (u.uuid.type) {
+		case BT_UUID_TYPE_16:
+			memcpy(&u.u16.val, data->value, sizeof(u.u16.val));
+			u.u16.val = sys_le16_to_cpu(u.u16.val);
+			break;
+		case BT_UUID_TYPE_128:
+			memcpy(u.u128.val, data->value, sizeof(u.u128.val));
+			break;
+		}
+
+		BT_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s",
+		       start_handle, end_handle, bt_uuid_str(&u.uuid));
+
+		uuid_svc.uuid.type = BT_UUID_TYPE_16;
+		if (params->type == BT_GATT_DISCOVER_PRIMARY) {
+			uuid_svc.val = BT_UUID_GATT_PRIMARY_VAL;
+		} else {
+			uuid_svc.val = BT_UUID_GATT_SECONDARY_VAL;
+		}
+
+		value.end_handle = end_handle;
+		value.uuid = &u.uuid;
+
+		attr.uuid = &uuid_svc.uuid;
+		attr.handle = start_handle;
+		attr.user_data = &value;
+
+		if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+			return 0;
+		}
+	}
+
+	/* Whole PDU read without error */
+	if (length == 0U && end_handle) {
+		return end_handle;
+	}
+
+done:
+	params->func(conn, NULL, params);
+	return 0;
+}
+
+static void gatt_read_group_rsp(struct bt_conn *conn, uint8_t err,
+				const void *pdu, uint16_t length,
+				void *user_data)
+{
+	struct bt_gatt_discover_params *params = user_data;
+	uint16_t handle;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err) {
+		params->func(conn, NULL, params);
+		return;
+	}
+
+	handle = parse_service(conn, pdu, params, length);
+	if (!handle) {
+		return;
+	}
+
+	gatt_discover_next(conn, handle, params);
+}
+
+static int gatt_read_group(struct bt_conn *conn,
+			   struct bt_gatt_discover_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_group_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_GROUP_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->start_handle = sys_cpu_to_le16(params->start_handle);
+	req->end_handle = sys_cpu_to_le16(params->end_handle);
+
+	if (params->type == BT_GATT_DISCOVER_PRIMARY) {
+		net_buf_add_le16(buf, BT_UUID_GATT_PRIMARY_VAL);
+	} else {
+		net_buf_add_le16(buf, BT_UUID_GATT_SECONDARY_VAL);
+	}
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
+	       params->end_handle);
+
+	return gatt_send(conn, buf, gatt_read_group_rsp, params, NULL);
+}
+
+static void gatt_find_info_rsp(struct bt_conn *conn, uint8_t err,
+			       const void *pdu, uint16_t length,
+			       void *user_data)
+{
+	const struct bt_att_find_info_rsp *rsp = pdu;
+	struct bt_gatt_discover_params *params = user_data;
+	uint16_t handle = 0U;
+	uint16_t len;
+	union {
+		const struct bt_att_info_16 *i16;
+		const struct bt_att_info_128 *i128;
+	} info;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_128 u128;
+	} u;
+	int i;
+	bool skip = false;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err) {
+		goto done;
+	}
+
+	/* Data can be either in UUID16 or UUID128 */
+	switch (rsp->format) {
+	case BT_ATT_INFO_16:
+		u.uuid.type = BT_UUID_TYPE_16;
+		len = sizeof(*info.i16);
+		break;
+	case BT_ATT_INFO_128:
+		u.uuid.type = BT_UUID_TYPE_128;
+		len = sizeof(*info.i128);
+		break;
+	default:
+		BT_ERR("Invalid format %u", rsp->format);
+		goto done;
+	}
+
+	length--;
+
+	/* Check if there is a least one descriptor in the response */
+	if (length < len) {
+		goto done;
+	}
+
+	/* Parse descriptors found */
+	for (i = length / len, pdu = rsp->info; i != 0;
+	     i--, pdu = (const uint8_t *)pdu + len) {
+		struct bt_gatt_attr attr;
+
+		info.i16 = pdu;
+		handle = sys_le16_to_cpu(info.i16->handle);
+
+		if (skip) {
+			skip = false;
+			continue;
+		}
+
+		switch (u.uuid.type) {
+		case BT_UUID_TYPE_16:
+			u.u16.val = sys_le16_to_cpu(info.i16->uuid);
+			break;
+		case BT_UUID_TYPE_128:
+			memcpy(u.u128.val, info.i128->uuid, 16);
+			break;
+		}
+
+		BT_DBG("handle 0x%04x uuid %s", handle, bt_uuid_str(&u.uuid));
+
+		/* Skip if UUID is set but doesn't match */
+		if (params->uuid && bt_uuid_cmp(&u.uuid, params->uuid)) {
+			continue;
+		}
+
+		if (params->type == BT_GATT_DISCOVER_DESCRIPTOR) {
+			/* Skip attributes that are not considered
+			 * descriptors.
+			 */
+			if (!bt_uuid_cmp(&u.uuid, BT_UUID_GATT_PRIMARY) ||
+			    !bt_uuid_cmp(&u.uuid, BT_UUID_GATT_SECONDARY) ||
+			    !bt_uuid_cmp(&u.uuid, BT_UUID_GATT_INCLUDE)) {
+				continue;
+			}
+
+			/* If Characteristic Declaration skip ahead as the next
+			 * entry must be its value.
+			 */
+			if (!bt_uuid_cmp(&u.uuid, BT_UUID_GATT_CHRC)) {
+				skip = true;
+				continue;
+			}
+		}
+
+		attr = (struct bt_gatt_attr)BT_GATT_ATTRIBUTE(
+			&u.uuid, 0, NULL, NULL, NULL);
+		attr.handle = handle;
+
+		if (params->func(conn, &attr, params) == BT_GATT_ITER_STOP) {
+			return;
+		}
+	}
+
+	gatt_discover_next(conn, handle, params);
+
+	return;
+
+done:
+	params->func(conn, NULL, params);
+}
+
+static int gatt_find_info(struct bt_conn *conn,
+			  struct bt_gatt_discover_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_find_info_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_INFO_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->start_handle = sys_cpu_to_le16(params->start_handle);
+	req->end_handle = sys_cpu_to_le16(params->end_handle);
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle,
+	       params->end_handle);
+
+	return gatt_send(conn, buf, gatt_find_info_rsp, params, NULL);
+}
+
+int bt_gatt_discover(struct bt_conn *conn,
+		     struct bt_gatt_discover_params *params)
+{
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(params && params->func, "invalid parameters\n");
+	__ASSERT((params->start_handle && params->end_handle),
+		 "invalid parameters\n");
+	__ASSERT((params->start_handle <= params->end_handle),
+		 "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	switch (params->type) {
+	case BT_GATT_DISCOVER_PRIMARY:
+	case BT_GATT_DISCOVER_SECONDARY:
+		if (params->uuid) {
+			return gatt_find_type(conn, params);
+		}
+		return gatt_read_group(conn, params);
+	case BT_GATT_DISCOVER_INCLUDE:
+	case BT_GATT_DISCOVER_CHARACTERISTIC:
+		return gatt_read_type(conn, params);
+	case BT_GATT_DISCOVER_DESCRIPTOR:
+		/* Only descriptors can be filtered */
+		if (params->uuid &&
+		    (!bt_uuid_cmp(params->uuid, BT_UUID_GATT_PRIMARY) ||
+		     !bt_uuid_cmp(params->uuid, BT_UUID_GATT_SECONDARY) ||
+		     !bt_uuid_cmp(params->uuid, BT_UUID_GATT_INCLUDE) ||
+		     !bt_uuid_cmp(params->uuid, BT_UUID_GATT_CHRC))) {
+			return -EINVAL;
+		}
+		__fallthrough;
+	case BT_GATT_DISCOVER_ATTRIBUTE:
+		return gatt_find_info(conn, params);
+	default:
+		BT_ERR("Invalid discovery type: %u", params->type);
+	}
+
+	return -EINVAL;
+}
+
+static void parse_read_by_uuid(struct bt_conn *conn,
+			       struct bt_gatt_read_params *params,
+			       const void *pdu, uint16_t length)
+{
+	const struct bt_att_read_type_rsp *rsp = pdu;
+
+	/* Parse values found */
+	for (length--, pdu = rsp->data; length;
+	     length -= rsp->len, pdu = (const uint8_t *)pdu + rsp->len) {
+		const struct bt_att_data *data = pdu;
+		uint16_t handle;
+		uint16_t len;
+
+		handle = sys_le16_to_cpu(data->handle);
+
+		/* Handle 0 is invalid */
+		if (!handle) {
+			BT_ERR("Invalid handle");
+			return;
+		}
+
+		len = rsp->len > length ? length - 2 : rsp->len - 2;
+
+		BT_DBG("handle 0x%04x len %u value %u", handle, rsp->len, len);
+
+		/* Update start_handle */
+		params->by_uuid.start_handle = handle;
+
+		if (params->func(conn, 0, params, data->value, len) ==
+		    BT_GATT_ITER_STOP) {
+			return;
+		}
+
+		/* Check if long attribute */
+		if (rsp->len > length) {
+			break;
+		}
+
+		/* Stop if it's the last handle to be read */
+		if (params->by_uuid.start_handle == params->by_uuid.end_handle) {
+			params->func(conn, 0, params, NULL, 0);
+			return;
+		}
+
+		params->by_uuid.start_handle++;
+	}
+
+	/* Continue reading the attributes */
+	if (bt_gatt_read(conn, params) < 0) {
+		params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0);
+	}
+}
+
+static void gatt_read_rsp(struct bt_conn *conn, uint8_t err, const void *pdu,
+			  uint16_t length, void *user_data)
+{
+	struct bt_gatt_read_params *params = user_data;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err || !length) {
+		params->func(conn, err, params, NULL, 0);
+		return;
+	}
+
+	if (!params->handle_count) {
+		parse_read_by_uuid(conn, params, pdu, length);
+		return;
+	}
+
+	if (params->func(conn, 0, params, pdu, length) == BT_GATT_ITER_STOP) {
+		return;
+	}
+
+	/*
+	 * Core Spec 4.2, Vol. 3, Part G, 4.8.1
+	 * If the Characteristic Value is greater than (ATT_MTU - 1) octets
+	 * in length, the Read Long Characteristic Value procedure may be used
+	 * if the rest of the Characteristic Value is required.
+	 */
+	if (length < (bt_att_get_mtu(conn) - 1)) {
+		params->func(conn, 0, params, NULL, 0);
+		return;
+	}
+
+	params->single.offset += length;
+
+	/* Continue reading the attribute */
+	if (bt_gatt_read(conn, params) < 0) {
+		params->func(conn, BT_ATT_ERR_UNLIKELY, params, NULL, 0);
+	}
+}
+
+static int gatt_read_blob(struct bt_conn *conn,
+			  struct bt_gatt_read_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_blob_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_BLOB_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(params->single.handle);
+	req->offset = sys_cpu_to_le16(params->single.offset);
+
+	BT_DBG("handle 0x%04x offset 0x%04x", params->single.handle,
+	       params->single.offset);
+
+	return gatt_send(conn, buf, gatt_read_rsp, params, NULL);
+}
+
+static int gatt_read_uuid(struct bt_conn *conn,
+			  struct bt_gatt_read_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_type_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_TYPE_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->start_handle = sys_cpu_to_le16(params->by_uuid.start_handle);
+	req->end_handle = sys_cpu_to_le16(params->by_uuid.end_handle);
+
+	if (params->by_uuid.uuid->type == BT_UUID_TYPE_16) {
+		net_buf_add_le16(buf, BT_UUID_16(params->by_uuid.uuid)->val);
+	} else {
+		net_buf_add_mem(buf, BT_UUID_128(params->by_uuid.uuid)->val, 16);
+	}
+
+	BT_DBG("start_handle 0x%04x end_handle 0x%04x uuid %s",
+		params->by_uuid.start_handle, params->by_uuid.end_handle,
+		bt_uuid_str(params->by_uuid.uuid));
+
+	return gatt_send(conn, buf, gatt_read_rsp, params, NULL);
+}
+
+#if defined(CONFIG_BT_GATT_READ_MULTIPLE)
+static void gatt_read_mult_rsp(struct bt_conn *conn, uint8_t err, const void *pdu,
+			       uint16_t length, void *user_data)
+{
+	struct bt_gatt_read_params *params = user_data;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err || !length) {
+		params->func(conn, err, params, NULL, 0);
+		return;
+	}
+
+	params->func(conn, 0, params, pdu, length);
+
+	/* mark read as complete since read multiple is single response */
+	params->func(conn, 0, params, NULL, 0);
+}
+
+static int gatt_read_mult(struct bt_conn *conn,
+			  struct bt_gatt_read_params *params)
+{
+	struct net_buf *buf;
+	uint8_t i;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_REQ,
+				params->handle_count * sizeof(uint16_t));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	for (i = 0U; i < params->handle_count; i++) {
+		net_buf_add_le16(buf, params->handles[i]);
+	}
+
+	return gatt_send(conn, buf, gatt_read_mult_rsp, params, NULL);
+}
+
+#if defined(CONFIG_BT_EATT)
+static void gatt_read_mult_vl_rsp(struct bt_conn *conn, uint8_t err,
+				  const void *pdu, uint16_t length,
+				  void *user_data)
+{
+	struct bt_gatt_read_params *params = user_data;
+	const struct bt_att_read_mult_vl_rsp *rsp;
+	struct net_buf_simple buf;
+
+	BT_DBG("err 0x%02x", err);
+
+	if (err || !length) {
+		if (err == BT_ATT_ERR_NOT_SUPPORTED) {
+			gatt_read_mult(conn, params);
+		}
+		params->func(conn, err, params, NULL, 0);
+		return;
+	}
+
+	net_buf_simple_init_with_data(&buf, (void *)pdu, length);
+
+	while (buf.len >= sizeof(*rsp)) {
+		uint16_t len;
+
+		rsp = net_buf_simple_pull_mem(&buf, sizeof(*rsp));
+		len = sys_le16_to_cpu(rsp->len);
+
+		/* If a Length Value Tuple is truncated, then the amount of
+		 * Attribute Value will be less than the value of the Value
+		 * Length field.
+		 */
+		if (len > buf.len) {
+			len = buf.len;
+		}
+
+		params->func(conn, 0, params, rsp->value, len);
+
+		net_buf_simple_pull_mem(&buf, len);
+	}
+
+	/* mark read as complete since read multiple is single response */
+	params->func(conn, 0, params, NULL, 0);
+}
+
+static int gatt_read_mult_vl(struct bt_conn *conn,
+			      struct bt_gatt_read_params *params)
+{
+	struct net_buf *buf;
+	uint8_t i;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_MULT_VL_REQ,
+				params->handle_count * sizeof(uint16_t));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	for (i = 0U; i < params->handle_count; i++) {
+		net_buf_add_le16(buf, params->handles[i]);
+	}
+
+	return gatt_send(conn, buf, gatt_read_mult_vl_rsp, params, NULL);
+}
+#endif /* CONFIG_BT_EATT */
+
+#else
+static int gatt_read_mult(struct bt_conn *conn,
+			      struct bt_gatt_read_params *params)
+{
+	return -ENOTSUP;
+}
+
+static int gatt_read_mult_vl(struct bt_conn *conn,
+			      struct bt_gatt_read_params *params)
+{
+	return -ENOTSUP;
+}
+#endif /* CONFIG_BT_GATT_READ_MULTIPLE */
+
+int bt_gatt_read(struct bt_conn *conn, struct bt_gatt_read_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_read_req *req;
+
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(params && params->func, "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (params->handle_count == 0) {
+		return gatt_read_uuid(conn, params);
+	}
+
+	if (params->handle_count > 1) {
+#if defined(CONFIG_BT_EATT)
+		return gatt_read_mult_vl(conn, params);
+#else
+		return gatt_read_mult(conn, params);
+#endif /* CONFIG_BT_EATT */
+	}
+
+	if (params->single.offset) {
+		return gatt_read_blob(conn, params);
+	}
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(params->single.handle);
+
+	BT_DBG("handle 0x%04x", params->single.handle);
+
+	return gatt_send(conn, buf, gatt_read_rsp, params, NULL);
+}
+
+static void gatt_write_rsp(struct bt_conn *conn, uint8_t err, const void *pdu,
+			   uint16_t length, void *user_data)
+{
+	struct bt_gatt_write_params *params = user_data;
+
+	BT_DBG("err 0x%02x", err);
+
+	params->func(conn, err, params);
+}
+
+int bt_gatt_write_without_response_cb(struct bt_conn *conn, uint16_t handle,
+				      const void *data, uint16_t length, bool sign,
+				      bt_gatt_complete_func_t func,
+				      void *user_data)
+{
+	struct net_buf *buf;
+	struct bt_att_write_cmd *cmd;
+	size_t write;
+
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(handle, "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+#if defined(CONFIG_BT_SMP)
+	if (conn->encrypt) {
+		/* Don't need to sign if already encrypted */
+		sign = false;
+	}
+#endif
+
+	if (sign) {
+		buf = bt_att_create_pdu(conn, BT_ATT_OP_SIGNED_WRITE_CMD,
+					sizeof(*cmd) + length + 12);
+	} else {
+		buf = bt_att_create_pdu(conn, BT_ATT_OP_WRITE_CMD,
+					sizeof(*cmd) + length);
+	}
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	cmd = net_buf_add(buf, sizeof(*cmd));
+	cmd->handle = sys_cpu_to_le16(handle);
+
+	write = net_buf_append_bytes(buf, length, data, K_NO_WAIT, NULL, NULL);
+	if (write != length) {
+		BT_WARN("Unable to allocate length %u: only %zu written",
+			length, write);
+		net_buf_unref(buf);
+		return -ENOMEM;
+	}
+
+	BT_DBG("handle 0x%04x length %u", handle, length);
+
+	return bt_att_send(conn, buf, func, user_data);
+}
+
+static int gatt_exec_write(struct bt_conn *conn,
+			   struct bt_gatt_write_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_exec_write_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_EXEC_WRITE_REQ, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->flags = BT_ATT_FLAG_EXEC;
+
+	BT_DBG("");
+
+	return gatt_send(conn, buf, gatt_write_rsp, params, NULL);
+}
+
+static void gatt_prepare_write_rsp(struct bt_conn *conn, uint8_t err,
+				   const void *pdu, uint16_t length,
+				   void *user_data)
+{
+	struct bt_gatt_write_params *params = user_data;
+
+	BT_DBG("err 0x%02x", err);
+
+
+	/* Don't continue in case of error */
+	if (err) {
+		params->func(conn, err, params);
+		return;
+	}
+
+	/* If there is no more data execute */
+	if (!params->length) {
+		gatt_exec_write(conn, params);
+		return;
+	}
+
+	/* Write next chunk */
+	bt_gatt_write(conn, params);
+}
+
+static int gatt_prepare_write(struct bt_conn *conn,
+			      struct bt_gatt_write_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_prepare_write_req *req;
+	uint16_t len;
+	size_t write;
+
+	len = MIN(params->length, bt_att_get_mtu(conn) - sizeof(*req) - 1);
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_PREPARE_WRITE_REQ,
+				sizeof(*req) + len);
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(params->handle);
+	req->offset = sys_cpu_to_le16(params->offset);
+
+	/* Append as much as possible */
+	write = net_buf_append_bytes(buf, len, params->data, K_NO_WAIT,
+				     NULL, NULL);
+
+	/* Update params */
+	params->offset += write;
+	params->data = (const uint8_t *)params->data + len;
+	params->length -= write;
+
+	BT_DBG("handle 0x%04x offset %u len %u", params->handle, params->offset,
+	       params->length);
+
+	return gatt_send(conn, buf, gatt_prepare_write_rsp, params, NULL);
+}
+
+int bt_gatt_write(struct bt_conn *conn, struct bt_gatt_write_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_write_req *req;
+	size_t write;
+
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(params && params->func, "invalid parameters\n");
+	__ASSERT(params->handle, "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	/* Use Prepare Write if offset is set or Long Write is required */
+	if (params->offset ||
+	    params->length > (bt_att_get_mtu(conn) - sizeof(*req) - 1)) {
+		return gatt_prepare_write(conn, params);
+	}
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_WRITE_REQ,
+				sizeof(*req) + params->length);
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(params->handle);
+
+	write = net_buf_append_bytes(buf, params->length, params->data,
+				     K_NO_WAIT, NULL, NULL);
+	if (write != params->length) {
+		net_buf_unref(buf);
+		return -ENOMEM;
+	}
+
+	BT_DBG("handle 0x%04x length %u", params->handle, params->length);
+
+	return gatt_send(conn, buf, gatt_write_rsp, params, NULL);
+}
+
+static void gatt_write_ccc_rsp(struct bt_conn *conn, uint8_t err,
+			       const void *pdu, uint16_t length,
+			       void *user_data)
+{
+	struct bt_gatt_subscribe_params *params = user_data;
+
+	BT_DBG("err 0x%02x", err);
+
+	atomic_clear_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING);
+
+	/* if write to CCC failed we remove subscription and notify app */
+	if (err) {
+		struct gatt_sub *sub;
+		sys_snode_t *node, *tmp, *prev = NULL;
+
+		sub = gatt_sub_find(conn);
+		if (!sub) {
+			return;
+		}
+
+		SYS_SLIST_FOR_EACH_NODE_SAFE(&sub->list, node, tmp) {
+			if (node == &params->node) {
+				gatt_sub_remove(conn, sub, tmp, params);
+				break;
+			}
+
+			prev = node;
+		}
+	} else if (!params->value) {
+		/* Notify with NULL data to complete unsubscribe */
+		params->notify(conn, params, NULL, 0);
+	}
+
+	if (params->write) {
+		params->write(conn, err, NULL);
+	}
+}
+
+static int gatt_write_ccc(struct bt_conn *conn, uint16_t handle, uint16_t value,
+			  bt_att_func_t func,
+			  struct bt_gatt_subscribe_params *params)
+{
+	struct net_buf *buf;
+	struct bt_att_write_req *req;
+
+	buf = bt_att_create_pdu(conn, BT_ATT_OP_WRITE_REQ,
+				sizeof(*req) + sizeof(uint16_t));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->handle = sys_cpu_to_le16(handle);
+	net_buf_add_le16(buf, value);
+
+	BT_DBG("handle 0x%04x value 0x%04x", handle, value);
+
+	atomic_set_bit(params->flags, BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING);
+
+	return gatt_send(conn, buf, func, params, NULL);
+}
+
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+static uint8_t gatt_ccc_discover_cb(struct bt_conn *conn,
+				    const struct bt_gatt_attr *attr,
+				    struct bt_gatt_discover_params *params)
+{
+	struct bt_gatt_subscribe_params *sub_params = params->sub_params;
+
+	if (!attr) {
+		memset(params, 0, sizeof(*params));
+		sub_params->notify(conn, sub_params, NULL, 0);
+		return BT_GATT_ITER_STOP;
+	}
+
+	if (params->type == BT_GATT_DISCOVER_DESCRIPTOR) {
+		memset(params, 0, sizeof(*params));
+		sub_params->ccc_handle = attr->handle;
+
+		if (bt_gatt_subscribe(conn, sub_params)) {
+			sub_params->notify(conn, sub_params, NULL, 0);
+		}
+		/* else if no error occurred, then `bt_gatt_subscribe` will
+		 * call the notify function once subscribed.
+		 */
+
+		return BT_GATT_ITER_STOP;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int gatt_ccc_discover(struct bt_conn *conn,
+			     struct bt_gatt_subscribe_params *params)
+{
+	int err;
+	static struct bt_uuid_16 ccc_uuid = BT_UUID_INIT_16(0);
+
+	memcpy(&ccc_uuid, BT_UUID_GATT_CCC, sizeof(ccc_uuid));
+	memset(params->disc_params, 0, sizeof(*params->disc_params));
+
+	params->disc_params->sub_params = params;
+	params->disc_params->uuid = &ccc_uuid.uuid;
+	params->disc_params->type = BT_GATT_DISCOVER_DESCRIPTOR;
+	params->disc_params->start_handle = params->value_handle;
+	params->disc_params->end_handle = params->end_handle;
+	params->disc_params->func = gatt_ccc_discover_cb;
+
+	err = bt_gatt_discover(conn, params->disc_params);
+	if (err) {
+		BT_DBG("CCC Discovery failed (err %d)", err);
+		return err;
+	}
+	return 0;
+
+}
+#endif /* CONFIG_BT_GATT_AUTO_DISCOVER_CCC */
+
+int bt_gatt_subscribe(struct bt_conn *conn,
+		      struct bt_gatt_subscribe_params *params)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *tmp;
+	bool has_subscription = false;
+
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(params && params->notify,  "invalid parameters\n");
+	__ASSERT(params->value, "invalid parameters\n");
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+	__ASSERT(params->ccc_handle ||
+		 (params->end_handle && params->disc_params),
+		 "invalid parameters\n");
+#else
+	__ASSERT(params->ccc_handle, "invalid parameters\n");
+#endif
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	sub = gatt_sub_add(conn);
+	if (!sub) {
+		return -ENOMEM;
+	}
+
+	/* Lookup existing subscriptions */
+	SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, tmp, node) {
+		/* Fail if entry already exists */
+		if (tmp == params) {
+			gatt_sub_remove(conn, sub, NULL, NULL);
+			return -EALREADY;
+		}
+
+		/* Check if another subscription exists */
+		if (tmp->value_handle == params->value_handle &&
+		    tmp->value >= params->value) {
+			has_subscription = true;
+		}
+	}
+
+	/* Skip write if already subscribed */
+	if (!has_subscription) {
+		int err;
+
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+		if (!params->ccc_handle) {
+			err = gatt_ccc_discover(conn, params);
+			if (err) {
+				return err;
+			}
+		}
+#endif
+		err = gatt_write_ccc(conn, params->ccc_handle, params->value,
+				     gatt_write_ccc_rsp, params);
+		if (err) {
+			gatt_sub_remove(conn, sub, NULL, NULL);
+			return err;
+		}
+	}
+
+	/*
+	 * Add subscription before write complete as some implementation were
+	 * reported to send notification before reply to CCC write.
+	 */
+	sys_slist_prepend(&sub->list, &params->node);
+
+	return 0;
+}
+
+int bt_gatt_resubscribe(uint8_t id, const bt_addr_le_t *peer,
+			     struct bt_gatt_subscribe_params *params)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *tmp;
+
+	__ASSERT(params && params->notify,  "invalid parameters\n");
+	__ASSERT(params->value, "invalid parameters\n");
+	__ASSERT(params->ccc_handle, "invalid parameters\n");
+
+	sub = gatt_sub_add_by_addr(id, peer);
+	if (!sub) {
+		return -ENOMEM;
+	}
+
+	/* Lookup existing subscriptions */
+	SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, tmp, node) {
+		/* Fail if entry already exists */
+		if (tmp == params) {
+			gatt_sub_remove(NULL, sub, NULL, NULL);
+			return -EALREADY;
+		}
+	}
+
+	sys_slist_prepend(&sub->list, &params->node);
+	return 0;
+}
+
+int bt_gatt_unsubscribe(struct bt_conn *conn,
+			struct bt_gatt_subscribe_params *params)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *tmp, *next;
+	bool has_subscription = false, found = false;
+	sys_snode_t *prev = NULL;
+
+	__ASSERT(conn, "invalid parameters\n");
+	__ASSERT(params, "invalid parameters\n");
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		return -EINVAL;
+	}
+
+	/* Lookup existing subscriptions */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, tmp, next, node) {
+		/* Remove subscription */
+		if (params == tmp) {
+			found = true;
+			sys_slist_remove(&sub->list, prev, &tmp->node);
+			/* Attempt to cancel if write is pending */
+			if (atomic_test_bit(params->flags,
+			    BT_GATT_SUBSCRIBE_FLAG_WRITE_PENDING)) {
+				bt_gatt_cancel(conn, params);
+			}
+			continue;
+		} else {
+			prev = &tmp->node;
+		}
+
+		/* Check if there still remains any other subscription */
+		if (tmp->value_handle == params->value_handle) {
+			has_subscription = true;
+		}
+	}
+
+	if (!found) {
+		return -EINVAL;
+	}
+
+	if (has_subscription) {
+		/* Notify with NULL data to complete unsubscribe */
+		params->notify(conn, params, NULL, 0);
+		return 0;
+	}
+
+	params->value = 0x0000;
+
+	return gatt_write_ccc(conn, params->ccc_handle, params->value,
+			      gatt_write_ccc_rsp, params);
+}
+
+void bt_gatt_cancel(struct bt_conn *conn, void *params)
+{
+	bt_att_req_cancel(conn, params);
+}
+
+static void add_subscriptions(struct bt_conn *conn)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *params;
+
+	sub = gatt_sub_find(conn);
+	if (!sub) {
+		return;
+	}
+
+	/* Lookup existing subscriptions */
+	SYS_SLIST_FOR_EACH_CONTAINER(&sub->list, params, node) {
+		if (bt_addr_le_is_bonded(conn->id, &conn->le.dst) &&
+		    !atomic_test_bit(params->flags,
+				     BT_GATT_SUBSCRIBE_FLAG_NO_RESUB)) {
+			/* Force write to CCC to workaround devices that don't
+			 * track it properly.
+			 */
+			gatt_write_ccc(conn, params->ccc_handle, params->value,
+				       gatt_write_ccc_rsp, params);
+		}
+	}
+}
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+#define CCC_STORE_MAX 48
+
+static struct bt_gatt_ccc_cfg *ccc_find_cfg(struct _bt_gatt_ccc *ccc,
+					    const bt_addr_le_t *addr,
+					    uint8_t id)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(ccc->cfg); i++) {
+		if (id == ccc->cfg[i].id &&
+		    !bt_addr_le_cmp(&ccc->cfg[i].peer, addr)) {
+			return &ccc->cfg[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct addr_with_id {
+	const bt_addr_le_t *addr;
+	uint8_t id;
+};
+
+struct ccc_load {
+	struct addr_with_id addr_with_id;
+	struct ccc_store *entry;
+	size_t count;
+};
+
+static void ccc_clear(struct _bt_gatt_ccc *ccc,
+		      const bt_addr_le_t *addr,
+		      uint8_t id)
+{
+	struct bt_gatt_ccc_cfg *cfg;
+
+	cfg = ccc_find_cfg(ccc, addr, id);
+	if (!cfg) {
+		BT_DBG("Unable to clear CCC: cfg not found");
+		return;
+	}
+
+	clear_ccc_cfg(cfg);
+}
+
+static uint8_t ccc_load(const struct bt_gatt_attr *attr, uint16_t handle,
+			void *user_data)
+{
+	struct ccc_load *load = user_data;
+	struct _bt_gatt_ccc *ccc;
+	struct bt_gatt_ccc_cfg *cfg;
+
+	/* Check if attribute is a CCC */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	/* Clear if value was invalidated */
+	if (!load->entry) {
+		ccc_clear(ccc, load->addr_with_id.addr, load->addr_with_id.id);
+		return BT_GATT_ITER_CONTINUE;
+	} else if (!load->count) {
+		return BT_GATT_ITER_STOP;
+	}
+
+	/* Skip if value is not for the given attribute */
+	if (load->entry->handle != handle) {
+		/* If attribute handle is bigger then it means
+		 * the attribute no longer exists and cannot
+		 * be restored.
+		 */
+		if (load->entry->handle < handle) {
+			BT_DBG("Unable to restore CCC: handle 0x%04x cannot be"
+			       " found",  load->entry->handle);
+			goto next;
+		}
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	BT_DBG("Restoring CCC: handle 0x%04x value 0x%04x", load->entry->handle,
+	       load->entry->value);
+
+	cfg = ccc_find_cfg(ccc, load->addr_with_id.addr, load->addr_with_id.id);
+	if (!cfg) {
+		cfg = ccc_find_cfg(ccc, BT_ADDR_LE_ANY, 0);
+		if (!cfg) {
+			BT_DBG("Unable to restore CCC: no cfg left");
+			goto next;
+		}
+		bt_addr_le_copy(&cfg->peer, load->addr_with_id.addr);
+		cfg->id = load->addr_with_id.id;
+	}
+
+	cfg->value = load->entry->value;
+
+next:
+	load->entry++;
+	load->count--;
+
+	return load->count ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP;
+}
+            
+
+static int ccc_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		   void *cb_arg)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		struct ccc_store ccc_store[CCC_STORE_MAX];
+		struct ccc_load load;
+		bt_addr_le_t addr;
+		ssize_t len;
+		int err;
+		const char *next;
+
+		settings_name_next(name, &next);
+
+		if (!name) {
+			BT_ERR("Insufficient number of arguments");
+			return -EINVAL;
+		} else if (!next) {
+			load.addr_with_id.id = BT_ID_DEFAULT;
+		} else {
+			load.addr_with_id.id = strtol(next, NULL, 10);
+		}
+
+		err = bt_settings_decode_key(name, &addr);
+		if (err) {
+			BT_ERR("Unable to decode address %s", log_strdup(name));
+			return -EINVAL;
+		}
+
+		load.addr_with_id.addr = &addr;
+
+		if (len_rd) {
+			len = read_cb(cb_arg, ccc_store, sizeof(ccc_store));
+
+			if (len < 0) {
+				BT_ERR("Failed to decode value (err %zd)", len);
+				return len;
+			}
+
+			load.entry = ccc_store;
+			load.count = len / sizeof(*ccc_store);
+
+			for (size_t i = 0; i < load.count; i++) {
+				BT_DBG("Read CCC: handle 0x%04x value 0x%04x",
+				       ccc_store[i].handle, ccc_store[i].value);
+			}
+		} else {
+			load.entry = NULL;
+			load.count = 0;
+		}
+
+		bt_gatt_foreach_attr(0x0001, 0xffff, ccc_load, &load);
+
+		BT_DBG("Restored CCC for id:%" PRIu8 " addr:%s",
+		       load.addr_with_id.id,
+		       bt_addr_le_str(load.addr_with_id.addr));
+	}
+
+	return 0;
+}
+
+static int ccc_set_cb(const char *name, size_t len_rd, settings_read_cb read_cb,
+		      void *cb_arg)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING)) {
+		/* Only load CCCs on demand */
+		return 0;
+	}
+
+	return ccc_set(name, len_rd, read_cb, cb_arg);
+}
+
+//SETTINGS_STATIC_HANDLER_DEFINE(bt_ccc, "bt/ccc", NULL, ccc_set_cb, NULL, NULL);
+
+static int ccc_set_direct(const char *key, size_t len, settings_read_cb read_cb,
+			  void *cb_arg, void *param)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		const char *name;
+
+		BT_DBG("key: %s", log_strdup((const char *)param));
+
+		/* Only "bt/ccc" settings should ever come here */
+		if (!settings_name_steq((const char *)param, "bt/ccc", &name)) {
+			BT_ERR("Invalid key");
+			return -EINVAL;
+		}
+
+		return ccc_set(name, len, read_cb, cb_arg);
+	}
+	return 0;
+}
+
+void bt_gatt_connected(struct bt_conn *conn)
+{
+	struct conn_data data;
+
+	BT_DBG("bt_gatt_connected conn %p", conn);
+
+	data.conn = conn;
+	data.sec = BT_SECURITY_L1;
+
+	/* Load CCC settings from backend if bonded */
+	if (IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING) &&
+	    bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		char key[BT_SETTINGS_KEY_MAX];
+
+		if (conn->id) {
+			char id_str[4];
+
+			//u8_to_dec(id_str, sizeof(id_str), conn->id);
+			//bt_settings_encode_key(key, sizeof(key), "ccc",
+			//		       &conn->le.dst, id_str);
+		} else {
+			//bt_settings_encode_key(key, sizeof(key), "ccc",
+			//		       &conn->le.dst, NULL);
+		}
+
+		//settings_load_subtree_direct(key, ccc_set_direct, (void *)key);
+	}
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, update_ccc, &data);
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part C page 2192:
+	 *
+	 * 10.3.1.1 Handling of GATT indications and notifications
+	 *
+	 * A client â€œrequestsâ€?a server to send indications and notifications
+	 * by appropriately configuring the server via a Client Characteristic
+	 * Configuration Descriptor. Since the configuration is persistent
+	 * across a disconnection and reconnection, security requirements must
+	 * be checked against the configuration upon a reconnection before
+	 * sending indications or notifications. When a server reconnects to a
+	 * client to send an indication or notification for which security is
+	 * required, the server shall initiate or request encryption with the
+	 * client prior to sending an indication or notification. If the client
+	 * does not have an LTK indicating that the client has lost the bond,
+	 * enabling encryption will fail.
+	 */
+	if (IS_ENABLED(CONFIG_BT_SMP) &&
+	    bt_conn_get_security(conn) < data.sec) {
+		bt_conn_set_security(conn, data.sec);
+	}
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+	add_subscriptions(conn);
+#endif /* CONFIG_BT_GATT_CLIENT */
+}
+
+void bt_gatt_encrypt_change(struct bt_conn *conn)
+{
+	struct conn_data data;
+
+	BT_DBG("conn %p", conn);
+
+	data.conn = conn;
+	data.sec = BT_SECURITY_L1;
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, update_ccc, &data);
+}
+
+bool bt_gatt_change_aware(struct bt_conn *conn, bool req)
+{
+#if defined(CONFIG_BT_GATT_CACHING)
+	struct gatt_cf_cfg *cfg;
+
+	cfg = find_cf_cfg(conn);
+	if (!cfg || !CF_ROBUST_CACHING(cfg)) {
+		return true;
+	}
+
+	if (atomic_test_bit(cfg->flags, CF_CHANGE_AWARE)) {
+		return true;
+	}
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2350:
+	 * If a change-unaware client sends an ATT command, the server shall
+	 * ignore it.
+	 */
+	if (!req) {
+		return false;
+	}
+
+	/* BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part G page 2347:
+	 * 2.5.2.1 Robust Caching
+	 * A connected client becomes change-aware when...
+	 * The server sends the client a response with the error code set to
+	 * Database Out Of Sync and then the server receives another ATT
+	 * request from the client.
+	 */
+	if (atomic_test_bit(cfg->flags, CF_OUT_OF_SYNC)) {
+		atomic_clear_bit(cfg->flags, CF_OUT_OF_SYNC);
+		atomic_set_bit(cfg->flags, CF_CHANGE_AWARE);
+		BT_DBG("%s change-aware", bt_addr_le_str(&cfg->peer));
+		return true;
+	}
+
+	atomic_set_bit(cfg->flags, CF_OUT_OF_SYNC);
+
+	return false;
+#else
+	return true;
+#endif
+}
+
+static int bt_gatt_store_cf(struct bt_conn *conn)
+{
+#if defined(CONFIG_BT_GATT_CACHING)
+	struct gatt_cf_cfg *cfg;
+	char key[BT_SETTINGS_KEY_MAX];
+	char *str;
+	size_t len;
+	int err;
+
+	cfg = find_cf_cfg(conn);
+	if (!cfg) {
+		/* No cfg found, just clear it */
+		BT_DBG("No config for CF");
+		str = NULL;
+		len = 0;
+	} else {
+		str = (char *)cfg->data;
+		len = sizeof(cfg->data);
+
+		if (conn->id) {
+			char id_str[4];
+
+			//u8_to_dec(id_str, sizeof(id_str), conn->id);
+			//bt_settings_encode_key(key, sizeof(key), "cf",
+			//		       &conn->le.dst, id_str);
+		}
+	}
+
+	if (!cfg || !conn->id) {
+		//bt_settings_encode_key(key, sizeof(key), "cf",
+		//		       &conn->le.dst, NULL);
+	}
+
+	//err = settings_save_one(key, str, len);
+	if (err) {
+		BT_ERR("Failed to store Client Features (err %d)", err);
+		return err;
+	}
+
+	BT_DBG("Stored CF for %s (%s)", bt_addr_le_str(&conn->le.dst), log_strdup(key));
+#endif /* CONFIG_BT_GATT_CACHING */
+	return 0;
+
+}
+
+static struct gatt_cf_cfg *find_cf_cfg_by_addr(uint8_t id,
+					       const bt_addr_le_t *addr)
+{
+	if (IS_ENABLED(CONFIG_BT_GATT_CACHING)) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(cf_cfg); i++) {
+			if (id == cf_cfg[i].id &&
+			    !bt_addr_le_cmp(addr, &cf_cfg[i].peer)) {
+				return &cf_cfg[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+#if defined(CONFIG_BT_SETTINGS)
+
+struct ccc_save {
+	struct addr_with_id addr_with_id;
+	struct ccc_store store[CCC_STORE_MAX];
+	size_t count;
+};
+
+static uint8_t ccc_save(const struct bt_gatt_attr *attr, uint16_t handle,
+			void *user_data)
+{
+	struct ccc_save *save = user_data;
+	struct _bt_gatt_ccc *ccc;
+	struct bt_gatt_ccc_cfg *cfg;
+
+	/* Check if attribute is a CCC */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	/* Check if there is a cfg for the peer */
+	cfg = ccc_find_cfg(ccc, save->addr_with_id.addr, save->addr_with_id.id);
+	if (!cfg) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	BT_DBG("Storing CCCs handle 0x%04x value 0x%04x", handle, cfg->value);
+
+	save->store[save->count].handle = handle;
+	save->store[save->count].value = cfg->value;
+	save->count++;
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+int bt_gatt_store_ccc(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct ccc_save save;
+	char key[BT_SETTINGS_KEY_MAX];
+	size_t len;
+	char *str;
+	int err;
+
+	save.addr_with_id.addr = addr;
+	save.addr_with_id.id = id;
+	save.count = 0;
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, ccc_save, &save);
+
+	if (id) {
+		char id_str[4];
+
+		//u8_to_dec(id_str, sizeof(id_str), id);
+		//bt_settings_encode_key(key, sizeof(key), "ccc", addr, id_str);
+	} else {
+		//bt_settings_encode_key(key, sizeof(key), "ccc", addr, NULL);
+	}
+
+	if (save.count) {
+		str = (char *)save.store;
+		len = save.count * sizeof(*save.store);
+	} else {
+		/* No entries to encode, just clear */
+		str = NULL;
+		len = 0;
+	}
+
+	//err = settings_save_one(key, str, len);
+	if (err) {
+		BT_ERR("Failed to store CCCs (err %d)", err);
+		return err;
+	}
+
+	BT_DBG("Stored CCCs for %s (%s)", bt_addr_le_str(addr),
+	       log_strdup(key));
+	if (len) {
+		for (size_t i = 0; i < save.count; i++) {
+			BT_DBG("  CCC: handle 0x%04x value 0x%04x",
+			       save.store[i].handle, save.store[i].value);
+		}
+	} else {
+		BT_DBG("  CCC: NULL");
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_GATT_SERVICE_CHANGED)
+static int sc_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		  void *cb_arg)
+{
+	struct gatt_sc_cfg *cfg;
+	uint8_t id;
+	bt_addr_le_t addr;
+	ssize_t len;
+	int err;
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -EINVAL;
+	}
+
+	err = bt_settings_decode_key(name, &addr);
+	if (err) {
+		BT_ERR("Unable to decode address %s", log_strdup(name));
+		return -EINVAL;
+	}
+
+	settings_name_next(name, &next);
+
+	if (!next) {
+		id = BT_ID_DEFAULT;
+	} else {
+		id = strtol(next, NULL, 10);
+	}
+
+	cfg = find_sc_cfg(id, &addr);
+	if (!cfg && len_rd) {
+		/* Find and initialize a free sc_cfg entry */
+		cfg = find_sc_cfg(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
+		if (!cfg) {
+			BT_ERR("Unable to restore SC: no cfg left");
+			return -ENOMEM;
+		}
+
+		cfg->id = id;
+		bt_addr_le_copy(&cfg->peer, &addr);
+	}
+
+	if (len_rd) {
+		len = read_cb(cb_arg, &cfg->data, sizeof(cfg->data));
+		if (len < 0) {
+			BT_ERR("Failed to decode value (err %zd)", len);
+			return len;
+		}
+
+		BT_DBG("Read SC: len %zd", len);
+
+		BT_DBG("Restored SC for %s", bt_addr_le_str(&addr));
+	} else if (cfg) {
+		/* Clear configuration */
+		memset(cfg, 0, sizeof(*cfg));
+
+		BT_DBG("Removed SC for %s", bt_addr_le_str(&addr));
+	}
+
+	return 0;
+}
+
+static int sc_commit(void)
+{
+	atomic_clear_bit(gatt_sc.flags, SC_INDICATE_PENDING);
+
+	if (atomic_test_bit(gatt_sc.flags, SC_RANGE_CHANGED)) {
+		/* Schedule SC indication since the range has changed */
+		sc_work_submit(SC_TIMEOUT);
+	}
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_sc, "bt/sc", NULL, sc_set, sc_commit, NULL);
+#endif /* CONFIG_BT_GATT_SERVICE_CHANGED */
+
+#if defined(CONFIG_BT_GATT_CACHING)
+static int cf_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		  void *cb_arg)
+{
+	struct gatt_cf_cfg *cfg;
+	bt_addr_le_t addr;
+	const char *next;
+	ssize_t len;
+	int err;
+	uint8_t id;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -EINVAL;
+	}
+
+	err = bt_settings_decode_key(name, &addr);
+	if (err) {
+		BT_ERR("Unable to decode address %s", log_strdup(name));
+		return -EINVAL;
+	}
+
+	settings_name_next(name, &next);
+
+	if (!next) {
+		id = BT_ID_DEFAULT;
+	} else {
+		id = strtol(next, NULL, 10);
+	}
+
+	cfg = find_cf_cfg_by_addr(id, &addr);
+	if (!cfg) {
+		cfg = find_cf_cfg(NULL);
+		if (!cfg) {
+			BT_ERR("Unable to restore CF: no cfg left");
+			return -ENOMEM;
+		}
+
+		cfg->id = id;
+		bt_addr_le_copy(&cfg->peer, &addr);
+	}
+
+	if (len_rd) {
+		len = read_cb(cb_arg, cfg->data, sizeof(cfg->data));
+		if (len < 0) {
+			BT_ERR("Failed to decode value (err %zd)", len);
+			return len;
+		}
+
+		BT_DBG("Read CF: len %zd", len);
+	} else {
+		clear_cf_cfg(cfg);
+	}
+
+	BT_DBG("Restored CF for %s", bt_addr_le_str(&addr));
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_cf, "bt/cf", NULL, cf_set, NULL, NULL);
+
+static uint8_t stored_hash[16];
+
+static int db_hash_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	ssize_t len;
+
+	len = read_cb(cb_arg, stored_hash, sizeof(stored_hash));
+	if (len < 0) {
+		BT_ERR("Failed to decode value (err %zd)", len);
+		return len;
+	}
+
+	BT_HEXDUMP_DBG(stored_hash, sizeof(stored_hash), "Stored Hash: ");
+
+	return 0;
+}
+
+static int db_hash_commit(void)
+{
+	int err;
+
+	/* Stop work and generate the hash */
+	err = k_delayed_work_cancel(&db_hash_work);
+	if (!err) {
+		db_hash_gen(false);
+	}
+
+	/* Check if hash matches then skip SC update */
+	if (!memcmp(stored_hash, db_hash, sizeof(stored_hash))) {
+		BT_DBG("Database Hash matches");
+		k_delayed_work_cancel(&gatt_sc.work);
+		atomic_clear_bit(gatt_sc.flags, SC_RANGE_CHANGED);
+		return 0;
+	}
+
+	BT_HEXDUMP_DBG(db_hash, sizeof(db_hash), "New Hash: ");
+
+	/**
+	 * GATT database has been modified since last boot, likely due to
+	 * a firmware update or a dynamic service that was not re-registered on
+	 * boot. Indicate Service Changed to all bonded devices for the full
+	 * database range to invalidate client-side cache and force discovery on
+	 * reconnect.
+	 */
+	sc_indicate(0x0001, 0xffff);
+
+	/* Hash did not match overwrite with current hash */
+	db_hash_store();
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_hash, "bt/hash", NULL, db_hash_set,
+			       db_hash_commit, NULL);
+#endif /*CONFIG_BT_GATT_CACHING */
+#endif /* CONFIG_BT_SETTINGS */
+
+static uint8_t remove_peer_from_attr(const struct bt_gatt_attr *attr,
+				     uint16_t handle, void *user_data)
+{
+	const struct addr_with_id *addr_with_id = user_data;
+	struct _bt_gatt_ccc *ccc;
+	struct bt_gatt_ccc_cfg *cfg;
+
+	/* Check if attribute is a CCC */
+	if (attr->write != bt_gatt_attr_write_ccc) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ccc = attr->user_data;
+
+	/* Check if there is a cfg for the peer */
+	cfg = ccc_find_cfg(ccc, addr_with_id->addr, addr_with_id->id);
+	if (cfg) {
+		memset(cfg, 0, sizeof(*cfg));
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int bt_gatt_clear_ccc(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct addr_with_id addr_with_id = {
+		.addr = addr,
+		.id = id,
+	};
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, remove_peer_from_attr,
+			     &addr_with_id);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		char key[BT_SETTINGS_KEY_MAX];
+
+		if (id) {
+			char id_str[4];
+
+			//u8_to_dec(id_str, sizeof(id_str), id);
+			//bt_settings_encode_key(key, sizeof(key), "ccc",
+			//		       addr, id_str);
+		} else {
+			//bt_settings_encode_key(key, sizeof(key), "ccc",
+			//		       addr, NULL);
+		}
+
+		return settings_delete(key);
+	}
+
+	return 0;
+}
+
+static int bt_gatt_clear_cf(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct gatt_cf_cfg *cfg;
+
+	cfg = find_cf_cfg_by_addr(id, addr);
+	if (cfg) {
+		clear_cf_cfg(cfg);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		char key[BT_SETTINGS_KEY_MAX];
+
+		if (id) {
+			char id_str[4];
+
+			//u8_to_dec(id_str, sizeof(id_str), id);
+			//bt_settings_encode_key(key, sizeof(key), "cf",
+			//		       addr, id_str);
+		} else {
+			//bt_settings_encode_key(key, sizeof(key), "cf",
+			//		       addr, NULL);
+		}
+
+		return settings_delete(key);
+	}
+
+	return 0;
+
+}
+
+
+static struct gatt_sub *find_gatt_sub(uint8_t id, const bt_addr_le_t *addr)
+{
+	for (int i = 0; i < ARRAY_SIZE(subscriptions); i++) {
+		struct gatt_sub *sub = &subscriptions[i];
+
+		if (id == sub->id &&
+		    !bt_addr_le_cmp(addr, &sub->peer)) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static void bt_gatt_clear_subscriptions(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct gatt_sub *sub;
+	struct bt_gatt_subscribe_params *params, *tmp;
+	sys_snode_t *prev = NULL;
+
+	sub = find_gatt_sub(id, addr);
+	if (!sub) {
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&sub->list, params, tmp,
+					  node) {
+		params->value = 0U;
+		gatt_sub_remove(NULL, sub, prev, params);
+	}
+}
+
+int bt_gatt_clear(uint8_t id, const bt_addr_le_t *addr)
+{
+	int err;
+
+	err = bt_gatt_clear_ccc(id, addr);
+	if (err < 0) {
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_GATT_SERVICE_CHANGED)) {
+		err = bt_gatt_clear_sc(id, addr);
+		if (err < 0) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_GATT_CACHING)) {
+		err = bt_gatt_clear_cf(id, addr);
+		if (err < 0) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_GATT_CLIENT)) {
+		bt_gatt_clear_subscriptions(id, addr);
+	}
+
+	return 0;
+}
+
+void bt_gatt_disconnected(struct bt_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+	bt_gatt_foreach_attr(0x0001, 0xffff, disconnected_cb, conn);
+
+#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE)
+	gatt_ccc_conn_unqueue(conn);
+
+	if (gatt_ccc_conn_queue_is_empty()) {
+		k_delayed_work_cancel(&gatt_ccc_store.work);
+	}
+#endif
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+	    bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		bt_gatt_store_ccc(conn->id, &conn->le.dst);
+		bt_gatt_store_cf(conn);
+	}
+
+	/* Make sure to clear the CCC entry when using lazy loading */
+	if (IS_ENABLED(CONFIG_BT_SETTINGS_CCC_LAZY_LOADING) &&
+	    bt_addr_le_is_bonded(conn->id, &conn->le.dst)) {
+		struct addr_with_id addr_with_id = {
+			.addr = &conn->le.dst,
+			.id = conn->id,
+		};
+		bt_gatt_foreach_attr(0x0001, 0xffff,
+				     remove_peer_from_attr,
+				     &addr_with_id);
+	}
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+	remove_subscriptions(conn);
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+#if defined(CONFIG_BT_GATT_CACHING)
+	remove_cf_cfg(conn);
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/gatt_internal.h	(working copy)
@@ -0,0 +1,58 @@
+/** @file
+ *  @brief Internal API for Generic Attribute Profile handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_GATT_CENTRAL_ADDR_RES_NOT_SUPP	0
+#define BT_GATT_CENTRAL_ADDR_RES_SUPP		1
+
+#define BT_GATT_PERM_READ_MASK			(BT_GATT_PERM_READ | \
+						BT_GATT_PERM_READ_ENCRYPT | \
+						BT_GATT_PERM_READ_AUTHEN)
+#define BT_GATT_PERM_WRITE_MASK			(BT_GATT_PERM_WRITE | \
+						BT_GATT_PERM_WRITE_ENCRYPT | \
+						BT_GATT_PERM_WRITE_AUTHEN)
+#define BT_GATT_PERM_ENCRYPT_MASK		(BT_GATT_PERM_READ_ENCRYPT | \
+						BT_GATT_PERM_WRITE_ENCRYPT)
+#define BT_GATT_PERM_AUTHEN_MASK		(BT_GATT_PERM_READ_AUTHEN | \
+						BT_GATT_PERM_WRITE_AUTHEN)
+
+void bt_gatt_init(void);
+void bt_gatt_connected(struct bt_conn *conn);
+void bt_gatt_encrypt_change(struct bt_conn *conn);
+void bt_gatt_disconnected(struct bt_conn *conn);
+
+bool bt_gatt_change_aware(struct bt_conn *conn, bool req);
+
+int bt_gatt_store_ccc(uint8_t id, const bt_addr_le_t *addr);
+
+int bt_gatt_clear(uint8_t id, const bt_addr_le_t *addr);
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+void bt_gatt_notification(struct bt_conn *conn, uint16_t handle,
+			  const void *data, uint16_t length);
+
+void bt_gatt_mult_notification(struct bt_conn *conn, const void *data,
+			       uint16_t length);
+#else
+static inline void bt_gatt_notification(struct bt_conn *conn, uint16_t handle,
+					const void *data, uint16_t length)
+{
+}
+
+static inline void bt_gatt_mult_notification(struct bt_conn *conn,
+					     const void *data, uint16_t length)
+{
+}
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+struct bt_gatt_attr;
+
+/* Check attribute permission */
+uint8_t bt_gatt_check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			uint8_t mask);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_common.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_common.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_common.c	(working copy)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <sys/byteorder.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+struct net_buf *bt_hci_evt_create(uint8_t evt, uint8_t len)
+{
+	struct bt_hci_evt_hdr *hdr;
+	struct net_buf *buf;
+
+	buf = bt_buf_get_evt(evt, false, K_FOREVER);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->evt = evt;
+	hdr->len = len;
+
+	return buf;
+}
+
+struct net_buf *bt_hci_cmd_complete_create(uint16_t op, uint8_t plen)
+{
+	struct net_buf *buf;
+	struct bt_hci_evt_cmd_complete *cc;
+
+	buf = bt_hci_evt_create(BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen);
+
+	cc = net_buf_add(buf, sizeof(*cc));
+	cc->ncmd = 1U;
+	cc->opcode = sys_cpu_to_le16(op);
+
+	return buf;
+}
+
+struct net_buf *bt_hci_cmd_status_create(uint16_t op, uint8_t status)
+{
+	struct net_buf *buf;
+	struct bt_hci_evt_cmd_status *cs;
+
+	buf = bt_hci_evt_create(BT_HCI_EVT_CMD_STATUS, sizeof(*cs));
+
+	cs = net_buf_add(buf, sizeof(*cs));
+	cs->status = status;
+	cs->ncmd = 1U;
+	cs->opcode = sys_cpu_to_le16(op);
+
+	return buf;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.h	(working copy)
@@ -0,0 +1,353 @@
+/* hci_core.h - Bluetooth HCI core access */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* LL connection parameters */
+#define LE_CONN_LATENCY		0x0000
+#define LE_CONN_TIMEOUT		0x002a
+
+#if defined(CONFIG_BT_BREDR)
+#define LMP_FEAT_PAGES_COUNT	3
+#else
+#define LMP_FEAT_PAGES_COUNT	1
+#endif
+
+/* SCO  settings */
+#define BT_VOICE_CVSD_16BIT     0x0060
+
+/* k_poll event tags */
+enum {
+	BT_EVENT_CMD_TX,
+	BT_EVENT_CONN_TX_QUEUE,
+};
+
+/* bt_dev flags: the flags defined here represent BT controller state */
+enum {
+	BT_DEV_ENABLE,
+	BT_DEV_READY,
+	BT_DEV_PRESET_ID,
+	BT_DEV_HAS_PUB_KEY,
+	BT_DEV_PUB_KEY_BUSY,
+
+	BT_DEV_SCANNING,
+	BT_DEV_EXPLICIT_SCAN,
+	BT_DEV_ACTIVE_SCAN,
+	BT_DEV_SCAN_FILTER_DUP,
+	BT_DEV_SCAN_WL,
+	BT_DEV_SCAN_LIMITED,
+	BT_DEV_INITIATING,
+
+	BT_DEV_RPA_VALID,
+	BT_DEV_RPA_TIMEOUT_SET,
+
+	BT_DEV_ID_PENDING,
+	BT_DEV_STORE_ID,
+
+#if defined(CONFIG_BT_BREDR)
+	BT_DEV_ISCAN,
+	BT_DEV_PSCAN,
+	BT_DEV_INQUIRY,
+#endif /* CONFIG_BT_BREDR */
+
+	/* Total number of flags - must be at the end of the enum */
+	BT_DEV_NUM_FLAGS,
+};
+
+/* Flags which should not be cleared upon HCI_Reset */
+#define BT_DEV_PERSISTENT_FLAGS (BIT(BT_DEV_ENABLE) | \
+				 BIT(BT_DEV_PRESET_ID))
+
+enum {
+	/* Advertising set has been created in the host. */
+	BT_ADV_CREATED,
+	/* Advertising parameters has been set in the controller.
+	 * This implies that the advertising set has been created in the
+	 * controller.
+	 */
+	BT_ADV_PARAMS_SET,
+	/* Advertising data has been set in the controller. */
+	BT_ADV_DATA_SET,
+	/* Advertising random address pending to be set in the controller. */
+	BT_ADV_RANDOM_ADDR_PENDING,
+	/* The private random address of the advertiser is valid for this cycle
+	 * of the RPA timeout.
+	 */
+	BT_ADV_RPA_VALID,
+	/* The advertiser set is limited by a timeout, or number of advertising
+	 * events, or both.
+	 */
+	BT_ADV_LIMITED,
+	/* Advertiser set is currently advertising in the controller. */
+	BT_ADV_ENABLED,
+	/* Advertiser should include name in advertising data */
+	BT_ADV_INCLUDE_NAME,
+	/* Advertiser set is connectable */
+	BT_ADV_CONNECTABLE,
+	/* Advertiser set is scannable */
+	BT_ADV_SCANNABLE,
+	/* Advertiser set is using extended advertising */
+	BT_ADV_EXT_ADV,
+	/* Advertiser set has disabled the use of private addresses and is using
+	 * the identity address instead.
+	 */
+	BT_ADV_USE_IDENTITY,
+	/* Advertiser has been configured to keep advertising after a connection
+	 * has been established as long as there are connections available.
+	 */
+	BT_ADV_PERSIST,
+	/* Advertiser has been temporarily disabled. */
+	BT_ADV_PAUSED,
+	/* Periodic Advertising has been enabled in the controller. */
+	BT_PER_ADV_ENABLED,
+	/* Periodic Advertising parameters has been set in the controller. */
+	BT_PER_ADV_PARAMS_SET,
+
+	BT_ADV_NUM_FLAGS,
+};
+
+struct bt_le_ext_adv {
+	/* ID Address used for advertising */
+	uint8_t                    id;
+
+	/* Advertising handle */
+	uint16_t			handle;
+
+	/* Current local Random Address */
+	bt_addr_le_t		random_addr;
+
+	/* Current target address */
+	bt_addr_le_t            target_addr;
+
+	ATOMIC_DEFINE(flags, BT_ADV_NUM_FLAGS);
+
+#if defined(CONFIG_BT_EXT_ADV)
+	const struct bt_le_ext_adv_cb *cb;
+
+	/* TX Power in use by the controller */
+	int8_t                    tx_power;
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+};
+
+
+enum {
+	/** Periodic Advertising Sync has been created in the host. */
+	BT_PER_ADV_SYNC_CREATED,
+
+	/** Periodic advertising is in sync and can be terminated */
+	BT_PER_ADV_SYNC_SYNCED,
+
+	/** Periodic advertising is attempting sync sync */
+	BT_PER_ADV_SYNC_SYNCING,
+
+	BT_PER_ADV_SYNC_NUM_FLAGS,
+};
+
+struct bt_le_per_adv_sync {
+	/** Periodic Advertiser Address */
+	bt_addr_le_t addr;
+
+	/** Advertiser SID */
+	uint8_t sid;
+
+	/** Sync handle */
+	uint16_t handle;
+
+	/** Periodic advertising interval (N * 1.25MS) */
+	uint16_t interval;
+
+	/** Periodic advertising advertiser clock accuracy (ppm) */
+	uint16_t clock_accuracy;
+
+	/** Advertiser PHY */
+	uint8_t phy;
+
+	/** Flags */
+	ATOMIC_DEFINE(flags, BT_PER_ADV_SYNC_NUM_FLAGS);
+
+	/** Callbacks */
+	const struct bt_le_per_adv_sync_cb *cb;
+};
+
+struct bt_dev_le {
+	/* LE features */
+	uint8_t			features[8];
+	/* LE states */
+	uint64_t			states;
+
+#if defined(CONFIG_BT_CONN)
+	/* Controller buffer information */
+	uint16_t		mtu;
+	//struct k_sem		pkts;
+	uint16_t		acl_mtu;
+	//struct k_sem		acl_pkts;
+#if defined(CONFIG_BT_ISO)
+	uint16_t		iso_mtu;
+	//struct k_sem		iso_pkts;
+#endif /* CONFIG_BT_ISO */
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_SMP)
+	/* Size of the the controller resolving list */
+	uint8_t                    rl_size;
+	/* Number of entries in the resolving list. rl_entries > rl_size
+	 * means that host-side resolving is used.
+	 */
+	uint8_t                    rl_entries;
+#endif /* CONFIG_BT_SMP */
+};
+
+#if defined(CONFIG_BT_BREDR)
+struct bt_dev_br {
+	/* Max controller's acceptable ACL packet length */
+	uint16_t         mtu;
+	struct k_sem  pkts;
+	uint16_t         esco_pkt_type;
+};
+#endif
+
+/* The theoretical max for these is 8 and 64, but there's no point
+ * in allocating the full memory if we only support a small subset.
+ * These values must be updated whenever the host implementation is
+ * extended beyond the current values.
+ */
+#define BT_DEV_VS_FEAT_MAX  1
+#define BT_DEV_VS_CMDS_MAX  2
+
+/* State tracking for the local Bluetooth controller */
+struct bt_dev {
+	/* Local Identity Address(es) */
+	bt_addr_le_t            id_addr[CONFIG_BT_ID_MAX];
+	uint8_t                    id_count;
+
+	struct bt_conn_le_create_param create_param;
+
+#if !defined(CONFIG_BT_EXT_ADV)
+	/* Legacy advertiser */
+	struct bt_le_ext_adv    adv;
+#else
+	/* Pointer to reserved advertising set */
+	struct bt_le_ext_adv    *adv;
+#endif
+	/* Current local Random Address */
+	bt_addr_le_t            random_addr;
+	uint8_t                    adv_conn_id;
+
+	/* Controller version & manufacturer information */
+	uint8_t			hci_version;
+	uint8_t			lmp_version;
+	uint16_t			hci_revision;
+	uint16_t			lmp_subversion;
+	uint16_t			manufacturer;
+
+	/* LMP features (pages 0, 1, 2) */
+	uint8_t			features[LMP_FEAT_PAGES_COUNT][8];
+
+	/* Supported commands */
+	uint8_t			supported_commands[64];
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+	/* Vendor HCI support */
+	uint8_t                    vs_features[BT_DEV_VS_FEAT_MAX];
+	uint8_t                    vs_commands[BT_DEV_VS_CMDS_MAX];
+#endif
+
+	//struct k_work           init;
+
+	ATOMIC_DEFINE(flags, BT_DEV_NUM_FLAGS);
+
+	/* LE controller specific features */
+	struct bt_dev_le	le;
+
+#if defined(CONFIG_BT_BREDR)
+	/* BR/EDR controller specific features */
+	struct bt_dev_br	br;
+#endif
+
+	/* Number of commands controller can accept */
+	//struct k_sem		ncmd_sem;
+
+	/* Last sent HCI command */
+	struct net_buf		*sent_cmd;
+
+#if !defined(CONFIG_BT_RECV_IS_RX_THREAD)
+	/* Queue for incoming HCI events & ACL data */
+	struct k_fifo		rx_queue;
+#endif
+
+	/* Queue for outgoing HCI commands */
+	struct k_fifo		cmd_tx_queue;
+
+	/* Registered HCI driver */
+	const struct bt_hci_driver *drv;
+
+#if defined(CONFIG_BT_PRIVACY)
+	/* Local Identity Resolving Key */
+	uint8_t			irk[CONFIG_BT_ID_MAX][16];
+
+	/* Work used for RPA rotation */
+	struct k_delayed_work rpa_update;
+#endif
+
+	/* Local Name */
+#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
+	char			name[CONFIG_BT_DEVICE_NAME_MAX + 1];
+#endif
+};
+
+extern struct bt_dev bt_dev;
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+extern const struct bt_conn_auth_cb *bt_auth;
+
+enum bt_security_err bt_security_err_get(uint8_t hci_err);
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+int bt_hci_disconnect(uint16_t handle, uint8_t reason);
+
+bool bt_le_conn_params_valid(const struct bt_le_conn_param *param);
+int bt_le_set_data_len(struct bt_conn *conn, uint16_t tx_octets, uint16_t tx_time);
+int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys,
+		  uint8_t pref_tx_phy, uint8_t pref_rx_phy, uint8_t phy_opts);
+
+int bt_le_scan_update(bool fast_scan);
+
+int bt_le_create_conn(const struct bt_conn *conn);
+int bt_le_create_conn_cancel(void);
+
+bool bt_addr_le_is_bonded(uint8_t id, const bt_addr_le_t *addr);
+const bt_addr_le_t *bt_lookup_id_addr(uint8_t id, const bt_addr_le_t *addr);
+
+int bt_send(struct net_buf *buf);
+
+/* Don't require everyone to include keys.h */
+struct bt_keys;
+void bt_id_add(struct bt_keys *keys);
+void bt_id_del(struct bt_keys *keys);
+
+int bt_setup_random_id_addr(void);
+void bt_setup_public_id_addr(void);
+
+void bt_finalize_init(void);
+
+int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
+			     const struct bt_data *ad, size_t ad_len,
+			     const struct bt_data *sd, size_t sd_len,
+			     const bt_addr_le_t *peer);
+
+void bt_le_adv_resume(void);
+bool bt_le_scan_random_addr_check(void);
+
+/* HCI event handlers */
+void hci_evt_pin_code_req(struct net_buf *buf);
+void hci_evt_link_key_notify(struct net_buf *buf);
+void hci_evt_link_key_req(struct net_buf *buf);
+void hci_evt_io_capa_resp(struct net_buf *buf);
+void hci_evt_io_capa_req(struct net_buf *buf);
+void hci_evt_ssp_complete(struct net_buf *buf);
+void hci_evt_user_confirm_req(struct net_buf *buf);
+void hci_evt_user_passkey_notify(struct net_buf *buf);
+void hci_evt_user_passkey_req(struct net_buf *buf);
+void hci_evt_auth_complete(struct net_buf *buf);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_core.c	(working copy)
@@ -0,0 +1,9536 @@
+/* hci_core.c - HCI core Bluetooth handling */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <sys/slist.h>
+#include <sys/byteorder.h>
+#include <sys/__assert.h>
+
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_vs.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_hci_core
+#include "common/log.h"
+
+#include "common/rpa.h"
+#include "keys.h"
+#include "monitor.h"
+#include "hci_core.h"
+#include "hci_ecc.h"
+#include "ecc.h"
+
+#include "conn_internal.h"
+#include "audio/iso_internal.h"
+#include "l2cap_internal.h"
+#include "gatt_internal.h"
+#include "smp.h"
+#include "crypto.h"
+#include "settings.h"
+
+#if !defined(CONFIG_BT_EXT_ADV_LEGACY_SUPPORT)
+#undef BT_FEAT_LE_EXT_ADV
+#define BT_FEAT_LE_EXT_ADV(feat)  1
+#endif
+
+/* Peripheral timeout to initialize Connection Parameter Update procedure */
+#define CONN_UPDATE_TIMEOUT  K_MSEC(CONFIG_BT_CONN_PARAM_UPDATE_TIMEOUT)
+#define RPA_TIMEOUT_MS       (CONFIG_BT_RPA_TIMEOUT * MSEC_PER_SEC)
+#define RPA_TIMEOUT          K_MSEC(RPA_TIMEOUT_MS)
+
+#define HCI_CMD_TIMEOUT      K_SECONDS(10)
+
+/* Stacks for the threads */
+#if !defined(CONFIG_BT_RECV_IS_RX_THREAD)
+//static struct k_thread rx_thread_data;
+//static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE);
+#endif
+//static struct k_thread tx_thread_data;
+//static K_KERNEL_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
+
+//static void init_work(struct k_work *work);
+
+struct bt_dev bt_dev = {
+	//.init          = Z_WORK_INITIALIZER(init_work),
+	/* Give cmd_sem allowing to send first HCI_Reset cmd, the only
+	 * exception is if the controller requests to wait for an
+	 * initial Command Complete for NOP.
+	 */
+#if !defined(CONFIG_BT_WAIT_NOP)
+	//.ncmd_sem      = Z_SEM_INITIALIZER(bt_dev.ncmd_sem, 1, 1),
+#else
+	.ncmd_sem      = Z_SEM_INITIALIZER(bt_dev.ncmd_sem, 0, 1),
+#endif
+	.cmd_tx_queue  = Z_FIFO_INITIALIZER(bt_dev.cmd_tx_queue),
+#if !defined(CONFIG_BT_RECV_IS_RX_THREAD)
+	.rx_queue      = Z_FIFO_INITIALIZER(bt_dev.rx_queue),
+#endif
+};
+
+static bt_ready_cb_t ready_cb;
+
+static bt_le_scan_cb_t *scan_dev_found_cb;
+
+#if defined(CONFIG_BT_OBSERVER)
+static int set_le_scan_enable(uint8_t enable);
+static sys_slist_t scan_cbs = SYS_SLIST_STATIC_INIT(&scan_cbs);
+#endif /* defined(CONFIG_BT_OBSERVER) */
+
+#if defined(CONFIG_BT_EXT_ADV)
+static struct bt_le_ext_adv adv_pool[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
+
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+static struct bt_le_per_adv_sync *get_pending_per_adv_sync(void);
+static struct bt_le_per_adv_sync per_adv_sync_pool[CONFIG_BT_PER_ADV_SYNC_MAX];
+static sys_slist_t pa_sync_cbs = SYS_SLIST_STATIC_INIT(&pa_sync_cbs);
+#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+#if defined(CONFIG_BT_HCI_VS_EVT_USER)
+static bt_hci_vnd_evt_cb_t *hci_vnd_evt_cb;
+#endif /* CONFIG_BT_HCI_VS_EVT_USER */
+
+#if defined(CONFIG_BT_ECC)
+static uint8_t pub_key[64];
+static struct bt_pub_key_cb *pub_key_cb;
+static bt_dh_key_cb_t dh_key_cb;
+#endif /* CONFIG_BT_ECC */
+
+#if defined(CONFIG_BT_BREDR)
+static bt_br_discovery_cb_t *discovery_cb;
+struct bt_br_discovery_result *discovery_results;
+static size_t discovery_results_size;
+static size_t discovery_results_count;
+#endif /* CONFIG_BT_BREDR */
+
+struct cmd_state_set {
+	atomic_t *target;
+	int bit;
+	bool val;
+};
+
+void cmd_state_set_init(struct cmd_state_set *state, atomic_t *target, int bit,
+			bool val)
+{
+	state->target = target;
+	state->bit = bit;
+	state->val = val;
+}
+
+struct cmd_data {
+	/** HCI status of the command completion */
+	uint8_t  status;
+
+	/** The command OpCode that the buffer contains */
+	uint16_t opcode;
+
+	/** The state to update when command completes with success. */
+	struct cmd_state_set *state;
+
+	/** Used by bt_hci_cmd_send_sync. */
+	struct k_sem *sync;
+};
+
+struct acl_data {
+	/** BT_BUF_ACL_IN */
+	uint8_t  type;
+
+	/* Index into the bt_conn storage array */
+	uint8_t  index;
+
+	/** ACL connection handle */
+	uint16_t handle;
+};
+
+static struct cmd_data cmd_data[CONFIG_BT_HCI_CMD_COUNT];
+
+#define cmd(buf) (&cmd_data[net_buf_id(buf)])
+#define acl(buf) ((struct acl_data *)net_buf_user_data(buf))
+
+/* HCI command buffers. Derive the needed size from BT_BUF_RX_SIZE since
+ * the same buffer is also used for the response.
+ */
+#define CMD_BUF_SIZE BT_BUF_RX_SIZE
+NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_HCI_CMD_COUNT,
+			  CMD_BUF_SIZE, NULL);
+
+NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT,
+			  BT_BUF_RX_SIZE, NULL);
+
+#if defined(CONFIG_BT_CONN)
+#define NUM_COMLETE_EVENT_SIZE BT_BUF_SIZE(\
+	sizeof(struct bt_hci_evt_hdr) +                                \
+	sizeof(struct bt_hci_cp_host_num_completed_packets) +          \
+	CONFIG_BT_MAX_CONN * sizeof(struct bt_hci_handle_count))
+/* Dedicated pool for HCI_Number_of_Completed_Packets. This event is always
+ * consumed synchronously by bt_recv_prio() so a single buffer is enough.
+ * Having a dedicated pool for it ensures that exhaustion of the RX pool
+ * cannot block the delivery of this priority event.
+ */
+NET_BUF_POOL_FIXED_DEFINE(num_complete_pool, 1, NUM_COMLETE_EVENT_SIZE, NULL);
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT)
+#define DISCARDABLE_EVENT_SIZE BT_BUF_SIZE(CONFIG_BT_DISCARDABLE_BUF_SIZE)
+NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_DISCARDABLE_BUF_COUNT,
+			  DISCARDABLE_EVENT_SIZE, NULL);
+#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */
+
+struct event_handler {
+	uint8_t event;
+	uint8_t min_len;
+	void (*handler)(struct net_buf *buf);
+};
+
+#define EVENT_HANDLER(_evt, _handler, _min_len) \
+{ \
+	.event = _evt, \
+	.handler = _handler, \
+	.min_len = _min_len, \
+}
+
+int bt_rand(void *buf, size_t len)
+{
+	return 0;
+}
+
+static inline void handle_event(uint8_t event, struct net_buf *buf,
+				const struct event_handler *handlers,
+				size_t num_handlers)
+{
+	size_t i;
+
+	for (i = 0; i < num_handlers; i++) {
+		const struct event_handler *handler = &handlers[i];
+
+		if (handler->event != event) {
+			continue;
+		}
+
+		if (buf->len < handler->min_len) {
+			BT_ERR("Too small (%u bytes) event 0x%02x",
+			       buf->len, event);
+			return;
+		}
+
+		handler->handler(buf);
+		return;
+	}
+
+	BT_WARN("Unhandled event 0x%02x len %u: %s", event,
+		buf->len, bt_hex(buf->data, buf->len));
+}
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+static void report_completed_packet(struct net_buf *buf)
+{
+
+	struct bt_hci_cp_host_num_completed_packets *cp;
+	uint16_t handle = acl(buf)->handle;
+	struct bt_hci_handle_count *hc;
+	struct bt_conn *conn;
+
+	net_buf_destroy(buf);
+
+	/* Do nothing if controller to host flow control is not supported */
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 10, 5)) {
+		return;
+	}
+
+	conn = bt_conn_lookup_index(acl(buf)->index);
+	if (!conn) {
+		BT_WARN("Unable to look up conn with index 0x%02x",
+			acl(buf)->index);
+		return;
+	}
+
+	if (!bt_conn_is_handle_valid(conn)) {
+		BT_WARN("Not reporting packet for non-connected conn");
+		bt_conn_unref(conn);
+		return;
+	}
+
+	bt_conn_unref(conn);
+
+	BT_DBG("Reporting completed packet for handle %u", handle);
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS,
+				sizeof(*cp) + sizeof(*hc));
+	if (!buf) {
+		BT_ERR("Unable to allocate new HCI command");
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->num_handles = sys_cpu_to_le16(1);
+
+	hc = net_buf_add(buf, sizeof(*hc));
+	hc->handle = sys_cpu_to_le16(handle);
+	hc->count  = sys_cpu_to_le16(1);
+
+	bt_hci_cmd_send(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, buf);
+}
+
+#define ACL_IN_SIZE BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_RX_MTU)
+NET_BUF_POOL_DEFINE(acl_in_pool, CONFIG_BT_ACL_RX_COUNT, ACL_IN_SIZE,
+		    sizeof(struct acl_data), report_completed_packet);
+#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
+
+struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len)
+{
+	struct bt_hci_cmd_hdr *hdr;
+	struct net_buf *buf;
+
+	BT_DBG("opcode 0x%04x param_len %u", opcode, param_len);
+
+	buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER);
+	__ASSERT_NO_MSG(buf);
+
+	BT_DBG("buf %p", buf);
+
+	net_buf_reserve(buf, BT_BUF_RESERVE);
+
+	bt_buf_set_type(buf, BT_BUF_CMD);
+
+	//BT_DBG("buf 1 %p", buf);
+	//BT_DBG("buf 2 %d, %p", net_buf_id(buf), cmd(buf));
+
+	cmd(buf)->opcode = opcode;
+	cmd(buf)->sync = NULL;
+	cmd(buf)->state = NULL;
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	//BT_DBG("buf 3 hdr: %p", hdr);
+	hdr->opcode = sys_cpu_to_le16(opcode);
+	hdr->param_len = param_len;
+
+	return buf;
+}
+
+int bt_hci_cmd_send(uint16_t opcode, struct net_buf *buf)
+{
+	if (!buf) {
+		buf = bt_hci_cmd_create(opcode, 0);
+		if (!buf) {
+			return -ENOBUFS;
+		}
+	}
+
+	BT_DBG("opcode 0x%04x len %u", opcode, buf->len);
+
+	/* Host Number of Completed Packets can ignore the ncmd value
+	 * and does not generate any cmd complete/status events.
+	 */
+	if (opcode == BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS) {
+		int err;
+
+		err = bt_send(buf);
+		if (err) {
+			BT_ERR("Unable to send to driver (err %d)", err);
+			net_buf_unref(buf);
+		}
+
+		return err;
+	}
+
+	net_buf_put(&bt_dev.cmd_tx_queue, buf);
+
+	return 0;
+}
+
+int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf,
+			 struct net_buf **rsp)
+{
+	BT_ERR("bt_hci_cmd_send_sync, work err. 0x%x",
+	       opcode);
+    while(1);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_OBSERVER) || defined(CONFIG_BT_BROADCASTER)
+const bt_addr_le_t *bt_lookup_id_addr(uint8_t id, const bt_addr_le_t *addr)
+{
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		struct bt_keys *keys;
+
+		keys = bt_keys_find_irk(id, addr);
+		if (keys) {
+			BT_DBG("Identity %s matched RPA %s",
+			       bt_addr_le_str(&keys->addr),
+			       bt_addr_le_str(addr));
+			return &keys->addr;
+		}
+	}
+
+	return addr;
+}
+#endif /* CONFIG_BT_OBSERVER || CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_EXT_ADV)
+uint8_t bt_le_ext_adv_get_index(struct bt_le_ext_adv *adv)
+{
+	uint8_t index = adv - adv_pool;
+
+	__ASSERT(index < ARRAY_SIZE(adv_pool), "Invalid bt_adv pointer");
+	return index;
+}
+
+static struct bt_le_ext_adv *adv_new(void)
+{
+	struct bt_le_ext_adv *adv = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adv_pool); i++) {
+		if (!atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED)) {
+			adv = &adv_pool[i];
+			break;
+		}
+	}
+
+	if (!adv) {
+		return NULL;
+	}
+
+	(void)memset(adv, 0, sizeof(*adv));
+	atomic_set_bit(adv_pool[i].flags, BT_ADV_CREATED);
+	adv->handle = i;
+
+	return adv;
+}
+
+static void adv_delete(struct bt_le_ext_adv *adv)
+{
+	atomic_clear_bit(adv->flags, BT_ADV_CREATED);
+}
+
+#if defined(CONFIG_BT_BROADCASTER)
+static struct bt_le_ext_adv *bt_adv_lookup_handle(uint8_t handle)
+{
+	if (handle < ARRAY_SIZE(adv_pool) &&
+	    atomic_test_bit(adv_pool[handle].flags, BT_ADV_CREATED)) {
+		return &adv_pool[handle];
+	}
+
+	return NULL;
+}
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+static void bt_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data),
+			   void *data)
+{
+#if defined(CONFIG_BT_EXT_ADV)
+	for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) {
+		if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED)) {
+			func(&adv_pool[i], data);
+		}
+	}
+#else
+	func(&bt_dev.adv, data);
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+}
+
+static struct bt_le_ext_adv *adv_new_legacy(void)
+{
+#if defined(CONFIG_BT_EXT_ADV)
+	if (bt_dev.adv) {
+		return NULL;
+	}
+
+	bt_dev.adv = adv_new();
+	return bt_dev.adv;
+#else
+	return &bt_dev.adv;
+#endif
+}
+
+static void adv_delete_legacy(void)
+{
+#if defined(CONFIG_BT_EXT_ADV)
+	if (bt_dev.adv) {
+		atomic_clear_bit(bt_dev.adv->flags, BT_ADV_CREATED);
+		bt_dev.adv = NULL;
+	}
+#endif
+}
+
+struct bt_le_ext_adv *bt_adv_lookup_legacy(void)
+{
+#if defined(CONFIG_BT_EXT_ADV)
+	return bt_dev.adv;
+#else
+	return &bt_dev.adv;
+#endif
+}
+
+static int set_le_adv_enable_legacy(struct bt_le_ext_adv *adv, bool enable)
+{
+	struct net_buf *buf;
+	struct cmd_state_set state;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	if (enable) {
+		net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE);
+	} else {
+		net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE);
+	}
+
+	cmd_state_set_init(&state, adv->flags, BT_ADV_ENABLED, enable);
+	cmd(buf)->state = &state;
+
+	err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_ENABLE, buf);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int set_random_address(const bt_addr_t *addr)
+{
+	struct net_buf *buf;
+	int err;
+
+	BT_DBG("%s", bt_addr_str(addr));
+
+	/* Do nothing if we already have the right address */
+	if (!bt_addr_cmp(addr, &bt_dev.random_addr.a)) {
+		return 0;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_mem(buf, addr, sizeof(*addr));
+
+	err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, buf);
+	if (err) {
+		return err;
+	}
+
+	bt_addr_copy(&bt_dev.random_addr.a, addr);
+	bt_dev.random_addr.type = BT_ADDR_LE_RANDOM;
+	return 0;
+}
+
+static int set_le_adv_enable_ext(struct bt_le_ext_adv *adv,
+				 bool enable,
+				 const struct bt_le_ext_adv_start_param *param)
+{
+	struct net_buf *buf;
+	struct cmd_state_set state;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, 6);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	if (enable) {
+		net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE);
+	} else {
+		net_buf_add_u8(buf, BT_HCI_LE_ADV_DISABLE);
+	}
+
+	net_buf_add_u8(buf, 1);
+
+	net_buf_add_u8(buf, adv->handle);
+	net_buf_add_le16(buf, param ? sys_cpu_to_le16(param->timeout) : 0);
+	net_buf_add_u8(buf, param ? param->num_events : 0);
+
+	cmd_state_set_init(&state, adv->flags, BT_ADV_ENABLED, enable);
+	cmd(buf)->state = &state;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int set_le_adv_enable(struct bt_le_ext_adv *adv, bool enable)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return set_le_adv_enable_ext(adv, enable, NULL);
+	}
+
+	return set_le_adv_enable_legacy(adv, enable);
+}
+
+static int set_adv_random_address(struct bt_le_ext_adv *adv,
+				  const bt_addr_t *addr)
+{
+	struct bt_hci_cp_le_set_adv_set_random_addr *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+		return set_random_address(addr);
+	}
+
+	BT_DBG("%s", bt_addr_str(addr));
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_PARAMS_SET)) {
+		bt_addr_copy(&adv->random_addr.a, addr);
+		adv->random_addr.type = BT_ADDR_LE_RANDOM;
+		atomic_set_bit(adv->flags, BT_ADV_RANDOM_ADDR_PENDING);
+		return 0;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR,
+				sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	cp->handle = adv->handle;
+	bt_addr_copy(&cp->bdaddr, addr);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, buf,
+				   NULL);
+	if (err) {
+		return err;
+	}
+
+	bt_addr_copy(&adv->random_addr.a, addr);
+	adv->random_addr.type = BT_ADDR_LE_RANDOM;
+	return 0;
+}
+
+int bt_addr_from_str(const char *str, bt_addr_t *addr)
+{
+	int i, j;
+	uint8_t tmp;
+
+	if (strlen(str) != 17U) {
+		return -EINVAL;
+	}
+
+	for (i = 5, j = 1; *str != '\0'; str++, j++) {
+		if (!(j % 3) && (*str != ':')) {
+			return -EINVAL;
+		} else if (*str == ':') {
+			i--;
+			continue;
+		}
+
+		addr->val[i] = addr->val[i] << 4;
+
+		if (char2hex(*str, &tmp) < 0) {
+			return -EINVAL;
+		}
+
+		addr->val[i] |= tmp;
+	}
+
+	return 0;
+}
+
+int bt_addr_le_from_str(const char *str, const char *type, bt_addr_le_t *addr)
+{
+	int err;
+
+	err = bt_addr_from_str(str, &addr->a);
+	if (err < 0) {
+		return err;
+	}
+
+	if (!strcmp(type, "public") || !strcmp(type, "(public)")) {
+		addr->type = BT_ADDR_LE_PUBLIC;
+	} else if (!strcmp(type, "random") || !strcmp(type, "(random)")) {
+		addr->type = BT_ADDR_LE_RANDOM;
+	} else if (!strcmp(type, "public-id") || !strcmp(type, "(public-id)")) {
+		addr->type = BT_ADDR_LE_PUBLIC_ID;
+	} else if (!strcmp(type, "random-id") || !strcmp(type, "(random-id)")) {
+		addr->type = BT_ADDR_LE_RANDOM_ID;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void adv_rpa_invalidate(struct bt_le_ext_adv *adv, void *data)
+{
+	if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
+		atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
+	}
+}
+
+static void le_rpa_invalidate(void)
+{
+	/* RPA must be submitted */
+	atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET);
+
+	/* Invalidate RPA */
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) {
+		atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+	}
+
+	bt_adv_foreach(adv_rpa_invalidate, NULL);
+}
+
+#if defined(CONFIG_BT_PRIVACY)
+static void le_rpa_timeout_submit(void)
+{
+	/* Check if RPA timer is running. */
+	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_RPA_TIMEOUT_SET)) {
+		return;
+	}
+
+	k_delayed_work_submit(&bt_dev.rpa_update, RPA_TIMEOUT);
+}
+
+/* this function sets new RPA only if current one is no longer valid */
+static int le_set_private_addr(uint8_t id)
+{
+	bt_addr_t rpa;
+	int err;
+
+	/* check if RPA is valid */
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_RPA_VALID)) {
+		return 0;
+	}
+
+	err = bt_rpa_create(bt_dev.irk[id], &rpa);
+	if (!err) {
+		err = set_random_address(&rpa);
+		if (!err) {
+			atomic_set_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+		}
+	}
+
+	le_rpa_timeout_submit();
+	return err;
+}
+
+static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
+{
+	bt_addr_t rpa;
+	int err;
+
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+		return le_set_private_addr(adv->id);
+	}
+
+	/* check if RPA is valid */
+	if (atomic_test_bit(adv->flags, BT_ADV_RPA_VALID)) {
+		return 0;
+	}
+
+	if (adv == bt_adv_lookup_legacy() && adv->id == BT_ID_DEFAULT) {
+		/* Make sure that a Legacy advertiser using default ID has same
+		 * RPA address as scanner roles.
+		 */
+		err = le_set_private_addr(BT_ID_DEFAULT);
+		if (err) {
+			return err;
+		}
+
+		err = set_adv_random_address(adv, &bt_dev.random_addr.a);
+		if (!err) {
+			atomic_set_bit(adv->flags, BT_ADV_RPA_VALID);
+		}
+
+		return 0;
+	}
+
+	err = bt_rpa_create(bt_dev.irk[adv->id], &rpa);
+	if (!err) {
+		err = set_adv_random_address(adv, &rpa);
+		if (!err) {
+			atomic_set_bit(adv->flags, BT_ADV_RPA_VALID);
+		}
+	}
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
+		le_rpa_timeout_submit();
+	}
+
+	return err;
+}
+#else
+static int le_set_private_addr(uint8_t id)
+{
+	bt_addr_t nrpa;
+	int err;
+
+	err = bt_rand(nrpa.val, sizeof(nrpa.val));
+	if (err) {
+		return err;
+	}
+
+	nrpa.val[5] &= 0x3f;
+
+	return set_random_address(&nrpa);
+}
+
+static int le_adv_set_private_addr(struct bt_le_ext_adv *adv)
+{
+	bt_addr_t nrpa;
+	int err;
+
+	err = bt_rand(nrpa.val, sizeof(nrpa.val));
+	if (err) {
+		return err;
+	}
+
+	nrpa.val[5] &= 0x3f;
+
+	return set_adv_random_address(adv, &nrpa);
+}
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+static void adv_update_rpa(struct bt_le_ext_adv *adv, void *data)
+{
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_LIMITED) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+		int err;
+
+		set_le_adv_enable_ext(adv, false, NULL);
+
+		err = le_adv_set_private_addr(adv);
+		if (err) {
+			BT_WARN("Failed to update advertiser RPA address (%d)",
+				err);
+		}
+
+		set_le_adv_enable_ext(adv, true, NULL);
+	}
+}
+
+static void le_update_private_addr(void)
+{
+	struct bt_le_ext_adv *adv = NULL;
+	bool adv_enabled = false;
+	uint8_t id = BT_ID_DEFAULT;
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		bt_adv_foreach(adv_update_rpa, NULL);
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	bool scan_enabled = false;
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN) &&
+	    !(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED))) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+		scan_enabled = true;
+	}
+#endif
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    IS_ENABLED(CONFIG_BT_WHITELIST) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+		/* Canceled initiating procedure will be restarted by
+		 * connection complete event.
+		 */
+		bt_le_create_conn_cancel();
+	}
+
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+		adv = bt_adv_lookup_legacy();
+
+		if (adv &&
+		    atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+		    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+			adv_enabled = true;
+			id = adv->id;
+			set_le_adv_enable_legacy(adv, false);
+		}
+	}
+
+	/* If both advertiser and scanner is running then the advertiser
+	 * ID must be BT_ID_DEFAULT, this will update the RPA address
+	 * for both roles.
+	 */
+	err = le_set_private_addr(id);
+	if (err) {
+		BT_WARN("Failed to update RPA address (%d)", err);
+		return;
+	}
+
+	if (adv && adv_enabled) {
+		set_le_adv_enable_legacy(adv, true);
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (scan_enabled) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
+	}
+#endif
+}
+
+struct adv_id_check_data {
+	uint8_t id;
+	bool adv_enabled;
+};
+
+static void adv_id_check_func(struct bt_le_ext_adv *adv, void *data)
+{
+	struct adv_id_check_data *check_data = data;
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV)) {
+		/* Only check if the ID is in use, as the advertiser can be
+		 * started and stopped without reconfiguring parameters.
+		 */
+		if (check_data->id == adv->id) {
+			check_data->adv_enabled = true;
+		}
+	} else {
+		if (check_data->id == adv->id &&
+		    atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+			check_data->adv_enabled = true;
+		}
+	}
+}
+
+static void adv_id_check_connectable_func(struct bt_le_ext_adv *adv, void *data)
+{
+	struct adv_id_check_data *check_data = data;
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+	    atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE) &&
+	    check_data->id != adv->id) {
+		check_data->adv_enabled = true;
+	}
+}
+
+#if defined(CONFIG_BT_SMP)
+static void adv_is_limited_enabled(struct bt_le_ext_adv *adv, void *data)
+{
+	bool *adv_enabled = data;
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+	    atomic_test_bit(adv->flags, BT_ADV_LIMITED)) {
+		*adv_enabled = true;
+	}
+}
+
+static void adv_pause_enabled(struct bt_le_ext_adv *adv, void *data)
+{
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		atomic_set_bit(adv->flags, BT_ADV_PAUSED);
+		set_le_adv_enable(adv, false);
+	}
+}
+
+static void adv_unpause_enabled(struct bt_le_ext_adv *adv, void *data)
+{
+	if (atomic_test_and_clear_bit(adv->flags, BT_ADV_PAUSED)) {
+		set_le_adv_enable(adv, true);
+	}
+}
+#endif /* defined(CONFIG_BT_SMP) */
+
+#if defined(CONFIG_BT_PRIVACY)
+static void adv_is_private_enabled(struct bt_le_ext_adv *adv, void *data)
+{
+	bool *adv_enabled = data;
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+		*adv_enabled = true;
+	}
+}
+
+static void rpa_timeout(struct k_work *work)
+{
+	bool adv_enabled = false;
+
+	BT_DBG("");
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+		struct bt_conn *conn =
+			bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL,
+						BT_CONN_CONNECT_SCAN);
+
+		if (conn) {
+			bt_conn_unref(conn);
+			bt_le_create_conn_cancel();
+		}
+	}
+
+	le_rpa_invalidate();
+
+	bt_adv_foreach(adv_is_private_enabled, &adv_enabled);
+
+	/* IF no roles using the RPA is running we can stop the RPA timer */
+	if (!(adv_enabled ||
+	      atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) ||
+	      (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
+	       atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)))) {
+		return;
+	}
+
+	le_update_private_addr();
+}
+#endif /* CONFIG_BT_PRIVACY */
+
+bool bt_le_scan_random_addr_check(void)
+{
+	struct bt_le_ext_adv *adv;
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		/* Advertiser and scanner using different random address */
+		return true;
+	}
+
+	adv = bt_adv_lookup_legacy();
+	if (!adv) {
+		return true;
+	}
+
+	/* If the advertiser is not enabled or not active there is no issue */
+	if (!IS_ENABLED(CONFIG_BT_BROADCASTER) ||
+	    !atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return true;
+	}
+
+	/* When privacy is enabled the random address will not be set
+	 * immediately before starting the role, because the RPA might still be
+	 * valid and only updated on RPA timeout.
+	 */
+	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		/* Cannot start scannor or initiator if the random address is
+		 * used by the advertiser for an RPA with a different identity
+		 * or for a random static identity address.
+		 */
+		if ((atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) &&
+		     bt_dev.id_addr[adv->id].type == BT_ADDR_LE_RANDOM) ||
+		    adv->id != BT_ID_DEFAULT) {
+			return false;
+		}
+	}
+
+	/* If privacy is not enabled then the random address will be attempted
+	 * to be set before enabling the role. If another role is already using
+	 * the random address then this command will fail, and should return
+	 * the error code to the application.
+	 */
+	return true;
+}
+
+static bool bt_le_adv_random_addr_check(const struct bt_le_adv_param *param)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		/* Advertiser and scanner using different random address */
+		return true;
+	}
+
+	/* If scanner roles are not enabled or not active there is no issue. */
+	if (!IS_ENABLED(CONFIG_BT_OBSERVER) ||
+	    !(atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING) ||
+	      atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING))) {
+		return true;
+	}
+
+	/* When privacy is enabled the random address will not be set
+	 * immediately before starting the role, because the RPA might still be
+	 * valid and only updated on RPA timeout.
+	 */
+	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		/* Cannot start an advertiser with random static identity or
+		 * using an RPA generated for a different identity than scanner
+		 * roles.
+		 */
+		if (((param->options & BT_LE_ADV_OPT_USE_IDENTITY) &&
+		     bt_dev.id_addr[param->id].type == BT_ADDR_LE_RANDOM) ||
+		    param->id != BT_ID_DEFAULT) {
+			return false;
+		}
+	} else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) &&
+		   atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
+		   bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) {
+		/* Scanning with random static identity. Stop the advertiser
+		 * from overwriting the passive scanner identity address.
+		 * In this case the LE Set Random Address command does not
+		 * protect us in the case of a passive scanner.
+		 * Explicitly stop it here.
+		 */
+
+		if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE) &&
+		     (param->options & BT_LE_ADV_OPT_USE_IDENTITY)) {
+			/* Attempt to set non-connectable NRPA */
+			return false;
+		} else if (bt_dev.id_addr[param->id].type ==
+			   BT_ADDR_LE_RANDOM &&
+			   param->id != BT_ID_DEFAULT) {
+			/* Attempt to set connectable, or non-connectable with
+			 * identity different than scanner.
+			 */
+			return false;
+		}
+	}
+
+	/* If privacy is not enabled then the random address will be attempted
+	 * to be set before enabling the role. If another role is already using
+	 * the random address then this command will fail, and should return
+	 * the error code to the application.
+	 */
+	return true;
+}
+
+
+#if defined(CONFIG_BT_OBSERVER)
+static int set_le_ext_scan_enable(uint8_t enable, uint16_t duration)
+{
+	struct bt_hci_cp_le_set_ext_scan_enable *cp;
+	struct cmd_state_set state;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	if (enable == BT_HCI_LE_SCAN_ENABLE) {
+		cp->filter_dup = atomic_test_bit(bt_dev.flags,
+						 BT_DEV_SCAN_FILTER_DUP);
+	} else {
+		cp->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
+	}
+
+	cp->enable = enable;
+	cp->duration = sys_cpu_to_le16(duration);
+	cp->period = 0;
+
+	cmd_state_set_init(&state, bt_dev.flags, BT_DEV_SCANNING,
+				   enable == BT_HCI_LE_SCAN_ENABLE);
+	cmd(buf)->state = &state;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int set_le_scan_enable_legacy(uint8_t enable)
+{
+	struct bt_hci_cp_le_set_scan_enable *cp;
+	struct cmd_state_set state;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	if (enable == BT_HCI_LE_SCAN_ENABLE) {
+		cp->filter_dup = atomic_test_bit(bt_dev.flags,
+						 BT_DEV_SCAN_FILTER_DUP);
+	} else {
+		cp->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
+	}
+
+	cp->enable = enable;
+
+	cmd_state_set_init(&state, bt_dev.flags, BT_DEV_SCANNING,
+				   enable == BT_HCI_LE_SCAN_ENABLE);
+	cmd(buf)->state = &state;
+
+	err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int set_le_scan_enable(uint8_t enable)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return set_le_ext_scan_enable(enable, 0);
+	}
+
+	return set_le_scan_enable_legacy(enable);
+}
+#endif /* CONFIG_BT_OBSERVER */
+
+static inline bool rpa_is_new(void)
+{
+#if defined(CONFIG_BT_PRIVACY)
+	/* RPA is considered new if there is less than half a second since the
+	 * timeout was started.
+	 */
+	return k_delayed_work_remaining_get(&bt_dev.rpa_update) >
+	       (RPA_TIMEOUT_MS - 500);
+#else
+	return false;
+#endif
+}
+
+static int hci_le_read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time)
+{
+	struct bt_hci_rp_le_read_max_data_len *rp;
+	struct net_buf *rsp;
+	int err;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_MAX_DATA_LEN, NULL, &rsp);
+	if (err) {
+		BT_ERR("Failed to read DLE max data len");
+		return err;
+	}
+
+	rp = (void *)rsp->data;
+	*tx_octets = sys_le16_to_cpu(rp->max_tx_octets);
+	*tx_time = sys_le16_to_cpu(rp->max_tx_time);
+	net_buf_unref(rsp);
+
+	return 0;
+}
+
+#if (defined(CONFIG_BT_OBSERVER) && defined(CONFIG_BT_EXT_ADV)) \
+	|| defined(CONFIG_BT_USER_PHY_UPDATE)
+static uint8_t get_phy(uint8_t hci_phy)
+{
+	switch (hci_phy) {
+	case BT_HCI_LE_PHY_1M:
+		return BT_GAP_LE_PHY_1M;
+	case BT_HCI_LE_PHY_2M:
+		return BT_GAP_LE_PHY_2M;
+	case BT_HCI_LE_PHY_CODED:
+		return BT_GAP_LE_PHY_CODED;
+	default:
+		return 0;
+	}
+}
+#endif /* (BT_OBSERVER && BT_EXT_ADV) || USER_PHY_UPDATE */
+
+#if defined(CONFIG_BT_CONN)
+static void hci_acl(struct net_buf *buf)
+{
+	struct bt_hci_acl_hdr *hdr;
+	uint16_t handle, len;
+	struct bt_conn *conn;
+	uint8_t flags;
+
+	BT_DBG("buf %p", buf);
+
+	BT_ASSERT(buf->len >= sizeof(*hdr));
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	len = sys_le16_to_cpu(hdr->len);
+	handle = sys_le16_to_cpu(hdr->handle);
+	flags = bt_acl_flags(handle);
+
+	acl(buf)->handle = bt_acl_handle(handle);
+	acl(buf)->index = BT_CONN_INDEX_INVALID;
+
+	BT_DBG("handle %u len %u flags %u", acl(buf)->handle, len, flags);
+
+	if (buf->len != len) {
+		BT_ERR("ACL data length mismatch (%u != %u)", buf->len, len);
+		net_buf_unref(buf);
+		return;
+	}
+
+	conn = bt_conn_lookup_handle(acl(buf)->handle);
+	if (!conn) {
+		BT_ERR("Unable to find conn for handle %u", acl(buf)->handle);
+		net_buf_unref(buf);
+		return;
+	}
+
+	acl(buf)->index = bt_conn_index(conn);
+
+	bt_conn_recv(conn, buf, flags);
+	bt_conn_unref(conn);
+}
+
+static void hci_data_buf_overflow(struct net_buf *buf)
+{
+	struct bt_hci_evt_data_buf_overflow *evt = (void *)buf->data;
+
+	BT_WARN("Data buffer overflow (link type 0x%02x)", evt->link_type);
+}
+
+static void hci_num_completed_packets(struct net_buf *buf)
+{
+	struct bt_hci_evt_num_completed_packets *evt = (void *)buf->data;
+	int i;
+
+	BT_DBG("num_handles %u", evt->num_handles);
+
+	for (i = 0; i < evt->num_handles; i++) {
+		uint16_t handle, count;
+		struct bt_conn *conn;
+		unsigned int key;
+
+		handle = sys_le16_to_cpu(evt->h[i].handle);
+		count = sys_le16_to_cpu(evt->h[i].count);
+
+		BT_DBG("handle %u count %u", handle, count);
+
+		key = irq_lock();
+
+		conn = bt_conn_lookup_handle(handle);
+		if (!conn) {
+			irq_unlock(key);
+			BT_ERR("No connection for handle %u", handle);
+			continue;
+		}
+
+		irq_unlock(key);
+
+		while (count--) {
+			struct bt_conn_tx *tx;
+			sys_snode_t *node;
+
+			key = irq_lock();
+
+			if (conn->pending_no_cb) {
+				conn->pending_no_cb--;
+				irq_unlock(key);
+				//k_sem_give(bt_conn_get_pkts(conn));
+				continue;
+			}
+
+			node = sys_slist_get(&conn->tx_pending);
+			irq_unlock(key);
+
+			if (!node) {
+				BT_ERR("packets count mismatch");
+				break;
+			}
+
+			tx = CONTAINER_OF(node, struct bt_conn_tx, node);
+
+			key = irq_lock();
+			conn->pending_no_cb = tx->pending_no_cb;
+			tx->pending_no_cb = 0U;
+			sys_slist_append(&conn->tx_complete, &tx->node);
+			irq_unlock(key);
+
+			//k_work_submit(&conn->tx_complete_work);
+			//k_sem_give(bt_conn_get_pkts(conn));
+		}
+
+		bt_conn_unref(conn);
+	}
+}
+
+static inline bool rpa_timeout_valid_check(void)
+{
+#if defined(CONFIG_BT_PRIVACY)
+	/* Check if create conn timeout will happen before RPA timeout. */
+	return k_delayed_work_remaining_get(&bt_dev.rpa_update) >
+	       (10 * bt_dev.create_param.timeout);
+#else
+	return true;
+#endif
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static int le_create_conn_set_random_addr(bool use_filter, uint8_t *own_addr_type)
+{
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		if (use_filter || rpa_timeout_valid_check()) {
+			err = le_set_private_addr(BT_ID_DEFAULT);
+			if (err) {
+				return err;
+			}
+		} else {
+			/* Force new RPA timeout so that RPA timeout is not
+			 * triggered while direct initiator is active.
+			 */
+			le_rpa_invalidate();
+			le_update_private_addr();
+		}
+
+		if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
+			*own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
+		} else {
+			*own_addr_type = BT_ADDR_LE_RANDOM;
+		}
+	} else {
+		const bt_addr_le_t *addr = &bt_dev.id_addr[BT_ID_DEFAULT];
+
+		/* If Static Random address is used as Identity address we
+		 * need to restore it before creating connection. Otherwise
+		 * NRPA used for active scan could be used for connection.
+		 */
+		if (addr->type == BT_ADDR_LE_RANDOM) {
+			err = set_random_address(&addr->a);
+			if (err) {
+				return err;
+			}
+		}
+
+		*own_addr_type = addr->type;
+	}
+
+	return 0;
+}
+
+static void set_phy_conn_param(const struct bt_conn *conn,
+			       struct bt_hci_ext_conn_phy *phy)
+{
+	phy->conn_interval_min = sys_cpu_to_le16(conn->le.interval_min);
+	phy->conn_interval_max = sys_cpu_to_le16(conn->le.interval_max);
+	phy->conn_latency = sys_cpu_to_le16(conn->le.latency);
+	phy->supervision_timeout = sys_cpu_to_le16(conn->le.timeout);
+
+	phy->min_ce_len = 0;
+	phy->max_ce_len = 0;
+}
+
+int bt_le_create_conn_ext(const struct bt_conn *conn)
+{
+	struct bt_hci_cp_le_ext_create_conn *cp;
+	struct bt_hci_ext_conn_phy *phy;
+	struct cmd_state_set state;
+	bool use_filter = false;
+	struct net_buf *buf;
+	uint8_t own_addr_type;
+	uint8_t num_phys;
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_WHITELIST)) {
+		use_filter = atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT);
+	}
+
+	err = le_create_conn_set_random_addr(use_filter, &own_addr_type);
+	if (err) {
+		return err;
+	}
+
+	num_phys = (!(bt_dev.create_param.options &
+		      BT_CONN_LE_OPT_NO_1M) ? 1 : 0) +
+		   ((bt_dev.create_param.options &
+		      BT_CONN_LE_OPT_CODED) ? 1 : 0);
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_EXT_CREATE_CONN, sizeof(*cp) +
+				num_phys * sizeof(*phy));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	if (use_filter) {
+		/* User Initiated procedure use fast scan parameters. */
+		bt_addr_le_copy(&cp->peer_addr, BT_ADDR_LE_ANY);
+		cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_WHITELIST;
+	} else {
+		const bt_addr_le_t *peer_addr = &conn->le.dst;
+
+#if defined(CONFIG_BT_SMP)
+		if (!bt_dev.le.rl_size ||
+		    bt_dev.le.rl_entries > bt_dev.le.rl_size) {
+			/* Host resolving is used, use the RPA directly. */
+			peer_addr = &conn->le.resp_addr;
+		}
+#endif
+		bt_addr_le_copy(&cp->peer_addr, peer_addr);
+		cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_DIRECT;
+	}
+
+	cp->own_addr_type = own_addr_type;
+	cp->phys = 0;
+
+	if (!(bt_dev.create_param.options & BT_CONN_LE_OPT_NO_1M)) {
+		cp->phys |= BT_HCI_LE_EXT_SCAN_PHY_1M;
+		phy = net_buf_add(buf, sizeof(*phy));
+		phy->scan_interval = sys_cpu_to_le16(
+			bt_dev.create_param.interval);
+		phy->scan_window = sys_cpu_to_le16(
+			bt_dev.create_param.window);
+		set_phy_conn_param(conn, phy);
+	}
+
+	if (bt_dev.create_param.options & BT_CONN_LE_OPT_CODED) {
+		cp->phys |= BT_HCI_LE_EXT_SCAN_PHY_CODED;
+		phy = net_buf_add(buf, sizeof(*phy));
+		phy->scan_interval = sys_cpu_to_le16(
+			bt_dev.create_param.interval_coded);
+		phy->scan_window = sys_cpu_to_le16(
+			bt_dev.create_param.window_coded);
+		set_phy_conn_param(conn, phy);
+	}
+
+	cmd_state_set_init(&state, bt_dev.flags, BT_DEV_INITIATING, true);
+	cmd(buf)->state = &state;
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_EXT_CREATE_CONN, buf, NULL);
+}
+
+int bt_le_create_conn_legacy(const struct bt_conn *conn)
+{
+	struct bt_hci_cp_le_create_conn *cp;
+	struct cmd_state_set state;
+	bool use_filter = false;
+	struct net_buf *buf;
+	uint8_t own_addr_type;
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_WHITELIST)) {
+		use_filter = atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT);
+	}
+
+	err = le_create_conn_set_random_addr(use_filter, &own_addr_type);
+	if (err) {
+		return err;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	memset(cp, 0, sizeof(*cp));
+	cp->own_addr_type = own_addr_type;
+
+	if (use_filter) {
+		/* User Initiated procedure use fast scan parameters. */
+		bt_addr_le_copy(&cp->peer_addr, BT_ADDR_LE_ANY);
+		cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_WHITELIST;
+	} else {
+		const bt_addr_le_t *peer_addr = &conn->le.dst;
+
+#if defined(CONFIG_BT_SMP)
+		if (!bt_dev.le.rl_size ||
+		    bt_dev.le.rl_entries > bt_dev.le.rl_size) {
+			/* Host resolving is used, use the RPA directly. */
+			peer_addr = &conn->le.resp_addr;
+		}
+#endif
+		bt_addr_le_copy(&cp->peer_addr, peer_addr);
+		cp->filter_policy = BT_HCI_LE_CREATE_CONN_FP_DIRECT;
+	}
+
+	cp->scan_interval = sys_cpu_to_le16(bt_dev.create_param.interval);
+	cp->scan_window = sys_cpu_to_le16(bt_dev.create_param.window);
+
+	cp->conn_interval_min = sys_cpu_to_le16(conn->le.interval_min);
+	cp->conn_interval_max = sys_cpu_to_le16(conn->le.interval_max);
+	cp->conn_latency = sys_cpu_to_le16(conn->le.latency);
+	cp->supervision_timeout = sys_cpu_to_le16(conn->le.timeout);
+
+	cmd_state_set_init(&state, bt_dev.flags, BT_DEV_INITIATING, true);
+	cmd(buf)->state = &state;
+
+	return bt_hci_cmd_send(BT_HCI_OP_LE_CREATE_CONN, buf);
+}
+
+int bt_le_create_conn(const struct bt_conn *conn)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return bt_le_create_conn_ext(conn);
+	}
+
+	return bt_le_create_conn_legacy(conn);
+}
+
+int bt_le_create_conn_cancel(void)
+{
+	struct net_buf *buf;
+	struct cmd_state_set state;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN_CANCEL, 0);
+
+	cmd_state_set_init(&state, bt_dev.flags, BT_DEV_INITIATING, false);
+	cmd(buf)->state = &state;
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CREATE_CONN_CANCEL, buf, NULL);
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+int bt_hci_disconnect(uint16_t handle, uint8_t reason)
+{
+	struct net_buf *buf;
+	struct bt_hci_cp_disconnect *disconn;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_DISCONNECT, sizeof(*disconn));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	disconn = net_buf_add(buf, sizeof(*disconn));
+	disconn->handle = sys_cpu_to_le16(handle);
+	disconn->reason = reason;
+
+	return bt_hci_cmd_send(BT_HCI_OP_DISCONNECT, buf);
+}
+
+static void hci_disconn_complete_prio(struct net_buf *buf)
+{
+	struct bt_hci_evt_disconn_complete *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x handle %u reason 0x%02x", evt->status, handle,
+	       evt->reason);
+
+	if (evt->status) {
+		return;
+	}
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to look up conn with handle %u", handle);
+		return;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_DISCONNECT_COMPLETE);
+	bt_conn_unref(conn);
+}
+
+static void hci_disconn_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_disconn_complete *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x handle %u reason 0x%02x", evt->status, handle,
+	       evt->reason);
+
+	if (evt->status) {
+		return;
+	}
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to look up conn with handle %u", handle);
+		return;
+	}
+
+	conn->err = evt->reason;
+
+	bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+	conn->handle = 0U;
+
+	if (conn->type != BT_CONN_TYPE_LE) {
+#if defined(CONFIG_BT_BREDR)
+		if (conn->type == BT_CONN_TYPE_SCO) {
+			bt_sco_cleanup(conn);
+			return;
+		}
+		/*
+		 * If only for one connection session bond was set, clear keys
+		 * database row for this connection.
+		 */
+		if (conn->type == BT_CONN_TYPE_BR &&
+		    atomic_test_and_clear_bit(conn->flags, BT_CONN_BR_NOBOND)) {
+			bt_keys_link_key_clear(conn->br.link_key);
+		}
+#endif
+		bt_conn_unref(conn);
+		return;
+	}
+
+#if defined(CONFIG_BT_CENTRAL) && !defined(CONFIG_BT_WHITELIST)
+	if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
+		bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
+		bt_le_scan_update(false);
+	}
+#endif /* defined(CONFIG_BT_CENTRAL) && !defined(CONFIG_BT_WHITELIST) */
+
+	bt_conn_unref(conn);
+}
+
+static int hci_le_read_remote_features(struct bt_conn *conn)
+{
+	struct bt_hci_cp_le_read_remote_features *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_REMOTE_FEATURES,
+				sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+	bt_hci_cmd_send(BT_HCI_OP_LE_READ_REMOTE_FEATURES, buf);
+
+	return 0;
+}
+
+static int hci_read_remote_version(struct bt_conn *conn)
+{
+	struct bt_hci_cp_read_remote_version_info *cp;
+	struct net_buf *buf;
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	/* Remote version cannot change. */
+	if (atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) {
+		return 0;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_VERSION_INFO,
+				sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_VERSION_INFO, buf,
+				    NULL);
+}
+
+/* LE Data Length Change Event is optional so this function just ignore
+ * error and stack will continue to use default values.
+ */
+int bt_le_set_data_len(struct bt_conn *conn, uint16_t tx_octets, uint16_t tx_time)
+{
+	struct bt_hci_cp_le_set_data_len *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DATA_LEN, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+	cp->tx_octets = sys_cpu_to_le16(tx_octets);
+	cp->tx_time = sys_cpu_to_le16(tx_time);
+
+	return bt_hci_cmd_send(BT_HCI_OP_LE_SET_DATA_LEN, buf);
+}
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+static int hci_le_read_phy(struct bt_conn *conn)
+{
+	struct bt_hci_cp_le_read_phy *cp;
+	struct bt_hci_rp_le_read_phy *rp;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_PHY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_PHY, buf, &rsp);
+	if (err) {
+		return err;
+	}
+
+	rp = (void *)rsp->data;
+	conn->le.phy.tx_phy = get_phy(rp->tx_phy);
+	conn->le.phy.rx_phy = get_phy(rp->rx_phy);
+	net_buf_unref(rsp);
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
+
+int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys,
+		  uint8_t pref_tx_phy, uint8_t pref_rx_phy, uint8_t phy_opts)
+{
+	struct bt_hci_cp_le_set_phy *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PHY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+	cp->all_phys = all_phys;
+	cp->tx_phys = pref_tx_phy;
+	cp->rx_phys = pref_rx_phy;
+	cp->phy_opts = phy_opts;
+
+	return bt_hci_cmd_send(BT_HCI_OP_LE_SET_PHY, buf);
+}
+
+static void slave_update_conn_param(struct bt_conn *conn)
+{
+	if (!IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		return;
+	}
+
+	/* don't start timer again on PHY update etc */
+	if (atomic_test_bit(conn->flags, BT_CONN_SLAVE_PARAM_UPDATE)) {
+		return;
+	}
+
+	/*
+	 * Core 4.2 Vol 3, Part C, 9.3.12.2
+	 * The Peripheral device should not perform a Connection Parameter
+	 * Update procedure within 5 s after establishing a connection.
+	 */
+	//k_delayed_work_submit(&conn->update_work, CONN_UPDATE_TIMEOUT);
+}
+
+#if defined(CONFIG_BT_SMP)
+static void pending_id_update(struct bt_keys *keys, void *data)
+{
+	if (keys->state & BT_KEYS_ID_PENDING_ADD) {
+		keys->state &= ~BT_KEYS_ID_PENDING_ADD;
+		bt_id_add(keys);
+		return;
+	}
+
+	if (keys->state & BT_KEYS_ID_PENDING_DEL) {
+		keys->state &= ~BT_KEYS_ID_PENDING_DEL;
+		bt_id_del(keys);
+		return;
+	}
+}
+
+static void pending_id_keys_update_set(struct bt_keys *keys, uint8_t flag)
+{
+	atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING);
+	keys->state |= flag;
+}
+
+static void pending_id_keys_update(void)
+{
+	if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) {
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    IS_ENABLED(CONFIG_BT_PRIVACY)) {
+			bt_keys_foreach(BT_KEYS_ALL, pending_id_update, NULL);
+		} else {
+			bt_keys_foreach(BT_KEYS_IRK, pending_id_update, NULL);
+		}
+	}
+}
+#endif /* defined(CONFIG_BT_SMP) */
+
+static struct bt_conn *find_pending_connect(uint8_t role, bt_addr_le_t *peer_addr)
+{
+	struct bt_conn *conn;
+
+	/*
+	 * Make lookup to check if there's a connection object in
+	 * CONNECT or CONNECT_AUTO state associated with passed peer LE address.
+	 */
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) && role == BT_HCI_ROLE_MASTER) {
+		conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, peer_addr,
+					       BT_CONN_CONNECT);
+		if (IS_ENABLED(CONFIG_BT_WHITELIST) && !conn) {
+			conn = bt_conn_lookup_state_le(BT_ID_DEFAULT,
+						       BT_ADDR_LE_NONE,
+						       BT_CONN_CONNECT_AUTO);
+		}
+
+		return conn;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && role == BT_HCI_ROLE_SLAVE) {
+		conn = bt_conn_lookup_state_le(bt_dev.adv_conn_id, peer_addr,
+					       BT_CONN_CONNECT_DIR_ADV);
+		if (!conn) {
+			conn = bt_conn_lookup_state_le(bt_dev.adv_conn_id,
+						       BT_ADDR_LE_NONE,
+						       BT_CONN_CONNECT_ADV);
+		}
+
+		return conn;
+	}
+
+	return NULL;
+}
+
+static void conn_auto_initiate(struct bt_conn *conn)
+{
+	int err;
+
+	if (conn->state != BT_CONN_CONNECTED) {
+		/* It is possible that connection was disconnected directly from
+		 * connected callback so we must check state before doing
+		 * connection parameters update.
+		 */
+		return;
+	}
+
+	if (!atomic_test_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH) &&
+	    ((conn->role == BT_HCI_ROLE_MASTER) ||
+	     BT_FEAT_LE_SLAVE_FEATURE_XCHG(bt_dev.le.features))) {
+		err = hci_le_read_remote_features(conn);
+		if (!err) {
+			return;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION) &&
+	    !atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) {
+		err = hci_read_remote_version(conn);
+		if (!err) {
+			return;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
+	    !atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE) &&
+	    BT_FEAT_LE_PHY_2M(bt_dev.le.features)) {
+		err = bt_le_set_phy(conn, 0U, BT_HCI_LE_PHY_PREFER_2M,
+				    BT_HCI_LE_PHY_PREFER_2M,
+				    BT_HCI_LE_PHY_CODED_ANY);
+		if (!err) {
+			atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE);
+			return;
+		}
+
+		BT_ERR("Failed to set LE PHY (%d)", err);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE) &&
+	    BT_FEAT_LE_DLE(bt_dev.le.features)) {
+		if (IS_BT_QUIRK_NO_AUTO_DLE(&bt_dev)) {
+			uint16_t tx_octets, tx_time;
+
+			err = hci_le_read_max_data_len(&tx_octets, &tx_time);
+			if (!err) {
+				err = bt_le_set_data_len(conn,
+						tx_octets, tx_time);
+				if (err) {
+					BT_ERR("Failed to set data len (%d)", err);
+				}
+			}
+		} else {
+			/* No need to auto-initiate DLE procedure.
+			 * It is done by the controller.
+			 */
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    conn->role == BT_CONN_ROLE_SLAVE) {
+		slave_update_conn_param(conn);
+	}
+}
+
+static void le_conn_complete_cancel(void)
+{
+	struct bt_conn *conn;
+
+	/* Handle create connection cancel.
+	 *
+	 * There is no need to check ID address as only one
+	 * connection in master role can be in pending state.
+	 */
+	conn = find_pending_connect(BT_HCI_ROLE_MASTER, NULL);
+	if (!conn) {
+		BT_ERR("No pending master connection");
+		return;
+	}
+
+	conn->err = BT_HCI_ERR_UNKNOWN_CONN_ID;
+
+	/* Handle cancellation of outgoing connection attempt. */
+	if (!IS_ENABLED(CONFIG_BT_WHITELIST)) {
+		/* We notify before checking autoconnect flag
+		 * as application may choose to change it from
+		 * callback.
+		 */
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		/* Check if device is marked for autoconnect. */
+		if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
+			/* Restart passive scanner for device */
+			bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);
+		}
+	} else {
+		if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) {
+			/* Restart whitelist initiator after RPA timeout. */
+			bt_le_create_conn(conn);
+		} else {
+			/* Create connection canceled by timeout */
+			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		}
+	}
+
+	bt_conn_unref(conn);
+}
+
+static void le_conn_complete_adv_timeout(void)
+{
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+		struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+		struct bt_conn *conn;
+
+		/* Handle advertising timeout after high duty cycle directed
+		 * advertising.
+		 */
+
+		atomic_clear_bit(adv->flags, BT_ADV_ENABLED);
+
+		if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+		    !BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+			/* No advertising set terminated event, must be a
+			 * legacy advertiser set.
+			 */
+			adv_delete_legacy();
+		}
+
+		/* There is no need to check ID address as only one
+		 * connection in slave role can be in pending state.
+		 */
+		conn = find_pending_connect(BT_HCI_ROLE_SLAVE, NULL);
+		if (!conn) {
+			BT_ERR("No pending slave connection");
+			return;
+		}
+
+		conn->err = BT_HCI_ERR_ADV_TIMEOUT;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+
+		bt_conn_unref(conn);
+	}
+}
+
+static void enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
+{
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	bt_addr_le_t peer_addr, id_addr;
+	struct bt_conn *conn;
+
+	BT_DBG("enh_conn_complete, status 0x%02x handle %u role %u peer %s peer RPA %s",
+	       evt->status, handle, evt->role, bt_addr_le_str(&evt->peer_addr),
+	       bt_addr_str(&evt->peer_rpa));
+	BT_DBG("local RPA %s", bt_addr_str(&evt->local_rpa));
+
+#if defined(CONFIG_BT_SMP)
+	pending_id_keys_update();
+#endif
+
+	if (evt->status) {
+		if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+		    evt->status == BT_HCI_ERR_ADV_TIMEOUT) {
+			le_conn_complete_adv_timeout();
+			return;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    evt->status == BT_HCI_ERR_UNKNOWN_CONN_ID) {
+			le_conn_complete_cancel();
+			bt_le_scan_update(false);
+			return;
+		}
+
+		BT_WARN("Unexpected status 0x%02x", evt->status);
+
+		return;
+	}
+
+	/* Translate "enhanced" identity address type to normal one */
+	if (evt->peer_addr.type == BT_ADDR_LE_PUBLIC_ID ||
+	    evt->peer_addr.type == BT_ADDR_LE_RANDOM_ID) {
+		bt_addr_le_copy(&id_addr, &evt->peer_addr);
+		id_addr.type -= BT_ADDR_LE_PUBLIC_ID;
+
+		bt_addr_copy(&peer_addr.a, &evt->peer_rpa);
+		peer_addr.type = BT_ADDR_LE_RANDOM;
+	} else {
+		uint8_t id = evt->role == BT_HCI_ROLE_SLAVE ? bt_dev.adv_conn_id :
+							   BT_ID_DEFAULT;
+
+		bt_addr_le_copy(&id_addr,
+				bt_lookup_id_addr(id, &evt->peer_addr));
+		bt_addr_le_copy(&peer_addr, &evt->peer_addr);
+	}
+
+	conn = find_pending_connect(evt->role, &id_addr);
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    evt->role == BT_HCI_ROLE_SLAVE &&
+	    !(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+		struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+		/* Clear advertising even if we are not able to add connection
+		 * object to keep host in sync with controller state.
+		 */
+		atomic_clear_bit(adv->flags, BT_ADV_ENABLED);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    evt->role == BT_HCI_ROLE_MASTER) {
+		/* Clear initiating even if we are not able to add connection
+		 * object to keep the host in sync with controller state.
+		 */
+		atomic_clear_bit(bt_dev.flags, BT_DEV_INITIATING);
+	}
+
+	if (!conn) {
+		BT_ERR("No pending conn for peer %s",
+		       bt_addr_le_str(&evt->peer_addr));
+		bt_hci_disconnect(handle, BT_HCI_ERR_UNSPECIFIED);
+		return;
+	}
+
+	conn->handle = handle;
+	bt_addr_le_copy(&conn->le.dst, &id_addr);
+	conn->le.interval = sys_le16_to_cpu(evt->interval);
+	conn->le.latency = sys_le16_to_cpu(evt->latency);
+	conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
+	conn->role = evt->role;
+	conn->err = 0U;
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	conn->le.data_len.tx_max_len = BT_GAP_DATA_LEN_DEFAULT;
+	conn->le.data_len.tx_max_time = BT_GAP_DATA_TIME_DEFAULT;
+	conn->le.data_len.rx_max_len = BT_GAP_DATA_LEN_DEFAULT;
+	conn->le.data_len.rx_max_time = BT_GAP_DATA_TIME_DEFAULT;
+#endif
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	conn->le.phy.tx_phy = BT_GAP_LE_PHY_1M;
+	conn->le.phy.rx_phy = BT_GAP_LE_PHY_1M;
+#endif
+	/*
+	 * Use connection address (instead of identity address) as initiator
+	 * or responder address. Only slave needs to be updated. For master all
+	 * was set during outgoing connection creation.
+	 */
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    conn->role == BT_HCI_ROLE_SLAVE) {
+		bt_addr_le_copy(&conn->le.init_addr, &peer_addr);
+
+		if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+		      BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+			struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+
+			if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+			    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+				conn->le.resp_addr.type = BT_ADDR_LE_RANDOM;
+				if (bt_addr_cmp(&evt->local_rpa,
+						BT_ADDR_ANY) != 0) {
+					bt_addr_copy(&conn->le.resp_addr.a,
+						     &evt->local_rpa);
+				} else {
+					bt_addr_copy(&conn->le.resp_addr.a,
+						     &bt_dev.random_addr.a);
+				}
+			} else {
+				bt_addr_le_copy(&conn->le.resp_addr,
+						&bt_dev.id_addr[conn->id]);
+			}
+		} else {
+			/* Copy the local RPA and handle this in advertising set
+			 * terminated event.
+			 */
+			bt_addr_copy(&conn->le.resp_addr.a, &evt->local_rpa);
+		}
+
+		/* if the controller supports, lets advertise for another
+		 * slave connection.
+		 * check for connectable advertising state is sufficient as
+		 * this is how this le connection complete for slave occurred.
+		 */
+		if (BT_LE_STATES_SLAVE_CONN_ADV(bt_dev.le.states)) {
+			bt_le_adv_resume();
+		}
+
+		if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+		    !BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+			struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+			/* No advertising set terminated event, must be a
+			 * legacy advertiser set.
+			 */
+			if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST)) {
+				adv_delete_legacy();
+			}
+		}
+	}
+
+	BT_ERR("enh_conn_complete role: %d.", conn->role);
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER) {
+		bt_addr_le_copy(&conn->le.resp_addr, &peer_addr);
+
+		if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+			conn->le.init_addr.type = BT_ADDR_LE_RANDOM;
+			if (bt_addr_cmp(&evt->local_rpa, BT_ADDR_ANY) != 0) {
+				bt_addr_copy(&conn->le.init_addr.a,
+					     &evt->local_rpa);
+			} else {
+				bt_addr_copy(&conn->le.init_addr.a,
+					     &bt_dev.random_addr.a);
+			}
+		} else {
+			bt_addr_le_copy(&conn->le.init_addr,
+					&bt_dev.id_addr[conn->id]);
+		}
+	}
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		int err;
+
+		err = hci_le_read_phy(conn);
+		if (err) {
+			BT_WARN("Failed to read PHY (%d)", err);
+		} else {
+			if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
+			    conn->le.phy.tx_phy == BT_HCI_LE_PHY_PREFER_2M &&
+			    conn->le.phy.rx_phy == BT_HCI_LE_PHY_PREFER_2M) {
+				/* Already on 2M, skip auto-phy update. */
+				atomic_set_bit(conn->flags,
+					       BT_CONN_AUTO_PHY_COMPLETE);
+			}
+		}
+	}
+#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */
+
+	bt_conn_set_state(conn, BT_CONN_CONNECTED);
+
+	/* Start auto-initiated procedures */
+	conn_auto_initiate(conn);
+
+	bt_conn_unref(conn);
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER) {
+		bt_le_scan_update(false);
+	}
+}
+
+static void le_enh_conn_complete(struct net_buf *buf)
+{
+	enh_conn_complete((void *)buf->data);
+}
+
+static void le_legacy_conn_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_conn_complete *evt = (void *)buf->data;
+	struct bt_hci_evt_le_enh_conn_complete enh;
+
+	BT_DBG("le_legacy_conn_complete, status 0x%02x role %u %s", evt->status, evt->role,
+	       bt_addr_le_str(&evt->peer_addr));
+
+	enh.status         = evt->status;
+	enh.handle         = evt->handle;
+	enh.role           = evt->role;
+	enh.interval       = evt->interval;
+	enh.latency        = evt->latency;
+	enh.supv_timeout   = evt->supv_timeout;
+	enh.clock_accuracy = evt->clock_accuracy;
+
+	bt_addr_le_copy(&enh.peer_addr, &evt->peer_addr);
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		bt_addr_copy(&enh.local_rpa, &bt_dev.random_addr.a);
+	} else {
+		bt_addr_copy(&enh.local_rpa, BT_ADDR_ANY);
+	}
+
+	bt_addr_copy(&enh.peer_rpa, BT_ADDR_ANY);
+
+	enh_conn_complete(&enh);
+}
+
+static void le_remote_feat_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_remote_feat_complete *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		return;
+	}
+
+	if (!evt->status) {
+		memcpy(conn->le.features, evt->features,
+		       sizeof(conn->le.features));
+	}
+
+	atomic_set_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH);
+
+	if (IS_ENABLED(CONFIG_BT_REMOTE_INFO) &&
+	    !IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) {
+		notify_remote_info(conn);
+	}
+
+	/* Continue with auto-initiated procedures */
+	conn_auto_initiate(conn);
+
+	bt_conn_unref(conn);
+}
+
+#if defined(CONFIG_BT_DATA_LEN_UPDATE)
+static void le_data_len_change(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_data_len_change *evt = (void *)buf->data;
+	uint16_t max_tx_octets = sys_le16_to_cpu(evt->max_tx_octets);
+	uint16_t max_rx_octets = sys_le16_to_cpu(evt->max_rx_octets);
+	uint16_t max_tx_time = sys_le16_to_cpu(evt->max_tx_time);
+	uint16_t max_rx_time = sys_le16_to_cpu(evt->max_rx_time);
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		return;
+	}
+
+	BT_DBG("max. tx: %u (%uus), max. rx: %u (%uus)", max_tx_octets,
+	       max_tx_time, max_rx_octets, max_rx_time);
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	if (IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE)) {
+		atomic_set_bit(conn->flags, BT_CONN_AUTO_DATA_LEN_COMPLETE);
+	}
+
+	conn->le.data_len.tx_max_len = max_tx_octets;
+	conn->le.data_len.tx_max_time = max_tx_time;
+	conn->le.data_len.rx_max_len = max_rx_octets;
+	conn->le.data_len.rx_max_time = max_rx_time;
+	notify_le_data_len_updated(conn);
+#endif
+
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_DATA_LEN_UPDATE */
+
+#if defined(CONFIG_BT_PHY_UPDATE)
+static void le_phy_update_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_phy_update_complete *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		return;
+	}
+
+	BT_DBG("PHY updated: status: 0x%02x, tx: %u, rx: %u",
+	       evt->status, evt->tx_phy, evt->rx_phy);
+
+	if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
+	    atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_PHY_UPDATE)) {
+		atomic_set_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE);
+
+		/* Continue with auto-initiated procedures */
+		conn_auto_initiate(conn);
+	}
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	conn->le.phy.tx_phy = get_phy(evt->tx_phy);
+	conn->le.phy.rx_phy = get_phy(evt->rx_phy);
+	notify_le_phy_updated(conn);
+#endif
+
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_PHY_UPDATE */
+
+bool bt_le_conn_params_valid(const struct bt_le_conn_param *param)
+{
+	/* All limits according to BT Core spec 5.0 [Vol 2, Part E, 7.8.12] */
+
+	if (param->interval_min > param->interval_max ||
+	    param->interval_min < 6 || param->interval_max > 3200) {
+		return false;
+	}
+
+	if (param->latency > 499) {
+		return false;
+	}
+
+	if (param->timeout < 10 || param->timeout > 3200 ||
+	    ((param->timeout * 4U) <=
+	     ((1U + param->latency) * param->interval_max))) {
+		return false;
+	}
+
+	return true;
+}
+
+static void le_conn_param_neg_reply(uint16_t handle, uint8_t reason)
+{
+	struct bt_hci_cp_le_conn_param_req_neg_reply *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY,
+				sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Unable to allocate buffer");
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(handle);
+	cp->reason = sys_cpu_to_le16(reason);
+
+	bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, buf);
+}
+
+static int le_conn_param_req_reply(uint16_t handle,
+				   const struct bt_le_conn_param *param)
+{
+	struct bt_hci_cp_le_conn_param_req_reply *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	cp->handle = sys_cpu_to_le16(handle);
+	cp->interval_min = sys_cpu_to_le16(param->interval_min);
+	cp->interval_max = sys_cpu_to_le16(param->interval_max);
+	cp->latency = sys_cpu_to_le16(param->latency);
+	cp->timeout = sys_cpu_to_le16(param->timeout);
+
+	return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, buf);
+}
+
+static void le_conn_param_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_conn_param_req *evt = (void *)buf->data;
+	struct bt_le_conn_param param;
+	struct bt_conn *conn;
+	uint16_t handle;
+
+	handle = sys_le16_to_cpu(evt->handle);
+	param.interval_min = sys_le16_to_cpu(evt->interval_min);
+	param.interval_max = sys_le16_to_cpu(evt->interval_max);
+	param.latency = sys_le16_to_cpu(evt->latency);
+	param.timeout = sys_le16_to_cpu(evt->timeout);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		le_conn_param_neg_reply(handle, BT_HCI_ERR_UNKNOWN_CONN_ID);
+		return;
+	}
+
+	if (!le_param_req(conn, &param)) {
+		le_conn_param_neg_reply(handle, BT_HCI_ERR_INVALID_LL_PARAM);
+	} else {
+		le_conn_param_req_reply(handle, &param);
+	}
+
+	bt_conn_unref(conn);
+}
+
+static void le_conn_update_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_conn_update_complete *evt = (void *)buf->data;
+	struct bt_conn *conn;
+	uint16_t handle;
+
+	handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("le_conn_update_complete, status 0x%02x, handle %u", evt->status, handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		return;
+	}
+
+	if (!evt->status) {
+		conn->le.interval = sys_le16_to_cpu(evt->interval);
+		conn->le.latency = sys_le16_to_cpu(evt->latency);
+		conn->le.timeout = sys_le16_to_cpu(evt->supv_timeout);
+		notify_le_param_updated(conn);
+	} else if (evt->status == BT_HCI_ERR_UNSUPP_REMOTE_FEATURE &&
+		   conn->role == BT_HCI_ROLE_SLAVE &&
+		   !atomic_test_and_set_bit(conn->flags,
+					    BT_CONN_SLAVE_PARAM_L2CAP)) {
+		/* CPR not supported, let's try L2CAP CPUP instead */
+		struct bt_le_conn_param param;
+
+		param.interval_min = conn->le.interval_min;
+		param.interval_max = conn->le.interval_max;
+		param.latency = conn->le.pending_latency;
+		param.timeout = conn->le.pending_timeout;
+
+		bt_l2cap_update_conn_param(conn, &param);
+	}
+
+	bt_conn_unref(conn);
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static void check_pending_conn(const bt_addr_le_t *id_addr,
+			       const bt_addr_le_t *addr, uint8_t adv_props)
+{
+	struct bt_conn *conn;
+
+	/* No connections are allowed during explicit scanning */
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
+		return;
+	}
+
+	/* Return if event is not connectable */
+	if (!(adv_props & BT_HCI_LE_ADV_EVT_TYPE_CONN)) {
+		return;
+	}
+
+	conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, id_addr,
+				       BT_CONN_CONNECT_SCAN);
+	if (!conn) {
+		return;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
+	    set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE)) {
+		goto failed;
+	}
+
+	bt_addr_le_copy(&conn->le.resp_addr, addr);
+	if (bt_le_create_conn(conn)) {
+		goto failed;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_CONNECT);
+	bt_conn_unref(conn);
+	return;
+
+failed:
+	conn->err = BT_HCI_ERR_UNSPECIFIED;
+	bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+	bt_conn_unref(conn);
+	bt_le_scan_update(false);
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+static int set_flow_control(void)
+{
+	struct bt_hci_cp_host_buffer_size *hbs;
+	struct net_buf *buf;
+	int err;
+
+	/* Check if host flow control is actually supported */
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 10, 5)) {
+		BT_WARN("Controller to host flow control not supported");
+		return 0;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_HOST_BUFFER_SIZE,
+				sizeof(*hbs));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	hbs = net_buf_add(buf, sizeof(*hbs));
+	(void)memset(hbs, 0, sizeof(*hbs));
+	hbs->acl_mtu = sys_cpu_to_le16(CONFIG_BT_L2CAP_RX_MTU +
+				       sizeof(struct bt_l2cap_hdr));
+	hbs->acl_pkts = sys_cpu_to_le16(CONFIG_BT_ACL_RX_COUNT);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_HOST_BUFFER_SIZE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, 1);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_u8(buf, BT_HCI_CTL_TO_HOST_FLOW_ENABLE);
+	return bt_hci_cmd_send_sync(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, buf, NULL);
+}
+#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
+
+static void unpair(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct bt_keys *keys = NULL;
+	struct bt_conn *conn = bt_conn_lookup_addr_le(id, addr);
+
+	if (conn) {
+		/* Clear the conn->le.keys pointer since we'll invalidate it,
+		 * and don't want any subsequent code (like disconnected
+		 * callbacks) accessing it.
+		 */
+		if (conn->type == BT_CONN_TYPE_LE) {
+			keys = conn->le.keys;
+			conn->le.keys = NULL;
+		}
+
+		bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+		bt_conn_unref(conn);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR)) {
+		/* LE Public may indicate BR/EDR as well */
+		if (addr->type == BT_ADDR_LE_PUBLIC) {
+			bt_keys_link_key_clear_addr(&addr->a);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		if (!keys) {
+			keys = bt_keys_find_addr(id, addr);
+		}
+
+		if (keys) {
+			bt_keys_clear(keys);
+		}
+	}
+
+	bt_gatt_clear(id, addr);
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	if (bt_auth && bt_auth->bond_deleted) {
+		bt_auth->bond_deleted(id, addr);
+	}
+#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
+}
+
+static void unpair_remote(const struct bt_bond_info *info, void *data)
+{
+	uint8_t *id = (uint8_t *) data;
+
+	unpair(*id, &info->addr);
+}
+
+int bt_unpair(uint8_t id, const bt_addr_le_t *addr)
+{
+	if (id >= CONFIG_BT_ID_MAX) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) &&
+	    (!addr || !bt_addr_le_cmp(addr, BT_ADDR_LE_ANY))) {
+		bt_foreach_bond(id, unpair_remote, &id);
+		return 0;
+	}
+
+	unpair(id, addr);
+	return 0;
+}
+
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+enum bt_security_err bt_security_err_get(uint8_t hci_err)
+{
+	switch (hci_err) {
+	case BT_HCI_ERR_SUCCESS:
+		return BT_SECURITY_ERR_SUCCESS;
+	case BT_HCI_ERR_AUTH_FAIL:
+		return BT_SECURITY_ERR_AUTH_FAIL;
+	case BT_HCI_ERR_PIN_OR_KEY_MISSING:
+		return BT_SECURITY_ERR_PIN_OR_KEY_MISSING;
+	case BT_HCI_ERR_PAIRING_NOT_SUPPORTED:
+		return BT_SECURITY_ERR_PAIR_NOT_SUPPORTED;
+	case BT_HCI_ERR_PAIRING_NOT_ALLOWED:
+		return BT_SECURITY_ERR_PAIR_NOT_ALLOWED;
+	case BT_HCI_ERR_INVALID_PARAM:
+		return BT_SECURITY_ERR_INVALID_PARAM;
+	default:
+		return BT_SECURITY_ERR_UNSPECIFIED;
+	}
+}
+#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
+
+#if defined(CONFIG_BT_BREDR)
+static int reject_conn(const bt_addr_t *bdaddr, uint8_t reason)
+{
+	struct bt_hci_cp_reject_conn_req *cp;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_REJECT_CONN_REQ, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	cp->reason = reason;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_REJECT_CONN_REQ, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int accept_sco_conn(const bt_addr_t *bdaddr, struct bt_conn *sco_conn)
+{
+	struct bt_hci_cp_accept_sync_conn_req *cp;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	cp->pkt_type = sco_conn->sco.pkt_type;
+	cp->tx_bandwidth = 0x00001f40;
+	cp->rx_bandwidth = 0x00001f40;
+	cp->max_latency = 0x0007;
+	cp->retrans_effort = 0x01;
+	cp->content_format = BT_VOICE_CVSD_16BIT;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int accept_conn(const bt_addr_t *bdaddr)
+{
+	struct bt_hci_cp_accept_conn_req *cp;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_CONN_REQ, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	cp->role = BT_HCI_ROLE_SLAVE;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_CONN_REQ, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static void bt_esco_conn_req(struct bt_hci_evt_conn_request *evt)
+{
+	struct bt_conn *sco_conn;
+
+	sco_conn = bt_conn_add_sco(&evt->bdaddr, evt->link_type);
+	if (!sco_conn) {
+		reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
+		return;
+	}
+
+	if (accept_sco_conn(&evt->bdaddr, sco_conn)) {
+		BT_ERR("Error accepting connection from %s",
+		       bt_addr_str(&evt->bdaddr));
+		reject_conn(&evt->bdaddr, BT_HCI_ERR_UNSPECIFIED);
+		bt_sco_cleanup(sco_conn);
+		return;
+	}
+
+	sco_conn->role = BT_HCI_ROLE_SLAVE;
+	bt_conn_set_state(sco_conn, BT_CONN_CONNECT);
+	bt_conn_unref(sco_conn);
+}
+
+static void conn_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_conn_request *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("conn req from %s, type 0x%02x", bt_addr_str(&evt->bdaddr),
+	       evt->link_type);
+
+	if (evt->link_type != BT_HCI_ACL) {
+		bt_esco_conn_req(evt);
+		return;
+	}
+
+	conn = bt_conn_add_br(&evt->bdaddr);
+	if (!conn) {
+		reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES);
+		return;
+	}
+
+	accept_conn(&evt->bdaddr);
+	conn->role = BT_HCI_ROLE_SLAVE;
+	bt_conn_set_state(conn, BT_CONN_CONNECT);
+	bt_conn_unref(conn);
+}
+
+static bool br_sufficient_key_size(struct bt_conn *conn)
+{
+	struct bt_hci_cp_read_encryption_key_size *cp;
+	struct bt_hci_rp_read_encryption_key_size *rp;
+	struct net_buf *buf, *rsp;
+	uint8_t key_size;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
+				sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Failed to allocate command buffer");
+		return false;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(conn->handle);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE,
+				   buf, &rsp);
+	if (err) {
+		BT_ERR("Failed to read encryption key size (err %d)", err);
+		return false;
+	}
+
+	if (rsp->len < sizeof(*rp)) {
+		BT_ERR("Too small command complete for encryption key size");
+		net_buf_unref(rsp);
+		return false;
+	}
+
+	rp = (void *)rsp->data;
+	key_size = rp->key_size;
+	net_buf_unref(rsp);
+
+	BT_DBG("Encryption key size is %u", key_size);
+
+	if (conn->sec_level == BT_SECURITY_L4) {
+		return key_size == BT_HCI_ENCRYPTION_KEY_SIZE_MAX;
+	}
+
+	return key_size >= BT_HCI_ENCRYPTION_KEY_SIZE_MIN;
+}
+
+static bool update_sec_level_br(struct bt_conn *conn)
+{
+	if (!conn->encrypt) {
+		conn->sec_level = BT_SECURITY_L1;
+		return true;
+	}
+
+	if (conn->br.link_key) {
+		if (conn->br.link_key->flags & BT_LINK_KEY_AUTHENTICATED) {
+			if (conn->encrypt == 0x02) {
+				conn->sec_level = BT_SECURITY_L4;
+			} else {
+				conn->sec_level = BT_SECURITY_L3;
+			}
+		} else {
+			conn->sec_level = BT_SECURITY_L2;
+		}
+	} else {
+		BT_WARN("No BR/EDR link key found");
+		conn->sec_level = BT_SECURITY_L2;
+	}
+
+	if (!br_sufficient_key_size(conn)) {
+		BT_ERR("Encryption key size is not sufficient");
+		bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
+		return false;
+	}
+
+	if (conn->required_sec_level > conn->sec_level) {
+		BT_ERR("Failed to set required security level");
+		bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
+		return false;
+	}
+
+	return true;
+}
+
+static void synchronous_conn_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_sync_conn_complete *evt = (void *)buf->data;
+	struct bt_conn *sco_conn;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle,
+	       evt->link_type);
+
+	sco_conn = bt_conn_lookup_addr_sco(&evt->bdaddr);
+	if (!sco_conn) {
+		BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	if (evt->status) {
+		sco_conn->err = evt->status;
+		bt_conn_set_state(sco_conn, BT_CONN_DISCONNECTED);
+		bt_conn_unref(sco_conn);
+		return;
+	}
+
+	sco_conn->handle = handle;
+	bt_conn_set_state(sco_conn, BT_CONN_CONNECTED);
+	bt_conn_unref(sco_conn);
+}
+
+static void conn_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_conn_complete *evt = (void *)buf->data;
+	struct bt_conn *conn;
+	struct bt_hci_cp_read_remote_features *cp;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle,
+	       evt->link_type);
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	if (evt->status) {
+		conn->err = evt->status;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	conn->handle = handle;
+	conn->err = 0U;
+	conn->encrypt = evt->encr_enabled;
+
+	if (!update_sec_level_br(conn)) {
+		bt_conn_unref(conn);
+		return;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_CONNECTED);
+	bt_conn_unref(conn);
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_FEATURES, sizeof(*cp));
+	if (!buf) {
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = evt->handle;
+
+	bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_FEATURES, buf, NULL);
+}
+
+struct discovery_priv {
+	uint16_t clock_offset;
+	uint8_t pscan_rep_mode;
+	uint8_t resolving;
+} __packed;
+
+static int request_name(const bt_addr_t *addr, uint8_t pscan, uint16_t offset)
+{
+	struct bt_hci_cp_remote_name_request *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_REQUEST, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	bt_addr_copy(&cp->bdaddr, addr);
+	cp->pscan_rep_mode = pscan;
+	cp->reserved = 0x00; /* reserver, should be set to 0x00 */
+	cp->clock_offset = offset;
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_REMOTE_NAME_REQUEST, buf, NULL);
+}
+
+#define EIR_SHORT_NAME		0x08
+#define EIR_COMPLETE_NAME	0x09
+
+static bool eir_has_name(const uint8_t *eir)
+{
+	int len = 240;
+
+	while (len) {
+		if (len < 2) {
+			break;
+		};
+
+		/* Look for early termination */
+		if (!eir[0]) {
+			break;
+		}
+
+		/* Check if field length is correct */
+		if (eir[0] > len - 1) {
+			break;
+		}
+
+		switch (eir[1]) {
+		case EIR_SHORT_NAME:
+		case EIR_COMPLETE_NAME:
+			if (eir[0] > 1) {
+				return true;
+			}
+			break;
+		default:
+			break;
+		}
+
+		/* Parse next AD Structure */
+		len -= eir[0] + 1;
+		eir += eir[0] + 1;
+	}
+
+	return false;
+}
+
+static void report_discovery_results(void)
+{
+	bool resolving_names = false;
+	int i;
+
+	for (i = 0; i < discovery_results_count; i++) {
+		struct discovery_priv *priv;
+
+		priv = (struct discovery_priv *)&discovery_results[i]._priv;
+
+		if (eir_has_name(discovery_results[i].eir)) {
+			continue;
+		}
+
+		if (request_name(&discovery_results[i].addr,
+				 priv->pscan_rep_mode, priv->clock_offset)) {
+			continue;
+		}
+
+		priv->resolving = 1U;
+		resolving_names = true;
+	}
+
+	if (resolving_names) {
+		return;
+	}
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
+
+	discovery_cb(discovery_results, discovery_results_count);
+
+	discovery_cb = NULL;
+	discovery_results = NULL;
+	discovery_results_size = 0;
+	discovery_results_count = 0;
+}
+
+static void inquiry_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_inquiry_complete *evt = (void *)buf->data;
+
+	if (evt->status) {
+		BT_ERR("Failed to complete inquiry");
+	}
+
+	report_discovery_results();
+}
+
+static struct bt_br_discovery_result *get_result_slot(const bt_addr_t *addr,
+						      int8_t rssi)
+{
+	struct bt_br_discovery_result *result = NULL;
+	size_t i;
+
+	/* check if already present in results */
+	for (i = 0; i < discovery_results_count; i++) {
+		if (!bt_addr_cmp(addr, &discovery_results[i].addr)) {
+			return &discovery_results[i];
+		}
+	}
+
+	/* Pick a new slot (if available) */
+	if (discovery_results_count < discovery_results_size) {
+		bt_addr_copy(&discovery_results[discovery_results_count].addr,
+			     addr);
+		return &discovery_results[discovery_results_count++];
+	}
+
+	/* ignore if invalid RSSI */
+	if (rssi == 0xff) {
+		return NULL;
+	}
+
+	/*
+	 * Pick slot with smallest RSSI that is smaller then passed RSSI
+	 * TODO handle TX if present
+	 */
+	for (i = 0; i < discovery_results_size; i++) {
+		if (discovery_results[i].rssi > rssi) {
+			continue;
+		}
+
+		if (!result || result->rssi > discovery_results[i].rssi) {
+			result = &discovery_results[i];
+		}
+	}
+
+	if (result) {
+		BT_DBG("Reusing slot (old %s rssi %d dBm)",
+		       bt_addr_str(&result->addr), result->rssi);
+
+		bt_addr_copy(&result->addr, addr);
+	}
+
+	return result;
+}
+
+static void inquiry_result_with_rssi(struct net_buf *buf)
+{
+	uint8_t num_reports = net_buf_pull_u8(buf);
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
+		return;
+	}
+
+	BT_DBG("number of results: %u", num_reports);
+
+	while (num_reports--) {
+		struct bt_hci_evt_inquiry_result_with_rssi *evt;
+		struct bt_br_discovery_result *result;
+		struct discovery_priv *priv;
+
+		if (buf->len < sizeof(*evt)) {
+			BT_ERR("Unexpected end to buffer");
+			return;
+		}
+
+		evt = net_buf_pull_mem(buf, sizeof(*evt));
+		BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi);
+
+		result = get_result_slot(&evt->addr, evt->rssi);
+		if (!result) {
+			return;
+		}
+
+		priv = (struct discovery_priv *)&result->_priv;
+		priv->pscan_rep_mode = evt->pscan_rep_mode;
+		priv->clock_offset = evt->clock_offset;
+
+		memcpy(result->cod, evt->cod, 3);
+		result->rssi = evt->rssi;
+
+		/* we could reuse slot so make sure EIR is cleared */
+		(void)memset(result->eir, 0, sizeof(result->eir));
+	}
+}
+
+static void extended_inquiry_result(struct net_buf *buf)
+{
+	struct bt_hci_evt_extended_inquiry_result *evt = (void *)buf->data;
+	struct bt_br_discovery_result *result;
+	struct discovery_priv *priv;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
+		return;
+	}
+
+	BT_DBG("%s rssi %d dBm", bt_addr_str(&evt->addr), evt->rssi);
+
+	result = get_result_slot(&evt->addr, evt->rssi);
+	if (!result) {
+		return;
+	}
+
+	priv = (struct discovery_priv *)&result->_priv;
+	priv->pscan_rep_mode = evt->pscan_rep_mode;
+	priv->clock_offset = evt->clock_offset;
+
+	result->rssi = evt->rssi;
+	memcpy(result->cod, evt->cod, 3);
+	memcpy(result->eir, evt->eir, sizeof(result->eir));
+}
+
+static void remote_name_request_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_remote_name_req_complete *evt = (void *)buf->data;
+	struct bt_br_discovery_result *result;
+	struct discovery_priv *priv;
+	int eir_len = 240;
+	uint8_t *eir;
+	int i;
+
+	result = get_result_slot(&evt->bdaddr, 0xff);
+	if (!result) {
+		return;
+	}
+
+	priv = (struct discovery_priv *)&result->_priv;
+	priv->resolving = 0U;
+
+	if (evt->status) {
+		goto check_names;
+	}
+
+	eir = result->eir;
+
+	while (eir_len) {
+		if (eir_len < 2) {
+			break;
+		};
+
+		/* Look for early termination */
+		if (!eir[0]) {
+			size_t name_len;
+
+			eir_len -= 2;
+
+			/* name is null terminated */
+			name_len = strlen((const char *)evt->name);
+
+			if (name_len > eir_len) {
+				eir[0] = eir_len + 1;
+				eir[1] = EIR_SHORT_NAME;
+			} else {
+				eir[0] = name_len + 1;
+				eir[1] = EIR_SHORT_NAME;
+			}
+
+			memcpy(&eir[2], evt->name, eir[0] - 1);
+
+			break;
+		}
+
+		/* Check if field length is correct */
+		if (eir[0] > eir_len - 1) {
+			break;
+		}
+
+		/* next EIR Structure */
+		eir_len -= eir[0] + 1;
+		eir += eir[0] + 1;
+	}
+
+check_names:
+	/* if still waiting for names */
+	for (i = 0; i < discovery_results_count; i++) {
+		struct discovery_priv *priv;
+
+		priv = (struct discovery_priv *)&discovery_results[i]._priv;
+
+		if (priv->resolving) {
+			return;
+		}
+	}
+
+	/* all names resolved, report discovery results */
+	atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
+
+	discovery_cb(discovery_results, discovery_results_count);
+
+	discovery_cb = NULL;
+	discovery_results = NULL;
+	discovery_results_size = 0;
+	discovery_results_count = 0;
+}
+
+static void read_remote_features_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_remote_features *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_hci_cp_read_remote_ext_features *cp;
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x handle %u", evt->status, handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Can't find conn for handle %u", handle);
+		return;
+	}
+
+	if (evt->status) {
+		goto done;
+	}
+
+	memcpy(conn->br.features[0], evt->features, sizeof(evt->features));
+
+	if (!BT_FEAT_EXT_FEATURES(conn->br.features)) {
+		goto done;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_EXT_FEATURES,
+				sizeof(*cp));
+	if (!buf) {
+		goto done;
+	}
+
+	/* Read remote host features (page 1) */
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = evt->handle;
+	cp->page = 0x01;
+
+	bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_EXT_FEATURES, buf, NULL);
+
+done:
+	bt_conn_unref(conn);
+}
+
+static void read_remote_ext_features_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_remote_ext_features *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x handle %u", evt->status, handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Can't find conn for handle %u", handle);
+		return;
+	}
+
+	if (!evt->status && evt->page == 0x01) {
+		memcpy(conn->br.features[1], evt->features,
+		       sizeof(conn->br.features[1]));
+	}
+
+	bt_conn_unref(conn);
+}
+
+static void role_change(struct net_buf *buf)
+{
+	struct bt_hci_evt_role_change *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x role %u addr %s", evt->status, evt->role,
+	       bt_addr_str(&evt->bdaddr));
+
+	if (evt->status) {
+		return;
+	}
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	if (evt->role) {
+		conn->role = BT_CONN_ROLE_SLAVE;
+	} else {
+		conn->role = BT_CONN_ROLE_MASTER;
+	}
+
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_BREDR */
+
+#if defined(CONFIG_BT_SMP)
+static int le_set_privacy_mode(const bt_addr_le_t *addr, uint8_t mode)
+{
+	struct bt_hci_cp_le_set_privacy_mode cp;
+	struct net_buf *buf;
+	int err;
+
+	/* Check if set privacy mode command is supported */
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 39, 2)) {
+		BT_WARN("Set privacy mode command is not supported");
+		return 0;
+	}
+
+	BT_DBG("addr %s mode 0x%02x", bt_addr_le_str(addr), mode);
+
+	bt_addr_le_copy(&cp.id_addr, addr);
+	cp.mode = mode;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_mem(buf, &cp, sizeof(cp));
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PRIVACY_MODE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int addr_res_enable(uint8_t enable)
+{
+	struct net_buf *buf;
+
+	BT_DBG("%s", enable ? "enabled" : "disabled");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, 1);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_u8(buf, enable);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE,
+				    buf, NULL);
+}
+
+static int hci_id_add(uint8_t id, const bt_addr_le_t *addr, uint8_t peer_irk[16])
+{
+	struct bt_hci_cp_le_add_dev_to_rl *cp;
+	struct net_buf *buf;
+
+	BT_DBG("addr %s", bt_addr_le_str(addr));
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_RL, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_le_copy(&cp->peer_id_addr, addr);
+	memcpy(cp->peer_irk, peer_irk, 16);
+
+#if defined(CONFIG_BT_PRIVACY)
+	memcpy(cp->local_irk, bt_dev.irk[id], 16);
+#else
+	(void)memset(cp->local_irk, 0, 16);
+#endif
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_RL, buf, NULL);
+}
+
+void bt_id_add(struct bt_keys *keys)
+{
+	struct bt_conn *conn;
+	int err;
+
+	BT_DBG("addr %s", bt_addr_le_str(&keys->addr));
+
+	/* Nothing to be done if host-side resolving is used */
+	if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) {
+		bt_dev.le.rl_entries++;
+		keys->state |= BT_KEYS_ID_ADDED;
+		return;
+	}
+
+	conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT);
+	if (conn) {
+		pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV)) {
+		bool adv_enabled = false;
+
+		bt_adv_foreach(adv_is_limited_enabled, &adv_enabled);
+		if (adv_enabled) {
+			pending_id_keys_update_set(keys,
+						   BT_KEYS_ID_PENDING_ADD);
+			return;
+		}
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING);
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) {
+		pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD);
+	}
+#endif
+
+	bt_adv_foreach(adv_pause_enabled, NULL);
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (scan_enabled) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	/* If there are any existing entries address resolution will be on */
+	if (bt_dev.le.rl_entries) {
+		err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE);
+		if (err) {
+			BT_WARN("Failed to disable address resolution");
+			goto done;
+		}
+	}
+
+	if (bt_dev.le.rl_entries == bt_dev.le.rl_size) {
+		BT_WARN("Resolving list size exceeded. Switching to host.");
+
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_RL, NULL, NULL);
+		if (err) {
+			BT_ERR("Failed to clear resolution list");
+			goto done;
+		}
+
+		bt_dev.le.rl_entries++;
+		keys->state |= BT_KEYS_ID_ADDED;
+
+		goto done;
+	}
+
+	err = hci_id_add(keys->id, &keys->addr, keys->irk.val);
+	if (err) {
+		BT_ERR("Failed to add IRK to controller");
+		goto done;
+	}
+
+	bt_dev.le.rl_entries++;
+	keys->state |= BT_KEYS_ID_ADDED;
+
+	/*
+	 * According to Core Spec. 5.0 Vol 1, Part A 5.4.5 Privacy Feature
+	 *
+	 * By default, network privacy mode is used when private addresses are
+	 * resolved and generated by the Controller, so advertising packets from
+	 * peer devices that contain private addresses will only be accepted.
+	 * By changing to the device privacy mode device is only concerned about
+	 * its privacy and will accept advertising packets from peer devices
+	 * that contain their identity address as well as ones that contain
+	 * a private address, even if the peer device has distributed its IRK in
+	 * the past.
+	 */
+	err = le_set_privacy_mode(&keys->addr, BT_HCI_LE_PRIVACY_MODE_DEVICE);
+	if (err) {
+		BT_ERR("Failed to set privacy mode");
+		goto done;
+	}
+
+done:
+	addr_res_enable(BT_HCI_ADDR_RES_ENABLE);
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (scan_enabled) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	bt_adv_foreach(adv_unpause_enabled, NULL);
+}
+
+static void keys_add_id(struct bt_keys *keys, void *data)
+{
+	if (keys->state & BT_KEYS_ID_ADDED) {
+		hci_id_add(keys->id, &keys->addr, keys->irk.val);
+	}
+}
+
+static int hci_id_del(const bt_addr_le_t *addr)
+{
+	struct bt_hci_cp_le_rem_dev_from_rl *cp;
+	struct net_buf *buf;
+
+	BT_DBG("addr %s", bt_addr_le_str(addr));
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_RL, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_le_copy(&cp->peer_id_addr, addr);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_RL, buf, NULL);
+}
+
+void bt_id_del(struct bt_keys *keys)
+{
+	struct bt_conn *conn;
+	int err;
+
+	BT_DBG("addr %s", bt_addr_le_str(&keys->addr));
+
+	if (!bt_dev.le.rl_size ||
+	    bt_dev.le.rl_entries > bt_dev.le.rl_size + 1) {
+		bt_dev.le.rl_entries--;
+		keys->state &= ~BT_KEYS_ID_ADDED;
+		return;
+	}
+
+	conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL, BT_CONN_CONNECT);
+	if (conn) {
+		pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV)) {
+		bool adv_enabled = false;
+
+		bt_adv_foreach(adv_is_limited_enabled, &adv_enabled);
+		if (adv_enabled) {
+			pending_id_keys_update_set(keys,
+						   BT_KEYS_ID_PENDING_ADD);
+			return;
+		}
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	bool scan_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING);
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) && scan_enabled &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) {
+		pending_id_keys_update_set(keys, BT_KEYS_ID_PENDING_DEL);
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	bt_adv_foreach(adv_pause_enabled, NULL);
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (scan_enabled) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	err = addr_res_enable(BT_HCI_ADDR_RES_DISABLE);
+	if (err) {
+		BT_ERR("Disabling address resolution failed (err %d)", err);
+		goto done;
+	}
+
+	/* We checked size + 1 earlier, so here we know we can fit again */
+	if (bt_dev.le.rl_entries > bt_dev.le.rl_size) {
+		bt_dev.le.rl_entries--;
+		keys->state &= ~BT_KEYS_ID_ADDED;
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    IS_ENABLED(CONFIG_BT_PRIVACY)) {
+			bt_keys_foreach(BT_KEYS_ALL, keys_add_id, NULL);
+		} else {
+			bt_keys_foreach(BT_KEYS_IRK, keys_add_id, NULL);
+		}
+		goto done;
+	}
+
+	err = hci_id_del(&keys->addr);
+	if (err) {
+		BT_ERR("Failed to remove IRK from controller");
+		goto done;
+	}
+
+	bt_dev.le.rl_entries--;
+	keys->state &= ~BT_KEYS_ID_ADDED;
+
+done:
+	/* Only re-enable if there are entries to do resolving with */
+	if (bt_dev.le.rl_entries) {
+		addr_res_enable(BT_HCI_ADDR_RES_ENABLE);
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (scan_enabled) {
+		set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
+	}
+#endif /* CONFIG_BT_OBSERVER */
+
+	bt_adv_foreach(adv_unpause_enabled, NULL);
+}
+
+static void update_sec_level(struct bt_conn *conn)
+{
+	if (!conn->encrypt) {
+		conn->sec_level = BT_SECURITY_L1;
+		return;
+	}
+
+	if (conn->le.keys && (conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
+		if (conn->le.keys->flags & BT_KEYS_SC &&
+		    conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE) {
+			conn->sec_level = BT_SECURITY_L4;
+		} else {
+			conn->sec_level = BT_SECURITY_L3;
+		}
+	} else {
+		conn->sec_level = BT_SECURITY_L2;
+	}
+
+	if (conn->required_sec_level > conn->sec_level) {
+		BT_ERR("Failed to set required security level");
+		bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
+	}
+}
+#endif /* CONFIG_BT_SMP */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+static void hci_encrypt_change(struct net_buf *buf)
+{
+	struct bt_hci_evt_encrypt_change *evt = (void *)buf->data;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x handle %u encrypt 0x%02x", evt->status, handle,
+	       evt->encrypt);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to look up conn with handle %u", handle);
+		return;
+	}
+
+	if (evt->status) {
+		bt_conn_security_changed(conn, evt->status,
+					 bt_security_err_get(evt->status));
+		bt_conn_unref(conn);
+		return;
+	}
+
+	conn->encrypt = evt->encrypt;
+
+#if defined(CONFIG_BT_SMP)
+	if (conn->type == BT_CONN_TYPE_LE) {
+		/*
+		 * we update keys properties only on successful encryption to
+		 * avoid losing valid keys if encryption was not successful.
+		 *
+		 * Update keys with last pairing info for proper sec level
+		 * update. This is done only for LE transport, for BR/EDR keys
+		 * are updated on HCI 'Link Key Notification Event'
+		 */
+		if (conn->encrypt) {
+			bt_smp_update_keys(conn);
+		}
+		update_sec_level(conn);
+	}
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR) {
+		if (!update_sec_level_br(conn)) {
+			bt_conn_unref(conn);
+			return;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_SMP)) {
+			/*
+			 * Start SMP over BR/EDR if we are pairing and are
+			 * master on the link
+			 */
+			if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING) &&
+			    conn->role == BT_CONN_ROLE_MASTER) {
+				bt_smp_br_send_pairing_req(conn);
+			}
+		}
+	}
+#endif /* CONFIG_BT_BREDR */
+
+	bt_conn_security_changed(conn, evt->status, BT_SECURITY_ERR_SUCCESS);
+
+	bt_conn_unref(conn);
+}
+
+static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_encrypt_key_refresh_complete *evt = (void *)buf->data;
+	struct bt_conn *conn;
+	uint16_t handle;
+
+	handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("status 0x%02x handle %u", evt->status, handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to look up conn with handle %u", handle);
+		return;
+	}
+
+	if (evt->status) {
+		bt_conn_security_changed(conn, evt->status,
+					 bt_security_err_get(evt->status));
+		bt_conn_unref(conn);
+		return;
+	}
+
+	/*
+	 * Update keys with last pairing info for proper sec level update.
+	 * This is done only for LE transport. For BR/EDR transport keys are
+	 * updated on HCI 'Link Key Notification Event', therefore update here
+	 * only security level based on available keys and encryption state.
+	 */
+#if defined(CONFIG_BT_SMP)
+	if (conn->type == BT_CONN_TYPE_LE) {
+		bt_smp_update_keys(conn);
+		update_sec_level(conn);
+	}
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR) {
+		if (!update_sec_level_br(conn)) {
+			bt_conn_unref(conn);
+			return;
+		}
+	}
+#endif /* CONFIG_BT_BREDR */
+
+	bt_conn_security_changed(conn, evt->status, BT_SECURITY_ERR_SUCCESS);
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+
+#if defined(CONFIG_BT_REMOTE_VERSION)
+static void bt_hci_evt_read_remote_version_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_remote_version_info *evt;
+	struct bt_conn *conn;
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+	conn = bt_conn_lookup_handle(evt->handle);
+	if (!conn) {
+		BT_ERR("No connection for handle %u", evt->handle);
+		return;
+	}
+
+	if (!evt->status) {
+		conn->rv.version = evt->version;
+		conn->rv.manufacturer = sys_le16_to_cpu(evt->manufacturer);
+		conn->rv.subversion = sys_le16_to_cpu(evt->subversion);
+	}
+
+	atomic_set_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO);
+
+	if (IS_ENABLED(CONFIG_BT_REMOTE_INFO)) {
+		/* Remote features is already present */
+		notify_remote_info(conn);
+	}
+
+	/* Continue with auto-initiated procedures */
+	conn_auto_initiate(conn);
+
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_REMOTE_VERSION */
+
+static void hci_hardware_error(struct net_buf *buf)
+{
+	struct bt_hci_evt_hardware_error *evt;
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+
+	BT_ERR("Hardware error, hardware code: %d", evt->hardware_code);
+}
+
+#if defined(CONFIG_BT_SMP)
+static void le_ltk_neg_reply(uint16_t handle)
+{
+	struct bt_hci_cp_le_ltk_req_neg_reply *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Out of command buffers");
+
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(handle);
+
+	bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, buf);
+}
+
+static void le_ltk_reply(uint16_t handle, uint8_t *ltk)
+{
+	struct bt_hci_cp_le_ltk_req_reply *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY,
+				sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Out of command buffers");
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = sys_cpu_to_le16(handle);
+	memcpy(cp->ltk, ltk, sizeof(cp->ltk));
+
+	bt_hci_cmd_send(BT_HCI_OP_LE_LTK_REQ_REPLY, buf);
+}
+
+static void le_ltk_request(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_ltk_request *evt = (void *)buf->data;
+	struct bt_conn *conn;
+	uint16_t handle;
+	uint8_t ltk[16];
+
+	handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("handle %u", handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Unable to lookup conn for handle %u", handle);
+		return;
+	}
+
+	if (bt_smp_request_ltk(conn, evt->rand, evt->ediv, ltk)) {
+		le_ltk_reply(handle, ltk);
+	} else {
+		le_ltk_neg_reply(handle);
+	}
+
+	bt_conn_unref(conn);
+}
+#endif /* CONFIG_BT_SMP */
+
+#if defined(CONFIG_BT_ECC)
+static void le_pkey_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data;
+	struct bt_pub_key_cb *cb;
+
+	BT_DBG("status: 0x%02x", evt->status);
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
+
+	if (!evt->status) {
+		memcpy(pub_key, evt->key, 64);
+		atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
+	}
+
+	for (cb = pub_key_cb; cb; cb = cb->_next) {
+		cb->func(evt->status ? NULL : pub_key);
+	}
+
+	pub_key_cb = NULL;
+}
+
+static void le_dhkey_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data;
+
+	BT_DBG("status: 0x%02x", evt->status);
+
+	if (dh_key_cb) {
+		dh_key_cb(evt->status ? NULL : evt->dhkey);
+		dh_key_cb = NULL;
+	}
+}
+#endif /* CONFIG_BT_ECC */
+
+static void hci_reset_complete(struct net_buf *buf)
+{
+	uint8_t status = buf->data[0];
+	atomic_t flags;
+
+	BT_DBG("status 0x%02x", status);
+
+	if (status) {
+		return;
+	}
+
+	scan_dev_found_cb = NULL;
+#if defined(CONFIG_BT_BREDR)
+	discovery_cb = NULL;
+	discovery_results = NULL;
+	discovery_results_size = 0;
+	discovery_results_count = 0;
+#endif /* CONFIG_BT_BREDR */
+
+	flags = (atomic_get(bt_dev.flags) & BT_DEV_PERSISTENT_FLAGS);
+	atomic_set(bt_dev.flags, flags);
+}
+
+static void hci_cmd_done(uint16_t opcode, uint8_t status, struct net_buf *buf)
+{
+	BT_DBG("hci_cmd_done opcode 0x%04x status 0x%02x buf %p", opcode, status, buf);
+
+	BT_DBG("hci_cmd_done buf->pool_id %p hci_cmd_pool %p", net_buf_pool_get(buf->pool_id), &hci_cmd_pool);
+
+	if (net_buf_pool_get(buf->pool_id) != &hci_cmd_pool) {
+		BT_WARN("opcode 0x%04x pool id %u pool %p != &hci_cmd_pool %p",
+			opcode, buf->pool_id, net_buf_pool_get(buf->pool_id),
+			&hci_cmd_pool);
+		return;
+	}
+
+	if (cmd(buf)->opcode != opcode) {
+		BT_WARN("OpCode 0x%04x completed instead of expected 0x%04x",
+			opcode, cmd(buf)->opcode);
+	}
+#if 0
+    BT_DBG("2222");
+
+	if (cmd(buf)->state && !status) {
+		struct cmd_state_set *update = cmd(buf)->state;
+
+		atomic_set_bit_to(update->target, update->bit, update->val);
+	}
+
+    BT_DBG("333");
+
+	/* If the command was synchronous wake up bt_hci_cmd_send_sync() */
+	if (cmd(buf)->sync) {
+		cmd(buf)->status = status;
+		//k_sem_give(cmd(buf)->sync);
+	}
+    BT_DBG("444");
+#endif
+}
+
+static void hci_cmd_status(struct net_buf *buf)
+{
+	struct bt_hci_evt_cmd_status *evt;
+	uint16_t opcode;
+	uint8_t ncmd;
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+	opcode = sys_le16_to_cpu(evt->opcode);
+	ncmd = evt->ncmd;
+
+	BT_DBG("opcode 0x%04x", opcode);
+
+	hci_cmd_done(opcode, evt->status, buf);
+
+	/* Allow next command to be sent */
+	//if (ncmd) {
+	//	k_sem_give(&bt_dev.ncmd_sem);
+	//}
+}
+
+#if defined(CONFIG_BT_OBSERVER)
+static bool is_adv_using_rand_addr(void)
+{
+	struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		/* When advertising using extended advertising HCI commands
+		 * then the advertiser has it's own random address command.
+		 */
+		return false;
+	}
+
+	return adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED);
+}
+
+static int le_scan_set_random_addr(bool active_scan, uint8_t *own_addr_type)
+{
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		err = le_set_private_addr(BT_ID_DEFAULT);
+		if (err) {
+			return err;
+		}
+
+		if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
+			*own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
+		} else {
+			*own_addr_type = BT_ADDR_LE_RANDOM;
+		}
+	} else {
+		*own_addr_type = bt_dev.id_addr[0].type;
+
+		/* Use NRPA unless identity has been explicitly requested
+		 * (through Kconfig).
+		 * Use same RPA as legacy advertiser if advertising.
+		 */
+		if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) &&
+		    !is_adv_using_rand_addr()) {
+			err = le_set_private_addr(BT_ID_DEFAULT);
+			if (err) {
+				if (active_scan || !is_adv_using_rand_addr()) {
+					return err;
+				} else {
+					BT_WARN("Ignoring failure to set "
+						"address for passive scan (%d)",
+						err);
+				}
+			}
+
+			*own_addr_type = BT_ADDR_LE_RANDOM;
+		} else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) &&
+			   *own_addr_type == BT_ADDR_LE_RANDOM) {
+			/* If scanning with Identity Address we must set the
+			 * random identity address for both active and passive
+			 * scanner in order to receive adv reports that are
+			 * directed towards this identity.
+			 */
+			err = set_random_address(&bt_dev.id_addr[0].a);
+			if (err) {
+				return err;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int start_le_scan_ext(struct bt_hci_ext_scan_phy *phy_1m,
+			     struct bt_hci_ext_scan_phy *phy_coded,
+			     uint16_t duration)
+{
+	struct bt_hci_cp_le_set_ext_scan_param *set_param;
+	struct net_buf *buf;
+	uint8_t own_addr_type;
+	bool active_scan;
+	int err;
+
+	active_scan = (phy_1m && phy_1m->type == BT_HCI_LE_SCAN_ACTIVE) ||
+		      (phy_coded && phy_coded->type == BT_HCI_LE_SCAN_ACTIVE);
+
+	if (duration > 0) {
+		atomic_set_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED);
+
+		/* Allow bt_le_oob_get_local to be called directly before
+		 * starting a scan limited by timeout.
+		 */
+		if (IS_ENABLED(CONFIG_BT_PRIVACY) && !rpa_is_new()) {
+			atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+		}
+	}
+
+	err = le_scan_set_random_addr(active_scan, &own_addr_type);
+	if (err) {
+		return err;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_SCAN_PARAM,
+				sizeof(*set_param) +
+				(phy_1m ? sizeof(*phy_1m) : 0) +
+				(phy_coded ? sizeof(*phy_coded) : 0));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	set_param = net_buf_add(buf, sizeof(*set_param));
+	set_param->own_addr_type = own_addr_type;
+	set_param->phys = 0;
+
+	if (IS_ENABLED(CONFIG_BT_WHITELIST) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_WL)) {
+		set_param->filter_policy = BT_HCI_LE_SCAN_FP_USE_WHITELIST;
+	} else {
+		set_param->filter_policy = BT_HCI_LE_SCAN_FP_NO_WHITELIST;
+	}
+
+	if (phy_1m) {
+		set_param->phys |= BT_HCI_LE_EXT_SCAN_PHY_1M;
+		net_buf_add_mem(buf, phy_1m, sizeof(*phy_1m));
+	}
+
+	if (phy_coded) {
+		set_param->phys |= BT_HCI_LE_EXT_SCAN_PHY_CODED;
+		net_buf_add_mem(buf, phy_coded, sizeof(*phy_coded));
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_SCAN_PARAM, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	err = set_le_ext_scan_enable(BT_HCI_LE_SCAN_ENABLE, duration);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_ACTIVE_SCAN, active_scan);
+
+	return 0;
+}
+
+static int start_le_scan_legacy(uint8_t scan_type, uint16_t interval, uint16_t window)
+{
+	struct bt_hci_cp_le_set_scan_param set_param;
+	struct net_buf *buf;
+	int err;
+	bool active_scan;
+
+	(void)memset(&set_param, 0, sizeof(set_param));
+
+	set_param.scan_type = scan_type;
+
+	/* for the rest parameters apply default values according to
+	 *  spec 4.2, vol2, part E, 7.8.10
+	 */
+	set_param.interval = sys_cpu_to_le16(interval);
+	set_param.window = sys_cpu_to_le16(window);
+
+	if (IS_ENABLED(CONFIG_BT_WHITELIST) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_SCAN_WL)) {
+		set_param.filter_policy = BT_HCI_LE_SCAN_FP_USE_WHITELIST;
+	} else {
+		set_param.filter_policy = BT_HCI_LE_SCAN_FP_NO_WHITELIST;
+	}
+
+	active_scan = scan_type == BT_HCI_LE_SCAN_ACTIVE;
+	err = le_scan_set_random_addr(active_scan, &set_param.addr_type);
+	if (err) {
+		return err;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(set_param));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_mem(buf, &set_param, sizeof(set_param));
+
+	err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAM, buf);
+	if (err) {
+		return err;
+	}
+
+	err = set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_ACTIVE_SCAN, active_scan);
+
+	return 0;
+}
+
+static int start_passive_scan(bool fast_scan)
+{
+	uint16_t interval, window;
+
+	if (fast_scan) {
+		interval = BT_GAP_SCAN_FAST_INTERVAL;
+		window = BT_GAP_SCAN_FAST_WINDOW;
+	} else {
+		interval = CONFIG_BT_BACKGROUND_SCAN_INTERVAL;
+		window = CONFIG_BT_BACKGROUND_SCAN_WINDOW;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		struct bt_hci_ext_scan_phy scan;
+
+		scan.type = BT_HCI_LE_SCAN_PASSIVE;
+		scan.interval = sys_cpu_to_le16(interval);
+		scan.window = sys_cpu_to_le16(window);
+
+		return start_le_scan_ext(&scan, NULL, 0);
+	}
+
+	return start_le_scan_legacy(BT_HCI_LE_SCAN_PASSIVE, interval, window);
+}
+
+int bt_le_scan_update(bool fast_scan)
+{
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
+		return 0;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
+		int err;
+
+		err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+		struct bt_conn *conn;
+
+		/* don't restart scan if we have pending connection */
+		conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL,
+					       BT_CONN_CONNECT);
+		if (conn) {
+			bt_conn_unref(conn);
+			return 0;
+		}
+
+		conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL,
+					       BT_CONN_CONNECT_SCAN);
+		if (conn) {
+			atomic_set_bit(bt_dev.flags, BT_DEV_SCAN_FILTER_DUP);
+
+			bt_conn_unref(conn);
+
+			return start_passive_scan(fast_scan);
+		}
+	}
+
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+	if (get_pending_per_adv_sync()) {
+		return start_passive_scan(fast_scan);
+	}
+#endif
+
+	return 0;
+}
+
+void bt_data_parse(struct net_buf_simple *ad,
+		   bool (*func)(struct bt_data *data, void *user_data),
+		   void *user_data)
+{
+	while (ad->len > 1) {
+		struct bt_data data;
+		uint8_t len;
+
+		len = net_buf_simple_pull_u8(ad);
+		if (len == 0U) {
+			/* Early termination */
+			return;
+		}
+
+		if (len > ad->len) {
+			BT_WARN("Malformed data");
+			return;
+		}
+
+		data.type = net_buf_simple_pull_u8(ad);
+		data.data_len = len - 1;
+		data.data = ad->data;
+
+		if (!func(&data, user_data)) {
+			return;
+		}
+
+		net_buf_simple_pull(ad, len - 1);
+	}
+}
+
+/* Convert Legacy adv report evt_type field to adv props */
+static uint8_t get_adv_props(uint8_t evt_type)
+{
+	switch (evt_type) {
+	case BT_GAP_ADV_TYPE_ADV_IND:
+		return BT_GAP_ADV_PROP_CONNECTABLE |
+		       BT_GAP_ADV_PROP_SCANNABLE;
+
+	case BT_GAP_ADV_TYPE_ADV_DIRECT_IND:
+		return BT_GAP_ADV_PROP_CONNECTABLE |
+		       BT_GAP_ADV_PROP_DIRECTED;
+
+	case BT_GAP_ADV_TYPE_ADV_SCAN_IND:
+		return BT_GAP_ADV_PROP_SCANNABLE;
+
+	case BT_GAP_ADV_TYPE_ADV_NONCONN_IND:
+		return 0;
+
+	/* In legacy advertising report, we don't know if the scan
+	 * response come from a connectable advertiser, so don't
+	 * set connectable property bit.
+	 */
+	case BT_GAP_ADV_TYPE_SCAN_RSP:
+		return BT_GAP_ADV_PROP_SCAN_RESPONSE |
+		       BT_GAP_ADV_PROP_SCANNABLE;
+
+	default:
+		return 0;
+	}
+}
+
+static void le_adv_recv(bt_addr_le_t *addr, struct bt_le_scan_recv_info *info,
+			struct net_buf *buf, uint8_t len)
+{
+	struct bt_le_scan_cb *listener;
+	struct net_buf_simple_state state;
+	bt_addr_le_t id_addr;
+
+	BT_DBG("%s event %u, len %u, rssi %d dBm", bt_addr_le_str(addr),
+	       info->adv_type, len, info->rssi);
+
+	if (!IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN) &&
+	    (info->adv_props & BT_HCI_LE_ADV_PROP_DIRECT)) {
+		BT_DBG("Dropped direct adv report");
+		return;
+	}
+
+	if (addr->type == BT_ADDR_LE_PUBLIC_ID ||
+	    addr->type == BT_ADDR_LE_RANDOM_ID) {
+		bt_addr_le_copy(&id_addr, addr);
+		id_addr.type -= BT_ADDR_LE_PUBLIC_ID;
+	} else if (addr->type == BT_HCI_PEER_ADDR_ANONYMOUS) {
+		bt_addr_le_copy(&id_addr, BT_ADDR_LE_ANY);
+	} else {
+		bt_addr_le_copy(&id_addr,
+				bt_lookup_id_addr(BT_ID_DEFAULT, addr));
+	}
+
+	info->addr = &id_addr;
+
+	if (scan_dev_found_cb) {
+		net_buf_simple_save(&buf->b, &state);
+
+		buf->len = len;
+		scan_dev_found_cb(&id_addr, info->rssi, info->adv_type,
+				  &buf->b);
+
+		net_buf_simple_restore(&buf->b, &state);
+	}
+
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&scan_cbs, listener, node) {
+		if (listener->recv) {
+			net_buf_simple_save(&buf->b, &state);
+
+			buf->len = len;
+			listener->recv(info, &buf->b);
+
+			net_buf_simple_restore(&buf->b, &state);
+		}
+	}
+
+#if defined(CONFIG_BT_CENTRAL)
+	check_pending_conn(&id_addr, addr, info->adv_props);
+#endif /* CONFIG_BT_CENTRAL */
+}
+
+#if defined(CONFIG_BT_EXT_ADV)
+static void le_scan_timeout(struct net_buf *buf)
+{
+	struct bt_le_scan_cb *listener;
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING);
+	atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED);
+	atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+
+#if defined(CONFIG_BT_SMP)
+	pending_id_keys_update();
+#endif
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&scan_cbs, listener, node) {
+		if (listener->timeout) {
+			listener->timeout();
+		}
+	}
+}
+
+/* Convert Extended adv report evt_type field into adv type */
+static uint8_t get_adv_type(uint8_t evt_type)
+{
+	switch (evt_type) {
+	case (BT_HCI_LE_ADV_EVT_TYPE_CONN |
+	      BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+	      BT_HCI_LE_ADV_EVT_TYPE_LEGACY):
+		return BT_GAP_ADV_TYPE_ADV_IND;
+
+	case (BT_HCI_LE_ADV_EVT_TYPE_CONN |
+	      BT_HCI_LE_ADV_EVT_TYPE_DIRECT |
+	      BT_HCI_LE_ADV_EVT_TYPE_LEGACY):
+		return BT_GAP_ADV_TYPE_ADV_DIRECT_IND;
+
+	case (BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+	      BT_HCI_LE_ADV_EVT_TYPE_LEGACY):
+		return BT_GAP_ADV_TYPE_ADV_SCAN_IND;
+
+	case BT_HCI_LE_ADV_EVT_TYPE_LEGACY:
+		return BT_GAP_ADV_TYPE_ADV_NONCONN_IND;
+
+	case (BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP |
+	      BT_HCI_LE_ADV_EVT_TYPE_CONN |
+	      BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+	      BT_HCI_LE_ADV_EVT_TYPE_LEGACY):
+	case (BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP |
+	      BT_HCI_LE_ADV_EVT_TYPE_SCAN |
+	      BT_HCI_LE_ADV_EVT_TYPE_LEGACY):
+		/* Scan response from connectable or non-connectable advertiser.
+		 */
+		return BT_GAP_ADV_TYPE_SCAN_RSP;
+
+	default:
+		return BT_GAP_ADV_TYPE_EXT_ADV;
+	}
+}
+
+static void le_adv_ext_report(struct net_buf *buf)
+{
+	uint8_t num_reports = net_buf_pull_u8(buf);
+
+	BT_DBG("Adv number of reports %u",  num_reports);
+
+	while (num_reports--) {
+		struct bt_hci_evt_le_ext_advertising_info *evt;
+		struct bt_le_scan_recv_info adv_info;
+
+		if (buf->len < sizeof(*evt)) {
+			BT_ERR("Unexpected end of buffer");
+			break;
+		}
+
+		evt = net_buf_pull_mem(buf, sizeof(*evt));
+
+		adv_info.primary_phy = get_phy(evt->prim_phy);
+		adv_info.secondary_phy = get_phy(evt->sec_phy);
+		adv_info.tx_power = evt->tx_power;
+		adv_info.rssi = evt->rssi;
+		adv_info.sid = evt->sid;
+		adv_info.interval = sys_le16_to_cpu(evt->interval);
+
+		adv_info.adv_type = get_adv_type(evt->evt_type);
+		/* Convert "Legacy" property to Extended property. */
+		adv_info.adv_props = evt->evt_type ^ BT_HCI_LE_ADV_PROP_LEGACY;
+
+		le_adv_recv(&evt->addr, &adv_info, buf, evt->length);
+
+		net_buf_pull(buf, evt->length);
+	}
+}
+
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+static void per_adv_sync_delete(struct bt_le_per_adv_sync *per_adv_sync)
+{
+	atomic_clear(per_adv_sync->flags);
+}
+
+static struct bt_le_per_adv_sync *get_pending_per_adv_sync(void)
+{
+	for (int i = 0; i < ARRAY_SIZE(per_adv_sync_pool); i++) {
+		if (atomic_test_bit(per_adv_sync_pool[i].flags,
+				    BT_PER_ADV_SYNC_SYNCING)) {
+			return &per_adv_sync_pool[i];
+		}
+	}
+
+	return NULL;
+}
+
+static struct bt_le_per_adv_sync *get_per_adv_sync(uint16_t handle)
+{
+	for (int i = 0; i < ARRAY_SIZE(per_adv_sync_pool); i++) {
+		if (per_adv_sync_pool[i].handle == handle &&
+		    atomic_test_bit(per_adv_sync_pool[i].flags,
+				    BT_PER_ADV_SYNC_SYNCED)) {
+			return &per_adv_sync_pool[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void le_per_adv_report(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_per_advertising_report *evt;
+	struct bt_le_per_adv_sync *per_adv_sync;
+	struct bt_le_per_adv_sync_recv_info info;
+	struct bt_le_per_adv_sync_cb *listener;
+	struct net_buf_simple_state state;
+
+	if (buf->len < sizeof(*evt)) {
+		BT_ERR("Unexpected end of buffer");
+		return;
+	}
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+
+	per_adv_sync = get_per_adv_sync(sys_le16_to_cpu(evt->handle));
+
+	if (!per_adv_sync) {
+		BT_ERR("Unknown handle 0x%04X for periodic advertising report",
+		       sys_le16_to_cpu(evt->handle));
+		return;
+	}
+
+	info.tx_power = evt->tx_power;
+	info.rssi = evt->rssi;
+	info.cte_type = evt->cte_type;
+	info.addr = &per_adv_sync->addr;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs, listener, node) {
+		if (listener->recv) {
+			net_buf_simple_save(&buf->b, &state);
+
+			buf->len = evt->length;
+			listener->recv(per_adv_sync, &info, &buf->b);
+
+			net_buf_simple_restore(&buf->b, &state);
+		}
+	}
+}
+
+static int per_adv_sync_terminate(uint16_t handle)
+{
+	struct bt_hci_cp_le_per_adv_terminate_sync *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC,
+				sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	cp->handle = sys_cpu_to_le16(handle);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC, buf,
+				    NULL);
+}
+
+static void le_per_adv_sync_established(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_per_adv_sync_established *evt =
+		(struct bt_hci_evt_le_per_adv_sync_established *)buf->data;
+	struct bt_le_per_adv_sync_synced_info sync_info;
+	struct bt_le_per_adv_sync *pending_per_adv_sync;
+	struct bt_le_per_adv_sync_cb *listener;
+	int err;
+
+	pending_per_adv_sync = get_pending_per_adv_sync();
+
+	if (pending_per_adv_sync) {
+		atomic_clear_bit(pending_per_adv_sync->flags,
+				 BT_PER_ADV_SYNC_SYNCING);
+		err = bt_le_scan_update(false);
+
+		if (err) {
+			BT_ERR("Could not update scan (%d)", err);
+		}
+	}
+
+	if (!pending_per_adv_sync ||
+	    pending_per_adv_sync->sid != evt->sid ||
+	    bt_addr_le_cmp(&pending_per_adv_sync->addr, &evt->adv_addr)) {
+		struct bt_le_per_adv_sync_term_info term_info;
+
+		BT_ERR("Unexpected per adv sync established event");
+		per_adv_sync_terminate(sys_le16_to_cpu(evt->handle));
+
+		if (pending_per_adv_sync) {
+			/* Terminate the pending PA sync and notify app */
+			term_info.addr = &pending_per_adv_sync->addr;
+			term_info.sid = pending_per_adv_sync->sid;
+
+			/* Deleting before callback, so the caller will be able
+			 * to restart sync in the callback.
+			 */
+			per_adv_sync_delete(pending_per_adv_sync);
+
+
+			SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs,
+						     listener,
+						     node) {
+				if (listener->term) {
+					listener->term(pending_per_adv_sync,
+						       &term_info);
+				}
+			}
+		}
+		return;
+	}
+
+	if (evt->status == BT_HCI_ERR_OP_CANCELLED_BY_HOST) {
+		/* Cancelled locally, don't call CB */
+		return;
+	}
+
+	atomic_set_bit(pending_per_adv_sync->flags, BT_PER_ADV_SYNC_SYNCED);
+
+	pending_per_adv_sync->handle = sys_le16_to_cpu(evt->handle);
+	pending_per_adv_sync->interval = sys_le16_to_cpu(evt->interval);
+	pending_per_adv_sync->clock_accuracy =
+		sys_le16_to_cpu(evt->clock_accuracy);
+	pending_per_adv_sync->phy = evt->phy;
+
+	sync_info.interval = pending_per_adv_sync->interval;
+	sync_info.phy = get_phy(pending_per_adv_sync->phy);
+	sync_info.addr = &pending_per_adv_sync->addr;
+	sync_info.sid = pending_per_adv_sync->sid;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs, listener, node) {
+		if (listener->synced) {
+			listener->synced(pending_per_adv_sync, &sync_info);
+		}
+	}
+}
+
+static void le_per_adv_sync_lost(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_per_adv_sync_lost *evt =
+		(struct bt_hci_evt_le_per_adv_sync_lost *)buf->data;
+	struct bt_le_per_adv_sync_term_info term_info;
+	struct bt_le_per_adv_sync *per_adv_sync;
+	struct bt_le_per_adv_sync_cb *listener;
+
+	per_adv_sync = get_per_adv_sync(sys_le16_to_cpu(evt->handle));
+
+	if (!per_adv_sync) {
+		BT_ERR("Unknown handle 0x%04Xfor periodic adv sync lost",
+		       sys_le16_to_cpu(evt->handle));
+		return;
+	}
+
+	term_info.addr = &per_adv_sync->addr;
+	term_info.sid = per_adv_sync->sid;
+
+	/* Deleting before callback, so the caller will be able to restart
+	 * sync in the callback
+	 */
+	per_adv_sync_delete(per_adv_sync);
+
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&pa_sync_cbs, listener, node) {
+		if (listener->term) {
+			listener->term(per_adv_sync, &term_info);
+		}
+	}
+}
+#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+static void le_adv_report(struct net_buf *buf)
+{
+	uint8_t num_reports = net_buf_pull_u8(buf);
+	struct bt_hci_evt_le_advertising_info *evt;
+
+	BT_DBG("Adv number of reports %u",  num_reports);
+
+	while (num_reports--) {
+		struct bt_le_scan_recv_info adv_info;
+
+		if (buf->len < sizeof(*evt)) {
+			BT_ERR("Unexpected end of buffer");
+			break;
+		}
+
+		evt = net_buf_pull_mem(buf, sizeof(*evt));
+
+		adv_info.rssi = evt->data[evt->length];
+		adv_info.primary_phy = BT_GAP_LE_PHY_1M;
+		adv_info.secondary_phy = 0;
+		adv_info.tx_power = BT_GAP_TX_POWER_INVALID;
+		adv_info.sid = BT_GAP_SID_INVALID;
+
+		adv_info.adv_type = evt->evt_type;
+		adv_info.adv_props = get_adv_props(evt->evt_type);
+
+		le_adv_recv(&evt->addr, &adv_info, buf, evt->length);
+
+		net_buf_pull(buf, evt->length + sizeof(adv_info.rssi));
+	}
+}
+#endif /* CONFIG_BT_OBSERVER */
+
+static void le_adv_stop_free_conn(const struct bt_le_ext_adv *adv, uint8_t status)
+{
+	struct bt_conn *conn;
+
+	if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) {
+		conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE,
+					       BT_CONN_CONNECT_ADV);
+	} else {
+		conn = bt_conn_lookup_state_le(adv->id, &adv->target_addr,
+					       BT_CONN_CONNECT_DIR_ADV);
+	}
+
+	if (conn) {
+		conn->err = status;
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+		bt_conn_unref(conn);
+	}
+}
+
+
+#if defined(CONFIG_BT_EXT_ADV)
+#if defined(CONFIG_BT_BROADCASTER)
+static void le_adv_set_terminated(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_adv_set_terminated *evt;
+	struct bt_le_ext_adv *adv;
+	uint16_t conn_handle;
+
+	evt = (void *)buf->data;
+	adv = bt_adv_lookup_handle(evt->adv_handle);
+	conn_handle = sys_le16_to_cpu(evt->conn_handle);
+
+	BT_DBG("status 0x%02x adv_handle %u conn_handle 0x%02x num %u",
+	       evt->status, evt->adv_handle, conn_handle,
+	       evt->num_completed_ext_adv_evts);
+
+	if (!adv) {
+		BT_ERR("No valid adv");
+		return;
+	}
+
+	atomic_clear_bit(adv->flags, BT_ADV_ENABLED);
+
+	if (evt->status && IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		/* Only set status for legacy advertising API.
+		 * This will call connected callback for high duty cycle
+		 * directed advertiser timeout.
+		 */
+		le_adv_stop_free_conn(adv, adv == bt_dev.adv ? evt->status : 0);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN) && !evt->status) {
+		struct bt_conn *conn = bt_conn_lookup_handle(conn_handle);
+
+		if (conn) {
+			if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+			    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+				/* Set Responder address unless already set */
+				conn->le.resp_addr.type = BT_ADDR_LE_RANDOM;
+				if (bt_addr_cmp(&conn->le.resp_addr.a,
+						BT_ADDR_ANY) == 0) {
+					bt_addr_copy(&conn->le.resp_addr.a,
+						     &adv->random_addr.a);
+				}
+			} else {
+				bt_addr_le_copy(&conn->le.resp_addr,
+					&bt_dev.id_addr[conn->id]);
+			}
+
+			if (adv->cb && adv->cb->connected) {
+				struct bt_le_ext_adv_connected_info info = {
+					.conn = conn,
+				};
+
+				adv->cb->connected(adv, &info);
+			}
+
+			bt_conn_unref(conn);
+		}
+	}
+
+	if (atomic_test_and_clear_bit(adv->flags, BT_ADV_LIMITED)) {
+		atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
+
+#if defined(CONFIG_BT_SMP)
+		pending_id_keys_update();
+#endif
+
+		if (adv->cb && adv->cb->sent) {
+			struct bt_le_ext_adv_sent_info info = {
+				.num_sent = evt->num_completed_ext_adv_evts,
+			};
+
+			adv->cb->sent(adv, &info);
+		}
+	}
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_PERSIST) && adv == bt_dev.adv) {
+		adv_delete_legacy();
+	}
+}
+
+static void le_scan_req_received(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_scan_req_received *evt;
+	struct bt_le_ext_adv *adv;
+
+	evt = (void *)buf->data;
+	adv = bt_adv_lookup_handle(evt->handle);
+
+	BT_DBG("handle %u peer %s", evt->handle, bt_addr_le_str(&evt->addr));
+
+	if (!adv) {
+		BT_ERR("No valid adv");
+		return;
+	}
+
+	if (adv->cb && adv->cb->scanned) {
+		struct bt_le_ext_adv_scanned_info info;
+		bt_addr_le_t id_addr;
+
+		if (evt->addr.type == BT_ADDR_LE_PUBLIC_ID ||
+		    evt->addr.type == BT_ADDR_LE_RANDOM_ID) {
+			bt_addr_le_copy(&id_addr, &evt->addr);
+			id_addr.type -= BT_ADDR_LE_PUBLIC_ID;
+		} else {
+			bt_addr_le_copy(&id_addr,
+					bt_lookup_id_addr(adv->id, &evt->addr));
+		}
+
+		info.addr = &id_addr;
+		adv->cb->scanned(adv, &info);
+	}
+}
+#endif /* defined(CONFIG_BT_BROADCASTER) */
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+int bt_hci_get_conn_handle(const struct bt_conn *conn, uint16_t *conn_handle)
+{
+	if (conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	*conn_handle = conn->handle;
+	return 0;
+}
+
+#if defined(CONFIG_BT_HCI_VS_EVT_USER)
+int bt_hci_register_vnd_evt_cb(bt_hci_vnd_evt_cb_t cb)
+{
+	hci_vnd_evt_cb = cb;
+	return 0;
+}
+#endif /* CONFIG_BT_HCI_VS_EVT_USER */
+
+static void hci_vendor_event(struct net_buf *buf)
+{
+	bool handled = false;
+
+#if defined(CONFIG_BT_HCI_VS_EVT_USER)
+	if (hci_vnd_evt_cb) {
+		struct net_buf_simple_state state;
+
+		net_buf_simple_save(&buf->b, &state);
+
+		handled = hci_vnd_evt_cb(&buf->b);
+
+		net_buf_simple_restore(&buf->b, &state);
+	}
+#endif /* CONFIG_BT_HCI_VS_EVT_USER */
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT) && !handled) {
+		/* do nothing at present time */
+		BT_WARN("Unhandled vendor-specific event: %s",
+			bt_hex(buf->data, buf->len));
+	}
+}
+
+static const struct event_handler meta_events[] = {
+#if defined(CONFIG_BT_OBSERVER)
+	EVENT_HANDLER(BT_HCI_EVT_LE_ADVERTISING_REPORT, le_adv_report,
+		      sizeof(struct bt_hci_evt_le_advertising_report)),
+#endif /* CONFIG_BT_OBSERVER */
+#if defined(CONFIG_BT_CONN)
+	EVENT_HANDLER(BT_HCI_EVT_LE_CONN_COMPLETE, le_legacy_conn_complete,
+		      sizeof(struct bt_hci_evt_le_conn_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_ENH_CONN_COMPLETE, le_enh_conn_complete,
+		      sizeof(struct bt_hci_evt_le_enh_conn_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE,
+		      le_conn_update_complete,
+		      sizeof(struct bt_hci_evt_le_conn_update_complete)),
+	EVENT_HANDLER(BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE,
+		      le_remote_feat_complete,
+		      sizeof(struct bt_hci_evt_le_remote_feat_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_CONN_PARAM_REQ, le_conn_param_req,
+		      sizeof(struct bt_hci_evt_le_conn_param_req)),
+#if defined(CONFIG_BT_DATA_LEN_UPDATE)
+	EVENT_HANDLER(BT_HCI_EVT_LE_DATA_LEN_CHANGE, le_data_len_change,
+		      sizeof(struct bt_hci_evt_le_data_len_change)),
+#endif /* CONFIG_BT_DATA_LEN_UPDATE */
+#if defined(CONFIG_BT_PHY_UPDATE)
+	EVENT_HANDLER(BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE,
+		      le_phy_update_complete,
+		      sizeof(struct bt_hci_evt_le_phy_update_complete)),
+#endif /* CONFIG_BT_PHY_UPDATE */
+#endif /* CONFIG_BT_CONN */
+#if defined(CONFIG_BT_SMP)
+	EVENT_HANDLER(BT_HCI_EVT_LE_LTK_REQUEST, le_ltk_request,
+		      sizeof(struct bt_hci_evt_le_ltk_request)),
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_ECC)
+	EVENT_HANDLER(BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE, le_pkey_complete,
+		      sizeof(struct bt_hci_evt_le_p256_public_key_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE, le_dhkey_complete,
+		      sizeof(struct bt_hci_evt_le_generate_dhkey_complete)),
+#endif /* CONFIG_BT_SMP */
+#if defined(CONFIG_BT_EXT_ADV)
+#if defined(CONFIG_BT_BROADCASTER)
+	EVENT_HANDLER(BT_HCI_EVT_LE_ADV_SET_TERMINATED, le_adv_set_terminated,
+		      sizeof(struct bt_hci_evt_le_adv_set_terminated)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_SCAN_REQ_RECEIVED, le_scan_req_received,
+		      sizeof(struct bt_hci_evt_le_scan_req_received)),
+#endif
+#if defined(CONFIG_BT_OBSERVER)
+	EVENT_HANDLER(BT_HCI_EVT_LE_SCAN_TIMEOUT, le_scan_timeout,
+		      0),
+	EVENT_HANDLER(BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT, le_adv_ext_report,
+		      sizeof(struct bt_hci_evt_le_ext_advertising_report)),
+#endif /* defined(CONFIG_BT_OBSERVER) */
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+	EVENT_HANDLER(BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED,
+		      le_per_adv_sync_established,
+		      sizeof(struct bt_hci_evt_le_per_adv_sync_established)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_PER_ADVERTISING_REPORT, le_per_adv_report,
+		      sizeof(struct bt_hci_evt_le_per_advertising_report)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_PER_ADV_SYNC_LOST, le_per_adv_sync_lost,
+		      sizeof(struct bt_hci_evt_le_per_adv_sync_lost)),
+#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+#if defined(CONFIG_BT_ISO)
+	EVENT_HANDLER(BT_HCI_EVT_LE_CIS_ESTABLISHED, hci_le_cis_estabilished,
+		      sizeof(struct bt_hci_evt_le_cis_established)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_CIS_REQ, hci_le_cis_req,
+		      sizeof(struct bt_hci_evt_le_cis_req)),
+#endif /* (CONFIG_BT_ISO) */
+};
+
+static void hci_le_meta_event(struct net_buf *buf)
+{
+	struct bt_hci_evt_le_meta_event *evt;
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+
+	BT_DBG("hci_le_meta_event 0x%02x", evt->subevent);
+
+	handle_event(evt->subevent, buf, meta_events, ARRAY_SIZE(meta_events));
+}
+
+static const struct event_handler normal_events[] = {
+	EVENT_HANDLER(BT_HCI_EVT_VENDOR, hci_vendor_event,
+		      sizeof(struct bt_hci_evt_vs)),
+	EVENT_HANDLER(BT_HCI_EVT_LE_META_EVENT, hci_le_meta_event,
+		      sizeof(struct bt_hci_evt_le_meta_event)),
+#if defined(CONFIG_BT_BREDR)
+	EVENT_HANDLER(BT_HCI_EVT_CONN_REQUEST, conn_req,
+		      sizeof(struct bt_hci_evt_conn_request)),
+	EVENT_HANDLER(BT_HCI_EVT_CONN_COMPLETE, conn_complete,
+		      sizeof(struct bt_hci_evt_conn_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_PIN_CODE_REQ, hci_evt_pin_code_req,
+		      sizeof(struct bt_hci_evt_pin_code_req)),
+	EVENT_HANDLER(BT_HCI_EVT_LINK_KEY_NOTIFY, hci_evt_link_key_notify,
+		      sizeof(struct bt_hci_evt_link_key_notify)),
+	EVENT_HANDLER(BT_HCI_EVT_LINK_KEY_REQ, hci_evt_link_key_req,
+		      sizeof(struct bt_hci_evt_link_key_req)),
+	EVENT_HANDLER(BT_HCI_EVT_IO_CAPA_RESP, hci_evt_io_capa_resp,
+		      sizeof(struct bt_hci_evt_io_capa_resp)),
+	EVENT_HANDLER(BT_HCI_EVT_IO_CAPA_REQ, hci_evt_io_capa_req,
+		      sizeof(struct bt_hci_evt_io_capa_req)),
+	EVENT_HANDLER(BT_HCI_EVT_SSP_COMPLETE, hci_evt_ssp_complete,
+		      sizeof(struct bt_hci_evt_ssp_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_USER_CONFIRM_REQ, hci_evt_user_confirm_req,
+		      sizeof(struct bt_hci_evt_user_confirm_req)),
+	EVENT_HANDLER(BT_HCI_EVT_USER_PASSKEY_NOTIFY,
+		      hci_evt_user_passkey_notify,
+		      sizeof(struct bt_hci_evt_user_passkey_notify)),
+	EVENT_HANDLER(BT_HCI_EVT_USER_PASSKEY_REQ, hci_evt_user_passkey_req,
+		      sizeof(struct bt_hci_evt_user_passkey_req)),
+	EVENT_HANDLER(BT_HCI_EVT_INQUIRY_COMPLETE, inquiry_complete,
+		      sizeof(struct bt_hci_evt_inquiry_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI,
+		      inquiry_result_with_rssi,
+		      sizeof(struct bt_hci_evt_inquiry_result_with_rssi)),
+	EVENT_HANDLER(BT_HCI_EVT_EXTENDED_INQUIRY_RESULT,
+		      extended_inquiry_result,
+		      sizeof(struct bt_hci_evt_extended_inquiry_result)),
+	EVENT_HANDLER(BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE,
+		      remote_name_request_complete,
+		      sizeof(struct bt_hci_evt_remote_name_req_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_AUTH_COMPLETE, hci_evt_auth_complete,
+		      sizeof(struct bt_hci_evt_auth_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_REMOTE_FEATURES,
+		      read_remote_features_complete,
+		      sizeof(struct bt_hci_evt_remote_features)),
+	EVENT_HANDLER(BT_HCI_EVT_REMOTE_EXT_FEATURES,
+		      read_remote_ext_features_complete,
+		      sizeof(struct bt_hci_evt_remote_ext_features)),
+	EVENT_HANDLER(BT_HCI_EVT_ROLE_CHANGE, role_change,
+		      sizeof(struct bt_hci_evt_role_change)),
+	EVENT_HANDLER(BT_HCI_EVT_SYNC_CONN_COMPLETE, synchronous_conn_complete,
+		      sizeof(struct bt_hci_evt_sync_conn_complete)),
+#endif /* CONFIG_BT_BREDR */
+#if defined(CONFIG_BT_CONN)
+	EVENT_HANDLER(BT_HCI_EVT_DISCONN_COMPLETE, hci_disconn_complete,
+		      sizeof(struct bt_hci_evt_disconn_complete)),
+#endif /* CONFIG_BT_CONN */
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	EVENT_HANDLER(BT_HCI_EVT_ENCRYPT_CHANGE, hci_encrypt_change,
+		      sizeof(struct bt_hci_evt_encrypt_change)),
+	EVENT_HANDLER(BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE,
+		      hci_encrypt_key_refresh_complete,
+		      sizeof(struct bt_hci_evt_encrypt_key_refresh_complete)),
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
+#if defined(CONFIG_BT_REMOTE_VERSION)
+	EVENT_HANDLER(BT_HCI_EVT_REMOTE_VERSION_INFO,
+		      bt_hci_evt_read_remote_version_complete,
+		      sizeof(struct bt_hci_evt_remote_version_info)),
+#endif /* CONFIG_BT_REMOTE_VERSION */
+	EVENT_HANDLER(BT_HCI_EVT_HARDWARE_ERROR, hci_hardware_error,
+		      sizeof(struct bt_hci_evt_hardware_error)),
+};
+
+static void hci_event(struct net_buf *buf)
+{
+	struct bt_hci_evt_hdr *hdr;
+
+	BT_ASSERT(buf->len >= sizeof(*hdr));
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	BT_DBG("event 0x%02x", hdr->evt);
+	BT_ASSERT(bt_hci_evt_get_flags(hdr->evt) & BT_HCI_EVT_FLAG_RECV);
+
+	handle_event(hdr->evt, buf, normal_events, ARRAY_SIZE(normal_events));
+
+	net_buf_unref(buf);
+}
+
+static void send_cmd(void)
+{
+	struct net_buf *buf;
+	int err;
+
+	/* Get next command */
+	BT_DBG("send_cmd, calling net_buf_get");
+	buf = net_buf_get(&bt_dev.cmd_tx_queue, K_NO_WAIT);
+	BT_ASSERT(buf);
+
+	/* Wait until ncmd > 0 */
+	//BT_DBG("calling sem_take_wait");
+	//k_sem_take(&bt_dev.ncmd_sem, K_FOREVER);
+
+	/* Clear out any existing sent command */
+	if (bt_dev.sent_cmd) {
+		BT_ERR("Uncleared pending sent_cmd");
+		net_buf_unref(bt_dev.sent_cmd);
+		bt_dev.sent_cmd = NULL;
+	}
+
+	bt_dev.sent_cmd = net_buf_ref(buf);
+
+	BT_DBG("Sending command 0x%04x (buf %p) to driver",
+	       cmd(buf)->opcode, buf);
+
+	err = bt_send(buf);
+	if (err) {
+		BT_ERR("Unable to send to driver (err %d)", err);
+		//k_sem_give(&bt_dev.ncmd_sem);
+		hci_cmd_done(cmd(buf)->opcode, BT_HCI_ERR_UNSPECIFIED, buf);
+		net_buf_unref(bt_dev.sent_cmd);
+		bt_dev.sent_cmd = NULL;
+		net_buf_unref(buf);
+	}
+}
+
+static void process_events(struct k_poll_event *ev, int count)
+{
+	BT_DBG("count %d", count);
+
+	for (; count; ev++, count--) {
+		BT_DBG("ev->state %u", ev->state);
+
+		switch (ev->state) {
+		case K_POLL_STATE_SIGNALED:
+			break;
+		case K_POLL_STATE_FIFO_DATA_AVAILABLE:
+			if (ev->tag == BT_EVENT_CMD_TX) {
+				send_cmd();
+			} else if (IS_ENABLED(CONFIG_BT_CONN)) {
+				struct bt_conn *conn;
+
+				if (ev->tag == BT_EVENT_CONN_TX_QUEUE) {
+					conn = CONTAINER_OF(ev->fifo,
+							    struct bt_conn,
+							    tx_queue);
+					bt_conn_process_tx(conn);
+				}
+			}
+			break;
+		case K_POLL_STATE_NOT_READY:
+			break;
+		default:
+			BT_WARN("Unexpected k_poll event state %u", ev->state);
+			break;
+		}
+	}
+}
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_ISO)
+/* command FIFO + conn_change signal + MAX_CONN + MAX_ISO_CONN */
+#define EV_COUNT (2 + CONFIG_BT_MAX_CONN + CONFIG_BT_MAX_ISO_CONN)
+#else
+/* command FIFO + conn_change signal + MAX_CONN */
+#define EV_COUNT (2 + CONFIG_BT_MAX_CONN)
+#endif /* CONFIG_BT_ISO */
+#else
+/* command FIFO */
+#define EV_COUNT 1
+#endif /* CONFIG_BT_CONN */
+
+static void hci_tx_thread(void)
+{
+    uint8_t i;
+    if(!net_buf_is_empty(&bt_dev.cmd_tx_queue))
+    {
+        // send one by one?
+    	if (bt_dev.sent_cmd) {
+            return;
+    	}
+        send_cmd();
+    }
+    if (IS_ENABLED(CONFIG_BT_CONN)) 
+    {
+        bt_conn_tx_polling();
+    }
+#if 0
+	static struct k_poll_event events[EV_COUNT] = {
+		K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+						K_POLL_MODE_NOTIFY_ONLY,
+						&bt_dev.cmd_tx_queue,
+						BT_EVENT_CMD_TX),
+	};
+
+	BT_DBG("Started");
+
+	while (1) {
+		int ev_count, err;
+
+		events[0].state = K_POLL_STATE_NOT_READY;
+		ev_count = 1;
+
+		if (IS_ENABLED(CONFIG_BT_CONN)) {
+			ev_count += bt_conn_prepare_events(&events[1]);
+		}
+
+		BT_DBG("Calling k_poll with %d events", ev_count);
+
+		err = k_poll(events, ev_count, K_FOREVER);
+		BT_ASSERT(err == 0);
+
+		process_events(events, ev_count);
+
+		/* Make sure we don't hog the CPU if there's all the time
+		 * some ready events.
+		 */
+		//k_yield();
+	}
+#endif
+}
+
+
+static void read_local_ver_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_read_local_version_info *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	bt_dev.hci_version = rp->hci_version;
+	bt_dev.hci_revision = sys_le16_to_cpu(rp->hci_revision);
+	bt_dev.lmp_version = rp->lmp_version;
+	bt_dev.lmp_subversion = sys_le16_to_cpu(rp->lmp_subversion);
+	bt_dev.manufacturer = sys_le16_to_cpu(rp->manufacturer);
+}
+
+static void read_le_features_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_le_read_local_features *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	memcpy(bt_dev.le.features, rp->features, sizeof(bt_dev.le.features));
+}
+
+#if defined(CONFIG_BT_BREDR)
+static void read_buffer_size_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data;
+	uint16_t pkts;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	bt_dev.br.mtu = sys_le16_to_cpu(rp->acl_max_len);
+	pkts = sys_le16_to_cpu(rp->acl_max_num);
+
+	BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.br.mtu);
+
+	k_sem_init(&bt_dev.br.pkts, pkts, pkts);
+}
+#elif defined(CONFIG_BT_CONN)
+static void read_buffer_size_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data;
+	uint16_t pkts;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	/* If LE-side has buffers we can ignore the BR/EDR values */
+	if (bt_dev.le.acl_mtu) {
+		return;
+	}
+
+	bt_dev.le.acl_mtu = sys_le16_to_cpu(rp->acl_max_len);
+	pkts = sys_le16_to_cpu(rp->acl_max_num);
+
+	BT_DBG("ACL BR/EDR buffers: pkts %u mtu %u", pkts, bt_dev.le.acl_mtu);
+
+	//k_sem_init(&bt_dev.le.acl_pkts, pkts, pkts);
+}
+#endif
+
+#if defined(CONFIG_BT_CONN)
+static void le_read_buffer_size_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_le_read_buffer_size *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	bt_dev.le.acl_mtu = sys_le16_to_cpu(rp->le_max_len);
+	if (!bt_dev.le.acl_mtu) {
+		return;
+	}
+
+	BT_DBG("ACL LE buffers: pkts %u mtu %u", rp->le_max_num,
+	       bt_dev.le.acl_mtu);
+
+	//k_sem_init(&bt_dev.le.acl_pkts, rp->le_max_num, rp->le_max_num);
+}
+
+static void read_buffer_size_v2_complete(struct net_buf *buf)
+{
+#if defined(CONFIG_BT_ISO)
+	struct bt_hci_rp_le_read_buffer_size_v2 *rp = (void *)buf->data;
+	uint8_t max_num;
+
+	BT_DBG("status %u", rp->status);
+
+	bt_dev.le.acl_mtu = sys_le16_to_cpu(rp->acl_mtu);
+	if (!bt_dev.le.acl_mtu) {
+		return;
+	}
+
+	BT_DBG("ACL LE buffers: pkts %u mtu %u", rp->acl_max_pkt,
+		bt_dev.le.acl_mtu);
+
+	max_num = MIN(rp->acl_max_pkt, CONFIG_BT_CONN_TX_MAX);
+	k_sem_init(&bt_dev.le.acl_pkts, max_num, max_num);
+
+	bt_dev.le.iso_mtu = sys_le16_to_cpu(rp->iso_mtu);
+	if (!bt_dev.le.iso_mtu) {
+		BT_ERR("ISO buffer size not set");
+		return;
+	}
+
+	BT_DBG("ISO buffers: pkts %u mtu %u", rp->iso_max_pkt,
+		bt_dev.le.iso_mtu);
+
+	max_num = MIN(rp->iso_max_pkt, CONFIG_BT_ISO_TX_BUF_COUNT);
+	k_sem_init(&bt_dev.le.iso_pkts, max_num, max_num);
+#endif /* CONFIG_BT_ISO */
+}
+
+static int le_set_host_feature(uint8_t bit_number, uint8_t bit_value)
+{
+#if defined(CONFIG_BT_ISO)
+	struct bt_hci_cp_le_set_host_feature *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_HOST_FEATURE, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->bit_number = bit_number;
+	cp->bit_value = bit_value;
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_HOST_FEATURE, buf, NULL);
+#else
+	return -ENOTSUP;
+#endif /* CONFIG_BT_ISO */
+}
+
+#endif /* CONFIG_BT_CONN */
+
+static void read_supported_commands_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_read_supported_commands *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	memcpy(bt_dev.supported_commands, rp->commands,
+	       sizeof(bt_dev.supported_commands));
+
+	/*
+	 * Report "LE Read Local P-256 Public Key" and "LE Generate DH Key" as
+	 * supported if TinyCrypt ECC is used for emulation.
+	 */
+	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
+		bt_dev.supported_commands[34] |= 0x02;
+		bt_dev.supported_commands[34] |= 0x04;
+	}
+}
+
+static void read_local_features_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_read_local_features *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	memcpy(bt_dev.features[0], rp->features, sizeof(bt_dev.features[0]));
+}
+
+static void le_read_supp_states_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_le_read_supp_states *rp = (void *)buf->data;
+
+	BT_DBG("status 0x%02x", rp->status);
+
+	bt_dev.le.states = sys_get_le64(rp->le_states);
+}
+
+#if defined(CONFIG_BT_SMP)
+static void le_read_resolving_list_size_complete(struct net_buf *buf)
+{
+	struct bt_hci_rp_le_read_rl_size *rp = (void *)buf->data;
+
+	BT_DBG("Resolving List size %u", rp->rl_size);
+
+	bt_dev.le.rl_size = rp->rl_size;
+}
+#endif /* defined(CONFIG_BT_SMP) */
+
+static int send_hci_cmd_with_init_process(int opcode, struct net_buf *buf)
+{
+	int err;
+
+    BT_INFO("send_hci_cmd_with_init_process, %x", opcode);
+
+	/* Read Local Supported Features */
+	err = bt_hci_cmd_send(opcode, buf);
+	if (err) {
+		return err;
+	}
+
+    return err;
+}
+
+void id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk);
+static void read_bd_addr_complete(struct net_buf *buf)
+{
+    bt_addr_le_t addr;
+    struct bt_hci_rp_read_bd_addr *rp;
+    uint8_t *irk = NULL;
+    rp = (void *)buf->data;
+    if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) ||
+        !bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) {
+        BT_DBG("Controller has no public address");
+        return;
+    }
+    bt_addr_copy(&addr.a, &rp->bdaddr);
+    addr.type = BT_ADDR_LE_PUBLIC;
+
+    bt_dev.id_count = 1;
+
+#if defined(CONFIG_BT_PRIVACY)
+    uint8_t ir_irk[16];
+    uint8_t ir[16];
+
+    bt_read_identity_root(ir);
+
+    if (!bt_smp_irk_get(ir, ir_irk)) {
+        irk = ir_irk;
+        } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+        atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID);
+    }
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+    id_create(BT_ID_DEFAULT, &addr, irk);
+}
+
+
+struct hci_command_complete_process_handler {
+	uint16_t opcode;
+	void (*handler)(struct net_buf *rsp);
+};
+
+#define HCI_COMMAND_COMPLETE_HANDLER(_opcode, _handler) \
+{ \
+	.opcode = _opcode, \
+	.handler = _handler, \
+}
+
+static const struct hci_command_complete_process_handler hci_cmd_cmp_handles[] = {
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_RESET
+        , hci_reset_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_READ_LOCAL_FEATURES
+        , read_local_features_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_READ_LOCAL_VERSION_INFO
+        , read_local_ver_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_READ_SUPPORTED_COMMANDS
+        , read_supported_commands_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_LE_READ_LOCAL_FEATURES
+        , read_le_features_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_READ_BD_ADDR
+        , read_bd_addr_complete),
+    HCI_COMMAND_COMPLETE_HANDLER(BT_HCI_OP_LE_READ_BUFFER_SIZE
+        , le_read_buffer_size_complete),
+        
+};
+    
+static inline void handle_hci_command_complete_work(uint16_t opcode, struct net_buf *buf,
+                const struct hci_command_complete_process_handler *handlers,
+                size_t num_handlers)
+{
+    size_t i;
+
+    for (i = 0; i < num_handlers; i++) {
+        const struct hci_command_complete_process_handler *handler = &handlers[i];
+
+        if (handler->opcode != opcode) {
+            continue;
+        }
+
+        handler->handler(buf);
+        return;
+    }
+
+    BT_WARN("Unhandled opcode 0x%02x, status: 0x%x", opcode, buf->data[0]);
+}
+
+void hci_init_process(int opcode, struct net_buf *rsp);
+static void hci_cmd_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_cmd_complete *evt;
+	uint8_t status, ncmd;
+	uint16_t opcode;
+
+	evt = net_buf_pull_mem(buf, sizeof(*evt));
+	ncmd = evt->ncmd;
+	opcode = sys_le16_to_cpu(evt->opcode);
+
+	BT_DBG("opcode 0x%04x", opcode);
+
+	/* All command return parameters have a 1-byte status in the
+	 * beginning, so we can safely make this generalization.
+	 */
+	status = buf->data[0];
+
+	hci_cmd_done(opcode, status, buf);
+
+	BT_DBG("222opcode 0x%04x", opcode);
+
+    handle_hci_command_complete_work(opcode, buf, hci_cmd_cmp_handles
+        , ARRAY_SIZE(hci_cmd_cmp_handles));
+
+	/* Allow next command to be sent */
+	//if (ncmd) {
+	//	k_sem_give(&bt_dev.ncmd_sem);
+	//}
+	hci_init_process(opcode, buf);
+}
+
+int gWorkInInitialWork = 0;
+int gWorkInInitialWorkProcess = 0;
+static int hci_le_init_process(int opcode)
+{
+    struct net_buf *buf;
+    struct bt_hci_cp_write_le_host_supp *cp_le;
+	int err;
+
+#if defined(CONFIG_BT_CONN)
+    if (IS_ENABLED(CONFIG_BT_ISO) &&
+        BT_FEAT_LE_ISO(bt_dev.le.features)) {
+        /* Set Isochronus Channels - Host support */
+        err = le_set_host_feature(BT_LE_FEAT_BIT_ISO_CHANNELS, 1);
+        if (err) {
+            return err;
+        }
+        /* Read ISO Buffer Size V2 */
+        err = bt_hci_cmd_send(BT_HCI_OP_LE_READ_BUFFER_SIZE_V2, NULL);
+        if (err) {
+            return err;
+        }
+        //read_buffer_size_v2_complete(rsp);
+        //net_buf_unref(rsp);
+    } else {
+        /* Read LE Buffer Size */
+        err = bt_hci_cmd_send(BT_HCI_OP_LE_READ_BUFFER_SIZE, NULL);
+        if (err) {
+            return err;
+        }
+    }
+#endif /* CONFIG_BT_CONN */
+
+    if(opcode == BT_HCI_OP_LE_READ_LOCAL_FEATURES)
+    {
+        if (BT_FEAT_BREDR(bt_dev.features)) {
+            buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP,
+                        sizeof(*cp_le));
+            if (!buf) {
+                return -ENOBUFS;
+            }
+
+            cp_le = net_buf_add(buf, sizeof(*cp_le));
+
+            /* Explicitly enable LE for dual-mode controllers */
+            cp_le->le = 0x01;
+            cp_le->simul = 0x00;
+            // here not need wait.
+            send_hci_cmd_with_init_process(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP
+                , buf);
+        }
+    }
+
+    le_set_event_mask();
+
+#if 0
+    /* Read LE Supported States */
+    if (BT_CMD_LE_STATES(bt_dev.supported_commands)) {
+        err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_SUPP_STATES, NULL,
+                       &rsp);
+        if (err) {
+            return err;
+        }
+
+        le_read_supp_states_complete(rsp);
+        net_buf_unref(rsp);
+    }
+
+    if (IS_ENABLED(CONFIG_BT_CONN) &&
+        IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
+        IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE) &&
+        BT_FEAT_LE_DLE(bt_dev.le.features)) {
+        struct bt_hci_cp_le_write_default_data_len *cp;
+        uint16_t tx_octets, tx_time;
+
+        err = hci_le_read_max_data_len(&tx_octets, &tx_time);
+        if (err) {
+            return err;
+        }
+
+        buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
+                    sizeof(*cp));
+        if (!buf) {
+            return -ENOBUFS;
+        }
+
+        cp = net_buf_add(buf, sizeof(*cp));
+        cp->max_tx_octets = sys_cpu_to_le16(tx_octets);
+        cp->max_tx_time = sys_cpu_to_le16(tx_time);
+
+        err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
+                       buf, NULL);
+        if (err) {
+            return err;
+        }
+    }
+
+#if defined(CONFIG_BT_SMP)
+    if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
+#if defined(CONFIG_BT_PRIVACY)
+        struct bt_hci_cp_le_set_rpa_timeout *cp;
+
+        buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT,
+                    sizeof(*cp));
+        if (!buf) {
+            return -ENOBUFS;
+        }
+
+        cp = net_buf_add(buf, sizeof(*cp));
+        cp->rpa_timeout = sys_cpu_to_le16(CONFIG_BT_RPA_TIMEOUT);
+        err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf,
+                       NULL);
+        if (err) {
+            return err;
+        }
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+        err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_RL_SIZE, NULL,
+                       &rsp);
+        if (err) {
+            return err;
+        }
+        le_read_resolving_list_size_complete(rsp);
+        net_buf_unref(rsp);
+    }
+#endif
+#endif
+
+le_init_process_end:
+    return 0;
+}
+static void hci_init_end(int err)
+{
+    BT_INFO("hci_init_end, work end.");
+    gWorkInInitialWork = 0;
+	if (IS_ENABLED(CONFIG_BT_CONN)) {
+		err = bt_conn_init();
+		if (err) {
+			return err;
+		}
+	}
+
+	bt_finalize_init();
+
+	if (ready_cb) {
+		ready_cb(err);
+	}
+}
+
+static void hci_init_process(int opcode, struct net_buf *rsp)
+{
+    if(!gWorkInInitialWork)
+    {
+        BT_INFO("hci_init_process, work error: 0x%04x",
+            opcode);
+        return;
+    }
+    switch(opcode)
+    {
+        case BT_HCI_OP_RESET:
+            send_hci_cmd_with_init_process(BT_HCI_OP_READ_LOCAL_FEATURES, NULL);
+            break;
+        case BT_HCI_OP_READ_LOCAL_FEATURES:
+            send_hci_cmd_with_init_process(BT_HCI_OP_READ_LOCAL_VERSION_INFO, NULL);
+            break;
+        case BT_HCI_OP_READ_LOCAL_VERSION_INFO:
+            send_hci_cmd_with_init_process(BT_HCI_OP_READ_SUPPORTED_COMMANDS, NULL);
+            break;
+        case BT_HCI_OP_READ_SUPPORTED_COMMANDS:
+            /* For now we only support LE capable controllers */
+            if (BT_FEAT_LE(bt_dev.features)) {
+                send_hci_cmd_with_init_process(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL);
+            }
+            break;
+        case BT_HCI_OP_LE_READ_LOCAL_FEATURES:
+            hci_le_init_process(opcode);
+            break;
+        
+        case BT_HCI_OP_LE_SET_EVENT_MASK:
+            set_event_mask();
+            break;
+
+        case BT_HCI_OP_SET_EVENT_MASK:
+            send_hci_cmd_with_init_process(BT_HCI_OP_READ_BD_ADDR, NULL);
+            break;
+
+        case BT_HCI_OP_READ_BD_ADDR:
+            hci_init_end(0);
+            break;
+        
+        default:
+            BT_WARN("hci_init_process, Unknown handle command: 0x%04x",
+                opcode);
+            break;
+    }
+    
+    
+}
+
+static int le_set_event_mask(void)
+{
+	struct bt_hci_cp_le_set_event_mask *cp_mask;
+	struct net_buf *buf;
+	uint64_t mask = 0U;
+
+	/* Set LE event mask */
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EVENT_MASK, sizeof(*cp_mask));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp_mask = net_buf_add(buf, sizeof(*cp_mask));
+
+	mask |= BT_EVT_MASK_LE_ADVERTISING_REPORT;
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		mask |= BT_EVT_MASK_LE_ADV_SET_TERMINATED;
+		mask |= BT_EVT_MASK_LE_SCAN_REQ_RECEIVED;
+		mask |= BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT;
+		mask |= BT_EVT_MASK_LE_SCAN_TIMEOUT;
+		if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC)) {
+			mask |= BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED;
+			mask |= BT_EVT_MASK_LE_PER_ADVERTISING_REPORT;
+			mask |= BT_EVT_MASK_LE_PER_ADV_SYNC_LOST;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN)) {
+		if ((IS_ENABLED(CONFIG_BT_SMP) &&
+		     BT_FEAT_LE_PRIVACY(bt_dev.le.features)) ||
+		    (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+		     BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+			/* C24:
+			 * Mandatory if the LE Controller supports Connection
+			 * State and either LE Feature (LL Privacy) or
+			 * LE Feature (Extended Advertising) is supported, ...
+			 */
+			mask |= BT_EVT_MASK_LE_ENH_CONN_COMPLETE;
+		} else {
+			mask |= BT_EVT_MASK_LE_CONN_COMPLETE;
+		}
+
+		mask |= BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE;
+		mask |= BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE;
+
+		if (BT_FEAT_LE_CONN_PARAM_REQ_PROC(bt_dev.le.features)) {
+			mask |= BT_EVT_MASK_LE_CONN_PARAM_REQ;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
+		    BT_FEAT_LE_DLE(bt_dev.le.features)) {
+			mask |= BT_EVT_MASK_LE_DATA_LEN_CHANGE;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_PHY_UPDATE) &&
+		    (BT_FEAT_LE_PHY_2M(bt_dev.le.features) ||
+		     BT_FEAT_LE_PHY_CODED(bt_dev.le.features))) {
+			mask |= BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) &&
+	    BT_FEAT_LE_ENCR(bt_dev.le.features)) {
+		mask |= BT_EVT_MASK_LE_LTK_REQUEST;
+	}
+
+	/*
+	 * If "LE Read Local P-256 Public Key" and "LE Generate DH Key" are
+	 * supported we need to enable events generated by those commands.
+	 */
+	if (IS_ENABLED(CONFIG_BT_ECC) &&
+	    (BT_CMD_TEST(bt_dev.supported_commands, 34, 1)) &&
+	    (BT_CMD_TEST(bt_dev.supported_commands, 34, 2))) {
+		mask |= BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE;
+		mask |= BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE;
+	}
+
+	/*
+	 * Enable CIS events only if ISO connections are enabled and controller
+	 * support them.
+	 */
+	if (IS_ENABLED(CONFIG_BT_ISO) &&
+	    BT_FEAT_LE_CIS(bt_dev.le.features)) {
+		mask |= BT_EVT_MASK_LE_CIS_ESTABLISHED;
+		if (BT_FEAT_LE_CIS_SLAVE(bt_dev.le.features)) {
+			mask |= BT_EVT_MASK_LE_CIS_REQ;
+		}
+	}
+	BT_ERR("le_set_event_mask, mask: 0x%x.", mask);
+
+	sys_put_le64(mask, cp_mask->events);
+	return send_hci_cmd_with_init_process(BT_HCI_OP_LE_SET_EVENT_MASK, buf);
+}
+
+static int le_init(void)
+{
+	struct bt_hci_cp_write_le_host_supp *cp_le;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	/* For now we only support LE capable controllers */
+	if (!BT_FEAT_LE(bt_dev.features)) {
+		BT_ERR("Non-LE capable controller detected!");
+		return -ENODEV;
+	}
+
+	/* Read Low Energy Supported Features */
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_LOCAL_FEATURES, NULL,
+				   &rsp);
+	if (err) {
+		return err;
+	}
+
+	read_le_features_complete(rsp);
+	net_buf_unref(rsp);
+
+#if defined(CONFIG_BT_CONN)
+	if (IS_ENABLED(CONFIG_BT_ISO) &&
+	    BT_FEAT_LE_ISO(bt_dev.le.features)) {
+		/* Set Isochronus Channels - Host support */
+		err = le_set_host_feature(BT_LE_FEAT_BIT_ISO_CHANNELS, 1);
+		if (err) {
+			return err;
+		}
+		/* Read ISO Buffer Size V2 */
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE_V2,
+					   NULL, &rsp);
+		if (err) {
+			return err;
+		}
+		read_buffer_size_v2_complete(rsp);
+		net_buf_unref(rsp);
+	} else {
+		/* Read LE Buffer Size */
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE,
+					   NULL, &rsp);
+		if (err) {
+			return err;
+		}
+		le_read_buffer_size_complete(rsp);
+		net_buf_unref(rsp);
+	}
+#endif /* CONFIG_BT_CONN */
+
+	if (BT_FEAT_BREDR(bt_dev.features)) {
+		buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP,
+					sizeof(*cp_le));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		cp_le = net_buf_add(buf, sizeof(*cp_le));
+
+		/* Explicitly enable LE for dual-mode controllers */
+		cp_le->le = 0x01;
+		cp_le->simul = 0x00;
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, buf,
+					   NULL);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* Read LE Supported States */
+	if (BT_CMD_LE_STATES(bt_dev.supported_commands)) {
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_SUPP_STATES, NULL,
+					   &rsp);
+		if (err) {
+			return err;
+		}
+
+		le_read_supp_states_complete(rsp);
+		net_buf_unref(rsp);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN) &&
+	    IS_ENABLED(CONFIG_BT_DATA_LEN_UPDATE) &&
+	    IS_ENABLED(CONFIG_BT_AUTO_DATA_LEN_UPDATE) &&
+	    BT_FEAT_LE_DLE(bt_dev.le.features)) {
+		struct bt_hci_cp_le_write_default_data_len *cp;
+		uint16_t tx_octets, tx_time;
+
+		err = hci_le_read_max_data_len(&tx_octets, &tx_time);
+		if (err) {
+			return err;
+		}
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
+					sizeof(*cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->max_tx_octets = sys_cpu_to_le16(tx_octets);
+		cp->max_tx_time = sys_cpu_to_le16(tx_time);
+
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN,
+					   buf, NULL);
+		if (err) {
+			return err;
+		}
+	}
+
+#if defined(CONFIG_BT_SMP)
+	if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
+#if defined(CONFIG_BT_PRIVACY)
+		struct bt_hci_cp_le_set_rpa_timeout *cp;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT,
+					sizeof(*cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->rpa_timeout = sys_cpu_to_le16(CONFIG_BT_RPA_TIMEOUT);
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RPA_TIMEOUT, buf,
+					   NULL);
+		if (err) {
+			return err;
+		}
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_RL_SIZE, NULL,
+					   &rsp);
+		if (err) {
+			return err;
+		}
+		le_read_resolving_list_size_complete(rsp);
+		net_buf_unref(rsp);
+	}
+#endif
+
+	return  le_set_event_mask();
+}
+
+#if defined(CONFIG_BT_BREDR)
+static int read_ext_features(void)
+{
+	int i;
+
+	/* Read Local Supported Extended Features */
+	for (i = 1; i < LMP_FEAT_PAGES_COUNT; i++) {
+		struct bt_hci_cp_read_local_ext_features *cp;
+		struct bt_hci_rp_read_local_ext_features *rp;
+		struct net_buf *buf, *rsp;
+		int err;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_READ_LOCAL_EXT_FEATURES,
+					sizeof(*cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->page = i;
+
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_LOCAL_EXT_FEATURES,
+					   buf, &rsp);
+		if (err) {
+			return err;
+		}
+
+		rp = (void *)rsp->data;
+
+		memcpy(&bt_dev.features[i], rp->ext_features,
+		       sizeof(bt_dev.features[i]));
+
+		if (rp->max_page <= i) {
+			net_buf_unref(rsp);
+			break;
+		}
+
+		net_buf_unref(rsp);
+	}
+
+	return 0;
+}
+
+void device_supported_pkt_type(void)
+{
+	/* Device supported features and sco packet types */
+	if (BT_FEAT_HV2_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV2);
+	}
+
+	if (BT_FEAT_HV3_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_HV3);
+	}
+
+	if (BT_FEAT_LMP_ESCO_CAPABLE(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV3);
+	}
+
+	if (BT_FEAT_EV4_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV4);
+	}
+
+	if (BT_FEAT_EV5_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_EV5);
+	}
+
+	if (BT_FEAT_2EV3_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV3);
+	}
+
+	if (BT_FEAT_3EV3_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_3EV3);
+	}
+
+	if (BT_FEAT_3SLOT_PKT(bt_dev.features)) {
+		bt_dev.br.esco_pkt_type |= (HCI_PKT_TYPE_ESCO_2EV5 |
+					    HCI_PKT_TYPE_ESCO_3EV5);
+	}
+}
+
+static int br_init(void)
+{
+	struct net_buf *buf;
+	struct bt_hci_cp_write_ssp_mode *ssp_cp;
+	struct bt_hci_cp_write_inquiry_mode *inq_cp;
+	struct bt_hci_write_local_name *name_cp;
+	int err;
+
+	/* Read extended local features */
+	if (BT_FEAT_EXT_FEATURES(bt_dev.features)) {
+		err = read_ext_features();
+		if (err) {
+			return err;
+		}
+	}
+
+	/* Add local supported packet types to bt_dev */
+	device_supported_pkt_type();
+
+	/* Get BR/EDR buffer size */
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &buf);
+	if (err) {
+		return err;
+	}
+
+	read_buffer_size_complete(buf);
+	net_buf_unref(buf);
+
+	/* Set SSP mode */
+	buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SSP_MODE, sizeof(*ssp_cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	ssp_cp = net_buf_add(buf, sizeof(*ssp_cp));
+	ssp_cp->mode = 0x01;
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SSP_MODE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	/* Enable Inquiry results with RSSI or extended Inquiry */
+	buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_INQUIRY_MODE, sizeof(*inq_cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	inq_cp = net_buf_add(buf, sizeof(*inq_cp));
+	inq_cp->mode = 0x02;
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_INQUIRY_MODE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	/* Set local name */
+	buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_LOCAL_NAME, sizeof(*name_cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	name_cp = net_buf_add(buf, sizeof(*name_cp));
+	strncpy((char *)name_cp->local_name, CONFIG_BT_DEVICE_NAME,
+		sizeof(name_cp->local_name));
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_LOCAL_NAME, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	/* Set page timeout*/
+	buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_PAGE_TIMEOUT, sizeof(uint16_t));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_le16(buf, CONFIG_BT_PAGE_TIMEOUT);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_PAGE_TIMEOUT, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	/* Enable BR/EDR SC if supported */
+	if (BT_FEAT_SC(bt_dev.features)) {
+		struct bt_hci_cp_write_sc_host_supp *sc_cp;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SC_HOST_SUPP,
+					sizeof(*sc_cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		sc_cp = net_buf_add(buf, sizeof(*sc_cp));
+		sc_cp->sc_support = 0x01;
+
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SC_HOST_SUPP, buf,
+					   NULL);
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+#else
+static int br_init(void)
+{
+#if defined(CONFIG_BT_CONN)
+	struct net_buf *rsp;
+	int err;
+
+	if (bt_dev.le.acl_mtu) {
+		return 0;
+	}
+
+	/* Use BR/EDR buffer size if LE reports zero buffers */
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BUFFER_SIZE, NULL, &rsp);
+	if (err) {
+		return err;
+	}
+
+	read_buffer_size_complete(rsp);
+	net_buf_unref(rsp);
+#endif /* CONFIG_BT_CONN */
+
+	return 0;
+}
+#endif
+
+static int set_event_mask(void)
+{
+	struct bt_hci_cp_set_event_mask *ev;
+	struct net_buf *buf;
+	uint64_t mask = 0U;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_SET_EVENT_MASK, sizeof(*ev));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	ev = net_buf_add(buf, sizeof(*ev));
+
+	if (IS_ENABLED(CONFIG_BT_BREDR)) {
+		/* Since we require LE support, we can count on a
+		 * Bluetooth 4.0 feature set
+		 */
+		mask |= BT_EVT_MASK_INQUIRY_COMPLETE;
+		mask |= BT_EVT_MASK_CONN_COMPLETE;
+		mask |= BT_EVT_MASK_CONN_REQUEST;
+		mask |= BT_EVT_MASK_AUTH_COMPLETE;
+		mask |= BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE;
+		mask |= BT_EVT_MASK_REMOTE_FEATURES;
+		mask |= BT_EVT_MASK_ROLE_CHANGE;
+		mask |= BT_EVT_MASK_PIN_CODE_REQ;
+		mask |= BT_EVT_MASK_LINK_KEY_REQ;
+		mask |= BT_EVT_MASK_LINK_KEY_NOTIFY;
+		mask |= BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI;
+		mask |= BT_EVT_MASK_REMOTE_EXT_FEATURES;
+		mask |= BT_EVT_MASK_SYNC_CONN_COMPLETE;
+		mask |= BT_EVT_MASK_EXTENDED_INQUIRY_RESULT;
+		mask |= BT_EVT_MASK_IO_CAPA_REQ;
+		mask |= BT_EVT_MASK_IO_CAPA_RESP;
+		mask |= BT_EVT_MASK_USER_CONFIRM_REQ;
+		mask |= BT_EVT_MASK_USER_PASSKEY_REQ;
+		mask |= BT_EVT_MASK_SSP_COMPLETE;
+		mask |= BT_EVT_MASK_USER_PASSKEY_NOTIFY;
+	}
+
+	mask |= BT_EVT_MASK_HARDWARE_ERROR;
+	mask |= BT_EVT_MASK_DATA_BUFFER_OVERFLOW;
+	mask |= BT_EVT_MASK_LE_META_EVENT;
+
+	if (IS_ENABLED(CONFIG_BT_CONN)) {
+		mask |= BT_EVT_MASK_DISCONN_COMPLETE;
+		mask |= BT_EVT_MASK_REMOTE_VERSION_INFO;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP) &&
+	    BT_FEAT_LE_ENCR(bt_dev.le.features)) {
+		mask |= BT_EVT_MASK_ENCRYPT_CHANGE;
+		mask |= BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE;
+	}
+
+	sys_put_le64(mask, ev->events);
+        
+    return send_hci_cmd_with_init_process(BT_HCI_OP_SET_EVENT_MASK, buf);
+}
+
+static inline int create_random_addr(bt_addr_le_t *addr)
+{
+	addr->type = BT_ADDR_LE_RANDOM;
+
+	return bt_rand(addr->a.val, 6);
+}
+
+int bt_addr_le_create_nrpa(bt_addr_le_t *addr)
+{
+	int err;
+
+	err = create_random_addr(addr);
+	if (err) {
+		return err;
+	}
+
+	BT_ADDR_SET_NRPA(&addr->a);
+
+	return 0;
+}
+
+int bt_addr_le_create_static(bt_addr_le_t *addr)
+{
+	int err;
+
+	err = create_random_addr(addr);
+	if (err) {
+		return err;
+	}
+
+	BT_ADDR_SET_STATIC(&addr->a);
+
+	return 0;
+}
+
+static uint8_t bt_read_public_addr(bt_addr_le_t *addr)
+{
+	struct bt_hci_rp_read_bd_addr *rp;
+	struct net_buf *rsp;
+	int err;
+
+	/* Read Bluetooth Address */
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_BD_ADDR, NULL, &rsp);
+	if (err) {
+		BT_WARN("Failed to read public address");
+		return 0U;
+	}
+
+	rp = (void *)rsp->data;
+
+	if (!bt_addr_cmp(&rp->bdaddr, BT_ADDR_ANY) ||
+	    !bt_addr_cmp(&rp->bdaddr, BT_ADDR_NONE)) {
+		BT_DBG("Controller has no public address");
+		net_buf_unref(rsp);
+		return 0U;
+	}
+
+	bt_addr_copy(&addr->a, &rp->bdaddr);
+	addr->type = BT_ADDR_LE_PUBLIC;
+
+	net_buf_unref(rsp);
+	return 1U;
+}
+
+#if defined(CONFIG_BT_DEBUG)
+static const char *ver_str(uint8_t ver)
+{
+	const char * const str[] = {
+		"1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2",
+		"5.0", "5.1", "5.2"
+	};
+
+	if (ver < ARRAY_SIZE(str)) {
+		return str[ver];
+	}
+
+	return "unknown";
+}
+
+static void bt_dev_show_info(void)
+{
+	int i;
+
+	BT_INFO("Identity%s: %s", bt_dev.id_count > 1 ? "[0]" : "",
+		bt_addr_le_str(&bt_dev.id_addr[0]));
+
+	for (i = 1; i < bt_dev.id_count; i++) {
+		BT_INFO("Identity[%d]: %s",
+			i, bt_addr_le_str(&bt_dev.id_addr[i]));
+	}
+
+	BT_INFO("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x",
+		ver_str(bt_dev.hci_version), bt_dev.hci_version,
+		bt_dev.hci_revision, bt_dev.manufacturer);
+	BT_INFO("LMP: version %s (0x%02x) subver 0x%04x",
+		ver_str(bt_dev.lmp_version), bt_dev.lmp_version,
+		bt_dev.lmp_subversion);
+}
+#else
+static inline void bt_dev_show_info(void)
+{
+}
+#endif /* CONFIG_BT_DEBUG */
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+#if defined(CONFIG_BT_DEBUG)
+static const char *vs_hw_platform(uint16_t platform)
+{
+	static const char * const plat_str[] = {
+		"reserved", "Intel Corporation", "Nordic Semiconductor",
+		"NXP Semiconductors" };
+
+	if (platform < ARRAY_SIZE(plat_str)) {
+		return plat_str[platform];
+	}
+
+	return "unknown";
+}
+
+static const char *vs_hw_variant(uint16_t platform, uint16_t variant)
+{
+	static const char * const nordic_str[] = {
+		"reserved", "nRF51x", "nRF52x", "nRF53x"
+	};
+
+	if (platform != BT_HCI_VS_HW_PLAT_NORDIC) {
+		return "unknown";
+	}
+
+	if (variant < ARRAY_SIZE(nordic_str)) {
+		return nordic_str[variant];
+	}
+
+	return "unknown";
+}
+
+static const char *vs_fw_variant(uint8_t variant)
+{
+	static const char * const var_str[] = {
+		"Standard Bluetooth controller",
+		"Vendor specific controller",
+		"Firmware loader",
+		"Rescue image",
+	};
+
+	if (variant < ARRAY_SIZE(var_str)) {
+		return var_str[variant];
+	}
+
+	return "unknown";
+}
+#endif /* CONFIG_BT_DEBUG */
+
+static void hci_vs_init(void)
+{
+	union {
+		struct bt_hci_rp_vs_read_version_info *info;
+		struct bt_hci_rp_vs_read_supported_commands *cmds;
+		struct bt_hci_rp_vs_read_supported_features *feat;
+	} rp;
+	struct net_buf *rsp;
+	int err;
+
+	/* If heuristics is enabled, try to guess HCI VS support by looking
+	 * at the HCI version and identity address. We haven't set any addresses
+	 * at this point. So we need to read the public address.
+	 */
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT)) {
+		bt_addr_le_t addr;
+
+		if ((bt_dev.hci_version < BT_HCI_VERSION_5_0) ||
+		    bt_read_public_addr(&addr)) {
+			BT_WARN("Controller doesn't seem to support "
+				"Zephyr vendor HCI");
+			return;
+		}
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_VERSION_INFO, NULL, &rsp);
+	if (err) {
+		BT_WARN("Vendor HCI extensions not available");
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+	    rsp->len != sizeof(struct bt_hci_rp_vs_read_version_info)) {
+		BT_WARN("Invalid Vendor HCI extensions");
+		net_buf_unref(rsp);
+		return;
+	}
+
+#if defined(CONFIG_BT_DEBUG)
+	rp.info = (void *)rsp->data;
+	BT_INFO("HW Platform: %s (0x%04x)",
+		vs_hw_platform(sys_le16_to_cpu(rp.info->hw_platform)),
+		sys_le16_to_cpu(rp.info->hw_platform));
+	BT_INFO("HW Variant: %s (0x%04x)",
+		vs_hw_variant(sys_le16_to_cpu(rp.info->hw_platform),
+			      sys_le16_to_cpu(rp.info->hw_variant)),
+		sys_le16_to_cpu(rp.info->hw_variant));
+	BT_INFO("Firmware: %s (0x%02x) Version %u.%u Build %u",
+		vs_fw_variant(rp.info->fw_variant), rp.info->fw_variant,
+		rp.info->fw_version, sys_le16_to_cpu(rp.info->fw_revision),
+		sys_le32_to_cpu(rp.info->fw_build));
+#endif /* CONFIG_BT_DEBUG */
+
+	net_buf_unref(rsp);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_SUPPORTED_COMMANDS,
+				   NULL, &rsp);
+	if (err) {
+		BT_WARN("Failed to read supported vendor commands");
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+	    rsp->len != sizeof(struct bt_hci_rp_vs_read_supported_commands)) {
+		BT_WARN("Invalid Vendor HCI extensions");
+		net_buf_unref(rsp);
+		return;
+	}
+
+	rp.cmds = (void *)rsp->data;
+	memcpy(bt_dev.vs_commands, rp.cmds->commands, BT_DEV_VS_CMDS_MAX);
+	net_buf_unref(rsp);
+
+	if (BT_VS_CMD_SUP_FEAT(bt_dev.vs_commands)) {
+		err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_SUPPORTED_FEATURES,
+					   NULL, &rsp);
+		if (err) {
+			BT_WARN("Failed to read supported vendor features");
+			return;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+		    rsp->len !=
+		    sizeof(struct bt_hci_rp_vs_read_supported_features)) {
+			BT_WARN("Invalid Vendor HCI extensions");
+			net_buf_unref(rsp);
+			return;
+		}
+
+		rp.feat = (void *)rsp->data;
+		memcpy(bt_dev.vs_features, rp.feat->features,
+		       BT_DEV_VS_FEAT_MAX);
+		net_buf_unref(rsp);
+	}
+}
+#endif /* CONFIG_BT_HCI_VS_EXT */
+
+static int hci_init(void)
+{
+	int err;
+    
+    BT_INFO("hci_init");
+
+    gWorkInInitialWork = 1;
+
+	if (!(bt_dev.drv->quirks & BT_QUIRK_NO_RESET)) {
+		/* Send HCI_RESET */
+		err = send_hci_cmd_with_init_process(BT_HCI_OP_RESET, NULL);
+	}
+
+	return 0;
+#if 0
+	err = common_init();
+	if (err) {
+		return err;
+	}
+
+	err = le_init();
+	if (err) {
+		return err;
+	}
+
+	if (BT_FEAT_BREDR(bt_dev.features)) {
+		err = br_init();
+		if (err) {
+			return err;
+		}
+	} else if (IS_ENABLED(CONFIG_BT_BREDR)) {
+		BT_ERR("Non-BR/EDR controller detected");
+		return -EIO;
+	}
+
+	err = set_event_mask();
+	if (err) {
+		return err;
+	}
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+	hci_vs_init();
+#endif
+	if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) {
+		BT_DBG("No user identity. Trying to set public.");
+
+		bt_setup_public_id_addr();
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_SETTINGS) && !bt_dev.id_count) {
+		BT_DBG("No public address. Trying to set static random.");
+
+		err = bt_setup_random_id_addr();
+		if (err) {
+			BT_ERR("Unable to set identity address");
+			return err;
+		}
+
+		/* The passive scanner just sends a dummy address type in the
+		 * command. If the first activity does this, and the dummy type
+		 * is a random address, it needs a valid value, even though it's
+		 * not actually used.
+		 */
+		err = set_random_address(&bt_dev.id_addr[0].a);
+		if (err) {
+			BT_ERR("Unable to set random address");
+			return err;
+		}
+	}
+#endif
+	return 0;
+}
+
+int bt_send(struct net_buf *buf)
+{
+	BT_DBG("buf %p len %u type %u", buf, buf->len, bt_buf_get_type(buf));
+
+	bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
+
+	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
+		return bt_hci_ecc_send(buf);
+	}
+
+	return bt_dev.drv->send(buf);
+}
+
+static const struct event_handler prio_events[] = {
+	EVENT_HANDLER(BT_HCI_EVT_CMD_COMPLETE, hci_cmd_complete,
+		      sizeof(struct bt_hci_evt_cmd_complete)),
+	EVENT_HANDLER(BT_HCI_EVT_CMD_STATUS, hci_cmd_status,
+		      sizeof(struct bt_hci_evt_cmd_status)),
+#if defined(CONFIG_BT_CONN)
+	EVENT_HANDLER(BT_HCI_EVT_DATA_BUF_OVERFLOW,
+		      hci_data_buf_overflow,
+		      sizeof(struct bt_hci_evt_data_buf_overflow)),
+	EVENT_HANDLER(BT_HCI_EVT_NUM_COMPLETED_PACKETS,
+		      hci_num_completed_packets,
+		      sizeof(struct bt_hci_evt_num_completed_packets)),
+	EVENT_HANDLER(BT_HCI_EVT_DISCONN_COMPLETE, hci_disconn_complete_prio,
+		      sizeof(struct bt_hci_evt_disconn_complete)),
+
+#endif /* CONFIG_BT_CONN */
+};
+
+void hci_event_prio(struct net_buf *buf)
+{
+	struct net_buf_simple_state state;
+	struct bt_hci_evt_hdr *hdr;
+	uint8_t evt_flags;
+
+	net_buf_simple_save(&buf->b, &state);
+
+	BT_ASSERT(buf->len >= sizeof(*hdr));
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	evt_flags = bt_hci_evt_get_flags(hdr->evt);
+	BT_ASSERT(evt_flags & BT_HCI_EVT_FLAG_RECV_PRIO);
+
+	handle_event(hdr->evt, buf, prio_events, ARRAY_SIZE(prio_events));
+
+	if (evt_flags & BT_HCI_EVT_FLAG_RECV) {
+		net_buf_simple_restore(&buf->b, &state);
+	} else {
+		net_buf_unref(buf);
+	}
+}
+
+int bt_recv(struct net_buf *buf)
+{
+	bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
+    
+    struct bt_hci_evt_hdr *hdr = (void *)buf->data;
+    uint8_t evt_flags = bt_hci_evt_get_flags(hdr->evt);
+
+	BT_DBG("bt_recv, evt: 0x%x, evt_flags: 0x%x, buf %p len %u pool %x", hdr->evt, evt_flags, buf, buf->len, buf->pool_id);
+    
+    if (evt_flags & BT_HCI_EVT_FLAG_RECV_PRIO) {
+        hci_event_prio(buf);
+    }
+    
+    if (evt_flags & BT_HCI_EVT_FLAG_RECV) {
+        net_buf_put(&bt_dev.rx_queue, buf);
+    }
+}
+
+#if defined(CONFIG_BT_RECV_IS_RX_THREAD)
+int bt_recv_prio(struct net_buf *buf)
+{
+	bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
+
+	BT_ASSERT(bt_buf_get_type(buf) == BT_BUF_EVT);
+
+	hci_event_prio(buf);
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_RECV_IS_RX_THREAD) */
+
+int bt_hci_driver_register(const struct bt_hci_driver *drv)
+{
+	if (bt_dev.drv) {
+		return -EALREADY;
+	}
+
+	if (!drv->open || !drv->send) {
+		return -EINVAL;
+	}
+
+	bt_dev.drv = drv;
+
+	BT_DBG("Registered %s", drv->name ? drv->name : "");
+
+	bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, drv->bus,
+			     BT_ADDR_ANY, drv->name ? drv->name : "bt0");
+
+	return 0;
+}
+
+void bt_finalize_init(void)
+{
+    BT_INFO("bt_finalize_init.");
+	atomic_set_bit(bt_dev.flags, BT_DEV_READY);
+
+	if (IS_ENABLED(CONFIG_BT_OBSERVER)) {
+		bt_le_scan_update(false);
+	}
+
+	bt_dev_show_info();
+}
+
+static int bt_init(void)
+{
+	int err;
+
+	err = hci_init();
+	if (err) {
+		return err;
+	}
+#if 0
+	if (IS_ENABLED(CONFIG_BT_CONN)) {
+		err = bt_conn_init();
+		if (err) {
+			return err;
+		}
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	k_delayed_work_init(&bt_dev.rpa_update, rpa_timeout);
+#endif
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		if (!bt_dev.id_count) {
+			BT_INFO("No ID address. App must call settings_load()");
+			return 0;
+		}
+
+		atomic_set_bit(bt_dev.flags, BT_DEV_PRESET_ID);
+	}
+
+	bt_finalize_init();
+#endif
+	return 0;
+}
+
+static void init_work(struct k_work *work)
+{
+	int err;
+
+	err = bt_init();
+	if (ready_cb) {
+		ready_cb(err);
+	}
+}
+
+static void hci_rx_thread(void)
+{
+	struct net_buf *buf;
+    if(net_buf_is_empty(&bt_dev.rx_queue))
+    {
+        return;
+    }
+    
+    BT_DBG("calling fifo_get_wait");
+    buf = net_buf_get(&bt_dev.rx_queue, K_FOREVER);
+    BT_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf),
+           buf->len);
+
+    switch (bt_buf_get_type(buf)) {
+#if defined(CONFIG_BT_CONN)
+    case BT_BUF_ACL_IN:
+        hci_acl(buf);
+        break;
+#endif /* CONFIG_BT_CONN */
+#if defined(CONFIG_BT_ISO)
+    case BT_BUF_ISO_IN:
+        hci_iso(buf);
+        break;
+#endif /* CONFIG_BT_ISO */
+    case BT_BUF_EVT:
+        hci_event(buf);
+        break;
+    default:
+        BT_ERR("Unknown buf type %u", bt_buf_get_type(buf));
+        net_buf_unref(buf);
+        break;
+    }
+
+}
+
+int bt_polling_work(void)
+{
+    hci_tx_thread();
+    hci_rx_thread();
+}
+
+int bt_enable(bt_ready_cb_t cb)
+{
+	int err;
+    
+    BT_ERR("bt_enable");
+
+	if (!bt_dev.drv) {
+		BT_ERR("No HCI driver registered");
+		return -ENODEV;
+	}
+
+	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_ENABLE)) {
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		err = bt_settings_init();
+		if (err) {
+			return err;
+		}
+	} else {
+		bt_set_name(CONFIG_BT_DEVICE_NAME);
+	}
+
+	ready_cb = cb;
+
+	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
+		bt_hci_ecc_init();
+	}
+
+	err = bt_dev.drv->open();
+	if (err) {
+		BT_ERR("HCI driver open failed (%d)", err);
+		return err;
+	}
+
+    bt_init();
+/*
+	if (!cb) {
+		return bt_init();
+	}
+
+	return 0;
+	*/
+}
+
+struct bt_ad {
+	const struct bt_data *data;
+	size_t len;
+};
+
+static int set_data_add(uint8_t *set_data, uint8_t set_data_len_max,
+			const struct bt_ad *ad, size_t ad_len, uint8_t *data_len)
+{
+	uint8_t set_data_len = 0;
+
+	for (size_t i = 0; i < ad_len; i++) {
+		const struct bt_data *data = ad[i].data;
+
+		for (size_t j = 0; j < ad[i].len; j++) {
+			size_t len = data[j].data_len;
+			uint8_t type = data[j].type;
+
+			/* Check if ad fit in the remaining buffer */
+			if ((set_data_len + len + 2) > set_data_len_max) {
+				ssize_t shortened_len = set_data_len_max -
+							(set_data_len + 2);
+
+				if (!(type == BT_DATA_NAME_COMPLETE &&
+				      shortened_len > 0)) {
+					BT_ERR("Too big advertising data");
+					return -EINVAL;
+				}
+
+				type = BT_DATA_NAME_SHORTENED;
+				len = shortened_len;
+			}
+
+			set_data[set_data_len++] = len + 1;
+			set_data[set_data_len++] = type;
+
+			memcpy(&set_data[set_data_len], data[j].data, len);
+			set_data_len += len;
+		}
+	}
+
+	*data_len = set_data_len;
+	return 0;
+}
+
+static int hci_set_ad(uint16_t hci_op, const struct bt_ad *ad, size_t ad_len)
+{
+	struct bt_hci_cp_le_set_adv_data *set_data;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(hci_op, sizeof(*set_data));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	set_data = net_buf_add(buf, sizeof(*set_data));
+	(void)memset(set_data, 0, sizeof(*set_data));
+
+	err = set_data_add(set_data->data, BT_GAP_ADV_MAX_ADV_DATA_LEN,
+			   ad, ad_len, &set_data->len);
+	if (err) {
+		net_buf_unref(buf);
+		return err;
+	}
+
+	return bt_hci_cmd_send(hci_op, buf);
+}
+
+/* Set legacy data using Extended Advertising HCI commands */
+static int hci_set_ad_ext(struct bt_le_ext_adv *adv, uint16_t hci_op,
+			  const struct bt_ad *ad, size_t ad_len)
+{
+	struct bt_hci_cp_le_set_ext_adv_data *set_data;
+	struct net_buf *buf;
+	int err;
+
+	buf = bt_hci_cmd_create(hci_op, sizeof(*set_data));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	set_data = net_buf_add(buf, sizeof(*set_data));
+	(void)memset(set_data, 0, sizeof(*set_data));
+
+	err = set_data_add(set_data->data, BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN,
+			   ad, ad_len, &set_data->len);
+	if (err) {
+		net_buf_unref(buf);
+		return err;
+	}
+
+	set_data->handle = adv->handle;
+	set_data->op = BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA;
+	set_data->frag_pref = BT_HCI_LE_EXT_ADV_FRAG_DISABLED;
+
+	return bt_hci_cmd_send_sync(hci_op, buf, NULL);
+}
+
+static int set_ad(struct bt_le_ext_adv *adv, const struct bt_ad *ad,
+		  size_t ad_len)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return hci_set_ad_ext(adv, BT_HCI_OP_LE_SET_EXT_ADV_DATA,
+				      ad, ad_len);
+	}
+
+	return hci_set_ad(BT_HCI_OP_LE_SET_ADV_DATA, ad, ad_len);
+}
+
+static int set_sd(struct bt_le_ext_adv *adv, const struct bt_ad *sd,
+		  size_t sd_len)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return hci_set_ad_ext(adv, BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
+				      sd, sd_len);
+	}
+
+	return hci_set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, sd, sd_len);
+}
+
+int bt_set_name(const char *name)
+{
+#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
+	struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+	size_t len = strlen(name);
+	int err;
+
+	if (len > CONFIG_BT_DEVICE_NAME_MAX) {
+		return -ENOMEM;
+	}
+
+	if (!strcmp(bt_dev.name, name)) {
+		return 0;
+	}
+
+	strncpy(bt_dev.name, name, len);
+	bt_dev.name[len] = '\0';
+
+	/* Update advertising name if in use */
+	if (adv && atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME)) {
+		struct bt_data data[] = { BT_DATA(BT_DATA_NAME_COMPLETE, name,
+						len) };
+		struct bt_ad sd = { data, ARRAY_SIZE(data) };
+
+		set_sd(adv, &sd, 1);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		err = settings_save_one("bt/name", bt_dev.name, len);
+		if (err) {
+			BT_WARN("Unable to store name");
+		}
+	}
+
+	return 0;
+#else
+	return -ENOMEM;
+#endif
+}
+
+const char *bt_get_name(void)
+{
+#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
+	return bt_dev.name;
+#else
+	return CONFIG_BT_DEVICE_NAME;
+#endif
+}
+
+int bt_set_id_addr(const bt_addr_le_t *addr)
+{
+	bt_addr_le_t non_const_addr;
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		BT_ERR("Setting identity not allowed after bt_enable()");
+		return -EBUSY;
+	}
+
+	bt_addr_le_copy(&non_const_addr, addr);
+
+	return bt_id_create(&non_const_addr, NULL);
+}
+
+void bt_id_get(bt_addr_le_t *addrs, size_t *count)
+{
+	size_t to_copy = MIN(*count, bt_dev.id_count);
+
+	memcpy(addrs, bt_dev.id_addr, to_copy * sizeof(bt_addr_le_t));
+	*count = to_copy;
+}
+
+static int id_find(const bt_addr_le_t *addr)
+{
+	uint8_t id;
+
+	for (id = 0U; id < bt_dev.id_count; id++) {
+		if (!bt_addr_le_cmp(addr, &bt_dev.id_addr[id])) {
+			return id;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static void id_create(uint8_t id, bt_addr_le_t *addr, uint8_t *irk)
+{
+	if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
+		bt_addr_le_copy(&bt_dev.id_addr[id], addr);
+	} else {
+		bt_addr_le_t new_addr;
+
+		do {
+			bt_addr_le_create_static(&new_addr);
+			/* Make sure we didn't generate a duplicate */
+		} while (id_find(&new_addr) >= 0);
+
+		bt_addr_le_copy(&bt_dev.id_addr[id], &new_addr);
+
+		if (addr) {
+			bt_addr_le_copy(addr, &bt_dev.id_addr[id]);
+		}
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	{
+		uint8_t zero_irk[16] = { 0 };
+
+		if (irk && memcmp(irk, zero_irk, 16)) {
+			memcpy(&bt_dev.irk[id], irk, 16);
+		} else {
+			bt_rand(&bt_dev.irk[id], 16);
+			if (irk) {
+				memcpy(irk, &bt_dev.irk[id], 16);
+			}
+		}
+	}
+#endif
+	/* Only store if stack was already initialized. Before initialization
+	 * we don't know the flash content, so it's potentially harmful to
+	 * try to write anything there.
+	 */
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		bt_settings_save_id();
+	}
+}
+
+int bt_id_create(bt_addr_le_t *addr, uint8_t *irk)
+{
+	int new_id;
+
+	if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
+		if (addr->type != BT_ADDR_LE_RANDOM ||
+		    !BT_ADDR_IS_STATIC(&addr->a)) {
+			BT_ERR("Only static random identity address supported");
+			return -EINVAL;
+		}
+
+		if (id_find(addr) >= 0) {
+			return -EALREADY;
+		}
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
+		return -EINVAL;
+	}
+
+	if (bt_dev.id_count == ARRAY_SIZE(bt_dev.id_addr)) {
+		return -ENOMEM;
+	}
+
+	new_id = bt_dev.id_count++;
+	id_create(new_id, addr, irk);
+
+	return new_id;
+}
+
+int bt_id_reset(uint8_t id, bt_addr_le_t *addr, uint8_t *irk)
+{
+	struct adv_id_check_data check_data = {
+		.id = id,
+		.adv_enabled = false,
+	};
+
+	if (addr && bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
+		if (addr->type != BT_ADDR_LE_RANDOM ||
+		    !BT_ADDR_IS_STATIC(&addr->a)) {
+			BT_ERR("Only static random identity address supported");
+			return -EINVAL;
+		}
+
+		if (id_find(addr) >= 0) {
+			return -EALREADY;
+		}
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_PRIVACY) && irk) {
+		return -EINVAL;
+	}
+
+	if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) {
+		return -EINVAL;
+	}
+
+	bt_adv_foreach(adv_id_check_func, &check_data);
+	if (check_data.adv_enabled) {
+		return -EBUSY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN) &&
+	    bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) {
+		int err;
+
+		err = bt_unpair(id, NULL);
+		if (err) {
+			return err;
+		}
+	}
+
+	id_create(id, addr, irk);
+
+	return id;
+}
+
+int bt_id_delete(uint8_t id)
+{
+	struct adv_id_check_data check_data = {
+		.id = id,
+		.adv_enabled = false,
+	};
+
+	if (id == BT_ID_DEFAULT || id >= bt_dev.id_count) {
+		return -EINVAL;
+	}
+
+	if (!bt_addr_le_cmp(&bt_dev.id_addr[id], BT_ADDR_LE_ANY)) {
+		return -EALREADY;
+	}
+
+	bt_adv_foreach(adv_id_check_func, &check_data);
+	if (check_data.adv_enabled) {
+		return -EBUSY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CONN)) {
+		int err;
+
+		err = bt_unpair(id, NULL);
+		if (err) {
+			return err;
+		}
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	(void)memset(bt_dev.irk[id], 0, 16);
+#endif
+	bt_addr_le_copy(&bt_dev.id_addr[id], BT_ADDR_LE_ANY);
+
+	if (id == bt_dev.id_count - 1) {
+		bt_dev.id_count--;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+	    atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		bt_settings_save_id();
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PRIVACY)
+static void bt_read_identity_root(uint8_t *ir)
+{
+	/* Invalid IR */
+	memset(ir, 0, 16);
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+	struct bt_hci_rp_vs_read_key_hierarchy_roots *rp;
+	struct net_buf *rsp;
+	int err;
+
+	if (!BT_VS_CMD_READ_KEY_ROOTS(bt_dev.vs_commands)) {
+		return;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS, NULL,
+				   &rsp);
+	if (err) {
+		BT_WARN("Failed to read identity root");
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+	    rsp->len != sizeof(struct bt_hci_rp_vs_read_key_hierarchy_roots)) {
+		BT_WARN("Invalid Vendor HCI extensions");
+		net_buf_unref(rsp);
+		return;
+	}
+
+	rp = (void *)rsp->data;
+	memcpy(ir, rp->ir, 16);
+
+	net_buf_unref(rsp);
+#endif /* defined(CONFIG_BT_HCI_VS_EXT) */
+}
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+void bt_setup_public_id_addr(void)
+{
+	bt_addr_le_t addr;
+	uint8_t *irk = NULL;
+
+	bt_dev.id_count = bt_read_public_addr(&addr);
+
+	if (!bt_dev.id_count) {
+		return;
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	uint8_t ir_irk[16];
+	uint8_t ir[16];
+
+	bt_read_identity_root(ir);
+
+	if (!bt_smp_irk_get(ir, ir_irk)) {
+		irk = ir_irk;
+	} else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID);
+	}
+#endif /* defined(CONFIG_BT_PRIVACY) */
+
+	id_create(BT_ID_DEFAULT, &addr, irk);
+}
+
+#if defined(CONFIG_BT_HCI_VS_EXT)
+uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size)
+{
+	struct bt_hci_rp_vs_read_static_addrs *rp;
+	struct net_buf *rsp;
+	int err, i;
+	uint8_t cnt;
+
+	if (!BT_VS_CMD_READ_STATIC_ADDRS(bt_dev.vs_commands)) {
+		BT_WARN("Read Static Addresses command not available");
+		return 0;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_STATIC_ADDRS, NULL, &rsp);
+	if (err) {
+		BT_WARN("Failed to read static addresses");
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+	    rsp->len < sizeof(struct bt_hci_rp_vs_read_static_addrs)) {
+		BT_WARN("Invalid Vendor HCI extensions");
+		net_buf_unref(rsp);
+		return 0;
+	}
+
+	rp = (void *)rsp->data;
+	cnt = MIN(rp->num_addrs, size);
+
+	if (IS_ENABLED(CONFIG_BT_HCI_VS_EXT_DETECT) &&
+	    rsp->len != (sizeof(struct bt_hci_rp_vs_read_static_addrs) +
+			 rp->num_addrs *
+			 sizeof(struct bt_hci_vs_static_addr))) {
+		BT_WARN("Invalid Vendor HCI extensions");
+		net_buf_unref(rsp);
+		return 0;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		memcpy(&addrs[i], rp->a, sizeof(struct bt_hci_vs_static_addr));
+	}
+
+	net_buf_unref(rsp);
+	if (!cnt) {
+		BT_WARN("No static addresses stored in controller");
+	}
+
+	return cnt;
+}
+#endif /* CONFIG_BT_HCI_VS_EXT */
+
+int bt_setup_random_id_addr(void)
+{
+#if defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR)
+	/* Only read the addresses if the user has not already configured one or
+	 * more identities (!bt_dev.id_count).
+	 */
+	if (!bt_dev.id_count) {
+		struct bt_hci_vs_static_addr addrs[CONFIG_BT_ID_MAX];
+
+		bt_dev.id_count = bt_read_static_addr(addrs, CONFIG_BT_ID_MAX);
+
+		if (bt_dev.id_count) {
+			for (uint8_t i = 0; i < bt_dev.id_count; i++) {
+				bt_addr_le_t addr;
+				uint8_t *irk = NULL;
+#if defined(CONFIG_BT_PRIVACY)
+				uint8_t ir_irk[16];
+
+				if (!bt_smp_irk_get(addrs[i].ir, ir_irk)) {
+					irk = ir_irk;
+				} else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+					atomic_set_bit(bt_dev.flags,
+						       BT_DEV_STORE_ID);
+				}
+#endif /* CONFIG_BT_PRIVACY */
+
+				bt_addr_copy(&addr.a, &addrs[i].bdaddr);
+				addr.type = BT_ADDR_LE_RANDOM;
+
+				id_create(i, &addr, irk);
+			}
+
+			return 0;
+		}
+	}
+#endif /* defined(CONFIG_BT_HCI_VS_EXT) || defined(CONFIG_BT_CTLR) */
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY) && IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		atomic_set_bit(bt_dev.flags, BT_DEV_STORE_ID);
+	}
+
+	return bt_id_create(NULL, NULL);
+}
+
+bool bt_addr_le_is_bonded(uint8_t id, const bt_addr_le_t *addr)
+{
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		struct bt_keys *keys = bt_keys_find_addr(id, addr);
+
+		/* if there are any keys stored then device is bonded */
+		return keys && keys->keys;
+	} else {
+		return false;
+	}
+}
+
+int bt_le_per_adv_set_param(struct bt_le_ext_adv *adv,
+			    const struct bt_le_per_adv_param *param)
+{
+	struct bt_hci_cp_le_set_per_adv_param *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (atomic_test_bit(adv->flags, BT_ADV_SCANNABLE)) {
+		return -EINVAL;
+	} else if (atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		return -EINVAL;
+	} else if (!atomic_test_bit(adv->flags, BT_ADV_EXT_ADV)) {
+		return -EINVAL;
+	}
+
+	if (param->interval_min < 0x0006 ||
+	    param->interval_max > 0xFFFF ||
+	    param->interval_min > param->interval_max) {
+		return -EINVAL;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_PARAM, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	cp->handle = sys_cpu_to_le16(adv->handle);
+	cp->min_interval = sys_cpu_to_le16(param->interval_min);
+	cp->max_interval = sys_cpu_to_le16(param->interval_max);
+
+	if (param->options & BT_LE_PER_ADV_OPT_USE_TX_POWER) {
+		cp->props |= BT_HCI_LE_ADV_PROP_TX_POWER;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PER_ADV_PARAM, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit(adv->flags, BT_PER_ADV_PARAMS_SET);
+
+	return 0;
+}
+
+int bt_le_per_adv_set_data(const struct bt_le_ext_adv *adv,
+			   const struct bt_data *ad, size_t ad_len)
+{
+	struct bt_hci_cp_le_set_per_adv_data *cp;
+	struct net_buf *buf;
+	struct bt_ad d = { .data = ad, .len = ad_len };
+	int err;
+
+	if (!atomic_test_bit(adv->flags, BT_PER_ADV_PARAMS_SET)) {
+		return -EINVAL;
+	}
+
+	if (!ad_len || !ad) {
+		return -EINVAL;
+	}
+
+	if (ad_len > BT_HCI_LE_PER_ADV_FRAG_MAX_LEN) {
+		return -EINVAL;
+	}
+
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_DATA, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	cp->handle = adv->handle;
+
+	/* TODO: If data is longer than what the controller can manage,
+	 * split the data. Read size from controller on boot.
+	 */
+	cp->op = BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA;
+
+	err = set_data_add(cp->data, BT_HCI_LE_PER_ADV_FRAG_MAX_LEN, &d, 1,
+			   &cp->len);
+	if (err) {
+		return err;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PER_ADV_DATA, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int bt_le_per_adv_enable(struct bt_le_ext_adv *adv, bool enable)
+{
+	struct bt_hci_cp_le_set_per_adv_enable *cp;
+	struct net_buf *buf;
+	struct cmd_state_set state;
+	int err;
+
+	/* TODO: We could setup some default ext adv params if not already set*/
+	if (!atomic_test_bit(adv->flags, BT_PER_ADV_PARAMS_SET)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(adv->flags, BT_PER_ADV_ENABLED) == enable) {
+		return -EALREADY;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_ENABLE, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	cp->handle = adv->handle;
+	cp->enable = enable ? 1 : 0;
+
+	cmd_state_set_init(&state, adv->flags, BT_PER_ADV_ENABLED, enable);
+	cmd(buf)->state = &state;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PER_ADV_ENABLE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_le_per_adv_start(struct bt_le_ext_adv *adv)
+{
+	return bt_le_per_adv_enable(adv, true);
+}
+
+int bt_le_per_adv_stop(struct bt_le_ext_adv *adv)
+{
+	return bt_le_per_adv_enable(adv, false);
+}
+
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+
+uint8_t bt_le_per_adv_sync_get_index(struct bt_le_per_adv_sync *per_adv_sync)
+{
+	uintptr_t index = per_adv_sync - per_adv_sync_pool;
+
+	__ASSERT(per_adv_sync >= per_adv_sync_pool &&
+			index < ARRAY_SIZE(per_adv_sync_pool),
+		 "Invalid per_adv_sync pointer");
+	return index;
+}
+
+static struct bt_le_per_adv_sync *per_adv_sync_new(void)
+{
+	struct bt_le_per_adv_sync *per_adv_sync = NULL;
+
+	for (int i = 0; i < ARRAY_SIZE(per_adv_sync_pool); i++) {
+		if (!atomic_test_bit(per_adv_sync_pool[i].flags,
+				     BT_PER_ADV_SYNC_CREATED)) {
+			per_adv_sync = &per_adv_sync_pool[i];
+			break;
+		}
+	}
+
+	if (!per_adv_sync) {
+		return NULL;
+	}
+
+	(void)memset(per_adv_sync, 0, sizeof(*per_adv_sync));
+	atomic_set_bit(per_adv_sync->flags, BT_PER_ADV_SYNC_CREATED);
+
+	return per_adv_sync;
+}
+
+int bt_le_per_adv_sync_create(const struct bt_le_per_adv_sync_param *param,
+			      struct bt_le_per_adv_sync **out_sync)
+{
+	struct bt_hci_cp_le_per_adv_create_sync *cp;
+	struct net_buf *buf;
+	struct bt_le_per_adv_sync *per_adv_sync;
+	int err;
+
+	if (!BT_FEAT_LE_EXT_PER_ADV(bt_dev.le.features)) {
+		return -ENOTSUP;
+	}
+
+	if (get_pending_per_adv_sync()) {
+		return -EBUSY;
+	}
+
+	if (param->sid > BT_GAP_SID_MAX ||
+		   param->skip > BT_GAP_PER_ADV_MAX_MAX_SKIP ||
+		   param->timeout > BT_GAP_PER_ADV_MAX_MAX_TIMEOUT) {
+		return -EINVAL;
+	}
+
+	per_adv_sync = per_adv_sync_new();
+	if (!per_adv_sync) {
+		return -ENOMEM;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC, sizeof(*cp));
+	if (!buf) {
+		per_adv_sync_delete(per_adv_sync);
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+
+	bt_addr_le_copy(&cp->addr, &param->addr);
+
+	if (param->options & BT_LE_PER_ADV_SYNC_OPT_USE_PER_ADV_LIST) {
+		cp->options |= BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST;
+	}
+
+	if (param->options & BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOA) {
+		cp->cte_type |= BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA;
+	}
+
+	if (param->options & BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_1US) {
+		cp->cte_type |=
+			BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US;
+	}
+
+	if (param->options & BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_2US) {
+		cp->cte_type |=
+			BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US;
+	}
+
+	if (param->options & BT_LE_PER_ADV_SYNC_OPT_SYNC_ONLY_CONST_TONE_EXT) {
+		cp->cte_type |= BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE;
+	}
+
+	cp->sid = param->sid;
+	cp->skip = sys_cpu_to_le16(param->skip);
+	cp->sync_timeout = sys_cpu_to_le16(param->timeout);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC, buf, NULL);
+	if (err) {
+		per_adv_sync_delete(per_adv_sync);
+		return err;
+	}
+
+	atomic_set_bit(per_adv_sync->flags, BT_PER_ADV_SYNC_SYNCING);
+
+	/* Syncing requires that scan is enabled. If the caller doesn't enable
+	 * scan first, we enable it here, and disable it once the sync has been
+	 * established. We don't need to use any callbacks since we rely on
+	 * the advertiser address in the sync params.
+	 */
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
+		err = bt_le_scan_update(true);
+
+		if (err) {
+			bt_le_per_adv_sync_delete(per_adv_sync);
+			return err;
+		}
+	}
+
+	*out_sync = per_adv_sync;
+	bt_addr_le_copy(&per_adv_sync->addr, &param->addr);
+	per_adv_sync->sid = param->sid;
+
+	return 0;
+}
+
+static int bt_le_per_adv_sync_create_cancel(
+	struct bt_le_per_adv_sync *per_adv_sync)
+{
+	struct net_buf *buf;
+	int err;
+
+	if (get_pending_per_adv_sync() != per_adv_sync) {
+		return -EINVAL;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL, 0);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL, buf,
+				   NULL);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int bt_le_per_adv_sync_terminate(struct bt_le_per_adv_sync *per_adv_sync)
+{
+	int err;
+
+	if (!atomic_test_bit(per_adv_sync->flags, BT_PER_ADV_SYNC_SYNCED)) {
+		return -EINVAL;
+	}
+
+	err = per_adv_sync_terminate(per_adv_sync->handle);
+
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_le_per_adv_sync_delete(struct bt_le_per_adv_sync *per_adv_sync)
+{
+	int err = 0;
+
+	if (atomic_test_bit(per_adv_sync->flags, BT_PER_ADV_SYNC_SYNCED)) {
+		err = bt_le_per_adv_sync_terminate(per_adv_sync);
+	} else if (get_pending_per_adv_sync() == per_adv_sync) {
+		err = bt_le_per_adv_sync_create_cancel(per_adv_sync);
+	}
+
+	if (err) {
+		return err;
+	}
+
+	per_adv_sync_delete(per_adv_sync);
+	return err;
+}
+
+void bt_le_per_adv_sync_cb_register(struct bt_le_per_adv_sync_cb *cb)
+{
+	sys_slist_append(&pa_sync_cbs, &cb->node);
+}
+#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
+
+static bool valid_adv_ext_param(const struct bt_le_adv_param *param)
+{
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		if (param->peer &&
+		    !(param->options & BT_LE_ADV_OPT_EXT_ADV) &&
+		    !(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
+			/* Cannot do directed non-connectable advertising
+			 * without extended advertising.
+			 */
+			return false;
+		}
+
+		if (!(param->options & BT_LE_ADV_OPT_EXT_ADV) &&
+		    param->options & (BT_LE_ADV_OPT_EXT_ADV |
+				      BT_LE_ADV_OPT_NO_2M |
+				      BT_LE_ADV_OPT_CODED |
+				      BT_LE_ADV_OPT_ANONYMOUS |
+				      BT_LE_ADV_OPT_USE_TX_POWER)) {
+			/* Extended options require extended advertising. */
+			return false;
+		}
+	}
+
+	if (param->id >= bt_dev.id_count ||
+	    !bt_addr_le_cmp(&bt_dev.id_addr[param->id], BT_ADDR_LE_ANY)) {
+		return false;
+	}
+
+	if (!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
+		/*
+		 * BT Core 4.2 [Vol 2, Part E, 7.8.5]
+		 * The Advertising_Interval_Min and Advertising_Interval_Max
+		 * shall not be set to less than 0x00A0 (100 ms) if the
+		 * Advertising_Type is set to ADV_SCAN_IND or ADV_NONCONN_IND.
+		 */
+		if (bt_dev.hci_version < BT_HCI_VERSION_5_0 &&
+		    param->interval_min < 0x00a0) {
+			return false;
+		}
+	}
+
+	if ((param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) ||
+	    !param->peer) {
+		if (param->interval_min > param->interval_max ||
+		    param->interval_min < 0x0020 ||
+		    param->interval_max > 0x4000) {
+			return false;
+		}
+	}
+
+	if ((param->options & BT_LE_ADV_OPT_DISABLE_CHAN_37) &&
+	    (param->options & BT_LE_ADV_OPT_DISABLE_CHAN_38) &&
+	    (param->options & BT_LE_ADV_OPT_DISABLE_CHAN_39)) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool valid_adv_param(const struct bt_le_adv_param *param)
+{
+	if (param->options & BT_LE_ADV_OPT_EXT_ADV) {
+		return false;
+	}
+
+	if (param->peer && !(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
+		return false;
+	}
+
+	return valid_adv_ext_param(param);
+}
+
+static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len)
+{
+	size_t i;
+
+	for (i = 0; i < ad_len; i++) {
+		if (ad[i].type == BT_DATA_NAME_COMPLETE ||
+		    ad[i].type == BT_DATA_NAME_SHORTENED) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int le_adv_update(struct bt_le_ext_adv *adv,
+			 const struct bt_data *ad, size_t ad_len,
+			 const struct bt_data *sd, size_t sd_len,
+			 bool ext_adv, bool scannable, bool use_name)
+{
+	struct bt_ad d[2] = {};
+	struct bt_data data;
+	size_t d_len;
+	int err;
+
+	if (use_name) {
+		const char *name = bt_get_name();
+
+		if ((ad && ad_has_name(ad, ad_len)) ||
+		    (sd && ad_has_name(sd, sd_len))) {
+			/* Cannot use name if name is already set */
+			return -EINVAL;
+		}
+
+		data = (struct bt_data)BT_DATA(
+			BT_DATA_NAME_COMPLETE,
+			name, strlen(name));
+	}
+
+	if (!(ext_adv && scannable)) {
+		d_len = 1;
+		d[0].data = ad;
+		d[0].len = ad_len;
+
+		if (use_name && !scannable) {
+			d[1].data = &data;
+			d[1].len = 1;
+			d_len = 2;
+		}
+
+		err = set_ad(adv, d, d_len);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (scannable) {
+		d_len = 1;
+		d[0].data = sd;
+		d[0].len = sd_len;
+
+		if (use_name) {
+			d[1].data = &data;
+			d[1].len = 1;
+			d_len = 2;
+		}
+
+		err = set_sd(adv, d, d_len);
+		if (err) {
+			return err;
+		}
+	}
+
+	atomic_set_bit(adv->flags, BT_ADV_DATA_SET);
+	return 0;
+}
+
+int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,
+			  const struct bt_data *sd, size_t sd_len)
+{
+	struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+	bool scannable, use_name;
+
+	if (!adv) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return -EAGAIN;
+	}
+
+	scannable = atomic_test_bit(adv->flags, BT_ADV_SCANNABLE);
+	use_name = atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME);
+
+	return le_adv_update(adv, ad, ad_len, sd, sd_len, false, scannable,
+			     use_name);
+}
+
+static uint8_t get_filter_policy(uint32_t options)
+{
+	if (!IS_ENABLED(CONFIG_BT_WHITELIST)) {
+		return BT_LE_ADV_FP_NO_WHITELIST;
+	} else if ((options & BT_LE_ADV_OPT_FILTER_SCAN_REQ) &&
+		   (options & BT_LE_ADV_OPT_FILTER_CONN)) {
+		return BT_LE_ADV_FP_WHITELIST_BOTH;
+	} else if (options & BT_LE_ADV_OPT_FILTER_SCAN_REQ) {
+		return BT_LE_ADV_FP_WHITELIST_SCAN_REQ;
+	} else if (options & BT_LE_ADV_OPT_FILTER_CONN) {
+		return BT_LE_ADV_FP_WHITELIST_CONN_IND;
+	} else {
+		return BT_LE_ADV_FP_NO_WHITELIST;
+	}
+}
+
+static uint8_t get_adv_channel_map(uint32_t options)
+{
+	uint8_t channel_map = 0x07;
+
+	if (options & BT_LE_ADV_OPT_DISABLE_CHAN_37) {
+		channel_map &= ~0x01;
+	}
+
+	if (options & BT_LE_ADV_OPT_DISABLE_CHAN_38) {
+		channel_map &= ~0x02;
+	}
+
+	if (options & BT_LE_ADV_OPT_DISABLE_CHAN_39) {
+		channel_map &= ~0x04;
+	}
+
+	return channel_map;
+}
+
+static int le_adv_set_random_addr(struct bt_le_ext_adv *adv, uint32_t options,
+				  bool dir_adv, uint8_t *own_addr_type)
+{
+	const bt_addr_le_t *id_addr;
+	int err = 0;
+
+	/* Set which local identity address we're advertising with */
+	id_addr = &bt_dev.id_addr[adv->id];
+
+	if (options & BT_LE_ADV_OPT_CONNECTABLE) {
+		if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+		    !(options & BT_LE_ADV_OPT_USE_IDENTITY)) {
+			err = le_adv_set_private_addr(adv);
+			if (err) {
+				return err;
+			}
+
+			if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
+				*own_addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
+			} else {
+				*own_addr_type = BT_ADDR_LE_RANDOM;
+			}
+		} else {
+			/*
+			 * If Static Random address is used as Identity
+			 * address we need to restore it before advertising
+			 * is enabled. Otherwise NRPA used for active scan
+			 * could be used for advertising.
+			 */
+			if (id_addr->type == BT_ADDR_LE_RANDOM) {
+				err = set_adv_random_address(adv, &id_addr->a);
+				if (err) {
+					return err;
+				}
+			}
+
+			*own_addr_type = id_addr->type;
+		}
+
+		if (dir_adv) {
+			if (IS_ENABLED(CONFIG_BT_SMP) &&
+			    !IS_ENABLED(CONFIG_BT_PRIVACY) &&
+			    BT_FEAT_LE_PRIVACY(bt_dev.le.features) &&
+			    (options & BT_LE_ADV_OPT_DIR_ADDR_RPA)) {
+				/* This will not use RPA for our own address
+				 * since we have set zeroed out the local IRK.
+				 */
+				*own_addr_type |= BT_HCI_OWN_ADDR_RPA_MASK;
+			}
+		}
+	} else {
+		if (options & BT_LE_ADV_OPT_USE_IDENTITY) {
+			if (id_addr->type == BT_ADDR_LE_RANDOM) {
+				err = set_adv_random_address(adv, &id_addr->a);
+			}
+
+			*own_addr_type = id_addr->type;
+		} else if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+			     BT_FEAT_LE_EXT_ADV(bt_dev.le.features))) {
+			/* In case advertising set random address is not
+			 * available we must handle the shared random address
+			 * problem.
+			 */
+#if defined(CONFIG_BT_OBSERVER)
+			bool scan_enabled = false;
+
+			/* If active scan with NRPA is ongoing refresh NRPA */
+			if (!IS_ENABLED(CONFIG_BT_PRIVACY) &&
+			    !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) &&
+			    atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) &&
+			    atomic_test_bit(bt_dev.flags, BT_DEV_ACTIVE_SCAN)) {
+				scan_enabled = true;
+				set_le_scan_enable(false);
+			}
+#endif /* defined(CONFIG_BT_OBSERVER) */
+			err = le_adv_set_private_addr(adv);
+			*own_addr_type = BT_ADDR_LE_RANDOM;
+
+#if defined(CONFIG_BT_OBSERVER)
+			if (scan_enabled) {
+				set_le_scan_enable(true);
+			}
+#endif /* defined(CONFIG_BT_OBSERVER) */
+		} else {
+			err = le_adv_set_private_addr(adv);
+			*own_addr_type = BT_ADDR_LE_RANDOM;
+		}
+
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int le_adv_start_add_conn(const struct bt_le_ext_adv *adv,
+				 struct bt_conn **out_conn)
+{
+	struct adv_id_check_data check_data = {
+		.id = adv->id,
+		.adv_enabled = false
+	};
+	struct bt_conn *conn;
+
+	bt_adv_foreach(adv_id_check_connectable_func, &check_data);
+	if (check_data.adv_enabled) {
+		return -ENOTSUP;
+	}
+
+	bt_dev.adv_conn_id = adv->id;
+
+	if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) {
+		/* Undirected advertising */
+		conn = bt_conn_add_le(adv->id, BT_ADDR_LE_NONE);
+		if (!conn) {
+			return -ENOMEM;
+		}
+
+		bt_conn_set_state(conn, BT_CONN_CONNECT_ADV);
+		*out_conn = conn;
+		return 0;
+	}
+
+	if (bt_conn_exists_le(adv->id, &adv->target_addr)) {
+		return -EINVAL;
+	}
+
+	conn = bt_conn_add_le(adv->id, &adv->target_addr);
+	if (!conn) {
+		return -ENOMEM;
+	}
+
+	bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV);
+	*out_conn = conn;
+	return 0;
+}
+
+int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv,
+			   const struct bt_le_adv_param *param,
+			   const struct bt_data *ad, size_t ad_len,
+			   const struct bt_data *sd, size_t sd_len)
+{
+	struct bt_hci_cp_le_set_adv_param set_param;
+	struct bt_conn *conn = NULL;
+	struct net_buf *buf;
+	bool dir_adv = (param->peer != NULL), scannable;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (!valid_adv_param(param)) {
+		return -EINVAL;
+	}
+
+	if (!bt_le_adv_random_addr_check(param)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return -EALREADY;
+	}
+
+	(void)memset(&set_param, 0, sizeof(set_param));
+
+	set_param.min_interval = sys_cpu_to_le16(param->interval_min);
+	set_param.max_interval = sys_cpu_to_le16(param->interval_max);
+	set_param.channel_map  = get_adv_channel_map(param->options);
+	set_param.filter_policy = get_filter_policy(param->options);
+
+	if (adv->id != param->id) {
+		atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+	}
+
+	adv->id = param->id;
+	bt_dev.adv_conn_id = adv->id;
+
+	err = le_adv_set_random_addr(adv, param->options, dir_adv,
+				     &set_param.own_addr_type);
+	if (err) {
+		return err;
+	}
+
+	if (dir_adv) {
+		bt_addr_le_copy(&adv->target_addr, param->peer);
+	} else {
+		bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY);
+	}
+
+	if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
+		scannable = true;
+
+		if (dir_adv) {
+			if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) {
+				set_param.type = BT_HCI_ADV_DIRECT_IND_LOW_DUTY;
+			} else {
+				set_param.type = BT_HCI_ADV_DIRECT_IND;
+			}
+
+			bt_addr_le_copy(&set_param.direct_addr, param->peer);
+		} else {
+			set_param.type = BT_HCI_ADV_IND;
+		}
+	} else {
+		scannable = sd || (param->options & BT_LE_ADV_OPT_USE_NAME);
+
+		set_param.type = scannable ? BT_HCI_ADV_SCAN_IND :
+					     BT_HCI_ADV_NONCONN_IND;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_mem(buf, &set_param, sizeof(set_param));
+
+	err = bt_hci_cmd_send(BT_HCI_OP_LE_SET_ADV_PARAM, buf);
+	if (err) {
+		return err;
+	}
+
+	if (!dir_adv) {
+		err = le_adv_update(adv, ad, ad_len, sd, sd_len, false,
+				    scannable,
+				    param->options & BT_LE_ADV_OPT_USE_NAME);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    (param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
+		err = le_adv_start_add_conn(adv, &conn);
+		if (err) {
+			if (err == -ENOMEM && !dir_adv &&
+			    !(param->options & BT_LE_ADV_OPT_ONE_TIME)) {
+				goto set_adv_state;
+			}
+
+			return err;
+		}
+	}
+
+	err = set_le_adv_enable(adv, true);
+	if (err) {
+		BT_ERR("Failed to start advertiser");
+		if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+			bt_conn_unref(conn);
+		}
+
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+		/* If undirected connectable advertiser we have created a
+		 * connection object that we don't yet give to the application.
+		 * Since we don't give the application a reference to manage in
+		 * this case, we need to release this reference here
+		 */
+		bt_conn_unref(conn);
+	}
+
+set_adv_state:
+	atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv &&
+			  !(param->options & BT_LE_ADV_OPT_ONE_TIME));
+
+	atomic_set_bit_to(adv->flags, BT_ADV_INCLUDE_NAME,
+			  param->options & BT_LE_ADV_OPT_USE_NAME);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE,
+			  param->options & BT_LE_ADV_OPT_CONNECTABLE);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_SCANNABLE, scannable);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_USE_IDENTITY,
+			  param->options & BT_LE_ADV_OPT_USE_IDENTITY);
+
+	return 0;
+}
+
+static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
+				const struct bt_le_adv_param *param,
+				bool  has_scan_data)
+{
+	struct bt_hci_cp_le_set_ext_adv_param *cp;
+	bool dir_adv = param->peer != NULL, scannable;
+	struct net_buf *buf, *rsp;
+	int err;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_ADV_PARAM, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	(void)memset(cp, 0, sizeof(*cp));
+
+	err = le_adv_set_random_addr(adv, param->options, dir_adv,
+				     &cp->own_addr_type);
+	if (err) {
+		return err;
+	}
+
+	if (dir_adv) {
+		bt_addr_le_copy(&adv->target_addr, param->peer);
+	} else {
+		bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY);
+	}
+
+	cp->handle = adv->handle;
+	sys_put_le24(param->interval_min, cp->prim_min_interval);
+	sys_put_le24(param->interval_max, cp->prim_max_interval);
+	cp->prim_channel_map = get_adv_channel_map(param->options);
+	cp->filter_policy = get_filter_policy(param->options);
+	cp->tx_power = BT_HCI_LE_ADV_TX_POWER_NO_PREF;
+
+	cp->prim_adv_phy = BT_HCI_LE_PHY_1M;
+	if (param->options & BT_LE_ADV_OPT_EXT_ADV) {
+		if (param->options & BT_LE_ADV_OPT_NO_2M) {
+			cp->sec_adv_phy = BT_HCI_LE_PHY_1M;
+		} else {
+			cp->sec_adv_phy = BT_HCI_LE_PHY_2M;
+		}
+	}
+
+	if (param->options & BT_LE_ADV_OPT_CODED) {
+		cp->prim_adv_phy = BT_HCI_LE_PHY_CODED;
+		cp->sec_adv_phy = BT_HCI_LE_PHY_CODED;
+	}
+
+	if (!(param->options & BT_LE_ADV_OPT_EXT_ADV)) {
+		cp->props |= BT_HCI_LE_ADV_PROP_LEGACY;
+	}
+
+	if (param->options & BT_LE_ADV_OPT_USE_TX_POWER) {
+		cp->props |= BT_HCI_LE_ADV_PROP_TX_POWER;
+	}
+
+	if (param->options & BT_LE_ADV_OPT_ANONYMOUS) {
+		cp->props |= BT_HCI_LE_ADV_PROP_ANON;
+	}
+
+	if (param->options & BT_LE_ADV_OPT_NOTIFY_SCAN_REQ) {
+		cp->scan_req_notify_enable = BT_HCI_LE_ADV_SCAN_REQ_ENABLE;
+	}
+
+	if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
+		cp->props |= BT_HCI_LE_ADV_PROP_CONN;
+		if (!dir_adv && !(param->options & BT_LE_ADV_OPT_EXT_ADV)) {
+			/* When using non-extended adv packets then undirected
+			 * advertising has to be scannable as well.
+			 * We didn't require this option to be set before, so
+			 * it is implicitly set instead in this case.
+			 */
+			cp->props |= BT_HCI_LE_ADV_PROP_SCAN;
+		}
+	}
+
+	if ((param->options & BT_LE_ADV_OPT_SCANNABLE) || has_scan_data) {
+		cp->props |= BT_HCI_LE_ADV_PROP_SCAN;
+	}
+
+	scannable = !!(cp->props & BT_HCI_LE_ADV_PROP_SCAN);
+
+	if (dir_adv) {
+		cp->props |= BT_HCI_LE_ADV_PROP_DIRECT;
+		if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
+			cp->props |= BT_HCI_LE_ADV_PROP_HI_DC_CONN;
+		}
+
+		bt_addr_le_copy(&cp->peer_addr, param->peer);
+	}
+
+	cp->sid = param->sid;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_ADV_PARAM, buf, &rsp);
+	if (err) {
+		return err;
+	}
+
+#if defined(CONFIG_BT_EXT_ADV)
+	struct bt_hci_rp_le_set_ext_adv_param *rp = (void *)rsp->data;
+
+	adv->tx_power = rp->tx_power;
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+	net_buf_unref(rsp);
+
+	atomic_set_bit(adv->flags, BT_ADV_PARAMS_SET);
+
+	if (atomic_test_and_clear_bit(adv->flags, BT_ADV_RANDOM_ADDR_PENDING)) {
+		err = set_adv_random_address(adv, &adv->random_addr.a);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* Flag only used by bt_le_adv_start API. */
+	atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, false);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_INCLUDE_NAME,
+			  param->options & BT_LE_ADV_OPT_USE_NAME);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_CONNECTABLE,
+			  param->options & BT_LE_ADV_OPT_CONNECTABLE);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_SCANNABLE, scannable);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_USE_IDENTITY,
+			  param->options & BT_LE_ADV_OPT_USE_IDENTITY);
+
+	atomic_set_bit_to(adv->flags, BT_ADV_EXT_ADV,
+			  param->options & BT_LE_ADV_OPT_EXT_ADV);
+
+	return 0;
+}
+
+int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
+			const struct bt_le_adv_param *param,
+			const struct bt_data *ad, size_t ad_len,
+			const struct bt_data *sd, size_t sd_len)
+{
+	struct bt_le_ext_adv_start_param start_param = {
+		.timeout = 0,
+		.num_events = 0,
+	};
+	bool dir_adv = (param->peer != NULL);
+	struct bt_conn *conn = NULL;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (!valid_adv_param(param)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return -EALREADY;
+	}
+
+	adv->id = param->id;
+	err = le_ext_adv_param_set(adv, param, sd ||
+				   (param->options & BT_LE_ADV_OPT_USE_NAME));
+	if (err) {
+		return err;
+	}
+
+	if (!dir_adv) {
+		//err = bt_le_ext_adv_set_data(adv, ad, ad_len, sd, sd_len);
+		if (err) {
+			return err;
+		}
+	} else {
+		if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
+			start_param.timeout =
+				BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT;
+			atomic_set_bit(adv->flags, BT_ADV_LIMITED);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    (param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
+		err = le_adv_start_add_conn(adv, &conn);
+		if (err) {
+			if (err == -ENOMEM && !dir_adv &&
+			    !(param->options & BT_LE_ADV_OPT_ONE_TIME)) {
+				goto set_adv_state;
+			}
+
+			return err;
+		}
+	}
+
+	err = set_le_adv_enable_ext(adv, true, &start_param);
+	if (err) {
+		BT_ERR("Failed to start advertiser");
+		if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+			bt_conn_unref(conn);
+		}
+
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+		/* If undirected connectable advertiser we have created a
+		 * connection object that we don't yet give to the application.
+		 * Since we don't give the application a reference to manage in
+		 * this case, we need to release this reference here
+		 */
+		bt_conn_unref(conn);
+	}
+
+set_adv_state:
+	/* Flag always set to false by le_ext_adv_param_set */
+	atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv &&
+			  !(param->options & BT_LE_ADV_OPT_ONE_TIME));
+
+	return 0;
+}
+
+int bt_le_adv_start(const struct bt_le_adv_param *param,
+		    const struct bt_data *ad, size_t ad_len,
+		    const struct bt_data *sd, size_t sd_len)
+{
+	struct bt_le_ext_adv *adv = adv_new_legacy();
+	int err;
+
+	if (!adv) {
+		return -ENOMEM;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		err = bt_le_adv_start_ext(adv, param, ad, ad_len, sd, sd_len);
+	} else {
+		err = bt_le_adv_start_legacy(adv, param, ad, ad_len, sd, sd_len);
+	}
+
+	if (err) {
+		adv_delete_legacy();
+	}
+
+	return err;
+}
+
+int bt_le_adv_stop(void)
+{
+	struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+	int err;
+
+	if (!adv) {
+		BT_ERR("No valid legacy adv");
+		return 0;
+	}
+
+	/* Make sure advertising is not re-enabled later even if it's not
+	 * currently enabled (i.e. BT_DEV_ADVERTISING is not set).
+	 */
+	atomic_clear_bit(adv->flags, BT_ADV_PERSIST);
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		/* Legacy advertiser exists, but is not currently advertising.
+		 * This happens when keep advertising behavior is active but
+		 * no conn object is available to do connectable advertising.
+		 */
+		adv_delete_legacy();
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		le_adv_stop_free_conn(adv, 0);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		err = set_le_adv_enable_ext(adv, false, NULL);
+		if (err) {
+			return err;
+		}
+	} else {
+		err = set_le_adv_enable_legacy(adv, false);
+		if (err) {
+			return err;
+		}
+	}
+
+	adv_delete_legacy();
+
+#if defined(CONFIG_BT_OBSERVER)
+	if (!(IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	      BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) &&
+	    !IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY)) {
+		/* If scan is ongoing set back NRPA */
+		if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
+			set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+			le_set_private_addr(BT_ID_DEFAULT);
+			set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
+		}
+	}
+#endif /* defined(CONFIG_BT_OBSERVER) */
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+void bt_le_adv_resume(void)
+{
+	struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
+	struct bt_conn *conn;
+	bool persist_paused = false;
+	int err;
+
+	if (!adv) {
+		BT_DBG("No valid legacy adv");
+		return;
+	}
+
+	if (!(atomic_test_bit(adv->flags, BT_ADV_PERSIST) &&
+	      !atomic_test_bit(adv->flags, BT_ADV_ENABLED))) {
+		return;
+	}
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		return;
+	}
+
+	err = le_adv_start_add_conn(adv, &conn);
+	if (err) {
+		BT_DBG("Host cannot resume connectable advertising (%d)", err);
+		return;
+	}
+
+	BT_DBG("Resuming connectable advertising");
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+		le_adv_set_private_addr(adv);
+	}
+
+	err = set_le_adv_enable(adv, true);
+	if (err) {
+		BT_DBG("Controller cannot resume connectable advertising (%d)",
+		       err);
+		bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+
+		/* Temporarily clear persist flag to avoid recursion in
+		 * bt_conn_unref if the flag is still set.
+		 */
+		persist_paused = atomic_test_and_clear_bit(adv->flags,
+							   BT_ADV_PERSIST);
+	}
+
+	/* Since we don't give the application a reference to manage in
+	 * this case, we need to release this reference here.
+	 */
+	bt_conn_unref(conn);
+	if (persist_paused) {
+		atomic_set_bit(adv->flags, BT_ADV_PERSIST);
+	}
+}
+#endif /* defined(CONFIG_BT_PERIPHERAL) */
+
+#if defined(CONFIG_BT_EXT_ADV)
+int bt_le_ext_adv_get_info(const struct bt_le_ext_adv *adv,
+			   struct bt_le_ext_adv_info *info)
+{
+	info->id = adv->id;
+	info->tx_power = adv->tx_power;
+
+	return 0;
+}
+
+int bt_le_ext_adv_create(const struct bt_le_adv_param *param,
+			 const struct bt_le_ext_adv_cb *cb,
+			 struct bt_le_ext_adv **out_adv)
+{
+	struct bt_le_ext_adv *adv;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (!valid_adv_ext_param(param)) {
+		return -EINVAL;
+	}
+
+	adv = adv_new();
+	if (!adv) {
+		return -ENOMEM;
+	}
+
+	adv->id = param->id;
+	adv->cb = cb;
+
+	err = le_ext_adv_param_set(adv, param, false);
+	if (err) {
+		adv_delete(adv);
+		return err;
+	}
+
+	*out_adv = adv;
+	return 0;
+}
+
+int bt_le_ext_adv_update_param(struct bt_le_ext_adv *adv,
+			       const struct bt_le_adv_param *param)
+{
+	if (!valid_adv_ext_param(param)) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PER_ADV) &&
+	    atomic_test_bit(adv->flags, BT_PER_ADV_PARAMS_SET)) {
+		/* If params for per adv has been set, do not allow setting
+		 * connectable, scanable or use legacy adv
+		 */
+		if (param->options & BT_LE_ADV_OPT_CONNECTABLE ||
+		    param->options & BT_LE_ADV_OPT_SCANNABLE ||
+		    !(param->options & BT_LE_ADV_OPT_EXT_ADV) ||
+		    param->options & BT_LE_ADV_OPT_ANONYMOUS) {
+			return -EINVAL;
+		}
+	}
+
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return -EINVAL;
+	}
+
+	if (param->id != adv->id) {
+		atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
+	}
+
+	return le_ext_adv_param_set(adv, param, false);
+}
+
+int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
+			struct bt_le_ext_adv_start_param *param)
+{
+	struct bt_conn *conn = NULL;
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		err = le_adv_start_add_conn(adv, &conn);
+		if (err) {
+			return err;
+		}
+	}
+
+	atomic_set_bit_to(adv->flags, BT_ADV_LIMITED, param &&
+			  (param->timeout > 0 || param->num_events > 0));
+
+	if (atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+		    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+			le_adv_set_private_addr(adv);
+		}
+	} else {
+		if (!atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+			le_adv_set_private_addr(adv);
+		}
+	}
+
+	if (atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_DATA_SET)) {
+		/* Set the advertiser name */
+		bt_le_ext_adv_set_data(adv, NULL, 0, NULL, 0);
+	}
+
+	err = set_le_adv_enable_ext(adv, true, param);
+	if (err) {
+		BT_ERR("Failed to start advertiser");
+		if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
+			bt_conn_unref(conn);
+		}
+
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
+		/* If undirected connectable advertiser we have created a
+		 * connection object that we don't yet give to the application.
+		 * Since we don't give the application a reference to manage in
+		 * this case, we need to release this reference here
+		 */
+		bt_conn_unref(conn);
+	}
+
+	return 0;
+}
+
+int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv)
+{
+	atomic_clear_bit(adv->flags, BT_ADV_PERSIST);
+
+	if (!atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return 0;
+	}
+
+	if (atomic_test_and_clear_bit(adv->flags, BT_ADV_LIMITED)) {
+		atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
+
+#if defined(CONFIG_BT_SMP)
+		pending_id_keys_update();
+#endif
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) {
+		le_adv_stop_free_conn(adv, 0);
+	}
+
+	return set_le_adv_enable_ext(adv, false, NULL);
+}
+
+int bt_le_ext_adv_set_data(struct bt_le_ext_adv *adv,
+			   const struct bt_data *ad, size_t ad_len,
+			   const struct bt_data *sd, size_t sd_len)
+{
+	bool ext_adv, scannable, use_name;
+
+	ext_adv = atomic_test_bit(adv->flags, BT_ADV_EXT_ADV);
+	scannable = atomic_test_bit(adv->flags, BT_ADV_SCANNABLE);
+	use_name = atomic_test_bit(adv->flags, BT_ADV_INCLUDE_NAME);
+
+	return le_adv_update(adv, ad, ad_len, sd, sd_len, ext_adv, scannable,
+			     use_name);
+}
+
+int bt_le_ext_adv_delete(struct bt_le_ext_adv *adv)
+{
+	struct bt_hci_cp_le_remove_adv_set *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (!BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		return -ENOTSUP;
+	}
+
+	/* Advertising set should be stopped first */
+	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
+		return -EINVAL;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_ADV_SET, sizeof(*cp));
+	if (!buf) {
+		BT_WARN("No HCI buffers");
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	cp->handle = adv->handle;
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REMOVE_ADV_SET, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	adv_delete(adv);
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+#if defined(CONFIG_BT_OBSERVER)
+static bool valid_le_scan_param(const struct bt_le_scan_param *param)
+{
+	if (param->type != BT_HCI_LE_SCAN_PASSIVE &&
+	    param->type != BT_HCI_LE_SCAN_ACTIVE) {
+		return false;
+	}
+
+	if (param->options & ~(BT_LE_SCAN_OPT_FILTER_DUPLICATE |
+			       BT_LE_SCAN_OPT_FILTER_WHITELIST |
+			       BT_LE_SCAN_OPT_CODED |
+			       BT_LE_SCAN_OPT_NO_1M)) {
+		return false;
+	}
+
+	if (param->interval < 0x0004 || param->interval > 0x4000) {
+		return false;
+	}
+
+	if (param->window < 0x0004 || param->window > 0x4000) {
+		return false;
+	}
+
+	if (param->window > param->interval) {
+		return false;
+	}
+
+	return true;
+}
+
+int bt_le_scan_start(const struct bt_le_scan_param *param, bt_le_scan_cb_t cb)
+{
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	/* Check that the parameters have valid values */
+	if (!valid_le_scan_param(param)) {
+		return -EINVAL;
+	}
+
+	if (param->type && !bt_le_scan_random_addr_check()) {
+		return -EINVAL;
+	}
+
+	/* Return if active scan is already enabled */
+	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
+		return -EALREADY;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) {
+		err = set_le_scan_enable(BT_HCI_LE_SCAN_DISABLE);
+		if (err) {
+			atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
+			return err;
+		}
+	}
+
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_SCAN_FILTER_DUP,
+			  param->options & BT_LE_SCAN_OPT_FILTER_DUPLICATE);
+
+#if defined(CONFIG_BT_WHITELIST)
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_SCAN_WL,
+			  param->options & BT_LE_SCAN_OPT_FILTER_WHITELIST);
+#endif /* defined(CONFIG_BT_WHITELIST) */
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
+		struct bt_hci_ext_scan_phy param_1m;
+		struct bt_hci_ext_scan_phy param_coded;
+
+		struct bt_hci_ext_scan_phy *phy_1m = NULL;
+		struct bt_hci_ext_scan_phy *phy_coded = NULL;
+
+		if (!(param->options & BT_LE_SCAN_OPT_NO_1M)) {
+			param_1m.type = param->type;
+			param_1m.interval = sys_cpu_to_le16(param->interval);
+			param_1m.window = sys_cpu_to_le16(param->window);
+
+			phy_1m = &param_1m;
+		}
+
+		if (param->options & BT_LE_SCAN_OPT_CODED) {
+			uint16_t interval = param->interval_coded ?
+				param->interval_coded :
+				param->interval;
+			uint16_t window = param->window_coded ?
+				param->window_coded :
+				param->window;
+
+			param_coded.type = param->type;
+			param_coded.interval = sys_cpu_to_le16(interval);
+			param_coded.window = sys_cpu_to_le16(window);
+			phy_coded = &param_coded;
+		}
+
+		err = start_le_scan_ext(phy_1m, phy_coded, param->timeout);
+	} else {
+		if (param->timeout) {
+			atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
+			return -ENOTSUP;
+		}
+
+		err = start_le_scan_legacy(param->type, param->interval,
+					   param->window);
+	}
+
+	if (err) {
+		atomic_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN);
+		return err;
+	}
+
+	scan_dev_found_cb = cb;
+
+	return 0;
+}
+
+int bt_le_scan_stop(void)
+{
+	/* Return if active scanning is already disabled */
+	if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) {
+		return -EALREADY;
+	}
+
+	scan_dev_found_cb = NULL;
+
+	if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
+	    atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_SCAN_LIMITED)) {
+		atomic_clear_bit(bt_dev.flags, BT_DEV_RPA_VALID);
+
+#if defined(CONFIG_BT_SMP)
+		pending_id_keys_update();
+#endif
+	}
+
+	return bt_le_scan_update(false);
+}
+
+void bt_le_scan_cb_register(struct bt_le_scan_cb *cb)
+{
+	sys_slist_append(&scan_cbs, &cb->node);
+}
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_WHITELIST)
+int bt_le_whitelist_add(const bt_addr_le_t *addr)
+{
+	struct bt_hci_cp_le_add_dev_to_wl *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_WL, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_le_copy(&cp->addr, addr);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_WL, buf, NULL);
+	if (err) {
+		BT_ERR("Failed to add device to whitelist");
+
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_le_whitelist_rem(const bt_addr_le_t *addr)
+{
+	struct bt_hci_cp_le_rem_dev_from_wl *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_WL, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_le_copy(&cp->addr, addr);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_WL, buf, NULL);
+	if (err) {
+		BT_ERR("Failed to remove device from whitelist");
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_le_whitelist_clear(void)
+{
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_CLEAR_WL, NULL, NULL);
+	if (err) {
+		BT_ERR("Failed to clear whitelist");
+		return err;
+	}
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_WHITELIST) */
+
+int bt_le_set_chan_map(uint8_t chan_map[5])
+{
+	struct bt_hci_cp_le_set_host_chan_classif *cp;
+	struct net_buf *buf;
+
+	if (!IS_ENABLED(CONFIG_BT_CENTRAL)) {
+		return -ENOTSUP;
+	}
+
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 3)) {
+		BT_WARN("Set Host Channel Classification command is "
+			"not supported");
+		return -ENOTSUP;
+	}
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF,
+				sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	memcpy(&cp->ch_map[0], &chan_map[0], 4);
+	cp->ch_map[4] = chan_map[4] & BIT_MASK(5);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF,
+				    buf, NULL);
+}
+
+struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout)
+{
+	struct net_buf *buf;
+
+	__ASSERT(type == BT_BUF_EVT || type == BT_BUF_ACL_IN ||
+		 type == BT_BUF_ISO_IN, "Invalid buffer type requested");
+
+	if (IS_ENABLED(CONFIG_BT_ISO) && type == BT_BUF_ISO_IN) {
+		return bt_iso_get_rx(timeout);
+	}
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+	if (type == BT_BUF_EVT) {
+		buf = net_buf_alloc(&hci_rx_pool, timeout);
+	} else {
+		buf = net_buf_alloc(&acl_in_pool, timeout);
+	}
+#else
+	buf = net_buf_alloc(&hci_rx_pool, timeout);
+#endif
+
+	if (buf) {
+		net_buf_reserve(buf, BT_BUF_RESERVE);
+		bt_buf_set_type(buf, type);
+	}
+
+	return buf;
+}
+
+struct net_buf *bt_buf_get_cmd_complete(k_timeout_t timeout)
+{
+	struct net_buf *buf;
+	unsigned int key;
+
+	key = irq_lock();
+	buf = bt_dev.sent_cmd;
+	bt_dev.sent_cmd = NULL;
+	irq_unlock(key);
+
+	BT_DBG("sent_cmd %p", buf);
+
+	if (buf) {
+		bt_buf_set_type(buf, BT_BUF_EVT);
+		buf->len = 0U;
+		net_buf_reserve(buf, BT_BUF_RESERVE);
+
+		return buf;
+	}
+
+	return bt_buf_get_rx(BT_BUF_EVT, timeout);
+}
+
+struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout)
+{
+	switch (evt) {
+#if defined(CONFIG_BT_CONN)
+	case BT_HCI_EVT_NUM_COMPLETED_PACKETS:
+		{
+			struct net_buf *buf;
+
+			buf = net_buf_alloc(&num_complete_pool, timeout);
+			if (buf) {
+				net_buf_reserve(buf, BT_BUF_RESERVE);
+				bt_buf_set_type(buf, BT_BUF_EVT);
+			}
+
+			return buf;
+		}
+#endif /* CONFIG_BT_CONN */
+	case BT_HCI_EVT_CMD_COMPLETE:
+	case BT_HCI_EVT_CMD_STATUS:
+		return bt_buf_get_cmd_complete(timeout);
+	default:
+#if defined(CONFIG_BT_DISCARDABLE_BUF_COUNT)
+		if (discardable) {
+			struct net_buf *buf;
+
+			buf = net_buf_alloc(&discardable_pool, timeout);
+			if (buf) {
+				net_buf_reserve(buf, BT_BUF_RESERVE);
+				bt_buf_set_type(buf, BT_BUF_EVT);
+			}
+
+			return buf;
+		}
+#endif /* CONFIG_BT_DISCARDABLE_BUF_COUNT */
+
+		return bt_buf_get_rx(BT_BUF_EVT, timeout);
+	}
+}
+
+#if defined(CONFIG_BT_BREDR)
+static int br_start_inquiry(const struct bt_br_discovery_param *param)
+{
+	const uint8_t iac[3] = { 0x33, 0x8b, 0x9e };
+	struct bt_hci_op_inquiry *cp;
+	struct net_buf *buf;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_INQUIRY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	cp->length = param->length;
+	cp->num_rsp = 0xff; /* we limit discovery only by time */
+
+	memcpy(cp->lap, iac, 3);
+	if (param->limited) {
+		cp->lap[0] = 0x00;
+	}
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_INQUIRY, buf, NULL);
+}
+
+static bool valid_br_discov_param(const struct bt_br_discovery_param *param,
+				  size_t num_results)
+{
+	if (!num_results || num_results > 255) {
+		return false;
+	}
+
+	if (!param->length || param->length > 0x30) {
+		return false;
+	}
+
+	return true;
+}
+
+int bt_br_discovery_start(const struct bt_br_discovery_param *param,
+			  struct bt_br_discovery_result *results, size_t cnt,
+			  bt_br_discovery_cb_t cb)
+{
+	int err;
+
+	BT_DBG("");
+
+	if (!valid_br_discov_param(param, cnt)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
+		return -EALREADY;
+	}
+
+	err = br_start_inquiry(param);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit(bt_dev.flags, BT_DEV_INQUIRY);
+
+	(void)memset(results, 0, sizeof(*results) * cnt);
+
+	discovery_cb = cb;
+	discovery_results = results;
+	discovery_results_size = cnt;
+	discovery_results_count = 0;
+
+	return 0;
+}
+
+int bt_br_discovery_stop(void)
+{
+	int err;
+	int i;
+
+	BT_DBG("");
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_INQUIRY)) {
+		return -EALREADY;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_INQUIRY_CANCEL, NULL, NULL);
+	if (err) {
+		return err;
+	}
+
+	for (i = 0; i < discovery_results_count; i++) {
+		struct discovery_priv *priv;
+		struct bt_hci_cp_remote_name_cancel *cp;
+		struct net_buf *buf;
+
+		priv = (struct discovery_priv *)&discovery_results[i]._priv;
+
+		if (!priv->resolving) {
+			continue;
+		}
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_CANCEL,
+					sizeof(*cp));
+		if (!buf) {
+			continue;
+		}
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		bt_addr_copy(&cp->bdaddr, &discovery_results[i].addr);
+
+		bt_hci_cmd_send_sync(BT_HCI_OP_REMOTE_NAME_CANCEL, buf, NULL);
+	}
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_INQUIRY);
+
+	discovery_cb = NULL;
+	discovery_results = NULL;
+	discovery_results_size = 0;
+	discovery_results_count = 0;
+
+	return 0;
+}
+
+static int write_scan_enable(uint8_t scan)
+{
+	struct net_buf *buf;
+	int err;
+
+	BT_DBG("type %u", scan);
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SCAN_ENABLE, 1);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_u8(buf, scan);
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_WRITE_SCAN_ENABLE, buf, NULL);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_ISCAN,
+			  (scan & BT_BREDR_SCAN_INQUIRY));
+	atomic_set_bit_to(bt_dev.flags, BT_DEV_PSCAN,
+			  (scan & BT_BREDR_SCAN_PAGE));
+
+	return 0;
+}
+
+int bt_br_set_connectable(bool enable)
+{
+	if (enable) {
+		if (atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
+			return -EALREADY;
+		} else {
+			return write_scan_enable(BT_BREDR_SCAN_PAGE);
+		}
+	} else {
+		if (!atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
+			return -EALREADY;
+		} else {
+			return write_scan_enable(BT_BREDR_SCAN_DISABLED);
+		}
+	}
+}
+
+int bt_br_set_discoverable(bool enable)
+{
+	if (enable) {
+		if (atomic_test_bit(bt_dev.flags, BT_DEV_ISCAN)) {
+			return -EALREADY;
+		}
+
+		if (!atomic_test_bit(bt_dev.flags, BT_DEV_PSCAN)) {
+			return -EPERM;
+		}
+
+		return write_scan_enable(BT_BREDR_SCAN_INQUIRY |
+					 BT_BREDR_SCAN_PAGE);
+	} else {
+		if (!atomic_test_bit(bt_dev.flags, BT_DEV_ISCAN)) {
+			return -EALREADY;
+		}
+
+		return write_scan_enable(BT_BREDR_SCAN_PAGE);
+	}
+}
+#endif /* CONFIG_BT_BREDR */
+
+#if defined(CONFIG_BT_ECC)
+int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
+{
+	int err;
+
+	/*
+	 * We check for both "LE Read Local P-256 Public Key" and
+	 * "LE Generate DH Key" support here since both commands are needed for
+	 * ECC support. If "LE Generate DH Key" is not supported then there
+	 * is no point in reading local public key.
+	 */
+	if (!BT_CMD_TEST(bt_dev.supported_commands, 34, 1) ||
+	    !BT_CMD_TEST(bt_dev.supported_commands, 34, 2)) {
+		BT_WARN("ECC HCI commands not available");
+		return -ENOTSUP;
+	}
+
+	new_cb->_next = pub_key_cb;
+	pub_key_cb = new_cb;
+
+	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
+		return 0;
+	}
+
+	atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_P256_PUBLIC_KEY, NULL, NULL);
+	if (err) {
+		BT_ERR("Sending LE P256 Public Key command failed");
+		atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
+		pub_key_cb = NULL;
+		return err;
+	}
+
+	return 0;
+}
+
+const uint8_t *bt_pub_key_get(void)
+{
+	if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
+		return pub_key;
+	}
+
+	return NULL;
+}
+
+int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
+{
+	struct bt_hci_cp_le_generate_dhkey *cp;
+	struct net_buf *buf;
+	int err;
+
+	if (dh_key_cb || atomic_test_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
+		return -EBUSY;
+	}
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
+		return -EADDRNOTAVAIL;
+	}
+
+	dh_key_cb = cb;
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
+	if (!buf) {
+		dh_key_cb = NULL;
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	memcpy(cp->key, remote_pk, sizeof(cp->key));
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
+	if (err) {
+		dh_key_cb = NULL;
+		return err;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_ECC */
+
+#if defined(CONFIG_BT_BREDR)
+int bt_br_oob_get_local(struct bt_br_oob *oob)
+{
+	bt_addr_copy(&oob->addr, &bt_dev.id_addr[0].a);
+
+	return 0;
+}
+#endif /* CONFIG_BT_BREDR */
+
+int bt_le_oob_get_local(uint8_t id, struct bt_le_oob *oob)
+{
+	struct bt_le_ext_adv *adv;
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (id >= CONFIG_BT_ID_MAX) {
+		return -EINVAL;
+	}
+
+	adv = bt_adv_lookup_legacy();
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !(adv && adv->id == id &&
+	      atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+	      atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) &&
+	      bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) {
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+			struct bt_conn *conn;
+
+			conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, NULL,
+						       BT_CONN_CONNECT_SCAN);
+			if (conn) {
+				/* Cannot set new RPA while creating
+				 * connections.
+				 */
+				bt_conn_unref(conn);
+				return -EINVAL;
+			}
+		}
+
+		if (adv &&
+		    atomic_test_bit(adv->flags, BT_ADV_ENABLED) &&
+		    atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY) &&
+		    (bt_dev.id_addr[id].type == BT_ADDR_LE_RANDOM)) {
+			/* Cannot set a new RPA address while advertising with
+			 * random static identity address for a different
+			 * identity.
+			 */
+			return -EINVAL;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_OBSERVER) &&
+		    id != BT_ID_DEFAULT &&
+		    (atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING) ||
+		     atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING))) {
+			/* Cannot switch identity of scanner or initiator */
+			return -EINVAL;
+		}
+
+		le_rpa_invalidate();
+		le_update_private_addr();
+
+		bt_addr_le_copy(&oob->addr, &bt_dev.random_addr);
+	} else {
+		bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[id]);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data);
+		if (err && err != -ENOTSUP) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_EXT_ADV)
+int bt_le_ext_adv_oob_get_local(struct bt_le_ext_adv *adv,
+				struct bt_le_oob *oob)
+{
+	int err;
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY)) {
+		/* Don't refresh RPA addresses if the RPA is new.
+		 * This allows back to back calls to this function or
+		 * bt_le_oob_get_local to not invalidate the previously set
+		 * RPAs.
+		 */
+		if (!atomic_test_bit(adv->flags, BT_ADV_LIMITED) &&
+		    !rpa_is_new()) {
+			if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+			    atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) {
+				struct bt_conn *conn;
+
+				conn = bt_conn_lookup_state_le(
+					BT_ID_DEFAULT, NULL,
+					BT_CONN_CONNECT_SCAN);
+
+				if (conn) {
+					/* Cannot set new RPA while creating
+					 * connections.
+					 */
+					bt_conn_unref(conn);
+					return -EINVAL;
+				}
+			}
+
+			le_rpa_invalidate();
+			le_update_private_addr();
+		}
+
+		bt_addr_le_copy(&oob->addr, &adv->random_addr);
+	} else {
+		bt_addr_le_copy(&oob->addr, &bt_dev.id_addr[adv->id]);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP)) {
+		err = bt_smp_le_oob_generate_sc_data(&oob->le_sc_data);
+		if (err && err != -ENOTSUP) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+#if defined(CONFIG_BT_SMP)
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+int bt_le_oob_set_legacy_tk(struct bt_conn *conn, const uint8_t *tk)
+{
+	return bt_smp_le_oob_set_tk(conn, tk);
+}
+#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+int bt_le_oob_set_sc_data(struct bt_conn *conn,
+			  const struct bt_le_oob_sc_data *oobd_local,
+			  const struct bt_le_oob_sc_data *oobd_remote)
+{
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	return bt_smp_le_oob_set_sc_data(conn, oobd_local, oobd_remote);
+}
+
+int bt_le_oob_get_sc_data(struct bt_conn *conn,
+			  const struct bt_le_oob_sc_data **oobd_local,
+			  const struct bt_le_oob_sc_data **oobd_remote)
+{
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		return -EAGAIN;
+	}
+
+	return bt_smp_le_oob_get_sc_data(conn, oobd_local, oobd_remote);
+}
+#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */
+#endif /* defined(CONFIG_BT_SMP) */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.h	(working copy)
@@ -0,0 +1,10 @@
+/* hci_ecc.h - HCI ECC emulation */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_hci_ecc_init(void);
+int bt_hci_ecc_send(struct net_buf *buf);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_ecc.c	(working copy)
@@ -0,0 +1,328 @@
+/**
+ * @file hci_ecc.c
+ * HCI ECC emulation
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <sys/atomic.h>
+#include <debug/stack.h>
+#include <sys/byteorder.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dh.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/hci.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_hci_ecc
+#include "common/log.h"
+
+#include "hci_ecc.h"
+#ifdef CONFIG_BT_HCI_RAW
+#include <bluetooth/hci_raw.h>
+#include "hci_raw_internal.h"
+#else
+#include "hci_core.h"
+#endif
+
+static struct k_thread ecc_thread_data;
+static K_KERNEL_STACK_DEFINE(ecc_thread_stack, CONFIG_BT_HCI_ECC_STACK_SIZE);
+
+/* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
+static const uint32_t debug_private_key[8] = {
+	0xcd3c1abd, 0x5899b8a6, 0xeb40b799, 0x4aff607b, 0xd2103f50, 0x74c9b3e3,
+	0xa3c55f38, 0x3f49f6d4
+};
+
+#if defined(CONFIG_BT_USE_DEBUG_KEYS)
+static const uint8_t debug_public_key[64] = {
+	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac,
+	0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 0x8b, 0xd2, 0x89, 0x15,
+	0xd0, 0x8e, 0x1c, 0x74, 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
+	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 0x6d, 0xeb, 0x2a, 0x65,
+	0x49, 0x9c, 0x80, 0xdc
+};
+#endif
+
+enum {
+	PENDING_PUB_KEY,
+	PENDING_DHKEY,
+
+	/* Total number of flags - must be at the end of the enum */
+	NUM_FLAGS,
+};
+
+static ATOMIC_DEFINE(flags, NUM_FLAGS);
+
+static K_SEM_DEFINE(cmd_sem, 0, 1);
+
+static struct {
+	uint8_t private_key[32];
+
+	union {
+		uint8_t pk[64];
+		uint8_t dhkey[32];
+	};
+} ecc;
+
+static void send_cmd_status(uint16_t opcode, uint8_t status)
+{
+	struct bt_hci_evt_cmd_status *evt;
+	struct bt_hci_evt_hdr *hdr;
+	struct net_buf *buf;
+
+	BT_DBG("opcode %x status %x", opcode, status);
+
+	buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, false, K_FOREVER);
+	bt_buf_set_type(buf, BT_BUF_EVT);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->evt = BT_HCI_EVT_CMD_STATUS;
+	hdr->len = sizeof(*evt);
+
+	evt = net_buf_add(buf, sizeof(*evt));
+	evt->ncmd = 1U;
+	evt->opcode = sys_cpu_to_le16(opcode);
+	evt->status = status;
+
+	if (IS_ENABLED(CONFIG_BT_RECV_IS_RX_THREAD)) {
+		bt_recv_prio(buf);
+	} else {
+		bt_recv(buf);
+	}
+}
+
+static uint8_t generate_keys(void)
+{
+#if !defined(CONFIG_BT_USE_DEBUG_KEYS)
+	do {
+		int rc;
+
+		rc = uECC_make_key(ecc.pk, ecc.private_key, &curve_secp256r1);
+		if (rc == TC_CRYPTO_FAIL) {
+			BT_ERR("Failed to create ECC public/private pair");
+			return BT_HCI_ERR_UNSPECIFIED;
+		}
+
+	/* make sure generated key isn't debug key */
+	} while (memcmp(ecc.private_key, debug_private_key, 32) == 0);
+#else
+	sys_memcpy_swap(&ecc.pk, debug_public_key, 32);
+	sys_memcpy_swap(&ecc.pk[32], &debug_public_key[32], 32);
+	sys_memcpy_swap(ecc.private_key, debug_private_key, 32);
+#endif
+	return 0;
+}
+
+static void emulate_le_p256_public_key_cmd(void)
+{
+	struct bt_hci_evt_le_p256_public_key_complete *evt;
+	struct bt_hci_evt_le_meta_event *meta;
+	struct bt_hci_evt_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t status;
+
+	BT_DBG("");
+
+	status = generate_keys();
+
+	buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->evt = BT_HCI_EVT_LE_META_EVENT;
+	hdr->len = sizeof(*meta) + sizeof(*evt);
+
+	meta = net_buf_add(buf, sizeof(*meta));
+	meta->subevent = BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE;
+
+	evt = net_buf_add(buf, sizeof(*evt));
+	evt->status = status;
+
+	if (status) {
+		(void)memset(evt->key, 0, sizeof(evt->key));
+	} else {
+		/* Convert X and Y coordinates from big-endian (provided
+		 * by crypto API) to little endian HCI.
+		 */
+		sys_memcpy_swap(evt->key, ecc.pk, 32);
+		sys_memcpy_swap(&evt->key[32], &ecc.pk[32], 32);
+	}
+
+	atomic_clear_bit(flags, PENDING_PUB_KEY);
+
+	bt_recv(buf);
+}
+
+static void emulate_le_generate_dhkey(void)
+{
+	struct bt_hci_evt_le_generate_dhkey_complete *evt;
+	struct bt_hci_evt_le_meta_event *meta;
+	struct bt_hci_evt_hdr *hdr;
+	struct net_buf *buf;
+	int ret;
+
+	ret = uECC_valid_public_key(ecc.pk, &curve_secp256r1);
+	if (ret < 0) {
+		BT_ERR("public key is not valid (ret %d)", ret);
+		ret = TC_CRYPTO_FAIL;
+	} else {
+		ret = uECC_shared_secret(ecc.pk, ecc.private_key, ecc.dhkey,
+					 &curve_secp256r1);
+	}
+
+	buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->evt = BT_HCI_EVT_LE_META_EVENT;
+	hdr->len = sizeof(*meta) + sizeof(*evt);
+
+	meta = net_buf_add(buf, sizeof(*meta));
+	meta->subevent = BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE;
+
+	evt = net_buf_add(buf, sizeof(*evt));
+
+	if (ret == TC_CRYPTO_FAIL) {
+		evt->status = BT_HCI_ERR_UNSPECIFIED;
+		(void)memset(evt->dhkey, 0xff, sizeof(evt->dhkey));
+	} else {
+		evt->status = 0U;
+		/* Convert from big-endian (provided by crypto API) to
+		 * little-endian HCI.
+		 */
+		sys_memcpy_swap(evt->dhkey, ecc.dhkey, sizeof(ecc.dhkey));
+	}
+
+	atomic_clear_bit(flags, PENDING_DHKEY);
+
+	bt_recv(buf);
+}
+
+static void ecc_thread(void *p1, void *p2, void *p3)
+{
+	while (true) {
+		k_sem_take(&cmd_sem, K_FOREVER);
+
+		if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
+			emulate_le_p256_public_key_cmd();
+		} else if (atomic_test_bit(flags, PENDING_DHKEY)) {
+			emulate_le_generate_dhkey();
+		} else {
+			__ASSERT(0, "Unhandled ECC command");
+		}
+	}
+}
+
+static void clear_ecc_events(struct net_buf *buf)
+{
+	struct bt_hci_cp_le_set_event_mask *cmd;
+
+	cmd = (void *)(buf->data + sizeof(struct bt_hci_cmd_hdr));
+
+	/*
+	 * don't enable controller ECC events as those will be generated from
+	 * emulation code
+	 */
+	cmd->events[0] &= ~0x80; /* LE Read Local P-256 PKey Compl */
+	cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */
+}
+
+static void le_gen_dhkey(struct net_buf *buf)
+{
+	struct bt_hci_cp_le_generate_dhkey *cmd;
+	uint8_t status;
+
+	if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
+		status = BT_HCI_ERR_CMD_DISALLOWED;
+		goto send_status;
+	}
+
+	if (buf->len < sizeof(struct bt_hci_cp_le_generate_dhkey)) {
+		status = BT_HCI_ERR_INVALID_PARAM;
+		goto send_status;
+	}
+
+	if (atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
+		status = BT_HCI_ERR_CMD_DISALLOWED;
+		goto send_status;
+	}
+
+	cmd = (void *)buf->data;
+	/* Convert X and Y coordinates from little-endian HCI to
+	 * big-endian (expected by the crypto API).
+	 */
+	sys_memcpy_swap(ecc.pk, cmd->key, 32);
+	sys_memcpy_swap(&ecc.pk[32], &cmd->key[32], 32);
+	k_sem_give(&cmd_sem);
+	status = BT_HCI_ERR_SUCCESS;
+
+send_status:
+	net_buf_unref(buf);
+	send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, status);
+}
+
+static void le_p256_pub_key(struct net_buf *buf)
+{
+	uint8_t status;
+
+	net_buf_unref(buf);
+
+	if (atomic_test_bit(flags, PENDING_DHKEY)) {
+		status = BT_HCI_ERR_CMD_DISALLOWED;
+	} else if (atomic_test_and_set_bit(flags, PENDING_PUB_KEY)) {
+		status = BT_HCI_ERR_CMD_DISALLOWED;
+	} else {
+		k_sem_give(&cmd_sem);
+		status = BT_HCI_ERR_SUCCESS;
+	}
+
+	send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, status);
+}
+
+int bt_hci_ecc_send(struct net_buf *buf)
+{
+	if (bt_buf_get_type(buf) == BT_BUF_CMD) {
+		struct bt_hci_cmd_hdr *chdr = (void *)buf->data;
+
+		switch (sys_le16_to_cpu(chdr->opcode)) {
+		case BT_HCI_OP_LE_P256_PUBLIC_KEY:
+			net_buf_pull(buf, sizeof(*chdr));
+			le_p256_pub_key(buf);
+			return 0;
+		case BT_HCI_OP_LE_GENERATE_DHKEY:
+			net_buf_pull(buf, sizeof(*chdr));
+			le_gen_dhkey(buf);
+			return 0;
+		case BT_HCI_OP_LE_SET_EVENT_MASK:
+			clear_ecc_events(buf);
+			break;
+		default:
+			break;
+		}
+	}
+
+	return bt_dev.drv->send(buf);
+}
+
+int default_CSPRNG(uint8_t *dst, unsigned int len)
+{
+	return !bt_rand(dst, len);
+}
+
+void bt_hci_ecc_init(void)
+{
+	k_thread_create(&ecc_thread_data, ecc_thread_stack,
+			K_KERNEL_STACK_SIZEOF(ecc_thread_stack), ecc_thread,
+			NULL, NULL, NULL, K_PRIO_PREEMPT(10), 0, K_NO_WAIT);
+	k_thread_name_set(&ecc_thread_data, "BT ECC");
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw.c	(working copy)
@@ -0,0 +1,375 @@
+/* hci_userchan.c - HCI user channel Bluetooth handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+
+#include <drivers/bluetooth/hci_driver.h>
+#include <bluetooth/hci_raw.h>
+#include <bluetooth/l2cap.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_hci_raw
+#include "common/log.h"
+
+#include "hci_ecc.h"
+#include "monitor.h"
+#include "hci_raw_internal.h"
+
+#define H4_CMD 0x01
+#define H4_ACL 0x02
+#define H4_SCO 0x03
+#define H4_EVT 0x04
+#define H4_ISO 0x05
+
+static struct k_fifo *raw_rx;
+
+#if defined(CONFIG_BT_HCI_RAW_H4_ENABLE)
+static uint8_t raw_mode = BT_HCI_RAW_MODE_H4;
+#else
+static uint8_t raw_mode;
+#endif
+
+NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, CONFIG_BT_RX_BUF_COUNT,
+			  BT_BUF_RX_SIZE, NULL);
+NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_HCI_CMD_COUNT,
+			  BT_BUF_RX_SIZE, NULL);
+NET_BUF_POOL_FIXED_DEFINE(hci_acl_pool, BT_HCI_ACL_COUNT,
+			  BT_BUF_ACL_SIZE, NULL);
+#if defined(CONFIG_BT_ISO)
+NET_BUF_POOL_FIXED_DEFINE(hci_iso_pool, BT_ISO_TX_BUF_COUNT,
+			  BT_ISO_TX_MTU, NULL);
+#endif
+
+struct bt_dev_raw bt_dev;
+struct bt_hci_raw_cmd_ext *cmd_ext;
+static size_t cmd_ext_size;
+
+int bt_hci_driver_register(const struct bt_hci_driver *drv)
+{
+	if (bt_dev.drv) {
+		return -EALREADY;
+	}
+
+	if (!drv->open || !drv->send) {
+		return -EINVAL;
+	}
+
+	bt_dev.drv = drv;
+
+	BT_DBG("Registered %s", drv->name ? drv->name : "");
+
+	bt_monitor_new_index(BT_MONITOR_TYPE_PRIMARY, drv->bus,
+			     BT_ADDR_ANY, drv->name ? drv->name : "bt0");
+
+	return 0;
+}
+
+struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout)
+{
+	struct net_buf *buf;
+
+	switch (type) {
+	case BT_BUF_EVT:
+	case BT_BUF_ACL_IN:
+		break;
+	default:
+		BT_ERR("Invalid type: %u", type);
+		return NULL;
+	}
+
+	buf = net_buf_alloc(&hci_rx_pool, timeout);
+	if (!buf) {
+		return buf;
+	}
+
+	net_buf_reserve(buf, BT_BUF_RESERVE);
+	bt_buf_set_type(buf, type);
+
+	return buf;
+}
+
+struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout,
+			      const void *data, size_t size)
+{
+	struct net_buf_pool *pool;
+	struct net_buf *buf;
+
+	switch (type) {
+	case BT_BUF_CMD:
+		pool = &hci_cmd_pool;
+		break;
+	case BT_BUF_ACL_OUT:
+		pool = &hci_acl_pool;
+		break;
+#if defined(CONFIG_BT_ISO)
+	case BT_BUF_ISO_OUT:
+		pool = &hci_iso_pool;
+		break;
+#endif
+	case BT_BUF_H4:
+		if (IS_ENABLED(CONFIG_BT_HCI_RAW_H4) &&
+		    raw_mode == BT_HCI_RAW_MODE_H4) {
+			switch (((uint8_t *)data)[0]) {
+			case H4_CMD:
+				type = BT_BUF_CMD;
+				pool = &hci_cmd_pool;
+				break;
+			case H4_ACL:
+				type = BT_BUF_ACL_OUT;
+				pool = &hci_acl_pool;
+				break;
+#if defined(CONFIG_BT_ISO)
+			case H4_ISO:
+				type = BT_BUF_ISO_OUT;
+				pool = &hci_iso_pool;
+#endif
+			default:
+				LOG_ERR("Unknown H4 type %u", type);
+				return NULL;
+			}
+
+			/* Adjust data pointer to discard the header */
+			data = (uint8_t *)data + 1;
+			size--;
+			break;
+		}
+		__fallthrough;
+	default:
+		BT_ERR("Invalid type: %u", type);
+		return NULL;
+	}
+
+	buf = net_buf_alloc(pool, timeout);
+	if (!buf) {
+		return buf;
+	}
+
+	net_buf_reserve(buf, BT_BUF_RESERVE);
+	bt_buf_set_type(buf, type);
+
+	if (data && size) {
+		net_buf_add_mem(buf, data, size);
+	}
+
+	return buf;
+}
+
+struct net_buf *bt_buf_get_cmd_complete(k_timeout_t timeout)
+{
+	return bt_buf_get_rx(BT_BUF_EVT, timeout);
+}
+
+struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout)
+{
+	return bt_buf_get_rx(BT_BUF_EVT, timeout);
+}
+
+int bt_recv(struct net_buf *buf)
+{
+	BT_DBG("buf %p len %u", buf, buf->len);
+
+	bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
+
+	if (IS_ENABLED(CONFIG_BT_HCI_RAW_H4) &&
+	    raw_mode == BT_HCI_RAW_MODE_H4) {
+		switch (bt_buf_get_type(buf)) {
+		case BT_BUF_EVT:
+			net_buf_push_u8(buf, H4_EVT);
+			break;
+		case BT_BUF_ACL_IN:
+			net_buf_push_u8(buf, H4_ACL);
+			break;
+		case BT_BUF_ISO_IN:
+			if (IS_ENABLED(CONFIG_BT_ISO)) {
+				net_buf_push_u8(buf, H4_ISO);
+				break;
+			}
+			__fallthrough;
+		default:
+			BT_ERR("Unknown type %u", bt_buf_get_type(buf));
+			return -EINVAL;
+		}
+	}
+
+	/* Queue to RAW rx queue */
+	net_buf_put(raw_rx, buf);
+
+	return 0;
+}
+
+int bt_recv_prio(struct net_buf *buf)
+{
+	if (bt_buf_get_type(buf) == BT_BUF_EVT) {
+		struct bt_hci_evt_hdr *hdr = (void *)buf->data;
+		uint8_t evt_flags = bt_hci_evt_get_flags(hdr->evt);
+
+		if ((evt_flags & BT_HCI_EVT_FLAG_RECV_PRIO) &&
+		    (evt_flags & BT_HCI_EVT_FLAG_RECV)) {
+			/* Avoid queuing the event twice */
+			return 0;
+		}
+	}
+
+	return bt_recv(buf);
+}
+
+static void bt_cmd_complete_ext(uint16_t op, uint8_t status)
+{
+	struct net_buf *buf;
+	struct bt_hci_evt_cc_status *cc;
+
+	if (status == BT_HCI_ERR_EXT_HANDLED) {
+		return;
+	}
+
+	buf = bt_hci_cmd_complete_create(op, sizeof(*cc));
+	cc = net_buf_add(buf, sizeof(*cc));
+	cc->status = status;
+
+	bt_recv(buf);
+}
+
+static uint8_t bt_send_ext(struct net_buf *buf)
+{
+	struct bt_hci_cmd_hdr *hdr;
+	struct net_buf_simple_state state;
+	int i;
+	uint16_t op;
+	uint8_t status;
+
+	status = BT_HCI_ERR_SUCCESS;
+
+	if (!cmd_ext) {
+		return status;
+	}
+
+	net_buf_simple_save(&buf->b, &state);
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("No HCI Command header");
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	if (buf->len < hdr->param_len) {
+		BT_ERR("Invalid HCI CMD packet length");
+		return BT_HCI_ERR_INVALID_PARAM;
+	}
+
+	op = sys_le16_to_cpu(hdr->opcode);
+
+	for (i = 0; i < cmd_ext_size; i++) {
+		struct bt_hci_raw_cmd_ext *cmd = &cmd_ext[i];
+
+		if (cmd->op == op) {
+			if (buf->len < cmd->min_len) {
+				status = BT_HCI_ERR_INVALID_PARAM;
+			} else {
+				status = cmd->func(buf);
+			}
+
+			break;
+		}
+	}
+
+	if (status) {
+		bt_cmd_complete_ext(op, status);
+		return status;
+	}
+
+	net_buf_simple_restore(&buf->b, &state);
+
+	return status;
+}
+
+int bt_send(struct net_buf *buf)
+{
+	BT_DBG("buf %p len %u", buf, buf->len);
+
+	bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len);
+
+	if (IS_ENABLED(CONFIG_BT_HCI_RAW_CMD_EXT) &&
+	    bt_buf_get_type(buf) == BT_BUF_CMD) {
+		uint8_t status;
+
+		status = bt_send_ext(buf);
+		if (status) {
+			return status;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
+		return bt_hci_ecc_send(buf);
+	}
+
+	return bt_dev.drv->send(buf);
+}
+
+int bt_hci_raw_set_mode(uint8_t mode)
+{
+	BT_DBG("mode %u", mode);
+
+	if (IS_ENABLED(CONFIG_BT_HCI_RAW_H4)) {
+		switch (mode) {
+		case BT_HCI_RAW_MODE_PASSTHROUGH:
+		case BT_HCI_RAW_MODE_H4:
+			raw_mode = mode;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+uint8_t bt_hci_raw_get_mode(void)
+{
+	if (IS_ENABLED(CONFIG_BT_HCI_RAW_H4)) {
+		return raw_mode;
+	}
+
+	return BT_HCI_RAW_MODE_PASSTHROUGH;
+}
+
+void bt_hci_raw_cmd_ext_register(struct bt_hci_raw_cmd_ext *cmds, size_t size)
+{
+	if (IS_ENABLED(CONFIG_BT_HCI_RAW_CMD_EXT)) {
+		cmd_ext = cmds;
+		cmd_ext_size = size;
+	}
+}
+
+int bt_enable_raw(struct k_fifo *rx_queue)
+{
+	const struct bt_hci_driver *drv = bt_dev.drv;
+	int err;
+
+	BT_DBG("");
+
+	raw_rx = rx_queue;
+
+	if (!bt_dev.drv) {
+		BT_ERR("No HCI driver registered");
+		return -ENODEV;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_TINYCRYPT_ECC)) {
+		bt_hci_ecc_init();
+	}
+
+	err = drv->open();
+	if (err) {
+		BT_ERR("HCI driver open failed (%d)", err);
+		return err;
+	}
+
+	BT_INFO("Bluetooth enabled in RAW mode");
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hci_raw_internal.h	(working copy)
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __BT_HCI_RAW_INTERNAL_H
+#define __BT_HCI_RAW_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_dev_raw {
+	/* Registered HCI driver */
+	const struct bt_hci_driver *drv;
+};
+
+extern struct bt_dev_raw bt_dev;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BT_HCI_RAW_INTERNAL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_hf.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_hf.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_hf.c	(working copy)
@@ -0,0 +1,707 @@
+/* hfp_hf.c - Hands free Profile - Handsfree side handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <zephyr.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <sys/printk.h>
+
+#include <bluetooth/conn.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HFP_HF)
+#define LOG_MODULE_NAME bt_hfp_hf
+#include "common/log.h"
+
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/hfp_hf.h>
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "rfcomm_internal.h"
+#include "at.h"
+#include "hfp_internal.h"
+
+#define MAX_IND_STR_LEN 17
+
+struct bt_hfp_hf_cb *bt_hf;
+
+NET_BUF_POOL_FIXED_DEFINE(hf_pool, CONFIG_BT_MAX_CONN + 1,
+			  BT_RFCOMM_BUF_SIZE(BT_HF_CLIENT_MAX_PDU), NULL);
+
+static struct bt_hfp_hf bt_hfp_hf_pool[CONFIG_BT_MAX_CONN];
+
+/* The order should follow the enum hfp_hf_ag_indicators */
+static const struct {
+	char *name;
+	uint32_t min;
+	uint32_t max;
+} ag_ind[] = {
+	{"service", 0, 1}, /* HF_SERVICE_IND */
+	{"call", 0, 1}, /* HF_CALL_IND */
+	{"callsetup", 0, 3}, /* HF_CALL_SETUP_IND */
+	{"callheld", 0, 2}, /* HF_CALL_HELD_IND */
+	{"signal", 0, 5}, /* HF_SINGNAL_IND */
+	{"roam", 0, 1}, /* HF_ROAM_IND */
+	{"battchg", 0, 5} /* HF_BATTERY_IND */
+};
+
+void hf_slc_error(struct at_client *hf_at)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	int err;
+
+	BT_ERR("SLC error: disconnecting");
+	err = bt_rfcomm_dlc_disconnect(&hf->rfcomm_dlc);
+	if (err) {
+		BT_ERR("Rfcomm: Unable to disconnect :%d", -err);
+	}
+}
+
+int hfp_hf_send_cmd(struct bt_hfp_hf *hf, at_resp_cb_t resp,
+		    at_finish_cb_t finish, const char *format, ...)
+{
+	struct net_buf *buf;
+	va_list vargs;
+	int ret;
+
+	/* register the callbacks */
+	at_register(&hf->at, resp, finish);
+
+	buf = bt_rfcomm_create_pdu(&hf_pool);
+	if (!buf) {
+		BT_ERR("No Buffers!");
+		return -ENOMEM;
+	}
+
+	va_start(vargs, format);
+	ret = vsnprintk(buf->data, (net_buf_tailroom(buf) - 1), format, vargs);
+	if (ret < 0) {
+		BT_ERR("Unable to format variable arguments");
+		return ret;
+	}
+	va_end(vargs);
+
+	net_buf_add(buf, ret);
+	net_buf_add_u8(buf, '\r');
+
+	ret = bt_rfcomm_dlc_send(&hf->rfcomm_dlc, buf);
+	if (ret < 0) {
+		BT_ERR("Rfcomm send error :(%d)", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int brsf_handle(struct at_client *hf_at)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	uint32_t val;
+	int ret;
+
+	ret = at_get_number(hf_at, &val);
+	if (ret < 0) {
+		BT_ERR("Error getting value");
+		return ret;
+	}
+
+	hf->ag_features = val;
+
+	return 0;
+}
+
+int brsf_resp(struct at_client *hf_at, struct net_buf *buf)
+{
+	int err;
+
+	BT_DBG("");
+
+	err = at_parse_cmd_input(hf_at, buf, "BRSF", brsf_handle,
+				 AT_CMD_TYPE_NORMAL);
+	if (err < 0) {
+		/* Returning negative value is avoided before SLC connection
+		 * established.
+		 */
+		BT_ERR("Error parsing CMD input");
+		hf_slc_error(hf_at);
+	}
+
+	return 0;
+}
+
+static void cind_handle_values(struct at_client *hf_at, uint32_t index,
+			       char *name, uint32_t min, uint32_t max)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	int i;
+
+	BT_DBG("index: %u, name: %s, min: %u, max:%u", index, name, min, max);
+
+	for (i = 0; i < ARRAY_SIZE(ag_ind); i++) {
+		if (strcmp(name, ag_ind[i].name) != 0) {
+			continue;
+		}
+		if (min != ag_ind[i].min || max != ag_ind[i].max) {
+			BT_ERR("%s indicator min/max value not matching", name);
+		}
+
+		hf->ind_table[index] = i;
+		break;
+	}
+}
+
+int cind_handle(struct at_client *hf_at)
+{
+	uint32_t index = 0U;
+
+	/* Parsing Example: CIND: ("call",(0,1)) etc.. */
+	while (at_has_next_list(hf_at)) {
+		char name[MAX_IND_STR_LEN];
+		uint32_t min, max;
+
+		if (at_open_list(hf_at) < 0) {
+			BT_ERR("Could not get open list");
+			goto error;
+		}
+
+		if (at_list_get_string(hf_at, name, sizeof(name)) < 0) {
+			BT_ERR("Could not get string");
+			goto error;
+		}
+
+		if (at_open_list(hf_at) < 0) {
+			BT_ERR("Could not get open list");
+			goto error;
+		}
+
+		if (at_list_get_range(hf_at, &min, &max) < 0) {
+			BT_ERR("Could not get range");
+			goto error;
+		}
+
+		if (at_close_list(hf_at) < 0) {
+			BT_ERR("Could not get close list");
+			goto error;
+		}
+
+		if (at_close_list(hf_at) < 0) {
+			BT_ERR("Could not get close list");
+			goto error;
+		}
+
+		cind_handle_values(hf_at, index, name, min, max);
+		index++;
+	}
+
+	return 0;
+error:
+	BT_ERR("Error on CIND response");
+	hf_slc_error(hf_at);
+	return -EINVAL;
+}
+
+int cind_resp(struct at_client *hf_at, struct net_buf *buf)
+{
+	int err;
+
+	err = at_parse_cmd_input(hf_at, buf, "CIND", cind_handle,
+				 AT_CMD_TYPE_NORMAL);
+	if (err < 0) {
+		BT_ERR("Error parsing CMD input");
+		hf_slc_error(hf_at);
+	}
+
+	return 0;
+}
+
+void ag_indicator_handle_values(struct at_client *hf_at, uint32_t index,
+				uint32_t value)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
+
+	BT_DBG("Index :%u, Value :%u", index, value);
+
+	if (index >= ARRAY_SIZE(ag_ind)) {
+		BT_ERR("Max only %lu indicators are supported",
+		       ARRAY_SIZE(ag_ind));
+		return;
+	}
+
+	if (value > ag_ind[hf->ind_table[index]].max ||
+	    value < ag_ind[hf->ind_table[index]].min) {
+		BT_ERR("Indicators out of range - value: %u", value);
+		return;
+	}
+
+	switch (hf->ind_table[index]) {
+	case HF_SERVICE_IND:
+		if (bt_hf->service) {
+			bt_hf->service(conn, value);
+		}
+		break;
+	case HF_CALL_IND:
+		if (bt_hf->call) {
+			bt_hf->call(conn, value);
+		}
+		break;
+	case HF_CALL_SETUP_IND:
+		if (bt_hf->call_setup) {
+			bt_hf->call_setup(conn, value);
+		}
+		break;
+	case HF_CALL_HELD_IND:
+		if (bt_hf->call_held) {
+			bt_hf->call_held(conn, value);
+		}
+		break;
+	case HF_SINGNAL_IND:
+		if (bt_hf->signal) {
+			bt_hf->signal(conn, value);
+		}
+		break;
+	case HF_ROAM_IND:
+		if (bt_hf->roam) {
+			bt_hf->roam(conn, value);
+		}
+		break;
+	case HF_BATTERY_IND:
+		if (bt_hf->battery) {
+			bt_hf->battery(conn, value);
+		}
+		break;
+	default:
+		BT_ERR("Unknown AG indicator");
+		break;
+	}
+}
+
+int cind_status_handle(struct at_client *hf_at)
+{
+	uint32_t index = 0U;
+
+	while (at_has_next_list(hf_at)) {
+		uint32_t value;
+		int ret;
+
+		ret = at_get_number(hf_at, &value);
+		if (ret < 0) {
+			BT_ERR("could not get the value");
+			return ret;
+		}
+
+		ag_indicator_handle_values(hf_at, index, value);
+
+		index++;
+	}
+
+	return 0;
+}
+
+int cind_status_resp(struct at_client *hf_at, struct net_buf *buf)
+{
+	int err;
+
+	err = at_parse_cmd_input(hf_at, buf, "CIND", cind_status_handle,
+				 AT_CMD_TYPE_NORMAL);
+	if (err < 0) {
+		BT_ERR("Error parsing CMD input");
+		hf_slc_error(hf_at);
+	}
+
+	return 0;
+}
+
+int ciev_handle(struct at_client *hf_at)
+{
+	uint32_t index, value;
+	int ret;
+
+	ret = at_get_number(hf_at, &index);
+	if (ret < 0) {
+		BT_ERR("could not get the Index");
+		return ret;
+	}
+	/* The first element of the list shall have 1 */
+	if (!index) {
+		BT_ERR("Invalid index value '0'");
+		return 0;
+	}
+
+	ret = at_get_number(hf_at, &value);
+	if (ret < 0) {
+		BT_ERR("could not get the value");
+		return ret;
+	}
+
+	ag_indicator_handle_values(hf_at, (index - 1), value);
+
+	return 0;
+}
+
+int ring_handle(struct at_client *hf_at)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
+
+	if (bt_hf->ring_indication) {
+		bt_hf->ring_indication(conn);
+	}
+
+	return 0;
+}
+
+static const struct unsolicited {
+	const char *cmd;
+	enum at_cmd_type type;
+	int (*func)(struct at_client *hf_at);
+} handlers[] = {
+	{ "CIEV", AT_CMD_TYPE_UNSOLICITED, ciev_handle },
+	{ "RING", AT_CMD_TYPE_OTHER, ring_handle }
+};
+
+static const struct unsolicited *hfp_hf_unsol_lookup(struct at_client *hf_at)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+		if (!strncmp(hf_at->buf, handlers[i].cmd,
+			     strlen(handlers[i].cmd))) {
+			return &handlers[i];
+		}
+	}
+
+	return NULL;
+}
+
+int unsolicited_cb(struct at_client *hf_at, struct net_buf *buf)
+{
+	const struct unsolicited *handler;
+
+	handler = hfp_hf_unsol_lookup(hf_at);
+	if (!handler) {
+		BT_ERR("Unhandled unsolicited response");
+		return -ENOMSG;
+	}
+
+	if (!at_parse_cmd_input(hf_at, buf, handler->cmd, handler->func,
+				handler->type)) {
+		return 0;
+	}
+
+	return -ENOMSG;
+}
+
+int cmd_complete(struct at_client *hf_at, enum at_result result,
+	       enum at_cme cme_err)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
+	struct bt_hfp_hf_cmd_complete cmd = { 0 };
+
+	BT_DBG("");
+
+	switch (result) {
+	case AT_RESULT_OK:
+		cmd.type = HFP_HF_CMD_OK;
+		break;
+	case AT_RESULT_ERROR:
+		cmd.type = HFP_HF_CMD_ERROR;
+		break;
+	case AT_RESULT_CME_ERROR:
+		cmd.type = HFP_HF_CMD_CME_ERROR;
+		cmd.cme = cme_err;
+		break;
+	default:
+		BT_ERR("Unknown error code");
+		cmd.type = HFP_HF_CMD_UNKNOWN_ERROR;
+		break;
+	}
+
+	if (bt_hf->cmd_complete_cb) {
+		bt_hf->cmd_complete_cb(conn, &cmd);
+	}
+
+	return 0;
+}
+
+int cmee_finish(struct at_client *hf_at, enum at_result result,
+		enum at_cme cme_err)
+{
+	if (result != AT_RESULT_OK) {
+		BT_ERR("SLC Connection ERROR in response");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void slc_completed(struct at_client *hf_at)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
+
+	if (bt_hf->connected) {
+		bt_hf->connected(conn);
+	}
+
+	if (hfp_hf_send_cmd(hf, NULL, cmee_finish, "AT+CMEE=1") < 0) {
+		BT_ERR("Error Sending AT+CMEE");
+	}
+}
+
+int cmer_finish(struct at_client *hf_at, enum at_result result,
+		enum at_cme cme_err)
+{
+	if (result != AT_RESULT_OK) {
+		BT_ERR("SLC Connection ERROR in response");
+		hf_slc_error(hf_at);
+		return -EINVAL;
+	}
+
+	slc_completed(hf_at);
+
+	return 0;
+}
+
+int cind_status_finish(struct at_client *hf_at, enum at_result result,
+		       enum at_cme cme_err)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	int err;
+
+	if (result != AT_RESULT_OK) {
+		BT_ERR("SLC Connection ERROR in response");
+		hf_slc_error(hf_at);
+		return -EINVAL;
+	}
+
+	at_register_unsolicited(hf_at, unsolicited_cb);
+	err = hfp_hf_send_cmd(hf, NULL, cmer_finish, "AT+CMER=3,0,0,1");
+	if (err < 0) {
+		hf_slc_error(hf_at);
+		return err;
+	}
+
+	return 0;
+}
+
+int cind_finish(struct at_client *hf_at, enum at_result result,
+		enum at_cme cme_err)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	int err;
+
+	if (result != AT_RESULT_OK) {
+		BT_ERR("SLC Connection ERROR in response");
+		hf_slc_error(hf_at);
+		return -EINVAL;
+	}
+
+	err = hfp_hf_send_cmd(hf, cind_status_resp, cind_status_finish,
+			      "AT+CIND?");
+	if (err < 0) {
+		hf_slc_error(hf_at);
+		return err;
+	}
+
+	return 0;
+}
+
+int brsf_finish(struct at_client *hf_at, enum at_result result,
+		enum at_cme cme_err)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
+	int err;
+
+	if (result != AT_RESULT_OK) {
+		BT_ERR("SLC Connection ERROR in response");
+		hf_slc_error(hf_at);
+		return -EINVAL;
+	}
+
+	err = hfp_hf_send_cmd(hf, cind_resp, cind_finish, "AT+CIND=?");
+	if (err < 0) {
+		hf_slc_error(hf_at);
+		return err;
+	}
+
+	return 0;
+}
+
+int hf_slc_establish(struct bt_hfp_hf *hf)
+{
+	int err;
+
+	BT_DBG("");
+
+	err = hfp_hf_send_cmd(hf, brsf_resp, brsf_finish, "AT+BRSF=%u",
+			      hf->hf_features);
+	if (err < 0) {
+		hf_slc_error(&hf->at);
+		return err;
+	}
+
+	return 0;
+}
+
+static struct bt_hfp_hf *bt_hfp_hf_lookup_bt_conn(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
+		struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
+
+		if (hf->rfcomm_dlc.session->br_chan.chan.conn == conn) {
+			return hf;
+		}
+	}
+
+	return NULL;
+}
+
+int bt_hfp_hf_send_cmd(struct bt_conn *conn, enum bt_hfp_hf_at_cmd cmd)
+{
+	struct bt_hfp_hf *hf;
+	int err;
+
+	BT_DBG("");
+
+	if (!conn) {
+		BT_ERR("Invalid connection");
+		return -ENOTCONN;
+	}
+
+	hf = bt_hfp_hf_lookup_bt_conn(conn);
+	if (!hf) {
+		BT_ERR("No HF connection found");
+		return -ENOTCONN;
+	}
+
+	switch (cmd) {
+	case BT_HFP_HF_ATA:
+		err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "ATA");
+		if (err < 0) {
+			BT_ERR("Failed ATA");
+			return err;
+		}
+		break;
+	case BT_HFP_HF_AT_CHUP:
+		err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "AT+CHUP");
+		if (err < 0) {
+			BT_ERR("Failed AT+CHUP");
+			return err;
+		}
+		break;
+	default:
+		BT_ERR("Invalid AT Command");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void hfp_hf_connected(struct bt_rfcomm_dlc *dlc)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(dlc, struct bt_hfp_hf, rfcomm_dlc);
+
+	BT_DBG("hf connected");
+
+	BT_ASSERT(hf);
+	hf_slc_establish(hf);
+}
+
+static void hfp_hf_disconnected(struct bt_rfcomm_dlc *dlc)
+{
+	struct bt_conn *conn = dlc->session->br_chan.chan.conn;
+
+	BT_DBG("hf disconnected!");
+	if (bt_hf->disconnected) {
+		bt_hf->disconnected(conn);
+	}
+}
+
+static void hfp_hf_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
+{
+	struct bt_hfp_hf *hf = CONTAINER_OF(dlc, struct bt_hfp_hf, rfcomm_dlc);
+
+	if (at_parse_input(&hf->at, buf) < 0) {
+		BT_ERR("Parsing failed");
+	}
+}
+
+static int bt_hfp_hf_accept(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc)
+{
+	int i;
+	static struct bt_rfcomm_dlc_ops ops = {
+		.connected = hfp_hf_connected,
+		.disconnected = hfp_hf_disconnected,
+		.recv = hfp_hf_recv,
+	};
+
+	BT_DBG("conn %p", conn);
+
+	for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
+		struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
+		int j;
+
+		if (hf->rfcomm_dlc.session) {
+			continue;
+		}
+
+		hf->at.buf = hf->hf_buffer;
+		hf->at.buf_max_len = HF_MAX_BUF_LEN;
+
+		hf->rfcomm_dlc.ops = &ops;
+		hf->rfcomm_dlc.mtu = BT_HFP_MAX_MTU;
+
+		*dlc = &hf->rfcomm_dlc;
+
+		/* Set the supported features*/
+		hf->hf_features = BT_HFP_HF_SUPPORTED_FEATURES;
+
+		for (j = 0; j < HF_MAX_AG_INDICATORS; j++) {
+			hf->ind_table[j] = -1;
+		}
+
+		return 0;
+	}
+
+	BT_ERR("Unable to establish HF connection (%p)", conn);
+
+	return -ENOMEM;
+}
+
+static void hfp_hf_init(void)
+{
+	static struct bt_rfcomm_server chan = {
+		.channel = BT_RFCOMM_CHAN_HFP_HF,
+		.accept = bt_hfp_hf_accept,
+	};
+
+	bt_rfcomm_server_register(&chan);
+}
+
+int bt_hfp_hf_register(struct bt_hfp_hf_cb *cb)
+{
+	if (!cb) {
+		return -EINVAL;
+	}
+
+	if (bt_hf) {
+		return -EALREADY;
+	}
+
+	bt_hf = cb;
+
+	hfp_hf_init();
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/hfp_internal.h	(working copy)
@@ -0,0 +1,64 @@
+/** @file
+ *  @brief Internal APIs for Bluetooth Handsfree profile handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_HFP_MAX_MTU           140
+#define BT_HF_CLIENT_MAX_PDU     BT_HFP_MAX_MTU
+
+/* HFP AG Features */
+#define BT_HFP_AG_FEATURE_3WAY_CALL     0x00000001 /* Three-way calling */
+#define BT_HFP_AG_FEATURE_ECNR          0x00000002 /* EC and/or NR function */
+#define BT_HFP_AG_FEATURE_VOICE_RECG    0x00000004 /* Voice recognition */
+#define BT_HFP_AG_INBAND_RING_TONE      0x00000008 /* In-band ring capability */
+#define BT_HFP_AG_VOICE_TAG             0x00000010 /* Attach no. to voice tag */
+#define BT_HFP_AG_FEATURE_REJECT_CALL   0x00000020 /* Ability to reject call */
+#define BT_HFP_AG_FEATURE_ECS           0x00000040 /* Enhanced call status */
+#define BT_HFP_AG_FEATURE_ECC           0x00000080 /* Enhanced call control */
+#define BT_HFP_AG_FEATURE_EXT_ERR       0x00000100 /* Extented error codes */
+#define BT_HFP_AG_FEATURE_CODEC_NEG     0x00000200 /* Codec negotiation */
+#define BT_HFP_AG_FEATURE_HF_IND        0x00000400 /* HF Indicators */
+#define BT_HFP_AG_FEARTURE_ESCO_S4      0x00000800 /* eSCO S4 Settings */
+
+/* HFP HF Features */
+#define BT_HFP_HF_FEATURE_ECNR          0x00000001 /* EC and/or NR */
+#define BT_HFP_HF_FEATURE_3WAY_CALL     0x00000002 /* Three-way calling */
+#define BT_HFP_HF_FEATURE_CLI           0x00000004 /* CLI presentation */
+#define BT_HFP_HF_FEATURE_VOICE_RECG    0x00000008 /* Voice recognition */
+#define BT_HFP_HF_FEATURE_VOLUME        0x00000010 /* Remote volume control */
+#define BT_HFP_HF_FEATURE_ECS           0x00000020 /* Enhanced call status */
+#define BT_HFP_HF_FEATURE_ECC           0x00000040 /* Enhanced call control */
+#define BT_HFP_HF_FEATURE_CODEC_NEG     0x00000080 /* CODEC Negotiation */
+#define BT_HFP_HF_FEATURE_HF_IND        0x00000100 /* HF Indicators */
+#define BT_HFP_HF_FEATURE_ESCO_S4       0x00000200 /* eSCO S4 Settings */
+
+/* HFP HF Supported features */
+#define BT_HFP_HF_SUPPORTED_FEATURES    (BT_HFP_HF_FEATURE_CLI | \
+					 BT_HFP_HF_FEATURE_VOLUME)
+
+#define HF_MAX_BUF_LEN                  BT_HF_CLIENT_MAX_PDU
+#define HF_MAX_AG_INDICATORS            20
+
+struct bt_hfp_hf {
+	struct bt_rfcomm_dlc rfcomm_dlc;
+	char hf_buffer[HF_MAX_BUF_LEN];
+	struct at_client at;
+	uint32_t hf_features;
+	uint32_t ag_features;
+	int8_t ind_table[HF_MAX_AG_INDICATORS];
+};
+
+enum hfp_hf_ag_indicators {
+	HF_SERVICE_IND,
+	HF_CALL_IND,
+	HF_CALL_SETUP_IND,
+	HF_CALL_HELD_IND,
+	HF_SINGNAL_IND,
+	HF_ROAM_IND,
+	HF_BATTERY_IND
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.h	(working copy)
@@ -0,0 +1,126 @@
+/* keys.h - Bluetooth key handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+enum {
+	BT_KEYS_SLAVE_LTK      = BIT(0),
+	BT_KEYS_IRK            = BIT(1),
+	BT_KEYS_LTK            = BIT(2),
+	BT_KEYS_LOCAL_CSRK     = BIT(3),
+	BT_KEYS_REMOTE_CSRK    = BIT(4),
+	BT_KEYS_LTK_P256       = BIT(5),
+
+	BT_KEYS_ALL            = (BT_KEYS_SLAVE_LTK | BT_KEYS_IRK | \
+				  BT_KEYS_LTK | BT_KEYS_LOCAL_CSRK | \
+				  BT_KEYS_REMOTE_CSRK | BT_KEYS_LTK_P256),
+};
+
+enum {
+	BT_KEYS_ID_PENDING_ADD  = BIT(0),
+	BT_KEYS_ID_PENDING_DEL  = BIT(1),
+	BT_KEYS_ID_ADDED        = BIT(2),
+};
+
+enum {
+	BT_KEYS_AUTHENTICATED   = BIT(0),
+	BT_KEYS_DEBUG           = BIT(1),
+	/* Bit 2 and 3 might accidentally exist in old stored keys */
+	BT_KEYS_SC              = BIT(4),
+};
+
+struct bt_ltk {
+	uint8_t                    rand[8];
+	uint8_t                    ediv[2];
+	uint8_t                    val[16];
+};
+
+struct bt_irk {
+	uint8_t                    val[16];
+	bt_addr_t               rpa;
+};
+
+struct bt_csrk {
+	uint8_t                    val[16];
+	uint32_t                   cnt;
+};
+
+struct bt_keys {
+	uint8_t                    id;
+	bt_addr_le_t            addr;
+	uint8_t                    state;
+	uint8_t                    storage_start[0] __aligned(sizeof(void *));
+	uint8_t                    enc_size;
+	uint8_t                    flags;
+	uint16_t                   keys;
+	struct bt_ltk           ltk;
+	struct bt_irk           irk;
+#if defined(CONFIG_BT_SIGNING)
+	struct bt_csrk          local_csrk;
+	struct bt_csrk          remote_csrk;
+#endif /* BT_SIGNING */
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	struct bt_ltk           slave_ltk;
+#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
+#if (defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST))
+	uint32_t                   aging_counter;
+#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+};
+
+#define BT_KEYS_STORAGE_LEN     (sizeof(struct bt_keys) - \
+				 offsetof(struct bt_keys, storage_start))
+
+void bt_keys_foreach(int type, void (*func)(struct bt_keys *keys, void *data),
+		     void *data);
+
+struct bt_keys *bt_keys_get_addr(uint8_t id, const bt_addr_le_t *addr);
+struct bt_keys *bt_keys_get_type(int type, uint8_t id, const bt_addr_le_t *addr);
+struct bt_keys *bt_keys_find(int type, uint8_t id, const bt_addr_le_t *addr);
+struct bt_keys *bt_keys_find_irk(uint8_t id, const bt_addr_le_t *addr);
+struct bt_keys *bt_keys_find_addr(uint8_t id, const bt_addr_le_t *addr);
+
+void bt_keys_add_type(struct bt_keys *keys, int type);
+void bt_keys_clear(struct bt_keys *keys);
+
+#if defined(CONFIG_BT_SETTINGS)
+int bt_keys_store(struct bt_keys *keys);
+#else
+static inline int bt_keys_store(struct bt_keys *keys)
+{
+	return 0;
+}
+#endif
+
+enum {
+	BT_LINK_KEY_AUTHENTICATED  = BIT(0),
+	BT_LINK_KEY_DEBUG          = BIT(1),
+	BT_LINK_KEY_SC             = BIT(2),
+};
+
+struct bt_keys_link_key {
+	bt_addr_t               addr;
+	uint8_t                 storage_start[0]  __aligned(sizeof(void *));
+	uint8_t                 flags;
+	uint8_t                 val[16];
+#if (defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST))
+	uint32_t                aging_counter;
+#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+};
+#define BT_KEYS_LINK_KEY_STORAGE_LEN     (sizeof(struct bt_keys_link_key) - \
+	offsetof(struct bt_keys_link_key, storage_start))
+
+struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr);
+struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr);
+void bt_keys_link_key_clear(struct bt_keys_link_key *link_key);
+void bt_keys_link_key_clear_addr(const bt_addr_t *addr);
+void bt_keys_link_key_store(struct bt_keys_link_key *link_key);
+
+
+/* This function is used to signal that the key has been used for paring */
+/* It updates the aging counter and saves it to flash if configuration option */
+/* BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING is enabled */
+void bt_keys_update_usage(uint8_t id, const bt_addr_le_t *addr);
+void bt_keys_link_key_update_usage(const bt_addr_t *addr);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys.c	(working copy)
@@ -0,0 +1,437 @@
+/* keys.c - Bluetooth key handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/hci.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_KEYS)
+#define LOG_MODULE_NAME bt_keys
+#include "common/log.h"
+
+#include "common/rpa.h"
+#include "gatt_internal.h"
+#include "hci_core.h"
+#include "smp.h"
+#include "settings.h"
+#include "keys.h"
+
+static struct bt_keys key_pool[CONFIG_BT_MAX_PAIRED];
+
+#define BT_KEYS_STORAGE_LEN_COMPAT (BT_KEYS_STORAGE_LEN - sizeof(uint32_t))
+
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+static uint32_t aging_counter_val;
+static struct bt_keys *last_keys_updated;
+#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+
+struct bt_keys *bt_keys_get_addr(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct bt_keys *keys;
+	int i;
+	size_t first_free_slot = ARRAY_SIZE(key_pool);
+
+	BT_DBG("%s", bt_addr_le_str(addr));
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		keys = &key_pool[i];
+
+		if (keys->id == id && !bt_addr_le_cmp(&keys->addr, addr)) {
+			return keys;
+		}
+
+		if (first_free_slot == ARRAY_SIZE(key_pool) &&
+		    !bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) {
+			first_free_slot = i;
+		}
+	}
+
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+	if (first_free_slot == ARRAY_SIZE(key_pool)) {
+		struct bt_keys *oldest = &key_pool[0];
+		bt_addr_le_t oldest_addr;
+
+		for (i = 1; i < ARRAY_SIZE(key_pool); i++) {
+			struct bt_keys *current = &key_pool[i];
+
+			if (current->aging_counter < oldest->aging_counter) {
+				oldest = current;
+			}
+		}
+
+		/* Use a copy as bt_unpair will clear the oldest key. */
+		bt_addr_le_copy(&oldest_addr, &oldest->addr);
+		bt_unpair(oldest->id, &oldest_addr);
+		if (!bt_addr_le_cmp(&oldest->addr, BT_ADDR_LE_ANY)) {
+			first_free_slot = oldest - &key_pool[0];
+		}
+	}
+
+#endif  /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+	if (first_free_slot < ARRAY_SIZE(key_pool)) {
+		keys = &key_pool[first_free_slot];
+		keys->id = id;
+		bt_addr_le_copy(&keys->addr, addr);
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+		keys->aging_counter = ++aging_counter_val;
+		last_keys_updated = keys;
+#endif  /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+		BT_DBG("created %p for %s", keys, bt_addr_le_str(addr));
+		return keys;
+	}
+
+	BT_DBG("unable to create keys for %s", bt_addr_le_str(addr));
+
+	return NULL;
+}
+
+void bt_foreach_bond(uint8_t id, void (*func)(const struct bt_bond_info *info,
+					   void *user_data),
+		     void *user_data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		struct bt_keys *keys = &key_pool[i];
+
+		if (keys->keys && keys->id == id) {
+			struct bt_bond_info info;
+
+			bt_addr_le_copy(&info.addr, &keys->addr);
+			func(&info, user_data);
+		}
+	}
+}
+
+void bt_keys_foreach(int type, void (*func)(struct bt_keys *keys, void *data),
+		     void *data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		if ((key_pool[i].keys & type)) {
+			func(&key_pool[i], data);
+		}
+	}
+}
+
+struct bt_keys *bt_keys_find(int type, uint8_t id, const bt_addr_le_t *addr)
+{
+	int i;
+
+	BT_DBG("type %d %s", type, bt_addr_le_str(addr));
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		if ((key_pool[i].keys & type) && key_pool[i].id == id &&
+		    !bt_addr_le_cmp(&key_pool[i].addr, addr)) {
+			return &key_pool[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_keys *bt_keys_get_type(int type, uint8_t id, const bt_addr_le_t *addr)
+{
+	struct bt_keys *keys;
+
+	BT_DBG("type %d %s", type, bt_addr_le_str(addr));
+
+	keys = bt_keys_find(type, id, addr);
+	if (keys) {
+		return keys;
+	}
+
+	keys = bt_keys_get_addr(id, addr);
+	if (!keys) {
+		return NULL;
+	}
+
+	bt_keys_add_type(keys, type);
+
+	return keys;
+}
+
+struct bt_keys *bt_keys_find_irk(uint8_t id, const bt_addr_le_t *addr)
+{
+	int i;
+
+	BT_DBG("%s", bt_addr_le_str(addr));
+
+	if (!bt_addr_le_is_rpa(addr)) {
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		if (!(key_pool[i].keys & BT_KEYS_IRK)) {
+			continue;
+		}
+
+		if (key_pool[i].id == id &&
+		    !bt_addr_cmp(&addr->a, &key_pool[i].irk.rpa)) {
+			BT_DBG("cached RPA %s for %s",
+			       bt_addr_str(&key_pool[i].irk.rpa),
+			       bt_addr_le_str(&key_pool[i].addr));
+			return &key_pool[i];
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		if (!(key_pool[i].keys & BT_KEYS_IRK)) {
+			continue;
+		}
+
+		if (key_pool[i].id != id) {
+			continue;
+		}
+
+		if (bt_rpa_irk_matches(key_pool[i].irk.val, &addr->a)) {
+			BT_DBG("RPA %s matches %s",
+			       bt_addr_str(&key_pool[i].irk.rpa),
+			       bt_addr_le_str(&key_pool[i].addr));
+
+			bt_addr_copy(&key_pool[i].irk.rpa, &addr->a);
+
+			return &key_pool[i];
+		}
+	}
+
+	BT_DBG("No IRK for %s", bt_addr_le_str(addr));
+
+	return NULL;
+}
+
+struct bt_keys *bt_keys_find_addr(uint8_t id, const bt_addr_le_t *addr)
+{
+	int i;
+
+	BT_DBG("%s", bt_addr_le_str(addr));
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		if (key_pool[i].id == id &&
+		    !bt_addr_le_cmp(&key_pool[i].addr, addr)) {
+			return &key_pool[i];
+		}
+	}
+
+	return NULL;
+}
+
+void bt_keys_add_type(struct bt_keys *keys, int type)
+{
+	keys->keys |= type;
+}
+
+void bt_keys_clear(struct bt_keys *keys)
+{
+	BT_DBG("%s (keys 0x%04x)", bt_addr_le_str(&keys->addr), keys->keys);
+
+	if (keys->state & BT_KEYS_ID_ADDED) {
+		bt_id_del(keys);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		char key[BT_SETTINGS_KEY_MAX];
+
+		/* Delete stored keys from flash */
+		if (keys->id) {
+			char id[4];
+
+			u8_to_dec(id, sizeof(id), keys->id);
+			bt_settings_encode_key(key, sizeof(key), "keys",
+					       &keys->addr, id);
+		} else {
+			bt_settings_encode_key(key, sizeof(key), "keys",
+					       &keys->addr, NULL);
+		}
+
+		BT_DBG("Deleting key %s", log_strdup(key));
+		settings_delete(key);
+	}
+
+	(void)memset(keys, 0, sizeof(*keys));
+}
+
+#if defined(CONFIG_BT_SETTINGS)
+int bt_keys_store(struct bt_keys *keys)
+{
+	char key[BT_SETTINGS_KEY_MAX];
+	int err;
+
+	if (keys->id) {
+		char id[4];
+
+		u8_to_dec(id, sizeof(id), keys->id);
+		bt_settings_encode_key(key, sizeof(key), "keys", &keys->addr,
+				       id);
+	} else {
+		bt_settings_encode_key(key, sizeof(key), "keys", &keys->addr,
+				       NULL);
+	}
+
+	err = settings_save_one(key, keys->storage_start, BT_KEYS_STORAGE_LEN);
+	if (err) {
+		BT_ERR("Failed to save keys (err %d)", err);
+		return err;
+	}
+
+	BT_DBG("Stored keys for %s (%s)", bt_addr_le_str(&keys->addr),
+	       log_strdup(key));
+
+	return 0;
+}
+
+static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		    void *cb_arg)
+{
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+	uint8_t id;
+	ssize_t len;
+	int err;
+	char val[BT_KEYS_STORAGE_LEN];
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -EINVAL;
+	}
+
+	len = read_cb(cb_arg, val, sizeof(val));
+	if (len < 0) {
+		BT_ERR("Failed to read value (err %zd)", len);
+		return -EINVAL;
+	}
+
+	BT_DBG("name %s val %s", log_strdup(name),
+	       (len) ? bt_hex(val, sizeof(val)) : "(null)");
+
+	err = bt_settings_decode_key(name, &addr);
+	if (err) {
+		BT_ERR("Unable to decode address %s", name);
+		return -EINVAL;
+	}
+
+	settings_name_next(name, &next);
+
+	if (!next) {
+		id = BT_ID_DEFAULT;
+	} else {
+		id = strtol(next, NULL, 10);
+	}
+
+	if (!len) {
+		keys = bt_keys_find(BT_KEYS_ALL, id, &addr);
+		if (keys) {
+			(void)memset(keys, 0, sizeof(*keys));
+			BT_DBG("Cleared keys for %s", bt_addr_le_str(&addr));
+		} else {
+			BT_WARN("Unable to find deleted keys for %s",
+				bt_addr_le_str(&addr));
+		}
+
+		return 0;
+	}
+
+	keys = bt_keys_get_addr(id, &addr);
+	if (!keys) {
+		BT_ERR("Failed to allocate keys for %s", bt_addr_le_str(&addr));
+		return -ENOMEM;
+	}
+	if (len != BT_KEYS_STORAGE_LEN) {
+		do {
+			/* Load shorter structure for compatibility with old
+			 * records format with no counter.
+			 */
+			if (IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST) &&
+			    len == BT_KEYS_STORAGE_LEN_COMPAT) {
+				BT_WARN("Keys for %s have no aging counter",
+					bt_addr_le_str(&addr));
+				memcpy(keys->storage_start, val, len);
+				continue;
+			}
+
+			BT_ERR("Invalid key length %zd != %zu", len,
+			       BT_KEYS_STORAGE_LEN);
+			bt_keys_clear(keys);
+
+			return -EINVAL;
+		} while (0);
+	} else {
+		memcpy(keys->storage_start, val, len);
+	}
+
+	BT_DBG("Successfully restored keys for %s", bt_addr_le_str(&addr));
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+	if (aging_counter_val < keys->aging_counter) {
+		aging_counter_val = keys->aging_counter;
+	}
+#endif  /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+	return 0;
+}
+
+static void id_add(struct bt_keys *keys, void *user_data)
+{
+	bt_id_add(keys);
+}
+
+static int keys_commit(void)
+{
+	BT_DBG("");
+
+	/* We do this in commit() rather than add() since add() may get
+	 * called multiple times for the same address, especially if
+	 * the keys were already removed.
+	 */
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) && IS_ENABLED(CONFIG_BT_PRIVACY)) {
+		bt_keys_foreach(BT_KEYS_ALL, id_add, NULL);
+	} else {
+		bt_keys_foreach(BT_KEYS_IRK, id_add, NULL);
+	}
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_keys, "bt/keys", NULL, keys_set, keys_commit,
+			       NULL);
+
+#endif /* CONFIG_BT_SETTINGS */
+
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+void bt_keys_update_usage(uint8_t id, const bt_addr_le_t *addr)
+{
+	struct bt_keys *keys = bt_keys_find_addr(id, addr);
+
+	if (!keys) {
+		return;
+	}
+
+	if (last_keys_updated == keys) {
+		return;
+	}
+
+	keys->aging_counter = ++aging_counter_val;
+	last_keys_updated = keys;
+
+	BT_DBG("Aging counter for %s is set to %u", bt_addr_le_str(addr),
+	       keys->aging_counter);
+
+	if (IS_ENABLED(CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING)) {
+		bt_keys_store(keys);
+	}
+}
+
+#endif  /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys_br.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys_br.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/keys_br.c	(working copy)
@@ -0,0 +1,239 @@
+/* keys_br.c - Bluetooth BR/EDR key handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/hci.h>
+#include <settings/settings.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_KEYS)
+#define LOG_MODULE_NAME bt_keys_br
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "settings.h"
+#include "keys.h"
+
+static struct bt_keys_link_key key_pool[CONFIG_BT_MAX_PAIRED];
+
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+static uint32_t aging_counter_val;
+static struct bt_keys_link_key *last_keys_updated;
+#endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+
+struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr)
+{
+	struct bt_keys_link_key *key;
+	int i;
+
+	BT_DBG("%s", bt_addr_str(addr));
+
+	for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+		key = &key_pool[i];
+
+		if (!bt_addr_cmp(&key->addr, addr)) {
+			return key;
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_keys_link_key *bt_keys_get_link_key(const bt_addr_t *addr)
+{
+	struct bt_keys_link_key *key;
+
+	key = bt_keys_find_link_key(addr);
+	if (key) {
+		return key;
+	}
+
+	key = bt_keys_find_link_key(BT_ADDR_ANY);
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+	if (!key) {
+		int i;
+
+		key = &key_pool[0];
+		for (i = 1; i < ARRAY_SIZE(key_pool); i++) {
+			struct bt_keys_link_key *current = &key_pool[i];
+
+			if (current->aging_counter < key->aging_counter) {
+				key = current;
+			}
+		}
+
+		if (key) {
+			bt_keys_link_key_clear(key);
+		}
+	}
+#endif
+
+	if (key) {
+		bt_addr_copy(&key->addr, addr);
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+		key->aging_counter = ++aging_counter_val;
+		last_keys_updated = key;
+#endif
+		BT_DBG("created %p for %s", key, bt_addr_str(addr));
+		return key;
+	}
+
+	BT_DBG("unable to create keys for %s", bt_addr_str(addr));
+
+	return NULL;
+}
+
+void bt_keys_link_key_clear(struct bt_keys_link_key *link_key)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		char key[BT_SETTINGS_KEY_MAX];
+		bt_addr_le_t le_addr;
+
+		le_addr.type = BT_ADDR_LE_PUBLIC;
+		bt_addr_copy(&le_addr.a, &link_key->addr);
+		bt_settings_encode_key(key, sizeof(key), "link_key",
+				       &le_addr, NULL);
+		settings_delete(key);
+	}
+
+	BT_DBG("%s", bt_addr_str(&link_key->addr));
+	(void)memset(link_key, 0, sizeof(*link_key));
+}
+
+void bt_keys_link_key_clear_addr(const bt_addr_t *addr)
+{
+	int i;
+	struct bt_keys_link_key *key;
+
+	if (!addr) {
+		for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
+			key = &key_pool[i];
+			bt_keys_link_key_clear(key);
+		}
+		return;
+	}
+
+	key = bt_keys_find_link_key(addr);
+	if (key) {
+		bt_keys_link_key_clear(key);
+	}
+}
+
+void bt_keys_link_key_store(struct bt_keys_link_key *link_key)
+{
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		int err;
+		char key[BT_SETTINGS_KEY_MAX];
+		bt_addr_le_t le_addr;
+
+		le_addr.type = BT_ADDR_LE_PUBLIC;
+		bt_addr_copy(&le_addr.a, &link_key->addr);
+		bt_settings_encode_key(key, sizeof(key), "link_key",
+				       &le_addr, NULL);
+
+		err = settings_save_one(key, link_key->storage_start,
+					BT_KEYS_LINK_KEY_STORAGE_LEN);
+		if (err) {
+			BT_ERR("Failed to svae link key (err %d)", err);
+		}
+	}
+}
+
+#if defined(CONFIG_BT_SETTINGS)
+
+static int link_key_set(const char *name, size_t len_rd,
+			settings_read_cb read_cb, void *cb_arg)
+{
+	int err;
+	ssize_t len;
+	bt_addr_le_t le_addr;
+	struct bt_keys_link_key *link_key;
+	char val[BT_KEYS_LINK_KEY_STORAGE_LEN];
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -EINVAL;
+	}
+
+	len = read_cb(cb_arg, val, sizeof(val));
+	if (len < 0) {
+		BT_ERR("Failed to read value (err %zu)", len);
+		return -EINVAL;
+	}
+
+	BT_DBG("name %s val %s", log_strdup(name),
+	       len ? bt_hex(val, sizeof(val)) : "(null)");
+
+	err = bt_settings_decode_key(name, &le_addr);
+	if (err) {
+		BT_ERR("Unable to decode address %s", name);
+		return -EINVAL;
+	}
+
+	link_key = bt_keys_get_link_key(&le_addr.a);
+	if (len != BT_KEYS_LINK_KEY_STORAGE_LEN) {
+		if (link_key) {
+			bt_keys_link_key_clear(link_key);
+			BT_DBG("Clear keys for %s", bt_addr_le_str(&le_addr));
+		} else {
+			BT_WARN("Unable to find deleted keys for %s",
+				bt_addr_le_str(&le_addr));
+		}
+
+		return 0;
+	}
+
+	memcpy(link_key->storage_start, val, len);
+	BT_DBG("Successfully restored link key for %s",
+	       bt_addr_le_str(&le_addr));
+#if IS_ENABLED(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
+	if (aging_counter_val < link_key->aging_counter) {
+		aging_counter_val = link_key->aging_counter;
+	}
+#endif  /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */
+
+	return 0;
+}
+
+static int link_key_commit(void)
+{
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_link_key, "bt/link_key", NULL, link_key_set,
+			       link_key_commit, NULL);
+
+void bt_keys_link_key_update_usage(const bt_addr_t *addr)
+{
+	struct bt_keys_link_key *link_key = bt_keys_find_link_key(addr);
+
+	if (!link_key) {
+		return;
+	}
+
+	if (last_keys_updated == link_key) {
+		return;
+	}
+
+	link_key->aging_counter = ++aging_counter_val;
+	last_keys_updated = link_key;
+
+	BT_DBG("Aging counter for %s is set to %u", bt_addr_str(addr),
+	       link_key->aging_counter);
+
+	if (IS_ENABLED(CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING)) {
+		bt_keys_link_key_store(link_key);
+	}
+}
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap.c	(working copy)
@@ -0,0 +1,2594 @@
+/* l2cap.c - L2CAP handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_L2CAP)
+#define LOG_MODULE_NAME bt_l2cap
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+
+#define LE_CHAN_RTX(_w) CONTAINER_OF(_w, struct bt_l2cap_le_chan, chan.rtx_work)
+#define CHAN_RX(_w) CONTAINER_OF(_w, struct bt_l2cap_le_chan, rx_work)
+
+#define L2CAP_LE_MIN_MTU		23
+#define L2CAP_ECRED_MIN_MTU		64
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+#define L2CAP_LE_MAX_CREDITS		(CONFIG_BT_ACL_RX_COUNT - 1)
+#else
+#define L2CAP_LE_MAX_CREDITS		(CONFIG_BT_RX_BUF_COUNT - 1)
+#endif
+
+#define L2CAP_LE_CID_DYN_START	0x0040
+#define L2CAP_LE_CID_DYN_END	0x007f
+#define L2CAP_LE_CID_IS_DYN(_cid) \
+	(_cid >= L2CAP_LE_CID_DYN_START && _cid <= L2CAP_LE_CID_DYN_END)
+
+#define L2CAP_LE_PSM_FIXED_START 0x0001
+#define L2CAP_LE_PSM_FIXED_END   0x007f
+#define L2CAP_LE_PSM_DYN_START   0x0080
+#define L2CAP_LE_PSM_DYN_END     0x00ff
+#define L2CAP_LE_PSM_IS_DYN(_psm) \
+	(_psm >= L2CAP_LE_PSM_DYN_START && _psm <= L2CAP_LE_PSM_DYN_END)
+
+#define L2CAP_CONN_TIMEOUT	K_SECONDS(40)
+#define L2CAP_DISC_TIMEOUT	K_SECONDS(2)
+#define L2CAP_RTX_TIMEOUT	K_SECONDS(2)
+
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+/* Dedicated pool for disconnect buffers so they are guaranteed to be send
+ * even in case of data congestion due to flooding.
+ */
+NET_BUF_POOL_FIXED_DEFINE(disc_pool, 1,
+			  BT_L2CAP_BUF_SIZE(
+				sizeof(struct bt_l2cap_disconn_req)),
+			  NULL);
+
+#define L2CAP_MAX_LE_MPS	CONFIG_BT_L2CAP_RX_MTU
+/* For now use MPS - SDU length to disable segmentation */
+#define L2CAP_MAX_LE_MTU	(L2CAP_MAX_LE_MPS - 2)
+
+#define L2CAP_ECRED_CHAN_MAX	5
+
+#define l2cap_lookup_ident(conn, ident) __l2cap_lookup_ident(conn, ident, false)
+#define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true)
+
+struct data_sent {
+	uint16_t len;
+};
+
+#define data_sent(buf) ((struct data_sent *)net_buf_user_data(buf))
+
+static sys_slist_t servers;
+
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+/* L2CAP signalling channel specific context */
+struct bt_l2cap {
+	/* The channel this context is associated with */
+	struct bt_l2cap_le_chan	chan;
+};
+
+static struct bt_l2cap bt_l2cap_pool[CONFIG_BT_MAX_CONN];
+
+static uint8_t get_ident(void)
+{
+	static uint8_t ident;
+
+	ident++;
+	/* handle integer overflow (0 is not valid) */
+	if (!ident) {
+		ident++;
+	}
+
+	return ident;
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
+						     struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	uint16_t cid;
+
+	/*
+	 * No action needed if there's already a CID allocated, e.g. in
+	 * the case of a fixed channel.
+	 */
+	if (ch->rx.cid > 0) {
+		return ch;
+	}
+
+	for (cid = L2CAP_LE_CID_DYN_START; cid <= L2CAP_LE_CID_DYN_END; cid++) {
+		if (!bt_l2cap_le_lookup_rx_cid(conn, cid)) {
+			ch->rx.cid = cid;
+			return ch;
+		}
+	}
+
+	return NULL;
+}
+
+static struct bt_l2cap_le_chan *
+__l2cap_lookup_ident(struct bt_conn *conn, uint16_t ident, bool remove)
+{
+	struct bt_l2cap_chan *chan;
+	sys_snode_t *prev = NULL;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (chan->ident == ident) {
+			if (remove) {
+				sys_slist_remove(&conn->channels, prev,
+						 &chan->node);
+			}
+			return BT_L2CAP_LE_CHAN(chan);
+		}
+
+		prev = &chan->node;
+	}
+
+	return NULL;
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *ch)
+{
+	struct bt_l2cap_chan *chan;
+	sys_snode_t *prev = NULL;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (chan == ch) {
+			sys_slist_remove(&conn->channels, prev, &chan->node);
+			return;
+		}
+
+		prev = &chan->node;
+	}
+}
+
+const char *bt_l2cap_chan_state_str(bt_l2cap_chan_state_t state)
+{
+	switch (state) {
+	case BT_L2CAP_DISCONNECTED:
+		return "disconnected";
+	case BT_L2CAP_CONNECT:
+		return "connect";
+	case BT_L2CAP_CONFIG:
+		return "config";
+	case BT_L2CAP_CONNECTED:
+		return "connected";
+	case BT_L2CAP_DISCONNECT:
+		return "disconnect";
+	default:
+		return "unknown";
+	}
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+#if defined(CONFIG_BT_DEBUG_L2CAP)
+void bt_l2cap_chan_set_state_debug(struct bt_l2cap_chan *chan,
+				   bt_l2cap_chan_state_t state,
+				   const char *func, int line)
+{
+	BT_DBG("chan %p psm 0x%04x %s -> %s", chan, chan->psm,
+	       bt_l2cap_chan_state_str(chan->state),
+	       bt_l2cap_chan_state_str(state));
+
+	/* check transitions validness */
+	switch (state) {
+	case BT_L2CAP_DISCONNECTED:
+		/* regardless of old state always allows this state */
+		break;
+	case BT_L2CAP_CONNECT:
+		if (chan->state != BT_L2CAP_DISCONNECTED) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_L2CAP_CONFIG:
+		if (chan->state != BT_L2CAP_CONNECT) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_L2CAP_CONNECTED:
+		if (chan->state != BT_L2CAP_CONFIG &&
+		    chan->state != BT_L2CAP_CONNECT) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	case BT_L2CAP_DISCONNECT:
+		if (chan->state != BT_L2CAP_CONFIG &&
+		    chan->state != BT_L2CAP_CONNECTED) {
+			BT_WARN("%s()%d: invalid transition", func, line);
+		}
+		break;
+	default:
+		BT_ERR("%s()%d: unknown (%u) state was set", func, line, state);
+		return;
+	}
+
+	chan->state = state;
+}
+#else
+void bt_l2cap_chan_set_state(struct bt_l2cap_chan *chan,
+			     bt_l2cap_chan_state_t state)
+{
+	chan->state = state;
+}
+#endif /* CONFIG_BT_DEBUG_L2CAP */
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+void bt_l2cap_chan_del(struct bt_l2cap_chan *chan)
+{
+	const struct bt_l2cap_chan_ops *ops = chan->ops;
+
+	BT_DBG("conn %p chan %p", chan->conn, chan);
+
+	if (!chan->conn) {
+		goto destroy;
+	}
+
+	if (ops->disconnected) {
+		ops->disconnected(chan);
+	}
+
+	chan->conn = NULL;
+
+destroy:
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	/* Reset internal members of common channel */
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_DISCONNECTED);
+	chan->psm = 0U;
+#endif
+	if (chan->destroy) {
+		chan->destroy(chan);
+	}
+
+	if (ops->released) {
+		ops->released(chan);
+	}
+}
+
+static void l2cap_rtx_timeout(struct k_work *work)
+{
+	struct bt_l2cap_le_chan *chan = NULL;//LE_CHAN_RTX(work);
+	struct bt_conn *conn = chan->chan.conn;
+
+	BT_ERR("chan %p timeout", chan);
+
+	bt_l2cap_chan_remove(conn, &chan->chan);
+	bt_l2cap_chan_del(&chan->chan);
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	/* Remove other channels if pending on the same ident */
+	while ((chan = l2cap_remove_ident(conn, chan->chan.ident))) {
+		bt_l2cap_chan_del(&chan->chan);
+	}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
+			       struct net_buf *buf);
+
+static void l2cap_rx_process(struct k_work *work)
+{
+	struct bt_l2cap_le_chan *ch = CHAN_RX(work);
+	struct net_buf *buf;
+
+	while ((buf = net_buf_get(&ch->rx_queue, K_NO_WAIT))) {
+		BT_DBG("ch %p buf %p", ch, buf);
+		l2cap_chan_le_recv(ch, buf);
+		net_buf_unref(buf);
+	}
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+		       bt_l2cap_chan_destroy_t destroy)
+{
+	/* Attach channel to the connection */
+	sys_slist_append(&conn->channels, &chan->node);
+	chan->conn = conn;
+	chan->destroy = destroy;
+
+	BT_DBG("conn %p chan %p", conn, chan);
+}
+
+static bool l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			   bt_l2cap_chan_destroy_t destroy)
+{
+	struct bt_l2cap_le_chan *ch;
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	ch = l2cap_chan_alloc_cid(conn, chan);
+#else
+	ch = BT_L2CAP_LE_CHAN(chan);
+#endif
+
+	if (!ch) {
+		BT_ERR("Unable to allocate L2CAP CID");
+		return false;
+	}
+
+	//k_delayed_work_init(&chan->rtx_work, l2cap_rtx_timeout);
+	atomic_clear(chan->status);
+
+	bt_l2cap_chan_add(conn, chan, destroy);
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	if (L2CAP_LE_CID_IS_DYN(ch->rx.cid)) {
+		k_work_init(&ch->rx_work, l2cap_rx_process);
+		k_fifo_init(&ch->rx_queue);
+		bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECT);
+	}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+	return true;
+}
+
+void bt_l2cap_connected(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+
+	BT_DBG("bt_l2cap_connected %p", conn);
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		bt_l2cap_br_connected(conn);
+		return;
+	}
+
+	Z_STRUCT_SECTION_FOREACH_NEW(bt_l2cap_fixed_chan, fchan, CONFIG_BT_L2CAP_FIXED_CHAN_SIZE) {
+		struct bt_l2cap_le_chan *ch;
+        //fchan = (struct bt_l2cap_fixed_chan*)0x10011b60;
+        BT_DBG("bt_l2cap_connected1 %p", fchan);
+
+        BT_DBG("bt_l2cap_connected2, cid: %d, accept: %p, des: %p"
+            , fchan->cid, fchan->accept, fchan->destroy);
+
+		if (fchan->accept(conn, &chan) < 0)
+        {
+            continue;
+        }
+        BT_DBG("bt_l2cap_connected3 %p", fchan->accept);
+
+		ch = BT_L2CAP_LE_CHAN(chan);
+
+		/* Fill up remaining fixed channel context attached in
+		 * fchan->accept()
+		 */
+		ch->rx.cid = fchan->cid;
+		ch->tx.cid = fchan->cid;
+
+		if (!l2cap_chan_add(conn, chan, fchan->destroy)) {
+			return;
+		}
+
+		if (chan->ops->connected) {
+			chan->ops->connected(chan);
+		}
+
+		/* Always set output status to fixed channels */
+		atomic_set_bit(chan->status, BT_L2CAP_STATUS_OUT);
+
+		if (chan->ops->status) {
+			chan->ops->status(chan, chan->status);
+		}
+	}
+
+}
+
+void bt_l2cap_disconnected(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan, *next;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->channels, chan, next, node) {
+		bt_l2cap_chan_del(chan);
+	}
+}
+
+static struct net_buf *l2cap_create_le_sig_pdu(struct net_buf *buf,
+					       uint8_t code, uint8_t ident,
+					       uint16_t len)
+{
+	struct bt_l2cap_sig_hdr *hdr;
+	struct net_buf_pool *pool = NULL;
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	if (code == BT_L2CAP_DISCONN_REQ) {
+		pool = &disc_pool;
+	}
+#endif
+	/* Don't wait more than the minimum RTX timeout of 2 seconds */
+	buf = bt_l2cap_create_pdu_timeout(pool, 0, L2CAP_RTX_TIMEOUT);
+	if (!buf) {
+		/* If it was not possible to allocate a buffer within the
+		 * timeout return NULL.
+		 */
+		BT_ERR("Unable to allocate buffer for op 0x%02x", code);
+		return NULL;
+	}
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = code;
+	hdr->ident = ident;
+	hdr->len = sys_cpu_to_le16(len);
+
+	return buf;
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static void l2cap_chan_send_req(struct bt_l2cap_chan *chan,
+				struct net_buf *buf, k_timeout_t timeout)
+{
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part A] page 126:
+	 *
+	 * The value of this timer is implementation-dependent but the minimum
+	 * initial value is 1 second and the maximum initial value is 60
+	 * seconds. One RTX timer shall exist for each outstanding signaling
+	 * request, including each Echo Request. The timer disappears on the
+	 * final expiration, when the response is received, or the physical
+	 * link is lost.
+	 */
+	k_delayed_work_submit(&chan->rtx_work, timeout);
+
+	bt_l2cap_send(chan->conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch)
+{
+	struct net_buf *buf;
+	struct bt_l2cap_le_conn_req *req;
+
+	ch->chan.ident = get_ident();
+
+	buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_LE_CONN_REQ,
+				      ch->chan.ident, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->psm = sys_cpu_to_le16(ch->chan.psm);
+	req->scid = sys_cpu_to_le16(ch->rx.cid);
+	req->mtu = sys_cpu_to_le16(ch->rx.mtu);
+	req->mps = sys_cpu_to_le16(ch->rx.mps);
+	req->credits = sys_cpu_to_le16(ch->rx.init_credits);
+
+	l2cap_chan_send_req(&ch->chan, buf, L2CAP_CONN_TIMEOUT);
+
+	return 0;
+}
+
+static int l2cap_ecred_conn_req(struct bt_l2cap_chan **chan, int channels)
+{
+	struct net_buf *buf;
+	struct bt_l2cap_ecred_conn_req *req;
+	struct bt_l2cap_le_chan *ch;
+	int i;
+	uint8_t ident;
+
+	if (!chan || !channels) {
+		return -EINVAL;
+	}
+
+	ident = get_ident();
+
+	buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_ECRED_CONN_REQ, ident,
+				      sizeof(*req) +
+				      (channels * sizeof(uint16_t)));
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	ch = BT_L2CAP_LE_CHAN(chan[0]);
+
+	/* Init common parameters */
+	req->psm = sys_cpu_to_le16(ch->chan.psm);
+	req->mtu = sys_cpu_to_le16(ch->rx.mtu);
+	req->mps = sys_cpu_to_le16(ch->rx.mps);
+	req->credits = sys_cpu_to_le16(ch->rx.init_credits);
+
+	for (i = 0; i < channels; i++) {
+		ch = BT_L2CAP_LE_CHAN(chan[i]);
+
+		ch->chan.ident = ident;
+
+		net_buf_add_le16(buf, ch->rx.cid);
+	}
+
+	l2cap_chan_send_req(*chan, buf, L2CAP_CONN_TIMEOUT);
+
+	return 0;
+}
+
+static void l2cap_le_encrypt_change(struct bt_l2cap_chan *chan, uint8_t status)
+{
+	int err;
+
+	/* Skip channels that are not pending waiting for encryption */
+	if (!atomic_test_and_clear_bit(chan->status,
+				       BT_L2CAP_STATUS_ENCRYPT_PENDING)) {
+		return;
+	}
+
+	if (status) {
+		goto fail;
+	}
+
+	if (chan->ident) {
+		struct bt_l2cap_chan *echan[L2CAP_ECRED_CHAN_MAX];
+		struct bt_l2cap_le_chan *ch;
+		int i = 0;
+
+		while ((ch = l2cap_remove_ident(chan->conn, chan->ident))) {
+			echan[i++] = &ch->chan;
+		}
+
+		/* Retry ecred connect */
+		l2cap_ecred_conn_req(echan, i);
+		return;
+	}
+
+	/* Retry to connect */
+	err = l2cap_le_conn_req(BT_L2CAP_LE_CHAN(chan));
+	if (err) {
+		goto fail;
+	}
+
+	return;
+fail:
+	bt_l2cap_chan_remove(chan->conn, chan);
+	bt_l2cap_chan_del(chan);
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+void bt_l2cap_security_changed(struct bt_conn *conn, uint8_t hci_status)
+{
+	struct bt_l2cap_chan *chan, *next;
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		l2cap_br_encrypt_change(conn, hci_status);
+		return;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn->channels, chan, next, node) {
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+		l2cap_le_encrypt_change(chan, hci_status);
+#endif
+
+		if (chan->ops->encrypt_change) {
+			chan->ops->encrypt_change(chan, hci_status);
+		}
+	}
+}
+
+struct net_buf *bt_l2cap_create_pdu_timeout(struct net_buf_pool *pool,
+					    size_t reserve,
+					    k_timeout_t timeout)
+{
+	return bt_conn_create_pdu_timeout(pool,
+					  sizeof(struct bt_l2cap_hdr) + reserve,
+					  timeout);
+}
+
+int bt_l2cap_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf,
+		     bt_conn_tx_cb_t cb, void *user_data)
+{
+	struct bt_l2cap_hdr *hdr;
+
+	BT_DBG("bt_l2cap_send_cb, conn %p cid %u len %zu", conn, cid, net_buf_frags_len(buf));
+
+	hdr = net_buf_push(buf, sizeof(*hdr));
+	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
+	hdr->cid = sys_cpu_to_le16(cid);
+
+	return bt_conn_send_cb(conn, buf, cb, user_data);
+}
+
+static void l2cap_send_reject(struct bt_conn *conn, uint8_t ident,
+			      uint16_t reason, void *data, uint8_t data_len)
+{
+	struct bt_l2cap_cmd_reject *rej;
+	struct net_buf *buf;
+
+	buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CMD_REJECT, ident,
+				      sizeof(*rej) + data_len);
+	if (!buf) {
+		return;
+	}
+
+	rej = net_buf_add(buf, sizeof(*rej));
+	rej->reason = sys_cpu_to_le16(reason);
+
+	if (data) {
+		net_buf_add_mem(buf, data, data_len);
+	}
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static void le_conn_param_rsp(struct bt_l2cap *l2cap, struct net_buf *buf)
+{
+	struct bt_l2cap_conn_param_rsp *rsp = (void *)buf->data;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small LE conn param rsp");
+		return;
+	}
+
+	BT_DBG("LE conn param rsp result %u", sys_le16_to_cpu(rsp->result));
+}
+
+static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident,
+				     struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_le_conn_param param;
+	struct bt_l2cap_conn_param_rsp *rsp;
+	struct bt_l2cap_conn_param_req *req = (void *)buf->data;
+	bool accepted;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small LE conn update param req");
+		return;
+	}
+
+	if (conn->role != BT_HCI_ROLE_MASTER) {
+		l2cap_send_reject(conn, ident, BT_L2CAP_REJ_NOT_UNDERSTOOD,
+				  NULL, 0);
+		return;
+	}
+
+	param.interval_min = sys_le16_to_cpu(req->min_interval);
+	param.interval_max = sys_le16_to_cpu(req->max_interval);
+	param.latency = sys_le16_to_cpu(req->latency);
+	param.timeout = sys_le16_to_cpu(req->timeout);
+
+	BT_DBG("le_conn_param_update_req min 0x%04x max 0x%04x latency: 0x%04x timeout: 0x%04x",
+	       param.interval_min, param.interval_max, param.latency,
+	       param.timeout);
+
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_CONN_PARAM_RSP, ident,
+				      sizeof(*rsp));
+	if (!buf) {
+		return;
+	}
+
+	accepted = le_param_req(conn, &param);
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	if (accepted) {
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_ACCEPTED);
+	} else {
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_REJECTED);
+	}
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+
+	if (accepted) {
+		bt_conn_le_conn_update(conn, &param);
+	}
+}
+
+struct bt_l2cap_chan *bt_l2cap_le_lookup_tx_cid(struct bt_conn *conn,
+						uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BT_L2CAP_LE_CHAN(chan)->tx.cid == cid) {
+			return chan;
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_l2cap_chan *bt_l2cap_le_lookup_rx_cid(struct bt_conn *conn,
+						uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BT_L2CAP_LE_CHAN(chan)->rx.cid == cid) {
+			return chan;
+		}
+	}
+
+	return NULL;
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static struct bt_l2cap_server *l2cap_server_lookup_psm(uint16_t psm)
+{
+	struct bt_l2cap_server *server;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&servers, server, node) {
+		if (server->psm == psm) {
+			return server;
+		}
+	}
+
+	return NULL;
+}
+
+int bt_l2cap_server_register(struct bt_l2cap_server *server)
+{
+	if (!server->accept) {
+		return -EINVAL;
+	}
+
+	if (server->psm) {
+		if (server->psm < L2CAP_LE_PSM_FIXED_START ||
+		    server->psm > L2CAP_LE_PSM_DYN_END) {
+			return -EINVAL;
+		}
+
+		/* Check if given PSM is already in use */
+		if (l2cap_server_lookup_psm(server->psm)) {
+			BT_DBG("PSM already registered");
+			return -EADDRINUSE;
+		}
+	} else {
+		uint16_t psm;
+
+		for (psm = L2CAP_LE_PSM_DYN_START;
+		     psm <= L2CAP_LE_PSM_DYN_END; psm++) {
+			if (!l2cap_server_lookup_psm(psm)) {
+				break;
+			}
+		}
+
+		if (psm > L2CAP_LE_PSM_DYN_END) {
+			BT_WARN("No free dynamic PSMs available");
+			return -EADDRNOTAVAIL;
+		}
+
+		BT_DBG("Allocated PSM 0x%04x for new server", psm);
+		server->psm = psm;
+	}
+
+	if (server->sec_level > BT_SECURITY_L4) {
+		return -EINVAL;
+	} else if (server->sec_level < BT_SECURITY_L1) {
+		/* Level 0 is only applicable for BR/EDR */
+		server->sec_level = BT_SECURITY_L1;
+	}
+
+	BT_DBG("PSM 0x%04x", server->psm);
+
+	sys_slist_append(&servers, &server->node);
+
+	return 0;
+}
+
+static void l2cap_chan_rx_init(struct bt_l2cap_le_chan *chan)
+{
+	BT_DBG("chan %p", chan);
+
+	/* Use existing MTU if defined */
+	if (!chan->rx.mtu) {
+		chan->rx.mtu = L2CAP_MAX_LE_MTU;
+	}
+
+	/* MPS shall not be bigger than MTU + 2 as the remaining bytes cannot
+	 * be used.
+	 */
+	chan->rx.mps = MIN(chan->rx.mtu + 2, L2CAP_MAX_LE_MPS);
+
+	/* Truncate MTU if channel have disabled segmentation but still have
+	 * set an MTU which requires it.
+	 */
+	if (!chan->chan.ops->alloc_buf && (chan->rx.mps < chan->rx.mtu + 2)) {
+		BT_WARN("Segmentation disabled but MTU > MPS, truncating MTU");
+		chan->rx.mtu = chan->rx.mps - 2;
+	}
+
+	/* Use existing credits if defined */
+	if (!chan->rx.init_credits) {
+		if (chan->chan.ops->alloc_buf) {
+			/* Auto tune credits to receive a full packet */
+			chan->rx.init_credits =
+				ceiling_fraction(chan->rx.mtu,
+						 L2CAP_MAX_LE_MPS);
+		} else {
+			chan->rx.init_credits = L2CAP_LE_MAX_CREDITS;
+		}
+	}
+
+	atomic_set(&chan->rx.credits,  0);
+
+	if (BT_DBG_ENABLED &&
+	    chan->rx.init_credits * chan->rx.mps < chan->rx.mtu + 2) {
+		BT_WARN("Not enough credits for a full packet");
+	}
+}
+
+static struct net_buf *l2cap_chan_le_get_tx_buf(struct bt_l2cap_le_chan *ch)
+{
+	struct net_buf *buf;
+
+	/* Return current buffer */
+	if (ch->tx_buf) {
+		buf = ch->tx_buf;
+		ch->tx_buf = NULL;
+		return buf;
+	}
+
+	return net_buf_get(&ch->tx_queue, K_NO_WAIT);
+}
+
+static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
+				  struct net_buf **buf, uint16_t sent);
+
+static void l2cap_chan_tx_process(struct k_work *work)
+{
+	struct bt_l2cap_le_chan *ch;
+	struct net_buf *buf;
+
+	ch = CONTAINER_OF(work, struct bt_l2cap_le_chan, tx_work);
+
+	/* Resume tx in case there are buffers in the queue */
+	while ((buf = l2cap_chan_le_get_tx_buf(ch))) {
+		int sent = data_sent(buf)->len;
+
+		BT_DBG("buf %p sent %u", buf, sent);
+
+		sent = l2cap_chan_le_send_sdu(ch, &buf, sent);
+		if (sent < 0) {
+			if (sent == -EAGAIN) {
+				ch->tx_buf = buf;
+			}
+			break;
+		}
+	}
+}
+
+static void l2cap_chan_tx_init(struct bt_l2cap_le_chan *chan)
+{
+	BT_DBG("chan %p", chan);
+
+	(void)memset(&chan->tx, 0, sizeof(chan->tx));
+	atomic_set(&chan->tx.credits, 0);
+	k_fifo_init(&chan->tx_queue);
+	k_work_init(&chan->tx_work, l2cap_chan_tx_process);
+}
+
+static void l2cap_chan_tx_give_credits(struct bt_l2cap_le_chan *chan,
+				       uint16_t credits)
+{
+	BT_DBG("chan %p credits %u", chan, credits);
+
+	atomic_add(&chan->tx.credits, credits);
+
+	if (!atomic_test_and_set_bit(chan->chan.status, BT_L2CAP_STATUS_OUT) &&
+	    chan->chan.ops->status) {
+		chan->chan.ops->status(&chan->chan, chan->chan.status);
+	}
+}
+
+static void l2cap_chan_rx_give_credits(struct bt_l2cap_le_chan *chan,
+				       uint16_t credits)
+{
+	BT_DBG("chan %p credits %u", chan, credits);
+
+	atomic_add(&chan->rx.credits, credits);
+}
+
+static void l2cap_chan_destroy(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	struct net_buf *buf;
+
+	BT_DBG("chan %p cid 0x%04x", ch, ch->rx.cid);
+
+	/* Cancel ongoing work */
+	k_delayed_work_cancel(&chan->rtx_work);
+
+	if (ch->tx_buf) {
+		net_buf_unref(ch->tx_buf);
+		ch->tx_buf = NULL;
+	}
+
+	/* Remove buffers on the TX queue */
+	while ((buf = net_buf_get(&ch->tx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	/* Remove buffers on the RX queue */
+	while ((buf = net_buf_get(&ch->rx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	/* Destroy segmented SDU if it exists */
+	if (ch->_sdu) {
+		net_buf_unref(ch->_sdu);
+		ch->_sdu = NULL;
+		ch->_sdu_len = 0U;
+	}
+}
+
+static uint16_t le_err_to_result(int err)
+{
+	switch (err) {
+	case -ENOMEM:
+		return BT_L2CAP_LE_ERR_NO_RESOURCES;
+	case -EACCES:
+		return BT_L2CAP_LE_ERR_AUTHORIZATION;
+	case -EPERM:
+		return BT_L2CAP_LE_ERR_KEY_SIZE;
+	case -ENOTSUP:
+		/* This handle the cases where a fixed channel is registered but
+		 * for some reason (e.g. controller not suporting a feature)
+		 * cannot be used.
+		 */
+		return BT_L2CAP_LE_ERR_PSM_NOT_SUPP;
+	default:
+		return BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
+	}
+}
+
+static uint16_t l2cap_chan_accept(struct bt_conn *conn,
+			       struct bt_l2cap_server *server, uint16_t scid,
+			       uint16_t mtu, uint16_t mps, uint16_t credits,
+			       struct bt_l2cap_chan **chan)
+{
+	struct bt_l2cap_le_chan *ch;
+	int err;
+
+	BT_DBG("conn %p scid 0x%04x chan %p", conn, scid, chan);
+
+	if (!L2CAP_LE_CID_IS_DYN(scid)) {
+		return BT_L2CAP_LE_ERR_INVALID_SCID;
+	}
+
+	*chan = bt_l2cap_le_lookup_tx_cid(conn, scid);
+	if (*chan) {
+		return BT_L2CAP_LE_ERR_SCID_IN_USE;
+	}
+
+	/* Request server to accept the new connection and allocate the
+	 * channel.
+	 */
+	err = server->accept(conn, chan);
+	if (err < 0) {
+		return le_err_to_result(err);
+	}
+
+	(*chan)->required_sec_level = server->sec_level;
+
+	if (!l2cap_chan_add(conn, *chan, l2cap_chan_destroy)) {
+		return BT_L2CAP_LE_ERR_NO_RESOURCES;
+	}
+
+	ch = BT_L2CAP_LE_CHAN(*chan);
+
+	/* Init TX parameters */
+	l2cap_chan_tx_init(ch);
+	ch->tx.cid = scid;
+	ch->tx.mps = mps;
+	ch->tx.mtu = mtu;
+	ch->tx.init_credits = credits;
+	l2cap_chan_tx_give_credits(ch, credits);
+
+	/* Init RX parameters */
+	l2cap_chan_rx_init(ch);
+	l2cap_chan_rx_give_credits(ch, ch->rx.init_credits);
+
+	/* Set channel PSM */
+	(*chan)->psm = server->psm;
+
+	/* Update state */
+	bt_l2cap_chan_set_state(*chan, BT_L2CAP_CONNECTED);
+
+	if ((*chan)->ops->connected) {
+		(*chan)->ops->connected(*chan);
+	}
+
+	return BT_L2CAP_LE_SUCCESS;
+}
+
+static bool l2cap_check_security(struct bt_conn *conn,
+				 struct bt_l2cap_server *server)
+{
+	if (IS_ENABLED(CONFIG_BT_CONN_DISABLE_SECURITY)) {
+		return true;
+	}
+
+	return conn->sec_level >= server->sec_level;
+}
+
+static void le_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
+			struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_le_chan *ch;
+	struct bt_l2cap_server *server;
+	struct bt_l2cap_le_conn_req *req = (void *)buf->data;
+	struct bt_l2cap_le_conn_rsp *rsp;
+	uint16_t psm, scid, mtu, mps, credits;
+	uint16_t result;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small LE conn req packet size");
+		return;
+	}
+
+	psm = sys_le16_to_cpu(req->psm);
+	scid = sys_le16_to_cpu(req->scid);
+	mtu = sys_le16_to_cpu(req->mtu);
+	mps = sys_le16_to_cpu(req->mps);
+	credits = sys_le16_to_cpu(req->credits);
+
+	BT_DBG("psm 0x%02x scid 0x%04x mtu %u mps %u credits %u", psm, scid,
+	       mtu, mps, credits);
+
+	if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MTU) {
+		BT_ERR("Invalid LE-Conn Req params");
+		return;
+	}
+
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CONN_RSP, ident,
+				      sizeof(*rsp));
+	if (!buf) {
+		return;
+	}
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	(void)memset(rsp, 0, sizeof(*rsp));
+
+	/* Check if there is a server registered */
+	server = l2cap_server_lookup_psm(psm);
+	if (!server) {
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_PSM_NOT_SUPP);
+		goto rsp;
+	}
+
+	/* Check if connection has minimum required security level */
+	if (!l2cap_check_security(conn, server)) {
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_LE_ERR_AUTHENTICATION);
+		goto rsp;
+	}
+
+	result = l2cap_chan_accept(conn, server, scid, mtu, mps, credits,
+				   &chan);
+	if (result != BT_L2CAP_LE_SUCCESS) {
+		rsp->result = sys_cpu_to_le16(result);
+		goto rsp;
+	}
+
+	ch = BT_L2CAP_LE_CHAN(chan);
+
+	/* Prepare response protocol data */
+	rsp->dcid = sys_cpu_to_le16(ch->rx.cid);
+	rsp->mps = sys_cpu_to_le16(ch->rx.mps);
+	rsp->mtu = sys_cpu_to_le16(ch->rx.mtu);
+	rsp->credits = sys_cpu_to_le16(ch->rx.init_credits);
+	rsp->result = BT_L2CAP_LE_SUCCESS;
+
+rsp:
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static void le_ecred_conn_req(struct bt_l2cap *l2cap, uint8_t ident,
+			      struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan[L2CAP_ECRED_CHAN_MAX];
+	struct bt_l2cap_le_chan *ch = NULL;
+	struct bt_l2cap_server *server;
+	struct bt_l2cap_ecred_conn_req *req;
+	struct bt_l2cap_ecred_conn_rsp *rsp;
+	uint16_t psm, mtu, mps, credits, result = BT_L2CAP_LE_ERR_INVALID_SCID;
+	uint16_t scid, dcid[L2CAP_ECRED_CHAN_MAX];
+	int i = 0;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small LE conn req packet size");
+		result = BT_L2CAP_LE_ERR_INVALID_PARAMS;
+		goto response;
+	}
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+	psm = sys_le16_to_cpu(req->psm);
+	mtu = sys_le16_to_cpu(req->mtu);
+	mps = sys_le16_to_cpu(req->mps);
+	credits = sys_le16_to_cpu(req->credits);
+
+	BT_DBG("psm 0x%02x mtu %u mps %u credits %u", psm, mtu, mps, credits);
+
+	if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MTU) {
+		BT_ERR("Invalid ecred conn req params");
+		result = BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
+		goto response;
+	}
+
+	/* Check if there is a server registered */
+	server = l2cap_server_lookup_psm(psm);
+	if (!server) {
+		result = BT_L2CAP_LE_ERR_PSM_NOT_SUPP;
+		goto response;
+	}
+
+	/* Check if connection has minimum required security level */
+	if (!l2cap_check_security(conn, server)) {
+		result = BT_L2CAP_LE_ERR_AUTHENTICATION;
+		goto response;
+	}
+
+	while (buf->len >= sizeof(scid)) {
+		scid = net_buf_pull_le16(buf);
+
+		result = l2cap_chan_accept(conn, server, scid, mtu, mps,
+					   credits, &chan[i]);
+		switch (result) {
+		case BT_L2CAP_LE_SUCCESS:
+			ch = BT_L2CAP_LE_CHAN(chan[i]);
+			dcid[i++] = sys_cpu_to_le16(ch->rx.cid);
+			continue;
+		/* Some connections refused â€?invalid Source CID */
+		case BT_L2CAP_LE_ERR_INVALID_SCID:
+		/* Some connections refused â€?Source CID already allocated */
+		case BT_L2CAP_LE_ERR_SCID_IN_USE:
+			/* If a Destination CID is 0x0000, the channel was not
+			 * established.
+			 */
+			dcid[i++] = 0x0000;
+			continue;
+		/* Some connections refused â€?not enough resources
+		 * available.
+		 */
+		case BT_L2CAP_LE_ERR_NO_RESOURCES:
+		default:
+			goto response;
+		}
+	}
+
+response:
+	if (!i) {
+		i = buf->len / sizeof(scid);
+	}
+
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_ECRED_CONN_RSP, ident,
+				      sizeof(*rsp) + (sizeof(scid) * i));
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	(void)memset(rsp, 0, sizeof(*rsp));
+
+	if (result == BT_L2CAP_LE_ERR_UNACCEPT_PARAMS ||
+	    result == BT_L2CAP_LE_ERR_PSM_NOT_SUPP ||
+	    result == BT_L2CAP_LE_ERR_AUTHENTICATION) {
+		memset(dcid, 0, sizeof(scid) * i);
+	} else if (ch) {
+		rsp->mps = sys_cpu_to_le16(ch->rx.mps);
+		rsp->mtu = sys_cpu_to_le16(ch->rx.mtu);
+		rsp->credits = sys_cpu_to_le16(ch->rx.init_credits);
+	}
+
+	net_buf_add_mem(buf, dcid, sizeof(scid) * i);
+
+	rsp->result = sys_cpu_to_le16(result);
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static void le_ecred_reconf_req(struct bt_l2cap *l2cap, uint8_t ident,
+				struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_ecred_reconf_req *req;
+	struct bt_l2cap_ecred_reconf_rsp *rsp;
+	uint16_t mtu, mps;
+	uint16_t scid, result;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small ecred reconf req packet size");
+		return;
+	}
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+
+	mtu = sys_le16_to_cpu(req->mtu);
+	mps = sys_le16_to_cpu(req->mps);
+
+	if (mtu < L2CAP_ECRED_MIN_MTU) {
+		result = BT_L2CAP_RECONF_INVALID_MTU;
+		goto response;
+	}
+
+	if (mps < L2CAP_ECRED_MIN_MTU) {
+		result = BT_L2CAP_RECONF_INVALID_MTU;
+		goto response;
+	}
+
+	while (buf->len >= sizeof(scid)) {
+		struct bt_l2cap_chan *chan;
+
+		scid = net_buf_pull_le16(buf);
+
+		BT_DBG("scid 0x%04x", scid);
+
+		if (!scid) {
+			continue;
+		}
+
+		chan = bt_l2cap_le_lookup_tx_cid(conn, scid);
+		if (!chan) {
+			continue;
+		}
+
+		/* If the MTU value is decreased for any of the included
+		 * channels, then the receiver shall disconnect all
+		 * included channels.
+		 */
+		if (BT_L2CAP_LE_CHAN(chan)->tx.mtu > mtu) {
+			BT_ERR("chan %p decreased MTU %u -> %u", chan,
+			       BT_L2CAP_LE_CHAN(chan)->tx.mtu, mtu);
+			result = BT_L2CAP_RECONF_INVALID_MTU;
+			bt_l2cap_chan_disconnect(chan);
+			goto response;
+		}
+
+		BT_L2CAP_LE_CHAN(chan)->tx.mtu = mtu;
+		BT_L2CAP_LE_CHAN(chan)->tx.mps = mps;
+	}
+
+	BT_DBG("mtu %u mps %u", mtu, mps);
+
+	result = BT_L2CAP_RECONF_SUCCESS;
+
+response:
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_ECRED_RECONF_RSP, ident,
+				      sizeof(*rsp));
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->result = sys_cpu_to_le16(result);
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static struct bt_l2cap_le_chan *l2cap_remove_rx_cid(struct bt_conn *conn,
+						    uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+	sys_snode_t *prev = NULL;
+
+	/* Protect fixed channels against accidental removal */
+	if (!L2CAP_LE_CID_IS_DYN(cid)) {
+		return NULL;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BT_L2CAP_LE_CHAN(chan)->rx.cid == cid) {
+			sys_slist_remove(&conn->channels, prev, &chan->node);
+			return BT_L2CAP_LE_CHAN(chan);
+		}
+
+		prev = &chan->node;
+	}
+
+	return NULL;
+}
+
+static void le_disconn_req(struct bt_l2cap *l2cap, uint8_t ident,
+			   struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_le_chan *chan;
+	struct bt_l2cap_disconn_req *req = (void *)buf->data;
+	struct bt_l2cap_disconn_rsp *rsp;
+	uint16_t dcid;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small LE conn req packet size");
+		return;
+	}
+
+	dcid = sys_le16_to_cpu(req->dcid);
+
+	BT_DBG("dcid 0x%04x scid 0x%04x", dcid, sys_le16_to_cpu(req->scid));
+
+	chan = l2cap_remove_rx_cid(conn, dcid);
+	if (!chan) {
+		struct bt_l2cap_cmd_reject_cid_data data;
+
+		data.scid = req->scid;
+		data.dcid = req->dcid;
+
+		l2cap_send_reject(conn, ident, BT_L2CAP_REJ_INVALID_CID, &data,
+				  sizeof(data));
+		return;
+	}
+
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_DISCONN_RSP, ident,
+				      sizeof(*rsp));
+	if (!buf) {
+		return;
+	}
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->dcid = sys_cpu_to_le16(chan->rx.cid);
+	rsp->scid = sys_cpu_to_le16(chan->tx.cid);
+
+	bt_l2cap_chan_del(&chan->chan);
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+}
+
+static int l2cap_change_security(struct bt_l2cap_le_chan *chan, uint16_t err)
+{
+	struct bt_conn *conn = chan->chan.conn;
+	bt_security_t sec;
+	int ret;
+
+	if (atomic_test_bit(chan->chan.status,
+			    BT_L2CAP_STATUS_ENCRYPT_PENDING)) {
+		return -EINPROGRESS;
+	}
+
+	switch (err) {
+	case BT_L2CAP_LE_ERR_ENCRYPTION:
+		if (conn->sec_level >= BT_SECURITY_L2) {
+			return -EALREADY;
+		}
+
+		sec = BT_SECURITY_L2;
+		break;
+	case BT_L2CAP_LE_ERR_AUTHENTICATION:
+		if (conn->sec_level < BT_SECURITY_L2) {
+			sec = BT_SECURITY_L2;
+		} else if (conn->sec_level < BT_SECURITY_L3) {
+			sec = BT_SECURITY_L3;
+		} else if (conn->sec_level < BT_SECURITY_L4) {
+			sec = BT_SECURITY_L4;
+		} else {
+			return -EALREADY;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = bt_conn_set_security(chan->chan.conn, sec);
+	if (ret < 0) {
+		return ret;
+	}
+
+	atomic_set_bit(chan->chan.status, BT_L2CAP_STATUS_ENCRYPT_PENDING);
+
+	return 0;
+}
+
+static void le_ecred_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
+			      struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_le_chan *chan;
+	struct bt_l2cap_ecred_conn_rsp *rsp;
+	uint16_t dcid, mtu, mps, credits, result;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small ecred conn rsp packet size");
+		return;
+	}
+
+	rsp = net_buf_pull_mem(buf, sizeof(*rsp));
+	mtu = sys_le16_to_cpu(rsp->mtu);
+	mps = sys_le16_to_cpu(rsp->mps);
+	credits = sys_le16_to_cpu(rsp->credits);
+	result = sys_le16_to_cpu(rsp->result);
+
+	BT_DBG("mtu 0x%04x mps 0x%04x credits 0x%04x result %u", mtu,
+	       mps, credits, result);
+
+	switch (result) {
+	case BT_L2CAP_LE_ERR_AUTHENTICATION:
+	case BT_L2CAP_LE_ERR_ENCRYPTION:
+		while ((chan = l2cap_lookup_ident(conn, ident))) {
+			/* Cancel RTX work */
+			k_delayed_work_cancel(&chan->chan.rtx_work);
+
+			/* If security needs changing wait it to be completed */
+			if (!l2cap_change_security(chan, result)) {
+				return;
+			}
+			bt_l2cap_chan_remove(conn, &chan->chan);
+			bt_l2cap_chan_del(&chan->chan);
+		}
+		break;
+	case BT_L2CAP_LE_SUCCESS:
+	/* Some connections refused â€?invalid Source CID */
+	case BT_L2CAP_LE_ERR_INVALID_SCID:
+	/* Some connections refused â€?Source CID already allocated */
+	case BT_L2CAP_LE_ERR_SCID_IN_USE:
+	/* Some connections refused â€?not enough resources available */
+	case BT_L2CAP_LE_ERR_NO_RESOURCES:
+		while ((chan = l2cap_lookup_ident(conn, ident))) {
+			struct bt_l2cap_chan *c;
+
+			/* Cancel RTX work */
+			k_delayed_work_cancel(&chan->chan.rtx_work);
+
+			dcid = net_buf_pull_le16(buf);
+
+			BT_DBG("dcid 0x%04x", dcid);
+
+			/* If a Destination CID is 0x0000, the channel was not
+			 * established.
+			 */
+			if (!dcid) {
+				bt_l2cap_chan_remove(conn, &chan->chan);
+				bt_l2cap_chan_del(&chan->chan);
+				continue;
+			}
+
+			c = bt_l2cap_le_lookup_tx_cid(conn, dcid);
+			if (c) {
+				/* If a device receives a
+				 * L2CAP_CREDIT_BASED_CONNECTION_RSP packet
+				 * with an already assigned Destination CID,
+				 * then both the original channel and the new
+				 * channel shall be immediately discarded and
+				 * not used.
+				 */
+				bt_l2cap_chan_remove(conn, &chan->chan);
+				bt_l2cap_chan_del(&chan->chan);
+				bt_l2cap_chan_disconnect(c);
+				continue;
+			}
+
+			chan->tx.cid = dcid;
+
+			chan->chan.ident = 0U;
+
+			chan->tx.mtu = mtu;
+			chan->tx.mps = mps;
+
+			/* Update state */
+			bt_l2cap_chan_set_state(&chan->chan,
+						BT_L2CAP_CONNECTED);
+
+			if (chan->chan.ops->connected) {
+				chan->chan.ops->connected(&chan->chan);
+			}
+
+			/* Give credits */
+			l2cap_chan_tx_give_credits(chan, credits);
+			l2cap_chan_rx_give_credits(chan, chan->rx.init_credits);
+		}
+		break;
+	case BT_L2CAP_LE_ERR_PSM_NOT_SUPP:
+	default:
+		while ((chan = l2cap_remove_ident(conn, ident))) {
+			bt_l2cap_chan_del(&chan->chan);
+		}
+		break;
+	}
+}
+
+static void le_conn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
+			struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_le_chan *chan;
+	struct bt_l2cap_le_conn_rsp *rsp = (void *)buf->data;
+	uint16_t dcid, mtu, mps, credits, result;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small LE conn rsp packet size");
+		return;
+	}
+
+	dcid = sys_le16_to_cpu(rsp->dcid);
+	mtu = sys_le16_to_cpu(rsp->mtu);
+	mps = sys_le16_to_cpu(rsp->mps);
+	credits = sys_le16_to_cpu(rsp->credits);
+	result = sys_le16_to_cpu(rsp->result);
+
+	BT_DBG("dcid 0x%04x mtu %u mps %u credits %u result 0x%04x", dcid,
+	       mtu, mps, credits, result);
+
+	/* Keep the channel in case of security errors */
+	if (result == BT_L2CAP_LE_SUCCESS ||
+	    result == BT_L2CAP_LE_ERR_AUTHENTICATION ||
+	    result == BT_L2CAP_LE_ERR_ENCRYPTION) {
+		chan = l2cap_lookup_ident(conn, ident);
+	} else {
+		chan = l2cap_remove_ident(conn, ident);
+	}
+
+	if (!chan) {
+		BT_ERR("Cannot find channel for ident %u", ident);
+		return;
+	}
+
+	/* Cancel RTX work */
+	k_delayed_work_cancel(&chan->chan.rtx_work);
+
+	/* Reset ident since it got a response */
+	chan->chan.ident = 0U;
+
+	switch (result) {
+	case BT_L2CAP_LE_SUCCESS:
+		chan->tx.cid = dcid;
+		chan->tx.mtu = mtu;
+		chan->tx.mps = mps;
+
+		/* Update state */
+		bt_l2cap_chan_set_state(&chan->chan, BT_L2CAP_CONNECTED);
+
+		if (chan->chan.ops->connected) {
+			chan->chan.ops->connected(&chan->chan);
+		}
+
+		/* Give credits */
+		l2cap_chan_tx_give_credits(chan, credits);
+		l2cap_chan_rx_give_credits(chan, chan->rx.init_credits);
+
+		break;
+	case BT_L2CAP_LE_ERR_AUTHENTICATION:
+	case BT_L2CAP_LE_ERR_ENCRYPTION:
+		/* If security needs changing wait it to be completed */
+		if (l2cap_change_security(chan, result) == 0) {
+			return;
+		}
+		bt_l2cap_chan_remove(conn, &chan->chan);
+		__fallthrough;
+	default:
+		bt_l2cap_chan_del(&chan->chan);
+	}
+}
+
+static void le_disconn_rsp(struct bt_l2cap *l2cap, uint8_t ident,
+			   struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_le_chan *chan;
+	struct bt_l2cap_disconn_rsp *rsp = (void *)buf->data;
+	uint16_t scid;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small LE disconn rsp packet size");
+		return;
+	}
+
+	scid = sys_le16_to_cpu(rsp->scid);
+
+	BT_DBG("dcid 0x%04x scid 0x%04x", sys_le16_to_cpu(rsp->dcid), scid);
+
+	chan = l2cap_remove_rx_cid(conn, scid);
+	if (!chan) {
+		return;
+	}
+
+	bt_l2cap_chan_del(&chan->chan);
+}
+
+static inline struct net_buf *l2cap_alloc_seg(struct net_buf *buf)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+	struct net_buf *seg;
+
+	/* Try to use original pool if possible */
+	seg = net_buf_alloc(pool, K_NO_WAIT);
+	if (seg) {
+		net_buf_reserve(seg, BT_L2CAP_CHAN_SEND_RESERVE);
+		return seg;
+	}
+
+	/* Fallback to using global connection tx pool */
+	return bt_l2cap_create_pdu_timeout(NULL, 0, K_NO_WAIT);
+}
+
+static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
+					     struct net_buf *buf,
+					     size_t sdu_hdr_len)
+{
+	struct net_buf *seg;
+	uint16_t headroom;
+	uint16_t len;
+
+	/* Segment if data (+ data headroom) is bigger than MPS */
+	if (buf->len + sdu_hdr_len > ch->tx.mps) {
+		goto segment;
+	}
+
+	headroom = BT_L2CAP_CHAN_SEND_RESERVE + sdu_hdr_len;
+
+	/* Check if original buffer has enough headroom and don't have any
+	 * fragments.
+	 */
+	if (net_buf_headroom(buf) >= headroom && !buf->frags) {
+		if (sdu_hdr_len) {
+			/* Push SDU length if set */
+			net_buf_push_le16(buf, net_buf_frags_len(buf));
+		}
+		return net_buf_ref(buf);
+	}
+
+segment:
+	seg = l2cap_alloc_seg(buf);
+	if (!seg) {
+		return NULL;
+	}
+
+	if (sdu_hdr_len) {
+		net_buf_add_le16(seg, net_buf_frags_len(buf));
+	}
+
+	/* Don't send more that TX MPS including SDU length */
+	len = MIN(net_buf_tailroom(seg), ch->tx.mps - sdu_hdr_len);
+	/* Limit if original buffer is smaller than the segment */
+	len = MIN(buf->len, len);
+	net_buf_add_mem(seg, buf->data, len);
+	net_buf_pull(buf, len);
+
+	BT_DBG("ch %p seg %p len %u", ch, seg, seg->len);
+
+	return seg;
+}
+
+static void l2cap_chan_tx_resume(struct bt_l2cap_le_chan *ch)
+{
+	if (!atomic_get(&ch->tx.credits) ||
+	    (k_fifo_is_empty(&ch->tx_queue) && !ch->tx_buf)) {
+		return;
+	}
+
+	k_work_submit(&ch->tx_work);
+}
+
+static void l2cap_chan_sdu_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *chan = user_data;
+
+	BT_DBG("conn %p chan %p", conn, chan);
+
+	if (chan->ops->sent) {
+		chan->ops->sent(chan);
+	}
+
+	l2cap_chan_tx_resume(BT_L2CAP_LE_CHAN(chan));
+}
+
+static void l2cap_chan_seg_sent(struct bt_conn *conn, void *user_data)
+{
+	struct bt_l2cap_chan *chan = user_data;
+
+	BT_DBG("conn %p chan %p", conn, chan);
+
+	l2cap_chan_tx_resume(BT_L2CAP_LE_CHAN(chan));
+}
+
+static bool test_and_dec(atomic_t *target)
+{
+	atomic_t old_value, new_value;
+
+	do {
+		old_value = atomic_get(target);
+		if (!old_value) {
+			return false;
+		}
+
+		new_value = old_value - 1;
+	} while (atomic_cas(target, old_value, new_value) == 0);
+
+	return true;
+}
+
+/* This returns -EAGAIN whenever a segment cannot be send immediately which can
+ * happen under the following circuntances:
+ *
+ * 1. There are no credits
+ * 2. There are no buffers
+ * 3. There are no TX contexts
+ *
+ * In all cases the original buffer is unaffected so it can be pushed back to
+ * be sent later.
+ */
+static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch,
+			      struct net_buf *buf, uint16_t sdu_hdr_len)
+{
+	struct net_buf *seg;
+	struct net_buf_simple_state state;
+	int len, err;
+
+	if (!test_and_dec(&ch->tx.credits)) {
+		BT_WARN("No credits to transmit packet");
+		return -EAGAIN;
+	}
+
+	/* Save state so it can be restored if we failed to send */
+	net_buf_simple_save(&buf->b, &state);
+
+	seg = l2cap_chan_create_seg(ch, buf, sdu_hdr_len);
+	if (!seg) {
+		atomic_inc(&ch->tx.credits);
+		return -EAGAIN;
+	}
+
+	BT_DBG("ch %p cid 0x%04x len %u credits %u", ch, ch->tx.cid,
+	       seg->len, atomic_get(&ch->tx.credits));
+
+	len = seg->len - sdu_hdr_len;
+
+	/* Set a callback if there is no data left in the buffer and sent
+	 * callback has been set.
+	 */
+	if ((buf == seg || !buf->len) && ch->chan.ops->sent) {
+		err = bt_l2cap_send_cb(ch->chan.conn, ch->tx.cid, seg,
+				       l2cap_chan_sdu_sent, &ch->chan);
+	} else {
+		err = bt_l2cap_send_cb(ch->chan.conn, ch->tx.cid, seg,
+				       l2cap_chan_seg_sent, &ch->chan);
+	}
+
+	if (err) {
+		BT_WARN("Unable to send seg %d", err);
+		atomic_inc(&ch->tx.credits);
+
+		if (err == -ENOBUFS) {
+			/* Restore state since segment could not be sent */
+			net_buf_simple_restore(&buf->b, &state);
+			return -EAGAIN;
+		}
+
+		return err;
+	}
+
+	/* Check if there is no credits left clear output status and notify its
+	 * change.
+	 */
+	if (!atomic_get(&ch->tx.credits)) {
+		atomic_clear_bit(ch->chan.status, BT_L2CAP_STATUS_OUT);
+		if (ch->chan.ops->status) {
+			ch->chan.ops->status(&ch->chan, ch->chan.status);
+		}
+	}
+
+	return len;
+}
+
+static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
+				  struct net_buf **buf, uint16_t sent)
+{
+	int ret, total_len;
+	struct net_buf *frag;
+
+	total_len = net_buf_frags_len(*buf) + sent;
+
+	if (total_len > ch->tx.mtu) {
+		return -EMSGSIZE;
+	}
+
+	frag = *buf;
+	if (!frag->len && frag->frags) {
+		frag = frag->frags;
+	}
+
+	if (!sent) {
+		/* Add SDU length for the first segment */
+		ret = l2cap_chan_le_send(ch, frag, BT_L2CAP_SDU_HDR_LEN);
+		if (ret < 0) {
+			if (ret == -EAGAIN) {
+				/* Store sent data into user_data */
+				data_sent(frag)->len = sent;
+			}
+			*buf = frag;
+			return ret;
+		}
+		sent = ret;
+	}
+
+	/* Send remaining segments */
+	for (ret = 0; sent < total_len; sent += ret) {
+		/* Proceed to next fragment */
+		if (!frag->len) {
+			frag = net_buf_frag_del(NULL, frag);
+		}
+
+		ret = l2cap_chan_le_send(ch, frag, 0);
+		if (ret < 0) {
+			if (ret == -EAGAIN) {
+				/* Store sent data into user_data */
+				data_sent(frag)->len = sent;
+			}
+			*buf = frag;
+			return ret;
+		}
+	}
+
+	BT_DBG("ch %p cid 0x%04x sent %u total_len %u", ch, ch->tx.cid, sent,
+	       total_len);
+
+	net_buf_unref(frag);
+
+	return ret;
+}
+
+static void le_credits(struct bt_l2cap *l2cap, uint8_t ident,
+		       struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_le_credits *ev = (void *)buf->data;
+	struct bt_l2cap_le_chan *ch;
+	uint16_t credits, cid;
+
+	if (buf->len < sizeof(*ev)) {
+		BT_ERR("Too small LE Credits packet size");
+		return;
+	}
+
+	cid = sys_le16_to_cpu(ev->cid);
+	credits = sys_le16_to_cpu(ev->credits);
+
+	BT_DBG("cid 0x%04x credits %u", cid, credits);
+
+	chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
+	if (!chan) {
+		BT_ERR("Unable to find channel of LE Credits packet");
+		return;
+	}
+
+	ch = BT_L2CAP_LE_CHAN(chan);
+
+	if (atomic_get(&ch->tx.credits) + credits > UINT16_MAX) {
+		BT_ERR("Credits overflow");
+		bt_l2cap_chan_disconnect(chan);
+		return;
+	}
+
+	l2cap_chan_tx_give_credits(ch, credits);
+
+	BT_DBG("chan %p total credits %u", ch, atomic_get(&ch->tx.credits));
+
+	l2cap_chan_tx_resume(ch);
+}
+
+static void reject_cmd(struct bt_l2cap *l2cap, uint8_t ident,
+		       struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_le_chan *chan;
+
+	/* Check if there is a outstanding channel */
+	chan = l2cap_remove_ident(conn, ident);
+	if (!chan) {
+		return;
+	}
+
+	bt_l2cap_chan_del(&chan->chan);
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap *l2cap = CONTAINER_OF(chan, struct bt_l2cap, chan);
+	struct bt_l2cap_sig_hdr *hdr;
+	uint16_t len;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small L2CAP signaling PDU");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	len = sys_le16_to_cpu(hdr->len);
+
+	BT_DBG("Signaling code 0x%02x ident %u len %u", hdr->code,
+	       hdr->ident, len);
+
+	if (buf->len != len) {
+		BT_ERR("L2CAP length mismatch (%u != %u)", buf->len, len);
+		return 0;
+	}
+
+	if (!hdr->ident) {
+		BT_ERR("Invalid ident value in L2CAP PDU");
+		return 0;
+	}
+
+	switch (hdr->code) {
+	case BT_L2CAP_CONN_PARAM_RSP:
+		le_conn_param_rsp(l2cap, buf);
+		break;
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	case BT_L2CAP_LE_CONN_REQ:
+		le_conn_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_LE_CONN_RSP:
+		le_conn_rsp(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_DISCONN_REQ:
+		le_disconn_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_DISCONN_RSP:
+		le_disconn_rsp(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_LE_CREDITS:
+		le_credits(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_CMD_REJECT:
+		reject_cmd(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_ECRED_CONN_REQ:
+		le_ecred_conn_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_ECRED_CONN_RSP:
+		le_ecred_conn_rsp(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_ECRED_RECONF_REQ:
+		le_ecred_reconf_req(l2cap, hdr->ident, buf);
+		break;
+#else
+	case BT_L2CAP_CMD_REJECT:
+		/* Ignored */
+		break;
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+	case BT_L2CAP_CONN_PARAM_REQ:
+		if (IS_ENABLED(CONFIG_BT_CENTRAL)) {
+			le_conn_param_update_req(l2cap, hdr->ident, buf);
+			break;
+		}
+		__fallthrough;
+	default:
+		BT_WARN("Unknown L2CAP PDU code 0x%02x", hdr->code);
+		l2cap_send_reject(chan->conn, hdr->ident,
+				  BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0);
+		break;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static void l2cap_chan_shutdown(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	struct net_buf *buf;
+
+	BT_DBG("chan %p", chan);
+
+	atomic_set_bit(chan->status, BT_L2CAP_STATUS_SHUTDOWN);
+
+	/* Destroy segmented SDU if it exists */
+	if (ch->_sdu) {
+		net_buf_unref(ch->_sdu);
+		ch->_sdu = NULL;
+		ch->_sdu_len = 0U;
+	}
+
+	/* Cleanup outstanding request */
+	if (ch->tx_buf) {
+		net_buf_unref(ch->tx_buf);
+		ch->tx_buf = NULL;
+	}
+
+	/* Remove buffers on the TX queue */
+	while ((buf = net_buf_get(&ch->tx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	/* Remove buffers on the RX queue */
+	while ((buf = net_buf_get(&ch->rx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	/* Update status */
+	if (chan->ops->status) {
+		chan->ops->status(chan, chan->status);
+	}
+}
+
+static void l2cap_chan_send_credits(struct bt_l2cap_le_chan *chan,
+				    struct net_buf *buf, uint16_t credits)
+{
+	struct bt_l2cap_le_credits *ev;
+
+	/* Cap the number of credits given */
+	if (credits > chan->rx.init_credits) {
+		credits = chan->rx.init_credits;
+	}
+
+	buf = l2cap_create_le_sig_pdu(buf, BT_L2CAP_LE_CREDITS, get_ident(),
+				      sizeof(*ev));
+	if (!buf) {
+		BT_ERR("Unable to send credits update");
+		/* Disconnect would probably not work either so the only
+		 * option left is to shutdown the channel.
+		 */
+		l2cap_chan_shutdown(&chan->chan);
+		return;
+	}
+
+	l2cap_chan_rx_give_credits(chan, credits);
+
+	ev = net_buf_add(buf, sizeof(*ev));
+	ev->cid = sys_cpu_to_le16(chan->rx.cid);
+	ev->credits = sys_cpu_to_le16(credits);
+
+	bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_LE_SIG, buf);
+
+	BT_DBG("chan %p credits %u", chan, atomic_get(&chan->rx.credits));
+}
+
+static void l2cap_chan_update_credits(struct bt_l2cap_le_chan *chan,
+				      struct net_buf *buf)
+{
+	uint16_t credits;
+	atomic_val_t old_credits = atomic_get(&chan->rx.credits);
+
+	/* Restore enough credits to complete the sdu */
+	credits = ((chan->_sdu_len - net_buf_frags_len(buf)) +
+		   (chan->rx.mps - 1)) / chan->rx.mps;
+
+	if (credits < old_credits) {
+		return;
+	}
+
+	credits -= old_credits;
+
+	l2cap_chan_send_credits(chan, buf, credits);
+}
+
+int bt_l2cap_chan_recv_complete(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	struct bt_conn *conn = chan->conn;
+	uint16_t credits;
+
+	__ASSERT_NO_MSG(chan);
+	__ASSERT_NO_MSG(buf);
+
+	if (!conn) {
+		return -ENOTCONN;
+	}
+
+	if (conn->type != BT_CONN_TYPE_LE) {
+		return -ENOTSUP;
+	}
+
+	BT_DBG("chan %p buf %p", chan, buf);
+
+	/* Restore credits used by packet */
+	memcpy(&credits, net_buf_user_data(buf), sizeof(credits));
+
+	l2cap_chan_send_credits(ch, buf, credits);
+
+	net_buf_unref(buf);
+
+	return 0;
+}
+
+static struct net_buf *l2cap_alloc_frag(k_timeout_t timeout, void *user_data)
+{
+	struct bt_l2cap_le_chan *chan = user_data;
+	struct net_buf *frag = NULL;
+
+	frag = chan->chan.ops->alloc_buf(&chan->chan);
+	if (!frag) {
+		return NULL;
+	}
+
+	BT_DBG("frag %p tailroom %zu", frag, net_buf_tailroom(frag));
+
+	return frag;
+}
+
+static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
+				   struct net_buf *buf, uint16_t seg)
+{
+	int err;
+
+	BT_DBG("chan %p len %zu", chan, net_buf_frags_len(buf));
+
+	/* Receiving complete SDU, notify channel and reset SDU buf */
+	err = chan->chan.ops->recv(&chan->chan, buf);
+	if (err < 0) {
+		if (err != -EINPROGRESS) {
+			BT_ERR("err %d", err);
+			bt_l2cap_chan_disconnect(&chan->chan);
+			net_buf_unref(buf);
+		}
+		return;
+	}
+
+	l2cap_chan_send_credits(chan, buf, seg);
+	net_buf_unref(buf);
+}
+
+static void l2cap_chan_le_recv_seg(struct bt_l2cap_le_chan *chan,
+				   struct net_buf *buf)
+{
+	uint16_t len;
+	uint16_t seg = 0U;
+
+	len = net_buf_frags_len(chan->_sdu);
+	if (len) {
+		memcpy(&seg, net_buf_user_data(chan->_sdu), sizeof(seg));
+	}
+
+	if (len + buf->len > chan->_sdu_len) {
+		BT_ERR("SDU length mismatch");
+		bt_l2cap_chan_disconnect(&chan->chan);
+		return;
+	}
+
+	seg++;
+	/* Store received segments in user_data */
+	memcpy(net_buf_user_data(chan->_sdu), &seg, sizeof(seg));
+
+	BT_DBG("chan %p seg %d len %zu", chan, seg, net_buf_frags_len(buf));
+
+	/* Append received segment to SDU */
+	len = net_buf_append_bytes(chan->_sdu, buf->len, buf->data, K_NO_WAIT,
+				   l2cap_alloc_frag, chan);
+	if (len != buf->len) {
+		BT_ERR("Unable to store SDU");
+		bt_l2cap_chan_disconnect(&chan->chan);
+		return;
+	}
+
+	if (net_buf_frags_len(chan->_sdu) < chan->_sdu_len) {
+		/* Give more credits if remote has run out of them, this
+		 * should only happen if the remote cannot fully utilize the
+		 * MPS for some reason.
+		 */
+		if (!atomic_get(&chan->rx.credits) &&
+		    seg == chan->rx.init_credits) {
+			l2cap_chan_update_credits(chan, buf);
+		}
+		return;
+	}
+
+	buf = chan->_sdu;
+	chan->_sdu = NULL;
+	chan->_sdu_len = 0U;
+
+	l2cap_chan_le_recv_sdu(chan, buf, seg);
+}
+
+static void l2cap_chan_le_recv(struct bt_l2cap_le_chan *chan,
+			       struct net_buf *buf)
+{
+	uint16_t sdu_len;
+	int err;
+
+	if (!test_and_dec(&chan->rx.credits)) {
+		BT_ERR("No credits to receive packet");
+		bt_l2cap_chan_disconnect(&chan->chan);
+		return;
+	}
+
+	/* Check if segments already exist */
+	if (chan->_sdu) {
+		l2cap_chan_le_recv_seg(chan, buf);
+		return;
+	}
+
+	sdu_len = net_buf_pull_le16(buf);
+
+	BT_DBG("chan %p len %u sdu_len %u", chan, buf->len, sdu_len);
+
+	if (sdu_len > chan->rx.mtu) {
+		BT_ERR("Invalid SDU length");
+		bt_l2cap_chan_disconnect(&chan->chan);
+		return;
+	}
+
+	/* Always allocate buffer from the channel if supported. */
+	if (chan->chan.ops->alloc_buf) {
+		chan->_sdu = chan->chan.ops->alloc_buf(&chan->chan);
+		if (!chan->_sdu) {
+			BT_ERR("Unable to allocate buffer for SDU");
+			bt_l2cap_chan_disconnect(&chan->chan);
+			return;
+		}
+		chan->_sdu_len = sdu_len;
+		l2cap_chan_le_recv_seg(chan, buf);
+		return;
+	}
+
+	err = chan->chan.ops->recv(&chan->chan, buf);
+	if (err) {
+		if (err != -EINPROGRESS) {
+			BT_ERR("err %d", err);
+			bt_l2cap_chan_disconnect(&chan->chan);
+		}
+		return;
+	}
+
+	l2cap_chan_send_credits(chan, buf, 1);
+}
+
+static void l2cap_chan_recv_queue(struct bt_l2cap_le_chan *chan,
+				  struct net_buf *buf)
+{
+	if (chan->chan.state == BT_L2CAP_DISCONNECT) {
+		BT_WARN("Ignoring data received while disconnecting");
+		net_buf_unref(buf);
+		return;
+	}
+
+	if (atomic_test_bit(chan->chan.status, BT_L2CAP_STATUS_SHUTDOWN)) {
+		BT_WARN("Ignoring data received while channel has shutdown");
+		net_buf_unref(buf);
+		return;
+	}
+
+	if (!L2CAP_LE_PSM_IS_DYN(chan->chan.psm)) {
+		l2cap_chan_le_recv(chan, buf);
+		net_buf_unref(buf);
+		return;
+	}
+
+	net_buf_put(&chan->rx_queue, buf);
+	k_work_submit(&chan->rx_work);
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+static void l2cap_chan_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+
+	if (L2CAP_LE_CID_IS_DYN(ch->rx.cid)) {
+		l2cap_chan_recv_queue(ch, buf);
+		return;
+	}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
+
+	BT_DBG("chan %p len %u", chan, buf->len);
+
+	chan->ops->recv(chan, buf);
+	net_buf_unref(buf);
+}
+
+void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct bt_l2cap_hdr *hdr;
+	struct bt_l2cap_chan *chan;
+	uint16_t cid;
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		bt_l2cap_br_recv(conn, buf);
+		return;
+	}
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small L2CAP PDU received");
+		net_buf_unref(buf);
+		return;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	cid = sys_le16_to_cpu(hdr->cid);
+
+	BT_DBG("Packet for CID %u len %u", cid, buf->len);
+
+	chan = bt_l2cap_le_lookup_rx_cid(conn, cid);
+	if (!chan) {
+		BT_WARN("Ignoring data for unknown CID 0x%04x", cid);
+		net_buf_unref(buf);
+		return;
+	}
+
+	l2cap_chan_recv(chan, buf);
+}
+
+int bt_l2cap_update_conn_param(struct bt_conn *conn,
+			       const struct bt_le_conn_param *param)
+{
+	struct bt_l2cap_conn_param_req *req;
+	struct net_buf *buf;
+
+	buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_CONN_PARAM_REQ,
+				      get_ident(), sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->min_interval = sys_cpu_to_le16(param->interval_min);
+	req->max_interval = sys_cpu_to_le16(param->interval_max);
+	req->latency = sys_cpu_to_le16(param->latency);
+	req->timeout = sys_cpu_to_le16(param->timeout);
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf);
+
+	return 0;
+}
+
+static void l2cap_connected(struct bt_l2cap_chan *chan)
+{
+	BT_DBG("ch %p cid 0x%04x", BT_L2CAP_LE_CHAN(chan),
+	       BT_L2CAP_LE_CHAN(chan)->rx.cid);
+}
+
+static void l2cap_disconnected(struct bt_l2cap_chan *chan)
+{
+	BT_DBG("ch %p cid 0x%04x", BT_L2CAP_LE_CHAN(chan),
+	       BT_L2CAP_LE_CHAN(chan)->rx.cid);
+}
+
+static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	int i;
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = l2cap_connected,
+		.disconnected = l2cap_disconnected,
+		.recv = l2cap_recv,
+	};
+
+	BT_DBG("l2cap_accept, conn %p handle %u", conn, conn->handle);
+
+	for (i = 0; i < ARRAY_SIZE(bt_l2cap_pool); i++) {
+		struct bt_l2cap *l2cap = &bt_l2cap_pool[i];
+
+		if (l2cap->chan.chan.conn) {
+			continue;
+		}
+
+		l2cap->chan.chan.ops = &ops;
+		*chan = &l2cap->chan.chan;
+
+		return 0;
+	}
+
+	BT_ERR("No available L2CAP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+BT_L2CAP_CHANNEL_DEFINE(le_fixed_chan, BT_L2CAP_CID_LE_SIG, l2cap_accept, NULL);
+
+void bt_l2cap_init(void)
+{
+	if (IS_ENABLED(CONFIG_BT_BREDR)) {
+		bt_l2cap_br_init();
+	}
+}
+
+#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
+static int l2cap_le_connect(struct bt_conn *conn, struct bt_l2cap_le_chan *ch,
+			    uint16_t psm)
+{
+	int err;
+
+	if (psm < L2CAP_LE_PSM_FIXED_START || psm > L2CAP_LE_PSM_DYN_END) {
+		return -EINVAL;
+	}
+
+	l2cap_chan_tx_init(ch);
+	l2cap_chan_rx_init(ch);
+
+	if (!l2cap_chan_add(conn, &ch->chan, l2cap_chan_destroy)) {
+		return -ENOMEM;
+	}
+
+	ch->chan.psm = psm;
+
+	if (conn->sec_level < ch->chan.required_sec_level) {
+		err = bt_conn_set_security(conn, ch->chan.required_sec_level);
+		if (err) {
+			goto fail;
+		}
+
+		atomic_set_bit(ch->chan.status,
+			       BT_L2CAP_STATUS_ENCRYPT_PENDING);
+
+		return 0;
+	}
+
+	err = l2cap_le_conn_req(ch);
+	if (err) {
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	bt_l2cap_chan_remove(conn, &ch->chan);
+	bt_l2cap_chan_del(&ch->chan);
+	return err;
+}
+
+static int l2cap_ecred_init(struct bt_conn *conn,
+			       struct bt_l2cap_le_chan *ch, uint16_t psm)
+{
+
+	if (psm < L2CAP_LE_PSM_FIXED_START || psm > L2CAP_LE_PSM_DYN_END) {
+		return -EINVAL;
+	}
+
+	l2cap_chan_tx_init(ch);
+	l2cap_chan_rx_init(ch);
+
+	if (!l2cap_chan_add(conn, &ch->chan, l2cap_chan_destroy)) {
+		return -ENOMEM;
+	}
+
+	ch->chan.psm = psm;
+
+	BT_DBG("ch %p psm 0x%02x mtu %u mps %u credits %u", ch, ch->chan.psm,
+		ch->rx.mtu, ch->rx.mps, ch->rx.init_credits);
+
+	return 0;
+}
+
+int bt_l2cap_ecred_chan_connect(struct bt_conn *conn,
+				struct bt_l2cap_chan **chan, uint16_t psm)
+{
+	int i, err;
+
+	BT_DBG("conn %p chan %p psm 0x%04x", conn, chan, psm);
+
+	if (!conn || !chan) {
+		return -EINVAL;
+	}
+
+	/* Init non-null channels */
+	for (i = 0; i < L2CAP_ECRED_CHAN_MAX; i++) {
+		if (!chan[i]) {
+			break;
+		}
+
+		err = l2cap_ecred_init(conn, BT_L2CAP_LE_CHAN(chan[i]), psm);
+		if (err < 0) {
+			i--;
+			goto fail;
+		}
+	}
+
+	return l2cap_ecred_conn_req(chan, i);
+fail:
+	/* Remove channels added */
+	for (; i >= 0; i--) {
+		if (!chan[i]) {
+			continue;
+		}
+
+		bt_l2cap_chan_remove(conn, chan[i]);
+	}
+
+	return err;
+}
+
+int bt_l2cap_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			  uint16_t psm)
+{
+	BT_DBG("conn %p chan %p psm 0x%04x", conn, chan, psm);
+
+	if (!conn || conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (!chan) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		return bt_l2cap_br_chan_connect(conn, chan, psm);
+	}
+
+	if (chan->required_sec_level > BT_SECURITY_L4) {
+		return -EINVAL;
+	} else if (chan->required_sec_level == BT_SECURITY_L0) {
+		chan->required_sec_level = BT_SECURITY_L1;
+	}
+
+	return l2cap_le_connect(conn, BT_L2CAP_LE_CHAN(chan), psm);
+}
+
+int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan)
+{
+	struct bt_conn *conn = chan->conn;
+	struct net_buf *buf;
+	struct bt_l2cap_disconn_req *req;
+	struct bt_l2cap_le_chan *ch;
+
+	if (!conn) {
+		return -ENOTCONN;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    conn->type == BT_CONN_TYPE_BR) {
+		return bt_l2cap_br_chan_disconnect(chan);
+	}
+
+	ch = BT_L2CAP_LE_CHAN(chan);
+
+	BT_DBG("chan %p scid 0x%04x dcid 0x%04x", chan, ch->rx.cid,
+	       ch->tx.cid);
+
+	ch->chan.ident = get_ident();
+
+	buf = l2cap_create_le_sig_pdu(NULL, BT_L2CAP_DISCONN_REQ,
+				      ch->chan.ident, sizeof(*req));
+	if (!buf) {
+		return -ENOMEM;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->dcid = sys_cpu_to_le16(ch->rx.cid);
+	req->scid = sys_cpu_to_le16(ch->tx.cid);
+
+	l2cap_chan_send_req(chan, buf, L2CAP_DISC_TIMEOUT);
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_DISCONNECT);
+
+	return 0;
+}
+
+int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap_le_chan *ch = BT_L2CAP_LE_CHAN(chan);
+	int err;
+
+	if (!buf) {
+		return -EINVAL;
+	}
+
+	BT_DBG("chan %p buf %p len %zu", chan, buf, net_buf_frags_len(buf));
+
+	if (!chan->conn || chan->conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (atomic_test_bit(chan->status, BT_L2CAP_STATUS_SHUTDOWN)) {
+		return -ESHUTDOWN;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BREDR) &&
+	    chan->conn->type == BT_CONN_TYPE_BR) {
+		return bt_l2cap_br_chan_send(chan, buf);
+	}
+
+	/* Queue if there are pending segments left from previous packet or
+	 * there are no credits available.
+	 */
+	if (ch->tx_buf || !k_fifo_is_empty(&ch->tx_queue) ||
+	    !atomic_get(&ch->tx.credits)) {
+		data_sent(buf)->len = 0;
+		net_buf_put(&ch->tx_queue, buf);
+		k_work_submit(&ch->tx_work);
+		return 0;
+	}
+
+	err = l2cap_chan_le_send_sdu(ch, &buf, 0);
+	if (err < 0) {
+		if (err == -EAGAIN && data_sent(buf)->len) {
+			/* Queue buffer if at least one segment could be sent */
+			net_buf_put(&ch->tx_queue, buf);
+			return data_sent(buf)->len;
+		}
+		BT_ERR("failed to send message %d", err);
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_br.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_br.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_br.c	(working copy)
@@ -0,0 +1,1555 @@
+/* l2cap_br.c - L2CAP BREDR oriented handling */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <drivers/bluetooth/hci_driver.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_L2CAP)
+#define LOG_MODULE_NAME bt_l2cap_br
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "avdtp_internal.h"
+#include "a2dp_internal.h"
+#include "rfcomm_internal.h"
+#include "sdp_internal.h"
+
+#define BR_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_br_chan, chan)
+#define BR_CHAN_RTX(_w) CONTAINER_OF(_w, struct bt_l2cap_br_chan, chan.rtx_work)
+
+#define L2CAP_BR_PSM_START	0x0001
+#define L2CAP_BR_PSM_END	0xffff
+
+#define L2CAP_BR_CID_DYN_START	0x0040
+#define L2CAP_BR_CID_DYN_END	0xffff
+#define L2CAP_BR_CID_IS_DYN(_cid) \
+	(_cid >= L2CAP_BR_CID_DYN_START && _cid <= L2CAP_BR_CID_DYN_END)
+
+#define L2CAP_BR_MIN_MTU	48
+#define L2CAP_BR_DEFAULT_MTU	672
+
+#define L2CAP_BR_PSM_SDP	0x0001
+
+#define L2CAP_BR_INFO_TIMEOUT		K_SECONDS(4)
+#define L2CAP_BR_CFG_TIMEOUT		K_SECONDS(4)
+#define L2CAP_BR_DISCONN_TIMEOUT	K_SECONDS(1)
+#define L2CAP_BR_CONN_TIMEOUT		K_SECONDS(40)
+
+/*
+ * L2CAP extended feature mask:
+ * BR/EDR fixed channel support enabled
+ */
+#define L2CAP_FEAT_FIXED_CHAN_MASK	0x00000080
+
+enum {
+	/* Connection oriented channels flags */
+	L2CAP_FLAG_CONN_LCONF_DONE,	/* local config accepted by remote */
+	L2CAP_FLAG_CONN_RCONF_DONE,	/* remote config accepted by local */
+	L2CAP_FLAG_CONN_ACCEPTOR,	/* getting incoming connection req */
+	L2CAP_FLAG_CONN_PENDING,	/* remote sent pending result in rsp */
+
+	/* Signaling channel flags */
+	L2CAP_FLAG_SIG_INFO_PENDING,	/* retrieving remote l2cap info */
+	L2CAP_FLAG_SIG_INFO_DONE,	/* remote l2cap info is done */
+
+	/* fixed channels flags */
+	L2CAP_FLAG_FIXED_CONNECTED,		/* fixed connected */
+};
+
+static sys_slist_t br_servers;
+
+
+/* Pool for outgoing BR/EDR signaling packets, min MTU is 48 */
+NET_BUF_POOL_FIXED_DEFINE(br_sig_pool, CONFIG_BT_MAX_CONN,
+			  BT_L2CAP_BUF_SIZE(L2CAP_BR_MIN_MTU), NULL);
+
+/* BR/EDR L2CAP signalling channel specific context */
+struct bt_l2cap_br {
+	/* The channel this context is associated with */
+	struct bt_l2cap_br_chan	chan;
+	uint8_t			info_ident;
+	uint8_t			info_fixed_chan;
+	uint32_t			info_feat_mask;
+};
+
+static struct bt_l2cap_br bt_l2cap_br_pool[CONFIG_BT_MAX_CONN];
+
+struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
+						uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BR_CHAN(chan)->rx.cid == cid) {
+			return chan;
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_l2cap_chan *bt_l2cap_br_lookup_tx_cid(struct bt_conn *conn,
+						uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BR_CHAN(chan)->tx.cid == cid) {
+			return chan;
+		}
+	}
+
+	return NULL;
+}
+
+static struct bt_l2cap_br_chan*
+l2cap_br_chan_alloc_cid(struct bt_conn *conn, struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
+	uint16_t cid;
+
+	/*
+	 * No action needed if there's already a CID allocated, e.g. in
+	 * the case of a fixed channel.
+	 */
+	if (ch->rx.cid > 0) {
+		return ch;
+	}
+
+	/*
+	 * L2CAP_BR_CID_DYN_END is 0xffff so we don't check against it since
+	 * cid is uint16_t, just check against uint16_t overflow
+	 */
+	for (cid = L2CAP_BR_CID_DYN_START; cid; cid++) {
+		if (!bt_l2cap_br_lookup_rx_cid(conn, cid)) {
+			ch->rx.cid = cid;
+			return ch;
+		}
+	}
+
+	return NULL;
+}
+
+static void l2cap_br_chan_cleanup(struct bt_l2cap_chan *chan)
+{
+	bt_l2cap_chan_remove(chan->conn, chan);
+	bt_l2cap_chan_del(chan);
+}
+
+static void l2cap_br_chan_destroy(struct bt_l2cap_chan *chan)
+{
+	BT_DBG("chan %p cid 0x%04x", BR_CHAN(chan), BR_CHAN(chan)->rx.cid);
+
+	/* Cancel ongoing work */
+	//k_delayed_work_cancel(&chan->rtx_work);
+
+	atomic_clear(BR_CHAN(chan)->flags);
+}
+
+static void l2cap_br_rtx_timeout(struct k_work *work)
+{
+	struct bt_l2cap_br_chan *chan = BR_CHAN_RTX(work);
+
+	BT_WARN("chan %p timeout", chan);
+
+	if (chan->rx.cid == BT_L2CAP_CID_BR_SIG) {
+		BT_DBG("Skip BR/EDR signalling channel ");
+		atomic_clear_bit(chan->flags, L2CAP_FLAG_SIG_INFO_PENDING);
+		return;
+	}
+
+	BT_DBG("chan %p %s scid 0x%04x", chan,
+	       bt_l2cap_chan_state_str(chan->chan.state),
+	       chan->rx.cid);
+
+	switch (chan->chan.state) {
+	case BT_L2CAP_CONFIG:
+		bt_l2cap_br_chan_disconnect(&chan->chan);
+		break;
+	case BT_L2CAP_DISCONNECT:
+	case BT_L2CAP_CONNECT:
+		l2cap_br_chan_cleanup(&chan->chan);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool l2cap_br_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			      bt_l2cap_chan_destroy_t destroy)
+{
+	struct bt_l2cap_br_chan *ch = l2cap_br_chan_alloc_cid(conn, chan);
+
+	if (!ch) {
+		BT_DBG("Unable to allocate L2CAP CID");
+		return false;
+	}
+
+	k_delayed_work_init(&chan->rtx_work, l2cap_br_rtx_timeout);
+	bt_l2cap_chan_add(conn, chan, destroy);
+
+	return true;
+}
+
+static uint8_t l2cap_br_get_ident(void)
+{
+	static uint8_t ident;
+
+	ident++;
+	/* handle integer overflow (0 is not valid) */
+	if (!ident) {
+		ident++;
+	}
+
+	return ident;
+}
+
+static void l2cap_br_chan_send_req(struct bt_l2cap_br_chan *chan,
+				   struct net_buf *buf, k_timeout_t timeout)
+{
+	/* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part A] page 126:
+	 *
+	 * The value of this timer is implementation-dependent but the minimum
+	 * initial value is 1 second and the maximum initial value is 60
+	 * seconds. One RTX timer shall exist for each outstanding signaling
+	 * request, including each Echo Request. The timer disappears on the
+	 * final expiration, when the response is received, or the physical
+	 * link is lost.
+	 */
+	k_delayed_work_submit(&chan->chan.rtx_work, timeout);
+
+	bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_BR_SIG, buf);
+}
+
+static void l2cap_br_get_info(struct bt_l2cap_br *l2cap, uint16_t info_type)
+{
+	struct bt_l2cap_info_req *info;
+	struct net_buf *buf;
+	struct bt_l2cap_sig_hdr *hdr;
+
+	BT_DBG("info type %u", info_type);
+
+	if (atomic_test_bit(l2cap->chan.flags, L2CAP_FLAG_SIG_INFO_PENDING)) {
+		return;
+	}
+
+	switch (info_type) {
+	case BT_L2CAP_INFO_FEAT_MASK:
+	case BT_L2CAP_INFO_FIXED_CHAN:
+		break;
+	default:
+		BT_WARN("Unsupported info type %u", info_type);
+		return;
+	}
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	atomic_set_bit(l2cap->chan.flags, L2CAP_FLAG_SIG_INFO_PENDING);
+	l2cap->info_ident = l2cap_br_get_ident();
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_INFO_REQ;
+	hdr->ident = l2cap->info_ident;
+	hdr->len = sys_cpu_to_le16(sizeof(*info));
+
+	info = net_buf_add(buf, sizeof(*info));
+	info->type = sys_cpu_to_le16(info_type);
+
+	l2cap_br_chan_send_req(&l2cap->chan, buf, L2CAP_BR_INFO_TIMEOUT);
+}
+
+static void connect_fixed_channel(struct bt_l2cap_br_chan *chan)
+{
+	if (atomic_test_and_set_bit(chan->flags, L2CAP_FLAG_FIXED_CONNECTED)) {
+		return;
+	}
+
+	if (chan->chan.ops && chan->chan.ops->connected) {
+		chan->chan.ops->connected(&chan->chan);
+	}
+}
+
+static void connect_optional_fixed_channels(struct bt_l2cap_br *l2cap)
+{
+	/* can be change to loop if more BR/EDR fixed channels are added */
+	if (l2cap->info_fixed_chan & BIT(BT_L2CAP_CID_BR_SMP)) {
+		struct bt_l2cap_chan *chan;
+
+		chan = bt_l2cap_br_lookup_rx_cid(l2cap->chan.chan.conn,
+						 BT_L2CAP_CID_BR_SMP);
+		if (chan) {
+			connect_fixed_channel(BR_CHAN(chan));
+		}
+	}
+}
+
+static int l2cap_br_info_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,
+			     struct net_buf *buf)
+{
+	struct bt_l2cap_info_rsp *rsp;
+	uint16_t type, result;
+	int err = 0;
+
+	if (atomic_test_bit(l2cap->chan.flags, L2CAP_FLAG_SIG_INFO_DONE)) {
+		return 0;
+	}
+
+	if (atomic_test_and_clear_bit(l2cap->chan.flags,
+				      L2CAP_FLAG_SIG_INFO_PENDING)) {
+		/*
+		 * Release RTX timer since got the response & there's pending
+		 * command request.
+		 */
+		k_delayed_work_cancel(&l2cap->chan.chan.rtx_work);
+	}
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small info rsp packet size");
+		err = -EINVAL;
+		goto done;
+	}
+
+	if (ident != l2cap->info_ident) {
+		BT_WARN("Idents mismatch");
+		err = -EINVAL;
+		goto done;
+	}
+
+	rsp = net_buf_pull_mem(buf, sizeof(*rsp));
+	result = sys_le16_to_cpu(rsp->result);
+	if (result != BT_L2CAP_INFO_SUCCESS) {
+		BT_WARN("Result unsuccessful");
+		err = -EINVAL;
+		goto done;
+	}
+
+	type = sys_le16_to_cpu(rsp->type);
+
+	switch (type) {
+	case BT_L2CAP_INFO_FEAT_MASK:
+		l2cap->info_feat_mask = net_buf_pull_le32(buf);
+		BT_DBG("remote info mask 0x%08x", l2cap->info_feat_mask);
+
+		if (!(l2cap->info_feat_mask & L2CAP_FEAT_FIXED_CHAN_MASK)) {
+			break;
+		}
+
+		l2cap_br_get_info(l2cap, BT_L2CAP_INFO_FIXED_CHAN);
+		return 0;
+	case BT_L2CAP_INFO_FIXED_CHAN:
+		l2cap->info_fixed_chan = net_buf_pull_u8(buf);
+		BT_DBG("remote fixed channel mask 0x%02x",
+		       l2cap->info_fixed_chan);
+
+		connect_optional_fixed_channels(l2cap);
+
+		break;
+	default:
+		BT_WARN("type 0x%04x unsupported", type);
+		err = -EINVAL;
+		break;
+	}
+done:
+	atomic_set_bit(l2cap->chan.flags, L2CAP_FLAG_SIG_INFO_DONE);
+	l2cap->info_ident = 0U;
+	return err;
+}
+
+static uint8_t get_fixed_channels_mask(void)
+{
+	uint8_t mask = 0U;
+
+	/* this needs to be enhanced if AMP Test Manager support is added */
+	Z_STRUCT_SECTION_FOREACH(bt_l2cap_br_fixed_chan, fchan) {
+		mask |= BIT(fchan->cid);
+	}
+
+	return mask;
+}
+
+static int l2cap_br_info_req(struct bt_l2cap_br *l2cap, uint8_t ident,
+			     struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_info_req *req = (void *)buf->data;
+	struct bt_l2cap_info_rsp *rsp;
+	struct net_buf *rsp_buf;
+	struct bt_l2cap_sig_hdr *hdr_info;
+	uint16_t type;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small info req packet size");
+		return -EINVAL;
+	}
+
+	rsp_buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	type = sys_le16_to_cpu(req->type);
+	BT_DBG("type 0x%04x", type);
+
+	hdr_info = net_buf_add(rsp_buf, sizeof(*hdr_info));
+	hdr_info->code = BT_L2CAP_INFO_RSP;
+	hdr_info->ident = ident;
+
+	rsp = net_buf_add(rsp_buf, sizeof(*rsp));
+
+	switch (type) {
+	case BT_L2CAP_INFO_FEAT_MASK:
+		rsp->type = sys_cpu_to_le16(BT_L2CAP_INFO_FEAT_MASK);
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_INFO_SUCCESS);
+		net_buf_add_le32(rsp_buf, L2CAP_FEAT_FIXED_CHAN_MASK);
+		hdr_info->len = sys_cpu_to_le16(sizeof(*rsp) + sizeof(uint32_t));
+		break;
+	case BT_L2CAP_INFO_FIXED_CHAN:
+		rsp->type = sys_cpu_to_le16(BT_L2CAP_INFO_FIXED_CHAN);
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_INFO_SUCCESS);
+		/* fixed channel mask protocol data is 8 octets wide */
+		(void)memset(net_buf_add(rsp_buf, 8), 0, 8);
+		rsp->data[0] = get_fixed_channels_mask();
+
+		hdr_info->len = sys_cpu_to_le16(sizeof(*rsp) + 8);
+		break;
+	default:
+		rsp->type = req->type;
+		rsp->result = sys_cpu_to_le16(BT_L2CAP_INFO_NOTSUPP);
+		hdr_info->len = sys_cpu_to_le16(sizeof(*rsp));
+		break;
+	}
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_BR_SIG, rsp_buf);
+
+	return 0;
+}
+
+void bt_l2cap_br_connected(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+
+	Z_STRUCT_SECTION_FOREACH(bt_l2cap_br_fixed_chan, fchan) {
+		struct bt_l2cap_br_chan *ch;
+
+		if (!fchan->accept) {
+			continue;
+		}
+
+		if (fchan->accept(conn, &chan) < 0) {
+			continue;
+		}
+
+		ch = BR_CHAN(chan);
+
+		ch->rx.cid = fchan->cid;
+		ch->tx.cid = fchan->cid;
+
+		if (!l2cap_br_chan_add(conn, chan, NULL)) {
+			return;
+		}
+
+		/*
+		 * other fixed channels will be connected after Information
+		 * Response is received
+		 */
+		if (fchan->cid == BT_L2CAP_CID_BR_SIG) {
+			struct bt_l2cap_br *sig_ch;
+
+			connect_fixed_channel(ch);
+
+			sig_ch = CONTAINER_OF(ch, struct bt_l2cap_br, chan);
+			l2cap_br_get_info(sig_ch, BT_L2CAP_INFO_FEAT_MASK);
+		}
+	}
+}
+
+static struct bt_l2cap_server *l2cap_br_server_lookup_psm(uint16_t psm)
+{
+	struct bt_l2cap_server *server;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&br_servers, server, node) {
+		if (server->psm == psm) {
+			return server;
+		}
+	}
+
+	return NULL;
+}
+
+static void l2cap_br_conf_add_mtu(struct net_buf *buf, const uint16_t mtu)
+{
+	net_buf_add_u8(buf, BT_L2CAP_CONF_OPT_MTU);
+	net_buf_add_u8(buf, sizeof(mtu));
+	net_buf_add_le16(buf, mtu);
+}
+
+static void l2cap_br_conf(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_sig_hdr *hdr;
+	struct bt_l2cap_conf_req *conf;
+	struct net_buf *buf;
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_CONF_REQ;
+	hdr->ident = l2cap_br_get_ident();
+	conf = net_buf_add(buf, sizeof(*conf));
+	(void)memset(conf, 0, sizeof(*conf));
+
+	conf->dcid = sys_cpu_to_le16(BR_CHAN(chan)->tx.cid);
+	/*
+	 * Add MTU option if app set non default BR/EDR L2CAP MTU,
+	 * otherwise sent empty configuration data meaning default MTU
+	 * to be used.
+	 */
+	if (BR_CHAN(chan)->rx.mtu != L2CAP_BR_DEFAULT_MTU) {
+		l2cap_br_conf_add_mtu(buf, BR_CHAN(chan)->rx.mtu);
+	}
+
+	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
+
+	/*
+	 * TODO:
+	 * might be needed to start tracking number of configuration iterations
+	 * on both directions
+	 */
+	l2cap_br_chan_send_req(BR_CHAN(chan), buf, L2CAP_BR_CFG_TIMEOUT);
+}
+
+enum l2cap_br_conn_security_result {
+	L2CAP_CONN_SECURITY_PASSED,
+	L2CAP_CONN_SECURITY_REJECT,
+	L2CAP_CONN_SECURITY_PENDING
+};
+
+/*
+ * Security helper against channel connection.
+ * Returns L2CAP_CONN_SECURITY_PASSED if:
+ * - existing security on link is applicable for requested PSM in connection,
+ * - legacy (non SSP) devices connecting with low security requirements,
+ * Returns L2CAP_CONN_SECURITY_PENDING if:
+ * - channel connection process is on hold since there were valid security
+ *   conditions triggering authentication indirectly in subcall.
+ * Returns L2CAP_CONN_SECURITY_REJECT if:
+ * - bt_conn_set_security API returns < 0.
+ */
+
+static enum l2cap_br_conn_security_result
+l2cap_br_conn_security(struct bt_l2cap_chan *chan, const uint16_t psm)
+{
+	int check;
+
+	/* For SDP PSM there's no need to change existing security on link */
+	if (chan->required_sec_level == BT_SECURITY_L0) {
+		return L2CAP_CONN_SECURITY_PASSED;
+	}
+
+	/*
+	 * No link key needed for legacy devices (pre 2.1) and when low security
+	 * level is required.
+	 */
+	if (chan->required_sec_level == BT_SECURITY_L1 &&
+	    !BT_FEAT_HOST_SSP(chan->conn->br.features)) {
+		return L2CAP_CONN_SECURITY_PASSED;
+	}
+
+	switch (chan->required_sec_level) {
+	case BT_SECURITY_L4:
+	case BT_SECURITY_L3:
+	case BT_SECURITY_L2:
+		break;
+	default:
+		/*
+		 * For non SDP PSM connections GAP's Security Mode 4 requires at
+		 * least unauthenticated link key and enabled encryption if
+		 * remote supports SSP before any L2CAP CoC traffic. So preset
+		 * local to MEDIUM security to trigger it if needed.
+		 */
+		if (BT_FEAT_HOST_SSP(chan->conn->br.features)) {
+			chan->required_sec_level = BT_SECURITY_L2;
+		}
+		break;
+	}
+
+	check = bt_conn_set_security(chan->conn, chan->required_sec_level);
+
+	/*
+	 * Check case when on existing connection security level already covers
+	 * channel (service) security requirements against link security and
+	 * bt_conn_set_security API returns 0 what implies also there was no
+	 * need to trigger authentication.
+	 */
+	if (check == 0 &&
+	    chan->conn->sec_level >= chan->required_sec_level) {
+		return L2CAP_CONN_SECURITY_PASSED;
+	}
+
+	/*
+	 * If 'check' still holds 0, it means local host just sent HCI
+	 * authentication command to start procedure to increase link security
+	 * since service/profile requires that.
+	 */
+	if (check == 0) {
+		return L2CAP_CONN_SECURITY_PENDING;
+	};
+
+	/*
+	 * For any other values in 'check' it means there was internal
+	 * validation condition forbidding to start authentication at this
+	 * moment.
+	 */
+	return L2CAP_CONN_SECURITY_REJECT;
+}
+
+static void l2cap_br_send_conn_rsp(struct bt_conn *conn, uint16_t scid,
+				  uint16_t dcid, uint8_t ident, uint16_t result)
+{
+	struct net_buf *buf;
+	struct bt_l2cap_conn_rsp *rsp;
+	struct bt_l2cap_sig_hdr *hdr;
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_CONN_RSP;
+	hdr->ident = ident;
+	hdr->len = sys_cpu_to_le16(sizeof(*rsp));
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->dcid = sys_cpu_to_le16(dcid);
+	rsp->scid = sys_cpu_to_le16(scid);
+	rsp->result = sys_cpu_to_le16(result);
+
+	if (result == BT_L2CAP_BR_PENDING) {
+		rsp->status = sys_cpu_to_le16(BT_L2CAP_CS_AUTHEN_PEND);
+	} else {
+		rsp->status = sys_cpu_to_le16(BT_L2CAP_CS_NO_INFO);
+	}
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_BR_SIG, buf);
+}
+
+static int l2cap_br_conn_req_reply(struct bt_l2cap_chan *chan, uint16_t result)
+{
+	/* Send response to connection request only when in acceptor role */
+	if (!atomic_test_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_ACCEPTOR)) {
+		return -ESRCH;
+	}
+
+	l2cap_br_send_conn_rsp(chan->conn, BR_CHAN(chan)->tx.cid,
+			       BR_CHAN(chan)->rx.cid, chan->ident, result);
+	chan->ident = 0U;
+
+	return 0;
+}
+
+static void l2cap_br_conn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
+			      struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_server *server;
+	struct bt_l2cap_conn_req *req = (void *)buf->data;
+	uint16_t psm, scid, result;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small L2CAP conn req packet size");
+		return;
+	}
+
+	psm = sys_le16_to_cpu(req->psm);
+	scid = sys_le16_to_cpu(req->scid);
+
+	BT_DBG("psm 0x%02x scid 0x%04x", psm, scid);
+
+	/* Check if there is a server registered */
+	server = l2cap_br_server_lookup_psm(psm);
+	if (!server) {
+		result = BT_L2CAP_BR_ERR_PSM_NOT_SUPP;
+		goto no_chan;
+	}
+
+	/*
+	 * Report security violation for non SDP channel without encryption when
+	 * remote supports SSP.
+	 */
+	if (server->sec_level != BT_SECURITY_L0 &&
+	    BT_FEAT_HOST_SSP(conn->br.features) && !conn->encrypt) {
+		result = BT_L2CAP_BR_ERR_SEC_BLOCK;
+		goto no_chan;
+	}
+
+	if (!L2CAP_BR_CID_IS_DYN(scid)) {
+		result = BT_L2CAP_BR_ERR_INVALID_SCID;
+		goto no_chan;
+	}
+
+	chan = bt_l2cap_br_lookup_tx_cid(conn, scid);
+	if (chan) {
+		/*
+		 * we have a chan here but this is due to SCID being already in
+		 * use so it is not channel we are suppose to pass to
+		 * l2cap_br_conn_req_reply as wrong DCID would be used
+		 */
+		result = BT_L2CAP_BR_ERR_SCID_IN_USE;
+		goto no_chan;
+	}
+
+	/*
+	 * Request server to accept the new connection and allocate the
+	 * channel. If no free channels available for PSM server reply with
+	 * proper result and quit since chan pointer is uninitialized then.
+	 */
+	if (server->accept(conn, &chan) < 0) {
+		result = BT_L2CAP_BR_ERR_NO_RESOURCES;
+		goto no_chan;
+	}
+
+	chan->required_sec_level = server->sec_level;
+
+	l2cap_br_chan_add(conn, chan, l2cap_br_chan_destroy);
+	BR_CHAN(chan)->tx.cid = scid;
+	chan->ident = ident;
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECT);
+	atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_ACCEPTOR);
+
+	/* Disable fragmentation of l2cap rx pdu */
+	BR_CHAN(chan)->rx.mtu = MIN(BR_CHAN(chan)->rx.mtu,
+				    CONFIG_BT_L2CAP_RX_MTU);
+
+	switch (l2cap_br_conn_security(chan, psm)) {
+	case L2CAP_CONN_SECURITY_PENDING:
+		result = BT_L2CAP_BR_PENDING;
+		/* TODO: auth timeout */
+		break;
+	case L2CAP_CONN_SECURITY_PASSED:
+		result = BT_L2CAP_BR_SUCCESS;
+		break;
+	case L2CAP_CONN_SECURITY_REJECT:
+	default:
+		result = BT_L2CAP_BR_ERR_SEC_BLOCK;
+		break;
+	}
+	/* Reply on connection request as acceptor */
+	l2cap_br_conn_req_reply(chan, result);
+
+	if (result != BT_L2CAP_BR_SUCCESS) {
+		/* Disconnect link when security rules were violated */
+		if (result == BT_L2CAP_BR_ERR_SEC_BLOCK) {
+			bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
+		}
+
+		return;
+	}
+
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
+	l2cap_br_conf(chan);
+	return;
+
+no_chan:
+	l2cap_br_send_conn_rsp(conn, scid, 0, ident, result);
+}
+
+static void l2cap_br_conf_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,
+			      uint16_t len, struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_conf_rsp *rsp = (void *)buf->data;
+	uint16_t flags, scid, result, opt_len;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small L2CAP conf rsp packet size");
+		return;
+	}
+
+	flags = sys_le16_to_cpu(rsp->flags);
+	scid = sys_le16_to_cpu(rsp->scid);
+	result = sys_le16_to_cpu(rsp->result);
+	opt_len = len - sizeof(*rsp);
+
+	BT_DBG("scid 0x%04x flags 0x%02x result 0x%02x len %u", scid, flags,
+	       result, opt_len);
+
+	chan = bt_l2cap_br_lookup_rx_cid(conn, scid);
+	if (!chan) {
+		BT_ERR("channel mismatch!");
+		return;
+	}
+
+	/* Release RTX work since got the response */
+	k_delayed_work_cancel(&chan->rtx_work);
+
+	/*
+	 * TODO: handle other results than success and parse response data if
+	 * available
+	 */
+	switch (result) {
+	case BT_L2CAP_CONF_SUCCESS:
+		atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_LCONF_DONE);
+
+		if (chan->state == BT_L2CAP_CONFIG &&
+		    atomic_test_bit(BR_CHAN(chan)->flags,
+				    L2CAP_FLAG_CONN_RCONF_DONE)) {
+			BT_DBG("scid 0x%04x rx MTU %u dcid 0x%04x tx MTU %u",
+			       BR_CHAN(chan)->rx.cid, BR_CHAN(chan)->rx.mtu,
+			       BR_CHAN(chan)->tx.cid, BR_CHAN(chan)->tx.mtu);
+
+			bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECTED);
+			if (chan->ops && chan->ops->connected) {
+				chan->ops->connected(chan);
+			}
+		}
+		break;
+	default:
+		/* currently disconnect channel on non success result */
+		bt_l2cap_chan_disconnect(chan);
+		break;
+	}
+}
+
+int bt_l2cap_br_server_register(struct bt_l2cap_server *server)
+{
+	if (server->psm < L2CAP_BR_PSM_START || !server->accept) {
+		return -EINVAL;
+	}
+
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((server->psm & 0x0101) != 0x0001) {
+		return -EINVAL;
+	}
+
+	if (server->sec_level > BT_SECURITY_L4) {
+		return -EINVAL;
+	} else if (server->sec_level == BT_SECURITY_L0 &&
+		   server->psm != L2CAP_BR_PSM_SDP) {
+		server->sec_level = BT_SECURITY_L1;
+	}
+
+	/* Check if given PSM is already in use */
+	if (l2cap_br_server_lookup_psm(server->psm)) {
+		BT_DBG("PSM already registered");
+		return -EADDRINUSE;
+	}
+
+	BT_DBG("PSM 0x%04x", server->psm);
+
+	sys_slist_append(&br_servers, &server->node);
+
+	return 0;
+}
+
+static void l2cap_br_send_reject(struct bt_conn *conn, uint8_t ident,
+				 uint16_t reason, void *data, uint8_t data_len)
+{
+	struct bt_l2cap_cmd_reject *rej;
+	struct bt_l2cap_sig_hdr *hdr;
+	struct net_buf *buf;
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_CMD_REJECT;
+	hdr->ident = ident;
+	hdr->len = sys_cpu_to_le16(sizeof(*rej) + data_len);
+
+	rej = net_buf_add(buf, sizeof(*rej));
+	rej->reason = sys_cpu_to_le16(reason);
+
+	/*
+	 * optional data if available must be already in little-endian format
+	 * made by caller.and be compliant with Core 4.2 [Vol 3, Part A, 4.1,
+	 * table 4.4]
+	 */
+	if (data) {
+		net_buf_add_mem(buf, data, data_len);
+	}
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_BR_SIG, buf);
+}
+
+static uint16_t l2cap_br_conf_opt_mtu(struct bt_l2cap_chan *chan,
+				   struct net_buf *buf, size_t len)
+{
+	uint16_t mtu, result = BT_L2CAP_CONF_SUCCESS;
+
+	/* Core 4.2 [Vol 3, Part A, 5.1] MTU payload length */
+	if (len != 2) {
+		BT_ERR("tx MTU length %zu invalid", len);
+		result = BT_L2CAP_CONF_REJECT;
+		goto done;
+	}
+
+	/* pulling MTU value moves buf data to next option item */
+	mtu = net_buf_pull_le16(buf);
+	if (mtu < L2CAP_BR_MIN_MTU) {
+		result = BT_L2CAP_CONF_UNACCEPT;
+		BR_CHAN(chan)->tx.mtu = L2CAP_BR_MIN_MTU;
+		BT_DBG("tx MTU %u invalid", mtu);
+		goto done;
+	}
+
+	BR_CHAN(chan)->tx.mtu = mtu;
+	BT_DBG("tx MTU %u", mtu);
+done:
+	return result;
+}
+
+static void l2cap_br_conf_req(struct bt_l2cap_br *l2cap, uint8_t ident,
+			      uint16_t len, struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_conf_req *req;
+	struct bt_l2cap_sig_hdr *hdr;
+	struct bt_l2cap_conf_rsp *rsp;
+	struct bt_l2cap_conf_opt *opt;
+	uint16_t flags, dcid, opt_len, hint, result = BT_L2CAP_CONF_SUCCESS;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small L2CAP conf req packet size");
+		return;
+	}
+
+	req = net_buf_pull_mem(buf, sizeof(*req));
+	flags = sys_le16_to_cpu(req->flags);
+	dcid = sys_le16_to_cpu(req->dcid);
+	opt_len = len - sizeof(*req);
+
+	BT_DBG("dcid 0x%04x flags 0x%02x len %u", dcid, flags, opt_len);
+
+	chan = bt_l2cap_br_lookup_rx_cid(conn, dcid);
+	if (!chan) {
+		BT_ERR("rx channel mismatch!");
+		struct bt_l2cap_cmd_reject_cid_data data = {.scid = req->dcid,
+							    .dcid = 0,
+							   };
+
+		l2cap_br_send_reject(conn, ident, BT_L2CAP_REJ_INVALID_CID,
+				     &data, sizeof(data));
+		return;
+	}
+
+	if (!opt_len) {
+		BT_DBG("tx default MTU %u", L2CAP_BR_DEFAULT_MTU);
+		BR_CHAN(chan)->tx.mtu = L2CAP_BR_DEFAULT_MTU;
+		goto send_rsp;
+	}
+
+	while (buf->len >= sizeof(*opt)) {
+		opt = net_buf_pull_mem(buf, sizeof(*opt));
+
+		/* make sure opt object can get safe dereference in iteration */
+		if (buf->len < opt->len) {
+			BT_ERR("Received too short option data");
+			result = BT_L2CAP_CONF_REJECT;
+			break;
+		}
+
+		hint = opt->type & BT_L2CAP_CONF_HINT;
+
+		switch (opt->type & BT_L2CAP_CONF_MASK) {
+		case BT_L2CAP_CONF_OPT_MTU:
+			/* getting MTU modifies buf internals */
+			result = l2cap_br_conf_opt_mtu(chan, buf, opt->len);
+			/*
+			 * MTU is done. For now bailout the loop but later on
+			 * there can be a need to continue checking next options
+			 * that are after MTU value and then goto is not proper
+			 * way out here.
+			 */
+			goto send_rsp;
+		default:
+			if (!hint) {
+				BT_DBG("option %u not handled", opt->type);
+				goto send_rsp;
+			}
+
+			/* Update buffer to point at next option */
+			net_buf_pull(buf, opt->len);
+			break;
+		}
+	}
+
+send_rsp:
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_CONF_RSP;
+	hdr->ident = ident;
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	(void)memset(rsp, 0, sizeof(*rsp));
+
+	rsp->result = sys_cpu_to_le16(result);
+	rsp->scid = sys_cpu_to_le16(BR_CHAN(chan)->tx.cid);
+
+	/*
+	 * TODO: If options other than MTU bacame meaningful then processing
+	 * the options chain need to be modified and taken into account when
+	 * sending back to peer.
+	 */
+	if (result == BT_L2CAP_CONF_UNACCEPT) {
+		l2cap_br_conf_add_mtu(buf, BR_CHAN(chan)->tx.mtu);
+	}
+
+	hdr->len = sys_cpu_to_le16(buf->len - sizeof(*hdr));
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_BR_SIG, buf);
+
+	if (result != BT_L2CAP_CONF_SUCCESS) {
+		return;
+	}
+
+	atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_RCONF_DONE);
+
+	if (atomic_test_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_LCONF_DONE) &&
+	    chan->state == BT_L2CAP_CONFIG) {
+		BT_DBG("scid 0x%04x rx MTU %u dcid 0x%04x tx MTU %u",
+		       BR_CHAN(chan)->rx.cid, BR_CHAN(chan)->rx.mtu,
+		       BR_CHAN(chan)->tx.cid, BR_CHAN(chan)->tx.mtu);
+
+		bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECTED);
+		if (chan->ops && chan->ops->connected) {
+			chan->ops->connected(chan);
+		}
+	}
+}
+
+static struct bt_l2cap_br_chan *l2cap_br_remove_tx_cid(struct bt_conn *conn,
+						       uint16_t cid)
+{
+	struct bt_l2cap_chan *chan;
+	sys_snode_t *prev = NULL;
+
+	/* Protect fixed channels against accidental removal */
+	if (!L2CAP_BR_CID_IS_DYN(cid)) {
+		return NULL;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		if (BR_CHAN(chan)->tx.cid == cid) {
+			sys_slist_remove(&conn->channels, prev, &chan->node);
+			return BR_CHAN(chan);
+		}
+
+		prev = &chan->node;
+	}
+
+	return NULL;
+}
+
+static void l2cap_br_disconn_req(struct bt_l2cap_br *l2cap, uint8_t ident,
+				 struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_br_chan *chan;
+	struct bt_l2cap_disconn_req *req = (void *)buf->data;
+	struct bt_l2cap_disconn_rsp *rsp;
+	struct bt_l2cap_sig_hdr *hdr;
+	uint16_t scid, dcid;
+
+	if (buf->len < sizeof(*req)) {
+		BT_ERR("Too small disconn req packet size");
+		return;
+	}
+
+	dcid = sys_le16_to_cpu(req->dcid);
+	scid = sys_le16_to_cpu(req->scid);
+
+	BT_DBG("scid 0x%04x dcid 0x%04x", dcid, scid);
+
+	chan = l2cap_br_remove_tx_cid(conn, scid);
+	if (!chan) {
+		struct bt_l2cap_cmd_reject_cid_data data;
+
+		data.scid = req->scid;
+		data.dcid = req->dcid;
+		l2cap_br_send_reject(conn, ident, BT_L2CAP_REJ_INVALID_CID,
+				     &data, sizeof(data));
+		return;
+	}
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_DISCONN_RSP;
+	hdr->ident = ident;
+	hdr->len = sys_cpu_to_le16(sizeof(*rsp));
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->dcid = sys_cpu_to_le16(chan->rx.cid);
+	rsp->scid = sys_cpu_to_le16(chan->tx.cid);
+
+	bt_l2cap_chan_del(&chan->chan);
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_BR_SIG, buf);
+}
+
+static void l2cap_br_connected(struct bt_l2cap_chan *chan)
+{
+	BT_DBG("ch %p cid 0x%04x", BR_CHAN(chan), BR_CHAN(chan)->rx.cid);
+}
+
+static void l2cap_br_disconnected(struct bt_l2cap_chan *chan)
+{
+	BT_DBG("ch %p cid 0x%04x", BR_CHAN(chan), BR_CHAN(chan)->rx.cid);
+
+	if (atomic_test_and_clear_bit(BR_CHAN(chan)->flags,
+				      L2CAP_FLAG_SIG_INFO_PENDING)) {
+		/* Cancel RTX work on signal channel */
+		k_delayed_work_cancel(&chan->rtx_work);
+	}
+}
+
+int bt_l2cap_br_chan_disconnect(struct bt_l2cap_chan *chan)
+{
+	struct bt_conn *conn = chan->conn;
+	struct net_buf *buf;
+	struct bt_l2cap_disconn_req *req;
+	struct bt_l2cap_sig_hdr *hdr;
+	struct bt_l2cap_br_chan *ch;
+
+	if (!conn) {
+		return -ENOTCONN;
+	}
+
+	if (chan->state == BT_L2CAP_DISCONNECT) {
+		return -EALREADY;
+	}
+
+	ch = BR_CHAN(chan);
+
+	BT_DBG("chan %p scid 0x%04x dcid 0x%04x", chan, ch->rx.cid,
+	       ch->tx.cid);
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_DISCONN_REQ;
+	hdr->ident = l2cap_br_get_ident();
+	hdr->len = sys_cpu_to_le16(sizeof(*req));
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->dcid = sys_cpu_to_le16(ch->tx.cid);
+	req->scid = sys_cpu_to_le16(ch->rx.cid);
+
+	l2cap_br_chan_send_req(ch, buf, L2CAP_BR_DISCONN_TIMEOUT);
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_DISCONNECT);
+
+	return 0;
+}
+
+static void l2cap_br_disconn_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,
+				 struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_br_chan *chan;
+	struct bt_l2cap_disconn_rsp *rsp = (void *)buf->data;
+	uint16_t dcid, scid;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small disconn rsp packet size");
+		return;
+	}
+
+	dcid = sys_le16_to_cpu(rsp->dcid);
+	scid = sys_le16_to_cpu(rsp->scid);
+
+	BT_DBG("dcid 0x%04x scid 0x%04x", dcid, scid);
+
+	chan = l2cap_br_remove_tx_cid(conn, dcid);
+	if (!chan) {
+		BT_WARN("No dcid 0x%04x channel found", dcid);
+		return;
+	}
+
+	bt_l2cap_chan_del(&chan->chan);
+}
+
+int bt_l2cap_br_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			     uint16_t psm)
+{
+	struct net_buf *buf;
+	struct bt_l2cap_sig_hdr *hdr;
+	struct bt_l2cap_conn_req *req;
+
+	if (!psm) {
+		return -EINVAL;
+	}
+
+	if (chan->psm) {
+		return -EEXIST;
+	}
+
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((psm & 0x0101) != 0x0001) {
+		return -EINVAL;
+	}
+
+	if (chan->required_sec_level > BT_SECURITY_L4) {
+		return -EINVAL;
+	} else if (chan->required_sec_level == BT_SECURITY_L0 &&
+		   psm != L2CAP_BR_PSM_SDP) {
+		chan->required_sec_level = BT_SECURITY_L1;
+	}
+
+	switch (chan->state) {
+	case BT_L2CAP_CONNECTED:
+		/* Already connected */
+		return -EISCONN;
+	case BT_L2CAP_DISCONNECTED:
+		/* Can connect */
+		break;
+	case BT_L2CAP_CONFIG:
+	case BT_L2CAP_DISCONNECT:
+	default:
+		/* Bad context */
+		return -EBUSY;
+	}
+
+	if (!l2cap_br_chan_add(conn, chan, l2cap_br_chan_destroy)) {
+		return -ENOMEM;
+	}
+
+	chan->psm = psm;
+	bt_l2cap_chan_set_state(chan, BT_L2CAP_CONNECT);
+	atomic_set_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_PENDING);
+
+	switch (l2cap_br_conn_security(chan, psm)) {
+	case L2CAP_CONN_SECURITY_PENDING:
+		/*
+		 * Authentication was triggered, wait with sending request on
+		 * connection security changed callback context.
+		 */
+		 return 0;
+	case L2CAP_CONN_SECURITY_PASSED:
+		break;
+	case L2CAP_CONN_SECURITY_REJECT:
+	default:
+		l2cap_br_chan_cleanup(chan);
+		return -EIO;
+	}
+
+	buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_L2CAP_CONN_REQ;
+	hdr->ident = l2cap_br_get_ident();
+	hdr->len = sys_cpu_to_le16(sizeof(*req));
+
+	req = net_buf_add(buf, sizeof(*req));
+	req->psm = sys_cpu_to_le16(psm);
+	req->scid = sys_cpu_to_le16(BR_CHAN(chan)->rx.cid);
+
+	l2cap_br_chan_send_req(BR_CHAN(chan), buf, L2CAP_BR_CONN_TIMEOUT);
+
+	return 0;
+}
+
+static void l2cap_br_conn_rsp(struct bt_l2cap_br *l2cap, uint8_t ident,
+			      struct net_buf *buf)
+{
+	struct bt_conn *conn = l2cap->chan.chan.conn;
+	struct bt_l2cap_chan *chan;
+	struct bt_l2cap_conn_rsp *rsp = (void *)buf->data;
+	uint16_t dcid, scid, result, status;
+
+	if (buf->len < sizeof(*rsp)) {
+		BT_ERR("Too small L2CAP conn rsp packet size");
+		return;
+	}
+
+	dcid = sys_le16_to_cpu(rsp->dcid);
+	scid = sys_le16_to_cpu(rsp->scid);
+	result = sys_le16_to_cpu(rsp->result);
+	status = sys_le16_to_cpu(rsp->status);
+
+	BT_DBG("dcid 0x%04x scid 0x%04x result %u status %u", dcid, scid,
+	       result, status);
+
+	chan = bt_l2cap_br_lookup_rx_cid(conn, scid);
+	if (!chan) {
+		BT_ERR("No scid 0x%04x channel found", scid);
+		return;
+	}
+
+	/* Release RTX work since got the response */
+	k_delayed_work_cancel(&chan->rtx_work);
+
+	if (chan->state != BT_L2CAP_CONNECT) {
+		BT_DBG("Invalid channel %p state %s", chan,
+		       bt_l2cap_chan_state_str(chan->state));
+		return;
+	}
+
+	switch (result) {
+	case BT_L2CAP_BR_SUCCESS:
+		chan->ident = 0U;
+		BR_CHAN(chan)->tx.cid = dcid;
+		l2cap_br_conf(chan);
+		bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
+		atomic_clear_bit(BR_CHAN(chan)->flags, L2CAP_FLAG_CONN_PENDING);
+		break;
+	case BT_L2CAP_BR_PENDING:
+		k_delayed_work_submit(&chan->rtx_work, L2CAP_BR_CONN_TIMEOUT);
+		break;
+	default:
+		l2cap_br_chan_cleanup(chan);
+		break;
+	}
+}
+
+int bt_l2cap_br_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap_br_chan *ch = BR_CHAN(chan);
+
+	if (buf->len > ch->tx.mtu) {
+		return -EMSGSIZE;
+	}
+
+	bt_l2cap_send(ch->chan.conn, ch->tx.cid, buf);
+
+	return buf->len;
+}
+
+static int l2cap_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap_br *l2cap = CONTAINER_OF(chan, struct bt_l2cap_br, chan);
+	struct bt_l2cap_sig_hdr *hdr;
+	uint16_t len;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small L2CAP signaling PDU");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	len = sys_le16_to_cpu(hdr->len);
+
+	BT_DBG("Signaling code 0x%02x ident %u len %u", hdr->code,
+	       hdr->ident, len);
+
+	if (buf->len != len) {
+		BT_ERR("L2CAP length mismatch (%u != %u)", buf->len, len);
+		return 0;
+	}
+
+	if (!hdr->ident) {
+		BT_ERR("Invalid ident value in L2CAP PDU");
+		return 0;
+	}
+
+	switch (hdr->code) {
+	case BT_L2CAP_INFO_RSP:
+		l2cap_br_info_rsp(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_INFO_REQ:
+		l2cap_br_info_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_DISCONN_REQ:
+		l2cap_br_disconn_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_CONN_REQ:
+		l2cap_br_conn_req(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_CONF_RSP:
+		l2cap_br_conf_rsp(l2cap, hdr->ident, len, buf);
+		break;
+	case BT_L2CAP_CONF_REQ:
+		l2cap_br_conf_req(l2cap, hdr->ident, len, buf);
+		break;
+	case BT_L2CAP_DISCONN_RSP:
+		l2cap_br_disconn_rsp(l2cap, hdr->ident, buf);
+		break;
+	case BT_L2CAP_CONN_RSP:
+		l2cap_br_conn_rsp(l2cap, hdr->ident, buf);
+		break;
+	default:
+		BT_WARN("Unknown/Unsupported L2CAP PDU code 0x%02x", hdr->code);
+		l2cap_br_send_reject(chan->conn, hdr->ident,
+				     BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0);
+		break;
+	}
+
+	return 0;
+}
+
+static void l2cap_br_conn_pend(struct bt_l2cap_chan *chan, uint8_t status)
+{
+	struct net_buf *buf;
+	struct bt_l2cap_sig_hdr *hdr;
+	struct bt_l2cap_conn_req *req;
+
+	if (chan->state != BT_L2CAP_CONNECT) {
+		return;
+	}
+
+	BT_DBG("chan %p status 0x%02x encr 0x%02x", chan, status,
+	       chan->conn->encrypt);
+
+	if (status) {
+		/*
+		 * Security procedure status is non-zero so respond with
+		 * security violation only as channel acceptor.
+		 */
+		l2cap_br_conn_req_reply(chan, BT_L2CAP_BR_ERR_SEC_BLOCK);
+
+		/* Release channel allocated to outgoing connection request */
+		if (atomic_test_bit(BR_CHAN(chan)->flags,
+				    L2CAP_FLAG_CONN_PENDING)) {
+			l2cap_br_chan_cleanup(chan);
+		}
+
+		return;
+	}
+
+	if (!chan->conn->encrypt) {
+		return;
+	}
+
+	/*
+	 * For incoming connection state send confirming outstanding
+	 * response and initiate configuration request.
+	 */
+	if (l2cap_br_conn_req_reply(chan, BT_L2CAP_BR_SUCCESS) == 0) {
+		bt_l2cap_chan_set_state(chan, BT_L2CAP_CONFIG);
+		/*
+		 * Initialize config request since remote needs to know
+		 * local MTU segmentation.
+		 */
+		l2cap_br_conf(chan);
+	} else if (atomic_test_and_clear_bit(BR_CHAN(chan)->flags,
+					     L2CAP_FLAG_CONN_PENDING)) {
+		buf = bt_l2cap_create_pdu(&br_sig_pool, 0);
+
+		hdr = net_buf_add(buf, sizeof(*hdr));
+		hdr->code = BT_L2CAP_CONN_REQ;
+		hdr->ident = l2cap_br_get_ident();
+		hdr->len = sys_cpu_to_le16(sizeof(*req));
+
+		req = net_buf_add(buf, sizeof(*req));
+		req->psm = sys_cpu_to_le16(chan->psm);
+		req->scid = sys_cpu_to_le16(BR_CHAN(chan)->rx.cid);
+
+		l2cap_br_chan_send_req(BR_CHAN(chan), buf,
+				       L2CAP_BR_CONN_TIMEOUT);
+	}
+}
+
+void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status)
+{
+	struct bt_l2cap_chan *chan;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn->channels, chan, node) {
+		l2cap_br_conn_pend(chan, hci_status);
+
+		if (chan->ops && chan->ops->encrypt_change) {
+			chan->ops->encrypt_change(chan, hci_status);
+		}
+	}
+}
+
+static void check_fixed_channel(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_br_chan *br_chan = BR_CHAN(chan);
+
+	if (br_chan->rx.cid < L2CAP_BR_CID_DYN_START) {
+		connect_fixed_channel(br_chan);
+	}
+}
+
+void bt_l2cap_br_recv(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct bt_l2cap_hdr *hdr;
+	struct bt_l2cap_chan *chan;
+	uint16_t cid;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small L2CAP PDU received");
+		net_buf_unref(buf);
+		return;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	cid = sys_le16_to_cpu(hdr->cid);
+
+	chan = bt_l2cap_br_lookup_rx_cid(conn, cid);
+	if (!chan) {
+		BT_WARN("Ignoring data for unknown CID 0x%04x", cid);
+		net_buf_unref(buf);
+		return;
+	}
+
+	/*
+	 * if data was received for fixed channel before Information
+	 * Response we connect channel here.
+	 */
+	check_fixed_channel(chan);
+
+	chan->ops->recv(chan, buf);
+	net_buf_unref(buf);
+}
+
+static int l2cap_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	int i;
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = l2cap_br_connected,
+		.disconnected = l2cap_br_disconnected,
+		.recv = l2cap_br_recv,
+	};
+
+	BT_DBG("conn %p handle %u", conn, conn->handle);
+
+	for (i = 0; i < ARRAY_SIZE(bt_l2cap_br_pool); i++) {
+		struct bt_l2cap_br *l2cap = &bt_l2cap_br_pool[i];
+
+		if (l2cap->chan.chan.conn) {
+			continue;
+		}
+
+		l2cap->chan.chan.ops = &ops;
+		*chan = &l2cap->chan.chan;
+		atomic_set(l2cap->chan.flags, 0);
+		return 0;
+	}
+
+	BT_ERR("No available L2CAP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+BT_L2CAP_BR_CHANNEL_DEFINE(br_fixed_chan, BT_L2CAP_CID_BR_SIG, l2cap_br_accept);
+
+void bt_l2cap_br_init(void)
+{
+	sys_slist_init(&br_servers);
+
+	if (IS_ENABLED(CONFIG_BT_RFCOMM)) {
+		bt_rfcomm_init();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_AVDTP)) {
+		bt_avdtp_init();
+	}
+
+	bt_sdp_init();
+
+	if (IS_ENABLED(CONFIG_BT_A2DP)) {
+		bt_a2dp_init();
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/l2cap_internal.h	(working copy)
@@ -0,0 +1,366 @@
+/** @file
+ *  @brief Internal APIs for Bluetooth L2CAP handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <bluetooth/l2cap.h>
+
+enum l2cap_conn_list_action {
+	BT_L2CAP_CHAN_LOOKUP,
+	BT_L2CAP_CHAN_DETACH,
+};
+
+#define BT_L2CAP_CID_BR_SIG             0x0001
+#define BT_L2CAP_CID_ATT                0x0004
+#define BT_L2CAP_CID_LE_SIG             0x0005
+#define BT_L2CAP_CID_SMP                0x0006
+#define BT_L2CAP_CID_BR_SMP             0x0007
+
+#define BT_L2CAP_PSM_RFCOMM             0x0003
+
+struct bt_l2cap_hdr {
+	uint16_t len;
+	uint16_t cid;
+} __packed;
+
+struct bt_l2cap_sig_hdr {
+	uint8_t  code;
+	uint8_t  ident;
+	uint16_t len;
+} __packed;
+
+#define BT_L2CAP_REJ_NOT_UNDERSTOOD     0x0000
+#define BT_L2CAP_REJ_MTU_EXCEEDED       0x0001
+#define BT_L2CAP_REJ_INVALID_CID        0x0002
+
+#define BT_L2CAP_CMD_REJECT             0x01
+struct bt_l2cap_cmd_reject {
+	uint16_t reason;
+	uint8_t  data[0];
+} __packed;
+
+struct bt_l2cap_cmd_reject_cid_data {
+	uint16_t scid;
+	uint16_t dcid;
+} __packed;
+
+#define BT_L2CAP_CONN_REQ               0x02
+struct bt_l2cap_conn_req {
+	uint16_t psm;
+	uint16_t scid;
+} __packed;
+
+/* command statuses in reposnse */
+#define BT_L2CAP_CS_NO_INFO             0x0000
+#define BT_L2CAP_CS_AUTHEN_PEND         0x0001
+
+/* valid results in conn response on BR/EDR */
+#define BT_L2CAP_BR_SUCCESS             0x0000
+#define BT_L2CAP_BR_PENDING             0x0001
+#define BT_L2CAP_BR_ERR_PSM_NOT_SUPP    0x0002
+#define BT_L2CAP_BR_ERR_SEC_BLOCK       0x0003
+#define BT_L2CAP_BR_ERR_NO_RESOURCES    0x0004
+#define BT_L2CAP_BR_ERR_INVALID_SCID    0x0006
+#define BT_L2CAP_BR_ERR_SCID_IN_USE     0x0007
+
+#define BT_L2CAP_CONN_RSP               0x03
+struct bt_l2cap_conn_rsp {
+	uint16_t dcid;
+	uint16_t scid;
+	uint16_t result;
+	uint16_t status;
+} __packed;
+
+#define BT_L2CAP_CONF_SUCCESS           0x0000
+#define BT_L2CAP_CONF_UNACCEPT          0x0001
+#define BT_L2CAP_CONF_REJECT            0x0002
+
+#define BT_L2CAP_CONF_REQ               0x04
+struct bt_l2cap_conf_req {
+	uint16_t dcid;
+	uint16_t flags;
+	uint8_t  data[0];
+} __packed;
+
+#define BT_L2CAP_CONF_RSP               0x05
+struct bt_l2cap_conf_rsp {
+	uint16_t scid;
+	uint16_t flags;
+	uint16_t result;
+	uint8_t  data[0];
+} __packed;
+
+/* Option type used by MTU config request data */
+#define BT_L2CAP_CONF_OPT_MTU           0x01
+/* Options bits selecting most significant bit (hint) in type field */
+#define BT_L2CAP_CONF_HINT              0x80
+#define BT_L2CAP_CONF_MASK              0x7f
+
+struct bt_l2cap_conf_opt {
+	uint8_t type;
+	uint8_t len;
+	uint8_t data[0];
+} __packed;
+
+#define BT_L2CAP_DISCONN_REQ            0x06
+struct bt_l2cap_disconn_req {
+	uint16_t dcid;
+	uint16_t scid;
+} __packed;
+
+#define BT_L2CAP_DISCONN_RSP            0x07
+struct bt_l2cap_disconn_rsp {
+	uint16_t dcid;
+	uint16_t scid;
+} __packed;
+
+#define BT_L2CAP_INFO_FEAT_MASK         0x0002
+#define BT_L2CAP_INFO_FIXED_CHAN        0x0003
+
+#define BT_L2CAP_INFO_REQ               0x0a
+struct bt_l2cap_info_req {
+	uint16_t type;
+} __packed;
+
+/* info result */
+#define BT_L2CAP_INFO_SUCCESS           0x0000
+#define BT_L2CAP_INFO_NOTSUPP           0x0001
+
+#define BT_L2CAP_INFO_RSP               0x0b
+struct bt_l2cap_info_rsp {
+	uint16_t type;
+	uint16_t result;
+	uint8_t  data[0];
+} __packed;
+
+#define BT_L2CAP_CONN_PARAM_REQ         0x12
+struct bt_l2cap_conn_param_req {
+	uint16_t min_interval;
+	uint16_t max_interval;
+	uint16_t latency;
+	uint16_t timeout;
+} __packed;
+
+#define BT_L2CAP_CONN_PARAM_ACCEPTED    0x0000
+#define BT_L2CAP_CONN_PARAM_REJECTED    0x0001
+
+#define BT_L2CAP_CONN_PARAM_RSP         0x13
+struct bt_l2cap_conn_param_rsp {
+	uint16_t result;
+} __packed;
+
+#define BT_L2CAP_LE_CONN_REQ            0x14
+struct bt_l2cap_le_conn_req {
+	uint16_t psm;
+	uint16_t scid;
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
+} __packed;
+
+/* valid results in conn response on LE */
+#define BT_L2CAP_LE_SUCCESS             0x0000
+#define BT_L2CAP_LE_ERR_PSM_NOT_SUPP    0x0002
+#define BT_L2CAP_LE_ERR_NO_RESOURCES    0x0004
+#define BT_L2CAP_LE_ERR_AUTHENTICATION  0x0005
+#define BT_L2CAP_LE_ERR_AUTHORIZATION   0x0006
+#define BT_L2CAP_LE_ERR_KEY_SIZE        0x0007
+#define BT_L2CAP_LE_ERR_ENCRYPTION      0x0008
+#define BT_L2CAP_LE_ERR_INVALID_SCID    0x0009
+#define BT_L2CAP_LE_ERR_SCID_IN_USE     0x000A
+#define BT_L2CAP_LE_ERR_UNACCEPT_PARAMS 0x000B
+#define BT_L2CAP_LE_ERR_INVALID_PARAMS  0x000C
+
+#define BT_L2CAP_LE_CONN_RSP            0x15
+struct bt_l2cap_le_conn_rsp {
+	uint16_t dcid;
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
+	uint16_t result;
+} __packed;
+
+#define BT_L2CAP_LE_CREDITS             0x16
+struct bt_l2cap_le_credits {
+	uint16_t cid;
+	uint16_t credits;
+} __packed;
+
+#define BT_L2CAP_ECRED_CONN_REQ         0x17
+struct bt_l2cap_ecred_conn_req {
+	uint16_t psm;
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
+	uint16_t scid[0];
+} __packed;
+
+#define BT_L2CAP_ECRED_CONN_RSP         0x18
+struct bt_l2cap_ecred_conn_rsp {
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t credits;
+	uint16_t result;
+	uint16_t dcid[0];
+} __packed;
+
+#define BT_L2CAP_ECRED_RECONF_REQ       0x19
+struct bt_l2cap_ecred_reconf_req {
+	uint16_t mtu;
+	uint16_t mps;
+	uint16_t scid[0];
+} __packed;
+
+#define BT_L2CAP_RECONF_SUCCESS         0x0000
+#define BT_L2CAP_RECONF_INVALID_MTU     0x0001
+#define BT_L2CAP_RECONF_INVALID_MPS     0x0002
+
+#define BT_L2CAP_ECRED_RECONF_RSP       0x1a
+struct bt_l2cap_ecred_reconf_rsp {
+	uint16_t result;
+} __packed;
+
+#define BT_L2CAP_SDU_HDR_LEN            2
+
+struct bt_l2cap_fixed_chan {
+	uint16_t		cid;
+	int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
+	bt_l2cap_chan_destroy_t destroy;
+};
+
+#define BT_L2CAP_CHANNEL_DEFINE(_name, _cid, _accept, _destroy)         \
+	const Z_STRUCT_SECTION_ITERABLE(bt_l2cap_fixed_chan, _name) = { \
+				.cid = _cid,                            \
+				.accept = _accept,                      \
+				.destroy = _destroy,                    \
+			};
+
+/* Need a name different than bt_l2cap_fixed_chan for a different section */
+struct bt_l2cap_br_fixed_chan {
+	uint16_t		cid;
+	int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
+};
+
+#define BT_L2CAP_BR_CHANNEL_DEFINE(_name, _cid, _accept)		\
+	const Z_STRUCT_SECTION_ITERABLE(bt_l2cap_br_fixed_chan, _name) = { \
+				.cid = _cid,			\
+				.accept = _accept,		\
+			}
+
+/* Notify L2CAP channels of a new connection */
+void bt_l2cap_connected(struct bt_conn *conn);
+
+/* Notify L2CAP channels of a disconnect event */
+void bt_l2cap_disconnected(struct bt_conn *conn);
+
+/* Add channel to the connection */
+void bt_l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+		       bt_l2cap_chan_destroy_t destroy);
+
+/* Remove channel from the connection */
+void bt_l2cap_chan_remove(struct bt_conn *conn, struct bt_l2cap_chan *chan);
+
+/* Delete channel */
+void bt_l2cap_chan_del(struct bt_l2cap_chan *chan);
+
+const char *bt_l2cap_chan_state_str(bt_l2cap_chan_state_t state);
+
+#if defined(CONFIG_BT_DEBUG_L2CAP)
+void bt_l2cap_chan_set_state_debug(struct bt_l2cap_chan *chan,
+				   bt_l2cap_chan_state_t state,
+				   const char *func, int line);
+#define bt_l2cap_chan_set_state(_chan, _state) \
+	bt_l2cap_chan_set_state_debug(_chan, _state, __func__, __LINE__)
+#else
+void bt_l2cap_chan_set_state(struct bt_l2cap_chan *chan,
+			     bt_l2cap_chan_state_t state);
+#endif /* CONFIG_BT_DEBUG_L2CAP */
+
+/*
+ * Notify L2CAP channels of a change in encryption state passing additionally
+ * HCI status of performed security procedure.
+ */
+void bt_l2cap_security_changed(struct bt_conn *conn, uint8_t hci_status);
+
+/* Prepare an L2CAP PDU to be sent over a connection */
+struct net_buf *bt_l2cap_create_pdu_timeout(struct net_buf_pool *pool,
+					    size_t reserve,
+					    k_timeout_t timeout);
+
+#define bt_l2cap_create_pdu(_pool, _reserve) \
+	bt_l2cap_create_pdu_timeout(_pool, _reserve, K_FOREVER)
+
+/* Prepare a L2CAP Response PDU to be sent over a connection */
+struct net_buf *bt_l2cap_create_rsp(struct net_buf *buf, size_t reserve);
+
+/* Send L2CAP PDU over a connection
+ *
+ * Buffer ownership is transferred to stack so either in case of success
+ * or error the buffer will be unref internally.
+ *
+ * Calling this from RX thread is assumed to never fail so the return can be
+ * ignored.
+ */
+int bt_l2cap_send_cb(struct bt_conn *conn, uint16_t cid, struct net_buf *buf,
+		     bt_conn_tx_cb_t cb, void *user_data);
+
+static inline void bt_l2cap_send(struct bt_conn *conn, uint16_t cid,
+				 struct net_buf *buf)
+{
+	bt_l2cap_send_cb(conn, cid, buf, NULL, NULL);
+}
+
+/* Receive a new L2CAP PDU from a connection */
+void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf);
+
+/* Perform connection parameter update request */
+int bt_l2cap_update_conn_param(struct bt_conn *conn,
+			       const struct bt_le_conn_param *param);
+
+/* Initialize L2CAP and supported channels */
+void bt_l2cap_init(void);
+
+/* Lookup channel by Transmission CID */
+struct bt_l2cap_chan *bt_l2cap_le_lookup_tx_cid(struct bt_conn *conn,
+						uint16_t cid);
+
+/* Lookup channel by Receiver CID */
+struct bt_l2cap_chan *bt_l2cap_le_lookup_rx_cid(struct bt_conn *conn,
+						uint16_t cid);
+
+/* Initialize BR/EDR L2CAP signal layer */
+void bt_l2cap_br_init(void);
+
+/* Register fixed channel */
+void bt_l2cap_br_fixed_chan_register(struct bt_l2cap_fixed_chan *chan);
+
+/* Notify BR/EDR L2CAP channels about established new ACL connection */
+void bt_l2cap_br_connected(struct bt_conn *conn);
+
+/* Lookup BR/EDR L2CAP channel by Receiver CID */
+struct bt_l2cap_chan *bt_l2cap_br_lookup_rx_cid(struct bt_conn *conn,
+						uint16_t cid);
+
+/* Disconnects dynamic channel */
+int bt_l2cap_br_chan_disconnect(struct bt_l2cap_chan *chan);
+
+/* Make connection to peer psm server */
+int bt_l2cap_br_chan_connect(struct bt_conn *conn, struct bt_l2cap_chan *chan,
+			     uint16_t psm);
+
+/* Send packet data to connected peer */
+int bt_l2cap_br_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf);
+
+/*
+ * Handle security level changed on link passing HCI status of performed
+ * security procedure.
+ */
+void l2cap_br_encrypt_change(struct bt_conn *conn, uint8_t hci_status);
+
+/* Handle received data */
+void bt_l2cap_br_recv(struct bt_conn *conn, struct net_buf *buf);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.h	(working copy)
@@ -0,0 +1,108 @@
+/** @file
+ *  @brief Custom monitor protocol logging over UART
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_DEBUG_MONITOR)
+
+#define BT_MONITOR_NEW_INDEX    0
+#define BT_MONITOR_DEL_INDEX    1
+#define BT_MONITOR_COMMAND_PKT  2
+#define BT_MONITOR_EVENT_PKT    3
+#define BT_MONITOR_ACL_TX_PKT   4
+#define BT_MONITOR_ACL_RX_PKT   5
+#define BT_MONITOR_SCO_TX_PKT   6
+#define BT_MONITOR_SCO_RX_PKT   7
+#define BT_MONITOR_OPEN_INDEX   8
+#define BT_MONITOR_CLOSE_INDEX  9
+#define BT_MONITOR_INDEX_INFO   10
+#define BT_MONITOR_VENDOR_DIAG  11
+#define BT_MONITOR_SYSTEM_NOTE  12
+#define BT_MONITOR_USER_LOGGING 13
+#define BT_MONITOR_ISO_TX_PKT   18
+#define BT_MONITOR_ISO_RX_PKT   19
+#define BT_MONITOR_NOP          255
+
+#define BT_MONITOR_TYPE_PRIMARY	0
+#define BT_MONITOR_TYPE_AMP	1
+
+/* Extended header types */
+#define BT_MONITOR_COMMAND_DROPS 1
+#define BT_MONITOR_EVENT_DROPS   2
+#define BT_MONITOR_ACL_RX_DROPS  3
+#define BT_MONITOR_ACL_TX_DROPS  4
+#define BT_MONITOR_SCO_RX_DROPS  5
+#define BT_MONITOR_SCO_TX_DROPS  6
+#define BT_MONITOR_OTHER_DROPS   7
+#define BT_MONITOR_TS32          8
+
+#define BT_MONITOR_BASE_HDR_LEN  6
+
+#if defined(CONFIG_BT_BREDR)
+#define BT_MONITOR_EXT_HDR_MAX 19
+#else
+#define BT_MONITOR_EXT_HDR_MAX 15
+#endif
+
+struct bt_monitor_hdr {
+	uint16_t  data_len;
+	uint16_t  opcode;
+	uint8_t   flags;
+	uint8_t   hdr_len;
+
+	uint8_t   ext[BT_MONITOR_EXT_HDR_MAX];
+} __packed;
+
+struct bt_monitor_ts32 {
+	uint8_t   type;
+	uint32_t  ts32;
+} __packed;
+
+struct bt_monitor_new_index {
+	uint8_t  type;
+	uint8_t  bus;
+	uint8_t  bdaddr[6];
+	char  name[8];
+} __packed;
+
+struct bt_monitor_user_logging {
+	uint8_t  priority;
+	uint8_t  ident_len;
+} __packed;
+
+static inline uint8_t bt_monitor_opcode(struct net_buf *buf)
+{
+	switch (bt_buf_get_type(buf)) {
+	case BT_BUF_CMD:
+		return BT_MONITOR_COMMAND_PKT;
+	case BT_BUF_EVT:
+		return BT_MONITOR_EVENT_PKT;
+	case BT_BUF_ACL_OUT:
+		return BT_MONITOR_ACL_TX_PKT;
+	case BT_BUF_ACL_IN:
+		return BT_MONITOR_ACL_RX_PKT;
+	case BT_BUF_ISO_OUT:
+		return BT_MONITOR_ISO_TX_PKT;
+	case BT_BUF_ISO_IN:
+		return BT_MONITOR_ISO_RX_PKT;
+	default:
+		return BT_MONITOR_NOP;
+	}
+}
+
+void bt_monitor_send(uint16_t opcode, const void *data, size_t len);
+
+void bt_monitor_new_index(uint8_t type, uint8_t bus, bt_addr_t *addr,
+			  const char *name);
+
+#else /* !CONFIG_BT_DEBUG_MONITOR */
+
+#define bt_monitor_send(opcode, data, len)
+#define bt_monitor_new_index(type, bus, addr, name)
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/monitor.c	(working copy)
@@ -0,0 +1,343 @@
+/** @file
+ *  @brief Custom logging over UART
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stdbool.h>
+
+#include <zephyr.h>
+#include <device.h>
+#include <init.h>
+#include <drivers/console/uart_pipe.h>
+#include <sys/byteorder.h>
+#include <drivers/uart.h>
+
+#include <logging/log_backend.h>
+#include <logging/log_output.h>
+#include <logging/log_ctrl.h>
+#include <logging/log.h>
+
+#include <bluetooth/buf.h>
+
+#include "monitor.h"
+
+/* This is the same default priority as for other console handlers,
+ * except that we're not exporting it as a Kconfig variable until a
+ * clear need arises.
+ */
+#define MONITOR_INIT_PRIORITY 60
+
+/* These defines follow the values used by syslog(2) */
+#define BT_LOG_ERR      3
+#define BT_LOG_WARN     4
+#define BT_LOG_INFO     6
+#define BT_LOG_DBG      7
+
+/* TS resolution is 1/10th of a millisecond */
+#define MONITOR_TS_FREQ 10000
+
+/* Maximum (string) length of a log message */
+#define MONITOR_MSG_MAX 128
+
+static const struct device *monitor_dev;
+
+enum {
+	BT_LOG_BUSY,
+	BT_CONSOLE_BUSY,
+};
+
+static atomic_t flags;
+
+static struct {
+	atomic_t cmd;
+	atomic_t evt;
+	atomic_t acl_tx;
+	atomic_t acl_rx;
+#if defined(CONFIG_BT_BREDR)
+	atomic_t sco_tx;
+	atomic_t sco_rx;
+#endif
+	atomic_t other;
+} drops;
+
+static void monitor_send(const void *data, size_t len)
+{
+	const uint8_t *buf = data;
+
+	while (len--) {
+		uart_poll_out(monitor_dev, *buf++);
+	}
+}
+
+static void encode_drops(struct bt_monitor_hdr *hdr, uint8_t type,
+			 atomic_t *val)
+{
+	atomic_val_t count;
+
+	count = atomic_set(val, 0);
+	if (count) {
+		hdr->ext[hdr->hdr_len++] = type;
+		hdr->ext[hdr->hdr_len++] = MIN(count, 255);
+	}
+}
+
+static uint32_t monitor_ts_get(void)
+{
+	return (k_cycle_get_32() /
+		(sys_clock_hw_cycles_per_sec() / MONITOR_TS_FREQ));
+}
+
+static inline void encode_hdr(struct bt_monitor_hdr *hdr, uint32_t timestamp,
+			      uint16_t opcode, uint16_t len)
+{
+	struct bt_monitor_ts32 *ts;
+
+	hdr->opcode   = sys_cpu_to_le16(opcode);
+	hdr->flags    = 0U;
+
+	ts = (void *)hdr->ext;
+	ts->type = BT_MONITOR_TS32;
+	ts->ts32 = timestamp;
+	hdr->hdr_len = sizeof(*ts);
+
+	encode_drops(hdr, BT_MONITOR_COMMAND_DROPS, &drops.cmd);
+	encode_drops(hdr, BT_MONITOR_EVENT_DROPS, &drops.evt);
+	encode_drops(hdr, BT_MONITOR_ACL_TX_DROPS, &drops.acl_tx);
+	encode_drops(hdr, BT_MONITOR_ACL_RX_DROPS, &drops.acl_rx);
+#if defined(CONFIG_BT_BREDR)
+	encode_drops(hdr, BT_MONITOR_SCO_TX_DROPS, &drops.sco_tx);
+	encode_drops(hdr, BT_MONITOR_SCO_RX_DROPS, &drops.sco_rx);
+#endif
+	encode_drops(hdr, BT_MONITOR_OTHER_DROPS, &drops.other);
+
+	hdr->data_len = sys_cpu_to_le16(4 + hdr->hdr_len + len);
+}
+
+static void drop_add(uint16_t opcode)
+{
+	switch (opcode) {
+	case BT_MONITOR_COMMAND_PKT:
+		atomic_inc(&drops.cmd);
+		break;
+	case BT_MONITOR_EVENT_PKT:
+		atomic_inc(&drops.evt);
+		break;
+	case BT_MONITOR_ACL_TX_PKT:
+		atomic_inc(&drops.acl_tx);
+		break;
+	case BT_MONITOR_ACL_RX_PKT:
+		atomic_inc(&drops.acl_rx);
+		break;
+#if defined(CONFIG_BT_BREDR)
+	case BT_MONITOR_SCO_TX_PKT:
+		atomic_inc(&drops.sco_tx);
+		break;
+	case BT_MONITOR_SCO_RX_PKT:
+		atomic_inc(&drops.sco_rx);
+		break;
+#endif
+	default:
+		atomic_inc(&drops.other);
+		break;
+	}
+}
+
+void bt_monitor_send(uint16_t opcode, const void *data, size_t len)
+{
+	struct bt_monitor_hdr hdr;
+
+	if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) {
+		drop_add(opcode);
+		return;
+	}
+
+	encode_hdr(&hdr, monitor_ts_get(), opcode, len);
+
+	monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len);
+	monitor_send(data, len);
+
+	atomic_clear_bit(&flags, BT_LOG_BUSY);
+}
+
+void bt_monitor_new_index(uint8_t type, uint8_t bus, bt_addr_t *addr,
+			  const char *name)
+{
+	struct bt_monitor_new_index pkt;
+
+	pkt.type = type;
+	pkt.bus = bus;
+	memcpy(pkt.bdaddr, addr, 6);
+	strncpy(pkt.name, name, sizeof(pkt.name) - 1);
+	pkt.name[sizeof(pkt.name) - 1] = '\0';
+
+	bt_monitor_send(BT_MONITOR_NEW_INDEX, &pkt, sizeof(pkt));
+}
+
+#if !defined(CONFIG_UART_CONSOLE) && !defined(CONFIG_LOG_PRINTK)
+static int monitor_console_out(int c)
+{
+	static char buf[MONITOR_MSG_MAX];
+	static size_t len;
+
+	if (atomic_test_and_set_bit(&flags, BT_CONSOLE_BUSY)) {
+		return c;
+	}
+
+	if (c != '\n' && len < sizeof(buf) - 1) {
+		buf[len++] = c;
+		atomic_clear_bit(&flags, BT_CONSOLE_BUSY);
+		return c;
+	}
+
+	buf[len++] = '\0';
+
+	bt_monitor_send(BT_MONITOR_SYSTEM_NOTE, buf, len);
+	len = 0;
+
+	atomic_clear_bit(&flags, BT_CONSOLE_BUSY);
+
+	return c;
+}
+
+extern void __printk_hook_install(int (*fn)(int));
+extern void __stdout_hook_install(int (*fn)(int));
+#endif /* !CONFIG_UART_CONSOLE */
+
+#if defined(CONFIG_HAS_DTS) && !defined(CONFIG_BT_MONITOR_ON_DEV_NAME)
+#define CONFIG_BT_MONITOR_ON_DEV_NAME CONFIG_UART_CONSOLE_ON_DEV_NAME
+#endif
+
+#ifndef CONFIG_LOG_MINIMAL
+struct monitor_log_ctx {
+	size_t total_len;
+	char msg[MONITOR_MSG_MAX];
+};
+
+static int monitor_log_out(uint8_t *data, size_t length, void *user_data)
+{
+	struct monitor_log_ctx *ctx = user_data;
+	size_t i;
+
+	for (i = 0; i < length && ctx->total_len < sizeof(ctx->msg); i++) {
+		/* With CONFIG_LOG_PRINTK the line terminator will come as
+		 * as part of messages.
+		 */
+		if (IS_ENABLED(CONFIG_LOG_PRINTK) &&
+		    (data[i] == '\r' || data[i] == '\n')) {
+			break;
+		}
+
+		ctx->msg[ctx->total_len++] = data[i];
+	}
+
+	return length;
+}
+
+static uint8_t buf;
+
+LOG_OUTPUT_DEFINE(monitor_log_output, monitor_log_out, &buf, 1);
+
+static inline uint8_t monitor_priority_get(uint8_t log_level)
+{
+	static const uint8_t prios[] = {
+		[LOG_LEVEL_NONE]  = 0,
+		[LOG_LEVEL_ERR]   = BT_LOG_ERR,
+		[LOG_LEVEL_WRN]   = BT_LOG_WARN,
+		[LOG_LEVEL_INF]   = BT_LOG_INFO,
+		[LOG_LEVEL_DBG]   = BT_LOG_DBG,
+	};
+
+	if (log_level < ARRAY_SIZE(prios)) {
+		return prios[log_level];
+	}
+
+	return BT_LOG_DBG;
+}
+
+static void monitor_log_put(const struct log_backend *const backend,
+			    struct log_msg *msg)
+{
+	struct bt_monitor_user_logging log;
+	struct monitor_log_ctx ctx;
+	struct bt_monitor_hdr hdr;
+	const char id[] = "bt";
+
+	log_msg_get(msg);
+
+	log_output_ctx_set(&monitor_log_output, &ctx);
+
+	ctx.total_len = 0;
+	log_output_msg_process(&monitor_log_output, msg,
+			       LOG_OUTPUT_FLAG_CRLF_NONE);
+
+	if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) {
+		drop_add(BT_MONITOR_USER_LOGGING);
+		log_msg_put(msg);
+		return;
+	}
+
+	encode_hdr(&hdr, msg->hdr.timestamp, BT_MONITOR_USER_LOGGING,
+		   sizeof(log) + sizeof(id) + ctx.total_len + 1);
+
+	log.priority = monitor_priority_get(msg->hdr.ids.level);
+	log.ident_len = sizeof(id);
+
+	log_msg_put(msg);
+
+	monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len);
+	monitor_send(&log, sizeof(log));
+	monitor_send(id, sizeof(id));
+	monitor_send(ctx.msg, ctx.total_len);
+
+	/* Terminate the string with null */
+	uart_poll_out(monitor_dev, '\0');
+
+	atomic_clear_bit(&flags, BT_LOG_BUSY);
+}
+
+static void monitor_log_panic(const struct log_backend *const backend)
+{
+}
+
+static void monitor_log_init(void)
+{
+	log_set_timestamp_func(monitor_ts_get, MONITOR_TS_FREQ);
+}
+
+static const struct log_backend_api monitor_log_api = {
+	.put = monitor_log_put,
+	.panic = monitor_log_panic,
+	.init = monitor_log_init,
+};
+
+LOG_BACKEND_DEFINE(bt_monitor, monitor_log_api, true);
+#endif /* CONFIG_LOG_MINIMAL */
+
+static int bt_monitor_init(const struct device *d)
+{
+	ARG_UNUSED(d);
+
+	monitor_dev = device_get_binding(CONFIG_BT_MONITOR_ON_DEV_NAME);
+
+	__ASSERT_NO_MSG(monitor_dev);
+
+#if defined(CONFIG_UART_INTERRUPT_DRIVEN)
+	uart_irq_rx_disable(monitor_dev);
+	uart_irq_tx_disable(monitor_dev);
+#endif
+
+#if !defined(CONFIG_UART_CONSOLE) && !defined(CONFIG_LOG_PRINTK)
+	__printk_hook_install(monitor_console_out);
+	__stdout_hook_install(monitor_console_out);
+#endif
+
+	return 0;
+}
+
+SYS_INIT(bt_monitor_init, PRE_KERNEL_1, MONITOR_INIT_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm.c	(working copy)
@@ -0,0 +1,1733 @@
+/* rfcomm.c - RFCOMM handling */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <debug/stack.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <drivers/bluetooth/hci_driver.h>
+#include <bluetooth/l2cap.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_RFCOMM)
+#define LOG_MODULE_NAME bt_rfcomm
+#include "common/log.h"
+
+#include <bluetooth/rfcomm.h>
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "rfcomm_internal.h"
+
+#define RFCOMM_CHANNEL_START	0x01
+#define RFCOMM_CHANNEL_END	0x1e
+
+#define RFCOMM_MIN_MTU		BT_RFCOMM_SIG_MIN_MTU
+#define RFCOMM_DEFAULT_MTU	127
+
+#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
+#define RFCOMM_MAX_CREDITS		(CONFIG_BT_ACL_RX_COUNT - 1)
+#else
+#define RFCOMM_MAX_CREDITS		(CONFIG_BT_RX_BUF_COUNT - 1)
+#endif
+
+#define RFCOMM_CREDITS_THRESHOLD	(RFCOMM_MAX_CREDITS / 2)
+#define RFCOMM_DEFAULT_CREDIT		RFCOMM_MAX_CREDITS
+
+#define RFCOMM_CONN_TIMEOUT     K_SECONDS(60)
+#define RFCOMM_DISC_TIMEOUT     K_SECONDS(20)
+#define RFCOMM_IDLE_TIMEOUT     K_SECONDS(2)
+
+#define DLC_RTX(_w) CONTAINER_OF(_w, struct bt_rfcomm_dlc, rtx_work)
+
+#define SESSION_RTX(_w) CONTAINER_OF(_w, struct bt_rfcomm_session, rtx_work)
+
+static struct bt_rfcomm_server *servers;
+
+/* Pool for dummy buffers to wake up the tx threads */
+NET_BUF_POOL_DEFINE(dummy_pool, CONFIG_BT_MAX_CONN, 0, 0, NULL);
+
+#define RFCOMM_SESSION(_ch) CONTAINER_OF(_ch, \
+					 struct bt_rfcomm_session, br_chan.chan)
+
+static struct bt_rfcomm_session bt_rfcomm_pool[CONFIG_BT_MAX_CONN];
+
+/* reversed, 8-bit, poly=0x07 */
+static const uint8_t rfcomm_crc_table[256] = {
+	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
+	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
+	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+
+	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
+	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
+	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+
+	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
+	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
+	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+
+	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
+	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
+	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+
+	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
+	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
+	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+
+	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
+	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
+	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+
+	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
+	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
+	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+
+	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
+	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
+	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
+};
+
+static uint8_t rfcomm_calc_fcs(uint16_t len, const uint8_t *data)
+{
+	uint8_t fcs = 0xff;
+
+	while (len--) {
+		fcs = rfcomm_crc_table[fcs ^ *data++];
+	}
+
+	/* Ones compliment */
+	return (0xff - fcs);
+}
+
+static bool rfcomm_check_fcs(uint16_t len, const uint8_t *data,
+			     uint8_t recvd_fcs)
+{
+	uint8_t fcs = 0xff;
+
+	while (len--) {
+		fcs = rfcomm_crc_table[fcs ^ *data++];
+	}
+
+	/* Ones compliment */
+	fcs = rfcomm_crc_table[fcs ^ recvd_fcs];
+
+	/*0xCF is the reversed order of 11110011.*/
+	return (fcs == 0xcf);
+}
+
+static struct bt_rfcomm_dlc *rfcomm_dlcs_lookup_dlci(struct bt_rfcomm_dlc *dlcs,
+						     uint8_t dlci)
+{
+	for (; dlcs; dlcs = dlcs->_next) {
+		if (dlcs->dlci == dlci) {
+			return dlcs;
+		}
+	}
+
+	return NULL;
+}
+
+static struct bt_rfcomm_dlc *rfcomm_dlcs_remove_dlci(struct bt_rfcomm_dlc *dlcs,
+						     uint8_t dlci)
+{
+	struct bt_rfcomm_dlc *tmp;
+
+	if (!dlcs) {
+		return NULL;
+	}
+
+	/* If first node is the one to be removed */
+	if (dlcs->dlci == dlci) {
+		dlcs->session->dlcs = dlcs->_next;
+		return dlcs;
+	}
+
+	for (tmp = dlcs, dlcs = dlcs->_next; dlcs; dlcs = dlcs->_next) {
+		if (dlcs->dlci == dlci) {
+			tmp->_next = dlcs->_next;
+			return dlcs;
+		}
+		tmp = dlcs;
+	}
+
+	return NULL;
+}
+
+static struct bt_rfcomm_server *rfcomm_server_lookup_channel(uint8_t channel)
+{
+	struct bt_rfcomm_server *server;
+
+	for (server = servers; server; server = server->_next) {
+		if (server->channel == channel) {
+			return server;
+		}
+	}
+
+	return NULL;
+}
+
+static struct bt_rfcomm_session *
+rfcomm_sessions_lookup_bt_conn(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_rfcomm_pool); i++) {
+		struct bt_rfcomm_session *session = &bt_rfcomm_pool[i];
+
+		if (session->br_chan.chan.conn == conn) {
+			return session;
+		}
+	}
+
+	return NULL;
+}
+
+int bt_rfcomm_server_register(struct bt_rfcomm_server *server)
+{
+	if (server->channel < RFCOMM_CHANNEL_START ||
+	    server->channel > RFCOMM_CHANNEL_END || !server->accept) {
+		return -EINVAL;
+	}
+
+	/* Check if given channel is already in use */
+	if (rfcomm_server_lookup_channel(server->channel)) {
+		BT_DBG("Channel already registered");
+		return -EADDRINUSE;
+	}
+
+	BT_DBG("Channel 0x%02x", server->channel);
+
+	server->_next = servers;
+	servers = server;
+
+	return 0;
+}
+
+static void rfcomm_dlc_tx_give_credits(struct bt_rfcomm_dlc *dlc,
+				       uint8_t credits)
+{
+	BT_DBG("dlc %p credits %u", dlc, credits);
+
+	while (credits--) {
+		k_sem_give(&dlc->tx_credits);
+	}
+
+	BT_DBG("dlc %p updated credits %u", dlc,
+	       k_sem_count_get(&dlc->tx_credits));
+}
+
+static void rfcomm_dlc_destroy(struct bt_rfcomm_dlc *dlc)
+{
+	BT_DBG("dlc %p", dlc);
+
+	k_delayed_work_cancel(&dlc->rtx_work);
+	dlc->state = BT_RFCOMM_STATE_IDLE;
+	dlc->session = NULL;
+
+	if (dlc->ops && dlc->ops->disconnected) {
+		dlc->ops->disconnected(dlc);
+	}
+}
+
+static void rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc)
+{
+	uint8_t old_state = dlc->state;
+
+	BT_DBG("dlc %p", dlc);
+
+	if (dlc->state == BT_RFCOMM_STATE_DISCONNECTED) {
+		return;
+	}
+
+	dlc->state = BT_RFCOMM_STATE_DISCONNECTED;
+
+	switch (old_state) {
+	case BT_RFCOMM_STATE_CONNECTED:
+		/* Queue a dummy buffer to wake up and stop the
+		 * tx thread for states where it was running.
+		 */
+		net_buf_put(&dlc->tx_queue,
+			    net_buf_alloc(&dummy_pool, K_NO_WAIT));
+
+		/* There could be a writer waiting for credits so return a
+		 * dummy credit to wake it up.
+		 */
+		rfcomm_dlc_tx_give_credits(dlc, 1);
+		k_sem_give(&dlc->session->fc);
+		break;
+	default:
+		rfcomm_dlc_destroy(dlc);
+		break;
+	}
+}
+
+static void rfcomm_session_disconnected(struct bt_rfcomm_session *session)
+{
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("Session %p", session);
+
+	if (session->state == BT_RFCOMM_STATE_DISCONNECTED) {
+		return;
+	}
+
+	for (dlc = session->dlcs; dlc;) {
+		struct bt_rfcomm_dlc *next;
+
+		/* prefetch since disconnected callback may cleanup */
+		next = dlc->_next;
+		dlc->_next = NULL;
+
+		rfcomm_dlc_disconnect(dlc);
+
+		dlc = next;
+	}
+
+	session->state = BT_RFCOMM_STATE_DISCONNECTED;
+	session->dlcs = NULL;
+}
+
+struct net_buf *bt_rfcomm_create_pdu(struct net_buf_pool *pool)
+{
+	/* Length in RFCOMM header can be 2 bytes depending on length of user
+	 * data
+	 */
+	return bt_conn_create_pdu(pool,
+				  sizeof(struct bt_l2cap_hdr) +
+				  sizeof(struct bt_rfcomm_hdr) + 1);
+}
+
+static int rfcomm_send_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t cr, fcs;
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	cr = BT_RFCOMM_CMD_CR(session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_SABM, BT_RFCOMM_PF_NON_UIH);
+	hdr->length = BT_RFCOMM_SET_LEN_8(0);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_disc(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t fcs, cr;
+
+	BT_DBG("dlci %d", dlci);
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	cr = BT_RFCOMM_RESP_CR(session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_DISC, BT_RFCOMM_PF_NON_UIH);
+	hdr->length = BT_RFCOMM_SET_LEN_8(0);
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static void rfcomm_session_disconnect(struct bt_rfcomm_session *session)
+{
+	if (session->dlcs) {
+		return;
+	}
+
+	session->state = BT_RFCOMM_STATE_DISCONNECTING;
+	rfcomm_send_disc(session, 0);
+	k_delayed_work_submit(&session->rtx_work, RFCOMM_DISC_TIMEOUT);
+}
+
+static struct net_buf *rfcomm_make_uih_msg(struct bt_rfcomm_session *session,
+					   uint8_t cr, uint8_t type,
+					   uint8_t len)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct bt_rfcomm_msg_hdr *msg_hdr;
+	struct net_buf *buf;
+	uint8_t hdr_cr;
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr_cr = BT_RFCOMM_UIH_CR(session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(0, hdr_cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH, BT_RFCOMM_PF_UIH);
+	hdr->length = BT_RFCOMM_SET_LEN_8(sizeof(*msg_hdr) + len);
+
+	msg_hdr = net_buf_add(buf, sizeof(*msg_hdr));
+	msg_hdr->type = BT_RFCOMM_SET_MSG_TYPE(type, cr);
+	msg_hdr->len = BT_RFCOMM_SET_LEN_8(len);
+
+	return buf;
+}
+
+static void rfcomm_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
+
+	BT_DBG("Session %p", session);
+
+	/* Need to include UIH header and FCS*/
+	session->mtu = MIN(session->br_chan.rx.mtu,
+			   session->br_chan.tx.mtu) -
+			   BT_RFCOMM_HDR_SIZE + BT_RFCOMM_FCS_SIZE;
+
+	if (session->state == BT_RFCOMM_STATE_CONNECTING) {
+		rfcomm_send_sabm(session, 0);
+	}
+}
+
+static void rfcomm_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
+
+	BT_DBG("Session %p", session);
+
+	k_delayed_work_cancel(&session->rtx_work);
+	rfcomm_session_disconnected(session);
+	session->state = BT_RFCOMM_STATE_IDLE;
+}
+
+static void rfcomm_dlc_rtx_timeout(struct k_work *work)
+{
+	struct bt_rfcomm_dlc *dlc = DLC_RTX(work);
+	struct bt_rfcomm_session *session = dlc->session;
+
+	BT_WARN("dlc %p state %d timeout", dlc, dlc->state);
+
+	rfcomm_dlcs_remove_dlci(session->dlcs, dlc->dlci);
+	rfcomm_dlc_disconnect(dlc);
+	rfcomm_session_disconnect(session);
+}
+
+static void rfcomm_dlc_init(struct bt_rfcomm_dlc *dlc,
+			    struct bt_rfcomm_session *session,
+			    uint8_t dlci,
+			    bt_rfcomm_role_t role)
+{
+	BT_DBG("dlc %p", dlc);
+
+	dlc->dlci = dlci;
+	dlc->session = session;
+	dlc->rx_credit = RFCOMM_DEFAULT_CREDIT;
+	dlc->state = BT_RFCOMM_STATE_INIT;
+	dlc->role = role;
+	k_delayed_work_init(&dlc->rtx_work, rfcomm_dlc_rtx_timeout);
+
+	/* Start a conn timer which includes auth as well */
+	k_delayed_work_submit(&dlc->rtx_work, RFCOMM_CONN_TIMEOUT);
+
+	dlc->_next = session->dlcs;
+	session->dlcs = dlc;
+}
+
+static struct bt_rfcomm_dlc *rfcomm_dlc_accept(struct bt_rfcomm_session *session,
+					       uint8_t dlci)
+{
+	struct bt_rfcomm_server *server;
+	struct bt_rfcomm_dlc *dlc;
+	uint8_t channel;
+
+	channel = BT_RFCOMM_GET_CHANNEL(dlci);
+	server = rfcomm_server_lookup_channel(channel);
+	if (!server) {
+		BT_ERR("Server Channel not registered");
+		return NULL;
+	}
+
+	if (server->accept(session->br_chan.chan.conn, &dlc) < 0) {
+		BT_DBG("Incoming connection rejected");
+		return NULL;
+	}
+
+	if (!BT_RFCOMM_CHECK_MTU(dlc->mtu)) {
+		rfcomm_dlc_destroy(dlc);
+		return NULL;
+	}
+
+	rfcomm_dlc_init(dlc, session, dlci, BT_RFCOMM_ROLE_ACCEPTOR);
+	dlc->mtu = MIN(dlc->mtu, session->mtu);
+
+	return dlc;
+}
+
+static int rfcomm_send_dm(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t fcs, cr;
+
+	BT_DBG("dlci %d", dlci);
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	cr = BT_RFCOMM_RESP_CR(session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
+	/* For DM PF bit is not relevant, we set it 1 */
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_DM, BT_RFCOMM_PF_NON_UIH);
+	hdr->length = BT_RFCOMM_SET_LEN_8(0);
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static void rfcomm_check_fc(struct bt_rfcomm_dlc *dlc)
+{
+	BT_DBG("%p", dlc);
+
+	BT_DBG("Wait for credits or MSC FC %p", dlc);
+	/* Wait for credits or MSC FC */
+	k_sem_take(&dlc->tx_credits, K_FOREVER);
+
+	if (dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
+		return;
+	}
+
+	k_sem_take(&dlc->session->fc, K_FOREVER);
+
+	/* Give the sems immediately so that sem will be available for all
+	 * the bufs in the queue. It will be blocked only once all the bufs
+	 * are sent (which will preempt this thread) and FCOFF / FC bit
+	 * with 1, is received.
+	 */
+	k_sem_give(&dlc->session->fc);
+	k_sem_give(&dlc->tx_credits);
+}
+
+static void rfcomm_dlc_tx_thread(void *p1, void *p2, void *p3)
+{
+	struct bt_rfcomm_dlc *dlc = p1;
+	k_timeout_t timeout = K_FOREVER;
+	struct net_buf *buf;
+
+	BT_DBG("Started for dlc %p", dlc);
+
+	while (dlc->state == BT_RFCOMM_STATE_CONNECTED ||
+	       dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
+		/* Get next packet for dlc */
+		BT_DBG("Wait for buf %p", dlc);
+		buf = net_buf_get(&dlc->tx_queue, timeout);
+		/* If its dummy buffer or non user disconnect then break */
+		if ((dlc->state != BT_RFCOMM_STATE_CONNECTED &&
+		     dlc->state != BT_RFCOMM_STATE_USER_DISCONNECT) ||
+		    !buf || !buf->len) {
+			if (buf) {
+				net_buf_unref(buf);
+			}
+			break;
+		}
+
+		rfcomm_check_fc(dlc);
+		if (dlc->state != BT_RFCOMM_STATE_CONNECTED &&
+		    dlc->state != BT_RFCOMM_STATE_USER_DISCONNECT) {
+			net_buf_unref(buf);
+			break;
+		}
+
+		if (bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf) < 0) {
+			/* This fails only if channel is disconnected */
+			dlc->state = BT_RFCOMM_STATE_DISCONNECTED;
+			net_buf_unref(buf);
+			break;
+		}
+
+		if (dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
+			timeout = K_NO_WAIT;
+		}
+	}
+
+	BT_DBG("dlc %p disconnected - cleaning up", dlc);
+
+	/* Give back any allocated buffers */
+	while ((buf = net_buf_get(&dlc->tx_queue, K_NO_WAIT))) {
+		net_buf_unref(buf);
+	}
+
+	if (dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
+		dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
+	}
+
+	if (dlc->state == BT_RFCOMM_STATE_DISCONNECTING) {
+		rfcomm_send_disc(dlc->session, dlc->dlci);
+		k_delayed_work_submit(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
+	} else {
+		rfcomm_dlc_destroy(dlc);
+	}
+
+	BT_DBG("dlc %p exiting", dlc);
+}
+
+static int rfcomm_send_ua(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t cr, fcs;
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	cr = BT_RFCOMM_RESP_CR(session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UA, BT_RFCOMM_PF_NON_UIH);
+	hdr->length = BT_RFCOMM_SET_LEN_8(0);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_msc(struct bt_rfcomm_dlc *dlc, uint8_t cr,
+			   uint8_t v24_signal)
+{
+	struct bt_rfcomm_msc *msc;
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(dlc->session, cr, BT_RFCOMM_MSC,
+				  sizeof(*msc));
+
+	msc = net_buf_add(buf, sizeof(*msc));
+	/* cr bit should be always 1 in MSC */
+	msc->dlci = BT_RFCOMM_SET_ADDR(dlc->dlci, 1);
+	msc->v24_signal = v24_signal;
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_rls(struct bt_rfcomm_dlc *dlc, uint8_t cr,
+			   uint8_t line_status)
+{
+	struct bt_rfcomm_rls *rls;
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(dlc->session, cr, BT_RFCOMM_RLS,
+				  sizeof(*rls));
+
+	rls = net_buf_add(buf, sizeof(*rls));
+	/* cr bit should be always 1 in RLS */
+	rls->dlci = BT_RFCOMM_SET_ADDR(dlc->dlci, 1);
+	rls->line_status = line_status;
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_rpn(struct bt_rfcomm_session *session, uint8_t cr,
+			   struct bt_rfcomm_rpn *rpn)
+{
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_RPN, sizeof(*rpn));
+
+	net_buf_add_mem(buf, rpn, sizeof(*rpn));
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_test(struct bt_rfcomm_session *session, uint8_t cr,
+			    uint8_t *pattern, uint8_t len)
+{
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_TEST, len);
+
+	net_buf_add_mem(buf, pattern, len);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_nsc(struct bt_rfcomm_session *session, uint8_t cmd_type)
+{
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(session, BT_RFCOMM_MSG_RESP_CR,
+				  BT_RFCOMM_NSC, sizeof(cmd_type));
+
+	net_buf_add_u8(buf, cmd_type);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_fcon(struct bt_rfcomm_session *session, uint8_t cr)
+{
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_FCON, 0);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_fcoff(struct bt_rfcomm_session *session, uint8_t cr)
+{
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_FCOFF, 0);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&session->br_chan.chan, buf);
+}
+
+static void rfcomm_dlc_connected(struct bt_rfcomm_dlc *dlc)
+{
+	dlc->state = BT_RFCOMM_STATE_CONNECTED;
+
+	rfcomm_send_msc(dlc, BT_RFCOMM_MSG_CMD_CR, BT_RFCOMM_DEFAULT_V24_SIG);
+
+	if (dlc->session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
+		/* This means PN negotiation is not done for this session and
+		 * can happen only for 1.0b device.
+		 */
+		dlc->session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
+	}
+
+	if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
+		BT_DBG("CFC not supported %p", dlc);
+		rfcomm_send_fcon(dlc->session, BT_RFCOMM_MSG_CMD_CR);
+		/* Use tx_credits as binary sem for MSC FC */
+		k_sem_init(&dlc->tx_credits, 0, 1);
+	}
+
+	/* Cancel conn timer */
+	k_delayed_work_cancel(&dlc->rtx_work);
+
+	k_fifo_init(&dlc->tx_queue);
+	k_thread_create(&dlc->tx_thread, dlc->stack,
+			K_KERNEL_STACK_SIZEOF(dlc->stack),
+			rfcomm_dlc_tx_thread, dlc, NULL, NULL, K_PRIO_COOP(7),
+			0, K_NO_WAIT);
+	k_thread_name_set(&dlc->tx_thread, "BT DLC");
+
+	if (dlc->ops && dlc->ops->connected) {
+		dlc->ops->connected(dlc);
+	}
+}
+
+enum security_result {
+	RFCOMM_SECURITY_PASSED,
+	RFCOMM_SECURITY_REJECT,
+	RFCOMM_SECURITY_PENDING
+};
+
+static enum security_result rfcomm_dlc_security(struct bt_rfcomm_dlc *dlc)
+{
+	struct bt_conn *conn = dlc->session->br_chan.chan.conn;
+
+	BT_DBG("dlc %p", dlc);
+
+	/* If current security level is greater than or equal to required
+	 * security level  then return SUCCESS.
+	 * For SSP devices the current security will be atleast MEDIUM
+	 * since L2CAP is enforcing it
+	 */
+	if (conn->sec_level >= dlc->required_sec_level) {
+		return RFCOMM_SECURITY_PASSED;
+	}
+
+	if (!bt_conn_set_security(conn, dlc->required_sec_level)) {
+		/* If Security elevation is initiated or in progress */
+		return RFCOMM_SECURITY_PENDING;
+	}
+
+	/* Security request failed */
+	return RFCOMM_SECURITY_REJECT;
+}
+
+static void rfcomm_dlc_drop(struct bt_rfcomm_dlc *dlc)
+{
+	BT_DBG("dlc %p", dlc);
+
+	rfcomm_dlcs_remove_dlci(dlc->session->dlcs, dlc->dlci);
+	rfcomm_dlc_destroy(dlc);
+}
+
+static int rfcomm_dlc_close(struct bt_rfcomm_dlc *dlc)
+{
+	BT_DBG("dlc %p", dlc);
+
+	switch (dlc->state) {
+	case BT_RFCOMM_STATE_SECURITY_PENDING:
+		if (dlc->role == BT_RFCOMM_ROLE_ACCEPTOR) {
+			rfcomm_send_dm(dlc->session, dlc->dlci);
+		}
+		__fallthrough;
+	case BT_RFCOMM_STATE_INIT:
+		rfcomm_dlc_drop(dlc);
+		break;
+	case BT_RFCOMM_STATE_CONNECTING:
+	case BT_RFCOMM_STATE_CONFIG:
+		dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
+		rfcomm_send_disc(dlc->session, dlc->dlci);
+		k_delayed_work_submit(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
+		break;
+	case BT_RFCOMM_STATE_CONNECTED:
+		dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
+
+		/* Queue a dummy buffer to wake up and stop the
+		 * tx thread.
+		 */
+		net_buf_put(&dlc->tx_queue,
+			    net_buf_alloc(&dummy_pool, K_NO_WAIT));
+
+		/* There could be a writer waiting for credits so return a
+		 * dummy credit to wake it up.
+		 */
+		rfcomm_dlc_tx_give_credits(dlc, 1);
+		break;
+	case BT_RFCOMM_STATE_DISCONNECTING:
+	case BT_RFCOMM_STATE_DISCONNECTED:
+		break;
+	case BT_RFCOMM_STATE_IDLE:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void rfcomm_handle_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	if (!dlci) {
+		if (rfcomm_send_ua(session, dlci) < 0) {
+			return;
+		}
+
+		session->state = BT_RFCOMM_STATE_CONNECTED;
+	} else {
+		struct bt_rfcomm_dlc *dlc;
+		enum security_result result;
+
+		dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+		if (!dlc) {
+			dlc = rfcomm_dlc_accept(session, dlci);
+			if (!dlc) {
+				rfcomm_send_dm(session, dlci);
+				return;
+			}
+		}
+
+		result = rfcomm_dlc_security(dlc);
+		switch (result) {
+		case RFCOMM_SECURITY_PENDING:
+			dlc->state = BT_RFCOMM_STATE_SECURITY_PENDING;
+			return;
+		case RFCOMM_SECURITY_PASSED:
+			break;
+		case RFCOMM_SECURITY_REJECT:
+		default:
+			rfcomm_send_dm(session, dlci);
+			rfcomm_dlc_drop(dlc);
+			return;
+		}
+
+		if (rfcomm_send_ua(session, dlci) < 0) {
+			return;
+		}
+
+		/* Cancel idle timer if any */
+		k_delayed_work_cancel(&session->rtx_work);
+
+		rfcomm_dlc_connected(dlc);
+	}
+}
+
+static int rfcomm_send_pn(struct bt_rfcomm_dlc *dlc, uint8_t cr)
+{
+	struct bt_rfcomm_pn *pn;
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(dlc->session, cr, BT_RFCOMM_PN, sizeof(*pn));
+
+	BT_DBG("mtu %x", dlc->mtu);
+
+	pn = net_buf_add(buf, sizeof(*pn));
+	pn->dlci = dlc->dlci;
+	pn->mtu = sys_cpu_to_le16(dlc->mtu);
+	if (dlc->state == BT_RFCOMM_STATE_CONFIG &&
+	    (dlc->session->cfc == BT_RFCOMM_CFC_UNKNOWN ||
+	     dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED)) {
+		pn->credits = dlc->rx_credit;
+		if (cr) {
+			pn->flow_ctrl = BT_RFCOMM_PN_CFC_CMD;
+		} else {
+			pn->flow_ctrl = BT_RFCOMM_PN_CFC_RESP;
+		}
+	} else {
+		/* If PN comes in already opened dlc or cfc not supported
+		 * these should be 0
+		 */
+		pn->credits = 0U;
+		pn->flow_ctrl = 0U;
+	}
+	pn->max_retrans = 0U;
+	pn->ack_timer = 0U;
+	pn->priority = 0U;
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
+}
+
+static int rfcomm_send_credit(struct bt_rfcomm_dlc *dlc, uint8_t credits)
+{
+	struct bt_rfcomm_hdr *hdr;
+	struct net_buf *buf;
+	uint8_t fcs, cr;
+
+	BT_DBG("Dlc %p credits %d", dlc, credits);
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	cr = BT_RFCOMM_UIH_CR(dlc->session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlc->dlci, cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH,
+					  BT_RFCOMM_PF_UIH_CREDIT);
+	hdr->length = BT_RFCOMM_SET_LEN_8(0);
+	net_buf_add_u8(buf, credits);
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
+}
+
+static int rfcomm_dlc_start(struct bt_rfcomm_dlc *dlc)
+{
+	enum security_result result;
+
+	BT_DBG("dlc %p", dlc);
+
+	result = rfcomm_dlc_security(dlc);
+	switch (result) {
+	case RFCOMM_SECURITY_PASSED:
+		dlc->mtu = MIN(dlc->mtu, dlc->session->mtu);
+		dlc->state = BT_RFCOMM_STATE_CONFIG;
+		rfcomm_send_pn(dlc, BT_RFCOMM_MSG_CMD_CR);
+		break;
+	case RFCOMM_SECURITY_PENDING:
+		dlc->state = BT_RFCOMM_STATE_SECURITY_PENDING;
+		break;
+	case RFCOMM_SECURITY_REJECT:
+	default:
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void rfcomm_handle_ua(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_dlc *dlc, *next;
+	int err;
+
+	if (!dlci) {
+		switch (session->state) {
+		case BT_RFCOMM_STATE_CONNECTING:
+			session->state = BT_RFCOMM_STATE_CONNECTED;
+			for (dlc = session->dlcs; dlc; dlc = next) {
+				next = dlc->_next;
+				if (dlc->role == BT_RFCOMM_ROLE_INITIATOR &&
+				    dlc->state == BT_RFCOMM_STATE_INIT) {
+					if (rfcomm_dlc_start(dlc) < 0) {
+						rfcomm_dlc_drop(dlc);
+					}
+				}
+			}
+			/* Disconnect session if there is no dlcs left */
+			rfcomm_session_disconnect(session);
+			break;
+		case BT_RFCOMM_STATE_DISCONNECTING:
+			session->state = BT_RFCOMM_STATE_DISCONNECTED;
+			/* Cancel disc timer */
+			k_delayed_work_cancel(&session->rtx_work);
+			err = bt_l2cap_chan_disconnect(&session->br_chan.chan);
+			if (err < 0) {
+				session->state = BT_RFCOMM_STATE_IDLE;
+			}
+			break;
+		default:
+			break;
+		}
+	} else {
+		dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+		if (!dlc) {
+			return;
+		}
+
+		switch (dlc->state) {
+		case BT_RFCOMM_STATE_CONNECTING:
+			rfcomm_dlc_connected(dlc);
+			break;
+		case BT_RFCOMM_STATE_DISCONNECTING:
+			rfcomm_dlc_drop(dlc);
+			rfcomm_session_disconnect(session);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static void rfcomm_handle_dm(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("dlci %d", dlci);
+
+	dlc = rfcomm_dlcs_remove_dlci(session->dlcs, dlci);
+	if (!dlc) {
+		return;
+	}
+
+	rfcomm_dlc_disconnect(dlc);
+	rfcomm_session_disconnect(session);
+}
+
+static void rfcomm_handle_msc(struct bt_rfcomm_session *session,
+			      struct net_buf *buf, uint8_t cr)
+{
+	struct bt_rfcomm_msc *msc = (void *)buf->data;
+	struct bt_rfcomm_dlc *dlc;
+	uint8_t dlci = BT_RFCOMM_GET_DLCI(msc->dlci);
+
+	BT_DBG("dlci %d", dlci);
+
+	dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+	if (!dlc) {
+		return;
+	}
+
+	if (cr == BT_RFCOMM_MSG_RESP_CR) {
+		return;
+	}
+
+	if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
+		/* Only FC bit affects the flow on RFCOMM level */
+		if (BT_RFCOMM_GET_FC(msc->v24_signal)) {
+			/* If FC bit is 1 the device is unable to accept frames.
+			 * Take the semaphore with timeout K_NO_WAIT so that
+			 * dlc thread will be blocked when it tries sem_take
+			 * before sending the data. K_NO_WAIT timeout will make
+			 * sure that RX thread will not be blocked while taking
+			 * the semaphore.
+			 */
+			k_sem_take(&dlc->tx_credits, K_NO_WAIT);
+		} else {
+			/* Give the sem so that it will unblock the waiting dlc
+			 * thread in sem_take().
+			 */
+			k_sem_give(&dlc->tx_credits);
+		}
+	}
+
+	rfcomm_send_msc(dlc, BT_RFCOMM_MSG_RESP_CR, msc->v24_signal);
+}
+
+static void rfcomm_handle_rls(struct bt_rfcomm_session *session,
+			      struct net_buf *buf, uint8_t cr)
+{
+	struct bt_rfcomm_rls *rls = (void *)buf->data;
+	uint8_t dlci = BT_RFCOMM_GET_DLCI(rls->dlci);
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("dlci %d", dlci);
+
+	if (!cr) {
+		/* Ignore if its a response */
+		return;
+	}
+
+	dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+	if (!dlc) {
+		return;
+	}
+
+	/* As per the ETSI same line status has to returned in the response */
+	rfcomm_send_rls(dlc, BT_RFCOMM_MSG_RESP_CR, rls->line_status);
+}
+
+static void rfcomm_handle_rpn(struct bt_rfcomm_session *session,
+			      struct net_buf *buf, uint8_t cr)
+{
+	struct bt_rfcomm_rpn default_rpn, *rpn = (void *)buf->data;
+	uint8_t dlci = BT_RFCOMM_GET_DLCI(rpn->dlci);
+	uint8_t data_bits, stop_bits, parity_bits;
+	/* Exclude fcs to get number of value bytes */
+	uint8_t value_len = buf->len - 1;
+
+	BT_DBG("dlci %d", dlci);
+
+	if (!cr) {
+		/* Ignore if its a response */
+		return;
+	}
+
+	if (value_len == sizeof(*rpn)) {
+		/* Accept all the values proposed by the sender */
+		rpn->param_mask = sys_cpu_to_le16(BT_RFCOMM_RPN_PARAM_MASK_ALL);
+		rfcomm_send_rpn(session, BT_RFCOMM_MSG_RESP_CR, rpn);
+		return;
+	}
+
+	if (value_len != 1U) {
+		return;
+	}
+
+	/* If only one value byte then current port settings has to be returned
+	 * We will send default values
+	 */
+	default_rpn.dlci = BT_RFCOMM_SET_ADDR(dlci, 1);
+	default_rpn.baud_rate = BT_RFCOMM_RPN_BAUD_RATE_9600;
+	default_rpn.flow_control = BT_RFCOMM_RPN_FLOW_NONE;
+	default_rpn.xoff_char = BT_RFCOMM_RPN_XOFF_CHAR;
+	default_rpn.xon_char = BT_RFCOMM_RPN_XON_CHAR;
+	data_bits = BT_RFCOMM_RPN_DATA_BITS_8;
+	stop_bits = BT_RFCOMM_RPN_STOP_BITS_1;
+	parity_bits = BT_RFCOMM_RPN_PARITY_NONE;
+	default_rpn.line_settings = BT_RFCOMM_SET_LINE_SETTINGS(data_bits,
+								stop_bits,
+								parity_bits);
+	default_rpn.param_mask = sys_cpu_to_le16(BT_RFCOMM_RPN_PARAM_MASK_ALL);
+
+	rfcomm_send_rpn(session, BT_RFCOMM_MSG_RESP_CR, &default_rpn);
+}
+
+static void rfcomm_handle_pn(struct bt_rfcomm_session *session,
+			     struct net_buf *buf, uint8_t cr)
+{
+	struct bt_rfcomm_pn *pn = (void *)buf->data;
+	struct bt_rfcomm_dlc *dlc;
+
+	dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, pn->dlci);
+	if (!dlc) {
+		/*  Ignore if it is a response */
+		if (!cr) {
+			return;
+		}
+
+		if (!BT_RFCOMM_CHECK_MTU(pn->mtu)) {
+			BT_ERR("Invalid mtu %d", pn->mtu);
+			rfcomm_send_dm(session, pn->dlci);
+			return;
+		}
+
+		dlc = rfcomm_dlc_accept(session, pn->dlci);
+		if (!dlc) {
+			rfcomm_send_dm(session, pn->dlci);
+			return;
+		}
+
+		BT_DBG("Incoming connection accepted dlc %p", dlc);
+
+		dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
+
+		if (pn->flow_ctrl == BT_RFCOMM_PN_CFC_CMD) {
+			if (session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
+				session->cfc = BT_RFCOMM_CFC_SUPPORTED;
+			}
+			k_sem_init(&dlc->tx_credits, 0, UINT32_MAX);
+			rfcomm_dlc_tx_give_credits(dlc, pn->credits);
+		} else {
+			session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
+		}
+
+		dlc->state = BT_RFCOMM_STATE_CONFIG;
+		rfcomm_send_pn(dlc, BT_RFCOMM_MSG_RESP_CR);
+		/* Cancel idle timer if any */
+		k_delayed_work_cancel(&session->rtx_work);
+	} else {
+		/* If its a command */
+		if (cr) {
+			if (!BT_RFCOMM_CHECK_MTU(pn->mtu)) {
+				BT_ERR("Invalid mtu %d", pn->mtu);
+				rfcomm_dlc_close(dlc);
+				return;
+			}
+			dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
+			rfcomm_send_pn(dlc, BT_RFCOMM_MSG_RESP_CR);
+		} else {
+			if (dlc->state != BT_RFCOMM_STATE_CONFIG) {
+				return;
+			}
+
+			dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
+			if (pn->flow_ctrl == BT_RFCOMM_PN_CFC_RESP) {
+				if (session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
+					session->cfc = BT_RFCOMM_CFC_SUPPORTED;
+				}
+				k_sem_init(&dlc->tx_credits, 0, UINT32_MAX);
+				rfcomm_dlc_tx_give_credits(dlc, pn->credits);
+			} else {
+				session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
+			}
+
+			dlc->state = BT_RFCOMM_STATE_CONNECTING;
+			rfcomm_send_sabm(session, dlc->dlci);
+		}
+	}
+}
+
+static void rfcomm_handle_disc(struct bt_rfcomm_session *session, uint8_t dlci)
+{
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("Dlci %d", dlci);
+
+	if (dlci) {
+		dlc = rfcomm_dlcs_remove_dlci(session->dlcs, dlci);
+		if (!dlc) {
+			rfcomm_send_dm(session, dlci);
+			return;
+		}
+
+		rfcomm_send_ua(session, dlci);
+		rfcomm_dlc_disconnect(dlc);
+
+		if (!session->dlcs) {
+			/* Start a session idle timer */
+			k_delayed_work_submit(&dlc->session->rtx_work,
+					      RFCOMM_IDLE_TIMEOUT);
+		}
+	} else {
+		/* Cancel idle timer */
+		k_delayed_work_cancel(&session->rtx_work);
+		rfcomm_send_ua(session, 0);
+		rfcomm_session_disconnected(session);
+	}
+}
+
+static void rfcomm_handle_msg(struct bt_rfcomm_session *session,
+			      struct net_buf *buf)
+{
+	struct bt_rfcomm_msg_hdr *hdr;
+	uint8_t msg_type, len, cr;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small RFCOMM message");
+		return;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	msg_type = BT_RFCOMM_GET_MSG_TYPE(hdr->type);
+	cr = BT_RFCOMM_GET_MSG_CR(hdr->type);
+	len = BT_RFCOMM_GET_LEN(hdr->len);
+
+	BT_DBG("msg type %x cr %x", msg_type, cr);
+
+	switch (msg_type) {
+	case BT_RFCOMM_PN:
+		rfcomm_handle_pn(session, buf, cr);
+		break;
+	case BT_RFCOMM_MSC:
+		rfcomm_handle_msc(session, buf, cr);
+		break;
+	case BT_RFCOMM_RLS:
+		rfcomm_handle_rls(session, buf, cr);
+		break;
+	case BT_RFCOMM_RPN:
+		rfcomm_handle_rpn(session, buf, cr);
+		break;
+	case BT_RFCOMM_TEST:
+		if (!cr) {
+			break;
+		}
+		rfcomm_send_test(session, BT_RFCOMM_MSG_RESP_CR, buf->data,
+				 buf->len - 1);
+		break;
+	case BT_RFCOMM_FCON:
+		if (session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
+			BT_ERR("FCON received when CFC is supported ");
+			return;
+		}
+
+		if (!cr) {
+			break;
+		}
+
+		/* Give the sem so that it will unblock the waiting dlc threads
+		 * of this session in sem_take().
+		 */
+		k_sem_give(&session->fc);
+		rfcomm_send_fcon(session, BT_RFCOMM_MSG_RESP_CR);
+		break;
+	case BT_RFCOMM_FCOFF:
+		if (session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
+			BT_ERR("FCOFF received when CFC is supported ");
+			return;
+		}
+
+		if (!cr) {
+			break;
+		}
+
+		/* Take the semaphore with timeout K_NO_WAIT so that all the
+		 * dlc threads in this session will be blocked when it tries
+		 * sem_take before sending the data. K_NO_WAIT timeout will
+		 * make sure that RX thread will not be blocked while taking
+		 * the semaphore.
+		 */
+		k_sem_take(&session->fc, K_NO_WAIT);
+		rfcomm_send_fcoff(session, BT_RFCOMM_MSG_RESP_CR);
+		break;
+	default:
+		BT_WARN("Unknown/Unsupported RFCOMM Msg type 0x%02x", msg_type);
+		rfcomm_send_nsc(session, hdr->type);
+		break;
+	}
+}
+
+static void rfcomm_dlc_update_credits(struct bt_rfcomm_dlc *dlc)
+{
+	uint8_t credits;
+
+	if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
+		return;
+	}
+
+	BT_DBG("dlc %p credits %u", dlc, dlc->rx_credit);
+
+	/* Only give more credits if it went below the defined threshold */
+	if (dlc->rx_credit > RFCOMM_CREDITS_THRESHOLD) {
+		return;
+	}
+
+	/* Restore credits */
+	credits = RFCOMM_MAX_CREDITS - dlc->rx_credit;
+	dlc->rx_credit += credits;
+
+	rfcomm_send_credit(dlc, credits);
+}
+
+static void rfcomm_handle_data(struct bt_rfcomm_session *session,
+			       struct net_buf *buf, uint8_t dlci, uint8_t pf)
+
+{
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("dlci %d, pf %d", dlci, pf);
+
+	dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+	if (!dlc) {
+		BT_ERR("Data recvd in non existing DLC");
+		rfcomm_send_dm(session, dlci);
+		return;
+	}
+
+	BT_DBG("dlc %p rx credit %d", dlc, dlc->rx_credit);
+
+	if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
+		return;
+	}
+
+	if (pf == BT_RFCOMM_PF_UIH_CREDIT) {
+		rfcomm_dlc_tx_give_credits(dlc, net_buf_pull_u8(buf));
+	}
+
+	if (buf->len > BT_RFCOMM_FCS_SIZE) {
+		if (dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED &&
+		    !dlc->rx_credit) {
+			BT_ERR("Data recvd when rx credit is 0");
+			rfcomm_dlc_close(dlc);
+			return;
+		}
+
+		/* Remove FCS */
+		buf->len -= BT_RFCOMM_FCS_SIZE;
+		if (dlc->ops && dlc->ops->recv) {
+			dlc->ops->recv(dlc, buf);
+		}
+
+		dlc->rx_credit--;
+		rfcomm_dlc_update_credits(dlc);
+	}
+}
+
+int bt_rfcomm_dlc_send(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
+{
+	struct bt_rfcomm_hdr *hdr;
+	uint8_t fcs, cr;
+
+	if (!buf) {
+		return -EINVAL;
+	}
+
+	BT_DBG("dlc %p tx credit %d", dlc, k_sem_count_get(&dlc->tx_credits));
+
+	if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (buf->len > dlc->mtu) {
+		return -EMSGSIZE;
+	}
+
+	if (buf->len > BT_RFCOMM_MAX_LEN_8) {
+		uint16_t *len;
+
+		/* Length is 2 byte */
+		hdr = net_buf_push(buf, sizeof(*hdr) + 1);
+		len = (uint16_t *)&hdr->length;
+		*len = BT_RFCOMM_SET_LEN_16(sys_cpu_to_le16(buf->len -
+							    sizeof(*hdr) - 1));
+	} else {
+		hdr = net_buf_push(buf, sizeof(*hdr));
+		hdr->length = BT_RFCOMM_SET_LEN_8(buf->len - sizeof(*hdr));
+	}
+
+	cr = BT_RFCOMM_UIH_CR(dlc->session->role);
+	hdr->address = BT_RFCOMM_SET_ADDR(dlc->dlci, cr);
+	hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH,
+					  BT_RFCOMM_PF_UIH_NO_CREDIT);
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	net_buf_put(&dlc->tx_queue, buf);
+
+	return buf->len;
+}
+
+static int rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
+	struct bt_rfcomm_hdr *hdr = (void *)buf->data;
+	uint8_t dlci, frame_type, fcs, fcs_len;
+
+	/* Need to consider FCS also*/
+	if (buf->len < (sizeof(*hdr) + 1)) {
+		BT_ERR("Too small RFCOMM Frame");
+		return 0;
+	}
+
+	dlci = BT_RFCOMM_GET_DLCI(hdr->address);
+	frame_type = BT_RFCOMM_GET_FRAME_TYPE(hdr->control);
+
+	BT_DBG("session %p dlci %x type %x", session, dlci, frame_type);
+
+	fcs_len = (frame_type == BT_RFCOMM_UIH) ? BT_RFCOMM_FCS_LEN_UIH :
+		   BT_RFCOMM_FCS_LEN_NON_UIH;
+	fcs = *(net_buf_tail(buf) - 1);
+	if (!rfcomm_check_fcs(fcs_len, buf->data, fcs)) {
+		BT_ERR("FCS check failed");
+		return 0;
+	}
+
+	if (BT_RFCOMM_LEN_EXTENDED(hdr->length)) {
+		net_buf_pull(buf, sizeof(*hdr) + 1);
+	} else {
+		net_buf_pull(buf, sizeof(*hdr));
+	}
+
+	switch (frame_type) {
+	case BT_RFCOMM_SABM:
+		rfcomm_handle_sabm(session, dlci);
+		break;
+	case BT_RFCOMM_UIH:
+		if (!dlci) {
+			rfcomm_handle_msg(session, buf);
+		} else {
+			rfcomm_handle_data(session, buf, dlci,
+					   BT_RFCOMM_GET_PF(hdr->control));
+		}
+		break;
+	case BT_RFCOMM_DISC:
+		rfcomm_handle_disc(session, dlci);
+		break;
+	case BT_RFCOMM_UA:
+		rfcomm_handle_ua(session, dlci);
+		break;
+	case BT_RFCOMM_DM:
+		rfcomm_handle_dm(session, dlci);
+		break;
+	default:
+		BT_WARN("Unknown/Unsupported RFCOMM Frame type 0x%02x",
+			frame_type);
+		break;
+	}
+
+	return 0;
+}
+
+static void rfcomm_encrypt_change(struct bt_l2cap_chan *chan,
+				  uint8_t hci_status)
+{
+	struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
+	struct bt_conn *conn = chan->conn;
+	struct bt_rfcomm_dlc *dlc, *next;
+
+	BT_DBG("session %p status 0x%02x encr 0x%02x", session, hci_status,
+	       conn->encrypt);
+
+	for (dlc = session->dlcs; dlc; dlc = next) {
+		next = dlc->_next;
+
+		if (dlc->state != BT_RFCOMM_STATE_SECURITY_PENDING) {
+			continue;
+		}
+
+		if (hci_status || !conn->encrypt ||
+		    conn->sec_level < dlc->required_sec_level) {
+			rfcomm_dlc_close(dlc);
+			continue;
+		}
+
+		if (dlc->role == BT_RFCOMM_ROLE_ACCEPTOR) {
+			rfcomm_send_ua(session, dlc->dlci);
+			rfcomm_dlc_connected(dlc);
+		} else {
+			dlc->mtu = MIN(dlc->mtu, session->mtu);
+			dlc->state = BT_RFCOMM_STATE_CONFIG;
+			rfcomm_send_pn(dlc, BT_RFCOMM_MSG_CMD_CR);
+		}
+	}
+}
+
+static void rfcomm_session_rtx_timeout(struct k_work *work)
+{
+	struct bt_rfcomm_session *session = SESSION_RTX(work);
+
+	BT_WARN("session %p state %d timeout", session, session->state);
+
+	switch (session->state) {
+	case BT_RFCOMM_STATE_CONNECTED:
+		rfcomm_session_disconnect(session);
+		break;
+	case BT_RFCOMM_STATE_DISCONNECTING:
+		session->state = BT_RFCOMM_STATE_DISCONNECTED;
+		if (bt_l2cap_chan_disconnect(&session->br_chan.chan) < 0) {
+			session->state = BT_RFCOMM_STATE_IDLE;
+		}
+		break;
+	}
+}
+
+static struct bt_rfcomm_session *rfcomm_session_new(bt_rfcomm_role_t role)
+{
+	int i;
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = rfcomm_connected,
+		.disconnected = rfcomm_disconnected,
+		.recv = rfcomm_recv,
+		.encrypt_change = rfcomm_encrypt_change,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(bt_rfcomm_pool); i++) {
+		struct bt_rfcomm_session *session = &bt_rfcomm_pool[i];
+
+		if (session->br_chan.chan.conn) {
+			continue;
+		}
+
+		BT_DBG("session %p initialized", session);
+
+		session->br_chan.chan.ops = &ops;
+		session->br_chan.rx.mtu	= CONFIG_BT_RFCOMM_L2CAP_MTU;
+		session->state = BT_RFCOMM_STATE_INIT;
+		session->role = role;
+		session->cfc = BT_RFCOMM_CFC_UNKNOWN;
+		k_delayed_work_init(&session->rtx_work,
+				    rfcomm_session_rtx_timeout);
+		k_sem_init(&session->fc, 0, 1);
+
+		return session;
+	}
+
+	return NULL;
+}
+
+int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
+			  uint8_t channel)
+{
+	struct bt_rfcomm_session *session;
+	struct bt_l2cap_chan *chan;
+	uint8_t dlci;
+	int ret;
+
+	BT_DBG("conn %p dlc %p channel %d", conn, dlc, channel);
+
+	if (!dlc) {
+		return -EINVAL;
+	}
+
+	if (!conn || conn->state != BT_CONN_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	if (channel < RFCOMM_CHANNEL_START || channel > RFCOMM_CHANNEL_END) {
+		return -EINVAL;
+	}
+
+	if (!BT_RFCOMM_CHECK_MTU(dlc->mtu)) {
+		return -EINVAL;
+	}
+
+	session = rfcomm_sessions_lookup_bt_conn(conn);
+	if (!session) {
+		session = rfcomm_session_new(BT_RFCOMM_ROLE_INITIATOR);
+		if (!session) {
+			return -ENOMEM;
+		}
+	}
+
+	dlci = BT_RFCOMM_DLCI(session->role, channel);
+
+	if (rfcomm_dlcs_lookup_dlci(session->dlcs, dlci)) {
+		return -EBUSY;
+	}
+
+	rfcomm_dlc_init(dlc, session, dlci, BT_RFCOMM_ROLE_INITIATOR);
+
+	switch (session->state) {
+	case BT_RFCOMM_STATE_INIT:
+		if (session->role == BT_RFCOMM_ROLE_ACCEPTOR) {
+			/* There is an ongoing incoming conn */
+			break;
+		}
+		chan = &session->br_chan.chan;
+		chan->required_sec_level = dlc->required_sec_level;
+		ret = bt_l2cap_chan_connect(conn, chan, BT_L2CAP_PSM_RFCOMM);
+		if (ret < 0) {
+			session->state = BT_RFCOMM_STATE_IDLE;
+			goto fail;
+		}
+		session->state = BT_RFCOMM_STATE_CONNECTING;
+		break;
+	case BT_RFCOMM_STATE_CONNECTING:
+		break;
+	case BT_RFCOMM_STATE_CONNECTED:
+		ret = rfcomm_dlc_start(dlc);
+		if (ret < 0) {
+			goto fail;
+		}
+		/* Cancel idle timer if any */
+		k_delayed_work_cancel(&session->rtx_work);
+		break;
+	default:
+		BT_ERR("Invalid session state %d", session->state);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	rfcomm_dlcs_remove_dlci(session->dlcs, dlc->dlci);
+	dlc->state = BT_RFCOMM_STATE_IDLE;
+	dlc->session = NULL;
+	return ret;
+}
+
+int bt_rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc)
+{
+	BT_DBG("dlc %p", dlc);
+
+	if (!dlc) {
+		return -EINVAL;
+	}
+
+	if (dlc->state == BT_RFCOMM_STATE_CONNECTED) {
+		/* This is to handle user initiated disconnect to send pending
+		 * bufs in the queue before disconnecting
+		 * Queue a dummy buffer (in case if queue is empty) to wake up
+		 * and stop the tx thread.
+		 */
+		dlc->state = BT_RFCOMM_STATE_USER_DISCONNECT;
+		net_buf_put(&dlc->tx_queue,
+			    net_buf_alloc(&dummy_pool, K_NO_WAIT));
+
+		k_delayed_work_submit(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
+
+		return 0;
+	}
+
+	return rfcomm_dlc_close(dlc);
+}
+
+static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	struct bt_rfcomm_session *session;
+
+	BT_DBG("conn %p", conn);
+
+	session = rfcomm_session_new(BT_RFCOMM_ROLE_ACCEPTOR);
+	if (session) {
+		*chan = &session->br_chan.chan;
+		return 0;
+	}
+
+	BT_ERR("No available RFCOMM context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+void bt_rfcomm_init(void)
+{
+	static struct bt_l2cap_server server = {
+		.psm       = BT_L2CAP_PSM_RFCOMM,
+		.accept    = rfcomm_accept,
+		.sec_level = BT_SECURITY_L1,
+	};
+
+	bt_l2cap_br_server_register(&server);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/rfcomm_internal.h	(working copy)
@@ -0,0 +1,213 @@
+/** @file
+ *  @brief Internal APIs for Bluetooth RFCOMM handling.
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <bluetooth/rfcomm.h>
+
+typedef enum {
+	BT_RFCOMM_CFC_UNKNOWN,
+	BT_RFCOMM_CFC_NOT_SUPPORTED,
+	BT_RFCOMM_CFC_SUPPORTED,
+} __packed bt_rfcomm_cfc_t;
+
+/* RFCOMM signalling connection specific context */
+struct bt_rfcomm_session {
+	/* L2CAP channel this context is associated with */
+	struct bt_l2cap_br_chan br_chan;
+	/* Response Timeout eXpired (RTX) timer */
+	//struct k_delayed_work rtx_work;
+	/* Binary sem for aggregate fc */
+	//struct k_sem fc;
+	struct bt_rfcomm_dlc *dlcs;
+	uint16_t mtu;
+	uint8_t state;
+	bt_rfcomm_role_t role;
+	bt_rfcomm_cfc_t cfc;
+};
+
+enum {
+	BT_RFCOMM_STATE_IDLE,
+	BT_RFCOMM_STATE_INIT,
+	BT_RFCOMM_STATE_SECURITY_PENDING,
+	BT_RFCOMM_STATE_CONNECTING,
+	BT_RFCOMM_STATE_CONNECTED,
+	BT_RFCOMM_STATE_CONFIG,
+	BT_RFCOMM_STATE_USER_DISCONNECT,
+	BT_RFCOMM_STATE_DISCONNECTING,
+	BT_RFCOMM_STATE_DISCONNECTED,
+};
+
+struct bt_rfcomm_hdr {
+	uint8_t address;
+	uint8_t control;
+	uint8_t length;
+} __packed;
+
+#define BT_RFCOMM_SABM  0x2f
+#define BT_RFCOMM_UA    0x63
+#define BT_RFCOMM_UIH   0xef
+
+struct bt_rfcomm_msg_hdr {
+	uint8_t type;
+	uint8_t len;
+} __packed;
+
+#define BT_RFCOMM_PN    0x20
+struct bt_rfcomm_pn {
+	uint8_t  dlci;
+	uint8_t  flow_ctrl;
+	uint8_t  priority;
+	uint8_t  ack_timer;
+	uint16_t mtu;
+	uint8_t  max_retrans;
+	uint8_t  credits;
+} __packed;
+
+#define BT_RFCOMM_MSC    0x38
+struct bt_rfcomm_msc {
+	uint8_t  dlci;
+	uint8_t  v24_signal;
+} __packed;
+
+#define BT_RFCOMM_DISC  0x43
+#define BT_RFCOMM_DM    0x0f
+
+#define BT_RFCOMM_RLS   0x14
+struct bt_rfcomm_rls {
+	uint8_t  dlci;
+	uint8_t  line_status;
+} __packed;
+
+#define BT_RFCOMM_RPN   0x24
+struct bt_rfcomm_rpn {
+	uint8_t  dlci;
+	uint8_t  baud_rate;
+	uint8_t  line_settings;
+	uint8_t  flow_control;
+	uint8_t  xon_char;
+	uint8_t  xoff_char;
+	uint16_t param_mask;
+} __packed;
+
+#define BT_RFCOMM_TEST  0x08
+#define BT_RFCOMM_NSC   0x04
+
+#define BT_RFCOMM_FCON  0x28
+#define BT_RFCOMM_FCOFF 0x18
+
+/* Default RPN Settings */
+#define BT_RFCOMM_RPN_BAUD_RATE_9600    0x03
+#define BT_RFCOMM_RPN_DATA_BITS_8       0x03
+#define BT_RFCOMM_RPN_STOP_BITS_1       0x00
+#define BT_RFCOMM_RPN_PARITY_NONE       0x00
+#define BT_RFCOMM_RPN_FLOW_NONE         0x00
+#define BT_RFCOMM_RPN_XON_CHAR          0x11
+#define BT_RFCOMM_RPN_XOFF_CHAR         0x13
+
+/* Set 1 to all the param mask except reserved */
+#define BT_RFCOMM_RPN_PARAM_MASK_ALL    0x3f7f
+
+#define BT_RFCOMM_SET_LINE_SETTINGS(data, stop, parity) ((data & 0x3) | \
+							 ((stop & 0x1) << 2) | \
+							 ((parity & 0x7) << 3))
+
+/* DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 */
+#define BT_RFCOMM_DEFAULT_V24_SIG 0x8d
+
+#define BT_RFCOMM_GET_FC(v24_signal) (((v24_signal) & 0x02) >> 1)
+
+#define BT_RFCOMM_SIG_MIN_MTU   23
+#define BT_RFCOMM_SIG_MAX_MTU   32767
+
+#define BT_RFCOMM_CHECK_MTU(mtu) (!!((mtu) >= BT_RFCOMM_SIG_MIN_MTU && \
+				     (mtu) <= BT_RFCOMM_SIG_MAX_MTU))
+
+/* Helper to calculate needed outgoing buffer size.
+ * Length in rfcomm header can be two bytes depending on user data length.
+ * One byte in the tail should be reserved for FCS.
+ */
+#define BT_RFCOMM_BUF_SIZE(mtu) (BT_BUF_RESERVE + \
+				 BT_HCI_ACL_HDR_SIZE + BT_L2CAP_HDR_SIZE + \
+				 sizeof(struct bt_rfcomm_hdr) + 1 + (mtu) + \
+				 BT_RFCOMM_FCS_SIZE)
+
+#define BT_RFCOMM_GET_DLCI(addr)           (((addr) & 0xfc) >> 2)
+#define BT_RFCOMM_GET_FRAME_TYPE(ctrl)     ((ctrl) & 0xef)
+#define BT_RFCOMM_GET_MSG_TYPE(type)       (((type) & 0xfc) >> 2)
+#define BT_RFCOMM_GET_MSG_CR(type)         (((type) & 0x02) >> 1)
+#define BT_RFCOMM_GET_LEN(len)             (((len) & 0xfe) >> 1)
+#define BT_RFCOMM_GET_CHANNEL(dlci)        ((dlci) >> 1)
+#define BT_RFCOMM_GET_PF(ctrl)             (((ctrl) & 0x10) >> 4)
+
+#define BT_RFCOMM_SET_ADDR(dlci, cr)       ((((dlci) & 0x3f) << 2) | \
+					    ((cr) << 1) | 0x01)
+#define BT_RFCOMM_SET_CTRL(type, pf)       (((type) & 0xef) | ((pf) << 4))
+#define BT_RFCOMM_SET_LEN_8(len)           (((len) << 1) | 1)
+#define BT_RFCOMM_SET_LEN_16(len)          ((len) << 1)
+#define BT_RFCOMM_SET_MSG_TYPE(type, cr)   (((type) << 2) | (cr << 1) | 0x01)
+
+#define BT_RFCOMM_LEN_EXTENDED(len)        (!((len) & 0x01))
+
+/* For CR in UIH Packet header
+ * Initiating station have the C/R bit set to 1 and those sent by the
+ * responding station have the C/R bit set to 0
+ */
+#define BT_RFCOMM_UIH_CR(role)             ((role) == BT_RFCOMM_ROLE_INITIATOR)
+
+/* For CR in Non UIH Packet header
+ * Command
+ * Initiator --> Responder 1
+ * Responder --> Initiator 0
+ * Response
+ * Initiator --> Responder 0
+ * Responder --> Initiator 1
+ */
+#define BT_RFCOMM_CMD_CR(role)             ((role) == BT_RFCOMM_ROLE_INITIATOR)
+#define BT_RFCOMM_RESP_CR(role)            ((role) == BT_RFCOMM_ROLE_ACCEPTOR)
+
+/* For CR in MSG header
+ * If the C/R bit is set to 1 the message is a command,
+ * if it is set to 0 the message is a response.
+ */
+#define BT_RFCOMM_MSG_CMD_CR               1
+#define BT_RFCOMM_MSG_RESP_CR              0
+
+#define BT_RFCOMM_DLCI(role, channel)      ((((channel) & 0x1f) << 1) | \
+					    ((role) == BT_RFCOMM_ROLE_ACCEPTOR))
+
+/* Excluding ext bit */
+#define BT_RFCOMM_MAX_LEN_8 127
+
+/* Length can be 2 bytes depending on data size */
+#define BT_RFCOMM_HDR_SIZE  (sizeof(struct bt_rfcomm_hdr) + 1)
+#define BT_RFCOMM_FCS_SIZE  1
+
+#define BT_RFCOMM_FCS_LEN_UIH      2
+#define BT_RFCOMM_FCS_LEN_NON_UIH  3
+
+/* For non UIH packets
+ * The P bit set to 1 shall be used to solicit a response frame with the
+ * F bit set to 1 from the other station.
+ */
+#define BT_RFCOMM_PF_NON_UIH         1
+
+/* For UIH packets
+ * Both stations set the P-bit to 0
+ * If credit based flow control is used, If P/F is 1 then one credit byte
+ * will be there after control in the frame else no credit byte.
+ */
+#define BT_RFCOMM_PF_UIH             0
+#define BT_RFCOMM_PF_UIH_CREDIT      1
+#define BT_RFCOMM_PF_UIH_NO_CREDIT   0
+
+#define BT_RFCOMM_PN_CFC_CMD   0xf0
+#define BT_RFCOMM_PN_CFC_RESP  0xe0
+
+/* Initialize RFCOMM signal layer */
+void bt_rfcomm_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp.c	(working copy)
@@ -0,0 +1,2536 @@
+/** @file
+ *  @brief Service Discovery Protocol handling.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/byteorder.h>
+#include <sys/__assert.h>
+
+#include <bluetooth/sdp.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SDP)
+#define LOG_MODULE_NAME bt_sdp
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "sdp_internal.h"
+
+#define SDP_PSM 0x0001
+
+#define SDP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp, chan.chan)
+
+#define IN_RANGE(val, min, max) (val >= min && val <= max)
+
+#define SDP_DATA_MTU 200
+
+#define SDP_MTU (SDP_DATA_MTU + sizeof(struct bt_sdp_hdr))
+
+#define MAX_NUM_ATT_ID_FILTER 10
+
+#define SDP_SERVICE_HANDLE_BASE 0x10000
+
+#define SDP_DATA_ELEM_NEST_LEVEL_MAX 5
+
+/* Size of Cont state length */
+#define SDP_CONT_STATE_LEN_SIZE 1
+
+/* 1 byte for the no. of services searched till this response */
+/* 2 bytes for the total no. of matching records */
+#define SDP_SS_CONT_STATE_SIZE 3
+
+/* 1 byte for the no. of attributes searched till this response */
+#define SDP_SA_CONT_STATE_SIZE 1
+
+/* 1 byte for the no. of services searched till this response */
+/* 1 byte for the no. of attributes searched till this response */
+#define SDP_SSA_CONT_STATE_SIZE 2
+
+#define SDP_INVALID 0xff
+
+struct bt_sdp {
+	struct bt_l2cap_br_chan chan;
+	struct k_fifo           partial_resp_queue;
+	/* TODO: Allow more than one pending request */
+};
+
+static struct bt_sdp_record *db;
+static uint8_t num_services;
+
+static struct bt_sdp bt_sdp_pool[CONFIG_BT_MAX_CONN];
+
+/* Pool for outgoing SDP packets */
+NET_BUF_POOL_FIXED_DEFINE(sdp_pool, CONFIG_BT_MAX_CONN,
+			  BT_L2CAP_BUF_SIZE(SDP_MTU), NULL);
+
+#define SDP_CLIENT_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp_client, chan.chan)
+
+#define SDP_CLIENT_MTU 64
+
+struct bt_sdp_client {
+	struct bt_l2cap_br_chan              chan;
+	/* list of waiting to be resolved UUID params */
+	sys_slist_t                          reqs;
+	/* required SDP transaction ID */
+	uint16_t                                tid;
+	/* UUID params holder being now resolved */
+	const struct bt_sdp_discover_params *param;
+	/* PDU continuation state object */
+	struct bt_sdp_pdu_cstate             cstate;
+	/* buffer for collecting record data */
+	struct net_buf                      *rec_buf;
+};
+
+static struct bt_sdp_client bt_sdp_client_pool[CONFIG_BT_MAX_CONN];
+
+enum {
+	BT_SDP_ITER_STOP,
+	BT_SDP_ITER_CONTINUE,
+};
+
+struct search_state {
+	uint16_t att_list_size;
+	uint8_t  current_svc;
+	uint8_t  last_att;
+	bool     pkt_full;
+};
+
+struct select_attrs_data {
+	struct bt_sdp_record        *rec;
+	struct net_buf              *rsp_buf;
+	struct bt_sdp               *sdp;
+	struct bt_sdp_data_elem_seq *seq;
+	struct search_state         *state;
+	uint32_t                       *filter;
+	uint16_t                        max_att_len;
+	uint16_t                        att_list_len;
+	uint8_t                         cont_state_size;
+	uint8_t                         num_filters;
+	bool                         new_service;
+};
+
+/* @typedef bt_sdp_attr_func_t
+ *  @brief SDP attribute iterator callback.
+ *
+ *  @param attr Attribute found.
+ *  @param att_idx Index of the found attribute in the attribute database.
+ *  @param user_data Data given.
+ *
+ *  @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
+ *  or BT_SDP_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_sdp_attr_func_t)(struct bt_sdp_attribute *attr,
+				   uint8_t att_idx, void *user_data);
+
+/* @typedef bt_sdp_svc_func_t
+ * @brief SDP service record iterator callback.
+ *
+ * @param rec Service record found.
+ * @param user_data Data given.
+ *
+ * @return BT_SDP_ITER_CONTINUE if should continue to the next service record
+ *  or BT_SDP_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_sdp_svc_func_t)(struct bt_sdp_record *rec,
+				  void *user_data);
+
+/* @brief Callback for SDP connection
+ *
+ *  Gets called when an SDP connection is established
+ *
+ *  @param chan L2CAP channel
+ *
+ *  @return None
+ */
+static void bt_sdp_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
+						   struct bt_l2cap_br_chan,
+						   chan);
+
+	struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
+
+	BT_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
+
+	k_fifo_init(&sdp->partial_resp_queue);
+}
+
+/** @brief Callback for SDP disconnection
+ *
+ *  Gets called when an SDP connection is terminated
+ *
+ *  @param chan L2CAP channel
+ *
+ *  @return None
+ */
+static void bt_sdp_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
+						   struct bt_l2cap_br_chan,
+						   chan);
+
+	struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
+
+	BT_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
+
+	(void)memset(sdp, 0, sizeof(*sdp));
+}
+
+/* @brief Creates an SDP PDU
+ *
+ *  Creates an empty SDP PDU and returns the buffer
+ *
+ *  @param None
+ *
+ *  @return Pointer to the net_buf buffer
+ */
+static struct net_buf *bt_sdp_create_pdu(void)
+{
+	return bt_l2cap_create_pdu(&sdp_pool, sizeof(struct bt_sdp_hdr));
+}
+
+/* @brief Sends out an SDP PDU
+ *
+ *  Sends out an SDP PDU after adding the relevant header
+ *
+ *  @param chan L2CAP channel
+ *  @param buf Buffer to be sent out
+ *  @param op Opcode to be used in the packet header
+ *  @param tid Transaction ID to be used in the packet header
+ *
+ *  @return None
+ */
+static void bt_sdp_send(struct bt_l2cap_chan *chan, struct net_buf *buf,
+			uint8_t op, uint16_t tid)
+{
+	struct bt_sdp_hdr *hdr;
+	uint16_t param_len = buf->len;
+
+	hdr = net_buf_push(buf, sizeof(struct bt_sdp_hdr));
+	hdr->op_code = op;
+	hdr->tid = tid;
+	hdr->param_len = sys_cpu_to_be16(param_len);
+
+	bt_l2cap_chan_send(chan, buf);
+}
+
+/* @brief Sends an error response PDU
+ *
+ *  Creates and sends an error response PDU
+ *
+ *  @param chan L2CAP channel
+ *  @param err Error code to be sent in the packet
+ *  @param tid Transaction ID to be used in the packet header
+ *
+ *  @return None
+ */
+static void send_err_rsp(struct bt_l2cap_chan *chan, uint16_t err,
+			 uint16_t tid)
+{
+	struct net_buf *buf;
+
+	BT_DBG("tid %u, error %u", tid, err);
+
+	buf = bt_sdp_create_pdu();
+
+	net_buf_add_be16(buf, err);
+
+	bt_sdp_send(chan, buf, BT_SDP_ERROR_RSP, tid);
+}
+
+/* @brief Parses data elements from a net_buf
+ *
+ * Parses the first data element from a buffer and splits it into type, size,
+ * data. Used for parsing incoming requests. Net buf is advanced to the data
+ * part of the element.
+ *
+ * @param buf Buffer to be advanced
+ * @param data_elem Pointer to the parsed data element structure
+ *
+ * @return 0 for success, or relevant error code
+ */
+static uint16_t parse_data_elem(struct net_buf *buf,
+				struct bt_sdp_data_elem *data_elem)
+{
+	uint8_t size_field_len = 0U; /* Space used to accommodate the size */
+
+	if (buf->len < 1) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	data_elem->type = net_buf_pull_u8(buf);
+
+	switch (data_elem->type & BT_SDP_TYPE_DESC_MASK) {
+	case BT_SDP_UINT8:
+	case BT_SDP_INT8:
+	case BT_SDP_UUID_UNSPEC:
+	case BT_SDP_BOOL:
+		data_elem->data_size = BIT(data_elem->type &
+					   BT_SDP_SIZE_DESC_MASK);
+		break;
+	case BT_SDP_TEXT_STR_UNSPEC:
+	case BT_SDP_SEQ_UNSPEC:
+	case BT_SDP_ALT_UNSPEC:
+	case BT_SDP_URL_STR_UNSPEC:
+		size_field_len = BIT((data_elem->type & BT_SDP_SIZE_DESC_MASK) -
+				     BT_SDP_SIZE_INDEX_OFFSET);
+		if (buf->len < size_field_len) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+		switch (size_field_len) {
+		case 1:
+			data_elem->data_size = net_buf_pull_u8(buf);
+			break;
+		case 2:
+			data_elem->data_size = net_buf_pull_be16(buf);
+			break;
+		case 4:
+			data_elem->data_size = net_buf_pull_be32(buf);
+			break;
+		default:
+			BT_WARN("Invalid size in remote request");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+		break;
+	default:
+		BT_WARN("Invalid type in remote request");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	if (buf->len < data_elem->data_size) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	data_elem->total_size = data_elem->data_size + size_field_len + 1;
+	data_elem->data = buf->data;
+
+	return 0;
+}
+
+/* @brief Searches for an UUID within an attribute
+ *
+ * Searches for an UUID within an attribute. If the attribute has data element
+ * sequences, it recursively searches within them as well. On finding a match
+ * with the UUID, it sets the found flag.
+ *
+ * @param elem Attribute to be used as the search space (haystack)
+ * @param uuid UUID to be looked for (needle)
+ * @param found Flag set to true if the UUID is found (to be returned)
+ * @param nest_level Used to limit the extent of recursion into nested data
+ *  elements, to avoid potential stack overflows
+ *
+ * @return Size of the last data element that has been searched
+ *  (used in recursion)
+ */
+static uint32_t search_uuid(struct bt_sdp_data_elem *elem, struct bt_uuid *uuid,
+			 bool *found, uint8_t nest_level)
+{
+	const uint8_t *cur_elem;
+	uint32_t seq_size, size;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_32 u32;
+		struct bt_uuid_128 u128;
+	} u;
+
+	if (*found) {
+		return 0;
+	}
+
+	/* Limit recursion depth to avoid stack overflows */
+	if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
+		return 0;
+	}
+
+	seq_size = elem->data_size;
+	cur_elem = elem->data;
+
+	if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
+		if (seq_size == 2U) {
+			u.uuid.type = BT_UUID_TYPE_16;
+			u.u16.val = *((uint16_t *)cur_elem);
+			if (!bt_uuid_cmp(&u.uuid, uuid)) {
+				*found = true;
+			}
+		} else if (seq_size == 4U) {
+			u.uuid.type = BT_UUID_TYPE_32;
+			u.u32.val = *((uint32_t *)cur_elem);
+			if (!bt_uuid_cmp(&u.uuid, uuid)) {
+				*found = true;
+			}
+		} else if (seq_size == 16U) {
+			u.uuid.type = BT_UUID_TYPE_128;
+			memcpy(u.u128.val, cur_elem, seq_size);
+			if (!bt_uuid_cmp(&u.uuid, uuid)) {
+				*found = true;
+			}
+		} else {
+			BT_WARN("Invalid UUID size in local database");
+			BT_ASSERT(0);
+		}
+	}
+
+	if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
+	    (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
+		do {
+			/* Recursively parse data elements */
+			size = search_uuid((struct bt_sdp_data_elem *)cur_elem,
+					   uuid, found, nest_level + 1);
+			if (*found) {
+				return 0;
+			}
+			cur_elem += sizeof(struct bt_sdp_data_elem);
+			seq_size -= size;
+		} while (seq_size);
+	}
+
+	return elem->total_size;
+}
+
+/* @brief SDP service record iterator.
+ *
+ * Iterate over service records from a starting point.
+ *
+ * @param func Callback function.
+ * @param user_data Data to pass to the callback.
+ *
+ * @return Pointer to the record where the iterator stopped, or NULL if all
+ *  records are covered
+ */
+static struct bt_sdp_record *bt_sdp_foreach_svc(bt_sdp_svc_func_t func,
+						void *user_data)
+{
+	struct bt_sdp_record *rec = db;
+
+	while (rec) {
+		if (func(rec, user_data) == BT_SDP_ITER_STOP) {
+			break;
+		}
+
+		rec = rec->next;
+	}
+	return rec;
+}
+
+/* @brief Inserts a service record into a record pointer list
+ *
+ * Inserts a service record into a record pointer list
+ *
+ * @param rec The current service record.
+ * @param user_data Pointer to the destination record list.
+ *
+ * @return BT_SDP_ITER_CONTINUE to move on to the next record.
+ */
+static uint8_t insert_record(struct bt_sdp_record *rec, void *user_data)
+{
+	struct bt_sdp_record **rec_list = user_data;
+
+	rec_list[rec->index] = rec;
+
+	return BT_SDP_ITER_CONTINUE;
+}
+
+/* @brief Looks for matching UUIDs in a list of service records
+ *
+ * Parses out a sequence of UUIDs from an input buffer, and checks if a record
+ * in the list contains all the UUIDs. If it doesn't, the record is removed
+ * from the list, so the list contains only the records which has all the
+ * input UUIDs in them.
+ *
+ * @param buf Incoming buffer containing all the UUIDs to be matched
+ * @param matching_recs List of service records to use for storing matching
+ * records
+ *
+ * @return 0 for success, or relevant error code
+ */
+static uint16_t find_services(struct net_buf *buf,
+			      struct bt_sdp_record **matching_recs)
+{
+	struct bt_sdp_data_elem data_elem;
+	struct bt_sdp_record *record;
+	uint32_t uuid_list_size;
+	uint16_t res;
+	uint8_t att_idx, rec_idx = 0U;
+	bool found;
+	union {
+		struct bt_uuid uuid;
+		struct bt_uuid_16 u16;
+		struct bt_uuid_32 u32;
+		struct bt_uuid_128 u128;
+	} u;
+
+	res = parse_data_elem(buf, &data_elem);
+	if (res) {
+		return res;
+	}
+
+	if (((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_SEQ_UNSPEC) &&
+	    ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_ALT_UNSPEC)) {
+		BT_WARN("Invalid type %x in service search pattern",
+			data_elem.type);
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	uuid_list_size = data_elem.data_size;
+
+	bt_sdp_foreach_svc(insert_record, matching_recs);
+
+	/* Go over the sequence of UUIDs, and match one UUID at a time */
+	while (uuid_list_size) {
+		res = parse_data_elem(buf, &data_elem);
+		if (res) {
+			return res;
+		}
+
+		if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) !=
+		    BT_SDP_UUID_UNSPEC) {
+			BT_WARN("Invalid type %u in service search pattern",
+				data_elem.type);
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		if (buf->len < data_elem.data_size) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		if (data_elem.data_size == 2U) {
+			u.uuid.type = BT_UUID_TYPE_16;
+			u.u16.val = net_buf_pull_be16(buf);
+		} else if (data_elem.data_size == 4U) {
+			u.uuid.type = BT_UUID_TYPE_32;
+			u.u32.val = net_buf_pull_be32(buf);
+		} else if (data_elem.data_size == 16U) {
+			u.uuid.type = BT_UUID_TYPE_128;
+			sys_memcpy_swap(u.u128.val, buf->data,
+					data_elem.data_size);
+			net_buf_pull(buf, data_elem.data_size);
+		} else {
+			BT_WARN("Invalid UUID len %u in service search pattern",
+				data_elem.data_size);
+			net_buf_pull(buf, data_elem.data_size);
+		}
+
+		uuid_list_size -= data_elem.total_size;
+
+		/* Go over the list of services, and look for a service which
+		 * doesn't have this UUID
+		 */
+		for (rec_idx = 0U; rec_idx < num_services; rec_idx++) {
+			record = matching_recs[rec_idx];
+
+			if (!record) {
+				continue;
+			}
+
+			found = false;
+
+			/* Search for the UUID in all the attrs of the svc */
+			for (att_idx = 0U; att_idx < record->attr_count;
+			     att_idx++) {
+				search_uuid(&record->attrs[att_idx].val,
+					    &u.uuid, &found, 1);
+				if (found) {
+					break;
+				}
+			}
+
+			/* Remove the record from the list if it doesn't have
+			 * the UUID
+			 */
+			if (!found) {
+				matching_recs[rec_idx] = NULL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* @brief Handler for Service Search Request
+ *
+ * Parses, processes and responds to a Service Search Request
+ *
+ * @param sdp Pointer to the SDP structure
+ * @param buf Request net buf
+ * @param tid Transaction ID
+ *
+ * @return 0 for success, or relevant error code
+ */
+static uint16_t sdp_svc_search_req(struct bt_sdp *sdp, struct net_buf *buf,
+				uint16_t tid)
+{
+	struct bt_sdp_svc_rsp *rsp;
+	struct net_buf *resp_buf;
+	struct bt_sdp_record *record;
+	struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
+	uint16_t max_rec_count, total_recs = 0U, current_recs = 0U, res;
+	uint8_t cont_state_size, cont_state = 0U, idx = 0U, count = 0U;
+	bool pkt_full = false;
+
+	res = find_services(buf, matching_recs);
+	if (res) {
+		/* Error in parsing */
+		return res;
+	}
+
+	if (buf->len < 3) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	max_rec_count = net_buf_pull_be16(buf);
+	cont_state_size = net_buf_pull_u8(buf);
+
+	/* Zero out the matching services beyond max_rec_count */
+	for (idx = 0U; idx < num_services; idx++) {
+		if (count == max_rec_count) {
+			matching_recs[idx] = NULL;
+			continue;
+		}
+
+		if (matching_recs[idx]) {
+			count++;
+		}
+	}
+
+	/* We send out only SDP_SS_CONT_STATE_SIZE bytes continuation state in
+	 * responses, so expect only SDP_SS_CONT_STATE_SIZE bytes in requests
+	 */
+	if (cont_state_size) {
+		if (cont_state_size != SDP_SS_CONT_STATE_SIZE) {
+			BT_WARN("Invalid cont state size %u", cont_state_size);
+			return BT_SDP_INVALID_CSTATE;
+		}
+
+		if (buf->len < cont_state_size) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		cont_state = net_buf_pull_u8(buf);
+		/* We include total_recs in the continuation state. We calculate
+		 * it once and preserve it across all the partial responses
+		 */
+		total_recs = net_buf_pull_be16(buf);
+	}
+
+	BT_DBG("max_rec_count %u, cont_state %u", max_rec_count, cont_state);
+
+	resp_buf = bt_sdp_create_pdu();
+	rsp = net_buf_add(resp_buf, sizeof(*rsp));
+
+	for (; cont_state < num_services; cont_state++) {
+		record = matching_recs[cont_state];
+
+		if (!record) {
+			continue;
+		}
+
+		/* Calculate total recs only if it is first packet */
+		if (!cont_state_size) {
+			total_recs++;
+		}
+
+		if (pkt_full) {
+			continue;
+		}
+
+		/* 4 bytes per Service Record Handle */
+		/* 4 bytes for ContinuationState */
+		if ((MIN(SDP_MTU, sdp->chan.tx.mtu) - resp_buf->len) <
+		    (4 + 4 + sizeof(struct bt_sdp_hdr))) {
+			pkt_full = true;
+		}
+
+		if (pkt_full) {
+			/* Packet exhausted: Add continuation state and break */
+			BT_DBG("Packet full, num_services_covered %u",
+			       cont_state);
+			net_buf_add_u8(resp_buf, SDP_SS_CONT_STATE_SIZE);
+			net_buf_add_u8(resp_buf, cont_state);
+
+			/* If it is the first packet of a partial response,
+			 * continue dry-running to calculate total_recs.
+			 * Else break
+			 */
+			if (cont_state_size) {
+				break;
+			}
+
+			continue;
+		}
+
+		/* Add the service record handle to the packet */
+		net_buf_add_be32(resp_buf, record->handle);
+		current_recs++;
+	}
+
+	/* Add 0 continuation state if packet is exhausted */
+	if (!pkt_full) {
+		net_buf_add_u8(resp_buf, 0);
+	} else {
+		net_buf_add_be16(resp_buf, total_recs);
+	}
+
+	rsp->total_recs = sys_cpu_to_be16(total_recs);
+	rsp->current_recs = sys_cpu_to_be16(current_recs);
+
+	BT_DBG("Sending response, len %u", resp_buf->len);
+	bt_sdp_send(&sdp->chan.chan, resp_buf, BT_SDP_SVC_SEARCH_RSP, tid);
+
+	return 0;
+}
+
+/* @brief Copies an attribute into an outgoing buffer
+ *
+ *  Copies an attribute into a buffer. Recursively calls itself for complex
+ *  attributes.
+ *
+ *  @param elem Attribute to be copied to the buffer
+ *  @param buf Buffer where the attribute is to be copied
+ *
+ *  @return Size of the last data element that has been searched
+ *  (used in recursion)
+ */
+static uint32_t copy_attribute(struct bt_sdp_data_elem *elem,
+			    struct net_buf *buf, uint8_t nest_level)
+{
+	const uint8_t *cur_elem;
+	uint32_t size, seq_size, total_size;
+
+	/* Limit recursion depth to avoid stack overflows */
+	if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
+		return 0;
+	}
+
+	seq_size = elem->data_size;
+	total_size = elem->total_size;
+	cur_elem = elem->data;
+
+	/* Copy the header */
+	net_buf_add_u8(buf, elem->type);
+
+	switch (total_size - (seq_size + 1U)) {
+	case 1:
+		net_buf_add_u8(buf, elem->data_size);
+		break;
+	case 2:
+		net_buf_add_be16(buf, elem->data_size);
+		break;
+	case 4:
+		net_buf_add_be32(buf, elem->data_size);
+		break;
+	}
+
+	/* Recursively parse (till the last element is not another data element)
+	 * and then fill the elements
+	 */
+	if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
+	    (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
+		do {
+			size = copy_attribute((struct bt_sdp_data_elem *)
+					      cur_elem, buf, nest_level + 1);
+			cur_elem += sizeof(struct bt_sdp_data_elem);
+			seq_size -= size;
+		} while (seq_size);
+	} else if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UINT8 ||
+		   (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_INT8 ||
+		   (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
+		if (seq_size == 1U) {
+			net_buf_add_u8(buf, *((uint8_t *)elem->data));
+		} else if (seq_size == 2U) {
+			net_buf_add_be16(buf, *((uint16_t *)elem->data));
+		} else if (seq_size == 4U) {
+			net_buf_add_be32(buf, *((uint32_t *)elem->data));
+		} else {
+			/* TODO: Convert 32bit and 128bit values to big-endian*/
+			net_buf_add_mem(buf, elem->data, seq_size);
+		}
+	} else {
+		net_buf_add_mem(buf, elem->data, seq_size);
+	}
+
+	return total_size;
+}
+
+/* @brief SDP attribute iterator.
+ *
+ *  Iterate over attributes of a service record from a starting index.
+ *
+ *  @param record Service record whose attributes are to be iterated over.
+ *  @param idx Index in the attribute list from where to start.
+ *  @param func Callback function.
+ *  @param user_data Data to pass to the callback.
+ *
+ *  @return Index of the attribute where the iterator stopped
+ */
+static uint8_t bt_sdp_foreach_attr(struct bt_sdp_record *record, uint8_t idx,
+				bt_sdp_attr_func_t func, void *user_data)
+{
+	for (; idx < record->attr_count; idx++) {
+		if (func(&record->attrs[idx], idx, user_data) ==
+		    BT_SDP_ITER_STOP) {
+			break;
+		}
+	}
+
+	return idx;
+}
+
+/* @brief Check if an attribute matches a range, and include it in the response
+ *
+ *  Checks if an attribute matches a given attribute ID or range, and if so,
+ *  includes it in the response packet
+ *
+ *  @param attr The current attribute
+ *  @param att_idx Index of the current attribute in the database
+ *  @param user_data Pointer to the structure containing response packet, byte
+ *   count, states, etc
+ *
+ *  @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
+ *   or BT_SDP_ITER_STOP to stop.
+ */
+static uint8_t select_attrs(struct bt_sdp_attribute *attr, uint8_t att_idx,
+			 void *user_data)
+{
+	struct select_attrs_data *sad = user_data;
+	uint16_t att_id_lower, att_id_upper, att_id_cur, space;
+	uint32_t attr_size, seq_size;
+	uint8_t idx_filter;
+
+	for (idx_filter = 0U; idx_filter < sad->num_filters; idx_filter++) {
+
+		att_id_lower = (sad->filter[idx_filter] >> 16);
+		att_id_upper = (sad->filter[idx_filter]);
+		att_id_cur = attr->id;
+
+		/* Check for range values */
+		if (att_id_lower != 0xffff &&
+		    (!IN_RANGE(att_id_cur, att_id_lower, att_id_upper))) {
+			continue;
+		}
+
+		/* Check for match values */
+		if (att_id_lower == 0xffff && att_id_cur != att_id_upper) {
+			continue;
+		}
+
+		/* Attribute ID matches */
+
+		/* 3 bytes for Attribute ID */
+		attr_size = 3 + attr->val.total_size;
+
+		/* If this is the first attribute of the service, then we need
+		 * to account for the space required to add the per-service
+		 * data element sequence header as well.
+		 */
+		if ((sad->state->current_svc != sad->rec->index) &&
+		    sad->new_service) {
+			/* 3 bytes for Per-Service Data Elem Seq declaration */
+			seq_size = attr_size + 3;
+		} else {
+			seq_size = attr_size;
+		}
+
+		if (sad->rsp_buf) {
+			space = MIN(SDP_MTU, sad->sdp->chan.tx.mtu) -
+				sad->rsp_buf->len - sizeof(struct bt_sdp_hdr);
+
+			if ((!sad->state->pkt_full) &&
+			    ((seq_size > sad->max_att_len) ||
+			     (space < seq_size + sad->cont_state_size))) {
+				/* Packet exhausted */
+				sad->state->pkt_full = true;
+			}
+		}
+
+		/* Keep filling data only if packet is not exhausted */
+		if (!sad->state->pkt_full && sad->rsp_buf) {
+			/* Add Per-Service Data Element Seq declaration once
+			 * only when we are starting from the first attribute
+			 */
+			if (!sad->seq &&
+			    (sad->state->current_svc != sad->rec->index)) {
+				sad->seq = net_buf_add(sad->rsp_buf,
+						       sizeof(*sad->seq));
+				sad->seq->type = BT_SDP_SEQ16;
+				sad->seq->size = 0U;
+			}
+
+			/* Add attribute ID */
+			net_buf_add_u8(sad->rsp_buf, BT_SDP_UINT16);
+			net_buf_add_be16(sad->rsp_buf, att_id_cur);
+
+			/* Add attribute value */
+			copy_attribute(&attr->val, sad->rsp_buf, 1);
+
+			sad->max_att_len -= seq_size;
+			sad->att_list_len += seq_size;
+			sad->state->last_att = att_idx;
+			sad->state->current_svc = sad->rec->index;
+		}
+
+		if (sad->seq) {
+			/* Keep adding the sequence size if this packet contains
+			 * the Per-Service Data Element Seq declaration header
+			 */
+			sad->seq->size += attr_size;
+			sad->state->att_list_size += seq_size;
+		} else {
+			/* Keep adding the total attr lists size if:
+			 * It's a dry-run, calculating the total attr lists size
+			 */
+			sad->state->att_list_size += seq_size;
+		}
+
+		sad->new_service = false;
+		break;
+	}
+
+	/* End the search if:
+	 * 1. We have exhausted the packet
+	 * AND
+	 * 2. This packet doesn't contain the service element declaration header
+	 * AND
+	 * 3. This is not a dry-run (then we look for other attrs that match)
+	 */
+	if (sad->state->pkt_full && !sad->seq && sad->rsp_buf) {
+		return BT_SDP_ITER_STOP;
+	}
+
+	return BT_SDP_ITER_CONTINUE;
+}
+
+/* @brief Creates attribute list in the given buffer
+ *
+ *  Populates the attribute list of a service record in the buffer. To be used
+ *  for responding to Service Attribute and Service Search Attribute requests
+ *
+ *  @param sdp Pointer to the SDP structure
+ *  @param record Service record whose attributes are to be included in the
+ *   response
+ *  @param filter Attribute values/ranges to be used as a filter
+ *  @param num_filters Number of elements in the attribute filter
+ *  @param max_att_len Maximum size of attributes to be included in the response
+ *  @param cont_state_size No. of additional continuation state bytes to keep
+ *   space for in the packet. This will vary based on the type of the request
+ *  @param next_att Starting position of the search in the service's attr list
+ *  @param state State of the overall search
+ *  @param rsp_buf Response buffer which is filled in
+ *
+ *  @return len Length of the attribute list created
+ */
+static uint16_t create_attr_list(struct bt_sdp *sdp, struct bt_sdp_record *record,
+			      uint32_t *filter, uint8_t num_filters,
+			      uint16_t max_att_len, uint8_t cont_state_size,
+			      uint8_t next_att, struct search_state *state,
+			      struct net_buf *rsp_buf)
+{
+	struct select_attrs_data sad;
+	uint8_t idx_att;
+
+	sad.num_filters = num_filters;
+	sad.rec = record;
+	sad.rsp_buf = rsp_buf;
+	sad.sdp = sdp;
+	sad.max_att_len = max_att_len;
+	sad.cont_state_size = cont_state_size;
+	sad.seq = NULL;
+	sad.filter = filter;
+	sad.state = state;
+	sad.att_list_len = 0U;
+	sad.new_service = true;
+
+	idx_att = bt_sdp_foreach_attr(sad.rec, next_att, select_attrs, &sad);
+
+	if (sad.seq) {
+		sad.seq->size = sys_cpu_to_be16(sad.seq->size);
+	}
+
+	return sad.att_list_len;
+}
+
+/* @brief Extracts the attribute search list from a buffer
+ *
+ *  Parses a buffer to extract the attribute search list (list of attribute IDs
+ *  and ranges) which are to be used to filter attributes.
+ *
+ *  @param buf Buffer to be parsed for extracting the attribute search list
+ *  @param filter Empty list of 4byte filters that are filled in. For attribute
+ *   IDs, the lower 2 bytes contain the ID and the upper 2 bytes are set to
+ *   0xFFFF. For attribute ranges, the lower 2bytes indicate the start ID and
+ *   the upper 2bytes indicate the end ID
+ *  @param num_filters No. of filter elements filled in (to be returned)
+ *
+ *  @return 0 for success, or relevant error code
+ */
+static uint16_t get_att_search_list(struct net_buf *buf, uint32_t *filter,
+				 uint8_t *num_filters)
+{
+	struct bt_sdp_data_elem data_elem;
+	uint16_t res;
+	uint32_t size;
+
+	*num_filters = 0U;
+	res = parse_data_elem(buf, &data_elem);
+	if (res) {
+		return res;
+	}
+
+	size = data_elem.data_size;
+
+	while (size) {
+		res = parse_data_elem(buf, &data_elem);
+		if (res) {
+			return res;
+		}
+
+		if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_UINT8) {
+			BT_WARN("Invalid type %u in attribute ID list",
+				data_elem.type);
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		if (buf->len < data_elem.data_size) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		/* This is an attribute ID */
+		if (data_elem.data_size == 2U) {
+			filter[(*num_filters)++] = 0xffff0000 |
+							net_buf_pull_be16(buf);
+		}
+
+		/* This is an attribute ID range */
+		if (data_elem.data_size == 4U) {
+			filter[(*num_filters)++] = net_buf_pull_be32(buf);
+		}
+
+		size -= data_elem.total_size;
+	}
+
+	return 0;
+}
+
+/* @brief Check if a given handle matches that of the current service
+ *
+ *  Checks if a given handle matches that of the current service
+ *
+ *  @param rec The current service record
+ *  @param user_data Pointer to the service record handle to be matched
+ *
+ *  @return BT_SDP_ITER_CONTINUE if should continue to the next record
+ *   or BT_SDP_ITER_STOP to stop.
+ */
+static uint8_t find_handle(struct bt_sdp_record *rec, void *user_data)
+{
+	uint32_t *svc_rec_hdl = user_data;
+
+	if (rec->handle == *svc_rec_hdl) {
+		return BT_SDP_ITER_STOP;
+	}
+
+	return BT_SDP_ITER_CONTINUE;
+}
+
+/* @brief Handler for Service Attribute Request
+ *
+ *  Parses, processes and responds to a Service Attribute Request
+ *
+ *  @param sdp Pointer to the SDP structure
+ *  @param buf Request buffer
+ *  @param tid Transaction ID
+ *
+ *  @return 0 for success, or relevant error code
+ */
+static uint16_t sdp_svc_att_req(struct bt_sdp *sdp, struct net_buf *buf,
+			     uint16_t tid)
+{
+	uint32_t filter[MAX_NUM_ATT_ID_FILTER];
+	struct search_state state = {
+		.current_svc = SDP_INVALID,
+		.last_att = SDP_INVALID,
+		.pkt_full = false
+	};
+	struct bt_sdp_record *record;
+	struct bt_sdp_att_rsp *rsp;
+	struct net_buf *rsp_buf;
+	uint32_t svc_rec_hdl;
+	uint16_t max_att_len, res, att_list_len;
+	uint8_t num_filters, cont_state_size, next_att = 0U;
+
+	if (buf->len < 6) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	svc_rec_hdl = net_buf_pull_be32(buf);
+	max_att_len = net_buf_pull_be16(buf);
+
+	/* Set up the filters */
+	res = get_att_search_list(buf, filter, &num_filters);
+	if (res) {
+		/* Error in parsing */
+		return res;
+	}
+
+	if (buf->len < 1) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	cont_state_size = net_buf_pull_u8(buf);
+
+	/* We only send out 1 byte continuation state in responses,
+	 * so expect only 1 byte in requests
+	 */
+	if (cont_state_size) {
+		if (cont_state_size != SDP_SA_CONT_STATE_SIZE) {
+			BT_WARN("Invalid cont state size %u", cont_state_size);
+			return BT_SDP_INVALID_CSTATE;
+		}
+
+		if (buf->len < cont_state_size) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		state.last_att = net_buf_pull_u8(buf) + 1;
+		next_att = state.last_att;
+	}
+
+	BT_DBG("svc_rec_hdl %u, max_att_len 0x%04x, cont_state %u", svc_rec_hdl,
+	       max_att_len, next_att);
+
+	/* Find the service */
+	record = bt_sdp_foreach_svc(find_handle, &svc_rec_hdl);
+
+	if (!record) {
+		BT_WARN("Handle %u not found", svc_rec_hdl);
+		return BT_SDP_INVALID_RECORD_HANDLE;
+	}
+
+	/* For partial responses, restore the search state */
+	if (cont_state_size) {
+		state.current_svc = record->index;
+	}
+
+	rsp_buf = bt_sdp_create_pdu();
+	rsp = net_buf_add(rsp_buf, sizeof(*rsp));
+
+	/* cont_state_size should include 1 byte header */
+	att_list_len = create_attr_list(sdp, record, filter, num_filters,
+					max_att_len, SDP_SA_CONT_STATE_SIZE + 1,
+					next_att, &state, rsp_buf);
+
+	if (!att_list_len) {
+		/* For empty responses, add an empty data element sequence */
+		net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
+		net_buf_add_u8(rsp_buf, 0);
+		att_list_len = 2U;
+	}
+
+	/* Add continuation state */
+	if (state.pkt_full) {
+		BT_DBG("Packet full, state.last_att %u", state.last_att);
+		net_buf_add_u8(rsp_buf, 1);
+		net_buf_add_u8(rsp_buf, state.last_att);
+	} else {
+		net_buf_add_u8(rsp_buf, 0);
+	}
+
+	rsp->att_list_len = sys_cpu_to_be16(att_list_len);
+
+	BT_DBG("Sending response, len %u", rsp_buf->len);
+	bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_ATTR_RSP, tid);
+
+	return 0;
+}
+
+/* @brief Handler for Service Search Attribute Request
+ *
+ *  Parses, processes and responds to a Service Search Attribute Request
+ *
+ *  @param sdp Pointer to the SDP structure
+ *  @param buf Request buffer
+ *  @param tid Transaction ID
+ *
+ *  @return 0 for success, or relevant error code
+ */
+static uint16_t sdp_svc_search_att_req(struct bt_sdp *sdp, struct net_buf *buf,
+				    uint16_t tid)
+{
+	uint32_t filter[MAX_NUM_ATT_ID_FILTER];
+	struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
+	struct search_state state = {
+		.att_list_size = 0,
+		.current_svc = SDP_INVALID,
+		.last_att = SDP_INVALID,
+		.pkt_full = false
+	};
+	struct net_buf *rsp_buf, *rsp_buf_cpy;
+	struct bt_sdp_record *record;
+	struct bt_sdp_att_rsp *rsp;
+	struct bt_sdp_data_elem_seq *seq = NULL;
+	uint16_t max_att_len, res, att_list_len = 0U;
+	uint8_t num_filters, cont_state_size, next_svc = 0U, next_att = 0U;
+	bool dry_run = false;
+
+	res = find_services(buf, matching_recs);
+	if (res) {
+		return res;
+	}
+
+	if (buf->len < 2) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	max_att_len = net_buf_pull_be16(buf);
+
+	/* Set up the filters */
+	res = get_att_search_list(buf, filter, &num_filters);
+
+	if (res) {
+		/* Error in parsing */
+		return res;
+	}
+
+	if (buf->len < 1) {
+		BT_WARN("Malformed packet");
+		return BT_SDP_INVALID_SYNTAX;
+	}
+
+	cont_state_size = net_buf_pull_u8(buf);
+
+	/* We only send out 2 bytes continuation state in responses,
+	 * so expect only 2 bytes in requests
+	 */
+	if (cont_state_size) {
+		if (cont_state_size != SDP_SSA_CONT_STATE_SIZE) {
+			BT_WARN("Invalid cont state size %u", cont_state_size);
+			return BT_SDP_INVALID_CSTATE;
+		}
+
+		if (buf->len < cont_state_size) {
+			BT_WARN("Malformed packet");
+			return BT_SDP_INVALID_SYNTAX;
+		}
+
+		state.current_svc = net_buf_pull_u8(buf);
+		state.last_att = net_buf_pull_u8(buf) + 1;
+		next_svc = state.current_svc;
+		next_att = state.last_att;
+	}
+
+	BT_DBG("max_att_len 0x%04x, state.current_svc %u, state.last_att %u",
+	       max_att_len, state.current_svc, state.last_att);
+
+	rsp_buf = bt_sdp_create_pdu();
+
+	rsp = net_buf_add(rsp_buf, sizeof(*rsp));
+
+	/* Add headers only if this is not a partial response */
+	if (!cont_state_size) {
+		seq = net_buf_add(rsp_buf, sizeof(*seq));
+		seq->type = BT_SDP_SEQ16;
+		seq->size = 0U;
+
+		/* 3 bytes for Outer Data Element Sequence declaration */
+		att_list_len = 3U;
+	}
+
+	rsp_buf_cpy = rsp_buf;
+
+	for (; next_svc < num_services; next_svc++) {
+		record = matching_recs[next_svc];
+
+		if (!record) {
+			continue;
+		}
+
+		att_list_len += create_attr_list(sdp, record, filter,
+						 num_filters, max_att_len,
+						 SDP_SSA_CONT_STATE_SIZE + 1,
+						 next_att, &state, rsp_buf_cpy);
+
+		/* Check if packet is full and not dry run */
+		if (state.pkt_full && !dry_run) {
+			BT_DBG("Packet full, state.last_att %u",
+			       state.last_att);
+			dry_run = true;
+
+			/* Add continuation state */
+			net_buf_add_u8(rsp_buf, 2);
+			net_buf_add_u8(rsp_buf, state.current_svc);
+			net_buf_add_u8(rsp_buf, state.last_att);
+
+			/* Break if it's not a partial response, else dry-run
+			 * Dry run: Look for other services that match
+			 */
+			if (cont_state_size) {
+				break;
+			}
+
+			rsp_buf_cpy = NULL;
+		}
+
+		next_att = 0U;
+	}
+
+	if (!dry_run) {
+		if (!att_list_len) {
+			/* For empty responses, add an empty data elem seq */
+			net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
+			net_buf_add_u8(rsp_buf, 0);
+			att_list_len = 2U;
+		}
+		/* Search exhausted */
+		net_buf_add_u8(rsp_buf, 0);
+	}
+
+	rsp->att_list_len = sys_cpu_to_be16(att_list_len);
+	if (seq) {
+		seq->size = sys_cpu_to_be16(state.att_list_size);
+	}
+
+	BT_DBG("Sending response, len %u", rsp_buf->len);
+	bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_SEARCH_ATTR_RSP,
+		    tid);
+
+	return 0;
+}
+
+static const struct {
+	uint8_t  op_code;
+	uint16_t  (*func)(struct bt_sdp *sdp, struct net_buf *buf, uint16_t tid);
+} handlers[] = {
+	{ BT_SDP_SVC_SEARCH_REQ, sdp_svc_search_req },
+	{ BT_SDP_SVC_ATTR_REQ, sdp_svc_att_req },
+	{ BT_SDP_SVC_SEARCH_ATTR_REQ, sdp_svc_search_att_req },
+};
+
+/* @brief Callback for SDP data receive
+ *
+ *  Gets called when an SDP PDU is received. Calls the corresponding handler
+ *  based on the op code of the PDU.
+ *
+ *  @param chan L2CAP channel
+ *  @param buf Received PDU
+ *
+ *  @return None
+ */
+static int bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
+			struct bt_l2cap_br_chan, chan);
+	struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
+	struct bt_sdp_hdr *hdr;
+	uint16_t err = BT_SDP_INVALID_SYNTAX;
+	size_t i;
+
+	BT_DBG("chan %p, ch %p, cid 0x%04x", chan, ch, ch->tx.cid);
+
+	BT_ASSERT(sdp);
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small SDP PDU received");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	BT_DBG("Received SDP code 0x%02x len %u", hdr->op_code, buf->len);
+
+	if (sys_cpu_to_be16(hdr->param_len) != buf->len) {
+		err = BT_SDP_INVALID_PDU_SIZE;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(handlers); i++) {
+			if (hdr->op_code != handlers[i].op_code) {
+				continue;
+			}
+
+			err = handlers[i].func(sdp, buf, hdr->tid);
+			break;
+		}
+	}
+
+	if (err) {
+		BT_WARN("SDP error 0x%02x", err);
+		send_err_rsp(chan, err, hdr->tid);
+	}
+
+	return 0;
+}
+
+/* @brief Callback for SDP connection accept
+ *
+ *  Gets called when an incoming SDP connection needs to be authorized.
+ *  Registers the L2CAP callbacks and allocates an SDP context to the connection
+ *
+ *  @param conn BT connection object
+ *  @param chan L2CAP channel structure (to be returned)
+ *
+ *  @return 0 for success, or relevant error code
+ */
+static int bt_sdp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = bt_sdp_connected,
+		.disconnected = bt_sdp_disconnected,
+		.recv = bt_sdp_recv,
+	};
+	int i;
+
+	BT_DBG("conn %p", conn);
+
+	for (i = 0; i < ARRAY_SIZE(bt_sdp_pool); i++) {
+		struct bt_sdp *sdp = &bt_sdp_pool[i];
+
+		if (sdp->chan.chan.conn) {
+			continue;
+		}
+
+		sdp->chan.chan.ops = &ops;
+		sdp->chan.rx.mtu = SDP_MTU;
+
+		*chan = &sdp->chan.chan;
+
+		return 0;
+	}
+
+	BT_ERR("No available SDP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+void bt_sdp_init(void)
+{
+	static struct bt_l2cap_server server = {
+		.psm = SDP_PSM,
+		.accept = bt_sdp_accept,
+		.sec_level = BT_SECURITY_L0,
+	};
+	int res;
+
+	res = bt_l2cap_br_server_register(&server);
+	if (res) {
+		BT_ERR("L2CAP server registration failed with error %d", res);
+	}
+}
+
+int bt_sdp_register_service(struct bt_sdp_record *service)
+{
+	uint32_t handle = SDP_SERVICE_HANDLE_BASE;
+
+	if (!service) {
+		BT_ERR("No service record specified");
+		return 0;
+	}
+
+	if (num_services == BT_SDP_MAX_SERVICES) {
+		BT_ERR("Reached max allowed registrations");
+		return -ENOMEM;
+	}
+
+	if (db) {
+		handle = db->handle + 1;
+	}
+
+	service->next = db;
+	service->index = num_services++;
+	service->handle = handle;
+	*((uint32_t *)(service->attrs[0].val.data)) = handle;
+	db = service;
+
+	BT_DBG("Service registered at %u", handle);
+
+	return 0;
+}
+
+#define GET_PARAM(__node) \
+	CONTAINER_OF(__node, struct bt_sdp_discover_params, _node)
+
+/* ServiceSearchAttribute PDU, ref to BT Core 4.2, Vol 3, part B, 4.7.1 */
+static int sdp_client_ssa_search(struct bt_sdp_client *session)
+{
+	const struct bt_sdp_discover_params *param;
+	struct bt_sdp_hdr *hdr;
+	struct net_buf *buf;
+
+	/*
+	 * Select proper user params, if session->param is invalid it means
+	 * getting new UUID from top of to be resolved params list. Otherwise
+	 * the context is in a middle of partial SDP PDU responses and cached
+	 * value from context can be used.
+	 */
+	if (!session->param) {
+		param = GET_PARAM(sys_slist_peek_head(&session->reqs));
+	} else {
+		param = session->param;
+	}
+
+	if (!param) {
+		BT_WARN("No UUIDs to be resolved on remote");
+		return -EINVAL;
+	}
+
+	buf = bt_l2cap_create_pdu(&sdp_pool, 0);
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+
+	hdr->op_code = BT_SDP_SVC_SEARCH_ATTR_REQ;
+	/* BT_SDP_SEQ8 means length of sequence is on additional next byte */
+	net_buf_add_u8(buf, BT_SDP_SEQ8);
+
+	switch (param->uuid->type) {
+	case BT_UUID_TYPE_16:
+		/* Seq length */
+		net_buf_add_u8(buf, 0x03);
+		/* Seq type */
+		net_buf_add_u8(buf, BT_SDP_UUID16);
+		/* Seq value */
+		net_buf_add_be16(buf, BT_UUID_16(param->uuid)->val);
+		break;
+	case BT_UUID_TYPE_32:
+		net_buf_add_u8(buf, 0x05);
+		net_buf_add_u8(buf, BT_SDP_UUID32);
+		net_buf_add_be32(buf, BT_UUID_32(param->uuid)->val);
+		break;
+	case BT_UUID_TYPE_128:
+		net_buf_add_u8(buf, 0x11);
+		net_buf_add_u8(buf, BT_SDP_UUID128);
+		net_buf_add_mem(buf, BT_UUID_128(param->uuid)->val,
+				ARRAY_SIZE(BT_UUID_128(param->uuid)->val));
+		break;
+	default:
+		BT_ERR("Unknown UUID type %u", param->uuid->type);
+		return -EINVAL;
+	}
+
+	/* Set attribute max bytes count to be returned from server */
+	net_buf_add_be16(buf, BT_SDP_MAX_ATTR_LEN);
+	/*
+	 * Sequence definition where data is sequence of elements and where
+	 * additional next byte points the size of elements within
+	 */
+	net_buf_add_u8(buf, BT_SDP_SEQ8);
+	net_buf_add_u8(buf, 0x05);
+	/* Data element definition for two following 16bits range elements */
+	net_buf_add_u8(buf, BT_SDP_UINT32);
+	/* Get all attributes. It enables filter out wanted only attributes */
+	net_buf_add_be16(buf, 0x0000);
+	net_buf_add_be16(buf, 0xffff);
+
+	/*
+	 * Update and validate PDU ContinuationState. Initial SSA Request has
+	 * zero length continuation state since no interaction has place with
+	 * server so far, otherwise use the original state taken from remote's
+	 * last response PDU that is cached by SDP client context.
+	 */
+	if (session->cstate.length == 0U) {
+		net_buf_add_u8(buf, 0x00);
+	} else {
+		net_buf_add_u8(buf, session->cstate.length);
+		net_buf_add_mem(buf, session->cstate.data,
+				session->cstate.length);
+	}
+
+	/* set overall PDU length */
+	hdr->param_len = sys_cpu_to_be16(buf->len - sizeof(*hdr));
+
+	/* Update context param to the one being resolving now */
+	session->param = param;
+	session->tid++;
+	hdr->tid = sys_cpu_to_be16(session->tid);
+
+	return bt_l2cap_chan_send(&session->chan.chan, buf);
+}
+
+static void sdp_client_params_iterator(struct bt_sdp_client *session)
+{
+	struct bt_l2cap_chan *chan = &session->chan.chan;
+	struct bt_sdp_discover_params *param, *tmp;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&session->reqs, param, tmp, _node) {
+		if (param != session->param) {
+			continue;
+		}
+
+		BT_DBG("");
+
+		/* Remove already checked UUID node */
+		sys_slist_remove(&session->reqs, NULL, &param->_node);
+		/* Invalidate cached param in context */
+		session->param = NULL;
+		/* Reset continuation state in current context */
+		(void)memset(&session->cstate, 0, sizeof(session->cstate));
+
+		/* Check if there's valid next UUID */
+		if (!sys_slist_is_empty(&session->reqs)) {
+			sdp_client_ssa_search(session);
+			return;
+		}
+
+		/* No UUID items, disconnect channel */
+		bt_l2cap_chan_disconnect(chan);
+		break;
+	}
+}
+
+static uint16_t sdp_client_get_total(struct bt_sdp_client *session,
+				  struct net_buf *buf, uint16_t *total)
+{
+	uint16_t pulled;
+	uint8_t seq;
+
+	/*
+	 * Pull value of total octets of all attributes available to be
+	 * collected when response gets completed for given UUID. Such info can
+	 * be get from the very first response frame after initial SSA request
+	 * was sent. For subsequent calls related to the same SSA request input
+	 * buf and in/out function parameters stays neutral.
+	 */
+	if (session->cstate.length == 0U) {
+		seq = net_buf_pull_u8(buf);
+		pulled = 1U;
+		switch (seq) {
+		case BT_SDP_SEQ8:
+			*total = net_buf_pull_u8(buf);
+			pulled += 1U;
+			break;
+		case BT_SDP_SEQ16:
+			*total = net_buf_pull_be16(buf);
+			pulled += 2U;
+			break;
+		default:
+			BT_WARN("Sequence type 0x%02x not handled", seq);
+			*total = 0U;
+			break;
+		}
+
+		BT_DBG("Total %u octets of all attributes", *total);
+	} else {
+		pulled = 0U;
+		*total = 0U;
+	}
+
+	return pulled;
+}
+
+static uint16_t get_record_len(struct net_buf *buf)
+{
+	uint16_t len;
+	uint8_t seq;
+
+	seq = net_buf_pull_u8(buf);
+
+	switch (seq) {
+	case BT_SDP_SEQ8:
+		len = net_buf_pull_u8(buf);
+		break;
+	case BT_SDP_SEQ16:
+		len = net_buf_pull_be16(buf);
+		break;
+	default:
+		BT_WARN("Sequence type 0x%02x not handled", seq);
+		len = 0U;
+		break;
+	}
+
+	BT_DBG("Record len %u", len);
+
+	return len;
+}
+
+enum uuid_state {
+	UUID_NOT_RESOLVED,
+	UUID_RESOLVED,
+};
+
+static void sdp_client_notify_result(struct bt_sdp_client *session,
+				     enum uuid_state state)
+{
+	struct bt_conn *conn = session->chan.chan.conn;
+	struct bt_sdp_client_result result;
+	uint16_t rec_len;
+	uint8_t user_ret;
+
+	result.uuid = session->param->uuid;
+
+	if (state == UUID_NOT_RESOLVED) {
+		result.resp_buf = NULL;
+		result.next_record_hint = false;
+		session->param->func(conn, &result);
+		return;
+	}
+
+	while (session->rec_buf->len) {
+		struct net_buf_simple_state buf_state;
+
+		rec_len = get_record_len(session->rec_buf);
+		/* tell the user about multi record resolution */
+		if (session->rec_buf->len > rec_len) {
+			result.next_record_hint = true;
+		} else {
+			result.next_record_hint = false;
+		}
+
+		/* save the original session buffer */
+		net_buf_simple_save(&session->rec_buf->b, &buf_state);
+		/* initialize internal result buffer instead of memcpy */
+		result.resp_buf = session->rec_buf;
+		/*
+		 * Set user internal result buffer length as same as record
+		 * length to fake user. User will see the individual record
+		 * length as rec_len insted of whole session rec_buf length.
+		 */
+		result.resp_buf->len = rec_len;
+
+		user_ret = session->param->func(conn, &result);
+
+		/* restore original session buffer */
+		net_buf_simple_restore(&session->rec_buf->b, &buf_state);
+		/*
+		 * sync session buffer data length with next record chunk not
+		 * send to user so far
+		 */
+		net_buf_pull(session->rec_buf, rec_len);
+		if (user_ret == BT_SDP_DISCOVER_UUID_STOP) {
+			break;
+		}
+	}
+}
+
+static int sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
+	struct bt_sdp_hdr *hdr;
+	struct bt_sdp_pdu_cstate *cstate;
+	uint16_t len, tid, frame_len;
+	uint16_t total;
+
+	BT_DBG("session %p buf %p", session, buf);
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small SDP PDU");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	if (hdr->op_code == BT_SDP_ERROR_RSP) {
+		BT_INFO("Error SDP PDU response");
+		return 0;
+	}
+
+	len = sys_be16_to_cpu(hdr->param_len);
+	tid = sys_be16_to_cpu(hdr->tid);
+
+	BT_DBG("SDP PDU tid %u len %u", tid, len);
+
+	if (buf->len != len) {
+		BT_ERR("SDP PDU length mismatch (%u != %u)", buf->len, len);
+		return 0;
+	}
+
+	if (tid != session->tid) {
+		BT_ERR("Mismatch transaction ID value in SDP PDU");
+		return 0;
+	}
+
+	switch (hdr->op_code) {
+	case BT_SDP_SVC_SEARCH_ATTR_RSP:
+		/* Get number of attributes in this frame. */
+		frame_len = net_buf_pull_be16(buf);
+		/* Check valid buf len for attribute list and cont state */
+		if (buf->len < frame_len + SDP_CONT_STATE_LEN_SIZE) {
+			BT_ERR("Invalid frame payload length");
+			return 0;
+		}
+		/* Check valid range of attributes length */
+		if (frame_len < 2) {
+			BT_ERR("Invalid attributes data length");
+			return 0;
+		}
+
+		/* Get PDU continuation state */
+		cstate = (struct bt_sdp_pdu_cstate *)(buf->data + frame_len);
+
+		if (cstate->length > BT_SDP_MAX_PDU_CSTATE_LEN) {
+			BT_ERR("Invalid SDP PDU Continuation State length %u",
+			       cstate->length);
+			return 0;
+		}
+
+		if ((frame_len + SDP_CONT_STATE_LEN_SIZE + cstate->length) >
+		     buf->len) {
+			BT_ERR("Invalid frame payload length");
+			return 0;
+		}
+
+		/*
+		 * No record found for given UUID. The check catches case when
+		 * current response frame has Continuation State shortest and
+		 * valid and this is the first response frame as well.
+		 */
+		if (frame_len == 2U && cstate->length == 0U &&
+		    session->cstate.length == 0U) {
+			BT_DBG("record for UUID 0x%s not found",
+				bt_uuid_str(session->param->uuid));
+			/* Call user UUID handler */
+			sdp_client_notify_result(session, UUID_NOT_RESOLVED);
+			net_buf_pull(buf, frame_len + sizeof(cstate->length));
+			goto iterate;
+		}
+
+		/* Get total value of all attributes to be collected */
+		frame_len -= sdp_client_get_total(session, buf, &total);
+
+		if (total > net_buf_tailroom(session->rec_buf)) {
+			BT_WARN("Not enough room for getting records data");
+			goto iterate;
+		}
+
+		net_buf_add_mem(session->rec_buf, buf->data, frame_len);
+		net_buf_pull(buf, frame_len);
+
+		/*
+		 * check if current response says there's next portion to be
+		 * fetched
+		 */
+		if (cstate->length) {
+			/* Cache original Continuation State in context */
+			memcpy(&session->cstate, cstate,
+			       sizeof(struct bt_sdp_pdu_cstate));
+
+			net_buf_pull(buf, cstate->length +
+				     sizeof(cstate->length));
+
+			/* Request for next portion of attributes data */
+			sdp_client_ssa_search(session);
+			break;
+		}
+
+		net_buf_pull(buf, sizeof(cstate->length));
+
+		BT_DBG("UUID 0x%s resolved", bt_uuid_str(session->param->uuid));
+		sdp_client_notify_result(session, UUID_RESOLVED);
+iterate:
+		/* Get next UUID and start resolving it */
+		sdp_client_params_iterator(session);
+		break;
+	default:
+		BT_DBG("PDU 0x%0x response not handled", hdr->op_code);
+		break;
+	}
+
+	return 0;
+}
+
+static int sdp_client_chan_connect(struct bt_sdp_client *session)
+{
+	return bt_l2cap_br_chan_connect(session->chan.chan.conn,
+					&session->chan.chan, SDP_PSM);
+}
+
+static struct net_buf *sdp_client_alloc_buf(struct bt_l2cap_chan *chan)
+{
+	struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
+	struct net_buf *buf;
+
+	BT_DBG("session %p chan %p", session, chan);
+
+	session->param = GET_PARAM(sys_slist_peek_head(&session->reqs));
+
+	buf = net_buf_alloc(session->param->pool, K_FOREVER);
+	__ASSERT_NO_MSG(buf);
+
+	return buf;
+}
+
+static void sdp_client_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
+
+	BT_DBG("session %p chan %p connected", session, chan);
+
+	session->rec_buf = chan->ops->alloc_buf(chan);
+
+	sdp_client_ssa_search(session);
+}
+
+static void sdp_client_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
+
+	BT_DBG("session %p chan %p disconnected", session, chan);
+
+	net_buf_unref(session->rec_buf);
+
+	/*
+	 * Reset session excluding L2CAP channel member. Let's the channel
+	 * resets autonomous.
+	 */
+	(void)memset(&session->reqs, 0,
+		     sizeof(*session) - sizeof(session->chan));
+}
+
+static const struct bt_l2cap_chan_ops sdp_client_chan_ops = {
+		.connected = sdp_client_connected,
+		.disconnected = sdp_client_disconnected,
+		.recv = sdp_client_receive,
+		.alloc_buf = sdp_client_alloc_buf,
+};
+
+static struct bt_sdp_client *sdp_client_new_session(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
+		struct bt_sdp_client *session = &bt_sdp_client_pool[i];
+		int err;
+
+		if (session->chan.chan.conn) {
+			continue;
+		}
+
+		sys_slist_init(&session->reqs);
+
+		session->chan.chan.ops = &sdp_client_chan_ops;
+		session->chan.chan.conn = conn;
+		session->chan.rx.mtu = SDP_CLIENT_MTU;
+
+		err = sdp_client_chan_connect(session);
+		if (err) {
+			(void)memset(session, 0, sizeof(*session));
+			BT_ERR("Cannot connect %d", err);
+			return NULL;
+		}
+
+		return session;
+	}
+
+	BT_ERR("No available SDP client context");
+
+	return NULL;
+}
+
+static struct bt_sdp_client *sdp_client_get_session(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
+		if (bt_sdp_client_pool[i].chan.chan.conn == conn) {
+			return &bt_sdp_client_pool[i];
+		}
+	}
+
+	/*
+	 * Try to allocate session context since not found in pool and attempt
+	 * connect to remote SDP endpoint.
+	 */
+	return sdp_client_new_session(conn);
+}
+
+int bt_sdp_discover(struct bt_conn *conn,
+		    const struct bt_sdp_discover_params *params)
+{
+	struct bt_sdp_client *session;
+
+	if (!params || !params->uuid || !params->func || !params->pool) {
+		BT_WARN("Invalid user params");
+		return -EINVAL;
+	}
+
+	session = sdp_client_get_session(conn);
+	if (!session) {
+		return -ENOMEM;
+	}
+
+	sys_slist_append(&session->reqs, (sys_snode_t *)&params->_node);
+
+	return 0;
+}
+
+/* Helper getting length of data determined by DTD for integers */
+static inline ssize_t sdp_get_int_len(const uint8_t *data, size_t len)
+{
+	BT_ASSERT(data);
+
+	switch (data[0]) {
+	case BT_SDP_DATA_NIL:
+		return 1;
+	case BT_SDP_BOOL:
+	case BT_SDP_INT8:
+	case BT_SDP_UINT8:
+		if (len < 2) {
+			break;
+		}
+
+		return 2;
+	case BT_SDP_INT16:
+	case BT_SDP_UINT16:
+		if (len < 3) {
+			break;
+		}
+
+		return 3;
+	case BT_SDP_INT32:
+	case BT_SDP_UINT32:
+		if (len < 5) {
+			break;
+		}
+
+		return 5;
+	case BT_SDP_INT64:
+	case BT_SDP_UINT64:
+		if (len < 9) {
+			break;
+		}
+
+		return 9;
+	case BT_SDP_INT128:
+	case BT_SDP_UINT128:
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
+		return -EINVAL;
+	}
+
+	BT_ERR("Too short buffer length %zu", len);
+	return -EMSGSIZE;
+}
+
+/* Helper getting length of data determined by DTD for UUID */
+static inline ssize_t sdp_get_uuid_len(const uint8_t *data, size_t len)
+{
+	BT_ASSERT(data);
+
+	switch (data[0]) {
+	case BT_SDP_UUID16:
+		if (len < 3) {
+			break;
+		}
+
+		return 3;
+	case BT_SDP_UUID32:
+		if (len < 5) {
+			break;
+		}
+
+		return 5;
+	case BT_SDP_UUID128:
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
+		return -EINVAL;
+	}
+
+	BT_ERR("Too short buffer length %zu", len);
+	return -EMSGSIZE;
+}
+
+/* Helper getting length of data determined by DTD for strings */
+static inline ssize_t sdp_get_str_len(const uint8_t *data, size_t len)
+{
+	const uint8_t *pnext;
+
+	BT_ASSERT(data);
+
+	/* validate len for pnext safe use to read next 8bit value */
+	if (len < 2) {
+		goto err;
+	}
+
+	pnext = data + sizeof(uint8_t);
+
+	switch (data[0]) {
+	case BT_SDP_TEXT_STR8:
+	case BT_SDP_URL_STR8:
+		if (len < (2 + pnext[0])) {
+			break;
+		}
+
+		return 2 + pnext[0];
+	case BT_SDP_TEXT_STR16:
+	case BT_SDP_URL_STR16:
+		/* validate len for pnext safe use to read 16bit value */
+		if (len < 3) {
+			break;
+		}
+
+		if (len < (3 + sys_get_be16(pnext))) {
+			break;
+		}
+
+		return 3 + sys_get_be16(pnext);
+	case BT_SDP_TEXT_STR32:
+	case BT_SDP_URL_STR32:
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
+		return -EINVAL;
+	}
+err:
+	BT_ERR("Too short buffer length %zu", len);
+	return -EMSGSIZE;
+}
+
+/* Helper getting length of data determined by DTD for sequences */
+static inline ssize_t sdp_get_seq_len(const uint8_t *data, size_t len)
+{
+	const uint8_t *pnext;
+
+	BT_ASSERT(data);
+
+	/* validate len for pnext safe use to read 8bit bit value */
+	if (len < 2) {
+		goto err;
+	}
+
+	pnext = data + sizeof(uint8_t);
+
+	switch (data[0]) {
+	case BT_SDP_SEQ8:
+	case BT_SDP_ALT8:
+		if (len < (2 + pnext[0])) {
+			break;
+		}
+
+		return 2 + pnext[0];
+	case BT_SDP_SEQ16:
+	case BT_SDP_ALT16:
+		/* validate len for pnext safe use to read 16bit value */
+		if (len < 3) {
+			break;
+		}
+
+		if (len < (3 + sys_get_be16(pnext))) {
+			break;
+		}
+
+		return 3 + sys_get_be16(pnext);
+	case BT_SDP_SEQ32:
+	case BT_SDP_ALT32:
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
+		return -EINVAL;
+	}
+err:
+	BT_ERR("Too short buffer length %zu", len);
+	return -EMSGSIZE;
+}
+
+/* Helper getting length of attribute value data */
+static ssize_t sdp_get_attr_value_len(const uint8_t *data, size_t len)
+{
+	BT_ASSERT(data);
+
+	BT_DBG("Attr val DTD 0x%02x", data[0]);
+
+	switch (data[0]) {
+	case BT_SDP_DATA_NIL:
+	case BT_SDP_BOOL:
+	case BT_SDP_UINT8:
+	case BT_SDP_UINT16:
+	case BT_SDP_UINT32:
+	case BT_SDP_UINT64:
+	case BT_SDP_UINT128:
+	case BT_SDP_INT8:
+	case BT_SDP_INT16:
+	case BT_SDP_INT32:
+	case BT_SDP_INT64:
+	case BT_SDP_INT128:
+		return sdp_get_int_len(data, len);
+	case BT_SDP_UUID16:
+	case BT_SDP_UUID32:
+	case BT_SDP_UUID128:
+		return sdp_get_uuid_len(data, len);
+	case BT_SDP_TEXT_STR8:
+	case BT_SDP_TEXT_STR16:
+	case BT_SDP_TEXT_STR32:
+	case BT_SDP_URL_STR8:
+	case BT_SDP_URL_STR16:
+	case BT_SDP_URL_STR32:
+		return sdp_get_str_len(data, len);
+	case BT_SDP_SEQ8:
+	case BT_SDP_SEQ16:
+	case BT_SDP_SEQ32:
+	case BT_SDP_ALT8:
+	case BT_SDP_ALT16:
+	case BT_SDP_ALT32:
+		return sdp_get_seq_len(data, len);
+	default:
+		BT_ERR("Unknown DTD 0x%02x", data[0]);
+		return -EINVAL;
+	}
+}
+
+/* Type holding UUID item and related to it specific information. */
+struct bt_sdp_uuid_desc {
+	union {
+		struct bt_uuid    uuid;
+		struct bt_uuid_16 uuid16;
+		struct bt_uuid_32 uuid32;
+	      };
+	uint16_t                     attr_id;
+	uint8_t                     *params;
+	uint16_t                     params_len;
+};
+
+/* Generic attribute item collector. */
+struct bt_sdp_attr_item {
+	/*  Attribute identifier. */
+	uint16_t                  attr_id;
+	/*  Address of beginning attribute value taken from original buffer
+	 *  holding response from server.
+	 */
+	uint8_t                  *val;
+	/*  Says about the length of attribute value. */
+	uint16_t                  len;
+};
+
+static int bt_sdp_get_attr(const struct net_buf *buf,
+			   struct bt_sdp_attr_item *attr, uint16_t attr_id)
+{
+	uint8_t *data;
+	uint16_t id;
+
+	data = buf->data;
+	while (data - buf->data < buf->len) {
+		ssize_t dlen;
+
+		/* data need to point to attribute id descriptor field (DTD)*/
+		if (data[0] != BT_SDP_UINT16) {
+			BT_ERR("Invalid descriptor 0x%02x", data[0]);
+			return -EINVAL;
+		}
+
+		data += sizeof(uint8_t);
+		id = sys_get_be16(data);
+		BT_DBG("Attribute ID 0x%04x", id);
+		data += sizeof(uint16_t);
+
+		dlen = sdp_get_attr_value_len(data,
+					      buf->len - (data - buf->data));
+		if (dlen < 0) {
+			BT_ERR("Invalid attribute value data");
+			return -EINVAL;
+		}
+
+		if (id == attr_id) {
+			BT_DBG("Attribute ID 0x%04x Value found", id);
+			/*
+			 * Initialize attribute value buffer data using selected
+			 * data slice from original buffer.
+			 */
+			attr->val = data;
+			attr->len = dlen;
+			attr->attr_id = id;
+			return 0;
+		}
+
+		data += dlen;
+	}
+
+	return -ENOENT;
+}
+
+/* reads SEQ item length, moves input buffer data reader forward */
+static ssize_t sdp_get_seq_len_item(uint8_t **data, size_t len)
+{
+	const uint8_t *pnext;
+
+	BT_ASSERT(data);
+	BT_ASSERT(*data);
+
+	/* validate len for pnext safe use to read 8bit bit value */
+	if (len < 2) {
+		goto err;
+	}
+
+	pnext = *data + sizeof(uint8_t);
+
+	switch (*data[0]) {
+	case BT_SDP_SEQ8:
+		if (len < (2 + pnext[0])) {
+			break;
+		}
+
+		*data += 2;
+		return pnext[0];
+	case BT_SDP_SEQ16:
+		/* validate len for pnext safe use to read 16bit value */
+		if (len < 3) {
+			break;
+		}
+
+		if (len < (3 + sys_get_be16(pnext))) {
+			break;
+		}
+
+		*data += 3;
+		return sys_get_be16(pnext);
+	case BT_SDP_SEQ32:
+		/* validate len for pnext safe use to read 32bit value */
+		if (len < 5) {
+			break;
+		}
+
+		if (len < (5 + sys_get_be32(pnext))) {
+			break;
+		}
+
+		*data += 5;
+		return sys_get_be32(pnext);
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x", *data[0]);
+		return -EINVAL;
+	}
+err:
+	BT_ERR("Too short buffer length %zu", len);
+	return -EMSGSIZE;
+}
+
+static int sdp_get_uuid_data(const struct bt_sdp_attr_item *attr,
+			     struct bt_sdp_uuid_desc *pd,
+			     uint16_t proto_profile)
+{
+	/* get start address of attribute value */
+	uint8_t *p = attr->val;
+	ssize_t slen;
+
+	BT_ASSERT(p);
+
+	/* Attribute value is a SEQ, get length of parent SEQ frame */
+	slen = sdp_get_seq_len_item(&p, attr->len);
+	if (slen < 0) {
+		return slen;
+	}
+
+	/* start reading stacked UUIDs in analyzed sequences tree */
+	while (p - attr->val < attr->len) {
+		size_t to_end, left = 0;
+
+		/* to_end tells how far to the end of input buffer */
+		to_end = attr->len - (p - attr->val);
+		/* how long is current UUID's item data associated to */
+		slen = sdp_get_seq_len_item(&p, to_end);
+		if (slen < 0) {
+			return slen;
+		}
+
+		/* left tells how far is to the end of current UUID */
+		left = slen;
+
+		/* check if at least DTD + UUID16 can be read safely */
+		if (left < 3) {
+			return -EMSGSIZE;
+		}
+
+		/* check DTD and get stacked UUID value */
+		switch (p[0]) {
+		case BT_SDP_UUID16:
+			memcpy(&pd->uuid16,
+			       BT_UUID_DECLARE_16(sys_get_be16(++p)),
+			       sizeof(struct bt_uuid_16));
+			p += sizeof(uint16_t);
+			left -= sizeof(uint16_t);
+			break;
+		case BT_SDP_UUID32:
+			/* check if valid UUID32 can be read safely */
+			if (left < 5) {
+				return -EMSGSIZE;
+			}
+
+			memcpy(&pd->uuid32,
+			       BT_UUID_DECLARE_32(sys_get_be32(++p)),
+			       sizeof(struct bt_uuid_32));
+			p += sizeof(uint32_t);
+			left -= sizeof(uint32_t);
+			break;
+		default:
+			BT_ERR("Invalid/unhandled DTD 0x%02x\n", p[0]);
+			return -EINVAL;
+		}
+
+		/* include last DTD in p[0] size itself updating left */
+		left -= sizeof(p[0]);
+
+		/*
+		 * Check if current UUID value matches input one given by user.
+		 * If found save it's location and length and return.
+		 */
+		if ((proto_profile == BT_UUID_16(&pd->uuid)->val) ||
+		    (proto_profile == BT_UUID_32(&pd->uuid)->val)) {
+			pd->params = p;
+			pd->params_len = left;
+
+			BT_DBG("UUID 0x%s found", bt_uuid_str(&pd->uuid));
+			return 0;
+		}
+
+		/* skip left octets to point beginning of next UUID in tree */
+		p += left;
+	}
+
+	BT_DBG("Value 0x%04x not found", proto_profile);
+	return -ENOENT;
+}
+
+/*
+ * Helper extracting specific parameters associated with UUID node given in
+ * protocol descriptor list or profile descriptor list.
+ */
+static int sdp_get_param_item(struct bt_sdp_uuid_desc *pd_item, uint16_t *param)
+{
+	const uint8_t *p = pd_item->params;
+	bool len_err = false;
+
+	BT_ASSERT(p);
+
+	BT_DBG("Getting UUID's 0x%s params", bt_uuid_str(&pd_item->uuid));
+
+	switch (p[0]) {
+	case BT_SDP_UINT8:
+		/* check if 8bits value can be read safely */
+		if (pd_item->params_len < 2) {
+			len_err = true;
+			break;
+		}
+		*param = (++p)[0];
+		p += sizeof(uint8_t);
+		break;
+	case BT_SDP_UINT16:
+		/* check if 16bits value can be read safely */
+		if (pd_item->params_len < 3) {
+			len_err = true;
+			break;
+		}
+		*param = sys_get_be16(++p);
+		p += sizeof(uint16_t);
+		break;
+	case BT_SDP_UINT32:
+		/* check if 32bits value can be read safely */
+		if (pd_item->params_len < 5) {
+			len_err = true;
+			break;
+		}
+		*param = sys_get_be32(++p);
+		p += sizeof(uint32_t);
+		break;
+	default:
+		BT_ERR("Invalid/unhandled DTD 0x%02x\n", p[0]);
+		return -EINVAL;
+	}
+	/*
+	 * Check if no more data than already read is associated with UUID. In
+	 * valid case after getting parameter we should reach data buf end.
+	 */
+	if (p - pd_item->params != pd_item->params_len || len_err) {
+		BT_DBG("Invalid param buffer length");
+		return -EMSGSIZE;
+	}
+
+	return 0;
+}
+
+int bt_sdp_get_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
+			   uint16_t *param)
+{
+	struct bt_sdp_attr_item attr;
+	struct bt_sdp_uuid_desc pd;
+	int res;
+
+	if (proto != BT_SDP_PROTO_RFCOMM && proto != BT_SDP_PROTO_L2CAP) {
+		BT_ERR("Invalid protocol specifier");
+		return -EINVAL;
+	}
+
+	res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROTO_DESC_LIST);
+	if (res < 0) {
+		BT_WARN("Attribute 0x%04x not found, err %d",
+			BT_SDP_ATTR_PROTO_DESC_LIST, res);
+		return res;
+	}
+
+	res = sdp_get_uuid_data(&attr, &pd, proto);
+	if (res < 0) {
+		BT_WARN("Protocol specifier 0x%04x not found, err %d", proto,
+			res);
+		return res;
+	}
+
+	return sdp_get_param_item(&pd, param);
+}
+
+int bt_sdp_get_profile_version(const struct net_buf *buf, uint16_t profile,
+			       uint16_t *version)
+{
+	struct bt_sdp_attr_item attr;
+	struct bt_sdp_uuid_desc pd;
+	int res;
+
+	res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROFILE_DESC_LIST);
+	if (res < 0) {
+		BT_WARN("Attribute 0x%04x not found, err %d",
+			BT_SDP_ATTR_PROFILE_DESC_LIST, res);
+		return res;
+	}
+
+	res = sdp_get_uuid_data(&attr, &pd, profile);
+	if (res < 0) {
+		BT_WARN("Profile 0x%04x not found, err %d", profile, res);
+		return res;
+	}
+
+	return sdp_get_param_item(&pd, version);
+}
+
+int bt_sdp_get_features(const struct net_buf *buf, uint16_t *features)
+{
+	struct bt_sdp_attr_item attr;
+	const uint8_t *p;
+	int res;
+
+	res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_SUPPORTED_FEATURES);
+	if (res < 0) {
+		BT_WARN("Attribute 0x%04x not found, err %d",
+			BT_SDP_ATTR_SUPPORTED_FEATURES, res);
+		return res;
+	}
+
+	p = attr.val;
+	BT_ASSERT(p);
+
+	if (p[0] != BT_SDP_UINT16) {
+		BT_ERR("Invalid DTD 0x%02x", p[0]);
+		return -EINVAL;
+	}
+
+	/* assert 16bit can be read safely */
+	if (attr.len < 3) {
+		BT_ERR("Data length too short %u", attr.len);
+		return -EMSGSIZE;
+	}
+
+	*features = sys_get_be16(++p);
+	p += sizeof(uint16_t);
+
+	if (p - attr.val != attr.len) {
+		BT_ERR("Invalid data length %u", attr.len);
+		return -EMSGSIZE;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/sdp_internal.h	(working copy)
@@ -0,0 +1,74 @@
+/* sdp_internal.h - Service Discovery Protocol handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * The PDU identifiers of SDP packets between client and server
+ */
+#define BT_SDP_ERROR_RSP           0x01
+#define BT_SDP_SVC_SEARCH_REQ      0x02
+#define BT_SDP_SVC_SEARCH_RSP      0x03
+#define BT_SDP_SVC_ATTR_REQ        0x04
+#define BT_SDP_SVC_ATTR_RSP        0x05
+#define BT_SDP_SVC_SEARCH_ATTR_REQ 0x06
+#define BT_SDP_SVC_SEARCH_ATTR_RSP 0x07
+
+/*
+ * Some additions to support service registration.
+ * These are outside the scope of the Bluetooth specification
+ */
+#define BT_SDP_SVC_REGISTER_REQ 0x75
+#define BT_SDP_SVC_REGISTER_RSP 0x76
+#define BT_SDP_SVC_UPDATE_REQ   0x77
+#define BT_SDP_SVC_UPDATE_RSP   0x78
+#define BT_SDP_SVC_REMOVE_REQ   0x79
+#define BT_SDP_SVC_REMOVE_RSP   0x80
+
+/*
+ * SDP Error codes
+ */
+#define BT_SDP_INVALID_VERSION       0x0001
+#define BT_SDP_INVALID_RECORD_HANDLE 0x0002
+#define BT_SDP_INVALID_SYNTAX        0x0003
+#define BT_SDP_INVALID_PDU_SIZE      0x0004
+#define BT_SDP_INVALID_CSTATE        0x0005
+
+#define BT_SDP_MAX_SERVICES   10
+
+struct bt_sdp_data_elem_seq {
+	uint8_t  type; /* Type: Will be data element sequence */
+	uint16_t size; /* We only support 2 byte sizes for now */
+} __packed;
+
+struct bt_sdp_hdr {
+	uint8_t  op_code;
+	uint16_t tid;
+	uint16_t param_len;
+} __packed;
+
+struct bt_sdp_svc_rsp {
+	uint16_t  total_recs;
+	uint16_t  current_recs;
+} __packed;
+
+struct bt_sdp_att_rsp {
+	uint16_t att_list_len;
+} __packed;
+
+/* Allowed attributes length in SSA Request PDU to be taken from server */
+#define BT_SDP_MAX_ATTR_LEN 0xffff
+
+/* Max allowed length of PDU Continuation State */
+#define BT_SDP_MAX_PDU_CSTATE_LEN 16
+
+/* Type mapping SDP PDU Continuation State */
+struct bt_sdp_pdu_cstate {
+	uint8_t length;
+	uint8_t data[BT_SDP_MAX_PDU_CSTATE_LEN];
+} __packed;
+
+void bt_sdp_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.h	(working copy)
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Max settings key length (with all components) */
+#define BT_SETTINGS_KEY_MAX 36
+
+/* Base64-encoded string buffer size of in_size bytes */
+#define BT_SETTINGS_SIZE(in_size) ((((((in_size) - 1) / 3) * 4) + 4) + 1)
+
+/* Helpers for keys containing a bdaddr */
+void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
+			    const bt_addr_le_t *addr, const char *key);
+int bt_settings_decode_key(const char *key, bt_addr_le_t *addr);
+
+void bt_settings_save_id(void);
+
+int bt_settings_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/settings.c	(working copy)
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+
+#include <zephyr.h>
+#include <settings/settings.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SETTINGS)
+#define LOG_MODULE_NAME bt_settings
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "settings.h"
+
+#if defined(CONFIG_BT_SETTINGS_USE_PRINTK)
+void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
+			    const bt_addr_le_t *addr, const char *key)
+{
+	if (key) {
+		snprintk(path, path_size,
+			 "bt/%s/%02x%02x%02x%02x%02x%02x%u/%s", subsys,
+			 addr->a.val[5], addr->a.val[4], addr->a.val[3],
+			 addr->a.val[2], addr->a.val[1], addr->a.val[0],
+			 addr->type, key);
+	} else {
+		snprintk(path, path_size,
+			 "bt/%s/%02x%02x%02x%02x%02x%02x%u", subsys,
+			 addr->a.val[5], addr->a.val[4], addr->a.val[3],
+			 addr->a.val[2], addr->a.val[1], addr->a.val[0],
+			 addr->type);
+	}
+
+	BT_DBG("Encoded path %s", log_strdup(path));
+}
+#else
+void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
+			    const bt_addr_le_t *addr, const char *key)
+{
+	size_t len = 3;
+
+	/* Skip if path_size is less than 3; strlen("bt/") */
+	if (len < path_size) {
+		/* Key format:
+		 *  "bt/<subsys>/<addr><type>/<key>", "/<key>" is optional
+		 */
+		strcpy(path, "bt/");
+		strncpy(&path[len], subsys, path_size - len);
+		len = strlen(path);
+		if (len < path_size) {
+			path[len] = '/';
+			len++;
+		}
+
+		for (int8_t i = 5; i >= 0 && len < path_size; i--) {
+			len += bin2hex(&addr->a.val[i], 1, &path[len],
+				       path_size - len);
+		}
+
+		if (len < path_size) {
+			/* Type can be either BT_ADDR_LE_PUBLIC or
+			 * BT_ADDR_LE_RANDOM (value 0 or 1)
+			 */
+			path[len] = '0' + addr->type;
+			len++;
+		}
+
+		if (key && len < path_size) {
+			path[len] = '/';
+			len++;
+			strncpy(&path[len], key, path_size - len);
+			len += strlen(&path[len]);
+		}
+
+		if (len >= path_size) {
+			/* Truncate string */
+			path[path_size - 1] = '\0';
+		}
+	} else if (path_size > 0) {
+		*path = '\0';
+	}
+
+	BT_DBG("Encoded path %s", log_strdup(path));
+}
+#endif
+
+int bt_settings_decode_key(const char *key, bt_addr_le_t *addr)
+{
+	if (settings_name_next(key, NULL) != 13) {
+		return -EINVAL;
+	}
+
+	if (key[12] == '0') {
+		addr->type = BT_ADDR_LE_PUBLIC;
+	} else if (key[12] == '1') {
+		addr->type = BT_ADDR_LE_RANDOM;
+	} else {
+		return -EINVAL;
+	}
+
+	for (uint8_t i = 0; i < 6; i++) {
+		hex2bin(&key[i * 2], 2, &addr->a.val[5 - i], 1);
+	}
+
+	BT_DBG("Decoded %s as %s", log_strdup(key), bt_addr_le_str(addr));
+
+	return 0;
+}
+
+static int set(const char *name, size_t len_rd, settings_read_cb read_cb,
+	       void *cb_arg)
+{
+	ssize_t len;
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	len = settings_name_next(name, &next);
+
+	if (!strncmp(name, "id", len)) {
+		/* Any previously provided identities supersede flash */
+		if (atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
+			BT_WARN("Ignoring identities stored in flash");
+			return 0;
+		}
+
+		len = read_cb(cb_arg, &bt_dev.id_addr, sizeof(bt_dev.id_addr));
+		if (len < sizeof(bt_dev.id_addr[0])) {
+			if (len < 0) {
+				BT_ERR("Failed to read ID address from storage"
+				       " (err %zd)", len);
+			} else {
+				BT_ERR("Invalid length ID address in storage");
+				BT_HEXDUMP_DBG(&bt_dev.id_addr, len,
+					       "data read");
+			}
+			(void)memset(bt_dev.id_addr, 0,
+				     sizeof(bt_dev.id_addr));
+			bt_dev.id_count = 0U;
+		} else {
+			int i;
+
+			bt_dev.id_count = len / sizeof(bt_dev.id_addr[0]);
+			for (i = 0; i < bt_dev.id_count; i++) {
+				BT_DBG("ID[%d] %s", i,
+				       bt_addr_le_str(&bt_dev.id_addr[i]));
+			}
+		}
+
+		return 0;
+	}
+
+#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
+	if (!strncmp(name, "name", len)) {
+		len = read_cb(cb_arg, &bt_dev.name, sizeof(bt_dev.name) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read device name from storage"
+			       " (err %zd)", len);
+		} else {
+			bt_dev.name[len] = '\0';
+
+			BT_DBG("Name set to %s", log_strdup(bt_dev.name));
+		}
+		return 0;
+	}
+#endif
+
+#if defined(CONFIG_BT_PRIVACY)
+	if (!strncmp(name, "irk", len)) {
+		len = read_cb(cb_arg, bt_dev.irk, sizeof(bt_dev.irk));
+		if (len < sizeof(bt_dev.irk[0])) {
+			if (len < 0) {
+				BT_ERR("Failed to read IRK from storage"
+				       " (err %zd)", len);
+			} else {
+				BT_ERR("Invalid length IRK in storage");
+				(void)memset(bt_dev.irk, 0, sizeof(bt_dev.irk));
+			}
+		} else {
+			int i, count;
+
+			count = len / sizeof(bt_dev.irk[0]);
+			for (i = 0; i < count; i++) {
+				BT_DBG("IRK[%d] %s", i,
+				       bt_hex(bt_dev.irk[i], 16));
+			}
+		}
+
+		return 0;
+	}
+#endif /* CONFIG_BT_PRIVACY */
+
+	return -ENOENT;
+}
+
+#define ID_DATA_LEN(array) (bt_dev.id_count * sizeof(array[0]))
+
+static void save_id(struct k_work *work)
+{
+	int err;
+	BT_INFO("Saving ID");
+	err = settings_save_one("bt/id", &bt_dev.id_addr,
+				ID_DATA_LEN(bt_dev.id_addr));
+	if (err) {
+		BT_ERR("Failed to save ID (err %d)", err);
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	err = settings_save_one("bt/irk", bt_dev.irk, ID_DATA_LEN(bt_dev.irk));
+	if (err) {
+		BT_ERR("Failed to save IRK (err %d)", err);
+	}
+#endif
+}
+
+K_WORK_DEFINE(save_id_work, save_id);
+
+void bt_settings_save_id(void)
+{
+	k_work_submit(&save_id_work);
+}
+
+static int commit(void)
+{
+	BT_DBG("");
+
+#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
+	if (bt_dev.name[0] == '\0') {
+		bt_set_name(CONFIG_BT_DEVICE_NAME);
+	}
+#endif
+	if (!bt_dev.id_count) {
+		bt_setup_public_id_addr();
+	}
+
+	if (!bt_dev.id_count) {
+		int err;
+
+		err = bt_setup_random_id_addr();
+		if (err) {
+			BT_ERR("Unable to setup an identity address");
+			return err;
+		}
+	}
+
+	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
+		bt_finalize_init();
+	}
+
+	/* If any part of the Identity Information of the device has been
+	 * generated this Identity needs to be saved persistently.
+	 */
+	if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_STORE_ID)) {
+		BT_DBG("Storing Identity Information");
+		bt_settings_save_id();
+	}
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt, "bt", NULL, set, commit, NULL);
+
+int bt_settings_init(void)
+{
+	int err;
+
+	BT_DBG("");
+
+	err = settings_subsys_init();
+	if (err) {
+		BT_ERR("settings_subsys_init failed (err %d)", err);
+		return err;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.h	(working copy)
@@ -0,0 +1,169 @@
+/**
+ * @file smp.h
+ * Security Manager Protocol implementation header
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_smp_hdr {
+	uint8_t  code;
+} __packed;
+
+#define BT_SMP_ERR_PASSKEY_ENTRY_FAILED		0x01
+#define BT_SMP_ERR_OOB_NOT_AVAIL		0x02
+#define BT_SMP_ERR_AUTH_REQUIREMENTS		0x03
+#define BT_SMP_ERR_CONFIRM_FAILED		0x04
+#define BT_SMP_ERR_PAIRING_NOTSUPP		0x05
+#define BT_SMP_ERR_ENC_KEY_SIZE			0x06
+#define BT_SMP_ERR_CMD_NOTSUPP			0x07
+#define BT_SMP_ERR_UNSPECIFIED			0x08
+#define BT_SMP_ERR_REPEATED_ATTEMPTS		0x09
+#define BT_SMP_ERR_INVALID_PARAMS		0x0a
+#define BT_SMP_ERR_DHKEY_CHECK_FAILED		0x0b
+#define BT_SMP_ERR_NUMERIC_COMP_FAILED		0x0c
+#define BT_SMP_ERR_BREDR_PAIRING_IN_PROGRESS	0x0d
+#define BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED	0x0e
+
+#define BT_SMP_IO_DISPLAY_ONLY			0x00
+#define BT_SMP_IO_DISPLAY_YESNO			0x01
+#define BT_SMP_IO_KEYBOARD_ONLY			0x02
+#define BT_SMP_IO_NO_INPUT_OUTPUT		0x03
+#define BT_SMP_IO_KEYBOARD_DISPLAY		0x04
+
+#define BT_SMP_OOB_DATA_MASK			0x01
+#define BT_SMP_OOB_NOT_PRESENT			0x00
+#define BT_SMP_OOB_PRESENT			0x01
+
+#define BT_SMP_MIN_ENC_KEY_SIZE			7
+#define BT_SMP_MAX_ENC_KEY_SIZE			16
+
+#define BT_SMP_DIST_ENC_KEY			0x01
+#define BT_SMP_DIST_ID_KEY			0x02
+#define BT_SMP_DIST_SIGN			0x04
+#define BT_SMP_DIST_LINK_KEY			0x08
+
+#define BT_SMP_DIST_MASK			0x0f
+
+#define BT_SMP_AUTH_NONE			0x00
+#define BT_SMP_AUTH_BONDING			0x01
+#define BT_SMP_AUTH_MITM			0x04
+#define BT_SMP_AUTH_SC				0x08
+#define BT_SMP_AUTH_KEYPRESS			0x10
+#define BT_SMP_AUTH_CT2				0x20
+
+#define BT_SMP_CMD_PAIRING_REQ			0x01
+#define BT_SMP_CMD_PAIRING_RSP			0x02
+struct bt_smp_pairing {
+	uint8_t  io_capability;
+	uint8_t  oob_flag;
+	uint8_t  auth_req;
+	uint8_t  max_key_size;
+	uint8_t  init_key_dist;
+	uint8_t  resp_key_dist;
+} __packed;
+
+#define BT_SMP_CMD_PAIRING_CONFIRM		0x03
+struct bt_smp_pairing_confirm {
+	uint8_t  val[16];
+} __packed;
+
+#define BT_SMP_CMD_PAIRING_RANDOM		0x04
+struct bt_smp_pairing_random {
+	uint8_t  val[16];
+} __packed;
+
+#define BT_SMP_CMD_PAIRING_FAIL			0x05
+struct bt_smp_pairing_fail {
+	uint8_t  reason;
+} __packed;
+
+#define BT_SMP_CMD_ENCRYPT_INFO			0x06
+struct bt_smp_encrypt_info {
+	uint8_t  ltk[16];
+} __packed;
+
+#define BT_SMP_CMD_MASTER_IDENT			0x07
+struct bt_smp_master_ident {
+	uint8_t ediv[2];
+	uint8_t rand[8];
+} __packed;
+
+#define BT_SMP_CMD_IDENT_INFO			0x08
+struct bt_smp_ident_info {
+	uint8_t  irk[16];
+} __packed;
+
+#define BT_SMP_CMD_IDENT_ADDR_INFO		0x09
+struct bt_smp_ident_addr_info {
+	bt_addr_le_t addr;
+} __packed;
+
+#define BT_SMP_CMD_SIGNING_INFO			0x0a
+struct bt_smp_signing_info {
+	uint8_t csrk[16];
+} __packed;
+
+#define BT_SMP_CMD_SECURITY_REQUEST		0x0b
+struct bt_smp_security_request {
+	uint8_t  auth_req;
+} __packed;
+
+#define BT_SMP_CMD_PUBLIC_KEY			0x0c
+struct bt_smp_public_key {
+	uint8_t x[32];
+	uint8_t y[32];
+} __packed;
+
+#define BT_SMP_DHKEY_CHECK			0x0d
+struct bt_smp_dhkey_check {
+	uint8_t e[16];
+} __packed;
+
+int bt_smp_start_security(struct bt_conn *conn);
+bool bt_smp_request_ltk(struct bt_conn *conn, uint64_t rand, uint16_t ediv,
+			uint8_t *ltk);
+
+void bt_smp_update_keys(struct bt_conn *conn);
+
+int bt_smp_br_send_pairing_req(struct bt_conn *conn);
+
+int bt_smp_init(void);
+
+int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
+int bt_smp_auth_passkey_confirm(struct bt_conn *conn);
+int bt_smp_auth_pairing_confirm(struct bt_conn *conn);
+int bt_smp_auth_cancel(struct bt_conn *conn);
+
+int bt_smp_le_oob_set_tk(struct bt_conn *conn, const uint8_t *tk);
+int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob);
+int bt_smp_le_oob_set_sc_data(struct bt_conn *conn,
+			      const struct bt_le_oob_sc_data *oobd_local,
+			      const struct bt_le_oob_sc_data *oobd_remote);
+int bt_smp_le_oob_get_sc_data(struct bt_conn *conn,
+			      const struct bt_le_oob_sc_data **oobd_local,
+			      const struct bt_le_oob_sc_data **oobd_remote);
+
+/** brief Verify signed message
+ *
+ *  @param conn Bluetooth connection
+ *  @param buf received packet buffer with message and signature
+ *
+ *  @return 0 in success, error code otherwise
+ */
+int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf);
+
+/** brief Sign message
+ *
+ *  @param conn Bluetooth connection
+ *  @param buf message buffer
+ *
+ *  @return 0 in success, error code otherwise
+ */
+int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf);
+
+/** Generate IRK from Identity Root (IR) */
+int bt_smp_irk_get(uint8_t *ir, uint8_t *irk);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp.c	(working copy)
@@ -0,0 +1,5568 @@
+/**
+ * @file smp.c
+ * Security Manager Protocol implementation
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <stddef.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+#include <debug/stack.h>
+
+#include <net/buf.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/buf.h>
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/aes.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/cmac_mode.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SMP)
+#define LOG_MODULE_NAME bt_smp
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "ecc.h"
+#include "keys.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "smp.h"
+
+#define SMP_TIMEOUT K_SECONDS(30)
+
+#if defined(CONFIG_BT_SIGNING)
+#define SIGN_DIST BT_SMP_DIST_SIGN
+#else
+#define SIGN_DIST 0
+#endif
+
+#if defined(CONFIG_BT_PRIVACY)
+#define ID_DIST BT_SMP_DIST_ID_KEY
+#else
+#define ID_DIST 0
+#endif
+
+#if defined(CONFIG_BT_BREDR)
+#define LINK_DIST BT_SMP_DIST_LINK_KEY
+#else
+#define LINK_DIST 0
+#endif
+
+#define RECV_KEYS (BT_SMP_DIST_ENC_KEY | BT_SMP_DIST_ID_KEY | SIGN_DIST |\
+		   LINK_DIST)
+#define SEND_KEYS (BT_SMP_DIST_ENC_KEY | ID_DIST | SIGN_DIST | LINK_DIST)
+
+#define RECV_KEYS_SC (RECV_KEYS & ~(BT_SMP_DIST_ENC_KEY))
+#define SEND_KEYS_SC (SEND_KEYS & ~(BT_SMP_DIST_ENC_KEY))
+
+#define BR_RECV_KEYS_SC (RECV_KEYS & ~(LINK_DIST))
+#define BR_SEND_KEYS_SC (SEND_KEYS & ~(LINK_DIST))
+
+#define BT_SMP_AUTH_MASK	0x07
+
+#if defined(CONFIG_BT_BONDABLE)
+#define BT_SMP_AUTH_BONDING_FLAGS BT_SMP_AUTH_BONDING
+#else
+#define BT_SMP_AUTH_BONDING_FLAGS 0
+#endif /* CONFIG_BT_BONDABLE */
+
+#if defined(CONFIG_BT_BREDR)
+
+#define BT_SMP_AUTH_MASK_SC	0x2f
+#if defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_CT2)
+#else
+#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_CT2 |\
+			     BT_SMP_AUTH_SC)
+#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
+
+#else
+
+#define BT_SMP_AUTH_MASK_SC	0x0f
+#if defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS)
+#else
+#define BT_SMP_AUTH_DEFAULT (BT_SMP_AUTH_BONDING_FLAGS | BT_SMP_AUTH_SC)
+#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
+
+#endif /* CONFIG_BT_BREDR */
+
+enum pairing_method {
+	JUST_WORKS,		/* JustWorks pairing */
+	PASSKEY_INPUT,		/* Passkey Entry input */
+	PASSKEY_DISPLAY,	/* Passkey Entry display */
+	PASSKEY_CONFIRM,	/* Passkey confirm */
+	PASSKEY_ROLE,		/* Passkey Entry depends on role */
+	LE_SC_OOB,		/* LESC Out of Band */
+	LEGACY_OOB,		/* Legacy Out of Band */
+};
+
+enum {
+	SMP_FLAG_CFM_DELAYED,	/* if confirm should be send when TK is valid */
+	SMP_FLAG_ENC_PENDING,	/* if waiting for an encryption change event */
+	SMP_FLAG_KEYS_DISTR,	/* if keys distribution phase is in progress */
+	SMP_FLAG_PAIRING,	/* if pairing is in progress */
+	SMP_FLAG_TIMEOUT,	/* if SMP timeout occurred */
+	SMP_FLAG_SC,		/* if LE Secure Connections is used */
+	SMP_FLAG_PKEY_SEND,	/* if should send Public Key when available */
+	SMP_FLAG_DHKEY_PENDING,	/* if waiting for local DHKey */
+	SMP_FLAG_DHKEY_SEND,	/* if should generate and send DHKey Check */
+	SMP_FLAG_USER,		/* if waiting for user input */
+	SMP_FLAG_DISPLAY,       /* if display_passkey() callback was called */
+	SMP_FLAG_OOB_PENDING,	/* if waiting for OOB data */
+	SMP_FLAG_BOND,		/* if bonding */
+	SMP_FLAG_SC_DEBUG_KEY,	/* if Secure Connection are using debug key */
+	SMP_FLAG_SEC_REQ,	/* if Security Request was sent/received */
+	SMP_FLAG_DHCHECK_WAIT,	/* if waiting for remote DHCheck (as slave) */
+	SMP_FLAG_DERIVE_LK,	/* if Link Key should be derived */
+	SMP_FLAG_BR_CONNECTED,	/* if BR/EDR channel is connected */
+	SMP_FLAG_BR_PAIR,	/* if should start BR/EDR pairing */
+	SMP_FLAG_CT2,		/* if should use H7 for keys derivation */
+
+	/* Total number of flags - must be at the end */
+	SMP_NUM_FLAGS,
+};
+
+/* SMP channel specific context */
+struct bt_smp {
+	/* The channel this context is associated with */
+	struct bt_l2cap_le_chan		chan;
+
+	/* Commands that remote is allowed to send */
+	atomic_t			allowed_cmds;
+
+	/* Flags for SMP state machine */
+	ATOMIC_DEFINE(flags, SMP_NUM_FLAGS);
+
+	/* Type of method used for pairing */
+	uint8_t				method;
+
+	/* Pairing Request PDU */
+	uint8_t				preq[7];
+
+	/* Pairing Response PDU */
+	uint8_t				prsp[7];
+
+	/* Pairing Confirm PDU */
+	uint8_t				pcnf[16];
+
+	/* Local random number */
+	uint8_t				prnd[16];
+
+	/* Remote random number */
+	uint8_t				rrnd[16];
+
+	/* Temporary key */
+	uint8_t				tk[16];
+
+	/* Remote Public Key for LE SC */
+	uint8_t				pkey[64];
+
+	/* DHKey */
+	uint8_t				dhkey[32];
+
+	/* Remote DHKey check */
+	uint8_t				e[16];
+
+	/* MacKey */
+	uint8_t				mackey[16];
+
+	/* LE SC passkey */
+	uint32_t				passkey;
+
+	/* LE SC passkey round */
+	uint8_t				passkey_round;
+
+	/* LE SC local OOB data */
+	const struct bt_le_oob_sc_data	*oobd_local;
+
+	/* LE SC remote OOB data */
+	const struct bt_le_oob_sc_data	*oobd_remote;
+
+	/* Local key distribution */
+	uint8_t				local_dist;
+
+	/* Remote key distribution */
+	uint8_t				remote_dist;
+
+	/* Delayed work for timeout handling */
+	struct k_delayed_work		work;
+};
+
+static unsigned int fixed_passkey = BT_PASSKEY_INVALID;
+
+#define DISPLAY_FIXED(smp) (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) && \
+			    fixed_passkey != BT_PASSKEY_INVALID && \
+			    (smp)->method == PASSKEY_DISPLAY)
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+/* based on table 2.8 Core Spec 2.3.5.1 Vol. 3 Part H */
+static const uint8_t gen_method_legacy[5 /* remote */][5 /* local */] = {
+	{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT },
+	{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT },
+	{ PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS,
+	  PASSKEY_DISPLAY },
+	{ JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS },
+	{ PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS,
+	  PASSKEY_ROLE },
+};
+#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+/* based on table 2.8 Core Spec 2.3.5.1 Vol. 3 Part H */
+static const uint8_t gen_method_sc[5 /* remote */][5 /* local */] = {
+	{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT },
+	{ JUST_WORKS, PASSKEY_CONFIRM, PASSKEY_INPUT, JUST_WORKS,
+	  PASSKEY_CONFIRM },
+	{ PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS,
+	  PASSKEY_DISPLAY },
+	{ JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS },
+	{ PASSKEY_DISPLAY, PASSKEY_CONFIRM, PASSKEY_INPUT, JUST_WORKS,
+	  PASSKEY_CONFIRM },
+};
+#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
+
+static const uint8_t sc_debug_public_key[64] = {
+	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac,
+	0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 0x8b, 0xd2, 0x89, 0x15,
+	0xd0, 0x8e, 0x1c, 0x74, 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
+	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 0x6d, 0xeb, 0x2a, 0x65,
+	0x49, 0x9c, 0x80, 0xdc
+};
+
+#if defined(CONFIG_BT_BREDR)
+/* SMP over BR/EDR channel specific context */
+struct bt_smp_br {
+	/* The channel this context is associated with */
+	struct bt_l2cap_br_chan	chan;
+
+	/* Commands that remote is allowed to send */
+	atomic_t		allowed_cmds;
+
+	/* Flags for SMP state machine */
+	ATOMIC_DEFINE(flags, SMP_NUM_FLAGS);
+
+	/* Local key distribution */
+	uint8_t			local_dist;
+
+	/* Remote key distribution */
+	uint8_t			remote_dist;
+
+	/* Encryption Key Size used for connection */
+	uint8_t 			enc_key_size;
+
+	/* Delayed work for timeout handling */
+	struct k_delayed_work 	work;
+};
+
+static struct bt_smp_br bt_smp_br_pool[CONFIG_BT_MAX_CONN];
+#endif /* CONFIG_BT_BREDR */
+
+static struct bt_smp bt_smp_pool[CONFIG_BT_MAX_CONN];
+static bool bondable = IS_ENABLED(CONFIG_BT_BONDABLE);
+static bool oobd_present;
+static bool sc_supported;
+static const uint8_t *sc_public_key;
+static K_SEM_DEFINE(sc_local_pkey_ready, 0, 1);
+
+static bool le_sc_supported(void)
+{
+	/*
+	 * If controller based ECC is to be used it must support
+	 * "LE Read Local P-256 Public Key" and "LE Generate DH Key" commands.
+	 * Otherwise LE SC are not supported.
+	 */
+	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
+		return false;
+	}
+
+	return BT_CMD_TEST(bt_dev.supported_commands, 34, 1) &&
+	       BT_CMD_TEST(bt_dev.supported_commands, 34, 2);
+}
+
+static uint8_t get_io_capa(void)
+{
+	if (!bt_auth) {
+		goto no_callbacks;
+	}
+
+	/* Passkey Confirmation is valid only for LE SC */
+	if (bt_auth->passkey_display && bt_auth->passkey_entry &&
+	    (bt_auth->passkey_confirm || !sc_supported)) {
+		return BT_SMP_IO_KEYBOARD_DISPLAY;
+	}
+
+	/* DisplayYesNo is useful only for LE SC */
+	if (sc_supported && bt_auth->passkey_display &&
+	    bt_auth->passkey_confirm) {
+		return BT_SMP_IO_DISPLAY_YESNO;
+	}
+
+	if (bt_auth->passkey_entry) {
+		if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
+		    fixed_passkey != BT_PASSKEY_INVALID) {
+			return BT_SMP_IO_KEYBOARD_DISPLAY;
+		} else {
+			return BT_SMP_IO_KEYBOARD_ONLY;
+		}
+	}
+
+	if (bt_auth->passkey_display) {
+		return BT_SMP_IO_DISPLAY_ONLY;
+	}
+
+no_callbacks:
+	if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
+	    fixed_passkey != BT_PASSKEY_INVALID) {
+		return BT_SMP_IO_DISPLAY_ONLY;
+	} else {
+		return BT_SMP_IO_NO_INPUT_OUTPUT;
+	}
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+static uint8_t legacy_get_pair_method(struct bt_smp *smp, uint8_t remote_io);
+#endif
+
+static bool smp_keys_check(struct bt_conn *conn)
+{
+	if (atomic_test_bit(conn->flags, BT_CONN_FORCE_PAIR)) {
+		return false;
+	}
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256,
+						     conn->id, &conn->le.dst);
+		if (!conn->le.keys) {
+			conn->le.keys = bt_keys_find(BT_KEYS_LTK,
+						     conn->id,
+						     &conn->le.dst);
+		}
+	}
+
+	if (!conn->le.keys ||
+	    !(conn->le.keys->keys & (BT_KEYS_LTK | BT_KEYS_LTK_P256))) {
+		return false;
+	}
+
+	if (conn->required_sec_level > BT_SECURITY_L2 &&
+	    !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
+		return false;
+	}
+
+	if (conn->required_sec_level > BT_SECURITY_L3 &&
+	    !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
+	    !(conn->le.keys->keys & BT_KEYS_LTK_P256) &&
+	    !(conn->le.keys->enc_size == BT_SMP_MAX_ENC_KEY_SIZE)) {
+		return false;
+	}
+
+	return true;
+}
+
+static uint8_t get_pair_method(struct bt_smp *smp, uint8_t remote_io)
+{
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		return legacy_get_pair_method(smp, remote_io);
+	}
+#endif
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+	struct bt_smp_pairing *req, *rsp;
+
+	req = (struct bt_smp_pairing *)&smp->preq[1];
+	rsp = (struct bt_smp_pairing *)&smp->prsp[1];
+
+	if ((req->auth_req & rsp->auth_req) & BT_SMP_AUTH_SC) {
+		/* if one side has OOB data use OOB */
+		if ((req->oob_flag | rsp->oob_flag) & BT_SMP_OOB_DATA_MASK) {
+			return LE_SC_OOB;
+		}
+	}
+
+	if (remote_io > BT_SMP_IO_KEYBOARD_DISPLAY) {
+		return JUST_WORKS;
+	}
+
+	/* if none side requires MITM use JustWorks */
+	if (!((req->auth_req | rsp->auth_req) & BT_SMP_AUTH_MITM)) {
+		return JUST_WORKS;
+	}
+
+	return gen_method_sc[remote_io][get_io_capa()];
+#else
+	return JUST_WORKS;
+#endif
+}
+
+static enum bt_security_err auth_err_get(uint8_t smp_err)
+{
+	switch (smp_err) {
+	case BT_SMP_ERR_PASSKEY_ENTRY_FAILED:
+	case BT_SMP_ERR_DHKEY_CHECK_FAILED:
+	case BT_SMP_ERR_NUMERIC_COMP_FAILED:
+	case BT_SMP_ERR_CONFIRM_FAILED:
+		return BT_SECURITY_ERR_AUTH_FAIL;
+	case BT_SMP_ERR_OOB_NOT_AVAIL:
+		return BT_SECURITY_ERR_OOB_NOT_AVAILABLE;
+	case BT_SMP_ERR_AUTH_REQUIREMENTS:
+	case BT_SMP_ERR_ENC_KEY_SIZE:
+		return BT_SECURITY_ERR_AUTH_REQUIREMENT;
+	case BT_SMP_ERR_PAIRING_NOTSUPP:
+	case BT_SMP_ERR_CMD_NOTSUPP:
+		return BT_SECURITY_ERR_PAIR_NOT_SUPPORTED;
+	case BT_SMP_ERR_REPEATED_ATTEMPTS:
+	case BT_SMP_ERR_BREDR_PAIRING_IN_PROGRESS:
+	case BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED:
+		return BT_SECURITY_ERR_PAIR_NOT_ALLOWED;
+	case BT_SMP_ERR_INVALID_PARAMS:
+		return BT_SECURITY_ERR_INVALID_PARAM;
+	case BT_SMP_ERR_UNSPECIFIED:
+	default:
+		return BT_SECURITY_ERR_UNSPECIFIED;
+	}
+}
+
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+static uint8_t smp_err_get(enum bt_security_err auth_err)
+{
+	switch (auth_err) {
+	case BT_SECURITY_ERR_OOB_NOT_AVAILABLE:
+		return BT_SMP_ERR_OOB_NOT_AVAIL;
+
+	case BT_SECURITY_ERR_AUTH_FAIL:
+	case BT_SECURITY_ERR_AUTH_REQUIREMENT:
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+
+	case BT_SECURITY_ERR_PAIR_NOT_SUPPORTED:
+		return BT_SMP_ERR_PAIRING_NOTSUPP;
+
+	case BT_SECURITY_ERR_INVALID_PARAM:
+		return BT_SMP_ERR_INVALID_PARAMS;
+
+	case BT_SECURITY_ERR_PIN_OR_KEY_MISSING:
+	case BT_SECURITY_ERR_PAIR_NOT_ALLOWED:
+	case BT_SECURITY_ERR_UNSPECIFIED:
+		return BT_SMP_ERR_UNSPECIFIED;
+	default:
+		return 0;
+	}
+}
+#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
+
+static struct net_buf *smp_create_pdu(struct bt_smp *smp, uint8_t op, size_t len)
+{
+	struct bt_smp_hdr *hdr;
+	struct net_buf *buf;
+	k_timeout_t timeout;
+
+	/* Don't if session had already timed out */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		timeout = K_NO_WAIT;
+	} else {
+		timeout = SMP_TIMEOUT;
+	}
+
+	/* Use smaller timeout if returning an error since that could be
+	 * caused by lack of buffers.
+	 */
+	buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout);
+	if (!buf) {
+		/* If it was not possible to allocate a buffer within the
+		 * timeout marked it as timed out.
+		 */
+		atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
+		return NULL;
+	}
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = op;
+
+	return buf;
+}
+
+/* Cypher based Message Authentication Code (CMAC) with AES 128 bit
+ *
+ * Input    : key    ( 128-bit key )
+ *          : in     ( message to be authenticated )
+ *          : len    ( length of the message in octets )
+ * Output   : out    ( message authentication code )
+ */
+static int bt_smp_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len,
+			   uint8_t *out)
+{
+	struct tc_aes_key_sched_struct sched;
+	struct tc_cmac_struct state;
+
+	if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
+		return -EIO;
+	}
+
+	if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) {
+		return -EIO;
+	}
+
+	if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int smp_d1(const uint8_t *key, uint16_t d, uint16_t r, uint8_t res[16])
+{
+	int err;
+
+	BT_DBG("key %s d %u r %u", bt_hex(key, 16), d, r);
+
+	sys_put_le16(d, &res[0]);
+	sys_put_le16(r, &res[2]);
+	memset(&res[4], 0, 16 - 4);
+
+	err = bt_encrypt_le(key, res, res);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("res %s", bt_hex(res, 16));
+	return 0;
+}
+
+static int smp_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x,
+		  uint8_t z, uint8_t res[16])
+{
+	uint8_t xs[16];
+	uint8_t m[65];
+	int err;
+
+	BT_DBG("u %s", bt_hex(u, 32));
+	BT_DBG("v %s", bt_hex(v, 32));
+	BT_DBG("x %s z 0x%x", bt_hex(x, 16), z);
+
+	/*
+	 * U, V and Z are concatenated and used as input m to the function
+	 * AES-CMAC and X is used as the key k.
+	 *
+	 * Core Spec 4.2 Vol 3 Part H 2.2.5
+	 *
+	 * note:
+	 * bt_smp_aes_cmac uses BE data and smp_f4 accept LE so we swap
+	 */
+	sys_memcpy_swap(m, u, 32);
+	sys_memcpy_swap(m + 32, v, 32);
+	m[64] = z;
+
+	sys_memcpy_swap(xs, x, 16);
+
+	err = bt_smp_aes_cmac(xs, m, sizeof(m), res);
+	if (err) {
+		return err;
+	}
+
+	sys_mem_swap(res, 16);
+
+	BT_DBG("res %s", bt_hex(res, 16));
+
+	return err;
+}
+
+static int smp_f5(const uint8_t *w, const uint8_t *n1, const uint8_t *n2,
+		  const bt_addr_le_t *a1, const bt_addr_le_t *a2, uint8_t *mackey,
+		  uint8_t *ltk)
+{
+	static const uint8_t salt[16] = { 0x6c, 0x88, 0x83, 0x91, 0xaa, 0xf5,
+					  0xa5, 0x38, 0x60, 0x37, 0x0b, 0xdb,
+					  0x5a, 0x60, 0x83, 0xbe };
+	uint8_t m[53] = { 0x00, /* counter */
+			  0x62, 0x74, 0x6c, 0x65, /* keyID */
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*n1*/
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*2*/
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a1 */
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a2 */
+			  0x01, 0x00 /* length */ };
+	uint8_t t[16], ws[32];
+	int err;
+
+	BT_DBG("w %s", bt_hex(w, 32));
+	BT_DBG("n1 %s", bt_hex(n1, 16));
+	BT_DBG("n2 %s", bt_hex(n2, 16));
+
+	sys_memcpy_swap(ws, w, 32);
+
+	err = bt_smp_aes_cmac(salt, ws, 32, t);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("t %s", bt_hex(t, 16));
+
+	sys_memcpy_swap(m + 5, n1, 16);
+	sys_memcpy_swap(m + 21, n2, 16);
+	m[37] = a1->type;
+	sys_memcpy_swap(m + 38, a1->a.val, 6);
+	m[44] = a2->type;
+	sys_memcpy_swap(m + 45, a2->a.val, 6);
+
+	err = bt_smp_aes_cmac(t, m, sizeof(m), mackey);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("mackey %1s", bt_hex(mackey, 16));
+
+	sys_mem_swap(mackey, 16);
+
+	/* counter for ltk is 1 */
+	m[0] = 0x01;
+
+	err = bt_smp_aes_cmac(t, m, sizeof(m), ltk);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("ltk %s", bt_hex(ltk, 16));
+
+	sys_mem_swap(ltk, 16);
+
+	return 0;
+}
+
+static int smp_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2,
+		  const uint8_t *r, const uint8_t *iocap, const bt_addr_le_t *a1,
+		  const bt_addr_le_t *a2, uint8_t *check)
+{
+	uint8_t ws[16];
+	uint8_t m[65];
+	int err;
+
+	BT_DBG("w %s", bt_hex(w, 16));
+	BT_DBG("n1 %s", bt_hex(n1, 16));
+	BT_DBG("n2 %s", bt_hex(n2, 16));
+	BT_DBG("r %s", bt_hex(r, 16));
+	BT_DBG("io_cap %s", bt_hex(iocap, 3));
+	BT_DBG("a1 %s", bt_hex(a1, 7));
+	BT_DBG("a2 %s", bt_hex(a2, 7));
+
+	sys_memcpy_swap(m, n1, 16);
+	sys_memcpy_swap(m + 16, n2, 16);
+	sys_memcpy_swap(m + 32, r, 16);
+	sys_memcpy_swap(m + 48, iocap, 3);
+
+	m[51] = a1->type;
+	memcpy(m + 52, a1->a.val, 6);
+	sys_memcpy_swap(m + 52, a1->a.val, 6);
+
+	m[58] = a2->type;
+	memcpy(m + 59, a2->a.val, 6);
+	sys_memcpy_swap(m + 59, a2->a.val, 6);
+
+	sys_memcpy_swap(ws, w, 16);
+
+	err = bt_smp_aes_cmac(ws, m, sizeof(m), check);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("res %s", bt_hex(check, 16));
+
+	sys_mem_swap(check, 16);
+
+	return 0;
+}
+
+static int smp_g2(const uint8_t u[32], const uint8_t v[32],
+		  const uint8_t x[16], const uint8_t y[16], uint32_t *passkey)
+{
+	uint8_t m[80], xs[16];
+	int err;
+
+	BT_DBG("u %s", bt_hex(u, 32));
+	BT_DBG("v %s", bt_hex(v, 32));
+	BT_DBG("x %s", bt_hex(x, 16));
+	BT_DBG("y %s", bt_hex(y, 16));
+
+	sys_memcpy_swap(m, u, 32);
+	sys_memcpy_swap(m + 32, v, 32);
+	sys_memcpy_swap(m + 64, y, 16);
+
+	sys_memcpy_swap(xs, x, 16);
+
+	/* reuse xs (key) as buffer for result */
+	err = bt_smp_aes_cmac(xs, m, sizeof(m), xs);
+	if (err) {
+		return err;
+	}
+	BT_DBG("res %s", bt_hex(xs, 16));
+
+	memcpy(passkey, xs + 12, 4);
+	*passkey = sys_be32_to_cpu(*passkey) % 1000000;
+
+	BT_DBG("passkey %u", *passkey);
+
+	return 0;
+}
+
+static uint8_t get_encryption_key_size(struct bt_smp *smp)
+{
+	struct bt_smp_pairing *req, *rsp;
+
+	req = (struct bt_smp_pairing *)&smp->preq[1];
+	rsp = (struct bt_smp_pairing *)&smp->prsp[1];
+
+	/*
+	 * The smaller value of the initiating and responding devices maximum
+	 * encryption key length parameters shall be used as the encryption key
+	 * size.
+	 */
+	return MIN(req->max_key_size, rsp->max_key_size);
+}
+
+/* Check that if a new pairing procedure with an existing bond will not lower
+ * the established security level of the bond.
+ */
+static bool update_keys_check(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_DISABLE_LEGACY_JW_PASSKEY) &&
+	    !atomic_test_bit(smp->flags, SMP_FLAG_SC) &&
+	    smp->method != LEGACY_OOB) {
+		return false;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) &&
+	    smp->method != LEGACY_OOB) {
+		return false;
+	}
+
+	if (!conn->le.keys ||
+	    !(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
+		return true;
+	}
+
+	if (conn->le.keys->enc_size > get_encryption_key_size(smp)) {
+		return false;
+	}
+
+	if ((conn->le.keys->keys & BT_KEYS_LTK_P256) &&
+	    !atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		return false;
+	}
+
+	if ((conn->le.keys->flags & BT_KEYS_AUTHENTICATED) &&
+	     smp->method == JUST_WORKS) {
+		return false;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE) &&
+	    (!(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)
+	     && smp->method == JUST_WORKS)) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool update_debug_keys_check(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+	}
+
+	if (!conn->le.keys ||
+	    !(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
+		return true;
+	}
+
+	if (conn->le.keys->flags & BT_KEYS_DEBUG) {
+		return false;
+	}
+
+	return true;
+}
+
+#if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_SIGNING) || \
+	!defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+/* For TX callbacks */
+static void smp_pairing_complete(struct bt_smp *smp, uint8_t status);
+#if defined(CONFIG_BT_BREDR)
+static void smp_pairing_br_complete(struct bt_smp_br *smp, uint8_t status);
+#endif
+
+static void smp_check_complete(struct bt_conn *conn, uint8_t dist_complete)
+{
+	struct bt_l2cap_chan *chan;
+
+	if (conn->type == BT_CONN_TYPE_LE) {
+		struct bt_smp *smp;
+
+		chan = bt_l2cap_le_lookup_tx_cid(conn, BT_L2CAP_CID_SMP);
+		__ASSERT(chan, "No SMP channel found");
+
+		smp = CONTAINER_OF(chan, struct bt_smp, chan);
+		smp->local_dist &= ~dist_complete;
+
+		/* if all keys were distributed, pairing is done */
+		if (!smp->local_dist && !smp->remote_dist) {
+			smp_pairing_complete(smp, 0);
+		}
+
+		return;
+	}
+
+#if defined(CONFIG_BT_BREDR)
+	if (conn->type == BT_CONN_TYPE_BR) {
+		struct bt_smp_br *smp;
+
+		chan = bt_l2cap_le_lookup_tx_cid(conn, BT_L2CAP_CID_BR_SMP);
+		__ASSERT(chan, "No SMP channel found");
+
+		smp = CONTAINER_OF(chan, struct bt_smp_br, chan);
+		smp->local_dist &= ~dist_complete;
+
+		/* if all keys were distributed, pairing is done */
+		if (!smp->local_dist && !smp->remote_dist) {
+			smp_pairing_br_complete(smp, 0);
+		}
+	}
+#endif
+}
+#endif
+
+#if defined(CONFIG_BT_PRIVACY)
+static void smp_id_sent(struct bt_conn *conn, void *user_data)
+{
+	smp_check_complete(conn, BT_SMP_DIST_ID_KEY);
+}
+#endif /* CONFIG_BT_PRIVACY */
+
+#if defined(CONFIG_BT_SIGNING)
+static void smp_sign_info_sent(struct bt_conn *conn, void *user_data)
+{
+	smp_check_complete(conn, BT_SMP_DIST_SIGN);
+}
+#endif /* CONFIG_BT_SIGNING */
+
+#if defined(CONFIG_BT_BREDR)
+static int smp_h6(const uint8_t w[16], const uint8_t key_id[4], uint8_t res[16])
+{
+	uint8_t ws[16];
+	uint8_t key_id_s[4];
+	int err;
+
+	BT_DBG("w %s", bt_hex(w, 16));
+	BT_DBG("key_id %s", bt_hex(key_id, 4));
+
+	sys_memcpy_swap(ws, w, 16);
+	sys_memcpy_swap(key_id_s, key_id, 4);
+
+	err = bt_smp_aes_cmac(ws, key_id_s, 4, res);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("res %s", bt_hex(res, 16));
+
+	sys_mem_swap(res, 16);
+
+	return 0;
+}
+
+static int smp_h7(const uint8_t salt[16], const uint8_t w[16], uint8_t res[16])
+{
+	uint8_t ws[16];
+	uint8_t salt_s[16];
+	int err;
+
+	BT_DBG("w %s", bt_hex(w, 16));
+	BT_DBG("salt %s", bt_hex(salt, 16));
+
+	sys_memcpy_swap(ws, w, 16);
+	sys_memcpy_swap(salt_s, salt, 16);
+
+	err = bt_smp_aes_cmac(salt_s, ws, 16, res);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("res %s", bt_hex(res, 16));
+
+	sys_mem_swap(res, 16);
+
+	return 0;
+}
+
+static void sc_derive_link_key(struct bt_smp *smp)
+{
+	/* constants as specified in Core Spec Vol.3 Part H 2.4.2.4 */
+	static const uint8_t lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys_link_key *link_key;
+	uint8_t ilk[16];
+
+	BT_DBG("");
+
+	/* TODO handle errors? */
+
+	/*
+	 * At this point remote device identity is known so we can use
+	 * destination address here
+	 */
+	link_key = bt_keys_get_link_key(&conn->le.dst.a);
+	if (!link_key) {
+		return;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_CT2)) {
+		/* constants as specified in Core Spec Vol.3 Part H 2.4.2.4 */
+		static const uint8_t salt[16] = { 0x31, 0x70, 0x6d, 0x74,
+					       0x00, 0x00, 0x00, 0x00,
+					       0x00, 0x00, 0x00, 0x00,
+					       0x00, 0x00, 0x00, 0x00 };
+
+		if (smp_h7(salt, conn->le.keys->ltk.val, ilk)) {
+			bt_keys_link_key_clear(link_key);
+			return;
+		}
+	} else {
+		/* constants as specified in Core Spec Vol.3 Part H 2.4.2.4 */
+		static const uint8_t tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
+
+		if (smp_h6(conn->le.keys->ltk.val, tmp1, ilk)) {
+			bt_keys_link_key_clear(link_key);
+			return;
+		}
+	}
+
+	if (smp_h6(ilk, lebr, link_key->val)) {
+		bt_keys_link_key_clear(link_key);
+	}
+
+	link_key->flags |= BT_LINK_KEY_SC;
+
+	if (conn->le.keys->flags & BT_KEYS_AUTHENTICATED) {
+		link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
+	} else {
+		link_key->flags &= ~BT_LINK_KEY_AUTHENTICATED;
+	}
+}
+
+static void smp_br_reset(struct bt_smp_br *smp)
+{
+	k_delayed_work_cancel(&smp->work);
+
+	atomic_set(smp->flags, 0);
+	atomic_set(&smp->allowed_cmds, 0);
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_REQ);
+}
+
+static void smp_pairing_br_complete(struct bt_smp_br *smp, uint8_t status)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+
+	BT_DBG("status 0x%x", status);
+
+	/* For dualmode devices LE address is same as BR/EDR address
+	 * and is of public type.
+	 */
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+	keys = bt_keys_find_addr(conn->id, &addr);
+
+	if (status) {
+		if (keys) {
+			bt_keys_clear(keys);
+		}
+
+		if (bt_auth && bt_auth->pairing_failed) {
+			bt_auth->pairing_failed(smp->chan.chan.conn,
+						auth_err_get(status));
+		}
+	} else {
+		bool bond_flag = atomic_test_bit(smp->flags, SMP_FLAG_BOND);
+
+		if (bond_flag && keys) {
+			bt_keys_store(keys);
+		}
+
+		if (bt_auth && bt_auth->pairing_complete) {
+			bt_auth->pairing_complete(smp->chan.chan.conn,
+						  bond_flag);
+		}
+	}
+
+	smp_br_reset(smp);
+}
+
+static void smp_br_timeout(struct k_work *work)
+{
+	struct bt_smp_br *smp = CONTAINER_OF(work, struct bt_smp_br, work);
+
+	BT_ERR("SMP Timeout");
+
+	smp_pairing_br_complete(smp, BT_SMP_ERR_UNSPECIFIED);
+	atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
+}
+
+static void smp_br_send(struct bt_smp_br *smp, struct net_buf *buf,
+			bt_conn_tx_cb_t cb)
+{
+	bt_l2cap_send_cb(smp->chan.chan.conn, BT_L2CAP_CID_BR_SMP, buf, cb,
+			 NULL);
+	k_delayed_work_submit(&smp->work, SMP_TIMEOUT);
+}
+
+static void bt_smp_br_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_smp_br *smp = CONTAINER_OF(chan, struct bt_smp_br, chan);
+
+	BT_DBG("chan %p cid 0x%04x", chan,
+	       CONTAINER_OF(chan, struct bt_l2cap_br_chan, chan)->tx.cid);
+
+	atomic_set_bit(smp->flags, SMP_FLAG_BR_CONNECTED);
+
+	/*
+	 * if this flag is set it means pairing was requested before channel
+	 * was connected
+	 */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BR_PAIR)) {
+		bt_smp_br_send_pairing_req(chan->conn);
+	}
+}
+
+static void bt_smp_br_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_smp_br *smp = CONTAINER_OF(chan, struct bt_smp_br, chan);
+
+	BT_DBG("chan %p cid 0x%04x", chan,
+	       CONTAINER_OF(chan, struct bt_l2cap_br_chan, chan)->tx.cid);
+
+	k_delayed_work_cancel(&smp->work);
+
+	(void)memset(smp, 0, sizeof(*smp));
+}
+
+static void smp_br_init(struct bt_smp_br *smp)
+{
+	/* Initialize SMP context without clearing L2CAP channel context */
+	(void)memset((uint8_t *)smp + sizeof(smp->chan), 0,
+		     sizeof(*smp) - (sizeof(smp->chan) + sizeof(smp->work)));
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_FAIL);
+}
+
+static void smp_br_derive_ltk(struct bt_smp_br *smp)
+{
+	/* constants as specified in Core Spec Vol.3 Part H 2.4.2.5 */
+	static const uint8_t brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys_link_key *link_key = conn->br.link_key;
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+	uint8_t ilk[16];
+
+	BT_DBG("");
+
+	if (!link_key) {
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_FORCE_BREDR) && conn->encrypt != 0x02) {
+		BT_WARN("Using P192 Link Key for P256 LTK derivation");
+	}
+
+	/*
+	 * For dualmode devices LE address is same as BR/EDR address and is of
+	 * public type.
+	 */
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+
+	keys = bt_keys_get_type(BT_KEYS_LTK_P256, conn->id, &addr);
+	if (!keys) {
+		BT_ERR("No keys space for %s", bt_addr_le_str(&addr));
+		return;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_CT2)) {
+		/* constants as specified in Core Spec Vol.3 Part H 2.4.2.5 */
+		static const uint8_t salt[16] = { 0x32, 0x70, 0x6d, 0x74,
+					       0x00, 0x00, 0x00, 0x00,
+					       0x00, 0x00, 0x00, 0x00,
+					       0x00, 0x00, 0x00, 0x00 };
+
+		if (smp_h7(salt, link_key->val, ilk)) {
+			bt_keys_link_key_clear(link_key);
+			return;
+		}
+	} else {
+		/* constants as specified in Core Spec Vol.3 Part H 2.4.2.5 */
+		static const uint8_t tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
+
+		if (smp_h6(link_key->val, tmp2, ilk)) {
+			bt_keys_clear(keys);
+			return;
+		}
+	}
+
+	if (smp_h6(ilk, brle, keys->ltk.val)) {
+		bt_keys_clear(keys);
+		return;
+	}
+
+	(void)memset(keys->ltk.ediv, 0, sizeof(keys->ltk.ediv));
+	(void)memset(keys->ltk.rand, 0, sizeof(keys->ltk.rand));
+	keys->enc_size = smp->enc_key_size;
+
+	if (link_key->flags & BT_LINK_KEY_AUTHENTICATED) {
+		keys->flags |= BT_KEYS_AUTHENTICATED;
+	} else {
+		keys->flags &= ~BT_KEYS_AUTHENTICATED;
+	}
+
+	BT_DBG("LTK derived from LinkKey");
+}
+
+static struct net_buf *smp_br_create_pdu(struct bt_smp_br *smp, uint8_t op,
+					 size_t len)
+{
+	struct bt_smp_hdr *hdr;
+	struct net_buf *buf;
+	k_timeout_t timeout;
+
+	/* Don't if session had already timed out */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		timeout = K_NO_WAIT;
+	} else {
+		timeout = SMP_TIMEOUT;
+	}
+
+	/* Use smaller timeout if returning an error since that could be
+	 * caused by lack of buffers.
+	 */
+	buf = bt_l2cap_create_pdu_timeout(NULL, 0, timeout);
+	if (!buf) {
+		/* If it was not possible to allocate a buffer within the
+		 * timeout marked it as timed out.
+		 */
+		atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
+		return NULL;
+	}
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = op;
+
+	return buf;
+}
+
+static void smp_br_distribute_keys(struct bt_smp_br *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+
+	/*
+	 * For dualmode devices LE address is same as BR/EDR address and is of
+	 * public type.
+	 */
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+
+	keys = bt_keys_get_addr(conn->id, &addr);
+	if (!keys) {
+		BT_ERR("No keys space for %s", bt_addr_le_str(&addr));
+		return;
+	}
+
+#if defined(CONFIG_BT_PRIVACY)
+	if (smp->local_dist & BT_SMP_DIST_ID_KEY) {
+		struct bt_smp_ident_info *id_info;
+		struct bt_smp_ident_addr_info *id_addr_info;
+		struct net_buf *buf;
+
+		smp->local_dist &= ~BT_SMP_DIST_ID_KEY;
+
+		buf = smp_br_create_pdu(smp, BT_SMP_CMD_IDENT_INFO,
+					sizeof(*id_info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Ident Info buffer");
+			return;
+		}
+
+		id_info = net_buf_add(buf, sizeof(*id_info));
+		memcpy(id_info->irk, bt_dev.irk[conn->id], 16);
+
+		smp_br_send(smp, buf, NULL);
+
+		buf = smp_br_create_pdu(smp, BT_SMP_CMD_IDENT_ADDR_INFO,
+				     sizeof(*id_addr_info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Ident Addr Info buffer");
+			return;
+		}
+
+		id_addr_info = net_buf_add(buf, sizeof(*id_addr_info));
+		bt_addr_le_copy(&id_addr_info->addr, &bt_dev.id_addr[conn->id]);
+
+		smp_br_send(smp, buf, smp_id_sent);
+	}
+#endif /* CONFIG_BT_PRIVACY */
+
+#if defined(CONFIG_BT_SIGNING)
+	if (smp->local_dist & BT_SMP_DIST_SIGN) {
+		struct bt_smp_signing_info *info;
+		struct net_buf *buf;
+
+		smp->local_dist &= ~BT_SMP_DIST_SIGN;
+
+		buf = smp_br_create_pdu(smp, BT_SMP_CMD_SIGNING_INFO,
+					sizeof(*info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Signing Info buffer");
+			return;
+		}
+
+		info = net_buf_add(buf, sizeof(*info));
+
+		bt_rand(info->csrk, sizeof(info->csrk));
+
+		if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+			bt_keys_add_type(keys, BT_KEYS_LOCAL_CSRK);
+			memcpy(keys->local_csrk.val, info->csrk, 16);
+			keys->local_csrk.cnt = 0U;
+		}
+
+		smp_br_send(smp, buf, smp_sign_info_sent);
+	}
+#endif /* CONFIG_BT_SIGNING */
+}
+
+static bool smp_br_pairing_allowed(struct bt_smp_br *smp)
+{
+	if (smp->chan.chan.conn->encrypt == 0x02) {
+		return true;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_FORCE_BREDR) &&
+	    smp->chan.chan.conn->encrypt == 0x01) {
+		BT_WARN("Allowing BR/EDR SMP with P-192 key");
+		return true;
+	}
+
+	return false;
+}
+
+static uint8_t smp_br_pairing_req(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	struct bt_smp_pairing *req = (void *)buf->data;
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_pairing *rsp;
+	struct net_buf *rsp_buf;
+	uint8_t max_key_size;
+
+	BT_DBG("");
+
+	/*
+	 * If a Pairing Request is received over the BR/EDR transport when
+	 * either cross-transport key derivation/generation is not supported or
+	 * the BR/EDR transport is not encrypted using a Link Key generated
+	 * using P256, a Pairing Failed shall be sent with the error code
+	 * "Cross-transport Key Derivation/Generation not allowed" (0x0E)."
+	 */
+	if (!smp_br_pairing_allowed(smp)) {
+		return BT_SMP_ERR_CROSS_TRANSP_NOT_ALLOWED;
+	}
+
+	max_key_size = bt_conn_enc_key_size(conn);
+	if (!max_key_size) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (req->max_key_size != max_key_size) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	rsp_buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
+	if (!rsp_buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	smp_br_init(smp);
+	smp->enc_key_size = max_key_size;
+
+	/*
+	 * If Secure Connections pairing has been initiated over BR/EDR, the IO
+	 * Capability, OOB data flag and Auth Req fields of the SM Pairing
+	 * Request/Response PDU shall be set to zero on transmission, and
+	 * ignored on reception.
+	 */
+	rsp = net_buf_add(rsp_buf, sizeof(*rsp));
+
+	rsp->auth_req = 0x00;
+	rsp->io_capability = 0x00;
+	rsp->oob_flag = 0x00;
+	rsp->max_key_size = max_key_size;
+	rsp->init_key_dist = (req->init_key_dist & BR_RECV_KEYS_SC);
+	rsp->resp_key_dist = (req->resp_key_dist & BR_RECV_KEYS_SC);
+
+	smp->local_dist = rsp->resp_key_dist;
+	smp->remote_dist = rsp->init_key_dist;
+
+	smp_br_send(smp, rsp_buf, NULL);
+
+	atomic_set_bit(smp->flags, SMP_FLAG_PAIRING);
+
+	/* derive LTK if requested and clear distribution bits */
+	if ((smp->local_dist & BT_SMP_DIST_ENC_KEY) &&
+	    (smp->remote_dist & BT_SMP_DIST_ENC_KEY)) {
+		smp_br_derive_ltk(smp);
+	}
+	smp->local_dist &= ~BT_SMP_DIST_ENC_KEY;
+	smp->remote_dist &= ~BT_SMP_DIST_ENC_KEY;
+
+	/* BR/EDR acceptor is like LE Slave and distributes keys first */
+	smp_br_distribute_keys(smp);
+
+	if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_INFO);
+	} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_br_complete(smp, 0);
+	}
+
+	return 0;
+}
+
+static uint8_t smp_br_pairing_rsp(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	struct bt_smp_pairing *rsp = (void *)buf->data;
+	struct bt_conn *conn = smp->chan.chan.conn;
+	uint8_t max_key_size;
+
+	BT_DBG("");
+
+	max_key_size = bt_conn_enc_key_size(conn);
+	if (!max_key_size) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (rsp->max_key_size != max_key_size) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	smp->local_dist &= rsp->init_key_dist;
+	smp->remote_dist &= rsp->resp_key_dist;
+
+	smp->local_dist &= SEND_KEYS_SC;
+	smp->remote_dist &= RECV_KEYS_SC;
+
+	/* slave distributes its keys first */
+
+	if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_INFO);
+	} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	/* derive LTK if requested and clear distribution bits */
+	if ((smp->local_dist & BT_SMP_DIST_ENC_KEY) &&
+	    (smp->remote_dist & BT_SMP_DIST_ENC_KEY)) {
+		smp_br_derive_ltk(smp);
+	}
+	smp->local_dist &= ~BT_SMP_DIST_ENC_KEY;
+	smp->remote_dist &= ~BT_SMP_DIST_ENC_KEY;
+
+	/* Pairing acceptor distributes it's keys first */
+	if (smp->remote_dist) {
+		return 0;
+	}
+
+	smp_br_distribute_keys(smp);
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_br_complete(smp, 0);
+	}
+
+	return 0;
+}
+
+static uint8_t smp_br_pairing_failed(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	struct bt_smp_pairing_fail *req = (void *)buf->data;
+
+	BT_ERR("reason 0x%x", req->reason);
+
+	smp_pairing_br_complete(smp, req->reason);
+	smp_br_reset(smp);
+
+	/* return no error to avoid sending Pairing Failed in response */
+	return 0;
+}
+
+static uint8_t smp_br_ident_info(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	struct bt_smp_ident_info *req = (void *)buf->data;
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+
+	BT_DBG("");
+
+	/* TODO should we resolve LE address if matching RPA is connected? */
+
+	/*
+	 * For dualmode devices LE address is same as BR/EDR address and is of
+	 * public type.
+	 */
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+
+	keys = bt_keys_get_type(BT_KEYS_IRK, conn->id, &addr);
+	if (!keys) {
+		BT_ERR("Unable to get keys for %s", bt_addr_le_str(&addr));
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	memcpy(keys->irk.val, req->irk, sizeof(keys->irk.val));
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_ADDR_INFO);
+
+	return 0;
+}
+
+static uint8_t smp_br_ident_addr_info(struct bt_smp_br *smp,
+				      struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_ident_addr_info *req = (void *)buf->data;
+	bt_addr_le_t addr;
+
+	BT_DBG("identity %s", bt_addr_le_str(&req->addr));
+
+	/*
+	 * For dual mode device identity address must be same as BR/EDR address
+	 * and be of public type. So if received one doesn't match BR/EDR
+	 * address we fail.
+	 */
+
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+
+	if (bt_addr_le_cmp(&addr, &req->addr)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	smp->remote_dist &= ~BT_SMP_DIST_ID_KEY;
+
+	if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	if (conn->role == BT_CONN_ROLE_MASTER && !smp->remote_dist) {
+		smp_br_distribute_keys(smp);
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_br_complete(smp, 0);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_SIGNING)
+static uint8_t smp_br_signing_info(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	struct bt_smp_signing_info *req = (void *)buf->data;
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys;
+	bt_addr_le_t addr;
+
+	BT_DBG("");
+
+	/*
+	 * For dualmode devices LE address is same as BR/EDR address and is of
+	 * public type.
+	 */
+	bt_addr_copy(&addr.a, &conn->br.dst);
+	addr.type = BT_ADDR_LE_PUBLIC;
+
+	keys = bt_keys_get_type(BT_KEYS_REMOTE_CSRK, conn->id, &addr);
+	if (!keys) {
+		BT_ERR("Unable to get keys for %s", bt_addr_le_str(&addr));
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	memcpy(keys->remote_csrk.val, req->csrk, sizeof(keys->remote_csrk.val));
+
+	smp->remote_dist &= ~BT_SMP_DIST_SIGN;
+
+	if (conn->role == BT_CONN_ROLE_MASTER && !smp->remote_dist) {
+		smp_br_distribute_keys(smp);
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_br_complete(smp, 0);
+	}
+
+	return 0;
+}
+#else
+static uint8_t smp_br_signing_info(struct bt_smp_br *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* CONFIG_BT_SIGNING */
+
+static const struct {
+	uint8_t  (*func)(struct bt_smp_br *smp, struct net_buf *buf);
+	uint8_t  expect_len;
+} br_handlers[] = {
+	{ }, /* No op-code defined for 0x00 */
+	{ smp_br_pairing_req,      sizeof(struct bt_smp_pairing) },
+	{ smp_br_pairing_rsp,      sizeof(struct bt_smp_pairing) },
+	{ }, /* pairing confirm not used over BR/EDR */
+	{ }, /* pairing random not used over BR/EDR */
+	{ smp_br_pairing_failed,   sizeof(struct bt_smp_pairing_fail) },
+	{ }, /* encrypt info not used over BR/EDR */
+	{ }, /* master ident not used over BR/EDR */
+	{ smp_br_ident_info,       sizeof(struct bt_smp_ident_info) },
+	{ smp_br_ident_addr_info,  sizeof(struct bt_smp_ident_addr_info) },
+	{ smp_br_signing_info,     sizeof(struct bt_smp_signing_info) },
+	/* security request not used over BR/EDR */
+	/* public key not used over BR/EDR */
+	/* DHKey check not used over BR/EDR */
+};
+
+static int smp_br_error(struct bt_smp_br *smp, uint8_t reason)
+{
+	struct bt_smp_pairing_fail *rsp;
+	struct net_buf *buf;
+
+	/* reset context and report */
+	smp_br_reset(smp);
+
+	buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_FAIL, sizeof(*rsp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->reason = reason;
+
+	/*
+	 * SMP timer is not restarted for PairingFailed so don't use
+	 * smp_br_send
+	 */
+	bt_l2cap_send(smp->chan.chan.conn, BT_L2CAP_CID_SMP, buf);
+
+	return 0;
+}
+
+static int bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_smp_br *smp = CONTAINER_OF(chan, struct bt_smp_br, chan);
+	struct bt_smp_hdr *hdr;
+	uint8_t err;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small SMP PDU received");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	BT_DBG("Received SMP code 0x%02x len %u", hdr->code, buf->len);
+
+	/*
+	 * If SMP timeout occurred "no further SMP commands shall be sent over
+	 * the L2CAP Security Manager Channel. A new SM procedure shall only be
+	 * performed when a new physical link has been established."
+	 */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		BT_WARN("SMP command (code 0x%02x) received after timeout",
+			hdr->code);
+		return 0;
+	}
+
+	if (hdr->code >= ARRAY_SIZE(br_handlers) ||
+	    !br_handlers[hdr->code].func) {
+		BT_WARN("Unhandled SMP code 0x%02x", hdr->code);
+		smp_br_error(smp, BT_SMP_ERR_CMD_NOTSUPP);
+		return 0;
+	}
+
+	if (!atomic_test_and_clear_bit(&smp->allowed_cmds, hdr->code)) {
+		BT_WARN("Unexpected SMP code 0x%02x", hdr->code);
+		smp_br_error(smp, BT_SMP_ERR_UNSPECIFIED);
+		return 0;
+	}
+
+	if (buf->len != br_handlers[hdr->code].expect_len) {
+		BT_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code);
+		smp_br_error(smp, BT_SMP_ERR_INVALID_PARAMS);
+		return 0;
+	}
+
+	err = br_handlers[hdr->code].func(smp, buf);
+	if (err) {
+		smp_br_error(smp, err);
+	}
+
+	return 0;
+}
+
+static bool br_sc_supported(void)
+{
+	if (IS_ENABLED(CONFIG_BT_SMP_FORCE_BREDR)) {
+		BT_WARN("Enabling BR/EDR SMP without BR/EDR SC support");
+		return true;
+	}
+
+	return BT_FEAT_SC(bt_dev.features);
+}
+
+static int bt_smp_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = bt_smp_br_connected,
+		.disconnected = bt_smp_br_disconnected,
+		.recv = bt_smp_br_recv,
+	};
+	int i;
+
+	/* Check BR/EDR SC is supported */
+	if (!br_sc_supported()) {
+		return -ENOTSUP;
+	}
+
+	BT_DBG("conn %p handle %u", conn, conn->handle);
+
+	for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
+		struct bt_smp_br *smp = &bt_smp_br_pool[i];
+
+		if (smp->chan.chan.conn) {
+			continue;
+		}
+
+		smp->chan.chan.ops = &ops;
+
+		*chan = &smp->chan.chan;
+
+		k_delayed_work_init(&smp->work, smp_br_timeout);
+		smp_br_reset(smp);
+
+		return 0;
+	}
+
+	BT_ERR("No available SMP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+static struct bt_smp_br *smp_br_chan_get(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+
+	chan = bt_l2cap_br_lookup_rx_cid(conn, BT_L2CAP_CID_BR_SMP);
+	if (!chan) {
+		BT_ERR("Unable to find SMP channel");
+		return NULL;
+	}
+
+	return CONTAINER_OF(chan, struct bt_smp_br, chan);
+}
+
+int bt_smp_br_send_pairing_req(struct bt_conn *conn)
+{
+	struct bt_smp_pairing *req;
+	struct net_buf *req_buf;
+	uint8_t max_key_size;
+	struct bt_smp_br *smp;
+
+	smp = smp_br_chan_get(conn);
+	if (!smp) {
+		return -ENOTCONN;
+	}
+
+	/* SMP Timeout */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		return -EIO;
+	}
+
+	/* pairing is in progress */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		return -EBUSY;
+	}
+
+	/* check if we are allowed to start SMP over BR/EDR */
+	if (!smp_br_pairing_allowed(smp)) {
+		return 0;
+	}
+
+	/* Channel not yet connected, will start pairing once connected */
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_BR_CONNECTED)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_BR_PAIR);
+		return 0;
+	}
+
+	max_key_size = bt_conn_enc_key_size(conn);
+	if (!max_key_size) {
+		return -EIO;
+	}
+
+	smp_br_init(smp);
+	smp->enc_key_size = max_key_size;
+
+	req_buf = smp_br_create_pdu(smp, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
+	if (!req_buf) {
+		return -ENOBUFS;
+	}
+
+	req = net_buf_add(req_buf, sizeof(*req));
+
+	/*
+	 * If Secure Connections pairing has been initiated over BR/EDR, the IO
+	 * Capability, OOB data flag and Auth Req fields of the SM Pairing
+	 * Request/Response PDU shall be set to zero on transmission, and
+	 * ignored on reception.
+	 */
+
+	req->auth_req = 0x00;
+	req->io_capability = 0x00;
+	req->oob_flag = 0x00;
+	req->max_key_size = max_key_size;
+	req->init_key_dist = BR_SEND_KEYS_SC;
+	req->resp_key_dist = BR_RECV_KEYS_SC;
+
+	smp_br_send(smp, req_buf, NULL);
+
+	smp->local_dist = BR_SEND_KEYS_SC;
+	smp->remote_dist = BR_RECV_KEYS_SC;
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RSP);
+
+	atomic_set_bit(smp->flags, SMP_FLAG_PAIRING);
+
+	return 0;
+}
+#endif /* CONFIG_BT_BREDR */
+
+static void smp_reset(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+
+	k_delayed_work_cancel(&smp->work);
+
+	smp->method = JUST_WORKS;
+	atomic_set(&smp->allowed_cmds, 0);
+	atomic_set(smp->flags, 0);
+
+	if (conn->required_sec_level != conn->sec_level) {
+		/* TODO report error */
+		/* reset required security level in case of error */
+		conn->required_sec_level = conn->sec_level;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_REQ);
+	}
+}
+
+/* Note: This function not only does set the status but also calls smp_reset
+ * at the end which clears any flags previously set.
+ */
+static void smp_pairing_complete(struct bt_smp *smp, uint8_t status)
+{
+	BT_DBG("status 0x%x", status);
+
+	if (!status) {
+#if defined(CONFIG_BT_BREDR)
+		/*
+		 * Don't derive if Debug Keys are used.
+		 * TODO should we allow this if BR/EDR is already connected?
+		 */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_DERIVE_LK) &&
+		    (!atomic_test_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY) ||
+		     IS_ENABLED(CONFIG_BT_STORE_DEBUG_KEYS))) {
+			sc_derive_link_key(smp);
+		}
+#endif /* CONFIG_BT_BREDR */
+		bool bond_flag = atomic_test_bit(smp->flags, SMP_FLAG_BOND);
+
+		if (bond_flag) {
+			bt_keys_store(smp->chan.chan.conn->le.keys);
+		}
+
+		if (bt_auth && bt_auth->pairing_complete) {
+			bt_auth->pairing_complete(smp->chan.chan.conn,
+						  bond_flag);
+		}
+	} else {
+		uint8_t auth_err = auth_err_get(status);
+
+		/* Clear the key pool entry in case of pairing failure if the
+		 * keys already existed before the pairing procedure or the
+		 * pairing failed during key distribution.
+		 */
+		if (smp->chan.chan.conn->le.keys &&
+		    (!smp->chan.chan.conn->le.keys->enc_size ||
+		     atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR))) {
+			bt_keys_clear(smp->chan.chan.conn->le.keys);
+			smp->chan.chan.conn->le.keys = NULL;
+		}
+
+		if (!atomic_test_bit(smp->flags, SMP_FLAG_KEYS_DISTR)) {
+			bt_conn_security_changed(smp->chan.chan.conn, status,
+						 auth_err);
+		}
+
+		if (bt_auth && bt_auth->pairing_failed) {
+			bt_auth->pairing_failed(smp->chan.chan.conn, auth_err);
+		}
+	}
+
+	smp_reset(smp);
+}
+
+static void smp_timeout(struct k_work *work)
+{
+	struct bt_smp *smp = CONTAINER_OF(work, struct bt_smp, work);
+
+	BT_ERR("SMP Timeout");
+
+	smp_pairing_complete(smp, BT_SMP_ERR_UNSPECIFIED);
+
+	/* smp_pairing_complete clears flags so setting timeout flag must come
+	 * after it.
+	 */
+	atomic_set_bit(smp->flags, SMP_FLAG_TIMEOUT);
+}
+
+static void smp_send(struct bt_smp *smp, struct net_buf *buf,
+		     bt_conn_tx_cb_t cb, void *user_data)
+{
+	bt_l2cap_send_cb(smp->chan.chan.conn, BT_L2CAP_CID_SMP, buf, cb, NULL);
+	k_delayed_work_submit(&smp->work, SMP_TIMEOUT);
+}
+
+static int smp_error(struct bt_smp *smp, uint8_t reason)
+{
+	struct bt_smp_pairing_fail *rsp;
+	struct net_buf *buf;
+
+	/* reset context and report */
+	smp_pairing_complete(smp, reason);
+
+	buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_FAIL, sizeof(*rsp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->reason = reason;
+
+	/* SMP timer is not restarted for PairingFailed so don't use smp_send */
+	bt_l2cap_send(smp->chan.chan.conn, BT_L2CAP_CID_SMP, buf);
+
+	return 0;
+}
+
+static uint8_t smp_send_pairing_random(struct bt_smp *smp)
+{
+	struct bt_smp_pairing_random *req;
+	struct net_buf *rsp_buf;
+
+	rsp_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_RANDOM, sizeof(*req));
+	if (!rsp_buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	req = net_buf_add(rsp_buf, sizeof(*req));
+	memcpy(req->val, smp->prnd, sizeof(req->val));
+
+	smp_send(smp, rsp_buf, NULL, NULL);
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+static void xor_128(const uint8_t p[16], const uint8_t q[16], uint8_t r[16])
+{
+	size_t len = 16;
+
+	while (len--) {
+		*r++ = *p++ ^ *q++;
+	}
+}
+
+static int smp_c1(const uint8_t k[16], const uint8_t r[16],
+		  const uint8_t preq[7], const uint8_t pres[7],
+		  const bt_addr_le_t *ia, const bt_addr_le_t *ra,
+		  uint8_t enc_data[16])
+{
+	uint8_t p1[16], p2[16];
+	int err;
+
+	BT_DBG("k %s", bt_hex(k, 16));
+	BT_DBG("r %s", bt_hex(r, 16));
+	BT_DBG("ia %s", bt_addr_le_str(ia));
+	BT_DBG("ra %s", bt_addr_le_str(ra));
+	BT_DBG("preq %s", bt_hex(preq, 7));
+	BT_DBG("pres %s", bt_hex(pres, 7));
+
+	/* pres, preq, rat and iat are concatenated to generate p1 */
+	p1[0] = ia->type;
+	p1[1] = ra->type;
+	memcpy(p1 + 2, preq, 7);
+	memcpy(p1 + 9, pres, 7);
+
+	BT_DBG("p1 %s", bt_hex(p1, 16));
+
+	/* c1 = e(k, e(k, r XOR p1) XOR p2) */
+
+	/* Using enc_data as temporary output buffer */
+	xor_128(r, p1, enc_data);
+
+	err = bt_encrypt_le(k, enc_data, enc_data);
+	if (err) {
+		return err;
+	}
+
+	/* ra is concatenated with ia and padding to generate p2 */
+	memcpy(p2, ra->a.val, 6);
+	memcpy(p2 + 6, ia->a.val, 6);
+	(void)memset(p2 + 12, 0, 4);
+
+	BT_DBG("p2 %s", bt_hex(p2, 16));
+
+	xor_128(enc_data, p2, enc_data);
+
+	return bt_encrypt_le(k, enc_data, enc_data);
+}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+static uint8_t smp_send_pairing_confirm(struct bt_smp *smp)
+{
+	struct bt_smp_pairing_confirm *req;
+	struct net_buf *buf;
+	uint8_t r;
+
+	switch (smp->method) {
+	case PASSKEY_CONFIRM:
+	case JUST_WORKS:
+		r = 0U;
+		break;
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+		/*
+		 * In the Passkey Entry protocol, the most significant
+		 * bit of Z is set equal to one and the least
+		 * significant bit is made up from one bit of the
+		 * passkey e.g. if the passkey bit is 1, then Z = 0x81
+		 * and if the passkey bit is 0, then Z = 0x80.
+		 */
+		r = (smp->passkey >> smp->passkey_round) & 0x01;
+		r |= 0x80;
+		break;
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
+	if (!buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	if (smp_f4(sc_public_key, smp->pkey, smp->prnd, r, req->val)) {
+		net_buf_unref(buf);
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	smp_send(smp, buf, NULL, NULL);
+
+	atomic_clear_bit(smp->flags, SMP_FLAG_CFM_DELAYED);
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+static void smp_ident_sent(struct bt_conn *conn, void *user_data)
+{
+	smp_check_complete(conn, BT_SMP_DIST_ENC_KEY);
+}
+
+static void legacy_distribute_keys(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys = conn->le.keys;
+
+	if (smp->local_dist & BT_SMP_DIST_ENC_KEY) {
+		struct bt_smp_encrypt_info *info;
+		struct bt_smp_master_ident *ident;
+		struct net_buf *buf;
+		/* Use struct to get randomness in single call to bt_rand */
+		struct {
+			uint8_t key[16];
+			uint8_t rand[8];
+			uint8_t ediv[2];
+		} rand;
+
+		bt_rand((void *)&rand, sizeof(rand));
+
+		buf = smp_create_pdu(smp, BT_SMP_CMD_ENCRYPT_INFO,
+				     sizeof(*info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Encrypt Info buffer");
+			return;
+		}
+
+		info = net_buf_add(buf, sizeof(*info));
+
+		/* distributed only enc_size bytes of key */
+		memcpy(info->ltk, rand.key, keys->enc_size);
+		if (keys->enc_size < sizeof(info->ltk)) {
+			(void)memset(info->ltk + keys->enc_size, 0,
+				     sizeof(info->ltk) - keys->enc_size);
+		}
+
+		smp_send(smp, buf, NULL, NULL);
+
+		buf = smp_create_pdu(smp, BT_SMP_CMD_MASTER_IDENT,
+				     sizeof(*ident));
+		if (!buf) {
+			BT_ERR("Unable to allocate Master Ident buffer");
+			return;
+		}
+
+		ident = net_buf_add(buf, sizeof(*ident));
+		memcpy(ident->rand, rand.rand, sizeof(ident->rand));
+		memcpy(ident->ediv, rand.ediv, sizeof(ident->ediv));
+
+		smp_send(smp, buf, smp_ident_sent, NULL);
+
+		if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+			bt_keys_add_type(keys, BT_KEYS_SLAVE_LTK);
+
+			memcpy(keys->slave_ltk.val, rand.key,
+			       sizeof(keys->slave_ltk.val));
+			memcpy(keys->slave_ltk.rand, rand.rand,
+			       sizeof(keys->slave_ltk.rand));
+			memcpy(keys->slave_ltk.ediv, rand.ediv,
+			       sizeof(keys->slave_ltk.ediv));
+		}
+	}
+}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+static uint8_t bt_smp_distribute_keys(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys = conn->le.keys;
+
+	if (!keys) {
+		BT_ERR("No keys space for %s", bt_addr_le_str(&conn->le.dst));
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	/* Distribute legacy pairing specific keys */
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		legacy_distribute_keys(smp);
+	}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+#if defined(CONFIG_BT_PRIVACY)
+	if (smp->local_dist & BT_SMP_DIST_ID_KEY) {
+		struct bt_smp_ident_info *id_info;
+		struct bt_smp_ident_addr_info *id_addr_info;
+		struct net_buf *buf;
+
+		buf = smp_create_pdu(smp, BT_SMP_CMD_IDENT_INFO,
+				     sizeof(*id_info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Ident Info buffer");
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		id_info = net_buf_add(buf, sizeof(*id_info));
+		memcpy(id_info->irk, bt_dev.irk[conn->id], 16);
+
+		smp_send(smp, buf, NULL, NULL);
+
+		buf = smp_create_pdu(smp, BT_SMP_CMD_IDENT_ADDR_INFO,
+				     sizeof(*id_addr_info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Ident Addr Info buffer");
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		id_addr_info = net_buf_add(buf, sizeof(*id_addr_info));
+		bt_addr_le_copy(&id_addr_info->addr, &bt_dev.id_addr[conn->id]);
+
+		smp_send(smp, buf, smp_id_sent, NULL);
+	}
+#endif /* CONFIG_BT_PRIVACY */
+
+#if defined(CONFIG_BT_SIGNING)
+	if (smp->local_dist & BT_SMP_DIST_SIGN) {
+		struct bt_smp_signing_info *info;
+		struct net_buf *buf;
+
+		buf = smp_create_pdu(smp, BT_SMP_CMD_SIGNING_INFO,
+				     sizeof(*info));
+		if (!buf) {
+			BT_ERR("Unable to allocate Signing Info buffer");
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		info = net_buf_add(buf, sizeof(*info));
+
+		bt_rand(info->csrk, sizeof(info->csrk));
+
+		if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+			bt_keys_add_type(keys, BT_KEYS_LOCAL_CSRK);
+			memcpy(keys->local_csrk.val, info->csrk, 16);
+			keys->local_csrk.cnt = 0U;
+		}
+
+		smp_send(smp, buf, smp_sign_info_sent, NULL);
+	}
+#endif /* CONFIG_BT_SIGNING */
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static uint8_t send_pairing_rsp(struct bt_smp *smp)
+{
+	struct bt_smp_pairing *rsp;
+	struct net_buf *rsp_buf;
+
+	rsp_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_RSP, sizeof(*rsp));
+	if (!rsp_buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	rsp = net_buf_add(rsp_buf, sizeof(*rsp));
+	memcpy(rsp, smp->prsp + 1, sizeof(*rsp));
+
+	smp_send(smp, rsp_buf, NULL, NULL);
+
+	return 0;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static uint8_t smp_pairing_accept_query(struct bt_conn *conn,
+				    struct bt_smp_pairing *pairing)
+{
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	if (bt_auth && bt_auth->pairing_accept) {
+		const struct bt_conn_pairing_feat feat = {
+			.io_capability = pairing->io_capability,
+			.oob_data_flag = pairing->oob_flag,
+			.auth_req = pairing->auth_req,
+			.max_enc_key_size = pairing->max_key_size,
+			.init_key_dist = pairing->init_key_dist,
+			.resp_key_dist = pairing->resp_key_dist
+		};
+
+		return smp_err_get(bt_auth->pairing_accept(conn, &feat));
+	}
+#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+static int smp_s1(const uint8_t k[16], const uint8_t r1[16],
+		  const uint8_t r2[16], uint8_t out[16])
+{
+	/* The most significant 64-bits of r1 are discarded to generate
+	 * r1' and the most significant 64-bits of r2 are discarded to
+	 * generate r2'.
+	 * r1' is concatenated with r2' to generate r' which is used as
+	 * the 128-bit input parameter plaintextData to security function e:
+	 *
+	 *    r' = r1' || r2'
+	 */
+	memcpy(out, r2, 8);
+	memcpy(out + 8, r1, 8);
+
+	/* s1(k, r1 , r2) = e(k, r') */
+	return bt_encrypt_le(k, out, out);
+}
+
+static uint8_t legacy_get_pair_method(struct bt_smp *smp, uint8_t remote_io)
+{
+	struct bt_smp_pairing *req, *rsp;
+	uint8_t method;
+
+	if (remote_io > BT_SMP_IO_KEYBOARD_DISPLAY) {
+		return JUST_WORKS;
+	}
+
+	req = (struct bt_smp_pairing *)&smp->preq[1];
+	rsp = (struct bt_smp_pairing *)&smp->prsp[1];
+
+	/* if both sides have OOB data use OOB */
+	if ((req->oob_flag & rsp->oob_flag) & BT_SMP_OOB_DATA_MASK) {
+		return LEGACY_OOB;
+	}
+
+	/* if none side requires MITM use JustWorks */
+	if (!((req->auth_req | rsp->auth_req) & BT_SMP_AUTH_MITM)) {
+		return JUST_WORKS;
+	}
+
+	method = gen_method_legacy[remote_io][get_io_capa()];
+
+	/* if both sides have KeyboardDisplay capabilities, initiator displays
+	 * and responder inputs
+	 */
+	if (method == PASSKEY_ROLE) {
+		if (smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+			method = PASSKEY_DISPLAY;
+		} else {
+			method = PASSKEY_INPUT;
+		}
+	}
+
+	return method;
+}
+
+static uint8_t legacy_request_tk(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_keys *keys;
+	uint32_t passkey;
+
+	/*
+	 * Fail if we have keys that are stronger than keys that will be
+	 * distributed in new pairing. This is to avoid replacing authenticated
+	 * keys with unauthenticated ones.
+	  */
+	keys = bt_keys_find_addr(conn->id, &conn->le.dst);
+	if (keys && (keys->flags & BT_KEYS_AUTHENTICATED) &&
+	    smp->method == JUST_WORKS) {
+		BT_ERR("JustWorks failed, authenticated keys present");
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	switch (smp->method) {
+	case LEGACY_OOB:
+		if (bt_auth && bt_auth->oob_data_request) {
+			struct bt_conn_oob_info info = {
+				.type = BT_CONN_OOB_LE_LEGACY,
+			};
+
+			atomic_set_bit(smp->flags, SMP_FLAG_USER);
+			bt_auth->oob_data_request(smp->chan.chan.conn, &info);
+		} else {
+			return BT_SMP_ERR_OOB_NOT_AVAIL;
+		}
+
+		break;
+	case PASSKEY_DISPLAY:
+		if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
+		    fixed_passkey != BT_PASSKEY_INVALID) {
+			passkey = fixed_passkey;
+		} else  {
+			if (bt_rand(&passkey, sizeof(passkey))) {
+				return BT_SMP_ERR_UNSPECIFIED;
+			}
+
+			passkey %= 1000000;
+		}
+
+		if (bt_auth && bt_auth->passkey_display) {
+			atomic_set_bit(smp->flags, SMP_FLAG_DISPLAY);
+			bt_auth->passkey_display(conn, passkey);
+		}
+
+		sys_put_le32(passkey, smp->tk);
+
+		break;
+	case PASSKEY_INPUT:
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->passkey_entry(conn);
+		break;
+	case JUST_WORKS:
+		break;
+	default:
+		BT_ERR("Unknown pairing method (%u)", smp->method);
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	return 0;
+}
+
+static uint8_t legacy_send_pairing_confirm(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_pairing_confirm *req;
+	struct net_buf *buf;
+
+	buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(*req));
+	if (!buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+
+	if (smp_c1(smp->tk, smp->prnd, smp->preq, smp->prsp,
+		   &conn->le.init_addr, &conn->le.resp_addr, req->val)) {
+		net_buf_unref(buf);
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	smp_send(smp, buf, NULL, NULL);
+
+	atomic_clear_bit(smp->flags, SMP_FLAG_CFM_DELAYED);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static uint8_t legacy_pairing_req(struct bt_smp *smp)
+{
+	uint8_t ret;
+
+	BT_DBG("");
+
+	/* ask for consent if pairing is not due to sending SecReq*/
+	if ((DISPLAY_FIXED(smp) || smp->method == JUST_WORKS) &&
+	    !atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ) &&
+	    bt_auth && bt_auth->pairing_confirm) {
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->pairing_confirm(smp->chan.chan.conn);
+		return 0;
+	}
+
+	ret = send_pairing_rsp(smp);
+	if (ret) {
+		return ret;
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+
+	return legacy_request_tk(smp);
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static uint8_t legacy_pairing_random(struct bt_smp *smp)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	uint8_t tmp[16];
+	int err;
+
+	BT_DBG("");
+
+	/* calculate confirmation */
+	err = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
+		     &conn->le.init_addr, &conn->le.resp_addr, tmp);
+	if (err) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	BT_DBG("pcnf %s", bt_hex(smp->pcnf, 16));
+	BT_DBG("cfm %s", bt_hex(tmp, 16));
+
+	if (memcmp(smp->pcnf, tmp, sizeof(smp->pcnf))) {
+		return BT_SMP_ERR_CONFIRM_FAILED;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER) {
+		uint8_t ediv[2], rand[8];
+
+		/* No need to store master STK */
+		err = smp_s1(smp->tk, smp->rrnd, smp->prnd, tmp);
+		if (err) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		/* Rand and EDiv are 0 for the STK */
+		(void)memset(ediv, 0, sizeof(ediv));
+		(void)memset(rand, 0, sizeof(rand));
+		if (bt_conn_le_start_encryption(conn, rand, ediv, tmp,
+						get_encryption_key_size(smp))) {
+			BT_ERR("Failed to start encryption");
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+
+		if (IS_ENABLED(CONFIG_BT_SMP_USB_HCI_CTLR_WORKAROUND)) {
+			if (smp->remote_dist & BT_SMP_DIST_ENC_KEY) {
+				atomic_set_bit(&smp->allowed_cmds,
+					       BT_SMP_CMD_ENCRYPT_INFO);
+			} else if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+				atomic_set_bit(&smp->allowed_cmds,
+					       BT_SMP_CMD_IDENT_INFO);
+			} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+				atomic_set_bit(&smp->allowed_cmds,
+					       BT_SMP_CMD_SIGNING_INFO);
+			}
+		}
+
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		err = smp_s1(smp->tk, smp->prnd, smp->rrnd, tmp);
+		if (err) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		memcpy(smp->tk, tmp, sizeof(smp->tk));
+		BT_DBG("generated STK %s", bt_hex(smp->tk, 16));
+
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+
+		return smp_send_pairing_random(smp);
+	}
+
+	return 0;
+}
+
+static uint8_t legacy_pairing_confirm(struct bt_smp *smp)
+{
+	BT_DBG("");
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		return legacy_send_pairing_confirm(smp);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		if (!atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PAIRING_RANDOM);
+			return legacy_send_pairing_confirm(smp);
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_CFM_DELAYED);
+	}
+
+	return 0;
+}
+
+static void legacy_user_tk_entry(struct bt_smp *smp)
+{
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_CFM_DELAYED)) {
+		return;
+	}
+
+	/* if confirm failed ie. due to invalid passkey, cancel pairing */
+	if (legacy_pairing_confirm(smp)) {
+		smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+	}
+}
+
+static void legacy_passkey_entry(struct bt_smp *smp, unsigned int passkey)
+{
+	passkey = sys_cpu_to_le32(passkey);
+	memcpy(smp->tk, &passkey, sizeof(passkey));
+
+	legacy_user_tk_entry(smp);
+}
+
+static uint8_t smp_encrypt_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	BT_DBG("");
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+		struct bt_smp_encrypt_info *req = (void *)buf->data;
+		struct bt_conn *conn = smp->chan.chan.conn;
+		struct bt_keys *keys;
+
+		keys = bt_keys_get_type(BT_KEYS_LTK, conn->id, &conn->le.dst);
+		if (!keys) {
+			BT_ERR("Unable to get keys for %s",
+			       bt_addr_le_str(&conn->le.dst));
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		memcpy(keys->ltk.val, req->ltk, 16);
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_MASTER_IDENT);
+
+	return 0;
+}
+
+static uint8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	uint8_t err;
+
+	BT_DBG("");
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+		struct bt_smp_master_ident *req = (void *)buf->data;
+		struct bt_keys *keys;
+
+		keys = bt_keys_get_type(BT_KEYS_LTK, conn->id, &conn->le.dst);
+		if (!keys) {
+			BT_ERR("Unable to get keys for %s",
+			       bt_addr_le_str(&conn->le.dst));
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		memcpy(keys->ltk.ediv, req->ediv, sizeof(keys->ltk.ediv));
+		memcpy(keys->ltk.rand, req->rand, sizeof(req->rand));
+
+		smp->remote_dist &= ~BT_SMP_DIST_ENC_KEY;
+	}
+
+	if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_INFO);
+	} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
+		err = bt_smp_distribute_keys(smp);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_complete(smp, 0);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static uint8_t legacy_pairing_rsp(struct bt_smp *smp)
+{
+	uint8_t ret;
+
+	BT_DBG("");
+
+	/* ask for consent if this is due to received SecReq */
+	if ((DISPLAY_FIXED(smp) || smp->method == JUST_WORKS) &&
+	    atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ) &&
+	    bt_auth && bt_auth->pairing_confirm) {
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->pairing_confirm(smp->chan.chan.conn);
+		return 0;
+	}
+
+	ret = legacy_request_tk(smp);
+	if (ret) {
+		return ret;
+	}
+
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		return legacy_send_pairing_confirm(smp);
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_CFM_DELAYED);
+
+	return 0;
+}
+#endif /* CONFIG_BT_CENTRAL */
+#else
+static uint8_t smp_encrypt_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+
+static uint8_t smp_master_ident(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+static int smp_init(struct bt_smp *smp)
+{
+	/* Initialize SMP context without clearing L2CAP channel context */
+	(void)memset((uint8_t *)smp + sizeof(smp->chan), 0,
+		     sizeof(*smp) - (sizeof(smp->chan) + sizeof(smp->work)));
+
+	/* Generate local random number */
+	if (bt_rand(smp->prnd, 16)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	BT_DBG("prnd %s", bt_hex(smp->prnd, 16));
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_FAIL);
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+	sc_public_key = bt_pub_key_get();
+#endif
+
+	return 0;
+}
+
+void bt_set_bondable(bool enable)
+{
+	bondable = enable;
+}
+
+void bt_set_oob_data_flag(bool enable)
+{
+	oobd_present = enable;
+}
+
+static uint8_t get_auth(struct bt_conn *conn, uint8_t auth)
+{
+	if (sc_supported) {
+		auth &= BT_SMP_AUTH_MASK_SC;
+	} else {
+		auth &= BT_SMP_AUTH_MASK;
+	}
+
+	if ((get_io_capa() == BT_SMP_IO_NO_INPUT_OUTPUT) ||
+	    (!IS_ENABLED(CONFIG_BT_SMP_ENFORCE_MITM) &&
+	    (conn->required_sec_level < BT_SECURITY_L3))) {
+		auth &= ~(BT_SMP_AUTH_MITM);
+	} else {
+		auth |= BT_SMP_AUTH_MITM;
+	}
+
+	if (bondable) {
+		auth |= BT_SMP_AUTH_BONDING;
+	} else {
+		auth &= ~BT_SMP_AUTH_BONDING;
+	}
+
+	return auth;
+}
+
+static bool sec_level_reachable(struct bt_conn *conn)
+{
+	switch (conn->required_sec_level) {
+	case BT_SECURITY_L1:
+	case BT_SECURITY_L2:
+		return true;
+	case BT_SECURITY_L3:
+		return get_io_capa() != BT_SMP_IO_NO_INPUT_OUTPUT ||
+		       (bt_auth && bt_auth->oob_data_request);
+	case BT_SECURITY_L4:
+		return (get_io_capa() != BT_SMP_IO_NO_INPUT_OUTPUT ||
+			(bt_auth && bt_auth->oob_data_request)) && sc_supported;
+	default:
+		return false;
+	}
+}
+
+static struct bt_smp *smp_chan_get(struct bt_conn *conn)
+{
+	struct bt_l2cap_chan *chan;
+
+	chan = bt_l2cap_le_lookup_rx_cid(conn, BT_L2CAP_CID_SMP);
+	if (!chan) {
+		BT_ERR("Unable to find SMP channel");
+		return NULL;
+	}
+
+	return CONTAINER_OF(chan, struct bt_smp, chan);
+}
+
+bool bt_smp_request_ltk(struct bt_conn *conn, uint64_t rand, uint16_t ediv, uint8_t *ltk)
+{
+	struct bt_smp *smp;
+	uint8_t enc_size;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return false;
+	}
+
+	/*
+	 * Both legacy STK and LE SC LTK have rand and ediv equal to zero.
+	 * If pairing is in progress use the TK for encryption.
+	 */
+	if (ediv == 0U && rand == 0U &&
+	    atomic_test_bit(smp->flags, SMP_FLAG_PAIRING) &&
+	    atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
+		enc_size = get_encryption_key_size(smp);
+
+		/*
+		 * We keep both legacy STK and LE SC LTK in TK.
+		 * Also use only enc_size bytes of key for encryption.
+		 */
+		memcpy(ltk, smp->tk, enc_size);
+		if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) {
+			(void)memset(ltk + enc_size, 0,
+				     BT_SMP_MAX_ENC_KEY_SIZE - enc_size);
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+		return true;
+	}
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, conn->id,
+					     &conn->le.dst);
+		if (!conn->le.keys) {
+			conn->le.keys = bt_keys_find(BT_KEYS_SLAVE_LTK,
+						     conn->id, &conn->le.dst);
+		}
+	}
+
+	if (ediv == 0U && rand == 0U &&
+	    conn->le.keys && (conn->le.keys->keys & BT_KEYS_LTK_P256)) {
+		enc_size = conn->le.keys->enc_size;
+
+		memcpy(ltk, conn->le.keys->ltk.val, enc_size);
+		if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) {
+			(void)memset(ltk + enc_size, 0,
+				     BT_SMP_MAX_ENC_KEY_SIZE - enc_size);
+		}
+
+		return true;
+	}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	if (conn->le.keys && (conn->le.keys->keys & BT_KEYS_SLAVE_LTK) &&
+	    !memcmp(conn->le.keys->slave_ltk.rand, &rand, 8) &&
+	    !memcmp(conn->le.keys->slave_ltk.ediv, &ediv, 2)) {
+		enc_size = conn->le.keys->enc_size;
+
+		memcpy(ltk, conn->le.keys->slave_ltk.val, enc_size);
+		if (enc_size < BT_SMP_MAX_ENC_KEY_SIZE) {
+			(void)memset(ltk + enc_size, 0,
+				     BT_SMP_MAX_ENC_KEY_SIZE - enc_size);
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+		return true;
+	}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) {
+		/* Notify higher level that security failed if security was
+		 * initiated by slave.
+		 */
+		bt_conn_security_changed(conn, BT_HCI_ERR_PIN_OR_KEY_MISSING,
+					 BT_SECURITY_ERR_PIN_OR_KEY_MISSING);
+	}
+
+	smp_reset(smp);
+	return false;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static int smp_send_security_req(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+	struct bt_smp_security_request *req;
+	struct net_buf *req_buf;
+
+	BT_DBG("");
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -ENOTCONN;
+	}
+
+	/* SMP Timeout */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		return -EIO;
+	}
+
+	/* pairing is in progress */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		return -EBUSY;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
+		return -EBUSY;
+	}
+
+	/* early verify if required sec level if reachable */
+	if (!(sec_level_reachable(conn) || smp_keys_check(conn))) {
+		return -EINVAL;
+	}
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+		if (!conn->le.keys) {
+			return -ENOMEM;
+		}
+	}
+
+	if (smp_init(smp) != 0) {
+		return -ENOBUFS;
+	}
+
+	req_buf = smp_create_pdu(smp, BT_SMP_CMD_SECURITY_REQUEST,
+				 sizeof(*req));
+	if (!req_buf) {
+		return -ENOBUFS;
+	}
+
+	req = net_buf_add(req_buf, sizeof(*req));
+	req->auth_req = get_auth(conn, BT_SMP_AUTH_DEFAULT);
+
+	/* SMP timer is not restarted for SecRequest so don't use smp_send */
+	bt_l2cap_send(conn, BT_L2CAP_CID_SMP, req_buf);
+
+	atomic_set_bit(smp->flags, SMP_FLAG_SEC_REQ);
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_REQ);
+
+	return 0;
+}
+
+static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_pairing *req = (void *)buf->data;
+	struct bt_smp_pairing *rsp;
+
+	BT_DBG("");
+
+	if ((req->max_key_size > BT_SMP_MAX_ENC_KEY_SIZE) ||
+	    (req->max_key_size < BT_SMP_MIN_ENC_KEY_SIZE)) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+		if (!conn->le.keys) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+	}
+
+	/* If we already sent a security request then the SMP context
+	 * is already initialized.
+	 */
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) {
+		int ret = smp_init(smp);
+
+		if (ret) {
+			return ret;
+		}
+	}
+
+	/* Store req for later use */
+	smp->preq[0] = BT_SMP_CMD_PAIRING_REQ;
+	memcpy(smp->preq + 1, req, sizeof(*req));
+
+	/* create rsp, it will be used later on */
+	smp->prsp[0] = BT_SMP_CMD_PAIRING_RSP;
+	rsp = (struct bt_smp_pairing *)&smp->prsp[1];
+
+	rsp->auth_req = get_auth(conn, req->auth_req);
+	rsp->io_capability = get_io_capa();
+	rsp->oob_flag = oobd_present ? BT_SMP_OOB_PRESENT :
+				       BT_SMP_OOB_NOT_PRESENT;
+	rsp->max_key_size = BT_SMP_MAX_ENC_KEY_SIZE;
+	rsp->init_key_dist = (req->init_key_dist & RECV_KEYS);
+	rsp->resp_key_dist = (req->resp_key_dist & SEND_KEYS);
+
+	if ((rsp->auth_req & BT_SMP_AUTH_SC) &&
+	    (req->auth_req & BT_SMP_AUTH_SC)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_SC);
+
+		rsp->init_key_dist &= RECV_KEYS_SC;
+		rsp->resp_key_dist &= SEND_KEYS_SC;
+	}
+
+	if ((rsp->auth_req & BT_SMP_AUTH_CT2) &&
+	    (req->auth_req & BT_SMP_AUTH_CT2)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_CT2);
+	}
+
+	smp->local_dist = rsp->resp_key_dist;
+	smp->remote_dist = rsp->init_key_dist;
+
+	if ((rsp->auth_req & BT_SMP_AUTH_BONDING) &&
+	    (req->auth_req & BT_SMP_AUTH_BONDING)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_BOND);
+	} else if (IS_ENABLED(CONFIG_BT_BONDING_REQUIRED)) {
+		/* Reject pairing req if not both intend to bond */
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_PAIRING);
+
+	smp->method = get_pair_method(smp, req->io_capability);
+
+	if (!update_keys_check(smp)) {
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+	}
+
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+#if defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+#else
+		if (IS_ENABLED(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)) {
+			uint8_t err;
+
+			err = smp_pairing_accept_query(smp->chan.chan.conn,
+						      req);
+			if (err) {
+				return err;
+			}
+		}
+
+		return legacy_pairing_req(smp);
+#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
+	}
+
+	if ((IS_ENABLED(CONFIG_BT_SMP_SC_ONLY) ||
+	     conn->required_sec_level == BT_SECURITY_L4) &&
+		smp->method == JUST_WORKS) {
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+	}
+
+	if ((IS_ENABLED(CONFIG_BT_SMP_SC_ONLY) ||
+	     conn->required_sec_level == BT_SECURITY_L4) &&
+	       get_encryption_key_size(smp) != BT_SMP_MAX_ENC_KEY_SIZE) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)) {
+		uint8_t err;
+
+		err = smp_pairing_accept_query(smp->chan.chan.conn, req);
+		if (err) {
+			return err;
+		}
+	}
+
+	if ((DISPLAY_FIXED(smp) || smp->method == JUST_WORKS) &&
+	    !atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ) &&
+	    bt_auth && bt_auth->pairing_confirm) {
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->pairing_confirm(smp->chan.chan.conn);
+		return 0;
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
+	return send_pairing_rsp(smp);
+}
+#else
+static uint8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static uint8_t sc_send_public_key(struct bt_smp *smp)
+{
+	struct bt_smp_public_key *req;
+	struct net_buf *req_buf;
+
+	req_buf = smp_create_pdu(smp, BT_SMP_CMD_PUBLIC_KEY, sizeof(*req));
+	if (!req_buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	req = net_buf_add(req_buf, sizeof(*req));
+
+	memcpy(req->x, sc_public_key, sizeof(req->x));
+	memcpy(req->y, &sc_public_key[32], sizeof(req->y));
+
+	smp_send(smp, req_buf, NULL, NULL);
+
+	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static int smp_send_pairing_req(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+	struct bt_smp_pairing *req;
+	struct net_buf *req_buf;
+
+	BT_DBG("");
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -ENOTCONN;
+	}
+
+	/* SMP Timeout */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		return -EIO;
+	}
+
+	/* pairing is in progress */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		return -EBUSY;
+	}
+
+	/* Encryption is in progress */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
+		return -EBUSY;
+	}
+
+	/* early verify if required sec level if reachable */
+	if (!sec_level_reachable(conn)) {
+		return -EINVAL;
+	}
+
+	if (!conn->le.keys) {
+		conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+		if (!conn->le.keys) {
+			return -ENOMEM;
+		}
+	}
+
+	if (smp_init(smp)) {
+		return -ENOBUFS;
+	}
+
+	req_buf = smp_create_pdu(smp, BT_SMP_CMD_PAIRING_REQ, sizeof(*req));
+	if (!req_buf) {
+		return -ENOBUFS;
+	}
+
+	req = net_buf_add(req_buf, sizeof(*req));
+
+	req->auth_req = get_auth(conn, BT_SMP_AUTH_DEFAULT);
+	req->io_capability = get_io_capa();
+	req->oob_flag = oobd_present ? BT_SMP_OOB_PRESENT :
+				       BT_SMP_OOB_NOT_PRESENT;
+	req->max_key_size = BT_SMP_MAX_ENC_KEY_SIZE;
+	req->init_key_dist = SEND_KEYS;
+	req->resp_key_dist = RECV_KEYS;
+
+	smp->local_dist = SEND_KEYS;
+	smp->remote_dist = RECV_KEYS;
+
+	/* Store req for later use */
+	smp->preq[0] = BT_SMP_CMD_PAIRING_REQ;
+	memcpy(smp->preq + 1, req, sizeof(*req));
+
+	smp_send(smp, req_buf, NULL, NULL);
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RSP);
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
+	atomic_set_bit(smp->flags, SMP_FLAG_PAIRING);
+
+	return 0;
+}
+
+static uint8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_pairing *rsp = (void *)buf->data;
+	struct bt_smp_pairing *req = (struct bt_smp_pairing *)&smp->preq[1];
+
+	BT_DBG("");
+
+	if ((rsp->max_key_size > BT_SMP_MAX_ENC_KEY_SIZE) ||
+	    (rsp->max_key_size < BT_SMP_MIN_ENC_KEY_SIZE)) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	smp->local_dist &= rsp->init_key_dist;
+	smp->remote_dist &= rsp->resp_key_dist;
+
+	/* Store rsp for later use */
+	smp->prsp[0] = BT_SMP_CMD_PAIRING_RSP;
+	memcpy(smp->prsp + 1, rsp, sizeof(*rsp));
+
+	if ((rsp->auth_req & BT_SMP_AUTH_SC) &&
+	    (req->auth_req & BT_SMP_AUTH_SC)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_SC);
+	}
+
+	if ((rsp->auth_req & BT_SMP_AUTH_CT2) &&
+	    (req->auth_req & BT_SMP_AUTH_CT2)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_CT2);
+	}
+
+	if ((rsp->auth_req & BT_SMP_AUTH_BONDING) &&
+	    (req->auth_req & BT_SMP_AUTH_BONDING)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_BOND);
+	} else if (IS_ENABLED(CONFIG_BT_BONDING_REQUIRED)) {
+		/* Reject pairing req if not both intend to bond */
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	smp->method = get_pair_method(smp, rsp->io_capability);
+
+	if (!update_keys_check(smp)) {
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+	}
+
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+#if defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+#else
+		if (IS_ENABLED(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)) {
+			uint8_t err;
+
+			err = smp_pairing_accept_query(smp->chan.chan.conn,
+						       rsp);
+			if (err) {
+				return err;
+			}
+		}
+
+		return legacy_pairing_rsp(smp);
+#endif /* CONFIG_BT_SMP_SC_PAIR_ONLY */
+	}
+
+	if ((IS_ENABLED(CONFIG_BT_SMP_SC_ONLY) ||
+	     conn->required_sec_level == BT_SECURITY_L4) &&
+	     smp->method == JUST_WORKS) {
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+	}
+
+	if ((IS_ENABLED(CONFIG_BT_SMP_SC_ONLY) ||
+	     conn->required_sec_level == BT_SECURITY_L4) &&
+	     get_encryption_key_size(smp) != BT_SMP_MAX_ENC_KEY_SIZE) {
+		return BT_SMP_ERR_ENC_KEY_SIZE;
+	}
+
+	smp->local_dist &= SEND_KEYS_SC;
+	smp->remote_dist &= RECV_KEYS_SC;
+
+	if (IS_ENABLED(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)) {
+		uint8_t err;
+
+		err = smp_pairing_accept_query(smp->chan.chan.conn, rsp);
+		if (err) {
+			return err;
+		}
+	}
+
+	if ((DISPLAY_FIXED(smp) || smp->method == JUST_WORKS) &&
+	    atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ) &&
+	    bt_auth && bt_auth->pairing_confirm) {
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->pairing_confirm(smp->chan.chan.conn);
+		return 0;
+	}
+
+	if (!sc_public_key) {
+		atomic_set_bit(smp->flags, SMP_FLAG_PKEY_SEND);
+		return 0;
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
+	atomic_clear_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
+
+	return sc_send_public_key(smp);
+}
+#else
+static uint8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+static uint8_t smp_pairing_confirm(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_smp_pairing_confirm *req = (void *)buf->data;
+
+	BT_DBG("");
+
+	atomic_clear_bit(smp->flags, SMP_FLAG_DISPLAY);
+
+	memcpy(smp->pcnf, req->val, sizeof(smp->pcnf));
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+		return smp_send_pairing_random(smp);
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		return 0;
+	}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		return legacy_pairing_confirm(smp);
+	}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+	switch (smp->method) {
+	case PASSKEY_DISPLAY:
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+		return smp_send_pairing_confirm(smp);
+	case PASSKEY_INPUT:
+		if (atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
+			atomic_set_bit(smp->flags, SMP_FLAG_CFM_DELAYED);
+			return 0;
+		}
+
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+		return smp_send_pairing_confirm(smp);
+	case JUST_WORKS:
+	case PASSKEY_CONFIRM:
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+}
+
+static uint8_t sc_smp_send_dhkey_check(struct bt_smp *smp, const uint8_t *e)
+{
+	struct bt_smp_dhkey_check *req;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = smp_create_pdu(smp, BT_SMP_DHKEY_CHECK, sizeof(*req));
+	if (!buf) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	req = net_buf_add(buf, sizeof(*req));
+	memcpy(req->e, e, sizeof(req->e));
+
+	smp_send(smp, buf, NULL, NULL);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static uint8_t compute_and_send_master_dhcheck(struct bt_smp *smp)
+{
+	uint8_t e[16], r[16];
+
+	(void)memset(r, 0, sizeof(r));
+
+	switch (smp->method) {
+	case JUST_WORKS:
+	case PASSKEY_CONFIRM:
+		break;
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+		memcpy(r, &smp->passkey, sizeof(smp->passkey));
+		break;
+	case LE_SC_OOB:
+		if (smp->oobd_remote) {
+			memcpy(r, smp->oobd_remote->r, sizeof(r));
+		}
+		break;
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	/* calculate LTK and mackey */
+	if (smp_f5(smp->dhkey, smp->prnd, smp->rrnd,
+		   &smp->chan.chan.conn->le.init_addr,
+		   &smp->chan.chan.conn->le.resp_addr, smp->mackey,
+		   smp->tk)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+	/* calculate local DHKey check */
+	if (smp_f6(smp->mackey, smp->prnd, smp->rrnd, r, &smp->preq[1],
+		   &smp->chan.chan.conn->le.init_addr,
+		   &smp->chan.chan.conn->le.resp_addr, e)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
+	return sc_smp_send_dhkey_check(smp, e);
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static uint8_t compute_and_check_and_send_slave_dhcheck(struct bt_smp *smp)
+{
+	uint8_t re[16], e[16], r[16];
+	uint8_t err;
+
+	(void)memset(r, 0, sizeof(r));
+
+	switch (smp->method) {
+	case JUST_WORKS:
+	case PASSKEY_CONFIRM:
+		break;
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+		memcpy(r, &smp->passkey, sizeof(smp->passkey));
+		break;
+	case LE_SC_OOB:
+		if (smp->oobd_remote) {
+			memcpy(r, smp->oobd_remote->r, sizeof(r));
+		}
+		break;
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	/* calculate LTK and mackey */
+	if (smp_f5(smp->dhkey, smp->rrnd, smp->prnd,
+		   &smp->chan.chan.conn->le.init_addr,
+		   &smp->chan.chan.conn->le.resp_addr, smp->mackey,
+		   smp->tk)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	/* calculate local DHKey check */
+	if (smp_f6(smp->mackey, smp->prnd, smp->rrnd, r, &smp->prsp[1],
+		   &smp->chan.chan.conn->le.resp_addr,
+		   &smp->chan.chan.conn->le.init_addr, e)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (smp->method == LE_SC_OOB) {
+		if (smp->oobd_local) {
+			memcpy(r, smp->oobd_local->r, sizeof(r));
+		} else {
+			memset(r, 0, sizeof(r));
+		}
+	}
+
+	/* calculate remote DHKey check */
+	if (smp_f6(smp->mackey, smp->rrnd, smp->prnd, r, &smp->preq[1],
+		   &smp->chan.chan.conn->le.init_addr,
+		   &smp->chan.chan.conn->le.resp_addr, re)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	/* compare received E with calculated remote */
+	if (memcmp(smp->e, re, 16)) {
+		return BT_SMP_ERR_DHKEY_CHECK_FAILED;
+	}
+
+	/* send local e */
+	err = sc_smp_send_dhkey_check(smp, e);
+	if (err) {
+		return err;
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+	return 0;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static void bt_smp_dhkey_ready(const uint8_t *dhkey)
+{
+	struct bt_smp *smp = NULL;
+	int i;
+
+	BT_DBG("%p", dhkey);
+
+	for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
+		if (atomic_test_and_clear_bit(bt_smp_pool[i].flags,
+					      SMP_FLAG_DHKEY_PENDING)) {
+			smp = &bt_smp_pool[i];
+			break;
+		}
+	}
+
+	if (!smp) {
+		return;
+	}
+
+	if (!dhkey) {
+		smp_error(smp, BT_SMP_ERR_DHKEY_CHECK_FAILED);
+		return;
+	}
+
+	memcpy(smp->dhkey, dhkey, 32);
+
+	/* wait for user passkey confirmation */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+		return;
+	}
+
+	/* wait for remote DHKey Check */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+		return;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_SEND)) {
+		uint8_t err;
+
+#if defined(CONFIG_BT_CENTRAL)
+		if (smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+			err = compute_and_send_master_dhcheck(smp);
+			if (err) {
+				smp_error(smp, err);
+			}
+
+			return;
+		}
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		err = compute_and_check_and_send_slave_dhcheck(smp);
+		if (err) {
+			smp_error(smp, err);
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+}
+
+static uint8_t sc_smp_check_confirm(struct bt_smp *smp)
+{
+	uint8_t cfm[16];
+	uint8_t r;
+
+	switch (smp->method) {
+	case LE_SC_OOB:
+		return 0;
+	case PASSKEY_CONFIRM:
+	case JUST_WORKS:
+		r = 0U;
+		break;
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+		/*
+		 * In the Passkey Entry protocol, the most significant
+		 * bit of Z is set equal to one and the least
+		 * significant bit is made up from one bit of the
+		 * passkey e.g. if the passkey bit is 1, then Z = 0x81
+		 * and if the passkey bit is 0, then Z = 0x80.
+		 */
+		r = (smp->passkey >> smp->passkey_round) & 0x01;
+		r |= 0x80;
+		break;
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (smp_f4(smp->pkey, sc_public_key, smp->rrnd, r, cfm)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	BT_DBG("pcnf %s", bt_hex(smp->pcnf, 16));
+	BT_DBG("cfm %s", bt_hex(cfm, 16));
+
+	if (memcmp(smp->pcnf, cfm, 16)) {
+		return BT_SMP_ERR_CONFIRM_FAILED;
+	}
+
+	return 0;
+}
+
+static bool le_sc_oob_data_req_check(struct bt_smp *smp)
+{
+	struct bt_smp_pairing *req = (struct bt_smp_pairing *)&smp->preq[1];
+
+	return ((req->oob_flag & BT_SMP_OOB_DATA_MASK) == BT_SMP_OOB_PRESENT);
+}
+
+static bool le_sc_oob_data_rsp_check(struct bt_smp *smp)
+{
+	struct bt_smp_pairing *rsp = (struct bt_smp_pairing *)&smp->prsp[1];
+
+	return ((rsp->oob_flag & BT_SMP_OOB_DATA_MASK) == BT_SMP_OOB_PRESENT);
+}
+
+static void le_sc_oob_config_set(struct bt_smp *smp,
+				 struct bt_conn_oob_info *info)
+{
+	bool req_oob_present = le_sc_oob_data_req_check(smp);
+	bool rsp_oob_present = le_sc_oob_data_rsp_check(smp);
+	int oob_config = BT_CONN_OOB_NO_DATA;
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		oob_config = req_oob_present ? BT_CONN_OOB_REMOTE_ONLY :
+					       BT_CONN_OOB_NO_DATA;
+
+		if (rsp_oob_present) {
+			oob_config = (oob_config == BT_CONN_OOB_REMOTE_ONLY) ?
+				     BT_CONN_OOB_BOTH_PEERS :
+				     BT_CONN_OOB_LOCAL_ONLY;
+		}
+	} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		oob_config = req_oob_present ? BT_CONN_OOB_LOCAL_ONLY :
+					       BT_CONN_OOB_NO_DATA;
+
+		if (rsp_oob_present) {
+			oob_config = (oob_config == BT_CONN_OOB_LOCAL_ONLY) ?
+				     BT_CONN_OOB_BOTH_PEERS :
+				     BT_CONN_OOB_REMOTE_ONLY;
+		}
+	}
+
+	info->lesc.oob_config = oob_config;
+}
+
+static uint8_t smp_pairing_random(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_smp_pairing_random *req = (void *)buf->data;
+	uint32_t passkey;
+	uint8_t err;
+
+	BT_DBG("");
+
+	memcpy(smp->rrnd, req->val, sizeof(smp->rrnd));
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		return legacy_pairing_random(smp);
+	}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+#if defined(CONFIG_BT_CENTRAL)
+	if (smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		err = sc_smp_check_confirm(smp);
+		if (err) {
+			return err;
+		}
+
+		switch (smp->method) {
+		case PASSKEY_CONFIRM:
+			/* compare passkey before calculating LTK */
+			if (smp_g2(sc_public_key, smp->pkey, smp->prnd,
+				   smp->rrnd, &passkey)) {
+				return BT_SMP_ERR_UNSPECIFIED;
+			}
+
+			atomic_set_bit(smp->flags, SMP_FLAG_USER);
+			atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+			bt_auth->passkey_confirm(smp->chan.chan.conn, passkey);
+			return 0;
+		case JUST_WORKS:
+			break;
+		case LE_SC_OOB:
+			break;
+		case PASSKEY_DISPLAY:
+		case PASSKEY_INPUT:
+			smp->passkey_round++;
+			if (smp->passkey_round == 20U) {
+				break;
+			}
+
+			if (bt_rand(smp->prnd, 16)) {
+				return BT_SMP_ERR_UNSPECIFIED;
+			}
+
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PAIRING_CONFIRM);
+			return smp_send_pairing_confirm(smp);
+		default:
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		/* wait for DHKey being generated */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_PENDING)) {
+			atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+			return 0;
+		}
+
+		return compute_and_send_master_dhcheck(smp);
+	}
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	switch (smp->method) {
+	case PASSKEY_CONFIRM:
+		if (smp_g2(smp->pkey, sc_public_key, smp->rrnd, smp->prnd,
+			   &passkey)) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->passkey_confirm(smp->chan.chan.conn, passkey);
+		break;
+	case JUST_WORKS:
+		break;
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+		err = sc_smp_check_confirm(smp);
+		if (err) {
+			return err;
+		}
+
+		atomic_set_bit(&smp->allowed_cmds,
+			       BT_SMP_CMD_PAIRING_CONFIRM);
+		err = smp_send_pairing_random(smp);
+		if (err) {
+			return err;
+		}
+
+		smp->passkey_round++;
+		if (smp->passkey_round == 20U) {
+			atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
+			atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
+			return 0;
+		}
+
+		if (bt_rand(smp->prnd, 16)) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		return 0;
+	case LE_SC_OOB:
+		/* Step 6: Select random N */
+		if (bt_rand(smp->prnd, 16)) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		if (bt_auth && bt_auth->oob_data_request) {
+			struct bt_conn_oob_info info = {
+				.type = BT_CONN_OOB_LE_SC,
+				.lesc.oob_config = BT_CONN_OOB_NO_DATA,
+			};
+
+			le_sc_oob_config_set(smp, &info);
+
+			smp->oobd_local = NULL;
+			smp->oobd_remote = NULL;
+
+			atomic_set_bit(smp->flags, SMP_FLAG_OOB_PENDING);
+			bt_auth->oob_data_request(smp->chan.chan.conn, &info);
+
+			return 0;
+		} else {
+			return BT_SMP_ERR_OOB_NOT_AVAIL;
+		}
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
+	atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
+	return smp_send_pairing_random(smp);
+#else
+	return BT_SMP_ERR_PAIRING_NOTSUPP;
+#endif /* CONFIG_BT_PERIPHERAL */
+}
+
+static uint8_t smp_pairing_failed(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_pairing_fail *req = (void *)buf->data;
+
+	BT_ERR("reason 0x%x", req->reason);
+
+	if (atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER) ||
+	    atomic_test_and_clear_bit(smp->flags, SMP_FLAG_DISPLAY)) {
+		if (bt_auth && bt_auth->cancel) {
+			bt_auth->cancel(conn);
+		}
+	}
+
+	smp_pairing_complete(smp, req->reason);
+
+	/* return no error to avoid sending Pairing Failed in response */
+	return 0;
+}
+
+static uint8_t smp_ident_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	BT_DBG("");
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+		struct bt_smp_ident_info *req = (void *)buf->data;
+		struct bt_conn *conn = smp->chan.chan.conn;
+		struct bt_keys *keys;
+
+		keys = bt_keys_get_type(BT_KEYS_IRK, conn->id, &conn->le.dst);
+		if (!keys) {
+			BT_ERR("Unable to get keys for %s",
+			       bt_addr_le_str(&conn->le.dst));
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		memcpy(keys->irk.val, req->irk, 16);
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_ADDR_INFO);
+
+	return 0;
+}
+
+static uint8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_ident_addr_info *req = (void *)buf->data;
+	uint8_t err;
+
+	BT_DBG("identity %s", bt_addr_le_str(&req->addr));
+
+	if (!bt_addr_le_is_identity(&req->addr)) {
+		BT_ERR("Invalid identity %s", bt_addr_le_str(&req->addr));
+		BT_ERR(" for %s", bt_addr_le_str(&conn->le.dst));
+		return BT_SMP_ERR_INVALID_PARAMS;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+		const bt_addr_le_t *dst;
+		struct bt_keys *keys;
+
+		keys = bt_keys_get_type(BT_KEYS_IRK, conn->id, &conn->le.dst);
+		if (!keys) {
+			BT_ERR("Unable to get keys for %s",
+			       bt_addr_le_str(&conn->le.dst));
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		/*
+		 * We can't use conn->dst here as this might already contain
+		 * identity address known from previous pairing. Since all keys
+		 * are cleared on re-pairing we wouldn't store IRK distributed
+		 * in new pairing.
+		 */
+		if (conn->role == BT_HCI_ROLE_MASTER) {
+			dst = &conn->le.resp_addr;
+		} else {
+			dst = &conn->le.init_addr;
+		}
+
+		if (bt_addr_le_is_rpa(dst)) {
+			/* always update last use RPA */
+			bt_addr_copy(&keys->irk.rpa, &dst->a);
+
+			/*
+			 * Update connection address and notify about identity
+			 * resolved only if connection wasn't already reported
+			 * with identity address. This may happen if IRK was
+			 * present before ie. due to re-pairing.
+			 */
+			if (!bt_addr_le_is_identity(&conn->le.dst)) {
+				bt_addr_le_copy(&keys->addr, &req->addr);
+				bt_addr_le_copy(&conn->le.dst, &req->addr);
+
+				bt_conn_identity_resolved(conn);
+			}
+		}
+
+		bt_id_add(keys);
+	}
+
+	smp->remote_dist &= ~BT_SMP_DIST_ID_KEY;
+
+	if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
+		err = bt_smp_distribute_keys(smp);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_complete(smp, 0);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_SIGNING)
+static uint8_t smp_signing_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	uint8_t err;
+
+	BT_DBG("");
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+		struct bt_smp_signing_info *req = (void *)buf->data;
+		struct bt_keys *keys;
+
+		keys = bt_keys_get_type(BT_KEYS_REMOTE_CSRK, conn->id,
+					&conn->le.dst);
+		if (!keys) {
+			BT_ERR("Unable to get keys for %s",
+			       bt_addr_le_str(&conn->le.dst));
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		memcpy(keys->remote_csrk.val, req->csrk,
+		       sizeof(keys->remote_csrk.val));
+	}
+
+	smp->remote_dist &= ~BT_SMP_DIST_SIGN;
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER && !smp->remote_dist) {
+		err = bt_smp_distribute_keys(smp);
+		if (err) {
+			return err;
+		}
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_complete(smp, 0);
+	}
+
+	return 0;
+}
+#else
+static uint8_t smp_signing_info(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* CONFIG_BT_SIGNING */
+
+#if defined(CONFIG_BT_CENTRAL)
+static uint8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_conn *conn = smp->chan.chan.conn;
+	struct bt_smp_security_request *req = (void *)buf->data;
+	uint8_t auth;
+
+	BT_DBG("");
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		/* We have already started pairing process */
+		return 0;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
+		/* We have already started encryption procedure */
+		return 0;
+	}
+
+	if (sc_supported) {
+		auth = req->auth_req & BT_SMP_AUTH_MASK_SC;
+	} else {
+		auth = req->auth_req & BT_SMP_AUTH_MASK;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_SC_PAIR_ONLY) &&
+	    !(auth & BT_SMP_AUTH_SC)) {
+		return BT_SMP_ERR_AUTH_REQUIREMENTS;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_BONDING_REQUIRED) &&
+	    !(bondable && (auth & BT_SMP_AUTH_BONDING))) {
+		/* Reject security req if not both intend to bond */
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (conn->le.keys) {
+		/* Make sure we have an LTK to encrypt with */
+		if (!(conn->le.keys->keys & (BT_KEYS_LTK_P256 | BT_KEYS_LTK))) {
+			goto pair;
+		}
+	} else {
+		conn->le.keys = bt_keys_find(BT_KEYS_LTK_P256, conn->id,
+					     &conn->le.dst);
+		if (!conn->le.keys) {
+			conn->le.keys = bt_keys_find(BT_KEYS_LTK, conn->id,
+						     &conn->le.dst);
+		}
+	}
+
+	if (!conn->le.keys) {
+		goto pair;
+	}
+
+	/* if MITM required key must be authenticated */
+	if ((auth & BT_SMP_AUTH_MITM) &&
+	    !(conn->le.keys->flags & BT_KEYS_AUTHENTICATED)) {
+		if (get_io_capa() != BT_SMP_IO_NO_INPUT_OUTPUT) {
+			BT_INFO("New auth requirements: 0x%x, repairing",
+				auth);
+			goto pair;
+		}
+
+		BT_WARN("Unsupported auth requirements: 0x%x, repairing",
+			auth);
+		goto pair;
+	}
+
+	/* if LE SC required and no p256 key present repair */
+	if ((auth & BT_SMP_AUTH_SC) &&
+	    !(conn->le.keys->keys & BT_KEYS_LTK_P256)) {
+		BT_INFO("New auth requirements: 0x%x, repairing", auth);
+		goto pair;
+	}
+
+	if (bt_conn_le_start_encryption(conn, conn->le.keys->ltk.rand,
+					conn->le.keys->ltk.ediv,
+					conn->le.keys->ltk.val,
+					conn->le.keys->enc_size) < 0) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+
+	return 0;
+pair:
+	if (smp_send_pairing_req(conn) < 0) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_SEC_REQ);
+
+	return 0;
+}
+#else
+static uint8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
+{
+	return BT_SMP_ERR_CMD_NOTSUPP;
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+static uint8_t generate_dhkey(struct bt_smp *smp)
+{
+	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	if (bt_dh_key_gen(smp->pkey, bt_smp_dhkey_ready)) {
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_PENDING);
+	return 0;
+}
+
+static uint8_t display_passkey(struct bt_smp *smp)
+{
+	if (IS_ENABLED(CONFIG_BT_FIXED_PASSKEY) &&
+	    fixed_passkey != BT_PASSKEY_INVALID) {
+		smp->passkey = fixed_passkey;
+	} else {
+		if (bt_rand(&smp->passkey, sizeof(smp->passkey))) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		smp->passkey %= 1000000;
+	}
+
+	smp->passkey_round = 0U;
+
+	if (bt_auth && bt_auth->passkey_display) {
+		atomic_set_bit(smp->flags, SMP_FLAG_DISPLAY);
+		bt_auth->passkey_display(smp->chan.chan.conn, smp->passkey);
+	}
+
+	smp->passkey = sys_cpu_to_le32(smp->passkey);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static uint8_t smp_public_key_slave(struct bt_smp *smp)
+{
+	uint8_t err;
+
+	err = sc_send_public_key(smp);
+	if (err) {
+		return err;
+	}
+
+	switch (smp->method) {
+	case PASSKEY_CONFIRM:
+	case JUST_WORKS:
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+
+		err = smp_send_pairing_confirm(smp);
+		if (err) {
+			return err;
+		}
+		break;
+	case PASSKEY_DISPLAY:
+		err = display_passkey(smp);
+		if (err) {
+			return err;
+		}
+
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		break;
+	case PASSKEY_INPUT:
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		atomic_set_bit(smp->flags, SMP_FLAG_USER);
+		bt_auth->passkey_entry(smp->chan.chan.conn);
+		break;
+	case LE_SC_OOB:
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+		break;
+	default:
+		return BT_SMP_ERR_UNSPECIFIED;
+	}
+
+	return generate_dhkey(smp);
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+static uint8_t smp_public_key(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_smp_public_key *req = (void *)buf->data;
+	uint8_t err;
+
+	BT_DBG("");
+
+	memcpy(smp->pkey, req->x, 32);
+	memcpy(&smp->pkey[32], req->y, 32);
+
+	/* mark key as debug if remote is using it */
+	if (memcmp(smp->pkey, sc_debug_public_key, 64) == 0) {
+		BT_INFO("Remote is using Debug Public key");
+		atomic_set_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY);
+
+		/* Don't allow a bond established without debug key to be
+		 * updated using LTK generated from debug key.
+		 */
+		if (!update_debug_keys_check(smp)) {
+			return BT_SMP_ERR_AUTH_REQUIREMENTS;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		switch (smp->method) {
+		case PASSKEY_CONFIRM:
+		case JUST_WORKS:
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PAIRING_CONFIRM);
+			break;
+		case PASSKEY_DISPLAY:
+			err = display_passkey(smp);
+			if (err) {
+				return err;
+			}
+
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PAIRING_CONFIRM);
+
+			err = smp_send_pairing_confirm(smp);
+			if (err) {
+				return err;
+			}
+			break;
+		case PASSKEY_INPUT:
+			atomic_set_bit(smp->flags, SMP_FLAG_USER);
+			bt_auth->passkey_entry(smp->chan.chan.conn);
+			break;
+		case LE_SC_OOB:
+			/* Step 6: Select random N */
+			if (bt_rand(smp->prnd, 16)) {
+				return BT_SMP_ERR_UNSPECIFIED;
+			}
+
+			if (bt_auth && bt_auth->oob_data_request) {
+				struct bt_conn_oob_info info = {
+					.type = BT_CONN_OOB_LE_SC,
+					.lesc.oob_config = BT_CONN_OOB_NO_DATA,
+				};
+
+				le_sc_oob_config_set(smp, &info);
+
+				smp->oobd_local = NULL;
+				smp->oobd_remote = NULL;
+
+				atomic_set_bit(smp->flags,
+					       SMP_FLAG_OOB_PENDING);
+				bt_auth->oob_data_request(smp->chan.chan.conn,
+							  &info);
+			} else {
+				return BT_SMP_ERR_OOB_NOT_AVAIL;
+			}
+			break;
+		default:
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		return generate_dhkey(smp);
+	}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!sc_public_key) {
+		atomic_set_bit(smp->flags, SMP_FLAG_PKEY_SEND);
+		return 0;
+	}
+
+	err = smp_public_key_slave(smp);
+	if (err) {
+		return err;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return 0;
+}
+
+static uint8_t smp_dhkey_check(struct bt_smp *smp, struct net_buf *buf)
+{
+	struct bt_smp_dhkey_check *req = (void *)buf->data;
+
+	BT_DBG("");
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		uint8_t e[16], r[16], enc_size;
+		uint8_t ediv[2], rand[8];
+
+		(void)memset(r, 0, sizeof(r));
+
+		switch (smp->method) {
+		case JUST_WORKS:
+		case PASSKEY_CONFIRM:
+			break;
+		case PASSKEY_DISPLAY:
+		case PASSKEY_INPUT:
+			memcpy(r, &smp->passkey, sizeof(smp->passkey));
+			break;
+		case LE_SC_OOB:
+			if (smp->oobd_local) {
+				memcpy(r, smp->oobd_local->r, sizeof(r));
+			}
+			break;
+		default:
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		/* calculate remote DHKey check for comparison */
+		if (smp_f6(smp->mackey, smp->rrnd, smp->prnd, r, &smp->prsp[1],
+			   &smp->chan.chan.conn->le.resp_addr,
+			   &smp->chan.chan.conn->le.init_addr, e)) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		if (memcmp(e, req->e, 16)) {
+			return BT_SMP_ERR_DHKEY_CHECK_FAILED;
+		}
+
+		enc_size = get_encryption_key_size(smp);
+
+		/* Rand and EDiv are 0 */
+		(void)memset(ediv, 0, sizeof(ediv));
+		(void)memset(rand, 0, sizeof(rand));
+		if (bt_conn_le_start_encryption(smp->chan.chan.conn, rand, ediv,
+						smp->tk, enc_size) < 0) {
+			return BT_SMP_ERR_UNSPECIFIED;
+		}
+
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+
+		if (IS_ENABLED(CONFIG_BT_SMP_USB_HCI_CTLR_WORKAROUND)) {
+			if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+				atomic_set_bit(&smp->allowed_cmds,
+					       BT_SMP_CMD_IDENT_INFO);
+			} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+				atomic_set_bit(&smp->allowed_cmds,
+					       BT_SMP_CMD_SIGNING_INFO);
+			}
+		}
+
+		return 0;
+	}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (smp->chan.chan.conn->role == BT_HCI_ROLE_SLAVE) {
+		atomic_clear_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
+		memcpy(smp->e, req->e, sizeof(smp->e));
+
+		/* wait for DHKey being generated */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_PENDING)) {
+			atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+			return 0;
+		}
+
+		/* waiting for user to confirm passkey */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
+			atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+			return 0;
+		}
+
+		return compute_and_check_and_send_slave_dhcheck(smp);
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return 0;
+}
+
+static const struct {
+	uint8_t  (*func)(struct bt_smp *smp, struct net_buf *buf);
+	uint8_t  expect_len;
+} handlers[] = {
+	{ }, /* No op-code defined for 0x00 */
+	{ smp_pairing_req,         sizeof(struct bt_smp_pairing) },
+	{ smp_pairing_rsp,         sizeof(struct bt_smp_pairing) },
+	{ smp_pairing_confirm,     sizeof(struct bt_smp_pairing_confirm) },
+	{ smp_pairing_random,      sizeof(struct bt_smp_pairing_random) },
+	{ smp_pairing_failed,      sizeof(struct bt_smp_pairing_fail) },
+	{ smp_encrypt_info,        sizeof(struct bt_smp_encrypt_info) },
+	{ smp_master_ident,        sizeof(struct bt_smp_master_ident) },
+	{ smp_ident_info,          sizeof(struct bt_smp_ident_info) },
+	{ smp_ident_addr_info,     sizeof(struct bt_smp_ident_addr_info) },
+	{ smp_signing_info,        sizeof(struct bt_smp_signing_info) },
+	{ smp_security_request,    sizeof(struct bt_smp_security_request) },
+	{ smp_public_key,          sizeof(struct bt_smp_public_key) },
+	{ smp_dhkey_check,         sizeof(struct bt_smp_dhkey_check) },
+};
+
+static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
+	struct bt_smp_hdr *hdr;
+	uint8_t err;
+
+	if (buf->len < sizeof(*hdr)) {
+		BT_ERR("Too small SMP PDU received");
+		return 0;
+	}
+
+	hdr = net_buf_pull_mem(buf, sizeof(*hdr));
+	BT_DBG("Received SMP code 0x%02x len %u", hdr->code, buf->len);
+
+	/*
+	 * If SMP timeout occurred "no further SMP commands shall be sent over
+	 * the L2CAP Security Manager Channel. A new SM procedure shall only be
+	 * performed when a new physical link has been established."
+	 */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_TIMEOUT)) {
+		BT_WARN("SMP command (code 0x%02x) received after timeout",
+			hdr->code);
+		return 0;
+	}
+
+	if (hdr->code >= ARRAY_SIZE(handlers) || !handlers[hdr->code].func) {
+		BT_WARN("Unhandled SMP code 0x%02x", hdr->code);
+		smp_error(smp, BT_SMP_ERR_CMD_NOTSUPP);
+		return 0;
+	}
+
+	if (!atomic_test_and_clear_bit(&smp->allowed_cmds, hdr->code)) {
+		BT_WARN("Unexpected SMP code 0x%02x", hdr->code);
+		/* Don't send error responses to error PDUs */
+		if (hdr->code != BT_SMP_CMD_PAIRING_FAIL) {
+			smp_error(smp, BT_SMP_ERR_UNSPECIFIED);
+		}
+		return 0;
+	}
+
+	if (buf->len != handlers[hdr->code].expect_len) {
+		BT_ERR("Invalid len %u for code 0x%02x", buf->len, hdr->code);
+		smp_error(smp, BT_SMP_ERR_INVALID_PARAMS);
+		return 0;
+	}
+
+	err = handlers[hdr->code].func(smp, buf);
+	if (err) {
+		smp_error(smp, err);
+	}
+
+	return 0;
+}
+
+static void bt_smp_pkey_ready(const uint8_t *pkey)
+{
+	int i;
+
+	BT_DBG("");
+
+	sc_public_key = pkey;
+
+	if (!pkey) {
+		BT_WARN("Public key not available");
+		return;
+	}
+
+	k_sem_give(&sc_local_pkey_ready);
+
+	for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
+		struct bt_smp *smp = &bt_smp_pool[i];
+		uint8_t err;
+
+		if (!atomic_test_bit(smp->flags, SMP_FLAG_PKEY_SEND)) {
+			continue;
+		}
+
+		if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+		    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+			err = sc_send_public_key(smp);
+			if (err) {
+				smp_error(smp, err);
+			}
+
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PUBLIC_KEY);
+			continue;
+		}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		err = smp_public_key_slave(smp);
+		if (err) {
+			smp_error(smp, err);
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+}
+
+static void bt_smp_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
+
+	BT_DBG("chan %p cid 0x%04x", chan,
+	       CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan)->tx.cid);
+
+	k_delayed_work_init(&smp->work, smp_timeout);
+	smp_reset(smp);
+}
+
+static void bt_smp_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
+	struct bt_keys *keys = chan->conn->le.keys;
+
+	BT_DBG("chan %p cid 0x%04x", chan,
+	       CONTAINER_OF(chan, struct bt_l2cap_le_chan, chan)->tx.cid);
+
+	k_delayed_work_cancel(&smp->work);
+
+	if (keys) {
+		/*
+		 * If debug keys were used for pairing remove them.
+		 * No keys indicate no bonding so free keys storage.
+		 */
+		if (!keys->keys || (!IS_ENABLED(CONFIG_BT_STORE_DEBUG_KEYS) &&
+		    (keys->flags & BT_KEYS_DEBUG))) {
+			bt_keys_clear(keys);
+		}
+	}
+
+	(void)memset(smp, 0, sizeof(*smp));
+}
+
+static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
+				  uint8_t hci_status)
+{
+	struct bt_smp *smp = CONTAINER_OF(chan, struct bt_smp, chan);
+	struct bt_conn *conn = chan->conn;
+
+	BT_DBG("chan %p conn %p handle %u encrypt 0x%02x hci status 0x%02x",
+	       chan, conn, conn->handle, conn->encrypt, hci_status);
+
+	atomic_clear_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+
+	if (hci_status) {
+		return;
+	}
+
+	if (!conn->encrypt) {
+		return;
+	}
+
+	/* We were waiting for encryption but with no pairing in progress.
+	 * This can happen if paired slave sent Security Request and we
+	 * enabled encryption.
+	 */
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		smp_reset(smp);
+		return;
+	}
+
+	/* derive BR/EDR LinkKey if supported by both sides */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		if ((smp->local_dist & BT_SMP_DIST_LINK_KEY) &&
+		    (smp->remote_dist & BT_SMP_DIST_LINK_KEY)) {
+			/*
+			 * Link Key will be derived after key distribution to
+			 * make sure remote device identity is known
+			 */
+			atomic_set_bit(smp->flags, SMP_FLAG_DERIVE_LK);
+		}
+		/*
+		 * Those are used as pairing finished indicator so generated
+		 * but not distributed keys must be cleared here.
+		 */
+		smp->local_dist &= ~BT_SMP_DIST_LINK_KEY;
+		smp->remote_dist &= ~BT_SMP_DIST_LINK_KEY;
+	}
+
+	if (smp->remote_dist & BT_SMP_DIST_ENC_KEY) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_ENCRYPT_INFO);
+	} else if (smp->remote_dist & BT_SMP_DIST_ID_KEY) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_IDENT_INFO);
+	} else if (smp->remote_dist & BT_SMP_DIST_SIGN) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SIGNING_INFO);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    IS_ENABLED(CONFIG_BT_PRIVACY) &&
+	    !(smp->remote_dist & BT_SMP_DIST_ID_KEY)) {
+		/* To resolve directed advertising we need our local IRK
+		 * in the controllers resolving list, add it now since the
+		 * peer has no identity key.
+		 */
+		bt_id_add(conn->le.keys);
+	}
+
+	atomic_set_bit(smp->flags, SMP_FLAG_KEYS_DISTR);
+
+	/* Slave distributes it's keys first */
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_HCI_ROLE_MASTER && smp->remote_dist) {
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_TESTING)) {
+		/* Avoid the HCI-USB race condition where HCI data and
+		 * HCI events can be re-ordered, and pairing information appears
+		 * to be sent unencrypted.
+		 */
+		k_sleep(K_MSEC(100));
+	}
+
+	if (bt_smp_distribute_keys(smp)) {
+		return;
+	}
+
+	/* if all keys were distributed, pairing is done */
+	if (!smp->local_dist && !smp->remote_dist) {
+		smp_pairing_complete(smp, 0);
+	}
+}
+
+#if defined(CONFIG_BT_SIGNING) || defined(CONFIG_BT_SMP_SELFTEST)
+/* Sign message using msg as a buffer, len is a size of the message,
+ * msg buffer contains message itself, 32 bit count and signature,
+ * so total buffer size is len + 4 + 8 octets.
+ * API is Little Endian to make it suitable for Bluetooth.
+ */
+static int smp_sign_buf(const uint8_t *key, uint8_t *msg, uint16_t len)
+{
+	uint8_t *m = msg;
+	uint32_t cnt = UNALIGNED_GET((uint32_t *)&msg[len]);
+	uint8_t *sig = msg + len;
+	uint8_t key_s[16], tmp[16];
+	int err;
+
+	BT_DBG("Signing msg %s len %u key %s", bt_hex(msg, len), len,
+	       bt_hex(key, 16));
+
+	sys_mem_swap(m, len + sizeof(cnt));
+	sys_memcpy_swap(key_s, key, 16);
+
+	err = bt_smp_aes_cmac(key_s, m, len + sizeof(cnt), tmp);
+	if (err) {
+		BT_ERR("Data signing failed");
+		return err;
+	}
+
+	sys_mem_swap(tmp, sizeof(tmp));
+	memcpy(tmp + 4, &cnt, sizeof(cnt));
+
+	/* Swap original message back */
+	sys_mem_swap(m, len + sizeof(cnt));
+
+	memcpy(sig, tmp + 4, 12);
+
+	BT_DBG("sig %s", bt_hex(sig, 12));
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_BT_SIGNING)
+int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct bt_keys *keys;
+	uint8_t sig[12];
+	uint32_t cnt;
+	int err;
+
+	/* Store signature incl. count */
+	memcpy(sig, net_buf_tail(buf) - sizeof(sig), sizeof(sig));
+
+	keys = bt_keys_find(BT_KEYS_REMOTE_CSRK, conn->id, &conn->le.dst);
+	if (!keys) {
+		BT_ERR("Unable to find Remote CSRK for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		return -ENOENT;
+	}
+
+	/* Copy signing count */
+	cnt = sys_cpu_to_le32(keys->remote_csrk.cnt);
+	memcpy(net_buf_tail(buf) - sizeof(sig), &cnt, sizeof(cnt));
+
+	BT_DBG("Sign data len %zu key %s count %u", buf->len - sizeof(sig),
+	       bt_hex(keys->remote_csrk.val, 16), keys->remote_csrk.cnt);
+
+	err = smp_sign_buf(keys->remote_csrk.val, buf->data,
+			   buf->len - sizeof(sig));
+	if (err) {
+		BT_ERR("Unable to create signature for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		return -EIO;
+	};
+
+	if (memcmp(sig, net_buf_tail(buf) - sizeof(sig), sizeof(sig))) {
+		BT_ERR("Unable to verify signature for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		return -EBADMSG;
+	};
+
+	keys->remote_csrk.cnt++;
+
+	return 0;
+}
+
+int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
+{
+	struct bt_keys *keys;
+	uint32_t cnt;
+	int err;
+
+	keys = bt_keys_find(BT_KEYS_LOCAL_CSRK, conn->id, &conn->le.dst);
+	if (!keys) {
+		BT_ERR("Unable to find local CSRK for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		return -ENOENT;
+	}
+
+	/* Reserve space for data signature */
+	net_buf_add(buf, 12);
+
+	/* Copy signing count */
+	cnt = sys_cpu_to_le32(keys->local_csrk.cnt);
+	memcpy(net_buf_tail(buf) - 12, &cnt, sizeof(cnt));
+
+	BT_DBG("Sign data len %u key %s count %u", buf->len,
+	       bt_hex(keys->local_csrk.val, 16), keys->local_csrk.cnt);
+
+	err = smp_sign_buf(keys->local_csrk.val, buf->data, buf->len - 12);
+	if (err) {
+		BT_ERR("Unable to create signature for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		return -EIO;
+	}
+
+	keys->local_csrk.cnt++;
+
+	return 0;
+}
+#else
+int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf)
+{
+	return -ENOTSUP;
+}
+
+int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
+{
+	return -ENOTSUP;
+}
+#endif /* CONFIG_BT_SIGNING */
+
+int bt_smp_irk_get(uint8_t *ir, uint8_t *irk)
+{
+	uint8_t invalid_ir[16] = { 0 };
+
+	if (!memcmp(ir, invalid_ir, 16)) {
+		return -EINVAL;
+	}
+
+	return smp_d1(ir, 1, 0, irk);
+}
+
+#if defined(CONFIG_BT_SMP_SELFTEST)
+/* Test vectors are taken from RFC 4493
+ * https://tools.ietf.org/html/rfc4493
+ * Same mentioned in the Bluetooth Spec.
+ */
+static const uint8_t key[] = {
+	0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+	0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+
+static const uint8_t M[] = {
+	0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+	0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+	0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+	0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+	0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+	0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+	0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+	0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+
+static int aes_test(const char *prefix, const uint8_t *key, const uint8_t *m,
+		    uint16_t len, const uint8_t *mac)
+{
+	uint8_t out[16];
+
+	BT_DBG("%s: AES CMAC of message with len %u", prefix, len);
+
+	bt_smp_aes_cmac(key, m, len, out);
+	if (!memcmp(out, mac, 16)) {
+		BT_DBG("%s: Success", prefix);
+	} else {
+		BT_ERR("%s: Failed", prefix);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int smp_aes_cmac_test(void)
+{
+	uint8_t mac1[] = {
+		0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+		0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+	};
+	uint8_t mac2[] = {
+		0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+		0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+	};
+	uint8_t mac3[] = {
+		0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+		0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
+	};
+	uint8_t mac4[] = {
+		0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+		0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+	};
+	int err;
+
+	err = aes_test("Test aes-cmac0", key, M, 0, mac1);
+	if (err) {
+		return err;
+	}
+
+	err = aes_test("Test aes-cmac16", key, M, 16, mac2);
+	if (err) {
+		return err;
+	}
+
+	err = aes_test("Test aes-cmac40", key, M, 40, mac3);
+	if (err) {
+		return err;
+	}
+
+	err = aes_test("Test aes-cmac64", key, M, 64, mac4);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int sign_test(const char *prefix, const uint8_t *key, const uint8_t *m,
+		     uint16_t len, const uint8_t *sig)
+{
+	uint8_t msg[len + sizeof(uint32_t) + 8];
+	uint8_t orig[len + sizeof(uint32_t) + 8];
+	uint8_t *out = msg + len;
+	int err;
+
+	BT_DBG("%s: Sign message with len %u", prefix, len);
+
+	(void)memset(msg, 0, sizeof(msg));
+	memcpy(msg, m, len);
+	(void)memset(msg + len, 0, sizeof(uint32_t));
+
+	memcpy(orig, msg, sizeof(msg));
+
+	err = smp_sign_buf(key, msg, len);
+	if (err) {
+		return err;
+	}
+
+	/* Check original message */
+	if (!memcmp(msg, orig, len + sizeof(uint32_t))) {
+		BT_DBG("%s: Original message intact", prefix);
+	} else {
+		BT_ERR("%s: Original message modified", prefix);
+		BT_DBG("%s: orig %s", prefix, bt_hex(orig, sizeof(orig)));
+		BT_DBG("%s: msg %s", prefix, bt_hex(msg, sizeof(msg)));
+		return -1;
+	}
+
+	if (!memcmp(out, sig, 12)) {
+		BT_DBG("%s: Success", prefix);
+	} else {
+		BT_ERR("%s: Failed", prefix);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int smp_sign_test(void)
+{
+	const uint8_t sig1[] = {
+		0x00, 0x00, 0x00, 0x00, 0xb3, 0xa8, 0x59, 0x41,
+		0x27, 0xeb, 0xc2, 0xc0
+	};
+	const uint8_t sig2[] = {
+		0x00, 0x00, 0x00, 0x00, 0x27, 0x39, 0x74, 0xf4,
+		0x39, 0x2a, 0x23, 0x2a
+	};
+	const uint8_t sig3[] = {
+		0x00, 0x00, 0x00, 0x00, 0xb7, 0xca, 0x94, 0xab,
+		0x87, 0xc7, 0x82, 0x18
+	};
+	const uint8_t sig4[] = {
+		0x00, 0x00, 0x00, 0x00, 0x44, 0xe1, 0xe6, 0xce,
+		0x1d, 0xf5, 0x13, 0x68
+	};
+	uint8_t key_s[16];
+	int err;
+
+	/* Use the same key as aes-cmac but swap bytes */
+	sys_memcpy_swap(key_s, key, 16);
+
+	err = sign_test("Test sign0", key_s, M, 0, sig1);
+	if (err) {
+		return err;
+	}
+
+	err = sign_test("Test sign16", key_s, M, 16, sig2);
+	if (err) {
+		return err;
+	}
+
+	err = sign_test("Test sign40", key_s, M, 40, sig3);
+	if (err) {
+		return err;
+	}
+
+	err = sign_test("Test sign64", key_s, M, 64, sig4);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int smp_f4_test(void)
+{
+	uint8_t u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
+			  0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
+			  0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+			  0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 };
+	uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+			  0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+			  0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+			  0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+	uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			  0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t z = 0x00;
+	uint8_t exp[16] = { 0x2d, 0x87, 0x74, 0xa9, 0xbe, 0xa1, 0xed, 0xf1,
+			    0x1c, 0xbd, 0xa9, 0x07, 0xf1, 0x16, 0xc9, 0xf2 };
+	uint8_t res[16];
+	int err;
+
+	err = smp_f4(u, v, x, z, res);
+	if (err) {
+		return err;
+	}
+
+	if (memcmp(res, exp, 16)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smp_f5_test(void)
+{
+	uint8_t w[32] = { 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86,
+			  0xf1, 0x66, 0xf8, 0xb4, 0x13, 0x6b, 0x79, 0x99,
+			  0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
+			  0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec };
+	uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			   0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			   0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+	bt_addr_le_t a1 = { .type = 0x00,
+			    .a.val = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 } };
+	bt_addr_le_t a2 = { .type = 0x00,
+			    .a.val = {0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 } };
+	uint8_t exp_ltk[16] = { 0x38, 0x0a, 0x75, 0x94, 0xb5, 0x22, 0x05,
+				0x98, 0x23, 0xcd, 0xd7, 0x69, 0x11, 0x79,
+				0x86, 0x69 };
+	uint8_t exp_mackey[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f,
+				   0xfd, 0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1,
+				   0x65, 0x29 };
+	uint8_t mackey[16], ltk[16];
+	int err;
+
+	err = smp_f5(w, n1, n2, &a1, &a2, mackey, ltk);
+	if (err) {
+		return err;
+	}
+
+	if (memcmp(mackey, exp_mackey, 16) || memcmp(ltk, exp_ltk, 16)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smp_f6_test(void)
+{
+	uint8_t w[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd,
+			  0x02, 0x4a, 0x08, 0xa1, 0x76, 0xf1, 0x65, 0x29 };
+	uint8_t n1[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			   0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t n2[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			   0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+	uint8_t r[16] = { 0xc8, 0x0f, 0x2d, 0x0c, 0xd2, 0x42, 0xda, 0x08,
+			  0x54, 0xbb, 0x53, 0xb4, 0x3b, 0x34, 0xa3, 0x12 };
+	uint8_t io_cap[3] = { 0x02, 0x01, 0x01 };
+	bt_addr_le_t a1 = { .type = 0x00,
+			    .a.val = { 0xce, 0xbf, 0x37, 0x37, 0x12, 0x56 } };
+	bt_addr_le_t a2 = { .type = 0x00,
+			    .a.val = {0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7 } };
+	uint8_t exp[16] = { 0x61, 0x8f, 0x95, 0xda, 0x09, 0x0b, 0x6c, 0xd2,
+			    0xc5, 0xe8, 0xd0, 0x9c, 0x98, 0x73, 0xc4, 0xe3 };
+	uint8_t res[16];
+	int err;
+
+	err = smp_f6(w, n1, n2, r, io_cap, &a1, &a2, res);
+	if (err)
+		return err;
+
+	if (memcmp(res, exp, 16))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int smp_g2_test(void)
+{
+	uint8_t u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
+			  0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
+			  0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
+			  0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20 };
+	uint8_t v[32] = { 0xfd, 0xc5, 0x7f, 0xf4, 0x49, 0xdd, 0x4f, 0x6b,
+			  0xfb, 0x7c, 0x9d, 0xf1, 0xc2, 0x9a, 0xcb, 0x59,
+			  0x2a, 0xe7, 0xd4, 0xee, 0xfb, 0xfc, 0x0a, 0x90,
+			  0x9a, 0xbb, 0xf6, 0x32, 0x3d, 0x8b, 0x18, 0x55 };
+	uint8_t x[16] = { 0xab, 0xae, 0x2b, 0x71, 0xec, 0xb2, 0xff, 0xff,
+			  0x3e, 0x73, 0x77, 0xd1, 0x54, 0x84, 0xcb, 0xd5 };
+	uint8_t y[16] = { 0xcf, 0xc4, 0x3d, 0xff, 0xf7, 0x83, 0x65, 0x21,
+			  0x6e, 0x5f, 0xa7, 0x25, 0xcc, 0xe7, 0xe8, 0xa6 };
+	uint32_t exp_val = 0x2f9ed5ba % 1000000;
+	uint32_t val;
+	int err;
+
+	err = smp_g2(u, v, x, y, &val);
+	if (err) {
+		return err;
+	}
+
+	if (val != exp_val) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_BREDR)
+static int smp_h6_test(void)
+{
+	uint8_t w[16] = { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
+			  0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec };
+	uint8_t key_id[4] = { 0x72, 0x62, 0x65, 0x6c };
+	uint8_t exp_res[16] = { 0x99, 0x63, 0xb1, 0x80, 0xe2, 0xa9, 0xd3, 0xe8,
+				0x1c, 0xc9, 0x6d, 0xe7, 0x02, 0xe1, 0x9a, 0x2d};
+	uint8_t res[16];
+	int err;
+
+	err = smp_h6(w, key_id, res);
+	if (err) {
+		return err;
+	}
+
+	if (memcmp(res, exp_res, 16)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smp_h7_test(void)
+{
+	uint8_t salt[16] = { 0x31, 0x70, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x00,
+			     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	uint8_t w[16] = { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
+			  0x05, 0xad, 0xc8, 0x57, 0xa3, 0x34, 0x02, 0xec };
+	uint8_t exp_res[16] = { 0x11, 0x70, 0xa5, 0x75, 0x2a, 0x8c, 0x99, 0xd2,
+				0xec, 0xc0, 0xa3, 0xc6, 0x97, 0x35, 0x17, 0xfb};
+	uint8_t res[16];
+	int err;
+
+	err = smp_h7(salt, w, res);
+	if (err) {
+		return err;
+	}
+
+	if (memcmp(res, exp_res, 16)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_BREDR */
+
+static int smp_self_test(void)
+{
+	int err;
+
+	err = smp_aes_cmac_test();
+	if (err) {
+		BT_ERR("SMP AES-CMAC self tests failed");
+		return err;
+	}
+
+	err = smp_sign_test();
+	if (err) {
+		BT_ERR("SMP signing self tests failed");
+		return err;
+	}
+
+	err = smp_f4_test();
+	if (err) {
+		BT_ERR("SMP f4 self test failed");
+		return err;
+	}
+
+	err = smp_f5_test();
+	if (err) {
+		BT_ERR("SMP f5 self test failed");
+		return err;
+	}
+
+	err = smp_f6_test();
+	if (err) {
+		BT_ERR("SMP f6 self test failed");
+		return err;
+	}
+
+	err = smp_g2_test();
+	if (err) {
+		BT_ERR("SMP g2 self test failed");
+		return err;
+	}
+
+#if defined(CONFIG_BT_BREDR)
+	err = smp_h6_test();
+	if (err) {
+		BT_ERR("SMP h6 self test failed");
+		return err;
+	}
+
+	err = smp_h7_test();
+	if (err) {
+		BT_ERR("SMP h7 self test failed");
+		return err;
+	}
+#endif /* CONFIG_BT_BREDR */
+
+	return 0;
+}
+#else
+static inline int smp_self_test(void)
+{
+	return 0;
+}
+#endif
+
+int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
+{
+	struct bt_smp *smp;
+	uint8_t err;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) {
+		return -EINVAL;
+	}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		legacy_passkey_entry(smp, passkey);
+		return 0;
+	}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+	smp->passkey = sys_cpu_to_le32(passkey);
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		err = smp_send_pairing_confirm(smp);
+		if (err) {
+			smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
+			return 0;
+		}
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_CONFIRM);
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
+	    atomic_test_bit(smp->flags, SMP_FLAG_CFM_DELAYED)) {
+		err = smp_send_pairing_confirm(smp);
+		if (err) {
+			smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
+			return 0;
+		}
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+	}
+
+	return 0;
+}
+
+int bt_smp_auth_passkey_confirm(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) {
+		return -EINVAL;
+	}
+
+	/* wait for DHKey being generated */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_PENDING)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+		return 0;
+	}
+
+	/* wait for remote DHKey Check */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT)) {
+		atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
+		return 0;
+	}
+
+	if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_SEND)) {
+		uint8_t err;
+
+#if defined(CONFIG_BT_CENTRAL)
+		if (smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+			err = compute_and_send_master_dhcheck(smp);
+			if (err) {
+				smp_error(smp, err);
+			}
+			return 0;
+		}
+#endif /* CONFIG_BT_CENTRAL */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+		err = compute_and_check_and_send_slave_dhcheck(smp);
+		if (err) {
+			smp_error(smp, err);
+		}
+#endif /* CONFIG_BT_PERIPHERAL */
+	}
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+int bt_smp_le_oob_set_tk(struct bt_conn *conn, const uint8_t *tk)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp || !tk) {
+		return -EINVAL;
+	}
+
+	BT_DBG("%s", bt_hex(tk, 16));
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) {
+		return -EINVAL;
+	}
+
+	memcpy(smp->tk, tk, 16*sizeof(uint8_t));
+
+	legacy_user_tk_entry(smp);
+
+	return 0;
+}
+#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
+
+int bt_smp_le_oob_generate_sc_data(struct bt_le_oob_sc_data *le_sc_oob)
+{
+	int err;
+
+	if (!le_sc_supported()) {
+		return -ENOTSUP;
+	}
+
+	if (!sc_public_key) {
+		err = k_sem_take(&sc_local_pkey_ready, K_FOREVER);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_OOB_DATA_FIXED)) {
+		uint8_t rand_num[] = {
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+		};
+
+		memcpy(le_sc_oob->r, rand_num, sizeof(le_sc_oob->r));
+	} else {
+		err = bt_rand(le_sc_oob->r, 16);
+		if (err) {
+			return err;
+		}
+	}
+
+	err = smp_f4(sc_public_key, sc_public_key, le_sc_oob->r, 0,
+		     le_sc_oob->c);
+	if (err) {
+		return err;
+	}
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+static bool le_sc_oob_data_check(struct bt_smp *smp, bool oobd_local_present,
+				 bool oobd_remote_present)
+{
+	bool req_oob_present = le_sc_oob_data_req_check(smp);
+	bool rsp_oob_present = le_sc_oob_data_rsp_check(smp);
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		if ((req_oob_present != oobd_remote_present) &&
+		    (rsp_oob_present != oobd_local_present)) {
+			return false;
+		}
+	} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		if ((req_oob_present != oobd_local_present) &&
+		    (rsp_oob_present != oobd_remote_present)) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int le_sc_oob_pairing_continue(struct bt_smp *smp)
+{
+	if (smp->oobd_remote) {
+		int err;
+		uint8_t c[16];
+
+		err = smp_f4(smp->pkey, smp->pkey, smp->oobd_remote->r, 0, c);
+		if (err) {
+			return err;
+		}
+
+		bool match = (memcmp(c, smp->oobd_remote->c, sizeof(c)) == 0);
+
+		if (!match) {
+			smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
+			return 0;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RANDOM);
+	} else if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_DHKEY_CHECK);
+		atomic_set_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT);
+	}
+
+	return smp_send_pairing_random(smp);
+}
+
+int bt_smp_le_oob_set_sc_data(struct bt_conn *conn,
+			      const struct bt_le_oob_sc_data *oobd_local,
+			      const struct bt_le_oob_sc_data *oobd_remote)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!le_sc_oob_data_check(smp, (oobd_local != NULL),
+				  (oobd_remote != NULL))) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_OOB_PENDING)) {
+		return -EINVAL;
+	}
+
+	smp->oobd_local = oobd_local;
+	smp->oobd_remote = oobd_remote;
+
+	return le_sc_oob_pairing_continue(smp);
+}
+
+int bt_smp_le_oob_get_sc_data(struct bt_conn *conn,
+			      const struct bt_le_oob_sc_data **oobd_local,
+			      const struct bt_le_oob_sc_data **oobd_remote)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!smp->oobd_local && !smp->oobd_remote) {
+		return -ESRCH;
+	}
+
+	if (oobd_local) {
+		*oobd_local = smp->oobd_local;
+	}
+
+	if (oobd_remote) {
+		*oobd_remote = smp->oobd_remote;
+	}
+
+	return 0;
+}
+#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
+
+int bt_smp_auth_cancel(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) {
+		return -EINVAL;
+	}
+
+	switch (smp->method) {
+	case PASSKEY_INPUT:
+	case PASSKEY_DISPLAY:
+		return smp_error(smp, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
+	case PASSKEY_CONFIRM:
+		return smp_error(smp, BT_SMP_ERR_CONFIRM_FAILED);
+	case LE_SC_OOB:
+	case LEGACY_OOB:
+		return smp_error(smp, BT_SMP_ERR_OOB_NOT_AVAIL);
+	case JUST_WORKS:
+		return smp_error(smp, BT_SMP_ERR_UNSPECIFIED);
+	default:
+		return 0;
+	}
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+int bt_smp_auth_pairing_confirm(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_USER)) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_CENTRAL) &&
+	    conn->role == BT_CONN_ROLE_MASTER) {
+		if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+			atomic_set_bit(&smp->allowed_cmds,
+				       BT_SMP_CMD_PAIRING_CONFIRM);
+			return legacy_send_pairing_confirm(smp);
+		}
+
+		if (!sc_public_key) {
+			atomic_set_bit(smp->flags, SMP_FLAG_PKEY_SEND);
+			return 0;
+		}
+
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
+		return sc_send_public_key(smp);
+	}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		atomic_set_bit(&smp->allowed_cmds,
+			       BT_SMP_CMD_PAIRING_CONFIRM);
+		return send_pairing_rsp(smp);
+	}
+
+	atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
+	if (send_pairing_rsp(smp)) {
+		return -EIO;
+	}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+	return 0;
+}
+#else
+int bt_smp_auth_pairing_confirm(struct bt_conn *conn)
+{
+	/* confirm_pairing will never be called in LE SC only mode */
+	return -EINVAL;
+}
+#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
+
+#if defined(CONFIG_BT_FIXED_PASSKEY)
+int bt_passkey_set(unsigned int passkey)
+{
+	if (passkey == BT_PASSKEY_INVALID) {
+		passkey = BT_PASSKEY_INVALID;
+		return 0;
+	}
+
+	if (passkey > 999999) {
+		return -EINVAL;
+	}
+
+	fixed_passkey = passkey;
+	return 0;
+}
+#endif /* CONFIG_BT_FIXED_PASSKEY */
+
+int bt_smp_start_security(struct bt_conn *conn)
+{
+	switch (conn->role) {
+#if defined(CONFIG_BT_CENTRAL)
+	case BT_HCI_ROLE_MASTER:
+	{
+		int err;
+		struct bt_smp *smp;
+
+		smp = smp_chan_get(conn);
+		if (!smp) {
+			return -ENOTCONN;
+		}
+
+		if (!smp_keys_check(conn)) {
+			return smp_send_pairing_req(conn);
+		}
+
+		/* pairing is in progress */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+			return -EBUSY;
+		}
+
+		/* Encryption is in progress */
+		if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
+			return -EBUSY;
+		}
+
+		/* LE SC LTK and legacy master LTK are stored in same place */
+		err = bt_conn_le_start_encryption(conn,
+						  conn->le.keys->ltk.rand,
+						  conn->le.keys->ltk.ediv,
+						  conn->le.keys->ltk.val,
+						  conn->le.keys->enc_size);
+		if (err) {
+			return err;
+		}
+
+		atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
+		atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
+		return 0;
+	}
+#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_SMP */
+#if defined(CONFIG_BT_PERIPHERAL)
+	case BT_HCI_ROLE_SLAVE:
+		return smp_send_security_req(conn);
+#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_SMP */
+	default:
+		return -EINVAL;
+	}
+}
+
+void bt_smp_update_keys(struct bt_conn *conn)
+{
+	struct bt_smp *smp;
+
+	smp = smp_chan_get(conn);
+	if (!smp) {
+		return;
+	}
+
+	if (!atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
+		return;
+	}
+
+	/*
+	 * If link was successfully encrypted cleanup old keys as from now on
+	 * only keys distributed in this pairing or LTK from LE SC will be used.
+	 */
+	if (conn->le.keys) {
+		bt_keys_clear(conn->le.keys);
+	}
+
+	conn->le.keys = bt_keys_get_addr(conn->id, &conn->le.dst);
+	if (!conn->le.keys) {
+		BT_ERR("Unable to get keys for %s",
+		       bt_addr_le_str(&conn->le.dst));
+		smp_error(smp, BT_SMP_ERR_UNSPECIFIED);
+		return;
+	}
+
+	/* mark keys as debug */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY)) {
+		conn->le.keys->flags |= BT_KEYS_DEBUG;
+	}
+
+	/*
+	 * store key type deducted from pairing method used
+	 * it is important to store it since type is used to determine
+	 * security level upon encryption
+	 */
+	switch (smp->method) {
+	case PASSKEY_DISPLAY:
+	case PASSKEY_INPUT:
+	case PASSKEY_CONFIRM:
+	case LE_SC_OOB:
+	case LEGACY_OOB:
+		conn->le.keys->flags |= BT_KEYS_AUTHENTICATED;
+		break;
+	case JUST_WORKS:
+	default:
+		/* unauthenticated key, clear it */
+		conn->le.keys->flags &= ~BT_KEYS_AUTHENTICATED;
+		break;
+	}
+
+	conn->le.keys->enc_size = get_encryption_key_size(smp);
+
+	/*
+	 * Store LTK if LE SC is used, this is safe since LE SC is mutually
+	 * exclusive with legacy pairing. Other keys are added on keys
+	 * distribution.
+	 */
+	if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
+		conn->le.keys->flags |= BT_KEYS_SC;
+
+		if (atomic_test_bit(smp->flags, SMP_FLAG_BOND)) {
+			bt_keys_add_type(conn->le.keys, BT_KEYS_LTK_P256);
+			memcpy(conn->le.keys->ltk.val, smp->tk,
+			       sizeof(conn->le.keys->ltk.val));
+			(void)memset(conn->le.keys->ltk.rand, 0,
+				     sizeof(conn->le.keys->ltk.rand));
+			(void)memset(conn->le.keys->ltk.ediv, 0,
+				     sizeof(conn->le.keys->ltk.ediv));
+		}
+	} else {
+		conn->le.keys->flags &= ~BT_KEYS_SC;
+	}
+}
+
+static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	int i;
+	static const struct bt_l2cap_chan_ops ops = {
+		.connected = bt_smp_connected,
+		.disconnected = bt_smp_disconnected,
+		.encrypt_change = bt_smp_encrypt_change,
+		.recv = bt_smp_recv,
+	};
+
+	BT_DBG("conn %p handle %u", conn, conn->handle);
+
+	for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
+		struct bt_smp *smp = &bt_smp_pool[i];
+
+		if (smp->chan.chan.conn) {
+			continue;
+		}
+
+		smp->chan.chan.ops = &ops;
+
+		*chan = &smp->chan.chan;
+
+		return 0;
+	}
+
+	BT_ERR("No available SMP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept, NULL);
+#if defined(CONFIG_BT_BREDR)
+BT_L2CAP_CHANNEL_DEFINE(smp_br_fixed_chan, BT_L2CAP_CID_BR_SMP,
+			bt_smp_br_accept, NULL);
+#endif /* CONFIG_BT_BREDR */
+
+int bt_smp_init(void)
+{
+	static struct bt_pub_key_cb pub_key_cb = {
+		.func           = bt_smp_pkey_ready,
+	};
+
+	sc_supported = le_sc_supported();
+	if (IS_ENABLED(CONFIG_BT_SMP_SC_PAIR_ONLY) && !sc_supported) {
+		BT_ERR("SC Pair Only Mode selected but LE SC not supported");
+		return -ENOENT;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_USB_HCI_CTLR_WORKAROUND)) {
+		BT_WARN("BT_SMP_USB_HCI_CTLR_WORKAROUND is enabled, which "
+			"exposes a security vulnerability!");
+	}
+
+	BT_DBG("LE SC %s", sc_supported ? "enabled" : "disabled");
+
+	if (!IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
+		bt_pub_key_gen(&pub_key_cb);
+	}
+
+	return smp_self_test();
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp_null.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp_null.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/smp_null.c	(working copy)
@@ -0,0 +1,101 @@
+/**
+ * @file smp_null.c
+ * Security Manager Protocol stub
+ */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/buf.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_smp
+#include "common/log.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+#include "l2cap_internal.h"
+#include "smp.h"
+
+static struct bt_l2cap_le_chan bt_smp_pool[CONFIG_BT_MAX_CONN];
+
+int bt_smp_sign_verify(struct bt_conn *conn, struct net_buf *buf)
+{
+	return -ENOTSUP;
+}
+
+int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf)
+{
+	return -ENOTSUP;
+}
+
+static int bt_smp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_conn *conn = chan->conn;
+	struct bt_smp_pairing_fail *rsp;
+	struct bt_smp_hdr *hdr;
+
+	/* If a device does not support pairing then it shall respond with
+	 * a Pairing Failed command with the reason set to "Pairing Not
+	 * Supported" when any command is received.
+	 * Core Specification Vol. 3, Part H, 3.3
+	 */
+
+	buf = bt_l2cap_create_pdu(NULL, 0);
+	/* NULL is not a possible return due to K_FOREVER */
+
+	hdr = net_buf_add(buf, sizeof(*hdr));
+	hdr->code = BT_SMP_CMD_PAIRING_FAIL;
+
+	rsp = net_buf_add(buf, sizeof(*rsp));
+	rsp->reason = BT_SMP_ERR_PAIRING_NOTSUPP;
+
+	bt_l2cap_send(conn, BT_L2CAP_CID_SMP, buf);
+
+	return 0;
+}
+
+static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	int i;
+	static const struct bt_l2cap_chan_ops ops = {
+		.recv = bt_smp_recv,
+	};
+
+	BT_DBG("conn %p handle %u", conn, conn->handle);
+
+	for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
+		struct bt_l2cap_le_chan *smp = &bt_smp_pool[i];
+
+		if (smp->chan.conn) {
+			continue;
+		}
+
+		smp->chan.ops = &ops;
+
+		*chan = &smp->chan;
+
+		return 0;
+	}
+
+	BT_ERR("No available SMP context for conn %p", conn);
+
+	return -ENOMEM;
+}
+
+BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept, NULL);
+
+int bt_smp_init(void)
+{
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.h	(working copy)
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int bt_ssp_start_security(struct bt_conn *conn);
+
+int bt_ssp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey);
+int bt_ssp_auth_passkey_confirm(struct bt_conn *conn);
+int bt_ssp_auth_cancel(struct bt_conn *conn);
+int bt_ssp_auth_pairing_confirm(struct bt_conn *conn);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/ssp.c	(working copy)
@@ -0,0 +1,789 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+
+#include <sys/byteorder.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/addr.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
+#define LOG_MODULE_NAME bt_ssp
+#include "common/log.h"
+
+#include "keys.h"
+
+#include "hci_core.h"
+#include "conn_internal.h"
+
+enum pairing_method {
+	LEGACY,			/* Legacy (pre-SSP) pairing */
+	JUST_WORKS,		/* JustWorks pairing */
+	PASSKEY_INPUT,		/* Passkey Entry input */
+	PASSKEY_DISPLAY,	/* Passkey Entry display */
+	PASSKEY_CONFIRM,	/* Passkey confirm */
+};
+
+/* based on table 5.7, Core Spec 4.2, Vol.3 Part C, 5.2.2.6 */
+static const uint8_t ssp_method[4 /* remote */][4 /* local */] = {
+	      { JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS },
+	      { JUST_WORKS, PASSKEY_CONFIRM, PASSKEY_INPUT, JUST_WORKS },
+	      { PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS },
+	      { JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS },
+};
+
+static int pin_code_neg_reply(const bt_addr_t *bdaddr)
+{
+	struct bt_hci_cp_pin_code_neg_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_NEG_REPLY, buf, NULL);
+}
+
+static int pin_code_reply(struct bt_conn *conn, const char *pin, uint8_t len)
+{
+	struct bt_hci_cp_pin_code_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+
+	bt_addr_copy(&cp->bdaddr, &conn->br.dst);
+	cp->pin_len = len;
+	strncpy((char *)cp->pin_code, pin, sizeof(cp->pin_code));
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_REPLY, buf, NULL);
+}
+
+int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin)
+{
+	size_t len;
+
+	if (!bt_auth) {
+		return -EINVAL;
+	}
+
+	if (conn->type != BT_CONN_TYPE_BR) {
+		return -EINVAL;
+	}
+
+	len = strlen(pin);
+	if (len > 16) {
+		return -EINVAL;
+	}
+
+	if (conn->required_sec_level == BT_SECURITY_L3 && len < 16) {
+		BT_WARN("PIN code for %s is not 16 bytes wide",
+			bt_addr_str(&conn->br.dst));
+		return -EPERM;
+	}
+
+	/* Allow user send entered PIN to remote, then reset user state. */
+	if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) {
+		return -EPERM;
+	}
+
+	if (len == 16) {
+		atomic_set_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE);
+	}
+
+	return pin_code_reply(conn, pin, len);
+}
+
+static void pin_code_req(struct bt_conn *conn)
+{
+	if (bt_auth && bt_auth->pincode_entry) {
+		bool secure = false;
+
+		if (conn->required_sec_level == BT_SECURITY_L3) {
+			secure = true;
+		}
+
+		atomic_set_bit(conn->flags, BT_CONN_USER);
+		atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING);
+		bt_auth->pincode_entry(conn, secure);
+	} else {
+		pin_code_neg_reply(&conn->br.dst);
+	}
+}
+
+static uint8_t get_io_capa(void)
+{
+	if (!bt_auth) {
+		return BT_IO_NO_INPUT_OUTPUT;
+	}
+
+	if (bt_auth->passkey_confirm && bt_auth->passkey_display) {
+		return BT_IO_DISPLAY_YESNO;
+	}
+
+	if (bt_auth->passkey_entry) {
+		return BT_IO_KEYBOARD_ONLY;
+	}
+
+	if (bt_auth->passkey_display) {
+		return BT_IO_DISPLAY_ONLY;
+	}
+
+	return BT_IO_NO_INPUT_OUTPUT;
+}
+
+static uint8_t ssp_pair_method(const struct bt_conn *conn)
+{
+	return ssp_method[conn->br.remote_io_capa][get_io_capa()];
+}
+
+static uint8_t ssp_get_auth(const struct bt_conn *conn)
+{
+	/* Validate no bond auth request, and if valid use it. */
+	if ((conn->br.remote_auth == BT_HCI_NO_BONDING) ||
+	    ((conn->br.remote_auth == BT_HCI_NO_BONDING_MITM) &&
+	     (ssp_pair_method(conn) > JUST_WORKS))) {
+		return conn->br.remote_auth;
+	}
+
+	/* Local & remote have enough IO capabilities to get MITM protection. */
+	if (ssp_pair_method(conn) > JUST_WORKS) {
+		return conn->br.remote_auth | BT_MITM;
+	}
+
+	/* No MITM protection possible so ignore remote MITM requirement. */
+	return (conn->br.remote_auth & ~BT_MITM);
+}
+
+static int ssp_confirm_reply(struct bt_conn *conn)
+{
+	struct bt_hci_cp_user_confirm_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_USER_CONFIRM_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, &conn->br.dst);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_USER_CONFIRM_REPLY, buf, NULL);
+}
+
+static int ssp_confirm_neg_reply(struct bt_conn *conn)
+{
+	struct bt_hci_cp_user_confirm_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_USER_CONFIRM_NEG_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, &conn->br.dst);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_USER_CONFIRM_NEG_REPLY, buf,
+				    NULL);
+}
+
+static void ssp_pairing_complete(struct bt_conn *conn, uint8_t status)
+{
+	if (!status) {
+		bool bond = !atomic_test_bit(conn->flags, BT_CONN_BR_NOBOND);
+
+		if (bt_auth && bt_auth->pairing_complete) {
+			bt_auth->pairing_complete(conn, bond);
+		}
+	} else {
+		if (bt_auth && bt_auth->pairing_failed) {
+			bt_auth->pairing_failed(conn, status);
+		}
+	}
+}
+
+static void ssp_auth(struct bt_conn *conn, uint32_t passkey)
+{
+	conn->br.pairing_method = ssp_pair_method(conn);
+
+	/*
+	 * If local required security is HIGH then MITM is mandatory.
+	 * MITM protection is no achievable when SSP 'justworks' is applied.
+	 */
+	if (conn->required_sec_level > BT_SECURITY_L2 &&
+	    conn->br.pairing_method == JUST_WORKS) {
+		BT_DBG("MITM protection infeasible for required security");
+		ssp_confirm_neg_reply(conn);
+		return;
+	}
+
+	switch (conn->br.pairing_method) {
+	case PASSKEY_CONFIRM:
+		atomic_set_bit(conn->flags, BT_CONN_USER);
+		bt_auth->passkey_confirm(conn, passkey);
+		break;
+	case PASSKEY_DISPLAY:
+		atomic_set_bit(conn->flags, BT_CONN_USER);
+		bt_auth->passkey_display(conn, passkey);
+		break;
+	case PASSKEY_INPUT:
+		atomic_set_bit(conn->flags, BT_CONN_USER);
+		bt_auth->passkey_entry(conn);
+		break;
+	case JUST_WORKS:
+		/*
+		 * When local host works as pairing acceptor and 'justworks'
+		 * model is applied then notify user about such pairing request.
+		 * [BT Core 4.2 table 5.7, Vol 3, Part C, 5.2.2.6]
+		 */
+		if (bt_auth && bt_auth->pairing_confirm &&
+		    !atomic_test_bit(conn->flags,
+				     BT_CONN_BR_PAIRING_INITIATOR)) {
+			atomic_set_bit(conn->flags, BT_CONN_USER);
+			bt_auth->pairing_confirm(conn);
+			break;
+		}
+		ssp_confirm_reply(conn);
+		break;
+	default:
+		break;
+	}
+}
+
+static int ssp_passkey_reply(struct bt_conn *conn, unsigned int passkey)
+{
+	struct bt_hci_cp_user_passkey_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_USER_PASSKEY_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, &conn->br.dst);
+	cp->passkey = sys_cpu_to_le32(passkey);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_USER_PASSKEY_REPLY, buf, NULL);
+}
+
+static int ssp_passkey_neg_reply(struct bt_conn *conn)
+{
+	struct bt_hci_cp_user_passkey_neg_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*cp));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, &conn->br.dst);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_USER_PASSKEY_NEG_REPLY, buf,
+				    NULL);
+}
+
+static int conn_auth(struct bt_conn *conn)
+{
+	struct bt_hci_cp_auth_requested *auth;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_AUTH_REQUESTED, sizeof(*auth));
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	auth = net_buf_add(buf, sizeof(*auth));
+	auth->handle = sys_cpu_to_le16(conn->handle);
+
+	atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
+
+	return bt_hci_cmd_send_sync(BT_HCI_OP_AUTH_REQUESTED, buf, NULL);
+}
+
+int bt_ssp_start_security(struct bt_conn *conn)
+{
+	if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING)) {
+		return -EBUSY;
+	}
+
+	if (conn->required_sec_level > BT_SECURITY_L3) {
+		return -ENOTSUP;
+	}
+
+	if (get_io_capa() == BT_IO_NO_INPUT_OUTPUT &&
+	    conn->required_sec_level > BT_SECURITY_L2) {
+		return -EINVAL;
+	}
+
+	return conn_auth(conn);
+}
+
+int bt_ssp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey)
+{
+	/* User entered passkey, reset user state. */
+	if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) {
+		return -EPERM;
+	}
+
+	if (conn->br.pairing_method == PASSKEY_INPUT) {
+		return ssp_passkey_reply(conn, passkey);
+	}
+
+	return -EINVAL;
+}
+
+int bt_ssp_auth_passkey_confirm(struct bt_conn *conn)
+{
+	/* Allow user confirm passkey value, then reset user state. */
+	if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) {
+		return -EPERM;
+	}
+
+	return ssp_confirm_reply(conn);
+}
+
+int bt_ssp_auth_pairing_confirm(struct bt_conn *conn)
+{
+	return ssp_confirm_reply(conn);
+}
+
+int bt_ssp_auth_cancel(struct bt_conn *conn)
+{
+	/* Allow user cancel authentication, then reset user state. */
+	if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) {
+		return -EPERM;
+	}
+
+	switch (conn->br.pairing_method) {
+	case JUST_WORKS:
+	case PASSKEY_CONFIRM:
+		return ssp_confirm_neg_reply(conn);
+	case PASSKEY_INPUT:
+		return ssp_passkey_neg_reply(conn);
+	case PASSKEY_DISPLAY:
+		return bt_conn_disconnect(conn,
+					  BT_HCI_ERR_AUTH_FAIL);
+	case LEGACY:
+		return pin_code_neg_reply(&conn->br.dst);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+void hci_evt_pin_code_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_pin_code_req *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("");
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	pin_code_req(conn);
+	bt_conn_unref(conn);
+}
+
+void hci_evt_link_key_notify(struct net_buf *buf)
+{
+	struct bt_hci_evt_link_key_notify *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	BT_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type);
+
+	if (!conn->br.link_key) {
+		conn->br.link_key = bt_keys_get_link_key(&evt->bdaddr);
+	}
+	if (!conn->br.link_key) {
+		BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr));
+		bt_conn_unref(conn);
+		return;
+	}
+
+	/* clear any old Link Key flags */
+	conn->br.link_key->flags = 0U;
+
+	switch (evt->key_type) {
+	case BT_LK_COMBINATION:
+		/*
+		 * Setting Combination Link Key as AUTHENTICATED means it was
+		 * successfully generated by 16 digits wide PIN code.
+		 */
+		if (atomic_test_and_clear_bit(conn->flags,
+					      BT_CONN_BR_LEGACY_SECURE)) {
+			conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
+		}
+		memcpy(conn->br.link_key->val, evt->link_key, 16);
+		break;
+	case BT_LK_AUTH_COMBINATION_P192:
+		conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
+		__fallthrough;
+	case BT_LK_UNAUTH_COMBINATION_P192:
+		/* Mark no-bond so that link-key is removed on disconnection */
+		if (ssp_get_auth(conn) < BT_HCI_DEDICATED_BONDING) {
+			atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND);
+		}
+
+		memcpy(conn->br.link_key->val, evt->link_key, 16);
+		break;
+	case BT_LK_AUTH_COMBINATION_P256:
+		conn->br.link_key->flags |= BT_LINK_KEY_AUTHENTICATED;
+		__fallthrough;
+	case BT_LK_UNAUTH_COMBINATION_P256:
+		conn->br.link_key->flags |= BT_LINK_KEY_SC;
+
+		/* Mark no-bond so that link-key is removed on disconnection */
+		if (ssp_get_auth(conn) < BT_HCI_DEDICATED_BONDING) {
+			atomic_set_bit(conn->flags, BT_CONN_BR_NOBOND);
+		}
+
+		memcpy(conn->br.link_key->val, evt->link_key, 16);
+		break;
+	default:
+		BT_WARN("Unsupported Link Key type %u", evt->key_type);
+		(void)memset(conn->br.link_key->val, 0,
+			     sizeof(conn->br.link_key->val));
+		break;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+	    !atomic_test_bit(conn->flags, BT_CONN_BR_NOBOND)) {
+		bt_keys_link_key_store(conn->br.link_key);
+	}
+
+	bt_conn_unref(conn);
+}
+
+void link_key_neg_reply(const bt_addr_t *bdaddr)
+{
+	struct bt_hci_cp_link_key_neg_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_NEG_REPLY, sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Out of command buffers");
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_NEG_REPLY, buf, NULL);
+}
+
+void link_key_reply(const bt_addr_t *bdaddr, const uint8_t *lk)
+{
+	struct bt_hci_cp_link_key_reply *cp;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_REPLY, sizeof(*cp));
+	if (!buf) {
+		BT_ERR("Out of command buffers");
+		return;
+	}
+
+	cp = net_buf_add(buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	memcpy(cp->link_key, lk, 16);
+	bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_REPLY, buf, NULL);
+}
+
+void hci_evt_link_key_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_link_key_req *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("%s", bt_addr_str(&evt->bdaddr));
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		link_key_neg_reply(&evt->bdaddr);
+		return;
+	}
+
+	if (!conn->br.link_key) {
+		conn->br.link_key = bt_keys_find_link_key(&evt->bdaddr);
+	}
+
+	if (!conn->br.link_key) {
+		link_key_neg_reply(&evt->bdaddr);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	/*
+	 * Enforce regenerate by controller stronger link key since found one
+	 * in database not covers requested security level.
+	 */
+	if (!(conn->br.link_key->flags & BT_LINK_KEY_AUTHENTICATED) &&
+	    conn->required_sec_level > BT_SECURITY_L2) {
+		link_key_neg_reply(&evt->bdaddr);
+		bt_conn_unref(conn);
+		return;
+	}
+
+	link_key_reply(&evt->bdaddr, conn->br.link_key->val);
+	bt_conn_unref(conn);
+}
+
+void io_capa_neg_reply(const bt_addr_t *bdaddr, const uint8_t reason)
+{
+	struct bt_hci_cp_io_capability_neg_reply *cp;
+	struct net_buf *resp_buf;
+
+	resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_NEG_REPLY,
+				     sizeof(*cp));
+	if (!resp_buf) {
+		BT_ERR("Out of command buffers");
+		return;
+	}
+
+	cp = net_buf_add(resp_buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, bdaddr);
+	cp->reason = reason;
+	bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_NEG_REPLY, resp_buf, NULL);
+}
+
+void hci_evt_io_capa_resp(struct net_buf *buf)
+{
+	struct bt_hci_evt_io_capa_resp *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("remote %s, IOcapa 0x%02x, auth 0x%02x",
+	       bt_addr_str(&evt->bdaddr), evt->capability, evt->authentication);
+
+	if (evt->authentication > BT_HCI_GENERAL_BONDING_MITM) {
+		BT_ERR("Invalid remote authentication requirements");
+		io_capa_neg_reply(&evt->bdaddr,
+				  BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
+		return;
+	}
+
+	if (evt->capability > BT_IO_NO_INPUT_OUTPUT) {
+		BT_ERR("Invalid remote io capability requirements");
+		io_capa_neg_reply(&evt->bdaddr,
+				  BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL);
+		return;
+	}
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	conn->br.remote_io_capa = evt->capability;
+	conn->br.remote_auth = evt->authentication;
+	atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING);
+	bt_conn_unref(conn);
+}
+
+void hci_evt_io_capa_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_io_capa_req *evt = (void *)buf->data;
+	struct net_buf *resp_buf;
+	struct bt_conn *conn;
+	struct bt_hci_cp_io_capability_reply *cp;
+	uint8_t auth;
+
+	BT_DBG("");
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_REPLY,
+				     sizeof(*cp));
+	if (!resp_buf) {
+		BT_ERR("Out of command buffers");
+		bt_conn_unref(conn);
+		return;
+	}
+
+	/*
+	 * Set authentication requirements when acting as pairing initiator to
+	 * 'dedicated bond' with MITM protection set if local IO capa
+	 * potentially allows it, and for acceptor, based on local IO capa and
+	 * remote's authentication set.
+	 */
+	if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR)) {
+		if (get_io_capa() != BT_IO_NO_INPUT_OUTPUT) {
+			auth = BT_HCI_DEDICATED_BONDING_MITM;
+		} else {
+			auth = BT_HCI_DEDICATED_BONDING;
+		}
+	} else {
+		auth = ssp_get_auth(conn);
+	}
+
+	cp = net_buf_add(resp_buf, sizeof(*cp));
+	bt_addr_copy(&cp->bdaddr, &evt->bdaddr);
+	cp->capability = get_io_capa();
+	cp->authentication = auth;
+	cp->oob_data = 0U;
+	bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_REPLY, resp_buf, NULL);
+	bt_conn_unref(conn);
+}
+
+void hci_evt_ssp_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_ssp_complete *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("status 0x%02x", evt->status);
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	ssp_pairing_complete(conn, bt_security_err_get(evt->status));
+	if (evt->status) {
+		bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
+	}
+
+	bt_conn_unref(conn);
+}
+
+void hci_evt_user_confirm_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_user_confirm_req *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	ssp_auth(conn, sys_le32_to_cpu(evt->passkey));
+	bt_conn_unref(conn);
+}
+
+void hci_evt_user_passkey_notify(struct net_buf *buf)
+{
+	struct bt_hci_evt_user_passkey_notify *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	BT_DBG("");
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	ssp_auth(conn, sys_le32_to_cpu(evt->passkey));
+	bt_conn_unref(conn);
+}
+
+void hci_evt_user_passkey_req(struct net_buf *buf)
+{
+	struct bt_hci_evt_user_passkey_req *evt = (void *)buf->data;
+	struct bt_conn *conn;
+
+	conn = bt_conn_lookup_addr_br(&evt->bdaddr);
+	if (!conn) {
+		BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr));
+		return;
+	}
+
+	ssp_auth(conn, 0);
+	bt_conn_unref(conn);
+}
+
+static void link_encr(const uint16_t handle)
+{
+	struct bt_hci_cp_set_conn_encrypt *encr;
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	buf = bt_hci_cmd_create(BT_HCI_OP_SET_CONN_ENCRYPT, sizeof(*encr));
+	if (!buf) {
+		BT_ERR("Out of command buffers");
+		return;
+	}
+
+	encr = net_buf_add(buf, sizeof(*encr));
+	encr->handle = sys_cpu_to_le16(handle);
+	encr->encrypt = 0x01;
+
+	bt_hci_cmd_send_sync(BT_HCI_OP_SET_CONN_ENCRYPT, buf, NULL);
+}
+
+void hci_evt_auth_complete(struct net_buf *buf)
+{
+	struct bt_hci_evt_auth_complete *evt = (void *)buf->data;
+	struct bt_conn *conn;
+	uint16_t handle = sys_le16_to_cpu(evt->handle);
+
+	BT_DBG("status 0x%02x, handle %u", evt->status, handle);
+
+	conn = bt_conn_lookup_handle(handle);
+	if (!conn) {
+		BT_ERR("Can't find conn for handle %u", handle);
+		return;
+	}
+
+	if (evt->status) {
+		/*
+		 * Inform layers above HCI about non-zero authentication
+		 * status to make them able cleanup pending jobs.
+		 */
+		bt_conn_security_changed(conn, evt->status,
+					 bt_security_err_get(evt->status));
+	} else {
+		link_encr(handle);
+	}
+
+	bt_conn_unref(conn);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.h	(working copy)
@@ -0,0 +1,21 @@
+/**
+ * @file testing.h
+ * @brief Internal API for Bluetooth testing.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_MESH)
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
+			   const void *payload, size_t payload_len);
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+			      uint16_t key_idx);
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+				uint16_t key_idx);
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode);
+void bt_test_mesh_trans_incomp_timer_exp(void);
+#endif /* CONFIG_BT_MESH */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/testing.c	(working copy)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <stddef.h>
+
+#include <bluetooth/testing.h>
+
+#if defined(CONFIG_BT_MESH)
+#include "mesh/net.h"
+#include "mesh/lpn.h"
+#include "mesh/rpl.h"
+#include "mesh/transport.h"
+#endif /* CONFIG_BT_MESH */
+
+#include "testing.h"
+
+static sys_slist_t cb_slist;
+
+void bt_test_cb_register(struct bt_test_cb *cb)
+{
+	sys_slist_append(&cb_slist, &cb->node);
+}
+
+void bt_test_cb_unregister(struct bt_test_cb *cb)
+{
+	sys_slist_find_and_remove(&cb_slist, &cb->node);
+}
+
+#if defined(CONFIG_BT_MESH)
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
+			   const void *payload, size_t payload_len)
+{
+	struct bt_test_cb *cb;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
+		if (cb->mesh_net_recv) {
+			cb->mesh_net_recv(ttl, ctl, src, dst, payload,
+					  payload_len);
+		}
+	}
+}
+
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+			      uint16_t key_idx)
+{
+	struct bt_test_cb *cb;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
+		if (cb->mesh_model_bound) {
+			cb->mesh_model_bound(addr, model, key_idx);
+		}
+	}
+}
+
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+				uint16_t key_idx)
+{
+	struct bt_test_cb *cb;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
+		if (cb->mesh_model_unbound) {
+			cb->mesh_model_unbound(addr, model, key_idx);
+		}
+	}
+}
+
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode)
+{
+	struct bt_test_cb *cb;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
+		if (cb->mesh_prov_invalid_bearer) {
+			cb->mesh_prov_invalid_bearer(opcode);
+		}
+	}
+}
+
+void bt_test_mesh_trans_incomp_timer_exp(void)
+{
+	struct bt_test_cb *cb;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) {
+		if (cb->mesh_trans_incomp_timer_exp) {
+			cb->mesh_trans_incomp_timer_exp();
+		}
+	}
+}
+
+int bt_test_mesh_lpn_group_add(uint16_t group)
+{
+	bt_mesh_lpn_group_add(group);
+
+	return 0;
+}
+
+int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count)
+{
+	bt_mesh_lpn_group_del(groups, groups_count);
+
+	return 0;
+}
+
+int bt_test_mesh_rpl_clear(void)
+{
+	bt_mesh_rpl_clear();
+
+	return 0;
+}
+#endif /* CONFIG_BT_MESH */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/uuid.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/uuid.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/host/uuid.c	(working copy)
@@ -0,0 +1,128 @@
+/* uuid.c - Bluetooth UUID handling */
+
+/*
+ * Copyright (c) 2015-2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <sys/byteorder.h>
+#include <sys/printk.h>
+
+#include <bluetooth/uuid.h>
+
+#define UUID_16_BASE_OFFSET 12
+
+/* TODO: Decide whether to continue using BLE format or switch to RFC 4122 */
+
+/* Base UUID : 0000[0000]-0000-1000-8000-00805F9B34FB
+ * 0x2800    : 0000[2800]-0000-1000-8000-00805F9B34FB
+ *  little endian 0x2800 : [00 28] -> no swapping required
+ *  big endian 0x2800    : [28 00] -> swapping required
+ */
+static const struct bt_uuid_128 uuid128_base = {
+	.uuid = { BT_UUID_TYPE_128 },
+	.val = { BT_UUID_128_ENCODE(
+		0x00000000, 0x0000, 0x1000, 0x8000, 0x00805F9B34FB) }
+};
+
+static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst)
+{
+	switch (src->type) {
+	case BT_UUID_TYPE_16:
+		*dst = uuid128_base;
+		sys_put_le16(BT_UUID_16(src)->val,
+			     &dst->val[UUID_16_BASE_OFFSET]);
+		return;
+	case BT_UUID_TYPE_32:
+		*dst = uuid128_base;
+		sys_put_le32(BT_UUID_32(src)->val,
+			     &dst->val[UUID_16_BASE_OFFSET]);
+		return;
+	case BT_UUID_TYPE_128:
+		memcpy(dst, src, sizeof(*dst));
+		return;
+	}
+}
+
+static int uuid128_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
+{
+	struct bt_uuid_128 uuid1, uuid2;
+
+	uuid_to_uuid128(u1, &uuid1);
+	uuid_to_uuid128(u2, &uuid2);
+
+	return memcmp(uuid1.val, uuid2.val, 16);
+}
+
+int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
+{
+	/* Convert to 128 bit if types don't match */
+	if (u1->type != u2->type) {
+		return uuid128_cmp(u1, u2);
+	}
+
+	switch (u1->type) {
+	case BT_UUID_TYPE_16:
+		return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val;
+	case BT_UUID_TYPE_32:
+		return (int)BT_UUID_32(u1)->val - (int)BT_UUID_32(u2)->val;
+	case BT_UUID_TYPE_128:
+		return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16);
+	}
+
+	return -EINVAL;
+}
+
+bool bt_uuid_create(struct bt_uuid *uuid, const uint8_t *data, uint8_t data_len)
+{
+	/* Copy UUID from packet data/internal variable to internal bt_uuid */
+	switch (data_len) {
+	case 2:
+		uuid->type = BT_UUID_TYPE_16;
+		BT_UUID_16(uuid)->val = sys_get_le16(data);
+		break;
+	case 4:
+		uuid->type = BT_UUID_TYPE_32;
+		BT_UUID_32(uuid)->val = sys_get_le32(data);
+		break;
+	case 16:
+		uuid->type = BT_UUID_TYPE_128;
+		memcpy(&BT_UUID_128(uuid)->val, data, 16);
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
+void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len)
+{
+	uint32_t tmp1, tmp5;
+	uint16_t tmp0, tmp2, tmp3, tmp4;
+
+	switch (uuid->type) {
+	case BT_UUID_TYPE_16:
+		snprintk(str, len, "%04x", BT_UUID_16(uuid)->val);
+		break;
+	case BT_UUID_TYPE_32:
+		snprintk(str, len, "%08x", BT_UUID_32(uuid)->val);
+		break;
+	case BT_UUID_TYPE_128:
+		memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0));
+		memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1));
+		memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2));
+		memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3));
+		memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4));
+		memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5));
+
+		snprintk(str, len, "%08x-%04x-%04x-%04x-%08x%04x",
+			 tmp5, tmp4, tmp3, tmp2, tmp1, tmp0);
+		break;
+	default:
+		(void)memset(str, 0, len);
+		return;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/CMakeLists.txt	(working copy)
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_link_libraries(subsys__bluetooth)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH
+    main.c
+    adv.c
+    beacon.c
+    net.c
+    transport.c
+    rpl.c
+    crypto.c
+    access.c
+    cfg_srv.c
+    health_srv.c
+)
+
+zephyr_library_sources_ifdef(CONFIG_BT_SETTINGS settings.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_LOW_POWER lpn.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_FRIEND friend.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROV prov.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_ADV pb_adv.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_GATT pb_gatt.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROXY proxy.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_CFG_CLI cfg_cli.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_HEALTH_CLI health_cli.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_SELF_TEST test.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_SHELL shell.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_CDB cdb.c)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/Kconfig	(working copy)
@@ -0,0 +1,672 @@
+# Bluetooth Mesh configuration options
+
+# Copyright (c) 2017 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig BT_MESH
+	bool "Bluetooth Mesh support"
+	select TINYCRYPT
+	select TINYCRYPT_AES
+	select TINYCRYPT_AES_CMAC
+	select BT_HOST_CCM
+	depends on BT_OBSERVER && BT_BROADCASTER
+	help
+	  This option enables Bluetooth Mesh support. The specific
+	  features that are available may depend on other features
+	  that have been enabled in the stack, such as GATT support.
+
+if BT_MESH
+
+# Virtual option enabled whenever Generic Provisioning layer is needed
+config BT_MESH_PROV
+	bool
+
+config BT_MESH_PB_ADV
+	bool "Provisioning support using the advertising bearer (PB-ADV)"
+	select BT_MESH_PROV
+	default y
+	help
+	  Enable this option to allow the device to be provisioned over
+	  the advertising bearer.
+
+config BT_MESH_UNPROV_BEACON_INT
+	int
+	prompt "The interval (in seconds) to send the unprovisioned beacon" if BT_MESH_PB_ADV
+	default 5
+	range 1 10
+	help
+	  This option specifies the interval (in seconds) at which the
+	  device sends unprovisioned beacon.
+
+config BT_MESH_PROVISIONER
+	bool "Provisioner support"
+	select BT_MESH_PROV
+	help
+	  Enable this option to have support for provisioning remote devices.
+
+config BT_MESH_CDB
+	bool "Mesh Configuration Database [EXPERIMENTAL]"
+
+if BT_MESH_CDB
+
+config BT_MESH_CDB_NODE_COUNT
+	int "Maximum number of nodes in the database"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many nodes each network can at most
+	  save in the configuration database.
+
+config BT_MESH_CDB_SUBNET_COUNT
+	int "Maximum number of subnets in the database"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many subnets that can at most be
+	  saved in the configuration database.
+
+config BT_MESH_CDB_APP_KEY_COUNT
+	int "Maximum number of application keys in the database"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many application keys that can at most
+	  be saved in the configuration database.
+
+endif # BT_MESH_CDB
+
+if BT_CONN
+
+# Virtual option enabled whenever any Proxy protocol is needed
+config BT_MESH_PROXY
+	bool
+	select BT_GATT_DYNAMIC_DB
+
+config BT_MESH_PB_GATT
+	bool "Provisioning support using GATT (PB-GATT)"
+	select BT_MESH_PROXY
+	select BT_MESH_PROV
+	help
+	  Enable this option to allow the device to be provisioned over
+	  GATT.
+
+config BT_MESH_GATT_PROXY
+	bool "GATT Proxy Service"
+	select BT_MESH_PROXY
+	help
+	  This option enables support for the Mesh GATT Proxy Service,
+	  i.e. the ability to act as a proxy between a Mesh GATT Client
+	  and a Mesh network.
+
+config BT_MESH_NODE_ID_TIMEOUT
+	int "Node Identity advertising timeout"
+	depends on BT_MESH_GATT_PROXY
+	range 1 60
+	default 60
+	help
+	  This option determines for how long the local node advertises
+	  using Node Identity. The given value is in seconds. The
+	  specification limits this to 60 seconds, and implies that to
+	  be the appropriate value as well, so just leaving this as the
+	  default is the safest option.
+
+config BT_MESH_PROXY_FILTER_SIZE
+	int "Maximum number of filter entries per Proxy Client"
+	default 3 if BT_MESH_GATT_PROXY
+	default 1
+	range 1 32767
+	depends on BT_MESH_PROXY
+	help
+	  This option specifies how many Proxy Filter entries the local
+	  node supports.
+
+endif # BT_CONN
+
+config BT_MESH_SELF_TEST
+	bool "Perform self-tests"
+	help
+	  This option adds extra self-tests which are run every time
+	  mesh networking is initialized.
+
+config BT_MESH_IV_UPDATE_TEST
+	bool "Test the IV Update Procedure"
+	help
+	  This option removes the 96 hour limit of the IV Update
+	  Procedure and lets the state be changed at any time.
+
+config BT_MESH_SUBNET_COUNT
+	int "Maximum number of mesh subnets per network"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many subnets a Mesh network can
+	  participate in at the same time.
+
+config BT_MESH_APP_KEY_COUNT
+	int "Maximum number of application keys per network"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many application keys the device can
+	  store per network.
+
+config BT_MESH_MODEL_KEY_COUNT
+	int "Maximum number of application keys per model"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many application keys each model can
+	  at most be bound to.
+
+config BT_MESH_MODEL_GROUP_COUNT
+	int "Maximum number of group address subscriptions per model"
+	default 1
+	range 1 4096
+	help
+	  This option specifies how many group addresses each model can
+	  at most be subscribed to.
+
+config BT_MESH_LABEL_COUNT
+	int "Maximum number of Label UUIDs used for Virtual Addresses"
+	default 1
+	range 0 4096
+	help
+	  This option specifies how many Label UUIDs can be stored.
+
+config BT_MESH_CRPL
+	int "Maximum capacity of the replay protection list"
+	default 10
+	range 2 65535
+	help
+	  This options specifies the maximum capacity of the replay
+	  protection list. This option is similar to the network message
+	  cache size, but has a different purpose.
+
+config BT_MESH_MSG_CACHE_SIZE
+	int "Network message cache size"
+	default 10
+	range 2 65535
+	help
+	  Number of messages that are cached for the network. This helps
+	  prevent unnecessary decryption operations and unnecessary
+	  relays. This option is similar to the replay protection list,
+	  but has a different purpose.
+
+config BT_MESH_ADV_BUF_COUNT
+	int "Number of advertising buffers"
+	default 6
+	range 1 256
+	help
+	  Number of advertising buffers available. This should be chosen
+	  based on what kind of features the local node should have. E.g.
+	  a relay will perform better the more buffers it has. Another
+	  thing to consider is outgoing segmented messages. There must
+	  be at least three more advertising buffers than the maximum
+	  supported outgoing segment count (BT_MESH_TX_SEG_MAX).
+
+config BT_MESH_ADV_STACK_SIZE
+	int "Mesh advertiser thread stack size"
+	default 1024 if BT_HOST_CRYPTO
+	default 768
+	help
+	  NOTE: This is an advanced setting and should not be changed unless
+	  absolutely necessary
+
+config BT_MESH_IVU_DIVIDER
+	int "Divider for IV Update state refresh timer"
+	default 4
+	range 2 96
+	help
+	  When the IV Update state enters Normal operation or IV Update
+	  in Progress, we need to keep track of how many hours has passed
+	  in the state, since the specification requires us to remain in
+	  the state at least for 96 hours (Update in Progress has an
+	  additional upper limit of 144 hours).
+
+	  In order to fulfill the above requirement, even if the node might
+	  be powered off once in a while, we need to store persistently
+	  how many hours the node has been in the state. This doesn't
+	  necessarily need to happen every hour (thanks to the flexible
+	  duration range). The exact cadence will depend a lot on the
+	  ways that the node will be used and what kind of power source it
+	  has.
+
+	  Since there is no single optimal answer, this configuration
+	  option allows specifying a divider, i.e. how many intervals
+	  the 96 hour minimum gets split into. After each interval the
+	  duration that the node has been in the current state gets
+	  stored to flash. E.g. the default value of 4 means that the
+	  state is saved every 24 hours (96 / 4).
+
+config BT_MESH_TX_SEG_MSG_COUNT
+	int "Maximum number of simultaneous outgoing segmented messages"
+	default 1
+	range 1 255
+	help
+	  Maximum number of simultaneous outgoing multi-segment and/or
+	  reliable messages.
+
+config BT_MESH_RX_SEG_MSG_COUNT
+	int "Maximum number of simultaneous incoming segmented messages"
+	default 1
+	range 1 255
+	help
+	  Maximum number of simultaneous incoming multi-segment and/or
+	  reliable messages.
+
+config BT_MESH_SEG_BUFS
+	int "Number of segment buffers available"
+	default 64
+	range BT_MESH_RX_SEG_MAX 16384 if BT_MESH_RX_SEG_MAX > \
+					  BT_MESH_TX_SEG_MAX
+	range BT_MESH_TX_SEG_MAX 16384
+	help
+	  The incoming and outgoing segmented messages allocate their
+	  segments from the same pool. Each segment is a 12 byte block,
+	  and may only be used by one message at the time.
+
+	  Outgoing messages will allocate their segments at the start of the
+	  transmission, and release them one by one as soon as they have been
+	  acknowledged by the receiver. Incoming messages allocate all their
+	  segments at the start of the transaction, and won't release them until
+	  the message is fully received.
+
+config BT_MESH_RX_SEG_MAX
+	int "Maximum number of segments in incoming messages"
+	default 3
+	range 2 32
+	help
+	  Maximum number of segments supported for incoming messages.
+	  This value should typically be fine-tuned based on what
+	  models the local node supports, i.e. what's the largest
+	  message payload that the node needs to be able to receive.
+	  This value affects memory and call stack consumption, which
+	  is why the default is lower than the maximum that the
+	  specification would allow (32 segments).
+
+	  The maximum incoming SDU size is 12 times this number (out of
+	  which 4 or 8 bytes is used for the Transport Layer MIC). For
+	  example, 5 segments means the maximum SDU size is 60 bytes,
+	  which leaves 56 bytes for application layer data using a
+	  4-byte MIC and 52 bytes using an 8-byte MIC.
+
+config BT_MESH_TX_SEG_MAX
+	int "Maximum number of segments in outgoing messages"
+	default 3
+	range 2 32
+	help
+	  Maximum number of segments supported for outgoing messages.
+	  This value should typically be fine-tuned based on what
+	  models the local node supports, i.e. what's the largest
+	  message payload that the node needs to be able to send.
+	  This value affects memory consumption, which is why the
+	  default is lower than the maximum that the specification
+	  would allow (32 segments).
+
+	  The maximum outgoing SDU size is 12 times this number (out of
+	  which 4 or 8 bytes is used for the Transport Layer MIC). For
+	  example, 5 segments means the maximum SDU size is 60 bytes,
+	  which leaves 56 bytes for application layer data using a
+	  4-byte MIC and 52 bytes using an 8-byte MIC.
+
+config BT_MESH_LOOPBACK_BUFS
+	int "Number of loopback buffers"
+	default 3
+	help
+	  The number of buffers allocated for the network loopback mechanism.
+	  Loopback is used when the device sends messages to itself.
+
+config BT_MESH_RELAY
+	bool "Relay support"
+	help
+	  Support for acting as a Mesh Relay Node.
+
+config BT_MESH_LOW_POWER
+	bool "Support for Low Power features"
+	help
+	  Enable this option to be able to act as a Low Power Node.
+
+if BT_MESH_LOW_POWER
+
+config BT_MESH_LPN_ESTABLISHMENT
+	bool "Perform Friendship establishment using low power"
+	default y
+	help
+	  Perform the Friendship establishment using low power, with
+	  the help of a reduced scan duty cycle. The downside of this
+	  is that the node may miss out on messages intended for it
+	  until it has successfully set up Friendship with a Friend
+	  node.
+
+config BT_MESH_LPN_AUTO
+	bool "Automatically start looking for Friend nodes once provisioned"
+	default y
+	help
+	  Automatically enable LPN functionality once provisioned and start
+	  looking for Friend nodes. If this option is disabled LPN mode
+	  needs to be manually enabled by calling bt_mesh_lpn_set(true).
+
+config BT_MESH_LPN_AUTO_TIMEOUT
+	int "Time from last received message before going to LPN mode"
+	default 15
+	range 0 3600
+	depends on BT_MESH_LPN_AUTO
+	help
+	  Time in seconds from the last received message, that the node
+	  will wait before starting to look for Friend nodes.
+
+config BT_MESH_LPN_RETRY_TIMEOUT
+	int "Retry timeout for Friend requests"
+	default 8
+	range 1 3600
+	help
+	  Time in seconds between Friend Requests, if a previous Friend
+	  Request did not receive any acceptable Friend Offers.
+
+config BT_MESH_LPN_RSSI_FACTOR
+	int "RSSIFactor, used in the Friend Offer Delay calculation"
+	range 0 3
+	default 0
+	help
+	  The contribution of the RSSI measured by the Friend node used
+	  in Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
+
+config BT_MESH_LPN_RECV_WIN_FACTOR
+	int "ReceiveWindowFactor, used in the Friend Offer Delay calculation"
+	range 0 3
+	default 0
+	help
+	  The contribution of the supported Receive Window used in
+	  Friend Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
+
+config BT_MESH_LPN_MIN_QUEUE_SIZE
+	int "Minimum size of acceptable friend queue (MinQueueSizeLog)"
+	range 1 7
+	default 1
+	help
+	  The MinQueueSizeLog field is defined as log_2(N), where N is
+	  the minimum number of maximum size Lower Transport PDUs that
+	  the Friend node can store in its Friend Queue. As an example,
+	  MinQueueSizeLog value 1 gives N = 2, and value 7 gives N = 128.
+
+config BT_MESH_LPN_RECV_DELAY
+	int "Receive delay requested by the local node"
+	range 10 255
+	default 100
+	help
+	  The ReceiveDelay is the time between the Low Power node
+	  sending a request and listening for a response. This delay
+	  allows the Friend node time to prepare the response. The value
+	  is in units of milliseconds.
+
+config BT_MESH_LPN_POLL_TIMEOUT
+	int "The value of the PollTimeout timer"
+	range 10 244735
+	default 300
+	help
+	  PollTimeout timer is used to measure time between two
+	  consecutive requests sent by the Low Power node. If no
+	  requests are received by the Friend node before the
+	  PollTimeout timer expires, then the friendship is considered
+	  terminated. The value is in units of 100 milliseconds, so e.g.
+	  a value of 300 means 30 seconds.
+
+config BT_MESH_LPN_INIT_POLL_TIMEOUT
+	int "The starting value of the PollTimeout timer"
+	range 10 BT_MESH_LPN_POLL_TIMEOUT
+	default BT_MESH_LPN_POLL_TIMEOUT
+	help
+	  The initial value of the PollTimeout timer when Friendship
+	  gets established for the first time. After this the timeout
+	  will gradually grow toward the actual PollTimeout, doubling
+	  in value for each iteration. The value is in units of 100
+	  milliseconds, so e.g. a value of 300 means 30 seconds.
+
+config BT_MESH_LPN_SCAN_LATENCY
+	int "Latency for enabling scanning"
+	range 0 50
+	default 10
+	help
+	  Latency in milliseconds that it takes to enable scanning. This
+	  is in practice how much time in advance before the Receive Window
+	  that scanning is requested to be enabled.
+
+config BT_MESH_LPN_GROUPS
+	int "Number of groups the LPN can subscribe to"
+	range 0 16384
+	default 8
+	help
+	  Maximum number of groups that the LPN can subscribe to.
+
+config BT_MESH_LPN_SUB_ALL_NODES_ADDR
+	bool "Automatically subscribe all nodes address"
+	help
+	  Automatically subscribe all nodes address when friendship
+	  established.
+
+endif # BT_MESH_LOW_POWER
+
+config BT_MESH_FRIEND
+	bool "Support for acting as a Friend Node"
+	help
+	  Enable this option to be able to act as a Friend Node.
+
+if BT_MESH_FRIEND
+
+config BT_MESH_FRIEND_RECV_WIN
+	int "Friend Receive Window"
+	range 1 255
+	default 255
+	help
+	  Receive Window in milliseconds supported by the Friend node.
+
+config BT_MESH_FRIEND_QUEUE_SIZE
+	int "Minimum number of buffers supported per Friend Queue"
+	range 2 65536
+	default 16
+	help
+	  Minimum number of buffers available to be stored for each
+	  local Friend Queue.
+
+config BT_MESH_FRIEND_SUB_LIST_SIZE
+	int "Friend Subscription List Size"
+	range 0 1023
+	default 3
+	help
+	  Size of the Subscription List that can be supported by a
+	  Friend node for a Low Power node.
+
+config BT_MESH_FRIEND_LPN_COUNT
+	int "Number of supported LPN nodes"
+	range 1 1000
+	default 2
+	help
+	  Number of Low Power Nodes the Friend can have a Friendship
+	  with simultaneously.
+
+config BT_MESH_FRIEND_SEG_RX
+	int "Number of incomplete segment lists per LPN"
+	range 1 1000
+	default 1
+	help
+	  Number of incomplete segment lists that we track for each LPN
+	  that we are Friends for. In other words, this determines how
+	  many elements we can simultaneously be receiving segmented
+	  messages from when the messages are going into the Friend queue.
+
+endif # BT_MESH_FRIEND
+
+config BT_MESH_CFG_CLI
+	bool "Support for Configuration Client Model"
+	help
+	  Enable support for the configuration client model.
+
+config BT_MESH_HEALTH_CLI
+	bool "Support for Health Client Model"
+	help
+	  Enable support for the health client model.
+
+config BT_MESH_SHELL
+	bool "Enable Bluetooth Mesh shell"
+	select SHELL
+	depends on BT_MESH_CFG_CLI
+	depends on BT_MESH_HEALTH_CLI
+	help
+	  Activate shell module that provides Bluetooth Mesh commands to
+	  the console.
+
+config BT_MESH_MODEL_EXTENSIONS
+	bool "Support for Model extensions"
+	help
+	  Enable support for the model extension concept, allowing the Access
+	  layer to know about Mesh model relationships.
+
+if BT_SETTINGS
+
+config BT_MESH_STORE_TIMEOUT
+	int "Delay (in seconds) before storing anything persistently"
+	range 0 1000000
+	default 2
+	help
+	  This value defines in seconds how soon any pending changes
+	  are actually written into persistent storage (flash) after
+	  a change occurs.
+
+config BT_MESH_SEQ_STORE_RATE
+	int "How often the sequence number gets updated in storage"
+	range 0 1000000
+	default 128
+	help
+	  This value defines how often the local sequence number gets
+	  updated in persistent storage (i.e. flash). E.g. a value of 100
+	  means that the sequence number will be stored to flash on every
+	  100th increment. If the node sends messages very frequently a
+	  higher value makes more sense, whereas if the node sends
+	  infrequently a value as low as 0 (update storage for every
+	  increment) can make sense. When the stack gets initialized it
+	  will add this number to the last stored one, so that it starts
+	  off with a value that's guaranteed to be larger than the last
+	  one used before power off.
+
+config BT_MESH_RPL_STORE_TIMEOUT
+	int "Minimum frequency that the RPL gets updated in storage"
+	range 0 1000000
+	default 5
+	help
+	  This value defines in seconds how soon the RPL gets written to
+	  persistent storage after a change occurs. If the node receives
+	  messages frequently it may make sense to have this set to a
+	  large value, whereas if the RPL gets updated infrequently a
+	  value as low as 0 (write immediately) may make sense. Note that
+	  if the node operates a security sensitive use case, and there's
+	  a risk of sudden power loss, it may be a security vulnerability
+	  to set this value to anything else than 0 (a power loss before
+	  writing to storage exposes the node to potential message
+	  replay attacks).
+
+endif # BT_SETTINGS
+
+config BT_MESH_DEBUG
+	bool "Enable debug logs"
+	depends on BT_DEBUG
+	help
+	  Use this option to enable debug logs for the Bluetooth
+	  Mesh functionality.
+
+if BT_MESH_DEBUG
+
+config BT_MESH_DEBUG_USE_ID_ADDR
+	bool "Use identity address for all advertising"
+	help
+	  This option forces the usage of the local identity address for
+	  all advertising. This can be a help for debugging (analyzing
+	  traces), however it should never be enabled for a production
+	  build as it compromises the privacy of the device.
+
+config BT_MESH_DEBUG_NET
+	bool "Network layer debug"
+	help
+	  Use this option to enable Network layer debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_RPL
+	bool "Replay protection list debug"
+	help
+	  Use this option to enable Replay protection list debug logs
+	  for the Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_TRANS
+	bool "Transport layer debug"
+	help
+	  Use this option to enable Transport layer debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_BEACON
+	bool "Beacon debug"
+	help
+	  Use this option to enable Beacon-related debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_CRYPTO
+	bool "Crypto debug"
+	help
+	  Use this option to enable cryptographic debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_PROV
+	bool "Provisioning debug"
+	help
+	  Use this option to enable Provisioning debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_ACCESS
+	bool "Access layer debug"
+	help
+	  Use this option to enable Access layer and device composition
+	  related debug logs for Bluetooth Mesh.
+
+config BT_MESH_DEBUG_MODEL
+	bool "Foundation model debug"
+	help
+	  Use this option to enable debug logs for the Foundation
+	  Models.
+
+config BT_MESH_DEBUG_ADV
+	bool "Advertising debug"
+	help
+	  Use this option to enable advertising debug logs for
+	  the Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_LOW_POWER
+	bool "Low Power debug"
+	help
+	  Use this option to enable Low Power debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_FRIEND
+	bool "Friend debug"
+	help
+	  Use this option to enable Friend debug logs for the
+	  Bluetooth Mesh functionality.
+
+config BT_MESH_DEBUG_PROXY
+	bool "Proxy debug"
+	depends on BT_MESH_PROXY
+	help
+	  Use this option to enable Proxy protocol debug logs.
+
+config BT_MESH_DEBUG_SETTINGS
+	bool "Persistent settings debug"
+	depends on BT_SETTINGS
+	help
+	  Use this option to enable persistent settings debug logs.
+
+config BT_MESH_DEBUG_CDB
+	bool "Configuration database debug"
+	depends on BT_MESH_CDB
+	help
+	  Use this option to enable configuration database debug logs.
+
+endif # BT_MESH_DEBUG
+
+endif # BT_MESH
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/TODO
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/TODO	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/TODO	(working copy)
@@ -0,0 +1,6 @@
+Bluetooth Mesh implementation tasks
+===================================
+
+ * Ability to act as provisioner
+
+ * More generally useful models from the Model Specification
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.h	(working copy)
@@ -0,0 +1,60 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* bt_mesh_model.flags */
+enum {
+	BT_MESH_MOD_BIND_PENDING = BIT(0),
+	BT_MESH_MOD_SUB_PENDING = BIT(1),
+	BT_MESH_MOD_PUB_PENDING = BIT(2),
+	BT_MESH_MOD_NEXT_IS_PARENT = BIT(3),
+};
+
+/* Tree walk return codes */
+enum bt_mesh_walk {
+	BT_MESH_WALK_STOP,
+	BT_MESH_WALK_CONTINUE,
+};
+
+void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
+
+uint8_t bt_mesh_elem_count(void);
+
+/* Find local element based on unicast or group address */
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
+
+struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
+void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
+			     enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
+						     uint32_t depth,
+						     void *user_data),
+			     void *user_data);
+
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr);
+
+bool bt_mesh_fixed_group_match(uint16_t addr);
+
+void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
+					struct bt_mesh_elem *elem,
+					bool vnd, bool primary,
+					void *user_data),
+			   void *user_data);
+
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
+
+void bt_mesh_comp_provision(uint16_t addr);
+void bt_mesh_comp_unprovision(void);
+
+uint16_t bt_mesh_primary_addr(void);
+
+const struct bt_mesh_comp *bt_mesh_comp_get(void);
+
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx);
+
+void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
+
+int bt_mesh_comp_register(const struct bt_mesh_comp *comp);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/access.c	(working copy)
@@ -0,0 +1,882 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ACCESS)
+#define LOG_MODULE_NAME bt_mesh_access
+#include "common/log.h"
+
+#include "mesh.h"
+#include "adv.h"
+#include "net.h"
+#include "lpn.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+
+static const struct bt_mesh_comp *dev_comp;
+static uint16_t dev_primary_addr;
+
+void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
+					struct bt_mesh_elem *elem,
+					bool vnd, bool primary,
+					void *user_data),
+			   void *user_data)
+{
+	int i, j;
+
+	for (i = 0; i < dev_comp->elem_count; i++) {
+		struct bt_mesh_elem *elem = &dev_comp->elem[i];
+
+		for (j = 0; j < elem->model_count; j++) {
+			struct bt_mesh_model *model = &elem->models[j];
+
+			func(model, elem, false, i == 0, user_data);
+		}
+
+		for (j = 0; j < elem->vnd_model_count; j++) {
+			struct bt_mesh_model *model = &elem->vnd_models[j];
+
+			func(model, elem, true, i == 0, user_data);
+		}
+	}
+}
+
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
+{
+	int32_t period;
+
+	if (!mod->pub) {
+		return 0;
+	}
+
+	switch (mod->pub->period >> 6) {
+	case 0x00:
+		/* 1 step is 100 ms */
+		period = (mod->pub->period & BIT_MASK(6)) * 100U;
+		break;
+	case 0x01:
+		/* 1 step is 1 second */
+		period = (mod->pub->period & BIT_MASK(6)) * MSEC_PER_SEC;
+		break;
+	case 0x02:
+		/* 1 step is 10 seconds */
+		period = (mod->pub->period & BIT_MASK(6)) * 10U * MSEC_PER_SEC;
+		break;
+	case 0x03:
+		/* 1 step is 10 minutes */
+		period = (mod->pub->period & BIT_MASK(6)) * 600U * MSEC_PER_SEC;
+		break;
+	default:
+		CODE_UNREACHABLE;
+	}
+
+	if (mod->pub->fast_period) {
+		return period >> mod->pub->period_div;
+	} else {
+		return period;
+	}
+}
+
+static int32_t next_period(struct bt_mesh_model *mod)
+{
+	struct bt_mesh_model_pub *pub = mod->pub;
+	uint32_t elapsed, period;
+
+	period = bt_mesh_model_pub_period_get(mod);
+	if (!period) {
+		return 0;
+	}
+
+	elapsed = k_uptime_get_32() - pub->period_start;
+
+	BT_DBG("Publishing took %ums", elapsed);
+
+	if (elapsed >= period) {
+		BT_WARN("Publication sending took longer than the period");
+		/* Return smallest positive number since 0 means disabled */
+		return 1;
+	}
+
+	return period - elapsed;
+}
+
+static void publish_sent(int err, void *user_data)
+{
+	struct bt_mesh_model *mod = user_data;
+	int32_t delay;
+
+	BT_DBG("err %d", err);
+
+	if (mod->pub->count) {
+		delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
+	} else {
+		delay = next_period(mod);
+	}
+
+	if (delay) {
+		BT_DBG("Publishing next time in %dms", delay);
+		k_delayed_work_submit(&mod->pub->timer, K_MSEC(delay));
+	}
+}
+
+static void publish_start(uint16_t duration, int err, void *user_data)
+{
+	struct bt_mesh_model *mod = user_data;
+	struct bt_mesh_model_pub *pub = mod->pub;
+
+	if (err) {
+		BT_ERR("Failed to publish: err %d", err);
+		return;
+	}
+
+	/* Initialize the timestamp for the beginning of a new period */
+	if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) {
+		pub->period_start = k_uptime_get_32();
+	}
+}
+
+static const struct bt_mesh_send_cb pub_sent_cb = {
+	.start = publish_start,
+	.end = publish_sent,
+};
+
+static int publish_retransmit(struct bt_mesh_model *mod)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	struct bt_mesh_model_pub *pub = mod->pub;
+	struct bt_mesh_app_key *key;
+	struct bt_mesh_msg_ctx ctx = {
+		.addr = pub->addr,
+		.send_ttl = pub->ttl,
+	};
+	struct bt_mesh_net_tx tx = {
+		.ctx = &ctx,
+		.src = bt_mesh_model_elem(mod)->addr,
+		.xmit = bt_mesh_net_transmit_get(),
+		.friend_cred = pub->cred,
+	};
+
+	key = bt_mesh_app_key_find(pub->key);
+	if (!key) {
+		return -EADDRNOTAVAIL;
+	}
+
+	tx.sub = bt_mesh_subnet_get(key->net_idx);
+
+	ctx.net_idx = key->net_idx;
+	ctx.app_idx = key->app_idx;
+
+	net_buf_simple_add_mem(&sdu, pub->msg->data, pub->msg->len);
+
+	pub->count--;
+
+	return bt_mesh_trans_send(&tx, &sdu, &pub_sent_cb, mod);
+}
+
+static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
+{
+	/* Cancel all retransmits for this publish attempt */
+	pub->count = 0U;
+	/* Make sure the publish timer gets reset */
+	publish_sent(err, pub->mod);
+}
+
+static void mod_publish(struct k_work *work)
+{
+	struct bt_mesh_model_pub *pub = CONTAINER_OF(work,
+						     struct bt_mesh_model_pub,
+						     timer.work);
+	int32_t period_ms;
+	int err;
+
+	BT_DBG("");
+
+	period_ms = bt_mesh_model_pub_period_get(pub->mod);
+	BT_DBG("period %u ms", period_ms);
+
+	if (pub->count) {
+		err = publish_retransmit(pub->mod);
+		if (err) {
+			BT_ERR("Failed to retransmit (err %d)", err);
+
+			pub->count = 0U;
+
+			/* Continue with normal publication */
+			if (period_ms) {
+				k_delayed_work_submit(&pub->timer,
+						      K_MSEC(period_ms));
+			}
+		}
+
+		return;
+	}
+
+	if (!period_ms) {
+		return;
+	}
+
+	__ASSERT_NO_MSG(pub->update != NULL);
+
+	err = pub->update(pub->mod);
+	if (err) {
+		/* Cancel this publish attempt. */
+		BT_DBG("Update failed, skipping publish (err: %d)", err);
+		pub->period_start = k_uptime_get_32();
+		publish_retransmit_end(err, pub);
+		return;
+	}
+
+	err = bt_mesh_model_publish(pub->mod);
+	if (err) {
+		BT_ERR("Publishing failed (err %d)", err);
+	}
+}
+
+struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
+{
+	return &dev_comp->elem[mod->elem_idx];
+}
+
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
+{
+	struct bt_mesh_elem *elem;
+
+	if (elem_idx >= dev_comp->elem_count) {
+		BT_ERR("Invalid element index %u", elem_idx);
+		return NULL;
+	}
+
+	elem = &dev_comp->elem[elem_idx];
+
+	if (vnd) {
+		if (mod_idx >= elem->vnd_model_count) {
+			BT_ERR("Invalid vendor model index %u", mod_idx);
+			return NULL;
+		}
+
+		return &elem->vnd_models[mod_idx];
+	} else {
+		if (mod_idx >= elem->model_count) {
+			BT_ERR("Invalid SIG model index %u", mod_idx);
+			return NULL;
+		}
+
+		return &elem->models[mod_idx];
+	}
+}
+
+static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+		     bool vnd, bool primary, void *user_data)
+{
+	int i;
+	int *err = user_data;
+
+	if (*err) {
+		return;
+	}
+
+	if (mod->pub) {
+		mod->pub->mod = mod;
+		k_delayed_work_init(&mod->pub->timer, mod_publish);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
+		mod->keys[i] = BT_MESH_KEY_UNUSED;
+	}
+
+	mod->elem_idx = elem - dev_comp->elem;
+	if (vnd) {
+		mod->mod_idx = mod - elem->vnd_models;
+	} else {
+		mod->mod_idx = mod - elem->models;
+	}
+
+	if (mod->cb && mod->cb->init) {
+		*err = mod->cb->init(mod);
+	}
+}
+
+int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
+{
+	int err;
+
+	/* There must be at least one element */
+	if (!comp->elem_count) {
+		return -EINVAL;
+	}
+
+	dev_comp = comp;
+
+	err = 0;
+	bt_mesh_model_foreach(mod_init, &err);
+
+	return err;
+}
+
+void bt_mesh_comp_provision(uint16_t addr)
+{
+	int i;
+
+	dev_primary_addr = addr;
+
+	BT_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count);
+
+	for (i = 0; i < dev_comp->elem_count; i++) {
+		struct bt_mesh_elem *elem = &dev_comp->elem[i];
+
+		elem->addr = addr++;
+
+		BT_DBG("addr 0x%04x mod_count %u vnd_mod_count %u",
+		       elem->addr, elem->model_count, elem->vnd_model_count);
+	}
+}
+
+void bt_mesh_comp_unprovision(void)
+{
+	BT_DBG("");
+
+	dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
+}
+
+uint16_t bt_mesh_primary_addr(void)
+{
+	return dev_primary_addr;
+}
+
+static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
+		if (mod->groups[i] == addr) {
+			return &mod->groups[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct find_group_visitor_ctx {
+	uint16_t *entry;
+	struct bt_mesh_model *mod;
+	uint16_t addr;
+};
+
+static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
+						uint32_t depth, void *user_data)
+{
+	struct find_group_visitor_ctx *ctx = user_data;
+
+	if (mod->elem_idx != ctx->mod->elem_idx) {
+		return BT_MESH_WALK_CONTINUE;
+	}
+
+	ctx->entry = model_group_get(mod, ctx->addr);
+	if (ctx->entry) {
+		ctx->mod = mod;
+		return BT_MESH_WALK_STOP;
+	}
+
+	return BT_MESH_WALK_CONTINUE;
+}
+
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
+{
+	struct find_group_visitor_ctx ctx = {
+		.mod = *mod,
+		.entry = NULL,
+		.addr = addr,
+	};
+
+	bt_mesh_model_tree_walk(bt_mesh_model_root(*mod),
+				find_group_mod_visitor, &ctx);
+
+	*mod = ctx.mod;
+	return ctx.entry;
+}
+
+static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
+						     uint16_t group_addr)
+{
+	struct bt_mesh_model *model;
+	uint16_t *match;
+	int i;
+
+	for (i = 0; i < elem->model_count; i++) {
+		model = &elem->models[i];
+
+		match = model_group_get(model, group_addr);
+		if (match) {
+			return model;
+		}
+	}
+
+	for (i = 0; i < elem->vnd_model_count; i++) {
+		model = &elem->vnd_models[i];
+
+		match = model_group_get(model, group_addr);
+		if (match) {
+			return model;
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
+{
+	uint16_t index;
+
+	if (BT_MESH_ADDR_IS_UNICAST(addr)) {
+		index = (addr - dev_comp->elem[0].addr);
+		if (index < dev_comp->elem_count) {
+			return &dev_comp->elem[index];
+		} else {
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < dev_comp->elem_count; index++) {
+		struct bt_mesh_elem *elem = &dev_comp->elem[index];
+
+		if (bt_mesh_elem_find_group(elem, addr)) {
+			return elem;
+		}
+	}
+
+	return NULL;
+}
+
+uint8_t bt_mesh_elem_count(void)
+{
+	return dev_comp->elem_count;
+}
+
+static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
+		if (mod->keys[i] == key ||
+		    (mod->keys[i] == BT_MESH_KEY_DEV_ANY &&
+		     BT_MESH_IS_DEV_KEY(key))) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
+{
+	if (BT_MESH_ADDR_IS_UNICAST(dst)) {
+		return (dev_comp->elem[mod->elem_idx].addr == dst);
+	} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
+		return !!bt_mesh_model_find_group(&mod, dst);
+	}
+
+	return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
+}
+
+static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
+					      uint8_t model_count, uint32_t opcode,
+					      struct bt_mesh_model **model)
+{
+	uint8_t i;
+
+	for (i = 0U; i < model_count; i++) {
+		const struct bt_mesh_model_op *op;
+
+		*model = &models[i];
+
+		for (op = (*model)->op; op->func; op++) {
+			if (op->opcode == opcode) {
+				return op;
+			}
+		}
+	}
+
+	*model = NULL;
+	return NULL;
+}
+
+static int get_opcode(struct net_buf_simple *buf, uint32_t *opcode)
+{
+	switch (buf->data[0] >> 6) {
+	case 0x00:
+	case 0x01:
+		if (buf->data[0] == 0x7f) {
+			BT_ERR("Ignoring RFU OpCode");
+			return -EINVAL;
+		}
+
+		*opcode = net_buf_simple_pull_u8(buf);
+		return 0;
+	case 0x02:
+		if (buf->len < 2) {
+			BT_ERR("Too short payload for 2-octet OpCode");
+			return -EINVAL;
+		}
+
+		*opcode = net_buf_simple_pull_be16(buf);
+		return 0;
+	case 0x03:
+		if (buf->len < 3) {
+			BT_ERR("Too short payload for 3-octet OpCode");
+			return -EINVAL;
+		}
+
+		*opcode = net_buf_simple_pull_u8(buf) << 16;
+		/* Using LE for the CID since the model layer is defined as
+		 * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+		 * will declare the opcode in this way.
+		 */
+		*opcode |= net_buf_simple_pull_le16(buf);
+		return 0;
+	}
+
+	CODE_UNREACHABLE;
+}
+
+bool bt_mesh_fixed_group_match(uint16_t addr)
+{
+	/* Check for fixed group addresses */
+	switch (addr) {
+	case BT_MESH_ADDR_ALL_NODES:
+		return true;
+	case BT_MESH_ADDR_PROXIES:
+		return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
+	case BT_MESH_ADDR_FRIENDS:
+		return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
+	case BT_MESH_ADDR_RELAYS:
+		return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
+	default:
+		return false;
+	}
+}
+
+void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
+{
+	struct bt_mesh_model *models, *model;
+	const struct bt_mesh_model_op *op;
+	uint32_t opcode;
+	uint8_t count;
+	int i;
+
+	BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
+	       rx->ctx.addr, rx->ctx.recv_dst);
+	BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	if (get_opcode(buf, &opcode) < 0) {
+		BT_WARN("Unable to decode OpCode");
+		return;
+	}
+
+	BT_DBG("OpCode 0x%08x", opcode);
+
+	for (i = 0; i < dev_comp->elem_count; i++) {
+		struct bt_mesh_elem *elem = &dev_comp->elem[i];
+		struct net_buf_simple_state state;
+
+		/* SIG models cannot contain 3-byte (vendor) OpCodes, and
+		 * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
+		 * we only need to do the lookup in one of the model lists.
+		 */
+		if (BT_MESH_MODEL_OP_LEN(opcode) < 3) {
+			models = elem->models;
+			count = elem->model_count;
+		} else {
+			models = elem->vnd_models;
+			count = elem->vnd_model_count;
+		}
+
+		op = find_op(models, count, opcode, &model);
+		if (!op) {
+			BT_DBG("No OpCode 0x%08x for elem %d", opcode, i);
+			continue;
+		}
+
+		if (!model_has_key(model, rx->ctx.app_idx)) {
+			continue;
+		}
+
+		if (!model_has_dst(model, rx->ctx.recv_dst)) {
+			continue;
+		}
+
+		if (buf->len < op->min_len) {
+			BT_ERR("Too short message for OpCode 0x%08x", opcode);
+			continue;
+		}
+
+		/* The callback will likely parse the buffer, so
+		 * store the parsing state in case multiple models
+		 * receive the message.
+		 */
+		net_buf_simple_save(buf, &state);
+		op->func(model, &rx->ctx, buf);
+		net_buf_simple_restore(buf, &state);
+	}
+}
+
+void bt_mesh_model_msg_init(struct net_buf_simple *msg, uint32_t opcode)
+{
+	net_buf_simple_init(msg, 0);
+
+	switch (BT_MESH_MODEL_OP_LEN(opcode)) {
+	case 1:
+		net_buf_simple_add_u8(msg, opcode);
+		break;
+	case 2:
+		net_buf_simple_add_be16(msg, opcode);
+		break;
+	case 3:
+		net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
+		/* Using LE for the CID since the model layer is defined as
+		 * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+		 * will declare the opcode in this way.
+		 */
+		net_buf_simple_add_le16(msg, opcode & 0xffff);
+		break;
+	default:
+		BT_WARN("Unknown opcode format");
+		break;
+	}
+}
+
+static int model_send(struct bt_mesh_model *model,
+		      struct bt_mesh_net_tx *tx, bool implicit_bind,
+		      struct net_buf_simple *msg,
+		      const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
+	       tx->ctx->app_idx, tx->ctx->addr);
+	BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
+
+	if (!bt_mesh_is_provisioned()) {
+		BT_ERR("Local node is not yet provisioned");
+		return -EAGAIN;
+	}
+
+	if (net_buf_simple_tailroom(msg) < 4) {
+		BT_ERR("Not enough tailroom for TransMIC");
+		return -EINVAL;
+	}
+
+	if (msg->len > BT_MESH_TX_SDU_MAX - 4) {
+		BT_ERR("Too big message");
+		return -EMSGSIZE;
+	}
+
+	if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
+		BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
+		return -EINVAL;
+	}
+
+	return bt_mesh_trans_send(tx, msg, cb, cb_data);
+}
+
+int bt_mesh_model_send(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *msg,
+		       const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	struct bt_mesh_app_key *app_key;
+
+	if (!BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
+		app_key = bt_mesh_app_key_find(ctx->app_idx);
+		if (!app_key) {
+			BT_ERR("Unknown app_idx 0x%04x", ctx->app_idx);
+			return -EINVAL;
+		}
+
+		ctx->net_idx = app_key->net_idx;
+	}
+
+	struct bt_mesh_net_tx tx = {
+		.sub = bt_mesh_subnet_get(ctx->net_idx),
+		.ctx = ctx,
+		.src = bt_mesh_model_elem(model)->addr,
+		.xmit = bt_mesh_net_transmit_get(),
+		.friend_cred = 0,
+	};
+
+	return model_send(model, &tx, false, msg, cb, cb_data);
+}
+
+int bt_mesh_model_publish(struct bt_mesh_model *model)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	struct bt_mesh_model_pub *pub = model->pub;
+	struct bt_mesh_app_key *key;
+	struct bt_mesh_msg_ctx ctx = {
+	};
+	struct bt_mesh_net_tx tx = {
+		.ctx = &ctx,
+		.src = bt_mesh_model_elem(model)->addr,
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+	int err;
+
+	BT_DBG("");
+
+	if (!pub) {
+		return -ENOTSUP;
+	}
+
+	if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
+		return -EADDRNOTAVAIL;
+	}
+
+	key = bt_mesh_app_key_find(pub->key);
+	if (!key) {
+		return -EADDRNOTAVAIL;
+	}
+
+	if (pub->msg->len + 4 > BT_MESH_TX_SDU_MAX) {
+		BT_ERR("Message does not fit maximum SDU size");
+		return -EMSGSIZE;
+	}
+
+	if (pub->count) {
+		BT_WARN("Clearing publish retransmit timer");
+		k_delayed_work_cancel(&pub->timer);
+	}
+
+	net_buf_simple_add_mem(&sdu, pub->msg->data, pub->msg->len);
+
+	ctx.addr = pub->addr;
+	ctx.send_ttl = pub->ttl;
+	ctx.send_rel = pub->send_rel;
+	ctx.net_idx = key->net_idx;
+	ctx.app_idx = key->app_idx;
+
+	tx.friend_cred = pub->cred;
+	tx.sub = bt_mesh_subnet_get(ctx.net_idx),
+
+	pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
+
+	BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
+	       BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
+
+	err = model_send(model, &tx, true, &sdu, &pub_sent_cb, model);
+	if (err) {
+		publish_retransmit_end(err, pub);
+		return err;
+	}
+
+	return 0;
+}
+
+struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
+					     uint16_t company, uint16_t id)
+{
+	uint8_t i;
+
+	for (i = 0U; i < elem->vnd_model_count; i++) {
+		if (elem->vnd_models[i].vnd.company == company &&
+		    elem->vnd_models[i].vnd.id == id) {
+			return &elem->vnd_models[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
+					 uint16_t id)
+{
+	uint8_t i;
+
+	for (i = 0U; i < elem->model_count; i++) {
+		if (elem->models[i].id == id) {
+			return &elem->models[i];
+		}
+	}
+
+	return NULL;
+}
+
+const struct bt_mesh_comp *bt_mesh_comp_get(void)
+{
+	return dev_comp;
+}
+
+struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
+{
+#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
+	while (mod->next) {
+		mod = mod->next;
+	}
+#endif
+	return mod;
+}
+
+void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
+			     enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
+						     uint32_t depth,
+						     void *user_data),
+			     void *user_data)
+{
+	struct bt_mesh_model *m = root;
+	uint32_t depth = 0;
+
+	do {
+		if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
+			return;
+		}
+#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
+		if (m->extends) {
+			m = m->extends;
+			depth++;
+		} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
+			m = m->next->next;
+			depth--;
+		} else {
+			m = m->next;
+		}
+#endif
+	} while (m && m != root);
+}
+
+#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS
+int bt_mesh_model_extend(struct bt_mesh_model *mod,
+			 struct bt_mesh_model *base_mod)
+{
+	/* Form a cyclical LCRS tree:
+	 * The extends-pointer points to the first child, and the next-pointer
+	 * points to the next sibling. The last sibling is marked by the
+	 * BT_MESH_MOD_NEXT_IS_PARENT flag, and its next-pointer points back to
+	 * the parent. This way, the whole tree is accessible from any node.
+	 *
+	 * We add children (extend them) by inserting them as the first child.
+	 */
+	if (base_mod->next) {
+		return -EALREADY;
+	}
+
+	if (mod->extends) {
+		base_mod->next = mod->extends;
+	} else {
+		base_mod->next = mod;
+		base_mod->flags |= BT_MESH_MOD_NEXT_IS_PARENT;
+	}
+
+	mod->extends = base_mod;
+	return 0;
+}
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.h	(working copy)
@@ -0,0 +1,56 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Maximum advertising data payload for a single data type */
+#define BT_MESH_ADV_DATA_SIZE 29
+
+/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */
+#define BT_MESH_ADV_USER_DATA_SIZE 4
+
+#define BT_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
+
+enum bt_mesh_adv_type {
+	BT_MESH_ADV_PROV,
+	BT_MESH_ADV_DATA,
+	BT_MESH_ADV_BEACON,
+	BT_MESH_ADV_URI,
+};
+
+typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, uint16_t duration,
+				   int err, void *user_data);
+
+struct bt_mesh_adv {
+	const struct bt_mesh_send_cb *cb;
+	void *cb_data;
+
+	uint8_t      type:2,
+		  busy:1;
+	uint8_t      xmit;
+};
+
+typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
+
+/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
+struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+				   k_timeout_t timeout);
+
+struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
+					     bt_mesh_adv_alloc_t get_id,
+					     enum bt_mesh_adv_type type,
+					     uint8_t xmit, k_timeout_t timeout);
+
+void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
+		      void *cb_data);
+
+void bt_mesh_adv_update(void);
+
+void bt_mesh_adv_init(void);
+
+int bt_mesh_scan_enable(void);
+
+int bt_mesh_scan_disable(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/adv.c	(working copy)
@@ -0,0 +1,331 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <debug/stack.h>
+#include <sys/util.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ADV)
+#define LOG_MODULE_NAME bt_mesh_adv
+#include "common/log.h"
+
+#include "host/hci_core.h"
+
+#include "adv.h"
+#include "net.h"
+#include "foundation.h"
+#include "beacon.h"
+#include "prov.h"
+#include "proxy.h"
+
+/* Convert from ms to 0.625ms units */
+#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
+
+/* Window and Interval are equal for continuous scanning */
+#define MESH_SCAN_INTERVAL_MS 30
+#define MESH_SCAN_WINDOW_MS   30
+#define MESH_SCAN_INTERVAL    ADV_SCAN_UNIT(MESH_SCAN_INTERVAL_MS)
+#define MESH_SCAN_WINDOW      ADV_SCAN_UNIT(MESH_SCAN_WINDOW_MS)
+
+/* Pre-5.0 controllers enforce a minimum interval of 100ms
+ * whereas 5.0+ controllers can go down to 20ms.
+ */
+#define ADV_INT_DEFAULT_MS 100
+#define ADV_INT_FAST_MS    20
+
+static K_FIFO_DEFINE(adv_queue);
+static struct k_thread adv_thread_data;
+static K_KERNEL_STACK_DEFINE(adv_thread_stack, CONFIG_BT_MESH_ADV_STACK_SIZE);
+
+NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BT_MESH_ADV_BUF_COUNT,
+		    BT_MESH_ADV_DATA_SIZE, BT_MESH_ADV_USER_DATA_SIZE, NULL);
+
+static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
+
+static struct bt_mesh_adv *adv_alloc(int id)
+{
+	return &adv_pool[id];
+}
+
+static inline void adv_send_start(uint16_t duration, int err,
+				  const struct bt_mesh_send_cb *cb,
+				  void *cb_data)
+{
+	if (cb && cb->start) {
+		cb->start(duration, err, cb_data);
+	}
+}
+
+static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
+				void *cb_data)
+{
+	if (cb && cb->end) {
+		cb->end(err, cb_data);
+	}
+}
+
+static inline void adv_send(struct net_buf *buf)
+{
+	static const uint8_t adv_type[] = {
+		[BT_MESH_ADV_PROV]   = BT_DATA_MESH_PROV,
+		[BT_MESH_ADV_DATA]   = BT_DATA_MESH_MESSAGE,
+		[BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON,
+		[BT_MESH_ADV_URI]    = BT_DATA_URI,
+	};
+	const int32_t adv_int_min = ((bt_dev.hci_version >= BT_HCI_VERSION_5_0) ?
+				   ADV_INT_FAST_MS : ADV_INT_DEFAULT_MS);
+	const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
+	void *cb_data = BT_MESH_ADV(buf)->cb_data;
+	struct bt_le_adv_param param = {};
+	uint16_t duration, adv_int;
+	struct bt_data ad;
+	int err;
+
+	adv_int = MAX(adv_int_min,
+		      BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit));
+	duration = (MESH_SCAN_WINDOW_MS +
+		    ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) *
+		     (adv_int + 10)));
+
+	BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type,
+	       buf->len, bt_hex(buf->data, buf->len));
+	BT_DBG("count %u interval %ums duration %ums",
+	       BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int,
+	       duration);
+
+	ad.type = adv_type[BT_MESH_ADV(buf)->type];
+	ad.data_len = buf->len;
+	ad.data = buf->data;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)) {
+		param.options = BT_LE_ADV_OPT_USE_IDENTITY;
+	} else {
+		param.options = 0U;
+	}
+
+	param.id = BT_ID_DEFAULT;
+	param.interval_min = ADV_SCAN_UNIT(adv_int);
+	param.interval_max = param.interval_min;
+
+	err = bt_le_adv_start(&param, &ad, 1, NULL, 0);
+	net_buf_unref(buf);
+	adv_send_start(duration, err, cb, cb_data);
+	if (err) {
+		BT_ERR("Advertising failed: err %d", err);
+		return;
+	}
+
+	BT_DBG("Advertising started. Sleeping %u ms", duration);
+
+	k_sleep(K_MSEC(duration));
+
+	err = bt_le_adv_stop();
+	adv_send_end(err, cb, cb_data);
+	if (err) {
+		BT_ERR("Stopping advertising failed: err %d", err);
+		return;
+	}
+
+	BT_DBG("Advertising stopped");
+}
+
+static void adv_thread(void *p1, void *p2, void *p3)
+{
+	BT_DBG("started");
+
+	while (1) {
+		struct net_buf *buf;
+
+		if (IS_ENABLED(CONFIG_BT_MESH_PROXY)) {
+			buf = net_buf_get(&adv_queue, K_NO_WAIT);
+			while (!buf) {
+				k_timeout_t timeout;
+
+				timeout = bt_mesh_proxy_adv_start();
+				BT_DBG("Proxy Advertising");
+
+				buf = net_buf_get(&adv_queue, timeout);
+				bt_mesh_proxy_adv_stop();
+			}
+		} else {
+			buf = net_buf_get(&adv_queue, K_FOREVER);
+		}
+
+		if (!buf) {
+			continue;
+		}
+
+		/* busy == 0 means this was canceled */
+		if (BT_MESH_ADV(buf)->busy) {
+			BT_MESH_ADV(buf)->busy = 0U;
+			adv_send(buf);
+		} else {
+			net_buf_unref(buf);
+		}
+
+		/* Give other threads a chance to run */
+		k_yield();
+	}
+}
+
+void bt_mesh_adv_update(void)
+{
+	BT_DBG("");
+
+	k_fifo_cancel_wait(&adv_queue);
+}
+
+struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
+					     bt_mesh_adv_alloc_t get_id,
+					     enum bt_mesh_adv_type type,
+					     uint8_t xmit, k_timeout_t timeout)
+{
+	struct bt_mesh_adv *adv;
+	struct net_buf *buf;
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
+		BT_WARN("Refusing to allocate buffer while suspended");
+		return NULL;
+	}
+
+	buf = net_buf_alloc(pool, timeout);
+	if (!buf) {
+		return NULL;
+	}
+
+	adv = get_id(net_buf_id(buf));
+	BT_MESH_ADV(buf) = adv;
+
+	(void)memset(adv, 0, sizeof(*adv));
+
+	adv->type         = type;
+	adv->xmit         = xmit;
+
+	return buf;
+}
+
+struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+				   k_timeout_t timeout)
+{
+	return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type,
+					    xmit, timeout);
+}
+
+void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
+		      void *cb_data)
+{
+	BT_DBG("type 0x%02x len %u: %s", BT_MESH_ADV(buf)->type, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	BT_MESH_ADV(buf)->cb = cb;
+	BT_MESH_ADV(buf)->cb_data = cb_data;
+	BT_MESH_ADV(buf)->busy = 1U;
+
+	net_buf_put(&adv_queue, net_buf_ref(buf));
+}
+
+static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
+			    uint8_t adv_type, struct net_buf_simple *buf)
+{
+	if (adv_type != BT_GAP_ADV_TYPE_ADV_NONCONN_IND) {
+		return;
+	}
+
+	BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	while (buf->len > 1) {
+		struct net_buf_simple_state state;
+		uint8_t len, type;
+
+		len = net_buf_simple_pull_u8(buf);
+		/* Check for early termination */
+		if (len == 0U) {
+			return;
+		}
+
+		if (len > buf->len) {
+			BT_WARN("AD malformed");
+			return;
+		}
+
+		net_buf_simple_save(buf, &state);
+
+		type = net_buf_simple_pull_u8(buf);
+
+		buf->len = len - 1;
+
+		switch (type) {
+		case BT_DATA_MESH_MESSAGE:
+			bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
+			break;
+#if defined(CONFIG_BT_MESH_PB_ADV)
+		case BT_DATA_MESH_PROV:
+			bt_mesh_pb_adv_recv(buf);
+			break;
+#endif
+		case BT_DATA_MESH_BEACON:
+			bt_mesh_beacon_recv(buf);
+			break;
+		default:
+			break;
+		}
+
+		net_buf_simple_restore(buf, &state);
+		net_buf_simple_pull(buf, len);
+	}
+}
+
+void bt_mesh_adv_init(void)
+{
+	k_thread_create(&adv_thread_data, adv_thread_stack,
+			K_KERNEL_STACK_SIZEOF(adv_thread_stack), adv_thread,
+			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
+	k_thread_name_set(&adv_thread_data, "BT Mesh adv");
+}
+
+int bt_mesh_scan_enable(void)
+{
+	struct bt_le_scan_param scan_param = {
+			.type       = BT_HCI_LE_SCAN_PASSIVE,
+			.filter_dup = BT_LE_SCAN_OPT_NONE,
+			.interval   = MESH_SCAN_INTERVAL,
+			.window     = MESH_SCAN_WINDOW };
+	int err;
+
+	BT_DBG("");
+
+	err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
+	if (err && err != -EALREADY) {
+		BT_ERR("starting scan failed (err %d)", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_mesh_scan_disable(void)
+{
+	int err;
+
+	BT_DBG("");
+
+	err = bt_le_scan_stop();
+	if (err && err != -EALREADY) {
+		BT_ERR("stopping scan failed (err %d)", err);
+		return err;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.h	(working copy)
@@ -0,0 +1,19 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_mesh_beacon_enable(void);
+void bt_mesh_beacon_disable(void);
+
+void bt_mesh_beacon_ivu_initiator(bool enable);
+
+void bt_mesh_beacon_recv(struct net_buf_simple *buf);
+
+void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
+			   struct net_buf_simple *buf);
+
+void bt_mesh_beacon_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/beacon.c	(working copy)
@@ -0,0 +1,448 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <sys/util.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_BEACON)
+#define LOG_MODULE_NAME bt_mesh_beacon
+#include "common/log.h"
+
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "prov.h"
+#include "crypto.h"
+#include "beacon.h"
+#include "foundation.h"
+
+#define PROVISIONED_INTERVAL       K_SECONDS(10)
+
+#define BEACON_TYPE_UNPROVISIONED  0x00
+#define BEACON_TYPE_SECURE         0x01
+
+/* 3 transmissions, 20ms interval */
+#define UNPROV_XMIT                BT_MESH_TRANSMIT(2, 20)
+
+/* 1 transmission, 20ms interval */
+#define PROV_XMIT                  BT_MESH_TRANSMIT(0, 20)
+
+static struct k_delayed_work beacon_timer;
+
+static struct bt_mesh_subnet *cache_check(uint8_t data[21])
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (!memcmp(sub->beacon_cache, data, 21)) {
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub)
+{
+	memcpy(sub->beacon_cache, data, 21);
+}
+
+static void beacon_complete(int err, void *user_data)
+{
+	struct bt_mesh_subnet *sub = user_data;
+
+	BT_DBG("err %d", err);
+
+	sub->beacon_sent = k_uptime_get_32();
+}
+
+void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
+			   struct net_buf_simple *buf)
+{
+	uint8_t flags = bt_mesh_net_flags(sub);
+	struct bt_mesh_subnet_keys *keys;
+
+	net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
+
+	if (sub->kr_flag) {
+		keys = &sub->keys[1];
+	} else {
+		keys = &sub->keys[0];
+	}
+
+	net_buf_simple_add_u8(buf, flags);
+
+	/* Network ID */
+	net_buf_simple_add_mem(buf, keys->net_id, 8);
+
+	/* IV Index */
+	net_buf_simple_add_be32(buf, bt_mesh.iv_index);
+
+	net_buf_simple_add_mem(buf, sub->auth, 8);
+
+	BT_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx,
+	       flags, bt_hex(keys->net_id, 8));
+	BT_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index,
+	       bt_hex(sub->auth, 8));
+}
+
+/* If the interval has passed or is within 5 seconds from now send a beacon */
+#define BEACON_THRESHOLD(sub) \
+	((10 * ((sub)->beacons_last + 1)) * MSEC_PER_SEC - (5 * MSEC_PER_SEC))
+
+static int secure_beacon_send(void)
+{
+	static const struct bt_mesh_send_cb send_cb = {
+		.end = beacon_complete,
+	};
+	uint32_t now = k_uptime_get_32();
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+		struct net_buf *buf;
+		uint32_t time_diff;
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		time_diff = now - sub->beacon_sent;
+		if (time_diff < (600 * MSEC_PER_SEC) &&
+		    time_diff < BEACON_THRESHOLD(sub)) {
+			continue;
+		}
+
+		buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
+					 K_NO_WAIT);
+		if (!buf) {
+			BT_ERR("Unable to allocate beacon buffer");
+			return -ENOBUFS;
+		}
+
+		bt_mesh_beacon_create(sub, &buf->b);
+
+		bt_mesh_adv_send(buf, &send_cb, sub);
+		net_buf_unref(buf);
+	}
+
+	return 0;
+}
+
+static int unprovisioned_beacon_send(void)
+{
+	const struct bt_mesh_prov *prov;
+	uint8_t uri_hash[16] = { 0 };
+	struct net_buf *buf;
+	uint16_t oob_info;
+
+	BT_DBG("");
+
+	buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT, K_NO_WAIT);
+	if (!buf) {
+		BT_ERR("Unable to allocate beacon buffer");
+		return -ENOBUFS;
+	}
+
+	prov = bt_mesh_prov_get();
+
+	net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED);
+	net_buf_add_mem(buf, prov->uuid, 16);
+
+	if (prov->uri && bt_mesh_s1(prov->uri, uri_hash) == 0) {
+		oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI;
+	} else {
+		oob_info = prov->oob_info;
+	}
+
+	net_buf_add_be16(buf, oob_info);
+	net_buf_add_mem(buf, uri_hash, 4);
+
+	bt_mesh_adv_send(buf, NULL, NULL);
+	net_buf_unref(buf);
+
+	if (prov->uri) {
+		size_t len;
+
+		buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT,
+					 K_NO_WAIT);
+		if (!buf) {
+			BT_ERR("Unable to allocate URI buffer");
+			return -ENOBUFS;
+		}
+
+		len = strlen(prov->uri);
+		if (net_buf_tailroom(buf) < len) {
+			BT_WARN("Too long URI to fit advertising data");
+		} else {
+			net_buf_add_mem(buf, prov->uri, len);
+			bt_mesh_adv_send(buf, NULL, NULL);
+		}
+
+		net_buf_unref(buf);
+	}
+
+	return 0;
+}
+
+static void unprovisioned_beacon_recv(struct net_buf_simple *buf)
+{
+	const struct bt_mesh_prov *prov;
+	uint8_t *uuid;
+	uint16_t oob_info;
+	uint32_t uri_hash_val;
+	uint32_t *uri_hash = NULL;
+
+	if (buf->len != 18 && buf->len != 22) {
+		BT_ERR("Invalid unprovisioned beacon length (%u)", buf->len);
+		return;
+	}
+
+	uuid = net_buf_simple_pull_mem(buf, 16);
+	oob_info = net_buf_simple_pull_be16(buf);
+
+	if (buf->len == 4) {
+		uri_hash_val = net_buf_simple_pull_be32(buf);
+		uri_hash = &uri_hash_val;
+	}
+
+	BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+	prov = bt_mesh_prov_get();
+
+	if (prov->unprovisioned_beacon) {
+		prov->unprovisioned_beacon(uuid,
+					   (bt_mesh_prov_oob_info_t)oob_info,
+					   uri_hash);
+	}
+}
+
+static void update_beacon_observation(void)
+{
+	static bool first_half;
+	int i;
+
+	/* Observation period is 20 seconds, whereas the beacon timer
+	 * runs every 10 seconds. We process what's happened during the
+	 * window only after the seconnd half.
+	 */
+	first_half = !first_half;
+	if (first_half) {
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		sub->beacons_last = sub->beacons_cur;
+		sub->beacons_cur = 0U;
+	}
+}
+
+static void beacon_send(struct k_work *work)
+{
+	/* Don't send anything if we have an active provisioning link */
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_prov_active()) {
+		k_delayed_work_submit(&beacon_timer, K_SECONDS(CONFIG_BT_MESH_UNPROV_BEACON_INT));
+		return;
+	}
+
+	BT_DBG("");
+
+	if (bt_mesh_is_provisioned()) {
+		update_beacon_observation();
+		secure_beacon_send();
+
+		/* Only resubmit if beaconing is still enabled */
+		if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
+		    atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
+			k_delayed_work_submit(&beacon_timer,
+					      PROVISIONED_INTERVAL);
+		}
+
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+		unprovisioned_beacon_send();
+		k_delayed_work_submit(&beacon_timer, K_SECONDS(CONFIG_BT_MESH_UNPROV_BEACON_INT));
+	}
+}
+
+static void secure_beacon_recv(struct net_buf_simple *buf)
+{
+	uint8_t *data, *net_id, *auth;
+	struct bt_mesh_subnet *sub;
+	uint32_t iv_index;
+	bool new_key, kr_change, iv_change;
+	uint8_t flags;
+
+	if (buf->len < 21) {
+		BT_ERR("Too short secure beacon (len %u)", buf->len);
+		return;
+	}
+
+	sub = cache_check(buf->data);
+	if (sub) {
+		/* We've seen this beacon before - just update the stats */
+		goto update_stats;
+	}
+
+	/* So we can add to the cache if auth matches */
+	data = buf->data;
+
+	flags = net_buf_simple_pull_u8(buf);
+	net_id = net_buf_simple_pull_mem(buf, 8);
+	iv_index = net_buf_simple_pull_be32(buf);
+	auth = buf->data;
+
+	BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
+	       flags, bt_hex(net_id, 8), iv_index);
+
+	sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
+	if (!sub) {
+		BT_DBG("No subnet that matched beacon");
+		return;
+	}
+
+	if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
+		BT_WARN("Ignoring Phase 2 KR Update secured using old key");
+		return;
+	}
+
+	cache_add(data, sub);
+
+	kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
+	if (kr_change) {
+		bt_mesh_net_beacon_update(sub);
+		/* Key Refresh without IV Update only impacts one subnet */
+		bt_mesh_net_sec_update(sub);
+	}
+
+	/* If we have NetKey0 accept initiation only from it */
+	if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
+	    sub->net_idx != BT_MESH_KEY_PRIMARY) {
+		BT_WARN("Ignoring secure beacon on non-primary subnet");
+		goto update_stats;
+	}
+
+	BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
+	       sub->net_idx, iv_index, bt_mesh.iv_index);
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
+	    (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
+	     BT_MESH_IV_UPDATE(flags))) {
+		bt_mesh_beacon_ivu_initiator(false);
+	}
+
+	iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
+
+	if (iv_change) {
+		/* Update all subnets */
+		bt_mesh_net_sec_update(NULL);
+	}
+
+update_stats:
+	if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
+	    sub->beacons_cur < 0xff) {
+		sub->beacons_cur++;
+	}
+}
+
+void bt_mesh_beacon_recv(struct net_buf_simple *buf)
+{
+	uint8_t type;
+
+	BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	if (buf->len < 1) {
+		BT_ERR("Too short beacon");
+		return;
+	}
+
+	type = net_buf_simple_pull_u8(buf);
+	switch (type) {
+	case BEACON_TYPE_UNPROVISIONED:
+		if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+			unprovisioned_beacon_recv(buf);
+		}
+		break;
+	case BEACON_TYPE_SECURE:
+		secure_beacon_recv(buf);
+		break;
+	default:
+		BT_WARN("Unknown beacon type 0x%02x", type);
+		break;
+	}
+}
+
+void bt_mesh_beacon_init(void)
+{
+	k_delayed_work_init(&beacon_timer, beacon_send);
+}
+
+void bt_mesh_beacon_ivu_initiator(bool enable)
+{
+	atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable);
+
+	if (enable) {
+		k_work_submit(&beacon_timer.work);
+	} else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
+		k_delayed_work_cancel(&beacon_timer);
+	}
+}
+
+void bt_mesh_beacon_enable(void)
+{
+	int i;
+
+	if (!bt_mesh_is_provisioned()) {
+		k_work_submit(&beacon_timer.work);
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		sub->beacons_last = 0U;
+		sub->beacons_cur = 0U;
+
+		bt_mesh_net_beacon_update(sub);
+	}
+
+	k_work_submit(&beacon_timer.work);
+}
+
+void bt_mesh_beacon_disable(void)
+{
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
+		k_delayed_work_cancel(&beacon_timer);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cdb.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cdb.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cdb.c	(working copy)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CDB)
+#define LOG_MODULE_NAME bt_mesh_cdb
+#include "common/log.h"
+
+#include "mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+
+struct bt_mesh_cdb bt_mesh_cdb = {
+	.nodes = {
+		[0 ... (CONFIG_BT_MESH_CDB_NODE_COUNT - 1)] = {
+			.addr = BT_MESH_ADDR_UNASSIGNED,
+		}
+	},
+	.subnets = {
+		[0 ... (CONFIG_BT_MESH_CDB_SUBNET_COUNT - 1)] = {
+			.net_idx = BT_MESH_KEY_UNUSED,
+		}
+	},
+	.app_keys = {
+		[0 ... (CONFIG_BT_MESH_CDB_APP_KEY_COUNT - 1)] = {
+			.net_idx = BT_MESH_KEY_UNUSED,
+		}
+	},
+};
+
+/*
+ * Check if an address range from addr_start for addr_start + num_elem - 1 is
+ * free for use. When a conflict is found, next will be set to the next address
+ * available after the conflicting range and -EAGAIN will be returned.
+ */
+static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
+{
+	uint16_t addr_end = addr_start + num_elem - 1;
+	uint16_t other_start, other_end;
+	int i;
+
+	if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
+	    !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
+	    num_elem == 0) {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		other_start = node->addr;
+		other_end = other_start + node->num_elem - 1;
+
+		if (!(addr_end < other_start || addr_start > other_end)) {
+			if (next) {
+				*next = other_end + 1;
+			}
+
+			return -EAGAIN;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Find the lowest possible starting address that can fit num_elem elements. If
+ * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
+ * returned. Otherwise the first address in the range is returned.
+ *
+ * NOTE: This is quite an ineffective algorithm as it might need to look
+ *       through the array of nodes N+2 times. A more effective algorithm
+ *       could be used if the nodes were stored in a sorted list.
+ */
+static uint16_t find_lowest_free_addr(uint8_t num_elem)
+{
+	uint16_t addr = 1, next;
+	int err, i;
+
+	/*
+	 * It takes a maximum of node count + 2 to find a free address if there
+	 * is any. +1 for our own address and +1 for making sure that the
+	 * address range is valid.
+	 */
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
+		err = addr_is_free(addr, num_elem, &next);
+		if (err == 0) {
+			break;
+		} else if (err != -EAGAIN) {
+			addr = BT_MESH_ADDR_UNASSIGNED;
+			break;
+		}
+
+		addr = next;
+	}
+
+	return addr;
+}
+
+int bt_mesh_cdb_create(const uint8_t key[16])
+{
+	struct bt_mesh_cdb_subnet *sub;
+
+	if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
+				    BT_MESH_CDB_VALID)) {
+		return -EALREADY;
+	}
+
+	sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
+	if (sub == NULL) {
+		return -ENOMEM;
+	}
+
+	memcpy(sub->keys[0].net_key, key, 16);
+	bt_mesh_cdb.iv_index = 0;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cdb();
+		bt_mesh_store_cdb_subnet(sub);
+	}
+
+	return 0;
+}
+
+void bt_mesh_cdb_clear(void)
+{
+	int i;
+
+	atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+		if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
+			bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+		if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
+			bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+		if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
+			bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cdb();
+	}
+}
+
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
+{
+	BT_DBG("Updating IV index to %d\n", iv_index);
+
+	bt_mesh_cdb.iv_index = iv_index;
+
+	atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
+			  iv_update);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cdb();
+	}
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
+{
+	struct bt_mesh_cdb_subnet *sub;
+	int i;
+
+	if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+		sub = &bt_mesh_cdb.subnets[i];
+
+		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		sub->net_idx = net_idx;
+
+		return sub;
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
+{
+	BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_clear_cdb_subnet(sub);
+	}
+
+	sub->net_idx = BT_MESH_KEY_UNUSED;
+	memset(sub->keys, 0, sizeof(sub->keys));
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+		if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
+			return &bt_mesh_cdb.subnets[i];
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
+{
+	bt_mesh_store_cdb_subnet(sub);
+}
+
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
+{
+	uint8_t flags = 0x00;
+
+	if (sub && sub->kr_flag) {
+		flags |= BT_MESH_NET_FLAG_KR;
+	}
+
+	if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
+		flags |= BT_MESH_NET_FLAG_IVU;
+	}
+
+	return flags;
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+						uint8_t num_elem, uint16_t net_idx)
+{
+	int i;
+
+	if (addr == BT_MESH_ADDR_UNASSIGNED) {
+		addr = find_lowest_free_addr(num_elem);
+		if (addr == BT_MESH_ADDR_UNASSIGNED) {
+			return NULL;
+		}
+	} else if (addr_is_free(addr, num_elem, NULL) < 0) {
+		BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
+		       addr + num_elem - 1);
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+			memcpy(node->uuid, uuid, 16);
+			node->addr = addr;
+			node->num_elem = num_elem;
+			node->net_idx = net_idx;
+			atomic_set(node->flags, 0);
+			return node;
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
+{
+	BT_DBG("Node addr 0x%04x store %u", node->addr, store);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_clear_cdb_node(node);
+	}
+
+	node->addr = BT_MESH_ADDR_UNASSIGNED;
+	memset(node->dev_key, 0, sizeof(node->dev_key));
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+		struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+		if (addr >= node->addr &&
+		    addr <= node->addr + node->num_elem - 1) {
+			return node;
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
+{
+	bt_mesh_store_cdb_node(node);
+}
+
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+		if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		if (func(&bt_mesh_cdb.nodes[i], user_data) ==
+		    BT_MESH_CDB_ITER_STOP) {
+			break;
+		}
+	}
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+						      uint16_t app_idx)
+{
+	struct bt_mesh_cdb_app_key *key;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+		key = &bt_mesh_cdb.app_keys[i];
+
+		if (key->net_idx != BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		key->net_idx = net_idx;
+		key->app_idx = app_idx;
+
+		return key;
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
+{
+	BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_clear_cdb_app_key(key);
+	}
+
+	key->net_idx = BT_MESH_ADDR_UNASSIGNED;
+	memset(key->keys, 0, sizeof(key->keys));
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
+		struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
+
+		if (key->net_idx != BT_MESH_KEY_UNUSED &&
+		    key->app_idx == app_idx) {
+			return key;
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
+{
+	bt_mesh_store_cdb_app_key(key);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_cli.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_cli.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_cli.c	(working copy)
@@ -0,0 +1,1980 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
+#define LOG_MODULE_NAME bt_mesh_cfg_cli
+#include "common/log.h"
+
+#include "net.h"
+#include "foundation.h"
+
+#define CID_NVAL 0xffff
+
+/* 2 byte dummy opcode for getting compile time buffer sizes. */
+#define DUMMY_2_BYTE_OP	BT_MESH_MODEL_OP_2(0xff, 0xff)
+
+struct comp_data {
+	uint8_t *status;
+	struct net_buf_simple *comp;
+};
+
+static int32_t msg_timeout;
+
+static struct bt_mesh_cfg_cli *cli;
+
+static void comp_data_status(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	struct comp_data *param;
+	size_t to_copy;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_DEV_COMP_DATA_STATUS) {
+		BT_WARN("Unexpected Composition Data Status");
+		return;
+	}
+
+	param = cli->op_param;
+
+	*(param->status) = net_buf_simple_pull_u8(buf);
+	to_copy  = MIN(net_buf_simple_tailroom(param->comp), buf->len);
+	net_buf_simple_add_mem(param->comp, buf->data, to_copy);
+
+	k_sem_give(&cli->op_sync);
+}
+
+static void state_status_u8(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf,
+			    uint32_t expect_status)
+{
+	uint8_t *status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != expect_status) {
+		BT_WARN("Unexpected Status (0x%08x != 0x%08x)",
+			cli->op_pending, expect_status);
+		return;
+	}
+
+	status = cli->op_param;
+	*status = net_buf_simple_pull_u8(buf);
+
+	k_sem_give(&cli->op_sync);
+}
+
+static void beacon_status(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	state_status_u8(model, ctx, buf, OP_BEACON_STATUS);
+}
+
+static void ttl_status(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	state_status_u8(model, ctx, buf, OP_DEFAULT_TTL_STATUS);
+}
+
+static void friend_status(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	state_status_u8(model, ctx, buf, OP_FRIEND_STATUS);
+}
+
+static void gatt_proxy_status(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS);
+}
+
+struct relay_param {
+	uint8_t *status;
+	uint8_t *transmit;
+};
+
+static void relay_status(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	struct relay_param *param;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_RELAY_STATUS) {
+		BT_WARN("Unexpected Relay Status message");
+		return;
+	}
+
+	param = cli->op_param;
+	*param->status = net_buf_simple_pull_u8(buf);
+	*param->transmit = net_buf_simple_pull_u8(buf);
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct net_key_param {
+	uint8_t *status;
+	uint16_t net_idx;
+};
+
+static void net_key_status(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct net_key_param *param;
+	uint16_t net_idx;
+	uint8_t status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_NET_KEY_STATUS) {
+		BT_WARN("Unexpected Net Key Status message");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
+
+	param = cli->op_param;
+	if (param->net_idx != net_idx) {
+		BT_WARN("Net Key Status key index does not match");
+		return;
+	}
+
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct net_key_list_param {
+	uint16_t *keys;
+	size_t *key_cnt;
+};
+
+static void net_key_list(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	struct net_key_list_param *param;
+	int i;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_NET_KEY_LIST) {
+		BT_WARN("Unexpected Net Key List message");
+		return;
+	}
+
+	param = cli->op_param;
+
+	for (i = 0; i < *param->key_cnt && buf->len >= 3; i += 2) {
+		key_idx_unpack(buf, &param->keys[i], &param->keys[i + 1]);
+	}
+
+	if (i < *param->key_cnt && buf->len >= 2) {
+		param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+	}
+
+	*param->key_cnt = i;
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct app_key_param {
+	uint8_t *status;
+	uint16_t net_idx;
+	uint16_t app_idx;
+};
+
+static void app_key_status(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct app_key_param *param;
+	uint16_t net_idx, app_idx;
+	uint8_t status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_APP_KEY_STATUS) {
+		BT_WARN("Unexpected App Key Status message");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+	key_idx_unpack(buf, &net_idx, &app_idx);
+
+	param = cli->op_param;
+	if (param->net_idx != net_idx || param->app_idx != app_idx) {
+		BT_WARN("App Key Status key indices did not match");
+		return;
+	}
+
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct app_key_list_param {
+	uint16_t net_idx;
+	uint8_t *status;
+	uint16_t *keys;
+	size_t *key_cnt;
+};
+
+static void app_key_list(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	struct app_key_list_param *param;
+	uint16_t net_idx;
+	uint8_t status;
+	int i;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_APP_KEY_LIST) {
+		BT_WARN("Unexpected App Key List message");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+	net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
+
+	param = cli->op_param;
+	if (param->net_idx != net_idx) {
+		BT_WARN("App Key List Net Key index did not match");
+		return;
+	}
+
+	for (i = 0; i < *param->key_cnt && buf->len >= 3; i += 2) {
+		key_idx_unpack(buf, &param->keys[i], &param->keys[i + 1]);
+	}
+
+	if (i < *param->key_cnt && buf->len >= 2) {
+		param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+	}
+
+	*param->key_cnt = i;
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct mod_app_param {
+	uint8_t *status;
+	uint16_t elem_addr;
+	uint16_t mod_app_idx;
+	uint16_t mod_id;
+	uint16_t cid;
+};
+
+static void mod_app_status(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, mod_app_idx, mod_id, cid;
+	struct mod_app_param *param;
+	uint8_t status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_MOD_APP_STATUS) {
+		BT_WARN("Unexpected Model App Status message");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+	elem_addr = net_buf_simple_pull_le16(buf);
+	mod_app_idx = net_buf_simple_pull_le16(buf);
+
+	if (buf->len >= 4U) {
+		cid = net_buf_simple_pull_le16(buf);
+	} else {
+		cid = CID_NVAL;
+	}
+
+	mod_id = net_buf_simple_pull_le16(buf);
+
+	param = cli->op_param;
+	if (param->elem_addr != elem_addr ||
+	    param->mod_app_idx != mod_app_idx || param->mod_id != mod_id ||
+	    param->cid != cid) {
+		BT_WARN("Model App Status parameters did not match");
+		return;
+	}
+
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct mod_member_list_param {
+	uint8_t *status;
+	uint16_t elem_addr;
+	uint16_t mod_id;
+	uint16_t cid;
+	uint16_t *members;
+	size_t *member_cnt;
+};
+
+static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx,
+				   struct net_buf_simple *buf, bool vnd)
+{
+	struct mod_member_list_param *param;
+	uint16_t elem_addr, mod_id, cid;
+	uint8_t status;
+	int i;
+
+	status = net_buf_simple_pull_u8(buf);
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (vnd) {
+		cid = net_buf_simple_pull_le16(buf);
+	}
+
+	mod_id = net_buf_simple_pull_le16(buf);
+
+	param = cli->op_param;
+	if (param->elem_addr != elem_addr || param->mod_id != mod_id ||
+	    (vnd && param->cid != cid)) {
+		BT_WARN("Model Member List parameters did not match");
+		return;
+	}
+
+	if (buf->len % 2) {
+		BT_WARN("Model Member List invalid length");
+		return;
+	}
+
+	for (i = 0; i < *param->member_cnt && buf->len; i++) {
+		param->members[i] = net_buf_simple_pull_le16(buf);
+	}
+
+	*param->member_cnt = i;
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+static void mod_app_list(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_SIG_MOD_APP_LIST) {
+		BT_WARN("Unexpected Model App List message");
+		return;
+	}
+
+	mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_app_list_vnd(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_VND_MOD_APP_LIST) {
+		BT_WARN("Unexpected Model App List Vendor message");
+		return;
+	}
+
+	mod_member_list_handle(ctx, buf, true);
+}
+
+struct mod_pub_param {
+	uint16_t                       mod_id;
+	uint16_t                       cid;
+	uint16_t                       elem_addr;
+	uint8_t                       *status;
+	struct bt_mesh_cfg_mod_pub *pub;
+};
+
+static void mod_pub_status(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint16_t mod_id, cid, elem_addr;
+	struct mod_pub_param *param;
+	uint8_t status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_MOD_PUB_STATUS) {
+		BT_WARN("Unexpected Model Pub Status message");
+		return;
+	}
+
+	param = cli->op_param;
+	if (param->cid != CID_NVAL) {
+		if (buf->len < 14) {
+			BT_WARN("Unexpected Mod Pub Status with SIG Model");
+			return;
+		}
+
+		cid = sys_get_le16(&buf->data[10]);
+		mod_id = sys_get_le16(&buf->data[12]);
+	} else {
+		if (buf->len > 12) {
+			BT_WARN("Unexpected Mod Pub Status with Vendor Model");
+			return;
+		}
+
+		cid = CID_NVAL;
+		mod_id = sys_get_le16(&buf->data[10]);
+	}
+
+	if (mod_id != param->mod_id || cid != param->cid) {
+		BT_WARN("Mod Pub Model ID or Company ID mismatch");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (elem_addr != param->elem_addr) {
+		BT_WARN("Model Pub Status for unexpected element (0x%04x)",
+			elem_addr);
+		return;
+	}
+
+	if (param->status) {
+		*param->status = status;
+	}
+
+	if (param->pub) {
+		param->pub->addr = net_buf_simple_pull_le16(buf);
+		param->pub->app_idx = net_buf_simple_pull_le16(buf);
+		param->pub->cred_flag = (param->pub->app_idx & BIT(12));
+		param->pub->app_idx &= BIT_MASK(12);
+		param->pub->ttl = net_buf_simple_pull_u8(buf);
+		param->pub->period = net_buf_simple_pull_u8(buf);
+		param->pub->transmit = net_buf_simple_pull_u8(buf);
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct mod_sub_param {
+	uint8_t *status;
+	uint16_t elem_addr;
+	uint16_t *sub_addr;
+	uint16_t *expect_sub;
+	uint16_t mod_id;
+	uint16_t cid;
+};
+
+static void mod_sub_status(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr, mod_id, cid;
+	struct mod_sub_param *param;
+	uint8_t status;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_MOD_SUB_STATUS) {
+		BT_WARN("Unexpected Model Subscription Status message");
+		return;
+	}
+
+	status = net_buf_simple_pull_u8(buf);
+	elem_addr = net_buf_simple_pull_le16(buf);
+	sub_addr = net_buf_simple_pull_le16(buf);
+
+	if (buf->len >= 4U) {
+		cid = net_buf_simple_pull_le16(buf);
+	} else {
+		cid = CID_NVAL;
+	}
+
+	mod_id = net_buf_simple_pull_le16(buf);
+
+	param = cli->op_param;
+	if (param->elem_addr != elem_addr || param->mod_id != mod_id ||
+	    (param->expect_sub && *param->expect_sub != sub_addr) ||
+	    param->cid != cid) {
+		BT_WARN("Model Subscription Status parameters did not match");
+		return;
+	}
+
+	if (param->sub_addr) {
+		*param->sub_addr = sub_addr;
+	}
+
+	if (param->status) {
+		*param->status = status;
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+static void mod_sub_list(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_MOD_SUB_LIST) {
+		BT_WARN("Unexpected Model Subscription List message");
+		return;
+	}
+
+	mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_sub_list_vnd(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_MOD_SUB_LIST_VND) {
+		BT_WARN("Unexpected Model Subscription List Vendor message");
+		return;
+	}
+
+	mod_member_list_handle(ctx, buf, true);
+}
+
+struct hb_sub_param {
+	uint8_t *status;
+	struct bt_mesh_cfg_hb_sub *sub;
+};
+
+static void hb_sub_status(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	struct hb_sub_param *param;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_HEARTBEAT_SUB_STATUS) {
+		BT_WARN("Unexpected Heartbeat Subscription Status message");
+		return;
+	}
+
+	param = cli->op_param;
+
+	*param->status = net_buf_simple_pull_u8(buf);
+
+	param->sub->src = net_buf_simple_pull_le16(buf);
+	param->sub->dst = net_buf_simple_pull_le16(buf);
+	param->sub->period = net_buf_simple_pull_u8(buf);
+	param->sub->count = net_buf_simple_pull_u8(buf);
+	param->sub->min = net_buf_simple_pull_u8(buf);
+	param->sub->max = net_buf_simple_pull_u8(buf);
+
+	k_sem_give(&cli->op_sync);
+}
+
+struct hb_pub_param {
+	uint8_t *status;
+	struct bt_mesh_cfg_hb_pub *pub;
+};
+
+static void hb_pub_status(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	struct hb_pub_param *param;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (cli->op_pending != OP_HEARTBEAT_PUB_STATUS) {
+		BT_WARN("Unexpected Heartbeat Publication Status message");
+		return;
+	}
+
+	param = cli->op_param;
+
+	*param->status = net_buf_simple_pull_u8(buf);
+
+	if (param->pub) {
+		param->pub->dst = net_buf_simple_pull_le16(buf);
+		param->pub->count = net_buf_simple_pull_u8(buf);
+		param->pub->period = net_buf_simple_pull_u8(buf);
+		param->pub->ttl = net_buf_simple_pull_u8(buf);
+		param->pub->feat = net_buf_simple_pull_u8(buf);
+		param->pub->net_idx = net_buf_simple_pull_u8(buf);
+	}
+
+	k_sem_give(&cli->op_sync);
+}
+
+const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
+	{ OP_DEV_COMP_DATA_STATUS,   15,  comp_data_status },
+	{ OP_BEACON_STATUS,          1,   beacon_status },
+	{ OP_DEFAULT_TTL_STATUS,     1,   ttl_status },
+	{ OP_FRIEND_STATUS,          1,   friend_status },
+	{ OP_GATT_PROXY_STATUS,      1,   gatt_proxy_status },
+	{ OP_RELAY_STATUS,           2,   relay_status },
+	{ OP_NET_KEY_STATUS,         3,   net_key_status },
+	{ OP_NET_KEY_LIST,           0,   net_key_list },
+	{ OP_APP_KEY_STATUS,         4,   app_key_status },
+	{ OP_APP_KEY_LIST,           3,   app_key_list },
+	{ OP_MOD_APP_STATUS,         7,   mod_app_status },
+	{ OP_SIG_MOD_APP_LIST,       5,   mod_app_list},
+	{ OP_VND_MOD_APP_LIST,       7,   mod_app_list_vnd},
+	{ OP_MOD_PUB_STATUS,         12,  mod_pub_status },
+	{ OP_MOD_SUB_STATUS,         7,   mod_sub_status },
+	{ OP_MOD_SUB_LIST,           5,   mod_sub_list},
+	{ OP_MOD_SUB_LIST_VND,       7,   mod_sub_list_vnd},
+	{ OP_HEARTBEAT_SUB_STATUS,   9,   hb_sub_status },
+	{ OP_HEARTBEAT_PUB_STATUS,   10,  hb_pub_status },
+	BT_MESH_MODEL_OP_END,
+};
+
+static int cfg_cli_init(struct bt_mesh_model *model)
+{
+	if (!bt_mesh_model_in_primary(model)) {
+		BT_ERR("Configuration Client only allowed in primary element");
+		return -EINVAL;
+	}
+
+	if (!model->user_data) {
+		BT_ERR("No Configuration Client context provided");
+		return -EINVAL;
+	}
+
+	cli = model->user_data;
+	cli->model = model;
+	msg_timeout = 2 * MSEC_PER_SEC;
+
+	/*
+	 * Configuration Model security is device-key based and both the local
+	 * and remote keys are allowed to access this model.
+	 */
+	model->keys[0] = BT_MESH_KEY_DEV_ANY;
+
+	k_sem_init(&cli->op_sync, 0, 1);
+
+	return 0;
+}
+
+const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = {
+	.init = cfg_cli_init,
+};
+
+static int cli_prepare(void *param, uint32_t op)
+{
+	if (!cli) {
+		BT_ERR("No available Configuration Client context!");
+		return -EINVAL;
+	}
+
+	if (cli->op_pending) {
+		BT_WARN("Another synchronous operation pending");
+		return -EBUSY;
+	}
+
+	cli->op_param = param;
+	cli->op_pending = op;
+
+	return 0;
+}
+
+static void cli_reset(void)
+{
+	cli->op_pending = 0U;
+	cli->op_param = NULL;
+}
+
+static int cli_wait(void)
+{
+	int err;
+
+	err = k_sem_take(&cli->op_sync, SYS_TIMEOUT_MS(msg_timeout));
+
+	cli_reset();
+
+	return err;
+}
+
+int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+			      uint8_t *status, struct net_buf_simple *comp)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_DEV_COMP_DATA_GET, 1);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct comp_data param = {
+		.status = status,
+		.comp = comp,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_DEV_COMP_DATA_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_DEV_COMP_DATA_GET);
+	net_buf_simple_add_u8(&msg, page);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+			uint8_t *val)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	int err;
+
+	err = cli_prepare(val, rsp);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, op);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+			uint8_t new_val, uint8_t *val)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 1);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	int err;
+
+	err = cli_prepare(val, rsp);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, op);
+	net_buf_simple_add_u8(&msg, new_val);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
+{
+	return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS,
+			    status);
+}
+
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
+{
+	return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS,
+			    val, status);
+}
+
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl)
+{
+	return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET,
+			    OP_DEFAULT_TTL_STATUS, ttl);
+}
+
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl)
+{
+	return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET,
+			    OP_DEFAULT_TTL_STATUS, val, ttl);
+}
+
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
+{
+	return get_state_u8(net_idx, addr, OP_FRIEND_GET,
+			    OP_FRIEND_STATUS, status);
+}
+
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
+{
+	return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS,
+			    val, status);
+}
+
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
+{
+	return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET,
+			    OP_GATT_PROXY_STATUS, status);
+}
+
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+			       uint8_t *status)
+{
+	return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET,
+			    OP_GATT_PROXY_STATUS, val, status);
+}
+
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+		uint8_t val, uint8_t *transmit)
+{
+	return set_state_u8(net_idx, addr, OP_NET_TRANSMIT_SET,
+				OP_NET_TRANSMIT_STATUS, val, transmit);
+}
+
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+		uint8_t *transmit)
+{
+	return get_state_u8(net_idx, addr, OP_NET_TRANSMIT_GET,
+			OP_NET_TRANSMIT_STATUS, transmit);
+}
+
+
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+			  uint8_t *transmit)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct relay_param param = {
+		.status = status,
+		.transmit = transmit,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_RELAY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_RELAY_GET);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+			  uint8_t new_transmit, uint8_t *status, uint8_t *transmit)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_SET, 2);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct relay_param param = {
+		.status = status,
+		.transmit = transmit,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_RELAY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_RELAY_SET);
+	net_buf_simple_add_u8(&msg, new_relay);
+	net_buf_simple_add_u8(&msg, new_transmit);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			    const uint8_t net_key[16], uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_ADD, 18);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct net_key_param param = {
+		.status = status,
+		.net_idx = key_net_idx,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_NET_KEY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NET_KEY_ADD);
+	net_buf_simple_add_le16(&msg, key_net_idx);
+	net_buf_simple_add_mem(&msg, net_key, 16);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+			     size_t *key_cnt)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct net_key_list_param param = {
+		.keys = keys,
+		.key_cnt = key_cnt,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_NET_KEY_LIST);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NET_KEY_GET);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+			    uint16_t key_net_idx, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_DEL, 2);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct net_key_param param = {
+		.status = status,
+		.net_idx = key_net_idx,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_NET_KEY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NET_KEY_DEL);
+	net_buf_simple_add_le16(&msg, key_net_idx);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			    uint16_t key_app_idx, const uint8_t app_key[16],
+			    uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_ADD, 19);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct app_key_param param = {
+		.status = status,
+		.net_idx = key_net_idx,
+		.app_idx = key_app_idx,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_APP_KEY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_ADD);
+	key_idx_pack(&msg, key_net_idx, key_app_idx);
+	net_buf_simple_add_mem(&msg, app_key, 16);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+			     uint8_t *status, uint16_t *keys, size_t *key_cnt)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_GET, 2);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct app_key_list_param param = {
+		.net_idx = key_net_idx,
+		.status = status,
+		.keys = keys,
+		.key_cnt = key_cnt,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_APP_KEY_LIST);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_GET);
+	net_buf_simple_add_le16(&msg, key_net_idx);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+	uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_DEL, 3);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct app_key_param param = {
+		.status = status,
+		.net_idx = key_net_idx,
+		.app_idx = key_app_idx,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_APP_KEY_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_DEL);
+	key_idx_pack(&msg, key_net_idx, key_app_idx);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+			uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_BIND, 8);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_app_param param = {
+		.status = status,
+		.elem_addr = elem_addr,
+		.mod_app_idx = mod_app_idx,
+		.mod_id = mod_id,
+		.cid = cid,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_APP_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_APP_BIND);
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_le16(&msg, mod_app_idx);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			     uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status)
+{
+	return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
+			    CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id, cid,
+			    status);
+}
+
+static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+			uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_UNBIND, 8);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_app_param param = {
+		.status = status,
+		.elem_addr = elem_addr,
+		.mod_app_idx = mod_app_idx,
+		.mod_id = mod_id,
+		.cid = cid,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_APP_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_APP_UNBIND);
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_le16(&msg, mod_app_idx);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+	uint16_t elem_addr, uint16_t mod_app_idx,
+	uint16_t mod_id, uint8_t *status)
+{
+	return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
+			CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+		uint16_t elem_addr, uint16_t mod_app_idx,
+		uint16_t mod_id, uint16_t cid, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx,
+			mod_id, cid, status);
+}
+
+static int mod_member_list_get(uint32_t op, uint32_t expect_op, uint16_t net_idx,
+			       uint16_t addr, uint16_t elem_addr, uint16_t mod_id,
+			       uint16_t cid, uint8_t *status, uint16_t *apps,
+			       size_t *app_cnt)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 6);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_member_list_param param = {
+		.status = status,
+		.elem_addr = elem_addr,
+		.mod_id = mod_id,
+		.cid = cid,
+		.members = apps,
+		.member_cnt = app_cnt,
+	};
+	int err;
+
+	err = cli_prepare(&param, expect_op);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x",
+	       net_idx, addr, elem_addr);
+	BT_DBG("mod_id 0x%04x cid 0x%04x op: %x", mod_id, cid, op);
+
+	bt_mesh_model_msg_init(&msg, op);
+	net_buf_simple_add_le16(&msg, elem_addr);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, uint8_t *status, uint16_t *apps,
+			    size_t *app_cnt)
+{
+	return mod_member_list_get(OP_SIG_MOD_APP_GET, OP_SIG_MOD_APP_LIST,
+				   net_idx, addr, elem_addr, mod_id, CID_NVAL,
+				   status, apps, app_cnt);
+}
+
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid, uint8_t *status,
+				uint16_t *apps, size_t *app_cnt)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST,
+				   net_idx, addr, elem_addr, mod_id, CID_NVAL,
+				   status, apps, app_cnt);
+}
+
+static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+		   uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 8);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_sub_param param = {
+		.status = status,
+		.elem_addr = elem_addr,
+		.expect_sub = &sub_addr,
+		.mod_id = mod_id,
+		.cid = cid,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_SUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, op);
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_le16(&msg, sub_addr);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
+{
+	return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
+		       mod_id, CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
+		       mod_id, cid, status);
+}
+
+int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
+{
+	return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
+		       mod_id, CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				 uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+				 uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
+		       mod_id, cid, status);
+}
+
+int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				  uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
+{
+	return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
+		       sub_addr, mod_id, CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+				      uint16_t elem_addr, uint16_t sub_addr,
+				      uint16_t mod_id, uint16_t cid, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
+		       sub_addr, mod_id, cid, status);
+}
+
+static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+		      const uint8_t label[16], uint16_t mod_id, uint16_t cid,
+		      uint16_t *virt_addr, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 22);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_sub_param param = {
+		.status = status,
+		.elem_addr = elem_addr,
+		.sub_addr = virt_addr,
+		.mod_id = mod_id,
+		.cid = cid,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_SUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s",
+	       net_idx, addr, elem_addr, label);
+	BT_DBG("mod_id 0x%04x cid 0x%04x", mod_id, cid);
+
+	bt_mesh_model_msg_init(&msg, op);
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_mem(&msg, label, 16);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			       const uint8_t label[16], uint16_t mod_id,
+			       uint16_t *virt_addr, uint8_t *status)
+{
+	return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
+			  mod_id, CID_NVAL, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				   const uint8_t label[16], uint16_t mod_id,
+				   uint16_t cid, uint16_t *virt_addr, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
+			  mod_id, cid, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			       const uint8_t label[16], uint16_t mod_id,
+			       uint16_t *virt_addr, uint8_t *status)
+{
+	return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
+			  mod_id, CID_NVAL, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				   const uint8_t label[16], uint16_t mod_id,
+				   uint16_t cid, uint16_t *virt_addr, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
+			  mod_id, cid, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+				     uint16_t elem_addr, const uint8_t label[16],
+				     uint16_t mod_id, uint16_t *virt_addr,
+				     uint8_t *status)
+{
+	return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
+			  label, mod_id, CID_NVAL, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+					 uint16_t elem_addr, const uint8_t label[16],
+					 uint16_t mod_id, uint16_t cid,
+					 uint16_t *virt_addr, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
+			  label, mod_id, cid, virt_addr, status);
+}
+
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, uint8_t *status, uint16_t *subs,
+			    size_t *sub_cnt)
+{
+	return mod_member_list_get(OP_MOD_SUB_GET, OP_MOD_SUB_LIST, net_idx,
+				   addr, elem_addr, mod_id, CID_NVAL, status,
+				   subs, sub_cnt);
+}
+
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid, uint8_t *status,
+				uint16_t *subs, size_t *sub_cnt)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND,
+				   net_idx, addr, elem_addr, mod_id, CID_NVAL,
+				   status, subs, sub_cnt);
+}
+
+static int mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+		       uint16_t mod_id, uint16_t cid,
+		       struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_GET, 6);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_pub_param param = {
+		.mod_id = mod_id,
+		.cid = cid,
+		.elem_addr = elem_addr,
+		.status = status,
+		.pub = pub,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_PUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_PUB_GET);
+
+	net_buf_simple_add_le16(&msg, elem_addr);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+			    uint8_t *status)
+{
+	return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL,
+			   pub, status);
+}
+
+int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid,
+				struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status);
+}
+
+static int mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+		       uint16_t mod_id, uint16_t cid,
+		       struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_SET, 13);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct mod_pub_param param = {
+		.mod_id = mod_id,
+		.cid = cid,
+		.elem_addr = elem_addr,
+		.status = status,
+		.pub = pub,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_MOD_PUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_PUB_SET);
+
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_le16(&msg, pub->addr);
+	net_buf_simple_add_le16(&msg, (pub->app_idx | (pub->cred_flag << 12)));
+	net_buf_simple_add_u8(&msg, pub->ttl);
+	net_buf_simple_add_u8(&msg, pub->period);
+	net_buf_simple_add_u8(&msg, pub->transmit);
+
+	if (cid != CID_NVAL) {
+		net_buf_simple_add_le16(&msg, cid);
+	}
+
+	net_buf_simple_add_le16(&msg, mod_id);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+			    uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+			    uint8_t *status)
+{
+	return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL,
+			   pub, status);
+}
+
+int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+				uint16_t mod_id, uint16_t cid,
+				struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
+{
+	if (cid == CID_NVAL) {
+		return -EINVAL;
+	}
+
+	return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status);
+}
+
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_SET, 5);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct hb_sub_param param = {
+		.status = status,
+		.sub = sub,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEARTBEAT_SUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_SET);
+	net_buf_simple_add_le16(&msg, sub->src);
+	net_buf_simple_add_le16(&msg, sub->dst);
+	net_buf_simple_add_u8(&msg, sub->period);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct hb_sub_param param = {
+		.status = status,
+		.sub = sub,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEARTBEAT_SUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_GET);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+			   const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_SET, 9);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct hb_pub_param param = {
+		.status = status,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEARTBEAT_PUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_SET);
+	net_buf_simple_add_le16(&msg, pub->dst);
+	net_buf_simple_add_u8(&msg, pub->count);
+	net_buf_simple_add_u8(&msg, pub->period);
+	net_buf_simple_add_u8(&msg, pub->ttl);
+	net_buf_simple_add_le16(&msg, pub->feat);
+	net_buf_simple_add_le16(&msg, pub->net_idx);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+			   struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = net_idx,
+		.app_idx = BT_MESH_KEY_DEV_REMOTE,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct hb_pub_param param = {
+		.status = status,
+		.pub = pub,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEARTBEAT_PUB_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_GET);
+
+	err = bt_mesh_model_send(cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!status) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int32_t bt_mesh_cfg_cli_timeout_get(void)
+{
+	return msg_timeout;
+}
+
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout)
+{
+	msg_timeout = timeout;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_srv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_srv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/cfg_srv.c	(working copy)
@@ -0,0 +1,3574 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
+#define LOG_MODULE_NAME bt_mesh_cfg_srv
+#include "common/log.h"
+
+#include "host/testing.h"
+
+#include "mesh.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "lpn.h"
+#include "transport.h"
+#include "crypto.h"
+#include "access.h"
+#include "beacon.h"
+#include "proxy.h"
+#include "foundation.h"
+#include "friend.h"
+#include "settings.h"
+
+#define DEFAULT_TTL 7
+
+static struct bt_mesh_cfg_srv *conf;
+
+static struct label labels[CONFIG_BT_MESH_LABEL_COUNT];
+
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+static uint8_t va_del(uint8_t *label_uuid, uint16_t *addr);
+#endif
+
+static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
+			 bool primary)
+{
+	struct bt_mesh_model *mod;
+	int i;
+
+	if (net_buf_simple_tailroom(buf) <
+	    4 + (elem->model_count * 2U) + (elem->vnd_model_count * 4U)) {
+		BT_ERR("Too large device composition");
+		return -E2BIG;
+	}
+
+	net_buf_simple_add_le16(buf, elem->loc);
+
+	net_buf_simple_add_u8(buf, elem->model_count);
+	net_buf_simple_add_u8(buf, elem->vnd_model_count);
+
+	for (i = 0; i < elem->model_count; i++) {
+		mod = &elem->models[i];
+		net_buf_simple_add_le16(buf, mod->id);
+	}
+
+	for (i = 0; i < elem->vnd_model_count; i++) {
+		mod = &elem->vnd_models[i];
+		net_buf_simple_add_le16(buf, mod->vnd.company);
+		net_buf_simple_add_le16(buf, mod->vnd.id);
+	}
+
+	return 0;
+}
+
+static int comp_get_page_0(struct net_buf_simple *buf)
+{
+	uint16_t feat = 0U;
+	const struct bt_mesh_comp *comp;
+	int i;
+
+	comp = bt_mesh_comp_get();
+
+	if (IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
+		feat |= BT_MESH_FEAT_RELAY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		feat |= BT_MESH_FEAT_PROXY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		feat |= BT_MESH_FEAT_FRIEND;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		feat |= BT_MESH_FEAT_LOW_POWER;
+	}
+
+	net_buf_simple_add_le16(buf, comp->cid);
+	net_buf_simple_add_le16(buf, comp->pid);
+	net_buf_simple_add_le16(buf, comp->vid);
+	net_buf_simple_add_le16(buf, CONFIG_BT_MESH_CRPL);
+	net_buf_simple_add_le16(buf, feat);
+
+	for (i = 0; i < comp->elem_count; i++) {
+		int err;
+
+		err = comp_add_elem(buf, &comp->elem[i], i == 0);
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static void dev_comp_data_get(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	uint8_t page;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	page = net_buf_simple_pull_u8(buf);
+	if (page != 0U) {
+		BT_DBG("Composition page %u not available", page);
+		page = 0U;
+	}
+
+	bt_mesh_model_msg_init(&sdu, OP_DEV_COMP_DATA_STATUS);
+
+	net_buf_simple_add_u8(&sdu, page);
+	if (comp_get_page_0(&sdu) < 0) {
+		BT_ERR("Unable to get composition page 0");
+		return;
+	}
+
+	if (bt_mesh_model_send(model, ctx, &sdu, NULL, NULL)) {
+		BT_ERR("Unable to send Device Composition Status response");
+	}
+}
+
+static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
+				       struct net_buf_simple *buf, bool *vnd)
+{
+	if (buf->len < 4) {
+		uint16_t id;
+
+		id = net_buf_simple_pull_le16(buf);
+
+		BT_DBG("ID 0x%04x addr 0x%04x", id, elem->addr);
+
+		*vnd = false;
+
+		return bt_mesh_model_find(elem, id);
+	} else {
+		uint16_t company, id;
+
+		company = net_buf_simple_pull_le16(buf);
+		id = net_buf_simple_pull_le16(buf);
+
+		BT_DBG("Company 0x%04x ID 0x%04x addr 0x%04x", company, id,
+		       elem->addr);
+
+		*vnd = true;
+
+		return bt_mesh_model_find_vnd(elem, company, id);
+	}
+}
+
+static bool app_key_is_valid(uint16_t app_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx != BT_MESH_KEY_UNUSED &&
+		    key->app_idx == app_idx) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
+			 uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period,
+			 uint8_t retransmit, bool store)
+{
+	if (!model->pub) {
+		return STATUS_NVAL_PUB_PARAM;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && cred_flag) {
+		return STATUS_FEAT_NOT_SUPP;
+	}
+
+	if (!model->pub->update && period) {
+		return STATUS_NVAL_PUB_PARAM;
+	}
+
+	if (pub_addr == BT_MESH_ADDR_UNASSIGNED) {
+		if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
+			return STATUS_SUCCESS;
+		}
+
+		model->pub->addr = BT_MESH_ADDR_UNASSIGNED;
+		model->pub->key = 0U;
+		model->pub->cred = 0U;
+		model->pub->ttl = 0U;
+		model->pub->period = 0U;
+		model->pub->retransmit = 0U;
+		model->pub->count = 0U;
+
+		if (model->pub->update) {
+			k_delayed_work_cancel(&model->pub->timer);
+		}
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+			bt_mesh_store_mod_pub(model);
+		}
+
+		return STATUS_SUCCESS;
+	}
+
+	if (!bt_mesh_app_key_find(app_idx)) {
+		return STATUS_INVALID_APPKEY;
+	}
+
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+	if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) {
+		uint8_t *uuid = bt_mesh_label_uuid_get(model->pub->addr);
+
+		if (uuid) {
+			va_del(uuid, NULL);
+		}
+	}
+#endif
+
+	model->pub->addr = pub_addr;
+	model->pub->key = app_idx;
+	model->pub->cred = cred_flag;
+	model->pub->ttl = ttl;
+	model->pub->period = period;
+	model->pub->retransmit = retransmit;
+
+	if (model->pub->update) {
+		int32_t period_ms;
+
+		period_ms = bt_mesh_model_pub_period_get(model);
+		BT_DBG("period %u ms", period_ms);
+
+		if (period_ms > 0) {
+			k_delayed_work_submit(&model->pub->timer,
+					      K_MSEC(period_ms));
+		} else {
+			k_delayed_work_cancel(&model->pub->timer);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_store_mod_pub(model);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx)
+{
+	int i;
+
+	BT_DBG("model %p key_idx 0x%03x", model, key_idx);
+
+	if (!app_key_is_valid(key_idx)) {
+		return STATUS_INVALID_APPKEY;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
+		/* Treat existing binding as success */
+		if (model->keys[i] == key_idx) {
+			return STATUS_SUCCESS;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
+		if (model->keys[i] == BT_MESH_KEY_UNUSED) {
+			model->keys[i] = key_idx;
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_mod_bind(model);
+			}
+
+			return STATUS_SUCCESS;
+		}
+	}
+
+	return STATUS_INSUFF_RESOURCES;
+}
+
+static uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store)
+{
+	int i;
+
+	BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
+
+	if (!app_key_is_valid(key_idx)) {
+		return STATUS_INVALID_APPKEY;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(model->keys); i++) {
+		if (model->keys[i] != key_idx) {
+			continue;
+		}
+
+		model->keys[i] = BT_MESH_KEY_UNUSED;
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+			bt_mesh_store_mod_bind(model);
+		}
+
+		if (model->pub && model->pub->key == key_idx) {
+			_mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED,
+				     0, 0, 0, 0, 0, store);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx == BT_MESH_KEY_UNUSED) {
+			return key;
+		}
+	}
+
+	return NULL;
+}
+
+static uint8_t app_key_set(uint16_t net_idx, uint16_t app_idx, const uint8_t val[16],
+			bool update)
+{
+	struct bt_mesh_app_keys *keys;
+	struct bt_mesh_app_key *key;
+	struct bt_mesh_subnet *sub;
+
+	BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s",
+	       net_idx, app_idx, update, bt_hex(val, 16));
+
+	sub = bt_mesh_subnet_get(net_idx);
+	if (!sub) {
+		return STATUS_INVALID_NETKEY;
+	}
+
+	key = bt_mesh_app_key_find(app_idx);
+	if (update) {
+		if (!key) {
+			return STATUS_INVALID_APPKEY;
+		}
+
+		if (key->net_idx != net_idx) {
+			return STATUS_INVALID_BINDING;
+		}
+
+		keys = &key->keys[1];
+
+		/* The AppKey Update message shall generate an error when node
+		 * is in normal operation, Phase 2, or Phase 3 or in Phase 1
+		 * when the AppKey Update message on a valid AppKeyIndex when
+		 * the AppKey value is different.
+		 */
+		if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
+			return STATUS_CANNOT_UPDATE;
+		}
+
+		if (key->updated) {
+			if (memcmp(keys->val, val, 16)) {
+				return STATUS_CANNOT_UPDATE;
+			} else {
+				return STATUS_SUCCESS;
+			}
+		}
+
+		key->updated = true;
+	} else {
+		if (key) {
+			if (key->net_idx == net_idx &&
+			    !memcmp(key->keys[0].val, val, 16)) {
+				return STATUS_SUCCESS;
+			}
+
+			if (key->net_idx == net_idx) {
+				return STATUS_IDX_ALREADY_STORED;
+			} else {
+				return STATUS_INVALID_NETKEY;
+			}
+		}
+
+		key = bt_mesh_app_key_alloc(app_idx);
+		if (!key) {
+			return STATUS_INSUFF_RESOURCES;
+		}
+
+		keys = &key->keys[0];
+	}
+
+	if (bt_mesh_app_id(val, &keys->id)) {
+		if (update) {
+			key->updated = false;
+		}
+
+		return STATUS_STORAGE_FAIL;
+	}
+
+	BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id);
+
+	key->net_idx = net_idx;
+	key->app_idx = app_idx;
+	memcpy(keys->val, val, 16);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing AppKey persistently");
+		bt_mesh_store_app_key(key);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void app_key_add(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
+	uint16_t key_net_idx, key_app_idx;
+	uint8_t status;
+
+	key_idx_unpack(buf, &key_net_idx, &key_app_idx);
+
+	BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
+
+	status = app_key_set(key_net_idx, key_app_idx, buf->data, false);
+	BT_DBG("status 0x%02x", status);
+	net_buf_simple_add_u8(&msg, status);
+
+	key_idx_pack(&msg, key_net_idx, key_app_idx);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send App Key Status response");
+	}
+}
+
+static void app_key_update(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
+	uint16_t key_net_idx, key_app_idx;
+	uint8_t status;
+
+	key_idx_unpack(buf, &key_net_idx, &key_app_idx);
+
+	BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
+
+	status = app_key_set(key_net_idx, key_app_idx, buf->data, true);
+	BT_DBG("status 0x%02x", status);
+	net_buf_simple_add_u8(&msg, status);
+
+	key_idx_pack(&msg, key_net_idx, key_app_idx);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send App Key Status response");
+	}
+}
+
+struct unbind_data {
+	uint16_t app_idx;
+	bool store;
+};
+
+static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+			bool vnd, bool primary, void *user_data)
+{
+	struct unbind_data *data = user_data;
+
+	mod_unbind(mod, data->app_idx, data->store);
+}
+
+void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
+{
+	struct unbind_data data = { .app_idx = key->app_idx, .store = store };
+
+	BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
+
+	bt_mesh_model_foreach(_mod_unbind, &data);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_clear_app_key(key);
+	}
+
+	key->net_idx = BT_MESH_KEY_UNUSED;
+	(void)memset(key->keys, 0, sizeof(key->keys));
+}
+
+static void app_key_del(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
+	uint16_t key_net_idx, key_app_idx;
+	struct bt_mesh_app_key *key;
+	uint8_t status;
+
+	key_idx_unpack(buf, &key_net_idx, &key_app_idx);
+
+	BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
+
+	if (!bt_mesh_subnet_get(key_net_idx)) {
+		status = STATUS_INVALID_NETKEY;
+		goto send_status;
+	}
+
+	key = bt_mesh_app_key_find(key_app_idx);
+	if (!key) {
+		/* Treat as success since the client might have missed a
+		 * previous response and is resending the request.
+		 */
+		status = STATUS_SUCCESS;
+		goto send_status;
+	}
+
+	if (key->net_idx != key_net_idx) {
+		status = STATUS_INVALID_BINDING;
+		goto send_status;
+	}
+
+	bt_mesh_app_key_del(key, true);
+	status = STATUS_SUCCESS;
+
+send_status:
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+
+	key_idx_pack(&msg, key_net_idx, key_app_idx);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send App Key Status response");
+	}
+}
+
+/* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */
+#define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2)
+
+static void app_key_get(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_LIST,
+				 3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
+	uint16_t get_idx, i, prev;
+	uint8_t status;
+
+	get_idx = net_buf_simple_pull_le16(buf);
+	if (get_idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", get_idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x", get_idx);
+
+	bt_mesh_model_msg_init(&msg, OP_APP_KEY_LIST);
+
+	if (!bt_mesh_subnet_get(get_idx)) {
+		status = STATUS_INVALID_NETKEY;
+	} else {
+		status = STATUS_SUCCESS;
+	}
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, get_idx);
+
+	if (status != STATUS_SUCCESS) {
+		goto send_status;
+	}
+
+	prev = BT_MESH_KEY_UNUSED;
+	for (i = 0U; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx != get_idx) {
+			continue;
+		}
+
+		if (prev == BT_MESH_KEY_UNUSED) {
+			prev = key->app_idx;
+			continue;
+		}
+
+		key_idx_pack(&msg, prev, key->app_idx);
+		prev = BT_MESH_KEY_UNUSED;
+	}
+
+	if (prev != BT_MESH_KEY_UNUSED) {
+		net_buf_simple_add_le16(&msg, prev);
+	}
+
+send_status:
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send AppKey List");
+	}
+}
+
+static void beacon_get(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_beacon_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Config Beacon Status response");
+	}
+}
+
+static void beacon_set(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (buf->data[0] == 0x00 || buf->data[0] == 0x01) {
+		if (buf->data[0] != cfg->beacon) {
+			cfg->beacon = buf->data[0];
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_cfg();
+			}
+
+			if (cfg->beacon) {
+				bt_mesh_beacon_enable();
+			} else {
+				bt_mesh_beacon_disable();
+			}
+		}
+	} else {
+		BT_WARN("Invalid Config Beacon value 0x%02x", buf->data[0]);
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_beacon_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Config Beacon Status response");
+	}
+}
+
+static void default_ttl_get(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	bt_mesh_model_msg_init(&msg, OP_DEFAULT_TTL_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_default_ttl_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Default TTL Status response");
+	}
+}
+
+static void default_ttl_set(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (buf->data[0] <= BT_MESH_TTL_MAX && buf->data[0] != 0x01) {
+		if (cfg->default_ttl != buf->data[0]) {
+			cfg->default_ttl = buf->data[0];
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_cfg();
+			}
+		}
+	} else {
+		BT_WARN("Prohibited Default TTL value 0x%02x", buf->data[0]);
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_DEFAULT_TTL_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_default_ttl_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Default TTL Status response");
+	}
+}
+
+static void send_gatt_proxy_status(struct bt_mesh_model *model,
+				   struct bt_mesh_msg_ctx *ctx)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_GATT_PROXY_STATUS, 1);
+
+	bt_mesh_model_msg_init(&msg, OP_GATT_PROXY_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_gatt_proxy_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send GATT Proxy Status");
+	}
+}
+
+static void gatt_proxy_get(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	send_gatt_proxy_status(model, ctx);
+}
+
+static void gatt_proxy_set(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (buf->data[0] != 0x00 && buf->data[0] != 0x01) {
+		BT_WARN("Invalid GATT Proxy value 0x%02x", buf->data[0]);
+		return;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) ||
+	    bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
+		goto send_status;
+	}
+
+	BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->data[0]);
+
+	if (cfg->gatt_proxy == buf->data[0]) {
+		goto send_status;
+	}
+
+	cfg->gatt_proxy = buf->data[0];
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cfg();
+	}
+
+	if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) {
+		(void)bt_mesh_heartbeat_send(NULL, NULL);
+	}
+
+send_status:
+	send_gatt_proxy_status(model, ctx);
+}
+
+static void net_transmit_get(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	bt_mesh_model_msg_init(&msg, OP_NET_TRANSMIT_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_net_transmit_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Config Network Transmit Status");
+	}
+}
+
+static void net_transmit_set(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	BT_DBG("Transmit 0x%02x (count %u interval %ums)", buf->data[0],
+	       BT_MESH_TRANSMIT_COUNT(buf->data[0]),
+	       BT_MESH_TRANSMIT_INT(buf->data[0]));
+
+	cfg->net_transmit = buf->data[0];
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cfg();
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NET_TRANSMIT_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_net_transmit_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Network Transmit Status");
+	}
+}
+
+static void relay_get(struct bt_mesh_model *model,
+		      struct bt_mesh_msg_ctx *ctx,
+		      struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	bt_mesh_model_msg_init(&msg, OP_RELAY_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_relay_get());
+	net_buf_simple_add_u8(&msg, bt_mesh_relay_retransmit_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Config Relay Status response");
+	}
+}
+
+static void relay_set(struct bt_mesh_model *model,
+		      struct bt_mesh_msg_ctx *ctx,
+		      struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (buf->data[0] == 0x00 || buf->data[0] == 0x01) {
+		bool change;
+
+		if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
+			change = false;
+		} else {
+			change = (cfg->relay != buf->data[0]);
+			cfg->relay = buf->data[0];
+			cfg->relay_retransmit = buf->data[1];
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_cfg();
+			}
+		}
+
+		BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)",
+		       cfg->relay, change ? "changed" : "not changed",
+		       cfg->relay_retransmit,
+		       BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
+		       BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
+
+		if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) {
+			(void)bt_mesh_heartbeat_send(NULL, NULL);
+		}
+	} else {
+		BT_WARN("Invalid Relay value 0x%02x", buf->data[0]);
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_RELAY_STATUS);
+	net_buf_simple_add_u8(&msg, bt_mesh_relay_get());
+	net_buf_simple_add_u8(&msg, bt_mesh_relay_retransmit_get());
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Relay Status response");
+	}
+}
+
+static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
+				struct bt_mesh_msg_ctx *ctx,
+				uint16_t elem_addr, uint16_t pub_addr,
+				bool vnd, struct bt_mesh_model *mod,
+				uint8_t status, uint8_t *mod_id)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_STATUS, 14);
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_PUB_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, elem_addr);
+
+	if (status != STATUS_SUCCESS) {
+		(void)memset(net_buf_simple_add(&msg, 7), 0, 7);
+	} else {
+		uint16_t idx_cred;
+
+		net_buf_simple_add_le16(&msg, pub_addr);
+
+		idx_cred = mod->pub->key | (uint16_t)mod->pub->cred << 12;
+		net_buf_simple_add_le16(&msg, idx_cred);
+		net_buf_simple_add_u8(&msg, mod->pub->ttl);
+		net_buf_simple_add_u8(&msg, mod->pub->period);
+		net_buf_simple_add_u8(&msg, mod->pub->retransmit);
+	}
+
+	if (vnd) {
+		memcpy(net_buf_simple_add(&msg, 4), mod_id, 4);
+	} else {
+		memcpy(net_buf_simple_add(&msg, 2), mod_id, 2);
+	}
+
+	if (bt_mesh_model_send(cfg_mod, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model Publication Status");
+	}
+}
+
+static void mod_pub_get(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, pub_addr = 0U;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id, status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	mod_id = buf->data;
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	if (!mod->pub) {
+		status = STATUS_NVAL_PUB_PARAM;
+		goto send_status;
+	}
+
+	pub_addr = mod->pub->addr;
+	status = STATUS_SUCCESS;
+
+send_status:
+	send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
+			    status, mod_id);
+}
+
+static void mod_pub_set(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+	uint16_t elem_addr, pub_addr, pub_app_idx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	pub_addr = net_buf_simple_pull_le16(buf);
+	pub_app_idx = net_buf_simple_pull_le16(buf);
+	cred_flag = ((pub_app_idx >> 12) & BIT_MASK(1));
+	pub_app_idx &= BIT_MASK(12);
+
+	pub_ttl = net_buf_simple_pull_u8(buf);
+	if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) {
+		BT_ERR("Invalid TTL value 0x%02x", pub_ttl);
+		return;
+	}
+
+	pub_period = net_buf_simple_pull_u8(buf);
+	retransmit = net_buf_simple_pull_u8(buf);
+	mod_id = buf->data;
+
+	BT_DBG("elem_addr 0x%04x pub_addr 0x%04x cred_flag %u",
+	       elem_addr, pub_addr, cred_flag);
+	BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x",
+	       pub_app_idx, pub_ttl, pub_period);
+	BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit,
+	       BT_MESH_PUB_TRANSMIT_COUNT(retransmit),
+	       BT_MESH_PUB_TRANSMIT_INT(retransmit));
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
+			      pub_period, retransmit, true);
+
+send_status:
+	send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
+			    status, mod_id);
+}
+
+struct label *get_label(uint16_t index)
+{
+	if (index >= ARRAY_SIZE(labels)) {
+		return NULL;
+	}
+
+	return &labels[index];
+}
+
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+static inline void va_store(struct label *store)
+{
+	atomic_set_bit(store->flags, BT_MESH_VA_CHANGED);
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_label();
+	}
+}
+
+static struct label *va_find(const uint8_t *label_uuid,
+				struct label **free_slot)
+{
+	struct label *match = NULL;
+	int i;
+
+	if (free_slot != NULL) {
+		*free_slot = NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(labels); i++) {
+		if (labels[i].ref == 0) {
+			if (free_slot != NULL) {
+				*free_slot = &labels[i];
+			}
+			continue;
+		}
+
+		if (!memcmp(labels[i].uuid, label_uuid, 16)) {
+			match = &labels[i];
+		}
+	}
+
+	return match;
+}
+
+static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr)
+{
+	struct label *update, *free_slot = NULL;
+
+	update = va_find(label_uuid, &free_slot);
+	if (update) {
+		update->ref++;
+		va_store(update);
+		return STATUS_SUCCESS;
+	}
+
+	if (!free_slot) {
+		return STATUS_INSUFF_RESOURCES;
+	}
+
+	if (bt_mesh_virtual_addr(label_uuid, addr) < 0) {
+		return STATUS_UNSPECIFIED;
+	}
+
+	free_slot->ref = 1U;
+	free_slot->addr = *addr;
+	memcpy(free_slot->uuid, label_uuid, 16);
+	va_store(free_slot);
+
+	return STATUS_SUCCESS;
+}
+
+static uint8_t va_del(uint8_t *label_uuid, uint16_t *addr)
+{
+	struct label *update;
+
+	update = va_find(label_uuid, NULL);
+	if (update) {
+		update->ref--;
+
+		if (addr) {
+			*addr = update->addr;
+		}
+
+		va_store(update);
+		return STATUS_SUCCESS;
+	}
+
+	if (addr) {
+		*addr = BT_MESH_ADDR_UNASSIGNED;
+	}
+
+	return STATUS_CANNOT_REMOVE;
+}
+
+static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
+{
+	uint8_t *label_uuid;
+	size_t clear_count;
+	int i;
+
+	/* Unref stored labels related to this model */
+	for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
+		if (!BT_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) {
+			if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+				mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
+				clear_count++;
+			}
+
+			continue;
+		}
+
+		label_uuid = bt_mesh_label_uuid_get(mod->groups[i]);
+
+		mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
+		clear_count++;
+
+		if (label_uuid) {
+			va_del(label_uuid, NULL);
+		} else {
+			BT_ERR("Label UUID not found");
+		}
+	}
+
+	return clear_count;
+}
+
+static void mod_pub_va_set(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+	uint16_t elem_addr, pub_addr, pub_app_idx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *label_uuid;
+	uint8_t *mod_id;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	label_uuid = net_buf_simple_pull_mem(buf, 16);
+	pub_app_idx = net_buf_simple_pull_le16(buf);
+	cred_flag = ((pub_app_idx >> 12) & BIT_MASK(1));
+	pub_app_idx &= BIT_MASK(12);
+	pub_ttl = net_buf_simple_pull_u8(buf);
+	if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) {
+		BT_ERR("Invalid TTL value 0x%02x", pub_ttl);
+		return;
+	}
+
+	pub_period = net_buf_simple_pull_u8(buf);
+	retransmit = net_buf_simple_pull_u8(buf);
+	mod_id = buf->data;
+
+	BT_DBG("elem_addr 0x%04x cred_flag %u", elem_addr, cred_flag);
+	BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x",
+	       pub_app_idx, pub_ttl, pub_period);
+	BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit,
+	       BT_MESH_PUB_TRANSMIT_COUNT(retransmit),
+	       BT_MESH_PUB_TRANSMIT_INT(retransmit));
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		pub_addr = 0U;
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		pub_addr = 0U;
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = va_add(label_uuid, &pub_addr);
+	if (status != STATUS_SUCCESS) {
+		goto send_status;
+	}
+
+	status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
+			      pub_period, retransmit, true);
+	if (status != STATUS_SUCCESS) {
+		va_del(label_uuid, NULL);
+	}
+
+send_status:
+	send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
+			    status, mod_id);
+}
+#else
+static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
+{
+	size_t clear_count;
+	int i;
+
+	/* Unref stored labels related to this model */
+	for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
+		if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+			if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+				bt_mesh_lpn_group_del(&mod->groups[i], 1);
+			}
+			mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
+			clear_count++;
+		}
+	}
+
+	return clear_count;
+}
+
+static void mod_pub_va_set(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint8_t *mod_id, status;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint16_t elem_addr, pub_addr = 0U;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	net_buf_simple_pull(buf, 16);
+	mod_id = net_buf_simple_pull(buf, 4);
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	if (!mod->pub) {
+		status = STATUS_NVAL_PUB_PARAM;
+		goto send_status;
+	}
+
+	pub_addr = mod->pub->addr;
+	status = STATUS_INSUFF_RESOURCES;
+
+send_status:
+	send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
+			    status, mod_id);
+}
+#endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */
+
+static void send_mod_sub_status(struct bt_mesh_model *model,
+				struct bt_mesh_msg_ctx *ctx, uint8_t status,
+				uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id,
+				bool vnd)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_STATUS, 9);
+
+	BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status,
+	       elem_addr, sub_addr);
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_SUB_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, elem_addr);
+	net_buf_simple_add_le16(&msg, sub_addr);
+
+	if (vnd) {
+		memcpy(net_buf_simple_add(&msg, 4), mod_id, 4);
+	} else {
+		memcpy(net_buf_simple_add(&msg, 2), mod_id, 2);
+	}
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model Subscription Status");
+	}
+}
+
+static void mod_sub_add(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id;
+	uint8_t status;
+	uint16_t *entry;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	sub_addr = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("elem_addr 0x%04x, sub_addr 0x%04x", elem_addr, sub_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) {
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	if (bt_mesh_model_find_group(&mod, sub_addr)) {
+		/* Tried to add existing subscription */
+		BT_DBG("found existing subscription");
+		status = STATUS_SUCCESS;
+		goto send_status;
+	}
+
+	entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
+	if (!entry) {
+		status = STATUS_INSUFF_RESOURCES;
+		goto send_status;
+	}
+
+	*entry = sub_addr;
+	status = STATUS_SUCCESS;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_mod_sub(mod);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_group_add(sub_addr);
+	}
+
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+
+static void mod_sub_del(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id;
+	uint16_t *match;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	sub_addr = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) {
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	/* An attempt to remove a non-existing address shall be treated
+	 * as a success.
+	 */
+	status = STATUS_SUCCESS;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_group_del(&sub_addr, 1);
+	}
+
+	match = bt_mesh_model_find_group(&mod, sub_addr);
+	if (match) {
+		*match = BT_MESH_ADDR_UNASSIGNED;
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_mod_sub(mod);
+		}
+	}
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+
+static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod,
+					       uint32_t depth, void *user_data)
+{
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
+	}
+
+	mod_sub_list_clear(mod);
+
+	return BT_MESH_WALK_CONTINUE;
+}
+
+static void mod_sub_overwrite(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	sub_addr = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) {
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+
+	if (ARRAY_SIZE(mod->groups) > 0) {
+		bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
+					mod_sub_clear_visitor, NULL);
+
+		mod->groups[0] = sub_addr;
+		status = STATUS_SUCCESS;
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_mod_sub(mod);
+		}
+
+		if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+			bt_mesh_lpn_group_add(sub_addr);
+		}
+	} else {
+		status = STATUS_INSUFF_RESOURCES;
+	}
+
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+
+static void mod_sub_del_all(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf)
+{
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint16_t elem_addr;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_clear_visitor,
+				NULL);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_mod_sub(mod);
+	}
+
+	status = STATUS_SUCCESS;
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr,
+			    BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
+}
+
+struct mod_sub_list_ctx {
+	uint16_t elem_idx;
+	struct net_buf_simple *msg;
+};
+
+static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod,
+					      uint32_t depth, void *ctx)
+{
+	struct mod_sub_list_ctx *visit = ctx;
+	int count = 0;
+	int i;
+
+	if (mod->elem_idx != visit->elem_idx) {
+		return BT_MESH_WALK_CONTINUE;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
+		if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		if (net_buf_simple_tailroom(visit->msg) <
+		    2 + BT_MESH_MIC_SHORT) {
+			BT_WARN("No room for all groups");
+			return BT_MESH_WALK_STOP;
+		}
+
+		net_buf_simple_add_le16(visit->msg, mod->groups[i]);
+		count++;
+	}
+
+	BT_DBG("sublist: model %u:%x: %u groups", mod->elem_idx, mod->id,
+	       count);
+
+	return BT_MESH_WALK_CONTINUE;
+}
+
+static void mod_sub_get(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(msg, BT_MESH_TX_SDU_MAX);
+	struct mod_sub_list_ctx visit_ctx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint16_t addr, id;
+
+	addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("addr 0x%04x id 0x%04x", addr, id);
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_SUB_LIST);
+
+	elem = bt_mesh_elem_find(addr);
+	if (!elem) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_ADDRESS);
+		net_buf_simple_add_le16(&msg, addr);
+		net_buf_simple_add_le16(&msg, id);
+		goto send_list;
+	}
+
+	mod = bt_mesh_model_find(elem, id);
+	if (!mod) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_MODEL);
+		net_buf_simple_add_le16(&msg, addr);
+		net_buf_simple_add_le16(&msg, id);
+		goto send_list;
+	}
+
+	net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
+
+	net_buf_simple_add_le16(&msg, addr);
+	net_buf_simple_add_le16(&msg, id);
+
+	visit_ctx.msg = &msg;
+	visit_ctx.elem_idx = mod->elem_idx;
+	bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
+				&visit_ctx);
+
+send_list:
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model Subscription List");
+	}
+}
+
+static void mod_sub_get_vnd(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(msg, BT_MESH_TX_SDU_MAX);
+	struct mod_sub_list_ctx visit_ctx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint16_t company, addr, id;
+
+	addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	company = net_buf_simple_pull_le16(buf);
+	id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("addr 0x%04x company 0x%04x id 0x%04x", addr, company, id);
+
+	bt_mesh_model_msg_init(&msg, OP_MOD_SUB_LIST_VND);
+
+	elem = bt_mesh_elem_find(addr);
+	if (!elem) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_ADDRESS);
+		net_buf_simple_add_le16(&msg, addr);
+		net_buf_simple_add_le16(&msg, company);
+		net_buf_simple_add_le16(&msg, id);
+		goto send_list;
+	}
+
+	mod = bt_mesh_model_find_vnd(elem, company, id);
+	if (!mod) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_MODEL);
+		net_buf_simple_add_le16(&msg, addr);
+		net_buf_simple_add_le16(&msg, company);
+		net_buf_simple_add_le16(&msg, id);
+		goto send_list;
+	}
+
+	net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
+
+	net_buf_simple_add_le16(&msg, addr);
+	net_buf_simple_add_le16(&msg, company);
+	net_buf_simple_add_le16(&msg, id);
+
+	visit_ctx.msg = &msg;
+	visit_ctx.elem_idx = mod->elem_idx;
+	bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
+				&visit_ctx);
+
+send_list:
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Vendor Model Subscription List");
+	}
+}
+
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+static void mod_sub_va_add(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *label_uuid;
+	uint8_t *mod_id;
+	uint16_t *entry;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	label_uuid = net_buf_simple_pull_mem(buf, 16);
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	mod_id = buf->data;
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		sub_addr = BT_MESH_ADDR_UNASSIGNED;
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		sub_addr = BT_MESH_ADDR_UNASSIGNED;
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = va_add(label_uuid, &sub_addr);
+	if (status != STATUS_SUCCESS) {
+		goto send_status;
+	}
+
+	if (bt_mesh_model_find_group(&mod, sub_addr)) {
+		/* Tried to add existing subscription */
+		status = STATUS_SUCCESS;
+		va_del(label_uuid, NULL);
+		goto send_status;
+	}
+
+
+	entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
+	if (!entry) {
+		status = STATUS_INSUFF_RESOURCES;
+		va_del(label_uuid, NULL);
+		goto send_status;
+	}
+
+	*entry = sub_addr;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_group_add(sub_addr);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_mod_sub(mod);
+	}
+
+	status = STATUS_SUCCESS;
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+
+static void mod_sub_va_del(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *label_uuid;
+	uint8_t *mod_id;
+	uint16_t *match;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	label_uuid = net_buf_simple_pull_mem(buf, 16);
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		sub_addr = BT_MESH_ADDR_UNASSIGNED;
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		sub_addr = BT_MESH_ADDR_UNASSIGNED;
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = va_del(label_uuid, &sub_addr);
+	if (sub_addr == BT_MESH_ADDR_UNASSIGNED) {
+		goto send_status;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_group_del(&sub_addr, 1);
+	}
+
+	match = bt_mesh_model_find_group(&mod, sub_addr);
+	if (match) {
+		*match = BT_MESH_ADDR_UNASSIGNED;
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_mod_sub(mod);
+		}
+
+		status = STATUS_SUCCESS;
+	} else {
+		status = STATUS_CANNOT_REMOVE;
+	}
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+
+static void mod_sub_va_overwrite(struct bt_mesh_model *model,
+				 struct bt_mesh_msg_ctx *ctx,
+				 struct net_buf_simple *buf)
+{
+	uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *label_uuid;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	label_uuid = net_buf_simple_pull_mem(buf, 16);
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+
+	if (ARRAY_SIZE(mod->groups) > 0) {
+
+		status = va_add(label_uuid, &sub_addr);
+		if (status == STATUS_SUCCESS) {
+			bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
+						mod_sub_clear_visitor, NULL);
+			mod->groups[0] = sub_addr;
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_mod_sub(mod);
+			}
+
+			if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+				bt_mesh_lpn_group_add(sub_addr);
+			}
+		}
+	} else {
+		status = STATUS_INSUFF_RESOURCES;
+	}
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
+			    mod_id, vnd);
+}
+#else
+static void mod_sub_va_add(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint16_t elem_addr;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	net_buf_simple_pull(buf, 16);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = STATUS_INSUFF_RESOURCES;
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr,
+			    BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
+}
+
+static void mod_sub_va_del(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_elem *elem;
+	uint16_t elem_addr;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	net_buf_simple_pull(buf, 16);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	if (!get_model(elem, buf, &vnd)) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = STATUS_INSUFF_RESOURCES;
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr,
+			    BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
+}
+
+static void mod_sub_va_overwrite(struct bt_mesh_model *model,
+				 struct bt_mesh_msg_ctx *ctx,
+				 struct net_buf_simple *buf)
+{
+	struct bt_mesh_elem *elem;
+	uint16_t elem_addr;
+	uint8_t *mod_id;
+	uint8_t status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	net_buf_simple_pull(buf, 18);
+
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	if (!get_model(elem, buf, &vnd)) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = STATUS_INSUFF_RESOURCES;
+
+send_status:
+	send_mod_sub_status(model, ctx, status, elem_addr,
+			    BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
+}
+#endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */
+
+static void send_net_key_status(struct bt_mesh_model *model,
+				struct bt_mesh_msg_ctx *ctx,
+				uint16_t idx, uint8_t status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_STATUS, 3);
+
+	bt_mesh_model_msg_init(&msg, OP_NET_KEY_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, idx);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send NetKey Status");
+	}
+}
+
+static void net_key_add(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	uint16_t idx;
+	int err;
+
+	idx = net_buf_simple_pull_le16(buf);
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x", idx);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+			if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
+				sub = &bt_mesh.sub[i];
+				break;
+			}
+		}
+
+		if (!sub) {
+			send_net_key_status(model, ctx, idx,
+					    STATUS_INSUFF_RESOURCES);
+			return;
+		}
+	}
+
+	/* Check for already existing subnet */
+	if (sub->net_idx == idx) {
+		uint8_t status;
+
+		if (memcmp(buf->data, sub->keys[0].net, 16)) {
+			status = STATUS_IDX_ALREADY_STORED;
+		} else {
+			status = STATUS_SUCCESS;
+		}
+
+		send_net_key_status(model, ctx, idx, status);
+		return;
+	}
+
+	err = bt_mesh_net_keys_create(&sub->keys[0], buf->data);
+	if (err) {
+		send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
+		return;
+	}
+
+	sub->net_idx = idx;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing NetKey persistently");
+		bt_mesh_store_subnet(sub);
+	}
+
+	/* Make sure we have valid beacon data to be sent */
+	bt_mesh_net_beacon_update(sub);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+		bt_mesh_proxy_beacon_send(sub);
+		bt_mesh_adv_update();
+	} else {
+		sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+	}
+
+	send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+}
+
+static void net_key_update(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	uint16_t idx;
+	int err;
+
+	idx = net_buf_simple_pull_le16(buf);
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x", idx);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY);
+		return;
+	}
+
+	/* The node shall successfully process a NetKey Update message on a
+	 * valid NetKeyIndex when the NetKey value is different and the Key
+	 * Refresh procedure has not been started, or when the NetKey value is
+	 * the same in Phase 1. The NetKey Update message shall generate an
+	 * error when the node is in Phase 2, or Phase 3.
+	 */
+	switch (sub->kr_phase) {
+	case BT_MESH_KR_NORMAL:
+		if (!memcmp(buf->data, sub->keys[0].net, 16)) {
+			return;
+		}
+		break;
+	case BT_MESH_KR_PHASE_1:
+		if (!memcmp(buf->data, sub->keys[1].net, 16)) {
+			send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+			return;
+		}
+		__fallthrough;
+	case BT_MESH_KR_PHASE_2:
+	case BT_MESH_KR_PHASE_3:
+		send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE);
+		return;
+	}
+
+	err = bt_mesh_net_keys_create(&sub->keys[1], buf->data);
+	if (!err && (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
+		     IS_ENABLED(CONFIG_BT_MESH_FRIEND))) {
+		err = friend_cred_update(sub);
+	}
+
+	if (err) {
+		send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
+		return;
+	}
+
+	sub->kr_phase = BT_MESH_KR_PHASE_1;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing NetKey persistently");
+		bt_mesh_store_subnet(sub);
+	}
+
+	bt_mesh_net_beacon_update(sub);
+
+	send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+}
+
+static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg)
+{
+	BT_DBG("");
+
+	cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
+	cfg->hb_pub.count = 0U;
+	cfg->hb_pub.ttl = 0U;
+	cfg->hb_pub.period = 0U;
+
+	k_delayed_work_cancel(&cfg->hb_pub.timer);
+}
+
+static void net_key_del(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	uint16_t del_idx;
+	uint8_t status;
+
+	del_idx = net_buf_simple_pull_le16(buf);
+	if (del_idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", del_idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x", del_idx);
+
+	sub = bt_mesh_subnet_get(del_idx);
+	if (!sub) {
+		/* This could be a retry of a previous attempt that had its
+		 * response lost, so pretend that it was a success.
+		 */
+		status = STATUS_SUCCESS;
+		goto send_status;
+	}
+
+	/* The key that the message was encrypted with cannot be removed.
+	 * The NetKey List must contain a minimum of one NetKey.
+	 */
+	if (ctx->net_idx == del_idx) {
+		status = STATUS_CANNOT_REMOVE;
+		goto send_status;
+	}
+
+	bt_mesh_subnet_del(sub, true);
+	status = STATUS_SUCCESS;
+
+send_status:
+	send_net_key_status(model, ctx, del_idx, status);
+}
+
+static void net_key_get(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_LIST,
+				 IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
+	uint16_t prev, i;
+
+	bt_mesh_model_msg_init(&msg, OP_NET_KEY_LIST);
+
+	prev = BT_MESH_KEY_UNUSED;
+	for (i = 0U; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (prev == BT_MESH_KEY_UNUSED) {
+			prev = sub->net_idx;
+			continue;
+		}
+
+		key_idx_pack(&msg, prev, sub->net_idx);
+		prev = BT_MESH_KEY_UNUSED;
+	}
+
+	if (prev != BT_MESH_KEY_UNUSED) {
+		net_buf_simple_add_le16(&msg, prev);
+	}
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send NetKey List");
+	}
+}
+
+static void node_identity_get(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
+	struct bt_mesh_subnet *sub;
+	uint8_t node_id;
+	uint16_t idx;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	idx = net_buf_simple_pull_le16(buf);
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NODE_IDENTITY_STATUS);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY);
+		node_id = 0x00;
+	} else {
+		net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
+		node_id = sub->node_id;
+	}
+
+	net_buf_simple_add_le16(&msg, idx);
+	net_buf_simple_add_u8(&msg, node_id);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Node Identity Status");
+	}
+}
+
+static void node_identity_set(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
+	struct bt_mesh_subnet *sub;
+	uint8_t node_id;
+	uint16_t idx;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	idx = net_buf_simple_pull_le16(buf);
+	if (idx > 0xfff) {
+		BT_WARN("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	node_id = net_buf_simple_pull_u8(buf);
+	if (node_id != 0x00 && node_id != 0x01) {
+		BT_WARN("Invalid Node ID value 0x%02x", node_id);
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_NODE_IDENTITY_STATUS);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		net_buf_simple_add_u8(&msg, STATUS_INVALID_NETKEY);
+		net_buf_simple_add_le16(&msg, idx);
+		net_buf_simple_add_u8(&msg, node_id);
+	} else  {
+		net_buf_simple_add_u8(&msg, STATUS_SUCCESS);
+		net_buf_simple_add_le16(&msg, idx);
+
+		if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+			if (node_id) {
+				bt_mesh_proxy_identity_start(sub);
+			} else {
+				bt_mesh_proxy_identity_stop(sub);
+			}
+			bt_mesh_adv_update();
+		}
+
+		net_buf_simple_add_u8(&msg, sub->node_id);
+	}
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Node Identity Status");
+	}
+}
+
+static void create_mod_app_status(struct net_buf_simple *msg,
+				  struct bt_mesh_model *mod, bool vnd,
+				  uint16_t elem_addr, uint16_t app_idx,
+				  uint8_t status, uint8_t *mod_id)
+{
+	bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS);
+
+	net_buf_simple_add_u8(msg, status);
+	net_buf_simple_add_le16(msg, elem_addr);
+	net_buf_simple_add_le16(msg, app_idx);
+
+	if (vnd) {
+		memcpy(net_buf_simple_add(msg, 4), mod_id, 4);
+	} else {
+		memcpy(net_buf_simple_add(msg, 2), mod_id, 2);
+	}
+}
+
+static void mod_app_bind(struct bt_mesh_model *model,
+			 struct bt_mesh_msg_ctx *ctx,
+			 struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9);
+	uint16_t elem_addr, key_app_idx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id, status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	key_app_idx = net_buf_simple_pull_le16(buf);
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	/* Configuration Server only allows device key based access */
+	if (model == mod) {
+		BT_ERR("Client tried to bind AppKey to Configuration Model");
+		status = STATUS_CANNOT_BIND;
+		goto send_status;
+	}
+
+	status = mod_bind(mod, key_app_idx);
+
+	if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
+		bt_test_mesh_model_bound(ctx->addr, mod, key_app_idx);
+	}
+
+send_status:
+	BT_DBG("status 0x%02x", status);
+	create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status,
+			      mod_id);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model App Bind Status response");
+	}
+}
+
+static void mod_app_unbind(struct bt_mesh_model *model,
+			   struct bt_mesh_msg_ctx *ctx,
+			   struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9);
+	uint16_t elem_addr, key_app_idx;
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id, status;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	key_app_idx = net_buf_simple_pull_le16(buf);
+	mod_id = buf->data;
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_status;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_status;
+	}
+
+	status = mod_unbind(mod, key_app_idx, true);
+
+	if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) {
+		bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx);
+	}
+
+send_status:
+	BT_DBG("status 0x%02x", status);
+	create_mod_app_status(&msg, mod, vnd, elem_addr, key_app_idx, status,
+			      mod_id);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model App Unbind Status response");
+	}
+}
+
+#define KEY_LIST_LEN (CONFIG_BT_MESH_MODEL_KEY_COUNT * 2)
+
+static void mod_app_get(struct bt_mesh_model *model,
+			struct bt_mesh_msg_ctx *ctx,
+			struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(msg,
+			      MAX(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST,
+							9 + KEY_LIST_LEN),
+				  BT_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST,
+							9 + KEY_LIST_LEN)));
+	struct bt_mesh_model *mod;
+	struct bt_mesh_elem *elem;
+	uint8_t *mod_id, status;
+	uint16_t elem_addr;
+	bool vnd;
+
+	elem_addr = net_buf_simple_pull_le16(buf);
+	if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
+		BT_WARN("Prohibited element address");
+		return;
+	}
+
+	mod_id = buf->data;
+
+	BT_DBG("elem_addr 0x%04x", elem_addr);
+
+	elem = bt_mesh_elem_find(elem_addr);
+	if (!elem) {
+		mod = NULL;
+		vnd = (buf->len == 4U);
+		status = STATUS_INVALID_ADDRESS;
+		goto send_list;
+	}
+
+	mod = get_model(elem, buf, &vnd);
+	if (!mod) {
+		status = STATUS_INVALID_MODEL;
+		goto send_list;
+	}
+
+	status = STATUS_SUCCESS;
+
+send_list:
+	if (vnd) {
+		bt_mesh_model_msg_init(&msg, OP_VND_MOD_APP_LIST);
+	} else {
+		bt_mesh_model_msg_init(&msg, OP_SIG_MOD_APP_LIST);
+	}
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, elem_addr);
+
+	if (vnd) {
+		net_buf_simple_add_mem(&msg, mod_id, 4);
+	} else {
+		net_buf_simple_add_mem(&msg, mod_id, 2);
+	}
+
+	if (mod) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
+			if (mod->keys[i] != BT_MESH_KEY_UNUSED) {
+				net_buf_simple_add_le16(&msg, mod->keys[i]);
+			}
+		}
+	}
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Model Application List message");
+	}
+}
+
+static void node_reset(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *buf)
+{
+	static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset};
+
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+
+	bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS);
+
+	/* Send the response first since we wont have any keys left to
+	 * send it later.
+	 */
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Node Reset Status");
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		bt_mesh_reset();
+		return;
+	}
+
+	/* If the response goes to a proxy node, we'll wait for the sending to
+	 * complete before moving on.
+	 */
+	bt_mesh_proxy_on_idle(&proxy_idle);
+}
+
+static void send_friend_status(struct bt_mesh_model *model,
+			       struct bt_mesh_msg_ctx *ctx)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_FRIEND_STATUS, 1);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	bt_mesh_model_msg_init(&msg, OP_FRIEND_STATUS);
+	net_buf_simple_add_u8(&msg, cfg->frnd);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Friend Status");
+	}
+}
+
+static void friend_get(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *buf)
+{
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	send_friend_status(model, ctx);
+}
+
+static void friend_set(struct bt_mesh_model *model,
+		       struct bt_mesh_msg_ctx *ctx,
+		       struct net_buf_simple *buf)
+{
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (buf->data[0] != 0x00 && buf->data[0] != 0x01) {
+		BT_WARN("Invalid Friend value 0x%02x", buf->data[0]);
+		return;
+	}
+
+	BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->data[0]);
+
+	if (cfg->frnd == buf->data[0]) {
+		goto send_status;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		cfg->frnd = buf->data[0];
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_cfg();
+		}
+
+		if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
+			bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
+		}
+	}
+
+	if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) {
+		(void)bt_mesh_heartbeat_send(NULL, NULL);
+	}
+
+send_status:
+	send_friend_status(model, ctx);
+}
+
+static void lpn_timeout_get(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    struct net_buf_simple *buf)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_LPN_TIMEOUT_STATUS, 5);
+	struct bt_mesh_friend *frnd;
+	uint16_t lpn_addr;
+	int32_t timeout_ms;
+
+	lpn_addr = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x lpn_addr 0x%02x",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, lpn_addr);
+
+	if (!BT_MESH_ADDR_IS_UNICAST(lpn_addr)) {
+		BT_WARN("Invalid LPNAddress; ignoring msg");
+		return;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_LPN_TIMEOUT_STATUS);
+	net_buf_simple_add_le16(&msg, lpn_addr);
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		timeout_ms = 0;
+		goto send_rsp;
+	}
+
+	frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, true, true);
+	if (!frnd) {
+		timeout_ms = 0;
+		goto send_rsp;
+	}
+
+	timeout_ms = k_delayed_work_remaining_get(&frnd->timer) / 100;
+
+send_rsp:
+	net_buf_simple_add_le24(&msg, timeout_ms);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send LPN PollTimeout Status");
+	}
+}
+
+static void send_krp_status(struct bt_mesh_model *model,
+			    struct bt_mesh_msg_ctx *ctx,
+			    uint16_t idx, uint8_t phase, uint8_t status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_KRP_STATUS, 4);
+
+	bt_mesh_model_msg_init(&msg, OP_KRP_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, idx);
+	net_buf_simple_add_u8(&msg, phase);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Key Refresh State Status");
+	}
+}
+
+static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
+		    struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	uint16_t idx;
+
+	idx = net_buf_simple_pull_le16(buf);
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x", idx);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
+	} else {
+		send_krp_status(model, ctx, idx, sub->kr_phase,
+				STATUS_SUCCESS);
+	}
+}
+
+static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
+		    struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	uint8_t phase;
+	uint16_t idx;
+
+	idx = net_buf_simple_pull_le16(buf);
+	phase = net_buf_simple_pull_u8(buf);
+
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	BT_DBG("idx 0x%04x transition 0x%02x", idx, phase);
+
+	sub = bt_mesh_subnet_get(idx);
+	if (!sub) {
+		send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
+		return;
+	}
+
+	BT_DBG("%u -> %u", sub->kr_phase, phase);
+
+	if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 ||
+	    (sub->kr_phase == BT_MESH_KR_NORMAL &&
+	     phase == BT_MESH_KR_PHASE_2)) {
+		BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase);
+		return;
+	}
+
+	if (sub->kr_phase == BT_MESH_KR_PHASE_1 &&
+	    phase == BT_MESH_KR_PHASE_2) {
+		sub->kr_phase = BT_MESH_KR_PHASE_2;
+		sub->kr_flag = 1;
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		    BT_DBG("Storing krp phase persistently");
+		    bt_mesh_store_subnet(sub);
+		}
+
+		bt_mesh_net_beacon_update(sub);
+	} else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 ||
+		    sub->kr_phase == BT_MESH_KR_PHASE_2) &&
+		   phase == BT_MESH_KR_PHASE_3) {
+		bt_mesh_net_revoke_keys(sub);
+		if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
+		    IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+			friend_cred_refresh(ctx->net_idx);
+		}
+
+		sub->kr_phase = BT_MESH_KR_NORMAL;
+		sub->kr_flag = 0;
+		bt_mesh_net_beacon_update(sub);
+	}
+
+	send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS);
+}
+
+static uint8_t hb_log(uint16_t val)
+{
+	if (!val) {
+		return 0x00;
+	} else if (val == 0xffff) {
+		return 0xff;
+	} else {
+		return 32 - __builtin_clz(val);
+	}
+}
+
+static uint8_t hb_pub_count_log(uint16_t val)
+{
+	if (!val) {
+		return 0x00;
+	} else if (val == 0x01) {
+		return 0x01;
+	} else if (val == 0xffff) {
+		return 0xff;
+	} else {
+		return 32 - __builtin_clz(val - 1) + 1;
+	}
+}
+
+static uint16_t hb_pwr2(uint8_t val, uint8_t sub)
+{
+	if (!val) {
+		return 0x0000;
+	} else if (val == 0xff || val == 0x11) {
+		return 0xffff;
+	} else {
+		return (1 << (val - sub));
+	}
+}
+
+struct hb_pub_param {
+	uint16_t dst;
+	uint8_t  count_log;
+	uint8_t  period_log;
+	uint8_t  ttl;
+	uint16_t feat;
+	uint16_t net_idx;
+} __packed;
+
+static void hb_pub_send_status(struct bt_mesh_model *model,
+			       struct bt_mesh_msg_ctx *ctx, uint8_t status,
+			       struct hb_pub_param *orig_msg)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_STATUS, 10);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_PUB_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+
+	if (orig_msg) {
+		memcpy(net_buf_simple_add(&msg, sizeof(*orig_msg)), orig_msg,
+		       sizeof(*orig_msg));
+		goto send;
+	}
+
+	net_buf_simple_add_le16(&msg, cfg->hb_pub.dst);
+	net_buf_simple_add_u8(&msg, hb_pub_count_log(cfg->hb_pub.count));
+	net_buf_simple_add_u8(&msg, cfg->hb_pub.period);
+	net_buf_simple_add_u8(&msg, cfg->hb_pub.ttl);
+	net_buf_simple_add_le16(&msg, cfg->hb_pub.feat);
+	net_buf_simple_add_le16(&msg, cfg->hb_pub.net_idx);
+
+send:
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Heartbeat Publication Status");
+	}
+}
+
+static void heartbeat_pub_get(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_DBG("src 0x%04x", ctx->addr);
+
+	hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
+}
+
+static void heartbeat_pub_set(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	struct hb_pub_param *param = (void *)buf->data;
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+	uint16_t dst, feat, idx;
+	uint8_t status;
+
+	BT_DBG("src 0x%04x", ctx->addr);
+
+	dst = sys_le16_to_cpu(param->dst);
+	/* All other address types but virtual are valid */
+	if (BT_MESH_ADDR_IS_VIRTUAL(dst)) {
+		status = STATUS_INVALID_ADDRESS;
+		goto failed;
+	}
+
+	if (param->count_log > 0x11 && param->count_log != 0xff) {
+		status = STATUS_CANNOT_SET;
+		goto failed;
+	}
+
+	if (param->period_log > 0x10) {
+		status = STATUS_CANNOT_SET;
+		goto failed;
+	}
+
+	if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) {
+		BT_ERR("Invalid TTL value 0x%02x", param->ttl);
+		return;
+	}
+
+	feat = sys_le16_to_cpu(param->feat);
+
+	idx = sys_le16_to_cpu(param->net_idx);
+	if (idx > 0xfff) {
+		BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+		return;
+	}
+
+	if (!bt_mesh_subnet_get(idx)) {
+		status = STATUS_INVALID_NETKEY;
+		goto failed;
+	}
+
+	cfg->hb_pub.dst = dst;
+	cfg->hb_pub.period = param->period_log;
+	cfg->hb_pub.feat = feat & BT_MESH_FEAT_SUPPORTED;
+	cfg->hb_pub.net_idx = idx;
+
+	if (dst == BT_MESH_ADDR_UNASSIGNED) {
+		hb_pub_disable(cfg);
+	} else {
+		/* 2^(n-1) */
+		cfg->hb_pub.count = hb_pwr2(param->count_log, 1);
+		cfg->hb_pub.ttl = param->ttl;
+
+		BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000U);
+
+		/* The first Heartbeat message shall be published as soon
+		 * as possible after the Heartbeat Publication Period state
+		 * has been configured for periodic publishing.
+		 */
+		if (param->period_log && param->count_log) {
+			k_work_submit(&cfg->hb_pub.timer.work);
+		} else {
+			k_delayed_work_cancel(&cfg->hb_pub.timer);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_hb_pub();
+	}
+
+	hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
+
+	return;
+
+failed:
+	hb_pub_send_status(model, ctx, status, param);
+}
+
+static void hb_sub_send_status(struct bt_mesh_model *model,
+			       struct bt_mesh_msg_ctx *ctx, uint8_t status)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_STATUS, 9);
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+	uint16_t period;
+	int64_t uptime;
+
+	BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
+
+	uptime = k_uptime_get();
+	if (uptime > cfg->hb_sub.expiry) {
+		period = 0U;
+	} else {
+		period = (cfg->hb_sub.expiry - uptime) / 1000;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEARTBEAT_SUB_STATUS);
+
+	net_buf_simple_add_u8(&msg, status);
+	net_buf_simple_add_le16(&msg, cfg->hb_sub.src);
+	net_buf_simple_add_le16(&msg, cfg->hb_sub.dst);
+	net_buf_simple_add_u8(&msg, hb_log(period));
+	net_buf_simple_add_u8(&msg, hb_log(cfg->hb_sub.count));
+	net_buf_simple_add_u8(&msg, cfg->hb_sub.min_hops);
+	net_buf_simple_add_u8(&msg, cfg->hb_sub.max_hops);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Heartbeat Subscription Status");
+	}
+}
+
+static void heartbeat_sub_get(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_DBG("src 0x%04x", ctx->addr);
+
+	hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+}
+
+static void heartbeat_sub_set(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+	uint16_t sub_src, sub_dst;
+	uint8_t sub_period;
+	int32_t period_ms;
+
+	BT_DBG("src 0x%04x", ctx->addr);
+
+	sub_src = net_buf_simple_pull_le16(buf);
+	sub_dst = net_buf_simple_pull_le16(buf);
+	sub_period = net_buf_simple_pull_u8(buf);
+
+	BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x",
+	       sub_src, sub_dst, sub_period);
+
+	if (sub_src != BT_MESH_ADDR_UNASSIGNED &&
+	    !BT_MESH_ADDR_IS_UNICAST(sub_src)) {
+		BT_WARN("Prohibited source address");
+		return;
+	}
+
+	if (BT_MESH_ADDR_IS_VIRTUAL(sub_dst) || BT_MESH_ADDR_IS_RFU(sub_dst) ||
+	    (BT_MESH_ADDR_IS_UNICAST(sub_dst) &&
+	     sub_dst != bt_mesh_primary_addr())) {
+		BT_WARN("Prohibited destination address");
+		return;
+	}
+
+	if (sub_period > 0x11) {
+		BT_WARN("Prohibited subscription period 0x%02x", sub_period);
+		return;
+	}
+
+	if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
+	    sub_dst == BT_MESH_ADDR_UNASSIGNED ||
+	    sub_period == 0x00) {
+		/* Only an explicit address change to unassigned should
+		 * trigger clearing of the values according to
+		 * MESH/NODE/CFG/HBS/BV-02-C.
+		 */
+		if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
+		    sub_dst == BT_MESH_ADDR_UNASSIGNED) {
+			cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
+			cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
+			cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
+			cfg->hb_sub.max_hops = 0U;
+			cfg->hb_sub.count = 0U;
+		}
+
+		period_ms = 0;
+	} else {
+		cfg->hb_sub.src = sub_src;
+		cfg->hb_sub.dst = sub_dst;
+		cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
+		cfg->hb_sub.max_hops = 0U;
+		cfg->hb_sub.count = 0U;
+		period_ms = hb_pwr2(sub_period, 1) * 1000U;
+	}
+
+	/* Let the transport layer know it needs to handle this address */
+	bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst);
+
+	BT_DBG("period_ms %u", period_ms);
+
+	if (period_ms) {
+		cfg->hb_sub.expiry = k_uptime_get() + period_ms;
+	} else {
+		cfg->hb_sub.expiry = 0;
+	}
+
+	hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+
+	/* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after
+	 * disabling subscription, but 0x00 for subsequent Get requests.
+	 */
+	if (!period_ms) {
+		cfg->hb_sub.min_hops = 0U;
+	}
+}
+
+const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
+	{ OP_DEV_COMP_DATA_GET,        1,   dev_comp_data_get },
+	{ OP_APP_KEY_ADD,              19,  app_key_add },
+	{ OP_APP_KEY_UPDATE,           19,  app_key_update },
+	{ OP_APP_KEY_DEL,              3,   app_key_del },
+	{ OP_APP_KEY_GET,              2,   app_key_get },
+	{ OP_BEACON_GET,               0,   beacon_get },
+	{ OP_BEACON_SET,               1,   beacon_set },
+	{ OP_DEFAULT_TTL_GET,          0,   default_ttl_get },
+	{ OP_DEFAULT_TTL_SET,          1,   default_ttl_set },
+	{ OP_GATT_PROXY_GET,           0,   gatt_proxy_get },
+	{ OP_GATT_PROXY_SET,           1,   gatt_proxy_set },
+	{ OP_NET_TRANSMIT_GET,         0,   net_transmit_get },
+	{ OP_NET_TRANSMIT_SET,         1,   net_transmit_set },
+	{ OP_RELAY_GET,                0,   relay_get },
+	{ OP_RELAY_SET,                2,   relay_set },
+	{ OP_MOD_PUB_GET,              4,   mod_pub_get },
+	{ OP_MOD_PUB_SET,              11,  mod_pub_set },
+	{ OP_MOD_PUB_VA_SET,           24,  mod_pub_va_set },
+	{ OP_MOD_SUB_ADD,              6,   mod_sub_add },
+	{ OP_MOD_SUB_VA_ADD,           20,  mod_sub_va_add },
+	{ OP_MOD_SUB_DEL,              6,   mod_sub_del },
+	{ OP_MOD_SUB_VA_DEL,           20,  mod_sub_va_del },
+	{ OP_MOD_SUB_OVERWRITE,        6,   mod_sub_overwrite },
+	{ OP_MOD_SUB_VA_OVERWRITE,     20,  mod_sub_va_overwrite },
+	{ OP_MOD_SUB_DEL_ALL,          4,   mod_sub_del_all },
+	{ OP_MOD_SUB_GET,              4,   mod_sub_get },
+	{ OP_MOD_SUB_GET_VND,          6,   mod_sub_get_vnd },
+	{ OP_NET_KEY_ADD,              18,  net_key_add },
+	{ OP_NET_KEY_UPDATE,           18,  net_key_update },
+	{ OP_NET_KEY_DEL,              2,   net_key_del },
+	{ OP_NET_KEY_GET,              0,   net_key_get },
+	{ OP_NODE_IDENTITY_GET,        2,   node_identity_get },
+	{ OP_NODE_IDENTITY_SET,        3,   node_identity_set },
+	{ OP_MOD_APP_BIND,             6,   mod_app_bind },
+	{ OP_MOD_APP_UNBIND,           6,   mod_app_unbind },
+	{ OP_SIG_MOD_APP_GET,          4,   mod_app_get },
+	{ OP_VND_MOD_APP_GET,          6,   mod_app_get },
+	{ OP_NODE_RESET,               0,   node_reset },
+	{ OP_FRIEND_GET,               0,   friend_get },
+	{ OP_FRIEND_SET,               1,   friend_set },
+	{ OP_LPN_TIMEOUT_GET,          2,   lpn_timeout_get },
+	{ OP_KRP_GET,                  2,   krp_get },
+	{ OP_KRP_SET,                  3,   krp_set },
+	{ OP_HEARTBEAT_PUB_GET,        0,   heartbeat_pub_get },
+	{ OP_HEARTBEAT_PUB_SET,        9,   heartbeat_pub_set },
+	{ OP_HEARTBEAT_SUB_GET,        0,   heartbeat_sub_get },
+	{ OP_HEARTBEAT_SUB_SET,        5,   heartbeat_sub_set },
+	BT_MESH_MODEL_OP_END,
+};
+
+static void hb_publish_end_cb(int err, void *cb_data)
+{
+	struct bt_mesh_cfg_srv *cfg = cb_data;
+	uint16_t period_ms;
+
+	period_ms = hb_pwr2(cfg->hb_pub.period, 1) * 1000U;
+	if (period_ms && cfg->hb_pub.count > 1) {
+		k_delayed_work_submit(&cfg->hb_pub.timer, K_MSEC(period_ms));
+	}
+
+	if (cfg->hb_pub.count != 0xffff) {
+		cfg->hb_pub.count--;
+	}
+}
+
+static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data)
+{
+	if (err) {
+		hb_publish_end_cb(err, cb_data);
+	}
+}
+
+static void hb_publish(struct k_work *work)
+{
+	static const struct bt_mesh_send_cb publish_cb = {
+		.start = hb_publish_start_cb,
+		.end = hb_publish_end_cb,
+	};
+	struct bt_mesh_cfg_srv *cfg = CONTAINER_OF(work,
+						   struct bt_mesh_cfg_srv,
+						   hb_pub.timer.work);
+	struct bt_mesh_subnet *sub;
+	int err;
+
+	BT_DBG("hb_pub.count: %u", cfg->hb_pub.count);
+
+	sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
+	if (!sub) {
+		BT_ERR("No matching subnet for idx 0x%02x",
+		       cfg->hb_pub.net_idx);
+		cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
+		return;
+	}
+
+	if (cfg->hb_pub.count == 0U) {
+		return;
+	}
+
+	err = bt_mesh_heartbeat_send(&publish_cb, cfg);
+	if (err) {
+		hb_publish_end_cb(err, cfg);
+	}
+}
+
+static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
+{
+	if (cfg->relay > 0x02) {
+		return false;
+	}
+
+	if (cfg->frnd > 0x02) {
+		return false;
+	}
+
+	if (cfg->gatt_proxy > 0x02) {
+		return false;
+	}
+
+	if (cfg->beacon > 0x01) {
+		return false;
+	}
+
+	if (cfg->default_ttl > BT_MESH_TTL_MAX) {
+		return false;
+	}
+
+	return true;
+}
+
+static int cfg_srv_init(struct bt_mesh_model *model)
+{
+	struct bt_mesh_cfg_srv *cfg = model->user_data;
+
+	if (!bt_mesh_model_in_primary(model)) {
+		BT_ERR("Configuration Server only allowed in primary element");
+		return -EINVAL;
+	}
+
+	if (!cfg) {
+		BT_ERR("No Configuration Server context provided");
+		return -EINVAL;
+	}
+
+	if (!conf_is_valid(cfg)) {
+		BT_ERR("Invalid values in configuration");
+		return -EINVAL;
+	}
+
+	/*
+	 * Configuration Model security is device-key based and only the local
+	 * device-key is allowed to access this model.
+	 */
+	model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
+		cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED;
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED;
+	}
+
+	k_delayed_work_init(&cfg->hb_pub.timer, hb_publish);
+	cfg->hb_pub.net_idx = BT_MESH_KEY_UNUSED;
+	cfg->hb_sub.expiry = 0;
+
+	cfg->model = model;
+
+	conf = cfg;
+
+	return 0;
+}
+
+const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb = {
+	.init = cfg_srv_init,
+};
+
+static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+		      bool vnd, bool primary, void *user_data)
+{
+	size_t clear_count;
+
+	/* Clear model state that isn't otherwise cleared. E.g. AppKey
+	 * binding and model publication is cleared as a consequence
+	 * of removing all app keys, however model subscription and user data
+	 * clearing must be taken care of here.
+	 */
+
+	clear_count = mod_sub_list_clear(mod);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		if (clear_count) {
+			bt_mesh_store_mod_sub(mod);
+		}
+	}
+
+	if (mod->cb && mod->cb->reset) {
+		mod->cb->reset(mod);
+	}
+}
+
+void bt_mesh_cfg_reset(void)
+{
+	struct bt_mesh_cfg_srv *cfg = conf;
+	int i;
+
+	BT_DBG("");
+
+	bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED);
+
+	cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
+	cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
+	cfg->hb_sub.expiry = 0;
+
+	/* Delete all net keys, which also takes care of all app keys which
+	 * are associated with each net key.
+	 */
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+			bt_mesh_subnet_del(sub, true);
+		}
+	}
+
+	bt_mesh_model_foreach(mod_reset, NULL);
+
+	(void)memset(labels, 0, sizeof(labels));
+}
+
+void bt_mesh_heartbeat(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat)
+{
+	struct bt_mesh_cfg_srv *cfg = conf;
+
+	if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
+		BT_WARN("No subscription for received heartbeat");
+		return;
+	}
+
+	if (k_uptime_get() > cfg->hb_sub.expiry) {
+		BT_WARN("Heartbeat subscription period expired");
+		return;
+	}
+
+	cfg->hb_sub.min_hops = MIN(cfg->hb_sub.min_hops, hops);
+	cfg->hb_sub.max_hops = MAX(cfg->hb_sub.max_hops, hops);
+
+	if (cfg->hb_sub.count < 0xffff) {
+		cfg->hb_sub.count++;
+	}
+
+	BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
+	       dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
+	       cfg->hb_sub.count);
+
+	if (cfg->hb_sub.func) {
+		cfg->hb_sub.func(hops, feat);
+	}
+}
+
+uint8_t bt_mesh_net_transmit_get(void)
+{
+	if (conf) {
+		return conf->net_transmit;
+	}
+
+	return 0;
+}
+
+uint8_t bt_mesh_relay_get(void)
+{
+	if (conf) {
+		return conf->relay;
+	}
+
+	return BT_MESH_RELAY_NOT_SUPPORTED;
+}
+
+uint8_t bt_mesh_friend_get(void)
+{
+	if (conf) {
+		BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd);
+		return conf->frnd;
+	}
+
+	return BT_MESH_FRIEND_NOT_SUPPORTED;
+}
+
+uint8_t bt_mesh_relay_retransmit_get(void)
+{
+	if (conf) {
+		return conf->relay_retransmit;
+	}
+
+	return 0;
+}
+
+uint8_t bt_mesh_beacon_get(void)
+{
+	if (conf) {
+		return conf->beacon;
+	}
+
+	return BT_MESH_BEACON_DISABLED;
+}
+
+uint8_t bt_mesh_gatt_proxy_get(void)
+{
+	if (conf) {
+		return conf->gatt_proxy;
+	}
+
+	return BT_MESH_GATT_PROXY_NOT_SUPPORTED;
+}
+
+uint8_t bt_mesh_default_ttl_get(void)
+{
+	if (conf) {
+		return conf->default_ttl;
+	}
+
+	return DEFAULT_TTL;
+}
+
+uint8_t *bt_mesh_label_uuid_get(uint16_t addr)
+{
+	int i;
+
+	BT_DBG("addr 0x%04x", addr);
+
+	for (i = 0; i < ARRAY_SIZE(labels); i++) {
+		if (labels[i].addr == addr) {
+			BT_DBG("Found Label UUID for 0x%04x: %s", addr,
+			       bt_hex(labels[i].uuid, 16));
+			return labels[i].uuid;
+		}
+	}
+
+	BT_WARN("No matching Label UUID for 0x%04x", addr);
+
+	return NULL;
+}
+
+struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
+{
+	return &conf->hb_pub;
+}
+
+void bt_mesh_hb_pub_disable(void)
+{
+	hb_pub_disable(conf);
+}
+
+struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
+{
+	return conf;
+}
+
+void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
+{
+	int i;
+
+	BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
+
+	if (conf->hb_pub.net_idx == sub->net_idx) {
+		hb_pub_disable(conf);
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+			bt_mesh_store_hb_pub();
+		}
+	}
+
+	/* Delete any app keys bound to this NetKey index */
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx == sub->net_idx) {
+			bt_mesh_app_key_del(key, store);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		bt_mesh_friend_clear_net_idx(sub->net_idx);
+	}
+
+	bt_mesh_net_loopback_clear(sub->net_idx);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+		bt_mesh_clear_subnet(sub);
+	}
+
+	(void)memset(sub, 0, sizeof(*sub));
+	sub->net_idx = BT_MESH_KEY_UNUSED;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.h	(working copy)
@@ -0,0 +1,157 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_mesh_sg {
+	const void *data;
+	size_t len;
+};
+
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+		     size_t sg_len, uint8_t mac[16]);
+
+static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
+				       size_t len, uint8_t mac[16])
+{
+	struct bt_mesh_sg sg = { m, len };
+
+	return bt_mesh_aes_cmac(key, &sg, 1, mac);
+}
+
+static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
+{
+	const uint8_t zero[16] = { 0 };
+
+	return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
+}
+
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+	       const char *info, uint8_t okm[16]);
+
+#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
+({ \
+	const uint8_t salt[16] = salt_str; \
+	bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
+})
+
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+	       uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]);
+
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]);
+
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]);
+
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]);
+
+static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16],
+					   uint8_t resolving_key[16])
+{
+	return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
+}
+
+static inline int bt_mesh_identity_key(const uint8_t net_key[16],
+				       uint8_t identity_key[16])
+{
+	return bt_mesh_id128(net_key, "nkik", identity_key);
+}
+
+static inline int bt_mesh_beacon_key(const uint8_t net_key[16],
+				     uint8_t beacon_key[16])
+{
+	return bt_mesh_id128(net_key, "nkbk", beacon_key);
+}
+
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+			const uint8_t net_id[16], uint32_t iv_index,
+			uint8_t auth[8]);
+
+static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1])
+{
+	return bt_mesh_k4(app_key, app_id);
+}
+
+static inline int bt_mesh_session_key(const uint8_t dhkey[32],
+				      const uint8_t prov_salt[16],
+				      uint8_t session_key[16])
+{
+	return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
+}
+
+static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32],
+				      const uint8_t prov_salt[16],
+				      uint8_t nonce[13])
+{
+	uint8_t tmp[16];
+	int err;
+
+	err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
+	if (!err) {
+		memcpy(nonce, tmp + 3, 13);
+	}
+
+	return err;
+}
+
+static inline int bt_mesh_dev_key(const uint8_t dhkey[32],
+				  const uint8_t prov_salt[16],
+				  uint8_t dev_key[16])
+{
+	return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
+}
+
+static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16],
+				    const uint8_t prov_rand[16],
+				    const uint8_t dev_rand[16],
+				    uint8_t prov_salt[16])
+{
+	const uint8_t prov_salt_key[16] = { 0 };
+	struct bt_mesh_sg sg[] = {
+		{ conf_salt, 16 },
+		{ prov_rand, 16 },
+		{ dev_rand, 16 },
+	};
+
+	return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
+}
+
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+			  const uint8_t privacy_key[16]);
+
+int bt_mesh_net_encrypt(const uint8_t key[16], struct net_buf_simple *buf,
+			uint32_t iv_index, bool proxy);
+
+int bt_mesh_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf,
+			uint32_t iv_index, bool proxy);
+
+int bt_mesh_app_encrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic,
+			struct net_buf_simple *buf, const uint8_t *ad,
+			uint16_t src, uint16_t dst, uint32_t seq_num, uint32_t iv_index);
+
+int bt_mesh_app_decrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic,
+			struct net_buf_simple *buf, struct net_buf_simple *out,
+			const uint8_t *ad, uint16_t src, uint16_t dst, uint32_t seq_num,
+			uint32_t iv_index);
+
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len);
+
+bool bt_mesh_fcs_check(struct net_buf_simple *buf, uint8_t received_fcs);
+
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr);
+
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]);
+
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+			  uint8_t conf_key[16]);
+
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+		      const uint8_t auth[16], uint8_t conf[16]);
+
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+			 const uint8_t data[25 + 8], uint8_t out[25]);
+
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+			 const uint8_t data[25], uint8_t out[25 + 8]);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/crypto.c	(working copy)
@@ -0,0 +1,554 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <toolchain.h>
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/aes.h>
+#include <tinycrypt/cmac_mode.h>
+#include <tinycrypt/ccm_mode.h>
+
+#include <bluetooth/mesh.h>
+#include <bluetooth/crypto.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CRYPTO)
+#define LOG_MODULE_NAME bt_mesh_crypto
+#include "common/log.h"
+
+#include "mesh.h"
+#include "crypto.h"
+
+#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
+#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
+
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+		     size_t sg_len, uint8_t mac[16])
+{
+	struct tc_aes_key_sched_struct sched;
+	struct tc_cmac_struct state;
+
+	if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
+		return -EIO;
+	}
+
+	for (; sg_len; sg_len--, sg++) {
+		if (tc_cmac_update(&state, sg->data,
+				   sg->len) == TC_CRYPTO_FAIL) {
+			return -EIO;
+		}
+	}
+
+	if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+	       const char *info, uint8_t okm[16])
+{
+	int err;
+
+	err = bt_mesh_aes_cmac_one(salt, ikm, ikm_len, okm);
+	if (err < 0) {
+		return err;
+	}
+
+	return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
+}
+
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+	       uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16])
+{
+	struct bt_mesh_sg sg[3];
+	uint8_t salt[16];
+	uint8_t out[16];
+	uint8_t t[16];
+	uint8_t pad;
+	int err;
+
+	BT_DBG("n %s", bt_hex(n, 16));
+	BT_DBG("p %s", bt_hex(p, p_len));
+
+	err = bt_mesh_s1("smk2", salt);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(salt, n, 16, t);
+	if (err) {
+		return err;
+	}
+
+	pad = 0x01;
+
+	sg[0].data = NULL;
+	sg[0].len  = 0;
+	sg[1].data = p;
+	sg[1].len  = p_len;
+	sg[2].data = &pad;
+	sg[2].len  = sizeof(pad);
+
+	err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
+	if (err) {
+		return err;
+	}
+
+	net_id[0] = out[15] & 0x7f;
+
+	sg[0].data = out;
+	sg[0].len  = sizeof(out);
+	pad = 0x02;
+
+	err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
+	if (err) {
+		return err;
+	}
+
+	memcpy(enc_key, out, 16);
+
+	pad = 0x03;
+
+	err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out);
+	if (err) {
+		return err;
+	}
+
+	memcpy(priv_key, out, 16);
+
+	BT_DBG("NID 0x%02x enc_key %s", net_id[0], bt_hex(enc_key, 16));
+	BT_DBG("priv_key %s", bt_hex(priv_key, 16));
+
+	return 0;
+}
+
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8])
+{
+	uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
+	uint8_t tmp[16];
+	uint8_t t[16];
+	int err;
+
+	err = bt_mesh_s1("smk3", tmp);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(tmp, n, 16, t);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(t, id64, sizeof(id64), tmp);
+	if (err) {
+		return err;
+	}
+
+	memcpy(out, tmp + 8, 8);
+
+	return 0;
+}
+
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1])
+{
+	uint8_t id6[] = { 'i', 'd', '6', 0x01 };
+	uint8_t tmp[16];
+	uint8_t t[16];
+	int err;
+
+	err = bt_mesh_s1("smk4", tmp);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(tmp, n, 16, t);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(t, id6, sizeof(id6), tmp);
+	if (err) {
+		return err;
+	}
+
+	out[0] = tmp[15] & BIT_MASK(6);
+
+	return 0;
+}
+
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
+{
+	const char *id128 = "id128\x01";
+	uint8_t salt[16];
+	int err;
+
+	err = bt_mesh_s1(s, salt);
+	if (err) {
+		return err;
+	}
+
+	return bt_mesh_k1(n, 16, salt, id128, out);
+}
+
+static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+			       uint32_t iv_index)
+{
+	/* Nonce Type */
+	nonce[0] = 0x03;
+
+	/* Pad */
+	nonce[1] = 0x00;
+
+	/* Sequence Number */
+	nonce[2] = pdu[2];
+	nonce[3] = pdu[3];
+	nonce[4] = pdu[4];
+
+	/* Source Address */
+	nonce[5] = pdu[5];
+	nonce[6] = pdu[6];
+
+	/* Pad */
+	nonce[7] = 0U;
+	nonce[8] = 0U;
+
+	/* IV Index */
+	sys_put_be32(iv_index, &nonce[9]);
+}
+
+static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu,
+			     uint32_t iv_index)
+{
+	/* Nonce Type */
+	nonce[0] = 0x00;
+
+	/* FRND + TTL */
+	nonce[1] = pdu[1];
+
+	/* Sequence Number */
+	nonce[2] = pdu[2];
+	nonce[3] = pdu[3];
+	nonce[4] = pdu[4];
+
+	/* Source Address */
+	nonce[5] = pdu[5];
+	nonce[6] = pdu[6];
+
+	/* Pad */
+	nonce[7] = 0U;
+	nonce[8] = 0U;
+
+	/* IV Index */
+	sys_put_be32(iv_index, &nonce[9]);
+}
+
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+			  const uint8_t privacy_key[16])
+{
+	uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
+	uint8_t tmp[16];
+	int err, i;
+
+	BT_DBG("IVIndex %u, PrivacyKey %s", iv_index, bt_hex(privacy_key, 16));
+
+	sys_put_be32(iv_index, &priv_rand[5]);
+	memcpy(&priv_rand[9], &pdu[7], 7);
+
+	BT_DBG("PrivacyRandom %s", bt_hex(priv_rand, 16));
+
+	err = bt_encrypt_be(privacy_key, priv_rand, tmp);
+	if (err) {
+		return err;
+	}
+
+	for (i = 0; i < 6; i++) {
+		pdu[1 + i] ^= tmp[i];
+	}
+
+	return 0;
+}
+
+int bt_mesh_net_encrypt(const uint8_t key[16], struct net_buf_simple *buf,
+			uint32_t iv_index, bool proxy)
+{
+	uint8_t mic_len = NET_MIC_LEN(buf->data);
+	uint8_t nonce[13];
+	int err;
+
+	BT_DBG("IVIndex %u EncKey %s mic_len %u", iv_index, bt_hex(key, 16),
+	       mic_len);
+	BT_DBG("PDU (len %u) %s", buf->len, bt_hex(buf->data, buf->len));
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) {
+		create_proxy_nonce(nonce, buf->data, iv_index);
+	} else {
+		create_net_nonce(nonce, buf->data, iv_index);
+	}
+
+	BT_DBG("Nonce %s", bt_hex(nonce, 13));
+
+	err = bt_ccm_encrypt(key, nonce, &buf->data[7], buf->len - 7, NULL, 0,
+			     &buf->data[7], mic_len);
+	if (!err) {
+		net_buf_simple_add(buf, mic_len);
+	}
+
+	return err;
+}
+
+int bt_mesh_net_decrypt(const uint8_t key[16], struct net_buf_simple *buf,
+			uint32_t iv_index, bool proxy)
+{
+	uint8_t mic_len = NET_MIC_LEN(buf->data);
+	uint8_t nonce[13];
+
+	BT_DBG("PDU (%u bytes) %s", buf->len, bt_hex(buf->data, buf->len));
+	BT_DBG("iv_index %u, key %s mic_len %u", iv_index, bt_hex(key, 16),
+	       mic_len);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) {
+		create_proxy_nonce(nonce, buf->data, iv_index);
+	} else {
+		create_net_nonce(nonce, buf->data, iv_index);
+	}
+
+	BT_DBG("Nonce %s", bt_hex(nonce, 13));
+
+	buf->len -= mic_len;
+
+	return bt_ccm_decrypt(key, nonce, &buf->data[7], buf->len - 7, NULL, 0,
+			      &buf->data[7], mic_len);
+}
+
+static void create_app_nonce(uint8_t nonce[13], bool dev_key, uint8_t aszmic,
+			     uint16_t src, uint16_t dst, uint32_t seq_num,
+			     uint32_t iv_index)
+{
+	if (dev_key) {
+		nonce[0] = 0x02;
+	} else {
+		nonce[0] = 0x01;
+	}
+
+	sys_put_be32((seq_num | ((uint32_t)aszmic << 31)), &nonce[1]);
+
+	sys_put_be16(src, &nonce[5]);
+	sys_put_be16(dst, &nonce[7]);
+
+	sys_put_be32(iv_index, &nonce[9]);
+}
+
+int bt_mesh_app_encrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic,
+			struct net_buf_simple *buf, const uint8_t *ad,
+			uint16_t src, uint16_t dst, uint32_t seq_num, uint32_t iv_index)
+{
+	uint8_t nonce[13];
+	int err;
+
+	BT_DBG("AppKey %s", bt_hex(key, 16));
+	BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
+	BT_DBG("seq_num 0x%08x iv_index 0x%08x", seq_num, iv_index);
+	BT_DBG("Clear: %s", bt_hex(buf->data, buf->len));
+
+	create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+
+	BT_DBG("Nonce  %s", bt_hex(nonce, 13));
+
+	err = bt_ccm_encrypt(key, nonce, buf->data, buf->len, ad, ad ? 16 : 0,
+			     buf->data, APP_MIC_LEN(aszmic));
+	if (!err) {
+		net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
+		BT_DBG("Encr: %s", bt_hex(buf->data, buf->len));
+	}
+
+	return err;
+}
+
+int bt_mesh_app_decrypt(const uint8_t key[16], bool dev_key, uint8_t aszmic,
+			struct net_buf_simple *buf, struct net_buf_simple *out,
+			const uint8_t *ad, uint16_t src, uint16_t dst, uint32_t seq_num,
+			uint32_t iv_index)
+{
+	uint8_t nonce[13];
+	int err;
+
+	BT_DBG("EncData (len %u) %s", buf->len, bt_hex(buf->data, buf->len));
+
+	create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+
+	BT_DBG("AppKey %s", bt_hex(key, 16));
+	BT_DBG("Nonce  %s", bt_hex(nonce, 13));
+
+	err = bt_ccm_decrypt(key, nonce, buf->data, buf->len, ad, ad ? 16 : 0,
+			     out->data, APP_MIC_LEN(aszmic));
+	if (!err) {
+		net_buf_simple_add(out, buf->len);
+	}
+
+	return err;
+}
+
+/* reversed, 8-bit, poly=0x07 */
+static const uint8_t crc_table[256] = {
+	0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
+	0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
+	0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
+	0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
+
+	0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
+	0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
+	0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
+	0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
+
+	0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
+	0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
+	0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
+	0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
+
+	0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
+	0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
+	0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
+	0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
+
+	0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
+	0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
+	0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
+	0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
+
+	0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
+	0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
+	0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
+	0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
+
+	0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
+	0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
+	0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
+	0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
+
+	0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
+	0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
+	0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
+	0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
+};
+
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len)
+{
+	uint8_t fcs = 0xff;
+
+	while (data_len--) {
+		fcs = crc_table[fcs ^ *data++];
+	}
+
+	BT_DBG("fcs 0x%02x", 0xff - fcs);
+
+	return 0xff - fcs;
+}
+
+bool bt_mesh_fcs_check(struct net_buf_simple *buf, uint8_t received_fcs)
+{
+	const uint8_t *data = buf->data;
+	uint16_t data_len = buf->len;
+	uint8_t fcs = 0xff;
+
+	while (data_len--) {
+		fcs = crc_table[fcs ^ *data++];
+	}
+
+	return crc_table[fcs ^ received_fcs] == 0xcf;
+}
+
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr)
+{
+	uint8_t salt[16];
+	uint8_t tmp[16];
+	int err;
+
+	err = bt_mesh_s1("vtad", salt);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_aes_cmac_one(salt, virtual_label, 16, tmp);
+	if (err) {
+		return err;
+	}
+
+	*addr = (sys_get_be16(&tmp[14]) & 0x3fff) | 0x8000;
+
+	return 0;
+}
+
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16])
+{
+	const uint8_t conf_salt_key[16] = { 0 };
+
+	return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
+}
+
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+			  uint8_t conf_key[16])
+{
+	return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
+}
+
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+		      const uint8_t auth[16], uint8_t conf[16])
+{
+	struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
+
+	BT_DBG("ConfirmationKey %s", bt_hex(conf_key, 16));
+	BT_DBG("RandomDevice %s", bt_hex(rand, 16));
+	BT_DBG("AuthValue %s", bt_hex(auth, 16));
+
+	return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
+}
+
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+			 const uint8_t data[25 + 8], uint8_t out[25])
+{
+	return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
+}
+
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+			 const uint8_t data[25], uint8_t out[25 + 8])
+{
+	return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
+}
+
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+			const uint8_t net_id[8], uint32_t iv_index,
+			uint8_t auth[8])
+{
+	uint8_t msg[13], tmp[16];
+	int err;
+
+	BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
+	BT_DBG("NetId %s", bt_hex(net_id, 8));
+	BT_DBG("IV Index 0x%08x", iv_index);
+
+	msg[0] = flags;
+	memcpy(&msg[1], net_id, 8);
+	sys_put_be32(iv_index, &msg[9]);
+
+	BT_DBG("BeaconMsg %s", bt_hex(msg, sizeof(msg)));
+
+	err = bt_mesh_aes_cmac_one(beacon_key, msg, sizeof(msg), tmp);
+	if (!err) {
+		memcpy(auth, tmp, 8);
+	}
+
+	return err;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/foundation.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/foundation.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/foundation.h	(working copy)
@@ -0,0 +1,168 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define OP_APP_KEY_ADD                     BT_MESH_MODEL_OP_1(0x00)
+#define OP_APP_KEY_UPDATE                  BT_MESH_MODEL_OP_1(0x01)
+#define OP_DEV_COMP_DATA_STATUS            BT_MESH_MODEL_OP_1(0x02)
+#define OP_MOD_PUB_SET                     BT_MESH_MODEL_OP_1(0x03)
+#define OP_HEALTH_CURRENT_STATUS           BT_MESH_MODEL_OP_1(0x04)
+#define OP_HEALTH_FAULT_STATUS             BT_MESH_MODEL_OP_1(0x05)
+#define OP_HEARTBEAT_PUB_STATUS            BT_MESH_MODEL_OP_1(0x06)
+#define OP_APP_KEY_DEL                     BT_MESH_MODEL_OP_2(0x80, 0x00)
+#define OP_APP_KEY_GET                     BT_MESH_MODEL_OP_2(0x80, 0x01)
+#define OP_APP_KEY_LIST                    BT_MESH_MODEL_OP_2(0x80, 0x02)
+#define OP_APP_KEY_STATUS                  BT_MESH_MODEL_OP_2(0x80, 0x03)
+#define OP_ATTENTION_GET                   BT_MESH_MODEL_OP_2(0x80, 0x04)
+#define OP_ATTENTION_SET                   BT_MESH_MODEL_OP_2(0x80, 0x05)
+#define OP_ATTENTION_SET_UNREL             BT_MESH_MODEL_OP_2(0x80, 0x06)
+#define OP_ATTENTION_STATUS                BT_MESH_MODEL_OP_2(0x80, 0x07)
+#define OP_DEV_COMP_DATA_GET               BT_MESH_MODEL_OP_2(0x80, 0x08)
+#define OP_BEACON_GET                      BT_MESH_MODEL_OP_2(0x80, 0x09)
+#define OP_BEACON_SET                      BT_MESH_MODEL_OP_2(0x80, 0x0a)
+#define OP_BEACON_STATUS                   BT_MESH_MODEL_OP_2(0x80, 0x0b)
+#define OP_DEFAULT_TTL_GET                 BT_MESH_MODEL_OP_2(0x80, 0x0c)
+#define OP_DEFAULT_TTL_SET                 BT_MESH_MODEL_OP_2(0x80, 0x0d)
+#define OP_DEFAULT_TTL_STATUS              BT_MESH_MODEL_OP_2(0x80, 0x0e)
+#define OP_FRIEND_GET                      BT_MESH_MODEL_OP_2(0x80, 0x0f)
+#define OP_FRIEND_SET                      BT_MESH_MODEL_OP_2(0x80, 0x10)
+#define OP_FRIEND_STATUS                   BT_MESH_MODEL_OP_2(0x80, 0x11)
+#define OP_GATT_PROXY_GET                  BT_MESH_MODEL_OP_2(0x80, 0x12)
+#define OP_GATT_PROXY_SET                  BT_MESH_MODEL_OP_2(0x80, 0x13)
+#define OP_GATT_PROXY_STATUS               BT_MESH_MODEL_OP_2(0x80, 0x14)
+#define OP_KRP_GET                         BT_MESH_MODEL_OP_2(0x80, 0x15)
+#define OP_KRP_SET                         BT_MESH_MODEL_OP_2(0x80, 0x16)
+#define OP_KRP_STATUS                      BT_MESH_MODEL_OP_2(0x80, 0x17)
+#define OP_MOD_PUB_GET                     BT_MESH_MODEL_OP_2(0x80, 0x18)
+#define OP_MOD_PUB_STATUS                  BT_MESH_MODEL_OP_2(0x80, 0x19)
+#define OP_MOD_PUB_VA_SET                  BT_MESH_MODEL_OP_2(0x80, 0x1a)
+#define OP_MOD_SUB_ADD                     BT_MESH_MODEL_OP_2(0x80, 0x1b)
+#define OP_MOD_SUB_DEL                     BT_MESH_MODEL_OP_2(0x80, 0x1c)
+#define OP_MOD_SUB_DEL_ALL                 BT_MESH_MODEL_OP_2(0x80, 0x1d)
+#define OP_MOD_SUB_OVERWRITE               BT_MESH_MODEL_OP_2(0x80, 0x1e)
+#define OP_MOD_SUB_STATUS                  BT_MESH_MODEL_OP_2(0x80, 0x1f)
+#define OP_MOD_SUB_VA_ADD                  BT_MESH_MODEL_OP_2(0x80, 0x20)
+#define OP_MOD_SUB_VA_DEL                  BT_MESH_MODEL_OP_2(0x80, 0x21)
+#define OP_MOD_SUB_VA_OVERWRITE            BT_MESH_MODEL_OP_2(0x80, 0x22)
+#define OP_NET_TRANSMIT_GET                BT_MESH_MODEL_OP_2(0x80, 0x23)
+#define OP_NET_TRANSMIT_SET                BT_MESH_MODEL_OP_2(0x80, 0x24)
+#define OP_NET_TRANSMIT_STATUS             BT_MESH_MODEL_OP_2(0x80, 0x25)
+#define OP_RELAY_GET                       BT_MESH_MODEL_OP_2(0x80, 0x26)
+#define OP_RELAY_SET                       BT_MESH_MODEL_OP_2(0x80, 0x27)
+#define OP_RELAY_STATUS                    BT_MESH_MODEL_OP_2(0x80, 0x28)
+#define OP_MOD_SUB_GET                     BT_MESH_MODEL_OP_2(0x80, 0x29)
+#define OP_MOD_SUB_LIST                    BT_MESH_MODEL_OP_2(0x80, 0x2a)
+#define OP_MOD_SUB_GET_VND                 BT_MESH_MODEL_OP_2(0x80, 0x2b)
+#define OP_MOD_SUB_LIST_VND                BT_MESH_MODEL_OP_2(0x80, 0x2c)
+#define OP_LPN_TIMEOUT_GET                 BT_MESH_MODEL_OP_2(0x80, 0x2d)
+#define OP_LPN_TIMEOUT_STATUS              BT_MESH_MODEL_OP_2(0x80, 0x2e)
+#define OP_HEALTH_FAULT_CLEAR              BT_MESH_MODEL_OP_2(0x80, 0x2f)
+#define OP_HEALTH_FAULT_CLEAR_UNREL        BT_MESH_MODEL_OP_2(0x80, 0x30)
+#define OP_HEALTH_FAULT_GET                BT_MESH_MODEL_OP_2(0x80, 0x31)
+#define OP_HEALTH_FAULT_TEST               BT_MESH_MODEL_OP_2(0x80, 0x32)
+#define OP_HEALTH_FAULT_TEST_UNREL         BT_MESH_MODEL_OP_2(0x80, 0x33)
+#define OP_HEALTH_PERIOD_GET               BT_MESH_MODEL_OP_2(0x80, 0x34)
+#define OP_HEALTH_PERIOD_SET               BT_MESH_MODEL_OP_2(0x80, 0x35)
+#define OP_HEALTH_PERIOD_SET_UNREL         BT_MESH_MODEL_OP_2(0x80, 0x36)
+#define OP_HEALTH_PERIOD_STATUS            BT_MESH_MODEL_OP_2(0x80, 0x37)
+#define OP_HEARTBEAT_PUB_GET               BT_MESH_MODEL_OP_2(0x80, 0x38)
+#define OP_HEARTBEAT_PUB_SET               BT_MESH_MODEL_OP_2(0x80, 0x39)
+#define OP_HEARTBEAT_SUB_GET               BT_MESH_MODEL_OP_2(0x80, 0x3a)
+#define OP_HEARTBEAT_SUB_SET               BT_MESH_MODEL_OP_2(0x80, 0x3b)
+#define OP_HEARTBEAT_SUB_STATUS            BT_MESH_MODEL_OP_2(0x80, 0x3c)
+#define OP_MOD_APP_BIND                    BT_MESH_MODEL_OP_2(0x80, 0x3d)
+#define OP_MOD_APP_STATUS                  BT_MESH_MODEL_OP_2(0x80, 0x3e)
+#define OP_MOD_APP_UNBIND                  BT_MESH_MODEL_OP_2(0x80, 0x3f)
+#define OP_NET_KEY_ADD                     BT_MESH_MODEL_OP_2(0x80, 0x40)
+#define OP_NET_KEY_DEL                     BT_MESH_MODEL_OP_2(0x80, 0x41)
+#define OP_NET_KEY_GET                     BT_MESH_MODEL_OP_2(0x80, 0x42)
+#define OP_NET_KEY_LIST                    BT_MESH_MODEL_OP_2(0x80, 0x43)
+#define OP_NET_KEY_STATUS                  BT_MESH_MODEL_OP_2(0x80, 0x44)
+#define OP_NET_KEY_UPDATE                  BT_MESH_MODEL_OP_2(0x80, 0x45)
+#define OP_NODE_IDENTITY_GET               BT_MESH_MODEL_OP_2(0x80, 0x46)
+#define OP_NODE_IDENTITY_SET               BT_MESH_MODEL_OP_2(0x80, 0x47)
+#define OP_NODE_IDENTITY_STATUS            BT_MESH_MODEL_OP_2(0x80, 0x48)
+#define OP_NODE_RESET                      BT_MESH_MODEL_OP_2(0x80, 0x49)
+#define OP_NODE_RESET_STATUS               BT_MESH_MODEL_OP_2(0x80, 0x4a)
+#define OP_SIG_MOD_APP_GET                 BT_MESH_MODEL_OP_2(0x80, 0x4b)
+#define OP_SIG_MOD_APP_LIST                BT_MESH_MODEL_OP_2(0x80, 0x4c)
+#define OP_VND_MOD_APP_GET                 BT_MESH_MODEL_OP_2(0x80, 0x4d)
+#define OP_VND_MOD_APP_LIST                BT_MESH_MODEL_OP_2(0x80, 0x4e)
+
+#define STATUS_SUCCESS                     0x00
+#define STATUS_INVALID_ADDRESS             0x01
+#define STATUS_INVALID_MODEL               0x02
+#define STATUS_INVALID_APPKEY              0x03
+#define STATUS_INVALID_NETKEY              0x04
+#define STATUS_INSUFF_RESOURCES            0x05
+#define STATUS_IDX_ALREADY_STORED          0x06
+#define STATUS_NVAL_PUB_PARAM              0x07
+#define STATUS_NOT_SUB_MOD                 0x08
+#define STATUS_STORAGE_FAIL                0x09
+#define STATUS_FEAT_NOT_SUPP               0x0a
+#define STATUS_CANNOT_UPDATE               0x0b
+#define STATUS_CANNOT_REMOVE               0x0c
+#define STATUS_CANNOT_BIND                 0x0d
+#define STATUS_TEMP_STATE_CHG_FAIL         0x0e
+#define STATUS_CANNOT_SET                  0x0f
+#define STATUS_UNSPECIFIED                 0x10
+#define STATUS_INVALID_BINDING             0x11
+
+enum {
+	BT_MESH_VA_CHANGED,	/* Label information changed */
+};
+
+struct label {
+	uint16_t ref;
+	uint16_t addr;
+	uint8_t  uuid[16];
+	atomic_t flags[1];
+};
+
+void bt_mesh_cfg_reset(void);
+
+void bt_mesh_heartbeat(uint16_t src, uint16_t dst, uint8_t hops, uint16_t feat);
+
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
+
+struct label *get_label(uint16_t index);
+
+uint8_t *bt_mesh_label_uuid_get(uint16_t addr);
+
+struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
+void bt_mesh_hb_pub_disable(void);
+struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
+
+uint8_t bt_mesh_net_transmit_get(void);
+uint8_t bt_mesh_relay_get(void);
+uint8_t bt_mesh_friend_get(void);
+uint8_t bt_mesh_relay_retransmit_get(void);
+uint8_t bt_mesh_beacon_get(void);
+uint8_t bt_mesh_gatt_proxy_get(void);
+uint8_t bt_mesh_default_ttl_get(void);
+
+void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
+
+struct bt_mesh_app_key *bt_mesh_app_key_alloc(uint16_t app_idx);
+void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
+
+#include <sys/byteorder.h>
+
+static inline void key_idx_pack(struct net_buf_simple *buf,
+				uint16_t idx1, uint16_t idx2)
+{
+	net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
+	net_buf_simple_add_u8(buf, idx2 >> 4);
+}
+
+static inline void key_idx_unpack(struct net_buf_simple *buf,
+				  uint16_t *idx1, uint16_t *idx2)
+{
+	*idx1 = sys_get_le16(&buf->data[0]) & 0xfff;
+	*idx2 = sys_get_le16(&buf->data[1]) >> 4;
+	net_buf_simple_pull(buf, 3);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.h	(working copy)
@@ -0,0 +1,49 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+enum bt_mesh_friend_pdu_type {
+	BT_MESH_FRIEND_PDU_SINGLE,
+	BT_MESH_FRIEND_PDU_PARTIAL,
+	BT_MESH_FRIEND_PDU_COMPLETE,
+};
+
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr);
+
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
+					   bool valid, bool established);
+
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+				    uint64_t *seq_auth, uint8_t seg_count);
+
+void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
+			       enum bt_mesh_friend_pdu_type type,
+			       const uint64_t *seq_auth, uint8_t seg_count,
+			       struct net_buf_simple *sbuf);
+bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
+			       enum bt_mesh_friend_pdu_type type,
+			       const uint64_t *seq_auth, uint8_t seg_count,
+			       struct net_buf_simple *sbuf);
+
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+				     uint16_t dst, uint64_t *seq_auth);
+
+void bt_mesh_friend_sec_update(uint16_t net_idx);
+
+void bt_mesh_friend_clear_net_idx(uint16_t net_idx);
+
+int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
+int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
+int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
+int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
+			     struct net_buf_simple *buf);
+int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
+			   struct net_buf_simple *buf);
+int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
+			   struct net_buf_simple *buf);
+
+int bt_mesh_friend_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/friend.c	(working copy)
@@ -0,0 +1,1636 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <zephyr.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_FRIEND)
+#define LOG_MODULE_NAME bt_mesh_friend
+#include "common/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "friend.h"
+
+/* We reserve one extra buffer for each friendship, since we need to be able
+ * to resend the last sent PDU, which sits separately outside of the queue.
+ */
+#define FRIEND_BUF_COUNT    ((CONFIG_BT_MESH_FRIEND_QUEUE_SIZE + 1) * \
+			     CONFIG_BT_MESH_FRIEND_LPN_COUNT)
+
+#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), struct friend_adv, adv)
+
+/* PDUs from Friend to the LPN should only be transmitted once with the
+ * smallest possible interval (20ms).
+ */
+#define FRIEND_XMIT         BT_MESH_TRANSMIT(0, 20)
+
+struct friend_pdu_info {
+	uint16_t  src;
+	uint16_t  dst;
+
+	uint8_t   seq[3];
+
+	uint8_t   ttl:7,
+	       ctl:1;
+
+	uint32_t  iv_index;
+};
+
+NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
+			  BT_MESH_ADV_DATA_SIZE, NULL);
+
+static struct friend_adv {
+	struct bt_mesh_adv adv;
+	uint16_t app_idx;
+} adv_pool[FRIEND_BUF_COUNT];
+
+static struct bt_mesh_adv *adv_alloc(int id)
+{
+	adv_pool[id].app_idx = BT_MESH_KEY_UNUSED;
+	return &adv_pool[id].adv;
+}
+
+static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
+{
+	if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) {
+		return false;
+	}
+
+	return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem));
+}
+
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
+					   bool valid, bool established)
+{
+	int i;
+
+	BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (valid && !frnd->valid) {
+			continue;
+		}
+
+		if (established && !frnd->established) {
+			continue;
+		}
+
+		if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
+			continue;
+		}
+
+		if (is_lpn_unicast(frnd, lpn_addr)) {
+			return frnd;
+		}
+	}
+
+	return NULL;
+}
+
+static void purge_buffers(sys_slist_t *list)
+{
+	while (!sys_slist_is_empty(list)) {
+		struct net_buf *buf;
+
+		buf = (void *)sys_slist_get_not_empty(list);
+
+		buf->frags = NULL;
+		buf->flags &= ~NET_BUF_FRAGS;
+
+		net_buf_unref(buf);
+	}
+}
+
+/* Intentionally start a little bit late into the ReceiveWindow when
+ * it's large enough. This may improve reliability with some platforms,
+ * like the PTS, where the receiver might not have sufficiently compensated
+ * for internal latencies required to start scanning.
+ */
+static int32_t recv_delay(struct bt_mesh_friend *frnd)
+{
+#if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
+	return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
+#else
+	return frnd->recv_delay;
+#endif
+}
+
+static void friend_clear(struct bt_mesh_friend *frnd)
+{
+	int i;
+
+	BT_DBG("LPN 0x%04x", frnd->lpn);
+
+	k_delayed_work_cancel(&frnd->timer);
+
+	friend_cred_del(frnd->net_idx, frnd->lpn);
+
+	if (frnd->last) {
+		/* Cancel the sending if necessary */
+		if (frnd->pending_buf) {
+			BT_MESH_ADV(frnd->last)->busy = 0U;
+		}
+
+		net_buf_unref(frnd->last);
+		frnd->last = NULL;
+	}
+
+	purge_buffers(&frnd->queue);
+
+	for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
+		struct bt_mesh_friend_seg *seg = &frnd->seg[i];
+
+		purge_buffers(&seg->queue);
+		seg->seg_count = 0U;
+	}
+
+	frnd->valid = 0U;
+	frnd->established = 0U;
+	frnd->pending_buf = 0U;
+	frnd->fsn = 0U;
+	frnd->queue_size = 0U;
+	frnd->pending_req = 0U;
+	(void)memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
+}
+
+void bt_mesh_friend_clear_net_idx(uint16_t net_idx)
+{
+	int i;
+
+	BT_DBG("net_idx 0x%04x", net_idx);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
+			friend_clear(frnd);
+		}
+	}
+}
+
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md);
+
+void bt_mesh_friend_sec_update(uint16_t net_idx)
+{
+	int i;
+
+	BT_DBG("net_idx 0x%04x", net_idx);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
+			enqueue_update(frnd, 0x00);
+		}
+	}
+}
+
+int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_clear *msg = (void *)buf->data;
+	struct bt_mesh_friend *frnd;
+	uint16_t lpn_addr, lpn_counter;
+	struct bt_mesh_net_tx tx = {
+		.sub  = rx->sub,
+		.ctx  = &rx->ctx,
+		.src  = bt_mesh_primary_addr(),
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+	struct bt_mesh_ctl_friend_clear_confirm cfm;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Clear");
+		return -EINVAL;
+	}
+
+	lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
+	lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
+
+	BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter);
+
+	frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false);
+	if (!frnd) {
+		BT_WARN("No matching LPN addr 0x%04x", lpn_addr);
+		return 0;
+	}
+
+	/* A Friend Clear message is considered valid if the result of the
+	 * subtraction of the value of the LPNCounter field of the Friend
+	 * Request message (the one that initiated the friendship) from the
+	 * value of the LPNCounter field of the Friend Clear message, modulo
+	 * 65536, is in the range 0 to 255 inclusive.
+	 */
+	if (lpn_counter - frnd->lpn_counter > 255) {
+		BT_WARN("LPN Counter out of range (old %u new %u)",
+			frnd->lpn_counter, lpn_counter);
+		return 0;
+	}
+
+	tx.ctx->send_ttl = BT_MESH_TTL_MAX;
+
+	cfm.lpn_addr    = msg->lpn_addr;
+	cfm.lpn_counter = msg->lpn_counter;
+
+	bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
+			 sizeof(cfm), NULL, NULL);
+
+	friend_clear(frnd);
+
+	return 0;
+}
+
+static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
+		if (frnd->sub_list[i] == BT_MESH_ADDR_UNASSIGNED) {
+			frnd->sub_list[i] = addr;
+			return;
+		}
+	}
+
+	BT_WARN("No space in friend subscription list");
+}
+
+static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
+		if (frnd->sub_list[i] == addr) {
+			frnd->sub_list[i] = BT_MESH_ADDR_UNASSIGNED;
+			return;
+		}
+	}
+}
+
+static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
+					 struct friend_pdu_info *info,
+					 struct net_buf_simple *sdu)
+{
+	struct net_buf *buf;
+
+	buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc,
+					   BT_MESH_ADV_DATA,
+					   FRIEND_XMIT, K_NO_WAIT);
+	if (!buf) {
+		return NULL;
+	}
+
+	net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */
+
+	if (info->ctl) {
+		net_buf_add_u8(buf, info->ttl | 0x80);
+	} else {
+		net_buf_add_u8(buf, info->ttl);
+	}
+
+	net_buf_add_mem(buf, info->seq, sizeof(info->seq));
+
+	net_buf_add_be16(buf, info->src);
+	net_buf_add_be16(buf, info->dst);
+
+	net_buf_add_mem(buf, sdu->data, sdu->len);
+
+	return buf;
+}
+
+struct unseg_app_sdu_meta {
+	struct bt_mesh_net_rx net;
+	const uint8_t *key;
+	struct bt_mesh_subnet *subnet;
+	bool is_dev_key;
+	uint8_t aid;
+	uint8_t *ad;
+};
+
+static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
+				struct net_buf *buf,
+				struct unseg_app_sdu_meta *meta)
+{
+	uint16_t app_idx = FRIEND_ADV(buf)->app_idx;
+	int err;
+
+	meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
+	meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx);
+	bt_mesh_net_header_parse(&buf->b, &meta->net);
+	err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst,
+				  &meta->key, &meta->aid);
+	if (err) {
+		return err;
+	}
+
+	if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
+		meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
+		if (!meta->ad) {
+			return -ENOENT;
+		}
+	} else {
+		meta->ad = NULL;
+	}
+
+	return 0;
+}
+
+static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
+				 struct net_buf *buf,
+				 const struct unseg_app_sdu_meta *meta)
+{
+	struct net_buf_simple sdu;
+
+	net_buf_simple_clone(&buf->b, &sdu);
+	net_buf_simple_pull(&sdu, 10);
+	sdu.len -= 4;
+
+	return bt_mesh_app_decrypt(meta->key, meta->is_dev_key, 0, &sdu, &sdu,
+				   meta->ad, meta->net.ctx.addr,
+				   meta->net.ctx.recv_dst, meta->net.seq,
+				   BT_MESH_NET_IVI_TX);
+}
+
+static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
+				 struct net_buf *buf,
+				 const struct unseg_app_sdu_meta *meta)
+{
+	struct net_buf_simple sdu;
+
+	net_buf_simple_clone(&buf->b, &sdu);
+	net_buf_simple_pull(&sdu, 10);
+	sdu.len -= 4;
+
+	return bt_mesh_app_encrypt(meta->key, meta->is_dev_key, 0, &sdu,
+				   meta->ad, meta->net.ctx.addr,
+				   meta->net.ctx.recv_dst, bt_mesh.seq,
+				   BT_MESH_NET_IVI_TX);
+}
+
+static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
+				 struct net_buf *buf)
+{
+	struct unseg_app_sdu_meta meta;
+	int err;
+
+	if (FRIEND_ADV(buf)->app_idx == BT_MESH_KEY_UNUSED) {
+		return 0;
+	}
+
+	err = unseg_app_sdu_unpack(frnd, buf, &meta);
+	if (err) {
+		return err;
+	}
+
+	/* No need to reencrypt the message if the sequence number is
+	 * unchanged.
+	 */
+	if (meta.net.seq == bt_mesh.seq) {
+		return 0;
+	}
+
+	err = unseg_app_sdu_decrypt(frnd, buf, &meta);
+	if (err) {
+		BT_WARN("Decryption failed! %d", err);
+		return err;
+	}
+
+	err = unseg_app_sdu_encrypt(frnd, buf, &meta);
+	if (err) {
+		BT_WARN("Re-encryption failed! %d", err);
+	}
+
+	return err;
+}
+
+static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf,
+			      bool master_cred)
+{
+	struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
+	const uint8_t *enc, *priv;
+	uint32_t iv_index;
+	uint16_t src;
+	uint8_t nid;
+	int err;
+
+	if (master_cred) {
+		enc = sub->keys[sub->kr_flag].enc;
+		priv = sub->keys[sub->kr_flag].privacy;
+		nid = sub->keys[sub->kr_flag].nid;
+	} else {
+		if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
+			BT_ERR("friend_cred_get failed");
+			return -ENOENT;
+		}
+	}
+
+	src = sys_get_be16(&buf->data[5]);
+
+	if (bt_mesh_elem_find(src)) {
+		uint32_t seq;
+
+		if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) {
+			err = unseg_app_sdu_prepare(frnd, buf);
+			if (err) {
+				return err;
+			}
+		}
+
+		seq = bt_mesh_next_seq();
+		sys_put_be24(seq, &buf->data[2]);
+
+		iv_index = BT_MESH_NET_IVI_TX;
+		FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED;
+	} else {
+		uint8_t ivi = (buf->data[0] >> 7);
+		iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
+	}
+
+	buf->data[0] = (nid | (iv_index & 1) << 7);
+
+	if (bt_mesh_net_encrypt(enc, &buf->b, iv_index, false)) {
+		BT_ERR("Encrypting failed");
+		return -EINVAL;
+	}
+
+	if (bt_mesh_net_obfuscate(buf->data, iv_index, priv)) {
+		BT_ERR("Obfuscating failed");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd,
+					 uint8_t ctl_op,
+					 struct net_buf_simple *sdu)
+{
+	struct friend_pdu_info info;
+
+	BT_DBG("LPN 0x%04x", frnd->lpn);
+
+	net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0));
+
+	info.src = bt_mesh_primary_addr();
+	info.dst = frnd->lpn;
+
+	info.ctl = 1U;
+	info.ttl = 0U;
+
+	memset(info.seq, 0, sizeof(info.seq));
+
+	info.iv_index = BT_MESH_NET_IVI_TX;
+
+	return create_friend_pdu(frnd, &info, sdu);
+}
+
+static struct net_buf *encode_update(struct bt_mesh_friend *frnd, uint8_t md)
+{
+	struct bt_mesh_ctl_friend_update *upd;
+	NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd));
+	struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
+
+	__ASSERT_NO_MSG(sub != NULL);
+
+	BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
+
+	net_buf_simple_reserve(&sdu, 1);
+
+	upd = net_buf_simple_add(&sdu, sizeof(*upd));
+	upd->flags = bt_mesh_net_flags(sub);
+	upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
+	upd->md = md;
+
+	return encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_UPDATE, &sdu);
+}
+
+static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact)
+{
+	struct bt_mesh_ctl_friend_sub_confirm *cfm;
+	NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*cfm));
+	struct net_buf *buf;
+
+	BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact);
+
+	net_buf_simple_reserve(&sdu, 1);
+
+	cfm = net_buf_simple_add(&sdu, sizeof(*cfm));
+	cfm->xact = xact;
+
+	buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_SUB_CFM, &sdu);
+	if (!buf) {
+		BT_ERR("Unable to encode Subscription List Confirmation");
+		return;
+	}
+
+	if (encrypt_friend_pdu(frnd, buf, false)) {
+		return;
+	}
+
+	if (frnd->last) {
+		BT_DBG("Discarding last PDU");
+		net_buf_unref(frnd->last);
+	}
+
+	frnd->last = buf;
+	frnd->send_last = 1U;
+}
+
+static void friend_recv_delay(struct bt_mesh_friend *frnd)
+{
+	frnd->pending_req = 1U;
+	k_delayed_work_submit(&frnd->timer, K_MSEC(recv_delay(frnd)));
+	BT_DBG("Waiting RecvDelay of %d ms", recv_delay(frnd));
+}
+
+int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_friend *frnd;
+	uint8_t xact;
+
+	if (buf->len < BT_MESH_FRIEND_SUB_MIN_LEN) {
+		BT_WARN("Too short Friend Subscription Add");
+		return -EINVAL;
+	}
+
+	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
+	if (!frnd) {
+		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
+		return 0;
+	}
+
+	if (frnd->pending_buf) {
+		BT_WARN("Previous buffer not yet sent!");
+		return 0;
+	}
+
+	friend_recv_delay(frnd);
+
+	xact = net_buf_simple_pull_u8(buf);
+
+	while (buf->len >= 2U) {
+		friend_sub_add(frnd, net_buf_simple_pull_be16(buf));
+	}
+
+	enqueue_sub_cfm(frnd, xact);
+
+	return 0;
+}
+
+int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
+			   struct net_buf_simple *buf)
+{
+	struct bt_mesh_friend *frnd;
+	uint8_t xact;
+
+	if (buf->len < BT_MESH_FRIEND_SUB_MIN_LEN) {
+		BT_WARN("Too short Friend Subscription Remove");
+		return -EINVAL;
+	}
+
+	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true);
+	if (!frnd) {
+		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
+		return 0;
+	}
+
+	if (frnd->pending_buf) {
+		BT_WARN("Previous buffer not yet sent!");
+		return 0;
+	}
+
+	friend_recv_delay(frnd);
+
+	xact = net_buf_simple_pull_u8(buf);
+
+	while (buf->len >= 2U) {
+		friend_sub_rem(frnd, net_buf_simple_pull_be16(buf));
+	}
+
+	enqueue_sub_cfm(frnd, xact);
+
+	return 0;
+}
+
+static void enqueue_buf(struct bt_mesh_friend *frnd, struct net_buf *buf)
+{
+	net_buf_slist_put(&frnd->queue, buf);
+	frnd->queue_size++;
+}
+
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md)
+{
+	struct net_buf *buf;
+
+	buf = encode_update(frnd, md);
+	if (!buf) {
+		BT_ERR("Unable to encode Friend Update");
+		return;
+	}
+
+	enqueue_buf(frnd, buf);
+}
+
+int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_poll *msg = (void *)buf->data;
+	struct bt_mesh_friend *frnd;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Poll");
+		return -EINVAL;
+	}
+
+	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
+	if (!frnd) {
+		BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr);
+		return 0;
+	}
+
+	if (msg->fsn & ~1) {
+		BT_WARN("Prohibited (non-zero) padding bits");
+		return -EINVAL;
+	}
+
+	if (frnd->pending_buf) {
+		BT_WARN("Previous buffer not yet sent");
+		return 0;
+	}
+
+	BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn);
+
+	friend_recv_delay(frnd);
+
+	if (!frnd->established) {
+		BT_DBG("Friendship established with 0x%04x", frnd->lpn);
+		frnd->established = 1U;
+	}
+
+	if (msg->fsn == frnd->fsn && frnd->last) {
+		BT_DBG("Re-sending last PDU");
+		frnd->send_last = 1U;
+	} else {
+		if (frnd->last) {
+			net_buf_unref(frnd->last);
+			frnd->last = NULL;
+		}
+
+		frnd->fsn = msg->fsn;
+
+		if (sys_slist_is_empty(&frnd->queue)) {
+			enqueue_update(frnd, 0);
+			BT_DBG("Enqueued Friend Update to empty queue");
+		}
+	}
+
+	return 0;
+}
+
+static struct bt_mesh_friend *find_clear(uint16_t prev_friend)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (frnd->clear.frnd == prev_friend) {
+			return frnd;
+		}
+	}
+
+	return NULL;
+}
+
+static void friend_clear_sent(int err, void *user_data)
+{
+	struct bt_mesh_friend *frnd = user_data;
+
+	k_delayed_work_submit(&frnd->clear.timer,
+			      K_SECONDS(frnd->clear.repeat_sec));
+	frnd->clear.repeat_sec *= 2U;
+}
+
+static const struct bt_mesh_send_cb clear_sent_cb = {
+	.end = friend_clear_sent,
+};
+
+static void send_friend_clear(struct bt_mesh_friend *frnd)
+{
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx  = frnd->net_idx,
+		.app_idx  = BT_MESH_KEY_UNUSED,
+		.addr     = frnd->clear.frnd,
+		.send_ttl = BT_MESH_TTL_MAX,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub  = bt_mesh_subnet_get(frnd->net_idx),
+		.ctx  = &ctx,
+		.src  = bt_mesh_primary_addr(),
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+	struct bt_mesh_ctl_friend_clear req = {
+		.lpn_addr    = sys_cpu_to_be16(frnd->lpn),
+		.lpn_counter = sys_cpu_to_be16(frnd->lpn_counter),
+	};
+
+	BT_DBG("");
+
+	bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
+			 sizeof(req), &clear_sent_cb, frnd);
+}
+
+static void clear_timeout(struct k_work *work)
+{
+	struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend,
+						   clear.timer.work);
+	uint32_t duration;
+
+	BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
+
+	duration = k_uptime_get_32() - frnd->clear.start;
+	if (duration > 2 * frnd->poll_to) {
+		BT_DBG("Clear Procedure timer expired");
+		frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
+		return;
+	}
+
+	send_friend_clear(frnd);
+}
+
+static void clear_procedure_start(struct bt_mesh_friend *frnd)
+{
+	BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
+
+	frnd->clear.start = k_uptime_get_32();
+	frnd->clear.repeat_sec = 1U;
+
+	send_friend_clear(frnd);
+}
+
+int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
+			     struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
+	struct bt_mesh_friend *frnd;
+	uint16_t lpn_addr, lpn_counter;
+
+	BT_DBG("");
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Clear Confirm");
+		return -EINVAL;
+	}
+
+	frnd = find_clear(rx->ctx.addr);
+	if (!frnd) {
+		BT_WARN("No pending clear procedure for 0x%02x", rx->ctx.addr);
+		return 0;
+	}
+
+	lpn_addr = sys_be16_to_cpu(msg->lpn_addr);
+	if (lpn_addr != frnd->lpn) {
+		BT_WARN("LPN address mismatch (0x%04x != 0x%04x)",
+			lpn_addr, frnd->lpn);
+		return 0;
+	}
+
+	lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
+	if (lpn_counter != frnd->lpn_counter) {
+		BT_WARN("LPN counter mismatch (0x%04x != 0x%04x)",
+			lpn_counter, frnd->lpn_counter);
+		return 0;
+	}
+
+	k_delayed_work_cancel(&frnd->clear.timer);
+	frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED;
+
+	return 0;
+}
+
+static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi)
+{
+	struct bt_mesh_ctl_friend_offer *off;
+	NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*off));
+	struct net_buf *buf;
+
+	BT_DBG("");
+
+	net_buf_simple_reserve(&sdu, 1);
+
+	off = net_buf_simple_add(&sdu, sizeof(*off));
+
+	off->recv_win = CONFIG_BT_MESH_FRIEND_RECV_WIN,
+	off->queue_size = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
+	off->sub_list_size = ARRAY_SIZE(frnd->sub_list),
+	off->rssi = rssi,
+	off->frnd_counter = sys_cpu_to_be16(frnd->counter);
+
+	buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_OFFER, &sdu);
+	if (!buf) {
+		BT_ERR("Unable to encode Friend Offer");
+		return;
+	}
+
+	if (encrypt_friend_pdu(frnd, buf, true)) {
+		return;
+	}
+
+	frnd->counter++;
+
+	if (frnd->last) {
+		net_buf_unref(frnd->last);
+	}
+
+	frnd->last = buf;
+	frnd->send_last = 1U;
+}
+
+#define RECV_WIN                  CONFIG_BT_MESH_FRIEND_RECV_WIN
+#define RSSI_FACT(crit)           (((crit) >> 5) & (uint8_t)BIT_MASK(2))
+#define RECV_WIN_FACT(crit)       (((crit) >> 3) & (uint8_t)BIT_MASK(2))
+#define MIN_QUEUE_SIZE_LOG(crit)  ((crit) & (uint8_t)BIT_MASK(3))
+#define MIN_QUEUE_SIZE(crit)      ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
+
+static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit)
+{
+	/* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
+	 * want to avoid floating-point arithmetic.
+	 */
+	static const uint8_t fact[] = { 10, 15, 20, 25 };
+	int32_t delay;
+
+	BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
+	       fact[RECV_WIN_FACT(crit)], RECV_WIN,
+	       fact[RSSI_FACT(crit)], rssi);
+
+	/* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
+	delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
+	delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi;
+	delay /= 10;
+
+	BT_DBG("Local Delay calculated as %d ms", delay);
+
+	return MAX(delay, 100);
+}
+
+int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_req *msg = (void *)buf->data;
+	struct bt_mesh_friend *frnd = NULL;
+	uint32_t poll_to;
+	int i;
+
+	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+		BT_DBG("Ignoring Friend request from local interface");
+		return 0;
+	}
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Request");
+		return -EINVAL;
+	}
+
+	if (msg->recv_delay <= 0x09) {
+		BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay);
+		return -EINVAL;
+	}
+
+	poll_to = sys_get_be24(msg->poll_to);
+
+	if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
+		BT_WARN("Prohibited PollTimeout (0x%06x)", poll_to);
+		return -EINVAL;
+	}
+
+	if (msg->num_elem == 0x00) {
+		BT_WARN("Prohibited NumElements value (0x00)");
+		return -EINVAL;
+	}
+
+	if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr + msg->num_elem - 1)) {
+		BT_WARN("LPN elements stretch outside of unicast range");
+		return -EINVAL;
+	}
+
+	if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) {
+		BT_WARN("Prohibited Minimum Queue Size in Friend Request");
+		return -EINVAL;
+	}
+
+	if (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) {
+		BT_WARN("We have a too small Friend Queue size (%u < %u)",
+			CONFIG_BT_MESH_FRIEND_QUEUE_SIZE,
+			MIN_QUEUE_SIZE(msg->criteria));
+		return 0;
+	}
+
+	frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false);
+	if (frnd) {
+		BT_WARN("Existing LPN re-requesting Friendship");
+		friend_clear(frnd);
+		goto init_friend;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		if (!bt_mesh.frnd[i].valid) {
+			frnd = &bt_mesh.frnd[i];
+			frnd->valid = 1U;
+			break;
+		}
+	}
+
+	if (!frnd) {
+		BT_WARN("No free Friend contexts for new LPN");
+		return -ENOMEM;
+	}
+
+init_friend:
+	frnd->lpn = rx->ctx.addr;
+	frnd->num_elem = msg->num_elem;
+	frnd->net_idx = rx->sub->net_idx;
+	frnd->recv_delay = msg->recv_delay;
+	frnd->poll_to = poll_to * 100U;
+	frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
+	frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
+
+	BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
+	       frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to);
+
+	if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) &&
+	    !bt_mesh_elem_find(frnd->clear.frnd)) {
+		clear_procedure_start(frnd);
+	}
+
+	k_delayed_work_submit(&frnd->timer,
+			      K_MSEC(offer_delay(frnd, rx->ctx.recv_rssi,
+						 msg->criteria)));
+
+	friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
+			   frnd->counter);
+
+	enqueue_offer(frnd, rx->ctx.recv_rssi);
+
+	return 0;
+}
+
+static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
+{
+	struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue);
+	struct net_buf_simple_state state;
+	uint16_t buf_seq_zero;
+	uint16_t buf_src;
+
+	if (!buf) {
+		return false;
+	}
+
+	net_buf_simple_save(&buf->b, &state);
+	net_buf_skip(buf, 5);   /* skip IVI, NID, CTL, TTL, SEQ */
+	buf_src = net_buf_pull_be16(buf);
+	net_buf_skip(buf, 3);   /* skip DST, OP/AID */
+	buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK);
+	net_buf_simple_restore(&buf->b, &state);
+
+	return ((src == buf_src) && (seq_zero == buf_seq_zero));
+}
+
+static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
+					  uint16_t src, uint16_t seq_zero,
+					  uint8_t seg_count)
+{
+	struct bt_mesh_friend_seg *unassigned = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
+		struct bt_mesh_friend_seg *seg = &frnd->seg[i];
+
+		if (is_seg(seg, src, seq_zero)) {
+			return seg;
+		}
+
+		if (!unassigned && !sys_slist_peek_head(&seg->queue)) {
+			unassigned = seg;
+		}
+	}
+
+	if (unassigned) {
+		unassigned->seg_count = seg_count;
+	}
+
+	return unassigned;
+}
+
+static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
+			       enum bt_mesh_friend_pdu_type type,
+			       uint16_t src, uint8_t seg_count,
+			       struct net_buf *buf)
+{
+	struct bt_mesh_friend_seg *seg;
+
+	BT_DBG("type %u", type);
+
+	if (type == BT_MESH_FRIEND_PDU_SINGLE) {
+		enqueue_buf(frnd, buf);
+		return;
+	}
+
+	uint16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
+
+	seg = get_seg(frnd, src, seq_zero, seg_count);
+	if (!seg) {
+		BT_ERR("No free friend segment RX contexts for 0x%04x", src);
+		net_buf_unref(buf);
+		return;
+	}
+
+	net_buf_slist_put(&seg->queue, buf);
+
+	if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
+		sys_slist_merge_slist(&frnd->queue, &seg->queue);
+
+		frnd->queue_size += seg->seg_count;
+		seg->seg_count = 0U;
+	} else {
+		/* Mark the buffer as having more to come after it */
+		buf->flags |= NET_BUF_FRAGS;
+	}
+}
+
+static void buf_send_start(uint16_t duration, int err, void *user_data)
+{
+	struct bt_mesh_friend *frnd = user_data;
+
+	BT_DBG("err %d", err);
+
+	frnd->pending_buf = 0U;
+
+	/* Friend Offer doesn't follow the re-sending semantics */
+	if (!frnd->established && frnd->last) {
+		net_buf_unref(frnd->last);
+		frnd->last = NULL;
+	}
+}
+
+static void buf_send_end(int err, void *user_data)
+{
+	struct bt_mesh_friend *frnd = user_data;
+
+	BT_DBG("err %d", err);
+
+	if (frnd->pending_req) {
+		BT_WARN("Another request before previous completed sending");
+		return;
+	}
+
+	if (frnd->established) {
+		k_delayed_work_submit(&frnd->timer, K_MSEC(frnd->poll_to));
+		BT_DBG("Waiting %u ms for next poll", frnd->poll_to);
+	} else {
+		/* Friend offer timeout is 1 second */
+		k_delayed_work_submit(&frnd->timer, K_SECONDS(1));
+		BT_DBG("Waiting for first poll");
+	}
+}
+
+static void update_overwrite(struct net_buf *buf, uint8_t md)
+{
+	struct net_buf_simple_state state;
+	struct bt_mesh_ctl_friend_update *upd;
+
+	if (buf->len != 16) {
+		return;
+	}
+
+	net_buf_simple_save(&buf->b, &state);
+
+	net_buf_skip(buf, 1); /* skip IVI, NID */
+
+	if (!(net_buf_pull_u8(buf) >> 7)) {
+		goto end;
+	}
+
+	net_buf_skip(buf, 7); /* skip seqnum src dec*/
+
+	if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1))
+			!= TRANS_CTL_OP_FRIEND_UPDATE) {
+		goto end;
+	}
+
+	upd = net_buf_pull_mem(buf, sizeof(*upd));
+	BT_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md);
+	upd->md = md;
+
+end:
+	net_buf_simple_restore(&buf->b, &state);
+}
+
+static void friend_timeout(struct k_work *work)
+{
+	struct bt_mesh_friend *frnd = CONTAINER_OF(work, struct bt_mesh_friend,
+						   timer.work);
+	static const struct bt_mesh_send_cb buf_sent_cb = {
+		.start = buf_send_start,
+		.end = buf_send_end,
+	};
+
+	uint8_t md;
+
+	__ASSERT_NO_MSG(frnd->pending_buf == 0U);
+
+	BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
+	       frnd->send_last, frnd->last);
+
+	if (frnd->send_last && frnd->last) {
+		BT_DBG("Sending frnd->last %p", frnd->last);
+		frnd->send_last = 0U;
+		goto send_last;
+	}
+
+	if (frnd->established && !frnd->pending_req) {
+		BT_WARN("Friendship lost with 0x%04x", frnd->lpn);
+		friend_clear(frnd);
+		return;
+	}
+
+	frnd->last = (void *)sys_slist_get(&frnd->queue);
+	if (!frnd->last) {
+		BT_WARN("Friendship not established with 0x%04x",
+			frnd->lpn);
+		friend_clear(frnd);
+		return;
+	}
+
+	md = (uint8_t)(sys_slist_peek_head(&frnd->queue) != NULL);
+
+	update_overwrite(frnd->last, md);
+
+	if (encrypt_friend_pdu(frnd, frnd->last, false)) {
+		return;
+	}
+
+	/* Clear the flag we use for segment tracking */
+	frnd->last->flags &= ~NET_BUF_FRAGS;
+	frnd->last->frags = NULL;
+
+	BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
+	       frnd->last, frnd->lpn);
+	frnd->queue_size--;
+
+send_last:
+	frnd->pending_req = 0U;
+	frnd->pending_buf = 1U;
+	bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
+}
+
+int bt_mesh_friend_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+		int j;
+
+		frnd->net_idx = BT_MESH_KEY_UNUSED;
+
+		sys_slist_init(&frnd->queue);
+
+		k_delayed_work_init(&frnd->timer, friend_timeout);
+		k_delayed_work_init(&frnd->clear.timer, clear_timeout);
+
+		for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
+			sys_slist_init(&frnd->seg[j].queue);
+		}
+	}
+
+	return 0;
+}
+
+static bool is_segack(struct net_buf *buf, const uint64_t *seqauth, uint16_t src)
+{
+	struct net_buf_simple_state state;
+	bool found = false;
+
+	if (buf->len != 16) {
+		return false;
+	}
+
+	net_buf_simple_save(&buf->b, &state);
+
+	net_buf_skip(buf, 1); /* skip IVI, NID */
+
+	if (!(net_buf_pull_u8(buf) >> 7)) {
+		goto end;
+	}
+
+	net_buf_pull(buf, 3); /* skip SEQNUM */
+
+	if (src != net_buf_pull_be16(buf)) {
+		goto end;
+	}
+
+	net_buf_skip(buf, 2); /* skip dst */
+
+	if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
+		goto end;
+	}
+
+	found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) ==
+		(*seqauth & TRANS_SEQ_ZERO_MASK);
+end:
+	net_buf_simple_restore(&buf->b, &state);
+	return found;
+}
+
+static void friend_purge_old_ack(struct bt_mesh_friend *frnd,
+				 const uint64_t *seq_auth, uint16_t src)
+{
+	sys_snode_t *cur, *prev = NULL;
+
+	BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src);
+
+	for (cur = sys_slist_peek_head(&frnd->queue);
+	     cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) {
+		struct net_buf *buf = (void *)cur;
+
+		if (is_segack(buf, seq_auth, src)) {
+			BT_DBG("Removing old ack from Friend Queue");
+
+			sys_slist_remove(&frnd->queue, prev, cur);
+			frnd->queue_size--;
+			/* Make sure old slist entry state doesn't remain */
+			buf->frags = NULL;
+
+			net_buf_unref(buf);
+			break;
+		}
+	}
+}
+
+static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
+				  struct bt_mesh_net_rx *rx,
+				  enum bt_mesh_friend_pdu_type type,
+				  const uint64_t *seq_auth, uint8_t seg_count,
+				  struct net_buf_simple *sbuf)
+{
+	struct friend_pdu_info info;
+	struct net_buf *buf;
+
+	/* Because of network loopback, tx packets will also be passed into
+	 * this rx function. These packets have already been added to the
+	 * queue, and should be ignored.
+	 */
+	if (bt_mesh_elem_find(rx->ctx.addr)) {
+		return;
+	}
+
+	BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
+
+	if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
+		friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr);
+	}
+
+	info.src = rx->ctx.addr;
+	info.dst = rx->ctx.recv_dst;
+
+	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+		info.ttl = rx->ctx.recv_ttl;
+	} else {
+		info.ttl = rx->ctx.recv_ttl - 1U;
+	}
+
+	info.ctl = rx->ctl;
+
+	sys_put_be24(rx->seq, info.seq);
+
+	info.iv_index = BT_MESH_NET_IVI_RX(rx);
+
+	buf = create_friend_pdu(frnd, &info, sbuf);
+	if (!buf) {
+		BT_ERR("Failed to encode Friend buffer");
+		return;
+	}
+
+	enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
+
+	BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
+	       frnd->lpn, frnd->queue_size);
+}
+
+static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
+				  struct bt_mesh_net_tx *tx,
+				  enum bt_mesh_friend_pdu_type type,
+				  const uint64_t *seq_auth, uint8_t seg_count,
+				  struct net_buf_simple *sbuf)
+{
+	struct friend_pdu_info info;
+	struct net_buf *buf;
+
+	BT_DBG("LPN 0x%04x", frnd->lpn);
+
+	if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) {
+		friend_purge_old_ack(frnd, seq_auth, tx->src);
+	}
+
+	info.src = tx->src;
+	info.dst = tx->ctx->addr;
+
+	info.ttl = tx->ctx->send_ttl;
+	info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
+
+	sys_put_be24(bt_mesh.seq, info.seq);
+
+	info.iv_index = BT_MESH_NET_IVI_TX;
+
+	buf = create_friend_pdu(frnd, &info, sbuf);
+	if (!buf) {
+		BT_ERR("Failed to encode Friend buffer");
+		return;
+	}
+
+	if (type == BT_MESH_FRIEND_PDU_SINGLE && !info.ctl) {
+		/* Unsegmented application packets may be reencrypted later,
+		 * as they depend on the the sequence number being the same
+		 * when encrypting in transport and network.
+		 */
+		FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx;
+	}
+
+	enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
+
+	BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
+}
+
+static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx,
+			       uint16_t addr)
+{
+	int i;
+
+	if (!frnd->established) {
+		return false;
+	}
+
+	if (net_idx != frnd->net_idx) {
+		return false;
+	}
+
+	if (BT_MESH_ADDR_IS_UNICAST(addr)) {
+		return is_lpn_unicast(frnd, addr);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) {
+		if (frnd->sub_list[i] == addr) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (friend_lpn_matches(frnd, net_idx, addr)) {
+			BT_DBG("LPN 0x%04x matched address 0x%04x",
+			       frnd->lpn, addr);
+			return true;
+		}
+	}
+
+	BT_DBG("No matching LPN for address 0x%04x", addr);
+
+	return false;
+}
+
+static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr,
+				   const uint64_t *seq_auth, uint8_t seg_count)
+{
+	uint32_t total = 0;
+	int i;
+
+	if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) {
+		return false;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
+		struct bt_mesh_friend_seg *seg = &frnd->seg[i];
+
+		if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
+			/* If there's a segment queue for this message then the
+			 * space verification has already happened.
+			 */
+			return true;
+		}
+
+		total += seg->seg_count;
+	}
+
+	/* If currently pending segments combined with this segmented message
+	 * are more than the Friend Queue Size, then there's no space. This
+	 * is because we don't have a mechanism of aborting already pending
+	 * segmented messages to free up buffers.
+	 */
+	return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
+}
+
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+				    uint64_t *seq_auth, uint8_t seg_count)
+{
+	bool someone_has_space = false, friend_match = false;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (!friend_lpn_matches(frnd, net_idx, dst)) {
+			continue;
+		}
+
+		friend_match = true;
+
+		if (friend_queue_has_space(frnd, src, seq_auth, seg_count)) {
+			someone_has_space = true;
+		}
+	}
+
+	/* If there were no matched LPNs treat this as success, so the
+	 * transport layer can continue its work.
+	 */
+	if (!friend_match) {
+		return true;
+	}
+
+	/* From the transport layers perspective it's good enough that at
+	 * least one Friend Queue has space. If there were multiple Friend
+	 * matches then the destination must be a group address, in which
+	 * case e.g. segment acks are not sent.
+	 */
+	return someone_has_space;
+}
+
+static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr,
+				       const uint64_t *seq_auth, uint8_t seg_count)
+{
+	bool pending_segments;
+	uint8_t avail_space;
+
+	if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
+		return false;
+	}
+
+	avail_space = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - frnd->queue_size;
+	pending_segments = false;
+
+	while (pending_segments || avail_space < seg_count) {
+		struct net_buf *buf = (void *)sys_slist_get(&frnd->queue);
+
+		if (!buf) {
+			BT_ERR("Unable to free up enough buffers");
+			return false;
+		}
+
+		frnd->queue_size--;
+		avail_space++;
+
+		pending_segments = (buf->flags & NET_BUF_FRAGS);
+
+		/* Make sure old slist entry state doesn't remain */
+		buf->frags = NULL;
+		buf->flags &= ~NET_BUF_FRAGS;
+
+		net_buf_unref(buf);
+	}
+
+	return true;
+}
+
+void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
+			       enum bt_mesh_friend_pdu_type type,
+			       const uint64_t *seq_auth, uint8_t seg_count,
+			       struct net_buf_simple *sbuf)
+{
+	int i;
+
+	if (!rx->friend_match ||
+	    (rx->ctx.recv_ttl <= 1U && rx->net_if != BT_MESH_NET_IF_LOCAL) ||
+	    bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
+		return;
+	}
+
+	BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x",
+	       rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr,
+	       rx->ctx.recv_dst);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (!friend_lpn_matches(frnd, rx->sub->net_idx,
+					rx->ctx.recv_dst)) {
+			continue;
+		}
+
+		if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth,
+						seg_count)) {
+			continue;
+		}
+
+		friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count,
+				      sbuf);
+	}
+}
+
+bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
+			       enum bt_mesh_friend_pdu_type type,
+			       const uint64_t *seq_auth, uint8_t seg_count,
+			       struct net_buf_simple *sbuf)
+{
+	bool matched = false;
+	int i;
+
+	if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) ||
+	    bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) {
+		return matched;
+	}
+
+	BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx,
+	       tx->ctx->addr, tx->src);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+		if (!friend_lpn_matches(frnd, tx->sub->net_idx,
+					tx->ctx->addr)) {
+			continue;
+		}
+
+		if (!friend_queue_prepare_space(frnd, tx->src, seq_auth,
+						seg_count)) {
+			continue;
+		}
+
+		friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, seg_count,
+				      sbuf);
+		matched = true;
+	}
+
+	return matched;
+}
+
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+				     uint16_t dst, uint64_t *seq_auth)
+{
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+		struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+		int j;
+
+		if (!friend_lpn_matches(frnd, sub->net_idx, dst)) {
+			continue;
+		}
+
+		for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
+			struct bt_mesh_friend_seg *seg = &frnd->seg[j];
+
+			if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
+				continue;
+			}
+
+			BT_WARN("Clearing incomplete segments for 0x%04x", src);
+
+			purge_buffers(&seg->queue);
+			seg->seg_count = 0U;
+			break;
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_cli.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_cli.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_cli.c	(working copy)
@@ -0,0 +1,531 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <zephyr/types.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
+#define LOG_MODULE_NAME bt_mesh_health_cli
+#include "common/log.h"
+
+#include "net.h"
+#include "foundation.h"
+
+static int32_t msg_timeout;
+
+static struct bt_mesh_health_cli *health_cli;
+
+struct health_fault_param {
+	uint16_t   cid;
+	uint8_t   *expect_test_id;
+	uint8_t   *test_id;
+	uint8_t   *faults;
+	size_t *fault_count;
+};
+
+static void health_fault_status(struct bt_mesh_model *model,
+				struct bt_mesh_msg_ctx *ctx,
+				struct net_buf_simple *buf)
+{
+	struct health_fault_param *param;
+	uint8_t test_id;
+	uint16_t cid;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (health_cli->op_pending != OP_HEALTH_FAULT_STATUS) {
+		BT_WARN("Unexpected Health Fault Status message");
+		return;
+	}
+
+	param = health_cli->op_param;
+
+	test_id = net_buf_simple_pull_u8(buf);
+	if (param->expect_test_id && test_id != *param->expect_test_id) {
+		BT_WARN("Health fault with unexpected Test ID");
+		return;
+	}
+
+	cid = net_buf_simple_pull_le16(buf);
+	if (cid != param->cid) {
+		BT_WARN("Health fault with unexpected Company ID");
+		return;
+	}
+
+	if (param->test_id) {
+		*param->test_id = test_id;
+	}
+
+	if (buf->len > *param->fault_count) {
+		BT_WARN("Got more faults than there's space for");
+	} else {
+		*param->fault_count = buf->len;
+	}
+
+	memcpy(param->faults, buf->data, *param->fault_count);
+
+	k_sem_give(&health_cli->op_sync);
+}
+
+static void health_current_status(struct bt_mesh_model *model,
+				  struct bt_mesh_msg_ctx *ctx,
+				  struct net_buf_simple *buf)
+{
+	struct bt_mesh_health_cli *cli = model->user_data;
+	uint8_t test_id;
+	uint16_t cid;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	test_id = net_buf_simple_pull_u8(buf);
+	cid = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("Test ID 0x%02x Company ID 0x%04x Fault Count %u",
+	       test_id, cid, buf->len);
+
+	if (!cli->current_status) {
+		BT_WARN("No Current Status callback available");
+		return;
+	}
+
+	cli->current_status(cli, ctx->addr, test_id, cid, buf->data, buf->len);
+}
+
+struct health_period_param {
+	uint8_t *divisor;
+};
+
+static void health_period_status(struct bt_mesh_model *model,
+				 struct bt_mesh_msg_ctx *ctx,
+				 struct net_buf_simple *buf)
+{
+	struct health_period_param *param;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (health_cli->op_pending != OP_HEALTH_PERIOD_STATUS) {
+		BT_WARN("Unexpected Health Period Status message");
+		return;
+	}
+
+	param = health_cli->op_param;
+
+	*param->divisor = net_buf_simple_pull_u8(buf);
+
+	k_sem_give(&health_cli->op_sync);
+}
+
+struct health_attention_param {
+	uint8_t *attention;
+};
+
+static void health_attention_status(struct bt_mesh_model *model,
+				    struct bt_mesh_msg_ctx *ctx,
+				    struct net_buf_simple *buf)
+{
+	struct health_attention_param *param;
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+	       ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
+	       bt_hex(buf->data, buf->len));
+
+	if (health_cli->op_pending != OP_ATTENTION_STATUS) {
+		BT_WARN("Unexpected Health Attention Status message");
+		return;
+	}
+
+	param = health_cli->op_param;
+
+	if (param->attention) {
+		*param->attention = net_buf_simple_pull_u8(buf);
+	}
+
+	k_sem_give(&health_cli->op_sync);
+}
+
+const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
+	{ OP_HEALTH_FAULT_STATUS,    3,   health_fault_status },
+	{ OP_HEALTH_CURRENT_STATUS,  3,   health_current_status },
+	{ OP_HEALTH_PERIOD_STATUS,   1,   health_period_status },
+	{ OP_ATTENTION_STATUS,       1,   health_attention_status },
+	BT_MESH_MODEL_OP_END,
+};
+
+static int cli_prepare(void *param, uint32_t op)
+{
+	if (!health_cli) {
+		BT_ERR("No available Health Client context!");
+		return -EINVAL;
+	}
+
+	if (health_cli->op_pending) {
+		BT_WARN("Another synchronous operation pending");
+		return -EBUSY;
+	}
+
+	health_cli->op_param = param;
+	health_cli->op_pending = op;
+
+	return 0;
+}
+
+static void cli_reset(void)
+{
+	health_cli->op_pending = 0U;
+	health_cli->op_param = NULL;
+}
+
+static int cli_wait(void)
+{
+	int err;
+
+	err = k_sem_take(&health_cli->op_sync, SYS_TIMEOUT_MS(msg_timeout));
+
+	cli_reset();
+
+	return err;
+}
+
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_attention_param param = {
+		.attention = attention,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_ATTENTION_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_ATTENTION_GET);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+				 uint8_t *updated_attention)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_SET, 1);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_attention_param param = {
+		.attention = updated_attention,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_ATTENTION_STATUS);
+	if (err) {
+		return err;
+	}
+
+	if (updated_attention) {
+		bt_mesh_model_msg_init(&msg, OP_ATTENTION_SET);
+	} else {
+		bt_mesh_model_msg_init(&msg, OP_ATTENTION_SET_UNREL);
+	}
+
+	net_buf_simple_add_u8(&msg, attention);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!updated_attention) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_GET, 0);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_period_param param = {
+		.divisor = divisor,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEALTH_PERIOD_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_GET);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+				 uint8_t *updated_divisor)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_SET, 1);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_period_param param = {
+		.divisor = updated_divisor,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEALTH_PERIOD_STATUS);
+	if (err) {
+		return err;
+	}
+
+	if (updated_divisor) {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_SET);
+	} else {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_SET_UNREL);
+	}
+
+	net_buf_simple_add_u8(&msg, divisor);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!updated_divisor) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t test_id, uint8_t *faults,
+				 size_t *fault_count)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_TEST, 3);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_fault_param param = {
+		.cid = cid,
+		.expect_test_id = &test_id,
+		.faults = faults,
+		.fault_count = fault_count,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEALTH_FAULT_STATUS);
+	if (err) {
+		return err;
+	}
+
+	if (faults) {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_TEST);
+	} else {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_TEST_UNREL);
+	}
+
+	net_buf_simple_add_u8(&msg, test_id);
+	net_buf_simple_add_le16(&msg, cid);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!faults) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t *test_id, uint8_t *faults,
+				 size_t *fault_count)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_CLEAR, 2);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_fault_param param = {
+		.cid = cid,
+		.test_id = test_id,
+		.faults = faults,
+		.fault_count = fault_count,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEALTH_FAULT_STATUS);
+	if (err) {
+		return err;
+	}
+
+	if (test_id) {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_CLEAR);
+	} else {
+		bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_CLEAR_UNREL);
+	}
+
+	net_buf_simple_add_le16(&msg, cid);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	if (!test_id) {
+		cli_reset();
+		return 0;
+	}
+
+	return cli_wait();
+}
+
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+				 uint8_t *test_id, uint8_t *faults,
+				 size_t *fault_count)
+{
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_GET, 2);
+	struct bt_mesh_msg_ctx ctx = {
+		.app_idx = app_idx,
+		.addr = addr,
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+	};
+	struct health_fault_param param = {
+		.cid = cid,
+		.test_id = test_id,
+		.faults = faults,
+		.fault_count = fault_count,
+	};
+	int err;
+
+	err = cli_prepare(&param, OP_HEALTH_FAULT_STATUS);
+	if (err) {
+		return err;
+	}
+
+	bt_mesh_model_msg_init(&msg, OP_HEALTH_FAULT_GET);
+	net_buf_simple_add_le16(&msg, cid);
+
+	err = bt_mesh_model_send(health_cli->model, &ctx, &msg, NULL, NULL);
+	if (err) {
+		BT_ERR("model_send() failed (err %d)", err);
+		cli_reset();
+		return err;
+	}
+
+	return cli_wait();
+}
+
+int32_t bt_mesh_health_cli_timeout_get(void)
+{
+	return msg_timeout;
+}
+
+void bt_mesh_health_cli_timeout_set(int32_t timeout)
+{
+	msg_timeout = timeout;
+}
+
+int bt_mesh_health_cli_set(struct bt_mesh_model *model)
+{
+	if (!model->user_data) {
+		BT_ERR("No Health Client context for given model");
+		return -EINVAL;
+	}
+
+	health_cli = model->user_data;
+	msg_timeout = 2 * MSEC_PER_SEC;
+
+	return 0;
+}
+
+static int health_cli_init(struct bt_mesh_model *model)
+{
+	struct bt_mesh_health_cli *cli = model->user_data;
+
+	BT_DBG("primary %u", bt_mesh_model_in_primary(model));
+
+	if (!cli) {
+		BT_ERR("No Health Client context provided");
+		return -EINVAL;
+	}
+
+	cli = model->user_data;
+	cli->model = model;
+
+	k_sem_init(&cli->op_sync, 0, 1);
+
+	/* Set the default health client pointer */
+	if (!health_cli) {
+		health_cli = cli;
+	}
+
+	return 0;
+}
+
+const struct bt_mesh_model_cb bt_mesh_health_cli_cb = {
+	.init = health_cli_init,
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_srv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_srv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/health_srv.c	(working copy)
@@ -0,0 +1,447 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_MODEL)
+#define LOG_MODULE_NAME bt_mesh_health_srv
+#include "common/log.h"
+
+#include "mesh.h"
+#include "adv.h"
+#include "net.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+
+#define HEALTH_TEST_STANDARD 0x00
+
+/* Health Server context of the primary element */
+struct bt_mesh_health_srv *health_srv;
+
+static void health_get_registered(struct bt_mesh_model *mod,
+				  uint16_t company_id,
+				  struct net_buf_simple *msg)
+{
+	struct bt_mesh_health_srv *srv = mod->user_data;
+	uint8_t *test_id;
+
+	BT_DBG("Company ID 0x%04x", company_id);
+
+	bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS);
+
+	test_id = net_buf_simple_add(msg, 1);
+	net_buf_simple_add_le16(msg, company_id);
+
+	if (srv->cb && srv->cb->fault_get_reg) {
+		uint8_t fault_count = net_buf_simple_tailroom(msg) - 4;
+		int err;
+
+		err = srv->cb->fault_get_reg(mod, company_id, test_id,
+					     net_buf_simple_tail(msg),
+					     &fault_count);
+		if (err) {
+			BT_ERR("Failed to get faults (err %d)", err);
+			*test_id = HEALTH_TEST_STANDARD;
+		} else {
+			net_buf_simple_add(msg, fault_count);
+		}
+	} else {
+		BT_WARN("No callback for getting faults");
+		*test_id = HEALTH_TEST_STANDARD;
+	}
+}
+
+static size_t health_get_current(struct bt_mesh_model *mod,
+				 struct net_buf_simple *msg)
+{
+	struct bt_mesh_health_srv *srv = mod->user_data;
+	const struct bt_mesh_comp *comp;
+	uint8_t *test_id, *company_ptr;
+	uint16_t company_id;
+	uint8_t fault_count;
+	int err;
+
+	bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
+
+	test_id = net_buf_simple_add(msg, 1);
+	company_ptr = net_buf_simple_add(msg, sizeof(company_id));
+	comp = bt_mesh_comp_get();
+
+	if (srv->cb && srv->cb->fault_get_cur) {
+		fault_count = net_buf_simple_tailroom(msg);
+		err = srv->cb->fault_get_cur(mod, test_id, &company_id,
+					     net_buf_simple_tail(msg),
+					     &fault_count);
+		if (err) {
+			BT_ERR("Failed to get faults (err %d)", err);
+			sys_put_le16(comp->cid, company_ptr);
+			*test_id = HEALTH_TEST_STANDARD;
+			fault_count = 0U;
+		} else {
+			sys_put_le16(company_id, company_ptr);
+			net_buf_simple_add(msg, fault_count);
+		}
+	} else {
+		BT_WARN("No callback for getting faults");
+		sys_put_le16(comp->cid, company_ptr);
+		*test_id = HEALTH_TEST_STANDARD;
+		fault_count = 0U;
+	}
+
+	return fault_count;
+}
+
+static void health_fault_get(struct bt_mesh_model *model,
+			     struct bt_mesh_msg_ctx *ctx,
+			     struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	uint16_t company_id;
+
+	company_id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("company_id 0x%04x", company_id);
+
+	health_get_registered(model, company_id, &sdu);
+
+	if (bt_mesh_model_send(model, ctx, &sdu, NULL, NULL)) {
+		BT_ERR("Unable to send Health Current Status response");
+	}
+}
+
+static void health_fault_clear_unrel(struct bt_mesh_model *model,
+				     struct bt_mesh_msg_ctx *ctx,
+				     struct net_buf_simple *buf)
+{
+	struct bt_mesh_health_srv *srv = model->user_data;
+	uint16_t company_id;
+
+	company_id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("company_id 0x%04x", company_id);
+
+	if (srv->cb && srv->cb->fault_clear) {
+		srv->cb->fault_clear(model, company_id);
+	}
+}
+
+static void health_fault_clear(struct bt_mesh_model *model,
+			       struct bt_mesh_msg_ctx *ctx,
+			       struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	struct bt_mesh_health_srv *srv = model->user_data;
+	uint16_t company_id;
+
+	company_id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("company_id 0x%04x", company_id);
+
+	if (srv->cb && srv->cb->fault_clear) {
+		srv->cb->fault_clear(model, company_id);
+	}
+
+	health_get_registered(model, company_id, &sdu);
+
+	if (bt_mesh_model_send(model, ctx, &sdu, NULL, NULL)) {
+		BT_ERR("Unable to send Health Current Status response");
+	}
+}
+
+static void health_fault_test_unrel(struct bt_mesh_model *model,
+				    struct bt_mesh_msg_ctx *ctx,
+				    struct net_buf_simple *buf)
+{
+	struct bt_mesh_health_srv *srv = model->user_data;
+	uint16_t company_id;
+	uint8_t test_id;
+
+	test_id = net_buf_simple_pull_u8(buf);
+	company_id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
+
+	if (srv->cb && srv->cb->fault_test) {
+		srv->cb->fault_test(model, test_id, company_id);
+	}
+}
+
+static void health_fault_test(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_TX_SDU_MAX);
+	struct bt_mesh_health_srv *srv = model->user_data;
+	uint16_t company_id;
+	uint8_t test_id;
+
+	BT_DBG("");
+
+	test_id = net_buf_simple_pull_u8(buf);
+	company_id = net_buf_simple_pull_le16(buf);
+
+	BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
+
+	if (srv->cb && srv->cb->fault_test) {
+		int err;
+
+		err = srv->cb->fault_test(model, test_id, company_id);
+		if (err) {
+			BT_WARN("Running fault test failed with err %d", err);
+			return;
+		}
+	}
+
+	health_get_registered(model, company_id, &sdu);
+
+	if (bt_mesh_model_send(model, ctx, &sdu, NULL, NULL)) {
+		BT_ERR("Unable to send Health Current Status response");
+	}
+}
+
+static void send_attention_status(struct bt_mesh_model *model,
+				  struct bt_mesh_msg_ctx *ctx)
+{
+	/* Needed size: opcode (2 bytes) + msg + MIC */
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_STATUS, 1);
+	struct bt_mesh_health_srv *srv = model->user_data;
+	uint8_t time;
+
+	time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
+	BT_DBG("%u second%s", time, (time == 1U) ? "" : "s");
+
+	bt_mesh_model_msg_init(&msg, OP_ATTENTION_STATUS);
+
+	net_buf_simple_add_u8(&msg, time);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Attention Status");
+	}
+}
+
+static void attention_get(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	BT_DBG("");
+
+	send_attention_status(model, ctx);
+}
+
+static void attention_set_unrel(struct bt_mesh_model *model,
+				struct bt_mesh_msg_ctx *ctx,
+				struct net_buf_simple *buf)
+{
+	uint8_t time;
+
+	time = net_buf_simple_pull_u8(buf);
+
+	BT_DBG("%u second%s", time, (time == 1U) ? "" : "s");
+
+	bt_mesh_attention(model, time);
+}
+
+static void attention_set(struct bt_mesh_model *model,
+			  struct bt_mesh_msg_ctx *ctx,
+			  struct net_buf_simple *buf)
+{
+	BT_DBG("");
+
+	attention_set_unrel(model, ctx, buf);
+
+	send_attention_status(model, ctx);
+}
+
+static void send_health_period_status(struct bt_mesh_model *model,
+				      struct bt_mesh_msg_ctx *ctx)
+{
+	/* Needed size: opcode (2 bytes) + msg + MIC */
+	BT_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_STATUS, 1);
+
+	bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS);
+
+	net_buf_simple_add_u8(&msg, model->pub->period_div);
+
+	if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
+		BT_ERR("Unable to send Health Period Status");
+	}
+}
+
+static void health_period_get(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_DBG("");
+
+	send_health_period_status(model, ctx);
+}
+
+static void health_period_set_unrel(struct bt_mesh_model *model,
+				    struct bt_mesh_msg_ctx *ctx,
+				    struct net_buf_simple *buf)
+{
+	uint8_t period;
+
+	period = net_buf_simple_pull_u8(buf);
+	if (period > 15) {
+		BT_WARN("Prohibited period value %u", period);
+		return;
+	}
+
+	BT_DBG("period %u", period);
+
+	model->pub->period_div = period;
+}
+
+static void health_period_set(struct bt_mesh_model *model,
+			      struct bt_mesh_msg_ctx *ctx,
+			      struct net_buf_simple *buf)
+{
+	BT_DBG("");
+
+	health_period_set_unrel(model, ctx, buf);
+
+	send_health_period_status(model, ctx);
+}
+
+const struct bt_mesh_model_op bt_mesh_health_srv_op[] = {
+	{ OP_HEALTH_FAULT_GET,         2,   health_fault_get },
+	{ OP_HEALTH_FAULT_CLEAR,       2,   health_fault_clear },
+	{ OP_HEALTH_FAULT_CLEAR_UNREL, 2,   health_fault_clear_unrel },
+	{ OP_HEALTH_FAULT_TEST,        3,   health_fault_test },
+	{ OP_HEALTH_FAULT_TEST_UNREL,  3,   health_fault_test_unrel },
+	{ OP_HEALTH_PERIOD_GET,        0,   health_period_get },
+	{ OP_HEALTH_PERIOD_SET,        1,   health_period_set },
+	{ OP_HEALTH_PERIOD_SET_UNREL,  1,   health_period_set_unrel },
+	{ OP_ATTENTION_GET,            0,   attention_get },
+	{ OP_ATTENTION_SET,            1,   attention_set },
+	{ OP_ATTENTION_SET_UNREL,      1,   attention_set_unrel },
+	BT_MESH_MODEL_OP_END,
+};
+
+static int health_pub_update(struct bt_mesh_model *mod)
+{
+	struct bt_mesh_model_pub *pub = mod->pub;
+	size_t count;
+
+	BT_DBG("");
+
+	count = health_get_current(mod, pub->msg);
+	if (count) {
+		pub->fast_period = 1U;
+	} else {
+		pub->fast_period = 0U;
+	}
+
+	return 0;
+}
+
+int bt_mesh_fault_update(struct bt_mesh_elem *elem)
+{
+	struct bt_mesh_model *mod;
+
+	mod = bt_mesh_model_find(elem, BT_MESH_MODEL_ID_HEALTH_SRV);
+	if (!mod) {
+		return -EINVAL;
+	}
+
+	/* Let periodic publishing, if enabled, take care of sending the
+	 * Health Current Status.
+	 */
+	if (bt_mesh_model_pub_period_get(mod) > 0) {
+		return 0;
+	}
+
+	health_pub_update(mod);
+
+	return bt_mesh_model_publish(mod);
+}
+
+static void attention_off(struct k_work *work)
+{
+	struct bt_mesh_health_srv *srv = CONTAINER_OF(work,
+						      struct bt_mesh_health_srv,
+						      attn_timer.work);
+	BT_DBG("");
+
+	if (srv->cb && srv->cb->attn_off) {
+		srv->cb->attn_off(srv->model);
+	}
+}
+
+static int health_srv_init(struct bt_mesh_model *model)
+{
+	struct bt_mesh_health_srv *srv = model->user_data;
+
+	if (!srv) {
+		BT_ERR("No Health Server context provided");
+		return -EINVAL;
+	}
+
+	if (!model->pub) {
+		BT_ERR("Health Server has no publication support");
+		return -EINVAL;
+	}
+
+	model->pub->update = health_pub_update;
+
+	k_delayed_work_init(&srv->attn_timer, attention_off);
+
+	srv->model = model;
+
+	if (bt_mesh_model_in_primary(model)) {
+		health_srv = srv;
+	}
+
+	return 0;
+}
+
+const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
+	.init = health_srv_init,
+};
+
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time)
+{
+	struct bt_mesh_health_srv *srv;
+
+	if (!model) {
+		srv = health_srv;
+		if (!srv) {
+			BT_WARN("No Health Server available");
+			return;
+		}
+
+		model = srv->model;
+	} else {
+		srv = model->user_data;
+	}
+
+	if (time > 0) {
+		if (srv->cb && srv->cb->attn_on) {
+			srv->cb->attn_on(model);
+		}
+
+		k_delayed_work_submit(&srv->attn_timer, K_SECONDS(time));
+	} else {
+		k_delayed_work_cancel(&srv->attn_timer);
+
+		if (srv->cb && srv->cb->attn_off) {
+			srv->cb->attn_off(model);
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.h	(working copy)
@@ -0,0 +1,62 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
+			      struct net_buf_simple *buf);
+int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
+			     struct net_buf_simple *buf);
+int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
+				 struct net_buf_simple *buf);
+int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
+			       struct net_buf_simple *buf);
+
+static inline bool bt_mesh_lpn_established(void)
+{
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	return bt_mesh.lpn.established;
+#else
+	return false;
+#endif
+}
+
+static inline bool bt_mesh_lpn_match(uint16_t addr)
+{
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	if (bt_mesh_lpn_established()) {
+		return (addr == bt_mesh.lpn.frnd);
+	}
+#endif
+	return false;
+}
+
+static inline bool bt_mesh_lpn_waiting_update(void)
+{
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	return (bt_mesh.lpn.state == BT_MESH_LPN_WAIT_UPDATE);
+#else
+	return false;
+#endif
+}
+
+static inline bool bt_mesh_lpn_timer(void)
+{
+#if defined(CONFIG_BT_MESH_LPN_AUTO)
+	return (bt_mesh.lpn.state == BT_MESH_LPN_TIMER);
+#else
+	return false;
+#endif
+}
+
+void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
+
+void bt_mesh_lpn_group_add(uint16_t group);
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count);
+
+void bt_mesh_lpn_disable(bool force);
+
+int bt_mesh_lpn_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/lpn.c	(working copy)
@@ -0,0 +1,1060 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <zephyr.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_LOW_POWER)
+#define LOG_MODULE_NAME bt_mesh_lpn
+#include "common/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "transport.h"
+#include "access.h"
+#include "beacon.h"
+#include "foundation.h"
+#include "lpn.h"
+
+#if defined(CONFIG_BT_MESH_LPN_AUTO)
+#define LPN_AUTO_TIMEOUT (CONFIG_BT_MESH_LPN_AUTO_TIMEOUT * MSEC_PER_SEC)
+#else
+#define LPN_AUTO_TIMEOUT 0
+#endif
+
+#define LPN_RECV_DELAY            CONFIG_BT_MESH_LPN_RECV_DELAY
+#define SCAN_LATENCY              MIN(CONFIG_BT_MESH_LPN_SCAN_LATENCY, \
+				      LPN_RECV_DELAY)
+
+#define FRIEND_REQ_RETRY_TIMEOUT  K_SECONDS(CONFIG_BT_MESH_LPN_RETRY_TIMEOUT)
+
+#define FRIEND_REQ_WAIT           100
+#define FRIEND_REQ_SCAN           (1 * MSEC_PER_SEC)
+#define FRIEND_REQ_TIMEOUT        (FRIEND_REQ_WAIT + FRIEND_REQ_SCAN)
+
+#define POLL_RETRY_TIMEOUT        100
+
+#define REQ_RETRY_DURATION(lpn)   (LPN_RECV_DELAY + (lpn)->adv_duration + \
+				      (lpn)->recv_win + POLL_RETRY_TIMEOUT)
+
+#define POLL_TIMEOUT_INIT         (CONFIG_BT_MESH_LPN_INIT_POLL_TIMEOUT * 100)
+
+#define REQ_ATTEMPTS_MAX          6
+#define REQ_ATTEMPTS(lpn)         MIN(REQ_ATTEMPTS_MAX, \
+			  POLL_TIMEOUT_INIT / REQ_RETRY_DURATION(lpn))
+
+#define POLL_TIMEOUT_MAX(lpn)     (POLL_TIMEOUT_INIT - \
+			  (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
+
+#define CLEAR_ATTEMPTS            3
+
+#define LPN_CRITERIA ((CONFIG_BT_MESH_LPN_MIN_QUEUE_SIZE) | \
+		      (CONFIG_BT_MESH_LPN_RSSI_FACTOR << 3) | \
+		      (CONFIG_BT_MESH_LPN_RECV_WIN_FACTOR << 5))
+
+#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
+#define LPN_POLL_TO POLL_TO(CONFIG_BT_MESH_LPN_POLL_TIMEOUT)
+
+/* 2 transmissions, 20ms interval */
+#define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
+
+static void (*lpn_cb)(uint16_t friend_addr, bool established);
+
+#if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
+static const char *state2str(int state)
+{
+	switch (state) {
+	case BT_MESH_LPN_DISABLED:
+		return "disabled";
+	case BT_MESH_LPN_CLEAR:
+		return "clear";
+	case BT_MESH_LPN_TIMER:
+		return "timer";
+	case BT_MESH_LPN_ENABLED:
+		return "enabled";
+	case BT_MESH_LPN_REQ_WAIT:
+		return "req wait";
+	case BT_MESH_LPN_WAIT_OFFER:
+		return "wait offer";
+	case BT_MESH_LPN_ESTABLISHED:
+		return "established";
+	case BT_MESH_LPN_RECV_DELAY:
+		return "recv delay";
+	case BT_MESH_LPN_WAIT_UPDATE:
+		return "wait update";
+	default:
+		return "(unknown)";
+	}
+}
+#endif /* CONFIG_BT_MESH_DEBUG_LOW_POWER */
+
+static inline void lpn_set_state(int state)
+{
+#if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
+	BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state));
+#endif
+	bt_mesh.lpn.state = state;
+}
+
+static inline void group_zero(atomic_t *target)
+{
+#if CONFIG_BT_MESH_LPN_GROUPS > 32
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
+		atomic_set(&target[i], 0);
+	}
+#else
+	atomic_set(target, 0);
+#endif
+}
+
+static inline void group_set(atomic_t *target, atomic_t *source)
+{
+#if CONFIG_BT_MESH_LPN_GROUPS > 32
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
+		(void)atomic_or(&target[i], atomic_get(&source[i]));
+	}
+#else
+	(void)atomic_or(target, atomic_get(source));
+#endif
+}
+
+static inline void group_clear(atomic_t *target, atomic_t *source)
+{
+#if CONFIG_BT_MESH_LPN_GROUPS > 32
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
+		(void)atomic_and(&target[i], ~atomic_get(&source[i]));
+	}
+#else
+	(void)atomic_and(target, ~atomic_get(source));
+#endif
+}
+
+static void clear_friendship(bool force, bool disable);
+
+static void friend_clear_sent(int err, void *user_data)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	/* Scanning will enable if lpn state still enabled  */
+
+	lpn->req_attempts++;
+
+	if (err) {
+		BT_ERR("Sending Friend Request failed (err %d)", err);
+		lpn_set_state(BT_MESH_LPN_ENABLED);
+		clear_friendship(false, lpn->disable);
+		return;
+	}
+
+	lpn_set_state(BT_MESH_LPN_CLEAR);
+	k_delayed_work_submit(&lpn->timer, K_MSEC(FRIEND_REQ_TIMEOUT));
+}
+
+static const struct bt_mesh_send_cb clear_sent_cb = {
+	.end = friend_clear_sent,
+};
+
+static int send_friend_clear(void)
+{
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx     = bt_mesh.sub[0].net_idx,
+		.app_idx     = BT_MESH_KEY_UNUSED,
+		.addr        = bt_mesh.lpn.frnd,
+		.send_ttl    = 0,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = &bt_mesh.sub[0],
+		.ctx = &ctx,
+		.src = bt_mesh_primary_addr(),
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+	struct bt_mesh_ctl_friend_clear req = {
+		.lpn_addr    = sys_cpu_to_be16(tx.src),
+		.lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
+	};
+
+	BT_DBG("");
+
+	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
+				sizeof(req), &clear_sent_cb, NULL);
+}
+
+static void clear_friendship(bool force, bool disable)
+{
+	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	BT_DBG("force %u disable %u", force, disable);
+
+	if (!force && lpn->established && !lpn->clear_success &&
+	    lpn->req_attempts < CLEAR_ATTEMPTS) {
+		send_friend_clear();
+		lpn->disable = disable;
+		return;
+	}
+
+	bt_mesh_rx_reset();
+
+	k_delayed_work_cancel(&lpn->timer);
+
+	friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
+
+	if (lpn->clear_success) {
+		lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
+	} else {
+		lpn->old_friend = lpn->frnd;
+	}
+
+	if (lpn_cb && lpn->frnd != BT_MESH_ADDR_UNASSIGNED) {
+		lpn_cb(lpn->frnd, false);
+	}
+
+	lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+	lpn->fsn = 0U;
+	lpn->req_attempts = 0U;
+	lpn->recv_win = 0U;
+	lpn->queue_size = 0U;
+	lpn->disable = 0U;
+	lpn->sent_req = 0U;
+	lpn->established = 0U;
+	lpn->clear_success = 0U;
+
+	group_zero(lpn->added);
+	group_zero(lpn->pending);
+	group_zero(lpn->to_remove);
+
+	/* Set this to 1 to force group subscription when the next
+	 * Friendship is created, in case lpn->groups doesn't get
+	 * modified meanwhile.
+	 */
+	lpn->groups_changed = 1U;
+
+	if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
+		(void)bt_mesh_heartbeat_send(NULL, NULL);
+	}
+
+	if (disable) {
+		lpn_set_state(BT_MESH_LPN_DISABLED);
+		return;
+	}
+
+	lpn_set_state(BT_MESH_LPN_ENABLED);
+	k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
+}
+
+static void friend_req_sent(uint16_t duration, int err, void *user_data)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	if (err) {
+		BT_ERR("Sending Friend Request failed (err %d)", err);
+		return;
+	}
+
+	lpn->adv_duration = duration;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+		k_delayed_work_submit(&lpn->timer, K_MSEC(FRIEND_REQ_WAIT));
+		lpn_set_state(BT_MESH_LPN_REQ_WAIT);
+	} else {
+		k_delayed_work_submit(&lpn->timer,
+				      K_MSEC(duration + FRIEND_REQ_TIMEOUT));
+		lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
+	}
+}
+
+static const struct bt_mesh_send_cb friend_req_sent_cb = {
+	.start = friend_req_sent,
+};
+
+static int send_friend_req(struct bt_mesh_lpn *lpn)
+{
+	const struct bt_mesh_comp *comp = bt_mesh_comp_get();
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx  = bt_mesh.sub[0].net_idx,
+		.app_idx  = BT_MESH_KEY_UNUSED,
+		.addr     = BT_MESH_ADDR_FRIENDS,
+		.send_ttl = 0,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = &bt_mesh.sub[0],
+		.ctx = &ctx,
+		.src = bt_mesh_primary_addr(),
+		.xmit = POLL_XMIT,
+	};
+	struct bt_mesh_ctl_friend_req req = {
+		.criteria    = LPN_CRITERIA,
+		.recv_delay  = LPN_RECV_DELAY,
+		.poll_to     = LPN_POLL_TO,
+		.prev_addr   = sys_cpu_to_be16(lpn->old_friend),
+		.num_elem    = comp->elem_count,
+		.lpn_counter = sys_cpu_to_be16(lpn->counter),
+	};
+
+	BT_DBG("");
+
+	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
+				sizeof(req), &friend_req_sent_cb, NULL);
+}
+
+static void req_sent(uint16_t duration, int err, void *user_data)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+#if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
+	BT_DBG("req 0x%02x duration %u err %d state %s",
+	       lpn->sent_req, duration, err, state2str(lpn->state));
+#endif
+
+	if (err) {
+		BT_ERR("Sending request failed (err %d)", err);
+		lpn->sent_req = 0U;
+		group_zero(lpn->pending);
+		return;
+	}
+
+	lpn->req_attempts++;
+	lpn->adv_duration = duration;
+
+	if (lpn->established || IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+		lpn_set_state(BT_MESH_LPN_RECV_DELAY);
+		/* We start scanning a bit early to elimitate risk of missing
+		 * response data due to HCI and other latencies.
+		 */
+		k_delayed_work_submit(&lpn->timer,
+				      K_MSEC(LPN_RECV_DELAY - SCAN_LATENCY));
+	} else {
+		k_delayed_work_submit(&lpn->timer,
+				      K_MSEC(LPN_RECV_DELAY + duration +
+					     lpn->recv_win));
+	}
+}
+
+static const struct bt_mesh_send_cb req_sent_cb = {
+	.start = req_sent,
+};
+
+static int send_friend_poll(void)
+{
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx     = bt_mesh.sub[0].net_idx,
+		.app_idx     = BT_MESH_KEY_UNUSED,
+		.addr        = bt_mesh.lpn.frnd,
+		.send_ttl    = 0,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = &bt_mesh.sub[0],
+		.ctx = &ctx,
+		.src = bt_mesh_primary_addr(),
+		.xmit = POLL_XMIT,
+		.friend_cred = true,
+	};
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	uint8_t fsn = lpn->fsn;
+	int err;
+
+	BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
+
+	if (lpn->sent_req) {
+		if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
+			lpn->pending_poll = 1U;
+		}
+
+		return 0;
+	}
+
+	err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
+			       &req_sent_cb, NULL);
+	if (err == 0) {
+		lpn->pending_poll = 0U;
+		lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
+	}
+
+	return err;
+}
+
+void bt_mesh_lpn_disable(bool force)
+{
+	if (bt_mesh.lpn.state == BT_MESH_LPN_DISABLED) {
+		return;
+	}
+
+	clear_friendship(force, true);
+}
+
+int bt_mesh_lpn_set(bool enable)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	if (enable) {
+		if (lpn->state != BT_MESH_LPN_DISABLED) {
+			return 0;
+		}
+	} else {
+		if (lpn->state == BT_MESH_LPN_DISABLED) {
+			return 0;
+		}
+	}
+
+	if (!bt_mesh_is_provisioned()) {
+		if (enable) {
+			lpn_set_state(BT_MESH_LPN_ENABLED);
+		} else {
+			lpn_set_state(BT_MESH_LPN_DISABLED);
+		}
+
+		return 0;
+	}
+
+	if (enable) {
+		lpn_set_state(BT_MESH_LPN_ENABLED);
+
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+			bt_mesh_scan_disable();
+		}
+
+		send_friend_req(lpn);
+	} else {
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO) &&
+		    lpn->state == BT_MESH_LPN_TIMER) {
+			k_delayed_work_cancel(&lpn->timer);
+			lpn_set_state(BT_MESH_LPN_DISABLED);
+		} else {
+			bt_mesh_lpn_disable(false);
+		}
+	}
+
+	return 0;
+}
+
+static void friend_response_received(struct bt_mesh_lpn *lpn)
+{
+	BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
+
+	if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) {
+		lpn->fsn++;
+	}
+
+	k_delayed_work_cancel(&lpn->timer);
+	bt_mesh_scan_disable();
+	lpn_set_state(BT_MESH_LPN_ESTABLISHED);
+	lpn->req_attempts = 0U;
+	lpn->sent_req = 0U;
+}
+
+void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	if (lpn->state == BT_MESH_LPN_TIMER) {
+		BT_DBG("Restarting establishment timer");
+		k_delayed_work_submit(&lpn->timer, K_MSEC(LPN_AUTO_TIMEOUT));
+		return;
+	}
+
+	if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
+		BT_WARN("Unexpected message withouth a preceding Poll");
+		return;
+	}
+
+	friend_response_received(lpn);
+
+	BT_DBG("Requesting more messages from Friend");
+
+	send_friend_poll();
+}
+
+int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
+			     struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_offer *msg = (void *)buf->data;
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	struct bt_mesh_subnet *sub = rx->sub;
+	struct friend_cred *cred;
+	uint16_t frnd_counter;
+	int err;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Offer");
+		return -EINVAL;
+	}
+
+	if (lpn->state != BT_MESH_LPN_WAIT_OFFER) {
+		BT_WARN("Ignoring unexpected Friend Offer");
+		return 0;
+	}
+
+	if (!msg->recv_win) {
+		BT_WARN("Prohibited ReceiveWindow value");
+		return -EINVAL;
+	}
+
+	frnd_counter = sys_be16_to_cpu(msg->frnd_counter);
+
+	BT_DBG("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u",
+	       msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
+	       frnd_counter);
+
+	lpn->frnd = rx->ctx.addr;
+
+	cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
+	if (!cred) {
+		lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+		return -ENOMEM;
+	}
+
+	/* TODO: Add offer acceptance criteria check */
+
+	k_delayed_work_cancel(&lpn->timer);
+
+	lpn->recv_win = msg->recv_win;
+	lpn->queue_size = msg->queue_size;
+
+	err = send_friend_poll();
+	if (err) {
+		friend_cred_clear(cred);
+		lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+		lpn->recv_win = 0U;
+		lpn->queue_size = 0U;
+		return err;
+	}
+
+	lpn->counter++;
+
+	return 0;
+}
+
+int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
+				 struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->data;
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	uint16_t addr, counter;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Clear Confirm");
+		return -EINVAL;
+	}
+
+	if (lpn->state != BT_MESH_LPN_CLEAR) {
+		BT_WARN("Ignoring unexpected Friend Clear Confirm");
+		return 0;
+	}
+
+	addr = sys_be16_to_cpu(msg->lpn_addr);
+	counter = sys_be16_to_cpu(msg->lpn_counter);
+
+	BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
+
+	if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
+		BT_WARN("Invalid parameters in Friend Clear Confirm");
+		return 0;
+	}
+
+	lpn->clear_success = 1U;
+	clear_friendship(false, lpn->disable);
+
+	return 0;
+}
+
+static void lpn_group_add(uint16_t group)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	uint16_t *free_slot = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
+		if (lpn->groups[i] == group) {
+			atomic_clear_bit(lpn->to_remove, i);
+			return;
+		}
+
+		if (!free_slot && lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
+			free_slot = &lpn->groups[i];
+		}
+	}
+
+	if (!free_slot) {
+		BT_WARN("Friend Subscription List exceeded!");
+		return;
+	}
+
+	*free_slot = group;
+	lpn->groups_changed = 1U;
+}
+
+static void lpn_group_del(uint16_t group)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
+		if (lpn->groups[i] == group) {
+			if (atomic_test_bit(lpn->added, i) ||
+			    atomic_test_bit(lpn->pending, i)) {
+				atomic_set_bit(lpn->to_remove, i);
+				lpn->groups_changed = 1U;
+			} else {
+				lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
+			}
+		}
+	}
+}
+
+static inline int group_popcount(atomic_t *target)
+{
+#if CONFIG_BT_MESH_LPN_GROUPS > 32
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) {
+		count += popcount(atomic_get(&target[i]));
+	}
+#else
+	return popcount(atomic_get(target));
+#endif
+}
+
+static bool sub_update(uint8_t op)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	int added_count = group_popcount(lpn->added);
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx     = bt_mesh.sub[0].net_idx,
+		.app_idx     = BT_MESH_KEY_UNUSED,
+		.addr        = lpn->frnd,
+		.send_ttl    = 0,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = &bt_mesh.sub[0],
+		.ctx = &ctx,
+		.src = bt_mesh_primary_addr(),
+		.xmit = POLL_XMIT,
+		.friend_cred = true,
+	};
+	struct bt_mesh_ctl_friend_sub req;
+	size_t i, g;
+
+	BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req);
+
+	if (lpn->sent_req) {
+		return false;
+	}
+
+	for (i = 0, g = 0; i < ARRAY_SIZE(lpn->groups); i++) {
+		if (lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) {
+			if (atomic_test_bit(lpn->added, i)) {
+				continue;
+			}
+		} else {
+			if (!atomic_test_bit(lpn->to_remove, i)) {
+				continue;
+			}
+		}
+
+		if (added_count + g >= lpn->queue_size) {
+			BT_WARN("Friend Queue Size exceeded");
+			break;
+		}
+
+		req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]);
+		atomic_set_bit(lpn->pending, i);
+
+		if (g == ARRAY_SIZE(req.addr_list)) {
+			break;
+		}
+	}
+
+	if (g == 0) {
+		group_zero(lpn->pending);
+		return false;
+	}
+
+	req.xact = lpn->xact_next++;
+
+	if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
+			     &req_sent_cb, NULL) < 0) {
+		group_zero(lpn->pending);
+		return false;
+	}
+
+	lpn->xact_pending = req.xact;
+	lpn->sent_req = op;
+	return true;
+}
+
+static void update_timeout(struct bt_mesh_lpn *lpn)
+{
+	if (lpn->established) {
+		BT_WARN("No response from Friend during ReceiveWindow");
+		bt_mesh_scan_disable();
+		lpn_set_state(BT_MESH_LPN_ESTABLISHED);
+		k_delayed_work_submit(&lpn->timer, K_MSEC(POLL_RETRY_TIMEOUT));
+	} else {
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+			bt_mesh_scan_disable();
+		}
+
+		if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
+			BT_WARN("Retrying first Friend Poll");
+			lpn->sent_req = 0U;
+			if (send_friend_poll() == 0) {
+				return;
+			}
+		}
+
+		BT_ERR("Timed out waiting for first Friend Update");
+		clear_friendship(false, false);
+	}
+}
+
+static void lpn_timeout(struct k_work *work)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+#if defined(CONFIG_BT_MESH_DEBUG_LOW_POWER)
+	BT_DBG("state: %s", state2str(lpn->state));
+#endif
+
+	switch (lpn->state) {
+	case BT_MESH_LPN_DISABLED:
+		break;
+	case BT_MESH_LPN_CLEAR:
+		clear_friendship(false, bt_mesh.lpn.disable);
+		break;
+	case BT_MESH_LPN_TIMER:
+		BT_DBG("Starting to look for Friend nodes");
+		lpn_set_state(BT_MESH_LPN_ENABLED);
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+			bt_mesh_scan_disable();
+		}
+		__fallthrough;
+	case BT_MESH_LPN_ENABLED:
+		send_friend_req(lpn);
+		break;
+	case BT_MESH_LPN_REQ_WAIT:
+		bt_mesh_scan_enable();
+		k_delayed_work_submit(&lpn->timer, K_MSEC(lpn->adv_duration +
+							  FRIEND_REQ_SCAN));
+		lpn_set_state(BT_MESH_LPN_WAIT_OFFER);
+		break;
+	case BT_MESH_LPN_WAIT_OFFER:
+		BT_WARN("No acceptable Friend Offers received");
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+			bt_mesh_scan_disable();
+		}
+		lpn->counter++;
+		lpn_set_state(BT_MESH_LPN_ENABLED);
+		lpn->sent_req = 0U;
+		k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
+		break;
+	case BT_MESH_LPN_ESTABLISHED:
+		if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
+			uint8_t req = lpn->sent_req;
+
+			lpn->sent_req = 0U;
+
+			if (!req || req == TRANS_CTL_OP_FRIEND_POLL) {
+				send_friend_poll();
+			} else {
+				sub_update(req);
+			}
+
+			break;
+		}
+
+		BT_ERR("No response from Friend after %u retries",
+		       lpn->req_attempts);
+		lpn->req_attempts = 0U;
+		clear_friendship(false, false);
+		break;
+	case BT_MESH_LPN_RECV_DELAY:
+		k_delayed_work_submit(&lpn->timer,
+				      K_MSEC(lpn->adv_duration + SCAN_LATENCY +
+					     lpn->recv_win));
+		bt_mesh_scan_enable();
+		lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
+		break;
+	case BT_MESH_LPN_WAIT_UPDATE:
+		update_timeout(lpn);
+		break;
+	default:
+		__ASSERT(0, "Unhandled LPN state");
+		break;
+	}
+}
+
+void bt_mesh_lpn_group_add(uint16_t group)
+{
+	BT_DBG("group 0x%04x", group);
+
+	lpn_group_add(group);
+
+	if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
+		return;
+	}
+
+	sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
+}
+
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
+{
+	int i;
+
+	for (i = 0; i < group_count; i++) {
+		if (groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+			BT_DBG("group 0x%04x", groups[i]);
+			lpn_group_del(groups[i]);
+		}
+	}
+
+	if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) {
+		return;
+	}
+
+	sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
+}
+
+static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
+{
+	/* If we're waiting for segment acks keep polling at high freq */
+	if (bt_mesh_tx_in_progress()) {
+		return MIN(POLL_TIMEOUT_MAX(lpn), 1 * MSEC_PER_SEC);
+	}
+
+	if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) {
+		lpn->poll_timeout *= 2;
+		lpn->poll_timeout = MIN(lpn->poll_timeout,
+					POLL_TIMEOUT_MAX(lpn));
+	}
+
+	BT_DBG("Poll Timeout is %ums", lpn->poll_timeout);
+
+	return lpn->poll_timeout;
+}
+
+int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
+			       struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->data;
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Subscription Confirm");
+		return -EINVAL;
+	}
+
+	BT_DBG("xact 0x%02x", msg->xact);
+
+	if (!lpn->sent_req) {
+		BT_WARN("No pending subscription list message");
+		return 0;
+	}
+
+	if (msg->xact != lpn->xact_pending) {
+		BT_WARN("Transaction mismatch (0x%02x != 0x%02x)",
+			msg->xact, lpn->xact_pending);
+		return 0;
+	}
+
+	if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_ADD) {
+		group_set(lpn->added, lpn->pending);
+		group_zero(lpn->pending);
+	} else if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_REM) {
+		int i;
+
+		group_clear(lpn->added, lpn->pending);
+
+		for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
+			if (atomic_test_and_clear_bit(lpn->pending, i) &&
+			    atomic_test_and_clear_bit(lpn->to_remove, i)) {
+				lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED;
+			}
+		}
+	} else {
+		BT_WARN("Unexpected Friend Subscription Confirm");
+		return 0;
+	}
+
+	friend_response_received(lpn);
+
+	if (lpn->groups_changed) {
+		sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
+		sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
+
+		if (!lpn->sent_req) {
+			lpn->groups_changed = 0U;
+		}
+	}
+
+	if (lpn->pending_poll) {
+		send_friend_poll();
+	}
+
+	if (!lpn->sent_req) {
+		k_delayed_work_submit(&lpn->timer, K_MSEC(poll_timeout(lpn)));
+	}
+
+	return 0;
+}
+
+int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
+			      struct net_buf_simple *buf)
+{
+	struct bt_mesh_ctl_friend_update *msg = (void *)buf->data;
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+	struct bt_mesh_subnet *sub = rx->sub;
+	uint32_t iv_index;
+
+	if (buf->len < sizeof(*msg)) {
+		BT_WARN("Too short Friend Update");
+		return -EINVAL;
+	}
+
+	if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) {
+		BT_WARN("Unexpected friend update");
+		return 0;
+	}
+
+	if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !rx->new_key) {
+		BT_WARN("Ignoring Phase 2 KR Update secured using old key");
+		return 0;
+	}
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
+	    (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
+	     BT_MESH_IV_UPDATE(msg->flags))) {
+		bt_mesh_beacon_ivu_initiator(false);
+	}
+
+	if (!lpn->established) {
+		struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+
+		/* This is normally checked on the transport layer, however
+		 * in this state we're also still accepting master
+		 * credentials so we need to ensure the right ones (Friend
+		 * Credentials) were used for this message.
+		 */
+		if (!rx->friend_cred) {
+			BT_WARN("Friend Update with wrong credentials");
+			return -EINVAL;
+		}
+
+		lpn->established = 1U;
+
+		BT_INFO("Friendship established with 0x%04x", lpn->frnd);
+
+		if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
+			(void)bt_mesh_heartbeat_send(NULL, NULL);
+		}
+
+		if (lpn_cb) {
+			lpn_cb(lpn->frnd, true);
+		}
+
+		/* Set initial poll timeout */
+		lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn),
+					POLL_TIMEOUT_INIT);
+	}
+
+	friend_response_received(lpn);
+
+	iv_index = sys_be32_to_cpu(msg->iv_index);
+
+	BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags, iv_index,
+	       msg->md);
+
+	if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
+			      rx->new_key)) {
+		bt_mesh_net_beacon_update(sub);
+	}
+
+	bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
+
+	if (lpn->groups_changed) {
+		sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
+		sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
+
+		if (!lpn->sent_req) {
+			lpn->groups_changed = 0U;
+		}
+	}
+
+	if (msg->md) {
+		BT_DBG("Requesting for more messages");
+		send_friend_poll();
+	}
+
+	if (!lpn->sent_req) {
+		k_delayed_work_submit(&lpn->timer, K_MSEC(poll_timeout(lpn)));
+	}
+
+	return 0;
+}
+
+int bt_mesh_lpn_poll(void)
+{
+	if (!bt_mesh.lpn.established) {
+		return -EAGAIN;
+	}
+
+	BT_DBG("Requesting more messages");
+
+	return send_friend_poll();
+}
+
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established))
+{
+	lpn_cb = cb;
+}
+
+int bt_mesh_lpn_init(void)
+{
+	struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+	BT_DBG("");
+
+	k_delayed_work_init(&lpn->timer, lpn_timeout);
+
+	if (lpn->state == BT_MESH_LPN_ENABLED) {
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
+			bt_mesh_scan_disable();
+		} else {
+			bt_mesh_scan_enable();
+		}
+
+		send_friend_req(lpn);
+	} else {
+		bt_mesh_scan_enable();
+
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO)) {
+			BT_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT);
+			lpn_set_state(BT_MESH_LPN_TIMER);
+			k_delayed_work_submit(&lpn->timer,
+					      K_MSEC(LPN_AUTO_TIMEOUT));
+		}
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/main.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/main.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/main.c	(working copy)
@@ -0,0 +1,355 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG)
+#define LOG_MODULE_NAME bt_mesh_main
+#include "common/log.h"
+
+#include "test.h"
+#include "adv.h"
+#include "prov.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "lpn.h"
+#include "friend.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "settings.h"
+#include "mesh.h"
+
+int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
+		      uint8_t flags, uint32_t iv_index, uint16_t addr,
+		      const uint8_t dev_key[16])
+{
+	bool pb_gatt_enabled;
+	int err;
+
+	BT_INFO("Primary Element: 0x%04x", addr);
+	BT_DBG("net_idx 0x%04x flags 0x%02x iv_index 0x%04x",
+	       net_idx, flags, iv_index);
+
+	if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_VALID)) {
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+		if (bt_mesh_proxy_prov_disable(false) == 0) {
+			pb_gatt_enabled = true;
+		} else {
+			pb_gatt_enabled = false;
+		}
+	} else {
+		pb_gatt_enabled = false;
+	}
+
+	/*
+	 * FIXME:
+	 * Should net_key and iv_index be over-ridden?
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		const struct bt_mesh_comp *comp;
+		const struct bt_mesh_prov *prov;
+		struct bt_mesh_cdb_node *node;
+
+		if (!atomic_test_bit(bt_mesh_cdb.flags,
+				     BT_MESH_CDB_VALID)) {
+			BT_ERR("No valid network");
+			atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+			return -EINVAL;
+		}
+
+		comp = bt_mesh_comp_get();
+		if (comp == NULL) {
+			BT_ERR("Failed to get node composition");
+			atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+			return -EINVAL;
+		}
+
+		if (!bt_mesh_cdb_subnet_get(net_idx)) {
+			BT_ERR("No subnet with idx %d", net_idx);
+			atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+			return -ENOENT;
+		}
+
+		prov = bt_mesh_prov_get();
+		node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
+					      comp->elem_count, net_idx);
+		if (node == NULL) {
+			BT_ERR("Failed to allocate database node");
+			atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+			return -ENOMEM;
+		}
+
+		addr = node->addr;
+		iv_index = bt_mesh_cdb.iv_index;
+		memcpy(node->dev_key, dev_key, 16);
+
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_cdb_node(node);
+		}
+	}
+
+	err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
+	if (err) {
+		atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+
+		if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && pb_gatt_enabled) {
+			bt_mesh_proxy_prov_enable();
+		}
+
+		return err;
+	}
+
+	bt_mesh.seq = 0U;
+
+	bt_mesh_comp_provision(addr);
+
+	memcpy(bt_mesh.dev_key, dev_key, 16);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+	    IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+		bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing network information persistently");
+		bt_mesh_store_net();
+		bt_mesh_store_subnet(&bt_mesh.sub[0]);
+		bt_mesh_store_iv(false);
+	}
+
+	bt_mesh_start();
+
+	return 0;
+}
+
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+			  uint8_t attention_duration)
+{
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+		return -EINVAL;
+	}
+
+	if (bt_mesh_subnet_get(net_idx) == NULL) {
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
+	    IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+		return bt_mesh_pb_adv_open(uuid, net_idx, addr,
+					   attention_duration);
+	}
+
+	return -ENOTSUP;
+}
+
+void bt_mesh_reset(void)
+{
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+		return;
+	}
+
+	bt_mesh.iv_index = 0U;
+	bt_mesh.seq = 0U;
+
+	memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags));
+
+	k_delayed_work_cancel(&bt_mesh.ivu_timer);
+
+	bt_mesh_cfg_reset();
+
+	bt_mesh_rx_reset();
+	bt_mesh_tx_reset();
+
+	bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+			uint16_t group = BT_MESH_ADDR_ALL_NODES;
+
+			bt_mesh_lpn_group_del(&group, 1);
+		}
+
+		bt_mesh_lpn_disable(true);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		bt_mesh_proxy_gatt_disable();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_clear_net();
+	}
+
+	(void)memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
+
+	bt_mesh_scan_disable();
+	bt_mesh_beacon_disable();
+
+	bt_mesh_comp_unprovision();
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+		bt_mesh_prov_reset();
+	}
+}
+
+bool bt_mesh_is_provisioned(void)
+{
+	return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
+}
+
+static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+			  bool vnd, bool primary, void *user_data)
+{
+	if (mod->pub && mod->pub->update) {
+		mod->pub->count = 0U;
+		k_delayed_work_cancel(&mod->pub->timer);
+	}
+}
+
+int bt_mesh_suspend(void)
+{
+	int err;
+
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+		return -EINVAL;
+	}
+
+	if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
+		return -EALREADY;
+	}
+
+	err = bt_mesh_scan_disable();
+	if (err) {
+		atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
+		BT_WARN("Disabling scanning failed (err %d)", err);
+		return err;
+	}
+
+	bt_mesh_hb_pub_disable();
+
+	if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+		bt_mesh_beacon_disable();
+	}
+
+	bt_mesh_model_foreach(model_suspend, NULL);
+
+	return 0;
+}
+
+static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+			  bool vnd, bool primary, void *user_data)
+{
+	if (mod->pub && mod->pub->update) {
+		int32_t period_ms = bt_mesh_model_pub_period_get(mod);
+
+		if (period_ms) {
+			k_delayed_work_submit(&mod->pub->timer,
+					      K_MSEC(period_ms));
+		}
+	}
+}
+
+int bt_mesh_resume(void)
+{
+	int err;
+
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+		return -EINVAL;
+	}
+
+	if (!atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
+		return -EALREADY;
+	}
+
+	err = bt_mesh_scan_enable();
+	if (err) {
+		BT_WARN("Re-enabling scanning failed (err %d)", err);
+		atomic_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
+		return err;
+	}
+
+	if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+		bt_mesh_beacon_enable();
+	}
+
+	bt_mesh_model_foreach(model_resume, NULL);
+
+	return err;
+}
+
+int bt_mesh_init(const struct bt_mesh_prov *prov,
+		 const struct bt_mesh_comp *comp)
+{
+	int err;
+
+	err = bt_mesh_test();
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_comp_register(comp);
+	if (err) {
+		return err;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROXY)) {
+		bt_mesh_proxy_init();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+		err = bt_mesh_prov_init(prov);
+		if (err) {
+			return err;
+		}
+	}
+
+	bt_mesh_net_init();
+	bt_mesh_trans_init();
+	bt_mesh_beacon_init();
+	bt_mesh_adv_init();
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_settings_init();
+	}
+
+	return 0;
+}
+
+static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+			bool vnd, bool primary, void *user_data)
+{
+	if (mod->cb && mod->cb->start) {
+		mod->cb->start(mod);
+	}
+}
+
+int bt_mesh_start(void)
+{
+	bt_mesh_net_start();
+	bt_mesh_model_foreach(model_start, NULL);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/mesh.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/mesh.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/mesh.h	(working copy)
@@ -0,0 +1,19 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_MESH_KEY_PRIMARY 0x0000
+#define BT_MESH_KEY_ANY     0xffff
+
+#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
+#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
+#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
+#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
+
+struct bt_mesh_net;
+
+int bt_mesh_start(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.h	(working copy)
@@ -0,0 +1,381 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_MESH_NET_FLAG_KR       BIT(0)
+#define BT_MESH_NET_FLAG_IVU      BIT(1)
+
+#define BT_MESH_KR_NORMAL         0x00
+#define BT_MESH_KR_PHASE_1        0x01
+#define BT_MESH_KR_PHASE_2        0x02
+#define BT_MESH_KR_PHASE_3        0x03
+
+#define BT_MESH_IV_UPDATE(flags)   ((flags >> 1) & 0x01)
+#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
+
+/* How many hours in between updating IVU duration */
+#define BT_MESH_IVU_MIN_HOURS      96
+#define BT_MESH_IVU_HOURS          (BT_MESH_IVU_MIN_HOURS /     \
+				    CONFIG_BT_MESH_IVU_DIVIDER)
+#define BT_MESH_IVU_TIMEOUT        K_HOURS(BT_MESH_IVU_HOURS)
+
+struct bt_mesh_app_key {
+	uint16_t net_idx;
+	uint16_t app_idx;
+	bool  updated;
+	struct bt_mesh_app_keys {
+		uint8_t id;
+		uint8_t val[16];
+	} keys[2];
+};
+
+struct bt_mesh_node {
+	uint16_t addr;
+	uint16_t net_idx;
+	uint8_t  dev_key[16];
+	uint8_t  num_elem;
+};
+
+struct bt_mesh_subnet {
+	uint32_t beacon_sent;        /* Timestamp of last sent beacon */
+	uint8_t  beacons_last;       /* Number of beacons during last
+				   * observation window
+				   */
+	uint8_t  beacons_cur;        /* Number of beaconds observed during
+				   * currently ongoing window.
+				   */
+
+	uint8_t  beacon_cache[21];   /* Cached last authenticated beacon */
+
+	uint16_t net_idx;            /* NetKeyIndex */
+
+	bool  kr_flag;            /* Key Refresh Flag */
+	uint8_t  kr_phase;           /* Key Refresh Phase */
+
+	uint8_t  node_id;            /* Node Identity State */
+	uint32_t node_id_start;      /* Node Identity started timestamp */
+
+	uint8_t  auth[8];            /* Beacon Authentication Value */
+
+	struct bt_mesh_subnet_keys {
+		uint8_t net[16];       /* NetKey */
+		uint8_t nid;           /* NID */
+		uint8_t enc[16];       /* EncKey */
+		uint8_t net_id[8];     /* Network ID */
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+		uint8_t identity[16];  /* IdentityKey */
+#endif
+		uint8_t privacy[16];   /* PrivacyKey */
+		uint8_t beacon[16];    /* BeaconKey */
+	} keys[2];
+};
+
+#if defined(CONFIG_BT_MESH_FRIEND)
+#define FRIEND_SEG_RX CONFIG_BT_MESH_FRIEND_SEG_RX
+#define FRIEND_SUB_LIST_SIZE CONFIG_BT_MESH_FRIEND_SUB_LIST_SIZE
+#else
+#define FRIEND_SEG_RX 0
+#define FRIEND_SUB_LIST_SIZE 0
+#endif
+
+struct bt_mesh_friend {
+	uint16_t lpn;
+	uint8_t  recv_delay;
+	uint8_t  fsn:1,
+	      send_last:1,
+	      pending_req:1,
+	      pending_buf:1,
+	      valid:1,
+	      established:1;
+	int32_t poll_to;
+	uint8_t  num_elem;
+	uint16_t lpn_counter;
+	uint16_t counter;
+
+	uint16_t net_idx;
+
+	uint16_t sub_list[FRIEND_SUB_LIST_SIZE];
+
+	struct k_delayed_work timer;
+
+	struct bt_mesh_friend_seg {
+		sys_slist_t queue;
+
+		/* The target number of segments, i.e. not necessarily
+		 * the current number of segments, in the queue. This is
+		 * used for Friend Queue free space calculations.
+		 */
+		uint8_t        seg_count;
+	} seg[FRIEND_SEG_RX];
+
+	struct net_buf *last;
+
+	sys_slist_t queue;
+	uint32_t queue_size;
+
+	/* Friend Clear Procedure */
+	struct {
+		uint32_t start;                  /* Clear Procedure start */
+		uint16_t frnd;                   /* Previous Friend's address */
+		uint16_t repeat_sec;             /* Repeat timeout in seconds */
+		struct k_delayed_work timer;  /* Repeat timer */
+	} clear;
+};
+
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+#define LPN_GROUPS CONFIG_BT_MESH_LPN_GROUPS
+#else
+#define LPN_GROUPS 0
+#endif
+
+/* Low Power Node state */
+struct bt_mesh_lpn {
+	enum __packed {
+		BT_MESH_LPN_DISABLED,     /* LPN feature is disabled */
+		BT_MESH_LPN_CLEAR,        /* Clear in progress */
+		BT_MESH_LPN_TIMER,        /* Waiting for auto timer expiry */
+		BT_MESH_LPN_ENABLED,      /* LPN enabled, but no Friend */
+		BT_MESH_LPN_REQ_WAIT,     /* Wait before scanning for offers */
+		BT_MESH_LPN_WAIT_OFFER,   /* Friend Req sent */
+		BT_MESH_LPN_ESTABLISHED,  /* Friendship established */
+		BT_MESH_LPN_RECV_DELAY,   /* Poll sent, waiting ReceiveDelay */
+		BT_MESH_LPN_WAIT_UPDATE,  /* Waiting for Update or message */
+	} state;
+
+	/* Transaction Number (used for subscription list) */
+	uint8_t xact_next;
+	uint8_t xact_pending;
+	uint8_t sent_req;
+
+	/* Address of our Friend when we're a LPN. Unassigned if we don't
+	 * have a friend yet.
+	 */
+	uint16_t frnd;
+
+	/* Value from the friend offer */
+	uint8_t  recv_win;
+
+	uint8_t  req_attempts;     /* Number of Request attempts */
+
+	int32_t poll_timeout;
+
+	uint8_t  groups_changed:1, /* Friend Subscription List needs updating */
+	      pending_poll:1,   /* Poll to be sent after subscription */
+	      disable:1,        /* Disable LPN after clearing */
+	      fsn:1,            /* Friend Sequence Number */
+	      established:1,    /* Friendship established */
+	      clear_success:1;  /* Friend Clear Confirm received */
+
+	/* Friend Queue Size */
+	uint8_t  queue_size;
+
+	/* LPNCounter */
+	uint16_t counter;
+
+	/* Previous Friend of this LPN */
+	uint16_t old_friend;
+
+	/* Duration reported for last advertising packet */
+	uint16_t adv_duration;
+
+	/* Next LPN related action timer */
+	struct k_delayed_work timer;
+
+	/* Subscribed groups */
+	uint16_t groups[LPN_GROUPS];
+
+	/* Bit fields for tracking which groups the Friend knows about */
+	ATOMIC_DEFINE(added, LPN_GROUPS);
+	ATOMIC_DEFINE(pending, LPN_GROUPS);
+	ATOMIC_DEFINE(to_remove, LPN_GROUPS);
+};
+
+/* bt_mesh_net.flags */
+enum {
+	BT_MESH_VALID,           /* We have been provisioned */
+	BT_MESH_SUSPENDED,       /* Network is temporarily suspended */
+	BT_MESH_IVU_IN_PROGRESS, /* IV Update in Progress */
+	BT_MESH_IVU_INITIATOR,   /* IV Update initiated by us */
+	BT_MESH_IVU_TEST,        /* IV Update test mode */
+	BT_MESH_IVU_PENDING,     /* Update blocked by SDU in progress */
+
+	/* pending storage actions, must reside within first 32 flags */
+	BT_MESH_RPL_PENDING,
+	BT_MESH_KEYS_PENDING,
+	BT_MESH_NET_PENDING,
+	BT_MESH_IV_PENDING,
+	BT_MESH_SEQ_PENDING,
+	BT_MESH_HB_PUB_PENDING,
+	BT_MESH_CFG_PENDING,
+	BT_MESH_MOD_PENDING,
+	BT_MESH_VA_PENDING,
+
+	/* Don't touch - intentionally last */
+	BT_MESH_FLAG_COUNT,
+};
+
+struct bt_mesh_net {
+	uint32_t iv_index; /* Current IV Index */
+	uint32_t seq;      /* Next outgoing sequence number (24 bits) */
+
+	ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT);
+
+	/* Local network interface */
+	struct k_work local_work;
+	sys_slist_t local_queue;
+
+#if defined(CONFIG_BT_MESH_FRIEND)
+	/* Friend state, unique for each LPN that we're Friends for */
+	struct bt_mesh_friend frnd[CONFIG_BT_MESH_FRIEND_LPN_COUNT];
+#endif
+
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	struct bt_mesh_lpn lpn;  /* Low Power Node state */
+#endif
+
+	/* Number of hours in current IV Update state */
+	uint8_t  ivu_duration;
+
+	/* Timer to track duration in current IV Update state */
+	struct k_delayed_work ivu_timer;
+
+	uint8_t dev_key[16];
+
+	struct bt_mesh_app_key app_keys[CONFIG_BT_MESH_APP_KEY_COUNT];
+
+	struct bt_mesh_subnet sub[CONFIG_BT_MESH_SUBNET_COUNT];
+};
+
+/* Network interface */
+enum bt_mesh_net_if {
+	BT_MESH_NET_IF_ADV,
+	BT_MESH_NET_IF_LOCAL,
+	BT_MESH_NET_IF_PROXY,
+	BT_MESH_NET_IF_PROXY_CFG,
+};
+
+/* Decoding context for Network/Transport data */
+struct bt_mesh_net_rx {
+	struct bt_mesh_subnet *sub;
+	struct bt_mesh_msg_ctx ctx;
+	uint32_t  seq;            /* Sequence Number */
+	uint8_t   old_iv:1,       /* iv_index - 1 was used */
+	       new_key:1,      /* Data was encrypted with updated key */
+	       friend_cred:1,  /* Data was encrypted with friend cred */
+	       ctl:1,          /* Network Control */
+	       net_if:2,       /* Network interface */
+	       local_match:1,  /* Matched a local element */
+	       friend_match:1; /* Matched an LPN we're friends for */
+	uint16_t  msg_cache_idx;  /* Index of entry in message cache */
+};
+
+/* Encoding context for Network/Transport data */
+struct bt_mesh_net_tx {
+	struct bt_mesh_subnet *sub;
+	struct bt_mesh_msg_ctx *ctx;
+	uint16_t src;
+	uint8_t  xmit;
+	uint8_t  friend_cred:1,
+	      aszmic:1,
+	      aid:6;
+};
+
+extern struct bt_mesh_net bt_mesh;
+
+#define BT_MESH_NET_IVI_TX (bt_mesh.iv_index - \
+			    atomic_test_bit(bt_mesh.flags, \
+					    BT_MESH_IVU_IN_PROGRESS))
+#define BT_MESH_NET_IVI_RX(rx) (bt_mesh.iv_index - (rx)->old_iv)
+
+#define BT_MESH_NET_HDR_LEN 9
+
+int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
+			    const uint8_t key[16]);
+
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+		       uint32_t iv_index);
+
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
+
+bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key);
+
+void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
+
+int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
+
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
+
+void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
+
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx);
+
+struct bt_mesh_subnet *bt_mesh_subnet_find(const uint8_t net_id[8], uint8_t flags,
+					   uint32_t iv_index, const uint8_t auth[8],
+					   bool *new_key);
+
+int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
+		       bool proxy);
+
+int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
+		     const struct bt_mesh_send_cb *cb, void *cb_data);
+
+int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
+		       struct bt_mesh_net_rx *rx, struct net_buf_simple *buf);
+
+void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
+		      enum bt_mesh_net_if net_if);
+
+void bt_mesh_net_loopback_clear(uint16_t net_idx);
+
+uint32_t bt_mesh_next_seq(void);
+
+void bt_mesh_net_start(void);
+
+void bt_mesh_net_init(void);
+void bt_mesh_net_header_parse(struct net_buf_simple *buf,
+			      struct bt_mesh_net_rx *rx);
+
+/* Friendship Credential Management */
+struct friend_cred {
+	uint16_t net_idx;
+	uint16_t addr;
+
+	uint16_t lpn_counter;
+	uint16_t frnd_counter;
+
+	struct {
+		uint8_t nid;         /* NID */
+		uint8_t enc[16];     /* EncKey */
+		uint8_t privacy[16]; /* PrivacyKey */
+	} cred[2];
+};
+
+int friend_cred_get(struct bt_mesh_subnet *sub, uint16_t addr, uint8_t *nid,
+			    const uint8_t **enc, const uint8_t **priv);
+int friend_cred_set(struct friend_cred *cred, uint8_t idx, const uint8_t net_key[16]);
+void friend_cred_refresh(uint16_t net_idx);
+int friend_cred_update(struct bt_mesh_subnet *sub);
+struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, uint16_t addr,
+				       uint16_t lpn_counter, uint16_t frnd_counter);
+void friend_cred_clear(struct friend_cred *cred);
+int friend_cred_del(uint16_t net_idx, uint16_t addr);
+
+static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
+				    void *cb_data)
+{
+	if (!cb) {
+		return;
+	}
+
+	if (cb->start) {
+		cb->start(0, 0, cb_data);
+	}
+
+	if (cb->end) {
+		cb->end(0, cb_data);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/net.c	(working copy)
@@ -0,0 +1,1432 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_NET)
+#define LOG_MODULE_NAME bt_mesh_net
+#include "common/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "lpn.h"
+#include "friend.h"
+#include "proxy.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "beacon.h"
+#include "settings.h"
+#include "prov.h"
+
+/* Minimum valid Mesh Network PDU length. The Network headers
+ * themselves take up 9 bytes. After that there is a minimum of 1 byte
+ * payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1
+ * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least
+ * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes.
+ */
+#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8)
+
+#define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16)
+#define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *)
+#define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf))
+
+/* Seq limit after IV Update is triggered */
+#define IV_UPDATE_SEQ_LIMIT 8000000
+
+#define IVI(pdu)           ((pdu)[0] >> 7)
+#define NID(pdu)           ((pdu)[0] & 0x7f)
+#define CTL(pdu)           ((pdu)[1] >> 7)
+#define TTL(pdu)           ((pdu)[1] & 0x7f)
+#define SEQ(pdu)           (sys_get_be24(&pdu[2]))
+#define SRC(pdu)           (sys_get_be16(&(pdu)[5]))
+#define DST(pdu)           (sys_get_be16(&(pdu)[7]))
+
+/* Determine how many friendship credentials we need */
+#if defined(CONFIG_BT_MESH_FRIEND)
+#define FRIEND_CRED_COUNT CONFIG_BT_MESH_FRIEND_LPN_COUNT
+#elif defined(CONFIG_BT_MESH_LOW_POWER)
+#define FRIEND_CRED_COUNT CONFIG_BT_MESH_SUBNET_COUNT
+#else
+#define FRIEND_CRED_COUNT 0
+#endif
+
+static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
+
+static struct {
+	uint32_t src : 15, /* MSb of source is always 0 */
+	      seq : 17;
+} msg_cache[CONFIG_BT_MESH_MSG_CACHE_SIZE];
+static uint16_t msg_cache_next;
+
+/* Singleton network context (the implementation only supports one) */
+struct bt_mesh_net bt_mesh = {
+	.local_queue = SYS_SLIST_STATIC_INIT(&bt_mesh.local_queue),
+	.sub = {
+		[0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+			.net_idx = BT_MESH_KEY_UNUSED,
+		}
+	},
+	.app_keys = {
+		[0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
+			.net_idx = BT_MESH_KEY_UNUSED,
+		}
+	},
+};
+
+NET_BUF_POOL_DEFINE(loopback_buf_pool, CONFIG_BT_MESH_LOOPBACK_BUFS,
+		    LOOPBACK_MAX_PDU_LEN, LOOPBACK_USER_DATA_SIZE, NULL);
+
+static uint32_t dup_cache[CONFIG_BT_MESH_MSG_CACHE_SIZE];
+static int   dup_cache_next;
+
+static bool check_dup(struct net_buf_simple *data)
+{
+	const uint8_t *tail = net_buf_simple_tail(data);
+	uint32_t val;
+	int i;
+
+	val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8);
+
+	for (i = 0; i < ARRAY_SIZE(dup_cache); i++) {
+		if (dup_cache[i] == val) {
+			return true;
+		}
+	}
+
+	dup_cache[dup_cache_next++] = val;
+	dup_cache_next %= ARRAY_SIZE(dup_cache);
+
+	return false;
+}
+
+static bool msg_cache_match(struct net_buf_simple *pdu)
+{
+	uint16_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(msg_cache); i++) {
+		if (msg_cache[i].src == SRC(pdu->data) &&
+		    msg_cache[i].seq == (SEQ(pdu->data) & BIT_MASK(17))) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void msg_cache_add(struct bt_mesh_net_rx *rx)
+{
+	rx->msg_cache_idx = msg_cache_next++;
+	msg_cache[rx->msg_cache_idx].src = rx->ctx.addr;
+	msg_cache[rx->msg_cache_idx].seq = rx->seq;
+	msg_cache_next %= ARRAY_SIZE(msg_cache);
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
+{
+	int i;
+
+	if (net_idx == BT_MESH_KEY_ANY) {
+		return &bt_mesh.sub[0];
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		if (bt_mesh.sub[i].net_idx == net_idx) {
+			return &bt_mesh.sub[i];
+		}
+	}
+
+	return NULL;
+}
+
+int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
+			    const uint8_t key[16])
+{
+	uint8_t p[] = { 0 };
+	uint8_t nid;
+	int err;
+
+	err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
+	if (err) {
+		BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+		return err;
+	}
+
+	memcpy(keys->net, key, 16);
+
+	keys->nid = nid;
+
+	BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
+	BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));
+
+	err = bt_mesh_k3(key, keys->net_id);
+	if (err) {
+		BT_ERR("Unable to generate Net ID");
+		return err;
+	}
+
+	BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	err = bt_mesh_identity_key(key, keys->identity);
+	if (err) {
+		BT_ERR("Unable to generate IdentityKey");
+		return err;
+	}
+
+	BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
+#endif /* GATT_PROXY */
+
+	err = bt_mesh_beacon_key(key, keys->beacon);
+	if (err) {
+		BT_ERR("Unable to generate beacon key");
+		return err;
+	}
+
+	BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
+
+	return 0;
+}
+
+int friend_cred_set(struct friend_cred *cred, uint8_t idx, const uint8_t net_key[16])
+{
+	uint16_t lpn_addr, frnd_addr;
+	int err;
+	uint8_t p[9];
+
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	if (cred->addr == bt_mesh.lpn.frnd) {
+		lpn_addr = bt_mesh_primary_addr();
+		frnd_addr = cred->addr;
+	} else {
+		lpn_addr = cred->addr;
+		frnd_addr = bt_mesh_primary_addr();
+	}
+#else
+	lpn_addr = cred->addr;
+	frnd_addr = bt_mesh_primary_addr();
+#endif
+
+	BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr);
+	BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter,
+	       cred->frnd_counter);
+
+	p[0] = 0x01;
+	sys_put_be16(lpn_addr, p + 1);
+	sys_put_be16(frnd_addr, p + 3);
+	sys_put_be16(cred->lpn_counter, p + 5);
+	sys_put_be16(cred->frnd_counter, p + 7);
+
+	err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid,
+			 cred->cred[idx].enc, cred->cred[idx].privacy);
+	if (err) {
+		BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+		return err;
+	}
+
+	BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid,
+	       bt_hex(cred->cred[idx].enc, 16));
+	BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16));
+
+	return 0;
+}
+
+void friend_cred_refresh(uint16_t net_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		struct friend_cred *cred = &friend_cred[i];
+
+		if (cred->addr != BT_MESH_ADDR_UNASSIGNED &&
+		    cred->net_idx == net_idx) {
+			memcpy(&cred->cred[0], &cred->cred[1],
+			       sizeof(cred->cred[0]));
+		}
+	}
+}
+
+int friend_cred_update(struct bt_mesh_subnet *sub)
+{
+	int err, i;
+
+	BT_DBG("net_idx 0x%04x", sub->net_idx);
+
+	for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		struct friend_cred *cred = &friend_cred[i];
+
+		if (cred->addr == BT_MESH_ADDR_UNASSIGNED ||
+		    cred->net_idx != sub->net_idx) {
+			continue;
+		}
+
+		err = friend_cred_set(cred, 1, sub->keys[1].net);
+		if (err) {
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, uint16_t addr,
+				       uint16_t lpn_counter, uint16_t frnd_counter)
+{
+	struct friend_cred *cred;
+	int i, err;
+
+	BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
+
+	for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
+		    (friend_cred[i].addr == addr &&
+		     friend_cred[i].net_idx == sub->net_idx)) {
+			cred = &friend_cred[i];
+			break;
+		}
+	}
+
+	if (!cred) {
+		BT_WARN("No free friend credential slots");
+		return NULL;
+	}
+
+	cred->net_idx = sub->net_idx;
+	cred->addr = addr;
+	cred->lpn_counter = lpn_counter;
+	cred->frnd_counter = frnd_counter;
+
+	err = friend_cred_set(cred, 0, sub->keys[0].net);
+	if (err) {
+		friend_cred_clear(cred);
+		return NULL;
+	}
+
+	if (sub->kr_flag) {
+		err = friend_cred_set(cred, 1, sub->keys[1].net);
+		if (err) {
+			friend_cred_clear(cred);
+			return NULL;
+		}
+	}
+
+	return cred;
+}
+
+void friend_cred_clear(struct friend_cred *cred)
+{
+	cred->net_idx = BT_MESH_KEY_UNUSED;
+	cred->addr = BT_MESH_ADDR_UNASSIGNED;
+	cred->lpn_counter = 0U;
+	cred->frnd_counter = 0U;
+	(void)memset(cred->cred, 0, sizeof(cred->cred));
+}
+
+int friend_cred_del(uint16_t net_idx, uint16_t addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		struct friend_cred *cred = &friend_cred[i];
+
+		if (cred->addr == addr && cred->net_idx == net_idx) {
+			friend_cred_clear(cred);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+int friend_cred_get(struct bt_mesh_subnet *sub, uint16_t addr, uint8_t *nid,
+		    const uint8_t **enc, const uint8_t **priv)
+{
+	int i;
+
+	BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
+
+	for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		struct friend_cred *cred = &friend_cred[i];
+
+		if (cred->net_idx != sub->net_idx) {
+			continue;
+		}
+
+		if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) {
+			continue;
+		}
+
+		if (nid) {
+			*nid = cred->cred[sub->kr_flag].nid;
+		}
+
+		if (enc) {
+			*enc = cred->cred[sub->kr_flag].enc;
+		}
+
+		if (priv) {
+			*priv = cred->cred[sub->kr_flag].privacy;
+		}
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
+{
+	uint8_t flags = 0x00;
+
+	if (sub && sub->kr_flag) {
+		flags |= BT_MESH_NET_FLAG_KR;
+	}
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+		flags |= BT_MESH_NET_FLAG_IVU;
+	}
+
+	return flags;
+}
+
+int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub)
+{
+	uint8_t flags = bt_mesh_net_flags(sub);
+	struct bt_mesh_subnet_keys *keys;
+
+	if (sub->kr_flag) {
+		BT_DBG("NetIndex %u Using new key", sub->net_idx);
+		keys = &sub->keys[1];
+	} else {
+		BT_DBG("NetIndex %u Using current key", sub->net_idx);
+		keys = &sub->keys[0];
+	}
+
+	BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
+
+	return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
+				   bt_mesh.iv_index, sub->auth);
+}
+
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+		       uint32_t iv_index)
+{
+	struct bt_mesh_subnet *sub;
+	int err;
+
+	BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index);
+
+	BT_DBG("NetKey %s", bt_hex(key, 16));
+
+	(void)memset(msg_cache, 0, sizeof(msg_cache));
+	msg_cache_next = 0U;
+
+	sub = &bt_mesh.sub[0];
+
+	sub->kr_flag = BT_MESH_KEY_REFRESH(flags);
+	if (sub->kr_flag) {
+		err = bt_mesh_net_keys_create(&sub->keys[1], key);
+		if (err) {
+			return -EIO;
+		}
+
+		sub->kr_phase = BT_MESH_KR_PHASE_2;
+	} else {
+		err = bt_mesh_net_keys_create(&sub->keys[0], key);
+		if (err) {
+			return -EIO;
+		}
+	}
+
+	sub->net_idx = idx;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+	} else {
+		sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+	}
+
+	bt_mesh.iv_index = iv_index;
+	atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS,
+			  BT_MESH_IV_UPDATE(flags));
+
+	/* Set minimum required hours, since the 96-hour minimum requirement
+	 * doesn't apply straight after provisioning (since we can't know how
+	 * long has actually passed since the network changed its state).
+	 */
+	bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
+
+	/* Make sure we have valid beacon data to be sent */
+	bt_mesh_net_beacon_update(sub);
+
+	return 0;
+}
+
+void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub)
+{
+	int i;
+
+	BT_DBG("idx 0x%04x", sub->net_idx);
+
+	memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		BT_DBG("Storing Updated NetKey persistently");
+		bt_mesh_store_subnet(sub);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx != sub->net_idx || !key->updated) {
+			continue;
+		}
+
+		memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0]));
+		key->updated = false;
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			BT_DBG("Storing Updated AppKey persistently");
+			bt_mesh_store_app_key(key);
+		}
+	}
+}
+
+bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, uint8_t new_kr, bool new_key)
+{
+	if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) {
+		BT_WARN("KR change in normal operation. Are we blacklisted?");
+		return false;
+	}
+
+	sub->kr_flag = new_kr;
+
+	if (sub->kr_flag) {
+		if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
+			BT_DBG("Phase 1 -> Phase 2");
+			sub->kr_phase = BT_MESH_KR_PHASE_2;
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				BT_DBG("Storing krp phase persistently");
+				bt_mesh_store_subnet(sub);
+			}
+
+			return true;
+		}
+	} else {
+		switch (sub->kr_phase) {
+		case BT_MESH_KR_PHASE_1:
+			if (!new_key) {
+				/* Ignore */
+				break;
+			}
+		/* Upon receiving a Secure Network beacon with the KR flag set
+		 * to 0 using the new NetKey in Phase 1, the node shall
+		 * immediately transition to Phase 3, which effectively skips
+		 * Phase 2.
+		 *
+		 * Intentional fall-through.
+		 */
+			__fallthrough;
+		case BT_MESH_KR_PHASE_2:
+			BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase);
+			bt_mesh_net_revoke_keys(sub);
+			if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
+			    IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+				friend_cred_refresh(sub->net_idx);
+			}
+
+			sub->kr_phase = BT_MESH_KR_NORMAL;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+#if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
+void bt_mesh_iv_update_test(bool enable)
+{
+	atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_TEST, enable);
+	/* Reset the duration variable - needed for some PTS tests */
+	bt_mesh.ivu_duration = 0U;
+}
+
+bool bt_mesh_iv_update(void)
+{
+	if (!bt_mesh_is_provisioned()) {
+		BT_ERR("Not yet provisioned");
+		return false;
+	}
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+		bt_mesh_net_iv_update(bt_mesh.iv_index, false);
+	} else {
+		bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
+	}
+
+	bt_mesh_net_sec_update(NULL);
+
+	return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
+}
+#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
+
+/* Used for sending immediate beacons to Friend queues and GATT clients */
+void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
+{
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+	    bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+		bt_mesh_proxy_beacon_send(sub);
+	}
+}
+
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
+{
+	int i;
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+		/* We're currently in IV Update mode */
+
+		if (iv_index != bt_mesh.iv_index) {
+			BT_WARN("IV Index mismatch: 0x%08x != 0x%08x",
+				iv_index, bt_mesh.iv_index);
+			return false;
+		}
+
+		if (iv_update) {
+			/* Nothing to do */
+			BT_DBG("Already in IV Update in Progress state");
+			return false;
+		}
+	} else {
+		/* We're currently in Normal mode */
+
+		if (iv_index == bt_mesh.iv_index) {
+			BT_DBG("Same IV Index in normal mode");
+			return false;
+		}
+
+		if (iv_index < bt_mesh.iv_index ||
+		    iv_index > bt_mesh.iv_index + 42) {
+			BT_ERR("IV Index out of sync: 0x%08x != 0x%08x",
+			       iv_index, bt_mesh.iv_index);
+			return false;
+		}
+
+		if (iv_index > bt_mesh.iv_index + 1) {
+			BT_WARN("Performing IV Index Recovery");
+			bt_mesh_rpl_clear();
+			bt_mesh.iv_index = iv_index;
+			bt_mesh.seq = 0U;
+			goto do_update;
+		}
+
+		if (iv_index == bt_mesh.iv_index + 1 && !iv_update) {
+			BT_WARN("Ignoring new index in normal mode");
+			return false;
+		}
+
+		if (!iv_update) {
+			/* Nothing to do */
+			BT_DBG("Already in Normal state");
+			return false;
+		}
+	}
+
+	if (!(IS_ENABLED(CONFIG_BT_MESH_IV_UPDATE_TEST) &&
+	      atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST))) {
+		if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
+			BT_WARN("IV Update before minimum duration");
+			return false;
+		}
+	}
+
+	/* Defer change to Normal Operation if there are pending acks */
+	if (!iv_update && bt_mesh_tx_in_progress()) {
+		BT_WARN("IV Update deferred because of pending transfer");
+		atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_PENDING);
+		return false;
+	}
+
+do_update:
+	atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv_update);
+	bt_mesh.ivu_duration = 0U;
+
+	if (iv_update) {
+		bt_mesh.iv_index = iv_index;
+		BT_DBG("IV Update state entered. New index 0x%08x",
+		       bt_mesh.iv_index);
+
+		bt_mesh_rpl_reset();
+	} else {
+		BT_DBG("Normal mode entered");
+		bt_mesh.seq = 0U;
+	}
+
+	k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
+			bt_mesh_net_beacon_update(&bt_mesh.sub[i]);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		bt_mesh_cdb_iv_update(iv_index, iv_update);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_iv(false);
+	}
+
+	return true;
+}
+
+uint32_t bt_mesh_next_seq(void)
+{
+	uint32_t seq = bt_mesh.seq++;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_seq();
+	}
+
+	if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) &&
+	    bt_mesh.seq > IV_UPDATE_SEQ_LIMIT &&
+	    bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) {
+		bt_mesh_beacon_ivu_initiator(true);
+		bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
+		bt_mesh_net_sec_update(NULL);
+	}
+
+	return seq;
+}
+
+static void bt_mesh_net_local(struct k_work *work)
+{
+	struct net_buf *buf;
+
+	while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
+		struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+		struct bt_mesh_net_rx rx = {
+			.ctx = {
+				.net_idx = sub->net_idx,
+				/* Initialize AppIdx to a sane value */
+				.app_idx = BT_MESH_KEY_UNUSED,
+				.recv_ttl = TTL(buf->data),
+				/* TTL=1 only goes to local IF */
+				.send_ttl = 1U,
+				.addr = SRC(buf->data),
+				.recv_dst = DST(buf->data),
+				.recv_rssi = 0,
+			},
+			.net_if = BT_MESH_NET_IF_LOCAL,
+			.sub = sub,
+			.old_iv = (IVI(buf->data) != (bt_mesh.iv_index & 0x01)),
+			.ctl = CTL(buf->data),
+			.seq = SEQ(buf->data),
+			.new_key = sub->kr_flag,
+			.local_match = 1U,
+			.friend_match = 0U,
+		};
+
+		BT_DBG("src: 0x%04x dst: 0x%04x seq 0x%06x sub %p", rx.ctx.addr,
+		       rx.ctx.addr, rx.seq, sub);
+
+		(void) bt_mesh_trans_recv(&buf->b, &rx);
+		net_buf_unref(buf);
+	}
+}
+
+static void net_tx_cred_get(struct bt_mesh_net_tx *tx, uint8_t *nid,
+			    const uint8_t **enc, const uint8_t **priv)
+{
+	if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) || !tx->friend_cred) {
+		tx->friend_cred = 0U;
+		*nid = tx->sub->keys[tx->sub->kr_flag].nid;
+		*enc = tx->sub->keys[tx->sub->kr_flag].enc;
+		*priv = tx->sub->keys[tx->sub->kr_flag].privacy;
+		return;
+	}
+
+	if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED, nid, enc, priv)) {
+		BT_WARN("Falling back to master credentials");
+
+		tx->friend_cred = 0U;
+
+		*nid = tx->sub->keys[tx->sub->kr_flag].nid;
+		*enc = tx->sub->keys[tx->sub->kr_flag].enc;
+		*priv = tx->sub->keys[tx->sub->kr_flag].privacy;
+	}
+}
+
+static int net_header_encode(struct bt_mesh_net_tx *tx, uint8_t nid,
+			     struct net_buf_simple *buf)
+{
+	const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
+
+	if (ctl && net_buf_simple_tailroom(buf) < 8) {
+		BT_ERR("Insufficient MIC space for CTL PDU");
+		return -EINVAL;
+	} else if (net_buf_simple_tailroom(buf) < 4) {
+		BT_ERR("Insufficient MIC space for PDU");
+		return -EINVAL;
+	}
+
+	BT_DBG("src 0x%04x dst 0x%04x ctl %u seq 0x%06x",
+	       tx->src, tx->ctx->addr, ctl, bt_mesh.seq);
+
+	net_buf_simple_push_be16(buf, tx->ctx->addr);
+	net_buf_simple_push_be16(buf, tx->src);
+	net_buf_simple_push_be24(buf, bt_mesh_next_seq());
+
+	if (ctl) {
+		net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80);
+	} else {
+		net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
+	}
+
+	net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
+
+	return 0;
+}
+
+int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
+		       bool proxy)
+{
+	const uint8_t *enc, *priv;
+	uint8_t nid;
+	int err;
+
+	net_tx_cred_get(tx, &nid, &enc, &priv);
+
+	err = net_header_encode(tx, nid, buf);
+	if (err) {
+		return err;
+	}
+
+	err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy);
+	if (err) {
+		return err;
+	}
+
+	return bt_mesh_net_obfuscate(buf->data, BT_MESH_NET_IVI_TX, priv);
+}
+
+static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data,
+		    size_t len)
+{
+	struct net_buf *buf;
+
+	buf = net_buf_alloc(&loopback_buf_pool, K_NO_WAIT);
+	if (!buf) {
+		BT_WARN("Unable to allocate loopback");
+		return -ENOMEM;
+	}
+
+	BT_DBG("");
+
+	LOOPBACK_BUF_SUB(buf) = tx->sub;
+
+	net_buf_add_mem(buf, data, len);
+
+	net_buf_slist_put(&bt_mesh.local_queue, buf);
+
+	k_work_submit(&bt_mesh.local_work);
+
+	return 0;
+}
+
+int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
+		     const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	const uint8_t *enc, *priv;
+	uint8_t nid;
+	int err;
+
+	BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
+	       tx->src, tx->ctx->addr, buf->len, net_buf_headroom(buf),
+	       net_buf_tailroom(buf));
+	BT_DBG("Payload len %u: %s", buf->len, bt_hex(buf->data, buf->len));
+	BT_DBG("Seq 0x%06x", bt_mesh.seq);
+
+	if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+		tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+	}
+
+	net_tx_cred_get(tx, &nid, &enc, &priv);
+	err = net_header_encode(tx, nid, &buf->b);
+	if (err) {
+		goto done;
+	}
+
+	/* Deliver to local network interface if necessary */
+	if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
+	    bt_mesh_elem_find(tx->ctx->addr)) {
+		err = loopback(tx, buf->data, buf->len);
+
+		/* Local unicast messages should not go out to network */
+		if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) ||
+		    tx->ctx->send_ttl == 1U) {
+			if (!err) {
+				send_cb_finalize(cb, cb_data);
+			}
+
+			goto done;
+		}
+	}
+
+	/* Mesh spec 3.4.5.2: "The output filter of the interface connected to
+	 * advertising or GATT bearers shall drop all messages with TTL value
+	 * set to 1." If a TTL=1 packet wasn't for a local interface, it is
+	 * invalid.
+	 */
+	if (tx->ctx->send_ttl == 1U) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	err = bt_mesh_net_encrypt(enc, &buf->b, BT_MESH_NET_IVI_TX, false);
+	if (err) {
+		goto done;
+	}
+
+	err = bt_mesh_net_obfuscate(buf->data, BT_MESH_NET_IVI_TX, priv);
+	if (err) {
+		goto done;
+	}
+
+	/* Deliver to GATT Proxy Clients if necessary. */
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+	    bt_mesh_proxy_relay(&buf->b, tx->ctx->addr) &&
+	    BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
+		/* Notify completion if this only went through the Mesh Proxy */
+		send_cb_finalize(cb, cb_data);
+
+		err = 0;
+		goto done;
+	}
+
+	bt_mesh_adv_send(buf, cb, cb_data);
+
+done:
+	net_buf_unref(buf);
+	return err;
+}
+
+void bt_mesh_net_loopback_clear(uint16_t net_idx)
+{
+	sys_slist_t new_list;
+	struct net_buf *buf;
+
+	BT_DBG("0x%04x", net_idx);
+
+	sys_slist_init(&new_list);
+
+	while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
+		struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+
+		if (net_idx == BT_MESH_KEY_ANY || net_idx == sub->net_idx) {
+			BT_DBG("Dropped 0x%06x", SEQ(buf->data));
+			net_buf_unref(buf);
+		} else {
+			net_buf_slist_put(&new_list, buf);
+		}
+	}
+
+	bt_mesh.local_queue = new_list;
+}
+
+static bool auth_match(struct bt_mesh_subnet_keys *keys,
+		       const uint8_t net_id[8], uint8_t flags,
+		       uint32_t iv_index, const uint8_t auth[8])
+{
+	uint8_t net_auth[8];
+
+	if (memcmp(net_id, keys->net_id, 8)) {
+		return false;
+	}
+
+	bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index,
+			    net_auth);
+
+	if (memcmp(auth, net_auth, 8)) {
+		BT_WARN("Authentication Value %s", bt_hex(auth, 8));
+		BT_WARN(" != %s", bt_hex(net_auth, 8));
+		return false;
+	}
+
+	return true;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_find(const uint8_t net_id[8], uint8_t flags,
+					   uint32_t iv_index, const uint8_t auth[8],
+					   bool *new_key)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) {
+			*new_key = false;
+			return sub;
+		}
+
+		if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+			continue;
+		}
+
+		if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) {
+			*new_key = true;
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static int net_decrypt(struct bt_mesh_subnet *sub, const uint8_t *enc,
+		       const uint8_t *priv, const uint8_t *data,
+		       size_t data_len, struct bt_mesh_net_rx *rx,
+		       struct net_buf_simple *buf)
+{
+	BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
+	BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data), bt_mesh.iv_index);
+
+	rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01));
+
+	net_buf_simple_reset(buf);
+	memcpy(net_buf_simple_add(buf, data_len), data, data_len);
+
+	if (bt_mesh_net_obfuscate(buf->data, BT_MESH_NET_IVI_RX(rx), priv)) {
+		return -ENOENT;
+	}
+
+	rx->ctx.addr = SRC(buf->data);
+	if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) {
+		BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
+		return -EINVAL;
+	}
+
+	if (bt_mesh_elem_find(rx->ctx.addr)) {
+		BT_DBG("Dropping locally originated packet");
+		return -EBADMSG;
+	}
+
+	if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(buf)) {
+		BT_DBG("Duplicate found in Network Message Cache");
+		return -EALREADY;
+	}
+
+	BT_DBG("src 0x%04x", rx->ctx.addr);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROXY) &&
+	    rx->net_if == BT_MESH_NET_IF_PROXY_CFG) {
+		return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx),
+					   true);
+	}
+
+	return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
+}
+
+static int friend_decrypt(struct bt_mesh_subnet *sub, const uint8_t *data,
+			  size_t data_len, struct bt_mesh_net_rx *rx,
+			  struct net_buf_simple *buf)
+{
+	int i;
+
+	BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
+
+	for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
+		struct friend_cred *cred = &friend_cred[i];
+
+		if (cred->net_idx != sub->net_idx) {
+			continue;
+		}
+
+		if (NID(data) == cred->cred[0].nid &&
+		    !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy,
+				 data, data_len, rx, buf)) {
+			return 0;
+		}
+
+		if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+			continue;
+		}
+
+		if (NID(data) == cred->cred[1].nid &&
+		    !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy,
+				 data, data_len, rx, buf)) {
+			rx->new_key = 1U;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static bool net_find_and_decrypt(const uint8_t *data, size_t data_len,
+				 struct bt_mesh_net_rx *rx,
+				 struct net_buf_simple *buf)
+{
+	struct bt_mesh_subnet *sub;
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		sub = &bt_mesh.sub[i];
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
+		     IS_ENABLED(CONFIG_BT_MESH_FRIEND)) &&
+		    !friend_decrypt(sub, data, data_len, rx, buf)) {
+			rx->friend_cred = 1U;
+			rx->ctx.net_idx = sub->net_idx;
+			rx->sub = sub;
+			return true;
+		}
+
+		if (NID(data) == sub->keys[0].nid &&
+		    !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
+				 data, data_len, rx, buf)) {
+			rx->ctx.net_idx = sub->net_idx;
+			rx->sub = sub;
+			return true;
+		}
+
+		if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+			continue;
+		}
+
+		if (NID(data) == sub->keys[1].nid &&
+		    !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy,
+				 data, data_len, rx, buf)) {
+			rx->new_key = 1U;
+			rx->ctx.net_idx = sub->net_idx;
+			rx->sub = sub;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/* Relaying from advertising to the advertising bearer should only happen
+ * if the Relay state is set to enabled. Locally originated packets always
+ * get sent to the advertising bearer. If the packet came in through GATT,
+ * then we should only relay it if the GATT Proxy state is enabled.
+ */
+static bool relay_to_adv(enum bt_mesh_net_if net_if)
+{
+	switch (net_if) {
+	case BT_MESH_NET_IF_ADV:
+		return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
+	case BT_MESH_NET_IF_PROXY:
+		return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
+	default:
+		return false;
+	}
+}
+
+static void bt_mesh_net_relay(struct net_buf_simple *sbuf,
+			      struct bt_mesh_net_rx *rx)
+{
+	const uint8_t *enc, *priv;
+	struct net_buf *buf;
+	uint8_t nid, transmit;
+
+	if (rx->ctx.recv_ttl <= 1U) {
+		return;
+	}
+
+	if (rx->net_if == BT_MESH_NET_IF_ADV &&
+	    bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED &&
+	    bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) {
+		return;
+	}
+
+	BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl,
+	       rx->ctx.recv_dst);
+
+	/* The Relay Retransmit state is only applied to adv-adv relaying.
+	 * Anything else (like GATT to adv, or locally originated packets)
+	 * use the Network Transmit state.
+	 */
+	if (rx->net_if == BT_MESH_NET_IF_ADV) {
+		transmit = bt_mesh_relay_retransmit_get();
+	} else {
+		transmit = bt_mesh_net_transmit_get();
+	}
+
+	buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, transmit, K_NO_WAIT);
+	if (!buf) {
+		BT_ERR("Out of relay buffers");
+		return;
+	}
+
+	/* Leave CTL bit intact */
+	sbuf->data[1] &= 0x80;
+	sbuf->data[1] |= rx->ctx.recv_ttl - 1U;
+
+	net_buf_add_mem(buf, sbuf->data, sbuf->len);
+
+	enc = rx->sub->keys[rx->sub->kr_flag].enc;
+	priv = rx->sub->keys[rx->sub->kr_flag].privacy;
+	nid = rx->sub->keys[rx->sub->kr_flag].nid;
+
+	BT_DBG("Relaying packet. TTL is now %u", TTL(buf->data));
+
+	/* Update NID if RX or RX was with friend credentials */
+	if (rx->friend_cred) {
+		buf->data[0] &= 0x80; /* Clear everything except IVI */
+		buf->data[0] |= nid;
+	}
+
+	/* We re-encrypt and obfuscate using the received IVI rather than
+	 * the normal TX IVI (which may be different) since the transport
+	 * layer nonce includes the IVI.
+	 */
+	if (bt_mesh_net_encrypt(enc, &buf->b, BT_MESH_NET_IVI_RX(rx), false)) {
+		BT_ERR("Re-encrypting failed");
+		goto done;
+	}
+
+	if (bt_mesh_net_obfuscate(buf->data, BT_MESH_NET_IVI_RX(rx), priv)) {
+		BT_ERR("Re-obfuscating failed");
+		goto done;
+	}
+
+	/* Sending to the GATT bearer should only happen if GATT Proxy
+	 * is enabled.
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+	    bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+		if (bt_mesh_proxy_relay(&buf->b, rx->ctx.recv_dst) &&
+		    BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
+			goto done;
+		}
+	}
+
+	if (relay_to_adv(rx->net_if)) {
+		bt_mesh_adv_send(buf, NULL, NULL);
+	}
+
+done:
+	net_buf_unref(buf);
+}
+
+void bt_mesh_net_header_parse(struct net_buf_simple *buf,
+			      struct bt_mesh_net_rx *rx)
+{
+	rx->old_iv = (IVI(buf->data) != (bt_mesh.iv_index & 0x01));
+	rx->ctl = CTL(buf->data);
+	rx->ctx.recv_ttl = TTL(buf->data);
+	rx->seq = SEQ(buf->data);
+	rx->ctx.addr = SRC(buf->data);
+	rx->ctx.recv_dst = DST(buf->data);
+}
+
+int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
+		       struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
+{
+	if (data->len < BT_MESH_NET_MIN_PDU_LEN) {
+		BT_WARN("Dropping too short mesh packet (len %u)", data->len);
+		BT_WARN("%s", bt_hex(data->data, data->len));
+		return -EINVAL;
+	}
+
+	if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) {
+		return -EINVAL;
+	}
+
+	BT_DBG("%u bytes: %s", data->len, bt_hex(data->data, data->len));
+
+	rx->net_if = net_if;
+
+	if (!net_find_and_decrypt(data->data, data->len, rx, buf)) {
+		BT_DBG("Unable to find matching net for packet");
+		return -ENOENT;
+	}
+
+	/* Initialize AppIdx to a sane value */
+	rx->ctx.app_idx = BT_MESH_KEY_UNUSED;
+
+	rx->ctx.recv_ttl = TTL(buf->data);
+
+	/* Default to responding with TTL 0 for non-routed messages */
+	if (rx->ctx.recv_ttl == 0U) {
+		rx->ctx.send_ttl = 0U;
+	} else {
+		rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT;
+	}
+
+	rx->ctl = CTL(buf->data);
+	rx->seq = SEQ(buf->data);
+	rx->ctx.recv_dst = DST(buf->data);
+
+	BT_DBG("Decryption successful. Payload len %u", buf->len);
+
+	if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
+	    rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
+		BT_ERR("Destination address is unassigned; dropping packet");
+		return -EBADMSG;
+	}
+
+	BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
+	       rx->ctx.recv_ttl);
+	BT_DBG("PDU: %s", bt_hex(buf->data, buf->len));
+
+	msg_cache_add(rx);
+
+	return 0;
+}
+
+void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi,
+		      enum bt_mesh_net_if net_if)
+{
+	NET_BUF_SIMPLE_DEFINE(buf, 29);
+	struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi };
+	struct net_buf_simple_state state;
+
+	BT_DBG("rssi %d net_if %u", rssi, net_if);
+
+	if (!bt_mesh_is_provisioned()) {
+		return;
+	}
+
+	if (bt_mesh_net_decode(data, net_if, &rx, &buf)) {
+		return;
+	}
+
+	/* Save the state so the buffer can later be relayed */
+	net_buf_simple_save(&buf, &state);
+
+	rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) ||
+			  bt_mesh_elem_find(rx.ctx.recv_dst));
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+	    net_if == BT_MESH_NET_IF_PROXY) {
+		bt_mesh_proxy_addr_add(data, rx.ctx.addr);
+
+		if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_DISABLED &&
+		    !rx.local_match) {
+			BT_INFO("Proxy is disabled; ignoring message");
+			return;
+		}
+	}
+
+	/* The transport layer has indicated that it has rejected the message,
+	 * but would like to see it again if it is received in the future.
+	 * This can happen if a message is received when the device is in
+	 * Low Power mode, but the message was not encrypted with the friend
+	 * credentials. Remove it from the message cache so that we accept
+	 * it again in the future.
+	 */
+	if (bt_mesh_trans_recv(&buf, &rx) == -EAGAIN) {
+		BT_WARN("Removing rejected message from Network Message Cache");
+		msg_cache[rx.msg_cache_idx].src = BT_MESH_ADDR_UNASSIGNED;
+		/* Rewind the next index now that we're not using this entry */
+		msg_cache_next = rx.msg_cache_idx;
+	}
+
+	/* Relay if this was a group/virtual address, or if the destination
+	 * was neither a local element nor an LPN we're Friends for.
+	 */
+	if (!BT_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) ||
+	    (!rx.local_match && !rx.friend_match)) {
+		net_buf_simple_restore(&buf, &state);
+		bt_mesh_net_relay(&buf, &rx);
+	}
+}
+
+static void ivu_refresh(struct k_work *work)
+{
+	bt_mesh.ivu_duration += BT_MESH_IVU_HOURS;
+
+	BT_DBG("%s for %u hour%s",
+	       atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ?
+	       "IVU in Progress" : "IVU Normal mode",
+	       bt_mesh.ivu_duration, bt_mesh.ivu_duration == 1U ? "" : "s");
+
+	if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
+		if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+			bt_mesh_store_iv(true);
+		}
+
+		k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
+		return;
+	}
+
+	if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+		bt_mesh_beacon_ivu_initiator(true);
+		bt_mesh_net_iv_update(bt_mesh.iv_index, false);
+	} else if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_iv(true);
+	}
+}
+
+void bt_mesh_net_start(void)
+{
+	if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+		bt_mesh_beacon_enable();
+	} else {
+		bt_mesh_beacon_disable();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+	    bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
+		bt_mesh_proxy_gatt_enable();
+		bt_mesh_adv_update();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		bt_mesh_lpn_init();
+	} else {
+		bt_mesh_scan_enable();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		bt_mesh_friend_init();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+		uint16_t net_idx = bt_mesh.sub[0].net_idx;
+		uint16_t addr = bt_mesh_primary_addr();
+
+		bt_mesh_prov_complete(net_idx, addr);
+	}
+}
+
+void bt_mesh_net_init(void)
+{
+	k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh);
+
+	k_work_init(&bt_mesh.local_work, bt_mesh_net_local);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_adv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_adv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_adv.c	(working copy)
@@ -0,0 +1,887 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+#include <string.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+#include <net/buf.h>
+#include "host/testing.h"
+#include "net.h"
+#include "prov.h"
+#include "adv.h"
+#include "crypto.h"
+#include "beacon.h"
+#include "prov_bearer.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
+#define LOG_MODULE_NAME bt_mesh_pb_adv
+#include "common/log.h"
+
+#define GPCF(gpc)           (gpc & 0x03)
+#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
+#define GPC_ACK             0x01
+#define GPC_CONT(seg_id)    (((seg_id) << 2) | 0x02)
+#define GPC_CTL(op)         (((op) << 2) | 0x03)
+
+#define START_PAYLOAD_MAX 20
+#define CONT_PAYLOAD_MAX  23
+
+#define START_LAST_SEG(gpc) (gpc >> 2)
+#define CONT_SEG_INDEX(gpc) (gpc >> 2)
+
+#define BEARER_CTL(gpc) (gpc >> 2)
+#define LINK_OPEN       0x00
+#define LINK_ACK        0x01
+#define LINK_CLOSE      0x02
+
+#define XACT_SEG_DATA(_seg) (&link.rx.buf->data[20 + ((_seg - 1) * 23)])
+#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
+
+#define XACT_ID_MAX  0x7f
+#define XACT_ID_NVAL 0xff
+#define SEG_NVAL     0xff
+
+#define RETRANSMIT_TIMEOUT  K_MSEC(500)
+#define BUF_TIMEOUT         K_MSEC(400)
+#define CLOSING_TIMEOUT     (3 * MSEC_PER_SEC)
+#define TRANSACTION_TIMEOUT (30 * MSEC_PER_SEC)
+
+/* Acked messages, will do retransmissions manually, taking acks into account:
+ */
+#define RETRANSMITS_RELIABLE   0
+/* Unacked messages: */
+#define RETRANSMITS_UNRELIABLE 2
+/* PDU acks: */
+#define RETRANSMITS_ACK        2
+
+enum {
+	LINK_ACTIVE,    /* Link has been opened */
+	LINK_ACK_RECVD, /* Ack for link has been received */
+	LINK_CLOSING,   /* Link is closing down */
+	LINK_INVALID,   /* Error occurred during provisioning */
+	ACK_PENDING,    /* An acknowledgment is being sent */
+	PROVISIONER,    /* The link was opened as provisioner */
+
+	NUM_FLAGS,
+};
+
+struct pb_adv {
+	uint32_t id; /* Link ID */
+
+	ATOMIC_DEFINE(flags, NUM_FLAGS);
+
+	const struct prov_bearer_cb *cb;
+	void *cb_data;
+
+	struct {
+		uint8_t id;       /* Most recent transaction ID */
+		uint8_t seg;      /* Bit-field of unreceived segments */
+		uint8_t last_seg; /* Last segment (to check length) */
+		uint8_t fcs;      /* Expected FCS value */
+		struct net_buf_simple *buf;
+	} rx;
+
+	struct {
+		/* Start timestamp of the transaction */
+		int64_t start;
+
+		/* Transaction id */
+		uint8_t id;
+
+		/* Current ack id */
+		uint8_t pending_ack;
+
+		/* Pending outgoing buffer(s) */
+		struct net_buf *buf[3];
+
+		prov_bearer_send_complete_t cb;
+
+		void *cb_data;
+
+		/* Retransmit timer */
+		struct k_delayed_work retransmit;
+	} tx;
+
+	/* Protocol timeout */
+	struct k_delayed_work prot_timer;
+};
+
+struct prov_rx {
+	uint32_t link_id;
+	uint8_t xact_id;
+	uint8_t gpc;
+};
+
+NET_BUF_SIMPLE_DEFINE_STATIC(rx_buf, 65);
+
+static struct pb_adv link = { .rx = { .buf = &rx_buf } };
+
+static void gen_prov_ack_send(uint8_t xact_id);
+static void link_open(struct prov_rx *rx, struct net_buf_simple *buf);
+static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf);
+static void link_close(struct prov_rx *rx, struct net_buf_simple *buf);
+
+static void buf_sent(int err, void *user_data)
+{
+	if (!link.tx.buf[0]) {
+		return;
+	}
+
+	k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
+}
+
+static struct bt_mesh_send_cb buf_sent_cb = {
+	.end = buf_sent,
+};
+
+static uint8_t last_seg(uint8_t len)
+{
+	if (len <= START_PAYLOAD_MAX) {
+		return 0;
+	}
+
+	len -= START_PAYLOAD_MAX;
+
+	return 1 + (len / CONT_PAYLOAD_MAX);
+}
+
+static void free_segments(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+		struct net_buf *buf = link.tx.buf[i];
+
+		if (!buf) {
+			break;
+		}
+
+		link.tx.buf[i] = NULL;
+		/* Mark as canceled */
+		BT_MESH_ADV(buf)->busy = 0U;
+		net_buf_unref(buf);
+	}
+}
+
+static uint8_t next_transaction_id(uint8_t id)
+{
+	return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1)));
+}
+
+static void prov_clear_tx(void)
+{
+	BT_DBG("");
+
+	k_delayed_work_cancel(&link.tx.retransmit);
+
+	free_segments();
+}
+
+static void reset_adv_link(void)
+{
+	BT_DBG("");
+	prov_clear_tx();
+
+	k_delayed_work_cancel(&link.prot_timer);
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		/* Clear everything except the retransmit and protocol timer
+		 * delayed work objects.
+		 */
+		(void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit));
+		link.rx.id = XACT_ID_NVAL;
+	} else {
+		/* Accept another provisioning attempt */
+		link.id = 0;
+		atomic_clear(link.flags);
+		link.rx.id = XACT_ID_MAX;
+		link.tx.id = XACT_ID_NVAL;
+	}
+
+	link.tx.pending_ack = XACT_ID_NVAL;
+	link.rx.buf = &rx_buf;
+	net_buf_simple_reset(link.rx.buf);
+}
+
+static void close_link(enum prov_bearer_link_status reason)
+{
+	const struct prov_bearer_cb *cb = link.cb;
+	void *cb_data = link.cb_data;
+
+	reset_adv_link();
+	cb->link_closed(&pb_adv, cb_data, reason);
+}
+
+static struct net_buf *adv_buf_create(uint8_t retransmits)
+{
+	struct net_buf *buf;
+
+	buf = bt_mesh_adv_create(BT_MESH_ADV_PROV,
+				 BT_MESH_TRANSMIT(retransmits, 20),
+				 BUF_TIMEOUT);
+	if (!buf) {
+		BT_ERR("Out of provisioning buffers");
+		return NULL;
+	}
+
+	return buf;
+}
+
+static void ack_complete(uint16_t duration, int err, void *user_data)
+{
+	BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack);
+	atomic_clear_bit(link.flags, ACK_PENDING);
+}
+
+static bool ack_pending(void)
+{
+	return atomic_test_bit(link.flags, ACK_PENDING);
+}
+
+static void prov_failed(uint8_t err)
+{
+	BT_DBG("%u", err);
+	link.cb->error(&pb_adv, link.cb_data, err);
+	atomic_set_bit(link.flags, LINK_INVALID);
+}
+
+static void prov_msg_recv(void)
+{
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
+		BT_ERR("Incorrect FCS");
+		return;
+	}
+
+	gen_prov_ack_send(link.rx.id);
+
+	if (atomic_test_bit(link.flags, LINK_INVALID)) {
+		BT_WARN("Unexpected msg 0x%02x on invalidated link",
+			link.rx.buf->data[0]);
+		prov_failed(PROV_ERR_UNEXP_PDU);
+		return;
+	}
+
+	link.cb->recv(&pb_adv, link.cb_data, link.rx.buf);
+}
+
+static void protocol_timeout(struct k_work *work)
+{
+	BT_DBG("");
+
+	link.rx.seg = 0U;
+	close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+/*******************************************************************************
+ * Generic provisioning
+ ******************************************************************************/
+
+static void gen_prov_ack_send(uint8_t xact_id)
+{
+	static const struct bt_mesh_send_cb cb = {
+		.start = ack_complete,
+	};
+	const struct bt_mesh_send_cb *complete;
+	struct net_buf *buf;
+	bool pending = atomic_test_and_set_bit(link.flags, ACK_PENDING);
+
+	BT_DBG("xact_id 0x%x", xact_id);
+
+	if (pending && link.tx.pending_ack == xact_id) {
+		BT_DBG("Not sending duplicate ack");
+		return;
+	}
+
+	buf = adv_buf_create(RETRANSMITS_ACK);
+	if (!buf) {
+		atomic_clear_bit(link.flags, ACK_PENDING);
+		return;
+	}
+
+	if (pending) {
+		complete = NULL;
+	} else {
+		link.tx.pending_ack = xact_id;
+		complete = &cb;
+	}
+
+	net_buf_add_be32(buf, link.id);
+	net_buf_add_u8(buf, xact_id);
+	net_buf_add_u8(buf, GPC_ACK);
+
+	bt_mesh_adv_send(buf, complete, NULL);
+	net_buf_unref(buf);
+}
+
+static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	uint8_t seg = CONT_SEG_INDEX(rx->gpc);
+
+	BT_DBG("len %u, seg_index %u", buf->len, seg);
+
+	if (!link.rx.seg && link.rx.id == rx->xact_id) {
+		if (!ack_pending()) {
+			BT_DBG("Resending ack");
+			gen_prov_ack_send(rx->xact_id);
+		}
+
+		return;
+	}
+
+	if (!link.rx.seg &&
+	    next_transaction_id(link.rx.id) == rx->xact_id) {
+		BT_DBG("Start segment lost");
+
+		link.rx.id = rx->xact_id;
+
+		net_buf_simple_reset(link.rx.buf);
+
+		link.rx.seg = SEG_NVAL;
+		link.rx.last_seg = SEG_NVAL;
+
+		prov_clear_tx();
+	} else if (rx->xact_id != link.rx.id) {
+		BT_WARN("Data for unknown transaction (0x%x != 0x%x)",
+				rx->xact_id, link.rx.id);
+		return;
+	}
+
+	if (seg > link.rx.last_seg) {
+		BT_ERR("Invalid segment index %u", seg);
+		prov_failed(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (!(link.rx.seg & BIT(seg))) {
+		BT_DBG("Ignoring already received segment");
+		return;
+	}
+
+	memcpy(XACT_SEG_DATA(seg), buf->data, buf->len);
+	XACT_SEG_RECV(seg);
+
+	if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) {
+		uint8_t expect_len;
+
+		expect_len = (link.rx.buf->len - 20U -
+				((link.rx.last_seg - 1) * 23U));
+		if (expect_len != buf->len) {
+			BT_ERR("Incorrect last seg len: %u != %u", expect_len,
+					buf->len);
+			prov_failed(PROV_ERR_NVAL_FMT);
+			return;
+		}
+	}
+
+	if (!link.rx.seg) {
+		prov_msg_recv();
+	}
+}
+
+static void gen_prov_ack(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	BT_DBG("len %u", buf->len);
+
+	if (!link.tx.buf[0]) {
+		return;
+	}
+
+	if (rx->xact_id == link.tx.id) {
+		/* Don't clear resending of LINK_CLOSE messages */
+		if (!atomic_test_bit(link.flags, LINK_CLOSING)) {
+			prov_clear_tx();
+		}
+
+		if (link.tx.cb) {
+			link.tx.cb(0, link.tx.cb_data);
+		}
+	}
+}
+
+static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	uint8_t seg = SEG_NVAL;
+
+	if (rx->xact_id == link.rx.id) {
+		if (!link.rx.seg) {
+			if (!ack_pending()) {
+				BT_DBG("Resending ack");
+				gen_prov_ack_send(rx->xact_id);
+			}
+
+			return;
+		}
+
+		if (!(link.rx.seg & BIT(0))) {
+			BT_DBG("Ignoring duplicate segment");
+			return;
+		}
+	} else if (rx->xact_id != next_transaction_id(link.rx.id)) {
+		BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id,
+			next_transaction_id(link.rx.id));
+		return;
+	}
+
+	net_buf_simple_reset(link.rx.buf);
+	link.rx.buf->len = net_buf_simple_pull_be16(buf);
+	link.rx.id = rx->xact_id;
+	link.rx.fcs = net_buf_simple_pull_u8(buf);
+
+	BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->len,
+	       START_LAST_SEG(rx->gpc), link.rx.buf->len, link.rx.fcs);
+
+	if (link.rx.buf->len < 1) {
+		BT_ERR("Ignoring zero-length provisioning PDU");
+		prov_failed(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (link.rx.buf->len > link.rx.buf->size) {
+		BT_ERR("Too large provisioning PDU (%u bytes)",
+		       link.rx.buf->len);
+		prov_failed(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->len <= 20U) {
+		BT_ERR("Too small total length for multi-segment PDU");
+		prov_failed(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	prov_clear_tx();
+
+	link.rx.last_seg = START_LAST_SEG(rx->gpc);
+
+	if ((link.rx.seg & BIT(0)) &&
+	    (find_msb_set(~link.rx.seg) >= link.rx.last_seg)) {
+		BT_ERR("Invalid segment index %u", seg);
+		prov_failed(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (link.rx.seg) {
+		seg = link.rx.seg;
+	}
+
+	link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1);
+	memcpy(link.rx.buf->data, buf->data, buf->len);
+	XACT_SEG_RECV(0);
+
+	if (!link.rx.seg) {
+		prov_msg_recv();
+	}
+}
+
+static void gen_prov_ctl(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->len);
+
+	switch (BEARER_CTL(rx->gpc)) {
+	case LINK_OPEN:
+		link_open(rx, buf);
+		break;
+	case LINK_ACK:
+		if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
+			return;
+		}
+
+		link_ack(rx, buf);
+		break;
+	case LINK_CLOSE:
+		if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
+			return;
+		}
+
+		link_close(rx, buf);
+		break;
+	default:
+		BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
+
+		if (IS_ENABLED(CONFIG_BT_TESTING)) {
+			bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
+		}
+
+		return;
+	}
+}
+
+static const struct {
+	void (*func)(struct prov_rx *rx, struct net_buf_simple *buf);
+	bool require_link;
+	uint8_t min_len;
+} gen_prov[] = {
+	{ gen_prov_start, true, 3 },
+	{ gen_prov_ack, true, 0 },
+	{ gen_prov_cont, true, 0 },
+	{ gen_prov_ctl, false, 0 },
+};
+
+static void gen_prov_recv(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	if (buf->len < gen_prov[GPCF(rx->gpc)].min_len) {
+		BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
+		return;
+	}
+
+	if (!atomic_test_bit(link.flags, LINK_ACTIVE) &&
+	    gen_prov[GPCF(rx->gpc)].require_link) {
+		BT_DBG("Ignoring message that requires active link");
+		return;
+	}
+
+	gen_prov[GPCF(rx->gpc)].func(rx, buf);
+}
+
+/*******************************************************************************
+ * TX
+ ******************************************************************************/
+
+static void send_reliable(void)
+{
+	int i;
+
+	link.tx.start = k_uptime_get();
+
+	for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+		struct net_buf *buf = link.tx.buf[i];
+
+		if (!buf) {
+			break;
+		}
+
+		if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+			bt_mesh_adv_send(buf, NULL, NULL);
+		} else {
+			bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+		}
+	}
+}
+
+static void prov_retransmit(struct k_work *work)
+{
+	int32_t timeout_ms;
+	int i;
+
+	BT_DBG("");
+
+	if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
+		BT_WARN("Link not active");
+		return;
+	}
+
+	/*
+	 * According to mesh profile spec (5.3.1.4.3), the close message should
+	 * be restransmitted at least three times. Retransmit the LINK_CLOSE
+	 * message until CLOSING_TIMEOUT has elapsed.
+	 */
+	if (atomic_test_bit(link.flags, LINK_CLOSING)) {
+		timeout_ms = CLOSING_TIMEOUT;
+	} else {
+		timeout_ms = TRANSACTION_TIMEOUT;
+	}
+
+	if (k_uptime_get() - link.tx.start > timeout_ms) {
+		if (atomic_test_bit(link.flags, LINK_CLOSING)) {
+			close_link(PROV_BEARER_LINK_STATUS_SUCCESS);
+		} else {
+			BT_WARN("Giving up transaction");
+			close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+		}
+
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+		struct net_buf *buf = link.tx.buf[i];
+
+		if (!buf) {
+			break;
+		}
+
+		if (BT_MESH_ADV(buf)->busy) {
+			continue;
+		}
+
+		BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
+
+		if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+			bt_mesh_adv_send(buf, NULL, NULL);
+		} else {
+			bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+		}
+	}
+}
+
+static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len,
+			   bool reliable)
+{
+	struct net_buf *buf;
+
+	BT_DBG("op 0x%02x data_len %u", op, data_len);
+
+	prov_clear_tx();
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE :
+					RETRANSMITS_UNRELIABLE);
+	if (!buf) {
+		return -ENOBUFS;
+	}
+
+	net_buf_add_be32(buf, link.id);
+	/* Transaction ID, always 0 for Bearer messages */
+	net_buf_add_u8(buf, 0x00);
+	net_buf_add_u8(buf, GPC_CTL(op));
+	net_buf_add_mem(buf, data, data_len);
+
+	if (reliable) {
+		link.tx.buf[0] = buf;
+		send_reliable();
+	} else {
+		bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+		net_buf_unref(buf);
+	}
+
+	return 0;
+}
+
+static int prov_send_adv(struct net_buf_simple *msg,
+			 prov_bearer_send_complete_t cb, void *cb_data)
+{
+	struct net_buf *start, *buf;
+	uint8_t seg_len, seg_id;
+
+	prov_clear_tx();
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	start = adv_buf_create(RETRANSMITS_RELIABLE);
+	if (!start) {
+		return -ENOBUFS;
+	}
+
+	link.tx.id = next_transaction_id(link.tx.id);
+	net_buf_add_be32(start, link.id);
+	net_buf_add_u8(start, link.tx.id);
+
+	net_buf_add_u8(start, GPC_START(last_seg(msg->len)));
+	net_buf_add_be16(start, msg->len);
+	net_buf_add_u8(start, bt_mesh_fcs_calc(msg->data, msg->len));
+
+	link.tx.buf[0] = start;
+	link.tx.cb = cb;
+	link.tx.cb_data = cb_data;
+
+	BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->len);
+
+	seg_len = MIN(msg->len, START_PAYLOAD_MAX);
+	BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->data, seg_len));
+	net_buf_add_mem(start, msg->data, seg_len);
+	net_buf_simple_pull(msg, seg_len);
+
+	buf = start;
+	for (seg_id = 1U; msg->len > 0; seg_id++) {
+		if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
+			BT_ERR("Too big message");
+			free_segments();
+			return -E2BIG;
+		}
+
+		buf = adv_buf_create(RETRANSMITS_RELIABLE);
+		if (!buf) {
+			free_segments();
+			return -ENOBUFS;
+		}
+
+		link.tx.buf[seg_id] = buf;
+
+		seg_len = MIN(msg->len, CONT_PAYLOAD_MAX);
+
+		BT_DBG("seg %u len %u: %s", seg_id, seg_len,
+		       bt_hex(msg->data, seg_len));
+
+		net_buf_add_be32(buf, link.id);
+		net_buf_add_u8(buf, link.tx.id);
+		net_buf_add_u8(buf, GPC_CONT(seg_id));
+		net_buf_add_mem(buf, msg->data, seg_len);
+		net_buf_simple_pull(msg, seg_len);
+	}
+
+	send_reliable();
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Link management rx
+ ******************************************************************************/
+
+static void link_open(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	BT_DBG("len %u", buf->len);
+
+	if (buf->len < 16) {
+		BT_ERR("Too short bearer open message (len %u)", buf->len);
+		return;
+	}
+
+	if (atomic_test_bit(link.flags, LINK_ACTIVE)) {
+		/* Send another link ack if the provisioner missed the last */
+		if (link.id == rx->link_id) {
+			BT_DBG("Resending link ack");
+			bearer_ctl_send(LINK_ACK, NULL, 0, false);
+		} else {
+			BT_DBG("Ignoring bearer open: link already active");
+		}
+
+		return;
+	}
+
+	if (memcmp(buf->data, bt_mesh_prov_get()->uuid, 16)) {
+		BT_DBG("Bearer open message not for us");
+		return;
+	}
+
+	link.id = rx->link_id;
+	atomic_set_bit(link.flags, LINK_ACTIVE);
+	net_buf_simple_reset(link.rx.buf);
+
+	bearer_ctl_send(LINK_ACK, NULL, 0, false);
+
+	link.cb->link_opened(&pb_adv, link.cb_data);
+}
+
+static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	BT_DBG("len %u", buf->len);
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) {
+			return;
+		}
+
+		prov_clear_tx();
+
+		link.cb->link_opened(&pb_adv, link.cb_data);
+	}
+}
+
+static void link_close(struct prov_rx *rx, struct net_buf_simple *buf)
+{
+	BT_DBG("len %u", buf->len);
+
+	if (buf->len != 1) {
+		return;
+	}
+
+	close_link(net_buf_simple_pull_u8(buf));
+}
+
+/*******************************************************************************
+ * Higher level functionality
+ ******************************************************************************/
+
+void bt_mesh_pb_adv_recv(struct net_buf_simple *buf)
+{
+	struct prov_rx rx;
+
+	if (!link.cb) {
+		return;
+	}
+
+	if (buf->len < 6) {
+		BT_WARN("Too short provisioning packet (len %u)", buf->len);
+		return;
+	}
+
+	rx.link_id = net_buf_simple_pull_be32(buf);
+	rx.xact_id = net_buf_simple_pull_u8(buf);
+	rx.gpc = net_buf_simple_pull_u8(buf);
+
+	if (atomic_test_bit(link.flags, LINK_ACTIVE) && link.id != rx.link_id) {
+		return;
+	}
+
+	BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id);
+
+	gen_prov_recv(&rx, buf);
+}
+
+static int prov_link_open(const uint8_t uuid[16], k_timeout_t timeout,
+			  const struct prov_bearer_cb *cb, void *cb_data)
+{
+	BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+	if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
+		return -EBUSY;
+	}
+
+	atomic_set_bit(link.flags, PROVISIONER);
+
+	bt_rand(&link.id, sizeof(link.id));
+	link.tx.id = XACT_ID_MAX;
+	link.rx.id = XACT_ID_NVAL;
+	link.cb = cb;
+	link.cb_data = cb_data;
+
+	net_buf_simple_reset(link.rx.buf);
+
+	bearer_ctl_send(LINK_OPEN, uuid, 16, true);
+
+	return 0;
+}
+
+static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+	if (atomic_test_bit(link.flags, LINK_ACTIVE)) {
+		return -EBUSY;
+	}
+
+	link.rx.id = XACT_ID_MAX;
+	link.tx.id = XACT_ID_NVAL;
+	link.cb = cb;
+	link.cb_data = cb_data;
+
+	/* Make sure we're scanning for provisioning inviations */
+	bt_mesh_scan_enable();
+	/* Enable unprovisioned beacon sending */
+	bt_mesh_beacon_enable();
+
+	return 0;
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+	if (atomic_test_and_set_bit(link.flags, LINK_CLOSING)) {
+		return;
+	}
+
+	bearer_ctl_send(LINK_CLOSE, &status, 1, true);
+}
+
+void pb_adv_init(void)
+{
+	k_delayed_work_init(&link.prot_timer, protocol_timeout);
+	k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
+}
+
+void pb_adv_reset(void)
+{
+	reset_adv_link();
+}
+
+const struct prov_bearer pb_adv = {
+	.type = BT_MESH_PROV_ADV,
+	.link_open = prov_link_open,
+	.link_accept = prov_link_accept,
+	.link_close = prov_link_close,
+	.send = prov_send_adv,
+	.clear_tx = prov_clear_tx,
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_gatt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_gatt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/pb_gatt.c	(working copy)
@@ -0,0 +1,154 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <bluetooth/mesh.h>
+#include <bluetooth/conn.h>
+#include "prov.h"
+#include "net.h"
+#include "proxy.h"
+#include "adv.h"
+#include "prov_bearer.h"
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
+#define LOG_MODULE_NAME bt_mesh_pb_gatt
+#include "common/log.h"
+
+struct prov_link {
+	struct bt_conn *conn;
+	const struct prov_bearer_cb *cb;
+	void *cb_data;
+	struct net_buf_simple *rx_buf;
+	struct k_delayed_work prot_timer;
+};
+
+static struct prov_link link;
+
+static void reset_state(void)
+{
+	if (link.conn) {
+		bt_conn_unref(link.conn);
+		link.conn = NULL;
+	}
+
+	k_delayed_work_cancel(&link.prot_timer);
+
+	link.rx_buf = bt_mesh_proxy_get_buf();
+}
+
+static void link_closed(enum prov_bearer_link_status status)
+{
+	const struct prov_bearer_cb *cb = link.cb;
+	void *cb_data = link.cb_data;
+
+	reset_state();
+
+	cb->link_closed(&pb_gatt, cb_data, status);
+}
+
+static void protocol_timeout(struct k_work *work)
+{
+	BT_DBG("Protocol timeout");
+
+	link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+
+int bt_mesh_pb_gatt_recv(struct bt_conn *conn, struct net_buf_simple *buf)
+{
+	BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	if (link.conn != conn || !link.cb) {
+		BT_WARN("Data for unexpected connection");
+		return -ENOTCONN;
+	}
+
+	if (buf->len < 1) {
+		BT_WARN("Too short provisioning packet (len %u)", buf->len);
+		return -EINVAL;
+	}
+
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	link.cb->recv(&pb_gatt, link.cb_data, buf);
+
+	return 0;
+}
+
+int bt_mesh_pb_gatt_open(struct bt_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+
+	if (link.conn) {
+		return -EBUSY;
+	}
+
+	link.conn = bt_conn_ref(conn);
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	link.cb->link_opened(&pb_gatt, link.cb_data);
+
+	return 0;
+}
+
+int bt_mesh_pb_gatt_close(struct bt_conn *conn)
+{
+	BT_DBG("conn %p", conn);
+
+	if (link.conn != conn) {
+		BT_DBG("Not connected");
+		return -ENOTCONN;
+	}
+
+	link_closed(PROV_BEARER_LINK_STATUS_SUCCESS);
+
+	return 0;
+}
+
+static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+	bt_mesh_proxy_prov_enable();
+	bt_mesh_adv_update();
+
+	link.cb = cb;
+	link.cb_data = cb_data;
+
+	return 0;
+}
+
+static int buf_send(struct net_buf_simple *buf, prov_bearer_send_complete_t cb,
+		    void *cb_data)
+{
+	if (!link.conn) {
+		return -ENOTCONN;
+	}
+
+	k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+	return bt_mesh_proxy_send(link.conn, BT_MESH_PROXY_PROV, buf);
+}
+
+static void clear_tx(void)
+{
+	/* No action */
+}
+
+void pb_gatt_init(void)
+{
+	k_delayed_work_init(&link.prot_timer, protocol_timeout);
+}
+
+void pb_gatt_reset(void)
+{
+	reset_state();
+}
+
+const struct prov_bearer pb_gatt = {
+	.type = BT_MESH_PROV_GATT,
+	.link_accept = link_accept,
+	.send = buf_send,
+	.clear_tx = clear_tx,
+};
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.h	(working copy)
@@ -0,0 +1,36 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define PROV_ERR_NONE          0x00
+#define PROV_ERR_NVAL_PDU      0x01
+#define PROV_ERR_NVAL_FMT      0x02
+#define PROV_ERR_UNEXP_PDU     0x03
+#define PROV_ERR_CFM_FAILED    0x04
+#define PROV_ERR_RESOURCES     0x05
+#define PROV_ERR_DECRYPT       0x06
+#define PROV_ERR_UNEXP_ERR     0x07
+#define PROV_ERR_ADDR          0x08
+
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+			uint8_t attention_duration);
+
+void bt_mesh_pb_adv_recv(struct net_buf_simple *buf);
+
+bool bt_prov_active(void);
+
+int bt_mesh_pb_gatt_open(struct bt_conn *conn);
+int bt_mesh_pb_gatt_close(struct bt_conn *conn);
+int bt_mesh_pb_gatt_recv(struct bt_conn *conn, struct net_buf_simple *buf);
+
+const struct bt_mesh_prov *bt_mesh_prov_get(void);
+
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
+
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr);
+void bt_mesh_prov_node_added(uint16_t net_idx, uint16_t addr, uint8_t num_elem);
+void bt_mesh_prov_reset(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov.c	(working copy)
@@ -0,0 +1,1292 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+#include <bluetooth/uuid.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
+#define LOG_MODULE_NAME bt_mesh_prov
+#include "common/log.h"
+
+#include "host/ecc.h"
+#include "host/testing.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+#include "prov_bearer.h"
+
+
+#define AUTH_METHOD_NO_OOB     0x00
+#define AUTH_METHOD_STATIC     0x01
+#define AUTH_METHOD_OUTPUT     0x02
+#define AUTH_METHOD_INPUT      0x03
+
+#define OUTPUT_OOB_BLINK       0x00
+#define OUTPUT_OOB_BEEP        0x01
+#define OUTPUT_OOB_VIBRATE     0x02
+#define OUTPUT_OOB_NUMBER      0x03
+#define OUTPUT_OOB_STRING      0x04
+
+#define INPUT_OOB_PUSH         0x00
+#define INPUT_OOB_TWIST        0x01
+#define INPUT_OOB_NUMBER       0x02
+#define INPUT_OOB_STRING       0x03
+
+#define PUB_KEY_NO_OOB         0x00
+#define PUB_KEY_OOB            0x01
+
+#define PROV_INVITE            0x00
+#define PROV_CAPABILITIES      0x01
+#define PROV_START             0x02
+#define PROV_PUB_KEY           0x03
+#define PROV_INPUT_COMPLETE    0x04
+#define PROV_CONFIRM           0x05
+#define PROV_RANDOM            0x06
+#define PROV_DATA              0x07
+#define PROV_COMPLETE          0x08
+#define PROV_FAILED            0x09
+
+#define PROV_NO_PDU            0xff
+
+#define PROV_ALG_P256          0x00
+
+enum {
+	WAIT_PUB_KEY,           /* Waiting for local PubKey to be generated */
+	LINK_ACTIVE,            /* Link has been opened */
+	WAIT_NUMBER,            /* Waiting for number input from user */
+	WAIT_STRING,            /* Waiting for string input from user */
+	NOTIFY_INPUT_COMPLETE,  /* Notify that input has been completed. */
+	PROVISIONER,            /* The link was opened as provisioner */
+	PUB_KEY_SENT,           /* Public key has been sent */
+	INPUT_COMPLETE,         /* Device input completed */
+
+	NUM_FLAGS,
+};
+
+struct provisioner_link {
+	struct bt_mesh_cdb_node *node;
+	uint16_t addr;
+	uint16_t net_idx;
+	uint8_t  attention_duration;
+	uint8_t  uuid[16];
+};
+
+struct prov_link {
+	ATOMIC_DEFINE(flags, NUM_FLAGS);
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	struct provisioner_link provisioner;
+#endif
+
+	uint8_t  dhkey[32];         /* Calculated DHKey */
+	uint8_t  expect;            /* Next expected PDU */
+
+	uint8_t  oob_method;
+	uint8_t  oob_action;
+	uint8_t  oob_size;
+
+	uint8_t  conf[16];          /* Remote Confirmation */
+	uint8_t  rand[16];          /* Local Random */
+	uint8_t  auth[16];          /* Authentication Value */
+
+	uint8_t  conf_salt[16];     /* ConfirmationSalt */
+	uint8_t  conf_key[16];      /* ConfirmationKey */
+	uint8_t  conf_inputs[145];  /* ConfirmationInputs */
+	uint8_t  prov_salt[16];     /* Provisioning Salt */
+
+	const struct prov_bearer *bearer;
+};
+
+#define PROV_BUF(name, len) \
+	NET_BUF_SIMPLE_DEFINE(name, PROV_BEARER_BUF_HEADROOM + len)
+
+static struct prov_link link;
+
+static const struct bt_mesh_prov *prov;
+
+static void send_pub_key(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+	static struct bt_pub_key_cb pub_key_cb = {
+		.func = pub_key_ready,
+	};
+	int err;
+
+	/* Disable Attention Timer if it was set */
+	if (link.conf_inputs[0]) {
+		bt_mesh_attention(NULL, 0);
+	}
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	if (link.provisioner.node != NULL) {
+		bt_mesh_cdb_node_del(link.provisioner.node, false);
+	}
+#endif
+
+	memset(&link, 0, sizeof(link));
+
+	err = bt_pub_key_gen(&pub_key_cb);
+	if (err) {
+		BT_ERR("Failed to generate public key (%d)", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static inline int prov_send(struct net_buf_simple *buf,
+			    prov_bearer_send_complete_t cb)
+{
+	return link.bearer->send(buf, cb, NULL);
+}
+
+static void prov_buf_init(struct net_buf_simple *buf, uint8_t type)
+{
+	net_buf_simple_reserve(buf, PROV_BEARER_BUF_HEADROOM);
+	net_buf_simple_add_u8(buf, type);
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+	BT_DBG("%u", status);
+	link.expect = PROV_NO_PDU;
+
+	link.bearer->link_close(status);
+}
+
+static void prov_send_fail_msg(uint8_t err)
+{
+	PROV_BUF(buf, 2);
+
+	BT_DBG("%u", err);
+
+	link.expect = PROV_NO_PDU;
+
+	prov_buf_init(&buf, PROV_FAILED);
+	net_buf_simple_add_u8(&buf, err);
+
+	if (prov_send(&buf, NULL)) {
+		BT_ERR("Failed to send Provisioning Failed message");
+	}
+}
+
+static void prov_fail(uint8_t reason)
+{
+	/* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+	 * provisioner just closes the link when something fails, while the
+	 * provisionee sends the fail message, and waits for the provisioner to
+	 * close the link.
+	 */
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		prov_link_close(PROV_BEARER_LINK_STATUS_FAIL);
+	} else {
+		prov_send_fail_msg(reason);
+	}
+}
+
+static void prov_invite(const uint8_t *data)
+{
+	PROV_BUF(buf, 12);
+
+	BT_DBG("Attention Duration: %u seconds", data[0]);
+
+	if (data[0]) {
+		bt_mesh_attention(NULL, data[0]);
+	}
+
+	link.conf_inputs[0] = data[0];
+
+	prov_buf_init(&buf, PROV_CAPABILITIES);
+
+	/* Number of Elements supported */
+	net_buf_simple_add_u8(&buf, bt_mesh_elem_count());
+
+	/* Supported algorithms - FIPS P-256 Eliptic Curve */
+	net_buf_simple_add_be16(&buf, BIT(PROV_ALG_P256));
+
+	/* Public Key Type, Only "No OOB" Public Key is supported */
+	net_buf_simple_add_u8(&buf, PUB_KEY_NO_OOB);
+
+	/* Static OOB Type */
+	net_buf_simple_add_u8(&buf, prov->static_val ? BIT(0) : 0x00);
+
+	/* Output OOB Size */
+	net_buf_simple_add_u8(&buf, prov->output_size);
+
+	/* Output OOB Action */
+	net_buf_simple_add_be16(&buf, prov->output_actions);
+
+	/* Input OOB Size */
+	net_buf_simple_add_u8(&buf, prov->input_size);
+
+	/* Input OOB Action */
+	net_buf_simple_add_be16(&buf, prov->input_actions);
+
+	memcpy(&link.conf_inputs[1], &buf.data[1], 11);
+
+	if (prov_send(&buf, NULL)) {
+		BT_ERR("Failed to send capabilities");
+		return;
+	}
+
+	link.expect = PROV_START;
+}
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+static void start_sent(int err, void *cb_data);
+
+static void send_invite(void)
+{
+	PROV_BUF(inv, 2);
+
+	BT_DBG("");
+
+	prov_buf_init(&inv, PROV_INVITE);
+	net_buf_simple_add_u8(&inv, link.provisioner.attention_duration);
+
+	link.conf_inputs[0] = link.provisioner.attention_duration;
+
+	if (prov_send(&inv, NULL)) {
+		BT_ERR("Failed to send invite");
+		return;
+	}
+
+	link.expect = PROV_CAPABILITIES;
+}
+
+static void send_start(void)
+{
+	PROV_BUF(start, 6);
+
+	BT_DBG("");
+
+	prov_buf_init(&start, PROV_START);
+
+	net_buf_simple_add_u8(&start, PROV_ALG_P256);
+	net_buf_simple_add_u8(&start, PUB_KEY_NO_OOB);
+	net_buf_simple_add_u8(&start, AUTH_METHOD_NO_OOB);
+	memset(link.auth, 0, sizeof(link.auth));
+
+	net_buf_simple_add_u8(&start, 0); /* Auth Action */
+	net_buf_simple_add_u8(&start, 0); /* Auth Size */
+
+	memcpy(&link.conf_inputs[12], &start.data[1], 5);
+
+	if (prov_send(&start, start_sent)) {
+		BT_ERR("Failed to send start");
+	}
+}
+
+static void start_sent(int err, void *cb_data)
+{
+	if (!bt_pub_key_get()) {
+		atomic_set_bit(link.flags, WAIT_PUB_KEY);
+		BT_WARN("Waiting for local public key");
+	} else {
+		send_pub_key();
+	}
+}
+#endif
+
+static void prov_capabilities(const uint8_t *data)
+{
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	uint16_t algorithms, output_action, input_action;
+
+	BT_DBG("Elements: %u", data[0]);
+
+	algorithms = sys_get_be16(&data[1]);
+	BT_DBG("Algorithms:        %u", algorithms);
+
+	BT_DBG("Public Key Type:   0x%02x", data[3]);
+	BT_DBG("Static OOB Type:   0x%02x", data[4]);
+	BT_DBG("Output OOB Size:   %u", data[5]);
+
+	output_action = sys_get_be16(&data[6]);
+	BT_DBG("Output OOB Action: 0x%04x", output_action);
+
+	BT_DBG("Input OOB Size:    %u", data[8]);
+
+	input_action = sys_get_be16(&data[9]);
+	BT_DBG("Input OOB Action:  0x%04x", input_action);
+
+	if (data[0] == 0) {
+		BT_ERR("Invalid number of elements");
+		prov_fail(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	link.provisioner.node =
+		bt_mesh_cdb_node_alloc(link.provisioner.uuid,
+				       link.provisioner.addr, data[0],
+				       link.provisioner.net_idx);
+	if (link.provisioner.node == NULL) {
+		BT_ERR("Failed allocating node 0x%04x", link.provisioner.addr);
+		prov_fail(PROV_ERR_RESOURCES);
+		return;
+	}
+
+	memcpy(&link.conf_inputs[1], data, 11);
+
+	send_start();
+#endif
+}
+
+static bt_mesh_output_action_t output_action(uint8_t action)
+{
+	switch (action) {
+	case OUTPUT_OOB_BLINK:
+		return BT_MESH_BLINK;
+	case OUTPUT_OOB_BEEP:
+		return BT_MESH_BEEP;
+	case OUTPUT_OOB_VIBRATE:
+		return BT_MESH_VIBRATE;
+	case OUTPUT_OOB_NUMBER:
+		return BT_MESH_DISPLAY_NUMBER;
+	case OUTPUT_OOB_STRING:
+		return BT_MESH_DISPLAY_STRING;
+	default:
+		return BT_MESH_NO_OUTPUT;
+	}
+}
+
+static bt_mesh_input_action_t input_action(uint8_t action)
+{
+	switch (action) {
+	case INPUT_OOB_PUSH:
+		return BT_MESH_PUSH;
+	case INPUT_OOB_TWIST:
+		return BT_MESH_TWIST;
+	case INPUT_OOB_NUMBER:
+		return BT_MESH_ENTER_NUMBER;
+	case INPUT_OOB_STRING:
+		return BT_MESH_ENTER_STRING;
+	default:
+		return BT_MESH_NO_INPUT;
+	}
+}
+
+static int prov_auth(uint8_t method, uint8_t action, uint8_t size)
+{
+	bt_mesh_output_action_t output;
+	bt_mesh_input_action_t input;
+
+	switch (method) {
+	case AUTH_METHOD_NO_OOB:
+		if (action || size) {
+			return -EINVAL;
+		}
+
+		(void)memset(link.auth, 0, sizeof(link.auth));
+		return 0;
+	case AUTH_METHOD_STATIC:
+		if (action || size) {
+			return -EINVAL;
+		}
+
+		memcpy(link.auth + 16 - prov->static_val_len,
+		       prov->static_val, prov->static_val_len);
+		(void)memset(link.auth, 0,
+			     sizeof(link.auth) - prov->static_val_len);
+		return 0;
+
+	case AUTH_METHOD_OUTPUT:
+		output = output_action(action);
+		if (!output) {
+			return -EINVAL;
+		}
+
+		if (!(prov->output_actions & output)) {
+			return -EINVAL;
+		}
+
+		if (size > prov->output_size) {
+			return -EINVAL;
+		}
+
+		atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE);
+
+		if (output == BT_MESH_DISPLAY_STRING) {
+			unsigned char str[9];
+			uint8_t i;
+
+			bt_rand(str, size);
+
+			/* Normalize to '0' .. '9' & 'A' .. 'Z' */
+			for (i = 0U; i < size; i++) {
+				str[i] %= 36;
+				if (str[i] < 10) {
+					str[i] += '0';
+				} else {
+					str[i] += 'A' - 10;
+				}
+			}
+			str[size] = '\0';
+
+			memcpy(link.auth, str, size);
+			(void)memset(link.auth + size, 0,
+				     sizeof(link.auth) - size);
+
+			return prov->output_string((char *)str);
+		} else {
+			uint32_t div[8] = { 10, 100, 1000, 10000, 100000,
+					    1000000, 10000000, 100000000 };
+			uint32_t num;
+
+			bt_rand(&num, sizeof(num));
+			num %= div[size - 1];
+
+			sys_put_be32(num, &link.auth[12]);
+			(void)memset(link.auth, 0, 12);
+
+			return prov->output_number(output, num);
+		}
+
+	case AUTH_METHOD_INPUT:
+		input = input_action(action);
+		if (!input) {
+			return -EINVAL;
+		}
+
+		if (!(prov->input_actions & input)) {
+			return -EINVAL;
+		}
+
+		if (size > prov->input_size) {
+			return -EINVAL;
+		}
+
+		if (input == BT_MESH_ENTER_STRING) {
+			atomic_set_bit(link.flags, WAIT_STRING);
+		} else {
+			atomic_set_bit(link.flags, WAIT_NUMBER);
+		}
+
+		return prov->input(input, size);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static void prov_start(const uint8_t *data)
+{
+	BT_DBG("Algorithm:   0x%02x", data[0]);
+	BT_DBG("Public Key:  0x%02x", data[1]);
+	BT_DBG("Auth Method: 0x%02x", data[2]);
+	BT_DBG("Auth Action: 0x%02x", data[3]);
+	BT_DBG("Auth Size:   0x%02x", data[4]);
+
+	if (data[0] != PROV_ALG_P256) {
+		BT_ERR("Unknown algorithm 0x%02x", data[0]);
+		prov_fail(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (data[1] != PUB_KEY_NO_OOB) {
+		BT_ERR("Invalid public key type: 0x%02x", data[1]);
+		prov_fail(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	memcpy(&link.conf_inputs[12], data, 5);
+
+	link.expect = PROV_PUB_KEY;
+
+	if (prov_auth(data[2], data[3], data[4]) < 0) {
+		BT_ERR("Invalid authentication method: 0x%02x; "
+			"action: 0x%02x; size: 0x%02x", data[2], data[3],
+			data[4]);
+		prov_fail(PROV_ERR_NVAL_FMT);
+	}
+}
+
+static void send_confirm(void)
+{
+	PROV_BUF(cfm, 17);
+
+	BT_DBG("ConfInputs[0]   %s", bt_hex(link.conf_inputs, 64));
+	BT_DBG("ConfInputs[64]  %s", bt_hex(&link.conf_inputs[64], 64));
+	BT_DBG("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17));
+
+	if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
+		BT_ERR("Unable to generate confirmation salt");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
+
+	if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
+		BT_ERR("Unable to generate confirmation key");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
+
+	if (bt_rand(link.rand, 16)) {
+		BT_ERR("Unable to generate random number");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("LocalRandom: %s", bt_hex(link.rand, 16));
+
+	prov_buf_init(&cfm, PROV_CONFIRM);
+
+	if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
+			      net_buf_simple_add(&cfm, 16))) {
+		BT_ERR("Unable to generate confirmation value");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	if (prov_send(&cfm, NULL)) {
+		BT_ERR("Failed to send Provisioning Confirm");
+		return;
+	}
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		link.expect = PROV_CONFIRM;
+	} else {
+		link.expect = PROV_RANDOM;
+	}
+}
+
+static void send_input_complete(void)
+{
+	PROV_BUF(buf, 1);
+
+	prov_buf_init(&buf, PROV_INPUT_COMPLETE);
+	if (prov_send(&buf, NULL)) {
+		BT_ERR("Failed to send Provisioning Input Complete");
+	}
+	link.expect = PROV_CONFIRM;
+}
+
+static void input_complete(void)
+{
+	if (atomic_test_bit(link.flags, PUB_KEY_SENT)) {
+		send_input_complete();
+	} else {
+		atomic_set_bit(link.flags, INPUT_COMPLETE);
+	}
+}
+
+int bt_mesh_input_number(uint32_t num)
+{
+	BT_DBG("%u", num);
+
+	if (!atomic_test_and_clear_bit(link.flags, WAIT_NUMBER)) {
+		return -EINVAL;
+	}
+
+	sys_put_be32(num, &link.auth[12]);
+
+	input_complete();
+
+	return 0;
+}
+
+int bt_mesh_input_string(const char *str)
+{
+	BT_DBG("%s", str);
+
+	if (!atomic_test_and_clear_bit(link.flags, WAIT_STRING)) {
+		return -EINVAL;
+	}
+
+	strncpy((char *)link.auth, str, prov->input_size);
+
+	input_complete();
+
+	return 0;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+	atomic_set_bit(link.flags, PUB_KEY_SENT);
+
+	if (atomic_test_bit(link.flags, INPUT_COMPLETE)) {
+		send_input_complete();
+		return;
+	}
+}
+
+static void send_pub_key(void)
+{
+	PROV_BUF(buf, 65);
+	const uint8_t *key;
+
+	key = bt_pub_key_get();
+	if (!key) {
+		BT_ERR("No public key available");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+	prov_buf_init(&buf, PROV_PUB_KEY);
+
+	/* Swap X and Y halves independently to big-endian */
+	sys_memcpy_swap(net_buf_simple_add(&buf, 32), key, 32);
+	sys_memcpy_swap(net_buf_simple_add(&buf, 32), &key[32], 32);
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		/* PublicKeyProvisioner */
+		memcpy(&link.conf_inputs[17], &buf.data[1], 64);
+	} else {
+		/* PublicKeyRemote */
+		memcpy(&link.conf_inputs[81], &buf.data[1], 64);
+	}
+
+	if (prov_send(&buf, public_key_sent)) {
+		BT_ERR("Failed to send Public Key");
+		return;
+	}
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		link.expect = PROV_PUB_KEY;
+	} else {
+		if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
+		    atomic_test_bit(link.flags, WAIT_STRING)) {
+			link.expect = PROV_NO_PDU; /* Wait for input */
+		} else {
+			link.expect = PROV_CONFIRM;
+		}
+	}
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+	BT_DBG("%p", dhkey);
+
+	if (!dhkey) {
+		BT_ERR("DHKey generation failed");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	sys_memcpy_swap(link.dhkey, dhkey, 32);
+
+	BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		send_confirm();
+	} else {
+		send_pub_key();
+	}
+}
+
+static void prov_dh_key_gen(void)
+{
+	uint8_t remote_pk_le[64], *remote_pk;
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		remote_pk = &link.conf_inputs[81];
+	} else {
+		remote_pk = &link.conf_inputs[17];
+	}
+
+	/* Copy remote key in little-endian for bt_dh_key_gen().
+	 * X and Y halves are swapped independently. The bt_dh_key_gen()
+	 * will also take care of validating the remote public key.
+	 */
+	sys_memcpy_swap(remote_pk_le, remote_pk, 32);
+	sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
+
+	if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+		BT_ERR("Failed to generate DHKey");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+	}
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+	BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		/* PublicKeyDevice */
+		memcpy(&link.conf_inputs[81], data, 64);
+		link.bearer->clear_tx();
+	} else {
+		/* PublicKeyProvisioner */
+		memcpy(&link.conf_inputs[17], data, 64);
+
+		if (!bt_pub_key_get()) {
+			/* Clear retransmit timer */
+			link.bearer->clear_tx();
+			atomic_set_bit(link.flags, WAIT_PUB_KEY);
+			BT_WARN("Waiting for local public key");
+			return;
+		}
+	}
+
+	prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+	if (!pkey) {
+		BT_WARN("Public key not available");
+		return;
+	}
+
+	BT_DBG("Local public key ready");
+
+	if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) {
+		if (atomic_test_bit(link.flags, PROVISIONER)) {
+			send_pub_key();
+		} else {
+			prov_dh_key_gen();
+		}
+	}
+}
+
+static void notify_input_complete(void)
+{
+	if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) &&
+	    prov->input_complete) {
+		prov->input_complete();
+	}
+}
+
+static void prov_input_complete(const uint8_t *data)
+{
+	BT_DBG("");
+	notify_input_complete();
+}
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+static void send_prov_data(void)
+{
+	PROV_BUF(pdu, 34);
+	struct bt_mesh_cdb_subnet *sub;
+	uint8_t session_key[16];
+	uint8_t nonce[13];
+	int err;
+
+	err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
+	if (err) {
+		BT_ERR("Unable to generate session key");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+	err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
+	if (err) {
+		BT_ERR("Unable to generate session nonce");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+	err = bt_mesh_dev_key(link.dhkey, link.prov_salt,
+			      link.provisioner.node->dev_key);
+	if (err) {
+		BT_ERR("Unable to generate device key");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("DevKey: %s", bt_hex(link.provisioner.node->dev_key, 16));
+
+	sub = bt_mesh_cdb_subnet_get(link.provisioner.node->net_idx);
+	if (sub == NULL) {
+		BT_ERR("No subnet with net_idx %u",
+		       link.provisioner.node->net_idx);
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	prov_buf_init(&pdu, PROV_DATA);
+	net_buf_simple_add_mem(&pdu, sub->keys[sub->kr_flag].net_key, 16);
+	net_buf_simple_add_be16(&pdu, link.provisioner.node->net_idx);
+	net_buf_simple_add_u8(&pdu, bt_mesh_cdb_subnet_flags(sub));
+	net_buf_simple_add_be32(&pdu, bt_mesh_cdb.iv_index);
+	net_buf_simple_add_be16(&pdu, link.provisioner.node->addr);
+	net_buf_simple_add(&pdu, 8); /* For MIC */
+
+	BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
+	       link.provisioner.node->net_idx, bt_mesh.iv_index,
+	       link.provisioner.node->addr);
+
+	err = bt_mesh_prov_encrypt(session_key, nonce, &pdu.data[1],
+				   &pdu.data[1]);
+	if (err) {
+		BT_ERR("Unable to encrypt provisioning data");
+		prov_fail(PROV_ERR_DECRYPT);
+		return;
+	}
+
+	if (prov_send(&pdu, NULL)) {
+		BT_ERR("Failed to send Provisioning Data");
+		return;
+	}
+
+	link.expect = PROV_COMPLETE;
+}
+#endif
+
+static void prov_complete(const uint8_t *data)
+{
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	struct bt_mesh_cdb_node *node = link.provisioner.node;
+
+	BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
+	       bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
+	       node->addr);
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_cdb_node(node);
+	}
+
+	link.provisioner.node = NULL;
+	prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS);
+
+	if (prov->node_added) {
+		prov->node_added(node->net_idx, node->uuid, node->addr,
+				 node->num_elem);
+	}
+#endif
+}
+
+static void send_random(void)
+{
+	PROV_BUF(rnd, 17);
+
+	prov_buf_init(&rnd, PROV_RANDOM);
+	net_buf_simple_add_mem(&rnd, link.rand, 16);
+
+	if (prov_send(&rnd, NULL)) {
+		BT_ERR("Failed to send Provisioning Random");
+		return;
+	}
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		link.expect = PROV_RANDOM;
+	} else {
+		link.expect = PROV_DATA;
+	}
+}
+
+static void prov_random(const uint8_t *data)
+{
+	uint8_t conf_verify[16];
+	const uint8_t *prov_rand, *dev_rand;
+
+	BT_DBG("Remote Random: %s", bt_hex(data, 16));
+
+	if (!memcmp(data, link.rand, 16)) {
+		BT_ERR("Random value is identical to ours, rejecting.");
+		prov_fail(PROV_ERR_CFM_FAILED);
+		return;
+	}
+
+	if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
+		BT_ERR("Unable to calculate confirmation verification");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	if (memcmp(conf_verify, link.conf, 16)) {
+		BT_ERR("Invalid confirmation value");
+		BT_DBG("Received:   %s", bt_hex(link.conf, 16));
+		BT_DBG("Calculated: %s",  bt_hex(conf_verify, 16));
+		prov_fail(PROV_ERR_CFM_FAILED);
+		return;
+	}
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		prov_rand = link.rand;
+		dev_rand = data;
+	} else {
+		prov_rand = data;
+		dev_rand = link.rand;
+	}
+
+	if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand,
+			      link.prov_salt)) {
+		BT_ERR("Failed to generate provisioning salt");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		send_prov_data();
+		return;
+	}
+#endif
+
+	send_random();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+	BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+	memcpy(link.conf, data, 16);
+
+	notify_input_complete();
+
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		send_random();
+	} else {
+		send_confirm();
+	}
+}
+
+static inline bool is_pb_gatt(void)
+{
+	return link.bearer && link.bearer->type == BT_MESH_PROV_GATT;
+}
+
+static void prov_data(const uint8_t *data)
+{
+	PROV_BUF(msg, 1);
+	uint8_t session_key[16];
+	uint8_t nonce[13];
+	uint8_t dev_key[16];
+	uint8_t pdu[25];
+	uint8_t flags;
+	uint32_t iv_index;
+	uint16_t addr;
+	uint16_t net_idx;
+	int err;
+	bool identity_enable;
+
+	BT_DBG("");
+
+	err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
+	if (err) {
+		BT_ERR("Unable to generate session key");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+	err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
+	if (err) {
+		BT_ERR("Unable to generate session nonce");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+	err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
+	if (err) {
+		BT_ERR("Unable to decrypt provisioning data");
+		prov_fail(PROV_ERR_DECRYPT);
+		return;
+	}
+
+	err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
+	if (err) {
+		BT_ERR("Unable to generate device key");
+		prov_fail(PROV_ERR_UNEXP_ERR);
+		return;
+	}
+
+	BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
+
+	net_idx = sys_get_be16(&pdu[16]);
+	flags = pdu[18];
+	iv_index = sys_get_be32(&pdu[19]);
+	addr = sys_get_be16(&pdu[23]);
+
+	BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
+	       net_idx, iv_index, addr);
+
+	prov_buf_init(&msg, PROV_COMPLETE);
+	if (prov_send(&msg, NULL)) {
+		BT_ERR("Failed to send Provisioning Complete");
+		return;
+	}
+
+	/* Ignore any further PDUs on this link */
+	link.expect = PROV_NO_PDU;
+
+	/* Store info, since bt_mesh_provision() will end up clearing it */
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		identity_enable = is_pb_gatt();
+	} else {
+		identity_enable = false;
+	}
+
+	err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+	if (err) {
+		BT_ERR("Failed to provision (err %d)", err);
+		return;
+	}
+
+	/* After PB-GATT provisioning we should start advertising
+	 * using Node Identity.
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
+		bt_mesh_proxy_identity_enable();
+	}
+}
+
+static void prov_failed(const uint8_t *data)
+{
+	BT_WARN("Error: 0x%02x", data[0]);
+	reset_state();
+}
+
+static const struct {
+	void (*func)(const uint8_t *data);
+	uint16_t len;
+} prov_handlers[] = {
+	{ prov_invite, 1 },
+	{ prov_capabilities, 11 },
+	{ prov_start, 5, },
+	{ prov_pub_key, 64 },
+	{ prov_input_complete, 0 },
+	{ prov_confirm, 16 },
+	{ prov_random, 16 },
+	{ prov_data, 33 },
+	{ prov_complete, 0 },
+	{ prov_failed, 1 },
+};
+
+static void prov_recv(const struct prov_bearer *bearer, void *cb_data,
+		      struct net_buf_simple *buf)
+{
+	uint8_t type = buf->data[0];
+
+	BT_DBG("type 0x%02x len %u", type, buf->len);
+
+	if (type >= ARRAY_SIZE(prov_handlers)) {
+		BT_ERR("Unknown provisioning PDU type 0x%02x", type);
+		prov_fail(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	if (type != PROV_FAILED && type != link.expect) {
+		BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
+		prov_fail(PROV_ERR_UNEXP_PDU);
+		return;
+	}
+
+	if (1 + prov_handlers[type].len != buf->len) {
+		BT_ERR("Invalid length %u for type 0x%02x", buf->len, type);
+		prov_fail(PROV_ERR_NVAL_FMT);
+		return;
+	}
+
+	prov_handlers[type].func(&buf->data[1]);
+}
+
+static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data)
+{
+	atomic_set_bit(link.flags, LINK_ACTIVE);
+
+	if (prov->link_open) {
+		prov->link_open(bearer->type);
+	}
+
+	link.bearer = bearer;
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	if (atomic_test_bit(link.flags, PROVISIONER)) {
+		send_invite();
+		return;
+	}
+#endif
+
+	link.expect = PROV_INVITE;
+}
+
+static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data,
+			     enum prov_bearer_link_status reason)
+{
+	/* Reset state before calling link_close, so a new provisioning
+	 * procedure can be started from the callback.
+	 */
+	reset_state();
+
+	BT_DBG("%u", reason);
+
+	if (prov->link_close) {
+		prov->link_close(bearer->type);
+	}
+}
+
+static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data,
+			      uint8_t err)
+{
+	prov_fail(err);
+}
+
+static const struct prov_bearer_cb prov_bearer_cb = {
+	.link_opened = prov_link_opened,
+	.link_closed = prov_link_closed,
+	.error = prov_bearer_error,
+	.recv = prov_recv,
+};
+
+#if defined(CONFIG_BT_MESH_PB_ADV) && defined(CONFIG_BT_MESH_PROVISIONER)
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+			uint8_t attention_duration)
+{
+	int err;
+
+	if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
+		return -EBUSY;
+	}
+
+	struct bt_uuid_128 uuid_repr = { .uuid = { BT_UUID_TYPE_128 } };
+
+	memcpy(uuid_repr.val, uuid, 16);
+	BT_DBG("Provisioning %s", bt_uuid_str(&uuid_repr.uuid));
+
+	atomic_set_bit(link.flags, PROVISIONER);
+	memcpy(link.provisioner.uuid, uuid, 16);
+	link.provisioner.addr = addr;
+	link.provisioner.net_idx = net_idx;
+	link.provisioner.attention_duration = attention_duration;
+	link.bearer = &pb_adv;
+
+	err = link.bearer->link_open(link.provisioner.uuid, PROTOCOL_TIMEOUT,
+				     &prov_bearer_cb, NULL);
+	if (err) {
+		atomic_clear_bit(link.flags, LINK_ACTIVE);
+	}
+
+	return err;
+}
+#endif
+
+const struct bt_mesh_prov *bt_mesh_prov_get(void)
+{
+	return prov;
+}
+
+bool bt_prov_active(void)
+{
+	return atomic_test_bit(link.flags, LINK_ACTIVE);
+}
+
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
+{
+	if (!prov_info) {
+		BT_ERR("No provisioning context provided");
+		return -EINVAL;
+	}
+
+	prov = prov_info;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+		pb_adv_init();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+		pb_gatt_init();
+	}
+
+	return reset_state();
+}
+
+int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
+{
+	if (bt_mesh_is_provisioned()) {
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_DEBUG)) {
+		struct bt_uuid_128 uuid = { .uuid = { BT_UUID_TYPE_128 } };
+
+		memcpy(uuid.val, prov->uuid, 16);
+		BT_INFO("Device UUID: %s", bt_uuid_str(&uuid.uuid));
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+	    (bearers & BT_MESH_PROV_ADV)) {
+		pb_adv.link_accept(&prov_bearer_cb, NULL);
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+	    (bearers & BT_MESH_PROV_GATT)) {
+		pb_gatt.link_accept(&prov_bearer_cb, NULL);
+	}
+
+	return 0;
+}
+
+int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
+{
+	if (bt_mesh_is_provisioned()) {
+		return -EALREADY;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+	    (bearers & BT_MESH_PROV_ADV)) {
+		bt_mesh_beacon_disable();
+		bt_mesh_scan_disable();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+	    (bearers & BT_MESH_PROV_GATT)) {
+		bt_mesh_proxy_prov_disable(true);
+	}
+
+	return 0;
+}
+
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr)
+{
+	if (prov->complete) {
+		prov->complete(net_idx, addr);
+	}
+}
+
+void bt_mesh_prov_reset(void)
+{
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+		pb_adv_reset();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+		pb_gatt_reset();
+	}
+
+	reset_state();
+
+	if (prov->reset) {
+		prov->reset();
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov_bearer.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov_bearer.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/prov_bearer.h	(working copy)
@@ -0,0 +1,116 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define PROTOCOL_TIMEOUT     K_SECONDS(60)
+
+/** @def PROV_BEARER_BUF_HEADROOM
+ *
+ *  @brief Required headroom for the bearer packet buffers.
+ */
+#if defined(CONFIG_BT_MESH_PB_GATT)
+#define PROV_BEARER_BUF_HEADROOM 5
+#else
+#define PROV_BEARER_BUF_HEADROOM 0
+#endif
+
+enum prov_bearer_link_status {
+	PROV_BEARER_LINK_STATUS_SUCCESS,
+	PROV_BEARER_LINK_STATUS_TIMEOUT,
+	PROV_BEARER_LINK_STATUS_FAIL,
+};
+
+struct prov_bearer;
+
+/** Callbacks from bearer to host */
+struct prov_bearer_cb {
+
+	void (*link_opened)(const struct prov_bearer *bearer, void *cb_data);
+
+	void (*link_closed)(const struct prov_bearer *bearer, void *cb_data,
+			    enum prov_bearer_link_status reason);
+
+	void (*error)(const struct prov_bearer *bearer, void *cb_data,
+		      uint8_t err);
+
+	void (*recv)(const struct prov_bearer *bearer, void *cb_data,
+		     struct net_buf_simple *buf);
+};
+
+typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data);
+
+/** Provisioning bearer API */
+struct prov_bearer {
+	/** Provisioning bearer type. */
+	bt_mesh_prov_bearer_t type;
+
+	/** @brief Enable link establishment as a provisionee.
+	 *
+	 *  Prompts the bearer to make itself visible to provisioners, and
+	 *  start accepting link open messages.
+	 *
+	 *  @param cb Bearer event callbacks used for the duration of the link.
+	 *  @param cb_data Context parameter to pass to the bearer callbacks.
+	 *
+	 *  @return Zero on success, or (negative) error code otherwise.
+	 */
+	int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data);
+
+	/** @brief Send a packet on an established link.
+	 *
+	 *  @param buf     Payload buffer. Requires @ref
+	 *                 PROV_BEARER_BUF_HEADROOM bytes of headroom.
+	 *  @param cb      Callback to call when sending is complete.
+	 *  @param cb_data Callback data.
+	 *
+	 *  @return Zero on success, or (negative) error code otherwise.
+	 */
+	int (*send)(struct net_buf_simple *buf, prov_bearer_send_complete_t cb,
+		    void *cb_data);
+
+	/** @brief Clear any ongoing transmissions, if possible.
+	 *
+	 *  Bearers that don't support tx clearing must implement this callback
+	 *  and leave it empty.
+	 */
+	void (*clear_tx)(void);
+
+	/* Only available in provisioners: */
+
+	/** @brief Open a new link as a provisioner.
+	 *
+	 *  Only available in provisioners. Bearers that don't support the
+	 *  provisioner role should leave this as NULL.
+	 *
+	 *  @param uuid UUID of the node to establish a link to.
+	 *  @param timeout Protocol timeout.
+	 *  @param cb Bearer event callbacks used for the duration of the link.
+	 *  @param cb_data Context parameter to pass to the bearer callbacks.
+	 *
+	 *  @return Zero on success, or (negative) error code otherwise.
+	 */
+	int (*link_open)(const uint8_t uuid[16], k_timeout_t timeout,
+			 const struct prov_bearer_cb *cb, void *cb_data);
+
+	/** @brief Close the current link.
+	 *
+	 *  Only available in provisioners. Bearers that don't support the
+	 *  provisioner role should leave this as NULL.
+	 *
+	 *  @param status Link status for the link close message.
+	 */
+	void (*link_close)(enum prov_bearer_link_status status);
+};
+
+extern const struct prov_bearer pb_adv;
+extern const struct prov_bearer pb_gatt;
+
+void pb_adv_init(void);
+void pb_gatt_init(void);
+
+void pb_adv_reset(void);
+void pb_gatt_reset(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.h	(working copy)
@@ -0,0 +1,44 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define BT_MESH_PROXY_NET_PDU   0x00
+#define BT_MESH_PROXY_BEACON    0x01
+#define BT_MESH_PROXY_CONFIG    0x02
+#define BT_MESH_PROXY_PROV      0x03
+
+
+struct bt_mesh_proxy_idle_cb {
+	sys_snode_t n;
+	void (*cb)(void);
+};
+
+int bt_mesh_proxy_send(struct bt_conn *conn, uint8_t type,
+		       struct net_buf_simple *msg);
+
+int bt_mesh_proxy_prov_enable(void);
+int bt_mesh_proxy_prov_disable(bool disconnect);
+
+int bt_mesh_proxy_gatt_enable(void);
+int bt_mesh_proxy_gatt_disable(void);
+void bt_mesh_proxy_gatt_disconnect(void);
+
+void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
+
+struct net_buf_simple *bt_mesh_proxy_get_buf(void);
+
+k_timeout_t bt_mesh_proxy_adv_start(void);
+void bt_mesh_proxy_adv_stop(void);
+
+void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
+void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
+
+bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst);
+void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, uint16_t addr);
+
+int bt_mesh_proxy_init(void);
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/proxy.c	(working copy)
@@ -0,0 +1,1382 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/gatt.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROXY)
+#define LOG_MODULE_NAME bt_mesh_proxy
+#include "common/log.h"
+
+#include "mesh.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "transport.h"
+#include "prov.h"
+#include "beacon.h"
+#include "foundation.h"
+#include "access.h"
+#include "proxy.h"
+
+#define PDU_TYPE(data)     (data[0] & BIT_MASK(6))
+#define PDU_SAR(data)      (data[0] >> 6)
+
+/* Mesh Profile 1.0 Section 6.6:
+ * "The timeout for the SAR transfer is 20 seconds. When the timeout
+ *  expires, the Proxy Server shall disconnect."
+ */
+#define PROXY_SAR_TIMEOUT  K_SECONDS(20)
+
+#define SAR_COMPLETE       0x00
+#define SAR_FIRST          0x01
+#define SAR_CONT           0x02
+#define SAR_LAST           0x03
+
+#define CFG_FILTER_SET     0x00
+#define CFG_FILTER_ADD     0x01
+#define CFG_FILTER_REMOVE  0x02
+#define CFG_FILTER_STATUS  0x03
+
+#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6)))
+
+#define CLIENT_BUF_SIZE 68
+
+#if defined(CONFIG_BT_MESH_DEBUG_USE_ID_ADDR)
+#define ADV_OPT (BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME | \
+		 BT_LE_ADV_OPT_USE_IDENTITY)
+#else
+#define ADV_OPT (BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME)
+#endif
+
+static const struct bt_le_adv_param slow_adv_param = {
+	.options = ADV_OPT,
+	.interval_min = BT_GAP_ADV_SLOW_INT_MIN,
+	.interval_max = BT_GAP_ADV_SLOW_INT_MAX,
+};
+
+static const struct bt_le_adv_param fast_adv_param = {
+	.options = ADV_OPT,
+	.interval_min = BT_GAP_ADV_FAST_INT_MIN_2,
+	.interval_max = BT_GAP_ADV_FAST_INT_MAX_2,
+};
+
+static bool proxy_adv_enabled;
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+static void proxy_send_beacons(struct k_work *work);
+#endif
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+static bool prov_fast_adv;
+#endif
+
+static struct bt_mesh_proxy_client {
+	struct bt_conn *conn;
+	uint16_t filter[CONFIG_BT_MESH_PROXY_FILTER_SIZE];
+	enum __packed {
+		NONE,
+		WHITELIST,
+		BLACKLIST,
+		PROV,
+	} filter_type;
+	uint8_t msg_type;
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	struct k_work send_beacons;
+#endif
+	struct k_delayed_work    sar_timer;
+	struct net_buf_simple    buf;
+} clients[CONFIG_BT_MAX_CONN] = {
+	[0 ... (CONFIG_BT_MAX_CONN - 1)] = {
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+		.send_beacons = Z_WORK_INITIALIZER(proxy_send_beacons),
+#endif
+	},
+};
+
+static sys_slist_t idle_waiters;
+static atomic_t pending_notifications;
+static uint8_t __noinit client_buf_data[CLIENT_BUF_SIZE * CONFIG_BT_MAX_CONN];
+
+/* Track which service is enabled */
+static enum {
+	MESH_GATT_NONE,
+	MESH_GATT_PROV,
+	MESH_GATT_PROXY,
+} gatt_svc = MESH_GATT_NONE;
+
+static struct bt_mesh_proxy_client *find_client(struct bt_conn *conn)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		if (clients[i].conn == conn) {
+			return &clients[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void proxy_sar_timeout(struct k_work *work)
+{
+	struct bt_mesh_proxy_client *client;
+
+	BT_WARN("Proxy SAR timeout");
+
+	client = CONTAINER_OF(work, struct bt_mesh_proxy_client, sar_timer);
+	if (client->conn) {
+		bt_conn_disconnect(client->conn,
+				   BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+	}
+}
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+/* Next subnet in queue to be advertised */
+static int next_idx;
+
+static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type,
+				  struct net_buf_simple *msg);
+
+static int filter_set(struct bt_mesh_proxy_client *client,
+		      struct net_buf_simple *buf)
+{
+	uint8_t type;
+
+	if (buf->len < 1) {
+		BT_WARN("Too short Filter Set message");
+		return -EINVAL;
+	}
+
+	type = net_buf_simple_pull_u8(buf);
+	BT_DBG("type 0x%02x", type);
+
+	switch (type) {
+	case 0x00:
+		(void)memset(client->filter, 0, sizeof(client->filter));
+		client->filter_type = WHITELIST;
+		break;
+	case 0x01:
+		(void)memset(client->filter, 0, sizeof(client->filter));
+		client->filter_type = BLACKLIST;
+		break;
+	default:
+		BT_WARN("Prohibited Filter Type 0x%02x", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
+{
+	int i;
+
+	BT_DBG("addr 0x%04x", addr);
+
+	if (addr == BT_MESH_ADDR_UNASSIGNED) {
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
+		if (client->filter[i] == addr) {
+			return;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
+		if (client->filter[i] == BT_MESH_ADDR_UNASSIGNED) {
+			client->filter[i] = addr;
+			return;
+		}
+	}
+}
+
+static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
+{
+	int i;
+
+	BT_DBG("addr 0x%04x", addr);
+
+	if (addr == BT_MESH_ADDR_UNASSIGNED) {
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
+		if (client->filter[i] == addr) {
+			client->filter[i] = BT_MESH_ADDR_UNASSIGNED;
+			return;
+		}
+	}
+}
+
+static void send_filter_status(struct bt_mesh_proxy_client *client,
+			       struct bt_mesh_net_rx *rx,
+			       struct net_buf_simple *buf)
+{
+	struct bt_mesh_net_tx tx = {
+		.sub = rx->sub,
+		.ctx = &rx->ctx,
+		.src = bt_mesh_primary_addr(),
+	};
+	uint16_t filter_size;
+	int i, err;
+
+	/* Configuration messages always have dst unassigned */
+	tx.ctx->addr = BT_MESH_ADDR_UNASSIGNED;
+
+	net_buf_simple_reset(buf);
+	net_buf_simple_reserve(buf, 10);
+
+	net_buf_simple_add_u8(buf, CFG_FILTER_STATUS);
+
+	if (client->filter_type == WHITELIST) {
+		net_buf_simple_add_u8(buf, 0x00);
+	} else {
+		net_buf_simple_add_u8(buf, 0x01);
+	}
+
+	for (filter_size = 0U, i = 0; i < ARRAY_SIZE(client->filter); i++) {
+		if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) {
+			filter_size++;
+		}
+	}
+
+	net_buf_simple_add_be16(buf, filter_size);
+
+	BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	err = bt_mesh_net_encode(&tx, buf, true);
+	if (err) {
+		BT_ERR("Encoding Proxy cfg message failed (err %d)", err);
+		return;
+	}
+
+	err = proxy_segment_and_send(client->conn, BT_MESH_PROXY_CONFIG, buf);
+	if (err) {
+		BT_ERR("Failed to send proxy cfg message (err %d)", err);
+	}
+}
+
+static void proxy_cfg(struct bt_mesh_proxy_client *client)
+{
+	NET_BUF_SIMPLE_DEFINE(buf, 29);
+	struct bt_mesh_net_rx rx;
+	uint8_t opcode;
+	int err;
+
+	err = bt_mesh_net_decode(&client->buf, BT_MESH_NET_IF_PROXY_CFG,
+				 &rx, &buf);
+	if (err) {
+		BT_ERR("Failed to decode Proxy Configuration (err %d)", err);
+		return;
+	}
+
+	rx.local_match = 1U;
+
+	if (bt_mesh_rpl_check(&rx, NULL)) {
+		BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
+			rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
+		return;
+	}
+
+	/* Remove network headers */
+	net_buf_simple_pull(&buf, BT_MESH_NET_HDR_LEN);
+
+	BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len));
+
+	if (buf.len < 1) {
+		BT_WARN("Too short proxy configuration PDU");
+		return;
+	}
+
+	opcode = net_buf_simple_pull_u8(&buf);
+	switch (opcode) {
+	case CFG_FILTER_SET:
+		filter_set(client, &buf);
+		send_filter_status(client, &rx, &buf);
+		break;
+	case CFG_FILTER_ADD:
+		while (buf.len >= 2) {
+			uint16_t addr;
+
+			addr = net_buf_simple_pull_be16(&buf);
+			filter_add(client, addr);
+		}
+		send_filter_status(client, &rx, &buf);
+		break;
+	case CFG_FILTER_REMOVE:
+		while (buf.len >= 2) {
+			uint16_t addr;
+
+			addr = net_buf_simple_pull_be16(&buf);
+			filter_remove(client, addr);
+		}
+		send_filter_status(client, &rx, &buf);
+		break;
+	default:
+		BT_WARN("Unhandled configuration OpCode 0x%02x", opcode);
+		break;
+	}
+}
+
+static int beacon_send(struct bt_conn *conn, struct bt_mesh_subnet *sub)
+{
+	NET_BUF_SIMPLE_DEFINE(buf, 23);
+
+	net_buf_simple_reserve(&buf, 1);
+	bt_mesh_beacon_create(sub, &buf);
+
+	return proxy_segment_and_send(conn, BT_MESH_PROXY_BEACON, &buf);
+}
+
+static void proxy_send_beacons(struct k_work *work)
+{
+	struct bt_mesh_proxy_client *client;
+	int i;
+
+	client = CONTAINER_OF(work, struct bt_mesh_proxy_client, send_beacons);
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+			beacon_send(client->conn, sub);
+		}
+	}
+}
+
+void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
+{
+	int i;
+
+	if (!sub) {
+		/* NULL means we send on all subnets */
+		for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+			if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
+				bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
+			}
+		}
+
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		if (clients[i].conn) {
+			beacon_send(clients[i].conn, sub);
+		}
+	}
+}
+
+void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+{
+	sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
+	sub->node_id_start = k_uptime_get_32();
+
+	/* Prioritize the recently enabled subnet */
+	next_idx = sub - bt_mesh.sub;
+}
+
+void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
+{
+	sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+	sub->node_id_start = 0U;
+}
+
+int bt_mesh_proxy_identity_enable(void)
+{
+	int i, count = 0;
+
+	BT_DBG("");
+
+	if (!bt_mesh_is_provisioned()) {
+		return -EAGAIN;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
+			continue;
+		}
+
+		bt_mesh_proxy_identity_start(sub);
+		count++;
+	}
+
+	if (count) {
+		bt_mesh_adv_update();
+	}
+
+	return 0;
+}
+
+#endif /* GATT_PROXY */
+
+static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
+{
+	switch (client->msg_type) {
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	case BT_MESH_PROXY_NET_PDU:
+		BT_DBG("Mesh Network PDU");
+		bt_mesh_net_recv(&client->buf, 0, BT_MESH_NET_IF_PROXY);
+		break;
+	case BT_MESH_PROXY_BEACON:
+		BT_DBG("Mesh Beacon PDU");
+		bt_mesh_beacon_recv(&client->buf);
+		break;
+	case BT_MESH_PROXY_CONFIG:
+		BT_DBG("Mesh Configuration PDU");
+		proxy_cfg(client);
+		break;
+#endif
+#if defined(CONFIG_BT_MESH_PB_GATT)
+	case BT_MESH_PROXY_PROV:
+		BT_DBG("Mesh Provisioning PDU");
+		bt_mesh_pb_gatt_recv(client->conn, &client->buf);
+		break;
+#endif
+	default:
+		BT_WARN("Unhandled Message Type 0x%02x", client->msg_type);
+		break;
+	}
+
+	net_buf_simple_reset(&client->buf);
+}
+
+#define ATTR_IS_PROV(attr) (attr->user_data != NULL)
+
+static ssize_t proxy_recv(struct bt_conn *conn,
+			  const struct bt_gatt_attr *attr, const void *buf,
+			  uint16_t len, uint16_t offset, uint8_t flags)
+{
+	struct bt_mesh_proxy_client *client = find_client(conn);
+	const uint8_t *data = buf;
+
+	if (!client) {
+		return -ENOTCONN;
+	}
+
+	if (len < 1) {
+		BT_WARN("Too small Proxy PDU");
+		return -EINVAL;
+	}
+
+	if (ATTR_IS_PROV(attr) != (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) {
+		BT_WARN("Proxy PDU type doesn't match GATT service");
+		return -EINVAL;
+	}
+
+	if (len - 1 > net_buf_simple_tailroom(&client->buf)) {
+		BT_WARN("Too big proxy PDU");
+		return -EINVAL;
+	}
+
+	switch (PDU_SAR(data)) {
+	case SAR_COMPLETE:
+		if (client->buf.len) {
+			BT_WARN("Complete PDU while a pending incomplete one");
+			return -EINVAL;
+		}
+
+		client->msg_type = PDU_TYPE(data);
+		net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
+		proxy_complete_pdu(client);
+		break;
+
+	case SAR_FIRST:
+		if (client->buf.len) {
+			BT_WARN("First PDU while a pending incomplete one");
+			return -EINVAL;
+		}
+
+		k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT);
+		client->msg_type = PDU_TYPE(data);
+		net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
+		break;
+
+	case SAR_CONT:
+		if (!client->buf.len) {
+			BT_WARN("Continuation with no prior data");
+			return -EINVAL;
+		}
+
+		if (client->msg_type != PDU_TYPE(data)) {
+			BT_WARN("Unexpected message type in continuation");
+			return -EINVAL;
+		}
+
+		k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT);
+		net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
+		break;
+
+	case SAR_LAST:
+		if (!client->buf.len) {
+			BT_WARN("Last SAR PDU with no prior data");
+			return -EINVAL;
+		}
+
+		if (client->msg_type != PDU_TYPE(data)) {
+			BT_WARN("Unexpected message type in last SAR PDU");
+			return -EINVAL;
+		}
+
+		k_delayed_work_cancel(&client->sar_timer);
+		net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
+		proxy_complete_pdu(client);
+		break;
+	}
+
+	return len;
+}
+
+static int conn_count;
+
+static void proxy_connected(struct bt_conn *conn, uint8_t err)
+{
+	struct bt_mesh_proxy_client *client;
+	int i;
+
+	BT_DBG("conn %p err 0x%02x", conn, err);
+
+	conn_count++;
+
+	/* Since we use ADV_OPT_ONE_TIME */
+	proxy_adv_enabled = false;
+
+	/* Try to re-enable advertising in case it's possible */
+	if (conn_count < CONFIG_BT_MAX_CONN) {
+		bt_mesh_adv_update();
+	}
+
+	for (client = NULL, i = 0; i < ARRAY_SIZE(clients); i++) {
+		if (!clients[i].conn) {
+			client = &clients[i];
+			break;
+		}
+	}
+
+	if (!client) {
+		BT_ERR("No free Proxy Client objects");
+		return;
+	}
+
+	client->conn = bt_conn_ref(conn);
+	client->filter_type = NONE;
+	(void)memset(client->filter, 0, sizeof(client->filter));
+	net_buf_simple_reset(&client->buf);
+}
+
+static void proxy_disconnected(struct bt_conn *conn, uint8_t reason)
+{
+	int i;
+
+	BT_DBG("conn %p reason 0x%02x", conn, reason);
+
+	conn_count--;
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		struct bt_mesh_proxy_client *client = &clients[i];
+
+		if (client->conn == conn) {
+			if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+			    client->filter_type == PROV) {
+				bt_mesh_pb_gatt_close(conn);
+			}
+
+			k_delayed_work_cancel(&client->sar_timer);
+			bt_conn_unref(client->conn);
+			client->conn = NULL;
+			break;
+		}
+	}
+
+	bt_mesh_adv_update();
+}
+
+struct net_buf_simple *bt_mesh_proxy_get_buf(void)
+{
+	struct net_buf_simple *buf = &clients[0].buf;
+
+	net_buf_simple_reset(buf);
+
+	return buf;
+}
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+static void prov_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
+{
+	BT_DBG("value 0x%04x", value);
+}
+
+static ssize_t prov_ccc_write(struct bt_conn *conn,
+			   const struct bt_gatt_attr *attr, uint16_t value)
+{
+	struct bt_mesh_proxy_client *client;
+
+	BT_DBG("value 0x%04x", value);
+
+	if (value != BT_GATT_CCC_NOTIFY) {
+		BT_WARN("Client wrote 0x%04x instead enabling notify", value);
+		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
+	}
+
+	/* If a connection exists there must be a client */
+	client = find_client(conn);
+	__ASSERT(client, "No client for connection");
+
+	if (client->filter_type == NONE) {
+		client->filter_type = PROV;
+		bt_mesh_pb_gatt_open(conn);
+	}
+
+	return sizeof(value);
+}
+
+/* Mesh Provisioning Service Declaration */
+static struct _bt_gatt_ccc prov_ccc =
+	BT_GATT_CCC_INITIALIZER(prov_ccc_changed, prov_ccc_write, NULL);
+
+static struct bt_gatt_attr prov_attrs[] = {
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_MESH_PROV),
+
+	BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROV_DATA_IN,
+			       BT_GATT_CHRC_WRITE_WITHOUT_RESP,
+			       BT_GATT_PERM_WRITE, NULL, proxy_recv,
+			       (void *)1),
+
+	BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROV_DATA_OUT,
+			       BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE,
+			       NULL, NULL, NULL),
+	BT_GATT_CCC_MANAGED(&prov_ccc,
+			    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+};
+
+static struct bt_gatt_service prov_svc = BT_GATT_SERVICE(prov_attrs);
+
+int bt_mesh_proxy_prov_enable(void)
+{
+	int i;
+
+	BT_DBG("");
+
+	if (gatt_svc == MESH_GATT_PROV) {
+		return -EALREADY;
+	}
+
+	if (gatt_svc != MESH_GATT_NONE) {
+		return -EBUSY;
+	}
+
+	bt_gatt_service_register(&prov_svc);
+	gatt_svc = MESH_GATT_PROV;
+	prov_fast_adv = true;
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		if (clients[i].conn) {
+			clients[i].filter_type = PROV;
+		}
+	}
+
+
+	return 0;
+}
+
+int bt_mesh_proxy_prov_disable(bool disconnect)
+{
+	int i;
+
+	BT_DBG("");
+
+	if (gatt_svc == MESH_GATT_NONE) {
+		return -EALREADY;
+	}
+
+	if (gatt_svc != MESH_GATT_PROV) {
+		return -EBUSY;
+	}
+
+	bt_gatt_service_unregister(&prov_svc);
+	gatt_svc = MESH_GATT_NONE;
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		struct bt_mesh_proxy_client *client = &clients[i];
+
+		if (!client->conn || client->filter_type != PROV) {
+			continue;
+		}
+
+		if (disconnect) {
+			bt_conn_disconnect(client->conn,
+					   BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+		} else {
+			bt_mesh_pb_gatt_close(client->conn);
+			client->filter_type = NONE;
+		}
+	}
+
+	bt_mesh_adv_update();
+
+	return 0;
+}
+
+#endif /* CONFIG_BT_MESH_PB_GATT */
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+static void proxy_ccc_changed(const struct bt_gatt_attr *attr, uint16_t value)
+{
+	BT_DBG("value 0x%04x", value);
+}
+
+static ssize_t proxy_ccc_write(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, uint16_t value)
+{
+	struct bt_mesh_proxy_client *client;
+
+	BT_DBG("value: 0x%04x", value);
+
+	if (value != BT_GATT_CCC_NOTIFY) {
+		BT_WARN("Client wrote 0x%04x instead enabling notify", value);
+		return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
+	}
+
+	/* If a connection exists there must be a client */
+	client = find_client(conn);
+	__ASSERT(client, "No client for connection");
+
+	if (client->filter_type == NONE) {
+		client->filter_type = WHITELIST;
+		k_work_submit(&client->send_beacons);
+	}
+
+	return sizeof(value);
+}
+
+/* Mesh Proxy Service Declaration */
+static struct _bt_gatt_ccc proxy_ccc =
+	BT_GATT_CCC_INITIALIZER(proxy_ccc_changed, proxy_ccc_write, NULL);
+
+static struct bt_gatt_attr proxy_attrs[] = {
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_MESH_PROXY),
+
+	BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROXY_DATA_IN,
+			       BT_GATT_CHRC_WRITE_WITHOUT_RESP,
+			       BT_GATT_PERM_WRITE,
+			       NULL, proxy_recv, NULL),
+
+	BT_GATT_CHARACTERISTIC(BT_UUID_MESH_PROXY_DATA_OUT,
+			       BT_GATT_CHRC_NOTIFY,
+			       BT_GATT_PERM_NONE,
+			       NULL, NULL, NULL),
+	BT_GATT_CCC_MANAGED(&proxy_ccc,
+			    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+};
+
+static struct bt_gatt_service proxy_svc = BT_GATT_SERVICE(proxy_attrs);
+
+int bt_mesh_proxy_gatt_enable(void)
+{
+	int i;
+
+	BT_DBG("");
+
+	if (gatt_svc == MESH_GATT_PROXY) {
+		return -EALREADY;
+	}
+
+	if (gatt_svc != MESH_GATT_NONE) {
+		return -EBUSY;
+	}
+
+	bt_gatt_service_register(&proxy_svc);
+	gatt_svc = MESH_GATT_PROXY;
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		if (clients[i].conn) {
+			clients[i].filter_type = WHITELIST;
+		}
+	}
+
+	return 0;
+}
+
+void bt_mesh_proxy_gatt_disconnect(void)
+{
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		struct bt_mesh_proxy_client *client = &clients[i];
+
+		if (client->conn && (client->filter_type == WHITELIST ||
+				     client->filter_type == BLACKLIST)) {
+			client->filter_type = NONE;
+			bt_conn_disconnect(client->conn,
+					   BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+		}
+	}
+}
+
+int bt_mesh_proxy_gatt_disable(void)
+{
+	BT_DBG("");
+
+	if (gatt_svc == MESH_GATT_NONE) {
+		return -EALREADY;
+	}
+
+	if (gatt_svc != MESH_GATT_PROXY) {
+		return -EBUSY;
+	}
+
+	bt_mesh_proxy_gatt_disconnect();
+
+	bt_gatt_service_unregister(&proxy_svc);
+	gatt_svc = MESH_GATT_NONE;
+
+	return 0;
+}
+
+void bt_mesh_proxy_addr_add(struct net_buf_simple *buf, uint16_t addr)
+{
+	struct bt_mesh_proxy_client *client =
+		CONTAINER_OF(buf, struct bt_mesh_proxy_client, buf);
+
+	BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
+
+	if (client->filter_type == WHITELIST) {
+		filter_add(client, addr);
+	} else if (client->filter_type == BLACKLIST) {
+		filter_remove(client, addr);
+	}
+}
+
+static bool client_filter_match(struct bt_mesh_proxy_client *client,
+				uint16_t addr)
+{
+	int i;
+
+	BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
+
+	if (client->filter_type == BLACKLIST) {
+		for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
+			if (client->filter[i] == addr) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	if (addr == BT_MESH_ADDR_ALL_NODES) {
+		return true;
+	}
+
+	if (client->filter_type == WHITELIST) {
+		for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
+			if (client->filter[i] == addr) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+bool bt_mesh_proxy_relay(struct net_buf_simple *buf, uint16_t dst)
+{
+	bool relayed = false;
+	int i;
+
+	BT_DBG("%u bytes to dst 0x%04x", buf->len, dst);
+
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		struct bt_mesh_proxy_client *client = &clients[i];
+		NET_BUF_SIMPLE_DEFINE(msg, 32);
+
+		if (!client->conn) {
+			continue;
+		}
+
+		if (!client_filter_match(client, dst)) {
+			continue;
+		}
+
+		/* Proxy PDU sending modifies the original buffer,
+		 * so we need to make a copy.
+		 */
+		net_buf_simple_reserve(&msg, 1);
+		net_buf_simple_add_mem(&msg, buf->data, buf->len);
+
+		bt_mesh_proxy_send(client->conn, BT_MESH_PROXY_NET_PDU, &msg);
+		relayed = true;
+	}
+
+	return relayed;
+}
+
+#endif /* CONFIG_BT_MESH_GATT_PROXY */
+
+static void notify_complete(struct bt_conn *conn, void *user_data)
+{
+	sys_snode_t *n;
+
+	if (atomic_dec(&pending_notifications) > 1) {
+		return;
+	}
+
+	BT_DBG("");
+
+	while ((n = sys_slist_get(&idle_waiters))) {
+		CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb();
+	}
+}
+
+static int proxy_send(struct bt_conn *conn, const void *data,
+		      uint16_t len)
+{
+	struct bt_gatt_notify_params params = {
+		.data = data,
+		.len = len,
+		.func = notify_complete,
+	};
+	int err;
+
+	BT_DBG("%u bytes: %s", len, bt_hex(data, len));
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	if (gatt_svc == MESH_GATT_PROXY) {
+		params.attr = &proxy_attrs[3];
+	}
+#endif
+#if defined(CONFIG_BT_MESH_PB_GATT)
+	if (gatt_svc == MESH_GATT_PROV) {
+		params.attr = &prov_attrs[3];
+	}
+#endif
+
+	if (!params.attr) {
+		return 0;
+	}
+
+	err = bt_gatt_notify_cb(conn, &params);
+	if (!err) {
+		atomic_inc(&pending_notifications);
+	}
+
+	return err;
+}
+
+static int proxy_segment_and_send(struct bt_conn *conn, uint8_t type,
+				  struct net_buf_simple *msg)
+{
+	uint16_t mtu;
+
+	BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len,
+	       bt_hex(msg->data, msg->len));
+
+	/* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
+	mtu = bt_gatt_get_mtu(conn) - 3;
+	if (mtu > msg->len) {
+		net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
+		return proxy_send(conn, msg->data, msg->len);
+	}
+
+	net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
+	proxy_send(conn, msg->data, mtu);
+	net_buf_simple_pull(msg, mtu);
+
+	while (msg->len) {
+		if (msg->len + 1 < mtu) {
+			net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
+			proxy_send(conn, msg->data, msg->len);
+			break;
+		}
+
+		net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
+		proxy_send(conn, msg->data, mtu);
+		net_buf_simple_pull(msg, mtu);
+	}
+
+	return 0;
+}
+
+int bt_mesh_proxy_send(struct bt_conn *conn, uint8_t type,
+		       struct net_buf_simple *msg)
+{
+	struct bt_mesh_proxy_client *client = find_client(conn);
+
+	if (!client) {
+		BT_ERR("No Proxy Client found");
+		return -ENOTCONN;
+	}
+
+	if ((client->filter_type == PROV) != (type == BT_MESH_PROXY_PROV)) {
+		BT_ERR("Invalid PDU type for Proxy Client");
+		return -EINVAL;
+	}
+
+	return proxy_segment_and_send(conn, type, msg);
+}
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+static uint8_t prov_svc_data[20] = {
+	BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL),
+};
+
+static const struct bt_data prov_ad[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+		      BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)),
+	BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
+};
+#endif /* PB_GATT */
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+
+#define ID_TYPE_NET  0x00
+#define ID_TYPE_NODE 0x01
+
+#define NODE_ID_LEN  19
+#define NET_ID_LEN   11
+
+#define NODE_ID_TIMEOUT (CONFIG_BT_MESH_NODE_ID_TIMEOUT * MSEC_PER_SEC)
+
+static uint8_t proxy_svc_data[NODE_ID_LEN] = {
+	BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
+};
+
+static const struct bt_data node_id_ad[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+		      BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
+	BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
+};
+
+static const struct bt_data net_id_ad[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+		      BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
+	BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
+};
+
+static int node_id_adv(struct bt_mesh_subnet *sub)
+{
+	uint8_t tmp[16];
+	int err;
+
+	BT_DBG("");
+
+	proxy_svc_data[2] = ID_TYPE_NODE;
+
+	err = bt_rand(proxy_svc_data + 11, 8);
+	if (err) {
+		return err;
+	}
+
+	(void)memset(tmp, 0, 6);
+	memcpy(tmp + 6, proxy_svc_data + 11, 8);
+	sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
+
+	err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
+	if (err) {
+		return err;
+	}
+
+	memcpy(proxy_svc_data + 3, tmp + 8, 8);
+
+	err = bt_le_adv_start(&fast_adv_param, node_id_ad,
+			      ARRAY_SIZE(node_id_ad), NULL, 0);
+	if (err) {
+		BT_WARN("Failed to advertise using Node ID (err %d)", err);
+		return err;
+	}
+
+	proxy_adv_enabled = true;
+
+	return 0;
+}
+
+static int net_id_adv(struct bt_mesh_subnet *sub)
+{
+	int err;
+
+	BT_DBG("");
+
+	proxy_svc_data[2] = ID_TYPE_NET;
+
+	BT_DBG("Advertising with NetId %s",
+	       bt_hex(sub->keys[sub->kr_flag].net_id, 8));
+
+	memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
+
+	err = bt_le_adv_start(&slow_adv_param, net_id_ad,
+			      ARRAY_SIZE(net_id_ad), NULL, 0);
+	if (err) {
+		BT_WARN("Failed to advertise using Network ID (err %d)", err);
+		return err;
+	}
+
+	proxy_adv_enabled = true;
+
+	return 0;
+}
+
+static bool advertise_subnet(struct bt_mesh_subnet *sub)
+{
+	if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+		return false;
+	}
+
+	return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
+		bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
+}
+
+static struct bt_mesh_subnet *next_sub(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub;
+
+		sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
+		if (advertise_subnet(sub)) {
+			next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
+			return sub;
+		}
+	}
+
+	return NULL;
+}
+
+static int sub_count(void)
+{
+	int i, count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+
+		if (advertise_subnet(sub)) {
+			count++;
+		}
+	}
+
+	return count;
+}
+
+static k_timeout_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
+{
+	int32_t remaining = SYS_FOREVER_MS;
+	int subnet_count;
+
+	BT_DBG("");
+
+	if (conn_count == CONFIG_BT_MAX_CONN) {
+		BT_DBG("Connectable advertising deferred (max connections)");
+		return K_FOREVER;
+	}
+
+	if (!sub) {
+		BT_WARN("No subnets to advertise on");
+		return K_FOREVER;
+	}
+
+	if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
+		uint32_t active = k_uptime_get_32() - sub->node_id_start;
+
+		if (active < NODE_ID_TIMEOUT) {
+			remaining = NODE_ID_TIMEOUT - active;
+			BT_DBG("Node ID active for %u ms, %d ms remaining",
+			       active, remaining);
+			node_id_adv(sub);
+		} else {
+			bt_mesh_proxy_identity_stop(sub);
+			BT_DBG("Node ID stopped");
+		}
+	}
+
+	if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) {
+		net_id_adv(sub);
+	}
+
+	subnet_count = sub_count();
+	BT_DBG("sub_count %u", subnet_count);
+	if (subnet_count > 1) {
+		int32_t max_timeout;
+
+		/* We use NODE_ID_TIMEOUT as a starting point since it may
+		 * be less than 60 seconds. Divide this period into at least
+		 * 6 slices, but make sure that a slice is at least one
+		 * second long (to avoid excessive rotation).
+		 */
+		max_timeout = NODE_ID_TIMEOUT / MAX(subnet_count, 6);
+		max_timeout = MAX(max_timeout, 1 * MSEC_PER_SEC);
+
+		if (remaining > max_timeout || remaining == SYS_FOREVER_MS) {
+			remaining = max_timeout;
+		}
+	}
+
+	BT_DBG("Advertising %d ms for net_idx 0x%04x", remaining, sub->net_idx);
+
+	return SYS_TIMEOUT_MS(remaining);
+}
+#endif /* GATT_PROXY */
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
+{
+	const struct bt_mesh_prov *prov = bt_mesh_prov_get();
+	const char *name = bt_get_name();
+	size_t name_len = strlen(name);
+	size_t prov_sd_len = 0;
+	size_t sd_space = 31;
+
+	memcpy(prov_svc_data + 2, prov->uuid, 16);
+	sys_put_be16(prov->oob_info, prov_svc_data + 18);
+
+	if (prov->uri) {
+		size_t uri_len = strlen(prov->uri);
+
+		if (uri_len > 29) {
+			/* There's no way to shorten an URI */
+			BT_WARN("Too long URI to fit advertising packet");
+		} else {
+			prov_sd[0].type = BT_DATA_URI;
+			prov_sd[0].data_len = uri_len;
+			prov_sd[0].data = prov->uri;
+			sd_space -= 2 + uri_len;
+			prov_sd_len++;
+		}
+	}
+
+	if (sd_space > 2 && name_len > 0) {
+		sd_space -= 2;
+
+		if (sd_space < name_len) {
+			prov_sd[prov_sd_len].type = BT_DATA_NAME_SHORTENED;
+			prov_sd[prov_sd_len].data_len = sd_space;
+		} else {
+			prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE;
+			prov_sd[prov_sd_len].data_len = name_len;
+		}
+
+		prov_sd[prov_sd_len].data = name;
+		prov_sd_len++;
+	}
+
+	return prov_sd_len;
+}
+#endif /* CONFIG_BT_MESH_PB_GATT */
+
+k_timeout_t bt_mesh_proxy_adv_start(void)
+{
+	BT_DBG("");
+
+	if (gatt_svc == MESH_GATT_NONE) {
+		return K_FOREVER;
+	}
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+	if (!bt_mesh_is_provisioned()) {
+		const struct bt_le_adv_param *param;
+		struct bt_data prov_sd[2];
+		size_t prov_sd_len;
+
+		if (prov_fast_adv) {
+			param = &fast_adv_param;
+		} else {
+			param = &slow_adv_param;
+		}
+
+		prov_sd_len = gatt_prov_adv_create(prov_sd);
+
+		if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad),
+				    prov_sd, prov_sd_len) == 0) {
+			proxy_adv_enabled = true;
+
+			/* Advertise 60 seconds using fast interval */
+			if (prov_fast_adv) {
+				prov_fast_adv = false;
+				return K_SECONDS(60);
+			}
+		}
+	}
+#endif /* PB_GATT */
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	if (bt_mesh_is_provisioned()) {
+		return gatt_proxy_advertise(next_sub());
+	}
+#endif /* GATT_PROXY */
+
+	return K_FOREVER;
+}
+
+void bt_mesh_proxy_adv_stop(void)
+{
+	int err;
+
+	BT_DBG("adv_enabled %u", proxy_adv_enabled);
+
+	if (!proxy_adv_enabled) {
+		return;
+	}
+
+	err = bt_le_adv_stop();
+	if (err) {
+		BT_ERR("Failed to stop advertising (err %d)", err);
+	} else {
+		proxy_adv_enabled = false;
+	}
+}
+
+static struct bt_conn_cb conn_callbacks = {
+	.connected = proxy_connected,
+	.disconnected = proxy_disconnected,
+};
+
+int bt_mesh_proxy_init(void)
+{
+	int i;
+
+	/* Initialize the client receive buffers */
+	for (i = 0; i < ARRAY_SIZE(clients); i++) {
+		struct bt_mesh_proxy_client *client = &clients[i];
+
+		client->buf.size = CLIENT_BUF_SIZE;
+		client->buf.__buf = client_buf_data + (i * CLIENT_BUF_SIZE);
+
+		k_delayed_work_init(&client->sar_timer, proxy_sar_timeout);
+	}
+
+	bt_conn_cb_register(&conn_callbacks);
+
+	return 0;
+}
+
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb)
+{
+	if (!atomic_get(&pending_notifications)) {
+		cb->cb();
+		return;
+	}
+
+	sys_slist_append(&idle_waiters, &cb->n);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.h	(working copy)
@@ -0,0 +1,30 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_mesh_rpl {
+	uint16_t src;
+	bool  old_iv;
+#if defined(CONFIG_BT_SETTINGS)
+	bool  store;
+#endif
+	uint32_t seq;
+};
+
+typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
+					void *user_data);
+
+void bt_mesh_rpl_reset(void);
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+			struct bt_mesh_rpl **match);
+void bt_mesh_rpl_clear(void);
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src);
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src);
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data);
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+			struct bt_mesh_net_rx *rx);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/rpl.c	(working copy)
@@ -0,0 +1,175 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <sys/atomic.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_RPL)
+#define LOG_MODULE_NAME bt_mesh_rpl
+#include "common/log.h"
+
+#include "mesh.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+
+static struct bt_mesh_rpl replay_list[CONFIG_BT_MESH_CRPL];
+
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+		struct bt_mesh_net_rx *rx)
+{
+	rpl->src = rx->ctx.addr;
+	rpl->seq = rx->seq;
+	rpl->old_iv = rx->old_iv;
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_store_rpl(rpl);
+	}
+}
+
+/* Check the Replay Protection List for a replay attempt. If non-NULL match
+ * parameter is given the RPL slot is returned but it is not immediately
+ * updated (needed for segmented messages), whereas if a NULL match is given
+ * the RPL is immediately updated (used for unsegmented messages).
+ */
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+		struct bt_mesh_rpl **match)
+{
+	int i;
+
+	/* Don't bother checking messages from ourselves */
+	if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+		return false;
+	}
+
+	/* The RPL is used only for the local node */
+	if (!rx->local_match) {
+		return false;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+		struct bt_mesh_rpl *rpl = &replay_list[i];
+
+		/* Empty slot */
+		if (!rpl->src) {
+			if (match) {
+				*match = rpl;
+			} else {
+				bt_mesh_rpl_update(rpl, rx);
+			}
+
+			return false;
+		}
+
+		/* Existing slot for given address */
+		if (rpl->src == rx->ctx.addr) {
+			if (rx->old_iv && !rpl->old_iv) {
+				return true;
+			}
+
+			if ((!rx->old_iv && rpl->old_iv) ||
+			    rpl->seq < rx->seq) {
+				if (match) {
+					*match = rpl;
+				} else {
+					bt_mesh_rpl_update(rpl, rx);
+				}
+
+				return false;
+			} else {
+				return true;
+			}
+		}
+	}
+
+	BT_ERR("RPL is full!");
+	return true;
+}
+
+void bt_mesh_rpl_clear(void)
+{
+	BT_DBG("");
+
+	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+		bt_mesh_clear_rpl();
+	} else {
+		(void)memset(replay_list, 0, sizeof(replay_list));
+	}
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+		if (replay_list[i].src == src) {
+			return &replay_list[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+		if (!replay_list[i].src) {
+			replay_list[i].src = src;
+			return &replay_list[i];
+		}
+	}
+
+	return NULL;
+}
+
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+		func(&replay_list[i], user_data);
+	}
+}
+
+void bt_mesh_rpl_reset(void)
+{
+	int i;
+
+	/* Discard "old old" IV Index entries from RPL and flag
+	 * any other ones (which are valid) as old.
+	 */
+	for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+		struct bt_mesh_rpl *rpl = &replay_list[i];
+
+		if (rpl->src) {
+			if (rpl->old_iv) {
+				(void)memset(rpl, 0, sizeof(*rpl));
+			} else {
+				rpl->old_iv = true;
+			}
+
+			if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+				bt_mesh_store_rpl(rpl);
+			}
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.h	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_mesh_store_net(void);
+void bt_mesh_store_iv(bool only_duration);
+void bt_mesh_store_seq(void);
+void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl);
+void bt_mesh_store_subnet(struct bt_mesh_subnet *sub);
+void bt_mesh_store_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_store_hb_pub(void);
+void bt_mesh_store_cfg(void);
+void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
+void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
+void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
+void bt_mesh_store_label(void);
+void bt_mesh_store_cdb(void);
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node);
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app);
+
+void bt_mesh_clear_net(void);
+void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
+void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_clear_rpl(void);
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node);
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app);
+
+void bt_mesh_settings_init(void);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/settings.c	(working copy)
@@ -0,0 +1,2442 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <settings/settings.h>
+
+#include <net/buf.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_SETTINGS)
+#define LOG_MODULE_NAME bt_mesh_settings
+#include "common/log.h"
+
+#include "mesh.h"
+#include "net.h"
+#include "crypto.h"
+#include "rpl.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "settings.h"
+#include "lpn.h"
+
+/* Tracking of what storage changes are pending for App and Net Keys. We
+ * track this in a separate array here instead of within the respective
+ * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
+ * gets deleted its struct becomes invalid and may be reused for other keys.
+ */
+struct key_update {
+	uint16_t key_idx:12,    /* AppKey or NetKey Index */
+	      valid:1,       /* 1 if this entry is valid, 0 if not */
+	      app_key:1,     /* 1 if this is an AppKey, 0 if a NetKey */
+	      clear:1;       /* 1 if key needs clearing, 0 if storing */
+};
+
+static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT +
+				     CONFIG_BT_MESH_SUBNET_COUNT];
+
+static struct k_delayed_work pending_store;
+
+/* Mesh network storage information */
+struct net_val {
+	uint16_t primary_addr;
+	uint8_t  dev_key[16];
+} __packed;
+
+/* Sequence number storage */
+struct seq_val {
+	uint8_t val[3];
+} __packed;
+
+/* Heartbeat Publication storage */
+struct hb_pub_val {
+	uint16_t dst;
+	uint8_t  period;
+	uint8_t  ttl;
+	uint16_t feat;
+	uint16_t net_idx:12,
+	      indefinite:1;
+};
+
+/* Miscellaneous configuration server model states */
+struct cfg_val {
+	uint8_t net_transmit;
+	uint8_t relay;
+	uint8_t relay_retransmit;
+	uint8_t beacon;
+	uint8_t gatt_proxy;
+	uint8_t frnd;
+	uint8_t default_ttl;
+};
+
+/* IV Index & IV Update storage */
+struct iv_val {
+	uint32_t iv_index;
+	uint8_t  iv_update:1,
+	      iv_duration:7;
+} __packed;
+
+/* Replay Protection List storage */
+struct rpl_val {
+	uint32_t seq:24,
+	      old_iv:1;
+};
+
+/* NetKey storage information */
+struct net_key_val {
+	uint8_t kr_flag:1,
+	     kr_phase:7;
+	uint8_t val[2][16];
+} __packed;
+
+/* AppKey storage information */
+struct app_key_val {
+	uint16_t net_idx;
+	bool  updated;
+	uint8_t  val[2][16];
+} __packed;
+
+struct mod_pub_val {
+	uint16_t addr;
+	uint16_t key;
+	uint8_t  ttl;
+	uint8_t  retransmit;
+	uint8_t  period;
+	uint8_t  period_div:4,
+	      cred:1;
+};
+
+/* Virtual Address information */
+struct va_val {
+	uint16_t ref;
+	uint16_t addr;
+	uint8_t uuid[16];
+} __packed;
+
+struct cdb_net_val {
+	uint32_t iv_index;
+	bool  iv_update;
+} __packed;
+
+/* Node storage information */
+struct node_val {
+	uint16_t net_idx;
+	uint8_t  num_elem;
+	uint8_t  flags;
+#define F_NODE_CONFIGURED 0x01
+	uint8_t  uuid[16];
+	uint8_t  dev_key[16];
+} __packed;
+
+struct node_update {
+	uint16_t addr;
+	bool clear;
+};
+
+#if defined(CONFIG_BT_MESH_CDB)
+static struct node_update cdb_node_updates[CONFIG_BT_MESH_CDB_NODE_COUNT];
+static struct key_update cdb_key_updates[CONFIG_BT_MESH_CDB_SUBNET_COUNT +
+					 CONFIG_BT_MESH_CDB_APP_KEY_COUNT];
+#else
+static struct node_update cdb_node_updates[0];
+static struct key_update cdb_key_updates[0];
+#endif
+
+/* We need this so we don't overwrite app-hardcoded values in case FCB
+ * contains a history of changes but then has a NULL at the end.
+ */
+static struct {
+	bool valid;
+	struct cfg_val cfg;
+} stored_cfg;
+
+static inline int mesh_x_set(settings_read_cb read_cb, void *cb_arg, void *out,
+			     size_t read_len)
+{
+	ssize_t len;
+
+	len = read_cb(cb_arg, out, read_len);
+	if (len < 0) {
+		BT_ERR("Failed to read value (err %zd)", len);
+		return len;
+	}
+
+	BT_HEXDUMP_DBG(out, len, "val");
+
+	if (len != read_len) {
+		BT_ERR("Unexpected value length (%zd != %zu)", len, read_len);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int net_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		   void *cb_arg)
+{
+	struct net_val net;
+	int err;
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+
+		bt_mesh_comp_unprovision();
+		(void)memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &net, sizeof(net));
+	if (err) {
+		BT_ERR("Failed to set \'net\'");
+		return err;
+	}
+
+	memcpy(bt_mesh.dev_key, net.dev_key, sizeof(bt_mesh.dev_key));
+	bt_mesh_comp_provision(net.primary_addr);
+
+	BT_DBG("Provisioned with primary address 0x%04x", net.primary_addr);
+	BT_DBG("Recovered DevKey %s", bt_hex(bt_mesh.dev_key, 16));
+
+	return 0;
+}
+
+static int iv_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		  void *cb_arg)
+{
+	struct iv_val iv;
+	int err;
+
+	if (len_rd == 0) {
+		BT_DBG("IV deleted");
+
+		bt_mesh.iv_index = 0U;
+		atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &iv, sizeof(iv));
+	if (err) {
+		BT_ERR("Failed to set \'iv\'");
+		return err;
+	}
+
+	bt_mesh.iv_index = iv.iv_index;
+	atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv.iv_update);
+	bt_mesh.ivu_duration = iv.iv_duration;
+
+	BT_DBG("IV Index 0x%04x (IV Update Flag %u) duration %u hours",
+	       iv.iv_index, iv.iv_update, iv.iv_duration);
+
+	return 0;
+}
+
+static int seq_set(const char *name, size_t len_rd, settings_read_cb read_cb,
+		   void *cb_arg)
+{
+	struct seq_val seq;
+	int err;
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+
+		bt_mesh.seq = 0U;
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &seq, sizeof(seq));
+	if (err) {
+		BT_ERR("Failed to set \'seq\'");
+		return err;
+	}
+
+	bt_mesh.seq = sys_get_le24(seq.val);
+
+	if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) {
+		/* Make sure we have a large enough sequence number. We
+		 * subtract 1 so that the first transmission causes a write
+		 * to the settings storage.
+		 */
+		bt_mesh.seq += (CONFIG_BT_MESH_SEQ_STORE_RATE -
+				(bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE));
+		bt_mesh.seq--;
+	}
+
+	BT_DBG("Sequence Number 0x%06x", bt_mesh.seq);
+
+	return 0;
+}
+
+static int rpl_set(const char *name, size_t len_rd,
+		   settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_rpl *entry;
+	struct rpl_val rpl;
+	int err;
+	uint16_t src;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	src = strtol(name, NULL, 16);
+	entry = bt_mesh_rpl_find(src);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		if (entry) {
+			(void)memset(entry, 0, sizeof(*entry));
+		} else {
+			BT_WARN("Unable to find RPL entry for 0x%04x", src);
+		}
+
+		return 0;
+	}
+
+	if (!entry) {
+		entry = bt_mesh_rpl_alloc(src);
+		if (!entry) {
+			BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
+			return -ENOMEM;
+		}
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &rpl, sizeof(rpl));
+	if (err) {
+		BT_ERR("Failed to set `net`");
+		return err;
+	}
+
+	entry->seq = rpl.seq;
+	entry->old_iv = rpl.old_iv;
+
+	BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src,
+	       entry->seq, entry->old_iv);
+
+	return 0;
+}
+
+static int net_key_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_subnet *sub;
+	struct net_key_val key;
+	int i, err;
+	uint16_t net_idx;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	net_idx = strtol(name, NULL, 16);
+	sub = bt_mesh_subnet_get(net_idx);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		if (!sub) {
+			BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
+			return -ENOENT;
+		}
+
+		BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
+		bt_mesh_subnet_del(sub, false);
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to set \'net-key\'");
+		return err;
+	}
+
+	if (sub) {
+		BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
+
+		sub->kr_flag = key.kr_flag;
+		sub->kr_phase = key.kr_phase;
+		memcpy(sub->keys[0].net, &key.val[0], 16);
+		memcpy(sub->keys[1].net, &key.val[1], 16);
+
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
+			sub = &bt_mesh.sub[i];
+			break;
+		}
+	}
+
+	if (!sub) {
+		BT_ERR("No space to allocate a new subnet");
+		return -ENOMEM;
+	}
+
+	sub->net_idx = net_idx;
+	sub->kr_flag = key.kr_flag;
+	sub->kr_phase = key.kr_phase;
+	memcpy(sub->keys[0].net, &key.val[0], 16);
+	memcpy(sub->keys[1].net, &key.val[1], 16);
+
+	BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
+
+	return 0;
+}
+
+static int app_key_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_app_key *app;
+	struct app_key_val key;
+	uint16_t app_idx;
+	int err;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	app_idx = strtol(name, NULL, 16);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
+
+		app = bt_mesh_app_key_find(app_idx);
+		if (app) {
+			bt_mesh_app_key_del(app, false);
+		}
+
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to set \'app-key\'");
+		return err;
+	}
+
+	app = bt_mesh_app_key_find(app_idx);
+	if (!app) {
+		app = bt_mesh_app_key_alloc(app_idx);
+	}
+
+	if (!app) {
+		BT_ERR("No space for a new app key");
+		return -ENOMEM;
+	}
+
+	app->net_idx = key.net_idx;
+	app->app_idx = app_idx;
+	app->updated = key.updated;
+	memcpy(app->keys[0].val, key.val[0], 16);
+	memcpy(app->keys[1].val, key.val[1], 16);
+
+	bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
+	bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
+
+	BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
+
+	return 0;
+}
+
+static int hb_pub_set(const char *name, size_t len_rd,
+		      settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+	struct hb_pub_val hb_val;
+	int err;
+
+	if (!pub) {
+		return -ENOENT;
+	}
+
+	if (len_rd == 0) {
+		pub->dst = BT_MESH_ADDR_UNASSIGNED;
+		pub->count = 0U;
+		pub->ttl = 0U;
+		pub->period = 0U;
+		pub->feat = 0U;
+
+		BT_DBG("Cleared heartbeat publication");
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &hb_val, sizeof(hb_val));
+	if (err) {
+		BT_ERR("Failed to set \'hb_val\'");
+		return err;
+	}
+
+	pub->dst = hb_val.dst;
+	pub->period = hb_val.period;
+	pub->ttl = hb_val.ttl;
+	pub->feat = hb_val.feat;
+	pub->net_idx = hb_val.net_idx;
+
+	if (hb_val.indefinite) {
+		pub->count = 0xffff;
+	} else {
+		pub->count = 0U;
+	}
+
+	BT_DBG("Restored heartbeat publication");
+
+	return 0;
+}
+
+static int cfg_set(const char *name, size_t len_rd,
+		   settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+	int err;
+
+	if (!cfg) {
+		return -ENOENT;
+	}
+
+	if (len_rd == 0) {
+		stored_cfg.valid = false;
+		BT_DBG("Cleared configuration state");
+		return 0;
+	}
+
+
+	err = mesh_x_set(read_cb, cb_arg, &stored_cfg.cfg,
+			 sizeof(stored_cfg.cfg));
+	if (err) {
+		BT_ERR("Failed to set \'cfg\'");
+		return err;
+	}
+
+	stored_cfg.valid = true;
+	BT_DBG("Restored configuration state");
+
+	return 0;
+}
+
+static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd,
+			settings_read_cb read_cb, void *cb_arg)
+{
+	ssize_t len;
+	int i;
+
+	/* Start with empty array regardless of cleared or set value */
+	for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
+		mod->keys[i] = BT_MESH_KEY_UNUSED;
+	}
+
+	if (len_rd == 0) {
+		BT_DBG("Cleared bindings for model");
+		return 0;
+	}
+
+	len = read_cb(cb_arg, mod->keys, sizeof(mod->keys));
+	if (len < 0) {
+		BT_ERR("Failed to read value (err %zd)", len);
+		return len;
+	}
+
+
+	BT_DBG("Decoded %zu bound keys for model", len / sizeof(mod->keys[0]));
+	return 0;
+}
+
+static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	ssize_t len;
+
+	/* Start with empty array regardless of cleared or set value */
+	(void)memset(mod->groups, 0, sizeof(mod->groups));
+
+	if (len_rd == 0) {
+		BT_DBG("Cleared subscriptions for model");
+		return 0;
+	}
+
+	len = read_cb(cb_arg, mod->groups, sizeof(mod->groups));
+	if (len < 0) {
+		BT_ERR("Failed to read value (err %zd)", len);
+		return len;
+	}
+
+	BT_DBG("Decoded %zu subscribed group addresses for model",
+	       len / sizeof(mod->groups[0]));
+	return 0;
+}
+
+static int mod_set_pub(struct bt_mesh_model *mod, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	struct mod_pub_val pub;
+	int err;
+
+	if (!mod->pub) {
+		BT_WARN("Model has no publication context!");
+		return -EINVAL;
+	}
+
+	if (len_rd == 0) {
+		mod->pub->addr = BT_MESH_ADDR_UNASSIGNED;
+		mod->pub->key = 0U;
+		mod->pub->cred = 0U;
+		mod->pub->ttl = 0U;
+		mod->pub->period = 0U;
+		mod->pub->retransmit = 0U;
+		mod->pub->count = 0U;
+
+		BT_DBG("Cleared publication for model");
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &pub, sizeof(pub));
+	if (err) {
+		BT_ERR("Failed to set \'model-pub\'");
+		return err;
+	}
+
+	mod->pub->addr = pub.addr;
+	mod->pub->key = pub.key;
+	mod->pub->cred = pub.cred;
+	mod->pub->ttl = pub.ttl;
+	mod->pub->period = pub.period;
+	mod->pub->retransmit = pub.retransmit;
+	mod->pub->count = 0U;
+
+	BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x",
+	       pub.addr, pub.key);
+
+	return 0;
+}
+
+static int mod_data_set(struct bt_mesh_model *mod,
+			const char *name, size_t len_rd,
+			settings_read_cb read_cb, void *cb_arg)
+{
+	const char *next;
+
+	settings_name_next(name, &next);
+
+	if (mod->cb && mod->cb->settings_set) {
+		return mod->cb->settings_set(mod, next, len_rd,
+			read_cb, cb_arg);
+	}
+
+	return 0;
+}
+
+static int mod_set(bool vnd, const char *name, size_t len_rd,
+		   settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_model *mod;
+	uint8_t elem_idx, mod_idx;
+	uint16_t mod_key;
+	int len;
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	mod_key = strtol(name, NULL, 16);
+	elem_idx = mod_key >> 8;
+	mod_idx = mod_key;
+
+	BT_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u",
+	       mod_key, elem_idx, mod_idx);
+
+	mod = bt_mesh_model_get(vnd, elem_idx, mod_idx);
+	if (!mod) {
+		BT_ERR("Failed to get model for elem_idx %u mod_idx %u",
+		       elem_idx, mod_idx);
+		return -ENOENT;
+	}
+
+	len = settings_name_next(name, &next);
+
+	if (!next) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	if (!strncmp(next, "bind", len)) {
+		return mod_set_bind(mod, len_rd, read_cb, cb_arg);
+	}
+
+	if (!strncmp(next, "sub", len)) {
+		return mod_set_sub(mod, len_rd, read_cb, cb_arg);
+	}
+
+	if (!strncmp(next, "pub", len)) {
+		return mod_set_pub(mod, len_rd, read_cb, cb_arg);
+	}
+
+	if (!strncmp(next, "data", len)) {
+		return mod_data_set(mod, next, len_rd, read_cb, cb_arg);
+	}
+
+	BT_WARN("Unknown module key %s", next);
+	return -ENOENT;
+}
+
+static int sig_mod_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	return mod_set(false, name, len_rd, read_cb, cb_arg);
+}
+
+static int vnd_mod_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	return mod_set(true, name, len_rd, read_cb, cb_arg);
+}
+
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+static int va_set(const char *name, size_t len_rd,
+		  settings_read_cb read_cb, void *cb_arg)
+{
+	struct va_val va;
+	struct label *lab;
+	uint16_t index;
+	int err;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	index = strtol(name, NULL, 16);
+
+	if (len_rd == 0) {
+		BT_WARN("Mesh Virtual Address length = 0");
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &va, sizeof(va));
+	if (err) {
+		BT_ERR("Failed to set \'virtual address\'");
+		return err;
+	}
+
+	if (va.ref == 0) {
+		BT_WARN("Ignore Mesh Virtual Address ref = 0");
+		return 0;
+	}
+
+	lab = get_label(index);
+	if (lab == NULL) {
+		BT_WARN("Out of labels buffers");
+		return -ENOBUFS;
+	}
+
+	memcpy(lab->uuid, va.uuid, 16);
+	lab->addr = va.addr;
+	lab->ref = va.ref;
+
+	BT_DBG("Restored Virtual Address, addr 0x%04x ref 0x%04x",
+	       lab->addr, lab->ref);
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_BT_MESH_CDB)
+static int cdb_net_set(const char *name, size_t len_rd,
+		       settings_read_cb read_cb, void *cb_arg)
+{
+	struct cdb_net_val net;
+	int err;
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &net, sizeof(net));
+	if (err) {
+		BT_ERR("Failed to set \'cdb_net\'");
+		return err;
+	}
+
+	bt_mesh_cdb.iv_index = net.iv_index;
+
+	if (net.iv_update) {
+		atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
+	}
+
+	atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+	return 0;
+}
+
+static int cdb_node_set(const char *name, size_t len_rd,
+			settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_cdb_node *node;
+	struct node_val val;
+	uint16_t addr;
+	int err;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	addr = strtol(name, NULL, 16);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		BT_DBG("Deleting node 0x%04x", addr);
+
+		node = bt_mesh_cdb_node_get(addr);
+		if (node) {
+			bt_mesh_cdb_node_del(node, false);
+		}
+
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &val, sizeof(val));
+	if (err) {
+		BT_ERR("Failed to set \'node\'");
+		return err;
+	}
+
+	node = bt_mesh_cdb_node_get(addr);
+	if (!node) {
+		node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
+					      val.net_idx);
+	}
+
+	if (!node) {
+		BT_ERR("No space for a new node");
+		return -ENOMEM;
+	}
+
+	if (val.flags & F_NODE_CONFIGURED) {
+		atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
+	}
+
+	memcpy(node->uuid, val.uuid, 16);
+	memcpy(node->dev_key, val.dev_key, 16);
+
+	BT_DBG("Node 0x%04x recovered from storage", addr);
+
+	return 0;
+}
+
+static int cdb_subnet_set(const char *name, size_t len_rd,
+			  settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_cdb_subnet *sub;
+	struct net_key_val key;
+	uint16_t net_idx;
+	int err;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	net_idx = strtol(name, NULL, 16);
+	sub = bt_mesh_cdb_subnet_get(net_idx);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		if (!sub) {
+			BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
+			return -ENOENT;
+		}
+
+		BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
+		bt_mesh_cdb_subnet_del(sub, false);
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to set \'net-key\'");
+		return err;
+	}
+
+	if (sub) {
+		BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
+
+		sub->kr_flag = key.kr_flag;
+		sub->kr_phase = key.kr_phase;
+		memcpy(sub->keys[0].net_key, &key.val[0], 16);
+		memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+		return 0;
+	}
+
+	sub = bt_mesh_cdb_subnet_alloc(net_idx);
+	if (!sub) {
+		BT_ERR("No space to allocate a new subnet");
+		return -ENOMEM;
+	}
+
+	sub->kr_flag = key.kr_flag;
+	sub->kr_phase = key.kr_phase;
+	memcpy(sub->keys[0].net_key, &key.val[0], 16);
+	memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+	BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
+
+	return 0;
+}
+
+static int cdb_app_key_set(const char *name, size_t len_rd,
+			   settings_read_cb read_cb, void *cb_arg)
+{
+	struct bt_mesh_cdb_app_key *app;
+	struct app_key_val key;
+	uint16_t app_idx;
+	int err;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	app_idx = strtol(name, NULL, 16);
+
+	if (len_rd == 0) {
+		BT_DBG("val (null)");
+		BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
+
+		app = bt_mesh_cdb_app_key_get(app_idx);
+		if (app) {
+			bt_mesh_cdb_app_key_del(app, false);
+		}
+
+		return 0;
+	}
+
+	err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to set \'app-key\'");
+		return err;
+	}
+
+	app = bt_mesh_cdb_app_key_get(app_idx);
+	if (!app) {
+		app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
+	}
+
+	if (!app) {
+		BT_ERR("No space for a new app key");
+		return -ENOMEM;
+	}
+
+	memcpy(app->keys[0].app_key, key.val[0], 16);
+	memcpy(app->keys[1].app_key, key.val[1], 16);
+
+	BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
+
+	return 0;
+}
+
+static int cdb_set(const char *name, size_t len_rd,
+		   settings_read_cb read_cb, void *cb_arg)
+{
+	int len;
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	if (!strcmp(name, "Net")) {
+		return cdb_net_set(name, len_rd, read_cb, cb_arg);
+	}
+
+
+	len = settings_name_next(name, &next);
+
+	if (!next) {
+		BT_ERR("Insufficient number of arguments");
+		return -ENOENT;
+	}
+
+	if (!strncmp(name, "Node", len)) {
+		return cdb_node_set(next, len_rd, read_cb, cb_arg);
+	}
+
+	if (!strncmp(name, "Subnet", len)) {
+		return cdb_subnet_set(next, len_rd, read_cb, cb_arg);
+	}
+
+	if (!strncmp(name, "AppKey", len)) {
+		return cdb_app_key_set(next, len_rd, read_cb, cb_arg);
+	}
+
+	BT_WARN("Unknown module key %s", name);
+	return -ENOENT;
+}
+#endif
+
+const struct mesh_setting {
+	const char *name;
+	int (*func)(const char *name, size_t len_rd,
+		    settings_read_cb read_cb, void *cb_arg);
+} settings[] = {
+	{ "Net", net_set },
+	{ "IV", iv_set },
+	{ "Seq", seq_set },
+	{ "RPL", rpl_set },
+	{ "NetKey", net_key_set },
+	{ "AppKey", app_key_set },
+	{ "HBPub", hb_pub_set },
+	{ "Cfg", cfg_set },
+	{ "s", sig_mod_set },
+	{ "v", vnd_mod_set },
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+	{ "Va", va_set },
+#endif
+#if defined(CONFIG_BT_MESH_CDB)
+	{ "cdb", cdb_set },
+#endif
+};
+
+static int mesh_set(const char *name, size_t len_rd,
+		    settings_read_cb read_cb, void *cb_arg)
+{
+	int i, len;
+	const char *next;
+
+	if (!name) {
+		BT_ERR("Insufficient number of arguments");
+		return -EINVAL;
+	}
+
+	len = settings_name_next(name, &next);
+
+	for (i = 0; i < ARRAY_SIZE(settings); i++) {
+		if (!strncmp(settings[i].name, name, len)) {
+			return settings[i].func(next, len_rd, read_cb, cb_arg);
+		}
+	}
+
+	BT_WARN("No matching handler for key %s", log_strdup(name));
+
+	return -ENOENT;
+}
+
+static int subnet_init(struct bt_mesh_subnet *sub)
+{
+	int err;
+
+	err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net);
+	if (err) {
+		BT_ERR("Unable to generate keys for subnet");
+		return -EIO;
+	}
+
+	if (sub->kr_phase != BT_MESH_KR_NORMAL) {
+		err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net);
+		if (err) {
+			BT_ERR("Unable to generate keys for subnet");
+			(void)memset(&sub->keys[0], 0, sizeof(sub->keys[0]));
+			return -EIO;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+		sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+	} else {
+		sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+	}
+
+	/* Make sure we have valid beacon data to be sent */
+	bt_mesh_net_beacon_update(sub);
+
+	return 0;
+}
+
+static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+		       bool vnd, bool primary, void *user_data)
+{
+	if (mod->pub && mod->pub->update &&
+	    mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
+		int32_t ms = bt_mesh_model_pub_period_get(mod);
+
+		if (ms > 0) {
+			BT_DBG("Starting publish timer (period %u ms)", ms);
+			k_delayed_work_submit(&mod->pub->timer, K_MSEC(ms));
+		}
+	}
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+		return;
+	}
+
+	for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) {
+		if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+			bt_mesh_lpn_group_add(mod->groups[i]);
+		}
+	}
+}
+
+static int mesh_commit(void)
+{
+	struct bt_mesh_hb_pub *hb_pub;
+	struct bt_mesh_cfg_srv *cfg;
+	int i;
+
+	BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
+
+	if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) {
+		/* Nothing to do since we're not yet provisioned */
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+		bt_mesh_proxy_prov_disable(true);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
+		struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+		int err;
+
+		if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		err = subnet_init(sub);
+		if (err) {
+			BT_ERR("Failed to init subnet 0x%03x", sub->net_idx);
+		}
+	}
+
+	if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
+		k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
+	}
+
+	bt_mesh_model_foreach(commit_mod, NULL);
+
+	hb_pub = bt_mesh_hb_pub_get();
+	if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
+	    hb_pub->count && hb_pub->period) {
+		BT_DBG("Starting heartbeat publication");
+		k_work_submit(&hb_pub->timer.work);
+	}
+
+	cfg = bt_mesh_cfg_get();
+	if (cfg && stored_cfg.valid) {
+		cfg->net_transmit = stored_cfg.cfg.net_transmit;
+		cfg->relay = stored_cfg.cfg.relay;
+		cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
+		cfg->beacon = stored_cfg.cfg.beacon;
+		cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
+		cfg->frnd = stored_cfg.cfg.frnd;
+		cfg->default_ttl = stored_cfg.cfg.default_ttl;
+	}
+
+	atomic_set_bit(bt_mesh.flags, BT_MESH_VALID);
+
+	bt_mesh_start();
+
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_mesh, "bt/mesh", NULL, mesh_set, mesh_commit,
+			       NULL);
+
+/* Pending flags that use K_NO_WAIT as the storage timeout */
+#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_NET_PENDING) |           \
+			      BIT(BT_MESH_IV_PENDING) |            \
+			      BIT(BT_MESH_SEQ_PENDING))
+
+/* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */
+#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) |          \
+			      BIT(BT_MESH_HB_PUB_PENDING) |        \
+			      BIT(BT_MESH_CFG_PENDING) |           \
+			      BIT(BT_MESH_MOD_PENDING))
+
+static void schedule_store(int flag)
+{
+	int32_t timeout_ms, remaining;
+
+	atomic_set_bit(bt_mesh.flags, flag);
+
+	if (atomic_get(bt_mesh.flags) & NO_WAIT_PENDING_BITS) {
+		timeout_ms = 0;
+	} else if (atomic_test_bit(bt_mesh.flags, BT_MESH_RPL_PENDING) &&
+		   (!(atomic_get(bt_mesh.flags) & GENERIC_PENDING_BITS) ||
+		    (CONFIG_BT_MESH_RPL_STORE_TIMEOUT <
+		     CONFIG_BT_MESH_STORE_TIMEOUT))) {
+		timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC;
+	} else {
+		timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC;
+	}
+
+	remaining = k_delayed_work_remaining_get(&pending_store);
+	if ((remaining > 0) && remaining < timeout_ms) {
+		BT_DBG("Not rescheduling due to existing earlier deadline");
+		return;
+	}
+
+	BT_DBG("Waiting %d seconds", timeout_ms / MSEC_PER_SEC);
+
+	k_delayed_work_submit(&pending_store, K_MSEC(timeout_ms));
+}
+
+static void clear_iv(void)
+{
+	int err;
+
+	err = settings_delete("bt/mesh/IV");
+	if (err) {
+		BT_ERR("Failed to clear IV");
+	} else {
+		BT_DBG("Cleared IV");
+	}
+}
+
+static void clear_net(void)
+{
+	int err;
+
+	err = settings_delete("bt/mesh/Net");
+	if (err) {
+		BT_ERR("Failed to clear Network");
+	} else {
+		BT_DBG("Cleared Network");
+	}
+}
+
+static void store_pending_net(void)
+{
+	struct net_val net;
+	int err;
+
+	BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(),
+	       bt_hex(bt_mesh.dev_key, 16));
+
+	net.primary_addr = bt_mesh_primary_addr();
+	memcpy(net.dev_key, bt_mesh.dev_key, 16);
+
+	err = settings_save_one("bt/mesh/Net", &net, sizeof(net));
+	if (err) {
+		BT_ERR("Failed to store Network value");
+	} else {
+		BT_DBG("Stored Network value");
+	}
+}
+
+void bt_mesh_store_net(void)
+{
+	schedule_store(BT_MESH_NET_PENDING);
+}
+
+static void store_pending_iv(void)
+{
+	struct iv_val iv;
+	int err;
+
+	iv.iv_index = bt_mesh.iv_index;
+	iv.iv_update = atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
+	iv.iv_duration = bt_mesh.ivu_duration;
+
+	err = settings_save_one("bt/mesh/IV", &iv, sizeof(iv));
+	if (err) {
+		BT_ERR("Failed to store IV value");
+	} else {
+		BT_DBG("Stored IV value");
+	}
+}
+
+void bt_mesh_store_iv(bool only_duration)
+{
+	schedule_store(BT_MESH_IV_PENDING);
+
+	if (!only_duration) {
+		/* Always update Seq whenever IV changes */
+		schedule_store(BT_MESH_SEQ_PENDING);
+	}
+}
+
+static void store_pending_seq(void)
+{
+	struct seq_val seq;
+	int err;
+
+	sys_put_le24(bt_mesh.seq, seq.val);
+
+	err = settings_save_one("bt/mesh/Seq", &seq, sizeof(seq));
+	if (err) {
+		BT_ERR("Failed to stor Seq value");
+	} else {
+		BT_DBG("Stored Seq value");
+	}
+}
+
+void bt_mesh_store_seq(void)
+{
+	if (CONFIG_BT_MESH_SEQ_STORE_RATE &&
+	    (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) {
+		return;
+	}
+
+	schedule_store(BT_MESH_SEQ_PENDING);
+}
+
+static void store_rpl(struct bt_mesh_rpl *entry)
+{
+	struct rpl_val rpl;
+	char path[18];
+	int err;
+
+	BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, entry->seq,
+	       entry->old_iv);
+
+	rpl.seq = entry->seq;
+	rpl.old_iv = entry->old_iv;
+
+	snprintk(path, sizeof(path), "bt/mesh/RPL/%x", entry->src);
+
+	err = settings_save_one(path, &rpl, sizeof(rpl));
+	if (err) {
+		BT_ERR("Failed to store RPL %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored RPL %s value", log_strdup(path));
+	}
+}
+
+static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
+{
+	int err;
+	char path[18];
+
+	if (!rpl->src) {
+		return;
+	}
+
+	snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear RPL");
+	} else {
+		BT_DBG("Cleared RPL");
+	}
+
+	(void)memset(rpl, 0, sizeof(*rpl));
+}
+
+static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
+{
+	BT_DBG("");
+
+	if (rpl->store) {
+		rpl->store = false;
+		store_rpl(rpl);
+	}
+}
+
+static void store_pending_hb_pub(void)
+{
+	struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+	struct hb_pub_val val;
+	int err;
+
+	if (!pub) {
+		return;
+	}
+
+	if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+		err = settings_delete("bt/mesh/HBPub");
+	} else {
+		val.indefinite = (pub->count == 0xffff);
+		val.dst = pub->dst;
+		val.period = pub->period;
+		val.ttl = pub->ttl;
+		val.feat = pub->feat;
+		val.net_idx = pub->net_idx;
+
+		err = settings_save_one("bt/mesh/HBPub", &val, sizeof(val));
+	}
+
+	if (err) {
+		BT_ERR("Failed to store Heartbeat Publication");
+	} else {
+		BT_DBG("Stored Heartbeat Publication");
+	}
+}
+
+static void store_pending_cfg(void)
+{
+	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+	struct cfg_val val;
+	int err;
+
+	if (!cfg) {
+		return;
+	}
+
+	val.net_transmit = cfg->net_transmit;
+	val.relay = cfg->relay;
+	val.relay_retransmit = cfg->relay_retransmit;
+	val.beacon = cfg->beacon;
+	val.gatt_proxy = cfg->gatt_proxy;
+	val.frnd = cfg->frnd;
+	val.default_ttl = cfg->default_ttl;
+
+	err = settings_save_one("bt/mesh/Cfg", &val, sizeof(val));
+	if (err) {
+		BT_ERR("Failed to store configuration value");
+	} else {
+		BT_DBG("Stored configuration value");
+		BT_HEXDUMP_DBG(&val, sizeof(val), "raw value");
+	}
+}
+
+static void clear_cfg(void)
+{
+	int err;
+
+	err = settings_delete("bt/mesh/Cfg");
+	if (err) {
+		BT_ERR("Failed to clear configuration");
+	} else {
+		BT_DBG("Cleared configuration");
+	}
+}
+
+static void clear_app_key(uint16_t app_idx)
+{
+	char path[20];
+	int err;
+
+	snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
+	} else {
+		BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
+	}
+}
+
+static void clear_net_key(uint16_t net_idx)
+{
+	char path[20];
+	int err;
+
+	BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+	snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", net_idx);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
+	} else {
+		BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
+	}
+}
+
+static void store_net_key(struct bt_mesh_subnet *sub)
+{
+	struct net_key_val key;
+	char path[20];
+	int err;
+
+	BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
+	       bt_hex(sub->keys[0].net, 16));
+
+	memcpy(&key.val[0], sub->keys[0].net, 16);
+	memcpy(&key.val[1], sub->keys[1].net, 16);
+	key.kr_flag = sub->kr_flag;
+	key.kr_phase = sub->kr_phase;
+
+	snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", sub->net_idx);
+
+	err = settings_save_one(path, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to store NetKey value");
+	} else {
+		BT_DBG("Stored NetKey value");
+	}
+}
+
+static void store_app_key(struct bt_mesh_app_key *app)
+{
+	struct app_key_val key;
+	char path[20];
+	int err;
+
+	key.net_idx = app->net_idx;
+	key.updated = app->updated;
+	memcpy(key.val[0], app->keys[0].val, 16);
+	memcpy(key.val[1], app->keys[1].val, 16);
+
+	snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app->app_idx);
+
+	err = settings_save_one(path, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to store AppKey %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored AppKey %s value", log_strdup(path));
+	}
+}
+
+static void store_pending_keys(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(key_updates); i++) {
+		struct key_update *update = &key_updates[i];
+
+		if (!update->valid) {
+			continue;
+		}
+
+		if (update->clear) {
+			if (update->app_key) {
+				clear_app_key(update->key_idx);
+			} else {
+				clear_net_key(update->key_idx);
+			}
+		} else {
+			if (update->app_key) {
+				struct bt_mesh_app_key *key;
+
+				key = bt_mesh_app_key_find(update->key_idx);
+				if (key) {
+					store_app_key(key);
+				} else {
+					BT_WARN("AppKeyIndex 0x%03x not found",
+					       update->key_idx);
+				}
+
+			} else {
+				struct bt_mesh_subnet *sub;
+
+				sub = bt_mesh_subnet_get(update->key_idx);
+				if (sub) {
+					store_net_key(sub);
+				} else {
+					BT_WARN("NetKeyIndex 0x%03x not found",
+					       update->key_idx);
+				}
+			}
+		}
+
+		update->valid = 0U;
+	}
+}
+
+static void clear_cdb(void)
+{
+	int err;
+
+	err = settings_delete("bt/mesh/cdb/Net");
+	if (err) {
+		BT_ERR("Failed to clear Network");
+	} else {
+		BT_DBG("Cleared Network");
+	}
+}
+
+static void store_pending_cdb(void)
+{
+	struct cdb_net_val net;
+	int err;
+
+	BT_DBG("");
+
+	net.iv_index = bt_mesh_cdb.iv_index;
+	net.iv_update = atomic_test_bit(bt_mesh_cdb.flags,
+					BT_MESH_CDB_IVU_IN_PROGRESS);
+
+	err = settings_save_one("bt/mesh/cdb/Net", &net, sizeof(net));
+	if (err) {
+		BT_ERR("Failed to store Network value");
+	} else {
+		BT_DBG("Stored Network value");
+	}
+}
+
+static void store_cdb_node(const struct bt_mesh_cdb_node *node)
+{
+	struct node_val val;
+	char path[30];
+	int err;
+
+	val.net_idx = node->net_idx;
+	val.num_elem = node->num_elem;
+	val.flags = 0;
+
+	if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
+		val.flags |= F_NODE_CONFIGURED;
+	}
+
+	memcpy(val.uuid, node->uuid, 16);
+	memcpy(val.dev_key, node->dev_key, 16);
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
+
+	err = settings_save_one(path, &val, sizeof(val));
+	if (err) {
+		BT_ERR("Failed to store Node %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored Node %s value", log_strdup(path));
+	}
+}
+
+static void clear_cdb_node(uint16_t addr)
+{
+	char path[30];
+	int err;
+
+	BT_DBG("Node 0x%04x", addr);
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear Node 0x%04x", addr);
+	} else {
+		BT_DBG("Cleared Node 0x%04x", addr);
+	}
+}
+
+static void store_pending_cdb_nodes(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
+		struct node_update *update = &cdb_node_updates[i];
+
+		if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
+
+		if (update->clear) {
+			clear_cdb_node(update->addr);
+		} else {
+			struct bt_mesh_cdb_node *node;
+
+			node = bt_mesh_cdb_node_get(update->addr);
+			if (node) {
+				store_cdb_node(node);
+			} else {
+				BT_WARN("Node 0x%04x not found", update->addr);
+			}
+		}
+
+		update->addr = BT_MESH_ADDR_UNASSIGNED;
+	}
+}
+
+static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+	struct net_key_val key;
+	char path[30];
+	int err;
+
+	BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
+	       bt_hex(sub->keys[0].net_key, 16));
+
+	memcpy(&key.val[0], sub->keys[0].net_key, 16);
+	memcpy(&key.val[1], sub->keys[1].net_key, 16);
+	key.kr_flag = sub->kr_flag;
+	key.kr_phase = sub->kr_phase;
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
+
+	err = settings_save_one(path, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to store Subnet value");
+	} else {
+		BT_DBG("Stored Subnet value");
+	}
+}
+
+static void clear_cdb_subnet(uint16_t net_idx)
+{
+	char path[30];
+	int err;
+
+	BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
+	} else {
+		BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
+	}
+}
+
+static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
+{
+	struct app_key_val key;
+	char path[30];
+	int err;
+
+	key.net_idx = app->net_idx;
+	key.updated = false;
+	memcpy(key.val[0], app->keys[0].app_key, 16);
+	memcpy(key.val[1], app->keys[1].app_key, 16);
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
+
+	err = settings_save_one(path, &key, sizeof(key));
+	if (err) {
+		BT_ERR("Failed to store AppKey %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored AppKey %s value", log_strdup(path));
+	}
+}
+
+static void clear_cdb_app_key(uint16_t app_idx)
+{
+	char path[30];
+	int err;
+
+	snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
+	err = settings_delete(path);
+	if (err) {
+		BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
+	} else {
+		BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
+	}
+}
+
+static void store_pending_cdb_keys(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+		struct key_update *update = &cdb_key_updates[i];
+
+		if (!update->valid) {
+			continue;
+		}
+
+		if (update->clear) {
+			if (update->app_key) {
+				clear_cdb_app_key(update->key_idx);
+			} else {
+				clear_cdb_subnet(update->key_idx);
+			}
+		} else {
+			if (update->app_key) {
+				struct bt_mesh_cdb_app_key *key;
+
+				key = bt_mesh_cdb_app_key_get(update->key_idx);
+				if (key) {
+					store_cdb_app_key(key);
+				} else {
+					BT_WARN("AppKeyIndex 0x%03x not found",
+						update->key_idx);
+				}
+			} else {
+				struct bt_mesh_cdb_subnet *sub;
+
+				sub = bt_mesh_cdb_subnet_get(update->key_idx);
+				if (sub) {
+					store_cdb_subnet(sub);
+				} else {
+					BT_WARN("NetKeyIndex 0x%03x not found",
+						update->key_idx);
+				}
+			}
+		}
+
+		update->valid = 0U;
+	}
+}
+
+static struct node_update *cdb_node_update_find(uint16_t addr,
+					       struct node_update **free_slot)
+{
+	struct node_update *match;
+	int i;
+
+	match = NULL;
+	*free_slot = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
+		struct node_update *update = &cdb_node_updates[i];
+
+		if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
+			*free_slot = update;
+			continue;
+		}
+
+		if (update->addr == addr) {
+			match = update;
+		}
+	}
+
+	return match;
+}
+
+static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
+			    const char *key, char *path, size_t path_len)
+{
+	uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx);
+
+	if (vnd) {
+		snprintk(path, path_len, "bt/mesh/v/%x/%s", mod_key, key);
+	} else {
+		snprintk(path, path_len, "bt/mesh/s/%x/%s", mod_key, key);
+	}
+}
+
+static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
+{
+	uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+	char path[20];
+	int i, count, err;
+
+	for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) {
+		if (mod->keys[i] != BT_MESH_KEY_UNUSED) {
+			keys[count++] = mod->keys[i];
+			BT_DBG("model key 0x%04x", mod->keys[i]);
+		}
+	}
+
+	encode_mod_path(mod, vnd, "bind", path, sizeof(path));
+
+	if (count) {
+		err = settings_save_one(path, keys, count * sizeof(keys[0]));
+	} else {
+		err = settings_delete(path);
+	}
+
+	if (err) {
+		BT_ERR("Failed to store %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored %s value", log_strdup(path));
+	}
+}
+
+static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
+{
+	uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+	char path[20];
+	int i, count, err;
+
+	for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) {
+		if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+			groups[count++] = mod->groups[i];
+		}
+	}
+
+	encode_mod_path(mod, vnd, "sub", path, sizeof(path));
+
+	if (count) {
+		err = settings_save_one(path, groups,
+					count * sizeof(groups[0]));
+	} else {
+		err = settings_delete(path);
+	}
+
+	if (err) {
+		BT_ERR("Failed to store %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored %s value", log_strdup(path));
+	}
+}
+
+static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd)
+{
+	struct mod_pub_val pub;
+	char path[20];
+	int err;
+
+	encode_mod_path(mod, vnd, "pub", path, sizeof(path));
+
+	if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
+		err = settings_delete(path);
+	} else {
+		pub.addr = mod->pub->addr;
+		pub.key = mod->pub->key;
+		pub.ttl = mod->pub->ttl;
+		pub.retransmit = mod->pub->retransmit;
+		pub.period = mod->pub->period;
+		pub.period_div = mod->pub->period_div;
+		pub.cred = mod->pub->cred;
+
+		err = settings_save_one(path, &pub, sizeof(pub));
+	}
+
+	if (err) {
+		BT_ERR("Failed to store %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored %s value", log_strdup(path));
+	}
+}
+
+static void store_pending_mod(struct bt_mesh_model *mod,
+			      struct bt_mesh_elem *elem, bool vnd,
+			      bool primary, void *user_data)
+{
+	if (!mod->flags) {
+		return;
+	}
+
+	if (mod->flags & BT_MESH_MOD_BIND_PENDING) {
+		mod->flags &= ~BT_MESH_MOD_BIND_PENDING;
+		store_pending_mod_bind(mod, vnd);
+	}
+
+	if (mod->flags & BT_MESH_MOD_SUB_PENDING) {
+		mod->flags &= ~BT_MESH_MOD_SUB_PENDING;
+		store_pending_mod_sub(mod, vnd);
+	}
+
+	if (mod->flags & BT_MESH_MOD_PUB_PENDING) {
+		mod->flags &= ~BT_MESH_MOD_PUB_PENDING;
+		store_pending_mod_pub(mod, vnd);
+	}
+}
+
+#define IS_VA_DEL(_label)	((_label)->ref == 0)
+static void store_pending_va(void)
+{
+	struct label *lab;
+	struct va_val va;
+	char path[18];
+	uint16_t i;
+	int err;
+
+	for (i = 0; (lab = get_label(i)) != NULL; i++) {
+		if (!atomic_test_and_clear_bit(lab->flags,
+					       BT_MESH_VA_CHANGED)) {
+			continue;
+		}
+
+		snprintk(path, sizeof(path), "bt/mesh/Va/%x", i);
+
+		if (IS_VA_DEL(lab)) {
+			err = settings_delete(path);
+		} else {
+			va.ref = lab->ref;
+			va.addr = lab->addr;
+			memcpy(va.uuid, lab->uuid, 16);
+
+			err = settings_save_one(path, &va, sizeof(va));
+		}
+
+		if (err) {
+			BT_ERR("Failed to %s %s value (err %d)",
+			       IS_VA_DEL(lab) ? "delete" : "store",
+			       log_strdup(path), err);
+		} else {
+			BT_DBG("%s %s value",
+			       IS_VA_DEL(lab) ? "Deleted" : "Stored",
+			       log_strdup(path));
+		}
+	}
+}
+
+static void store_pending(struct k_work *work)
+{
+	BT_DBG("");
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
+		if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+			bt_mesh_rpl_foreach(store_pending_rpl, NULL);
+		} else {
+			bt_mesh_rpl_foreach(clear_rpl, NULL);
+		}
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_KEYS_PENDING)) {
+		store_pending_keys();
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NET_PENDING)) {
+		if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+			store_pending_net();
+		} else {
+			clear_net();
+		}
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IV_PENDING)) {
+		if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+			store_pending_iv();
+		} else {
+			clear_iv();
+		}
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SEQ_PENDING)) {
+		store_pending_seq();
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_HB_PUB_PENDING)) {
+		store_pending_hb_pub();
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_CFG_PENDING)) {
+		if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+			store_pending_cfg();
+		} else {
+			clear_cfg();
+		}
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_MOD_PENDING)) {
+		bt_mesh_model_foreach(store_pending_mod, NULL);
+	}
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_VA_PENDING)) {
+		store_pending_va();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+					      BT_MESH_CDB_SUBNET_PENDING)) {
+			if (atomic_test_bit(bt_mesh_cdb.flags,
+					    BT_MESH_CDB_VALID)) {
+				store_pending_cdb();
+			} else {
+				clear_cdb();
+			}
+		}
+
+		if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+					      BT_MESH_CDB_NODES_PENDING)) {
+			store_pending_cdb_nodes();
+		}
+
+		if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+					      BT_MESH_CDB_KEYS_PENDING)) {
+			store_pending_cdb_keys();
+		}
+	}
+}
+
+void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
+{
+	entry->store = true;
+	schedule_store(BT_MESH_RPL_PENDING);
+}
+
+static struct key_update *key_update_find(bool app_key, uint16_t key_idx,
+					  struct key_update **free_slot)
+{
+	struct key_update *match;
+	int i;
+
+	match = NULL;
+	*free_slot = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(key_updates); i++) {
+		struct key_update *update = &key_updates[i];
+
+		if (!update->valid) {
+			*free_slot = update;
+			continue;
+		}
+
+		if (update->app_key != app_key) {
+			continue;
+		}
+
+		if (update->key_idx == key_idx) {
+			match = update;
+		}
+	}
+
+	return match;
+}
+
+void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+	update = key_update_find(false, sub->net_idx, &free_slot);
+	if (update) {
+		update->clear = 0U;
+		schedule_store(BT_MESH_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		store_net_key(sub);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = sub->net_idx;
+	free_slot->app_key = 0U;
+	free_slot->clear = 0U;
+
+	schedule_store(BT_MESH_KEYS_PENDING);
+}
+
+void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+	update = key_update_find(true, key->app_idx, &free_slot);
+	if (update) {
+		update->clear = 0U;
+		schedule_store(BT_MESH_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		store_app_key(key);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = key->app_idx;
+	free_slot->app_key = 1U;
+	free_slot->clear = 0U;
+
+	schedule_store(BT_MESH_KEYS_PENDING);
+}
+
+void bt_mesh_store_hb_pub(void)
+{
+	schedule_store(BT_MESH_HB_PUB_PENDING);
+}
+
+void bt_mesh_store_cfg(void)
+{
+	schedule_store(BT_MESH_CFG_PENDING);
+}
+
+void bt_mesh_clear_net(void)
+{
+	schedule_store(BT_MESH_NET_PENDING);
+	schedule_store(BT_MESH_IV_PENDING);
+	schedule_store(BT_MESH_CFG_PENDING);
+}
+
+void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+	update = key_update_find(false, sub->net_idx, &free_slot);
+	if (update) {
+		update->clear = 1U;
+		schedule_store(BT_MESH_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		clear_net_key(sub->net_idx);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = sub->net_idx;
+	free_slot->app_key = 0U;
+	free_slot->clear = 1U;
+
+	schedule_store(BT_MESH_KEYS_PENDING);
+}
+
+void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+	update = key_update_find(true, key->app_idx, &free_slot);
+	if (update) {
+		update->clear = 1U;
+		schedule_store(BT_MESH_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		clear_app_key(key->app_idx);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = key->app_idx;
+	free_slot->app_key = 1U;
+	free_slot->clear = 1U;
+
+	schedule_store(BT_MESH_KEYS_PENDING);
+}
+
+void bt_mesh_clear_rpl(void)
+{
+	schedule_store(BT_MESH_RPL_PENDING);
+}
+
+void bt_mesh_store_mod_bind(struct bt_mesh_model *mod)
+{
+	mod->flags |= BT_MESH_MOD_BIND_PENDING;
+	schedule_store(BT_MESH_MOD_PENDING);
+}
+
+void bt_mesh_store_mod_sub(struct bt_mesh_model *mod)
+{
+	mod->flags |= BT_MESH_MOD_SUB_PENDING;
+	schedule_store(BT_MESH_MOD_PENDING);
+}
+
+void bt_mesh_store_mod_pub(struct bt_mesh_model *mod)
+{
+	mod->flags |= BT_MESH_MOD_PUB_PENDING;
+	schedule_store(BT_MESH_MOD_PENDING);
+}
+
+
+void bt_mesh_store_label(void)
+{
+	schedule_store(BT_MESH_VA_PENDING);
+}
+
+static void schedule_cdb_store(int flag)
+{
+	atomic_set_bit(bt_mesh_cdb.flags, flag);
+	k_delayed_work_submit(&pending_store, K_NO_WAIT);
+}
+
+void bt_mesh_store_cdb(void)
+{
+	schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
+}
+
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node)
+{
+	struct node_update *update, *free_slot;
+
+	BT_DBG("Node 0x%04x", node->addr);
+
+	update = cdb_node_update_find(node->addr, &free_slot);
+	if (update) {
+		update->clear = false;
+		schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		store_cdb_node(node);
+		return;
+	}
+
+	free_slot->addr = node->addr;
+	free_slot->clear = false;
+
+	schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+}
+
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node)
+{
+	struct node_update *update, *free_slot;
+
+	BT_DBG("Node 0x%04x", node->addr);
+
+	update = cdb_node_update_find(node->addr, &free_slot);
+	if (update) {
+		update->clear = true;
+		schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		clear_cdb_node(node->addr);
+		return;
+	}
+
+	free_slot->addr = node->addr;
+	free_slot->clear = true;
+
+	schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+}
+
+/* TODO: Could be shared with key_update_find? */
+static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx,
+					     struct key_update **free_slot)
+{
+	struct key_update *match;
+	int i;
+
+	match = NULL;
+	*free_slot = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+		struct key_update *update = &cdb_key_updates[i];
+
+		if (!update->valid) {
+			*free_slot = update;
+			continue;
+		}
+
+		if (update->app_key != app_key) {
+			continue;
+		}
+
+		if (update->key_idx == key_idx) {
+			match = update;
+		}
+	}
+
+	return match;
+}
+
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+	update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+	if (update) {
+		update->clear = 0U;
+		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		store_cdb_subnet(sub);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = sub->net_idx;
+	free_slot->app_key = 0U;
+	free_slot->clear = 0U;
+
+	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+	update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+	if (update) {
+		update->clear = 1U;
+		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		clear_cdb_subnet(sub->net_idx);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = sub->net_idx;
+	free_slot->app_key = 0U;
+	free_slot->clear = 1U;
+
+	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+	update = cdb_key_update_find(true, key->app_idx, &free_slot);
+	if (update) {
+		update->clear = 0U;
+		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		store_cdb_app_key(key);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = key->app_idx;
+	free_slot->app_key = 1U;
+	free_slot->clear = 0U;
+
+	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key)
+{
+	struct key_update *update, *free_slot;
+
+	BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+	update = cdb_key_update_find(true, key->app_idx, &free_slot);
+	if (update) {
+		update->clear = 1U;
+		schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+		return;
+	}
+
+	if (!free_slot) {
+		clear_cdb_app_key(key->app_idx);
+		return;
+	}
+
+	free_slot->valid = 1U;
+	free_slot->key_idx = key->app_idx;
+	free_slot->app_key = 1U;
+	free_slot->clear = 1U;
+
+	schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
+			const char *name, const void *data,
+			size_t data_len)
+{
+	char path[30];
+	int err;
+
+	encode_mod_path(mod, vnd, "data", path, sizeof(path));
+	if (name) {
+		strcat(path, "/");
+		strncat(path, name, 8);
+	}
+
+	if (data_len) {
+		err = settings_save_one(path, data, data_len);
+	} else {
+		err = settings_delete(path);
+	}
+
+	if (err) {
+		BT_ERR("Failed to store %s value", log_strdup(path));
+	} else {
+		BT_DBG("Stored %s value", log_strdup(path));
+	}
+	return err;
+}
+
+void bt_mesh_settings_init(void)
+{
+	k_delayed_work_init(&pending_store, store_pending);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/shell.c	(working copy)
@@ -0,0 +1,2815 @@
+/** @file
+ *  @brief Bluetooth Mesh shell
+ *
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <zephyr.h>
+#include <sys/printk.h>
+#include <sys/util.h>
+
+#include <shell/shell.h>
+#include <settings/settings.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/mesh.h>
+
+/* Private includes for raw Network & Transport layer access */
+#include "mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "transport.h"
+#include "foundation.h"
+#include "settings.h"
+
+#define CID_NVAL   0xffff
+
+static const struct shell *ctx_shell;
+
+/* Default net, app & dev key values, unless otherwise specified */
+static const uint8_t default_key[16] = {
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+};
+
+static struct {
+	uint16_t local;
+	uint16_t dst;
+	uint16_t net_idx;
+	uint16_t app_idx;
+} net = {
+	.local = BT_MESH_ADDR_UNASSIGNED,
+	.dst = BT_MESH_ADDR_UNASSIGNED,
+};
+
+static struct bt_mesh_cfg_srv cfg_srv = {
+	.relay = BT_MESH_RELAY_DISABLED,
+	.beacon = BT_MESH_BEACON_DISABLED,
+#if defined(CONFIG_BT_MESH_FRIEND)
+	.frnd = BT_MESH_FRIEND_DISABLED,
+#else
+	.frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
+#endif
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	.gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
+#else
+	.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
+#endif
+
+	.default_ttl = 7,
+
+	/* 3 transmissions with 20ms interval */
+	.net_transmit = BT_MESH_TRANSMIT(2, 20),
+	.relay_retransmit = BT_MESH_TRANSMIT(2, 20),
+};
+
+#define CUR_FAULTS_MAX 4
+
+static uint8_t cur_faults[CUR_FAULTS_MAX];
+static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
+
+static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
+{
+	uint8_t i, limit = *count;
+
+	for (i = 0U, *count = 0U; i < faults_size && *count < limit; i++) {
+		if (faults[i]) {
+			*dst++ = faults[i];
+			(*count)++;
+		}
+	}
+}
+
+static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
+			 uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
+{
+	shell_print(ctx_shell, "Sending current faults");
+
+	*test_id = 0x00;
+	*company_id = BT_COMP_ID_LF;
+
+	get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
+
+	return 0;
+}
+
+static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid,
+			 uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
+{
+	if (cid != BT_COMP_ID_LF) {
+		shell_print(ctx_shell, "Faults requested for unknown Company ID"
+			    " 0x%04x", cid);
+		return -EINVAL;
+	}
+
+	shell_print(ctx_shell, "Sending registered faults");
+
+	*test_id = 0x00;
+
+	get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
+
+	return 0;
+}
+
+static int fault_clear(struct bt_mesh_model *model, uint16_t cid)
+{
+	if (cid != BT_COMP_ID_LF) {
+		return -EINVAL;
+	}
+
+	(void)memset(reg_faults, 0, sizeof(reg_faults));
+
+	return 0;
+}
+
+static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
+		      uint16_t cid)
+{
+	if (cid != BT_COMP_ID_LF) {
+		return -EINVAL;
+	}
+
+	if (test_id != 0x00) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct bt_mesh_health_srv_cb health_srv_cb = {
+	.fault_get_cur = fault_get_cur,
+	.fault_get_reg = fault_get_reg,
+	.fault_clear = fault_clear,
+	.fault_test = fault_test,
+};
+
+static struct bt_mesh_health_srv health_srv = {
+	.cb = &health_srv_cb,
+};
+
+BT_MESH_HEALTH_PUB_DEFINE(health_pub, CUR_FAULTS_MAX);
+
+static struct bt_mesh_cfg_cli cfg_cli = {
+};
+
+void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
+{
+	size_t i;
+
+	if (!fault_count) {
+		shell_print(ctx_shell, "Health Test ID 0x%02x Company ID "
+			    "0x%04x: no faults", test_id, cid);
+		return;
+	}
+
+	shell_print(ctx_shell, "Health Test ID 0x%02x Company ID 0x%04x Fault "
+		    "Count %zu:", test_id, cid, fault_count);
+
+	for (i = 0; i < fault_count; i++) {
+		shell_print(ctx_shell, "\t0x%02x", faults[i]);
+	}
+}
+
+static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
+				  uint8_t test_id, uint16_t cid, uint8_t *faults,
+				  size_t fault_count)
+{
+	shell_print(ctx_shell, "Health Current Status from 0x%04x", addr);
+	show_faults(test_id, cid, faults, fault_count);
+}
+
+static struct bt_mesh_health_cli health_cli = {
+	.current_status = health_current_status,
+};
+
+static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
+
+static struct bt_mesh_model root_models[] = {
+	BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+	BT_MESH_MODEL_CFG_CLI(&cfg_cli),
+	BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
+	BT_MESH_MODEL_HEALTH_CLI(&health_cli),
+};
+
+static struct bt_mesh_elem elements[] = {
+	BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE),
+};
+
+static const struct bt_mesh_comp comp = {
+	.cid = BT_COMP_ID_LF,
+	.elem = elements,
+	.elem_count = ARRAY_SIZE(elements),
+};
+
+static void prov_complete(uint16_t net_idx, uint16_t addr)
+{
+
+	shell_print(ctx_shell, "Local node provisioned, net_idx 0x%04x address "
+		    "0x%04x", net_idx, addr);
+
+	net.local = addr;
+	net.net_idx = net_idx,
+	net.dst = addr;
+}
+
+static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+			    uint8_t num_elem)
+{
+	shell_print(ctx_shell, "Node provisioned, net_idx 0x%04x address "
+		    "0x%04x elements %d", net_idx, addr, num_elem);
+
+	net.net_idx = net_idx,
+	net.dst = addr;
+}
+
+static void prov_input_complete(void)
+{
+	shell_print(ctx_shell, "Input complete");
+}
+
+static void prov_reset(void)
+{
+	shell_print(ctx_shell, "The local node has been reset and needs "
+		    "reprovisioning");
+}
+
+static int output_number(bt_mesh_output_action_t action, uint32_t number)
+{
+	shell_print(ctx_shell, "OOB Number: %u", number);
+	return 0;
+}
+
+static int output_string(const char *str)
+{
+	shell_print(ctx_shell, "OOB String: %s", str);
+	return 0;
+}
+
+static bt_mesh_input_action_t input_act;
+static uint8_t input_size;
+
+static int cmd_input_num(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (input_act != BT_MESH_ENTER_NUMBER) {
+		shell_print(shell, "A number hasn't been requested!");
+		return 0;
+	}
+
+	if (strlen(argv[1]) < input_size) {
+		shell_print(shell, "Too short input (%u digits required)",
+			    input_size);
+		return 0;
+	}
+
+	err = bt_mesh_input_number(strtoul(argv[1], NULL, 10));
+	if (err) {
+		shell_error(shell, "Numeric input failed (err %d)", err);
+		return 0;
+	}
+
+	input_act = BT_MESH_NO_INPUT;
+	return 0;
+}
+
+static int cmd_input_str(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (input_act != BT_MESH_ENTER_STRING) {
+		shell_print(shell, "A string hasn't been requested!");
+		return 0;
+	}
+
+	if (strlen(argv[1]) < input_size) {
+		shell_print(shell, "Too short input (%u characters required)",
+		       input_size);
+		return 0;
+	}
+
+	err = bt_mesh_input_string(argv[1]);
+	if (err) {
+		shell_error(shell, "String input failed (err %d)", err);
+		return 0;
+	}
+
+	input_act = BT_MESH_NO_INPUT;
+	return 0;
+}
+
+static int input(bt_mesh_input_action_t act, uint8_t size)
+{
+	switch (act) {
+	case BT_MESH_ENTER_NUMBER:
+		shell_print(ctx_shell, "Enter a number (max %u digits) with: "
+			    "input-num <num>", size);
+		break;
+	case BT_MESH_ENTER_STRING:
+		shell_print(ctx_shell, "Enter a string (max %u chars) with: "
+			    "input-str <str>", size);
+		break;
+	default:
+		shell_error(ctx_shell, "Unknown input action %u (size %u) "
+			    "requested!", act, size);
+		return -EINVAL;
+	}
+
+	input_act = act;
+	input_size = size;
+	return 0;
+}
+
+static const char *bearer2str(bt_mesh_prov_bearer_t bearer)
+{
+	switch (bearer) {
+	case BT_MESH_PROV_ADV:
+		return "PB-ADV";
+	case BT_MESH_PROV_GATT:
+		return "PB-GATT";
+	default:
+		return "unknown";
+	}
+}
+
+static void link_open(bt_mesh_prov_bearer_t bearer)
+{
+	shell_print(ctx_shell, "Provisioning link opened on %s",
+		    bearer2str(bearer));
+}
+
+static void link_close(bt_mesh_prov_bearer_t bearer)
+{
+	shell_print(ctx_shell, "Provisioning link closed on %s",
+		    bearer2str(bearer));
+}
+
+static uint8_t static_val[16];
+
+static struct bt_mesh_prov prov = {
+	.uuid = dev_uuid,
+	.link_open = link_open,
+	.link_close = link_close,
+	.complete = prov_complete,
+	.node_added = prov_node_added,
+	.reset = prov_reset,
+	.static_val = NULL,
+	.static_val_len = 0,
+	.output_size = 6,
+	.output_actions = (BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING),
+	.output_number = output_number,
+	.output_string = output_string,
+	.input_size = 6,
+	.input_actions = (BT_MESH_ENTER_NUMBER | BT_MESH_ENTER_STRING),
+	.input = input,
+	.input_complete = prov_input_complete,
+};
+
+static int cmd_static_oob(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc < 2) {
+		prov.static_val = NULL;
+		prov.static_val_len = 0U;
+	} else {
+		prov.static_val_len = hex2bin(argv[1], strlen(argv[1]),
+					      static_val, 16);
+		if (prov.static_val_len) {
+			prov.static_val = static_val;
+		} else {
+			prov.static_val = NULL;
+		}
+	}
+
+	if (prov.static_val) {
+		shell_print(shell, "Static OOB value set (length %u)",
+			    prov.static_val_len);
+	} else {
+		shell_print(shell, "Static OOB value cleared");
+	}
+
+	return 0;
+}
+
+static int cmd_uuid(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t uuid[16];
+	size_t len;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
+	if (len < 1) {
+		return -EINVAL;
+	}
+
+	memcpy(dev_uuid, uuid, len);
+	(void)memset(dev_uuid + len, 0, sizeof(dev_uuid) - len);
+
+	shell_print(shell, "Device UUID set");
+
+	return 0;
+}
+
+static int cmd_reset(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_mesh_reset();
+	shell_print(shell, "Local node reset complete");
+	return 0;
+}
+
+static uint8_t str2u8(const char *str)
+{
+	if (isdigit((unsigned char)str[0])) {
+		return strtoul(str, NULL, 0);
+	}
+
+	return (!strcmp(str, "on") || !strcmp(str, "enable"));
+}
+
+static bool str2bool(const char *str)
+{
+	return str2u8(str);
+}
+
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+static int cmd_lpn(const struct shell *shell, size_t argc, char *argv[])
+{
+	static bool enabled;
+	int err;
+
+	if (argc < 2) {
+		shell_print(shell, "%s", enabled ? "enabled" : "disabled");
+		return 0;
+	}
+
+	if (str2bool(argv[1])) {
+		if (enabled) {
+			shell_print(shell, "LPN already enabled");
+			return 0;
+		}
+
+		err = bt_mesh_lpn_set(true);
+		if (err) {
+			shell_error(shell, "Enabling LPN failed (err %d)", err);
+		} else {
+			enabled = true;
+		}
+	} else {
+		if (!enabled) {
+			shell_print(shell, "LPN already disabled");
+			return 0;
+		}
+
+		err = bt_mesh_lpn_set(false);
+		if (err) {
+			shell_error(shell, "Enabling LPN failed (err %d)", err);
+		} else {
+			enabled = false;
+		}
+	}
+
+	return 0;
+}
+
+static int cmd_poll(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_mesh_lpn_poll();
+	if (err) {
+		shell_error(shell, "Friend Poll failed (err %d)", err);
+	}
+
+	return 0;
+}
+
+static void lpn_cb(uint16_t friend_addr, bool established)
+{
+	if (established) {
+		shell_print(ctx_shell, "Friendship (as LPN) established to "
+			    "Friend 0x%04x", friend_addr);
+	} else {
+		shell_print(ctx_shell, "Friendship (as LPN) lost with Friend "
+			    "0x%04x", friend_addr);
+	}
+}
+
+#endif /* MESH_LOW_POWER */
+
+static int cmd_init(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_enable(NULL);
+	if (err && err != -EALREADY) {
+		shell_error(shell, "Bluetooth init failed (err %d)", err);
+		return 0;
+	} else if (!err) {
+		shell_print(shell, "Bluetooth initialized");
+	}
+
+	err = bt_mesh_init(&prov, &comp);
+	if (err) {
+		shell_error(shell, "Mesh initialization failed (err %d)", err);
+	}
+
+	shell_print(shell, "Mesh initialized");
+
+	ctx_shell = shell;
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		settings_load();
+	}
+
+	if (bt_mesh_is_provisioned()) {
+		shell_print(shell, "Mesh network restored from flash");
+	} else {
+		shell_print(shell, "Use \"pb-adv on\" or \"pb-gatt on\" to "
+			    "enable advertising");
+	}
+
+#if IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)
+	bt_mesh_lpn_set_cb(lpn_cb);
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+static int cmd_ident(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_mesh_proxy_identity_enable();
+	if (err) {
+		shell_error(shell, "Failed advertise using Node Identity (err "
+			    "%d)", err);
+	}
+
+	return 0;
+}
+#endif /* MESH_GATT_PROXY */
+
+static int cmd_get_comp(const struct shell *shell, size_t argc, char *argv[])
+{
+	NET_BUF_SIMPLE_DEFINE(comp, 32);
+	uint8_t status, page = 0x00;
+	int err;
+
+	if (argc > 1) {
+		page = strtol(argv[1], NULL, 0);
+	}
+
+	err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page,
+					&status, &comp);
+	if (err) {
+		shell_error(shell, "Getting composition failed (err %d)", err);
+		return 0;
+	}
+
+	if (status != 0x00) {
+		shell_print(shell, "Got non-success status 0x%02x", status);
+		return 0;
+	}
+
+	shell_print(shell, "Got Composition Data for 0x%04x:", net.dst);
+	shell_print(shell, "\tCID      0x%04x",
+		    net_buf_simple_pull_le16(&comp));
+	shell_print(shell, "\tPID      0x%04x",
+		    net_buf_simple_pull_le16(&comp));
+	shell_print(shell, "\tVID      0x%04x",
+		    net_buf_simple_pull_le16(&comp));
+	shell_print(shell, "\tCRPL     0x%04x",
+		    net_buf_simple_pull_le16(&comp));
+	shell_print(shell, "\tFeatures 0x%04x",
+		    net_buf_simple_pull_le16(&comp));
+
+	while (comp.len > 4) {
+		uint8_t sig, vnd;
+		uint16_t loc;
+		int i;
+
+		loc = net_buf_simple_pull_le16(&comp);
+		sig = net_buf_simple_pull_u8(&comp);
+		vnd = net_buf_simple_pull_u8(&comp);
+
+		shell_print(shell, "\tElement @ 0x%04x:", loc);
+
+		if (comp.len < ((sig * 2U) + (vnd * 4U))) {
+			shell_print(shell, "\t\t...truncated data!");
+			break;
+		}
+
+		if (sig) {
+			shell_print(shell, "\t\tSIG Models:");
+		} else {
+			shell_print(shell, "\t\tNo SIG Models");
+		}
+
+		for (i = 0; i < sig; i++) {
+			uint16_t mod_id = net_buf_simple_pull_le16(&comp);
+
+			shell_print(shell, "\t\t\t0x%04x", mod_id);
+		}
+
+		if (vnd) {
+			shell_print(shell, "\t\tVendor Models:");
+		} else {
+			shell_print(shell, "\t\tNo Vendor Models");
+		}
+
+		for (i = 0; i < vnd; i++) {
+			uint16_t cid = net_buf_simple_pull_le16(&comp);
+			uint16_t mod_id = net_buf_simple_pull_le16(&comp);
+
+			shell_print(shell, "\t\t\tCompany 0x%04x: 0x%04x", cid,
+				    mod_id);
+		}
+	}
+
+	return 0;
+}
+
+static int cmd_dst(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc < 2) {
+		shell_print(shell, "Destination address: 0x%04x%s", net.dst,
+			    net.dst == net.local ? " (local)" : "");
+		return 0;
+	}
+
+	if (!strcmp(argv[1], "local")) {
+		net.dst = net.local;
+	} else {
+		net.dst = strtoul(argv[1], NULL, 0);
+	}
+
+	shell_print(shell, "Destination address set to 0x%04x%s", net.dst,
+		    net.dst == net.local ? " (local)" : "");
+	return 0;
+}
+
+static int cmd_netidx(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc < 2) {
+		shell_print(shell, "NetIdx: 0x%04x", net.net_idx);
+		return 0;
+	}
+
+	net.net_idx = strtoul(argv[1], NULL, 0);
+	shell_print(shell, "NetIdx set to 0x%04x", net.net_idx);
+	return 0;
+}
+
+static int cmd_appidx(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc < 2) {
+		shell_print(shell, "AppIdx: 0x%04x", net.app_idx);
+		return 0;
+	}
+
+	net.app_idx = strtoul(argv[1], NULL, 0);
+	shell_print(shell, "AppIdx set to 0x%04x", net.app_idx);
+	return 0;
+}
+
+static int cmd_net_send(const struct shell *shell, size_t argc, char *argv[])
+{
+	NET_BUF_SIMPLE_DEFINE(msg, 32);
+	struct bt_mesh_msg_ctx ctx = {
+		.send_ttl = BT_MESH_TTL_DEFAULT,
+		.net_idx = net.net_idx,
+		.addr = net.dst,
+		.app_idx = net.app_idx,
+
+	};
+	struct bt_mesh_net_tx tx = {
+		.ctx = &ctx,
+		.src = net.local,
+		.xmit = bt_mesh_net_transmit_get(),
+		.sub = bt_mesh_subnet_get(net.net_idx),
+	};
+	size_t len;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (!tx.sub) {
+		shell_print(shell, "No matching subnet for NetKey Index 0x%04x",
+			    net.net_idx);
+		return 0;
+	}
+
+	len = hex2bin(argv[1], strlen(argv[1]),
+		      msg.data, net_buf_simple_tailroom(&msg) - 4);
+	net_buf_simple_add(&msg, len);
+
+	err = bt_mesh_trans_send(&tx, &msg, NULL, NULL);
+	if (err) {
+		shell_error(shell, "Failed to send (err %d)", err);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
+static int cmd_iv_update(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (bt_mesh_iv_update()) {
+		shell_print(shell, "Transitioned to IV Update In Progress "
+			    "state");
+	} else {
+		shell_print(shell, "Transitioned to IV Update Normal state");
+	}
+
+	shell_print(shell, "IV Index is 0x%08x", bt_mesh.iv_index);
+
+	return 0;
+}
+
+static int cmd_iv_update_test(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	bool enable;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	enable = str2bool(argv[1]);
+	if (enable) {
+		shell_print(shell, "Enabling IV Update test mode");
+	} else {
+		shell_print(shell, "Disabling IV Update test mode");
+	}
+
+	bt_mesh_iv_update_test(enable);
+
+	return 0;
+}
+#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
+
+static int cmd_rpl_clear(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_mesh_rpl_clear();
+	return 0;
+}
+
+static int cmd_beacon(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t status;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
+	} else {
+		uint8_t val = str2u8(argv[1]);
+
+		err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
+					     &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Beacon Get/Set message "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "Beacon state is 0x%02x", status);
+
+	return 0;
+}
+
+static void print_unprovisioned_beacon(uint8_t uuid[16],
+				       bt_mesh_prov_oob_info_t oob_info,
+				       uint32_t *uri_hash)
+{
+	char uuid_hex_str[32 + 1];
+
+	bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+
+	shell_print(ctx_shell, "UUID %s, OOB Info 0x%04x, URI Hash 0x%x",
+		    uuid_hex_str, oob_info,
+		    (uri_hash == NULL ? 0 : *uri_hash));
+}
+
+static int cmd_beacon_listen(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	uint8_t val = str2u8(argv[1]);
+
+	if (val) {
+		prov.unprovisioned_beacon = print_unprovisioned_beacon;
+	} else {
+		prov.unprovisioned_beacon = NULL;
+	}
+
+	return 0;
+}
+
+static int cmd_ttl(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t ttl;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
+	} else {
+		uint8_t val = strtoul(argv[1], NULL, 0);
+
+		err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Default TTL Get/Set "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "Default TTL is 0x%02x", ttl);
+
+	return 0;
+}
+
+static int cmd_friend(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t frnd;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
+	} else {
+		uint8_t val = str2u8(argv[1]);
+
+		err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Friend Get/Set (err %d)",
+			    err);
+		return 0;
+	}
+
+	shell_print(shell, "Friend is set to 0x%02x", frnd);
+
+	return 0;
+}
+
+static int cmd_gatt_proxy(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t proxy;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
+	} else {
+		uint8_t val = str2u8(argv[1]);
+
+		err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
+						 &proxy);
+	}
+
+	if (err) {
+		shell_print(shell, "Unable to send GATT Proxy Get/Set "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "GATT Proxy is set to 0x%02x", proxy);
+
+	return 0;
+}
+
+static int cmd_net_transmit(const struct shell *shell,
+		size_t argc, char *argv[])
+{
+	uint8_t transmit;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_net_transmit_get(net.net_idx,
+				net.dst, &transmit);
+	} else {
+		if (argc != 3) {
+			shell_error(shell, "Wrong number of input arguments"
+						"(2 arguments are required)");
+			return -EINVAL;
+		}
+
+		uint8_t count, interval, new_transmit;
+
+		count = strtoul(argv[1], NULL, 0);
+		interval = strtoul(argv[2], NULL, 0);
+
+		new_transmit = BT_MESH_TRANSMIT(count, interval);
+
+		err = bt_mesh_cfg_net_transmit_set(net.net_idx, net.dst,
+				new_transmit, &transmit);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send network transmit"
+				" Get/Set (err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "Transmit 0x%02x (count %u interval %ums)",
+			transmit, BT_MESH_TRANSMIT_COUNT(transmit),
+			BT_MESH_TRANSMIT_INT(transmit));
+
+	return 0;
+}
+
+static int cmd_relay(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t relay, transmit;
+	int err;
+
+	if (argc < 2) {
+		err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
+					    &transmit);
+	} else {
+		uint8_t val = str2u8(argv[1]);
+		uint8_t count, interval, new_transmit;
+
+		if (val) {
+			if (argc > 2) {
+				count = strtoul(argv[2], NULL, 0);
+			} else {
+				count = 2U;
+			}
+
+			if (argc > 3) {
+				interval = strtoul(argv[3], NULL, 0);
+			} else {
+				interval = 20U;
+			}
+
+			new_transmit = BT_MESH_TRANSMIT(count, interval);
+		} else {
+			new_transmit = 0U;
+		}
+
+		err = bt_mesh_cfg_relay_set(net.net_idx, net.dst, val,
+					    new_transmit, &relay, &transmit);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Relay Get/Set (err %d)",
+			    err);
+		return 0;
+	}
+
+	shell_print(shell, "Relay is 0x%02x, Transmit 0x%02x (count %u interval"
+		    " %ums)", relay, transmit, BT_MESH_TRANSMIT_COUNT(transmit),
+		    BT_MESH_TRANSMIT_INT(transmit));
+
+	return 0;
+}
+
+static int cmd_net_key_add(const struct shell *shell, size_t argc, char *argv[])
+{
+	bool has_key_val = (argc > 2);
+	uint8_t key_val[16];
+	uint16_t key_net_idx;
+	uint8_t status;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	key_net_idx = strtoul(argv[1], NULL, 0);
+
+	if (has_key_val) {
+		size_t len;
+
+		len = hex2bin(argv[3], strlen(argv[3]),
+			      key_val, sizeof(key_val));
+		(void)memset(key_val, 0, sizeof(key_val) - len);
+	} else {
+		memcpy(key_val, default_key, sizeof(key_val));
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		struct bt_mesh_cdb_subnet *subnet;
+
+		subnet = bt_mesh_cdb_subnet_get(key_net_idx);
+		if (subnet) {
+			if (has_key_val) {
+				shell_error(shell,
+					    "Subnet 0x%03x already has a value",
+					    key_net_idx);
+				return 0;
+			}
+
+			memcpy(key_val, subnet->keys[0].net_key, 16);
+		} else {
+			subnet = bt_mesh_cdb_subnet_alloc(key_net_idx);
+			if (!subnet) {
+				shell_error(shell,
+					    "No space for subnet in cdb");
+				return 0;
+			}
+
+			memcpy(subnet->keys[0].net_key, key_val, 16);
+			bt_mesh_cdb_subnet_store(subnet);
+		}
+	}
+
+	err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
+				      key_val, &status);
+	if (err) {
+		shell_print(shell, "Unable to send NetKey Add (err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "NetKeyAdd failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "NetKey added with NetKey Index 0x%03x",
+			    key_net_idx);
+	}
+
+	return 0;
+}
+
+static int cmd_net_key_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t keys[16];
+	size_t cnt;
+	int err, i;
+
+	cnt = ARRAY_SIZE(keys);
+
+	err = bt_mesh_cfg_net_key_get(net.net_idx, net.dst, keys, &cnt);
+	if (err) {
+		shell_print(shell, "Unable to send NetKeyGet (err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "NetKeys known by 0x%04x:", net.dst);
+	for (i = 0; i < cnt; i++) {
+		shell_print(shell, "\t0x%03x", keys[i]);
+	}
+
+	return 0;
+}
+
+static int cmd_net_key_del(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t key_net_idx;
+	uint8_t status;
+	int err;
+
+	key_net_idx = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_cfg_net_key_del(net.net_idx, net.dst, key_net_idx,
+				      &status);
+	if (err) {
+		shell_print(shell, "Unable to send NetKeyDel (err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "NetKeyDel failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "NetKey 0x%03x deleted", key_net_idx);
+	}
+
+	return 0;
+}
+
+static int cmd_app_key_add(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t key_val[16];
+	uint16_t key_net_idx, key_app_idx;
+	bool has_key_val = (argc > 3);
+	uint8_t status;
+	int err;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	key_net_idx = strtoul(argv[1], NULL, 0);
+	key_app_idx = strtoul(argv[2], NULL, 0);
+
+	if (has_key_val) {
+		size_t len;
+
+		len = hex2bin(argv[3], strlen(argv[3]),
+			      key_val, sizeof(key_val));
+		(void)memset(key_val, 0, sizeof(key_val) - len);
+	} else {
+		memcpy(key_val, default_key, sizeof(key_val));
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		struct bt_mesh_cdb_app_key *app_key;
+
+		app_key = bt_mesh_cdb_app_key_get(key_app_idx);
+		if (app_key) {
+			if (has_key_val) {
+				shell_error(
+					shell,
+					"App key 0x%03x already has a value",
+					key_app_idx);
+				return 0;
+			}
+
+			memcpy(key_val, app_key->keys[0].app_key, 16);
+		} else {
+			app_key = bt_mesh_cdb_app_key_alloc(key_net_idx,
+							    key_app_idx);
+			if (!app_key) {
+				shell_error(shell,
+					    "No space for app key in cdb");
+				return 0;
+			}
+
+			memcpy(app_key->keys[0].app_key, key_val, 16);
+			bt_mesh_cdb_app_key_store(app_key);
+		}
+	}
+
+	err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
+				      key_app_idx, key_val, &status);
+	if (err) {
+		shell_error(shell, "Unable to send App Key Add (err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "AppKeyAdd failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "AppKey added, NetKeyIndex 0x%04x "
+			    "AppKeyIndex 0x%04x", key_net_idx, key_app_idx);
+	}
+
+	return 0;
+}
+
+static int cmd_app_key_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t net_idx;
+	uint16_t keys[16];
+	size_t cnt;
+	uint8_t status;
+	int err, i;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+	cnt = ARRAY_SIZE(keys);
+
+	err = bt_mesh_cfg_app_key_get(net.net_idx, net.dst, net_idx, &status,
+				      keys, &cnt);
+	if (err) {
+		shell_print(shell, "Unable to send AppKeyGet (err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "AppKeyGet failed with status 0x%02x",
+			    status);
+		return 0;
+	}
+
+	shell_print(shell,
+		    "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx,
+		    net.dst);
+	for (i = 0; i < cnt; i++) {
+		shell_print(shell, "\t0x%03x", keys[i]);
+	}
+
+	return 0;
+}
+
+static int cmd_app_key_del(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t key_net_idx, key_app_idx;
+	uint8_t status;
+	int err;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	key_net_idx = strtoul(argv[1], NULL, 0);
+	key_app_idx = strtoul(argv[2], NULL, 0);
+
+	err = bt_mesh_cfg_app_key_del(net.net_idx, net.dst, key_net_idx,
+				      key_app_idx, &status);
+	if (err) {
+		shell_error(shell, "Unable to send App Key del(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "AppKeyDel failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "AppKey deleted, NetKeyIndex 0x%04x "
+			    "AppKeyIndex 0x%04x", key_net_idx, key_app_idx);
+	}
+
+	return 0;
+}
+
+static int cmd_mod_app_bind(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	uint16_t elem_addr, mod_app_idx, mod_id, cid;
+	uint8_t status;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	mod_app_idx = strtoul(argv[2], NULL, 0);
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_app_bind_vnd(net.net_idx, net.dst,
+						   elem_addr, mod_app_idx,
+						   mod_id, cid, &status);
+	} else {
+		err = bt_mesh_cfg_mod_app_bind(net.net_idx, net.dst, elem_addr,
+					       mod_app_idx, mod_id, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model App Bind (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model App Bind failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "AppKey successfully bound");
+	}
+
+	return 0;
+}
+
+
+static int cmd_mod_app_unbind(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	uint16_t elem_addr, mod_app_idx, mod_id, cid;
+	uint8_t status;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	mod_app_idx = strtoul(argv[2], NULL, 0);
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_app_unbind_vnd(net.net_idx, net.dst,
+						   elem_addr, mod_app_idx,
+						   mod_id, cid, &status);
+	} else {
+		err = bt_mesh_cfg_mod_app_unbind(net.net_idx, net.dst,
+				elem_addr, mod_app_idx, mod_id, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model App Unbind (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model App Unbind failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "AppKey successfully unbound");
+	}
+
+	return 0;
+}
+
+static int cmd_mod_app_get(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	uint16_t elem_addr, mod_id, cid;
+	uint16_t apps[16];
+	uint8_t status;
+	size_t cnt;
+	int err, i;
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	mod_id = strtoul(argv[2], NULL, 0);
+	cnt = ARRAY_SIZE(apps);
+
+	if (argc > 3) {
+		cid = strtoul(argv[3], NULL, 0);
+		err = bt_mesh_cfg_mod_app_get_vnd(net.net_idx, net.dst,
+						  elem_addr, mod_id, cid,
+						  &status, apps, &cnt);
+	} else {
+		err = bt_mesh_cfg_mod_app_get(net.net_idx, net.dst, elem_addr,
+					      mod_id, &status, apps, &cnt);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model App Get (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model App Get failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(
+			shell,
+			"Apps bound to Element 0x%04x, Model 0x%04x %s:",
+			elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+		if (!cnt) {
+			shell_print(shell, "\tNone.");
+		}
+
+		for (i = 0; i < cnt; i++) {
+			shell_print(shell, "\t0x%04x", apps[i]);
+		}
+	}
+
+	return 0;
+}
+
+static int cmd_mod_sub_add(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t elem_addr, sub_addr, mod_id, cid;
+	uint8_t status;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	sub_addr = strtoul(argv[2], NULL, 0);
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_add_vnd(net.net_idx, net.dst,
+						  elem_addr, sub_addr, mod_id,
+						  cid, &status);
+	} else {
+		err = bt_mesh_cfg_mod_sub_add(net.net_idx, net.dst, elem_addr,
+					      sub_addr, mod_id, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model Subscription Add "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Subscription Add failed with status "
+			    "0x%02x", status);
+	} else {
+		shell_print(shell, "Model subscription was successful");
+	}
+
+	return 0;
+}
+
+static int cmd_mod_sub_del(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t elem_addr, sub_addr, mod_id, cid;
+	uint8_t status;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	sub_addr = strtoul(argv[2], NULL, 0);
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_del_vnd(net.net_idx, net.dst,
+						  elem_addr, sub_addr, mod_id,
+						  cid, &status);
+	} else {
+		err = bt_mesh_cfg_mod_sub_del(net.net_idx, net.dst, elem_addr,
+					      sub_addr, mod_id, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model Subscription Delete "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Subscription Delete failed with "
+			    "status 0x%02x", status);
+	} else {
+		shell_print(shell, "Model subscription deltion was successful");
+	}
+
+	return 0;
+}
+
+static int cmd_mod_sub_add_va(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	uint16_t elem_addr, sub_addr, mod_id, cid;
+	uint8_t label[16];
+	uint8_t status;
+	size_t len;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+
+	len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
+	(void)memset(label + len, 0, sizeof(label) - len);
+
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_va_add_vnd(net.net_idx, net.dst,
+						     elem_addr, label, mod_id,
+						     cid, &sub_addr, &status);
+	} else {
+		err = bt_mesh_cfg_mod_sub_va_add(net.net_idx, net.dst,
+						 elem_addr, label, mod_id,
+						 &sub_addr, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Mod Sub VA Add (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Mod Sub VA Add failed with status 0x%02x",
+			    status);
+	} else {
+		shell_print(shell, "0x%04x subscribed to Label UUID %s "
+			    "(va 0x%04x)", elem_addr, argv[2], sub_addr);
+	}
+
+	return 0;
+}
+
+static int cmd_mod_sub_del_va(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	uint16_t elem_addr, sub_addr, mod_id, cid;
+	uint8_t label[16];
+	uint8_t status;
+	size_t len;
+	int err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+
+	len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
+	(void)memset(label + len, 0, sizeof(label) - len);
+
+	mod_id = strtoul(argv[3], NULL, 0);
+
+	if (argc > 4) {
+		cid = strtoul(argv[4], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_va_del_vnd(net.net_idx, net.dst,
+						     elem_addr, label, mod_id,
+						     cid, &sub_addr, &status);
+	} else {
+		err = bt_mesh_cfg_mod_sub_va_del(net.net_idx, net.dst,
+						 elem_addr, label, mod_id,
+						 &sub_addr, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model Subscription Delete "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Subscription Delete failed with "
+			    "status 0x%02x", status);
+	} else {
+		shell_print(shell, "0x%04x unsubscribed from Label UUID %s "
+			    "(va 0x%04x)", elem_addr, argv[2], sub_addr);
+	}
+
+	return 0;
+}
+
+static int cmd_mod_sub_get(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	uint16_t elem_addr, mod_id, cid;
+	uint16_t subs[16];
+	uint8_t status;
+	size_t cnt;
+	int err, i;
+
+	elem_addr = strtoul(argv[1], NULL, 0);
+	mod_id = strtoul(argv[2], NULL, 0);
+	cnt = ARRAY_SIZE(subs);
+
+	if (argc > 3) {
+		cid = strtoul(argv[3], NULL, 0);
+		err = bt_mesh_cfg_mod_sub_get_vnd(net.net_idx, net.dst,
+						  elem_addr, mod_id, cid,
+						  &status, subs, &cnt);
+	} else {
+		err = bt_mesh_cfg_mod_sub_get(net.net_idx, net.dst, elem_addr,
+					      mod_id, &status, subs, &cnt);
+	}
+
+	if (err) {
+		shell_error(shell, "Unable to send Model Subscription Get "
+			    "(err %d)", err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Subscription Get failed with "
+			    "status 0x%02x", status);
+	} else {
+		shell_print(
+			shell,
+			"Model Subscriptions for Element 0x%04x, "
+			"Model 0x%04x %s:",
+			elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+		if (!cnt) {
+			shell_print(shell, "\tNone.");
+		}
+
+		for (i = 0; i < cnt; i++) {
+			shell_print(shell, "\t0x%04x", subs[i]);
+		}
+	}
+
+	return 0;
+}
+
+static int mod_pub_get(const struct shell *shell, uint16_t addr, uint16_t mod_id,
+		       uint16_t cid)
+{
+	struct bt_mesh_cfg_mod_pub pub;
+	uint8_t status;
+	int err;
+
+	if (cid == CID_NVAL) {
+		err = bt_mesh_cfg_mod_pub_get(net.net_idx, net.dst, addr,
+					      mod_id, &pub, &status);
+	} else {
+		err = bt_mesh_cfg_mod_pub_get_vnd(net.net_idx, net.dst, addr,
+						  mod_id, cid, &pub, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Model Publication Get failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Publication Get failed "
+			    "(status 0x%02x)", status);
+		return 0;
+	}
+
+	shell_print(shell, "Model Publication for Element 0x%04x, Model 0x%04x:"
+		    "\tPublish Address:                0x%04x"
+		    "\tAppKeyIndex:                    0x%04x"
+		    "\tCredential Flag:                %u"
+		    "\tPublishTTL:                     %u"
+		    "\tPublishPeriod:                  0x%02x"
+		    "\tPublishRetransmitCount:         %u"
+		    "\tPublishRetransmitInterval:      %ums",
+		    addr, mod_id, pub.addr, pub.app_idx, pub.cred_flag, pub.ttl,
+		    pub.period, BT_MESH_PUB_TRANSMIT_COUNT(pub.transmit),
+		    BT_MESH_PUB_TRANSMIT_INT(pub.transmit));
+
+	return 0;
+}
+
+static int mod_pub_set(const struct shell *shell, uint16_t addr, uint16_t mod_id,
+		       uint16_t cid, char *argv[])
+{
+	struct bt_mesh_cfg_mod_pub pub;
+	uint8_t status, count;
+	uint16_t interval;
+	int err;
+
+	pub.addr = strtoul(argv[0], NULL, 0);
+	pub.app_idx = strtoul(argv[1], NULL, 0);
+	pub.cred_flag = str2bool(argv[2]);
+	pub.ttl = strtoul(argv[3], NULL, 0);
+	pub.period = strtoul(argv[4], NULL, 0);
+
+	count = strtoul(argv[5], NULL, 0);
+	if (count > 7) {
+		shell_print(shell, "Invalid retransmit count");
+		return -EINVAL;
+	}
+
+	interval = strtoul(argv[6], NULL, 0);
+	if (interval > (31 * 50) || (interval % 50)) {
+		shell_print(shell, "Invalid retransmit interval %u", interval);
+		return -EINVAL;
+	}
+
+	pub.transmit = BT_MESH_PUB_TRANSMIT(count, interval);
+
+	if (cid == CID_NVAL) {
+		err = bt_mesh_cfg_mod_pub_set(net.net_idx, net.dst, addr,
+					      mod_id, &pub, &status);
+	} else {
+		err = bt_mesh_cfg_mod_pub_set_vnd(net.net_idx, net.dst, addr,
+						  mod_id, cid, &pub, &status);
+	}
+
+	if (err) {
+		shell_error(shell, "Model Publication Set failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Model Publication Set failed "
+			    "(status 0x%02x)", status);
+	} else {
+		shell_print(shell, "Model Publication successfully set");
+	}
+
+	return 0;
+}
+
+static int cmd_mod_pub(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t addr, mod_id, cid;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	addr = strtoul(argv[1], NULL, 0);
+	mod_id = strtoul(argv[2], NULL, 0);
+
+	argc -= 3;
+	argv += 3;
+
+	if (argc == 1 || argc == 8) {
+		cid = strtoul(argv[0], NULL, 0);
+		argc--;
+		argv++;
+	} else {
+		cid = CID_NVAL;
+	}
+
+	if (argc > 0) {
+		if (argc < 7) {
+			return -EINVAL;
+		}
+
+		return mod_pub_set(shell, addr, mod_id, cid, argv);
+	} else {
+		return mod_pub_get(shell, addr, mod_id, cid);
+	}
+}
+
+static void hb_sub_print(const struct shell *shell,
+			 struct bt_mesh_cfg_hb_sub *sub)
+{
+	shell_print(shell, "Heartbeat Subscription:"
+		    "\tSource:      0x%04x"
+		    "\tDestination: 0x%04x"
+		    "\tPeriodLog:   0x%02x"
+		    "\tCountLog:    0x%02x"
+		    "\tMinHops:     %u"
+		    "\tMaxHops:     %u",
+		    sub->src, sub->dst, sub->period, sub->count,
+		    sub->min, sub->max);
+}
+
+static int hb_sub_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_mesh_cfg_hb_sub sub;
+	uint8_t status;
+	int err;
+
+	err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
+	if (err) {
+		shell_error(shell, "Heartbeat Subscription Get failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Heartbeat Subscription Get failed "
+			    "(status 0x%02x)", status);
+	} else {
+		hb_sub_print(shell, &sub);
+	}
+
+	return 0;
+}
+
+static int hb_sub_set(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_mesh_cfg_hb_sub sub;
+	uint8_t status;
+	int err;
+
+	sub.src = strtoul(argv[1], NULL, 0);
+	sub.dst = strtoul(argv[2], NULL, 0);
+	sub.period = strtoul(argv[3], NULL, 0);
+
+	err = bt_mesh_cfg_hb_sub_set(net.net_idx, net.dst, &sub, &status);
+	if (err) {
+		shell_error(shell, "Heartbeat Subscription Set failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Heartbeat Subscription Set failed "
+			    "(status 0x%02x)", status);
+	} else {
+		hb_sub_print(shell, &sub);
+	}
+
+	return 0;
+}
+
+static int cmd_hb_sub(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc > 1) {
+		if (argc < 4) {
+			return -EINVAL;
+		}
+
+		return hb_sub_set(shell, argc, argv);
+	} else {
+		return hb_sub_get(shell, argc, argv);
+	}
+}
+
+static int hb_pub_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_mesh_cfg_hb_pub pub;
+	uint8_t status;
+	int err;
+
+	err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
+	if (err) {
+		shell_error(shell, "Heartbeat Publication Get failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Heartbeat Publication Get failed "
+			    "(status 0x%02x)", status);
+		return 0;
+	}
+
+	shell_print(shell, "Heartbeat publication:");
+	shell_print(shell, "\tdst 0x%04x count 0x%02x period 0x%02x",
+		    pub.dst, pub.count, pub.period);
+	shell_print(shell, "\tttl 0x%02x feat 0x%04x net_idx 0x%04x",
+		    pub.ttl, pub.feat, pub.net_idx);
+
+	return 0;
+}
+
+static int hb_pub_set(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_mesh_cfg_hb_pub pub;
+	uint8_t status;
+	int err;
+
+	pub.dst = strtoul(argv[1], NULL, 0);
+	pub.count = strtoul(argv[2], NULL, 0);
+	pub.period = strtoul(argv[3], NULL, 0);
+	pub.ttl = strtoul(argv[4], NULL, 0);
+	pub.feat = strtoul(argv[5], NULL, 0);
+	pub.net_idx = strtoul(argv[5], NULL, 0);
+
+	err = bt_mesh_cfg_hb_pub_set(net.net_idx, net.dst, &pub, &status);
+	if (err) {
+		shell_error(shell, "Heartbeat Publication Set failed (err %d)",
+			    err);
+		return 0;
+	}
+
+	if (status) {
+		shell_print(shell, "Heartbeat Publication Set failed "
+			    "(status 0x%02x)", status);
+	} else {
+		shell_print(shell, "Heartbeat publication successfully set");
+	}
+
+	return 0;
+}
+
+static int cmd_hb_pub(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc > 1) {
+		if (argc < 7) {
+			return -EINVAL;
+		}
+
+		return hb_pub_set(shell, argc, argv);
+	} else {
+		return hb_pub_get(shell, argc, argv);
+	}
+}
+
+#if defined(CONFIG_BT_MESH_PROV)
+static int cmd_pb(bt_mesh_prov_bearer_t bearer, const struct shell *shell,
+		  size_t argc, char *argv[])
+{
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (str2bool(argv[1])) {
+		err = bt_mesh_prov_enable(bearer);
+		if (err) {
+			shell_error(shell, "Failed to enable %s (err %d)",
+				    bearer2str(bearer), err);
+		} else {
+			shell_print(shell, "%s enabled", bearer2str(bearer));
+		}
+	} else {
+		err = bt_mesh_prov_disable(bearer);
+		if (err) {
+			shell_error(shell, "Failed to disable %s (err %d)",
+				    bearer2str(bearer), err);
+		} else {
+			shell_print(shell, "%s disabled", bearer2str(bearer));
+		}
+	}
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_BT_MESH_PB_ADV)
+static int cmd_pb_adv(const struct shell *shell, size_t argc, char *argv[])
+{
+	return cmd_pb(BT_MESH_PROV_ADV, shell, argc, argv);
+}
+
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+static int cmd_provision_adv(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	uint8_t uuid[16];
+	uint8_t attention_duration;
+	uint16_t net_idx;
+	uint16_t addr;
+	size_t len;
+	int err;
+
+	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
+	(void)memset(uuid + len, 0, sizeof(uuid) - len);
+
+	net_idx = strtoul(argv[2], NULL, 0);
+	addr = strtoul(argv[3], NULL, 0);
+	attention_duration = strtoul(argv[4], NULL, 0);
+
+	err = bt_mesh_provision_adv(uuid, net_idx, addr, attention_duration);
+	if (err) {
+		shell_error(shell, "Provisioning failed (err %d)", err);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_MESH_PROVISIONER */
+
+#endif /* CONFIG_BT_MESH_PB_ADV */
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
+static int cmd_pb_gatt(const struct shell *shell, size_t argc, char *argv[])
+{
+	return cmd_pb(BT_MESH_PROV_GATT, shell, argc, argv);
+}
+#endif /* CONFIG_BT_MESH_PB_GATT */
+
+static int cmd_provision(const struct shell *shell, size_t argc, char *argv[])
+{
+	const uint8_t *net_key = default_key;
+	uint16_t net_idx, addr;
+	uint32_t iv_index;
+	int err;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	net_idx = strtoul(argv[1], NULL, 0);
+	addr = strtoul(argv[2], NULL, 0);
+
+	if (argc > 3) {
+		iv_index = strtoul(argv[3], NULL, 0);
+	} else {
+		iv_index = 0U;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+		const struct bt_mesh_cdb_subnet *sub;
+
+		sub = bt_mesh_cdb_subnet_get(net_idx);
+		if (!sub) {
+			shell_error(shell, "No cdb entry for subnet 0x%03x",
+				    net_idx);
+			return 0;
+		}
+
+		net_key = sub->keys[sub->kr_flag].net_key;
+	}
+
+	err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr,
+				default_key);
+	if (err) {
+		shell_error(shell, "Provisioning failed (err %d)", err);
+	}
+
+	return 0;
+}
+
+int cmd_timeout(const struct shell *shell, size_t argc, char *argv[])
+{
+	int32_t timeout_ms;
+
+	if (argc == 2) {
+		int32_t timeout_s;
+
+		timeout_s = strtol(argv[1], NULL, 0);
+		if (timeout_s < 0 || timeout_s > (INT32_MAX / 1000)) {
+			timeout_ms = SYS_FOREVER_MS;
+		} else {
+			timeout_ms = timeout_s * MSEC_PER_SEC;
+		}
+
+		bt_mesh_cfg_cli_timeout_set(timeout_ms);
+	}
+
+	timeout_ms = bt_mesh_cfg_cli_timeout_get();
+	if (timeout_ms == SYS_FOREVER_MS) {
+		shell_print(shell, "Message timeout: forever");
+	} else {
+		shell_print(shell, "Message timeout: %u seconds",
+			    timeout_ms / 1000);
+	}
+
+	return 0;
+}
+
+static int cmd_fault_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t faults[32];
+	size_t fault_count;
+	uint8_t test_id;
+	uint16_t cid;
+	int err;
+
+	cid = strtoul(argv[1], NULL, 0);
+	fault_count = sizeof(faults);
+
+	err = bt_mesh_health_fault_get(net.dst, net.app_idx, cid, &test_id,
+				 faults, &fault_count);
+	if (err) {
+		shell_error(shell, "Failed to send Health Fault Get (err %d)",
+			    err);
+	} else {
+		show_faults(test_id, cid, faults, fault_count);
+	}
+
+	return 0;
+}
+
+static int cmd_fault_clear(const struct shell *shell, size_t argc,
+			   char *argv[])
+{
+	uint8_t faults[32];
+	size_t fault_count;
+	uint8_t test_id;
+	uint16_t cid;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	cid = strtoul(argv[1], NULL, 0);
+	fault_count = sizeof(faults);
+
+	err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+				 &test_id, faults, &fault_count);
+	if (err) {
+		shell_error(shell, "Failed to send Health Fault Clear (err %d)",
+			    err);
+	} else {
+		show_faults(test_id, cid, faults, fault_count);
+	}
+
+	return 0;
+}
+
+static int cmd_fault_clear_unack(const struct shell *shell, size_t argc,
+				 char *argv[])
+{
+	uint16_t cid;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	cid = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+					 NULL, NULL, NULL);
+	if (err) {
+		shell_error(shell, "Health Fault Clear Unacknowledged failed "
+			    "(err %d)", err);
+	}
+
+	return 0;
+}
+
+static int cmd_fault_test(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t faults[32];
+	size_t fault_count;
+	uint8_t test_id;
+	uint16_t cid;
+	int err;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	cid = strtoul(argv[1], NULL, 0);
+	test_id = strtoul(argv[2], NULL, 0);
+	fault_count = sizeof(faults);
+
+	err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+				 test_id, faults, &fault_count);
+	if (err) {
+		shell_error(shell, "Failed to send Health Fault Test (err %d)",
+			    err);
+	} else {
+		show_faults(test_id, cid, faults, fault_count);
+	}
+
+	return 0;
+}
+
+static int cmd_fault_test_unack(const struct shell *shell, size_t argc,
+				char *argv[])
+{
+	uint16_t cid;
+	uint8_t test_id;
+	int err;
+
+	if (argc < 3) {
+		return -EINVAL;
+	}
+
+	cid = strtoul(argv[1], NULL, 0);
+	test_id = strtoul(argv[2], NULL, 0);
+
+	err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+				 test_id, NULL, NULL);
+	if (err) {
+		shell_error(shell, "Health Fault Test Unacknowledged failed "
+			    "(err %d)", err);
+	}
+
+	return 0;
+}
+
+static int cmd_period_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t divisor;
+	int err;
+
+	err = bt_mesh_health_period_get(net.dst, net.app_idx, &divisor);
+	if (err) {
+		shell_error(shell, "Failed to send Health Period Get (err %d)",
+			    err);
+	} else {
+		shell_print(shell, "Health FastPeriodDivisor: %u", divisor);
+	}
+
+	return 0;
+}
+
+static int cmd_period_set(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t divisor, updated_divisor;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	divisor = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor,
+				 &updated_divisor);
+	if (err) {
+		shell_error(shell, "Failed to send Health Period Set (err %d)",
+			    err);
+	} else {
+		shell_print(shell, "Health FastPeriodDivisor: %u",
+			    updated_divisor);
+	}
+
+	return 0;
+}
+
+static int cmd_period_set_unack(const struct shell *shell, size_t argc,
+				char *argv[])
+{
+	uint8_t divisor;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	divisor = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor, NULL);
+	if (err) {
+		shell_print(shell, "Failed to send Health Period Set (err %d)",
+			    err);
+	}
+
+	return 0;
+}
+
+static int cmd_attention_get(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	uint8_t attention;
+	int err;
+
+	err = bt_mesh_health_attention_get(net.dst, net.app_idx,
+					   &attention);
+	if (err) {
+		shell_error(shell, "Failed to send Health Attention Get "
+			    "(err %d)", err);
+	} else {
+		shell_print(shell, "Health Attention Timer: %u", attention);
+	}
+
+	return 0;
+}
+
+static int cmd_attention_set(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	uint8_t attention, updated_attention;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	attention = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+				 &updated_attention);
+	if (err) {
+		shell_error(shell, "Failed to send Health Attention Set "
+			    "(err %d)", err);
+	} else {
+		shell_print(shell, "Health Attention Timer: %u",
+			    updated_attention);
+	}
+
+	return 0;
+}
+
+static int cmd_attention_set_unack(const struct shell *shell, size_t argc,
+				   char *argv[])
+{
+	uint8_t attention;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	attention = strtoul(argv[1], NULL, 0);
+
+	err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+				 NULL);
+	if (err) {
+		shell_error(shell, "Failed to send Health Attention Set "
+			    "(err %d)", err);
+	}
+
+	return 0;
+}
+
+static int cmd_add_fault(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t fault_id;
+	uint8_t i;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	fault_id = strtoul(argv[1], NULL, 0);
+	if (!fault_id) {
+		shell_print(shell, "The Fault ID must be non-zero!");
+		return -EINVAL;
+	}
+
+	for (i = 0U; i < sizeof(cur_faults); i++) {
+		if (!cur_faults[i]) {
+			cur_faults[i] = fault_id;
+			break;
+		}
+	}
+
+	if (i == sizeof(cur_faults)) {
+		shell_print(shell, "Fault array is full. Use \"del-fault\" to "
+			    "clear it");
+		return 0;
+	}
+
+	for (i = 0U; i < sizeof(reg_faults); i++) {
+		if (!reg_faults[i]) {
+			reg_faults[i] = fault_id;
+			break;
+		}
+	}
+
+	if (i == sizeof(reg_faults)) {
+		shell_print(shell, "No space to store more registered faults");
+	}
+
+	bt_mesh_fault_update(&elements[0]);
+
+	return 0;
+}
+
+static int cmd_del_fault(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t fault_id;
+	uint8_t i;
+
+	if (argc < 2) {
+		(void)memset(cur_faults, 0, sizeof(cur_faults));
+		shell_print(shell, "All current faults cleared");
+		bt_mesh_fault_update(&elements[0]);
+		return 0;
+	}
+
+	fault_id = strtoul(argv[1], NULL, 0);
+	if (!fault_id) {
+		shell_print(shell, "The Fault ID must be non-zero!");
+		return -EINVAL;
+	}
+
+	for (i = 0U; i < sizeof(cur_faults); i++) {
+		if (cur_faults[i] == fault_id) {
+			cur_faults[i] = 0U;
+			shell_print(shell, "Fault cleared");
+		}
+	}
+
+	bt_mesh_fault_update(&elements[0]);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_MESH_CDB)
+static int cmd_cdb_create(const struct shell *shell, size_t argc,
+			  char *argv[])
+{
+	uint8_t net_key[16];
+	size_t len;
+	int err;
+
+	if (argc < 2) {
+		bt_rand(net_key, 16);
+	} else {
+		len = hex2bin(argv[1], strlen(argv[1]), net_key,
+			      sizeof(net_key));
+		memset(net_key + len, 0, sizeof(net_key) - len);
+	}
+
+	err = bt_mesh_cdb_create(net_key);
+	if (err < 0) {
+		shell_print(shell, "Failed to create CDB (err %d)", err);
+	}
+
+	return 0;
+}
+
+static int cmd_cdb_clear(const struct shell *shell, size_t argc,
+			 char *argv[])
+{
+	bt_mesh_cdb_clear();
+
+	shell_print(shell, "Cleared CDB");
+
+	return 0;
+}
+
+static void cdb_print_nodes(const struct shell *shell)
+{
+	char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
+	struct bt_mesh_cdb_node *node;
+	int i, total = 0;
+	bool configured;
+
+	shell_print(shell, "Address  Elements  Flags  %-32s  DevKey", "UUID");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+		node = &bt_mesh_cdb.nodes[i];
+		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+			continue;
+		}
+
+		configured = atomic_test_bit(node->flags,
+					     BT_MESH_CDB_NODE_CONFIGURED);
+
+		total++;
+		bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+		bin2hex(node->dev_key, 16, key_hex_str, sizeof(key_hex_str));
+		shell_print(shell, "0x%04x   %-8d  %-5s  %s  %s", node->addr,
+			    node->num_elem, configured ? "C" : "-",
+			    uuid_hex_str, key_hex_str);
+	}
+
+	shell_print(shell, "> Total nodes: %d", total);
+}
+
+static void cdb_print_subnets(const struct shell *shell)
+{
+	struct bt_mesh_cdb_subnet *subnet;
+	char key_hex_str[32 + 1];
+	int i, total = 0;
+
+	shell_print(shell, "NetIdx  NetKey");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+		subnet = &bt_mesh_cdb.subnets[i];
+		if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		total++;
+		bin2hex(subnet->keys[0].net_key, 16, key_hex_str,
+			sizeof(key_hex_str));
+		shell_print(shell, "0x%03x   %s", subnet->net_idx,
+			    key_hex_str);
+	}
+
+	shell_print(shell, "> Total subnets: %d", total);
+}
+
+static void cdb_print_app_keys(const struct shell *shell)
+{
+	struct bt_mesh_cdb_app_key *app_key;
+	char key_hex_str[32 + 1];
+	int i, total = 0;
+
+	shell_print(shell, "NetIdx  AppIdx  AppKey");
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+		app_key = &bt_mesh_cdb.app_keys[i];
+		if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
+			continue;
+		}
+
+		total++;
+		bin2hex(app_key->keys[0].app_key, 16, key_hex_str,
+			sizeof(key_hex_str));
+		shell_print(shell, "0x%03x   0x%03x   %s",
+			    app_key->net_idx, app_key->app_idx, key_hex_str);
+	}
+
+	shell_print(shell, "> Total app-keys: %d", total);
+}
+
+static int cmd_cdb_show(const struct shell *shell, size_t argc,
+			char *argv[])
+{
+	if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
+		shell_print(shell, "No valid networks");
+		return 0;
+	}
+
+	shell_print(shell, "Mesh Network Information");
+	shell_print(shell, "========================");
+
+	cdb_print_nodes(shell);
+	shell_print(shell, "---");
+	cdb_print_subnets(shell);
+	shell_print(shell, "---");
+	cdb_print_app_keys(shell);
+
+	return 0;
+}
+
+static int cmd_cdb_node_add(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	struct bt_mesh_cdb_node *node;
+	uint8_t uuid[16], dev_key[16];
+	uint16_t addr, net_idx;
+	uint8_t num_elem;
+	size_t len;
+
+	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
+	memset(uuid + len, 0, sizeof(uuid) - len);
+
+	addr = strtoul(argv[2], NULL, 0);
+	num_elem = strtoul(argv[3], NULL, 0);
+	net_idx = strtoul(argv[4], NULL, 0);
+
+	if (argc < 6) {
+		bt_rand(dev_key, 16);
+	} else {
+		len = hex2bin(argv[5], strlen(argv[5]), dev_key,
+			      sizeof(dev_key));
+		memset(dev_key + len, 0, sizeof(dev_key) - len);
+	}
+
+	node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
+	if (node == NULL) {
+		shell_print(shell, "Failed to allocate node");
+		return 0;
+	}
+
+	memcpy(node->dev_key, dev_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_node(node);
+	}
+
+	shell_print(shell, "Added node 0x%04x", addr);
+
+	return 0;
+}
+
+static int cmd_cdb_node_del(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	struct bt_mesh_cdb_node *node;
+	uint16_t addr;
+
+	addr = strtoul(argv[1], NULL, 0);
+
+	node = bt_mesh_cdb_node_get(addr);
+	if (node == NULL) {
+		shell_print(shell, "No node with address 0x%04x", addr);
+		return 0;
+	}
+
+	bt_mesh_cdb_node_del(node, true);
+
+	shell_print(shell, "Deleted node 0x%04x", addr);
+
+	return 0;
+}
+
+static int cmd_cdb_subnet_add(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	struct bt_mesh_cdb_subnet *sub;
+	uint8_t net_key[16];
+	uint16_t net_idx;
+	size_t len;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+
+	if (argc < 3) {
+		bt_rand(net_key, 16);
+	} else {
+		len = hex2bin(argv[2], strlen(argv[2]), net_key,
+			      sizeof(net_key));
+		memset(net_key + len, 0, sizeof(net_key) - len);
+	}
+
+	sub = bt_mesh_cdb_subnet_alloc(net_idx);
+	if (sub == NULL) {
+		shell_print(shell, "Could not add subnet");
+		return 0;
+	}
+
+	memcpy(sub->keys[0].net_key, net_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_subnet(sub);
+	}
+
+	shell_print(shell, "Added Subnet 0x%03x", net_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_subnet_del(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	struct bt_mesh_cdb_subnet *sub;
+	uint16_t net_idx;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+
+	sub = bt_mesh_cdb_subnet_get(net_idx);
+	if (sub == NULL) {
+		shell_print(shell, "No subnet with NetIdx 0x%03x", net_idx);
+		return 0;
+	}
+
+	bt_mesh_cdb_subnet_del(sub, true);
+
+	shell_print(shell, "Deleted subnet 0x%03x", net_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_app_key_add(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	struct bt_mesh_cdb_app_key *key;
+	uint16_t net_idx, app_idx;
+	uint8_t app_key[16];
+	size_t len;
+
+	net_idx = strtoul(argv[1], NULL, 0);
+	app_idx = strtoul(argv[2], NULL, 0);
+
+	if (argc < 4) {
+		bt_rand(app_key, 16);
+	} else {
+		len = hex2bin(argv[3], strlen(argv[3]), app_key,
+			      sizeof(app_key));
+		memset(app_key + len, 0, sizeof(app_key) - len);
+	}
+
+	key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
+	if (key == NULL) {
+		shell_print(shell, "Could not add AppKey");
+		return 0;
+	}
+
+	memcpy(key->keys[0].app_key, app_key, 16);
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		bt_mesh_store_cdb_app_key(key);
+	}
+
+	shell_print(shell, "Added AppKey 0x%03x", app_idx);
+
+	return 0;
+}
+
+static int cmd_cdb_app_key_del(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	struct bt_mesh_cdb_app_key *key;
+	uint16_t app_idx;
+
+	app_idx = strtoul(argv[1], NULL, 0);
+
+	key = bt_mesh_cdb_app_key_get(app_idx);
+	if (key == NULL) {
+		shell_print(shell, "No AppKey 0x%03x", app_idx);
+		return 0;
+	}
+
+	bt_mesh_cdb_app_key_del(key, true);
+
+	shell_print(shell, "Deleted AppKey 0x%03x", app_idx);
+
+	return 0;
+}
+#endif
+
+/* List of Mesh subcommands.
+ *
+ * Each command is documented in doc/reference/bluetooth/mesh/shell.rst.
+ *
+ * Please keep the documentation up to date by adding any new commands to the
+ * list.
+ */
+SHELL_STATIC_SUBCMD_SET_CREATE(mesh_cmds,
+	/* General operations */
+	SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1, 0),
+	SHELL_CMD_ARG(reset, NULL, NULL, cmd_reset, 1, 0),
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	SHELL_CMD_ARG(lpn, NULL, "<value: off, on>", cmd_lpn, 2, 0),
+	SHELL_CMD_ARG(poll, NULL, NULL, cmd_poll, 1, 0),
+#endif
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+	SHELL_CMD_ARG(ident, NULL, NULL, cmd_ident, 1, 0),
+#endif
+	SHELL_CMD_ARG(dst, NULL, "[destination address]", cmd_dst, 1, 1),
+	SHELL_CMD_ARG(netidx, NULL, "[NetIdx]", cmd_netidx, 1, 1),
+	SHELL_CMD_ARG(appidx, NULL, "[AppIdx]", cmd_appidx, 1, 1),
+
+	/* Commands which access internal APIs, for testing only */
+	SHELL_CMD_ARG(net-send, NULL, "<hex string>", cmd_net_send, 2, 0),
+#if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
+	SHELL_CMD_ARG(iv-update, NULL, NULL, cmd_iv_update, 1, 0),
+	SHELL_CMD_ARG(iv-update-test, NULL, "<value: off, on>",
+		      cmd_iv_update_test, 2, 0),
+#endif
+	SHELL_CMD_ARG(rpl-clear, NULL, NULL, cmd_rpl_clear, 1, 0),
+
+	/* Provisioning operations */
+#if defined(CONFIG_BT_MESH_PB_GATT)
+	SHELL_CMD_ARG(pb-gatt, NULL, "<val: off, on>", cmd_pb_gatt, 2, 0),
+#endif
+#if defined(CONFIG_BT_MESH_PB_ADV)
+	SHELL_CMD_ARG(pb-adv, NULL, "<val: off, on>", cmd_pb_adv, 2, 0),
+#if defined(CONFIG_BT_MESH_PROVISIONER)
+	SHELL_CMD_ARG(provision-adv, NULL, "<UUID> <NetKeyIndex> <addr> "
+		      "<AttentionDuration>", cmd_provision_adv, 5, 0),
+#endif
+#endif
+	SHELL_CMD_ARG(uuid, NULL, "<UUID: 1-16 hex values>", cmd_uuid, 2, 0),
+	SHELL_CMD_ARG(input-num, NULL, "<number>", cmd_input_num, 2, 0),
+	SHELL_CMD_ARG(input-str, NULL, "<string>", cmd_input_str, 2, 0),
+	SHELL_CMD_ARG(static-oob, NULL, "[val: 1-16 hex values]",
+		      cmd_static_oob, 2, 1),
+	SHELL_CMD_ARG(provision, NULL, "<NetKeyIndex> <addr> [IVIndex]",
+		      cmd_provision, 3, 1),
+	SHELL_CMD_ARG(beacon-listen, NULL, "<val: off, on>", cmd_beacon_listen,
+		      2, 0),
+
+	/* Configuration Client Model operations */
+	SHELL_CMD_ARG(timeout, NULL, "[timeout in seconds]", cmd_timeout, 1, 1),
+	SHELL_CMD_ARG(get-comp, NULL, "[page]", cmd_get_comp, 1, 1),
+	SHELL_CMD_ARG(beacon, NULL, "[val: off, on]", cmd_beacon, 2, 1),
+	SHELL_CMD_ARG(ttl, NULL, "[ttl: 0x00, 0x02-0x7f]", cmd_ttl, 1, 1),
+	SHELL_CMD_ARG(friend, NULL, "[val: off, on]", cmd_friend, 1, 1),
+	SHELL_CMD_ARG(gatt-proxy, NULL, "[val: off, on]", cmd_gatt_proxy, 1, 1),
+	SHELL_CMD_ARG(relay, NULL,
+		      "[<val: off, on> [<count: 0-7> [interval: 10-320]]]",
+		      cmd_relay, 1, 3),
+	SHELL_CMD_ARG(net-key-add, NULL, "<NetKeyIndex> [val]", cmd_net_key_add,
+		      2, 1),
+	SHELL_CMD_ARG(net-key-get, NULL, NULL, cmd_net_key_get, 1, 0),
+	SHELL_CMD_ARG(net-key-del, NULL, "<NetKeyIndex>", cmd_net_key_del, 2,
+		      0),
+	SHELL_CMD_ARG(app-key-add, NULL, "<NetKeyIndex> <AppKeyIndex> [val]",
+		      cmd_app_key_add, 3, 1),
+	SHELL_CMD_ARG(app-key-del, NULL, "<NetKeyIndex> <AppKeyIndex>",
+		      cmd_app_key_del, 3, 0),
+	SHELL_CMD_ARG(app-key-get, NULL, "<NetKeyIndex>", cmd_app_key_get, 2,
+		      0),
+	SHELL_CMD_ARG(net-transmit-param, NULL, "[<count: 0-7>"
+			" <interval: 10-320>]", cmd_net_transmit, 1, 2),
+	SHELL_CMD_ARG(mod-app-bind, NULL,
+		      "<addr> <AppIndex> <Model ID> [Company ID]",
+		      cmd_mod_app_bind, 4, 1),
+	SHELL_CMD_ARG(mod-app-get, NULL,
+		      "<elem addr> <Model ID> [Company ID]",
+		      cmd_mod_app_get, 3, 1),
+	SHELL_CMD_ARG(mod-app-unbind, NULL,
+		      "<addr> <AppIndex> <Model ID> [Company ID]",
+		      cmd_mod_app_unbind, 4, 1),
+	SHELL_CMD_ARG(mod-pub, NULL, "<addr> <mod id> [cid] [<PubAddr> "
+		      "<AppKeyIndex> <cred: off, on> <ttl> <period> <count> <interval>]",
+		      cmd_mod_pub, 3, 1 + 7),
+	SHELL_CMD_ARG(mod-sub-add, NULL,
+		      "<elem addr> <sub addr> <Model ID> [Company ID]",
+		      cmd_mod_sub_add, 4, 1),
+	SHELL_CMD_ARG(mod-sub-del, NULL,
+		      "<elem addr> <sub addr> <Model ID> [Company ID]",
+		      cmd_mod_sub_del, 4, 1),
+	SHELL_CMD_ARG(mod-sub-add-va, NULL,
+		      "<elem addr> <Label UUID> <Model ID> [Company ID]",
+		      cmd_mod_sub_add_va, 4, 1),
+	SHELL_CMD_ARG(mod-sub-del-va, NULL,
+		      "<elem addr> <Label UUID> <Model ID> [Company ID]",
+		      cmd_mod_sub_del_va, 4, 1),
+	SHELL_CMD_ARG(mod-sub-get, NULL,
+		      "<elem addr> <Model ID> [Company ID]",
+		      cmd_mod_sub_get, 3, 1),
+	SHELL_CMD_ARG(hb-sub, NULL, "[<src> <dst> <period>]", cmd_hb_sub, 1, 3),
+	SHELL_CMD_ARG(hb-pub, NULL,
+		      "[<dst> <count> <period> <ttl> <features> <NetKeyIndex>]",
+		      cmd_hb_pub, 1, 6),
+
+	/* Health Client Model Operations */
+	SHELL_CMD_ARG(fault-get, NULL, "<Company ID>", cmd_fault_get, 2, 0),
+	SHELL_CMD_ARG(fault-clear, NULL, "<Company ID>", cmd_fault_clear, 2, 0),
+	SHELL_CMD_ARG(fault-clear-unack, NULL, "<Company ID>",
+		      cmd_fault_clear_unack, 2, 0),
+	SHELL_CMD_ARG(fault-test, NULL, "<Company ID> <Test ID>",
+		      cmd_fault_test, 3, 0),
+	SHELL_CMD_ARG(fault-test-unack, NULL, "<Company ID> <Test ID>",
+		      cmd_fault_test_unack, 3, 0),
+	SHELL_CMD_ARG(period-get, NULL, NULL, cmd_period_get, 1, 0),
+	SHELL_CMD_ARG(period-set, NULL, "<divisor>", cmd_period_set, 2, 0),
+	SHELL_CMD_ARG(period-set-unack, NULL, "<divisor>", cmd_period_set_unack,
+		      2, 0),
+	SHELL_CMD_ARG(attention-get, NULL, NULL, cmd_attention_get, 1, 0),
+	SHELL_CMD_ARG(attention-set, NULL, "<timer>", cmd_attention_set, 2, 0),
+	SHELL_CMD_ARG(attention-set-unack, NULL, "<timer>",
+		      cmd_attention_set_unack, 2, 0),
+
+	/* Health Server Model Operations */
+	SHELL_CMD_ARG(add-fault, NULL, "<Fault ID>", cmd_add_fault, 2, 0),
+	SHELL_CMD_ARG(del-fault, NULL, "[Fault ID]", cmd_del_fault, 1, 1),
+
+#if defined(CONFIG_BT_MESH_CDB)
+	/* Mesh Configuration Database Operations */
+	SHELL_CMD_ARG(cdb-create, NULL, "[NetKey]", cmd_cdb_create, 1, 1),
+	SHELL_CMD_ARG(cdb-clear, NULL, NULL, cmd_cdb_clear, 1, 0),
+	SHELL_CMD_ARG(cdb-show, NULL, NULL, cmd_cdb_show, 1, 0),
+	SHELL_CMD_ARG(cdb-node-add, NULL, "<UUID> <addr> <num-elem> "
+		      "<NetKeyIdx> [DevKey]", cmd_cdb_node_add, 5, 1),
+	SHELL_CMD_ARG(cdb-node-del, NULL, "<addr>", cmd_cdb_node_del, 2, 0),
+	SHELL_CMD_ARG(cdb-subnet-add, NULL, "<NeyKeyIdx> [<NetKey>]",
+		      cmd_cdb_subnet_add, 2, 1),
+	SHELL_CMD_ARG(cdb-subnet-del, NULL, "<NetKeyIdx>", cmd_cdb_subnet_del,
+		      2, 0),
+	SHELL_CMD_ARG(cdb-app-key-add, NULL, "<NetKeyIdx> <AppKeyIdx> "
+		      "[<AppKey>]", cmd_cdb_app_key_add, 3, 1),
+	SHELL_CMD_ARG(cdb-app-key-del, NULL, "<AppKeyIdx>", cmd_cdb_app_key_del,
+		      2, 0),
+#endif
+
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_mesh(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -EINVAL;
+}
+
+SHELL_CMD_ARG_REGISTER(mesh, &mesh_cmds, "Bluetooth Mesh shell commands",
+		       cmd_mesh, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.h	(working copy)
@@ -0,0 +1,16 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_BT_MESH_SELF_TEST)
+int bt_mesh_test(void);
+#else
+static inline int bt_mesh_test(void)
+{
+	return 0;
+}
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/test.c	(working copy)
@@ -0,0 +1,23 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include <bluetooth/mesh.h>
+
+#define LOG_MODULE_NAME bt_mesh_test
+#include "common/log.h"
+
+#include "mesh.h"
+#include "test.h"
+
+int bt_mesh_test(void)
+{
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.h	(working copy)
@@ -0,0 +1,105 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define TRANS_SEQ_AUTH_NVAL            0xffffffffffffffff
+
+#define BT_MESH_SDU_UNSEG_MAX          11
+#define BT_MESH_CTL_SEG_SDU_MAX        8
+#define BT_MESH_APP_SEG_SDU_MAX        12
+#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
+#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
+#define BT_MESH_RX_CTL_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_CTL_SEG_SDU_MAX)
+
+#define TRANS_SEQ_ZERO_MASK            ((uint16_t)BIT_MASK(13))
+#define TRANS_CTL_OP_MASK              ((uint8_t)BIT_MASK(7))
+#define TRANS_CTL_OP(data)             ((data)[0] & TRANS_CTL_OP_MASK)
+#define TRANS_CTL_HDR(op, seg)         ((op & TRANS_CTL_OP_MASK) | (seg << 7))
+
+#define TRANS_CTL_OP_ACK               0x00
+#define TRANS_CTL_OP_FRIEND_POLL       0x01
+#define TRANS_CTL_OP_FRIEND_UPDATE     0x02
+#define TRANS_CTL_OP_FRIEND_REQ        0x03
+#define TRANS_CTL_OP_FRIEND_OFFER      0x04
+#define TRANS_CTL_OP_FRIEND_CLEAR      0x05
+#define TRANS_CTL_OP_FRIEND_CLEAR_CFM  0x06
+#define TRANS_CTL_OP_FRIEND_SUB_ADD    0x07
+#define TRANS_CTL_OP_FRIEND_SUB_REM    0x08
+#define TRANS_CTL_OP_FRIEND_SUB_CFM    0x09
+#define TRANS_CTL_OP_HEARTBEAT         0x0a
+
+struct bt_mesh_ctl_friend_poll {
+	uint8_t  fsn;
+} __packed;
+
+struct bt_mesh_ctl_friend_update {
+	uint8_t  flags;
+	uint32_t iv_index;
+	uint8_t  md;
+} __packed;
+
+struct bt_mesh_ctl_friend_req {
+	uint8_t  criteria;
+	uint8_t  recv_delay;
+	uint8_t  poll_to[3];
+	uint16_t prev_addr;
+	uint8_t  num_elem;
+	uint16_t lpn_counter;
+} __packed;
+
+struct bt_mesh_ctl_friend_offer {
+	uint8_t  recv_win;
+	uint8_t  queue_size;
+	uint8_t  sub_list_size;
+	int8_t  rssi;
+	uint16_t frnd_counter;
+} __packed;
+
+struct bt_mesh_ctl_friend_clear {
+	uint16_t lpn_addr;
+	uint16_t lpn_counter;
+} __packed;
+
+struct bt_mesh_ctl_friend_clear_confirm {
+	uint16_t lpn_addr;
+	uint16_t lpn_counter;
+} __packed;
+
+#define BT_MESH_FRIEND_SUB_MIN_LEN (1 + 2)
+struct bt_mesh_ctl_friend_sub {
+	uint8_t  xact;
+	uint16_t addr_list[5];
+} __packed;
+
+struct bt_mesh_ctl_friend_sub_confirm {
+	uint8_t xact;
+} __packed;
+
+void bt_mesh_set_hb_sub_dst(uint16_t addr);
+
+struct bt_mesh_app_key *bt_mesh_app_key_find(uint16_t app_idx);
+
+bool bt_mesh_tx_in_progress(void);
+
+void bt_mesh_rx_reset(void);
+void bt_mesh_tx_reset(void);
+
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+		     size_t data_len, const struct bt_mesh_send_cb *cb,
+		     void *cb_data);
+
+int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
+		       const struct bt_mesh_send_cb *cb, void *cb_data);
+
+int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx);
+
+void bt_mesh_trans_init(void);
+
+int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data);
+
+int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
+			uint16_t addr, const uint8_t **key, uint8_t *aid);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/mesh/transport.c	(working copy)
@@ -0,0 +1,1880 @@
+/*  Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/util.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/mesh.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_TRANS)
+#define LOG_MODULE_NAME bt_mesh_transport
+#include "common/log.h"
+
+#include "host/testing.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh.h"
+#include "net.h"
+#include "lpn.h"
+#include "rpl.h"
+#include "friend.h"
+#include "access.h"
+#include "foundation.h"
+#include "settings.h"
+#include "transport.h"
+
+#define AID_MASK                    ((uint8_t)(BIT_MASK(6)))
+
+#define SEG(data)                   ((data)[0] >> 7)
+#define AKF(data)                   (((data)[0] >> 6) & 0x01)
+#define AID(data)                   ((data)[0] & AID_MASK)
+#define ASZMIC(data)                (((data)[1] >> 7) & 1)
+
+#define APP_MIC_LEN(aszmic) ((aszmic) ? BT_MESH_MIC_LONG : BT_MESH_MIC_SHORT)
+
+#define UNSEG_HDR(akf, aid)         ((akf << 6) | (aid & AID_MASK))
+#define SEG_HDR(akf, aid)           (UNSEG_HDR(akf, aid) | 0x80)
+
+#define BLOCK_COMPLETE(seg_n)       (uint32_t)(((uint64_t)1 << (seg_n + 1)) - 1)
+
+#define SEQ_AUTH(iv_index, seq)     (((uint64_t)iv_index) << 24 | (uint64_t)seq)
+
+/* Number of retransmit attempts (after the initial transmit) per segment */
+#define SEG_RETRANSMIT_ATTEMPTS     4
+
+/* "This timer shall be set to a minimum of 200 + 50 * TTL milliseconds.".
+ * We use 400 since 300 is a common send duration for standard HCI, and we
+ * need to have a timeout that's bigger than that.
+ */
+#define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) (400 + 50 * (tx)->ttl)
+/* When sending to a group, the messages are not acknowledged, and there's no
+ * reason to delay the repetitions significantly. Delaying by more than 0 ms
+ * to avoid flooding the network.
+ */
+#define SEG_RETRANSMIT_TIMEOUT_GROUP 50
+
+#define SEG_RETRANSMIT_TIMEOUT(tx)                                             \
+	(BT_MESH_ADDR_IS_UNICAST(tx->dst) ?                                    \
+		 SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) :                          \
+		 SEG_RETRANSMIT_TIMEOUT_GROUP)
+/* How long to wait for available buffers before giving up */
+#define BUF_TIMEOUT                 K_NO_WAIT
+
+static struct seg_tx {
+	struct bt_mesh_subnet *sub;
+	void                  *seg[CONFIG_BT_MESH_TX_SEG_MAX];
+	uint64_t              seq_auth;
+	uint16_t              src;
+	uint16_t              dst;
+	uint16_t              len;
+	uint8_t               hdr;
+	uint8_t               xmit;
+	uint8_t               seg_n;         /* Last segment index */
+	uint8_t               seg_o;         /* Segment being sent */
+	uint8_t               nack_count;    /* Number of unacked segs */
+	uint8_t               attempts;      /* Remaining tx attempts */
+	uint8_t               ttl;           /* Transmitted TTL value */
+	uint8_t               seg_pending;   /* Number of segments pending */
+	uint8_t               blocked:1,     /* Blocked by ongoing tx */
+			      ctl:1,         /* Control packet */
+			      aszmic:1,      /* MIC size */
+			      started:1,     /* Start cb called */
+			      sending:1,     /* Sending is in progress */
+			      friend_cred:1; /* Using Friend credentials */
+	const struct bt_mesh_send_cb *cb;
+	void                  *cb_data;
+	struct k_delayed_work retransmit;    /* Retransmit timer */
+} seg_tx[CONFIG_BT_MESH_TX_SEG_MSG_COUNT];
+
+static struct seg_rx {
+	struct bt_mesh_subnet   *sub;
+	void                    *seg[CONFIG_BT_MESH_RX_SEG_MAX];
+	uint64_t                    seq_auth;
+	uint16_t                    src;
+	uint16_t                    dst;
+	uint16_t                    len;
+	uint8_t                     hdr;
+	uint8_t                     seg_n:5,
+				 ctl:1,
+				 in_use:1,
+				 obo:1;
+	uint8_t                     ttl;
+	uint32_t                    block;
+	uint32_t                    last;
+	struct k_delayed_work    ack;
+} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
+
+K_MEM_SLAB_DEFINE(segs, BT_MESH_APP_SEG_SDU_MAX, CONFIG_BT_MESH_SEG_BUFS, 4);
+
+static uint16_t hb_sub_dst = BT_MESH_ADDR_UNASSIGNED;
+
+void bt_mesh_set_hb_sub_dst(uint16_t addr)
+{
+	hb_sub_dst = addr;
+}
+
+static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
+		      const struct bt_mesh_send_cb *cb, void *cb_data,
+		      const uint8_t *ctl_op)
+{
+	struct net_buf *buf;
+
+	buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
+	if (!buf) {
+		BT_ERR("Out of network buffers");
+		return -ENOBUFS;
+	}
+
+	net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
+
+	if (ctl_op) {
+		net_buf_add_u8(buf, TRANS_CTL_HDR(*ctl_op, 0));
+	} else if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
+		net_buf_add_u8(buf, UNSEG_HDR(0, 0));
+	} else {
+		net_buf_add_u8(buf, UNSEG_HDR(1, tx->aid));
+	}
+
+	net_buf_add_mem(buf, sdu->data, sdu->len);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx,
+						    tx->src, tx->ctx->addr,
+						    NULL, 1)) {
+			if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
+				BT_ERR("Not enough space in Friend Queue");
+				net_buf_unref(buf);
+				return -ENOBUFS;
+			} else {
+				BT_WARN("No space in Friend Queue");
+				goto send;
+			}
+		}
+
+		if (bt_mesh_friend_enqueue_tx(tx, BT_MESH_FRIEND_PDU_SINGLE,
+					      NULL, 1, &buf->b) &&
+		    BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
+			/* PDUs for a specific Friend should only go
+			 * out through the Friend Queue.
+			 */
+			net_buf_unref(buf);
+			send_cb_finalize(cb, cb_data);
+			return 0;
+		}
+	}
+
+send:
+	return bt_mesh_net_send(tx, buf, cb, cb_data);
+}
+
+static inline uint8_t seg_len(bool ctl)
+{
+	if (ctl) {
+		return BT_MESH_CTL_SEG_SDU_MAX;
+	} else {
+		return BT_MESH_APP_SEG_SDU_MAX;
+	}
+}
+
+bool bt_mesh_tx_in_progress(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
+		if (seg_tx[i].nack_count) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
+{
+	k_mem_slab_free(&segs, (void **)&tx->seg[seg_idx]);
+	tx->seg[seg_idx] = NULL;
+	tx->nack_count--;
+}
+
+static bool seg_tx_blocks(struct seg_tx *tx, uint16_t src, uint16_t dst)
+{
+	return (tx->src == src) && (tx->dst == dst);
+}
+
+static void seg_tx_unblock_check(struct seg_tx *tx)
+{
+	struct seg_tx *blocked = NULL;
+	int i;
+
+	/* Unblock the first blocked tx with the same params. */
+	for (i = 0; i < ARRAY_SIZE(seg_tx); ++i) {
+		if (&seg_tx[i] != tx &&
+		    seg_tx[i].blocked &&
+		    seg_tx_blocks(tx, seg_tx[i].src, seg_tx[i].dst) &&
+		    (!blocked || seg_tx[i].seq_auth < blocked->seq_auth)) {
+			blocked = &seg_tx[i];
+		}
+	}
+
+	if (blocked) {
+		BT_DBG("Unblocked 0x%04x",
+		       (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK));
+		blocked->blocked = false;
+		k_delayed_work_submit(&blocked->retransmit, K_NO_WAIT);
+	}
+}
+
+static void seg_tx_reset(struct seg_tx *tx)
+{
+	int i;
+
+	k_delayed_work_cancel(&tx->retransmit);
+
+	tx->cb = NULL;
+	tx->cb_data = NULL;
+	tx->seq_auth = 0U;
+	tx->sub = NULL;
+	tx->src = BT_MESH_ADDR_UNASSIGNED;
+	tx->dst = BT_MESH_ADDR_UNASSIGNED;
+	tx->blocked = false;
+
+	for (i = 0; i <= tx->seg_n && tx->nack_count; i++) {
+		if (!tx->seg[i]) {
+			continue;
+		}
+
+		seg_tx_done(tx, i);
+	}
+
+	tx->nack_count = 0;
+
+	if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) {
+		BT_DBG("Proceeding with pending IV Update");
+		/* bt_mesh_net_iv_update() will re-enable the flag if this
+		 * wasn't the only transfer.
+		 */
+		if (bt_mesh_net_iv_update(bt_mesh.iv_index, false)) {
+			bt_mesh_net_sec_update(NULL);
+		}
+	}
+}
+
+static inline void seg_tx_complete(struct seg_tx *tx, int err)
+{
+	const struct bt_mesh_send_cb *cb = tx->cb;
+	void *cb_data = tx->cb_data;
+
+	seg_tx_unblock_check(tx);
+
+	seg_tx_reset(tx);
+
+	if (cb && cb->end) {
+		cb->end(err, cb_data);
+	}
+}
+
+static void schedule_retransmit(struct seg_tx *tx)
+{
+	if (!tx->nack_count) {
+		return;
+	}
+
+	if (--tx->seg_pending || tx->sending) {
+		return;
+	}
+
+	BT_DBG("");
+
+	/* If we haven't gone through all the segments for this attempt yet,
+	 * (likely because of a buffer allocation failure or because we
+	 * called this from inside bt_mesh_net_send), we should continue the
+	 * retransmit immediately, as we just freed up a tx buffer.
+	 */
+	k_delayed_work_submit(&tx->retransmit,
+			      tx->seg_o ? K_NO_WAIT :
+					  K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
+}
+
+static void seg_send_start(uint16_t duration, int err, void *user_data)
+{
+	struct seg_tx *tx = user_data;
+
+	if (!tx->started && tx->cb && tx->cb->start) {
+		tx->cb->start(duration, err, tx->cb_data);
+		tx->started = 1U;
+	}
+
+	/* If there's an error in transmitting the 'sent' callback will never
+	 * be called. Make sure that we kick the retransmit timer also in this
+	 * case since otherwise we risk the transmission of becoming stale.
+	 */
+	if (err) {
+		schedule_retransmit(tx);
+	}
+}
+
+static void seg_sent(int err, void *user_data)
+{
+	struct seg_tx *tx = user_data;
+
+	schedule_retransmit(tx);
+}
+
+static const struct bt_mesh_send_cb seg_sent_cb = {
+	.start = seg_send_start,
+	.end = seg_sent,
+};
+
+static void seg_tx_buf_build(struct seg_tx *tx, uint8_t seg_o,
+			     struct net_buf_simple *buf)
+{
+	uint16_t seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
+	uint8_t len = MIN(seg_len(tx->ctl), tx->len - (seg_len(tx->ctl) * seg_o));
+
+	net_buf_simple_add_u8(buf, tx->hdr);
+	net_buf_simple_add_u8(buf, (tx->aszmic << 7) | seq_zero >> 6);
+	net_buf_simple_add_u8(buf, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
+	net_buf_simple_add_u8(buf, ((seg_o & 0x07) << 5) | tx->seg_n);
+	net_buf_simple_add_mem(buf, tx->seg[seg_o], len);
+}
+
+static void seg_tx_send_unacked(struct seg_tx *tx)
+{
+	if (!tx->nack_count) {
+		return;
+	}
+
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = tx->sub->net_idx,
+		/* App idx only used by network to detect control messages: */
+		.app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0),
+		.addr = tx->dst,
+		.send_rel = true,
+		.send_ttl = tx->ttl,
+	};
+	struct bt_mesh_net_tx net_tx = {
+		.sub = tx->sub,
+		.ctx = &ctx,
+		.src = tx->src,
+		.xmit = tx->xmit,
+		.friend_cred = tx->friend_cred,
+		.aid = tx->hdr & AID_MASK,
+	};
+
+	if (!tx->attempts) {
+		if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+			BT_ERR("Ran out of retransmit attempts");
+			seg_tx_complete(tx, -ETIMEDOUT);
+		} else {
+			/* Segmented sending to groups doesn't have acks, so
+			 * running out of attempts is the expected behavior.
+			 */
+			seg_tx_complete(tx, 0);
+		}
+
+		return;
+	}
+
+	BT_DBG("SeqZero: 0x%04x Attempts: %u",
+	       (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts);
+
+	tx->sending = 1U;
+
+	for (; tx->seg_o <= tx->seg_n; tx->seg_o++) {
+		struct net_buf *seg;
+		int err;
+
+		if (!tx->seg[tx->seg_o]) {
+			continue;
+		}
+
+		seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit,
+					 BUF_TIMEOUT);
+		if (!seg) {
+			BT_DBG("Allocating segment failed");
+			goto end;
+		}
+
+		net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
+		seg_tx_buf_build(tx, tx->seg_o, &seg->b);
+
+		tx->seg_pending++;
+
+		BT_DBG("Sending %u/%u", tx->seg_o, tx->seg_n);
+
+		err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx);
+		if (err) {
+			BT_DBG("Sending segment failed");
+			tx->seg_pending--;
+			goto end;
+		}
+	}
+
+	tx->seg_o = 0U;
+	tx->attempts--;
+
+end:
+	if (!tx->seg_pending) {
+		k_delayed_work_submit(&tx->retransmit,
+				      K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
+	}
+
+	tx->sending = 0U;
+}
+
+static void seg_retransmit(struct k_work *work)
+{
+	struct seg_tx *tx = CONTAINER_OF(work, struct seg_tx, retransmit);
+
+	seg_tx_send_unacked(tx);
+}
+
+static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
+		    const struct bt_mesh_send_cb *cb, void *cb_data,
+		    uint8_t *ctl_op)
+{
+	bool blocked = false;
+	struct seg_tx *tx;
+	uint8_t seg_o;
+	int i;
+
+	BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
+	       net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx,
+	       net_tx->aszmic, sdu->len);
+
+	for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) {
+		if (seg_tx[i].nack_count) {
+			blocked |= seg_tx_blocks(&seg_tx[i], net_tx->src,
+						 net_tx->ctx->addr);
+		} else if (!tx) {
+			tx = &seg_tx[i];
+		}
+	}
+
+	if (!tx) {
+		BT_ERR("No multi-segment message contexts available");
+		return -EBUSY;
+	}
+
+	if (ctl_op) {
+		tx->hdr = TRANS_CTL_HDR(*ctl_op, 1);
+	} else if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
+		tx->hdr = SEG_HDR(0, 0);
+	} else {
+		tx->hdr = SEG_HDR(1, net_tx->aid);
+	}
+
+	tx->src = net_tx->src;
+	tx->dst = net_tx->ctx->addr;
+	tx->seg_n = (sdu->len - 1) / seg_len(!!ctl_op);
+	tx->seg_o = 0;
+	tx->len = sdu->len;
+	tx->nack_count = tx->seg_n + 1;
+	tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
+	tx->sub = net_tx->sub;
+	tx->cb = cb;
+	tx->cb_data = cb_data;
+	tx->attempts = SEG_RETRANSMIT_ATTEMPTS;
+	tx->seg_pending = 0;
+	tx->xmit = net_tx->xmit;
+	tx->aszmic = net_tx->aszmic;
+	tx->friend_cred = net_tx->friend_cred;
+	tx->blocked = blocked;
+	tx->started = 0;
+	tx->ctl = !!ctl_op;
+
+	if (net_tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+		tx->ttl = bt_mesh_default_ttl_get();
+	} else {
+		tx->ttl = net_tx->ctx->send_ttl;
+	}
+
+	BT_DBG("SeqZero 0x%04x (segs: %u)",
+	       (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->nack_count);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
+	    !bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src,
+					    tx->dst, &tx->seq_auth,
+					    tx->seg_n + 1) &&
+	    BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+		BT_ERR("Not enough space in Friend Queue for %u segments",
+		       tx->seg_n + 1);
+		seg_tx_reset(tx);
+		return -ENOBUFS;
+	}
+
+	for (seg_o = 0U; sdu->len; seg_o++) {
+		void *buf;
+		uint16_t len;
+		int err;
+
+		err = k_mem_slab_alloc(&segs, &buf, BUF_TIMEOUT);
+		if (err) {
+			BT_ERR("Out of segment buffers");
+			seg_tx_reset(tx);
+			return -ENOBUFS;
+		}
+
+		len = MIN(sdu->len, seg_len(!!ctl_op));
+		memcpy(buf, net_buf_simple_pull_mem(sdu, len), len);
+
+		BT_DBG("seg %u: %s", seg_o, bt_hex(buf, len));
+
+		tx->seg[seg_o] = buf;
+
+		if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+			enum bt_mesh_friend_pdu_type type;
+
+			NET_BUF_SIMPLE_DEFINE(seg, 16);
+			seg_tx_buf_build(tx, seg_o, &seg);
+
+			if (seg_o == tx->seg_n) {
+				type = BT_MESH_FRIEND_PDU_COMPLETE;
+			} else {
+				type = BT_MESH_FRIEND_PDU_PARTIAL;
+			}
+
+			if (bt_mesh_friend_enqueue_tx(
+				    net_tx, type, ctl_op ? NULL : &tx->seq_auth,
+				    tx->seg_n + 1, &seg) &&
+			    BT_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
+				/* PDUs for a specific Friend should only go
+				 * out through the Friend Queue.
+				 */
+				k_mem_slab_free(&segs, &buf);
+				tx->seg[seg_o] = NULL;
+			}
+
+		}
+
+	}
+
+	/* This can happen if segments only went into the Friend Queue */
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !tx->seg[0]) {
+		seg_tx_reset(tx);
+
+		/* If there was a callback notify sending immediately since
+		 * there's no other way to track this (at least currently)
+		 * with the Friend Queue.
+		 */
+		send_cb_finalize(cb, cb_data);
+		return 0;
+	}
+
+	if (blocked) {
+		/* Move the sequence number, so we don't end up creating
+		 * another segmented transmission with the same SeqZero while
+		 * this one is blocked.
+		 */
+		bt_mesh_next_seq();
+		BT_DBG("Blocked.");
+		return 0;
+	}
+
+	seg_tx_send_unacked(tx);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+	    bt_mesh_lpn_established()) {
+		bt_mesh_lpn_poll();
+	}
+
+	return 0;
+}
+
+struct bt_mesh_app_key *bt_mesh_app_key_find(uint16_t app_idx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		if (key->net_idx != BT_MESH_KEY_UNUSED &&
+		    key->app_idx == app_idx) {
+			return key;
+		}
+	}
+
+	return NULL;
+}
+
+int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
+		       const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	const uint8_t *key;
+	uint8_t *ad;
+	uint8_t aid;
+	int err;
+
+	if (msg->len < 1) {
+		BT_ERR("Zero-length SDU not allowed");
+		return -EINVAL;
+	}
+
+	if (msg->len > BT_MESH_TX_SDU_MAX) {
+		BT_ERR("Not enough segment buffers for length %u", msg->len);
+		return -EMSGSIZE;
+	}
+
+	if (net_buf_simple_tailroom(msg) < 4) {
+		BT_ERR("Insufficient tailroom for Transport MIC");
+		return -EINVAL;
+	}
+
+	if (msg->len > BT_MESH_SDU_UNSEG_MAX) {
+		tx->ctx->send_rel = true;
+	}
+
+	BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx,
+	       tx->ctx->app_idx, tx->ctx->addr);
+	BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
+
+	err = bt_mesh_app_key_get(tx->sub, tx->ctx->app_idx,
+				  tx->ctx->addr, &key, &aid);
+	if (err) {
+		return err;
+	}
+
+	tx->aid = aid;
+
+	if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
+		tx->aszmic = 0U;
+	} else {
+		tx->aszmic = 1U;
+	}
+
+	if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+		ad = bt_mesh_label_uuid_get(tx->ctx->addr);
+	} else {
+		ad = NULL;
+	}
+
+	err = bt_mesh_app_encrypt(key, BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
+				  tx->aszmic, msg, ad, tx->src, tx->ctx->addr,
+				  bt_mesh.seq, BT_MESH_NET_IVI_TX);
+	if (err) {
+		return err;
+	}
+
+	if (tx->ctx->send_rel) {
+		err = send_seg(tx, msg, cb, cb_data, NULL);
+	} else {
+		err = send_unseg(tx, msg, cb, cb_data, NULL);
+	}
+
+	return err;
+}
+
+static void seg_rx_assemble(struct seg_rx *rx, struct net_buf_simple *buf,
+			    uint8_t aszmic)
+{
+	int i;
+
+	net_buf_simple_reset(buf);
+
+	for (i = 0; i <= rx->seg_n; i++) {
+		net_buf_simple_add_mem(buf, rx->seg[i],
+				       MIN(seg_len(rx->ctl),
+					   rx->len - (i * seg_len(rx->ctl))));
+	}
+
+	/* Adjust the length to not contain the MIC at the end */
+	if (!rx->ctl) {
+		buf->len -= APP_MIC_LEN(aszmic);
+	}
+}
+
+static int remote_devkey_decrypt(struct bt_mesh_net_rx *rx, uint32_t seq, uint8_t *ad,
+				 uint8_t aszmic, struct net_buf_simple *buf,
+				 struct net_buf_simple *sdu)
+{
+	struct bt_mesh_cdb_node *node;
+	int err;
+
+	if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
+		return -ENOENT;
+	}
+
+	/* We will try our local devkey separately. */
+	if (bt_mesh_elem_find(rx->ctx.addr)) {
+		return -ENOENT;
+	}
+
+	/*
+	 * There is no way of knowing if we should use our
+	 * local DevKey or the remote DevKey to decrypt the
+	 * message so we must try both.
+	 */
+	node = bt_mesh_cdb_node_get(rx->ctx.addr);
+	if (node == NULL) {
+		BT_ERR("No node found for addr 0x%04x", rx->ctx.addr);
+		return -EINVAL;
+	}
+
+	err = bt_mesh_app_decrypt(node->dev_key, true, aszmic, buf, sdu, ad,
+				  rx->ctx.addr, rx->ctx.recv_dst, seq,
+				  BT_MESH_NET_IVI_RX(rx));
+	if (err) {
+		BT_DBG("Unable to decrypt with node DevKey");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int app_key_decrypt(struct bt_mesh_net_rx *rx,
+			   struct bt_mesh_app_key *key, uint32_t seq, uint8_t *ad,
+			   uint8_t hdr, uint8_t aszmic, struct net_buf_simple *buf,
+			   struct net_buf_simple *sdu)
+{
+	struct bt_mesh_app_keys *keys;
+	int err;
+
+	/* Check that this AppKey matches received net_idx */
+	if (key->net_idx != rx->sub->net_idx) {
+		return -EINVAL;
+	}
+
+	if (rx->new_key && key->updated) {
+		keys = &key->keys[1];
+	} else {
+		keys = &key->keys[0];
+	}
+
+	/* Check that the AppKey ID matches */
+	if (AID(&hdr) != keys->id) {
+		return -EINVAL;
+	}
+
+	err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf, sdu, ad,
+				  rx->ctx.addr, rx->ctx.recv_dst, seq,
+				  BT_MESH_NET_IVI_RX(rx));
+	if (err) {
+		BT_WARN("Unable to decrypt with AppKey 0x%03x", key->app_idx);
+	}
+
+	return err;
+}
+
+static int sdu_recv_unseg(struct bt_mesh_net_rx *rx, uint8_t hdr,
+			  struct net_buf_simple *buf)
+{
+	NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_SDU_UNSEG_MAX);
+	uint8_t *ad;
+	uint16_t i;
+	int err;
+
+	BT_DBG("AKF %u AID 0x%02x", AKF(&hdr), AID(&hdr));
+	BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
+
+	if (buf->len < 1 + APP_MIC_LEN(0)) {
+		BT_ERR("Too short SDU + MIC");
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
+		BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
+		       rx->ctx.recv_dst);
+		return 0;
+	}
+
+	if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
+		ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
+	} else {
+		ad = NULL;
+	}
+
+	/* Adjust the length to not contain the MIC at the end */
+	buf->len -= APP_MIC_LEN(0);
+
+	if (!AKF(&hdr)) {
+		/* Attempt remote dev key first, as that is only available for
+		 * provisioner devices, which normally don't interact with nodes
+		 * that know their local dev key.
+		 */
+		net_buf_simple_reset(&sdu);
+		err = remote_devkey_decrypt(rx, rx->seq, ad, 0, buf, &sdu);
+		if (!err) {
+			rx->ctx.app_idx = BT_MESH_KEY_DEV_REMOTE;
+			bt_mesh_model_recv(rx, &sdu);
+			return 0;
+		}
+
+		net_buf_simple_reset(&sdu);
+		err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, 0, buf, &sdu,
+					  ad, rx->ctx.addr, rx->ctx.recv_dst,
+					  rx->seq, BT_MESH_NET_IVI_RX(rx));
+		if (err) {
+			BT_ERR("Unable to decrypt with local DevKey");
+			return err;
+		}
+
+		rx->ctx.app_idx = BT_MESH_KEY_DEV_LOCAL;
+		bt_mesh_model_recv(rx, &sdu);
+		return 0;
+	}
+
+	for (i = 0U; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		net_buf_simple_reset(&sdu);
+		err = app_key_decrypt(rx, &bt_mesh.app_keys[i], rx->seq, ad,
+				      hdr, 0, buf, &sdu);
+
+		if (err) {
+			continue;
+		}
+
+		rx->ctx.app_idx = key->app_idx;
+
+		bt_mesh_model_recv(rx, &sdu);
+		return 0;
+	}
+
+	if (rx->local_match) {
+		BT_WARN("No matching AppKey");
+	}
+
+	return 0;
+}
+
+static int sdu_recv_seg(struct seg_rx *seg, uint8_t hdr, uint8_t aszmic,
+			struct bt_mesh_net_rx *rx)
+{
+	NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX);
+	struct net_buf_simple sdu;
+	uint32_t seq = (seg->seq_auth & 0xffffff);
+	uint8_t *ad;
+	uint16_t i;
+	int err;
+
+	BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr));
+
+	if (seg->len < 1 + APP_MIC_LEN(aszmic)) {
+		BT_ERR("Too short SDU + MIC");
+		return -EINVAL;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
+		BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
+		       rx->ctx.recv_dst);
+		return 0;
+	}
+
+	if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
+		ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
+	} else {
+		ad = NULL;
+	}
+
+	/* Decrypting in place to avoid creating two assembly buffers.
+	 * We'll reassemble the buffer from the segments before each decryption
+	 * attempt.
+	 */
+	if (!AKF(&hdr)) {
+		/* Attempt remote dev key first, as that is only available for
+		 * provisioner devices, which normally don't interact with nodes
+		 * that know their local dev key.
+		 */
+		seg_rx_assemble(seg, &buf, aszmic);
+		net_buf_simple_init_with_data(&sdu, buf.data,
+					      seg->len - APP_MIC_LEN(aszmic));
+		sdu.len = 0;
+
+		err = remote_devkey_decrypt(rx, seq, ad, aszmic, &buf, &sdu);
+		if (!err) {
+			rx->ctx.app_idx = BT_MESH_KEY_DEV_REMOTE;
+			bt_mesh_model_recv(rx, &sdu);
+			return 0;
+		}
+
+		seg_rx_assemble(seg, &buf, aszmic);
+		net_buf_simple_init_with_data(&sdu, buf.data,
+					      seg->len - APP_MIC_LEN(aszmic));
+		sdu.len = 0;
+
+		err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, &buf,
+					  &sdu, ad, rx->ctx.addr,
+					  rx->ctx.recv_dst, seq,
+					  BT_MESH_NET_IVI_RX(rx));
+		if (err) {
+			BT_ERR("Unable to decrypt with local DevKey");
+			return err;
+		}
+
+		rx->ctx.app_idx = BT_MESH_KEY_DEV_LOCAL;
+		bt_mesh_model_recv(rx, &sdu);
+		return 0;
+	}
+
+	for (i = 0U; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
+		struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+
+		seg_rx_assemble(seg, &buf, aszmic);
+		net_buf_simple_init_with_data(&sdu, buf.data,
+					      seg->len - APP_MIC_LEN(aszmic));
+		sdu.len = 0;
+
+		err = app_key_decrypt(rx, &bt_mesh.app_keys[i], seq, ad, hdr,
+				      aszmic, &buf, &sdu);
+		if (err) {
+			continue;
+		}
+
+		rx->ctx.app_idx = key->app_idx;
+
+		bt_mesh_model_recv(rx, &sdu);
+		return 0;
+	}
+
+	if (rx->local_match) {
+		BT_WARN("No matching AppKey");
+	}
+
+	return 0;
+}
+
+static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t addr)
+{
+	struct seg_tx *tx;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
+		tx = &seg_tx[i];
+
+		if ((tx->seq_auth & TRANS_SEQ_ZERO_MASK) != seq_zero) {
+			continue;
+		}
+
+		if (tx->dst == addr) {
+			return tx;
+		}
+
+		/* If the expected remote address doesn't match,
+		 * but the OBO flag is set and this is the first
+		 * acknowledgement, assume it's a Friend that's
+		 * responding and therefore accept the message.
+		 */
+		if (obo && tx->nack_count == tx->seg_n + 1) {
+			tx->dst = addr;
+			return tx;
+		}
+	}
+
+	return NULL;
+}
+
+static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
+		     struct net_buf_simple *buf, uint64_t *seq_auth)
+{
+	struct seg_tx *tx;
+	unsigned int bit;
+	uint32_t ack;
+	uint16_t seq_zero;
+	uint8_t obo;
+
+	if (buf->len < 6) {
+		BT_ERR("Too short ack message");
+		return -EINVAL;
+	}
+
+	seq_zero = net_buf_simple_pull_be16(buf);
+	obo = seq_zero >> 15;
+	seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match) {
+		BT_DBG("Ack for LPN 0x%04x of this Friend", rx->ctx.recv_dst);
+		/* Best effort - we don't have enough info for true SeqAuth */
+		*seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_RX(rx), seq_zero);
+		return 0;
+	}
+
+	ack = net_buf_simple_pull_be32(buf);
+
+	BT_DBG("OBO %u seq_zero 0x%04x ack 0x%08x", obo, seq_zero, ack);
+
+	tx = seg_tx_lookup(seq_zero, obo, rx->ctx.addr);
+	if (!tx) {
+		BT_WARN("No matching TX context for ack");
+		return -EINVAL;
+	}
+
+	if (!BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+		BT_ERR("Received ack for group seg");
+		return -EINVAL;
+	}
+
+	*seq_auth = tx->seq_auth;
+
+	if (!ack) {
+		BT_WARN("SDU canceled");
+		seg_tx_complete(tx, -ECANCELED);
+		return 0;
+	}
+
+	if (find_msb_set(ack) - 1 > tx->seg_n) {
+		BT_ERR("Too large segment number in ack");
+		return -EINVAL;
+	}
+
+	k_delayed_work_cancel(&tx->retransmit);
+
+	while ((bit = find_lsb_set(ack))) {
+		if (tx->seg[bit - 1]) {
+			BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
+			seg_tx_done(tx, bit - 1);
+		}
+
+		ack &= ~BIT(bit - 1);
+	}
+
+	if (tx->nack_count) {
+		seg_tx_send_unacked(tx);
+	} else {
+		BT_DBG("SDU TX complete");
+		seg_tx_complete(tx, 0);
+	}
+
+	return 0;
+}
+
+static int trans_heartbeat(struct bt_mesh_net_rx *rx,
+			   struct net_buf_simple *buf)
+{
+	uint8_t init_ttl, hops;
+	uint16_t feat;
+
+	if (buf->len < 3) {
+		BT_ERR("Too short heartbeat message");
+		return -EINVAL;
+	}
+
+	if (rx->ctx.recv_dst != hb_sub_dst) {
+		BT_WARN("Ignoring heartbeat to non-subscribed destination");
+		return 0;
+	}
+
+	init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
+	feat = net_buf_simple_pull_be16(buf);
+
+	hops = (init_ttl - rx->ctx.recv_ttl + 1);
+
+	BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
+	       rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
+	       (hops == 1U) ? "" : "s", feat);
+
+	bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
+
+	return 0;
+}
+
+static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr,
+		    struct net_buf_simple *buf, uint64_t *seq_auth)
+{
+	uint8_t ctl_op = TRANS_CTL_OP(&hdr);
+
+	BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->len);
+
+	switch (ctl_op) {
+	case TRANS_CTL_OP_ACK:
+		return trans_ack(rx, hdr, buf, seq_auth);
+	case TRANS_CTL_OP_HEARTBEAT:
+		return trans_heartbeat(rx, buf);
+	}
+
+	/* Only acks and heartbeats may need processing without local_match */
+	if (!rx->local_match) {
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !bt_mesh_lpn_established()) {
+		switch (ctl_op) {
+		case TRANS_CTL_OP_FRIEND_POLL:
+			return bt_mesh_friend_poll(rx, buf);
+		case TRANS_CTL_OP_FRIEND_REQ:
+			return bt_mesh_friend_req(rx, buf);
+		case TRANS_CTL_OP_FRIEND_CLEAR:
+			return bt_mesh_friend_clear(rx, buf);
+		case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
+			return bt_mesh_friend_clear_cfm(rx, buf);
+		case TRANS_CTL_OP_FRIEND_SUB_ADD:
+			return bt_mesh_friend_sub_add(rx, buf);
+		case TRANS_CTL_OP_FRIEND_SUB_REM:
+			return bt_mesh_friend_sub_rem(rx, buf);
+		}
+	}
+
+#if defined(CONFIG_BT_MESH_LOW_POWER)
+	if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) {
+		return bt_mesh_lpn_friend_offer(rx, buf);
+	}
+
+	if (rx->ctx.addr == bt_mesh.lpn.frnd) {
+		if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) {
+			return bt_mesh_lpn_friend_clear_cfm(rx, buf);
+		}
+
+		if (!rx->friend_cred) {
+			BT_WARN("Message from friend with wrong credentials");
+			return -EINVAL;
+		}
+
+		switch (ctl_op) {
+		case TRANS_CTL_OP_FRIEND_UPDATE:
+			return bt_mesh_lpn_friend_update(rx, buf);
+		case TRANS_CTL_OP_FRIEND_SUB_CFM:
+			return bt_mesh_lpn_friend_sub_cfm(rx, buf);
+		}
+	}
+#endif /* CONFIG_BT_MESH_LOW_POWER */
+
+	BT_WARN("Unhandled TransOpCode 0x%02x", ctl_op);
+
+	return -ENOENT;
+}
+
+static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
+		       uint64_t *seq_auth)
+{
+	uint8_t hdr;
+
+	BT_DBG("AFK %u AID 0x%02x", AKF(buf->data), AID(buf->data));
+
+	if (buf->len < 1) {
+		BT_ERR("Too small unsegmented PDU");
+		return -EINVAL;
+	}
+
+	if (bt_mesh_rpl_check(rx, NULL)) {
+		BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
+			rx->ctx.addr, rx->ctx.recv_dst, rx->seq);
+		return -EINVAL;
+	}
+
+	hdr = net_buf_simple_pull_u8(buf);
+
+	if (rx->ctl) {
+		return ctl_recv(rx, hdr, buf, seq_auth);
+	} else {
+		/* SDUs must match a local element or an LPN of this Friend. */
+		if (!rx->local_match && !rx->friend_match) {
+			return 0;
+		}
+
+		return sdu_recv_unseg(rx, hdr, buf);
+	}
+}
+
+static inline int32_t ack_timeout(struct seg_rx *rx)
+{
+	int32_t to;
+	uint8_t ttl;
+
+	if (rx->ttl == BT_MESH_TTL_DEFAULT) {
+		ttl = bt_mesh_default_ttl_get();
+	} else {
+		ttl = rx->ttl;
+	}
+
+	/* The acknowledgment timer shall be set to a minimum of
+	 * 150 + 50 * TTL milliseconds.
+	 */
+	to = 150 + (ttl * 50U);
+
+	/* 100 ms for every not yet received segment */
+	to += ((rx->seg_n + 1) - popcount(rx->block)) * 100U;
+
+	/* Make sure we don't send more frequently than the duration for
+	 * each packet (default is 300ms).
+	 */
+	return MAX(to, 400);
+}
+
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+		     size_t data_len,
+		     const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	struct net_buf_simple buf;
+
+	net_buf_simple_init_with_data(&buf, data, data_len);
+
+	if (data_len > BT_MESH_SDU_UNSEG_MAX) {
+		tx->ctx->send_rel = true;
+	}
+
+	tx->ctx->app_idx = BT_MESH_KEY_UNUSED;
+
+	BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src,
+	       tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
+	BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
+
+	if (tx->ctx->send_rel) {
+		return send_seg(tx, &buf, cb, cb_data, &ctl_op);
+	} else {
+		return send_unseg(tx, &buf, cb, cb_data, &ctl_op);
+	}
+}
+
+static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst,
+		    uint8_t ttl, uint64_t *seq_auth, uint32_t block, uint8_t obo)
+{
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = sub->net_idx,
+		.app_idx = BT_MESH_KEY_UNUSED,
+		.addr = dst,
+		.send_ttl = ttl,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = sub,
+		.ctx = &ctx,
+		.src = obo ? bt_mesh_primary_addr() : src,
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+	uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
+	uint8_t buf[6];
+
+	BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero, block, obo);
+
+	if (bt_mesh_lpn_established()) {
+		BT_WARN("Not sending ack when LPN is enabled");
+		return 0;
+	}
+
+	/* This can happen if the segmented message was destined for a group
+	 * or virtual address.
+	 */
+	if (!BT_MESH_ADDR_IS_UNICAST(src)) {
+		BT_DBG("Not sending ack for non-unicast address");
+		return 0;
+	}
+
+	sys_put_be16(((seq_zero << 2) & 0x7ffc) | (obo << 15), buf);
+	sys_put_be32(block, &buf[2]);
+
+	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_ACK, buf, sizeof(buf),
+				NULL, NULL);
+}
+
+static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
+{
+	int i;
+
+	BT_DBG("rx %p", rx);
+
+	k_delayed_work_cancel(&rx->ack);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo &&
+	    rx->block != BLOCK_COMPLETE(rx->seg_n)) {
+		BT_WARN("Clearing incomplete buffers from Friend queue");
+		bt_mesh_friend_clear_incomplete(rx->sub, rx->src, rx->dst,
+						&rx->seq_auth);
+	}
+
+	for (i = 0; i <= rx->seg_n; i++) {
+		if (!rx->seg[i]) {
+			continue;
+		}
+
+		k_mem_slab_free(&segs, &rx->seg[i]);
+		rx->seg[i] = NULL;
+	}
+
+	rx->in_use = 0U;
+
+	/* We don't always reset these values since we need to be able to
+	 * send an ack if we receive a segment after we've already received
+	 * the full SDU.
+	 */
+	if (full_reset) {
+		rx->seq_auth = 0U;
+		rx->sub = NULL;
+		rx->src = BT_MESH_ADDR_UNASSIGNED;
+		rx->dst = BT_MESH_ADDR_UNASSIGNED;
+	}
+}
+
+static void seg_ack(struct k_work *work)
+{
+	struct seg_rx *rx = CONTAINER_OF(work, struct seg_rx, ack);
+
+	BT_DBG("rx %p", rx);
+
+	if (k_uptime_get_32() - rx->last > (60 * MSEC_PER_SEC)) {
+		BT_WARN("Incomplete timer expired");
+		seg_rx_reset(rx, false);
+
+		if (IS_ENABLED(CONFIG_BT_TESTING)) {
+			bt_test_mesh_trans_incomp_timer_exp();
+		}
+
+		return;
+	}
+
+	send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
+		 rx->block, rx->obo);
+
+	k_delayed_work_submit(&rx->ack, K_MSEC(ack_timeout(rx)));
+}
+
+static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
+{
+	return (seg_n < CONFIG_BT_MESH_RX_SEG_MAX);
+}
+
+static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
+				  const uint64_t *seq_auth)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
+		struct seg_rx *rx = &seg_rx[i];
+
+		if (rx->src != net_rx->ctx.addr ||
+		    rx->dst != net_rx->ctx.recv_dst) {
+			continue;
+		}
+
+		/* Return newer RX context in addition to an exact match, so
+		 * the calling function can properly discard an old SeqAuth.
+		 */
+		if (rx->seq_auth >= *seq_auth) {
+			return rx;
+		}
+
+		if (rx->in_use) {
+			BT_WARN("Duplicate SDU from src 0x%04x",
+				net_rx->ctx.addr);
+
+			/* Clear out the old context since the sender
+			 * has apparently started sending a new SDU.
+			 */
+			seg_rx_reset(rx, true);
+
+			/* Return non-match so caller can re-allocate */
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
+			    const uint8_t *hdr, uint8_t seg_n)
+{
+	if (rx->hdr != *hdr || rx->seg_n != seg_n) {
+		BT_ERR("Invalid segment for ongoing session");
+		return false;
+	}
+
+	if (rx->src != net_rx->ctx.addr || rx->dst != net_rx->ctx.recv_dst) {
+		BT_ERR("Invalid source or destination for segment");
+		return false;
+	}
+
+	if (rx->ctl != net_rx->ctl) {
+		BT_ERR("Inconsistent CTL in segment");
+		return false;
+	}
+
+	return true;
+}
+
+static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
+				   const uint8_t *hdr, const uint64_t *seq_auth,
+				   uint8_t seg_n)
+{
+	int i;
+
+	/* No race condition on this check, as this function only executes in
+	 * the collaborative Bluetooth rx thread:
+	 */
+	if (k_mem_slab_num_free_get(&segs) < 1) {
+		BT_WARN("Not enough segments for incoming message");
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
+		struct seg_rx *rx = &seg_rx[i];
+
+		if (rx->in_use) {
+			continue;
+		}
+
+		rx->in_use = 1U;
+		rx->sub = net_rx->sub;
+		rx->ctl = net_rx->ctl;
+		rx->seq_auth = *seq_auth;
+		rx->seg_n = seg_n;
+		rx->hdr = *hdr;
+		rx->ttl = net_rx->ctx.send_ttl;
+		rx->src = net_rx->ctx.addr;
+		rx->dst = net_rx->ctx.recv_dst;
+		rx->block = 0U;
+
+		BT_DBG("New RX context. Block Complete 0x%08x",
+		       BLOCK_COMPLETE(seg_n));
+
+		return rx;
+	}
+
+	return NULL;
+}
+
+static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
+		     enum bt_mesh_friend_pdu_type *pdu_type, uint64_t *seq_auth,
+		     uint8_t *seg_count)
+{
+	struct bt_mesh_rpl *rpl = NULL;
+	struct seg_rx *rx;
+	uint8_t *hdr = buf->data;
+	uint16_t seq_zero;
+	uint8_t seg_n;
+	uint8_t seg_o;
+	int err;
+
+	if (buf->len < 5) {
+		BT_ERR("Too short segmented message (len %u)", buf->len);
+		return -EINVAL;
+	}
+
+	if (bt_mesh_rpl_check(net_rx, &rpl)) {
+		BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
+			net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
+		return -EINVAL;
+	}
+
+	BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr));
+
+	net_buf_simple_pull(buf, 1);
+
+	seq_zero = net_buf_simple_pull_be16(buf);
+	seg_o = (seq_zero & 0x03) << 3;
+	seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK;
+	seg_n = net_buf_simple_pull_u8(buf);
+	seg_o |= seg_n >> 5;
+	seg_n &= 0x1f;
+
+	BT_DBG("SeqZero 0x%04x SegO %u SegN %u", seq_zero, seg_o, seg_n);
+
+	if (seg_o > seg_n) {
+		BT_ERR("SegO greater than SegN (%u > %u)", seg_o, seg_n);
+		return -EINVAL;
+	}
+
+	/* According to Mesh 1.0 specification:
+	 * "The SeqAuth is composed of the IV Index and the sequence number
+	 *  (SEQ) of the first segment"
+	 *
+	 * Therefore we need to calculate very first SEQ in order to find
+	 * seqAuth. We can calculate as below:
+	 *
+	 * SEQ(0) = SEQ(n) - (delta between seqZero and SEQ(n) by looking into
+	 * 14 least significant bits of SEQ(n))
+	 *
+	 * Mentioned delta shall be >= 0, if it is not then seq_auth will
+	 * be broken and it will be verified by the code below.
+	 */
+	*seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_RX(net_rx),
+			     (net_rx->seq -
+			      ((((net_rx->seq & BIT_MASK(14)) - seq_zero)) &
+			       BIT_MASK(13))));
+
+	*seg_count = seg_n + 1;
+
+	/* Look for old RX sessions */
+	rx = seg_rx_find(net_rx, seq_auth);
+	if (rx) {
+		/* Discard old SeqAuth packet */
+		if (rx->seq_auth > *seq_auth) {
+			BT_WARN("Ignoring old SeqAuth");
+			return -EINVAL;
+		}
+
+		if (!seg_rx_is_valid(rx, net_rx, hdr, seg_n)) {
+			return -EINVAL;
+		}
+
+		if (rx->in_use) {
+			BT_DBG("Existing RX context. Block 0x%08x", rx->block);
+			goto found_rx;
+		}
+
+		if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
+			BT_DBG("Got segment for already complete SDU");
+
+			send_ack(net_rx->sub, net_rx->ctx.recv_dst,
+				 net_rx->ctx.addr, net_rx->ctx.send_ttl,
+				 seq_auth, rx->block, rx->obo);
+
+			if (rpl) {
+				bt_mesh_rpl_update(rpl, net_rx);
+			}
+
+			return -EALREADY;
+		}
+
+		/* We ignore instead of sending block ack 0 since the
+		 * ack timer is always smaller than the incomplete
+		 * timer, i.e. the sender is misbehaving.
+		 */
+		BT_WARN("Got segment for canceled SDU");
+		return -EINVAL;
+	}
+
+	/* Bail out early if we're not ready to receive such a large SDU */
+	if (!sdu_len_is_ok(net_rx->ctl, seg_n)) {
+		BT_ERR("Too big incoming SDU length");
+		send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
+			 net_rx->ctx.send_ttl, seq_auth, 0,
+			 net_rx->friend_match);
+		return -EMSGSIZE;
+	}
+
+	/* Verify early that there will be space in the Friend Queue(s) in
+	 * case this message is destined to an LPN of ours.
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
+	    net_rx->friend_match && !net_rx->local_match &&
+	    !bt_mesh_friend_queue_has_space(net_rx->sub->net_idx,
+					    net_rx->ctx.addr,
+					    net_rx->ctx.recv_dst, seq_auth,
+					    *seg_count)) {
+		BT_ERR("No space in Friend Queue for %u segments", *seg_count);
+		send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
+			 net_rx->ctx.send_ttl, seq_auth, 0,
+			 net_rx->friend_match);
+		return -ENOBUFS;
+	}
+
+	/* Look for free slot for a new RX session */
+	rx = seg_rx_alloc(net_rx, hdr, seq_auth, seg_n);
+	if (!rx) {
+		/* Warn but don't cancel since the existing slots willl
+		 * eventually be freed up and we'll be able to process
+		 * this one.
+		 */
+		BT_WARN("No free slots for new incoming segmented messages");
+		return -ENOMEM;
+	}
+
+	rx->obo = net_rx->friend_match;
+
+found_rx:
+	if (BIT(seg_o) & rx->block) {
+		BT_DBG("Received already received fragment");
+		return -EALREADY;
+	}
+
+	/* All segments, except the last one, must either have 8 bytes of
+	 * payload (for 64bit Net MIC) or 12 bytes of payload (for 32bit
+	 * Net MIC).
+	 */
+	if (seg_o == seg_n) {
+		/* Set the expected final buffer length */
+		rx->len = seg_n * seg_len(rx->ctl) + buf->len;
+		BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
+		       buf->len, rx->len);
+
+		if (rx->len > BT_MESH_RX_SDU_MAX) {
+			BT_ERR("Too large SDU len");
+			send_ack(net_rx->sub, net_rx->ctx.recv_dst,
+				 net_rx->ctx.addr, net_rx->ctx.send_ttl,
+				 seq_auth, 0, rx->obo);
+			seg_rx_reset(rx, true);
+			return -EMSGSIZE;
+		}
+	} else {
+		if (buf->len != seg_len(rx->ctl)) {
+			BT_ERR("Incorrect segment size for message type");
+			return -EINVAL;
+		}
+	}
+
+	/* Reset the Incomplete Timer */
+	rx->last = k_uptime_get_32();
+
+	if (!k_delayed_work_remaining_get(&rx->ack) &&
+	    !bt_mesh_lpn_established()) {
+		k_delayed_work_submit(&rx->ack, K_MSEC(ack_timeout(rx)));
+	}
+
+	/* Allocated segment here */
+	err = k_mem_slab_alloc(&segs, &rx->seg[seg_o], K_NO_WAIT);
+	if (err) {
+		BT_WARN("Unable allocate buffer for Seg %u", seg_o);
+		return -ENOBUFS;
+	}
+
+	memcpy(rx->seg[seg_o], buf->data, buf->len);
+
+	BT_DBG("Received %u/%u", seg_o, seg_n);
+
+	/* Mark segment as received */
+	rx->block |= BIT(seg_o);
+
+	if (rx->block != BLOCK_COMPLETE(seg_n)) {
+		*pdu_type = BT_MESH_FRIEND_PDU_PARTIAL;
+		return 0;
+	}
+
+	BT_DBG("Complete SDU");
+
+	if (rpl) {
+		bt_mesh_rpl_update(rpl, net_rx);
+	}
+
+	*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
+
+	k_delayed_work_cancel(&rx->ack);
+	send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr,
+		 net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
+
+	if (net_rx->ctl) {
+		NET_BUF_SIMPLE_DEFINE(sdu, BT_MESH_RX_CTL_MAX);
+		seg_rx_assemble(rx, &sdu, 0U);
+		err = ctl_recv(net_rx, *hdr, &sdu, seq_auth);
+	} else {
+		err = sdu_recv_seg(rx, *hdr, ASZMIC(hdr), net_rx);
+	}
+
+	seg_rx_reset(rx, false);
+
+	return err;
+}
+
+int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
+{
+	uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
+	enum bt_mesh_friend_pdu_type pdu_type = BT_MESH_FRIEND_PDU_SINGLE;
+	struct net_buf_simple_state state;
+	uint8_t seg_count = 0;
+	int err;
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+		rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx,
+							rx->ctx.recv_dst);
+	} else {
+		rx->friend_match = false;
+	}
+
+	BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u",
+	       rx->ctx.addr, rx->ctx.recv_dst, rx->seq, rx->friend_match);
+
+	/* Remove network headers */
+	net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
+
+	BT_DBG("Payload %s", bt_hex(buf->data, buf->len));
+
+	if (IS_ENABLED(CONFIG_BT_TESTING)) {
+		bt_test_mesh_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr,
+				      rx->ctx.recv_dst, buf->data, buf->len);
+	}
+
+	/* If LPN mode is enabled messages are only accepted when we've
+	 * requested the Friend to send them. The messages must also
+	 * be encrypted using the Friend Credentials.
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+	    bt_mesh_lpn_established() && rx->net_if == BT_MESH_NET_IF_ADV &&
+	    (!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) {
+		BT_WARN("Ignoring unexpected message in Low Power mode");
+		return -EAGAIN;
+	}
+
+	/* Save the app-level state so the buffer can later be placed in
+	 * the Friend Queue.
+	 */
+	net_buf_simple_save(buf, &state);
+
+	if (SEG(buf->data)) {
+		/* Segmented messages must match a local element or an
+		 * LPN of this Friend.
+		 */
+		if (!rx->local_match && !rx->friend_match) {
+			return 0;
+		}
+
+		err = trans_seg(buf, rx, &pdu_type, &seq_auth, &seg_count);
+	} else {
+		seg_count = 1;
+		err = trans_unseg(buf, rx, &seq_auth);
+	}
+
+	/* Notify LPN state machine so a Friend Poll will be sent. If the
+	 * message was a Friend Update it's possible that a Poll was already
+	 * queued for sending, however that's fine since then the
+	 * bt_mesh_lpn_waiting_update() function will return false:
+	 * we still need to go through the actual sending to the bearer and
+	 * wait for ReceiveDelay before transitioning to WAIT_UPDATE state.
+	 * Another situation where we want to notify the LPN state machine
+	 * is if it's configured to use an automatic Friendship establishment
+	 * timer, in which case we want to reset the timer at this point.
+	 *
+	 */
+	if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+	    (bt_mesh_lpn_timer() ||
+	     (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) {
+		bt_mesh_lpn_msg_received(rx);
+	}
+
+	net_buf_simple_restore(buf, &state);
+
+	if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match && !err) {
+		if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
+			bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
+						  seg_count, buf);
+		} else {
+			bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
+						  seg_count, buf);
+		}
+	}
+
+	return err;
+}
+
+void bt_mesh_rx_reset(void)
+{
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
+		seg_rx_reset(&seg_rx[i], true);
+	}
+
+	bt_mesh_rpl_clear();
+}
+
+void bt_mesh_tx_reset(void)
+{
+	int i;
+
+	BT_DBG("");
+
+	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
+		seg_tx_reset(&seg_tx[i]);
+	}
+}
+
+void bt_mesh_trans_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
+		k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
+		k_delayed_work_init(&seg_rx[i].ack, seg_ack);
+	}
+}
+
+int bt_mesh_heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+	struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+	uint16_t feat = 0U;
+	struct __packed {
+		uint8_t  init_ttl;
+		uint16_t feat;
+	} hb;
+	struct bt_mesh_msg_ctx ctx = {
+		.net_idx = cfg->hb_pub.net_idx,
+		.app_idx = BT_MESH_KEY_UNUSED,
+		.addr = cfg->hb_pub.dst,
+		.send_ttl = cfg->hb_pub.ttl,
+	};
+	struct bt_mesh_net_tx tx = {
+		.sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
+		.ctx = &ctx,
+		.src = bt_mesh_model_elem(cfg->model)->addr,
+		.xmit = bt_mesh_net_transmit_get(),
+	};
+
+	/* Do nothing if heartbeat publication is not enabled */
+	if (cfg->hb_pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+		return 0;
+	}
+
+	hb.init_ttl = cfg->hb_pub.ttl;
+
+	if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
+		feat |= BT_MESH_FEAT_RELAY;
+	}
+
+	if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+		feat |= BT_MESH_FEAT_PROXY;
+	}
+
+	if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
+		feat |= BT_MESH_FEAT_FRIEND;
+	}
+
+	if (bt_mesh_lpn_established()) {
+		feat |= BT_MESH_FEAT_LOW_POWER;
+	}
+
+	hb.feat = sys_cpu_to_be16(feat);
+
+	BT_DBG("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
+
+	return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
+				cb, cb_data);
+}
+
+int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, uint16_t app_idx,
+			uint16_t addr, const uint8_t **key, uint8_t *aid)
+{
+	struct bt_mesh_app_key *app_key;
+
+	if (app_idx == BT_MESH_KEY_DEV_LOCAL ||
+	    (app_idx == BT_MESH_KEY_DEV_REMOTE &&
+	     bt_mesh_elem_find(addr) != NULL)) {
+		*aid = 0;
+		*key = bt_mesh.dev_key;
+		return 0;
+	} else if (app_idx == BT_MESH_KEY_DEV_REMOTE) {
+		if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+			return -EINVAL;
+		}
+
+		struct bt_mesh_cdb_node *node = bt_mesh_cdb_node_get(addr);
+		if (!node) {
+			return -EINVAL;
+		}
+
+		*key = node->dev_key;
+		*aid = 0;
+		return 0;
+	}
+
+	if (!subnet) {
+		return -EINVAL;
+	}
+
+	app_key = bt_mesh_app_key_find(app_idx);
+	if (!app_key) {
+		return -ENOENT;
+	}
+
+	if (subnet->kr_phase == BT_MESH_KR_PHASE_2 && app_key->updated) {
+		*key = app_key->keys[1].val;
+		*aid = app_key->keys[1].id;
+	} else {
+		*key = app_key->keys[0].val;
+		*aid = app_key->keys[0].id;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/CMakeLists.txt	(working copy)
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0
+
+
+zephyr_sources_ifdef(CONFIG_BT_DIS dis.c)
+
+zephyr_sources_ifdef(CONFIG_BT_BAS bas.c)
+
+zephyr_sources_ifdef(CONFIG_BT_HRS hrs.c)
+
+add_subdirectory_ifdef(CONFIG_BT_OTS ots)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig	(working copy)
@@ -0,0 +1,17 @@
+# GATT Services
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menu "GATT Services"
+	depends on BT_CONN
+
+source "subsys/bluetooth/services/Kconfig.dis"
+
+source "subsys/bluetooth/services/Kconfig.bas"
+
+source "subsys/bluetooth/services/Kconfig.hrs"
+
+source "subsys/bluetooth/services/ots/Kconfig"
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.bas
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.bas	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.bas	(working copy)
@@ -0,0 +1,23 @@
+# Bluetooth GATT Battery service
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig BT_BAS
+	bool "Enable GATT Battery service"
+	select SENSOR
+
+config BT_BAS_LOG_LEVEL
+	int "Battery service log level"
+	depends on LOG
+	range 0 4
+	default 0
+	depends on BT_BAS
+	help
+	  Sets log level for the Battery service.
+	  Levels are:
+	  0 OFF, do not write
+	  1 ERROR, only write LOG_ERR
+	  2 WARNING, write LOG_WRN in addition to previous level
+	  3 INFO, write LOG_INF in addition to previous levels
+	  4 DEBUG, write LOG_DBG in addition to previous levels
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.dis
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.dis	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.dis	(working copy)
@@ -0,0 +1,144 @@
+# GATT Device Information service
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig BT_DIS
+	bool "Enable GATT Device Information service"
+
+if BT_DIS
+
+config BT_DIS_SETTINGS
+	bool "Enable Settings usage in Device Information Service"
+	help
+	  Enable Settings usage in Device Information Service.
+
+config BT_DIS_STR_MAX
+	int "Maximum size in bytes for DIS strings"
+	depends on BT_DIS_SETTINGS
+	default 21
+	range 2 248
+	help
+	  Bluetooth DIS string storage size. Storage can be up to 248 bytes
+	  long (excluding NULL termination).
+
+config BT_DIS_MODEL
+	string "Model name"
+	default SOC
+	help
+	  The device model inside Device Information Service.
+
+config BT_DIS_MANUF
+	string "Manufacturer name"
+	default "Manufacturer"
+	help
+	  The device manufacturer inside Device Information Service.
+
+config BT_DIS_PNP
+	bool "Enable PnP_ID characteristic"
+	default y
+	help
+	  Enable PnP_ID characteristic in Device Information Service.
+
+if BT_DIS_PNP
+
+config BT_DIS_PNP_VID_SRC
+	int "Vendor ID source"
+	range 1 2
+	default 1
+	help
+	  The Vendor ID Source field designates which organization assigned the
+	  value used in the Vendor ID field value.
+	  The possible values are:
+	  - 1 Bluetooth SIG, the Vendor ID was assigned by the Bluetooth SIG
+	  - 2 USB IF, the Vendor ID was assigned by the USB IF
+
+config BT_DIS_PNP_VID
+	hex "Vendor ID"
+	range 0 0xFFFF
+	default 0
+	help
+	  The Vendor ID field is intended to uniquely identify the vendor of the
+	  device. This field is used in conjunction with Vendor ID Source field,
+	  which determines which organization assigned the Vendor ID field value.
+	  Note: The Bluetooth Special Interest Group assigns Device ID Vendor ID,
+	  and the USB Implementers Forum assigns Vendor IDs,
+	  either of which can be used for the Vendor ID field value.
+	  Device providers should procure the Vendor ID from the USB Implementers
+	  Forum or the Company Identifier from the Bluetooth SIG.
+
+config BT_DIS_PNP_PID
+	hex "Product ID"
+	range 0 0xFFFF
+	default 0
+	help
+	  The Product ID field is intended to distinguish between different products
+	  made by the vendor identified with the Vendor ID field. The vendors
+	  themselves manage Product ID field values.
+
+config BT_DIS_PNP_VER
+	hex "Product Version"
+	range 0 0xFFFF
+	default 1
+	help
+	  The Product Version field is a numeric expression identifying the device
+	  release number in Binary-Coded Decimal. This is a vendor-assigned value,
+	  which defines the version of the product identified by the Vendor ID and
+	  Product ID fields. This field is intended to differentiate between
+	  versions of products with identical Vendor IDs and Product IDs.
+	  The value of the field value is 0xJJMN for version JJ.M.N
+	  (JJ - major version number, M - minor version number,
+	  N - sub-minor version number); e.g., version 2.1.3 is represented with
+	  value 0x0213 and version 2.0.0 is represented with a value of 0x0200.
+	  When upward-compatible changes are made to the device, it is recommended
+	  that the minor version number be incremented. If incompatible changes are
+	  made to the device, it is recommended that the major version number be
+	  incremented. The sub-minor version is incremented for bug fixes.
+
+endif # BT_DIS_PNP
+
+config BT_DIS_SERIAL_NUMBER
+	bool "Enable DIS Serial number characteristic"
+	help
+	  Enable Serial Number characteristic in Device Information Service.
+
+config BT_DIS_SERIAL_NUMBER_STR
+	string "Serial Number"
+	depends on BT_DIS_SERIAL_NUMBER
+	help
+	  Enable Serial Number characteristic in Device Information Service.
+
+config BT_DIS_FW_REV
+	bool "Enable DIS Firmware Revision characteristic"
+	help
+	  Enable Firmware Revision characteristic in Device Information Service.
+
+config BT_DIS_FW_REV_STR
+	string "Firmware revision"
+	depends on BT_DIS_FW_REV
+	help
+	  Enable firmware revision characteristic in Device Information Service.
+
+config BT_DIS_HW_REV
+	bool "Enable DIS Hardware Revision characteristic"
+	help
+	  Enable Hardware Revision characteristic in Device Information Service.
+
+config BT_DIS_HW_REV_STR
+	string "Hardware revision"
+	depends on BT_DIS_HW_REV
+	help
+	  Enable hardware revision characteristic in Device Information Service.
+
+config BT_DIS_SW_REV
+	bool "Enable DIS Software Revision characteristic"
+	help
+	  Enable Software Revision characteristic in Device Information Service.
+
+config BT_DIS_SW_REV_STR
+	string "Software revision"
+	depends on BT_DIS_SW_REV
+	help
+	  Enable software revision characteristic in Device Information Service.
+
+endif # BT_DIS
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.hrs
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.hrs	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/Kconfig.hrs	(working copy)
@@ -0,0 +1,22 @@
+# Bluetooth GATT Heart Rate service
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig BT_HRS
+	bool "Enable GATT Heart Rate service"
+
+config BT_HRS_LOG_LEVEL
+	int "Heart Rate service log level"
+	depends on LOG
+	range 0 4
+	default 0
+	depends on BT_HRS
+	help
+	  Sets log level for the Heart Rate service.
+	  Levels are:
+	  0 OFF, do not write
+	  1 ERROR, only write LOG_ERR
+	  2 WARNING, write LOG_WRN in addition to previous level
+	  3 INFO, write LOG_INF in addition to previous levels
+	  4 DEBUG, write LOG_DBG in addition to previous levels
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/bas.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/bas.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/bas.c	(working copy)
@@ -0,0 +1,87 @@
+/** @file
+ *  @brief GATT Battery Service
+ */
+
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <init.h>
+#include <sys/__assert.h>
+#include <stdbool.h>
+#include <zephyr/types.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/gatt.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/services/bas.h>
+
+#define LOG_LEVEL CONFIG_BT_BAS_LOG_LEVEL
+#include <logging/log.h>
+LOG_MODULE_REGISTER(bas);
+
+static uint8_t battery_level = 100U;
+
+static void blvl_ccc_cfg_changed(const struct bt_gatt_attr *attr,
+				       uint16_t value)
+{
+	ARG_UNUSED(attr);
+
+	bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
+
+	LOG_INF("BAS Notifications %s", notif_enabled ? "enabled" : "disabled");
+}
+
+static ssize_t read_blvl(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, void *buf,
+			       uint16_t len, uint16_t offset)
+{
+	uint8_t lvl8 = battery_level;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &lvl8,
+				 sizeof(lvl8));
+}
+
+BT_GATT_SERVICE_DEFINE(bas,
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS),
+	BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL,
+			       BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
+			       BT_GATT_PERM_READ, read_blvl, NULL,
+			       &battery_level),
+	BT_GATT_CCC(blvl_ccc_cfg_changed,
+		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+);
+
+static int bas_init(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	return 0;
+}
+
+uint8_t bt_bas_get_battery_level(void)
+{
+	return battery_level;
+}
+
+int bt_bas_set_battery_level(uint8_t level)
+{
+	int rc;
+
+	if (level > 100U) {
+		return -EINVAL;
+	}
+
+	battery_level = level;
+
+	rc = bt_gatt_notify(NULL, &bas.attrs[1], &level, sizeof(level));
+
+	return rc == -ENOTCONN ? 0 : rc;
+}
+
+SYS_INIT(bas_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/dis.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/dis.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/dis.c	(working copy)
@@ -0,0 +1,239 @@
+/** @file
+ *  @brief GATT Device Information Service
+ */
+
+/*
+ * Copyright (c) 2019 Demant
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <zephyr.h>
+#include <init.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+
+#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SERVICE)
+#define LOG_MODULE_NAME bt_dis
+#include "common/log.h"
+
+#if CONFIG_BT_DIS_PNP
+struct dis_pnp {
+	uint8_t pnp_vid_src;
+	uint16_t pnp_vid;
+	uint16_t pnp_pid;
+	uint16_t pnp_ver;
+} __packed;
+
+static struct dis_pnp dis_pnp_id = {
+	.pnp_vid_src = CONFIG_BT_DIS_PNP_VID_SRC,
+	.pnp_vid = CONFIG_BT_DIS_PNP_VID,
+	.pnp_pid = CONFIG_BT_DIS_PNP_PID,
+	.pnp_ver = CONFIG_BT_DIS_PNP_VER,
+};
+#endif
+
+#if defined(CONFIG_BT_DIS_SETTINGS)
+static uint8_t dis_model[CONFIG_BT_DIS_STR_MAX] = CONFIG_BT_DIS_MODEL;
+static uint8_t dis_manuf[CONFIG_BT_DIS_STR_MAX] = CONFIG_BT_DIS_MANUF;
+#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
+static uint8_t dis_serial_number[CONFIG_BT_DIS_STR_MAX] =
+	CONFIG_BT_DIS_SERIAL_NUMBER_STR;
+#endif
+#if defined(CONFIG_BT_DIS_FW_REV)
+static uint8_t dis_fw_rev[CONFIG_BT_DIS_STR_MAX] =
+	CONFIG_BT_DIS_FW_REV_STR;
+#endif
+#if defined(CONFIG_BT_DIS_HW_REV)
+static uint8_t dis_hw_rev[CONFIG_BT_DIS_STR_MAX] =
+	CONFIG_BT_DIS_HW_REV_STR;
+#endif
+#if defined(CONFIG_BT_DIS_SW_REV)
+static uint8_t dis_sw_rev[CONFIG_BT_DIS_STR_MAX] =
+	CONFIG_BT_DIS_SW_REV_STR;
+#endif
+
+#define BT_DIS_MODEL_REF		dis_model
+#define BT_DIS_MANUF_REF		dis_manuf
+#define BT_DIS_SERIAL_NUMBER_STR_REF	dis_serial_number
+#define BT_DIS_FW_REV_STR_REF		dis_fw_rev
+#define BT_DIS_HW_REV_STR_REF		dis_hw_rev
+#define BT_DIS_SW_REV_STR_REF		dis_sw_rev
+
+#else /* CONFIG_BT_DIS_SETTINGS */
+
+#define BT_DIS_MODEL_REF		CONFIG_BT_DIS_MODEL
+#define BT_DIS_MANUF_REF		CONFIG_BT_DIS_MANUF
+#define BT_DIS_SERIAL_NUMBER_STR_REF	CONFIG_BT_DIS_SERIAL_NUMBER_STR
+#define BT_DIS_FW_REV_STR_REF		CONFIG_BT_DIS_FW_REV_STR
+#define BT_DIS_HW_REV_STR_REF		CONFIG_BT_DIS_HW_REV_STR
+#define BT_DIS_SW_REV_STR_REF		CONFIG_BT_DIS_SW_REV_STR
+
+#endif /* CONFIG_BT_DIS_SETTINGS */
+
+static ssize_t read_str(struct bt_conn *conn,
+			  const struct bt_gatt_attr *attr, void *buf,
+			  uint16_t len, uint16_t offset)
+{
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
+				 strlen(attr->user_data));
+}
+
+#if CONFIG_BT_DIS_PNP
+static ssize_t read_pnp_id(struct bt_conn *conn,
+			   const struct bt_gatt_attr *attr, void *buf,
+			   uint16_t len, uint16_t offset)
+{
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &dis_pnp_id,
+				 sizeof(dis_pnp_id));
+}
+#endif
+
+/* Device Information Service Declaration */
+BT_GATT_SERVICE_DEFINE(dis_svc,
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS),
+
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL, BT_DIS_MODEL_REF),
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL, BT_DIS_MANUF_REF),
+#if CONFIG_BT_DIS_PNP
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_PNP_ID,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_pnp_id, NULL, &dis_pnp_id),
+#endif
+
+#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SERIAL_NUMBER,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL,
+			       BT_DIS_SERIAL_NUMBER_STR_REF),
+#endif
+#if defined(CONFIG_BT_DIS_FW_REV)
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_FIRMWARE_REVISION,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL, BT_DIS_FW_REV_STR_REF),
+#endif
+#if defined(CONFIG_BT_DIS_HW_REV)
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_HARDWARE_REVISION,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL, BT_DIS_HW_REV_STR_REF),
+#endif
+#if defined(CONFIG_BT_DIS_SW_REV)
+	BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SOFTWARE_REVISION,
+			       BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
+			       read_str, NULL, BT_DIS_SW_REV_STR_REF),
+#endif
+
+);
+
+#if defined(CONFIG_BT_SETTINGS) && defined(CONFIG_BT_DIS_SETTINGS)
+static int dis_set(const char *name, size_t len_rd,
+		   settings_read_cb read_cb, void *store)
+{
+	ssize_t len;
+	int nlen;
+	const char *next;
+
+	nlen = settings_name_next(name, &next);
+	if (!strncmp(name, "manuf", nlen)) {
+		len = read_cb(store, &dis_manuf, sizeof(dis_manuf) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read manufacturer from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_manuf[len] = '\0';
+
+			BT_DBG("Manufacturer set to %s", dis_manuf);
+		}
+		return 0;
+	}
+	if (!strncmp(name, "model", nlen)) {
+		len = read_cb(store, &dis_model, sizeof(dis_model) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read model from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_model[len] = '\0';
+
+			BT_DBG("Model set to %s", dis_model);
+		}
+		return 0;
+	}
+#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
+	if (!strncmp(name, "serial", nlen)) {
+		len = read_cb(store, &dis_serial_number,
+			   sizeof(dis_serial_number) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read serial number from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_serial_number[len] = '\0';
+
+			BT_DBG("Serial number set to %s", dis_serial_number);
+		}
+		return 0;
+	}
+#endif
+#if defined(CONFIG_BT_DIS_FW_REV)
+	if (!strncmp(name, "fw", nlen)) {
+		len = read_cb(store, &dis_fw_rev, sizeof(dis_fw_rev) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read firmware revision from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_fw_rev[len] = '\0';
+
+			BT_DBG("Firmware revision set to %s", dis_fw_rev);
+		}
+		return 0;
+	}
+#endif
+#if defined(CONFIG_BT_DIS_HW_REV)
+	if (!strncmp(name, "hw", nlen)) {
+		len = read_cb(store, &dis_hw_rev, sizeof(dis_hw_rev) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read hardware revision from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_hw_rev[len] = '\0';
+
+			BT_DBG("Hardware revision set to %s", dis_hw_rev);
+		}
+		return 0;
+	}
+#endif
+#if defined(CONFIG_BT_DIS_SW_REV)
+	if (!strncmp(name, "sw", nlen)) {
+		len = read_cb(store, &dis_sw_rev, sizeof(dis_sw_rev) - 1);
+		if (len < 0) {
+			BT_ERR("Failed to read software revision from storage"
+				       " (err %zd)", len);
+		} else {
+			dis_sw_rev[len] = '\0';
+
+			BT_DBG("Software revision set to %s", dis_sw_rev);
+		}
+		return 0;
+	}
+#endif
+	return 0;
+}
+
+SETTINGS_STATIC_HANDLER_DEFINE(bt_dis, "bt/dis", NULL, dis_set, NULL, NULL);
+
+#endif /* CONFIG_BT_DIS_SETTINGS && CONFIG_BT_SETTINGS*/
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/hrs.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/hrs.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/hrs.c	(working copy)
@@ -0,0 +1,81 @@
+/** @file
+ *  @brief HRS Service sample
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <zephyr.h>
+#include <init.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+
+#define LOG_LEVEL CONFIG_BT_HRS_LOG_LEVEL
+#include <logging/log.h>
+LOG_MODULE_REGISTER(hrs);
+
+static uint8_t hrs_blsc;
+
+static void hrmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
+{
+	ARG_UNUSED(attr);
+
+	bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);
+
+	LOG_INF("HRS notifications %s", notif_enabled ? "enabled" : "disabled");
+}
+
+static ssize_t read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 void *buf, uint16_t len, uint16_t offset)
+{
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &hrs_blsc,
+				 sizeof(hrs_blsc));
+}
+
+/* Heart Rate Service Declaration */
+BT_GATT_SERVICE_DEFINE(hrs_svc,
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_HRS),
+	BT_GATT_CHARACTERISTIC(BT_UUID_HRS_MEASUREMENT, BT_GATT_CHRC_NOTIFY,
+			       BT_GATT_PERM_NONE, NULL, NULL, NULL),
+	BT_GATT_CCC(hrmc_ccc_cfg_changed,
+		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+	BT_GATT_CHARACTERISTIC(BT_UUID_HRS_BODY_SENSOR, BT_GATT_CHRC_READ,
+			       BT_GATT_PERM_READ, read_blsc, NULL, NULL),
+	BT_GATT_CHARACTERISTIC(BT_UUID_HRS_CONTROL_POINT, BT_GATT_CHRC_WRITE,
+			       BT_GATT_PERM_NONE, NULL, NULL, NULL),
+);
+
+static int hrs_init(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	hrs_blsc = 0x01;
+
+	return 0;
+}
+
+int bt_hrs_notify(uint16_t heartrate)
+{
+	int rc;
+	static uint8_t hrm[2];
+
+	hrm[0] = 0x06; /* uint8, sensor contact */
+	hrm[1] = heartrate;
+
+	rc = bt_gatt_notify(NULL, &hrs_svc.attrs[1], &hrm, sizeof(hrm));
+
+	return rc == -ENOTCONN ? 0 : rc;
+}
+
+SYS_INIT(hrs_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/CMakeLists.txt	(working copy)
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_sources_ifdef(
+  CONFIG_BT_OTS
+  ots.c
+  ots_l2cap.c
+  ots_obj_manager.c
+  ots_oacp.c
+  ots_olcp.c)
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/Kconfig	(working copy)
@@ -0,0 +1,47 @@
+# Bluetooth Object Transfer service
+
+# Copyright (c) 2020 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+config BT_OTS
+	bool "Object Transfer Service (OTS) [EXPERIMENTAL]"
+	select BT_L2CAP_DYNAMIC_CHANNEL
+	select BT_GATT_DYNAMIC_DB
+	select BT_SMP
+	help
+	  Enable Object Transfer Service.
+
+if BT_OTS
+
+config BT_OTS_MAX_INST_CNT
+	int "Maximum number of available OTS instances"
+	default 1
+	range 1 1 if !BT_OTS_SECONDARY_SVC
+
+config BT_OTS_MAX_OBJ_CNT
+	int "Maximum number of objects that each service instance can store"
+	default 5
+
+config BT_OTS_SECONDARY_SVC
+	bool "Register OTS as Secondary Service"
+
+config BT_OTS_OACP_READ_SUPPORT
+	bool "Support OACP Read Operation"
+	default y
+
+config BT_OTS_OLCP_GO_TO_SUPPORT
+	bool "Support OLCP Go To Operation"
+	default y
+
+config BT_OTS_L2CAP_CHAN_RX_MTU
+	int "Size of RX MTU for Object Transfer Channel"
+	default BT_L2CAP_RX_MTU if BT_HCI_ACL_FLOW_CONTROL
+	default 23
+	range 23 BT_L2CAP_RX_MTU if BT_HCI_ACL_FLOW_CONTROL
+	range 23 BT_RX_BUF_LEN
+
+module = BT_OTS
+module-str = BT_OTS
+source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"
+
+endif # BT_OTS
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots.c	(working copy)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <init.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+
+#include <bluetooth/services/ots.h>
+#include "ots_internal.h"
+#include "ots_obj_manager_internal.h"
+
+#include <logging/log.h>
+
+LOG_MODULE_REGISTER(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
+
+#if defined(CONFIG_BT_OTS_OACP_READ_SUPPORT)
+#define OACP_FEAT_BIT_READ BIT(BT_OTS_OACP_FEAT_READ)
+#else
+#define OACP_FEAT_BIT_READ 0
+#endif
+
+/* OACP features supported by Kconfig */
+#define OACP_FEAT OACP_FEAT_BIT_READ
+
+#if defined(CONFIG_BT_OTS_OLCP_GO_TO_SUPPORT)
+#define OLCP_FEAT_BIT_GOTO BIT(BT_OTS_OLCP_FEAT_GO_TO)
+#else
+#define OLCP_FEAT_BIT_GOTO 0
+#endif
+
+/* OLCP features supported by Kconfig */
+#define OLCP_FEAT OLCP_FEAT_BIT_GOTO
+
+static ssize_t ots_feature_read(struct bt_conn *conn,
+				const struct bt_gatt_attr *attr, void *buf,
+				uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("OTS Feature GATT Read Operation");
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, &ots->features,
+		sizeof(ots->features));
+}
+
+static ssize_t ots_obj_name_read(struct bt_conn *conn,
+				 const struct bt_gatt_attr *attr, void *buf,
+				 uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("OTS Object Name GATT Read Operation");
+
+	if (!ots->cur_obj) {
+		LOG_DBG("No Current Object selected in OTS!");
+		return BT_GATT_ERR(BT_GATT_OTS_OBJECT_NOT_SELECTED);
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset,
+				 ots->cur_obj->metadata.name,
+				 strlen(ots->cur_obj->metadata.name));
+}
+
+static ssize_t ots_obj_type_read(struct bt_conn *conn,
+				 const struct bt_gatt_attr *attr, void *buf,
+				 uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+	struct bt_ots_obj_metadata *obj_meta;
+
+	LOG_DBG("OTS Object Type GATT Read Operation");
+
+	if (!ots->cur_obj) {
+		LOG_DBG("No Current Object selected in OTS!");
+		return BT_GATT_ERR(BT_GATT_OTS_OBJECT_NOT_SELECTED);
+	}
+
+	obj_meta = &ots->cur_obj->metadata;
+	if (obj_meta->type.uuid.type == BT_UUID_TYPE_128) {
+		return bt_gatt_attr_read(conn, attr, buf, len, offset,
+					 obj_meta->type.uuid_128.val,
+					 sizeof(obj_meta->type.uuid_128.val));
+	} else {
+		return bt_gatt_attr_read(conn, attr, buf, len, offset,
+					 &obj_meta->type.uuid_16.val,
+					 sizeof(obj_meta->type.uuid_16.val));
+	}
+}
+
+static ssize_t ots_obj_size_read(struct bt_conn *conn,
+				 const struct bt_gatt_attr *attr, void *buf,
+				 uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("OTS Object Size GATT Read Operation");
+
+	if (!ots->cur_obj) {
+		LOG_DBG("No Current Object selected in OTS!");
+		return BT_GATT_ERR(BT_GATT_OTS_OBJECT_NOT_SELECTED);
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset,
+				 &ots->cur_obj->metadata.size,
+				 sizeof(ots->cur_obj->metadata.size));
+}
+
+static ssize_t ots_obj_id_read(struct bt_conn *conn,
+			       const struct bt_gatt_attr *attr, void *buf,
+			       uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+	uint8_t id[BT_OTS_OBJ_ID_SIZE];
+	char id_str[BT_OTS_OBJ_ID_STR_LEN];
+
+	LOG_DBG("OTS Object ID GATT Read Operation");
+
+	if (!ots->cur_obj) {
+		LOG_DBG("No Current Object selected in OTS!");
+		return BT_GATT_ERR(BT_GATT_OTS_OBJECT_NOT_SELECTED);
+	}
+
+	sys_put_le48(ots->cur_obj->id, id);
+
+	bt_ots_obj_id_to_str(ots->cur_obj->id, id_str,
+				      sizeof(id_str));
+	LOG_DBG("Current Object ID: %s", log_strdup(id_str));
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, id, sizeof(id));
+}
+
+static ssize_t ots_obj_prop_read(struct bt_conn *conn,
+				 const struct bt_gatt_attr *attr, void *buf,
+				 uint16_t len, uint16_t offset)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("OTS Object Properties GATT Read Operation");
+
+	if (!ots->cur_obj) {
+		LOG_DBG("No Current Object selected in OTS!");
+		return BT_GATT_ERR(BT_GATT_OTS_OBJECT_NOT_SELECTED);
+	}
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset,
+				 &ots->cur_obj->metadata.props,
+				 sizeof(ots->cur_obj->metadata.props));
+}
+
+int bt_ots_obj_add(struct bt_ots *ots,
+			    struct bt_ots_obj_metadata *obj_init)
+{
+	int err;
+	struct bt_gatt_ots_object *obj;
+
+	err = bt_gatt_ots_obj_manager_obj_add(ots->obj_manager, &obj);
+	if (err) {
+		LOG_ERR("No space available in the object manager");
+		return err;
+	}
+
+	/* Initialize object. */
+	memcpy(&obj->metadata, obj_init, sizeof(obj->metadata));
+
+	/* Request object data. */
+	if (ots->cb->obj_created) {
+		err = ots->cb->obj_created(ots, NULL, obj->id, obj_init);
+		if (err) {
+			bt_gatt_ots_obj_manager_obj_delete(obj);
+			return err;
+		}
+	}
+
+	/* Make object the Current Object if this is the first one added. */
+	if (!ots->cur_obj) {
+		ots->cur_obj = obj;
+	}
+
+	return 0;
+}
+
+int bt_ots_obj_delete(struct bt_ots *ots, uint64_t id)
+{
+	int err;
+	struct bt_gatt_ots_object *obj;
+
+	err = bt_gatt_ots_obj_manager_obj_get(ots->obj_manager, id, &obj);
+	if (err) {
+		return err;
+	}
+
+	if (ots->cur_obj == obj) {
+		if (obj->state.type != BT_GATT_OTS_OBJECT_IDLE_STATE) {
+			return -EBUSY;
+		}
+		ots->cur_obj = NULL;
+	}
+
+	err = bt_gatt_ots_obj_manager_obj_delete(obj);
+	if (err) {
+		return err;
+	}
+
+	if (ots->cb->obj_deleted) {
+		ots->cb->obj_deleted(ots, NULL, obj->id);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_OTS_SECONDARY_SVC)
+void *bt_ots_svc_decl_get(struct bt_ots *ots)
+{
+	return ots->service->attrs;
+}
+#endif
+
+int bt_ots_init(struct bt_ots *ots,
+		     struct bt_ots_init *ots_init)
+{
+	int err;
+
+	if (!ots || !ots_init || !ots_init->cb) {
+		return -EINVAL;
+	}
+
+	__ASSERT(ots_init->cb->obj_created,
+		 "Callback for object creation is not set");
+	__ASSERT(ots_init->cb->obj_read ||
+		 !BT_OTS_OACP_GET_FEAT_READ(ots_init->features.oacp),
+		 "Callback for object reading is not set");
+
+	/* Set callback structure. */
+	ots->cb = ots_init->cb;
+
+	/* Check OACP supported features against Kconfig. */
+	if (ots_init->features.oacp & (~((uint32_t) OACP_FEAT))) {
+		return -ENOTSUP;
+	}
+
+	ots->features.oacp = ots_init->features.oacp;
+	LOG_DBG("OACP features: 0x%04X", ots->features.oacp);
+
+	/* Check OLCP supported features against Kconfig. */
+	if (ots_init->features.olcp & (~((uint32_t) OLCP_FEAT))) {
+		return -ENOTSUP;
+	}
+	ots->features.olcp = ots_init->features.olcp;
+	LOG_DBG("OLCP features: 0x%04X", ots->features.olcp);
+
+	/* Register L2CAP context. */
+	err = bt_gatt_ots_l2cap_register(&ots->l2cap);
+	if (err) {
+		return err;
+	}
+
+	err = bt_gatt_service_register(ots->service);
+	if (err) {
+		bt_gatt_ots_l2cap_unregister(&ots->l2cap);
+
+		return err;
+	}
+
+	LOG_DBG("Initialized OTS");
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_OTS_SECONDARY_SVC)
+	#define BT_GATT_OTS_SERVICE	BT_GATT_SECONDARY_SERVICE
+#else
+	#define BT_GATT_OTS_SERVICE	BT_GATT_PRIMARY_SERVICE
+#endif
+
+#define BT_GATT_OTS_ATTRS(_ots) {					\
+	BT_GATT_OTS_SERVICE(BT_UUID_OTS),				\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_FEATURE,			\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_feature_read, NULL, &_ots),				\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_NAME,			\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_obj_name_read, NULL, &_ots),			\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_TYPE,			\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_obj_type_read, NULL, &_ots),			\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_SIZE,			\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_obj_size_read, NULL, &_ots),			\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_ID,				\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_obj_id_read, NULL, &_ots),				\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_PROPERTIES,			\
+		BT_GATT_CHRC_READ, BT_GATT_PERM_READ,			\
+		ots_obj_prop_read, NULL, &_ots),			\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_ACTION_CP,			\
+		BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE,		\
+		BT_GATT_PERM_WRITE, NULL,				\
+		bt_gatt_ots_oacp_write, &_ots),				\
+	BT_GATT_CCC_MANAGED(&_ots.oacp_ind.ccc,				\
+		BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),		\
+	BT_GATT_CHARACTERISTIC(BT_UUID_OTS_LIST_CP,			\
+		BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE,		\
+		BT_GATT_PERM_WRITE, NULL,				\
+		bt_gatt_ots_olcp_write, &_ots),				\
+	BT_GATT_CCC_MANAGED(&_ots.olcp_ind.ccc,				\
+		BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)			\
+}
+
+#define BT_GATT_OTS_INSTANCE_LIST_SIZE	(ARRAY_SIZE(ots_instances))
+#define BT_GATT_OTS_INSTANCE_LIST_START	ots_instances
+#define BT_GATT_OTS_INSTANCE_LIST_END	\
+	(&ots_instances[BT_GATT_OTS_INSTANCE_LIST_SIZE])
+
+#define BT_GATT_OTS_SERVICE_LIST_START	ots_service_list
+
+static struct bt_ots ots_instances[CONFIG_BT_OTS_MAX_INST_CNT];
+static uint32_t instance_cnt;
+BT_GATT_SERVICE_INSTANCE_DEFINE(ots_service_list, ots_instances,
+				CONFIG_BT_OTS_MAX_INST_CNT,
+				BT_GATT_OTS_ATTRS);
+
+struct bt_ots *bt_ots_free_instance_get(void)
+{
+	if (instance_cnt >= BT_GATT_OTS_INSTANCE_LIST_SIZE) {
+		return NULL;
+	}
+
+	return &BT_GATT_OTS_INSTANCE_LIST_START[instance_cnt++];
+}
+
+static int bt_gatt_ots_instances_prepare(const struct device *dev)
+{
+	uint32_t index;
+	struct bt_ots *instance;
+
+	for (instance = BT_GATT_OTS_INSTANCE_LIST_START, index = 0;
+	     instance != BT_GATT_OTS_INSTANCE_LIST_END;
+	     instance++, index++) {
+		/* Assign an object pool to the OTS instance. */
+		instance->obj_manager = bt_gatt_ots_obj_manager_assign();
+		if (!instance->obj_manager) {
+			LOG_ERR("OTS Object manager instance not available");
+			return -ENOMEM;
+		}
+
+		/* Assign pointer to the service descriptor. */
+		instance->service = &BT_GATT_OTS_SERVICE_LIST_START[index];
+
+		/* Initialize CCC descriptors for characteristics with
+		 * indication properties.
+		 */
+		instance->oacp_ind.ccc.cfg_changed =
+			bt_gatt_ots_oacp_cfg_changed;
+		instance->olcp_ind.ccc.cfg_changed =
+			bt_gatt_ots_olcp_cfg_changed;
+	}
+
+	return 0;
+}
+
+SYS_INIT(bt_gatt_ots_instances_prepare, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_internal.h	(working copy)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BT_GATT_OTS_INTERNAL_H_
+#define BT_GATT_OTS_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <zephyr/types.h>
+#include "ots_l2cap_internal.h"
+#include "ots_oacp_internal.h"
+#include "ots_olcp_internal.h"
+
+/**@brief OTS Attribute Protocol Application Error codes. */
+enum bt_gatt_ots_att_err_codes {
+	/** An attempt was made to write a value that is invalid or
+	 *  not supported by this Server for a reason other than
+	 *  the attribute permissions.
+	 */
+	BT_GATT_OTS_WRITE_REQUEST_REJECTED     = 0x80,
+	/** An attempt was made to read or write to an Object Metadata
+	 *  characteristic while the Current Object was an Invalid Object.
+	 */
+	BT_GATT_OTS_OBJECT_NOT_SELECTED        = 0x81,
+	/** The Server is unable to service the Read Request or Write Request
+	 *  because it exceeds the concurrency limit of the service.
+	 */
+	BT_GATT_OTS_CONCURRENCY_LIMIT_EXCEEDED = 0x82,
+	/** The requested object name was rejected because
+	 *  the name was already in use by an existing object on the Server.
+	 */
+	BT_GATT_OTS_OBJECT_NAME_ALREADY_EXISTS = 0x83,
+};
+
+enum bt_gatt_ots_object_state_type {
+	BT_GATT_OTS_OBJECT_IDLE_STATE,
+
+	BT_GATT_OTS_OBJECT_READ_OP_STATE,
+};
+
+struct bt_gatt_ots_object_state {
+	enum bt_gatt_ots_object_state_type type;
+	union {
+		struct bt_gatt_ots_object_read_op {
+			struct bt_gatt_ots_oacp_read_params oacp_params;
+			uint32_t sent_len;
+		} read_op;
+	};
+};
+
+struct bt_gatt_ots_object {
+	uint64_t id;
+	struct bt_ots_obj_metadata metadata;
+	struct bt_gatt_ots_object_state state;
+};
+
+struct bt_gatt_ots_indicate {
+	struct bt_gatt_indicate_params params;
+	struct bt_gatt_attr attr;
+	struct _bt_gatt_ccc ccc;
+	bool is_enabled;
+};
+
+struct bt_ots {
+	struct bt_ots_feat features;
+	struct bt_gatt_ots_object *cur_obj;
+	struct bt_gatt_service *service;
+	struct bt_gatt_ots_indicate oacp_ind;
+	struct bt_gatt_ots_indicate olcp_ind;
+	struct bt_gatt_ots_l2cap l2cap;
+	struct bt_ots_cb *cb;
+	void *obj_manager;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_GATT_OTS_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap.c	(working copy)
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+#include <init.h>
+
+#include <net/buf.h>
+
+#include "ots_l2cap_internal.h"
+
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
+
+/* According to BLE specification Assigned Numbers that are used in the
+ * Logical Link Control for protocol/service multiplexers.
+ */
+#define BT_GATT_OTS_L2CAP_PSM	0x0025
+
+/* Maximum size of TX buffer and its payload. */
+#define MAX_TX_BUF_SIZE		256
+#define MAX_TX_BUF_PAYLOAD_SIZE (MAX_TX_BUF_SIZE - BT_L2CAP_CHAN_SEND_RESERVE)
+
+NET_BUF_POOL_FIXED_DEFINE(ot_chan_tx_pool, 1, MAX_TX_BUF_SIZE, NULL);
+
+/* List of Object Transfer Channels. */
+static sys_slist_t channels;
+
+static int ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx)
+{
+	int ret;
+	struct net_buf *buf;
+	uint32_t len;
+
+	/* Calculate maximum length of data chunk. */
+	len = MIN(l2cap_ctx->ot_chan.tx.mtu, MAX_TX_BUF_PAYLOAD_SIZE);
+	len = MIN(len, l2cap_ctx->tx.len - l2cap_ctx->tx.len_sent);
+
+	/* Prepare buffer for sending. */
+	buf = net_buf_alloc(&ot_chan_tx_pool, K_FOREVER);
+	net_buf_reserve(buf, BT_L2CAP_CHAN_SEND_RESERVE);
+	net_buf_add_mem(buf, &l2cap_ctx->tx.data[l2cap_ctx->tx.len_sent], len);
+
+	ret = bt_l2cap_chan_send(&l2cap_ctx->ot_chan.chan, buf);
+	if (ret < 0) {
+		LOG_ERR("Unable to send data over CoC: %d", ret);
+		net_buf_unref(buf);
+
+		return -ENOEXEC;
+	}
+
+	/* Mark that L2CAP TX was accepted. */
+	l2cap_ctx->tx.len_sent += len;
+
+	LOG_DBG("Sending TX chunk with %d bytes on L2CAP CoC", len);
+
+	return 0;
+}
+
+static void l2cap_sent(struct bt_l2cap_chan *chan)
+{
+	struct bt_gatt_ots_l2cap *l2cap_ctx;
+
+	LOG_DBG("Outgoing data channel %p transmitted", chan);
+
+	l2cap_ctx = CONTAINER_OF(chan, struct bt_gatt_ots_l2cap, ot_chan);
+
+	/* Ongoing TX - sending next chunk. */
+	if (l2cap_ctx->tx.len != l2cap_ctx->tx.len_sent) {
+		ots_l2cap_send(l2cap_ctx);
+
+		return;
+	}
+
+	/* TX completed - notify upper layers and clean up. */
+	memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
+
+	LOG_DBG("Scheduled TX on L2CAP CoC is complete");
+
+	if (l2cap_ctx->tx_done) {
+		l2cap_ctx->tx_done(l2cap_ctx, chan->conn);
+	}
+}
+
+static void l2cap_status(struct bt_l2cap_chan *chan, atomic_t *status)
+{
+	LOG_DBG("Channel %p status %u", chan, *status);
+}
+
+static void l2cap_connected(struct bt_l2cap_chan *chan)
+{
+	LOG_DBG("Channel %p connected", chan);
+}
+
+static void l2cap_disconnected(struct bt_l2cap_chan *chan)
+{
+	LOG_DBG("Channel %p disconnected", chan);
+}
+
+static const struct bt_l2cap_chan_ops l2cap_ops = {
+	.sent		= l2cap_sent,
+	.status		= l2cap_status,
+	.connected	= l2cap_connected,
+	.disconnected	= l2cap_disconnected,
+};
+
+static inline void l2cap_chan_init(struct bt_l2cap_le_chan *chan)
+{
+	chan->rx.mtu = CONFIG_BT_OTS_L2CAP_CHAN_RX_MTU;
+	chan->chan.ops = &l2cap_ops;
+
+	LOG_DBG("RX MTU set to %u", chan->rx.mtu);
+}
+
+static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	struct bt_gatt_ots_l2cap *l2cap_ctx;
+
+	LOG_DBG("Incoming conn %p", conn);
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&channels, l2cap_ctx, node) {
+		if (l2cap_ctx->ot_chan.chan.conn) {
+			continue;
+		}
+
+		l2cap_chan_init(&l2cap_ctx->ot_chan);
+		memset(&l2cap_ctx->tx, 0, sizeof(l2cap_ctx->tx));
+
+		*chan = &l2cap_ctx->ot_chan.chan;
+
+		return 0;
+	}
+
+	return -ENOMEM;
+}
+
+static struct bt_l2cap_server l2cap_server = {
+	.psm = BT_GATT_OTS_L2CAP_PSM,
+	.accept	= l2cap_accept,
+};
+
+static int bt_gatt_ots_l2cap_init(const struct device *arg)
+{
+	int err;
+
+	sys_slist_init(&channels);
+
+	err = bt_l2cap_server_register(&l2cap_server);
+	if (err) {
+		LOG_ERR("Unable to register OTS PSM");
+		return err;
+	}
+
+	LOG_DBG("Initialized OTS L2CAP");
+
+	return 0;
+}
+
+bool bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap *l2cap_ctx,
+				   struct bt_conn *conn)
+{
+	return (l2cap_ctx->ot_chan.chan.conn == conn);
+}
+
+int bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx,
+			       uint8_t *data, uint32_t len)
+{
+	int err;
+
+	if (l2cap_ctx->tx.len != 0) {
+		LOG_ERR("L2CAP TX in progress");
+
+		return -EAGAIN;
+	}
+
+	l2cap_ctx->tx.data = data;
+	l2cap_ctx->tx.len = len;
+
+	LOG_DBG("Starting TX on L2CAP CoC with %d byte packet", len);
+
+	err = ots_l2cap_send(l2cap_ctx);
+	if (err) {
+		LOG_ERR("Unable to send data over CoC: %d", err);
+
+		return err;
+	}
+
+	return 0;
+}
+
+int bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap *l2cap_ctx)
+{
+	sys_slist_append(&channels, &l2cap_ctx->node);
+
+	return 0;
+}
+
+int bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap *l2cap_ctx)
+{
+	sys_slist_find_and_remove(&channels, &l2cap_ctx->node);
+
+	return 0;
+}
+
+SYS_INIT(bt_gatt_ots_l2cap_init, APPLICATION,
+	 CONFIG_APPLICATION_INIT_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_l2cap_internal.h	(working copy)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BT_GATT_OTS_L2CAP_H_
+#define BT_GATT_OTS_L2CAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <zephyr/types.h>
+#include <sys/slist.h>
+
+#include <bluetooth/l2cap.h>
+
+struct bt_gatt_ots_l2cap_tx {
+	uint8_t *data;
+	uint32_t len;
+	uint32_t len_sent;
+};
+
+struct bt_gatt_ots_l2cap {
+	sys_snode_t node;
+	struct bt_l2cap_le_chan ot_chan;
+	struct bt_gatt_ots_l2cap_tx tx;
+	void (*tx_done)(struct bt_gatt_ots_l2cap *l2cap_ctx,
+			struct bt_conn *conn);
+};
+
+bool bt_gatt_ots_l2cap_is_open(struct bt_gatt_ots_l2cap *l2cap_ctx,
+				   struct bt_conn *conn);
+
+int bt_gatt_ots_l2cap_send(struct bt_gatt_ots_l2cap *l2cap_ctx,
+			       uint8_t *data,
+			       uint32_t len);
+
+int bt_gatt_ots_l2cap_register(struct bt_gatt_ots_l2cap *l2cap_ctx);
+
+int bt_gatt_ots_l2cap_unregister(struct bt_gatt_ots_l2cap *l2cap_ctx);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* BT_GATT_OTS_L2CAP_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp.c	(working copy)
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <bluetooth/gatt.h>
+#include <bluetooth/services/ots.h>
+#include "ots_internal.h"
+
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
+
+#define OACP_PROC_TYPE_SIZE	1
+#define OACP_RES_MAX_SIZE	3
+
+static enum bt_gatt_ots_oacp_res_code oacp_read_proc_validate(
+	struct bt_conn *conn,
+	struct bt_ots *ots,
+	struct bt_gatt_ots_oacp_proc *proc)
+{
+	struct bt_gatt_ots_oacp_read_params *params = &proc->read_params;
+
+	LOG_DBG("Validating Read procedure with offset: 0x%08X and "
+		"length: 0x%08X", params->offset, params->len);
+
+	if (!ots->cur_obj) {
+		return BT_GATT_OTS_OACP_RES_INV_OBJ;
+	}
+
+	if (!BT_OTS_OBJ_GET_PROP_READ(ots->cur_obj->metadata.props)) {
+		return BT_GATT_OTS_OACP_RES_NOT_PERMITTED;
+	}
+
+	if (!bt_gatt_ots_l2cap_is_open(&ots->l2cap, conn)) {
+		return BT_GATT_OTS_OACP_RES_CHAN_UNAVAIL;
+	}
+
+	if ((params->offset + (uint64_t) params->len) >
+		ots->cur_obj->metadata.size.cur) {
+		return BT_GATT_OTS_OACP_RES_INV_PARAM;
+	}
+
+	if (ots->cur_obj->state.type != BT_GATT_OTS_OBJECT_IDLE_STATE) {
+		return BT_GATT_OTS_OACP_RES_OBJ_LOCKED;
+	}
+
+	ots->cur_obj->state.type = BT_GATT_OTS_OBJECT_READ_OP_STATE;
+	ots->cur_obj->state.read_op.sent_len = 0;
+	memcpy(&ots->cur_obj->state.read_op.oacp_params, &proc->read_params,
+		sizeof(ots->cur_obj->state.read_op.oacp_params));
+
+	LOG_DBG("Read procedure is accepted");
+
+	return BT_GATT_OTS_OACP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_oacp_res_code oacp_proc_validate(
+	struct bt_conn *conn,
+	struct bt_ots *ots,
+	struct bt_gatt_ots_oacp_proc *proc)
+{
+	switch (proc->type) {
+	case BT_GATT_OTS_OACP_PROC_READ:
+		return oacp_read_proc_validate(conn, ots, proc);
+	case BT_GATT_OTS_OACP_PROC_CREATE:
+	case BT_GATT_OTS_OACP_PROC_DELETE:
+	case BT_GATT_OTS_OACP_PROC_CHECKSUM_CALC:
+	case BT_GATT_OTS_OACP_PROC_EXECUTE:
+	case BT_GATT_OTS_OACP_PROC_WRITE:
+	case BT_GATT_OTS_OACP_PROC_ABORT:
+	default:
+		return BT_GATT_OTS_OACP_RES_OPCODE_NOT_SUP;
+	}
+};
+
+static enum bt_gatt_ots_oacp_res_code oacp_command_decode(
+	const uint8_t *buf, uint16_t len,
+	struct bt_gatt_ots_oacp_proc *proc)
+{
+	struct net_buf_simple net_buf;
+
+	net_buf_simple_init_with_data(&net_buf, (void *) buf, len);
+
+	proc->type = net_buf_simple_pull_u8(&net_buf);
+	switch (proc->type) {
+	case BT_GATT_OTS_OACP_PROC_CREATE:
+		proc->create_params.size = net_buf_simple_pull_le32(&net_buf);
+		bt_uuid_create(&proc->create_params.type.uuid, net_buf.data,
+			       net_buf.len);
+		net_buf_simple_pull_mem(&net_buf, net_buf.len);
+		break;
+	case BT_GATT_OTS_OACP_PROC_DELETE:
+		break;
+	case BT_GATT_OTS_OACP_PROC_CHECKSUM_CALC:
+		proc->cs_calc_params.offset =
+			net_buf_simple_pull_le32(&net_buf);
+		proc->cs_calc_params.len =
+			net_buf_simple_pull_le32(&net_buf);
+		break;
+	case BT_GATT_OTS_OACP_PROC_EXECUTE:
+		break;
+	case BT_GATT_OTS_OACP_PROC_READ:
+		proc->read_params.offset =
+			net_buf_simple_pull_le32(&net_buf);
+		proc->read_params.len =
+			net_buf_simple_pull_le32(&net_buf);
+		return BT_GATT_OTS_OACP_RES_SUCCESS;
+	case BT_GATT_OTS_OACP_PROC_WRITE:
+		proc->write_params.offset =
+			net_buf_simple_pull_le32(&net_buf);
+		proc->write_params.len =
+			net_buf_simple_pull_le32(&net_buf);
+		proc->write_params.mode =
+			net_buf_simple_pull_u8(&net_buf);
+		break;
+	case BT_GATT_OTS_OACP_PROC_ABORT:
+	default:
+		break;
+	}
+
+	LOG_WRN("OACP unsupported procedure type");
+	return BT_GATT_OTS_OACP_RES_OPCODE_NOT_SUP;
+}
+
+static bool oacp_command_len_verify(struct bt_gatt_ots_oacp_proc *proc,
+				    uint16_t len)
+{
+	uint16_t ref_len = OACP_PROC_TYPE_SIZE;
+
+	switch (proc->type) {
+	case BT_GATT_OTS_OACP_PROC_CREATE:
+	{
+		struct bt_ots_obj_type *type;
+
+		ref_len += sizeof(proc->create_params.size);
+
+		type = &proc->create_params.type;
+		if (type->uuid.type == BT_UUID_TYPE_16) {
+			ref_len += sizeof(type->uuid_16.val);
+		} else if (type->uuid.type == BT_UUID_TYPE_128) {
+			ref_len += sizeof(type->uuid_128.val);
+		} else {
+			return true;
+		}
+	} break;
+	case BT_GATT_OTS_OACP_PROC_DELETE:
+		break;
+	case BT_GATT_OTS_OACP_PROC_CHECKSUM_CALC:
+		ref_len += sizeof(proc->cs_calc_params);
+		break;
+	case BT_GATT_OTS_OACP_PROC_EXECUTE:
+		break;
+	case BT_GATT_OTS_OACP_PROC_READ:
+		ref_len += sizeof(proc->read_params);
+		break;
+	case BT_GATT_OTS_OACP_PROC_WRITE:
+		ref_len += sizeof(proc->write_params);
+		break;
+	case BT_GATT_OTS_OACP_PROC_ABORT:
+		break;
+	default:
+		return true;
+	}
+
+	return (len == ref_len);
+}
+
+static void oacp_read_proc_cb(struct bt_gatt_ots_l2cap *l2cap_ctx,
+			      struct bt_conn *conn)
+{
+	int err;
+	uint8_t *obj_chunk;
+	uint32_t offset;
+	uint32_t len;
+	struct bt_ots *ots;
+	struct bt_gatt_ots_object_read_op *read_op;
+
+	ots     = CONTAINER_OF(l2cap_ctx, struct bt_ots, l2cap);
+	read_op = &ots->cur_obj->state.read_op;
+	offset  = read_op->oacp_params.offset + read_op->sent_len;
+
+	if (read_op->sent_len >= read_op->oacp_params.len) {
+		LOG_DBG("OACP Read Op over L2CAP is completed");
+
+		if (read_op->sent_len > read_op->oacp_params.len) {
+			LOG_WRN("More bytes sent that the client requested");
+		}
+
+		ots->cur_obj->state.type = BT_GATT_OTS_OBJECT_IDLE_STATE;
+		ots->cb->obj_read(ots, conn, ots->cur_obj->id, NULL, 0,
+				  offset);
+		return;
+	}
+
+	len = read_op->oacp_params.len - read_op->sent_len;
+	len = ots->cb->obj_read(ots, conn, ots->cur_obj->id, &obj_chunk, len,
+				offset);
+
+	ots->l2cap.tx_done = oacp_read_proc_cb;
+	err = bt_gatt_ots_l2cap_send(&ots->l2cap, obj_chunk, len);
+	if (err) {
+		LOG_ERR("L2CAP CoC error: %d while trying to execute OACP "
+			"Read procedure", err);
+		ots->cur_obj->state.type = BT_GATT_OTS_OBJECT_IDLE_STATE;
+	} else {
+		read_op->sent_len += len;
+	}
+}
+
+static void oacp_read_proc_execute(struct bt_ots *ots,
+				   struct bt_conn *conn)
+{
+	struct bt_gatt_ots_oacp_read_params *params =
+		&ots->cur_obj->state.read_op.oacp_params;
+
+	if (!ots->cur_obj) {
+		LOG_ERR("Invalid Current Object on OACP Read procedure");
+		return;
+	}
+
+	LOG_DBG("Executing Read procedure with offset: 0x%08X and "
+		"length: 0x%08X", params->offset, params->len);
+
+	if (ots->cb->obj_read) {
+		oacp_read_proc_cb(&ots->l2cap, conn);
+	} else {
+		ots->cur_obj->state.type = BT_GATT_OTS_OBJECT_IDLE_STATE;
+		LOG_ERR("OTS Read operation failed: "
+			"there is no OTS Read callback");
+	}
+}
+
+static void oacp_ind_cb(struct bt_conn *conn,
+			const struct bt_gatt_attr *attr,
+			uint8_t err)
+{
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("Received OACP Indication ACK with status: 0x%04X", err);
+
+	switch (ots->cur_obj->state.type) {
+	case BT_GATT_OTS_OBJECT_READ_OP_STATE:
+		oacp_read_proc_execute(ots, conn);
+		break;
+	default:
+		LOG_ERR("Unsupported OTS state: %d", ots->cur_obj->state.type);
+		break;
+	}
+}
+
+static int oacp_ind_send(const struct bt_gatt_attr *oacp_attr,
+			 enum bt_gatt_ots_oacp_proc_type req_op_code,
+			 enum bt_gatt_ots_oacp_res_code oacp_status)
+{
+	uint8_t oacp_res[OACP_RES_MAX_SIZE];
+	uint16_t oacp_res_len = 0;
+	struct bt_ots *ots = (struct bt_ots *) oacp_attr->user_data;
+
+	/* Encode OACP Response */
+	oacp_res[oacp_res_len++] = BT_GATT_OTS_OACP_PROC_RESP;
+	oacp_res[oacp_res_len++] = req_op_code;
+	oacp_res[oacp_res_len++] = oacp_status;
+
+	/* Prepare indication parameters */
+	memset(&ots->oacp_ind.params, 0, sizeof(ots->oacp_ind.params));
+	memcpy(&ots->oacp_ind.attr, oacp_attr, sizeof(ots->oacp_ind.attr));
+	ots->oacp_ind.params.attr = &ots->oacp_ind.attr;
+	ots->oacp_ind.params.func = oacp_ind_cb;
+	ots->oacp_ind.params.data = oacp_res;
+	ots->oacp_ind.params.len  = oacp_res_len;
+
+	LOG_DBG("Sending OACP indication");
+
+	return bt_gatt_indicate(NULL, &ots->oacp_ind.params);
+}
+
+ssize_t bt_gatt_ots_oacp_write(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   const void *buf, uint16_t len,
+				   uint16_t offset, uint8_t flags)
+{
+	enum bt_gatt_ots_oacp_res_code oacp_status;
+	struct bt_gatt_ots_oacp_proc oacp_proc;
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("Object Action Control Point GATT Write Operation");
+
+	if (!ots->oacp_ind.is_enabled) {
+		LOG_WRN("OACP indications not enabled");
+		return BT_GATT_ERR(BT_ATT_ERR_CCC_IMPROPER_CONF);
+	}
+
+	if (offset != 0) {
+		LOG_ERR("Invalid offset of OACP Write Request");
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	oacp_status = oacp_command_decode(buf, len, &oacp_proc);
+
+	if (!oacp_command_len_verify(&oacp_proc, len)) {
+		LOG_ERR("Invalid length of OACP Write Request for 0x%02X "
+			"Op Code", oacp_proc.type);
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
+	}
+
+	if (oacp_status == BT_GATT_OTS_OACP_RES_SUCCESS) {
+		oacp_status = oacp_proc_validate(conn, ots, &oacp_proc);
+	}
+
+	if (oacp_status != BT_GATT_OTS_OACP_RES_SUCCESS) {
+		LOG_WRN("OACP Write error status: 0x%02X", oacp_status);
+	}
+
+	oacp_ind_send(attr, oacp_proc.type, oacp_status);
+	return len;
+}
+
+void bt_gatt_ots_oacp_cfg_changed(const struct bt_gatt_attr *attr,
+				      uint16_t value)
+{
+	struct bt_gatt_ots_indicate *oacp_ind =
+	    CONTAINER_OF((struct _bt_gatt_ccc *) attr->user_data,
+			 struct bt_gatt_ots_indicate, ccc);
+
+	LOG_DBG("Object Action Control Point CCCD value: 0x%04X", value);
+
+	oacp_ind->is_enabled = false;
+	if (value == BT_GATT_CCC_INDICATE) {
+		oacp_ind->is_enabled = true;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_oacp_internal.h	(working copy)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BT_GATT_OTS_OACP_H_
+#define BT_GATT_OTS_OACP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <zephyr/types.h>
+#include <bluetooth/gatt.h>
+#include <bluetooth/services/ots.h>
+
+/* Types of Object Action Control Point Procedures. */
+enum bt_gatt_ots_oacp_proc_type {
+	/** Create object.*/
+	BT_GATT_OTS_OACP_PROC_CREATE        = 0x01,
+	/** Delete object.*/
+	BT_GATT_OTS_OACP_PROC_DELETE        = 0x02,
+	/** Calculate Checksum.*/
+	BT_GATT_OTS_OACP_PROC_CHECKSUM_CALC = 0x03,
+	/** Execute Object.*/
+	BT_GATT_OTS_OACP_PROC_EXECUTE       = 0x04,
+	/** Read object.*/
+	BT_GATT_OTS_OACP_PROC_READ          = 0x05,
+	/** Write object.*/
+	BT_GATT_OTS_OACP_PROC_WRITE         = 0x06,
+	/** Abort object.*/
+	BT_GATT_OTS_OACP_PROC_ABORT         = 0x07,
+	/** Procedure response.*/
+	BT_GATT_OTS_OACP_PROC_RESP          = 0x60
+};
+
+/* Object Action Control Point return codes. */
+enum bt_gatt_ots_oacp_res_code {
+	/** Success.*/
+	BT_GATT_OTS_OACP_RES_SUCCESS        = 0x01,
+	/** Not supported*/
+	BT_GATT_OTS_OACP_RES_OPCODE_NOT_SUP = 0x02,
+	/** Invalid parameter*/
+	BT_GATT_OTS_OACP_RES_INV_PARAM      = 0x03,
+	/** Insufficient resources.*/
+	BT_GATT_OTS_OACP_RES_INSUFF_RES     = 0x04,
+	/** Invalid object.*/
+	BT_GATT_OTS_OACP_RES_INV_OBJ        = 0x05,
+	/** Channel unavailable.*/
+	BT_GATT_OTS_OACP_RES_CHAN_UNAVAIL   = 0x06,
+	/** Unsupported procedure.*/
+	BT_GATT_OTS_OACP_RES_UNSUP_TYPE     = 0x07,
+	/** Procedure not permitted.*/
+	BT_GATT_OTS_OACP_RES_NOT_PERMITTED  = 0x08,
+	/** Object locked.*/
+	BT_GATT_OTS_OACP_RES_OBJ_LOCKED     = 0x09,
+	/** Operation Failed.*/
+	BT_GATT_OTS_OACP_RES_OPER_FAILED    = 0x0A
+};
+
+/* Object Action Control Point procedure definition. */
+struct bt_gatt_ots_oacp_proc {
+	enum bt_gatt_ots_oacp_proc_type type;
+	union {
+		struct bt_gatt_ots_oacp_create_params {
+			uint32_t size;
+			struct bt_ots_obj_type type;
+		} create_params;
+		struct bt_gatt_ots_oacp_cs_calc_params {
+			uint32_t offset;
+			uint32_t len;
+		} cs_calc_params;
+		struct bt_gatt_ots_oacp_read_params {
+			uint32_t offset;
+			uint32_t len;
+		} read_params;
+		struct bt_gatt_ots_oacp_write_params {
+			uint32_t offset;
+			uint32_t len;
+			uint8_t mode;
+		} write_params;
+	};
+};
+
+ssize_t bt_gatt_ots_oacp_write(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   const void *buf, uint16_t len,
+				   uint16_t offset, uint8_t flags);
+
+void bt_gatt_ots_oacp_cfg_changed(const struct bt_gatt_attr *attr,
+				      uint16_t value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_GATT_OTS_OACP_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager.c	(working copy)
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/dlist.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/services/ots.h>
+#include "ots_internal.h"
+
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
+
+/**Start of the usable range of Object IDs (values 0 to 0x100 are reserved)*/
+#define OTS_OBJ_ID_START_RANGE  0x000000000100
+
+#define OTS_OBJ_INDEX_TO_ID(_index) (OTS_OBJ_ID_START_RANGE + (_index))
+#define OTS_OBJ_ID_TO_INDEX(_id)    ((_id) - OTS_OBJ_ID_START_RANGE)
+
+struct bt_gatt_ots_pool_item {
+	sys_dnode_t dnode;
+	struct bt_gatt_ots_object val;
+	bool is_allocated;
+};
+
+struct bt_gatt_ots_obj_manager {
+	sys_dlist_t list;
+	struct bt_gatt_ots_pool_item pool[CONFIG_BT_OTS_MAX_OBJ_CNT];
+	bool is_assigned;
+};
+
+int bt_gatt_ots_obj_manager_first_obj_get(
+	struct bt_gatt_ots_obj_manager *obj_manager,
+	struct bt_gatt_ots_object **obj)
+{
+	sys_dnode_t *obj_dnode;
+	struct bt_gatt_ots_pool_item *first_item;
+
+	if (sys_dlist_is_empty(&obj_manager->list)) {
+		return -ENOENT;
+	}
+
+	obj_dnode = sys_dlist_peek_head_not_empty(&obj_manager->list);
+	first_item = CONTAINER_OF(obj_dnode, struct bt_gatt_ots_pool_item,
+				  dnode);
+	*obj = &first_item->val;
+
+	return 0;
+}
+
+int bt_gatt_ots_obj_manager_last_obj_get(
+	struct bt_gatt_ots_obj_manager *obj_manager,
+	struct bt_gatt_ots_object **obj)
+{
+	sys_dnode_t *obj_dnode;
+	struct bt_gatt_ots_pool_item *last_item;
+
+	if (sys_dlist_is_empty(&obj_manager->list)) {
+		return -ENOENT;
+	}
+
+	obj_dnode = sys_dlist_peek_tail(&obj_manager->list);
+	last_item = CONTAINER_OF(obj_dnode, struct bt_gatt_ots_pool_item,
+				 dnode);
+	*obj = &last_item->val;
+
+	return 0;
+}
+
+int bt_gatt_ots_obj_manager_prev_obj_get(
+	struct bt_gatt_ots_obj_manager *obj_manager,
+	const struct bt_gatt_ots_object *cur_obj,
+	struct bt_gatt_ots_object **prev_obj)
+{
+	sys_dnode_t *prev_obj_dnode;
+	struct bt_gatt_ots_pool_item *cur_item, *prev_item;
+
+	if (sys_dlist_is_empty(&obj_manager->list)) {
+		return -ENOENT;
+	}
+
+	cur_item = CONTAINER_OF(cur_obj, struct bt_gatt_ots_pool_item, val);
+	prev_obj_dnode = sys_dlist_peek_prev_no_check(&obj_manager->list,
+						      &cur_item->dnode);
+	if (!prev_obj_dnode) {
+		return -ENFILE;
+	}
+
+	prev_item = CONTAINER_OF(prev_obj_dnode,
+				 struct bt_gatt_ots_pool_item,
+				 dnode);
+	*prev_obj = &prev_item->val;
+
+	return 0;
+}
+
+int bt_gatt_ots_obj_manager_next_obj_get(
+	struct bt_gatt_ots_obj_manager *obj_manager,
+	const struct bt_gatt_ots_object *cur_obj,
+	struct bt_gatt_ots_object **next_obj)
+{
+	sys_dnode_t *next_obj_dnode;
+	struct bt_gatt_ots_pool_item *cur_item, *next_item;
+
+	if (sys_dlist_is_empty(&obj_manager->list)) {
+		return -ENOENT;
+	}
+
+	cur_item = CONTAINER_OF(cur_obj, struct bt_gatt_ots_pool_item, val);
+	next_obj_dnode = sys_dlist_peek_next_no_check(&obj_manager->list,
+						      &cur_item->dnode);
+	if (!next_obj_dnode) {
+		return -ENFILE;
+	}
+
+	next_item = CONTAINER_OF(next_obj_dnode,
+				 struct bt_gatt_ots_pool_item,
+				 dnode);
+	*next_obj = &next_item->val;
+
+	return 0;
+}
+
+int bt_gatt_ots_obj_manager_obj_get(
+	struct bt_gatt_ots_obj_manager *obj_manager, uint64_t id,
+	struct bt_gatt_ots_object **object)
+{
+	uint64_t i = OTS_OBJ_ID_TO_INDEX(id);
+
+	if (sys_dlist_is_empty(&obj_manager->list)) {
+		return -ENOENT;
+	}
+
+	if (id < OTS_OBJ_ID_START_RANGE) {
+		return -EINVAL;
+	}
+
+	if (i >= ARRAY_SIZE(obj_manager->pool)) {
+		return -EINVAL;
+	}
+
+	if (!obj_manager->pool[i].is_allocated) {
+		return -EINVAL;
+	}
+
+	*object = &obj_manager->pool[i].val;
+
+	return 0;
+}
+
+int bt_gatt_ots_obj_manager_obj_add(
+	struct bt_gatt_ots_obj_manager *obj_manager,
+	struct bt_gatt_ots_object **object)
+{
+	for (uint64_t i = 0; i < ARRAY_SIZE(obj_manager->pool); i++) {
+		struct bt_gatt_ots_pool_item *cur_obj =
+			&obj_manager->pool[i];
+
+		if (!cur_obj->is_allocated) {
+			cur_obj->is_allocated = true;
+			cur_obj->val.id = OTS_OBJ_INDEX_TO_ID(i);
+			sys_dlist_append(&obj_manager->list, &cur_obj->dnode);
+
+			*object = &cur_obj->val;
+			return 0;
+		}
+	}
+
+	return -ENOMEM;
+}
+
+int bt_gatt_ots_obj_manager_obj_delete(struct bt_gatt_ots_object *obj)
+{
+	struct bt_gatt_ots_pool_item *item;
+
+	item = CONTAINER_OF(obj, struct bt_gatt_ots_pool_item, val);
+
+	if (!item->is_allocated) {
+		return -EINVAL;
+	}
+
+	item->is_allocated = false;
+	sys_dlist_remove(&item->dnode);
+
+	return 0;
+}
+
+void *bt_gatt_ots_obj_manager_assign(void)
+{
+	static struct bt_gatt_ots_obj_manager
+		obj_manager[CONFIG_BT_OTS_MAX_INST_CNT];
+	struct bt_gatt_ots_obj_manager *cur_manager;
+
+
+	for (cur_manager = obj_manager;
+	     cur_manager != obj_manager + CONFIG_BT_OTS_MAX_INST_CNT;
+	     cur_manager++) {
+		if (!cur_manager->is_assigned) {
+			break;
+		}
+	}
+
+	if (cur_manager->is_assigned) {
+		return NULL;
+	}
+
+	cur_manager->is_assigned = true;
+	sys_dlist_init(&cur_manager->list);
+
+	return cur_manager;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_obj_manager_internal.h	(working copy)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BT_GATT_OTS_OBJ_MANAGER_H_
+#define BT_GATT_OTS_OBJ_MANAGER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <zephyr/types.h>
+
+int bt_gatt_ots_obj_manager_first_obj_get(void *obj_manager,
+	struct bt_gatt_ots_object **obj);
+
+int bt_gatt_ots_obj_manager_last_obj_get(void *obj_manager,
+	struct bt_gatt_ots_object **obj);
+
+int bt_gatt_ots_obj_manager_prev_obj_get(
+	void *obj_manager,
+	const struct bt_gatt_ots_object *cur_obj,
+	struct bt_gatt_ots_object **prev_obj);
+
+int bt_gatt_ots_obj_manager_next_obj_get(
+	void *obj_manager,
+	const struct bt_gatt_ots_object *cur_obj,
+	struct bt_gatt_ots_object **next_obj);
+
+int bt_gatt_ots_obj_manager_obj_get(void *obj_manager,
+					uint64_t id,
+					struct bt_gatt_ots_object **obj);
+
+int bt_gatt_ots_obj_manager_obj_add(void *obj_manager,
+					struct bt_gatt_ots_object **obj);
+
+int bt_gatt_ots_obj_manager_obj_delete(struct bt_gatt_ots_object *obj);
+
+void *bt_gatt_ots_obj_manager_assign(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_GATT_OTS_OBJ_MANAGER_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp.c	(working copy)
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <bluetooth/gatt.h>
+#include <bluetooth/services/ots.h>
+#include "ots_internal.h"
+#include "ots_obj_manager_internal.h"
+
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);
+
+#define OLCP_PROC_TYPE_SIZE	1
+#define OLCP_RES_MAX_SIZE	7
+
+static enum bt_gatt_ots_olcp_res_code obj_manager_to_olcp_err_map(int err)
+{
+	switch (-err) {
+	case EINVAL:
+		return BT_GATT_OTS_OLCP_RES_OBJECT_ID_NOT_FOUND;
+	case ENFILE:
+		return BT_GATT_OTS_OLCP_RES_OUT_OF_BONDS;
+	case ENOENT:
+	default:
+		return BT_GATT_OTS_OLCP_RES_NO_OBJECT;
+	}
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_first_proc_execute(
+	struct bt_ots *ots)
+{
+	int err;
+	struct bt_gatt_ots_object *first_obj;
+
+	err = bt_gatt_ots_obj_manager_first_obj_get(ots->obj_manager,
+						    &first_obj);
+	if (err) {
+		return obj_manager_to_olcp_err_map(err);
+	}
+
+	ots->cur_obj = first_obj;
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_last_proc_execute(
+	struct bt_ots *ots)
+{
+	int err;
+	struct bt_gatt_ots_object *last_obj;
+
+	err = bt_gatt_ots_obj_manager_last_obj_get(ots->obj_manager,
+						   &last_obj);
+	if (err) {
+		return obj_manager_to_olcp_err_map(err);
+	}
+
+	ots->cur_obj = last_obj;
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_prev_proc_execute(
+	struct bt_ots *ots)
+{
+	int err;
+	struct bt_gatt_ots_object *prev_obj;
+
+	if (!ots->cur_obj) {
+		return BT_GATT_OTS_OLCP_RES_OPERATION_FAILED;
+	}
+	err = bt_gatt_ots_obj_manager_prev_obj_get(ots->obj_manager,
+						   ots->cur_obj,
+						   &prev_obj);
+	if (err) {
+		return obj_manager_to_olcp_err_map(err);
+	}
+
+	ots->cur_obj = prev_obj;
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_next_proc_execute(
+	struct bt_ots *ots)
+{
+	int err;
+	struct bt_gatt_ots_object *next_obj;
+
+	if (!ots->cur_obj) {
+		return BT_GATT_OTS_OLCP_RES_OPERATION_FAILED;
+	}
+	err = bt_gatt_ots_obj_manager_next_obj_get(ots->obj_manager,
+						   ots->cur_obj,
+						   &next_obj);
+	if (err) {
+		return obj_manager_to_olcp_err_map(err);
+	}
+
+	ots->cur_obj = next_obj;
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_goto_proc_execute(
+	struct bt_ots *ots, uint64_t id)
+{
+	int err;
+	struct bt_gatt_ots_object *id_obj;
+
+	err = bt_gatt_ots_obj_manager_obj_get(ots->obj_manager,
+					      id,
+					      &id_obj);
+	if (err) {
+		return obj_manager_to_olcp_err_map(err);
+	}
+
+	ots->cur_obj = id_obj;
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static enum bt_gatt_ots_olcp_res_code olcp_proc_execute(
+	struct bt_ots *ots, struct bt_gatt_ots_olcp_proc *proc)
+{
+	LOG_DBG("Executing OLCP procedure with 0x%02X Op Code", proc->type);
+
+	switch (proc->type) {
+	case BT_GATT_OTS_OLCP_PROC_FIRST:
+		return olcp_first_proc_execute(ots);
+	case BT_GATT_OTS_OLCP_PROC_LAST:
+		return olcp_last_proc_execute(ots);
+	case BT_GATT_OTS_OLCP_PROC_PREV:
+		return olcp_prev_proc_execute(ots);
+	case BT_GATT_OTS_OLCP_PROC_NEXT:
+		return olcp_next_proc_execute(ots);
+	case BT_GATT_OTS_OLCP_PROC_GOTO:
+		return olcp_goto_proc_execute(ots, proc->goto_params.id);
+	case BT_GATT_OTS_OLCP_PROC_ORDER:
+	case BT_GATT_OTS_OLCP_PROC_REQ_NUM_OBJS:
+	case BT_GATT_OTS_OLCP_PROC_CLEAR_MARKING:
+	default:
+		return BT_GATT_OTS_OLCP_RES_PROC_NOT_SUP;
+	}
+};
+
+static enum bt_gatt_ots_olcp_res_code olcp_command_decode(
+	const uint8_t *buf, struct bt_gatt_ots_olcp_proc *proc)
+{
+	memset(proc, 0, sizeof(*proc));
+
+	proc->type = *buf++;
+
+	switch (proc->type) {
+	case BT_GATT_OTS_OLCP_PROC_FIRST:
+	case BT_GATT_OTS_OLCP_PROC_LAST:
+	case BT_GATT_OTS_OLCP_PROC_PREV:
+	case BT_GATT_OTS_OLCP_PROC_NEXT:
+		break;
+	case BT_GATT_OTS_OLCP_PROC_GOTO:
+		proc->goto_params.id = sys_get_le48(buf);
+		break;
+	default:
+		LOG_WRN("OLCP unsupported procedure type");
+		return BT_GATT_OTS_OLCP_RES_PROC_NOT_SUP;
+	}
+
+	return BT_GATT_OTS_OLCP_RES_SUCCESS;
+}
+
+static bool olcp_command_len_verify(enum bt_gatt_ots_olcp_proc_type type,
+				    uint16_t len)
+{
+	uint16_t ref_len = OLCP_PROC_TYPE_SIZE;
+
+	switch (type) {
+	case BT_GATT_OTS_OLCP_PROC_FIRST:
+	case BT_GATT_OTS_OLCP_PROC_LAST:
+	case BT_GATT_OTS_OLCP_PROC_PREV:
+	case BT_GATT_OTS_OLCP_PROC_NEXT:
+	case BT_GATT_OTS_OLCP_PROC_REQ_NUM_OBJS:
+	case BT_GATT_OTS_OLCP_PROC_CLEAR_MARKING:
+		break;
+	case BT_GATT_OTS_OLCP_PROC_GOTO:
+		ref_len += BT_OTS_OBJ_ID_SIZE;
+		break;
+	case BT_GATT_OTS_OLCP_PROC_ORDER:
+		ref_len += sizeof(uint8_t);
+		break;
+	default:
+		return true;
+	}
+
+	return (len == ref_len);
+}
+
+static void olcp_ind_cb(struct bt_conn *conn,
+		const struct bt_gatt_attr *attr,
+		uint8_t err)
+{
+	LOG_DBG("Received OLCP Indication ACK with status: 0x%04X", err);
+}
+
+static int olcp_ind_send(const struct bt_gatt_attr *olcp_attr,
+			 enum bt_gatt_ots_olcp_proc_type req_op_code,
+			 enum bt_gatt_ots_olcp_res_code olcp_status)
+{
+	uint8_t olcp_res[OLCP_RES_MAX_SIZE];
+	uint16_t olcp_res_len = 0;
+	struct bt_ots *ots = (struct bt_ots *) olcp_attr->user_data;
+
+	/* Encode OLCP Response */
+	olcp_res[olcp_res_len++] = BT_GATT_OTS_OLCP_PROC_RESP;
+	olcp_res[olcp_res_len++] = req_op_code;
+	olcp_res[olcp_res_len++] = olcp_status;
+
+	/* Prepare indication parameters */
+	memset(&ots->olcp_ind.params, 0, sizeof(ots->olcp_ind.params));
+	memcpy(&ots->olcp_ind.attr, olcp_attr, sizeof(ots->olcp_ind.attr));
+	ots->olcp_ind.params.attr = olcp_attr;
+	ots->olcp_ind.params.func = olcp_ind_cb;
+	ots->olcp_ind.params.data = olcp_res;
+	ots->olcp_ind.params.len  = olcp_res_len;
+
+	LOG_DBG("Sending OLCP indication");
+
+	return bt_gatt_indicate(NULL, &ots->olcp_ind.params);
+}
+
+ssize_t bt_gatt_ots_olcp_write(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   const void *buf, uint16_t len,
+				   uint16_t offset, uint8_t flags)
+{
+	struct bt_gatt_ots_object *old_obj;
+	enum bt_gatt_ots_olcp_res_code olcp_status;
+	struct bt_gatt_ots_olcp_proc olcp_proc;
+	struct bt_ots *ots = (struct bt_ots *) attr->user_data;
+
+	LOG_DBG("Object List Control Point GATT Write Operation");
+
+	if (!ots->olcp_ind.is_enabled) {
+		LOG_WRN("OLCP indications not enabled");
+		return BT_GATT_ERR(BT_ATT_ERR_CCC_IMPROPER_CONF);
+	}
+
+	if (offset != 0) {
+		LOG_ERR("Invalid offset of OLCP Write Request");
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	olcp_status = olcp_command_decode(buf, &olcp_proc);
+
+	if (!olcp_command_len_verify(olcp_proc.type, len)) {
+		LOG_ERR("Invalid length of OLCP Write Request for 0x%02X "
+			"Op Code", olcp_proc.type);
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
+	}
+
+	old_obj = ots->cur_obj;
+	if (olcp_status == BT_GATT_OTS_OLCP_RES_SUCCESS) {
+		olcp_status = olcp_proc_execute(ots, &olcp_proc);
+	}
+
+	if (olcp_status != BT_GATT_OTS_OLCP_RES_SUCCESS) {
+		LOG_WRN("OLCP Write error status: 0x%02X", olcp_status);
+	} else if (old_obj != ots->cur_obj) {
+		char id[BT_OTS_OBJ_ID_STR_LEN];
+
+		bt_ots_obj_id_to_str(ots->cur_obj->id, id,
+					      sizeof(id));
+		LOG_DBG("Selecting a new Current Object with id: %s",
+			log_strdup(id));
+
+		if (ots->cb->obj_selected) {
+			ots->cb->obj_selected(ots, conn, ots->cur_obj->id);
+		}
+	}
+
+	olcp_ind_send(attr, olcp_proc.type, olcp_status);
+	return len;
+}
+
+void bt_gatt_ots_olcp_cfg_changed(const struct bt_gatt_attr *attr,
+				      uint16_t value)
+{
+	struct bt_gatt_ots_indicate *olcp_ind =
+	    CONTAINER_OF((struct _bt_gatt_ccc *) attr->user_data,
+			 struct bt_gatt_ots_indicate, ccc);
+
+	LOG_DBG("Object List Control Point CCCD value: 0x%04X", value);
+
+	olcp_ind->is_enabled = false;
+	if (value == BT_GATT_CCC_INDICATE) {
+		olcp_ind->is_enabled = true;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/services/ots/ots_olcp_internal.h	(working copy)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef BT_GATT_OTS_OLCP_H_
+#define BT_GATT_OTS_OLCP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <zephyr/types.h>
+#include <bluetooth/gatt.h>
+
+/* The types of OLCP procedures. */
+enum bt_gatt_ots_olcp_proc_type {
+	/* Select the first object.*/
+	BT_GATT_OTS_OLCP_PROC_FIRST         = 0x01,
+	/* Select the last object.*/
+	BT_GATT_OTS_OLCP_PROC_LAST          = 0x02,
+	/* Select the previous object.*/
+	BT_GATT_OTS_OLCP_PROC_PREV          = 0x03,
+	/* Select the next object.*/
+	BT_GATT_OTS_OLCP_PROC_NEXT          = 0x04,
+	/* Select the object with the given object ID.*/
+	BT_GATT_OTS_OLCP_PROC_GOTO          = 0x05,
+	/* Order the objects.*/
+	BT_GATT_OTS_OLCP_PROC_ORDER         = 0x06,
+	/* Request the number of objects.*/
+	BT_GATT_OTS_OLCP_PROC_REQ_NUM_OBJS  = 0x07,
+	/* Clear Marking.*/
+	BT_GATT_OTS_OLCP_PROC_CLEAR_MARKING = 0x08,
+	/* Response.*/
+	BT_GATT_OTS_OLCP_PROC_RESP          = 0x70,
+};
+
+/* Definition of a OLCP procedure. */
+struct bt_gatt_ots_olcp_proc {
+	enum bt_gatt_ots_olcp_proc_type type;
+	union {
+		struct {
+			uint64_t id;
+		} goto_params;
+	};
+};
+
+/* The return codes obtained from doing OLCP procedures. */
+enum bt_gatt_ots_olcp_res_code {
+	/* Response for successful operation. */
+	BT_GATT_OTS_OLCP_RES_SUCCESS = 0x01,
+	/* Response if unsupported Op Code is received.*/
+	BT_GATT_OTS_OLCP_RES_PROC_NOT_SUP = 0x02,
+	/* Response if Parameter received does not meet
+	 * the requirements of the service.
+	 */
+	BT_GATT_OTS_OLCP_RES_INVALID_PARAMETER = 0x03,
+	/* Response if the requested procedure failed for a reason
+	 * other than those enumerated below.
+	 */
+	BT_GATT_OTS_OLCP_RES_OPERATION_FAILED = 0x04,
+	/* Response if the requested procedure attempted to select an object
+	 * beyond the first object or
+	 * beyond the last object in the current list.
+	 */
+	BT_GATT_OTS_OLCP_RES_OUT_OF_BONDS = 0x05,
+	/* Response if the requested procedure failed due
+	 * to too many objects in the current list.
+	 */
+	BT_GATT_OTS_OLCP_RES_TOO_MANY_OBJECTS = 0x06,
+	/* Response if the requested procedure failed due
+	 * to there being zero objects in the current list.
+	 */
+	BT_GATT_OTS_OLCP_RES_NO_OBJECT = 0x07,
+	/* Response if the requested procedure failed due
+	 * to there being no object with the requested Object ID.
+	 */
+	BT_GATT_OTS_OLCP_RES_OBJECT_ID_NOT_FOUND = 0x08,
+};
+
+ssize_t bt_gatt_ots_olcp_write(struct bt_conn *conn,
+				   const struct bt_gatt_attr *attr,
+				   const void *buf, uint16_t len,
+				   uint16_t offset, uint8_t flags);
+
+void bt_gatt_ots_olcp_cfg_changed(const struct bt_gatt_attr *attr,
+				      uint16_t value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_GATT_OTS_OLCP_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/CMakeLists.txt	(working copy)
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_sources(
+  bt.c
+  hci.c
+  )
+zephyr_library_sources_ifdef(
+  CONFIG_BT_CONN
+  gatt.c
+  )
+zephyr_library_sources_ifdef(
+  CONFIG_BT_BREDR
+  bredr.c
+  )
+zephyr_library_sources_ifdef(
+  CONFIG_BT_L2CAP_DYNAMIC_CHANNEL
+  l2cap.c
+  )
+zephyr_library_sources_ifdef(
+  CONFIG_BT_RFCOMM
+  rfcomm.c
+  )
+zephyr_library_sources_ifdef(
+  CONFIG_BT_ISO
+  iso.c
+  )
+
+if(CONFIG_BT_CTLR AND CONFIG_BT_LL_SW_SPLIT)
+  zephyr_library_sources(
+    ll.c
+    ticker.c
+    )
+  zephyr_include_directories(
+    ${ZEPHYR_BASE}/subsys/bluetooth/controller/ll_sw/nordic
+    )
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/Kconfig	(working copy)
@@ -0,0 +1,11 @@
+# Shell configuration options
+
+# Copyright (c) 2017 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config BT_SHELL
+	bool "Enable Bluetooth shell"
+	select SHELL
+	help
+	  Activate shell module that provides Bluetooth commands to the
+	  console.
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bredr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bredr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bredr.c	(working copy)
@@ -0,0 +1,564 @@
+/** @file
+ * @brief Bluetooth BR/EDR shell module
+ *
+ * Provide some Bluetooth shell commands that can be useful to applications.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+
+#include <shell/shell.h>
+
+#include "bt.h"
+
+#if defined(CONFIG_BT_CONN)
+/* Connection context for BR/EDR legacy pairing in sec mode 3 */
+static struct bt_conn *pairing_conn;
+#endif /* CONFIG_BT_CONN */
+
+#define DATA_BREDR_MTU		48
+
+NET_BUF_POOL_FIXED_DEFINE(data_pool, 1, DATA_BREDR_MTU, NULL);
+
+#define SDP_CLIENT_USER_BUF_LEN		512
+NET_BUF_POOL_FIXED_DEFINE(sdp_client_pool, CONFIG_BT_MAX_CONN,
+			  SDP_CLIENT_USER_BUF_LEN, NULL);
+
+static int cmd_auth_pincode(const struct shell *shell,
+			    size_t argc, char *argv[])
+{
+	struct bt_conn *conn;
+	uint8_t max = 16U;
+
+	if (default_conn) {
+		conn = default_conn;
+	} else if (pairing_conn) {
+		conn = pairing_conn;
+	} else {
+		conn = NULL;
+	}
+
+	if (!conn) {
+		shell_print(shell, "Not connected");
+		return 0;
+	}
+
+	if (strlen(argv[1]) > max) {
+		shell_print(shell, "PIN code value invalid - enter max %u "
+			    "digits", max);
+		return 0;
+	}
+
+	shell_print(shell, "PIN code \"%s\" applied", argv[1]);
+
+	bt_conn_auth_pincode_entry(conn, argv[1]);
+
+	return 0;
+}
+
+static int cmd_connect(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_conn *conn;
+	bt_addr_t addr;
+	int err;
+
+	err = bt_addr_from_str(argv[1], &addr);
+	if (err) {
+		shell_print(shell, "Invalid peer address (err %d)", err);
+		return -ENOEXEC;
+	}
+
+	conn = bt_conn_create_br(&addr, BT_BR_CONN_PARAM_DEFAULT);
+	if (!conn) {
+		shell_print(shell, "Connection failed");
+	} else {
+
+		shell_print(shell, "Connection pending");
+
+		/* unref connection obj in advance as app user */
+		bt_conn_unref(conn);
+	}
+
+	return 0;
+}
+
+static void br_device_found(const bt_addr_t *addr, int8_t rssi,
+				  const uint8_t cod[3], const uint8_t eir[240])
+{
+	char br_addr[BT_ADDR_STR_LEN];
+	char name[239];
+	int len = 240;
+
+	(void)memset(name, 0, sizeof(name));
+
+	while (len) {
+		if (len < 2) {
+			break;
+		};
+
+		/* Look for early termination */
+		if (!eir[0]) {
+			break;
+		}
+
+		/* Check if field length is correct */
+		if (eir[0] > len - 1) {
+			break;
+		}
+
+		switch (eir[1]) {
+		case BT_DATA_NAME_SHORTENED:
+		case BT_DATA_NAME_COMPLETE:
+			if (eir[0] > sizeof(name) - 1) {
+				memcpy(name, &eir[2], sizeof(name) - 1);
+			} else {
+				memcpy(name, &eir[2], eir[0] - 1);
+			}
+			break;
+		default:
+			break;
+		}
+
+		/* Parse next AD Structure */
+		len -= eir[0] + 1;
+		eir += eir[0] + 1;
+	}
+
+	bt_addr_to_str(addr, br_addr, sizeof(br_addr));
+
+	shell_print(ctx_shell, "[DEVICE]: %s, RSSI %i %s", br_addr, rssi, name);
+}
+
+static struct bt_br_discovery_result br_discovery_results[5];
+
+static void br_discovery_complete(struct bt_br_discovery_result *results,
+				  size_t count)
+{
+	size_t i;
+
+	shell_print(ctx_shell, "BR/EDR discovery complete");
+
+	for (i = 0; i < count; i++) {
+		br_device_found(&results[i].addr, results[i].rssi,
+				results[i].cod, results[i].eir);
+	}
+}
+
+static int cmd_discovery(const struct shell *shell, size_t argc, char *argv[])
+{
+	const char *action;
+
+	action = argv[1];
+	if (!strcmp(action, "on")) {
+		struct bt_br_discovery_param param;
+
+		param.limited = false;
+		param.length = 8U;
+
+		if (argc > 2) {
+			param.length = atoi(argv[2]);
+		}
+
+		if (argc > 3 && !strcmp(argv[3], "limited")) {
+			param.limited = true;
+		}
+
+		if (bt_br_discovery_start(&param, br_discovery_results,
+					  ARRAY_SIZE(br_discovery_results),
+					  br_discovery_complete) < 0) {
+			shell_print(shell, "Failed to start discovery");
+			return 0;
+		}
+
+		shell_print(shell, "Discovery started");
+	} else if (!strcmp(action, "off")) {
+		if (bt_br_discovery_stop()) {
+			shell_print(shell, "Failed to stop discovery");
+			return 0;
+		}
+
+		shell_print(shell, "Discovery stopped");
+	} else {
+		shell_help(shell);
+	}
+
+	return 0;
+}
+
+static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	shell_print(ctx_shell, "Incoming data channel %p len %u", chan,
+		    buf->len);
+
+	return 0;
+}
+
+static void l2cap_connected(struct bt_l2cap_chan *chan)
+{
+	shell_print(ctx_shell, "Channel %p connected", chan);
+}
+
+static void l2cap_disconnected(struct bt_l2cap_chan *chan)
+{
+	shell_print(ctx_shell, "Channel %p disconnected", chan);
+}
+
+static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
+{
+	shell_print(ctx_shell, "Channel %p requires buffer", chan);
+
+	return net_buf_alloc(&data_pool, K_FOREVER);
+}
+
+static const struct bt_l2cap_chan_ops l2cap_ops = {
+	.alloc_buf	= l2cap_alloc_buf,
+	.recv		= l2cap_recv,
+	.connected	= l2cap_connected,
+	.disconnected	= l2cap_disconnected,
+};
+
+static struct bt_l2cap_br_chan l2cap_chan = {
+	.chan.ops	= &l2cap_ops,
+	 /* Set for now min. MTU */
+	.rx.mtu		= 48,
+};
+
+static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	shell_print(ctx_shell, "Incoming BR/EDR conn %p", conn);
+
+	if (l2cap_chan.chan.conn) {
+		shell_error(ctx_shell, "No channels available");
+		return -ENOMEM;
+	}
+
+	*chan = &l2cap_chan.chan;
+
+	return 0;
+}
+
+static struct bt_l2cap_server br_server = {
+	.accept = l2cap_accept,
+};
+
+static int cmd_l2cap_register(const struct shell *shell,
+			      size_t argc, char *argv[])
+{
+	if (br_server.psm) {
+		shell_print(shell, "Already registered");
+		return 0;
+	}
+
+	br_server.psm = strtoul(argv[1], NULL, 16);
+
+	if (bt_l2cap_br_server_register(&br_server) < 0) {
+		shell_error(shell, "Unable to register psm");
+		br_server.psm = 0U;
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "L2CAP psm %u registered", br_server.psm);
+	}
+
+	return 0;
+}
+
+static int cmd_discoverable(const struct shell *shell,
+			    size_t argc, char *argv[])
+{
+	int err;
+	const char *action;
+
+	action = argv[1];
+
+	if (!strcmp(action, "on")) {
+		err = bt_br_set_discoverable(true);
+	} else if (!strcmp(action, "off")) {
+		err = bt_br_set_discoverable(false);
+	} else {
+		shell_help(shell);
+		return 0;
+	}
+
+	if (err) {
+		shell_print(shell, "BR/EDR set/reset discoverable failed "
+			    "(err %d)", err);
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "BR/EDR set/reset discoverable done");
+	}
+
+	return 0;
+}
+
+static int cmd_connectable(const struct shell *shell,
+			   size_t argc, char *argv[])
+{
+	int err;
+	const char *action;
+
+	action = argv[1];
+
+	if (!strcmp(action, "on")) {
+		err = bt_br_set_connectable(true);
+	} else if (!strcmp(action, "off")) {
+		err = bt_br_set_connectable(false);
+	} else {
+		shell_help(shell);
+		return 0;
+	}
+
+	if (err) {
+		shell_print(shell, "BR/EDR set/rest connectable failed "
+			    "(err %d)", err);
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "BR/EDR set/reset connectable done");
+	}
+
+	return 0;
+}
+
+static int cmd_oob(const struct shell *shell, size_t argc, char *argv[])
+{
+	char addr[BT_ADDR_STR_LEN];
+	struct bt_br_oob oob;
+	int err;
+
+	err = bt_br_oob_get_local(&oob);
+	if (err) {
+		shell_print(shell, "BR/EDR OOB data failed");
+		return -ENOEXEC;
+	}
+
+	bt_addr_to_str(&oob.addr, addr, sizeof(addr));
+
+	shell_print(shell, "BR/EDR OOB data:");
+	shell_print(shell, "  addr %s", addr);
+	return 0;
+}
+
+static uint8_t sdp_hfp_ag_user(struct bt_conn *conn,
+			       struct bt_sdp_client_result *result)
+{
+	char addr[BT_ADDR_STR_LEN];
+	uint16_t param, version;
+	uint16_t features;
+	int res;
+
+	conn_addr_str(conn, addr, sizeof(addr));
+
+	if (result) {
+		shell_print(ctx_shell, "SDP HFPAG data@%p (len %u) hint %u from"
+			    " remote %s", result->resp_buf,
+			    result->resp_buf->len, result->next_record_hint,
+			    addr);
+
+		/*
+		 * Focus to get BT_SDP_ATTR_PROTO_DESC_LIST attribute item to
+		 * get HFPAG Server Channel Number operating on RFCOMM protocol.
+		 */
+		res = bt_sdp_get_proto_param(result->resp_buf,
+					     BT_SDP_PROTO_RFCOMM, &param);
+		if (res < 0) {
+			shell_error(ctx_shell, "Error getting Server CN, "
+				    "err %d", res);
+			goto done;
+		}
+		shell_print(ctx_shell, "HFPAG Server CN param 0x%04x", param);
+
+		res = bt_sdp_get_profile_version(result->resp_buf,
+						 BT_SDP_HANDSFREE_SVCLASS,
+						 &version);
+		if (res < 0) {
+			shell_error(ctx_shell, "Error getting profile version, "
+				    "err %d", res);
+			goto done;
+		}
+		shell_print(ctx_shell, "HFP version param 0x%04x", version);
+
+		/*
+		 * Focus to get BT_SDP_ATTR_SUPPORTED_FEATURES attribute item to
+		 * get profile Supported Features mask.
+		 */
+		res = bt_sdp_get_features(result->resp_buf, &features);
+		if (res < 0) {
+			shell_error(ctx_shell, "Error getting HFPAG Features, "
+				    "err %d", res);
+			goto done;
+		}
+		shell_print(ctx_shell, "HFPAG Supported Features param 0x%04x",
+		      features);
+	} else {
+		shell_print(ctx_shell, "No SDP HFPAG data from remote %s",
+			    addr);
+	}
+done:
+	return BT_SDP_DISCOVER_UUID_CONTINUE;
+}
+
+static uint8_t sdp_a2src_user(struct bt_conn *conn,
+			   struct bt_sdp_client_result *result)
+{
+	char addr[BT_ADDR_STR_LEN];
+	uint16_t param, version;
+	uint16_t features;
+	int res;
+
+	conn_addr_str(conn, addr, sizeof(addr));
+
+	if (result) {
+		shell_print(ctx_shell, "SDP A2SRC data@%p (len %u) hint %u from"
+			    " remote %s", result->resp_buf,
+			    result->resp_buf->len, result->next_record_hint,
+			    addr);
+
+		/*
+		 * Focus to get BT_SDP_ATTR_PROTO_DESC_LIST attribute item to
+		 * get A2SRC Server PSM Number.
+		 */
+		res = bt_sdp_get_proto_param(result->resp_buf,
+					     BT_SDP_PROTO_L2CAP, &param);
+		if (res < 0) {
+			shell_error(ctx_shell, "A2SRC PSM Number not found, "
+				    "err %d", res);
+			goto done;
+		}
+
+		shell_print(ctx_shell, "A2SRC Server PSM Number param 0x%04x",
+			    param);
+
+		/*
+		 * Focus to get BT_SDP_ATTR_PROFILE_DESC_LIST attribute item to
+		 * get profile version number.
+		 */
+		res = bt_sdp_get_profile_version(result->resp_buf,
+						 BT_SDP_ADVANCED_AUDIO_SVCLASS,
+						 &version);
+		if (res < 0) {
+			shell_error(ctx_shell, "A2SRC version not found, "
+				    "err %d", res);
+			goto done;
+		}
+		shell_print(ctx_shell, "A2SRC version param 0x%04x", version);
+
+		/*
+		 * Focus to get BT_SDP_ATTR_SUPPORTED_FEATURES attribute item to
+		 * get profile supported features mask.
+		 */
+		res = bt_sdp_get_features(result->resp_buf, &features);
+		if (res < 0) {
+			shell_error(ctx_shell, "A2SRC Features not found, "
+				    "err %d", res);
+			goto done;
+		}
+		shell_print(ctx_shell, "A2SRC Supported Features param 0x%04x",
+		      features);
+	} else {
+		shell_print(ctx_shell, "No SDP A2SRC data from remote %s",
+			    addr);
+	}
+done:
+	return BT_SDP_DISCOVER_UUID_CONTINUE;
+}
+
+static struct bt_sdp_discover_params discov_hfpag = {
+	.uuid = BT_UUID_DECLARE_16(BT_SDP_HANDSFREE_AGW_SVCLASS),
+	.func = sdp_hfp_ag_user,
+	.pool = &sdp_client_pool,
+};
+
+static struct bt_sdp_discover_params discov_a2src = {
+	.uuid = BT_UUID_DECLARE_16(BT_SDP_AUDIO_SOURCE_SVCLASS),
+	.func = sdp_a2src_user,
+	.pool = &sdp_client_pool,
+};
+
+static struct bt_sdp_discover_params discov;
+
+static int cmd_sdp_find_record(const struct shell *shell,
+			       size_t argc, char *argv[])
+{
+	int res;
+	const char *action;
+
+	if (!default_conn) {
+		shell_print(shell, "Not connected");
+		return 0;
+	}
+
+	action = argv[1];
+
+	if (!strcmp(action, "HFPAG")) {
+		discov = discov_hfpag;
+	} else if (!strcmp(action, "A2SRC")) {
+		discov = discov_a2src;
+	} else {
+		shell_help(shell);
+		return 0;
+	}
+
+	shell_print(shell, "SDP UUID \'%s\' gets applied", action);
+
+	res = bt_sdp_discover(default_conn, &discov);
+	if (res) {
+		shell_error(shell, "SDP discovery failed: result %d", res);
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "SDP discovery started");
+	}
+
+	return 0;
+}
+
+#define HELP_NONE "[none]"
+#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
+
+SHELL_STATIC_SUBCMD_SET_CREATE(br_cmds,
+	SHELL_CMD_ARG(auth-pincode, NULL, "<pincode>", cmd_auth_pincode, 2, 0),
+	SHELL_CMD_ARG(connect, NULL, "<address>", cmd_connect, 2, 0),
+	SHELL_CMD_ARG(discovery, NULL,
+		      "<value: on, off> [length: 1-48] [mode: limited]",
+		      cmd_discovery, 2, 2),
+	SHELL_CMD_ARG(iscan, NULL, "<value: on, off>", cmd_discoverable, 2, 0),
+	SHELL_CMD_ARG(l2cap-register, NULL, "<psm>", cmd_l2cap_register, 2, 0),
+	SHELL_CMD_ARG(oob, NULL, NULL, cmd_oob, 1, 0),
+	SHELL_CMD_ARG(pscan, NULL, "<value: on, off>", cmd_connectable, 2, 0),
+	SHELL_CMD_ARG(sdp-find, NULL, "<HFPAG>", cmd_sdp_find_record, 2, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_br(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -ENOEXEC;
+}
+
+SHELL_CMD_ARG_REGISTER(br, &br_cmds, "Bluetooth BR/EDR shell commands", cmd_br,
+		       1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.h	(working copy)
@@ -0,0 +1,21 @@
+/** @file
+ *  @brief Bluetooth shell functions
+ *
+ *  This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __BT_H
+#define __BT_H
+
+extern const struct shell *ctx_shell;
+extern struct bt_conn *default_conn;
+
+void conn_addr_str(struct bt_conn *conn, char *addr, size_t len);
+
+#endif /* __BT_H */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/bt.c	(working copy)
@@ -0,0 +1,2919 @@
+/** @file
+ * @brief Bluetooth shell module
+ *
+ * Provide some Bluetooth shell commands that can be useful to applications.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+#include <zephyr.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/hci.h>
+
+#include <shell/shell.h>
+
+#include "bt.h"
+#include "ll.h"
+#include "hci.h"
+
+#define DEVICE_NAME		CONFIG_BT_DEVICE_NAME
+#define DEVICE_NAME_LEN		(sizeof(DEVICE_NAME) - 1)
+
+uint8_t selected_id = BT_ID_DEFAULT;
+const struct shell *ctx_shell;
+
+#if defined(CONFIG_BT_CONN)
+struct bt_conn *default_conn;
+
+/* Connection context for BR/EDR legacy pairing in sec mode 3 */
+static struct bt_conn *pairing_conn;
+
+static struct bt_le_oob oob_local;
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+static struct bt_le_oob oob_remote;
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
+#endif /* CONFIG_BT_CONN */
+
+#define NAME_LEN 30
+
+#define KEY_STR_LEN 33
+
+/*
+ * Based on the maximum number of parameters for HCI_LE_Generate_DHKey
+ * See BT Core Spec V5.2 Vol. 4, Part E, section 7.8.37
+ */
+#define HCI_CMD_MAX_PARAM 65
+
+#if defined(CONFIG_BT_EXT_ADV)
+#if defined(CONFIG_BT_BROADCASTER)
+static uint8_t selected_adv;
+struct bt_le_ext_adv *adv_sets[CONFIG_BT_EXT_ADV_MAX_ADV_SET];
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* CONFIG_BT_EXT_ADV */
+
+#if defined(CONFIG_BT_OBSERVER)
+static bool data_cb(struct bt_data *data, void *user_data)
+{
+	char *name = user_data;
+
+	switch (data->type) {
+	case BT_DATA_NAME_SHORTENED:
+	case BT_DATA_NAME_COMPLETE:
+		memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
+		return false;
+	default:
+		return true;
+	}
+}
+
+static const char *phy2str(uint8_t phy)
+{
+	switch (phy) {
+	case 0: return "No packets";
+	case BT_GAP_LE_PHY_1M: return "LE 1M";
+	case BT_GAP_LE_PHY_2M: return "LE 2M";
+	case BT_GAP_LE_PHY_CODED: return "LE Coded";
+	default: return "Unknown";
+	}
+}
+
+static void scan_recv(const struct bt_le_scan_recv_info *info,
+		      struct net_buf_simple *buf)
+{
+	char le_addr[BT_ADDR_LE_STR_LEN];
+	char name[NAME_LEN];
+
+	(void)memset(name, 0, sizeof(name));
+
+	bt_data_parse(buf, data_cb, name);
+
+	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
+	shell_print(ctx_shell, "[DEVICE]: %s, AD evt type %u, RSSI %i %s "
+		    "C:%u S:%u D:%d SR:%u E:%u Prim: %s, Secn: %s, "
+		    "Interval: 0x%04x (%u ms), SID: 0x%x",
+		    le_addr, info->adv_type, info->rssi, name,
+		    (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
+		    (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
+		    (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
+		    (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
+		    (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
+		    phy2str(info->primary_phy), phy2str(info->secondary_phy),
+		    info->interval, info->interval * 5 / 4, info->sid);
+}
+
+static void scan_timeout(void)
+{
+	shell_print(ctx_shell, "Scan timeout");
+}
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_EXT_ADV)
+#if defined(CONFIG_BT_BROADCASTER)
+static void adv_sent(struct bt_le_ext_adv *adv,
+		     struct bt_le_ext_adv_sent_info *info)
+{
+	shell_print(ctx_shell, "Advertiser[%d] %p sent %d",
+		    bt_le_ext_adv_get_index(adv), adv, info->num_sent);
+}
+
+static void adv_scanned(struct bt_le_ext_adv *adv,
+			struct bt_le_ext_adv_scanned_info *info)
+{
+	char str[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(info->addr, str, sizeof(str));
+
+	shell_print(ctx_shell, "Advertiser[%d] %p scanned by %s",
+		    bt_le_ext_adv_get_index(adv), adv, str);
+}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static void adv_connected(struct bt_le_ext_adv *adv,
+			  struct bt_le_ext_adv_connected_info *info)
+{
+	char str[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(bt_conn_get_dst(info->conn), str, sizeof(str));
+
+	shell_print(ctx_shell, "Advertiser[%d] %p connected by %s",
+		    bt_le_ext_adv_get_index(adv), adv, str);
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+#endif /* CONFIG_BT_EXT_ADV */
+
+#if !defined(CONFIG_BT_CONN)
+#if 0 /* FIXME: Add support for changing prompt */
+static const char *current_prompt(void)
+{
+	return NULL;
+}
+#endif
+#endif /* !CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_CONN)
+#if 0 /* FIXME: Add support for changing prompt */
+static const char *current_prompt(void)
+{
+	static char str[BT_ADDR_LE_STR_LEN + 2];
+	static struct bt_conn_info info;
+
+	if (!default_conn) {
+		return NULL;
+	}
+
+	if (bt_conn_get_info(default_conn, &info) < 0) {
+		return NULL;
+	}
+
+	if (info.type != BT_CONN_TYPE_LE) {
+		return NULL;
+	}
+
+	bt_addr_le_to_str(info.le.dst, str, sizeof(str) - 2);
+	strcat(str, "> ");
+	return str;
+}
+#endif
+
+void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
+{
+	struct bt_conn_info info;
+
+	if (bt_conn_get_info(conn, &info) < 0) {
+		addr[0] = '\0';
+		return;
+	}
+
+	switch (info.type) {
+#if defined(CONFIG_BT_BREDR)
+	case BT_CONN_TYPE_BR:
+		bt_addr_to_str(info.br.dst, addr, len);
+		break;
+#endif
+	case BT_CONN_TYPE_LE:
+		bt_addr_le_to_str(info.le.dst, addr, len);
+		break;
+	}
+}
+
+static void print_le_oob(const struct shell *shell, struct bt_le_oob *oob)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	char c[KEY_STR_LEN];
+	char r[KEY_STR_LEN];
+
+	bt_addr_le_to_str(&oob->addr, addr, sizeof(addr));
+
+	bin2hex(oob->le_sc_data.c, sizeof(oob->le_sc_data.c), c, sizeof(c));
+	bin2hex(oob->le_sc_data.r, sizeof(oob->le_sc_data.r), r, sizeof(r));
+
+	shell_print(shell, "OOB data:");
+	shell_print(shell, "%-29s %-32s %-32s", "addr", "random", "confirm");
+	shell_print(shell, "%29s %32s %32s", addr, r, c);
+}
+
+static void connected(struct bt_conn *conn, uint8_t err)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	conn_addr_str(conn, addr, sizeof(addr));
+
+	if (err) {
+		shell_error(ctx_shell, "Failed to connect to %s (0x%02x)", addr,
+			     err);
+		goto done;
+	}
+
+	shell_print(ctx_shell, "Connected: %s", addr);
+
+	if (!default_conn) {
+		default_conn = bt_conn_ref(conn);
+	}
+
+done:
+	/* clear connection reference for sec mode 3 pairing */
+	if (pairing_conn) {
+		bt_conn_unref(pairing_conn);
+		pairing_conn = NULL;
+	}
+}
+
+static void disconnected(struct bt_conn *conn, uint8_t reason)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	conn_addr_str(conn, addr, sizeof(addr));
+	shell_print(ctx_shell, "Disconnected: %s (reason 0x%02x)", addr, reason);
+
+	if (default_conn == conn) {
+		bt_conn_unref(default_conn);
+		default_conn = NULL;
+	}
+}
+
+static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
+{
+	shell_print(ctx_shell, "LE conn  param req: int (0x%04x, 0x%04x) lat %d"
+		    " to %d", param->interval_min, param->interval_max,
+		    param->latency, param->timeout);
+
+	return true;
+}
+
+static void le_param_updated(struct bt_conn *conn, uint16_t interval,
+			     uint16_t latency, uint16_t timeout)
+{
+	shell_print(ctx_shell, "LE conn param updated: int 0x%04x lat %d "
+		     "to %d", interval, latency, timeout);
+}
+
+#if defined(CONFIG_BT_SMP)
+static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
+			      const bt_addr_le_t *identity)
+{
+	char addr_identity[BT_ADDR_LE_STR_LEN];
+	char addr_rpa[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
+	bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
+
+	shell_print(ctx_shell, "Identity resolved %s -> %s", addr_rpa,
+	      addr_identity);
+}
+#endif
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+static void security_changed(struct bt_conn *conn, bt_security_t level,
+			     enum bt_security_err err)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	conn_addr_str(conn, addr, sizeof(addr));
+
+	if (!err) {
+		shell_print(ctx_shell, "Security changed: %s level %u", addr,
+			    level);
+	} else {
+		shell_print(ctx_shell, "Security failed: %s level %u reason %d",
+			    addr, level, err);
+	}
+}
+#endif
+
+#if defined(CONFIG_BT_REMOTE_INFO)
+static const char *ver_str(uint8_t ver)
+{
+	const char * const str[] = {
+		"1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2",
+		"5.0", "5.1",
+	};
+
+	if (ver < ARRAY_SIZE(str)) {
+		return str[ver];
+	}
+
+	return "unknown";
+}
+
+static void remote_info_available(struct bt_conn *conn,
+				  struct bt_conn_remote_info *remote_info)
+{
+	struct bt_conn_info info;
+
+	bt_conn_get_info(conn, &info);
+
+	if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) {
+		shell_print(ctx_shell,
+			    "Remote LMP version %s (0x%02x) subversion 0x%04x "
+			    "manufacturer 0x%04x", ver_str(remote_info->version),
+			    remote_info->version, remote_info->subversion,
+			    remote_info->manufacturer);
+	}
+
+	if (info.type == BT_CONN_TYPE_LE) {
+		uint8_t features[8];
+		char features_str[2 * sizeof(features) +  1];
+
+		sys_memcpy_swap(features, remote_info->le.features,
+				sizeof(features));
+		bin2hex(features, sizeof(features),
+			features_str, sizeof(features_str));
+		shell_print(ctx_shell, "LE Features: 0x%s ", features_str);
+	}
+}
+#endif /* defined(CONFIG_BT_REMOTE_INFO) */
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+void le_data_len_updated(struct bt_conn *conn,
+			 struct bt_conn_le_data_len_info *info)
+{
+	shell_print(ctx_shell,
+		    "LE data len updated: TX (len: %d time: %d)"
+		    " RX (len: %d time: %d)", info->tx_max_len,
+		    info->tx_max_time, info->rx_max_len, info->rx_max_time);
+}
+#endif
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+void le_phy_updated(struct bt_conn *conn,
+		    struct bt_conn_le_phy_info *info)
+{
+	shell_print(ctx_shell, "LE PHY updated: TX PHY %s, RX PHY %s",
+		    phy2str(info->tx_phy), phy2str(info->rx_phy));
+}
+#endif
+
+static struct bt_conn_cb conn_callbacks = {
+	.connected = connected,
+	.disconnected = disconnected,
+	.le_param_req = le_param_req,
+	.le_param_updated = le_param_updated,
+#if defined(CONFIG_BT_SMP)
+	.identity_resolved = identity_resolved,
+#endif
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	.security_changed = security_changed,
+#endif
+#if defined(CONFIG_BT_REMOTE_INFO)
+	.remote_info_available = remote_info_available,
+#endif
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	.le_data_len_updated = le_data_len_updated,
+#endif
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	.le_phy_updated = le_phy_updated,
+#endif
+};
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_OBSERVER)
+static struct bt_le_scan_cb scan_callbacks = {
+	.recv = scan_recv,
+	.timeout = scan_timeout,
+};
+#endif /* defined(CONFIG_BT_OBSERVER) */
+
+#if defined(CONFIG_BT_EXT_ADV)
+#if defined(CONFIG_BT_BROADCASTER)
+static struct bt_le_ext_adv_cb adv_callbacks = {
+	.sent = adv_sent,
+	.scanned = adv_scanned,
+#if defined(CONFIG_BT_PERIPHERAL)
+	.connected = adv_connected,
+#endif /* CONFIG_BT_PERIPHERAL */
+};
+#endif /* CONFIG_BT_BROADCASTER */
+#endif /* CONFIG_BT_EXT_ADV */
+
+static void bt_ready(int err)
+{
+	if (err) {
+		shell_error(ctx_shell, "Bluetooth init failed (err %d)", err);
+		return;
+	}
+
+	shell_print(ctx_shell, "Bluetooth initialized");
+
+	if (IS_ENABLED(CONFIG_SETTINGS)) {
+		settings_load();
+	}
+
+	if (IS_ENABLED(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)) {
+		bt_set_oob_data_flag(true);
+	}
+
+#if defined(CONFIG_BT_OBSERVER)
+	bt_le_scan_cb_register(&scan_callbacks);
+#endif
+
+#if defined(CONFIG_BT_CONN)
+	default_conn = NULL;
+
+	bt_conn_cb_register(&conn_callbacks);
+#endif /* CONFIG_BT_CONN */
+}
+
+static int cmd_init(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	ctx_shell = shell;
+
+	err = bt_enable(bt_ready);
+	if (err) {
+		shell_error(shell, "Bluetooth init failed (err %d)", err);
+	}
+
+	return err;
+}
+
+#if defined(CONFIG_BT_HCI)
+static int cmd_hci_cmd(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t ogf;
+	uint16_t ocf;
+	struct net_buf *buf = NULL, *rsp;
+	int err;
+	static uint8_t hex_data[HCI_CMD_MAX_PARAM];
+	int hex_data_len;
+
+	hex_data_len = 0;
+	ogf = strtoul(argv[1], NULL, 16);
+	ocf = strtoul(argv[2], NULL, 16);
+
+	if (argc > 3) {
+		size_t len;
+
+		if (strlen(argv[3]) > 2 * HCI_CMD_MAX_PARAM) {
+			shell_error(shell, "Data field too large\n");
+			return -ENOEXEC;
+		}
+
+		len = hex2bin(argv[3], strlen(argv[3]), &hex_data[hex_data_len],
+			      sizeof(hex_data) - hex_data_len);
+		if (!len) {
+			shell_error(shell, "HCI command illegal data field\n");
+			return -ENOEXEC;
+		}
+
+		buf = bt_hci_cmd_create(BT_OP(ogf, ocf), len);
+		net_buf_add_mem(buf, hex_data, len);
+	}
+
+	err = bt_hci_cmd_send_sync(BT_OP(ogf, ocf), buf, &rsp);
+	if (err) {
+		shell_error(shell, "HCI command failed (err %d)", err);
+		return err;
+	} else {
+		shell_hexdump(shell, rsp->data, rsp->len);
+		net_buf_unref(rsp);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_HCI */
+
+static int cmd_name(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (argc < 2) {
+		shell_print(shell, "Bluetooth Local Name: %s", bt_get_name());
+		return 0;
+	}
+
+	err = bt_set_name(argv[1]);
+	if (err) {
+		shell_error(shell, "Unable to set name %s (err %d)", argv[1],
+			    err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cmd_id_create(const struct shell *shell, size_t argc, char *argv[])
+{
+	char addr_str[BT_ADDR_LE_STR_LEN];
+	bt_addr_le_t addr;
+	int err;
+
+	if (argc > 1) {
+		err = bt_addr_le_from_str(argv[1], "random", &addr);
+		if (err) {
+			shell_error(shell, "Invalid address");
+		}
+	} else {
+		bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
+	}
+
+	err = bt_id_create(&addr, NULL);
+	if (err < 0) {
+		shell_error(shell, "Creating new ID failed (err %d)", err);
+	}
+
+	bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
+	shell_print(shell, "New identity (%d) created: %s", err, addr_str);
+
+	return 0;
+}
+
+static int cmd_id_reset(const struct shell *shell, size_t argc, char *argv[])
+{
+	char addr_str[BT_ADDR_LE_STR_LEN];
+	bt_addr_le_t addr;
+	uint8_t id;
+	int err;
+
+	if (argc < 2) {
+		shell_error(shell, "Identity identifier not specified");
+		return -ENOEXEC;
+	}
+
+	id = strtol(argv[1], NULL, 10);
+
+	if (argc > 2) {
+		err = bt_addr_le_from_str(argv[2], "random", &addr);
+		if (err) {
+			shell_print(shell, "Invalid address");
+			return err;
+		}
+	} else {
+		bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
+	}
+
+	err = bt_id_reset(id, &addr, NULL);
+	if (err < 0) {
+		shell_print(shell, "Resetting ID %u failed (err %d)", id, err);
+		return err;
+	}
+
+	bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));
+	shell_print(shell, "Identity %u reset: %s", id, addr_str);
+
+	return 0;
+}
+
+static int cmd_id_delete(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t id;
+	int err;
+
+	if (argc < 2) {
+		shell_error(shell, "Identity identifier not specified");
+		return -ENOEXEC;
+	}
+
+	id = strtol(argv[1], NULL, 10);
+
+	err = bt_id_delete(id);
+	if (err < 0) {
+		shell_error(shell, "Deleting ID %u failed (err %d)", id, err);
+		return err;
+	}
+
+	shell_print(shell, "Identity %u deleted", id);
+
+	return 0;
+}
+
+static int cmd_id_show(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
+	size_t i, count = CONFIG_BT_ID_MAX;
+
+	bt_id_get(addrs, &count);
+
+	for (i = 0; i < count; i++) {
+		char addr_str[BT_ADDR_LE_STR_LEN];
+
+		bt_addr_le_to_str(&addrs[i], addr_str, sizeof(addr_str));
+		shell_print(shell, "%s%zu: %s", i == selected_id ? "*" : " ", i,
+		      addr_str);
+	}
+
+	return 0;
+}
+
+static int cmd_id_select(const struct shell *shell, size_t argc, char *argv[])
+{
+	char addr_str[BT_ADDR_LE_STR_LEN];
+	bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
+	size_t count = CONFIG_BT_ID_MAX;
+	uint8_t id;
+
+	id = strtol(argv[1], NULL, 10);
+
+	bt_id_get(addrs, &count);
+	if (count <= id) {
+		shell_error(shell, "Invalid identity");
+		return -ENOEXEC;
+	}
+
+	bt_addr_le_to_str(&addrs[id], addr_str, sizeof(addr_str));
+	shell_print(shell, "Selected identity: %s", addr_str);
+	selected_id = id;
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_OBSERVER)
+static int cmd_active_scan_on(const struct shell *shell, uint32_t options,
+			      uint16_t timeout)
+{
+	int err;
+	struct bt_le_scan_param param = {
+			.type       = BT_LE_SCAN_TYPE_ACTIVE,
+			.options    = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
+			.interval   = BT_GAP_SCAN_FAST_INTERVAL,
+			.window     = BT_GAP_SCAN_FAST_WINDOW,
+			.timeout    = timeout, };
+
+	param.options |= options;
+
+	err = bt_le_scan_start(&param, NULL);
+	if (err) {
+		shell_error(shell, "Bluetooth set active scan failed "
+		      "(err %d)", err);
+		return err;
+	} else {
+		shell_print(shell, "Bluetooth active scan enabled");
+	}
+
+	return 0;
+}
+
+static int cmd_passive_scan_on(const struct shell *shell, uint32_t options,
+			       uint16_t timeout)
+{
+	struct bt_le_scan_param param = {
+			.type       = BT_LE_SCAN_TYPE_PASSIVE,
+			.options    = BT_LE_SCAN_OPT_NONE,
+			.interval   = 0x10,
+			.window     = 0x10,
+			.timeout    = timeout, };
+	int err;
+
+	param.options |= options;
+
+	err = bt_le_scan_start(&param, NULL);
+	if (err) {
+		shell_error(shell, "Bluetooth set passive scan failed "
+			    "(err %d)", err);
+		return err;
+	} else {
+		shell_print(shell, "Bluetooth passive scan enabled");
+	}
+
+	return 0;
+}
+
+static int cmd_scan_off(const struct shell *shell)
+{
+	int err;
+
+	err = bt_le_scan_stop();
+	if (err) {
+		shell_error(shell, "Stopping scanning failed (err %d)", err);
+		return err;
+	} else {
+		shell_print(shell, "Scan successfully stopped");
+	}
+
+	return 0;
+}
+
+static int cmd_scan(const struct shell *shell, size_t argc, char *argv[])
+{
+	const char *action;
+	uint32_t options = 0;
+	uint16_t timeout = 0;
+
+	/* Parse duplicate filtering data */
+	for (size_t argn = 2; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "dups")) {
+			options |= BT_LE_SCAN_OPT_FILTER_DUPLICATE;
+		} else if (!strcmp(arg, "nodups")) {
+			options &= ~BT_LE_SCAN_OPT_FILTER_DUPLICATE;
+		} else if (!strcmp(arg, "wl")) {
+			options |= BT_LE_SCAN_OPT_FILTER_WHITELIST;
+		} else if (!strcmp(arg, "coded")) {
+			options |= BT_LE_SCAN_OPT_CODED;
+		} else if (!strcmp(arg, "no-1m")) {
+			options |= BT_LE_SCAN_OPT_NO_1M;
+		} else if (!strcmp(arg, "timeout")) {
+			if (++argn == argc) {
+				shell_help(shell);
+				return SHELL_CMD_HELP_PRINTED;
+			}
+
+			timeout = strtoul(argv[argn], NULL, 16);
+		} else {
+			shell_help(shell);
+			return SHELL_CMD_HELP_PRINTED;
+		}
+	}
+
+	action = argv[1];
+	if (!strcmp(action, "on")) {
+		return cmd_active_scan_on(shell, options, timeout);
+	} else if (!strcmp(action, "off")) {
+		return cmd_scan_off(shell);
+	} else if (!strcmp(action, "passive")) {
+		return cmd_passive_scan_on(shell, options, timeout);
+	} else {
+		shell_help(shell);
+		return SHELL_CMD_HELP_PRINTED;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_OBSERVER */
+
+#if defined(CONFIG_BT_BROADCASTER)
+static const struct bt_data ad_discov[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+};
+
+static int cmd_advertise(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_adv_param param = {};
+	const struct bt_data *ad;
+	size_t ad_len;
+	int err;
+
+	if (!strcmp(argv[1], "off")) {
+		if (bt_le_adv_stop() < 0) {
+			shell_error(shell, "Failed to stop advertising");
+			return -ENOEXEC;
+		} else {
+			shell_print(shell, "Advertising stopped");
+		}
+
+		return 0;
+	}
+
+	param.id = selected_id;
+	param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
+	param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
+
+	if (!strcmp(argv[1], "on")) {
+		param.options = (BT_LE_ADV_OPT_CONNECTABLE |
+				 BT_LE_ADV_OPT_USE_NAME);
+	} else if (!strcmp(argv[1], "scan")) {
+		param.options = BT_LE_ADV_OPT_USE_NAME;
+	} else if (!strcmp(argv[1], "nconn")) {
+		param.options = 0U;
+	} else {
+		goto fail;
+	}
+
+	ad = ad_discov;
+	ad_len = ARRAY_SIZE(ad_discov);
+
+	for (size_t argn = 2; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "discov")) {
+			/* Default */
+		} else if (!strcmp(arg, "non_discov")) {
+			ad = NULL;
+			ad_len = 0;
+		} else if (!strcmp(arg, "wl")) {
+			param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
+			param.options |= BT_LE_ADV_OPT_FILTER_CONN;
+		} else if (!strcmp(arg, "wl-scan")) {
+			param.options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
+		} else if (!strcmp(arg, "wl-conn")) {
+			param.options |= BT_LE_ADV_OPT_FILTER_CONN;
+		} else if (!strcmp(arg, "identity")) {
+			param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
+		} else if (!strcmp(arg, "no-name")) {
+			param.options &= ~BT_LE_ADV_OPT_USE_NAME;
+		} else if (!strcmp(arg, "one-time")) {
+			param.options |= BT_LE_ADV_OPT_ONE_TIME;
+		} else if (!strcmp(arg, "disable-37")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
+		} else if (!strcmp(arg, "disable-38")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
+		} else if (!strcmp(arg, "disable-39")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
+		} else {
+			goto fail;
+		}
+	}
+
+	err = bt_le_adv_start(&param, ad, ad_len, NULL, 0);
+	if (err < 0) {
+		shell_error(shell, "Failed to start advertising (err %d)",
+			    err);
+		return err;
+	} else {
+		shell_print(shell, "Advertising started");
+	}
+
+	return 0;
+
+fail:
+	shell_help(shell);
+	return -ENOEXEC;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static int cmd_directed_adv(const struct shell *shell,
+			     size_t argc, char *argv[])
+{
+	int err;
+	bt_addr_le_t addr;
+	struct bt_le_adv_param param;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	param = *BT_LE_ADV_CONN_DIR(&addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	for (size_t argn = 3; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "low")) {
+			param.options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
+			param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
+			param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
+		} else if (!strcmp(arg, "identity")) {
+			param.options |= BT_LE_ADV_OPT_USE_IDENTITY;
+		} else if (!strcmp(arg, "dir-rpa")) {
+			param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
+		} else if (!strcmp(arg, "disable-37")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
+		} else if (!strcmp(arg, "disable-38")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
+		} else if (!strcmp(arg, "disable-39")) {
+			param.options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
+		} else {
+			shell_help(shell);
+			return -ENOEXEC;
+		}
+	}
+
+	err = bt_le_adv_start(&param, NULL, 0, NULL, 0);
+	if (err) {
+		shell_error(shell, "Failed to start directed advertising (%d)",
+			    err);
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "Started directed advertising");
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_EXT_ADV)
+static bool adv_param_parse(size_t argc, char *argv[],
+			   struct bt_le_adv_param *param)
+{
+	memset(param, 0, sizeof(struct bt_le_adv_param));
+
+	if (!strcmp(argv[1], "conn-scan")) {
+		param->options |= BT_LE_ADV_OPT_CONNECTABLE;
+		param->options |= BT_LE_ADV_OPT_SCANNABLE;
+	} else if (!strcmp(argv[1], "conn-nscan")) {
+		param->options |= BT_LE_ADV_OPT_CONNECTABLE;
+	} else if (!strcmp(argv[1], "nconn-scan")) {
+		param->options |= BT_LE_ADV_OPT_SCANNABLE;
+	} else if (!strcmp(argv[1], "nconn-nscan")) {
+		/* Acceptable option, nothing to do */
+	} else {
+		return false;
+	}
+
+	for (size_t argn = 2; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "ext-adv")) {
+			param->options |= BT_LE_ADV_OPT_EXT_ADV;
+		} else if (!strcmp(arg, "coded")) {
+			param->options |= BT_LE_ADV_OPT_CODED;
+		} else if (!strcmp(arg, "no-2m")) {
+			param->options |= BT_LE_ADV_OPT_NO_2M;
+		} else if (!strcmp(arg, "anon")) {
+			param->options |= BT_LE_ADV_OPT_ANONYMOUS;
+		} else if (!strcmp(arg, "tx-power")) {
+			param->options |= BT_LE_ADV_OPT_USE_TX_POWER;
+		} else if (!strcmp(arg, "scan-reports")) {
+			param->options |= BT_LE_ADV_OPT_NOTIFY_SCAN_REQ;
+		} else if (!strcmp(arg, "wl")) {
+			param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
+			param->options |= BT_LE_ADV_OPT_FILTER_CONN;
+		} else if (!strcmp(arg, "wl-scan")) {
+			param->options |= BT_LE_ADV_OPT_FILTER_SCAN_REQ;
+		} else if (!strcmp(arg, "wl-conn")) {
+			param->options |= BT_LE_ADV_OPT_FILTER_CONN;
+		} else if (!strcmp(arg, "identity")) {
+			param->options |= BT_LE_ADV_OPT_USE_IDENTITY;
+		} else if (!strcmp(arg, "name")) {
+			param->options |= BT_LE_ADV_OPT_USE_NAME;
+		} else if (!strcmp(arg, "low")) {
+			param->options |= BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY;
+		} else if (!strcmp(arg, "disable-37")) {
+			param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_37;
+		} else if (!strcmp(arg, "disable-38")) {
+			param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_38;
+		} else if (!strcmp(arg, "disable-39")) {
+			param->options |= BT_LE_ADV_OPT_DISABLE_CHAN_39;
+		} else if (!strcmp(arg, "directed")) {
+			static bt_addr_le_t addr;
+
+			if ((argn + 2) >= argc) {
+				return false;
+			}
+
+			if (bt_addr_le_from_str(argv[argn + 1], argv[argn + 2],
+						&addr)) {
+				return false;
+			}
+
+			param->peer = &addr;
+			argn += 2;
+		} else {
+			return false;
+		}
+	}
+
+	param->id = selected_id;
+	param->sid = 0;
+	if (param->peer &&
+	    !(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
+		param->interval_min = 0;
+		param->interval_max = 0;
+	} else {
+		param->interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
+		param->interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
+	}
+
+	return true;
+}
+
+static int cmd_adv_create(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_adv_param param;
+	struct bt_le_ext_adv *adv;
+	uint8_t adv_index;
+	int err;
+
+	if (!adv_param_parse(argc, argv, &param)) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	err = bt_le_ext_adv_create(&param, &adv_callbacks, &adv);
+	if (err) {
+		shell_error(shell, "Failed to create advertiser set (%d)", err);
+		return -ENOEXEC;
+	}
+
+	adv_index = bt_le_ext_adv_get_index(adv);
+	adv_sets[adv_index] = adv;
+
+	shell_print(shell, "Created adv id: %d, adv: %p", adv_index, adv);
+
+	return 0;
+}
+
+static int cmd_adv_param(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	struct bt_le_adv_param param;
+	int err;
+
+	if (!adv_param_parse(argc, argv, &param)) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	err = bt_le_ext_adv_update_param(adv, &param);
+	if (err) {
+		shell_error(shell, "Failed to update advertiser set (%d)", err);
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
+static int cmd_adv_data(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t discov_data = (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR);
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	static uint8_t hex_data[1650];
+	struct bt_data *data;
+	struct bt_data ad[8];
+	struct bt_data sd[8];
+	size_t hex_data_len;
+	size_t ad_len = 0;
+	size_t sd_len = 0;
+	size_t *data_len;
+	int err;
+
+	if (!adv) {
+		return -EINVAL;
+	}
+
+	hex_data_len = 0;
+	data = ad;
+	data_len = &ad_len;
+
+	for (size_t argn = 1; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (strcmp(arg, "scan-response") &&
+		    *data_len == ARRAY_SIZE(ad)) {
+			/* Maximum entries limit reached. */
+			return -ENOEXEC;
+		}
+
+		if (!strcmp(arg, "discov")) {
+			data[*data_len].type = BT_DATA_FLAGS;
+			data[*data_len].data_len = sizeof(discov_data);
+			data[*data_len].data = &discov_data;
+			(*data_len)++;
+		} else if (!strcmp(arg, "name")) {
+			const char *name = bt_get_name();
+
+			data[*data_len].type = BT_DATA_NAME_COMPLETE;
+			data[*data_len].data_len = strlen(name);
+			data[*data_len].data = name;
+			(*data_len)++;
+		} else if (!strcmp(arg, "scan-response")) {
+			if (data == sd) {
+				return -ENOEXEC;
+			}
+
+			data = sd;
+			data_len = &sd_len;
+		} else {
+			size_t len;
+
+			len = hex2bin(arg, strlen(arg), &hex_data[hex_data_len],
+				      sizeof(hex_data) - hex_data_len);
+
+			if (!len || (len - 1) != (hex_data[hex_data_len])) {
+				return -ENOEXEC;
+			}
+
+			data[*data_len].type = hex_data[hex_data_len + 1];
+			data[*data_len].data_len = hex_data[hex_data_len];
+			data[*data_len].data = &hex_data[hex_data_len + 2];
+			(*data_len)++;
+			hex_data_len += len;
+		}
+	}
+
+	err = bt_le_ext_adv_set_data(adv, ad_len > 0 ? ad : NULL, ad_len,
+					  sd_len > 0 ? sd : NULL, sd_len);
+	if (err) {
+		shell_print(shell, "Failed to set advertising set data (%d)",
+			    err);
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
+static int cmd_adv_start(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	struct bt_le_ext_adv_start_param param;
+	uint8_t num_events = 0;
+	int32_t timeout = 0;
+	int err;
+
+	if (!adv) {
+		shell_print(shell, "Advertiser[%d] not created", selected_adv);
+		return -EINVAL;
+	}
+
+	for (size_t argn = 1; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "timeout")) {
+			if (++argn == argc) {
+				goto fail_show_help;
+			}
+
+			timeout = strtoul(argv[argn], NULL, 16);
+		}
+
+		if (!strcmp(arg, "num-events")) {
+			if (++argn == argc) {
+				goto fail_show_help;
+			}
+
+			num_events = strtoul(argv[argn], NULL, 16);
+		}
+	}
+
+	param.timeout = timeout;
+	param.num_events = num_events;
+
+	err = bt_le_ext_adv_start(adv, &param);
+	if (err) {
+		shell_print(shell, "Failed to start advertising set (%d)", err);
+		return -ENOEXEC;
+	}
+
+	shell_print(shell, "Advertiser[%d] %p set started", selected_adv, adv);
+	return 0;
+
+fail_show_help:
+	shell_help(shell);
+	return -ENOEXEC;
+}
+
+static int cmd_adv_stop(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	int err;
+
+	if (!adv) {
+		shell_print(shell, "Advertiser[%d] not created", selected_adv);
+		return -EINVAL;
+	}
+
+	err = bt_le_ext_adv_stop(adv);
+	if (err) {
+		shell_print(shell, "Failed to stop advertising set (%d)", err);
+		return -ENOEXEC;
+	}
+
+	shell_print(shell, "Advertiser set stopped");
+	return 0;
+}
+
+static int cmd_adv_delete(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	int err;
+
+	if (!adv) {
+		shell_print(shell, "Advertiser[%d] not created", selected_adv);
+		return -EINVAL;
+	}
+
+	err = bt_le_ext_adv_delete(adv);
+	if (err) {
+		shell_error(ctx_shell, "Failed to delete advertiser set");
+		return err;
+	}
+
+	adv_sets[selected_adv] = NULL;
+	return 0;
+}
+
+static int cmd_adv_select(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc == 2) {
+		uint8_t id = strtol(argv[1], NULL, 10);
+
+		if (!(id < ARRAY_SIZE(adv_sets))) {
+			return -EINVAL;
+		}
+
+		selected_adv = id;
+		return 0;
+	}
+
+	for (int i = 0; i < ARRAY_SIZE(adv_sets); i++) {
+		if (adv_sets[i]) {
+			shell_print(shell, "Advertiser[%d] %p", i, adv_sets[i]);
+		}
+	}
+
+	return -ENOEXEC;
+}
+
+static int cmd_adv_info(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	struct bt_le_ext_adv_info info;
+	int err;
+
+	if (!adv) {
+		return -EINVAL;
+	}
+
+	err = bt_le_ext_adv_get_info(adv, &info);
+	if (err) {
+		shell_error(shell, "OOB data failed");
+		return err;
+	}
+
+	shell_print(shell, "Advertiser[%d] %p", selected_adv, adv);
+	shell_print(shell, "Id: %d, TX power: %d dBm", info.id, info.tx_power);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_PERIPHERAL)
+static int cmd_adv_oob(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	int err;
+
+	if (!adv) {
+		return -EINVAL;
+	}
+
+	err = bt_le_ext_adv_oob_get_local(adv, &oob_local);
+	if (err) {
+		shell_error(shell, "OOB data failed");
+		return err;
+	}
+
+	print_le_oob(shell, &oob_local);
+
+	return 0;
+}
+#endif /* CONFIG_BT_PERIPHERAL */
+
+#if defined(CONFIG_BT_PER_ADV)
+static int cmd_per_adv(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+
+	if (!adv) {
+		shell_error(shell, "No extended advertisement set selected");
+		return -EINVAL;
+	}
+
+	if (!strcmp(argv[1], "off")) {
+		if (bt_le_per_adv_stop(adv) < 0) {
+			shell_error(shell,
+				    "Failed to stop periodic advertising");
+		} else {
+			shell_print(shell, "Periodic advertising stopped");
+		}
+	} else if (!strcmp(argv[1], "on")) {
+		if (bt_le_per_adv_start(adv) < 0) {
+			shell_error(shell,
+				    "Failed to start periodic advertising");
+		} else {
+			shell_print(shell, "Periodic advertising started");
+		}
+	} else {
+		shell_error(shell, "Invalid argument: %s", argv[1]);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cmd_per_adv_param(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	struct bt_le_per_adv_param param;
+	int err;
+
+	if (!adv) {
+		shell_error(shell, "No extended advertisement set selected");
+		return -EINVAL;
+	}
+
+	if (argc > 1) {
+		param.interval_min = strtol(argv[1], NULL, 16);
+	} else {
+		param.interval_min = BT_GAP_ADV_SLOW_INT_MIN;
+	}
+
+	if (argc > 2) {
+		param.interval_max = strtol(argv[2], NULL, 16);
+	} else {
+		param.interval_max = param.interval_min * 1.2;
+
+	}
+
+	if (param.interval_min > param.interval_max) {
+		shell_error(shell,
+			    "Min interval shall be less than max interval");
+		return -EINVAL;
+	}
+
+	if (argc > 3 && !strcmp(argv[3], "tx-power")) {
+		param.options = BT_LE_ADV_OPT_USE_TX_POWER;
+	} else {
+		param.options = 0;
+	}
+
+	err = bt_le_per_adv_set_param(adv, &param);
+	if (err) {
+		shell_error(shell, "Failed to set periodic advertising "
+			    "parameters (%d)", err);
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
+static int cmd_per_adv_data(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	struct bt_le_ext_adv *adv = adv_sets[selected_adv];
+	static struct bt_data ad;
+	static uint8_t hex_data[256];
+	uint8_t ad_len = 0;
+	int err;
+
+	if (!adv) {
+		shell_error(shell, "No extended advertisement set selected");
+		return -EINVAL;
+	}
+
+	ad_len = hex2bin(argv[1], strlen(argv[1]), hex_data, sizeof(hex_data));
+
+	if (!ad_len) {
+		shell_error(shell, "Could not parse adv data");
+		return -ENOEXEC;
+	}
+
+	ad.data_len = hex_data[0];
+	ad.type = hex_data[1];
+	ad.data = &hex_data[2];
+
+	err = bt_le_per_adv_set_data(adv, &ad, ad_len);
+	if (err) {
+		shell_error(shell,
+			    "Failed to set periodic advertising data (%d)",
+			    err);
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_PER_ADV */
+#endif /* CONFIG_BT_EXT_ADV */
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+static struct bt_le_per_adv_sync *per_adv_syncs[CONFIG_BT_PER_ADV_SYNC_MAX];
+
+static void per_adv_sync_sync_cb(struct bt_le_per_adv_sync *sync,
+				 struct bt_le_per_adv_sync_synced_info *info)
+{
+	char le_addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
+	shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
+		    "Interval 0x%04x (%u ms), PHY %s",
+		    bt_le_per_adv_sync_get_index(sync), le_addr,
+		    info->interval, info->interval * 5 / 4, phy2str(info->phy));
+}
+
+static void per_adv_sync_terminated_cb(
+	struct bt_le_per_adv_sync *sync,
+	const struct bt_le_per_adv_sync_term_info *info)
+{
+	char le_addr[BT_ADDR_LE_STR_LEN];
+
+	for (int i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
+		if (per_adv_syncs[i] == sync) {
+			per_adv_syncs[i] = NULL;
+			break;
+		}
+	}
+
+	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
+	shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated",
+		    bt_le_per_adv_sync_get_index(sync), le_addr);
+}
+
+static void per_adv_sync_recv_cb(
+	struct bt_le_per_adv_sync *sync,
+	const struct bt_le_per_adv_sync_recv_info *info,
+	struct net_buf_simple *buf)
+{
+	char le_addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
+	shell_print(ctx_shell, "PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
+		    "RSSI %i, CTE %u, data length %u",
+		    bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
+		    info->rssi, info->cte_type, buf->len);
+}
+
+static struct bt_le_per_adv_sync_cb per_adv_sync_cb = {
+	.synced = per_adv_sync_sync_cb,
+	.term = per_adv_sync_terminated_cb,
+	.recv = per_adv_sync_recv_cb
+};
+
+static int cmd_per_adv_sync_create(const struct shell *shell, size_t argc,
+				   char *argv[])
+{
+	int err;
+	struct bt_le_per_adv_sync_param create_params = { 0 };
+	uint32_t options = 0;
+	struct bt_le_per_adv_sync **free_per_adv_sync = NULL;
+	int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(per_adv_syncs); i++) {
+		if (per_adv_syncs[i] == NULL) {
+			free_per_adv_sync = &per_adv_syncs[i];
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(per_adv_syncs)) {
+		shell_error(shell, "Cannot create more per adv syncs");
+		return -ENOEXEC;
+	}
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &create_params.addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return -ENOEXEC;
+	}
+
+	/* Default values */
+	create_params.timeout = 1000; /* 10 seconds */
+	create_params.skip = 10;
+
+	create_params.sid = strtol(argv[3], NULL, 16);
+
+	for (int i = 4; i < argc; i++) {
+		if (!strcmp(argv[i], "aoa")) {
+			options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOA;
+		} else if (!strcmp(argv[i], "aod_1us")) {
+			options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_1US;
+		} else if (!strcmp(argv[i], "aod_2us")) {
+			options |= BT_LE_PER_ADV_SYNC_OPT_DONT_SYNC_AOD_2US;
+		} else if (!strcmp(argv[i], "only_cte")) {
+			options |=
+				BT_LE_PER_ADV_SYNC_OPT_SYNC_ONLY_CONST_TONE_EXT;
+		} else if (!strcmp(argv[i], "timeout")) {
+			if (++i == argc) {
+				shell_help(shell);
+				return SHELL_CMD_HELP_PRINTED;
+			}
+
+			create_params.timeout = strtoul(argv[i], NULL, 16);
+		} else if (!strcmp(argv[i], "skip")) {
+			if (++i == argc) {
+				shell_help(shell);
+				return SHELL_CMD_HELP_PRINTED;
+			}
+
+			create_params.skip = strtoul(argv[i], NULL, 16);
+		} else {
+			shell_help(shell);
+			return SHELL_CMD_HELP_PRINTED;
+		}
+
+		/* TODO: add support to parse using the per adv list */
+	}
+
+	create_params.options = options;
+
+	bt_le_per_adv_sync_cb_register(&per_adv_sync_cb);
+
+	err = bt_le_per_adv_sync_create(&create_params, free_per_adv_sync);
+	if (err) {
+		shell_error(shell, "Per adv sync failed (%d)", err);
+	} else {
+		shell_print(shell, "Per adv sync pending");
+	}
+
+	return 0;
+}
+
+static int cmd_per_adv_sync_delete(const struct shell *shell, size_t argc,
+				   char *argv[])
+{
+	int err;
+	int index = 0;
+	struct bt_le_per_adv_sync **per_adv_sync = NULL;
+
+	if (argc > 1) {
+		index = strtol(argv[1], NULL, 10);
+	}
+
+	per_adv_sync = &per_adv_syncs[index];
+
+	if (!per_adv_sync) {
+		return -EINVAL;
+	}
+
+	err = bt_le_per_adv_sync_delete(*per_adv_sync);
+
+	if (err) {
+		shell_error(shell, "Per adv sync delete failed (%d)", err);
+	} else {
+		shell_print(shell, "Per adv sync deleted");
+		*per_adv_sync = NULL;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_PER_ADV_SYNC */
+
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+static int cmd_connect_le(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+	bt_addr_le_t addr;
+	struct bt_conn *conn;
+	uint32_t options = 0;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+#if defined(CONFIG_BT_EXT_ADV)
+	for (size_t argn = 3; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "coded")) {
+			options |= BT_CONN_LE_OPT_CODED;
+		} else if (!strcmp(arg, "no-1m")) {
+			options |= BT_CONN_LE_OPT_NO_1M;
+		} else {
+			shell_help(shell);
+			return SHELL_CMD_HELP_PRINTED;
+		}
+	}
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+	struct bt_conn_le_create_param *create_params =
+		BT_CONN_LE_CREATE_PARAM(options,
+					BT_GAP_SCAN_FAST_INTERVAL,
+					BT_GAP_SCAN_FAST_INTERVAL);
+
+	err = bt_conn_le_create(&addr, create_params, BT_LE_CONN_PARAM_DEFAULT,
+				&conn);
+	if (err) {
+		shell_error(shell, "Connection failed (%d)", err);
+		return -ENOEXEC;
+	} else {
+
+		shell_print(shell, "Connection pending");
+
+		/* unref connection obj in advance as app user */
+		bt_conn_unref(conn);
+	}
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_WHITELIST)
+static int cmd_auto_conn(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_addr_le_t addr;
+	int err;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	if (argc < 4) {
+		return bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
+	} else if (!strcmp(argv[3], "on")) {
+		return bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
+	} else if (!strcmp(argv[3], "off")) {
+		return bt_le_set_auto_conn(&addr, NULL);
+	} else {
+		shell_help(shell);
+		return SHELL_CMD_HELP_PRINTED;
+	}
+
+	return 0;
+}
+#endif /* !defined(CONFIG_BT_WHITELIST) */
+#endif /* CONFIG_BT_CENTRAL */
+
+static int cmd_disconnect(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_conn *conn;
+	int err;
+
+	if (default_conn && argc < 3) {
+		conn = bt_conn_ref(default_conn);
+	} else {
+		bt_addr_le_t addr;
+
+		if (argc < 3) {
+			shell_help(shell);
+			return SHELL_CMD_HELP_PRINTED;
+		}
+
+		err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+		if (err) {
+			shell_error(shell, "Invalid peer address (err %d)",
+				    err);
+			return err;
+		}
+
+		conn = bt_conn_lookup_addr_le(selected_id, &addr);
+	}
+
+	if (!conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+	if (err) {
+		shell_error(shell, "Disconnection failed (err %d)", err);
+		return err;
+	}
+
+	bt_conn_unref(conn);
+
+	return 0;
+}
+
+static int cmd_select(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_conn *conn;
+	bt_addr_le_t addr;
+	int err;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	conn = bt_conn_lookup_addr_le(selected_id, &addr);
+	if (!conn) {
+		shell_error(shell, "No matching connection found");
+		return -ENOEXEC;
+	}
+
+	if (default_conn) {
+		bt_conn_unref(default_conn);
+	}
+
+	default_conn = conn;
+
+	return 0;
+}
+
+static const char *get_conn_type_str(uint8_t type)
+{
+	switch (type) {
+	case BT_CONN_TYPE_LE: return "LE";
+	case BT_CONN_TYPE_BR: return "BR/EDR";
+	case BT_CONN_TYPE_SCO: return "SCO";
+	default: return "Invalid";
+	}
+}
+
+static const char *get_conn_role_str(uint8_t role)
+{
+	switch (role) {
+	case BT_CONN_ROLE_MASTER: return "master";
+	case BT_CONN_ROLE_SLAVE: return "slave";
+	default: return "Invalid";
+	}
+}
+
+static void print_le_addr(const char *desc, const bt_addr_le_t *addr)
+{
+	char addr_str[BT_ADDR_LE_STR_LEN];
+
+	const char *addr_desc = bt_addr_le_is_identity(addr) ? "identity" :
+				bt_addr_le_is_rpa(addr) ? "resolvable" :
+				"non-resolvable";
+
+	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
+
+	shell_print(ctx_shell, "%s address: %s (%s)", desc, addr_str,
+		    addr_desc);
+}
+
+static int cmd_info(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_conn *conn = NULL;
+	struct bt_conn_info info;
+	bt_addr_le_t addr;
+	int err;
+
+	switch (argc) {
+	case 1:
+		if (default_conn) {
+			conn = bt_conn_ref(default_conn);
+		}
+		break;
+	case 2:
+		addr.type = BT_ADDR_LE_PUBLIC;
+		err = bt_addr_from_str(argv[1], &addr.a);
+		if (err) {
+			shell_error(shell, "Invalid peer address (err %d)",
+				    err);
+			return err;
+		}
+		conn = bt_conn_lookup_addr_le(selected_id, &addr);
+		break;
+	case 3:
+		err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+
+		if (err) {
+			shell_error(shell, "Invalid peer address (err %d)",
+				    err);
+			return err;
+		}
+		conn = bt_conn_lookup_addr_le(selected_id, &addr);
+		break;
+	}
+
+	if (!conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	err = bt_conn_get_info(conn, &info);
+	if (err) {
+		shell_print(ctx_shell, "Failed to get info");
+		goto done;
+	}
+
+	shell_print(ctx_shell, "Type: %s, Role: %s, Id: %u",
+		    get_conn_type_str(info.type),
+		    get_conn_role_str(info.role),
+		    info.id);
+
+	if (info.type == BT_CONN_TYPE_LE) {
+		print_le_addr("Remote", info.le.dst);
+		print_le_addr("Local", info.le.src);
+		print_le_addr("Remote on-air", info.le.remote);
+		print_le_addr("Local on-air", info.le.local);
+
+		shell_print(ctx_shell, "Interval: 0x%04x (%u ms)",
+			    info.le.interval, info.le.interval * 5 / 4);
+		shell_print(ctx_shell, "Latency: 0x%04x (%u ms)",
+			    info.le.latency, info.le.latency * 5 / 4);
+		shell_print(ctx_shell, "Supervision timeout: 0x%04x (%d ms)",
+			    info.le.timeout, info.le.timeout * 10);
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+		shell_print(ctx_shell, "LE PHY: TX PHY %s, RX PHY %s",
+			    phy2str(info.le.phy->tx_phy),
+			    phy2str(info.le.phy->rx_phy));
+#endif
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+		shell_print(ctx_shell, "LE data len: TX (len: %d time: %d)"
+			    " RX (len: %d time: %d)",
+			    info.le.data_len->tx_max_len,
+			    info.le.data_len->tx_max_time,
+			    info.le.data_len->rx_max_len,
+			    info.le.data_len->rx_max_time);
+#endif
+	}
+
+#if defined(CONFIG_BT_BREDR)
+	if (info.type == BT_CONN_TYPE_BR) {
+		char addr_str[BT_ADDR_STR_LEN];
+
+		bt_addr_to_str(info.br.dst, addr_str, sizeof(addr_str));
+		shell_print(ctx_shell, "Peer address %s", addr_str);
+	}
+#endif /* defined(CONFIG_BT_BREDR) */
+
+done:
+	bt_conn_unref(conn);
+
+	return err;
+}
+
+static int cmd_conn_update(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_le_conn_param param;
+	int err;
+
+	param.interval_min = strtoul(argv[1], NULL, 16);
+	param.interval_max = strtoul(argv[2], NULL, 16);
+	param.latency = strtoul(argv[3], NULL, 16);
+	param.timeout = strtoul(argv[4], NULL, 16);
+
+	err = bt_conn_le_param_update(default_conn, &param);
+	if (err) {
+		shell_error(shell, "conn update failed (err %d).", err);
+	} else {
+		shell_print(shell, "conn update initiated.");
+	}
+
+	return err;
+}
+
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+static uint16_t tx_time_calc(uint8_t phy, uint16_t max_len)
+{
+	/* Access address + header + payload + MIC + CRC */
+	uint16_t total_len = 4 + 2 + max_len + 4 + 3;
+
+	switch (phy) {
+	case BT_GAP_LE_PHY_1M:
+		/* 1 byte preamble, 8 us per byte */
+		return 8 * (1 + total_len);
+	case BT_GAP_LE_PHY_2M:
+		/* 2 byte preamble, 4 us per byte */
+		return 4 * (2 + total_len);
+	case BT_GAP_LE_PHY_CODED:
+		/* S8: Preamble + CI + TERM1 + 64 us per byte + TERM2 */
+		return 80 + 16 + 24 + 64 * (total_len) + 24;
+	default:
+		return 0;
+	}
+}
+
+static int cmd_conn_data_len_update(const struct shell *shell, size_t argc,
+				    char *argv[])
+{
+	struct bt_conn_le_data_len_param param;
+	int err;
+
+	param.tx_max_len = strtoul(argv[1], NULL, 10);
+
+	if (argc > 2) {
+		param.tx_max_time = strtoul(argv[2], NULL, 10);
+	} else {
+		/* Assume 1M if not able to retrieve PHY */
+		uint8_t phy = BT_GAP_LE_PHY_1M;
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+		struct bt_conn_info info;
+
+		err = bt_conn_get_info(default_conn, &info);
+		if (!err) {
+			phy = info.le.phy->tx_phy;
+		}
+#endif
+		param.tx_max_time = tx_time_calc(phy, param.tx_max_len);
+		shell_print(shell, "Calculated tx time: %d", param.tx_max_time);
+	}
+
+
+
+	err = bt_conn_le_data_len_update(default_conn, &param);
+	if (err) {
+		shell_error(shell, "data len update failed (err %d).", err);
+	} else {
+		shell_print(shell, "data len update initiated.");
+	}
+
+	return err;
+}
+#endif
+
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+static int cmd_conn_phy_update(const struct shell *shell, size_t argc,
+			       char *argv[])
+{
+	struct bt_conn_le_phy_param param;
+	int err;
+
+	param.pref_tx_phy = strtoul(argv[1], NULL, 16);
+	param.pref_rx_phy = param.pref_tx_phy;
+	param.options = BT_CONN_LE_PHY_OPT_NONE;
+
+	for (size_t argn = 2; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "s2")) {
+			param.options |= BT_CONN_LE_PHY_OPT_CODED_S2;
+		} else if (!strcmp(arg, "s8")) {
+			param.options |= BT_CONN_LE_PHY_OPT_CODED_S8;
+		} else {
+			param.pref_rx_phy = strtoul(arg, NULL, 16);
+		}
+	}
+
+	err = bt_conn_le_phy_update(default_conn, &param);
+	if (err) {
+		shell_error(shell, "PHY update failed (err %d).", err);
+	} else {
+		shell_print(shell, "PHY update initiated.");
+	}
+
+	return err;
+}
+#endif
+
+#if defined(CONFIG_BT_CENTRAL)
+static int cmd_chan_map(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t chan_map[5] = {};
+	int err;
+
+	if (hex2bin(argv[1], strlen(argv[1]), chan_map, 5) == 0) {
+		shell_error(shell, "Invalid channel map");
+		return -ENOEXEC;
+	}
+	sys_mem_swap(chan_map, 5);
+
+	err = bt_le_set_chan_map(chan_map);
+	if (err) {
+		shell_error(shell, "Failed to set channel map (err %d)", err);
+	} else {
+		shell_print(shell, "Channel map set");
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_CENTRAL */
+
+static int cmd_oob(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_le_oob_get_local(selected_id, &oob_local);
+	if (err) {
+		shell_error(shell, "OOB data failed");
+		return err;
+	}
+
+	print_le_oob(shell, &oob_local);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+static int cmd_oob_remote(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	int err;
+	bt_addr_le_t addr;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	bt_addr_le_copy(&oob_remote.addr, &addr);
+
+	if (argc == 5) {
+		hex2bin(argv[3], strlen(argv[3]), oob_remote.le_sc_data.r,
+			sizeof(oob_remote.le_sc_data.r));
+		hex2bin(argv[4], strlen(argv[4]), oob_remote.le_sc_data.c,
+			sizeof(oob_remote.le_sc_data.c));
+		bt_set_oob_data_flag(true);
+	} else {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
+static int cmd_oob_clear(const struct shell *shell, size_t argc, char *argv[])
+{
+	memset(&oob_remote, 0, sizeof(oob_remote));
+	bt_set_oob_data_flag(false);
+
+	return 0;
+}
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
+
+static int cmd_clear(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_addr_le_t addr;
+	int err;
+
+	if (strcmp(argv[1], "all") == 0) {
+		err = bt_unpair(selected_id, NULL);
+		if (err) {
+			shell_error(shell, "Failed to clear pairings (err %d)",
+			      err);
+			return err;
+		} else {
+			shell_print(shell, "Pairings successfully cleared");
+		}
+
+		return 0;
+	}
+
+	if (argc < 3) {
+#if defined(CONFIG_BT_BREDR)
+		addr.type = BT_ADDR_LE_PUBLIC;
+		err = bt_addr_from_str(argv[1], &addr.a);
+#else
+		shell_print(shell, "Both address and address type needed");
+		return -ENOEXEC;
+#endif
+	} else {
+		err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	}
+
+	if (err) {
+		shell_print(shell, "Invalid address");
+		return err;
+	}
+
+	err = bt_unpair(selected_id, &addr);
+	if (err) {
+		shell_error(shell, "Failed to clear pairing (err %d)", err);
+	} else {
+		shell_print(shell, "Pairing successfully cleared");
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_CONN */
+
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+static int cmd_security(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err, sec;
+	struct bt_conn_info info;
+
+	if (!default_conn || (bt_conn_get_info(default_conn, &info) < 0)) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	sec = *argv[1] - '0';
+
+	if ((info.type == BT_CONN_TYPE_BR &&
+	    (sec < BT_SECURITY_L0 || sec > BT_SECURITY_L3))) {
+		shell_error(shell, "Invalid BR/EDR security level (%d)", sec);
+		return -ENOEXEC;
+	}
+
+	if ((info.type == BT_CONN_TYPE_LE &&
+	    (sec < BT_SECURITY_L1 || sec > BT_SECURITY_L4))) {
+		shell_error(shell, "Invalid LE security level (%d)", sec);
+		return -ENOEXEC;
+	}
+
+	if (argc > 2) {
+		if (!strcmp(argv[2], "force-pair")) {
+			sec |= BT_SECURITY_FORCE_PAIR;
+		} else {
+			shell_help(shell);
+			return -ENOEXEC;
+		}
+	}
+
+	err = bt_conn_set_security(default_conn, sec);
+	if (err) {
+		shell_error(shell, "Setting security failed (err %d)", err);
+	}
+
+	return err;
+}
+
+static int cmd_bondable(const struct shell *shell, size_t argc, char *argv[])
+{
+	const char *bondable;
+
+	bondable = argv[1];
+	if (!strcmp(bondable, "on")) {
+		bt_set_bondable(true);
+	} else if (!strcmp(bondable, "off")) {
+		bt_set_bondable(false);
+	} else {
+		shell_help(shell);
+		return SHELL_CMD_HELP_PRINTED;
+	}
+
+	return 0;
+}
+
+static void bond_info(const struct bt_bond_info *info, void *user_data)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	int *bond_count = user_data;
+
+	bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
+	shell_print(ctx_shell, "Remote Identity: %s", addr);
+	(*bond_count)++;
+}
+
+static int cmd_bonds(const struct shell *shell, size_t argc, char *argv[])
+{
+	int bond_count = 0;
+
+	shell_print(shell, "Bonded devices:");
+	bt_foreach_bond(selected_id, bond_info, &bond_count);
+	shell_print(shell, "Total %d", bond_count);
+
+	return 0;
+}
+
+static void connection_info(struct bt_conn *conn, void *user_data)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	int *conn_count = user_data;
+
+	conn_addr_str(conn, addr, sizeof(addr));
+	shell_print(ctx_shell, "Remote Identity: %s", addr);
+	(*conn_count)++;
+}
+
+static int cmd_connections(const struct shell *shell, size_t argc, char *argv[])
+{
+	int conn_count = 0;
+
+	shell_print(shell, "Connected devices:");
+	bt_conn_foreach(BT_CONN_TYPE_ALL, connection_info, &conn_count);
+	shell_print(shell, "Total %d", conn_count);
+
+	return 0;
+}
+
+static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	char passkey_str[7];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	snprintk(passkey_str, 7, "%06u", passkey);
+
+	shell_print(ctx_shell, "Passkey for %s: %s", addr, passkey_str);
+}
+
+static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	char passkey_str[7];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	snprintk(passkey_str, 7, "%06u", passkey);
+
+	shell_print(ctx_shell, "Confirm passkey for %s: %s", addr, passkey_str);
+}
+
+static void auth_passkey_entry(struct bt_conn *conn)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	shell_print(ctx_shell, "Enter passkey for %s", addr);
+}
+
+static void auth_cancel(struct bt_conn *conn)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	conn_addr_str(conn, addr, sizeof(addr));
+
+	shell_print(ctx_shell, "Pairing cancelled: %s", addr);
+
+	/* clear connection reference for sec mode 3 pairing */
+	if (pairing_conn) {
+		bt_conn_unref(pairing_conn);
+		pairing_conn = NULL;
+	}
+}
+
+static void auth_pairing_confirm(struct bt_conn *conn)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	shell_print(ctx_shell, "Confirm pairing for %s", addr);
+}
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+static const char *oob_config_str(int oob_config)
+{
+	switch (oob_config) {
+	case BT_CONN_OOB_LOCAL_ONLY:
+		return "Local";
+	case BT_CONN_OOB_REMOTE_ONLY:
+		return "Remote";
+	case BT_CONN_OOB_BOTH_PEERS:
+		return "Local and Remote";
+	case BT_CONN_OOB_NO_DATA:
+	default:
+		return "no";
+	}
+}
+#endif /* !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY) */
+
+static void auth_pairing_oob_data_request(struct bt_conn *conn,
+					  struct bt_conn_oob_info *oob_info)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+	struct bt_conn_info info;
+	int err;
+
+	err = bt_conn_get_info(conn, &info);
+	if (err) {
+		return;
+	}
+
+#if !defined(CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY)
+	if (oob_info->type == BT_CONN_OOB_LE_SC) {
+		struct bt_le_oob_sc_data *oobd_local =
+			oob_info->lesc.oob_config != BT_CONN_OOB_REMOTE_ONLY
+						  ? &oob_local.le_sc_data
+						  : NULL;
+		struct bt_le_oob_sc_data *oobd_remote =
+			oob_info->lesc.oob_config != BT_CONN_OOB_LOCAL_ONLY
+						  ? &oob_remote.le_sc_data
+						  : NULL;
+
+		if (oobd_remote &&
+		    bt_addr_le_cmp(info.le.remote, &oob_remote.addr)) {
+			bt_addr_le_to_str(info.le.remote, addr, sizeof(addr));
+			shell_print(ctx_shell,
+				    "No OOB data available for remote %s",
+				    addr);
+			bt_conn_auth_cancel(conn);
+			return;
+		}
+
+		if (oobd_local &&
+		    bt_addr_le_cmp(info.le.local, &oob_local.addr)) {
+			bt_addr_le_to_str(info.le.local, addr, sizeof(addr));
+			shell_print(ctx_shell,
+				    "No OOB data available for local %s",
+				    addr);
+			bt_conn_auth_cancel(conn);
+			return;
+		}
+
+		bt_le_oob_set_sc_data(conn, oobd_local, oobd_remote);
+
+		bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
+		shell_print(ctx_shell, "Set %s OOB SC data for %s, ",
+			    oob_config_str(oob_info->lesc.oob_config), addr);
+		return;
+	}
+#endif /* CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
+
+	bt_addr_le_to_str(info.le.dst, addr, sizeof(addr));
+	shell_print(ctx_shell, "Legacy OOB TK requested from remote %s", addr);
+}
+
+static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	shell_print(ctx_shell, "%s with %s", bonded ? "Bonded" : "Paired",
+		    addr);
+}
+
+static void auth_pairing_failed(struct bt_conn *conn,
+				enum bt_security_err reason)
+{
+	char addr[BT_ADDR_LE_STR_LEN];
+
+	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+	shell_print(ctx_shell, "Pairing failed with %s reason %d", addr,
+		    reason);
+}
+
+#if defined(CONFIG_BT_BREDR)
+static void auth_pincode_entry(struct bt_conn *conn, bool highsec)
+{
+	char addr[BT_ADDR_STR_LEN];
+	struct bt_conn_info info;
+
+	if (bt_conn_get_info(conn, &info) < 0) {
+		return;
+	}
+
+	if (info.type != BT_CONN_TYPE_BR) {
+		return;
+	}
+
+	bt_addr_to_str(info.br.dst, addr, sizeof(addr));
+
+	if (highsec) {
+		shell_print(ctx_shell, "Enter 16 digits wide PIN code for %s",
+			    addr);
+	} else {
+		shell_print(ctx_shell, "Enter PIN code for %s", addr);
+	}
+
+	/*
+	 * Save connection info since in security mode 3 (link level enforced
+	 * security) PIN request callback is called before connected callback
+	 */
+	if (!default_conn && !pairing_conn) {
+		pairing_conn = bt_conn_ref(conn);
+	}
+}
+#endif
+
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+enum bt_security_err pairing_accept(
+	struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat)
+{
+	shell_print(ctx_shell, "Remote pairing features: "
+			       "IO: 0x%02x, OOB: %d, AUTH: 0x%02x, Key: %d, "
+			       "Init Kdist: 0x%02x, Resp Kdist: 0x%02x",
+			       feat->io_capability, feat->oob_data_flag,
+			       feat->auth_req, feat->max_enc_key_size,
+			       feat->init_key_dist, feat->resp_key_dist);
+
+	return BT_SECURITY_ERR_SUCCESS;
+}
+#endif /* CONFIG_BT_SMP_APP_PAIRING_ACCEPT */
+
+void bond_deleted(uint8_t id, const bt_addr_le_t *peer)
+{
+	char addr[BT_ADDR_STR_LEN];
+
+	bt_addr_le_to_str(peer, addr, sizeof(addr));
+	shell_print(ctx_shell, "Bond deleted for %s, id %u", addr, id);
+}
+
+static struct bt_conn_auth_cb auth_cb_display = {
+	.passkey_display = auth_passkey_display,
+	.passkey_entry = NULL,
+	.passkey_confirm = NULL,
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = auth_pincode_entry,
+#endif
+	.oob_data_request = NULL,
+	.cancel = auth_cancel,
+	.pairing_confirm = auth_pairing_confirm,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+static struct bt_conn_auth_cb auth_cb_display_yes_no = {
+	.passkey_display = auth_passkey_display,
+	.passkey_entry = NULL,
+	.passkey_confirm = auth_passkey_confirm,
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = auth_pincode_entry,
+#endif
+	.oob_data_request = NULL,
+	.cancel = auth_cancel,
+	.pairing_confirm = auth_pairing_confirm,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+static struct bt_conn_auth_cb auth_cb_input = {
+	.passkey_display = NULL,
+	.passkey_entry = auth_passkey_entry,
+	.passkey_confirm = NULL,
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = auth_pincode_entry,
+#endif
+	.oob_data_request = NULL,
+	.cancel = auth_cancel,
+	.pairing_confirm = auth_pairing_confirm,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+static struct bt_conn_auth_cb auth_cb_confirm = {
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = auth_pincode_entry,
+#endif
+	.oob_data_request = NULL,
+	.cancel = auth_cancel,
+	.pairing_confirm = auth_pairing_confirm,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+static struct bt_conn_auth_cb auth_cb_all = {
+	.passkey_display = auth_passkey_display,
+	.passkey_entry = auth_passkey_entry,
+	.passkey_confirm = auth_passkey_confirm,
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = auth_pincode_entry,
+#endif
+	.oob_data_request = auth_pairing_oob_data_request,
+	.cancel = auth_cancel,
+	.pairing_confirm = auth_pairing_confirm,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+static struct bt_conn_auth_cb auth_cb_oob = {
+	.passkey_display = NULL,
+	.passkey_entry = NULL,
+	.passkey_confirm = NULL,
+#if defined(CONFIG_BT_BREDR)
+	.pincode_entry = NULL,
+#endif
+	.oob_data_request = auth_pairing_oob_data_request,
+	.cancel = auth_cancel,
+	.pairing_confirm = NULL,
+	.pairing_failed = auth_pairing_failed,
+	.pairing_complete = auth_pairing_complete,
+#if defined(CONFIG_BT_SMP_APP_PAIRING_ACCEPT)
+	.pairing_accept = pairing_accept,
+#endif
+	.bond_deleted = bond_deleted,
+};
+
+
+static int cmd_auth(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (!strcmp(argv[1], "all")) {
+		err = bt_conn_auth_cb_register(&auth_cb_all);
+	} else if (!strcmp(argv[1], "input")) {
+		err = bt_conn_auth_cb_register(&auth_cb_input);
+	} else if (!strcmp(argv[1], "display")) {
+		err = bt_conn_auth_cb_register(&auth_cb_display);
+	} else if (!strcmp(argv[1], "yesno")) {
+		err = bt_conn_auth_cb_register(&auth_cb_display_yes_no);
+	} else if (!strcmp(argv[1], "confirm")) {
+		err = bt_conn_auth_cb_register(&auth_cb_confirm);
+	} else if (!strcmp(argv[1], "oob")) {
+		err = bt_conn_auth_cb_register(&auth_cb_oob);
+	} else if (!strcmp(argv[1], "none")) {
+		err = bt_conn_auth_cb_register(NULL);
+	} else {
+		shell_help(shell);
+		return SHELL_CMD_HELP_PRINTED;
+	}
+
+	return err;
+}
+
+static int cmd_auth_cancel(const struct shell *shell,
+			   size_t argc, char *argv[])
+{
+	struct bt_conn *conn;
+
+	if (default_conn) {
+		conn = default_conn;
+	} else if (pairing_conn) {
+		conn = pairing_conn;
+	} else {
+		conn = NULL;
+	}
+
+	if (!conn) {
+		shell_print(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	bt_conn_auth_cancel(conn);
+
+	return 0;
+}
+
+static int cmd_auth_passkey_confirm(const struct shell *shell,
+				    size_t argc, char *argv[])
+{
+	if (!default_conn) {
+		shell_print(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	bt_conn_auth_passkey_confirm(default_conn);
+	return 0;
+}
+
+static int cmd_auth_pairing_confirm(const struct shell *shell,
+				    size_t argc, char *argv[])
+{
+	if (!default_conn) {
+		shell_print(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	bt_conn_auth_pairing_confirm(default_conn);
+	return 0;
+}
+
+#if defined(CONFIG_BT_WHITELIST)
+static int cmd_wl_add(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_addr_le_t addr;
+	int err;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	err = bt_le_whitelist_add(&addr);
+	if (err) {
+		shell_error(shell, "Add to whitelist failed (err %d)", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cmd_wl_rem(const struct shell *shell, size_t argc, char *argv[])
+{
+	bt_addr_le_t addr;
+	int err;
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return err;
+	}
+
+	err = bt_le_whitelist_rem(&addr);
+	if (err) {
+		shell_error(shell, "Remove from whitelist failed (err %d)",
+			    err);
+		return err;
+	}
+	return 0;
+}
+
+static int cmd_wl_clear(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_le_whitelist_clear();
+	if (err) {
+		shell_error(shell, "Clearing whitelist failed (err %d)", err);
+		return err;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CENTRAL)
+static int cmd_wl_connect(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+	const char *action = argv[1];
+	uint32_t options = 0;
+
+#if defined(CONFIG_BT_EXT_ADV)
+	for (size_t argn = 2; argn < argc; argn++) {
+		const char *arg = argv[argn];
+
+		if (!strcmp(arg, "coded")) {
+			options |= BT_CONN_LE_OPT_CODED;
+		} else if (!strcmp(arg, "no-1m")) {
+			options |= BT_CONN_LE_OPT_NO_1M;
+		} else {
+			shell_help(shell);
+			return SHELL_CMD_HELP_PRINTED;
+		}
+	}
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+	struct bt_conn_le_create_param *create_params =
+		BT_CONN_LE_CREATE_PARAM(options,
+					BT_GAP_SCAN_FAST_INTERVAL,
+					BT_GAP_SCAN_FAST_WINDOW);
+
+	if (!strcmp(action, "on")) {
+		err = bt_conn_le_create_auto(create_params,
+					     BT_LE_CONN_PARAM_DEFAULT);
+		if (err) {
+			shell_error(shell, "Auto connect failed (err %d)", err);
+			return err;
+		}
+	} else if (!strcmp(action, "off")) {
+		err = bt_conn_create_auto_stop();
+		if (err) {
+			shell_error(shell, "Auto connect stop failed (err %d)",
+				    err);
+		}
+		return err;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BT_CENTRAL */
+#endif /* defined(CONFIG_BT_WHITELIST) */
+
+#if defined(CONFIG_BT_FIXED_PASSKEY)
+static int cmd_fixed_passkey(const struct shell *shell,
+			     size_t argc, char *argv[])
+{
+	unsigned int passkey;
+	int err;
+
+	if (argc < 2) {
+		bt_passkey_set(BT_PASSKEY_INVALID);
+		shell_print(shell, "Fixed passkey cleared");
+		return 0;
+	}
+
+	passkey = atoi(argv[1]);
+	if (passkey > 999999) {
+		shell_print(shell, "Passkey should be between 0-999999");
+		return -ENOEXEC;
+	}
+
+	err = bt_passkey_set(passkey);
+	if (err) {
+		shell_print(shell, "Setting fixed passkey failed (err %d)",
+			    err);
+	}
+
+	return err;
+}
+#endif
+
+static int cmd_auth_passkey(const struct shell *shell,
+			    size_t argc, char *argv[])
+{
+	unsigned int passkey;
+	int err;
+
+	if (!default_conn) {
+		shell_print(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	passkey = atoi(argv[1]);
+	if (passkey > 999999) {
+		shell_print(shell, "Passkey should be between 0-999999");
+		return -EINVAL;
+	}
+
+	err = bt_conn_auth_passkey_entry(default_conn, passkey);
+	if (err) {
+		shell_error(shell, "Failed to set passkey (%d)", err);
+		return err;
+	}
+
+	return 0;
+}
+
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+static int cmd_auth_oob_tk(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t tk[16];
+	size_t len;
+	int err;
+
+	len = hex2bin(argv[1], strlen(argv[1]), tk, sizeof(tk));
+	if (len != sizeof(tk)) {
+		shell_error(shell, "TK should be 16 bytes");
+		return -EINVAL;
+	}
+
+	err = bt_le_oob_set_legacy_tk(default_conn, tk);
+	if (err) {
+		shell_error(shell, "Failed to set TK (%d)", err);
+		return err;
+	}
+
+	return 0;
+}
+#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
+#endif /* CONFIG_BT_SMP) || CONFIG_BT_BREDR */
+
+
+#define HELP_NONE "[none]"
+#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
+
+#if defined(CONFIG_BT_EXT_ADV)
+#define EXT_ADV_SCAN_OPT " [coded] [no-1m]"
+#define EXT_ADV_PARAM "<type: conn-scan conn-nscan, nconn-scan nconn-nscan> " \
+		      "[ext-adv] [no-2m] [coded] "                            \
+		      "[whitelist: wl, wl-scan, wl-conn] [identity] [name] "  \
+		      "[directed "HELP_ADDR_LE"] [mode: low]"                 \
+		      "[disable-37] [disable-38] [disable-39]"
+#else
+#define EXT_ADV_SCAN_OPT ""
+#endif /* defined(CONFIG_BT_EXT_ADV) */
+
+SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds,
+	SHELL_CMD_ARG(init, NULL, HELP_NONE, cmd_init, 1, 0),
+#if defined(CONFIG_BT_HCI)
+	SHELL_CMD_ARG(hci-cmd, NULL, "<ogf> <ocf> [data]", cmd_hci_cmd, 3, 1),
+#endif
+	SHELL_CMD_ARG(id-create, NULL, "[addr]", cmd_id_create, 1, 1),
+	SHELL_CMD_ARG(id-reset, NULL, "<id> [addr]", cmd_id_reset, 2, 1),
+	SHELL_CMD_ARG(id-delete, NULL, "<id>", cmd_id_delete, 2, 0),
+	SHELL_CMD_ARG(id-show, NULL, HELP_NONE, cmd_id_show, 1, 0),
+	SHELL_CMD_ARG(id-select, NULL, "<id>", cmd_id_select, 2, 0),
+	SHELL_CMD_ARG(name, NULL, "[name]", cmd_name, 1, 1),
+#if defined(CONFIG_BT_OBSERVER)
+	SHELL_CMD_ARG(scan, NULL,
+		      "<value: on, passive, off> [filter: dups, nodups] [wl]"
+		      EXT_ADV_SCAN_OPT,
+		      cmd_scan, 2, 4),
+#endif /* CONFIG_BT_OBSERVER */
+#if defined(CONFIG_BT_BROADCASTER)
+	SHELL_CMD_ARG(advertise, NULL,
+		      "<type: off, on, scan, nconn> [mode: discov, non_discov] "
+		      "[whitelist: wl, wl-scan, wl-conn] [identity] [no-name] "
+		      "[one-time] [disable-37] [disable-38] [disable-39]",
+		      cmd_advertise, 2, 8),
+#if defined(CONFIG_BT_PERIPHERAL)
+	SHELL_CMD_ARG(directed-adv, NULL, HELP_ADDR_LE " [mode: low] "
+		      "[identity] [dir-rpa]",
+		      cmd_directed_adv, 3, 6),
+#endif /* CONFIG_BT_PERIPHERAL */
+#if defined(CONFIG_BT_EXT_ADV)
+	SHELL_CMD_ARG(adv-create, NULL, EXT_ADV_PARAM, cmd_adv_create, 2, 11),
+	SHELL_CMD_ARG(adv-param, NULL, EXT_ADV_PARAM, cmd_adv_param, 2, 11),
+	SHELL_CMD_ARG(adv-data, NULL, "<data> [scan-response <data>] "
+				      "<type: discov, name, hex>", cmd_adv_data,
+		      1, 16),
+	SHELL_CMD_ARG(adv-start, NULL,
+		"[timeout <timeout>] [num-events <num events>]",
+		cmd_adv_start, 1, 4),
+	SHELL_CMD_ARG(adv-stop, NULL, "", cmd_adv_stop, 1, 0),
+	SHELL_CMD_ARG(adv-delete, NULL, "", cmd_adv_delete, 1, 0),
+	SHELL_CMD_ARG(adv-select, NULL, "[adv]", cmd_adv_select, 1, 1),
+	SHELL_CMD_ARG(adv-info, NULL, HELP_NONE, cmd_adv_info, 1, 0),
+#if defined(CONFIG_BT_PERIPHERAL)
+	SHELL_CMD_ARG(adv-oob, NULL, HELP_NONE, cmd_adv_oob, 1, 0),
+#endif /* CONFIG_BT_PERIPHERAL */
+#if defined(CONFIG_BT_PER_ADV)
+	SHELL_CMD_ARG(per-adv, NULL, "<type: off, on>", cmd_per_adv, 2, 0),
+	SHELL_CMD_ARG(per-adv-param, NULL,
+		      "[<interval-min> [<interval-max> [tx_power]]]",
+		      cmd_per_adv_param, 1, 3),
+	SHELL_CMD_ARG(per-adv-data, NULL, "<data>", cmd_per_adv_data, 2, 0),
+#endif /* CONFIG_BT_PER_ADV */
+#endif /* CONFIG_BT_EXT_ADV */
+#endif /* CONFIG_BT_BROADCASTER */
+#if defined(CONFIG_BT_PER_ADV_SYNC)
+	SHELL_CMD_ARG(per-adv-sync-create, NULL,
+		      HELP_ADDR_LE " <sid> [skip <count>] [timeout <ms>] [aoa] "
+		      "[aod_1us] [aod_2us] [cte_only]",
+		      cmd_per_adv_sync_create, 4, 6),
+	SHELL_CMD_ARG(per-adv-sync-delete, NULL, "[<index>]",
+		      cmd_per_adv_sync_delete, 1, 1),
+#endif /* defined(CONFIG_BT_PER_ADV_SYNC) */
+#if defined(CONFIG_BT_CONN)
+#if defined(CONFIG_BT_CENTRAL)
+	SHELL_CMD_ARG(connect, NULL, HELP_ADDR_LE EXT_ADV_SCAN_OPT,
+		      cmd_connect_le, 3, 3),
+#if !defined(CONFIG_BT_WHITELIST)
+	SHELL_CMD_ARG(auto-conn, NULL, HELP_ADDR_LE, cmd_auto_conn, 3, 0),
+#endif /* !defined(CONFIG_BT_WHITELIST) */
+#endif /* CONFIG_BT_CENTRAL */
+	SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 2),
+	SHELL_CMD_ARG(select, NULL, HELP_ADDR_LE, cmd_select, 3, 0),
+	SHELL_CMD_ARG(info, NULL, HELP_ADDR_LE, cmd_info, 1, 2),
+	SHELL_CMD_ARG(conn-update, NULL, "<min> <max> <latency> <timeout>",
+		      cmd_conn_update, 5, 0),
+#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
+	SHELL_CMD_ARG(data-len-update, NULL, "<tx_max_len> [tx_max_time]",
+		      cmd_conn_data_len_update, 2, 1),
+#endif
+#if defined(CONFIG_BT_USER_PHY_UPDATE)
+	SHELL_CMD_ARG(phy-update, NULL, "<tx_phy> [rx_phy] [s2] [s8]",
+		      cmd_conn_phy_update, 2, 3),
+#endif
+#if defined(CONFIG_BT_CENTRAL)
+	SHELL_CMD_ARG(channel-map, NULL, "<channel-map: XXXXXXXXXX> (36-0)",
+		      cmd_chan_map, 2, 1),
+#endif /* CONFIG_BT_CENTRAL */
+	SHELL_CMD_ARG(oob, NULL, NULL, cmd_oob, 1, 0),
+	SHELL_CMD_ARG(clear, NULL, "<remote: addr, all>", cmd_clear, 2, 1),
+#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
+	SHELL_CMD_ARG(security, NULL, "<security level BR/EDR: 0 - 3, "
+				      "LE: 1 - 4> [force-pair]",
+		      cmd_security, 2, 1),
+	SHELL_CMD_ARG(bondable, NULL, "<bondable: on, off>", cmd_bondable,
+		      2, 0),
+	SHELL_CMD_ARG(bonds, NULL, HELP_NONE, cmd_bonds, 1, 0),
+	SHELL_CMD_ARG(connections, NULL, HELP_NONE, cmd_connections, 1, 0),
+	SHELL_CMD_ARG(auth, NULL,
+		      "<method: all, input, display, yesno, confirm, "
+		      "oob, none>",
+		      cmd_auth, 2, 0),
+	SHELL_CMD_ARG(auth-cancel, NULL, HELP_NONE, cmd_auth_cancel, 1, 0),
+	SHELL_CMD_ARG(auth-passkey, NULL, "<passkey>", cmd_auth_passkey, 2, 0),
+	SHELL_CMD_ARG(auth-passkey-confirm, NULL, HELP_NONE,
+		      cmd_auth_passkey_confirm, 1, 0),
+	SHELL_CMD_ARG(auth-pairing-confirm, NULL, HELP_NONE,
+		      cmd_auth_pairing_confirm, 1, 0),
+#if !defined(CONFIG_BT_SMP_SC_PAIR_ONLY)
+	SHELL_CMD_ARG(auth-oob-tk, NULL, "<tk>", cmd_auth_oob_tk, 2, 0),
+#endif /* !defined(CONFIG_BT_SMP_SC_PAIR_ONLY) */
+	SHELL_CMD_ARG(oob-remote, NULL,
+		      HELP_ADDR_LE" <oob rand> <oob confirm>",
+		      cmd_oob_remote, 3, 2),
+	SHELL_CMD_ARG(oob-clear, NULL, HELP_NONE, cmd_oob_clear, 1, 0),
+#if defined(CONFIG_BT_WHITELIST)
+	SHELL_CMD_ARG(wl-add, NULL, HELP_ADDR_LE, cmd_wl_add, 3, 0),
+	SHELL_CMD_ARG(wl-rem, NULL, HELP_ADDR_LE, cmd_wl_rem, 3, 0),
+	SHELL_CMD_ARG(wl-clear, NULL, HELP_NONE, cmd_wl_clear, 1, 0),
+
+#if defined(CONFIG_BT_CENTRAL)
+	SHELL_CMD_ARG(wl-connect, NULL, "<on, off>" EXT_ADV_SCAN_OPT,
+		      cmd_wl_connect, 2, 3),
+#endif /* CONFIG_BT_CENTRAL */
+#endif /* defined(CONFIG_BT_WHITELIST) */
+#if defined(CONFIG_BT_FIXED_PASSKEY)
+	SHELL_CMD_ARG(fixed-passkey, NULL, "[passkey]", cmd_fixed_passkey,
+		      1, 1),
+#endif
+#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
+#endif /* CONFIG_BT_CONN */
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	SHELL_CMD(mesh_adv, NULL, "<on, off>", cmd_mesh_adv),
+#endif /* CONFIG_BT_HCI_MESH_EXT */
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#if defined(CONFIG_BT_BROADCASTER)
+	SHELL_CMD_ARG(advx, NULL,
+		      "<on hdcd ldcd off> [coded] [anon] [txp] [ad]",
+		      cmd_advx, 2, 4),
+#endif /* CONFIG_BT_BROADCASTER */
+#if defined(CONFIG_BT_OBSERVER)
+	SHELL_CMD_ARG(scanx, NULL, "<on passive off> [coded]", cmd_scanx,
+		      2, 1),
+#endif /* CONFIG_BT_OBSERVER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
+#if defined(CONFIG_BT_CTLR_DTM)
+	SHELL_CMD_ARG(test_tx, NULL, "<chan> <len> <type> <phy>", cmd_test_tx,
+		      5, 0),
+	SHELL_CMD_ARG(test_rx, NULL, "<chan> <phy> <mod_idx>", cmd_test_rx,
+		      4, 0),
+	SHELL_CMD_ARG(test_end, NULL, HELP_NONE, cmd_test_end, 1, 0),
+#endif /* CONFIG_BT_CTLR_DTM */
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_bt(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		return SHELL_CMD_HELP_PRINTED;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -EINVAL;
+}
+
+SHELL_CMD_REGISTER(bt, &bt_cmds, "Bluetooth shell commands", cmd_bt);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/gatt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/gatt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/gatt.c	(working copy)
@@ -0,0 +1,1196 @@
+/** @file
+ * @brief Bluetooth GATT shell functions
+ *
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/gatt.h>
+
+#include <shell/shell.h>
+
+#include "bt.h"
+
+#define CHAR_SIZE_MAX           512
+
+extern uint8_t selected_id;
+
+#if defined(CONFIG_BT_GATT_CLIENT)
+static void exchange_func(struct bt_conn *conn, uint8_t err,
+			  struct bt_gatt_exchange_params *params)
+{
+	shell_print(ctx_shell, "Exchange %s", err == 0U ? "successful" :
+		    "failed");
+
+	(void)memset(params, 0, sizeof(*params));
+}
+
+static struct bt_gatt_exchange_params exchange_params;
+
+static int cmd_exchange_mtu(const struct shell *shell,
+			     size_t argc, char *argv[])
+{
+	int err;
+
+	if (!default_conn) {
+		shell_print(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (exchange_params.func) {
+		shell_print(shell, "MTU Exchange ongoing");
+		return -ENOEXEC;
+	}
+
+	exchange_params.func = exchange_func;
+
+	err = bt_gatt_exchange_mtu(default_conn, &exchange_params);
+	if (err) {
+		shell_print(shell, "Exchange failed (err %d)", err);
+	} else {
+		shell_print(shell, "Exchange pending");
+	}
+
+	return err;
+}
+
+static struct bt_gatt_discover_params discover_params;
+static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
+
+static void print_chrc_props(const struct shell *shell, uint8_t properties)
+{
+	shell_print(shell, "Properties: ");
+
+	if (properties & BT_GATT_CHRC_BROADCAST) {
+		shell_print(shell, "[bcast]");
+	}
+
+	if (properties & BT_GATT_CHRC_READ) {
+		shell_print(shell, "[read]");
+	}
+
+	if (properties & BT_GATT_CHRC_WRITE) {
+		shell_print(shell, "[write]");
+	}
+
+	if (properties & BT_GATT_CHRC_WRITE_WITHOUT_RESP) {
+		shell_print(shell, "[write w/w rsp]");
+	}
+
+	if (properties & BT_GATT_CHRC_NOTIFY) {
+		shell_print(shell, "[notify]");
+	}
+
+	if (properties & BT_GATT_CHRC_INDICATE) {
+		shell_print(shell, "[indicate]");
+	}
+
+	if (properties & BT_GATT_CHRC_AUTH) {
+		shell_print(shell, "[auth]");
+	}
+
+	if (properties & BT_GATT_CHRC_EXT_PROP) {
+		shell_print(shell, "[ext prop]");
+	}
+
+	shell_print(shell, "");
+}
+
+static uint8_t discover_func(struct bt_conn *conn,
+			     const struct bt_gatt_attr *attr,
+			     struct bt_gatt_discover_params *params)
+{
+	struct bt_gatt_service_val *gatt_service;
+	struct bt_gatt_chrc *gatt_chrc;
+	struct bt_gatt_include *gatt_include;
+	char str[BT_UUID_STR_LEN];
+
+	if (!attr) {
+		shell_print(ctx_shell, "Discover complete");
+		(void)memset(params, 0, sizeof(*params));
+		return BT_GATT_ITER_STOP;
+	}
+
+	switch (params->type) {
+	case BT_GATT_DISCOVER_SECONDARY:
+	case BT_GATT_DISCOVER_PRIMARY:
+		gatt_service = attr->user_data;
+		bt_uuid_to_str(gatt_service->uuid, str, sizeof(str));
+		shell_print(ctx_shell, "Service %s found: start handle %x, "
+			    "end_handle %x", str, attr->handle,
+			    gatt_service->end_handle);
+		break;
+	case BT_GATT_DISCOVER_CHARACTERISTIC:
+		gatt_chrc = attr->user_data;
+		bt_uuid_to_str(gatt_chrc->uuid, str, sizeof(str));
+		shell_print(ctx_shell, "Characteristic %s found: handle %x",
+			    str, attr->handle);
+		print_chrc_props(ctx_shell, gatt_chrc->properties);
+		break;
+	case BT_GATT_DISCOVER_INCLUDE:
+		gatt_include = attr->user_data;
+		bt_uuid_to_str(gatt_include->uuid, str, sizeof(str));
+		shell_print(ctx_shell, "Include %s found: handle %x, start %x, "
+			    "end %x", str, attr->handle,
+			    gatt_include->start_handle,
+			    gatt_include->end_handle);
+		break;
+	default:
+		bt_uuid_to_str(attr->uuid, str, sizeof(str));
+		shell_print(ctx_shell, "Descriptor %s found: handle %x", str,
+			    attr->handle);
+		break;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_discover(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (discover_params.func) {
+		shell_print(shell, "Discover ongoing");
+		return -ENOEXEC;
+	}
+
+	discover_params.func = discover_func;
+	discover_params.start_handle = 0x0001;
+	discover_params.end_handle = 0xffff;
+
+	if (argc > 1) {
+		/* Only set the UUID if the value is valid (non zero) */
+		uuid.val = strtoul(argv[1], NULL, 16);
+		if (uuid.val) {
+			discover_params.uuid = &uuid.uuid;
+		}
+	}
+
+	if (argc > 2) {
+		discover_params.start_handle = strtoul(argv[2], NULL, 16);
+		if (argc > 3) {
+			discover_params.end_handle = strtoul(argv[3], NULL, 16);
+		}
+	}
+
+	if (!strcmp(argv[0], "discover")) {
+		discover_params.type = BT_GATT_DISCOVER_ATTRIBUTE;
+	} else if (!strcmp(argv[0], "discover-secondary")) {
+		discover_params.type = BT_GATT_DISCOVER_SECONDARY;
+	} else if (!strcmp(argv[0], "discover-include")) {
+		discover_params.type = BT_GATT_DISCOVER_INCLUDE;
+	} else if (!strcmp(argv[0], "discover-characteristic")) {
+		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
+	} else if (!strcmp(argv[0], "discover-descriptor")) {
+		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
+	} else {
+		discover_params.type = BT_GATT_DISCOVER_PRIMARY;
+	}
+
+	err = bt_gatt_discover(default_conn, &discover_params);
+	if (err) {
+		shell_error(shell, "Discover failed (err %d)", err);
+	} else {
+		shell_print(shell, "Discover pending");
+	}
+
+	return err;
+}
+
+static struct bt_gatt_read_params read_params;
+
+static uint8_t read_func(struct bt_conn *conn, uint8_t err,
+			 struct bt_gatt_read_params *params,
+			 const void *data, uint16_t length)
+{
+	shell_print(ctx_shell, "Read complete: err 0x%02x length %u", err, length);
+
+	if (!data) {
+		(void)memset(params, 0, sizeof(*params));
+		return BT_GATT_ITER_STOP;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_read(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (read_params.func) {
+		shell_print(shell, "Read ongoing");
+		return -ENOEXEC;
+	}
+
+	read_params.func = read_func;
+	read_params.handle_count = 1;
+	read_params.single.handle = strtoul(argv[1], NULL, 16);
+	read_params.single.offset = 0U;
+
+	if (argc > 2) {
+		read_params.single.offset = strtoul(argv[2], NULL, 16);
+	}
+
+	err = bt_gatt_read(default_conn, &read_params);
+	if (err) {
+		shell_error(shell, "Read failed (err %d)", err);
+	} else {
+		shell_print(shell, "Read pending");
+	}
+
+	return err;
+}
+
+static int cmd_mread(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t h[8];
+	size_t i;
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (read_params.func) {
+		shell_print(shell, "Read ongoing");
+		return -ENOEXEC;
+	}
+
+	if ((argc - 1) >  ARRAY_SIZE(h)) {
+		shell_print(shell, "Enter max %lu handle items to read",
+			    ARRAY_SIZE(h));
+		return -EINVAL;
+	}
+
+	for (i = 0; i < argc - 1; i++) {
+		h[i] = strtoul(argv[i + 1], NULL, 16);
+	}
+
+	read_params.func = read_func;
+	read_params.handle_count = i;
+	read_params.handles = h; /* not used in read func */
+
+	err = bt_gatt_read(default_conn, &read_params);
+	if (err) {
+		shell_error(shell, "GATT multiple read request failed (err %d)",
+			    err);
+	}
+
+	return err;
+}
+
+static int cmd_read_uuid(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (read_params.func) {
+		shell_print(shell, "Read ongoing");
+		return -ENOEXEC;
+	}
+
+	read_params.func = read_func;
+	read_params.handle_count = 0;
+	read_params.by_uuid.start_handle = 0x0001;
+	read_params.by_uuid.end_handle = 0xffff;
+
+	if (argc > 1) {
+		uuid.val = strtoul(argv[1], NULL, 16);
+		if (uuid.val) {
+			read_params.by_uuid.uuid = &uuid.uuid;
+		}
+	}
+
+	if (argc > 2) {
+		read_params.by_uuid.start_handle = strtoul(argv[2], NULL, 16);
+		if (argc > 3) {
+			read_params.by_uuid.end_handle = strtoul(argv[3],
+								 NULL, 16);
+		}
+	}
+
+	err = bt_gatt_read(default_conn, &read_params);
+	if (err) {
+		shell_error(shell, "Read failed (err %d)", err);
+	} else {
+		shell_print(shell, "Read pending");
+	}
+
+	return err;
+}
+
+static struct bt_gatt_write_params write_params;
+static uint8_t gatt_write_buf[CHAR_SIZE_MAX];
+
+static void write_func(struct bt_conn *conn, uint8_t err,
+		       struct bt_gatt_write_params *params)
+{
+	shell_print(ctx_shell, "Write complete: err 0x%02x", err);
+
+	(void)memset(&write_params, 0, sizeof(write_params));
+}
+
+static int cmd_write(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+	uint16_t handle, offset;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (write_params.func) {
+		shell_error(shell, "Write ongoing");
+		return -ENOEXEC;
+	}
+
+	handle = strtoul(argv[1], NULL, 16);
+	offset = strtoul(argv[2], NULL, 16);
+
+	gatt_write_buf[0] = strtoul(argv[3], NULL, 16);
+	write_params.data = gatt_write_buf;
+	write_params.length = 1U;
+	write_params.handle = handle;
+	write_params.offset = offset;
+	write_params.func = write_func;
+
+	if (argc == 5) {
+		size_t len, i;
+
+		len = MIN(strtoul(argv[4], NULL, 16), sizeof(gatt_write_buf));
+
+		for (i = 1; i < len; i++) {
+			gatt_write_buf[i] = gatt_write_buf[0];
+		}
+
+		write_params.length = len;
+	}
+
+	err = bt_gatt_write(default_conn, &write_params);
+	if (err) {
+		shell_error(shell, "Write failed (err %d)", err);
+	} else {
+		shell_print(shell, "Write pending");
+	}
+
+	return err;
+}
+
+static struct write_stats {
+	uint32_t count;
+	uint32_t len;
+	uint32_t total;
+	uint32_t rate;
+} write_stats;
+
+static void update_write_stats(uint16_t len)
+{
+	static uint32_t cycle_stamp;
+	uint32_t delta;
+
+	delta = k_cycle_get_32() - cycle_stamp;
+	delta = (uint32_t)k_cyc_to_ns_floor64(delta);
+
+	if (!delta) {
+		delta = 1;
+	}
+
+	write_stats.count++;
+	write_stats.total += len;
+
+	/* if last data rx-ed was greater than 1 second in the past,
+	 * reset the metrics.
+	 */
+	if (delta > 1000000000) {
+		write_stats.len = 0U;
+		write_stats.rate = 0U;
+		cycle_stamp = k_cycle_get_32();
+	} else {
+		write_stats.len += len;
+		write_stats.rate = ((uint64_t)write_stats.len << 3) *
+				   1000000000U / delta;
+	}
+}
+
+static void reset_write_stats(void)
+{
+	memset(&write_stats, 0, sizeof(write_stats));
+}
+
+static void print_write_stats(void)
+{
+	shell_print(ctx_shell, "Write #%u: %u bytes (%u bps)",
+		    write_stats.count, write_stats.total, write_stats.rate);
+}
+
+static void write_without_rsp_cb(struct bt_conn *conn, void *user_data)
+{
+	uint16_t len = POINTER_TO_UINT(user_data);
+
+	update_write_stats(len);
+
+	print_write_stats();
+}
+
+static int cmd_write_without_rsp(const struct shell *shell,
+				 size_t argc, char *argv[])
+{
+	uint16_t handle;
+	uint16_t repeat;
+	int err;
+	uint16_t len;
+	bool sign;
+	bt_gatt_complete_func_t func = NULL;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	sign = !strcmp(argv[0], "signed-write");
+	if (!sign) {
+		if (!strcmp(argv[0], "write-without-response-cb")) {
+			func = write_without_rsp_cb;
+			reset_write_stats();
+		}
+	}
+
+	handle = strtoul(argv[1], NULL, 16);
+	gatt_write_buf[0] = strtoul(argv[2], NULL, 16);
+	len = 1U;
+
+	if (argc > 3) {
+		int i;
+
+		len = MIN(strtoul(argv[3], NULL, 16), sizeof(gatt_write_buf));
+
+		for (i = 1; i < len; i++) {
+			gatt_write_buf[i] = gatt_write_buf[0];
+		}
+	}
+
+	repeat = 0U;
+
+	if (argc > 4) {
+		repeat = strtoul(argv[4], NULL, 16);
+	}
+
+	if (!repeat) {
+		repeat = 1U;
+	}
+
+	while (repeat--) {
+		err = bt_gatt_write_without_response_cb(default_conn, handle,
+							gatt_write_buf, len,
+							sign, func,
+							UINT_TO_POINTER(len));
+		if (err) {
+			break;
+		}
+
+		k_yield();
+
+	}
+
+	shell_print(shell, "Write Complete (err %d)", err);
+	return err;
+}
+
+static struct bt_gatt_subscribe_params subscribe_params;
+
+static uint8_t notify_func(struct bt_conn *conn,
+			struct bt_gatt_subscribe_params *params,
+			const void *data, uint16_t length)
+{
+	if (!data) {
+		shell_print(ctx_shell, "Unsubscribed");
+		params->value_handle = 0U;
+		return BT_GATT_ITER_STOP;
+	}
+
+	shell_print(ctx_shell, "Notification: data %p length %u", data, length);
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_subscribe(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (subscribe_params.value_handle) {
+		shell_error(shell, "Cannot subscribe: subscription to %x "
+			    "already exists", subscribe_params.value_handle);
+		return -ENOEXEC;
+	}
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	subscribe_params.ccc_handle = strtoul(argv[1], NULL, 16);
+	subscribe_params.value_handle = strtoul(argv[2], NULL, 16);
+	subscribe_params.value = BT_GATT_CCC_NOTIFY;
+	subscribe_params.notify = notify_func;
+
+#if defined(CONFIG_BT_GATT_AUTO_DISCOVER_CCC)
+	if (subscribe_params.ccc_handle == 0) {
+		static struct bt_gatt_discover_params disc_params;
+
+		subscribe_params.disc_params = &disc_params;
+		subscribe_params.end_handle = 0xFFFF;
+	}
+#endif /* CONFIG_BT_GATT_AUTO_DISCOVER_CCC */
+
+
+	if (argc > 3 && !strcmp(argv[3], "ind")) {
+		subscribe_params.value = BT_GATT_CCC_INDICATE;
+	}
+
+	err = bt_gatt_subscribe(default_conn, &subscribe_params);
+	if (err) {
+		subscribe_params.value_handle = 0U;
+		shell_error(shell, "Subscribe failed (err %d)", err);
+	} else {
+		shell_print(shell, "Subscribed");
+	}
+
+	return err;
+}
+
+static int cmd_resubscribe(const struct shell *shell, size_t argc,
+				char *argv[])
+{
+	bt_addr_le_t addr;
+	int err;
+
+	if (subscribe_params.value_handle) {
+		shell_error(shell, "Cannot resubscribe: subscription to %x"
+			    " already exists", subscribe_params.value_handle);
+		return -ENOEXEC;
+	}
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_error(shell, "Invalid peer address (err %d)", err);
+		return -ENOEXEC;
+	}
+
+	subscribe_params.ccc_handle = strtoul(argv[3], NULL, 16);
+	subscribe_params.value_handle = strtoul(argv[4], NULL, 16);
+	subscribe_params.value = BT_GATT_CCC_NOTIFY;
+	subscribe_params.notify = notify_func;
+
+	if (argc > 5 && !strcmp(argv[5], "ind")) {
+		subscribe_params.value = BT_GATT_CCC_INDICATE;
+	}
+
+	err = bt_gatt_resubscribe(selected_id, &addr, &subscribe_params);
+	if (err) {
+		subscribe_params.value_handle = 0U;
+		shell_error(shell, "Resubscribe failed (err %d)", err);
+	} else {
+		shell_print(shell, "Resubscribed");
+	}
+
+	return err;
+}
+
+static int cmd_unsubscribe(const struct shell *shell,
+			   size_t argc, char *argv[])
+{
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (!subscribe_params.value_handle) {
+		shell_error(shell, "No subscription found");
+		return -ENOEXEC;
+	}
+
+	err = bt_gatt_unsubscribe(default_conn, &subscribe_params);
+	if (err) {
+		shell_error(shell, "Unsubscribe failed (err %d)", err);
+	} else {
+		shell_print(shell, "Unsubscribe success");
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_GATT_CLIENT */
+
+static struct db_stats {
+	uint16_t svc_count;
+	uint16_t attr_count;
+	uint16_t chrc_count;
+	uint16_t ccc_count;
+} stats;
+
+static uint8_t print_attr(const struct bt_gatt_attr *attr, uint16_t handle,
+			  void *user_data)
+{
+	const struct shell *shell = user_data;
+	char str[BT_UUID_STR_LEN];
+
+	stats.attr_count++;
+
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_PRIMARY) ||
+	    !bt_uuid_cmp(attr->uuid, BT_UUID_GATT_SECONDARY)) {
+		stats.svc_count++;
+	}
+
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
+		stats.chrc_count++;
+	}
+
+	if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CCC) &&
+	    attr->write == bt_gatt_attr_write_ccc) {
+		stats.ccc_count++;
+	}
+
+	bt_uuid_to_str(attr->uuid, str, sizeof(str));
+	shell_print(shell, "attr %p handle 0x%04x uuid %s perm 0x%02x",
+		    attr, handle, str, attr->perm);
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_show_db(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_uuid_16 uuid;
+	size_t total_len;
+
+	memset(&stats, 0, sizeof(stats));
+
+	if (argc > 1) {
+		uint16_t num_matches = 0;
+
+		uuid.uuid.type = BT_UUID_TYPE_16;
+		uuid.val = strtoul(argv[1], NULL, 16);
+
+		if (argc > 2) {
+			num_matches = strtoul(argv[2], NULL, 10);
+		}
+
+		bt_gatt_foreach_attr_type(0x0001, 0xffff, &uuid.uuid, NULL,
+					  num_matches, print_attr,
+					  (void *)shell);
+		return 0;
+	}
+
+	bt_gatt_foreach_attr(0x0001, 0xffff, print_attr, (void *)shell);
+
+	if (!stats.attr_count) {
+		shell_print(shell, "No attribute found");
+		return 0;
+	}
+
+	total_len = stats.svc_count * sizeof(struct bt_gatt_service);
+	total_len += stats.chrc_count * sizeof(struct bt_gatt_chrc);
+	total_len += stats.attr_count * sizeof(struct bt_gatt_attr);
+	total_len += stats.ccc_count * sizeof(struct _bt_gatt_ccc);
+
+	shell_print(shell, "=================================================");
+	shell_print(shell, "Total: %u services %u attributes (%u bytes)",
+		    stats.svc_count, stats.attr_count, total_len);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+/* Custom Service Variables */
+static struct bt_uuid_128 vnd_uuid = BT_UUID_INIT_128(
+	0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+static struct bt_uuid_128 vnd_auth_uuid = BT_UUID_INIT_128(
+	0xf2, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+static const struct bt_uuid_128 vnd_long_uuid1 = BT_UUID_INIT_128(
+	0xf3, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+static const struct bt_uuid_128 vnd_long_uuid2 = BT_UUID_INIT_128(
+	0xde, 0xad, 0xfa, 0xce, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static uint8_t vnd_value[] = { 'V', 'e', 'n', 'd', 'o', 'r' };
+
+static struct bt_uuid_128 vnd1_uuid = BT_UUID_INIT_128(
+	0xf4, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static const struct bt_uuid_128 vnd1_echo_uuid = BT_UUID_INIT_128(
+	0xf5, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static uint8_t echo_enabled;
+
+static void vnd1_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
+{
+	echo_enabled = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
+}
+
+static ssize_t write_vnd1(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			  const void *buf, uint16_t len, uint16_t offset,
+			  uint8_t flags)
+{
+	if (echo_enabled) {
+		shell_print(ctx_shell, "Echo attr len %u", len);
+		bt_gatt_notify(conn, attr, buf, len);
+	}
+
+	return len;
+}
+
+static ssize_t read_vnd(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			void *buf, uint16_t len, uint16_t offset)
+{
+	const char *value = attr->user_data;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+				 strlen(value));
+}
+
+static ssize_t write_vnd(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 const void *buf, uint16_t len, uint16_t offset,
+			 uint8_t flags)
+{
+	uint8_t *value = attr->user_data;
+
+	if (offset + len > sizeof(vnd_value)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	memcpy(value + offset, buf, len);
+
+	return len;
+}
+
+#define MAX_DATA 30
+static uint8_t vnd_long_value1[MAX_DATA] = { 'V', 'e', 'n', 'd', 'o', 'r' };
+static uint8_t vnd_long_value2[MAX_DATA] = { 'S', 't', 'r', 'i', 'n', 'g' };
+
+static ssize_t read_long_vnd(struct bt_conn *conn,
+			     const struct bt_gatt_attr *attr, void *buf,
+			     uint16_t len, uint16_t offset)
+{
+	uint8_t *value = attr->user_data;
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+				 sizeof(vnd_long_value1));
+}
+
+static ssize_t write_long_vnd(struct bt_conn *conn,
+			      const struct bt_gatt_attr *attr, const void *buf,
+			      uint16_t len, uint16_t offset, uint8_t flags)
+{
+	uint8_t *value = attr->user_data;
+
+	if (flags & BT_GATT_WRITE_FLAG_PREPARE) {
+		return 0;
+	}
+
+	if (offset + len > sizeof(vnd_long_value1)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	/* Copy to buffer */
+	memcpy(value + offset, buf, len);
+
+	return len;
+}
+
+static struct bt_gatt_attr vnd_attrs[] = {
+	/* Vendor Primary Service Declaration */
+	BT_GATT_PRIMARY_SERVICE(&vnd_uuid),
+
+	BT_GATT_CHARACTERISTIC(&vnd_auth_uuid.uuid,
+			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
+			       BT_GATT_PERM_READ_AUTHEN |
+			       BT_GATT_PERM_WRITE_AUTHEN,
+			       read_vnd, write_vnd, vnd_value),
+
+	BT_GATT_CHARACTERISTIC(&vnd_long_uuid1.uuid, BT_GATT_CHRC_READ |
+			       BT_GATT_CHRC_WRITE | BT_GATT_CHRC_EXT_PROP,
+			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE |
+			       BT_GATT_PERM_PREPARE_WRITE,
+			       read_long_vnd, write_long_vnd,
+			       &vnd_long_value1),
+
+	BT_GATT_CHARACTERISTIC(&vnd_long_uuid2.uuid, BT_GATT_CHRC_READ |
+			       BT_GATT_CHRC_WRITE | BT_GATT_CHRC_EXT_PROP,
+			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE |
+			       BT_GATT_PERM_PREPARE_WRITE,
+			       read_long_vnd, write_long_vnd,
+			       &vnd_long_value2),
+};
+
+static struct bt_gatt_service vnd_svc = BT_GATT_SERVICE(vnd_attrs);
+
+static struct bt_gatt_attr vnd1_attrs[] = {
+	/* Vendor Primary Service Declaration */
+	BT_GATT_PRIMARY_SERVICE(&vnd1_uuid),
+
+	BT_GATT_CHARACTERISTIC(&vnd1_echo_uuid.uuid,
+			       BT_GATT_CHRC_WRITE_WITHOUT_RESP |
+			       BT_GATT_CHRC_NOTIFY,
+			       BT_GATT_PERM_WRITE, NULL, write_vnd1, NULL),
+	BT_GATT_CCC(vnd1_ccc_cfg_changed,
+		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
+};
+
+static struct bt_gatt_service vnd1_svc = BT_GATT_SERVICE(vnd1_attrs);
+
+static int cmd_register_test_svc(const struct shell *shell,
+				  size_t argc, char *argv[])
+{
+	bt_gatt_service_register(&vnd_svc);
+	bt_gatt_service_register(&vnd1_svc);
+
+	shell_print(shell, "Registering test vendor services");
+	return 0;
+}
+
+static int cmd_unregister_test_svc(const struct shell *shell,
+				    size_t argc, char *argv[])
+{
+	bt_gatt_service_unregister(&vnd_svc);
+	bt_gatt_service_unregister(&vnd1_svc);
+
+	shell_print(shell, "Unregistering test vendor services");
+	return 0;
+}
+
+static void notify_cb(struct bt_conn *conn, void *user_data)
+{
+	const struct shell *shell = user_data;
+
+	shell_print(shell, "Nofication sent to conn %p", conn);
+}
+
+static int cmd_notify(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_gatt_notify_params params;
+	uint8_t data = 0;
+
+	if (!echo_enabled) {
+		shell_error(shell, "Nofication not enabled");
+		return -ENOEXEC;
+	}
+
+	if (argc > 1) {
+		data = strtoul(argv[1], NULL, 16);
+	}
+
+	memset(&params, 0, sizeof(params));
+
+	params.uuid = &vnd1_echo_uuid.uuid;
+	params.attr = vnd1_attrs;
+	params.data = &data;
+	params.len = sizeof(data);
+	params.func = notify_cb;
+	params.user_data = (void *)shell;
+
+	bt_gatt_notify_cb(NULL, &params);
+
+	return 0;
+}
+
+static struct bt_uuid_128 met_svc_uuid = BT_UUID_INIT_128(
+	0x01, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static const struct bt_uuid_128 met_char_uuid = BT_UUID_INIT_128(
+	0x02, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
+	0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
+
+static uint8_t met_char_value[CHAR_SIZE_MAX] = {
+	'M', 'e', 't', 'r', 'i', 'c', 's' };
+
+static ssize_t read_met(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			void *buf, uint16_t len, uint16_t offset)
+{
+	const char *value = attr->user_data;
+	uint16_t value_len;
+
+	value_len = MIN(strlen(value), CHAR_SIZE_MAX);
+
+	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
+				 value_len);
+}
+
+static ssize_t write_met(struct bt_conn *conn, const struct bt_gatt_attr *attr,
+			 const void *buf, uint16_t len, uint16_t offset,
+			 uint8_t flags)
+{
+	uint8_t *value = attr->user_data;
+
+	if (offset + len > sizeof(met_char_value)) {
+		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
+	}
+
+	memcpy(value + offset, buf, len);
+
+	update_write_stats(len);
+
+	return len;
+}
+
+static struct bt_gatt_attr met_attrs[] = {
+	BT_GATT_PRIMARY_SERVICE(&met_svc_uuid),
+
+	BT_GATT_CHARACTERISTIC(&met_char_uuid.uuid,
+			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
+			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
+			       read_met, write_met, met_char_value),
+};
+
+static struct bt_gatt_service met_svc = BT_GATT_SERVICE(met_attrs);
+
+static int cmd_metrics(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err = 0;
+
+	if (argc < 2) {
+		print_write_stats();
+		return 0;
+	}
+
+	if (!strcmp(argv[1], "on")) {
+		shell_print(shell, "Registering GATT metrics test Service.");
+		err = bt_gatt_service_register(&met_svc);
+	} else if (!strcmp(argv[1], "off")) {
+		shell_print(shell, "Unregistering GATT metrics test Service.");
+		err = bt_gatt_service_unregister(&met_svc);
+	} else {
+		shell_error(shell, "Incorrect value: %s", argv[1]);
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!err) {
+		shell_print(shell, "GATT write cmd metrics %s.", argv[1]);
+	}
+
+	return err;
+}
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+
+static uint8_t get_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+		      void *user_data)
+{
+	struct shell *shell = user_data;
+	uint8_t buf[256];
+	ssize_t ret;
+	char str[BT_UUID_STR_LEN];
+
+	bt_uuid_to_str(attr->uuid, str, sizeof(str));
+	shell_print(shell, "attr %p uuid %s perm 0x%02x", attr, str,
+		    attr->perm);
+
+	if (!attr->read) {
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	ret = attr->read(NULL, attr, (void *)buf, sizeof(buf), 0);
+	if (ret < 0) {
+		shell_print(shell, "Failed to read: %d", ret);
+		return BT_GATT_ITER_STOP;
+	}
+
+	shell_hexdump(shell, buf, ret);
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t start, end;
+
+	start = strtoul(argv[1], NULL, 16);
+	end = start;
+
+	if (argc > 2) {
+		end = strtoul(argv[2], NULL, 16);
+	}
+
+	bt_gatt_foreach_attr(start, end, get_cb, (void *)shell);
+
+	return 0;
+}
+
+struct set_data {
+	const struct shell *shell;
+	size_t argc;
+	char **argv;
+	int err;
+};
+
+static uint8_t set_cb(const struct bt_gatt_attr *attr, uint16_t handle,
+		      void *user_data)
+{
+	struct set_data *data = user_data;
+	uint8_t buf[256];
+	size_t i;
+	ssize_t ret;
+
+	if (!attr->write) {
+		shell_error(data->shell, "Write not supported");
+		data->err = -ENOENT;
+		return BT_GATT_ITER_CONTINUE;
+	}
+
+	for (i = 0; i < data->argc; i++) {
+		buf[i] = strtoul(data->argv[i], NULL, 16);
+	}
+
+	ret = attr->write(NULL, attr, (void *)buf, i, 0, 0);
+	if (ret < 0) {
+		data->err = ret;
+		shell_error(data->shell, "Failed to write: %d", ret);
+		return BT_GATT_ITER_STOP;
+	}
+
+	return BT_GATT_ITER_CONTINUE;
+}
+
+static int cmd_set(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t handle;
+	struct set_data data;
+
+	handle = strtoul(argv[1], NULL, 16);
+
+	data.shell = shell;
+	data.argc = argc - 2;
+	data.argv = argv + 2;
+	data.err = 0;
+
+	bt_gatt_foreach_attr(handle, handle, set_cb, &data);
+
+	if (data.err < 0) {
+		return -ENOEXEC;
+	}
+
+	bt_gatt_foreach_attr(handle, handle, get_cb, (void *)shell);
+
+	return 0;
+}
+
+int cmd_att_mtu(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t mtu;
+
+	if (default_conn) {
+		mtu = bt_gatt_get_mtu(default_conn);
+		shell_print(shell, "MTU size: %d", mtu);
+	} else {
+		shell_print(shell, "No default connection");
+	}
+
+	return 0;
+}
+
+#define HELP_NONE "[none]"
+#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
+
+SHELL_STATIC_SUBCMD_SET_CREATE(gatt_cmds,
+#if defined(CONFIG_BT_GATT_CLIENT)
+	SHELL_CMD_ARG(discover, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(discover-characteristic, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(discover-descriptor, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(discover-include, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(discover-primary, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(discover-secondary, NULL,
+		      "[UUID] [start handle] [end handle]", cmd_discover, 1, 3),
+	SHELL_CMD_ARG(exchange-mtu, NULL, HELP_NONE, cmd_exchange_mtu, 1, 0),
+	SHELL_CMD_ARG(read, NULL, "<handle> [offset]", cmd_read, 2, 1),
+	SHELL_CMD_ARG(read-uuid, NULL, "<UUID> [start handle] [end handle]",
+		      cmd_read_uuid, 2, 2),
+	SHELL_CMD_ARG(read-multiple, NULL, "<handle 1> <handle 2> ...",
+		      cmd_mread, 2, -1),
+	SHELL_CMD_ARG(signed-write, NULL, "<handle> <data> [length] [repeat]",
+		      cmd_write_without_rsp, 3, 2),
+	SHELL_CMD_ARG(subscribe, NULL, "<CCC handle> <value handle> [ind]",
+		      cmd_subscribe, 3, 1),
+	SHELL_CMD_ARG(resubscribe, NULL, HELP_ADDR_LE" <CCC handle> "
+		      "<value handle> [ind]", cmd_resubscribe, 5, 1),
+	SHELL_CMD_ARG(write, NULL, "<handle> <offset> <data> [length]",
+		      cmd_write, 4, 1),
+	SHELL_CMD_ARG(write-without-response, NULL,
+		      "<handle> <data> [length] [repeat]",
+		      cmd_write_without_rsp, 3, 2),
+	SHELL_CMD_ARG(write-without-response-cb, NULL,
+		      "<handle> <data> [length] [repeat]",
+		      cmd_write_without_rsp, 3, 2),
+	SHELL_CMD_ARG(unsubscribe, NULL, HELP_NONE, cmd_unsubscribe, 1, 0),
+#endif /* CONFIG_BT_GATT_CLIENT */
+	SHELL_CMD_ARG(get, NULL, "<start handle> [end handle]", cmd_get, 2, 1),
+	SHELL_CMD_ARG(set, NULL, "<handle> [data...]", cmd_set, 2, 255),
+	SHELL_CMD_ARG(show-db, NULL, "[uuid] [num_matches]", cmd_show_db, 1, 2),
+	SHELL_CMD_ARG(att_mtu, NULL, "Output ATT MTU size", cmd_att_mtu, 1, 0),
+#if defined(CONFIG_BT_GATT_DYNAMIC_DB)
+	SHELL_CMD_ARG(metrics, NULL, "[value: on, off]", cmd_metrics, 1, 1),
+	SHELL_CMD_ARG(register, NULL,
+		      "register pre-predefined test service",
+		      cmd_register_test_svc, 1, 0),
+	SHELL_CMD_ARG(unregister, NULL,
+		      "unregister pre-predefined test service",
+		      cmd_unregister_test_svc, 1, 0),
+	SHELL_CMD_ARG(notify, NULL, "[data]", cmd_notify, 1, 1),
+#endif /* CONFIG_BT_GATT_DYNAMIC_DB */
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_gatt(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -EINVAL;
+}
+
+SHELL_CMD_ARG_REGISTER(gatt, &gatt_cmds, "Bluetooth GATT shell commands",
+		       cmd_gatt, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.h	(working copy)
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int cmd_mesh_adv(const struct shell *shell, size_t argc, char *argv[]);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/hci.c	(working copy)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2017-2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <zephyr.h>
+#include <shell/shell.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_vs.h>
+#include <bluetooth/conn.h>
+
+#include "../host/hci_core.h"
+
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+int cmd_mesh_adv(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct net_buf *buf;
+	int err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (!strcmp(argv[1], "on")) {
+		struct bt_hci_cp_mesh_advertise *cp;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_VS_MESH,
+					sizeof(struct bt_hci_cp_mesh) +
+					sizeof(*cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		net_buf_add_u8(buf, BT_HCI_OC_MESH_ADVERTISE);
+
+		/* TODO: fetch and fill cmdline params */
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->adv_slot = 0U;
+		cp->own_addr_type = 0x01;
+		memset(&cp->random_addr, 0, sizeof(bt_addr_t));
+		cp->ch_map = 0x07;
+		cp->tx_power = 0;
+		cp->min_tx_delay = 0U;
+		cp->max_tx_delay = 0x32;
+		cp->retx_count = 0x07;
+		cp->retx_interval = 0x00;
+		cp->scan_delay = 0x0a;
+		cp->scan_duration = sys_cpu_to_le16(0x0064);
+		cp->scan_filter = 0x00;
+		cp->data_len = 0U;
+		memset(cp->data, 0, sizeof(cp->data));
+	} else if (!strcmp(argv[1], "off")) {
+		struct bt_hci_cp_mesh_advertise_cancel *cp;
+
+		buf = bt_hci_cmd_create(BT_HCI_OP_VS_MESH,
+					sizeof(struct bt_hci_cp_mesh) +
+					sizeof(*cp));
+		if (!buf) {
+			return -ENOBUFS;
+		}
+
+		net_buf_add_u8(buf, BT_HCI_OC_MESH_ADVERTISE_CANCEL);
+
+		cp = net_buf_add(buf, sizeof(*cp));
+		cp->adv_slot = 0U;
+	} else {
+		return -EINVAL;
+	}
+
+	err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_MESH, buf, NULL);
+
+	return err;
+}
+#endif /* CONFIG_BT_HCI_MESH_EXT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/iso.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/iso.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/iso.c	(working copy)
@@ -0,0 +1,256 @@
+/** @file
+ *  @brief Bluetooth Audio shell
+ *
+ */
+
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <zephyr.h>
+#include <shell/shell.h>
+#include <sys/printk.h>
+#include <sys/byteorder.h>
+#include <sys/util.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/iso.h>
+
+#include "bt.h"
+
+static void iso_recv(struct bt_iso_chan *chan, struct net_buf *buf)
+{
+	printk("Incoming data channel %p len %u\n", chan, buf->len);
+}
+
+static void iso_connected(struct bt_iso_chan *chan)
+{
+	printk("ISO Channel %p connected\n", chan);
+}
+
+static void iso_disconnected(struct bt_iso_chan *chan)
+{
+	printk("ISO Channel %p disconnected\n", chan);
+}
+
+static struct bt_iso_chan_ops iso_ops = {
+	.recv		= iso_recv,
+	.connected	= iso_connected,
+	.disconnected	= iso_disconnected,
+};
+
+static struct bt_iso_chan_qos iso_qos = {
+	.sca = 0x07,
+};
+
+static struct bt_iso_chan iso_chan = {
+	.ops = &iso_ops,
+	.qos = &iso_qos,
+};
+
+static int iso_accept(struct bt_conn *conn, struct bt_iso_chan **chan)
+{
+	printk("Incoming conn %p\n", conn);
+
+	if (iso_chan.conn) {
+		printk("No channels available\n");
+		return -ENOMEM;
+	}
+
+	*chan = &iso_chan;
+
+	return 0;
+}
+
+struct bt_iso_server iso_server = {
+	.sec_level = BT_SECURITY_L1,
+	.accept = iso_accept,
+};
+
+static int cmd_listen(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	if (argc > 1) {
+		iso_server.sec_level = *argv[1] - '0';
+	}
+
+	err = bt_iso_server_register(&iso_server);
+	if (err) {
+		shell_error(shell, "Unable to register ISO cap (err %d)",
+			    err);
+	}
+
+	return err;
+}
+
+static int cmd_bind(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_conn *conns[1];
+	struct bt_iso_chan *chans[1];
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return 0;
+	}
+
+	if (iso_chan.conn) {
+		shell_error(shell, "Already bound");
+		return 0;
+	}
+
+	conns[0] = default_conn;
+	chans[0] = &iso_chan;
+
+	if (argc > 1) {
+		chans[0]->qos->dir = strtol(argv[1], NULL, 0);
+	}
+
+	if (argc > 2) {
+		chans[0]->qos->interval = strtol(argv[2], NULL, 0);
+	}
+
+	if (argc > 3) {
+		chans[0]->qos->packing = strtol(argv[3], NULL, 0);
+	}
+
+	if (argc > 4) {
+		chans[0]->qos->framing = strtol(argv[4], NULL, 0);
+	}
+
+	if (argc > 5) {
+		chans[0]->qos->latency = strtol(argv[5], NULL, 0);
+	}
+
+	if (argc > 6) {
+		chans[0]->qos->sdu = strtol(argv[6], NULL, 0);
+	}
+
+	if (argc > 7) {
+		chans[0]->qos->phy = strtol(argv[7], NULL, 0);
+	}
+
+	if (argc > 8) {
+		chans[0]->qos->rtn = strtol(argv[8], NULL, 0);
+	}
+
+	err = bt_iso_chan_bind(conns, 1, chans);
+	if (err) {
+		shell_error(shell, "Unable to bind (err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "ISO Channel bound");
+
+	return 0;
+}
+
+static int cmd_connect(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct bt_iso_chan *chans[1];
+	int err;
+
+	if (!iso_chan.conn) {
+		shell_error(shell, "Not bound");
+		return 0;
+	}
+
+	chans[0] = &iso_chan;
+
+	err = bt_iso_chan_connect(chans, 1);
+	if (err) {
+		shell_error(shell, "Unable to connect (err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "ISO Connect pending...");
+
+	return 0;
+}
+
+#define DATA_MTU CONFIG_BT_ISO_TX_MTU
+NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, NULL);
+
+static int cmd_send(const struct shell *shell, size_t argc, char *argv[])
+{
+	static uint8_t buf_data[DATA_MTU] = { [0 ... (DATA_MTU - 1)] = 0xff };
+	int ret, len, count = 1;
+	struct net_buf *buf;
+
+	if (argc > 1) {
+		count = strtoul(argv[1], NULL, 10);
+	}
+
+	if (!iso_chan.conn) {
+		shell_error(shell, "Not bound");
+		return 0;
+	}
+
+	len = MIN(iso_chan.qos->sdu, DATA_MTU - BT_ISO_CHAN_SEND_RESERVE);
+
+	while (count--) {
+		buf = net_buf_alloc(&tx_pool, K_FOREVER);
+		net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
+
+		net_buf_add_mem(buf, buf_data, len);
+		ret = bt_iso_chan_send(&iso_chan, buf);
+		if (ret < 0) {
+			shell_print(shell, "Unable to send: %d", -ret);
+			net_buf_unref(buf);
+			return -ENOEXEC;
+		}
+	}
+
+	shell_print(shell, "ISO sending...");
+
+	return 0;
+}
+
+static int cmd_disconnect(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	int err;
+
+	err = bt_iso_chan_disconnect(&iso_chan);
+	if (err) {
+		shell_error(shell, "Unable to disconnect (err %d)", err);
+		return 0;
+	}
+
+	shell_print(shell, "ISO Disconnect pending...");
+
+	return 0;
+}
+
+SHELL_STATIC_SUBCMD_SET_CREATE(iso_cmds,
+	SHELL_CMD_ARG(bind, NULL, "[dir] [interval] [packing] [framing] "
+		      "[latency] [sdu] [phy] [rtn]", cmd_bind, 1, 8),
+	SHELL_CMD_ARG(connect, NULL, "Connect ISO Channel", cmd_connect, 1, 0),
+	SHELL_CMD_ARG(listen, NULL, "[security level]", cmd_listen, 1, 1),
+	SHELL_CMD_ARG(send, NULL, "Send to ISO Channel", cmd_send, 1, 0),
+	SHELL_CMD_ARG(disconnect, NULL, "Disconnect ISO Channel",
+		      cmd_disconnect, 1, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_iso(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc > 1) {
+		shell_error(shell, "%s unknown parameter: %s",
+			    argv[0], argv[1]);
+	} else {
+		shell_error(shell, "%s Missing subcommand", argv[0]);
+	}
+
+	return -ENOEXEC;
+}
+
+SHELL_CMD_ARG_REGISTER(iso, &iso_cmds, "Bluetooth ISO shell commands",
+		       cmd_iso, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/l2cap.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/l2cap.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/l2cap.c	(working copy)
@@ -0,0 +1,456 @@
+/** @file
+ * @brief Bluetooth shell module
+ *
+ * Provide some Bluetooth shell commands that can be useful to applications.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+
+#include <shell/shell.h>
+
+#include "bt.h"
+
+#define CREDITS			10
+#define DATA_MTU		(23 * CREDITS)
+
+#define L2CAP_POLICY_NONE		0x00
+#define L2CAP_POLICY_WHITELIST		0x01
+#define L2CAP_POLICY_16BYTE_KEY		0x02
+
+NET_BUF_POOL_FIXED_DEFINE(data_tx_pool, 1, DATA_MTU, NULL);
+NET_BUF_POOL_FIXED_DEFINE(data_rx_pool, 1, DATA_MTU, NULL);
+
+static uint8_t l2cap_policy;
+static struct bt_conn *l2cap_whitelist[CONFIG_BT_MAX_CONN];
+
+static uint32_t l2cap_rate;
+static uint32_t l2cap_recv_delay_ms;
+static K_FIFO_DEFINE(l2cap_recv_fifo);
+struct l2ch {
+	struct k_delayed_work recv_work;
+	struct bt_l2cap_le_chan ch;
+};
+#define L2CH_CHAN(_chan) CONTAINER_OF(_chan, struct l2ch, ch.chan)
+#define L2CH_WORK(_work) CONTAINER_OF(_work, struct l2ch, recv_work)
+#define L2CAP_CHAN(_chan) _chan->ch.chan
+
+static bool metrics;
+
+static int l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	static uint32_t len;
+	static uint32_t cycle_stamp;
+	uint32_t delta;
+
+	delta = k_cycle_get_32() - cycle_stamp;
+	delta = (uint32_t)k_cyc_to_ns_floor64(delta);
+
+	/* if last data rx-ed was greater than 1 second in the past,
+	 * reset the metrics.
+	 */
+	if (delta > 1000000000) {
+		len = 0U;
+		l2cap_rate = 0U;
+		cycle_stamp = k_cycle_get_32();
+	} else {
+		len += buf->len;
+		l2cap_rate = ((uint64_t)len << 3) * 1000000000U / delta;
+	}
+
+	return 0;
+}
+
+static void l2cap_recv_cb(struct k_work *work)
+{
+	struct l2ch *c = L2CH_WORK(work);
+	struct net_buf *buf;
+
+	while ((buf = net_buf_get(&l2cap_recv_fifo, K_NO_WAIT))) {
+		shell_print(ctx_shell, "Confirming reception");
+		bt_l2cap_chan_recv_complete(&c->ch.chan, buf);
+	}
+}
+
+static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct l2ch *l2ch = L2CH_CHAN(chan);
+
+	if (metrics) {
+		return l2cap_recv_metrics(chan, buf);
+	}
+
+	shell_print(ctx_shell, "Incoming data channel %p len %u", chan,
+		    buf->len);
+
+	if (buf->len) {
+		shell_hexdump(ctx_shell, buf->data, buf->len);
+	}
+
+	if (l2cap_recv_delay_ms > 0) {
+		/* Submit work only if queue is empty */
+		if (k_fifo_is_empty(&l2cap_recv_fifo)) {
+			shell_print(ctx_shell, "Delaying response in %u ms...",
+				    l2cap_recv_delay_ms);
+			k_delayed_work_submit(&l2ch->recv_work,
+					      K_MSEC(l2cap_recv_delay_ms));
+		}
+		net_buf_put(&l2cap_recv_fifo, buf);
+		return -EINPROGRESS;
+	}
+
+	return 0;
+}
+
+static void l2cap_sent(struct bt_l2cap_chan *chan)
+{
+	shell_print(ctx_shell, "Outgoing data channel %p transmitted", chan);
+}
+
+static void l2cap_status(struct bt_l2cap_chan *chan, atomic_t *status)
+{
+	shell_print(ctx_shell, "Channel %p status %u", chan, status);
+}
+
+static void l2cap_connected(struct bt_l2cap_chan *chan)
+{
+	struct l2ch *c = L2CH_CHAN(chan);
+
+	k_delayed_work_init(&c->recv_work, l2cap_recv_cb);
+
+	shell_print(ctx_shell, "Channel %p connected", chan);
+}
+
+static void l2cap_disconnected(struct bt_l2cap_chan *chan)
+{
+	shell_print(ctx_shell, "Channel %p disconnected", chan);
+}
+
+static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
+{
+	/* print if metrics is disabled */
+	if (!metrics) {
+		shell_print(ctx_shell, "Channel %p requires buffer", chan);
+	}
+
+	return net_buf_alloc(&data_rx_pool, K_FOREVER);
+}
+
+static const struct bt_l2cap_chan_ops l2cap_ops = {
+	.alloc_buf	= l2cap_alloc_buf,
+	.recv		= l2cap_recv,
+	.sent		= l2cap_sent,
+	.status		= l2cap_status,
+	.connected	= l2cap_connected,
+	.disconnected	= l2cap_disconnected,
+};
+
+static struct l2ch l2ch_chan = {
+	.ch.chan.ops	= &l2cap_ops,
+	.ch.rx.mtu	= DATA_MTU,
+};
+
+static void l2cap_whitelist_remove(struct bt_conn *conn, uint8_t reason)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(l2cap_whitelist); i++) {
+		if (l2cap_whitelist[i] == conn) {
+			bt_conn_unref(l2cap_whitelist[i]);
+			l2cap_whitelist[i] = NULL;
+		}
+	}
+}
+
+static struct bt_conn_cb l2cap_conn_callbacks = {
+	.disconnected = l2cap_whitelist_remove,
+};
+
+static int l2cap_accept_policy(struct bt_conn *conn)
+{
+	int i;
+
+	if (l2cap_policy == L2CAP_POLICY_16BYTE_KEY) {
+		uint8_t enc_key_size = bt_conn_enc_key_size(conn);
+
+		if (enc_key_size && enc_key_size < BT_ENC_KEY_SIZE_MAX) {
+			return -EPERM;
+		}
+	} else if (l2cap_policy == L2CAP_POLICY_WHITELIST) {
+		for (i = 0; i < ARRAY_SIZE(l2cap_whitelist); i++) {
+			if (l2cap_whitelist[i] == conn) {
+				return 0;
+			}
+		}
+
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	int err;
+
+	shell_print(ctx_shell, "Incoming conn %p", conn);
+
+	err = l2cap_accept_policy(conn);
+	if (err < 0) {
+		return err;
+	}
+
+	if (l2ch_chan.ch.chan.conn) {
+		shell_print(ctx_shell, "No channels available");
+		return -ENOMEM;
+	}
+
+	*chan = &l2ch_chan.ch.chan;
+
+	return 0;
+}
+
+static struct bt_l2cap_server server = {
+	.accept		= l2cap_accept,
+};
+
+static int cmd_register(const struct shell *shell, size_t argc, char *argv[])
+{
+	const char *policy;
+
+	if (server.psm) {
+		shell_error(shell, "Already registered");
+		return -ENOEXEC;
+	}
+
+	server.psm = strtoul(argv[1], NULL, 16);
+
+	if (argc > 2) {
+		server.sec_level = strtoul(argv[2], NULL, 10);
+	}
+
+	if (argc > 3) {
+		policy = argv[3];
+
+		if (!strcmp(policy, "whitelist")) {
+			l2cap_policy = L2CAP_POLICY_WHITELIST;
+		} else if (!strcmp(policy, "16byte_key")) {
+			l2cap_policy = L2CAP_POLICY_16BYTE_KEY;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	if (bt_l2cap_server_register(&server) < 0) {
+		shell_error(shell, "Unable to register psm");
+		server.psm = 0U;
+		return -ENOEXEC;
+	} else {
+		bt_conn_cb_register(&l2cap_conn_callbacks);
+
+		shell_print(shell, "L2CAP psm %u sec_level %u registered",
+			    server.psm, server.sec_level);
+	}
+
+	return 0;
+}
+
+static int cmd_connect(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t psm;
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	if (l2ch_chan.ch.chan.conn) {
+		shell_error(shell, "Channel already in use");
+		return -ENOEXEC;
+	}
+
+	psm = strtoul(argv[1], NULL, 16);
+
+	if (argc > 2) {
+		int sec;
+
+		sec = *argv[2] - '0';
+
+		l2ch_chan.ch.chan.required_sec_level = sec;
+	}
+
+	err = bt_l2cap_chan_connect(default_conn, &l2ch_chan.ch.chan, psm);
+	if (err < 0) {
+		shell_error(shell, "Unable to connect to psm %u (err %d)", psm,
+			    err);
+	} else {
+		shell_print(shell, "L2CAP connection pending");
+	}
+
+	return err;
+}
+
+static int cmd_disconnect(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_l2cap_chan_disconnect(&l2ch_chan.ch.chan);
+	if (err) {
+		shell_print(shell, "Unable to disconnect: %u", -err);
+	}
+
+	return err;
+}
+
+static int cmd_send(const struct shell *shell, size_t argc, char *argv[])
+{
+	static uint8_t buf_data[DATA_MTU] = { [0 ... (DATA_MTU - 1)] = 0xff };
+	int ret, len, count = 1;
+	struct net_buf *buf;
+
+	if (argc > 1) {
+		count = strtoul(argv[1], NULL, 10);
+	}
+
+	len = MIN(l2ch_chan.ch.tx.mtu, DATA_MTU - BT_L2CAP_CHAN_SEND_RESERVE);
+
+	while (count--) {
+		buf = net_buf_alloc(&data_tx_pool, K_FOREVER);
+		net_buf_reserve(buf, BT_L2CAP_CHAN_SEND_RESERVE);
+
+		net_buf_add_mem(buf, buf_data, len);
+		ret = bt_l2cap_chan_send(&l2ch_chan.ch.chan, buf);
+		if (ret < 0) {
+			shell_print(shell, "Unable to send: %d", -ret);
+			net_buf_unref(buf);
+			return -ENOEXEC;
+		}
+	}
+
+	return 0;
+}
+
+static int cmd_recv(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argc > 1) {
+		l2cap_recv_delay_ms = strtoul(argv[1], NULL, 10);
+	} else {
+		shell_print(shell, "l2cap receive delay: %u ms",
+			    l2cap_recv_delay_ms);
+	}
+
+	return 0;
+}
+
+static int cmd_metrics(const struct shell *shell, size_t argc, char *argv[])
+{
+	const char *action;
+
+	if (argc < 2) {
+		shell_print(shell, "l2cap rate: %u bps.", l2cap_rate);
+
+		return 0;
+	}
+
+	action = argv[1];
+
+	if (!strcmp(action, "on")) {
+		metrics = true;
+	} else if (!strcmp(action, "off")) {
+		metrics = false;
+	} else {
+		shell_help(shell);
+		return 0;
+	}
+
+	shell_print(shell, "l2cap metrics %s.", action);
+	return 0;
+}
+
+static int cmd_whitelist_add(const struct shell *shell, size_t argc, char *argv[])
+{
+	int i;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(l2cap_whitelist); i++) {
+		if (l2cap_whitelist[i] == NULL) {
+			l2cap_whitelist[i] = bt_conn_ref(default_conn);
+			return 0;
+		}
+	}
+
+	return -ENOMEM;
+}
+
+static int cmd_whitelist_remove(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return 0;
+	}
+
+	l2cap_whitelist_remove(default_conn, 0);
+
+	return 0;
+}
+
+#define HELP_NONE "[none]"
+
+SHELL_STATIC_SUBCMD_SET_CREATE(whitelist_cmds,
+	SHELL_CMD_ARG(add, NULL, HELP_NONE, cmd_whitelist_add, 1, 0),
+	SHELL_CMD_ARG(remove, NULL, HELP_NONE, cmd_whitelist_remove, 1, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(l2cap_cmds,
+	SHELL_CMD_ARG(connect, NULL, "<psm> [sec_level]", cmd_connect, 2, 1),
+	SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 0),
+	SHELL_CMD_ARG(metrics, NULL, "<value on, off>", cmd_metrics, 2, 0),
+	SHELL_CMD_ARG(recv, NULL, "[delay (in miliseconds)", cmd_recv, 1, 1),
+	SHELL_CMD_ARG(register, NULL, "<psm> [sec_level] "
+		      "[policy: whitelist, 16byte_key]", cmd_register, 2, 2),
+	SHELL_CMD_ARG(send, NULL, "<number of packets>", cmd_send, 2, 0),
+	SHELL_CMD_ARG(whitelist, &whitelist_cmds, HELP_NONE, NULL, 1, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_l2cap(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -ENOEXEC;
+}
+
+SHELL_CMD_ARG_REGISTER(l2cap, &l2cap_cmds, "Bluetooth L2CAP shell commands",
+		       cmd_l2cap, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.h	(working copy)
@@ -0,0 +1,24 @@
+/** @file
+ * @brief Bluetooth Link Layer shell functions
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2017 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __LL_H
+#define __LL_H
+
+int cmd_ll_addr_get(const struct shell *shell, size_t argc, char *argv[]);
+
+int cmd_advx(const struct shell *shell, size_t  argc, char *argv[]);
+int cmd_scanx(const struct shell *shell, size_t  argc, char *argv[]);
+
+int cmd_test_tx(const struct shell *shell, size_t  argc, char *argv[]);
+int cmd_test_rx(const struct shell *shell, size_t  argc, char *argv[]);
+int cmd_test_end(const struct shell *shell, size_t  argc, char *argv[]);
+#endif /* __LL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ll.c	(working copy)
@@ -0,0 +1,355 @@
+/** @file
+ * @brief Bluetooth Link Layer functions
+ *
+ */
+
+/*
+ * Copyright (c) 2017-2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <zephyr.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+
+#include <shell/shell.h>
+
+#include "../controller/util/memq.h"
+#include "../controller/include/ll.h"
+
+#include "bt.h"
+
+int cmd_ll_addr_get(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t addr_type;
+	const char *str_type;
+	bt_addr_t addr;
+	char str_addr[BT_ADDR_STR_LEN];
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	str_type = argv[1];
+	if (!strcmp(str_type, "random")) {
+		addr_type = 1U;
+	} else if (!strcmp(str_type, "public")) {
+		addr_type = 0U;
+	} else {
+		return -EINVAL;
+	}
+
+	(void)ll_addr_get(addr_type, addr.val);
+	bt_addr_to_str(&addr, str_addr, sizeof(str_addr));
+
+	shell_print(shell, "Current %s address: %s", str_type, str_addr);
+
+	return 0;
+}
+
+#if defined(CONFIG_BT_CTLR_DTM)
+#include "../controller/ll_sw/ll_test.h"
+
+int cmd_test_tx(const struct shell *shell, size_t  argc, char *argv[])
+{
+	uint8_t chan, len, type, phy;
+	uint32_t err;
+
+	if (argc < 5) {
+		return -EINVAL;
+	}
+
+	chan = strtoul(argv[1], NULL, 16);
+	len  = strtoul(argv[2], NULL, 16);
+	type = strtoul(argv[3], NULL, 16);
+	phy  = strtoul(argv[4], NULL, 16);
+
+	err = ll_test_tx(chan, len, type, phy);
+	if (err) {
+		return -EINVAL;
+	}
+
+	shell_print(shell, "test_tx...");
+
+	return 0;
+}
+
+int cmd_test_rx(const struct shell *shell, size_t  argc, char *argv[])
+{
+	uint8_t chan, phy, mod_idx;
+	uint32_t err;
+
+	if (argc < 4) {
+		return -EINVAL;
+	}
+
+	chan    = strtoul(argv[1], NULL, 16);
+	phy     = strtoul(argv[2], NULL, 16);
+	mod_idx = strtoul(argv[3], NULL, 16);
+
+	err = ll_test_rx(chan, phy, mod_idx);
+	if (err) {
+		return -EINVAL;
+	}
+
+	shell_print(shell, "test_rx...");
+
+	return 0;
+}
+
+int cmd_test_end(const struct shell *shell, size_t  argc, char *argv[])
+{
+	uint16_t num_rx;
+	uint32_t err;
+
+	err = ll_test_end(&num_rx);
+	if (err) {
+		return -EINVAL;
+	}
+
+	shell_print(shell, "num_rx= %u.", num_rx);
+
+	return 0;
+}
+#endif /* CONFIG_BT_CTLR_DTM */
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+#include "../controller/ll_sw/lll.h"
+
+#if defined(CONFIG_BT_BROADCASTER)
+#define OWN_ADDR_TYPE 1
+#define PEER_ADDR_TYPE 0
+#define PEER_ADDR NULL
+#define ADV_CHAN_MAP 0x07
+#define FILTER_POLICY 0x00
+#define ADV_TX_PWR NULL
+#define ADV_SEC_SKIP 0
+#define ADV_PHY_S 0x01
+#define ADV_SID 0
+#define SCAN_REQ_NOT 0
+
+#define AD_OP 0x03
+#define AD_FRAG_PREF 0x00
+
+static const struct bt_data adv_data[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
+	};
+
+int cmd_advx(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint16_t adv_interval = 0x20;
+	uint16_t handle = 0U;
+	uint16_t evt_prop = 0U;
+	uint8_t adv_type;
+	uint8_t enable;
+	uint8_t ad = 0;
+	uint8_t phy_p;
+	int32_t err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (argc > 1) {
+		if (!strcmp(argv[1], "on")) {
+			adv_type = 0x05; /* Adv. Ext. */
+			enable = 1U;
+		} else if (!strcmp(argv[1], "hdcd")) {
+			adv_type = 0x01; /* Directed */
+			adv_interval = 0U; /* High Duty Cycle */
+			phy_p = BIT(0);
+			enable = 1U;
+			goto do_enable;
+		} else if (!strcmp(argv[1], "ldcd")) {
+			adv_type = 0x04; /* Directed */
+			enable = 1U;
+		} else if (!strcmp(argv[1], "off")) {
+			enable = 0U;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	phy_p = BIT(0);
+
+	if (argc > 2) {
+		if (!strcmp(argv[2], "coded")) {
+			phy_p = BIT(2);
+		} else if (!strcmp(argv[2], "anon")) {
+			evt_prop |= BIT(5);
+		} else if (!strcmp(argv[2], "txp")) {
+			evt_prop |= BIT(6);
+		} else if (!strcmp(argv[2], "ad")) {
+			ad = 1;
+		} else {
+			handle = strtoul(argv[2], NULL, 16);
+			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (argc > 3) {
+		if (!strcmp(argv[3], "anon")) {
+			evt_prop |= BIT(5);
+		} else if (!strcmp(argv[3], "txp")) {
+			evt_prop |= BIT(6);
+		} else if (!strcmp(argv[3], "ad")) {
+			ad = 1;
+		} else {
+			handle = strtoul(argv[3], NULL, 16);
+			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (argc > 4) {
+		if (!strcmp(argv[4], "txp")) {
+			evt_prop |= BIT(6);
+		} else if (!strcmp(argv[4], "ad")) {
+			ad = 1;
+		} else {
+			handle = strtoul(argv[4], NULL, 16);
+			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (argc > 5) {
+		if (!strcmp(argv[5], "ad")) {
+			ad = 1;
+		} else {
+			handle = strtoul(argv[5], NULL, 16);
+			if (handle >= CONFIG_BT_CTLR_ADV_SET) {
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (argc > 6) {
+		handle = strtoul(argv[6], NULL, 16);
+		if (handle >= CONFIG_BT_CTLR_ADV_SET) {
+			return -EINVAL;
+		}
+	}
+
+	if (!enable) {
+		goto disable;
+	}
+
+do_enable:
+	shell_print(shell, "adv param set...");
+	err = ll_adv_params_set(handle, evt_prop, adv_interval, adv_type,
+				OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR,
+				ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR,
+				phy_p, ADV_SEC_SKIP, ADV_PHY_S, ADV_SID,
+				SCAN_REQ_NOT);
+	if (err) {
+		goto exit;
+	}
+
+	if (ad) {
+		shell_print(shell, "ad data set...");
+		err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF,
+					     ARRAY_SIZE(adv_data),
+					     (void *)adv_data);
+		if (err) {
+			goto exit;
+		}
+	}
+
+disable:
+	shell_print(shell, "adv enable (%u)...", enable);
+#if defined(CONFIG_BT_HCI_MESH_EXT)
+	err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0);
+#else /* !CONFIG_BT_HCI_MESH_EXT */
+	err = ll_adv_enable(handle, enable, 0, 0);
+#endif /* !CONFIG_BT_HCI_MESH_EXT */
+	if (err) {
+		goto exit;
+	}
+
+	if (!enable) {
+		err = ll_adv_aux_set_remove(handle);
+		if (err) {
+			goto exit;
+		}
+	}
+
+exit:
+	shell_print(shell, "done (err= %d).", err);
+
+	return 0;
+}
+#endif /* CONFIG_BT_BROADCASTER */
+
+#if defined(CONFIG_BT_OBSERVER)
+#define SCAN_INTERVAL 0x0004
+#define SCAN_WINDOW 0x0004
+#define SCAN_OWN_ADDR_TYPE 1
+#define SCAN_FILTER_POLICY 0
+
+int cmd_scanx(const struct shell *shell, size_t  argc, char *argv[])
+{
+	uint8_t type = 0U;
+	uint8_t enable;
+	int32_t err;
+
+	if (argc < 2) {
+		return -EINVAL;
+	}
+
+	if (argc > 1) {
+		if (!strcmp(argv[1], "on")) {
+			enable = 1U;
+			type = 1U;
+		} else if (!strcmp(argv[1], "passive")) {
+			enable = 1U;
+			type = 0U;
+		} else if (!strcmp(argv[1], "off")) {
+			enable = 0U;
+			goto disable;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	type |= BIT(1);
+
+	if (argc > 2) {
+		if (!strcmp(argv[2], "coded")) {
+			type &= BIT(0);
+			type |= BIT(3);
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	shell_print(shell, "scan param set...");
+	err = ll_scan_params_set(type, SCAN_INTERVAL, SCAN_WINDOW,
+				 SCAN_OWN_ADDR_TYPE, SCAN_FILTER_POLICY);
+	if (err) {
+		goto exit;
+	}
+
+disable:
+	shell_print(shell, "scan enable (%u)...", enable);
+	err = ll_scan_enable(enable);
+	if (err) {
+		goto exit;
+	}
+
+exit:
+	shell_print(shell, "done (err= %d).", err);
+
+	return err;
+}
+#endif /* CONFIG_BT_OBSERVER */
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/rfcomm.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/rfcomm.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/rfcomm.c	(working copy)
@@ -0,0 +1,258 @@
+/** @file
+ * @brief Bluetooth RFCOMM shell module
+ *
+ * Provide some Bluetooth shell commands that can be useful to applications.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/byteorder.h>
+#include <zephyr.h>
+
+#include <settings/settings.h>
+
+#include <bluetooth/hci.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+
+#include <shell/shell.h>
+
+#include "bt.h"
+
+#define DATA_MTU 48
+
+NET_BUF_POOL_FIXED_DEFINE(pool, 1, DATA_MTU, NULL);
+
+static struct bt_sdp_attribute spp_attrs[] = {
+	BT_SDP_NEW_SERVICE,
+	BT_SDP_LIST(
+		BT_SDP_ATTR_SVCLASS_ID_LIST,
+		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
+		BT_SDP_DATA_ELEM_LIST(
+		{
+			BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
+			BT_SDP_ARRAY_16(BT_SDP_SERIAL_PORT_SVCLASS)
+		},
+		)
+	),
+	BT_SDP_LIST(
+		BT_SDP_ATTR_PROTO_DESC_LIST,
+		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 12),
+		BT_SDP_DATA_ELEM_LIST(
+		{
+			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3),
+			BT_SDP_DATA_ELEM_LIST(
+			{
+				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
+				BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP)
+			},
+			)
+		},
+		{
+			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 5),
+			BT_SDP_DATA_ELEM_LIST(
+			{
+				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
+				BT_SDP_ARRAY_16(BT_SDP_PROTO_RFCOMM)
+			},
+			{
+				BT_SDP_TYPE_SIZE(BT_SDP_UINT8),
+				BT_SDP_ARRAY_8(BT_RFCOMM_CHAN_SPP)
+			},
+			)
+		},
+		)
+	),
+	BT_SDP_LIST(
+		BT_SDP_ATTR_PROFILE_DESC_LIST,
+		BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8),
+		BT_SDP_DATA_ELEM_LIST(
+		{
+			BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),
+			BT_SDP_DATA_ELEM_LIST(
+			{
+				BT_SDP_TYPE_SIZE(BT_SDP_UUID16),
+				BT_SDP_ARRAY_16(BT_SDP_SERIAL_PORT_SVCLASS)
+			},
+			{
+				BT_SDP_TYPE_SIZE(BT_SDP_UINT16),
+				BT_SDP_ARRAY_16(0x0102)
+			},
+			)
+		},
+		)
+	),
+	BT_SDP_SERVICE_NAME("Serial Port"),
+};
+
+static struct bt_sdp_record spp_rec = BT_SDP_RECORD(spp_attrs);
+
+static void rfcomm_recv(struct bt_rfcomm_dlc *dlci, struct net_buf *buf)
+{
+	shell_print(ctx_shell, "Incoming data dlc %p len %u", dlci, buf->len);
+}
+
+static void rfcomm_connected(struct bt_rfcomm_dlc *dlci)
+{
+	shell_print(ctx_shell, "Dlc %p connected", dlci);
+}
+
+static void rfcomm_disconnected(struct bt_rfcomm_dlc *dlci)
+{
+	shell_print(ctx_shell, "Dlc %p disconnected", dlci);
+}
+
+static struct bt_rfcomm_dlc_ops rfcomm_ops = {
+	.recv		= rfcomm_recv,
+	.connected	= rfcomm_connected,
+	.disconnected	= rfcomm_disconnected,
+};
+
+static struct bt_rfcomm_dlc rfcomm_dlc = {
+	.ops = &rfcomm_ops,
+	.mtu = 30,
+};
+
+static int rfcomm_accept(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc)
+{
+	shell_print(ctx_shell, "Incoming RFCOMM conn %p", conn);
+
+	if (rfcomm_dlc.session) {
+		shell_error(ctx_shell, "No channels available");
+		return -ENOMEM;
+	}
+
+	*dlc = &rfcomm_dlc;
+
+	return 0;
+}
+
+struct bt_rfcomm_server rfcomm_server = {
+	.accept = &rfcomm_accept,
+};
+
+static int cmd_register(const struct shell *shell, size_t argc, char *argv[])
+{
+	int ret;
+
+	if (rfcomm_server.channel) {
+		shell_error(shell, "Already registered");
+		return -ENOEXEC;
+	}
+
+	rfcomm_server.channel = BT_RFCOMM_CHAN_SPP;
+
+	ret = bt_rfcomm_server_register(&rfcomm_server);
+	if (ret < 0) {
+		shell_error(shell, "Unable to register channel %x", ret);
+		rfcomm_server.channel = 0U;
+		return -ENOEXEC;
+	} else {
+		shell_print(shell, "RFCOMM channel %u registered",
+			    rfcomm_server.channel);
+		bt_sdp_register_service(&spp_rec);
+	}
+
+	return 0;
+}
+
+static int cmd_connect(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t channel;
+	int err;
+
+	if (!default_conn) {
+		shell_error(shell, "Not connected");
+		return -ENOEXEC;
+	}
+
+	channel = strtoul(argv[1], NULL, 16);
+
+	err = bt_rfcomm_dlc_connect(default_conn, &rfcomm_dlc, channel);
+	if (err < 0) {
+		shell_error(shell, "Unable to connect to channel %d (err %u)",
+			    channel, err);
+	} else {
+		shell_print(shell, "RFCOMM connection pending");
+	}
+
+	return err;
+}
+
+static int cmd_send(const struct shell *shell, size_t argc, char *argv[])
+{
+	uint8_t buf_data[DATA_MTU] = { [0 ... (DATA_MTU - 1)] = 0xff };
+	int ret, len, count = 1;
+	struct net_buf *buf;
+
+	if (argc > 1) {
+		count = strtoul(argv[1], NULL, 10);
+	}
+
+	while (count--) {
+		buf = bt_rfcomm_create_pdu(&pool);
+		/* Should reserve one byte in tail for FCS */
+		len = MIN(rfcomm_dlc.mtu, net_buf_tailroom(buf) - 1);
+
+		net_buf_add_mem(buf, buf_data, len);
+		ret = bt_rfcomm_dlc_send(&rfcomm_dlc, buf);
+		if (ret < 0) {
+			shell_error(shell, "Unable to send: %d", -ret);
+			net_buf_unref(buf);
+			return -ENOEXEC;
+		}
+	}
+
+	return 0;
+}
+
+static int cmd_disconnect(const struct shell *shell, size_t argc, char *argv[])
+{
+	int err;
+
+	err = bt_rfcomm_dlc_disconnect(&rfcomm_dlc);
+	if (err) {
+		shell_error(shell, "Unable to disconnect: %u", -err);
+	}
+
+	return err;
+}
+
+#define HELP_NONE "[none]"
+#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
+
+SHELL_STATIC_SUBCMD_SET_CREATE(rfcomm_cmds,
+	SHELL_CMD_ARG(register, NULL, "<channel>", cmd_register, 2, 0),
+	SHELL_CMD_ARG(connect, NULL, "<channel>", cmd_connect, 2, 0),
+	SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 0),
+	SHELL_CMD_ARG(send, NULL, "<number of packets>", cmd_send, 2, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_rfcomm(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]);
+
+	return -ENOEXEC;
+}
+
+SHELL_CMD_ARG_REGISTER(rfcomm, &rfcomm_cmds, "Bluetooth RFCOMM shell commands",
+		       cmd_rfcomm, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ticker.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ticker.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/bluetooth/shell/ticker.c	(working copy)
@@ -0,0 +1,145 @@
+/** @file
+ * @brief Bluetooth Controller Ticker functions
+ *
+ */
+
+/*
+ * Copyright (c) 2017-2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/conn.h>
+
+#include <shell/shell.h>
+
+#include "../controller/util/memq.h"
+#include "../controller/util/mayfly.h"
+#include "../controller/hal/ticker.h"
+#include "../controller/ticker/ticker.h"
+
+#if defined(CONFIG_BT_MAX_CONN)
+#define TICKERS_MAX (CONFIG_BT_MAX_CONN + 2)
+#else
+#define TICKERS_MAX 2
+#endif
+
+#include "bt.h"
+
+static void ticker_op_done(uint32_t err, void *context)
+{
+	*((uint32_t volatile *)context) = err;
+}
+
+int cmd_ticker_info(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct {
+		uint8_t id;
+		uint32_t ticks_to_expire;
+	} tickers[TICKERS_MAX];
+	uint32_t ticks_to_expire;
+	uint32_t ticks_current;
+	uint8_t tickers_count;
+	uint8_t ticker_id;
+	uint8_t retry;
+	uint8_t i;
+
+	ticker_id = TICKER_NULL;
+	ticks_to_expire = 0U;
+	ticks_current = 0U;
+	tickers_count = 0U;
+	retry = 4U;
+	do {
+		uint32_t volatile err_cb = TICKER_STATUS_BUSY;
+		uint32_t ticks_previous;
+		uint32_t err;
+
+		ticks_previous = ticks_current;
+
+		err = ticker_next_slot_get(0, MAYFLY_CALL_ID_PROGRAM,
+					   &ticker_id, &ticks_current,
+					   &ticks_to_expire,
+					   ticker_op_done, (void *)&err_cb);
+		if (err == TICKER_STATUS_BUSY) {
+			while (err_cb == TICKER_STATUS_BUSY) {
+				ticker_job_sched(0, MAYFLY_CALL_ID_PROGRAM);
+			}
+		}
+
+		if ((err_cb != TICKER_STATUS_SUCCESS) ||
+		    (ticker_id == TICKER_NULL)) {
+			shell_print(shell, "Query done (0x%02x, err= %u).",
+				    ticker_id, err);
+
+			break;
+		}
+
+		if (ticks_current != ticks_previous) {
+			retry--;
+			if (!retry) {
+				shell_print(shell, "Retry again, tickers too "
+					    "busy now.");
+
+				return -EAGAIN;
+			}
+
+			if (tickers_count) {
+				tickers_count = 0U;
+
+				shell_print(shell, "Query reset, %u retries "
+					    "remaining.", retry);
+			}
+		}
+
+		tickers[tickers_count].id = ticker_id;
+		tickers[tickers_count].ticks_to_expire = ticks_to_expire;
+		tickers_count++;
+
+	} while (tickers_count < TICKERS_MAX);
+
+	shell_print(shell, "Tickers: %u.", tickers_count);
+	shell_print(shell, "Tick: %u (%uus).", ticks_current,
+	       HAL_TICKER_TICKS_TO_US(ticks_current));
+
+	if (!tickers_count) {
+		return 0;
+	}
+
+	shell_print(shell, "---------------------");
+	shell_print(shell, " id   offset   offset");
+	shell_print(shell, "      (tick)     (us)");
+	shell_print(shell, "---------------------");
+	for (i = 0U; i < tickers_count; i++) {
+		shell_print(shell, "%03u %08u %08u", tickers[i].id,
+		       tickers[i].ticks_to_expire,
+		       HAL_TICKER_TICKS_TO_US(tickers[i].ticks_to_expire));
+	}
+	shell_print(shell, "---------------------");
+
+	return 0;
+}
+
+#define HELP_NONE "[none]"
+
+SHELL_STATIC_SUBCMD_SET_CREATE(ticker_cmds,
+	SHELL_CMD_ARG(info, NULL, HELP_NONE, cmd_ticker_info, 1, 0),
+	SHELL_SUBCMD_SET_END
+);
+
+static int cmd_ticker(const struct shell *shell, size_t argc, char **argv)
+{
+	if (argc == 1) {
+		shell_help(shell);
+		/* shell returns 1 when help is printed */
+		return 1;
+	}
+
+	shell_error(shell, "%s:%s%s", argv[0], "unknown parameter: ", argv[1]);
+	return -ENOEXEC;
+}
+
+SHELL_CMD_ARG_REGISTER(ticker, &ticker_cmds, "Bluetooth Ticker shell commands",
+		       cmd_ticker, 1, 1);
Index: ModuleDemo/BLE/CM0/User/subsys/net/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/CMakeLists.txt	(working copy)
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_sources_ifdef(CONFIG_NET_BUF             buf.c)
+zephyr_library_sources_ifdef(CONFIG_NET_HOSTNAME_ENABLE hostname.c)
+
+if(CONFIG_NETWORKING)
+  add_subdirectory(l2)
+
+  if(CONFIG_NET_RAW_MODE)
+    zephyr_library_sources(ip/net_pkt.c)
+  else()
+    add_subdirectory(ip)
+  endif()
+endif()
+
+add_subdirectory(lib)
Index: ModuleDemo/BLE/CM0/User/subsys/net/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig	(working copy)
@@ -0,0 +1,93 @@
+# Net stack configuration options
+
+# Copyright (c) 2015 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menu "Networking"
+
+config NET_BUF
+	bool "Network buffer support"
+	help
+	  This option enables support for generic network protocol
+	  buffers.
+
+if NET_BUF
+
+config NET_BUF_USER_DATA_SIZE
+	int "Size of user_data available in every network buffer"
+	default 8 if (BT || NET_TCP2) && 64BIT
+	default 4
+	range 4 65535 if BT || NET_TCP2
+	range 0 65535
+	help
+	  Amount of memory reserved in each network buffer for user data. In
+	  most cases this can be left as the default value.
+
+config NET_BUF_LOG
+	bool "Network buffer logging"
+	select LOG
+	help
+	  Enable logs and checks for the generic network buffers.
+
+module = NET_BUF
+module-str = net_buf
+source "subsys/logging/Kconfig.template.log_config"
+
+if NET_BUF_LOG
+
+config NET_BUF_WARN_ALLOC_INTERVAL
+	int "Interval of Network buffer allocation warnings"
+	default 1
+	range 0 60
+	help
+	  Interval in seconds of Network buffer allocation warnings which are
+	  generated when a buffer cannot immediately be allocated with K_FOREVER
+	  which may lead to deadlocks. Setting it to 0 makes warnings to be
+	  printed only once per allocation.
+
+config NET_BUF_SIMPLE_LOG
+	bool "Network buffer memory debugging"
+	select LOG
+	help
+	  Enable extra debug logs and checks for the generic network buffers.
+
+endif # NET_BUF_LOG
+
+config NET_BUF_POOL_USAGE
+	bool "Network buffer pool usage tracking"
+	help
+	  Enable network buffer pool tracking. This means that:
+	  * amount of free buffers in the pool is remembered
+	  * total size of the pool is calculated
+	  * pool name is stored and can be shown in debugging prints
+
+endif # NET_BUF
+
+config NETWORKING
+	bool "Link layer and IP networking support"
+	select NET_BUF
+	select POLL
+	select ENTROPY_GENERATOR
+	help
+	  This option enabled generic link layer and IP networking support.
+
+if NETWORKING
+
+# Such option should not be configured manually but by device drivers
+# which supports PM properly.
+config NET_POWER_MANAGEMENT
+	bool
+	default n
+	depends on DEVICE_POWER_MANAGEMENT
+
+source "subsys/net/Kconfig.hostname"
+
+source "subsys/net/l2/Kconfig"
+
+source "subsys/net/ip/Kconfig"
+
+source "subsys/net/lib/Kconfig"
+
+endif
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.hostname
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.hostname	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.hostname	(working copy)
@@ -0,0 +1,33 @@
+# Hostname config
+
+# Copyright (c) 2017 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+config NET_HOSTNAME_ENABLE
+	bool "Add hostname to the device"
+	help
+	  This is used for example in mDNS to respond to <hostname>.local
+	  mDNS queries.
+
+if NET_HOSTNAME_ENABLE
+
+config NET_HOSTNAME
+	string "The hostname of this device"
+	default "zephyr"
+	help
+	  The string should be a valid hostname.
+
+config NET_HOSTNAME_UNIQUE
+	bool "Make hostname unique"
+	help
+	  This will append link address to hostname to create a unique
+	  hostname. For example, zephyr00005e005357 could be the hostname
+	  if this setting is enabled.
+
+module = NET_HOSTNAME
+module-dep = NET_LOG
+module-str = Log level for hostname configuration
+module-help = Enables hostname configuration code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.default.net
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.default.net	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.default.net	(working copy)
@@ -0,0 +1,50 @@
+# Kconfig template file for setting networking log level for
+# various network related components. This template variant
+# allows user to specify the default log level.
+
+# Copyright (c) 2018 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+choice
+	prompt "$(module-str)"
+	default $(module)_$(module-def)
+	depends on $(module-dep)
+# If we ever get help text macro expansion, then just uncomment
+# the following lines.
+#	help
+#	  $(module-help)
+
+config $(module)_LOG_LEVEL_OFF
+	bool "Off"
+	help
+	  Do not write to log.
+
+config $(module)_LOG_LEVEL_ERR
+	bool "Error"
+	help
+	  Only write to log when NET_ERR or LOG_ERR is used.
+
+config $(module)_LOG_LEVEL_WRN
+	bool "Warning"
+	help
+	  Write to log with NET_WARN or LOG_WRN in addition to previous level.
+
+config $(module)_LOG_LEVEL_INF
+	bool "Info"
+	help
+	  Write to log with NET_INFO or LOG_INF in addition to previous levels.
+
+config $(module)_LOG_LEVEL_DBG
+	bool "Debug"
+	help
+	  Write to log with NET_DBG or LOG_DBG in addition to previous levels.
+
+endchoice
+
+config $(module)_LOG_LEVEL
+	int
+	default 0 if $(module)_LOG_LEVEL_OFF || !$(module-dep)
+	default 1 if $(module)_LOG_LEVEL_ERR
+	default 2 if $(module)_LOG_LEVEL_WRN
+	default 3 if $(module)_LOG_LEVEL_INF
+	default 4 if $(module)_LOG_LEVEL_DBG
Index: ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.net
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.net	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/Kconfig.template.log_config.net	(working copy)
@@ -0,0 +1,55 @@
+# Kconfig template file for setting networking log level for
+# various network related components.
+
+# Copyright (c) 2018 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+choice
+	prompt "$(module-str)"
+	default $(module)_LOG_LEVEL_DEFAULT
+	depends on $(module-dep)
+# If we ever get help text macro expansion, then just uncomment
+# the following lines.
+#	help
+#	  $(module-help)
+
+config $(module)_LOG_LEVEL_OFF
+	bool "Off"
+	help
+	  Do not write to log.
+
+config $(module)_LOG_LEVEL_ERR
+	bool "Error"
+	help
+	  Only write to log when NET_ERR or LOG_ERR is used.
+
+config $(module)_LOG_LEVEL_WRN
+	bool "Warning"
+	help
+	  Write to log with NET_WARN or LOG_WRN in addition to previous level.
+
+config $(module)_LOG_LEVEL_INF
+	bool "Info"
+	help
+	  Write to log with NET_INFO or LOG_INF in addition to previous levels.
+
+config $(module)_LOG_LEVEL_DBG
+	bool "Debug"
+	help
+	  Write to log with NET_DBG or LOG_DBG in addition to previous levels.
+
+config $(module)_LOG_LEVEL_DEFAULT
+	bool "Default"
+	help
+	  Use default log level.
+
+endchoice
+
+config $(module)_LOG_LEVEL
+	int
+	default 0 if $(module)_LOG_LEVEL_OFF || !$(module-dep)
+	default 1 if $(module)_LOG_LEVEL_ERR
+	default 2 if $(module)_LOG_LEVEL_WRN
+	default 3 if $(module)_LOG_LEVEL_INF
+	default 4 if $(module)_LOG_LEVEL_DBG
+	default LOG_DEFAULT_LEVEL if $(module)_LOG_LEVEL_DEFAULT
Index: ModuleDemo/BLE/CM0/User/subsys/net/buf.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/buf.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/buf.c	(working copy)
@@ -0,0 +1,1081 @@
+/* buf.c - Buffer management */
+
+/*
+ * Copyright (c) 2015-2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_buf
+#define LOG_LEVEL CONFIG_NET_BUF_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdio.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+
+#if defined(CONFIG_NET_BUF_LOG)
+#define NET_BUF_DBG(fmt, ...) LOG_DBG("(%p) " fmt, k_current_get(), \
+				      ##__VA_ARGS__)
+#define NET_BUF_ERR(fmt, ...) LOG_ERR(fmt, ##__VA_ARGS__)
+#define NET_BUF_WARN(fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__)
+#define NET_BUF_INFO(fmt, ...) LOG_INF(fmt, ##__VA_ARGS__)
+#else
+
+#define NET_BUF_DBG(fmt, ...)
+#define NET_BUF_ERR(fmt, ...)
+#define NET_BUF_WARN(fmt, ...)
+#define NET_BUF_INFO(fmt, ...)
+#endif /* CONFIG_NET_BUF_LOG */
+
+#define NET_BUF_ASSERT(cond, ...) __ASSERT(cond, "" __VA_ARGS__)
+
+#if CONFIG_NET_BUF_WARN_ALLOC_INTERVAL > 0
+#define WARN_ALLOC_INTERVAL K_SECONDS(CONFIG_NET_BUF_WARN_ALLOC_INTERVAL)
+#else
+#define WARN_ALLOC_INTERVAL K_FOREVER
+#endif
+
+/* Linker-defined symbol bound to the static pool structs */
+extern struct net_buf_pool _net_buf_pool_list[];
+
+struct net_buf_pool *net_buf_pool_get(int id)
+{
+	return &_net_buf_pool_list[id];
+}
+
+static int pool_id(struct net_buf_pool *pool)
+{
+	return pool - _net_buf_pool_list;
+}
+
+int net_buf_id(struct net_buf *buf)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return buf - pool->__bufs;
+}
+
+static inline struct net_buf *pool_get_uninit(struct net_buf_pool *pool,
+					      uint16_t uninit_count)
+{
+	struct net_buf *buf;
+
+	buf = &pool->__bufs[pool->buf_count - uninit_count];
+
+	buf->pool_id = pool_id(pool);
+
+	return buf;
+}
+
+void net_buf_reset(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf->flags == 0U);
+	__ASSERT_NO_MSG(buf->frags == NULL);
+
+	net_buf_simple_reset(&buf->b);
+}
+
+static uint8_t *generic_data_ref(struct net_buf *buf, uint8_t *data)
+{
+	uint8_t *ref_count;
+
+	ref_count = data - 1;
+	(*ref_count)++;
+
+	return data;
+}
+
+static uint8_t *fixed_data_alloc(struct net_buf *buf, size_t *size,
+			      k_timeout_t timeout)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	*size = MIN(fixed->data_size, *size);
+
+	return fixed->data_pool + fixed->data_size * net_buf_id(buf);
+}
+
+static void fixed_data_unref(struct net_buf *buf, uint8_t *data)
+{
+	/* Nothing needed for fixed-size data pools */
+}
+
+const struct net_buf_data_cb net_buf_fixed_cb = {
+	.alloc = fixed_data_alloc,
+	.unref = fixed_data_unref,
+};
+
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+
+static uint8_t *heap_data_alloc(struct net_buf *buf, size_t *size,
+			     k_timeout_t timeout)
+{
+	uint8_t *ref_count;
+
+	ref_count = k_malloc(1 + *size);
+	if (!ref_count) {
+		return NULL;
+	}
+
+	*ref_count = 1U;
+
+	return ref_count + 1;
+}
+
+static void heap_data_unref(struct net_buf *buf, uint8_t *data)
+{
+	uint8_t *ref_count;
+
+	ref_count = data - 1;
+	if (--(*ref_count)) {
+		return;
+	}
+
+	k_free(ref_count);
+}
+
+static const struct net_buf_data_cb net_buf_heap_cb = {
+	.alloc = heap_data_alloc,
+	.ref   = generic_data_ref,
+	.unref = heap_data_unref,
+};
+
+const struct net_buf_data_alloc net_buf_heap_alloc = {
+	.cb = &net_buf_heap_cb,
+};
+
+#endif /* CONFIG_HEAP_MEM_POOL_SIZE > 0 */
+
+static uint8_t *data_alloc(struct net_buf *buf, size_t *size, k_timeout_t timeout)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return pool->alloc->cb->alloc(buf, size, timeout);
+}
+
+static uint8_t *data_ref(struct net_buf *buf, uint8_t *data)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return pool->alloc->cb->ref(buf, data);
+}
+
+static void data_unref(struct net_buf *buf, uint8_t *data)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	if (buf->flags & NET_BUF_EXTERNAL_DATA) {
+		return;
+	}
+
+	pool->alloc->cb->unref(buf, data);
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_len_debug(struct net_buf_pool *pool, size_t size,
+					k_timeout_t timeout, const char *func,
+					int line)
+#else
+struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size,
+				  k_timeout_t timeout)
+#endif
+{
+	uint64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf *buf;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(pool);
+
+	NET_BUF_DBG("%s():%d: pool %p size %zu", func, line, pool, size);
+
+	/* We need to lock interrupts temporarily to prevent race conditions
+	 * when accessing pool->uninit_count.
+	 */
+	key = irq_lock();
+
+	/* If there are uninitialized buffers we're guaranteed to succeed
+	 * with the allocation one way or another.
+	 */
+	if (pool->uninit_count) {
+		uint16_t uninit_count;
+
+		/* If this is not the first access to the pool, we can
+		 * be opportunistic and try to fetch a previously used
+		 * buffer from the LIFO with K_NO_WAIT.
+		 */
+		if (pool->uninit_count < pool->buf_count) {
+			buf = k_lifo_get(&pool->free, K_NO_WAIT);
+			if (buf) {
+				irq_unlock(key);
+				goto success;
+			}
+		}
+
+		uninit_count = pool->uninit_count--;
+		irq_unlock(key);
+
+		buf = pool_get_uninit(pool, uninit_count);
+		goto success;
+	}
+
+	irq_unlock(key);
+
+#if defined(CONFIG_NET_BUF_LOG) && (CONFIG_NET_BUF_LOG_LEVEL >= LOG_LEVEL_WRN)
+	if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+		uint32_t ref = k_uptime_get_32();
+		buf = k_lifo_get(&pool->free, K_NO_WAIT);
+		while (!buf) {
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+			NET_BUF_WARN("%s():%d: Pool %s low on buffers.",
+				     func, line, pool->name);
+#else
+			NET_BUF_WARN("%s():%d: Pool %p low on buffers.",
+				     func, line, pool);
+#endif
+			buf = k_lifo_get(&pool->free, WARN_ALLOC_INTERVAL);
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+			NET_BUF_WARN("%s():%d: Pool %s blocked for %u secs",
+				     func, line, pool->name,
+				     (k_uptime_get_32() - ref) / MSEC_PER_SEC);
+#else
+			NET_BUF_WARN("%s():%d: Pool %p blocked for %u secs",
+				     func, line, pool,
+				     (k_uptime_get_32() - ref) / MSEC_PER_SEC);
+#endif
+		}
+	} else {
+		buf = k_lifo_get(&pool->free, timeout);
+	}
+#else
+	buf = k_lifo_get(&pool->free, timeout);
+#endif
+	if (!buf) {
+		NET_BUF_ERR("%s():%d: Failed to get free buffer", func, line);
+		return NULL;
+	}
+
+success:
+	NET_BUF_DBG("allocated buf %p", buf);
+
+	if (size) {
+#if __ASSERT_ON
+		size_t req_size = size;
+#endif
+		if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+		    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			int64_t remaining = end - z_tick_get();
+
+			if (remaining <= 0) {
+				timeout = K_NO_WAIT;
+			} else {
+				timeout = Z_TIMEOUT_TICKS(remaining);
+			}
+		}
+
+		buf->__buf = data_alloc(buf, &size, timeout);
+		if (!buf->__buf) {
+			NET_BUF_ERR("%s():%d: Failed to allocate data",
+				    func, line);
+			net_buf_destroy(buf);
+			return NULL;
+		}
+
+		NET_BUF_ASSERT(req_size <= size);
+	} else {
+		buf->__buf = NULL;
+	}
+
+	buf->ref   = 1U;
+	buf->flags = 0U;
+	buf->frags = NULL;
+	buf->size  = size;
+	net_buf_reset(buf);
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	pool->avail_count--;
+	__ASSERT_NO_MSG(pool->avail_count >= 0);
+#endif
+	return buf;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool,
+					  k_timeout_t timeout, const char *func,
+					  int line)
+{
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	return net_buf_alloc_len_debug(pool, fixed->data_size, timeout, func,
+				       line);
+}
+#else
+struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool,
+				    k_timeout_t timeout)
+{
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	return net_buf_alloc_len(pool, fixed->data_size, timeout);
+}
+#endif
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_with_data_debug(struct net_buf_pool *pool,
+					      void *data, size_t size,
+					      k_timeout_t timeout,
+					      const char *func, int line)
+#else
+struct net_buf *net_buf_alloc_with_data(struct net_buf_pool *pool,
+					void *data, size_t size,
+					k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf;
+
+#if defined(CONFIG_NET_BUF_LOG)
+	buf = net_buf_alloc_len_debug(pool, 0, timeout, func, line);
+#else
+	buf = net_buf_alloc_len(pool, 0, timeout);
+#endif
+	if (!buf) {
+		return NULL;
+	}
+
+	net_buf_simple_init_with_data(&buf->b, data, size);
+	buf->flags = NET_BUF_EXTERNAL_DATA;
+
+	return buf;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_get_debug(struct k_fifo *fifo, k_timeout_t timeout,
+				  const char *func, int line)
+#else
+struct net_buf *net_buf_get(struct k_fifo *fifo, k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf, *frag;
+
+	NET_BUF_DBG("%s():%d: fifo %p", func, line, fifo);
+
+	buf = k_fifo_get(fifo, timeout);
+	if (!buf) {
+		return NULL;
+	}
+
+	NET_BUF_DBG("%s():%d: buf %p fifo %p", func, line, buf, fifo);
+
+	/* Get any fragments belonging to this buffer */
+	for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) {
+		frag->frags = k_fifo_get(fifo, K_NO_WAIT);
+		__ASSERT_NO_MSG(frag->frags);
+
+		/* The fragments flag is only for FIFO-internal usage */
+		frag->flags &= ~NET_BUF_FRAGS;
+	}
+
+	/* Mark the end of the fragment list */
+	frag->frags = NULL;
+
+	return buf;
+}
+
+void net_buf_simple_init_with_data(struct net_buf_simple *buf,
+				   void *data, size_t size)
+{
+	buf->__buf = data;
+	buf->data  = data;
+	buf->size  = size;
+	buf->len   = size;
+}
+
+void net_buf_simple_reserve(struct net_buf_simple *buf, size_t reserve)
+{
+	__ASSERT_NO_MSG(buf);
+	__ASSERT_NO_MSG(buf->len == 0U);
+	NET_BUF_DBG("buf %p reserve %zu", buf, reserve);
+
+	buf->data = buf->__buf + reserve;
+}
+
+void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf)
+{
+	struct net_buf *tail;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(list);
+	__ASSERT_NO_MSG(buf);
+
+	for (tail = buf; tail->frags; tail = tail->frags) {
+		tail->flags |= NET_BUF_FRAGS;
+	}
+
+	key = irq_lock();
+	sys_slist_append_list(list, &buf->node, &tail->node);
+	irq_unlock(key);
+}
+
+struct net_buf *net_buf_slist_get(sys_slist_t *list)
+{
+	struct net_buf *buf, *frag;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(list);
+
+	key = irq_lock();
+	buf = (void *)sys_slist_get(list);
+	irq_unlock(key);
+
+	if (!buf) {
+		return NULL;
+	}
+
+	/* Get any fragments belonging to this buffer */
+	for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) {
+		key = irq_lock();
+		frag->frags = (void *)sys_slist_get(list);
+		irq_unlock(key);
+
+		__ASSERT_NO_MSG(frag->frags);
+
+		/* The fragments flag is only for list-internal usage */
+		frag->flags &= ~NET_BUF_FRAGS;
+	}
+
+	/* Mark the end of the fragment list */
+	frag->frags = NULL;
+
+	return buf;
+}
+
+void net_buf_put(struct k_fifo *fifo, struct net_buf *buf)
+{
+	struct net_buf *tail;
+
+	__ASSERT_NO_MSG(fifo);
+	__ASSERT_NO_MSG(buf);
+
+	for (tail = buf; tail->frags; tail = tail->frags) {
+		tail->flags |= NET_BUF_FRAGS;
+	}
+
+	k_fifo_put_list(fifo, buf, tail);
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+void net_buf_unref_debug(struct net_buf *buf, const char *func, int line)
+#else
+void net_buf_unref(struct net_buf *buf)
+#endif
+{
+	__ASSERT_NO_MSG(buf);
+
+	while (buf) {
+		struct net_buf *frags = buf->frags;
+		struct net_buf_pool *pool;
+
+#if defined(CONFIG_NET_BUF_LOG)
+		if (!buf->ref) {
+			NET_BUF_ERR("%s():%d: buf %p double free", func, line,
+				    buf);
+			return;
+		}
+#endif
+		NET_BUF_DBG("buf %p ref %u pool_id %u frags %p", buf, buf->ref,
+			    buf->pool_id, buf->frags);
+
+		if (--buf->ref > 0) {
+			return;
+		}
+
+		if (buf->__buf) {
+			data_unref(buf, buf->__buf);
+			buf->__buf = NULL;
+		}
+
+		buf->data = NULL;
+		buf->frags = NULL;
+
+		pool = net_buf_pool_get(buf->pool_id);
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+		pool->avail_count++;
+		__ASSERT_NO_MSG(pool->avail_count <= pool->buf_count);
+#endif
+
+		if (pool->destroy) {
+			pool->destroy(buf);
+		} else {
+			net_buf_destroy(buf);
+		}
+
+		buf = frags;
+	}
+}
+
+struct net_buf *net_buf_ref(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf);
+
+	NET_BUF_DBG("buf %p (old) ref %u pool_id %u",
+		    buf, buf->ref, buf->pool_id);
+	buf->ref++;
+	return buf;
+}
+
+struct net_buf *net_buf_clone(struct net_buf *buf, k_timeout_t timeout)
+{
+	int64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf_pool *pool;
+	struct net_buf *clone;
+
+	__ASSERT_NO_MSG(buf);
+
+	pool = net_buf_pool_get(buf->pool_id);
+
+	clone = net_buf_alloc_len(pool, 0, timeout);
+	if (!clone) {
+		return NULL;
+	}
+
+	/* If the pool supports data referencing use that. Otherwise
+	 * we need to allocate new data and make a copy.
+	 */
+	if (pool->alloc->cb->ref && !(buf->flags & NET_BUF_EXTERNAL_DATA)) {
+		clone->__buf = data_ref(buf, buf->__buf);
+		clone->data = buf->data;
+		clone->len = buf->len;
+		clone->size = buf->size;
+	} else {
+		size_t size = buf->size;
+
+		if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+		    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			int64_t remaining = end - z_tick_get();
+
+			if (remaining <= 0) {
+				timeout = K_NO_WAIT;
+			} else {
+				timeout = Z_TIMEOUT_TICKS(remaining);
+			}
+		}
+
+		clone->__buf = data_alloc(clone, &size, timeout);
+		if (!clone->__buf || size < buf->size) {
+			net_buf_destroy(clone);
+			return NULL;
+		}
+
+		clone->size = size;
+		clone->data = clone->__buf + net_buf_headroom(buf);
+		net_buf_add_mem(clone, buf->data, buf->len);
+	}
+
+	return clone;
+}
+
+struct net_buf *net_buf_frag_last(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf);
+
+	while (buf->frags) {
+		buf = buf->frags;
+	}
+
+	return buf;
+}
+
+void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag)
+{
+	__ASSERT_NO_MSG(parent);
+	__ASSERT_NO_MSG(frag);
+
+	if (parent->frags) {
+		net_buf_frag_last(frag)->frags = parent->frags;
+	}
+	/* Take ownership of the fragment reference */
+	parent->frags = frag;
+}
+
+struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag)
+{
+	__ASSERT_NO_MSG(frag);
+
+	if (!head) {
+		return net_buf_ref(frag);
+	}
+
+	net_buf_frag_insert(net_buf_frag_last(head), frag);
+
+	return head;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_frag_del_debug(struct net_buf *parent,
+				       struct net_buf *frag,
+				       const char *func, int line)
+#else
+struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag)
+#endif
+{
+	struct net_buf *next_frag;
+
+	__ASSERT_NO_MSG(frag);
+
+	if (parent) {
+		__ASSERT_NO_MSG(parent->frags);
+		__ASSERT_NO_MSG(parent->frags == frag);
+		parent->frags = frag->frags;
+	}
+
+	next_frag = frag->frags;
+
+	frag->frags = NULL;
+
+#if defined(CONFIG_NET_BUF_LOG)
+	net_buf_unref_debug(frag, func, line);
+#else
+	net_buf_unref(frag);
+#endif
+
+	return next_frag;
+}
+
+size_t net_buf_linearize(void *dst, size_t dst_len, struct net_buf *src,
+			 size_t offset, size_t len)
+{
+	struct net_buf *frag;
+	size_t to_copy;
+	size_t copied;
+
+	len = MIN(len, dst_len);
+
+	frag = src;
+
+	/* find the right fragment to start copying from */
+	while (frag && offset >= frag->len) {
+		offset -= frag->len;
+		frag = frag->frags;
+	}
+
+	/* traverse the fragment chain until len bytes are copied */
+	copied = 0;
+	while (frag && len > 0) {
+		to_copy = MIN(len, frag->len - offset);
+		memcpy((uint8_t *)dst + copied, frag->data + offset, to_copy);
+
+		copied += to_copy;
+
+		/* to_copy is always <= len */
+		len -= to_copy;
+		frag = frag->frags;
+
+		/* after the first iteration, this value will be 0 */
+		offset = 0;
+	}
+
+	return copied;
+}
+
+/* This helper routine will append multiple bytes, if there is no place for
+ * the data in current fragment then create new fragment and add it to
+ * the buffer. It assumes that the buffer has at least one fragment.
+ */
+size_t net_buf_append_bytes(struct net_buf *buf, size_t len,
+			    const void *value, k_timeout_t timeout,
+			    net_buf_allocator_cb allocate_cb, void *user_data)
+{
+	struct net_buf *frag = net_buf_frag_last(buf);
+	size_t added_len = 0;
+	const uint8_t *value8 = value;
+
+	do {
+		uint16_t count = MIN(len, net_buf_tailroom(frag));
+
+		net_buf_add_mem(frag, value8, count);
+		len -= count;
+		added_len += count;
+		value8 += count;
+
+		if (len == 0) {
+			return added_len;
+		}
+
+		frag = allocate_cb(timeout, user_data);
+		if (!frag) {
+			return added_len;
+		}
+
+		net_buf_frag_add(buf, frag);
+	} while (1);
+
+	/* Unreachable */
+	return 0;
+}
+
+#if defined(CONFIG_NET_BUF_SIMPLE_LOG)
+#define NET_BUF_SIMPLE_DBG(fmt, ...) NET_BUF_DBG(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_ERR(fmt, ...) NET_BUF_ERR(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_WARN(fmt, ...) NET_BUF_WARN(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_INFO(fmt, ...) NET_BUF_INFO(fmt, ##__VA_ARGS__)
+#else
+#define NET_BUF_SIMPLE_DBG(fmt, ...)
+#define NET_BUF_SIMPLE_ERR(fmt, ...)
+#define NET_BUF_SIMPLE_WARN(fmt, ...)
+#define NET_BUF_SIMPLE_INFO(fmt, ...)
+#endif /* CONFIG_NET_BUF_SIMPLE_LOG */
+
+void net_buf_simple_clone(const struct net_buf_simple *original,
+			  struct net_buf_simple *clone)
+{
+	memcpy(clone, original, sizeof(struct net_buf_simple));
+}
+
+void *net_buf_simple_add(struct net_buf_simple *buf, size_t len)
+{
+	uint8_t *tail = net_buf_simple_tail(buf);
+
+	NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(net_buf_simple_tailroom(buf) >= len);
+
+	buf->len += len;
+	return tail;
+}
+
+void *net_buf_simple_add_mem(struct net_buf_simple *buf, const void *mem,
+			     size_t len)
+{
+	NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
+
+	return memcpy(net_buf_simple_add(buf, len), mem, len);
+}
+
+uint8_t *net_buf_simple_add_u8(struct net_buf_simple *buf, uint8_t val)
+{
+	uint8_t *u8;
+
+	NET_BUF_SIMPLE_DBG("buf %p val 0x%02x", buf, val);
+
+	u8 = net_buf_simple_add(buf, 1);
+	*u8 = val;
+
+	return u8;
+}
+
+void net_buf_simple_add_le16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le16(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be16(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_le24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le24(val, net_buf_simple_add(buf, 3));
+}
+
+void net_buf_simple_add_be24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be24(val, net_buf_simple_add(buf, 3));
+}
+
+void net_buf_simple_add_le32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le32(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be32(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_le48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_le48(val, net_buf_simple_add(buf, 6));
+}
+
+void net_buf_simple_add_be48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_be48(val, net_buf_simple_add(buf, 6));
+}
+
+void net_buf_simple_add_le64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_le64(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_be64(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void *net_buf_simple_push(struct net_buf_simple *buf, size_t len)
+{
+	NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(net_buf_simple_headroom(buf) >= len);
+
+	buf->data -= len;
+	buf->len += len;
+	return buf->data;
+}
+
+void net_buf_simple_push_le16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le16(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be16(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_u8(struct net_buf_simple *buf, uint8_t val)
+{
+	uint8_t *data = net_buf_simple_push(buf, 1);
+
+	*data = val;
+}
+
+void net_buf_simple_push_le24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le24(val, net_buf_simple_push(buf, 3));
+}
+
+void net_buf_simple_push_be24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be24(val, net_buf_simple_push(buf, 3));
+}
+
+void net_buf_simple_push_le32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_le32(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
+
+	sys_put_be32(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_le48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_le48(val, net_buf_simple_push(buf, 6));
+}
+
+void net_buf_simple_push_be48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_be48(val, net_buf_simple_push(buf, 6));
+}
+
+void net_buf_simple_push_le64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_le64(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
+
+	sys_put_be64(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len)
+{
+	NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(buf->len >= len);
+
+	buf->len -= len;
+	return buf->data += len;
+}
+
+void *net_buf_simple_pull_mem(struct net_buf_simple *buf, size_t len)
+{
+	void *data = buf->data;
+
+	NET_BUF_SIMPLE_DBG("buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(buf->len >= len);
+
+	buf->len -= len;
+	buf->data += len;
+
+	return data;
+}
+
+uint8_t net_buf_simple_pull_u8(struct net_buf_simple *buf)
+{
+	uint8_t val;
+
+	val = buf->data[0];
+	net_buf_simple_pull(buf, 1);
+
+	return val;
+}
+
+uint16_t net_buf_simple_pull_le16(struct net_buf_simple *buf)
+{
+	uint16_t val;
+
+	val = UNALIGNED_GET((uint16_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le16_to_cpu(val);
+}
+
+uint16_t net_buf_simple_pull_be16(struct net_buf_simple *buf)
+{
+	uint16_t val;
+
+	val = UNALIGNED_GET((uint16_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be16_to_cpu(val);
+}
+
+uint32_t net_buf_simple_pull_le24(struct net_buf_simple *buf)
+{
+	struct uint24 {
+		uint32_t u24:24;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint24 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le24_to_cpu(val.u24);
+}
+
+uint32_t net_buf_simple_pull_be24(struct net_buf_simple *buf)
+{
+	struct uint24 {
+		uint32_t u24:24;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint24 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be24_to_cpu(val.u24);
+}
+
+uint32_t net_buf_simple_pull_le32(struct net_buf_simple *buf)
+{
+	uint32_t val;
+
+	val = UNALIGNED_GET((uint32_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le32_to_cpu(val);
+}
+
+uint32_t net_buf_simple_pull_be32(struct net_buf_simple *buf)
+{
+	uint32_t val;
+
+	val = UNALIGNED_GET((uint32_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be32_to_cpu(val);
+}
+
+uint64_t net_buf_simple_pull_le48(struct net_buf_simple *buf)
+{
+	struct uint48 {
+		uint64_t u48:48;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint48 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le48_to_cpu(val.u48);
+}
+
+uint64_t net_buf_simple_pull_be48(struct net_buf_simple *buf)
+{
+	struct uint48 {
+		uint64_t u48:48;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint48 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be48_to_cpu(val.u48);
+}
+
+uint64_t net_buf_simple_pull_le64(struct net_buf_simple *buf)
+{
+	uint64_t val;
+
+	val = UNALIGNED_GET((uint64_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le64_to_cpu(val);
+}
+
+uint64_t net_buf_simple_pull_be64(struct net_buf_simple *buf)
+{
+	uint64_t val;
+
+	val = UNALIGNED_GET((uint64_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be64_to_cpu(val);
+}
+
+size_t net_buf_simple_headroom(struct net_buf_simple *buf)
+{
+	return buf->data - buf->__buf;
+}
+
+size_t net_buf_simple_tailroom(struct net_buf_simple *buf)
+{
+	return buf->size - net_buf_simple_headroom(buf) - buf->len;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/hostname.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/hostname.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/hostname.c	(working copy)
@@ -0,0 +1,70 @@
+/** @file
+ * @brief Hostname configuration
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_hostname, CONFIG_NET_HOSTNAME_LOG_LEVEL);
+
+#include <zephyr.h>
+
+#include <net/net_core.h>
+
+#if defined(CONFIG_NET_HOSTNAME_UNIQUE)
+/* Allocate extra space to append MAC address to hostname */
+#define EXTRA_SPACE (8 * 2)
+#else
+#define EXTRA_SPACE 0
+#endif /* CONFIG_NET_HOSTNAME_UNIQUE */
+
+static char hostname[sizeof(CONFIG_NET_HOSTNAME) + EXTRA_SPACE];
+
+const char *net_hostname_get(void)
+{
+	return hostname;
+}
+
+#if defined(CONFIG_NET_HOSTNAME_UNIQUE)
+int net_hostname_set_postfix(const uint8_t *hostname_postfix,
+			     int postfix_len)
+{
+	static bool postfix_set;
+	int pos = 0;
+	int i;
+
+	if (postfix_set) {
+		return -EALREADY;
+	}
+
+	NET_ASSERT(postfix_len > 0);
+
+	/* Note that we convert the postfix to hex (2 chars / byte) */
+	if ((postfix_len * 2) >
+	    ((sizeof(hostname) - 1) - (sizeof(CONFIG_NET_HOSTNAME) - 1))) {
+		return -EMSGSIZE;
+	}
+
+	for (i = 0; i < postfix_len; i++, pos += 2) {
+		snprintk(&hostname[sizeof(CONFIG_NET_HOSTNAME) - 1 + pos],
+			 2 + 1, "%02x", hostname_postfix[i]);
+	}
+
+	NET_DBG("New hostname %s", hostname);
+
+	postfix_set = true;
+
+	return 0;
+}
+#endif /* CONFIG_NET_HOSTNAME_UNIQUE */
+
+void net_hostname_init(void)
+{
+	memcpy(hostname, CONFIG_NET_HOSTNAME, sizeof(CONFIG_NET_HOSTNAME) - 1);
+
+	NET_DBG("Hostname set to %s", hostname);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.h	(working copy)
@@ -0,0 +1,95 @@
+/** @file
+ @brief 6lowpan handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __NET_6LO_H
+#define __NET_6LO_H
+
+#include <sys/slist.h>
+#include <zephyr/types.h>
+
+#include <net/net_pkt.h>
+#include "icmpv6.h"
+
+/**
+ *  @brief Compress IPv6 packet as per RFC 6282
+ *
+ *  @details After this IPv6 packet and next header(if UDP), headers
+ *  are compressed as per RFC 6282. After header compression data
+ *  will be adjusted according to remaining space in fragments.
+ *
+ *  @param Pointer to network packet
+ *  @param iphc true for IPHC compression, false for IPv6 dispatch header
+ *
+ *  @return header size difference on success (>= 0), negative errno otherwise
+ */
+#if defined(CONFIG_NET_6LO)
+int net_6lo_compress(struct net_pkt *pkt, bool iphc);
+#else
+static inline int net_6lo_compress(struct net_pkt *pkt, bool iphc)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(iphc);
+
+	return 0;
+}
+#endif
+
+/**
+ *  @brief Uncompress IPv6 packet as per RFC 6282
+ *
+ *  @details After this IPv6 packet and next header(if UDP), headers
+ *  are uncompressed as per RFC 6282. After header uncompression data
+ *  will be adjusted according to remaining space in fragments.
+ *
+ *  @param Pointer to network packet
+ *
+ *  @return True on success, false otherwise
+ */
+#if defined(CONFIG_NET_6LO)
+bool net_6lo_uncompress(struct net_pkt *pkt);
+#else
+static inline bool net_6lo_uncompress(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return true;
+}
+#endif
+
+/**
+ *  @brief Set 6lowpan context information
+ *
+ *  @details Set 6lowpan context information. This context information
+ *  will be used in IPv6 header compression and uncompression.
+ *
+ *  @return True on success, false otherwise
+ */
+#if defined(CONFIG_NET_6LO_CONTEXT)
+void net_6lo_set_context(struct net_if *iface,
+			 struct net_icmpv6_nd_opt_6co *context);
+#endif
+
+/**
+ *  @brief Return the header size difference after uncompression
+ *
+ * @details This will do a dry-run on uncompressing the headers.
+ *          The point is only to calculate the difference.
+ *
+ * @param Pointer to network packet
+ *
+ * @return header difference or INT_MAX in case of error.
+ */
+#if defined(CONFIG_NET_6LO)
+int net_6lo_uncompress_hdr_diff(struct net_pkt *pkt);
+#endif
+
+#endif /* __NET_6LO_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo.c	(working copy)
@@ -0,0 +1,1594 @@
+/** @file
+ * @brief 6lopan related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2019 Alexander Wachter
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_6lo, CONFIG_NET_6LO_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_if.h>
+#include <net/net_stats.h>
+#include <net/udp.h>
+
+#include "net_private.h"
+#include "6lo.h"
+#include "6lo_private.h"
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+struct net_6lo_context {
+	struct in6_addr prefix;
+	struct net_if *iface;
+	uint16_t lifetime;
+	uint8_t is_used		: 1;
+	uint8_t compress	: 1;
+	uint8_t cid		: 4;
+	uint8_t unused		: 2;
+} __packed;
+
+static inline uint8_t get_6co_compress(struct net_icmpv6_nd_opt_6co *opt)
+{
+	return (opt->flag & 0x10) >> 4;
+}
+
+static inline uint8_t get_6co_cid(struct net_icmpv6_nd_opt_6co *opt)
+{
+	return opt->flag & 0x0F;
+}
+
+static struct net_6lo_context ctx_6co[CONFIG_NET_MAX_6LO_CONTEXTS];
+#endif
+
+static const uint8_t udp_nhc_inline_size_table[] = {4, 3, 3, 1};
+
+static const uint8_t tf_inline_size_table[] = {4, 3, 1, 0};
+/* The first bit of the index is SAC        |  SAC=0   |  SAC=1   |*/
+static const uint8_t sa_inline_size_table[] = {16, 8, 2, 0, 0, 8, 2, 0};
+
+/* The first bit is M, the second DAC
+ *	| M=0 DAC=0 | M=0 DAC=1 | M=1 DAC=0  | M=1 DAC=1 (DAM always 00)
+ */
+static const uint8_t da_inline_size_table[] = {
+	16, 8, 2, 0, 0, 8, 2, 0, 16, 6, 4, 1, 6
+	};
+
+static int get_udp_nhc_inlined_size(uint8_t nhc)
+{
+	int size = 0;
+
+	if ((nhc & 0xF8) != NET_6LO_NHC_UDP_BARE) {
+		NET_DBG("UDP NHC dispatch doesn't match");
+		return 0;
+	}
+
+	if (!(nhc & NET_6LO_NHC_UDP_CHECKSUM)) {
+		size += 2U;
+	}
+
+	size += udp_nhc_inline_size_table[(nhc & NET_6LO_NHC_UDP_PORT_MASK)];
+
+	NET_DBG("Size of inlined UDP HDR data: %d", size);
+
+	return size;
+}
+
+static int get_ihpc_inlined_size(uint16_t iphc)
+{
+	int size = 0;
+
+	if (((iphc >> 8) & NET_6LO_DISPATCH_IPHC_MASK) !=
+	    NET_6LO_DISPATCH_IPHC) {
+		NET_DBG("IPHC dispatch doesn't match");
+		return -1;
+	}
+
+	size += tf_inline_size_table[(iphc & NET_6LO_IPHC_TF_MASK) >>
+				     NET_6LO_IPHC_TF_POS];
+
+	if (!(iphc & NET_6LO_IPHC_NH_MASK)) {
+		size += 1U;
+	}
+
+	if (!(iphc & NET_6LO_IPHC_HLIM_MASK)) {
+		size += 1U;
+	}
+
+	if (iphc & NET_6LO_IPHC_CID_MASK) {
+		size += 1U;
+	}
+
+	size += sa_inline_size_table[(iphc & NET_6LO_IPHC_SA_MASK) >>
+				      NET_6LO_IPHC_SAM_POS];
+
+	size += da_inline_size_table[(iphc & NET_6LO_IPHC_DA_MASK) >>
+				      NET_6LO_IPHC_DAM_POS];
+
+	NET_DBG("Size of inlined IP HDR data: %d", size);
+
+	return size;
+}
+
+/* TODO: Unicast-Prefix based IPv6 Multicast(dst) address compression
+ *       Mesh header compression
+ */
+
+static inline bool net_6lo_ll_prefix_padded_with_zeros(struct in6_addr *addr)
+{
+	return (net_ipv6_is_ll_addr(addr) &&
+		(UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
+		(UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00));
+}
+
+static inline bool net_6lo_addr_16_bit_compressible(struct in6_addr *addr)
+{
+	return ((UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0xFF)) &&
+		 (UNALIGNED_GET(&addr->s6_addr16[6]) == htons(0xFE00)));
+}
+
+static inline bool net_6lo_maddr_8_bit_compressible(struct in6_addr *addr)
+{
+	return ((addr->s6_addr[1] == 0x02) &&
+		 (UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
+		 (UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
+		 (UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
+		 (addr->s6_addr[14] == 0x00));
+}
+
+static inline bool net_6lo_maddr_32_bit_compressible(struct in6_addr *addr)
+{
+	return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
+		 (UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
+		 (addr->s6_addr[12] == 0x00));
+}
+
+static inline bool net_6lo_maddr_48_bit_compressible(struct in6_addr *addr)
+{
+	return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
+		 (UNALIGNED_GET(&addr->s6_addr16[4]) == 0x00) &&
+		 (addr->s6_addr[10] == 0x00));
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+/* RFC 6775, 4.2, 5.4.2, 5.4.3 and 7.2*/
+static inline void set_6lo_context(struct net_if *iface, uint8_t index,
+				   struct net_icmpv6_nd_opt_6co *context)
+
+{
+	ctx_6co[index].is_used = true;
+	ctx_6co[index].iface = iface;
+
+	/*TODO: Start timer */
+	ctx_6co[index].lifetime = context->lifetime;
+	ctx_6co[index].compress = get_6co_compress(context);
+	ctx_6co[index].cid = get_6co_cid(context);
+
+	net_ipaddr_copy(&ctx_6co[index].prefix, &context->prefix);
+}
+
+void net_6lo_set_context(struct net_if *iface,
+			 struct net_icmpv6_nd_opt_6co *context)
+{
+	int unused = -1;
+	uint8_t i;
+
+	/* If the context information already exists, update or remove
+	 * as per data.
+	 */
+	for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
+		if (!ctx_6co[i].is_used) {
+			unused = i;
+			continue;
+		}
+
+		if (ctx_6co[i].iface == iface &&
+		    ctx_6co[i].cid == get_6co_cid(context)) {
+			/* Remove if lifetime is zero */
+			if (!context->lifetime) {
+				ctx_6co[i].is_used = false;
+				return;
+			}
+
+			/* Update the context */
+			set_6lo_context(iface, i, context);
+			return;
+		}
+	}
+
+	/* Cache the context information. */
+	if (unused != -1) {
+		set_6lo_context(iface, unused, context);
+		return;
+	}
+
+	NET_DBG("Either no free slots in the table or exceeds limit");
+}
+
+/* Get the context by matching cid */
+static inline struct net_6lo_context *
+get_6lo_context_by_cid(struct net_if *iface, uint8_t cid)
+{
+	uint8_t i;
+
+	for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
+		if (!ctx_6co[i].is_used) {
+			continue;
+		}
+
+		if (ctx_6co[i].iface == iface && ctx_6co[i].cid == cid) {
+			return &ctx_6co[i];
+		}
+	}
+
+	return NULL;
+}
+
+/* Get the context by addr */
+static inline struct net_6lo_context *
+get_6lo_context_by_addr(struct net_if *iface, struct in6_addr *addr)
+{
+	uint8_t i;
+
+	for (i = 0U; i < CONFIG_NET_MAX_6LO_CONTEXTS; i++) {
+		if (!ctx_6co[i].is_used) {
+			continue;
+		}
+
+		if (ctx_6co[i].iface == iface &&
+		    !memcmp(ctx_6co[i].prefix.s6_addr, addr->s6_addr, 8)) {
+			return &ctx_6co[i];
+		}
+	}
+
+	return NULL;
+}
+
+#endif
+
+/* Helper routine to compress Traffic class and Flow label */
+/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Version| Traffic Class |           Flow Label                  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * version: 4 bits, Traffic Class: 8 bits, Flow label: 20 bits
+ * The Traffic Class field in the IPv6 header comprises 6 bits of
+ * Diffserv extension [RFC2474] and 2 bits of Explicit Congestion
+ * Notification (ECN) [RFC3168]
+ */
+
+/* IPHC (compressed) format of traffic class is ECN, DSCP but original
+ * IPv6 traffic class format is DSCP, ECN.
+ * DSCP(6), ECN(2).
+ */
+static uint8_t *compress_tfl(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			  uint16_t *iphc)
+{
+	uint8_t tcl;
+
+	tcl = ((ipv6->vtc & 0x0F) << 4) | ((ipv6->tcflow & 0xF0) >> 4);
+	tcl = (tcl << 6) | (tcl >> 2);   /* ECN(2), DSCP(6) */
+
+	if (((ipv6->tcflow & 0x0F) == 0U) && (ipv6->flow == 0U)) {
+		if (((ipv6->vtc & 0x0F) == 0U) && ((ipv6->tcflow & 0xF0) == 0U)) {
+			NET_DBG("Traffic class and Flow label elided");
+
+			/* Traffic class and Flow label elided */
+			*iphc |= NET_6LO_IPHC_TF_11;
+		} else {
+			NET_DBG("Flow label elided");
+
+			/* Flow label elided */
+			*iphc |= NET_6LO_IPHC_TF_10;
+
+			inline_ptr -= sizeof(tcl);
+			*inline_ptr = tcl;
+		}
+	} else {
+		if (((ipv6->vtc & 0x0F) == 0U) && (ipv6->tcflow & 0x30)) {
+			NET_DBG("ECN + 2-bit Pad + Flow Label, DSCP is elided");
+
+			/* ECN + 2-bit Pad + Flow Label, DSCP is elided.*/
+			*iphc |= NET_6LO_IPHC_TF_01;
+
+			inline_ptr -= sizeof(ipv6->flow);
+			memmove(inline_ptr, &ipv6->flow, sizeof(ipv6->flow));
+
+			inline_ptr -= sizeof(uint8_t);
+			*inline_ptr = (tcl & 0xC0) | (ipv6->tcflow & 0x0F);
+		} else {
+			NET_DBG("ECN + DSCP + 4-bit Pad + Flow Label");
+
+			/* ECN + DSCP + 4-bit Pad + Flow Label */
+			*iphc |= NET_6LO_IPHC_TF_00;
+
+			inline_ptr -= sizeof(ipv6->flow);
+			memmove(inline_ptr, &ipv6->flow, sizeof(ipv6->flow));
+
+			inline_ptr -= sizeof(uint8_t);
+			*inline_ptr = ipv6->tcflow & 0x0F;
+			inline_ptr -= sizeof(tcl);
+			*inline_ptr = tcl;
+		}
+	}
+
+	return inline_ptr;
+}
+
+/* Helper to compress Hop limit */
+static uint8_t *compress_hoplimit(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			       uint16_t *iphc)
+{
+	/* Hop Limit */
+	switch (ipv6->hop_limit) {
+	case 1:
+		NET_DBG("HLIM compressed (1)");
+		*iphc |= NET_6LO_IPHC_HLIM1;
+		break;
+	case 64:
+		NET_DBG("HLIM compressed (64)");
+		*iphc |= NET_6LO_IPHC_HLIM64;
+		break;
+	case 255:
+		NET_DBG("HLIM compressed (255)");
+		*iphc |= NET_6LO_IPHC_HLIM255;
+		break;
+	default:
+		inline_ptr -= sizeof(ipv6->hop_limit);
+		*inline_ptr = ipv6->hop_limit;
+		break;
+	}
+
+	return inline_ptr;
+}
+
+/* Helper to compress Next header */
+static uint8_t *compress_nh(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			 uint16_t *iphc)
+{
+	/* Next header */
+	if (ipv6->nexthdr == IPPROTO_UDP) {
+		*iphc |= NET_6LO_IPHC_NH_1;
+	} else {
+		inline_ptr -= sizeof(ipv6->nexthdr);
+		*inline_ptr = ipv6->nexthdr;
+	}
+
+	return inline_ptr;
+}
+
+/* Helpers to compress Source Address */
+static uint8_t *compress_sa(struct net_ipv6_hdr *ipv6, struct net_pkt *pkt,
+			 uint8_t *inline_ptr, uint16_t *iphc)
+{
+	NET_ASSERT(net_pkt_lladdr_src(pkt)->addr);
+
+	/* Address is fully elided */
+	if (net_ipv6_addr_based_on_ll(&ipv6->src, net_pkt_lladdr_src(pkt))) {
+		NET_DBG("SAM_11 src address is fully elided");
+
+		*iphc |= NET_6LO_IPHC_SAM_11;
+		return inline_ptr;
+	}
+
+	/* Following 64 bits are 0000:00ff:fe00:XXXX */
+	if (net_6lo_addr_16_bit_compressible(&ipv6->src)) {
+		NET_DBG("SAM_10 src addr 16 bit compressible");
+		*iphc |= NET_6LO_IPHC_SAM_10;
+
+		inline_ptr -= sizeof(uint16_t);
+		memmove(inline_ptr, &ipv6->src.s6_addr[14], sizeof(uint16_t));
+
+		return inline_ptr;
+	}
+
+	NET_DBG("SAM_01 src 64 bits are inlined");
+	/* Remaining 64 bits are in-line */
+	*iphc |= NET_6LO_IPHC_SAM_01;
+
+	inline_ptr -= 8U;
+	memmove(inline_ptr, &ipv6->src.s6_addr[8], 8U);
+
+	return inline_ptr;
+}
+
+static uint8_t *set_sa_inline(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			   uint16_t *iphc)
+{
+	*iphc |= NET_6LO_IPHC_SAM_00;
+	inline_ptr -= 16U;
+	memmove(inline_ptr, &ipv6->src.s6_addr[0], 16U);
+	return inline_ptr;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+static uint8_t *compress_sa_ctx(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			     struct net_pkt *pkt, uint16_t *iphc,
+			     struct net_6lo_context *src)
+{
+	NET_ASSERT(net_pkt_lladdr_src(pkt)->addr);
+
+	NET_DBG("SAC_1 src address context based");
+	*iphc |= NET_6LO_IPHC_SAC_1;
+
+	if (net_ipv6_addr_based_on_ll(&ipv6->src, net_pkt_lladdr_src(pkt))) {
+		NET_DBG("SAM_11 src address is fully elided");
+
+		/* Address is fully elided */
+		*iphc |= NET_6LO_IPHC_SAM_11;
+		return inline_ptr;
+	}
+
+	/* Following 64 bits are 0000:00ff:fe00:XXXX */
+	if (net_6lo_addr_16_bit_compressible(&ipv6->src)) {
+		NET_DBG("SAM_10 src addr 16 bit compressible");
+
+		*iphc |= NET_6LO_IPHC_SAM_10;
+
+		inline_ptr -= sizeof(uint16_t);
+		memmove(inline_ptr, &ipv6->src.s6_addr[14], sizeof(uint16_t));
+		return inline_ptr;
+	}
+
+	NET_DBG("SAM_01 src remaining 64 bits are inlined");
+
+	/* Remaining 64 bits are in-line */
+	*iphc |= NET_6LO_IPHC_SAM_01;
+
+	inline_ptr -= 8U;
+	memmove(inline_ptr, &ipv6->src.s6_addr[8], 8U);
+
+	return inline_ptr;
+}
+#endif
+
+/* Helpers to compress Destination Address */
+static uint8_t *compress_da_mcast(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			       uint16_t *iphc)
+{
+	*iphc |= NET_6LO_IPHC_M_1;
+
+	NET_DBG("M_1 dst is mcast");
+
+	if (net_6lo_maddr_8_bit_compressible(&ipv6->dst)) {
+		NET_DBG("DAM_11 dst maddr 8 bit compressible");
+
+		/* last byte */
+		*iphc |= NET_6LO_IPHC_DAM_11;
+
+		inline_ptr -= sizeof(uint8_t);
+		memmove(inline_ptr, &ipv6->dst.s6_addr[15], sizeof(uint8_t));
+
+		return inline_ptr;
+	}
+
+	if (net_6lo_maddr_32_bit_compressible(&ipv6->dst)) {
+		NET_DBG("DAM_10 4 bytes: 2nd byte + last three bytes");
+
+		/* 4 bytes: 2nd byte + last three bytes */
+		*iphc |= NET_6LO_IPHC_DAM_10;
+
+		inline_ptr -= 3U;
+		memmove(inline_ptr, &ipv6->dst.s6_addr[13], 3U);
+
+		inline_ptr -= sizeof(uint8_t);
+		memmove(inline_ptr, &ipv6->dst.s6_addr[1], sizeof(uint8_t));
+
+		return inline_ptr;
+	}
+
+	if (net_6lo_maddr_48_bit_compressible(&ipv6->dst)) {
+		NET_DBG("DAM_01 6 bytes: 2nd byte + last five bytes");
+
+		/* 6 bytes: 2nd byte + last five bytes */
+		*iphc |= NET_6LO_IPHC_DAM_01;
+
+		inline_ptr -= 5U;
+		memmove(inline_ptr, &ipv6->dst.s6_addr[11], 5U);
+
+		inline_ptr -= sizeof(uint8_t);
+		memmove(inline_ptr, &ipv6->dst.s6_addr[1], sizeof(uint8_t));
+
+		return inline_ptr;
+	}
+
+	NET_DBG("DAM_00 dst complete addr inlined");
+
+	/* complete address NET_6LO_IPHC_DAM_00 */
+	inline_ptr -= 16U;
+	memmove(inline_ptr, &ipv6->dst.s6_addr[0], 16U);
+
+	return inline_ptr;
+}
+
+static uint8_t *compress_da(struct net_ipv6_hdr *ipv6, struct net_pkt *pkt,
+			 uint8_t *inline_ptr, uint16_t *iphc)
+{
+	NET_ASSERT(net_pkt_lladdr_dst(pkt)->addr);
+	/* Address is fully elided */
+	if (net_ipv6_addr_based_on_ll(&ipv6->dst, net_pkt_lladdr_dst(pkt))) {
+		NET_DBG("DAM_11 dst addr fully elided");
+
+		*iphc |= NET_6LO_IPHC_DAM_11;
+		return inline_ptr;
+	}
+
+	/* Following 64 bits are 0000:00ff:fe00:XXXX */
+	if (net_6lo_addr_16_bit_compressible(&ipv6->dst)) {
+		NET_DBG("DAM_10 dst addr 16 bit compressible");
+
+		*iphc |= NET_6LO_IPHC_DAM_10;
+
+		inline_ptr -= sizeof(uint16_t);
+		memmove(inline_ptr, &ipv6->dst.s6_addr[14], sizeof(uint16_t));
+		return inline_ptr;
+	}
+
+	NET_DBG("DAM_01 remaining 64 bits are inlined");
+
+	/* Remaining 64 bits are in-line */
+	*iphc |= NET_6LO_IPHC_DAM_01;
+
+	inline_ptr -= 8U;
+	memmove(inline_ptr, &ipv6->dst.s6_addr[8], 8U);
+
+	return inline_ptr;
+}
+
+static uint8_t *set_da_inline(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			   uint16_t *iphc)
+{
+	*iphc |= NET_6LO_IPHC_DAM_00;
+	inline_ptr -= 16U;
+	memmove(inline_ptr, &ipv6->dst.s6_addr[0], 16U);
+	return inline_ptr;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+static uint8_t *compress_da_ctx(struct net_ipv6_hdr *ipv6, uint8_t *inline_ptr,
+			     struct net_pkt *pkt, uint16_t *iphc,
+			     struct net_6lo_context *dst)
+{
+	*iphc |= NET_6LO_IPHC_DAC_1;
+
+	if (net_ipv6_addr_based_on_ll(&ipv6->dst, net_pkt_lladdr_dst(pkt))) {
+		NET_DBG("DAM_11 dst addr fully elided");
+
+		*iphc |= NET_6LO_IPHC_DAM_11;
+		return inline_ptr;
+	}
+
+	/* Following 64 bits are 0000:00ff:fe00:XXXX */
+	if (net_6lo_addr_16_bit_compressible(&ipv6->dst)) {
+		NET_DBG("DAM_10 dst addr 16 bit compressible");
+
+		*iphc |= NET_6LO_IPHC_DAM_10;
+		inline_ptr -= sizeof(uint16_t);
+		memmove(inline_ptr, &ipv6->dst.s6_addr[14], sizeof(uint16_t));
+		return inline_ptr;
+	}
+
+	NET_DBG("DAM_01 remaining 64 bits are inlined");
+
+	/* Remaining 64 bits are in-line */
+	*iphc |= NET_6LO_IPHC_DAM_01;
+
+	inline_ptr -= 8U;
+	memmove(inline_ptr, &ipv6->dst.s6_addr[8], 8U);
+
+	return inline_ptr;
+}
+#endif
+
+/* Helper to compress Next header UDP */
+static inline uint8_t *compress_nh_udp(struct net_udp_hdr *udp, uint8_t *inline_ptr,
+				    bool compress_checksum)
+{
+	uint8_t nhc = NET_6LO_NHC_UDP_BARE;
+	uint8_t *inline_ptr_udp = inline_ptr;
+	uint8_t tmp;
+
+	/* 4.3.3 UDP LOWPAN_NHC Format
+	 *   0   1   2   3   4   5   6   7
+	 * +---+---+---+---+---+---+---+---+
+	 * | 1 | 1 | 1 | 1 | 0 | C |   P   |
+	 * +---+---+---+---+---+---+---+---+
+	 */
+
+	/* Port compression
+	 * 00:  All 16 bits for src and dst are inlined.
+	 * 01:  All 16 bits for src port inlined. First 8 bits of dst port is
+	 *      0xf0 and elided.  The remaining 8 bits of dst port inlined.
+	 * 10:  First 8 bits of src port 0xf0 and elided. The remaining 8 bits
+	 *      of src port inlined. All 16 bits of dst port inlined.
+	 * 11:  First 12 bits of both src and dst are 0xf0b and elided. The
+	 *      remaining 4 bits for each are inlined.
+	 */
+
+	if (compress_checksum) {
+		nhc |= NET_6LO_NHC_UDP_CHECKSUM;
+	} else {
+		inline_ptr_udp -= sizeof(udp->chksum);
+		memmove(inline_ptr_udp, &udp->chksum, sizeof(udp->chksum));
+	}
+
+	if ((((htons(udp->src_port) >> 4) & 0xFFF) ==
+	    NET_6LO_NHC_UDP_4_BIT_PORT) &&
+	    (((htons(udp->dst_port) >> 4) & 0xFFF) ==
+	    NET_6LO_NHC_UDP_4_BIT_PORT)) {
+
+		NET_DBG("UDP ports src and dst 4 bits inlined");
+		/** src: first 16 bits elided, next 4 bits inlined
+		  * dst: first 16 bits elided, next 4 bits inlined
+		  */
+		nhc |= NET_6LO_NHC_UDP_PORT_11;
+
+		tmp = (uint8_t)(htons(udp->src_port));
+		tmp = tmp << 4;
+
+		tmp |= (((uint8_t)(htons(udp->dst_port))) & 0x0F);
+		inline_ptr_udp -= sizeof(tmp);
+		*inline_ptr_udp = tmp;
+
+	} else if (((htons(udp->dst_port) >> 8) & 0xFF) ==
+		   NET_6LO_NHC_UDP_8_BIT_PORT) {
+
+		NET_DBG("UDP ports src full, dst 8 bits inlined");
+		/* dst: first 8 bits elided, next 8 bits inlined
+		 * src: fully carried inline
+		 */
+		nhc |= NET_6LO_NHC_UDP_PORT_01;
+
+		inline_ptr_udp -= sizeof(uint8_t);
+		*inline_ptr_udp = (uint8_t)(htons(udp->dst_port));
+
+		inline_ptr_udp -= sizeof(udp->src_port);
+		memmove(inline_ptr_udp, &udp->src_port, sizeof(udp->src_port));
+
+	} else if (((htons(udp->src_port) >> 8) & 0xFF) ==
+		    NET_6LO_NHC_UDP_8_BIT_PORT) {
+
+		NET_DBG("UDP ports src 8bits, dst full inlined");
+		/* src: first 8 bits elided, next 8 bits inlined
+		 * dst: fully carried inline
+		 */
+		nhc |= NET_6LO_NHC_UDP_PORT_10;
+
+		inline_ptr_udp -= sizeof(udp->dst_port);
+		memmove(inline_ptr_udp, &udp->dst_port, sizeof(udp->dst_port));
+
+		inline_ptr_udp -= sizeof(uint8_t);
+		*inline_ptr_udp = (uint8_t)(htons(udp->src_port));
+
+	} else {
+		NET_DBG("Can not compress ports, ports are inlined");
+
+		/* can not compress ports, ports are inlined */
+		inline_ptr_udp -= sizeof(udp->dst_port) + sizeof(udp->src_port);
+		memmove(inline_ptr_udp, &udp->src_port,
+			sizeof(udp->dst_port) + sizeof(udp->src_port));
+	}
+
+	inline_ptr_udp -= sizeof(nhc);
+	*inline_ptr_udp = nhc;
+
+	return inline_ptr_udp;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+
+static struct net_6lo_context *get_src_addr_ctx(struct net_pkt *pkt,
+						struct net_ipv6_hdr *ipv6)
+{
+	/* If compress flag is unset means use only in uncompression. */
+	struct net_6lo_context *src;
+
+	src = get_6lo_context_by_addr(net_pkt_iface(pkt), &ipv6->src);
+	if (!src || !src->compress) {
+		return NULL;
+	}
+
+	return src;
+}
+
+static struct net_6lo_context *get_dst_addr_ctx(struct net_pkt *pkt,
+						struct net_ipv6_hdr *ipv6)
+{
+	/* If compress flag is unset means use only in uncompression. */
+	struct net_6lo_context *dst;
+
+	dst = get_6lo_context_by_addr(net_pkt_iface(pkt), &ipv6->dst);
+	if (!dst || !dst->compress) {
+		return NULL;
+	}
+
+	return dst;
+}
+#endif /* CONFIG_NET_6LO_CONTEXT */
+
+/* RFC 6282 LOWPAN IPHC Encoding format (3.1)
+ *  Base Format
+ *   0                                       1
+ *   0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ * | 0 | 1 | 1 |  TF   |NH | HLIM  |CID|SAC|  SAM  | M |DAC|  DAM  |
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ */
+static inline int compress_IPHC_header(struct net_pkt *pkt)
+{
+#if defined(CONFIG_NET_6LO_CONTEXT)
+	struct net_6lo_context *src_ctx = NULL;
+	struct net_6lo_context *dst_ctx = NULL;
+#endif
+	uint8_t compressed = 0;
+	uint16_t iphc = (NET_6LO_DISPATCH_IPHC << 8);
+	struct net_ipv6_hdr *ipv6 = NET_IPV6_HDR(pkt);
+	struct net_udp_hdr *udp;
+	uint8_t *inline_pos;
+
+	if (pkt->frags->len < NET_IPV6H_LEN) {
+		NET_ERR("Invalid length %d, min %d",
+			pkt->frags->len, NET_IPV6H_LEN);
+		return -EINVAL;
+	}
+
+	if (ipv6->nexthdr == IPPROTO_UDP &&
+	    pkt->frags->len < NET_IPV6UDPH_LEN) {
+		NET_ERR("Invalid length %d, min %d",
+			pkt->frags->len, NET_IPV6UDPH_LEN);
+		return -EINVAL;
+	}
+
+	inline_pos = pkt->buffer->data + NET_IPV6H_LEN;
+
+	if (ipv6->nexthdr == IPPROTO_UDP) {
+		udp = (struct net_udp_hdr *)inline_pos;
+		inline_pos += NET_UDPH_LEN;
+
+		inline_pos = compress_nh_udp(udp, inline_pos, false);
+	}
+
+	if (net_6lo_ll_prefix_padded_with_zeros(&ipv6->dst)) {
+		inline_pos = compress_da(ipv6, pkt, inline_pos, &iphc);
+		goto da_end;
+	}
+
+	if (net_ipv6_is_addr_mcast(&ipv6->dst)) {
+		inline_pos = compress_da_mcast(ipv6, inline_pos, &iphc);
+		goto da_end;
+	}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+	dst_ctx = get_dst_addr_ctx(pkt, ipv6);
+	if (dst_ctx) {
+		iphc |= NET_6LO_IPHC_CID_1;
+		inline_pos = compress_da_ctx(ipv6, inline_pos, pkt, &iphc,
+					     dst_ctx);
+		goto da_end;
+	}
+#endif
+	inline_pos = set_da_inline(ipv6, inline_pos, &iphc);
+da_end:
+
+	if (net_6lo_ll_prefix_padded_with_zeros(&ipv6->src)) {
+		inline_pos = compress_sa(ipv6, pkt, inline_pos, &iphc);
+		goto sa_end;
+	}
+
+	if (net_ipv6_is_addr_unspecified(&ipv6->src)) {
+		NET_DBG("SAM_00, SAC_1 unspecified src address");
+
+		/* Unspecified IPv6 src address */
+		iphc |= NET_6LO_IPHC_SAC_1;
+		iphc |= NET_6LO_IPHC_SAM_00;
+		goto sa_end;
+	}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+	src_ctx = get_src_addr_ctx(pkt, ipv6);
+	if (src_ctx) {
+		inline_pos = compress_sa_ctx(ipv6, inline_pos, pkt, &iphc,
+					     src_ctx);
+		iphc |= NET_6LO_IPHC_CID_1;
+		goto sa_end;
+	}
+#endif
+	inline_pos = set_sa_inline(ipv6, inline_pos, &iphc);
+sa_end:
+
+	inline_pos = compress_hoplimit(ipv6, inline_pos, &iphc);
+	inline_pos = compress_nh(ipv6, inline_pos, &iphc);
+	inline_pos = compress_tfl(ipv6, inline_pos, &iphc);
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+	if (iphc & NET_6LO_IPHC_CID_1) {
+		inline_pos -= sizeof(uint8_t);
+		*inline_pos = 0;
+
+		if (src_ctx) {
+			*inline_pos = src_ctx->cid << 4;
+		}
+
+		if (dst_ctx) {
+			*inline_pos |= dst_ctx->cid & 0x0F;
+		}
+	}
+#endif
+
+	inline_pos -= sizeof(iphc);
+	iphc = htons(iphc);
+	memmove(inline_pos, &iphc, sizeof(iphc));
+
+	compressed = inline_pos - pkt->buffer->data;
+
+	net_buf_pull(pkt->buffer, compressed);
+
+	return compressed;
+}
+
+/* Helper to uncompress Traffic class and Flow label */
+static inline uint8_t *uncompress_tfl(uint16_t iphc, uint8_t *cursor,
+				  struct net_ipv6_hdr *ipv6)
+{
+	uint8_t tcl;
+
+	/* Uncompress tcl and flow label */
+	switch (iphc & NET_6LO_IPHC_TF_11) {
+	case NET_6LO_IPHC_TF_00:
+		NET_DBG("ECN + DSCP + 4-bit Pad + Flow Label");
+
+		tcl = *cursor;
+		cursor++;
+		tcl = (tcl >> 6) | (tcl << 2);
+
+		ipv6->vtc |= ((tcl & 0xF0) >> 4);
+		ipv6->tcflow = ((tcl & 0x0F) << 4) | (*cursor & 0x0F);
+		cursor++;
+
+		memmove(&ipv6->flow, cursor, sizeof(ipv6->flow));
+		cursor += sizeof(ipv6->flow);
+		break;
+	case NET_6LO_IPHC_TF_01:
+		NET_DBG("ECN + 2-bit Pad + Flow Label, DSCP is elided");
+
+		tcl = ((*cursor & 0xF0) >> 6);
+		ipv6->tcflow = ((tcl & 0x0F) << 4) | (*cursor & 0x0F);
+		cursor++;
+
+		memmove(&ipv6->flow, cursor, sizeof(ipv6->flow));
+		cursor += sizeof(ipv6->flow);
+
+		break;
+	case NET_6LO_IPHC_TF_10:
+		NET_DBG("Flow label elided");
+
+		tcl = *cursor;
+		cursor++;
+		tcl = (tcl >> 6) | (tcl << 2);
+
+		ipv6->vtc |= ((tcl & 0xF0) >> 4);
+		ipv6->tcflow = (tcl & 0x0F) << 4;
+		ipv6->flow = 0U;
+
+		break;
+	case NET_6LO_IPHC_TF_11:
+		NET_DBG("Tcl and Flow label elided");
+
+		ipv6->tcflow = 0U;
+		ipv6->flow = 0U;
+
+		break;
+	}
+
+	return cursor;
+}
+
+/* Helper to uncompress Hoplimit */
+static inline uint8_t *uncompress_hoplimit(uint16_t iphc, uint8_t *cursor,
+				       struct net_ipv6_hdr *ipv6)
+{
+	switch (iphc & NET_6LO_IPHC_HLIM_MASK) {
+	case NET_6LO_IPHC_HLIM:
+		ipv6->hop_limit = *cursor;
+		cursor++;
+
+		break;
+	case NET_6LO_IPHC_HLIM1:
+		ipv6->hop_limit = 1U;
+
+		break;
+	case NET_6LO_IPHC_HLIM64:
+		ipv6->hop_limit = 64U;
+
+		break;
+	case NET_6LO_IPHC_HLIM255:
+		ipv6->hop_limit = 255U;
+
+		break;
+	}
+
+	return cursor;
+}
+
+/* Helper to uncompress Source Address */
+static inline uint8_t *uncompress_sa(uint16_t iphc, uint8_t *cursor,
+				 struct net_ipv6_hdr *ipv6,
+				 struct net_pkt *pkt)
+{
+
+	NET_DBG("SAC_0");
+
+	switch (iphc & NET_6LO_IPHC_SAM_MASK) {
+	case NET_6LO_IPHC_SAM_00:
+		NET_DBG("SAM_00 full src addr inlined");
+
+		memmove(ipv6->src.s6_addr, cursor, sizeof(ipv6->src.s6_addr));
+		cursor += sizeof(ipv6->src.s6_addr);
+
+		break;
+	case NET_6LO_IPHC_SAM_01:
+		NET_DBG("SAM_01 last 64 bits are inlined");
+
+		memmove(&ipv6->src.s6_addr[8], cursor, 8);
+		cursor += 8U;
+
+		ipv6->src.s6_addr32[0] = 0x00;
+		ipv6->src.s6_addr32[1] = 0x00;
+		ipv6->src.s6_addr[0] = 0xFE;
+		ipv6->src.s6_addr[1] = 0x80;
+
+		break;
+	case NET_6LO_IPHC_SAM_10:
+		NET_DBG("SAM_10 src addr 16 bit compressed");
+
+		memmove(&ipv6->src.s6_addr[14], cursor, 2);
+		cursor += 2U;
+		ipv6->src.s6_addr16[6] = 0x00;
+
+		ipv6->src.s6_addr32[0] = 0x00;
+		ipv6->src.s6_addr32[1] = 0x00;
+		ipv6->src.s6_addr32[2] = 0x00;
+		ipv6->src.s6_addr[0] = 0xFE;
+		ipv6->src.s6_addr[1] = 0x80;
+		ipv6->src.s6_addr[11] = 0xFF;
+		ipv6->src.s6_addr[12] = 0xFE;
+
+		break;
+	case NET_6LO_IPHC_SAM_11:
+		NET_DBG("SAM_11 generate src addr from ll");
+
+		net_ipv6_addr_create_iid(&ipv6->src, net_pkt_lladdr_src(pkt));
+
+		break;
+	}
+
+	return cursor;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+static inline uint8_t *uncompress_sa_ctx(uint16_t iphc, uint8_t *cursor,
+				     struct net_ipv6_hdr *ipv6,
+				     struct net_6lo_context *ctx,
+				     struct net_pkt *pkt)
+{
+	switch (iphc & NET_6LO_IPHC_SAM_MASK) {
+	case NET_6LO_IPHC_SAM_01:
+		NET_DBG("SAM_01 last 64 bits are inlined");
+
+		/* First 8 bytes are from context */
+		memmove(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+
+		/* And the rest are carried in-line*/
+		memmove(&ipv6->src.s6_addr[8], cursor, 8);
+		cursor += 8U;
+
+		break;
+	case NET_6LO_IPHC_SAM_10:
+		NET_DBG("SAM_10 src addr 16 bit compressed");
+
+		/* 16 bit carried in-line */
+		memmove(&ipv6->src.s6_addr[14], cursor, 2);
+		cursor += 2U;
+
+		/* First 8 bytes are from context */
+		memmove(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+
+		ipv6->src.s6_addr32[2] = 0x00;
+		ipv6->src.s6_addr16[6] = 0x00;
+		ipv6->src.s6_addr[11] = 0xFF;
+		ipv6->src.s6_addr[12] = 0xFE;
+
+		break;
+	case NET_6LO_IPHC_SAM_11:
+		NET_DBG("SAM_11 generate src addr from ll");
+
+		/* RFC 6282, 3.1.1. If SAC = 1 and SAM = 11
+		 * Derive addr using context information and
+		 * the encapsulating header.
+		 * (e.g., 802.15.4 or IPv6 source address).
+		 */
+		net_ipv6_addr_create_iid(&ipv6->src, net_pkt_lladdr_src(pkt));
+
+		/* net_ipv6_addr_create_iid will copy first 8 bytes
+		 * as link local prefix.
+		 * Overwrite first 8 bytes from context prefix here.
+		 */
+		memmove(&ipv6->src.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+		break;
+	}
+
+	return cursor;
+}
+#endif
+
+/* Helpers to uncompress Destination Address */
+static inline uint8_t *uncompress_da_mcast(uint16_t iphc, uint8_t *cursor,
+				       struct net_ipv6_hdr *ipv6)
+{
+	NET_DBG("Dst is multicast");
+
+	if (iphc & NET_6LO_IPHC_DAC_1) {
+		NET_WARN("Unsupported DAM options");
+		return 0;
+	}
+
+	/* If M=1 and DAC=0:
+	 * 00: 128 bits, The full address is carried in-line.
+	 * 01:  48 bits, The address takes the form ffXX::00XX:XXXX:XXXX.
+	 * 10:  32 bits, The address takes the form ffXX::00XX:XXXX.
+	 * 11:   8 bits, The address takes the form ff02::00XX.
+	 */
+
+	switch (iphc & NET_6LO_IPHC_DAM_MASK) {
+	case NET_6LO_IPHC_DAM_00:
+		NET_DBG("DAM_00 full dst addr inlined");
+
+		memmove(&ipv6->dst.s6_addr[0], cursor,
+			sizeof(ipv6->dst.s6_addr));
+
+		cursor += sizeof(ipv6->dst.s6_addr);
+		break;
+	case NET_6LO_IPHC_DAM_01:
+		NET_DBG("DAM_01 2nd byte and last five bytes");
+
+		ipv6->dst.s6_addr[1] = *cursor;
+		cursor++;
+		memmove(&ipv6->dst.s6_addr[11], cursor, 5);
+		cursor += 5U;
+
+
+		ipv6->dst.s6_addr[0] = 0xFF;
+		ipv6->dst.s6_addr16[1] = 0x00;
+		ipv6->dst.s6_addr32[1] = 0x00;
+		ipv6->dst.s6_addr[10] = 0x00;
+		ipv6->dst.s6_addr16[4] = 0x00;
+
+		break;
+	case NET_6LO_IPHC_DAM_10:
+		NET_DBG("DAM_10 2nd byte and last three bytes");
+
+		ipv6->dst.s6_addr[1] = *cursor;
+		cursor++;
+		memmove(&ipv6->dst.s6_addr[13], cursor, 3);
+		cursor += 3U;
+
+		ipv6->dst.s6_addr[0] = 0xFF;
+		ipv6->dst.s6_addr16[1] = 0x00;
+		ipv6->dst.s6_addr32[1] = 0x00;
+		ipv6->dst.s6_addr32[2] = 0x00;
+		ipv6->dst.s6_addr[12] = 0x00;
+
+		break;
+	case NET_6LO_IPHC_DAM_11:
+		NET_DBG("DAM_11 8 bit compressed");
+
+		ipv6->dst.s6_addr[15] = *cursor;
+		cursor++;
+		ipv6->dst.s6_addr[14] = 0x00;
+
+		ipv6->dst.s6_addr32[0] = 0x00;
+		ipv6->dst.s6_addr32[1] = 0x00;
+		ipv6->dst.s6_addr32[2] = 0x00;
+		ipv6->dst.s6_addr16[6] = 0x00;
+		ipv6->dst.s6_addr[0] = 0xFF;
+		ipv6->dst.s6_addr[1] = 0x02;
+
+		break;
+	}
+
+	return cursor;
+}
+
+/* Helper to uncompress Destination Address */
+static inline uint8_t *uncompress_da(uint16_t iphc, uint8_t *cursor,
+				 struct net_ipv6_hdr *ipv6,
+				 struct net_pkt *pkt)
+{
+	NET_DBG("DAC_0");
+
+	switch (iphc & NET_6LO_IPHC_DAM_MASK) {
+	case NET_6LO_IPHC_DAM_00:
+		NET_DBG("DAM_00 full dst addr inlined");
+
+		memmove(&ipv6->dst.s6_addr[0], cursor,
+			sizeof(ipv6->dst.s6_addr));
+		cursor += sizeof(ipv6->dst.s6_addr);
+
+		break;
+	case NET_6LO_IPHC_DAM_01:
+		NET_DBG("DAM_01 last 64 bits are inlined");
+
+		memmove(&ipv6->dst.s6_addr[8], cursor, 8);
+		cursor += 8U;
+
+		ipv6->dst.s6_addr32[0] = 0x00;
+		ipv6->dst.s6_addr32[1] = 0x00;
+		ipv6->dst.s6_addr[0] = 0xFE;
+		ipv6->dst.s6_addr[1] = 0x80;
+
+
+
+		break;
+	case NET_6LO_IPHC_DAM_10:
+		NET_DBG("DAM_10 dst addr 16 bit compressed");
+
+		memmove(&ipv6->dst.s6_addr[14], cursor, 2);
+		cursor += 2U;
+
+		ipv6->dst.s6_addr32[0] = 0x00;
+		ipv6->dst.s6_addr32[1] = 0x00;
+		ipv6->dst.s6_addr32[2] = 0x00;
+		ipv6->dst.s6_addr16[6] = 0x00;
+		ipv6->dst.s6_addr[0] = 0xFE;
+		ipv6->dst.s6_addr[1] = 0x80;
+		ipv6->dst.s6_addr[11] = 0xFF;
+		ipv6->dst.s6_addr[12] = 0xFE;
+
+		break;
+	case NET_6LO_IPHC_DAM_11:
+		NET_DBG("DAM_11 generate dst addr from ll");
+
+		net_ipv6_addr_create_iid(&ipv6->dst, net_pkt_lladdr_dst(pkt));
+
+		break;
+	}
+
+	return cursor;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+static inline uint8_t *uncompress_da_ctx(uint16_t iphc, uint8_t *cursor,
+				     struct net_ipv6_hdr *ipv6,
+				     struct net_6lo_context *ctx,
+				     struct net_pkt *pkt)
+{
+	NET_DBG("DAC_1");
+
+	switch (iphc & NET_6LO_IPHC_DAM_MASK) {
+	case NET_6LO_IPHC_DAM_01:
+		NET_DBG("DAM_01 last 64 bits are inlined");
+
+		/* Last 8 bytes carried in-line */
+		memmove(&ipv6->dst.s6_addr[8], cursor, 8);
+		cursor += 8U;
+
+		/* First 8 bytes are from context */
+		memmove(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+
+		break;
+	case NET_6LO_IPHC_DAM_10:
+		NET_DBG("DAM_10 src addr 16 bit compressed");
+
+		/* 16 bit carried in-line */
+		memmove(&ipv6->dst.s6_addr[14], cursor, 2);
+		cursor += 2U;
+
+		/* First 8 bytes are from context */
+		memmove(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+
+		ipv6->dst.s6_addr32[2] = 0x00;
+		ipv6->dst.s6_addr16[6] = 0x00;
+		ipv6->dst.s6_addr[11] = 0xFF;
+		ipv6->dst.s6_addr[12] = 0xFE;
+
+		break;
+	case NET_6LO_IPHC_DAM_11:
+		NET_DBG("DAM_11 generate src addr from ll");
+
+		/* RFC 6282, 3.1.1. If SAC = 1 and SAM = 11
+		 * Derive addr using context information and
+		 * the encapsulating header.
+		 * (e.g., 802.15.4 or IPv6 source address).
+		 */
+		net_ipv6_addr_create_iid(&ipv6->dst, net_pkt_lladdr_dst(pkt));
+
+		/* net_ipv6_addr_create_iid will copy first 8 bytes
+		 * as link local prefix.
+		 * Overwrite first 8 bytes from context prefix here.
+		 */
+		memmove(&ipv6->dst.s6_addr[0], &ctx->prefix.s6_addr[0], 8);
+
+		break;
+	}
+
+	return cursor;
+}
+#endif
+
+/* Helper to uncompress NH UDP */
+static uint8_t *uncompress_nh_udp(uint8_t nhc, uint8_t *cursor,
+				      struct net_udp_hdr *udp)
+{
+
+	/* Port uncompression
+	 * 00:  All 16 bits for src and dst are inlined
+	 * 01: src, 16 bits are lined, dst(0xf0) 8 bits are inlined
+	 * 10: dst, 16 bits are lined, src(0xf0) 8 bits are inlined
+	 * 11: src, dst (0xf0b) 4 bits are inlined
+	 */
+
+	/* UDP header uncompression */
+	switch (nhc & NET_6LO_NHC_UDP_PORT_11) {
+	case NET_6LO_NHC_UDP_PORT_00:
+		NET_DBG("src and dst ports are inlined");
+
+		memmove(&udp->src_port, cursor, sizeof(udp->src_port));
+		cursor += sizeof(udp->src_port);
+		memmove(&udp->dst_port, cursor, sizeof(udp->dst_port));
+		cursor += sizeof(udp->dst_port);
+
+		break;
+	case NET_6LO_NHC_UDP_PORT_01:
+		NET_DBG("src full, dst 8 bits inlined");
+
+		memmove(&udp->src_port, cursor, sizeof(udp->src_port));
+		cursor += sizeof(udp->src_port);
+		udp->dst_port = htons(((uint16_t)NET_6LO_NHC_UDP_8_BIT_PORT << 8) |
+				*cursor);
+		cursor++;
+
+		break;
+	case NET_6LO_NHC_UDP_PORT_10:
+		NET_DBG("src 8 bits, dst full inlined");
+
+		udp->src_port = htons(((uint16_t)NET_6LO_NHC_UDP_8_BIT_PORT << 8) |
+				*cursor);
+		cursor++;
+		memmove(&udp->dst_port, cursor, sizeof(udp->dst_port));
+		cursor += sizeof(udp->dst_port);
+
+		break;
+	case NET_6LO_NHC_UDP_PORT_11:
+		NET_DBG("src and dst 4 bits inlined");
+
+		udp->src_port = htons((NET_6LO_NHC_UDP_4_BIT_PORT << 4) |
+				(*cursor >> 4));
+
+		udp->dst_port = htons((NET_6LO_NHC_UDP_4_BIT_PORT << 4) |
+				(*cursor & 0x0F));
+		cursor++;
+
+		break;
+	}
+
+	if (!(nhc & NET_6LO_NHC_UDP_CHECKSUM)) {
+		memmove(&udp->chksum, cursor, sizeof(udp->chksum));
+		cursor += sizeof(udp->chksum);
+	}
+
+	return cursor;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+/* Helper function to uncompress src and dst contexts */
+static inline void uncompress_cid(struct net_pkt *pkt, uint8_t cid,
+				  struct net_6lo_context **src,
+				  struct net_6lo_context **dst)
+{
+	uint8_t cid_tmp;
+
+	/* Extract source and destination Context Index,
+	 * Either src or dest address is context based or both.
+	 */
+	cid_tmp = (cid >> 4) & 0x0F;
+	*src = get_6lo_context_by_cid(net_pkt_iface(pkt), cid_tmp);
+	if (!(*src)) {
+		NET_DBG("Unknown src cid %d", cid_tmp);
+	}
+
+	cid_tmp = cid & 0x0F;
+	*dst = get_6lo_context_by_cid(net_pkt_iface(pkt), cid_tmp);
+	if (!(*dst)) {
+		NET_DBG("Unknown dst cid %d", cid_tmp);
+	}
+}
+#endif
+
+static bool uncompress_IPHC_header(struct net_pkt *pkt)
+{
+	struct net_udp_hdr *udp = NULL;
+	struct net_buf *frag = NULL;
+	uint8_t nhc = 0;
+	int nhc_inline_size = 0;
+	struct net_ipv6_hdr *ipv6;
+	uint16_t len;
+	uint16_t iphc;
+	int inline_size, compressed_hdr_size;
+	size_t diff;
+	uint8_t *cursor;
+#if defined(CONFIG_NET_6LO_CONTEXT)
+	struct net_6lo_context *src = NULL;
+	struct net_6lo_context *dst = NULL;
+#endif
+
+	iphc = ntohs(UNALIGNED_GET((uint16_t *)pkt->buffer->data));
+
+	inline_size = get_ihpc_inlined_size(iphc);
+	if (inline_size < 0) {
+		return false;
+	}
+
+	compressed_hdr_size = sizeof(iphc) + inline_size;
+	diff = sizeof(struct net_ipv6_hdr) - compressed_hdr_size;
+
+	if (iphc & NET_6LO_IPHC_NH_MASK) {
+		nhc = *(pkt->buffer->data + sizeof(iphc) + inline_size);
+		if ((nhc & 0xF8) != NET_6LO_NHC_UDP_BARE) {
+			NET_ERR("Unsupported next header");
+			return false;
+		}
+
+		nhc_inline_size = get_udp_nhc_inlined_size(nhc);
+		compressed_hdr_size += sizeof(uint8_t) + nhc_inline_size;
+		diff += sizeof(struct net_udp_hdr) - sizeof(uint8_t) -
+			nhc_inline_size;
+	}
+
+	if (net_buf_tailroom(pkt->buffer) >= diff) {
+		NET_DBG("Enough tailroom. Uncompress inplace");
+		frag = pkt->buffer;
+		net_buf_add(frag, diff);
+		cursor = frag->data + diff;
+		memmove(cursor, frag->data, frag->len - diff);
+	} else {
+		NET_DBG("Not enough tailroom. Get new fragment");
+		cursor =  pkt->buffer->data;
+		frag = net_pkt_get_frag(pkt, NET_6LO_RX_PKT_TIMEOUT);
+		if (!frag) {
+			NET_ERR("Can't get frag for uncompression");
+			return false;
+		}
+
+		net_buf_pull(pkt->buffer, compressed_hdr_size);
+		net_buf_add(frag, nhc ? NET_IPV6UDPH_LEN : NET_IPV6H_LEN);
+	}
+
+	ipv6 = (struct net_ipv6_hdr *)(frag->data);
+	cursor += sizeof(iphc);
+
+	if (iphc & NET_6LO_IPHC_CID_1) {
+#if defined(CONFIG_NET_6LO_CONTEXT)
+		uncompress_cid(pkt, *cursor, &src, &dst);
+		cursor++;
+#else
+		NET_ERR("Context based uncompression not enabled");
+		return false;
+#endif
+	}
+
+	/* Version is always 6 */
+	ipv6->vtc = 0x60;
+	net_pkt_set_ip_hdr_len(pkt, NET_IPV6H_LEN);
+
+	/* Uncompress Traffic class and Flow label */
+	cursor = uncompress_tfl(iphc, cursor, ipv6);
+
+	if (!(iphc & NET_6LO_IPHC_NH_MASK)) {
+		ipv6->nexthdr = *cursor;
+		cursor++;
+	}
+
+	/* Uncompress Hoplimit */
+	cursor = uncompress_hoplimit(iphc, cursor, ipv6);
+
+	/* Uncompress Source Address */
+	if (iphc & NET_6LO_IPHC_SAC_1) {
+		NET_DBG("SAC_1");
+
+		if ((iphc & NET_6LO_IPHC_SAM_MASK) == NET_6LO_IPHC_SAM_00) {
+			NET_DBG("SAM_00 unspecified address");
+			memset(&ipv6->src.s6_addr[0], 0,
+				sizeof(ipv6->src.s6_addr));
+		} else if (IS_ENABLED(CONFIG_NET_6LO_CONTEXT)) {
+#if defined(CONFIG_NET_6LO_CONTEXT)
+			if (!src) {
+				NET_ERR("Src context doesn't exists");
+				goto fail;
+			}
+
+			cursor = uncompress_sa_ctx(iphc, cursor, ipv6, src, pkt);
+#endif
+		} else {
+			NET_ERR("Context based uncompression not enabled");
+			goto fail;
+		}
+	} else {
+		cursor = uncompress_sa(iphc, cursor, ipv6, pkt);
+	}
+
+	/* Uncompress Destination Address */
+	if (iphc & NET_6LO_IPHC_M_1) {
+		if (iphc & NET_6LO_IPHC_DAC_1) {
+			/* TODO: DAM00 Unicast-Prefix-based IPv6 Multicast
+			 * Addresses. DAM_01, DAM_10 and DAM_11 are reserved.
+			 */
+			NET_ERR("DAC_1 and M_1 is not supported");
+			goto fail;
+		} else {
+			cursor = uncompress_da_mcast(iphc, cursor, ipv6);
+		}
+	} else {
+		if (iphc & NET_6LO_IPHC_DAC_1) {
+#if defined(CONFIG_NET_6LO_CONTEXT)
+			if (!dst) {
+				NET_ERR("Dst context doesn't exists");
+				goto fail;
+			}
+
+			cursor = uncompress_da_ctx(iphc, cursor, ipv6, dst, pkt);
+#else
+			NET_ERR("Context based uncompression not enabled");
+			goto fail;
+#endif
+		} else {
+			cursor = uncompress_da(iphc, cursor, ipv6, pkt);
+		}
+	}
+
+	if (iphc & NET_6LO_IPHC_NH_MASK) {
+		ipv6->nexthdr = IPPROTO_UDP;
+		udp = (struct net_udp_hdr *)(frag->data + NET_IPV6H_LEN);
+		/* skip nhc */
+		cursor++;
+		cursor = uncompress_nh_udp(nhc, cursor, udp);
+	}
+
+	if (frag != pkt->buffer) {
+		/* Insert the fragment (this one holds uncompressed headers) */
+		net_pkt_frag_insert(pkt, frag);
+	}
+
+	/* Set IPv6 header and UDP (if next header is) length */
+	len = net_pkt_get_len(pkt) - NET_IPV6H_LEN;
+	ipv6->len = htons(len);
+
+	if (ipv6->nexthdr == IPPROTO_UDP && udp) {
+		udp->len = htons(len);
+
+		if (nhc & NET_6LO_NHC_UDP_CHECKSUM) {
+			udp->chksum = net_calc_chksum_udp(pkt);
+		}
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	return true;
+
+fail:
+	if (frag != pkt->buffer) {
+		net_pkt_frag_unref(frag);
+	}
+
+	return false;
+}
+
+/* Adds IPv6 dispatch as first byte and adjust fragments  */
+static inline int compress_ipv6_header(struct net_pkt *pkt)
+{
+	struct net_buf *buffer = pkt->buffer;
+
+	if (net_buf_tailroom(buffer) >= 1U) {
+		memmove(buffer->data + 1U, buffer->data, buffer->len);
+		net_buf_add(buffer, 1U);
+		buffer->data[0] = NET_6LO_DISPATCH_IPV6;
+		return 0;
+	}
+
+	buffer = net_pkt_get_frag(pkt, K_FOREVER);
+	if (!buffer) {
+		return -ENOBUFS;
+	}
+
+	buffer->data[0] = NET_6LO_DISPATCH_IPV6;
+	net_buf_add(buffer, 1);
+
+	net_pkt_frag_insert(pkt, buffer);
+
+	/* Compact the fragments, so that gaps will be filled */
+	net_pkt_compact(pkt);
+
+	return 0;
+}
+
+static inline bool uncompress_ipv6_header(struct net_pkt *pkt)
+{
+	/* Pull off IPv6 dispatch header and adjust data and length */
+	net_buf_pull(pkt->buffer, 1U);
+	net_pkt_cursor_init(pkt);
+
+	return true;
+}
+
+int net_6lo_compress(struct net_pkt *pkt, bool iphc)
+{
+	if (iphc) {
+		return compress_IPHC_header(pkt);
+	} else {
+		return compress_ipv6_header(pkt);
+	}
+}
+
+bool net_6lo_uncompress(struct net_pkt *pkt)
+{
+	NET_ASSERT(pkt && pkt->frags);
+
+	if ((pkt->frags->data[0] & NET_6LO_DISPATCH_IPHC_MASK) ==
+	    NET_6LO_DISPATCH_IPHC) {
+		/* Uncompress IPHC header */
+		return uncompress_IPHC_header(pkt);
+
+	} else if (pkt->frags->data[0] == NET_6LO_DISPATCH_IPV6) {
+		/* Uncompress IPv6 header, it has only IPv6 dispatch in the
+		 * beginning */
+		return uncompress_ipv6_header(pkt);
+	}
+
+	NET_DBG("pkt %p is not compressed", pkt);
+
+	return true;
+}
+
+int net_6lo_uncompress_hdr_diff(struct net_pkt *pkt)
+{
+	int inline_size, compressed_hdr_size, nhc_inline_size, diff;
+	uint16_t iphc;
+	uint8_t nhc;
+
+	if (pkt->frags->data[0] == NET_6LO_DISPATCH_IPV6) {
+		return -1;
+	}
+
+	if ((pkt->frags->data[0] & NET_6LO_DISPATCH_IPHC_MASK) !=
+	    NET_6LO_DISPATCH_IPHC) {
+		return 0;
+	}
+
+	iphc = ntohs(UNALIGNED_GET((uint16_t *)pkt->buffer->data));
+
+	inline_size = get_ihpc_inlined_size(iphc);
+	if (inline_size < 0) {
+		return INT_MAX;
+	}
+
+	compressed_hdr_size = sizeof(iphc) + inline_size;
+	diff = sizeof(struct net_ipv6_hdr) - compressed_hdr_size;
+
+	if (iphc & NET_6LO_IPHC_NH_MASK) {
+		nhc = *(pkt->buffer->data + sizeof(iphc) + inline_size);
+		if ((nhc & 0xF8) != NET_6LO_NHC_UDP_BARE) {
+			NET_ERR("Unsupported next header");
+			return INT_MAX;
+		}
+
+		nhc_inline_size = get_udp_nhc_inlined_size(nhc);
+		compressed_hdr_size += sizeof(uint8_t) + nhc_inline_size;
+		diff += sizeof(struct net_udp_hdr) - sizeof(uint8_t) -
+			nhc_inline_size;
+	}
+
+	return diff;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo_private.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo_private.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/6lo_private.h	(working copy)
@@ -0,0 +1,124 @@
+/** @file
+ @brief 6lowpan private header
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+
+/* 6lopan dispatches */
+#define NET_6LO_DISPATCH_IPV6		0x41 /* 01000001 */
+#define NET_6LO_DISPATCH_BROADCAST	0x50 /* 01010000 */
+#define NET_6LO_DISPATCH_IPHC		0x60 /* 01100000 */
+#define NET_6LO_DISPATCH_MESH		0x80 /* 10xxxxxx */
+#define NET_6LO_DISPATCH_FRAG1		0xC0 /* 11000xxx */
+#define NET_6LO_DISPATCH_FRAGN		0xE0 /* 11100xxx */
+
+#define NET_6LO_DISPATCH_IPHC_MASK	0xE0
+/**
+  * TF (Traffic class and Flow label)
+  * 00:  ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+  * 01:  ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.
+  * 10:  ECN + DSCP (1 byte), Flow Label is elided.
+  * 11:  Traffic Class and Flow Label are elided.
+  */
+#define NET_6LO_IPHC_TF_POS		11
+#define NET_6LO_IPHC_TF_MASK		(0x03 << NET_6LO_IPHC_TF_POS)
+#define NET_6LO_IPHC_TF_00		(0x00 << NET_6LO_IPHC_TF_POS)
+#define NET_6LO_IPHC_TF_01		(0x01 << NET_6LO_IPHC_TF_POS)
+#define NET_6LO_IPHC_TF_10		(0x02 << NET_6LO_IPHC_TF_POS)
+#define NET_6LO_IPHC_TF_11		(0x03 << NET_6LO_IPHC_TF_POS)
+
+/* NH (next header) */
+#define NET_6LO_IPHC_NH_POS		10
+#define NET_6LO_IPHC_NH_MASK	(0x01 << NET_6LO_IPHC_NH_POS)
+#define NET_6LO_IPHC_NH_0		(0x00 << NET_6LO_IPHC_NH_POS)
+#define NET_6LO_IPHC_NH_1		(0x01 << NET_6LO_IPHC_NH_POS)
+
+/* HLIM (Hop Limit) */
+#define NET_6LO_IPHC_HLIM_POS		8
+#define NET_6LO_IPHC_HLIM_MASK		(0x03 << NET_6LO_IPHC_HLIM_POS)
+#define NET_6LO_IPHC_HLIM		(0x00 << NET_6LO_IPHC_HLIM_POS) /* 00 */
+#define NET_6LO_IPHC_HLIM1		(0x01 << NET_6LO_IPHC_HLIM_POS) /* 01 */
+#define NET_6LO_IPHC_HLIM64		(0x02 << NET_6LO_IPHC_HLIM_POS) /* 10 */
+#define NET_6LO_IPHC_HLIM255		(0x03 << NET_6LO_IPHC_HLIM_POS) /* 11 */
+
+/* CID (Context Identifier Extension) */
+#define NET_6LO_IPHC_CID_POS		7
+#define NET_6LO_IPHC_CID_MASK		(0x01 << NET_6LO_IPHC_CID_POS)
+#define NET_6LO_IPHC_CID_0		(0x00 << NET_6LO_IPHC_CID_POS)
+#define NET_6LO_IPHC_CID_1		(0x01 << NET_6LO_IPHC_CID_POS)
+
+/* SAC (Source Address Compression) */
+#define NET_6LO_IPHC_SAC_POS		6
+#define NET_6LO_IPHC_SAC_MASK		(0x01 << NET_6LO_IPHC_SAC_POS)
+#define NET_6LO_IPHC_SAC_0		(0x00 << NET_6LO_IPHC_SAC_POS)
+#define NET_6LO_IPHC_SAC_1		(0x01 << NET_6LO_IPHC_SAC_POS)
+
+/* SAM (Source Address Mode) */
+#define NET_6LO_IPHC_SAM_POS		4
+#define NET_6LO_IPHC_SAM_MASK		(0x03 << NET_6LO_IPHC_SAM_POS)
+#define NET_6LO_IPHC_SAM_00		(0x00 << NET_6LO_IPHC_SAM_POS)
+#define NET_6LO_IPHC_SAM_01		(0x01 << NET_6LO_IPHC_SAM_POS)
+#define NET_6LO_IPHC_SAM_10		(0x02 << NET_6LO_IPHC_SAM_POS)
+#define NET_6LO_IPHC_SAM_11		(0x03 << NET_6LO_IPHC_SAM_POS)
+
+#define NET_6LO_IPHC_SA_MASK		(NET_6LO_IPHC_SAC_MASK | \
+					 NET_6LO_IPHC_SAM_MASK)
+
+/* M (Multicast compression) */
+#define NET_6LO_IPHC_M_POS		3
+#define NET_6LO_IPHC_M_MASK		(0x01 << NET_6LO_IPHC_M_POS)
+#define NET_6LO_IPHC_M_0		(0x00 << NET_6LO_IPHC_M_POS)
+#define NET_6LO_IPHC_M_1		(0x01 << NET_6LO_IPHC_M_POS)
+
+/* DAC (Destination Address Compression) */
+#define NET_6LO_IPHC_DAC_POS		2
+#define NET_6LO_IPHC_DAC_MASK		(0x01 << NET_6LO_IPHC_DAC_POS)
+#define NET_6LO_IPHC_DAC_0		(0x00 << NET_6LO_IPHC_DAC_POS)
+#define NET_6LO_IPHC_DAC_1		(0x01 << NET_6LO_IPHC_DAC_POS)
+
+/* DAM (Destination Address Mode) */
+#define NET_6LO_IPHC_DAM_POS		0
+#define NET_6LO_IPHC_DAM_MASK		(0x03 << NET_6LO_IPHC_DAM_POS)
+#define NET_6LO_IPHC_DAM_00		(0x00 << NET_6LO_IPHC_DAM_POS)
+#define NET_6LO_IPHC_DAM_01		(0x01 << NET_6LO_IPHC_DAM_POS)
+#define NET_6LO_IPHC_DAM_10		(0x02 << NET_6LO_IPHC_DAM_POS)
+#define NET_6LO_IPHC_DAM_11		(0x03 << NET_6LO_IPHC_DAM_POS)
+
+#define NET_6LO_IPHC_DA_MASK		(NET_6LO_IPHC_DAC_MASK | \
+					 NET_6LO_IPHC_DAM_MASK | \
+					 NET_6LO_IPHC_M_MASK)
+
+/* Next Header UDP */
+#define NET_6LO_NHC_UDP_BARE		0xF0
+
+#define NET_6LO_NHC_UDP_CHKSUM_0	0x00
+#define NET_6LO_NHC_UDP_CHKSUM_1	0x08
+
+#define NET_6LO_NHC_UDP_PORT_MASK 0x03
+#define NET_6LO_NHC_UDP_PORT_00		0x00
+#define NET_6LO_NHC_UDP_PORT_01		0x01
+#define NET_6LO_NHC_UDP_PORT_10		0x02
+#define NET_6LO_NHC_UDP_PORT_11		0x03
+#define NET_6LO_NHC_UDP_CHECKSUM	0x04
+#define NET_6LO_NHC_UDP_8_BIT_PORT	0xF0
+#define NET_6LO_NHC_UDP_4_BIT_PORT	0xF0B
+
+#define NET_6LO_FRAG1_HDR_LEN		4
+#define NET_6LO_FRAGN_HDR_LEN		5
+
+#define NET_6LO_FRAG_DATAGRAM_SIZE_LEN		2
+#define NET_6LO_FRAG_DATAGRAM_OFFSET_LEN	2
+
+/* Timeout when getting net_buf in RX path. In RX, we must not wait forever as
+ * that can cause the stack to deadlock. This can happen if RX side is flooding
+ * incoming data and we cannot get process the packet in 6lo side.
+ */
+#define NET_6LO_RX_PKT_TIMEOUT K_MSEC(100) /* in ms */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/CMakeLists.txt	(working copy)
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(.)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources(
+  net_core.c
+  net_if.c
+  utils.c
+  )
+
+if(CONFIG_NET_OFFLOAD)
+zephyr_library_sources(net_context.c net_pkt.c net_tc.c)
+endif()
+
+zephyr_library_sources_ifdef(CONFIG_NET_MGMT_EVENT   net_mgmt.c)
+
+if(CONFIG_NET_NATIVE)
+zephyr_library_sources(net_context.c)
+zephyr_library_sources(net_pkt.c)
+zephyr_library_sources(net_tc.c)
+zephyr_library_sources_ifdef(CONFIG_NET_6LO          6lo.c)
+zephyr_library_sources_ifdef(CONFIG_NET_DHCPV4       dhcpv4.c)
+zephyr_library_sources_ifdef(CONFIG_NET_IPV4_AUTO    ipv4_autoconf.c)
+zephyr_library_sources_ifdef(CONFIG_NET_IPV4         icmpv4.c       ipv4.c)
+zephyr_library_sources_ifdef(CONFIG_NET_IPV6         icmpv6.c nbr.c
+                                                     ipv6.c ipv6_nbr.c)
+zephyr_library_sources_ifdef(CONFIG_NET_IPV6_MLD     ipv6_mld.c)
+zephyr_library_sources_ifdef(CONFIG_NET_IPV6_FRAGMENT     ipv6_fragment.c)
+zephyr_library_sources_ifdef(CONFIG_NET_ROUTE        route.c)
+zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS   net_stats.c)
+zephyr_library_sources_ifdef(CONFIG_NET_TCP1         connection.c tcp.c)
+zephyr_library_sources_ifdef(CONFIG_NET_TCP2         connection.c tcp2.c)
+zephyr_library_sources_ifdef(CONFIG_NET_TEST_PROTOCOL           tp.c)
+zephyr_library_sources_ifdef(CONFIG_NET_TRICKLE      trickle.c)
+zephyr_library_sources_ifdef(CONFIG_NET_UDP          connection.c udp.c)
+zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_PACKET  connection.c
+                                                        packet_socket.c)
+zephyr_library_sources_ifdef(CONFIG_NET_SOCKETS_CAN  connection.c
+                                                     canbus_socket.c)
+zephyr_library_sources_ifdef(CONFIG_NET_PROMISCUOUS_MODE promiscuous.c)
+endif()
+
+zephyr_library_include_directories(
+  ${ZEPHYR_BASE}/kernel/include
+  ${ARCH_DIR}/${ARCH}/include
+  )
+
+if(CONFIG_NET_SHELL)
+zephyr_library_sources(net_shell.c)
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/l2)
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/lib)
+zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig	(working copy)
@@ -0,0 +1,779 @@
+# IP stack config
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menu "IP stack"
+
+config NET_NATIVE
+	bool "Enable native IP stack"
+	default y
+	help
+	  Enables Zephyr native IP stack. If you disable this, then
+	  you need to enable the offloading support if you want to
+	  have IP connectivity.
+
+# Hidden options for enabling native IPv6/IPv4. Using these options
+# avoids having "defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_NATIVE)"
+# in the code as we can have "defined(CONFIG_NET_NATIVE_IPV6)" instead.
+config NET_NATIVE_IPV6
+	bool
+	depends on NET_NATIVE
+	default y if NET_IPV6
+
+config NET_NATIVE_IPV4
+	bool
+	depends on NET_NATIVE
+	default y if NET_IPV4
+
+config NET_NATIVE_TCP
+	bool
+	depends on NET_NATIVE
+	default y if NET_TCP
+
+config NET_NATIVE_UDP
+	bool
+	depends on NET_NATIVE
+	default y if NET_UDP
+
+config NET_OFFLOAD
+	bool "Offload IP stack [EXPERIMENTAL]"
+	help
+	  Enables TCP/IP stack to be offload to a co-processor.
+
+if NET_OFFLOAD
+module = NET_OFFLOAD
+module-dep = NET_LOG
+module-str = Log level for offload layer
+module-help = Enables offload layer to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_OFFLOAD
+
+config NET_RAW_MODE
+	bool
+	help
+	  This is a very specific option used to built only the very minimal
+	  part of the net stack in order to get network drivers working without
+	  any net stack above: core, L2 etc... Basically this will build only
+	  net_pkt part. It is currently used only by IEEE 802.15.4 drivers,
+	  though any type of net drivers could use it.
+
+if !NET_RAW_MODE
+
+choice
+	prompt "Qemu networking"
+	default NET_QEMU_PPP if NET_PPP
+	default NET_QEMU_SLIP
+	depends on QEMU_TARGET
+	help
+	  Can be used to select how the network connectivity is established
+	  from inside qemu to host system. This can be done either via
+	  serial connection (SLIP) or via Qemu ethernet driver.
+
+config NET_QEMU_SLIP
+	bool "SLIP"
+	help
+	  Connect to host or to another Qemu via SLIP.
+
+config NET_QEMU_PPP
+	bool "PPP"
+	help
+	  Connect to host via PPP.
+
+config NET_QEMU_ETHERNET
+	bool "Ethernet"
+	help
+	  Connect to host system via Qemu ethernet driver support. One such
+	  driver that Zephyr supports is Intel e1000 ethernet driver.
+
+config NET_QEMU_USER
+	bool "SLIRP"
+	help
+	  Connect to host system via Qemu's built-in User Networking support. This
+	  is implemented using "slirp", which provides a full TCP/IP stack within
+	  QEMU and uses that stack to implement a virtual NAT'd network.
+
+endchoice
+
+config NET_QEMU_USER_EXTRA_ARGS
+	string "Qemu User Networking Args"
+	depends on NET_QEMU_USER
+	default ""
+	help
+	  Extra arguments passed to QEMU when User Networking is enabled. This may
+	  include host / guest port forwarding, device id, Network address
+	  information etc. This string is appended to the QEMU "-net user" option.
+
+config NET_INIT_PRIO
+	int
+	default 90
+	help
+	  Network initialization priority level. This number tells how
+	  early in the boot the network stack is initialized.
+
+source "subsys/net/ip/Kconfig.ipv6"
+
+source "subsys/net/ip/Kconfig.ipv4"
+
+config NET_SHELL
+	bool "Enable network shell utilities"
+	select SHELL
+	help
+	  Activate shell module that provides network commands like
+	  ping to the console.
+
+config NET_SHELL_DYN_CMD_COMPLETION
+	bool "Enable network shell dynamic command completion"
+	depends on NET_SHELL
+	default y
+	help
+	  Enable various net-shell command to support dynamic command
+	  completion. This means that for example the nbr command can
+	  automatically complete the neighboring IPv6 address and user
+	  does not need to type it manually.
+	  Please note that this uses more memory in order to save the
+	  dynamic command strings. For example for nbr command the
+	  increase is 320 bytes (8 neighbors * 40 bytes for IPv6 address
+	  length) by default. Other dynamic completion commands in
+	  net-shell require also some smaller amount of memory.
+
+config NET_TC_TX_COUNT
+	int "How many Tx traffic classes to have for each network device"
+	default 1
+	range 1 8
+	help
+	  Define how many Tx traffic classes (queues) the system should have
+	  when sending a network packet. The network packet priority can then
+	  be mapped to this traffic class so that higher prioritized packets
+	  can be processed before lower prioritized ones. Each queue is handled
+	  by a separate thread which will need RAM for stack space.
+	  Only increase the value from 1 if you really need this feature.
+	  The default value is 1 which means that all the network traffic is
+	  handled equally. In this implementation, the higher traffic class
+	  value corresponds to lower thread priority.
+
+config NET_TC_RX_COUNT
+	int "How many Rx traffic classes to have for each network device"
+	default 1
+	range 1 8
+	help
+	  Define how many Rx traffic classes (queues) the system should have
+	  when receiving a network packet. The network packet priority can then
+	  be mapped to this traffic class so that higher prioritized packets
+	  can be processed before lower prioritized ones. Each queue is handled
+	  by a separate thread which will need RAM for stack space.
+	  Only increase the value from 1 if you really need this feature.
+	  The default value is 1 which means that all the network traffic is
+	  handled equally. In this implementation, the higher traffic class
+	  value corresponds to lower thread priority.
+
+choice
+	prompt "Priority to traffic class mapping"
+	help
+	  Select mapping to use to map network packet priorities to traffic
+	  classes.
+
+config NET_TC_MAPPING_STRICT
+	bool "Strict priority mapping"
+	help
+	  This is the recommended default priority to traffic class mapping.
+	  Use it for implementations that do not support the credit-based
+	  shaper transmission selection algorithm.
+	  See 802.1Q, chapter 8.6.6 for more information.
+
+config NET_TC_MAPPING_SR_CLASS_A_AND_B
+	bool "SR class A and class B mapping"
+	depends on NET_TC_TX_COUNT >= 2
+	depends on NET_TC_RX_COUNT >= 2
+	help
+	  This is the recommended priority to traffic class mapping for a
+	  system that supports SR (Stream Reservation) class A and SR class B.
+	  See 802.1Q, chapter 34.5 for more information.
+
+config NET_TC_MAPPING_SR_CLASS_B_ONLY
+	bool "SR class B only mapping"
+	depends on NET_TC_TX_COUNT >= 2
+	depends on NET_TC_RX_COUNT >= 2
+	help
+	  This is the recommended priority to traffic class mapping for a
+	  system that supports SR (Stream Reservation) class B only.
+	  See 802.1Q, chapter 34.5 for more information.
+endchoice
+
+config NET_TX_DEFAULT_PRIORITY
+	int "Default network TX packet priority if none have been set"
+	default 1
+	range 0 7
+	help
+	  What is the default network packet priority if user has not specified
+	  one. The value 0 means lowest priority and 7 is the highest.
+
+config NET_RX_DEFAULT_PRIORITY
+	int "Default network RX packet priority if none have been set"
+	default 0
+	range 0 7
+	help
+	  What is the default network RX packet priority if user has not set
+	  one. The value 0 means lowest priority and 7 is the highest.
+
+config NET_IP_ADDR_CHECK
+	bool "Check IP address validity before sending IP packet"
+	default y
+	help
+	  Check that either the source or destination address is
+	  correct before sending either IPv4 or IPv6 network packet.
+
+config NET_MAX_ROUTERS
+	int "How many routers are supported"
+	default 2 if NET_IPV4 && NET_IPV6
+	default 1 if NET_IPV4 && !NET_IPV6
+	default 1 if !NET_IPV4 && NET_IPV6
+	range 1 254
+	help
+	  The value depends on your network needs.
+
+# Normally the route support is enabled by RPL or similar technology
+# that needs to use the routing infrastructure.
+config NET_ROUTE
+	bool
+	depends on NET_IPV6_NBR_CACHE
+	default y if NET_IPV6_NBR_CACHE
+
+# Temporarily hide the routing option as we do not have RPL in the system
+# that used to populate the routing table.
+config NET_ROUTING
+	bool
+	depends on NET_ROUTE
+	help
+	  Allow IPv6 routing between different network interfaces and
+	  technologies. Currently this has limited use as some entity
+	  would need to populate the routing table. RPL used to do that
+	  earlier but currently there is no RPL support in Zephyr.
+
+config NET_MAX_ROUTES
+	int "Max number of routing entries stored."
+	default NET_IPV6_MAX_NEIGHBORS
+	depends on NET_ROUTE
+	help
+	  This determines how many entries can be stored in routing table.
+
+config NET_MAX_NEXTHOPS
+	int "Max number of next hop entries stored."
+	default NET_MAX_ROUTES
+	depends on NET_ROUTE
+	help
+	  This determines how many entries can be stored in nexthop table.
+
+config NET_ROUTE_MCAST
+	bool "Enable Multicast Routing / Forwarding"
+	depends on NET_ROUTE
+	help
+	  Activates multicast routing/forwarding
+
+config NET_MAX_MCAST_ROUTES
+	int "Max number of multicast routing entries stored."
+	default 1
+	depends on NET_ROUTE_MCAST
+	help
+	  This determines how many entries can be stored in multicast
+	  routing table.
+
+config NET_TCP
+	bool "Enable TCP"
+	help
+	  The value depends on your network needs.
+
+config NET_TCP_CHECKSUM
+	bool "Check TCP checksum"
+	default y
+	depends on NET_TCP
+	help
+	  Enables TCP handler to check TCP checksum. If the checksum is invalid,
+	  then the packet is discarded.
+
+if NET_TCP
+module = NET_TCP
+module-dep = NET_LOG
+module-str = Log level for TCP
+module-help = Enables TCP handler output debug messages
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_TCP
+
+config NET_TCP_BACKLOG_SIZE
+	int "Number of simultaneous incoming TCP connections"
+	depends on NET_TCP
+	default 1
+	range 1 128
+	help
+	  The number of simultaneous TCP connection attempts, i.e. outstanding
+	  TCP connections waiting for initial ACK.
+
+config NET_TCP_AUTO_ACCEPT
+	bool "Auto accept incoming TCP data"
+	depends on NET_TCP
+	help
+	  Automatically accept incoming TCP data packet to the valid
+	  connection even if the application has not yet called accept().
+	  This speeds up incoming data processing and is done like in Linux.
+	  Drawback is that we allocate data for the incoming packets even if
+	  the application has not yet accepted the connection. If the peer
+	  sends lot of packets, we might run out of memory in this case.
+
+config NET_TCP_TIME_WAIT_DELAY
+	int "How long to wait in TIME_WAIT state (in milliseconds)"
+	depends on NET_TCP
+	default 250
+	help
+	  To avoid a (low-probability) issue when delayed packets from
+	  previous connection get delivered to next connection reusing
+	  the same local/remote ports, RFC 793 (TCP) suggests to keep
+	  an old, closed connection in a special "TIME_WAIT" state for
+	  the duration of 2*MSL (Maximum Segment Lifetime). The RFC
+	  suggests to use MSL of 2 minutes, but notes "This is an
+	  engineering choice, and may be changed if experience indicates
+	  it is desirable to do so." For low-resource systems, having
+	  large MSL may lead to quick resource exhaustion (and related
+	  DoS attacks). At the same time, the issue of packet misdelivery
+	  is largely alleviated in the modern TCP stacks by using random,
+	  non-repeating port numbers and initial sequence numbers. Due
+	  to this, Zephyr uses much lower value of 250ms by default.
+	  Value of 0 disables TIME_WAIT state completely.
+
+config NET_TCP_ACK_TIMEOUT
+	int "How long to wait for ACK (in milliseconds)"
+	depends on NET_TCP
+	default 1000
+	range 1 2147483647
+	help
+	  This value affects the timeout when waiting ACK to arrive in
+	  various TCP states. The value is in milliseconds. Note that
+	  having a very low value here could prevent connectivity.
+
+config NET_TCP_INIT_RETRANSMISSION_TIMEOUT
+	int "Initial value of Retransmission Timeout (RTO) (in milliseconds)"
+	depends on NET_TCP
+	default 200
+	range 100 60000
+	help
+	  This value affects the timeout between initial retransmission
+	  of TCP data packets. The value is in milliseconds.
+
+config NET_TCP_RETRY_COUNT
+	int "Maximum number of TCP segment retransmissions"
+	depends on NET_TCP
+	default 9
+	help
+	  The following formula can be used to determine the time (in ms)
+	  that a segment will be be buffered awaiting retransmission:
+	  n=NET_TCP_RETRY_COUNT
+	  Sum((1<<n) * NET_TCP_INIT_RETRANSMISSION_TIMEOUT)
+	  n=0
+	  With the default value of 9, the IP stack will try to
+	  retransmit for up to 1:42 minutes.  This is as close as possible
+	  to the minimum value recommended by RFC1122 (1:40 minutes).
+	  Only 5 bits are dedicated for the retransmission count, so accepted
+	  values are in the 0-31 range.  It's highly recommended to not go
+	  below 9, though.
+	  Should a retransmission timeout occur, the receive callback is
+	  called with -ECONNRESET error code and the context is dereferenced.
+
+config NET_TCP_MAX_SEND_WINDOW_SIZE
+	int "Maximum sending window size to use"
+	depends on NET_TCP2
+	default 0
+	range 0 65535
+	help
+	  This value affects how the TCP selects the maximum sending window
+	  size. The default value 0 lets the TCP stack select the value
+	  according to amount of network buffers configured in the system.
+
+choice
+	prompt "Select TCP stack"
+	depends on NET_TCP
+	default NET_TCP2
+	help
+	  Select the TCP stack implementation to use.
+
+config NET_TCP2
+	bool "New TCP stack"
+	help
+	  Enable new TCP stack for Zephyr 2.4
+
+config NET_TCP1
+	bool "Legacy TCP stack"
+	help
+	  The legacy TCP stack that has been in use since Zephyr 1.0.
+
+endchoice
+
+config NET_TEST_PROTOCOL
+	bool "Enable JSON based test protocol (UDP)"
+	help
+	  Enable JSON based test protocol (UDP).
+
+config NET_UDP
+	bool "Enable UDP"
+	default y
+	help
+	  The value depends on your network needs.
+
+config NET_UDP_CHECKSUM
+	bool "Check UDP checksum"
+	default y
+	depends on NET_UDP
+	help
+	  Enables UDP handler to check UDP checksum. If the checksum is invalid,
+	  then the packet is discarded.
+
+config NET_UDP_MISSING_CHECKSUM
+	bool "Accept missing checksum (IPv4 only)"
+	depends on NET_UDP && NET_IPV4
+	help
+	  RFC 768 states the possibility to have a missing checksum, for
+	  debugging purposes for instance. That feature is however valid only
+	  for IPv4 and on reception only, since Zephyr will always compute the
+	  UDP checksum in transmission path.
+
+if NET_UDP
+module = NET_UDP
+module-dep = NET_LOG
+module-str = Log level for UDP
+module-help = Enables UDP handler output debug messages
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_UDP
+
+config NET_MAX_CONN
+	int "How many network connections are supported"
+	depends on NET_UDP || NET_TCP || NET_SOCKETS_PACKET || NET_SOCKETS_CAN
+	default 8 if NET_IPV6 && NET_IPV4
+	default 4
+	help
+	  The value depends on your network needs. The value
+	  should include both UDP and TCP connections.
+
+config NET_MAX_CONTEXTS
+	int "Number of network contexts to allocate"
+	default 6
+	help
+	  Each network context is used to describe a network 5-tuple that
+	  is used when listening or sending network traffic. This is very
+	  similar as one could call a network socket in some other systems.
+
+config NET_CONTEXT_NET_PKT_POOL
+	bool "Enable net_buf TX pool / context"
+	default y if NET_TCP && NET_6LO
+	help
+	  If enabled, then it is possible to fine-tune network packet pool
+	  for each context when sending network data. If this setting is
+	  enabled, then you should define the context pools in your application
+	  using NET_PKT_TX_POOL_DEFINE() and NET_PKT_DATA_POOL_DEFINE()
+	  macros and tie these pools to desired context using the
+	  net_context_setup_pools() function.
+
+config NET_CONTEXT_SYNC_RECV
+	bool "Support synchronous functionality in net_context_recv() API"
+	default y
+	help
+	  You can disable sync support to save some memory if you are calling
+	  net_context_recv() in async way only when timeout is set to 0.
+
+config NET_CONTEXT_CHECK
+	bool "Check options when calling various net_context functions"
+	default y
+	help
+	  If you know that the options passed to net_context...() functions
+	  are ok, then you can disable the checks to save some memory.
+
+config NET_CONTEXT_PRIORITY
+	bool "Add priority support to net_context"
+	help
+	  It is possible to prioritize network traffic. This requires
+	  also traffic class support to work as expected.
+
+config NET_CONTEXT_TIMESTAMP
+	bool "Add timestamp support to net_context"
+	select NET_PKT_TIMESTAMP
+	help
+	  It is possible to timestamp outgoing packets and get information
+	  about these timestamps.
+
+config NET_CONTEXT_TXTIME
+	bool "Add TXTIME support to net_context"
+	select NET_PKT_TXTIME
+	help
+	  It is possible to add information when the outgoing network packet
+	  should be sent. The TX time information should be placed into
+	  ancillary data field in sendmsg call.
+
+config NET_TEST
+	bool "Network Testing"
+	help
+	  Used for self-contained networking tests that do not require a
+	  network device.
+
+config NET_SLIP_TAP
+	bool "TAP SLIP driver"
+	depends on NET_QEMU_SLIP
+	depends on NET_NATIVE
+	select SLIP
+	select UART_PIPE
+	select UART_INTERRUPT_DRIVEN
+	select SLIP_TAP
+	default y if (QEMU_TARGET && !NET_TEST && !NET_L2_BT)
+	help
+	  SLIP TAP support is necessary when testing with QEMU. The host
+	  needs to have tunslip6 with TAP support running in order to
+	  communicate via the SLIP driver. See net-tools project at
+	  https://github.com/zephyrproject-rtos/net-tools for more details.
+
+config NET_TRICKLE
+	bool "Enable Trickle library"
+	help
+	  Normally this is enabled automatically if needed,
+	  so say 'n' if unsure.
+
+if NET_TRICKLE
+module = NET_TRICKLE
+module-dep = NET_LOG
+module-str = Log level for Trickle algorithm
+module-help = Enables Trickle library output debug messages
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_TRICKLE
+
+endif # NET_RAW_MODE
+
+config NET_PKT_RX_COUNT
+	int "How many packet receives can be pending at the same time"
+	default 14 if NET_L2_ETHERNET
+	default 4
+	help
+	  Each RX buffer will occupy smallish amount of memory.
+	  See include/net/net_pkt.h and the sizeof(struct net_pkt)
+
+config NET_PKT_TX_COUNT
+	int "How many packet sends can be pending at the same time"
+	default 14 if NET_L2_ETHERNET
+	default 4
+	help
+	  Each TX buffer will occupy smallish amount of memory.
+	  See include/net/net_pkt.h and the sizeof(struct net_pkt)
+
+config NET_BUF_RX_COUNT
+	int "How many network buffers are allocated for receiving data"
+	default 36 if NET_L2_ETHERNET
+	default 16
+	help
+	  Each data buffer will occupy CONFIG_NET_BUF_DATA_SIZE + smallish
+	  header (sizeof(struct net_buf)) amount of data.
+
+config NET_BUF_TX_COUNT
+	int "How many network buffers are allocated for sending data"
+	default 36 if NET_L2_ETHERNET
+	default 16
+	help
+	  Each data buffer will occupy CONFIG_NET_BUF_DATA_SIZE + smallish
+	  header (sizeof(struct net_buf)) amount of data.
+
+choice
+	prompt "Network packet data allocator type"
+	default NET_BUF_FIXED_DATA_SIZE
+	help
+	  Select the memory allocator for the network buffers that hold the
+	  packet data.
+
+config NET_BUF_FIXED_DATA_SIZE
+	bool "Fixed data size buffer"
+	help
+	  Each buffer comes with a built time configured size. If runtime
+	  requested is bigger than that, it will allocate as many net_buf
+	  as necessary to reach that request.
+
+config NET_BUF_VARIABLE_DATA_SIZE
+	bool "Variable data size buffer [EXPERIMENTAL]"
+	help
+	  The buffer is dynamically allocated from runtime requested size.
+
+endchoice
+
+config NET_BUF_DATA_SIZE
+	int "Size of each network data fragment"
+	default 128
+	depends on NET_BUF_FIXED_DATA_SIZE
+	help
+	  This value tells what is the fixed size of each network buffer.
+
+config NET_BUF_DATA_POOL_SIZE
+	int "Size of the memory pool where buffers are allocated from"
+	default 4096 if NET_L2_ETHERNET
+	default 2048
+	depends on NET_BUF_VARIABLE_DATA_SIZE
+	help
+	  This value tell what is the size of the memory pool where each
+	  network buffer is allocated from.
+
+config NET_HEADERS_ALWAYS_CONTIGUOUS
+	bool
+	help
+	  This a hidden option, which one should use with a lot of care.
+	  NO bug reports will be accepted if that option is enabled!
+	  You are warned.
+	  If you are 100% sure the headers memory space is always in a
+	  contiguous space, this will save stack usage and ROM in net core.
+	  This is a possible case when using IPv4 only, with
+	  NET_BUF_FIXED_DATA_SIZE enabled and NET_BUF_DATA_SIZE of 128 for
+	  instance.
+
+choice
+	prompt "Default Network Interface"
+	default NET_DEFAULT_IF_FIRST
+	help
+	  If system has multiple interfaces enabled, then user shall be able
+	  to choose default interface. Otherwise first interface will be the
+	  default interface.
+
+config NET_DEFAULT_IF_FIRST
+	bool "First available interface"
+
+config NET_DEFAULT_IF_ETHERNET
+	bool "Ethernet"
+	depends on NET_L2_ETHERNET
+
+config NET_DEFAULT_IF_BLUETOOTH
+	bool "Bluetooth"
+	depends on NET_L2_BT
+
+config NET_DEFAULT_IF_IEEE802154
+	bool "IEEE 802.15.4"
+	depends on NET_L2_IEEE802154
+
+config NET_DEFAULT_IF_OFFLOAD
+	bool "Offloaded interface"
+	depends on NET_OFFLOAD
+
+config NET_DEFAULT_IF_DUMMY
+	bool "Dummy testing interface"
+	depends on NET_L2_DUMMY
+
+config NET_DEFAULT_IF_CANBUS
+	bool "6LoCAN (IPv6 over CAN) interface"
+	depends on NET_L2_CANBUS
+
+config NET_DEFAULT_IF_CANBUS_RAW
+	bool "Socket CAN interface"
+	depends on NET_L2_CANBUS_RAW
+
+config NET_DEFAULT_IF_PPP
+	bool "PPP interface"
+	depends on NET_L2_PPP
+
+endchoice
+
+config NET_PKT_TIMESTAMP
+	bool "Enable network packet timestamp support"
+	help
+	  Enable network packet timestamp support. This is needed for
+	  example in gPTP which needs to know how long it takes to send
+	  a network packet.
+
+config NET_PKT_TIMESTAMP_THREAD
+	bool "Create TX timestamp thread"
+	default y if NET_GPTP
+	depends on NET_PKT_TIMESTAMP
+	help
+	  Create a TX timestamp thread that will pass the timestamped network
+	  packets to some other module like gPTP for further processing.
+	  If you just want to timestamp network packets and get information
+	  how long the network packets flow in the system, you can disable
+	  the thread support.
+
+config NET_PKT_TIMESTAMP_STACK_SIZE
+	int "Timestamp thread stack size"
+	default 1024
+	depends on NET_PKT_TIMESTAMP_THREAD
+	help
+	  Set the timestamp thread stack size in bytes. The timestamp
+	  thread waits for timestamped TX frames and calls registered
+	  callbacks.
+
+config NET_PKT_TXTIME
+	bool "Enable network packet TX time support"
+	help
+	  Enable network packet TX time support. This is needed for
+	  when the application wants to set the exact time when the network
+	  packet should be sent.
+
+config NET_PKT_RXTIME_STATS
+	bool "Enable network packet RX time statistics"
+	select NET_PKT_TIMESTAMP
+	select NET_STATISTICS
+	depends on (NET_UDP || NET_TCP || NET_SOCKETS_PACKET) && NET_NATIVE
+	help
+	  Enable network packet RX time statistics support. This is used to
+	  calculate how long on average it takes for a packet to travel from
+	  device driver to just before it is given to application. The RX
+	  timing information can then be seen in network interface statistics
+	  in net-shell.
+	  The RX statistics are only calculated for UDP and TCP packets.
+
+config NET_PKT_RXTIME_STATS_DETAIL
+	bool "Get extra receive detail statistics in RX path"
+	depends on NET_PKT_RXTIME_STATS
+	help
+	  Store receive statistics detail information in certain key points
+	  in RX path. This is very special configuration and will increase
+	  the size of net_pkt so in typical cases you should not enable it.
+	  The extra statistics can be seen in net-shell using "net stats"
+	  command.
+
+config NET_PKT_TXTIME_STATS
+	bool "Enable network packet TX time statistics"
+	select NET_PKT_TIMESTAMP
+	select NET_STATISTICS
+	depends on (NET_UDP || NET_TCP || NET_SOCKETS_PACKET) && NET_NATIVE
+	help
+	  Enable network packet TX time statistics support. This is used to
+	  calculate how long on average it takes for a packet to travel from
+	  application to just before it is sent to network. The TX timing
+	  information can then be seen in network interface statistics in
+	  net-shell.
+	  The RX calculation is done only for UDP, TCP or RAW packets,
+	  but for TX we do not know the protocol so the TX packet timing is
+	  done for all network protocol packets.
+
+config NET_PKT_TXTIME_STATS_DETAIL
+	bool "Get extra transmit detail statistics in TX path"
+	depends on NET_PKT_TXTIME_STATS
+	help
+	  Store receive statistics detail information in certain key points
+	  in TX path. This is very special configuration and will increase
+	  the size of net_pkt so in typical cases you should not enable it.
+	  The extra statistics can be seen in net-shell using "net stats"
+	  command.
+
+config NET_PROMISCUOUS_MODE
+	bool "Enable promiscuous mode support [EXPERIMENTAL]"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	select NET_L2_ETHERNET_MGMT if NET_L2_ETHERNET
+	help
+	  Enable promiscuous mode support. This only works if the network
+	  device driver supports promiscuous mode. The user application
+	  also needs to read the promiscuous mode data.
+
+if NET_PROMISCUOUS_MODE
+module = NET_PROMISC
+module-dep = NET_LOG
+module-str = Log level for promiscuous mode
+module-help = Enables promiscuous mode to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_PROMISCUOUS_MODE
+
+source "subsys/net/ip/Kconfig.stack"
+
+source "subsys/net/ip/Kconfig.mgmt"
+
+source "subsys/net/ip/Kconfig.stats"
+
+source "subsys/net/ip/Kconfig.debug"
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.debug
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.debug	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.debug	(working copy)
@@ -0,0 +1,90 @@
+# Debug Options
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_LOG
+	bool "Enable network stack logging and debugging"
+	select LOG
+	help
+	  Enable logging in various parts of the network stack.
+	  Specific debugging options to other sub-menus will be unlocked
+	  as well (IPv6, IPv4, ...).
+
+module = NET_PKT
+module-dep = NET_LOG
+module-str = Log level for network packet and buffer allocation
+module-help = Enables debug of network packet and buffer allocations and frees.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_DEBUG_NET_PKT_ALLOC
+	bool "Debug network packet and buffer individual allocation"
+	default y if NET_PKT_LOG_LEVEL_DBG
+	help
+	  Enables printing of network packet and buffer allocations and frees for
+	  each allocation. This can produce lot of output so it is disabled by
+	  default.
+
+config NET_DEBUG_NET_PKT_EXTERNALS
+	int "How many external network packet allocations"
+	default 0
+	help
+	  How many external net_pkt objects are there in user specific pools.
+	  This value is used when allocating space for tracking the
+	  memory allocations.
+
+config NET_DEBUG_NET_PKT_NON_FRAGILE_ACCESS
+	bool "Reduce r/w fragility by resetting the packet cursor when freed"
+	select NET_DEBUG_NET_PKT_ALLOC
+	help
+	  This MUST not be used unless you have an hard to catch bug. This will
+	  reset the pkt cursor when it's freed, so any subsequent r/w operations
+	  will not segfault, but just bail out and hopefully it will enable you
+	  to know who/where the packet was freed already. Do not set this, by
+	  any means, unless you are actively debugging.
+
+if !NET_RAW_MODE
+
+module = NET_CORE
+module-dep = NET_LOG
+module-str = Log level for core IP stack
+module-help = Enables core network stack code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_IF
+module-dep = NET_LOG
+module-str = Log level for network interface code
+module-help = Enables network interface code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_TC
+module-dep = NET_LOG
+module-str = Log level for network traffic class code
+module-help = Enables network traffic class code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_UTILS
+module-dep = NET_LOG
+module-str = Log level for utility functions in IP stack
+module-help = Enables utility functions to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_CONTEXT
+module-dep = NET_LOG
+module-str = Log level for network context allocation
+module-help = Enables printing of network context allocations and frees.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_CONN
+module-dep = NET_LOG
+module-str = Log level for UDP/TCP connection handling
+module-help = Enables UDP/TCP connection debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_ROUTE
+module-dep = NET_LOG
+module-str = Log level for route management
+module-help = Enables routing engine debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # NET_RAW_MODE
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv4
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv4	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv4	(working copy)
@@ -0,0 +1,103 @@
+# IPv4 Options
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_IPV4
+	bool "IPv4"
+	help
+	  Enable IPv4 support. If this is enabled then the device is
+	  able to send and receive IPv4 network packets.
+
+if NET_IPV4
+
+config NET_INITIAL_TTL
+	int "Initial time to live for a connection"
+	default 64
+	help
+	  The value should be > 0
+
+config NET_IF_MAX_IPV4_COUNT
+	int "Max number of IPv4 network interfaces in the system"
+	default NET_VLAN_COUNT if NET_VLAN
+	default 1
+	help
+	  This tells how many network interfaces there will be in the system
+	  that will have IPv4 enabled.
+
+config NET_IF_UNICAST_IPV4_ADDR_COUNT
+	int "Max number of unicast IPv4 addresses per network interface"
+	default 2 if NET_IPV4_AUTO
+	default 1
+
+config NET_IF_MCAST_IPV4_ADDR_COUNT
+	int "Max number of multicast IPv4 addresses per network interface"
+	default 1
+
+config NET_ICMPV4_ACCEPT_BROADCAST
+	bool "Accept broadcast ICMPv4 echo-request"
+	help
+	  If set, then respond to ICMPv4 echo-request that is sent to
+	  broadcast address.
+
+config NET_IPV4_ACCEPT_ZERO_BROADCAST
+	bool "Accept 0.0.0.0 broadcast destination address"
+	help
+	  If set, then accept UDP packets destined to non-standard
+	  0.0.0.0 broadcast address as described in RFC 1122 ch. 3.3.6
+
+config NET_DHCPV4
+	bool "Enable DHCPv4 client"
+	depends on NET_UDP
+
+config NET_DHCPV4_INITIAL_DELAY_MAX
+	int "Maximum time out for initial discover request"
+	depends on NET_DHCPV4
+	default 10
+	range 2 10
+	help
+	  As per RFC2131 4.1.1, we wait a random period between
+	  1 and 10 seconds before sending the initial discover.
+
+config NET_IPV4_AUTO
+	bool "Enable IPv4 autoconfiguration [EXPERIMENTAL]"
+	depends on NET_ARP
+	help
+	  Enables IPv4 auto IP address configuration (see RFC 3927)
+
+config NET_IPV4_HDR_OPTIONS
+	bool "Enable IPv4 Header options support"
+	help
+	  Enables IPv4 header options support. Current support for only
+	  ICMPv4 Echo request. Only RecordRoute and Timestamp are handled.
+
+
+module = NET_IPV4
+module-dep = NET_LOG
+module-str = Log level for core IPv4
+module-help = Enables core IPv4 code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_ICMPV4
+module-dep = NET_LOG
+module-str = Log level for ICMPv4
+module-help = Enables ICMPv4 code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+if NET_DHCPV4
+module = NET_DHCPV4
+module-dep = NET_LOG
+module-str = Log level for DHCPv4 client
+module-help = Enable debug diagnostic from DHCPV4 client.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_DHCPV4
+
+if NET_IPV4_AUTO
+module = NET_IPV4_AUTO
+module-dep = NET_LOG
+module-str = Log level for IPv4 autoconf client
+module-help = Enable debug diagnostic from IPv4 autoconf client.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_IPV4_AUTO
+
+endif # NET_IPV4
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv6
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv6	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.ipv6	(working copy)
@@ -0,0 +1,170 @@
+# IPv6 Options
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_IPV6
+	bool "IPv6"
+	default y
+	help
+	  Enable IPv6 support. This should be selected by default as there
+	  is limited set of network bearers provided that support IPv4.
+
+if NET_IPV6
+
+config NET_IF_MAX_IPV6_COUNT
+	int "Max number of IPv6 network interfaces in the system"
+	default BT_MAX_CONN if NET_L2_BT
+	default NET_VLAN_COUNT if NET_VLAN
+	default 1
+	help
+	  This tells how many network interfaces there will be in the system
+	  that will have IPv6 enabled.
+
+config NET_IF_UNICAST_IPV6_ADDR_COUNT
+	int "Max number of unicast IPv6 addresses per network interface"
+	default 6 if NET_L2_OPENTHREAD
+	default 2
+
+config NET_IF_MCAST_IPV6_ADDR_COUNT
+	int "Max number of multicast IPv6 addresses per network interface"
+	default 8 if NET_L2_OPENTHREAD
+	default 3
+
+config NET_IF_IPV6_PREFIX_COUNT
+	int "Max number of IPv6 prefixes per network interface"
+	default 2
+
+config NET_INITIAL_HOP_LIMIT
+	int "Initial hop limit for a connection"
+	default 64
+	help
+	  The value should be > 0
+
+config NET_IPV6_MAX_NEIGHBORS
+	int "How many IPv6 neighbors are supported"
+	default 8
+	range 1 254
+	help
+	  The value depends on your network needs.
+
+config NET_IPV6_FRAGMENT
+	bool "Support IPv6 fragmentation"
+	help
+	  IPv6 fragmentation is disabled by default. This saves memory and
+	  should not cause issues normally as we support anyway the minimum
+	  length IPv6 packets (1280 bytes). If you enable fragmentation
+	  support, please increase amount of RX data buffers so that larger
+	  than 1280 byte packets can be received.
+
+config NET_IPV6_FRAGMENT_MAX_COUNT
+	int "How many packets to reassemble at a time"
+	range 1 16
+	default 1
+	depends on NET_IPV6_FRAGMENT
+	help
+	  How many fragmented IPv6 packets can be waiting reassembly
+	  simultaneously. Each fragment count might use up to 1280 bytes
+	  of memory so you need to plan this and increase the network buffer
+	  count.
+
+config NET_IPV6_FRAGMENT_TIMEOUT
+	int "How long to wait the fragments to receive"
+	range 1 60
+	default 5
+	depends on NET_IPV6_FRAGMENT
+	help
+	  How long to wait for IPv6 fragment to arrive before the reassembly
+	  will timeout. RFC 2460 chapter 4.5 tells to wait for 60 seconds but
+	  this might be too long in memory constrained devices. This value
+	  is in seconds.
+
+config NET_IPV6_MLD
+	bool "Multicast Listener Discovery support"
+	default y
+	help
+	  The value depends on your network needs. MLD should normally
+	  be active. Currently we support only MLDv2. See RFC 3810 for
+	  details.
+
+config NET_IPV6_NBR_CACHE
+	bool "Neighbor cache"
+	default y
+	help
+	  The value depends on your network needs. Neighbor cache should
+	  normally be active.
+
+config NET_IPV6_ND
+	bool "Activate neighbor discovery"
+	depends on NET_IPV6_NBR_CACHE
+	default y
+	help
+	  The value depends on your network needs. ND should normally
+	  be active.
+
+config NET_IPV6_DAD
+	bool "Activate duplicate address detection"
+	depends on NET_IPV6_NBR_CACHE
+	default y
+	help
+	  The value depends on your network needs. DAD should normally
+	  be active.
+
+config NET_IPV6_RA_RDNSS
+	bool "Support RA RDNSS option"
+	depends on NET_IPV6_ND
+	default y
+	help
+	  Support Router Advertisement Recursive DNS Server option.
+	  See RFC 6106 for details. The value depends on your network needs.
+
+config NET_6LO
+	bool "Enable 6lowpan IPv6 Compression library"
+	default y if NET_L2_IEEE802154
+	help
+	  6lowpan compression and fragmentation. It is enabled by default
+	  if 802.15.4 is present, since using IPv6 on it requires it.
+
+config NET_6LO_CONTEXT
+	bool "Enable 6lowpan context based compression"
+	depends on NET_6LO
+	help
+	  Enables 6lowpan context based compression based on information
+	  received in RA(Router Advertisement) message.
+
+config NET_MAX_6LO_CONTEXTS
+	int "Number of supported 6CO (6lowpan contexts options)"
+	depends on NET_6LO_CONTEXT
+	default 1
+	range 1 16
+	help
+	  6lowpan context options table size. The value depends on your
+	  network and memory consumption. More 6CO options uses more memory.
+
+if NET_6LO
+module = NET_6LO
+module-dep = NET_LOG
+module-str = Log level for 6LoWPAN library
+module-help = Enables 6LoWPAN code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_6LO
+
+module = NET_IPV6
+module-dep = NET_LOG
+module-str = Log level for core IPv6
+module-help = Enables core IPv6 code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_ICMPV6
+module-dep = NET_LOG
+module-str = Log level for ICMPv6
+module-help = Enables ICMPv6 code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+module = NET_IPV6_NBR_CACHE
+module-dep = NET_LOG
+module-str = Log level for IPv6 neighbor cache
+module-help = Enables IPv6 Neighbor Cache code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # NET_IPV6
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.mgmt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.mgmt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.mgmt	(working copy)
@@ -0,0 +1,85 @@
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_MGMT
+	bool "Network Management API"
+	help
+	  Add support for NM API that enables managing different aspects
+	  of the network stack as well as receiving notification on network
+	  events (ip address change, iface up and running ...).
+
+config NET_MGMT_EVENT
+	bool "Add support for runtime network event notifications"
+	depends on NET_MGMT
+	help
+	  This adds support for the stack to notify events towards any
+	  relevant listener. This can be necessary when application
+	  (or else) needs to be notified on a specific network event
+	  (ip address change for instance) to trigger some related work.
+
+if NET_MGMT_EVENT
+
+config NET_MGMT_EVENT_STACK_SIZE
+	int "Stack size for the inner thread handling event callbacks"
+	default 2048 if COVERAGE_GCOV
+	default 768
+	help
+	  Set the internal stack size for NM to run registered callbacks
+	  on events.
+
+config NET_MGMT_EVENT_THREAD_PRIO
+	int "Inner thread priority (use with care)"
+	default 7
+	help
+	  Set the network management event core's inner thread priority.
+	  Do not change this unless you know what you are doing.
+
+config NET_MGMT_EVENT_QUEUE_SIZE
+	int "Size of event queue"
+	default 16 if NET_MGMT_EVENT_MONITOR
+	default 2
+	range 1 1024
+	help
+	  Numbers of events which can be queued at same time. Note that if a
+	  3rd event comes in, the first will be removed without generating any
+	  notification. Thus the size of this queue has to be tweaked depending
+	  on the load of the system, planned for the usage.
+
+config NET_MGMT_EVENT_INFO
+	bool "Enable passing information along with an event"
+	help
+	  Event notifier will be able to provide information to an event,
+	  and listeners will then be able to get it. Such information depends
+	  on the type of event.
+
+config NET_MGMT_EVENT_MONITOR
+	bool "Monitor network events from net shell"
+	depends on NET_SHELL && NET_MGMT_EVENT_INFO
+	help
+	  Allow user to monitor network events from net shell using
+	  "net events [on|off]" command. The monitoring is disabled by
+	  default. Note that you should probably increase the value of
+	  NET_MGMT_EVENT_QUEUE_SIZE from the default in order not to miss
+	  any events.
+
+config NET_MGMT_EVENT_MONITOR_AUTO_START
+	bool "Start the event monitor automatically at boot"
+	depends on NET_MGMT_EVENT_MONITOR && SHELL_BACKEND_SERIAL
+	help
+	  Allow user to start monitoring network events automatically
+	  when the system starts. The auto start is disabled by default.
+	  The default UART based shell is used to print data.
+
+module = NET_MGMT_EVENT
+module-dep = NET_LOG
+module-str = Log level for network management event core
+module-help = Enable debug messages output for network management events.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_DEBUG_MGMT_EVENT_STACK
+	bool "Enable stack analysis output on Net MGMT event core"
+	select INIT_STACKS
+	help
+	  Add debug messages output on how much Net MGMT event stack is used.
+
+endif # NET_MGMT_EVENT
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stack
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stack	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stack	(working copy)
@@ -0,0 +1,27 @@
+# Stack usage related options
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menu "Stack usage"
+
+config NET_TX_STACK_SIZE
+	int "TX thread stack size"
+	default 1200
+	help
+	  Set the TX thread stack size in bytes. The TX thread is waiting
+	  data from application. Each network interface will start one
+	  TX thread for sending network packets destined to it.
+	  This value is a baseline and the actual TX stack size might
+	  be bigger depending on what features are enabled.
+
+config NET_RX_STACK_SIZE
+	int "RX thread stack size"
+	default 1500
+	help
+	  Set the RX thread stack size in bytes. The RX thread is waiting
+	  data from network. There is one RX thread in the system.
+	  This value is a baseline and the actual RX stack size might
+	  be bigger depending on what features are enabled.
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stats
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stats	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/Kconfig.stats	(working copy)
@@ -0,0 +1,121 @@
+# Statistics Options
+
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_STATISTICS
+	bool "Network statistics"
+	help
+	  Manage statistics accounting. This takes memory so say 'n' if unsure.
+
+if NET_STATISTICS
+
+module = NET_STATISTICS
+module-dep = NET_LOG
+module-str = Log level for network statistics
+module-help = Enables statistics module to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_STATISTICS_PER_INTERFACE
+	bool "Collect statistics per network interface"
+	default y
+	help
+	  Collect statistics also for each network interface.
+
+config NET_STATISTICS_USER_API
+	bool "Expose statistics through NET MGMT API"
+	select NET_MGMT
+	help
+	  Enable this if you need to grab relevant statistics in your code,
+	  via calling net_mgmt() with relevant NET_REQUEST_STATS_GET_* command.
+
+config NET_STATISTICS_PERIODIC_OUTPUT
+	bool "Simple periodic output"
+	depends on NET_LOG
+	help
+	  Print out all the statistics periodically through logging.
+	  This is meant for testing mostly.
+
+config NET_STATISTICS_IPV4
+	bool "IPv4 statistics"
+	depends on NET_IPV4
+	default y
+	help
+	  Keep track of IPv4 related statistics
+
+config NET_STATISTICS_IPV6
+	bool "IPv6 statistics"
+	depends on NET_IPV6
+	default y
+	help
+	  Keep track of IPv6 related statistics
+
+config NET_STATISTICS_IPV6_ND
+	bool "IPv6 statistics"
+	depends on NET_IPV6_ND
+	default y
+	help
+	  Keep track of IPv6 Neighbor Discovery related statistics
+
+config NET_STATISTICS_ICMP
+	bool "ICMP statistics"
+	depends on NET_IPV6 || NET_IPV4
+	default y
+	help
+	  Keep track of ICMPv4/6 related statistics, depending whether IPv4
+	  and/or IPv6 is/are enabled.
+
+config NET_STATISTICS_UDP
+	bool "UDP statistics"
+	depends on NET_UDP
+	default y
+	help
+	  Keep track of UDP related statistics
+
+config NET_STATISTICS_TCP
+	bool "TCP statistics"
+	depends on NET_TCP
+	default y
+	help
+	  Keep track of TCP related statistics
+
+config NET_STATISTICS_MLD
+	bool "Multicast Listener Discovery (MLD) statistics"
+	depends on NET_IPV6_MLD
+	default y
+	help
+	  Keep track of MLD related statistics
+
+config NET_STATISTICS_PPP
+	bool "Point-to-point (PPP) statistics"
+	depends on NET_PPP
+	default y
+	help
+	  Keep track of PPP related statistics
+
+config NET_STATISTICS_ETHERNET
+	bool "Ethernet statistics"
+	depends on NET_L2_ETHERNET
+	default y
+	help
+	  Keep track of Ethernet related statistics. Note that this
+	  requires support from the ethernet driver. The driver needs
+	  to collect the statistics.
+
+config NET_STATISTICS_ETHERNET_VENDOR
+	bool "Vendor specific Ethernet statistics"
+	depends on NET_STATISTICS_ETHERNET
+	help
+	  Allows Ethernet drivers to provide statistics information
+	  from vendor specific hardware registers in a form of
+	  key-value pairs. Deciphering the information may require
+	  vendor documentation.
+
+config NET_STATISTICS_POWER_MANAGEMENT
+	bool "Power management statistics"
+	depends on NET_POWER_MANAGEMENT
+	help
+	  This will provide how many time a network interface went
+	  suspended, for how long the last time and on average.
+
+endif # NET_STATISTICS
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.h	(working copy)
@@ -0,0 +1,36 @@
+/** @file
+ * @brief CANBUS Socket related functions
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __CAN_SOCKET_H
+#define __CAN_SOCKET_H
+
+#include <zephyr/types.h>
+
+/**
+ * @brief Called by net_core.c when a CANBUS packet is received.
+ *
+ * @param pkt Network packet
+ *
+ * @return NET_OK if the packet was consumed, NET_DROP if
+ * the packet parsing failed and the caller should handle
+ * the received packet.
+ */
+#if defined(CONFIG_NET_SOCKETS_CAN)
+enum net_verdict net_canbus_socket_input(struct net_pkt *pkt);
+#else
+static inline enum net_verdict net_canbus_socket_input(struct net_pkt *pkt)
+{
+	return NET_CONTINUE;
+}
+#endif
+
+#endif /* __CAN_SOCKET_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/canbus_socket.c	(working copy)
@@ -0,0 +1,29 @@
+/** @file
+ * @brief CANBUS Sockets related functions
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sockets_can, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_pkt.h>
+#include <net/net_context.h>
+#include <net/socket_can.h>
+
+#include "connection.h"
+
+enum net_verdict net_canbus_socket_input(struct net_pkt *pkt)
+{
+	if (net_pkt_family(pkt) == AF_CAN &&
+	    net_if_l2(net_pkt_iface(pkt)) == &NET_L2_GET_NAME(CANBUS_RAW)) {
+		return net_conn_input(pkt, NULL, CAN_RAW, NULL);
+	}
+
+	return NET_CONTINUE;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.h	(working copy)
@@ -0,0 +1,211 @@
+/** @file
+ @brief Generic connection handling.
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __CONNECTION_H
+#define __CONNECTION_H
+
+#include <zephyr/types.h>
+
+#include <sys/util.h>
+
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct net_conn;
+
+struct net_conn_handle;
+
+/**
+ * @brief Function that is called by connection subsystem when UDP/TCP
+ * packet is received and which matches local and remote IP address
+ * and port.
+ */
+typedef enum net_verdict (*net_conn_cb_t)(struct net_conn *conn,
+					  struct net_pkt *pkt,
+					  union net_ip_header *ip_hdr,
+					  union net_proto_header *proto_hdr,
+					  void *user_data);
+
+/**
+ * @brief Information about a connection in the system.
+ *
+ * Stores the connection information.
+ *
+ */
+struct net_conn {
+	/** Internal slist node */
+	sys_snode_t node;
+
+	/** Remote IP address */
+	struct sockaddr remote_addr;
+
+	/** Local IP address */
+	struct sockaddr local_addr;
+
+	/** Callback to be called when matching UDP packet is received */
+	net_conn_cb_t cb;
+
+	/** Possible user to pass to the callback */
+	void *user_data;
+
+	/** Connection protocol */
+	uint16_t proto;
+
+	/** Protocol family */
+	uint8_t family;
+
+	/** Flags for the connection */
+	uint8_t flags;
+};
+
+/**
+ * @brief Register a callback to be called when UDP/TCP packet
+ * is received corresponding to received packet.
+ *
+ * @param proto Protocol for the connection (UDP or TCP or SOCK_RAW)
+ * @param family Protocol family (AF_INET or AF_INET6 or AF_PACKET)
+ * @param remote_addr Remote address of the connection end point.
+ * @param local_addr Local address of the connection end point.
+ * @param remote_port Remote port of the connection end point.
+ * @param local_port Local port of the connection end point.
+ * @param cb Callback to be called
+ * @param user_data User data supplied by caller.
+ * @param handle Connection handle that can be used when unregistering
+ *
+ * @return Return 0 if the registration succeed, <0 otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE)
+int net_conn_register(uint16_t proto, uint8_t family,
+		      const struct sockaddr *remote_addr,
+		      const struct sockaddr *local_addr,
+		      uint16_t remote_port,
+		      uint16_t local_port,
+		      net_conn_cb_t cb,
+		      void *user_data,
+		      struct net_conn_handle **handle);
+#else
+static inline int net_conn_register(uint16_t proto, uint8_t family,
+				    const struct sockaddr *remote_addr,
+				    const struct sockaddr *local_addr,
+				    uint16_t remote_port,
+				    uint16_t local_port,
+				    net_conn_cb_t cb,
+				    void *user_data,
+				    struct net_conn_handle **handle)
+{
+	ARG_UNUSED(proto);
+	ARG_UNUSED(family);
+	ARG_UNUSED(remote_addr);
+	ARG_UNUSED(local_addr);
+	ARG_UNUSED(remote_port);
+	ARG_UNUSED(local_port);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+	ARG_UNUSED(handle);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Unregister connection handler.
+ *
+ * @param handle Handle from registering.
+ *
+ * @return Return 0 if the unregistration succeed, <0 otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE)
+int net_conn_unregister(struct net_conn_handle *handle);
+#else
+static inline int net_conn_unregister(struct net_conn_handle *handle)
+{
+	ARG_UNUSED(handle);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Change the callback and user_data for a registered connection
+ * handle.
+ *
+ * @param handle A handle registered with net_conn_register()
+ * @param cb Callback to be called
+ * @param user_data User data supplied by caller.
+ *
+ * @return Return 0 if the the change succeed, <0 otherwise.
+ */
+int net_conn_change_callback(struct net_conn_handle *handle,
+			     net_conn_cb_t cb, void *user_data);
+
+/**
+ * @brief Called by net_core.c when a network packet is received.
+ *
+ * @param pkt Network packet holding received data
+ * @param proto Protocol for the connection
+ *
+ * @return NET_OK if the packet was consumed, NET_DROP if
+ * the packet parsing failed and the caller should handle
+ * the received packet. If corresponding IP protocol support is
+ * disabled, the function will always return NET_DROP.
+ */
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) || \
+	defined(CONFIG_NET_SOCKETS_PACKET) || defined(CONFIG_NET_SOCKETS_CAN)
+enum net_verdict net_conn_input(struct net_pkt *pkt,
+				union net_ip_header *ip_hdr,
+				uint8_t proto,
+				union net_proto_header *proto_hdr);
+#else
+static inline enum net_verdict net_conn_input(struct net_pkt *pkt,
+					      union net_ip_header *ip_hdr,
+					      uint8_t proto,
+					      union net_proto_header *proto_hdr)
+{
+	return NET_DROP;
+}
+#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP  || CONFIG_NET_SOCKETS_PACKET */
+
+/**
+ * @typedef net_conn_foreach_cb_t
+ * @brief Callback used while iterating over network connection
+ * handlers.
+ *
+ * @param conn A valid pointer on current network connection handler.
+ * @param user_data A valid pointer on some user data or NULL
+ */
+typedef void (*net_conn_foreach_cb_t)(struct net_conn *conn, void *user_data);
+
+/**
+ * @brief Go through all the network connection handlers and call callback
+ * for each network connection handler.
+ *
+ * @param cb User supplied callback function to call.
+ * @param user_data User specified data.
+ */
+void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data);
+
+#if defined(CONFIG_NET_NATIVE)
+void net_conn_init(void);
+#else
+#define net_conn_init(...)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNECTION_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/connection.c	(working copy)
@@ -0,0 +1,796 @@
+/** @file
+ * @brief Generic connection related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_conn, CONFIG_NET_CONN_LOG_LEVEL);
+
+#include <errno.h>
+#include <sys/util.h>
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/udp.h>
+#include <net/ethernet.h>
+#include <net/socket_can.h>
+
+#include "net_private.h"
+#include "icmpv6.h"
+#include "icmpv4.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "connection.h"
+#include "net_stats.h"
+
+/** How long to wait for when cloning multicast packet */
+#define CLONE_TIMEOUT K_MSEC(100)
+
+/** Is this connection used or not */
+#define NET_CONN_IN_USE			BIT(0)
+
+/** Remote address set */
+#define NET_CONN_REMOTE_ADDR_SET	BIT(1)
+
+/** Local address set */
+#define NET_CONN_LOCAL_ADDR_SET		BIT(2)
+
+/** Local port set */
+#define NET_CONN_REMOTE_PORT_SPEC	BIT(3)
+
+/** Remote port set */
+#define NET_CONN_LOCAL_PORT_SPEC	BIT(4)
+
+/** Local address specified */
+#define NET_CONN_REMOTE_ADDR_SPEC	BIT(5)
+
+/** Remote address specified */
+#define NET_CONN_LOCAL_ADDR_SPEC	BIT(6)
+
+#define NET_CONN_RANK(_flags)		(_flags & 0x78)
+
+static struct net_conn conns[CONFIG_NET_MAX_CONN];
+
+static sys_slist_t conn_unused;
+static sys_slist_t conn_used;
+
+#if (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG)
+static inline
+void conn_register_debug(struct net_conn *conn,
+			 uint16_t remote_port, uint16_t local_port)
+{
+	char dst[NET_IPV6_ADDR_LEN];
+	char src[NET_IPV6_ADDR_LEN];
+
+	if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    conn->family == AF_INET6) {
+			snprintk(dst, sizeof(dst), "%s",
+				 log_strdup(net_sprint_ipv6_addr(
+				    &net_sin6(&conn->remote_addr)->sin6_addr)));
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+			   conn->family == AF_INET) {
+			snprintk(dst, sizeof(dst), "%s",
+				 log_strdup(net_sprint_ipv4_addr(
+				    &net_sin(&conn->remote_addr)->sin_addr)));
+		} else {
+			snprintk(dst, sizeof(dst), "%s", "?");
+		}
+	} else {
+		snprintk(dst, sizeof(dst), "%s", "-");
+	}
+
+	if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    conn->family == AF_INET6) {
+			snprintk(src, sizeof(src), "%s",
+				 log_strdup(net_sprint_ipv6_addr(
+				    &net_sin6(&conn->local_addr)->sin6_addr)));
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+			   conn->family == AF_INET) {
+			snprintk(src, sizeof(src), "%s",
+				 log_strdup(net_sprint_ipv4_addr(
+				    &net_sin(&conn->local_addr)->sin_addr)));
+		} else {
+			snprintk(src, sizeof(src), "%s", "?");
+		}
+	} else {
+		snprintk(src, sizeof(src), "%s", "-");
+	}
+
+	NET_DBG("[%p/%d/%u/0x%02x] remote %s/%u ",
+		conn, conn->proto, conn->family, conn->flags,
+		log_strdup(dst), remote_port);
+	NET_DBG("  local %s/%u cb %p ud %p",
+		log_strdup(src), local_port, conn->cb, conn->user_data);
+}
+#else
+#define conn_register_debug(...)
+#endif /* (CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG) */
+
+static struct net_conn *conn_get_unused(void)
+{
+	sys_snode_t *node;
+
+	node = sys_slist_peek_head(&conn_unused);
+	if (!node) {
+		return NULL;
+	}
+
+	sys_slist_remove(&conn_unused, NULL, node);
+
+	return CONTAINER_OF(node, struct net_conn, node);
+}
+
+static void conn_set_used(struct net_conn *conn)
+{
+	conn->flags |= NET_CONN_IN_USE;
+
+	sys_slist_prepend(&conn_used, &conn->node);
+}
+
+static void conn_set_unused(struct net_conn *conn)
+{
+	(void)memset(conn, 0, sizeof(*conn));
+
+	sys_slist_prepend(&conn_unused, &conn->node);
+}
+
+/* Check if we already have identical connection handler installed. */
+static struct net_conn *conn_find_handler(uint16_t proto, uint8_t family,
+					  const struct sockaddr *remote_addr,
+					  const struct sockaddr *local_addr,
+					  uint16_t remote_port,
+					  uint16_t local_port)
+{
+	struct net_conn *conn;
+	struct net_conn *tmp;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&conn_used, conn, tmp, node) {
+		if (conn->proto != proto) {
+			continue;
+		}
+
+		if (conn->family != family) {
+			continue;
+		}
+
+		if (remote_addr) {
+			if (!(conn->flags & NET_CONN_REMOTE_ADDR_SET)) {
+				continue;
+			}
+
+			if (IS_ENABLED(CONFIG_NET_IPV6) &&
+			    remote_addr->sa_family == AF_INET6 &&
+			    remote_addr->sa_family ==
+			    conn->remote_addr.sa_family) {
+				if (!net_ipv6_addr_cmp(
+					    &net_sin6(remote_addr)->sin6_addr,
+					    &net_sin6(&conn->remote_addr)->
+								sin6_addr)) {
+					continue;
+				}
+			} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+				   remote_addr->sa_family == AF_INET &&
+				   remote_addr->sa_family ==
+				   conn->remote_addr.sa_family) {
+				if (!net_ipv4_addr_cmp(
+					    &net_sin(remote_addr)->sin_addr,
+					    &net_sin(&conn->remote_addr)->
+								sin_addr)) {
+					continue;
+				}
+			} else {
+				continue;
+			}
+		} else if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
+			continue;
+		}
+
+		if (local_addr) {
+			if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) {
+				continue;
+			}
+
+			if (IS_ENABLED(CONFIG_NET_IPV6) &&
+			    local_addr->sa_family == AF_INET6 &&
+			    local_addr->sa_family ==
+			    conn->local_addr.sa_family) {
+				if (!net_ipv6_addr_cmp(
+					    &net_sin6(local_addr)->sin6_addr,
+					    &net_sin6(&conn->local_addr)->
+								sin6_addr)) {
+					continue;
+				}
+			} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+				   local_addr->sa_family == AF_INET &&
+				   local_addr->sa_family ==
+				   conn->local_addr.sa_family) {
+				if (!net_ipv4_addr_cmp(
+					    &net_sin(local_addr)->sin_addr,
+					    &net_sin(&conn->local_addr)->
+								sin_addr)) {
+					continue;
+				}
+			} else {
+				continue;
+			}
+		} else if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
+			continue;
+		}
+
+		if (net_sin(&conn->remote_addr)->sin_port !=
+		    htons(remote_port)) {
+			continue;
+		}
+
+		if (net_sin(&conn->local_addr)->sin_port !=
+		    htons(local_port)) {
+			continue;
+		}
+
+		return conn;
+	}
+
+	return NULL;
+}
+
+int net_conn_register(uint16_t proto, uint8_t family,
+		      const struct sockaddr *remote_addr,
+		      const struct sockaddr *local_addr,
+		      uint16_t remote_port,
+		      uint16_t local_port,
+		      net_conn_cb_t cb,
+		      void *user_data,
+		      struct net_conn_handle **handle)
+{
+	struct net_conn *conn;
+	uint8_t flags = 0U;
+
+	conn = conn_find_handler(proto, family, remote_addr, local_addr,
+				 remote_port, local_port);
+	if (conn) {
+		NET_ERR("Identical connection handler %p already found.", conn);
+		return -EALREADY;
+	}
+
+	conn = conn_get_unused();
+	if (!conn) {
+		return -ENOENT;
+	}
+
+	if (remote_addr) {
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    remote_addr->sa_family == AF_INET6) {
+			memcpy(&conn->remote_addr, remote_addr,
+			       sizeof(struct sockaddr_in6));
+
+			if (!net_ipv6_is_addr_unspecified(
+				    &net_sin6(remote_addr)->
+				    sin6_addr)) {
+				flags |= NET_CONN_REMOTE_ADDR_SPEC;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+			   remote_addr->sa_family == AF_INET) {
+			memcpy(&conn->remote_addr, remote_addr,
+			       sizeof(struct sockaddr_in));
+
+			if (net_sin(remote_addr)->sin_addr.s_addr) {
+				flags |= NET_CONN_REMOTE_ADDR_SPEC;
+			}
+		} else {
+			NET_ERR("Remote address family not set");
+			goto error;
+		}
+
+		flags |= NET_CONN_REMOTE_ADDR_SET;
+	}
+
+	if (local_addr) {
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    local_addr->sa_family == AF_INET6) {
+			memcpy(&conn->local_addr, local_addr,
+			       sizeof(struct sockaddr_in6));
+
+			if (!net_ipv6_is_addr_unspecified(
+				    &net_sin6(local_addr)->
+				    sin6_addr)) {
+				flags |= NET_CONN_LOCAL_ADDR_SPEC;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+			   local_addr->sa_family == AF_INET) {
+			memcpy(&conn->local_addr, local_addr,
+			       sizeof(struct sockaddr_in));
+
+			if (net_sin(local_addr)->sin_addr.s_addr) {
+				flags |= NET_CONN_LOCAL_ADDR_SPEC;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+			   local_addr->sa_family == AF_CAN) {
+			memcpy(&conn->local_addr, local_addr,
+			       sizeof(struct sockaddr_can));
+		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+			   local_addr->sa_family == AF_PACKET) {
+			memcpy(&conn->local_addr, local_addr,
+			       sizeof(struct sockaddr_ll));
+		} else {
+			NET_ERR("Local address family not set");
+			goto error;
+		}
+
+		flags |= NET_CONN_LOCAL_ADDR_SET;
+	}
+
+	if (remote_addr && local_addr) {
+		if (remote_addr->sa_family != local_addr->sa_family) {
+			NET_ERR("Address families different");
+			goto error;
+		}
+	}
+
+	if (remote_port) {
+		flags |= NET_CONN_REMOTE_PORT_SPEC;
+		net_sin(&conn->remote_addr)->sin_port = htons(remote_port);
+	}
+
+	if (local_port) {
+		flags |= NET_CONN_LOCAL_PORT_SPEC;
+		net_sin(&conn->local_addr)->sin_port = htons(local_port);
+	}
+
+	conn->cb = cb;
+	conn->user_data = user_data;
+	conn->flags = flags;
+	conn->proto = proto;
+	conn->family = family;
+
+	if (handle) {
+		*handle = (struct net_conn_handle *)conn;
+	}
+
+	conn_set_used(conn);
+
+	conn_register_debug(conn, remote_port, local_port);
+
+	return 0;
+error:
+	conn_set_unused(conn);
+	return -EINVAL;
+}
+
+int net_conn_unregister(struct net_conn_handle *handle)
+{
+	struct net_conn *conn = (struct net_conn *)handle;
+
+	if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
+		return -EINVAL;
+	}
+
+	if (!(conn->flags & NET_CONN_IN_USE)) {
+		return -ENOENT;
+	}
+
+	NET_DBG("Connection handler %p removed", conn);
+
+	sys_slist_find_and_remove(&conn_used, &conn->node);
+
+	conn_set_unused(conn);
+
+	return 0;
+}
+
+int net_conn_change_callback(struct net_conn_handle *handle,
+			     net_conn_cb_t cb, void *user_data)
+{
+	struct net_conn *conn = (struct net_conn *)handle;
+
+	if (conn < &conns[0] || conn > &conns[CONFIG_NET_MAX_CONN]) {
+		return -EINVAL;
+	}
+
+	if (!(conn->flags & NET_CONN_IN_USE)) {
+		return -ENOENT;
+	}
+
+	NET_DBG("[%zu] connection handler %p changed callback",
+		conn - conns, conn);
+
+	conn->cb = cb;
+	conn->user_data = user_data;
+
+	return 0;
+}
+
+static bool conn_addr_cmp(struct net_pkt *pkt,
+			  union net_ip_header *ip_hdr,
+			  struct sockaddr *addr,
+			  bool is_remote)
+{
+	if (addr->sa_family != net_pkt_family(pkt)) {
+		return false;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_pkt_family(pkt) == AF_INET6 &&
+	    addr->sa_family == AF_INET6) {
+		struct in6_addr *addr6;
+
+		if (is_remote) {
+			addr6 = &ip_hdr->ipv6->src;
+		} else {
+			addr6 = &ip_hdr->ipv6->dst;
+		}
+
+		if (!net_ipv6_is_addr_unspecified(
+			    &net_sin6(addr)->sin6_addr)) {
+			if (!net_ipv6_addr_cmp(&net_sin6(addr)->sin6_addr,
+					       addr6)) {
+				return false;
+			}
+		}
+
+		return true;
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_pkt_family(pkt) == AF_INET &&
+		   addr->sa_family == AF_INET) {
+		struct in_addr *addr4;
+
+		if (is_remote) {
+			addr4 = &ip_hdr->ipv4->src;
+		} else {
+			addr4 = &ip_hdr->ipv4->dst;
+		}
+
+		if (net_sin(addr)->sin_addr.s_addr) {
+			if (!net_ipv4_addr_cmp(&net_sin(addr)->sin_addr,
+					       addr4)) {
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+static inline void conn_send_icmp_error(struct net_pkt *pkt)
+{
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		net_icmpv6_send_error(pkt, NET_ICMPV6_DST_UNREACH,
+				      NET_ICMPV6_DST_UNREACH_NO_PORT, 0);
+
+	} else if (IS_ENABLED(CONFIG_NET_IPV4)) {
+		net_icmpv4_send_error(pkt, NET_ICMPV4_DST_UNREACH,
+				      NET_ICMPV4_DST_UNREACH_NO_PORT);
+	}
+}
+
+static bool conn_are_end_points_valid(struct net_pkt *pkt,
+				      union net_ip_header *ip_hdr,
+				      uint16_t src_port,
+				      uint16_t dst_port)
+{
+	bool my_src_addr = false;
+
+	/* For AF_PACKET family, we are not parsing headers. */
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+	    net_pkt_family(pkt) == AF_PACKET) {
+		return true;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+	    net_pkt_family(pkt) == AF_CAN) {
+		return true;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		if (net_ipv4_addr_cmp(&ip_hdr->ipv4->src,
+				      &ip_hdr->ipv4->dst) ||
+		    net_ipv4_is_my_addr(&ip_hdr->ipv4->src)) {
+			my_src_addr = true;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		if (net_ipv6_addr_cmp(&ip_hdr->ipv6->src,
+				      &ip_hdr->ipv6->dst) ||
+		    net_ipv6_is_my_addr(&ip_hdr->ipv6->src)) {
+			my_src_addr = true;
+		}
+	}
+
+	return !(my_src_addr && (src_port == dst_port));
+}
+
+enum net_verdict net_conn_input(struct net_pkt *pkt,
+				union net_ip_header *ip_hdr,
+				uint8_t proto,
+				union net_proto_header *proto_hdr)
+{
+	struct net_if *pkt_iface = net_pkt_iface(pkt);
+	struct net_conn *best_match = NULL;
+	bool is_mcast_pkt = false, mcast_pkt_delivered = false;
+	bool is_bcast_pkt = false;
+	bool raw_pkt_delivered = false;
+	int16_t best_rank = -1;
+	struct net_conn *conn;
+	uint16_t src_port;
+	uint16_t dst_port;
+
+	if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
+		src_port = proto_hdr->udp->src_port;
+		dst_port = proto_hdr->udp->dst_port;
+	} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+		if (proto_hdr->tcp == NULL) {
+			return NET_DROP;
+		}
+
+		src_port = proto_hdr->tcp->src_port;
+		dst_port = proto_hdr->tcp->dst_port;
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
+		if (net_pkt_family(pkt) != AF_PACKET ||
+		    (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) &&
+		     proto != ETH_P_ALL)) {
+			return NET_DROP;
+		}
+
+		src_port = dst_port = 0U;
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+		   net_pkt_family(pkt) == AF_CAN) {
+		if (proto != CAN_RAW) {
+			return NET_DROP;
+		}
+
+		src_port = dst_port = 0U;
+	} else {
+		NET_DBG("No suitable protocol handler configured");
+		return NET_DROP;
+	}
+
+	if (!conn_are_end_points_valid(pkt, ip_hdr, src_port, dst_port)) {
+		NET_DBG("Dropping invalid src/dst end-points packet");
+		return NET_DROP;
+	}
+
+	/* TODO: Make core part of networing subsystem less dependent on
+	 * UDP, TCP, IPv4 or IPv6. So that we can add new features with
+	 * less cross-module changes.
+	 */
+	NET_DBG("Check %s listener for pkt %p src port %u dst port %u"
+		" family %d", net_proto2str(net_pkt_family(pkt), proto), pkt,
+		ntohs(src_port), ntohs(dst_port), net_pkt_family(pkt));
+
+	/* If we receive a packet with multicast destination address, we might
+	 * need to deliver the packet to multiple recipients.
+	 */
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		if (net_ipv4_is_addr_mcast(&ip_hdr->ipv4->dst)) {
+			is_mcast_pkt = true;
+		} else if (net_if_ipv4_is_addr_bcast(pkt_iface,
+						     &ip_hdr->ipv4->dst)) {
+			is_bcast_pkt = true;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+					   net_pkt_family(pkt) == AF_INET6) {
+		if (net_ipv6_is_addr_mcast(&ip_hdr->ipv6->dst)) {
+			is_mcast_pkt = true;
+		}
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
+		/* For packet socket data, the proto is set to ETH_P_ALL but
+		 * the listener might have a specific protocol set. This is ok
+		 * and let the packet pass this check in this case.
+		 */
+		if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET_DGRAM) ||
+		    IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
+			if ((conn->proto != proto) && (proto != ETH_P_ALL)) {
+				continue;
+			}
+		} else {
+			if ((conn->proto != proto)) {
+				continue;
+			}
+		}
+
+		if (conn->family != AF_UNSPEC &&
+		    conn->family != net_pkt_family(pkt)) {
+			continue;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_UDP) ||
+		    IS_ENABLED(CONFIG_NET_TCP)) {
+			if (net_sin(&conn->remote_addr)->sin_port) {
+				if (net_sin(&conn->remote_addr)->sin_port !=
+				    src_port) {
+					continue;
+				}
+			}
+
+			if (net_sin(&conn->local_addr)->sin_port) {
+				if (net_sin(&conn->local_addr)->sin_port !=
+				    dst_port) {
+					continue;
+				}
+			}
+
+			if (conn->flags & NET_CONN_REMOTE_ADDR_SET) {
+				if (!conn_addr_cmp(pkt, ip_hdr,
+						   &conn->remote_addr,
+						   true)) {
+					continue;
+				}
+			}
+
+			if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
+				if (!conn_addr_cmp(pkt, ip_hdr,
+						   &conn->local_addr,
+						   false)) {
+					continue;
+				}
+			}
+
+			/* If we have an existing best_match, and that one
+			 * specifies a remote port, then we've matched to a
+			 * LISTENING connection that should not override.
+			 */
+			if (best_match != NULL &&
+			    best_match->flags & NET_CONN_REMOTE_PORT_SPEC) {
+				continue;
+			}
+
+			if (best_rank < NET_CONN_RANK(conn->flags)) {
+				struct net_pkt *mcast_pkt;
+
+				if (!is_mcast_pkt) {
+					best_rank = NET_CONN_RANK(conn->flags);
+					best_match = conn;
+
+					continue;
+				}
+
+				/* If we have a multicast packet, and we found
+				 * a match, then deliver the packet immediately
+				 * to the handler. As there might be several
+				 * sockets interested about these, we need to
+				 * clone the received pkt.
+				 */
+
+				NET_DBG("[%p] mcast match found cb %p ud %p",
+					conn, conn->cb,	conn->user_data);
+
+				mcast_pkt = net_pkt_clone(pkt, CLONE_TIMEOUT);
+				if (!mcast_pkt) {
+					goto drop;
+				}
+
+				if (conn->cb(conn, mcast_pkt, ip_hdr,
+					     proto_hdr, conn->user_data) ==
+								NET_DROP) {
+					net_stats_update_per_proto_drop(
+							pkt_iface, proto);
+					net_pkt_unref(mcast_pkt);
+				} else {
+					net_stats_update_per_proto_recv(
+						pkt_iface, proto);
+				}
+
+				mcast_pkt_delivered = true;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET)) {
+			if (conn->flags & NET_CONN_LOCAL_ADDR_SET) {
+				struct sockaddr_ll *local;
+				struct net_pkt *raw_pkt;
+
+				local = (struct sockaddr_ll *)&conn->local_addr;
+
+				if (local->sll_ifindex !=
+				    net_if_get_by_iface(net_pkt_iface(pkt))) {
+					continue;
+				}
+
+				NET_DBG("[%p] raw match found cb %p ud %p",
+					conn, conn->cb,	conn->user_data);
+
+				raw_pkt = net_pkt_clone(pkt, CLONE_TIMEOUT);
+				if (!raw_pkt) {
+					goto drop;
+				}
+
+				if (conn->cb(conn, raw_pkt, ip_hdr,
+					     proto_hdr, conn->user_data) ==
+								NET_DROP) {
+					net_stats_update_per_proto_drop(
+							pkt_iface, proto);
+					net_pkt_unref(raw_pkt);
+				} else {
+					net_stats_update_per_proto_recv(
+						pkt_iface, proto);
+				}
+
+				raw_pkt_delivered = true;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+			best_rank = 0;
+			best_match = conn;
+		}
+	}
+
+	if ((is_mcast_pkt && mcast_pkt_delivered) || raw_pkt_delivered) {
+		/* As one or more multicast or raw socket packets have already
+		 * been delivered in the loop above, we shall not call the
+		 * callback again here.
+		 */
+
+		net_pkt_unref(pkt);
+
+		return NET_OK;
+	}
+
+	conn = best_match;
+	if (conn) {
+		NET_DBG("[%p] match found cb %p ud %p rank 0x%02x",
+			conn, conn->cb, conn->user_data, conn->flags);
+
+		if (conn->cb(conn, pkt, ip_hdr, proto_hdr,
+			     conn->user_data) == NET_DROP) {
+			goto drop;
+		}
+
+		net_stats_update_per_proto_recv(pkt_iface, proto);
+
+		return NET_OK;
+	}
+
+	NET_DBG("No match found.");
+
+	/* Do not send ICMP error for Packet socket as that makes no
+	 * sense here.
+	 */
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_pkt_family(pkt) == AF_INET6 && is_mcast_pkt) {
+		;
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_pkt_family(pkt) == AF_INET &&
+		   (is_mcast_pkt || is_bcast_pkt)) {
+		;
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		    net_pkt_family(pkt) == AF_PACKET) {
+		;
+	} else {
+		conn_send_icmp_error(pkt);
+
+		if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+			net_stats_update_tcp_seg_connrst(pkt_iface);
+		}
+	}
+
+drop:
+	net_stats_update_per_proto_drop(pkt_iface, proto);
+
+	return NET_DROP;
+}
+
+void net_conn_foreach(net_conn_foreach_cb_t cb, void *user_data)
+{
+	struct net_conn *conn;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&conn_used, conn, node) {
+		cb(conn, user_data);
+	}
+}
+
+void net_conn_init(void)
+{
+	int i;
+
+	sys_slist_init(&conn_unused);
+	sys_slist_init(&conn_used);
+
+	for (i = 0; i < CONFIG_NET_MAX_CONN; i++) {
+		sys_slist_prepend(&conn_unused, &conns[i].node);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.h	(working copy)
@@ -0,0 +1,133 @@
+/** @file
+ *
+ * @brief DHCPv4 handler.
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2017 ARM Ltd.
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __INTERNAL_DHCPV4_H
+#define __INTERNAL_DHCPV4_H
+
+struct dhcp_msg {
+	uint8_t op;		/* Message type, 1:BOOTREQUEST, 2:BOOTREPLY */
+	uint8_t htype;		/* Hardware Address Type */
+	uint8_t hlen;		/* Hardware Address length */
+	uint8_t hops;		/* used by relay agents when booting via relay
+				 * agent, client sets zero
+				 */
+	uint32_t xid;		/* Transaction ID, random number */
+	uint16_t secs;		/* Seconds elapsed since client began address
+				 * acquisition or renewal process
+				 */
+	uint16_t flags;		/* Broadcast or Unicast */
+	uint8_t ciaddr[4];		/* Client IP Address */
+	uint8_t yiaddr[4];		/* your (client) IP address */
+	uint8_t siaddr[4];		/* IP address of next server to use in bootstrap
+				 * returned in DHCPOFFER, DHCPACK by server
+				 */
+	uint8_t giaddr[4];		/* Relat agent IP address */
+	uint8_t chaddr[16];	/* Client hardware address */
+} __packed;
+
+#define SIZE_OF_SNAME		64
+#define SIZE_OF_FILE		128
+#define SIZE_OF_MAGIC_COOKIE	4
+
+#define DHCPV4_MSG_BROADCAST	0x8000
+#define DHCPV4_MSG_UNICAST	0x0000
+
+#define DHCPV4_MSG_BOOT_REQUEST	1
+#define DHCPV4_MSG_BOOT_REPLY	2
+
+#define HARDWARE_ETHERNET_TYPE	1
+#define HARDWARE_ETHERNET_LEN	6
+
+#define DHCPV4_SERVER_PORT	67
+#define DHCPV4_CLIENT_PORT	68
+
+/* These enumerations represent RFC2131 defined msy type codes, hence
+ * they should not be renumbered.
+ */
+enum dhcpv4_msg_type {
+	DHCPV4_MSG_TYPE_DISCOVER	= 1,
+	DHCPV4_MSG_TYPE_OFFER		= 2,
+	DHCPV4_MSG_TYPE_REQUEST		= 3,
+	DHCPV4_MSG_TYPE_DECLINE		= 4,
+	DHCPV4_MSG_TYPE_ACK		= 5,
+	DHCPV4_MSG_TYPE_NAK		= 6,
+	DHCPV4_MSG_TYPE_RELEASE		= 7,
+	DHCPV4_MSG_TYPE_INFORM		= 8,
+};
+
+#define DHCPV4_OPTIONS_SUBNET_MASK	1
+#define DHCPV4_OPTIONS_ROUTER		3
+#define DHCPV4_OPTIONS_DNS_SERVER	6
+#define DHCPV4_OPTIONS_HOST_NAME	12
+#define DHCPV4_OPTIONS_REQ_IPADDR	50
+#define DHCPV4_OPTIONS_LEASE_TIME	51
+#define DHCPV4_OPTIONS_MSG_TYPE		53
+#define DHCPV4_OPTIONS_SERVER_ID	54
+#define DHCPV4_OPTIONS_REQ_LIST		55
+#define DHCPV4_OPTIONS_RENEWAL		58
+#define DHCPV4_OPTIONS_REBINDING	59
+#define DHCPV4_OPTIONS_END		255
+
+/* Useful size macros */
+#define DHCPV4_OLV_MSG_HOST_NAME	2
+#define DHCPV4_OLV_MSG_REQ_IPADDR	6
+#define DHCPV4_OLV_MSG_TYPE_SIZE	3
+#define DHCPV4_OLV_MSG_SERVER_ID	6
+#define DHCPV4_OLV_MSG_REQ_LIST		5
+
+#define DHCPV4_OLV_END_SIZE		1
+
+#define DHCPV4_MESSAGE_SIZE		(sizeof(struct dhcp_msg) +	\
+					 SIZE_OF_SNAME + SIZE_OF_FILE + \
+					 SIZE_OF_MAGIC_COOKIE +		\
+					 DHCPV4_OLV_MSG_TYPE_SIZE +	\
+					 DHCPV4_OLV_END_SIZE)
+
+
+/* TODO:
+ * 1) Support for UNICAST flag (some dhcpv4 servers will not reply if
+ *    DISCOVER message contains BROADCAST FLAG).
+ * 2) Support T2(Rebind) timer.
+ */
+
+/* Maximum number of REQUEST or RENEWAL retransmits before reverting
+ * to DISCOVER.
+ */
+#define DHCPV4_MAX_NUMBER_OF_ATTEMPTS	3
+
+/* Initial message retry timeout (s).  This timeout increases
+ * exponentially on each retransmit.
+ * RFC2131 4.1
+ */
+#define DHCPV4_INITIAL_RETRY_TIMEOUT 4
+
+/* Initial minimum delay in INIT state before sending the
+ * initial DISCOVER message. MAx value is defined with
+ * CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX. Default max value
+ * should be 10.
+ * RFC2131 4.1.1
+ */
+#define DHCPV4_INITIAL_DELAY_MIN 1
+
+#if defined(CONFIG_NET_DHCPV4)
+
+int net_dhcpv4_init(void);
+
+#else
+
+#define net_dhcpv4_init() 0
+
+#endif /* CONFIG_NET_DHCPV4 */
+
+#endif /* __INTERNAL_DHCPV4_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/dhcpv4.c	(working copy)
@@ -0,0 +1,1223 @@
+/** @file
+ * @brief DHCPv4 client related functions
+ */
+
+/*
+ * Copyright (c) 2017 ARM Ltd.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2018 Vincent van der Locht
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_dhcpv4, CONFIG_NET_DHCPV4_LOG_LEVEL);
+
+#include <errno.h>
+#include <inttypes.h>
+#include <random/rand32.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+#include "net_private.h"
+
+#include <net/udp.h>
+#include "udp_internal.h"
+#include <net/dhcpv4.h>
+#include <net/dns_resolve.h>
+
+#include "dhcpv4.h"
+#include "ipv4.h"
+
+#define PKT_WAIT_TIME K_SECONDS(1)
+
+static sys_slist_t dhcpv4_ifaces;
+static struct k_delayed_work timeout_work;
+
+static struct net_mgmt_event_callback mgmt4_cb;
+
+/* RFC 1497 [17] */
+static const uint8_t magic_cookie[4] = { 0x63, 0x82, 0x53, 0x63 };
+
+static const char *dhcpv4_msg_type_name(enum dhcpv4_msg_type msg_type)
+	__attribute__((unused));
+
+static const char *dhcpv4_msg_type_name(enum dhcpv4_msg_type msg_type)
+{
+	static const char * const name[] = {
+		"discover",
+		"offer",
+		"request",
+		"decline",
+		"ack",
+		"nak",
+		"release",
+		"inform"
+	};
+
+	__ASSERT_NO_MSG(msg_type >= 1 && msg_type <= sizeof(name));
+	return name[msg_type - 1];
+}
+
+/* Add magic cookie to DCHPv4 messages */
+static inline bool dhcpv4_add_cookie(struct net_pkt *pkt)
+{
+	if (net_pkt_write(pkt, (void *)magic_cookie,
+			  ARRAY_SIZE(magic_cookie))) {
+		return false;
+	}
+
+	return true;
+}
+
+/* Add a an option with the form OPTION LENGTH VALUE.  */
+static bool dhcpv4_add_option_length_value(struct net_pkt *pkt, uint8_t option,
+					   uint8_t size, const void *value)
+{
+	if (net_pkt_write_u8(pkt, option) ||
+	    net_pkt_write_u8(pkt, size) ||
+	    net_pkt_write(pkt, value, size)) {
+		return false;
+	}
+
+	return true;
+}
+
+/* Add DHCPv4 message type */
+static bool dhcpv4_add_msg_type(struct net_pkt *pkt, uint8_t type)
+{
+	return dhcpv4_add_option_length_value(pkt, DHCPV4_OPTIONS_MSG_TYPE,
+					      1, &type);
+}
+
+/* Add DHCPv4 minimum required options for server to reply.
+ * Can be added more if needed.
+ */
+static bool dhcpv4_add_req_options(struct net_pkt *pkt)
+{
+	static uint8_t data[3] = { DHCPV4_OPTIONS_SUBNET_MASK,
+				DHCPV4_OPTIONS_ROUTER,
+				DHCPV4_OPTIONS_DNS_SERVER };
+
+	return dhcpv4_add_option_length_value(pkt, DHCPV4_OPTIONS_REQ_LIST,
+					      ARRAY_SIZE(data), data);
+}
+
+static bool dhcpv4_add_server_id(struct net_pkt *pkt,
+				 const struct in_addr *addr)
+{
+	return dhcpv4_add_option_length_value(pkt, DHCPV4_OPTIONS_SERVER_ID,
+					      4, addr->s4_addr);
+}
+
+static bool dhcpv4_add_req_ipaddr(struct net_pkt *pkt,
+				  const struct in_addr *addr)
+{
+	return dhcpv4_add_option_length_value(pkt, DHCPV4_OPTIONS_REQ_IPADDR,
+					      4, addr->s4_addr);
+}
+
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+static bool dhcpv4_add_hostname(struct net_pkt *pkt,
+				 const char *hostname, const size_t size)
+{
+	return dhcpv4_add_option_length_value(pkt, DHCPV4_OPTIONS_HOST_NAME,
+					      size, hostname);
+}
+#endif
+
+/* Add DHCPv4 Options end, rest of the message can be padded wit zeros */
+static inline bool dhcpv4_add_end(struct net_pkt *pkt)
+{
+	if (net_pkt_write_u8(pkt, DHCPV4_OPTIONS_END)) {
+		return false;
+	}
+
+	return true;
+}
+
+/* File is empty ATM */
+static inline bool dhcpv4_add_file(struct net_pkt *pkt)
+{
+	if (net_pkt_memset(pkt, 0, SIZE_OF_FILE)) {
+		return false;
+	}
+
+	return true;
+}
+
+/* SNAME is empty ATM */
+static inline bool dhcpv4_add_sname(struct net_pkt *pkt)
+{
+	if (net_pkt_memset(pkt, 0, SIZE_OF_SNAME)) {
+		return false;
+	}
+
+	return true;
+}
+
+/* Create DHCPv4 message and add options as per message type */
+static struct net_pkt *dhcpv4_create_message(struct net_if *iface, uint8_t type,
+					     const struct in_addr *ciaddr,
+					     const struct in_addr *src_addr,
+					     const struct in_addr *server_addr,
+					     bool server_id, bool requested_ip)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(dhcp_access, struct dhcp_msg);
+	const struct in_addr *addr;
+	size_t size = DHCPV4_MESSAGE_SIZE;
+	struct net_pkt *pkt;
+	struct dhcp_msg *msg;
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+	const char *hostname = net_hostname_get();
+	const size_t hostname_size = strlen(hostname);
+#endif
+
+	if (src_addr == NULL) {
+		addr = net_ipv4_unspecified_address();
+	} else {
+		addr = src_addr;
+	}
+
+	if (server_id) {
+		size += DHCPV4_OLV_MSG_SERVER_ID;
+	}
+
+	if (requested_ip) {
+		size +=  DHCPV4_OLV_MSG_REQ_IPADDR;
+	}
+
+	if (type == DHCPV4_MSG_TYPE_DISCOVER) {
+		size +=  DHCPV4_OLV_MSG_REQ_LIST;
+	}
+
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+	if (hostname_size > 0) {
+		size += DHCPV4_OLV_MSG_HOST_NAME + hostname_size;
+	}
+#endif
+
+	pkt = net_pkt_alloc_with_buffer(iface, size, AF_INET,
+					IPPROTO_UDP, K_FOREVER);
+
+	net_pkt_set_ipv4_ttl(pkt, 0xFF);
+
+	if (net_ipv4_create(pkt, addr, server_addr) ||
+	    net_udp_create(pkt, htons(DHCPV4_CLIENT_PORT),
+			   htons(DHCPV4_SERVER_PORT))) {
+		goto fail;
+	}
+
+	msg = (struct dhcp_msg *)net_pkt_get_data(pkt, &dhcp_access);
+
+	(void)memset(msg, 0, sizeof(struct dhcp_msg));
+
+	msg->op    = DHCPV4_MSG_BOOT_REQUEST;
+	msg->htype = HARDWARE_ETHERNET_TYPE;
+	msg->hlen  = HARDWARE_ETHERNET_LEN;
+	msg->xid   = htonl(iface->config.dhcpv4.xid);
+	msg->flags = htons(DHCPV4_MSG_BROADCAST);
+
+	if (ciaddr) {
+		/* The ciaddr field was zero'd out above, if we are
+		 * asked to send a ciaddr then fill it in now
+		 * otherwise leave it as all zeros.
+		 */
+		memcpy(msg->ciaddr, ciaddr, 4);
+	}
+
+	memcpy(msg->chaddr, net_if_get_link_addr(iface)->addr,
+	       net_if_get_link_addr(iface)->len);
+
+	if (net_pkt_set_data(pkt, &dhcp_access)) {
+		goto fail;
+	}
+
+	if (!dhcpv4_add_sname(pkt) ||
+	    !dhcpv4_add_file(pkt) ||
+	    !dhcpv4_add_cookie(pkt) ||
+	    !dhcpv4_add_msg_type(pkt, type)) {
+		goto fail;
+	}
+
+	if ((server_id &&
+	     !dhcpv4_add_server_id(pkt, &iface->config.dhcpv4.server_id)) ||
+	    (requested_ip &&
+	     !dhcpv4_add_req_ipaddr(pkt, &iface->config.dhcpv4.requested_ip))) {
+		goto fail;
+	}
+
+	if (type == DHCPV4_MSG_TYPE_DISCOVER && !dhcpv4_add_req_options(pkt)) {
+		goto fail;
+	}
+
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+	if (hostname_size > 0 &&
+	     !dhcpv4_add_hostname(pkt, hostname, hostname_size)) {
+		goto fail;
+	}
+#endif
+
+	if (!dhcpv4_add_end(pkt)) {
+		goto fail;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	net_ipv4_finalize(pkt, IPPROTO_UDP);
+
+	return pkt;
+
+fail:
+	NET_DBG("Message creation failed");
+	net_pkt_unref(pkt);
+
+	return NULL;
+}
+
+static uint32_t dhcpv4_update_message_timeout(struct net_if_dhcpv4 *dhcpv4)
+{
+	uint32_t timeout;
+
+	timeout = DHCPV4_INITIAL_RETRY_TIMEOUT << dhcpv4->attempts;
+
+	/* Max 64 seconds, see RFC 2131 chapter 4.1 */
+	if (timeout < DHCPV4_INITIAL_RETRY_TIMEOUT || timeout > 64) {
+		timeout = 64;
+	}
+
+	/* +1/-1 second randomization */
+	timeout += (sys_rand32_get() % 3U) - 1;
+
+	dhcpv4->attempts++;
+	dhcpv4->timer_start = k_uptime_get();
+	dhcpv4->request_time = timeout;
+
+	return timeout;
+}
+
+/* Prepare DHCPv4 Message request and send it to peer */
+static uint32_t dhcpv4_send_request(struct net_if *iface)
+{
+	const struct in_addr *server_addr = net_ipv4_broadcast_address();
+	const struct in_addr *ciaddr = NULL;
+	const struct in_addr *src_addr = NULL;
+	bool with_server_id = false;
+	bool with_requested_ip = false;
+	struct net_pkt *pkt;
+	uint32_t timeout;
+
+	iface->config.dhcpv4.xid++;
+
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_SELECTING:
+	case NET_DHCPV4_BOUND:
+		/* Not possible */
+		NET_ASSERT(0, "Invalid state %s",
+			   net_dhcpv4_state_name(iface->config.dhcpv4.state));
+		break;
+	case NET_DHCPV4_REQUESTING:
+		with_server_id = true;
+		with_requested_ip = true;
+		break;
+	case NET_DHCPV4_RENEWING:
+		/* Since we have an address populate the ciaddr field.
+		 */
+		ciaddr = &iface->config.dhcpv4.requested_ip;
+
+		/* UNICAST the DHCPREQUEST */
+		src_addr = ciaddr;
+		server_addr = &iface->config.dhcpv4.server_id;
+
+		/* RFC2131 4.4.5 Client MUST NOT include server
+		 * identifier in the DHCPREQUEST.
+		 */
+		break;
+	case NET_DHCPV4_REBINDING:
+		/* Since we have an address populate the ciaddr field.
+		 */
+		ciaddr = &iface->config.dhcpv4.requested_ip;
+		src_addr = ciaddr;
+
+		break;
+	}
+
+	pkt = dhcpv4_create_message(iface, DHCPV4_MSG_TYPE_REQUEST,
+				    ciaddr, src_addr, server_addr,
+				    with_server_id, with_requested_ip);
+	if (!pkt) {
+		goto fail;
+	}
+
+	if (net_send_data(pkt) < 0) {
+		goto fail;
+	}
+
+	timeout = dhcpv4_update_message_timeout(&iface->config.dhcpv4);
+
+	NET_DBG("send request dst=%s xid=0x%x ciaddr=%s%s%s timeout=%us",
+		log_strdup(net_sprint_ipv4_addr(server_addr)),
+		iface->config.dhcpv4.xid,
+		ciaddr ?
+		log_strdup(net_sprint_ipv4_addr(ciaddr)) : "<unknown>",
+		with_server_id ? " +server-id" : "",
+		with_requested_ip ? " +requested-ip" : "",
+		timeout);
+
+	return timeout;
+
+fail:
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	return UINT32_MAX;
+}
+
+/* Prepare DHCPv4 Discover message and broadcast it */
+static uint32_t dhcpv4_send_discover(struct net_if *iface)
+{
+	struct net_pkt *pkt;
+	uint32_t timeout;
+
+	iface->config.dhcpv4.xid++;
+
+	pkt = dhcpv4_create_message(iface, DHCPV4_MSG_TYPE_DISCOVER,
+				    NULL, NULL, net_ipv4_broadcast_address(),
+				    false, false);
+	if (!pkt) {
+		goto fail;
+	}
+
+	if (net_send_data(pkt) < 0) {
+		goto fail;
+	}
+
+	timeout = dhcpv4_update_message_timeout(&iface->config.dhcpv4);
+
+	NET_DBG("send discover xid=0x%x timeout=%us",
+		iface->config.dhcpv4.xid, timeout);
+
+	return timeout;
+
+fail:
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	return iface->config.dhcpv4.xid %
+			(CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX -
+			 DHCPV4_INITIAL_DELAY_MIN) +
+			DHCPV4_INITIAL_DELAY_MIN;
+}
+
+static void dhcpv4_update_timeout_work(uint32_t timeout)
+{
+	if (!k_delayed_work_remaining_get(&timeout_work) ||
+	    (MSEC_PER_SEC * timeout) <
+	    k_delayed_work_remaining_get(&timeout_work)) {
+		k_delayed_work_cancel(&timeout_work);
+		k_delayed_work_submit(&timeout_work, K_SECONDS(timeout));
+	}
+}
+
+static void dhcpv4_enter_selecting(struct net_if *iface)
+{
+	iface->config.dhcpv4.attempts = 0U;
+
+	iface->config.dhcpv4.lease_time = 0U;
+	iface->config.dhcpv4.renewal_time = 0U;
+	iface->config.dhcpv4.rebinding_time = 0U;
+
+	iface->config.dhcpv4.state = NET_DHCPV4_SELECTING;
+	NET_DBG("enter state=%s",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state));
+}
+
+static bool dhcpv4_check_timeout(int64_t start, uint32_t time, int64_t timeout)
+{
+	start += MSEC_PER_SEC * time;
+	if (start < 0) {
+		start = -start;
+	}
+
+	if (start > timeout) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool dhcpv4_request_timedout(struct net_if *iface, int64_t timeout)
+{
+	return dhcpv4_check_timeout(iface->config.dhcpv4.timer_start,
+				    iface->config.dhcpv4.request_time,
+				    timeout);
+}
+
+static bool dhcpv4_renewal_timedout(struct net_if *iface, int64_t timeout)
+{
+	if (!dhcpv4_check_timeout(iface->config.dhcpv4.timer_start,
+				  iface->config.dhcpv4.renewal_time,
+				  timeout)) {
+		return false;
+	}
+
+	iface->config.dhcpv4.state = NET_DHCPV4_RENEWING;
+	NET_DBG("enter state=%s",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state));
+	iface->config.dhcpv4.attempts = 0U;
+
+	return true;
+}
+
+static bool dhcpv4_rebinding_timedout(struct net_if *iface, int64_t timeout)
+{
+	if (!dhcpv4_check_timeout(iface->config.dhcpv4.timer_start,
+				  iface->config.dhcpv4.rebinding_time,
+				  timeout)) {
+		return false;
+	}
+
+	iface->config.dhcpv4.state = NET_DHCPV4_REBINDING;
+	NET_DBG("enter state=%s",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state));
+	iface->config.dhcpv4.attempts = 0U;
+
+	return true;
+}
+
+static void dhcpv4_enter_requesting(struct net_if *iface)
+{
+	iface->config.dhcpv4.attempts = 0U;
+	iface->config.dhcpv4.state = NET_DHCPV4_REQUESTING;
+	NET_DBG("enter state=%s",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state));
+
+	dhcpv4_update_timeout_work(dhcpv4_send_request(iface));
+}
+
+static void dhcpv4_enter_bound(struct net_if *iface)
+{
+	uint32_t renewal_time;
+	uint32_t rebinding_time;
+
+	renewal_time = iface->config.dhcpv4.renewal_time;
+	if (!renewal_time) {
+		/* The default renewal time rfc2131 4.4.5 */
+		renewal_time = iface->config.dhcpv4.lease_time / 2U;
+		iface->config.dhcpv4.renewal_time = renewal_time;
+	}
+
+	rebinding_time = iface->config.dhcpv4.rebinding_time;
+	if (!rebinding_time) {
+		/* The default rebinding time rfc2131 4.4.5 */
+		rebinding_time = iface->config.dhcpv4.lease_time * 875U / 1000;
+		iface->config.dhcpv4.rebinding_time = rebinding_time;
+	}
+
+	iface->config.dhcpv4.state = NET_DHCPV4_BOUND;
+	NET_DBG("enter state=%s renewal=%us rebinding=%us",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state),
+		renewal_time, rebinding_time);
+
+	iface->config.dhcpv4.timer_start = k_uptime_get();
+	iface->config.dhcpv4.request_time = MIN(renewal_time, rebinding_time);
+
+	dhcpv4_update_timeout_work(iface->config.dhcpv4.request_time);
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV4_DHCP_BOUND, iface,
+					&iface->config.dhcpv4,
+					sizeof(iface->config.dhcpv4));
+}
+
+static uint32_t dhcph4_manage_timers(struct net_if *iface, int64_t timeout)
+{
+	NET_DBG("iface %p state=%s", iface,
+		net_dhcpv4_state_name(iface->config.dhcpv4.state));
+
+	if (!dhcpv4_request_timedout(iface, timeout)) {
+		return iface->config.dhcpv4.request_time;
+	}
+
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+		break;
+	case NET_DHCPV4_INIT:
+		dhcpv4_enter_selecting(iface);
+		__fallthrough;
+	case NET_DHCPV4_SELECTING:
+		/* Failed to get OFFER message, send DISCOVER again */
+		return dhcpv4_send_discover(iface);
+	case NET_DHCPV4_REQUESTING:
+		/* Maximum number of renewal attempts failed, so start
+		 * from the beginning.
+		 */
+		if (iface->config.dhcpv4.attempts >=
+					DHCPV4_MAX_NUMBER_OF_ATTEMPTS) {
+			NET_DBG("too many attempts, restart");
+			dhcpv4_enter_selecting(iface);
+			return dhcpv4_send_discover(iface);
+		}
+
+		return dhcpv4_send_request(iface);
+	case NET_DHCPV4_BOUND:
+		if (dhcpv4_renewal_timedout(iface, timeout) ||
+		    dhcpv4_rebinding_timedout(iface, timeout)) {
+			return dhcpv4_send_request(iface);
+		}
+
+		return MIN(iface->config.dhcpv4.renewal_time,
+			   iface->config.dhcpv4.rebinding_time);
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_REBINDING:
+		if (iface->config.dhcpv4.attempts >=
+					DHCPV4_MAX_NUMBER_OF_ATTEMPTS) {
+			NET_DBG("too many attempts, restart");
+
+			if (!net_if_ipv4_addr_rm(iface,
+					 &iface->config.dhcpv4.requested_ip)) {
+				NET_DBG("Failed to remove addr from iface");
+			}
+
+			/* Maximum number of renewal attempts failed, so start
+			 * from the beginning.
+			 */
+			dhcpv4_enter_selecting(iface);
+			return dhcpv4_send_discover(iface);
+		} else {
+			return dhcpv4_send_request(iface);
+		}
+	}
+
+	return UINT32_MAX;
+}
+
+static void dhcpv4_timeout(struct k_work *work)
+{
+	uint32_t timeout_update = UINT32_MAX - 1;
+	int64_t timeout = k_uptime_get();
+	struct net_if_dhcpv4 *current, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&dhcpv4_ifaces, current, next, node) {
+		struct net_if *iface = CONTAINER_OF(
+			CONTAINER_OF(current, struct net_if_config, dhcpv4),
+			struct net_if, config);
+		uint32_t next_timeout;
+
+		next_timeout = dhcph4_manage_timers(iface, timeout);
+		if (next_timeout < timeout_update) {
+			timeout_update = next_timeout;
+		}
+	}
+
+	if (timeout_update != UINT32_MAX) {
+		NET_DBG("Waiting for %us", timeout_update);
+
+		k_delayed_work_submit(&timeout_work,
+				      K_SECONDS(timeout_update));
+	}
+}
+
+/* Parse DHCPv4 options and retrieve relavant information
+ * as per RFC 2132.
+ */
+static bool dhcpv4_parse_options(struct net_pkt *pkt,
+				 struct net_if *iface,
+				 enum dhcpv4_msg_type *msg_type)
+{
+	uint8_t cookie[4];
+	uint8_t length;
+	uint8_t type;
+
+	if (net_pkt_read(pkt, cookie, sizeof(cookie)) ||
+	    memcmp(magic_cookie, cookie, sizeof(magic_cookie))) {
+		NET_DBG("Incorrect magic cookie");
+		return false;
+	}
+
+	while (!net_pkt_read_u8(pkt, &type)) {
+		if (type == DHCPV4_OPTIONS_END) {
+			NET_DBG("options_end");
+			return true;
+		}
+
+		if (net_pkt_read_u8(pkt, &length)) {
+			NET_ERR("option parsing, bad length");
+			return false;
+		}
+
+		switch (type) {
+		case DHCPV4_OPTIONS_SUBNET_MASK: {
+			struct in_addr netmask;
+
+			if (length != 4U) {
+				NET_ERR("options_subnet_mask, bad length");
+				return false;
+			}
+
+			if (net_pkt_read(pkt, netmask.s4_addr, length)) {
+				NET_ERR("options_subnet_mask, short packet");
+				return false;
+			}
+
+			net_if_ipv4_set_netmask(iface, &netmask);
+			NET_DBG("options_subnet_mask %s",
+				log_strdup(net_sprint_ipv4_addr(&netmask)));
+			break;
+		}
+		case DHCPV4_OPTIONS_ROUTER: {
+			struct in_addr router;
+
+			/* Router option may present 1 or more
+			 * addresses for routers on the clients
+			 * subnet.  Routers should be listed in order
+			 * of preference.  Hence we choose the first
+			 * and skip the rest.
+			 */
+			if (length % 4 != 0U || length < 4) {
+				NET_ERR("options_router, bad length");
+				return false;
+			}
+
+			if (net_pkt_read(pkt, router.s4_addr, 4) ||
+			    net_pkt_skip(pkt, length - 4U)) {
+				NET_ERR("options_router, short packet");
+				return false;
+			}
+
+			NET_DBG("options_router: %s",
+				log_strdup(net_sprint_ipv4_addr(&router)));
+			net_if_ipv4_set_gw(iface, &router);
+			break;
+		}
+#if defined(CONFIG_DNS_RESOLVER)
+		case DHCPV4_OPTIONS_DNS_SERVER: {
+			int i;
+			struct dns_resolve_context *ctx;
+			struct sockaddr_in dns;
+			const struct sockaddr *dns_servers[] = {
+				(struct sockaddr *)&dns, NULL
+			};
+			int status;
+
+			/* DNS server option may present 1 or more
+			 * addresses. Each 4 bytes in length. DNS
+			 * servers should be listed in order
+			 * of preference.  Hence we choose the first
+			 * and skip the rest.
+			 */
+			if (length % 4 != 0U) {
+				NET_ERR("options_dns, bad length");
+				return false;
+			}
+
+			(void)memset(&dns, 0, sizeof(dns));
+
+			if (net_pkt_read(pkt, dns.sin_addr.s4_addr, 4) ||
+			    net_pkt_skip(pkt, length - 4U)) {
+				NET_ERR("options_dns, short packet");
+				return false;
+			}
+
+			ctx = dns_resolve_get_default();
+			for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+				if (!ctx->queries[i].cb) {
+					continue;
+				}
+
+				dns_resolve_cancel(ctx, ctx->queries[i].id);
+			}
+			dns_resolve_close(ctx);
+
+			dns.sin_family = AF_INET;
+			status = dns_resolve_init(ctx, NULL, dns_servers);
+			if (status < 0) {
+				NET_DBG("options_dns, failed to set "
+					"resolve address: %d", status);
+				return false;
+			}
+
+			break;
+		}
+#endif
+		case DHCPV4_OPTIONS_LEASE_TIME:
+			if (length != 4U) {
+				NET_ERR("options_lease_time, bad length");
+				return false;
+			}
+
+			if (net_pkt_read_be32(
+				    pkt, &iface->config.dhcpv4.lease_time) ||
+			    !iface->config.dhcpv4.lease_time) {
+				NET_ERR("options_lease_time, wrong value");
+				return false;
+			}
+
+			NET_DBG("options_lease_time: %u",
+				iface->config.dhcpv4.lease_time);
+
+			break;
+		case DHCPV4_OPTIONS_RENEWAL:
+			if (length != 4U) {
+				NET_DBG("options_renewal, bad length");
+				return false;
+			}
+
+			if (net_pkt_read_be32(
+				    pkt, &iface->config.dhcpv4.renewal_time) ||
+			    !iface->config.dhcpv4.renewal_time) {
+				NET_DBG("options_renewal, wrong value");
+				return false;
+			}
+
+			NET_DBG("options_renewal: %u",
+				iface->config.dhcpv4.renewal_time);
+
+			break;
+		case DHCPV4_OPTIONS_REBINDING:
+			if (length != 4U) {
+				NET_DBG("options_rebinding, bad length");
+				return false;
+			}
+
+			if (net_pkt_read_be32(
+				    pkt,
+				    &iface->config.dhcpv4.rebinding_time) ||
+			    !iface->config.dhcpv4.rebinding_time) {
+				NET_DBG("options_rebinding, wrong value");
+				return false;
+			}
+
+			NET_DBG("options_rebinding: %u",
+				iface->config.dhcpv4.rebinding_time);
+
+			break;
+		case DHCPV4_OPTIONS_SERVER_ID:
+			if (length != 4U) {
+				NET_DBG("options_server_id, bad length");
+				return false;
+			}
+
+			if (net_pkt_read(
+				    pkt,
+				    iface->config.dhcpv4.server_id.s4_addr,
+				    length)) {
+				NET_DBG("options_server_id, read err");
+				return false;
+			}
+
+			NET_DBG("options_server_id: %s",
+				log_strdup(net_sprint_ipv4_addr(
+					   &iface->config.dhcpv4.server_id)));
+			break;
+		case DHCPV4_OPTIONS_MSG_TYPE: {
+			if (length != 1U) {
+				NET_DBG("options_msg_type, bad length");
+				return false;
+			}
+
+			if (net_pkt_read_u8(pkt, (uint8_t *)msg_type)) {
+				NET_DBG("options_msg_type, read err");
+				return false;
+			}
+
+			break;
+		}
+		default:
+			NET_DBG("option unknown: %d", type);
+
+			if (net_pkt_skip(pkt, length)) {
+				NET_DBG("option unknown, skip err");
+				return false;
+			}
+
+			break;
+		}
+	}
+
+	/* Invalid case: Options without DHCPV4_OPTIONS_END. */
+	return false;
+}
+
+static inline void dhcpv4_handle_msg_offer(struct net_if *iface)
+{
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_REQUESTING:
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_REBINDING:
+	case NET_DHCPV4_BOUND:
+		break;
+	case NET_DHCPV4_SELECTING:
+		dhcpv4_enter_requesting(iface);
+		break;
+	}
+}
+
+static void dhcpv4_handle_msg_ack(struct net_if *iface)
+{
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_SELECTING:
+	case NET_DHCPV4_BOUND:
+		break;
+	case NET_DHCPV4_REQUESTING:
+		NET_INFO("Received: %s",
+			 log_strdup(net_sprint_ipv4_addr(
+					 &iface->config.dhcpv4.requested_ip)));
+
+		if (!net_if_ipv4_addr_add(iface,
+					  &iface->config.dhcpv4.requested_ip,
+					  NET_ADDR_DHCP,
+					  iface->config.dhcpv4.lease_time)) {
+			NET_DBG("Failed to add IPv4 addr to iface %p", iface);
+			return;
+		}
+
+		dhcpv4_enter_bound(iface);
+		break;
+
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_REBINDING:
+		/* TODO: If the renewal is success, update only
+		 * vlifetime on iface.
+		 */
+		dhcpv4_enter_bound(iface);
+		break;
+	}
+}
+
+static void dhcpv4_handle_msg_nak(struct net_if *iface)
+{
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_SELECTING:
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_BOUND:
+		break;
+	case NET_DHCPV4_REQUESTING:
+	case NET_DHCPV4_REBINDING:
+		/* Restart the configuration process. */
+		dhcpv4_enter_selecting(iface);
+		break;
+	}
+}
+
+static void dhcpv4_handle_reply(struct net_if *iface,
+				enum dhcpv4_msg_type msg_type)
+{
+	NET_DBG("state=%s msg=%s",
+		net_dhcpv4_state_name(iface->config.dhcpv4.state),
+		dhcpv4_msg_type_name(msg_type));
+
+	switch (msg_type) {
+	case DHCPV4_MSG_TYPE_OFFER:
+		dhcpv4_handle_msg_offer(iface);
+		break;
+	case DHCPV4_MSG_TYPE_ACK:
+		dhcpv4_handle_msg_ack(iface);
+		break;
+	case DHCPV4_MSG_TYPE_NAK:
+		dhcpv4_handle_msg_nak(iface);
+		break;
+	default:
+		NET_DBG("ignore message");
+		break;
+	}
+}
+
+static enum net_verdict net_dhcpv4_input(struct net_conn *conn,
+					 struct net_pkt *pkt,
+					 union net_ip_header *ip_hdr,
+					 union net_proto_header *proto_hdr,
+					 void *user_data)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(dhcp_access, struct dhcp_msg);
+	enum dhcpv4_msg_type msg_type = 0;
+	struct dhcp_msg *msg;
+	struct net_if *iface;
+
+	if (!conn) {
+		NET_DBG("Invalid connection");
+		return NET_DROP;
+	}
+
+	if (!pkt) {
+		NET_DBG("Invalid packet");
+		return NET_DROP;
+	}
+
+	iface = net_pkt_iface(pkt);
+	if (!iface) {
+		NET_DBG("no iface");
+		return NET_DROP;
+	}
+
+	/* If the message is not DHCP then continue passing to
+	 * related handlers.
+	 */
+	if (net_pkt_get_len(pkt) < NET_IPV4UDPH_LEN + sizeof(struct dhcp_msg)) {
+		NET_DBG("Input msg is not related to DHCPv4");
+		return NET_CONTINUE;
+
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, NET_IPV4UDPH_LEN)) {
+		return NET_DROP;
+	}
+
+	msg = (struct dhcp_msg *)net_pkt_get_data(pkt, &dhcp_access);
+	if (!msg) {
+		return NET_DROP;
+	}
+
+	NET_DBG("Received dhcp msg [op=0x%x htype=0x%x hlen=%u xid=0x%x "
+		"secs=%u flags=0x%x chaddr=%s",
+		msg->op, msg->htype, msg->hlen, ntohl(msg->xid),
+		msg->secs, msg->flags,
+		log_strdup(net_sprint_ll_addr(msg->chaddr, 6)));
+	NET_DBG("  ciaddr=%d.%d.%d.%d",
+		msg->ciaddr[0], msg->ciaddr[1], msg->ciaddr[2], msg->ciaddr[3]);
+	NET_DBG("  yiaddr=%d.%d.%d.%d",
+		msg->yiaddr[0], msg->yiaddr[1], msg->yiaddr[2], msg->yiaddr[3]);
+	NET_DBG("  siaddr=%d.%d.%d.%d",
+		msg->siaddr[0], msg->siaddr[1], msg->siaddr[2], msg->siaddr[3]);
+	NET_DBG("  giaddr=%d.%d.%d.%d]",
+		msg->giaddr[0], msg->giaddr[1], msg->giaddr[2], msg->giaddr[3]);
+
+	if (!(msg->op == DHCPV4_MSG_BOOT_REPLY &&
+	      iface->config.dhcpv4.xid == ntohl(msg->xid) &&
+	      !memcmp(msg->chaddr, net_if_get_link_addr(iface)->addr,
+		      net_if_get_link_addr(iface)->len))) {
+
+		NET_DBG("Unexpected op (%d), xid (%x vs %x) or chaddr",
+			msg->op, iface->config.dhcpv4.xid, ntohl(msg->xid));
+		return NET_DROP;
+	}
+
+	memcpy(iface->config.dhcpv4.requested_ip.s4_addr,
+	       msg->yiaddr, sizeof(msg->yiaddr));
+
+	net_pkt_acknowledge_data(pkt, &dhcp_access);
+
+	/* SNAME, FILE are not used at the moment, skip it */
+	if (net_pkt_skip(pkt, SIZE_OF_SNAME + SIZE_OF_FILE)) {
+		NET_DBG("short packet while skipping sname");
+		return NET_DROP;
+	}
+
+	if (!dhcpv4_parse_options(pkt, iface, &msg_type)) {
+		return NET_DROP;
+	}
+
+	net_pkt_unref(pkt);
+
+	dhcpv4_handle_reply(iface, msg_type);
+
+	return NET_OK;
+}
+
+static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb,
+				       uint32_t mgmt_event, struct net_if *iface)
+{
+	sys_snode_t *node = NULL;
+
+	SYS_SLIST_FOR_EACH_NODE(&dhcpv4_ifaces, node) {
+		if (node == &iface->config.dhcpv4.node) {
+			break;
+		}
+	}
+
+	if (node == NULL) {
+		return;
+	}
+
+	if (mgmt_event == NET_EVENT_IF_DOWN) {
+		NET_DBG("Interface %p going down", iface);
+
+		if (iface->config.dhcpv4.state == NET_DHCPV4_BOUND) {
+			iface->config.dhcpv4.attempts = 0U;
+			iface->config.dhcpv4.state = NET_DHCPV4_RENEWING;
+			NET_DBG("enter state=%s", net_dhcpv4_state_name(
+					iface->config.dhcpv4.state));
+		}
+	} else if (mgmt_event == NET_EVENT_IF_UP) {
+		NET_DBG("Interface %p coming up", iface);
+
+		/* We should not call dhcpv4_send_request() directly here as
+		 * the CONFIG_NET_MGMT_EVENT_STACK_SIZE is not large
+		 * enough. Instead we can force a request timeout
+		 * which will then call dhcpv4_send_request() automatically.
+		 */
+		iface->config.dhcpv4.timer_start = k_uptime_get() - 1;
+		iface->config.dhcpv4.request_time = 0U;
+
+		k_delayed_work_cancel(&timeout_work);
+		k_delayed_work_submit(&timeout_work, K_NO_WAIT);
+	}
+}
+
+const char *net_dhcpv4_state_name(enum net_dhcpv4_state state)
+{
+	static const char * const name[] = {
+		"disabled",
+		"init",
+		"selecting",
+		"requesting",
+		"renewing",
+		"rebinding",
+		"bound",
+	};
+
+	__ASSERT_NO_MSG(state >= 0 && state < sizeof(name));
+	return name[state];
+}
+
+void net_dhcpv4_start(struct net_if *iface)
+{
+	uint32_t timeout;
+	uint32_t entropy;
+
+	net_mgmt_event_notify(NET_EVENT_IPV4_DHCP_START, iface);
+
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+		iface->config.dhcpv4.state = NET_DHCPV4_INIT;
+		NET_DBG("iface %p state=%s", iface,
+			net_dhcpv4_state_name(iface->config.dhcpv4.state));
+
+		iface->config.dhcpv4.attempts = 0U;
+		iface->config.dhcpv4.lease_time = 0U;
+		iface->config.dhcpv4.renewal_time = 0U;
+
+		iface->config.dhcpv4.server_id.s_addr = 0U;
+		iface->config.dhcpv4.requested_ip.s_addr = 0U;
+
+		/* We need entropy for both an XID and a random delay
+		 * before sending the initial discover message.
+		 */
+		entropy = sys_rand32_get();
+
+		/* A DHCP client MUST choose xid's in such a way as to
+		 * minimize the change of using and xid identical to
+		 * one used by another client.  Choose a random xid st
+		 * startup and increment it on each new request.
+		 */
+		iface->config.dhcpv4.xid = entropy;
+
+
+		/* RFC2131 4.1.1 requires we wait a random period
+		 * between 1 and 10 seconds before sending the initial
+		 * discover.
+		 */
+		timeout = entropy %
+				(CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX -
+				  DHCPV4_INITIAL_DELAY_MIN) +
+				DHCPV4_INITIAL_DELAY_MIN;
+
+		NET_DBG("wait timeout=%us", timeout);
+
+		if (sys_slist_is_empty(&dhcpv4_ifaces)) {
+			net_mgmt_add_event_callback(&mgmt4_cb);
+		}
+
+		sys_slist_append(&dhcpv4_ifaces,
+				 &iface->config.dhcpv4.node);
+
+		iface->config.dhcpv4.timer_start = k_uptime_get();
+		iface->config.dhcpv4.request_time = timeout;
+
+		dhcpv4_update_timeout_work(timeout);
+
+		break;
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_SELECTING:
+	case NET_DHCPV4_REQUESTING:
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_REBINDING:
+	case NET_DHCPV4_BOUND:
+		break;
+	}
+}
+
+void net_dhcpv4_stop(struct net_if *iface)
+{
+	switch (iface->config.dhcpv4.state) {
+	case NET_DHCPV4_DISABLED:
+		break;
+
+	case NET_DHCPV4_RENEWING:
+	case NET_DHCPV4_BOUND:
+		if (!net_if_ipv4_addr_rm(iface,
+					 &iface->config.dhcpv4.requested_ip)) {
+			NET_DBG("Failed to remove addr from iface");
+		}
+
+		__fallthrough;
+	case NET_DHCPV4_INIT:
+	case NET_DHCPV4_SELECTING:
+	case NET_DHCPV4_REQUESTING:
+	case NET_DHCPV4_REBINDING:
+		iface->config.dhcpv4.state = NET_DHCPV4_DISABLED;
+		NET_DBG("state=%s",
+			net_dhcpv4_state_name(iface->config.dhcpv4.state));
+
+		sys_slist_find_and_remove(&dhcpv4_ifaces,
+					  &iface->config.dhcpv4.node);
+
+		if (sys_slist_is_empty(&dhcpv4_ifaces)) {
+			k_delayed_work_cancel(&timeout_work);
+			net_mgmt_del_event_callback(&mgmt4_cb);
+		}
+
+		break;
+	}
+
+	net_mgmt_event_notify(NET_EVENT_IPV4_DHCP_STOP, iface);
+}
+
+int net_dhcpv4_init(void)
+{
+	struct sockaddr local_addr;
+	int ret;
+
+	NET_DBG("");
+
+	net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
+			net_ipv4_unspecified_address());
+	local_addr.sa_family = AF_INET;
+
+	/* Register UDP input callback on
+	 * DHCPV4_SERVER_PORT(67) and DHCPV4_CLIENT_PORT(68) for
+	 * all dhcpv4 related incoming packets.
+	 */
+	ret = net_udp_register(AF_INET, NULL, &local_addr,
+			       DHCPV4_SERVER_PORT,
+			       DHCPV4_CLIENT_PORT,
+			       net_dhcpv4_input, NULL, NULL);
+	if (ret < 0) {
+		NET_DBG("UDP callback registration failed");
+		return ret;
+	}
+
+	k_delayed_work_init(&timeout_work, dhcpv4_timeout);
+
+	/* Catch network interface UP or DOWN events and renew the address
+	 * if interface is coming back up again.
+	 */
+	net_mgmt_init_event_callback(&mgmt4_cb, dhcpv4_iface_event_handler,
+					 NET_EVENT_IF_DOWN | NET_EVENT_IF_UP);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.h	(working copy)
@@ -0,0 +1,114 @@
+/** @file
+ @brief ICMPv4 handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ICMPV4_H
+#define __ICMPV4_H
+
+#include <zephyr/types.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+
+#define NET_ICMPV4_DST_UNREACH  3	/* Destination unreachable */
+#define NET_ICMPV4_ECHO_REQUEST 8
+#define NET_ICMPV4_ECHO_REPLY   0
+
+#define NET_ICMPV4_DST_UNREACH_NO_PROTO  2 /* Protocol not supported */
+#define NET_ICMPV4_DST_UNREACH_NO_PORT   3 /* Port unreachable */
+
+#define NET_ICMPV4_UNUSED_LEN 4
+
+struct net_icmpv4_echo_req {
+	uint16_t identifier;
+	uint16_t sequence;
+} __packed;
+
+typedef enum net_verdict (*icmpv4_callback_handler_t)(
+					struct net_pkt *pkt,
+					struct net_ipv4_hdr *ip_hdr,
+					struct net_icmp_hdr *icmp_hdr);
+
+struct net_icmpv4_handler {
+	sys_snode_t node;
+	icmpv4_callback_handler_t handler;
+	uint8_t type;
+	uint8_t code;
+};
+
+/**
+ * @brief Send ICMPv4 error message.
+ * @param pkt Network packet that this error is related to.
+ * @param type Type of the error message.
+ * @param code Code of the type of the error message.
+ * @return Return 0 if the sending succeed, <0 otherwise.
+ */
+int net_icmpv4_send_error(struct net_pkt *pkt, uint8_t type, uint8_t code);
+
+/**
+ * @brief Send ICMPv4 echo request message.
+ *
+ * @param iface Network interface.
+ * @param dst IPv4 address of the target host.
+ * @param identifier An identifier to aid in matching Echo Replies
+ * to this Echo Request. May be zero.
+ * @param sequence A sequence number to aid in matching Echo Replies
+ * to this Echo Request. May be zero.
+ * @param data Arbitrary payload data that will be included in the
+ * Echo Reply verbatim. May be zero.
+ * @param data_size Size of the Payload Data in bytes. May be zero.
+ *
+ * @return Return 0 if the sending succeed, <0 otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+int net_icmpv4_send_echo_request(struct net_if *iface,
+				 struct in_addr *dst,
+				 uint16_t identifier,
+				 uint16_t sequence,
+				 const void *data,
+				 size_t data_size);
+#else
+static inline int net_icmpv4_send_echo_request(struct net_if *iface,
+					       struct in_addr *dst,
+					       uint16_t identifier,
+					       uint16_t sequence,
+					       const void *data,
+					       size_t data_size)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(dst);
+	ARG_UNUSED(identifier);
+	ARG_UNUSED(sequence);
+	ARG_UNUSED(data);
+	ARG_UNUSED(data_size);
+
+	return -ENOTSUP;
+}
+#endif
+
+#if defined(CONFIG_NET_NATIVE_IPV4)
+void net_icmpv4_register_handler(struct net_icmpv4_handler *handler);
+
+void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler);
+
+enum net_verdict net_icmpv4_input(struct net_pkt *pkt,
+				  struct net_ipv4_hdr *ip_hdr);
+
+int net_icmpv4_finalize(struct net_pkt *pkt);
+
+void net_icmpv4_init(void);
+#else
+#define net_icmpv4_init(...)
+#define net_icmpv4_register_handler(...)
+#define net_icmpv4_unregister_handler(...)
+#endif
+
+#endif /* __ICMPV4_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv4.c	(working copy)
@@ -0,0 +1,718 @@
+/** @file
+ * @brief ICMPv4 related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_icmpv4, CONFIG_NET_ICMPV4_LOG_LEVEL);
+
+#include <errno.h>
+#include <sys/slist.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include "net_private.h"
+#include "ipv4.h"
+#include "icmpv4.h"
+#include "net_stats.h"
+
+#define PKT_WAIT_TIME K_SECONDS(1)
+
+static sys_slist_t handlers;
+
+struct net_icmpv4_hdr_opts_data {
+	struct net_pkt *reply;
+	const struct in_addr *src;
+};
+
+static int icmpv4_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmpv4_access);
+	if (!icmp_hdr) {
+		return -ENOBUFS;
+	}
+
+	icmp_hdr->type   = icmp_type;
+	icmp_hdr->code   = icmp_code;
+	icmp_hdr->chksum = 0U;
+
+	return net_pkt_set_data(pkt, &icmpv4_access);
+}
+
+int net_icmpv4_finalize(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+
+	if (IS_ENABLED(CONFIG_NET_IPV4_HDR_OPTIONS)) {
+		if (net_pkt_skip(pkt, net_pkt_ipv4_opts_len(pkt))) {
+			return -ENOBUFS;
+		}
+	}
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmpv4_access);
+	if (!icmp_hdr) {
+		return -ENOBUFS;
+	}
+
+	icmp_hdr->chksum = net_calc_chksum_icmpv4(pkt);
+
+	return net_pkt_set_data(pkt, &icmpv4_access);
+}
+
+#if defined(CONFIG_NET_IPV4_HDR_OPTIONS)
+
+/* Parse Record Route and add our own IP address based on
+ * free entries.
+ */
+static int icmpv4_update_record_route(uint8_t *opt_data,
+				      uint8_t opt_len,
+				      struct net_pkt *reply,
+				      const struct in_addr *src)
+{
+	uint8_t len = net_pkt_ipv4_opts_len(reply);
+	uint8_t addr_len = sizeof(struct in_addr);
+	uint8_t ptr_offset = 4U;
+	uint8_t offset = 0U;
+	uint8_t skip;
+	uint8_t ptr;
+
+	if (net_pkt_write_u8(reply, NET_IPV4_OPTS_RR)) {
+		goto drop;
+	}
+
+	len++;
+
+	if (net_pkt_write_u8(reply, opt_len + 2U)) {
+		goto drop;
+	}
+
+	len++;
+
+	/* The third octet is the pointer into the route data
+	 * indicating the octet which begins the next area to
+	 * store a route address. The pointer is relative to
+	 * this option, and the smallest legal value for the
+	 * pointer is 4.
+	 */
+	ptr = opt_data[offset++];
+
+	/* If the route data area is already full (the pointer exceeds
+	 * the length) the datagram is forwarded without inserting the
+	 * address into the recorded route.
+	 */
+	if (ptr >= opt_len) {
+		/* No free entry to update RecordRoute */
+		if (net_pkt_write_u8(reply, ptr)) {
+			goto drop;
+		}
+
+		len++;
+
+		if (net_pkt_write(reply, opt_data + offset, opt_len)) {
+			goto drop;
+		}
+
+		len += opt_len;
+
+		net_pkt_set_ipv4_opts_len(reply, len);
+
+		return 0;
+	}
+
+	/* If there is some room but not enough room for a full address
+	 * to be inserted, the original datagram is considered to be in
+	 * error and is discarded.
+	 */
+	if ((ptr + addr_len) > opt_len) {
+		goto drop;
+	}
+
+	/* So, there is a free entry to update Record Route */
+	if (net_pkt_write_u8(reply, ptr + addr_len)) {
+		goto drop;
+	}
+
+	len++;
+
+	skip = ptr - ptr_offset;
+	if (skip) {
+		/* Do not alter existed routes */
+		if (net_pkt_write(reply, opt_data + offset, skip)) {
+			goto drop;
+		}
+
+		offset += skip;
+		len += skip;
+	}
+
+	if (net_pkt_write(reply, (void *)src, addr_len)) {
+		goto drop;
+	}
+
+	len += addr_len;
+	offset += addr_len;
+
+	if (opt_len > offset) {
+		if (net_pkt_write(reply, opt_data + offset, opt_len - offset)) {
+			goto drop;
+		}
+	}
+
+	len += opt_len - offset;
+
+	net_pkt_set_ipv4_opts_len(reply, len);
+
+	return 0;
+
+drop:
+	return -EINVAL;
+}
+
+/* TODO: Timestamp value should updated, as per RFC 791
+ * Internet Timestamp. Timestamp value : 32-bit timestamp
+ * in milliseconds since midnight UT.
+ */
+static int icmpv4_update_time_stamp(uint8_t *opt_data,
+				   uint8_t opt_len,
+				   struct net_pkt *reply,
+				   const struct in_addr *src)
+{
+	uint8_t len = net_pkt_ipv4_opts_len(reply);
+	uint8_t addr_len = sizeof(struct in_addr);
+	uint8_t ptr_offset = 5U;
+	uint8_t offset = 0U;
+	uint8_t new_entry_len;
+	uint8_t overflow;
+	uint8_t flag;
+	uint8_t skip;
+	uint8_t ptr;
+
+	if (net_pkt_write_u8(reply, NET_IPV4_OPTS_TS)) {
+		goto drop;
+	}
+
+	len++;
+
+	if (net_pkt_write_u8(reply, opt_len + 2U)) {
+		goto drop;
+	}
+
+	len++;
+
+	/* The Pointer is the number of octets from the beginning of
+	 * this option to the end of timestamps plus one (i.e., it
+	 * points to the octet beginning the space for next timestamp).
+	 * The smallest legal value is 5.  The timestamp area is full
+	 * when the pointer is greater than the length.
+	 */
+	ptr = opt_data[offset++];
+	flag = opt_data[offset++];
+
+	flag = flag & 0x0F;
+	overflow = (flag & 0xF0) >> 4U;
+
+	/* If the timestamp data area is already full (the pointer
+	 * exceeds the length) the datagram is forwarded without
+	 * inserting the timestamp, but the overflow count is
+	 * incremented by one.
+	 */
+	if (ptr >= opt_len) {
+		/* overflow count itself overflows, the original datagram
+		 * is considered to be in error and is discarded.
+		 */
+		if (overflow == 0x0F) {
+			goto drop;
+		}
+
+		/* No free entry to update Timestamp data */
+		if (net_pkt_write_u8(reply, ptr)) {
+			goto drop;
+		}
+
+		len++;
+
+		overflow++;
+		flag = (overflow << 4U) | flag;
+
+		if (net_pkt_write_u8(reply, flag)) {
+			goto drop;
+		}
+
+		len++;
+
+		if (net_pkt_write(reply, opt_data + offset, opt_len)) {
+			goto drop;
+		}
+
+		len += opt_len;
+
+		net_pkt_set_ipv4_opts_len(reply, len);
+
+		return 0;
+	}
+
+	switch (flag) {
+	case NET_IPV4_TS_OPT_TS_ONLY:
+		new_entry_len = sizeof(uint32_t);
+		break;
+	case NET_IPV4_TS_OPT_TS_ADDR:
+		new_entry_len = addr_len + sizeof(uint32_t);
+		break;
+	case NET_IPV4_TS_OPT_TS_PRES: /* TODO */
+	default:
+		goto drop;
+	}
+
+	/* So, there is a free entry to update Timestamp */
+	if (net_pkt_write_u8(reply, ptr + new_entry_len)) {
+		goto drop;
+	}
+
+	len++;
+
+	if (net_pkt_write_u8(reply, (overflow << 4) | flag)) {
+		goto drop;
+	}
+
+	len++;
+
+	skip = ptr - ptr_offset;
+	if (skip) {
+		/* Do not alter existed routes */
+		if (net_pkt_write(reply, opt_data + offset, skip)) {
+			goto drop;
+		}
+
+		len += skip;
+		offset += skip;
+	}
+
+	switch (flag) {
+	case NET_IPV4_TS_OPT_TS_ONLY:
+		if (net_pkt_write_be32(reply, htons(k_uptime_get_32()))) {
+			goto drop;
+		}
+
+		len += sizeof(uint32_t);
+
+		offset += sizeof(uint32_t);
+
+		break;
+	case NET_IPV4_TS_OPT_TS_ADDR:
+		if (net_pkt_write(reply, (void *)src, addr_len)) {
+			goto drop;
+		}
+
+		len += addr_len;
+
+		if (net_pkt_write_be32(reply, htons(k_uptime_get_32()))) {
+			goto drop;
+		}
+
+		len += sizeof(uint32_t);
+
+		offset += (addr_len + sizeof(uint32_t));
+
+		break;
+	}
+
+	if (opt_len > offset) {
+		if (net_pkt_write(reply, opt_data + offset, opt_len - offset)) {
+			goto drop;
+		}
+	}
+
+	len += opt_len - offset;
+
+	net_pkt_set_ipv4_opts_len(reply, len);
+
+	return 0;
+
+drop:
+	return -EINVAL;
+}
+
+static int icmpv4_reply_to_options(uint8_t opt_type,
+				   uint8_t *opt_data,
+				   uint8_t opt_len,
+				   void *user_data)
+{
+	struct net_icmpv4_hdr_opts_data *ud =
+		(struct net_icmpv4_hdr_opts_data *)user_data;
+
+	if (opt_type == NET_IPV4_OPTS_RR) {
+		return icmpv4_update_record_route(opt_data, opt_len,
+						  ud->reply, ud->src);
+	} else if (opt_type == NET_IPV4_OPTS_TS) {
+		return icmpv4_update_time_stamp(opt_data, opt_len,
+						ud->reply, ud->src);
+	}
+
+	return 0;
+}
+
+static int icmpv4_handle_header_options(struct net_pkt *pkt,
+					struct net_pkt *reply,
+					const struct in_addr *src)
+{
+	struct net_icmpv4_hdr_opts_data ud;
+	uint8_t len;
+
+	ud.reply = reply;
+	ud.src = src;
+
+	if (net_ipv4_parse_hdr_options(pkt, icmpv4_reply_to_options, &ud)) {
+		return -EINVAL;
+	}
+
+	len = net_pkt_ipv4_opts_len(reply);
+
+	/* IPv4 optional header part should ends in 32 bit boundary */
+	if (len % 4U != 0U) {
+		uint8_t i = 4U - (len % 4U);
+
+		if (net_pkt_memset(reply, NET_IPV4_OPTS_NOP, i)) {
+			return -EINVAL;
+		}
+
+		len += i;
+	}
+
+	/* Options are added now, update the header length. */
+	net_pkt_set_ipv4_opts_len(reply, len);
+
+	return 0;
+}
+#else
+static int icmpv4_handle_header_options(struct net_pkt *pkt,
+					struct net_pkt *reply,
+					const struct in_addr *src)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(reply);
+	ARG_UNUSED(src);
+
+	return 0;
+}
+#endif
+
+static enum net_verdict icmpv4_handle_echo_request(struct net_pkt *pkt,
+					   struct net_ipv4_hdr *ip_hdr,
+					   struct net_icmp_hdr *icmp_hdr)
+{
+	struct net_pkt *reply = NULL;
+	const struct in_addr *src;
+	int16_t payload_len;
+
+	/* If interface can not select src address based on dst addr
+	 * and src address is unspecified, drop the echo request.
+	 */
+	if (net_ipv4_is_addr_unspecified(&ip_hdr->src)) {
+		NET_DBG("DROP: src addr is unspecified");
+		goto drop;
+	}
+
+	NET_DBG("Received Echo Request from %s to %s",
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->src)),
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->dst)));
+
+	payload_len = net_pkt_get_len(pkt) -
+		      net_pkt_ip_hdr_len(pkt) -
+		      net_pkt_ipv4_opts_len(pkt) - NET_ICMPH_LEN;
+	if (payload_len < NET_ICMPV4_UNUSED_LEN) {
+		/* No identifier or sequence number present */
+		goto drop;
+	}
+
+	reply = net_pkt_alloc_with_buffer(net_pkt_iface(pkt),
+					  net_pkt_ipv4_opts_len(pkt) +
+					  payload_len,
+					  AF_INET, IPPROTO_ICMP,
+					  PKT_WAIT_TIME);
+	if (!reply) {
+		NET_DBG("DROP: No buffer");
+		goto drop;
+	}
+
+	if (net_ipv4_is_addr_mcast(&ip_hdr->dst)) {
+		src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
+						  &ip_hdr->dst);
+	} else {
+		src = &ip_hdr->dst;
+	}
+
+	if (net_ipv4_create(reply, src, &ip_hdr->src)) {
+		goto drop;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4_HDR_OPTIONS)) {
+		if (net_pkt_ipv4_opts_len(pkt) &&
+		    icmpv4_handle_header_options(pkt, reply, src)) {
+			goto drop;
+		}
+	}
+
+	if (icmpv4_create(reply, NET_ICMPV4_ECHO_REPLY, 0) ||
+	    net_pkt_copy(reply, pkt, payload_len)) {
+		goto drop;
+	}
+
+	net_pkt_cursor_init(reply);
+	net_ipv4_finalize(reply, IPPROTO_ICMP);
+
+	NET_DBG("Sending Echo Reply from %s to %s",
+		log_strdup(net_sprint_ipv4_addr(src)),
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->src)));
+
+	if (net_send_data(reply) < 0) {
+		goto drop;
+	}
+
+	net_stats_update_icmp_sent(net_pkt_iface(reply));
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+drop:
+	if (reply) {
+		net_pkt_unref(reply);
+	}
+
+	net_stats_update_icmp_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+int net_icmpv4_send_echo_request(struct net_if *iface,
+				 struct in_addr *dst,
+				 uint16_t identifier,
+				 uint16_t sequence,
+				 const void *data,
+				 size_t data_size)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access,
+					      struct net_icmpv4_echo_req);
+	int ret = -ENOBUFS;
+	struct net_icmpv4_echo_req *echo_req;
+	const struct in_addr *src;
+	struct net_pkt *pkt;
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) && net_if_is_ip_offloaded(iface)) {
+		return -ENOTSUP;
+	}
+
+	if (!iface->config.ip.ipv4) {
+		return -ENETUNREACH;
+	}
+
+	/* Take the first address of the network interface */
+	src = &iface->config.ip.ipv4->unicast[0].address.in_addr;
+
+	pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_icmpv4_echo_req)
+					+ data_size,
+					AF_INET, IPPROTO_ICMP,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	if (net_ipv4_create(pkt, src, dst) ||
+	    icmpv4_create(pkt, NET_ICMPV4_ECHO_REQUEST, 0)) {
+		goto drop;
+	}
+
+	echo_req = (struct net_icmpv4_echo_req *)net_pkt_get_data(
+							pkt, &icmpv4_access);
+	if (!echo_req) {
+		goto drop;
+	}
+
+	echo_req->identifier = htons(identifier);
+	echo_req->sequence   = htons(sequence);
+
+	net_pkt_set_data(pkt, &icmpv4_access);
+	net_pkt_write(pkt, data, data_size);
+
+	net_pkt_cursor_init(pkt);
+
+	net_ipv4_finalize(pkt, IPPROTO_ICMP);
+
+	NET_DBG("Sending ICMPv4 Echo Request type %d from %s to %s",
+		NET_ICMPV4_ECHO_REQUEST,
+		log_strdup(net_sprint_ipv4_addr(src)),
+		log_strdup(net_sprint_ipv4_addr(dst)));
+
+	if (net_send_data(pkt) >= 0) {
+		net_stats_update_icmp_sent(iface);
+		return 0;
+	}
+
+	net_stats_update_icmp_drop(iface);
+
+	ret = -EIO;
+
+drop:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+int net_icmpv4_send_error(struct net_pkt *orig, uint8_t type, uint8_t code)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
+	int err = -EIO;
+	struct net_ipv4_hdr *ip_hdr;
+	struct net_pkt *pkt;
+	size_t copy_len;
+
+	net_pkt_cursor_init(orig);
+
+	ip_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(orig, &ipv4_access);
+	if (!ip_hdr) {
+		goto drop_no_pkt;
+	}
+
+	if (ip_hdr->proto == IPPROTO_ICMP) {
+		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv4_access,
+						      struct net_icmp_hdr);
+		struct net_icmp_hdr *icmp_hdr;
+
+		icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(
+							orig, &icmpv4_access);
+		if (!icmp_hdr || icmp_hdr->code < 8) {
+			/* We must not send ICMP errors back */
+			err = -EINVAL;
+			goto drop_no_pkt;
+		}
+	}
+
+	if (ip_hdr->proto == IPPROTO_UDP) {
+		copy_len = sizeof(struct net_ipv4_hdr) +
+			sizeof(struct net_udp_hdr);
+	} else if (ip_hdr->proto == IPPROTO_TCP) {
+		copy_len = sizeof(struct net_ipv4_hdr) +
+			sizeof(struct net_tcp_hdr);
+	} else {
+		copy_len = 0;
+	}
+
+	pkt = net_pkt_alloc_with_buffer(net_pkt_iface(orig),
+					copy_len + NET_ICMPV4_UNUSED_LEN,
+					AF_INET, IPPROTO_ICMP,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		err =  -ENOMEM;
+		goto drop_no_pkt;
+	}
+
+	if (net_ipv4_create(pkt, &ip_hdr->dst, &ip_hdr->src) ||
+	    icmpv4_create(pkt, type, code) ||
+	    net_pkt_memset(pkt, 0, NET_ICMPV4_UNUSED_LEN) ||
+	    net_pkt_copy(pkt, orig, copy_len)) {
+		goto drop;
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_ipv4_finalize(pkt, IPPROTO_ICMP);
+
+	net_pkt_lladdr_dst(pkt)->addr = net_pkt_lladdr_src(orig)->addr;
+	net_pkt_lladdr_dst(pkt)->len = net_pkt_lladdr_src(orig)->len;
+
+	NET_DBG("Sending ICMPv4 Error Message type %d code %d from %s to %s",
+		type, code,
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->src)),
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->dst)));
+
+	if (net_send_data(pkt) >= 0) {
+		net_stats_update_icmp_sent(net_pkt_iface(orig));
+		return 0;
+	}
+
+drop:
+	net_pkt_unref(pkt);
+
+drop_no_pkt:
+	net_stats_update_icmp_drop(net_pkt_iface(orig));
+
+	return err;
+
+}
+
+void net_icmpv4_register_handler(struct net_icmpv4_handler *handler)
+{
+	sys_slist_prepend(&handlers, &handler->node);
+}
+
+void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler)
+{
+	sys_slist_find_and_remove(&handlers, &handler->node);
+}
+
+enum net_verdict net_icmpv4_input(struct net_pkt *pkt,
+				  struct net_ipv4_hdr *ip_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+	struct net_icmpv4_handler *cb;
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
+	if (!icmp_hdr) {
+		NET_DBG("DROP: NULL ICMPv4 header");
+		return NET_DROP;
+	}
+
+	if (net_calc_chksum_icmpv4(pkt) != 0U) {
+		NET_DBG("DROP: Invalid checksum");
+		goto drop;
+	}
+
+	if (net_ipv4_is_addr_bcast(net_pkt_iface(pkt), &ip_hdr->dst) &&
+	    (!IS_ENABLED(CONFIG_NET_ICMPV4_ACCEPT_BROADCAST) ||
+	     icmp_hdr->type != NET_ICMPV4_ECHO_REQUEST)) {
+		NET_DBG("DROP: broadcast pkt");
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &icmp_access);
+
+	NET_DBG("ICMPv4 packet received type %d code %d",
+		icmp_hdr->type, icmp_hdr->code);
+
+	net_stats_update_icmp_recv(net_pkt_iface(pkt));
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) {
+		if (cb->type == icmp_hdr->type &&
+		    (cb->code == icmp_hdr->code || cb->code == 0U)) {
+			return cb->handler(pkt, ip_hdr, icmp_hdr);
+		}
+	}
+
+drop:
+	net_stats_update_icmp_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+static struct net_icmpv4_handler echo_request_handler = {
+	.type = NET_ICMPV4_ECHO_REQUEST,
+	.code = 0,
+	.handler = icmpv4_handle_echo_request,
+};
+
+void net_icmpv4_init(void)
+{
+	net_icmpv4_register_handler(&echo_request_handler);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.h	(working copy)
@@ -0,0 +1,229 @@
+/** @file
+ @brief ICMPv6 handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ICMPV6_H
+#define __ICMPV6_H
+
+#include <sys/slist.h>
+#include <zephyr/types.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+
+struct net_icmpv6_ns_hdr {
+	uint32_t reserved;
+	struct in6_addr tgt;
+} __packed;
+
+struct net_icmpv6_nd_opt_hdr {
+	uint8_t type;
+	uint8_t len;
+} __packed;
+
+struct net_icmpv6_na_hdr {
+	uint8_t flags;
+	uint8_t reserved[3];
+	struct in6_addr tgt;
+} __packed;
+
+struct net_icmpv6_rs_hdr {
+	uint32_t reserved;
+} __packed;
+
+struct net_icmpv6_ra_hdr {
+	uint8_t cur_hop_limit;
+	uint8_t flags;
+	uint16_t router_lifetime;
+	uint32_t reachable_time;
+	uint32_t retrans_timer;
+} __packed;
+
+struct net_icmpv6_nd_opt_mtu {
+	uint16_t reserved;
+	uint32_t mtu;
+} __packed;
+
+struct net_icmpv6_nd_opt_prefix_info {
+	uint8_t prefix_len;
+	uint8_t flags;
+	uint32_t valid_lifetime;
+	uint32_t preferred_lifetime;
+	uint32_t reserved;
+	struct in6_addr prefix;
+} __packed;
+
+struct net_icmpv6_nd_opt_6co {
+	uint8_t context_len;
+	uint8_t flag; /*res:3,c:1,cid:4 */
+	uint16_t reserved;
+	uint16_t lifetime;
+	struct in6_addr prefix;
+} __packed;
+
+struct net_icmpv6_echo_req {
+	uint16_t identifier;
+	uint16_t sequence;
+} __packed;
+
+struct net_icmpv6_mld_query {
+	uint16_t max_response_code;
+	uint16_t reserved;
+	struct in6_addr mcast_address;
+	uint16_t flagg; /*S, QRV & QQIC */
+	uint16_t num_sources;
+} __packed;
+
+struct net_icmpv6_mld_mcast_record {
+	uint8_t record_type;
+	uint8_t aux_data_len;
+	uint16_t num_sources;
+	struct in6_addr mcast_address;
+} __packed;
+
+
+#define NET_ICMPV6_ND_O_FLAG(flag) ((flag) & 0x40)
+#define NET_ICMPV6_ND_M_FLAG(flag) ((flag) & 0x80)
+
+#define NET_ICMPV6_ND_OPT_SLLAO       1
+#define NET_ICMPV6_ND_OPT_TLLAO       2
+#define NET_ICMPV6_ND_OPT_PREFIX_INFO 3
+#define NET_ICMPV6_ND_OPT_MTU         5
+#define NET_ICMPV6_ND_OPT_ROUTE       24
+#define NET_ICMPV6_ND_OPT_RDNSS       25
+#define NET_ICMPV6_ND_OPT_DNSSL       31
+#define NET_ICMPV6_ND_OPT_6CO         34
+
+#define NET_ICMPV6_OPT_TYPE_OFFSET   0
+#define NET_ICMPV6_OPT_LEN_OFFSET    1
+#define NET_ICMPV6_OPT_DATA_OFFSET   2
+
+#define NET_ICMPV6_NA_FLAG_ROUTER     0x80
+#define NET_ICMPV6_NA_FLAG_SOLICITED  0x40
+#define NET_ICMPV6_NA_FLAG_OVERRIDE   0x20
+#define NET_ICMPV6_RA_FLAG_ONLINK     0x80
+#define NET_ICMPV6_RA_FLAG_AUTONOMOUS 0x40
+
+#define NET_ICMPV6_DST_UNREACH    1	/* Destination unreachable */
+#define NET_ICMPV6_PACKET_TOO_BIG 2	/* Packet too big */
+#define NET_ICMPV6_TIME_EXCEEDED  3	/* Time exceeded */
+#define NET_ICMPV6_PARAM_PROBLEM  4	/* IPv6 header is bad */
+#define NET_ICMPV6_ECHO_REQUEST 128
+#define NET_ICMPV6_ECHO_REPLY   129
+#define NET_ICMPV6_MLD_QUERY    130	/* Multicast Listener Query */
+#define NET_ICMPV6_RS           133	/* Router Solicitation */
+#define NET_ICMPV6_RA           134	/* Router Advertisement */
+#define NET_ICMPV6_NS           135	/* Neighbor Solicitation */
+#define NET_ICMPV6_NA           136	/* Neighbor Advertisement */
+#define NET_ICMPV6_MLDv2        143	/* Multicast Listener Report v2 */
+
+/* Codes for ICMPv6 Destination Unreachable message */
+#define NET_ICMPV6_DST_UNREACH_NO_ROUTE  0 /* No route to destination */
+#define NET_ICMPV6_DST_UNREACH_ADMIN     1 /* Admin prohibited communication */
+#define NET_ICMPV6_DST_UNREACH_SCOPE     2 /* Beoynd scope of source address */
+#define NET_ICMPV6_DST_UNREACH_NO_ADDR   3 /* Address unrechable */
+#define NET_ICMPV6_DST_UNREACH_NO_PORT   4 /* Port unreachable */
+#define NET_ICMPV6_DST_UNREACH_SRC_ADDR  5 /* Source address failed */
+#define NET_ICMPV6_DST_UNREACH_REJ_ROUTE 6 /* Reject route to destination */
+
+/* Codes for ICMPv6 Parameter Problem message */
+#define NET_ICMPV6_PARAM_PROB_HEADER     0 /* Erroneous header field */
+#define NET_ICMPV6_PARAM_PROB_NEXTHEADER 1 /* Unrecognized next header */
+#define NET_ICMPV6_PARAM_PROB_OPTION     2 /* Unrecognized option */
+
+/* ICMPv6 header has 4 unused bytes that must be zero, RFC 4443 ch 3.1 */
+#define NET_ICMPV6_UNUSED_LEN 4
+
+typedef enum net_verdict (*icmpv6_callback_handler_t)(
+						struct net_pkt *pkt,
+						struct net_ipv6_hdr *ip_hdr,
+						struct net_icmp_hdr *icmp_hdr);
+
+const char *net_icmpv6_type2str(int icmpv6_type);
+
+struct net_icmpv6_handler {
+	sys_snode_t node;
+	icmpv6_callback_handler_t handler;
+	uint8_t type;
+	uint8_t code;
+};
+
+/**
+ * @brief Send ICMPv6 error message.
+ * @param pkt Network packet that this error is related to.
+ * @param type Type of the error message.
+ * @param code Code of the type of the error message.
+ * @param param Optional parameter value for this error. Depending on type
+ * and code this gives extra information to the recipient. Set 0 if unsure
+ * what value to use.
+ * @return Return 0 if the sending succeed, <0 otherwise.
+ */
+int net_icmpv6_send_error(struct net_pkt *pkt, uint8_t type, uint8_t code,
+			  uint32_t param);
+
+/**
+ * @brief Send ICMPv6 echo request message.
+ *
+ * @param iface Network interface.
+ * @param dst IPv6 address of the target host.
+ * @param identifier An identifier to aid in matching Echo Replies
+ * to this Echo Request. May be zero.
+ * @param sequence A sequence number to aid in matching Echo Replies
+ * to this Echo Request. May be zero.
+ * @param data Arbitrary payload data that will be included in the
+ * Echo Reply verbatim. May be zero.
+ * @param data_size Size of the Payload Data in bytes. May be zero.
+ *
+ * @return Return 0 if the sending succeed, <0 otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+int net_icmpv6_send_echo_request(struct net_if *iface,
+				 struct in6_addr *dst,
+				 uint16_t identifier,
+				 uint16_t sequence,
+				 const void *data,
+				 size_t data_size);
+#else
+static inline int net_icmpv6_send_echo_request(struct net_if *iface,
+					       struct in6_addr *dst,
+					       uint16_t identifier,
+					       uint16_t sequence,
+					       const void *data,
+					       size_t data_size)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(dst);
+	ARG_UNUSED(identifier);
+	ARG_UNUSED(sequence);
+	ARG_UNUSED(data);
+	ARG_UNUSED(data_size);
+
+	return -ENOTSUP;
+}
+#endif
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+void net_icmpv6_register_handler(struct net_icmpv6_handler *handler);
+void net_icmpv6_unregister_handler(struct net_icmpv6_handler *handler);
+enum net_verdict net_icmpv6_input(struct net_pkt *pkt,
+				  struct net_ipv6_hdr *ip_hdr);
+
+int net_icmpv6_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code);
+int net_icmpv6_finalize(struct net_pkt *pkt);
+
+void net_icmpv6_init(void);
+#else
+#define net_icmpv6_init(...)
+#define net_icmpv6_register_handler(...)
+#define net_icmpv6_unregister_handler(...)
+#endif
+
+#endif /* __ICMPV6_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/icmpv6.c	(working copy)
@@ -0,0 +1,410 @@
+/** @file
+ * @brief ICMPv6 related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_icmpv6, CONFIG_NET_ICMPV6_LOG_LEVEL);
+
+#include <errno.h>
+#include <sys/slist.h>
+#include <sys/byteorder.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include "net_private.h"
+#include "icmpv6.h"
+#include "ipv6.h"
+#include "net_stats.h"
+
+#define PKT_WAIT_TIME K_SECONDS(1)
+
+static sys_slist_t handlers;
+
+const char *net_icmpv6_type2str(int icmpv6_type)
+{
+	switch (icmpv6_type) {
+	case NET_ICMPV6_DST_UNREACH:
+		return "Destination Unreachable";
+	case NET_ICMPV6_PACKET_TOO_BIG:
+		return "Packet Too Big";
+	case NET_ICMPV6_TIME_EXCEEDED:
+		return "Time Exceeded";
+	case NET_ICMPV6_PARAM_PROBLEM:
+		return "IPv6 Bad Header";
+	case NET_ICMPV6_ECHO_REQUEST:
+		return "Echo Request";
+	case NET_ICMPV6_ECHO_REPLY:
+		return "Echo Reply";
+	case NET_ICMPV6_MLD_QUERY:
+		return "Multicast Listener Query";
+	case NET_ICMPV6_RS:
+		return "Router Solicitation";
+	case NET_ICMPV6_RA:
+		return "Router Advertisement";
+	case NET_ICMPV6_NS:
+		return "Neighbor Solicitation";
+	case NET_ICMPV6_NA:
+		return "Neighbor Advertisement";
+	case NET_ICMPV6_MLDv2:
+		return "Multicast Listener Report v2";
+	}
+
+	return "?";
+}
+
+void net_icmpv6_register_handler(struct net_icmpv6_handler *handler)
+{
+	sys_slist_prepend(&handlers, &handler->node);
+}
+
+void net_icmpv6_unregister_handler(struct net_icmpv6_handler *handler)
+{
+	sys_slist_find_and_remove(&handlers, &handler->node);
+}
+
+int net_icmpv6_finalize(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
+	if (!icmp_hdr) {
+		return -ENOBUFS;
+	}
+
+	icmp_hdr->chksum = net_calc_chksum_icmpv6(pkt);
+
+	return net_pkt_set_data(pkt, &icmp_access);
+}
+
+int net_icmpv6_create(struct net_pkt *pkt, uint8_t icmp_type, uint8_t icmp_code)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
+	if (!icmp_hdr) {
+		return -ENOBUFS;
+	}
+
+	icmp_hdr->type   = icmp_type;
+	icmp_hdr->code   = icmp_code;
+	icmp_hdr->chksum = 0U;
+
+	return net_pkt_set_data(pkt, &icmp_access);
+}
+
+static
+enum net_verdict icmpv6_handle_echo_request(struct net_pkt *pkt,
+					    struct net_ipv6_hdr *ip_hdr,
+					    struct net_icmp_hdr *icmp_hdr)
+{
+	struct net_pkt *reply = NULL;
+	const struct in6_addr *src;
+	int16_t payload_len;
+
+	ARG_UNUSED(icmp_hdr);
+
+	NET_DBG("Received Echo Request from %s to %s",
+		log_strdup(net_sprint_ipv6_addr(&ip_hdr->src)),
+		log_strdup(net_sprint_ipv6_addr(&ip_hdr->dst)));
+
+	payload_len = ntohs(ip_hdr->len) -
+		net_pkt_ipv6_ext_len(pkt) - NET_ICMPH_LEN;
+	if (payload_len < NET_ICMPV6_UNUSED_LEN) {
+		/* No identifier or sequence number present */
+		goto drop;
+	}
+
+	reply = net_pkt_alloc_with_buffer(net_pkt_iface(pkt), payload_len,
+					  AF_INET6, IPPROTO_ICMPV6,
+					  PKT_WAIT_TIME);
+	if (!reply) {
+		NET_DBG("DROP: No buffer");
+		goto drop;
+	}
+
+	if (net_ipv6_is_addr_mcast(&ip_hdr->dst)) {
+		src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
+						  &ip_hdr->dst);
+	} else {
+		src = &ip_hdr->dst;
+	}
+
+	/* We must not set the destination ll address here but trust
+	 * that it is set properly using a value from neighbor cache.
+	 * Same for source as it points to original pkt ll src address.
+	 */
+	net_pkt_lladdr_dst(reply)->addr = NULL;
+	net_pkt_lladdr_src(reply)->addr = NULL;
+
+	if (net_ipv6_create(reply, src, &ip_hdr->src)) {
+		NET_DBG("DROP: wrong buffer");
+		goto drop;
+	}
+
+	if (net_icmpv6_create(reply, NET_ICMPV6_ECHO_REPLY, 0) ||
+	    net_pkt_copy(reply, pkt, payload_len)) {
+		NET_DBG("DROP: wrong buffer");
+		goto drop;
+	}
+
+	net_pkt_cursor_init(reply);
+	net_ipv6_finalize(reply, IPPROTO_ICMPV6);
+
+	NET_DBG("Sending Echo Reply from %s to %s",
+		log_strdup(net_sprint_ipv6_addr(src)),
+		log_strdup(net_sprint_ipv6_addr(&ip_hdr->src)));
+
+	if (net_send_data(reply) < 0) {
+		goto drop;
+	}
+
+	net_stats_update_icmp_sent(net_pkt_iface(reply));
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+
+drop:
+	if (reply) {
+		net_pkt_unref(reply);
+	}
+
+	net_stats_update_icmp_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+int net_icmpv6_send_error(struct net_pkt *orig, uint8_t type, uint8_t code,
+			  uint32_t param)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	int err = -EIO;
+	struct net_ipv6_hdr *ip_hdr;
+	const struct in6_addr *src;
+	struct net_pkt *pkt;
+	size_t copy_len;
+
+	net_pkt_cursor_init(orig);
+
+	ip_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(orig, &ipv6_access);
+	if (!ip_hdr) {
+		goto drop_no_pkt;
+	}
+
+	if (ip_hdr->nexthdr == IPPROTO_ICMPV6) {
+		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv6_access,
+						      struct net_icmp_hdr);
+		struct net_icmp_hdr *icmp_hdr;
+
+		net_pkt_acknowledge_data(orig, &ipv6_access);
+
+		icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(
+							orig, &icmpv6_access);
+		if (!icmp_hdr || icmp_hdr->code < 128) {
+			/* We must not send ICMP errors back */
+			err = -EINVAL;
+			goto drop_no_pkt;
+		}
+
+		net_pkt_cursor_init(orig);
+	}
+
+	if (ip_hdr->nexthdr == IPPROTO_UDP) {
+		copy_len = sizeof(struct net_ipv6_hdr) +
+			sizeof(struct net_udp_hdr);
+	} else if (ip_hdr->nexthdr == IPPROTO_TCP) {
+		copy_len = sizeof(struct net_ipv6_hdr) +
+			sizeof(struct net_tcp_hdr);
+	} else {
+		copy_len = net_pkt_get_len(orig);
+	}
+
+	pkt = net_pkt_alloc_with_buffer(net_pkt_iface(orig),
+					copy_len + NET_ICMPV6_UNUSED_LEN,
+					AF_INET6, IPPROTO_ICMPV6,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		err = -ENOMEM;
+		goto drop_no_pkt;
+	}
+
+	if (net_ipv6_is_addr_mcast(&ip_hdr->dst)) {
+		src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
+						  &ip_hdr->dst);
+	} else {
+		src = &ip_hdr->dst;
+	}
+
+	if (net_ipv6_create(pkt, src, &ip_hdr->src) ||
+	    net_icmpv6_create(pkt, type, code)) {
+		goto drop;
+	}
+
+	/* Depending on error option, we store the param into the ICMP message.
+	 */
+	if (type == NET_ICMPV6_PARAM_PROBLEM) {
+		err = net_pkt_write_be32(pkt, param);
+	} else {
+		err = net_pkt_memset(pkt, 0, NET_ICMPV6_UNUSED_LEN);
+	}
+
+	/* Allocator might not have been able to allocate all requested space,
+	 * so let's copy as much as we can.
+	 */
+	copy_len = net_pkt_available_buffer(pkt);
+
+	if (err || net_pkt_copy(pkt, orig, copy_len)) {
+		goto drop;
+	}
+
+	net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_dst(orig)->addr;
+	net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_dst(orig)->len;
+	net_pkt_lladdr_dst(pkt)->addr = net_pkt_lladdr_src(orig)->addr;
+	net_pkt_lladdr_dst(pkt)->len = net_pkt_lladdr_src(orig)->len;
+
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	NET_DBG("Sending ICMPv6 Error Message type %d code %d param %d"
+		" from %s to %s", type, code, param,
+		log_strdup(net_sprint_ipv6_addr(src)),
+		log_strdup(net_sprint_ipv6_addr(&ip_hdr->src)));
+
+	if (net_send_data(pkt) >= 0) {
+		net_stats_update_icmp_sent(net_pkt_iface(pkt));
+		return 0;
+	}
+
+drop:
+	net_pkt_unref(pkt);
+
+drop_no_pkt:
+	net_stats_update_icmp_drop(net_pkt_iface(orig));
+
+	return err;
+}
+
+int net_icmpv6_send_echo_request(struct net_if *iface,
+				 struct in6_addr *dst,
+				 uint16_t identifier,
+				 uint16_t sequence,
+				 const void *data,
+				 size_t data_size)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmpv6_access,
+					      struct net_icmpv6_echo_req);
+	int ret = -ENOBUFS;
+	struct net_icmpv6_echo_req *echo_req;
+	const struct in6_addr *src;
+	struct net_pkt *pkt;
+
+	src = net_if_ipv6_select_src_addr(iface, dst);
+
+	pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_icmpv6_echo_req)
+					+ data_size,
+					AF_INET6, IPPROTO_ICMPV6,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	if (net_ipv6_create(pkt, src, dst) ||
+	    net_icmpv6_create(pkt, NET_ICMPV6_ECHO_REQUEST, 0)) {
+		goto drop;
+	}
+
+	echo_req = (struct net_icmpv6_echo_req *)net_pkt_get_data(
+							pkt, &icmpv6_access);
+	if (!echo_req) {
+		goto drop;
+	}
+
+	echo_req->identifier = htons(identifier);
+	echo_req->sequence   = htons(sequence);
+
+	net_pkt_set_data(pkt, &icmpv6_access);
+	net_pkt_write(pkt, data, data_size);
+
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	NET_DBG("Sending ICMPv6 Echo Request type %d from %s to %s",
+		NET_ICMPV6_ECHO_REQUEST,
+		log_strdup(net_sprint_ipv6_addr(src)),
+		log_strdup(net_sprint_ipv6_addr(dst)));
+
+	if (net_send_data(pkt) >= 0) {
+		net_stats_update_icmp_sent(iface);
+		return 0;
+	}
+
+	net_stats_update_icmp_drop(iface);
+
+	ret = -EIO;
+
+drop:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+enum net_verdict net_icmpv6_input(struct net_pkt *pkt,
+				  struct net_ipv6_hdr *ip_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmp_hdr);
+	struct net_icmp_hdr *icmp_hdr;
+	struct net_icmpv6_handler *cb;
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
+	if (!icmp_hdr) {
+		NET_DBG("DROP: NULL ICMPv6 header");
+		return NET_DROP;
+	}
+
+	if (net_calc_chksum_icmpv6(pkt) != 0U) {
+		NET_DBG("DROP: invalid checksum");
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &icmp_access);
+
+	NET_DBG("ICMPv6 %s received type %d code %d",
+		net_icmpv6_type2str(icmp_hdr->type),
+		icmp_hdr->type, icmp_hdr->code);
+
+	net_stats_update_icmp_recv(net_pkt_iface(pkt));
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) {
+		if (cb->type == icmp_hdr->type &&
+		    (cb->code == icmp_hdr->code || cb->code == 0U)) {
+			return cb->handler(pkt, ip_hdr, icmp_hdr);
+		}
+	}
+drop:
+	net_stats_update_icmp_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+static struct net_icmpv6_handler echo_request_handler = {
+	.type = NET_ICMPV6_ECHO_REQUEST,
+	.code = 0,
+	.handler = icmpv6_handle_echo_request,
+};
+
+void net_icmpv6_init(void)
+{
+	net_icmpv6_register_handler(&echo_request_handler);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.h	(working copy)
@@ -0,0 +1,135 @@
+/** @file
+ @brief IPv4 related functions
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __IPV4_H
+#define __IPV4_H
+
+#include <zephyr/types.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_context.h>
+
+#define NET_IPV4_IHL_MASK 0x0F
+
+/* IPv4 Options */
+#define NET_IPV4_OPTS_EO   0   /* End of Options */
+#define NET_IPV4_OPTS_NOP  1   /* No operation */
+#define NET_IPV4_OPTS_RR   7   /* Record Route */
+#define NET_IPV4_OPTS_TS   68  /* Timestamp */
+
+/* IPv4 Options Timestamp flags */
+#define NET_IPV4_TS_OPT_TS_ONLY	0 /* Timestamp only */
+#define NET_IPV4_TS_OPT_TS_ADDR	1 /* Timestamp and address */
+#define NET_IPV4_TS_OPT_TS_PRES	3 /* Timestamp prespecified hops*/
+
+#define NET_IPV4_HDR_OPTNS_MAX_LEN 40
+
+/**
+ * @brief Create IPv4 packet in provided net_pkt.
+ *
+ * @param pkt Network packet
+ * @param src Source IPv4 address
+ * @param dst Destination IPv4 address
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+int net_ipv4_create(struct net_pkt *pkt,
+		    const struct in_addr *src,
+		    const struct in_addr *dst);
+#else
+static inline int net_ipv4_create(struct net_pkt *pkt,
+				  const struct in_addr *src,
+				  const struct in_addr *dst)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(src);
+	ARG_UNUSED(dst);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Finalize IPv4 packet. It should be called right before
+ * sending the packet and after all the data has been added into
+ * the packet. This function will set the length of the
+ * packet and calculate the higher protocol checksum if needed.
+ *
+ * @param pkt Network packet
+ * @param next_header_proto Protocol type of the next header after IPv4 header.
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV4)
+int net_ipv4_finalize(struct net_pkt *pkt, uint8_t next_header_proto);
+#else
+static inline int net_ipv4_finalize(struct net_pkt *pkt,
+				    uint8_t next_header_proto)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(next_header_proto);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @typedef net_ipv4_parse_hdr_options_cb_t
+ * @brief IPv4 header options handle callback
+ *
+ * @details The callback is called when parser encounter
+ * supported options.
+ *
+ * @param opt_type Option type
+ * @param opt_data Option data
+ * @param opt_len Option length
+ * @param user_data Userdata given in net_ipv4_parse_hdr_options()
+ *
+ * @return 0 on success, negative otherwise.
+ */
+typedef int (*net_ipv4_parse_hdr_options_cb_t)(uint8_t opt_type,
+					       uint8_t *opt_data,
+					       uint8_t opt_len,
+					       void *user_data);
+
+/**
+ * @brief Parse IPv4 header options.
+ * Parse the IPv4 header options and call the callback with
+ * options type, data and length along with user_data.
+ *
+ * @param pkt Network packet
+ * @param cb callback to handle IPv4 header options
+ * @param user_data User data
+ *
+ * @return 0 on success, negative otherwise.
+ */
+#if defined(CONFIG_NET_IPV4_HDR_OPTIONS)
+int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
+			       net_ipv4_parse_hdr_options_cb_t cb,
+			       void *user_data);
+#else
+static inline int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
+					     net_ipv4_parse_hdr_options_cb_t cb,
+					     void *user_data)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+
+	return -ENOTSUP;
+}
+#endif
+
+#endif /* __IPV4_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4.c	(working copy)
@@ -0,0 +1,331 @@
+/** @file
+ * @brief IPv4 related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ipv4, CONFIG_NET_IPV4_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_context.h>
+#include "net_private.h"
+#include "connection.h"
+#include "net_stats.h"
+#include "icmpv4.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv4.h"
+
+/* Timeout for various buffer allocations in this file. */
+#define NET_BUF_TIMEOUT K_MSEC(50)
+
+int net_ipv4_create(struct net_pkt *pkt,
+		    const struct in_addr *src,
+		    const struct in_addr *dst)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
+	struct net_ipv4_hdr *ipv4_hdr;
+
+	ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);
+	if (!ipv4_hdr) {
+		return -ENOBUFS;
+	}
+
+	ipv4_hdr->vhl       = 0x45;
+	ipv4_hdr->tos       = 0x00;
+	ipv4_hdr->len       = 0U;
+	ipv4_hdr->id[0]     = 0U;
+	ipv4_hdr->id[1]     = 0U;
+	ipv4_hdr->offset[0] = 0U;
+	ipv4_hdr->offset[1] = 0U;
+
+	ipv4_hdr->ttl       = net_pkt_ipv4_ttl(pkt);
+	if (ipv4_hdr->ttl == 0U) {
+		ipv4_hdr->ttl = net_if_ipv4_get_ttl(net_pkt_iface(pkt));
+	}
+
+	ipv4_hdr->proto     = 0U;
+	ipv4_hdr->chksum    = 0U;
+
+	net_ipaddr_copy(&ipv4_hdr->dst, dst);
+	net_ipaddr_copy(&ipv4_hdr->src, src);
+
+	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
+
+	return net_pkt_set_data(pkt, &ipv4_access);
+}
+
+int net_ipv4_finalize(struct net_pkt *pkt, uint8_t next_header_proto)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
+	struct net_ipv4_hdr *ipv4_hdr;
+
+	net_pkt_set_overwrite(pkt, true);
+
+	ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);
+	if (!ipv4_hdr) {
+		return -ENOBUFS;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4_HDR_OPTIONS)) {
+		if (net_pkt_ipv4_opts_len(pkt)) {
+			ipv4_hdr->vhl = 0x40 | (0x0F &
+					((net_pkt_ip_hdr_len(pkt) +
+					  net_pkt_ipv4_opts_len(pkt)) / 4U));
+		}
+	}
+
+	ipv4_hdr->len   = htons(net_pkt_get_len(pkt));
+	ipv4_hdr->proto = next_header_proto;
+
+	if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) {
+		ipv4_hdr->chksum = net_calc_chksum_ipv4(pkt);
+	}
+
+	net_pkt_set_data(pkt, &ipv4_access);
+
+	if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    next_header_proto == IPPROTO_UDP) {
+		return net_udp_finalize(pkt);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   next_header_proto == IPPROTO_TCP) {
+		return net_tcp_finalize(pkt);
+	} else if (next_header_proto == IPPROTO_ICMP) {
+		return net_icmpv4_finalize(pkt);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_IPV4_HDR_OPTIONS)
+int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
+			       net_ipv4_parse_hdr_options_cb_t cb,
+			       void *user_data)
+{
+	struct net_pkt_cursor cur;
+	uint8_t opt_data[NET_IPV4_HDR_OPTNS_MAX_LEN];
+	uint8_t total_opts_len;
+
+	if (!cb) {
+		return -EINVAL;
+	}
+
+	net_pkt_cursor_backup(pkt, &cur);
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, sizeof(struct net_ipv4_hdr))) {
+		return -EINVAL;
+	}
+
+	total_opts_len = net_pkt_ipv4_opts_len(pkt);
+
+	while (total_opts_len) {
+		uint8_t opt_len = 0U;
+		uint8_t opt_type;
+
+		if (net_pkt_read_u8(pkt, &opt_type)) {
+			return -EINVAL;
+		}
+
+		total_opts_len--;
+
+		if (!(opt_type == NET_IPV4_OPTS_EO ||
+		      opt_type == NET_IPV4_OPTS_NOP)) {
+			if (net_pkt_read_u8(pkt, &opt_len)) {
+				return -EINVAL;
+			}
+
+			if (opt_len < 2U || total_opts_len < 1U) {
+				return -EINVAL;
+			}
+
+			opt_len -= 2U;
+			total_opts_len--;
+		}
+
+		if (opt_len > total_opts_len) {
+			return -EINVAL;
+		}
+
+		switch (opt_type) {
+		case NET_IPV4_OPTS_NOP:
+			break;
+
+		case NET_IPV4_OPTS_EO:
+			/* Options length should be zero, when cursor reachs to
+			 * End of options.
+			 */
+			if (total_opts_len) {
+				return -EINVAL;
+			}
+
+			break;
+		case NET_IPV4_OPTS_RR:
+		case NET_IPV4_OPTS_TS:
+			if (net_pkt_read(pkt, opt_data, opt_len)) {
+				return -EINVAL;
+			}
+
+			if (cb(opt_type, opt_data, opt_len, user_data)) {
+				return -EINVAL;
+			}
+
+			break;
+		default:
+			if (net_pkt_skip(pkt, opt_len)) {
+				return -EINVAL;
+			}
+
+			break;
+		}
+
+		total_opts_len -= opt_len;
+	}
+
+	net_pkt_cursor_restore(pkt, &cur);
+
+	return 0;
+}
+#endif
+
+enum net_verdict net_ipv4_input(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access, struct net_ipv4_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	int real_len = net_pkt_get_len(pkt);
+	enum net_verdict verdict = NET_DROP;
+	union net_proto_header proto_hdr;
+	struct net_ipv4_hdr *hdr;
+	union net_ip_header ip;
+	uint8_t hdr_len;
+	uint8_t opts_len;
+	int pkt_len;
+
+	net_stats_update_ipv4_recv(net_pkt_iface(pkt));
+
+	hdr = (struct net_ipv4_hdr *)net_pkt_get_data(pkt, &ipv4_access);
+	if (!hdr) {
+		NET_DBG("DROP: no buffer");
+		goto drop;
+	}
+
+	hdr_len = (hdr->vhl & NET_IPV4_IHL_MASK) * 4U;
+	if (hdr_len < sizeof(struct net_ipv4_hdr)) {
+		NET_DBG("DROP: Invalid hdr length");
+		goto drop;
+	}
+
+	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
+
+	opts_len = hdr_len - sizeof(struct net_ipv4_hdr);
+	if (opts_len > NET_IPV4_HDR_OPTNS_MAX_LEN) {
+		return -EINVAL;
+	}
+
+	net_pkt_set_ipv4_opts_len(pkt, opts_len);
+
+	pkt_len = ntohs(hdr->len);
+	if (real_len < pkt_len) {
+		NET_DBG("DROP: pkt len per hdr %d != pkt real len %d",
+			pkt_len, real_len);
+		goto drop;
+	} else if (real_len > pkt_len) {
+		net_pkt_update_length(pkt, pkt_len);
+	}
+
+	if (net_ipv4_is_addr_mcast(&hdr->src)) {
+		NET_DBG("DROP: src addr is %s", "mcast");
+		goto drop;
+	}
+
+	if (net_ipv4_is_addr_bcast(net_pkt_iface(pkt), &hdr->src)) {
+		NET_DBG("DROP: src addr is %s", "bcast");
+		goto drop;
+	}
+
+	if (net_ipv4_is_addr_unspecified(&hdr->src)) {
+		NET_DBG("DROP: src addr is %s", "unspecified");
+		goto drop;
+	}
+
+	if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) &&
+	    net_calc_chksum_ipv4(pkt) != 0U) {
+		NET_DBG("DROP: invalid chksum");
+		goto drop;
+	}
+
+	if ((!net_ipv4_is_my_addr(&hdr->dst) &&
+	     !net_ipv4_is_addr_mcast(&hdr->dst) &&
+	     !(hdr->proto == IPPROTO_UDP &&
+	       (net_ipv4_addr_cmp(&hdr->dst, net_ipv4_broadcast_address()) ||
+		/* RFC 1122 ch. 3.3.6 The 0.0.0.0 is non-standard bcast addr */
+		(IS_ENABLED(CONFIG_NET_IPV4_ACCEPT_ZERO_BROADCAST) &&
+		 net_ipv4_addr_cmp(&hdr->dst,
+				   net_ipv4_unspecified_address()))))) ||
+	    (hdr->proto == IPPROTO_TCP &&
+	     net_ipv4_is_addr_bcast(net_pkt_iface(pkt), &hdr->dst))) {
+		NET_DBG("DROP: not for me");
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &ipv4_access);
+
+	if (opts_len) {
+		/* Only few options are handled in EchoRequest, rest skipped */
+		if (net_pkt_skip(pkt, opts_len)) {
+			NET_DBG("Header too big? %u", hdr_len);
+			goto drop;
+		}
+	}
+
+	net_pkt_set_ipv4_ttl(pkt, hdr->ttl);
+
+	net_pkt_set_family(pkt, PF_INET);
+
+	NET_DBG("IPv4 packet received from %s to %s",
+		log_strdup(net_sprint_ipv4_addr(&hdr->src)),
+		log_strdup(net_sprint_ipv4_addr(&hdr->dst)));
+
+	switch (hdr->proto) {
+	case IPPROTO_ICMP:
+		verdict = net_icmpv4_input(pkt, hdr);
+		break;
+	case IPPROTO_TCP:
+		proto_hdr.tcp = net_tcp_input(pkt, &tcp_access);
+		if (proto_hdr.tcp) {
+			verdict = NET_OK;
+		}
+		break;
+	case IPPROTO_UDP:
+		proto_hdr.udp = net_udp_input(pkt, &udp_access);
+		if (proto_hdr.udp) {
+			verdict = NET_OK;
+		}
+		break;
+	}
+
+	if (verdict == NET_DROP) {
+		goto drop;
+	} else if (hdr->proto == IPPROTO_ICMP) {
+		return verdict;
+	}
+
+	ip.ipv4 = hdr;
+
+	verdict = net_conn_input(pkt, &ip, hdr->proto, &proto_hdr);
+	if (verdict != NET_DROP) {
+		return verdict;
+	}
+drop:
+	net_stats_update_ipv4_drop(net_pkt_iface(pkt));
+	return NET_DROP;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf.c	(working copy)
@@ -0,0 +1,386 @@
+/** @file
+ * @brief IPv4 autoconf related functions
+ */
+
+/*
+ * Copyright (c) 2017 Matthias Boesl
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ipv4_autoconf, CONFIG_NET_IPV4_AUTO_LOG_LEVEL);
+
+#include "net_private.h"
+#include <errno.h>
+#include "../l2/ethernet/arp.h"
+#include <net/net_pkt.h>
+#include <net/net_core.h>
+#include <net/net_if.h>
+#include <random/rand32.h>
+
+#include "ipv4_autoconf_internal.h"
+
+/* Have only one timer in order to save memory */
+static struct k_delayed_work ipv4auto_timer;
+
+/* Track currently active timers */
+static sys_slist_t ipv4auto_ifaces;
+
+#define BUF_ALLOC_TIMEOUT K_MSEC(100)
+
+static struct net_pkt *ipv4_autoconf_prepare_arp(struct net_if *iface)
+{
+	struct net_if_config *cfg = net_if_get_config(iface);
+	struct net_pkt *pkt;
+
+	/* We provide AF_UNSPEC to the allocator: this packet does not
+	 * need space for any IPv4 header.
+	 */
+	pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr),
+					AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT);
+	if (!pkt) {
+		return NULL;
+	}
+
+	net_pkt_set_family(pkt, AF_INET);
+	net_pkt_set_ipv4_auto(pkt, true);
+
+	return net_arp_prepare(pkt, &cfg->ipv4auto.requested_ip,
+			       &cfg->ipv4auto.current_ip);
+}
+
+static void ipv4_autoconf_send_probe(struct net_if_ipv4_autoconf *ipv4auto)
+{
+	struct net_pkt *pkt;
+
+	pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface);
+	if (!pkt) {
+		NET_DBG("Failed to prepare probe %p", ipv4auto->iface);
+		return;
+	}
+
+	NET_DBG("Probing pkt %p", pkt);
+
+	if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) {
+		net_pkt_unref(pkt);
+	} else {
+		ipv4auto->probe_cnt++;
+		ipv4auto->state = NET_IPV4_AUTOCONF_PROBE;
+	}
+}
+
+static void ipv4_autoconf_send_announcement(
+	struct net_if_ipv4_autoconf *ipv4auto)
+{
+	struct net_pkt *pkt;
+
+	pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface);
+	if (!pkt) {
+		NET_DBG("Failed to prepare announcement %p", ipv4auto->iface);
+		return;
+	}
+
+	NET_DBG("Announcing pkt %p", pkt);
+
+	if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) {
+		net_pkt_unref(pkt);
+	} else {
+		ipv4auto->announce_cnt++;
+		ipv4auto->state = NET_IPV4_AUTOCONF_ANNOUNCE;
+	}
+}
+
+enum net_verdict net_ipv4_autoconf_input(struct net_if *iface,
+					 struct net_pkt *pkt)
+{
+	struct net_if_config *cfg = net_if_get_config(iface);
+	struct net_arp_hdr *arp_hdr;
+
+	cfg = net_if_get_config(iface);
+	if (!cfg) {
+		NET_DBG("Interface %p configuration missing!", iface);
+		return NET_DROP;
+	}
+
+	if (net_pkt_get_len(pkt) < sizeof(struct net_arp_hdr)) {
+		NET_DBG("Invalid ARP header (len %zu, min %zu bytes)",
+			net_pkt_get_len(pkt), sizeof(struct net_arp_hdr));
+		return NET_DROP;
+	}
+
+	arp_hdr = NET_ARP_HDR(pkt);
+
+	if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr,
+			       &cfg->ipv4auto.requested_ip)) {
+		/* No conflict */
+		return NET_CONTINUE;
+	}
+
+	if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr,
+			       &cfg->ipv4auto.requested_ip)) {
+		/* No need to defend */
+		return NET_CONTINUE;
+	}
+
+	NET_DBG("Conflict detected from %s for %s, state %d",
+		log_strdup(net_sprint_ll_addr((uint8_t *)&arp_hdr->src_hwaddr,
+					      arp_hdr->hwlen)),
+		log_strdup(net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr)),
+		cfg->ipv4auto.state);
+
+	cfg->ipv4auto.conflict_cnt++;
+
+	switch (cfg->ipv4auto.state) {
+	case NET_IPV4_AUTOCONF_PROBE:
+		/* restart probing with renewed IP */
+		net_ipv4_autoconf_start(iface);
+		break;
+	case NET_IPV4_AUTOCONF_ANNOUNCE:
+	case NET_IPV4_AUTOCONF_ASSIGNED:
+		if (cfg->ipv4auto.conflict_cnt == 1U) {
+			/* defend IP */
+			ipv4_autoconf_send_announcement(&cfg->ipv4auto);
+		} else {
+			/* unset host ip */
+			if (!net_if_ipv4_addr_rm(iface,
+						 &cfg->ipv4auto.requested_ip)) {
+				NET_DBG("Failed to remove addr from iface");
+			}
+
+			/* restart probing after second conflict */
+			net_ipv4_autoconf_start(iface);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	return NET_DROP;
+}
+
+static void ipv4_autoconf_send(struct net_if_ipv4_autoconf *ipv4auto)
+{
+	switch (ipv4auto->state) {
+	case NET_IPV4_AUTOCONF_INIT:
+		ipv4auto->probe_cnt = 0U;
+		ipv4auto->announce_cnt = 0U;
+		ipv4auto->conflict_cnt = 0U;
+		(void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr));
+		ipv4auto->requested_ip.s4_addr[0] = 169U;
+		ipv4auto->requested_ip.s4_addr[1] = 254U;
+		ipv4auto->requested_ip.s4_addr[2] = sys_rand32_get() % 254;
+		ipv4auto->requested_ip.s4_addr[3] = sys_rand32_get() % 254;
+
+		NET_DBG("%s: Starting probe for 169.254.%d.%d", "Init",
+			ipv4auto->requested_ip.s4_addr[2],
+			ipv4auto->requested_ip.s4_addr[3]);
+		ipv4_autoconf_send_probe(ipv4auto);
+		break;
+	case NET_IPV4_AUTOCONF_RENEW:
+		ipv4auto->probe_cnt = 0U;
+		ipv4auto->announce_cnt = 0U;
+		ipv4auto->conflict_cnt = 0U;
+		(void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr));
+		NET_DBG("%s: Starting probe for 169.254.%d.%d", "Renew",
+			ipv4auto->requested_ip.s4_addr[2],
+			ipv4auto->requested_ip.s4_addr[3]);
+		ipv4_autoconf_send_probe(ipv4auto);
+		break;
+	case NET_IPV4_AUTOCONF_PROBE:
+		/* schedule next probe */
+		if (ipv4auto->probe_cnt <= (IPV4_AUTOCONF_PROBE_NUM - 1)) {
+			ipv4_autoconf_send_probe(ipv4auto);
+			break;
+		}
+		__fallthrough;
+	case NET_IPV4_AUTOCONF_ANNOUNCE:
+		if (ipv4auto->announce_cnt <=
+		    (IPV4_AUTOCONF_ANNOUNCE_NUM - 1)) {
+			net_ipaddr_copy(&ipv4auto->current_ip,
+					&ipv4auto->requested_ip);
+			ipv4_autoconf_send_announcement(ipv4auto);
+			break;
+		}
+
+		/* success, add new IPv4 address */
+		if (!net_if_ipv4_addr_add(ipv4auto->iface,
+					  &ipv4auto->requested_ip,
+					  NET_ADDR_AUTOCONF, 0)) {
+			NET_DBG("Failed to add IPv4 addr to iface %p",
+				ipv4auto->iface);
+			return;
+		}
+
+		ipv4auto->state = NET_IPV4_AUTOCONF_ASSIGNED;
+		break;
+	default:
+		break;
+	}
+}
+
+static uint32_t ipv4_autoconf_get_timeout(struct net_if_ipv4_autoconf *ipv4auto)
+{
+	switch (ipv4auto->state) {
+	case NET_IPV4_AUTOCONF_PROBE:
+		if (ipv4auto->conflict_cnt >= IPV4_AUTOCONF_MAX_CONFLICTS) {
+			NET_DBG("Rate limiting");
+			return MSEC_PER_SEC * IPV4_AUTOCONF_RATE_LIMIT_INTERVAL;
+
+		} else if (ipv4auto->probe_cnt == IPV4_AUTOCONF_PROBE_NUM) {
+			return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL;
+		}
+
+		return IPV4_AUTOCONF_PROBE_WAIT * MSEC_PER_SEC +
+			(sys_rand32_get() % MSEC_PER_SEC);
+
+	case NET_IPV4_AUTOCONF_ANNOUNCE:
+		return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static void ipv4_autoconf_submit_work(uint32_t timeout)
+{
+	if (!k_delayed_work_remaining_get(&ipv4auto_timer) ||
+	    timeout < k_delayed_work_remaining_get(&ipv4auto_timer)) {
+		k_delayed_work_cancel(&ipv4auto_timer);
+		k_delayed_work_submit(&ipv4auto_timer, K_MSEC(timeout));
+
+		NET_DBG("Next wakeup in %d ms",
+			k_delayed_work_remaining_get(&ipv4auto_timer));
+	}
+}
+
+static bool ipv4_autoconf_check_timeout(int64_t start, uint32_t time, int64_t timeout)
+{
+	start += time;
+	if (start < 0) {
+		start = -start;
+	}
+
+	if (start > timeout) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool ipv4_autoconf_timedout(struct net_if_ipv4_autoconf *ipv4auto,
+				   int64_t timeout)
+{
+	return ipv4_autoconf_check_timeout(ipv4auto->timer_start,
+					   ipv4auto->timer_timeout,
+					   timeout);
+}
+
+static uint32_t ipv4_autoconf_manage_timeouts(
+	struct net_if_ipv4_autoconf *ipv4auto,
+	int64_t timeout)
+{
+	if (ipv4_autoconf_timedout(ipv4auto, timeout)) {
+		ipv4_autoconf_send(ipv4auto);
+	}
+
+	ipv4auto->timer_timeout = ipv4_autoconf_get_timeout(ipv4auto);
+
+	return ipv4auto->timer_timeout;
+}
+
+static void ipv4_autoconf_timeout(struct k_work *work)
+{
+	uint32_t timeout_update = UINT32_MAX - 1;
+	int64_t timeout = k_uptime_get();
+	struct net_if_ipv4_autoconf *current, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ipv4auto_ifaces, current, next,
+					  node) {
+		uint32_t next_timeout;
+
+		next_timeout = ipv4_autoconf_manage_timeouts(current, timeout);
+		if (next_timeout < timeout_update) {
+			timeout_update = next_timeout;
+		}
+	}
+
+	if (timeout_update != UINT32_MAX && timeout_update > 0) {
+		NET_DBG("Waiting for %u ms", timeout_update);
+
+		k_delayed_work_submit(&ipv4auto_timer, K_MSEC(timeout_update));
+	}
+}
+
+static void ipv4_autoconf_start_timer(struct net_if *iface,
+				      struct net_if_ipv4_autoconf *ipv4auto)
+{
+	sys_slist_append(&ipv4auto_ifaces, &ipv4auto->node);
+
+	ipv4auto->timer_start = k_uptime_get();
+	ipv4auto->timer_timeout = MSEC_PER_SEC * IPV4_AUTOCONF_START_DELAY;
+	ipv4auto->iface = iface;
+
+	ipv4_autoconf_submit_work(ipv4auto->timer_timeout);
+}
+
+void net_ipv4_autoconf_start(struct net_if *iface)
+{
+	/* Initialize interface and start probing */
+	struct net_if_config *cfg;
+
+	cfg = net_if_get_config(iface);
+	if (!cfg) {
+		return;
+	}
+
+	/* Remove the existing registration if found */
+	if (cfg->ipv4auto.iface == iface) {
+		net_ipv4_autoconf_reset(iface);
+	}
+
+	NET_DBG("Starting IPv4 autoconf for iface %p", iface);
+
+	if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) {
+		cfg->ipv4auto.state = NET_IPV4_AUTOCONF_RENEW;
+	} else {
+		cfg->ipv4auto.state = NET_IPV4_AUTOCONF_INIT;
+	}
+
+	ipv4_autoconf_start_timer(iface, &cfg->ipv4auto);
+}
+
+void net_ipv4_autoconf_reset(struct net_if *iface)
+{
+	struct net_if_config *cfg;
+
+	cfg = net_if_get_config(iface);
+	if (!cfg) {
+		return;
+	}
+
+	/* Initialize interface and start probing */
+	if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) {
+		net_if_ipv4_addr_rm(iface, &cfg->ipv4auto.current_ip);
+	}
+
+	NET_DBG("Autoconf reset for %p", iface);
+
+	/* Cancel any ongoing probing/announcing attempt*/
+	sys_slist_find_and_remove(&ipv4auto_ifaces, &cfg->ipv4auto.node);
+
+	if (sys_slist_is_empty(&ipv4auto_ifaces)) {
+		k_delayed_work_cancel(&ipv4auto_timer);
+	}
+}
+
+void net_ipv4_autoconf_init(void)
+{
+	k_delayed_work_init(&ipv4auto_timer, ipv4_autoconf_timeout);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv4_autoconf_internal.h	(working copy)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017 Matthias Boesl
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief IPv4 Autoconfiguration
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __IPV4_AUTOCONF_INTERNAL_H
+#define __IPV4_AUTOCONF_INTERNAL_H
+
+#include <zephyr.h>
+
+#include <net/ipv4_autoconf.h>
+
+/* Initial random delay*/
+#define IPV4_AUTOCONF_PROBE_WAIT 1
+
+/* Number of probe packets */
+#define IPV4_AUTOCONF_PROBE_NUM 3
+
+/* Minimum delay till repeated probe */
+#define IPV4_AUTOCONF_PROBE_MIN 1
+
+/* Maximum delay till repeated probe */
+#define IPV4_AUTOCONF_PROBE_MAX 2
+
+/* Number of announcement packets */
+#define IPV4_AUTOCONF_ANNOUNCE_NUM 2
+
+/* Time between announcement packets */
+#define IPV4_AUTOCONF_ANNOUNCE_INTERVAL 2
+
+/* Max conflicts before rate limiting */
+#define IPV4_AUTOCONF_MAX_CONFLICTS 10
+
+/* Delay between successive attempts */
+#define IPV4_AUTOCONF_RATE_LIMIT_INTERVAL 60
+
+/* Minimum interval between defensive ARPs */
+#define IPV4_AUTOCONF_DEFEND_INTERVAL 10
+
+/* Time between carrier up and first probe */
+#define IPV4_AUTOCONF_START_DELAY 3
+
+/**
+ * @brief Start IPv4 autocofiguration RFC 3927: IPv4 Link Local
+ *
+ * @details Start IPv4 IP autoconfiguration
+ *
+ * @param iface A valid pointer on an interface
+ */
+#if defined(CONFIG_NET_IPV4_AUTO)
+void net_ipv4_autoconf_start(struct net_if *iface);
+#else
+#define net_ipv4_autoconf_start(...)
+#endif
+
+/**
+ * @brief Reset autoconf process
+ *
+ * @details Reset IPv4 IP autoconfiguration
+ *
+ * @param iface A valid pointer on an interface
+ */
+#if defined(CONFIG_NET_IPV4_AUTO)
+void net_ipv4_autoconf_reset(struct net_if *iface);
+#else
+#define net_ipv4_autoconf_reset(...)
+#endif
+
+/**
+ * @brief Autoconf ARP input message handler.
+ *
+ * @details Called when ARP message is received when auto is enabled.
+ *
+ * @param iface A valid pointer on an interface
+ * @param pkt Received network packet
+ *
+ * @return What should be done with packet (drop or accept)
+ */
+#if defined(CONFIG_NET_IPV4_AUTO)
+enum net_verdict net_ipv4_autoconf_input(struct net_if *iface,
+					 struct net_pkt *pkt);
+#else
+#define net_ipv4_autoconf_input(...) NET_CONTINUE
+#endif
+
+#endif /* __IPV4_AUTOCONF_INTERNAL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.h	(working copy)
@@ -0,0 +1,486 @@
+/** @file
+ @brief IPv6 data handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __IPV6_H
+#define __IPV6_H
+
+#include <zephyr/types.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_context.h>
+
+#include "icmpv6.h"
+#include "nbr.h"
+
+#define NET_IPV6_ND_HOP_LIMIT 255
+#define NET_IPV6_ND_INFINITE_LIFETIME 0xFFFFFFFF
+
+#define NET_IPV6_DEFAULT_PREFIX_LEN 64
+
+#define NET_MAX_RS_COUNT 3
+
+/**
+ * @brief Bitmaps for IPv6 extension header processing
+ *
+ * When processing extension headers, we record which one we have seen.
+ * This is done as the network packet cannot have twice the same header,
+ * except for destination option.
+ * This information is stored in bitfield variable.
+ * The order of the bitmap is the order recommended in RFC 2460.
+ */
+#define NET_IPV6_EXT_HDR_BITMAP_HBHO   0x01
+#define NET_IPV6_EXT_HDR_BITMAP_DESTO1 0x02
+#define NET_IPV6_EXT_HDR_BITMAP_ROUTING        0x04
+#define NET_IPV6_EXT_HDR_BITMAP_FRAG   0x08
+#define NET_IPV6_EXT_HDR_BITMAP_AH     0x10
+#define NET_IPV6_EXT_HDR_BITMAP_ESP    0x20
+#define NET_IPV6_EXT_HDR_BITMAP_DESTO2 0x40
+
+/**
+ * @brief Destination and Hop By Hop extension headers option types
+ */
+#define NET_IPV6_EXT_HDR_OPT_PAD1  0
+#define NET_IPV6_EXT_HDR_OPT_PADN  1
+#define NET_IPV6_EXT_HDR_OPT_RPL   0x63
+
+/**
+ * @brief Multicast Listener Record v2 record types.
+ */
+#define NET_IPV6_MLDv2_MODE_IS_INCLUDE        1
+#define NET_IPV6_MLDv2_MODE_IS_EXCLUDE        2
+#define NET_IPV6_MLDv2_CHANGE_TO_INCLUDE_MODE 3
+#define NET_IPV6_MLDv2_CHANGE_TO_EXCLUDE_MODE 4
+#define NET_IPV6_MLDv2_ALLOW_NEW_SOURCES      5
+#define NET_IPV6_MLDv2_BLOCK_OLD_SOURCES      6
+
+/* State of the neighbor */
+enum net_ipv6_nbr_state {
+	NET_IPV6_NBR_STATE_INCOMPLETE,
+	NET_IPV6_NBR_STATE_REACHABLE,
+	NET_IPV6_NBR_STATE_STALE,
+	NET_IPV6_NBR_STATE_DELAY,
+	NET_IPV6_NBR_STATE_PROBE,
+	NET_IPV6_NBR_STATE_STATIC,
+};
+
+const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state);
+
+/**
+ * @brief IPv6 neighbor information.
+ */
+struct net_ipv6_nbr_data {
+	/** Any pending packet waiting ND to finish. */
+	struct net_pkt *pending;
+
+	/** IPv6 address. */
+	struct in6_addr addr;
+
+	/** Reachable timer. */
+	int64_t reachable;
+
+	/** Reachable timeout */
+	int32_t reachable_timeout;
+
+	/** Neighbor Solicitation reply timer */
+	int64_t send_ns;
+
+	/** State of the neighbor discovery */
+	enum net_ipv6_nbr_state state;
+
+	/** Link metric for the neighbor */
+	uint16_t link_metric;
+
+	/** How many times we have sent NS */
+	uint8_t ns_count;
+
+	/** Is the neighbor a router */
+	bool is_router;
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) || defined(CONFIG_NET_IPV6_ND)
+	/** Stale counter used to removed oldest nbr in STALE state,
+	 *  when table is full.
+	 */
+	uint32_t stale_counter;
+#endif
+};
+
+static inline struct net_ipv6_nbr_data *net_ipv6_nbr_data(struct net_nbr *nbr)
+{
+	return (struct net_ipv6_nbr_data *)nbr->data;
+}
+
+#if defined(CONFIG_NET_IPV6_DAD)
+int net_ipv6_start_dad(struct net_if *iface, struct net_if_addr *ifaddr);
+#endif
+
+int net_ipv6_send_ns(struct net_if *iface, struct net_pkt *pending,
+		     const struct in6_addr *src, const struct in6_addr *dst,
+		     const struct in6_addr *tgt, bool is_my_address);
+
+int net_ipv6_send_rs(struct net_if *iface);
+int net_ipv6_start_rs(struct net_if *iface);
+
+int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src,
+		     const struct in6_addr *dst, const struct in6_addr *tgt,
+		     uint8_t flags);
+
+
+static inline bool net_ipv6_is_nexthdr_upper_layer(uint8_t nexthdr)
+{
+	return (nexthdr == IPPROTO_ICMPV6 || nexthdr == IPPROTO_UDP ||
+		nexthdr == IPPROTO_TCP);
+}
+
+/**
+ * @brief Create IPv6 packet in provided net_pkt.
+ *
+ * @param pkt Network packet
+ * @param src Source IPv6 address
+ * @param dst Destination IPv6 address
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+int net_ipv6_create(struct net_pkt *pkt,
+		    const struct in6_addr *src,
+		    const struct in6_addr *dst);
+#else
+static inline int net_ipv6_create(struct net_pkt *pkt,
+				  const struct in6_addr *src,
+				  const struct in6_addr *dst)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(src);
+	ARG_UNUSED(dst);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Finalize IPv6 packet. It should be called right before
+ * sending the packet and after all the data has been added into
+ * the packet. This function will set the length of the
+ * packet and calculate the higher protocol checksum if needed.
+ *
+ * @param pkt Network packet
+ * @param next_header_proto Protocol type of the next header after IPv6 header.
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_IPV6)
+int net_ipv6_finalize(struct net_pkt *pkt, uint8_t next_header_proto);
+#else
+static inline int net_ipv6_finalize(struct net_pkt *pkt,
+				    uint8_t next_header_proto)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(next_header_proto);
+
+	return -ENOTSUP;
+}
+#endif
+
+/**
+ * @brief Join a given multicast group.
+ *
+ * @param iface Network interface where join message is sent
+ * @param addr Multicast group to join
+ *
+ * @return Return 0 if joining was done, <0 otherwise.
+ */
+#if defined(CONFIG_NET_IPV6_MLD)
+int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr);
+#else
+#define net_ipv6_mld_join(...)
+#endif /* CONFIG_NET_IPV6_MLD */
+
+/**
+ * @brief Leave a given multicast group.
+ *
+ * @param iface Network interface where leave message is sent
+ * @param addr Multicast group to leave
+ *
+ * @return Return 0 if leaving is done, <0 otherwise.
+ */
+#if defined(CONFIG_NET_IPV6_MLD)
+int net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr);
+#else
+#define net_ipv6_mld_leave(...)
+#endif /* CONFIG_NET_IPV6_MLD */
+
+/**
+ * @typedef net_nbr_cb_t
+ * @brief Callback used while iterating over neighbors.
+ *
+ * @param nbr A valid pointer on current neighbor.
+ * @param user_data A valid pointer on some user data or NULL
+ */
+typedef void (*net_nbr_cb_t)(struct net_nbr *nbr, void *user_data);
+
+/**
+ * @brief Make sure the link layer address is set according to
+ * destination address. If the ll address is not yet known, then
+ * start neighbor discovery to find it out. If ND needs to be done
+ * then the returned packet is the Neighbor Solicitation message
+ * and the original message is sent after Neighbor Advertisement
+ * message is received.
+ *
+ * @param pkt Network packet
+ *
+ * @return Return a verdict.
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt);
+#else
+static inline enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt)
+{
+	return NET_OK;
+}
+#endif
+
+/**
+ * @brief Look for a neighbor from it's address on an iface
+ *
+ * @param iface A valid pointer on a network interface
+ * @param addr The IPv6 address to match
+ *
+ * @return A valid pointer on a neighbor on success, NULL otherwise
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+struct net_nbr *net_ipv6_nbr_lookup(struct net_if *iface,
+				    struct in6_addr *addr);
+#else
+static inline struct net_nbr *net_ipv6_nbr_lookup(struct net_if *iface,
+						  struct in6_addr *addr)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Get neighbor from its index.
+ *
+ * @param iface Network interface to match. If NULL, then use
+ * whatever interface there is configured for the neighbor address.
+ * @param idx Index of the link layer address in the address array
+ *
+ * @return A valid pointer on a neighbor on success, NULL otherwise
+ */
+struct net_nbr *net_ipv6_get_nbr(struct net_if *iface, uint8_t idx);
+
+/**
+ * @brief Look for a neighbor from it's link local address index
+ *
+ * @param iface Network interface to match. If NULL, then use
+ * whatever interface there is configured for the neighbor address.
+ * @param idx Index of the link layer address in the address array
+ *
+ * @return A valid pointer on a neighbor on success, NULL otherwise
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
+					      uint8_t idx);
+#else
+static inline
+struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
+					      uint8_t idx)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Add a neighbor to neighbor cache
+ *
+ * Add a neighbor to the cache after performing a lookup and in case
+ * there exists an entry in the cache update its state and lladdr.
+ *
+ * @param iface A valid pointer on a network interface
+ * @param addr Neighbor IPv6 address
+ * @param lladdr Neighbor link layer address
+ * @param is_router Set to true if the neighbor is a router, false
+ * otherwise
+ * @param state Initial state of the neighbor entry in the cache
+ *
+ * @return A valid pointer on a neighbor on success, NULL otherwise
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
+				 const struct in6_addr *addr,
+				 const struct net_linkaddr *lladdr,
+				 bool is_router,
+				 enum net_ipv6_nbr_state state);
+#else
+static inline struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
+					       const struct in6_addr *addr,
+					       const struct net_linkaddr *lladdr,
+					       bool is_router,
+					       enum net_ipv6_nbr_state state)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Remove a neighbor from neighbor cache.
+ *
+ * @param iface A valid pointer on a network interface
+ * @param addr Neighbor IPv6 address
+ *
+ * @return True if neighbor could be removed, False otherwise
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+bool net_ipv6_nbr_rm(struct net_if *iface, struct in6_addr *addr);
+#else
+static inline bool net_ipv6_nbr_rm(struct net_if *iface, struct in6_addr *addr)
+{
+	return true;
+}
+#endif
+
+/**
+ * @brief Go through all the neighbors and call callback for each of them.
+ *
+ * @param cb User supplied callback function to call.
+ * @param user_data User specified data.
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) && defined(CONFIG_NET_NATIVE_IPV6)
+void net_ipv6_nbr_foreach(net_nbr_cb_t cb, void *user_data);
+#else /* CONFIG_NET_IPV6_NBR_CACHE */
+static inline void net_ipv6_nbr_foreach(net_nbr_cb_t cb, void *user_data)
+{
+	return;
+}
+#endif /* CONFIG_NET_IPV6_NBR_CACHE */
+
+/**
+ * @brief Set the neighbor reachable timer.
+ *
+ * @param iface A valid pointer on a network interface
+ * @param nbr Neighbor struct pointer
+ */
+#if defined(CONFIG_NET_IPV6_ND) && defined(CONFIG_NET_NATIVE_IPV6)
+void net_ipv6_nbr_set_reachable_timer(struct net_if *iface,
+				      struct net_nbr *nbr);
+
+#else /* CONFIG_NET_IPV6_ND */
+static inline void net_ipv6_nbr_set_reachable_timer(struct net_if *iface,
+						    struct net_nbr *nbr)
+{
+}
+#endif
+
+/* We do not have to accept larger than 1500 byte IPv6 packet (RFC 2460 ch 5).
+ * This means that we should receive everything within first two fragments.
+ * The first one being 1280 bytes and the second one 220 bytes.
+ */
+#if !defined(NET_IPV6_FRAGMENTS_MAX_PKT)
+#define NET_IPV6_FRAGMENTS_MAX_PKT 2
+#endif
+
+/** Store pending IPv6 fragment information that is needed for reassembly. */
+struct net_ipv6_reassembly {
+	/** IPv6 source address of the fragment */
+	struct in6_addr src;
+
+	/** IPv6 destination address of the fragment */
+	struct in6_addr dst;
+
+	/**
+	 * Timeout for cancelling the reassembly. The timer is used
+	 * also to detect if this reassembly slot is used or not.
+	 */
+	struct k_delayed_work timer;
+
+	/** Pointers to pending fragments */
+	struct net_pkt *pkt[NET_IPV6_FRAGMENTS_MAX_PKT];
+
+	/** IPv6 fragment identification */
+	uint32_t id;
+};
+
+/**
+ * @typedef net_ipv6_frag_cb_t
+ * @brief Callback used while iterating over pending IPv6 fragments.
+ *
+ * @param reass IPv6 fragment reassembly struct
+ * @param user_data A valid pointer on some user data or NULL
+ */
+typedef void (*net_ipv6_frag_cb_t)(struct net_ipv6_reassembly *reass,
+				   void *user_data);
+
+/**
+ * @brief Go through all the currently pending IPv6 fragments.
+ *
+ * @param cb Callback to call for each pending IPv6 fragment.
+ * @param user_data User specified data or NULL.
+ */
+void net_ipv6_frag_foreach(net_ipv6_frag_cb_t cb, void *user_data);
+
+/**
+ * @brief Find the last IPv6 extension header in the network packet.
+ *
+ * @param pkt Network head packet.
+ * @param next_hdr_off Offset of the next header field that points
+ * to last header. This is returned to caller.
+ * @param last_hdr_off Offset of the last header field in the packet.
+ * This is returned to caller.
+ *
+ * @return 0 on success, a negative errno otherwise.
+ */
+int net_ipv6_find_last_ext_hdr(struct net_pkt *pkt, uint16_t *next_hdr_off,
+			       uint16_t *last_hdr_off);
+
+/**
+ * @brief Handles IPv6 fragmented packets.
+ *
+ * @param pkt     Network head packet.
+ * @param hdr     The IPv6 header of the current packet
+ * @param nexthdr IPv6 next header after fragment header part
+ *
+ * @return Return verdict about the packet
+ */
+#if defined(CONFIG_NET_IPV6_FRAGMENT) && defined(CONFIG_NET_NATIVE_IPV6)
+enum net_verdict net_ipv6_handle_fragment_hdr(struct net_pkt *pkt,
+					      struct net_ipv6_hdr *hdr,
+					      uint8_t nexthdr);
+#else
+static inline
+enum net_verdict net_ipv6_handle_fragment_hdr(struct net_pkt *pkt,
+					      struct net_ipv6_hdr *hdr,
+					      uint8_t nexthdr)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(hdr);
+	ARG_UNUSED(nexthdr);
+
+	return NET_DROP;
+}
+#endif /* CONFIG_NET_IPV6_FRAGMENT */
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+void net_ipv6_init(void);
+void net_ipv6_nbr_init(void);
+#if defined(CONFIG_NET_IPV6_MLD)
+void net_ipv6_mld_init(void);
+#else
+#define net_ipv6_mld_init(...)
+#endif
+#else
+#define net_ipv6_init(...)
+#define net_ipv6_nbr_init(...)
+#endif
+
+#endif /* __IPV6_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6.c	(working copy)
@@ -0,0 +1,655 @@
+/** @file
+ * @brief IPv6 related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* By default this prints too much data, set the value to 1 to see
+ * neighbor cache contents.
+ */
+#define NET_DEBUG_NBR 0
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
+
+#include <errno.h>
+#include <stdlib.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_context.h>
+#include <net/net_mgmt.h>
+#include "net_private.h"
+#include "connection.h"
+#include "icmpv6.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv6.h"
+#include "nbr.h"
+#include "6lo.h"
+#include "route.h"
+#include "net_stats.h"
+
+/* Timeout value to be used when allocating net buffer during various
+ * neighbor discovery procedures.
+ */
+#define ND_NET_BUF_TIMEOUT K_MSEC(100)
+
+/* Timeout for various buffer allocations in this file. */
+#define NET_BUF_TIMEOUT K_MSEC(50)
+
+/* Maximum reachable time value specified in RFC 4861 section
+ * 6.2.1. Router Configuration Variables, AdvReachableTime
+ */
+#define MAX_REACHABLE_TIME 3600000
+
+int net_ipv6_create(struct net_pkt *pkt,
+		    const struct in6_addr *src,
+		    const struct in6_addr *dst)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct net_ipv6_hdr *ipv6_hdr;
+
+	ipv6_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!ipv6_hdr) {
+		return -ENOBUFS;
+	}
+
+	ipv6_hdr->vtc     = 0x60;
+	ipv6_hdr->tcflow  = 0U;
+	ipv6_hdr->flow    = 0U;
+	ipv6_hdr->len     = 0U;
+	ipv6_hdr->nexthdr = 0U;
+
+	/* User can tweak the default hop limit if needed */
+	ipv6_hdr->hop_limit = net_pkt_ipv6_hop_limit(pkt);
+	if (ipv6_hdr->hop_limit == 0U) {
+		ipv6_hdr->hop_limit =
+			net_if_ipv6_get_hop_limit(net_pkt_iface(pkt));
+	}
+
+	net_ipaddr_copy(&ipv6_hdr->dst, dst);
+	net_ipaddr_copy(&ipv6_hdr->src, src);
+
+	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
+	net_pkt_set_ipv6_ext_len(pkt, 0);
+
+	return net_pkt_set_data(pkt, &ipv6_access);
+}
+
+int net_ipv6_finalize(struct net_pkt *pkt, uint8_t next_header_proto)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct net_ipv6_hdr *ipv6_hdr;
+
+	net_pkt_set_overwrite(pkt, true);
+
+	ipv6_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!ipv6_hdr) {
+		return -ENOBUFS;
+	}
+
+	ipv6_hdr->len = htons(net_pkt_get_len(pkt) -
+			      sizeof(struct net_ipv6_hdr));
+
+	if (net_pkt_ipv6_next_hdr(pkt) != 255U) {
+		ipv6_hdr->nexthdr = net_pkt_ipv6_next_hdr(pkt);
+	} else {
+		ipv6_hdr->nexthdr = next_header_proto;
+	}
+
+	net_pkt_set_data(pkt, &ipv6_access);
+
+	if (net_pkt_ipv6_next_hdr(pkt) != 255U &&
+	    net_pkt_skip(pkt, net_pkt_ipv6_ext_len(pkt))) {
+		return -ENOBUFS;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    next_header_proto == IPPROTO_UDP) {
+		return net_udp_finalize(pkt);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   next_header_proto == IPPROTO_TCP) {
+		return net_tcp_finalize(pkt);
+	} else if (next_header_proto == IPPROTO_ICMPV6) {
+		return net_icmpv6_finalize(pkt);
+	}
+
+	return 0;
+}
+
+static inline bool ipv6_drop_on_unknown_option(struct net_pkt *pkt,
+					       struct net_ipv6_hdr *hdr,
+					       uint8_t opt_type,
+					       uint16_t length)
+{
+	/* RFC 2460 chapter 4.2 tells how to handle the unknown
+	 * options by the two highest order bits of the option:
+	 *
+	 * 00: Skip over this option and continue processing the header.
+	 * 01: Discard the packet.
+	 * 10: Discard the packet and, regardless of whether or not the
+	 *     packet's Destination Address was a multicast address,
+	 *     send an ICMP Parameter Problem, Code 2, message to the packet's
+	 *     Source Address, pointing to the unrecognized Option Type.
+	 * 11: Discard the packet and, only if the packet's Destination
+	 *     Address was not a multicast address, send an ICMP Parameter
+	 *     Problem, Code 2, message to the packet's Source Address,
+	 *     pointing to the unrecognized Option Type.
+	 */
+	NET_DBG("Unknown option %d (0x%02x) MSB %d - 0x%02x",
+		opt_type, opt_type, opt_type >> 6, opt_type & 0xc0);
+
+	switch (opt_type & 0xc0) {
+	case 0x00:
+		return false;
+	case 0x40:
+		break;
+	case 0xc0:
+		if (net_ipv6_is_addr_mcast(&hdr->dst)) {
+			break;
+		}
+
+		__fallthrough;
+	case 0x80:
+		net_icmpv6_send_error(pkt, NET_ICMPV6_PARAM_PROBLEM,
+				      NET_ICMPV6_PARAM_PROB_OPTION,
+				      (uint32_t)length);
+		break;
+	}
+
+	return true;
+}
+
+static inline int ipv6_handle_ext_hdr_options(struct net_pkt *pkt,
+					      struct net_ipv6_hdr *hdr,
+					      uint16_t pkt_len)
+{
+	uint16_t exthdr_len = 0U;
+	uint16_t length = 0U;
+
+	if (net_pkt_read_u8(pkt, (uint8_t *)&exthdr_len)) {
+		return -ENOBUFS;
+	}
+
+	exthdr_len = exthdr_len * 8U + 8;
+	if (exthdr_len > pkt_len) {
+		NET_DBG("Corrupted packet, extension header %d too long "
+			"(max %d bytes)", exthdr_len, pkt_len);
+		return -EINVAL;
+	}
+
+	length += 2U;
+
+	while (length < exthdr_len) {
+		uint8_t opt_type, opt_len;
+
+		/* Each extension option has type and length */
+		if (net_pkt_read_u8(pkt, &opt_type)) {
+			return -ENOBUFS;
+		}
+
+		if (opt_type != NET_IPV6_EXT_HDR_OPT_PAD1) {
+			if (net_pkt_read_u8(pkt, &opt_len)) {
+				return -ENOBUFS;
+			}
+		}
+
+		switch (opt_type) {
+		case NET_IPV6_EXT_HDR_OPT_PAD1:
+			length++;
+			break;
+		case NET_IPV6_EXT_HDR_OPT_PADN:
+			NET_DBG("PADN option");
+			length += opt_len + 2;
+
+			break;
+		default:
+			/* Make sure that the option length is not too large.
+			 * The former 1 + 1 is the length of extension type +
+			 * length fields.
+			 * The latter 1 + 1 is the length of the sub-option
+			 * type and length fields.
+			 */
+			if (opt_len > (exthdr_len - (1 + 1 + 1 + 1))) {
+				return -EINVAL;
+			}
+
+			if (ipv6_drop_on_unknown_option(pkt, hdr,
+							opt_type, length)) {
+				return -ENOTSUP;
+			}
+
+			if (net_pkt_skip(pkt, opt_len)) {
+				return -ENOBUFS;
+			}
+
+			length += opt_len + 2;
+
+			break;
+		}
+	}
+
+	return exthdr_len;
+}
+
+#if defined(CONFIG_NET_ROUTE)
+static struct net_route_entry *add_route(struct net_if *iface,
+					 struct in6_addr *addr,
+					 uint8_t prefix_len)
+{
+	struct net_route_entry *route;
+
+	route = net_route_lookup(iface, addr);
+	if (route) {
+		return route;
+	}
+
+	route = net_route_add(iface, addr, prefix_len, addr);
+
+	NET_DBG("%s route to %s/%d iface %p", route ? "Add" : "Cannot add",
+		log_strdup(net_sprint_ipv6_addr(addr)), prefix_len, iface);
+
+	return route;
+}
+#endif /* CONFIG_NET_ROUTE */
+
+static void ipv6_no_route_info(struct net_pkt *pkt,
+			       struct in6_addr *src,
+			       struct in6_addr *dst)
+{
+	NET_DBG("Will not route pkt %p ll src %s to dst %s between interfaces",
+		pkt, log_strdup(net_sprint_ipv6_addr(src)),
+		log_strdup(net_sprint_ipv6_addr(dst)));
+}
+
+#if defined(CONFIG_NET_ROUTE)
+static enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
+					  struct net_ipv6_hdr *hdr)
+{
+	struct net_route_entry *route;
+	struct in6_addr *nexthop;
+	bool found;
+
+	/* Check if the packet can be routed */
+	if (IS_ENABLED(CONFIG_NET_ROUTING)) {
+		found = net_route_get_info(NULL, &hdr->dst, &route,
+					   &nexthop);
+	} else {
+		found = net_route_get_info(net_pkt_iface(pkt),
+					   &hdr->dst, &route, &nexthop);
+	}
+
+	if (found) {
+		int ret;
+
+		if (IS_ENABLED(CONFIG_NET_ROUTING) &&
+		    (net_ipv6_is_ll_addr(&hdr->src) ||
+		     net_ipv6_is_ll_addr(&hdr->dst))) {
+			/* RFC 4291 ch 2.5.6 */
+			ipv6_no_route_info(pkt, &hdr->src, &hdr->dst);
+			goto drop;
+		}
+
+		/* Used when detecting if the original link
+		 * layer address length is changed or not.
+		 */
+		net_pkt_set_orig_iface(pkt, net_pkt_iface(pkt));
+
+		if (route) {
+			net_pkt_set_iface(pkt, route->iface);
+		}
+
+		if (IS_ENABLED(CONFIG_NET_ROUTING) &&
+		    net_pkt_orig_iface(pkt) != net_pkt_iface(pkt)) {
+			/* If the route interface to destination is
+			 * different than the original route, then add
+			 * route to original source.
+			 */
+			NET_DBG("Route pkt %p from %p to %p",
+				pkt, net_pkt_orig_iface(pkt),
+				net_pkt_iface(pkt));
+
+			add_route(net_pkt_orig_iface(pkt), &hdr->src, 128);
+		}
+
+		ret = net_route_packet(pkt, nexthop);
+		if (ret < 0) {
+			NET_DBG("Cannot re-route pkt %p via %s "
+				"at iface %p (%d)",
+				pkt, log_strdup(net_sprint_ipv6_addr(nexthop)),
+				net_pkt_iface(pkt), ret);
+		} else {
+			return NET_OK;
+		}
+	} else {
+		struct net_if *iface = NULL;
+		int ret;
+
+		if (net_if_ipv6_addr_onlink(&iface, &hdr->dst)) {
+			ret = net_route_packet_if(pkt, iface);
+			if (ret < 0) {
+				NET_DBG("Cannot re-route pkt %p "
+					"at iface %p (%d)",
+					pkt, net_pkt_iface(pkt), ret);
+			} else {
+				return NET_OK;
+			}
+		}
+
+		NET_DBG("No route to %s pkt %p dropped",
+			log_strdup(net_sprint_ipv6_addr(&hdr->dst)), pkt);
+	}
+
+drop:
+	return NET_DROP;
+}
+#else
+static inline enum net_verdict ipv6_route_packet(struct net_pkt *pkt,
+						 struct net_ipv6_hdr *hdr)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(hdr);
+
+	NET_DBG("DROP: Packet %p not for me", pkt);
+
+	return NET_DROP;
+}
+
+#endif /* CONFIG_NET_ROUTE */
+
+
+static enum net_verdict ipv6_forward_mcast_packet(struct net_pkt *pkt,
+						 struct net_ipv6_hdr *hdr)
+{
+#if defined(CONFIG_NET_ROUTE_MCAST)
+	int routed;
+
+	/* check if routing loop could be created or if the destination is of
+	 * interface local scope or if from link local source
+	 */
+	if (net_ipv6_is_addr_mcast(&hdr->src)  ||
+	      net_ipv6_is_addr_mcast_iface(&hdr->dst) ||
+	       net_ipv6_is_ll_addr(&hdr->src)) {
+		return NET_CONTINUE;
+	}
+
+	routed = net_route_mcast_forward_packet(pkt, hdr);
+
+	if (routed < 0) {
+		return NET_DROP;
+	}
+#endif /*CONFIG_NET_ROUTE_MCAST*/
+	return NET_CONTINUE;
+}
+
+enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	struct net_if *pkt_iface = net_pkt_iface(pkt);
+	enum net_verdict verdict = NET_DROP;
+	int real_len = net_pkt_get_len(pkt);
+	uint8_t ext_bitmap = 0U;
+	uint16_t ext_len = 0U;
+	uint8_t nexthdr, next_nexthdr, prev_hdr_offset;
+	union net_proto_header proto_hdr;
+	struct net_ipv6_hdr *hdr;
+	struct net_if_mcast_addr *if_mcast_addr;
+	union net_ip_header ip;
+	int pkt_len;
+
+	net_stats_update_ipv6_recv(pkt_iface);
+
+	hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!hdr) {
+		NET_DBG("DROP: no buffer");
+		goto drop;
+	}
+
+	pkt_len = ntohs(hdr->len) + sizeof(struct net_ipv6_hdr);
+	if (real_len < pkt_len) {
+		NET_DBG("DROP: pkt len per hdr %d != pkt real len %d",
+			pkt_len, real_len);
+		goto drop;
+	} else if (real_len > pkt_len) {
+		net_pkt_update_length(pkt, pkt_len);
+	}
+
+	NET_DBG("IPv6 packet len %d received from %s to %s", pkt_len,
+		log_strdup(net_sprint_ipv6_addr(&hdr->src)),
+		log_strdup(net_sprint_ipv6_addr(&hdr->dst)));
+
+	if (net_ipv6_is_addr_unspecified(&hdr->src)) {
+		NET_DBG("DROP: src addr is %s", "unspecified");
+		goto drop;
+	}
+
+	if (net_ipv6_is_addr_mcast(&hdr->src) ||
+	    net_ipv6_is_addr_mcast_scope(&hdr->dst, 0)) {
+		NET_DBG("DROP: multicast packet");
+		goto drop;
+	}
+
+	if (!is_loopback) {
+		if (net_ipv6_is_addr_loopback(&hdr->dst) ||
+		    net_ipv6_is_addr_loopback(&hdr->src)) {
+			NET_DBG("DROP: ::1 packet");
+			goto drop;
+		}
+
+		if (net_ipv6_is_addr_mcast_iface(&hdr->dst) ||
+		    (net_ipv6_is_addr_mcast_group(
+			    &hdr->dst, net_ipv6_unspecified_address()) &&
+		     (net_ipv6_is_addr_mcast_site(&hdr->dst) ||
+		      net_ipv6_is_addr_mcast_org(&hdr->dst)))) {
+			NET_DBG("DROP: invalid scope multicast packet");
+			goto drop;
+		}
+	}
+
+	/* Check extension headers */
+	net_pkt_set_ipv6_next_hdr(pkt, hdr->nexthdr);
+	net_pkt_set_ipv6_ext_len(pkt, 0);
+	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
+	net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_HDR(pkt)->hop_limit);
+	net_pkt_set_family(pkt, PF_INET6);
+
+	if (IS_ENABLED(CONFIG_NET_ROUTE_MCAST) &&
+		net_ipv6_is_addr_mcast(&hdr->dst)) {
+		/* If the packet is a multicast packet and multicast routing
+		 * is activated, we give the packet to the routing engine.
+		 *
+		 * But we only drop the packet if an error occurs, otherwise
+		 * it might be eminent to respond on the packet on application
+		 * layer.
+		 */
+		if (ipv6_forward_mcast_packet(pkt, hdr) == NET_DROP) {
+			goto drop;
+		}
+	}
+
+	if (!net_ipv6_is_addr_mcast(&hdr->dst)) {
+		if (!net_ipv6_is_my_addr(&hdr->dst)) {
+			if (ipv6_route_packet(pkt, hdr) == NET_OK) {
+				return NET_OK;
+			}
+
+			goto drop;
+		}
+
+		/* If we receive a packet with ll source address fe80: and
+		 * destination address is one of ours, and if the packet would
+		 * cross interface boundary, then drop the packet.
+		 * RFC 4291 ch 2.5.6
+		 */
+		if (IS_ENABLED(CONFIG_NET_ROUTING) &&
+		    net_ipv6_is_ll_addr(&hdr->src) &&
+		    !net_if_ipv6_addr_lookup_by_iface(pkt_iface, &hdr->dst)) {
+			ipv6_no_route_info(pkt, &hdr->src, &hdr->dst);
+			goto drop;
+		}
+	}
+
+	if (net_ipv6_is_addr_mcast(&hdr->dst) &&
+	    !(net_ipv6_is_addr_mcast_iface(&hdr->dst) ||
+	      net_ipv6_is_addr_mcast_link_all_nodes(&hdr->dst))) {
+		/* If we receive a packet with a interface-local or
+		 * link-local all-nodes multicast destination address we
+		 * always have to pass it to the upper layer.
+		 *
+		 * For all other destination multicast addresses we have to
+		 * check if one of the joined multicast groups on the
+		 * originating interface of the packet matches. Otherwise the
+		 * packet will be dropped.
+		 * RFC4291 ch 2.7.1, ch 2.8
+		 */
+		if_mcast_addr = net_if_ipv6_maddr_lookup(&hdr->dst, &pkt_iface);
+
+		if (!if_mcast_addr ||
+		    !net_if_ipv6_maddr_is_joined(if_mcast_addr)) {
+			NET_DBG("DROP: packet for unjoined multicast address");
+			goto drop;
+		}
+	}
+
+	net_pkt_acknowledge_data(pkt, &ipv6_access);
+
+	nexthdr = hdr->nexthdr;
+	prev_hdr_offset = (uint8_t *)&hdr->nexthdr - (uint8_t *)hdr;
+
+	while (!net_ipv6_is_nexthdr_upper_layer(nexthdr)) {
+		int exthdr_len;
+
+		NET_DBG("IPv6 next header %d", nexthdr);
+
+		if (net_pkt_read_u8(pkt, &next_nexthdr)) {
+			goto drop;
+		}
+
+		switch (nexthdr) {
+		case NET_IPV6_NEXTHDR_HBHO:
+			if (ext_bitmap & NET_IPV6_EXT_HDR_BITMAP_HBHO) {
+				NET_ERR("DROP: multiple hop-by-hop");
+				goto drop;
+			}
+
+			/* HBH option needs to be the first one */
+			if (nexthdr != hdr->nexthdr) {
+				goto bad_hdr;
+			}
+
+			ext_bitmap |= NET_IPV6_EXT_HDR_BITMAP_HBHO;
+
+			break;
+
+		case NET_IPV6_NEXTHDR_DESTO:
+			if (ext_bitmap & NET_IPV6_EXT_HDR_BITMAP_DESTO2) {
+				/* DESTO option cannot appear more than twice */
+				goto bad_hdr;
+			}
+
+			if (ext_bitmap & NET_IPV6_EXT_HDR_BITMAP_DESTO1) {
+				ext_bitmap |= NET_IPV6_EXT_HDR_BITMAP_DESTO2;
+			} else {
+				ext_bitmap |= NET_IPV6_EXT_HDR_BITMAP_DESTO1;
+			}
+
+			break;
+
+		case NET_IPV6_NEXTHDR_FRAG:
+			if (IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT)) {
+				net_pkt_set_ipv6_hdr_prev(pkt,
+							  prev_hdr_offset);
+				net_pkt_set_ipv6_fragment_start(
+					pkt,
+					net_pkt_get_current_offset(pkt) - 1);
+				return net_ipv6_handle_fragment_hdr(pkt, hdr,
+								    nexthdr);
+			}
+
+			goto bad_hdr;
+
+		case NET_IPV6_NEXTHDR_NONE:
+			/* There is nothing after this header (see RFC 2460,
+			 * ch 4.7), so we can drop the packet now.
+			 * This is not an error case so do not update drop
+			 * statistics.
+			 */
+			return NET_DROP;
+
+		default:
+			goto bad_hdr;
+		}
+
+		exthdr_len = ipv6_handle_ext_hdr_options(pkt, hdr, pkt_len);
+		if (exthdr_len < 0) {
+			goto drop;
+		}
+
+		ext_len += exthdr_len;
+		nexthdr = next_nexthdr;
+	}
+
+	net_pkt_set_ipv6_ext_len(pkt, ext_len);
+
+	switch (nexthdr) {
+	case IPPROTO_ICMPV6:
+		verdict = net_icmpv6_input(pkt, hdr);
+		break;
+	case IPPROTO_TCP:
+		proto_hdr.tcp = net_tcp_input(pkt, &tcp_access);
+		if (proto_hdr.tcp) {
+			verdict = NET_OK;
+		}
+		break;
+	case IPPROTO_UDP:
+		proto_hdr.udp = net_udp_input(pkt, &udp_access);
+		if (proto_hdr.udp) {
+			verdict = NET_OK;
+		}
+		break;
+	}
+
+	if (verdict == NET_DROP) {
+		goto drop;
+	} else if (nexthdr == IPPROTO_ICMPV6) {
+		return verdict;
+	}
+
+	ip.ipv6 = hdr;
+
+	verdict = net_conn_input(pkt, &ip, nexthdr, &proto_hdr);
+	if (verdict != NET_DROP) {
+		return verdict;
+	}
+
+drop:
+	net_stats_update_ipv6_drop(pkt_iface);
+	return NET_DROP;
+
+bad_hdr:
+	/* Send error message about parameter problem (RFC 2460) */
+	net_icmpv6_send_error(pkt, NET_ICMPV6_PARAM_PROBLEM,
+			      NET_ICMPV6_PARAM_PROB_NEXTHEADER,
+			      net_pkt_get_current_offset(pkt) - 1);
+
+	NET_DBG("DROP: Unknown/wrong nexthdr type");
+	net_stats_update_ip_errors_protoerr(pkt_iface);
+
+	return NET_DROP;
+}
+
+void net_ipv6_init(void)
+{
+	net_ipv6_nbr_init();
+
+#if defined(CONFIG_NET_IPV6_MLD)
+	net_ipv6_mld_init();
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_fragment.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_fragment.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_fragment.c	(working copy)
@@ -0,0 +1,721 @@
+/** @file
+ * @brief IPv6 Fragment related functions
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_context.h>
+#include <net/net_mgmt.h>
+#include <random/rand32.h>
+#include "net_private.h"
+#include "connection.h"
+#include "icmpv6.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv6.h"
+#include "nbr.h"
+#include "6lo.h"
+#include "route.h"
+#include "net_stats.h"
+
+/* Timeout for various buffer allocations in this file. */
+#define NET_BUF_TIMEOUT K_MSEC(50)
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT_TIMEOUT)
+#define IPV6_REASSEMBLY_TIMEOUT K_SECONDS(CONFIG_NET_IPV6_FRAGMENT_TIMEOUT)
+#else
+#define IPV6_REASSEMBLY_TIMEOUT K_SECONDS(5)
+#endif /* CONFIG_NET_IPV6_FRAGMENT_TIMEOUT */
+
+#define FRAG_BUF_WAIT K_MSEC(10) /* how long to max wait for a buffer */
+
+static void reassembly_timeout(struct k_work *work);
+static bool reassembly_init_done;
+
+static struct net_ipv6_reassembly
+reassembly[CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT];
+
+int net_ipv6_find_last_ext_hdr(struct net_pkt *pkt, uint16_t *next_hdr_off,
+			       uint16_t *last_hdr_off)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct net_ipv6_hdr *hdr;
+	uint8_t next_nexthdr;
+	uint8_t nexthdr;
+	uint16_t length;
+
+	if (!pkt || !pkt->frags || !next_hdr_off || !last_hdr_off) {
+		return -EINVAL;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!hdr) {
+		return -ENOBUFS;
+	}
+
+	net_pkt_acknowledge_data(pkt, &ipv6_access);
+
+	nexthdr = hdr->nexthdr;
+
+	/* Initial values */
+	*next_hdr_off = offsetof(struct net_ipv6_hdr, nexthdr);
+	*last_hdr_off = sizeof(struct net_ipv6_hdr);
+
+	nexthdr = hdr->nexthdr;
+	while (!net_ipv6_is_nexthdr_upper_layer(nexthdr)) {
+		if (net_pkt_read_u8(pkt, &next_nexthdr)) {
+			goto fail;
+		}
+
+		switch (nexthdr) {
+		case NET_IPV6_NEXTHDR_HBHO:
+		case NET_IPV6_NEXTHDR_DESTO:
+			length = 0U;
+
+			if (net_pkt_read_u8(pkt, (uint8_t *)&length)) {
+				goto fail;
+			}
+
+			length = length * 8U + 8 - 2;
+
+			if (net_pkt_skip(pkt, length)) {
+				goto fail;
+			}
+
+			break;
+		case NET_IPV6_NEXTHDR_FRAG:
+			if (net_pkt_skip(pkt, 7)) {
+				goto fail;
+			}
+
+			break;
+		case NET_IPV6_NEXTHDR_NONE:
+			goto out;
+		default:
+			/* TODO: Add more IPv6 extension headers to check */
+			goto fail;
+		}
+
+		*next_hdr_off = *last_hdr_off;
+		*last_hdr_off = net_pkt_get_current_offset(pkt);
+
+		nexthdr = next_nexthdr;
+	}
+out:
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+static struct net_ipv6_reassembly *reassembly_get(uint32_t id,
+						  struct in6_addr *src,
+						  struct in6_addr *dst)
+{
+	int i, avail = -1;
+
+	for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT; i++) {
+
+		if (k_delayed_work_remaining_get(&reassembly[i].timer) &&
+		    reassembly[i].id == id &&
+		    net_ipv6_addr_cmp(src, &reassembly[i].src) &&
+		    net_ipv6_addr_cmp(dst, &reassembly[i].dst)) {
+			return &reassembly[i];
+		}
+
+		if (k_delayed_work_remaining_get(&reassembly[i].timer)) {
+			continue;
+		}
+
+		if (avail < 0) {
+			avail = i;
+		}
+	}
+
+	if (avail < 0) {
+		return NULL;
+	}
+
+	k_delayed_work_submit(&reassembly[avail].timer,
+			      IPV6_REASSEMBLY_TIMEOUT);
+
+	net_ipaddr_copy(&reassembly[avail].src, src);
+	net_ipaddr_copy(&reassembly[avail].dst, dst);
+
+	reassembly[avail].id = id;
+
+	return &reassembly[avail];
+}
+
+static bool reassembly_cancel(uint32_t id,
+			      struct in6_addr *src,
+			      struct in6_addr *dst)
+{
+	int i, j;
+
+	NET_DBG("Cancel 0x%x", id);
+
+	for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT; i++) {
+		int32_t remaining;
+
+		if (reassembly[i].id != id ||
+		    !net_ipv6_addr_cmp(src, &reassembly[i].src) ||
+		    !net_ipv6_addr_cmp(dst, &reassembly[i].dst)) {
+			continue;
+		}
+
+		remaining = k_delayed_work_remaining_get(&reassembly[i].timer);
+		if (remaining) {
+			k_delayed_work_cancel(&reassembly[i].timer);
+		}
+
+		NET_DBG("IPv6 reassembly id 0x%x remaining %d ms",
+			reassembly[i].id, remaining);
+
+		reassembly[i].id = 0U;
+
+		for (j = 0; j < NET_IPV6_FRAGMENTS_MAX_PKT; j++) {
+			if (!reassembly[i].pkt[j]) {
+				continue;
+			}
+
+			NET_DBG("[%d] IPv6 reassembly pkt %p %zd bytes data",
+				j, reassembly[i].pkt[j],
+				net_pkt_get_len(reassembly[i].pkt[j]));
+
+			net_pkt_unref(reassembly[i].pkt[j]);
+			reassembly[i].pkt[j] = NULL;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static void reassembly_info(char *str, struct net_ipv6_reassembly *reass)
+{
+	NET_DBG("%s id 0x%x src %s dst %s remain %d ms", str, reass->id,
+		log_strdup(net_sprint_ipv6_addr(&reass->src)),
+		log_strdup(net_sprint_ipv6_addr(&reass->dst)),
+		k_delayed_work_remaining_get(&reass->timer));
+}
+
+static void reassembly_timeout(struct k_work *work)
+{
+	struct net_ipv6_reassembly *reass =
+		CONTAINER_OF(work, struct net_ipv6_reassembly, timer);
+
+	reassembly_info("Reassembly cancelled", reass);
+
+	reassembly_cancel(reass->id, &reass->src, &reass->dst);
+}
+
+static void reassemble_packet(struct net_ipv6_reassembly *reass)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(frag_access, struct net_ipv6_frag_hdr);
+	union {
+		struct net_ipv6_hdr *hdr;
+		struct net_ipv6_frag_hdr *frag_hdr;
+	} ipv6;
+
+	struct net_pkt *pkt;
+	struct net_buf *last;
+	uint8_t next_hdr;
+	int i, len;
+
+	k_delayed_work_cancel(&reass->timer);
+
+	NET_ASSERT(reass->pkt[0]);
+
+	last = net_buf_frag_last(reass->pkt[0]->buffer);
+
+	/* We start from 2nd packet which is then appended to
+	 * the first one.
+	 */
+	for (i = 1; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
+		int removed_len;
+
+		pkt = reass->pkt[i];
+
+		net_pkt_cursor_init(pkt);
+
+		/* Get rid of IPv6 and fragment header which are at
+		 * the beginning of the fragment.
+		 */
+		removed_len = net_pkt_ipv6_fragment_start(pkt) +
+			      sizeof(struct net_ipv6_frag_hdr);
+
+		NET_DBG("Removing %d bytes from start of pkt %p",
+			removed_len, pkt->buffer);
+
+		if (net_pkt_pull(pkt, removed_len)) {
+			NET_ERR("Failed to pull headers");
+			reassembly_cancel(reass->id, &reass->src, &reass->dst);
+			return;
+		}
+
+		/* Attach the data to previous pkt */
+		last->frags = pkt->buffer;
+		last = net_buf_frag_last(pkt->buffer);
+
+		pkt->buffer = NULL;
+		reass->pkt[i] = NULL;
+
+		net_pkt_unref(pkt);
+	}
+
+	pkt = reass->pkt[0];
+	reass->pkt[0] = NULL;
+
+	/* Next we need to strip away the fragment header from the first packet
+	 * and set the various pointers and values in packet.
+	 */
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, net_pkt_ipv6_fragment_start(pkt))) {
+		NET_ERR("Failed to move to fragment header");
+		goto error;
+	}
+
+	ipv6.frag_hdr = (struct net_ipv6_frag_hdr *)net_pkt_get_data(
+							pkt, &frag_access);
+	if (!ipv6.frag_hdr) {
+		NET_ERR("Failed to get fragment header");
+		goto error;
+	}
+
+	next_hdr = ipv6.frag_hdr->nexthdr;
+
+	if (net_pkt_pull(pkt, sizeof(struct net_ipv6_frag_hdr))) {
+		NET_ERR("Failed to remove fragment header");
+		goto error;
+	}
+
+	/* This one updates the previous header's nexthdr value */
+	if (net_pkt_skip(pkt, net_pkt_ipv6_hdr_prev(pkt)) ||
+	    net_pkt_write_u8(pkt, next_hdr)) {
+		goto error;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	ipv6.hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!ipv6.hdr) {
+		goto error;
+	}
+
+	/* Fix the total length of the IPv6 packet. */
+	len = net_pkt_ipv6_ext_len(pkt);
+	if (len > 0) {
+		NET_DBG("Old pkt %p IPv6 ext len is %d bytes", pkt, len);
+		net_pkt_set_ipv6_ext_len(pkt,
+				len - sizeof(struct net_ipv6_frag_hdr));
+	}
+
+	len = net_pkt_get_len(pkt) - sizeof(struct net_ipv6_hdr);
+
+	ipv6.hdr->len = htons(len);
+
+	net_pkt_set_data(pkt, &ipv6_access);
+
+	NET_DBG("New pkt %p IPv6 len is %d bytes", pkt,
+		len + NET_IPV6H_LEN);
+
+	/* We need to use the queue when feeding the packet back into the
+	 * IP stack as we might run out of stack if we call processing_data()
+	 * directly. As the packet does not contain link layer header, we
+	 * MUST NOT pass it to L2 so there will be a special check for that
+	 * in process_data() when handling the packet.
+	 */
+	if (net_recv_data(net_pkt_iface(pkt), pkt) >= 0) {
+		return;
+	}
+error:
+	net_pkt_unref(pkt);
+}
+
+void net_ipv6_frag_foreach(net_ipv6_frag_cb_t cb, void *user_data)
+{
+	int i;
+
+	for (i = 0; reassembly_init_done &&
+		     i < CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT; i++) {
+		if (!k_delayed_work_remaining_get(&reassembly[i].timer)) {
+			continue;
+		}
+
+		cb(&reassembly[i], user_data);
+	}
+}
+
+/* Verify that we have all the fragments received and in correct order.
+ */
+static bool fragment_verify(struct net_ipv6_reassembly *reass)
+{
+	uint16_t offset;
+	int i, prev_len;
+
+	prev_len = net_pkt_get_len(reass->pkt[0]);
+	offset = net_pkt_ipv6_fragment_offset(reass->pkt[0]);
+
+	NET_DBG("pkt %p offset %u", reass->pkt[0], offset);
+
+	if (offset != 0U) {
+		return false;
+	}
+
+	for (i = 1; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
+		offset = net_pkt_ipv6_fragment_offset(reass->pkt[i]);
+
+		NET_DBG("pkt %p offset %u prev_len %d", reass->pkt[i],
+			offset, prev_len);
+
+		if (prev_len < offset) {
+			/* Something wrong with the offset value */
+			return false;
+		}
+
+		prev_len = net_pkt_get_len(reass->pkt[i]);
+	}
+
+	return true;
+}
+
+static int shift_packets(struct net_ipv6_reassembly *reass, int pos)
+{
+	int i;
+
+	for (i = pos + 1; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
+		if (!reass->pkt[i]) {
+			NET_DBG("Moving [%d] %p (offset 0x%x) to [%d]",
+				pos, reass->pkt[pos],
+				net_pkt_ipv6_fragment_offset(reass->pkt[pos]),
+				i);
+
+			/* Do we have enough space in packet array to make
+			 * the move?
+			 */
+			if (((i - pos) + 1) >
+			    (NET_IPV6_FRAGMENTS_MAX_PKT - i)) {
+				return -ENOMEM;
+			}
+
+			memmove(&reass->pkt[i], &reass->pkt[pos],
+				sizeof(void *) * (i - pos));
+
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+enum net_verdict net_ipv6_handle_fragment_hdr(struct net_pkt *pkt,
+					      struct net_ipv6_hdr *hdr,
+					      uint8_t nexthdr)
+{
+	struct net_ipv6_reassembly *reass = NULL;
+	uint16_t flag;
+	bool found;
+	uint8_t more;
+	uint32_t id;
+	int i;
+
+	if (!reassembly_init_done) {
+		/* Static initializing does not work here because of the array
+		 * so we must do it at runtime.
+		 */
+		for (i = 0; i < CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT; i++) {
+			k_delayed_work_init(&reassembly[i].timer,
+					    reassembly_timeout);
+		}
+
+		reassembly_init_done = true;
+	}
+
+	/* Each fragment has a fragment header, however since we already
+	 * read the nexthdr part of it, we are not going to use
+	 * net_pkt_get_data() and access the header directly: the cursor
+	 * being 1 byte too far, let's just read the next relevant pieces.
+	 */
+	if (net_pkt_skip(pkt, 1) || /* reserved */
+	    net_pkt_read_be16(pkt, &flag) ||
+	    net_pkt_read_be32(pkt, &id)) {
+		goto drop;
+	}
+
+	reass = reassembly_get(id, &hdr->src, &hdr->dst);
+	if (!reass) {
+		NET_DBG("Cannot get reassembly slot, dropping pkt %p", pkt);
+		goto drop;
+	}
+
+	more = flag & 0x01;
+	net_pkt_set_ipv6_fragment_offset(pkt, flag & 0xfff8);
+
+	if (!reass->pkt[0]) {
+		NET_DBG("Storing pkt %p to slot %d offset %d",
+			pkt, 0, net_pkt_ipv6_fragment_offset(pkt));
+		reass->pkt[0] = pkt;
+
+		reassembly_info("Reassembly 1st pkt", reass);
+
+		/* Wait for more fragments to receive. */
+		goto accept;
+	}
+
+	/* The fragments might come in wrong order so place them
+	 * in reassembly chain in correct order.
+	 */
+	for (i = 0, found = false; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
+		if (reass->pkt[i]) {
+			if (net_pkt_ipv6_fragment_offset(reass->pkt[i]) <
+			    net_pkt_ipv6_fragment_offset(pkt)) {
+				continue;
+			}
+
+			/* Make room for this fragment. If there is no room,
+			 * then it will discard the whole reassembly.
+			 */
+			if (shift_packets(reass, i)) {
+				break;
+			}
+		}
+
+		NET_DBG("Storing pkt %p to slot %d offset %d",
+			pkt, i, net_pkt_ipv6_fragment_offset(pkt));
+		reass->pkt[i] = pkt;
+		found = true;
+
+		break;
+	}
+
+	if (!found) {
+		/* We could not add this fragment into our saved fragment
+		 * list. We must discard the whole packet at this point.
+		 */
+		NET_DBG("No slots available for 0x%x", reass->id);
+		net_pkt_unref(pkt);
+		goto drop;
+	}
+
+	if (more) {
+		if (net_pkt_get_len(pkt) % 8) {
+			/* Fragment length is not multiple of 8, discard
+			 * the packet and send parameter problem error.
+			 */
+			net_icmpv6_send_error(pkt, NET_ICMPV6_PARAM_PROBLEM,
+					      NET_ICMPV6_PARAM_PROB_OPTION, 0);
+			goto drop;
+		}
+
+		reassembly_info("Reassembly nth pkt", reass);
+
+		NET_DBG("More fragments to be received");
+		goto accept;
+	}
+
+	reassembly_info("Reassembly last pkt", reass);
+
+	if (!fragment_verify(reass)) {
+		NET_DBG("Reassembled IPv6 verify failed, dropping id %u",
+			reass->id);
+
+		/* Let the caller release the already inserted pkt */
+		if (i < NET_IPV6_FRAGMENTS_MAX_PKT) {
+			reass->pkt[i] = NULL;
+		}
+
+		net_pkt_unref(pkt);
+		goto drop;
+	}
+
+	/* The last fragment received, reassemble the packet */
+	reassemble_packet(reass);
+
+accept:
+	return NET_OK;
+
+drop:
+	if (reass) {
+		if (reassembly_cancel(reass->id, &reass->src, &reass->dst)) {
+			return NET_OK;
+		}
+	}
+
+	return NET_DROP;
+}
+
+#define BUF_ALLOC_TIMEOUT K_MSEC(100)
+
+static int send_ipv6_fragment(struct net_pkt *pkt,
+			      uint16_t fit_len,
+			      uint16_t frag_offset,
+			      uint16_t next_hdr_off,
+			      uint8_t next_hdr,
+			      bool final)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(frag_access, struct net_ipv6_frag_hdr);
+	uint8_t frag_pkt_next_hdr = NET_IPV6_NEXTHDR_HBHO;
+	int ret = -ENOBUFS;
+	struct net_ipv6_frag_hdr *frag_hdr;
+	struct net_pkt *frag_pkt;
+
+	frag_pkt = net_pkt_alloc_with_buffer(net_pkt_iface(pkt), fit_len +
+					     net_pkt_ipv6_ext_len(pkt) +
+					     NET_IPV6_FRAGH_LEN,
+					     AF_INET6, 0, BUF_ALLOC_TIMEOUT);
+	if (!frag_pkt) {
+		return -ENOMEM;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	/* We copy original headers back to the fragment packet
+	 * Note that we insert the right next header to point to fragment header
+	 */
+	if (net_pkt_copy(frag_pkt, pkt, next_hdr_off) ||
+	    net_pkt_write_u8(frag_pkt, NET_IPV6_NEXTHDR_FRAG) ||
+	    net_pkt_skip(pkt, 1) ||
+	    net_pkt_copy(frag_pkt, pkt, net_pkt_ip_hdr_len(pkt) +
+			 net_pkt_ipv6_ext_len(pkt) - next_hdr_off - 1)) {
+		goto fail;
+	}
+
+	if (!net_pkt_ipv6_ext_len(pkt)) {
+		frag_pkt_next_hdr = NET_IPV6_NEXTHDR_FRAG;
+	}
+
+	/* And we append the fragmentation header */
+	frag_hdr = (struct net_ipv6_frag_hdr *)net_pkt_get_data(frag_pkt,
+								&frag_access);
+	if (!frag_hdr) {
+		goto fail;
+	}
+
+	frag_hdr->nexthdr = next_hdr;
+	frag_hdr->reserved = 0U;
+	frag_hdr->id = net_pkt_ipv6_fragment_id(pkt);
+	frag_hdr->offset = htons(((frag_offset / 8U) << 3) | !final);
+
+	if (net_pkt_set_data(frag_pkt, &frag_access)) {
+		goto fail;
+	}
+
+	net_pkt_set_ipv6_ext_len(frag_pkt,
+				 net_pkt_ipv6_ext_len(pkt) +
+				 sizeof(struct net_ipv6_frag_hdr));
+
+	/* Finally we copy the payload part of this fragment from
+	 * the original packet
+	 */
+	if (net_pkt_skip(pkt, frag_offset) ||
+	    net_pkt_copy(frag_pkt, pkt, fit_len)) {
+		goto fail;
+	}
+
+	net_pkt_cursor_init(frag_pkt);
+
+	if (net_ipv6_finalize(frag_pkt, frag_pkt_next_hdr) < 0) {
+		goto fail;
+	}
+
+	/* If everything has been ok so far, we can send the packet. */
+	ret = net_send_data(frag_pkt);
+	if (ret < 0) {
+		goto fail;
+	}
+
+	/* Let this packet to be sent and hopefully it will release
+	 * the memory that can be utilized for next sent IPv6 fragment.
+	 */
+	k_yield();
+
+	return 0;
+
+fail:
+	NET_DBG("Cannot send fragment (%d)", ret);
+	net_pkt_unref(frag_pkt);
+
+	return ret;
+}
+
+int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt,
+				 uint16_t pkt_len)
+{
+	uint16_t next_hdr_off;
+	uint16_t last_hdr_off;
+	uint16_t frag_offset;
+	size_t length;
+	uint8_t next_hdr;
+	uint8_t last_hdr;
+	int fit_len;
+	int ret;
+
+	net_pkt_set_ipv6_fragment_id(pkt, sys_rand32_get());
+
+	ret = net_ipv6_find_last_ext_hdr(pkt, &next_hdr_off, &last_hdr_off);
+	if (ret < 0) {
+		return ret;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, next_hdr_off) ||
+	    net_pkt_read_u8(pkt, &next_hdr) ||
+	    net_pkt_skip(pkt, last_hdr_off) ||
+	    net_pkt_read_u8(pkt, &last_hdr)) {
+		return -ENOBUFS;
+	}
+
+	/* The Maximum payload can fit into each packet after IPv6 header,
+	 * Extenstion headers and Fragmentation header.
+	 */
+	fit_len = NET_IPV6_MTU - NET_IPV6_FRAGH_LEN -
+		(net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt));
+	if (fit_len <= 0) {
+		/* Must be invalid extension headers length */
+		NET_DBG("No room for IPv6 payload MTU %d hdrs_len %d",
+			NET_IPV6_MTU, NET_IPV6_FRAGH_LEN +
+			net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt));
+		return -EINVAL;
+	}
+
+	frag_offset = 0U;
+
+	length = net_pkt_get_len(pkt) -
+		(net_pkt_ip_hdr_len(pkt) + net_pkt_ipv6_ext_len(pkt));
+	while (length) {
+		bool final = false;
+
+		if (fit_len >= length) {
+			final = true;
+			fit_len = length;
+		}
+
+		ret = send_ipv6_fragment(pkt, fit_len, frag_offset,
+					 next_hdr_off, next_hdr, final);
+		if (ret < 0) {
+			return ret;
+		}
+
+		length -= fit_len;
+		frag_offset += fit_len;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_mld.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_mld.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_mld.c	(working copy)
@@ -0,0 +1,362 @@
+/** @file
+ * @brief IPv6 MLD related functions
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_context.h>
+#include <net/net_mgmt.h>
+#include "net_private.h"
+#include "connection.h"
+#include "icmpv6.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv6.h"
+#include "nbr.h"
+#include "6lo.h"
+#include "route.h"
+#include "net_stats.h"
+
+/* Timeout for various buffer allocations in this file. */
+#define PKT_WAIT_TIME K_MSEC(50)
+
+#define MLDv2_MCAST_RECORD_LEN sizeof(struct net_icmpv6_mld_mcast_record)
+#define IPV6_OPT_HDR_ROUTER_ALERT_LEN 8
+
+#define MLDv2_LEN (MLDv2_MCAST_RECORD_LEN + sizeof(struct in6_addr))
+
+static int mld_create(struct net_pkt *pkt,
+		      const struct in6_addr *addr,
+		      uint8_t record_type,
+		      uint16_t num_sources)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(mld_access,
+				   struct net_icmpv6_mld_mcast_record);
+	struct net_icmpv6_mld_mcast_record *mld;
+
+	mld = (struct net_icmpv6_mld_mcast_record *)
+				net_pkt_get_data(pkt, &mld_access);
+	if (!mld) {
+		return -ENOBUFS;
+	}
+
+	mld->record_type = record_type;
+	mld->aux_data_len = 0U;
+	mld->num_sources = htons(num_sources);
+
+	net_ipaddr_copy(&mld->mcast_address, addr);
+
+	if (net_pkt_set_data(pkt, &mld_access)) {
+		return -ENOBUFS;
+	}
+
+	if (num_sources > 0) {
+		/* All source addresses, RFC 3810 ch 3 */
+		if (net_pkt_write(pkt,
+				  net_ipv6_unspecified_address()->s6_addr,
+				  sizeof(struct in6_addr))) {
+			return -ENOBUFS;
+		}
+	}
+
+	return 0;
+}
+
+static int mld_create_packet(struct net_pkt *pkt, uint16_t count)
+{
+	struct in6_addr dst;
+
+	/* Sent to all MLDv2-capable routers */
+	net_ipv6_addr_create(&dst, 0xff02, 0, 0, 0, 0, 0, 0, 0x0016);
+
+	net_pkt_set_ipv6_hop_limit(pkt, 1); /* RFC 3810 ch 7.4 */
+
+	if (net_ipv6_create(pkt, net_if_ipv6_select_src_addr(
+				    net_pkt_iface(pkt), &dst),
+			    &dst)) {
+		return -ENOBUFS;
+	}
+
+	/* Add hop-by-hop option and router alert option, RFC 3810 ch 5. */
+	if (net_pkt_write_u8(pkt, IPPROTO_ICMPV6) ||
+	    net_pkt_write_u8(pkt, 0)) {
+		return -ENOBUFS;
+	}
+
+	/* IPv6 router alert option is described in RFC 2711.
+	 * - 0x0502 RFC 2711 ch 2.1
+	 * - MLD (value 0)
+	 * - 2 bytes of padding
+	 */
+	if (net_pkt_write_be16(pkt, 0x0502) ||
+	    net_pkt_write_be16(pkt, 0) ||
+	    net_pkt_write_be16(pkt, 0)) {
+		return -ENOBUFS;
+	}
+
+	net_pkt_set_ipv6_ext_len(pkt, IPV6_OPT_HDR_ROUTER_ALERT_LEN);
+
+	/* ICMPv6 header + reserved space + count.
+	 * MLDv6 stuff will come right after
+	 */
+	if (net_icmpv6_create(pkt, NET_ICMPV6_MLDv2, 0) ||
+	    net_pkt_write_be16(pkt, 0) ||
+	    net_pkt_write_be16(pkt, count)) {
+		return -ENOBUFS;
+	}
+
+	net_pkt_set_ipv6_next_hdr(pkt, NET_IPV6_NEXTHDR_HBHO);
+
+	return 0;
+}
+
+static int mld_send(struct net_pkt *pkt)
+{
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	if (net_send_data(pkt) < 0) {
+		net_stats_update_icmp_drop(net_pkt_iface(pkt));
+		net_stats_update_ipv6_mld_drop(net_pkt_iface(pkt));
+
+		net_pkt_unref(pkt);
+
+		return -1;
+	}
+
+	net_stats_update_icmp_sent(net_pkt_iface(pkt));
+	net_stats_update_ipv6_mld_sent(net_pkt_iface(pkt));
+
+	return 0;
+}
+
+static int mld_send_generic(struct net_if *iface,
+			    const struct in6_addr *addr,
+			    uint8_t mode)
+{
+	struct net_pkt *pkt;
+	int ret;
+
+	pkt = net_pkt_alloc_with_buffer(iface, IPV6_OPT_HDR_ROUTER_ALERT_LEN +
+					NET_ICMPV6_UNUSED_LEN +
+					MLDv2_MCAST_RECORD_LEN +
+					sizeof(struct in6_addr),
+					AF_INET6, IPPROTO_ICMPV6,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	if (mld_create_packet(pkt, 1) ||
+	    mld_create(pkt, addr, mode, 1)) {
+		ret = -ENOBUFS;
+		goto drop;
+	}
+
+	ret = mld_send(pkt);
+	if (ret) {
+		goto drop;
+	}
+
+	return 0;
+
+drop:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr)
+{
+	struct net_if_mcast_addr *maddr;
+	int ret;
+
+	maddr = net_if_ipv6_maddr_lookup(addr, &iface);
+	if (maddr && net_if_ipv6_maddr_is_joined(maddr)) {
+		return -EALREADY;
+	}
+
+	if (!maddr) {
+		maddr = net_if_ipv6_maddr_add(iface, addr);
+		if (!maddr) {
+			return -ENOMEM;
+		}
+	}
+
+	ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_EXCLUDE);
+	if (ret < 0) {
+		return ret;
+	}
+
+	net_if_ipv6_maddr_join(maddr);
+
+	net_if_mcast_monitor(iface, addr, true);
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_MCAST_JOIN, iface,
+					&maddr->address.in6_addr,
+					sizeof(struct in6_addr));
+
+	return ret;
+}
+
+int net_ipv6_mld_leave(struct net_if *iface, const struct in6_addr *addr)
+{
+	struct net_if_mcast_addr *maddr;
+	int ret;
+
+	maddr = net_if_ipv6_maddr_lookup(addr, &iface);
+	if (!maddr) {
+		return -ENOENT;
+	}
+
+	if (!net_if_ipv6_maddr_rm(iface, addr)) {
+		return -EINVAL;
+	}
+
+	ret = mld_send_generic(iface, addr, NET_IPV6_MLDv2_MODE_IS_INCLUDE);
+	if (ret < 0) {
+		return ret;
+	}
+
+	net_if_mcast_monitor(iface, addr, false);
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_MCAST_LEAVE, iface,
+					&maddr->address.in6_addr,
+					sizeof(struct in6_addr));
+
+	return ret;
+}
+
+static void send_mld_report(struct net_if *iface)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	struct net_pkt *pkt;
+	int i, count = 0;
+
+	NET_ASSERT(ipv6);
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		if (!ipv6->mcast[i].is_used || !ipv6->mcast[i].is_joined) {
+			continue;
+		}
+
+		count++;
+	}
+
+	pkt = net_pkt_alloc_with_buffer(iface, IPV6_OPT_HDR_ROUTER_ALERT_LEN +
+					NET_ICMPV6_UNUSED_LEN +
+					count * MLDv2_MCAST_RECORD_LEN,
+					AF_INET6, IPPROTO_ICMPV6,
+					PKT_WAIT_TIME);
+	if (!pkt) {
+		return;
+	}
+
+	if (mld_create_packet(pkt, count)) {
+		goto drop;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		if (!ipv6->mcast[i].is_used || !ipv6->mcast[i].is_joined) {
+			continue;
+		}
+
+		if (!mld_create(pkt, &ipv6->mcast[i].address.in6_addr,
+				NET_IPV6_MLDv2_MODE_IS_EXCLUDE, 0)) {
+			goto drop;
+		}
+	}
+
+	if (!mld_send(pkt)) {
+		return;
+	}
+
+drop:
+	net_pkt_unref(pkt);
+}
+
+#define dbg_addr(action, pkt_str, src, dst)				\
+	do {								\
+		NET_DBG("%s %s from %s to %s", action, pkt_str,         \
+			log_strdup(net_sprint_ipv6_addr(src)),		\
+			log_strdup(net_sprint_ipv6_addr(dst)));		\
+	} while (0)
+
+#define dbg_addr_recv(pkt_str, src, dst)	\
+	dbg_addr("Received", pkt_str, src, dst)
+
+static enum net_verdict handle_mld_query(struct net_pkt *pkt,
+					 struct net_ipv6_hdr *ip_hdr,
+					 struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(mld_access,
+					      struct net_icmpv6_mld_query);
+	uint16_t length = net_pkt_get_len(pkt);
+	struct net_icmpv6_mld_query *mld_query;
+	uint16_t pkt_len;
+
+	mld_query = (struct net_icmpv6_mld_query *)
+				net_pkt_get_data(pkt, &mld_access);
+	if (!mld_query) {
+		NET_DBG("DROP: NULL MLD query");
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &mld_access);
+
+	dbg_addr_recv("Multicast Listener Query", &ip_hdr->src, &ip_hdr->dst);
+
+	net_stats_update_ipv6_mld_recv(net_pkt_iface(pkt));
+
+	mld_query->num_sources = ntohs(mld_query->num_sources);
+
+	pkt_len = sizeof(struct net_ipv6_hdr) +	net_pkt_ipv6_ext_len(pkt) +
+		sizeof(struct net_icmp_hdr) +
+		sizeof(struct net_icmpv6_mld_query) +
+		sizeof(struct in6_addr) * mld_query->num_sources;
+
+	if (length < pkt_len || pkt_len > NET_IPV6_MTU ||
+	    ip_hdr->hop_limit != 1U || icmp_hdr->code != 0U) {
+		goto drop;
+	}
+
+	/* Currently we only support an unspecified address query. */
+	if (!net_ipv6_addr_cmp(&mld_query->mcast_address,
+			       net_ipv6_unspecified_address())) {
+		NET_DBG("DROP: only supporting unspecified address query");
+		goto drop;
+	}
+
+	send_mld_report(net_pkt_iface(pkt));
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+
+drop:
+	net_stats_update_ipv6_mld_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+static struct net_icmpv6_handler mld_query_input_handler = {
+	.type = NET_ICMPV6_MLD_QUERY,
+	.code = 0,
+	.handler = handle_mld_query,
+};
+
+void net_ipv6_mld_init(void)
+{
+	net_icmpv6_register_handler(&mld_query_input_handler);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_nbr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_nbr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/ipv6_nbr.c	(working copy)
@@ -0,0 +1,2510 @@
+/** @file
+ * @brief IPv6 Neighbor related functions
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* By default this prints too much data, set the value to 1 to see
+ * neighbor cache contents.
+ */
+#define NET_DEBUG_NBR 0
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_ipv6, CONFIG_NET_IPV6_LOG_LEVEL);
+
+#include <errno.h>
+#include <stdlib.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+#include <net/net_context.h>
+#include <net/net_mgmt.h>
+#include "net_private.h"
+#include "connection.h"
+#include "icmpv6.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv6.h"
+#include "nbr.h"
+#include "6lo.h"
+#include "route.h"
+#include "net_stats.h"
+
+/* Timeout value to be used when allocating net buffer during various
+ * neighbor discovery procedures.
+ */
+#define ND_NET_BUF_TIMEOUT K_MSEC(100)
+
+/* Timeout for various buffer allocations in this file. */
+#define NET_BUF_TIMEOUT K_MSEC(50)
+
+/* Maximum reachable time value specified in RFC 4861 section
+ * 6.2.1. Router Configuration Variables, AdvReachableTime
+ */
+#define MAX_REACHABLE_TIME 3600000
+
+/* IPv6 minimum link MTU specified in RFC 8200 section 5
+ * Packet Size Issues
+ */
+#define MIN_IPV6_MTU NET_IPV6_MTU
+#define MAX_IPV6_MTU 0xffff
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE) || defined(CONFIG_NET_IPV6_ND)
+/* Global stale counter, whenever ipv6 neighbor enters into
+ * stale state, stale counter is incremented by one.
+ * When network stack tries to add new neighbor and if table
+ * is full, oldest (oldest stale counter) neighbor in stale
+ * state will be removed from the table and new entry will be
+ * added.
+ */
+static uint32_t stale_counter;
+
+static struct k_sem nbr_lock;
+#endif
+
+#if defined(CONFIG_NET_IPV6_ND)
+static struct k_delayed_work ipv6_nd_reachable_timer;
+static void ipv6_nd_reachable_timeout(struct k_work *work);
+static void ipv6_nd_restart_reachable_timer(struct net_nbr *nbr, int64_t time);
+#endif
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE)
+
+/* Protocol constants from RFC 4861 Chapter 10 */
+#define MAX_MULTICAST_SOLICIT 3
+#define MAX_UNICAST_SOLICIT   3
+#define DELAY_FIRST_PROBE_TIME (5 * MSEC_PER_SEC)
+#define RETRANS_TIMER 1000 /* ms */
+
+extern void net_neighbor_data_remove(struct net_nbr *nbr);
+extern void net_neighbor_table_clear(struct net_nbr_table *table);
+
+/** Neighbor Solicitation reply timer */
+static struct k_delayed_work ipv6_ns_reply_timer;
+
+NET_NBR_POOL_INIT(net_neighbor_pool,
+		  CONFIG_NET_IPV6_MAX_NEIGHBORS,
+		  sizeof(struct net_ipv6_nbr_data),
+		  net_neighbor_data_remove,
+		  0);
+
+NET_NBR_TABLE_INIT(NET_NBR_GLOBAL,
+		   neighbor,
+		   net_neighbor_pool,
+		   net_neighbor_table_clear);
+
+const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)
+{
+	switch (state) {
+	case NET_IPV6_NBR_STATE_INCOMPLETE:
+		return "incomplete";
+	case NET_IPV6_NBR_STATE_REACHABLE:
+		return "reachable";
+	case NET_IPV6_NBR_STATE_STALE:
+		return "stale";
+	case NET_IPV6_NBR_STATE_DELAY:
+		return "delay";
+	case NET_IPV6_NBR_STATE_PROBE:
+		return "probe";
+	case NET_IPV6_NBR_STATE_STATIC:
+		return "static";
+	}
+
+	return "<invalid state>";
+}
+
+static inline struct net_nbr *get_nbr(int idx)
+{
+	return &net_neighbor_pool[idx].nbr;
+}
+
+static inline struct net_nbr *get_nbr_from_data(struct net_ipv6_nbr_data *data)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (nbr->data == (uint8_t *)data) {
+			return nbr;
+		}
+	}
+
+	return NULL;
+}
+
+static void ipv6_nbr_set_state(struct net_nbr *nbr,
+			       enum net_ipv6_nbr_state new_state)
+{
+	if (new_state == net_ipv6_nbr_data(nbr)->state ||
+	    net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STATIC) {
+		return;
+	}
+
+	NET_DBG("nbr %p %s -> %s", nbr,
+		net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state),
+		net_ipv6_nbr_state2str(new_state));
+
+	net_ipv6_nbr_data(nbr)->state = new_state;
+
+	if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STALE) {
+		if (stale_counter + 1 != UINT32_MAX) {
+			net_ipv6_nbr_data(nbr)->stale_counter = stale_counter++;
+		} else {
+			/* Global stale counter reached UINT32_MAX, reset it and
+			 * respective neighbors stale counter too.
+			 */
+			struct net_nbr *n = NULL;
+			struct net_ipv6_nbr_data *data = NULL;
+			int i;
+
+			k_sem_take(&nbr_lock, K_FOREVER);
+
+			stale_counter = 0U;
+
+			for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+				n = get_nbr(i);
+				if (!n || !n->ref) {
+					continue;
+				}
+
+				data = net_ipv6_nbr_data(nbr);
+				if (!data) {
+					continue;
+				}
+
+				if (data->state != NET_IPV6_NBR_STATE_STALE) {
+					continue;
+				}
+
+				data->stale_counter = stale_counter++;
+			}
+
+			k_sem_give(&nbr_lock);
+		}
+	}
+}
+
+struct iface_cb_data {
+	net_nbr_cb_t cb;
+	void *user_data;
+};
+
+static void iface_cb(struct net_if *iface, void *user_data)
+{
+	struct iface_cb_data *data = user_data;
+	int i;
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref || nbr->iface != iface) {
+			continue;
+		}
+
+		data->cb(nbr, data->user_data);
+	}
+}
+
+void net_ipv6_nbr_foreach(net_nbr_cb_t cb, void *user_data)
+{
+	struct iface_cb_data cb_data = {
+		.cb = cb,
+		.user_data = user_data,
+	};
+
+	/* Return the neighbors according to network interface. This makes it
+	 * easier in the callback to use the neighbor information.
+	 */
+	net_if_foreach(iface_cb, &cb_data);
+}
+
+#if NET_DEBUG_NBR
+void nbr_print(void)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		NET_DBG("[%d] %p %d/%d/%d/%d/%d pending %p iface %p/%d "
+			"ll %s addr %s",
+			i, nbr, nbr->ref, net_ipv6_nbr_data(nbr)->ns_count,
+			net_ipv6_nbr_data(nbr)->is_router,
+			net_ipv6_nbr_data(nbr)->state,
+			net_ipv6_nbr_data(nbr)->link_metric,
+			net_ipv6_nbr_data(nbr)->pending,
+			nbr->iface, nbr->idx,
+			nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
+			log_strdup(net_sprint_ll_addr(
+				net_nbr_get_lladdr(nbr->idx)->addr,
+				net_nbr_get_lladdr(nbr->idx)->len)),
+			log_strdup(net_sprint_ipv6_addr(
+					   &net_ipv6_nbr_data(nbr)->addr)));
+	}
+}
+#else
+#define nbr_print(...)
+#endif
+
+static struct net_nbr *nbr_lookup(struct net_nbr_table *table,
+				  struct net_if *iface,
+				  const struct in6_addr *addr)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		if (iface && nbr->iface != iface) {
+			continue;
+		}
+
+		if (net_ipv6_addr_cmp(&net_ipv6_nbr_data(nbr)->addr, addr)) {
+			return nbr;
+		}
+	}
+
+	return NULL;
+}
+
+static inline void nbr_clear_ns_pending(struct net_ipv6_nbr_data *data)
+{
+	data->send_ns = 0;
+
+	if (data->pending) {
+		net_pkt_unref(data->pending);
+		data->pending = NULL;
+	}
+}
+
+static inline void nbr_free(struct net_nbr *nbr)
+{
+	NET_DBG("nbr %p", nbr);
+
+	nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
+
+	net_ipv6_nbr_data(nbr)->reachable = 0;
+	net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
+
+	net_nbr_unref(nbr);
+	net_nbr_unlink(nbr, NULL);
+}
+
+bool net_ipv6_nbr_rm(struct net_if *iface, struct in6_addr *addr)
+{
+	struct net_nbr *nbr;
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	struct net_event_ipv6_nbr info;
+#endif
+
+	nbr = nbr_lookup(&net_neighbor.table, iface, addr);
+	if (!nbr) {
+		return false;
+	}
+
+	/* Remove any routes with nbr as nexthop in first place */
+	net_route_del_by_nexthop(iface, addr);
+
+	nbr_free(nbr);
+
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	info.idx = -1;
+	net_ipaddr_copy(&info.addr, addr);
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_NBR_DEL,
+					iface, (void *) &info,
+					sizeof(struct net_event_ipv6_nbr));
+#else
+	net_mgmt_event_notify(NET_EVENT_IPV6_NBR_DEL, iface);
+#endif
+
+	return true;
+}
+
+#define NS_REPLY_TIMEOUT (1 * MSEC_PER_SEC)
+
+static void ipv6_ns_reply_timeout(struct k_work *work)
+{
+	int64_t current = k_uptime_get();
+	struct net_nbr *nbr = NULL;
+	struct net_ipv6_nbr_data *data;
+	int i;
+
+	ARG_UNUSED(work);
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		int64_t remaining;
+		nbr = get_nbr(i);
+
+		if (!nbr || !nbr->ref) {
+			continue;
+		}
+
+		data = net_ipv6_nbr_data(nbr);
+		if (!data) {
+			continue;
+		}
+
+		if (!data->send_ns) {
+			continue;
+		}
+
+		remaining = data->send_ns + NS_REPLY_TIMEOUT - current;
+
+		if (remaining > 0) {
+			if (!k_delayed_work_remaining_get(
+						&ipv6_ns_reply_timer)) {
+				k_delayed_work_submit(&ipv6_ns_reply_timer,
+						      K_MSEC(remaining));
+			}
+
+			continue;
+		}
+
+		data->send_ns = 0;
+
+		/* We did not receive reply to a sent NS */
+		if (!data->pending) {
+			/* Silently return, this is not an error as the work
+			 * cannot be cancelled in certain cases.
+			 */
+			continue;
+		}
+
+		NET_DBG("NS nbr %p pending %p timeout to %s", nbr,
+			data->pending,
+			log_strdup(net_sprint_ipv6_addr(
+					 &NET_IPV6_HDR(data->pending)->dst)));
+
+		/* To unref when pending variable was set */
+		net_pkt_unref(data->pending);
+
+		/* To unref the original pkt allocation */
+		net_pkt_unref(data->pending);
+
+		data->pending = NULL;
+
+		net_nbr_unref(nbr);
+	}
+}
+
+static void nbr_init(struct net_nbr *nbr, struct net_if *iface,
+		     const struct in6_addr *addr, bool is_router,
+		     enum net_ipv6_nbr_state state)
+{
+	nbr->idx = NET_NBR_LLADDR_UNKNOWN;
+	nbr->iface = iface;
+
+	net_ipaddr_copy(&net_ipv6_nbr_data(nbr)->addr, addr);
+	ipv6_nbr_set_state(nbr, state);
+	net_ipv6_nbr_data(nbr)->is_router = is_router;
+	net_ipv6_nbr_data(nbr)->pending = NULL;
+	net_ipv6_nbr_data(nbr)->send_ns = 0;
+
+#if defined(CONFIG_NET_IPV6_ND)
+	net_ipv6_nbr_data(nbr)->reachable = 0;
+	net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
+#endif
+}
+
+static struct net_nbr *nbr_new(struct net_if *iface,
+			       const struct in6_addr *addr, bool is_router,
+			       enum net_ipv6_nbr_state state)
+{
+	struct net_nbr *nbr = net_nbr_get(&net_neighbor.table);
+
+	if (!nbr) {
+		return NULL;
+	}
+
+	nbr_init(nbr, iface, addr, is_router, state);
+
+	NET_DBG("nbr %p iface %p/%d state %d IPv6 %s",
+		nbr, iface, net_if_get_by_iface(iface), state,
+		log_strdup(net_sprint_ipv6_addr(addr)));
+
+	return nbr;
+}
+
+static void dbg_update_neighbor_lladdr(const struct net_linkaddr *new_lladdr,
+				       const struct net_linkaddr_storage *old_lladdr,
+				       const struct in6_addr *addr)
+{
+	char out[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+
+	snprintk(out, sizeof(out), "%s",
+		 net_sprint_ll_addr(old_lladdr->addr, old_lladdr->len));
+
+	NET_DBG("Updating neighbor %s lladdr %s (was %s)",
+		log_strdup(net_sprint_ipv6_addr(addr)),
+		log_strdup(net_sprint_ll_addr(new_lladdr->addr,
+					      new_lladdr->len)),
+		log_strdup(out));
+}
+
+static void dbg_update_neighbor_lladdr_raw(uint8_t *new_lladdr,
+				       struct net_linkaddr_storage *old_lladdr,
+				       struct in6_addr *addr)
+{
+	struct net_linkaddr lladdr = {
+		.len = old_lladdr->len,
+		.addr = new_lladdr,
+	};
+
+	dbg_update_neighbor_lladdr(&lladdr, old_lladdr, addr);
+}
+
+#define dbg_addr(action, pkt_str, src, dst, pkt)			\
+	do {								\
+		NET_DBG("%s %s from %s to %s iface %p/%d",		\
+			action, pkt_str,				\
+			log_strdup(net_sprint_ipv6_addr(src)),		\
+			log_strdup(net_sprint_ipv6_addr(dst)),		\
+			net_pkt_iface(pkt),				\
+			net_if_get_by_iface(net_pkt_iface(pkt)));	\
+	} while (0)
+
+#define dbg_addr_recv(pkt_str, src, dst, pkt)	\
+	dbg_addr("Received", pkt_str, src, dst, pkt)
+
+#define dbg_addr_sent(pkt_str, src, dst, pkt)	\
+	dbg_addr("Sent", pkt_str, src, dst, pkt)
+
+#define dbg_addr_with_tgt(action, pkt_str, src, dst, target, pkt)	\
+	do {								\
+		NET_DBG("%s %s from %s to %s, target %s iface %p/%d",	\
+			action,						\
+			pkt_str,                                        \
+			log_strdup(net_sprint_ipv6_addr(src)),		\
+			log_strdup(net_sprint_ipv6_addr(dst)),		\
+			log_strdup(net_sprint_ipv6_addr(target)),	\
+			net_pkt_iface(pkt),				\
+			net_if_get_by_iface(net_pkt_iface(pkt)));	\
+	} while (0)
+
+#define dbg_addr_recv_tgt(pkt_str, src, dst, tgt, pkt)		\
+	dbg_addr_with_tgt("Received", pkt_str, src, dst, tgt, pkt)
+
+#define dbg_addr_sent_tgt(pkt_str, src, dst, tgt, pkt)		\
+	dbg_addr_with_tgt("Sent", pkt_str, src, dst, tgt, pkt)
+
+static void ipv6_nd_remove_old_stale_nbr(void)
+{
+	struct net_nbr *nbr = NULL;
+	struct net_ipv6_nbr_data *data = NULL;
+	int nbr_idx = -1;
+	uint32_t oldest = UINT32_MAX;
+	int i;
+
+	k_sem_take(&nbr_lock, K_FOREVER);
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		nbr = get_nbr(i);
+		if (!nbr || !nbr->ref) {
+			continue;
+		}
+
+		data = net_ipv6_nbr_data(nbr);
+		if (!data || data->is_router ||
+		    data->state != NET_IPV6_NBR_STATE_STALE) {
+			continue;
+		}
+
+		if (nbr_idx == -1) {
+			nbr_idx = i;
+			oldest = data->stale_counter;
+			continue;
+		}
+
+		if (oldest == MIN(oldest, data->stale_counter)) {
+			continue;
+		}
+
+		nbr_idx = i;
+		oldest = data->stale_counter;
+	}
+
+	if (nbr_idx != -1) {
+		nbr = get_nbr(nbr_idx);
+		if (!nbr) {
+			return;
+		}
+
+		net_ipv6_nbr_rm(nbr->iface,
+				&net_ipv6_nbr_data(nbr)->addr);
+	}
+
+	k_sem_give(&nbr_lock);
+}
+
+static struct net_nbr *add_nbr(struct net_if *iface,
+			       const struct in6_addr *addr,
+			       bool is_router,
+			       enum net_ipv6_nbr_state state)
+{
+	struct net_nbr *nbr;
+
+	nbr = nbr_lookup(&net_neighbor.table, iface, addr);
+	if (nbr) {
+		return nbr;
+	}
+
+	nbr = nbr_new(iface, addr, is_router, state);
+	if (nbr) {
+		return nbr;
+	}
+
+	/* Check if there are any stale neighbors, delete the oldest
+	 * one and try to add new neighbor.
+	 */
+	ipv6_nd_remove_old_stale_nbr();
+
+	nbr = nbr_new(iface, addr, is_router, state);
+	if (!nbr) {
+		return NULL;
+	}
+
+	return nbr;
+}
+
+struct net_nbr *net_ipv6_nbr_add(struct net_if *iface,
+				 const struct in6_addr *addr,
+				 const struct net_linkaddr *lladdr,
+				 bool is_router,
+				 enum net_ipv6_nbr_state state)
+{
+	struct net_nbr *nbr;
+	int ret;
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	struct net_event_ipv6_nbr info;
+#endif
+
+	nbr = add_nbr(iface, addr, is_router, state);
+	if (!nbr) {
+		NET_ERR("Could not add router neighbor %s [%s]",
+			log_strdup(net_sprint_ipv6_addr(addr)),
+			log_strdup(net_sprint_ll_addr(lladdr->addr,
+						      lladdr->len)));
+		return NULL;
+	}
+
+	if (net_nbr_link(nbr, iface, lladdr) == -EALREADY &&
+	    net_ipv6_nbr_data(nbr)->state != NET_IPV6_NBR_STATE_STATIC) {
+		/* Update the lladdr if the node was already known */
+		struct net_linkaddr_storage *cached_lladdr;
+
+		cached_lladdr = net_nbr_get_lladdr(nbr->idx);
+
+		if (memcmp(cached_lladdr->addr, lladdr->addr, lladdr->len)) {
+			dbg_update_neighbor_lladdr(lladdr, cached_lladdr, addr);
+
+			net_linkaddr_set(cached_lladdr, lladdr->addr,
+					 lladdr->len);
+
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
+		} else if (net_ipv6_nbr_data(nbr)->state ==
+			   NET_IPV6_NBR_STATE_INCOMPLETE) {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
+		}
+	}
+
+	if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_INCOMPLETE) {
+		/* Send NS so that we can verify that the neighbor is
+		 * reachable.
+		 */
+		ret = net_ipv6_send_ns(iface, NULL, NULL, NULL, addr, false);
+		if (ret < 0) {
+			NET_DBG("Cannot send NS (%d)", ret);
+		}
+	}
+
+	NET_DBG("[%d] nbr %p state %d router %d IPv6 %s ll %s iface %p/%d",
+		nbr->idx, nbr, state, is_router,
+		log_strdup(net_sprint_ipv6_addr(addr)),
+		log_strdup(net_sprint_ll_addr(lladdr->addr, lladdr->len)),
+		nbr->iface, net_if_get_by_iface(nbr->iface));
+
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	info.idx = nbr->idx;
+	net_ipaddr_copy(&info.addr, addr);
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_NBR_ADD,
+					iface, (void *) &info,
+					sizeof(struct net_event_ipv6_nbr));
+#else
+	net_mgmt_event_notify(NET_EVENT_IPV6_NBR_ADD, iface);
+#endif
+
+	return nbr;
+}
+
+void net_neighbor_data_remove(struct net_nbr *nbr)
+{
+	NET_DBG("Neighbor %p removed", nbr);
+
+	return;
+}
+
+void net_neighbor_table_clear(struct net_nbr_table *table)
+{
+	NET_DBG("Neighbor table %p cleared", table);
+}
+
+struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
+					      uint8_t idx)
+{
+	int i;
+
+	if (idx == NET_NBR_LLADDR_UNKNOWN) {
+		return NULL;
+	}
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		if (iface && nbr->iface != iface) {
+			continue;
+		}
+
+		if (nbr->idx == idx) {
+			return &net_ipv6_nbr_data(nbr)->addr;
+		}
+	}
+
+	return NULL;
+}
+#else
+const char *net_ipv6_nbr_state2str(enum net_ipv6_nbr_state state)
+{
+	return "<unknown state>";
+}
+#endif /* CONFIG_NET_IPV6_NBR_CACHE */
+
+#if defined(CONFIG_NET_IPV6_DAD)
+int net_ipv6_start_dad(struct net_if *iface, struct net_if_addr *ifaddr)
+{
+	return net_ipv6_send_ns(iface, NULL, NULL, NULL,
+				&ifaddr->address.in6_addr, true);
+}
+
+static inline bool dad_failed(struct net_if *iface, struct in6_addr *addr)
+{
+	if (net_ipv6_is_ll_addr(addr)) {
+		NET_ERR("DAD failed, no ll IPv6 address!");
+		return false;
+	}
+
+	net_if_ipv6_dad_failed(iface, addr);
+
+	return true;
+}
+#endif /* CONFIG_NET_IPV6_DAD */
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE)
+static struct in6_addr *check_route(struct net_if *iface,
+				    struct in6_addr *dst,
+				    bool *try_route)
+{
+	struct in6_addr *nexthop = NULL;
+	struct net_route_entry *route;
+	struct net_if_router *router;
+
+	route = net_route_lookup(iface, dst);
+	if (route) {
+		nexthop = net_route_get_nexthop(route);
+
+		NET_DBG("Route %p nexthop %s iface %p/%d",
+			route,
+			nexthop ? log_strdup(net_sprint_ipv6_addr(nexthop)) :
+			"<unknown>",
+			iface, net_if_get_by_iface(iface));
+
+		if (!nexthop) {
+			net_route_del(route);
+
+			NET_DBG("No route to host %s",
+				log_strdup(net_sprint_ipv6_addr(dst)));
+
+			return NULL;
+		}
+	} else {
+		/* No specific route to this host, use the default
+		 * route instead.
+		 */
+		router = net_if_ipv6_router_find_default(NULL, dst);
+		if (!router) {
+			NET_DBG("No default route to %s",
+				log_strdup(net_sprint_ipv6_addr(dst)));
+
+			/* Try to send the packet anyway */
+			nexthop = dst;
+			if (try_route) {
+				*try_route = true;
+			}
+
+			return nexthop;
+		}
+
+		nexthop = &router->address.in6_addr;
+
+		NET_DBG("Router %p nexthop %s", router,
+			log_strdup(net_sprint_ipv6_addr(nexthop)));
+	}
+
+	return nexthop;
+}
+
+enum net_verdict net_ipv6_prepare_for_send(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct in6_addr *nexthop = NULL;
+	struct net_if *iface = NULL;
+	struct net_ipv6_hdr *ip_hdr;
+	struct net_nbr *nbr;
+	int ret;
+
+	NET_ASSERT(pkt && pkt->buffer);
+
+	ip_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!ip_hdr) {
+		return NET_DROP;
+	}
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+	/* If we have already fragmented the packet, the fragment id will
+	 * contain a proper value and we can skip other checks.
+	 */
+	if (net_pkt_ipv6_fragment_id(pkt) == 0U) {
+		uint16_t mtu = net_if_get_mtu(net_pkt_iface(pkt));
+		size_t pkt_len = net_pkt_get_len(pkt);
+
+		mtu = MAX(NET_IPV6_MTU, mtu);
+		if (mtu < pkt_len) {
+			ret = net_ipv6_send_fragmented_pkt(net_pkt_iface(pkt),
+							   pkt, pkt_len);
+			if (ret < 0) {
+				NET_DBG("Cannot fragment IPv6 pkt (%d)", ret);
+
+				if (ret == -ENOMEM) {
+					/* Try to send the packet if we could
+					 * not allocate enough network packets
+					 * and hope the original large packet
+					 * can be sent ok.
+					 */
+					goto ignore_frag_error;
+				}
+			}
+
+			/* We "fake" the sending of the packet here so that
+			 * tcp.c:tcp_retry_expired() will increase the ref
+			 * count when re-sending the packet. This is crucial
+			 * thing to do here and will cause free memory access
+			 * if not done.
+			 */
+			if (IS_ENABLED(CONFIG_NET_TCP)) {
+				net_pkt_set_sent(pkt, true);
+			}
+
+			/* We need to unref here because we simulate the packet
+			 * sending.
+			 */
+			net_pkt_unref(pkt);
+
+			/* No need to continue with the sending as the packet
+			 * is now split and its fragments will be sent
+			 * separately to network.
+			 */
+			return NET_CONTINUE;
+		}
+	}
+ignore_frag_error:
+#endif /* CONFIG_NET_IPV6_FRAGMENT */
+
+	/* If the IPv6 destination address is not link local, then try to get
+	 * the next hop from routing table if we have multi interface routing
+	 * enabled. The reason for this is that the neighbor cache will not
+	 * contain public IPv6 address information so in that case we should
+	 * not enter this branch.
+	 */
+	if ((net_pkt_lladdr_dst(pkt)->addr &&
+	     ((IS_ENABLED(CONFIG_NET_ROUTING) &&
+	      net_ipv6_is_ll_addr(&ip_hdr->dst)) ||
+	      !IS_ENABLED(CONFIG_NET_ROUTING))) ||
+	    net_ipv6_is_addr_mcast(&ip_hdr->dst) ||
+	    /* Workaround Linux bug, see:
+	     * https://github.com/zephyrproject-rtos/zephyr/issues/3111
+	     */
+	    net_if_flag_is_set(net_pkt_iface(pkt),
+			       NET_IF_POINTOPOINT)) {
+		return NET_OK;
+	}
+
+	if (net_if_ipv6_addr_onlink(&iface, &ip_hdr->dst)) {
+		nexthop = &ip_hdr->dst;
+		net_pkt_set_iface(pkt, iface);
+	} else {
+		/* We need to figure out where the destination
+		 * host is located.
+		 */
+		bool try_route = false;
+
+		nexthop = check_route(NULL, &ip_hdr->dst, &try_route);
+		if (!nexthop) {
+			return NET_DROP;
+		}
+
+		if (try_route) {
+			goto try_send;
+		}
+	}
+
+	if (!iface) {
+		/* This means that the dst was not onlink, so try to
+		 * figure out the interface using nexthop instead.
+		 */
+		if (net_if_ipv6_addr_onlink(&iface, nexthop)) {
+			net_pkt_set_iface(pkt, iface);
+		} else {
+			/* nexthop might be the nbr list, e.g. a link-local
+			 * address of a connected peer.
+			 */
+			nbr = net_ipv6_nbr_lookup(NULL, nexthop);
+			if (nbr) {
+				iface = nbr->iface;
+				net_pkt_set_iface(pkt, iface);
+			} else {
+				iface = net_pkt_iface(pkt);
+			}
+		}
+
+		/* If the above check returns null, we try to send
+		 * the packet and hope for the best.
+		 */
+	}
+
+try_send:
+	nbr = nbr_lookup(&net_neighbor.table, iface, nexthop);
+
+	NET_DBG("Neighbor lookup %p (%d) iface %p/%d addr %s state %s", nbr,
+		nbr ? nbr->idx : NET_NBR_LLADDR_UNKNOWN,
+		iface, net_if_get_by_iface(iface),
+		log_strdup(net_sprint_ipv6_addr(nexthop)),
+		nbr ? net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state) :
+		"-");
+
+	if (nbr && nbr->idx != NET_NBR_LLADDR_UNKNOWN) {
+		struct net_linkaddr_storage *lladdr;
+
+		lladdr = net_nbr_get_lladdr(nbr->idx);
+
+		net_pkt_lladdr_dst(pkt)->addr = lladdr->addr;
+		net_pkt_lladdr_dst(pkt)->len = lladdr->len;
+
+		NET_DBG("Neighbor %p addr %s", nbr,
+			log_strdup(net_sprint_ll_addr(lladdr->addr,
+						      lladdr->len)));
+
+		/* Start the NUD if we are in STALE state.
+		 * See RFC 4861 ch 7.3.3 for details.
+		 */
+#if defined(CONFIG_NET_IPV6_ND)
+		if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_STALE) {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_DELAY);
+
+			ipv6_nd_restart_reachable_timer(nbr,
+							DELAY_FIRST_PROBE_TIME);
+		}
+#endif
+		return NET_OK;
+	}
+
+#if defined(CONFIG_NET_IPV6_ND)
+	/* We need to send NS and wait for NA before sending the packet. */
+	ret = net_ipv6_send_ns(net_pkt_iface(pkt), pkt,
+			       &ip_hdr->src, NULL, nexthop, false);
+	if (ret < 0) {
+		/* In case of an error, the NS send function will unref
+		 * the pkt.
+		 */
+		NET_DBG("Cannot send NS (%d) iface %p/%d",
+			ret, net_pkt_iface(pkt),
+			net_if_get_by_iface(net_pkt_iface(pkt)));
+	}
+
+	NET_DBG("pkt %p (buffer %p) will be sent later to iface %p/%d",
+		pkt, pkt->buffer, net_pkt_iface(pkt),
+		net_if_get_by_iface(net_pkt_iface(pkt)));
+
+	return NET_CONTINUE;
+#else
+	ARG_UNUSED(ret);
+
+	NET_DBG("pkt %p (buffer %p) cannot be sent to iface %p/%d, "
+		"dropping it.", pkt, pkt->buffer,
+		net_pkt_iface(pkt), net_if_get_by_iface(net_pkt_iface(pkt)));
+
+	return NET_DROP;
+#endif /* CONFIG_NET_IPV6_ND */
+}
+
+struct net_nbr *net_ipv6_nbr_lookup(struct net_if *iface,
+				    struct in6_addr *addr)
+{
+	return nbr_lookup(&net_neighbor.table, iface, addr);
+}
+
+struct net_nbr *net_ipv6_get_nbr(struct net_if *iface, uint8_t idx)
+{
+	int i;
+
+	if (idx == NET_NBR_LLADDR_UNKNOWN) {
+		return NULL;
+	}
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (nbr->ref) {
+			if (iface && nbr->iface != iface) {
+				continue;
+			}
+
+			if (nbr->idx == idx) {
+				return nbr;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static inline uint8_t get_llao_len(struct net_if *iface)
+{
+	uint8_t total_len = net_if_get_link_addr(iface)->len +
+			 sizeof(struct net_icmpv6_nd_opt_hdr);
+
+	return ROUND_UP(total_len, 8U);
+}
+
+static inline bool set_llao(struct net_pkt *pkt,
+			    struct net_linkaddr *lladdr,
+			    uint8_t llao_len, uint8_t type)
+{
+	struct net_icmpv6_nd_opt_hdr opt_hdr = {
+		.type = type,
+		.len  = llao_len >> 3,
+	};
+
+	if (net_pkt_write(pkt, &opt_hdr,
+			  sizeof(struct net_icmpv6_nd_opt_hdr)) ||
+	    net_pkt_write(pkt, lladdr->addr, lladdr->len) ||
+	    net_pkt_memset(pkt, 0, llao_len - lladdr->len - 2)) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool read_llao(struct net_pkt *pkt,
+		      uint8_t len,
+		      struct net_linkaddr_storage *llstorage)
+{
+	uint8_t padding;
+
+	llstorage->len = NET_LINK_ADDR_MAX_LENGTH;
+	if (net_pkt_lladdr_src(pkt)->len < llstorage->len) {
+		llstorage->len = net_pkt_lladdr_src(pkt)->len;
+	}
+
+	if (net_pkt_read(pkt, llstorage->addr, llstorage->len)) {
+		return false;
+	}
+
+	padding = len * 8U - 2 - llstorage->len;
+	if (padding) {
+		if (net_pkt_skip(pkt, padding)) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+int net_ipv6_send_na(struct net_if *iface, const struct in6_addr *src,
+		     const struct in6_addr *dst, const struct in6_addr *tgt,
+		     uint8_t flags)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(na_access,
+					      struct net_icmpv6_na_hdr);
+	int ret = -ENOBUFS;
+	struct net_icmpv6_na_hdr *na_hdr;
+	struct net_pkt *pkt;
+	uint8_t llao_len;
+
+	llao_len = get_llao_len(iface);
+
+	pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_icmpv6_na_hdr) +
+					llao_len,
+					AF_INET6, IPPROTO_ICMPV6,
+					ND_NET_BUF_TIMEOUT);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
+
+	if (net_ipv6_create(pkt, src, dst) ||
+	    net_icmpv6_create(pkt, NET_ICMPV6_NA, 0)) {
+		goto drop;
+	}
+
+	na_hdr = (struct net_icmpv6_na_hdr *)net_pkt_get_data(pkt, &na_access);
+	if (!na_hdr) {
+		goto drop;
+	}
+
+	/* Let's make sure reserved part is full of 0 */
+	memset(na_hdr, 0, sizeof(struct net_icmpv6_na_hdr));
+
+	na_hdr->flags = flags;
+	net_ipaddr_copy(&na_hdr->tgt, tgt);
+
+	if (net_pkt_set_data(pkt, &na_access)) {
+		goto drop;
+	}
+
+	if (!set_llao(pkt, net_if_get_link_addr(iface),
+		      llao_len, NET_ICMPV6_ND_OPT_TLLAO)) {
+		goto drop;
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	dbg_addr_sent_tgt("Neighbor Advertisement", src, dst, &na_hdr->tgt,
+			  pkt);
+
+	if (net_send_data(pkt) < 0) {
+		net_stats_update_ipv6_nd_drop(iface);
+		ret = -EINVAL;
+
+		goto drop;
+	}
+
+	net_stats_update_ipv6_nd_sent(iface);
+
+	return 0;
+
+drop:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+static void ns_routing_info(struct net_pkt *pkt,
+			    struct in6_addr *nexthop,
+			    struct in6_addr *tgt)
+{
+	if (CONFIG_NET_IPV6_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		char out[NET_IPV6_ADDR_LEN];
+
+		snprintk(out, sizeof(out), "%s",
+			 net_sprint_ipv6_addr(nexthop));
+
+		if (net_ipv6_addr_cmp(nexthop, tgt)) {
+			NET_DBG("Routing to %s iface %p/%d",
+				log_strdup(out),
+				net_pkt_iface(pkt),
+				net_if_get_by_iface(net_pkt_iface(pkt)));
+		} else {
+			NET_DBG("Routing to %s via %s iface %p/%d",
+				log_strdup(net_sprint_ipv6_addr(tgt)),
+				log_strdup(out),
+				net_pkt_iface(pkt),
+				net_if_get_by_iface(net_pkt_iface(pkt)));
+		}
+	}
+}
+
+static enum net_verdict handle_ns_input(struct net_pkt *pkt,
+					struct net_ipv6_hdr *ip_hdr,
+					struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ns_access,
+					      struct net_icmpv6_ns_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
+	uint16_t length = net_pkt_get_len(pkt);
+	uint8_t flags = 0U;
+	bool routing = false;
+	struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
+	struct net_icmpv6_ns_hdr *ns_hdr;
+	struct net_if_addr *ifaddr;
+	const struct in6_addr *na_src;
+	const struct in6_addr *na_dst;
+	struct in6_addr *tgt;
+	struct net_linkaddr_storage src_lladdr_s;
+	struct net_linkaddr src_lladdr;
+
+	src_lladdr.len = 0;
+
+	ns_hdr = (struct net_icmpv6_ns_hdr *)net_pkt_get_data(pkt, &ns_access);
+	if (!ns_hdr) {
+		NET_ERR("DROP: NULL NS header");
+		goto drop;
+	}
+
+	dbg_addr_recv_tgt("Neighbor Solicitation",
+			  &ip_hdr->src, &ip_hdr->dst, &ns_hdr->tgt, pkt);
+
+	net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
+
+	if (((length < (sizeof(struct net_ipv6_hdr) +
+			  sizeof(struct net_icmp_hdr) +
+			  sizeof(struct net_icmpv6_ns_hdr))) ||
+	    (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT)) &&
+	    (net_ipv6_is_addr_mcast(&ns_hdr->tgt) && icmp_hdr->code != 0U)) {
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &ns_access);
+
+	net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_ns_hdr));
+	length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
+
+	nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+				net_pkt_get_data(pkt, &nd_access);
+
+	while (nd_opt_hdr && nd_opt_hdr->len > 0 &&
+	       net_pkt_ipv6_ext_opt_len(pkt) < length) {
+		uint8_t prev_opt_len;
+
+		net_pkt_acknowledge_data(pkt, &nd_access);
+
+		switch (nd_opt_hdr->type) {
+		case NET_ICMPV6_ND_OPT_SLLAO:
+			if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
+				goto drop;
+			}
+
+			if (!read_llao(pkt, nd_opt_hdr->len, &src_lladdr_s)) {
+				NET_ERR("DROP: failed to read LLAO");
+				goto drop;
+			}
+
+			src_lladdr.len = src_lladdr_s.len;
+			src_lladdr.addr = src_lladdr_s.addr;
+
+			break;
+		default:
+			NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
+			break;
+		}
+
+		prev_opt_len = net_pkt_ipv6_ext_opt_len(pkt);
+
+		net_pkt_set_ipv6_ext_opt_len(pkt,
+					     net_pkt_ipv6_ext_opt_len(pkt) +
+					     (nd_opt_hdr->len << 3));
+
+		if (prev_opt_len >= net_pkt_ipv6_ext_opt_len(pkt)) {
+			NET_ERR("DROP: Corrupted NS message");
+			goto drop;
+		}
+
+		nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+					net_pkt_get_data(pkt, &nd_access);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_ROUTING)) {
+		ifaddr = net_if_ipv6_addr_lookup(&ns_hdr->tgt, NULL);
+	} else {
+		ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
+							  &ns_hdr->tgt);
+	}
+
+	if (!ifaddr) {
+		if (IS_ENABLED(CONFIG_NET_ROUTING)) {
+			struct in6_addr *nexthop;
+
+			nexthop = check_route(NULL, &ns_hdr->tgt, NULL);
+			if (nexthop) {
+				ns_routing_info(pkt, nexthop, &ns_hdr->tgt);
+				na_dst = &ip_hdr->dst;
+				/* Note that the target is not the address of
+				 * the "nethop" as that is a link-local address
+				 * which is not routable.
+				 */
+				tgt = &ns_hdr->tgt;
+
+				/* Source address must be one of our real
+				 * interface address where the packet was
+				 * received.
+				 */
+				na_src = net_if_ipv6_select_src_addr(
+					net_pkt_iface(pkt), &ip_hdr->src);
+				if (!na_src) {
+					NET_DBG("DROP: No interface address "
+						"for dst %s iface %p/%d",
+						log_strdup(
+						  net_sprint_ipv6_addr(
+							  &ip_hdr->src)),
+						net_pkt_iface(pkt),
+						net_if_get_by_iface(
+							net_pkt_iface(pkt)));
+					goto drop;
+				}
+
+				routing = true;
+				goto nexthop_found;
+			}
+		}
+
+		NET_DBG("DROP: No such interface address %s",
+			log_strdup(net_sprint_ipv6_addr(&ns_hdr->tgt)));
+		goto drop;
+	} else {
+		tgt = &ifaddr->address.in6_addr;
+		na_src = &ip_hdr->dst;
+	}
+
+nexthop_found:
+
+#if !defined(CONFIG_NET_IPV6_DAD)
+	if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
+		goto drop;
+	}
+
+#else /* CONFIG_NET_IPV6_DAD */
+
+	/* Do DAD */
+	if (net_ipv6_is_addr_unspecified(&ip_hdr->src)) {
+
+		if (!net_ipv6_is_addr_solicited_node(&ip_hdr->dst)) {
+			NET_DBG("DROP: Not solicited node addr %s",
+				log_strdup(net_sprint_ipv6_addr(&ip_hdr->dst)));
+			goto drop;
+		}
+
+		if (ifaddr->addr_state == NET_ADDR_TENTATIVE) {
+			NET_DBG("DROP: DAD failed for %s iface %p/%d",
+				log_strdup(net_sprint_ipv6_addr(
+						   &ifaddr->address.in6_addr)),
+				net_pkt_iface(pkt),
+				net_if_get_by_iface(net_pkt_iface(pkt)));
+
+			dad_failed(net_pkt_iface(pkt),
+				   &ifaddr->address.in6_addr);
+			goto drop;
+		}
+
+		/* We reuse the received packet for the NA addresses*/
+		net_ipv6_addr_create_ll_allnodes_mcast(&ip_hdr->dst);
+		net_ipaddr_copy(&ip_hdr->src,
+				net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
+							    &ip_hdr->dst));
+		na_src = &ip_hdr->src;
+		na_dst = &ip_hdr->dst;
+		flags = NET_ICMPV6_NA_FLAG_OVERRIDE;
+		goto send_na;
+	}
+#endif /* CONFIG_NET_IPV6_DAD */
+
+	if (net_ipv6_is_my_addr(&ip_hdr->src)) {
+		NET_DBG("DROP: Duplicate IPv6 %s address",
+			log_strdup(net_sprint_ipv6_addr(&ip_hdr->src)));
+		goto drop;
+	}
+
+	/* Address resolution */
+	if (net_ipv6_is_addr_solicited_node(&ip_hdr->dst)) {
+		na_src = &ns_hdr->tgt;
+		na_dst = &ip_hdr->src;
+		flags = NET_ICMPV6_NA_FLAG_SOLICITED |
+			NET_ICMPV6_NA_FLAG_OVERRIDE;
+		goto send_na;
+	}
+
+	if (routing) {
+		/* No need to do NUD here when the target is being routed. */
+		goto send_na;
+	}
+
+	/* Neighbor Unreachability Detection (NUD) */
+	if (IS_ENABLED(CONFIG_NET_ROUTING)) {
+		ifaddr = net_if_ipv6_addr_lookup(&ip_hdr->dst, NULL);
+	} else {
+		ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
+							  &ip_hdr->dst);
+	}
+
+	if (ifaddr) {
+		na_src = &ns_hdr->tgt;
+		na_dst = &ip_hdr->src;
+		tgt = &ifaddr->address.in6_addr;
+		flags = NET_ICMPV6_NA_FLAG_SOLICITED |
+			NET_ICMPV6_NA_FLAG_OVERRIDE;
+		goto send_na;
+	} else {
+		NET_DBG("DROP: NUD failed");
+		goto drop;
+	}
+
+send_na:
+	if (src_lladdr.len) {
+		if (!net_ipv6_nbr_add(net_pkt_iface(pkt),
+				      &ip_hdr->src,
+				      &src_lladdr, false,
+				      NET_IPV6_NBR_STATE_INCOMPLETE)) {
+			goto drop;
+		}
+	}
+
+	if (!net_ipv6_send_na(net_pkt_iface(pkt), na_src,
+			      na_dst, tgt, flags)) {
+		net_pkt_unref(pkt);
+		return NET_OK;
+	}
+
+	NET_DBG("DROP: Cannot send NA");
+
+	return NET_DROP;
+
+drop:
+	net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+#endif /* CONFIG_NET_IPV6_NBR_CACHE */
+
+#if defined(CONFIG_NET_IPV6_ND)
+static void ipv6_nd_restart_reachable_timer(struct net_nbr *nbr, int64_t time)
+{
+	int64_t remaining;
+
+	if (nbr) {
+		net_ipv6_nbr_data(nbr)->reachable = k_uptime_get();
+		net_ipv6_nbr_data(nbr)->reachable_timeout = time;
+	}
+
+	remaining = k_delayed_work_remaining_get(&ipv6_nd_reachable_timer);
+	if (!remaining || remaining > time) {
+		k_delayed_work_submit(&ipv6_nd_reachable_timer, K_MSEC(time));
+	}
+}
+
+static void ipv6_nd_reachable_timeout(struct k_work *work)
+{
+	int64_t current = k_uptime_get();
+	struct net_nbr *nbr = NULL;
+	struct net_ipv6_nbr_data *data = NULL;
+	int ret;
+	int i;
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		int64_t remaining;
+
+		nbr = get_nbr(i);
+		if (!nbr || !nbr->ref) {
+			continue;
+		}
+
+		data = net_ipv6_nbr_data(nbr);
+		if (!data) {
+			continue;
+		}
+
+		if (!data->reachable) {
+			continue;
+		}
+
+		remaining = data->reachable + data->reachable_timeout - current;
+		if (remaining > 0) {
+			ipv6_nd_restart_reachable_timer(NULL, remaining);
+			continue;
+		}
+
+		data->reachable = 0;
+
+		switch (data->state) {
+		case NET_IPV6_NBR_STATE_STATIC:
+			NET_ASSERT(false, "Static entry shall never timeout");
+			break;
+
+		case NET_IPV6_NBR_STATE_INCOMPLETE:
+			if (data->ns_count >= MAX_MULTICAST_SOLICIT) {
+				net_ipv6_nbr_rm(nbr->iface, &data->addr);
+			} else {
+				data->ns_count++;
+
+				NET_DBG("nbr %p incomplete count %u", nbr,
+					data->ns_count);
+
+				ret = net_ipv6_send_ns(nbr->iface, NULL, NULL,
+						       NULL, &data->addr,
+						       false);
+				if (ret < 0) {
+					NET_DBG("Cannot send NS (%d)", ret);
+				}
+			}
+			break;
+
+		case NET_IPV6_NBR_STATE_REACHABLE:
+			data->state = NET_IPV6_NBR_STATE_STALE;
+
+			NET_DBG("nbr %p moving %s state to STALE (%d)",
+				nbr,
+				log_strdup(net_sprint_ipv6_addr(&data->addr)),
+				data->state);
+			break;
+
+		case NET_IPV6_NBR_STATE_STALE:
+			NET_DBG("nbr %p removing stale address %s",
+				nbr,
+				log_strdup(net_sprint_ipv6_addr(&data->addr)));
+			net_ipv6_nbr_rm(nbr->iface, &data->addr);
+			break;
+
+		case NET_IPV6_NBR_STATE_DELAY:
+			data->state = NET_IPV6_NBR_STATE_PROBE;
+			data->ns_count = 0U;
+
+			NET_DBG("nbr %p moving %s state to PROBE (%d)",
+				nbr,
+				log_strdup(net_sprint_ipv6_addr(&data->addr)),
+				data->state);
+
+			/* Intentionally continuing to probe state */
+			__fallthrough;
+
+		case NET_IPV6_NBR_STATE_PROBE:
+			if (data->ns_count >= MAX_UNICAST_SOLICIT) {
+				net_ipv6_nbr_rm(nbr->iface, &data->addr);
+			} else {
+				data->ns_count++;
+
+				NET_DBG("nbr %p probe count %u", nbr,
+					data->ns_count);
+
+				ret = net_ipv6_send_ns(nbr->iface, NULL, NULL,
+						       NULL, &data->addr,
+						       false);
+				if (ret < 0) {
+					NET_DBG("Cannot send NS (%d)", ret);
+				}
+
+				ipv6_nd_restart_reachable_timer(nbr,
+								RETRANS_TIMER);
+			}
+			break;
+		}
+	}
+}
+
+void net_ipv6_nbr_set_reachable_timer(struct net_if *iface,
+				      struct net_nbr *nbr)
+{
+	uint32_t time;
+
+	time = net_if_ipv6_get_reachable_time(iface);
+
+	NET_ASSERT(time, "Zero reachable timeout!");
+
+	NET_DBG("Starting reachable timer nbr %p data %p time %d ms",
+		nbr, net_ipv6_nbr_data(nbr), time);
+
+	ipv6_nd_restart_reachable_timer(nbr, time);
+}
+#endif /* CONFIG_NET_IPV6_ND */
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE)
+static inline bool handle_na_neighbor(struct net_pkt *pkt,
+				      struct net_icmpv6_na_hdr *na_hdr,
+				      uint16_t tllao_offset)
+{
+	struct net_linkaddr_storage lladdr = { 0 };
+	bool lladdr_changed = false;
+	struct net_linkaddr_storage *cached_lladdr;
+	struct net_pkt *pending;
+	struct net_nbr *nbr;
+
+	nbr = nbr_lookup(&net_neighbor.table, net_pkt_iface(pkt), &na_hdr->tgt);
+
+	NET_DBG("Neighbor lookup %p iface %p/%d addr %s", nbr,
+		net_pkt_iface(pkt), net_if_get_by_iface(net_pkt_iface(pkt)),
+		log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)));
+
+	if (!nbr) {
+		nbr_print();
+
+		NET_DBG("No such neighbor found, msg discarded");
+		return false;
+	}
+
+	if (tllao_offset) {
+		lladdr.len = net_pkt_lladdr_src(pkt)->len;
+
+		net_pkt_cursor_init(pkt);
+
+		if (net_pkt_skip(pkt, tllao_offset) ||
+		    net_pkt_read(pkt, lladdr.addr, lladdr.len)) {
+			return false;
+		}
+	}
+
+	if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
+		struct net_linkaddr nbr_lladdr;
+
+		if (!tllao_offset) {
+			NET_DBG("No target link layer address.");
+			return false;
+		}
+
+		nbr_lladdr.len = lladdr.len;
+		nbr_lladdr.addr = lladdr.addr;
+
+		if (net_nbr_link(nbr, net_pkt_iface(pkt), &nbr_lladdr)) {
+			nbr_free(nbr);
+			return false;
+		}
+
+		NET_DBG("[%d] nbr %p state %d IPv6 %s ll %s",
+			nbr->idx, nbr, net_ipv6_nbr_data(nbr)->state,
+			log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)),
+			log_strdup(net_sprint_ll_addr(nbr_lladdr.addr,
+						      nbr_lladdr.len)));
+	}
+
+	cached_lladdr = net_nbr_get_lladdr(nbr->idx);
+	if (!cached_lladdr) {
+		NET_DBG("No lladdr but index defined");
+		return false;
+	}
+
+	if (tllao_offset) {
+		lladdr_changed = memcmp(lladdr.addr,
+					cached_lladdr->addr,
+					cached_lladdr->len);
+	}
+
+	/* Update the cached address if we do not yet known it */
+	if (net_ipv6_nbr_data(nbr)->state == NET_IPV6_NBR_STATE_INCOMPLETE) {
+		if (!tllao_offset) {
+			return false;
+		}
+
+		if (lladdr_changed) {
+			dbg_update_neighbor_lladdr_raw(lladdr.addr,
+						       cached_lladdr,
+						       &na_hdr->tgt);
+
+			net_linkaddr_set(cached_lladdr, lladdr.addr,
+					 cached_lladdr->len);
+		}
+
+		if (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED) {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
+			net_ipv6_nbr_data(nbr)->ns_count = 0U;
+
+			/* We might have active timer from PROBE */
+			net_ipv6_nbr_data(nbr)->reachable = 0;
+			net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
+
+			net_ipv6_nbr_set_reachable_timer(net_pkt_iface(pkt),
+							 nbr);
+		} else {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
+		}
+
+		net_ipv6_nbr_data(nbr)->is_router =
+			(na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER);
+
+		goto send_pending;
+	}
+
+	/* We do not update the address if override bit is not set
+	 * and we have a valid address in the cache.
+	 */
+	if (!(na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE) && lladdr_changed) {
+		if (net_ipv6_nbr_data(nbr)->state ==
+		    NET_IPV6_NBR_STATE_REACHABLE) {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_STALE);
+		}
+
+		return false;
+	}
+
+	if (na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE ||
+	    (!(na_hdr->flags & NET_ICMPV6_NA_FLAG_OVERRIDE) &&
+	     tllao_offset && !lladdr_changed)) {
+
+		if (lladdr_changed) {
+			dbg_update_neighbor_lladdr_raw(
+				lladdr.addr, cached_lladdr, &na_hdr->tgt);
+
+			net_linkaddr_set(cached_lladdr, lladdr.addr,
+					 cached_lladdr->len);
+		}
+
+		if (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED) {
+			ipv6_nbr_set_state(nbr, NET_IPV6_NBR_STATE_REACHABLE);
+
+			/* We might have active timer from PROBE */
+			net_ipv6_nbr_data(nbr)->reachable = 0;
+			net_ipv6_nbr_data(nbr)->reachable_timeout = 0;
+
+			net_ipv6_nbr_set_reachable_timer(net_pkt_iface(pkt),
+							 nbr);
+		} else {
+			if (lladdr_changed) {
+				ipv6_nbr_set_state(nbr,
+						   NET_IPV6_NBR_STATE_STALE);
+			}
+		}
+	}
+
+	if (net_ipv6_nbr_data(nbr)->is_router &&
+	    !(na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER)) {
+		/* Update the routing if the peer is no longer
+		 * a router.
+		 */
+		/* FIXME */
+	}
+
+	net_ipv6_nbr_data(nbr)->is_router =
+		(na_hdr->flags & NET_ICMPV6_NA_FLAG_ROUTER);
+
+send_pending:
+	/* Next send any pending messages to the peer. */
+	pending = net_ipv6_nbr_data(nbr)->pending;
+	if (pending) {
+		NET_DBG("Sending pending %p to lladdr %s", pending,
+			log_strdup(net_sprint_ll_addr(cached_lladdr->addr,
+						      cached_lladdr->len)));
+
+		if (net_send_data(pending) < 0) {
+			nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
+		} else {
+			net_ipv6_nbr_data(nbr)->pending = NULL;
+		}
+
+		net_pkt_unref(pending);
+	}
+
+	return true;
+}
+
+static enum net_verdict handle_na_input(struct net_pkt *pkt,
+					struct net_ipv6_hdr *ip_hdr,
+					struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(na_access,
+					      struct net_icmpv6_na_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
+	uint16_t length = net_pkt_get_len(pkt);
+	uint16_t tllao_offset = 0U;
+	struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
+	struct net_icmpv6_na_hdr *na_hdr;
+	struct net_if_addr *ifaddr;
+
+	na_hdr = (struct net_icmpv6_na_hdr *)net_pkt_get_data(pkt, &na_access);
+	if (!na_hdr) {
+		NET_ERR("DROP: NULL NA header");
+		goto drop;
+	}
+
+	dbg_addr_recv_tgt("Neighbor Advertisement",
+			  &ip_hdr->src, &ip_hdr->dst, &na_hdr->tgt, pkt);
+
+	net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
+
+	if (((length < (sizeof(struct net_ipv6_hdr) +
+			sizeof(struct net_icmp_hdr) +
+			sizeof(struct net_icmpv6_na_hdr) +
+			sizeof(struct net_icmpv6_nd_opt_hdr))) ||
+	     (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT) ||
+	     net_ipv6_is_addr_mcast(&na_hdr->tgt) ||
+	     (na_hdr->flags & NET_ICMPV6_NA_FLAG_SOLICITED &&
+	      net_ipv6_is_addr_mcast(&ip_hdr->dst))) &&
+	    (icmp_hdr->code != 0U)) {
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &na_access);
+
+	net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_na_hdr));
+	length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
+
+	nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+				net_pkt_get_data(pkt, &nd_access);
+
+	while (nd_opt_hdr && nd_opt_hdr->len &&
+	       net_pkt_ipv6_ext_opt_len(pkt) < length) {
+		uint8_t prev_opt_len;
+
+		switch (nd_opt_hdr->type) {
+		case NET_ICMPV6_ND_OPT_TLLAO:
+			tllao_offset = net_pkt_ip_hdr_len(pkt) +
+				net_pkt_ipv6_ext_len(pkt) +
+				sizeof(struct net_icmp_hdr) +
+				net_pkt_ipv6_ext_opt_len(pkt) + 1 + 1;
+			break;
+
+		default:
+			NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
+			break;
+		}
+
+		prev_opt_len = net_pkt_ipv6_ext_opt_len(pkt);
+
+		net_pkt_set_ipv6_ext_opt_len(pkt,
+					     net_pkt_ipv6_ext_opt_len(pkt) +
+					     (nd_opt_hdr->len << 3));
+
+		if (prev_opt_len >= net_pkt_ipv6_ext_opt_len(pkt)) {
+			NET_ERR("DROP: Corrupted NA message");
+			goto drop;
+		}
+
+		net_pkt_acknowledge_data(pkt, &nd_access);
+		nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+					net_pkt_get_data(pkt, &nd_access);
+	}
+
+	ifaddr = net_if_ipv6_addr_lookup_by_iface(net_pkt_iface(pkt),
+						  &na_hdr->tgt);
+	if (ifaddr) {
+		NET_DBG("Interface %p/%d already has address %s",
+			net_pkt_iface(pkt),
+			net_if_get_by_iface(net_pkt_iface(pkt)),
+			log_strdup(net_sprint_ipv6_addr(&na_hdr->tgt)));
+
+#if defined(CONFIG_NET_IPV6_DAD)
+		if (ifaddr->addr_state == NET_ADDR_TENTATIVE) {
+			dad_failed(net_pkt_iface(pkt), &na_hdr->tgt);
+		}
+#endif /* CONFIG_NET_IPV6_DAD */
+
+		goto drop;
+	}
+
+	if (!handle_na_neighbor(pkt, na_hdr, tllao_offset)) {
+		goto drop;
+	}
+
+	net_stats_update_ipv6_nd_sent(net_pkt_iface(pkt));
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+
+drop:
+	net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+int net_ipv6_send_ns(struct net_if *iface,
+		     struct net_pkt *pending,
+		     const struct in6_addr *src,
+		     const struct in6_addr *dst,
+		     const struct in6_addr *tgt,
+		     bool is_my_address)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ns_access,
+					      struct net_icmpv6_ns_hdr);
+	struct net_pkt *pkt = NULL;
+	int ret = -ENOBUFS;
+	struct net_icmpv6_ns_hdr *ns_hdr;
+	struct in6_addr node_dst;
+	struct net_nbr *nbr;
+	uint8_t llao_len;
+
+	if (!dst) {
+		net_ipv6_addr_create_solicited_node(tgt, &node_dst);
+		dst = &node_dst;
+	}
+
+	llao_len = get_llao_len(iface);
+
+	if (is_my_address) {
+		src = net_ipv6_unspecified_address();
+		llao_len = 0U;
+	} else {
+		if (!src) {
+			src = net_if_ipv6_select_src_addr(iface, tgt);
+		}
+
+		if (net_ipv6_is_addr_unspecified(src)) {
+			NET_DBG("No source address for NS (tgt %s)",
+				log_strdup(net_sprint_ipv6_addr(tgt)));
+			ret = -EINVAL;
+
+			goto drop;
+		}
+	}
+
+	pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_icmpv6_ns_hdr) +
+					llao_len,
+					AF_INET6, IPPROTO_ICMPV6,
+					ND_NET_BUF_TIMEOUT);
+	if (!pkt) {
+		ret = -ENOMEM;
+		goto drop;
+	}
+
+	net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
+
+	if (net_ipv6_create(pkt, src, dst) ||
+	    net_icmpv6_create(pkt, NET_ICMPV6_NS, 0)) {
+		goto drop;
+	}
+
+	ns_hdr = (struct net_icmpv6_ns_hdr *)net_pkt_get_data(pkt, &ns_access);
+	if (!ns_hdr) {
+		goto drop;
+	}
+
+	ns_hdr->reserved = 0U;
+	net_ipaddr_copy(&ns_hdr->tgt, tgt);
+
+	if (net_pkt_set_data(pkt, &ns_access)) {
+		goto drop;
+	}
+
+	if (!is_my_address) {
+		if (!set_llao(pkt, net_if_get_link_addr(iface),
+			      llao_len, NET_ICMPV6_ND_OPT_SLLAO)) {
+			goto drop;
+		}
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	nbr = add_nbr(iface, &ns_hdr->tgt, false,
+		      NET_IPV6_NBR_STATE_INCOMPLETE);
+	if (!nbr) {
+		NET_DBG("Could not create new neighbor %s",
+			log_strdup(net_sprint_ipv6_addr(&ns_hdr->tgt)));
+		goto drop;
+	}
+
+	if (pending) {
+		if (!net_ipv6_nbr_data(nbr)->pending) {
+			net_ipv6_nbr_data(nbr)->pending = net_pkt_ref(pending);
+		} else {
+			NET_DBG("Packet %p already pending for "
+				"operation. Discarding pending %p and pkt %p",
+				net_ipv6_nbr_data(nbr)->pending, pending, pkt);
+			goto drop;
+		}
+
+		NET_DBG("Setting timeout %d for NS", NS_REPLY_TIMEOUT);
+
+		net_ipv6_nbr_data(nbr)->send_ns = k_uptime_get();
+
+		/* Let's start the timer if necessary */
+		if (!k_delayed_work_remaining_get(&ipv6_ns_reply_timer)) {
+			k_delayed_work_submit(&ipv6_ns_reply_timer,
+					      K_MSEC(NS_REPLY_TIMEOUT));
+		}
+	}
+
+	dbg_addr_sent_tgt("Neighbor Solicitation", src, dst, &ns_hdr->tgt,
+			  pkt);
+
+	if (net_send_data(pkt) < 0) {
+		NET_DBG("Cannot send NS %p (pending %p)", pkt, pending);
+
+		if (pending) {
+			nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
+			pending = NULL;
+		}
+
+		goto drop;
+	}
+
+	net_stats_update_ipv6_nd_sent(iface);
+
+	return 0;
+
+drop:
+	if (pending) {
+		net_pkt_unref(pending);
+	}
+
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	net_stats_update_ipv6_nd_drop(iface);
+
+	return ret;
+}
+#endif /* CONFIG_NET_IPV6_NBR_CACHE */
+
+#if defined(CONFIG_NET_IPV6_ND)
+int net_ipv6_send_rs(struct net_if *iface)
+{
+	uint8_t llao_len = 0U;
+	int ret = -ENOBUFS;
+	const struct in6_addr *src;
+	struct in6_addr dst;
+	struct net_pkt *pkt;
+
+	net_ipv6_addr_create_ll_allrouters_mcast(&dst);
+	src = net_if_ipv6_select_src_addr(iface, &dst);
+
+	if (!net_ipv6_is_addr_unspecified(src)) {
+		llao_len = get_llao_len(iface);
+	}
+
+	pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_icmpv6_rs_hdr) +
+					llao_len,
+					AF_INET6, IPPROTO_ICMPV6,
+					ND_NET_BUF_TIMEOUT);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	net_pkt_set_ipv6_hop_limit(pkt, NET_IPV6_ND_HOP_LIMIT);
+
+	if (net_ipv6_create(pkt, src, &dst) ||
+	    net_icmpv6_create(pkt, NET_ICMPV6_RS, 0) ||
+	    net_pkt_memset(pkt, 0, sizeof(struct net_icmpv6_rs_hdr))) {
+		goto drop;
+	}
+
+	if (llao_len > 0) {
+		if (!set_llao(pkt, net_if_get_link_addr(iface),
+			      llao_len, NET_ICMPV6_ND_OPT_SLLAO)) {
+			goto drop;
+		}
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_ipv6_finalize(pkt, IPPROTO_ICMPV6);
+
+	dbg_addr_sent("Router Solicitation", src, &dst, pkt);
+
+	if (net_send_data(pkt) < 0) {
+		net_stats_update_ipv6_nd_drop(iface);
+		ret = -EINVAL;
+
+		goto drop;
+	}
+
+	net_stats_update_ipv6_nd_sent(iface);
+
+	return 0;
+
+drop:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+int net_ipv6_start_rs(struct net_if *iface)
+{
+	return net_ipv6_send_rs(iface);
+}
+
+static inline struct net_nbr *handle_ra_neighbor(struct net_pkt *pkt, uint8_t len)
+{
+	struct net_linkaddr lladdr;
+	struct net_linkaddr_storage llstorage;
+
+	if (!read_llao(pkt, len, &llstorage)) {
+		return NULL;
+	}
+
+	lladdr.len = llstorage.len;
+	lladdr.addr = llstorage.addr;
+
+	return net_ipv6_nbr_add(net_pkt_iface(pkt),
+				&NET_IPV6_HDR(pkt)->src,
+				&lladdr, true,
+				NET_IPV6_NBR_STATE_STALE);
+}
+
+static inline void handle_prefix_onlink(struct net_pkt *pkt,
+			struct net_icmpv6_nd_opt_prefix_info *prefix_info)
+{
+	struct net_if_ipv6_prefix *prefix;
+
+	prefix = net_if_ipv6_prefix_lookup(net_pkt_iface(pkt),
+					   &prefix_info->prefix,
+					   prefix_info->prefix_len);
+	if (!prefix) {
+		if (!prefix_info->valid_lifetime) {
+			return;
+		}
+
+		prefix = net_if_ipv6_prefix_add(net_pkt_iface(pkt),
+						&prefix_info->prefix,
+						prefix_info->prefix_len,
+						prefix_info->valid_lifetime);
+		if (prefix) {
+			NET_DBG("Interface %p/%d add prefix %s/%d lifetime %u",
+				net_pkt_iface(pkt),
+				net_if_get_by_iface(net_pkt_iface(pkt)),
+				log_strdup(net_sprint_ipv6_addr(
+						   &prefix_info->prefix)),
+				prefix_info->prefix_len,
+				prefix_info->valid_lifetime);
+		} else {
+			NET_ERR("Prefix %s/%d could not be added to "
+				"iface %p/%d",
+				log_strdup(net_sprint_ipv6_addr(
+						   &prefix_info->prefix)),
+				prefix_info->prefix_len,
+				net_pkt_iface(pkt),
+				net_if_get_by_iface(net_pkt_iface(pkt)));
+
+			return;
+		}
+	}
+
+	switch (prefix_info->valid_lifetime) {
+	case 0:
+		NET_DBG("Interface %p/%d delete prefix %s/%d",
+			net_pkt_iface(pkt),
+			net_if_get_by_iface(net_pkt_iface(pkt)),
+			log_strdup(net_sprint_ipv6_addr(&prefix_info->prefix)),
+			prefix_info->prefix_len);
+
+		net_if_ipv6_prefix_rm(net_pkt_iface(pkt),
+				      &prefix->prefix,
+				      prefix->len);
+		break;
+
+	case NET_IPV6_ND_INFINITE_LIFETIME:
+		NET_DBG("Interface %p/%d prefix %s/%d infinite",
+			net_pkt_iface(pkt),
+			net_if_get_by_iface(net_pkt_iface(pkt)),
+			log_strdup(net_sprint_ipv6_addr(&prefix->prefix)),
+			prefix->len);
+
+		net_if_ipv6_prefix_set_lf(prefix, true);
+		break;
+
+	default:
+		NET_DBG("Interface %p/%d update prefix %s/%u lifetime %u",
+			net_pkt_iface(pkt),
+			net_if_get_by_iface(net_pkt_iface(pkt)),
+			log_strdup(net_sprint_ipv6_addr(&prefix_info->prefix)),
+			prefix_info->prefix_len, prefix_info->valid_lifetime);
+
+		net_if_ipv6_prefix_set_lf(prefix, false);
+		net_if_ipv6_prefix_set_timer(prefix,
+					     prefix_info->valid_lifetime);
+		break;
+	}
+}
+
+#define TWO_HOURS (2 * 60 * 60)
+
+static uint32_t time_diff(uint32_t time1, uint32_t time2)
+{
+	return (uint32_t)abs((int32_t)time1 - (int32_t)time2);
+}
+
+static inline uint32_t remaining_lifetime(struct net_if_addr *ifaddr)
+{
+	uint64_t remaining;
+
+	if (ifaddr->lifetime.timer_timeout == 0) {
+		return 0;
+	}
+
+	remaining = (uint64_t)ifaddr->lifetime.timer_timeout +
+		(uint64_t)ifaddr->lifetime.wrap_counter *
+		(uint64_t)NET_TIMEOUT_MAX_VALUE -
+		(uint64_t)time_diff(k_uptime_get_32(),
+				 ifaddr->lifetime.timer_start);
+
+	return (uint32_t)(remaining / MSEC_PER_SEC);
+}
+
+static inline void handle_prefix_autonomous(struct net_pkt *pkt,
+			struct net_icmpv6_nd_opt_prefix_info *prefix_info)
+{
+	struct in6_addr addr = { };
+	struct net_if_addr *ifaddr;
+
+	/* Create IPv6 address using the given prefix and iid. We first
+	 * setup link local address, and then copy prefix over first 8
+	 * bytes of that address.
+	 */
+	net_ipv6_addr_create_iid(&addr,
+				 net_if_get_link_addr(net_pkt_iface(pkt)));
+	memcpy(&addr, &prefix_info->prefix, sizeof(struct in6_addr) / 2);
+
+	ifaddr = net_if_ipv6_addr_lookup(&addr, NULL);
+	if (ifaddr && ifaddr->addr_type == NET_ADDR_AUTOCONF) {
+		if (prefix_info->valid_lifetime ==
+		    NET_IPV6_ND_INFINITE_LIFETIME) {
+			net_if_addr_set_lf(ifaddr, true);
+			return;
+		}
+
+		/* RFC 4862 ch 5.5.3 */
+		if ((prefix_info->valid_lifetime > TWO_HOURS) ||
+		    (prefix_info->valid_lifetime >
+		     remaining_lifetime(ifaddr))) {
+			NET_DBG("Timer updating for address %s "
+				"long lifetime %u secs",
+				log_strdup(net_sprint_ipv6_addr(&addr)),
+				prefix_info->valid_lifetime);
+
+			net_if_ipv6_addr_update_lifetime(
+				ifaddr, prefix_info->valid_lifetime);
+		} else {
+			NET_DBG("Timer updating for address %s "
+				"lifetime %u secs",
+				log_strdup(net_sprint_ipv6_addr(&addr)),
+				TWO_HOURS);
+
+			net_if_ipv6_addr_update_lifetime(ifaddr, TWO_HOURS);
+		}
+
+		net_if_addr_set_lf(ifaddr, false);
+	} else {
+		if (prefix_info->valid_lifetime ==
+		    NET_IPV6_ND_INFINITE_LIFETIME) {
+			net_if_ipv6_addr_add(net_pkt_iface(pkt),
+					     &addr, NET_ADDR_AUTOCONF, 0);
+		} else {
+			net_if_ipv6_addr_add(net_pkt_iface(pkt),
+					     &addr, NET_ADDR_AUTOCONF,
+					     prefix_info->valid_lifetime);
+		}
+	}
+}
+
+static inline bool handle_ra_prefix(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(rapfx_access,
+				   struct net_icmpv6_nd_opt_prefix_info);
+	struct net_icmpv6_nd_opt_prefix_info *pfx_info;
+	uint32_t valid_lifetime, preferred_lifetime;
+
+	pfx_info = (struct net_icmpv6_nd_opt_prefix_info *)
+				net_pkt_get_data(pkt, &rapfx_access);
+	if (!pfx_info) {
+		return false;
+	}
+
+	net_pkt_acknowledge_data(pkt, &rapfx_access);
+
+	valid_lifetime = ntohl(pfx_info->valid_lifetime);
+	preferred_lifetime = ntohl(pfx_info->preferred_lifetime);
+
+	if (valid_lifetime >= preferred_lifetime &&
+	    !net_ipv6_is_ll_addr(&pfx_info->prefix)) {
+		if (pfx_info->flags & NET_ICMPV6_RA_FLAG_ONLINK) {
+			handle_prefix_onlink(pkt, pfx_info);
+		}
+
+		if ((pfx_info->flags & NET_ICMPV6_RA_FLAG_AUTONOMOUS) &&
+		    valid_lifetime &&
+		    (pfx_info->prefix_len == NET_IPV6_DEFAULT_PREFIX_LEN)) {
+			handle_prefix_autonomous(pkt, pfx_info);
+		}
+	}
+
+	return true;
+}
+
+#if defined(CONFIG_NET_6LO_CONTEXT)
+/* 6lowpan Context Option RFC 6775, 4.2 */
+static inline bool handle_ra_6co(struct net_pkt *pkt, uint8_t len)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(ctx_access, struct net_icmpv6_nd_opt_6co);
+	struct net_icmpv6_nd_opt_6co *context;
+
+	context = (struct net_icmpv6_nd_opt_6co *)
+				net_pkt_get_data(pkt, &ctx_access);
+	if (!context) {
+		return false;
+	}
+
+	/* RFC 6775, 4.2
+	 * Context Length: 8-bit unsigned integer.  The number of leading
+	 * bits in the Context Prefix field that are valid.  The value ranges
+	 * from 0 to 128.  If it is more than 64, then the Length MUST be 3.
+	 */
+	if ((context->context_len > 64 && len != 3U) ||
+	    (context->context_len <= 64U && len != 2U)) {
+		return false;
+	}
+
+	context->context_len = context->context_len / 8U;
+
+	/* context_len: The number of leading bits in the Context Prefix
+	 * field that are valid. Rest must be set to 0 by the sender and
+	 * ignored by the receiver. But since there is no way to make sure
+	 * the sender followed the rule, let's make sure rest is set to 0.
+	 */
+	if (context->context_len != sizeof(struct in6_addr)) {
+		(void)memset(context->prefix.s6_addr + context->context_len, 0,
+			     sizeof(struct in6_addr) - context->context_len);
+	}
+
+	net_6lo_set_context(net_pkt_iface(pkt), context);
+
+	return true;
+}
+#endif
+
+static enum net_verdict handle_ra_input(struct net_pkt *pkt,
+					struct net_ipv6_hdr *ip_hdr,
+					struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ra_access,
+					      struct net_icmpv6_ra_hdr);
+	NET_PKT_DATA_ACCESS_DEFINE(nd_access, struct net_icmpv6_nd_opt_hdr);
+	uint16_t length = net_pkt_get_len(pkt);
+	struct net_nbr *nbr = NULL;
+	struct net_icmpv6_nd_opt_hdr *nd_opt_hdr;
+	struct net_icmpv6_ra_hdr *ra_hdr;
+	struct net_if_router *router;
+	uint32_t mtu, reachable_time, retrans_timer;
+	uint16_t router_lifetime;
+
+	ra_hdr = (struct net_icmpv6_ra_hdr *)net_pkt_get_data(pkt, &ra_access);
+	if (!ra_hdr) {
+		NET_ERR("DROP: NULL RA header");
+		goto drop;
+	}
+
+	dbg_addr_recv("Router Advertisement", &ip_hdr->src, &ip_hdr->dst, pkt);
+
+	net_stats_update_ipv6_nd_recv(net_pkt_iface(pkt));
+
+	if (((length < (sizeof(struct net_ipv6_hdr) +
+			sizeof(struct net_icmp_hdr) +
+			sizeof(struct net_icmpv6_ra_hdr) +
+			sizeof(struct net_icmpv6_nd_opt_hdr))) ||
+	     (ip_hdr->hop_limit != NET_IPV6_ND_HOP_LIMIT) ||
+	     !net_ipv6_is_ll_addr(&ip_hdr->src)) &&
+		icmp_hdr->code != 0U) {
+		goto drop;
+	}
+
+	net_pkt_acknowledge_data(pkt, &ra_access);
+
+	router_lifetime = ntohs(ra_hdr->router_lifetime);
+	reachable_time = ntohl(ra_hdr->reachable_time);
+	retrans_timer = ntohl(ra_hdr->retrans_timer);
+
+	if (ra_hdr->cur_hop_limit) {
+		net_ipv6_set_hop_limit(net_pkt_iface(pkt),
+				       ra_hdr->cur_hop_limit);
+		NET_DBG("New hop limit %d",
+			net_if_ipv6_get_hop_limit(net_pkt_iface(pkt)));
+	}
+
+	if (reachable_time && reachable_time <= MAX_REACHABLE_TIME &&
+	    (net_if_ipv6_get_reachable_time(net_pkt_iface(pkt)) !=
+	     reachable_time)) {
+		net_if_ipv6_set_base_reachable_time(net_pkt_iface(pkt),
+						    reachable_time);
+		net_if_ipv6_set_reachable_time(
+			net_pkt_iface(pkt)->config.ip.ipv6);
+	}
+
+	if (retrans_timer) {
+		net_if_ipv6_set_retrans_timer(net_pkt_iface(pkt),
+					      ra_hdr->retrans_timer);
+	}
+
+	net_pkt_set_ipv6_ext_opt_len(pkt, sizeof(struct net_icmpv6_ra_hdr));
+	length -= (sizeof(struct net_ipv6_hdr) + sizeof(struct net_icmp_hdr));
+
+	nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+				net_pkt_get_data(pkt, &nd_access);
+	while (nd_opt_hdr) {
+		net_pkt_acknowledge_data(pkt, &nd_access);
+
+		switch (nd_opt_hdr->type) {
+		case NET_ICMPV6_ND_OPT_SLLAO:
+			nbr = handle_ra_neighbor(pkt, nd_opt_hdr->len);
+			if (!nbr) {
+				goto drop;
+			}
+
+			break;
+		case NET_ICMPV6_ND_OPT_MTU:
+			/* MTU has reserved 2 bytes, so skip it. */
+			if (net_pkt_skip(pkt, 2) ||
+			    net_pkt_read_be32(pkt, &mtu)) {
+				goto drop;
+			}
+
+			if (mtu < MIN_IPV6_MTU || mtu > MAX_IPV6_MTU) {
+				NET_ERR("DROP: Unsupported MTU %u, min is %u, "
+					"max is %u",
+					mtu, MIN_IPV6_MTU, MAX_IPV6_MTU);
+				goto drop;
+			}
+
+			net_if_set_mtu(net_pkt_iface(pkt), mtu);
+
+			break;
+		case NET_ICMPV6_ND_OPT_PREFIX_INFO:
+			if (nd_opt_hdr->len != 4) {
+				NET_ERR("DROP: Invalid %s length (%d)",
+					"prefix opt", nd_opt_hdr->len);
+				goto drop;
+			}
+
+			if (!handle_ra_prefix(pkt)) {
+				goto drop;
+			}
+
+			break;
+#if defined(CONFIG_NET_6LO_CONTEXT)
+		case NET_ICMPV6_ND_OPT_6CO:
+			/* RFC 6775, 4.2 (Length)*/
+			if (!(nd_opt_hdr->len == 2U || nd_opt_hdr->len == 3U)) {
+				NET_ERR("DROP: Invalid %s length %d",
+					"6CO", nd_opt_hdr->len);
+				goto drop;
+			}
+
+			if (!handle_ra_6co(pkt, nd_opt_hdr->len)) {
+				goto drop;
+			}
+
+			break;
+#endif
+		case NET_ICMPV6_ND_OPT_ROUTE:
+			NET_DBG("Route option skipped");
+			goto skip;
+
+#if defined(CONFIG_NET_IPV6_RA_RDNSS)
+		case NET_ICMPV6_ND_OPT_RDNSS:
+			NET_DBG("RDNSS option skipped");
+			goto skip;
+#endif
+
+		case NET_ICMPV6_ND_OPT_DNSSL:
+			NET_DBG("DNSSL option skipped");
+			goto skip;
+
+		default:
+			NET_DBG("Unknown ND option 0x%x", nd_opt_hdr->type);
+		skip:
+			if (net_pkt_skip(pkt, nd_opt_hdr->len * 8U - 2)) {
+				goto drop;
+			}
+
+			break;
+		}
+
+		nd_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+					net_pkt_get_data(pkt, &nd_access);
+	}
+
+	router = net_if_ipv6_router_lookup(net_pkt_iface(pkt), &ip_hdr->src);
+	if (router) {
+		if (!router_lifetime) {
+			/* TODO: Start rs_timer on iface if no routers
+			 * at all available on iface.
+			 */
+			net_if_ipv6_router_rm(router);
+		} else {
+			if (nbr) {
+				net_ipv6_nbr_data(nbr)->is_router = true;
+			}
+
+			net_if_ipv6_router_update_lifetime(
+					router, router_lifetime);
+		}
+	} else {
+		net_if_ipv6_router_add(net_pkt_iface(pkt),
+				       &ip_hdr->src, router_lifetime);
+	}
+
+	if (nbr && net_ipv6_nbr_data(nbr)->pending) {
+		NET_DBG("Sending pending pkt %p to %s",
+			net_ipv6_nbr_data(nbr)->pending,
+			log_strdup(net_sprint_ipv6_addr(&NET_IPV6_HDR(
+				net_ipv6_nbr_data(nbr)->pending)->dst)));
+
+		if (net_send_data(net_ipv6_nbr_data(nbr)->pending) < 0) {
+			net_pkt_unref(net_ipv6_nbr_data(nbr)->pending);
+		}
+
+		nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
+	}
+
+	/* Cancel the RS timer on iface */
+	net_if_stop_rs(net_pkt_iface(pkt));
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+
+drop:
+	net_stats_update_ipv6_nd_drop(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+#endif /* CONFIG_NET_IPV6_ND */
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE)
+static struct net_icmpv6_handler ns_input_handler = {
+	.type = NET_ICMPV6_NS,
+	.code = 0,
+	.handler = handle_ns_input,
+};
+
+static struct net_icmpv6_handler na_input_handler = {
+	.type = NET_ICMPV6_NA,
+	.code = 0,
+	.handler = handle_na_input,
+};
+#endif /* CONFIG_NET_IPV6_NBR_CACHE */
+
+#if defined(CONFIG_NET_IPV6_ND)
+static struct net_icmpv6_handler ra_input_handler = {
+	.type = NET_ICMPV6_RA,
+	.code = 0,
+	.handler = handle_ra_input,
+};
+#endif /* CONFIG_NET_IPV6_ND */
+
+void net_ipv6_nbr_init(void)
+{
+#if defined(CONFIG_NET_IPV6_NBR_CACHE)
+	net_icmpv6_register_handler(&ns_input_handler);
+	net_icmpv6_register_handler(&na_input_handler);
+	k_delayed_work_init(&ipv6_ns_reply_timer, ipv6_ns_reply_timeout);
+#endif
+#if defined(CONFIG_NET_IPV6_ND)
+	net_icmpv6_register_handler(&ra_input_handler);
+	k_delayed_work_init(&ipv6_nd_reachable_timer,
+			    ipv6_nd_reachable_timeout);
+	k_sem_init(&nbr_lock, 1, UINT_MAX);
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.h	(working copy)
@@ -0,0 +1,224 @@
+/** @file
+ *  @brief IPv6 neighbor management.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __NET_NBR_H
+#define __NET_NBR_H
+
+#include <stddef.h>
+#include <zephyr/types.h>
+#include <stdbool.h>
+
+#include <net/net_if.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NET_NBR_LLADDR_UNKNOWN 0xff
+
+/* The neighbors are tracked by link layer address. This is not part
+ * of struct net_nbr because this data can be shared between different
+ * neighboring tables.
+ */
+struct net_nbr_lladdr {
+	/** Link layer address */
+	struct net_linkaddr_storage lladdr;
+
+	/** Reference count. */
+	uint8_t ref;
+};
+
+#define NET_NBR_LLADDR_INIT(_name, _count)	\
+	struct net_nbr_lladdr _name[_count] = { }
+
+/* Alignment needed for various parts of the neighbor definition */
+#define __net_nbr_align __aligned(sizeof(int))
+
+/* The neighbor node generic data. There can be sub-system specific
+ * data at the end of the node.
+ */
+struct net_nbr {
+	/** Reference count. */
+	uint8_t ref;
+
+	/** Link to ll address. This is the index into lladdr array.
+	 * The value NET_NBR_LLADDR_UNKNOWN tells that this neighbor
+	 * does not yet have lladdr linked to it.
+	 */
+	uint8_t idx;
+
+	/** Amount of data that this neighbor buffer can store. */
+	const uint16_t size;
+
+	/** Extra data size associated with this neighbor */
+	const uint16_t extra_data_size;
+
+	/** Interface this neighbor is found */
+	struct net_if *iface;
+
+	/** Pointer to the start of data in the neighbor table. */
+	uint8_t *data;
+
+	/** Function to be called when the neighbor is removed. */
+	void (*const remove)(struct net_nbr *nbr);
+
+	/** Start of the data storage. Not to be accessed directly
+	 *  (the data pointer should be used instead).
+	 */
+	uint8_t __nbr[0] __net_nbr_align;
+};
+
+/* This is an array of struct net_nbr + some additional data */
+#define NET_NBR_POOL_INIT(_name, _count, _size, _remove, _extra_size)	\
+	struct {							\
+		struct net_nbr nbr;					\
+		uint8_t data[ROUND_UP(_size, 4)] __net_nbr_align;	\
+		uint8_t extra[ROUND_UP(_extra_size, 4)] __net_nbr_align;\
+	} _name[_count] = {						\
+		[0 ... (_count - 1)] = { .nbr = {			\
+			.idx = NET_NBR_LLADDR_UNKNOWN,			\
+			.remove = _remove,				\
+			.size = ROUND_UP(_size, 4),			\
+			.extra_data_size = ROUND_UP(_extra_size, 4) } },\
+	}
+
+struct net_nbr_table {
+	/** Link to a neighbor pool */
+	struct net_nbr *nbr;
+
+	/** Function to be called when the table is cleared. */
+	void (*const clear)(struct net_nbr_table *table);
+
+	/** Max number of neighbors in the pool */
+	const uint16_t nbr_count;
+};
+
+#define NET_NBR_LOCAL static
+#define NET_NBR_GLOBAL
+
+/* Type of the table can be NET_NBR_LOCAL or NET_NBR_GLOBAL
+ */
+#define NET_NBR_TABLE_INIT(_type, _name, _pool, _clear)			\
+	_type struct net_nbr_table_##_name {				\
+		struct net_nbr_table table;				\
+	} net_##_name __used = {					\
+		.table = {						\
+			.clear = _clear,				\
+			.nbr = (struct net_nbr *)_pool,			\
+			.nbr_count = ARRAY_SIZE(_pool),			\
+		}							\
+	}
+
+/**
+ *  @brief Get a pointer to the extra data of a neighbor entry.
+ *
+ *  @param nbr A valid pointer to neighbor
+ *
+ *  @return Pointer to the extra data of the nbr.
+ */
+static inline void *net_nbr_extra_data(struct net_nbr *nbr)
+{
+	return (void *)ROUND_UP((nbr->__nbr + nbr->size), sizeof(int));
+}
+
+/**
+ * @brief Decrement the reference count. If count goes to 0, the neighbor
+ * is released and returned to free list.
+ * @param nbr Pointer to neighbor
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+void net_nbr_unref_debug(struct net_nbr *nbr, const char *caller, int line);
+#define net_nbr_unref(nbr) net_nbr_unref_debug(nbr, __func__, __LINE__)
+#else
+void net_nbr_unref(struct net_nbr *nbr);
+#endif
+
+/**
+ * @brief Increment the reference count.
+ * @param nbr Pointer to neighbor
+ * @return Pointer to neighbor
+ */
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+struct net_nbr *net_nbr_ref_debug(struct net_nbr *nbr, const char *caller,
+				  int line);
+#define net_nbr_ref(nbr) net_nbr_ref_debug(nbr, __func__, __LINE__)
+#else
+struct net_nbr *net_nbr_ref(struct net_nbr *nbr);
+#endif
+
+/**
+ * @brief Get a free neighbor from specific table.
+ * @param table Neighbor table
+ * @return Pointer to neighbor, NULL if no free neighbors
+ */
+struct net_nbr *net_nbr_get(struct net_nbr_table *table);
+
+/**
+ * @brief Find a neighbor from specific table.
+ * @param table Neighbor table
+ * @param iface Network interface to use
+ * @param lladdr Neighbor link layer address
+ * @return Pointer to neighbor, NULL if not found
+ */
+struct net_nbr *net_nbr_lookup(struct net_nbr_table *table,
+			       struct net_if *iface,
+			       struct net_linkaddr *lladdr);
+
+/**
+ * @brief Link a neighbor to specific link layer address.
+ * @param table Neighbor table
+ * @param iface Network interface to use
+ * @param lladdr Neighbor link layer address
+ * @return 0 if ok, <0 if linking failed
+ */
+int net_nbr_link(struct net_nbr *nbr, struct net_if *iface,
+		 const struct net_linkaddr *lladdr);
+
+/**
+ * @brief Unlink a neighbor from specific link layer address.
+ * @param table Neighbor table
+ * @param lladdr Neighbor link layer address
+ * @return 0 if ok, <0 if unlinking failed
+ */
+int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr);
+
+/**
+ * @brief Return link address for a specific lladdr table index
+ * @param idx Link layer address index in ll table.
+ * @return Pointer to link layer address storage, NULL if not found
+ */
+#if defined(CONFIG_NET_NATIVE)
+struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx);
+#else
+static inline struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx)
+{
+	ARG_UNUSED(idx);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Clear table from all neighbors. After this the linking between
+ * lladdr and neighbor is removed.
+ * @param table Neighbor table
+ */
+void net_nbr_clear_table(struct net_nbr_table *table);
+
+/**
+ * @brief Debug helper to print out the neighbor information.
+ * @param table Neighbor table
+ */
+void net_nbr_print(struct net_nbr_table *table);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NET_NBR_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/nbr.c	(working copy)
@@ -0,0 +1,231 @@
+/* nbr.c - Neighbor table management */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_nbr, CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL);
+
+#include <errno.h>
+
+#include <net/net_core.h>
+
+#include "net_private.h"
+
+#include "nbr.h"
+
+NET_NBR_LLADDR_INIT(net_neighbor_lladdr, CONFIG_NET_IPV6_MAX_NEIGHBORS);
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+void net_nbr_unref_debug(struct net_nbr *nbr, const char *caller, int line)
+#define net_nbr_unref(nbr) net_nbr_unref_debug(nbr, __func__, __LINE__)
+#else
+void net_nbr_unref(struct net_nbr *nbr)
+#endif
+{
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+	NET_DBG("nbr %p ref %u (%s():%d)", nbr, nbr->ref - 1, caller, line);
+#else
+	NET_DBG("nbr %p ref %u", nbr, nbr->ref - 1);
+#endif
+	if (--nbr->ref) {
+		return;
+	}
+
+	if (nbr->remove) {
+		nbr->remove(nbr);
+	}
+}
+
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+struct net_nbr *net_nbr_ref_debug(struct net_nbr *nbr, const char *caller,
+				  int line)
+#else
+struct net_nbr *net_nbr_ref(struct net_nbr *nbr)
+#endif
+{
+#if defined(CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL_DBG)
+	NET_DBG("nbr %p ref %u (%s():%d)", nbr, nbr->ref + 1, caller, line);
+#else
+	NET_DBG("nbr %p ref %u", nbr, nbr->ref + 1);
+#endif
+	nbr->ref++;
+
+	return nbr;
+}
+
+static inline struct net_nbr *get_nbr(struct net_nbr *start, int idx)
+{
+	NET_ASSERT(idx < CONFIG_NET_IPV6_MAX_NEIGHBORS);
+
+	return (struct net_nbr *)((uint8_t *)start +
+			((sizeof(struct net_nbr) +
+			  start->size + start->extra_data_size) * idx));
+}
+
+struct net_nbr *net_nbr_get(struct net_nbr_table *table)
+{
+	int i;
+
+	for (i = 0; i < table->nbr_count; i++) {
+		struct net_nbr *nbr = get_nbr(table->nbr, i);
+
+		if (!nbr->ref) {
+			nbr->data = nbr->__nbr;
+
+			return net_nbr_ref(nbr);
+		}
+	}
+
+	return NULL;
+}
+
+int net_nbr_link(struct net_nbr *nbr, struct net_if *iface,
+		 const struct net_linkaddr *lladdr)
+{
+	int i, avail = -1;
+
+	if (nbr->idx != NET_NBR_LLADDR_UNKNOWN) {
+		return -EALREADY;
+	}
+
+	for (i = 0; i < CONFIG_NET_IPV6_MAX_NEIGHBORS; i++) {
+		if (avail < 0 && !net_neighbor_lladdr[i].ref) {
+			avail = i;
+		}
+
+		if (net_neighbor_lladdr[i].ref &&
+		    !memcmp(lladdr->addr,
+			    net_neighbor_lladdr[i].lladdr.addr,
+			    lladdr->len)) {
+			/* We found same lladdr in nbr cache so just
+			 * increase the ref count.
+			 */
+			net_neighbor_lladdr[i].ref++;
+
+			nbr->idx = i;
+			nbr->iface = iface;
+
+			return 0;
+		}
+	}
+
+	if (avail < 0) {
+		return -ENOENT;
+	}
+
+	/* There was no existing entry in the lladdr cache,
+	 * so allocate one for this lladdr.
+	 */
+	net_neighbor_lladdr[avail].ref++;
+	nbr->idx = avail;
+
+	net_linkaddr_set(&net_neighbor_lladdr[avail].lladdr, lladdr->addr,
+			 lladdr->len);
+	net_neighbor_lladdr[avail].lladdr.len = lladdr->len;
+	net_neighbor_lladdr[avail].lladdr.type = lladdr->type;
+
+	nbr->iface = iface;
+
+	return 0;
+}
+
+int net_nbr_unlink(struct net_nbr *nbr, struct net_linkaddr *lladdr)
+{
+	ARG_UNUSED(lladdr);
+
+	if (nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
+		return -EALREADY;
+	}
+
+	NET_ASSERT(nbr->idx < CONFIG_NET_IPV6_MAX_NEIGHBORS);
+	NET_ASSERT(net_neighbor_lladdr[nbr->idx].ref > 0);
+
+	net_neighbor_lladdr[nbr->idx].ref--;
+
+	if (!net_neighbor_lladdr[nbr->idx].ref) {
+		(void)memset(net_neighbor_lladdr[nbr->idx].lladdr.addr, 0,
+			     sizeof(net_neighbor_lladdr[nbr->idx].lladdr.addr));
+	}
+
+	nbr->idx = NET_NBR_LLADDR_UNKNOWN;
+	nbr->iface = NULL;
+
+	return 0;
+}
+
+struct net_nbr *net_nbr_lookup(struct net_nbr_table *table,
+			       struct net_if *iface,
+			       struct net_linkaddr *lladdr)
+{
+	int i;
+
+	for (i = 0; i < table->nbr_count; i++) {
+		struct net_nbr *nbr = get_nbr(table->nbr, i);
+
+		if (nbr->ref && nbr->iface == iface &&
+		    net_neighbor_lladdr[nbr->idx].ref &&
+		    !memcmp(net_neighbor_lladdr[nbr->idx].lladdr.addr,
+			    lladdr->addr, lladdr->len)) {
+			return nbr;
+		}
+	}
+
+	return NULL;
+}
+
+struct net_linkaddr_storage *net_nbr_get_lladdr(uint8_t idx)
+{
+	NET_ASSERT(idx < CONFIG_NET_IPV6_MAX_NEIGHBORS,
+		   "idx %d >= max %d", idx,
+		   CONFIG_NET_IPV6_MAX_NEIGHBORS);
+
+	return &net_neighbor_lladdr[idx].lladdr;
+}
+
+void net_nbr_clear_table(struct net_nbr_table *table)
+{
+	int i;
+
+	for (i = 0; i < table->nbr_count; i++) {
+		struct net_nbr *nbr = get_nbr(table->nbr, i);
+		struct net_linkaddr lladdr = {
+			.addr = net_neighbor_lladdr[i].lladdr.addr,
+			.len = net_neighbor_lladdr[i].lladdr.len
+		};
+
+		net_nbr_unlink(nbr, &lladdr);
+	}
+
+	if (table->clear) {
+		table->clear(table);
+	}
+}
+
+void net_nbr_print(struct net_nbr_table *table)
+{
+	if (CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		int i;
+
+		for (i = 0; i < table->nbr_count; i++) {
+			struct net_nbr *nbr = get_nbr(table->nbr, i);
+
+			if (!nbr->ref) {
+				continue;
+			}
+
+			NET_DBG("[%d] nbr %p data %p ref %d iface %p idx %d "
+				"ll %s",
+				i, nbr, nbr->data, nbr->ref, nbr->iface,
+				nbr->idx,
+				nbr->idx == NET_NBR_LLADDR_UNKNOWN ?
+				"<unknown>" :
+				log_strdup(net_sprint_ll_addr(
+				   net_neighbor_lladdr[nbr->idx].lladdr.addr,
+				   net_neighbor_lladdr[nbr->idx].lladdr.len)));
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_context.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_context.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_context.c	(working copy)
@@ -0,0 +1,2234 @@
+/** @file
+ * @brief Network context API
+ *
+ * An API for applications to define a network connection.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ctx, CONFIG_NET_CONTEXT_LOG_LEVEL);
+
+#include <kernel.h>
+#include <random/rand32.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <net/net_pkt.h>
+#include <net/net_ip.h>
+#include <net/socket.h>
+#include <net/net_context.h>
+#include <net/net_offload.h>
+#include <net/ethernet.h>
+#include <net/socket_can.h>
+
+#include "connection.h"
+#include "net_private.h"
+
+#include "ipv6.h"
+#include "ipv4.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "net_stats.h"
+
+#if IS_ENABLED(CONFIG_NET_TCP2)
+#include "tcp2.h"
+#endif
+
+#ifndef EPFNOSUPPORT
+/* Some old versions of newlib haven't got this defined in errno.h,
+ * Just use EPROTONOSUPPORT in this case
+ */
+#define EPFNOSUPPORT EPROTONOSUPPORT
+#endif
+
+#define PKT_WAIT_TIME K_SECONDS(1)
+
+#define NET_MAX_CONTEXT CONFIG_NET_MAX_CONTEXTS
+
+static struct net_context contexts[NET_MAX_CONTEXT];
+
+/* We need to lock the contexts array as these APIs are typically called
+ * from applications which are usually run in task context.
+ */
+static struct k_sem contexts_lock;
+
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
+static int check_used_port(enum net_ip_protocol ip_proto,
+			   uint16_t local_port,
+			   const struct sockaddr *local_addr)
+
+{
+	int i;
+
+	for (i = 0; i < NET_MAX_CONTEXT; i++) {
+		if (!net_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		if (!(net_context_get_ip_proto(&contexts[i]) == ip_proto &&
+		      net_sin((struct sockaddr *)&
+			      contexts[i].local)->sin_port == local_port)) {
+			continue;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    local_addr->sa_family == AF_INET6) {
+			if (net_ipv6_addr_cmp(
+				    net_sin6_ptr(&contexts[i].local)->
+							     sin6_addr,
+				    &((struct sockaddr_in6 *)
+				      local_addr)->sin6_addr)) {
+				return -EEXIST;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+			   local_addr->sa_family == AF_INET) {
+			if (net_ipv4_addr_cmp(
+				    net_sin_ptr(&contexts[i].local)->
+							      sin_addr,
+				    &((struct sockaddr_in *)
+				      local_addr)->sin_addr)) {
+				return -EEXIST;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static uint16_t find_available_port(struct net_context *context,
+				    const struct sockaddr *addr)
+{
+	uint16_t local_port;
+
+	do {
+		local_port = sys_rand32_get() | 0x8000;
+		if (local_port <= 1023U) {
+			/* 0 - 1023 ports are reserved */
+			continue;
+		}
+	} while (check_used_port(net_context_get_ip_proto(context),
+				 htons(local_port), addr) == -EEXIST);
+
+	return htons(local_port);
+}
+#else
+#define check_used_port(...) 0
+#define find_available_port(...) 0
+#endif
+
+int net_context_get(sa_family_t family,
+		    enum net_sock_type type,
+		    uint16_t ip_proto,
+		    struct net_context **context)
+{
+	int i, ret = -ENOENT;
+
+	if (IS_ENABLED(CONFIG_NET_CONTEXT_CHECK)) {
+		if (!IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+			NET_DBG("IPv4 disabled");
+			return -EPFNOSUPPORT;
+		}
+
+		if (!IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+			NET_DBG("IPv6 disabled");
+			return -EPFNOSUPPORT;
+		}
+
+		if (!IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN) {
+			NET_DBG("AF_CAN disabled");
+			return -EPFNOSUPPORT;
+		}
+
+		if (type == SOCK_RAW) {
+			if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+			    IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+				if (family != AF_PACKET && family != AF_CAN) {
+					NET_DBG("Invalid family");
+					return -EINVAL;
+				}
+			} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+				   !IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+				if (family != AF_PACKET) {
+					NET_DBG("Invalid family");
+					return -EINVAL;
+				}
+			} else if (!IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+				   IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+				if (family != AF_CAN) {
+					NET_DBG("Invalid family");
+					return -EINVAL;
+				}
+			}
+		} else {
+			if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+			    family == AF_PACKET && type == SOCK_DGRAM &&
+			    ip_proto > 0) {
+				goto check_context;
+			} else if (family == AF_PACKET || family == AF_CAN) {
+				NET_DBG("Invalid family");
+				return -EPROTOTYPE;
+			}
+		}
+
+		if (!IS_ENABLED(CONFIG_NET_UDP)) {
+			if (type == SOCK_DGRAM) {
+				NET_DBG("Datagram context disabled");
+				return -EPROTOTYPE;
+			}
+
+			if (ip_proto == IPPROTO_UDP) {
+				NET_DBG("UDP disabled");
+				return -EPROTONOSUPPORT;
+			}
+		}
+
+		if (!IS_ENABLED(CONFIG_NET_TCP)) {
+			if (type == SOCK_STREAM) {
+				NET_DBG("Stream context disabled");
+				return -EPROTOTYPE;
+			}
+
+			if (ip_proto == IPPROTO_TCP) {
+				NET_DBG("TCP disabled");
+				return -EPROTONOSUPPORT;
+			}
+		}
+
+		if (family != AF_INET && family != AF_INET6 &&
+		    family != AF_PACKET && family != AF_CAN) {
+			NET_DBG("Unknown address family %d", family);
+			return -EAFNOSUPPORT;
+		}
+
+		if (type != SOCK_DGRAM && type != SOCK_STREAM &&
+		    type != SOCK_RAW) {
+			NET_DBG("Unknown context type");
+			return -EPROTOTYPE;
+		}
+
+		if (type != SOCK_RAW && ip_proto != IPPROTO_UDP &&
+		    ip_proto != IPPROTO_TCP) {
+			NET_DBG("Unknown IP protocol %d", ip_proto);
+			return -EPROTONOSUPPORT;
+		}
+
+		if ((type == SOCK_STREAM && ip_proto == IPPROTO_UDP) ||
+		    (type == SOCK_DGRAM && ip_proto == IPPROTO_TCP)) {
+			NET_DBG("Context type and protocol mismatch,"
+				" type %d proto %d", type, ip_proto);
+			return -EOPNOTSUPP;
+		}
+
+	check_context:
+		if (!context) {
+			NET_DBG("Invalid context");
+			return -EINVAL;
+		}
+	}
+
+	k_sem_take(&contexts_lock, K_FOREVER);
+
+	for (i = 0; i < NET_MAX_CONTEXT; i++) {
+		if (net_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		memset(&contexts[i], 0, sizeof(contexts[i]));
+	/* FIXME - Figure out a way to get the correct network interface
+	 * as it is not known at this point yet.
+	 */
+		if (!net_if_is_ip_offloaded(net_if_get_default())
+			&& ip_proto == IPPROTO_TCP) {
+			if (net_tcp_get(&contexts[i]) < 0) {
+				break;
+			}
+		}
+
+		contexts[i].iface = -1;
+		contexts[i].flags = 0U;
+		atomic_set(&contexts[i].refcount, 1);
+
+		net_context_set_family(&contexts[i], family);
+		net_context_set_type(&contexts[i], type);
+		net_context_set_ip_proto(&contexts[i], ip_proto);
+
+		if (IS_ENABLED(CONFIG_NET_IPV6) ||
+		    IS_ENABLED(CONFIG_NET_IPV4)) {
+			(void)memset(&contexts[i].remote, 0,
+				     sizeof(struct sockaddr));
+			(void)memset(&contexts[i].local, 0,
+				     sizeof(struct sockaddr_ptr));
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+			struct sockaddr_in6 *addr6 = (struct sockaddr_in6
+						      *)&contexts[i].local;
+			addr6->sin6_port = find_available_port(&contexts[i],
+						    (struct sockaddr *)addr6);
+
+			if (!addr6->sin6_port) {
+				ret = -EADDRINUSE;
+				break;
+			}
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+			struct sockaddr_in *addr = (struct sockaddr_in
+						      *)&contexts[i].local;
+			addr->sin_port = find_available_port(&contexts[i],
+						    (struct sockaddr *)addr);
+
+			if (!addr->sin_port) {
+				ret = -EADDRINUSE;
+				break;
+			}
+		}
+
+#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
+		k_sem_init(&contexts[i].recv_data_wait, 1, UINT_MAX);
+#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
+
+		k_mutex_init(&contexts[i].lock);
+
+		contexts[i].flags |= NET_CONTEXT_IN_USE;
+		*context = &contexts[i];
+
+		ret = 0;
+		break;
+	}
+
+	k_sem_give(&contexts_lock);
+
+	/* FIXME - Figure out a way to get the correct network interface
+	 * as it is not known at this point yet.
+	 */
+	if (!ret && IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_if_get_default())) {
+		ret = net_offload_get(net_if_get_default(),
+				      family,
+				      type,
+				      ip_proto,
+				      context);
+		if (ret < 0) {
+			(*context)->flags &= ~NET_CONTEXT_IN_USE;
+			*context = NULL;
+		}
+
+		return ret;
+	}
+
+	return ret;
+}
+
+int net_context_ref(struct net_context *context)
+{
+	int old_rc = atomic_inc(&context->refcount);
+
+	return old_rc + 1;
+}
+
+int net_context_unref(struct net_context *context)
+{
+	int old_rc = atomic_dec(&context->refcount);
+
+	if (old_rc != 1) {
+		return old_rc - 1;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	net_tcp_unref(context);
+
+	if (context->conn_handler) {
+		if (IS_ENABLED(CONFIG_NET_TCP) || IS_ENABLED(CONFIG_NET_UDP) ||
+		    IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+			net_conn_unregister(context->conn_handler);
+		}
+
+		context->conn_handler = NULL;
+	}
+
+	net_context_set_state(context, NET_CONTEXT_UNCONNECTED);
+
+	context->flags &= ~NET_CONTEXT_IN_USE;
+
+	NET_DBG("Context %p released", context);
+
+	k_mutex_unlock(&context->lock);
+
+	return 0;
+}
+
+int net_context_put(struct net_context *context)
+{
+	int ret = 0;
+
+	NET_ASSERT(context);
+
+	if (!PART_OF_ARRAY(contexts, context)) {
+		return -EINVAL;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		context->flags &= ~NET_CONTEXT_IN_USE;
+		ret = net_offload_put(net_context_get_iface(context), context);
+		goto unlock;
+	}
+
+	context->connect_cb = NULL;
+	context->recv_cb = NULL;
+	context->send_cb = NULL;
+
+	/* Decrement refcount on user app's behalf */
+	net_context_unref(context);
+
+	/* net_tcp_put() will handle decrementing refcount on stack's behalf */
+	net_tcp_put(context);
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+/* If local address is not bound, bind it to INADDR_ANY and random port. */
+static int bind_default(struct net_context *context)
+{
+	sa_family_t family = net_context_get_family(context);
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		struct sockaddr_in6 addr6;
+
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			return 0;
+		}
+
+		addr6.sin6_family = AF_INET6;
+		memcpy(&addr6.sin6_addr, net_ipv6_unspecified_address(),
+		       sizeof(addr6.sin6_addr));
+		addr6.sin6_port =
+			find_available_port(context,
+					    (struct sockaddr *)&addr6);
+
+		return net_context_bind(context, (struct sockaddr *)&addr6,
+					sizeof(addr6));
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+		struct sockaddr_in addr4;
+
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			return 0;
+		}
+
+		addr4.sin_family = AF_INET;
+		addr4.sin_addr.s_addr = INADDR_ANY;
+		addr4.sin_port =
+			find_available_port(context,
+					    (struct sockaddr *)&addr4);
+
+		return net_context_bind(context, (struct sockaddr *)&addr4,
+					sizeof(addr4));
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == AF_PACKET) {
+		struct sockaddr_ll ll_addr;
+
+		if (net_sll_ptr(&context->local)->sll_addr) {
+			return 0;
+		}
+
+		ll_addr.sll_family = AF_PACKET;
+		ll_addr.sll_protocol = htons(ETH_P_ALL);
+		ll_addr.sll_ifindex = net_if_get_by_iface(net_if_get_default());
+
+		return net_context_bind(context, (struct sockaddr *)&ll_addr,
+					sizeof(ll_addr));
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && family == AF_CAN) {
+		struct sockaddr_can can_addr;
+
+		if (context->iface >= 0) {
+			return 0;
+		} else {
+#if defined(CONFIG_NET_L2_CANBUS_RAW)
+			struct net_if *iface;
+
+			iface = net_if_get_first_by_type(
+						&NET_L2_GET_NAME(CANBUS_RAW));
+			if (!iface) {
+				return -ENOENT;
+			}
+
+			can_addr.can_ifindex = net_if_get_by_iface(iface);
+			context->iface = can_addr.can_ifindex;
+#else
+			return -ENOENT;
+#endif
+		}
+
+		can_addr.can_family = AF_CAN;
+
+		return net_context_bind(context, (struct sockaddr *)&can_addr,
+					sizeof(can_addr));
+	}
+
+	return -EINVAL;
+}
+
+int net_context_bind(struct net_context *context, const struct sockaddr *addr,
+		     socklen_t addrlen)
+{
+	NET_ASSERT(addr);
+	NET_ASSERT(PART_OF_ARRAY(contexts, context));
+
+	/* If we already have connection handler, then it effectively
+	 * means that it's already bound to an interface/port, and we
+	 * don't support rebinding connection to new address/port in
+	 * the code below.
+	 * TODO: Support rebinding.
+	 */
+	if (context->conn_handler) {
+		return -EISCONN;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) {
+		struct net_if *iface = NULL;
+		struct in6_addr *ptr;
+		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+		int ret;
+
+		if (addrlen < sizeof(struct sockaddr_in6)) {
+			return -EINVAL;
+		}
+
+		if (net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
+			struct net_if_mcast_addr *maddr;
+
+			maddr = net_if_ipv6_maddr_lookup(&addr6->sin6_addr,
+							 &iface);
+			if (!maddr) {
+				return -ENOENT;
+			}
+
+			ptr = &maddr->address.in6_addr;
+
+		} else if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
+			iface = net_if_ipv6_select_src_iface(
+				&net_sin6(&context->remote)->sin6_addr);
+
+			ptr = (struct in6_addr *)net_ipv6_unspecified_address();
+		} else {
+			struct net_if_addr *ifaddr;
+
+			ifaddr = net_if_ipv6_addr_lookup(&addr6->sin6_addr,
+							 &iface);
+			if (!ifaddr) {
+				return -ENOENT;
+			}
+
+			ptr = &ifaddr->address.in6_addr;
+		}
+
+		if (!iface) {
+			NET_ERR("Cannot bind to %s",
+				log_strdup(net_sprint_ipv6_addr(
+						   &addr6->sin6_addr)));
+
+			return -EADDRNOTAVAIL;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		    net_if_is_ip_offloaded(iface)) {
+			net_context_set_iface(context, iface);
+
+			return net_offload_bind(iface,
+						context,
+						addr,
+						addrlen);
+		}
+
+		net_context_set_iface(context, iface);
+
+		net_sin6_ptr(&context->local)->sin6_family = AF_INET6;
+		net_sin6_ptr(&context->local)->sin6_addr = ptr;
+		if (addr6->sin6_port) {
+			ret = check_used_port(AF_INET6, addr6->sin6_port,
+					      addr);
+			if (!ret) {
+				net_sin6_ptr(&context->local)->sin6_port =
+					addr6->sin6_port;
+			} else {
+				NET_ERR("Port %d is in use!",
+					ntohs(addr6->sin6_port));
+				return ret;
+			}
+		} else {
+			addr6->sin6_port =
+				net_sin6_ptr(&context->local)->sin6_port;
+		}
+
+		NET_DBG("Context %p binding to %s [%s]:%d iface %p",
+			context,
+			net_proto2str(AF_INET6,
+				      net_context_get_ip_proto(context)),
+			log_strdup(net_sprint_ipv6_addr(ptr)),
+			ntohs(addr6->sin6_port), iface);
+
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
+		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
+		struct net_if *iface = NULL;
+		struct net_if_addr *ifaddr;
+		struct in_addr *ptr;
+		int ret;
+
+		if (addrlen < sizeof(struct sockaddr_in)) {
+			return -EINVAL;
+		}
+
+		if (net_ipv4_is_addr_mcast(&addr4->sin_addr)) {
+			struct net_if_mcast_addr *maddr;
+
+			maddr = net_if_ipv4_maddr_lookup(&addr4->sin_addr,
+							 &iface);
+			if (!maddr) {
+				return -ENOENT;
+			}
+
+			ptr = &maddr->address.in_addr;
+
+		} else if (addr4->sin_addr.s_addr == INADDR_ANY) {
+			iface = net_if_ipv4_select_src_iface(
+				&net_sin(&context->remote)->sin_addr);
+
+			ptr = (struct in_addr *)net_ipv4_unspecified_address();
+		} else {
+			ifaddr = net_if_ipv4_addr_lookup(&addr4->sin_addr,
+							 &iface);
+			if (!ifaddr) {
+				return -ENOENT;
+			}
+
+			ptr = &ifaddr->address.in_addr;
+		}
+
+		if (!iface) {
+			NET_ERR("Cannot bind to %s",
+				log_strdup(net_sprint_ipv4_addr(
+						   &addr4->sin_addr)));
+
+			return -EADDRNOTAVAIL;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		    net_if_is_ip_offloaded(iface)) {
+			net_context_set_iface(context, iface);
+
+			return net_offload_bind(iface,
+						context,
+						addr,
+						addrlen);
+		}
+
+		k_mutex_lock(&context->lock, K_FOREVER);
+
+		ret = 0;
+
+		net_context_set_iface(context, iface);
+
+		net_sin_ptr(&context->local)->sin_family = AF_INET;
+		net_sin_ptr(&context->local)->sin_addr = ptr;
+		if (addr4->sin_port) {
+			ret = check_used_port(AF_INET, addr4->sin_port,
+					      addr);
+			if (!ret) {
+				net_sin_ptr(&context->local)->sin_port =
+					addr4->sin_port;
+			} else {
+				NET_ERR("Port %d is in use!",
+					ntohs(addr4->sin_port));
+				goto unlock;
+			}
+		} else {
+			addr4->sin_port =
+				net_sin_ptr(&context->local)->sin_port;
+		}
+
+		NET_DBG("Context %p binding to %s %s:%d iface %p",
+			context,
+			net_proto2str(AF_INET,
+				      net_context_get_ip_proto(context)),
+			log_strdup(net_sprint_ipv4_addr(ptr)),
+			ntohs(addr4->sin_port), iface);
+
+	unlock:
+		k_mutex_unlock(&context->lock);
+
+		return ret;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+	    addr->sa_family == AF_PACKET) {
+		struct sockaddr_ll *ll_addr = (struct sockaddr_ll *)addr;
+		struct net_if *iface = NULL;
+
+		if (addrlen < sizeof(struct sockaddr_ll)) {
+			return -EINVAL;
+		}
+
+		if (ll_addr->sll_ifindex < 0) {
+			return -EINVAL;
+		}
+
+		iface = net_if_get_by_index(ll_addr->sll_ifindex);
+		if (!iface) {
+			NET_ERR("Cannot bind to interface index %d",
+				ll_addr->sll_ifindex);
+			return -EADDRNOTAVAIL;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		    net_if_is_ip_offloaded(iface)) {
+			net_context_set_iface(context, iface);
+
+			return net_offload_bind(iface,
+						context,
+						addr,
+						addrlen);
+		}
+
+		net_context_set_iface(context, iface);
+
+		net_sll_ptr(&context->local)->sll_family = AF_PACKET;
+		net_sll_ptr(&context->local)->sll_ifindex =
+			ll_addr->sll_ifindex;
+		net_sll_ptr(&context->local)->sll_protocol =
+			ll_addr->sll_protocol;
+		net_sll_ptr(&context->local)->sll_addr =
+			net_if_get_link_addr(iface)->addr;
+		net_sll_ptr(&context->local)->sll_halen =
+			net_if_get_link_addr(iface)->len;
+
+		NET_DBG("Context %p bind to type 0x%04x iface[%d] %p addr %s",
+			context, htons(net_context_get_ip_proto(context)),
+			ll_addr->sll_ifindex, iface,
+			log_strdup(net_sprint_ll_addr(
+				net_sll_ptr(&context->local)->sll_addr,
+				net_sll_ptr(&context->local)->sll_halen)));
+
+		return 0;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) && addr->sa_family == AF_CAN) {
+		struct sockaddr_can *can_addr = (struct sockaddr_can *)addr;
+		struct net_if *iface = NULL;
+
+		if (addrlen < sizeof(struct sockaddr_can)) {
+			return -EINVAL;
+		}
+
+		if (can_addr->can_ifindex < 0) {
+			return -EINVAL;
+		}
+
+		iface = net_if_get_by_index(can_addr->can_ifindex);
+		if (!iface) {
+			NET_ERR("Cannot bind to interface index %d",
+				can_addr->can_ifindex);
+			return -EADDRNOTAVAIL;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		    net_if_is_ip_offloaded(iface)) {
+			net_context_set_iface(context, iface);
+
+			return net_offload_bind(iface,
+						context,
+						addr,
+						addrlen);
+		}
+
+		net_context_set_iface(context, iface);
+		net_context_set_family(context, AF_CAN);
+
+		net_can_ptr(&context->local)->can_family = AF_CAN;
+		net_can_ptr(&context->local)->can_ifindex =
+			can_addr->can_ifindex;
+
+		NET_DBG("Context %p binding to %d iface[%d] %p",
+			context, net_context_get_ip_proto(context),
+			can_addr->can_ifindex, iface);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static inline struct net_context *find_context(void *conn_handler)
+{
+	int i;
+
+	for (i = 0; i < NET_MAX_CONTEXT; i++) {
+		if (!net_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		if (contexts[i].conn_handler == conn_handler) {
+			return &contexts[i];
+		}
+	}
+
+	return NULL;
+}
+
+int net_context_listen(struct net_context *context, int backlog)
+{
+	ARG_UNUSED(backlog);
+
+	NET_ASSERT(PART_OF_ARRAY(contexts, context));
+
+	if (!net_context_is_used(context)) {
+		return -EBADF;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		return net_offload_listen(net_context_get_iface(context),
+					  context, backlog);
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (net_tcp_listen(context) >= 0) {
+		k_mutex_unlock(&context->lock);
+		return 0;
+	}
+
+	k_mutex_unlock(&context->lock);
+
+	return -EOPNOTSUPP;
+}
+
+#if defined(CONFIG_NET_IPV4)
+int net_context_create_ipv4_new(struct net_context *context,
+				struct net_pkt *pkt,
+				const struct in_addr *src,
+				const struct in_addr *dst)
+{
+	if (!src) {
+		NET_ASSERT(((
+			struct sockaddr_in_ptr *)&context->local)->sin_addr);
+
+		src = ((struct sockaddr_in_ptr *)&context->local)->sin_addr;
+	}
+
+	if (net_ipv4_is_addr_unspecified(src)
+	    || net_ipv4_is_addr_mcast(src)) {
+		src = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
+						  (struct in_addr *)dst);
+		/* If src address is still unspecified, do not create pkt */
+		if (net_ipv4_is_addr_unspecified(src)) {
+			NET_DBG("DROP: src addr is unspecified");
+			return -EINVAL;
+		}
+	}
+
+	net_pkt_set_ipv4_ttl(pkt, net_context_get_ipv4_ttl(context));
+
+	return net_ipv4_create(pkt, src, dst);
+}
+#endif /* CONFIG_NET_IPV4 */
+
+#if defined(CONFIG_NET_IPV6)
+int net_context_create_ipv6_new(struct net_context *context,
+				struct net_pkt *pkt,
+				const struct in6_addr *src,
+				const struct in6_addr *dst)
+{
+	if (!src) {
+		NET_ASSERT(((
+			struct sockaddr_in6_ptr *)&context->local)->sin6_addr);
+
+		src = ((struct sockaddr_in6_ptr *)&context->local)->sin6_addr;
+	}
+
+	if (net_ipv6_is_addr_unspecified(src)
+	    || net_ipv6_is_addr_mcast(src)) {
+		src = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
+						  (struct in6_addr *)dst);
+	}
+
+	net_pkt_set_ipv6_hop_limit(pkt,
+				   net_context_get_ipv6_hop_limit(context));
+
+	return net_ipv6_create(pkt, src, dst);
+}
+#endif /* CONFIG_NET_IPV6 */
+
+int net_context_connect(struct net_context *context,
+			const struct sockaddr *addr,
+			socklen_t addrlen,
+			net_context_connect_cb_t cb,
+			k_timeout_t timeout,
+			void *user_data)
+{
+	struct sockaddr *laddr = NULL;
+	struct sockaddr local_addr __unused;
+	uint16_t lport, rport;
+	int ret;
+
+	NET_ASSERT(addr);
+	NET_ASSERT(PART_OF_ARRAY(contexts, context));
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (!net_context_is_used(context)) {
+		ret = -EBADF;
+		goto unlock;
+	}
+
+	if (addr->sa_family != net_context_get_family(context)) {
+		NET_ASSERT(addr->sa_family == net_context_get_family(context),
+			   "Family mismatch %d should be %d",
+			   addr->sa_family,
+			   net_context_get_family(context));
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+	    addr->sa_family == AF_PACKET) {
+		ret = -EOPNOTSUPP;
+		goto unlock;
+	}
+
+	if (net_context_get_state(context) == NET_CONTEXT_LISTENING) {
+		ret = -EOPNOTSUPP;
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)
+							&context->remote;
+
+		if (addrlen < sizeof(struct sockaddr_in6)) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+
+		if (net_context_get_ip_proto(context) == IPPROTO_TCP &&
+		    net_ipv6_is_addr_mcast(&addr6->sin6_addr)) {
+			ret = -EADDRNOTAVAIL;
+			goto unlock;
+		}
+
+		memcpy(&addr6->sin6_addr, &net_sin6(addr)->sin6_addr,
+		       sizeof(struct in6_addr));
+
+		addr6->sin6_port = net_sin6(addr)->sin6_port;
+		addr6->sin6_family = AF_INET6;
+
+		if (!net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
+			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
+		} else {
+			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
+		}
+
+		rport = addr6->sin6_port;
+
+		/* The binding must be done after we have set the remote
+		 * address but before checking the local address. Otherwise
+		 * the laddr might not be set properly which would then cause
+		 * issues when doing net_tcp_connect(). This issue was seen
+		 * with socket tests and when connecting to loopback interface.
+		 */
+		ret = bind_default(context);
+		if (ret) {
+			goto unlock;
+		}
+
+		net_sin6_ptr(&context->local)->sin6_family = AF_INET6;
+		net_sin6(&local_addr)->sin6_family = AF_INET6;
+		net_sin6(&local_addr)->sin6_port = lport =
+			net_sin6((struct sockaddr *)&context->local)->sin6_port;
+
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
+				     net_sin6_ptr(&context->local)->sin6_addr);
+
+			laddr = &local_addr;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		struct sockaddr_in *addr4 = (struct sockaddr_in *)
+							&context->remote;
+
+		if (addrlen < sizeof(struct sockaddr_in)) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+
+		/* FIXME - Add multicast and broadcast address check */
+
+		addr4 = (struct sockaddr_in *)&context->remote;
+
+		memcpy(&addr4->sin_addr, &net_sin(addr)->sin_addr,
+		       sizeof(struct in_addr));
+
+		addr4->sin_port = net_sin(addr)->sin_port;
+		addr4->sin_family = AF_INET;
+
+		if (addr4->sin_addr.s_addr) {
+			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
+		} else {
+			context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
+		}
+
+		rport = addr4->sin_port;
+
+		ret = bind_default(context);
+		if (ret) {
+			goto unlock;
+		}
+
+		net_sin_ptr(&context->local)->sin_family = AF_INET;
+		net_sin(&local_addr)->sin_family = AF_INET;
+		net_sin(&local_addr)->sin_port = lport =
+			net_sin((struct sockaddr *)&context->local)->sin_port;
+
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
+				       net_sin_ptr(&context->local)->sin_addr);
+
+			laddr = &local_addr;
+		}
+	} else {
+		ret = -EINVAL; /* Not IPv4 or IPv6 */
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		ret = net_offload_connect(
+			net_context_get_iface(context),
+			context,
+			addr,
+			addrlen,
+			cb,
+			timeout,
+			user_data);
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    net_context_get_type(context) == SOCK_DGRAM) {
+		if (cb) {
+			cb(context, 0, user_data);
+		}
+
+		ret = 0;
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   net_context_get_type(context) == SOCK_STREAM) {
+		ret = net_tcp_connect(context, addr, laddr, rport, lport,
+				      timeout, cb, user_data);
+	} else {
+		ret = -ENOTSUP;
+	}
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+int net_context_accept(struct net_context *context,
+		       net_tcp_accept_cb_t cb,
+		       k_timeout_t timeout,
+		       void *user_data)
+{
+	int ret = 0;
+
+	NET_ASSERT(PART_OF_ARRAY(contexts, context));
+
+	if (!net_context_is_used(context)) {
+		return -EBADF;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		ret = net_offload_accept(
+			net_context_get_iface(context),
+			context,
+			cb,
+			timeout,
+			user_data);
+		goto unlock;
+	}
+
+	if ((net_context_get_state(context) != NET_CONTEXT_LISTENING) &&
+	    (net_context_get_type(context) != SOCK_STREAM)) {
+		NET_DBG("Invalid socket, state %d type %d",
+			net_context_get_state(context),
+			net_context_get_type(context));
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		ret = net_tcp_accept(context, cb, user_data);
+		goto unlock;
+	}
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+
+static int get_context_priority(struct net_context *context,
+				void *value, size_t *len)
+{
+#if defined(CONFIG_NET_CONTEXT_PRIORITY)
+	*((uint8_t *)value) = context->options.priority;
+
+	if (len) {
+		*len = sizeof(uint8_t);
+	}
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+static int get_context_timepstamp(struct net_context *context,
+				  void *value, size_t *len)
+{
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+	*((bool *)value) = context->options.timestamp;
+
+	if (len) {
+		*len = sizeof(bool);
+	}
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+static int get_context_proxy(struct net_context *context,
+			     void *value, size_t *len)
+{
+#if defined(CONFIG_SOCKS)
+	struct sockaddr *addr = (struct sockaddr *)value;
+
+	if (!value || !len) {
+		return -EINVAL;
+	}
+
+	if (*len < context->options.proxy.addrlen) {
+		return -EINVAL;
+	}
+
+	*len = MIN(context->options.proxy.addrlen, *len);
+
+	memcpy(addr, &context->options.proxy.addr, *len);
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+int net_context_get_timestamp(struct net_context *context,
+			      struct net_pkt *pkt,
+			      struct net_ptp_time *timestamp)
+{
+	bool is_timestamped;
+
+	get_context_timepstamp(context, &is_timestamped, NULL);
+	if (is_timestamped) {
+		memcpy(timestamp, net_pkt_timestamp(pkt), sizeof(*timestamp));
+		return 0;
+	}
+
+	return -ENOENT;
+}
+#endif /* CONFIG_NET_CONTEXT_TIMESTAMP */
+
+static int get_context_txtime(struct net_context *context,
+			      void *value, size_t *len)
+{
+#if defined(CONFIG_NET_CONTEXT_TXTIME)
+	*((bool *)value) = context->options.txtime;
+
+	if (len) {
+		*len = sizeof(bool);
+	}
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+/* If buf is not NULL, then use it. Otherwise read the data to be written
+ * to net_pkt from msghdr.
+ */
+static int context_write_data(struct net_pkt *pkt, const void *buf,
+			      int buf_len, const struct msghdr *msghdr)
+{
+	int ret = 0;
+
+	if (msghdr) {
+		int i;
+
+		for (i = 0; i < msghdr->msg_iovlen; i++) {
+			ret = net_pkt_write(pkt, msghdr->msg_iov[i].iov_base,
+					    msghdr->msg_iov[i].iov_len);
+			if (ret < 0) {
+				break;
+			}
+		}
+	} else {
+		ret = net_pkt_write(pkt, buf, buf_len);
+	}
+
+	return ret;
+}
+
+static int context_setup_udp_packet(struct net_context *context,
+				    struct net_pkt *pkt,
+				    const void *buf,
+				    size_t len,
+				    const struct msghdr *msg,
+				    const struct sockaddr *dst_addr,
+				    socklen_t addrlen)
+{
+	int ret = -EINVAL;
+	uint16_t dst_port = 0U;
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)dst_addr;
+
+		dst_port = addr6->sin6_port;
+
+		ret = net_context_create_ipv6_new(context, pkt,
+						  NULL, &addr6->sin6_addr);
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		struct sockaddr_in *addr4 = (struct sockaddr_in *)dst_addr;
+
+		dst_port = addr4->sin_port;
+
+		ret = net_context_create_ipv4_new(context, pkt,
+						  NULL, &addr4->sin_addr);
+	}
+
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = bind_default(context);
+	if (ret) {
+		return ret;
+	}
+
+	ret = net_udp_create(pkt,
+			     net_sin((struct sockaddr *)
+				     &context->local)->sin_port,
+			     dst_port);
+	if (ret) {
+		return ret;
+	}
+
+	ret = context_write_data(pkt, buf, len, msg);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+static void context_finalize_packet(struct net_context *context,
+				    struct net_pkt *pkt)
+{
+	/* This function is meant to be temporary: once all moved to new
+	 * API, it will be up to net_send_data() to finalize the packet.
+	 */
+
+	net_pkt_cursor_init(pkt);
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		net_ipv6_finalize(pkt, net_context_get_ip_proto(context));
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		net_ipv4_finalize(pkt, net_context_get_ip_proto(context));
+	}
+}
+
+static struct net_pkt *context_alloc_pkt(struct net_context *context,
+					 size_t len, k_timeout_t timeout)
+{
+	struct net_pkt *pkt;
+
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+	if (context->tx_slab) {
+		pkt = net_pkt_alloc_from_slab(context->tx_slab(), timeout);
+		if (!pkt) {
+			return NULL;
+		}
+
+		net_pkt_set_iface(pkt, net_context_get_iface(context));
+		net_pkt_set_family(pkt, net_context_get_family(context));
+		net_pkt_set_context(pkt, context);
+
+		if (net_pkt_alloc_buffer(pkt, len,
+					 net_context_get_ip_proto(context),
+					 timeout)) {
+			net_pkt_unref(pkt);
+			return NULL;
+		}
+
+		return pkt;
+	}
+#endif
+	pkt = net_pkt_alloc_with_buffer(net_context_get_iface(context), len,
+					net_context_get_family(context),
+					net_context_get_ip_proto(context),
+					timeout);
+	if (pkt) {
+		net_pkt_set_context(pkt, context);
+	}
+
+	return pkt;
+}
+
+static void set_pkt_txtime(struct net_pkt *pkt, const struct msghdr *msghdr)
+{
+	struct cmsghdr *cmsg;
+
+	for (cmsg = CMSG_FIRSTHDR(msghdr); cmsg != NULL;
+	     cmsg = CMSG_NXTHDR(msghdr, cmsg)) {
+		if (cmsg->cmsg_len == CMSG_LEN(sizeof(uint64_t)) &&
+		    cmsg->cmsg_level == SOL_SOCKET &&
+		    cmsg->cmsg_type == SCM_TXTIME) {
+			uint64_t txtime = *(uint64_t *)CMSG_DATA(cmsg);
+
+			net_pkt_set_txtime(pkt, txtime);
+			break;
+		}
+	}
+}
+
+static int context_sendto(struct net_context *context,
+			  const void *buf,
+			  size_t len,
+			  const struct sockaddr *dst_addr,
+			  socklen_t addrlen,
+			  net_context_send_cb_t cb,
+			  k_timeout_t timeout,
+			  void *user_data,
+			  bool sendto)
+{
+	const struct msghdr *msghdr = NULL;
+	struct net_pkt *pkt;
+	size_t tmp_len;
+	int ret;
+
+	NET_ASSERT(PART_OF_ARRAY(contexts, context));
+
+	if (!net_context_is_used(context)) {
+		return -EBADF;
+	}
+
+	if (sendto && addrlen == 0 && dst_addr == NULL && buf != NULL) {
+		/* User wants to call sendmsg */
+		msghdr = buf;
+	}
+
+	if (!msghdr && !dst_addr) {
+		return -EDESTADDRREQ;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		const struct sockaddr_in6 *addr6 =
+			(const struct sockaddr_in6 *)dst_addr;
+
+		if (msghdr) {
+			addr6 = msghdr->msg_name;
+			addrlen = msghdr->msg_namelen;
+
+			if (!addr6) {
+				addr6 = net_sin6(&context->remote);
+				addrlen = sizeof(struct sockaddr_in6);
+			}
+
+			/* For sendmsg(), the dst_addr is NULL so set it here.
+			 */
+			dst_addr = (const struct sockaddr *)addr6;
+		}
+
+		if (addrlen < sizeof(struct sockaddr_in6)) {
+			return -EINVAL;
+		}
+
+		if (net_ipv6_is_addr_unspecified(&addr6->sin6_addr)) {
+			return -EDESTADDRREQ;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		const struct sockaddr_in *addr4 =
+			(const struct sockaddr_in *)dst_addr;
+
+		if (msghdr) {
+			addr4 = msghdr->msg_name;
+			addrlen = msghdr->msg_namelen;
+
+			if (!addr4) {
+				addr4 = net_sin(&context->remote);
+				addrlen = sizeof(struct sockaddr_in);
+			}
+
+			/* For sendmsg(), the dst_addr is NULL so set it here.
+			 */
+			dst_addr = (const struct sockaddr *)addr4;
+		}
+
+		if (addrlen < sizeof(struct sockaddr_in)) {
+			return -EINVAL;
+		}
+
+		if (!addr4->sin_addr.s_addr) {
+			return -EDESTADDRREQ;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		   net_context_get_family(context) == AF_PACKET) {
+		struct sockaddr_ll *ll_addr = (struct sockaddr_ll *)dst_addr;
+		struct net_if *iface;
+
+		if (msghdr) {
+			ll_addr = msghdr->msg_name;
+			addrlen = msghdr->msg_namelen;
+
+			if (!ll_addr) {
+				ll_addr = (struct sockaddr_ll *)
+							(&context->remote);
+				addrlen = sizeof(struct sockaddr_ll);
+			}
+
+			/* For sendmsg(), the dst_addr is NULL so set it here.
+			 */
+			dst_addr = (const struct sockaddr *)ll_addr;
+		}
+
+		if (addrlen < sizeof(struct sockaddr_ll)) {
+			return -EINVAL;
+		}
+
+		if (ll_addr->sll_ifindex < 0) {
+			return -EDESTADDRREQ;
+		}
+
+		iface = net_if_get_by_index(ll_addr->sll_ifindex);
+		if (!iface) {
+			NET_ERR("Cannot bind to interface index %d",
+				ll_addr->sll_ifindex);
+			return -EDESTADDRREQ;
+		}
+
+		if (net_context_get_type(context) == SOCK_DGRAM) {
+			context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
+
+			/* The user must set the protocol in send call */
+
+			/* For sendmsg() call, we might have set ll_addr to
+			 * point to remote addr.
+			 */
+			if ((void *)&context->remote != (void *)ll_addr) {
+				memcpy((struct sockaddr_ll *)&context->remote,
+				       ll_addr, sizeof(struct sockaddr_ll));
+			}
+		}
+
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+		   net_context_get_family(context) == AF_CAN) {
+		struct sockaddr_can *can_addr = (struct sockaddr_can *)dst_addr;
+		struct net_if *iface;
+
+		if (msghdr) {
+			can_addr = msghdr->msg_name;
+			addrlen = msghdr->msg_namelen;
+
+			if (!can_addr) {
+				can_addr = (struct sockaddr_can *)
+							(&context->remote);
+				addrlen = sizeof(struct sockaddr_can);
+			}
+
+			/* For sendmsg(), the dst_addr is NULL so set it here.
+			 */
+			dst_addr = (const struct sockaddr *)can_addr;
+		}
+
+		if (addrlen < sizeof(struct sockaddr_can)) {
+			return -EINVAL;
+		}
+
+		if (can_addr->can_ifindex < 0) {
+			/* The index should have been set in bind */
+			can_addr->can_ifindex =
+				net_can_ptr(&context->local)->can_ifindex;
+		}
+
+		if (can_addr->can_ifindex < 0) {
+			return -EDESTADDRREQ;
+		}
+
+		iface = net_if_get_by_index(can_addr->can_ifindex);
+		if (!iface) {
+			NET_ERR("Cannot bind to interface index %d",
+				can_addr->can_ifindex);
+			return -EDESTADDRREQ;
+		}
+	} else {
+		NET_DBG("Invalid protocol family %d",
+			net_context_get_family(context));
+		return -EINVAL;
+	}
+
+	if (msghdr && len == 0) {
+		int i;
+
+		for (i = 0; i < msghdr->msg_iovlen; i++) {
+			len += msghdr->msg_iov[i].iov_len;
+		}
+	}
+
+	pkt = context_alloc_pkt(context, len, PKT_WAIT_TIME);
+	if (!pkt) {
+		return -ENOBUFS;
+	}
+
+	tmp_len = net_pkt_available_payload_buffer(
+				pkt, net_context_get_ip_proto(context));
+	if (tmp_len < len) {
+		len = tmp_len;
+	}
+
+	context->send_cb = cb;
+	context->user_data = user_data;
+
+	if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
+		uint8_t priority;
+
+		get_context_priority(context, &priority, NULL);
+		net_pkt_set_priority(pkt, priority);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP)) {
+		bool timestamp;
+
+		get_context_timepstamp(context, &timestamp, NULL);
+		if (timestamp) {
+			struct net_ptp_time tp = {
+				/* Use the nanosecond field to temporarily
+				 * store the cycle count as it is a 32-bit
+				 * variable. The value is checked in
+				 * net_if.c:net_if_tx()
+				 *
+				 * The net_pkt timestamp field is used in two
+				 * roles here:
+				 * 1) To calculate how long it takes the packet
+				 *    from net_context to be sent by the
+				 *    network device driver.
+				 * 2) gPTP enabled Ethernet device driver will
+				 *    use the value to tell gPTP what time the
+				 *    packet was sent.
+				 *
+				 * Because these two things are happening at
+				 * different times, we can share the variable.
+				 */
+				.nanosecond = k_cycle_get_32(),
+			};
+
+			net_pkt_set_timestamp(pkt, &tp);
+		}
+	}
+
+	/* If there is ancillary data in msghdr, then we need to add that
+	 * to net_pkt as there is no other way to store it.
+	 */
+	if (msghdr && msghdr->msg_control && msghdr->msg_controllen) {
+		if (IS_ENABLED(CONFIG_NET_CONTEXT_TXTIME)) {
+			bool is_txtime;
+
+			get_context_txtime(context, &is_txtime, NULL);
+			if (is_txtime) {
+				set_pkt_txtime(pkt, msghdr);
+			}
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		ret = context_write_data(pkt, buf, len, msghdr);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		net_pkt_cursor_init(pkt);
+
+		if (sendto) {
+			ret = net_offload_sendto(net_context_get_iface(context),
+						 pkt, dst_addr, addrlen, cb,
+						 timeout, user_data);
+		} else {
+			ret = net_offload_send(net_context_get_iface(context),
+					       pkt, cb, timeout, user_data);
+		}
+	} else if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    net_context_get_ip_proto(context) == IPPROTO_UDP) {
+		ret = context_setup_udp_packet(context, pkt, buf, len, msghdr,
+					       dst_addr, addrlen);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		context_finalize_packet(context, pkt);
+
+		ret = net_send_data(pkt);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   net_context_get_ip_proto(context) == IPPROTO_TCP) {
+
+		ret = context_write_data(pkt, buf, len, msghdr);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		net_pkt_cursor_init(pkt);
+		ret = net_tcp_queue_data(context, pkt);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		ret = net_tcp_send_data(context, cb, user_data);
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		   net_context_get_family(context) == AF_PACKET) {
+		ret = context_write_data(pkt, buf, len, msghdr);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		net_pkt_cursor_init(pkt);
+
+		net_if_queue_tx(net_pkt_iface(pkt), pkt);
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+		   net_context_get_family(context) == AF_CAN &&
+		   net_context_get_ip_proto(context) == CAN_RAW) {
+		ret = context_write_data(pkt, buf, len, msghdr);
+		if (ret < 0) {
+			goto fail;
+		}
+
+		net_pkt_cursor_init(pkt);
+
+		ret = net_send_data(pkt);
+	} else {
+		NET_DBG("Unknown protocol while sending packet: %d",
+		net_context_get_ip_proto(context));
+		ret = -EPROTONOSUPPORT;
+	}
+
+	if (ret < 0) {
+		goto fail;
+	}
+
+	return len;
+fail:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+int net_context_send(struct net_context *context,
+		     const void *buf,
+		     size_t len,
+		     net_context_send_cb_t cb,
+		     k_timeout_t timeout,
+		     void *user_data)
+{
+	socklen_t addrlen;
+	int ret = 0;
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (!(context->flags & NET_CONTEXT_REMOTE_ADDR_SET) ||
+	    !net_sin(&context->remote)->sin_port) {
+		ret = -EDESTADDRREQ;
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		addrlen = sizeof(struct sockaddr_in6);
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		addrlen = sizeof(struct sockaddr_in);
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		   net_context_get_family(context) == AF_PACKET) {
+		ret = -EOPNOTSUPP;
+		goto unlock;
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+		   net_context_get_family(context) == AF_CAN) {
+		addrlen = sizeof(struct sockaddr_can);
+	} else {
+		addrlen = 0;
+	}
+
+	ret = context_sendto(context, buf, len, &context->remote,
+			     addrlen, cb, timeout, user_data, false);
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+int net_context_sendmsg(struct net_context *context,
+			const struct msghdr *msghdr,
+			int flags,
+			net_context_send_cb_t cb,
+			k_timeout_t timeout,
+			void *user_data)
+{
+	int ret;
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	ret = context_sendto(context, msghdr, 0, NULL, 0,
+			     cb, timeout, user_data, true);
+
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+int net_context_sendto(struct net_context *context,
+		       const void *buf,
+		       size_t len,
+		       const struct sockaddr *dst_addr,
+		       socklen_t addrlen,
+		       net_context_send_cb_t cb,
+		       k_timeout_t timeout,
+		       void *user_data)
+{
+	int ret;
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	ret = context_sendto(context, buf, len, dst_addr, addrlen,
+			     cb, timeout, user_data, true);
+
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+enum net_verdict net_context_packet_received(struct net_conn *conn,
+					     struct net_pkt *pkt,
+					     union net_ip_header *ip_hdr,
+					     union net_proto_header *proto_hdr,
+					     void *user_data)
+{
+	struct net_context *context = find_context(conn);
+	enum net_verdict verdict = NET_DROP;
+
+	NET_ASSERT(context);
+	NET_ASSERT(net_pkt_iface(pkt));
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	net_context_set_iface(context, net_pkt_iface(pkt));
+	net_pkt_set_context(pkt, context);
+
+	/* If there is no callback registered, then we can only drop
+	 * the packet.
+	 */
+	if (!context->recv_cb) {
+		goto unlock;
+	}
+
+	if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		net_stats_update_tcp_recv(net_pkt_iface(pkt),
+					  net_pkt_remaining_data(pkt));
+	}
+
+	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
+
+#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
+	k_sem_give(&context->recv_data_wait);
+#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
+
+	verdict = NET_OK;
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return verdict;
+}
+
+#if defined(CONFIG_NET_UDP)
+static int recv_udp(struct net_context *context,
+		    net_context_recv_cb_t cb,
+		    k_timeout_t timeout,
+		    void *user_data)
+{
+	struct sockaddr local_addr = {
+		.sa_family = net_context_get_family(context),
+	};
+	struct sockaddr *laddr = NULL;
+	uint16_t lport = 0U;
+	int ret;
+
+	ARG_UNUSED(timeout);
+
+	if (context->conn_handler) {
+		net_conn_unregister(context->conn_handler);
+		context->conn_handler = NULL;
+	}
+
+	ret = bind_default(context);
+	if (ret) {
+		return ret;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
+				     net_sin6_ptr(&context->local)->sin6_addr);
+
+			laddr = &local_addr;
+		}
+
+		net_sin6(&local_addr)->sin6_port =
+			net_sin6((struct sockaddr *)&context->local)->sin6_port;
+		lport = net_sin6((struct sockaddr *)&context->local)->sin6_port;
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
+				      net_sin_ptr(&context->local)->sin_addr);
+
+			laddr = &local_addr;
+		}
+
+		lport = net_sin((struct sockaddr *)&context->local)->sin_port;
+	}
+
+	context->recv_cb = cb;
+
+	ret = net_conn_register(net_context_get_ip_proto(context),
+				net_context_get_family(context),
+				context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
+							&context->remote : NULL,
+				laddr,
+				ntohs(net_sin(&context->remote)->sin_port),
+				ntohs(lport),
+				net_context_packet_received,
+				user_data,
+				&context->conn_handler);
+
+	return ret;
+}
+#else
+#define recv_udp(...) 0
+#endif /* CONFIG_NET_UDP */
+
+static enum net_verdict net_context_raw_packet_received(
+					struct net_conn *conn,
+					struct net_pkt *pkt,
+					union net_ip_header *ip_hdr,
+					union net_proto_header *proto_hdr,
+					void *user_data)
+{
+	struct net_context *context = find_context(conn);
+
+	NET_ASSERT(context);
+	NET_ASSERT(net_pkt_iface(pkt));
+
+	/* If there is no callback registered, then we can only drop
+	 * the packet.
+	 */
+
+	if (!context->recv_cb) {
+		return NET_DROP;
+	}
+
+	net_context_set_iface(context, net_pkt_iface(pkt));
+	net_pkt_set_context(pkt, context);
+
+	context->recv_cb(context, pkt, ip_hdr, proto_hdr, 0, user_data);
+
+#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
+	k_sem_give(&context->recv_data_wait);
+#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
+
+	return NET_OK;
+}
+
+static int recv_raw(struct net_context *context,
+		    net_context_recv_cb_t cb,
+		    k_timeout_t timeout,
+		    struct sockaddr *local_addr,
+		    void *user_data)
+{
+	int ret;
+
+	ARG_UNUSED(timeout);
+
+	context->recv_cb = cb;
+
+	if (context->conn_handler) {
+		net_conn_unregister(context->conn_handler);
+		context->conn_handler = NULL;
+	}
+
+	ret = bind_default(context);
+	if (ret) {
+		return ret;
+	}
+
+	ret = net_conn_register(net_context_get_ip_proto(context),
+				net_context_get_family(context),
+				NULL, local_addr, 0, 0,
+				net_context_raw_packet_received,
+				user_data,
+				&context->conn_handler);
+
+	return ret;
+}
+
+int net_context_recv(struct net_context *context,
+		     net_context_recv_cb_t cb,
+		     k_timeout_t timeout,
+		     void *user_data)
+{
+	int ret;
+	NET_ASSERT(context);
+
+	if (!net_context_is_used(context)) {
+		return -EBADF;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	    net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		ret = net_offload_recv(
+			net_context_get_iface(context),
+			context, cb, timeout, user_data);
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    net_context_get_ip_proto(context) == IPPROTO_UDP) {
+		ret = recv_udp(context, cb, timeout, user_data);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		ret = net_tcp_recv(context, cb, user_data);
+	} else {
+		if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		    net_context_get_family(context) == AF_PACKET) {
+			struct sockaddr_ll addr;
+
+			addr.sll_family = AF_PACKET;
+			addr.sll_ifindex =
+				net_sll_ptr(&context->local)->sll_ifindex;
+			addr.sll_protocol =
+				net_sll_ptr(&context->local)->sll_protocol;
+			addr.sll_halen =
+				net_sll_ptr(&context->local)->sll_halen;
+
+			memcpy(addr.sll_addr,
+			       net_sll_ptr(&context->local)->sll_addr,
+			       MIN(addr.sll_halen, sizeof(addr.sll_addr)));
+
+			ret = recv_raw(context, cb, timeout,
+				       (struct sockaddr *)&addr, user_data);
+		} else if (IS_ENABLED(CONFIG_NET_SOCKETS_CAN) &&
+			   net_context_get_family(context) == AF_CAN) {
+			struct sockaddr_can local_addr = {
+				.can_family = AF_CAN,
+			};
+
+			ret = recv_raw(context, cb, timeout,
+				       (struct sockaddr *)&local_addr,
+				       user_data);
+			if (ret == -EALREADY) {
+				/* This is perfectly normal for CAN sockets.
+				 * The SocketCAN will dispatch the packet to
+				 * correct net_context listener.
+				 */
+				ret = 0;
+			}
+		} else {
+			ret = -EPROTOTYPE;
+		}
+	}
+
+	if (ret < 0) {
+		goto unlock;
+	}
+
+#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
+	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
+		int ret;
+
+		/* Make sure we have the lock, then the
+		 * net_context_packet_received() callback will release the
+		 * semaphore when data has been received.
+		 */
+		k_sem_reset(&context->recv_data_wait);
+
+		k_mutex_unlock(&context->lock);
+
+		ret = k_sem_take(&context->recv_data_wait, timeout);
+
+		k_mutex_lock(&context->lock, K_FOREVER);
+
+		if (ret == -EAGAIN) {
+			ret = -ETIMEDOUT;
+			goto unlock;
+		}
+	}
+#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+int net_context_update_recv_wnd(struct net_context *context,
+				int32_t delta)
+{
+	int ret;
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		net_if_is_ip_offloaded(net_context_get_iface(context))) {
+		return 0;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	ret = net_tcp_update_recv_wnd(context, delta);
+
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+static int set_context_priority(struct net_context *context,
+				const void *value, size_t len)
+{
+#if defined(CONFIG_NET_CONTEXT_PRIORITY)
+	if (len > sizeof(uint8_t)) {
+		return -EINVAL;
+	}
+
+	context->options.priority = *((uint8_t *)value);
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+static int set_context_timestamp(struct net_context *context,
+				 const void *value, size_t len)
+{
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+	if (len > sizeof(bool)) {
+		return -EINVAL;
+	}
+
+	context->options.timestamp = *((bool *)value);
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+static int set_context_txtime(struct net_context *context,
+			      const void *value, size_t len)
+{
+#if defined(CONFIG_NET_CONTEXT_TXTIME)
+	if (len > sizeof(bool)) {
+		return -EINVAL;
+	}
+
+	context->options.txtime = *((bool *)value);
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+static int set_context_proxy(struct net_context *context,
+			     const void *value, size_t len)
+{
+#if defined(CONFIG_SOCKS)
+	struct sockaddr *addr = (struct sockaddr *)value;
+
+	if (len > NET_SOCKADDR_MAX_SIZE) {
+		return -EINVAL;
+	}
+
+	if (addr->sa_family != net_context_get_family(context)) {
+		return -EINVAL;
+	}
+
+	context->options.proxy.addrlen = len;
+	memcpy(&context->options.proxy.addr, addr, len);
+
+	return 0;
+#else
+	return -ENOTSUP;
+#endif
+}
+
+int net_context_set_option(struct net_context *context,
+			   enum net_context_option option,
+			   const void *value, size_t len)
+{
+	int ret = 0;
+
+	NET_ASSERT(context);
+
+	if (!PART_OF_ARRAY(contexts, context)) {
+		return -EINVAL;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	switch (option) {
+	case NET_OPT_PRIORITY:
+		ret = set_context_priority(context, value, len);
+		break;
+	case NET_OPT_TIMESTAMP:
+		ret = set_context_timestamp(context, value, len);
+		break;
+	case NET_OPT_TXTIME:
+		ret = set_context_txtime(context, value, len);
+		break;
+	case NET_OPT_SOCKS5:
+		ret = set_context_proxy(context, value, len);
+		break;
+	}
+
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+int net_context_get_option(struct net_context *context,
+			    enum net_context_option option,
+			    void *value, size_t *len)
+{
+	int ret = 0;
+
+	NET_ASSERT(context);
+
+	if (!PART_OF_ARRAY(contexts, context)) {
+		return -EINVAL;
+	}
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	switch (option) {
+	case NET_OPT_PRIORITY:
+		ret = get_context_priority(context, value, len);
+		break;
+	case NET_OPT_TIMESTAMP:
+		ret = get_context_timepstamp(context, value, len);
+		break;
+	case NET_OPT_TXTIME:
+		ret = get_context_txtime(context, value, len);
+		break;
+	case NET_OPT_SOCKS5:
+		ret = get_context_proxy(context, value, len);
+		break;
+	}
+
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+void net_context_foreach(net_context_cb_t cb, void *user_data)
+{
+	int i;
+
+	k_sem_take(&contexts_lock, K_FOREVER);
+
+	for (i = 0; i < NET_MAX_CONTEXT; i++) {
+		if (!net_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		k_mutex_lock(&contexts[i].lock, K_FOREVER);
+
+		cb(&contexts[i], user_data);
+
+		k_mutex_unlock(&contexts[i].lock);
+	}
+
+	k_sem_give(&contexts_lock);
+}
+
+const char *net_context_state(struct net_context *context)
+{
+	switch (net_context_get_state(context)) {
+	case NET_CONTEXT_IDLE:
+		return "IDLE";
+	case NET_CONTEXT_CONNECTING:
+		return "CONNECTING";
+	case NET_CONTEXT_CONNECTED:
+		return "CONNECTED";
+	case NET_CONTEXT_LISTENING:
+		return "LISTENING";
+	}
+
+	return NULL;
+}
+
+void net_context_init(void)
+{
+	k_sem_init(&contexts_lock, 1, UINT_MAX);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_core.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_core.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_core.c	(working copy)
@@ -0,0 +1,470 @@
+/** @file
+ * @brief Network initialization
+ *
+ * Initialize the network IP stack. Create one thread for reading data
+ * from IP stack and passing that data to applications (Rx thread).
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL);
+
+#include <init.h>
+#include <kernel.h>
+#include <toolchain.h>
+#include <linker/sections.h>
+#include <string.h>
+#include <errno.h>
+
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+#include <net/net_pkt.h>
+#include <net/net_core.h>
+#include <net/dns_resolve.h>
+#include <net/gptp.h>
+#include <net/websocket.h>
+
+#if defined(CONFIG_NET_LLDP)
+#include <net/lldp.h>
+#endif
+
+#include "net_private.h"
+#include "net_shell.h"
+
+#include "icmpv6.h"
+#include "ipv6.h"
+
+#include "icmpv4.h"
+
+#include "dhcpv4.h"
+
+#include "route.h"
+
+#include "packet_socket.h"
+#include "canbus_socket.h"
+
+#include "connection.h"
+#include "udp_internal.h"
+#include "tcp_internal.h"
+#include "ipv4_autoconf_internal.h"
+
+#include "net_stats.h"
+
+static inline enum net_verdict process_data(struct net_pkt *pkt,
+					    bool is_loopback)
+{
+	int ret;
+	bool locally_routed = false;
+
+	ret = net_packet_socket_input(pkt);
+	if (ret != NET_CONTINUE) {
+		return ret;
+	}
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+	/* If the packet is routed back to us when we have reassembled
+	 * an IPv6 packet, then do not pass it to L2 as the packet does
+	 * not have link layer headers in it.
+	 */
+	if (net_pkt_ipv6_fragment_start(pkt)) {
+		locally_routed = true;
+	}
+#endif
+
+	/* If there is no data, then drop the packet. */
+	if (!pkt->frags) {
+		NET_DBG("Corrupted packet (frags %p)", pkt->frags);
+		net_stats_update_processing_error(net_pkt_iface(pkt));
+
+		return NET_DROP;
+	}
+
+	if (!is_loopback && !locally_routed) {
+		ret = net_if_recv_data(net_pkt_iface(pkt), pkt);
+		if (ret != NET_CONTINUE) {
+			if (ret == NET_DROP) {
+				NET_DBG("Packet %p discarded by L2", pkt);
+				net_stats_update_processing_error(
+							net_pkt_iface(pkt));
+			}
+
+			return ret;
+		}
+	}
+
+	ret = net_canbus_socket_input(pkt);
+	if (ret != NET_CONTINUE) {
+		return ret;
+	}
+
+	/* L2 has modified the buffer starting point, it is easier
+	 * to re-initialize the cursor rather than updating it.
+	 */
+	net_pkt_cursor_init(pkt);
+
+	/* IP version and header length. */
+	switch (NET_IPV6_HDR(pkt)->vtc & 0xf0) {
+#if defined(CONFIG_NET_IPV6)
+	case 0x60:
+		return net_ipv6_input(pkt, is_loopback);
+#endif
+#if defined(CONFIG_NET_IPV4)
+	case 0x40:
+		return net_ipv4_input(pkt);
+#endif
+	}
+
+	NET_DBG("Unknown IP family packet (0x%x)",
+		NET_IPV6_HDR(pkt)->vtc & 0xf0);
+	net_stats_update_ip_errors_protoerr(net_pkt_iface(pkt));
+	net_stats_update_ip_errors_vhlerr(net_pkt_iface(pkt));
+
+	return NET_DROP;
+}
+
+static void processing_data(struct net_pkt *pkt, bool is_loopback)
+{
+	switch (process_data(pkt, is_loopback)) {
+	case NET_OK:
+		NET_DBG("Consumed pkt %p", pkt);
+		break;
+	case NET_DROP:
+	default:
+		NET_DBG("Dropping pkt %p", pkt);
+		net_pkt_unref(pkt);
+		break;
+	}
+}
+
+/* Things to setup after we are able to RX and TX */
+static void net_post_init(void)
+{
+#if defined(CONFIG_NET_LLDP)
+	net_lldp_init();
+#endif
+#if defined(CONFIG_NET_GPTP)
+	net_gptp_init();
+#endif
+}
+
+static void init_rx_queues(void)
+{
+	/* Starting TX side. The ordering is important here and the TX
+	 * can only be started when RX side is ready to receive packets.
+	 */
+	net_if_init();
+
+	net_tc_rx_init();
+
+	/* This will take the interface up and start everything. */
+	net_if_post_init();
+
+	/* Things to init after network interface is working */
+	net_post_init();
+}
+
+/* If loopback driver is enabled, then direct packets to it so the address
+ * check is not needed.
+ */
+#if defined(CONFIG_NET_IP_ADDR_CHECK) && !defined(CONFIG_NET_LOOPBACK)
+/* Check if the IPv{4|6} addresses are proper. As this can be expensive,
+ * make this optional.
+ */
+static inline int check_ip_addr(struct net_pkt *pkt)
+{
+#if defined(CONFIG_NET_IPV6)
+	if (net_pkt_family(pkt) == AF_INET6) {
+		if (net_ipv6_addr_cmp(&NET_IPV6_HDR(pkt)->dst,
+				      net_ipv6_unspecified_address())) {
+			NET_DBG("IPv6 dst address missing");
+			return -EADDRNOTAVAIL;
+		}
+
+		/* If the destination address is our own, then route it
+		 * back to us.
+		 */
+		if (net_ipv6_is_addr_loopback(&NET_IPV6_HDR(pkt)->dst) ||
+		    net_ipv6_is_my_addr(&NET_IPV6_HDR(pkt)->dst)) {
+			struct in6_addr addr;
+
+			/* Swap the addresses so that in receiving side
+			 * the packet is accepted.
+			 */
+			net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src);
+			net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src,
+					&NET_IPV6_HDR(pkt)->dst);
+			net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr);
+
+			return 1;
+		}
+
+		/* If the destination address is interface local scope
+		 * multicast address, then loop the data back to us.
+		 * The FF01:: multicast addresses are only meant to be used
+		 * in local host, so this is similar as how ::1 unicast
+		 * addresses are handled. See RFC 3513 ch 2.7 for details.
+		 */
+		if (net_ipv6_is_addr_mcast_iface(&NET_IPV6_HDR(pkt)->dst)) {
+			NET_DBG("IPv6 interface scope mcast dst address");
+			return 1;
+		}
+
+		/* The source check must be done after the destination check
+		 * as having src ::1 is perfectly ok if dst is ::1 too.
+		 */
+		if (net_ipv6_is_addr_loopback(&NET_IPV6_HDR(pkt)->src)) {
+			NET_DBG("IPv6 loopback src address");
+			return -EADDRNOTAVAIL;
+		}
+	} else
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+	if (net_pkt_family(pkt) == AF_INET) {
+		if (net_ipv4_addr_cmp(&NET_IPV4_HDR(pkt)->dst,
+				      net_ipv4_unspecified_address())) {
+			NET_DBG("IPv4 dst address missing");
+			return -EADDRNOTAVAIL;
+		}
+
+		/* If the destination address is our own, then route it
+		 * back to us.
+		 */
+		if (net_ipv4_is_addr_loopback(&NET_IPV4_HDR(pkt)->dst) ||
+		    (net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
+				     &NET_IPV4_HDR(pkt)->dst) == false &&
+		     net_ipv4_is_my_addr(&NET_IPV4_HDR(pkt)->dst))) {
+			struct in_addr addr;
+
+			/* Swap the addresses so that in receiving side
+			 * the packet is accepted.
+			 */
+			net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src);
+			net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src,
+					&NET_IPV4_HDR(pkt)->dst);
+			net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr);
+
+			return 1;
+		}
+
+		/* The source check must be done after the destination check
+		 * as having src 127.0.0.0/8 is perfectly ok if dst is in
+		 * localhost subnet too.
+		 */
+		if (net_ipv4_is_addr_loopback(&NET_IPV4_HDR(pkt)->src)) {
+			NET_DBG("IPv4 loopback src address");
+			return -EADDRNOTAVAIL;
+		}
+	} else
+#endif /* CONFIG_NET_IPV4 */
+
+	{
+		;
+	}
+
+	return 0;
+}
+#else
+#define check_ip_addr(pkt) 0
+#endif
+
+/* Called when data needs to be sent to network */
+int net_send_data(struct net_pkt *pkt)
+{
+	int status;
+
+	if (!pkt || !pkt->frags) {
+		return -ENODATA;
+	}
+
+	if (!net_pkt_iface(pkt)) {
+		return -EINVAL;
+	}
+
+#if defined(CONFIG_NET_STATISTICS)
+	switch (net_pkt_family(pkt)) {
+	case AF_INET:
+		net_stats_update_ipv4_sent(net_pkt_iface(pkt));
+		break;
+	case AF_INET6:
+		net_stats_update_ipv6_sent(net_pkt_iface(pkt));
+		break;
+	}
+#endif
+
+	net_pkt_trim_buffer(pkt);
+	net_pkt_cursor_init(pkt);
+
+	status = check_ip_addr(pkt);
+	if (status < 0) {
+		return status;
+	} else if (status > 0) {
+		/* Packet is destined back to us so send it directly
+		 * to RX processing.
+		 */
+		NET_DBG("Loopback pkt %p back to us", pkt);
+		processing_data(pkt, true);
+		return 0;
+	}
+
+	if (net_if_send_data(net_pkt_iface(pkt), pkt) == NET_DROP) {
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void net_rx(struct net_if *iface, struct net_pkt *pkt)
+{
+	bool is_loopback = false;
+	size_t pkt_len;
+
+	pkt_len = net_pkt_get_len(pkt);
+
+	NET_DBG("Received pkt %p len %zu", pkt, pkt_len);
+
+	net_stats_update_bytes_recv(iface, pkt_len);
+
+	if (IS_ENABLED(CONFIG_NET_LOOPBACK)) {
+#ifdef CONFIG_NET_L2_DUMMY
+		if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
+			is_loopback = true;
+		}
+#endif
+	}
+
+	processing_data(pkt, is_loopback);
+
+	net_print_statistics();
+	net_pkt_print();
+}
+
+static void process_rx_packet(struct k_work *work)
+{
+	struct net_pkt *pkt;
+
+	pkt = CONTAINER_OF(work, struct net_pkt, work);
+
+	net_pkt_set_rx_stats_tick(pkt, k_cycle_get_32());
+
+	net_rx(net_pkt_iface(pkt), pkt);
+}
+
+static void net_queue_rx(struct net_if *iface, struct net_pkt *pkt)
+{
+	uint8_t prio = net_pkt_priority(pkt);
+	uint8_t tc = net_rx_priority2tc(prio);
+
+	k_work_init(net_pkt_work(pkt), process_rx_packet);
+
+#if defined(CONFIG_NET_STATISTICS)
+	net_stats_update_tc_recv_pkt(iface, tc);
+	net_stats_update_tc_recv_bytes(iface, tc, net_pkt_get_len(pkt));
+	net_stats_update_tc_recv_priority(iface, tc, prio);
+#endif
+
+#if NET_TC_RX_COUNT > 1
+	NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
+#endif
+
+	net_tc_submit_to_rx_queue(tc, pkt);
+}
+
+/* Called by driver when an IP packet has been received */
+int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
+{
+	if (!pkt || !iface) {
+		return -EINVAL;
+	}
+
+	if (net_pkt_is_empty(pkt)) {
+		return -ENODATA;
+	}
+
+	if (!net_if_flag_is_set(iface, NET_IF_UP)) {
+		return -ENETDOWN;
+	}
+
+	net_pkt_set_overwrite(pkt, true);
+	net_pkt_cursor_init(pkt);
+
+	NET_DBG("prio %d iface %p pkt %p len %zu", net_pkt_priority(pkt),
+		iface, pkt, net_pkt_get_len(pkt));
+
+	if (IS_ENABLED(CONFIG_NET_ROUTING)) {
+		net_pkt_set_orig_iface(pkt, iface);
+	}
+
+	net_pkt_set_iface(pkt, iface);
+
+	net_queue_rx(iface, pkt);
+
+	return 0;
+}
+
+static inline void l3_init(void)
+{
+	net_icmpv4_init();
+	net_icmpv6_init();
+	net_ipv6_init();
+
+	net_ipv4_autoconf_init();
+
+	if (IS_ENABLED(CONFIG_NET_UDP) ||
+	    IS_ENABLED(CONFIG_NET_TCP) ||
+	    IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) ||
+	    IS_ENABLED(CONFIG_NET_SOCKETS_CAN)) {
+		net_conn_init();
+	}
+
+	net_tcp_init();
+
+	net_route_init();
+
+	NET_DBG("Network L3 init done");
+}
+
+static inline int services_init(void)
+{
+	int status;
+
+	status = net_dhcpv4_init();
+	if (status) {
+		return status;
+	}
+
+	dns_init_resolver();
+	websocket_init();
+
+	net_coap_init();
+
+	net_shell_init();
+
+	return status;
+}
+
+static int net_init(const struct device *unused)
+{
+	net_hostname_init();
+
+	NET_DBG("Priority %d", CONFIG_NET_INIT_PRIO);
+
+	net_pkt_init();
+
+	net_context_init();
+
+	l3_init();
+
+	net_mgmt_event_init();
+
+	init_rx_queues();
+
+	return services_init();
+}
+
+SYS_INIT(net_init, POST_KERNEL, CONFIG_NET_INIT_PRIO);
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_if.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_if.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_if.c	(working copy)
@@ -0,0 +1,3856 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL);
+
+#include <init.h>
+#include <kernel.h>
+#include <linker/sections.h>
+#include <random/rand32.h>
+#include <syscall_handler.h>
+#include <stdlib.h>
+#include <string.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+#include <net/ethernet.h>
+
+#include "net_private.h"
+#include "ipv6.h"
+#include "ipv4_autoconf_internal.h"
+
+#include "net_stats.h"
+
+#define REACHABLE_TIME (MSEC_PER_SEC * 30) /* in ms */
+/*
+ * split the min/max random reachable factors into numerator/denominator
+ * so that integer-based math works better
+ */
+#define MIN_RANDOM_NUMER (1)
+#define MIN_RANDOM_DENOM (2)
+#define MAX_RANDOM_NUMER (3)
+#define MAX_RANDOM_DENOM (2)
+
+/* net_if dedicated section limiters */
+extern struct net_if _net_if_list_start[];
+extern struct net_if _net_if_list_end[];
+
+#if defined(CONFIG_NET_NATIVE_IPV4) || defined(CONFIG_NET_NATIVE_IPV6)
+static struct net_if_router routers[CONFIG_NET_MAX_ROUTERS];
+static struct k_delayed_work router_timer;
+static sys_slist_t active_router_timers;
+#endif
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+/* Timer that triggers network address renewal */
+static struct k_delayed_work address_lifetime_timer;
+
+/* Track currently active address lifetime timers */
+static sys_slist_t active_address_lifetime_timers;
+
+/* Timer that triggers IPv6 prefix lifetime */
+static struct k_delayed_work prefix_lifetime_timer;
+
+/* Track currently active IPv6 prefix lifetime timers */
+static sys_slist_t active_prefix_lifetime_timers;
+
+#if defined(CONFIG_NET_IPV6_DAD)
+/** Duplicate address detection (DAD) timer */
+static struct k_delayed_work dad_timer;
+static sys_slist_t active_dad_timers;
+#endif
+
+#if defined(CONFIG_NET_IPV6_ND)
+static struct k_delayed_work rs_timer;
+static sys_slist_t active_rs_timers;
+#endif
+
+static struct {
+	struct net_if_ipv6 ipv6;
+	struct net_if *iface;
+} ipv6_addresses[CONFIG_NET_IF_MAX_IPV6_COUNT];
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_NATIVE_IPV4)
+static struct {
+	struct net_if_ipv4 ipv4;
+	struct net_if *iface;
+} ipv4_addresses[CONFIG_NET_IF_MAX_IPV4_COUNT];
+#endif /* CONFIG_NET_IPV4 */
+
+/* We keep track of the link callbacks in this list.
+ */
+static sys_slist_t link_callbacks;
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+/* Multicast join/leave tracking.
+ */
+static sys_slist_t mcast_monitor_callbacks;
+#endif
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD)
+#if !defined(CONFIG_NET_PKT_TIMESTAMP_STACK_SIZE)
+#define CONFIG_NET_PKT_TIMESTAMP_STACK_SIZE 1024
+#endif
+
+K_KERNEL_STACK_DEFINE(tx_ts_stack, CONFIG_NET_PKT_TIMESTAMP_STACK_SIZE);
+K_FIFO_DEFINE(tx_ts_queue);
+
+static struct k_thread tx_thread_ts;
+
+/* We keep track of the timestamp callbacks in this list.
+ */
+static sys_slist_t timestamp_callbacks;
+#endif /* CONFIG_NET_PKT_TIMESTAMP_THREAD */
+
+#if CONFIG_NET_IF_LOG_LEVEL >= LOG_LEVEL_DBG
+#define debug_check_packet(pkt)						\
+	do {								\
+		NET_DBG("Processing (pkt %p, prio %d) network packet "	\
+			"iface %p/%d",					\
+			pkt, net_pkt_priority(pkt),			\
+			net_pkt_iface(pkt),				\
+			net_if_get_by_iface(net_pkt_iface(pkt)));	\
+									\
+		NET_ASSERT(pkt->frags);					\
+	} while (0)
+#else
+#define debug_check_packet(...)
+#endif /* CONFIG_NET_IF_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+struct net_if *z_impl_net_if_get_by_index(int index)
+{
+	if (index <= 0) {
+		return NULL;
+	}
+
+	if (&_net_if_list_start[index - 1] >= _net_if_list_end) {
+		NET_DBG("Index %d is too large", index);
+		return NULL;
+	}
+
+	return &_net_if_list_start[index - 1];
+}
+
+#ifdef CONFIG_USERSPACE
+struct net_if *z_vrfy_net_if_get_by_index(int index)
+{
+	struct net_if *iface;
+	struct z_object *zo;
+	int ret;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return NULL;
+	}
+
+	zo = z_object_find(iface);
+
+	ret = z_object_validate(zo, K_OBJ_NET_IF, _OBJ_INIT_TRUE);
+	if (ret != 0) {
+		z_dump_object_error(ret, iface, zo, K_OBJ_NET_IF);
+		return NULL;
+	}
+
+	return iface;
+}
+
+#include <syscalls/net_if_get_by_index_mrsh.c>
+#endif
+
+static inline void net_context_send_cb(struct net_context *context,
+				       int status)
+{
+	if (!context) {
+		return;
+	}
+
+	if (context->send_cb) {
+		context->send_cb(context, status, context->user_data);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) &&
+	    net_context_get_ip_proto(context) == IPPROTO_UDP) {
+		net_stats_update_udp_sent(net_context_get_iface(context));
+	} else if (IS_ENABLED(CONFIG_NET_TCP) &&
+		   net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		net_stats_update_tcp_seg_sent(net_context_get_iface(context));
+	}
+}
+
+static void update_txtime_stats_detail(struct net_pkt *pkt,
+				       uint32_t start_time, uint32_t stop_time)
+{
+	uint32_t val, prev = start_time;
+	int i;
+
+	for (i = 0; i < net_pkt_stats_tick_count(pkt); i++) {
+		if (!net_pkt_stats_tick(pkt)[i]) {
+			break;
+		}
+
+		val = net_pkt_stats_tick(pkt)[i] - prev;
+		prev = net_pkt_stats_tick(pkt)[i];
+		net_pkt_stats_tick(pkt)[i] = val;
+	}
+}
+
+static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct net_linkaddr ll_dst = {
+		.addr = NULL
+	};
+	struct net_linkaddr_storage ll_dst_storage;
+	struct net_context *context;
+	int status;
+
+	/* Timestamp of the current network packet sent if enabled */
+	struct net_ptp_time start_timestamp;
+	uint32_t curr_time = 0;
+
+	/* We collect send statistics for each socket priority if enabled */
+	uint8_t pkt_priority;
+
+	if (!pkt) {
+		return false;
+	}
+
+	debug_check_packet(pkt);
+
+	/* If there're any link callbacks, with such a callback receiving
+	 * a destination address, copy that address out of packet, just in
+	 * case packet is freed before callback is called.
+	 */
+	if (!sys_slist_is_empty(&link_callbacks)) {
+		if (net_linkaddr_set(&ll_dst_storage,
+				     net_pkt_lladdr_dst(pkt)->addr,
+				     net_pkt_lladdr_dst(pkt)->len) == 0) {
+			ll_dst.addr = ll_dst_storage.addr;
+			ll_dst.len = ll_dst_storage.len;
+			ll_dst.type = net_pkt_lladdr_dst(pkt)->type;
+		}
+	}
+
+	context = net_pkt_context(pkt);
+
+	if (net_if_flag_is_set(iface, NET_IF_UP)) {
+		if (IS_ENABLED(CONFIG_NET_TCP) &&
+		    net_pkt_family(pkt) != AF_UNSPEC) {
+			net_pkt_set_queued(pkt, false);
+		}
+
+		if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && context) {
+			if (net_context_get_timestamp(context, pkt,
+						      &start_timestamp) < 0) {
+				start_timestamp.nanosecond = 0;
+			} else {
+				pkt_priority = net_pkt_priority(pkt);
+			}
+		}
+
+		if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
+			memcpy(&start_timestamp, net_pkt_timestamp(pkt),
+			       sizeof(start_timestamp));
+			pkt_priority = net_pkt_priority(pkt);
+
+			if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)) {
+				/* Make sure the statistics information is not
+				 * lost by keeping the net_pkt over L2 send.
+				 */
+				net_pkt_ref(pkt);
+			}
+		}
+
+		status = net_if_l2(iface)->send(iface, pkt);
+
+		if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && status >= 0 &&
+		    context) {
+			if (start_timestamp.nanosecond > 0) {
+				curr_time = k_cycle_get_32();
+			}
+		}
+
+		if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
+			uint32_t end_tick = k_cycle_get_32();
+
+			net_pkt_set_tx_stats_tick(pkt, end_tick);
+
+			net_stats_update_tc_tx_time(iface,
+						    pkt_priority,
+						    start_timestamp.nanosecond,
+						    end_tick);
+
+			if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)) {
+				update_txtime_stats_detail(
+					pkt,
+					start_timestamp.nanosecond,
+					end_tick);
+
+				net_stats_update_tc_tx_time_detail(
+					iface, pkt_priority,
+					net_pkt_stats_tick(pkt));
+
+				/* For TCP connections, we might keep the pkt
+				 * longer so that we can resend it if needed.
+				 * Because of that we need to clear the
+				 * statistics here.
+				 */
+				net_pkt_stats_tick_reset(pkt);
+
+				net_pkt_unref(pkt);
+			}
+		}
+
+	} else {
+		/* Drop packet if interface is not up */
+		NET_WARN("iface %p is down", iface);
+		status = -ENETDOWN;
+	}
+
+	if (status < 0) {
+		net_pkt_unref(pkt);
+	} else {
+		net_stats_update_bytes_sent(iface, status);
+	}
+
+	if (context) {
+		NET_DBG("Calling context send cb %p status %d",
+			context, status);
+
+		net_context_send_cb(context, status);
+
+		if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && status >= 0 &&
+		    start_timestamp.nanosecond && curr_time > 0) {
+			/* So we know now how long the network packet was in
+			 * transit from when it was allocated to when we
+			 * got information that it was sent successfully.
+			 */
+			net_stats_update_tc_tx_time(iface,
+						    pkt_priority,
+						    start_timestamp.nanosecond,
+						    curr_time);
+		}
+	}
+
+	if (ll_dst.addr) {
+		net_if_call_link_cb(iface, &ll_dst, status);
+	}
+
+	return true;
+}
+
+static void process_tx_packet(struct k_work *work)
+{
+	struct net_if *iface;
+	struct net_pkt *pkt;
+
+	pkt = CONTAINER_OF(work, struct net_pkt, work);
+
+	net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32());
+
+	iface = net_pkt_iface(pkt);
+
+	net_if_tx(iface, pkt);
+
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	iface->tx_pending--;
+#endif
+}
+
+void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
+{
+	uint8_t prio = net_pkt_priority(pkt);
+	uint8_t tc = net_tx_priority2tc(prio);
+
+	k_work_init(net_pkt_work(pkt), process_tx_packet);
+
+	net_stats_update_tc_sent_pkt(iface, tc);
+	net_stats_update_tc_sent_bytes(iface, tc, net_pkt_get_len(pkt));
+	net_stats_update_tc_sent_priority(iface, tc, prio);
+
+#if NET_TC_TX_COUNT > 1
+	NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
+#endif
+
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	iface->tx_pending++;
+#endif
+
+	if (!net_tc_submit_to_tx_queue(tc, pkt)) {
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+		iface->tx_pending--
+#endif
+			;
+	}
+}
+
+void net_if_stats_reset(struct net_if *iface)
+{
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+	Z_STRUCT_SECTION_FOREACH(net_if, tmp) {
+		if (iface == tmp) {
+			memset(&iface->stats, 0, sizeof(iface->stats));
+			return;
+		}
+	}
+#endif
+}
+
+void net_if_stats_reset_all(void)
+{
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		memset(&iface->stats, 0, sizeof(iface->stats));
+	}
+#endif
+}
+
+static inline void init_iface(struct net_if *iface)
+{
+	const struct net_if_api *api = net_if_get_device(iface)->api;
+
+	if (!api || !api->init) {
+		NET_ERR("Iface %p driver API init NULL", iface);
+		return;
+	}
+
+	NET_DBG("On iface %p", iface);
+
+#ifdef CONFIG_USERSPACE
+	z_object_init(iface);
+#endif
+
+	api->init(iface);
+}
+
+enum net_verdict net_if_send_data(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct net_context *context = net_pkt_context(pkt);
+	struct net_linkaddr *dst = net_pkt_lladdr_dst(pkt);
+	enum net_verdict verdict = NET_OK;
+	int status = -EIO;
+
+	if (!net_if_flag_is_set(iface, NET_IF_UP) ||
+	    net_if_flag_is_set(iface, NET_IF_SUSPENDED)) {
+		/* Drop packet if interface is not up */
+		NET_WARN("iface %p is down", iface);
+		verdict = NET_DROP;
+		status = -ENETDOWN;
+		goto done;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_OFFLOAD) && !net_if_l2(iface)) {
+		NET_WARN("no l2 for iface %p, discard pkt", iface);
+		verdict = NET_DROP;
+		goto done;
+	}
+
+	/* If the ll address is not set at all, then we must set
+	 * it here.
+	 * Workaround Linux bug, see:
+	 * https://github.com/zephyrproject-rtos/zephyr/issues/3111
+	 */
+	if (!net_if_flag_is_set(iface, NET_IF_POINTOPOINT) &&
+	    !net_pkt_lladdr_src(pkt)->addr) {
+		net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
+		net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
+	}
+
+#if defined(CONFIG_NET_LOOPBACK)
+	/* If the packet is destined back to us, then there is no need to do
+	 * additional checks, so let the packet through.
+	 */
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
+		goto done;
+	}
+#endif
+
+	/* If the ll dst address is not set check if it is present in the nbr
+	 * cache.
+	 */
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		verdict = net_ipv6_prepare_for_send(pkt);
+	}
+
+done:
+	/*   NET_OK in which case packet has checked successfully. In this case
+	 *   the net_context callback is called after successful delivery in
+	 *   net_if_tx_thread().
+	 *
+	 *   NET_DROP in which case we call net_context callback that will
+	 *   give the status to user application.
+	 *
+	 *   NET_CONTINUE in which case the sending of the packet is delayed.
+	 *   This can happen for example if we need to do IPv6 ND to figure
+	 *   out link layer address.
+	 */
+	if (verdict == NET_DROP) {
+		if (context) {
+			NET_DBG("Calling ctx send cb %p verdict %d",
+				context, verdict);
+			net_context_send_cb(context, status);
+		}
+
+		if (dst->addr) {
+			net_if_call_link_cb(iface, dst, status);
+		}
+	} else if (verdict == NET_OK) {
+		/* Packet is ready to be sent by L2, let's queue */
+		net_if_queue_tx(iface, pkt);
+	}
+
+	return verdict;
+}
+
+struct net_if *net_if_get_by_link_addr(struct net_linkaddr *ll_addr)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (!memcmp(net_if_get_link_addr(iface)->addr, ll_addr->addr,
+			    ll_addr->len)) {
+			return iface;
+		}
+	}
+
+	return NULL;
+}
+
+struct net_if *net_if_lookup_by_dev(const struct device *dev)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (net_if_get_device(iface) == dev) {
+			return iface;
+		}
+	}
+
+	return NULL;
+}
+
+struct net_if *net_if_get_default(void)
+{
+	struct net_if *iface = NULL;
+
+	if (_net_if_list_start == _net_if_list_end) {
+		return NULL;
+	}
+
+#if defined(CONFIG_NET_DEFAULT_IF_ETHERNET)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_IEEE802154)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(IEEE802154));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_BLUETOOTH)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(BLUETOOTH));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_DUMMY)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_OFFLOAD)
+	iface = net_if_get_first_by_type(NULL);
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_CANBUS_RAW)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS_RAW));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_CANBUS)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS));
+#endif
+#if defined(CONFIG_NET_DEFAULT_IF_PPP)
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(PPP));
+#endif
+
+	return iface ? iface : _net_if_list_start;
+}
+
+struct net_if *net_if_get_first_by_type(const struct net_l2 *l2)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+		    !l2 && net_if_offload(iface)) {
+			return iface;
+		}
+
+		if (net_if_l2(iface) == l2) {
+			return iface;
+		}
+	}
+
+	return NULL;
+}
+
+static enum net_l2_flags l2_flags_get(struct net_if *iface)
+{
+	enum net_l2_flags flags = 0;
+
+	if (net_if_l2(iface) && net_if_l2(iface)->get_flags) {
+		flags = net_if_l2(iface)->get_flags(iface);
+	}
+
+	return flags;
+}
+
+#if defined(CONFIG_NET_NATIVE_IPV4) || defined(CONFIG_NET_NATIVE_IPV6)
+/* Return how many bits are shared between two IP addresses */
+static uint8_t get_ipaddr_diff(const uint8_t *src, const uint8_t *dst, int addr_len)
+{
+	uint8_t j, k, xor;
+	uint8_t len = 0U;
+
+	for (j = 0U; j < addr_len; j++) {
+		if (src[j] == dst[j]) {
+			len += 8U;
+		} else {
+			xor = src[j] ^ dst[j];
+			for (k = 0U; k < 8; k++) {
+				if (!(xor & 0x80)) {
+					len++;
+					xor <<= 1;
+				} else {
+					break;
+				}
+			}
+			break;
+		}
+	}
+
+	return len;
+}
+
+static struct net_if_router *iface_router_lookup(struct net_if *iface,
+						 uint8_t family, void *addr)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTERS; i++) {
+		if (!routers[i].is_used ||
+		    routers[i].address.family != family ||
+		    routers[i].iface != iface) {
+			continue;
+		}
+
+		if ((IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6 &&
+		     net_ipv6_addr_cmp(net_if_router_ipv6(&routers[i]),
+				       (struct in6_addr *)addr)) ||
+		    (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET &&
+		     net_ipv4_addr_cmp(net_if_router_ipv4(&routers[i]),
+				       (struct in_addr *)addr))) {
+			return &routers[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void iface_router_notify_deletion(struct net_if_router *router,
+					 const char *delete_reason)
+{
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    router->address.family == AF_INET6) {
+		NET_DBG("IPv6 router %s %s",
+			log_strdup(net_sprint_ipv6_addr(
+					   net_if_router_ipv6(router))),
+			delete_reason);
+
+		net_mgmt_event_notify_with_info(NET_EVENT_IPV6_ROUTER_DEL,
+						router->iface,
+						&router->address.in6_addr,
+						sizeof(struct in6_addr));
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   router->address.family == AF_INET) {
+		NET_DBG("IPv4 router %s %s",
+			log_strdup(net_sprint_ipv4_addr(
+					   net_if_router_ipv4(router))),
+			delete_reason);
+
+		net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ROUTER_DEL,
+						router->iface,
+						&router->address.in_addr,
+						sizeof(struct in6_addr));
+	}
+}
+
+
+static void iface_router_run_timer(uint32_t current_time)
+{
+	struct net_if_router *router, *next;
+	uint32_t new_timer = UINT_MAX;
+
+	if (k_delayed_work_remaining_get(&router_timer)) {
+		k_delayed_work_cancel(&router_timer);
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_router_timers,
+					 router, next, node) {
+		uint32_t current_timer = router->life_start +
+			(MSEC_PER_SEC * router->lifetime) - current_time;
+
+		new_timer = MIN(current_timer, new_timer);
+	}
+
+	if (new_timer != UINT_MAX) {
+		k_delayed_work_submit(&router_timer, K_MSEC(new_timer));
+	}
+}
+
+static void iface_router_expired(struct k_work *work)
+{
+	uint32_t current_time = k_uptime_get_32();
+	struct net_if_router *router, *next;
+	sys_snode_t *prev_node = NULL;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_router_timers,
+					  router, next, node) {
+
+		if ((int32_t)(router->life_start +
+			    (MSEC_PER_SEC * router->lifetime) -
+			    current_time) > 0) {
+			/* We have to loop on all active routers as their
+			 * lifetime differ from each other.
+			 */
+			prev_node = &router->node;
+			continue;
+		}
+
+		iface_router_notify_deletion(router, "has expired");
+		sys_slist_remove(&active_router_timers,
+				 prev_node, &router->node);
+		router->is_used = false;
+	}
+
+	iface_router_run_timer(current_time);
+}
+
+static struct net_if_router *iface_router_add(struct net_if *iface,
+					      uint8_t family, void *addr,
+					      bool is_default,
+					      uint16_t lifetime)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTERS; i++) {
+		if (routers[i].is_used) {
+			continue;
+		}
+
+		routers[i].is_used = true;
+		routers[i].iface = iface;
+		routers[i].address.family = family;
+
+		if (lifetime) {
+			routers[i].is_default = true;
+			routers[i].is_infinite = false;
+			routers[i].lifetime = lifetime;
+			routers[i].life_start = k_uptime_get_32();
+
+			sys_slist_append(&active_router_timers,
+					 &routers[i].node);
+
+			iface_router_run_timer(routers[i].life_start);
+		} else {
+			routers[i].is_default = false;
+			routers[i].is_infinite = true;
+			routers[i].lifetime = 0;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+			memcpy(net_if_router_ipv6(&routers[i]), addr,
+			       sizeof(struct in6_addr));
+			net_mgmt_event_notify_with_info(
+					NET_EVENT_IPV6_ROUTER_ADD, iface,
+					&routers[i].address.in6_addr,
+					sizeof(struct in6_addr));
+
+			NET_DBG("interface %p router %s lifetime %u default %d "
+				"added", iface,
+				log_strdup(net_sprint_ipv6_addr(
+						   (struct in6_addr *)addr)),
+				lifetime, routers[i].is_default);
+		} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+			memcpy(net_if_router_ipv4(&routers[i]), addr,
+			       sizeof(struct in_addr));
+			routers[i].is_default = is_default;
+
+			net_mgmt_event_notify_with_info(
+					NET_EVENT_IPV4_ROUTER_ADD, iface,
+					&routers[i].address.in_addr,
+					sizeof(struct in_addr));
+
+			NET_DBG("interface %p router %s lifetime %u default %d "
+				"added", iface,
+				log_strdup(net_sprint_ipv4_addr(
+						   (struct in_addr *)addr)),
+				lifetime, is_default);
+		}
+
+		return &routers[i];
+	}
+
+	return NULL;
+}
+
+static bool iface_router_rm(struct net_if_router *router)
+{
+	if (!router->is_used) {
+		return false;
+	}
+
+	iface_router_notify_deletion(router, "has been removed");
+
+	/* We recompute the timer if only the router was time limited */
+	if (sys_slist_find_and_remove(&active_router_timers, &router->node)) {
+		iface_router_run_timer(k_uptime_get_32());
+	}
+
+	router->is_used = false;
+
+	return true;
+}
+
+static struct net_if_router *iface_router_find_default(struct net_if *iface,
+						       uint8_t family, void *addr)
+{
+	int i;
+
+	/* Todo: addr will need to be handled */
+	ARG_UNUSED(addr);
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTERS; i++) {
+		if (!routers[i].is_used ||
+		    !routers[i].is_default ||
+		    routers[i].address.family != family) {
+			continue;
+		}
+
+		if (iface && iface != routers[i].iface) {
+			continue;
+		}
+
+		return &routers[i];
+	}
+
+	return NULL;
+}
+
+static void iface_router_init(void)
+{
+	k_delayed_work_init(&router_timer, iface_router_expired);
+	sys_slist_init(&active_router_timers);
+}
+#else
+#define iface_router_init(...)
+#endif
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+int net_if_config_ipv6_get(struct net_if *iface, struct net_if_ipv6 **ipv6)
+{
+	int i;
+
+	if (iface->config.ip.ipv6) {
+		if (ipv6) {
+			*ipv6 = iface->config.ip.ipv6;
+		}
+
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv6_addresses); i++) {
+		if (ipv6_addresses[i].iface) {
+			continue;
+		}
+
+		iface->config.ip.ipv6 = &ipv6_addresses[i].ipv6;
+		ipv6_addresses[i].iface = iface;
+
+		if (ipv6) {
+			*ipv6 = &ipv6_addresses[i].ipv6;
+		}
+
+		return 0;
+	}
+
+	return -ESRCH;
+}
+
+int net_if_config_ipv6_put(struct net_if *iface)
+{
+	int i;
+
+	if (!iface->config.ip.ipv6) {
+		return -EALREADY;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv6_addresses); i++) {
+		if (ipv6_addresses[i].iface != iface) {
+			continue;
+		}
+
+		iface->config.ip.ipv6 = NULL;
+		ipv6_addresses[i].iface = NULL;
+
+		return 0;
+	}
+
+	return -ESRCH;
+}
+
+#if defined(CONFIG_NET_IPV6_MLD)
+static void join_mcast_allnodes(struct net_if *iface)
+{
+	struct in6_addr addr;
+	int ret;
+
+	net_ipv6_addr_create_ll_allnodes_mcast(&addr);
+
+	ret = net_ipv6_mld_join(iface, &addr);
+	if (ret < 0 && ret != -EALREADY) {
+		NET_ERR("Cannot join all nodes address %s (%d)",
+			log_strdup(net_sprint_ipv6_addr(&addr)), ret);
+	}
+}
+
+static void join_mcast_solicit_node(struct net_if *iface,
+				    struct in6_addr *my_addr)
+{
+	struct in6_addr addr;
+	int ret;
+
+	/* Join to needed multicast groups, RFC 4291 ch 2.8 */
+	net_ipv6_addr_create_solicited_node(my_addr, &addr);
+
+	ret = net_ipv6_mld_join(iface, &addr);
+	if (ret < 0 && ret != -EALREADY) {
+		NET_ERR("Cannot join solicit node address %s (%d)",
+			log_strdup(net_sprint_ipv6_addr(&addr)), ret);
+	}
+}
+
+static void leave_mcast_all(struct net_if *iface)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		if (!ipv6->mcast[i].is_used ||
+		    !ipv6->mcast[i].is_joined) {
+			continue;
+		}
+
+		net_ipv6_mld_leave(iface, &ipv6->mcast[i].address.in6_addr);
+	}
+}
+
+static void join_mcast_nodes(struct net_if *iface, struct in6_addr *addr)
+{
+	enum net_l2_flags flags = 0;
+
+	flags = l2_flags_get(iface);
+	if (flags & NET_L2_MULTICAST) {
+		join_mcast_allnodes(iface);
+
+		if (!(flags & NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE)) {
+			join_mcast_solicit_node(iface, addr);
+		}
+	}
+}
+#else
+#define join_mcast_allnodes(...)
+#define join_mcast_solicit_node(...)
+#define leave_mcast_all(...)
+#define join_mcast_nodes(...)
+#endif /* CONFIG_NET_IPV6_MLD */
+
+#if defined(CONFIG_NET_IPV6_DAD)
+#define DAD_TIMEOUT 100 /* ms */
+
+static void dad_timeout(struct k_work *work)
+{
+	uint32_t current_time = k_uptime_get_32();
+	struct net_if_addr *ifaddr, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_dad_timers,
+					  ifaddr, next, dad_node) {
+		struct net_if_addr *tmp;
+		struct net_if *iface;
+
+		if ((int32_t)(ifaddr->dad_start +
+			    DAD_TIMEOUT - current_time) > 0) {
+			break;
+		}
+
+		/* Removing the ifaddr from active_dad_timers list */
+		sys_slist_remove(&active_dad_timers, NULL, &ifaddr->dad_node);
+
+		NET_DBG("DAD succeeded for %s",
+			log_strdup(net_sprint_ipv6_addr(
+					   &ifaddr->address.in6_addr)));
+
+		ifaddr->addr_state = NET_ADDR_PREFERRED;
+
+		/* Because we do not know the interface at this point,
+		 * we need to lookup for it.
+		 */
+		iface = NULL;
+		tmp = net_if_ipv6_addr_lookup(&ifaddr->address.in6_addr,
+					      &iface);
+		if (tmp == ifaddr) {
+			net_mgmt_event_notify_with_info(
+					NET_EVENT_IPV6_DAD_SUCCEED,
+					iface, &ifaddr->address.in6_addr,
+					sizeof(struct in6_addr));
+
+			/* The address gets added to neighbor cache which is not
+			 * needed in this case as the address is our own one.
+			 */
+			net_ipv6_nbr_rm(iface, &ifaddr->address.in6_addr);
+		}
+
+		ifaddr = NULL;
+	}
+
+	if (ifaddr) {
+		k_delayed_work_submit(&dad_timer,
+				      K_MSEC(ifaddr->dad_start +
+					     DAD_TIMEOUT - current_time));
+	}
+}
+
+static void net_if_ipv6_start_dad(struct net_if *iface,
+				  struct net_if_addr *ifaddr)
+{
+	ifaddr->addr_state = NET_ADDR_TENTATIVE;
+
+	if (net_if_is_up(iface)) {
+		NET_DBG("Interface %p ll addr %s tentative IPv6 addr %s",
+			iface,
+			log_strdup(net_sprint_ll_addr(
+					   net_if_get_link_addr(iface)->addr,
+					   net_if_get_link_addr(iface)->len)),
+			log_strdup(net_sprint_ipv6_addr(
+					   &ifaddr->address.in6_addr)));
+
+		ifaddr->dad_count = 1U;
+
+		if (!net_ipv6_start_dad(iface, ifaddr)) {
+			ifaddr->dad_start = k_uptime_get_32();
+			sys_slist_append(&active_dad_timers, &ifaddr->dad_node);
+
+			if (!k_delayed_work_remaining_get(&dad_timer)) {
+				k_delayed_work_submit(&dad_timer,
+						      K_MSEC(DAD_TIMEOUT));
+			}
+		}
+	} else {
+		NET_DBG("Interface %p is down, starting DAD for %s later.",
+			iface,
+			log_strdup(net_sprint_ipv6_addr(
+					   &ifaddr->address.in6_addr)));
+	}
+}
+
+void net_if_start_dad(struct net_if *iface)
+{
+	struct net_if_addr *ifaddr;
+	struct net_if_ipv6 *ipv6;
+	struct in6_addr addr = { };
+	int i;
+
+	NET_DBG("Starting DAD for iface %p", iface);
+
+	if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
+		NET_WARN("Cannot do DAD IPv6 config is not valid.");
+		return;
+	}
+
+	if (!ipv6) {
+		return;
+	}
+
+	net_ipv6_addr_create_iid(&addr, net_if_get_link_addr(iface));
+
+	ifaddr = net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, 0);
+	if (!ifaddr) {
+		NET_ERR("Cannot add %s address to interface %p, DAD fails",
+			log_strdup(net_sprint_ipv6_addr(&addr)), iface);
+	}
+
+	/* Start DAD for all the addresses that were added earlier when
+	 * the interface was down.
+	 */
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used ||
+		    ipv6->unicast[i].address.family != AF_INET6 ||
+		    &ipv6->unicast[i] == ifaddr) {
+			continue;
+		}
+
+		net_if_ipv6_start_dad(iface, &ipv6->unicast[i]);
+	}
+}
+
+void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr)
+{
+	struct net_if_addr *ifaddr;
+
+	ifaddr = net_if_ipv6_addr_lookup(addr, &iface);
+	if (!ifaddr) {
+		NET_ERR("Cannot find %s address in interface %p",
+			log_strdup(net_sprint_ipv6_addr(addr)), iface);
+		return;
+	}
+
+	sys_slist_find_and_remove(&active_dad_timers, &ifaddr->dad_node);
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_DAD_FAILED, iface,
+					&ifaddr->address.in6_addr,
+					sizeof(struct in6_addr));
+
+	net_if_ipv6_addr_rm(iface, addr);
+}
+
+static inline void iface_ipv6_dad_init(void)
+{
+	k_delayed_work_init(&dad_timer, dad_timeout);
+	sys_slist_init(&active_dad_timers);
+}
+
+#else
+static inline void net_if_ipv6_start_dad(struct net_if *iface,
+					 struct net_if_addr *ifaddr)
+{
+	ifaddr->addr_state = NET_ADDR_PREFERRED;
+}
+
+#define iface_ipv6_dad_init(...)
+#endif /* CONFIG_NET_IPV6_DAD */
+
+#if defined(CONFIG_NET_IPV6_ND)
+#define RS_TIMEOUT (1 * MSEC_PER_SEC)
+#define RS_COUNT 3
+
+static void rs_timeout(struct k_work *work)
+{
+	uint32_t current_time = k_uptime_get_32();
+	struct net_if_ipv6 *ipv6, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_rs_timers,
+					  ipv6, next, rs_node) {
+		struct net_if *iface = NULL;
+
+		if ((int32_t)(ipv6->rs_start + RS_TIMEOUT - current_time) > 0) {
+			break;
+		}
+
+		/* Removing the ipv6 from active_rs_timers list */
+		sys_slist_remove(&active_rs_timers, NULL, &ipv6->rs_node);
+
+		/* Did not receive RA yet. */
+		ipv6->rs_count++;
+
+		Z_STRUCT_SECTION_FOREACH(net_if, tmp) {
+			if (tmp->config.ip.ipv6 == ipv6) {
+				iface = tmp;
+				break;
+			}
+		}
+
+		if (iface) {
+			NET_DBG("RS no respond iface %p count %d",
+				iface, ipv6->rs_count);
+			if (ipv6->rs_count < RS_COUNT) {
+				net_if_start_rs(iface);
+			}
+		} else {
+			NET_DBG("Interface IPv6 config %p not found", ipv6);
+		}
+
+		ipv6 = NULL;
+	}
+
+	if (ipv6) {
+		k_delayed_work_submit(&rs_timer,
+				      K_MSEC(ipv6->rs_start +
+					     RS_TIMEOUT - current_time));
+	}
+}
+
+void net_if_start_rs(struct net_if *iface)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+
+	if (!ipv6) {
+		return;
+	}
+
+	NET_DBG("Starting ND/RS for iface %p", iface);
+
+	if (!net_ipv6_start_rs(iface)) {
+		ipv6->rs_start = k_uptime_get_32();
+		sys_slist_append(&active_rs_timers, &ipv6->rs_node);
+
+		if (!k_delayed_work_remaining_get(&rs_timer)) {
+			k_delayed_work_submit(&rs_timer, K_MSEC(RS_TIMEOUT));
+		}
+	}
+}
+
+void net_if_stop_rs(struct net_if *iface)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+
+	if (!ipv6) {
+		return;
+	}
+
+	NET_DBG("Stopping ND/RS for iface %p", iface);
+
+	sys_slist_find_and_remove(&active_rs_timers, &ipv6->rs_node);
+}
+
+static inline void iface_ipv6_nd_init(void)
+{
+	k_delayed_work_init(&rs_timer, rs_timeout);
+	sys_slist_init(&active_rs_timers);
+}
+
+#else
+#define net_if_start_rs(...)
+#define net_if_stop_rs(...)
+#define iface_ipv6_nd_init(...)
+#endif /* CONFIG_NET_IPV6_ND */
+
+struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
+					    struct net_if **ret)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+		int i;
+
+		if (!ipv6) {
+			continue;
+		}
+
+		for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+			if (!ipv6->unicast[i].is_used ||
+			    ipv6->unicast[i].address.family != AF_INET6) {
+				continue;
+			}
+
+			if (net_ipv6_is_prefix(
+				    addr->s6_addr,
+				    ipv6->unicast[i].address.in6_addr.s6_addr,
+				    128)) {
+
+				if (ret) {
+					*ret = iface;
+				}
+
+				return &ipv6->unicast[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+struct net_if_addr *net_if_ipv6_addr_lookup_by_iface(struct net_if *iface,
+						     struct in6_addr *addr)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used ||
+		    ipv6->unicast[i].address.family != AF_INET6) {
+			continue;
+		}
+
+		if (net_ipv6_is_prefix(
+			    addr->s6_addr,
+			    ipv6->unicast[i].address.in6_addr.s6_addr,
+			    128)) {
+			return &ipv6->unicast[i];
+		}
+	}
+
+	return NULL;
+}
+
+int z_impl_net_if_ipv6_addr_lookup_by_index(const struct in6_addr *addr)
+{
+	struct net_if *iface = NULL;
+	struct net_if_addr *if_addr;
+
+	if_addr = net_if_ipv6_addr_lookup(addr, &iface);
+	if (!if_addr) {
+		return 0;
+	}
+
+	return net_if_get_by_iface(iface);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_net_if_ipv6_addr_lookup_by_index(
+					  const struct in6_addr *addr)
+{
+	struct in6_addr addr_v6;
+
+	Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6)));
+
+	return z_impl_net_if_ipv6_addr_lookup_by_index(&addr_v6);
+}
+#include <syscalls/net_if_ipv6_addr_lookup_by_index_mrsh.c>
+#endif
+
+static bool check_timeout(uint32_t start, int32_t timeout, uint32_t counter,
+			  uint32_t current_time)
+{
+	if (counter > 0) {
+		return false;
+	}
+
+	if ((int32_t)((start + (uint32_t)timeout) - current_time) > 0) {
+		return false;
+	}
+
+	return true;
+}
+
+static void address_expired(struct net_if_addr *ifaddr)
+{
+	NET_DBG("IPv6 address %s is deprecated",
+		log_strdup(net_sprint_ipv6_addr(&ifaddr->address.in6_addr)));
+
+	ifaddr->addr_state = NET_ADDR_DEPRECATED;
+	ifaddr->lifetime.timer_timeout = 0;
+	ifaddr->lifetime.wrap_counter = 0;
+
+	sys_slist_find_and_remove(&active_address_lifetime_timers,
+				  &ifaddr->lifetime.node);
+}
+
+static bool address_manage_timeout(struct net_if_addr *ifaddr,
+				   uint32_t current_time, uint32_t *next_wakeup)
+{
+	if (check_timeout(ifaddr->lifetime.timer_start,
+			  ifaddr->lifetime.timer_timeout,
+			  ifaddr->lifetime.wrap_counter,
+			  current_time)) {
+		address_expired(ifaddr);
+		return true;
+	}
+
+	if (current_time == NET_TIMEOUT_MAX_VALUE) {
+		ifaddr->lifetime.timer_start = k_uptime_get_32();
+		ifaddr->lifetime.wrap_counter--;
+	}
+
+	if (ifaddr->lifetime.wrap_counter > 0) {
+		*next_wakeup = NET_TIMEOUT_MAX_VALUE;
+	} else {
+		*next_wakeup = ifaddr->lifetime.timer_timeout;
+	}
+
+	return false;
+}
+
+static void address_lifetime_timeout(struct k_work *work)
+{
+	uint64_t timeout_update = UINT64_MAX;
+	uint32_t current_time = k_uptime_get_32();
+	bool found = false;
+	struct net_if_addr *current, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_address_lifetime_timers,
+					  current, next, lifetime.node) {
+		uint32_t next_timeout;
+		bool is_timeout;
+
+		is_timeout = address_manage_timeout(current, current_time,
+						    &next_timeout);
+		if (!is_timeout) {
+			if (next_timeout < timeout_update) {
+				timeout_update = next_timeout;
+				found = true;
+			}
+		}
+
+		if (current == next) {
+			break;
+		}
+	}
+
+	if (found) {
+		/* If we are near upper limit of int32_t timeout, then lower it
+		 * a bit so that kernel timeout variable will not overflow.
+		 */
+		if (timeout_update >= NET_TIMEOUT_MAX_VALUE) {
+			timeout_update = NET_TIMEOUT_MAX_VALUE;
+		}
+
+		NET_DBG("Waiting for %d ms", (int32_t)timeout_update);
+
+		k_delayed_work_submit(&address_lifetime_timer,
+				      K_MSEC(timeout_update));
+	}
+}
+
+#if defined(CONFIG_NET_TEST)
+void net_address_lifetime_timeout(void)
+{
+	address_lifetime_timeout(NULL);
+}
+#endif
+
+static void address_submit_work(struct net_if_addr *ifaddr)
+{
+	int32_t remaining;
+
+	remaining = k_delayed_work_remaining_get(&address_lifetime_timer);
+	if (!remaining || (ifaddr->lifetime.wrap_counter == 0 &&
+			   ifaddr->lifetime.timer_timeout < remaining)) {
+		k_delayed_work_cancel(&address_lifetime_timer);
+
+		if (ifaddr->lifetime.wrap_counter > 0 && remaining == 0) {
+			k_delayed_work_submit(&address_lifetime_timer,
+					      K_MSEC(NET_TIMEOUT_MAX_VALUE));
+		} else {
+			k_delayed_work_submit(&address_lifetime_timer,
+				       K_MSEC(ifaddr->lifetime.timer_timeout));
+		}
+
+		NET_DBG("Next wakeup in %d ms",
+			k_delayed_work_remaining_get(&address_lifetime_timer));
+	}
+}
+
+static void address_start_timer(struct net_if_addr *ifaddr, uint32_t vlifetime)
+{
+	uint64_t expire_timeout = (uint64_t)MSEC_PER_SEC * (uint64_t)vlifetime;
+
+	sys_slist_append(&active_address_lifetime_timers,
+			 &ifaddr->lifetime.node);
+
+	ifaddr->lifetime.timer_start = k_uptime_get_32();
+	ifaddr->lifetime.wrap_counter = expire_timeout /
+		(uint64_t)NET_TIMEOUT_MAX_VALUE;
+	ifaddr->lifetime.timer_timeout = expire_timeout -
+		(uint64_t)NET_TIMEOUT_MAX_VALUE *
+		(uint64_t)ifaddr->lifetime.wrap_counter;
+
+	address_submit_work(ifaddr);
+}
+
+void net_if_ipv6_addr_update_lifetime(struct net_if_addr *ifaddr,
+				      uint32_t vlifetime)
+{
+	NET_DBG("Updating expire time of %s by %u secs",
+		log_strdup(net_sprint_ipv6_addr(&ifaddr->address.in6_addr)),
+		vlifetime);
+
+	ifaddr->addr_state = NET_ADDR_PREFERRED;
+
+	address_start_timer(ifaddr, vlifetime);
+}
+
+static struct net_if_addr *ipv6_addr_find(struct net_if *iface,
+					  struct in6_addr *addr)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used) {
+			continue;
+		}
+
+		if (net_ipv6_addr_cmp(
+			    addr, &ipv6->unicast[i].address.in6_addr)) {
+
+			return &ipv6->unicast[i];
+		}
+	}
+
+	return NULL;
+}
+
+static inline void net_if_addr_init(struct net_if_addr *ifaddr,
+				    struct in6_addr *addr,
+				    enum net_addr_type addr_type,
+				    uint32_t vlifetime)
+{
+	ifaddr->is_used = true;
+	ifaddr->address.family = AF_INET6;
+	ifaddr->addr_type = addr_type;
+	net_ipaddr_copy(&ifaddr->address.in6_addr, addr);
+
+	/* FIXME - set the mcast addr for this node */
+
+	if (vlifetime) {
+		ifaddr->is_infinite = false;
+
+		NET_DBG("Expiring %s in %u secs",
+			log_strdup(net_sprint_ipv6_addr(addr)),
+			vlifetime);
+
+		net_if_ipv6_addr_update_lifetime(ifaddr, vlifetime);
+	} else {
+		ifaddr->is_infinite = true;
+	}
+}
+
+struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
+					 struct in6_addr *addr,
+					 enum net_addr_type addr_type,
+					 uint32_t vlifetime)
+{
+	struct net_if_addr *ifaddr;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
+		return NULL;
+	}
+
+	ifaddr = ipv6_addr_find(iface, addr);
+	if (ifaddr) {
+		return ifaddr;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (ipv6->unicast[i].is_used) {
+			continue;
+		}
+
+		net_if_addr_init(&ipv6->unicast[i], addr, addr_type,
+				 vlifetime);
+
+		NET_DBG("[%d] interface %p address %s type %s added", i,
+			iface, log_strdup(net_sprint_ipv6_addr(addr)),
+			net_addr_type2str(addr_type));
+
+		if (!(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) {
+			/* RFC 4862 5.4.2
+			 * Before sending a Neighbor Solicitation, an interface
+			 * MUST join the all-nodes multicast address and the
+			 * solicited-node multicast address of the tentative
+			 * address.
+			 */
+			/* The allnodes multicast group is only joined once as
+			 * net_ipv6_mcast_join() checks if we have already
+			 * joined.
+			 */
+			join_mcast_nodes(iface,
+					 &ipv6->unicast[i].address.in6_addr);
+
+			net_if_ipv6_start_dad(iface, &ipv6->unicast[i]);
+		}
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_ADDR_ADD, iface,
+			&ipv6->unicast[i].address.in6_addr,
+			sizeof(struct in6_addr));
+
+		return &ipv6->unicast[i];
+	}
+
+	return NULL;
+}
+
+bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	NET_ASSERT(addr);
+
+	if (!ipv6) {
+		return false;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		struct in6_addr maddr;
+
+		if (!ipv6->unicast[i].is_used) {
+			continue;
+		}
+
+		if (!net_ipv6_addr_cmp(&ipv6->unicast[i].address.in6_addr,
+				       addr)) {
+			continue;
+		}
+
+		if (!ipv6->unicast[i].is_infinite) {
+			sys_slist_find_and_remove(
+				&active_address_lifetime_timers,
+				&ipv6->unicast[i].lifetime.node);
+
+			if (sys_slist_is_empty(
+				    &active_address_lifetime_timers)) {
+				k_delayed_work_cancel(&address_lifetime_timer);
+			}
+		}
+
+		ipv6->unicast[i].is_used = false;
+
+		net_ipv6_addr_create_solicited_node(addr, &maddr);
+
+		net_if_ipv6_maddr_rm(iface, &maddr);
+
+		NET_DBG("[%d] interface %p address %s type %s removed",
+			i, iface, log_strdup(net_sprint_ipv6_addr(addr)),
+			net_addr_type2str(ipv6->unicast[i].addr_type));
+
+		/* Using the IPv6 address pointer here can give false
+		 * info if someone adds a new IP address into this position
+		 * in the address array. This is quite unlikely thou.
+		 */
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_ADDR_DEL,
+			iface,
+			&ipv6->unicast[i].address.in6_addr,
+			sizeof(struct in6_addr));
+
+		return true;
+	}
+
+	return false;
+}
+
+bool z_impl_net_if_ipv6_addr_add_by_index(int index,
+					  struct in6_addr *addr,
+					  enum net_addr_type addr_type,
+					  uint32_t vlifetime)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	return net_if_ipv6_addr_add(iface, addr, addr_type, vlifetime) ?
+		true : false;
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv6_addr_add_by_index(int index,
+					  struct in6_addr *addr,
+					  enum net_addr_type addr_type,
+					  uint32_t vlifetime)
+{
+	struct in6_addr addr_v6;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6)));
+
+	return z_impl_net_if_ipv6_addr_add_by_index(index,
+						    &addr_v6,
+						    addr_type,
+						    vlifetime);
+}
+
+#include <syscalls/net_if_ipv6_addr_add_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+bool z_impl_net_if_ipv6_addr_rm_by_index(int index,
+					 const struct in6_addr *addr)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	return net_if_ipv6_addr_rm(iface, addr);
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv6_addr_rm_by_index(int index,
+					 const struct in6_addr *addr)
+{
+	struct in6_addr addr_v6;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&addr_v6, (void *)addr, sizeof(addr_v6)));
+
+	return z_impl_net_if_ipv6_addr_rm_by_index(index, &addr_v6);
+}
+
+#include <syscalls/net_if_ipv6_addr_rm_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+struct net_if_mcast_addr *net_if_ipv6_maddr_add(struct net_if *iface,
+						const struct in6_addr *addr)
+{
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
+		return NULL;
+	}
+
+	if (!net_ipv6_is_addr_mcast(addr)) {
+		NET_DBG("Address %s is not a multicast address.",
+			log_strdup(net_sprint_ipv6_addr(addr)));
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		if (ipv6->mcast[i].is_used) {
+			continue;
+		}
+
+		ipv6->mcast[i].is_used = true;
+		ipv6->mcast[i].address.family = AF_INET6;
+		memcpy(&ipv6->mcast[i].address.in6_addr, addr, 16);
+
+		NET_DBG("[%d] interface %p address %s added", i, iface,
+			log_strdup(net_sprint_ipv6_addr(addr)));
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_MADDR_ADD, iface,
+			&ipv6->mcast[i].address.in6_addr,
+			sizeof(struct in6_addr));
+
+		return &ipv6->mcast[i];
+	}
+
+	return NULL;
+}
+
+bool net_if_ipv6_maddr_rm(struct net_if *iface, const struct in6_addr *addr)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return false;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		if (!ipv6->mcast[i].is_used) {
+			continue;
+		}
+
+		if (!net_ipv6_addr_cmp(&ipv6->mcast[i].address.in6_addr,
+				       addr)) {
+			continue;
+		}
+
+		ipv6->mcast[i].is_used = false;
+
+		NET_DBG("[%d] interface %p address %s removed",
+			i, iface, log_strdup(net_sprint_ipv6_addr(addr)));
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_MADDR_DEL, iface,
+			&ipv6->mcast[i].address.in6_addr,
+			sizeof(struct in6_addr));
+
+		return true;
+	}
+
+	return false;
+}
+
+struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *maddr,
+						   struct net_if **ret)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+		int i;
+
+		if (ret && *ret && iface != *ret) {
+			continue;
+		}
+
+		if (!ipv6) {
+			continue;
+		}
+
+		for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+			if (!ipv6->mcast[i].is_used ||
+			    ipv6->mcast[i].address.family != AF_INET6) {
+				continue;
+			}
+
+			if (net_ipv6_is_prefix(
+				    maddr->s6_addr,
+				    ipv6->mcast[i].address.in6_addr.s6_addr,
+				    128)) {
+				if (ret) {
+					*ret = iface;
+				}
+
+				return &ipv6->mcast[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+void net_if_mcast_mon_register(struct net_if_mcast_monitor *mon,
+			       struct net_if *iface,
+			       net_if_mcast_callback_t cb)
+{
+	sys_slist_find_and_remove(&mcast_monitor_callbacks, &mon->node);
+	sys_slist_prepend(&mcast_monitor_callbacks, &mon->node);
+
+	mon->iface = iface;
+	mon->cb = cb;
+}
+
+void net_if_mcast_mon_unregister(struct net_if_mcast_monitor *mon)
+{
+	sys_slist_find_and_remove(&mcast_monitor_callbacks, &mon->node);
+}
+
+void net_if_mcast_monitor(struct net_if *iface,
+			  const struct in6_addr *addr,
+			  bool is_joined)
+{
+	struct net_if_mcast_monitor *mon, *tmp;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&mcast_monitor_callbacks,
+					  mon, tmp, node) {
+		if (iface == mon->iface) {
+			mon->cb(iface, addr, is_joined);
+		}
+	}
+}
+
+static void remove_prefix_addresses(struct net_if *iface,
+				    struct net_if_ipv6 *ipv6,
+				    struct in6_addr *addr,
+				    uint8_t len)
+{
+	int i;
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used ||
+		    ipv6->unicast[i].address.family != AF_INET6 ||
+		    ipv6->unicast[i].addr_type != NET_ADDR_AUTOCONF) {
+			continue;
+		}
+
+		if (net_ipv6_is_prefix(
+				addr->s6_addr,
+				ipv6->unicast[i].address.in6_addr.s6_addr,
+				len)) {
+			net_if_ipv6_addr_rm(iface,
+					    &ipv6->unicast[i].address.in6_addr);
+		}
+	}
+}
+
+static void prefix_lifetime_expired(struct net_if_ipv6_prefix *ifprefix)
+{
+	struct net_if_ipv6 *ipv6;
+
+	NET_DBG("Prefix %s/%d expired",
+		log_strdup(net_sprint_ipv6_addr(&ifprefix->prefix)),
+		ifprefix->len);
+
+	ifprefix->is_used = false;
+
+	if (net_if_config_ipv6_get(ifprefix->iface, &ipv6) < 0) {
+		return;
+	}
+
+	/* Remove also all auto addresses if the they have the same prefix.
+	 */
+	remove_prefix_addresses(ifprefix->iface, ipv6, &ifprefix->prefix,
+				ifprefix->len);
+
+	net_mgmt_event_notify_with_info(
+		NET_EVENT_IPV6_PREFIX_DEL, ifprefix->iface,
+		&ifprefix->prefix, sizeof(struct in6_addr));
+}
+
+static void prefix_timer_remove(struct net_if_ipv6_prefix *ifprefix)
+{
+	NET_DBG("IPv6 prefix %s/%d removed",
+		log_strdup(net_sprint_ipv6_addr(&ifprefix->prefix)),
+		ifprefix->len);
+
+	ifprefix->lifetime.timer_timeout = 0;
+	ifprefix->lifetime.wrap_counter = 0;
+
+	sys_slist_find_and_remove(&active_prefix_lifetime_timers,
+				  &ifprefix->lifetime.node);
+}
+
+static bool prefix_manage_timeout(struct net_if_ipv6_prefix *ifprefix,
+				  uint32_t current_time, uint32_t *next_wakeup)
+{
+	if (check_timeout(ifprefix->lifetime.timer_start,
+			  ifprefix->lifetime.timer_timeout,
+			  ifprefix->lifetime.wrap_counter,
+			  current_time)) {
+		prefix_lifetime_expired(ifprefix);
+		return true;
+	}
+
+	if (current_time == NET_TIMEOUT_MAX_VALUE) {
+		ifprefix->lifetime.wrap_counter--;
+	}
+
+	if (ifprefix->lifetime.wrap_counter > 0) {
+		*next_wakeup = NET_TIMEOUT_MAX_VALUE;
+	} else {
+		*next_wakeup = ifprefix->lifetime.timer_timeout;
+	}
+
+	return false;
+}
+
+static void prefix_lifetime_timeout(struct k_work *work)
+{
+	uint64_t timeout_update = UINT64_MAX;
+	uint32_t current_time = k_uptime_get_32();
+	bool found = false;
+	struct net_if_ipv6_prefix *current, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&active_prefix_lifetime_timers,
+					  current, next, lifetime.node) {
+		uint32_t next_timeout;
+		bool is_timeout;
+
+		is_timeout = prefix_manage_timeout(current, current_time,
+						   &next_timeout);
+		if (!is_timeout) {
+			if (next_timeout < timeout_update) {
+				timeout_update = next_timeout;
+				found = true;
+			}
+		}
+
+		if (current == next) {
+			break;
+		}
+	}
+
+	if (found) {
+		/* If we are near upper limit of int32_t timeout, then lower it
+		 * a bit so that kernel timeout will not overflow.
+		 */
+		if (timeout_update >= NET_TIMEOUT_MAX_VALUE) {
+			timeout_update = NET_TIMEOUT_MAX_VALUE;
+		}
+
+		NET_DBG("Waiting for %d ms", (uint32_t)timeout_update);
+
+		k_delayed_work_submit(&prefix_lifetime_timer,
+				      K_MSEC(timeout_update));
+	}
+}
+
+static void prefix_submit_work(struct net_if_ipv6_prefix *ifprefix)
+{
+	int32_t remaining;
+
+	remaining = k_delayed_work_remaining_get(&prefix_lifetime_timer);
+	if (!remaining || (ifprefix->lifetime.wrap_counter == 0 &&
+			   ifprefix->lifetime.timer_timeout < remaining)) {
+		k_delayed_work_cancel(&prefix_lifetime_timer);
+
+		if (ifprefix->lifetime.wrap_counter > 0 && remaining == 0) {
+			k_delayed_work_submit(&prefix_lifetime_timer,
+					      K_MSEC(NET_TIMEOUT_MAX_VALUE));
+		} else {
+			k_delayed_work_submit(&prefix_lifetime_timer,
+				     K_MSEC(ifprefix->lifetime.timer_timeout));
+		}
+
+		NET_DBG("Next wakeup in %d ms",
+			k_delayed_work_remaining_get(&prefix_lifetime_timer));
+	}
+}
+
+static void prefix_start_timer(struct net_if_ipv6_prefix *ifprefix,
+			       uint32_t lifetime)
+{
+	uint64_t expire_timeout = (uint64_t)MSEC_PER_SEC * (uint64_t)lifetime;
+
+	(void)sys_slist_find_and_remove(&active_prefix_lifetime_timers,
+					&ifprefix->lifetime.node);
+	sys_slist_append(&active_prefix_lifetime_timers,
+			 &ifprefix->lifetime.node);
+
+	ifprefix->lifetime.timer_start = k_uptime_get_32();
+	ifprefix->lifetime.wrap_counter = expire_timeout /
+		(uint64_t)NET_TIMEOUT_MAX_VALUE;
+	ifprefix->lifetime.timer_timeout = expire_timeout -
+		(uint64_t)NET_TIMEOUT_MAX_VALUE *
+		(uint64_t)ifprefix->lifetime.wrap_counter;
+
+	prefix_submit_work(ifprefix);
+}
+
+static struct net_if_ipv6_prefix *ipv6_prefix_find(struct net_if *iface,
+						   struct in6_addr *prefix,
+						   uint8_t prefix_len)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		if (!ipv6->unicast[i].is_used) {
+			continue;
+		}
+
+		if (net_ipv6_addr_cmp(prefix, &ipv6->prefix[i].prefix) &&
+		    prefix_len == ipv6->prefix[i].len) {
+			return &ipv6->prefix[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void net_if_ipv6_prefix_init(struct net_if *iface,
+				    struct net_if_ipv6_prefix *ifprefix,
+				    struct in6_addr *addr, uint8_t len,
+				    uint32_t lifetime)
+{
+	ifprefix->is_used = true;
+	ifprefix->len = len;
+	ifprefix->iface = iface;
+	net_ipaddr_copy(&ifprefix->prefix, addr);
+
+	if (lifetime == NET_IPV6_ND_INFINITE_LIFETIME) {
+		ifprefix->is_infinite = true;
+	} else {
+		ifprefix->is_infinite = false;
+	}
+}
+
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_add(struct net_if *iface,
+						  struct in6_addr *prefix,
+						  uint8_t len,
+						  uint32_t lifetime)
+{
+	struct net_if_ipv6_prefix *ifprefix;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
+		return NULL;
+	}
+
+	ifprefix = ipv6_prefix_find(iface, prefix, len);
+	if (ifprefix) {
+		return ifprefix;
+	}
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		if (ipv6->prefix[i].is_used) {
+			continue;
+		}
+
+		net_if_ipv6_prefix_init(iface, &ipv6->prefix[i], prefix,
+					len, lifetime);
+
+		NET_DBG("[%d] interface %p prefix %s/%d added", i, iface,
+			log_strdup(net_sprint_ipv6_addr(prefix)), len);
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_PREFIX_ADD, iface,
+			&ipv6->prefix[i].prefix, sizeof(struct in6_addr));
+
+		return &ipv6->prefix[i];
+	}
+
+	return NULL;
+}
+
+bool net_if_ipv6_prefix_rm(struct net_if *iface, struct in6_addr *addr,
+			   uint8_t len)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return false;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		if (!ipv6->prefix[i].is_used) {
+			continue;
+		}
+
+		if (!net_ipv6_addr_cmp(&ipv6->prefix[i].prefix, addr) ||
+		    ipv6->prefix[i].len != len) {
+			continue;
+		}
+
+		net_if_ipv6_prefix_unset_timer(&ipv6->prefix[i]);
+
+		ipv6->prefix[i].is_used = false;
+
+		/* Remove also all auto addresses if the they have the same
+		 * prefix.
+		 */
+		remove_prefix_addresses(iface, ipv6, addr, len);
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV6_PREFIX_DEL, iface,
+			&ipv6->prefix[i].prefix, sizeof(struct in6_addr));
+
+		return true;
+	}
+
+	return false;
+}
+
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_get(struct net_if *iface,
+						  struct in6_addr *addr)
+{
+	struct net_if_ipv6_prefix *prefix = NULL;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (!iface) {
+		iface = net_if_get_default();
+	}
+
+	ipv6 = iface->config.ip.ipv6;
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		if (!ipv6->prefix[i].is_used) {
+			continue;
+		}
+
+		if (net_ipv6_is_prefix(ipv6->prefix[i].prefix.s6_addr,
+				       addr->s6_addr,
+				       ipv6->prefix[i].len)) {
+			if (!prefix || prefix->len > ipv6->prefix[i].len) {
+				prefix = &ipv6->prefix[i];
+			}
+		}
+	}
+
+	return prefix;
+}
+
+struct net_if_ipv6_prefix *net_if_ipv6_prefix_lookup(struct net_if *iface,
+						     struct in6_addr *addr,
+						     uint8_t len)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		if (!ipv6->prefix[i].is_used) {
+			continue;
+		}
+
+		if (net_ipv6_is_prefix(ipv6->prefix[i].prefix.s6_addr,
+				       addr->s6_addr, len)) {
+			return &ipv6->prefix[i];
+		}
+	}
+
+	return NULL;
+}
+
+bool net_if_ipv6_addr_onlink(struct net_if **iface, struct in6_addr *addr)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, tmp) {
+		struct net_if_ipv6 *ipv6 = tmp->config.ip.ipv6;
+		int i;
+
+		if (iface && *iface && *iface != tmp) {
+			continue;
+		}
+
+		if (!ipv6) {
+			continue;
+		}
+
+		for (i = 0; i < NET_IF_MAX_IPV6_PREFIX; i++) {
+			if (ipv6->prefix[i].is_used &&
+			    net_ipv6_is_prefix(ipv6->prefix[i].prefix.s6_addr,
+					       addr->s6_addr,
+					       ipv6->prefix[i].len)) {
+				if (iface) {
+					*iface = tmp;
+				}
+
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+void net_if_ipv6_prefix_set_timer(struct net_if_ipv6_prefix *prefix,
+				  uint32_t lifetime)
+{
+	/* No need to set a timer for infinite timeout */
+	if (lifetime == 0xffffffff) {
+		return;
+	}
+
+	NET_DBG("Prefix lifetime %u sec", lifetime);
+
+	prefix_start_timer(prefix, lifetime);
+}
+
+void net_if_ipv6_prefix_unset_timer(struct net_if_ipv6_prefix *prefix)
+{
+	if (!prefix->is_used) {
+		return;
+	}
+
+	prefix_timer_remove(prefix);
+}
+
+struct net_if_router *net_if_ipv6_router_lookup(struct net_if *iface,
+						struct in6_addr *addr)
+{
+	return iface_router_lookup(iface, AF_INET6, addr);
+}
+
+struct net_if_router *net_if_ipv6_router_find_default(struct net_if *iface,
+						      struct in6_addr *addr)
+{
+	return iface_router_find_default(iface, AF_INET6, addr);
+}
+
+void net_if_ipv6_router_update_lifetime(struct net_if_router *router,
+					uint16_t lifetime)
+{
+	NET_DBG("Updating expire time of %s by %u secs",
+		log_strdup(net_sprint_ipv6_addr(&router->address.in6_addr)),
+		lifetime);
+
+	router->life_start = k_uptime_get_32();
+	router->lifetime = lifetime;
+
+	iface_router_run_timer(router->life_start);
+}
+
+struct net_if_router *net_if_ipv6_router_add(struct net_if *iface,
+					     struct in6_addr *addr,
+					     uint16_t lifetime)
+{
+	return iface_router_add(iface, AF_INET6, addr, false, lifetime);
+}
+
+bool net_if_ipv6_router_rm(struct net_if_router *router)
+{
+	return iface_router_rm(router);
+}
+
+struct in6_addr *net_if_ipv6_get_ll(struct net_if *iface,
+				    enum net_addr_state addr_state)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used ||
+		    (addr_state != NET_ADDR_ANY_STATE &&
+		     ipv6->unicast[i].addr_state != addr_state) ||
+		    ipv6->unicast[i].address.family != AF_INET6) {
+			continue;
+		}
+
+		if (net_ipv6_is_ll_addr(&ipv6->unicast[i].address.in6_addr)) {
+			return &ipv6->unicast[i].address.in6_addr;
+		}
+	}
+
+	return NULL;
+}
+
+struct in6_addr *net_if_ipv6_get_ll_addr(enum net_addr_state state,
+					 struct net_if **iface)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, tmp) {
+		struct in6_addr *addr;
+
+		addr = net_if_ipv6_get_ll(tmp, state);
+		if (addr) {
+			if (iface) {
+				*iface = tmp;
+			}
+
+			return addr;
+		}
+	}
+
+	return NULL;
+}
+
+static inline struct in6_addr *check_global_addr(struct net_if *iface,
+						 enum net_addr_state state)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!ipv6->unicast[i].is_used ||
+		    (ipv6->unicast[i].addr_state != state) ||
+		    ipv6->unicast[i].address.family != AF_INET6) {
+			continue;
+		}
+
+		if (!net_ipv6_is_ll_addr(&ipv6->unicast[i].address.in6_addr)) {
+			return &ipv6->unicast[i].address.in6_addr;
+		}
+	}
+
+	return NULL;
+}
+
+struct in6_addr *net_if_ipv6_get_global_addr(enum net_addr_state state,
+					     struct net_if **iface)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, tmp) {
+		struct in6_addr *addr;
+
+		if (iface && *iface && tmp != *iface) {
+			continue;
+		}
+
+		addr = check_global_addr(tmp, state);
+		if (addr) {
+			if (iface) {
+				*iface = tmp;
+			}
+
+			return addr;
+		}
+	}
+
+	return NULL;
+}
+
+static uint8_t get_diff_ipv6(const struct in6_addr *src,
+			  const struct in6_addr *dst)
+{
+	return get_ipaddr_diff((const uint8_t *)src, (const uint8_t *)dst, 16);
+}
+
+static inline bool is_proper_ipv6_address(struct net_if_addr *addr)
+{
+	if (addr->is_used && addr->addr_state == NET_ADDR_PREFERRED &&
+	    addr->address.family == AF_INET6 &&
+	    !net_ipv6_is_ll_addr(&addr->address.in6_addr)) {
+		return true;
+	}
+
+	return false;
+}
+
+static struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface,
+						   const struct in6_addr *dst,
+						   uint8_t *best_so_far)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	struct in6_addr *src = NULL;
+	uint8_t len;
+	int i;
+
+	if (!ipv6) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		if (!is_proper_ipv6_address(&ipv6->unicast[i])) {
+			continue;
+		}
+
+		len = get_diff_ipv6(dst, &ipv6->unicast[i].address.in6_addr);
+		if (len >= *best_so_far) {
+			/* Mesh local address can only be selected for the same
+			 * subnet.
+			 */
+			if (ipv6->unicast[i].is_mesh_local && len < 64 &&
+			    !net_ipv6_is_addr_mcast_mesh(dst)) {
+				continue;
+			}
+
+			*best_so_far = len;
+			src = &ipv6->unicast[i].address.in6_addr;
+		}
+	}
+
+	return src;
+}
+
+const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
+						   const struct in6_addr *dst)
+{
+	struct in6_addr *src = NULL;
+	uint8_t best_match = 0U;
+
+	if (!net_ipv6_is_ll_addr(dst) && (!net_ipv6_is_addr_mcast(dst) ||
+	    net_ipv6_is_addr_mcast_mesh(dst))) {
+
+		/* If caller has supplied interface, then use that */
+		if (dst_iface) {
+			src = net_if_ipv6_get_best_match(dst_iface, dst,
+							 &best_match);
+		} else {
+			Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+				struct in6_addr *addr;
+
+				addr = net_if_ipv6_get_best_match(iface, dst,
+								  &best_match);
+				if (addr) {
+					src = addr;
+				}
+			}
+		}
+
+	} else {
+		if (dst_iface) {
+			src = net_if_ipv6_get_ll(dst_iface, NET_ADDR_PREFERRED);
+		} else {
+			Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+				struct in6_addr *addr;
+
+				addr = net_if_ipv6_get_ll(iface,
+							  NET_ADDR_PREFERRED);
+				if (addr) {
+					src = addr;
+					break;
+				}
+			}
+		}
+	}
+
+	if (!src) {
+		return net_ipv6_unspecified_address();
+	}
+
+	return src;
+}
+
+struct net_if *net_if_ipv6_select_src_iface(const struct in6_addr *dst)
+{
+	const struct in6_addr *src;
+	struct net_if *iface;
+
+	src = net_if_ipv6_select_src_addr(NULL, dst);
+	if (src == net_ipv6_unspecified_address()) {
+		return net_if_get_default();
+	}
+
+	if (!net_if_ipv6_addr_lookup(src, &iface)) {
+		return net_if_get_default();
+	}
+
+	return iface;
+}
+
+uint32_t net_if_ipv6_calc_reachable_time(struct net_if_ipv6 *ipv6)
+{
+	uint32_t min_reachable, max_reachable;
+
+	min_reachable = (MIN_RANDOM_NUMER * ipv6->base_reachable_time)
+			/ MIN_RANDOM_DENOM;
+	max_reachable = (MAX_RANDOM_NUMER * ipv6->base_reachable_time)
+			/ MAX_RANDOM_DENOM;
+
+	NET_DBG("min_reachable:%u max_reachable:%u", min_reachable,
+		max_reachable);
+
+	return min_reachable +
+	       sys_rand32_get() % (max_reachable - min_reachable);
+}
+
+static void iface_ipv6_start(struct net_if *iface)
+{
+	if (IS_ENABLED(CONFIG_NET_IPV6_DAD)) {
+		net_if_start_dad(iface);
+	} else {
+		struct net_if_ipv6 *ipv6 __unused = iface->config.ip.ipv6;
+
+		join_mcast_nodes(iface,
+				 &ipv6->mcast[0].address.in6_addr);
+	}
+
+	net_if_start_rs(iface);
+}
+
+static void iface_ipv6_init(int if_count)
+{
+	int i;
+
+	iface_ipv6_dad_init();
+	iface_ipv6_nd_init();
+
+	k_delayed_work_init(&address_lifetime_timer, address_lifetime_timeout);
+	k_delayed_work_init(&prefix_lifetime_timer, prefix_lifetime_timeout);
+
+	if (if_count > ARRAY_SIZE(ipv6_addresses)) {
+		NET_WARN("You have %lu IPv6 net_if addresses but %d "
+			 "network interfaces", ARRAY_SIZE(ipv6_addresses),
+			 if_count);
+		NET_WARN("Consider increasing CONFIG_NET_IF_MAX_IPV6_COUNT "
+			 "value.");
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv6_addresses); i++) {
+		ipv6_addresses[i].ipv6.hop_limit = CONFIG_NET_INITIAL_HOP_LIMIT;
+		ipv6_addresses[i].ipv6.base_reachable_time = REACHABLE_TIME;
+
+		net_if_ipv6_set_reachable_time(&ipv6_addresses[i].ipv6);
+	}
+}
+
+#else
+#define join_mcast_allnodes(...)
+#define join_mcast_solicit_node(...)
+#define leave_mcast_all(...)
+#define join_mcast_nodes(...)
+#define iface_ipv6_start(...)
+#define iface_ipv6_init(...)
+
+struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr,
+						   struct net_if **iface)
+{
+	ARG_UNUSED(addr);
+	ARG_UNUSED(iface);
+
+	return NULL;
+}
+
+struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
+					    struct net_if **ret)
+{
+	ARG_UNUSED(addr);
+	ARG_UNUSED(ret);
+
+	return NULL;
+}
+
+struct in6_addr *net_if_ipv6_get_global_addr(enum net_addr_state state,
+					     struct net_if **iface)
+{
+	ARG_UNUSED(state);
+	ARG_UNUSED(iface);
+
+	return NULL;
+}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_NATIVE_IPV4)
+int net_if_config_ipv4_get(struct net_if *iface, struct net_if_ipv4 **ipv4)
+{
+	int i;
+
+	if (iface->config.ip.ipv4) {
+		if (ipv4) {
+			*ipv4 = iface->config.ip.ipv4;
+		}
+
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv4_addresses); i++) {
+		if (ipv4_addresses[i].iface) {
+			continue;
+		}
+
+		iface->config.ip.ipv4 = &ipv4_addresses[i].ipv4;
+		ipv4_addresses[i].iface = iface;
+
+		if (ipv4) {
+			*ipv4 = &ipv4_addresses[i].ipv4;
+		}
+
+		return 0;
+	}
+
+	return -ESRCH;
+}
+
+int net_if_config_ipv4_put(struct net_if *iface)
+{
+	int i;
+
+	if (!iface->config.ip.ipv4) {
+		return -EALREADY;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv4_addresses); i++) {
+		if (ipv4_addresses[i].iface != iface) {
+			continue;
+		}
+
+		iface->config.ip.ipv4 = NULL;
+		ipv4_addresses[i].iface = NULL;
+
+		return 0;
+	}
+
+	return 0;
+}
+
+struct net_if_router *net_if_ipv4_router_lookup(struct net_if *iface,
+						struct in_addr *addr)
+{
+	return iface_router_lookup(iface, AF_INET, addr);
+}
+
+struct net_if_router *net_if_ipv4_router_find_default(struct net_if *iface,
+						      struct in_addr *addr)
+{
+	return iface_router_find_default(iface, AF_INET, addr);
+}
+
+struct net_if_router *net_if_ipv4_router_add(struct net_if *iface,
+					     struct in_addr *addr,
+					     bool is_default,
+					     uint16_t lifetime)
+{
+	return iface_router_add(iface, AF_INET, addr, is_default, lifetime);
+}
+
+bool net_if_ipv4_router_rm(struct net_if_router *router)
+{
+	return iface_router_rm(router);
+}
+
+bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
+			       const struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	uint32_t subnet;
+	int i;
+
+	if (!ipv4) {
+		return false;
+	}
+
+	subnet = UNALIGNED_GET(&addr->s_addr) & ipv4->netmask.s_addr;
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (!ipv4->unicast[i].is_used ||
+		    ipv4->unicast[i].address.family != AF_INET) {
+			continue;
+		}
+
+		if ((ipv4->unicast[i].address.in_addr.s_addr &
+		     ipv4->netmask.s_addr) == subnet) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool ipv4_is_broadcast_address(struct net_if *iface,
+				      const struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+
+	if (!ipv4) {
+		return false;
+	}
+
+	if (!net_if_ipv4_addr_mask_cmp(iface, addr)) {
+		return false;
+	}
+
+	if ((UNALIGNED_GET(&addr->s_addr) & ~ipv4->netmask.s_addr) ==
+	    ~ipv4->netmask.s_addr) {
+		return true;
+	}
+
+	return false;
+}
+
+bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
+			       const struct in_addr *addr)
+{
+	if (iface) {
+		return ipv4_is_broadcast_address(iface, addr);
+	}
+
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		bool ret;
+
+		ret = ipv4_is_broadcast_address(iface, addr);
+		if (ret) {
+			return ret;
+		}
+	}
+
+	return false;
+}
+
+struct net_if *net_if_ipv4_select_src_iface(const struct in_addr *dst)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		bool ret;
+
+		ret = net_if_ipv4_addr_mask_cmp(iface, dst);
+		if (ret) {
+			return iface;
+		}
+	}
+
+	return net_if_get_default();
+}
+
+static uint8_t get_diff_ipv4(const struct in_addr *src,
+			  const struct in_addr *dst)
+{
+	return get_ipaddr_diff((const uint8_t *)src, (const uint8_t *)dst, 4);
+}
+
+static inline bool is_proper_ipv4_address(struct net_if_addr *addr)
+{
+	if (addr->is_used && addr->addr_state == NET_ADDR_PREFERRED &&
+	    addr->address.family == AF_INET &&
+	    !net_ipv4_is_ll_addr(&addr->address.in_addr)) {
+		return true;
+	}
+
+	return false;
+}
+
+static struct in_addr *net_if_ipv4_get_best_match(struct net_if *iface,
+						  const struct in_addr *dst,
+						  uint8_t *best_so_far)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	struct in_addr *src = NULL;
+	uint8_t len;
+	int i;
+
+	if (!ipv4) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (!is_proper_ipv4_address(&ipv4->unicast[i])) {
+			continue;
+		}
+
+		len = get_diff_ipv4(dst, &ipv4->unicast[i].address.in_addr);
+		if (len >= *best_so_far) {
+			*best_so_far = len;
+			src = &ipv4->unicast[i].address.in_addr;
+		}
+	}
+
+	return src;
+}
+
+static struct in_addr *if_ipv4_get_addr(struct net_if *iface,
+					enum net_addr_state addr_state, bool ll)
+{
+	struct net_if_ipv4 *ipv4;
+	int i;
+
+	if (!iface) {
+		return NULL;
+	}
+
+	ipv4 = iface->config.ip.ipv4;
+	if (!ipv4) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (!ipv4->unicast[i].is_used ||
+		    (addr_state != NET_ADDR_ANY_STATE &&
+		     ipv4->unicast[i].addr_state != addr_state) ||
+		    ipv4->unicast[i].address.family != AF_INET) {
+			continue;
+		}
+
+		if (net_ipv4_is_ll_addr(&ipv4->unicast[i].address.in_addr)) {
+			if (!ll) {
+				continue;
+			}
+		} else {
+			if (ll) {
+				continue;
+			}
+		}
+
+		return &ipv4->unicast[i].address.in_addr;
+	}
+
+	return NULL;
+}
+
+struct in_addr *net_if_ipv4_get_ll(struct net_if *iface,
+				   enum net_addr_state addr_state)
+{
+	return if_ipv4_get_addr(iface, addr_state, true);
+}
+
+struct in_addr *net_if_ipv4_get_global_addr(struct net_if *iface,
+					    enum net_addr_state addr_state)
+{
+	return if_ipv4_get_addr(iface, addr_state, false);
+}
+
+const struct in_addr *net_if_ipv4_select_src_addr(struct net_if *dst_iface,
+						  const struct in_addr *dst)
+{
+	struct in_addr *src = NULL;
+	uint8_t best_match = 0U;
+
+	if (!net_ipv4_is_ll_addr(dst) && !net_ipv4_is_addr_mcast(dst)) {
+
+		/* If caller has supplied interface, then use that */
+		if (dst_iface) {
+			src = net_if_ipv4_get_best_match(dst_iface, dst,
+							 &best_match);
+		} else {
+			Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+				struct in_addr *addr;
+
+				addr = net_if_ipv4_get_best_match(iface, dst,
+								  &best_match);
+				if (addr) {
+					src = addr;
+				}
+			}
+		}
+
+	} else {
+		if (dst_iface) {
+			src = net_if_ipv4_get_ll(dst_iface, NET_ADDR_PREFERRED);
+		} else {
+			Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+				struct in_addr *addr;
+
+				addr = net_if_ipv4_get_ll(iface,
+							  NET_ADDR_PREFERRED);
+				if (addr) {
+					src = addr;
+					break;
+				}
+			}
+		}
+	}
+
+	if (!src) {
+		src = net_if_ipv4_get_global_addr(dst_iface,
+						  NET_ADDR_PREFERRED);
+		if (src) {
+			return src;
+		}
+
+		return net_ipv4_unspecified_address();
+	}
+
+	return src;
+}
+
+struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
+					    struct net_if **ret)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+		int i;
+
+		if (!ipv4) {
+			continue;
+		}
+
+		for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+			if (!ipv4->unicast[i].is_used ||
+			    ipv4->unicast[i].address.family != AF_INET) {
+				continue;
+			}
+
+			if (UNALIGNED_GET(&addr->s4_addr32[0]) ==
+			    ipv4->unicast[i].address.in_addr.s_addr) {
+
+				if (ret) {
+					*ret = iface;
+				}
+
+				return &ipv4->unicast[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+int z_impl_net_if_ipv4_addr_lookup_by_index(const struct in_addr *addr)
+{
+	struct net_if_addr *if_addr;
+	struct net_if *iface = NULL;
+
+	if_addr = net_if_ipv4_addr_lookup(addr, &iface);
+	if (!if_addr) {
+		return 0;
+	}
+
+	return net_if_get_by_iface(iface);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_net_if_ipv4_addr_lookup_by_index(
+					  const struct in_addr *addr)
+{
+	struct in_addr addr_v4;
+
+	Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4)));
+
+	return z_impl_net_if_ipv4_addr_lookup_by_index(&addr_v4);
+}
+#include <syscalls/net_if_ipv4_addr_lookup_by_index_mrsh.c>
+#endif
+
+void net_if_ipv4_set_netmask(struct net_if *iface,
+			     const struct in_addr *netmask)
+{
+	if (net_if_config_ipv4_get(iface, NULL) < 0) {
+		return;
+	}
+
+	if (!iface->config.ip.ipv4) {
+		return;
+	}
+
+	net_ipaddr_copy(&iface->config.ip.ipv4->netmask, netmask);
+}
+
+bool z_impl_net_if_ipv4_set_netmask_by_index(int index,
+					     const struct in_addr *netmask)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	net_if_ipv4_set_netmask(iface, netmask);
+
+	return true;
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv4_set_netmask_by_index(int index,
+					     const struct in_addr *netmask)
+{
+	struct in_addr netmask_addr;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&netmask_addr, (void *)netmask,
+				sizeof(netmask_addr)));
+
+	return z_impl_net_if_ipv4_set_netmask_by_index(index, &netmask_addr);
+}
+
+#include <syscalls/net_if_ipv4_set_netmask_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+void net_if_ipv4_set_gw(struct net_if *iface, const struct in_addr *gw)
+{
+	if (net_if_config_ipv4_get(iface, NULL) < 0) {
+		return;
+	}
+
+	if (!iface->config.ip.ipv4) {
+		return;
+	}
+
+	net_ipaddr_copy(&iface->config.ip.ipv4->gw, gw);
+}
+
+bool z_impl_net_if_ipv4_set_gw_by_index(int index,
+					const struct in_addr *gw)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	net_if_ipv4_set_gw(iface, gw);
+
+	return true;
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv4_set_gw_by_index(int index,
+					const struct in_addr *gw)
+{
+	struct in_addr gw_addr;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&gw_addr, (void *)gw, sizeof(gw_addr)));
+
+	return z_impl_net_if_ipv4_set_gw_by_index(index, &gw_addr);
+}
+
+#include <syscalls/net_if_ipv4_set_gw_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static struct net_if_addr *ipv4_addr_find(struct net_if *iface,
+					  struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	int i;
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (!ipv4->unicast[i].is_used) {
+			continue;
+		}
+
+		if (net_ipv4_addr_cmp(addr,
+				      &ipv4->unicast[i].address.in_addr)) {
+			return &ipv4->unicast[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
+					 struct in_addr *addr,
+					 enum net_addr_type addr_type,
+					 uint32_t vlifetime)
+{
+	struct net_if_addr *ifaddr;
+	struct net_if_ipv4 *ipv4;
+	int i;
+
+	if (net_if_config_ipv4_get(iface, &ipv4) < 0) {
+		return NULL;
+	}
+
+	ifaddr = ipv4_addr_find(iface, addr);
+	if (ifaddr) {
+		/* TODO: should set addr_type/vlifetime */
+		return ifaddr;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		struct net_if_addr *cur = &ipv4->unicast[i];
+
+		if (addr_type == NET_ADDR_DHCP
+		    && cur->addr_type == NET_ADDR_OVERRIDABLE) {
+			ifaddr = cur;
+			break;
+		}
+
+		if (!ipv4->unicast[i].is_used) {
+			ifaddr = cur;
+			break;
+		}
+	}
+
+	if (ifaddr) {
+		ifaddr->is_used = true;
+		ifaddr->address.family = AF_INET;
+		ifaddr->address.in_addr.s4_addr32[0] =
+						addr->s4_addr32[0];
+		ifaddr->addr_type = addr_type;
+
+		/* Caller has to take care of timers and their expiry */
+		if (vlifetime) {
+			ifaddr->is_infinite = false;
+		} else {
+			ifaddr->is_infinite = true;
+		}
+
+		/**
+		 *  TODO: Handle properly PREFERRED/DEPRECATED state when
+		 *  address in use, expired and renewal state.
+		 */
+		ifaddr->addr_state = NET_ADDR_PREFERRED;
+
+		NET_DBG("[%d] interface %p address %s type %s added", i, iface,
+			log_strdup(net_sprint_ipv4_addr(addr)),
+			net_addr_type2str(addr_type));
+
+		net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ADDR_ADD, iface,
+						&ifaddr->address.in_addr,
+						sizeof(struct in_addr));
+
+		return ifaddr;
+	}
+
+	return NULL;
+}
+
+bool net_if_ipv4_addr_rm(struct net_if *iface, const struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	int i;
+
+	if (!ipv4) {
+		return false;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (!ipv4->unicast[i].is_used) {
+			continue;
+		}
+
+		if (!net_ipv4_addr_cmp(&ipv4->unicast[i].address.in_addr,
+				       addr)) {
+			continue;
+		}
+
+		ipv4->unicast[i].is_used = false;
+
+		NET_DBG("[%d] interface %p address %s removed",
+			i, iface, log_strdup(net_sprint_ipv4_addr(addr)));
+
+		net_mgmt_event_notify_with_info(
+			NET_EVENT_IPV4_ADDR_DEL, iface,
+			&ipv4->unicast[i].address.in_addr,
+			sizeof(struct in_addr));
+
+		return true;
+	}
+
+	return false;
+}
+
+bool z_impl_net_if_ipv4_addr_add_by_index(int index,
+					  struct in_addr *addr,
+					  enum net_addr_type addr_type,
+					  uint32_t vlifetime)
+{
+	struct net_if *iface;
+	struct net_if_addr *if_addr;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	if_addr = net_if_ipv4_addr_add(iface, addr, addr_type, vlifetime);
+	return if_addr ? true : false;
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv4_addr_add_by_index(int index,
+					  struct in_addr *addr,
+					  enum net_addr_type addr_type,
+					  uint32_t vlifetime)
+{
+	struct in_addr addr_v4;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4)));
+
+	return z_impl_net_if_ipv4_addr_add_by_index(index,
+						    &addr_v4,
+						    addr_type,
+						    vlifetime);
+}
+
+#include <syscalls/net_if_ipv4_addr_add_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+bool z_impl_net_if_ipv4_addr_rm_by_index(int index,
+					 const struct in_addr *addr)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	return net_if_ipv4_addr_rm(iface, addr);
+}
+
+#ifdef CONFIG_USERSPACE
+bool z_vrfy_net_if_ipv4_addr_rm_by_index(int index,
+					 const struct in_addr *addr)
+{
+	struct in_addr addr_v4;
+	struct net_if *iface;
+
+	iface = z_vrfy_net_if_get_by_index(index);
+	if (!iface) {
+		return false;
+	}
+
+	Z_OOPS(z_user_from_copy(&addr_v4, (void *)addr, sizeof(addr_v4)));
+
+	return (uint32_t)z_impl_net_if_ipv4_addr_rm_by_index(index, &addr_v4);
+}
+
+#include <syscalls/net_if_ipv4_addr_rm_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static struct net_if_mcast_addr *ipv4_maddr_find(struct net_if *iface,
+						 bool is_used,
+						 const struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	int i;
+
+	if (!ipv4) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) {
+		if ((is_used && !ipv4->mcast[i].is_used) ||
+		    (!is_used && ipv4->mcast[i].is_used)) {
+			continue;
+		}
+
+		if (addr) {
+			if (!net_ipv4_addr_cmp(&ipv4->mcast[i].address.in_addr,
+					       addr)) {
+				continue;
+			}
+		}
+
+		return &ipv4->mcast[i];
+	}
+
+	return NULL;
+}
+struct net_if_mcast_addr *net_if_ipv4_maddr_add(struct net_if *iface,
+						const struct in_addr *addr)
+{
+	struct net_if_mcast_addr *maddr;
+
+	if (net_if_config_ipv4_get(iface, NULL) < 0) {
+		return NULL;
+	}
+
+	if (!net_ipv4_is_addr_mcast(addr)) {
+		NET_DBG("Address %s is not a multicast address.",
+			log_strdup(net_sprint_ipv4_addr(addr)));
+		return NULL;
+	}
+
+	maddr = ipv4_maddr_find(iface, false, NULL);
+	if (maddr) {
+		maddr->is_used = true;
+		maddr->address.family = AF_INET;
+		maddr->address.in_addr.s4_addr32[0] = addr->s4_addr32[0];
+
+		NET_DBG("interface %p address %s added", iface,
+			log_strdup(net_sprint_ipv4_addr(addr)));
+	}
+
+	return maddr;
+}
+
+bool net_if_ipv4_maddr_rm(struct net_if *iface, const struct in_addr *addr)
+{
+	struct net_if_mcast_addr *maddr;
+
+	maddr = ipv4_maddr_find(iface, true, addr);
+	if (maddr) {
+		maddr->is_used = false;
+
+		NET_DBG("interface %p address %s removed",
+			iface, log_strdup(net_sprint_ipv4_addr(addr)));
+
+		return true;
+	}
+
+	return false;
+}
+
+struct net_if_mcast_addr *net_if_ipv4_maddr_lookup(const struct in_addr *maddr,
+						   struct net_if **ret)
+{
+	struct net_if_mcast_addr *addr;
+
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (ret && *ret && iface != *ret) {
+			continue;
+		}
+
+		addr = ipv4_maddr_find(iface, true, maddr);
+		if (addr) {
+			if (ret) {
+				*ret = iface;
+			}
+
+			return addr;
+		}
+	}
+
+	return NULL;
+}
+
+static void iface_ipv4_init(int if_count)
+{
+	int i;
+
+	if (if_count > ARRAY_SIZE(ipv4_addresses)) {
+		NET_WARN("You have %lu IPv4 net_if addresses but %d "
+			 "network interfaces", ARRAY_SIZE(ipv4_addresses),
+			 if_count);
+		NET_WARN("Consider increasing CONFIG_NET_IF_MAX_IPV4_COUNT "
+			 "value.");
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ipv4_addresses); i++) {
+		ipv4_addresses[i].ipv4.ttl = CONFIG_NET_INITIAL_TTL;
+	}
+}
+
+#else
+#define iface_ipv4_init(...)
+
+struct net_if_mcast_addr *net_if_ipv4_maddr_lookup(const struct in_addr *addr,
+						   struct net_if **iface)
+{
+	ARG_UNUSED(addr);
+	ARG_UNUSED(iface);
+
+	return NULL;
+}
+
+struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
+					    struct net_if **ret)
+{
+	ARG_UNUSED(addr);
+	ARG_UNUSED(ret);
+
+	return NULL;
+}
+
+struct in_addr *net_if_ipv4_get_global_addr(struct net_if *iface,
+					    enum net_addr_state addr_state)
+{
+	ARG_UNUSED(addr_state);
+	ARG_UNUSED(iface);
+
+	return NULL;
+}
+#endif /* CONFIG_NET_IPV4 */
+
+struct net_if *net_if_select_src_iface(const struct sockaddr *dst)
+{
+	struct net_if *iface;
+
+	if (!dst) {
+		goto out;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && dst->sa_family == AF_INET6) {
+		iface = net_if_ipv6_select_src_iface(&net_sin6(dst)->sin6_addr);
+		if (!iface) {
+			goto out;
+		}
+
+		return iface;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && dst->sa_family == AF_INET) {
+		iface = net_if_ipv4_select_src_iface(&net_sin(dst)->sin_addr);
+		if (!iface) {
+			goto out;
+		}
+
+		return iface;
+	}
+
+out:
+	return net_if_get_default();
+}
+
+enum net_verdict net_if_recv_data(struct net_if *iface, struct net_pkt *pkt)
+{
+	if (IS_ENABLED(CONFIG_NET_PROMISCUOUS_MODE) &&
+	    net_if_is_promisc(iface)) {
+		/* If the packet is not for us and the promiscuous
+		 * mode is enabled, then increase the ref count so
+		 * that net_core.c:processing_data() will not free it.
+		 * The promiscuous mode handler must free the packet
+		 * after it has finished working with it.
+		 *
+		 * If packet is for us, then NET_CONTINUE is returned.
+		 * In this case we must clone the packet, as the packet
+		 * could be manipulated by other part of the stack.
+		 */
+		enum net_verdict verdict;
+		struct net_pkt *new_pkt;
+
+		/* This protects pkt so that it will not be freed by L2 recv()
+		 */
+		net_pkt_ref(pkt);
+
+		verdict = net_if_l2(iface)->recv(iface, pkt);
+		if (verdict == NET_CONTINUE) {
+			new_pkt = net_pkt_clone(pkt, K_NO_WAIT);
+		} else {
+			new_pkt = net_pkt_ref(pkt);
+		}
+
+		/* L2 has modified the buffer starting point, it is easier
+		 * to re-initialize the cursor rather than updating it.
+		 */
+		net_pkt_cursor_init(new_pkt);
+
+		if (net_promisc_mode_input(new_pkt) == NET_DROP) {
+			net_pkt_unref(new_pkt);
+		}
+
+		net_pkt_unref(pkt);
+
+		return verdict;
+	}
+
+	return net_if_l2(iface)->recv(iface, pkt);
+}
+
+void net_if_register_link_cb(struct net_if_link_cb *link,
+			     net_if_link_callback_t cb)
+{
+	sys_slist_find_and_remove(&link_callbacks, &link->node);
+	sys_slist_prepend(&link_callbacks, &link->node);
+
+	link->cb = cb;
+}
+
+void net_if_unregister_link_cb(struct net_if_link_cb *link)
+{
+	sys_slist_find_and_remove(&link_callbacks, &link->node);
+}
+
+void net_if_call_link_cb(struct net_if *iface, struct net_linkaddr *lladdr,
+			 int status)
+{
+	struct net_if_link_cb *link, *tmp;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&link_callbacks, link, tmp, node) {
+		link->cb(iface, lladdr, status);
+	}
+}
+
+static bool need_calc_checksum(struct net_if *iface, enum ethernet_hw_caps caps)
+{
+#if defined(CONFIG_NET_L2_ETHERNET)
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return true;
+	}
+
+	return !(net_eth_get_hw_capabilities(iface) & caps);
+#else
+	return true;
+#endif
+}
+
+bool net_if_need_calc_tx_checksum(struct net_if *iface)
+{
+	return need_calc_checksum(iface, ETHERNET_HW_TX_CHKSUM_OFFLOAD);
+}
+
+bool net_if_need_calc_rx_checksum(struct net_if *iface)
+{
+	return need_calc_checksum(iface, ETHERNET_HW_RX_CHKSUM_OFFLOAD);
+}
+
+int net_if_get_by_iface(struct net_if *iface)
+{
+	if (!(iface >= _net_if_list_start && iface < _net_if_list_end)) {
+		return -1;
+	}
+
+	return (iface - _net_if_list_start) + 1;
+}
+
+void net_if_foreach(net_if_cb_t cb, void *user_data)
+{
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		cb(iface, user_data);
+	}
+}
+
+int net_if_up(struct net_if *iface)
+{
+	int status;
+
+	NET_DBG("iface %p", iface);
+
+	if (net_if_flag_is_set(iface, NET_IF_UP)) {
+		return 0;
+	}
+
+	if ((IS_ENABLED(CONFIG_NET_OFFLOAD) &&
+	     net_if_is_ip_offloaded(iface)) ||
+	    (IS_ENABLED(CONFIG_NET_SOCKETS_OFFLOAD) &&
+	     net_if_is_socket_offloaded(iface))) {
+		net_if_flag_set(iface, NET_IF_UP);
+		goto exit;
+	}
+
+	/* If the L2 does not support enable just set the flag */
+	if (!net_if_l2(iface) || !net_if_l2(iface)->enable) {
+		goto done;
+	}
+
+	/* Notify L2 to enable the interface */
+	status = net_if_l2(iface)->enable(iface, true);
+	if (status < 0) {
+		return status;
+	}
+
+done:
+	/* In many places it's assumed that link address was set with
+	 * net_if_set_link_addr(). Better check that now.
+	 */
+	NET_ASSERT(net_if_get_link_addr(iface)->addr != NULL);
+
+	net_if_flag_set(iface, NET_IF_UP);
+
+	/* If the interface is only having point-to-point traffic then we do
+	 * not need to run DAD etc for it.
+	 */
+	if (!(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) {
+		iface_ipv6_start(iface);
+
+		net_ipv4_autoconf_start(iface);
+	}
+
+exit:
+	net_mgmt_event_notify(NET_EVENT_IF_UP, iface);
+
+	return 0;
+}
+
+void net_if_carrier_down(struct net_if *iface)
+{
+	NET_DBG("iface %p", iface);
+
+	net_if_flag_clear(iface, NET_IF_UP);
+
+	net_ipv4_autoconf_reset(iface);
+
+	net_mgmt_event_notify(NET_EVENT_IF_DOWN, iface);
+}
+
+int net_if_down(struct net_if *iface)
+{
+	int status;
+
+	NET_DBG("iface %p", iface);
+
+	leave_mcast_all(iface);
+
+	if (net_if_is_ip_offloaded(iface)) {
+		goto done;
+	}
+
+	/* If the L2 does not support enable just clear the flag */
+	if (!net_if_l2(iface) || !net_if_l2(iface)->enable) {
+		goto done;
+	}
+
+	/* Notify L2 to disable the interface */
+	status = net_if_l2(iface)->enable(iface, false);
+	if (status < 0) {
+		return status;
+	}
+
+done:
+	net_if_flag_clear(iface, NET_IF_UP);
+
+	net_mgmt_event_notify(NET_EVENT_IF_DOWN, iface);
+
+	return 0;
+}
+
+static int promisc_mode_set(struct net_if *iface, bool enable)
+{
+	enum net_l2_flags l2_flags = 0;
+
+	NET_ASSERT(iface);
+
+	l2_flags = l2_flags_get(iface);
+	if (!(l2_flags & NET_L2_PROMISC_MODE)) {
+		return -ENOTSUP;
+	}
+
+#if defined(CONFIG_NET_L2_ETHERNET)
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+		int ret = net_eth_promisc_mode(iface, enable);
+
+		if (ret < 0) {
+			return ret;
+		}
+	}
+#else
+	return -ENOTSUP;
+#endif
+
+	return 0;
+}
+
+int net_if_set_promisc(struct net_if *iface)
+{
+	int ret;
+
+	ret = promisc_mode_set(iface, true);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = net_if_flag_test_and_set(iface, NET_IF_PROMISC);
+	if (ret) {
+		return -EALREADY;
+	}
+
+	return 0;
+}
+
+void net_if_unset_promisc(struct net_if *iface)
+{
+	int ret;
+
+	ret = promisc_mode_set(iface, false);
+	if (ret < 0) {
+		return;
+	}
+
+	net_if_flag_clear(iface, NET_IF_PROMISC);
+}
+
+bool net_if_is_promisc(struct net_if *iface)
+{
+	NET_ASSERT(iface);
+
+	return net_if_flag_is_set(iface, NET_IF_PROMISC);
+}
+
+#ifdef CONFIG_NET_POWER_MANAGEMENT
+
+int net_if_suspend(struct net_if *iface)
+{
+	if (net_if_are_pending_tx_packets(iface)) {
+		return -EBUSY;
+	}
+
+	if (net_if_flag_test_and_set(iface, NET_IF_SUSPENDED)) {
+		return -EALREADY;
+	}
+
+	net_stats_add_suspend_start_time(iface, k_cycle_get_32());
+
+	return 0;
+}
+
+int net_if_resume(struct net_if *iface)
+{
+	if (!net_if_flag_is_set(iface, NET_IF_SUSPENDED)) {
+		return -EALREADY;
+	}
+
+	net_if_flag_clear(iface, NET_IF_SUSPENDED);
+
+	net_stats_add_suspend_end_time(iface, k_cycle_get_32());
+
+	return 0;
+}
+
+bool net_if_is_suspended(struct net_if *iface)
+{
+	return net_if_flag_is_set(iface, NET_IF_SUSPENDED);
+}
+
+#endif /* CONFIG_NET_POWER_MANAGEMENT */
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD)
+static void net_tx_ts_thread(void)
+{
+	struct net_pkt *pkt;
+
+	NET_DBG("Starting TX timestamp callback thread");
+
+	while (1) {
+		pkt = k_fifo_get(&tx_ts_queue, K_FOREVER);
+		if (pkt) {
+			net_if_call_timestamp_cb(pkt);
+		}
+	}
+}
+
+void net_if_register_timestamp_cb(struct net_if_timestamp_cb *handle,
+				  struct net_pkt *pkt,
+				  struct net_if *iface,
+				  net_if_timestamp_callback_t cb)
+{
+	sys_slist_find_and_remove(&timestamp_callbacks, &handle->node);
+	sys_slist_prepend(&timestamp_callbacks, &handle->node);
+
+	handle->iface = iface;
+	handle->cb = cb;
+	handle->pkt = pkt;
+}
+
+void net_if_unregister_timestamp_cb(struct net_if_timestamp_cb *handle)
+{
+	sys_slist_find_and_remove(&timestamp_callbacks, &handle->node);
+}
+
+void net_if_call_timestamp_cb(struct net_pkt *pkt)
+{
+	sys_snode_t *sn, *sns;
+
+	SYS_SLIST_FOR_EACH_NODE_SAFE(&timestamp_callbacks, sn, sns) {
+		struct net_if_timestamp_cb *handle =
+			CONTAINER_OF(sn, struct net_if_timestamp_cb, node);
+
+		if (((handle->iface == NULL) ||
+		     (handle->iface == net_pkt_iface(pkt))) &&
+		    (handle->pkt == NULL || handle->pkt == pkt)) {
+			handle->cb(pkt);
+		}
+	}
+}
+
+void net_if_add_tx_timestamp(struct net_pkt *pkt)
+{
+	k_fifo_put(&tx_ts_queue, pkt);
+}
+#endif /* CONFIG_NET_PKT_TIMESTAMP_THREAD */
+
+void net_if_init(void)
+{
+	int if_count = 0;
+
+	NET_DBG("");
+
+	net_tc_tx_init();
+
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		init_iface(iface);
+		if_count++;
+	}
+
+	if (if_count == 0) {
+		NET_ERR("There is no network interface to work with!");
+		return;
+	}
+
+	iface_ipv6_init(if_count);
+	iface_ipv4_init(if_count);
+	iface_router_init();
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP_THREAD)
+	k_thread_create(&tx_thread_ts, tx_ts_stack,
+			K_KERNEL_STACK_SIZEOF(tx_ts_stack),
+			(k_thread_entry_t)net_tx_ts_thread,
+			NULL, NULL, NULL, K_PRIO_COOP(1), 0, K_NO_WAIT);
+	k_thread_name_set(&tx_thread_ts, "tx_tstamp");
+#endif /* CONFIG_NET_PKT_TIMESTAMP_THREAD */
+
+#if defined(CONFIG_NET_VLAN)
+	/* Make sure that we do not have too many network interfaces
+	 * compared to the number of VLAN interfaces.
+	 */
+	if_count = 0;
+
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+			if_count++;
+		}
+	}
+
+	if (if_count > CONFIG_NET_VLAN_COUNT) {
+		NET_WARN("You have configured only %d VLAN interfaces"
+			 " but you have %d network interfaces.",
+			 CONFIG_NET_VLAN_COUNT, if_count);
+	}
+#endif
+}
+
+void net_if_post_init(void)
+{
+	NET_DBG("");
+
+	/* After TX is running, attempt to bring the interface up */
+	Z_STRUCT_SECTION_FOREACH(net_if, iface) {
+		if (!net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
+			net_if_up(iface);
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_mgmt.c	(working copy)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mgmt, CONFIG_NET_MGMT_EVENT_LOG_LEVEL);
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <linker/sections.h>
+
+#include <sys/util.h>
+#include <sys/slist.h>
+#include <net/net_mgmt.h>
+#include <debug/stack.h>
+
+#include "net_private.h"
+
+struct mgmt_event_entry {
+	uint32_t event;
+	struct net_if *iface;
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+	uint8_t info[NET_EVENT_INFO_MAX_SIZE];
+	size_t info_length;
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+};
+
+struct mgmt_event_wait {
+	struct k_sem sync_call;
+	struct net_if *iface;
+};
+
+static K_SEM_DEFINE(network_event, 0, UINT_MAX);
+static K_SEM_DEFINE(net_mgmt_lock, 1, 1);
+
+K_KERNEL_STACK_DEFINE(mgmt_stack, CONFIG_NET_MGMT_EVENT_STACK_SIZE);
+static struct k_thread mgmt_thread_data;
+static struct mgmt_event_entry events[CONFIG_NET_MGMT_EVENT_QUEUE_SIZE];
+static uint32_t global_event_mask;
+static sys_slist_t event_callbacks;
+static int16_t in_event;
+static int16_t out_event;
+
+static inline void mgmt_push_event(uint32_t mgmt_event, struct net_if *iface,
+				   const void *info, size_t length)
+{
+	int16_t i_idx;
+
+#ifndef CONFIG_NET_MGMT_EVENT_INFO
+	ARG_UNUSED(info);
+	ARG_UNUSED(length);
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+
+	k_sem_take(&net_mgmt_lock, K_FOREVER);
+
+	i_idx = in_event + 1;
+	if (i_idx == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
+		i_idx = 0;
+	}
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+	if (info && length) {
+		if (length <= NET_EVENT_INFO_MAX_SIZE) {
+			memcpy(events[i_idx].info, info, length);
+			events[i_idx].info_length = length;
+		} else {
+			NET_ERR("Event info length %zu > max size %zu",
+				length, NET_EVENT_INFO_MAX_SIZE);
+			k_sem_give(&net_mgmt_lock);
+
+			return;
+		}
+	} else {
+		events[i_idx].info_length = 0;
+	}
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+
+	events[i_idx].event = mgmt_event;
+	events[i_idx].iface = iface;
+
+	if (i_idx == out_event) {
+		uint16_t o_idx = out_event + 1;
+
+		if (o_idx == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
+			o_idx = 0U;
+		}
+
+		if (events[o_idx].event) {
+			out_event = o_idx;
+		}
+	} else if (out_event < 0) {
+		out_event = i_idx;
+	}
+
+	in_event = i_idx;
+
+	k_sem_give(&net_mgmt_lock);
+}
+
+static inline struct mgmt_event_entry *mgmt_pop_event(void)
+{
+	int16_t o_idx;
+
+	if (out_event < 0 || !events[out_event].event) {
+		return NULL;
+	}
+
+	o_idx = out_event;
+	out_event++;
+
+	if (o_idx == in_event) {
+		in_event = -1;
+		out_event = -1;
+	} else if (out_event == CONFIG_NET_MGMT_EVENT_QUEUE_SIZE) {
+		out_event = 0;
+	}
+
+	return &events[o_idx];
+}
+
+static inline void mgmt_clean_event(struct mgmt_event_entry *mgmt_event)
+{
+	mgmt_event->event = 0U;
+	mgmt_event->iface = NULL;
+}
+
+static inline void mgmt_add_event_mask(uint32_t event_mask)
+{
+	global_event_mask |= event_mask;
+}
+
+static inline void mgmt_rebuild_global_event_mask(void)
+{
+	struct net_mgmt_event_callback *cb, *tmp;
+
+	global_event_mask = 0U;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&event_callbacks, cb, tmp, node) {
+		mgmt_add_event_mask(cb->event_mask);
+	}
+}
+
+static inline bool mgmt_is_event_handled(uint32_t mgmt_event)
+{
+	return (((NET_MGMT_GET_LAYER(mgmt_event) &
+		  NET_MGMT_GET_LAYER(global_event_mask)) ==
+		 NET_MGMT_GET_LAYER(mgmt_event)) &&
+		((NET_MGMT_GET_LAYER_CODE(mgmt_event) &
+		  NET_MGMT_GET_LAYER_CODE(global_event_mask)) ==
+		 NET_MGMT_GET_LAYER_CODE(mgmt_event)) &&
+		((NET_MGMT_GET_COMMAND(mgmt_event) &
+		  NET_MGMT_GET_COMMAND(global_event_mask)) ==
+		 NET_MGMT_GET_COMMAND(mgmt_event)));
+}
+
+static inline void mgmt_run_callbacks(struct mgmt_event_entry *mgmt_event)
+{
+	sys_snode_t *prev = NULL;
+	struct net_mgmt_event_callback *cb, *tmp;
+
+	NET_DBG("Event layer %u code %u cmd %u",
+		NET_MGMT_GET_LAYER(mgmt_event->event),
+		NET_MGMT_GET_LAYER_CODE(mgmt_event->event),
+		NET_MGMT_GET_COMMAND(mgmt_event->event));
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&event_callbacks, cb, tmp, node) {
+		if (!(NET_MGMT_GET_LAYER(mgmt_event->event) ==
+		      NET_MGMT_GET_LAYER(cb->event_mask)) ||
+		    !(NET_MGMT_GET_LAYER_CODE(mgmt_event->event) ==
+		      NET_MGMT_GET_LAYER_CODE(cb->event_mask)) ||
+		    (NET_MGMT_GET_COMMAND(mgmt_event->event) &&
+		     NET_MGMT_GET_COMMAND(cb->event_mask) &&
+		     !(NET_MGMT_GET_COMMAND(mgmt_event->event) &
+		       NET_MGMT_GET_COMMAND(cb->event_mask)))) {
+			continue;
+		}
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+		if (mgmt_event->info_length) {
+			cb->info = (void *)mgmt_event->info;
+			cb->info_length = mgmt_event->info_length;
+		} else {
+			cb->info = NULL;
+			cb->info_length = 0;
+		}
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+
+		if (NET_MGMT_EVENT_SYNCHRONOUS(cb->event_mask)) {
+			struct mgmt_event_wait *sync_data =
+				CONTAINER_OF(cb->sync_call,
+					     struct mgmt_event_wait, sync_call);
+
+			if (sync_data->iface &&
+			    sync_data->iface != mgmt_event->iface) {
+				continue;
+			}
+
+			NET_DBG("Unlocking %p synchronous call", cb);
+
+			cb->raised_event = mgmt_event->event;
+			sync_data->iface = mgmt_event->iface;
+
+			sys_slist_remove(&event_callbacks, prev, &cb->node);
+
+			k_sem_give(cb->sync_call);
+		} else {
+			NET_DBG("Running callback %p : %p",
+				cb, cb->handler);
+
+			cb->handler(cb, mgmt_event->event, mgmt_event->iface);
+			prev = &cb->node;
+		}
+	}
+
+#ifdef CONFIG_NET_DEBUG_MGMT_EVENT_STACK
+	log_stack_usage(&mgmt_thread_data);
+#endif
+}
+
+static void mgmt_thread(void)
+{
+	struct mgmt_event_entry *mgmt_event;
+
+	while (1) {
+		k_sem_take(&network_event, K_FOREVER);
+		k_sem_take(&net_mgmt_lock, K_FOREVER);
+
+		NET_DBG("Handling events, forwarding it relevantly");
+
+		mgmt_event = mgmt_pop_event();
+		if (!mgmt_event) {
+			/* System is over-loaded?
+			 * At this point we have most probably notified
+			 * more events than we could handle
+			 */
+			NET_DBG("Some event got probably lost (%u)",
+				k_sem_count_get(&network_event));
+
+			k_sem_init(&network_event, 0, UINT_MAX);
+			k_sem_give(&net_mgmt_lock);
+
+			continue;
+		}
+
+		mgmt_run_callbacks(mgmt_event);
+
+		mgmt_clean_event(mgmt_event);
+
+		k_sem_give(&net_mgmt_lock);
+
+		k_yield();
+	}
+}
+
+static int mgmt_event_wait_call(struct net_if *iface,
+				uint32_t mgmt_event_mask,
+				uint32_t *raised_event,
+				struct net_if **event_iface,
+				const void **info,
+				size_t *info_length,
+				k_timeout_t timeout)
+{
+	struct mgmt_event_wait sync_data = {
+		.sync_call = Z_SEM_INITIALIZER(sync_data.sync_call, 0, 1),
+	};
+	struct net_mgmt_event_callback sync = {
+		.sync_call = &sync_data.sync_call,
+		.event_mask = mgmt_event_mask | NET_MGMT_SYNC_EVENT_BIT,
+	};
+	int ret;
+
+	if (iface) {
+		sync_data.iface = iface;
+	}
+
+	NET_DBG("Synchronous event 0x%08x wait %p", sync.event_mask, &sync);
+
+	net_mgmt_add_event_callback(&sync);
+
+	ret = k_sem_take(sync.sync_call, timeout);
+	if (ret == -EAGAIN) {
+		ret = -ETIMEDOUT;
+	} else {
+		if (!ret) {
+			if (raised_event) {
+				*raised_event = sync.raised_event;
+			}
+
+			if (event_iface) {
+				*event_iface = sync_data.iface;
+			}
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+			if (info) {
+				*info = sync.info;
+
+				if (info_length) {
+					*info_length = sync.info_length;
+				}
+			}
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+		}
+	}
+
+	return ret;
+}
+
+void net_mgmt_add_event_callback(struct net_mgmt_event_callback *cb)
+{
+	NET_DBG("Adding event callback %p", cb);
+
+	k_sem_take(&net_mgmt_lock, K_FOREVER);
+
+	sys_slist_prepend(&event_callbacks, &cb->node);
+
+	mgmt_add_event_mask(cb->event_mask);
+
+	k_sem_give(&net_mgmt_lock);
+}
+
+void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb)
+{
+	NET_DBG("Deleting event callback %p", cb);
+
+	k_sem_take(&net_mgmt_lock, K_FOREVER);
+
+	sys_slist_find_and_remove(&event_callbacks, &cb->node);
+
+	mgmt_rebuild_global_event_mask();
+
+	k_sem_give(&net_mgmt_lock);
+}
+
+void net_mgmt_event_notify_with_info(uint32_t mgmt_event, struct net_if *iface,
+				     const void *info, size_t length)
+{
+	if (mgmt_is_event_handled(mgmt_event)) {
+		NET_DBG("Notifying Event layer %u code %u type %u",
+			NET_MGMT_GET_LAYER(mgmt_event),
+			NET_MGMT_GET_LAYER_CODE(mgmt_event),
+			NET_MGMT_GET_COMMAND(mgmt_event));
+
+		mgmt_push_event(mgmt_event, iface, info, length);
+		k_sem_give(&network_event);
+	}
+}
+
+int net_mgmt_event_wait(uint32_t mgmt_event_mask,
+			uint32_t *raised_event,
+			struct net_if **iface,
+			const void **info,
+			size_t *info_length,
+			k_timeout_t timeout)
+{
+	return mgmt_event_wait_call(NULL, mgmt_event_mask,
+				    raised_event, iface, info, info_length,
+				    timeout);
+}
+
+int net_mgmt_event_wait_on_iface(struct net_if *iface,
+				 uint32_t mgmt_event_mask,
+				 uint32_t *raised_event,
+				 const void **info,
+				 size_t *info_length,
+				 k_timeout_t timeout)
+{
+	NET_ASSERT(NET_MGMT_ON_IFACE(mgmt_event_mask));
+	NET_ASSERT(iface);
+
+	return mgmt_event_wait_call(iface, mgmt_event_mask,
+				    raised_event, NULL, info, info_length,
+				    timeout);
+}
+
+void net_mgmt_event_init(void)
+{
+	sys_slist_init(&event_callbacks);
+	global_event_mask = 0U;
+
+	in_event = -1;
+	out_event = -1;
+
+	(void)memset(events, 0, CONFIG_NET_MGMT_EVENT_QUEUE_SIZE *
+			sizeof(struct mgmt_event_entry));
+
+	k_thread_create(&mgmt_thread_data, mgmt_stack,
+			K_KERNEL_STACK_SIZEOF(mgmt_stack),
+			(k_thread_entry_t)mgmt_thread, NULL, NULL, NULL,
+			K_PRIO_COOP(CONFIG_NET_MGMT_EVENT_THREAD_PRIO), 0,
+			K_NO_WAIT);
+	k_thread_name_set(&mgmt_thread_data, "net_mgmt");
+
+	NET_DBG("Net MGMT initialized: queue of %u entries, stack size of %u",
+		CONFIG_NET_MGMT_EVENT_QUEUE_SIZE,
+		CONFIG_NET_MGMT_EVENT_STACK_SIZE);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_pkt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_pkt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_pkt.c	(working copy)
@@ -0,0 +1,2036 @@
+/** @file
+ @brief Network packet buffers for IP stack
+
+ Network data is passed between components using net_pkt.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_pkt, CONFIG_NET_PKT_LOG_LEVEL);
+
+/* This enables allocation debugging but does not print so much output
+ * as that can slow things down a lot.
+ */
+#undef NET_LOG_LEVEL
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+#define NET_LOG_LEVEL 5
+#else
+#define NET_LOG_LEVEL CONFIG_NET_PKT_LOG_LEVEL
+#endif
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <string.h>
+#include <zephyr/types.h>
+#include <sys/types.h>
+
+#include <sys/util.h>
+
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/buf.h>
+#include <net/net_pkt.h>
+#include <net/ethernet.h>
+#include <net/udp.h>
+
+#include "net_private.h"
+#include "tcp_internal.h"
+
+/* Find max header size of IP protocol (IPv4 or IPv6) */
+#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_RAW_MODE) || \
+    defined(CONFIG_NET_SOCKETS_PACKET) || defined(CONFIG_NET_SOCKETS_OFFLOAD)
+#define MAX_IP_PROTO_LEN NET_IPV6H_LEN
+#else
+#if defined(CONFIG_NET_IPV4)
+#define MAX_IP_PROTO_LEN NET_IPV4H_LEN
+#else
+#if defined(CONFIG_NET_SOCKETS_CAN)
+/* TODO: Use CAN MTU here instead of hard coded value. There was
+ * weird circular dependency issue so this needs more TLC.
+ */
+#define MAX_IP_PROTO_LEN 8
+#else
+#error "Either IPv6 or IPv4 needs to be selected."
+#endif /* SOCKETS_CAN */
+#endif /* IPv4 */
+#endif /* IPv6 */
+
+/* Find max header size of "next" protocol (TCP, UDP or ICMP) */
+#if defined(CONFIG_NET_TCP)
+#define MAX_NEXT_PROTO_LEN NET_TCPH_LEN
+#else
+#if defined(CONFIG_NET_UDP)
+#define MAX_NEXT_PROTO_LEN NET_UDPH_LEN
+#else
+#if defined(CONFIG_NET_SOCKETS_CAN)
+#define MAX_NEXT_PROTO_LEN 0
+#else
+/* If no TCP and no UDP, apparently we still want pings to work. */
+#define MAX_NEXT_PROTO_LEN NET_ICMPH_LEN
+#endif /* SOCKETS_CAN */
+#endif /* UDP */
+#endif /* TCP */
+
+/* Make sure that IP + TCP/UDP/ICMP headers fit into one fragment. This
+ * makes possible to cast a fragment pointer to protocol header struct.
+ */
+#if CONFIG_NET_BUF_DATA_SIZE < (MAX_IP_PROTO_LEN + MAX_NEXT_PROTO_LEN)
+#if defined(STRING2)
+#undef STRING2
+#endif
+#if defined(STRING)
+#undef STRING
+#endif
+#define STRING2(x) #x
+#define STRING(x) STRING2(x)
+#pragma message "Data len " STRING(CONFIG_NET_BUF_DATA_SIZE)
+#pragma message "Minimum len " STRING(MAX_IP_PROTO_LEN + MAX_NEXT_PROTO_LEN)
+#error "Too small net_buf fragment size"
+#endif
+
+#if CONFIG_NET_PKT_RX_COUNT <= 0
+#error "Minimum value for CONFIG_NET_PKT_RX_COUNT is 1"
+#endif
+
+#if CONFIG_NET_PKT_TX_COUNT <= 0
+#error "Minimum value for CONFIG_NET_PKT_TX_COUNT is 1"
+#endif
+
+#if CONFIG_NET_BUF_RX_COUNT <= 0
+#error "Minimum value for CONFIG_NET_BUF_RX_COUNT is 1"
+#endif
+
+#if CONFIG_NET_BUF_TX_COUNT <= 0
+#error "Minimum value for CONFIG_NET_BUF_TX_COUNT is 1"
+#endif
+
+K_MEM_SLAB_DEFINE(rx_pkts, sizeof(struct net_pkt), CONFIG_NET_PKT_RX_COUNT, 4);
+K_MEM_SLAB_DEFINE(tx_pkts, sizeof(struct net_pkt), CONFIG_NET_PKT_TX_COUNT, 4);
+
+#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
+
+NET_BUF_POOL_FIXED_DEFINE(rx_bufs, CONFIG_NET_BUF_RX_COUNT,
+			  CONFIG_NET_BUF_DATA_SIZE, NULL);
+NET_BUF_POOL_FIXED_DEFINE(tx_bufs, CONFIG_NET_BUF_TX_COUNT,
+			  CONFIG_NET_BUF_DATA_SIZE, NULL);
+
+#else /* !CONFIG_NET_BUF_FIXED_DATA_SIZE */
+
+NET_BUF_POOL_VAR_DEFINE(rx_bufs, CONFIG_NET_BUF_RX_COUNT,
+			CONFIG_NET_BUF_DATA_POOL_SIZE, NULL);
+NET_BUF_POOL_VAR_DEFINE(tx_bufs, CONFIG_NET_BUF_TX_COUNT,
+			CONFIG_NET_BUF_DATA_POOL_SIZE, NULL);
+
+#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
+
+/* Allocation tracking is only available if separately enabled */
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+struct net_pkt_alloc {
+	union {
+		struct net_pkt *pkt;
+		struct net_buf *buf;
+		void *alloc_data;
+	};
+	const char *func_alloc;
+	const char *func_free;
+	uint16_t line_alloc;
+	uint16_t line_free;
+	uint8_t in_use;
+	bool is_pkt;
+};
+
+#define MAX_NET_PKT_ALLOCS (CONFIG_NET_PKT_RX_COUNT + \
+			    CONFIG_NET_PKT_TX_COUNT + \
+			    CONFIG_NET_BUF_RX_COUNT + \
+			    CONFIG_NET_BUF_TX_COUNT + \
+			    CONFIG_NET_DEBUG_NET_PKT_EXTERNALS)
+
+static struct net_pkt_alloc net_pkt_allocs[MAX_NET_PKT_ALLOCS];
+
+static void net_pkt_alloc_add(void *alloc_data, bool is_pkt,
+			      const char *func, int line)
+{
+	int i;
+
+	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
+		if (net_pkt_allocs[i].in_use) {
+			continue;
+		}
+
+		net_pkt_allocs[i].in_use = true;
+		net_pkt_allocs[i].is_pkt = is_pkt;
+		net_pkt_allocs[i].alloc_data = alloc_data;
+		net_pkt_allocs[i].func_alloc = func;
+		net_pkt_allocs[i].line_alloc = line;
+
+		return;
+	}
+}
+
+static void net_pkt_alloc_del(void *alloc_data, const char *func, int line)
+{
+	int i;
+
+	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
+		if (net_pkt_allocs[i].in_use &&
+		    net_pkt_allocs[i].alloc_data == alloc_data) {
+			net_pkt_allocs[i].func_free = func;
+			net_pkt_allocs[i].line_free = line;
+			net_pkt_allocs[i].in_use = false;
+
+			return;
+		}
+	}
+}
+
+static bool net_pkt_alloc_find(void *alloc_data,
+			       const char **func_free,
+			       int *line_free)
+{
+	int i;
+
+	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
+		if (!net_pkt_allocs[i].in_use &&
+		    net_pkt_allocs[i].alloc_data == alloc_data) {
+			*func_free = net_pkt_allocs[i].func_free;
+			*line_free = net_pkt_allocs[i].line_free;
+
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void net_pkt_allocs_foreach(net_pkt_allocs_cb_t cb, void *user_data)
+{
+	int i;
+
+	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
+		if (net_pkt_allocs[i].in_use) {
+			cb(net_pkt_allocs[i].is_pkt ?
+			   net_pkt_allocs[i].pkt : NULL,
+			   net_pkt_allocs[i].is_pkt ?
+			   NULL : net_pkt_allocs[i].buf,
+			   net_pkt_allocs[i].func_alloc,
+			   net_pkt_allocs[i].line_alloc,
+			   net_pkt_allocs[i].func_free,
+			   net_pkt_allocs[i].line_free,
+			   net_pkt_allocs[i].in_use,
+			   user_data);
+		}
+	}
+
+	for (i = 0; i < MAX_NET_PKT_ALLOCS; i++) {
+		if (!net_pkt_allocs[i].in_use) {
+			cb(net_pkt_allocs[i].is_pkt ?
+			   net_pkt_allocs[i].pkt : NULL,
+			   net_pkt_allocs[i].is_pkt ?
+			   NULL : net_pkt_allocs[i].buf,
+			   net_pkt_allocs[i].func_alloc,
+			   net_pkt_allocs[i].line_alloc,
+			   net_pkt_allocs[i].func_free,
+			   net_pkt_allocs[i].line_free,
+			   net_pkt_allocs[i].in_use,
+			   user_data);
+		}
+	}
+}
+#else
+#define net_pkt_alloc_add(alloc_data, is_pkt, func, line)
+#define net_pkt_alloc_del(alloc_data, func, line)
+#define net_pkt_alloc_find(alloc_data, func_free, line_free) false
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) || \
+	CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+
+#define NET_FRAG_CHECK_IF_NOT_IN_USE(frag, ref)				\
+	do {								\
+		if (!(ref)) {                                           \
+			NET_ERR("**ERROR** frag %p not in use (%s:%s():%d)", \
+				frag, __FILE__, __func__, __LINE__);     \
+		}                                                       \
+	} while (0)
+
+const char *net_pkt_slab2str(struct k_mem_slab *slab)
+{
+	if (slab == &rx_pkts) {
+		return "RX";
+	} else if (slab == &tx_pkts) {
+		return "TX";
+	}
+
+	return "EXT";
+}
+
+const char *net_pkt_pool2str(struct net_buf_pool *pool)
+{
+	if (pool == &rx_bufs) {
+		return "RDATA";
+	} else if (pool == &tx_bufs) {
+		return "TDATA";
+	}
+
+	return "EDATA";
+}
+#endif
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC) || \
+	CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+static inline int16_t get_frees(struct net_buf_pool *pool)
+{
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	return pool->avail_count;
+#else
+	return 0;
+#endif
+}
+#endif
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+static inline const char *get_name(struct net_buf_pool *pool)
+{
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	return pool->name;
+#else
+	return "?";
+#endif
+}
+
+static inline int16_t get_size(struct net_buf_pool *pool)
+{
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	return pool->pool_size;
+#else
+	return 0;
+#endif
+}
+
+static inline const char *slab2str(struct k_mem_slab *slab)
+{
+	return net_pkt_slab2str(slab);
+}
+
+static inline const char *pool2str(struct net_buf_pool *pool)
+{
+	return net_pkt_pool2str(pool);
+}
+
+void net_pkt_print_frags(struct net_pkt *pkt)
+{
+	struct net_buf *frag;
+	size_t total = 0;
+	int count = 0, frag_size = 0;
+
+	if (!pkt) {
+		NET_INFO("pkt %p", pkt);
+		return;
+	}
+
+	NET_INFO("pkt %p frags %p", pkt, pkt->frags);
+
+	NET_ASSERT(pkt->frags);
+
+	frag = pkt->frags;
+	while (frag) {
+		total += frag->len;
+
+		frag_size = frag->size;
+
+		NET_INFO("[%d] frag %p len %d size %d pool %p",
+			 count, frag, frag->len, frag_size,
+			 net_buf_pool_get(frag->pool_id));
+
+		count++;
+
+		frag = frag->frags;
+	}
+
+	NET_INFO("Total data size %zu, occupied %d bytes, utilization %zu%%",
+		 total, count * frag_size,
+		 count ? (total * 100) / (count * frag_size) : 0);
+}
+#endif /* CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_buf *net_pkt_get_reserve_data_debug(struct net_buf_pool *pool,
+					       k_timeout_t timeout,
+					       const char *caller,
+					       int line)
+#else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+struct net_buf *net_pkt_get_reserve_data(struct net_buf_pool *pool,
+					 k_timeout_t timeout)
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+{
+	struct net_buf *frag;
+
+	/*
+	 * The reserve_head variable in the function will tell
+	 * the size of the link layer headers if there are any.
+	 */
+
+	if (k_is_in_isr()) {
+		frag = net_buf_alloc(pool, K_NO_WAIT);
+	} else {
+		frag = net_buf_alloc(pool, timeout);
+	}
+
+	if (!frag) {
+		return NULL;
+	}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_FRAG_CHECK_IF_NOT_IN_USE(frag, frag->ref + 1U);
+#endif
+
+	net_pkt_alloc_add(frag, false, caller, line);
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
+		pool2str(pool), get_name(pool), get_frees(pool),
+		frag, frag->ref, caller, line);
+#endif
+
+	return frag;
+}
+
+/* Get a fragment, try to figure out the pool from where to get
+ * the data.
+ */
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_buf *net_pkt_get_frag_debug(struct net_pkt *pkt,
+				       k_timeout_t timeout,
+				       const char *caller, int line)
+#else
+struct net_buf *net_pkt_get_frag(struct net_pkt *pkt,
+				 k_timeout_t timeout)
+#endif
+{
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+	struct net_context *context;
+
+	context = net_pkt_context(pkt);
+	if (context && context->data_pool) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		return net_pkt_get_reserve_data_debug(context->data_pool(),
+						      timeout, caller, line);
+#else
+		return net_pkt_get_reserve_data(context->data_pool(), timeout);
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+	}
+#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
+
+	if (pkt->slab == &rx_pkts) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		return net_pkt_get_reserve_rx_data_debug(timeout,
+							 caller, line);
+#else
+		return net_pkt_get_reserve_rx_data(timeout);
+#endif
+	}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return net_pkt_get_reserve_tx_data_debug(timeout, caller, line);
+#else
+	return net_pkt_get_reserve_tx_data(timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_buf *net_pkt_get_reserve_rx_data_debug(k_timeout_t timeout,
+						  const char *caller, int line)
+{
+	return net_pkt_get_reserve_data_debug(&rx_bufs, timeout, caller, line);
+}
+
+struct net_buf *net_pkt_get_reserve_tx_data_debug(k_timeout_t timeout,
+						  const char *caller, int line)
+{
+	return net_pkt_get_reserve_data_debug(&tx_bufs, timeout, caller, line);
+}
+
+#else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+struct net_buf *net_pkt_get_reserve_rx_data(k_timeout_t timeout)
+{
+	return net_pkt_get_reserve_data(&rx_bufs, timeout);
+}
+
+struct net_buf *net_pkt_get_reserve_tx_data(k_timeout_t timeout)
+{
+	return net_pkt_get_reserve_data(&tx_bufs, timeout);
+}
+
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+static inline struct k_mem_slab *get_tx_slab(struct net_context *context)
+{
+	if (context->tx_slab) {
+		return context->tx_slab();
+	}
+
+	return NULL;
+}
+
+static inline struct net_buf_pool *get_data_pool(struct net_context *context)
+{
+	if (context->data_pool) {
+		return context->data_pool();
+	}
+
+	return NULL;
+}
+#else
+#define get_tx_slab(...) NULL
+#define get_data_pool(...) NULL
+#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+void net_pkt_unref_debug(struct net_pkt *pkt, const char *caller, int line)
+{
+	struct net_buf *frag;
+
+#else
+void net_pkt_unref(struct net_pkt *pkt)
+{
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+	atomic_val_t ref;
+
+	if (!pkt) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_ERR("*** ERROR *** pkt %p (%s():%d)", pkt, caller, line);
+#endif
+		return;
+	}
+
+	do {
+		ref = atomic_get(&pkt->atomic_ref);
+		if (!ref) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+			const char *func_freed;
+			int line_freed;
+
+			if (net_pkt_alloc_find(pkt, &func_freed, &line_freed)) {
+				NET_ERR("*** ERROR *** pkt %p is freed already "
+					"by %s():%d (%s():%d)",
+					pkt, func_freed, line_freed, caller,
+					line);
+			} else {
+				NET_ERR("*** ERROR *** pkt %p is freed already "
+					"(%s():%d)", pkt, caller, line);
+			}
+#endif
+			return;
+		}
+	} while (!atomic_cas(&pkt->atomic_ref, ref, ref - 1));
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("%s [%d] pkt %p ref %d frags %p (%s():%d)",
+		slab2str(pkt->slab), k_mem_slab_num_free_get(pkt->slab),
+		pkt, ref - 1, pkt->frags, caller, line);
+#endif
+	if (ref > 1) {
+		goto done;
+	}
+
+	frag = pkt->frags;
+	while (frag) {
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_DBG("%s (%s) [%d] frag %p ref %d frags %p (%s():%d)",
+			pool2str(net_buf_pool_get(frag->pool_id)),
+			get_name(net_buf_pool_get(frag->pool_id)),
+			get_frees(net_buf_pool_get(frag->pool_id)), frag,
+			frag->ref - 1U, frag->frags, caller, line);
+#endif
+
+		if (!frag->ref) {
+			const char *func_freed;
+			int line_freed;
+
+			if (net_pkt_alloc_find(frag,
+					       &func_freed, &line_freed)) {
+				NET_ERR("*** ERROR *** frag %p is freed "
+					"already by %s():%d (%s():%d)",
+					frag, func_freed, line_freed,
+					caller, line);
+			} else {
+				NET_ERR("*** ERROR *** frag %p is freed "
+					"already (%s():%d)",
+					frag, caller, line);
+			}
+		}
+
+		net_pkt_alloc_del(frag, caller, line);
+
+		frag = frag->frags;
+	}
+
+	net_pkt_alloc_del(pkt, caller, line);
+done:
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+	if (ref > 1) {
+		return;
+	}
+
+	if (pkt->frags) {
+		net_pkt_frag_unref(pkt->frags);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_DEBUG_NET_PKT_NON_FRAGILE_ACCESS)) {
+		pkt->buffer = NULL;
+		net_pkt_cursor_init(pkt);
+	}
+
+	k_mem_slab_free(pkt->slab, (void **)&pkt);
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_ref_debug(struct net_pkt *pkt, const char *caller,
+				  int line)
+#else
+struct net_pkt *net_pkt_ref(struct net_pkt *pkt)
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+{
+	atomic_val_t ref;
+
+	do {
+		ref = pkt ? atomic_get(&pkt->atomic_ref) : 0;
+		if (!ref) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+			NET_ERR("*** ERROR *** pkt %p (%s():%d)",
+				pkt, caller, line);
+#endif
+			return NULL;
+		}
+	} while (!atomic_cas(&pkt->atomic_ref, ref, ref + 1));
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("%s [%d] pkt %p ref %d (%s():%d)",
+		slab2str(pkt->slab), k_mem_slab_num_free_get(pkt->slab),
+		pkt, ref + 1, caller, line);
+#endif
+
+
+	return pkt;
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_buf *net_pkt_frag_ref_debug(struct net_buf *frag,
+				       const char *caller, int line)
+#else
+struct net_buf *net_pkt_frag_ref(struct net_buf *frag)
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+{
+	if (!frag) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_ERR("*** ERROR *** frag %p (%s():%d)", frag, caller, line);
+#endif
+		return NULL;
+	}
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
+		pool2str(net_buf_pool_get(frag->pool_id)),
+		get_name(net_buf_pool_get(frag->pool_id)),
+		get_frees(net_buf_pool_get(frag->pool_id)),
+		frag, frag->ref + 1U, caller, line);
+#endif
+
+	return net_buf_ref(frag);
+}
+
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+void net_pkt_frag_unref_debug(struct net_buf *frag,
+			      const char *caller, int line)
+#else
+void net_pkt_frag_unref(struct net_buf *frag)
+#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
+{
+	if (!frag) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_ERR("*** ERROR *** frag %p (%s():%d)", frag, caller, line);
+#endif
+		return;
+	}
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
+		pool2str(net_buf_pool_get(frag->pool_id)),
+		get_name(net_buf_pool_get(frag->pool_id)),
+		get_frees(net_buf_pool_get(frag->pool_id)),
+		frag, frag->ref - 1U, caller, line);
+#endif
+
+	if (frag->ref == 1U) {
+		net_pkt_alloc_del(frag, caller, line);
+	}
+
+	net_buf_unref(frag);
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_buf *net_pkt_frag_del_debug(struct net_pkt *pkt,
+				       struct net_buf *parent,
+				       struct net_buf *frag,
+				       const char *caller, int line)
+#else
+struct net_buf *net_pkt_frag_del(struct net_pkt *pkt,
+				 struct net_buf *parent,
+				 struct net_buf *frag)
+#endif
+{
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("pkt %p parent %p frag %p ref %u (%s:%d)",
+		pkt, parent, frag, frag->ref, caller, line);
+#endif
+
+	if (pkt->frags == frag && !parent) {
+		struct net_buf *tmp;
+
+		if (frag->ref == 1U) {
+			net_pkt_alloc_del(frag, caller, line);
+		}
+
+		tmp = net_buf_frag_del(NULL, frag);
+		pkt->frags = tmp;
+
+		return tmp;
+	}
+
+	if (frag->ref == 1U) {
+		net_pkt_alloc_del(frag, caller, line);
+	}
+
+	return net_buf_frag_del(parent, frag);
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+void net_pkt_frag_add_debug(struct net_pkt *pkt, struct net_buf *frag,
+			    const char *caller, int line)
+#else
+void net_pkt_frag_add(struct net_pkt *pkt, struct net_buf *frag)
+#endif
+{
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("pkt %p frag %p (%s:%d)", pkt, frag, caller, line);
+#endif
+
+	/* We do not use net_buf_frag_add() as this one will refcount
+	 * the frag once more if !pkt->frags
+	 */
+	if (!pkt->frags) {
+		pkt->frags = frag;
+		return;
+	}
+
+	net_buf_frag_insert(net_buf_frag_last(pkt->frags), frag);
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+void net_pkt_frag_insert_debug(struct net_pkt *pkt, struct net_buf *frag,
+			       const char *caller, int line)
+#else
+void net_pkt_frag_insert(struct net_pkt *pkt, struct net_buf *frag)
+#endif
+{
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("pkt %p frag %p (%s:%d)", pkt, frag, caller, line);
+#endif
+
+	net_buf_frag_last(frag)->frags = pkt->frags;
+	pkt->frags = frag;
+}
+
+bool net_pkt_compact(struct net_pkt *pkt)
+{
+	struct net_buf *frag, *prev;
+
+	NET_DBG("Compacting data in pkt %p", pkt);
+
+	frag = pkt->frags;
+	prev = NULL;
+
+	while (frag) {
+		if (frag->frags) {
+			/* Copy amount of data from next fragment to this
+			 * fragment.
+			 */
+			size_t copy_len;
+
+			copy_len = frag->frags->len;
+			if (copy_len > net_buf_tailroom(frag)) {
+				copy_len = net_buf_tailroom(frag);
+			}
+
+			memcpy(net_buf_tail(frag), frag->frags->data, copy_len);
+			net_buf_add(frag, copy_len);
+
+			memmove(frag->frags->data,
+				frag->frags->data + copy_len,
+				frag->frags->len - copy_len);
+
+			frag->frags->len -= copy_len;
+
+			/* Is there any more space in this fragment */
+			if (net_buf_tailroom(frag)) {
+				/* There is. This also means that the next
+				 * fragment is empty as otherwise we could
+				 * not have copied all data. Remove next
+				 * fragment as there is no data in it any more.
+				 */
+				net_pkt_frag_del(pkt, frag, frag->frags);
+
+				/* Then check next fragment */
+				continue;
+			}
+		} else {
+			if (!frag->len) {
+				/* Remove the last fragment because there is no
+				 * data in it.
+				 */
+				net_pkt_frag_del(pkt, prev, frag);
+
+				break;
+			}
+		}
+
+		prev = frag;
+		frag = frag->frags;
+	}
+
+	return true;
+}
+
+void net_pkt_get_info(struct k_mem_slab **rx,
+		      struct k_mem_slab **tx,
+		      struct net_buf_pool **rx_data,
+		      struct net_buf_pool **tx_data)
+{
+	if (rx) {
+		*rx = &rx_pkts;
+	}
+
+	if (tx) {
+		*tx = &tx_pkts;
+	}
+
+	if (rx_data) {
+		*rx_data = &rx_bufs;
+	}
+
+	if (tx_data) {
+		*tx_data = &tx_bufs;
+	}
+}
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+void net_pkt_print(void)
+{
+	NET_DBG("TX %u RX %u RDATA %d TDATA %d",
+		k_mem_slab_num_free_get(&tx_pkts),
+		k_mem_slab_num_free_get(&rx_pkts),
+		get_frees(&rx_bufs), get_frees(&tx_bufs));
+}
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
+
+/* New allocator and API starts here */
+
+#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
+					size_t size, k_timeout_t timeout,
+					const char *caller, int line)
+#else
+static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
+					size_t size, k_timeout_t timeout)
+#endif
+{
+	uint64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf *first = NULL;
+	struct net_buf *current = NULL;
+
+	while (size) {
+		struct net_buf *new;
+
+		new = net_buf_alloc_fixed(pool, timeout);
+		if (!new) {
+			goto error;
+		}
+
+		if (!first && !current) {
+			first = new;
+		} else {
+			current->frags = new;
+		}
+
+		current = new;
+		if (current->size > size) {
+			current->size = size;
+		}
+
+		size -= current->size;
+
+		if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+		    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			int64_t remaining = end - z_tick_get();
+
+			if (remaining <= 0) {
+				break;
+			}
+
+			timeout = Z_TIMEOUT_TICKS(remaining);
+		}
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_FRAG_CHECK_IF_NOT_IN_USE(new, new->ref + 1);
+
+		net_pkt_alloc_add(new, false, caller, line);
+
+		NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
+			pool2str(pool), get_name(pool), get_frees(pool),
+			new, new->ref, caller, line);
+#endif
+	}
+
+	return first;
+error:
+	if (first) {
+		net_buf_unref(first);
+	}
+
+	return NULL;
+}
+
+#else /* !CONFIG_NET_BUF_FIXED_DATA_SIZE */
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
+					size_t size, k_timeout_t timeout,
+					const char *caller, int line)
+#else
+static struct net_buf *pkt_alloc_buffer(struct net_buf_pool *pool,
+					size_t size, k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf;
+
+	buf = net_buf_alloc_len(pool, size, timeout);
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_FRAG_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1);
+
+	net_pkt_alloc_add(buf, false, caller, line);
+
+	NET_DBG("%s (%s) [%d] frag %p ref %d (%s():%d)",
+		pool2str(pool), get_name(pool), get_frees(pool),
+		buf, buf->ref, caller, line);
+#endif
+
+	return buf;
+}
+
+#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
+
+static size_t pkt_buffer_length(struct net_pkt *pkt,
+				size_t size,
+				enum net_ip_protocol proto,
+				size_t existing)
+{
+	sa_family_t family = net_pkt_family(pkt);
+	size_t max_len;
+
+	if (net_pkt_iface(pkt)) {
+		max_len = net_if_get_mtu(net_pkt_iface(pkt));
+	} else {
+		max_len = 0;
+	}
+
+	/* Family vs iface MTU */
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		if (IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) && (size > max_len)) {
+			/* We support larger packets if IPv6 fragmentation is
+			 * enabled.
+			 */
+			max_len = size;
+		}
+
+		max_len = MAX(max_len, NET_IPV6_MTU);
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+		max_len = MAX(max_len, NET_IPV4_MTU);
+	} else { /* family == AF_UNSPEC */
+#if defined (CONFIG_NET_L2_ETHERNET)
+		if (net_if_l2(net_pkt_iface(pkt)) ==
+		    &NET_L2_GET_NAME(ETHERNET)) {
+			max_len += sizeof(struct net_eth_hdr);
+		} else
+#endif /* CONFIG_NET_L2_ETHERNET */
+		{
+			/* Other L2 are not checked as the pkt MTU in this case
+			 * is based on the IP layer (IPv6 most of the time).
+			 */
+			max_len = size;
+		}
+	}
+
+	max_len -= existing;
+
+	return MIN(size, max_len);
+}
+
+static size_t pkt_estimate_headers_length(struct net_pkt *pkt,
+					  sa_family_t family,
+					  enum net_ip_protocol proto)
+{
+	size_t hdr_len = 0;
+
+	if (family == AF_UNSPEC) {
+		return  0;
+	}
+
+	/* Family header */
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		hdr_len += NET_IPV6H_LEN;
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+		hdr_len += NET_IPV4H_LEN;
+	}
+
+	/* + protocol header */
+	if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+		hdr_len += NET_TCPH_LEN + NET_TCP_MAX_OPT_SIZE;
+	} else if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
+		hdr_len += NET_UDPH_LEN;
+	} else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
+		hdr_len += NET_ICMPH_LEN;
+	}
+
+	NET_DBG("HDRs length estimation %zu", hdr_len);
+
+	return hdr_len;
+}
+
+static size_t pkt_get_size(struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->buffer;
+	size_t size = 0;
+
+	while (buf) {
+		size += buf->size;
+		buf = buf->frags;
+	}
+
+	return size;
+}
+
+size_t net_pkt_available_buffer(struct net_pkt *pkt)
+{
+	if (!pkt) {
+		return 0;
+	}
+
+	return pkt_get_size(pkt) - net_pkt_get_len(pkt);
+}
+
+size_t net_pkt_available_payload_buffer(struct net_pkt *pkt,
+					enum net_ip_protocol proto)
+{
+	size_t hdr_len = 0;
+	size_t len;
+
+	if (!pkt) {
+		return 0;
+	}
+
+	hdr_len = pkt_estimate_headers_length(pkt, net_pkt_family(pkt), proto);
+	len = net_pkt_get_len(pkt);
+
+	hdr_len = hdr_len <= len ? 0 : hdr_len - len;
+
+	len = net_pkt_available_buffer(pkt) - hdr_len;
+
+	return len;
+}
+
+void net_pkt_trim_buffer(struct net_pkt *pkt)
+{
+	struct net_buf *buf, *prev;
+
+	buf = pkt->buffer;
+	prev = buf;
+
+	while (buf) {
+		struct net_buf *next = buf->frags;
+
+		if (!buf->len) {
+			if (buf == pkt->buffer) {
+				pkt->buffer = next;
+			} else if (buf == prev->frags) {
+				prev->frags = next;
+			}
+
+			buf->frags = NULL;
+			net_buf_unref(buf);
+		} else {
+			prev = buf;
+		}
+
+		buf = next;
+	}
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+int net_pkt_alloc_buffer_debug(struct net_pkt *pkt,
+			       size_t size,
+			       enum net_ip_protocol proto,
+			       k_timeout_t timeout,
+			       const char *caller,
+			       int line)
+#else
+int net_pkt_alloc_buffer(struct net_pkt *pkt,
+			 size_t size,
+			 enum net_ip_protocol proto,
+			 k_timeout_t timeout)
+#endif
+{
+	uint64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf_pool *pool = NULL;
+	size_t alloc_len = 0;
+	size_t hdr_len = 0;
+	struct net_buf *buf;
+
+	if (!size && proto == 0 && net_pkt_family(pkt) == AF_UNSPEC) {
+		return 0;
+	}
+
+	if (k_is_in_isr()) {
+		timeout = K_NO_WAIT;
+	}
+
+	/* Verifying existing buffer and take into account free space there */
+	alloc_len = pkt_get_size(pkt) - net_pkt_get_len(pkt);
+	if (!alloc_len) {
+		/* In case of no free space, it will account for header
+		 * space estimation
+		 */
+		hdr_len = pkt_estimate_headers_length(pkt,
+						      net_pkt_family(pkt),
+						      proto);
+	}
+
+	/* Calculate the maximum that can be allocated depending on size */
+	alloc_len = pkt_buffer_length(pkt, size + hdr_len, proto, alloc_len);
+
+	NET_DBG("Data allocation maximum size %zu (requested %zu)",
+		alloc_len, size);
+
+	if (pkt->context) {
+		pool = get_data_pool(pkt->context);
+	}
+
+	if (!pool) {
+		pool = pkt->slab == &tx_pkts ? &tx_bufs : &rx_bufs;
+	}
+
+	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+	    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+		int64_t remaining = end - z_tick_get();
+
+		if (remaining <= 0) {
+			timeout = K_NO_WAIT;
+		} else {
+			timeout = Z_TIMEOUT_TICKS(remaining);
+		}
+	}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	buf = pkt_alloc_buffer(pool, alloc_len, timeout, caller, line);
+#else
+	buf = pkt_alloc_buffer(pool, alloc_len, timeout);
+#endif
+
+	if (!buf) {
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+		NET_ERR("Data buffer (%zd) allocation failed (%s:%d)",
+			alloc_len, caller, line);
+#else
+		NET_ERR("Data buffer (%zd) allocation failed.", alloc_len);
+#endif
+		return -ENOMEM;
+	}
+
+	net_pkt_append_buffer(pkt, buf);
+
+	return 0;
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, k_timeout_t timeout,
+				 const char *caller, int line)
+#else
+static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, k_timeout_t timeout)
+#endif
+{
+	struct net_pkt *pkt;
+	int ret;
+
+	if (k_is_in_isr()) {
+		timeout = K_NO_WAIT;
+	}
+
+	ret = k_mem_slab_alloc(slab, (void **)&pkt, timeout);
+	if (ret) {
+		return NULL;
+	}
+
+	memset(pkt, 0, sizeof(struct net_pkt));
+
+	pkt->atomic_ref = ATOMIC_INIT(1);
+	pkt->slab = slab;
+
+	if (IS_ENABLED(CONFIG_NET_IPV6)) {
+		net_pkt_set_ipv6_next_hdr(pkt, 255);
+	}
+
+#if IS_ENABLED(CONFIG_NET_TX_DEFAULT_PRIORITY)
+#define TX_DEFAULT_PRIORITY CONFIG_NET_TX_DEFAULT_PRIORITY
+#else
+#define TX_DEFAULT_PRIORITY 0
+#endif
+
+#if IS_ENABLED(CONFIG_NET_RX_DEFAULT_PRIORITY)
+#define RX_DEFAULT_PRIORITY CONFIG_NET_RX_DEFAULT_PRIORITY
+#else
+#define RX_DEFAULT_PRIORITY 0
+#endif
+
+	if (&tx_pkts == slab) {
+		net_pkt_set_priority(pkt, TX_DEFAULT_PRIORITY);
+	} else if (&rx_pkts == slab) {
+		net_pkt_set_priority(pkt, RX_DEFAULT_PRIORITY);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) ||
+	    IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
+		struct net_ptp_time tp = {
+			/* Use the nanosecond field to temporarily
+			 * store the cycle count as it is a 32-bit
+			 * variable. The net_pkt timestamp field is used
+			 * to calculate how long it takes the packet to travel
+			 * between network device driver and application.
+			 */
+			.nanosecond = k_cycle_get_32(),
+		};
+
+		net_pkt_set_timestamp(pkt, &tp);
+	}
+
+	net_pkt_set_vlan_tag(pkt, NET_VLAN_TAG_UNSPEC);
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	net_pkt_alloc_add(pkt, true, caller, line);
+#endif
+
+	net_pkt_cursor_init(pkt);
+
+	return pkt;
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_alloc_debug(k_timeout_t timeout,
+				    const char *caller, int line)
+#else
+struct net_pkt *net_pkt_alloc(k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc(&tx_pkts, timeout, caller, line);
+#else
+	return pkt_alloc(&tx_pkts, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_alloc_from_slab_debug(struct k_mem_slab *slab,
+					      k_timeout_t timeout,
+					      const char *caller, int line)
+#else
+struct net_pkt *net_pkt_alloc_from_slab(struct k_mem_slab *slab,
+					k_timeout_t timeout)
+#endif
+{
+	if (!slab) {
+		return NULL;
+	}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc(slab, timeout, caller, line);
+#else
+	return pkt_alloc(slab, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_rx_alloc_debug(k_timeout_t timeout,
+				       const char *caller, int line)
+#else
+struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc(&rx_pkts, timeout, caller, line);
+#else
+	return pkt_alloc(&rx_pkts, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+static struct net_pkt *pkt_alloc_on_iface(struct k_mem_slab *slab,
+					  struct net_if *iface,
+					  k_timeout_t timeout,
+					  const char *caller, int line)
+#else
+static struct net_pkt *pkt_alloc_on_iface(struct k_mem_slab *slab,
+					  struct net_if *iface,
+					  k_timeout_t timeout)
+
+#endif
+{
+	struct net_pkt *pkt;
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	pkt = pkt_alloc(slab, timeout, caller, line);
+#else
+	pkt = pkt_alloc(slab, timeout);
+#endif
+
+	if (pkt) {
+		net_pkt_set_iface(pkt, iface);
+	}
+
+	return pkt;
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_alloc_on_iface_debug(struct net_if *iface,
+					     k_timeout_t timeout,
+					     const char *caller,
+					     int line)
+#else
+struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface,
+				       k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc_on_iface(&tx_pkts, iface, timeout, caller, line);
+#else
+	return pkt_alloc_on_iface(&tx_pkts, iface, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_rx_alloc_on_iface_debug(struct net_if *iface,
+						k_timeout_t timeout,
+						const char *caller,
+						int line)
+#else
+struct net_pkt *net_pkt_rx_alloc_on_iface(struct net_if *iface,
+					  k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc_on_iface(&rx_pkts, iface, timeout, caller, line);
+#else
+	return pkt_alloc_on_iface(&rx_pkts, iface, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+static struct net_pkt *
+pkt_alloc_with_buffer(struct k_mem_slab *slab,
+		      struct net_if *iface,
+		      size_t size,
+		      sa_family_t family,
+		      enum net_ip_protocol proto,
+		      k_timeout_t timeout,
+		      const char *caller,
+		      int line)
+#else
+static struct net_pkt *
+pkt_alloc_with_buffer(struct k_mem_slab *slab,
+		      struct net_if *iface,
+		      size_t size,
+		      sa_family_t family,
+		      enum net_ip_protocol proto,
+		      k_timeout_t timeout)
+#endif
+{
+	uint64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_pkt *pkt;
+	int ret;
+
+	NET_DBG("On iface %p size %zu", iface, size);
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	pkt = pkt_alloc_on_iface(slab, iface, timeout, caller, line);
+#else
+	pkt = pkt_alloc_on_iface(slab, iface, timeout);
+#endif
+
+	if (!pkt) {
+		return NULL;
+	}
+
+	net_pkt_set_family(pkt, family);
+
+	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+	    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+		int64_t remaining = end - z_tick_get();
+
+		if (remaining <= 0) {
+			timeout = K_NO_WAIT;
+		} else {
+			timeout = Z_TIMEOUT_TICKS(remaining);
+		}
+	}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	ret = net_pkt_alloc_buffer_debug(pkt, size, proto, timeout,
+					 caller, line);
+#else
+	ret = net_pkt_alloc_buffer(pkt, size, proto, timeout);
+#endif
+
+	if (ret) {
+		net_pkt_unref(pkt);
+		return NULL;
+	}
+
+	return pkt;
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_alloc_with_buffer_debug(struct net_if *iface,
+						size_t size,
+						sa_family_t family,
+						enum net_ip_protocol proto,
+						k_timeout_t timeout,
+						const char *caller,
+						int line)
+#else
+struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface,
+					  size_t size,
+					  sa_family_t family,
+					  enum net_ip_protocol proto,
+					  k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc_with_buffer(&tx_pkts, iface, size, family,
+				     proto, timeout, caller, line);
+#else
+	return pkt_alloc_with_buffer(&tx_pkts, iface, size, family,
+				     proto, timeout);
+#endif
+}
+
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+struct net_pkt *net_pkt_rx_alloc_with_buffer_debug(struct net_if *iface,
+						   size_t size,
+						   sa_family_t family,
+						   enum net_ip_protocol proto,
+						   k_timeout_t timeout,
+						   const char *caller,
+						   int line)
+#else
+struct net_pkt *net_pkt_rx_alloc_with_buffer(struct net_if *iface,
+					     size_t size,
+					     sa_family_t family,
+					     enum net_ip_protocol proto,
+					     k_timeout_t timeout)
+#endif
+{
+#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
+	return pkt_alloc_with_buffer(&rx_pkts, iface, size, family,
+					proto, timeout, caller, line);
+#else
+	return pkt_alloc_with_buffer(&rx_pkts, iface, size, family,
+					proto, timeout);
+#endif
+}
+
+void net_pkt_append_buffer(struct net_pkt *pkt, struct net_buf *buffer)
+{
+	if (!pkt->buffer) {
+		pkt->buffer = buffer;
+		net_pkt_cursor_init(pkt);
+	} else {
+		net_buf_frag_insert(net_buf_frag_last(pkt->buffer), buffer);
+	}
+}
+
+void net_pkt_cursor_init(struct net_pkt *pkt)
+{
+	pkt->cursor.buf = pkt->buffer;
+	if (pkt->cursor.buf) {
+		pkt->cursor.pos = pkt->cursor.buf->data;
+	} else {
+		pkt->cursor.pos = NULL;
+	}
+}
+
+static void pkt_cursor_jump(struct net_pkt *pkt, bool write)
+{
+	struct net_pkt_cursor *cursor = &pkt->cursor;
+
+	cursor->buf = cursor->buf->frags;
+	while (cursor->buf) {
+		size_t len = write ? cursor->buf->size : cursor->buf->len;
+
+		if (!len) {
+			cursor->buf = cursor->buf->frags;
+		} else {
+			break;
+		}
+	}
+
+	if (cursor->buf) {
+		cursor->pos = cursor->buf->data;
+	} else {
+		cursor->pos = NULL;
+	}
+}
+
+static void pkt_cursor_advance(struct net_pkt *pkt, bool write)
+{
+	struct net_pkt_cursor *cursor = &pkt->cursor;
+	size_t len;
+
+	if (!cursor->buf) {
+		return;
+	}
+
+	len = write ? cursor->buf->size : cursor->buf->len;
+	if ((cursor->pos - cursor->buf->data) == len) {
+		pkt_cursor_jump(pkt, write);
+	}
+}
+
+static void pkt_cursor_update(struct net_pkt *pkt,
+			      size_t length, bool write)
+{
+	struct net_pkt_cursor *cursor = &pkt->cursor;
+	size_t len;
+
+	if (net_pkt_is_being_overwritten(pkt)) {
+		write = false;
+	}
+
+	len = write ? cursor->buf->size : cursor->buf->len;
+	if (length + (cursor->pos - cursor->buf->data) == len &&
+	    !(net_pkt_is_being_overwritten(pkt) && len < cursor->buf->size)) {
+		pkt_cursor_jump(pkt, write);
+	} else {
+		cursor->pos += length;
+	}
+}
+
+/* Internal function that does all operation (skip/read/write/memset) */
+static int net_pkt_cursor_operate(struct net_pkt *pkt,
+				  void *data, size_t length,
+				  bool copy, bool write)
+{
+	/* We use such variable to avoid lengthy lines */
+	struct net_pkt_cursor *c_op = &pkt->cursor;
+
+	while (c_op->buf && length) {
+		size_t d_len, len;
+
+		pkt_cursor_advance(pkt, net_pkt_is_being_overwritten(pkt) ?
+				   false : write);
+		if (c_op->buf == NULL) {
+			break;
+		}
+
+		if (write && !net_pkt_is_being_overwritten(pkt)) {
+			d_len = c_op->buf->size - (c_op->pos - c_op->buf->data);
+		} else {
+			d_len = c_op->buf->len - (c_op->pos - c_op->buf->data);
+		}
+
+		if (!d_len) {
+			break;
+		}
+
+		if (length < d_len) {
+			len = length;
+		} else {
+			len = d_len;
+		}
+
+		if (copy) {
+			memcpy(write ? c_op->pos : data,
+			       write ? data : c_op->pos,
+			       len);
+		} else if (data) {
+			memset(c_op->pos, *(int *)data, len);
+		}
+
+		if (write && !net_pkt_is_being_overwritten(pkt)) {
+			net_buf_add(c_op->buf, len);
+		}
+
+		pkt_cursor_update(pkt, len, write);
+
+		if (copy && data) {
+			data = (uint8_t *) data + len;
+		}
+
+		length -= len;
+	}
+
+	if (length) {
+		NET_DBG("Still some length to go %zu", length);
+		return -ENOBUFS;
+	}
+
+	return 0;
+}
+
+int net_pkt_skip(struct net_pkt *pkt, size_t skip)
+{
+	NET_DBG("pkt %p skip %zu", pkt, skip);
+
+	return net_pkt_cursor_operate(pkt, NULL, skip, false, true);
+}
+
+int net_pkt_memset(struct net_pkt *pkt, int byte, size_t amount)
+{
+	NET_DBG("pkt %p byte %d amount %zu", pkt, byte, amount);
+
+	return net_pkt_cursor_operate(pkt, &byte, amount, false, true);
+}
+
+int net_pkt_read(struct net_pkt *pkt, void *data, size_t length)
+{
+	NET_DBG("pkt %p data %p length %zu", pkt, data, length);
+
+	return net_pkt_cursor_operate(pkt, data, length, true, false);
+}
+
+int net_pkt_read_be16(struct net_pkt *pkt, uint16_t *data)
+{
+	uint8_t d16[2];
+	int ret;
+
+	ret = net_pkt_read(pkt, d16, sizeof(uint16_t));
+
+	*data = d16[0] << 8 | d16[1];
+
+	return ret;
+}
+
+int net_pkt_read_le16(struct net_pkt *pkt, uint16_t *data)
+{
+	uint8_t d16[2];
+	int ret;
+
+	ret = net_pkt_read(pkt, d16, sizeof(uint16_t));
+
+	*data = d16[1] << 8 | d16[0];
+
+	return ret;
+}
+
+int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data)
+{
+	uint8_t d32[4];
+	int ret;
+
+	ret = net_pkt_read(pkt, d32, sizeof(uint32_t));
+
+	*data = d32[0] << 24 | d32[1] << 16 | d32[2] << 8 | d32[3];
+
+	return ret;
+}
+
+int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length)
+{
+	NET_DBG("pkt %p data %p length %zu", pkt, data, length);
+
+	if (data == pkt->cursor.pos && net_pkt_is_contiguous(pkt, length)) {
+		return net_pkt_skip(pkt, length);
+	}
+
+	return net_pkt_cursor_operate(pkt, (void *)data, length, true, true);
+}
+
+int net_pkt_copy(struct net_pkt *pkt_dst,
+		 struct net_pkt *pkt_src,
+		 size_t length)
+{
+	struct net_pkt_cursor *c_dst = &pkt_dst->cursor;
+	struct net_pkt_cursor *c_src = &pkt_src->cursor;
+
+	while (c_dst->buf && c_src->buf && length) {
+		size_t s_len, d_len, len;
+
+		pkt_cursor_advance(pkt_dst, true);
+		pkt_cursor_advance(pkt_src, false);
+
+		if (!c_dst->buf || !c_src->buf) {
+			break;
+		}
+
+		s_len = c_src->buf->len - (c_src->pos - c_src->buf->data);
+		d_len = c_dst->buf->size - (c_dst->pos - c_dst->buf->data);
+		if (length < s_len && length < d_len) {
+			len = length;
+		} else {
+			if (d_len < s_len) {
+				len = d_len;
+			} else {
+				len = s_len;
+			}
+		}
+
+		if (!len) {
+			break;
+		}
+
+		memcpy(c_dst->pos, c_src->pos, len);
+
+		if (!net_pkt_is_being_overwritten(pkt_dst)) {
+			net_buf_add(c_dst->buf, len);
+		}
+
+		pkt_cursor_update(pkt_dst, len, true);
+		pkt_cursor_update(pkt_src, len, false);
+
+		length -= len;
+	}
+
+	if (length) {
+		NET_DBG("Still some length to go %zu", length);
+		return -ENOBUFS;
+	}
+
+	return 0;
+}
+
+static void clone_pkt_attributes(struct net_pkt *pkt, struct net_pkt *clone_pkt)
+{
+	net_pkt_set_family(clone_pkt, net_pkt_family(pkt));
+	net_pkt_set_context(clone_pkt, net_pkt_context(pkt));
+	net_pkt_set_ip_hdr_len(clone_pkt, net_pkt_ip_hdr_len(pkt));
+	net_pkt_set_vlan_tag(clone_pkt, net_pkt_vlan_tag(pkt));
+	net_pkt_set_timestamp(clone_pkt, net_pkt_timestamp(pkt));
+	net_pkt_set_priority(clone_pkt, net_pkt_priority(pkt));
+	net_pkt_set_orig_iface(clone_pkt, net_pkt_orig_iface(pkt));
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		net_pkt_set_ipv4_ttl(clone_pkt, net_pkt_ipv4_ttl(pkt));
+		net_pkt_set_ipv4_opts_len(clone_pkt,
+					  net_pkt_ipv4_opts_len(pkt));
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		net_pkt_set_ipv6_hop_limit(clone_pkt,
+					   net_pkt_ipv6_hop_limit(pkt));
+		net_pkt_set_ipv6_ext_len(clone_pkt, net_pkt_ipv6_ext_len(pkt));
+		net_pkt_set_ipv6_ext_opt_len(clone_pkt,
+					     net_pkt_ipv6_ext_opt_len(pkt));
+		net_pkt_set_ipv6_hdr_prev(clone_pkt,
+					  net_pkt_ipv6_hdr_prev(pkt));
+		net_pkt_set_ipv6_next_hdr(clone_pkt,
+					  net_pkt_ipv6_next_hdr(pkt));
+	}
+}
+
+struct net_pkt *net_pkt_clone(struct net_pkt *pkt, k_timeout_t timeout)
+{
+	size_t cursor_offset = net_pkt_get_current_offset(pkt);
+	struct net_pkt *clone_pkt;
+	struct net_pkt_cursor backup;
+
+	clone_pkt = net_pkt_alloc_with_buffer(net_pkt_iface(pkt),
+					      net_pkt_get_len(pkt),
+					      AF_UNSPEC, 0, timeout);
+	if (!clone_pkt) {
+		return NULL;
+	}
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_copy(clone_pkt, pkt, net_pkt_get_len(pkt))) {
+		net_pkt_unref(clone_pkt);
+		net_pkt_cursor_restore(pkt, &backup);
+		return NULL;
+	}
+
+	if (clone_pkt->buffer) {
+		/* The link header pointers are only usable if there is
+		 * a buffer that we copied because those pointers point
+		 * to start of the fragment which we do not have right now.
+		 */
+		memcpy(&clone_pkt->lladdr_src, &pkt->lladdr_src,
+		       sizeof(clone_pkt->lladdr_src));
+		memcpy(&clone_pkt->lladdr_dst, &pkt->lladdr_dst,
+		       sizeof(clone_pkt->lladdr_dst));
+	}
+
+	clone_pkt_attributes(pkt, clone_pkt);
+
+	net_pkt_cursor_init(clone_pkt);
+
+	if (cursor_offset) {
+		net_pkt_set_overwrite(clone_pkt, true);
+		net_pkt_skip(clone_pkt, cursor_offset);
+	}
+
+	net_pkt_cursor_restore(pkt, &backup);
+
+	NET_DBG("Cloned %p to %p", pkt, clone_pkt);
+
+	return clone_pkt;
+}
+
+struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, k_timeout_t timeout)
+{
+	struct net_pkt *clone_pkt;
+	struct net_buf *buf;
+
+	clone_pkt = net_pkt_alloc(timeout);
+	if (!clone_pkt) {
+		return NULL;
+	}
+
+	net_pkt_set_iface(clone_pkt, net_pkt_iface(pkt));
+	clone_pkt->buffer = pkt->buffer;
+	buf = pkt->buffer;
+
+	while (buf) {
+		net_pkt_frag_ref(buf);
+		buf = buf->frags;
+	}
+
+	if (pkt->buffer) {
+		/* The link header pointers are only usable if there is
+		 * a buffer that we copied because those pointers point
+		 * to start of the fragment which we do not have right now.
+		 */
+		memcpy(&clone_pkt->lladdr_src, &pkt->lladdr_src,
+		       sizeof(clone_pkt->lladdr_src));
+		memcpy(&clone_pkt->lladdr_dst, &pkt->lladdr_dst,
+		       sizeof(clone_pkt->lladdr_dst));
+	}
+
+	clone_pkt_attributes(pkt, clone_pkt);
+
+	net_pkt_cursor_restore(clone_pkt, &pkt->cursor);
+
+	NET_DBG("Shallow cloned %p to %p", pkt, clone_pkt);
+
+	return clone_pkt;
+}
+
+size_t net_pkt_remaining_data(struct net_pkt *pkt)
+{
+	struct net_buf *buf;
+	size_t data_length;
+
+	if (!pkt || !pkt->cursor.buf || !pkt->cursor.pos) {
+		return 0;
+	}
+
+	buf = pkt->cursor.buf;
+	data_length = buf->len - (pkt->cursor.pos - buf->data);
+
+	buf = buf->frags;
+	while (buf) {
+		data_length += buf->len;
+		buf = buf->frags;
+	}
+
+	return data_length;
+}
+
+int net_pkt_update_length(struct net_pkt *pkt, size_t length)
+{
+	struct net_buf *buf;
+
+	for (buf = pkt->buffer; buf; buf = buf->frags) {
+		if (buf->len < length) {
+			length -= buf->len;
+		} else {
+			buf->len = length;
+			length = 0;
+		}
+	}
+
+	return !length ? 0 : -EINVAL;
+}
+
+int net_pkt_pull(struct net_pkt *pkt, size_t length)
+{
+	struct net_pkt_cursor *c_op = &pkt->cursor;
+
+	while (length) {
+		size_t left, rem;
+
+		pkt_cursor_advance(pkt, false);
+
+		if (!c_op->buf) {
+			break;
+		}
+
+		left = c_op->buf->len - (c_op->pos - c_op->buf->data);
+		if (!left) {
+			break;
+		}
+
+		rem = left;
+		if (rem > length) {
+			rem = length;
+		}
+
+		c_op->buf->len -= rem;
+		left -= rem;
+		if (left) {
+			memmove(c_op->pos, c_op->pos+rem, left);
+		} else {
+			struct net_buf *buf = pkt->buffer;
+
+			if (buf) {
+				pkt->buffer = buf->frags;
+				buf->frags = NULL;
+				net_buf_unref(buf);
+			}
+
+			net_pkt_cursor_init(pkt);
+		}
+
+		length -= rem;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	if (length) {
+		NET_DBG("Still some length to go %zu", length);
+		return -ENOBUFS;
+	}
+
+	return 0;
+}
+
+uint16_t net_pkt_get_current_offset(struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->buffer;
+	uint16_t offset;
+
+	if (!pkt->cursor.buf || !pkt->cursor.pos) {
+		return 0;
+	}
+
+	offset = 0U;
+
+	while (buf != pkt->cursor.buf) {
+		offset += buf->len;
+		buf = buf->frags;
+	}
+
+	offset += pkt->cursor.pos - buf->data;
+
+	return offset;
+}
+
+bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size)
+{
+	pkt_cursor_advance(pkt, !net_pkt_is_being_overwritten(pkt));
+
+	if (pkt->cursor.buf && pkt->cursor.pos) {
+		size_t len;
+
+		len = net_pkt_is_being_overwritten(pkt) ?
+			pkt->cursor.buf->len : pkt->cursor.buf->size;
+		len -= pkt->cursor.pos - pkt->cursor.buf->data;
+		if (len >= size) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void *net_pkt_get_data(struct net_pkt *pkt,
+		       struct net_pkt_data_access *access)
+{
+	if (IS_ENABLED(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)) {
+		if (!net_pkt_is_contiguous(pkt, access->size)) {
+			return NULL;
+		}
+
+		return pkt->cursor.pos;
+	} else {
+		if (net_pkt_is_contiguous(pkt, access->size)) {
+			access->data = pkt->cursor.pos;
+		} else if (net_pkt_is_being_overwritten(pkt)) {
+			struct net_pkt_cursor backup;
+
+			if (!access->data) {
+				NET_ERR("Uncontiguous data"
+					" cannot be linearized");
+				return NULL;
+			}
+
+			net_pkt_cursor_backup(pkt, &backup);
+
+			if (net_pkt_read(pkt, access->data, access->size)) {
+				net_pkt_cursor_restore(pkt, &backup);
+				return NULL;
+			}
+
+			net_pkt_cursor_restore(pkt, &backup);
+		}
+
+		return access->data;
+	}
+
+	return NULL;
+}
+
+int net_pkt_set_data(struct net_pkt *pkt,
+		     struct net_pkt_data_access *access)
+{
+	if (IS_ENABLED(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS)) {
+		return net_pkt_skip(pkt, access->size);
+	}
+
+	return net_pkt_write(pkt, access->data, access->size);
+}
+
+void net_pkt_init(void)
+{
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("Allocating %u RX (%zu bytes), %u TX (%zu bytes), "
+		"%d RX data (%u bytes) and %d TX data (%u bytes) buffers",
+		k_mem_slab_num_free_get(&rx_pkts),
+		(size_t)(k_mem_slab_num_free_get(&rx_pkts) *
+			 sizeof(struct net_pkt)),
+		k_mem_slab_num_free_get(&tx_pkts),
+		(size_t)(k_mem_slab_num_free_get(&tx_pkts) *
+			 sizeof(struct net_pkt)),
+		get_frees(&rx_bufs), get_size(&rx_bufs),
+		get_frees(&tx_bufs), get_size(&tx_bufs));
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_private.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_private.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_private.h	(working copy)
@@ -0,0 +1,274 @@
+/** @file
+ @brief Network stack private header
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <sys/printk.h>
+#include <net/net_context.h>
+#include <net/net_pkt.h>
+
+#ifdef CONFIG_NET_MGMT_EVENT_INFO
+
+#include <net/net_event.h>
+
+/* Maximum size of "struct net_event_ipv6_addr" or
+ * "struct net_event_ipv6_nbr" or "struct net_event_ipv6_route".
+ * NOTE: Update comments here and calculate which struct occupies max size.
+ */
+
+#ifdef CONFIG_NET_L2_WIFI_MGMT
+
+#include <net/wifi_mgmt.h>
+#define NET_EVENT_INFO_MAX_SIZE sizeof(struct wifi_scan_result)
+
+#else
+
+#if defined(CONFIG_NET_DHCPV4)
+#define NET_EVENT_INFO_MAX_SIZE sizeof(struct net_if_dhcpv4)
+#else
+#define NET_EVENT_INFO_MAX_SIZE sizeof(struct net_event_ipv6_route)
+#endif
+
+#endif /* CONFIG_NET_L2_WIFI_MGMT */
+#endif /* CONFIG_NET_MGMT_EVENT_INFO */
+
+#include "connection.h"
+
+extern void net_if_init(void);
+extern void net_if_post_init(void);
+extern void net_if_carrier_down(struct net_if *iface);
+extern void net_if_stats_reset(struct net_if *iface);
+extern void net_if_stats_reset_all(void);
+
+#if defined(CONFIG_NET_NATIVE) || defined(CONFIG_NET_OFFLOAD)
+extern void net_context_init(void);
+extern const char *net_context_state(struct net_context *context);
+extern void net_pkt_init(void);
+extern void net_tc_tx_init(void);
+extern void net_tc_rx_init(void);
+#else
+static inline void net_context_init(void) { }
+static inline void net_pkt_init(void) { }
+static inline void net_tc_tx_init(void) { }
+static inline void net_tc_rx_init(void) { }
+static inline const char *net_context_state(struct net_context *context)
+{
+	ARG_UNUSED(context);
+	return NULL;
+}
+#endif
+
+#if defined(CONFIG_NET_NATIVE)
+enum net_verdict net_ipv4_input(struct net_pkt *pkt);
+enum net_verdict net_ipv6_input(struct net_pkt *pkt, bool is_loopback);
+#else
+static inline enum net_verdict net_ipv4_input(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return NET_CONTINUE;
+}
+
+static inline enum net_verdict net_ipv6_input(struct net_pkt *pkt,
+					      bool is_loopback)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(is_loopback);
+
+	return NET_CONTINUE;
+}
+#endif
+extern bool net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt);
+extern void net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt);
+extern enum net_verdict net_promisc_mode_input(struct net_pkt *pkt);
+
+char *net_sprint_addr(sa_family_t af, const void *addr);
+
+#define net_sprint_ipv4_addr(_addr) net_sprint_addr(AF_INET, _addr)
+
+#define net_sprint_ipv6_addr(_addr) net_sprint_addr(AF_INET6, _addr)
+
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+int net_context_get_timestamp(struct net_context *context,
+			      struct net_pkt *pkt,
+			      struct net_ptp_time *timestamp);
+#else
+static inline int net_context_get_timestamp(struct net_context *context,
+					    struct net_pkt *pkt,
+					    struct net_ptp_time *timestamp)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(timestamp);
+
+	return -ENOTSUP;
+}
+#endif
+
+#if defined(CONFIG_COAP)
+/**
+ * @brief CoAP init function declaration. It belongs here because we don't want
+ * to expose it as a public API -- it should only be called once, and only by
+ * net_core.
+ */
+extern void net_coap_init(void);
+#else
+static inline void net_coap_init(void)
+{
+	return;
+}
+#endif
+
+
+
+#if defined(CONFIG_NET_GPTP)
+/**
+ * @brief Initialize Precision Time Protocol Layer.
+ */
+void net_gptp_init(void);
+
+/**
+ * @brief Process a ptp message.
+ *
+ * @param buf Buffer with a valid PTP Ethernet type.
+ *
+ * @return Return the policy for network buffer.
+ */
+enum net_verdict net_gptp_recv(struct net_if *iface, struct net_pkt *pkt);
+#else
+#define net_gptp_init()
+#define net_gptp_recv(iface, pkt) NET_DROP
+#endif /* CONFIG_NET_GPTP */
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_pkt *pkt,
+				 uint16_t pkt_len);
+#endif
+
+extern const char *net_proto2str(int family, int proto);
+extern char *net_byte_to_hex(char *ptr, uint8_t byte, char base, bool pad);
+extern char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
+				    char *buf, int buflen);
+extern uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto);
+
+/**
+ * @brief Deliver the incoming packet through the recv_cb of the net_context
+ *        to the upper layers
+ *
+ * @param conn		Network connection
+ * @param pkt		Network packet
+ * @param ip_hdr	Pointer to IP header, optional
+ * @param proto_hdr	Pointer to transport layer protocol header, optional
+ * @param user_data	User data passed as an argument
+ *
+ * @return NET_OK	if the packet is consumed through the recv_cb
+ *         NET_DROP	if the recv_cb isn't set
+ */
+enum net_verdict net_context_packet_received(struct net_conn *conn,
+					     struct net_pkt *pkt,
+					     union net_ip_header *ip_hdr,
+					     union net_proto_header *proto_hdr,
+					     void *user_data);
+
+#if defined(CONFIG_NET_IPV4)
+extern uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt);
+#endif /* CONFIG_NET_IPV4 */
+
+static inline uint16_t net_calc_chksum_icmpv6(struct net_pkt *pkt)
+{
+	return net_calc_chksum(pkt, IPPROTO_ICMPV6);
+}
+
+static inline uint16_t net_calc_chksum_icmpv4(struct net_pkt *pkt)
+{
+	return net_calc_chksum(pkt, IPPROTO_ICMP);
+}
+
+static inline uint16_t net_calc_chksum_udp(struct net_pkt *pkt)
+{
+	uint16_t chksum = net_calc_chksum(pkt, IPPROTO_UDP);
+
+	return chksum == 0U ? 0xffff : chksum;
+}
+
+static inline uint16_t net_calc_verify_chksum_udp(struct net_pkt *pkt)
+{
+	return net_calc_chksum(pkt, IPPROTO_UDP);
+}
+
+static inline uint16_t net_calc_chksum_tcp(struct net_pkt *pkt)
+{
+	return net_calc_chksum(pkt, IPPROTO_TCP);
+}
+
+static inline char *net_sprint_ll_addr(const uint8_t *ll, uint8_t ll_len)
+{
+	static char buf[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+
+	return net_sprint_ll_addr_buf(ll, ll_len, (char *)buf, sizeof(buf));
+}
+
+static inline void net_hexdump(const char *str,
+			       const uint8_t *packet, size_t length)
+{
+	if (!length) {
+		LOG_DBG("%s zero-length packet", str);
+		return;
+	}
+
+	LOG_HEXDUMP_DBG(packet, length, str);
+}
+
+
+/* Hexdump from all fragments */
+static inline void net_pkt_hexdump(struct net_pkt *pkt, const char *str)
+{
+	struct net_buf *buf = pkt->buffer;
+	char pkt_str[sizeof("0x") + sizeof(intptr_t) * 2];
+
+	if (str && str[0]) {
+		LOG_DBG("%s", str);
+	}
+
+	snprintk(pkt_str, sizeof(pkt_str), "%p", pkt);
+
+	while (buf) {
+		LOG_HEXDUMP_DBG(buf->data, buf->len, log_strdup(pkt_str));
+		buf = buf->frags;
+	}
+}
+
+static inline void net_pkt_print_buffer_info(struct net_pkt *pkt, const char *str)
+{
+	struct net_buf *buf = pkt->buffer;
+
+	if (str) {
+		printk("%s", str);
+	}
+
+	printk("%p[%d]", pkt, atomic_get(&pkt->atomic_ref));
+
+	if (buf) {
+		printk("->");
+	}
+
+	while (buf) {
+		printk("%p[%d/%u (%u)]",
+		       buf, atomic_get(&pkt->atomic_ref), buf->len, buf->size);
+
+		buf = buf->frags;
+		if (buf) {
+			printk("->");
+		}
+	}
+
+	printk("\n");
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.h	(working copy)
@@ -0,0 +1,25 @@
+/** @file
+ * @brief Network shell handler
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __NET_SHELL_H
+#define __NET_SHELL_H
+
+#if defined(CONFIG_NET_SHELL)
+extern int net_shell_init(void);
+#else
+static inline int net_shell_init(void)
+{
+	return 0;
+}
+#endif
+
+#endif /* __NET_SHELL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_shell.c	(working copy)
@@ -0,0 +1,5224 @@
+/** @file
+ * @brief Network shell module
+ *
+ * Provide some networking shell commands that can be useful to applications.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_shell, LOG_LEVEL_DBG);
+
+#include <zephyr.h>
+#include <kernel_internal.h>
+#include <random/rand32.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <shell/shell.h>
+#include <shell/shell_uart.h>
+
+#include <net/net_if.h>
+#include <net/dns_resolve.h>
+#include <net/ppp.h>
+#include <net/net_stats.h>
+#include <sys/printk.h>
+
+#include "route.h"
+#include "icmpv6.h"
+#include "icmpv4.h"
+#include "connection.h"
+
+#if defined(CONFIG_NET_TCP)
+#include "tcp_internal.h"
+#endif
+
+#include "ipv6.h"
+
+#if defined(CONFIG_NET_ARP)
+#include "ethernet/arp.h"
+#endif
+
+#if defined(CONFIG_NET_L2_ETHERNET)
+#include <net/ethernet.h>
+#endif
+
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+#include <net/ethernet_mgmt.h>
+#endif
+
+#if defined(CONFIG_NET_GPTP)
+#include <net/gptp.h>
+#include "ethernet/gptp/gptp_messages.h"
+#include "ethernet/gptp/gptp_md.h"
+#include "ethernet/gptp/gptp_state.h"
+#include "ethernet/gptp/gptp_data_set.h"
+#include "ethernet/gptp/gptp_private.h"
+#endif
+
+#if defined(CONFIG_NET_L2_PPP)
+#include <net/ppp.h>
+#include "ppp/ppp_internal.h"
+#endif
+
+#include "net_shell.h"
+#include "net_stats.h"
+
+#include <sys/fdtable.h>
+#include "websocket/websocket_internal.h"
+
+#define PR(fmt, ...)						\
+	shell_fprintf(shell, SHELL_NORMAL, fmt, ##__VA_ARGS__)
+
+#define PR_SHELL(shell, fmt, ...)				\
+	shell_fprintf(shell, SHELL_NORMAL, fmt, ##__VA_ARGS__)
+
+#define PR_ERROR(fmt, ...)					\
+	shell_fprintf(shell, SHELL_ERROR, fmt, ##__VA_ARGS__)
+
+#define PR_INFO(fmt, ...)					\
+	shell_fprintf(shell, SHELL_INFO, fmt, ##__VA_ARGS__)
+
+#define PR_WARNING(fmt, ...)					\
+	shell_fprintf(shell, SHELL_WARNING, fmt, ##__VA_ARGS__)
+
+#include "net_private.h"
+
+struct net_shell_user_data {
+	const struct shell *shell;
+	void *user_data;
+};
+
+static inline const char *addrtype2str(enum net_addr_type addr_type)
+{
+	switch (addr_type) {
+	case NET_ADDR_ANY:
+		return "<unknown type>";
+	case NET_ADDR_AUTOCONF:
+		return "autoconf";
+	case NET_ADDR_DHCP:
+		return "DHCP";
+	case NET_ADDR_MANUAL:
+		return "manual";
+	case NET_ADDR_OVERRIDABLE:
+		return "overridable";
+	}
+
+	return "<invalid type>";
+}
+
+static inline const char *addrstate2str(enum net_addr_state addr_state)
+{
+	switch (addr_state) {
+	case NET_ADDR_ANY_STATE:
+		return "<unknown state>";
+	case NET_ADDR_TENTATIVE:
+		return "tentative";
+	case NET_ADDR_PREFERRED:
+		return "preferred";
+	case NET_ADDR_DEPRECATED:
+		return "deprecated";
+	}
+
+	return "<invalid state>";
+}
+
+static const char *iface2str(struct net_if *iface, const char **extra)
+{
+#ifdef CONFIG_NET_L2_IEEE802154
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) {
+		if (extra) {
+			*extra = "=============";
+		}
+
+		return "IEEE 802.15.4";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_ETHERNET
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+		if (extra) {
+			*extra = "========";
+		}
+
+		return "Ethernet";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_PPP
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
+		if (extra) {
+			*extra = "===";
+		}
+
+		return "PPP";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_DUMMY
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
+		if (extra) {
+			*extra = "=====";
+		}
+
+		return "Dummy";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_OPENTHREAD
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) {
+		if (extra) {
+			*extra = "==========";
+		}
+
+		return "OpenThread";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_BT
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) {
+		if (extra) {
+			*extra = "=========";
+		}
+
+		return "Bluetooth";
+	}
+#endif
+
+#ifdef CONFIG_NET_OFFLOAD
+	if (net_if_is_ip_offloaded(iface)) {
+		if (extra) {
+			*extra = "==========";
+		}
+
+		return "IP Offload";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_CANBUS
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS)) {
+		if (extra) {
+			*extra = "======";
+		}
+
+		return "CANBUS";
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_CANBUS_RAW
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) {
+		if (extra) {
+			*extra = "==========";
+		}
+
+		return "CANBUS_RAW";
+	}
+#endif
+
+	if (extra) {
+		*extra = "==============";
+	}
+
+	return "<unknown type>";
+}
+
+#if defined(CONFIG_NET_L2_ETHERNET) && defined(CONFIG_NET_NATIVE)
+struct ethernet_capabilities {
+	enum ethernet_hw_caps capability;
+	const char * const description;
+};
+
+#define EC(cap, desc) { .capability = cap, .description = desc }
+
+static struct ethernet_capabilities eth_hw_caps[] = {
+	EC(ETHERNET_HW_TX_CHKSUM_OFFLOAD, "TX checksum offload"),
+	EC(ETHERNET_HW_RX_CHKSUM_OFFLOAD, "RX checksum offload"),
+	EC(ETHERNET_HW_VLAN,              "Virtual LAN"),
+	EC(ETHERNET_HW_VLAN_TAG_STRIP,    "VLAN Tag stripping"),
+	EC(ETHERNET_AUTO_NEGOTIATION_SET, "Auto negotiation"),
+	EC(ETHERNET_LINK_10BASE_T,        "10 Mbits"),
+	EC(ETHERNET_LINK_100BASE_T,       "100 Mbits"),
+	EC(ETHERNET_LINK_1000BASE_T,      "1 Gbits"),
+	EC(ETHERNET_DUPLEX_SET,           "Half/full duplex"),
+	EC(ETHERNET_PTP,                  "IEEE 802.1AS gPTP clock"),
+	EC(ETHERNET_QAV,                  "IEEE 802.1Qav (credit shaping)"),
+	EC(ETHERNET_PROMISC_MODE,         "Promiscuous mode"),
+	EC(ETHERNET_PRIORITY_QUEUES,      "Priority queues"),
+	EC(ETHERNET_HW_FILTERING,         "MAC address filtering"),
+};
+
+static void print_supported_ethernet_capabilities(
+	const struct shell *shell, struct net_if *iface)
+{
+	enum ethernet_hw_caps caps = net_eth_get_hw_capabilities(iface);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(eth_hw_caps); i++) {
+		if (caps & eth_hw_caps[i].capability) {
+			PR("\t%s\n", eth_hw_caps[i].description);
+		}
+	}
+}
+#endif /* CONFIG_NET_L2_ETHERNET */
+
+static void iface_cb(struct net_if *iface, void *user_data)
+{
+#if defined(CONFIG_NET_NATIVE)
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+
+#if defined(CONFIG_NET_IPV6)
+	struct net_if_ipv6_prefix *prefix;
+	struct net_if_router *router;
+	struct net_if_ipv6 *ipv6;
+#endif
+#if defined(CONFIG_NET_IPV4)
+	struct net_if_ipv4 *ipv4;
+#endif
+#if defined(CONFIG_NET_VLAN)
+	struct ethernet_context *eth_ctx;
+#endif
+#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
+	struct net_if_addr *unicast;
+	struct net_if_mcast_addr *mcast;
+#endif
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+	struct ethernet_req_params params;
+	int ret;
+#endif
+	const char *extra;
+#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_IPV6)
+	int i, count;
+#endif
+
+	if (data->user_data && data->user_data != iface) {
+		return;
+	}
+
+	PR("\nInterface %p (%s) [%d]\n", iface, iface2str(iface, &extra),
+	   net_if_get_by_iface(iface));
+	PR("===========================%s\n", extra);
+
+	if (!net_if_is_up(iface)) {
+		PR_INFO("Interface is down.\n");
+		return;
+	}
+
+#ifdef CONFIG_NET_POWER_MANAGEMENT
+	if (net_if_is_suspended(iface)) {
+		PR_INFO("Interface is suspended, thus not able to tx/rx.\n");
+	}
+#endif
+
+	if (net_if_get_link_addr(iface) &&
+	    net_if_get_link_addr(iface)->addr) {
+		PR("Link addr : %s\n",
+		   net_sprint_ll_addr(net_if_get_link_addr(iface)->addr,
+				      net_if_get_link_addr(iface)->len));
+	}
+
+	PR("MTU       : %d\n", net_if_get_mtu(iface));
+
+#if defined(CONFIG_NET_L2_ETHERNET_MGMT)
+	count = 0;
+	ret = net_mgmt(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
+		       iface,
+		       &params, sizeof(struct ethernet_req_params));
+
+	if (!ret && params.priority_queues_num) {
+		count = params.priority_queues_num;
+		PR("Priority queues:\n");
+		for (i = 0; i < count; ++i) {
+			params.qav_param.queue_id = i;
+			params.qav_param.type = ETHERNET_QAV_PARAM_TYPE_STATUS;
+			ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QAV_PARAM,
+				       iface,
+				       &params,
+				       sizeof(struct ethernet_req_params));
+
+			PR("\t%d: Qav ", i);
+			if (ret) {
+				PR("not supported\n");
+			} else {
+				PR("%s\n",
+				   params.qav_param.enabled ?
+				       "enabled" :
+				       "disabled");
+			}
+		}
+	}
+#endif
+
+#if defined(CONFIG_NET_PROMISCUOUS_MODE)
+	PR("Promiscuous mode : %s\n",
+	   net_if_is_promisc(iface) ? "enabled" : "disabled");
+#endif
+
+#if defined(CONFIG_NET_VLAN)
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+		eth_ctx = net_if_l2_data(iface);
+
+		if (eth_ctx->vlan_enabled) {
+			for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+				if (eth_ctx->vlan[i].iface != iface ||
+				    eth_ctx->vlan[i].tag ==
+							NET_VLAN_TAG_UNSPEC) {
+					continue;
+				}
+
+				PR("VLAN tag  : %d (0x%x)\n",
+				   eth_ctx->vlan[i].tag,
+				   eth_ctx->vlan[i].tag);
+			}
+		} else {
+			PR("VLAN not enabled\n");
+		}
+	}
+#endif
+
+#ifdef CONFIG_NET_L2_ETHERNET
+	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+		PR("Ethernet capabilities supported:\n");
+		print_supported_ethernet_capabilities(shell, iface);
+	}
+#endif /* CONFIG_NET_L2_ETHERNET */
+
+#if defined(CONFIG_NET_IPV6)
+	count = 0;
+
+	ipv6 = iface->config.ip.ipv6;
+
+	PR("IPv6 unicast addresses (max %d):\n", NET_IF_MAX_IPV6_ADDR);
+	for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_ADDR; i++) {
+		unicast = &ipv6->unicast[i];
+
+		if (!unicast->is_used) {
+			continue;
+		}
+
+		PR("\t%s %s %s%s%s\n",
+		   net_sprint_ipv6_addr(&unicast->address.in6_addr),
+		   addrtype2str(unicast->addr_type),
+		   addrstate2str(unicast->addr_state),
+		   unicast->is_infinite ? " infinite" : "",
+		   unicast->is_mesh_local ? " meshlocal" : "");
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+
+	count = 0;
+
+	PR("IPv6 multicast addresses (max %d):\n", NET_IF_MAX_IPV6_MADDR);
+	for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_MADDR; i++) {
+		mcast = &ipv6->mcast[i];
+
+		if (!mcast->is_used) {
+			continue;
+		}
+
+		PR("\t%s\n", net_sprint_ipv6_addr(&mcast->address.in6_addr));
+
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+
+	count = 0;
+
+	PR("IPv6 prefixes (max %d):\n", NET_IF_MAX_IPV6_PREFIX);
+	for (i = 0; ipv6 && i < NET_IF_MAX_IPV6_PREFIX; i++) {
+		prefix = &ipv6->prefix[i];
+
+		if (!prefix->is_used) {
+			continue;
+		}
+
+		PR("\t%s/%d%s\n",
+		   net_sprint_ipv6_addr(&prefix->prefix),
+		   prefix->len, prefix->is_infinite ? " infinite" : "");
+
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+
+	router = net_if_ipv6_router_find_default(iface, NULL);
+	if (router) {
+		PR("IPv6 default router :\n");
+		PR("\t%s%s\n",
+		   net_sprint_ipv6_addr(&router->address.in6_addr),
+		   router->is_infinite ? " infinite" : "");
+	}
+
+	if (ipv6) {
+		PR("IPv6 hop limit           : %d\n",
+		   ipv6->hop_limit);
+		PR("IPv6 base reachable time : %d\n",
+		   ipv6->base_reachable_time);
+		PR("IPv6 reachable time      : %d\n",
+		   ipv6->reachable_time);
+		PR("IPv6 retransmit timer    : %d\n",
+		   ipv6->retrans_timer);
+	}
+
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+	/* No need to print IPv4 information for interface that does not
+	 * support that protocol.
+	 */
+	if (
+#if defined(CONFIG_NET_L2_IEEE802154)
+		(net_if_l2(iface) == &NET_L2_GET_NAME(IEEE802154)) ||
+#endif
+#if defined(CONFIG_NET_L2_BT)
+		 (net_if_l2(iface) == &NET_L2_GET_NAME(BLUETOOTH)) ||
+#endif
+		 0) {
+		PR_WARNING("IPv4 not supported for this interface.\n");
+		return;
+	}
+
+	count = 0;
+
+	ipv4 = iface->config.ip.ipv4;
+
+	PR("IPv4 unicast addresses (max %d):\n", NET_IF_MAX_IPV4_ADDR);
+	for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_ADDR; i++) {
+		unicast = &ipv4->unicast[i];
+
+		if (!unicast->is_used) {
+			continue;
+		}
+
+		PR("\t%s %s %s%s\n",
+		   net_sprint_ipv4_addr(&unicast->address.in_addr),
+		   addrtype2str(unicast->addr_type),
+		   addrstate2str(unicast->addr_state),
+		   unicast->is_infinite ? " infinite" : "");
+
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+
+	count = 0;
+
+	PR("IPv4 multicast addresses (max %d):\n", NET_IF_MAX_IPV4_MADDR);
+	for (i = 0; ipv4 && i < NET_IF_MAX_IPV4_MADDR; i++) {
+		mcast = &ipv4->mcast[i];
+
+		if (!mcast->is_used) {
+			continue;
+		}
+
+		PR("\t%s\n", net_sprint_ipv4_addr(&mcast->address.in_addr));
+
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+
+	if (ipv4) {
+		PR("IPv4 gateway : %s\n",
+		   net_sprint_ipv4_addr(&ipv4->gw));
+		PR("IPv4 netmask : %s\n",
+		   net_sprint_ipv4_addr(&ipv4->netmask));
+	}
+#endif /* CONFIG_NET_IPV4 */
+
+#if defined(CONFIG_NET_DHCPV4)
+	PR("DHCPv4 lease time : %u\n",
+	   iface->config.dhcpv4.lease_time);
+	PR("DHCPv4 renew time : %u\n",
+	   iface->config.dhcpv4.renewal_time);
+	PR("DHCPv4 server     : %s\n",
+	   net_sprint_ipv4_addr(&iface->config.dhcpv4.server_id));
+	PR("DHCPv4 requested  : %s\n",
+	   net_sprint_ipv4_addr(&iface->config.dhcpv4.requested_ip));
+	PR("DHCPv4 state      : %s\n",
+	   net_dhcpv4_state_name(iface->config.dhcpv4.state));
+	PR("DHCPv4 attempts   : %d\n",
+	   iface->config.dhcpv4.attempts);
+#endif /* CONFIG_NET_DHCPV4 */
+
+#else
+	ARG_UNUSED(iface);
+	ARG_UNUSED(user_data);
+
+#endif /* CONFIG_NET_NATIVE */
+}
+
+#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE)
+static void route_cb(struct net_route_entry *entry, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	struct net_if *iface = data->user_data;
+	struct net_route_nexthop *nexthop_route;
+	int count;
+
+	if (entry->iface != iface) {
+		return;
+	}
+
+	PR("IPv6 prefix : %s/%d\n", net_sprint_ipv6_addr(&entry->addr),
+	   entry->prefix_len);
+
+	count = 0;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&entry->nexthop, nexthop_route, node) {
+		struct net_linkaddr_storage *lladdr;
+
+		if (!nexthop_route->nbr) {
+			continue;
+		}
+
+		PR("\tneighbor : %p\t", nexthop_route->nbr);
+
+		if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
+			PR("addr : <unknown>\n");
+		} else {
+			lladdr = net_nbr_get_lladdr(nexthop_route->nbr->idx);
+
+			PR("addr : %s\n", net_sprint_ll_addr(lladdr->addr,
+							     lladdr->len));
+		}
+
+		count++;
+	}
+
+	if (count == 0) {
+		PR("\t<none>\n");
+	}
+}
+
+static void iface_per_route_cb(struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	const char *extra;
+
+	PR("\nIPv6 routes for interface %p (%s)\n", iface,
+	   iface2str(iface, &extra));
+	PR("=======================================%s\n", extra);
+
+	data->user_data = iface;
+
+	net_route_foreach(route_cb, data);
+}
+#endif /* CONFIG_NET_ROUTE */
+
+#if defined(CONFIG_NET_ROUTE_MCAST) && defined(CONFIG_NET_NATIVE)
+static void route_mcast_cb(struct net_route_entry_mcast *entry,
+			   void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	struct net_if *iface = data->user_data;
+	const char *extra;
+
+	if (entry->iface != iface) {
+		return;
+	}
+
+	PR("IPv6 multicast route %p for interface %p (%s)\n", entry,
+	   iface, iface2str(iface, &extra));
+	PR("==========================================================="
+	   "%s\n", extra);
+
+	PR("IPv6 group     : %s\n", net_sprint_ipv6_addr(&entry->group));
+	PR("IPv6 group len : %d\n", entry->prefix_len);
+	PR("Lifetime       : %u\n", entry->lifetime);
+}
+
+static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+
+	data->user_data = iface;
+
+	net_route_mcast_foreach(route_mcast_cb, NULL, data);
+}
+#endif /* CONFIG_NET_ROUTE_MCAST */
+
+#if defined(CONFIG_NET_STATISTICS)
+
+#if NET_TC_COUNT > 1
+static const char *priority2str(enum net_priority priority)
+{
+	switch (priority) {
+	case NET_PRIORITY_BK:
+		return "BK"; /* Background */
+	case NET_PRIORITY_BE:
+		return "BE"; /* Best effort */
+	case NET_PRIORITY_EE:
+		return "EE"; /* Excellent effort */
+	case NET_PRIORITY_CA:
+		return "CA"; /* Critical applications */
+	case NET_PRIORITY_VI:
+		return "VI"; /* Video, < 100 ms latency and jitter */
+	case NET_PRIORITY_VO:
+		return "VO"; /* Voice, < 10 ms latency and jitter  */
+	case NET_PRIORITY_IC:
+		return "IC"; /* Internetwork control */
+	case NET_PRIORITY_NC:
+		return "NC"; /* Network control */
+	}
+
+	return "??";
+}
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
+					defined(CONFIG_NET_STATISTICS_USER_API)
+static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data,
+			    const struct shell *shell)
+{
+	PR("Statistics for Ethernet interface %p [%d]\n", iface,
+	       net_if_get_by_iface(iface));
+
+	PR("Bytes received   : %u\n", data->bytes.received);
+	PR("Bytes sent       : %u\n", data->bytes.sent);
+	PR("Packets received : %u\n", data->pkts.rx);
+	PR("Packets sent     : %u\n", data->pkts.tx);
+	PR("Bcast received   : %u\n", data->broadcast.rx);
+	PR("Bcast sent       : %u\n", data->broadcast.tx);
+	PR("Mcast received   : %u\n", data->multicast.rx);
+	PR("Mcast sent       : %u\n", data->multicast.tx);
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET_VENDOR)
+	if (data->vendor) {
+		PR("Vendor specific statistics for Ethernet "
+		   "interface %p [%d]:\n",
+			iface, net_if_get_by_iface(iface));
+		size_t i = 0;
+
+		do {
+			PR("%s : %u\n", data->vendor[i].key,
+			   data->vendor[i].value);
+			i++;
+		} while (data->vendor[i].key);
+	}
+#endif /* CONFIG_NET_STATISTICS_ETHERNET_VENDOR */
+}
+#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
+
+#if defined(CONFIG_NET_STATISTICS_PPP) && \
+					defined(CONFIG_NET_STATISTICS_USER_API)
+static void print_ppp_stats(struct net_if *iface, struct net_stats_ppp *data,
+			    const struct shell *shell)
+{
+	PR("Frames recv    %u\n", data->pkts.rx);
+	PR("Frames sent    %u\n", data->pkts.tx);
+	PR("Frames dropped %u\n", data->drop);
+	PR("Bad FCS        %u\n", data->chkerr);
+}
+#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
+
+#if !defined(CONFIG_NET_NATIVE)
+#define GET_STAT(a, b) 0
+#endif
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \
+	defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
+static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
+					  bool is_tx)
+{
+	static char extra_stats[sizeof("\t[0=xxxx us]") +
+				sizeof("->xxxx") *
+				NET_PKT_DETAIL_STATS_COUNT];
+	int j, total = 0, pos = 0;
+
+	pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
+
+	for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
+		net_stats_t count = 0;
+		uint32_t avg;
+
+		if (is_tx) {
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
+			count = GET_STAT(iface,
+					 tc.sent[i].tx_time_detail[j].count);
+#endif
+		} else {
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
+			count = GET_STAT(iface,
+					 tc.recv[i].rx_time_detail[j].count);
+#endif
+		}
+
+		if (count == 0) {
+			break;
+		}
+
+		if (is_tx) {
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) && (NET_TC_TX_COUNT > 1)
+			avg = (uint32_t)(GET_STAT(iface,
+					   tc.sent[i].tx_time_detail[j].sum) /
+				      (uint64_t)count);
+#endif
+		} else {
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) && (NET_TC_RX_COUNT > 1)
+			avg = (uint32_t)(GET_STAT(iface,
+					   tc.recv[i].rx_time_detail[j].sum) /
+				      (uint64_t)count);
+#endif
+		}
+
+		if (avg == 0) {
+			continue;
+		}
+
+		total += avg;
+
+		pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
+				"->%u", avg);
+	}
+
+	if (total == 0U) {
+		return "\0";
+	}
+
+	pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
+				"=%u us]", total);
+
+	return extra_stats;
+}
+#endif /* (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1) */
+
+#if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1)
+static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
+{
+	static char extra_stats[sizeof("\t[0=xxxx us]") + sizeof("->xxxx") *
+				NET_PKT_DETAIL_STATS_COUNT];
+	int j, total = 0, pos = 0;
+
+	pos += snprintk(extra_stats, sizeof(extra_stats), "\t[0");
+
+	for (j = 0; j < NET_PKT_DETAIL_STATS_COUNT; j++) {
+		net_stats_t count;
+		uint32_t avg;
+
+		if (is_tx) {
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+			count = GET_STAT(iface, tx_time_detail[j].count);
+#endif
+		} else {
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+			count = GET_STAT(iface, rx_time_detail[j].count);
+#endif
+		}
+
+		if (count == 0) {
+			break;
+		}
+
+		if (is_tx) {
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+			avg = (uint32_t)(GET_STAT(iface,
+					       tx_time_detail[j].sum) /
+				      (uint64_t)count);
+#endif
+		} else {
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+			avg = (uint32_t)(GET_STAT(iface,
+					       rx_time_detail[j].sum) /
+				      (uint64_t)count);
+#endif
+		}
+
+		if (avg == 0) {
+			continue;
+		}
+
+		total += avg;
+
+		pos += snprintk(extra_stats + pos,
+				sizeof(extra_stats) - pos,
+				"->%u", avg);
+	}
+
+	if (total == 0U) {
+		return "\0";
+	}
+
+	pos += snprintk(extra_stats + pos, sizeof(extra_stats) - pos,
+			"=%u us]", total);
+
+	return extra_stats;
+}
+#endif /* (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1) */
+
+#else /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
+	 CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS) || \
+	defined(CONFIG_NET_PKT_RXTIME_STATS) || \
+	defined(CONFIG_NET_CONTEXT_TIMESTAMP)
+
+#if (NET_TC_TX_COUNT > 1) || (NET_TC_RX_COUNT > 1)
+static char *get_net_pkt_tc_stats_detail(struct net_if *iface, int i,
+					 bool is_tx)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(i);
+	ARG_UNUSED(is_tx);
+
+	return "\0";
+}
+#endif
+
+#if (NET_TC_TX_COUNT == 1) || (NET_TC_RX_COUNT == 1)
+static char *get_net_pkt_stats_detail(struct net_if *iface, bool is_tx)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(is_tx);
+
+	return "\0";
+}
+#endif
+#endif /* CONFIG_NET_PKT_TXTIME_STATS) || CONFIG_NET_PKT_RXTIME_STATS ||
+	  CONFIG_NET_CONTEXT_TIMESTAMP */
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL ||
+	  CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+static void print_tc_tx_stats(const struct shell *shell, struct net_if *iface)
+{
+#if NET_TC_TX_COUNT > 1
+	int i;
+
+	PR("TX traffic class statistics:\n");
+
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
+				defined(CONFIG_NET_PKT_TXTIME_STATS)
+	PR("TC  Priority\tSent pkts\tbytes\ttime\n");
+
+	for (i = 0; i < NET_TC_TX_COUNT; i++) {
+		net_stats_t count = GET_STAT(iface,
+					     tc.sent[i].tx_time.count);
+		if (count == 0) {
+			PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
+			   priority2str(GET_STAT(iface, tc.sent[i].priority)),
+			   GET_STAT(iface, tc.sent[i].priority),
+			   GET_STAT(iface, tc.sent[i].pkts),
+			   GET_STAT(iface, tc.sent[i].bytes));
+		} else {
+			PR("[%d] %s (%d)\t%d\t\t%d\t%lu us%s\n", i,
+			   priority2str(GET_STAT(iface, tc.sent[i].priority)),
+			   GET_STAT(iface, tc.sent[i].priority),
+			   GET_STAT(iface, tc.sent[i].pkts),
+			   GET_STAT(iface, tc.sent[i].bytes),
+			   (uint32_t)(GET_STAT(iface,
+					    tc.sent[i].tx_time.sum) /
+				   (uint64_t)count),
+			   get_net_pkt_tc_stats_detail(iface, i, true));
+		}
+	}
+#else
+	PR("TC  Priority\tSent pkts\tbytes\n");
+
+	for (i = 0; i < NET_TC_TX_COUNT; i++) {
+		PR("[%d] %s (%d)\t%d\t\t%d\n", i,
+		   priority2str(GET_STAT(iface, tc.sent[i].priority)),
+		   GET_STAT(iface, tc.sent[i].priority),
+		   GET_STAT(iface, tc.sent[i].pkts),
+		   GET_STAT(iface, tc.sent[i].bytes));
+	}
+#endif /* CONFIG_NET_CONTEXT_TIMESTAMP */
+#else
+	ARG_UNUSED(shell);
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS)
+	net_stats_t count = GET_STAT(iface, tx_time.count);
+
+	if (count != 0) {
+		PR("Avg %s net_pkt (%u) time %lu us%s\n", "TX", count,
+		   (uint32_t)(GET_STAT(iface, tx_time.sum) / (uint64_t)count),
+		   get_net_pkt_stats_detail(iface, true));
+	}
+#else
+	ARG_UNUSED(iface);
+#endif /* CONFIG_NET_PKT_TXTIME_STATS */
+#endif /* NET_TC_TX_COUNT > 1 */
+}
+
+static void print_tc_rx_stats(const struct shell *shell, struct net_if *iface)
+{
+#if NET_TC_RX_COUNT > 1
+	int i;
+
+	PR("RX traffic class statistics:\n");
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS)
+	PR("TC  Priority\tRecv pkts\tbytes\ttime\n");
+
+	for (i = 0; i < NET_TC_RX_COUNT; i++) {
+		net_stats_t count = GET_STAT(iface,
+					     tc.recv[i].rx_time.count);
+		if (count == 0) {
+			PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i,
+			   priority2str(GET_STAT(iface, tc.recv[i].priority)),
+			   GET_STAT(iface, tc.recv[i].priority),
+			   GET_STAT(iface, tc.recv[i].pkts),
+			   GET_STAT(iface, tc.recv[i].bytes));
+		} else {
+			PR("[%d] %s (%d)\t%d\t\t%d\t%lu us%s\n", i,
+			   priority2str(GET_STAT(iface, tc.recv[i].priority)),
+			   GET_STAT(iface, tc.recv[i].priority),
+			   GET_STAT(iface, tc.recv[i].pkts),
+			   GET_STAT(iface, tc.recv[i].bytes),
+			   (uint32_t)(GET_STAT(iface,
+					    tc.recv[i].rx_time.sum) /
+				   (uint64_t)count),
+			   get_net_pkt_tc_stats_detail(iface, i, false));
+		}
+	}
+#else
+	PR("TC  Priority\tRecv pkts\tbytes\n");
+
+	for (i = 0; i < NET_TC_RX_COUNT; i++) {
+		PR("[%d] %s (%d)\t%d\t\t%d\n", i,
+		   priority2str(GET_STAT(iface, tc.recv[i].priority)),
+		   GET_STAT(iface, tc.recv[i].priority),
+		   GET_STAT(iface, tc.recv[i].pkts),
+		   GET_STAT(iface, tc.recv[i].bytes));
+	}
+#endif /* CONFIG_NET_PKT_RXTIME_STATS */
+#else
+	ARG_UNUSED(shell);
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS)
+	net_stats_t count = GET_STAT(iface, rx_time.count);
+
+	if (count != 0) {
+		PR("Avg %s net_pkt (%u) time %lu us%s\n", "RX", count,
+		   (uint32_t)(GET_STAT(iface, rx_time.sum) / (uint64_t)count),
+		   get_net_pkt_stats_detail(iface, false));
+	}
+#else
+	ARG_UNUSED(iface);
+#endif /* CONFIG_NET_PKT_RXTIME_STATS */
+
+#endif /* NET_TC_RX_COUNT > 1 */
+}
+
+static void print_net_pm_stats(const struct shell *shell, struct net_if *iface)
+{
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+	PR("PM suspend stats:\n");
+	PR("\tLast time     : %u ms\n",
+	   GET_STAT(iface, pm.last_suspend_time));
+	PR("\tAverage time  : %u ms\n",
+	   (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) /
+		   GET_STAT(iface, pm.suspend_count)));
+	PR("\tTotal time    : %llu ms\n",
+	   GET_STAT(iface, pm.overall_suspend_time));
+	PR("\tHow many times: %u\n",
+	   GET_STAT(iface, pm.suspend_count));
+#else
+	ARG_UNUSED(shell);
+	ARG_UNUSED(iface);
+#endif
+}
+
+static void net_shell_print_statistics(struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+
+	if (iface) {
+		const char *extra;
+
+		PR("\nInterface %p (%s) [%d]\n", iface,
+		   iface2str(iface, &extra), net_if_get_by_iface(iface));
+		PR("===========================%s\n", extra);
+	} else {
+		PR("\nGlobal statistics\n");
+		PR("=================\n");
+	}
+
+#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6)
+	PR("IPv6 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
+	   GET_STAT(iface, ipv6.recv),
+	   GET_STAT(iface, ipv6.sent),
+	   GET_STAT(iface, ipv6.drop),
+	   GET_STAT(iface, ipv6.forwarded));
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+	PR("IPv6 ND recv   %d\tsent\t%d\tdrop\t%d\n",
+	   GET_STAT(iface, ipv6_nd.recv),
+	   GET_STAT(iface, ipv6_nd.sent),
+	   GET_STAT(iface, ipv6_nd.drop));
+#endif /* CONFIG_NET_STATISTICS_IPV6_ND */
+#if defined(CONFIG_NET_STATISTICS_MLD)
+	PR("IPv6 MLD recv  %d\tsent\t%d\tdrop\t%d\n",
+	   GET_STAT(iface, ipv6_mld.recv),
+	   GET_STAT(iface, ipv6_mld.sent),
+	   GET_STAT(iface, ipv6_mld.drop));
+#endif /* CONFIG_NET_STATISTICS_MLD */
+#endif /* CONFIG_NET_STATISTICS_IPV6 */
+
+#if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+	PR("IPv4 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
+	   GET_STAT(iface, ipv4.recv),
+	   GET_STAT(iface, ipv4.sent),
+	   GET_STAT(iface, ipv4.drop),
+	   GET_STAT(iface, ipv4.forwarded));
+#endif /* CONFIG_NET_STATISTICS_IPV4 */
+
+	PR("IP vhlerr      %d\thblener\t%d\tlblener\t%d\n",
+	   GET_STAT(iface, ip_errors.vhlerr),
+	   GET_STAT(iface, ip_errors.hblenerr),
+	   GET_STAT(iface, ip_errors.lblenerr));
+	PR("IP fragerr     %d\tchkerr\t%d\tprotoer\t%d\n",
+	   GET_STAT(iface, ip_errors.fragerr),
+	   GET_STAT(iface, ip_errors.chkerr),
+	   GET_STAT(iface, ip_errors.protoerr));
+
+#if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4)
+	PR("ICMP recv      %d\tsent\t%d\tdrop\t%d\n",
+	   GET_STAT(iface, icmp.recv),
+	   GET_STAT(iface, icmp.sent),
+	   GET_STAT(iface, icmp.drop));
+	PR("ICMP typeer    %d\tchkerr\t%d\n",
+	   GET_STAT(iface, icmp.typeerr),
+	   GET_STAT(iface, icmp.chkerr));
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP)
+	PR("UDP recv       %d\tsent\t%d\tdrop\t%d\n",
+	   GET_STAT(iface, udp.recv),
+	   GET_STAT(iface, udp.sent),
+	   GET_STAT(iface, udp.drop));
+	PR("UDP chkerr     %d\n",
+	   GET_STAT(iface, udp.chkerr));
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+	PR("TCP bytes recv %u\tsent\t%d\n",
+	   GET_STAT(iface, tcp.bytes.received),
+	   GET_STAT(iface, tcp.bytes.sent));
+	PR("TCP seg recv   %d\tsent\t%d\tdrop\t%d\n",
+	   GET_STAT(iface, tcp.recv),
+	   GET_STAT(iface, tcp.sent),
+	   GET_STAT(iface, tcp.drop));
+	PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
+	   GET_STAT(iface, tcp.resent),
+	   GET_STAT(iface, tcp.chkerr),
+	   GET_STAT(iface, tcp.ackerr));
+	PR("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n",
+	   GET_STAT(iface, tcp.rsterr),
+	   GET_STAT(iface, tcp.rst),
+	   GET_STAT(iface, tcp.rexmit));
+	PR("TCP conn drop  %d\tconnrst\t%d\n",
+	   GET_STAT(iface, tcp.conndrop),
+	   GET_STAT(iface, tcp.connrst));
+#endif
+
+#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && defined(CONFIG_NET_NATIVE)
+	if (GET_STAT(iface, tx_time.count) > 0) {
+		PR("Network pkt TX time %lu us\n",
+		   (uint32_t)(GET_STAT(iface, tx_time.sum) /
+			   (uint64_t)GET_STAT(iface, tx_time.count)));
+	}
+#endif
+
+	PR("Bytes received %u\n", GET_STAT(iface, bytes.received));
+	PR("Bytes sent     %u\n", GET_STAT(iface, bytes.sent));
+	PR("Processing err %d\n", GET_STAT(iface, processing_error));
+
+	print_tc_tx_stats(shell, iface);
+	print_tc_rx_stats(shell, iface);
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET) && \
+					defined(CONFIG_NET_STATISTICS_USER_API)
+	if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
+		struct net_stats_eth eth_data;
+		int ret;
+
+		ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface,
+			       &eth_data, sizeof(eth_data));
+		if (!ret) {
+			print_eth_stats(iface, &eth_data, shell);
+		}
+	}
+#endif /* CONFIG_NET_STATISTICS_ETHERNET && CONFIG_NET_STATISTICS_USER_API */
+
+#if defined(CONFIG_NET_STATISTICS_PPP) && \
+					defined(CONFIG_NET_STATISTICS_USER_API)
+	if (iface && net_if_l2(iface) == &NET_L2_GET_NAME(PPP)) {
+		struct net_stats_ppp ppp_data;
+		int ret;
+
+		ret = net_mgmt(NET_REQUEST_STATS_GET_PPP, iface,
+			       &ppp_data, sizeof(ppp_data));
+		if (!ret) {
+			print_ppp_stats(iface, &ppp_data, shell);
+		}
+	}
+#endif /* CONFIG_NET_STATISTICS_PPP && CONFIG_NET_STATISTICS_USER_API */
+
+	print_net_pm_stats(shell, iface);
+}
+#endif /* CONFIG_NET_STATISTICS */
+
+#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
+static void get_addresses(struct net_context *context,
+			  char addr_local[], int local_len,
+			  char addr_remote[], int remote_len)
+{
+#if defined(CONFIG_NET_IPV6)
+	if (context->local.family == AF_INET6) {
+		snprintk(addr_local, local_len, "[%s]:%u",
+			 net_sprint_ipv6_addr(
+				 net_sin6_ptr(&context->local)->sin6_addr),
+			 ntohs(net_sin6_ptr(&context->local)->sin6_port));
+		snprintk(addr_remote, remote_len, "[%s]:%u",
+			 net_sprint_ipv6_addr(
+				 &net_sin6(&context->remote)->sin6_addr),
+			 ntohs(net_sin6(&context->remote)->sin6_port));
+	} else
+#endif
+#if defined(CONFIG_NET_IPV4)
+	if (context->local.family == AF_INET) {
+		snprintk(addr_local, local_len, "%s:%d",
+			 net_sprint_ipv4_addr(
+				 net_sin_ptr(&context->local)->sin_addr),
+			 ntohs(net_sin_ptr(&context->local)->sin_port));
+		snprintk(addr_remote, remote_len, "%s:%d",
+			 net_sprint_ipv4_addr(
+				 &net_sin(&context->remote)->sin_addr),
+			 ntohs(net_sin(&context->remote)->sin_port));
+	} else
+#endif
+	if (context->local.family == AF_UNSPEC) {
+		snprintk(addr_local, local_len, "AF_UNSPEC");
+	} else if (context->local.family == AF_PACKET) {
+		snprintk(addr_local, local_len, "AF_PACKET");
+	} else if (context->local.family == AF_CAN) {
+		snprintk(addr_local, local_len, "AF_CAN");
+	} else {
+		snprintk(addr_local, local_len, "AF_UNK(%d)",
+			 context->local.family);
+	}
+}
+
+static void context_cb(struct net_context *context, void *user_data)
+{
+#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
+#define ADDR_LEN NET_IPV4_ADDR_LEN
+#else
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#endif
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	/* +7 for []:port */
+	char addr_local[ADDR_LEN + 7];
+	char addr_remote[ADDR_LEN + 7] = "";
+
+	get_addresses(context, addr_local, sizeof(addr_local),
+		      addr_remote, sizeof(addr_remote));
+
+	PR("[%2d] %p\t%p    %c%c%c   %16s\t%16s\n",
+	   (*count) + 1, context,
+	   net_context_get_iface(context),
+	   net_context_get_family(context) == AF_INET6 ? '6' :
+	   (net_context_get_family(context) == AF_INET ? '4' : ' '),
+	   net_context_get_type(context) == SOCK_DGRAM ? 'D' :
+	   (net_context_get_type(context) == SOCK_STREAM ? 'S' :
+	    (net_context_get_type(context) == SOCK_RAW ? 'R' : ' ')),
+	   net_context_get_ip_proto(context) == IPPROTO_UDP ? 'U' :
+	   (net_context_get_ip_proto(context) == IPPROTO_TCP ? 'T' : ' '),
+	   addr_local, addr_remote);
+
+	(*count)++;
+}
+#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
+
+#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG
+static void conn_handler_cb(struct net_conn *conn, void *user_data)
+{
+#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
+#define ADDR_LEN NET_IPV4_ADDR_LEN
+#else
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#endif
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	/* +7 for []:port */
+	char addr_local[ADDR_LEN + 7];
+	char addr_remote[ADDR_LEN + 7] = "";
+
+#if defined(CONFIG_NET_IPV6)
+	if (conn->local_addr.sa_family == AF_INET6) {
+		snprintk(addr_local, sizeof(addr_local), "[%s]:%u",
+			 net_sprint_ipv6_addr(
+				 &net_sin6(&conn->local_addr)->sin6_addr),
+			 ntohs(net_sin6(&conn->local_addr)->sin6_port));
+		snprintk(addr_remote, sizeof(addr_remote), "[%s]:%u",
+			 net_sprint_ipv6_addr(
+				 &net_sin6(&conn->remote_addr)->sin6_addr),
+			 ntohs(net_sin6(&conn->remote_addr)->sin6_port));
+	} else
+#endif
+#if defined(CONFIG_NET_IPV4)
+	if (conn->local_addr.sa_family == AF_INET) {
+		snprintk(addr_local, sizeof(addr_local), "%s:%d",
+			 net_sprint_ipv4_addr(
+				 &net_sin(&conn->local_addr)->sin_addr),
+			 ntohs(net_sin(&conn->local_addr)->sin_port));
+		snprintk(addr_remote, sizeof(addr_remote), "%s:%d",
+			 net_sprint_ipv4_addr(
+				 &net_sin(&conn->remote_addr)->sin_addr),
+			 ntohs(net_sin(&conn->remote_addr)->sin_port));
+	} else
+#endif
+#ifdef CONFIG_NET_L2_CANBUS
+	if (conn->local_addr.sa_family == AF_CAN) {
+		snprintk(addr_local, sizeof(addr_local), "-");
+	} else
+#endif
+	if (conn->local_addr.sa_family == AF_UNSPEC) {
+		snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC");
+	} else {
+		snprintk(addr_local, sizeof(addr_local), "AF_UNK(%d)",
+			 conn->local_addr.sa_family);
+	}
+
+	PR("[%2d] %p %p\t%s\t%16s\t%16s\n",
+	   (*count) + 1, conn, conn->cb,
+	   net_proto2str(conn->local_addr.sa_family, conn->proto),
+	   addr_local, addr_remote);
+
+	(*count)++;
+}
+#endif /* CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG */
+
+#if defined(CONFIG_NET_TCP1) && \
+	(defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE))
+static void tcp_cb(struct net_tcp *tcp, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	uint16_t recv_mss = net_tcp_get_recv_mss(tcp);
+
+	PR("%p %p   %5u    %5u %10u %10u %5u   %s\n",
+	   tcp, tcp->context,
+	   ntohs(net_sin6_ptr(&tcp->context->local)->sin6_port),
+	   ntohs(net_sin6(&tcp->context->remote)->sin6_port),
+	   tcp->send_seq, tcp->send_ack, recv_mss,
+	   net_tcp_state_str(net_tcp_get_state(tcp)));
+
+	(*count)++;
+}
+
+#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
+static void tcp_sent_list_cb(struct net_tcp *tcp, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *printed = data->user_data;
+	struct net_pkt *pkt;
+	struct net_pkt *tmp;
+
+	if (sys_slist_is_empty(&tcp->sent_list)) {
+		return;
+	}
+
+	if (!*printed) {
+		PR("\nTCP packets waiting ACK:\n");
+		PR("TCP             net_pkt[ref/totlen]->net_buf[ref/len]..."
+		   "\n");
+	}
+
+	PR("%p      ", tcp);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp->sent_list, pkt, tmp,
+					  sent_list) {
+		struct net_buf *frag = pkt->frags;
+
+		if (!*printed) {
+			PR("%p[%d/%zd]", pkt, atomic_get(&pkt->atomic_ref),
+			       net_pkt_get_len(pkt));
+			*printed = true;
+		} else {
+			PR("                %p[%d/%zd]",
+			   pkt, atomic_get(&pkt->atomic_ref),
+			   net_pkt_get_len(pkt));
+		}
+
+		if (frag) {
+			PR("->");
+		}
+
+		while (frag) {
+			PR("%p[%d/%d]", frag, frag->ref, frag->len);
+
+			frag = frag->frags;
+			if (frag) {
+				PR("->");
+			}
+		}
+
+		PR("\n");
+	}
+
+	*printed = true;
+}
+#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */
+#endif
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+static void ipv6_frag_cb(struct net_ipv6_reassembly *reass,
+			 void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	char src[ADDR_LEN];
+	int i;
+
+	if (!*count) {
+		PR("\nIPv6 reassembly Id         Remain "
+		   "Src             \tDst\n");
+	}
+
+	snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src));
+
+	PR("%p      0x%08x  %5d %16s\t%16s\n",
+	   reass, reass->id,
+	   k_delayed_work_remaining_get(&reass->timer),
+	   src, net_sprint_ipv6_addr(&reass->dst));
+
+	for (i = 0; i < NET_IPV6_FRAGMENTS_MAX_PKT; i++) {
+		if (reass->pkt[i]) {
+			struct net_buf *frag = reass->pkt[i]->frags;
+
+			PR("[%d] pkt %p->", i, reass->pkt[i]);
+
+			while (frag) {
+				PR("%p", frag);
+
+				frag = frag->frags;
+				if (frag) {
+					PR("->");
+				}
+			}
+
+			PR("\n");
+		}
+	}
+
+	(*count)++;
+}
+#endif /* CONFIG_NET_IPV6_FRAGMENT */
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+static void allocs_cb(struct net_pkt *pkt,
+		      struct net_buf *buf,
+		      const char *func_alloc,
+		      int line_alloc,
+		      const char *func_free,
+		      int line_free,
+		      bool in_use,
+		      void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	const char *str;
+
+	if (in_use) {
+		str = "used";
+	} else {
+		if (func_alloc) {
+			str = "free";
+		} else {
+			str = "avail";
+		}
+	}
+
+	if (buf) {
+		goto buf;
+	}
+
+	if (func_alloc) {
+		if (in_use) {
+			PR("%p/%d\t%5s\t%5s\t%s():%d\n",
+			   pkt, atomic_get(&pkt->atomic_ref), str,
+			   net_pkt_slab2str(pkt->slab),
+			   func_alloc, line_alloc);
+		} else {
+			PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n",
+			   pkt, str, net_pkt_slab2str(pkt->slab),
+			   func_alloc, line_alloc, func_free,
+			   line_free);
+		}
+	}
+
+	return;
+buf:
+	if (func_alloc) {
+		struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+		if (in_use) {
+			PR("%p/%d\t%5s\t%5s\t%s():%d\n",
+			   buf, buf->ref,
+			   str, net_pkt_pool2str(pool), func_alloc,
+			   line_alloc);
+		} else {
+			PR("%p\t%5s\t%5s\t%s():%d -> %s():%d\n",
+			   buf, str, net_pkt_pool2str(pool),
+			   func_alloc, line_alloc, func_free,
+			   line_free);
+		}
+	}
+}
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
+
+/* Put the actual shell commands after this */
+
+static int cmd_net_allocs(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+	struct net_shell_user_data user_data;
+#endif
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+	user_data.shell = shell;
+
+	PR("Network memory allocations\n\n");
+	PR("memory\t\tStatus\tPool\tFunction alloc -> freed\n");
+	net_pkt_allocs_foreach(allocs_cb, &user_data);
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_DEBUG_NET_PKT_ALLOC", "net_pkt allocation");
+#endif /* CONFIG_NET_DEBUG_NET_PKT_ALLOC */
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE)
+static void arp_cb(struct arp_entry *entry, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+
+	if (*count == 0) {
+		PR("     Interface  Link              Address\n");
+	}
+
+	PR("[%2d] %p %s %s\n", *count, entry->iface,
+	   net_sprint_ll_addr(entry->eth.addr, sizeof(struct net_eth_addr)),
+	   net_sprint_ipv4_addr(&entry->ip));
+
+	(*count)++;
+}
+#endif /* CONFIG_NET_ARP */
+
+#if !defined(CONFIG_NET_ARP)
+static void print_arp_error(const struct shell *shell)
+{
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_NATIVE, CONFIG_NET_ARP, CONFIG_NET_IPV4 and"
+		" CONFIG_NET_L2_ETHERNET", "ARP");
+}
+#endif
+
+static int cmd_net_arp(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_ARP)
+	struct net_shell_user_data user_data;
+	int arg = 1;
+#endif
+
+	ARG_UNUSED(argc);
+
+#if defined(CONFIG_NET_ARP)
+	if (!argv[arg]) {
+		/* ARP cache content */
+		int count = 0;
+
+		user_data.shell = shell;
+		user_data.user_data = &count;
+
+		if (net_arp_foreach(arp_cb, &user_data) == 0) {
+			PR("ARP cache is empty.\n");
+		}
+	}
+#else
+	print_arp_error(shell);
+#endif
+
+	return 0;
+}
+
+static int cmd_net_arp_flush(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_ARP)
+	PR("Flushing ARP cache.\n");
+	net_arp_clear_cache(NULL);
+#else
+	print_arp_error(shell);
+#endif
+
+	return 0;
+}
+
+static int cmd_net_conn(const struct shell *shell, size_t argc, char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
+	struct net_shell_user_data user_data;
+	int count = 0;
+
+	PR("     Context   \tIface         Flags Local           \tRemote\n");
+
+	user_data.shell = shell;
+	user_data.user_data = &count;
+
+	net_context_foreach(context_cb, &user_data);
+
+	if (count == 0) {
+		PR("No connections\n");
+	}
+
+#if CONFIG_NET_CONN_LOG_LEVEL >= LOG_LEVEL_DBG
+	PR("\n     Handler    Callback  \tProto\tLocal           \tRemote\n");
+
+	count = 0;
+
+	net_conn_foreach(conn_handler_cb, &user_data);
+
+	if (count == 0) {
+		PR("No connection handlers found.\n");
+	}
+#endif
+
+#if defined(CONFIG_NET_TCP1)
+	PR("\nTCP        Context   Src port Dst port   "
+	   "Send-Seq   Send-Ack  MSS    State\n");
+
+	count = 0;
+
+	net_tcp_foreach(tcp_cb, &user_data);
+
+	if (count == 0) {
+		PR("No TCP connections\n");
+	} else {
+#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
+		/* Print information about pending packets */
+		count = 0;
+		net_tcp_foreach(tcp_sent_list_cb, &user_data);
+#endif /* CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG */
+	}
+
+#if CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_TCP_LOG_LEVEL_DBG", "TCP debugging");
+#endif /* CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG */
+
+#endif
+
+#if defined(CONFIG_NET_IPV6_FRAGMENT)
+	count = 0;
+
+	net_ipv6_frag_foreach(ipv6_frag_cb, &user_data);
+
+	/* Do not print anything if no fragments are pending atm */
+#endif
+
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE",
+		"connection information");
+
+#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
+
+	return 0;
+}
+
+#if defined(CONFIG_DNS_RESOLVER)
+static void dns_result_cb(enum dns_resolve_status status,
+			  struct dns_addrinfo *info,
+			  void *user_data)
+{
+	const struct shell *shell = user_data;
+
+	if (status == DNS_EAI_CANCELED) {
+		PR_WARNING("dns: Timeout while resolving name.\n");
+		return;
+	}
+
+	if (status == DNS_EAI_INPROGRESS && info) {
+		char addr[NET_IPV6_ADDR_LEN];
+
+		if (info->ai_family == AF_INET) {
+			net_addr_ntop(AF_INET,
+				      &net_sin(&info->ai_addr)->sin_addr,
+				      addr, NET_IPV4_ADDR_LEN);
+		} else if (info->ai_family == AF_INET6) {
+			net_addr_ntop(AF_INET6,
+				      &net_sin6(&info->ai_addr)->sin6_addr,
+				      addr, NET_IPV6_ADDR_LEN);
+		} else {
+			strncpy(addr, "Invalid protocol family",
+				sizeof(addr));
+			/* strncpy() doesn't guarantee NUL byte at the end. */
+			addr[sizeof(addr) - 1] = 0;
+		}
+
+		PR("dns: %s\n", addr);
+		return;
+	}
+
+	if (status == DNS_EAI_ALLDONE) {
+		PR("dns: All results received\n");
+		return;
+	}
+
+	if (status == DNS_EAI_FAIL) {
+		PR_WARNING("dns: No such name found.\n");
+		return;
+	}
+
+	PR_WARNING("dns: Unhandled status %d received\n", status);
+}
+
+static void print_dns_info(const struct shell *shell,
+			   struct dns_resolve_context *ctx)
+{
+	int i;
+
+	PR("DNS servers:\n");
+
+	for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS +
+		     DNS_MAX_MCAST_SERVERS; i++) {
+		if (ctx->servers[i].dns_server.sa_family == AF_INET) {
+			PR("\t%s:%u\n",
+			   net_sprint_ipv4_addr(
+				   &net_sin(&ctx->servers[i].dns_server)->
+				   sin_addr),
+			   ntohs(net_sin(
+				 &ctx->servers[i].dns_server)->sin_port));
+		} else if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
+			PR("\t[%s]:%u\n",
+			   net_sprint_ipv6_addr(
+				   &net_sin6(&ctx->servers[i].dns_server)->
+				   sin6_addr),
+			   ntohs(net_sin6(
+				 &ctx->servers[i].dns_server)->sin6_port));
+		}
+	}
+
+	PR("Pending queries:\n");
+
+	for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+		int32_t remaining;
+
+		if (!ctx->queries[i].cb) {
+			continue;
+		}
+
+		remaining =
+			k_delayed_work_remaining_get(&ctx->queries[i].timer);
+
+		if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) {
+			PR("\tIPv4[%u]: %s remaining %d\n",
+			   ctx->queries[i].id,
+			   ctx->queries[i].query,
+			   remaining);
+		} else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) {
+			PR("\tIPv6[%u]: %s remaining %d\n",
+			   ctx->queries[i].id,
+			   ctx->queries[i].query,
+			   remaining);
+		}
+	}
+}
+#endif
+
+static int cmd_net_dns_cancel(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+#if defined(CONFIG_DNS_RESOLVER)
+	struct dns_resolve_context *ctx;
+	int ret, i;
+#endif
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_DNS_RESOLVER)
+	ctx = dns_resolve_get_default();
+	if (!ctx) {
+		PR_WARNING("No default DNS context found.\n");
+		return -ENOEXEC;
+	}
+
+	for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+		if (!ctx->queries[i].cb) {
+			continue;
+		}
+
+		if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) {
+			ret++;
+		}
+	}
+
+	if (ret) {
+		PR("Cancelled %d pending requests.\n", ret);
+	} else {
+		PR("No pending DNS requests.\n");
+	}
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_DNS_RESOLVER",
+		"DNS resolver");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_dns_query(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+
+#if defined(CONFIG_DNS_RESOLVER)
+#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
+	enum dns_query_type qtype = DNS_QUERY_TYPE_A;
+	char *host, *type = NULL;
+	int ret, arg = 1;
+
+	host = argv[arg++];
+	if (!host) {
+		PR_WARNING("Hostname not specified.\n");
+		return -ENOEXEC;
+	}
+
+	if (argv[arg]) {
+		type = argv[arg];
+	}
+
+	if (type) {
+		if (strcmp(type, "A") == 0) {
+			qtype = DNS_QUERY_TYPE_A;
+			PR("IPv4 address type\n");
+		} else if (strcmp(type, "AAAA") == 0) {
+			qtype = DNS_QUERY_TYPE_AAAA;
+			PR("IPv6 address type\n");
+		} else {
+			PR_WARNING("Unknown query type, specify either "
+				   "A or AAAA\n");
+			return -ENOEXEC;
+		}
+	}
+
+	ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb,
+				(void *)shell, DNS_TIMEOUT);
+	if (ret < 0) {
+		PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret);
+	} else {
+		PR("Query for '%s' sent.\n", host);
+	}
+#else
+	PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "
+		"enable it.\n");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_dns(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_DNS_RESOLVER)
+	struct dns_resolve_context *ctx;
+#endif
+
+#if defined(CONFIG_DNS_RESOLVER)
+	if (argv[1]) {
+		/* So this is a query then */
+		cmd_net_dns_query(shell, argc, argv);
+		return 0;
+	}
+
+	/* DNS status */
+	ctx = dns_resolve_get_default();
+	if (!ctx) {
+		PR_WARNING("No default DNS context found.\n");
+		return -ENOEXEC;
+	}
+
+	print_dns_info(shell, ctx);
+#else
+	PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "
+		"enable it.\n");
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
+#define EVENT_MON_STACK_SIZE 1024
+#define THREAD_PRIORITY K_PRIO_COOP(2)
+#define MAX_EVENT_INFO_SIZE NET_EVENT_INFO_MAX_SIZE
+#define MONITOR_L2_MASK (_NET_EVENT_IF_BASE)
+#define MONITOR_L3_IPV4_MASK (_NET_EVENT_IPV4_BASE)
+#define MONITOR_L3_IPV6_MASK (_NET_EVENT_IPV6_BASE)
+#define MONITOR_L4_MASK (_NET_EVENT_L4_BASE)
+
+static bool net_event_monitoring;
+static bool net_event_shutting_down;
+static struct net_mgmt_event_callback l2_cb;
+static struct net_mgmt_event_callback l3_ipv4_cb;
+static struct net_mgmt_event_callback l3_ipv6_cb;
+static struct net_mgmt_event_callback l4_cb;
+static struct k_thread event_mon;
+static K_THREAD_STACK_DEFINE(event_mon_stack, EVENT_MON_STACK_SIZE);
+
+struct event_msg {
+	struct net_if *iface;
+	size_t len;
+	uint32_t event;
+	uint8_t data[MAX_EVENT_INFO_SIZE];
+};
+
+K_MSGQ_DEFINE(event_mon_msgq, sizeof(struct event_msg),
+	      CONFIG_NET_MGMT_EVENT_QUEUE_SIZE, sizeof(intptr_t));
+
+static void event_handler(struct net_mgmt_event_callback *cb,
+			  uint32_t mgmt_event, struct net_if *iface)
+{
+	struct event_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof(msg));
+
+	msg.len = MIN(sizeof(msg.data), cb->info_length);
+	msg.event = mgmt_event;
+	msg.iface = iface;
+
+	if (cb->info_length > 0) {
+		memcpy(msg.data, cb->info, msg.len);
+	}
+
+	ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(10));
+	if (ret < 0) {
+		NET_ERR("Cannot write to msgq (%d)\n", ret);
+	}
+}
+
+static const char *get_l2_desc(uint32_t event)
+{
+	static const char *desc = "<unknown event>";
+
+	switch (event) {
+	case NET_EVENT_IF_DOWN:
+		desc = "down";
+		break;
+	case NET_EVENT_IF_UP:
+		desc = "up";
+		break;
+	}
+
+	return desc;
+}
+
+static char *get_l3_desc(struct event_msg *msg,
+			 const char **desc, const char **desc2,
+			 char *extra_info, size_t extra_info_len)
+{
+	static const char *desc_unknown = "<unknown event>";
+	char *info = NULL;
+
+	*desc = desc_unknown;
+
+	switch (msg->event) {
+	case NET_EVENT_IPV6_ADDR_ADD:
+		*desc = "IPv6 address";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_ADDR_DEL:
+		*desc = "IPv6 address";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_MADDR_ADD:
+		*desc = "IPv6 mcast address";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_MADDR_DEL:
+		*desc = "IPv6 mcast address";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_PREFIX_ADD:
+		*desc = "IPv6 prefix";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_PREFIX_DEL:
+		*desc = "IPv6 prefix";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_MCAST_JOIN:
+		*desc = "IPv6 mcast";
+		*desc2 = "join";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_MCAST_LEAVE:
+		*desc = "IPv6 mcast";
+		*desc2 = "leave";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_ROUTER_ADD:
+		*desc = "IPv6 router";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_ROUTER_DEL:
+		*desc = "IPv6 router";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_ROUTE_ADD:
+		*desc = "IPv6 route";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_ROUTE_DEL:
+		*desc = "IPv6 route";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_DAD_SUCCEED:
+		*desc = "IPv6 DAD";
+		*desc2 = "ok";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_DAD_FAILED:
+		*desc = "IPv6 DAD";
+		*desc2 = "fail";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_NBR_ADD:
+		*desc = "IPv6 neighbor";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV6_NBR_DEL:
+		*desc = "IPv6 neighbor";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET6, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV4_ADDR_ADD:
+		*desc = "IPv4 address";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV4_ADDR_DEL:
+		*desc = "IPv4 address";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV4_ROUTER_ADD:
+		*desc = "IPv4 router";
+		*desc2 = "add";
+		info = net_addr_ntop(AF_INET, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV4_ROUTER_DEL:
+		*desc = "IPv4 router";
+		*desc2 = "del";
+		info = net_addr_ntop(AF_INET, msg->data, extra_info,
+				     extra_info_len);
+		break;
+	case NET_EVENT_IPV4_DHCP_START:
+		*desc = "DHCPv4";
+		*desc2 = "start";
+		break;
+	case NET_EVENT_IPV4_DHCP_BOUND:
+		*desc = "DHCPv4";
+		*desc2 = "bound";
+#if defined(CONFIG_NET_DHCPV4)
+		struct net_if_dhcpv4 *data = (struct net_if_dhcpv4 *)msg->data;
+
+		info = net_addr_ntop(AF_INET, &data->requested_ip, extra_info,
+				     extra_info_len);
+#endif
+		break;
+	case NET_EVENT_IPV4_DHCP_STOP:
+		*desc = "DHCPv4";
+		*desc2 = "stop";
+		break;
+	}
+
+	return info;
+}
+
+static const char *get_l4_desc(uint32_t event)
+{
+	static const char *desc = "<unknown event>";
+
+	switch (event) {
+	case NET_EVENT_L4_CONNECTED:
+		desc = "connected";
+		break;
+	case NET_EVENT_L4_DISCONNECTED:
+		desc = "disconnected";
+		break;
+	case NET_EVENT_DNS_SERVER_ADD:
+		desc = "DNS server add";
+		break;
+	case NET_EVENT_DNS_SERVER_DEL:
+		desc = "DNS server del";
+		break;
+	}
+
+	return desc;
+}
+
+/* We use a separate thread in order not to do any shell printing from
+ * event handler callback (to avoid stack size issues).
+ */
+static void event_mon_handler(const struct shell *shell)
+{
+	char extra_info[NET_IPV6_ADDR_LEN];
+	struct event_msg msg;
+
+	net_mgmt_init_event_callback(&l2_cb, event_handler,
+				     MONITOR_L2_MASK);
+	net_mgmt_add_event_callback(&l2_cb);
+
+	net_mgmt_init_event_callback(&l3_ipv4_cb, event_handler,
+				     MONITOR_L3_IPV4_MASK);
+	net_mgmt_add_event_callback(&l3_ipv4_cb);
+
+	net_mgmt_init_event_callback(&l3_ipv6_cb, event_handler,
+				     MONITOR_L3_IPV6_MASK);
+	net_mgmt_add_event_callback(&l3_ipv6_cb);
+
+	net_mgmt_init_event_callback(&l4_cb, event_handler,
+				     MONITOR_L4_MASK);
+	net_mgmt_add_event_callback(&l4_cb);
+
+	while (net_event_shutting_down == false) {
+		const char *layer_str = "<unknown layer>";
+		const char *desc = "", *desc2 = "";
+		char *info = NULL;
+		uint32_t layer;
+
+		(void)k_msgq_get(&event_mon_msgq, &msg, K_FOREVER);
+
+		if (msg.iface == NULL && msg.event == 0 && msg.len == 0) {
+			/* This is the stop message */
+			continue;
+		}
+
+		layer = NET_MGMT_GET_LAYER(msg.event);
+		if (layer == NET_MGMT_LAYER_L2) {
+			layer_str = "L2";
+			desc = get_l2_desc(msg.event);
+		} else if (layer == NET_MGMT_LAYER_L3) {
+			layer_str = "L3";
+			info = get_l3_desc(&msg, &desc, &desc2,
+					   extra_info, NET_IPV6_ADDR_LEN);
+		} else if (layer == NET_MGMT_LAYER_L4) {
+			layer_str = "L4";
+			desc = get_l4_desc(msg.event);
+		}
+
+		PR_INFO("EVENT: %s [%d] %s%s%s%s%s\n", layer_str,
+			net_if_get_by_iface(msg.iface), desc,
+			desc2 ? " " : "", desc2 ? desc2 : "",
+			info ? " " : "", info ? info : "");
+	}
+
+	net_mgmt_del_event_callback(&l2_cb);
+	net_mgmt_del_event_callback(&l3_ipv4_cb);
+	net_mgmt_del_event_callback(&l3_ipv6_cb);
+	net_mgmt_del_event_callback(&l4_cb);
+
+	k_msgq_purge(&event_mon_msgq);
+
+	net_event_monitoring = false;
+	net_event_shutting_down = false;
+
+	PR_INFO("Network event monitoring %s.\n", "disabled");
+}
+#endif
+
+static int cmd_net_events_on(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
+	k_tid_t tid;
+
+	if (net_event_monitoring) {
+		PR_INFO("Network event monitoring is already %s.\n",
+			"enabled");
+		return -ENOEXEC;
+	}
+
+	tid = k_thread_create(&event_mon, event_mon_stack,
+			      K_THREAD_STACK_SIZEOF(event_mon_stack),
+			      (k_thread_entry_t)event_mon_handler,
+			      (void *)shell, NULL, NULL, THREAD_PRIORITY, 0,
+			      K_FOREVER);
+	if (!tid) {
+		PR_ERROR("Cannot create network event monitor thread!");
+		return -ENOEXEC;
+	}
+
+	k_thread_name_set(tid, "event_mon");
+
+	PR_INFO("Network event monitoring %s.\n", "enabled");
+
+	net_event_monitoring = true;
+	net_event_shutting_down = false;
+
+	k_thread_start(tid);
+#else
+	PR_INFO("Network management events are not supported. "
+		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_events_off(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
+	static const struct event_msg msg;
+	int ret;
+
+	if (!net_event_monitoring) {
+		PR_INFO("Network event monitoring is already %s.\n",
+			"disabled");
+		return -ENOEXEC;
+	}
+
+	net_event_shutting_down = true;
+
+	ret = k_msgq_put(&event_mon_msgq, (void *)&msg, K_MSEC(100));
+	if (ret < 0) {
+		PR_ERROR("Cannot write to msgq (%d)\n", ret);
+		return -ENOEXEC;
+	}
+#else
+	PR_INFO("Network management events are not supported. "
+		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_events(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_MGMT_EVENT_MONITOR)
+	PR("Network event monitoring is %s.\n",
+	   net_event_monitoring ? "enabled" : "disabled");
+
+	if (!argv[1]) {
+		PR_INFO("Give 'on' to enable event monitoring and "
+			"'off' to disable it.\n");
+	}
+#else
+	PR_INFO("Network management events are not supported. "
+		"Set CONFIG_NET_MGMT_EVENT_MONITOR to enable it.\n");
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_GPTP)
+static const char *selected_role_str(int port);
+
+static void gptp_port_cb(int port, struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+
+	if (*count == 0) {
+		PR("Port Interface  \tRole\n");
+	}
+
+	(*count)++;
+
+	PR("%2d   %p [%d]  \t%s\n", port, iface, net_if_get_by_iface(iface),
+	   selected_role_str(port));
+}
+
+static const char *pdelay_req2str(enum gptp_pdelay_req_states state)
+{
+	switch (state) {
+	case GPTP_PDELAY_REQ_NOT_ENABLED:
+		return "REQ_NOT_ENABLED";
+	case GPTP_PDELAY_REQ_INITIAL_SEND_REQ:
+		return "INITIAL_SEND_REQ";
+	case GPTP_PDELAY_REQ_RESET:
+		return "REQ_RESET";
+	case GPTP_PDELAY_REQ_SEND_REQ:
+		return "SEND_REQ";
+	case GPTP_PDELAY_REQ_WAIT_RESP:
+		return "WAIT_RESP";
+	case GPTP_PDELAY_REQ_WAIT_FOLLOW_UP:
+		return "WAIT_FOLLOW_UP";
+	case GPTP_PDELAY_REQ_WAIT_ITV_TIMER:
+		return "WAIT_ITV_TIMER";
+	}
+
+	return "<unknown>";
+};
+
+static const char *pdelay_resp2str(enum gptp_pdelay_resp_states state)
+{
+	switch (state) {
+	case GPTP_PDELAY_RESP_NOT_ENABLED:
+		return "RESP_NOT_ENABLED";
+	case GPTP_PDELAY_RESP_INITIAL_WAIT_REQ:
+		return "INITIAL_WAIT_REQ";
+	case GPTP_PDELAY_RESP_WAIT_REQ:
+		return "WAIT_REQ";
+	case GPTP_PDELAY_RESP_WAIT_TSTAMP:
+		return "WAIT_TSTAMP";
+	}
+
+	return "<unknown>";
+}
+
+static const char *sync_rcv2str(enum gptp_sync_rcv_states state)
+{
+	switch (state) {
+	case GPTP_SYNC_RCV_DISCARD:
+		return "DISCARD";
+	case GPTP_SYNC_RCV_WAIT_SYNC:
+		return "WAIT_SYNC";
+	case GPTP_SYNC_RCV_WAIT_FOLLOW_UP:
+		return "WAIT_FOLLOW_UP";
+	}
+
+	return "<unknown>";
+}
+
+static const char *sync_send2str(enum gptp_sync_send_states state)
+{
+	switch (state) {
+	case GPTP_SYNC_SEND_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_SYNC_SEND_SEND_SYNC:
+		return "SEND_SYNC";
+	case GPTP_SYNC_SEND_SEND_FUP:
+		return "SEND_FUP";
+	}
+
+	return "<unknown>";
+}
+
+static const char *pss_rcv2str(enum gptp_pss_rcv_states state)
+{
+	switch (state) {
+	case GPTP_PSS_RCV_DISCARD:
+		return "DISCARD";
+	case GPTP_PSS_RCV_RECEIVED_SYNC:
+		return "RECEIVED_SYNC";
+	}
+
+	return "<unknown>";
+}
+
+static const char *pss_send2str(enum gptp_pss_send_states state)
+{
+	switch (state) {
+	case GPTP_PSS_SEND_TRANSMIT_INIT:
+		return "TRANSMIT_INIT";
+	case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT:
+		return "SYNC_RECEIPT_TIMEOUT";
+	case GPTP_PSS_SEND_SEND_MD_SYNC:
+		return "SEND_MD_SYNC";
+	case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
+		return "SET_SYNC_RECEIPT_TIMEOUT";
+	}
+
+	return "<unknown>";
+}
+
+static const char *pa_rcv2str(enum gptp_pa_rcv_states state)
+{
+	switch (state) {
+	case GPTP_PA_RCV_DISCARD:
+		return "DISCARD";
+	case GPTP_PA_RCV_RECEIVE:
+		return "RECEIVE";
+	}
+
+	return "<unknown>";
+};
+
+static const char *pa_info2str(enum gptp_pa_info_states state)
+{
+	switch (state) {
+	case GPTP_PA_INFO_DISABLED:
+		return "DISABLED";
+	case GPTP_PA_INFO_POST_DISABLED:
+		return "POST_DISABLED";
+	case GPTP_PA_INFO_AGED:
+		return "AGED";
+	case GPTP_PA_INFO_UPDATE:
+		return "UPDATE";
+	case GPTP_PA_INFO_CURRENT:
+		return "CURRENT";
+	case GPTP_PA_INFO_RECEIVE:
+		return "RECEIVE";
+	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
+		return "SUPERIOR_MASTER_PORT";
+	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
+		return "REPEATED_MASTER_PORT";
+	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
+		return "INFERIOR_MASTER_OR_OTHER_PORT";
+	}
+
+	return "<unknown>";
+};
+
+static const char *pa_transmit2str(enum gptp_pa_transmit_states state)
+{
+	switch (state) {
+	case GPTP_PA_TRANSMIT_INIT:
+		return "INIT";
+	case GPTP_PA_TRANSMIT_PERIODIC:
+		return "PERIODIC";
+	case GPTP_PA_TRANSMIT_IDLE:
+		return "IDLE";
+	case GPTP_PA_TRANSMIT_POST_IDLE:
+		return "POST_IDLE";
+	}
+
+	return "<unknown>";
+};
+
+static const char *site_sync2str(enum gptp_site_sync_sync_states state)
+{
+	switch (state) {
+	case GPTP_SSS_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_SSS_RECEIVING_SYNC:
+		return "RECEIVING_SYNC";
+	}
+
+	return "<unknown>";
+}
+
+static const char *clk_slave2str(enum gptp_clk_slave_sync_states state)
+{
+	switch (state) {
+	case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
+		return "SEND_SYNC_IND";
+	}
+
+	return "<unknown>";
+};
+
+static const char *pr_selection2str(enum gptp_pr_selection_states state)
+{
+	switch (state) {
+	case GPTP_PR_SELECTION_INIT_BRIDGE:
+		return "INIT_BRIDGE";
+	case GPTP_PR_SELECTION_ROLE_SELECTION:
+		return "ROLE_SELECTION";
+	}
+
+	return "<unknown>";
+};
+
+static const char *cms_rcv2str(enum gptp_cms_rcv_states state)
+{
+	switch (state) {
+	case GPTP_CMS_RCV_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_CMS_RCV_WAITING:
+		return "WAITING";
+	case GPTP_CMS_RCV_SOURCE_TIME:
+		return "SOURCE_TIME";
+	}
+
+	return "<unknown>";
+};
+
+#if !defined(USCALED_NS_TO_NS)
+#define USCALED_NS_TO_NS(val) (val >> 16)
+#endif
+
+static const char *selected_role_str(int port)
+{
+	switch (GPTP_GLOBAL_DS()->selected_role[port]) {
+	case GPTP_PORT_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_PORT_FAULTY:
+		return "FAULTY";
+	case GPTP_PORT_DISABLED:
+		return "DISABLED";
+	case GPTP_PORT_LISTENING:
+		return "LISTENING";
+	case GPTP_PORT_PRE_MASTER:
+		return "PRE-MASTER";
+	case GPTP_PORT_MASTER:
+		return "MASTER";
+	case GPTP_PORT_PASSIVE:
+		return "PASSIVE";
+	case GPTP_PORT_UNCALIBRATED:
+		return "UNCALIBRATED";
+	case GPTP_PORT_SLAVE:
+		return "SLAVE";
+	}
+
+	return "<unknown>";
+}
+
+static void gptp_print_port_info(const struct shell *shell, int port)
+{
+	struct gptp_port_bmca_data *port_bmca_data;
+	struct gptp_port_param_ds *port_param_ds;
+	struct gptp_port_states *port_state;
+	struct gptp_domain *gptp_domain;
+	struct gptp_port_ds *port_ds;
+	struct net_if *iface;
+	int ret, i;
+
+	gptp_domain = gptp_get_domain();
+
+	ret = gptp_get_port_data(gptp_domain,
+				 port,
+				 &port_ds,
+				 &port_param_ds,
+				 &port_state,
+				 &port_bmca_data,
+				 &iface);
+	if (ret < 0) {
+		PR_WARNING("Cannot get gPTP information for port %d (%d)\n",
+			   port, ret);
+		return;
+	}
+
+	NET_ASSERT(port == port_ds->port_id.port_number,
+		   "Port number mismatch! (%d vs %d)", port,
+		   port_ds->port_id.port_number);
+
+	PR("Port id    : %d (%s)\n", port_ds->port_id.port_number,
+	   selected_role_str(port_ds->port_id.port_number));
+	PR("Interface  : %p [%d]\n", iface, net_if_get_by_iface(iface));
+	PR("Clock id   : ");
+	for (i = 0; i < sizeof(port_ds->port_id.clk_id); i++) {
+		PR("%02x", port_ds->port_id.clk_id[i]);
+
+		if (i != (sizeof(port_ds->port_id.clk_id) - 1)) {
+			PR(":");
+		}
+	}
+	PR("\n");
+
+	PR("Version    : %d\n", port_ds->version);
+	PR("AS capable : %s\n", port_ds->as_capable ? "yes" : "no");
+
+	PR("\nConfiguration:\n");
+	PR("Time synchronization and Best Master Selection enabled        "
+	   ": %s\n", port_ds->ptt_port_enabled ? "yes" : "no");
+	PR("The port is measuring the path delay                          "
+	   ": %s\n", port_ds->is_measuring_delay ? "yes" : "no");
+	PR("One way propagation time on %s    : %u ns\n",
+	   "the link attached to this port",
+	   (uint32_t)port_ds->neighbor_prop_delay);
+	PR("Propagation time threshold for %s : %u ns\n",
+	   "the link attached to this port",
+	   (uint32_t)port_ds->neighbor_prop_delay_thresh);
+	PR("Estimate of the ratio of the frequency with the peer          "
+	   ": %u\n", (uint32_t)port_ds->neighbor_rate_ratio);
+	PR("Asymmetry on the link relative to the grand master time base  "
+	   ": %lld\n", port_ds->delay_asymmetry);
+	PR("Maximum interval between sync %s                        "
+	   ": %llu\n", "messages",
+	   port_ds->sync_receipt_timeout_time_itv);
+	PR("Maximum number of Path Delay Requests without a response      "
+	   ": %d\n", port_ds->allowed_lost_responses);
+	PR("Current Sync %s                        : %d\n",
+	   "sequence id for this port", port_ds->sync_seq_id);
+	PR("Current Path Delay Request %s          : %d\n",
+	   "sequence id for this port", port_ds->pdelay_req_seq_id);
+	PR("Current Announce %s                    : %d\n",
+	   "sequence id for this port", port_ds->announce_seq_id);
+	PR("Current Signaling %s                   : %d\n",
+	   "sequence id for this port", port_ds->signaling_seq_id);
+	PR("Whether neighborRateRatio %s  : %s\n",
+	   "needs to be computed for this port",
+	   port_ds->compute_neighbor_rate_ratio ? "yes" : "no");
+	PR("Whether neighborPropDelay %s  : %s\n",
+	   "needs to be computed for this port",
+	   port_ds->compute_neighbor_prop_delay ? "yes" : "no");
+	PR("Initial Announce Interval %s            : %d\n",
+	   "as a Logarithm to base 2", port_ds->ini_log_announce_itv);
+	PR("Current Announce Interval %s            : %d\n",
+	   "as a Logarithm to base 2", port_ds->cur_log_announce_itv);
+	PR("Initial Sync Interval %s                : %d\n",
+	   "as a Logarithm to base 2", port_ds->ini_log_half_sync_itv);
+	PR("Current Sync Interval %s                : %d\n",
+	   "as a Logarithm to base 2", port_ds->cur_log_half_sync_itv);
+	PR("Initial Path Delay Request Interval %s  : %d\n",
+	   "as a Logarithm to base 2", port_ds->ini_log_pdelay_req_itv);
+	PR("Current Path Delay Request Interval %s  : %d\n",
+	   "as a Logarithm to base 2", port_ds->cur_log_pdelay_req_itv);
+	PR("Time without receiving announce %s %s  : %d ms (%d)\n",
+	   "messages", "before running BMCA",
+	   gptp_uscaled_ns_to_timer_ms(
+		   &port_bmca_data->ann_rcpt_timeout_time_interval),
+	   port_ds->announce_receipt_timeout);
+	PR("Time without receiving sync %s %s      : %llu ms (%d)\n",
+	   "messages", "before running BMCA",
+	   (port_ds->sync_receipt_timeout_time_itv >> 16) /
+					(NSEC_PER_SEC / MSEC_PER_SEC),
+	   port_ds->sync_receipt_timeout);
+	PR("Sync event %s                 : %llu ms\n",
+	   "transmission interval for the port",
+	   USCALED_NS_TO_NS(port_ds->half_sync_itv.low) /
+					(NSEC_PER_USEC * USEC_PER_MSEC));
+	PR("Path Delay Request %s         : %llu ms\n",
+	   "transmission interval for the port",
+	   USCALED_NS_TO_NS(port_ds->pdelay_req_itv.low) /
+					(NSEC_PER_USEC * USEC_PER_MSEC));
+	PR("BMCA %s %s%d%s: %d\n", "default", "priority", 1,
+	   "                                        ",
+	   gptp_domain->default_ds.priority1);
+	PR("BMCA %s %s%d%s: %d\n", "default", "priority", 2,
+	   "                                        ",
+	   gptp_domain->default_ds.priority2);
+
+	PR("\nRuntime status:\n");
+	PR("Current global port state                          "
+	   "      : %s\n", selected_role_str(port));
+	PR("Path Delay Request state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pdelay_req2str(port_state->pdelay_req.state));
+	PR("\tInitial Path Delay Response Peer Timestamp       "
+	   ": %llu\n", port_state->pdelay_req.ini_resp_evt_tstamp);
+	PR("\tInitial Path Delay Response Ingress Timestamp    "
+	   ": %llu\n", port_state->pdelay_req.ini_resp_ingress_tstamp);
+	PR("\tPath Delay Response %s %s            : %u\n",
+	   "messages", "received",
+	   port_state->pdelay_req.rcvd_pdelay_resp);
+	PR("\tPath Delay Follow Up %s %s           : %u\n",
+	   "messages", "received",
+	   port_state->pdelay_req.rcvd_pdelay_follow_up);
+	PR("\tNumber of lost Path Delay Responses              "
+	   ": %u\n", port_state->pdelay_req.lost_responses);
+	PR("\tTimer expired send a new Path Delay Request      "
+	   ": %u\n", port_state->pdelay_req.pdelay_timer_expired);
+	PR("\tNeighborRateRatio has been computed successfully "
+	   ": %u\n", port_state->pdelay_req.neighbor_rate_ratio_valid);
+	PR("\tPath Delay has already been computed after init  "
+	   ": %u\n", port_state->pdelay_req.init_pdelay_compute);
+	PR("\tCount consecutive reqs with multiple responses   "
+	   ": %u\n", port_state->pdelay_req.multiple_resp_count);
+
+	PR("Path Delay Response state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pdelay_resp2str(port_state->pdelay_resp.state));
+
+	PR("SyncReceive state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", sync_rcv2str(port_state->sync_rcv.state));
+	PR("\tA Sync %s %s                 : %s\n",
+	   "Message", "has been received",
+	   port_state->sync_rcv.rcvd_sync ? "yes" : "no");
+	PR("\tA Follow Up %s %s            : %s\n",
+	   "Message", "has been received",
+	   port_state->sync_rcv.rcvd_follow_up ? "yes" : "no");
+	PR("\tA Follow Up %s %s                      : %s\n",
+	   "Message", "timeout",
+	   port_state->sync_rcv.follow_up_timeout_expired ? "yes" : "no");
+	PR("\tTime at which a Sync %s without Follow Up\n"
+	   "\t                             will be discarded   "
+	   ": %llu\n", "Message",
+	   port_state->sync_rcv.follow_up_receipt_timeout);
+
+	PR("SyncSend state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", sync_send2str(port_state->sync_send.state));
+	PR("\tA MDSyncSend structure %s         : %s\n",
+	   "has been received",
+	   port_state->sync_send.rcvd_md_sync ? "yes" : "no");
+	PR("\tThe timestamp for the sync msg %s : %s\n",
+	   "has been received",
+	   port_state->sync_send.md_sync_timestamp_avail ? "yes" : "no");
+
+	PR("PortSyncSyncReceive state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pss_rcv2str(port_state->pss_rcv.state));
+	PR("\tGrand Master / Local Clock frequency ratio       "
+	   ": %f\n", port_state->pss_rcv.rate_ratio);
+	PR("\tA MDSyncReceive struct is ready to be processed  "
+	   ": %s\n", port_state->pss_rcv.rcvd_md_sync ? "yes" : "no");
+	PR("\tExpiry of SyncReceiptTimeoutTimer                : %s\n",
+	   port_state->pss_rcv.rcv_sync_receipt_timeout_timer_expired ?
+	   "yes" : "no");
+
+	PR("PortSyncSyncSend state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pss_send2str(port_state->pss_send.state));
+	PR("\tFollow Up Correction Field of last recv PSS      "
+	   ": %lld\n",
+	   port_state->pss_send.last_follow_up_correction_field);
+	PR("\tUpstream Tx Time of the last recv PortSyncSync   "
+	   ": %llu\n", port_state->pss_send.last_upstream_tx_time);
+	PR("\tRate Ratio of the last received PortSyncSync     "
+	   ": %f\n",
+	   port_state->pss_send.last_rate_ratio);
+	PR("\tGM Freq Change of the last received PortSyncSync "
+	   ": %f\n", port_state->pss_send.last_gm_freq_change);
+	PR("\tGM Time Base Indicator of last recv PortSyncSync "
+	   ": %d\n", port_state->pss_send.last_gm_time_base_indicator);
+	PR("\tReceived Port Number of last recv PortSyncSync   "
+	   ": %d\n",
+	   port_state->pss_send.last_rcvd_port_num);
+	PR("\tPortSyncSync structure is ready to be processed  "
+	   ": %s\n", port_state->pss_send.rcvd_pss_sync ? "yes" : "no");
+	PR("\tFlag when the %s has expired    : %s\n",
+	   "half_sync_itv_timer",
+	   port_state->pss_send.half_sync_itv_timer_expired ? "yes" : "no");
+	PR("\tHas %s expired twice            : %s\n",
+	   "half_sync_itv_timer",
+	   port_state->pss_send.sync_itv_timer_expired ? "yes" : "no");
+	PR("\tHas syncReceiptTimeoutTime expired               "
+	   ": %s\n",
+	   port_state->pss_send.send_sync_receipt_timeout_timer_expired ?
+	   "yes" : "no");
+
+	PR("PortAnnounceReceive state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pa_rcv2str(port_state->pa_rcv.state));
+	PR("\tAn announce message is ready to be processed     "
+	   ": %s\n",
+	   port_state->pa_rcv.rcvd_announce ? "yes" : "no");
+
+	PR("PortAnnounceInformation state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pa_info2str(port_state->pa_info.state));
+	PR("\tExpired announce information                     "
+	   ": %s\n", port_state->pa_info.ann_expired ? "yes" : "no");
+
+	PR("PortAnnounceTransmit state machine variables:\n");
+	PR("\tCurrent state                                    "
+	   ": %s\n", pa_transmit2str(port_state->pa_transmit.state));
+	PR("\tTrigger announce information                     "
+	   ": %s\n", port_state->pa_transmit.ann_trigger ? "yes" : "no");
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+	PR("\nStatistics:\n");
+	PR("Sync %s %s                 : %u\n",
+	   "messages", "received", port_param_ds->rx_sync_count);
+	PR("Follow Up %s %s            : %u\n",
+	   "messages", "received", port_param_ds->rx_fup_count);
+	PR("Path Delay Request %s %s   : %u\n",
+	   "messages", "received", port_param_ds->rx_pdelay_req_count);
+	PR("Path Delay Response %s %s  : %u\n",
+	   "messages", "received", port_param_ds->rx_pdelay_resp_count);
+	PR("Path Delay %s threshold %s : %u\n",
+	   "messages", "exceeded",
+	   port_param_ds->neighbor_prop_delay_exceeded);
+	PR("Path Delay Follow Up %s %s : %u\n",
+	   "messages", "received", port_param_ds->rx_pdelay_resp_fup_count);
+	PR("Announce %s %s             : %u\n",
+	   "messages", "received", port_param_ds->rx_announce_count);
+	PR("ptp %s discarded                 : %u\n",
+	   "messages", port_param_ds->rx_ptp_packet_discard_count);
+	PR("Sync %s %s                 : %u\n",
+	   "reception", "timeout",
+	   port_param_ds->sync_receipt_timeout_count);
+	PR("Announce %s %s             : %u\n",
+	   "reception", "timeout",
+	   port_param_ds->announce_receipt_timeout_count);
+	PR("Path Delay Requests without a response "
+	   ": %u\n",
+	   port_param_ds->pdelay_allowed_lost_resp_exceed_count);
+	PR("Sync %s %s                     : %u\n",
+	   "messages", "sent", port_param_ds->tx_sync_count);
+	PR("Follow Up %s %s                : %u\n",
+	   "messages", "sent", port_param_ds->tx_fup_count);
+	PR("Path Delay Request %s %s       : %u\n",
+	   "messages", "sent", port_param_ds->tx_pdelay_req_count);
+	PR("Path Delay Response %s %s      : %u\n",
+	   "messages", "sent", port_param_ds->tx_pdelay_resp_count);
+	PR("Path Delay Response FUP %s %s  : %u\n",
+	   "messages", "sent", port_param_ds->tx_pdelay_resp_fup_count);
+	PR("Announce %s %s                 : %u\n",
+	   "messages", "sent", port_param_ds->tx_announce_count);
+#endif /* CONFIG_NET_GPTP_STATISTICS */
+}
+#endif /* CONFIG_NET_GPTP */
+
+static int cmd_net_gptp_port(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+#if defined(CONFIG_NET_GPTP)
+	int arg = 1;
+	char *endptr;
+	int port;
+#endif
+
+#if defined(CONFIG_NET_GPTP)
+	if (!argv[arg]) {
+		PR_WARNING("Port number must be given.\n");
+		return -ENOEXEC;
+	}
+
+	port = strtol(argv[arg], &endptr, 10);
+
+	if (*endptr == '\0') {
+		gptp_print_port_info(shell, port);
+	} else {
+		PR_WARNING("Not a valid gPTP port number: %s\n", argv[arg]);
+	}
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_gptp(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_GPTP)
+	/* gPTP status */
+	struct gptp_domain *domain = gptp_get_domain();
+	int count = 0;
+	int arg = 1;
+#endif
+
+#if defined(CONFIG_NET_GPTP)
+	if (argv[arg]) {
+		cmd_net_gptp_port(shell, argc, argv);
+	} else {
+		struct net_shell_user_data user_data;
+
+		user_data.shell = shell;
+		user_data.user_data = &count;
+
+		gptp_foreach_port(gptp_port_cb, &user_data);
+
+		PR("\n");
+
+		PR("SiteSyncSync state machine variables:\n");
+		PR("\tCurrent state                  : %s\n",
+		   site_sync2str(domain->state.site_ss.state));
+		PR("\tA PortSyncSync struct is ready : %s\n",
+		   domain->state.site_ss.rcvd_pss ? "yes" : "no");
+
+		PR("ClockSlaveSync state machine variables:\n");
+		PR("\tCurrent state                  : %s\n",
+		   clk_slave2str(domain->state.clk_slave_sync.state));
+		PR("\tA PortSyncSync struct is ready : %s\n",
+		   domain->state.clk_slave_sync.rcvd_pss ? "yes" : "no");
+		PR("\tThe local clock has expired    : %s\n",
+		   domain->state.clk_slave_sync.rcvd_local_clk_tick ?
+							   "yes" : "no");
+
+		PR("PortRoleSelection state machine variables:\n");
+		PR("\tCurrent state                  : %s\n",
+		   pr_selection2str(domain->state.pr_sel.state));
+
+		PR("ClockMasterSyncReceive state machine variables:\n");
+		PR("\tCurrent state                  : %s\n",
+		   cms_rcv2str(domain->state.clk_master_sync_receive.state));
+		PR("\tA ClockSourceTime              : %s\n",
+		   domain->state.clk_master_sync_receive.rcvd_clock_source_req
+							       ? "yes" : "no");
+		PR("\tThe local clock has expired    : %s\n",
+		   domain->state.clk_master_sync_receive.rcvd_local_clock_tick
+							       ? "yes" : "no");
+	}
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_GPTP", "gPTP");
+#endif
+
+	return 0;
+}
+
+static int get_iface_idx(const struct shell *shell, char *index_str)
+{
+	char *endptr;
+	int idx;
+
+	if (!index_str) {
+		PR_WARNING("Interface index is missing.\n");
+		return -EINVAL;
+	}
+
+	idx = strtol(index_str, &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid index %s\n", index_str);
+		return -ENOENT;
+	}
+
+	if (idx < 0 || idx > 255) {
+		PR_WARNING("Invalid index %d\n", idx);
+		return -ERANGE;
+	}
+
+	return idx;
+}
+
+static int cmd_net_iface_up(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	struct net_if *iface;
+	int idx, ret;
+
+	idx = get_iface_idx(shell, argv[1]);
+	if (idx < 0) {
+		return -ENOEXEC;
+	}
+
+	iface = net_if_get_by_index(idx);
+	if (!iface) {
+		PR_WARNING("No such interface in index %d\n", idx);
+		return -ENOEXEC;
+	}
+
+	if (net_if_is_up(iface)) {
+		PR_WARNING("Interface %d is already up.\n", idx);
+		return -ENOEXEC;
+	}
+
+	ret = net_if_up(iface);
+	if (ret) {
+		PR_WARNING("Cannot take interface %d up (%d)\n", idx, ret);
+		return -ENOEXEC;
+	} else {
+		PR("Interface %d is up\n", idx);
+	}
+
+	return 0;
+}
+
+static int cmd_net_iface_down(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	struct net_if *iface;
+	int idx, ret;
+
+	idx = get_iface_idx(shell, argv[1]);
+	if (idx < 0) {
+		return -ENOEXEC;
+	}
+
+	iface = net_if_get_by_index(idx);
+	if (!iface) {
+		PR_WARNING("No such interface in index %d\n", idx);
+		return -ENOEXEC;
+	}
+
+	ret = net_if_down(iface);
+	if (ret) {
+		PR_WARNING("Cannot take interface %d down (%d)\n", idx, ret);
+		return -ENOEXEC;
+	} else {
+		PR("Interface %d is down\n", idx);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+static uint32_t time_diff(uint32_t time1, uint32_t time2)
+{
+	return (uint32_t)abs((int32_t)time1 - (int32_t)time2);
+}
+
+static void address_lifetime_cb(struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	const char *extra;
+	int i;
+
+	ARG_UNUSED(user_data);
+
+	PR("\nIPv6 addresses for interface %p (%s)\n", iface,
+	       iface2str(iface, &extra));
+	PR("==========================================%s\n", extra);
+
+	if (!ipv6) {
+		PR("No IPv6 config found for this interface.\n");
+		return;
+	}
+
+	PR("Type      \tState    \tLifetime (sec)\tAddress\n");
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		struct net_if_ipv6_prefix *prefix;
+		char remaining_str[sizeof("01234567890")];
+		uint64_t remaining;
+		uint8_t prefix_len;
+
+		if (!ipv6->unicast[i].is_used ||
+		    ipv6->unicast[i].address.family != AF_INET6) {
+			continue;
+		}
+
+		remaining = (uint64_t)ipv6->unicast[i].lifetime.timer_timeout +
+			(uint64_t)ipv6->unicast[i].lifetime.wrap_counter *
+			(uint64_t)NET_TIMEOUT_MAX_VALUE -
+			(uint64_t)time_diff(k_uptime_get_32(),
+				ipv6->unicast[i].lifetime.timer_start);
+
+		prefix = net_if_ipv6_prefix_get(iface,
+					   &ipv6->unicast[i].address.in6_addr);
+		if (prefix) {
+			prefix_len = prefix->len;
+		} else {
+			prefix_len = 128U;
+		}
+
+		if (ipv6->unicast[i].is_infinite) {
+			snprintk(remaining_str, sizeof(remaining_str) - 1,
+				 "infinite");
+		} else {
+			snprintk(remaining_str, sizeof(remaining_str) - 1,
+				 "%u", (uint32_t)(remaining / 1000U));
+		}
+
+		PR("%s  \t%s\t%s    \t%s/%d\n",
+		       addrtype2str(ipv6->unicast[i].addr_type),
+		       addrstate2str(ipv6->unicast[i].addr_state),
+		       remaining_str,
+		       net_sprint_ipv6_addr(
+			       &ipv6->unicast[i].address.in6_addr),
+		       prefix_len);
+	}
+}
+#endif /* CONFIG_NET_NATIVE_IPV6 */
+
+static int cmd_net_ipv6(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	struct net_shell_user_data user_data;
+#endif
+
+	PR("IPv6 support                              : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6) ?
+	   "enabled" : "disabled");
+	if (!IS_ENABLED(CONFIG_NET_IPV6)) {
+		return -ENOEXEC;
+	}
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+	PR("IPv6 fragmentation support                : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_FRAGMENT) ? "enabled" :
+	   "disabled");
+	PR("Multicast Listener Discovery support      : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_MLD) ? "enabled" :
+	   "disabled");
+	PR("Neighbor cache support                    : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_NBR_CACHE) ? "enabled" :
+	   "disabled");
+	PR("Neighbor discovery support                : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_ND) ? "enabled" :
+	   "disabled");
+	PR("Duplicate address detection (DAD) support : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_DAD) ? "enabled" :
+	   "disabled");
+	PR("Router advertisement RDNSS option support : %s\n",
+	   IS_ENABLED(CONFIG_NET_IPV6_RA_RDNSS) ? "enabled" :
+	   "disabled");
+	PR("6lo header compression support            : %s\n",
+	   IS_ENABLED(CONFIG_NET_6LO) ? "enabled" :
+	   "disabled");
+
+	if (IS_ENABLED(CONFIG_NET_6LO_CONTEXT)) {
+		PR("6lo context based compression "
+		   "support     : %s\n",
+		   IS_ENABLED(CONFIG_NET_6LO_CONTEXT) ? "enabled" :
+		   "disabled");
+	}
+
+	PR("Max number of IPv6 network interfaces "
+	   "in the system          : %d\n",
+	   CONFIG_NET_IF_MAX_IPV6_COUNT);
+	PR("Max number of unicast IPv6 addresses "
+	   "per network interface   : %d\n",
+	   CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT);
+	PR("Max number of multicast IPv6 addresses "
+	   "per network interface : %d\n",
+	   CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT);
+	PR("Max number of IPv6 prefixes per network "
+	   "interface            : %d\n",
+	   CONFIG_NET_IF_IPV6_PREFIX_COUNT);
+
+	user_data.shell = shell;
+	user_data.user_data = NULL;
+
+	/* Print information about address lifetime */
+	net_if_foreach(address_lifetime_cb, &user_data);
+#endif
+
+	return 0;
+}
+
+static int cmd_net_iface(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct net_if *iface = NULL;
+	struct net_shell_user_data user_data;
+	int idx;
+
+	if (argv[1]) {
+		idx = get_iface_idx(shell, argv[1]);
+		if (idx < 0) {
+			return -ENOEXEC;
+		}
+
+		iface = net_if_get_by_index(idx);
+		if (!iface) {
+			PR_WARNING("No such interface in index %d\n", idx);
+			return -ENOEXEC;
+		}
+	}
+
+#if defined(CONFIG_NET_HOSTNAME_ENABLE)
+	PR("Hostname: %s\n\n", net_hostname_get());
+#endif
+
+	user_data.shell = shell;
+	user_data.user_data = iface;
+
+	net_if_foreach(iface_cb, &user_data);
+
+	return 0;
+}
+
+struct ctx_info {
+	int pos;
+	bool are_external_pools;
+	struct k_mem_slab *tx_slabs[CONFIG_NET_MAX_CONTEXTS];
+	struct net_buf_pool *data_pools[CONFIG_NET_MAX_CONTEXTS];
+};
+
+#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+static bool slab_pool_found_already(struct ctx_info *info,
+				    struct k_mem_slab *slab,
+				    struct net_buf_pool *pool)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_CONTEXTS; i++) {
+		if (slab) {
+			if (info->tx_slabs[i] == slab) {
+				return true;
+			}
+		} else {
+			if (info->data_pools[i] == pool) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+#endif
+
+static void context_info(struct net_context *context, void *user_data)
+{
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	struct ctx_info *info = data->user_data;
+	struct k_mem_slab *slab;
+	struct net_buf_pool *pool;
+
+	if (!net_context_is_used(context)) {
+		return;
+	}
+
+	if (context->tx_slab) {
+		slab = context->tx_slab();
+
+		if (slab_pool_found_already(info, slab, NULL)) {
+			return;
+		}
+
+#if CONFIG_NET_PKT_LOG_LEVEL >= LOG_LEVEL_DBG
+		PR("%p\t%u\t%u\tETX\n",
+		   slab, slab->num_blocks, k_mem_slab_num_free_get(slab));
+#else
+		PR("%p\t%d\tETX\n", slab, slab->num_blocks);
+#endif
+		info->are_external_pools = true;
+		info->tx_slabs[info->pos] = slab;
+	}
+
+	if (context->data_pool) {
+		pool = context->data_pool();
+
+		if (slab_pool_found_already(info, NULL, pool)) {
+			return;
+		}
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+		PR("%p\t%d\t%d\tEDATA (%s)\n",
+		   pool, pool->buf_count,
+		   pool->avail_count, pool->name);
+#else
+		PR("%p\t%d\tEDATA\n", pool, pool->buf_count);
+#endif
+		info->are_external_pools = true;
+		info->data_pools[info->pos] = pool;
+	}
+
+	info->pos++;
+#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
+}
+#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
+
+static int cmd_net_mem(const struct shell *shell, size_t argc, char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_NATIVE)
+	struct k_mem_slab *rx, *tx;
+	struct net_buf_pool *rx_data, *tx_data;
+
+	net_pkt_get_info(&rx, &tx, &rx_data, &tx_data);
+
+	PR("Fragment length %d bytes\n", CONFIG_NET_BUF_DATA_SIZE);
+
+	PR("Network buffer pools:\n");
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	PR("Address\t\tTotal\tAvail\tName\n");
+
+	PR("%p\t%d\t%u\tRX\n",
+	       rx, rx->num_blocks, k_mem_slab_num_free_get(rx));
+
+	PR("%p\t%d\t%u\tTX\n",
+	       tx, tx->num_blocks, k_mem_slab_num_free_get(tx));
+
+	PR("%p\t%d\t%d\tRX DATA (%s)\n",
+	       rx_data, rx_data->buf_count,
+	       rx_data->avail_count, rx_data->name);
+
+	PR("%p\t%d\t%d\tTX DATA (%s)\n",
+	       tx_data, tx_data->buf_count,
+	       tx_data->avail_count, tx_data->name);
+#else
+	PR("Address\t\tTotal\tName\n");
+
+	PR("%p\t%d\tRX\n", rx, rx->num_blocks);
+	PR("%p\t%d\tTX\n", tx, tx->num_blocks);
+	PR("%p\t%d\tRX DATA\n", rx_data, rx_data->buf_count);
+	PR("%p\t%d\tTX DATA\n", tx_data, tx_data->buf_count);
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_BUF_POOL_USAGE", "net_buf allocation");
+#endif /* CONFIG_NET_BUF_POOL_USAGE */
+
+	if (IS_ENABLED(CONFIG_NET_CONTEXT_NET_PKT_POOL)) {
+		struct net_shell_user_data user_data;
+		struct ctx_info info;
+
+		(void)memset(&info, 0, sizeof(info));
+
+		user_data.shell = shell;
+		user_data.user_data = &info;
+
+		net_context_foreach(context_info, &user_data);
+
+		if (!info.are_external_pools) {
+			PR("No external memory pools found.\n");
+		}
+	}
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_OFFLOAD or CONFIG_NET_NATIVE", "memory usage");
+#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_NATIVE */
+
+	return 0;
+}
+
+static int cmd_net_nbr_rm(const struct shell *shell, size_t argc,
+			  char *argv[])
+{
+#if defined(CONFIG_NET_IPV6)
+	struct in6_addr addr;
+	int ret;
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+	if (!argv[1]) {
+		PR_WARNING("Neighbor IPv6 address missing.\n");
+		return -ENOEXEC;
+	}
+
+	ret = net_addr_pton(AF_INET6, argv[1], &addr);
+	if (ret < 0) {
+		PR_WARNING("Cannot parse '%s'\n", argv[1]);
+		return -ENOEXEC;
+	}
+
+	if (!net_ipv6_nbr_rm(NULL, &addr)) {
+		PR_WARNING("Cannot remove neighbor %s\n",
+			   net_sprint_ipv6_addr(&addr));
+		return -ENOEXEC;
+	} else {
+		PR("Neighbor %s removed.\n", net_sprint_ipv6_addr(&addr));
+	}
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("IPv6 not enabled.\n");
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_IPV6)
+static void nbr_cb(struct net_nbr *nbr, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	char *padding = "";
+	char *state_pad = "";
+	const char *state_str;
+#if defined(CONFIG_NET_IPV6_ND)
+	int64_t remaining;
+#endif
+
+#if defined(CONFIG_NET_L2_IEEE802154)
+	padding = "      ";
+#endif
+
+	if (*count == 0) {
+		PR("     Neighbor   Interface        Flags State     "
+		   "Remain  Link              %sAddress\n", padding);
+	}
+
+	(*count)++;
+
+	state_str = net_ipv6_nbr_state2str(net_ipv6_nbr_data(nbr)->state);
+
+	/* This is not a proper way but the minimal libc does not honor
+	 * string lengths in %s modifier so in order the output to look
+	 * nice, do it like this.
+	 */
+	if (strlen(state_str) == 5) {
+		state_pad = "    ";
+	}
+
+#if defined(CONFIG_NET_IPV6_ND)
+	remaining = net_ipv6_nbr_data(nbr)->reachable +
+		    net_ipv6_nbr_data(nbr)->reachable_timeout -
+		    k_uptime_get();
+#endif
+
+	PR("[%2d] %p %p %5d/%d/%d/%d %s%s %6d  %17s%s %s\n",
+	   *count, nbr, nbr->iface,
+	   net_ipv6_nbr_data(nbr)->link_metric,
+	   nbr->ref,
+	   net_ipv6_nbr_data(nbr)->ns_count,
+	   net_ipv6_nbr_data(nbr)->is_router,
+	   state_str,
+	   state_pad,
+#if defined(CONFIG_NET_IPV6_ND)
+	   (int)(remaining > 0 ? remaining : 0),
+#else
+	   0,
+#endif
+	   nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
+	   net_sprint_ll_addr(
+		   net_nbr_get_lladdr(nbr->idx)->addr,
+		   net_nbr_get_lladdr(nbr->idx)->len),
+	   net_nbr_get_lladdr(nbr->idx)->len == 8U ? "" : padding,
+	   net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr));
+}
+#endif
+
+static int cmd_net_nbr(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_IPV6)
+	int count = 0;
+	struct net_shell_user_data user_data;
+#endif
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_IPV6)
+	user_data.shell = shell;
+	user_data.user_data = &count;
+
+	net_ipv6_nbr_foreach(nbr_cb, &user_data);
+
+	if (count == 0) {
+		PR("No neighbors.\n");
+	}
+#else
+	PR_INFO("IPv6 not enabled.\n");
+#endif /* CONFIG_NET_IPV6 */
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
+
+K_SEM_DEFINE(ping_timeout, 0, 1);
+static const struct shell *shell_for_ping;
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+
+static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt,
+						struct net_ipv6_hdr *ip_hdr,
+						struct net_icmp_hdr *icmp_hdr);
+
+static struct net_icmpv6_handler ping6_handler = {
+	.type = NET_ICMPV6_ECHO_REPLY,
+	.code = 0,
+	.handler = handle_ipv6_echo_reply,
+};
+
+static inline void remove_ipv6_ping_handler(void)
+{
+	net_icmpv6_unregister_handler(&ping6_handler);
+}
+
+static enum net_verdict handle_ipv6_echo_reply(struct net_pkt *pkt,
+					       struct net_ipv6_hdr *ip_hdr,
+					       struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmpv6_echo_req);
+	struct net_icmpv6_echo_req *icmp_echo;
+	uint32_t cycles;
+
+	icmp_echo = (struct net_icmpv6_echo_req *)net_pkt_get_data(pkt,
+								&icmp_access);
+	if (icmp_echo == NULL) {
+		return -NET_DROP;
+	}
+
+	net_pkt_skip(pkt, sizeof(*icmp_echo));
+	if (net_pkt_read_be32(pkt, &cycles)) {
+		return -NET_DROP;
+	}
+
+	cycles = k_cycle_get_32() - cycles;
+
+	PR_SHELL(shell_for_ping, "%d bytes from %s to %s: icmp_seq=%d ttl=%d "
+#ifdef CONFIG_IEEE802154
+		 "rssi=%d "
+#endif
+#ifdef CONFIG_FPU
+		 "time=%.2f ms\n",
+#else
+		 "time=%d ms\n",
+#endif
+		 ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) -
+								NET_ICMPH_LEN,
+		 net_sprint_ipv6_addr(&ip_hdr->src),
+		 net_sprint_ipv6_addr(&ip_hdr->dst),
+		 ntohs(icmp_echo->sequence),
+		 ip_hdr->hop_limit,
+#ifdef CONFIG_IEEE802154
+		 net_pkt_ieee802154_rssi(pkt),
+#endif
+#ifdef CONFIG_FPU
+		 ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f));
+#else
+		 ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000));
+#endif
+	k_sem_give(&ping_timeout);
+
+	net_pkt_unref(pkt);
+	return NET_OK;
+}
+
+static int ping_ipv6(const struct shell *shell,
+		     char *host,
+		     unsigned int count,
+		     unsigned int interval,
+		     int iface_idx)
+{
+	struct net_if *iface = net_if_get_by_index(iface_idx);
+	int ret = 0;
+	struct in6_addr ipv6_target;
+	struct net_nbr *nbr;
+
+#if defined(CONFIG_NET_ROUTE)
+	struct net_route_entry *route;
+#endif
+
+	if (net_addr_pton(AF_INET6, host, &ipv6_target) < 0) {
+		return -EINVAL;
+	}
+
+	net_icmpv6_register_handler(&ping6_handler);
+
+	if (!iface) {
+		iface = net_if_ipv6_select_src_iface(&ipv6_target);
+		if (!iface) {
+			nbr = net_ipv6_nbr_lookup(NULL, &ipv6_target);
+			if (nbr) {
+				iface = nbr->iface;
+			} else {
+				iface = net_if_get_default();
+			}
+		}
+	}
+
+#if defined(CONFIG_NET_ROUTE)
+	route = net_route_lookup(NULL, &ipv6_target);
+	if (route) {
+		iface = route->iface;
+	}
+#endif
+
+	PR("PING %s\n", host);
+
+	for (int i = 0; i < count; ++i) {
+		uint32_t time_stamp = htonl(k_cycle_get_32());
+
+		ret = net_icmpv6_send_echo_request(iface,
+						   &ipv6_target,
+						   sys_rand32_get(),
+						   i,
+						   &time_stamp,
+						   sizeof(time_stamp));
+		if (ret) {
+			break;
+		}
+
+		k_msleep(interval);
+	}
+
+	remove_ipv6_ping_handler();
+
+	return ret;
+}
+#else
+#define ping_ipv6(...) -ENOTSUP
+#define remove_ipv6_ping_handler()
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_NATIVE_IPV4)
+
+static enum net_verdict handle_ipv4_echo_reply(struct net_pkt *pkt,
+					       struct net_ipv4_hdr *ip_hdr,
+					       struct net_icmp_hdr *icmp_hdr);
+
+static struct net_icmpv4_handler ping4_handler = {
+	.type = NET_ICMPV4_ECHO_REPLY,
+	.code = 0,
+	.handler = handle_ipv4_echo_reply,
+};
+
+static inline void remove_ipv4_ping_handler(void)
+{
+	net_icmpv4_unregister_handler(&ping4_handler);
+}
+
+static enum net_verdict handle_ipv4_echo_reply(struct net_pkt *pkt,
+					       struct net_ipv4_hdr *ip_hdr,
+					       struct net_icmp_hdr *icmp_hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access,
+					      struct net_icmpv4_echo_req);
+	uint32_t cycles;
+	struct net_icmpv4_echo_req *icmp_echo;
+
+	icmp_echo = (struct net_icmpv4_echo_req *)net_pkt_get_data(pkt,
+								&icmp_access);
+	if (icmp_echo == NULL) {
+		return -NET_DROP;
+	}
+
+	net_pkt_skip(pkt, sizeof(*icmp_echo));
+	if (net_pkt_read_be32(pkt, &cycles)) {
+		return -NET_DROP;
+	}
+
+	cycles = k_cycle_get_32() - cycles;
+
+	PR_SHELL(shell_for_ping, "%d bytes from %s to %s: icmp_seq=%d ttl=%d "
+#ifdef CONFIG_FPU
+		 "time=%.2f ms\n",
+#else
+		 "time=%d ms\n",
+#endif
+		 ntohs(ip_hdr->len) - net_pkt_ipv6_ext_len(pkt) -
+								NET_ICMPH_LEN,
+		 net_sprint_ipv4_addr(&ip_hdr->src),
+		 net_sprint_ipv4_addr(&ip_hdr->dst),
+		 ntohs(icmp_echo->sequence),
+		 ip_hdr->ttl,
+#ifdef CONFIG_FPU
+		 ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000.f));
+#else
+		 ((uint32_t)k_cyc_to_ns_floor64(cycles) / 1000000));
+#endif
+	k_sem_give(&ping_timeout);
+
+	net_pkt_unref(pkt);
+	return NET_OK;
+}
+
+static int ping_ipv4(const struct shell *shell,
+		     char *host,
+		     unsigned int count,
+		     unsigned int interval,
+		     int iface_idx)
+{
+	struct in_addr ipv4_target;
+	struct net_if *iface = net_if_get_by_index(iface_idx);
+	int ret = 0;
+
+	if (net_addr_pton(AF_INET, host, &ipv4_target) < 0) {
+		return -EINVAL;
+	}
+
+	if (!iface) {
+		iface = net_if_ipv4_select_src_iface(&ipv4_target);
+	}
+
+	net_icmpv4_register_handler(&ping4_handler);
+
+	PR("PING %s\n", host);
+
+	for (int i = 0; i < count; ++i) {
+		uint32_t time_stamp = htonl(k_cycle_get_32());
+
+		ret = net_icmpv4_send_echo_request(iface,
+						   &ipv4_target,
+						   sys_rand32_get(),
+						   i,
+						   &time_stamp,
+						   sizeof(time_stamp));
+		if (ret) {
+			break;
+		}
+
+		k_msleep(interval);
+	}
+
+	remove_ipv4_ping_handler();
+
+	return ret;
+}
+#else
+#define ping_ipv4(...) -ENOTSUP
+#define remove_ipv4_ping_handler()
+#endif /* CONFIG_NET_IPV4 */
+
+static int parse_arg(size_t *i, size_t argc, char *argv[])
+{
+	int res = -1;
+	const char *str = argv[*i] + 2;
+	char *endptr;
+
+	if (*str == 0) {
+		if (*i + 1 >= argc) {
+			return -1;
+		}
+
+		*i += 1;
+		str = argv[*i];
+	}
+
+	res = strtol(str, &endptr, 10);
+
+	if (errno || (endptr == str)) {
+		return -1;
+	}
+
+	return res;
+}
+#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
+
+static int cmd_net_ping(const struct shell *shell, size_t argc, char *argv[])
+{
+#if !defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
+	ARG_UNUSED(shell);
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	return -EOPNOTSUPP;
+#else
+	char *host = NULL;
+	int ret;
+
+	int count = 3;
+	int interval = 1000;
+	int iface_idx = -1;
+
+	for (size_t i = 1; i < argc; ++i) {
+
+		if (*argv[i] != '-') {
+			host = argv[i];
+			continue;
+		}
+
+		switch (argv[i][1]) {
+		case 'c':
+			count = parse_arg(&i, argc, argv);
+			if (count < 0) {
+				PR_WARNING("Parse error: %s\n", argv[i]);
+				return -ENOEXEC;
+			}
+
+
+			break;
+		case 'i':
+			interval = parse_arg(&i, argc, argv);
+			if (interval < 0) {
+				PR_WARNING("Parse error: %s\n", argv[i]);
+				return -ENOEXEC;
+			}
+
+			break;
+
+		case 'I':
+			iface_idx = parse_arg(&i, argc, argv);
+			if (iface_idx < 0 || !net_if_get_by_index(iface_idx)) {
+				PR_WARNING("Parse error: %s\n", argv[i]);
+				return -ENOEXEC;
+			}
+			break;
+		default:
+			PR_WARNING("Unrecognized argument: %s\n", argv[i]);
+			return -ENOEXEC;
+		}
+	}
+
+	if (!host) {
+		PR_WARNING("Target host missing\n");
+		return -ENOEXEC;
+	}
+
+	shell_for_ping = shell;
+
+	if (IS_ENABLED(CONFIG_NET_IPV6)) {
+		ret = ping_ipv6(shell, host, count, interval, iface_idx);
+		if (!ret) {
+			goto wait_reply;
+		} else if (ret == -EIO) {
+			PR_WARNING("Cannot send IPv6 ping\n");
+			return -ENOEXEC;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4)) {
+		ret = ping_ipv4(shell, host, count, interval, iface_idx);
+		if (ret) {
+			if (ret == -EIO || ret == -ENETUNREACH) {
+				PR_WARNING("Cannot send IPv4 ping\n");
+			} else if (ret == -EINVAL) {
+				PR_WARNING("Invalid IP address\n");
+			}
+
+			return -ENOEXEC;
+		}
+	}
+
+wait_reply:
+	ret = k_sem_take(&ping_timeout, K_SECONDS(2));
+	if (ret == -EAGAIN) {
+		PR_INFO("Ping timeout\n");
+		remove_ipv6_ping_handler();
+		remove_ipv4_ping_handler();
+
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+#endif
+}
+
+static struct net_pkt *get_net_pkt(const char *ptr_str)
+{
+	uint8_t buf[sizeof(intptr_t)];
+	intptr_t ptr = 0;
+	size_t len;
+	int i;
+
+	if (ptr_str[0] == '0' && ptr_str[1] == 'x') {
+		ptr_str += 2;
+	}
+
+	len = hex2bin(ptr_str, strlen(ptr_str), buf, sizeof(buf));
+	if (!len) {
+		return NULL;
+	}
+
+	for (i = len - 1; i >= 0; i--) {
+		ptr |= buf[i] << 8 * (len - 1 - i);
+	}
+
+	return (struct net_pkt *)ptr;
+}
+
+static void net_pkt_buffer_info(const struct shell *shell, struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->buffer;
+
+	PR("net_pkt %p buffer chain:\n", pkt);
+	PR("%p[%d]", pkt, atomic_get(&pkt->atomic_ref));
+
+	if (buf) {
+		PR("->");
+	}
+
+	while (buf) {
+		PR("%p[%d/%u (%u)]",
+		   buf, atomic_get(&pkt->atomic_ref), buf->len, buf->size);
+
+		buf = buf->frags;
+		if (buf) {
+			PR("->");
+		}
+	}
+
+	PR("\n");
+}
+
+static void net_pkt_buffer_hexdump(const struct shell *shell,
+				   struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->buffer;
+	int i = 0;
+
+	if (!buf || buf->ref == 0) {
+		return;
+	}
+
+	PR("net_pkt %p buffer chain hexdump:\n", pkt);
+
+	while (buf) {
+		PR("net_buf[%d] %p\n", i++, buf);
+		shell_hexdump(shell, buf->data, buf->len);
+		buf = buf->frags;
+	}
+}
+
+static int cmd_net_pkt(const struct shell *shell, size_t argc, char *argv[])
+{
+	if (argv[1]) {
+		struct net_pkt *pkt;
+
+		pkt = get_net_pkt(argv[1]);
+		if (!pkt) {
+			PR_ERROR("Invalid ptr value (%s). "
+				 "Example: 0x01020304\n", argv[1]);
+			return -ENOEXEC;
+		}
+
+		net_pkt_buffer_info(shell, pkt);
+		PR("\n");
+		net_pkt_buffer_hexdump(shell, pkt);
+	} else {
+		PR_INFO("Pointer value must be given.\n");
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
+static int cmd_net_ppp_ping(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+#if defined(CONFIG_NET_PPP)
+	if (argv[1]) {
+		int ret, idx = get_iface_idx(shell, argv[1]);
+
+		if (idx < 0) {
+			return -ENOEXEC;
+		}
+
+		ret = net_ppp_ping(idx, MSEC_PER_SEC * 1);
+		if (ret < 0) {
+			if (ret == -EAGAIN) {
+				PR_INFO("PPP Echo-Req timeout.\n");
+			} else if (ret == -ENODEV || ret == -ENOENT) {
+				PR_INFO("Not a PPP interface (%d)\n", idx);
+			} else {
+				PR_INFO("PPP Echo-Req failed (%d)\n", ret);
+			}
+		} else {
+			if (ret > 1000) {
+				PR_INFO("%s%d msec\n",
+					"Received PPP Echo-Reply in ",
+					ret / 1000);
+			} else {
+				PR_INFO("%s%d usec\n",
+					"Received PPP Echo-Reply in ", ret);
+			}
+		}
+	} else {
+		PR_INFO("PPP network interface must be given.\n");
+		return -ENOEXEC;
+	}
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_L2_PPP", "PPP");
+#endif
+	return 0;
+}
+
+static int cmd_net_ppp_status(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+#if defined(CONFIG_NET_PPP)
+	int idx = 0;
+	struct ppp_context *ctx;
+
+	if (argv[1]) {
+		idx = get_iface_idx(shell, argv[1]);
+		if (idx < 0) {
+			return -ENOEXEC;
+		}
+	}
+
+	ctx = net_ppp_context_get(idx);
+	if (!ctx) {
+		PR_INFO("PPP context not found.\n");
+		return -ENOEXEC;
+	}
+
+	PR("PPP phase           : %s (%d)\n", ppp_phase_str(ctx->phase),
+								ctx->phase);
+	PR("LCP state           : %s (%d)\n",
+	   ppp_state_str(ctx->lcp.fsm.state), ctx->lcp.fsm.state);
+	PR("LCP retransmits     : %u\n", ctx->lcp.fsm.retransmits);
+	PR("LCP NACK loops      : %u\n", ctx->lcp.fsm.nack_loops);
+	PR("LCP NACKs recv      : %u\n", ctx->lcp.fsm.recv_nack_loops);
+	PR("LCP current id      : %d\n", ctx->lcp.fsm.id);
+	PR("LCP ACK received    : %s\n", ctx->lcp.fsm.ack_received ?
+								"yes" : "no");
+
+#if defined(CONFIG_NET_IPV4)
+	PR("IPCP state          : %s (%d)\n",
+	   ppp_state_str(ctx->ipcp.fsm.state), ctx->ipcp.fsm.state);
+	PR("IPCP retransmits    : %u\n", ctx->ipcp.fsm.retransmits);
+	PR("IPCP NACK loops     : %u\n", ctx->ipcp.fsm.nack_loops);
+	PR("IPCP NACKs recv     : %u\n", ctx->ipcp.fsm.recv_nack_loops);
+	PR("IPCP current id     : %d\n", ctx->ipcp.fsm.id);
+	PR("IPCP ACK received   : %s\n", ctx->ipcp.fsm.ack_received ?
+								"yes" : "no");
+#endif /* CONFIG_NET_IPV4 */
+
+#if defined(CONFIG_NET_IPV6)
+	PR("IPv6CP state        : %s (%d)\n",
+	   ppp_state_str(ctx->ipv6cp.fsm.state), ctx->ipv6cp.fsm.state);
+	PR("IPv6CP retransmits  : %u\n", ctx->ipv6cp.fsm.retransmits);
+	PR("IPv6CP NACK loops   : %u\n", ctx->ipv6cp.fsm.nack_loops);
+	PR("IPv6CP NACKs recv   : %u\n", ctx->ipv6cp.fsm.recv_nack_loops);
+	PR("IPv6CP current id   : %d\n", ctx->ipv6cp.fsm.id);
+	PR("IPv6CP ACK received : %s\n", ctx->ipv6cp.fsm.ack_received ?
+								"yes" : "no");
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_L2_PPP_PAP)
+	PR("PAP state           : %s (%d)\n",
+	   ppp_state_str(ctx->pap.fsm.state), ctx->pap.fsm.state);
+	PR("PAP retransmits     : %u\n", ctx->pap.fsm.retransmits);
+	PR("PAP NACK loops      : %u\n", ctx->pap.fsm.nack_loops);
+	PR("PAP NACKs recv      : %u\n", ctx->pap.fsm.recv_nack_loops);
+	PR("PAP current id      : %d\n", ctx->pap.fsm.id);
+	PR("PAP ACK received    : %s\n", ctx->pap.fsm.ack_received ?
+								"yes" : "no");
+#endif /* CONFIG_NET_L2_PPP_PAP */
+
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_L2_PPP and CONFIG_NET_PPP", "PPP");
+#endif
+	return 0;
+}
+
+static int cmd_net_route(const struct shell *shell, size_t argc, char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+#if defined(CONFIG_NET_NATIVE)
+#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST)
+	struct net_shell_user_data user_data;
+#endif
+
+#if defined(CONFIG_NET_ROUTE) || defined(CONFIG_NET_ROUTE_MCAST)
+	user_data.shell = shell;
+#endif
+
+#if defined(CONFIG_NET_ROUTE)
+	net_if_foreach(iface_per_route_cb, &user_data);
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_ROUTE",
+		"network route");
+#endif
+
+#if defined(CONFIG_NET_ROUTE_MCAST)
+	net_if_foreach(iface_per_mcast_route_cb, &user_data);
+#endif
+#endif
+	return 0;
+}
+
+static int cmd_net_stacks(const struct shell *shell, size_t argc,
+			  char *argv[])
+{
+#if !defined(CONFIG_KERNEL_SHELL)
+	PR("Enable CONFIG_KERNEL_SHELL and type \"kernel stacks\" to see stack information.\n");
+#else
+	PR("Type \"kernel stacks\" to see stack information.\n");
+#endif
+	return 0;
+}
+
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+static void net_shell_print_statistics_all(struct net_shell_user_data *data)
+{
+	net_if_foreach(net_shell_print_statistics, data);
+}
+#endif
+
+static int cmd_net_stats_all(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+#if defined(CONFIG_NET_STATISTICS)
+	struct net_shell_user_data user_data;
+#endif
+
+#if defined(CONFIG_NET_STATISTICS)
+	user_data.shell = shell;
+
+	/* Print global network statistics */
+	net_shell_print_statistics_all(&user_data);
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
+		"statistics");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_stats_iface(const struct shell *shell, size_t argc,
+			       char *argv[])
+{
+#if defined(CONFIG_NET_STATISTICS)
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+	struct net_shell_user_data data;
+	struct net_if *iface;
+	char *endptr;
+	int idx;
+#endif
+#endif
+
+#if defined(CONFIG_NET_STATISTICS)
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+	idx = strtol(argv[1], &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid index %s\n", argv[1]);
+		return -ENOEXEC;
+	}
+
+	iface = net_if_get_by_index(idx);
+	if (!iface) {
+		PR_WARNING("No such interface in index %d\n", idx);
+		return -ENOEXEC;
+	}
+
+	data.shell = shell;
+
+	net_shell_print_statistics(iface, &data);
+#else
+	PR_INFO("Per network interface statistics not collected.\n");
+	PR_INFO("Please enable CONFIG_NET_STATISTICS_PER_INTERFACE\n");
+#endif /* CONFIG_NET_STATISTICS_PER_INTERFACE */
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
+		"statistics");
+#endif
+
+	return 0;
+}
+
+static int cmd_net_stats(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_STATISTICS)
+	if (!argv[1]) {
+		cmd_net_stats_all(shell, argc, argv);
+		return 0;
+	}
+
+	if (strcmp(argv[1], "reset") == 0) {
+		net_stats_reset(NULL);
+	} else {
+		cmd_net_stats_iface(shell, argc, argv);
+	}
+#else
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_STATISTICS",
+		"statistics");
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+static struct net_context *tcp_ctx;
+static const struct shell *tcp_shell;
+
+#define TCP_CONNECT_TIMEOUT K_SECONDS(5) /* ms */
+#define TCP_TIMEOUT K_SECONDS(2) /* ms */
+
+static void tcp_connected(struct net_context *context,
+			  int status,
+			  void *user_data)
+{
+	if (status < 0) {
+		PR_SHELL(tcp_shell, "TCP connection failed (%d)\n", status);
+
+		net_context_put(context);
+
+		tcp_ctx = NULL;
+	} else {
+		PR_SHELL(tcp_shell, "TCP connected\n");
+	}
+}
+
+static void get_my_ipv6_addr(struct net_if *iface,
+			     struct sockaddr *myaddr)
+{
+#if defined(CONFIG_NET_IPV6)
+	const struct in6_addr *my6addr;
+
+	my6addr = net_if_ipv6_select_src_addr(iface,
+					      &net_sin6(myaddr)->sin6_addr);
+
+	memcpy(&net_sin6(myaddr)->sin6_addr, my6addr, sizeof(struct in6_addr));
+
+	net_sin6(myaddr)->sin6_port = 0U; /* let the IP stack to select */
+#endif
+}
+
+static void get_my_ipv4_addr(struct net_if *iface,
+			     struct sockaddr *myaddr)
+{
+#if defined(CONFIG_NET_NATIVE_IPV4)
+	/* Just take the first IPv4 address of an interface. */
+	memcpy(&net_sin(myaddr)->sin_addr,
+	       &iface->config.ip.ipv4->unicast[0].address.in_addr,
+	       sizeof(struct in_addr));
+
+	net_sin(myaddr)->sin_port = 0U; /* let the IP stack to select */
+#endif
+}
+
+static void print_connect_info(const struct shell *shell,
+			       int family,
+			       struct sockaddr *myaddr,
+			       struct sockaddr *addr)
+{
+	switch (family) {
+	case AF_INET:
+		if (IS_ENABLED(CONFIG_NET_IPV4)) {
+			PR("Connecting from %s:%u ",
+			   net_sprint_ipv4_addr(&net_sin(myaddr)->sin_addr),
+			   ntohs(net_sin(myaddr)->sin_port));
+			PR("to %s:%u\n",
+			   net_sprint_ipv4_addr(&net_sin(addr)->sin_addr),
+			   ntohs(net_sin(addr)->sin_port));
+		} else {
+			PR_INFO("IPv4 not supported\n");
+		}
+
+		break;
+
+	case AF_INET6:
+		if (IS_ENABLED(CONFIG_NET_IPV6)) {
+			PR("Connecting from [%s]:%u ",
+			   net_sprint_ipv6_addr(&net_sin6(myaddr)->sin6_addr),
+			   ntohs(net_sin6(myaddr)->sin6_port));
+			PR("to [%s]:%u\n",
+			   net_sprint_ipv6_addr(&net_sin6(addr)->sin6_addr),
+			   ntohs(net_sin6(addr)->sin6_port));
+		} else {
+			PR_INFO("IPv6 not supported\n");
+		}
+
+		break;
+
+	default:
+		PR_WARNING("Unknown protocol family (%d)\n", family);
+		break;
+	}
+}
+
+static void tcp_connect(const struct shell *shell, char *host, uint16_t port,
+			struct net_context **ctx)
+{
+	struct net_if *iface = net_if_get_default();
+	struct sockaddr myaddr;
+	struct sockaddr addr;
+	struct net_nbr *nbr;
+	int addrlen;
+	int family;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && !IS_ENABLED(CONFIG_NET_IPV4)) {
+		ret = net_addr_pton(AF_INET6, host,
+				    &net_sin6(&addr)->sin6_addr);
+		if (ret < 0) {
+			PR_WARNING("Invalid IPv6 address\n");
+			return;
+		}
+
+		net_sin6(&addr)->sin6_port = htons(port);
+		addrlen = sizeof(struct sockaddr_in6);
+
+		nbr = net_ipv6_nbr_lookup(NULL, &net_sin6(&addr)->sin6_addr);
+		if (nbr) {
+			iface = nbr->iface;
+		}
+
+		get_my_ipv6_addr(iface, &myaddr);
+		family = addr.sa_family = myaddr.sa_family = AF_INET6;
+
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   !IS_ENABLED(CONFIG_NET_IPV6)) {
+		ARG_UNUSED(nbr);
+
+		ret = net_addr_pton(AF_INET, host, &net_sin(&addr)->sin_addr);
+		if (ret < 0) {
+			PR_WARNING("Invalid IPv4 address\n");
+			return;
+		}
+
+		get_my_ipv4_addr(iface, &myaddr);
+		net_sin(&addr)->sin_port = htons(port);
+		addrlen = sizeof(struct sockaddr_in);
+		family = addr.sa_family = myaddr.sa_family = AF_INET;
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   IS_ENABLED(CONFIG_NET_IPV4)) {
+		ret = net_addr_pton(AF_INET6, host,
+				    &net_sin6(&addr)->sin6_addr);
+		if (ret < 0) {
+			ret = net_addr_pton(AF_INET, host,
+					    &net_sin(&addr)->sin_addr);
+			if (ret < 0) {
+				PR_WARNING("Invalid IP address\n");
+				return;
+			}
+
+			net_sin(&addr)->sin_port = htons(port);
+			addrlen = sizeof(struct sockaddr_in);
+
+			get_my_ipv4_addr(iface, &myaddr);
+			family = addr.sa_family = myaddr.sa_family = AF_INET;
+		} else {
+			net_sin6(&addr)->sin6_port = htons(port);
+			addrlen = sizeof(struct sockaddr_in6);
+
+			nbr = net_ipv6_nbr_lookup(NULL,
+						  &net_sin6(&addr)->sin6_addr);
+			if (nbr) {
+				iface = nbr->iface;
+			}
+
+			get_my_ipv6_addr(iface, &myaddr);
+			family = addr.sa_family = myaddr.sa_family = AF_INET6;
+		}
+	} else {
+		PR_WARNING("No IPv6 nor IPv4 is enabled\n");
+		return;
+	}
+
+	print_connect_info(shell, family, &myaddr, &addr);
+
+	ret = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, ctx);
+	if (ret < 0) {
+		PR_WARNING("Cannot get TCP context (%d)\n", ret);
+		return;
+	}
+
+	ret = net_context_bind(*ctx, &myaddr, addrlen);
+	if (ret < 0) {
+		PR_WARNING("Cannot bind TCP (%d)\n", ret);
+		return;
+	}
+
+	/* Note that we cannot put shell as a user_data when connecting
+	 * because the tcp_connected() will be called much later and
+	 * all local stack variables are lost at that point.
+	 */
+	tcp_shell = shell;
+
+	net_context_connect(*ctx, &addr, addrlen, tcp_connected,
+			    K_NO_WAIT, NULL);
+}
+
+static void tcp_sent_cb(struct net_context *context,
+			int status, void *user_data)
+{
+	PR_SHELL(tcp_shell, "Message sent\n");
+}
+
+static void tcp_recv_cb(struct net_context *context, struct net_pkt *pkt,
+			union net_ip_header *ip_hdr,
+			union net_proto_header *proto_hdr,
+			int status, void *user_data)
+{
+	int ret;
+
+	if (pkt == NULL) {
+		if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
+			return;
+		}
+
+		ret = net_context_put(tcp_ctx);
+		if (ret < 0) {
+			PR_SHELL(tcp_shell,
+				 "Cannot close the connection (%d)\n", ret);
+			return;
+		}
+
+		PR_SHELL(tcp_shell, "Connection closed by remote peer.\n");
+		tcp_ctx = NULL;
+
+		return;
+	}
+
+	PR_SHELL(tcp_shell, "%d bytes received\n", net_pkt_get_len(pkt));
+}
+#endif
+
+static int cmd_net_tcp_connect(const struct shell *shell, size_t argc,
+			       char *argv[])
+{
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+	int arg = 0;
+
+	/* tcp connect <ip> port */
+	char *endptr;
+	char *ip;
+	uint16_t port;
+
+	/* tcp connect <ip> port */
+	if (tcp_ctx && net_context_is_used(tcp_ctx)) {
+		PR("Already connected\n");
+		return -ENOEXEC;
+	}
+
+	if (!argv[++arg]) {
+		PR_WARNING("Peer IP address missing.\n");
+		return -ENOEXEC;
+	}
+
+	ip = argv[arg];
+
+	if (!argv[++arg]) {
+		PR_WARNING("Peer port missing.\n");
+		return -ENOEXEC;
+	}
+
+	port = strtol(argv[arg], &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid port %s\n", argv[arg]);
+		return -ENOEXEC;
+	}
+
+	tcp_connect(shell, ip, port, &tcp_ctx);
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP");
+#endif /* CONFIG_NET_NATIVE_TCP */
+
+	return 0;
+}
+
+static int cmd_net_tcp_send(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+	int arg = 0;
+	int ret;
+	struct net_shell_user_data user_data;
+
+	/* tcp send <data> */
+	if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
+		PR_WARNING("Not connected\n");
+		return -ENOEXEC;
+	}
+
+	if (!argv[++arg]) {
+		PR_WARNING("No data to send.\n");
+		return -ENOEXEC;
+	}
+
+	user_data.shell = shell;
+
+	ret = net_context_send(tcp_ctx, (uint8_t *)argv[arg],
+			       strlen(argv[arg]), tcp_sent_cb,
+			       TCP_TIMEOUT, &user_data);
+	if (ret < 0) {
+		PR_WARNING("Cannot send msg (%d)\n", ret);
+		return -ENOEXEC;
+	}
+
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP");
+#endif /* CONFIG_NET_NATIVE_TCP */
+
+	return 0;
+}
+
+static int cmd_net_tcp_recv(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+	int ret;
+	struct net_shell_user_data user_data;
+
+	/* tcp recv */
+	if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
+		PR_WARNING("Not connected\n");
+		return -ENOEXEC;
+	}
+
+	user_data.shell = shell;
+
+	ret = net_context_recv(tcp_ctx, tcp_recv_cb, K_NO_WAIT, &user_data);
+	if (ret < 0) {
+		PR_WARNING("Cannot recv data (%d)\n", ret);
+		return -ENOEXEC;
+	}
+
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP");
+#endif /* CONFIG_NET_NATIVE_TCP */
+
+	return 0;
+}
+
+static int cmd_net_tcp_close(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+	int ret;
+
+	/* tcp close */
+	if (!tcp_ctx || !net_context_is_used(tcp_ctx)) {
+		PR_WARNING("Not connected\n");
+		return -ENOEXEC;
+	}
+
+	ret = net_context_put(tcp_ctx);
+	if (ret < 0) {
+		PR_WARNING("Cannot close the connection (%d)\n", ret);
+		return -ENOEXEC;
+	}
+
+	PR("Connection closed.\n");
+	tcp_ctx = NULL;
+#else
+	PR_INFO("Set %s to enable %s support.\n",
+		"CONFIG_NET_TCP and CONFIG_NET_NATIVE", "TCP");
+#endif /* CONFIG_NET_TCP */
+
+	return 0;
+}
+
+static int cmd_net_tcp(const struct shell *shell, size_t argc, char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_VLAN)
+static void iface_vlan_del_cb(struct net_if *iface, void *user_data)
+{
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	uint16_t vlan_tag = POINTER_TO_UINT(data->user_data);
+	int ret;
+
+	ret = net_eth_vlan_disable(iface, vlan_tag);
+	if (ret < 0) {
+		if (ret != -ESRCH) {
+			PR_WARNING("Cannot delete VLAN tag %d from "
+				   "interface %p\n",
+				   vlan_tag, iface);
+		}
+
+		return;
+	}
+
+	PR("VLAN tag %d removed from interface %p\n", vlan_tag, iface);
+}
+
+static void iface_vlan_cb(struct net_if *iface, void *user_data)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	int *count = data->user_data;
+	int i;
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return;
+	}
+
+	if (*count == 0) {
+		PR("    Interface  Type     Tag\n");
+	}
+
+	if (!ctx->vlan_enabled) {
+		PR_WARNING("VLAN tag(s) not set\n");
+		return;
+	}
+
+	for (i = 0; i < NET_VLAN_MAX_COUNT; i++) {
+		if (!ctx->vlan[i].iface || ctx->vlan[i].iface != iface) {
+			continue;
+		}
+
+		if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) {
+			continue;
+		}
+
+		PR("[%d] %p %s %d\n", net_if_get_by_iface(iface), iface,
+		   iface2str(iface, NULL), ctx->vlan[i].tag);
+
+		break;
+	}
+
+	(*count)++;
+}
+#endif /* CONFIG_NET_VLAN */
+
+static int cmd_net_vlan(const struct shell *shell, size_t argc, char *argv[])
+{
+#if defined(CONFIG_NET_VLAN)
+	struct net_shell_user_data user_data;
+	int count;
+#endif
+
+#if defined(CONFIG_NET_VLAN)
+	count = 0;
+
+	user_data.shell = shell;
+	user_data.user_data = &count;
+
+	net_if_foreach(iface_vlan_cb, &user_data);
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
+#endif /* CONFIG_NET_VLAN */
+
+	return 0;
+}
+
+static int cmd_net_vlan_add(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+#if defined(CONFIG_NET_VLAN)
+	int arg = 0;
+	int ret;
+	uint16_t tag;
+	struct net_if *iface;
+	char *endptr;
+	uint32_t iface_idx;
+#endif
+
+#if defined(CONFIG_NET_VLAN)
+	/* vlan add <tag> <interface index> */
+	if (!argv[++arg]) {
+		PR_WARNING("VLAN tag missing.\n");
+		goto usage;
+	}
+
+	tag = strtol(argv[arg], &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid tag %s\n", argv[arg]);
+		return -ENOEXEC;
+	}
+
+	if (!argv[++arg]) {
+		PR_WARNING("Network interface index missing.\n");
+		goto usage;
+	}
+
+	iface_idx = strtol(argv[arg], &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid index %s\n", argv[arg]);
+		goto usage;
+	}
+
+	iface = net_if_get_by_index(iface_idx);
+	if (!iface) {
+		PR_WARNING("Network interface index %d is invalid.\n",
+			   iface_idx);
+		goto usage;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		PR_WARNING("Network interface %p is not ethernet interface\n",
+			   iface);
+		return -ENOEXEC;
+	}
+
+	ret = net_eth_vlan_enable(iface, tag);
+	if (ret < 0) {
+		if (ret == -ENOENT) {
+			PR_WARNING("No IP address configured.\n");
+		}
+
+		PR_WARNING("Cannot set VLAN tag (%d)\n", ret);
+
+		return -ENOEXEC;
+	}
+
+	PR("VLAN tag %d set to interface %p\n", tag, iface);
+
+	return 0;
+
+usage:
+	PR("Usage:\n");
+	PR("\tvlan add <tag> <interface index>\n");
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
+#endif /* CONFIG_NET_VLAN */
+
+	return 0;
+}
+
+static int cmd_net_vlan_del(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+#if defined(CONFIG_NET_VLAN)
+	int arg = 0;
+	struct net_shell_user_data user_data;
+	char *endptr;
+	uint16_t tag;
+#endif
+
+#if defined(CONFIG_NET_VLAN)
+	/* vlan del <tag> */
+	if (!argv[++arg]) {
+		PR_WARNING("VLAN tag missing.\n");
+		goto usage;
+	}
+
+	tag = strtol(argv[arg], &endptr, 10);
+	if (*endptr != '\0') {
+		PR_WARNING("Invalid tag %s\n", argv[arg]);
+		return -ENOEXEC;
+	}
+
+	user_data.shell = shell;
+	user_data.user_data = UINT_TO_POINTER((uint32_t)tag);
+
+	net_if_foreach(iface_vlan_del_cb, &user_data);
+
+	return 0;
+
+usage:
+	PR("Usage:\n");
+	PR("\tvlan del <tag>\n");
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_NET_VLAN", "VLAN");
+#endif /* CONFIG_NET_VLAN */
+
+	return 0;
+}
+
+static int cmd_net_suspend(const struct shell *shell, size_t argc,
+			   char *argv[])
+{
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	if (argv[1]) {
+		struct net_if *iface = NULL;
+		const struct device *dev;
+		int idx;
+		int ret;
+
+		idx = get_iface_idx(shell, argv[1]);
+		if (idx < 0) {
+			return -ENOEXEC;
+		}
+
+		iface = net_if_get_by_index(idx);
+		if (!iface) {
+			PR_WARNING("No such interface in index %d\n", idx);
+			return -ENOEXEC;
+		}
+
+		dev = net_if_get_device(iface);
+
+		ret = device_set_power_state(dev, DEVICE_PM_SUSPEND_STATE,
+					     NULL, NULL);
+		if (ret != 0) {
+			PR_INFO("Iface could not be suspended: ");
+
+			if (ret == -EBUSY) {
+				PR_INFO("device is busy\n");
+			} else if (ret == -EALREADY) {
+				PR_INFO("dehive is already suspended\n");
+			}
+		}
+	} else {
+		PR("Usage:\n");
+		PR("\tsuspend <iface index>\n");
+	}
+#else
+	PR_INFO("You need a network driver supporting Power Management.\n");
+#endif /* CONFIG_NET_POWER_MANAGEMENT */
+
+	return 0;
+}
+
+static int cmd_net_resume(const struct shell *shell, size_t argc,
+			  char *argv[])
+{
+#if defined(CONFIG_NET_POWER_MANAGEMENT)
+	if (argv[1]) {
+		struct net_if *iface = NULL;
+		const struct device *dev;
+		int idx;
+		int ret;
+
+		idx = get_iface_idx(shell, argv[1]);
+		if (idx < 0) {
+			return -ENOEXEC;
+		}
+
+		iface = net_if_get_by_index(idx);
+		if (!iface) {
+			PR_WARNING("No such interface in index %d\n", idx);
+			return -ENOEXEC;
+		}
+
+		dev = net_if_get_device(iface);
+
+		ret = device_set_power_state(dev, DEVICE_PM_ACTIVE_STATE,
+					     NULL, NULL);
+		if (ret != 0) {
+			PR_INFO("Iface could not be resumed\n");
+		}
+
+	} else {
+		PR("Usage:\n");
+		PR("\tresume <iface index>\n");
+	}
+#else
+	PR_INFO("You need a network driver supporting Power Management.\n");
+#endif /* CONFIG_NET_POWER_MANAGEMENT */
+
+	return 0;
+}
+
+#if defined(CONFIG_WEBSOCKET_CLIENT)
+static void websocket_context_cb(struct websocket_context *context,
+				 void *user_data)
+{
+#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
+#define ADDR_LEN NET_IPV4_ADDR_LEN
+#else
+#define ADDR_LEN NET_IPV6_ADDR_LEN
+#endif
+	struct net_shell_user_data *data = user_data;
+	const struct shell *shell = data->shell;
+	struct net_context *net_ctx;
+	int *count = data->user_data;
+	/* +7 for []:port */
+	char addr_local[ADDR_LEN + 7];
+	char addr_remote[ADDR_LEN + 7] = "";
+
+	net_ctx = z_get_fd_obj(context->real_sock, NULL, 0);
+	if (net_ctx == NULL) {
+		PR_ERROR("Invalid fd %d");
+		return;
+	}
+
+	get_addresses(net_ctx, addr_local, sizeof(addr_local),
+		      addr_remote, sizeof(addr_remote));
+
+	PR("[%2d] %p/%p\t%p   %16s\t%16s\n",
+	   (*count) + 1, context, net_ctx,
+	   net_context_get_iface(net_ctx),
+	   addr_local, addr_remote);
+
+	(*count)++;
+}
+#endif /* CONFIG_WEBSOCKET_CLIENT */
+
+static int cmd_net_websocket(const struct shell *shell, size_t argc,
+			     char *argv[])
+{
+#if defined(CONFIG_WEBSOCKET_CLIENT)
+	struct net_shell_user_data user_data;
+	int count = 0;
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	PR("     websocket/net_ctx\tIface         "
+	   "Local              \tRemote\n");
+
+	user_data.shell = shell;
+	user_data.user_data = &count;
+
+	websocket_context_foreach(websocket_context_cb, &user_data);
+
+	if (count == 0) {
+		PR("No connections\n");
+	}
+#else
+	PR_INFO("Set %s to enable %s support.\n", "CONFIG_WEBSOCKET_CLIENT",
+		"Websocket");
+#endif /* CONFIG_WEBSOCKET_CLIENT */
+
+	return 0;
+}
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_arp,
+	SHELL_CMD(flush, NULL, "Remove all entries from ARP cache.",
+		  cmd_net_arp_flush),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_dns,
+	SHELL_CMD(cancel, NULL, "Cancel all pending requests.",
+		  cmd_net_dns_cancel),
+	SHELL_CMD(query, NULL,
+		  "'net dns <hostname> [A or AAAA]' queries IPv4 address "
+		  "(default) or IPv6 address for a host name.",
+		  cmd_net_dns_query),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_events,
+	SHELL_CMD(on, NULL, "Turn on network event monitoring.",
+		  cmd_net_events_on),
+	SHELL_CMD(off, NULL, "Turn off network event monitoring.",
+		  cmd_net_events_off),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_gptp,
+	SHELL_CMD(port, NULL,
+		  "'net gptp [<port>]' prints detailed information about "
+		  "gPTP port.",
+		  cmd_net_gptp_port),
+	SHELL_SUBCMD_SET_END
+);
+
+#if !defined(NET_VLAN_MAX_COUNT)
+#define MAX_IFACE_COUNT NET_IF_MAX_CONFIGS
+#else
+#define MAX_IFACE_COUNT NET_VLAN_MAX_COUNT
+#endif
+
+#if defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
+
+#define MAX_IFACE_HELP_STR_LEN sizeof("longbearername (0xabcd0123)")
+#define MAX_IFACE_STR_LEN sizeof("xxx")
+
+static char iface_help_buffer[MAX_IFACE_COUNT][MAX_IFACE_HELP_STR_LEN];
+static char iface_index_buffer[MAX_IFACE_COUNT][MAX_IFACE_STR_LEN];
+
+static char *set_iface_index_buffer(size_t idx)
+{
+	struct net_if *iface = net_if_get_by_index(idx);
+
+	if (!iface) {
+		return NULL;
+	}
+
+	snprintk(iface_index_buffer[idx], MAX_IFACE_STR_LEN, "%zu", idx);
+
+	return iface_index_buffer[idx];
+}
+
+static char *set_iface_index_help(size_t idx)
+{
+	struct net_if *iface = net_if_get_by_index(idx);
+
+	if (!iface) {
+		return NULL;
+	}
+
+	snprintk(iface_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
+		 "%s (%p)", iface2str(iface, NULL), iface);
+
+	return iface_help_buffer[idx];
+}
+
+static void iface_index_get(size_t idx, struct shell_static_entry *entry);
+
+SHELL_DYNAMIC_CMD_CREATE(iface_index, iface_index_get);
+
+static void iface_index_get(size_t idx, struct shell_static_entry *entry)
+{
+	entry->handler = NULL;
+	entry->help  = set_iface_index_help(idx);
+	entry->subcmd = &iface_index;
+	entry->syntax = set_iface_index_buffer(idx);
+}
+
+#define IFACE_DYN_CMD &iface_index
+
+#if defined(CONFIG_NET_PPP)
+static char *set_iface_ppp_index_buffer(size_t idx)
+{
+	struct net_if *iface = net_if_get_by_index(idx);
+
+	if (!iface) {
+		return NULL;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
+		return NULL;
+	}
+
+	snprintk(iface_index_buffer[idx], MAX_IFACE_STR_LEN, "%zu", idx);
+
+	return iface_index_buffer[idx];
+}
+
+static char *set_iface_ppp_index_help(size_t idx)
+{
+	struct net_if *iface = net_if_get_by_index(idx);
+
+	if (!iface) {
+		return NULL;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
+		return NULL;
+	}
+
+	snprintk(iface_help_buffer[idx], MAX_IFACE_HELP_STR_LEN,
+		 "%s (%p)", iface2str(iface, NULL), iface);
+
+	return iface_help_buffer[idx];
+}
+
+static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry);
+
+SHELL_DYNAMIC_CMD_CREATE(iface_ppp_index, iface_ppp_index_get);
+
+static void iface_ppp_index_get(size_t idx, struct shell_static_entry *entry)
+{
+	entry->handler = NULL;
+	entry->help  = set_iface_ppp_index_help(idx);
+	entry->subcmd = &iface_ppp_index;
+	entry->syntax = set_iface_ppp_index_buffer(idx);
+}
+
+#define IFACE_PPP_DYN_CMD &iface_ppp_index
+#else
+#define IFACE_PPP_DYN_CMD NULL
+#endif /* CONFIG_NET_PPP */
+
+#else
+#define IFACE_DYN_CMD NULL
+#define IFACE_PPP_DYN_CMD NULL
+#endif /* CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_iface,
+	SHELL_CMD(up, IFACE_DYN_CMD,
+		  "'net iface up <index>' takes network interface up.",
+		  cmd_net_iface_up),
+	SHELL_CMD(down, IFACE_DYN_CMD,
+		  "'net iface down <index>' takes network interface "
+		  "down.",
+		  cmd_net_iface_down),
+	SHELL_CMD(show, IFACE_DYN_CMD,
+		  "'net iface <index>' shows network interface "
+		  "information.",
+		  cmd_net_iface),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ppp,
+	SHELL_CMD(ping, IFACE_PPP_DYN_CMD,
+		  "'net ppp ping <index>' sends Echo-request to PPP interface.",
+		  cmd_net_ppp_ping),
+	SHELL_CMD(status, NULL,
+		  "'net ppp status' prints information about PPP.",
+		  cmd_net_ppp_status),
+	SHELL_SUBCMD_SET_END
+);
+
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
+static
+char nbr_address_buffer[CONFIG_NET_IPV6_MAX_NEIGHBORS][NET_IPV6_ADDR_LEN];
+
+static void nbr_address_cb(struct net_nbr *nbr, void *user_data)
+{
+	int *count = user_data;
+
+	if (*count >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
+		return;
+	}
+
+	snprintk(nbr_address_buffer[*count], NET_IPV6_ADDR_LEN,
+		 "%s", net_sprint_ipv6_addr(&net_ipv6_nbr_data(nbr)->addr));
+
+	(*count)++;
+}
+
+static void nbr_populate_addresses(void)
+{
+	int count = 0;
+
+	net_ipv6_nbr_foreach(nbr_address_cb, &count);
+}
+
+static char *set_nbr_address(size_t idx)
+{
+	if (idx == 0) {
+		memset(nbr_address_buffer, 0, sizeof(nbr_address_buffer));
+		nbr_populate_addresses();
+	}
+
+	if (idx >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
+		return NULL;
+	}
+
+	if (!nbr_address_buffer[idx][0]) {
+		return NULL;
+	}
+
+	return nbr_address_buffer[idx];
+}
+
+static void nbr_address_get(size_t idx, struct shell_static_entry *entry);
+
+SHELL_DYNAMIC_CMD_CREATE(nbr_address, nbr_address_get);
+
+#define NBR_ADDRESS_CMD &nbr_address
+
+static void nbr_address_get(size_t idx, struct shell_static_entry *entry)
+{
+	entry->handler = NULL;
+	entry->help  = NULL;
+	entry->subcmd = &nbr_address;
+	entry->syntax = set_nbr_address(idx);
+}
+
+#else
+#define NBR_ADDRESS_CMD NULL
+#endif /* CONFIG_NET_IPV6 && CONFIG_NET_SHELL_DYN_CMD_COMPLETION */
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_nbr,
+	SHELL_CMD(rm, NBR_ADDRESS_CMD,
+		  "'net nbr rm <address>' removes neighbor from cache.",
+		  cmd_net_nbr_rm),
+	SHELL_SUBCMD_SET_END
+);
+
+#if defined(CONFIG_NET_STATISTICS) && \
+	defined(CONFIG_NET_STATISTICS_PER_INTERFACE) && \
+	defined(CONFIG_NET_SHELL_DYN_CMD_COMPLETION)
+#define STATS_IFACE_CMD &iface_index
+#else
+#define STATS_IFACE_CMD NULL
+#endif /* CONFIG_NET_STATISTICS && CONFIG_NET_STATISTICS_PER_INTERFACE &&
+	* CONFIG_NET_SHELL_DYN_CMD_COMPLETION
+	*/
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_stats,
+	SHELL_CMD(all, NULL,
+		  "Show network statistics for all network interfaces.",
+		  cmd_net_stats_all),
+	SHELL_CMD(iface, STATS_IFACE_CMD,
+		  "'net stats <index>' shows network statistics for "
+		  "one specific network interface.",
+		  cmd_net_stats_iface),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_tcp,
+	SHELL_CMD(connect, NULL,
+		  "'net tcp connect <address> <port>' connects to TCP peer.",
+		  cmd_net_tcp_connect),
+	SHELL_CMD(send, NULL,
+		  "'net tcp send <data>' sends data to peer using TCP.",
+		  cmd_net_tcp_send),
+	SHELL_CMD(recv, NULL,
+		  "'net tcp recv' receives data using TCP.",
+		  cmd_net_tcp_recv),
+	SHELL_CMD(close, NULL,
+		  "'net tcp close' closes TCP connection.", cmd_net_tcp_close),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_vlan,
+	SHELL_CMD(add, NULL,
+		  "'net vlan add <tag> <index>' adds VLAN tag to the "
+		  "network interface.",
+		  cmd_net_vlan_add),
+	SHELL_CMD(del, NULL,
+		  "'net vlan del <tag>' deletes VLAN tag from the network "
+		  "interface.",
+		  cmd_net_vlan_del),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_ping,
+	SHELL_CMD(--help, NULL,
+		  "'net ping [-c count] [-i interval ms] [-I <iface index>] <host>' "
+		  "Send ICMPv4 or ICMPv6 Echo-Request to a network host.",
+		  cmd_net_ping),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_cmd_pkt,
+	SHELL_CMD(--help, NULL,
+		  "'net pkt [ptr in hex]' "
+		  "Print information about given net_pkt",
+		  cmd_net_pkt),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(net_commands,
+	SHELL_CMD(allocs, NULL, "Print network memory allocations.",
+		  cmd_net_allocs),
+	SHELL_CMD(arp, &net_cmd_arp, "Print information about IPv4 ARP cache.",
+		  cmd_net_arp),
+	SHELL_CMD(conn, NULL, "Print information about network connections.",
+		  cmd_net_conn),
+	SHELL_CMD(dns, &net_cmd_dns, "Show how DNS is configured.",
+		  cmd_net_dns),
+	SHELL_CMD(events, &net_cmd_events, "Monitor network management events.",
+		  cmd_net_events),
+	SHELL_CMD(gptp, &net_cmd_gptp, "Print information about gPTP support.",
+		  cmd_net_gptp),
+	SHELL_CMD(iface, &net_cmd_iface,
+		  "Print information about network interfaces.",
+		  cmd_net_iface),
+	SHELL_CMD(ipv6, NULL,
+		  "Print information about IPv6 specific information and "
+		  "configuration.",
+		  cmd_net_ipv6),
+	SHELL_CMD(mem, NULL, "Print information about network memory usage.",
+		  cmd_net_mem),
+	SHELL_CMD(nbr, &net_cmd_nbr, "Print neighbor information.",
+		  cmd_net_nbr),
+	SHELL_CMD(ping, &net_cmd_ping, "Ping a network host.", cmd_net_ping),
+	SHELL_CMD(pkt, &net_cmd_pkt, "net_pkt information.", cmd_net_pkt),
+	SHELL_CMD(ppp, &net_cmd_ppp, "PPP information.", cmd_net_ppp_status),
+	SHELL_CMD(resume, NULL, "Resume a network interface", cmd_net_resume),
+	SHELL_CMD(route, NULL, "Show network route.", cmd_net_route),
+	SHELL_CMD(stacks, NULL, "Show network stacks information.",
+		  cmd_net_stacks),
+	SHELL_CMD(stats, &net_cmd_stats, "Show network statistics.",
+		  cmd_net_stats),
+	SHELL_CMD(suspend, NULL, "Suspend a network interface",
+		  cmd_net_suspend),
+	SHELL_CMD(tcp, &net_cmd_tcp, "Connect/send/close TCP connection.",
+		  cmd_net_tcp),
+	SHELL_CMD(vlan, &net_cmd_vlan, "Show VLAN information.", cmd_net_vlan),
+	SHELL_CMD(websocket, NULL, "Print information about WebSocket "
+								"connections.",
+		  cmd_net_websocket),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_CMD_REGISTER(net, &net_commands, "Networking commands", NULL);
+
+int net_shell_init(void)
+{
+#if defined(CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START)
+	char *argv[] = {
+		"on",
+		NULL
+	};
+
+	(void)cmd_net_events_on(shell_backend_uart_get_ptr(), 1, argv);
+#endif
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.h	(working copy)
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __NET_STATS_H__
+#define __NET_STATS_H__
+
+#if defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
+
+#include <stdlib.h>
+
+#include <net/net_ip.h>
+#include <net/net_stats.h>
+#include <net/net_if.h>
+
+extern struct net_stats net_stats;
+
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+#define SET_STAT(cmd) (cmd)
+#define GET_STAT(iface, s) (iface ? iface->stats.s : net_stats.s)
+#define GET_STAT_ADDR(iface, s) (iface ? &iface->stats.s : &net_stats.s)
+#else
+#define SET_STAT(cmd)
+#define GET_STAT(iface, s) (net_stats.s)
+#define GET_STAT_ADDR(iface, s) (&GET_STAT(iface, s))
+#endif
+
+#define UPDATE_STAT_GLOBAL(cmd) (net_##cmd)
+#define UPDATE_STAT(_iface, _cmd) \
+	{ NET_ASSERT(_iface); (UPDATE_STAT_GLOBAL(_cmd)); \
+	  SET_STAT(_iface->_cmd); }
+/* Core stats */
+
+static inline void net_stats_update_processing_error(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.processing_error++);
+}
+
+static inline void net_stats_update_ip_errors_protoerr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ip_errors.protoerr++);
+}
+
+static inline void net_stats_update_ip_errors_vhlerr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ip_errors.vhlerr++);
+}
+
+static inline void net_stats_update_bytes_recv(struct net_if *iface,
+					       uint32_t bytes)
+{
+	UPDATE_STAT(iface, stats.bytes.received += bytes);
+}
+
+static inline void net_stats_update_bytes_sent(struct net_if *iface,
+					       uint32_t bytes)
+{
+	UPDATE_STAT(iface, stats.bytes.sent += bytes);
+}
+#else
+#define net_stats_update_processing_error(iface)
+#define net_stats_update_ip_errors_protoerr(iface)
+#define net_stats_update_ip_errors_vhlerr(iface)
+#define net_stats_update_bytes_recv(iface, bytes)
+#define net_stats_update_bytes_sent(iface, bytes)
+#endif /* CONFIG_NET_STATISTICS */
+
+#if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6)
+/* IPv6 stats */
+
+static inline void net_stats_update_ipv6_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6.sent++);
+}
+
+static inline void net_stats_update_ipv6_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6.recv++);
+}
+
+static inline void net_stats_update_ipv6_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6.drop++);
+}
+#else
+#define net_stats_update_ipv6_drop(iface)
+#define net_stats_update_ipv6_sent(iface)
+#define net_stats_update_ipv6_recv(iface)
+#endif /* CONFIG_NET_STATISTICS_IPV6 */
+
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND) && defined(CONFIG_NET_NATIVE_IPV6)
+/* IPv6 Neighbor Discovery stats*/
+
+static inline void net_stats_update_ipv6_nd_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_nd.sent++);
+}
+
+static inline void net_stats_update_ipv6_nd_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_nd.recv++);
+}
+
+static inline void net_stats_update_ipv6_nd_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_nd.drop++);
+}
+#else
+#define net_stats_update_ipv6_nd_sent(iface)
+#define net_stats_update_ipv6_nd_recv(iface)
+#define net_stats_update_ipv6_nd_drop(iface)
+#endif /* CONFIG_NET_STATISTICS_IPV6_ND */
+
+#if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+/* IPv4 stats */
+
+static inline void net_stats_update_ipv4_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv4.drop++);
+}
+
+static inline void net_stats_update_ipv4_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv4.sent++);
+}
+
+static inline void net_stats_update_ipv4_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv4.recv++);
+}
+#else
+#define net_stats_update_ipv4_drop(iface)
+#define net_stats_update_ipv4_sent(iface)
+#define net_stats_update_ipv4_recv(iface)
+#endif /* CONFIG_NET_STATISTICS_IPV4 */
+
+#if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4)
+/* Common ICMPv4/ICMPv6 stats */
+static inline void net_stats_update_icmp_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.icmp.sent++);
+}
+
+static inline void net_stats_update_icmp_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.icmp.recv++);
+}
+
+static inline void net_stats_update_icmp_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.icmp.drop++);
+}
+#else
+#define net_stats_update_icmp_sent(iface)
+#define net_stats_update_icmp_recv(iface)
+#define net_stats_update_icmp_drop(iface)
+#endif /* CONFIG_NET_STATISTICS_ICMP */
+
+#if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP)
+/* UDP stats */
+static inline void net_stats_update_udp_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.udp.sent++);
+}
+
+static inline void net_stats_update_udp_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.udp.recv++);
+}
+
+static inline void net_stats_update_udp_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.udp.drop++);
+}
+
+static inline void net_stats_update_udp_chkerr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.udp.chkerr++);
+}
+#else
+#define net_stats_update_udp_sent(iface)
+#define net_stats_update_udp_recv(iface)
+#define net_stats_update_udp_drop(iface)
+#define net_stats_update_udp_chkerr(iface)
+#endif /* CONFIG_NET_STATISTICS_UDP */
+
+#if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP)
+/* TCP stats */
+static inline void net_stats_update_tcp_sent(struct net_if *iface, uint32_t bytes)
+{
+	UPDATE_STAT(iface, stats.tcp.bytes.sent += bytes);
+}
+
+static inline void net_stats_update_tcp_recv(struct net_if *iface, uint32_t bytes)
+{
+	UPDATE_STAT(iface, stats.tcp.bytes.received += bytes);
+}
+
+static inline void net_stats_update_tcp_resent(struct net_if *iface,
+					       uint32_t bytes)
+{
+	UPDATE_STAT(iface, stats.tcp.resent += bytes);
+}
+
+static inline void net_stats_update_tcp_seg_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.sent++);
+}
+
+static inline void net_stats_update_tcp_seg_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.recv++);
+}
+
+static inline void net_stats_update_tcp_seg_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.drop++);
+}
+
+static inline void net_stats_update_tcp_seg_rst(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.rst++);
+}
+
+static inline void net_stats_update_tcp_seg_conndrop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.conndrop++);
+}
+
+static inline void net_stats_update_tcp_seg_connrst(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.connrst++);
+}
+
+static inline void net_stats_update_tcp_seg_chkerr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.chkerr++);
+}
+
+static inline void net_stats_update_tcp_seg_ackerr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.ackerr++);
+}
+
+static inline void net_stats_update_tcp_seg_rsterr(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.rsterr++);
+}
+
+static inline void net_stats_update_tcp_seg_rexmit(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.tcp.rexmit++);
+}
+#else
+#define net_stats_update_tcp_sent(iface, bytes)
+#define net_stats_update_tcp_resent(iface, bytes)
+#define net_stats_update_tcp_recv(iface, bytes)
+#define net_stats_update_tcp_seg_sent(iface)
+#define net_stats_update_tcp_seg_recv(iface)
+#define net_stats_update_tcp_seg_drop(iface)
+#define net_stats_update_tcp_seg_rst(iface)
+#define net_stats_update_tcp_seg_conndrop(iface)
+#define net_stats_update_tcp_seg_connrst(iface)
+#define net_stats_update_tcp_seg_chkerr(iface)
+#define net_stats_update_tcp_seg_ackerr(iface)
+#define net_stats_update_tcp_seg_rsterr(iface)
+#define net_stats_update_tcp_seg_rexmit(iface)
+#endif /* CONFIG_NET_STATISTICS_TCP */
+
+static inline void net_stats_update_per_proto_recv(struct net_if *iface,
+						   enum net_ip_protocol proto)
+{
+	if (!IS_ENABLED(CONFIG_NET_NATIVE)) {
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
+		net_stats_update_udp_recv(iface);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+		net_stats_update_tcp_seg_recv(iface);
+	}
+}
+
+static inline void net_stats_update_per_proto_drop(struct net_if *iface,
+						   enum net_ip_protocol proto)
+{
+	if (!IS_ENABLED(CONFIG_NET_NATIVE)) {
+		return;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
+		net_stats_update_udp_drop(iface);
+	} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+		net_stats_update_tcp_seg_drop(iface);
+	}
+}
+
+#if defined(CONFIG_NET_STATISTICS_MLD) && defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_ipv6_mld_recv(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_mld.recv++);
+}
+
+static inline void net_stats_update_ipv6_mld_sent(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_mld.sent++);
+}
+
+static inline void net_stats_update_ipv6_mld_drop(struct net_if *iface)
+{
+	UPDATE_STAT(iface, stats.ipv6_mld.drop++);
+}
+#else
+#define net_stats_update_ipv6_mld_recv(iface)
+#define net_stats_update_ipv6_mld_sent(iface)
+#define net_stats_update_ipv6_mld_drop(iface)
+#endif /* CONFIG_NET_STATISTICS_MLD */
+
+#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
+	defined(CONFIG_NET_PKT_TXTIME_STATS)) && defined(CONFIG_NET_STATISTICS)
+static inline void net_stats_update_tx_time(struct net_if *iface,
+					    uint32_t start_time,
+					    uint32_t end_time)
+{
+	uint32_t diff = end_time - start_time;
+
+	UPDATE_STAT(iface, stats.tx_time.sum +=
+		    k_cyc_to_ns_floor64(diff) / 1000);
+	UPDATE_STAT(iface, stats.tx_time.count += 1);
+}
+#else
+#define net_stats_update_tx_time(iface, start_time, end_time)
+#endif /* (TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+static inline void net_stats_update_tx_time_detail(struct net_if *iface,
+						   uint32_t detail_stat[])
+{
+	int i;
+
+	for (i = 0; i < NET_PKT_DETAIL_STATS_COUNT; i++) {
+		UPDATE_STAT(iface,
+			    stats.tx_time_detail[i].sum +=
+			    k_cyc_to_ns_floor64(detail_stat[i]) / 1000);
+		UPDATE_STAT(iface,
+			    stats.tx_time_detail[i].count += 1);
+	}
+}
+#else
+#define net_stats_update_tx_time_detail(iface, detail_stat)
+#endif /* NET_PKT_TXTIME_STATS_DETAIL */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS)
+static inline void net_stats_update_rx_time(struct net_if *iface,
+					    uint32_t start_time,
+					    uint32_t end_time)
+{
+	uint32_t diff = end_time - start_time;
+
+	UPDATE_STAT(iface, stats.rx_time.sum +=
+		    k_cyc_to_ns_floor64(diff) / 1000);
+	UPDATE_STAT(iface, stats.rx_time.count += 1);
+}
+#else
+#define net_stats_update_rx_time(iface, start_time, end_time)
+#endif /* NET_CONTEXT_TIMESTAMP && STATISTICS */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+static inline void net_stats_update_rx_time_detail(struct net_if *iface,
+						   uint32_t detail_stat[])
+{
+	int i;
+
+	for (i = 0; i < NET_PKT_DETAIL_STATS_COUNT; i++) {
+		UPDATE_STAT(iface,
+			    stats.rx_time_detail[i].sum +=
+			    k_cyc_to_ns_floor64(detail_stat[i]) / 1000);
+		UPDATE_STAT(iface,
+			    stats.rx_time_detail[i].count += 1);
+	}
+}
+#else
+#define net_stats_update_rx_time_detail(iface, detail_stat)
+#endif /* NET_PKT_RXTIME_STATS_DETAIL */
+
+#if (NET_TC_COUNT > 1) && defined(CONFIG_NET_STATISTICS) \
+	&& defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_tc_sent_pkt(struct net_if *iface, uint8_t tc)
+{
+	UPDATE_STAT(iface, stats.tc.sent[tc].pkts++);
+}
+
+static inline void net_stats_update_tc_sent_bytes(struct net_if *iface,
+						  uint8_t tc, size_t bytes)
+{
+	UPDATE_STAT(iface, stats.tc.sent[tc].bytes += bytes);
+}
+
+static inline void net_stats_update_tc_sent_priority(struct net_if *iface,
+						     uint8_t tc, uint8_t priority)
+{
+	UPDATE_STAT(iface, stats.tc.sent[tc].priority = priority);
+}
+
+#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
+	defined(CONFIG_NET_PKT_TXTIME_STATS)) && \
+	defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_tc_tx_time(struct net_if *iface,
+					       uint8_t priority,
+					       uint32_t start_time,
+					       uint32_t end_time)
+{
+	uint32_t diff = end_time - start_time;
+	int tc = net_tx_priority2tc(priority);
+
+	UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.sum +=
+		    k_cyc_to_ns_floor64(diff) / 1000);
+	UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.count += 1);
+
+	net_stats_update_tx_time(iface, start_time, end_time);
+}
+#else
+#define net_stats_update_tc_tx_time(iface, tc, start_time, end_time)
+#endif /* (NET_CONTEXT_TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+static inline void net_stats_update_tc_tx_time_detail(struct net_if *iface,
+						      uint8_t priority,
+						      uint32_t detail_stat[])
+{
+	int tc = net_tx_priority2tc(priority);
+	int i;
+
+	for (i = 0; i < NET_PKT_DETAIL_STATS_COUNT; i++) {
+		UPDATE_STAT(iface,
+			    stats.tc.sent[tc].tx_time_detail[i].sum +=
+			    k_cyc_to_ns_floor64(detail_stat[i]) / 1000);
+		UPDATE_STAT(iface,
+			    stats.tc.sent[tc].tx_time_detail[i].count += 1);
+	}
+
+	net_stats_update_tx_time_detail(iface, detail_stat);
+}
+#else
+#define net_stats_update_tc_tx_time_detail(iface, tc, detail_stat)
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS) \
+	&& defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_tc_rx_time(struct net_if *iface,
+					       uint8_t priority,
+					       uint32_t start_time,
+					       uint32_t end_time)
+{
+	uint32_t diff = end_time - start_time;
+	int tc = net_rx_priority2tc(priority);
+
+	UPDATE_STAT(iface, stats.tc.recv[tc].rx_time.sum +=
+		    k_cyc_to_ns_floor64(diff) / 1000);
+	UPDATE_STAT(iface, stats.tc.recv[tc].rx_time.count += 1);
+
+	net_stats_update_rx_time(iface, start_time, end_time);
+}
+#else
+#define net_stats_update_tc_rx_time(iface, tc, start_time, end_time)
+#endif /* NET_PKT_RXTIME_STATS && NET_STATISTICS */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+static inline void net_stats_update_tc_rx_time_detail(struct net_if *iface,
+						      uint8_t priority,
+						      uint32_t detail_stat[])
+{
+	int tc = net_rx_priority2tc(priority);
+	int i;
+
+	for (i = 0; i < NET_PKT_DETAIL_STATS_COUNT; i++) {
+		UPDATE_STAT(iface,
+			    stats.tc.recv[tc].rx_time_detail[i].sum +=
+			    k_cyc_to_ns_floor64(detail_stat[i]) / 1000);
+		UPDATE_STAT(iface,
+			    stats.tc.recv[tc].rx_time_detail[i].count += 1);
+	}
+
+	net_stats_update_rx_time_detail(iface, detail_stat);
+}
+#else
+#define net_stats_update_tc_rx_time_detail(iface, tc, detail_stat)
+#endif /* CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+
+static inline void net_stats_update_tc_recv_pkt(struct net_if *iface, uint8_t tc)
+{
+	UPDATE_STAT(iface, stats.tc.recv[tc].pkts++);
+}
+
+static inline void net_stats_update_tc_recv_bytes(struct net_if *iface,
+						  uint8_t tc, size_t bytes)
+{
+	UPDATE_STAT(iface, stats.tc.recv[tc].bytes += bytes);
+}
+
+static inline void net_stats_update_tc_recv_priority(struct net_if *iface,
+						     uint8_t tc, uint8_t priority)
+{
+	UPDATE_STAT(iface, stats.tc.recv[tc].priority = priority);
+}
+#else
+#define net_stats_update_tc_sent_pkt(iface, tc)
+#define net_stats_update_tc_sent_bytes(iface, tc, bytes)
+#define net_stats_update_tc_sent_priority(iface, tc, priority)
+#define net_stats_update_tc_recv_pkt(iface, tc)
+#define net_stats_update_tc_recv_bytes(iface, tc, bytes)
+#define net_stats_update_tc_recv_priority(iface, tc, priority)
+
+#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
+	defined(CONFIG_NET_PKT_TXTIME_STATS)) && \
+	defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_tc_tx_time(struct net_if *iface,
+					       uint8_t pkt_priority,
+					       uint32_t start_time,
+					       uint32_t end_time)
+{
+	ARG_UNUSED(pkt_priority);
+
+	net_stats_update_tx_time(iface, start_time, end_time);
+}
+#else
+#define net_stats_update_tc_tx_time(iface, priority, start_time, end_time)
+#endif /* (NET_CONTEXT_TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
+
+#if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)
+static inline void net_stats_update_tc_tx_time_detail(struct net_if *iface,
+						      uint8_t pkt_priority,
+						      uint32_t detail_stat[])
+{
+	ARG_UNUSED(pkt_priority);
+
+	net_stats_update_tx_time_detail(iface, detail_stat);
+}
+#else
+#define net_stats_update_tc_tx_time_detail(iface, pkt_priority, detail_stat)
+#endif /* CONFIG_NET_PKT_TXTIME_STATS_DETAIL */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS) \
+	&& defined(CONFIG_NET_NATIVE)
+static inline void net_stats_update_tc_rx_time(struct net_if *iface,
+					       uint8_t pkt_priority,
+					       uint32_t start_time,
+					       uint32_t end_time)
+{
+	ARG_UNUSED(pkt_priority);
+
+	net_stats_update_rx_time(iface, start_time, end_time);
+}
+#else
+#define net_stats_update_tc_rx_time(iface, priority, start_time, end_time)
+#endif /* NET_PKT_RXTIME_STATS && NET_STATISTICS */
+
+#if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL)
+static inline void net_stats_update_tc_rx_time_detail(struct net_if *iface,
+						      uint8_t pkt_priority,
+						      uint32_t detail_stat[])
+{
+	ARG_UNUSED(pkt_priority);
+
+	net_stats_update_rx_time_detail(iface, detail_stat);
+}
+#else
+#define net_stats_update_tc_rx_time_detail(iface, pkt_priority, detail_stat)
+#endif /* CONFIG_NET_PKT_RXTIME_STATS_DETAIL */
+#endif /* NET_TC_COUNT > 1 */
+
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)	\
+	&& defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
+static inline void net_stats_add_suspend_start_time(struct net_if *iface,
+						    uint32_t time)
+{
+	UPDATE_STAT(iface, stats.pm.start_time = time);
+}
+
+static inline void net_stats_add_suspend_end_time(struct net_if *iface,
+						  uint32_t time)
+{
+	uint32_t diff_time =
+		k_cyc_to_ms_floor32(time - GET_STAT(iface, pm.start_time));
+
+	UPDATE_STAT(iface, stats.pm.start_time = 0);
+	UPDATE_STAT(iface, stats.pm.last_suspend_time = diff_time);
+	UPDATE_STAT(iface, stats.pm.suspend_count++);
+	UPDATE_STAT(iface, stats.pm.overall_suspend_time += diff_time);
+}
+#else
+#define net_stats_add_suspend_start_time(iface, time)
+#define net_stats_add_suspend_end_time(iface, time)
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_PERIODIC_OUTPUT) \
+	&& defined(CONFIG_NET_NATIVE)
+/* A simple periodic statistic printer, used only in net core */
+void net_print_statistics_all(void);
+void net_print_statistics_iface(struct net_if *iface);
+void net_print_statistics(void);
+#else
+#define net_print_statistics_all()
+#define net_print_statistics_iface(iface)
+#define net_print_statistics()
+#endif
+
+void net_stats_reset(struct net_if *iface);
+#endif /* __NET_STATS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_stats.c	(working copy)
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_NET_STATISTICS_PERIODIC_OUTPUT)
+#define NET_LOG_LEVEL LOG_LEVEL_INF
+#else
+#define NET_LOG_LEVEL CONFIG_NET_STATISTICS_LOG_LEVEL
+#endif
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_stats, NET_LOG_LEVEL);
+
+#include <kernel.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <net/net_core.h>
+
+#include "net_stats.h"
+#include "net_private.h"
+
+/* Global network statistics.
+ *
+ * The variable needs to be global so that the GET_STAT() macro can access it
+ * from net_shell.c
+ */
+struct net_stats net_stats = { 0 };
+
+#if defined(CONFIG_NET_STATISTICS_PERIODIC_OUTPUT)
+
+#define PRINT_STATISTICS_INTERVAL (30 * MSEC_PER_SEC)
+
+#if NET_TC_COUNT > 1
+static const char *priority2str(enum net_priority priority)
+{
+	switch (priority) {
+	case NET_PRIORITY_BK:
+		return "BK"; /* Background */
+	case NET_PRIORITY_BE:
+		return "BE"; /* Best effort */
+	case NET_PRIORITY_EE:
+		return "EE"; /* Excellent effort */
+	case NET_PRIORITY_CA:
+		return "CA"; /* Critical applications */
+	case NET_PRIORITY_VI:
+		return "VI"; /* Video, < 100 ms latency and jitter */
+	case NET_PRIORITY_VO:
+		return "VO"; /* Voice, < 10 ms latency and jitter  */
+	case NET_PRIORITY_IC:
+		return "IC"; /* Internetwork control */
+	case NET_PRIORITY_NC:
+		return "NC"; /* Network control */
+	}
+
+	return "??";
+}
+#endif
+
+static inline int64_t cmp_val(uint64_t val1, uint64_t val2)
+{
+	return (int64_t)(val1 - val2);
+}
+
+static inline void stats(struct net_if *iface)
+{
+	static uint64_t next_print;
+	uint64_t curr = k_uptime_get();
+	int64_t cmp = cmp_val(curr, next_print);
+	int i;
+
+	if (!next_print || (abs(cmp) > PRINT_STATISTICS_INTERVAL)) {
+		if (iface) {
+			NET_INFO("Interface %p [%d]", iface,
+				 net_if_get_by_iface(iface));
+		} else {
+			NET_INFO("Global statistics:");
+		}
+
+#if defined(CONFIG_NET_STATISTICS_IPV6)
+		NET_INFO("IPv6 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d",
+			 GET_STAT(iface, ipv6.recv),
+			 GET_STAT(iface, ipv6.sent),
+			 GET_STAT(iface, ipv6.drop),
+			 GET_STAT(iface, ipv6.forwarded));
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+		NET_INFO("IPv6 ND recv   %d\tsent\t%d\tdrop\t%d",
+			 GET_STAT(iface, ipv6_nd.recv),
+			 GET_STAT(iface, ipv6_nd.sent),
+			 GET_STAT(iface, ipv6_nd.drop));
+#endif /* CONFIG_NET_STATISTICS_IPV6_ND */
+#if defined(CONFIG_NET_STATISTICS_MLD)
+		NET_INFO("IPv6 MLD recv  %d\tsent\t%d\tdrop\t%d",
+			 GET_STAT(iface, ipv6_mld.recv),
+			 GET_STAT(iface, ipv6_mld.sent),
+			 GET_STAT(iface, ipv6_mld.drop));
+#endif /* CONFIG_NET_STATISTICS_MLD */
+#endif /* CONFIG_NET_STATISTICS_IPV6 */
+
+#if defined(CONFIG_NET_STATISTICS_IPV4)
+		NET_INFO("IPv4 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d",
+			 GET_STAT(iface, ipv4.recv),
+			 GET_STAT(iface, ipv4.sent),
+			 GET_STAT(iface, ipv4.drop),
+			 GET_STAT(iface, ipv4.forwarded));
+#endif /* CONFIG_NET_STATISTICS_IPV4 */
+
+		NET_INFO("IP vhlerr      %d\thblener\t%d\tlblener\t%d",
+			 GET_STAT(iface, ip_errors.vhlerr),
+			 GET_STAT(iface, ip_errors.hblenerr),
+			 GET_STAT(iface, ip_errors.lblenerr));
+		NET_INFO("IP fragerr     %d\tchkerr\t%d\tprotoer\t%d",
+			 GET_STAT(iface, ip_errors.fragerr),
+			 GET_STAT(iface, ip_errors.chkerr),
+			 GET_STAT(iface, ip_errors.protoerr));
+
+		NET_INFO("ICMP recv      %d\tsent\t%d\tdrop\t%d",
+			 GET_STAT(iface, icmp.recv),
+			 GET_STAT(iface, icmp.sent),
+			 GET_STAT(iface, icmp.drop));
+		NET_INFO("ICMP typeer    %d\tchkerr\t%d",
+			 GET_STAT(iface, icmp.typeerr),
+			 GET_STAT(iface, icmp.chkerr));
+
+#if defined(CONFIG_NET_STATISTICS_UDP)
+		NET_INFO("UDP recv       %d\tsent\t%d\tdrop\t%d",
+			 GET_STAT(iface, udp.recv),
+			 GET_STAT(iface, udp.sent),
+			 GET_STAT(iface, udp.drop));
+		NET_INFO("UDP chkerr     %d",
+			 GET_STAT(iface, udp.chkerr));
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_TCP)
+		NET_INFO("TCP bytes recv %u\tsent\t%d",
+			 GET_STAT(iface, tcp.bytes.received),
+			 GET_STAT(iface, tcp.bytes.sent));
+		NET_INFO("TCP seg recv   %d\tsent\t%d\tdrop\t%d",
+			 GET_STAT(iface, tcp.recv),
+			 GET_STAT(iface, tcp.sent),
+			 GET_STAT(iface, tcp.drop));
+		NET_INFO("TCP seg resent %d\tchkerr\t%d\tackerr\t%d",
+			 GET_STAT(iface, tcp.resent),
+			 GET_STAT(iface, tcp.chkerr),
+			 GET_STAT(iface, tcp.ackerr));
+		NET_INFO("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d",
+			 GET_STAT(iface, tcp.rsterr),
+			 GET_STAT(iface, tcp.rst),
+			 GET_STAT(iface, tcp.rexmit));
+		NET_INFO("TCP conn drop  %d\tconnrst\t%d",
+			 GET_STAT(iface, tcp.conndrop),
+			 GET_STAT(iface, tcp.connrst));
+#endif
+
+		NET_INFO("Bytes received %u", GET_STAT(iface, bytes.received));
+		NET_INFO("Bytes sent     %u", GET_STAT(iface, bytes.sent));
+		NET_INFO("Processing err %d",
+			 GET_STAT(iface, processing_error));
+
+#if NET_TC_COUNT > 1
+#if NET_TC_TX_COUNT > 1
+		NET_INFO("TX traffic class statistics:");
+		NET_INFO("TC  Priority\tSent pkts\tbytes");
+
+		for (i = 0; i < NET_TC_TX_COUNT; i++) {
+			NET_INFO("[%d] %s (%d)\t%d\t\t%d", i,
+				 priority2str(GET_STAT(iface,
+						       tc.sent[i].priority)),
+				 GET_STAT(iface, tc.sent[i].priority),
+				 GET_STAT(iface, tc.sent[i].pkts),
+				 GET_STAT(iface, tc.sent[i].bytes));
+		}
+#endif
+
+#if NET_TC_RX_COUNT > 1
+		NET_INFO("RX traffic class statistics:");
+		NET_INFO("TC  Priority\tRecv pkts\tbytes");
+
+		for (i = 0; i < NET_TC_RX_COUNT; i++) {
+			NET_INFO("[%d] %s (%d)\t%d\t\t%d", i,
+				 priority2str(GET_STAT(iface,
+						       tc.recv[i].priority)),
+				 GET_STAT(iface, tc.recv[i].priority),
+				 GET_STAT(iface, tc.recv[i].pkts),
+				 GET_STAT(iface, tc.recv[i].bytes));
+		}
+#endif
+#else /* NET_TC_COUNT > 1 */
+		ARG_UNUSED(i);
+#endif /* NET_TC_COUNT > 1 */
+
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+		NET_INFO("Power management statistics:");
+		NET_INFO("Last suspend time: %u ms",
+			 GET_STAT(iface, pm.last_suspend_time));
+		NET_INFO("Got suspended %d times",
+			 GET_STAT(iface, pm.suspend_count));
+		NET_INFO("Average suspend time: %u ms",
+			 (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) /
+				 GET_STAT(iface, pm.suspend_count)));
+		NET_INFO("Total suspended time: %llu ms",
+			 GET_STAT(iface, pm.overall_suspend_time));
+#endif
+		next_print = curr + PRINT_STATISTICS_INTERVAL;
+	}
+}
+
+void net_print_statistics_iface(struct net_if *iface)
+{
+	/* In order to make the info print lines shorter, use shorter
+	 * function name.
+	 */
+	stats(iface);
+}
+
+static void iface_cb(struct net_if *iface, void *user_data)
+{
+	net_print_statistics_iface(iface);
+}
+
+void net_print_statistics_all(void)
+{
+	net_if_foreach(iface_cb, NULL);
+}
+
+void net_print_statistics(void)
+{
+	net_print_statistics_iface(NULL);
+}
+
+#endif /* CONFIG_NET_STATISTICS_PERIODIC_OUTPUT */
+
+#if defined(CONFIG_NET_STATISTICS_USER_API)
+
+static int net_stats_get(uint32_t mgmt_request, struct net_if *iface,
+			 void *data, size_t len)
+{
+	size_t len_chk = 0;
+	void *src = NULL;
+
+	switch (NET_MGMT_GET_COMMAND(mgmt_request)) {
+	case NET_REQUEST_STATS_CMD_GET_ALL:
+		len_chk = sizeof(struct net_stats);
+#if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
+		src = iface ? &iface->stats : &net_stats;
+#else
+		src = &net_stats;
+#endif
+		break;
+	case NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR:
+		len_chk = sizeof(net_stats_t);
+		src = GET_STAT_ADDR(iface, processing_error);
+		break;
+	case NET_REQUEST_STATS_CMD_GET_BYTES:
+		len_chk = sizeof(struct net_stats_bytes);
+		src = GET_STAT_ADDR(iface, bytes);
+		break;
+	case NET_REQUEST_STATS_CMD_GET_IP_ERRORS:
+		len_chk = sizeof(struct net_stats_ip_errors);
+		src = GET_STAT_ADDR(iface, ip_errors);
+		break;
+#if defined(CONFIG_NET_STATISTICS_IPV4)
+	case NET_REQUEST_STATS_CMD_GET_IPV4:
+		len_chk = sizeof(struct net_stats_ip);
+		src = GET_STAT_ADDR(iface, ipv4);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_IPV6)
+	case NET_REQUEST_STATS_CMD_GET_IPV6:
+		len_chk = sizeof(struct net_stats_ip);
+		src = GET_STAT_ADDR(iface, ipv6);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+	case NET_REQUEST_STATS_CMD_GET_IPV6_ND:
+		len_chk = sizeof(struct net_stats_ipv6_nd);
+		src = GET_STAT_ADDR(iface, ipv6_nd);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_ICMP)
+	case NET_REQUEST_STATS_CMD_GET_ICMP:
+		len_chk = sizeof(struct net_stats_icmp);
+		src = GET_STAT_ADDR(iface, icmp);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_UDP)
+	case NET_REQUEST_STATS_CMD_GET_UDP:
+		len_chk = sizeof(struct net_stats_udp);
+		src = GET_STAT_ADDR(iface, udp);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_TCP)
+	case NET_REQUEST_STATS_CMD_GET_TCP:
+		len_chk = sizeof(struct net_stats_tcp);
+		src = GET_STAT_ADDR(iface, tcp);
+		break;
+#endif
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+	case NET_REQUEST_STATS_GET_PM:
+		len_chk = sizeof(struct net_stats_pm);
+		src = GET_STAT_ADDR(iface, pm);
+		break;
+#endif
+	}
+
+	if (len != len_chk || !src) {
+		return -EINVAL;
+	}
+
+	memcpy(data, src, len);
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL,
+				  net_stats_get);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR,
+				  net_stats_get);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES,
+				  net_stats_get);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS,
+				  net_stats_get);
+
+#if defined(CONFIG_NET_STATISTICS_IPV4)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV4,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_IPV6)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_IPV6_ND)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6_ND,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_ICMP)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ICMP,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_UDP)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_UDP,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_TCP)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_TCP,
+				  net_stats_get);
+#endif
+
+#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM,
+				  net_stats_get);
+#endif
+
+#endif /* CONFIG_NET_STATISTICS_USER_API */
+
+void net_stats_reset(struct net_if *iface)
+{
+	if (iface) {
+		net_if_stats_reset(iface);
+		return;
+	}
+
+	net_if_stats_reset_all();
+	memset(&net_stats, 0, sizeof(net_stats));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc.c	(working copy)
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_tc, CONFIG_NET_TC_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <string.h>
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_stats.h>
+
+#include "net_private.h"
+#include "net_stats.h"
+#include "net_tc_mapping.h"
+
+/* Stacks for TX work queue */
+K_KERNEL_STACK_ARRAY_DEFINE(tx_stack, NET_TC_TX_COUNT,
+			    CONFIG_NET_TX_STACK_SIZE);
+
+/* Stacks for RX work queue */
+K_KERNEL_STACK_ARRAY_DEFINE(rx_stack, NET_TC_RX_COUNT,
+			    CONFIG_NET_RX_STACK_SIZE);
+
+static struct net_traffic_class tx_classes[NET_TC_TX_COUNT];
+static struct net_traffic_class rx_classes[NET_TC_RX_COUNT];
+
+bool net_tc_submit_to_tx_queue(uint8_t tc, struct net_pkt *pkt)
+{
+	if (k_work_pending(net_pkt_work(pkt))) {
+		return false;
+	}
+
+	net_pkt_set_tx_stats_tick(pkt, k_cycle_get_32());
+
+	k_work_submit_to_queue(&tx_classes[tc].work_q, net_pkt_work(pkt));
+
+	return true;
+}
+
+void net_tc_submit_to_rx_queue(uint8_t tc, struct net_pkt *pkt)
+{
+	net_pkt_set_rx_stats_tick(pkt, k_cycle_get_32());
+
+	k_work_submit_to_queue(&rx_classes[tc].work_q, net_pkt_work(pkt));
+}
+
+int net_tx_priority2tc(enum net_priority prio)
+{
+	if (prio > NET_PRIORITY_NC) {
+		/* Use default value suggested in 802.1Q */
+		prio = NET_PRIORITY_BE;
+	}
+
+	return tx_prio2tc_map[prio];
+}
+
+int net_rx_priority2tc(enum net_priority prio)
+{
+	if (prio > NET_PRIORITY_NC) {
+		/* Use default value suggested in 802.1Q */
+		prio = NET_PRIORITY_BE;
+	}
+
+	return rx_prio2tc_map[prio];
+}
+
+/* Convert traffic class to thread priority */
+static uint8_t tx_tc2thread(uint8_t tc)
+{
+	/* Initial implementation just maps the traffic class to certain queue.
+	 * If there are less queues than classes, then map them into
+	 * some specific queue. In order to make this work same way as before,
+	 * the thread priority 7 is used to map the default traffic class so
+	 * this system works same way as before when TX thread default priority
+	 * was 7.
+	 *
+	 * Lower value in this table means higher thread priority. The
+	 * value is used as a parameter to K_PRIO_COOP() which converts it
+	 * to actual thread priority.
+	 *
+	 * Higher traffic class value means higher priority queue. This means
+	 * that thread_priorities[7] value should contain the highest priority
+	 * for the TX queue handling thread.
+	 */
+	static const uint8_t thread_priorities[] = {
+#if NET_TC_TX_COUNT == 1
+		7
+#endif
+#if NET_TC_TX_COUNT == 2
+		8, 7
+#endif
+#if NET_TC_TX_COUNT == 3
+		8, 7, 6
+#endif
+#if NET_TC_TX_COUNT == 4
+		8, 7, 6, 5
+#endif
+#if NET_TC_TX_COUNT == 5
+		8, 7, 6, 5, 4
+#endif
+#if NET_TC_TX_COUNT == 6
+		8, 7, 6, 5, 4, 3
+#endif
+#if NET_TC_TX_COUNT == 7
+		8, 7, 6, 5, 4, 3, 2
+#endif
+#if NET_TC_TX_COUNT == 8
+		8, 7, 6, 5, 4, 3, 2, 1
+#endif
+	};
+
+	BUILD_ASSERT(NET_TC_TX_COUNT <= CONFIG_NUM_COOP_PRIORITIES,
+		     "Too many traffic classes");
+
+	NET_ASSERT(tc < ARRAY_SIZE(thread_priorities));
+
+	return thread_priorities[tc];
+}
+
+/* Convert traffic class to thread priority */
+static uint8_t rx_tc2thread(uint8_t tc)
+{
+	/* Initial implementation just maps the traffic class to certain queue.
+	 * If there are less queues than classes, then map them into
+	 * some specific queue. In order to make this work same way as before,
+	 * the thread priority 7 is used to map the default traffic class so
+	 * this system works same way as before when RX thread default priority
+	 * was 7.
+	 *
+	 * Lower value in this table means higher thread priority. The
+	 * value is used as a parameter to K_PRIO_COOP() which converts it
+	 * to actual thread priority.
+	 *
+	 * Higher traffic class value means higher priority queue. This means
+	 * that thread_priorities[7] value should contain the highest priority
+	 * for the RX queue handling thread.
+	 */
+	static const uint8_t thread_priorities[] = {
+#if NET_TC_RX_COUNT == 1
+		7
+#endif
+#if NET_TC_RX_COUNT == 2
+		8, 7
+#endif
+#if NET_TC_RX_COUNT == 3
+		8, 7, 6
+#endif
+#if NET_TC_RX_COUNT == 4
+		8, 7, 6, 5
+#endif
+#if NET_TC_RX_COUNT == 5
+		8, 7, 6, 5, 4
+#endif
+#if NET_TC_RX_COUNT == 6
+		8, 7, 6, 5, 4, 3
+#endif
+#if NET_TC_RX_COUNT == 7
+		8, 7, 6, 5, 4, 3, 2
+#endif
+#if NET_TC_RX_COUNT == 8
+		8, 7, 6, 5, 4, 3, 2, 1
+#endif
+	};
+
+	BUILD_ASSERT(NET_TC_RX_COUNT <= CONFIG_NUM_COOP_PRIORITIES,
+		     "Too many traffic classes");
+
+	NET_ASSERT(tc < ARRAY_SIZE(thread_priorities));
+
+	return thread_priorities[tc];
+}
+
+#if defined(CONFIG_NET_STATISTICS)
+/* Fixup the traffic class statistics so that "net stats" shell command will
+ * print output correctly.
+ */
+static void tc_tx_stats_priority_setup(struct net_if *iface)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		net_stats_update_tc_sent_priority(iface, net_tx_priority2tc(i),
+						  i);
+	}
+}
+
+static void tc_rx_stats_priority_setup(struct net_if *iface)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		net_stats_update_tc_recv_priority(iface, net_rx_priority2tc(i),
+						  i);
+	}
+}
+
+static void net_tc_tx_stats_priority_setup(struct net_if *iface,
+					   void *user_data)
+{
+	ARG_UNUSED(user_data);
+
+	tc_tx_stats_priority_setup(iface);
+}
+
+static void net_tc_rx_stats_priority_setup(struct net_if *iface,
+					   void *user_data)
+{
+	ARG_UNUSED(user_data);
+
+	tc_rx_stats_priority_setup(iface);
+}
+#endif
+
+/* Create workqueue for each traffic class we are using. All the network
+ * traffic goes through these classes. There needs to be at least one traffic
+ * class in the system.
+ */
+void net_tc_tx_init(void)
+{
+	int i;
+
+	BUILD_ASSERT(NET_TC_TX_COUNT > 0);
+
+#if defined(CONFIG_NET_STATISTICS)
+	net_if_foreach(net_tc_tx_stats_priority_setup, NULL);
+#endif
+
+	for (i = 0; i < NET_TC_TX_COUNT; i++) {
+		uint8_t thread_priority;
+
+		thread_priority = tx_tc2thread(i);
+
+		NET_DBG("[%d] Starting TX queue %p stack size %zd "
+			"prio %d (%d)", i,
+			&tx_classes[i].work_q.queue,
+			K_KERNEL_STACK_SIZEOF(tx_stack[i]),
+			thread_priority, K_PRIO_COOP(thread_priority));
+
+		k_work_q_start(&tx_classes[i].work_q,
+			       tx_stack[i],
+			       K_KERNEL_STACK_SIZEOF(tx_stack[i]),
+			       K_PRIO_COOP(thread_priority));
+		k_thread_name_set(&tx_classes[i].work_q.thread, "tx_workq");
+	}
+}
+
+void net_tc_rx_init(void)
+{
+	int i;
+
+	BUILD_ASSERT(NET_TC_RX_COUNT > 0);
+
+#if defined(CONFIG_NET_STATISTICS)
+	net_if_foreach(net_tc_rx_stats_priority_setup, NULL);
+#endif
+
+	for (i = 0; i < NET_TC_RX_COUNT; i++) {
+		uint8_t thread_priority;
+
+		thread_priority = rx_tc2thread(i);
+
+		NET_DBG("[%d] Starting RX queue %p stack size %zd "
+			"prio %d (%d)", i,
+			&rx_classes[i].work_q.queue,
+			K_KERNEL_STACK_SIZEOF(rx_stack[i]),
+			thread_priority, K_PRIO_COOP(thread_priority));
+
+		k_work_q_start(&rx_classes[i].work_q,
+			       rx_stack[i],
+			       K_KERNEL_STACK_SIZEOF(rx_stack[i]),
+			       K_PRIO_COOP(thread_priority));
+		k_thread_name_set(&rx_classes[i].work_q.thread, "rx_workq");
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc_mapping.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc_mapping.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/net_tc_mapping.h	(working copy)
@@ -0,0 +1,138 @@
+/** @file
+ * @brief Various priority to traffic class mappings
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __TC_MAPPING_H
+#define __TC_MAPPING_H
+
+#include <zephyr/types.h>
+
+/* All the maps below use priorities and indexes, below is the list of them
+ * according to 802.1Q - table I-2.
+ *
+ *  Priority         Acronym   Traffic types
+ *  1 (lowest)       BK        Background
+ *  0 (default)      BE        Best effort
+ *  2                EE        Excellent effort
+ *  3                CA        Critical applications
+ *  4                VI        Video, < 100 ms latency and jitter
+ *  5                VO        Voice, < 10 ms latency and jitter
+ *  6                IC        Internetwork control
+ *  7 (highest)      NC        Network control
+ */
+
+/* Helper macros used to generate the map to use */
+#define PRIORITY2TC_GEN_INNER(TYPE, COUNT) priority2tc_ ## TYPE ## _ ## COUNT
+#define PRIORITY2TC_GEN(TYPE, COUNT) PRIORITY2TC_GEN_INNER(TYPE, COUNT)
+
+#if defined(CONFIG_NET_TC_MAPPING_STRICT)
+
+/* This is the recommended priority to traffic class mapping for
+ * implementations that do not support the credit-based shaper transmission
+ * selection algorithm.
+ * Ref: 802.1Q - chapter 8.6.6 - table 8-4
+ */
+
+#if NET_TC_TX_COUNT == 1 || NET_TC_RX_COUNT == 1
+static const uint8_t priority2tc_strict_1[] = {0, 0, 0, 0, 0, 0, 0, 0};
+#endif
+#if NET_TC_TX_COUNT == 2 || NET_TC_RX_COUNT == 2
+static const uint8_t priority2tc_strict_2[] = {0, 0, 0, 0, 1, 1, 1, 1};
+#endif
+#if NET_TC_TX_COUNT == 3 || NET_TC_RX_COUNT == 3
+static const uint8_t priority2tc_strict_3[] = {0, 0, 0, 0, 1, 1, 2, 2};
+#endif
+#if NET_TC_TX_COUNT == 4 || NET_TC_RX_COUNT == 4
+static const uint8_t priority2tc_strict_4[] = {0, 0, 1, 1, 2, 2, 3, 3};
+#endif
+#if NET_TC_TX_COUNT == 5 || NET_TC_RX_COUNT == 5
+static const uint8_t priority2tc_strict_5[] = {0, 0, 1, 1, 2, 2, 3, 4};
+#endif
+#if NET_TC_TX_COUNT == 6 || NET_TC_RX_COUNT == 6
+static const uint8_t priority2tc_strict_6[] = {1, 0, 2, 2, 3, 3, 4, 5};
+#endif
+#if NET_TC_TX_COUNT == 7 || NET_TC_RX_COUNT == 7
+static const uint8_t priority2tc_strict_7[] = {1, 0, 2, 3, 4, 4, 5, 6};
+#endif
+#if NET_TC_TX_COUNT == 8 || NET_TC_RX_COUNT == 8
+static const uint8_t priority2tc_strict_8[] = {1, 0, 2, 3, 4, 5, 6, 7};
+#endif
+
+static const uint8_t *tx_prio2tc_map = PRIORITY2TC_GEN(strict, NET_TC_TX_COUNT);
+static const uint8_t *rx_prio2tc_map = PRIORITY2TC_GEN(strict, NET_TC_RX_COUNT);
+
+#elif defined(CONFIG_NET_TC_MAPPING_SR_CLASS_A_AND_B)
+
+/* This is the recommended priority to traffic class mapping for a system that
+ * supports SR (Stream Reservation) class A and SR class B.
+ * Ref: 802.1Q - chapter 34.5 - table 34-1
+ */
+
+#if NET_TC_TX_COUNT == 2 || NET_TC_RX_COUNT == 2
+static const uint8_t priority2tc_sr_ab_2[] = {0, 0, 1, 1, 0, 0, 0, 0};
+#endif
+#if NET_TC_TX_COUNT == 3 || NET_TC_RX_COUNT == 3
+static const uint8_t priority2tc_sr_ab_3[] = {0, 0, 1, 2, 0, 0, 0, 0};
+#endif
+#if NET_TC_TX_COUNT == 4 || NET_TC_RX_COUNT == 4
+static const uint8_t priority2tc_sr_ab_4[] = {0, 0, 2, 3, 1, 1, 1, 1};
+#endif
+#if NET_TC_TX_COUNT == 5 || NET_TC_RX_COUNT == 5
+static const uint8_t priority2tc_sr_ab_5[] = {0, 0, 3, 4, 1, 1, 2, 2};
+#endif
+#if NET_TC_TX_COUNT == 6 || NET_TC_RX_COUNT == 6
+static const uint8_t priority2tc_sr_ab_6[] = {0, 0, 4, 5, 1, 1, 2, 3};
+#endif
+#if NET_TC_TX_COUNT == 7 || NET_TC_RX_COUNT == 7
+static const uint8_t priority2tc_sr_ab_7[] = {0, 0, 5, 6, 1, 2, 3, 4};
+#endif
+#if NET_TC_TX_COUNT == 8 || NET_TC_RX_COUNT == 8
+static const uint8_t priority2tc_sr_ab_8[] = {1, 0, 6, 7, 2, 3, 4, 5};
+#endif
+
+static const uint8_t *tx_prio2tc_map = PRIORITY2TC_GEN(sr_ab, NET_TC_TX_COUNT);
+static const uint8_t *rx_prio2tc_map = PRIORITY2TC_GEN(sr_ab, NET_TC_RX_COUNT);
+
+#elif defined(CONFIG_NET_TC_MAPPING_SR_CLASS_B_ONLY)
+
+/* This is the recommended priority to traffic class mapping for a system that
+ * supports SR (Stream Reservation) class B only.
+ * Ref: 802.1Q - chapter 34.5 - table 34-2
+ */
+
+#if NET_TC_TX_COUNT == 2 || NET_TC_RX_COUNT == 2
+static const uint8_t priority2tc_sr_b_2[] = {0, 0, 1, 0, 0, 0, 0, 0};
+#endif
+#if NET_TC_TX_COUNT == 3 || NET_TC_RX_COUNT == 3
+static const uint8_t priority2tc_sr_b_3[] = {0, 0, 2, 0, 1, 1, 1, 1};
+#endif
+#if NET_TC_TX_COUNT == 4 || NET_TC_RX_COUNT == 4
+static const uint8_t priority2tc_sr_b_4[] = {0, 0, 3, 0, 1, 1, 2, 2};
+#endif
+#if NET_TC_TX_COUNT == 5 || NET_TC_RX_COUNT == 5
+static const uint8_t priority2tc_sr_b_5[] = {0, 0, 4, 1, 2, 2, 3, 3};
+#endif
+#if NET_TC_TX_COUNT == 6 || NET_TC_RX_COUNT == 6
+static const uint8_t priority2tc_sr_b_6[] = {0, 0, 5, 1, 2, 2, 3, 4};
+#endif
+#if NET_TC_TX_COUNT == 7 || NET_TC_RX_COUNT == 7
+static const uint8_t priority2tc_sr_b_7[] = {1, 0, 6, 2, 3, 3, 4, 5};
+#endif
+#if NET_TC_TX_COUNT == 8 || NET_TC_RX_COUNT == 8
+static const uint8_t priority2tc_sr_b_8[] = {1, 0, 7, 2, 3, 4, 5, 6};
+#endif
+
+static const uint8_t *tx_prio2tc_map = PRIORITY2TC_GEN(sr_b, NET_TC_TX_COUNT);
+static const uint8_t *rx_prio2tc_map = PRIORITY2TC_GEN(sr_b, NET_TC_RX_COUNT);
+
+#endif
+
+#endif /* __TC_MAPPING_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.h	(working copy)
@@ -0,0 +1,37 @@
+/** @file
+ * @brief Packet Socket related functions
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __PACKET_SOCKET_H
+#define __PACKET_SOCKET_H
+
+#include <zephyr/types.h>
+
+/**
+ * @brief Called by net_core.c when a network packet is received.
+ *
+ * @param pkt Network packet
+ *
+ * @return NET_OK if the packet was consumed, NET_DROP if
+ * the packet parsing failed and the caller should handle
+ * the received packet. If corresponding IP protocol support is
+ * disabled, the function will always return NET_DROP.
+ */
+#if defined(CONFIG_NET_SOCKETS_PACKET)
+enum net_verdict net_packet_socket_input(struct net_pkt *pkt);
+#else
+static inline enum net_verdict net_packet_socket_input(struct net_pkt *pkt)
+{
+	return NET_CONTINUE;
+}
+#endif
+
+#endif /* __PACKET_SOCKET_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/packet_socket.c	(working copy)
@@ -0,0 +1,42 @@
+/** @file
+ * @brief Packet Sockets related functions
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sockets_raw, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_pkt.h>
+#include <net/net_context.h>
+#include <net/ethernet.h>
+
+#include "connection.h"
+#include "packet_socket.h"
+
+enum net_verdict net_packet_socket_input(struct net_pkt *pkt)
+{
+	/* Currently we are skipping L2 layer verification and not
+	 * removing L2 header from packet.
+	 * TODO :
+	 * 1) Pass it through L2 layer, so that L2 will verify
+	 * that packet is intended to us or not and sets src and dst lladdr.
+	 * And L2 should not pull off L2 header when combination of socket
+	 * like this AF_PACKET, SOCK_RAW and ETH_P_ALL proto.
+	 * 2) Socket combination of AF_INET, SOCK_RAW, IPPROTO_RAW
+	 * packet has to go through L2 and L2 verfies it's header and removes
+	 * header. Only packet with L3 header will be given to socket.
+	 * 3) If user opens raw and non raw socket together, based on raw
+	 * socket combination packet has to be feed to raw socket and only
+	 * data part to be feed to non raw socket.
+	 */
+
+	net_pkt_set_family(pkt, AF_PACKET);
+
+	return net_conn_input(pkt, NULL, ETH_P_ALL, NULL);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/promiscuous.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/promiscuous.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/promiscuous.c	(working copy)
@@ -0,0 +1,98 @@
+/** @file
+ * @brief Promiscuous mode support
+ *
+ * Allow user to receive all network packets that are seen by a
+ * network interface. This requires that network device driver
+ * supports promiscuous mode.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_promisc, CONFIG_NET_PROMISC_LOG_LEVEL);
+
+#include <kernel.h>
+#include <errno.h>
+
+#include <net/net_if.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+static K_FIFO_DEFINE(promiscuous_queue);
+static atomic_t enabled = ATOMIC_INIT(0);
+
+struct net_pkt *net_promisc_mode_wait_data(k_timeout_t timeout)
+{
+	return k_fifo_get(&promiscuous_queue, timeout);
+}
+
+int net_promisc_mode_on(struct net_if *iface)
+{
+	int ret;
+
+	if (!iface) {
+		return -EINVAL;
+	}
+
+	ret = net_if_set_promisc(iface);
+	if (!ret) {
+		atomic_inc(&enabled);
+	}
+
+	return ret;
+}
+
+static void flush_queue(void)
+{
+	struct net_pkt *pkt;
+
+	while (1) {
+		pkt = k_fifo_get(&promiscuous_queue, K_NO_WAIT);
+		if (!pkt) {
+			return;
+		}
+
+		net_pkt_unref(pkt);
+	}
+}
+
+int net_promisc_mode_off(struct net_if *iface)
+{
+	atomic_val_t prev;
+	bool ret;
+
+	ret = net_if_is_promisc(iface);
+	if (ret) {
+		net_if_unset_promisc(iface);
+
+		prev = atomic_dec(&enabled);
+		if (prev == 1) {
+			atomic_clear(&enabled);
+
+			flush_queue();
+		}
+
+		return 0;
+	}
+
+	return -EALREADY;
+}
+
+enum net_verdict net_promisc_mode_input(struct net_pkt *pkt)
+{
+	if (!pkt) {
+		return NET_CONTINUE;
+	}
+
+	if (!atomic_get(&enabled)) {
+		return NET_DROP;
+	}
+
+	k_fifo_put(&promiscuous_queue, pkt);
+
+	return NET_OK;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/route.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/route.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/route.h	(working copy)
@@ -0,0 +1,303 @@
+/** @file
+ * @brief Route handler
+ *
+ * This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ROUTE_H
+#define __ROUTE_H
+
+#include <kernel.h>
+#include <sys/slist.h>
+
+#include <net/net_ip.h>
+
+#include "nbr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Next hop entry for a given route.
+ */
+struct net_route_nexthop {
+	/** Pointer to nexthop that has same route to a specific
+	 * neighbor.
+	 */
+	sys_snode_t node;
+
+	/** Next hop neighbor */
+	struct net_nbr *nbr;
+};
+
+/**
+ * @brief Route entry to a specific neighbor.
+ */
+struct net_route_entry {
+	/** Node information. The routes are also in separate list in
+	 * order to keep track which one of them is the oldest so that
+	 * we can remove it if we run out of available routes.
+	 * The oldest one is the last entry in the list.
+	 */
+	sys_snode_t node;
+
+	/** List of neighbors that the routes go through. */
+	sys_slist_t nexthop;
+
+	/** Network interface for the route. */
+	struct net_if *iface;
+
+	/** IPv6 address/prefix of the route. */
+	struct in6_addr addr;
+
+	/** IPv6 address/prefix length. */
+	uint8_t prefix_len;
+};
+
+/**
+ * @brief Lookup route to a given destination.
+ *
+ * @param iface Network interface. If NULL, then check against all interfaces.
+ * @param dst Destination IPv6 address.
+ *
+ * @return Return route entry related to a given destination address, NULL
+ * if not found.
+ */
+#if defined(CONFIG_NET_NATIVE)
+struct net_route_entry *net_route_lookup(struct net_if *iface,
+					 struct in6_addr *dst);
+#else
+static inline struct net_route_entry *net_route_lookup(struct net_if *iface,
+						       struct in6_addr *dst)
+{
+	ARG_UNUSED(iface);
+	ARG_UNUSED(dst);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Add a route to routing table.
+ *
+ * @param iface Network interface that this route is tied to.
+ * @param addr IPv6 address.
+ * @param prefix_len Length of the IPv6 address/prefix.
+ * @param nexthop IPv6 address of the Next hop device.
+ *
+ * @return Return created route entry, NULL if could not be created.
+ */
+struct net_route_entry *net_route_add(struct net_if *iface,
+				      struct in6_addr *addr,
+				      uint8_t prefix_len,
+				      struct in6_addr *nexthop);
+
+/**
+ * @brief Delete a route from routing table.
+ *
+ * @param entry Existing route entry.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int net_route_del(struct net_route_entry *entry);
+
+/**
+ * @brief Delete a route from routing table by nexthop.
+ *
+ * @param iface Network interface to use.
+ * @param nexthop IPv6 address of the nexthop device.
+ *
+ * @return number of routes deleted, <0 if error
+ */
+int net_route_del_by_nexthop(struct net_if *iface,
+			     struct in6_addr *nexthop);
+
+/**
+ * @brief Delete a route from routing table by nexthop if the routing engine
+ * specific data matches.
+ *
+ * @detail The routing engine specific data could be the RPL data.
+ *
+ * @param iface Network interface to use.
+ * @param nexthop IPv6 address of the nexthop device.
+ * @param data Routing engine specific data.
+ *
+ * @return number of routes deleted, <0 if error
+ */
+int net_route_del_by_nexthop_data(struct net_if *iface,
+				  struct in6_addr *nexthop,
+				  void *data);
+
+/**
+ * @brief Get nexthop IPv6 address tied to this route.
+ *
+ * There can be multiple routes to a host but this function
+ * will only return the first one in this version.
+ *
+ * @param entry Route entry to use.
+ *
+ * @return IPv6 address of the nexthop, NULL if not found.
+ */
+struct in6_addr *net_route_get_nexthop(struct net_route_entry *entry);
+
+/**
+ * @brief Get generic neighbor entry from route entry.
+ *
+ * @param route Pointer to routing entry.
+ *
+ * @return Generic neighbor entry.
+ */
+struct net_nbr *net_route_get_nbr(struct net_route_entry *route);
+
+typedef void (*net_route_cb_t)(struct net_route_entry *entry,
+			       void *user_data);
+
+/**
+ * @brief Go through all the routing entries and call callback
+ * for each entry that is in use.
+ *
+ * @param cb User supplied callback function to call.
+ * @param user_data User specified data.
+ *
+ * @return Total number of routing entries found.
+ */
+int net_route_foreach(net_route_cb_t cb, void *user_data);
+
+/**
+ * @brief Multicast route entry.
+ */
+struct net_route_entry_mcast {
+	/** Network interface for the route. */
+	struct net_if *iface;
+
+	/** Extra routing engine specific data */
+	void *data;
+
+	/** IPv6 multicast group of the route. */
+	struct in6_addr group;
+
+	/** Routing entry lifetime in seconds. */
+	uint32_t lifetime;
+
+	/** Is this entry in use or not */
+	bool is_used;
+
+	/** IPv6 multicast group prefix length. */
+	uint8_t prefix_len;
+};
+
+typedef void (*net_route_mcast_cb_t)(struct net_route_entry_mcast *entry,
+				     void *user_data);
+
+/**
+ * @brief Forwards a multicast packet by checking the local multicast
+ * routing table
+ *
+ * @param pkt The original received ipv6 packet to forward
+ * @param hdr The IPv6 header of the packet
+ *
+ * @return Number of interfaces which forwarded the packet, or a negative
+ * value in case of an error.
+ */
+int net_route_mcast_forward_packet(struct net_pkt *pkt,
+				   const struct net_ipv6_hdr *hdr);
+
+/**
+ * @brief Go through all the multicast routing entries and call callback
+ * for each entry that is in use.
+ *
+ * @param cb User supplied callback function to call.
+ * @param skip Do not call callback for this address.
+ * @param user_data User specified data.
+ *
+ * @return Total number of multicast routing entries that are in use.
+ */
+int net_route_mcast_foreach(net_route_mcast_cb_t cb,
+			    struct in6_addr *skip,
+			    void *user_data);
+
+/**
+ * @brief Add a multicast routing entry.
+ *
+ * @param iface Network interface to use.
+ * @param group IPv6 multicast address.
+ * @param prefix_len Length of the IPv6 group that must match.
+ *
+ * @return Multicast routing entry.
+ */
+struct net_route_entry_mcast *net_route_mcast_add(struct net_if *iface,
+						  struct in6_addr *group,
+						  uint8_t prefix_len);
+
+/**
+ * @brief Delete a multicast routing entry.
+ *
+ * @param route Multicast routing entry.
+ *
+ * @return True if entry was deleted, false otherwise.
+ */
+bool net_route_mcast_del(struct net_route_entry_mcast *route);
+
+/**
+ * @brief Lookup a multicast routing entry.
+ *
+ * @param group IPv6 multicast group address
+ *
+ * @return Routing entry corresponding this multicast group.
+ */
+struct net_route_entry_mcast *
+net_route_mcast_lookup(struct in6_addr *group);
+
+/**
+ * @brief Return a route to destination via some intermediate host.
+ *
+ * @param iface Network interface
+ * @param dst Destination IPv6 address
+ * @param route Route entry to destination is returned.
+ * @param nexthop Next hop neighbor IPv6 address is returned.
+ *
+ * @return True if there is a route to the destination, False otherwise
+ */
+bool net_route_get_info(struct net_if *iface,
+			struct in6_addr *dst,
+			struct net_route_entry **route,
+			struct in6_addr **nexthop);
+
+/**
+ * @brief Send the network packet to network via some intermediate host.
+ *
+ * @param pkt Network packet to send.
+ * @param nexthop Next hop neighbor IPv6 address.
+ *
+ * @return 0 if there was no error, <0 if the packet could not be sent.
+ */
+int net_route_packet(struct net_pkt *pkt, struct in6_addr *nexthop);
+
+/**
+ * @brief Send the network packet to network via the given interface.
+ *
+ * @param pkt Network packet to send.
+ * @param iface The network interface the packet should be sent on.
+ *
+ * @return 0 if there was no error, <0 if the packet could not be sent.
+ */
+int net_route_packet_if(struct net_pkt *pkt, struct net_if *iface);
+
+#if defined(CONFIG_NET_ROUTE) && defined(CONFIG_NET_NATIVE)
+void net_route_init(void);
+#else
+#define net_route_init(...)
+#endif /* CONFIG_NET_ROUTE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ROUTE_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/route.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/route.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/route.c	(working copy)
@@ -0,0 +1,918 @@
+/** @file
+ * @brief Route handling.
+ *
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_route, CONFIG_NET_ROUTE_LOG_LEVEL);
+
+#include <kernel.h>
+#include <limits.h>
+#include <zephyr/types.h>
+#include <sys/slist.h>
+
+#include <net/net_pkt.h>
+#include <net/net_core.h>
+#include <net/net_stats.h>
+#include <net/net_mgmt.h>
+#include <net/net_ip.h>
+
+#include "net_private.h"
+#include "ipv6.h"
+#include "icmpv6.h"
+#include "nbr.h"
+#include "route.h"
+
+#if !defined(NET_ROUTE_EXTRA_DATA_SIZE)
+#define NET_ROUTE_EXTRA_DATA_SIZE 0
+#endif
+
+/* We keep track of the routes in a separate list so that we can remove
+ * the oldest routes (at tail) if needed.
+ */
+static sys_slist_t routes;
+
+static void net_route_nexthop_remove(struct net_nbr *nbr)
+{
+	NET_DBG("Nexthop %p removed", nbr);
+}
+
+/*
+ * This pool contains information next hop neighbors.
+ */
+NET_NBR_POOL_INIT(net_route_nexthop_pool,
+		  CONFIG_NET_MAX_NEXTHOPS,
+		  sizeof(struct net_route_nexthop),
+		  net_route_nexthop_remove,
+		  0);
+
+static inline struct net_route_nexthop *net_nexthop_data(struct net_nbr *nbr)
+{
+	return (struct net_route_nexthop *)nbr->data;
+}
+
+static inline struct net_nbr *get_nexthop_nbr(struct net_nbr *start, int idx)
+{
+	NET_ASSERT(idx < CONFIG_NET_MAX_NEXTHOPS, "idx %d >= max %d",
+		   idx, CONFIG_NET_MAX_NEXTHOPS);
+
+	return (struct net_nbr *)((uint8_t *)start +
+			((sizeof(struct net_nbr) + start->size) * idx));
+}
+
+static struct net_nbr *get_nexthop_route(void)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_NEXTHOPS; i++) {
+		struct net_nbr *nbr = get_nexthop_nbr(
+			(struct net_nbr *)net_route_nexthop_pool, i);
+
+		if (!nbr->ref) {
+			nbr->data = nbr->__nbr;
+
+			nbr->idx = NET_NBR_LLADDR_UNKNOWN;
+
+			return net_nbr_ref(nbr);
+		}
+	}
+
+	return NULL;
+}
+
+static void net_route_entry_remove(struct net_nbr *nbr)
+{
+	NET_DBG("Route %p removed", nbr);
+}
+
+static void net_route_entries_table_clear(struct net_nbr_table *table)
+{
+	NET_DBG("Route table %p cleared", table);
+}
+
+/*
+ * This pool contains routing table entries.
+ */
+NET_NBR_POOL_INIT(net_route_entries_pool,
+		  CONFIG_NET_MAX_ROUTES,
+		  sizeof(struct net_route_entry),
+		  net_route_entry_remove,
+		  NET_ROUTE_EXTRA_DATA_SIZE);
+
+NET_NBR_TABLE_INIT(NET_NBR_LOCAL, nbr_routes, net_route_entries_pool,
+		   net_route_entries_table_clear);
+
+static inline struct net_nbr *get_nbr(int idx)
+{
+	return &net_route_entries_pool[idx].nbr;
+}
+
+static inline struct net_route_entry *net_route_data(struct net_nbr *nbr)
+{
+	return (struct net_route_entry *)nbr->data;
+}
+
+struct net_nbr *net_route_get_nbr(struct net_route_entry *route)
+{
+	int i;
+
+	NET_ASSERT(route);
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		if (nbr->data == (uint8_t *)route) {
+			if (!nbr->ref) {
+				return NULL;
+			}
+
+			return nbr;
+		}
+	}
+
+	return NULL;
+}
+
+void net_routes_print(void)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		NET_DBG("[%d] %p %d addr %s/%d",
+			i, nbr, nbr->ref,
+			log_strdup(net_sprint_ipv6_addr(
+					   &net_route_data(nbr)->addr)),
+			net_route_data(nbr)->prefix_len);
+		NET_DBG("    iface %p idx %d ll %s",
+			nbr->iface, nbr->idx,
+			nbr->idx == NET_NBR_LLADDR_UNKNOWN ? "?" :
+			log_strdup(net_sprint_ll_addr(
+				net_nbr_get_lladdr(nbr->idx)->addr,
+				net_nbr_get_lladdr(nbr->idx)->len)));
+	}
+}
+
+static inline void nbr_free(struct net_nbr *nbr)
+{
+	NET_DBG("nbr %p", nbr);
+
+	net_nbr_unref(nbr);
+}
+
+static struct net_nbr *nbr_new(struct net_if *iface,
+			       struct in6_addr *addr,
+			       uint8_t prefix_len)
+{
+	struct net_nbr *nbr = net_nbr_get(&net_nbr_routes.table);
+
+	if (!nbr) {
+		return NULL;
+	}
+
+	nbr->iface = iface;
+
+	net_ipaddr_copy(&net_route_data(nbr)->addr, addr);
+	net_route_data(nbr)->prefix_len = prefix_len;
+
+	NET_DBG("[%d] nbr %p iface %p IPv6 %s/%d",
+		nbr->idx, nbr, iface,
+		log_strdup(net_sprint_ipv6_addr(&net_route_data(nbr)->addr)),
+		prefix_len);
+
+	return nbr;
+}
+
+static struct net_nbr *nbr_nexthop_get(struct net_if *iface,
+				       struct in6_addr *addr)
+{
+	/* Note that the nexthop host must be already in the neighbor
+	 * cache. We just increase the ref count of an existing entry.
+	 */
+	struct net_nbr *nbr;
+
+	nbr = net_ipv6_nbr_lookup(iface, addr);
+	if (nbr == NULL) {
+		NET_DBG("Next hop neighbor not found!");
+		return NULL;
+	}
+
+	NET_ASSERT(nbr->idx != NET_NBR_LLADDR_UNKNOWN,
+		   "Nexthop %s not in neighbor cache!",
+		   log_strdup(net_sprint_ipv6_addr(addr)));
+
+	net_nbr_ref(nbr);
+
+	NET_DBG("[%d] nbr %p iface %p IPv6 %s",
+		nbr->idx, nbr, iface,
+		log_strdup(net_sprint_ipv6_addr(addr)));
+
+	return nbr;
+}
+
+static int nbr_nexthop_put(struct net_nbr *nbr)
+{
+	NET_ASSERT(nbr);
+
+	NET_DBG("[%d] nbr %p iface %p", nbr->idx, nbr, nbr->iface);
+
+	net_nbr_unref(nbr);
+
+	return 0;
+}
+
+
+#define net_route_info(str, route, dst)					\
+	do {								\
+	if (CONFIG_NET_ROUTE_LOG_LEVEL >= LOG_LEVEL_DBG) {		\
+		struct in6_addr *naddr = net_route_get_nexthop(route);	\
+									\
+		NET_ASSERT(naddr, "Unknown nexthop address");	\
+									\
+		NET_DBG("%s route to %s via %s (iface %p)", str,	\
+			log_strdup(net_sprint_ipv6_addr(dst)),		\
+			log_strdup(net_sprint_ipv6_addr(naddr)),	\
+			route->iface);					\
+	} } while (0)
+
+/* Route was accessed, so place it in front of the routes list */
+static inline void update_route_access(struct net_route_entry *route)
+{
+	sys_slist_find_and_remove(&routes, &route->node);
+	sys_slist_prepend(&routes, &route->node);
+}
+
+struct net_route_entry *net_route_lookup(struct net_if *iface,
+					 struct in6_addr *dst)
+{
+	struct net_route_entry *route, *found = NULL;
+	uint8_t longest_match = 0U;
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES && longest_match < 128; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+
+		if (!nbr->ref) {
+			continue;
+		}
+
+		if (iface && nbr->iface != iface) {
+			continue;
+		}
+
+		route = net_route_data(nbr);
+
+		if (route->prefix_len >= longest_match &&
+		    net_ipv6_is_prefix(dst->s6_addr,
+				       route->addr.s6_addr,
+				       route->prefix_len)) {
+			found = route;
+			longest_match = route->prefix_len;
+		}
+	}
+
+	if (found) {
+		net_route_info("Found", found, dst);
+
+		update_route_access(found);
+	}
+
+	return found;
+}
+
+struct net_route_entry *net_route_add(struct net_if *iface,
+				      struct in6_addr *addr,
+				      uint8_t prefix_len,
+				      struct in6_addr *nexthop)
+{
+	struct net_linkaddr_storage *nexthop_lladdr;
+	struct net_nbr *nbr, *nbr_nexthop, *tmp;
+	struct net_route_nexthop *nexthop_route;
+	struct net_route_entry *route;
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+       struct net_event_ipv6_route info;
+#endif
+
+	NET_ASSERT(addr);
+	NET_ASSERT(iface);
+	NET_ASSERT(nexthop);
+
+	if (net_ipv6_addr_cmp(addr, net_ipv6_unspecified_address())) {
+		NET_DBG("Route cannot be towards unspecified address");
+		return NULL;
+	}
+
+	nbr_nexthop = net_ipv6_nbr_lookup(iface, nexthop);
+	if (!nbr_nexthop) {
+		NET_DBG("No such neighbor %s found",
+			log_strdup(net_sprint_ipv6_addr(nexthop)));
+		return NULL;
+	}
+
+	nexthop_lladdr = net_nbr_get_lladdr(nbr_nexthop->idx);
+
+	NET_ASSERT(nexthop_lladdr);
+
+	NET_DBG("Nexthop %s lladdr is %s",
+		log_strdup(net_sprint_ipv6_addr(nexthop)),
+		log_strdup(net_sprint_ll_addr(nexthop_lladdr->addr,
+					      nexthop_lladdr->len)));
+
+	route = net_route_lookup(iface, addr);
+	if (route) {
+		/* Update nexthop if not the same */
+		struct in6_addr *nexthop_addr;
+
+		nexthop_addr = net_route_get_nexthop(route);
+		if (nexthop_addr && net_ipv6_addr_cmp(nexthop, nexthop_addr)) {
+			NET_DBG("No changes, return old route %p", route);
+			return route;
+		}
+
+		NET_DBG("Old route to %s found",
+			log_strdup(net_sprint_ipv6_addr(nexthop_addr)));
+
+		net_route_del(route);
+	}
+
+	nbr = nbr_new(iface, addr, prefix_len);
+	if (!nbr) {
+		/* Remove the oldest route and try again */
+		sys_snode_t *last = sys_slist_peek_tail(&routes);
+
+		sys_slist_find_and_remove(&routes, last);
+
+		route = CONTAINER_OF(last,
+				     struct net_route_entry,
+				     node);
+
+		if (CONFIG_NET_ROUTE_LOG_LEVEL >= LOG_LEVEL_DBG) {
+			struct in6_addr *tmp;
+			struct net_linkaddr_storage *llstorage;
+
+			tmp = net_route_get_nexthop(route);
+			nbr = net_ipv6_nbr_lookup(iface, tmp);
+			if (nbr) {
+				llstorage = net_nbr_get_lladdr(nbr->idx);
+
+				NET_DBG("Removing the oldest route %s "
+					"via %s [%s]",
+					log_strdup(net_sprint_ipv6_addr(
+							   &route->addr)),
+					log_strdup(net_sprint_ipv6_addr(tmp)),
+					log_strdup(net_sprint_ll_addr(
+							   llstorage->addr,
+							   llstorage->len)));
+			}
+		}
+
+		net_route_del(route);
+
+		nbr = nbr_new(iface, addr, prefix_len);
+		if (!nbr) {
+			NET_ERR("Neighbor route alloc failed!");
+			return NULL;
+		}
+	}
+
+	tmp = get_nexthop_route();
+	if (!tmp) {
+		NET_ERR("No nexthop route available!");
+		return NULL;
+	}
+
+	nexthop_route = net_nexthop_data(tmp);
+
+	route = net_route_data(nbr);
+	route->iface = iface;
+
+	sys_slist_prepend(&routes, &route->node);
+
+	tmp = nbr_nexthop_get(iface, nexthop);
+
+	NET_ASSERT(tmp == nbr_nexthop);
+
+	nexthop_route->nbr = tmp;
+
+	sys_slist_init(&route->nexthop);
+	sys_slist_prepend(&route->nexthop, &nexthop_route->node);
+
+	net_route_info("Added", route, addr);
+
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	net_ipaddr_copy(&info.addr, addr);
+	net_ipaddr_copy(&info.nexthop, nexthop);
+	info.prefix_len = prefix_len;
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_ROUTE_ADD,
+					iface, (void *) &info,
+					sizeof(struct net_event_ipv6_route));
+#else
+	net_mgmt_event_notify(NET_EVENT_IPV6_ROUTE_ADD, iface);
+#endif
+
+	return route;
+}
+
+int net_route_del(struct net_route_entry *route)
+{
+	struct net_nbr *nbr;
+	struct net_route_nexthop *nexthop_route;
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+       struct net_event_ipv6_route info;
+#endif
+
+	if (!route) {
+		return -EINVAL;
+	}
+
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	net_ipaddr_copy(&info.addr, &route->addr);
+	info.prefix_len = route->prefix_len;
+	net_ipaddr_copy(&info.nexthop,
+			net_route_get_nexthop(route));
+
+	net_mgmt_event_notify_with_info(NET_EVENT_IPV6_ROUTE_DEL,
+					route->iface, (void *) &info,
+					sizeof(struct net_event_ipv6_route));
+#else
+	net_mgmt_event_notify(NET_EVENT_IPV6_ROUTE_DEL, route->iface);
+#endif
+
+	sys_slist_find_and_remove(&routes, &route->node);
+
+	nbr = net_route_get_nbr(route);
+	if (!nbr) {
+		return -ENOENT;
+	}
+
+	net_route_info("Deleted", route, &route->addr);
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&route->nexthop, nexthop_route, node) {
+		if (!nexthop_route->nbr) {
+			continue;
+		}
+
+		nbr_nexthop_put(nexthop_route->nbr);
+	}
+
+	nbr_free(nbr);
+
+	return 0;
+}
+
+int net_route_del_by_nexthop(struct net_if *iface, struct in6_addr *nexthop)
+{
+	int count = 0, status = 0;
+	struct net_nbr *nbr_nexthop;
+	struct net_route_nexthop *nexthop_route;
+	int i, ret;
+
+	NET_ASSERT(iface);
+	NET_ASSERT(nexthop);
+
+	nbr_nexthop = net_ipv6_nbr_lookup(iface, nexthop);
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+		struct net_route_entry *route = net_route_data(nbr);
+
+		if (!route) {
+			continue;
+		}
+
+		SYS_SLIST_FOR_EACH_CONTAINER(&route->nexthop, nexthop_route,
+					     node) {
+			if (nexthop_route->nbr == nbr_nexthop) {
+				/* This route contains this nexthop */
+				ret = net_route_del(route);
+				if (!ret) {
+					count++;
+				} else {
+					status = ret;
+				}
+				break;
+			}
+		}
+	}
+
+	if (count) {
+		return count;
+	} else if (status < 0) {
+		return status;
+	}
+
+	return 0;
+}
+
+int net_route_del_by_nexthop_data(struct net_if *iface,
+				  struct in6_addr *nexthop,
+				  void *data)
+{
+	int count = 0, status = 0;
+	struct net_nbr *nbr_nexthop;
+	struct net_route_nexthop *nexthop_route;
+	int i, ret;
+
+	NET_ASSERT(iface);
+	NET_ASSERT(nexthop);
+
+	nbr_nexthop = net_ipv6_nbr_lookup(iface, nexthop);
+	if (!nbr_nexthop) {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES; i++) {
+		struct net_nbr *nbr = get_nbr(i);
+		struct net_route_entry *route = net_route_data(nbr);
+
+		SYS_SLIST_FOR_EACH_CONTAINER(&route->nexthop, nexthop_route,
+					     node) {
+			void *extra_data;
+
+			if (nexthop_route->nbr != nbr_nexthop) {
+				continue;
+			}
+
+			if (nbr->extra_data_size == 0U) {
+				continue;
+			}
+
+			/* Routing engine specific extra data needs
+			 * to match too.
+			 */
+			extra_data = net_nbr_extra_data(nbr_nexthop);
+			if (extra_data != data) {
+				continue;
+			}
+
+			ret = net_route_del(route);
+			if (!ret) {
+				count++;
+			} else {
+				status = ret;
+			}
+
+			break;
+		}
+	}
+
+	if (count) {
+		return count;
+	}
+
+	return status;
+}
+
+struct in6_addr *net_route_get_nexthop(struct net_route_entry *route)
+{
+	struct net_route_nexthop *nexthop_route;
+	struct net_ipv6_nbr_data *ipv6_nbr_data;
+
+	if (!route) {
+		return NULL;
+	}
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&route->nexthop, nexthop_route, node) {
+		struct in6_addr *addr;
+
+		NET_ASSERT(nexthop_route->nbr->idx != NET_NBR_LLADDR_UNKNOWN);
+
+		if (nexthop_route->nbr->idx == NET_NBR_LLADDR_UNKNOWN) {
+			continue;
+		}
+
+		ipv6_nbr_data = net_ipv6_nbr_data(nexthop_route->nbr);
+		if (ipv6_nbr_data) {
+			addr = &ipv6_nbr_data->addr;
+			NET_ASSERT(addr);
+
+			return addr;
+		} else {
+			NET_ERR("could not get neighbor data from next hop");
+		}
+	}
+
+	return NULL;
+}
+
+int net_route_foreach(net_route_cb_t cb, void *user_data)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < CONFIG_NET_MAX_ROUTES; i++) {
+		struct net_route_entry *route;
+		struct net_nbr *nbr;
+
+		nbr = get_nbr(i);
+		if (!nbr) {
+			continue;
+		}
+
+		route = net_route_data(nbr);
+		if (!route) {
+			continue;
+		}
+
+		cb(route, user_data);
+
+		ret++;
+	}
+
+	return ret;
+}
+
+#if defined(CONFIG_NET_ROUTE_MCAST)
+/*
+ * This array contains multicast routing entries.
+ */
+static
+struct net_route_entry_mcast route_mcast_entries[CONFIG_NET_MAX_MCAST_ROUTES];
+
+int net_route_mcast_forward_packet(struct net_pkt *pkt,
+				   const struct net_ipv6_hdr *hdr)
+{
+	int i, ret = 0, err = 0;
+
+	for (i = 0; i < CONFIG_NET_MAX_MCAST_ROUTES; ++i) {
+		struct net_route_entry_mcast *route = &route_mcast_entries[i];
+		struct net_pkt *pkt_cpy = NULL;
+
+		if (!route->is_used) {
+			continue;
+		}
+
+		if (!net_if_flag_is_set(route->iface,
+					NET_IF_FORWARD_MULTICASTS) ||
+		    !net_ipv6_is_prefix(hdr->dst.s6_addr,
+					route->group.s6_addr,
+					route->prefix_len)         ||
+		    (pkt->iface == route->iface)) {
+			continue;
+		}
+
+		pkt_cpy = net_pkt_shallow_clone(pkt, K_NO_WAIT);
+
+		if (pkt_cpy == NULL) {
+			err--;
+			continue;
+		}
+
+		net_pkt_set_forwarding(pkt_cpy, true);
+		net_pkt_set_iface(pkt_cpy, route->iface);
+
+		if (net_send_data(pkt_cpy) >= 0) {
+			++ret;
+		} else {
+			--err;
+		}
+	}
+
+	return (err == 0) ? ret : err;
+}
+
+int net_route_mcast_foreach(net_route_mcast_cb_t cb,
+			    struct in6_addr *skip,
+			    void *user_data)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < CONFIG_NET_MAX_MCAST_ROUTES; i++) {
+		struct net_route_entry_mcast *route = &route_mcast_entries[i];
+
+		if (route->is_used) {
+			if (skip && net_ipv6_is_prefix(skip->s6_addr,
+						       route->group.s6_addr,
+						       route->prefix_len)) {
+				continue;
+			}
+
+			cb(route, user_data);
+
+			ret++;
+		}
+	}
+
+	return ret;
+}
+
+struct net_route_entry_mcast *net_route_mcast_add(struct net_if *iface,
+						  struct in6_addr *group,
+						  uint8_t prefix_len)
+{
+	int i;
+
+	if ((!net_if_flag_is_set(iface, NET_IF_FORWARD_MULTICASTS)) ||
+			(!net_ipv6_is_addr_mcast(group)) ||
+			(net_ipv6_is_addr_mcast_iface(group)) ||
+			(net_ipv6_is_addr_mcast_link(group))) {
+		return NULL;
+	}
+
+	for (i = 0; i < CONFIG_NET_MAX_MCAST_ROUTES; i++) {
+		struct net_route_entry_mcast *route = &route_mcast_entries[i];
+
+		if (!route->is_used) {
+			net_ipaddr_copy(&route->group, group);
+
+			route->prefix_len = prefix_len;
+			route->iface = iface;
+			route->is_used = true;
+
+			return route;
+		}
+	}
+
+	return NULL;
+}
+
+bool net_route_mcast_del(struct net_route_entry_mcast *route)
+{
+	if (route > &route_mcast_entries[CONFIG_NET_MAX_MCAST_ROUTES - 1] ||
+	    route < &route_mcast_entries[0]) {
+		return false;
+	}
+
+	NET_ASSERT(route->is_used,
+		   "Multicast route %p to %s was already removed", route,
+		   log_strdup(net_sprint_ipv6_addr(&route->group)));
+
+	route->is_used = false;
+
+	return true;
+}
+
+struct net_route_entry_mcast *
+net_route_mcast_lookup(struct in6_addr *group)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_MAX_MCAST_ROUTES; i++) {
+		struct net_route_entry_mcast *route = &route_mcast_entries[i];
+
+		if (!route->is_used) {
+			continue;
+		}
+
+		if (net_ipv6_is_prefix(group->s6_addr,
+					route->group.s6_addr,
+					route->prefix_len)) {
+			return route;
+		}
+	}
+
+	return NULL;
+}
+#endif /* CONFIG_NET_ROUTE_MCAST */
+
+bool net_route_get_info(struct net_if *iface,
+			struct in6_addr *dst,
+			struct net_route_entry **route,
+			struct in6_addr **nexthop)
+{
+	struct net_if_router *router;
+
+	/* Search in neighbor table first, if not search in routing table. */
+	if (net_ipv6_nbr_lookup(iface, dst)) {
+		/* Found nexthop, no need to look into routing table. */
+		*route = NULL;
+		*nexthop = dst;
+
+		return true;
+	}
+
+	*route = net_route_lookup(iface, dst);
+	if (*route) {
+		*nexthop = net_route_get_nexthop(*route);
+		if (!*nexthop) {
+			return false;
+		}
+
+		return true;
+	} else {
+		/* No specific route to this host, use the default
+		 * route instead.
+		 */
+		router = net_if_ipv6_router_find_default(NULL, dst);
+		if (!router) {
+			return false;
+		}
+
+		*nexthop = &router->address.in6_addr;
+
+		return true;
+	}
+
+	return false;
+}
+
+int net_route_packet(struct net_pkt *pkt, struct in6_addr *nexthop)
+{
+	struct net_linkaddr_storage *lladdr;
+	struct net_nbr *nbr;
+
+	nbr = net_ipv6_nbr_lookup(NULL, nexthop);
+	if (!nbr) {
+		NET_DBG("Cannot find %s neighbor",
+			log_strdup(net_sprint_ipv6_addr(nexthop)));
+		return -ENOENT;
+	}
+
+	lladdr = net_nbr_get_lladdr(nbr->idx);
+	if (!lladdr) {
+		NET_DBG("Cannot find %s neighbor link layer address.",
+			log_strdup(net_sprint_ipv6_addr(nexthop)));
+		return -ESRCH;
+	}
+
+#if defined(CONFIG_NET_L2_DUMMY)
+	/* No need to do this check for dummy L2 as it does not have any
+	 * link layer. This is done at runtime because we can have multiple
+	 * network technologies enabled.
+	 */
+	if (net_if_l2(net_pkt_iface(pkt)) != &NET_L2_GET_NAME(DUMMY)) {
+#endif
+#if defined(CONFIG_NET_L2_PPP)
+		/* PPP does not populate the lladdr fields */
+		if (net_if_l2(net_pkt_iface(pkt)) != &NET_L2_GET_NAME(PPP)) {
+#endif
+			if (!net_pkt_lladdr_src(pkt)->addr) {
+				NET_DBG("Link layer source address not set");
+				return -EINVAL;
+			}
+
+			/* Sanitycheck: If src and dst ll addresses are going
+			 * to be same, then something went wrong in route
+			 * lookup.
+			 */
+			if (!memcmp(net_pkt_lladdr_src(pkt)->addr, lladdr->addr,
+				    lladdr->len)) {
+				NET_ERR("Src ll and Dst ll are same");
+				return -EINVAL;
+			}
+#if defined(CONFIG_NET_L2_PPP)
+		}
+#endif
+#if defined(CONFIG_NET_L2_DUMMY)
+	}
+#endif
+
+	net_pkt_set_forwarding(pkt, true);
+
+	/* Set the destination and source ll address in the packet.
+	 * We set the destination address to be the nexthop recipient.
+	 */
+	net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
+	net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
+	net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
+
+	net_pkt_lladdr_dst(pkt)->addr = lladdr->addr;
+	net_pkt_lladdr_dst(pkt)->type = lladdr->type;
+	net_pkt_lladdr_dst(pkt)->len = lladdr->len;
+
+	net_pkt_set_iface(pkt, nbr->iface);
+
+	return net_send_data(pkt);
+}
+
+int net_route_packet_if(struct net_pkt *pkt, struct net_if *iface)
+{
+	/* The destination is reachable via iface. But since no valid nexthop
+	 * is known, net_pkt_lladdr_dst(pkt) cannot be set here.
+	 */
+
+	net_pkt_set_orig_iface(pkt, net_pkt_iface(pkt));
+	net_pkt_set_iface(pkt, iface);
+
+	net_pkt_set_forwarding(pkt, true);
+
+	net_pkt_lladdr_src(pkt)->addr = net_pkt_lladdr_if(pkt)->addr;
+	net_pkt_lladdr_src(pkt)->type = net_pkt_lladdr_if(pkt)->type;
+	net_pkt_lladdr_src(pkt)->len = net_pkt_lladdr_if(pkt)->len;
+
+	return net_send_data(pkt);
+}
+
+void net_route_init(void)
+{
+	NET_DBG("Allocated %d routing entries (%zu bytes)",
+		CONFIG_NET_MAX_ROUTES, sizeof(net_route_entries_pool));
+
+	NET_DBG("Allocated %d nexthop entries (%zu bytes)",
+		CONFIG_NET_MAX_NEXTHOPS, sizeof(net_route_nexthop_pool));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp.c	(working copy)
@@ -0,0 +1,2774 @@
+/** @file
+ * @brief TCP handler
+ *
+ * Handle TCP connections.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright 2011-2015 by Andrey Butok. FNET Community.
+ * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
+ * Copyright 2003 by Alexey Shervashidze, Andrey Butok. Motorola SPS.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL);
+
+#include <kernel.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <net/net_pkt.h>
+#include <net/net_ip.h>
+#include <net/net_context.h>
+#include <sys/byteorder.h>
+
+#include "connection.h"
+#include "net_private.h"
+
+#include "ipv6.h"
+#include "ipv4.h"
+#include "tcp_internal.h"
+#include "net_stats.h"
+
+#define ALLOC_TIMEOUT K_MSEC(500)
+
+static int net_tcp_queue_pkt(struct net_context *context, struct net_pkt *pkt);
+
+/*
+ * Each TCP connection needs to be tracked by net_context, so
+ * we need to allocate equal number of control structures here.
+ */
+#define NET_MAX_TCP_CONTEXT CONFIG_NET_MAX_CONTEXTS
+static struct net_tcp tcp_context[NET_MAX_TCP_CONTEXT];
+
+static struct tcp_backlog_entry {
+	struct net_tcp *tcp;
+	uint32_t send_seq;
+	uint32_t send_ack;
+	struct k_delayed_work ack_timer;
+	struct sockaddr remote;
+	uint16_t send_mss;
+} tcp_backlog[CONFIG_NET_TCP_BACKLOG_SIZE];
+
+#if defined(CONFIG_NET_TCP_ACK_TIMEOUT)
+#define ACK_TIMEOUT_MS CONFIG_NET_TCP_ACK_TIMEOUT
+#define ACK_TIMEOUT K_MSEC(ACK_TIMEOUT_MS)
+#else
+#define ACK_TIMEOUT_MS (1 * MSEC_PER_SEC)
+#define ACK_TIMEOUT K_MSEC(MSEC_PER_SEC)
+#endif
+
+#define FIN_TIMEOUT_MS (1 * MSEC_PER_SEC)
+#define FIN_TIMEOUT K_MSEC(MSEC_PER_SEC)
+
+/* Declares a wrapper function for a net_conn callback that refs the
+ * context around the invocation (to protect it from premature
+ * deletion).  Long term would be nice to see this feature be part of
+ * the connection type itself, but right now it has opaque "user_data"
+ * pointers and doesn't understand what a net_context is.
+ */
+#define NET_CONN_CB(name) \
+	static enum net_verdict _##name(struct net_conn *conn,		\
+					struct net_pkt *pkt,		\
+					union net_ip_header *ip_hdr,	\
+					union net_proto_header *proto_hdr, \
+					void *user_data);		\
+	static enum net_verdict name(struct net_conn *conn,		\
+				     struct net_pkt *pkt,		\
+				     union net_ip_header *ip_hdr,	\
+				     union net_proto_header *proto_hdr,	\
+				     void *user_data)			\
+	{								\
+		enum net_verdict result;				\
+									\
+		net_context_ref(user_data);				\
+		result = _##name(conn, pkt, ip_hdr,			\
+				 proto_hdr, user_data);			\
+		net_context_unref(user_data);				\
+		return result;						\
+	}								\
+	static enum net_verdict _##name(struct net_conn *conn,		\
+					struct net_pkt *pkt,		\
+					union net_ip_header *ip_hdr,	\
+					union net_proto_header *proto_hdr, \
+					void *user_data)		\
+
+
+struct tcp_segment {
+	uint32_t seq;
+	uint32_t ack;
+	uint16_t wnd;
+	uint8_t flags;
+	uint8_t optlen;
+	void *options;
+	struct sockaddr_ptr *src_addr;
+	const struct sockaddr *dst_addr;
+};
+
+static char upper_if_set(char chr, bool set)
+{
+	if (set) {
+		return chr & ~0x20;
+	}
+
+	return chr | 0x20;
+}
+
+static void net_tcp_trace(struct net_pkt *pkt,
+			  struct net_tcp *tcp,
+			  struct net_tcp_hdr *tcp_hdr)
+{
+	uint32_t rel_ack, ack;
+	uint8_t flags;
+
+	if (CONFIG_NET_TCP_LOG_LEVEL < LOG_LEVEL_DBG) {
+		return;
+	}
+
+	flags = NET_TCP_FLAGS(tcp_hdr);
+	ack = sys_get_be32(tcp_hdr->ack);
+
+	if (!tcp->sent_ack) {
+		rel_ack = 0U;
+	} else {
+		rel_ack = ack ? ack - tcp->sent_ack : 0;
+	}
+
+	NET_DBG("[%p] pkt %p src %u dst %u",
+		tcp, pkt,
+		ntohs(tcp_hdr->src_port),
+		ntohs(tcp_hdr->dst_port));
+
+	NET_DBG("  seq 0x%04x (%u) ack 0x%04x (%u/%u)",
+		sys_get_be32(tcp_hdr->seq),
+		sys_get_be32(tcp_hdr->seq),
+		ack,
+		ack,
+		/* This tells how many bytes we are acking now */
+		rel_ack);
+
+	NET_DBG("  flags %c%c%c%c%c%c",
+		upper_if_set('u', flags & NET_TCP_URG),
+		upper_if_set('a', flags & NET_TCP_ACK),
+		upper_if_set('p', flags & NET_TCP_PSH),
+		upper_if_set('r', flags & NET_TCP_RST),
+		upper_if_set('s', flags & NET_TCP_SYN),
+		upper_if_set('f', flags & NET_TCP_FIN));
+
+	NET_DBG("  win %u chk 0x%04x",
+		sys_get_be16(tcp_hdr->wnd),
+		ntohs(tcp_hdr->chksum));
+}
+
+static inline k_timeout_t retry_timeout(const struct net_tcp *tcp)
+{
+	return K_MSEC(((uint32_t)1 << tcp->retry_timeout_shift) *
+		      CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT);
+}
+
+#define is_6lo_technology(pkt)						\
+	(IS_ENABLED(CONFIG_NET_IPV6) &&	net_pkt_family(pkt) == AF_INET6 &&  \
+	 ((IS_ENABLED(CONFIG_NET_L2_BT) &&				\
+	   net_pkt_lladdr_dst(pkt)->type == NET_LINK_BLUETOOTH) ||	\
+	  (IS_ENABLED(CONFIG_NET_L2_IEEE802154) &&			\
+	   net_pkt_lladdr_dst(pkt)->type == NET_LINK_IEEE802154) ||	\
+	  (IS_ENABLED(CONFIG_NET_L2_CANBUS) &&			\
+	   net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS)))
+
+/* The ref should not be done for Bluetooth and IEEE 802.15.4 which use
+ * IPv6 header compression (6lo). For BT and 802.15.4 we copy the pkt
+ * chain we are about to send so it is fine if the network driver
+ * releases it. As we have our own copy of the sent data, we do not
+ * need to take a reference of it. See also net_tcp_send_pkt().
+ *
+ * Note that this is macro so that we get information who called the
+ * net_pkt_ref() if memory debugging is active.
+ */
+#define do_ref_if_needed(tcp, pkt)					\
+	do {								\
+		if (!is_6lo_technology(pkt)) {				\
+			NET_DBG("[%p] ref pkt %p new ref %d (%s:%d)",	\
+				tcp, pkt, atomic_get(&pkt->atomic_ref) + 1, \
+				__func__, __LINE__);			\
+			pkt = net_pkt_ref(pkt);				\
+		}							\
+	} while (0)
+
+static void abort_connection(struct net_tcp *tcp)
+{
+	struct net_context *ctx = tcp->context;
+
+	NET_DBG("[%p] segment retransmission exceeds %d, resetting context %p",
+		tcp, CONFIG_NET_TCP_RETRY_COUNT, ctx);
+
+	if (ctx->recv_cb) {
+		ctx->recv_cb(ctx, NULL, NULL, NULL, -ECONNRESET,
+			     tcp->recv_user_data);
+	}
+
+	net_context_unref(ctx);
+}
+
+static void tcp_retry_expired(struct k_work *work)
+{
+	struct net_tcp *tcp = CONTAINER_OF(work, struct net_tcp, retry_timer);
+	struct net_pkt *pkt;
+
+	/* Double the retry period for exponential backoff and resend
+	 * the first (only the first!) unack'd packet.
+	 */
+	if (!sys_slist_is_empty(&tcp->sent_list)) {
+		tcp->retry_timeout_shift++;
+
+		if (tcp->retry_timeout_shift > CONFIG_NET_TCP_RETRY_COUNT) {
+			abort_connection(tcp);
+			return;
+		}
+
+		k_delayed_work_submit(&tcp->retry_timer, retry_timeout(tcp));
+
+		pkt = CONTAINER_OF(sys_slist_peek_head(&tcp->sent_list),
+				   struct net_pkt, sent_list);
+
+		if (k_work_pending(net_pkt_work(pkt))) {
+			/* If the packet is still pending in TX queue, then do
+			 * not try to resend it again. This can happen if the
+			 * device is so busy that the TX thread has not yet
+			 * finished previous sending of this packet.
+			 */
+			NET_DBG("[%p] pkt %p still pending in TX queue",
+				tcp, pkt);
+			return;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
+			/* If we have enabled net_pkt TXTIME statistics, and we
+			 * about to re-send already sent net_pkt, then reset
+			 * the net_pkt start time as otherwise the TX average
+			 * will be wrong (as it would be calculated from when
+			 * the packet was created).
+			 */
+			struct net_ptp_time tp = {
+				.nanosecond = k_cycle_get_32(),
+			};
+
+			net_pkt_set_timestamp(pkt, &tp);
+		}
+
+		net_pkt_set_queued(pkt, true);
+		net_pkt_set_tcp_1st_msg(pkt, false);
+
+		/* The ref here is for the initial reference which was lost
+		 * when the pkt was sent. Typically the ref count should be 2
+		 * at this point if the pkt is being sent by the driver.
+		 */
+		if (!is_6lo_technology(pkt)) {
+			net_pkt_ref(pkt);
+		}
+
+		if (net_tcp_send_pkt(pkt) < 0 && !is_6lo_technology(pkt)) {
+			NET_DBG("retry %u: [%p] pkt %p send failed",
+				tcp->retry_timeout_shift, tcp, pkt);
+			/* Undo the ref done above */
+			net_pkt_unref(pkt);
+		} else {
+			NET_DBG("retry %u: [%p] sent pkt %p",
+				tcp->retry_timeout_shift, tcp, pkt);
+			if (IS_ENABLED(CONFIG_NET_STATISTICS_TCP) &&
+			    !is_6lo_technology(pkt)) {
+				net_stats_update_tcp_seg_rexmit(
+							net_pkt_iface(pkt));
+			}
+		}
+	} else if (CONFIG_NET_TCP_TIME_WAIT_DELAY != 0) {
+		if (tcp->fin_sent && tcp->fin_rcvd) {
+			NET_DBG("[%p] Closing connection (context %p)",
+				tcp, tcp->context);
+			net_context_unref(tcp->context);
+		}
+	}
+}
+
+struct net_tcp *net_tcp_alloc(struct net_context *context)
+{
+	int i, key;
+
+	key = irq_lock();
+	for (i = 0; i < NET_MAX_TCP_CONTEXT; i++) {
+		if (!net_tcp_is_used(&tcp_context[i])) {
+			tcp_context[i].flags |= NET_TCP_IN_USE;
+			break;
+		}
+	}
+	irq_unlock(key);
+
+	if (i >= NET_MAX_TCP_CONTEXT) {
+		return NULL;
+	}
+
+	(void)memset(&tcp_context[i], 0, sizeof(struct net_tcp));
+
+	tcp_context[i].flags = NET_TCP_IN_USE;
+	tcp_context[i].state = NET_TCP_CLOSED;
+	tcp_context[i].context = context;
+
+	tcp_context[i].send_seq = tcp_init_isn();
+	tcp_context[i].recv_wnd = MIN(NET_TCP_MAX_WIN, NET_TCP_BUF_MAX_LEN);
+	tcp_context[i].send_mss = NET_TCP_DEFAULT_MSS;
+
+	tcp_context[i].accept_cb = NULL;
+
+	k_delayed_work_init(&tcp_context[i].retry_timer, tcp_retry_expired);
+	k_sem_init(&tcp_context[i].connect_wait, 0, UINT_MAX);
+
+	return &tcp_context[i];
+}
+
+static void ack_timer_cancel(struct net_tcp *tcp)
+{
+	k_delayed_work_cancel(&tcp->ack_timer);
+}
+
+static void fin_timer_cancel(struct net_tcp *tcp)
+{
+	k_delayed_work_cancel(&tcp->fin_timer);
+}
+
+static void retry_timer_cancel(struct net_tcp *tcp)
+{
+	k_delayed_work_cancel(&tcp->retry_timer);
+}
+
+static void timewait_timer_cancel(struct net_tcp *tcp)
+{
+	k_delayed_work_cancel(&tcp->timewait_timer);
+}
+
+int net_tcp_release(struct net_tcp *tcp)
+{
+	struct net_pkt *pkt;
+	struct net_pkt *tmp;
+	unsigned int key;
+
+	if (!PART_OF_ARRAY(tcp_context, tcp)) {
+		return -EINVAL;
+	}
+
+	retry_timer_cancel(tcp);
+	k_sem_reset(&tcp->connect_wait);
+
+	ack_timer_cancel(tcp);
+	fin_timer_cancel(tcp);
+	timewait_timer_cancel(tcp);
+
+	net_tcp_change_state(tcp, NET_TCP_CLOSED);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp->sent_list, pkt, tmp,
+					  sent_list) {
+		int refcount;
+
+		sys_slist_remove(&tcp->sent_list, NULL, &pkt->sent_list);
+
+		/* The packet might get freed when sending it, so if that is
+		 * so, just skip it.
+		 */
+		if (atomic_get(&pkt->atomic_ref) == 0) {
+			continue;
+		}
+
+		/* Make sure we undo the reference done in net_tcp_queue_pkt()
+		 */
+		net_pkt_unref(pkt);
+
+		/* Release the packet fully unless it is still pending */
+		refcount = atomic_get(&pkt->atomic_ref);
+		if (refcount > 0) {
+			/* If the pkt was already placed to TX queue, let
+			 * it go as it will be released by L2 after it is
+			 * sent.
+			 */
+			if (k_work_pending(net_pkt_work(pkt)) ||
+			    net_pkt_sent(pkt)) {
+				refcount--;
+			}
+
+			while (refcount) {
+				net_pkt_unref(pkt);
+				refcount--;
+			}
+		}
+	}
+
+	tcp->context = NULL;
+
+	key = irq_lock();
+	tcp->flags &= ~(NET_TCP_IN_USE | NET_TCP_RECV_MSS_SET);
+	irq_unlock(key);
+
+	NET_DBG("[%p] Disposed of TCP connection state", tcp);
+
+	return 0;
+}
+
+static int finalize_segment(struct net_pkt *pkt)
+{
+	net_pkt_cursor_init(pkt);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		return net_ipv4_finalize(pkt, IPPROTO_TCP);
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		return net_ipv6_finalize(pkt, IPPROTO_TCP);
+	}
+
+	return -EINVAL;
+}
+
+static int prepare_segment(struct net_tcp *tcp,
+			   struct tcp_segment *segment,
+			   struct net_pkt *pkt,
+			   struct net_pkt **out_pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	struct net_context *context = tcp->context;
+	struct net_buf *tail = NULL;
+	struct net_tcp_hdr *tcp_hdr;
+	uint16_t dst_port, src_port;
+	bool pkt_allocated;
+	uint8_t optlen = 0U;
+	int status;
+
+	NET_ASSERT(context);
+
+	if (pkt) {
+		/* TCP transmit data comes in with a pre-allocated
+		 * net_pkt at the head (so that net_context_send can find
+		 * the context), and the data after.  Rejigger so we
+		 * can insert a TCP header cleanly
+		 */
+		tail = pkt->buffer;
+		pkt->buffer = NULL;
+		pkt_allocated = false;
+
+		status = net_pkt_alloc_buffer(pkt, segment->optlen,
+					      IPPROTO_TCP, ALLOC_TIMEOUT);
+		if (status) {
+			goto fail;
+		}
+	} else {
+		pkt = net_pkt_alloc_with_buffer(net_context_get_iface(context),
+						segment->optlen,
+						net_context_get_family(context),
+						IPPROTO_TCP, ALLOC_TIMEOUT);
+		if (!pkt) {
+			return -ENOMEM;
+		}
+
+		net_pkt_set_context(pkt, context);
+		pkt_allocated = true;
+	}
+
+	net_pkt_set_tcp_1st_msg(pkt, true);
+	net_pkt_set_sent(pkt, false);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		status = net_context_create_ipv4_new(context, pkt,
+				net_sin_ptr(segment->src_addr)->sin_addr,
+				&(net_sin(segment->dst_addr)->sin_addr));
+		if (status < 0) {
+			goto fail;
+		}
+
+		dst_port = net_sin(segment->dst_addr)->sin_port;
+		src_port = ((struct sockaddr_in_ptr *)&context->local)->
+								sin_port;
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		status = net_context_create_ipv6_new(context, pkt,
+				net_sin6_ptr(segment->src_addr)->sin6_addr,
+				&(net_sin6(segment->dst_addr)->sin6_addr));
+		if (status < 0) {
+			goto fail;
+		}
+
+		dst_port = net_sin6(segment->dst_addr)->sin6_port;
+		src_port = ((struct sockaddr_in6_ptr *)&context->local)->
+								sin6_port;
+	} else {
+		NET_DBG("[%p] Protocol family %d not supported", tcp,
+			net_pkt_family(pkt));
+
+		status = -EINVAL;
+		goto fail;
+	}
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access);
+	if (!tcp_hdr) {
+		status = -ENOBUFS;
+		goto fail;
+	}
+
+	if (segment->options && segment->optlen) {
+		/* Set the length (this value is saved in 4-byte words format)
+		 */
+		if ((segment->optlen & 0x3u) != 0u) {
+			optlen = (segment->optlen & 0xfffCu) + 4u;
+		} else {
+			optlen = segment->optlen;
+		}
+	}
+
+	memset(tcp_hdr, 0, NET_TCPH_LEN);
+
+	tcp_hdr->src_port = src_port;
+	tcp_hdr->dst_port = dst_port;
+	sys_put_be32(segment->seq, tcp_hdr->seq);
+	sys_put_be32(segment->ack, tcp_hdr->ack);
+	tcp_hdr->offset   = (NET_TCPH_LEN + optlen) << 2;
+	tcp_hdr->flags    = segment->flags;
+	sys_put_be16(segment->wnd, tcp_hdr->wnd);
+	tcp_hdr->chksum   = 0U;
+	tcp_hdr->urg[0]   = 0U;
+	tcp_hdr->urg[1]   = 0U;
+
+	net_pkt_set_data(pkt, &tcp_access);
+
+	if (optlen && net_pkt_write(pkt, segment->options, segment->optlen)) {
+		goto fail;
+	}
+
+	if (tail) {
+		net_pkt_append_buffer(pkt, tail);
+	}
+
+	status = finalize_segment(pkt);
+	if (status < 0) {
+		if (pkt_allocated) {
+			net_pkt_unref(pkt);
+		}
+
+		return status;
+	}
+
+	net_tcp_trace(pkt, tcp, tcp_hdr);
+
+	*out_pkt = pkt;
+
+	return 0;
+
+fail:
+	if (pkt_allocated) {
+		net_pkt_unref(pkt);
+	} else {
+		net_buf_unref(pkt->buffer);
+		pkt->buffer = tail;
+	}
+
+	return status;
+}
+
+uint32_t net_tcp_get_recv_wnd(const struct net_tcp *tcp)
+{
+	return tcp->recv_wnd;
+}
+
+int net_tcp_prepare_segment(struct net_tcp *tcp, uint8_t flags,
+			    void *options, size_t optlen,
+			    const struct sockaddr_ptr *local,
+			    const struct sockaddr *remote,
+			    struct net_pkt **send_pkt)
+{
+	struct tcp_segment segment = { 0 };
+	uint32_t seq;
+	uint16_t wnd;
+	int status;
+
+	if (!local) {
+		local = &tcp->context->local;
+	}
+
+	seq = tcp->send_seq;
+
+	if (flags & NET_TCP_ACK) {
+		if (net_tcp_get_state(tcp) == NET_TCP_FIN_WAIT_1) {
+			if (flags & NET_TCP_FIN) {
+				/* FIN is used here only to determine which
+				 * state to go to next; it's not to be used
+				 * in the sent segment.
+				 */
+				flags &= ~NET_TCP_FIN;
+				net_tcp_change_state(tcp, NET_TCP_TIME_WAIT);
+			} else {
+				net_tcp_change_state(tcp, NET_TCP_CLOSING);
+			}
+		} else if (net_tcp_get_state(tcp) == NET_TCP_FIN_WAIT_2) {
+			net_tcp_change_state(tcp, NET_TCP_TIME_WAIT);
+		} else if (net_tcp_get_state(tcp) == NET_TCP_CLOSE_WAIT) {
+			tcp->flags |= NET_TCP_IS_SHUTDOWN;
+			flags |= NET_TCP_FIN;
+			net_tcp_change_state(tcp, NET_TCP_LAST_ACK);
+		}
+	}
+
+	if (flags & NET_TCP_FIN) {
+		/* RFC793 says about ACK bit: "Once a connection is
+		 * established this is always sent." as teardown
+		 * happens when connection is established, it must
+		 * have ACK set.
+		 */
+		flags |= NET_TCP_ACK;
+		seq++;
+
+		if (net_tcp_get_state(tcp) == NET_TCP_ESTABLISHED ||
+		    net_tcp_get_state(tcp) == NET_TCP_SYN_RCVD) {
+			net_tcp_change_state(tcp, NET_TCP_FIN_WAIT_1);
+		}
+	}
+
+	wnd = net_tcp_get_recv_wnd(tcp);
+
+	segment.src_addr = (struct sockaddr_ptr *)local;
+	segment.dst_addr = remote;
+	segment.seq = tcp->send_seq;
+	segment.ack = tcp->send_ack;
+	segment.flags = flags;
+	segment.wnd = wnd;
+	segment.options = options;
+	segment.optlen = optlen;
+
+	status = prepare_segment(tcp, &segment, *send_pkt, send_pkt);
+	if (status < 0) {
+		return status;
+	}
+
+	tcp->send_seq = seq;
+
+	return 0;
+}
+
+static inline uint32_t get_size(uint32_t pos1, uint32_t pos2)
+{
+	uint32_t size;
+
+	if (pos1 <= pos2) {
+		size = pos2 - pos1;
+	} else {
+		size = NET_TCP_MAX_SEQ - pos1 + pos2 + 1;
+	}
+
+	return size;
+}
+
+#if defined(CONFIG_NET_IPV4)
+#ifndef NET_IP_MAX_PACKET
+#define NET_IP_MAX_PACKET (10 * 1024)
+#endif
+
+#define NET_IP_MAX_OPTIONS 40 /* Maximum option field length */
+
+static inline size_t ip_max_packet_len(struct in_addr *dest_ip)
+{
+	ARG_UNUSED(dest_ip);
+
+	return (NET_IP_MAX_PACKET - (NET_IP_MAX_OPTIONS +
+		      sizeof(struct net_ipv4_hdr))) & (~0x3LU);
+}
+#else /* CONFIG_NET_IPV4 */
+#define ip_max_packet_len(...) 0
+#endif /* CONFIG_NET_IPV4 */
+
+uint16_t net_tcp_get_recv_mss(const struct net_tcp *tcp)
+{
+	sa_family_t family = net_context_get_family(tcp->context);
+
+	if (family == AF_INET) {
+#if defined(CONFIG_NET_IPV4)
+		struct net_if *iface = net_context_get_iface(tcp->context);
+
+		if (iface && net_if_get_mtu(iface) >= NET_IPV4TCPH_LEN) {
+			/* Detect MSS based on interface MTU minus "TCP,IP
+			 * header size"
+			 */
+			return net_if_get_mtu(iface) - NET_IPV4TCPH_LEN;
+		}
+#else
+		return 0;
+#endif /* CONFIG_NET_IPV4 */
+	}
+#if defined(CONFIG_NET_IPV6)
+	else if (family == AF_INET6) {
+		struct net_if *iface = net_context_get_iface(tcp->context);
+		int mss = 0;
+
+		if (iface && net_if_get_mtu(iface) >= NET_IPV6TCPH_LEN) {
+			/* Detect MSS based on interface MTU minus "TCP,IP
+			 * header size"
+			 */
+			mss = net_if_get_mtu(iface) - NET_IPV6TCPH_LEN;
+		}
+
+		if (mss < NET_IPV6_MTU) {
+			mss = NET_IPV6_MTU;
+		}
+
+		return mss;
+	}
+#endif /* CONFIG_NET_IPV6 */
+
+	return 0;
+}
+
+static void net_tcp_set_syn_opt(struct net_tcp *tcp, uint8_t *options,
+				uint8_t *optionlen)
+{
+	uint32_t recv_mss;
+
+	*optionlen = 0U;
+
+	if (!(tcp->flags & NET_TCP_RECV_MSS_SET)) {
+		recv_mss = net_tcp_get_recv_mss(tcp);
+		tcp->flags |= NET_TCP_RECV_MSS_SET;
+	} else {
+		recv_mss = 0U;
+	}
+
+	recv_mss |= (NET_TCP_MSS_OPT << 24) | (NET_TCP_MSS_SIZE << 16);
+	UNALIGNED_PUT(htonl(recv_mss),
+		      (uint32_t *)(options + *optionlen));
+
+	*optionlen += NET_TCP_MSS_SIZE;
+}
+
+int net_tcp_prepare_ack(struct net_tcp *tcp, const struct sockaddr *remote,
+			struct net_pkt **pkt)
+{
+	uint8_t options[NET_TCP_MAX_OPT_SIZE];
+	uint8_t optionlen;
+
+	switch (net_tcp_get_state(tcp)) {
+	case NET_TCP_SYN_RCVD:
+		/* In the SYN_RCVD state acknowledgment must be with the
+		 * SYN flag.
+		 */
+		net_tcp_set_syn_opt(tcp, options, &optionlen);
+
+		return net_tcp_prepare_segment(tcp, NET_TCP_SYN | NET_TCP_ACK,
+					       options, optionlen, NULL, remote,
+					       pkt);
+	case NET_TCP_FIN_WAIT_1:
+	case NET_TCP_LAST_ACK:
+		/* In the FIN_WAIT_1 and LAST_ACK states acknowledgment must
+		 * be with the FIN flag.
+		 */
+		return net_tcp_prepare_segment(tcp, NET_TCP_FIN | NET_TCP_ACK,
+					       0, 0, NULL, remote, pkt);
+	default:
+		return net_tcp_prepare_segment(tcp, NET_TCP_ACK, 0, 0, NULL,
+					       remote, pkt);
+	}
+
+	return -EINVAL;
+}
+
+static inline void copy_sockaddr_to_sockaddr_ptr(struct net_tcp *tcp,
+						 const struct sockaddr *local,
+						 struct sockaddr_ptr *addr)
+{
+	(void)memset(addr, 0, sizeof(struct sockaddr_ptr));
+
+#if defined(CONFIG_NET_IPV4)
+	if (local->sa_family == AF_INET) {
+		net_sin_ptr(addr)->sin_family = AF_INET;
+		net_sin_ptr(addr)->sin_port = net_sin(local)->sin_port;
+		net_sin_ptr(addr)->sin_addr = &net_sin(local)->sin_addr;
+	}
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+	if (local->sa_family == AF_INET6) {
+		net_sin6_ptr(addr)->sin6_family = AF_INET6;
+		net_sin6_ptr(addr)->sin6_port = net_sin6(local)->sin6_port;
+		net_sin6_ptr(addr)->sin6_addr = &net_sin6(local)->sin6_addr;
+	}
+#endif
+}
+
+int net_tcp_prepare_reset(struct net_tcp *tcp,
+			  const struct sockaddr *local,
+			  const struct sockaddr *remote,
+			  struct net_pkt **pkt)
+{
+	struct tcp_segment segment = { 0 };
+	int status = 0;
+	struct sockaddr_ptr src_addr_ptr;
+
+	if ((net_context_get_state(tcp->context) != NET_CONTEXT_UNCONNECTED) &&
+	    (net_tcp_get_state(tcp) != NET_TCP_SYN_SENT) &&
+	    (net_tcp_get_state(tcp) != NET_TCP_TIME_WAIT)) {
+		/* Send the reset segment always with acknowledgment. */
+		segment.ack = tcp->send_ack;
+		segment.flags = NET_TCP_RST | NET_TCP_ACK;
+		segment.seq = tcp->send_seq;
+
+		if (!local) {
+			segment.src_addr = &tcp->context->local;
+		} else {
+			copy_sockaddr_to_sockaddr_ptr(tcp, local,
+						      &src_addr_ptr);
+			segment.src_addr = &src_addr_ptr;
+		}
+
+		segment.dst_addr = remote;
+		segment.wnd = 0U;
+		segment.options = NULL;
+		segment.optlen = 0U;
+
+		status = prepare_segment(tcp, &segment, NULL, pkt);
+	}
+
+	return status;
+}
+
+const char *net_tcp_state_str(enum net_tcp_state state)
+{
+#if (CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
+	switch (state) {
+	case NET_TCP_CLOSED:
+		return "CLOSED";
+	case NET_TCP_LISTEN:
+		return "LISTEN";
+	case NET_TCP_SYN_SENT:
+		return "SYN_SENT";
+	case NET_TCP_SYN_RCVD:
+		return "SYN_RCVD";
+	case NET_TCP_ESTABLISHED:
+		return "ESTABLISHED";
+	case NET_TCP_CLOSE_WAIT:
+		return "CLOSE_WAIT";
+	case NET_TCP_LAST_ACK:
+		return "LAST_ACK";
+	case NET_TCP_FIN_WAIT_1:
+		return "FIN_WAIT_1";
+	case NET_TCP_FIN_WAIT_2:
+		return "FIN_WAIT_2";
+	case NET_TCP_TIME_WAIT:
+		return "TIME_WAIT";
+	case NET_TCP_CLOSING:
+		return "CLOSING";
+	}
+#else
+	ARG_UNUSED(state);
+#endif
+
+	return "";
+}
+
+int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
+{
+	struct net_conn *conn = (struct net_conn *)context->conn_handler;
+	size_t data_len = net_pkt_get_len(pkt);
+	int ret;
+
+	NET_DBG("[%p] Queue %p len %zd", context->tcp, pkt, data_len);
+
+	if (net_context_get_state(context) != NET_CONTEXT_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	NET_ASSERT(context->tcp);
+	if (context->tcp->flags & NET_TCP_IS_SHUTDOWN) {
+		return -ESHUTDOWN;
+	}
+
+	/* Set PSH on all packets, our window is so small that there's
+	 * no point in the remote side trying to finesse things and
+	 * coalesce packets.
+	 */
+	ret = net_tcp_prepare_segment(context->tcp, NET_TCP_PSH | NET_TCP_ACK,
+				      NULL, 0, NULL, &conn->remote_addr, &pkt);
+	if (ret) {
+		return ret;
+	}
+
+	context->tcp->send_seq += data_len;
+
+	net_stats_update_tcp_sent(net_pkt_iface(pkt), data_len);
+
+	return net_tcp_queue_pkt(context, pkt);
+}
+
+/* This function is the sole point of *adding* packets to tcp->sent_list,
+ * and should remain such.
+ */
+static int net_tcp_queue_pkt(struct net_context *context, struct net_pkt *pkt)
+{
+	sys_slist_append(&context->tcp->sent_list, &pkt->sent_list);
+
+	/* We need to restart retry_timer if it is stopped. */
+	if (k_delayed_work_remaining_get(&context->tcp->retry_timer) == 0) {
+		k_delayed_work_submit(&context->tcp->retry_timer,
+				      retry_timeout(context->tcp));
+	}
+
+	/* Increase the ref count so that we do not lose the packet and
+	 * can resend later if needed. The pkt will be released after we
+	 * have received the ACK or the TCP stream is removed. This is only
+	 * done for non-6lo technologies that will keep the data until ACK
+	 * is received or timeout happens.
+	 */
+	do_ref_if_needed(context->tcp, pkt);
+
+	return 0;
+}
+
+int net_tcp_send_pkt(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	struct net_context *ctx = net_pkt_context(pkt);
+	struct net_tcp_hdr *tcp_hdr;
+	bool calc_chksum = false;
+	int ret;
+
+	if (!ctx || !ctx->tcp) {
+		NET_ERR("%scontext is not set on pkt %p",
+			!ctx ? "" : "TCP ", pkt);
+		return -EINVAL;
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+
+	if (net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+			 net_pkt_ip_opts_len(pkt))) {
+		return -EMSGSIZE;
+	}
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access);
+	if (!tcp_hdr) {
+		NET_ERR("Packet %p does not contain TCP header", pkt);
+		return -EMSGSIZE;
+	}
+
+	if (sys_get_be32(tcp_hdr->ack) != ctx->tcp->send_ack) {
+		sys_put_be32(ctx->tcp->send_ack, tcp_hdr->ack);
+		tcp_hdr->chksum = 0U;
+		calc_chksum = true;
+	}
+
+	/* The data stream code always sets this flag, because
+	 * existing stacks (Linux, anyway) seem to ignore data packets
+	 * without a valid-but-already-transmitted ACK.  But set it
+	 * anyway if we know we need it just to sanify edge cases.
+	 */
+	if (ctx->tcp->sent_ack != ctx->tcp->send_ack &&
+		(tcp_hdr->flags & NET_TCP_ACK) == 0U) {
+		tcp_hdr->flags |= NET_TCP_ACK;
+		tcp_hdr->chksum = 0U;
+		calc_chksum = true;
+	}
+
+	/* As we modified the header, we need to write it back.
+	 */
+	net_pkt_set_data(pkt, &tcp_access);
+
+	if (calc_chksum) {
+		net_pkt_cursor_init(pkt);
+		net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+			     net_pkt_ip_opts_len(pkt));
+
+		/* No need to get tcp_hdr again */
+		tcp_hdr->chksum = net_calc_chksum_tcp(pkt);
+
+		net_pkt_set_data(pkt, &tcp_access);
+	}
+
+	if (tcp_hdr->flags & NET_TCP_FIN) {
+		ctx->tcp->fin_sent = 1U;
+	}
+
+	ctx->tcp->sent_ack = ctx->tcp->send_ack;
+
+	/* We must have special handling for some network technologies that
+	 * tweak the IP protocol headers during packet sending. This happens
+	 * with Bluetooth and IEEE 802.15.4 which use IPv6 header compression
+	 * (6lo) and alter the sent network packet. So in order to avoid any
+	 * corruption of the original data buffer, we must copy the sent data.
+	 * For Bluetooth, its fragmentation code will even mangle the data
+	 * part of the message so we need to copy those too.
+	 */
+	if (is_6lo_technology(pkt)) {
+		struct net_pkt *new_pkt, *check_pkt;
+		bool pkt_in_slist = false;
+
+		/*
+		 * There are users of this function that don't add pkt to TCP
+		 * sent_list. (See send_ack() in net_context.c) In these cases,
+		 * we should avoid the extra 6lowpan specific buffer copy
+		 * below.
+		 */
+		SYS_SLIST_FOR_EACH_CONTAINER(&ctx->tcp->sent_list,
+					     check_pkt, sent_list) {
+			if (check_pkt == pkt) {
+				pkt_in_slist = true;
+				break;
+			}
+		}
+
+		if (pkt_in_slist) {
+			new_pkt = net_pkt_clone(pkt, ALLOC_TIMEOUT);
+			if (!new_pkt) {
+				return -ENOMEM;
+			}
+
+			/* This function is called from net_context.c and if we
+			 * return < 0, the caller will unref the original pkt.
+			 * This would leak the new_pkt so remove it here.
+			 */
+			ret = net_send_data(new_pkt);
+			if (ret < 0) {
+				net_pkt_unref(new_pkt);
+			} else {
+				net_stats_update_tcp_seg_rexmit(
+							net_pkt_iface(pkt));
+				net_pkt_set_sent(pkt, true);
+			}
+
+			return ret;
+		}
+	}
+
+	ret = net_send_data(pkt);
+	if (ret == 0) {
+		net_pkt_set_sent(pkt, true);
+	}
+
+	return ret;
+}
+
+static void flush_queue(struct net_context *context)
+{
+	(void)net_tcp_send_data(context, NULL, NULL);
+}
+
+static void restart_timer(struct net_tcp *tcp)
+{
+	if (!sys_slist_is_empty(&tcp->sent_list)) {
+		tcp->flags |= NET_TCP_RETRYING;
+		tcp->retry_timeout_shift = 0U;
+		k_delayed_work_submit(&tcp->retry_timer, retry_timeout(tcp));
+	} else if (CONFIG_NET_TCP_TIME_WAIT_DELAY != 0 &&
+			(tcp->fin_sent && tcp->fin_rcvd)) {
+		/* We know sent_list is empty, which means if
+		 * fin_sent is true it must have been ACKd
+		 */
+		k_delayed_work_submit(&tcp->retry_timer,
+				      K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
+		net_context_ref(tcp->context);
+	} else {
+		k_delayed_work_cancel(&tcp->retry_timer);
+		tcp->flags &= ~NET_TCP_RETRYING;
+	}
+}
+
+int net_tcp_send_data(struct net_context *context, net_context_send_cb_t cb,
+		      void *user_data)
+{
+	struct net_pkt *pkt;
+	int ret;
+
+	/* For now, just send all queued data synchronously.  Need to
+	 * add window handling and retry/ACK logic.
+	 */
+	SYS_SLIST_FOR_EACH_CONTAINER(&context->tcp->sent_list, pkt, sent_list) {
+		/* Do not resend packets that were sent by expire timer */
+		if (net_pkt_queued(pkt)) {
+			NET_DBG("[%p] Skipping pkt %p because it was already "
+				"sent.", context->tcp, pkt);
+			continue;
+		}
+
+		/* If this pkt is the first one (not a resend), then we do
+		 * not need to increase the ref count as it is 1 already.
+		 * For a resent packet, the ref count is only 1 atm, and
+		 * the packet would be freed in driver if we do not increase
+		 * it here. This is only done for non-6lo technologies where
+		 * we keep the original packet (by referencing it) for possible
+		 * re-send (if ACK is not received on time).
+		 */
+		if (!is_6lo_technology(pkt)) {
+			if (!net_pkt_tcp_1st_msg(pkt)) {
+				net_pkt_ref(pkt);
+			}
+		}
+
+		NET_DBG("[%p] Sending pkt %p (%zd bytes)", context->tcp,
+			pkt, net_pkt_get_len(pkt));
+
+		ret = net_tcp_send_pkt(pkt);
+		if (ret < 0) {
+			NET_DBG("[%p] pkt %p not sent (%d)",
+				context->tcp, pkt, ret);
+			if (!is_6lo_technology(pkt)) {
+				net_pkt_unref(pkt);
+			}
+
+			return ret;
+		}
+
+		net_pkt_set_queued(pkt, true);
+		net_pkt_set_tcp_1st_msg(pkt, false);
+	}
+
+	/* Just make the callback synchronously even if it didn't
+	 * go over the wire.  In theory it would be nice to track
+	 * specific ACK locations in the stream and make the
+	 * callback at that time, but there's nowhere to store the
+	 * user_data value right now.
+	 */
+	if (cb) {
+		cb(context, 0, user_data);
+	}
+
+	return 0;
+}
+
+bool net_tcp_ack_received(struct net_context *ctx, uint32_t ack)
+{
+	struct net_tcp *tcp = ctx->tcp;
+	sys_slist_t *list = &ctx->tcp->sent_list;
+	sys_snode_t *head;
+	struct net_pkt *pkt;
+	bool valid_ack = false;
+
+	if (net_tcp_seq_greater(ack, ctx->tcp->send_seq)) {
+		NET_ERR("ctx %p: ACK for unsent data", ctx);
+		net_stats_update_tcp_seg_ackerr(net_context_get_iface(ctx));
+		/* RFC 793 doesn't say that invalid ack sequence is an error
+		 * in the general case, but we implement tighter checking,
+		 * and consider entire packet invalid.
+		 */
+		return false;
+	}
+
+	while (!sys_slist_is_empty(list)) {
+		NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+		struct net_tcp_hdr *tcp_hdr;
+		uint32_t last_seq;
+		uint32_t seq_len;
+
+		head = sys_slist_peek_head(list);
+		pkt = CONTAINER_OF(head, struct net_pkt, sent_list);
+
+		net_pkt_cursor_init(pkt);
+		net_pkt_set_overwrite(pkt, true);
+
+		if (net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+				 net_pkt_ip_opts_len(pkt))) {
+			sys_slist_remove(list, NULL, head);
+			net_pkt_unref(pkt);
+			continue;
+		}
+
+		tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt,
+								 &tcp_access);
+		if (!tcp_hdr) {
+			/* The pkt does not contain TCP header, this should
+			 * not happen.
+			 */
+			NET_ERR("pkt %p has no TCP header", pkt);
+			sys_slist_remove(list, NULL, head);
+			net_pkt_unref(pkt);
+			continue;
+		}
+
+		net_pkt_acknowledge_data(pkt, &tcp_access);
+		seq_len = net_pkt_remaining_data(pkt);
+
+		/* Each of SYN and FIN flags are counted
+		 * as one sequence number.
+		 */
+		if (tcp_hdr->flags & NET_TCP_SYN) {
+			seq_len += 1U;
+		}
+		if (tcp_hdr->flags & NET_TCP_FIN) {
+			seq_len += 1U;
+		}
+
+		/* Last sequence number in this packet. */
+		last_seq = sys_get_be32(tcp_hdr->seq) + seq_len - 1;
+
+		/* Ack number should be strictly greater to acknowledged numbers
+		 * below it. For example, ack no. 10 acknowledges all numbers up
+		 * to and including 9.
+		 */
+		if (!net_tcp_seq_greater(ack, last_seq)) {
+			break;
+		}
+
+		if (tcp_hdr->flags & NET_TCP_FIN) {
+			enum net_tcp_state s = net_tcp_get_state(tcp);
+
+			if (s == NET_TCP_FIN_WAIT_1) {
+				net_tcp_change_state(tcp, NET_TCP_FIN_WAIT_2);
+			} else if (s == NET_TCP_CLOSING) {
+				net_tcp_change_state(tcp, NET_TCP_TIME_WAIT);
+			}
+		}
+
+		NET_DBG("[%p] Received ACK pkt %p (len %zd bytes)", ctx->tcp,
+			pkt, net_pkt_get_len(pkt));
+
+		sys_slist_remove(list, NULL, head);
+
+		/* If we receive a valid ACK, then we need to undo the ref
+		 * set in net_tcp_queue_pkt() (when using non-6lo technology)
+		 * or the ref set in packet creation (for 6lo packet) in order
+		 * to release the pkt.
+		 */
+		net_pkt_set_sent(pkt, false);
+		net_pkt_unref(pkt);
+
+		valid_ack = true;
+	}
+
+	/* Restart the timer (if needed) on a valid inbound ACK.  This isn't
+	 * quite the same behavior as per-packet retry timers, but is close in
+	 * practice (it starts retries one timer period after the connection
+	 * "got stuck") and avoids the need to track per-packet timers or
+	 * sent times.
+	 */
+	if (valid_ack) {
+		restart_timer(ctx->tcp);
+
+		/* Flush anything pending. This is important as if there
+		 * is FIN waiting in the queue, it gets sent asap.
+		 */
+		flush_queue(ctx);
+	}
+
+	return true;
+}
+
+void net_tcp_init(void)
+{
+}
+
+#if CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG
+static void validate_state_transition(enum net_tcp_state current,
+				      enum net_tcp_state new)
+{
+	static const uint16_t valid_transitions[] = {
+		[NET_TCP_CLOSED] = 1 << NET_TCP_LISTEN |
+			1 << NET_TCP_SYN_SENT |
+			/* Initial transition from closed->established when
+			 * socket is accepted.
+			 */
+			1 << NET_TCP_ESTABLISHED,
+		[NET_TCP_LISTEN] = 1 << NET_TCP_SYN_RCVD |
+			1 << NET_TCP_SYN_SENT |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_SYN_RCVD] = 1 << NET_TCP_FIN_WAIT_1 |
+			1 << NET_TCP_ESTABLISHED |
+			1 << NET_TCP_LISTEN |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_SYN_SENT] = 1 << NET_TCP_CLOSED |
+			1 << NET_TCP_ESTABLISHED |
+			1 << NET_TCP_SYN_RCVD |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_ESTABLISHED] = 1 << NET_TCP_CLOSE_WAIT |
+			1 << NET_TCP_FIN_WAIT_1 |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_CLOSE_WAIT] = 1 << NET_TCP_LAST_ACK |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_LAST_ACK] = 1 << NET_TCP_CLOSED,
+		[NET_TCP_FIN_WAIT_1] = 1 << NET_TCP_CLOSING |
+			1 << NET_TCP_FIN_WAIT_2 |
+			1 << NET_TCP_TIME_WAIT |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_FIN_WAIT_2] = 1 << NET_TCP_TIME_WAIT |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_CLOSING] = 1 << NET_TCP_TIME_WAIT |
+			1 << NET_TCP_CLOSED,
+		[NET_TCP_TIME_WAIT] = 1 << NET_TCP_CLOSED
+	};
+
+	if (!(valid_transitions[current] & 1 << new)) {
+		NET_DBG("Invalid state transition: %s (%d) => %s (%d)",
+			net_tcp_state_str(current), current,
+			net_tcp_state_str(new), new);
+	}
+}
+#else
+static inline void validate_state_transition(enum net_tcp_state current,
+					     enum net_tcp_state new)
+{
+	ARG_UNUSED(current);
+	ARG_UNUSED(new);
+}
+#endif
+
+void net_tcp_change_state(struct net_tcp *tcp,
+			  enum net_tcp_state new_state)
+{
+	NET_ASSERT(tcp);
+
+	if (net_tcp_get_state(tcp) == new_state) {
+		return;
+	}
+
+	NET_ASSERT(new_state >= NET_TCP_CLOSED &&
+		   new_state <= NET_TCP_CLOSING);
+
+	NET_DBG("[%p] state %s (%d) => %s (%d)",
+		tcp, net_tcp_state_str(tcp->state), tcp->state,
+		net_tcp_state_str(new_state), new_state);
+
+	validate_state_transition(tcp->state, new_state);
+
+	tcp->state = new_state;
+
+	if (net_tcp_get_state(tcp) != NET_TCP_CLOSED) {
+		return;
+	}
+
+	if (!tcp->context) {
+		return;
+	}
+
+	/* Remove any port handlers if we are closing */
+	if (tcp->context->conn_handler) {
+		net_tcp_unregister(tcp->context->conn_handler);
+		tcp->context->conn_handler = NULL;
+	}
+
+	if (tcp->accept_cb) {
+		tcp->accept_cb(tcp->context,
+			       &tcp->context->remote,
+			       sizeof(struct sockaddr),
+			       -ENETRESET,
+			       tcp->context->user_data);
+	}
+}
+
+void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
+{
+	int i, key;
+
+	key = irq_lock();
+
+	for (i = 0; i < NET_MAX_TCP_CONTEXT; i++) {
+		if (!net_tcp_is_used(&tcp_context[i])) {
+			continue;
+		}
+
+		irq_unlock(key);
+
+		cb(&tcp_context[i], user_data);
+
+		key = irq_lock();
+	}
+
+	irq_unlock(key);
+}
+
+bool net_tcp_validate_seq(struct net_tcp *tcp, struct net_tcp_hdr *tcp_hdr)
+{
+	return (net_tcp_seq_cmp(sys_get_be32(tcp_hdr->seq),
+				tcp->send_ack) >= 0) &&
+		(net_tcp_seq_cmp(sys_get_be32(tcp_hdr->seq),
+				 tcp->send_ack
+					+ net_tcp_get_recv_wnd(tcp)) < 0);
+}
+
+int net_tcp_finalize(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	struct net_tcp_hdr *tcp_hdr;
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access);
+	if (!tcp_hdr) {
+		return -ENOBUFS;
+	}
+
+	tcp_hdr->chksum = 0U;
+
+	if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) {
+		tcp_hdr->chksum = net_calc_chksum_tcp(pkt);
+	}
+
+	return net_pkt_set_data(pkt, &tcp_access);
+}
+
+int net_tcp_parse_opts(struct net_pkt *pkt, int opt_totlen,
+		       struct net_tcp_options *opts)
+{
+	uint8_t opt, optlen;
+
+	while (opt_totlen) {
+		if (net_pkt_read_u8(pkt, &opt)) {
+			optlen = 0U;
+			goto error;
+		}
+
+		opt_totlen--;
+
+		/* https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-parameters-1 */
+		/* "Options 0 and 1 are exactly one octet which is their
+		 * kind field.  All other options have their one octet
+		 * kind field, followed by a one octet length field,
+		 * followed by length-2 octets of option data."
+		 */
+		if (opt == NET_TCP_END_OPT) {
+			break;
+		} else if (opt == NET_TCP_NOP_OPT) {
+			continue;
+		}
+
+		if (!opt_totlen) {
+			optlen = 0U;
+			goto error;
+		}
+
+		if (net_pkt_read_u8(pkt, &optlen) || optlen < 2) {
+			goto error;
+		}
+
+		opt_totlen--;
+
+		/* Subtract opt/optlen size now to avoid doing this
+		 * repeatedly.
+		 */
+		optlen -= 2U;
+		if (opt_totlen < optlen) {
+			goto error;
+		}
+
+		switch (opt) {
+		case NET_TCP_MSS_OPT:
+			if (optlen != 2U) {
+				goto error;
+			}
+
+			if (net_pkt_read_be16(pkt, &opts->mss)) {
+				goto error;
+			}
+
+			break;
+		default:
+			if (net_pkt_skip(pkt, optlen)) {
+				goto error;
+			}
+
+			break;
+		}
+
+		opt_totlen -= optlen;
+	}
+
+	return 0;
+
+error:
+	NET_ERR("Invalid TCP opt: %d len: %d", opt, optlen);
+	return -EINVAL;
+}
+
+int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb,
+		 void *user_data)
+{
+	NET_ASSERT(context->tcp);
+
+	if (context->tcp->flags & NET_TCP_IS_SHUTDOWN) {
+		return -ESHUTDOWN;
+	} else if (net_context_get_state(context) != NET_CONTEXT_CONNECTED) {
+		return -ENOTCONN;
+	}
+
+	context->recv_cb = cb;
+	context->tcp->recv_user_data = user_data;
+
+	return 0;
+}
+
+static void queue_fin(struct net_context *ctx)
+{
+	struct net_pkt *pkt = NULL;
+	bool flush = false;
+	int ret;
+
+	ret = net_tcp_prepare_segment(ctx->tcp, NET_TCP_FIN, NULL, 0,
+				      NULL, &ctx->remote, &pkt);
+	if (ret || !pkt) {
+		return;
+	}
+
+	if (sys_slist_is_empty(&ctx->tcp->sent_list)) {
+		flush = true;
+	}
+
+	net_tcp_queue_pkt(ctx, pkt);
+
+	if (flush) {
+		flush_queue(ctx);
+	}
+}
+
+int net_tcp_put(struct net_context *context)
+{
+	if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		if (net_context_get_state(context) == NET_CONTEXT_CONNECTED
+		    && context->tcp
+		    && !context->tcp->fin_rcvd) {
+			NET_DBG("TCP connection in active close, not "
+				"disposing yet (waiting %dms)", FIN_TIMEOUT_MS);
+			k_delayed_work_submit(&context->tcp->fin_timer,
+					      FIN_TIMEOUT);
+			queue_fin(context);
+			return 0;
+		}
+
+		/* A listening context is only used to establish connections.
+		 * Since once the connection is established it is not handled
+		 * directly by the listening context but rather by the child it
+		 * spawned, it is not needed to send FIN when closing such
+		 * contexts.
+		 */
+		if (context->tcp &&
+		    net_context_get_state(context) == NET_CONTEXT_LISTENING) {
+			net_context_unref(context);
+			return 0;
+		}
+
+		if (context->tcp &&
+		    net_tcp_get_state(context->tcp) == NET_TCP_SYN_SENT) {
+			net_context_unref(context);
+		}
+
+		return -ENOTCONN;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int net_tcp_listen(struct net_context *context)
+{
+	if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		net_tcp_change_state(context->tcp, NET_TCP_LISTEN);
+		net_context_set_state(context, NET_CONTEXT_LISTENING);
+
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta)
+{
+	int32_t new_win;
+
+	if (!context->tcp) {
+		NET_ERR("context->tcp == NULL");
+		return -EPROTOTYPE;
+	}
+
+	new_win = context->tcp->recv_wnd + delta;
+	if (new_win < 0 || new_win > UINT16_MAX) {
+		return -EINVAL;
+	}
+
+	context->tcp->recv_wnd = new_win;
+
+	return 0;
+}
+
+static int send_reset(struct net_context *context, struct sockaddr *local,
+		      struct sockaddr *remote);
+
+static void backlog_ack_timeout(struct k_work *work)
+{
+	struct tcp_backlog_entry *backlog =
+		CONTAINER_OF(work, struct tcp_backlog_entry, ack_timer);
+
+	NET_DBG("Did not receive ACK in %dms", ACK_TIMEOUT_MS);
+
+	/* TODO: If net_context is bound to unspecified IPv6 address
+	 * and some port number, local address is not available.
+	 * RST packet might be invalid. Cache local address
+	 * and use it in RST message preparation.
+	 */
+	send_reset(backlog->tcp->context, NULL, &backlog->remote);
+
+	(void)memset(backlog, 0, sizeof(struct tcp_backlog_entry));
+}
+
+static void tcp_copy_ip_addr_from_hdr(sa_family_t family,
+				      union net_ip_header *ip_hdr,
+				      struct net_tcp_hdr *tcp_hdr,
+				      struct sockaddr *addr,
+				      bool is_src_addr)
+{
+	uint16_t port;
+
+	if (is_src_addr) {
+		port = tcp_hdr->src_port;
+	} else {
+		port = tcp_hdr->dst_port;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+		struct sockaddr_in *addr4 = net_sin(addr);
+
+		if (is_src_addr) {
+			net_ipaddr_copy(&addr4->sin_addr, &ip_hdr->ipv4->src);
+		} else {
+			net_ipaddr_copy(&addr4->sin_addr, &ip_hdr->ipv4->dst);
+		}
+
+		addr4->sin_port = port;
+		addr->sa_family = AF_INET;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		struct sockaddr_in6 *addr6 = net_sin6(addr);
+
+		if (is_src_addr) {
+			net_ipaddr_copy(&addr6->sin6_addr, &ip_hdr->ipv6->src);
+		} else {
+			net_ipaddr_copy(&addr6->sin6_addr, &ip_hdr->ipv6->dst);
+		}
+
+		addr6->sin6_port = port;
+		addr->sa_family = AF_INET6;
+	}
+}
+
+static int tcp_backlog_find(struct net_pkt *pkt,
+			    union net_ip_header *ip_hdr,
+			    struct net_tcp_hdr *tcp_hdr,
+			    int *empty_slot)
+{
+	int i, empty = -1;
+
+	for (i = 0; i < CONFIG_NET_TCP_BACKLOG_SIZE; i++) {
+		if (tcp_backlog[i].tcp == NULL && empty < 0) {
+			empty = i;
+			continue;
+		}
+
+		if (net_pkt_family(pkt) != tcp_backlog[i].remote.sa_family) {
+			continue;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		    net_pkt_family(pkt) == AF_INET) {
+			if (net_sin(&tcp_backlog[i].remote)->sin_port !=
+			    tcp_hdr->src_port) {
+				continue;
+			}
+
+			if (memcmp(&net_sin(&tcp_backlog[i].remote)->sin_addr,
+				   &ip_hdr->ipv4->src,
+				   sizeof(struct in_addr))) {
+				continue;
+			}
+		} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    net_pkt_family(pkt) == AF_INET6) {
+			if (net_sin6(&tcp_backlog[i].remote)->sin6_port !=
+			    tcp_hdr->src_port) {
+				continue;
+			}
+
+			if (memcmp(&net_sin6(&tcp_backlog[i].remote)->sin6_addr,
+				   &ip_hdr->ipv6->src,
+				   sizeof(struct in6_addr))) {
+				continue;
+			}
+		}
+
+		return i;
+	}
+
+	if (empty_slot) {
+		*empty_slot = empty;
+	}
+
+	return -EADDRNOTAVAIL;
+}
+
+static int tcp_backlog_syn(struct net_pkt *pkt,
+			   union net_ip_header *ip_hdr,
+			   struct net_tcp_hdr *tcp_hdr,
+			   struct net_context *context,
+			   uint16_t send_mss)
+{
+	int empty_slot = -1;
+
+	if (tcp_backlog_find(pkt, ip_hdr, tcp_hdr, &empty_slot) >= 0) {
+		return -EADDRINUSE;
+	}
+
+	if (empty_slot < 0) {
+		return -ENOSPC;
+	}
+
+	tcp_backlog[empty_slot].tcp = context->tcp;
+
+	tcp_copy_ip_addr_from_hdr(net_pkt_family(pkt), ip_hdr, tcp_hdr,
+				  &tcp_backlog[empty_slot].remote, true);
+
+	tcp_backlog[empty_slot].send_seq = context->tcp->send_seq;
+	tcp_backlog[empty_slot].send_ack = context->tcp->send_ack;
+	tcp_backlog[empty_slot].send_mss = send_mss;
+
+	k_delayed_work_init(&tcp_backlog[empty_slot].ack_timer,
+			    backlog_ack_timeout);
+	k_delayed_work_submit(&tcp_backlog[empty_slot].ack_timer, ACK_TIMEOUT);
+
+	return 0;
+}
+
+static int tcp_backlog_ack(struct net_pkt *pkt,
+			   union net_ip_header *ip_hdr,
+			   struct net_tcp_hdr *tcp_hdr,
+			   struct net_context *context)
+{
+	int r;
+
+	r = tcp_backlog_find(pkt, ip_hdr, tcp_hdr, NULL);
+	if (r < 0) {
+		return r;
+	}
+
+	/* Sent SEQ + 1 needs to be the same as the received ACK */
+	if (tcp_backlog[r].send_seq + 1 != sys_get_be32(tcp_hdr->ack)) {
+		return -EINVAL;
+	}
+
+	memcpy(&context->remote, &tcp_backlog[r].remote,
+		sizeof(struct sockaddr));
+	context->tcp->send_seq = tcp_backlog[r].send_seq + 1;
+	context->tcp->send_ack = tcp_backlog[r].send_ack;
+	context->tcp->send_mss = tcp_backlog[r].send_mss;
+
+	k_delayed_work_cancel(&tcp_backlog[r].ack_timer);
+	(void)memset(&tcp_backlog[r], 0, sizeof(struct tcp_backlog_entry));
+
+	return 0;
+}
+
+static int tcp_backlog_rst(struct net_pkt *pkt,
+			   union net_ip_header *ip_hdr,
+			   struct net_tcp_hdr *tcp_hdr)
+{
+	int r;
+
+	r = tcp_backlog_find(pkt, ip_hdr, tcp_hdr, NULL);
+	if (r < 0) {
+		return r;
+	}
+
+	/* The ACK sent needs to be the same as the received SEQ */
+	if (tcp_backlog[r].send_ack != sys_get_be32(tcp_hdr->seq)) {
+		return -EINVAL;
+	}
+
+	k_delayed_work_cancel(&tcp_backlog[r].ack_timer);
+	(void)memset(&tcp_backlog[r], 0, sizeof(struct tcp_backlog_entry));
+
+	return 0;
+}
+
+static void handle_fin_timeout(struct k_work *work)
+{
+	struct net_tcp *tcp =
+		CONTAINER_OF(work, struct net_tcp, fin_timer);
+
+	NET_DBG("Did not receive FIN in %dms", FIN_TIMEOUT_MS);
+
+	net_context_unref(tcp->context);
+}
+
+static void handle_ack_timeout(struct k_work *work)
+{
+	/* This means that we did not receive ACK response in time. */
+	struct net_tcp *tcp = CONTAINER_OF(work, struct net_tcp, ack_timer);
+
+	NET_DBG("Did not receive ACK in %dms while in %s", ACK_TIMEOUT_MS,
+		net_tcp_state_str(net_tcp_get_state(tcp)));
+
+	if (net_tcp_get_state(tcp) == NET_TCP_LAST_ACK) {
+		/* We did not receive the last ACK on time. We can only
+		 * close the connection at this point. We will not send
+		 * anything to peer in this last state, but will go directly
+		 * to to CLOSED state.
+		 */
+		net_tcp_change_state(tcp, NET_TCP_CLOSED);
+
+		if (tcp->context->recv_cb) {
+			tcp->context->recv_cb(tcp->context, NULL, NULL, NULL,
+					      0, tcp->recv_user_data);
+		}
+
+		net_context_unref(tcp->context);
+	}
+}
+
+static void handle_timewait_timeout(struct k_work *work)
+{
+	struct net_tcp *tcp = CONTAINER_OF(work, struct net_tcp,
+					   timewait_timer);
+
+	NET_DBG("Timewait expired in %dms", CONFIG_NET_TCP_TIME_WAIT_DELAY);
+
+	if (net_tcp_get_state(tcp) == NET_TCP_TIME_WAIT) {
+		net_tcp_change_state(tcp, NET_TCP_CLOSED);
+
+		if (tcp->context->recv_cb) {
+			tcp->context->recv_cb(tcp->context, NULL, NULL, NULL,
+					      0, tcp->recv_user_data);
+		}
+
+		net_context_unref(tcp->context);
+	}
+}
+
+int net_tcp_get(struct net_context *context)
+{
+	context->tcp = net_tcp_alloc(context);
+	if (!context->tcp) {
+		NET_ASSERT(context->tcp, "Cannot allocate TCP context");
+		return -ENOBUFS;
+	}
+
+	k_delayed_work_init(&context->tcp->ack_timer, handle_ack_timeout);
+	k_delayed_work_init(&context->tcp->fin_timer, handle_fin_timeout);
+	k_delayed_work_init(&context->tcp->timewait_timer,
+			    handle_timewait_timeout);
+
+	return 0;
+}
+
+int net_tcp_unref(struct net_context *context)
+{
+	int i;
+
+	if (!context->tcp)
+		return 0;
+
+	/* Clear the backlog for this TCP context. */
+	for (i = 0; i < CONFIG_NET_TCP_BACKLOG_SIZE; i++) {
+		if (tcp_backlog[i].tcp != context->tcp) {
+			continue;
+		}
+
+		k_delayed_work_cancel(&tcp_backlog[i].ack_timer);
+		(void)memset(&tcp_backlog[i], 0, sizeof(tcp_backlog[i]));
+	}
+
+	net_tcp_release(context->tcp);
+	context->tcp = NULL;
+
+	return 0;
+}
+
+/** **/
+
+#define net_tcp_print_recv_info(str, pkt, port)				\
+	if (IS_ENABLED(CONFIG_NET_TCP_LOG_LEVEL_DBG)) {			\
+		if (net_pkt_family(pkt) == AF_INET6) {	\
+			NET_DBG("%s received from %s port %d", str,	\
+				log_strdup(net_sprint_ipv6_addr(	\
+					     &NET_IPV6_HDR(pkt)->src)), \
+				ntohs(port));				\
+		} else if (net_pkt_family(pkt) == AF_INET) {\
+			NET_DBG("%s received from %s port %d", str,	\
+				log_strdup(net_sprint_ipv4_addr(	\
+					     &NET_IPV4_HDR(pkt)->src)), \
+				ntohs(port));				\
+		}							\
+	}
+
+#define net_tcp_print_send_info(str, pkt, port)				\
+	if (IS_ENABLED(CONFIG_NET_TCP_LOG_LEVEL_DBG)) {			\
+		if (net_pkt_family(pkt) == AF_INET6) {		\
+			NET_DBG("%s sent to %s port %d", str,		\
+				log_strdup(net_sprint_ipv6_addr(	\
+					     &NET_IPV6_HDR(pkt)->dst)), \
+				ntohs(port));				\
+		} else if (net_pkt_family(pkt) == AF_INET) {	\
+			NET_DBG("%s sent to %s port %d", str,		\
+				log_strdup(net_sprint_ipv4_addr(	\
+					     &NET_IPV4_HDR(pkt)->dst)), \
+				ntohs(port));				\
+		}							\
+	}
+
+static void print_send_info(struct net_pkt *pkt,
+			    const char *msg, const struct sockaddr *remote)
+{
+	if (CONFIG_NET_TCP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		uint16_t port = 0U;
+
+		if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		    net_pkt_family(pkt) == AF_INET) {
+			struct sockaddr_in *addr4 = net_sin(remote);
+
+			port = addr4->sin_port;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		    net_pkt_family(pkt) == AF_INET6) {
+			struct sockaddr_in6 *addr6 = net_sin6(remote);
+
+			port = addr6->sin6_port;
+		}
+
+		net_tcp_print_send_info(msg, pkt, port);
+	}
+}
+
+/* Send SYN or SYN/ACK. */
+static inline int send_syn_segment(struct net_context *context,
+				       const struct sockaddr_ptr *local,
+				       const struct sockaddr *remote,
+				       int flags, const char *msg)
+{
+	struct net_pkt *pkt = NULL;
+	int ret;
+	uint8_t options[NET_TCP_MAX_OPT_SIZE];
+	uint8_t optionlen = 0U;
+
+	if (flags == NET_TCP_SYN) {
+		net_tcp_set_syn_opt(context->tcp, options, &optionlen);
+	}
+
+	ret = net_tcp_prepare_segment(context->tcp, flags, options, optionlen,
+				      local, remote, &pkt);
+	if (ret) {
+		return ret;
+	}
+
+	print_send_info(pkt, msg, remote);
+
+	ret = net_send_data(pkt);
+	if (ret < 0) {
+		net_pkt_unref(pkt);
+		return ret;
+	}
+
+	net_pkt_set_sent(pkt, true);
+	context->tcp->send_seq++;
+
+	return ret;
+}
+
+static inline int send_syn(struct net_context *context,
+			   const struct sockaddr *remote)
+{
+	net_tcp_change_state(context->tcp, NET_TCP_SYN_SENT);
+
+	return send_syn_segment(context, NULL, remote, NET_TCP_SYN, "SYN");
+}
+
+static inline int send_syn_ack(struct net_context *context,
+			       struct sockaddr_ptr *local,
+			       struct sockaddr *remote)
+{
+	return send_syn_segment(context, local, remote,
+				    NET_TCP_SYN | NET_TCP_ACK,
+				    "SYN_ACK");
+}
+
+static int send_ack(struct net_context *context,
+		    struct sockaddr *remote, bool force)
+{
+	struct net_pkt *pkt = NULL;
+	int ret;
+
+	/* Something (e.g. a data transmission under the user
+	 * callback) already sent the ACK, no need
+	 */
+	if (!force && context->tcp->send_ack == context->tcp->sent_ack) {
+		return 0;
+	}
+
+	ret = net_tcp_prepare_ack(context->tcp, remote, &pkt);
+	if (ret) {
+		return ret;
+	}
+
+	print_send_info(pkt, "ACK", remote);
+
+	ret = net_tcp_send_pkt(pkt);
+	if (ret < 0) {
+		net_pkt_unref(pkt);
+	}
+
+	return ret;
+}
+
+static int send_reset(struct net_context *context,
+		      struct sockaddr *local,
+		      struct sockaddr *remote)
+{
+	struct net_pkt *pkt = NULL;
+	int ret;
+
+	ret = net_tcp_prepare_reset(context->tcp, local, remote, &pkt);
+	if (ret || !pkt) {
+		return ret;
+	}
+
+	print_send_info(pkt, "RST", remote);
+
+	ret = net_send_data(pkt);
+	if (ret < 0) {
+		net_pkt_unref(pkt);
+	}
+
+	net_pkt_set_sent(pkt, true);
+	return ret;
+}
+
+static uint16_t adjust_data_len(struct net_pkt *pkt, struct net_tcp_hdr *tcp_hdr,
+			     uint16_t data_len)
+{
+	uint8_t offset = tcp_hdr->offset >> 4;
+
+	/* We need to adjust the length of the data part if there
+	 * are TCP options.
+	 */
+	if ((offset << 2) > sizeof(struct net_tcp_hdr)) {
+		net_pkt_skip(pkt, (offset << 2) -
+			     sizeof(struct net_tcp_hdr));
+
+		data_len -= (offset << 2) - sizeof(struct net_tcp_hdr);
+	}
+
+	return data_len;
+}
+
+/* This is called when we receive data after the connection has been
+ * established. The core TCP logic is located here.
+ *
+ * Prototype:
+ * enum net_verdict tcp_established(struct net_conn *conn,
+ *				    union net_ip_header *ip_hdr,
+ *				    union net_proto_header *proto_hdr,
+ *				    struct net_pkt *pkt,
+ *                                  void *user_data)
+ */
+NET_CONN_CB(tcp_established)
+{
+	struct net_context *context = (struct net_context *)user_data;
+	struct net_tcp_hdr *tcp_hdr = proto_hdr->tcp;
+	enum net_verdict ret = NET_OK;
+	bool do_not_send_ack = false;
+	uint8_t tcp_flags;
+	uint16_t data_len;
+
+	k_mutex_lock(&context->lock, K_FOREVER);
+
+	NET_ASSERT(context && context->tcp);
+
+	if (net_tcp_get_state(context->tcp) < NET_TCP_ESTABLISHED) {
+		NET_ERR("Context %p in wrong state %d",
+			context, net_tcp_get_state(context->tcp));
+		ret = NET_DROP;
+		goto unlock;
+	}
+
+	net_tcp_print_recv_info("DATA", pkt, tcp_hdr->src_port);
+
+	tcp_flags = NET_TCP_FLAGS(tcp_hdr);
+
+	if (net_tcp_seq_cmp(sys_get_be32(tcp_hdr->seq),
+			    context->tcp->send_ack) < 0) {
+		/* Peer sent us packet we've already seen. Apparently,
+		 * our ack was lost.
+		 */
+
+		/* RFC793 specifies that "highest" (i.e. current from our PoV)
+		 * ack # value can/should be sent, so we just force resend.
+		 */
+resend_ack:
+		send_ack(context, &conn->remote_addr, true);
+		ret = NET_DROP;
+		goto unlock;
+	}
+
+	if (net_tcp_seq_cmp(sys_get_be32(tcp_hdr->seq),
+			    context->tcp->send_ack) > 0) {
+		/* Don't try to reorder packets.  If it doesn't
+		 * match the next segment exactly, drop and wait for
+		 * retransmit
+		 */
+		ret = NET_DROP;
+		goto unlock;
+	}
+
+	/*
+	 * If we receive RST here, we close the socket. See RFC 793 chapter
+	 * called "Reset Processing" for details.
+	 */
+	if (tcp_flags & NET_TCP_RST) {
+		/* We only accept RST packet that has valid seq field. */
+		if (!net_tcp_validate_seq(context->tcp, tcp_hdr)) {
+			net_stats_update_tcp_seg_rsterr(net_pkt_iface(pkt));
+			ret = NET_DROP;
+			goto unlock;
+		}
+
+		net_stats_update_tcp_seg_rst(net_pkt_iface(pkt));
+
+		net_tcp_print_recv_info("RST", pkt, tcp_hdr->src_port);
+
+		if (context->recv_cb) {
+			context->recv_cb(context, NULL, NULL, NULL, -ECONNRESET,
+					 context->tcp->recv_user_data);
+		}
+
+		net_context_unref(context);
+
+		ret = NET_DROP;
+		goto unlock;
+	}
+
+	/* Handle TCP state transition */
+	if (tcp_flags & NET_TCP_ACK) {
+		if (!net_tcp_ack_received(context,
+					  sys_get_be32(tcp_hdr->ack))) {
+			ret = NET_DROP;
+			goto unlock;
+		}
+
+		/* TCP state might be changed after maintaining the sent pkt
+		 * list, e.g., an ack of FIN is received.
+		 */
+
+		if (net_tcp_get_state(context->tcp)
+			   == NET_TCP_FIN_WAIT_1) {
+			/* Active close: step to FIN_WAIT_2 */
+			net_tcp_change_state(context->tcp, NET_TCP_FIN_WAIT_2);
+		} else if (net_tcp_get_state(context->tcp)
+			   == NET_TCP_LAST_ACK) {
+			/* Passive close: step to CLOSED */
+			net_tcp_change_state(context->tcp, NET_TCP_CLOSED);
+			/* Release the pkt before clean up */
+			net_pkt_unref(pkt);
+			goto clean_up;
+		}
+	}
+
+	if (tcp_flags & NET_TCP_FIN) {
+		if (net_tcp_get_state(context->tcp) == NET_TCP_ESTABLISHED) {
+			/* Passive close: step to CLOSE_WAIT */
+			net_tcp_change_state(context->tcp, NET_TCP_CLOSE_WAIT);
+
+			/* We should receive ACK next in order to get rid of
+			 * LAST_ACK state that we are entering in a short while.
+			 * But we need to be prepared to NOT to receive it as
+			 * otherwise the connection would be stuck forever.
+			 */
+			k_delayed_work_submit(&context->tcp->ack_timer,
+					      ACK_TIMEOUT);
+
+			net_context_set_closing(context, true);
+		} else if (net_tcp_get_state(context->tcp)
+			   == NET_TCP_FIN_WAIT_2) {
+			/* Received FIN on FIN_WAIT_2, so cancel the timer */
+			k_delayed_work_cancel(&context->tcp->fin_timer);
+			/* Active close: step to TIME_WAIT */
+			net_tcp_change_state(context->tcp, NET_TCP_TIME_WAIT);
+		}
+
+		context->tcp->fin_rcvd = 1U;
+	}
+
+	if (!IS_ENABLED(CONFIG_NET_TCP_AUTO_ACCEPT) &&
+	    net_context_is_accepting(context)) {
+		data_len = 0;
+		do_not_send_ack = true;
+	} else {
+		data_len = net_pkt_remaining_data(pkt);
+	}
+
+	if (data_len > net_tcp_get_recv_wnd(context->tcp)) {
+		/* In case we have zero window, we should still accept
+		 * Zero Window Probes from peer, which per convention
+		 * come with len=1. Note that normally we need to check
+		 * for net_tcp_get_recv_wnd(context->tcp) == 0, but
+		 * given the if above, we know that if data_len == 1,
+		 * then net_tcp_get_recv_wnd(context->tcp) can be only 0
+		 * here.
+		 */
+		if (data_len == 1U) {
+			goto resend_ack;
+		}
+
+		NET_ERR("Context %p: overflow of recv window (%d vs %d), "
+			"pkt dropped",
+			context, net_tcp_get_recv_wnd(context->tcp), data_len);
+		ret = NET_DROP;
+		goto unlock;
+	}
+
+	/* If the pkt has data, notify the recv callback which should
+	 * release the pkt. Otherwise, release the pkt immediately.
+	 */
+	if (data_len > 0) {
+		data_len = adjust_data_len(pkt, tcp_hdr, data_len);
+
+		ret = net_context_packet_received(conn, pkt, ip_hdr, proto_hdr,
+						  context->tcp->recv_user_data);
+	} else if (data_len == 0U) {
+		net_pkt_unref(pkt);
+	}
+
+	if (do_not_send_ack == false) {
+		/* Increment the ack */
+		context->tcp->send_ack += data_len;
+		if (tcp_flags & NET_TCP_FIN) {
+			context->tcp->send_ack += 1U;
+		}
+
+		send_ack(context, &conn->remote_addr, false);
+	}
+
+clean_up:
+	if (net_tcp_get_state(context->tcp) == NET_TCP_TIME_WAIT) {
+		k_delayed_work_submit(&context->tcp->timewait_timer,
+				      K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
+	}
+
+	if (net_tcp_get_state(context->tcp) == NET_TCP_CLOSED) {
+		if (context->recv_cb) {
+			context->recv_cb(context, NULL, NULL, NULL, 0,
+					 context->tcp->recv_user_data);
+		}
+
+		net_context_unref(context);
+	}
+
+unlock:
+	k_mutex_unlock(&context->lock);
+
+	return ret;
+}
+
+/*
+ * Prototype:
+ * enum net_verdict tcp_synack_received(struct net_conn *conn,
+ *					struct net_pkt *pkt,
+ *				        union net_ip_header *ip_hdr,
+ *				        union net_proto_header *proto_hdr,
+ *					void *user_data)
+ */
+NET_CONN_CB(tcp_synack_received)
+{
+	struct net_context *context = (struct net_context *)user_data;
+	struct net_tcp_hdr *tcp_hdr = proto_hdr->tcp;
+	int ret;
+
+	NET_ASSERT(context && context->tcp);
+
+	switch (net_tcp_get_state(context->tcp)) {
+	case NET_TCP_SYN_SENT:
+		net_context_set_iface(context, net_pkt_iface(pkt));
+		break;
+	default:
+		NET_DBG("Context %p in wrong state %d",
+			context, net_tcp_get_state(context->tcp));
+		return NET_DROP;
+	}
+
+	net_pkt_set_context(pkt, context);
+
+	NET_ASSERT(net_pkt_iface(pkt));
+
+	if (NET_TCP_FLAGS(tcp_hdr) & NET_TCP_RST) {
+		/* We only accept RST packet that has valid seq field. */
+		if (!net_tcp_validate_seq(context->tcp, tcp_hdr)) {
+			net_stats_update_tcp_seg_rsterr(net_pkt_iface(pkt));
+			return NET_DROP;
+		}
+
+		net_stats_update_tcp_seg_rst(net_pkt_iface(pkt));
+
+		k_sem_give(&context->tcp->connect_wait);
+
+		if (context->connect_cb) {
+			context->connect_cb(context, -ECONNREFUSED,
+					    context->user_data);
+		}
+
+		return NET_DROP;
+	}
+
+	if (NET_TCP_FLAGS(tcp_hdr) & NET_TCP_SYN) {
+		context->tcp->send_ack =
+			sys_get_be32(tcp_hdr->seq) + 1;
+	}
+	/*
+	 * If we receive SYN, we send SYN-ACK and go to SYN_RCVD state.
+	 */
+	if (NET_TCP_FLAGS(tcp_hdr) == (NET_TCP_SYN | NET_TCP_ACK)) {
+		/* Remove the temporary connection handler and register
+		 * a proper now as we have an established connection.
+		 */
+		struct sockaddr local_addr;
+		struct sockaddr remote_addr;
+
+		tcp_copy_ip_addr_from_hdr(net_pkt_family(pkt), ip_hdr, tcp_hdr,
+					  &remote_addr, true);
+		tcp_copy_ip_addr_from_hdr(net_pkt_family(pkt), ip_hdr, tcp_hdr,
+					  &local_addr, false);
+
+		net_tcp_unregister(context->conn_handler);
+
+		ret = net_tcp_register(net_pkt_family(pkt),
+				       &remote_addr,
+				       &local_addr,
+				       ntohs(tcp_hdr->src_port),
+				       ntohs(tcp_hdr->dst_port),
+				       tcp_established,
+				       context,
+				       &context->conn_handler);
+		if (ret < 0) {
+			NET_DBG("Cannot register TCP handler (%d)", ret);
+			send_reset(context, &local_addr, &remote_addr);
+			return NET_DROP;
+		}
+
+		net_tcp_change_state(context->tcp, NET_TCP_ESTABLISHED);
+		net_context_set_state(context, NET_CONTEXT_CONNECTED);
+
+		send_ack(context, &remote_addr, false);
+
+		k_sem_give(&context->tcp->connect_wait);
+
+		if (context->connect_cb) {
+			context->connect_cb(context, 0, context->user_data);
+		}
+	}
+
+	return NET_DROP;
+}
+
+static void get_sockaddr_ptr(union net_ip_header *ip_hdr,
+			     struct net_tcp_hdr *tcp_hdr,
+			     sa_family_t family,
+			     struct sockaddr_ptr *addr)
+{
+	(void)memset(addr, 0, sizeof(*addr));
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
+		struct sockaddr_in_ptr *addr4 = net_sin_ptr(addr);
+
+		addr4->sin_family = AF_INET;
+		addr4->sin_port = tcp_hdr->dst_port;
+		addr4->sin_addr = &ip_hdr->ipv4->dst;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		struct sockaddr_in6_ptr *addr6 = net_sin6_ptr(addr);
+
+		addr6->sin6_family = AF_INET6;
+		addr6->sin6_port = tcp_hdr->dst_port;
+		addr6->sin6_addr = &ip_hdr->ipv6->dst;
+	}
+}
+
+#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
+static inline void copy_pool_vars(struct net_context *new_context,
+				  struct net_context *listen_context)
+{
+	new_context->tx_slab = listen_context->tx_slab;
+	new_context->data_pool = listen_context->data_pool;
+}
+#else
+#define copy_pool_vars(...)
+#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
+
+/* This callback is called when we are waiting connections and we receive
+ * a packet. We need to check if we are receiving proper msg (SYN) here.
+ * The ACK could also be received, in which case we have an established
+ * connection.
+ *
+ * Prototype:
+ * enum net_verdict tcp_syn_rcvd(struct net_conn *conn,
+ *			         struct net_pkt *pkt,
+ *			         union net_ip_header *ip_hdr,
+ *			         union net_proto_header *proto_hdr,
+ *			         void *user_data)
+ */
+NET_CONN_CB(tcp_syn_rcvd)
+{
+	struct net_context *context = (struct net_context *)user_data;
+	struct net_tcp_hdr *tcp_hdr = proto_hdr->tcp;
+	struct net_tcp *tcp;
+	struct sockaddr_ptr pkt_src_addr;
+	struct sockaddr local_addr;
+	struct sockaddr remote_addr;
+
+	NET_ASSERT(context && context->tcp);
+
+	tcp = context->tcp;
+
+	switch (net_tcp_get_state(tcp)) {
+	case NET_TCP_LISTEN:
+		net_context_set_iface(context, net_pkt_iface(pkt));
+		break;
+	case NET_TCP_SYN_RCVD:
+		if (net_pkt_iface(pkt) != net_context_get_iface(context)) {
+			return NET_DROP;
+		}
+		break;
+	default:
+		NET_DBG("Context %p in wrong state %d",
+			context, tcp->state);
+		return NET_DROP;
+	}
+
+	net_pkt_set_context(pkt, context);
+
+	NET_ASSERT(net_pkt_iface(pkt));
+
+	tcp_copy_ip_addr_from_hdr(net_pkt_family(pkt), ip_hdr, tcp_hdr,
+				  &remote_addr, true);
+	tcp_copy_ip_addr_from_hdr(net_pkt_family(pkt), ip_hdr, tcp_hdr,
+				  &local_addr, false);
+
+	/*
+	 * If we receive SYN, we send SYN-ACK and go to SYN_RCVD state.
+	 */
+	if (NET_TCP_FLAGS(tcp_hdr) == NET_TCP_SYN) {
+		struct net_tcp_options tcp_opts = {
+			.mss = NET_TCP_DEFAULT_MSS,
+		};
+		int opt_totlen;
+		int r;
+
+		net_tcp_print_recv_info("SYN", pkt, tcp_hdr->src_port);
+
+		opt_totlen = NET_TCP_HDR_LEN(tcp_hdr)
+			     - sizeof(struct net_tcp_hdr);
+		/* We expect MSS option to be present (opt_totlen > 0),
+		 * so call unconditionally.
+		 */
+		if (net_tcp_parse_opts(pkt, opt_totlen, &tcp_opts) < 0) {
+			return NET_DROP;
+		}
+
+		net_tcp_change_state(tcp, NET_TCP_SYN_RCVD);
+
+		/* Set TCP seq and ack which are then stored in the backlog */
+		context->tcp->send_seq = tcp_init_isn();
+		context->tcp->send_ack =
+			sys_get_be32(tcp_hdr->seq) + 1;
+
+		/* Get MSS from TCP options here*/
+
+		r = tcp_backlog_syn(pkt, ip_hdr, tcp_hdr,
+				    context, tcp_opts.mss);
+		if (r < 0) {
+			if (r == -EADDRINUSE) {
+				NET_DBG("TCP connection already exists");
+			} else {
+				NET_DBG("No free TCP backlog entries");
+			}
+
+			return NET_DROP;
+		}
+
+		get_sockaddr_ptr(ip_hdr, tcp_hdr,
+				 net_context_get_family(context),
+				 &pkt_src_addr);
+		send_syn_ack(context, &pkt_src_addr, &remote_addr);
+		net_pkt_unref(pkt);
+		return NET_OK;
+	}
+
+	/*
+	 * See RFC 793 chapter 3.4 "Reset Processing" and RFC 793, page 65
+	 * for more details.
+	 */
+	if (NET_TCP_FLAGS(tcp_hdr) & NET_TCP_RST) {
+
+		if (tcp_backlog_rst(pkt, ip_hdr, tcp_hdr) < 0) {
+			net_stats_update_tcp_seg_rsterr(net_pkt_iface(pkt));
+			return NET_DROP;
+		}
+
+		net_stats_update_tcp_seg_rst(net_pkt_iface(pkt));
+
+		net_tcp_print_recv_info("RST", pkt, tcp_hdr->src_port);
+
+		return NET_DROP;
+	}
+
+	/*
+	 * If we receive ACK, we go to ESTABLISHED state.
+	 */
+	if (NET_TCP_FLAGS(tcp_hdr) & NET_TCP_ACK) {
+		struct net_context *new_context;
+		socklen_t addrlen;
+		int ret;
+
+		net_tcp_print_recv_info("ACK", pkt, tcp_hdr->src_port);
+
+		if (!context->tcp->accept_cb) {
+			NET_DBG("No accept callback, connection reset.");
+			goto reset;
+		}
+
+		/* We create a new context that starts to wait data.
+		 */
+		ret = net_context_get(net_pkt_family(pkt),
+				      SOCK_STREAM, IPPROTO_TCP,
+				      &new_context);
+		if (ret < 0) {
+			NET_DBG("Cannot get accepted context, "
+				"connection reset");
+			goto conndrop;
+		}
+
+		ret = tcp_backlog_ack(pkt, ip_hdr, tcp_hdr, new_context);
+		if (ret < 0) {
+			NET_DBG("Cannot find context from TCP backlog");
+
+			net_context_unref(new_context);
+
+			goto conndrop;
+		}
+
+		ret = net_context_bind(new_context, &local_addr,
+				       sizeof(local_addr));
+		if (ret < 0) {
+			NET_DBG("Cannot bind accepted context, "
+				"connection reset");
+			net_context_unref(new_context);
+			goto conndrop;
+		}
+
+		new_context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
+
+		memcpy(&new_context->remote, &remote_addr,
+		       sizeof(remote_addr));
+
+		ret = net_tcp_register(net_pkt_family(pkt),
+			       &new_context->remote,
+			       &local_addr,
+			       ntohs(net_sin(&new_context->remote)->sin_port),
+			       ntohs(net_sin(&local_addr)->sin_port),
+			       tcp_established,
+			       new_context,
+			       &new_context->conn_handler);
+		if (ret < 0) {
+			NET_DBG("Cannot register accepted TCP handler (%d)",
+				ret);
+			net_context_unref(new_context);
+			goto conndrop;
+		}
+
+		/* Swap the newly-created TCP states with the one that
+		 * was used to establish this connection. The old TCP
+		 * must be listening to accept other connections.
+		 */
+		copy_pool_vars(new_context, context);
+
+		net_tcp_change_state(tcp, NET_TCP_LISTEN);
+
+		net_tcp_change_state(new_context->tcp, NET_TCP_ESTABLISHED);
+
+		/* Mark the new context to be still accepting so that we
+		 * can do proper cleanup if connection is closed before
+		 * we have called accept()
+		 */
+		net_context_set_accepting(new_context, true);
+
+		net_context_set_state(new_context, NET_CONTEXT_CONNECTED);
+
+		if (new_context->remote.sa_family == AF_INET) {
+			addrlen = sizeof(struct sockaddr_in);
+		} else if (new_context->remote.sa_family == AF_INET6) {
+			addrlen = sizeof(struct sockaddr_in6);
+		} else {
+			NET_ASSERT(false, "Invalid protocol family %d",
+				   new_context->remote.sa_family);
+			net_context_unref(new_context);
+			return NET_DROP;
+		}
+
+		context->tcp->accept_cb(new_context,
+					&new_context->remote,
+					addrlen,
+					0,
+					context->user_data);
+		net_pkt_unref(pkt);
+		return NET_OK;
+	}
+
+	return NET_DROP;
+
+conndrop:
+	net_stats_update_tcp_seg_conndrop(net_pkt_iface(pkt));
+
+reset:
+	send_reset(tcp->context, &local_addr, &remote_addr);
+
+	return NET_DROP;
+}
+
+int net_tcp_accept(struct net_context *context,
+		   net_tcp_accept_cb_t cb,
+		   void *user_data)
+{
+	struct sockaddr local_addr;
+	struct sockaddr *laddr = NULL;
+	uint16_t lport = 0U;
+	int ret;
+
+	NET_ASSERT(context->tcp);
+
+	if (net_tcp_get_state(context->tcp) != NET_TCP_LISTEN) {
+		NET_DBG("Context %p in wrong state %d, should be %d",
+			context, context->tcp->state, NET_TCP_LISTEN);
+		return -EINVAL;
+	}
+
+	if (cb == NULL) {
+		/* The context is being shut down */
+		if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+			context->tcp->accept_cb = NULL;
+			return 0;
+		}
+	}
+
+	local_addr.sa_family = net_context_get_family(context);
+
+#if defined(CONFIG_NET_IPV6)
+	if (net_context_get_family(context) == AF_INET6) {
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
+				     net_sin6_ptr(&context->local)->sin6_addr);
+
+			laddr = &local_addr;
+		}
+
+		net_sin6(&local_addr)->sin6_port = lport =
+			net_sin6((struct sockaddr *)&context->local)->sin6_port;
+	}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+	if (net_context_get_family(context) == AF_INET) {
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
+				      net_sin_ptr(&context->local)->sin_addr);
+
+			laddr = &local_addr;
+		}
+
+		net_sin(&local_addr)->sin_port = lport =
+			net_sin((struct sockaddr *)&context->local)->sin_port;
+	}
+#endif /* CONFIG_NET_IPV4 */
+
+	ret = net_tcp_register(net_context_get_family(context),
+			       context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
+			       &context->remote : NULL,
+			       laddr,
+			       ntohs(net_sin(&context->remote)->sin_port),
+			       ntohs(lport),
+			       tcp_syn_rcvd,
+			       context,
+			       &context->conn_handler);
+	if (ret < 0) {
+		return ret;
+	}
+
+	context->user_data = user_data;
+
+	/* accept callback is only valid for TCP contexts */
+	if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
+		context->tcp->accept_cb = cb;
+	}
+
+	return 0;
+}
+
+int net_tcp_connect(struct net_context *context,
+		    const struct sockaddr *addr,
+		    struct sockaddr *laddr,
+		    uint16_t rport,
+		    uint16_t lport,
+		    k_timeout_t timeout,
+		    net_context_connect_cb_t cb,
+		    void *user_data)
+{
+	int ret;
+
+	NET_ASSERT(context->tcp);
+
+	if (net_context_get_type(context) != SOCK_STREAM) {
+		return -ENOTSUP;
+	}
+
+	/* We need to register a handler, otherwise the SYN-ACK
+	 * packet would not be received.
+	 */
+	ret = net_tcp_register(net_context_get_family(context),
+			       addr,
+			       laddr,
+			       ntohs(rport),
+			       ntohs(lport),
+			       tcp_synack_received,
+			       context,
+			       &context->conn_handler);
+	if (ret < 0) {
+		return ret;
+	}
+
+	context->connect_cb = cb;
+	context->user_data = user_data;
+
+	net_context_set_state(context, NET_CONTEXT_CONNECTING);
+
+	send_syn(context, addr);
+
+	/* in tcp_synack_received() we give back this semaphore */
+	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+	    k_sem_take(&context->tcp->connect_wait, timeout)) {
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *tcp_access)
+{
+	struct net_tcp_hdr *tcp_hdr;
+
+	if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) &&
+	    net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) &&
+	    net_calc_chksum_tcp(pkt) != 0U) {
+		NET_DBG("DROP: checksum mismatch");
+		goto drop;
+	}
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, tcp_access);
+	if (tcp_hdr && !net_pkt_set_data(pkt, tcp_access)) {
+		return tcp_hdr;
+	}
+
+drop:
+	net_stats_update_tcp_seg_chkerr(net_pkt_iface(pkt));
+	return NULL;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.h	(working copy)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018-2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @brief Transmission Control Protocol (TCP)
+ *
+ * - net_tcp_get() is called by net_context_get(AF_INET, SOCK_STREAM,
+     IPPROTO_TCP, ...) and creates struct tcp for the net_context
+ * - net_tcp_listen()/net_tcp_accept() listen/accept
+ * - At the reception of SYN on the listening net_context, a new pair
+ *   of net_context/struct tcp registers a new net_conn handle
+ *   with the tcp_recv() as a callback
+ * - net_tcp_queue() queues the data for the transmission
+ * - The incoming data is delivered up through the context->recv_cb
+ * - net_tcp_put() closes the connection
+ *
+ * NOTE: The present API is provided in order to make the integration
+ *       into the ip stack and the socket layer less intrusive.
+ *
+ *       Semantically cleaner use is possible (and might be exposed),
+ *       look into the unit test tests/net/tcp2 for insights.
+ */
+
+#ifndef TCP2_H
+#define TCP2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/**
+ * @brief Allocate a TCP connecton for the net_context
+ *        and mutually link the net_context and TCP connection.
+ *
+ * @param context Network context
+ *
+ * @return 0 on success, < 0 on error
+ */
+int net_tcp_get(struct net_context *context);
+
+/**
+ * @brief Close and delete the TCP connecton for the net_context
+ *
+ * @param context Network context
+ *
+ * @return 0 on success, < 0 on error
+ */
+int net_tcp_put(struct net_context *context);
+
+/* TODO: Clarify what happens if the ref count goes to 0 */
+/**
+ * @brief Unref a TCP connecton
+ *
+ * @param context Network context
+ *
+ * @return 0 if successful, < 0 on error
+ */
+int net_tcp_unref(struct net_context *context);
+/* TODO: Merge net_tcp_unref() and net_tcp_put() */
+
+/**
+ * @brief Listen for an incoming TCP connection
+ *
+ * @param context Network context
+ *
+ * @return 0 if successful, < 0 on error
+ */
+int net_tcp_listen(struct net_context *context);
+
+/**
+ * @brief Register an accept callback
+ *
+ * @param context	Network context
+ * @param cb		net_tcp_accept_cb_t callback
+ * @param user_data	User data passed as an argument in the callback
+ *
+ * @return 0 if successful, < 0 on error
+ */
+int net_tcp_accept(struct net_context *context, net_tcp_accept_cb_t cb,
+			void *user_data);
+/**
+ * @brief Enqueue data for transmission
+ *
+ * @param context	Network context
+ * @param buf		Pointer to the data
+ * @param len		Number of bytes
+ * @param msghdr	Data for a vector array operation
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int net_tcp_queue(struct net_context *context, const void *buf, size_t len,
+		  const struct msghdr *msghdr);
+/* TODO: split into 2 functions, conn -> context, queue -> send? */
+
+/* The following functions are provided solely for the compatibility
+ * with the old TCP
+ */
+
+/**
+ * @brief Return struct net_tcp_hdr pointer
+ *
+ * @param pkt Network packet
+ * @param tcp_access Helper variable for accessing TCP header
+ *
+ * @return Pointer to the TCP header on success, NULL on error
+ */
+struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt,
+					struct net_pkt_data_access *tcp_access);
+/* TODO: net_tcp_input() isn't used by TCP and might be dropped with little
+ *       re-factorig
+ */
+
+/* No ops, provided for compatibility with the old TCP */
+
+#if defined(CONFIG_NET_NATIVE_TCP)
+void net_tcp_init(void);
+#else
+#define net_tcp_init(...)
+#endif
+int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta);
+int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt);
+int net_tcp_finalize(struct net_pkt *pkt);
+
+#if defined(CONFIG_NET_TEST_PROTOCOL)
+/**
+ * @brief Handle an incoming TCP packet
+ *
+ * This function is provided for the TCP sanity check and will be eventually
+ * dropped.
+ *
+ * @param pkt Network packet
+ */
+void tcp_input(struct net_pkt *pkt);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TCP2_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2.c	(working copy)
@@ -0,0 +1,2126 @@
+/*
+ * Copyright (c) 2018-2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_tcp, CONFIG_NET_TCP_LOG_LEVEL);
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <zephyr.h>
+#include <random/rand32.h>
+#include <net/net_pkt.h>
+#include <net/net_context.h>
+#include <net/udp.h>
+#include "ipv4.h"
+#include "ipv6.h"
+#include "connection.h"
+#include "net_stats.h"
+#include "net_private.h"
+#include "tcp2_priv.h"
+
+#define FIN_TIMEOUT_MS MSEC_PER_SEC
+#define FIN_TIMEOUT K_MSEC(FIN_TIMEOUT_MS)
+
+static int tcp_rto = CONFIG_NET_TCP_INIT_RETRANSMISSION_TIMEOUT;
+static int tcp_retries = CONFIG_NET_TCP_RETRY_COUNT;
+static int tcp_window = NET_IPV6_MTU;
+
+static sys_slist_t tcp_conns = SYS_SLIST_STATIC_INIT(&tcp_conns);
+
+static K_MEM_SLAB_DEFINE(tcp_conns_slab, sizeof(struct tcp),
+				CONFIG_NET_MAX_CONTEXTS, 4);
+
+static void tcp_in(struct tcp *conn, struct net_pkt *pkt);
+
+int (*tcp_send_cb)(struct net_pkt *pkt) = NULL;
+size_t (*tcp_recv_cb)(struct tcp *conn, struct net_pkt *pkt) = NULL;
+
+static int tcp_pkt_linearize(struct net_pkt *pkt, size_t pos, size_t len)
+{
+	struct net_buf *buf, *first = pkt->cursor.buf, *second = first->frags;
+	int ret = 0;
+	size_t len1, len2;
+
+	if (net_pkt_get_len(pkt) < (pos + len)) {
+		NET_ERR("Insufficient packet len=%zd (pos+len=%zu)",
+			net_pkt_get_len(pkt), pos + len);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buf = net_pkt_get_frag(pkt, TCP_PKT_ALLOC_TIMEOUT);
+
+	if (!buf || buf->size < len) {
+		if (buf) {
+			net_buf_unref(buf);
+		}
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	net_buf_linearize(buf->data, buf->size, pkt->frags, pos, len);
+	net_buf_add(buf, len);
+
+	len1 = first->len - (pkt->cursor.pos - pkt->cursor.buf->data);
+	len2 = len - len1;
+
+	first->len -= len1;
+
+	while (len2) {
+		size_t pull_len = MIN(second->len, len2);
+		struct net_buf *next;
+
+		len2 -= pull_len;
+		net_buf_pull(second, pull_len);
+		next = second->frags;
+		if (second->len == 0) {
+			net_buf_unref(second);
+		}
+		second = next;
+	}
+
+	buf->frags = second;
+	first->frags = buf;
+ out:
+	return ret;
+}
+
+static struct tcphdr *th_get(struct net_pkt *pkt)
+{
+	size_t ip_len = net_pkt_ip_hdr_len(pkt) + net_pkt_ip_opts_len(pkt);
+	struct tcphdr *th = NULL;
+ again:
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+
+	if (net_pkt_skip(pkt, ip_len) != 0) {
+		goto out;
+	}
+
+	if (!net_pkt_is_contiguous(pkt, sizeof(*th))) {
+		if (tcp_pkt_linearize(pkt, ip_len, sizeof(*th)) < 0) {
+			goto out;
+		}
+
+		goto again;
+	}
+
+	th = net_pkt_cursor_get_pos(pkt);
+ out:
+	return th;
+}
+
+static size_t tcp_endpoint_len(sa_family_t af)
+{
+	return (af == AF_INET) ? sizeof(struct sockaddr_in) :
+		sizeof(struct sockaddr_in6);
+}
+
+static int tcp_endpoint_set(union tcp_endpoint *ep, struct net_pkt *pkt,
+			    enum pkt_addr src)
+{
+	int ret = 0;
+
+	switch (net_pkt_family(pkt)) {
+	case AF_INET:
+		if (IS_ENABLED(CONFIG_NET_IPV4)) {
+			struct net_ipv4_hdr *ip = NET_IPV4_HDR(pkt);
+			struct tcphdr *th;
+
+			th = th_get(pkt);
+			if (!th) {
+				return -ENOBUFS;
+			}
+
+			memset(ep, 0, sizeof(*ep));
+
+			ep->sin.sin_port = src == TCP_EP_SRC ? th->th_sport :
+							       th->th_dport;
+			net_ipaddr_copy(&ep->sin.sin_addr,
+					src == TCP_EP_SRC ?
+							&ip->src : &ip->dst);
+			ep->sa.sa_family = AF_INET;
+		} else {
+			ret = -EINVAL;
+		}
+
+		break;
+
+	case AF_INET6:
+		if (IS_ENABLED(CONFIG_NET_IPV6)) {
+			struct net_ipv6_hdr *ip = NET_IPV6_HDR(pkt);
+			struct tcphdr *th;
+
+			th = th_get(pkt);
+			if (!th) {
+				return -ENOBUFS;
+			}
+
+			memset(ep, 0, sizeof(*ep));
+
+			ep->sin6.sin6_port = src == TCP_EP_SRC ? th->th_sport :
+								 th->th_dport;
+			net_ipaddr_copy(&ep->sin6.sin6_addr,
+					src == TCP_EP_SRC ?
+							&ip->src : &ip->dst);
+			ep->sa.sa_family = AF_INET6;
+		} else {
+			ret = -EINVAL;
+		}
+
+		break;
+
+	default:
+		NET_ERR("Unknown address family: %hu", net_pkt_family(pkt));
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const char *tcp_flags(uint8_t flags)
+{
+#define BUF_SIZE 25 /* 6 * 4 + 1 */
+	static char buf[BUF_SIZE];
+	int len = 0;
+
+	buf[0] = '\0';
+
+	if (flags) {
+		if (flags & SYN) {
+			len += snprintk(buf + len, BUF_SIZE - len, "SYN,");
+		}
+		if (flags & FIN) {
+			len += snprintk(buf + len, BUF_SIZE - len, "FIN,");
+		}
+		if (flags & ACK) {
+			len += snprintk(buf + len, BUF_SIZE - len, "ACK,");
+		}
+		if (flags & PSH) {
+			len += snprintk(buf + len, BUF_SIZE - len, "PSH,");
+		}
+		if (flags & RST) {
+			len += snprintk(buf + len, BUF_SIZE - len, "RST,");
+		}
+		if (flags & URG) {
+			len += snprintk(buf + len, BUF_SIZE - len, "URG,");
+		}
+
+		buf[len - 1] = '\0'; /* delete the last comma */
+	}
+#undef BUF_SIZE
+	return buf;
+}
+
+static size_t tcp_data_len(struct net_pkt *pkt)
+{
+	struct tcphdr *th = th_get(pkt);
+	size_t tcp_options_len = (th->th_off - 5) * 4;
+	int len = net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) -
+		net_pkt_ip_opts_len(pkt) - sizeof(*th) - tcp_options_len;
+
+	return len > 0 ? (size_t)len : 0;
+}
+
+static const char *tcp_th(struct net_pkt *pkt)
+{
+#define BUF_SIZE 80
+	static char buf[BUF_SIZE];
+	int len = 0;
+	struct tcphdr *th = th_get(pkt);
+
+	buf[0] = '\0';
+
+	if (th->th_off < 5) {
+		len += snprintk(buf + len, BUF_SIZE - len,
+				"bogus th_off: %hu", (uint16_t)th->th_off);
+		goto end;
+	}
+
+	len += snprintk(buf + len, BUF_SIZE - len,
+			"%s Seq=%u", tcp_flags(th->th_flags), th_seq(th));
+
+	if (th->th_flags & ACK) {
+		len += snprintk(buf + len, BUF_SIZE - len,
+				" Ack=%u", th_ack(th));
+	}
+
+	len += snprintk(buf + len, BUF_SIZE - len,
+			" Len=%ld", (long)tcp_data_len(pkt));
+end:
+#undef BUF_SIZE
+	return buf;
+}
+
+static void tcp_send(struct net_pkt *pkt)
+{
+	NET_DBG("%s", log_strdup(tcp_th(pkt)));
+
+	tcp_pkt_ref(pkt);
+
+	if (tcp_send_cb) {
+		if (tcp_send_cb(pkt) < 0) {
+			NET_ERR("net_send_data()");
+			tcp_pkt_unref(pkt);
+		}
+		goto out;
+	}
+
+	if (net_send_data(pkt) < 0) {
+		NET_ERR("net_send_data()");
+		tcp_pkt_unref(pkt);
+	}
+out:
+	tcp_pkt_unref(pkt);
+}
+
+static void tcp_send_queue_flush(struct tcp *conn)
+{
+	struct net_pkt *pkt;
+
+	k_delayed_work_cancel(&conn->send_timer);
+
+	while ((pkt = tcp_slist(&conn->send_queue, get,
+				struct net_pkt, next))) {
+		tcp_pkt_unref(pkt);
+	}
+}
+
+static int tcp_conn_unref(struct tcp *conn)
+{
+	int key, ref_count = atomic_get(&conn->ref_count);
+
+	NET_DBG("conn: %p, ref_count=%d", conn, ref_count);
+
+#if !defined(CONFIG_NET_TEST_PROTOCOL)
+	if (conn->in_connect) {
+		NET_DBG("conn: %p is waiting on connect semaphore", conn);
+		tcp_send_queue_flush(conn);
+		goto out;
+	}
+#endif /* CONFIG_NET_TEST_PROTOCOL */
+
+	ref_count = atomic_dec(&conn->ref_count) - 1;
+
+	if (ref_count) {
+		tp_out(net_context_get_family(conn->context), conn->iface,
+		       "TP_TRACE", "event", "CONN_DELETE");
+		goto out;
+	}
+
+	key = irq_lock();
+
+	if (conn->context->conn_handler) {
+		net_conn_unregister(conn->context->conn_handler);
+		conn->context->conn_handler = NULL;
+	}
+
+	if (conn->context->recv_cb) {
+		conn->context->recv_cb(conn->context, NULL, NULL, NULL,
+					-ECONNRESET, conn->recv_user_data);
+	}
+
+	conn->context->tcp = NULL;
+
+	net_context_unref(conn->context);
+
+	tcp_send_queue_flush(conn);
+
+	k_delayed_work_cancel(&conn->send_data_timer);
+	tcp_pkt_unref(conn->send_data);
+
+	k_delayed_work_cancel(&conn->timewait_timer);
+	k_delayed_work_cancel(&conn->fin_timer);
+
+	sys_slist_find_and_remove(&tcp_conns, &conn->next);
+
+	memset(conn, 0, sizeof(*conn));
+
+	k_mem_slab_free(&tcp_conns_slab, (void **)&conn);
+
+	irq_unlock(key);
+out:
+	return ref_count;
+}
+
+int net_tcp_unref(struct net_context *context)
+{
+	int ref_count = 0;
+
+	NET_DBG("context: %p, conn: %p", context, context->tcp);
+
+	if (context->tcp) {
+		ref_count = tcp_conn_unref(context->tcp);
+	}
+
+	return ref_count;
+}
+
+static void tcp_send_process(struct k_work *work)
+{
+	struct tcp *conn = CONTAINER_OF(work, struct tcp, send_timer);
+	bool unref = false;
+	struct net_pkt *pkt;
+
+	k_mutex_lock(&conn->lock, K_FOREVER);
+
+	pkt = tcp_slist(&conn->send_queue, peek_head,
+			struct net_pkt, next);
+	if (!pkt) {
+		goto out;
+	}
+
+	NET_DBG("%s %s", log_strdup(tcp_th(pkt)), conn->in_retransmission ?
+		"in_retransmission" : "");
+
+	if (conn->in_retransmission) {
+		if (conn->send_retries > 0) {
+			struct net_pkt *clone = tcp_pkt_clone(pkt);
+
+			if (clone) {
+				tcp_send(clone);
+				conn->send_retries--;
+			}
+		} else {
+			unref = true;
+			goto out;
+		}
+	} else {
+		uint8_t fl = th_get(pkt)->th_flags;
+		bool forget = ACK == fl || PSH == fl || (ACK | PSH) == fl ||
+			RST & fl;
+
+		pkt = forget ? tcp_slist(&conn->send_queue, get, struct net_pkt,
+						next) : tcp_pkt_clone(pkt);
+		if (!pkt) {
+			NET_ERR("net_pkt alloc failure");
+			goto out;
+		}
+
+		tcp_send(pkt);
+
+		if (forget == false && !k_delayed_work_remaining_get(
+				&conn->send_timer)) {
+			conn->send_retries = tcp_retries;
+			conn->in_retransmission = true;
+		}
+	}
+
+	if (conn->in_retransmission) {
+		k_delayed_work_submit(&conn->send_timer, K_MSEC(tcp_rto));
+	}
+
+out:
+	k_mutex_unlock(&conn->lock);
+
+	if (unref) {
+		tcp_conn_unref(conn);
+	}
+}
+
+static void tcp_send_timer_cancel(struct tcp *conn)
+{
+	if (conn->in_retransmission == false) {
+		return;
+	}
+
+	k_delayed_work_cancel(&conn->send_timer);
+
+	{
+		struct net_pkt *pkt = tcp_slist(&conn->send_queue, get,
+						struct net_pkt, next);
+		if (pkt) {
+			NET_DBG("%s", log_strdup(tcp_th(pkt)));
+			tcp_pkt_unref(pkt);
+		}
+	}
+
+	if (sys_slist_is_empty(&conn->send_queue)) {
+		conn->in_retransmission = false;
+	} else {
+		conn->send_retries = tcp_retries;
+		k_delayed_work_submit(&conn->send_timer, K_MSEC(tcp_rto));
+	}
+}
+
+static const char *tcp_state_to_str(enum tcp_state state, bool prefix)
+{
+	const char *s = NULL;
+#define _(_x) case _x: do { s = #_x; goto out; } while (0)
+	switch (state) {
+	_(TCP_LISTEN);
+	_(TCP_SYN_SENT);
+	_(TCP_SYN_RECEIVED);
+	_(TCP_ESTABLISHED);
+	_(TCP_FIN_WAIT_1);
+	_(TCP_FIN_WAIT_2);
+	_(TCP_CLOSE_WAIT);
+	_(TCP_CLOSING);
+	_(TCP_LAST_ACK);
+	_(TCP_TIME_WAIT);
+	_(TCP_CLOSED);
+	}
+#undef _
+	NET_ASSERT(s, "Invalid TCP state: %u", state);
+out:
+	return prefix ? s : (s + 4);
+}
+
+static const char *tcp_conn_state(struct tcp *conn, struct net_pkt *pkt)
+{
+#define BUF_SIZE 160
+	static char buf[BUF_SIZE];
+
+	snprintk(buf, BUF_SIZE, "%s [%s Seq=%u Ack=%u]", pkt ? tcp_th(pkt) : "",
+			tcp_state_to_str(conn->state, false),
+			conn->seq, conn->ack);
+#undef BUF_SIZE
+	return buf;
+}
+
+static uint8_t *tcp_options_get(struct net_pkt *pkt, int tcp_options_len,
+				uint8_t *buf, size_t buf_len)
+{
+	struct net_pkt_cursor backup;
+	int ret;
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ip_opts_len(pkt) +
+		     sizeof(struct tcphdr));
+	ret = net_pkt_read(pkt, buf, MIN(tcp_options_len, buf_len));
+	if (ret < 0) {
+		buf = NULL;
+	}
+
+	net_pkt_cursor_restore(pkt, &backup);
+
+	return buf;
+}
+
+static bool tcp_options_check(struct tcp_options *recv_options,
+			      struct net_pkt *pkt, ssize_t len)
+{
+	uint8_t options_buf[40]; /* TCP header max options size is 40 */
+	bool result = len > 0 && ((len % 4) == 0) ? true : false;
+	uint8_t *options = tcp_options_get(pkt, len, options_buf,
+					   sizeof(options_buf));
+	uint8_t opt, opt_len;
+
+	NET_DBG("len=%zd", len);
+
+	recv_options->mss_found = false;
+	recv_options->wnd_found = false;
+
+	for ( ; options && len >= 1; options += opt_len, len -= opt_len) {
+		opt = options[0];
+
+		if (opt == TCPOPT_END) {
+			break;
+		} else if (opt == TCPOPT_NOP) {
+			opt_len = 1;
+			continue;
+		} else {
+			if (len < 2) { /* Only END and NOP can have length 1 */
+				NET_ERR("Illegal option %d with length %zd",
+					opt, len);
+				result = false;
+				break;
+			}
+			opt_len = options[1];
+		}
+		NET_DBG("opt: %hu, opt_len: %hu", (uint16_t)opt, (uint16_t)opt_len);
+
+		if (opt_len < 2 || opt_len > len) {
+			result = false;
+			break;
+		}
+
+		switch (opt) {
+		case TCPOPT_MAXSEG:
+			if (opt_len != 4) {
+				result = false;
+				goto end;
+			}
+
+			recv_options->mss =
+				ntohs(UNALIGNED_GET((uint16_t *)(options + 2)));
+			recv_options->mss_found = true;
+			NET_DBG("MSS=%hu", recv_options->mss);
+			break;
+		case TCPOPT_WINDOW:
+			if (opt_len != 3) {
+				result = false;
+				goto end;
+			}
+
+			recv_options->window = opt;
+			recv_options->wnd_found = true;
+			break;
+		default:
+			continue;
+		}
+	}
+end:
+	if (false == result) {
+		NET_WARN("Invalid TCP options");
+	}
+
+	return result;
+}
+
+static int tcp_data_get(struct tcp *conn, struct net_pkt *pkt)
+{
+	int len = tcp_data_len(pkt);
+
+	if (tcp_recv_cb) {
+		tcp_recv_cb(conn, pkt);
+		goto out;
+	}
+
+	if (len > 0) {
+		if (conn->context->recv_cb) {
+			struct net_pkt *up =
+				net_pkt_clone(pkt, TCP_PKT_ALLOC_TIMEOUT);
+
+			if (!up) {
+				len = -ENOBUFS;
+				goto out;
+			}
+
+			net_pkt_cursor_init(up);
+			net_pkt_set_overwrite(up, true);
+
+			net_pkt_skip(up, net_pkt_get_len(up) - len);
+
+			net_context_packet_received(
+				(struct net_conn *)conn->context->conn_handler,
+				up, NULL, NULL, conn->recv_user_data);
+		}
+	}
+ out:
+	return len;
+}
+
+static int tcp_finalize_pkt(struct net_pkt *pkt)
+{
+	net_pkt_cursor_init(pkt);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		return net_ipv4_finalize(pkt, IPPROTO_TCP);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		return net_ipv6_finalize(pkt, IPPROTO_TCP);
+	}
+
+	return -EINVAL;
+}
+
+static int tcp_header_add(struct tcp *conn, struct net_pkt *pkt, uint8_t flags,
+			  uint32_t seq)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct tcphdr);
+	struct tcphdr *th;
+
+	th = (struct tcphdr *)net_pkt_get_data(pkt, &tcp_access);
+	if (!th) {
+		return -ENOBUFS;
+	}
+
+	memset(th, 0, sizeof(struct tcphdr));
+
+	th->th_sport = conn->src.sin.sin_port;
+	th->th_dport = conn->dst.sin.sin_port;
+
+	th->th_off = 5;
+	th->th_flags = flags;
+	th->th_win = htons(conn->recv_win);
+	th->th_seq = htonl(seq);
+
+	if (ACK & flags) {
+		th->th_ack = htonl(conn->ack);
+	}
+
+	return net_pkt_set_data(pkt, &tcp_access);
+}
+
+static int ip_header_add(struct tcp *conn, struct net_pkt *pkt)
+{
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		return net_context_create_ipv4_new(conn->context, pkt,
+						&conn->src.sin.sin_addr,
+						&conn->dst.sin.sin_addr);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		return net_context_create_ipv6_new(conn->context, pkt,
+						&conn->src.sin6.sin6_addr,
+						&conn->dst.sin6.sin6_addr);
+	}
+
+	return -EINVAL;
+}
+
+static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data,
+		       uint32_t seq)
+{
+	struct net_pkt *pkt;
+	int ret = 0;
+
+	pkt = tcp_pkt_alloc(conn, sizeof(struct tcphdr));
+	if (!pkt) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	if (data) {
+		/* Append the data buffer to the pkt */
+		net_pkt_append_buffer(pkt, data->buffer);
+		data->buffer = NULL;
+	}
+
+	ret = ip_header_add(conn, pkt);
+	if (ret < 0) {
+		tcp_pkt_unref(pkt);
+		goto out;
+	}
+
+	ret = tcp_header_add(conn, pkt, flags, seq);
+	if (ret < 0) {
+		tcp_pkt_unref(pkt);
+		goto out;
+	}
+
+	ret = tcp_finalize_pkt(pkt);
+	if (ret < 0) {
+		tcp_pkt_unref(pkt);
+		goto out;
+	}
+
+	NET_DBG("%s", log_strdup(tcp_th(pkt)));
+
+	if (tcp_send_cb) {
+		ret = tcp_send_cb(pkt);
+		goto out;
+	}
+
+	sys_slist_append(&conn->send_queue, &pkt->next);
+
+	tcp_send_process(&conn->send_timer.work);
+out:
+	return ret;
+}
+
+static void tcp_out(struct tcp *conn, uint8_t flags)
+{
+	(void)tcp_out_ext(conn, flags, NULL /* no data */, conn->seq);
+}
+
+static int tcp_pkt_pull(struct net_pkt *pkt, size_t len)
+{
+	int total = net_pkt_get_len(pkt);
+	int ret = 0;
+
+	if (len > total) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+	net_pkt_pull(pkt, len);
+	net_pkt_trim_buffer(pkt);
+ out:
+	return ret;
+}
+
+static int tcp_pkt_peek(struct net_pkt *to, struct net_pkt *from, size_t pos,
+			size_t len)
+{
+	net_pkt_cursor_init(to);
+	net_pkt_cursor_init(from);
+
+	if (pos) {
+		net_pkt_set_overwrite(from, true);
+		net_pkt_skip(from, pos);
+	}
+
+	return net_pkt_copy(to, from, len);
+}
+
+static bool tcp_window_full(struct tcp *conn)
+{
+	bool window_full = !(conn->unacked_len < conn->send_win);
+
+	NET_DBG("conn: %p window_full=%hu", conn, window_full);
+
+	return window_full;
+}
+
+static int tcp_unsent_len(struct tcp *conn)
+{
+	int unsent_len;
+
+	if (conn->unacked_len > conn->send_data_total) {
+		NET_ERR("total=%zu, unacked_len=%d",
+			conn->send_data_total, conn->unacked_len);
+		unsent_len = -ERANGE;
+		goto out;
+	}
+
+	unsent_len = conn->send_data_total - conn->unacked_len;
+ out:
+	NET_DBG("unsent_len=%d", unsent_len);
+
+	return unsent_len;
+}
+
+static int tcp_send_data(struct tcp *conn)
+{
+	int ret = 0;
+	int pos, len;
+	struct net_pkt *pkt;
+
+	pos = conn->unacked_len;
+	len = MIN3(conn->send_data_total - conn->unacked_len,
+		   conn->send_win - conn->unacked_len,
+		   conn_mss(conn));
+
+	pkt = tcp_pkt_alloc(conn, len);
+	if (!pkt) {
+		NET_ERR("conn: %p packet allocation failed, len=%d", conn, len);
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	ret = tcp_pkt_peek(pkt, conn->send_data, pos, len);
+	if (ret < 0) {
+		tcp_pkt_unref(pkt);
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	ret = tcp_out_ext(conn, PSH | ACK, pkt, conn->seq + conn->unacked_len);
+	if (ret == 0) {
+		conn->unacked_len += len;
+	}
+
+	/* The data we want to send, has been moved to the send queue so we
+	 * can unref the head net_pkt. If there was an error, we need to remove
+	 * the packet anyway.
+	 */
+	tcp_pkt_unref(pkt);
+
+	conn_send_data_dump(conn);
+
+ out:
+	return ret;
+}
+
+/* Send all queued but unsent data from the send_data packet by packet
+ * until the receiver's window is full. */
+static int tcp_send_queued_data(struct tcp *conn)
+{
+	int ret = 0;
+	bool subscribe = false;
+
+	if (conn->data_mode == TCP_DATA_MODE_RESEND) {
+		goto out;
+	}
+
+	while (tcp_unsent_len(conn) > 0) {
+
+		if (tcp_window_full(conn)) {
+			subscribe = true;
+			break;
+		}
+
+		ret = tcp_send_data(conn);
+		if (ret < 0) {
+			break;
+		}
+	}
+
+	if (conn->unacked_len) {
+		subscribe = true;
+	}
+
+	if (k_delayed_work_remaining_get(&conn->send_data_timer)) {
+		subscribe = false;
+	}
+
+	/* If we have out-of-bufs case, then do not start retransmit timer
+	 * yet. The socket layer will catch this and resend data if needed.
+	 */
+	if (ret == -ENOBUFS) {
+		NET_DBG("No bufs, cancelling retransmit timer");
+		k_delayed_work_cancel(&conn->send_data_timer);
+	}
+
+	if (subscribe) {
+		conn->send_data_retries = 0;
+		k_delayed_work_submit(&conn->send_data_timer, K_MSEC(tcp_rto));
+	}
+ out:
+	return ret;
+}
+
+static void tcp_resend_data(struct k_work *work)
+{
+	struct tcp *conn = CONTAINER_OF(work, struct tcp, send_data_timer);
+	bool conn_unref = false;
+	int ret;
+
+	k_mutex_lock(&conn->lock, K_FOREVER);
+
+	NET_DBG("send_data_retries=%hu", conn->send_data_retries);
+
+	if (conn->send_data_retries >= tcp_retries) {
+		NET_DBG("conn: %p close, data retransmissions exceeded", conn);
+		conn_unref = true;
+		goto out;
+	}
+
+	conn->data_mode = TCP_DATA_MODE_RESEND;
+	conn->unacked_len = 0;
+
+	ret = tcp_send_data(conn);
+	if (ret == 0) {
+		conn->send_data_retries++;
+
+		if (conn->in_close && conn->send_data_total == 0) {
+			NET_DBG("TCP connection in active close, "
+				"not disposing yet (waiting %dms)",
+				FIN_TIMEOUT_MS);
+			k_delayed_work_submit(&conn->fin_timer, FIN_TIMEOUT);
+
+			conn_state(conn, TCP_FIN_WAIT_1);
+
+			ret = tcp_out_ext(conn, FIN | ACK, NULL,
+				    conn->seq + conn->unacked_len);
+			if (ret == 0) {
+				conn_seq(conn, + 1);
+			}
+
+			goto out;
+		}
+	}
+
+	k_delayed_work_submit(&conn->send_data_timer, K_MSEC(tcp_rto));
+
+ out:
+	k_mutex_unlock(&conn->lock);
+
+	if (conn_unref) {
+		tcp_conn_unref(conn);
+	}
+}
+
+static void tcp_timewait_timeout(struct k_work *work)
+{
+	struct tcp *conn = CONTAINER_OF(work, struct tcp, timewait_timer);
+
+	NET_DBG("conn: %p %s", conn, log_strdup(tcp_conn_state(conn, NULL)));
+
+	/* Extra unref from net_tcp_put() */
+	net_context_unref(conn->context);
+}
+
+static void tcp_fin_timeout(struct k_work *work)
+{
+	struct tcp *conn = CONTAINER_OF(work, struct tcp, fin_timer);
+
+	NET_DBG("Did not receive FIN in %dms", FIN_TIMEOUT_MS);
+	NET_DBG("conn: %p %s", conn, log_strdup(tcp_conn_state(conn, NULL)));
+
+	/* Extra unref from net_tcp_put() */
+	net_context_unref(conn->context);
+}
+
+static void tcp_conn_ref(struct tcp *conn)
+{
+	int ref_count = atomic_inc(&conn->ref_count) + 1;
+
+	NET_DBG("conn: %p, ref_count: %d", conn, ref_count);
+}
+
+static struct tcp *tcp_conn_alloc(void)
+{
+	struct tcp *conn = NULL;
+	int ret;
+
+	ret = k_mem_slab_alloc(&tcp_conns_slab, (void **)&conn, K_NO_WAIT);
+	if (ret) {
+		goto out;
+	}
+
+	memset(conn, 0, sizeof(*conn));
+
+	k_mutex_init(&conn->lock);
+
+	conn->state = TCP_LISTEN;
+
+	conn->recv_win = tcp_window;
+
+	conn->seq = (IS_ENABLED(CONFIG_NET_TEST_PROTOCOL) ||
+		     IS_ENABLED(CONFIG_NET_TEST)) ? 0 : sys_rand32_get();
+
+	sys_slist_init(&conn->send_queue);
+
+	k_delayed_work_init(&conn->send_timer, tcp_send_process);
+
+	k_delayed_work_init(&conn->timewait_timer, tcp_timewait_timeout);
+	k_delayed_work_init(&conn->fin_timer, tcp_fin_timeout);
+
+	conn->send_data = tcp_pkt_alloc(conn, 0);
+	k_delayed_work_init(&conn->send_data_timer, tcp_resend_data);
+
+	k_sem_init(&conn->connect_sem, 0, UINT_MAX);
+	conn->in_connect = false;
+
+	tcp_conn_ref(conn);
+
+	sys_slist_append(&tcp_conns, &conn->next);
+out:
+	NET_DBG("conn: %p", conn);
+
+	return conn;
+}
+
+int net_tcp_get(struct net_context *context)
+{
+	int ret = 0, key = irq_lock();
+	struct tcp *conn;
+
+	conn = tcp_conn_alloc();
+	if (conn == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Mutually link the net_context and tcp connection */
+	conn->context = context;
+	context->tcp = conn;
+out:
+	irq_unlock(key);
+
+	return ret;
+}
+
+static bool tcp_endpoint_cmp(union tcp_endpoint *ep, struct net_pkt *pkt,
+			     enum pkt_addr which)
+{
+	union tcp_endpoint ep_tmp;
+
+	if (tcp_endpoint_set(&ep_tmp, pkt, which) < 0) {
+		return false;
+	}
+
+	return !memcmp(ep, &ep_tmp, tcp_endpoint_len(ep->sa.sa_family));
+}
+
+static bool tcp_conn_cmp(struct tcp *conn, struct net_pkt *pkt)
+{
+	return tcp_endpoint_cmp(&conn->src, pkt, TCP_EP_DST) &&
+		tcp_endpoint_cmp(&conn->dst, pkt, TCP_EP_SRC);
+}
+
+static struct tcp *tcp_conn_search(struct net_pkt *pkt)
+{
+	bool found = false;
+	struct tcp *conn;
+	struct tcp *tmp;
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&tcp_conns, conn, tmp, next) {
+
+		found = tcp_conn_cmp(conn, pkt);
+		if (found) {
+			break;
+		}
+	}
+
+	return found ? conn : NULL;
+}
+
+static struct tcp *tcp_conn_new(struct net_pkt *pkt);
+
+static enum net_verdict tcp_recv(struct net_conn *net_conn,
+				 struct net_pkt *pkt,
+				 union net_ip_header *ip,
+				 union net_proto_header *proto,
+				 void *user_data)
+{
+	struct tcp *conn;
+	struct tcphdr *th;
+
+	ARG_UNUSED(net_conn);
+	ARG_UNUSED(proto);
+
+	conn = tcp_conn_search(pkt);
+	if (conn) {
+		goto in;
+	}
+
+	th = th_get(pkt);
+
+	if (th->th_flags & SYN && !(th->th_flags & ACK)) {
+		struct tcp *conn_old = ((struct net_context *)user_data)->tcp;
+
+		conn = tcp_conn_new(pkt);
+		if (!conn) {
+			NET_ERR("Cannot allocate a new TCP connection");
+			goto in;
+		}
+
+		net_ipaddr_copy(&conn_old->context->remote, &conn->dst.sa);
+
+		conn->accepted_conn = conn_old;
+	}
+ in:
+	if (conn) {
+		tcp_in(conn, pkt);
+	}
+
+	return NET_DROP;
+}
+
+/* Create a new tcp connection, as a part of it, create and register
+ * net_context
+ */
+static struct tcp *tcp_conn_new(struct net_pkt *pkt)
+{
+	struct tcp *conn = NULL;
+	struct net_context *context = NULL;
+	sa_family_t af = net_pkt_family(pkt);
+	struct sockaddr local_addr = { 0 };
+	int ret;
+
+	ret = net_context_get(af, SOCK_STREAM, IPPROTO_TCP, &context);
+	if (ret < 0) {
+		NET_ERR("net_context_get(): %d", ret);
+		goto err;
+	}
+
+	conn = context->tcp;
+	conn->iface = pkt->iface;
+
+	net_context_set_family(conn->context, net_pkt_family(pkt));
+
+	if (tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC) < 0) {
+		net_context_unref(context);
+		conn = NULL;
+		goto err;
+	}
+
+	if (tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST) < 0) {
+		net_context_unref(context);
+		conn = NULL;
+		goto err;
+	}
+
+	NET_DBG("conn: src: %s, dst: %s",
+		log_strdup(net_sprint_addr(conn->src.sa.sa_family,
+				(const void *)&conn->src.sin.sin_addr)),
+		log_strdup(net_sprint_addr(conn->dst.sa.sa_family,
+				(const void *)&conn->dst.sin.sin_addr)));
+
+	memcpy(&context->remote, &conn->dst, sizeof(context->remote));
+	context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
+
+	net_sin_ptr(&context->local)->sin_family = af;
+
+	local_addr.sa_family = net_context_get_family(context);
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(context) == AF_INET6) {
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			net_ipaddr_copy(&net_sin6(&local_addr)->sin6_addr,
+				     net_sin6_ptr(&context->local)->sin6_addr);
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(context) == AF_INET) {
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			net_ipaddr_copy(&net_sin(&local_addr)->sin_addr,
+				      net_sin_ptr(&context->local)->sin_addr);
+		}
+	}
+
+	ret = net_context_bind(context, &local_addr, sizeof(local_addr));
+	if (ret < 0) {
+		NET_DBG("Cannot bind accepted context, connection reset");
+		net_context_unref(context);
+		conn = NULL;
+		goto err;
+	}
+
+	NET_DBG("context: local: %s, remote: %s",
+		log_strdup(net_sprint_addr(
+		      local_addr.sa_family,
+		      (const void *)&net_sin(&local_addr)->sin_addr)),
+		log_strdup(net_sprint_addr(
+		      context->remote.sa_family,
+		      (const void *)&net_sin(&context->remote)->sin_addr)));
+
+	ret = net_conn_register(IPPROTO_TCP, af,
+				&context->remote, &local_addr,
+				ntohs(conn->dst.sin.sin_port),/* local port */
+				ntohs(conn->src.sin.sin_port),/* remote port */
+				tcp_recv, context,
+				&context->conn_handler);
+	if (ret < 0) {
+		NET_ERR("net_conn_register(): %d", ret);
+		net_context_unref(context);
+		conn = NULL;
+		goto err;
+	}
+err:
+	return conn;
+}
+
+/* TCP state machine, everything happens here */
+static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
+{
+	struct tcphdr *th = pkt ? th_get(pkt) : NULL;
+	uint8_t next = 0, fl = 0;
+	size_t tcp_options_len = th ? (th->th_off - 5) * 4 : 0;
+	size_t len;
+	int ret;
+
+	if (th) {
+		/* Currently we ignore ECN and CWR flags */
+		fl = th->th_flags & ~(ECN | CWR);
+	}
+
+	k_mutex_lock(&conn->lock, K_FOREVER);
+
+	NET_DBG("%s", log_strdup(tcp_conn_state(conn, pkt)));
+
+	if (th && th->th_off < 5) {
+		tcp_out(conn, RST);
+		conn_state(conn, TCP_CLOSED);
+		goto next_state;
+	}
+
+	if (tcp_options_len && !tcp_options_check(&conn->recv_options, pkt,
+						  tcp_options_len)) {
+		NET_DBG("DROP: Invalid TCP option list");
+		tcp_out(conn, RST);
+		conn_state(conn, TCP_CLOSED);
+		goto next_state;
+	}
+
+	if (th) {
+		size_t max_win;
+
+		conn->send_win = ntohs(th->th_win);
+
+#if IS_ENABLED(CONFIG_NET_TCP_MAX_SEND_WINDOW_SIZE)
+		if (CONFIG_NET_TCP_MAX_SEND_WINDOW_SIZE) {
+			max_win = CONFIG_NET_TCP_MAX_SEND_WINDOW_SIZE;
+		} else
+#endif
+		{
+			/* Adjust the window so that we do not run out of bufs
+			 * while waiting acks.
+			 */
+			max_win = (CONFIG_NET_BUF_TX_COUNT *
+				   CONFIG_NET_BUF_DATA_SIZE) / 3;
+		}
+
+		max_win = MAX(max_win, NET_IPV6_MTU);
+		if ((size_t)conn->send_win > max_win) {
+			NET_DBG("Lowering send window from %zd to %zd",
+				(size_t)conn->send_win, max_win);
+
+			conn->send_win = max_win;
+		}
+	}
+
+	if (FL(&fl, &, RST)) {
+		conn_state(conn, TCP_CLOSED);
+	}
+next_state:
+	len = pkt ? tcp_data_len(pkt) : 0;
+
+	switch (conn->state) {
+	case TCP_LISTEN:
+		if (FL(&fl, ==, SYN)) {
+			conn_ack(conn, th_seq(th) + 1); /* capture peer's isn */
+			tcp_out(conn, SYN | ACK);
+			conn_seq(conn, + 1);
+			next = TCP_SYN_RECEIVED;
+		} else {
+			tcp_out(conn, SYN);
+			conn_seq(conn, + 1);
+			next = TCP_SYN_SENT;
+		}
+		break;
+	case TCP_SYN_RECEIVED:
+		if (FL(&fl, &, ACK, th_ack(th) == conn->seq &&
+				th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			next = TCP_ESTABLISHED;
+			net_context_set_state(conn->context,
+					      NET_CONTEXT_CONNECTED);
+
+			if (conn->accepted_conn) {
+				conn->accepted_conn->accept_cb(
+					conn->context,
+					&conn->accepted_conn->context->remote,
+					sizeof(struct sockaddr), 0,
+					conn->accepted_conn->context);
+
+				/* Make sure the accept_cb is only called once.
+				 */
+				conn->accepted_conn = NULL;
+			}
+
+			if (len) {
+				if (tcp_data_get(conn, pkt) < 0) {
+					break;
+				}
+				conn_ack(conn, + len);
+				tcp_out(conn, ACK);
+			}
+		}
+		break;
+	case TCP_SYN_SENT:
+		/* if we are in SYN SENT and receive only a SYN without an
+		 * ACK , shouldn't we go to SYN RECEIVED state? See Figure
+		 * 6 of RFC 793
+		 */
+		if (FL(&fl, &, SYN | ACK, th && th_ack(th) == conn->seq)) {
+			tcp_send_timer_cancel(conn);
+			conn_ack(conn, th_seq(th) + 1);
+			if (len) {
+				if (tcp_data_get(conn, pkt) < 0) {
+					break;
+				}
+				conn_ack(conn, + len);
+			}
+			k_sem_give(&conn->connect_sem);
+			next = TCP_ESTABLISHED;
+			net_context_set_state(conn->context,
+					      NET_CONTEXT_CONNECTED);
+			tcp_out(conn, ACK);
+		}
+		break;
+	case TCP_ESTABLISHED:
+		/* full-close */
+		if (th && FL(&fl, ==, (FIN | ACK), th_seq(th) == conn->ack)) {
+			conn_ack(conn, + 1);
+			tcp_out(conn, FIN | ACK);
+			next = TCP_LAST_ACK;
+			break;
+		} else if (th && FL(&fl, ==, FIN, th_seq(th) == conn->ack)) {
+			conn_ack(conn, + 1);
+			tcp_out(conn, ACK);
+			next = TCP_CLOSE_WAIT;
+			break;
+		} else if (th && FL(&fl, ==, (FIN | ACK | PSH),
+				    th_seq(th) == conn->ack)) {
+			if (len) {
+				if (tcp_data_get(conn, pkt) < 0) {
+					break;
+				}
+			}
+
+			conn_ack(conn, + len + 1);
+			tcp_out(conn, FIN | ACK);
+			next = TCP_LAST_ACK;
+			break;
+		}
+
+		if (th && net_tcp_seq_cmp(th_ack(th), conn->seq) > 0) {
+			uint32_t len_acked = th_ack(th) - conn->seq;
+
+			NET_DBG("conn: %p len_acked=%u", conn, len_acked);
+
+			if ((conn->send_data_total < len_acked) ||
+					(tcp_pkt_pull(conn->send_data,
+						      len_acked) < 0)) {
+				NET_ERR("conn: %p, Invalid len_acked=%u "
+					"(total=%zu)", conn, len_acked,
+					conn->send_data_total);
+				tcp_out(conn, RST);
+				conn_state(conn, TCP_CLOSED);
+				break;
+			}
+
+			conn->send_data_total -= len_acked;
+			conn->unacked_len -= len_acked;
+			conn_seq(conn, + len_acked);
+
+			conn_send_data_dump(conn);
+
+			if (!k_delayed_work_remaining_get(&conn->send_data_timer)) {
+				NET_DBG("conn: %p, Missing a subscription "
+					"of the send_data queue timer", conn);
+				break;
+			}
+			conn->send_data_retries = 0;
+			k_delayed_work_cancel(&conn->send_data_timer);
+			if (conn->data_mode == TCP_DATA_MODE_RESEND) {
+				conn->unacked_len = 0;
+			}
+			conn->data_mode = TCP_DATA_MODE_SEND;
+
+			/* We are closing the connection, send a FIN to peer */
+			if (conn->in_close && conn->send_data_total == 0) {
+				tcp_send_timer_cancel(conn);
+				next = TCP_FIN_WAIT_1;
+
+				tcp_out(conn, FIN | ACK);
+				conn_seq(conn, + 1);
+				break;
+			}
+
+			ret = tcp_send_queued_data(conn);
+			if (ret < 0 && ret != -ENOBUFS) {
+				tcp_out(conn, RST);
+				conn_state(conn, TCP_CLOSED);
+				break;
+			}
+		}
+
+		if (th && len) {
+			if (th_seq(th) == conn->ack) {
+				if (tcp_data_get(conn, pkt) < 0) {
+					break;
+				}
+				conn_ack(conn, + len);
+				tcp_out(conn, ACK);
+			} else if (net_tcp_seq_greater(conn->ack, th_seq(th))) {
+				tcp_out(conn, ACK); /* peer has resent */
+			}
+		}
+		break;
+	case TCP_CLOSE_WAIT:
+		tcp_out(conn, FIN);
+		next = TCP_LAST_ACK;
+		break;
+	case TCP_LAST_ACK:
+		if (th && FL(&fl, ==, ACK, th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			next = TCP_CLOSED;
+		}
+		break;
+	case TCP_CLOSED:
+		tcp_conn_unref(conn);
+		break;
+	case TCP_FIN_WAIT_1:
+		if (th && FL(&fl, ==, (FIN | ACK), th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			conn_ack(conn, + 1);
+			tcp_out(conn, ACK);
+			next = TCP_TIME_WAIT;
+		} else if (th && FL(&fl, ==, FIN, th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			conn_ack(conn, + 1);
+			tcp_out(conn, ACK);
+			next = TCP_CLOSING;
+		} else if (th && FL(&fl, ==, ACK, th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			next = TCP_FIN_WAIT_2;
+		}
+		break;
+	case TCP_FIN_WAIT_2:
+		if (th && (FL(&fl, ==, FIN, th_seq(th) == conn->ack) ||
+			   FL(&fl, ==, FIN | ACK, th_seq(th) == conn->ack))) {
+			/* Received FIN on FIN_WAIT_2, so cancel the timer */
+			k_delayed_work_cancel(&conn->fin_timer);
+
+			conn_ack(conn, + 1);
+			tcp_out(conn, ACK);
+			next = TCP_TIME_WAIT;
+		}
+		break;
+	case TCP_CLOSING:
+		if (th && FL(&fl, ==, ACK, th_seq(th) == conn->ack)) {
+			tcp_send_timer_cancel(conn);
+			next = TCP_TIME_WAIT;
+		}
+		break;
+	case TCP_TIME_WAIT:
+		k_delayed_work_submit(&conn->timewait_timer,
+				      K_MSEC(CONFIG_NET_TCP_TIME_WAIT_DELAY));
+		break;
+	default:
+		NET_ASSERT(false, "%s is unimplemented",
+			   tcp_state_to_str(conn->state, true));
+	}
+
+	if (next) {
+		pkt = NULL;
+		th = NULL;
+		conn_state(conn, next);
+		next = 0;
+		goto next_state;
+	}
+
+	k_mutex_unlock(&conn->lock);
+}
+
+/* Active connection close: send FIN and go to FIN_WAIT_1 state */
+int net_tcp_put(struct net_context *context)
+{
+	struct tcp *conn = context->tcp;
+
+	if (!conn) {
+		return -ENOENT;
+	}
+
+	k_mutex_lock(&conn->lock, K_FOREVER);
+
+	NET_DBG("%s", conn ? log_strdup(tcp_conn_state(conn, NULL)) : "");
+	NET_DBG("context %p %s", context,
+		log_strdup(({ const char *state = net_context_state(context);
+					state ? state : "<unknown>"; })));
+
+	if (conn && conn->state == TCP_ESTABLISHED) {
+		/* Send all remaining data if possible. */
+		if (conn->send_data_total > 0) {
+			NET_DBG("conn %p pending %zu bytes", conn,
+				conn->send_data_total);
+			conn->in_close = true;
+
+			/* How long to wait until all the data has been sent?
+			 */
+			k_delayed_work_submit(&conn->send_data_timer,
+					      K_MSEC(tcp_rto));
+		} else {
+			int ret;
+
+			NET_DBG("TCP connection in active close, not "
+				"disposing yet (waiting %dms)", FIN_TIMEOUT_MS);
+			k_delayed_work_submit(&conn->fin_timer, FIN_TIMEOUT);
+
+			ret = tcp_out_ext(conn, FIN | ACK, NULL,
+				    conn->seq + conn->unacked_len);
+			if (ret == 0) {
+				conn_seq(conn, + 1);
+			}
+
+			conn_state(conn, TCP_FIN_WAIT_1);
+		}
+
+		/* Make sure we do not delete the connection yet until we have
+		 * sent the final ACK.
+		 */
+		net_context_ref(context);
+	}
+
+	k_mutex_unlock(&conn->lock);
+
+	net_context_unref(context);
+
+	return 0;
+}
+
+int net_tcp_listen(struct net_context *context)
+{
+	/* when created, tcp connections are in state TCP_LISTEN */
+	net_context_set_state(context, NET_CONTEXT_LISTENING);
+
+	return 0;
+}
+
+int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(delta);
+
+	return -EPROTONOSUPPORT;
+}
+
+/* net_context queues the outgoing data for the TCP connection */
+int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
+{
+	struct tcp *conn = context->tcp;
+	struct net_buf *orig_buf = NULL;
+	int ret = 0;
+	size_t len;
+
+	if (!conn || conn->state != TCP_ESTABLISHED) {
+		return -ENOTCONN;
+	}
+
+	k_mutex_lock(&conn->lock, K_FOREVER);
+
+	if (tcp_window_full(conn)) {
+		/* Trigger resend if the timer is not active */
+		if (!k_delayed_work_remaining_get(&conn->send_data_timer)) {
+			NET_DBG("Window full, trigger resend");
+			tcp_resend_data(&conn->send_data_timer.work);
+		}
+
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	len = net_pkt_get_len(pkt);
+
+	if (conn->send_data->buffer) {
+		orig_buf = net_buf_frag_last(conn->send_data->buffer);
+	}
+
+	net_pkt_append_buffer(conn->send_data, pkt->buffer);
+	conn->send_data_total += len;
+	NET_DBG("conn: %p Queued %zu bytes (total %zu)", conn, len,
+		conn->send_data_total);
+	pkt->buffer = NULL;
+
+	ret = tcp_send_queued_data(conn);
+	if (ret < 0 && ret != -ENOBUFS) {
+		tcp_conn_unref(conn);
+		goto out;
+	}
+
+	if (ret == -ENOBUFS) {
+		/* Restore the original data so that we do not resend the pkt
+		 * data multiple times.
+		 */
+		conn->send_data_total -= len;
+
+		if (orig_buf) {
+			pkt->buffer = orig_buf->frags;
+			orig_buf->frags = NULL;
+		} else {
+			pkt->buffer = conn->send_data->buffer;
+			conn->send_data->buffer = NULL;
+		}
+	} else {
+		/* We should not free the pkt if there was an error. It will be
+		 * freed in net_context.c:context_sendto()
+		 */
+		tcp_pkt_unref(pkt);
+	}
+out:
+	k_mutex_unlock(&conn->lock);
+
+	return ret;
+}
+
+/* net context is about to send out queued data - inform caller only */
+int net_tcp_send_data(struct net_context *context, net_context_send_cb_t cb,
+		      void *user_data)
+{
+	if (cb) {
+		cb(context, 0, user_data);
+	}
+
+	return 0;
+}
+
+/* When connect() is called on a TCP socket, register the socket for incoming
+ * traffic with net context and give the TCP packet receiving function, which
+ * in turn will call tcp_in() to deliver the TCP packet to the stack
+ */
+int net_tcp_connect(struct net_context *context,
+		    const struct sockaddr *remote_addr,
+		    struct sockaddr *local_addr,
+		    uint16_t remote_port, uint16_t local_port,
+		    k_timeout_t timeout, net_context_connect_cb_t cb,
+		    void *user_data)
+{
+	struct tcp *conn;
+	int ret = 0;
+
+	NET_DBG("context: %p, local: %s, remote: %s", context,
+		log_strdup(net_sprint_addr(
+			    local_addr->sa_family,
+			    (const void *)&net_sin(local_addr)->sin_addr)),
+		log_strdup(net_sprint_addr(
+			    remote_addr->sa_family,
+			    (const void *)&net_sin(remote_addr)->sin_addr)));
+
+	conn = context->tcp;
+	conn->iface = net_context_get_iface(context);
+
+	switch (net_context_get_family(context)) {
+		const struct in_addr *ip4;
+		const struct in6_addr *ip6;
+
+	case AF_INET:
+		memset(&conn->src, 0, sizeof(struct sockaddr_in));
+		memset(&conn->dst, 0, sizeof(struct sockaddr_in));
+
+		conn->src.sa.sa_family = AF_INET;
+		conn->dst.sa.sa_family = AF_INET;
+
+		conn->dst.sin.sin_port = remote_port;
+		conn->src.sin.sin_port = local_port;
+
+		/* we have to select the source address here as
+		 * net_context_create_ipv4_new() is not called in the packet
+		 * output chain
+		 */
+		ip4 = net_if_ipv4_select_src_addr(
+			net_context_get_iface(context),
+			&net_sin(remote_addr)->sin_addr);
+		conn->src.sin.sin_addr = *ip4;
+		net_ipaddr_copy(&conn->dst.sin.sin_addr,
+				&net_sin(remote_addr)->sin_addr);
+		break;
+
+	case AF_INET6:
+		memset(&conn->src, 0, sizeof(struct sockaddr_in6));
+		memset(&conn->dst, 0, sizeof(struct sockaddr_in6));
+
+		conn->src.sin6.sin6_family = AF_INET6;
+		conn->dst.sin6.sin6_family = AF_INET6;
+
+		conn->dst.sin6.sin6_port = remote_port;
+		conn->src.sin6.sin6_port = local_port;
+
+		ip6 = net_if_ipv6_select_src_addr(
+					net_context_get_iface(context),
+					&net_sin6(remote_addr)->sin6_addr);
+		conn->src.sin6.sin6_addr = *ip6;
+		net_ipaddr_copy(&conn->dst.sin6.sin6_addr,
+				&net_sin6(remote_addr)->sin6_addr);
+		break;
+
+	default:
+		ret = -EPROTONOSUPPORT;
+	}
+
+	NET_DBG("conn: %p src: %s, dst: %s", conn,
+		log_strdup(net_sprint_addr(conn->src.sa.sa_family,
+				(const void *)&conn->src.sin.sin_addr)),
+		log_strdup(net_sprint_addr(conn->dst.sa.sa_family,
+				(const void *)&conn->dst.sin.sin_addr)));
+
+	net_context_set_state(context, NET_CONTEXT_CONNECTING);
+
+	ret = net_conn_register(net_context_get_ip_proto(context),
+				net_context_get_family(context),
+				remote_addr, local_addr,
+				ntohs(remote_port), ntohs(local_port),
+				tcp_recv, context,
+				&context->conn_handler);
+	if (ret < 0) {
+		goto out;
+	}
+
+	/* Input of a (nonexistent) packet with no flags set will cause
+	 * a TCP connection to be established
+	 */
+	tcp_in(conn, NULL);
+
+	if (!IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)) {
+		conn->in_connect = true;
+
+		if (k_sem_take(&conn->connect_sem, timeout) != 0 &&
+		    conn->state != TCP_ESTABLISHED) {
+			conn->in_connect = false;
+			tcp_conn_unref(conn);
+			ret = -ETIMEDOUT;
+			goto out;
+		}
+		conn->in_connect = false;
+	}
+ out:
+	NET_DBG("conn: %p, ret=%d", conn, ret);
+
+	return ret;
+}
+
+int net_tcp_accept(struct net_context *context, net_tcp_accept_cb_t cb,
+		   void *user_data)
+{
+	struct tcp *conn = context->tcp;
+	struct sockaddr local_addr = { };
+	uint16_t local_port, remote_port;
+
+	if (!conn) {
+		return -EINVAL;
+	}
+
+	NET_DBG("context: %p, tcp: %p, cb: %p", context, conn, cb);
+
+	if (conn->state != TCP_LISTEN) {
+		return -EINVAL;
+	}
+
+	conn->accept_cb = cb;
+	local_addr.sa_family = net_context_get_family(context);
+
+	switch (local_addr.sa_family) {
+		struct sockaddr_in *in;
+		struct sockaddr_in6 *in6;
+
+	case AF_INET:
+		in = (struct sockaddr_in *)&local_addr;
+
+		if (net_sin_ptr(&context->local)->sin_addr) {
+			net_ipaddr_copy(&in->sin_addr,
+					net_sin_ptr(&context->local)->sin_addr);
+		}
+
+		in->sin_port =
+			net_sin((struct sockaddr *)&context->local)->sin_port;
+		local_port = ntohs(in->sin_port);
+		remote_port = ntohs(net_sin(&context->remote)->sin_port);
+
+		break;
+
+	case AF_INET6:
+		in6 = (struct sockaddr_in6 *)&local_addr;
+
+		if (net_sin6_ptr(&context->local)->sin6_addr) {
+			net_ipaddr_copy(&in6->sin6_addr,
+				net_sin6_ptr(&context->local)->sin6_addr);
+		}
+
+		in6->sin6_port =
+			net_sin6((struct sockaddr *)&context->local)->sin6_port;
+		local_port = ntohs(in6->sin6_port);
+		remote_port = ntohs(net_sin6(&context->remote)->sin6_port);
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	context->user_data = user_data;
+
+	/* Remove the temporary connection handler and register
+	 * a proper now as we have an established connection.
+	 */
+	net_conn_unregister(context->conn_handler);
+
+	return net_conn_register(net_context_get_ip_proto(context),
+				 local_addr.sa_family,
+				 context->flags & NET_CONTEXT_REMOTE_ADDR_SET ?
+				 &context->remote : NULL,
+				 &local_addr,
+				 remote_port, local_port,
+				 tcp_recv, context,
+				 &context->conn_handler);
+}
+
+int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb,
+		 void *user_data)
+{
+	struct tcp *conn = context->tcp;
+
+	NET_DBG("context: %p, cb: %p, user_data: %p", context, cb, user_data);
+
+	context->recv_cb = cb;
+
+	if (conn) {
+		conn->recv_user_data = user_data;
+	}
+
+	return 0;
+}
+
+int net_tcp_finalize(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+	struct net_tcp_hdr *tcp_hdr;
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access);
+	if (!tcp_hdr) {
+		return -ENOBUFS;
+	}
+
+	tcp_hdr->chksum = 0U;
+
+	if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) {
+		tcp_hdr->chksum = net_calc_chksum_tcp(pkt);
+	}
+
+	return net_pkt_set_data(pkt, &tcp_access);
+}
+
+struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *tcp_access)
+{
+	struct net_tcp_hdr *tcp_hdr;
+
+	if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) &&
+			net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) &&
+			net_calc_chksum_tcp(pkt) != 0U) {
+		NET_DBG("DROP: checksum mismatch");
+		goto drop;
+	}
+
+	tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, tcp_access);
+	if (tcp_hdr && !net_pkt_set_data(pkt, tcp_access)) {
+		return tcp_hdr;
+	}
+
+drop:
+	net_stats_update_tcp_seg_chkerr(net_pkt_iface(pkt));
+	return NULL;
+}
+
+#if defined(CONFIG_NET_TEST_PROTOCOL)
+static enum net_verdict tcp_input(struct net_conn *net_conn,
+				  struct net_pkt *pkt,
+				  union net_ip_header *ip,
+				  union net_proto_header *proto,
+				  void *user_data)
+{
+	struct tcphdr *th = th_get(pkt);
+
+	if (th) {
+		struct tcp *conn = tcp_conn_search(pkt);
+
+		if (conn == NULL && SYN == th->th_flags) {
+			struct net_context *context =
+				tcp_calloc(1, sizeof(struct net_context));
+			net_tcp_get(context);
+			net_context_set_family(context, net_pkt_family(pkt));
+			conn = context->tcp;
+			tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC);
+			tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST);
+			/* Make an extra reference, the sanity check suite
+			 * will delete the connection explicitly
+			 */
+			tcp_conn_ref(conn);
+		}
+
+		if (conn) {
+			conn->iface = pkt->iface;
+			tcp_in(conn, pkt);
+		}
+	}
+
+	return NET_DROP;
+}
+
+static size_t tp_tcp_recv_cb(struct tcp *conn, struct net_pkt *pkt)
+{
+	ssize_t len = tcp_data_len(pkt);
+	struct net_pkt *up = tcp_pkt_clone(pkt);
+
+	NET_DBG("pkt: %p, len: %zu", pkt, net_pkt_get_len(pkt));
+
+	net_pkt_cursor_init(up);
+	net_pkt_set_overwrite(up, true);
+
+	net_pkt_pull(up, net_pkt_get_len(up) - len);
+
+	net_tcp_queue_data(conn->context, up);
+
+	return len;
+}
+
+static ssize_t tp_tcp_recv(int fd, void *buf, size_t len, int flags)
+{
+	return 0;
+}
+
+static void tp_init(struct tcp *conn, struct tp *tp)
+{
+	struct tp out = {
+		.msg = "",
+		.status = "",
+		.state = tcp_state_to_str(conn->state, true),
+		.seq = conn->seq,
+		.ack = conn->ack,
+		.rcv = "",
+		.data = "",
+		.op = "",
+	};
+
+	*tp = out;
+}
+
+static void tcp_to_json(struct tcp *conn, void *data, size_t *data_len)
+{
+	struct tp tp;
+
+	tp_init(conn, &tp);
+
+	tp_encode(&tp, data, data_len);
+}
+
+enum net_verdict tp_input(struct net_conn *net_conn,
+			  struct net_pkt *pkt,
+			  union net_ip_header *ip_hdr,
+			  union net_proto_header *proto,
+			  void *user_data)
+{
+	struct net_udp_hdr *uh = net_udp_get_hdr(pkt, NULL);
+	size_t data_len = ntohs(uh->len) - sizeof(*uh);
+	struct tcp *conn = tcp_conn_search(pkt);
+	size_t json_len = 0;
+	struct tp *tp;
+	struct tp_new *tp_new;
+	enum tp_type type;
+	bool responded = false;
+	static char buf[512];
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+		     net_pkt_ip_opts_len(pkt) + sizeof(*uh));
+	net_pkt_read(pkt, buf, data_len);
+	buf[data_len] = '\0';
+	data_len += 1;
+
+	type = json_decode_msg(buf, data_len);
+
+	data_len = ntohs(uh->len) - sizeof(*uh);
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+		     net_pkt_ip_opts_len(pkt) + sizeof(*uh));
+	net_pkt_read(pkt, buf, data_len);
+	buf[data_len] = '\0';
+	data_len += 1;
+
+	switch (type) {
+	case TP_CONFIG_REQUEST:
+		tp_new = json_to_tp_new(buf, data_len);
+		break;
+	default:
+		tp = json_to_tp(buf, data_len);
+		break;
+	}
+
+	switch (type) {
+	case TP_COMMAND:
+		if (is("CONNECT", tp->op)) {
+			tp_output(pkt->family, pkt->iface, buf, 1);
+			responded = true;
+			{
+				struct net_context *context = tcp_calloc(1,
+						sizeof(struct net_context));
+				net_tcp_get(context);
+				net_context_set_family(context,
+						       net_pkt_family(pkt));
+				conn = context->tcp;
+				tcp_endpoint_set(&conn->dst, pkt, TCP_EP_SRC);
+				tcp_endpoint_set(&conn->src, pkt, TCP_EP_DST);
+				conn->iface = pkt->iface;
+				tcp_conn_ref(conn);
+			}
+			conn->seq = tp->seq;
+			tcp_in(conn, NULL);
+		}
+		if (is("CLOSE", tp->op)) {
+			tp_trace = false;
+			{
+				struct net_context *context;
+
+				conn = (void *)sys_slist_peek_head(&tcp_conns);
+				context = conn->context;
+				while (tcp_conn_unref(conn))
+					;
+				tcp_free(context);
+			}
+			tp_mem_stat();
+			tp_nbuf_stat();
+			tp_pkt_stat();
+			tp_seq_stat();
+		}
+		if (is("CLOSE2", tp->op)) {
+			struct tcp *conn =
+				(void *)sys_slist_peek_head(&tcp_conns);
+			net_tcp_put(conn->context);
+		}
+		if (is("RECV", tp->op)) {
+#define HEXSTR_SIZE 64
+			char hexstr[HEXSTR_SIZE];
+			ssize_t len = tp_tcp_recv(0, buf, sizeof(buf), 0);
+
+			tp_init(conn, tp);
+			bin2hex(buf, len, hexstr, HEXSTR_SIZE);
+			tp->data = hexstr;
+			NET_DBG("%zd = tcp_recv(\"%s\")", len, tp->data);
+			json_len = sizeof(buf);
+			tp_encode(tp, buf, &json_len);
+		}
+		if (is("SEND", tp->op)) {
+			ssize_t len = tp_str_to_hex(buf, sizeof(buf), tp->data);
+			struct tcp *conn =
+				(void *)sys_slist_peek_head(&tcp_conns);
+
+			tp_output(pkt->family, pkt->iface, buf, 1);
+			responded = true;
+			NET_DBG("tcp_send(\"%s\")", tp->data);
+			{
+				struct net_pkt *data_pkt;
+
+				data_pkt = tcp_pkt_alloc(conn, len);
+				net_pkt_write(data_pkt, buf, len);
+				net_pkt_cursor_init(data_pkt);
+				net_tcp_queue_data(conn->context, data_pkt);
+			}
+		}
+		break;
+	case TP_CONFIG_REQUEST:
+		tp_new_find_and_apply(tp_new, "tcp_rto", &tcp_rto, TP_INT);
+		tp_new_find_and_apply(tp_new, "tcp_retries", &tcp_retries,
+					TP_INT);
+		tp_new_find_and_apply(tp_new, "tcp_window", &tcp_window,
+					TP_INT);
+		tp_new_find_and_apply(tp_new, "tp_trace", &tp_trace, TP_BOOL);
+		break;
+	case TP_INTROSPECT_REQUEST:
+		json_len = sizeof(buf);
+		conn = (void *)sys_slist_peek_head(&tcp_conns);
+		tcp_to_json(conn, buf, &json_len);
+		break;
+	case TP_DEBUG_STOP: case TP_DEBUG_CONTINUE:
+		tp_state = tp->type;
+		break;
+	default:
+		NET_ASSERT(false, "Unimplemented tp command: %s", tp->msg);
+	}
+
+	if (json_len) {
+		tp_output(pkt->family, pkt->iface, buf, json_len);
+	} else if ((TP_CONFIG_REQUEST == type || TP_COMMAND == type)
+			&& responded == false) {
+		tp_output(pkt->family, pkt->iface, buf, 1);
+	}
+
+	return NET_DROP;
+}
+
+static void test_cb_register(sa_family_t family, uint8_t proto, uint16_t remote_port,
+			     uint16_t local_port, net_conn_cb_t cb)
+{
+	struct net_conn_handle *conn_handle = NULL;
+	const struct sockaddr addr = { .sa_family = family, };
+
+	int ret = net_conn_register(proto,
+				    family,
+				    &addr,	/* remote address */
+				    &addr,	/* local address */
+				    local_port,
+				    remote_port,
+				    cb,
+				    NULL,	/* user_data */
+				    &conn_handle);
+	if (ret < 0) {
+		NET_ERR("net_conn_register(): %d", ret);
+	}
+}
+#endif /* CONFIG_NET_TEST_PROTOCOL */
+
+void net_tcp_init(void)
+{
+#if defined(CONFIG_NET_TEST_PROTOCOL)
+	/* Register inputs for TTCN-3 based TCP2 sanity check */
+	test_cb_register(AF_INET,  IPPROTO_TCP, 4242, 4242, tcp_input);
+	test_cb_register(AF_INET6, IPPROTO_TCP, 4242, 4242, tcp_input);
+	test_cb_register(AF_INET,  IPPROTO_UDP, 4242, 4242, tp_input);
+	test_cb_register(AF_INET6, IPPROTO_UDP, 4242, 4242, tp_input);
+
+	tcp_recv_cb = tp_tcp_recv_cb;
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2_priv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2_priv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp2_priv.h	(working copy)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2018-2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "tp.h"
+
+#define is(_a, _b) (strcmp((_a), (_b)) == 0)
+
+#ifndef MIN3
+#define MIN3(_a, _b, _c) MIN((_a), MIN((_b), (_c)))
+#endif
+
+#define th_seq(_x) ntohl(UNALIGNED_GET(&(_x)->th_seq))
+#define th_ack(_x) ntohl(UNALIGNED_GET(&(_x)->th_ack))
+
+#define tcp_slist(_slist, _op, _type, _link)				\
+({									\
+	sys_snode_t *_node = sys_slist_##_op(_slist);			\
+									\
+	_type * _x = _node ? CONTAINER_OF(_node, _type, _link) : NULL;	\
+									\
+	_x;								\
+})
+
+#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
+#define tcp_malloc(_size) \
+	tp_malloc(_size, tp_basename(__FILE__), __LINE__, __func__)
+#define tcp_calloc(_nmemb, _size) \
+	tp_calloc(_nmemb, _size, tp_basename(__FILE__), __LINE__, __func__)
+#define tcp_free(_ptr) tp_free(_ptr, tp_basename(__FILE__), __LINE__, __func__)
+#else
+#define tcp_malloc(_size) k_malloc(_size)
+#define tcp_calloc(_nmemb, _size) k_calloc(_nmemb, _size)
+#define tcp_free(_ptr) k_free(_ptr)
+#endif
+
+#define TCP_PKT_ALLOC_TIMEOUT K_MSEC(100)
+
+#if defined(CONFIG_NET_TEST_PROTOCOL)
+#define tcp_pkt_clone(_pkt) tp_pkt_clone(_pkt, tp_basename(__FILE__), __LINE__)
+#define tcp_pkt_unref(_pkt) tp_pkt_unref(_pkt, tp_basename(__FILE__), __LINE__)
+#else
+#define tcp_pkt_clone(_pkt) net_pkt_clone(_pkt, TCP_PKT_ALLOC_TIMEOUT)
+#define tcp_pkt_unref(_pkt) net_pkt_unref(_pkt)
+#define tp_pkt_alloc(args...)
+#endif
+
+#define tcp_pkt_ref(_pkt) net_pkt_ref(_pkt)
+#define tcp_pkt_alloc(_conn, _len)					\
+({									\
+	struct net_pkt *_pkt;						\
+									\
+	if ((_len) > 0) {						\
+		_pkt = net_pkt_alloc_with_buffer(			\
+			(_conn)->iface,					\
+			(_len),						\
+			net_context_get_family((_conn)->context),	\
+			IPPROTO_TCP,					\
+			TCP_PKT_ALLOC_TIMEOUT);				\
+	} else {							\
+		_pkt = net_pkt_alloc(TCP_PKT_ALLOC_TIMEOUT);		\
+	}								\
+									\
+	tp_pkt_alloc(_pkt, tp_basename(__FILE__), __LINE__);		\
+									\
+	_pkt;								\
+})
+
+
+#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
+#define conn_seq(_conn, _req) \
+	tp_seq_track(TP_SEQ, &(_conn)->seq, (_req), tp_basename(__FILE__), \
+			__LINE__, __func__)
+#define conn_ack(_conn, _req) \
+	tp_seq_track(TP_ACK, &(_conn)->ack, (_req), tp_basename(__FILE__), \
+			__LINE__, __func__)
+#else
+#define conn_seq(_conn, _req) (_conn)->seq += (_req)
+#define conn_ack(_conn, _req) (_conn)->ack += (_req)
+#endif
+
+#define conn_mss(_conn)					\
+	((_conn)->recv_options.mss_found ?		\
+	 (_conn)->recv_options.mss : NET_IPV6_MTU)
+
+#define conn_state(_conn, _s)						\
+({									\
+	NET_DBG("%s->%s",						\
+		tcp_state_to_str((_conn)->state, false),		\
+		tcp_state_to_str((_s), false));				\
+	(_conn)->state = _s;						\
+})
+
+#define conn_send_data_dump(_conn)					\
+({									\
+	NET_DBG("conn: %p total=%zd, unacked_len=%d, "			\
+		"send_win=%hu, mss=%hu",				\
+		(_conn), net_pkt_get_len((_conn)->send_data),		\
+		conn->unacked_len, conn->send_win,			\
+		conn_mss((_conn)));					\
+	NET_DBG("conn: %p send_data_timer=%hu, send_data_retries=%hu",	\
+		(_conn),						\
+		(bool)k_delayed_work_remaining_get(&(_conn)->send_data_timer),\
+		(_conn)->send_data_retries);				\
+})
+
+#define TCPOPT_END	0
+#define TCPOPT_NOP	1
+#define TCPOPT_MAXSEG	2
+#define TCPOPT_WINDOW	3
+
+enum pkt_addr {
+	TCP_EP_SRC = 1,
+	TCP_EP_DST = 0
+};
+
+struct tcphdr {
+	uint16_t th_sport;
+	uint16_t th_dport;
+	uint32_t th_seq;
+	uint32_t th_ack;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t th_x2:4;	/* unused */
+	uint8_t th_off:4;	/* data offset */
+#endif
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t th_off:4;
+	uint8_t th_x2:4;
+#endif
+	uint8_t th_flags;
+	uint16_t th_win;
+	uint16_t th_sum;
+	uint16_t th_urp;
+};
+
+enum th_flags {
+	FIN = 1,
+	SYN = 1 << 1,
+	RST = 1 << 2,
+	PSH = 1 << 3,
+	ACK = 1 << 4,
+	URG = 1 << 5,
+	ECN = 1 << 6,
+	CWR = 1 << 7,
+};
+
+enum tcp_state {
+	TCP_LISTEN = 1,
+	TCP_SYN_SENT,
+	TCP_SYN_RECEIVED,
+	TCP_ESTABLISHED,
+	TCP_FIN_WAIT_1,
+	TCP_FIN_WAIT_2,
+	TCP_CLOSE_WAIT,
+	TCP_CLOSING,
+	TCP_LAST_ACK,
+	TCP_TIME_WAIT,
+	TCP_CLOSED
+};
+
+enum tcp_data_mode {
+	TCP_DATA_MODE_SEND = 0,
+	TCP_DATA_MODE_RESEND = 1
+};
+
+union tcp_endpoint {
+	struct sockaddr sa;
+	struct sockaddr_in sin;
+	struct sockaddr_in6 sin6;
+};
+
+struct tcp_options {
+	uint16_t mss;
+	uint16_t window;
+	bool mss_found : 1;
+	bool wnd_found : 1;
+};
+
+struct tcp { /* TCP connection */
+	sys_snode_t next;
+	struct net_context *context;
+	struct net_pkt *send_data;
+	struct net_if *iface;
+	void *recv_user_data;
+	sys_slist_t send_queue;
+	union {
+		net_tcp_accept_cb_t accept_cb;
+		struct tcp *accepted_conn;
+	};
+	struct k_mutex lock;
+	struct k_sem connect_sem; /* semaphore for blocking connect */
+	struct tcp_options recv_options;
+	struct k_delayed_work send_timer;
+	struct k_delayed_work send_data_timer;
+	struct k_delayed_work timewait_timer;
+	struct k_delayed_work fin_timer;
+	union tcp_endpoint src;
+	union tcp_endpoint dst;
+	size_t send_data_total;
+	size_t send_retries;
+	int unacked_len;
+	atomic_t ref_count;
+	enum tcp_state state;
+	enum tcp_data_mode data_mode;
+	uint32_t seq;
+	uint32_t ack;
+	uint16_t recv_win;
+	uint16_t send_win;
+	uint8_t send_data_retries;
+	bool in_retransmission : 1;
+	bool in_connect : 1;
+	bool in_close : 1;
+};
+
+#define _flags(_fl, _op, _mask, _cond)					\
+({									\
+	bool result = false;						\
+									\
+	if (UNALIGNED_GET(_fl) && (_cond) &&				\
+	    (UNALIGNED_GET(_fl) _op(_mask))) {				\
+		UNALIGNED_PUT(UNALIGNED_GET(_fl) & ~(_mask), _fl);	\
+		result = true;						\
+	}								\
+									\
+	result;								\
+})
+
+#define FL(_fl, _op, _mask, _args...)					\
+	_flags(_fl, _op, _mask, strlen("" #_args) ? _args : true)
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tcp_internal.h	(working copy)
@@ -0,0 +1,799 @@
+/** @file
+ @brief TCP data handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __TCP_INTERNAL_H
+#define __TCP_INTERNAL_H
+
+#include <zephyr/types.h>
+#include <random/rand32.h>
+
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_context.h>
+
+#include "connection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Is this TCP context/socket used or not */
+#define NET_TCP_IN_USE BIT(0)
+
+/* BIT(1), BIT(2) are unused and available */
+
+/** Is the socket shutdown for read/write */
+#define NET_TCP_IS_SHUTDOWN BIT(3)
+
+/** A retransmitted packet has been sent and not yet ack'd */
+#define NET_TCP_RETRYING BIT(4)
+
+/** MSS option has been set already */
+#define NET_TCP_RECV_MSS_SET BIT(5)
+
+/*
+ * TCP connection states
+ */
+enum net_tcp_state {
+	NET_TCP_CLOSED = 0,
+	NET_TCP_LISTEN,
+	NET_TCP_SYN_SENT,
+	NET_TCP_SYN_RCVD,
+	NET_TCP_ESTABLISHED,
+	NET_TCP_CLOSE_WAIT,
+	NET_TCP_LAST_ACK,
+	NET_TCP_FIN_WAIT_1,
+	NET_TCP_FIN_WAIT_2,
+	NET_TCP_TIME_WAIT,
+	NET_TCP_CLOSING,
+};
+
+/* TCP packet types */
+#define NET_TCP_FIN 0x01
+#define NET_TCP_SYN 0x02
+#define NET_TCP_RST 0x04
+#define NET_TCP_PSH 0x08
+#define NET_TCP_ACK 0x10
+#define NET_TCP_URG 0x20
+#define NET_TCP_CTL 0x3f
+
+#define NET_TCP_FLAGS(hdr) (hdr->flags & NET_TCP_CTL)
+
+/* Length of TCP header, including options */
+/* "offset": 4-bit field in high nibble, units of dwords */
+#define NET_TCP_HDR_LEN(hdr) (4 * ((hdr)->offset >> 4))
+
+/* RFC 1122 4.2.2.6 "If an MSS option is not received at connection
+ * setup, TCP MUST assume a default send MSS of 536"
+ */
+#define NET_TCP_DEFAULT_MSS   536
+
+/* TCP max window size */
+#define NET_TCP_MAX_WIN   (4 * 1024)
+
+/* Maximal value of the sequence number */
+#define NET_TCP_MAX_SEQ   0xffffffff
+
+#define NET_TCP_MAX_OPT_SIZE  8
+
+/* TCP Option codes */
+#define NET_TCP_END_OPT          0
+#define NET_TCP_NOP_OPT          1
+#define NET_TCP_MSS_OPT          2
+#define NET_TCP_WINDOW_SCALE_OPT 3
+
+/* TCP Option sizes */
+#define NET_TCP_END_SIZE          1
+#define NET_TCP_NOP_SIZE          1
+#define NET_TCP_MSS_SIZE          4
+#define NET_TCP_WINDOW_SCALE_SIZE 3
+
+/** Parsed TCP option values for net_tcp_parse_opts()  */
+struct net_tcp_options {
+	uint16_t mss;
+};
+
+/* Max received bytes to buffer internally */
+#define NET_TCP_BUF_MAX_LEN 1280
+
+/* Max segment lifetime, in seconds */
+#define NET_TCP_MAX_SEG_LIFETIME 60
+
+struct net_context;
+
+struct net_tcp {
+	/** Network context back pointer. */
+	struct net_context *context;
+
+	/** Cookie pointer passed to net_context_recv() */
+	void *recv_user_data;
+
+	/** ACK message timer */
+	struct k_delayed_work ack_timer;
+
+	/** Timer for doing active close in case the peer FIN is lost. */
+	struct k_delayed_work fin_timer;
+
+	/** Retransmit timer */
+	struct k_delayed_work retry_timer;
+
+	/** TIME_WAIT timer */
+	struct k_delayed_work timewait_timer;
+
+	/** List pointer used for TCP retransmit buffering */
+	sys_slist_t sent_list;
+
+	/** Current sequence number. */
+	uint32_t send_seq;
+
+	/** Acknowledgment number to send in next packet. */
+	uint32_t send_ack;
+
+	/** Last ACK value sent */
+	uint32_t sent_ack;
+
+	/** Accept callback to be called when the connection has been
+	 * established.
+	 */
+	net_tcp_accept_cb_t accept_cb;
+
+	/**
+	 * Semaphore to signal TCP connection completion
+	 */
+	struct k_sem connect_wait;
+
+	/**
+	 * Current TCP receive window for our side
+	 */
+	uint16_t recv_wnd;
+
+	/**
+	 * Send MSS for the peer
+	 */
+	uint16_t send_mss;
+
+	/** Current retransmit period */
+	uint32_t retry_timeout_shift : 5;
+	/** Flags for the TCP */
+	uint32_t flags : 8;
+	/** Current TCP state */
+	uint32_t state : 4;
+	/* An outbound FIN packet has been sent */
+	uint32_t fin_sent : 1;
+	/* An inbound FIN packet has been received */
+	uint32_t fin_rcvd : 1;
+	/** Remaining bits in this uint32_t */
+	uint32_t _padding : 13;
+};
+
+typedef void (*net_tcp_cb_t)(struct net_tcp *tcp, void *user_data);
+
+static inline bool net_tcp_is_used(struct net_tcp *tcp)
+{
+	NET_ASSERT(tcp);
+
+	return tcp->flags & NET_TCP_IN_USE;
+}
+
+/**
+ * @brief Register a callback to be called when TCP packet
+ * is received corresponding to received packet.
+ *
+ * @param family Protocol family
+ * @param remote_addr Remote address of the connection end point.
+ * @param local_addr Local address of the connection end point.
+ * @param remote_port Remote port of the connection end point.
+ * @param local_port Local port of the connection end point.
+ * @param cb Callback to be called
+ * @param user_data User data supplied by caller.
+ * @param handle TCP handle that can be used when unregistering
+ *
+ * @return Return 0 if the registration succeed, <0 otherwise.
+ */
+static inline int net_tcp_register(uint8_t family,
+				   const struct sockaddr *remote_addr,
+				   const struct sockaddr *local_addr,
+				   uint16_t remote_port,
+				   uint16_t local_port,
+				   net_conn_cb_t cb,
+				   void *user_data,
+				   struct net_conn_handle **handle)
+{
+	return net_conn_register(IPPROTO_TCP, family, remote_addr, local_addr,
+				 remote_port, local_port, cb, user_data,
+				 handle);
+}
+
+/**
+ * @brief Unregister TCP handler.
+ *
+ * @param handle Handle from registering.
+ *
+ * @return Return 0 if the unregistration succeed, <0 otherwise.
+ */
+static inline int net_tcp_unregister(struct net_conn_handle *handle)
+{
+	return net_conn_unregister(handle);
+}
+
+/*
+ * @brief Generate initial TCP sequence number
+ *
+ * @return Return a random TCP sequence number
+ */
+static inline uint32_t tcp_init_isn(void)
+{
+	/* Randomise initial seq number */
+	return sys_rand32_get();
+}
+
+const char *net_tcp_state_str(enum net_tcp_state state);
+
+#if defined(CONFIG_NET_NATIVE_TCP)
+void net_tcp_change_state(struct net_tcp *tcp, enum net_tcp_state new_state);
+#else
+#define net_tcp_change_state(...)
+#endif
+
+/**
+ * @brief Allocate TCP connection context.
+ *
+ * @param context Pointer to net_context that is tied to this TCP
+ * context.
+ *
+ * @return Pointer TCP connection context. NULL if no available
+ * context can be found.
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+struct net_tcp *net_tcp_alloc(struct net_context *context);
+#else
+static inline struct net_tcp *net_tcp_alloc(struct net_context *context)
+{
+	ARG_UNUSED(context);
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Release TCP connection context.
+ *
+ * @param tcp Pointer to net_tcp context.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_release(struct net_tcp *tcp);
+#else
+static inline int net_tcp_release(struct net_tcp *tcp)
+{
+	ARG_UNUSED(tcp);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Send a TCP segment without any data. The returned buffer
+ * is a ready made packet that can be sent via net_send_data()
+ * function.
+ *
+ * @param tcp TCP context
+ * @param flags TCP flags
+ * @param options Pointer TCP options, NULL if no options.
+ * @param optlen Length of the options.
+ * @param local Source address, or NULL to use the local address of
+ *        the TCP context
+ * @param remote Peer address
+ * @param send_pkt Full IP + TCP header that is to be sent.
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_prepare_segment(struct net_tcp *tcp, uint8_t flags,
+			    void *options, size_t optlen,
+			    const struct sockaddr_ptr *local,
+			    const struct sockaddr *remote,
+			    struct net_pkt **send_pkt);
+#else
+static inline int net_tcp_prepare_segment(struct net_tcp *tcp, uint8_t flags,
+					  void *options, size_t optlen,
+					  const struct sockaddr_ptr *local,
+					  const struct sockaddr *remote,
+					  struct net_pkt **send_pkt)
+{
+	ARG_UNUSED(tcp);
+	ARG_UNUSED(flags);
+	ARG_UNUSED(options);
+	ARG_UNUSED(optlen);
+	ARG_UNUSED(local);
+	ARG_UNUSED(remote);
+	ARG_UNUSED(send_pkt);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Prepare a TCP ACK message that can be send to peer.
+ *
+ * @param tcp TCP context
+ * @param remote Peer address
+ * @param pkt Network buffer
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_prepare_ack(struct net_tcp *tcp, const struct sockaddr *remote,
+			struct net_pkt **pkt);
+#else
+static inline int net_tcp_prepare_ack(struct net_tcp *tcp,
+				      const struct sockaddr *remote,
+				      struct net_pkt **pkt)
+{
+	ARG_UNUSED(tcp);
+	ARG_UNUSED(remote);
+	ARG_UNUSED(pkt);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Prepare a TCP RST message that can be send to peer.
+ *
+ * @param tcp TCP context
+ * @param local Source address
+ * @param remote Peer address
+ * @param pkt Network buffer
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_prepare_reset(struct net_tcp *tcp,
+			  const struct sockaddr *local,
+			  const struct sockaddr *remote,
+			  struct net_pkt **pkt);
+#else
+static inline int net_tcp_prepare_reset(struct net_tcp *tcp,
+					const struct sockaddr *remote,
+					struct net_pkt **pkt)
+{
+	ARG_UNUSED(tcp);
+	ARG_UNUSED(remote);
+	ARG_UNUSED(pkt);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Go through all the TCP connections and call callback
+ * for each of them.
+ *
+ * @param cb User supplied callback function to call.
+ * @param user_data User specified data.
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+void net_tcp_foreach(net_tcp_cb_t cb, void *user_data);
+#else
+static inline void net_tcp_foreach(net_tcp_cb_t cb, void *user_data)
+{
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+}
+#endif
+
+/**
+ * @brief Send available queued data over TCP connection
+ *
+ * @param context TCP context
+ * @param cb TCP callback function
+ * @param user_data User specified data
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_send_data(struct net_context *context, net_context_send_cb_t cb,
+		      void *user_data);
+#else
+static inline int net_tcp_send_data(struct net_context *context,
+				    net_context_send_cb_t cb,
+				    void *user_data)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+
+	return 0;
+}
+#endif
+
+/**
+ * @brief Enqueue a single packet for transmission
+ *
+ * @param context TCP context
+ * @param pkt Packet
+ *
+ * @return 0 if ok, < 0 if error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt);
+#else
+static inline int net_tcp_queue_data(struct net_context *context,
+				     struct net_pkt *pkt)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(pkt);
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Sends one TCP packet initialized with the _prepare_*()
+ *        family of functions.
+ *
+ * @param pkt Packet
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_send_pkt(struct net_pkt *pkt);
+#else
+static inline int net_tcp_send_pkt(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Handle a received TCP ACK
+ *
+ * @param cts Context
+ * @param seq Received ACK sequence number
+ * @return False if ACK sequence number is invalid, true otherwise
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+bool net_tcp_ack_received(struct net_context *ctx, uint32_t ack);
+#else
+static inline bool net_tcp_ack_received(struct net_context *ctx, uint32_t ack)
+{
+	ARG_UNUSED(ctx);
+	ARG_UNUSED(ack);
+	return false;
+}
+#endif
+
+/**
+ * @brief Calculates and returns the MSS for a given TCP context
+ *
+ * @param tcp TCP context
+ *
+ * @return Maximum Segment Size
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+uint16_t net_tcp_get_recv_mss(const struct net_tcp *tcp);
+#else
+static inline uint16_t net_tcp_get_recv_mss(const struct net_tcp *tcp)
+{
+	ARG_UNUSED(tcp);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Returns the receive window for a given TCP context
+ *
+ * @param tcp TCP context
+ *
+ * @return Current TCP receive window
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+uint32_t net_tcp_get_recv_wnd(const struct net_tcp *tcp);
+#else
+static inline uint32_t net_tcp_get_recv_wnd(const struct net_tcp *tcp)
+{
+	ARG_UNUSED(tcp);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Obtains the state for a TCP context
+ *
+ * @param tcp TCP context
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+static inline enum net_tcp_state net_tcp_get_state(const struct net_tcp *tcp)
+{
+	return (enum net_tcp_state)tcp->state;
+}
+#else
+static inline enum net_tcp_state net_tcp_get_state(const struct net_tcp *tcp)
+{
+	ARG_UNUSED(tcp);
+	return NET_TCP_CLOSED;
+}
+#endif
+
+/**
+ * @brief Check if the sequence number is valid i.e., it is inside the window.
+ *
+ * @param tcp TCP context
+ * @param tcp_hdr TCP header pointer
+ *
+ * @return true if network packet sequence number is valid, false otherwise
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+bool net_tcp_validate_seq(struct net_tcp *tcp, struct net_tcp_hdr *tcp_hdr);
+#else
+static inline bool net_tcp_validate_seq(struct net_tcp *tcp,
+					struct net_tcp_hdr *tcp_hdr)
+{
+	ARG_UNUSED(tcp);
+	ARG_UNUSED(tcp_hdr);
+	return false;
+}
+#endif
+
+/**
+ * @brief Finalize TCP packet
+ *
+ * @param pkt Network packet
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_finalize(struct net_pkt *pkt);
+#else
+static inline int net_tcp_finalize(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+	return 0;
+}
+#endif
+
+/**
+ * @brief Parse TCP options from network packet.
+ *
+ * Parse TCP options, returning MSS value (as that the only one we
+ * handle so far).
+ *
+ * @param pkt Network packet
+ * @param opt_totlen Total length of options to parse
+ * @param opts Pointer to TCP options structure. (Each option is updated
+ * only if present, so the structure must be initialized with the default
+ * values.)
+ *
+ * @return 0 if no error, <0 in case of error
+ */
+int net_tcp_parse_opts(struct net_pkt *pkt, int opt_totlen,
+		       struct net_tcp_options *opts);
+
+/**
+ * @brief TCP receive function
+ *
+ * @param context Network context
+ * @param cb TCP receive callback function
+ * @param user_data TCP receive callback user data
+ *
+ * @return 0 if no erro, < 0 in case of error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_recv(struct net_context *context, net_context_recv_cb_t cb,
+		 void *user_data);
+#else
+static inline int net_tcp_recv(struct net_context *context,
+			       net_context_recv_cb_t cb, void *user_data)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+
+	return -EPROTOTYPE;
+}
+#endif
+
+/**
+ * @brief Queue a TCP FIN packet if needed to close the socket
+ *
+ * @param context Network context
+ *
+ * @return 0 on success where a TCP FIN packet has been queueed, -ENOTCONN
+ *         in case the socket was not connected or listening, -EOPNOTSUPP
+ *         in case it was not a TCP socket or -EPROTONOSUPPORT if TCP is not
+ *         supported
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_put(struct net_context *context);
+#else
+static inline int net_tcp_put(struct net_context *context)
+{
+	ARG_UNUSED(context);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Set TCP socket into listening state
+ *
+ * @param context Network context
+ *
+ * @return 0 if successful, -EOPNOTSUPP if the context was not for TCP,
+ *         -EPROTONOSUPPORT if TCP is not supported
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_listen(struct net_context *context);
+#else
+static inline int net_tcp_listen(struct net_context *context)
+{
+	ARG_UNUSED(context);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Update TCP receive window
+ *
+ * @param context Network context
+ * @param delta Receive window delta
+ *
+ * @return 0 on success, -EPROTOTYPE if there is no TCP context, -EINVAL
+ *         if the receive window delta is out of bounds, -EPROTONOSUPPORT
+ *         if TCP is not supported
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_update_recv_wnd(struct net_context *context, int32_t delta);
+#else
+static inline int net_tcp_update_recv_wnd(struct net_context *context,
+					  int32_t delta)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(delta);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Initialize TCP parts of a context
+ *
+ * @param context Network context
+ *
+ * @return 0 if successful, < 0 on error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_get(struct net_context *context);
+#else
+static inline int net_tcp_get(struct net_context *context)
+{
+	ARG_UNUSED(context);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Unref TCP parts of a context
+ *
+ * @param context Network context
+ *
+ * @return 0 if successful, < 0 on error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_unref(struct net_context *context);
+#else
+static inline int net_tcp_unref(struct net_context *context)
+{
+	ARG_UNUSED(context);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Accept TCP connection
+ *
+ * @param context Network context
+ * @param cb Accept callback
+ * @param user_data Accept callback user data
+ *
+ * @return 0 on success, < 0 on error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_accept(struct net_context *context, net_tcp_accept_cb_t cb,
+		   void *user_data);
+#else
+static inline int net_tcp_accept(struct net_context *context,
+				 net_tcp_accept_cb_t cb, void *user_data)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Connect TCP connection
+ *
+ * @param context Network context
+ * @param addr Remote address
+ * @param laddr Local address
+ * @param rport Remote port
+ * @param lport Local port
+ * @param timeout Connect timeout
+ * @param cb Connect callback
+ * @param user_data Connect callback user data
+ *
+ * @return 0 on success, < 0 on error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+int net_tcp_connect(struct net_context *context,
+		    const struct sockaddr *addr,
+		    struct sockaddr *laddr,
+		    uint16_t rport,
+		    uint16_t lport,
+		    k_timeout_t timeout,
+		    net_context_connect_cb_t cb,
+		    void *user_data);
+#else
+static inline int net_tcp_connect(struct net_context *context,
+				  const struct sockaddr *addr,
+				  struct sockaddr *laddr,
+				  uint16_t rport, uint16_t lport, k_timeout_t timeout,
+				  net_context_connect_cb_t cb, void *user_data)
+{
+	ARG_UNUSED(context);
+	ARG_UNUSED(addr);
+	ARG_UNUSED(laddr);
+	ARG_UNUSED(rport);
+	ARG_UNUSED(lport);
+	ARG_UNUSED(cb);
+	ARG_UNUSED(user_data);
+
+	return -EPROTONOSUPPORT;
+}
+#endif
+
+/**
+ * @brief Get pointer to TCP header in net_pkt
+ *
+ * @param pkt Network packet
+ * @param tcp_access Helper variable for accessing TCP header
+ *
+ * @return TCP header on success, NULL on error
+ */
+#if defined(CONFIG_NET_NATIVE_TCP)
+struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *tcp_access);
+#else
+static inline
+struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *tcp_access)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(tcp_access);
+
+	return NULL;
+}
+#endif
+
+#if defined(CONFIG_NET_NATIVE_TCP)
+void net_tcp_init(void);
+#else
+#define net_tcp_init(...)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TCP_INTERNAL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.h	(working copy)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2018-2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef TP_H
+#define TP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <data/json.h>
+#include <net/net_pkt.h>
+#include "connection.h"
+
+#if IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)
+
+#define TP_SEQ 0
+#define TP_ACK 1
+
+#define TP_BOOL	1
+#define TP_INT	2
+
+enum tp_type { /* Test protocol message type */
+	TP_NONE = 0,
+	TP_COMMAND,
+	TP_CONFIG_REQUEST,
+	TP_CONFIG_REPLY,
+	TP_INTROSPECT_REQUEST,
+	TP_INTROSPECT_REPLY,
+	TP_INTROSPECT_MEMORY_REQUEST,
+	TP_INTROSPECT_MEMORY_REPLY,
+	TP_INTROSPECT_PACKETS_REQUEST,
+	TP_INTROSPECT_PACKETS_REPLY,
+	TP_DEBUG_STOP,
+	TP_DEBUG_STEP,
+	TP_DEBUG_CONTINUE,
+	TP_DEBUG_RESPONSE,
+	TP_DEBUG_BREAKPOINT_ADD,
+	TP_DEBUG_BREAKPOINT_DELETE,
+	TP_TRACE_ADD,
+	TP_TRACE_DELETE
+};
+
+extern bool tp_trace;
+extern enum tp_type tp_state;
+
+struct tp_msg {
+	const char *msg;
+};
+
+static const struct json_obj_descr tp_msg_dsc[] = {
+	JSON_OBJ_DESCR_PRIM(struct tp_msg, msg, JSON_TOK_STRING)
+};
+
+struct tp {
+	enum tp_type type;
+	const char *msg;
+	const char *status;
+	const char *state;
+	int seq;
+	int ack;
+	const char *rcv;
+	const char *data;
+	const char *op;
+};
+
+#define json_str(_type, _field) \
+	JSON_OBJ_DESCR_PRIM(struct _type, _field, JSON_TOK_STRING)
+#define json_num(_type, _field) \
+	JSON_OBJ_DESCR_PRIM(struct _type, _field, JSON_TOK_NUMBER)
+
+static const struct json_obj_descr tp_descr[] = {
+	json_str(tp, msg),
+	json_str(tp, status),
+	json_str(tp, state),
+	json_num(tp, seq),
+	json_num(tp, ack),
+	json_str(tp, rcv),
+	json_str(tp, data),
+	json_str(tp, op),
+};
+
+struct tp_entry {
+	const char *key;
+	const char *value;
+};
+
+static const struct json_obj_descr tp_entry_dsc[] = {
+	JSON_OBJ_DESCR_PRIM(struct tp_entry, key, JSON_TOK_STRING),
+	JSON_OBJ_DESCR_PRIM(struct tp_entry, value, JSON_TOK_STRING),
+};
+
+struct tp_new {
+	const char *msg;
+	struct tp_entry data[10];
+	size_t num_entries;
+};
+
+static const struct json_obj_descr tp_new_dsc[] = {
+	JSON_OBJ_DESCR_PRIM(struct tp_new, msg, JSON_TOK_STRING),
+	JSON_OBJ_DESCR_OBJ_ARRAY(struct tp_new, data, 10, num_entries,
+				 tp_entry_dsc, ARRAY_SIZE(tp_entry_dsc)),
+};
+
+enum net_verdict tp_input(struct net_conn *net_conn,
+			  struct net_pkt *pkt,
+			  union net_ip_header *ip,
+			  union net_proto_header *proto,
+			  void *user_data);
+
+char *tp_basename(char *path);
+const char *tp_hex_to_str(void *data, size_t len);
+size_t tp_str_to_hex(void *buf, size_t bufsize, const char *s);
+
+void _tp_output(sa_family_t af, struct net_if *iface, void *data,
+		size_t data_len, const char *file, int line);
+#define tp_output(_af, _iface, _data, _data_len)	\
+	_tp_output(_af, _iface, _data, _data_len,	\
+		   tp_basename(__FILE__), __LINE__)
+
+void tp_pkt_adj(struct net_pkt *pkt, int req_len);
+
+enum tp_type tp_msg_to_type(const char *s);
+
+void *tp_malloc(size_t size, const char *file, int line, const char *func);
+void tp_free(void *ptr, const char *file, int line, const char *func);
+void *tp_calloc(size_t nmemb, size_t size, const char *file, int line,
+		const char *func);
+void tp_mem_stat(void);
+
+struct net_buf *tp_nbuf_alloc(struct net_buf_pool *pool, size_t len,
+				const char *file, int line, const char *func);
+struct net_buf *tp_nbuf_clone(struct net_buf *buf, const char *file, int line,
+				const char *func);
+void tp_nbuf_unref(struct net_buf *nbuf, const char *file, int line,
+			const char *func);
+void tp_nbuf_stat(void);
+void tp_pkt_alloc(struct net_pkt *pkt,
+		  const char *file, int line);
+
+struct net_pkt *tp_pkt_clone(struct net_pkt *pkt, const char *file, int line);
+void tp_pkt_unref(struct net_pkt *pkt, const char *file, int line);
+void tp_pkt_stat(void);
+
+uint32_t tp_seq_track(int kind, uint32_t *pvalue, int req,
+			const char *file, int line, const char *func);
+void tp_seq_stat(void);
+
+struct tp *json_to_tp(void *data, size_t data_len);
+enum tp_type json_decode_msg(void *data, size_t data_len);
+struct tp_new *json_to_tp_new(void *data, size_t data_len);
+void tp_encode(struct tp *tp, void *data, size_t *data_len);
+void tp_new_to_json(struct tp_new *tp, void *data, size_t *data_len);
+void tp_new_find_and_apply(struct tp_new *tp, const char *key, void *value,
+				int type);
+void tp_out(sa_family_t af, struct net_if *iface, const char *msg,
+	    const char *key, const char *value);
+
+bool tp_tap_input(struct net_pkt *pkt);
+
+#else /* else of IS_ENABLED(CONFIG_NET_TEST_PROTOCOL) */
+
+#define tp_tap_input(_pkt) false
+#define tp_input(_pkt) false
+#define tp_out(args...)
+
+#endif /* end of IS_ENABLED(CONFIG_NET_TEST_PROTOCOL) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TP_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp.c	(working copy)
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2018-2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "tp.h"
+#include "tp_priv.h"
+#include "ipv4.h"
+#include "ipv6.h"
+#include "udp_internal.h"
+
+static sys_slist_t tp_mem = SYS_SLIST_STATIC_INIT(&tp_mem);
+static sys_slist_t tp_nbufs = SYS_SLIST_STATIC_INIT(&tp_nbufs);
+static sys_slist_t tp_pkts = SYS_SLIST_STATIC_INIT(&tp_pkts);
+static sys_slist_t tp_seq = SYS_SLIST_STATIC_INIT(&tp_seq);
+
+bool tp_trace;
+enum tp_type tp_state = TP_NONE;
+
+char *tp_basename(char *path)
+{
+	char *filename = strrchr(path, '/');
+
+	return filename ? (filename + 1) : path;
+}
+
+size_t tp_str_to_hex(void *buf, size_t bufsize, const char *s)
+{
+	size_t i, j, len = strlen(s);
+
+	tp_assert((len % 2) == 0, "Invalid string: %s", s);
+
+	for (i = 0, j = 0; i < len; i += 2, j++) {
+
+		uint8_t byte = (s[i] - '0') << 4 | (s[i + 1] - '0');
+
+		((uint8_t *) buf)[j] = byte;
+	}
+
+	return j;
+}
+
+void *tp_malloc(size_t size, const char *file, int line, const char *func)
+{
+	struct tp_mem *mem = k_malloc(sizeof(struct tp_mem) + size +
+					sizeof(*mem->footer));
+
+	mem->file = file;
+	mem->line = line;
+	mem->func = func;
+
+	mem->size = size;
+
+	mem->header = TP_MEM_HEADER_COOKIE;
+
+	mem->footer = (void *) ((uint8_t *) &mem->mem + size);
+	*mem->footer = TP_MEM_FOOTER_COOKIE;
+
+	sys_slist_append(&tp_mem, (sys_snode_t *) mem);
+
+	return &mem->mem;
+}
+
+static void dump(void *data, size_t len)
+{
+	uint8_t *buf = data;
+	size_t i, width = 8;
+
+	for (i = 0; i < len; i++) {
+
+		if ((i % width) == 0) {
+			printk("0x%08lx\t", POINTER_TO_INT(buf + i));
+		}
+
+		printk("%02x ", buf[i]);
+
+		if (((i + 1) % width) == 0 || i == (len - 1)) {
+			printk("\n");
+		}
+	}
+}
+
+void tp_mem_chk(struct tp_mem *mem)
+{
+	if (mem->header != TP_MEM_HEADER_COOKIE ||
+		*mem->footer != TP_MEM_FOOTER_COOKIE) {
+
+		tp_dbg("%s:%d %s() %p size: %zu",
+			mem->file, mem->line, mem->func, mem->mem, mem->size);
+
+		dump(&mem->header, sizeof(mem->header));
+		dump(mem->mem, mem->size);
+		dump(mem->footer, sizeof(*mem->footer));
+
+		tp_assert(mem->header == TP_MEM_HEADER_COOKIE,
+				"%s:%d %s() %p Corrupt header cookie: 0x%x",
+				mem->file, mem->line, mem->func, mem->mem,
+				mem->header);
+
+		tp_assert(*mem->footer == TP_MEM_FOOTER_COOKIE,
+				"%s:%d %s() %p Corrupt footer cookie: 0x%x",
+				mem->file, mem->line, mem->func, mem->mem,
+				*mem->footer);
+	}
+}
+
+void tp_free(void *ptr, const char *file, int line, const char *func)
+{
+	struct tp_mem *mem = (void *)((uint8_t *) ptr - sizeof(struct tp_mem));
+
+	tp_mem_chk(mem);
+
+	if (!sys_slist_find_and_remove(&tp_mem, (sys_snode_t *) mem)) {
+		tp_assert(false, "%s:%d %s() Invalid free(%p)",
+				file, line, func, ptr);
+	}
+
+	memset(mem, 0, sizeof(tp_mem) + mem->size + sizeof(*mem->footer));
+	k_free(mem);
+}
+
+void *tp_calloc(size_t nmemb, size_t size, const char *file, int line,
+		const char *func)
+{
+	size_t bytes = size * nmemb;
+	void *ptr = tp_malloc(bytes, file, line, func);
+
+	memset(ptr, 0, bytes);
+
+	return ptr;
+}
+
+void tp_mem_stat(void)
+{
+	struct tp_mem *mem;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&tp_mem, mem, next) {
+		tp_dbg("len=%zu %s:%d", mem->size, mem->file, mem->line);
+		tp_mem_chk(mem);
+	}
+}
+
+struct net_buf *tp_nbuf_alloc(struct net_buf_pool *pool, size_t len,
+				const char *file, int line, const char *func)
+{
+	struct net_buf *nbuf = net_buf_alloc_len(pool, len, K_NO_WAIT);
+	struct tp_nbuf *tp_nbuf = k_malloc(sizeof(struct tp_nbuf));
+
+	tp_assert(len, "");
+	tp_assert(nbuf, "Out of nbufs");
+
+	tp_dbg("size=%d %p %s:%d %s()", nbuf->size, nbuf, file, line, func);
+
+	tp_nbuf->nbuf = nbuf;
+	tp_nbuf->file = file;
+	tp_nbuf->line = line;
+
+	sys_slist_append(&tp_nbufs, (sys_snode_t *) tp_nbuf);
+
+	return nbuf;
+}
+
+struct net_buf *tp_nbuf_clone(struct net_buf *buf, const char *file, int line,
+				const char *func)
+{
+	struct net_buf *clone = net_buf_clone(buf, K_NO_WAIT);
+	struct tp_nbuf *tb = k_malloc(sizeof(struct tp_nbuf));
+
+	tp_dbg("size=%d %p %s:%d %s()", clone->size, clone, file, line, func);
+
+	tb->nbuf = clone;
+	tb->file = file;
+	tb->line = line;
+
+	sys_slist_append(&tp_nbufs, &tb->next);
+
+	return clone;
+
+}
+
+void tp_nbuf_unref(struct net_buf *nbuf, const char *file, int line,
+			const char *func)
+{
+	bool found = false;
+	struct tp_nbuf *tp_nbuf;
+
+	tp_dbg("len=%d %p %s:%d %s()", nbuf->len, nbuf, file, line, func);
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&tp_nbufs, tp_nbuf, next) {
+		if (tp_nbuf->nbuf == nbuf) {
+			found = true;
+			break;
+		}
+	}
+
+	tp_assert(found, "Invalid %s(%p): %s:%d", __func__, nbuf, file, line);
+
+	sys_slist_find_and_remove(&tp_nbufs, (sys_snode_t *) tp_nbuf);
+
+	net_buf_unref(nbuf);
+
+	k_free(tp_nbuf);
+}
+
+void tp_nbuf_stat(void)
+{
+	struct tp_nbuf *tp_nbuf;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&tp_nbufs, tp_nbuf, next) {
+		tp_dbg("%s:%d len=%d", tp_nbuf->file, tp_nbuf->line,
+			tp_nbuf->nbuf->len);
+	}
+}
+
+void tp_pkt_alloc(struct net_pkt *pkt,
+		  const char *file, int line)
+{
+	struct tp_pkt *tp_pkt = k_malloc(sizeof(struct tp_pkt));
+
+	tp_assert(tp_pkt, "");
+	tp_assert(pkt, "");
+
+	tp_pkt->pkt = pkt;
+	tp_pkt->file = file;
+	tp_pkt->line = line;
+
+	sys_slist_append(&tp_pkts, (sys_snode_t *) tp_pkt);
+}
+
+struct net_pkt *tp_pkt_clone(struct net_pkt *pkt, const char *file, int line)
+{
+	struct tp_pkt *tp_pkt = k_malloc(sizeof(struct tp_pkt));
+
+	pkt = net_pkt_clone(pkt, K_NO_WAIT);
+
+	tp_pkt->pkt = pkt;
+	tp_pkt->file = file;
+	tp_pkt->line = line;
+
+	sys_slist_append(&tp_pkts, (sys_snode_t *) tp_pkt);
+
+	return pkt;
+}
+
+void tp_pkt_unref(struct net_pkt *pkt, const char *file, int line)
+{
+	bool found = false;
+	struct tp_pkt *tp_pkt;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&tp_pkts, tp_pkt, next) {
+		if (tp_pkt->pkt == pkt) {
+			found = true;
+			break;
+		}
+	}
+
+	tp_assert(found, "Invalid %s(%p): %s:%d", __func__, pkt, file, line);
+
+	sys_slist_find_and_remove(&tp_pkts, (sys_snode_t *) tp_pkt);
+
+	net_pkt_unref(tp_pkt->pkt);
+
+	k_free(tp_pkt);
+}
+
+void tp_pkt_stat(void)
+{
+	struct tp_pkt *pkt;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&tp_pkts, pkt, next) {
+		tp_dbg("%s:%d %p", pkt->file, pkt->line, pkt->pkt);
+	}
+}
+
+#define tp_seq_dump(_seq)						\
+{									\
+	tp_dbg("%s %u->%u (%s%d) %s:%d %s() %s",			\
+		(_seq)->kind == TP_SEQ ? "SEQ" : "ACK",			\
+		(_seq)->old_value, (_seq)->value,			\
+		(_seq)->req >= 0 ? "+" : "", (_seq)->req,		\
+		(_seq)->file, (_seq)->line, (_seq)->func,		\
+		(_seq)->of ? "OF" : "");				\
+}
+
+uint32_t tp_seq_track(int kind, uint32_t *pvalue, int req,
+			const char *file, int line, const char *func)
+{
+	struct tp_seq *seq = k_calloc(1, sizeof(struct tp_seq));
+
+	seq->file = file;
+	seq->line = line;
+	seq->func = func;
+
+	seq->kind = kind;
+
+	seq->req = req;
+	seq->old_value = *pvalue;
+
+	if (req > 0) {
+		seq->of = __builtin_uadd_overflow(seq->old_value, seq->req,
+							&seq->value);
+	} else {
+		seq->value += req;
+	}
+
+	*pvalue = seq->value;
+
+	sys_slist_append(&tp_seq, (sys_snode_t *) seq);
+
+	tp_seq_dump(seq);
+
+	return seq->value;
+}
+
+void tp_seq_stat(void)
+{
+	struct tp_seq *seq;
+
+	while ((seq = (struct tp_seq *) sys_slist_get(&tp_seq))) {
+		tp_seq_dump(seq);
+		k_free(seq);
+	}
+}
+
+enum tp_type tp_msg_to_type(const char *s)
+{
+	enum tp_type type = TP_NONE;
+
+#define is_tp(_s, _type) do {		\
+	if (is(#_type, _s)) {		\
+		type = _type;		\
+		goto out;		\
+	}				\
+} while (0)
+
+	is_tp(s, TP_COMMAND);
+	is_tp(s, TP_CONFIG_REQUEST);
+	is_tp(s, TP_INTROSPECT_REQUEST);
+	is_tp(s, TP_DEBUG_STOP);
+	is_tp(s, TP_DEBUG_STEP);
+	is_tp(s, TP_DEBUG_CONTINUE);
+
+#undef is_tp
+
+out:
+	tp_assert(type != TP_NONE, "Invalid message: %s", s);
+
+	return type;
+}
+
+static void udp_finalize_pkt(struct net_pkt *pkt)
+{
+	int ret = 0;
+
+	net_pkt_cursor_init(pkt);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		ret = net_ipv4_finalize(pkt, IPPROTO_UDP);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		ret = net_ipv6_finalize(pkt, IPPROTO_UDP);
+	}
+
+	NET_ASSERT(ret == 0);
+}
+
+static int ip_header_add(struct net_pkt *pkt)
+{
+	if (IS_ENABLED(CONFIG_NET_IPV4) && net_pkt_family(pkt) == AF_INET) {
+		struct in_addr src;
+		struct in_addr dst;
+
+		net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &src);
+		net_addr_pton(AF_INET, CONFIG_NET_CONFIG_PEER_IPV4_ADDR, &dst);
+
+		return net_ipv4_create(pkt, &src, &dst);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && net_pkt_family(pkt) == AF_INET6) {
+		struct in6_addr src;
+		struct in6_addr dst;
+
+		net_addr_pton(AF_INET6, CONFIG_NET_CONFIG_MY_IPV6_ADDR, &src);
+		net_addr_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR, &dst);
+
+		return net_ipv6_create(pkt, &src, &dst);
+	}
+
+	return -EINVAL;
+}
+
+static void tp_pkt_send(struct net_pkt *pkt)
+{
+	net_pkt_ref(pkt);
+
+	if (net_send_data(pkt) < 0) {
+		tp_err("net_send_data()");
+	}
+
+	tp_pkt_unref(pkt, tp_basename(__FILE__), __LINE__);
+}
+
+static struct net_pkt *tp_output_pkt_alloc(sa_family_t af,
+					   struct net_if *iface,
+					   size_t len,
+					   const char *file, int line)
+{
+	struct tp_pkt *tp_pkt = k_malloc(sizeof(struct tp_pkt));
+
+	tp_assert(tp_pkt, "");
+
+	tp_pkt->pkt = net_pkt_alloc_with_buffer(iface,
+					sizeof(struct net_udp_hdr) + len,
+					af, IPPROTO_UDP, K_NO_WAIT);
+	tp_assert(tp_pkt->pkt, "");
+
+	tp_pkt->file = file;
+	tp_pkt->line = line;
+
+	sys_slist_append(&tp_pkts, (sys_snode_t *) tp_pkt);
+
+	return tp_pkt->pkt;
+}
+
+void _tp_output(sa_family_t af, struct net_if *iface, void *data,
+		size_t data_len, const char *file, int line)
+{
+	struct net_pkt *pkt = tp_output_pkt_alloc(af, iface, data_len,
+						  file, line);
+	int ret;
+
+	ret = ip_header_add(pkt);
+	if (ret < 0) {
+		goto fail;
+	}
+
+	ret = net_udp_create(pkt, htons(4242), htons(4242));
+	if (ret < 0) {
+		goto fail;
+	}
+
+	ret = net_pkt_write(pkt, data, data_len);
+	if (ret < 0) {
+		goto fail;
+	}
+
+	udp_finalize_pkt(pkt);
+
+	NET_ASSERT(net_pkt_get_len(pkt) <= net_if_get_mtu(pkt->iface));
+
+	tp_pkt_send(pkt);
+
+	return;
+fail:
+	NET_ASSERT(false);
+}
+
+struct tp *json_to_tp(void *data, size_t data_len)
+{
+	static struct tp tp;
+
+	memset(&tp, 0, sizeof(tp));
+
+	if (json_obj_parse(data, data_len, tp_descr, ARRAY_SIZE(tp_descr),
+			&tp) < 0) {
+		tp_err("json_obj_parse()");
+	}
+
+	tp.type = tp_msg_to_type(tp.msg);
+
+	return &tp;
+}
+
+void tp_new_find_and_apply(struct tp_new *tp, const char *key, void *value,
+				int type)
+{
+	bool found = false;
+	int i;
+
+	for (i = 0; i < tp->num_entries; i++) {
+		if (is(key, tp->data[i].key)) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found) {
+		switch (type) {
+		case TP_BOOL: {
+			bool new_value, old = *((bool *) value);
+
+			new_value = atoi(tp->data[i].value);
+			*((bool *) value) = new_value;
+			tp_dbg("%s %d->%d", key, old, new_value);
+			break;
+		}
+		case TP_INT: {
+			int new_value, old_value = *((int *) value);
+
+			new_value = atoi(tp->data[i].value);
+			*((int *) value) = new_value;
+			tp_dbg("%s %d->%d", key, old_value, new_value);
+			break;
+		}
+		default:
+			tp_err("Unimplemented");
+		}
+	}
+}
+
+enum tp_type json_decode_msg(void *data, size_t data_len)
+{
+	int decoded;
+	struct tp_msg tp;
+
+	memset(&tp, 0, sizeof(tp));
+
+	decoded = json_obj_parse(data, data_len, tp_msg_dsc,
+					ARRAY_SIZE(tp_msg_dsc), &tp);
+#if 0
+	if ((decoded & 1) == false) { /* TODO: this fails, why? */
+		tp_err("json_obj_parse()");
+	}
+#endif
+	tp_dbg("%s", tp.msg);
+
+	return tp.msg ? tp_msg_to_type(tp.msg) : TP_NONE;
+}
+
+struct tp_new *json_to_tp_new(void *data, size_t data_len)
+{
+	static struct tp_new tp;
+	int i;
+
+	memset(&tp, 0, sizeof(tp));
+
+	if (json_obj_parse(data, data_len, tp_new_dsc, ARRAY_SIZE(tp_new_dsc),
+				&tp) < 0) {
+		tp_err("json_obj_parse()");
+	}
+
+	tp_dbg("%s", tp.msg);
+
+	for (i = 0; i < tp.num_entries; i++) {
+		tp_dbg("%s=%s", tp.data[i].key, tp.data[i].value);
+	}
+
+	return &tp;
+}
+
+void tp_encode(struct tp *tp, void *data, size_t *data_len)
+{
+	int error;
+
+	error = json_obj_encode_buf(tp_descr, ARRAY_SIZE(tp_descr), tp,
+					data, *data_len);
+	if (error) {
+		tp_err("json_obj_encode_buf()");
+	}
+
+	*data_len = error ? 0 : strlen(data);
+}
+
+
+void tp_new_to_json(struct tp_new *tp, void *data, size_t *data_len)
+{
+	int error = json_obj_encode_buf(tp_new_dsc, ARRAY_SIZE(tp_new_dsc), tp,
+					data, *data_len);
+	if (error) {
+		tp_err("json_obj_encode_buf()");
+	}
+
+	*data_len = error ? 0 : strlen(data);
+}
+
+void tp_out(sa_family_t af, struct net_if *iface, const char *msg,
+	    const char *key, const char *value)
+{
+	if (tp_trace) {
+		size_t json_len;
+		static uint8_t buf[128]; /* TODO: Merge all static buffers and
+				       * eventually drop them
+				       */
+		struct tp_new tp = {
+			.msg = msg,
+			.data = { { .key = key, .value = value } },
+			.num_entries = 1
+		};
+		json_len = sizeof(buf);
+		tp_new_to_json(&tp, buf, &json_len);
+		if (json_len) {
+			tp_output(af, iface, buf, json_len);
+		}
+	}
+}
+
+bool tp_tap_input(struct net_pkt *pkt)
+{
+	bool tap = tp_state != TP_NONE;
+
+	if (tap) {
+		net_pkt_ref(pkt);
+		/* STAILQ_INSERT_HEAD(&tp_q, pkt, stq_next); */
+	}
+
+	return tap;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/tp_priv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp_priv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/tp_priv.h	(working copy)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018-2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef TP_PRIV_H
+#define TP_PRIV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <zephyr.h>
+#include <net/net_pkt.h>
+
+#define tp_dbg(fmt, args...) printk("%s: " fmt "\n", __func__, ## args)
+#define tp_err(fmt, args...) do {				\
+	printk("%s: Error: " fmt "\n", __func__, ## args);	\
+	k_oops();						\
+} while (0)
+
+#define tp_assert(cond, fmt, args...) do {			\
+	if ((cond) == false) {					\
+		printk("%s: Assertion failed: %s, " fmt "\n",	\
+			__func__, #cond, ## args);		\
+		k_oops();					\
+	}							\
+} while (0)
+
+#define is(_a, _b) (strcmp((_a), (_b)) == 0)
+#define ip_get(_x) ((struct net_ipv4_hdr *) net_pkt_ip_data((_x)))
+
+#define TP_MEM_HEADER_COOKIE 0xAAAAAAAA
+#define TP_MEM_FOOTER_COOKIE 0xBBBBBBBB
+
+struct tp_mem {
+	sys_snode_t next;
+	const char *file;
+	int line;
+	const char *func;
+	size_t size;
+	uint32_t *footer;
+	uint32_t header;
+	uint8_t mem[];
+};
+
+struct tp_nbuf {
+	sys_snode_t next;
+	struct net_buf *nbuf;
+	const char *file;
+	int line;
+};
+
+struct tp_pkt {
+	sys_snode_t next;
+	struct net_pkt *pkt;
+	const char *file;
+	int line;
+};
+
+struct tp_seq {
+	sys_snode_t next;
+	const char *file;
+	int line;
+	const char *func;
+	int kind;
+	int req;
+	uint32_t value;
+	uint32_t old_value;
+	int of;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TP_PRIV_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/trickle.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/trickle.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/trickle.c	(working copy)
@@ -0,0 +1,230 @@
+/** @file
+ * @brief Trickle timer library
+ *
+ * This implements Trickle timer as specified in RFC 6206
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_trickle, CONFIG_NET_TRICKLE_LOG_LEVEL);
+
+#include <errno.h>
+#include <sys/util.h>
+#include <random/rand32.h>
+
+#include <net/net_core.h>
+#include <net/trickle.h>
+
+#define TICK_MAX ~0
+
+static void trickle_timeout(struct k_work *work);
+
+static inline bool is_suppression_disabled(struct net_trickle *trickle)
+{
+	return trickle->k == NET_TRICKLE_INFINITE_REDUNDANCY;
+}
+
+static inline bool is_tx_allowed(struct net_trickle *trickle)
+{
+	return is_suppression_disabled(trickle) ||
+		(trickle->c < trickle->k);
+}
+
+static inline uint32_t get_end(struct net_trickle *trickle)
+{
+	return trickle->Istart + trickle->I;
+}
+
+/* Returns a random time point t in [I/2 , I) */
+static uint32_t get_t(uint32_t I)
+{
+	I >>= 1;
+
+	NET_DBG("[%d, %d)", I, I << 1);
+
+	return I + (sys_rand32_get() % I);
+}
+
+static void double_interval_timeout(struct k_work *work)
+{
+	struct net_trickle *trickle = CONTAINER_OF(work,
+						   struct net_trickle,
+						   timer);
+	uint32_t rand_time;
+	uint32_t last_end = get_end(trickle);
+
+	trickle->c = 0U;
+
+	NET_DBG("now %u (was at %u)", k_uptime_get_32(), last_end);
+
+	/* Check if we need to double the interval */
+	if (trickle->I <= (trickle->Imax_abs >> 1)) {
+		/* Double if I <= Imax/2 */
+		trickle->I <<= 1;
+
+		NET_DBG("double I %u", trickle->I);
+	} else {
+		trickle->I = trickle->Imax_abs;
+
+		NET_DBG("I %u", trickle->I);
+	}
+
+	/* Random t in [I/2, I) */
+	rand_time = get_t(trickle->I);
+
+	NET_DBG("doubling time %u", rand_time);
+
+	trickle->Istart = k_uptime_get_32() + rand_time;
+	k_delayed_work_init(&trickle->timer, trickle_timeout);
+	k_delayed_work_submit(&trickle->timer, K_MSEC(rand_time));
+
+	NET_DBG("last end %u new end %u for %u I %u",
+		last_end, get_end(trickle), trickle->Istart, trickle->I);
+}
+
+static inline void reschedule(struct net_trickle *trickle)
+{
+	uint32_t now = k_uptime_get_32();
+	uint32_t diff = get_end(trickle) - now;
+
+	NET_DBG("now %d end in %d", now, diff);
+
+	/* Did the clock wrap */
+	if ((int32_t)diff < 0) {
+		diff = 0U;
+		NET_DBG("Clock wrap");
+	}
+
+	k_delayed_work_init(&trickle->timer, double_interval_timeout);
+	k_delayed_work_submit(&trickle->timer, K_MSEC(diff));
+}
+
+static void trickle_timeout(struct k_work *work)
+{
+	struct net_trickle *trickle = CONTAINER_OF(work,
+						   struct net_trickle,
+						   timer);
+
+	NET_DBG("Trickle timeout at %d", k_uptime_get_32());
+
+	if (trickle->cb) {
+		NET_DBG("TX ok %d c(%u) < k(%u)",
+			is_tx_allowed(trickle), trickle->c, trickle->k);
+
+		trickle->cb(trickle, is_tx_allowed(trickle),
+			    trickle->user_data);
+	}
+
+	if (net_trickle_is_running(trickle)) {
+		reschedule(trickle);
+	}
+}
+
+static void setup_new_interval(struct net_trickle *trickle)
+{
+	uint32_t t;
+
+	trickle->c = 0U;
+
+	t = get_t(trickle->I);
+
+	trickle->Istart = k_uptime_get_32();
+
+	k_delayed_work_submit(&trickle->timer, K_MSEC(t));
+
+	NET_DBG("new interval at %d ends %d t %d I %d",
+		trickle->Istart,
+		get_end(trickle),
+		t,
+		trickle->I);
+}
+
+#define CHECK_IMIN(Imin) \
+	((Imin < 2) || (Imin > (TICK_MAX >> 1)))
+
+int net_trickle_create(struct net_trickle *trickle,
+		       uint32_t Imin,
+		       uint8_t Imax,
+		       uint8_t k)
+{
+	NET_ASSERT(trickle && Imax > 0 && k > 0 && !CHECK_IMIN(Imin));
+
+	(void)memset(trickle, 0, sizeof(struct net_trickle));
+
+	trickle->Imin = Imin;
+	trickle->Imax = Imax;
+	trickle->Imax_abs = Imin << Imax;
+	trickle->k = k;
+
+	NET_ASSERT(trickle->Imax_abs);
+
+	NET_DBG("Imin %d Imax %u k %u Imax_abs %d",
+		trickle->Imin, trickle->Imax, trickle->k,
+		trickle->Imax_abs);
+
+	k_delayed_work_init(&trickle->timer, trickle_timeout);
+
+	return 0;
+}
+
+int net_trickle_start(struct net_trickle *trickle,
+		      net_trickle_cb_t cb,
+		      void *user_data)
+{
+	NET_ASSERT(trickle && cb);
+
+	trickle->cb = cb;
+	trickle->user_data = user_data;
+
+	/* Random I in [Imin , Imax] */
+	trickle->I = trickle->Imin +
+		(sys_rand32_get() % (trickle->Imax_abs - trickle->Imin + 1));
+
+	setup_new_interval(trickle);
+
+	NET_DBG("start %d end %d in [%d , %d)",
+		trickle->Istart, get_end(trickle),
+		trickle->I >> 1, trickle->I);
+
+	return 0;
+}
+
+int net_trickle_stop(struct net_trickle *trickle)
+{
+	NET_ASSERT(trickle);
+
+	k_delayed_work_cancel(&trickle->timer);
+
+	trickle->I = 0U;
+
+	return 0;
+}
+
+void net_trickle_consistency(struct net_trickle *trickle)
+{
+	NET_ASSERT(trickle);
+
+	if (trickle->c < 0xFF) {
+		trickle->c++;
+	}
+
+	NET_DBG("consistency %u", trickle->c);
+}
+
+void net_trickle_inconsistency(struct net_trickle *trickle)
+{
+	NET_ASSERT(trickle);
+
+	if (trickle->I != trickle->Imin) {
+		NET_DBG("inconsistency");
+
+		trickle->I = trickle->Imin;
+	}
+
+	setup_new_interval(trickle);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/udp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/udp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/udp.c	(working copy)
@@ -0,0 +1,185 @@
+/** @file
+ * @brief UDP packet helpers.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_udp, CONFIG_NET_UDP_LOG_LEVEL);
+
+#include "net_private.h"
+#include "udp_internal.h"
+#include "net_stats.h"
+
+#define PKT_WAIT_TIME K_SECONDS(1)
+
+int net_udp_create(struct net_pkt *pkt, uint16_t src_port, uint16_t dst_port)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+	struct net_udp_hdr *udp_hdr;
+
+	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
+	if (!udp_hdr) {
+		return -ENOBUFS;
+	}
+
+	udp_hdr->src_port = src_port;
+	udp_hdr->dst_port = dst_port;
+	udp_hdr->len      = 0U;
+	udp_hdr->chksum   = 0U;
+
+	return net_pkt_set_data(pkt, &udp_access);
+}
+
+int net_udp_finalize(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+	struct net_udp_hdr *udp_hdr;
+	uint16_t length = 0;
+
+	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
+	if (!udp_hdr) {
+		return -ENOBUFS;
+	}
+
+	length = net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) -
+		 net_pkt_ip_opts_len(pkt);
+
+	udp_hdr->len = htons(length);
+
+	if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) {
+		udp_hdr->chksum = net_calc_chksum_udp(pkt);
+	}
+
+	return net_pkt_set_data(pkt, &udp_access);
+}
+
+struct net_udp_hdr *net_udp_get_hdr(struct net_pkt *pkt,
+				    struct net_udp_hdr *hdr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(udp_access, struct net_udp_hdr);
+	struct net_pkt_cursor backup;
+	struct net_udp_hdr *udp_hdr;
+	bool overwrite;
+
+	udp_access.data = hdr;
+
+	overwrite = net_pkt_is_being_overwritten(pkt);
+	net_pkt_set_overwrite(pkt, true);
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+			 net_pkt_ip_opts_len(pkt))) {
+		udp_hdr = NULL;
+		goto out;
+	}
+
+	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
+
+out:
+	net_pkt_cursor_restore(pkt, &backup);
+	net_pkt_set_overwrite(pkt, overwrite);
+
+	return udp_hdr;
+}
+
+struct net_udp_hdr *net_udp_set_hdr(struct net_pkt *pkt,
+				    struct net_udp_hdr *hdr)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+	struct net_pkt_cursor backup;
+	struct net_udp_hdr *udp_hdr;
+	bool overwrite;
+
+	overwrite = net_pkt_is_being_overwritten(pkt);
+	net_pkt_set_overwrite(pkt, true);
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+
+	if (net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) +
+			 net_pkt_ip_opts_len(pkt))) {
+		udp_hdr = NULL;
+		goto out;
+	}
+
+	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
+	if (!udp_hdr) {
+		goto out;
+	}
+
+	memcpy(udp_hdr, hdr, sizeof(struct net_udp_hdr));
+
+	net_pkt_set_data(pkt, &udp_access);
+out:
+	net_pkt_cursor_restore(pkt, &backup);
+	net_pkt_set_overwrite(pkt, overwrite);
+
+	return udp_hdr == NULL ? NULL : hdr;
+}
+
+int net_udp_register(uint8_t family,
+		     const struct sockaddr *remote_addr,
+		     const struct sockaddr *local_addr,
+		     uint16_t remote_port,
+		     uint16_t local_port,
+		     net_conn_cb_t cb,
+		     void *user_data,
+		     struct net_conn_handle **handle)
+{
+	return net_conn_register(IPPROTO_UDP, family, remote_addr, local_addr,
+				 remote_port, local_port, cb, user_data,
+				 handle);
+}
+
+int net_udp_unregister(struct net_conn_handle *handle)
+{
+	return net_conn_unregister(handle);
+}
+
+struct net_udp_hdr *net_udp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *udp_access)
+{
+	struct net_udp_hdr *udp_hdr;
+
+	udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, udp_access);
+	if (!udp_hdr || net_pkt_set_data(pkt, udp_access)) {
+		NET_DBG("DROP: corrupted header");
+		goto drop;
+	}
+
+	if (ntohs(udp_hdr->len) != (net_pkt_get_len(pkt) -
+				    net_pkt_ip_hdr_len(pkt) -
+				    net_pkt_ip_opts_len(pkt))) {
+		NET_DBG("DROP: Invalid hdr length");
+		goto drop;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) &&
+	    net_if_need_calc_rx_checksum(net_pkt_iface(pkt))) {
+		if (!udp_hdr->chksum) {
+			if (IS_ENABLED(CONFIG_NET_UDP_MISSING_CHECKSUM) &&
+			    net_pkt_family(pkt) == AF_INET) {
+				goto out;
+			}
+
+			goto drop;
+		}
+
+		if (net_calc_verify_chksum_udp(pkt) != 0U) {
+			NET_DBG("DROP: checksum mismatch");
+			goto drop;
+		}
+	}
+out:
+	return udp_hdr;
+drop:
+	net_stats_update_udp_chkerr(net_pkt_iface(pkt));
+	return NULL;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/udp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/udp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/udp_internal.h	(working copy)
@@ -0,0 +1,136 @@
+/** @file
+ @brief UDP data handler
+
+ This is not to be included by the application and is only used by
+ core IP stack.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __UDP_INTERNAL_H
+#define __UDP_INTERNAL_H
+
+#include <zephyr/types.h>
+
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_context.h>
+
+#include "connection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create UDP packet into net_pkt
+ *
+ * Note: pkt's cursor should be set a the right position.
+ *       (i.e. after IP header)
+ *
+ * @param pkt Network packet
+ * @param src_port Destination port in network byte order.
+ * @param dst_port Destination port in network byte order.
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_UDP)
+int net_udp_create(struct net_pkt *pkt, uint16_t src_port, uint16_t dst_port);
+#else
+static inline int net_udp_create(struct net_pkt *pkt,
+				 uint16_t src_port, uint16_t dst_port)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(src_port);
+	ARG_UNUSED(dst_port);
+
+	return 0;
+}
+#endif
+
+/**
+ * @brief Finalize UDP packet
+ *
+ * Note: calculates final length and setting up the checksum.
+ *
+ * @param pkt Network packet
+ *
+ * @return 0 on success, negative errno otherwise.
+ */
+#if defined(CONFIG_NET_NATIVE_UDP)
+int net_udp_finalize(struct net_pkt *pkt);
+#else
+static inline int net_udp_finalize(struct net_pkt *pkt)
+{
+	ARG_UNUSED(pkt);
+
+	return 0;
+}
+#endif
+
+/**
+ * @brief Get pointer to UDP header in net_pkt
+ *
+ * @param pkt Network packet
+ * @param udp_access Helper variable for accessing UDP header
+ *
+ * @return UDP header on success, NULL on error
+ */
+#if defined(CONFIG_NET_NATIVE_UDP)
+struct net_udp_hdr *net_udp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *udp_access);
+#else
+static inline
+struct net_udp_hdr *net_udp_input(struct net_pkt *pkt,
+				  struct net_pkt_data_access *udp_access)
+{
+	ARG_UNUSED(pkt);
+	ARG_UNUSED(udp_access);
+
+	return NULL;
+}
+#endif
+
+/**
+ * @brief Register a callback to be called when UDP packet
+ * is received corresponding to received packet.
+ *
+ * @param family Protocol family
+ * @param remote_addr Remote address of the connection end point.
+ * @param local_addr Local address of the connection end point.
+ * @param remote_port Remote port of the connection end point.
+ * @param local_port Local port of the connection end point.
+ * @param cb Callback to be called
+ * @param user_data User data supplied by caller.
+ * @param handle UDP handle that can be used when unregistering
+ *
+ * @return Return 0 if the registration succeed, <0 otherwise.
+ */
+int net_udp_register(uint8_t family,
+		     const struct sockaddr *remote_addr,
+		     const struct sockaddr *local_addr,
+		     uint16_t remote_port,
+		     uint16_t local_port,
+		     net_conn_cb_t cb,
+		     void *user_data,
+		     struct net_conn_handle **handle);
+
+/**
+ * @brief Unregister UDP handler.
+ *
+ * @param handle Handle from registering.
+ *
+ * @return Return 0 if the unregistration succeed, <0 otherwise.
+ */
+int net_udp_unregister(struct net_conn_handle *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UDP_INTERNAL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/ip/utils.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/utils.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/ip/utils.c	(working copy)
@@ -0,0 +1,912 @@
+/** @file
+ * @brief Misc network utility functions
+ *
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_utils, CONFIG_NET_UTILS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <stdlib.h>
+#include <syscall_handler.h>
+#include <zephyr/types.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_core.h>
+#include <net/socket_can.h>
+
+char *net_sprint_addr(sa_family_t af, const void *addr)
+{
+#define NBUFS 3
+	static char buf[NBUFS][NET_IPV6_ADDR_LEN];
+	static int i;
+	char *s = buf[++i % NBUFS];
+
+	return net_addr_ntop(af, addr, s, NET_IPV6_ADDR_LEN);
+}
+
+const char *net_proto2str(int family, int proto)
+{
+	if (family == AF_INET || family == AF_INET6) {
+		switch (proto) {
+		case IPPROTO_ICMP:
+			return "ICMPv4";
+		case IPPROTO_TCP:
+			return "TCP";
+		case IPPROTO_UDP:
+			return "UDP";
+		case IPPROTO_ICMPV6:
+			return "ICMPv6";
+		default:
+			break;
+		}
+	} else if (family == AF_CAN) {
+		switch (proto) {
+		case CAN_RAW:
+			return "CAN_RAW";
+		default:
+			break;
+		}
+	}
+
+	return "UNK_PROTO";
+}
+
+char *net_byte_to_hex(char *ptr, uint8_t byte, char base, bool pad)
+{
+	int i, val;
+
+	for (i = 0, val = (byte & 0xf0) >> 4; i < 2; i++, val = byte & 0x0f) {
+		if (i == 0 && !pad && !val) {
+			continue;
+		}
+		if (val < 10) {
+			*ptr++ = (char) (val + '0');
+		} else {
+			*ptr++ = (char) (val - 10 + base);
+		}
+	}
+
+	*ptr = '\0';
+
+	return ptr;
+}
+
+char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
+			     char *buf, int buflen)
+{
+	uint8_t i, len, blen;
+	char *ptr = buf;
+
+	switch (ll_len) {
+	case 8:
+		len = 8U;
+		break;
+	case 6:
+		len = 6U;
+		break;
+	case 2:
+		len = 2U;
+		break;
+	default:
+		len = 6U;
+		break;
+	}
+
+	for (i = 0U, blen = buflen; i < len && blen > 0; i++) {
+		ptr = net_byte_to_hex(ptr, (char)ll[i], 'A', true);
+		*ptr++ = ':';
+		blen -= 3U;
+	}
+
+	if (!(ptr - buf)) {
+		return NULL;
+	}
+
+	*(ptr - 1) = '\0';
+	return buf;
+}
+
+static int net_value_to_udec(char *buf, uint32_t value, int precision)
+{
+	uint32_t divisor;
+	int i;
+	int temp;
+	char *start = buf;
+
+	divisor = 1000000000U;
+	if (precision < 0) {
+		precision = 1;
+	}
+
+	for (i = 9; i >= 0; i--, divisor /= 10U) {
+		temp = value / divisor;
+		value = value % divisor;
+		if ((precision > i) || (temp != 0)) {
+			precision = i;
+			*buf++ = (char) (temp + '0');
+		}
+	}
+	*buf = 0;
+
+	return buf - start;
+}
+
+char *z_impl_net_addr_ntop(sa_family_t family, const void *src,
+			   char *dst, size_t size)
+{
+	struct in_addr *addr;
+	struct in6_addr *addr6;
+	uint16_t *w;
+	uint8_t i, bl, bh, longest = 1U;
+	int8_t pos = -1;
+	char delim = ':';
+	unsigned char zeros[8] = { 0 };
+	char *ptr = dst;
+	int len = -1;
+	uint16_t value;
+	bool needcolon = false;
+
+	if (family == AF_INET6) {
+		addr6 = (struct in6_addr *)src;
+		w = (uint16_t *)addr6->s6_addr16;
+		len = 8;
+
+		for (i = 0U; i < 8; i++) {
+			uint8_t j;
+
+			for (j = i; j < 8; j++) {
+				if (UNALIGNED_GET(&w[j]) != 0) {
+					break;
+				}
+
+				zeros[i]++;
+			}
+		}
+
+		for (i = 0U; i < 8; i++) {
+			if (zeros[i] > longest) {
+				longest = zeros[i];
+				pos = i;
+			}
+		}
+
+		if (longest == 1U) {
+			pos = -1;
+		}
+
+	} else if (family == AF_INET) {
+		addr = (struct in_addr *)src;
+		len = 4;
+		delim = '.';
+	} else {
+		return NULL;
+	}
+
+	for (i = 0U; i < len; i++) {
+		/* IPv4 address a.b.c.d */
+		if (len == 4) {
+			uint8_t l;
+
+			value = (uint32_t)addr->s4_addr[i];
+
+			/* net_byte_to_udec() eats 0 */
+			if (value == 0U) {
+				*ptr++ = '0';
+				*ptr++ = delim;
+				continue;
+			}
+
+			l = net_value_to_udec(ptr, value, 0);
+
+			ptr += l;
+			*ptr++ = delim;
+
+			continue;
+		}
+
+		/* IPv6 address */
+		if (i == pos) {
+			if (needcolon || i == 0U) {
+				*ptr++ = ':';
+			}
+
+			*ptr++ = ':';
+			needcolon = false;
+			i += longest - 1U;
+
+			continue;
+		}
+
+		if (needcolon) {
+			*ptr++ = ':';
+			needcolon = false;
+		}
+
+		value = (uint32_t)sys_be16_to_cpu(UNALIGNED_GET(&w[i]));
+		bh = value >> 8;
+		bl = value & 0xff;
+
+		if (bh) {
+			if (bh > 0x0f) {
+				ptr = net_byte_to_hex(ptr, bh, 'a', false);
+			} else {
+				if (bh < 10) {
+					*ptr++ = (char)(bh + '0');
+				} else {
+					*ptr++ = (char) (bh - 10 + 'a');
+				}
+			}
+
+			ptr = net_byte_to_hex(ptr, bl, 'a', true);
+		} else if (bl > 0x0f) {
+			ptr = net_byte_to_hex(ptr, bl, 'a', false);
+		} else {
+			if (bl < 10) {
+				*ptr++ = (char)(bl + '0');
+			} else {
+				*ptr++ = (char) (bl - 10 + 'a');
+			}
+		}
+
+		needcolon = true;
+	}
+
+	if (!(ptr - dst)) {
+		return NULL;
+	}
+
+	if (family == AF_INET) {
+		*(ptr - 1) = '\0';
+	} else {
+		*ptr = '\0';
+	}
+
+	return dst;
+}
+
+#if defined(CONFIG_USERSPACE)
+char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src,
+			   char *dst, size_t size)
+{
+	char str[INET6_ADDRSTRLEN];
+	struct in6_addr addr6;
+	struct in_addr addr4;
+	char *out;
+	const void *addr;
+
+	Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
+
+	if (family == AF_INET) {
+		Z_OOPS(z_user_from_copy(&addr4, (const void *)src,
+					sizeof(addr4)));
+		addr = &addr4;
+	} else if (family == AF_INET6) {
+		Z_OOPS(z_user_from_copy(&addr6, (const void *)src,
+					sizeof(addr6)));
+		addr = &addr6;
+	} else {
+		return 0;
+	}
+
+	out = z_impl_net_addr_ntop(family, addr, str, sizeof(str));
+	if (!out) {
+		return 0;
+	}
+
+	Z_OOPS(z_user_to_copy((void *)dst, str, MIN(size, sizeof(str))));
+
+	return dst;
+}
+#include <syscalls/net_addr_ntop_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int z_impl_net_addr_pton(sa_family_t family, const char *src,
+			 void *dst)
+{
+	if (family == AF_INET) {
+		struct in_addr *addr = (struct in_addr *)dst;
+		size_t i, len;
+
+		len = strlen(src);
+		for (i = 0; i < len; i++) {
+			if (!(src[i] >= '0' && src[i] <= '9') &&
+			    src[i] != '.') {
+				return -EINVAL;
+			}
+		}
+
+		(void)memset(addr, 0, sizeof(struct in_addr));
+
+		for (i = 0; i < sizeof(struct in_addr); i++) {
+			char *endptr;
+
+			addr->s4_addr[i] = strtol(src, &endptr, 10);
+
+			src = ++endptr;
+		}
+
+	} else if (family == AF_INET6) {
+		/* If the string contains a '.', it means it's of the form
+		 * X:X:X:X:X:X:x.x.x.x, and contains only 6 16-bit pieces
+		 */
+		int expected_groups = strchr(src, '.') ? 6 : 8;
+		struct in6_addr *addr = (struct in6_addr *)dst;
+		int i, len;
+
+		if (*src == ':') {
+			/* Ignore a leading colon, makes parsing neater */
+			src++;
+		}
+
+		len = strlen(src);
+		for (i = 0; i < len; i++) {
+			if (!(src[i] >= '0' && src[i] <= '9') &&
+			    !(src[i] >= 'A' && src[i] <= 'F') &&
+			    !(src[i] >= 'a' && src[i] <= 'f') &&
+			    src[i] != '.' && src[i] != ':') {
+				return -EINVAL;
+			}
+		}
+
+		for (i = 0; i < expected_groups; i++) {
+			char *tmp;
+
+			if (!src || *src == '\0') {
+				return -EINVAL;
+			}
+
+			if (*src != ':') {
+				/* Normal IPv6 16-bit piece */
+				UNALIGNED_PUT(htons(strtol(src, NULL, 16)),
+					      &addr->s6_addr16[i]);
+				src = strchr(src, ':');
+				if (src) {
+					src++;
+				} else {
+					if (i < expected_groups - 1) {
+						return -EINVAL;
+					}
+				}
+
+				continue;
+			}
+
+			/* Two colons in a row */
+
+			for (; i < expected_groups; i++) {
+				UNALIGNED_PUT(0, &addr->s6_addr16[i]);
+			}
+
+			tmp = strrchr(src, ':');
+			if (src == tmp && (expected_groups == 6 || !src[1])) {
+				src++;
+				break;
+			}
+
+			if (expected_groups == 6) {
+				/* we need to drop the trailing
+				 * colon since it's between the
+				 * ipv6 and ipv4 addresses, rather than being
+				 * a part of the ipv6 address
+				 */
+				tmp--;
+			}
+
+			/* Calculate the amount of skipped zeros */
+			i = expected_groups - 1;
+			do {
+				if (*tmp == ':') {
+					i--;
+				}
+
+				if (i < 0) {
+					return -EINVAL;
+				}
+			} while (tmp-- != src);
+
+			src++;
+		}
+
+		if (expected_groups == 6) {
+			/* Parse the IPv4 part */
+			for (i = 0; i < 4; i++) {
+				if (!src || !*src) {
+					return -EINVAL;
+				}
+
+				addr->s6_addr[12 + i] = strtol(src, NULL, 10);
+
+				src = strchr(src, '.');
+				if (src) {
+					src++;
+				} else {
+					if (i < 3) {
+						return -EINVAL;
+					}
+				}
+			}
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_USERSPACE)
+int z_vrfy_net_addr_pton(sa_family_t family, const char *src,
+			 void *dst)
+{
+	char str[INET6_ADDRSTRLEN];
+	struct in6_addr addr6;
+	struct in_addr addr4;
+	void *addr;
+	size_t size;
+	size_t nlen;
+	int err;
+
+	if (family == AF_INET) {
+		size = sizeof(struct in_addr);
+		addr = &addr4;
+	} else if (family == AF_INET6) {
+		size = sizeof(struct in6_addr);
+		addr = &addr6;
+	} else {
+		return -EINVAL;
+	}
+
+	memset(str, 0, sizeof(str));
+
+	nlen = z_user_string_nlen((const char *)src, sizeof(str), &err);
+	if (err) {
+		return -EINVAL;
+	}
+
+	Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
+	Z_OOPS(Z_SYSCALL_MEMORY_READ(src, nlen));
+	Z_OOPS(z_user_from_copy(str, (const void *)src, nlen));
+
+	err = z_impl_net_addr_pton(family, str, addr);
+	if (err) {
+		return err;
+	}
+
+	Z_OOPS(z_user_to_copy((void *)dst, addr, size));
+
+	return 0;
+}
+#include <syscalls/net_addr_pton_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static uint16_t calc_chksum(uint16_t sum, const uint8_t *data, size_t len)
+{
+	const uint8_t *end;
+	uint16_t tmp;
+
+	end = data + len - 1;
+
+	while (data < end) {
+		tmp = (data[0] << 8) + data[1];
+		sum += tmp;
+		if (sum < tmp) {
+			sum++;
+		}
+
+		data += 2;
+	}
+
+	if (data == end) {
+		tmp = data[0] << 8;
+		sum += tmp;
+		if (sum < tmp) {
+			sum++;
+		}
+	}
+
+	return sum;
+}
+
+static inline uint16_t pkt_calc_chksum(struct net_pkt *pkt, uint16_t sum)
+{
+	struct net_pkt_cursor *cur = &pkt->cursor;
+	size_t len;
+
+	if (!cur->buf || !cur->pos) {
+		return sum;
+	}
+
+	len = cur->buf->len - (cur->pos - cur->buf->data);
+
+	while (cur->buf) {
+		sum = calc_chksum(sum, cur->pos, len);
+
+		cur->buf = cur->buf->frags;
+		if (!cur->buf || !cur->buf->len) {
+			break;
+		}
+
+		cur->pos = cur->buf->data;
+
+		if (len % 2) {
+			sum += *cur->pos;
+			if (sum < *cur->pos) {
+				sum++;
+			}
+
+			cur->pos++;
+			len = cur->buf->len - 1;
+		} else {
+			len = cur->buf->len;
+		}
+	}
+
+	return sum;
+}
+
+uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto)
+{
+	size_t len = 0U;
+	uint16_t sum = 0U;
+	struct net_pkt_cursor backup;
+	bool ow;
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		if (proto != IPPROTO_ICMP) {
+			len = 2 * sizeof(struct in_addr);
+			sum = net_pkt_get_len(pkt) -
+				net_pkt_ip_hdr_len(pkt) -
+				net_pkt_ipv4_opts_len(pkt) + proto;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		len = 2 * sizeof(struct in6_addr);
+		sum =  net_pkt_get_len(pkt) -
+			net_pkt_ip_hdr_len(pkt) -
+			net_pkt_ipv6_ext_len(pkt) + proto;
+	} else {
+		NET_DBG("Unknown protocol family %d", net_pkt_family(pkt));
+		return 0;
+	}
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+
+	ow = net_pkt_is_being_overwritten(pkt);
+	net_pkt_set_overwrite(pkt, true);
+
+	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) - len);
+
+	sum = calc_chksum(sum, pkt->cursor.pos, len);
+	net_pkt_skip(pkt, len + net_pkt_ip_opts_len(pkt));
+
+	sum = pkt_calc_chksum(pkt, sum);
+
+	sum = (sum == 0U) ? 0xffff : htons(sum);
+
+	net_pkt_cursor_restore(pkt, &backup);
+
+	net_pkt_set_overwrite(pkt, ow);
+
+	return ~sum;
+}
+
+#if defined(CONFIG_NET_IPV4)
+uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt)
+{
+	uint16_t sum;
+
+	sum = calc_chksum(0, pkt->buffer->data,
+			  net_pkt_ip_hdr_len(pkt) +
+			  net_pkt_ipv4_opts_len(pkt));
+
+	sum = (sum == 0U) ? 0xffff : htons(sum);
+
+	return ~sum;
+}
+#endif /* CONFIG_NET_IPV4 */
+
+#if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
+static bool convert_port(const char *buf, uint16_t *port)
+{
+	unsigned long tmp;
+	char *endptr;
+
+	tmp = strtoul(buf, &endptr, 10);
+	if ((endptr == buf && tmp == 0) ||
+	    !(*buf != '\0' && *endptr == '\0') ||
+	    ((unsigned long)(unsigned short)tmp != tmp)) {
+		return false;
+	}
+
+	*port = tmp;
+
+	return true;
+}
+#endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
+
+#if defined(CONFIG_NET_IPV6)
+static bool parse_ipv6(const char *str, size_t str_len,
+		       struct sockaddr *addr, bool has_port)
+{
+	char *ptr = NULL;
+	struct in6_addr *addr6;
+	char ipaddr[INET6_ADDRSTRLEN + 1];
+	int end, len, ret, i;
+	uint16_t port;
+
+	len = MIN(INET6_ADDRSTRLEN, str_len);
+
+	for (i = 0; i < len; i++) {
+		if (!str[i]) {
+			len = i;
+			break;
+		}
+	}
+
+	if (has_port) {
+		/* IPv6 address with port number */
+		ptr = memchr(str, ']', len);
+		if (!ptr) {
+			return false;
+		}
+
+		end = MIN(len, ptr - (str + 1));
+		memcpy(ipaddr, str + 1, end);
+	} else {
+		end = len;
+		memcpy(ipaddr, str, end);
+	}
+
+	ipaddr[end] = '\0';
+
+	addr6 = &net_sin6(addr)->sin6_addr;
+
+	ret = net_addr_pton(AF_INET6, ipaddr, addr6);
+	if (ret < 0) {
+		return false;
+	}
+
+	net_sin6(addr)->sin6_family = AF_INET6;
+
+	if (!has_port) {
+		return true;
+	}
+
+	if ((ptr + 1) < (str + str_len) && *(ptr + 1) == ':') {
+		/* -1 as end does not contain first [
+		 * -2 as pointer is advanced by 2, skipping ]:
+		 */
+		len = str_len - end - 1 - 2;
+
+		ptr += 2;
+
+		for (i = 0; i < len; i++) {
+			if (!ptr[i]) {
+				len = i;
+				break;
+			}
+		}
+
+		/* Re-use the ipaddr buf for port conversion */
+		memcpy(ipaddr, ptr, len);
+		ipaddr[len] = '\0';
+
+		ret = convert_port(ipaddr, &port);
+		if (!ret) {
+			return false;
+		}
+
+		net_sin6(addr)->sin6_port = htons(port);
+
+		NET_DBG("IPv6 host %s port %d",
+			log_strdup(net_addr_ntop(AF_INET6, addr6,
+						 ipaddr, sizeof(ipaddr) - 1)),
+			port);
+	} else {
+		NET_DBG("IPv6 host %s",
+			log_strdup(net_addr_ntop(AF_INET6, addr6,
+						 ipaddr, sizeof(ipaddr) - 1)));
+	}
+
+	return true;
+}
+#else
+static inline bool parse_ipv6(const char *str, size_t str_len,
+			      struct sockaddr *addr, bool has_port)
+{
+	return false;
+}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+static bool parse_ipv4(const char *str, size_t str_len,
+		       struct sockaddr *addr, bool has_port)
+{
+	char *ptr = NULL;
+	char ipaddr[NET_IPV4_ADDR_LEN + 1];
+	struct in_addr *addr4;
+	int end, len, ret, i;
+	uint16_t port;
+
+	len = MIN(NET_IPV4_ADDR_LEN, str_len);
+
+	for (i = 0; i < len; i++) {
+		if (!str[i]) {
+			len = i;
+			break;
+		}
+	}
+
+	if (has_port) {
+		/* IPv4 address with port number */
+		ptr = memchr(str, ':', len);
+		if (!ptr) {
+			return false;
+		}
+
+		end = MIN(len, ptr - str);
+	} else {
+		end = len;
+	}
+
+	memcpy(ipaddr, str, end);
+	ipaddr[end] = '\0';
+
+	addr4 = &net_sin(addr)->sin_addr;
+
+	ret = net_addr_pton(AF_INET, ipaddr, addr4);
+	if (ret < 0) {
+		return false;
+	}
+
+	net_sin(addr)->sin_family = AF_INET;
+
+	if (!has_port) {
+		return true;
+	}
+
+	memcpy(ipaddr, ptr + 1, str_len - end);
+	ipaddr[str_len - end] = '\0';
+
+	ret = convert_port(ipaddr, &port);
+	if (!ret) {
+		return false;
+	}
+
+	net_sin(addr)->sin_port = htons(port);
+
+	NET_DBG("IPv4 host %s port %d",
+		log_strdup(net_addr_ntop(AF_INET, addr4,
+					 ipaddr, sizeof(ipaddr) - 1)),
+		port);
+	return true;
+}
+#else
+static inline bool parse_ipv4(const char *str, size_t str_len,
+			      struct sockaddr *addr, bool has_port)
+{
+	return false;
+}
+#endif /* CONFIG_NET_IPV4 */
+
+bool net_ipaddr_parse(const char *str, size_t str_len, struct sockaddr *addr)
+{
+	int i, count;
+
+	if (!str || str_len == 0) {
+		return false;
+	}
+
+	/* We cannot accept empty string here */
+	if (*str == '\0') {
+		return false;
+	}
+
+	if (*str == '[') {
+		return parse_ipv6(str, str_len, addr, true);
+	}
+
+	for (count = i = 0; str[i] && i < str_len; i++) {
+		if (str[i] == ':') {
+			count++;
+		}
+	}
+
+	if (count == 1) {
+		return parse_ipv4(str, str_len, addr, true);
+	}
+
+#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
+	if (!parse_ipv4(str, str_len, addr, false)) {
+		return parse_ipv6(str, str_len, addr, false);
+	}
+
+	return true;
+#endif
+
+#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
+	return parse_ipv4(str, str_len, addr, false);
+#endif
+
+#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
+	return parse_ipv6(str, str_len, addr, false);
+#endif
+	return false;
+}
+
+int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src)
+{
+	unsigned int i;
+	char *endptr;
+
+	for (i = 0U; i < strlen(src); i++) {
+		if (!(src[i] >= '0' && src[i] <= '9') &&
+		    !(src[i] >= 'A' && src[i] <= 'F') &&
+		    !(src[i] >= 'a' && src[i] <= 'f') &&
+		    src[i] != ':') {
+			return -EINVAL;
+		}
+	}
+
+	(void)memset(buf, 0, buf_len);
+
+	for (i = 0U; i < buf_len; i++) {
+		buf[i] = strtol(src, &endptr, 16);
+		src = ++endptr;
+	}
+
+	return 0;
+}
+
+const char *net_family2str(sa_family_t family)
+{
+	switch (family) {
+	case AF_UNSPEC:
+		return "AF_UNSPEC";
+	case AF_INET:
+		return "AF_INET";
+	case AF_INET6:
+		return "AF_INET6";
+	case AF_PACKET:
+		return "AF_PACKET";
+	case AF_CAN:
+		return "AF_CAN";
+	}
+
+	return NULL;
+}
+
+const struct in_addr *net_ipv4_unspecified_address(void)
+{
+	static const struct in_addr addr;
+
+	return &addr;
+}
+
+const struct in_addr *net_ipv4_broadcast_address(void)
+{
+	static const struct in_addr addr = { { { 255, 255, 255, 255 } } };
+
+	return &addr;
+}
+
+/* IPv6 wildcard and loopback address defined by RFC2553 */
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+
+const struct in6_addr *net_ipv6_unspecified_address(void)
+{
+	return &in6addr_any;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/CMakeLists.txt	(working copy)
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: Apache-2.0
+
+if(CONFIG_NET_L2_BT OR CONFIG_NET_L2_BT_SHELL)
+  add_subdirectory(bluetooth)
+endif()
+
+if(CONFIG_NET_L2_DUMMY)
+  add_subdirectory(dummy)
+endif()
+
+if(CONFIG_NET_L2_ETHERNET)
+  add_subdirectory(ethernet)
+endif()
+
+if(CONFIG_NET_L2_PPP)
+  add_subdirectory(ppp)
+endif()
+
+if(CONFIG_NET_L2_IEEE802154)
+  add_subdirectory(ieee802154)
+endif()
+
+if(CONFIG_NET_L2_OPENTHREAD)
+  add_subdirectory(openthread)
+endif()
+
+if(CONFIG_NET_L2_WIFI_MGMT OR CONFIG_NET_L2_WIFI_SHELL)
+  add_subdirectory(wifi)
+endif()
+
+if(CONFIG_NET_L2_CANBUS OR CONFIG_NET_L2_CANBUS_RAW)
+  add_subdirectory(canbus)
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/Kconfig	(working copy)
@@ -0,0 +1,102 @@
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menu "Link layer options"
+
+config NET_L2_DUMMY
+	bool "Enable dummy l2 layer"
+	default y if !NET_L2_ETHERNET && NET_TEST
+	help
+	  Add a dummy L2 layer driver. This is usually only needed when
+	  simulating a network interface when running network stack inside QEMU.
+
+config NET_L2_BT
+	bool "Enable Bluetooth support"
+	depends on NET_IPV6
+	depends on BT
+	depends on BT_PERIPHERAL
+	depends on BT_CENTRAL
+	depends on BT_SMP
+	depends on BT_L2CAP_DYNAMIC_CHANNEL
+	select NET_6LO
+	help
+	  Enable Bluetooth driver that send and receives IPv6 packets,
+	  does header compression on it and writes it to the
+	  Bluetooth stack via L2CAP channel.
+
+if NET_L2_BT
+config NET_L2_BT_ZEP1656
+	bool "***Workaround to work with Linux.***"
+	help
+	  This workaround is necessary to interoperate with Linux up to 4.10 but
+	  it might not be compliant with RFC 7668 as it cause the stack to skip
+	  Neighbor Discovery cache causing the destination link address to be
+	  omitted. For more details why this is needed see:
+	  https://github.com/zephyrproject-rtos/zephyr/issues/3111
+
+config NET_L2_BT_SEC_LEVEL
+	int "Security level of Bluetooth Link"
+	default 1
+	range 1 4
+	help
+	  Security level of Bluetooth Link:
+	  Level 1 (BT_SECURITY_LOW) = No encryption or authentication required
+	  Level 2 (BT_SECURITY_MEDIUM) = Only encryption required
+	  Level 3 (BT_SECURITY_HIGH) = Encryption and authentication required
+	  Level 4 (BT_SECURITY_FIPS) = Secure connection required
+
+module = NET_L2_BT
+module-dep = NET_LOG
+module-str = Log level for Bluetooth L2 layer
+module-help = Enables Bluetooth L2 to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif
+
+config NET_L2_BT_MGMT
+	bool "Enable Bluetooth Network Management support"
+	depends on NET_L2_BT
+	select NET_MGMT
+	select NET_MGMT_EVENT
+
+config NET_L2_BT_SHELL
+	bool "Enable Bluetooth shell module"
+	select SHELL
+	select NET_L2_BT_MGMT
+	help
+	  This can be used for testing Bluetooth management commands through the
+	  console via a shell module named "net_bt".
+
+source "subsys/net/l2/ethernet/Kconfig"
+
+source "subsys/net/l2/ppp/Kconfig"
+
+source "subsys/net/l2/ieee802154/Kconfig"
+
+source "subsys/net/l2/openthread/Kconfig"
+
+source "subsys/net/l2/canbus/Kconfig"
+
+config NET_L2_WIFI_MGMT
+	bool "Enable Wi-Fi Management support"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	select NET_MGMT_EVENT_INFO
+	help
+	  Add support for Wi-Fi Management interface.
+
+if NET_L2_WIFI_MGMT
+module = NET_L2_WIFI_MGMT
+module-dep = NET_LOG
+module-str = Log level for Wi-Fi management layer
+module-help = Enables Wi-Fi management interface to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_L2_WIFI_MGMT
+
+config NET_L2_WIFI_SHELL
+	bool "Enable Wi-Fi shell module"
+	select NET_L2_WIFI_MGMT
+	help
+	  This can be used for controlling Wi-Fi through the console via
+	  exposing a shell module named "wifi".
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/CMakeLists.txt	(working copy)
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_BT       bluetooth.c)
+zephyr_library_sources_ifdef(CONFIG_NET_L2_BT_SHELL bluetooth_shell.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth.c	(working copy)
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_bt, CONFIG_NET_L2_BT_LOG_LEVEL);
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <linker/sections.h>
+#include <string.h>
+#include <errno.h>
+
+#include <device.h>
+#include <init.h>
+
+#include <net/net_pkt.h>
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/bt.h>
+#include <6lo.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/conn.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/l2cap.h>
+
+#include "net_private.h"
+#include "ipv6.h"
+
+#define BUF_TIMEOUT K_MSEC(50)
+
+#define L2CAP_IPSP_PSM 0x0023
+#define L2CAP_IPSP_MTU 1280
+
+#define CHAN_CONN(_conn) CONTAINER_OF(_conn, struct bt_if_conn, ipsp_chan.chan)
+
+#if defined(CONFIG_NET_L2_BT_MGMT)
+static struct bt_conn *default_conn;
+#endif
+
+#if defined(CONFIG_NET_L2_BT_SHELL)
+extern int net_bt_shell_init(void);
+#else
+#define net_bt_shell_init(...)
+#endif
+
+struct bt_if_conn {
+	struct net_if *iface;
+	struct bt_l2cap_le_chan ipsp_chan;
+	bt_addr_t src;
+	bt_addr_t dst;
+};
+
+struct bt_context {
+	struct bt_if_conn conns[CONFIG_BT_MAX_CONN];
+};
+
+static enum net_verdict net_bt_recv(struct net_if *iface, struct net_pkt *pkt)
+{
+	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));
+
+	if (!net_6lo_uncompress(pkt)) {
+		NET_DBG("Packet decompression failed");
+		return NET_DROP;
+	}
+
+	return NET_CONTINUE;
+}
+
+static struct bt_if_conn *net_bt_get_conn(struct net_if *iface)
+{
+	struct bt_context *ctxt = net_if_get_device(iface)->data;
+	int i;
+
+	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		if (ctxt->conns[i].iface == iface) {
+			return &ctxt->conns[i];
+		}
+	}
+
+	return NULL;
+}
+
+static int net_bt_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct bt_if_conn *conn = net_bt_get_conn(iface);
+	struct net_buf *buffer;
+	int length;
+	int ret;
+
+	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));
+
+	/* Only accept IPv6 packets */
+	if (net_pkt_family(pkt) != AF_INET6) {
+		return -EINVAL;
+	}
+
+	ret = net_6lo_compress(pkt, true);
+	if (ret < 0) {
+		NET_DBG("Packet compression failed");
+		return ret;
+	}
+
+	length = net_pkt_get_len(pkt);
+
+	/* Dettach data fragments for packet */
+	buffer = pkt->buffer;
+	pkt->buffer = NULL;
+
+	ret = bt_l2cap_chan_send(&conn->ipsp_chan.chan, buffer);
+	if (ret < 0) {
+		NET_ERR("Unable to send packet: %d", ret);
+		bt_l2cap_chan_disconnect(&conn->ipsp_chan.chan);
+		return ret;
+	}
+
+	net_pkt_unref(pkt);
+
+	return length;
+}
+
+static int net_bt_enable(struct net_if *iface, bool state)
+{
+	struct bt_if_conn *conn = net_bt_get_conn(iface);
+
+	NET_DBG("iface %p %s", iface, state ? "up" : "down");
+
+	if (state && conn->ipsp_chan.chan.state != BT_L2CAP_CONNECTED) {
+		return -ENETDOWN;
+	}
+
+	return 0;
+}
+
+static enum net_l2_flags net_bt_flags(struct net_if *iface)
+{
+	return NET_L2_MULTICAST | NET_L2_MULTICAST_SKIP_JOIN_SOLICIT_NODE;
+}
+
+NET_L2_INIT(BLUETOOTH_L2, net_bt_recv, net_bt_send,
+	    net_bt_enable, net_bt_flags);
+
+static void ipsp_connected(struct bt_l2cap_chan *chan)
+{
+	struct bt_if_conn *conn = CHAN_CONN(chan);
+	struct bt_conn_info info;
+	struct net_linkaddr ll;
+	struct in6_addr in6;
+
+	if (bt_conn_get_info(chan->conn, &info) < 0) {
+		NET_ERR("Unable to get connection info");
+		bt_l2cap_chan_disconnect(chan);
+		return;
+	}
+
+	if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		char src[BT_ADDR_LE_STR_LEN];
+		char dst[BT_ADDR_LE_STR_LEN];
+
+		bt_addr_le_to_str(info.le.src, src, sizeof(src));
+		bt_addr_le_to_str(info.le.dst, dst, sizeof(dst));
+
+		NET_DBG("Channel %p Source %s connected to Destination %s",
+			chan, log_strdup(src), log_strdup(dst));
+	}
+
+	/* Swap bytes since net APIs expect big endian address */
+	sys_memcpy_swap(conn->src.val, info.le.src->a.val, sizeof(conn->src));
+	sys_memcpy_swap(conn->dst.val, info.le.dst->a.val, sizeof(conn->dst));
+
+	net_if_set_link_addr(conn->iface, conn->src.val, sizeof(conn->src.val),
+			     NET_LINK_BLUETOOTH);
+
+	ll.addr = conn->dst.val;
+	ll.len = sizeof(conn->dst.val);
+	ll.type = NET_LINK_BLUETOOTH;
+
+	/* Add remote link-local address to the nbr cache to avoid sending ns:
+	 * https://tools.ietf.org/html/rfc7668#section-3.2.3
+	 * A Bluetooth LE 6LN MUST NOT register its link-local address.
+	 */
+	net_ipv6_addr_create_iid(&in6, &ll);
+	net_ipv6_nbr_add(conn->iface, &in6, &ll, false,
+			 NET_IPV6_NBR_STATE_STATIC);
+
+	/* Set iface up */
+	net_if_up(conn->iface);
+}
+
+static void ipsp_disconnected(struct bt_l2cap_chan *chan)
+{
+	struct bt_if_conn *conn = CHAN_CONN(chan);
+
+	NET_DBG("Channel %p disconnected", chan);
+
+	/* Set iface down */
+	net_if_carrier_down(conn->iface);
+
+#if defined(CONFIG_NET_L2_BT_MGMT)
+	if (chan->conn != default_conn) {
+		return;
+	}
+
+	bt_conn_unref(default_conn);
+	default_conn = NULL;
+#endif
+}
+
+static int ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
+{
+	struct bt_if_conn *conn = CHAN_CONN(chan);
+	struct net_pkt *pkt;
+
+	NET_DBG("Incoming data channel %p len %zu", chan,
+		net_buf_frags_len(buf));
+
+	/* Get packet for bearer / protocol related data */
+	pkt = net_pkt_rx_alloc_on_iface(conn->iface, BUF_TIMEOUT);
+	if (!pkt) {
+		return -ENOMEM;
+	}
+
+	/* Set destination address */
+	net_pkt_lladdr_dst(pkt)->addr = conn->src.val;
+	net_pkt_lladdr_dst(pkt)->len = sizeof(conn->src);
+	net_pkt_lladdr_dst(pkt)->type = NET_LINK_BLUETOOTH;
+
+	/* Set source address */
+	net_pkt_lladdr_src(pkt)->addr = conn->dst.val;
+	net_pkt_lladdr_src(pkt)->len = sizeof(conn->dst);
+	net_pkt_lladdr_src(pkt)->type = NET_LINK_BLUETOOTH;
+
+	/* Add data buffer as fragment of RX buffer, take a reference while
+	 * doing so since L2CAP will unref the buffer after return.
+	 */
+	net_pkt_append_buffer(pkt, net_buf_ref(buf));
+
+	if (net_recv_data(conn->iface, pkt) < 0) {
+		NET_DBG("Packet dropped by NET stack");
+		net_pkt_unref(pkt);
+	}
+
+	return 0;
+}
+
+static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)
+{
+	NET_DBG("Channel %p requires buffer", chan);
+
+	return net_pkt_get_reserve_rx_data(BUF_TIMEOUT);
+}
+
+static const struct bt_l2cap_chan_ops ipsp_ops = {
+	.alloc_buf	= ipsp_alloc_buf,
+	.recv		= ipsp_recv,
+	.connected	= ipsp_connected,
+	.disconnected	= ipsp_disconnected,
+};
+
+static struct bt_context bt_context_data = {
+	.conns[0 ... (CONFIG_BT_MAX_CONN - 1)] = {
+		.iface			= NULL,
+		.ipsp_chan.chan.ops	= &ipsp_ops,
+		.ipsp_chan.rx.mtu	= L2CAP_IPSP_MTU,
+	}
+};
+
+static void bt_iface_init(struct net_if *iface)
+{
+	struct bt_context *ctxt = net_if_get_device(iface)->data;
+	struct bt_if_conn *conn = NULL;
+	int i;
+
+	NET_DBG("iface %p", iface);
+
+	/* Find unused slot to store the iface */
+	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		if (!ctxt->conns[i].iface) {
+			conn = &ctxt->conns[i];
+			NET_DBG("[%d] alloc ctxt %p iface %p", i, ctxt, iface);
+			break;
+		}
+	}
+
+	if (!conn) {
+		NET_ERR("Unable to allocate iface");
+		return;
+	}
+
+	conn->iface = iface;
+
+	net_if_flag_set(iface, NET_IF_NO_AUTO_START);
+
+#if defined(CONFIG_NET_L2_BT_ZEP1656)
+	/* Workaround Linux bug, see:
+	 * https://github.com/zephyrproject-rtos/zephyr/issues/3111
+	 */
+	net_if_flag_set(iface, NET_IF_POINTOPOINT);
+#endif
+}
+
+static struct net_if_api bt_if_api = {
+	.init = bt_iface_init,
+};
+
+static int ipsp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
+{
+	struct bt_if_conn *if_conn = NULL;
+	int i;
+
+	NET_DBG("Incoming conn %p", conn);
+
+	/* Find unused slot to store the iface */
+	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		if (bt_context_data.conns[i].iface &&
+		    !bt_context_data.conns[i].ipsp_chan.chan.conn) {
+			if_conn = &bt_context_data.conns[i];
+			break;
+		}
+	}
+
+	if (!if_conn) {
+		NET_ERR("No channels available");
+		return -ENOMEM;
+	}
+
+	*chan = &if_conn->ipsp_chan.chan;
+
+	return 0;
+}
+
+static struct bt_l2cap_server server = {
+	.psm		= L2CAP_IPSP_PSM,
+	.sec_level	= CONFIG_NET_L2_BT_SEC_LEVEL,
+	.accept		= ipsp_accept,
+};
+
+#if defined(CONFIG_NET_L2_BT_MGMT)
+
+#define DEVICE_NAME		CONFIG_BT_DEVICE_NAME
+#define DEVICE_NAME_LEN		(sizeof(DEVICE_NAME) - 1)
+#define UNKNOWN_APPEARANCE	0x0000
+
+static const struct bt_data ad[] = {
+	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
+	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_IPSS_VAL)),
+};
+
+static const struct bt_data sd[] = {
+	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
+};
+
+static int bt_advertise(uint32_t mgmt_request, struct net_if *iface, void *data,
+		      size_t len)
+{
+	if (!strcmp(data, "on")) {
+		return bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
+				       sd, ARRAY_SIZE(sd));
+	} else if (!strcmp(data, "off")) {
+		return bt_le_adv_stop();
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bt_connect(uint32_t mgmt_request, struct net_if *iface, void *data,
+		      size_t len)
+{
+	struct bt_if_conn *conn = net_bt_get_conn(iface);
+	bt_addr_le_t *addr = data;
+
+	if (len != sizeof(*addr)) {
+		NET_ERR("Invalid address");
+		return -EINVAL;
+	}
+
+	if (conn->ipsp_chan.chan.conn) {
+		NET_ERR("No channels available");
+		return -ENOMEM;
+	}
+
+	if (default_conn) {
+		return bt_l2cap_chan_connect(default_conn,
+					     &conn->ipsp_chan.chan,
+					     L2CAP_IPSP_PSM);
+	}
+
+	return bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
+				 BT_LE_CONN_PARAM_DEFAULT, &default_conn);
+}
+
+static bool eir_found(uint8_t type, const uint8_t *data, uint8_t data_len,
+		      void *user_data)
+{
+	int i;
+
+	if (type != BT_DATA_UUID16_SOME && type != BT_DATA_UUID16_ALL) {
+		return false;
+	}
+
+	if (data_len % sizeof(uint16_t) != 0U) {
+		NET_ERR("AD malformed\n");
+		return false;
+	}
+
+	for (i = 0; i < data_len; i += sizeof(uint16_t)) {
+		struct bt_uuid *uuid;
+		uint16_t u16;
+
+		memcpy(&u16, &data[i], sizeof(u16));
+		uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16));
+		if (bt_uuid_cmp(uuid, BT_UUID_IPSS)) {
+			continue;
+		}
+
+		if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
+			bt_addr_le_t *addr = user_data;
+			char dev[BT_ADDR_LE_STR_LEN];
+
+			bt_addr_le_to_str(addr, dev, sizeof(dev));
+			NET_DBG("[DEVICE]: %s", log_strdup(dev));
+		}
+
+		/* TODO: Notify device address found */
+		net_mgmt_event_notify(NET_EVENT_BT_SCAN_RESULT,
+				      bt_context_data.conns[0].iface);
+
+		return true;
+	}
+
+	return false;
+}
+
+static bool ad_parse(struct net_buf_simple *ad,
+		     bool (*func)(uint8_t type, const uint8_t *data,
+				  uint8_t data_len, void *user_data),
+		     void *user_data)
+{
+	while (ad->len > 1) {
+		uint8_t len = net_buf_simple_pull_u8(ad);
+		uint8_t type;
+
+		/* Check for early termination */
+		if (len == 0U) {
+			return false;
+		}
+
+		if (len > ad->len) {
+			NET_ERR("AD malformed\n");
+			return false;
+		}
+
+		type = net_buf_simple_pull_u8(ad);
+
+		if (func(type, ad->data, len - 1, user_data)) {
+			return true;
+		}
+
+		net_buf_simple_pull(ad, len - 1);
+	}
+
+	return false;
+}
+
+static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
+			 struct net_buf_simple *ad)
+{
+	/* We're only interested in connectable events */
+	if (type == BT_GAP_ADV_TYPE_ADV_IND ||
+	    type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
+		ad_parse(ad, eir_found, (void *)addr);
+	}
+}
+
+static void bt_active_scan(void)
+{
+	int err;
+
+	err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
+	if (err) {
+		NET_ERR("Bluetooth set active scan failed (err %d)\n", err);
+	}
+}
+
+static void bt_passive_scan(void)
+{
+	int err;
+
+	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
+	if (err) {
+		NET_ERR("Bluetooth set passive scan failed (err %d)\n", err);
+	}
+}
+
+static void bt_scan_off(void)
+{
+	int err;
+
+	err = bt_le_scan_stop();
+	if (err) {
+		NET_ERR("Stopping scanning failed (err %d)\n", err);
+	}
+}
+
+static int bt_scan(uint32_t mgmt_request, struct net_if *iface, void *data,
+		   size_t len)
+{
+	if (!strcmp(data, "on") || !strcmp(data, "active")) {
+		bt_active_scan();
+	} else if (!strcmp(data, "passive")) {
+		bt_passive_scan();
+	} else if (!strcmp("off", data)) {
+		bt_scan_off();
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bt_disconnect(uint32_t mgmt_request, struct net_if *iface,
+			 void *data, size_t len)
+{
+	struct bt_if_conn *conn = net_bt_get_conn(iface);
+
+	if (!conn->ipsp_chan.chan.conn) {
+		NET_ERR("Not connected");
+		return -ENOTCONN;
+	}
+
+	/* Release connect reference in case of central/router role */
+	if (default_conn) {
+		bt_conn_unref(default_conn);
+		default_conn = NULL;
+	}
+
+	return bt_l2cap_chan_disconnect(&conn->ipsp_chan.chan);
+}
+
+static void connected(struct bt_conn *conn, uint8_t err)
+{
+	int i;
+
+	if (err) {
+		if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
+			char addr[BT_ADDR_LE_STR_LEN];
+
+			bt_addr_le_to_str(bt_conn_get_dst(conn), addr,
+					  sizeof(addr));
+
+			NET_ERR("Failed to connect to %s (%u)\n",
+				log_strdup(addr), err);
+		}
+
+		return;
+	}
+
+	if (conn != default_conn) {
+		return;
+	}
+
+	for (i = 0; i < CONFIG_BT_MAX_CONN; i++) {
+		struct bt_if_conn *if_conn = &bt_context_data.conns[i];
+
+		if (if_conn->ipsp_chan.chan.conn == conn) {
+			bt_l2cap_chan_connect(conn, &if_conn->ipsp_chan.chan,
+					      L2CAP_IPSP_PSM);
+			break;
+		}
+	}
+}
+
+static void disconnected(struct bt_conn *conn, uint8_t reason)
+{
+	if (conn != default_conn) {
+		return;
+	}
+
+	if (CONFIG_NET_L2_BT_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		char addr[BT_ADDR_LE_STR_LEN];
+
+		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
+
+		NET_DBG("Disconnected: %s (reason 0x%02x)\n",
+			log_strdup(addr), reason);
+	}
+
+	bt_conn_unref(default_conn);
+	default_conn = NULL;
+}
+
+static struct bt_conn_cb conn_callbacks = {
+	.connected = connected,
+	.disconnected = disconnected,
+};
+#endif /* CONFIG_NET_L2_BT_MGMT */
+
+static int net_bt_init(const struct device *dev)
+{
+	NET_DBG("dev %p driver_data %p", dev, dev->data);
+
+#if defined(CONFIG_NET_L2_BT_MGMT)
+	bt_conn_cb_register(&conn_callbacks);
+#endif
+	bt_l2cap_server_register(&server);
+
+	net_bt_shell_init();
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_L2_BT_MGMT)
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_ADVERTISE, bt_advertise);
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_CONNECT, bt_connect);
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_SCAN, bt_scan);
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_BT_DISCONNECT, bt_disconnect);
+#endif
+
+DEVICE_AND_API_INIT(net_bt, "net_bt", net_bt_init, &bt_context_data, NULL,
+		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+		    &bt_if_api);
+NET_L2_DATA_INIT(net_bt, 0, NET_L2_GET_CTX_TYPE(BLUETOOTH_L2));
+NET_IF_INIT(net_bt, 0, BLUETOOTH_L2, L2CAP_IPSP_MTU, CONFIG_BT_MAX_CONN);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth_shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth_shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/bluetooth/bluetooth_shell.c	(working copy)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_bt_shell, CONFIG_NET_L2_BT_LOG_LEVEL);
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <linker/sections.h>
+#include <string.h>
+#include <errno.h>
+
+#include <shell/shell.h>
+#include <sys/printk.h>
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/bt.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+static int shell_cmd_connect(const struct shell *shell,
+			     size_t argc, char *argv[])
+{
+	int err;
+	bt_addr_le_t addr;
+	struct net_if *iface = net_if_get_default();
+
+	if (argc < 3) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	err = bt_addr_le_from_str(argv[1], argv[2], &addr);
+	if (err) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Invalid peer address (err %d)\n", err);
+		return 0;
+	}
+
+	if (net_mgmt(NET_REQUEST_BT_CONNECT, iface, &addr, sizeof(addr))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Connection failed\n");
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Connection pending\n");
+	}
+
+	return 0;
+}
+
+static int shell_cmd_scan(const struct shell *shell,
+			  size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_BT_SCAN, iface, argv[1], strlen(argv[1]))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Scan failed\n");
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Scan in progress\n");
+	}
+
+	return 0;
+}
+
+static int shell_cmd_disconnect(const struct shell *shell,
+				size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+
+	if (net_mgmt(NET_REQUEST_BT_DISCONNECT, iface, NULL, 0)) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Disconnect failed\n");
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Disconnected\n");
+	}
+
+	return 0;
+}
+
+static int shell_cmd_advertise(const struct shell *shell,
+			       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_BT_ADVERTISE, iface, argv[1],
+		     strlen(argv[1]))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Advertise failed\n");
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Advertise in progress\n");
+	}
+
+	return 0;
+}
+
+SHELL_STATIC_SUBCMD_SET_CREATE(bt_commands,
+	SHELL_CMD(advertise, NULL,
+		  "on/off",
+		  shell_cmd_advertise),
+	SHELL_CMD(connect, NULL,
+		  "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>",
+		  shell_cmd_connect),
+	SHELL_CMD(scan, NULL,
+		  "<on/off/active/passive>",
+		  shell_cmd_scan),
+	SHELL_CMD(disconnect, NULL,
+		  "",
+		  shell_cmd_disconnect),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_CMD_REGISTER(net_bt, &bt_commands, "Net Bluetooth commands", NULL);
+
+void net_bt_shell_init(void)
+{
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/6locan.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/6locan.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/6locan.c	(working copy)
@@ -0,0 +1,1788 @@
+/*
+ * Copyright (c) 2019 Alexander Wachter.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_l2_canbus, CONFIG_NET_L2_CANBUS_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/can.h>
+#include "canbus_internal.h"
+#include <6lo.h>
+#include <timeout_q.h>
+#include <string.h>
+#include <sys/byteorder.h>
+#include <net/ethernet.h>
+#include <net/net_ip.h>
+#include <string.h>
+#include <random/rand32.h>
+
+#define NET_CAN_WFTMAX 2
+#define NET_CAN_ALLOC_TIMEOUT K_MSEC(100)
+
+/* Minimal separation time betwee frames */
+#define NET_CAN_STMIN CONFIG_NET_L2_CANBUS_STMIN
+#define NET_CAN_BS CONFIG_NET_L2_CANBUS_BS
+
+#define NET_CAN_DAD_SEND_RETRY 5
+#define NET_CAN_DAD_TIMEOUT K_MSEC(100)
+
+extern uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto);
+
+static struct canbus_l2_ctx l2_ctx;
+
+static struct k_work_q net_canbus_workq;
+K_KERNEL_STACK_DEFINE(net_canbus_stack, 512);
+
+char *net_sprint_addr(sa_family_t af, const void *addr);
+
+#if CONFIG_NET_L2_CANBUS_LOG_LEVEL >= LOG_LEVEL_DBG
+static void canbus_print_ip_hdr(struct net_ipv6_hdr *ip_hdr)
+{
+	uint8_t version = (ip_hdr->vtc >> 4);
+	uint8_t tc = ((ip_hdr->vtc & 0x0F) << 4) | ((ip_hdr->tcflow & 0xF0 >> 4));
+	uint32_t flow = ((ip_hdr->tcflow & 0x0F) << 16) | ip_hdr->flow;
+
+	NET_DBG("IP header: Version: 0x%x, TC: 0x%x, Flow Label: 0x%x, "
+		"Payload Length: %u, Next Header: 0x%x, Hop Limit: %u, "
+		"Src: %s, Dest: %s",
+		version, tc, flow, ntohs(ip_hdr->len), ip_hdr->nexthdr,
+		ip_hdr->hop_limit,
+		log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->src)),
+		log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->dst)));
+}
+#else
+#define canbus_print_ip_hdr(...)
+#endif
+
+static void canbus_free_tx_ctx(struct canbus_isotp_tx_ctx *ctx)
+{
+	k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER);
+	ctx->state = NET_CAN_TX_STATE_UNUSED;
+	k_mutex_unlock(&l2_ctx.tx_ctx_mtx);
+}
+
+static void canbus_free_rx_ctx(struct canbus_isotp_rx_ctx *ctx)
+{
+	k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER);
+	ctx->state = NET_CAN_RX_STATE_UNUSED;
+	k_mutex_unlock(&l2_ctx.rx_ctx_mtx);
+}
+
+static void canbus_tx_finish(struct net_pkt *pkt)
+{
+	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
+
+	if (ctx->state != NET_CAN_TX_STATE_RESET) {
+		z_abort_timeout(&ctx->timeout);
+	}
+
+	canbus_free_tx_ctx(ctx);
+	net_pkt_unref(pkt);
+	k_sem_give(&l2_ctx.tx_sem);
+}
+
+static void canbus_rx_finish(struct net_pkt *pkt)
+{
+	struct canbus_isotp_rx_ctx *ctx = pkt->canbus_rx_ctx;
+
+	canbus_free_rx_ctx(ctx);
+}
+
+static void canbus_tx_report_err(struct net_pkt *pkt)
+{
+	canbus_tx_finish(pkt);
+}
+
+static void canbus_rx_report_err(struct net_pkt *pkt)
+{
+	canbus_rx_finish(pkt);
+	net_pkt_unref(pkt);
+}
+
+static void rx_err_work_handler(struct k_work *item)
+{
+	struct net_pkt *pkt = CONTAINER_OF(item, struct net_pkt, work);
+
+	canbus_rx_report_err(pkt);
+}
+
+static void canbus_rx_report_err_from_isr(struct net_pkt *pkt)
+{
+	k_work_init(&pkt->work, rx_err_work_handler);
+	k_work_submit_to_queue(&net_canbus_workq, &pkt->work);
+}
+
+static void canbus_tx_timeout(struct _timeout *t)
+{
+	struct canbus_isotp_tx_ctx *ctx =
+		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
+
+	NET_ERR("TX Timeout. CTX: %p", ctx);
+	ctx->state = NET_CAN_TX_STATE_ERR;
+	k_work_submit_to_queue(&net_canbus_workq, &ctx->pkt->work);
+}
+
+static void canbus_rx_timeout(struct _timeout *t)
+{
+	struct canbus_isotp_rx_ctx *ctx =
+		CONTAINER_OF(t, struct canbus_isotp_rx_ctx, timeout);
+
+	NET_ERR("RX Timeout. CTX: %p", ctx);
+	ctx->state = NET_CAN_RX_STATE_TIMEOUT;
+	canbus_rx_report_err_from_isr(ctx->pkt);
+}
+
+static void canbus_st_min_timeout(struct _timeout *t)
+{
+	struct canbus_isotp_tx_ctx *ctx =
+		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
+
+	k_work_submit_to_queue(&net_canbus_workq, &ctx->pkt->work);
+}
+
+static k_timeout_t canbus_stmin_to_ticks(uint8_t stmin)
+{
+	/* According to ISO 15765-2 stmin should be 127ms if value is corrupt */
+	if (stmin > NET_CAN_STMIN_MAX ||
+	    (stmin > NET_CAN_STMIN_MS_MAX && stmin < NET_CAN_STMIN_US_BEGIN)) {
+		return K_MSEC(NET_CAN_STMIN_MS_MAX);
+	} else if (stmin >= NET_CAN_STMIN_US_BEGIN) {
+		return K_USEC((stmin + 1 - NET_CAN_STMIN_US_BEGIN) * 100U);
+	}
+
+	return K_MSEC(stmin);
+}
+
+static uint16_t canbus_get_lladdr(struct net_linkaddr *net_lladdr)
+{
+	NET_ASSERT(net_lladdr->len == sizeof(uint16_t));
+
+	return sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)net_lladdr->addr));
+}
+
+static uint16_t canbus_get_src_lladdr(struct net_pkt *pkt)
+{
+	return net_pkt_lladdr_src(pkt)->type == NET_LINK_CANBUS ?
+	       canbus_get_lladdr(net_pkt_lladdr_src(pkt)) :
+	       NET_CAN_ETH_TRANSLATOR_ADDR;
+}
+
+static uint16_t canbus_get_dest_lladdr(struct net_pkt *pkt)
+{
+	return net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS &&
+	       net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_canbus_lladdr) ?
+	       canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) :
+	       NET_CAN_ETH_TRANSLATOR_ADDR;
+}
+
+static inline bool canbus_dest_is_mcast(struct net_pkt *pkt)
+{
+	uint16_t lladdr_be = UNALIGNED_GET((uint16_t *)net_pkt_lladdr_dst(pkt)->addr);
+
+	return (sys_be16_to_cpu(lladdr_be) & CAN_NET_IF_IS_MCAST_BIT);
+}
+
+static bool canbus_src_is_translator(struct net_pkt *pkt)
+{
+	return ((canbus_get_src_lladdr(pkt) & CAN_NET_IF_ADDR_MASK) ==
+		NET_CAN_ETH_TRANSLATOR_ADDR);
+}
+
+static bool canbus_dest_is_translator(struct net_pkt *pkt)
+{
+	return (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET ||
+		net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_eth_addr));
+}
+
+#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
+static bool canbus_is_for_translator(struct net_pkt *pkt)
+{
+	return ((net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS) &&
+		(canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) ==
+		 NET_CAN_ETH_TRANSLATOR_ADDR));
+}
+#else
+#define canbus_is_for_translator(...) false
+#endif /* CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR */
+
+static size_t canbus_total_lladdr_len(struct net_pkt *pkt)
+{
+	/* This pkt will be farowarded to Ethernet
+	 * Destination MAC is carried inline, source is going to be extended
+	 */
+	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+	    canbus_is_for_translator(pkt)) {
+		return sizeof(struct net_eth_addr) +
+		       sizeof(struct net_canbus_lladdr);
+	}
+
+	return 2U * sizeof(struct net_canbus_lladdr);
+}
+
+static inline void canbus_cpy_lladdr(struct net_pkt *dst, struct net_pkt *src)
+{
+	struct net_linkaddr *lladdr;
+
+	lladdr = net_pkt_lladdr_dst(dst);
+	lladdr->addr = net_pkt_cursor_get_pos(dst);
+	net_pkt_write(dst, net_pkt_lladdr_dst(src)->addr,
+		      sizeof(struct net_canbus_lladdr));
+	lladdr->len = sizeof(struct net_canbus_lladdr);
+	lladdr->type = NET_LINK_CANBUS;
+
+	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+	    canbus_is_for_translator(src)) {
+		/* Make room for address extension */
+		net_pkt_skip(dst, sizeof(struct net_eth_addr) -
+			     sizeof(struct net_canbus_lladdr));
+	}
+
+	lladdr = net_pkt_lladdr_src(dst);
+	lladdr->addr = net_pkt_cursor_get_pos(dst);
+
+	if (canbus_src_is_translator(src)) {
+		net_pkt_copy(dst, src, sizeof(struct net_eth_addr));
+		lladdr->len = sizeof(struct net_eth_addr);
+		lladdr->type = NET_LINK_ETHERNET;
+		NET_DBG("Inline MAC: %02x:%02x:%02x:%02x:%02x:%02x",
+			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
+			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
+	} else {
+		net_pkt_write(dst, net_pkt_lladdr_src(src)->addr,
+			      sizeof(struct net_canbus_lladdr));
+		lladdr->len = sizeof(struct net_canbus_lladdr);
+		lladdr->type = NET_LINK_CANBUS;
+	}
+}
+
+
+static struct canbus_isotp_rx_ctx *canbus_get_rx_ctx(uint8_t state,
+						     uint16_t src_addr)
+{
+	int i;
+	struct canbus_isotp_rx_ctx *ret = NULL;
+
+	k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER);
+	for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) {
+		struct canbus_isotp_rx_ctx *ctx = &l2_ctx.rx_ctx[i];
+
+		if (ctx->state == state) {
+			if (state == NET_CAN_RX_STATE_UNUSED) {
+				ctx->state = NET_CAN_RX_STATE_RESET;
+				z_init_timeout(&ctx->timeout);
+				ret = ctx;
+				break;
+			}
+
+			if (canbus_get_src_lladdr(ctx->pkt) == src_addr) {
+				ret = ctx;
+				break;
+			}
+		}
+	}
+
+	k_mutex_unlock(&l2_ctx.rx_ctx_mtx);
+	return ret;
+}
+
+static struct canbus_isotp_tx_ctx *canbus_get_tx_ctx(uint8_t state,
+						     uint16_t dest_addr)
+{
+	int i;
+	struct canbus_isotp_tx_ctx *ret = NULL;
+
+	k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER);
+	for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) {
+		struct canbus_isotp_tx_ctx *ctx = &l2_ctx.tx_ctx[i];
+
+		if (ctx->state == state) {
+			if (state == NET_CAN_TX_STATE_UNUSED) {
+				ctx->state = NET_CAN_TX_STATE_RESET;
+				z_init_timeout(&ctx->timeout);
+				ret = ctx;
+				break;
+			}
+
+			if (ctx->dest_addr.addr == dest_addr) {
+				ret = ctx;
+				break;
+			}
+		}
+	}
+
+	k_mutex_unlock(&l2_ctx.tx_ctx_mtx);
+	return ret;
+}
+
+static inline uint16_t canbus_receive_get_ff_length(struct net_pkt *pkt)
+{
+	uint16_t len;
+	int ret;
+
+	ret = net_pkt_read_be16(pkt, &len);
+	if (ret < 0) {
+		NET_ERR("Can't read length");
+	}
+
+	return len & 0x0FFF;
+}
+
+static inline size_t canbus_get_sf_length(struct net_pkt *pkt)
+{
+	size_t len;
+
+	net_buf_pull_u8(pkt->frags);
+	len = net_buf_pull_u8(pkt->frags);
+
+	return len;
+}
+
+static inline void canbus_set_frame_datalength(struct zcan_frame *frame,
+					       uint8_t length)
+{
+	/* TODO: Needs update when CAN FD support is added */
+	NET_ASSERT(length <= NET_CAN_DL);
+	frame->dlc = length;
+}
+
+static enum net_verdict canbus_finish_pkt(struct net_pkt *pkt)
+{
+	/* Pull the ll addresses to ignore them in upper layers */
+	net_buf_pull(pkt->buffer, net_pkt_lladdr_dst(pkt)->len +
+		     net_pkt_lladdr_src(pkt)->len);
+
+	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+	    canbus_is_for_translator(pkt)) {
+		/* Pull room for address extension */
+		net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr) -
+			     net_pkt_lladdr_src(pkt)->len);
+		/* Set the destination address to the inline MAC and pull it */
+		net_pkt_cursor_init(pkt);
+		net_pkt_lladdr_dst(pkt)->addr = net_pkt_cursor_get_pos(pkt);
+		net_pkt_lladdr_dst(pkt)->type = NET_LINK_ETHERNET;
+		net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+		net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr));
+	}
+
+	net_pkt_cursor_init(pkt);
+	if (!net_6lo_uncompress(pkt)) {
+		NET_ERR("6lo uncompression failed");
+		return NET_DROP;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+	return NET_CONTINUE;
+}
+
+static inline uint32_t canbus_addr_to_id(uint16_t dest, uint16_t src)
+{
+	return (dest << CAN_NET_IF_ADDR_DEST_POS) |
+	       (src << CAN_NET_IF_ADDR_SRC_POS);
+}
+
+static void canbus_set_frame_addr(struct zcan_frame *frame,
+				  const struct net_canbus_lladdr *dest,
+				  const struct net_canbus_lladdr *src,
+				  bool mcast)
+{
+	frame->id_type = CAN_EXTENDED_IDENTIFIER;
+	frame->rtr = CAN_DATAFRAME;
+
+	frame->ext_id = canbus_addr_to_id(dest->addr, src->addr);
+
+	if (mcast) {
+		frame->ext_id |= CAN_NET_IF_ADDR_MCAST_MASK;
+	}
+}
+
+static void canbus_set_frame_addr_pkt(struct zcan_frame *frame,
+				      struct net_pkt *pkt,
+				      struct net_canbus_lladdr *dest_addr,
+				      bool mcast)
+{
+	struct net_canbus_lladdr src_addr;
+
+	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+	    net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) {
+		src_addr.addr = NET_CAN_ETH_TRANSLATOR_ADDR;
+	} else {
+		src_addr.addr = canbus_get_lladdr(net_if_get_link_addr(pkt->iface));
+	}
+
+	canbus_set_frame_addr(frame, dest_addr, &src_addr, mcast);
+}
+
+static void canbus_fc_send_cb(uint32_t err_flags, void *arg)
+{
+	if (err_flags) {
+		NET_ERR("Sending FC frame failed: %d", err_flags);
+	}
+}
+
+static int canbus_send_fc(const struct device *net_can_dev,
+			  struct net_canbus_lladdr *dest,
+			  struct net_canbus_lladdr *src, uint8_t fs)
+{
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_frame frame = {
+		.id_type = CAN_EXTENDED_IDENTIFIER,
+		.rtr = CAN_DATAFRAME,
+	};
+
+	NET_ASSERT(!(fs & NET_CAN_PCI_TYPE_MASK));
+
+	canbus_set_frame_addr(&frame, dest, src, false);
+
+	frame.data[0] = NET_CAN_PCI_TYPE_FC | fs;
+	/* BS (Block Size) */
+	frame.data[1] = NET_CAN_BS;
+	/* STmin (minimum Seperation Time) */
+	frame.data[2] = NET_CAN_STMIN;
+	canbus_set_frame_datalength(&frame, 3);
+
+	NET_DBG("Sending FC to ID: 0x%08x", frame.ext_id);
+	return api->send(net_can_dev, &frame, canbus_fc_send_cb, NULL,
+			 K_FOREVER);
+}
+
+static int canbus_process_cf_data(struct net_pkt *frag_pkt,
+				  struct canbus_isotp_rx_ctx *ctx)
+{
+	struct net_pkt *pkt = ctx->pkt;
+	size_t data_len = net_pkt_get_len(frag_pkt) - 1;
+	uint8_t pci;
+	int ret;
+
+	pci = net_buf_pull_u8(frag_pkt->frags);
+
+	if ((pci & NET_CAN_PCI_SN_MASK) != ctx->sn) {
+		NET_ERR("Sequence number missmatch. Expect %u, got %u",
+			ctx->sn, pci & NET_CAN_PCI_SN_MASK);
+		goto err;
+	}
+
+	ctx->sn++;
+
+	if (data_len > ctx->rem_len) {
+		NET_DBG("Remove padding of %d bytes", data_len - ctx->rem_len);
+		data_len = ctx->rem_len;
+	}
+
+	net_pkt_cursor_init(frag_pkt);
+	NET_DBG("Appending CF data to pkt (%d bytes)", data_len);
+	ret = net_pkt_copy(pkt, frag_pkt, data_len);
+	if (ret < 0) {
+		NET_ERR("Failed to write data to pkt [%d]", ret);
+		goto err;
+	}
+
+	ctx->rem_len -= data_len;
+
+	NET_DBG("%u bytes remaining", ctx->rem_len);
+
+	return 0;
+err:
+	canbus_rx_report_err(pkt);
+	return -1;
+}
+
+static enum net_verdict canbus_process_cf(struct net_pkt *pkt)
+{
+	struct canbus_isotp_rx_ctx *rx_ctx;
+	enum net_verdict ret;
+	const struct device *net_can_dev;
+	struct net_canbus_lladdr src, dest;
+	bool mcast;
+
+	mcast = canbus_dest_is_mcast(pkt);
+
+	rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_CF,
+				   canbus_get_src_lladdr(pkt));
+	if (!rx_ctx) {
+		NET_INFO("Got CF but can't find a CTX that is waiting for it. "
+			 "Src: 0x%04x", canbus_get_src_lladdr(pkt));
+		return NET_DROP;
+	}
+
+	z_abort_timeout(&rx_ctx->timeout);
+
+	ret = canbus_process_cf_data(pkt, rx_ctx);
+	if (ret < 0) {
+		return NET_DROP;
+	}
+
+	net_pkt_unref(pkt);
+
+	if (rx_ctx->rem_len == 0) {
+		rx_ctx->state = NET_CAN_RX_STATE_FIN;
+		ret = net_recv_data(pkt->iface, rx_ctx->pkt);
+		if (ret < 0) {
+			NET_ERR("Packet dropped by NET stack");
+			net_pkt_unref(pkt);
+		}
+	} else {
+		z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout,
+			      NET_CAN_BS_TIME);
+
+		if (NET_CAN_BS != 0 && !mcast) {
+			rx_ctx->act_block_nr++;
+			if (rx_ctx->act_block_nr >= NET_CAN_BS) {
+				NET_DBG("BS reached. Send FC");
+				src.addr = canbus_get_src_lladdr(pkt);
+				dest.addr = canbus_get_dest_lladdr(pkt);
+				net_can_dev = net_if_get_device(pkt->iface);
+				ret = canbus_send_fc(net_can_dev, &src, &dest,
+						     NET_CAN_PCI_FS_CTS);
+				if (ret) {
+					NET_ERR("Failed to send FC CTS. BS: %d",
+						NET_CAN_BS);
+					canbus_rx_report_err(rx_ctx->pkt);
+					return NET_OK;
+				}
+
+				rx_ctx->act_block_nr = 0;
+			}
+		}
+	}
+
+	return NET_OK;
+}
+
+static enum net_verdict canbus_process_ff(struct net_pkt *pkt)
+{
+	const struct device *net_can_dev = net_if_get_device(pkt->iface);
+	struct canbus_isotp_rx_ctx *rx_ctx = NULL;
+	struct net_pkt *new_pkt = NULL;
+	int ret;
+	struct net_canbus_lladdr src, dest;
+	uint16_t msg_len;
+	size_t new_pkt_len;
+	uint8_t data_len;
+	bool mcast;
+
+	mcast = canbus_dest_is_mcast(pkt);
+	src.addr = canbus_get_src_lladdr(pkt);
+	dest.addr = canbus_get_dest_lladdr(pkt);
+	net_pkt_cursor_init(pkt);
+
+	msg_len = canbus_receive_get_ff_length(pkt);
+
+	new_pkt_len = msg_len + canbus_total_lladdr_len(pkt);
+
+	new_pkt = net_pkt_rx_alloc_with_buffer(pkt->iface, new_pkt_len,
+					       AF_INET6, 0,
+					       NET_CAN_ALLOC_TIMEOUT);
+	if (!new_pkt) {
+		NET_ERR("Failed to obtain net_pkt with size of %d", new_pkt_len);
+
+		if (!mcast) {
+			canbus_send_fc(net_can_dev, &src, &dest,
+				       NET_CAN_PCI_FS_OVFLW);
+		}
+
+		goto err;
+	}
+
+	rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_UNUSED, 0);
+	if (!rx_ctx) {
+		NET_ERR("No rx context left");
+
+		if (!mcast) {
+			canbus_send_fc(net_can_dev, &src, &dest,
+				       NET_CAN_PCI_FS_OVFLW);
+		}
+
+		goto err;
+	}
+
+	rx_ctx->act_block_nr = 0;
+	rx_ctx->pkt = new_pkt;
+	new_pkt->canbus_rx_ctx = rx_ctx;
+
+	net_pkt_cursor_init(new_pkt);
+	data_len = net_pkt_remaining_data(pkt);
+	canbus_cpy_lladdr(new_pkt, pkt);
+	rx_ctx->sn = 1;
+
+	ret = net_pkt_copy(new_pkt, pkt, net_pkt_remaining_data(pkt));
+	if (ret) {
+		NET_ERR("Failed to write to pkt [%d]", ret);
+		goto err;
+	}
+
+	rx_ctx->rem_len = msg_len - data_len;
+	net_pkt_unref(pkt);
+
+	if (!mcast) {
+		/* switch src and dest because we are answering */
+		ret = canbus_send_fc(net_can_dev, &src, &dest,
+				     NET_CAN_PCI_FS_CTS);
+		if (ret) {
+			NET_ERR("Failed to send FC CTS");
+			canbus_rx_report_err(new_pkt);
+			return NET_OK;
+		}
+	}
+
+	/* At this point we expect to get Consecutive frames directly */
+	z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout, NET_CAN_BS_TIME);
+
+	rx_ctx->state = NET_CAN_RX_STATE_CF;
+
+	NET_DBG("Processed FF from 0x%04x (%scast)"
+		"Msg length: %u CTX: %p",
+		src.addr, mcast ? "m" : "uni", msg_len, rx_ctx);
+
+	return NET_OK;
+
+err:
+	if (new_pkt) {
+		net_pkt_unref(new_pkt);
+	}
+
+	if (rx_ctx) {
+		canbus_free_rx_ctx(rx_ctx);
+	}
+
+	return NET_DROP;
+}
+
+static enum net_verdict canbus_process_sf(struct net_pkt *pkt)
+{
+	size_t data_len;
+	size_t pkt_len;
+
+	net_pkt_set_family(pkt, AF_INET6);
+
+	data_len = canbus_get_sf_length(pkt);
+	pkt_len = net_pkt_get_len(pkt);
+
+	if (data_len > pkt_len) {
+		NET_ERR("SF datalen > pkt size");
+		return NET_DROP;
+	}
+
+	if (pkt_len != data_len) {
+		NET_DBG("Remove padding (%d byte)", pkt_len - data_len);
+		net_pkt_update_length(pkt, data_len);
+	}
+
+	return canbus_finish_pkt(pkt);
+}
+
+static void canbus_tx_frame_isr(uint32_t err_flags, void *arg)
+{
+	struct net_pkt *pkt = (struct net_pkt *)arg;
+	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
+
+	ctx->tx_backlog--;
+
+	if (ctx->state == NET_CAN_TX_STATE_WAIT_TX_BACKLOG) {
+		if (ctx->tx_backlog > 0) {
+			return;
+		}
+
+		ctx->state = NET_CAN_TX_STATE_FIN;
+	}
+
+	k_work_submit_to_queue(&net_canbus_workq, &pkt->work);
+}
+
+static inline int canbus_send_cf(struct net_pkt *pkt)
+{
+	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
+	const struct device *net_can_dev = net_if_get_device(pkt->iface);
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_frame frame;
+	struct net_pkt_cursor cursor_backup;
+	int ret, len;
+
+	canbus_set_frame_addr_pkt(&frame, pkt, &ctx->dest_addr, ctx->is_mcast);
+
+	/* sn wraps around at 0xF automatically because it has a 4 bit size */
+	frame.data[0] = NET_CAN_PCI_TYPE_CF | ctx->sn;
+
+	len = MIN(ctx->rem_len, NET_CAN_DL - 1);
+
+	canbus_set_frame_datalength(&frame, len + 1);
+
+	net_pkt_cursor_backup(pkt, &cursor_backup);
+	net_pkt_read(pkt, &frame.data[1], len);
+	ret = api->send(net_can_dev, &frame, canbus_tx_frame_isr,
+			pkt, K_NO_WAIT);
+	if (ret == CAN_TX_OK) {
+		ctx->sn++;
+		ctx->rem_len -= len;
+		ctx->act_block_nr--;
+		ctx->tx_backlog++;
+	} else {
+		net_pkt_cursor_restore(pkt, &cursor_backup);
+	}
+
+	NET_DBG("CF sent. %d bytes left. CTX: %p", ctx->rem_len, ctx);
+
+	return ret ? ret : ctx->rem_len;
+}
+
+static void canbus_tx_work(struct net_pkt *pkt)
+{
+	int ret;
+	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
+
+	NET_ASSERT(ctx);
+
+	switch (ctx->state) {
+	case NET_CAN_TX_STATE_SEND_CF:
+		do {
+			ret = canbus_send_cf(ctx->pkt);
+			if (!ret) {
+				ctx->state = NET_CAN_TX_STATE_WAIT_TX_BACKLOG;
+				break;
+			}
+
+			if (ret < 0 && ret != CAN_TIMEOUT) {
+				NET_ERR("Failed to send CF. CTX: %p", ctx);
+				canbus_tx_report_err(pkt);
+				break;
+			}
+
+			if (ctx->opts.bs && !ctx->is_mcast &&
+			    !ctx->act_block_nr) {
+				NET_DBG("BS reached. Wait for FC again. CTX: %p",
+					ctx);
+				ctx->state = NET_CAN_TX_STATE_WAIT_FC;
+				z_add_timeout(&ctx->timeout, canbus_tx_timeout,
+					      NET_CAN_BS_TIME);
+				break;
+			} else if (ctx->opts.stmin) {
+				ctx->state = NET_CAN_TX_STATE_WAIT_ST;
+				break;
+			}
+		} while (ret > 0);
+
+		break;
+
+	case NET_CAN_TX_STATE_WAIT_ST:
+		NET_DBG("SM wait ST. CTX: %p", ctx);
+		z_add_timeout(&ctx->timeout, canbus_st_min_timeout,
+			      canbus_stmin_to_ticks(ctx->opts.stmin));
+		ctx->state = NET_CAN_TX_STATE_SEND_CF;
+		break;
+
+	case NET_CAN_TX_STATE_ERR:
+		NET_DBG("SM handle error. CTX: %p", ctx);
+		canbus_tx_report_err(pkt);
+		break;
+
+	case NET_CAN_TX_STATE_FIN:
+		canbus_tx_finish(ctx->pkt);
+		NET_DBG("SM finish. CTX: %p", ctx);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void canbus_tx_work_handler(struct k_work *item)
+{
+	struct net_pkt *pkt = CONTAINER_OF(item, struct net_pkt, work);
+
+	canbus_tx_work(pkt);
+}
+
+static enum net_verdict canbus_process_fc_data(struct canbus_isotp_tx_ctx *ctx,
+					       struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->frags;
+	uint8_t pci;
+
+	pci = net_buf_pull_u8(buf);
+
+	switch (pci & NET_CAN_PCI_FS_MASK) {
+	case NET_CAN_PCI_FS_CTS:
+		if (net_buf_frags_len(buf) != 2) {
+			NET_ERR("Frame length error for CTS");
+			canbus_tx_report_err(pkt);
+			return NET_DROP;
+		}
+
+		ctx->state = NET_CAN_TX_STATE_SEND_CF;
+		ctx->wft = 0;
+		ctx->opts.bs = net_buf_pull_u8(buf);
+		ctx->opts.stmin = net_buf_pull_u8(buf);
+		ctx->act_block_nr = ctx->opts.bs;
+		z_abort_timeout(&ctx->timeout);
+		NET_DBG("Got CTS. BS: %d, STmin: %d. CTX: %p",
+			ctx->opts.bs, ctx->opts.stmin, ctx);
+		net_pkt_unref(pkt);
+		return NET_OK;
+	case NET_CAN_PCI_FS_WAIT:
+		NET_DBG("Got WAIT frame. CTX: %p", ctx);
+		z_abort_timeout(&ctx->timeout);
+		z_add_timeout(&ctx->timeout, canbus_tx_timeout,
+			      NET_CAN_BS_TIME);
+		if (ctx->wft >= NET_CAN_WFTMAX) {
+			NET_INFO("Got to many wait frames. CTX: %p", ctx);
+			ctx->state = NET_CAN_TX_STATE_ERR;
+		}
+
+		ctx->wft++;
+		return NET_OK;
+	case NET_CAN_PCI_FS_OVFLW:
+		NET_ERR("Got overflow FC frame. CTX: %p", ctx);
+		ctx->state = NET_CAN_TX_STATE_ERR;
+		return NET_OK;
+	default:
+		NET_ERR("Invalid Frame Status. CTX: %p", ctx);
+		ctx->state = NET_CAN_TX_STATE_ERR;
+		break;
+	}
+
+	return NET_DROP;
+}
+
+static enum net_verdict canbus_process_fc(struct net_pkt *pkt)
+{
+	struct canbus_isotp_tx_ctx *tx_ctx;
+	uint16_t src_addr = canbus_get_src_lladdr(pkt);
+	enum net_verdict ret;
+
+	tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_WAIT_FC, src_addr);
+	if (!tx_ctx) {
+		NET_WARN("Got FC frame from 0x%04x but can't find any "
+			 "CTX waiting for it", src_addr);
+		return NET_DROP;
+	}
+
+	ret = canbus_process_fc_data(tx_ctx, pkt);
+	if (ret == NET_OK) {
+		k_work_submit_to_queue(&net_canbus_workq, &tx_ctx->pkt->work);
+	}
+
+	return ret;
+}
+
+static inline int canbus_send_ff(struct net_pkt *pkt, size_t len, bool mcast,
+				 struct net_canbus_lladdr *dest_addr)
+{
+	const struct device *net_can_dev = net_if_get_device(pkt->iface);
+	const struct net_can_api *api = net_can_dev->api;
+	struct net_linkaddr *lladdr_inline;
+	struct zcan_frame frame;
+	int ret, index = 0;
+
+	canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast);
+	canbus_set_frame_datalength(&frame, NET_CAN_DL);
+
+	if (mcast) {
+		NET_DBG("Sending FF (multicast). ID: 0x%08x. PKT len: %zu"
+			" CTX: %p",
+			frame.ext_id, len, pkt->canbus_tx_ctx);
+	} else {
+		NET_DBG("Sending FF (unicast). ID: 0x%08x. PKT len: %zu"
+			" CTX: %p",
+			frame.ext_id, len, pkt->canbus_tx_ctx);
+	}
+
+#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
+	NET_ASSERT(mcast || !(canbus_dest_is_translator(pkt) &&
+			      canbus_src_is_translator(pkt)));
+
+	if (canbus_src_is_translator(pkt)) {
+		len += net_pkt_lladdr_src(pkt)->len;
+	}
+#endif
+	if (!mcast && canbus_dest_is_translator(pkt)) {
+		len += net_pkt_lladdr_dst(pkt)->len;
+	}
+
+	frame.data[index++] = NET_CAN_PCI_TYPE_FF | (len >> 8);
+	frame.data[index++] = len & 0xFF;
+
+	/* According to ISO, FF has sn 0 and is incremented to one
+	 * alltough it's not part of the FF frame
+	 */
+	pkt->canbus_tx_ctx->sn = 1;
+
+	if (!mcast && canbus_dest_is_translator(pkt)) {
+		lladdr_inline = net_pkt_lladdr_dst(pkt);
+		memcpy(&frame.data[index], lladdr_inline->addr,
+		       lladdr_inline->len);
+		index += lladdr_inline->len;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+	    net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) {
+		lladdr_inline = net_pkt_lladdr_src(pkt);
+		memcpy(&frame.data[index], lladdr_inline->addr,
+		       lladdr_inline->len);
+		index += lladdr_inline->len;
+	}
+
+	net_pkt_read(pkt, &frame.data[index], NET_CAN_DL - index);
+	pkt->canbus_tx_ctx->rem_len -= NET_CAN_DL - index;
+
+	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
+	if (ret != CAN_TX_OK) {
+		NET_ERR("Sending FF failed [%d]. CTX: %p",
+			ret, pkt->canbus_tx_ctx);
+	}
+
+	return ret;
+}
+
+static inline int canbus_send_single_frame(struct net_pkt *pkt, size_t len,
+					   bool mcast,
+					   struct net_canbus_lladdr *dest_addr)
+{
+	const struct device *net_can_dev = net_if_get_device(pkt->iface);
+	const struct net_can_api *api = net_can_dev->api;
+	int index = 0;
+	struct zcan_frame frame;
+	struct net_linkaddr *lladdr_dest;
+	int ret;
+
+	canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast);
+
+	frame.data[index++] = NET_CAN_PCI_TYPE_SF;
+	frame.data[index++] = len;
+
+	NET_ASSERT((len + (!mcast && canbus_dest_is_translator(pkt)) ?
+		    net_pkt_lladdr_dst(pkt)->len : 0) <= NET_CAN_DL - 1);
+
+	if (!mcast && canbus_dest_is_translator(pkt)) {
+		lladdr_dest = net_pkt_lladdr_dst(pkt);
+		memcpy(&frame.data[index], lladdr_dest->addr, lladdr_dest->len);
+		index += lladdr_dest->len;
+	}
+
+	net_pkt_read(pkt, &frame.data[index], len);
+
+	canbus_set_frame_datalength(&frame, len + index);
+
+	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
+	if (ret != CAN_TX_OK) {
+		NET_ERR("Sending SF failed [%d]", ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void canbus_start_sending_cf(struct _timeout *t)
+{
+	struct canbus_isotp_tx_ctx *ctx =
+		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
+
+	k_work_submit_to_queue(&net_canbus_workq, &ctx->pkt->work);
+}
+
+static int canbus_send_multiple_frames(struct net_pkt *pkt, size_t len,
+				       bool mcast,
+				       struct net_canbus_lladdr *dest_addr)
+{
+	struct canbus_isotp_tx_ctx *tx_ctx = NULL;
+	int ret;
+
+	tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_UNUSED, 0);
+
+	if (!tx_ctx) {
+		NET_ERR("No tx context left");
+		k_sem_give(&l2_ctx.tx_sem);
+		return -EAGAIN;
+	}
+
+	tx_ctx->pkt = pkt;
+	pkt->canbus_tx_ctx = tx_ctx;
+	tx_ctx->is_mcast = mcast;
+	tx_ctx->dest_addr = *dest_addr;
+	tx_ctx->rem_len = net_pkt_get_len(pkt);
+	tx_ctx->tx_backlog = 0;
+
+	k_work_init(&pkt->work, canbus_tx_work_handler);
+
+	ret = canbus_send_ff(pkt, len, mcast, dest_addr);
+	if (ret != CAN_TX_OK) {
+		NET_ERR("Failed to send FF [%d]", ret);
+		canbus_tx_report_err(pkt);
+		return -EIO;
+	}
+
+	if (!mcast) {
+		z_add_timeout(&tx_ctx->timeout, canbus_tx_timeout,
+			      NET_CAN_BS_TIME);
+		tx_ctx->state = NET_CAN_TX_STATE_WAIT_FC;
+	} else {
+		tx_ctx->state = NET_CAN_TX_STATE_SEND_CF;
+		z_add_timeout(&tx_ctx->timeout, canbus_start_sending_cf,
+			      NET_CAN_FF_CF_TIME);
+	}
+
+	return 0;
+}
+
+static void canbus_ipv6_mcast_to_dest(struct net_pkt *pkt,
+				      struct net_canbus_lladdr *dest_addr)
+{
+	dest_addr->addr =
+		sys_be16_to_cpu(UNALIGNED_GET(&NET_IPV6_HDR(pkt)->dst.s6_addr16[7]));
+}
+
+static inline uint16_t canbus_eth_to_can_addr(struct net_linkaddr *lladdr)
+{
+	return (sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&lladdr->addr[4])) &
+		CAN_NET_IF_ADDR_MASK);
+}
+
+static int canbus_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	int ret = 0;
+	int comp_len;
+	size_t pkt_len, inline_lladdr_len;
+	struct net_canbus_lladdr dest_addr;
+	bool mcast;
+
+	if (net_pkt_family(pkt) != AF_INET6) {
+		return -EINVAL;
+	}
+
+	mcast = net_ipv6_is_addr_mcast(&NET_IPV6_HDR(pkt)->dst);
+	if (mcast || canbus_dest_is_mcast(pkt)) {
+		canbus_ipv6_mcast_to_dest(pkt, &dest_addr);
+	} else if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
+		   net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) {
+		struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt);
+
+		lladdr->type = NET_LINK_CANBUS;
+		lladdr->len = sizeof(struct net_canbus_lladdr);
+		dest_addr.addr = canbus_eth_to_can_addr(net_pkt_lladdr_dst(pkt));
+		NET_DBG("Translated %02x:%02x:%02x:%02x:%02x:%02x to 0x%04x",
+			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
+			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5],
+			dest_addr.addr);
+	} else {
+		dest_addr.addr = canbus_get_dest_lladdr(pkt);
+	}
+
+	net_pkt_cursor_init(pkt);
+	canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt));
+	comp_len = net_6lo_compress(pkt, true);
+	if (comp_len < 0) {
+		NET_ERR("IPHC failed [%d]", comp_len);
+		return comp_len;
+	}
+
+	NET_DBG("IPv6 hdr compressed by %d bytes", comp_len);
+	net_pkt_cursor_init(pkt);
+	pkt_len = net_pkt_get_len(pkt);
+
+	NET_DBG("Send CAN frame to 0x%04x%s", dest_addr.addr,
+		mcast ? " (mcast)" : "");
+
+	inline_lladdr_len = (!mcast && canbus_dest_is_translator(pkt)) ?
+			    net_pkt_lladdr_dst(pkt)->len : 0;
+
+	if ((pkt_len + inline_lladdr_len) > (NET_CAN_DL - 1)) {
+		k_sem_take(&l2_ctx.tx_sem, K_FOREVER);
+		ret = canbus_send_multiple_frames(pkt, pkt_len, mcast,
+						  &dest_addr);
+	} else {
+		ret = canbus_send_single_frame(pkt, pkt_len, mcast, &dest_addr);
+		canbus_tx_finish(pkt);
+	}
+
+	return ret;
+}
+
+static enum net_verdict canbus_process_frame(struct net_pkt *pkt)
+{
+	enum net_verdict ret = NET_DROP;
+	uint8_t pci_type;
+
+	net_pkt_cursor_init(pkt);
+	ret = net_pkt_read_u8(pkt, &pci_type);
+	if (ret < 0) {
+		NET_ERR("Can't read PCI");
+	}
+	pci_type = (pci_type & NET_CAN_PCI_TYPE_MASK) >> NET_CAN_PCI_TYPE_POS;
+
+	switch (pci_type) {
+	case NET_CAN_PCI_SF:
+		ret = canbus_process_sf(pkt);
+		break;
+	case NET_CAN_PCI_FF:
+		ret = canbus_process_ff(pkt);
+		break;
+	case NET_CAN_PCI_CF:
+		ret = canbus_process_cf(pkt);
+		break;
+	case NET_CAN_PCI_FC:
+		ret = canbus_process_fc(pkt);
+		break;
+	default:
+		NET_ERR("Unknown PCI number %u", pci_type);
+		break;
+	}
+
+	return ret;
+}
+
+#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
+static void forward_eth_frame(struct net_pkt *pkt, struct net_if *canbus_iface)
+{
+	pkt->iface = canbus_iface;
+	net_if_queue_tx(canbus_iface, pkt);
+}
+
+static struct net_ipv6_hdr *get_ip_hdr_from_eth_frame(struct net_pkt *pkt)
+{
+	return (struct net_ipv6_hdr *)((uint8_t *)net_pkt_data(pkt) +
+				       sizeof(struct net_eth_hdr));
+}
+
+enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface,
+						struct net_pkt *pkt)
+{
+	struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt);
+	struct net_pkt *clone_pkt;
+	struct net_if *canbus_iface;
+
+	/* Forward only IPv6 frames */
+	if ((get_ip_hdr_from_eth_frame(pkt)->vtc & 0xf0) != 0x60) {
+		return NET_CONTINUE;
+	}
+
+	/* This frame is for the Ethernet interface itself */
+	if (net_linkaddr_cmp(net_if_get_link_addr(iface), lladdr)) {
+		NET_DBG("Frame is for Ethernet only %02x:%02x:%02x:%02x:%02x:%02x",
+			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
+			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
+		return NET_CONTINUE;
+	}
+
+	canbus_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS));
+
+	net_pkt_cursor_init(pkt);
+	/* Forward all broadcasts */
+	if (net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr) ||
+	    net_eth_is_addr_multicast((struct net_eth_addr *)lladdr->addr)) {
+		if (!canbus_iface || !net_if_is_up(canbus_iface)) {
+			NET_ERR("No canbus iface");
+			return NET_CONTINUE;
+		}
+
+		clone_pkt = net_pkt_shallow_clone(pkt, NET_CAN_ALLOC_TIMEOUT);
+		if (clone_pkt) {
+			NET_DBG("Frame is %scast %02x:%02x:%02x:%02x:%02x:%02x,",
+				net_eth_is_addr_broadcast(
+					(struct net_eth_addr *)lladdr->addr) ? "broad" :
+				"multi",
+				lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
+				lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
+			net_pkt_set_family(clone_pkt, AF_INET6);
+			forward_eth_frame(clone_pkt, canbus_iface);
+		} else {
+			NET_ERR("PKT forwarding: cloning failed");
+		}
+
+		return NET_CONTINUE;
+	}
+
+	if (!canbus_iface || !net_if_is_up(canbus_iface)) {
+		NET_ERR("No canbus iface");
+		return NET_DROP;
+	}
+
+	/* This frame is for 6LoCAN only */
+	net_pkt_set_family(pkt, AF_INET6);
+	net_buf_pull(pkt->buffer, sizeof(struct net_eth_hdr));
+	forward_eth_frame(pkt, canbus_iface);
+	NET_DBG("Frame is for CANBUS: 0x%04x", canbus_get_dest_lladdr(pkt));
+
+	return NET_OK;
+}
+
+static void forward_can_frame(struct net_pkt *pkt, struct net_if *eth_iface)
+{
+	net_pkt_set_iface(pkt, eth_iface);
+	net_if_queue_tx(eth_iface, pkt);
+}
+
+static void rewrite_icmp_hdr(struct net_pkt *pkt, struct net_icmp_hdr *icmp_hdr)
+{
+	int ret;
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
+	ret = net_icmpv6_create(pkt, icmp_hdr->type, icmp_hdr->code);
+	if (ret) {
+		NET_ERR("Can't create ICMP HDR");
+		return;
+	}
+
+	net_pkt_cursor_init(pkt);
+	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
+	ret = net_icmpv6_finalize(pkt);
+	if (ret) {
+		NET_ERR("Can't finalize ICMP HDR");
+	}
+}
+
+static void extend_llao(struct net_pkt *pkt, struct net_linkaddr *mac_addr)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr);
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_opt_access,
+					      struct net_icmpv6_nd_opt_hdr);
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(llao_access,
+					      struct net_eth_addr);
+	struct net_pkt_cursor cursor_backup;
+	struct net_icmp_hdr *icmp_hdr;
+	struct net_icmpv6_nd_opt_hdr *icmp_opt_hdr;
+	uint8_t *llao, llao_backup[2];
+	int ret;
+
+	net_pkt_cursor_backup(pkt, &cursor_backup);
+	net_pkt_cursor_init(pkt);
+	net_pkt_set_overwrite(pkt, true);
+	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
+
+	if (net_calc_chksum(pkt, IPPROTO_ICMPV6) != 0U) {
+		NET_ERR("Invalid checksum");
+		return;
+	}
+
+	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
+	if (!icmp_hdr) {
+		NET_ERR("No ICMP6 HDR");
+		goto done;
+	}
+
+	switch (icmp_hdr->type) {
+
+	case NET_ICMPV6_NS:
+		net_pkt_skip(pkt, sizeof(struct net_icmpv6_ns_hdr));
+		NET_DBG("Extend NS SLLAO");
+		break;
+
+	case NET_ICMPV6_NA:
+		net_pkt_skip(pkt, sizeof(struct net_icmpv6_na_hdr));
+		NET_DBG("Extend NA TLLAO");
+		break;
+
+	case NET_ICMPV6_RS:
+		net_pkt_skip(pkt, sizeof(struct net_icmpv6_rs_hdr));
+		NET_DBG("Extend RS SLLAO");
+		break;
+
+	case NET_ICMPV6_RA:
+		net_pkt_skip(pkt, sizeof(struct net_icmpv6_ra_hdr));
+		NET_DBG("Extend RA SLLAO");
+		break;
+
+	default:
+		goto done;
+	}
+
+	net_pkt_acknowledge_data(pkt, &icmp_access);
+
+	icmp_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
+		       net_pkt_get_data(pkt, &icmp_opt_access);
+	if (!icmp_opt_hdr) {
+		NET_DBG("No LLAO opt to extend");
+		goto done;
+	}
+
+	net_pkt_acknowledge_data(pkt, &icmp_opt_access);
+
+	if (icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_SLLAO &&
+	    (icmp_hdr->type == NET_ICMPV6_NA &&
+	     icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_TLLAO)) {
+		NET_DBG("opt was not LLAO");
+		goto done;
+	}
+
+	if (icmp_opt_hdr->len != 1) {
+		NET_ERR("LLAO len is %u. This should be 1 for 6LoCAN",
+			icmp_opt_hdr->len);
+		goto done;
+	}
+
+	llao = (uint8_t *)net_pkt_get_data(pkt, &llao_access);
+	if (!llao) {
+		NET_ERR("Can't read LLAO");
+		goto done;
+	}
+
+	memcpy(llao_backup, llao, sizeof(struct net_canbus_lladdr));
+	memcpy(llao, mac_addr->addr, mac_addr->len);
+
+	llao[4] = (llao[4] & 0xC0) | llao_backup[0];
+	llao[5] = llao_backup[1];
+
+	ret = net_pkt_set_data(pkt, &llao_access);
+	if (ret < 0) {
+		NET_ERR("Failed to write MAC to LLAO [%d]", ret);
+		goto done;
+	}
+
+	rewrite_icmp_hdr(pkt, icmp_hdr);
+
+	NET_DBG("LLAO extended to %02x:%02x:%02x:%02x:%02x:%02x",
+		llao[0], llao[1], llao[2], llao[3], llao[4], llao[5]);
+
+done:
+	net_pkt_cursor_restore(pkt, &cursor_backup);
+}
+
+static bool pkt_is_icmp(struct net_pkt *pkt)
+{
+	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct net_ipv6_hdr *ipv6_hdr =
+		(struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+
+	if (!ipv6_hdr) {
+		NET_ERR("No IPv6 HDR");
+		return false;
+	}
+
+	return (ipv6_hdr->nexthdr == IPPROTO_ICMPV6);
+}
+
+static void swap_scr_lladdr(struct net_pkt *pkt, struct net_pkt *pkt_clone)
+{
+	struct net_linkaddr *lladdr_origin = net_pkt_lladdr_src(pkt);
+	struct net_linkaddr *lladdr_clone = net_pkt_lladdr_src(pkt_clone);
+	size_t offset;
+
+	offset = lladdr_origin->addr - pkt->buffer->data;
+	lladdr_clone->addr = pkt_clone->buffer->data + offset;
+}
+
+static void can_to_eth_lladdr(struct net_pkt *pkt, struct net_if *eth_iface,
+			      bool bcast)
+{
+	uint16_t src_can_addr = canbus_get_src_lladdr(pkt);
+	struct net_linkaddr *lladdr_src = net_pkt_lladdr_src(pkt);
+	struct net_linkaddr *lladdr_dst;
+
+	if (bcast) {
+		lladdr_dst = net_pkt_lladdr_dst(pkt);
+		lladdr_dst->len = sizeof(struct net_eth_addr);
+		lladdr_dst->type = NET_LINK_ETHERNET;
+		lladdr_dst->addr = (uint8_t *)net_eth_broadcast_addr()->addr;
+	}
+
+	lladdr_src->addr = net_pkt_lladdr_src(pkt)->addr -
+			   (sizeof(struct net_eth_addr) - lladdr_src->len);
+	memcpy(lladdr_src->addr, net_if_get_link_addr(eth_iface)->addr,
+	       sizeof(struct net_eth_addr));
+	lladdr_src->addr[4] = (lladdr_src->addr[4] & 0xC0) | (src_can_addr >> 8U);
+	lladdr_src->addr[5] = src_can_addr & 0xFF;
+	lladdr_src->len = sizeof(struct net_eth_addr);
+	lladdr_src->type = NET_LINK_ETHERNET;
+}
+
+void translate_to_eth_frame(struct net_pkt *pkt, bool is_bcast,
+			    struct net_if *eth_iface)
+{
+	struct net_linkaddr *dest_addr = net_pkt_lladdr_dst(pkt);
+	struct net_linkaddr *src_addr = net_pkt_lladdr_src(pkt);
+	bool is_icmp;
+
+	is_icmp = pkt_is_icmp(pkt);
+
+	can_to_eth_lladdr(pkt, eth_iface, is_bcast);
+	canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt));
+	NET_DBG("Forward frame to %02x:%02x:%02x:%02x:%02x:%02x. "
+		"Src: %02x:%02x:%02x:%02x:%02x:%02x",
+		dest_addr->addr[0], dest_addr->addr[1], dest_addr->addr[2],
+		dest_addr->addr[3], dest_addr->addr[4], dest_addr->addr[5],
+		src_addr->addr[0], src_addr->addr[1], src_addr->addr[2],
+		src_addr->addr[3], src_addr->addr[4], src_addr->addr[5]);
+
+	if (is_icmp) {
+		extend_llao(pkt, net_if_get_link_addr(eth_iface));
+	}
+}
+
+static enum net_verdict canbus_forward_to_eth(struct net_pkt *pkt)
+{
+	struct net_pkt *pkt_clone;
+	struct net_if *eth_iface;
+
+	eth_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
+	if (!eth_iface || !net_if_is_up(eth_iface)) {
+		NET_ERR("No Ethernet iface available");
+		if (canbus_is_for_translator(pkt)) {
+			return NET_DROP;
+		} else {
+			return NET_CONTINUE;
+		}
+	}
+
+	if (canbus_dest_is_mcast(pkt)) {
+		/* net_pkt_clone can't be called on a pkt where
+		 * net_buf_pull was called on. We need to clone
+		 * first and then finish the pkt.
+		 */
+		pkt_clone = net_pkt_clone(pkt, NET_CAN_ALLOC_TIMEOUT);
+		if (pkt_clone) {
+			swap_scr_lladdr(pkt, pkt_clone);
+			canbus_finish_pkt(pkt_clone);
+			translate_to_eth_frame(pkt_clone, true, eth_iface);
+			forward_can_frame(pkt_clone, eth_iface);
+			NET_DBG("Len: %zu", net_pkt_get_len(pkt_clone));
+		} else {
+			NET_ERR("Failed to clone pkt");
+		}
+	}
+
+	canbus_finish_pkt(pkt);
+
+	if (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) {
+		translate_to_eth_frame(pkt, false, eth_iface);
+		forward_can_frame(pkt, eth_iface);
+		return NET_OK;
+	}
+
+	return NET_CONTINUE;
+}
+#else
+#define canbus_forward_to_eth(...) 0
+#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/
+
+static enum net_verdict canbus_recv(struct net_if *iface,
+				    struct net_pkt *pkt)
+{
+	struct net_linkaddr *lladdr = net_pkt_lladdr_src(pkt);
+	enum net_verdict ret = NET_DROP;
+
+	if (pkt->canbus_rx_ctx) {
+		if (lladdr->len == sizeof(struct net_canbus_lladdr)) {
+			NET_DBG("Push reassembled packet from 0x%04x trough "
+				"stack again", canbus_get_src_lladdr(pkt));
+		} else {
+			NET_DBG("Push reassembled packet from "
+				"%02x:%02x:%02x:%02x:%02x:%02x trough stack again",
+				lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
+				lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
+		}
+
+		if (pkt->canbus_rx_ctx->state == NET_CAN_RX_STATE_FIN) {
+			canbus_rx_finish(pkt);
+
+			if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)) {
+				ret = canbus_forward_to_eth(pkt);
+			} else {
+				canbus_finish_pkt(pkt);
+				canbus_print_ip_hdr(NET_IPV6_HDR(pkt));
+				ret = NET_CONTINUE;
+			}
+		} else {
+			NET_ERR("Expected pkt in FIN state");
+		}
+	} else {
+		ret = canbus_process_frame(pkt);
+	}
+
+	return ret;
+}
+
+static inline int canbus_send_dad_request(const struct device *net_can_dev,
+					  struct net_canbus_lladdr *ll_addr)
+{
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_frame frame;
+	int ret;
+
+	canbus_set_frame_datalength(&frame, 0);
+	frame.rtr = CAN_REMOTEREQUEST;
+	frame.id_type = CAN_EXTENDED_IDENTIFIER;
+	frame.ext_id = canbus_addr_to_id(ll_addr->addr,
+					 sys_rand32_get() & CAN_NET_IF_ADDR_MASK);
+
+	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
+	if (ret != CAN_TX_OK) {
+		NET_ERR("Sending DAD request failed [%d]", ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void canbus_send_dad_resp_cb(uint32_t err_flags, void *cb_arg)
+{
+	static uint8_t fail_cnt;
+	struct k_work *work = (struct k_work *)cb_arg;
+
+	if (err_flags) {
+		NET_ERR("Failed to send dad response [%u]", err_flags);
+		if (err_flags != CAN_TX_BUS_OFF &&
+		    fail_cnt < NET_CAN_DAD_SEND_RETRY) {
+			k_work_submit_to_queue(&net_canbus_workq, work);
+		}
+
+		fail_cnt++;
+	} else {
+		fail_cnt = 0;
+	}
+}
+
+static inline void canbus_send_dad_response(struct k_work *item)
+{
+	struct canbus_net_ctx *ctx = CONTAINER_OF(item, struct canbus_net_ctx,
+						  dad_work);
+	struct net_if *iface = ctx->iface;
+	struct net_linkaddr *ll_addr = net_if_get_link_addr(iface);
+	const struct device *net_can_dev = net_if_get_device(iface);
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_frame frame;
+	int ret;
+
+	canbus_set_frame_datalength(&frame, 0);
+	frame.rtr = CAN_DATAFRAME;
+	frame.id_type = CAN_EXTENDED_IDENTIFIER;
+	frame.ext_id = canbus_addr_to_id(NET_CAN_DAD_ADDR,
+					 ntohs(UNALIGNED_GET((uint16_t *) ll_addr->addr)));
+
+	ret = api->send(net_can_dev, &frame, canbus_send_dad_resp_cb, item,
+			K_FOREVER);
+	if (ret != CAN_TX_OK) {
+		NET_ERR("Sending SF failed [%d]", ret);
+	} else {
+		NET_INFO("DAD response sent");
+	}
+}
+
+static inline void canbus_detach_filter(const struct device *net_can_dev,
+					int filter_id)
+{
+	const struct net_can_api *api = net_can_dev->api;
+
+	api->detach_filter(net_can_dev, filter_id);
+}
+
+static void canbus_dad_resp_cb(struct zcan_frame *frame, void *arg)
+{
+	struct k_sem *dad_sem = (struct k_sem *)arg;
+
+	k_sem_give(dad_sem);
+}
+
+static inline
+int canbus_attach_dad_resp_filter(const struct device *net_can_dev,
+				  struct net_canbus_lladdr *ll_addr,
+				  struct k_sem *dad_sem)
+{
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_filter filter = {
+		.id_type = CAN_EXTENDED_IDENTIFIER,
+		.rtr = CAN_DATAFRAME,
+		.rtr_mask = 1,
+		.ext_id_mask = CAN_EXT_ID_MASK
+	};
+	int filter_id;
+
+	filter.ext_id = canbus_addr_to_id(NET_CAN_DAD_ADDR, ll_addr->addr);
+
+	filter_id = api->attach_filter(net_can_dev, canbus_dad_resp_cb,
+				       dad_sem, &filter);
+	if (filter_id == CAN_NO_FREE_FILTER) {
+		NET_ERR("Can't attach dad response filter");
+	}
+
+	return filter_id;
+}
+
+static void canbus_dad_request_cb(struct zcan_frame *frame, void *arg)
+{
+	struct k_work *work = (struct k_work *)arg;
+
+	k_work_submit_to_queue(&net_canbus_workq, work);
+}
+
+static inline int canbus_attach_dad_filter(const struct device *net_can_dev,
+					   struct net_canbus_lladdr *ll_addr,
+					   struct k_work *dad_work)
+{
+	const struct net_can_api *api = net_can_dev->api;
+	struct zcan_filter filter = {
+		.id_type = CAN_EXTENDED_IDENTIFIER,
+		.rtr = CAN_REMOTEREQUEST,
+		.rtr_mask = 1,
+		.ext_id_mask = (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS)
+	};
+	int filter_id;
+
+	filter.ext_id = canbus_addr_to_id(ll_addr->addr, 0);
+
+	filter_id = api->attach_filter(net_can_dev, canbus_dad_request_cb,
+				       dad_work, &filter);
+	if (filter_id == CAN_NO_FREE_FILTER) {
+		NET_ERR("Can't attach dad filter");
+	}
+
+	return filter_id;
+}
+
+static inline int canbus_init_ll_addr(struct net_if *iface)
+{
+	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
+	const struct device *net_can_dev = net_if_get_device(iface);
+	int dad_resp_filter_id = CAN_NET_FILTER_NOT_SET;
+	struct net_canbus_lladdr ll_addr;
+	int ret;
+	struct k_sem dad_sem;
+
+#if defined(CONFIG_NET_L2_CANBUS_USE_FIXED_ADDR)
+	ll_addr.addr = CONFIG_NET_L2_CANBUS_FIXED_ADDR;
+#else
+	do {
+		ll_addr.addr = sys_rand32_get() % (NET_CAN_MAX_ADDR + 1);
+	} while (ll_addr.addr < NET_CAN_MIN_ADDR);
+#endif
+
+	/* Add address early for DAD response */
+	ctx->ll_addr = sys_cpu_to_be16(ll_addr.addr);
+	net_if_set_link_addr(iface, (uint8_t *)&ctx->ll_addr, sizeof(ll_addr),
+			     NET_LINK_CANBUS);
+
+	dad_resp_filter_id = canbus_attach_dad_resp_filter(net_can_dev, &ll_addr,
+							   &dad_sem);
+	if (dad_resp_filter_id < 0) {
+		return -EIO;
+	}
+	/*
+	 * Attach this filter now to defend this address instantly.
+	 * This filter is not called for own DAD because loopback is not
+	 * enabled.
+	 */
+	ctx->dad_filter_id = canbus_attach_dad_filter(net_can_dev, &ll_addr,
+						      &ctx->dad_work);
+	if (ctx->dad_filter_id < 0) {
+		ret = -EIO;
+		goto dad_err;
+	}
+
+	k_sem_init(&dad_sem, 0, 1);
+	ret = canbus_send_dad_request(net_can_dev, &ll_addr);
+	if (ret) {
+		ret = -EIO;
+		goto dad_err;
+	}
+
+	ret = k_sem_take(&dad_sem, NET_CAN_DAD_TIMEOUT);
+	canbus_detach_filter(net_can_dev, dad_resp_filter_id);
+	dad_resp_filter_id = CAN_NET_FILTER_NOT_SET;
+
+	if (ret != -EAGAIN) {
+		NET_INFO("DAD failed");
+		ret = -EAGAIN;
+		goto dad_err;
+	}
+
+	return 0;
+
+dad_err:
+	net_if_set_link_addr(iface, NULL, 0, NET_LINK_CANBUS);
+	if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) {
+		canbus_detach_filter(net_can_dev, ctx->dad_filter_id);
+		ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET;
+	}
+
+	if (dad_resp_filter_id != CAN_NET_FILTER_NOT_SET) {
+		canbus_detach_filter(net_can_dev, dad_resp_filter_id);
+	}
+
+	return ret;
+}
+
+void net_6locan_init(struct net_if *iface)
+{
+	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
+	uint8_t thread_priority;
+	int i;
+
+	NET_DBG("Init CAN net interface");
+
+	for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) {
+		l2_ctx.tx_ctx[i].state = NET_CAN_TX_STATE_UNUSED;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) {
+		l2_ctx.rx_ctx[i].state = NET_CAN_RX_STATE_UNUSED;
+	}
+
+	ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET;
+	ctx->iface = iface;
+	k_work_init(&ctx->dad_work, canbus_send_dad_response);
+
+	k_mutex_init(&l2_ctx.tx_ctx_mtx);
+	k_mutex_init(&l2_ctx.rx_ctx_mtx);
+	k_sem_init(&l2_ctx.tx_sem, 1, INT_MAX);
+
+	/* This work queue should have precedence over the tx stream
+	 * TODO thread_priority = tx_tc2thread(NET_TC_TX_COUNT -1) - 1;
+	 */
+	thread_priority = 6;
+
+	k_work_q_start(&net_canbus_workq, net_canbus_stack,
+		       K_KERNEL_STACK_SIZEOF(net_canbus_stack),
+		       K_PRIO_COOP(thread_priority));
+	k_thread_name_set(&net_canbus_workq.thread, "isotp_work");
+	NET_DBG("Workq started. Thread ID: %p", &net_canbus_workq.thread);
+}
+
+static int canbus_enable(struct net_if *iface, bool state)
+{
+	const struct device *net_can_dev = net_if_get_device(iface);
+	const struct net_can_api *api = net_can_dev->api;
+	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
+	int dad_retry_cnt, ret;
+
+	NET_DBG("start to bring iface %p %s", iface, state ? "up" : "down");
+
+	if (state) {
+		for (dad_retry_cnt = CONFIG_NET_L2_CANBUS_DAD_RETRIES;
+		     dad_retry_cnt; dad_retry_cnt--) {
+			ret = canbus_init_ll_addr(iface);
+			if (ret == 0) {
+				break;
+			} else if (ret == -EIO) {
+				return -EIO;
+			}
+		}
+
+		if (ret != 0) {
+			return ret;
+		}
+
+	} else {
+		if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) {
+			canbus_detach_filter(net_can_dev, ctx->dad_filter_id);
+		}
+	}
+
+	ret = api->enable(net_can_dev, state);
+	if (!ret) {
+		NET_DBG("Iface %p is up", iface);
+	}
+
+	return ret;
+}
+
+static enum net_l2_flags canbus_net_flags(struct net_if *iface)
+{
+	return NET_L2_MULTICAST;
+}
+
+NET_L2_INIT(CANBUS_L2, canbus_recv, canbus_send, canbus_enable,
+	    canbus_net_flags);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/CMakeLists.txt	(working copy)
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_CANBUS_RAW canbus_raw.c)
+zephyr_library_sources_ifdef(CONFIG_NET_L2_CANBUS 6locan.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/Kconfig	(working copy)
@@ -0,0 +1,76 @@
+# Copyright (c) 2019 Alexander Wachter
+# SPDX-License-Identifier: Apache-2.0
+
+config NET_L2_CANBUS
+	bool "Enable CANBUS L2 layer [EXPERIMENTAL]"
+	depends on CAN_NET
+	select NET_6LO
+	help
+	  Add a CANBUS L2 layer driver. This is the layer for IPv6 over CAN
+	  (6loCAN). It uses IPHC to compress the IP header and ISO-TP for
+	  flow control and reassembling.
+
+if NET_L2_CANBUS
+
+config NET_L2_CANBUS_USE_FIXED_ADDR
+	bool "Use fixed L2 address"
+	help
+	  Use a fixed L2 address for 6LoCAN instead of a random chosen one.
+
+config NET_L2_CANBUS_FIXED_ADDR
+	hex "L2 address"
+	depends on NET_L2_CANBUS_USE_FIXED_ADDR
+	range 0x00FF 0x3DEF
+
+config NET_L2_CANBUS_DAD_RETRIES
+	int "Number of DAD retries"
+	default 5
+	help
+	  Number of retries for Duplicate Address Detection.
+	  Greater than one only makes sense for random link layer addresses.
+
+config NET_L2_CANBUS_STMIN
+	int "STmin"
+	default 0
+	range 0 127
+	help
+	  Minimal separation time between frames in ms.
+	  The timer starts when the frame is queued and the next frame is
+	  transmitted after expiration.
+	  STmin is chosen by the receiver and transmitted in the FC
+	  (Flow Control) frame. See also: ISO 15765-2:2016
+
+config NET_L2_CANBUS_BS
+	int "BS (Block Size)"
+	default 8
+	range 0 256
+	help
+	  Number of CF (Contiguous Frame) PDUs before next FC (Flow Control)
+	  frame is sent. Zero value means all frames are sent consecutive
+	  without an additional FC frame.
+	  A BS counter at the sender counts from one to BS. When BS is reached,
+	  the sender waits for a FC frame again an BS is reset.
+	  See also: ISO 15765-2:2016
+
+config NET_L2_CANBUS_ETH_TRANSLATOR
+	bool "Enable 6LoCAN to Ethernet translator"
+	depends on NET_L2_ETHERNET
+	help
+	  Enable a 6LoCAN Ethernet translator. With this translator it is
+	  possible to connect a 6LoCAN network to a Ethernet network directly,
+	  via a Switch or trough a router. Messages that goes through the
+	  translator have a special address and the MAC address is carried inline.
+	  The packet is forwarded with uncompressed IPv6 header.
+
+module = NET_L2_CANBUS
+module-dep = NET_LOG
+module-str = Log level for CANbus L2 layer
+module-help = Enables CANbus L2 to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # NET_L2_CANBUS
+
+config NET_L2_CANBUS_RAW
+	bool "Enable CANBUS RAW l2 layer"
+	help
+	  Add a CANBUS L2 layer driver. This is the layer for SOCKET CAN.
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_internal.h	(working copy)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2019 Alexander Wachter
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_
+#define ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_
+
+
+#ifdef NET_CAN_USE_CAN_FD
+#define NET_CAN_DL 64
+#else
+#define NET_CAN_DL 8
+#endif/*NET_CAN_USE_CAN_FD*/
+
+/* Protocol control information*/
+#define NET_CAN_PCI_SF 0x00 /* Single frame*/
+#define NET_CAN_PCI_FF 0x01 /* First frame */
+#define NET_CAN_PCI_CF 0x02 /* Consecutive frame */
+#define NET_CAN_PCI_FC 0x03 /* Flow control frame */
+
+#define NET_CAN_PCI_TYPE_BYTE        0
+#define NET_CAN_PCI_TYPE_POS         4
+#define NET_CAN_PCI_TYPE_MASK        0xF0
+#define NET_CAN_PCI_TYPE_SF   (NET_CAN_PCI_SF << NET_CAN_PCI_TYPE_POS)
+#define NET_CAN_PCI_TYPE_FF   (NET_CAN_PCI_FF << NET_CAN_PCI_TYPE_POS)
+#define NET_CAN_PCI_TYPE_CF   (NET_CAN_PCI_CF << NET_CAN_PCI_TYPE_POS)
+#define NET_CAN_PCI_TYPE_FC   (NET_CAN_PCI_FC << NET_CAN_PCI_TYPE_POS)
+
+#define NET_CAN_PCI_SF_DL_MASK       0x0F
+
+#define NET_CAN_PCI_FF_DL_UPPER_BYTE 0
+#define NET_CAN_PCI_FF_DL_UPPER_MASK 0x0F
+#define NET_CAN_PCI_FF_DL_LOWER_BYTE 1
+
+#define NET_CAN_PCI_FS_BYTE          0
+#define NET_CAN_PCI_FS_MASK          0x0F
+#define NET_CAN_PCI_BS_BYTE          1
+#define NET_CAN_PCI_ST_MIN_BYTE      2
+
+#define NET_CAN_PCI_FS_CTS           0x0
+#define NET_CAN_PCI_FS_WAIT          0x1
+#define NET_CAN_PCI_FS_OVFLW         0x2
+
+#define NET_CAN_PCI_SN_MASK          0x0F
+
+#define NET_CAN_FF_DL_MIN            (NET_CAN_CAN_DL)
+
+#define NET_CAN_WFT_FIRST            0xFF
+
+#define NET_CAN_BS_TIME K_MSEC(1000)
+#define NET_CAN_A_TIME  K_MSEC(1000)
+
+#define NET_CAN_FF_CF_TIME K_MSEC(1)
+
+#define NET_CAN_STMIN_MAX            0xFA
+#define NET_CAN_STMIN_MS_MAX         0x7F
+#define NET_CAN_STMIN_US_BEGIN       0xF1
+#define NET_CAN_STMIN_US_END         0xF9
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum net_can_isotp_tx_state {
+	NET_CAN_TX_STATE_UNUSED,
+	NET_CAN_TX_STATE_RESET,
+	NET_CAN_TX_STATE_WAIT_FC,
+	NET_CAN_TX_STATE_SEND_CF,
+	NET_CAN_TX_STATE_WAIT_ST,
+	NET_CAN_TX_STATE_WAIT_TX_BACKLOG,
+	NET_CAN_TX_STATE_FIN,
+	NET_CAN_TX_STATE_ERR
+};
+
+enum net_can_isotp_rx_state {
+	NET_CAN_RX_STATE_UNUSED,
+	NET_CAN_RX_STATE_RESET,
+	NET_CAN_RX_STATE_FF,
+	NET_CAN_RX_STATE_CF,
+	NET_CAN_RX_STATE_FIN,
+	NET_CAN_RX_STATE_TIMEOUT
+};
+
+struct canbus_l2_ctx {
+	struct canbus_isotp_tx_ctx tx_ctx[CONFIG_NET_PKT_TX_COUNT];
+	struct canbus_isotp_rx_ctx rx_ctx[CONFIG_NET_PKT_RX_COUNT];
+	struct k_mutex tx_ctx_mtx;
+	struct k_mutex rx_ctx_mtx;
+	struct k_sem tx_sem;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_raw.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_raw.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/canbus/canbus_raw.c	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_l2_canbus, LOG_LEVEL_NONE);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/socket_can.h>
+
+static inline enum net_verdict canbus_recv(struct net_if *iface,
+					   struct net_pkt *pkt)
+{
+	net_pkt_lladdr_src(pkt)->addr = NULL;
+	net_pkt_lladdr_src(pkt)->len = 0U;
+	net_pkt_lladdr_src(pkt)->type = NET_LINK_CANBUS_RAW;
+	net_pkt_lladdr_dst(pkt)->addr = NULL;
+	net_pkt_lladdr_dst(pkt)->len = 0U;
+	net_pkt_lladdr_dst(pkt)->type = NET_LINK_CANBUS_RAW;
+
+	net_pkt_set_family(pkt, AF_CAN);
+
+	return NET_CONTINUE;
+}
+
+static inline int canbus_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	const struct canbus_api *api = net_if_get_device(iface)->api;
+	int ret;
+
+	if (!api) {
+		return -ENOENT;
+	}
+
+	ret = api->send(net_if_get_device(iface), pkt);
+	if (!ret) {
+		ret = net_pkt_get_len(pkt);
+		net_pkt_unref(pkt);
+	}
+
+	return ret;
+}
+
+NET_L2_INIT(CANBUS_RAW_L2, canbus_recv, canbus_send, NULL, NULL);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/CMakeLists.txt	(working copy)
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_DUMMY    dummy.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/dummy.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/dummy.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/dummy/dummy.c	(working copy)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_l2_dummy, LOG_LEVEL_NONE);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+
+#include <net/dummy.h>
+
+static inline enum net_verdict dummy_recv(struct net_if *iface,
+					  struct net_pkt *pkt)
+{
+	net_pkt_lladdr_src(pkt)->addr = NULL;
+	net_pkt_lladdr_src(pkt)->len = 0U;
+	net_pkt_lladdr_src(pkt)->type = NET_LINK_DUMMY;
+	net_pkt_lladdr_dst(pkt)->addr = NULL;
+	net_pkt_lladdr_dst(pkt)->len = 0U;
+	net_pkt_lladdr_dst(pkt)->type = NET_LINK_DUMMY;
+
+	return NET_CONTINUE;
+}
+
+static inline int dummy_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	const struct dummy_api *api = net_if_get_device(iface)->api;
+	int ret;
+
+	if (!api) {
+		return -ENOENT;
+	}
+
+	ret = api->send(net_if_get_device(iface), pkt);
+	if (!ret) {
+		ret = net_pkt_get_len(pkt);
+		net_pkt_unref(pkt);
+	}
+
+	return ret;
+}
+
+static enum net_l2_flags dummy_flags(struct net_if *iface)
+{
+	return NET_L2_MULTICAST;
+}
+
+NET_L2_INIT(DUMMY_L2, dummy_recv, dummy_send, NULL, dummy_flags);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/CMakeLists.txt	(working copy)
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_ETHERNET      ethernet.c)
+zephyr_library_sources_ifdef(CONFIG_NET_L2_ETHERNET_MGMT ethernet_mgmt.c)
+
+if(CONFIG_NET_NATIVE)
+zephyr_library_sources_ifdef(CONFIG_NET_ARP              arp.c)
+zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS_ETHERNET ethernet_stats.c)
+
+if(CONFIG_NET_GPTP)
+  add_subdirectory(gptp)
+endif()
+
+if(CONFIG_NET_LLDP)
+  add_subdirectory(lldp)
+endif()
+
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/Kconfig	(working copy)
@@ -0,0 +1,79 @@
+# Copyright (c) 2018 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_L2_ETHERNET
+	bool "Enable Ethernet support"
+	help
+	  Add support for Ethernet, enabling selecting relevant hardware drivers.
+	  If NET_SLIP_TAP is selected, NET_L2_ETHERNET will enable to fully
+	  simulate Ethernet through SLIP.
+
+if NET_L2_ETHERNET
+
+module = NET_L2_ETHERNET
+module-dep = NET_LOG
+module-str = Log level for Ethernet L2 layer
+module-help = Enables Ethernet L2 to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_L2_ETHERNET_MGMT
+	bool "Enable Ethernet network management interface"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	help
+	  Enable support net_mgmt Ethernet interface which can be used to
+	  configure at run-time Ethernet drivers and L2 settings.
+
+config NET_VLAN
+	bool "Enable virtual lan support"
+	help
+	  Enables virtual lan (VLAN) support for Ethernet.
+
+config NET_VLAN_COUNT
+	int "Max VLAN tags supported in the system"
+	default 1
+	range 1 255
+	depends on NET_VLAN
+	help
+	  How many VLAN tags can be configured.
+
+config NET_ARP
+	bool "Enable ARP"
+	default y
+	depends on NET_IPV4
+	help
+	  Enable ARP support. This is necessary on hardware that requires it to
+	  get IPv4 working (like Ethernet devices).
+
+config NET_ARP_TABLE_SIZE
+	int "Number of entries in ARP table."
+	depends on NET_ARP
+	default 2
+	help
+	  Each entry in the ARP table consumes 22 bytes of memory.
+
+config NET_ARP_GRATUITOUS
+	bool "Support gratuitous ARP requests/replies."
+	depends on NET_ARP
+	default y
+	help
+	  Gratuitous in this case means a ARP request or reply that is not
+	  normally needed according to the ARP specification but could be used
+	  in some cases. A gratuitous ARP request is a ARP request packet where
+	  the source and destination IP are both set to the IP of the machine
+	  issuing the packet and the destination MAC is the broadcast address
+	  ff:ff:ff:ff:ff:ff. Ordinarily, no reply packet will occur.
+	  A gratuitous ARP reply is a reply to which no request has been made.
+
+if NET_ARP
+module = NET_ARP
+module-dep = NET_LOG
+module-str = Log level for IPv4 ARP
+module-help = Enables core ARP code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+endif # NET_ARP
+
+source "subsys/net/l2/ethernet/gptp/Kconfig"
+source "subsys/net/l2/ethernet/lldp/Kconfig"
+
+endif # NET_L2_ETHERNET
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.h	(working copy)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ARP_H
+#define __ARP_H
+
+#if defined(CONFIG_NET_ARP) && defined(CONFIG_NET_NATIVE)
+
+#include <sys/slist.h>
+#include <net/ethernet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Address resolution (ARP) library
+ * @defgroup arp ARP Library
+ * @ingroup networking
+ * @{
+ */
+
+#define NET_ARP_HDR(pkt) ((struct net_arp_hdr *)net_pkt_data(pkt))
+
+struct net_arp_hdr {
+	uint16_t hwtype;		/* HTYPE */
+	uint16_t protocol;		/* PTYPE */
+	uint8_t hwlen;			/* HLEN */
+	uint8_t protolen;		/* PLEN */
+	uint16_t opcode;
+	struct net_eth_addr src_hwaddr;	/* SHA */
+	struct in_addr src_ipaddr;	/* SPA */
+	struct net_eth_addr dst_hwaddr;	/* THA */
+	struct in_addr dst_ipaddr;	/* TPA */
+}  __packed;
+
+#define NET_ARP_HTYPE_ETH 1
+#define NET_ARP_IPV4_PTYPE_SIZE 4
+
+#define NET_ARP_REQUEST 1
+#define NET_ARP_REPLY   2
+
+struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
+				struct in_addr *request_ip,
+				struct in_addr *current_ip);
+enum net_verdict net_arp_input(struct net_pkt *pkt,
+			       struct net_eth_hdr *eth_hdr);
+
+struct arp_entry {
+	sys_snode_t node;
+	uint32_t req_start;
+	struct net_if *iface;
+	struct in_addr ip;
+	union {
+		struct net_pkt *pending;
+		struct net_eth_addr eth;
+	};
+};
+
+typedef void (*net_arp_cb_t)(struct arp_entry *entry,
+			     void *user_data);
+int net_arp_foreach(net_arp_cb_t cb, void *user_data);
+
+void net_arp_clear_cache(struct net_if *iface);
+void net_arp_init(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* CONFIG_NET_ARP */
+#define net_arp_prepare(_kt, _u1, _u2) _kt
+#define net_arp_input(...) NET_OK
+#define net_arp_clear_cache(...)
+#define net_arp_foreach(...) 0
+#define net_arp_init(...)
+
+#endif /* CONFIG_NET_ARP */
+
+#endif /* __ARP_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/arp.c	(working copy)
@@ -0,0 +1,744 @@
+/** @file
+ * @brief ARP related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_arp, CONFIG_NET_ARP_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_stats.h>
+
+#include "arp.h"
+#include "net_private.h"
+
+#define NET_BUF_TIMEOUT K_MSEC(100)
+#define ARP_REQUEST_TIMEOUT (2 * MSEC_PER_SEC)
+
+static bool arp_cache_initialized;
+static struct arp_entry arp_entries[CONFIG_NET_ARP_TABLE_SIZE];
+
+static sys_slist_t arp_free_entries;
+static sys_slist_t arp_pending_entries;
+static sys_slist_t arp_table;
+
+struct k_delayed_work arp_request_timer;
+
+static void arp_entry_cleanup(struct arp_entry *entry, bool pending)
+{
+	NET_DBG("%p", entry);
+
+	if (pending) {
+		NET_DBG("Releasing pending pkt %p (ref %d)",
+			entry->pending,
+			atomic_get(&entry->pending->atomic_ref) - 1);
+		net_pkt_unref(entry->pending);
+		entry->pending = NULL;
+	}
+
+	entry->iface = NULL;
+
+	(void)memset(&entry->ip, 0, sizeof(struct in_addr));
+	(void)memset(&entry->eth, 0, sizeof(struct net_eth_addr));
+}
+
+static struct arp_entry *arp_entry_find(sys_slist_t *list,
+					struct net_if *iface,
+					struct in_addr *dst,
+					sys_snode_t **previous)
+{
+	struct arp_entry *entry;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(list, entry, node) {
+		NET_DBG("iface %p dst %s",
+			iface, log_strdup(net_sprint_ipv4_addr(&entry->ip)));
+
+		if (entry->iface == iface &&
+		    net_ipv4_addr_cmp(&entry->ip, dst)) {
+			return entry;
+		}
+
+		if (previous) {
+			*previous = &entry->node;
+		}
+	}
+
+	return NULL;
+}
+
+static inline struct arp_entry *arp_entry_find_move_first(struct net_if *iface,
+							  struct in_addr *dst)
+{
+	sys_snode_t *prev = NULL;
+	struct arp_entry *entry;
+
+	NET_DBG("dst %s", log_strdup(net_sprint_ipv4_addr(dst)));
+
+	entry = arp_entry_find(&arp_table, iface, dst, &prev);
+	if (entry) {
+		/* Let's assume the target is going to be accessed
+		 * more than once here in a short time frame. So we
+		 * place the entry first in position into the table
+		 * in order to reduce subsequent find.
+		 */
+		if (&entry->node != sys_slist_peek_head(&arp_table)) {
+			sys_slist_remove(&arp_table, prev, &entry->node);
+			sys_slist_prepend(&arp_table, &entry->node);
+		}
+	}
+
+	return entry;
+}
+
+static inline
+struct arp_entry *arp_entry_find_pending(struct net_if *iface,
+					 struct in_addr *dst)
+{
+	NET_DBG("dst %s", log_strdup(net_sprint_ipv4_addr(dst)));
+
+	return arp_entry_find(&arp_pending_entries, iface, dst, NULL);
+}
+
+static struct arp_entry *arp_entry_get_pending(struct net_if *iface,
+					       struct in_addr *dst)
+{
+	sys_snode_t *prev = NULL;
+	struct arp_entry *entry;
+
+	NET_DBG("dst %s", log_strdup(net_sprint_ipv4_addr(dst)));
+
+	entry = arp_entry_find(&arp_pending_entries, iface, dst, &prev);
+	if (entry) {
+		/* We remove the entry from the pending list */
+		sys_slist_remove(&arp_pending_entries, prev, &entry->node);
+	}
+
+	if (sys_slist_is_empty(&arp_pending_entries)) {
+		k_delayed_work_cancel(&arp_request_timer);
+	}
+
+	return entry;
+}
+
+static struct arp_entry *arp_entry_get_free(void)
+{
+	sys_snode_t *node;
+
+	node = sys_slist_peek_head(&arp_free_entries);
+	if (!node) {
+		return NULL;
+	}
+
+	/* We remove the node from the free list */
+	sys_slist_remove(&arp_free_entries, NULL, node);
+
+	return CONTAINER_OF(node, struct arp_entry, node);
+}
+
+static struct arp_entry *arp_entry_get_last_from_table(void)
+{
+	sys_snode_t *node;
+
+	/* We assume last entry is the oldest one,
+	 * so is the preferred one to be taken out.
+	 */
+
+	node = sys_slist_peek_tail(&arp_table);
+	if (!node) {
+		return NULL;
+	}
+
+	sys_slist_find_and_remove(&arp_table, node);
+
+	return CONTAINER_OF(node, struct arp_entry, node);
+}
+
+
+static void arp_entry_register_pending(struct arp_entry *entry)
+{
+	NET_DBG("dst %s", log_strdup(net_sprint_ipv4_addr(&entry->ip)));
+
+	sys_slist_append(&arp_pending_entries, &entry->node);
+
+	entry->req_start = k_uptime_get_32();
+
+	/* Let's start the timer if necessary */
+	if (!k_delayed_work_remaining_get(&arp_request_timer)) {
+		k_delayed_work_submit(&arp_request_timer,
+				      K_MSEC(ARP_REQUEST_TIMEOUT));
+	}
+}
+
+static void arp_request_timeout(struct k_work *work)
+{
+	uint32_t current = k_uptime_get_32();
+	struct arp_entry *entry, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&arp_pending_entries,
+					  entry, next, node) {
+		if ((int32_t)(entry->req_start +
+			    ARP_REQUEST_TIMEOUT - current) > 0) {
+			break;
+		}
+
+		arp_entry_cleanup(entry, true);
+
+		sys_slist_remove(&arp_pending_entries, NULL, &entry->node);
+		sys_slist_append(&arp_free_entries, &entry->node);
+
+		entry = NULL;
+	}
+
+	if (entry) {
+		k_delayed_work_submit(&arp_request_timer,
+				      K_MSEC(entry->req_start +
+					     ARP_REQUEST_TIMEOUT - current));
+	}
+}
+
+static inline struct in_addr *if_get_addr(struct net_if *iface,
+					  struct in_addr *addr)
+{
+	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
+	int i;
+
+	if (!ipv4) {
+		return NULL;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		if (ipv4->unicast[i].is_used &&
+		    ipv4->unicast[i].address.family == AF_INET &&
+		    ipv4->unicast[i].addr_state == NET_ADDR_PREFERRED &&
+		    (!addr ||
+		     net_ipv4_addr_cmp(addr,
+				       &ipv4->unicast[i].address.in_addr))) {
+			return &ipv4->unicast[i].address.in_addr;
+		}
+	}
+
+	return NULL;
+}
+
+static inline struct net_pkt *arp_prepare(struct net_if *iface,
+					  struct in_addr *next_addr,
+					  struct arp_entry *entry,
+					  struct net_pkt *pending,
+					  struct in_addr *current_ip)
+{
+	struct net_arp_hdr *hdr;
+	struct in_addr *my_addr;
+	struct net_pkt *pkt;
+
+	if (current_ip) {
+		/* This is the IPv4 autoconf case where we have already
+		 * things setup so no need to allocate new net_pkt
+		 */
+		pkt = pending;
+	} else {
+		pkt = net_pkt_alloc_with_buffer(iface,
+						sizeof(struct net_arp_hdr),
+						AF_UNSPEC, 0, NET_BUF_TIMEOUT);
+		if (!pkt) {
+			return NULL;
+		}
+	}
+
+	net_pkt_set_vlan_tag(pkt, net_eth_get_vlan_tag(iface));
+
+	net_buf_add(pkt->buffer, sizeof(struct net_arp_hdr));
+
+	hdr = NET_ARP_HDR(pkt);
+
+	/* If entry is not set, then we are just about to send
+	 * an ARP request using the data in pending net_pkt.
+	 * This can happen if there is already a pending ARP
+	 * request and we want to send it again.
+	 */
+	if (entry) {
+		entry->pending = net_pkt_ref(pending);
+		entry->iface = net_pkt_iface(pkt);
+
+		net_ipaddr_copy(&entry->ip, next_addr);
+
+		net_pkt_lladdr_src(pkt)->addr =
+			(uint8_t *)net_if_get_link_addr(entry->iface)->addr;
+
+		arp_entry_register_pending(entry);
+	} else {
+		net_pkt_lladdr_src(pkt)->addr =
+			(uint8_t *)net_if_get_link_addr(iface)->addr;
+	}
+
+	net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr);
+
+	net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)net_eth_broadcast_addr();
+	net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+
+	hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
+	hdr->protocol = htons(NET_ETH_PTYPE_IP);
+	hdr->hwlen = sizeof(struct net_eth_addr);
+	hdr->protolen = sizeof(struct in_addr);
+	hdr->opcode = htons(NET_ARP_REQUEST);
+
+	(void)memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr));
+
+	net_ipaddr_copy(&hdr->dst_ipaddr, next_addr);
+
+	memcpy(hdr->src_hwaddr.addr, net_pkt_lladdr_src(pkt)->addr,
+	       sizeof(struct net_eth_addr));
+
+	if (!entry || net_pkt_ipv4_auto(pkt)) {
+		my_addr = current_ip;
+	} else {
+		my_addr = if_get_addr(entry->iface, current_ip);
+	}
+
+	if (my_addr) {
+		net_ipaddr_copy(&hdr->src_ipaddr, my_addr);
+	} else {
+		(void)memset(&hdr->src_ipaddr, 0, sizeof(struct in_addr));
+	}
+
+	return pkt;
+}
+
+struct net_pkt *net_arp_prepare(struct net_pkt *pkt,
+				struct in_addr *request_ip,
+				struct in_addr *current_ip)
+{
+	struct arp_entry *entry;
+	struct in_addr *addr;
+
+	if (!pkt || !pkt->buffer) {
+		return NULL;
+	}
+
+	/* Is the destination in the local network, if not route via
+	 * the gateway address.
+	 */
+	if (!current_ip &&
+	    !net_if_ipv4_addr_mask_cmp(net_pkt_iface(pkt), request_ip)) {
+		struct net_if_ipv4 *ipv4 = net_pkt_iface(pkt)->config.ip.ipv4;
+
+		if (ipv4) {
+			addr = &ipv4->gw;
+			if (net_ipv4_is_addr_unspecified(addr)) {
+				NET_ERR("Gateway not set for iface %p",
+					net_pkt_iface(pkt));
+
+				return NULL;
+			}
+		} else {
+			addr = request_ip;
+		}
+	} else {
+		addr = request_ip;
+	}
+
+	/* If the destination address is already known, we do not need
+	 * to send any ARP packet.
+	 */
+	entry = arp_entry_find_move_first(net_pkt_iface(pkt), addr);
+	if (!entry) {
+		struct net_pkt *req;
+
+		entry = arp_entry_find_pending(net_pkt_iface(pkt), addr);
+		if (!entry) {
+			/* No pending, let's try to get a new entry */
+			entry = arp_entry_get_free();
+			if (!entry) {
+				/* Then let's take one from table? */
+				entry = arp_entry_get_last_from_table();
+			}
+		} else {
+			/* There is a pending already */
+			entry = NULL;
+		}
+
+		req = arp_prepare(net_pkt_iface(pkt), addr, entry, pkt,
+				  current_ip);
+
+		if (!entry) {
+			/* We cannot send the packet, the ARP cache is full
+			 * or there is already a pending query to this IP
+			 * address, so this packet must be discarded.
+			 */
+			NET_DBG("Resending ARP %p", req);
+		}
+
+		return req;
+	}
+
+	net_pkt_lladdr_src(pkt)->addr =
+		(uint8_t *)net_if_get_link_addr(entry->iface)->addr;
+	net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr);
+
+	net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)&entry->eth;
+	net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+
+	NET_DBG("ARP using ll %s for IP %s",
+		log_strdup(net_sprint_ll_addr(net_pkt_lladdr_dst(pkt)->addr,
+					      sizeof(struct net_eth_addr))),
+		log_strdup(net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)));
+
+	return pkt;
+}
+
+static void arp_gratuitous(struct net_if *iface,
+			   struct in_addr *src,
+			   struct net_eth_addr *hwaddr)
+{
+	sys_snode_t *prev = NULL;
+	struct arp_entry *entry;
+
+	entry = arp_entry_find(&arp_table, iface, src, &prev);
+	if (entry) {
+		NET_DBG("Gratuitous ARP hwaddr %s -> %s",
+			log_strdup(net_sprint_ll_addr(
+					   (const uint8_t *)&entry->eth,
+					   sizeof(struct net_eth_addr))),
+			log_strdup(net_sprint_ll_addr(
+					   (const uint8_t *)hwaddr,
+					   sizeof(struct net_eth_addr))));
+
+		memcpy(&entry->eth, hwaddr, sizeof(struct net_eth_addr));
+	}
+}
+
+static void arp_update(struct net_if *iface,
+		       struct in_addr *src,
+		       struct net_eth_addr *hwaddr,
+		       bool gratuitous,
+		       bool force)
+{
+	struct arp_entry *entry;
+	struct net_pkt *pkt;
+
+	NET_DBG("src %s", log_strdup(net_sprint_ipv4_addr(src)));
+
+	entry = arp_entry_get_pending(iface, src);
+	if (!entry) {
+		if (IS_ENABLED(CONFIG_NET_ARP_GRATUITOUS) && gratuitous) {
+			arp_gratuitous(iface, src, hwaddr);
+		}
+
+		if (force) {
+			sys_snode_t *prev = NULL;
+			struct arp_entry *entry;
+
+			entry = arp_entry_find(&arp_table, iface, src, &prev);
+			if (entry) {
+				memcpy(&entry->eth, hwaddr,
+				       sizeof(struct net_eth_addr));
+			} else {
+				/* Add new entry as it was not found and force
+				 * was set.
+				 */
+				entry = arp_entry_get_free();
+				if (!entry) {
+					/* Then let's take one from table? */
+					entry = arp_entry_get_last_from_table();
+				}
+
+				if (entry) {
+					entry->req_start = k_uptime_get_32();
+					entry->iface = iface;
+					net_ipaddr_copy(&entry->ip, src);
+					memcpy(&entry->eth, hwaddr, sizeof(entry->eth));
+					sys_slist_prepend(&arp_table, &entry->node);
+				}
+			}
+		}
+
+		return;
+	}
+
+	/* Set the dst in the pending packet */
+	net_pkt_lladdr_dst(entry->pending)->len = sizeof(struct net_eth_addr);
+	net_pkt_lladdr_dst(entry->pending)->addr =
+		(uint8_t *) &NET_ETH_HDR(entry->pending)->dst.addr;
+
+	NET_DBG("dst %s pending %p frag %p",
+		log_strdup(net_sprint_ipv4_addr(&entry->ip)),
+		entry->pending, entry->pending->frags);
+
+	pkt = entry->pending;
+	entry->pending = NULL;
+
+	memcpy(&entry->eth, hwaddr, sizeof(struct net_eth_addr));
+
+	/* Inserting entry into the table */
+	sys_slist_prepend(&arp_table, &entry->node);
+
+	net_if_queue_tx(iface, pkt);
+}
+
+static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,
+						struct net_pkt *req,
+						struct net_eth_hdr *eth_query,
+						struct net_eth_addr *dst_addr)
+{
+	struct net_arp_hdr *hdr, *query;
+	struct net_pkt *pkt;
+
+	pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr),
+					AF_UNSPEC, 0, NET_BUF_TIMEOUT);
+	if (!pkt) {
+		return NULL;
+	}
+
+	net_buf_add(pkt->buffer, sizeof(struct net_arp_hdr));
+
+	hdr = NET_ARP_HDR(pkt);
+	query = NET_ARP_HDR(req);
+
+	net_pkt_set_vlan_tag(pkt, net_pkt_vlan_tag(req));
+
+	hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
+	hdr->protocol = htons(NET_ETH_PTYPE_IP);
+	hdr->hwlen = sizeof(struct net_eth_addr);
+	hdr->protolen = sizeof(struct in_addr);
+	hdr->opcode = htons(NET_ARP_REPLY);
+
+	memcpy(&hdr->dst_hwaddr.addr, &dst_addr->addr,
+	       sizeof(struct net_eth_addr));
+	memcpy(&hdr->src_hwaddr.addr, net_if_get_link_addr(iface)->addr,
+	       sizeof(struct net_eth_addr));
+
+	net_ipaddr_copy(&hdr->dst_ipaddr, &query->src_ipaddr);
+	net_ipaddr_copy(&hdr->src_ipaddr, &query->dst_ipaddr);
+
+	net_pkt_lladdr_src(pkt)->addr = net_if_get_link_addr(iface)->addr;
+	net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr);
+
+	net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)&hdr->dst_hwaddr.addr;
+	net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+
+	return pkt;
+}
+
+static bool arp_hdr_check(struct net_arp_hdr *arp_hdr)
+{
+	if (ntohs(arp_hdr->hwtype) != NET_ARP_HTYPE_ETH ||
+	    ntohs(arp_hdr->protocol) != NET_ETH_PTYPE_IP ||
+	    arp_hdr->hwlen != sizeof(struct net_eth_addr) ||
+	    arp_hdr->protolen != NET_ARP_IPV4_PTYPE_SIZE ||
+	    net_ipv4_is_addr_loopback(&arp_hdr->src_ipaddr)) {
+		NET_DBG("DROP: Invalid ARP header");
+		return false;
+	}
+
+	return true;
+}
+
+enum net_verdict net_arp_input(struct net_pkt *pkt,
+			       struct net_eth_hdr *eth_hdr)
+{
+	struct net_eth_addr *dst_hw_addr;
+	struct net_arp_hdr *arp_hdr;
+	struct net_pkt *reply;
+	struct in_addr *addr;
+
+	if (net_pkt_get_len(pkt) < (sizeof(struct net_arp_hdr) -
+				    (net_pkt_ip_data(pkt) - (uint8_t *)eth_hdr))) {
+		NET_DBG("Invalid ARP header (len %zu, min %zu bytes) %p",
+			net_pkt_get_len(pkt), sizeof(struct net_arp_hdr) -
+			(net_pkt_ip_data(pkt) - (uint8_t *)eth_hdr), pkt);
+		return NET_DROP;
+	}
+
+	arp_hdr = NET_ARP_HDR(pkt);
+	if (!arp_hdr_check(arp_hdr)) {
+		return NET_DROP;
+	}
+
+	switch (ntohs(arp_hdr->opcode)) {
+	case NET_ARP_REQUEST:
+		/* If ARP request sender hw address is our address,
+		 * we must drop the packet.
+		 */
+		if (memcmp(&arp_hdr->src_hwaddr,
+			   net_if_get_link_addr(net_pkt_iface(pkt))->addr,
+			   sizeof(struct net_eth_addr)) == 0) {
+			return NET_DROP;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_ARP_GRATUITOUS)) {
+			if (memcmp(&eth_hdr->dst,
+				   net_eth_broadcast_addr(),
+				   sizeof(struct net_eth_addr)) == 0 &&
+			    memcmp(&arp_hdr->dst_hwaddr,
+				   net_eth_broadcast_addr(),
+				   sizeof(struct net_eth_addr)) == 0 &&
+			    memcmp(&arp_hdr->dst_ipaddr, &arp_hdr->src_ipaddr,
+				   sizeof(struct in_addr)) == 0) {
+				/* If the IP address is in our cache,
+				 * then update it here.
+				 */
+				arp_update(net_pkt_iface(pkt),
+					   &arp_hdr->src_ipaddr,
+					   &arp_hdr->src_hwaddr,
+					   true, false);
+				break;
+			}
+		}
+
+		/* Discard ARP request if Ethernet address is broadcast
+		 * and Source IP address is Multicast address.
+		 */
+		if (memcmp(&eth_hdr->dst, net_eth_broadcast_addr(),
+			   sizeof(struct net_eth_addr)) == 0 &&
+		    net_ipv4_is_addr_mcast(&arp_hdr->src_ipaddr)) {
+			NET_DBG("DROP: eth addr is bcast, src addr is mcast");
+			return NET_DROP;
+		}
+
+		/* Someone wants to know our ll address */
+		addr = if_get_addr(net_pkt_iface(pkt), &arp_hdr->dst_ipaddr);
+		if (!addr) {
+			/* Not for us so drop the packet silently */
+			return NET_DROP;
+		}
+
+		NET_DBG("ARP request from %s [%s] for %s",
+			log_strdup(net_sprint_ipv4_addr(&arp_hdr->src_ipaddr)),
+			log_strdup(net_sprint_ll_addr(
+					   (uint8_t *)&arp_hdr->src_hwaddr,
+					   arp_hdr->hwlen)),
+			log_strdup(net_sprint_ipv4_addr(
+					   &arp_hdr->dst_ipaddr)));
+
+		/* Update the ARP cache if the sender MAC address has
+		 * changed. In this case the target MAC address is all zeros
+		 * and the target IP address is our address.
+		 */
+		if (net_eth_is_addr_unspecified(&arp_hdr->dst_hwaddr)) {
+			NET_DBG("Updating ARP cache for %s [%s]",
+				log_strdup(net_sprint_ipv4_addr(
+						 &arp_hdr->src_ipaddr)),
+				log_strdup(net_sprint_ll_addr(
+						 (uint8_t *)&arp_hdr->src_hwaddr,
+						 arp_hdr->hwlen)));
+
+			arp_update(net_pkt_iface(pkt),
+				   &arp_hdr->src_ipaddr,
+				   &arp_hdr->src_hwaddr,
+				   false, true);
+
+			dst_hw_addr = &arp_hdr->src_hwaddr;
+		} else {
+			dst_hw_addr = &eth_hdr->src;
+		}
+
+		/* Send reply */
+		reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, eth_hdr,
+					  dst_hw_addr);
+		if (reply) {
+			net_if_queue_tx(net_pkt_iface(reply), reply);
+		} else {
+			NET_DBG("Cannot send ARP reply");
+		}
+		break;
+
+	case NET_ARP_REPLY:
+		if (net_ipv4_is_my_addr(&arp_hdr->dst_ipaddr)) {
+			arp_update(net_pkt_iface(pkt),
+				   &arp_hdr->src_ipaddr,
+				   &arp_hdr->src_hwaddr,
+				   false, false);
+		}
+
+		break;
+	}
+
+	net_pkt_unref(pkt);
+
+	return NET_OK;
+}
+
+void net_arp_clear_cache(struct net_if *iface)
+{
+	sys_snode_t *prev = NULL;
+	struct arp_entry *entry, *next;
+
+	NET_DBG("Flushing ARP table");
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&arp_table, entry, next, node) {
+		if (iface && iface != entry->iface) {
+			prev = &entry->node;
+			continue;
+		}
+
+		arp_entry_cleanup(entry, false);
+
+		sys_slist_remove(&arp_table, prev, &entry->node);
+		sys_slist_prepend(&arp_free_entries, &entry->node);
+	}
+
+	prev = NULL;
+
+	NET_DBG("Flushing ARP pending requests");
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&arp_pending_entries,
+					  entry, next, node) {
+		if (iface && iface != entry->iface) {
+			prev = &entry->node;
+			continue;
+		}
+
+		arp_entry_cleanup(entry, true);
+
+		sys_slist_remove(&arp_pending_entries, prev, &entry->node);
+		sys_slist_prepend(&arp_free_entries, &entry->node);
+	}
+
+	if (sys_slist_is_empty(&arp_pending_entries)) {
+		k_delayed_work_cancel(&arp_request_timer);
+	}
+}
+
+int net_arp_foreach(net_arp_cb_t cb, void *user_data)
+{
+	int ret = 0;
+	struct arp_entry *entry;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&arp_table, entry, node) {
+		ret++;
+		cb(entry, user_data);
+	}
+
+	return ret;
+}
+
+void net_arp_init(void)
+{
+	int i;
+
+	if (arp_cache_initialized) {
+		return;
+	}
+
+	sys_slist_init(&arp_free_entries);
+	sys_slist_init(&arp_pending_entries);
+	sys_slist_init(&arp_table);
+
+	for (i = 0; i < CONFIG_NET_ARP_TABLE_SIZE; i++) {
+		/* Inserting entry as free */
+		sys_slist_prepend(&arp_free_entries, &arp_entries[i].node);
+	}
+
+	k_delayed_work_init(&arp_request_timer, arp_request_timeout);
+
+	arp_cache_initialized = true;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/eth_stats.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/eth_stats.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/eth_stats.h	(working copy)
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ETH_STATS_H__
+#define __ETH_STATS_H__
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET)
+
+#include <net/net_ip.h>
+#include <net/net_stats.h>
+#include <net/net_if.h>
+
+static inline void eth_stats_update_bytes_rx(struct net_if *iface,
+					     uint32_t bytes)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->bytes.received += bytes;
+}
+
+static inline void eth_stats_update_bytes_tx(struct net_if *iface,
+					     uint32_t bytes)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->bytes.sent += bytes;
+}
+
+static inline void eth_stats_update_pkts_rx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->pkts.rx++;
+}
+
+static inline void eth_stats_update_pkts_tx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->pkts.tx++;
+}
+
+static inline void eth_stats_update_broadcast_rx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->broadcast.rx++;
+}
+
+static inline void eth_stats_update_broadcast_tx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->broadcast.tx++;
+}
+
+static inline void eth_stats_update_multicast_rx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->multicast.rx++;
+}
+
+static inline void eth_stats_update_multicast_tx(struct net_if *iface)
+{
+	const struct ethernet_api *api = (const struct ethernet_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_eth *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->multicast.tx++;
+}
+
+
+static inline void eth_stats_update_errors_rx(struct net_if *iface)
+{
+	struct net_stats_eth *stats;
+	const struct ethernet_api *api;
+
+	if (!iface) {
+		return;
+	}
+
+	api = ((const struct ethernet_api *)
+	       net_if_get_device(iface)->api);
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->errors.rx++;
+}
+
+static inline void eth_stats_update_errors_tx(struct net_if *iface)
+{
+	struct net_stats_eth *stats;
+	const struct ethernet_api *api = ((const struct ethernet_api *)
+		net_if_get_device(iface)->api);
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->errors.tx++;
+}
+
+#else /* CONFIG_NET_STATISTICS_ETHERNET */
+
+#define eth_stats_update_bytes_rx(iface, bytes)
+#define eth_stats_update_bytes_tx(iface, bytes)
+#define eth_stats_update_pkts_rx(iface)
+#define eth_stats_update_pkts_tx(iface)
+#define eth_stats_update_broadcast_rx(iface)
+#define eth_stats_update_broadcast_tx(iface)
+#define eth_stats_update_multicast_rx(iface)
+#define eth_stats_update_multicast_tx(iface)
+#define eth_stats_update_errors_rx(iface)
+#define eth_stats_update_errors_tx(iface)
+
+#endif /* CONFIG_NET_STATISTICS_ETHERNET */
+
+#endif /* __ETH_STATS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet.c	(working copy)
@@ -0,0 +1,1180 @@
+/*
+ * Copyright (c) 2016-2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+#include <net/ethernet.h>
+#include <net/ethernet_mgmt.h>
+#include <net/gptp.h>
+#include <random/rand32.h>
+
+#if defined(CONFIG_NET_LLDP)
+#include <net/lldp.h>
+#endif
+
+#include <syscall_handler.h>
+#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
+#include <net/can.h>
+#endif
+
+#include "arp.h"
+#include "eth_stats.h"
+#include "net_private.h"
+#include "ipv6.h"
+#include "ipv4_autoconf_internal.h"
+
+#define NET_BUF_TIMEOUT K_MSEC(100)
+
+static const struct net_eth_addr multicast_eth_addr __unused = {
+	{ 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 } };
+
+static const struct net_eth_addr broadcast_eth_addr = {
+	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
+
+const struct net_eth_addr *net_eth_broadcast_addr(void)
+{
+	return &broadcast_eth_addr;
+}
+
+void net_eth_ipv6_mcast_to_mac_addr(const struct in6_addr *ipv6_addr,
+				    struct net_eth_addr *mac_addr)
+{
+	/* RFC 2464 7. Address Mapping -- Multicast
+	 * "An IPv6 packet with a multicast destination address DST,
+	 * consisting of the sixteen octets DST[1] through DST[16],
+	 * is transmitted to the Ethernet multicast address whose
+	 * first two octets are the value 3333 hexadecimal and whose
+	 * last four octets are the last four octets of DST."
+	 */
+	mac_addr->addr[0] = mac_addr->addr[1] = 0x33;
+	memcpy(mac_addr->addr + 2, &ipv6_addr->s6_addr[12], 4);
+}
+
+#define print_ll_addrs(pkt, type, len, src, dst)			   \
+	if (CONFIG_NET_L2_ETHERNET_LOG_LEVEL >= LOG_LEVEL_DBG) {	   \
+		char out[sizeof("xx:xx:xx:xx:xx:xx")];			   \
+									   \
+		snprintk(out, sizeof(out), "%s",			   \
+			 net_sprint_ll_addr((src)->addr,		   \
+					    sizeof(struct net_eth_addr))); \
+									   \
+		NET_DBG("iface %p src %s dst %s type 0x%x len %zu",	   \
+			net_pkt_iface(pkt), log_strdup(out),		   \
+			log_strdup(net_sprint_ll_addr((dst)->addr,	   \
+					    sizeof(struct net_eth_addr))), \
+			type, (size_t)len);				   \
+	}
+
+#ifdef CONFIG_NET_VLAN
+#define print_vlan_ll_addrs(pkt, type, tci, len, src, dst, tagstrip)       \
+	if (CONFIG_NET_L2_ETHERNET_LOG_LEVEL >= LOG_LEVEL_DBG) {	   \
+		char out[sizeof("xx:xx:xx:xx:xx:xx")];			   \
+									   \
+		snprintk(out, sizeof(out), "%s",			   \
+			 net_sprint_ll_addr((src)->addr,		   \
+					    sizeof(struct net_eth_addr))); \
+									   \
+		NET_DBG("iface %p src %s dst %s type 0x%x "		   \
+			"tag %d %spri %d len %zu",			   \
+			net_pkt_iface(pkt), log_strdup(out),		   \
+			log_strdup(net_sprint_ll_addr((dst)->addr,	   \
+				   sizeof(struct net_eth_addr))),	   \
+			type, net_eth_vlan_get_vid(tci),		   \
+			tagstrip ? "(stripped) " : "",			   \
+			net_eth_vlan_get_pcp(tci), (size_t)len);	   \
+	}
+#else
+#define print_vlan_ll_addrs(...)
+#endif /* CONFIG_NET_VLAN */
+
+static inline void ethernet_update_length(struct net_if *iface,
+					  struct net_pkt *pkt)
+{
+	uint16_t len;
+
+	/* Let's check IP payload's length. If it's smaller than 46 bytes,
+	 * i.e. smaller than minimal Ethernet frame size minus ethernet
+	 * header size,then Ethernet has padded so it fits in the minimal
+	 * frame size of 60 bytes. In that case, we need to get rid of it.
+	 */
+
+	if (net_pkt_family(pkt) == AF_INET) {
+		len = ntohs(NET_IPV4_HDR(pkt)->len);
+	} else {
+		len = ntohs(NET_IPV6_HDR(pkt)->len) + NET_IPV6H_LEN;
+	}
+
+	if (len < NET_ETH_MINIMAL_FRAME_SIZE - sizeof(struct net_eth_hdr)) {
+		struct net_buf *frag;
+
+		for (frag = pkt->frags; frag; frag = frag->frags) {
+			if (frag->len < len) {
+				len -= frag->len;
+			} else {
+				frag->len = len;
+				len = 0U;
+			}
+		}
+	}
+}
+
+static void ethernet_update_rx_stats(struct net_if *iface,
+				     struct net_pkt *pkt, size_t length)
+{
+#if defined(CONFIG_NET_STATISTICS_ETHERNET)
+	struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
+
+	eth_stats_update_bytes_rx(iface, length);
+	eth_stats_update_pkts_rx(iface);
+
+	if (net_eth_is_addr_broadcast(&hdr->dst)) {
+		eth_stats_update_broadcast_rx(iface);
+	} else if (net_eth_is_addr_multicast(&hdr->dst)) {
+		eth_stats_update_multicast_rx(iface);
+	}
+#endif /* CONFIG_NET_STATISTICS_ETHERNET */
+}
+
+static inline bool eth_is_vlan_tag_stripped(struct net_if *iface)
+{
+	const struct device *dev = net_if_get_device(iface);
+	const struct ethernet_api *api = dev->api;
+
+	return (api->get_capabilities(dev) & ETHERNET_HW_VLAN_TAG_STRIP);
+}
+
+/* Drop packet if it has broadcast destination MAC address but the IP
+ * address is not multicast or broadcast address. See RFC 1122 ch 3.3.6
+ */
+static inline
+enum net_verdict ethernet_check_ipv4_bcast_addr(struct net_pkt *pkt,
+						struct net_eth_hdr *hdr)
+{
+	if (net_eth_is_addr_broadcast(&hdr->dst) &&
+	    !(net_ipv4_is_addr_mcast(&NET_IPV4_HDR(pkt)->dst) ||
+	      net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
+				     &NET_IPV4_HDR(pkt)->dst))) {
+		return NET_DROP;
+	}
+
+	return NET_OK;
+}
+
+static enum net_verdict ethernet_recv(struct net_if *iface,
+				      struct net_pkt *pkt)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
+	uint8_t hdr_len = sizeof(struct net_eth_hdr);
+	uint16_t type;
+	struct net_linkaddr *lladdr;
+	sa_family_t family;
+
+	/* This expects that the Ethernet header is in the first net_buf
+	 * fragment. This is a safe expectation here as it would not make
+	 * any sense to split the Ethernet header to two net_buf's by the
+	 * Ethernet driver.
+	 */
+	if (hdr == NULL || pkt->buffer->len < hdr_len) {
+		goto drop;
+	}
+
+	type = ntohs(hdr->type);
+
+	if (net_eth_is_vlan_enabled(ctx, iface) &&
+	    type == NET_ETH_PTYPE_VLAN &&
+	    !eth_is_vlan_tag_stripped(iface)) {
+		struct net_eth_vlan_hdr *hdr_vlan =
+			(struct net_eth_vlan_hdr *)NET_ETH_HDR(pkt);
+
+		net_pkt_set_vlan_tci(pkt, ntohs(hdr_vlan->vlan.tci));
+		type = ntohs(hdr_vlan->type);
+		hdr_len = sizeof(struct net_eth_vlan_hdr);
+	}
+
+	switch (type) {
+	case NET_ETH_PTYPE_IP:
+	case NET_ETH_PTYPE_ARP:
+		net_pkt_set_family(pkt, AF_INET);
+		family = AF_INET;
+		break;
+	case NET_ETH_PTYPE_IPV6:
+		net_pkt_set_family(pkt, AF_INET6);
+		family = AF_INET6;
+		break;
+#if defined(CONFIG_NET_GPTP)
+	case NET_ETH_PTYPE_PTP:
+		family = AF_UNSPEC;
+		break;
+#endif
+	case NET_ETH_PTYPE_LLDP:
+#if defined(CONFIG_NET_LLDP)
+		net_buf_pull(pkt->frags, hdr_len);
+		return net_lldp_recv(iface, pkt);
+#else
+		NET_DBG("LLDP Rx agent not enabled");
+		goto drop;
+#endif
+	default:
+		NET_DBG("Unknown hdr type 0x%04x iface %p", type, iface);
+		goto drop;
+	}
+
+	/* Set the pointers to ll src and dst addresses */
+	lladdr = net_pkt_lladdr_src(pkt);
+	lladdr->addr = hdr->src.addr;
+	lladdr->len = sizeof(struct net_eth_addr);
+	lladdr->type = NET_LINK_ETHERNET;
+
+	lladdr = net_pkt_lladdr_dst(pkt);
+	lladdr->addr = hdr->dst.addr;
+	lladdr->len = sizeof(struct net_eth_addr);
+	lladdr->type = NET_LINK_ETHERNET;
+
+	if (net_eth_is_vlan_enabled(ctx, iface)) {
+		if (type == NET_ETH_PTYPE_VLAN ||
+		    (eth_is_vlan_tag_stripped(iface) &&
+		     net_pkt_vlan_tci(pkt))) {
+			print_vlan_ll_addrs(pkt, type, net_pkt_vlan_tci(pkt),
+					    net_pkt_get_len(pkt),
+					    net_pkt_lladdr_src(pkt),
+					    net_pkt_lladdr_dst(pkt),
+					    eth_is_vlan_tag_stripped(iface));
+		} else {
+			print_ll_addrs(pkt, type, net_pkt_get_len(pkt),
+				       net_pkt_lladdr_src(pkt),
+				       net_pkt_lladdr_dst(pkt));
+		}
+	} else {
+		print_ll_addrs(pkt, type, net_pkt_get_len(pkt),
+			       net_pkt_lladdr_src(pkt),
+			       net_pkt_lladdr_dst(pkt));
+	}
+
+#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
+	if (net_canbus_translate_eth_frame(iface, pkt) == NET_OK) {
+		return NET_OK;
+	}
+#endif
+
+	if (!net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr) &&
+	    !net_eth_is_addr_multicast((struct net_eth_addr *)lladdr->addr) &&
+	    !net_eth_is_addr_lldp_multicast(
+		    (struct net_eth_addr *)lladdr->addr) &&
+	    !net_linkaddr_cmp(net_if_get_link_addr(iface), lladdr)) {
+		/* The ethernet frame is not for me as the link addresses
+		 * are different.
+		 */
+		NET_DBG("Dropping frame, not for me [%s]",
+			log_strdup(net_sprint_ll_addr(
+					   net_if_get_link_addr(iface)->addr,
+					   sizeof(struct net_eth_addr))));
+		goto drop;
+	}
+
+	net_buf_pull(pkt->frags, hdr_len);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && type == NET_ETH_PTYPE_IP &&
+	    ethernet_check_ipv4_bcast_addr(pkt, hdr) == NET_DROP) {
+		goto drop;
+	}
+
+	ethernet_update_rx_stats(iface, pkt, net_pkt_get_len(pkt) + hdr_len);
+
+	if (IS_ENABLED(CONFIG_NET_ARP) &&
+	    family == AF_INET && type == NET_ETH_PTYPE_ARP) {
+		NET_DBG("ARP packet from %s received",
+			log_strdup(net_sprint_ll_addr(
+					   (uint8_t *)hdr->src.addr,
+					   sizeof(struct net_eth_addr))));
+
+		if (IS_ENABLED(CONFIG_NET_IPV4_AUTO) &&
+		    net_ipv4_autoconf_input(iface, pkt) == NET_DROP) {
+			return NET_DROP;
+		}
+
+		return net_arp_input(pkt, hdr);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_GPTP) && type == NET_ETH_PTYPE_PTP) {
+		return net_gptp_recv(iface, pkt);
+	}
+
+	ethernet_update_length(iface, pkt);
+
+	return NET_CONTINUE;
+drop:
+	eth_stats_update_errors_rx(iface);
+	return NET_DROP;
+}
+
+#ifdef CONFIG_NET_IPV4
+static inline bool ethernet_ipv4_dst_is_broadcast_or_mcast(struct net_pkt *pkt)
+{
+	if (net_ipv4_is_addr_bcast(net_pkt_iface(pkt),
+				   &NET_IPV4_HDR(pkt)->dst) ||
+	    net_ipv4_is_addr_mcast(&NET_IPV4_HDR(pkt)->dst)) {
+		return true;
+	}
+
+	return false;
+}
+
+static bool ethernet_fill_in_dst_on_ipv4_mcast(struct net_pkt *pkt,
+					       struct net_eth_addr *dst)
+{
+	if (net_pkt_family(pkt) == AF_INET &&
+	    net_ipv4_is_addr_mcast(&NET_IPV4_HDR(pkt)->dst)) {
+		/* Multicast address */
+		dst->addr[0] = 0x01;
+		dst->addr[1] = 0x00;
+		dst->addr[2] = 0x5e;
+		dst->addr[3] = NET_IPV4_HDR(pkt)->dst.s4_addr[1];
+		dst->addr[4] = NET_IPV4_HDR(pkt)->dst.s4_addr[2];
+		dst->addr[5] = NET_IPV4_HDR(pkt)->dst.s4_addr[3];
+
+		dst->addr[3] &= 0x7f;
+
+		return true;
+	}
+
+	return false;
+}
+
+static struct net_pkt *ethernet_ll_prepare_on_ipv4(struct net_if *iface,
+						   struct net_pkt *pkt)
+{
+	if (ethernet_ipv4_dst_is_broadcast_or_mcast(pkt)) {
+		return pkt;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_ARP)) {
+		struct net_pkt *arp_pkt;
+
+		arp_pkt = net_arp_prepare(pkt, &NET_IPV4_HDR(pkt)->dst, NULL);
+		if (!arp_pkt) {
+			return NULL;
+		}
+
+		if (pkt != arp_pkt) {
+			NET_DBG("Sending arp pkt %p (orig %p) to iface %p",
+				arp_pkt, pkt, iface);
+			net_pkt_unref(pkt);
+			return arp_pkt;
+		}
+
+		NET_DBG("Found ARP entry, sending pkt %p to iface %p",
+			pkt, iface);
+	}
+
+	return pkt;
+}
+#else
+#define ethernet_ipv4_dst_is_broadcast_or_mcast(...) false
+#define ethernet_fill_in_dst_on_ipv4_mcast(...) false
+#define ethernet_ll_prepare_on_ipv4(...) NULL
+#endif /* CONFIG_NET_IPV4 */
+
+#ifdef CONFIG_NET_IPV6
+static bool ethernet_fill_in_dst_on_ipv6_mcast(struct net_pkt *pkt,
+					       struct net_eth_addr *dst)
+{
+	if (net_pkt_family(pkt) == AF_INET6 &&
+	    net_ipv6_is_addr_mcast(&NET_IPV6_HDR(pkt)->dst)) {
+		memcpy(dst, (uint8_t *)multicast_eth_addr.addr,
+		       sizeof(struct net_eth_addr) - 4);
+		memcpy((uint8_t *)dst + 2,
+		       (uint8_t *)(&NET_IPV6_HDR(pkt)->dst) + 12,
+		       sizeof(struct net_eth_addr) - 2);
+
+		return true;
+	}
+
+	return false;
+}
+#else
+#define ethernet_fill_in_dst_on_ipv6_mcast(...) false
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_VLAN)
+static enum net_verdict set_vlan_tag(struct ethernet_context *ctx,
+				     struct net_if *iface,
+				     struct net_pkt *pkt)
+{
+	int i;
+
+	if (net_pkt_vlan_tag(pkt) != NET_VLAN_TAG_UNSPEC) {
+		return NET_OK;
+	}
+
+#if defined(CONFIG_NET_IPV6)
+	if (net_pkt_family(pkt) == AF_INET6) {
+		struct net_if *target;
+
+		if (net_if_ipv6_addr_lookup(&NET_IPV6_HDR(pkt)->src,
+					    &target)) {
+			if (target != iface) {
+				NET_DBG("Iface %p should be %p", iface,
+					target);
+
+				iface = target;
+			}
+		}
+	}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+	if (net_pkt_family(pkt) == AF_INET) {
+		struct net_if *target;
+
+		if (net_if_ipv4_addr_lookup(&NET_IPV4_HDR(pkt)->src,
+					    &target)) {
+			if (target != iface) {
+				NET_DBG("Iface %p should be %p", iface,
+					target);
+				iface = target;
+			}
+		}
+	}
+#endif
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC ||
+		    ctx->vlan[i].iface != iface) {
+			continue;
+		}
+
+		/* Depending on source address, use the proper network
+		 * interface when sending.
+		 */
+		net_pkt_set_vlan_tag(pkt, ctx->vlan[i].tag);
+
+		return NET_OK;
+	}
+
+	return NET_DROP;
+}
+
+static void set_vlan_priority(struct ethernet_context *ctx,
+			      struct net_pkt *pkt)
+{
+	uint8_t vlan_priority;
+
+	vlan_priority = net_priority2vlan(net_pkt_priority(pkt));
+	net_pkt_set_vlan_priority(pkt, vlan_priority);
+}
+#else
+#define set_vlan_tag(...) NET_DROP
+#define set_vlan_priority(...)
+#endif /* CONFIG_NET_VLAN */
+
+static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx,
+					    struct net_pkt *pkt,
+					    uint32_t ptype)
+{
+	struct net_buf *hdr_frag;
+	struct net_eth_hdr *hdr;
+
+	hdr_frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
+	if (!hdr_frag) {
+		return NULL;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_VLAN) &&
+	    net_eth_is_vlan_enabled(ctx, net_pkt_iface(pkt))) {
+		struct net_eth_vlan_hdr *hdr_vlan;
+
+		hdr_vlan = (struct net_eth_vlan_hdr *)(hdr_frag->data);
+
+		if (!ethernet_fill_in_dst_on_ipv4_mcast(pkt, &hdr_vlan->dst) &&
+		    !ethernet_fill_in_dst_on_ipv6_mcast(pkt, &hdr_vlan->dst)) {
+			memcpy(&hdr_vlan->dst, net_pkt_lladdr_dst(pkt)->addr,
+			       sizeof(struct net_eth_addr));
+		}
+
+		memcpy(&hdr_vlan->src, net_pkt_lladdr_src(pkt)->addr,
+		       sizeof(struct net_eth_addr));
+
+		hdr_vlan->type = ptype;
+		hdr_vlan->vlan.tpid = htons(NET_ETH_PTYPE_VLAN);
+		hdr_vlan->vlan.tci = htons(net_pkt_vlan_tci(pkt));
+		net_buf_add(hdr_frag, sizeof(struct net_eth_vlan_hdr));
+
+		print_vlan_ll_addrs(pkt, ntohs(hdr_vlan->type),
+				    net_pkt_vlan_tci(pkt),
+				    hdr_frag->len,
+				    &hdr_vlan->src, &hdr_vlan->dst, false);
+	} else {
+		hdr = (struct net_eth_hdr *)(hdr_frag->data);
+
+		if (!ethernet_fill_in_dst_on_ipv4_mcast(pkt, &hdr->dst) &&
+		    !ethernet_fill_in_dst_on_ipv6_mcast(pkt, &hdr->dst)) {
+			memcpy(&hdr->dst, net_pkt_lladdr_dst(pkt)->addr,
+			       sizeof(struct net_eth_addr));
+		}
+
+		memcpy(&hdr->src, net_pkt_lladdr_src(pkt)->addr,
+		       sizeof(struct net_eth_addr));
+
+		hdr->type = ptype;
+		net_buf_add(hdr_frag, sizeof(struct net_eth_hdr));
+
+		print_ll_addrs(pkt, ntohs(hdr->type),
+			       hdr_frag->len, &hdr->src, &hdr->dst);
+	}
+
+	net_pkt_frag_insert(pkt, hdr_frag);
+
+	return hdr_frag;
+}
+
+#if defined(CONFIG_NET_STATISTICS_ETHERNET)
+static void ethernet_update_tx_stats(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
+
+	eth_stats_update_bytes_tx(iface, net_pkt_get_len(pkt));
+	eth_stats_update_pkts_tx(iface);
+
+	if (net_eth_is_addr_multicast(&hdr->dst)) {
+		eth_stats_update_multicast_tx(iface);
+	} else if (net_eth_is_addr_broadcast(&hdr->dst)) {
+		eth_stats_update_broadcast_tx(iface);
+	}
+}
+#else
+#define ethernet_update_tx_stats(...)
+#endif /* CONFIG_NET_STATISTICS_ETHERNET */
+
+static void ethernet_remove_l2_header(struct net_pkt *pkt)
+{
+	struct net_buf *buf;
+
+	/* Remove the buffer added in ethernet_fill_header() */
+	buf = pkt->buffer;
+	pkt->buffer = buf->frags;
+	buf->frags = NULL;
+
+	net_pkt_frag_unref(buf);
+}
+
+static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	const struct ethernet_api *api = net_if_get_device(iface)->api;
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	uint16_t ptype;
+	int ret;
+
+	if (!api) {
+		ret = -ENOENT;
+		goto error;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		struct net_pkt *tmp;
+
+		if (net_pkt_ipv4_auto(pkt)) {
+			ptype = htons(NET_ETH_PTYPE_ARP);
+		} else {
+			tmp = ethernet_ll_prepare_on_ipv4(iface, pkt);
+			if (!tmp) {
+				ret = -ENOMEM;
+				goto error;
+			} else if (IS_ENABLED(CONFIG_NET_ARP) && tmp != pkt) {
+				/* Original pkt got queued and is replaced
+				 * by an ARP request packet.
+				 */
+				pkt = tmp;
+				ptype = htons(NET_ETH_PTYPE_ARP);
+				net_pkt_set_family(pkt, AF_INET);
+			} else {
+				ptype = htons(NET_ETH_PTYPE_IP);
+			}
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		ptype = htons(NET_ETH_PTYPE_IPV6);
+	} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
+		   net_pkt_family(pkt) == AF_PACKET) {
+		struct net_context *context = net_pkt_context(pkt);
+
+		if (context && net_context_get_type(context) == SOCK_DGRAM) {
+			struct sockaddr_ll *dst_addr;
+			struct sockaddr_ll_ptr *src_addr;
+
+			/* The destination address is set in remote for this
+			 * socket type.
+			 */
+			dst_addr = (struct sockaddr_ll *)&context->remote;
+			src_addr = (struct sockaddr_ll_ptr *)&context->local;
+
+			net_pkt_lladdr_dst(pkt)->addr = dst_addr->sll_addr;
+			net_pkt_lladdr_dst(pkt)->len =
+						sizeof(struct net_eth_addr);
+			net_pkt_lladdr_src(pkt)->addr = src_addr->sll_addr;
+			net_pkt_lladdr_src(pkt)->len =
+						sizeof(struct net_eth_addr);
+			ptype = dst_addr->sll_protocol;
+		} else {
+			goto send;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_GPTP) && net_pkt_is_gptp(pkt)) {
+		ptype = htons(NET_ETH_PTYPE_PTP);
+	} else if (IS_ENABLED(CONFIG_NET_LLDP) && net_pkt_is_lldp(pkt)) {
+		ptype = htons(NET_ETH_PTYPE_LLDP);
+	} else if (IS_ENABLED(CONFIG_NET_ARP)) {
+		/* Unktown type: Unqueued pkt is an ARP reply.
+		 */
+		ptype = htons(NET_ETH_PTYPE_ARP);
+		net_pkt_set_family(pkt, AF_INET);
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* If the ll dst addr has not been set before, let's assume
+	 * temporarily it's a broadcast one. When filling the header,
+	 * it might detect this should be multicast and act accordingly.
+	 */
+	if (!net_pkt_lladdr_dst(pkt)->addr) {
+		net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)broadcast_eth_addr.addr;
+		net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_VLAN) &&
+	    net_eth_is_vlan_enabled(ctx, iface)) {
+		if (set_vlan_tag(ctx, iface, pkt) == NET_DROP) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		set_vlan_priority(ctx, pkt);
+	}
+
+	/* Then set the ethernet header.
+	 */
+	if (!ethernet_fill_header(ctx, pkt, ptype)) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	net_pkt_cursor_init(pkt);
+
+send:
+	ret = api->send(net_if_get_device(iface), pkt);
+	if (ret != 0) {
+		eth_stats_update_errors_tx(iface);
+		ethernet_remove_l2_header(pkt);
+		goto error;
+	}
+
+	ethernet_update_tx_stats(iface, pkt);
+
+	ret = net_pkt_get_len(pkt);
+	ethernet_remove_l2_header(pkt);
+
+	net_pkt_unref(pkt);
+error:
+	return ret;
+}
+
+static inline int ethernet_enable(struct net_if *iface, bool state)
+{
+	const struct ethernet_api *eth =
+		net_if_get_device(iface)->api;
+
+	if (!eth) {
+		return -ENOENT;
+	}
+
+	if (!state) {
+		net_arp_clear_cache(iface);
+
+		if (eth->stop) {
+			eth->stop(net_if_get_device(iface));
+		}
+	} else {
+		if (eth->start) {
+			eth->start(net_if_get_device(iface));
+		}
+	}
+
+	return 0;
+}
+
+enum net_l2_flags ethernet_flags(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	return ctx->ethernet_l2_flags;
+}
+
+#if defined(CONFIG_NET_VLAN)
+struct net_if *net_eth_get_vlan_iface(struct net_if *iface, uint16_t tag)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	struct net_if *first_non_vlan_iface = NULL;
+	int i;
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (ctx->vlan[i].tag == NET_VLAN_TAG_UNSPEC) {
+			if (!first_non_vlan_iface) {
+				first_non_vlan_iface = ctx->vlan[i].iface;
+			}
+
+			continue;
+		}
+
+		if (ctx->vlan[i].tag != tag) {
+			continue;
+		}
+
+		NET_DBG("[%d] vlan tag %d -> iface %p", i, tag,
+			ctx->vlan[i].iface);
+
+		return ctx->vlan[i].iface;
+	}
+
+	return first_non_vlan_iface;
+}
+
+static bool enable_vlan_iface(struct ethernet_context *ctx,
+			      struct net_if *iface)
+{
+	int iface_idx = net_if_get_by_iface(iface);
+
+	if (iface_idx < 0) {
+		return false;
+	}
+
+	atomic_set_bit(ctx->interfaces, iface_idx);
+
+	return true;
+}
+
+static bool disable_vlan_iface(struct ethernet_context *ctx,
+			       struct net_if *iface)
+{
+	int iface_idx = net_if_get_by_iface(iface);
+
+	if (iface_idx < 0) {
+		return false;
+	}
+
+	atomic_clear_bit(ctx->interfaces, iface_idx);
+
+	return true;
+}
+
+static bool is_vlan_enabled_for_iface(struct ethernet_context *ctx,
+				      struct net_if *iface)
+{
+	int iface_idx = net_if_get_by_iface(iface);
+
+	if (iface_idx < 0) {
+		return false;
+	}
+
+	return !!atomic_test_bit(ctx->interfaces, iface_idx);
+}
+
+bool net_eth_is_vlan_enabled(struct ethernet_context *ctx,
+			     struct net_if *iface)
+{
+	if (ctx->vlan_enabled) {
+		if (ctx->vlan_enabled == NET_VLAN_MAX_COUNT) {
+			/* All network interface are using VLAN, no need
+			 * to check further.
+			 */
+			return true;
+		}
+
+		if (is_vlan_enabled_for_iface(ctx, iface)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+uint16_t net_eth_get_vlan_tag(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	int i;
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (ctx->vlan[i].iface == iface) {
+			return ctx->vlan[i].tag;
+		}
+	}
+
+	return NET_VLAN_TAG_UNSPEC;
+}
+
+bool net_eth_get_vlan_status(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	if (ctx->vlan_enabled &&
+	    net_eth_get_vlan_tag(iface) != NET_VLAN_TAG_UNSPEC) {
+		return true;
+	}
+
+	return false;
+}
+
+static struct ethernet_vlan *get_vlan(struct ethernet_context *ctx,
+				      struct net_if *iface,
+				      uint16_t vlan_tag)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (ctx->vlan[i].iface == iface &&
+		    ctx->vlan[i].tag == vlan_tag) {
+			return &ctx->vlan[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void setup_ipv6_link_local_addr(struct net_if *iface)
+{
+	struct net_linkaddr link_addr;
+	struct net_if_addr *ifaddr;
+	struct in6_addr addr;
+	uint32_t entropy;
+	uint8_t mac_addr[6];
+
+	entropy = sys_rand32_get();
+	mac_addr[0] = entropy >> 0;
+	mac_addr[1] = entropy >> 8;
+	mac_addr[2] = entropy >> 16;
+
+	entropy = sys_rand32_get();
+	mac_addr[3] = entropy >> 0;
+	mac_addr[4] = entropy >> 8;
+	mac_addr[5] = entropy >> 16;
+
+	mac_addr[0] |= 0x02; /* force LAA bit */
+
+	link_addr.len = sizeof(mac_addr);
+	link_addr.type = NET_LINK_ETHERNET;
+	link_addr.addr = mac_addr;
+
+	net_ipv6_addr_create_iid(&addr, &link_addr);
+
+	ifaddr = net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, 0);
+	if (!ifaddr) {
+		NET_DBG("Cannot add %s address to VLAN interface %p",
+			log_strdup(net_sprint_ipv6_addr(&addr)), iface);
+	}
+}
+
+int net_eth_vlan_enable(struct net_if *iface, uint16_t tag)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	const struct ethernet_api *eth =
+		net_if_get_device(iface)->api;
+	struct ethernet_vlan *vlan;
+	int i;
+
+	if (!eth) {
+		return -ENOENT;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return -EINVAL;
+	}
+
+	if (!ctx->is_init) {
+		return -EPERM;
+	}
+
+	if (tag == NET_VLAN_TAG_UNSPEC) {
+		return -EBADF;
+	}
+
+	vlan = get_vlan(ctx, iface, tag);
+	if (vlan) {
+		return -EALREADY;
+	}
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (ctx->vlan[i].iface != iface) {
+			continue;
+		}
+
+		if (ctx->vlan[i].tag != NET_VLAN_TAG_UNSPEC) {
+			continue;
+		}
+
+		NET_DBG("[%d] Adding vlan tag %d to iface %p", i, tag, iface);
+
+		ctx->vlan[i].tag = tag;
+
+		/* Add a link local IPv6 address to VLAN interface here.
+		 * Each network interface needs LL address, but as there is
+		 * only one link (MAC) address defined for all the master and
+		 * slave interfaces, the VLAN interface might be left without
+		 * a LL address. In order to solve this issue, we create a
+		 * random LL address and set it to the VLAN network interface.
+		 */
+		if (IS_ENABLED(CONFIG_NET_IPV6)) {
+			setup_ipv6_link_local_addr(iface);
+		}
+
+		enable_vlan_iface(ctx, iface);
+
+		if (eth->vlan_setup) {
+			eth->vlan_setup(net_if_get_device(iface),
+					iface, tag, true);
+		}
+
+		ctx->vlan_enabled++;
+		if (ctx->vlan_enabled > NET_VLAN_MAX_COUNT) {
+			ctx->vlan_enabled = NET_VLAN_MAX_COUNT;
+		}
+
+		ethernet_mgmt_raise_vlan_enabled_event(iface, tag);
+
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int net_eth_vlan_disable(struct net_if *iface, uint16_t tag)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	const struct ethernet_api *eth =
+		net_if_get_device(iface)->api;
+	struct ethernet_vlan *vlan;
+
+	if (!eth) {
+		return -ENOENT;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return -EINVAL;
+	}
+
+	if (tag == NET_VLAN_TAG_UNSPEC) {
+		return -EBADF;
+	}
+
+	vlan = get_vlan(ctx, iface, tag);
+	if (!vlan) {
+		return -ESRCH;
+	}
+
+	NET_DBG("Removing vlan tag %d from iface %p", vlan->tag, vlan->iface);
+
+	vlan->tag = NET_VLAN_TAG_UNSPEC;
+
+	disable_vlan_iface(ctx, iface);
+
+	if (eth->vlan_setup) {
+		eth->vlan_setup(net_if_get_device(iface), iface, tag, false);
+	}
+
+	ethernet_mgmt_raise_vlan_disabled_event(iface, tag);
+
+	ctx->vlan_enabled--;
+	if (ctx->vlan_enabled < 0) {
+		ctx->vlan_enabled = 0;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_NET_VLAN */
+
+NET_L2_INIT(ETHERNET_L2, ethernet_recv, ethernet_send, ethernet_enable,
+	    ethernet_flags);
+
+static void carrier_on(struct k_work *work)
+{
+	struct ethernet_context *ctx = CONTAINER_OF(work,
+						    struct ethernet_context,
+						    carrier_mgmt.work);
+
+	NET_DBG("Carrier ON for interface %p", ctx->carrier_mgmt.iface);
+
+	ethernet_mgmt_raise_carrier_on_event(ctx->carrier_mgmt.iface);
+
+	net_if_up(ctx->carrier_mgmt.iface);
+}
+
+static void carrier_off(struct k_work *work)
+{
+	struct ethernet_context *ctx = CONTAINER_OF(work,
+						    struct ethernet_context,
+						    carrier_mgmt.work);
+
+	NET_DBG("Carrier OFF for interface %p", ctx->carrier_mgmt.iface);
+
+	ethernet_mgmt_raise_carrier_off_event(ctx->carrier_mgmt.iface);
+
+	net_if_carrier_down(ctx->carrier_mgmt.iface);
+}
+
+static void handle_carrier(struct ethernet_context *ctx,
+			   struct net_if *iface,
+			   k_work_handler_t handler)
+{
+	k_work_init(&ctx->carrier_mgmt.work, handler);
+
+	ctx->carrier_mgmt.iface = iface;
+
+	k_work_submit(&ctx->carrier_mgmt.work);
+}
+
+void net_eth_carrier_on(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	handle_carrier(ctx, iface, carrier_on);
+}
+
+void net_eth_carrier_off(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	handle_carrier(ctx, iface, carrier_off);
+}
+
+#if defined(CONFIG_PTP_CLOCK)
+const struct device *net_eth_get_ptp_clock(struct net_if *iface)
+{
+	const struct device *dev = net_if_get_device(iface);
+	const struct ethernet_api *api = dev->api;
+
+	if (!api) {
+		return NULL;
+	}
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return NULL;
+	}
+
+	if (!(api->get_capabilities(dev) & ETHERNET_PTP)) {
+		return NULL;
+	}
+
+	if (!api->get_ptp_clock) {
+		return NULL;
+	}
+
+	return api->get_ptp_clock(net_if_get_device(iface));
+}
+#endif /* CONFIG_PTP_CLOCK */
+
+#if defined(CONFIG_PTP_CLOCK)
+const struct device *z_impl_net_eth_get_ptp_clock_by_index(int index)
+{
+	struct net_if *iface;
+
+	iface = net_if_get_by_index(index);
+	if (!iface) {
+		return NULL;
+	}
+
+	return net_eth_get_ptp_clock(iface);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline const struct device *z_vrfy_net_eth_get_ptp_clock_by_index(int index)
+{
+	return z_impl_net_eth_get_ptp_clock_by_index(index);
+}
+#include <syscalls/net_eth_get_ptp_clock_by_index_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+#else /* CONFIG_PTP_CLOCK */
+const struct device *z_impl_net_eth_get_ptp_clock_by_index(int index)
+{
+	ARG_UNUSED(index);
+
+	return NULL;
+}
+#endif /* CONFIG_PTP_CLOCK */
+
+#if defined(CONFIG_NET_GPTP)
+int net_eth_get_ptp_port(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	return ctx->port;
+}
+
+void net_eth_set_ptp_port(struct net_if *iface, int port)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+	ctx->port = port;
+}
+#endif /* CONFIG_NET_GPTP */
+
+int net_eth_promisc_mode(struct net_if *iface, bool enable)
+{
+	struct ethernet_req_params params;
+
+	if (!(net_eth_get_hw_capabilities(iface) & ETHERNET_PROMISC_MODE)) {
+		return -ENOTSUP;
+	}
+
+	params.promisc_mode = enable;
+
+	return net_mgmt(NET_REQUEST_ETHERNET_SET_PROMISC_MODE, iface,
+			&params, sizeof(struct ethernet_req_params));
+}
+
+void ethernet_init(struct net_if *iface)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+
+#if defined(CONFIG_NET_VLAN)
+	int i;
+#endif
+
+	NET_DBG("Initializing Ethernet L2 %p for iface %p", ctx, iface);
+
+	ctx->ethernet_l2_flags = NET_L2_MULTICAST;
+
+	if (net_eth_get_hw_capabilities(iface) & ETHERNET_PROMISC_MODE) {
+		ctx->ethernet_l2_flags |= NET_L2_PROMISC_MODE;
+	}
+
+#if defined(CONFIG_NET_VLAN)
+	if (!(net_eth_get_hw_capabilities(iface) & ETHERNET_HW_VLAN)) {
+		return;
+	}
+
+	for (i = 0; i < CONFIG_NET_VLAN_COUNT; i++) {
+		if (!ctx->vlan[i].iface) {
+			NET_DBG("[%d] alloc ctx %p iface %p", i, ctx, iface);
+			ctx->vlan[i].tag = NET_VLAN_TAG_UNSPEC;
+			ctx->vlan[i].iface = iface;
+
+			if (!ctx->is_init) {
+				atomic_clear(ctx->interfaces);
+			}
+
+			break;
+		}
+	}
+#endif
+
+	net_arp_init();
+
+	ctx->is_init = true;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_mgmt.c	(working copy)
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ethernet_mgmt, CONFIG_NET_L2_ETHERNET_LOG_LEVEL);
+
+#include <errno.h>
+
+#include <net/net_core.h>
+#include <net/net_if.h>
+#include <net/ethernet_mgmt.h>
+
+static inline bool is_hw_caps_supported(const struct device *dev,
+					enum ethernet_hw_caps caps)
+{
+	const struct ethernet_api *api = dev->api;
+
+	if (!api) {
+		return false;
+	}
+
+	return !!(api->get_capabilities(dev) & caps);
+}
+
+static int ethernet_set_config(uint32_t mgmt_request,
+			       struct net_if *iface,
+			       void *data, size_t len)
+{
+	struct ethernet_req_params *params = (struct ethernet_req_params *)data;
+	const struct device *dev = net_if_get_device(iface);
+	const struct ethernet_api *api = dev->api;
+	struct ethernet_config config = { 0 };
+	enum ethernet_config_type type;
+
+	if (!api) {
+		return -ENOENT;
+	}
+
+	if (!api->set_config) {
+		return -ENOTSUP;
+	}
+
+	if (!data || (len != sizeof(struct ethernet_req_params))) {
+		return -EINVAL;
+	}
+
+	if (mgmt_request == NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION) {
+		if (!is_hw_caps_supported(dev,
+					  ETHERNET_AUTO_NEGOTIATION_SET)) {
+			return -ENOTSUP;
+		}
+
+		config.auto_negotiation = params->auto_negotiation;
+		type = ETHERNET_CONFIG_TYPE_AUTO_NEG;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_SET_LINK) {
+		type = ETHERNET_CONFIG_TYPE_LINK;
+
+		if (params->l.link_10bt) {
+			if (!is_hw_caps_supported(dev,
+						  ETHERNET_LINK_10BASE_T)) {
+				return -ENOTSUP;
+			}
+
+			config.l.link_10bt = true;
+		} else if (params->l.link_100bt) {
+			if (!is_hw_caps_supported(dev,
+						  ETHERNET_LINK_100BASE_T)) {
+				return -ENOTSUP;
+			}
+
+			config.l.link_100bt = true;
+		} else if (params->l.link_1000bt) {
+			if (!is_hw_caps_supported(dev,
+						  ETHERNET_LINK_1000BASE_T)) {
+				return -ENOTSUP;
+			}
+
+			config.l.link_1000bt = true;
+		} else {
+			return -EINVAL;
+		}
+
+		type = ETHERNET_CONFIG_TYPE_LINK;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_SET_DUPLEX) {
+		if (!is_hw_caps_supported(dev, ETHERNET_DUPLEX_SET)) {
+			return -ENOTSUP;
+		}
+
+		config.full_duplex = params->full_duplex;
+		type = ETHERNET_CONFIG_TYPE_DUPLEX;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_SET_MAC_ADDRESS) {
+		if (net_if_is_up(iface)) {
+			return -EACCES;
+		}
+
+		/* We need to remove the old IPv6 link layer address, that is
+		 * generated from old MAC address, from network interface if
+		 * needed.
+		 */
+		if (IS_ENABLED(CONFIG_NET_IPV6)) {
+			struct in6_addr iid;
+
+			net_ipv6_addr_create_iid(&iid,
+						 net_if_get_link_addr(iface));
+
+			/* No need to check the return value in this case. It
+			 * is not an error if the address is not found atm.
+			 */
+			(void)net_if_ipv6_addr_rm(iface, &iid);
+		}
+
+		memcpy(&config.mac_address, &params->mac_address,
+		       sizeof(struct net_eth_addr));
+		type = ETHERNET_CONFIG_TYPE_MAC_ADDRESS;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_SET_QAV_PARAM) {
+		if (!is_hw_caps_supported(dev, ETHERNET_QAV)) {
+			return -ENOTSUP;
+		}
+
+		/* Validate params which need global validating */
+		switch (params->qav_param.type) {
+		case ETHERNET_QAV_PARAM_TYPE_DELTA_BANDWIDTH:
+			if (params->qav_param.delta_bandwidth > 100) {
+				return -EINVAL;
+			}
+			break;
+		case ETHERNET_QAV_PARAM_TYPE_OPER_IDLE_SLOPE:
+		case ETHERNET_QAV_PARAM_TYPE_TRAFFIC_CLASS:
+			/* Read-only parameters */
+			return -EINVAL;
+		default:
+			/* No validation needed */
+			break;
+		}
+
+		memcpy(&config.qav_param, &params->qav_param,
+		       sizeof(struct ethernet_qav_param));
+		type = ETHERNET_CONFIG_TYPE_QAV_PARAM;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_SET_PROMISC_MODE) {
+		if (!is_hw_caps_supported(dev, ETHERNET_PROMISC_MODE)) {
+			return -ENOTSUP;
+		}
+
+		config.promisc_mode = params->promisc_mode;
+		type = ETHERNET_CONFIG_TYPE_PROMISC_MODE;
+	} else {
+		return -EINVAL;
+	}
+
+	return api->set_config(net_if_get_device(iface), type, &config);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION,
+				  ethernet_set_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_LINK,
+				  ethernet_set_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_DUPLEX,
+				  ethernet_set_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS,
+				  ethernet_set_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_QAV_PARAM,
+				  ethernet_set_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_SET_PROMISC_MODE,
+				  ethernet_set_config);
+
+static int ethernet_get_config(uint32_t mgmt_request,
+			       struct net_if *iface,
+			       void *data, size_t len)
+{
+	struct ethernet_req_params *params = (struct ethernet_req_params *)data;
+	const struct device *dev = net_if_get_device(iface);
+	const struct ethernet_api *api = dev->api;
+	struct ethernet_config config = { 0 };
+	int ret = 0;
+	enum ethernet_config_type type;
+
+	if (!api) {
+		return -ENOENT;
+	}
+
+	if (!api->get_config) {
+		return -ENOTSUP;
+	}
+
+	if (!data || (len != sizeof(struct ethernet_req_params))) {
+		return -EINVAL;
+	}
+
+	if (mgmt_request == NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM) {
+		if (!is_hw_caps_supported(dev, ETHERNET_PRIORITY_QUEUES)) {
+			return -ENOTSUP;
+		}
+
+		type = ETHERNET_CONFIG_TYPE_PRIORITY_QUEUES_NUM;
+
+		ret = api->get_config(dev, type, &config);
+		if (ret) {
+			return ret;
+		}
+
+		params->priority_queues_num = config.priority_queues_num;
+	} else if (mgmt_request == NET_REQUEST_ETHERNET_GET_QAV_PARAM) {
+		if (!is_hw_caps_supported(dev, ETHERNET_QAV)) {
+			return -ENOTSUP;
+		}
+
+		config.qav_param.queue_id = params->qav_param.queue_id;
+		config.qav_param.type = params->qav_param.type;
+
+		type = ETHERNET_CONFIG_TYPE_QAV_PARAM;
+
+		ret = api->get_config(dev, type, &config);
+		if (ret) {
+			return ret;
+		}
+
+		switch (config.qav_param.type) {
+		case ETHERNET_QAV_PARAM_TYPE_DELTA_BANDWIDTH:
+			params->qav_param.delta_bandwidth =
+				config.qav_param.delta_bandwidth;
+			break;
+		case ETHERNET_QAV_PARAM_TYPE_IDLE_SLOPE:
+			params->qav_param.idle_slope =
+				config.qav_param.idle_slope;
+			break;
+		case ETHERNET_QAV_PARAM_TYPE_OPER_IDLE_SLOPE:
+			params->qav_param.oper_idle_slope =
+				config.qav_param.oper_idle_slope;
+			break;
+		case ETHERNET_QAV_PARAM_TYPE_TRAFFIC_CLASS:
+			params->qav_param.traffic_class =
+				config.qav_param.traffic_class;
+			break;
+		case ETHERNET_QAV_PARAM_TYPE_STATUS:
+			params->qav_param.enabled = config.qav_param.enabled;
+			break;
+		}
+
+	} else {
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_GET_PRIORITY_QUEUES_NUM,
+				  ethernet_get_config);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_ETHERNET_GET_QAV_PARAM,
+				  ethernet_get_config);
+
+void ethernet_mgmt_raise_carrier_on_event(struct net_if *iface)
+{
+	net_mgmt_event_notify(NET_EVENT_ETHERNET_CARRIER_ON, iface);
+}
+
+void ethernet_mgmt_raise_carrier_off_event(struct net_if *iface)
+{
+	net_mgmt_event_notify(NET_EVENT_ETHERNET_CARRIER_OFF, iface);
+}
+
+void ethernet_mgmt_raise_vlan_enabled_event(struct net_if *iface, uint16_t tag)
+{
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	net_mgmt_event_notify_with_info(NET_EVENT_ETHERNET_VLAN_TAG_ENABLED,
+					iface, &tag, sizeof(tag));
+#else
+	net_mgmt_event_notify(NET_EVENT_ETHERNET_VLAN_TAG_ENABLED,
+			      iface);
+#endif
+}
+
+void ethernet_mgmt_raise_vlan_disabled_event(struct net_if *iface, uint16_t tag)
+{
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	net_mgmt_event_notify_with_info(NET_EVENT_ETHERNET_VLAN_TAG_DISABLED,
+					iface, &tag, sizeof(tag));
+#else
+	net_mgmt_event_notify(NET_EVENT_ETHERNET_VLAN_TAG_DISABLED, iface);
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_stats.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_stats.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/ethernet_stats.c	(working copy)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ethernet_stats, CONFIG_NET_L2_ETHERNET_LOG_LEVEL);
+
+#include <kernel.h>
+#include <string.h>
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/ethernet.h>
+
+#include "net_stats.h"
+
+#if defined(CONFIG_NET_STATISTICS_USER_API)
+
+static int eth_stats_get(uint32_t mgmt_request, struct net_if *iface,
+			 void *data, size_t len)
+{
+	size_t len_chk = 0;
+	void *src = NULL;
+	const struct ethernet_api *eth;
+
+	switch (NET_MGMT_GET_COMMAND(mgmt_request)) {
+	case NET_REQUEST_STATS_CMD_GET_ETHERNET:
+		if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+			return -ENOENT;
+		}
+
+		eth = net_if_get_device(iface)->api;
+		if (eth == NULL || eth->get_stats == NULL) {
+			return -ENOENT;
+		}
+
+		len_chk = sizeof(struct net_stats_eth);
+		src = eth->get_stats(net_if_get_device(iface));
+		break;
+	}
+
+	if (len != len_chk || !src) {
+		return -EINVAL;
+	}
+
+	memcpy(data, src, len);
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ETHERNET,
+				  eth_stats_get);
+
+#endif /* CONFIG_NET_STATISTICS_USER_API */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/CMakeLists.txt	(working copy)
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources(
+  gptp.c
+  gptp_user_api.c
+  gptp_md.c
+  gptp_messages.c
+  gptp_mi.c
+  )
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/Kconfig	(working copy)
@@ -0,0 +1,229 @@
+# Copyright (c) 2018 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_GPTP
+	bool "Enable IEEE 802.1AS (gPTP) support [EXPERIMENTAL]"
+	select NET_PKT_TIMESTAMP
+	select PTP_CLOCK
+	help
+	  Enable gPTP driver that send and receives gPTP packets
+	  and handles network packet timestamps.
+
+if NET_GPTP
+
+module = NET_GPTP
+module-dep = NET_LOG
+module-str = Log level for gPTP
+module-help = Enable logs for the gPTP stack.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_GPTP_GM_CAPABLE
+	bool "Enable IEEE 802.1AS GrandMaster Capability"
+	help
+	  Enable to mark the whole system as Grand Master Capable.
+
+config NET_GPTP_PROBE_CLOCK_SOURCE_ON_DEMAND
+	bool "Probe clock source on demand"
+	depends on NET_GPTP_GM_CAPABLE
+	default y
+	help
+	  This option is helpful if the driver does not fully support the
+	  ClockSourceTime.invoke function. If this is enabled, the clock
+	  source is probed when it is actually needed instead of being
+	  updated on each tick.
+	  See IEEE 802.1AS-2011, chapter 9.2 for more details.
+
+choice
+	prompt "gPTP Clock Accuracy"
+	default NET_GPTP_CLOCK_ACCURACY_UNKNOWN
+	help
+	  Specify the accuracy of the clock. This setting should reflect
+	  the actual capabilities of the hardware.
+	  See 7.6.2.5 of IEEE 1588-2008 for more info.
+
+	config NET_GPTP_CLOCK_ACCURACY_UNKNOWN
+		bool "Unknown"
+	config NET_GPTP_CLOCK_ACCURACY_25NS
+		bool "25ns"
+	config NET_GPTP_CLOCK_ACCURACY_100NS
+		bool "100ns"
+	config NET_GPTP_CLOCK_ACCURACY_250NS
+		bool "250ns"
+	config NET_GPTP_CLOCK_ACCURACY_1US
+		bool "1us"
+	config NET_GPTP_CLOCK_ACCURACY_2_5US
+		bool "2.5us"
+	config NET_GPTP_CLOCK_ACCURACY_10US
+		bool "10us"
+	config NET_GPTP_CLOCK_ACCURACY_25US
+		bool "25us"
+	config NET_GPTP_CLOCK_ACCURACY_100US
+		bool "100us"
+	config NET_GPTP_CLOCK_ACCURACY_250US
+		bool "250us"
+	config NET_GPTP_CLOCK_ACCURACY_1MS
+		bool "1ms"
+	config NET_GPTP_CLOCK_ACCURACY_2_5MS
+		bool "1.5ms"
+	config NET_GPTP_CLOCK_ACCURACY_10MS
+		bool "10ms"
+	config NET_GPTP_CLOCK_ACCURACY_25MS
+		bool "25ms"
+	config NET_GPTP_CLOCK_ACCURACY_100MS
+		bool "100ms"
+	config NET_GPTP_CLOCK_ACCURACY_250MS
+		bool "250ms"
+	config NET_GPTP_CLOCK_ACCURACY_1S
+		bool "1s"
+	config NET_GPTP_CLOCK_ACCURACY_10S
+		bool "10s"
+	config NET_GPTP_CLOCK_ACCURACY_GT_10S
+		bool "> 10s"
+endchoice
+
+config NET_GPTP_CLOCK_ACCURACY
+	hex
+	default 0x20 if NET_GPTP_CLOCK_ACCURACY_25NS
+	default 0x21 if NET_GPTP_CLOCK_ACCURACY_100NS
+	default 0x22 if NET_GPTP_CLOCK_ACCURACY_250NS
+	default 0x23 if NET_GPTP_CLOCK_ACCURACY_1US
+	default 0x24 if NET_GPTP_CLOCK_ACCURACY_2_5US
+	default 0x25 if NET_GPTP_CLOCK_ACCURACY_10US
+	default 0x26 if NET_GPTP_CLOCK_ACCURACY_25US
+	default 0x27 if NET_GPTP_CLOCK_ACCURACY_100US
+	default 0x28 if NET_GPTP_CLOCK_ACCURACY_250US
+	default 0x29 if NET_GPTP_CLOCK_ACCURACY_1MS
+	default 0x2a if NET_GPTP_CLOCK_ACCURACY_2_5MS
+	default 0x2b if NET_GPTP_CLOCK_ACCURACY_10MS
+	default 0x2c if NET_GPTP_CLOCK_ACCURACY_25MS
+	default 0x2d if NET_GPTP_CLOCK_ACCURACY_100MS
+	default 0x2e if NET_GPTP_CLOCK_ACCURACY_250MS
+	default 0x2f if NET_GPTP_CLOCK_ACCURACY_1S
+	default 0x30 if NET_GPTP_CLOCK_ACCURACY_10S
+	default 0x31 if NET_GPTP_CLOCK_ACCURACY_GT_10S
+	default 0xfe
+
+config NET_GPTP_NUM_PORTS
+	int "Number of gPTP ports"
+	default 1
+	help
+	  Configures the gPTP stack to work with the given number of ports.
+	  The port concept is the same thing as network interface.
+
+config NET_GPTP_VLAN
+	bool "Run gPTP over VLAN link"
+	depends on NET_VLAN
+	select NET_L2_ETHERNET_MGMT
+	select NET_MGMT_EVENT
+	select NET_MGMT_EVENT_INFO
+	help
+	  This setting allows gPTP to run over VLAN link. Currently only
+	  one port can have VLAN tag set. Note that CONFIG_NET_GPTP_VLAN_TAG
+	  setting must have a proper tag value set, otherwise the gPTP over
+	  VLAN will not work.
+
+config NET_GPTP_VLAN_TAG
+	int "VLAN tag to use"
+	default 4095
+	depends on NET_GPTP_VLAN
+	help
+	  The VLAN tag to use when sending and receiving gPTP messages.
+	  The default value 4095 (0x0fff) means unspecified tag which is
+	  not a valid value. This means that you need to set the tag to
+	  a valid value.
+
+config NET_GPTP_NEIGHBOR_PROP_DELAY_THR
+	int "Set neighbor propagation delay threshold (ns)"
+	default 100000
+	help
+	  Defines the neighbor propagation delay threshold in nanoseconds.
+	  This is the propagation time threshold, above which a port is not
+	  considered capable of participating in the IEEE 802.1AS protocol.
+	  See IEEE 802.1AS chapter 11.2.12.6 for details.
+
+config NET_GPTP_INIT_LOG_PDELAY_REQ_ITV
+	int "Set initial pdelay request interval in Log2 base"
+	default 0
+	help
+	  Defines the interval at which a Path Delay Request will be sent.
+	  The value is the converted in nanoseconds as follow:
+	  nanoseconds = (10^9) * 2^(value)
+
+config NET_GPTP_INIT_LOG_SYNC_ITV
+	int "Set initial sync interval in Log2 base"
+	default -3
+	help
+	  Defines the interval at which a Sync message will be sent.
+	  The value is the converted in nanoseconds as follow:
+	  nanoseconds = (10^9) * 2^(value)
+
+config NET_GPTP_INIT_LOG_ANNOUNCE_ITV
+	int "Set initial announce interval in Log2 base"
+	default 0
+	help
+	  Defines the interval at which an Announce message will be sent.
+	  The value is the converted in nanoseconds as follow:
+	  nanoseconds = (10^9) * 2^(value)
+
+config NET_GPTP_SYNC_RECEIPT_TIMEOUT
+	int "Number of sync intervals to wait"
+	default 3
+	help
+	  Defines the number of sync intervals to wait without receiving
+	  synchronization information before assuming that the master is no
+	  longer transmitting synchronization information.
+
+config NET_GPTP_ANNOUNCE_RECEIPT_TIMEOUT
+	int "Number of announce intervals to wait"
+	default 3
+	help
+	  Defines the number of announce intervals to wait without receiving
+	  an Announce message before assuming that the master is no longer
+	  transmitting Announce messages.
+
+config NET_GPTP_USE_DEFAULT_CLOCK_UPDATE
+	bool "Use a default clock update function"
+	default y
+	help
+	  Use a default internal function to update port local clock.
+
+config NET_GPTP_PATH_TRACE_ELEMENTS
+	int "How many path trace elements to track"
+	default 8
+	help
+	  This tells the number of time-aware systems that transmits the
+	  Announce message. Each array element takes 8 bytes. If this value
+	  is set to 8, then 8 * 8 = 64 bytes of memory is used.
+
+config NET_GPTP_BMCA_PRIORITY1
+	int "BMCA priority1 value"
+	default 248 if NET_GPTP_GM_CAPABLE
+	default 255
+	range 0 255
+	help
+	  The priority1 attribute of the local clock. It is used in the
+	  Best Master Clock selection Algorithm (BMCA), lower values take
+	  precedence. The default value is 255 if the device is non grand
+	  master capable, and 248 if it is GM capable.
+	  See Chapter 8.6.2.1 of IEEE 802.1AS for a more detailed description
+	  of priority1. Note that if the system	is non GM capable, then the
+	  value 255 is used always and this setting is ignored.
+
+config NET_GPTP_BMCA_PRIORITY2
+	int "BMCA priority2 value"
+	default 248
+	range 0 255
+	help
+	  The priority2 attribute of the local clock. It is used in the BMCA
+	  (Best Master Clock selection Algorithm), lower values take
+	  precedence. The default value is 248.
+	  See Chapter 8.6.2.5 of IEEE 802.1AS for a more detailed description
+	  of priority2.
+
+config NET_GPTP_STATISTICS
+	bool "Collect gPTP statistics"
+	help
+	  Enable this if you need to collect gPTP statistics. The statistics
+	  can be seen in net-shell if needed.
+
+endif # NET_GPTP
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp.c	(working copy)
@@ -0,0 +1,1050 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
+
+#include <net/net_pkt.h>
+#include <ptp_clock.h>
+#include <net/ethernet_mgmt.h>
+#include <random/rand32.h>
+
+#include <net/gptp.h>
+
+#include "gptp_messages.h"
+#include "gptp_mi.h"
+#include "gptp_data_set.h"
+
+#include "gptp_private.h"
+
+#define NET_GPTP_STACK_SIZE 2048
+
+#if CONFIG_NET_GPTP_NUM_PORTS > 32
+/*
+ * Boolean arrays sizes have been hardcoded.
+ * It has been arbitrary chosen that a system can not
+ * have more than 32 ports.
+ */
+#error Maximum number of ports exceeded. (Max is 32).
+#endif
+
+K_KERNEL_STACK_DEFINE(gptp_stack, NET_GPTP_STACK_SIZE);
+K_FIFO_DEFINE(gptp_rx_queue);
+
+static k_tid_t tid;
+static struct k_thread gptp_thread_data;
+struct gptp_domain gptp_domain;
+
+int gptp_get_port_number(struct net_if *iface)
+{
+	int port = net_eth_get_ptp_port(iface) + 1;
+
+	if (port >= GPTP_PORT_START && port < GPTP_PORT_END) {
+		return port;
+	}
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		if (GPTP_PORT_IFACE(port) == iface) {
+			return port;
+		}
+	}
+
+	return -ENODEV;
+}
+
+bool gptp_is_slave_port(int port)
+{
+	return (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE);
+}
+
+/*
+ * Use the given port to generate the clock identity
+ * for the device.
+ * The clock identity is unique for one time-aware system.
+ */
+static void gptp_compute_clock_identity(int port)
+{
+	struct net_if *iface = GPTP_PORT_IFACE(port);
+	struct gptp_default_ds *default_ds;
+
+	default_ds = GPTP_DEFAULT_DS();
+
+	if (iface) {
+		default_ds->clk_id[0] = net_if_get_link_addr(iface)->addr[0];
+		default_ds->clk_id[1] = net_if_get_link_addr(iface)->addr[1];
+		default_ds->clk_id[2] = net_if_get_link_addr(iface)->addr[2];
+		default_ds->clk_id[3] = 0xFF;
+		default_ds->clk_id[4] = 0xFE;
+		default_ds->clk_id[5] = net_if_get_link_addr(iface)->addr[3];
+		default_ds->clk_id[6] = net_if_get_link_addr(iface)->addr[4];
+		default_ds->clk_id[7] = net_if_get_link_addr(iface)->addr[5];
+	}
+}
+
+/* Note that we do not use log_strdup() here when printing msg as currently the
+ * msg variable is always a const string that is not allocated from the stack.
+ * If this changes at some point, then add log_strdup(msg) here.
+ */
+#define PRINT_INFO(msg, hdr, pkt)				\
+	NET_DBG("Received %s seq %d pkt %p", msg,		\
+		ntohs(hdr->sequence_id), pkt)			\
+
+
+static bool gptp_handle_critical_msg(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct gptp_hdr *hdr = GPTP_HDR(pkt);
+	bool handled = false;
+	int port;
+
+	switch (hdr->message_type) {
+	case GPTP_PATH_DELAY_REQ_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_REQ_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "PDELAY_REQ",
+				 GPTP_PDELAY_REQ_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			break;
+		}
+
+		PRINT_INFO("PDELAY_REQ", hdr, pkt);
+
+		port = gptp_get_port_number(iface);
+		if (port == -ENODEV) {
+			NET_DBG("No port found for gPTP buffer");
+			return handled;
+		}
+
+		if (GPTP_PORT_STATE(port)->pdelay_resp.state !=
+						GPTP_PDELAY_RESP_NOT_ENABLED) {
+			gptp_handle_pdelay_req(port, pkt);
+		}
+
+		handled = true;
+		break;
+	default:
+		/* Not a critical message, this will be handled later. */
+		break;
+	}
+
+	return handled;
+}
+
+static void gptp_handle_msg(struct net_pkt *pkt)
+{
+	struct gptp_hdr *hdr = GPTP_HDR(pkt);
+	struct gptp_pdelay_req_state *pdelay_req_state;
+	struct gptp_sync_rcv_state *sync_rcv_state;
+	struct gptp_port_announce_receive_state *pa_rcv_state;
+	struct gptp_port_bmca_data *bmca_data;
+	int port;
+
+	port = gptp_get_port_number(net_pkt_iface(pkt));
+	if (port == -ENODEV) {
+		NET_DBG("No port found for ptp buffer");
+		return;
+	}
+
+	pdelay_req_state = &GPTP_PORT_STATE(port)->pdelay_req;
+	sync_rcv_state = &GPTP_PORT_STATE(port)->sync_rcv;
+
+	switch (hdr->message_type) {
+	case GPTP_SYNC_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_SYNC_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "SYNC",
+				 GPTP_SYNC_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("SYNC", hdr, pkt);
+
+		sync_rcv_state->rcvd_sync = true;
+
+		/* If we already have one, drop the previous one. */
+		if (sync_rcv_state->rcvd_sync_ptr) {
+			net_pkt_unref(sync_rcv_state->rcvd_sync_ptr);
+		}
+
+		/* Keep the buffer alive until follow_up is received. */
+		net_pkt_ref(pkt);
+		sync_rcv_state->rcvd_sync_ptr = pkt;
+
+		GPTP_STATS_INC(port, rx_sync_count);
+		break;
+
+	case GPTP_DELAY_REQ_MESSAGE:
+		NET_DBG("Delay Request not handled.");
+		break;
+
+	case GPTP_PATH_DELAY_REQ_MESSAGE:
+		/*
+		 * Path Delay Responses to Path Delay Requests need
+		 * very low latency. These need to handled in priority
+		 * when received as they cannot afford to be delayed
+		 * by context switches.
+		 */
+		NET_WARN("Path Delay Request received as normal messages!");
+		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+		break;
+
+	case GPTP_PATH_DELAY_RESP_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_RESP_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "PDELAY_RESP",
+				 GPTP_PDELAY_RESP_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("PDELAY_RESP", hdr, pkt);
+
+		pdelay_req_state->rcvd_pdelay_resp++;
+
+		/* If we already have one, drop the received one. */
+		if (pdelay_req_state->rcvd_pdelay_resp_ptr) {
+			break;
+		}
+
+		/* Keep the buffer alive until pdelay_rate_ratio is computed. */
+		net_pkt_ref(pkt);
+		pdelay_req_state->rcvd_pdelay_resp_ptr = pkt;
+		break;
+
+	case GPTP_FOLLOWUP_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_FOLLOW_UP_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "FOLLOWUP",
+				 GPTP_FOLLOW_UP_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("FOLLOWUP", hdr, pkt);
+
+		sync_rcv_state->rcvd_follow_up = true;
+
+		/* If we already have one, drop the previous one. */
+		if (sync_rcv_state->rcvd_follow_up_ptr) {
+			net_pkt_unref(sync_rcv_state->rcvd_follow_up_ptr);
+		}
+
+		/* Keep the pkt alive until info is extracted. */
+		sync_rcv_state->rcvd_follow_up_ptr = net_pkt_ref(pkt);
+		NET_DBG("Keeping %s seq %d pkt %p", "FOLLOWUP",
+			ntohs(hdr->sequence_id), pkt);
+		break;
+
+	case GPTP_PATH_DELAY_FOLLOWUP_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_RESP_FUP_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "PDELAY_FOLLOWUP",
+				 GPTP_PDELAY_RESP_FUP_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("PDELAY_FOLLOWUP", hdr, pkt);
+
+		pdelay_req_state->rcvd_pdelay_follow_up++;
+
+		/* If we already have one, drop the received one. */
+		if (pdelay_req_state->rcvd_pdelay_follow_up_ptr) {
+			break;
+		}
+
+		/* Keep the buffer alive until pdelay_rate_ratio is computed. */
+		net_pkt_ref(pkt);
+		pdelay_req_state->rcvd_pdelay_follow_up_ptr = pkt;
+
+		GPTP_STATS_INC(port, rx_pdelay_resp_fup_count);
+		break;
+
+	case GPTP_ANNOUNCE_MESSAGE:
+		if (GPTP_ANNOUNCE_CHECK_LEN(pkt)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "ANNOUNCE",
+				 GPTP_ANNOUNCE_LEN(pkt),
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("ANNOUNCE", hdr, pkt);
+
+		pa_rcv_state = &GPTP_PORT_STATE(port)->pa_rcv;
+		bmca_data = GPTP_PORT_BMCA_DATA(port);
+
+		if (pa_rcv_state->rcvd_announce == false &&
+				bmca_data->rcvd_announce_ptr == NULL) {
+			pa_rcv_state->rcvd_announce = true;
+			bmca_data->rcvd_announce_ptr = pkt;
+			net_pkt_ref(pkt);
+		}
+
+		GPTP_STATS_INC(port, rx_announce_count);
+		break;
+
+	case GPTP_SIGNALING_MESSAGE:
+		if (GPTP_CHECK_LEN(pkt, GPTP_SIGNALING_LEN)) {
+			NET_WARN("Invalid length for %s packet "
+				 "should have %zd bytes but has %zd bytes",
+				 "SIGNALING",
+				 GPTP_SIGNALING_LEN,
+				 GPTP_PACKET_LEN(pkt));
+			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+			break;
+		}
+
+		PRINT_INFO("SIGNALING", hdr, pkt);
+
+		gptp_handle_signaling(port, pkt);
+		break;
+
+	case GPTP_MANAGEMENT_MESSAGE:
+		PRINT_INFO("MANAGEMENT", hdr, pkt);
+		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+		break;
+
+	default:
+		NET_DBG("Received unknown message %x", hdr->message_type);
+		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
+		break;
+	}
+}
+
+enum net_verdict net_gptp_recv(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct gptp_hdr *hdr = GPTP_HDR(pkt);
+
+	if ((hdr->ptp_version != GPTP_VERSION) ||
+			(hdr->transport_specific != GPTP_TRANSPORT_802_1_AS)) {
+		/* The stack only supports PTP V2 and transportSpecific set
+		 * to 1 with IEEE802.1AS-2011.
+		 */
+		return NET_DROP;
+	}
+
+	/* Handle critical messages. */
+	if (!gptp_handle_critical_msg(iface, pkt)) {
+		k_fifo_put(&gptp_rx_queue, pkt);
+
+		/* Returning OK here makes sure the network statistics are
+		 * properly updated.
+		 */
+		return NET_OK;
+	}
+
+	/* Message not propagated up in the stack. */
+	return NET_DROP;
+}
+
+static void gptp_init_clock_ds(void)
+{
+	struct gptp_global_ds *global_ds;
+	struct gptp_default_ds *default_ds;
+	struct gptp_current_ds *current_ds;
+	struct gptp_parent_ds *parent_ds;
+	struct gptp_time_prop_ds *prop_ds;
+
+	global_ds = GPTP_GLOBAL_DS();
+	default_ds = GPTP_DEFAULT_DS();
+	current_ds = GPTP_CURRENT_DS();
+	parent_ds = GPTP_PARENT_DS();
+	prop_ds = GPTP_PROPERTIES_DS();
+
+	/* Initialize global data set. */
+	(void)memset(global_ds, 0, sizeof(struct gptp_global_ds));
+
+	/* Initialize default data set. */
+
+	/* Compute the clock identity from the first port MAC address. */
+	gptp_compute_clock_identity(GPTP_PORT_START);
+
+	default_ds->gm_capable = IS_ENABLED(CONFIG_NET_GPTP_GM_CAPABLE);
+	default_ds->clk_quality.clock_class = GPTP_CLASS_OTHER;
+	default_ds->clk_quality.clock_accuracy =
+		CONFIG_NET_GPTP_CLOCK_ACCURACY;
+	default_ds->clk_quality.offset_scaled_log_var =
+		GPTP_OFFSET_SCALED_LOG_VAR_UNKNOWN;
+
+	if (default_ds->gm_capable) {
+		/* The priority1 value cannot be 255 for GM capable
+		 * system.
+		 */
+		if (CONFIG_NET_GPTP_BMCA_PRIORITY1 ==
+		    GPTP_PRIORITY1_NON_GM_CAPABLE) {
+			default_ds->priority1 = GPTP_PRIORITY1_GM_CAPABLE;
+		} else {
+			default_ds->priority1 = CONFIG_NET_GPTP_BMCA_PRIORITY1;
+		}
+	} else {
+		default_ds->priority1 = GPTP_PRIORITY1_NON_GM_CAPABLE;
+	}
+
+	default_ds->priority2 = GPTP_PRIORITY2_DEFAULT;
+
+	default_ds->cur_utc_offset = 37U; /* Current leap seconds TAI - UTC */
+	default_ds->flags.all = 0U;
+	default_ds->flags.octets[1] = GPTP_FLAG_TIME_TRACEABLE;
+	default_ds->time_source = GPTP_TS_INTERNAL_OSCILLATOR;
+
+	/* Initialize current data set. */
+	(void)memset(current_ds, 0, sizeof(struct gptp_current_ds));
+
+	/* Initialize parent data set. */
+
+	/* parent clock id is initialized to default_ds clock id. */
+	memcpy(parent_ds->port_id.clk_id, default_ds->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+	memcpy(parent_ds->gm_id, default_ds->clk_id, GPTP_CLOCK_ID_LEN);
+	parent_ds->port_id.port_number = 0U;
+
+	/* TODO: Check correct value for below field. */
+	parent_ds->cumulative_rate_ratio = 0;
+
+	parent_ds->gm_clk_quality.clock_class =
+		default_ds->clk_quality.clock_class;
+	parent_ds->gm_clk_quality.clock_accuracy =
+		default_ds->clk_quality.clock_accuracy;
+	parent_ds->gm_clk_quality.offset_scaled_log_var =
+		default_ds->clk_quality.offset_scaled_log_var;
+	parent_ds->gm_priority1 = default_ds->priority1;
+	parent_ds->gm_priority2 = default_ds->priority2;
+
+	/* Initialize properties data set. */
+
+	/* TODO: Get accurate values for below. From the GM. */
+	prop_ds->cur_utc_offset = 37U; /* Current leap seconds TAI - UTC */
+	prop_ds->cur_utc_offset_valid = false;
+	prop_ds->leap59 = false;
+	prop_ds->leap61 = false;
+	prop_ds->time_traceable = false;
+	prop_ds->freq_traceable = false;
+	prop_ds->time_source = GPTP_TS_INTERNAL_OSCILLATOR;
+
+	/* Set system values. */
+	global_ds->sys_flags.all = default_ds->flags.all;
+	global_ds->sys_current_utc_offset = default_ds->cur_utc_offset;
+	global_ds->sys_time_source = default_ds->time_source;
+	global_ds->clk_master_sync_itv =
+		NSEC_PER_SEC * GPTP_POW2(CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV);
+}
+
+static void gptp_init_port_ds(int port)
+{
+	struct gptp_default_ds *default_ds;
+	struct gptp_port_ds *port_ds;
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+	struct gptp_port_param_ds *port_param_ds;
+
+	port_param_ds = GPTP_PORT_PARAM_DS(port);
+#endif
+
+	default_ds = GPTP_DEFAULT_DS();
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Initialize port data set. */
+	memcpy(port_ds->port_id.clk_id, default_ds->clk_id, GPTP_CLOCK_ID_LEN);
+	port_ds->port_id.port_number = port;
+
+	port_ds->ptt_port_enabled = true;
+	port_ds->prev_ptt_port_enabled = true;
+
+	port_ds->neighbor_prop_delay = 0;
+	port_ds->neighbor_prop_delay_thresh = GPTP_NEIGHBOR_PROP_DELAY_THR;
+	port_ds->delay_asymmetry = 0;
+
+	port_ds->ini_log_announce_itv = CONFIG_NET_GPTP_INIT_LOG_ANNOUNCE_ITV;
+	port_ds->cur_log_announce_itv = port_ds->ini_log_announce_itv;
+	port_ds->announce_receipt_timeout =
+		CONFIG_NET_GPTP_ANNOUNCE_RECEIPT_TIMEOUT;
+
+	/* Subtract 1 to divide by 2 the sync interval. */
+	port_ds->ini_log_half_sync_itv = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV - 1;
+	port_ds->cur_log_half_sync_itv = port_ds->ini_log_half_sync_itv;
+	port_ds->sync_receipt_timeout = CONFIG_NET_GPTP_SYNC_RECEIPT_TIMEOUT;
+	port_ds->sync_receipt_timeout_time_itv = 10000000U; /* 10ms */
+
+	port_ds->ini_log_pdelay_req_itv =
+		CONFIG_NET_GPTP_INIT_LOG_PDELAY_REQ_ITV;
+	port_ds->cur_log_pdelay_req_itv = port_ds->ini_log_pdelay_req_itv;
+	port_ds->allowed_lost_responses = GPTP_ALLOWED_LOST_RESP;
+	port_ds->version = GPTP_VERSION;
+
+	gptp_set_time_itv(&port_ds->pdelay_req_itv, 1,
+			  port_ds->cur_log_pdelay_req_itv);
+
+	gptp_set_time_itv(&port_ds->half_sync_itv, 1,
+			  port_ds->cur_log_half_sync_itv);
+
+	port_ds->compute_neighbor_rate_ratio = true;
+	port_ds->compute_neighbor_prop_delay = true;
+
+	/* Random Sequence Numbers. */
+	port_ds->sync_seq_id = (uint16_t)sys_rand32_get();
+	port_ds->pdelay_req_seq_id = (uint16_t)sys_rand32_get();
+	port_ds->announce_seq_id = (uint16_t)sys_rand32_get();
+	port_ds->signaling_seq_id = (uint16_t)sys_rand32_get();
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+	/* Initialize stats data set. */
+	(void)memset(port_param_ds, 0, sizeof(struct gptp_port_param_ds));
+#endif
+}
+
+static void gptp_init_state_machine(void)
+{
+	gptp_md_init_state_machine();
+	gptp_mi_init_state_machine();
+}
+
+static void gptp_state_machine(void)
+{
+	int port;
+
+	/* Manage port states. */
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		struct gptp_port_ds *port_ds = GPTP_PORT_DS(port);
+
+		switch (GPTP_GLOBAL_DS()->selected_role[port]) {
+		case GPTP_PORT_DISABLED:
+		case GPTP_PORT_MASTER:
+		case GPTP_PORT_PASSIVE:
+		case GPTP_PORT_SLAVE:
+			gptp_md_state_machines(port);
+			gptp_mi_port_sync_state_machines(port);
+			gptp_mi_port_bmca_state_machines(port);
+			break;
+		default:
+			NET_DBG("%s: Unknown port state", __func__);
+			break;
+		}
+
+		port_ds->prev_ptt_port_enabled = port_ds->ptt_port_enabled;
+	}
+
+	gptp_mi_state_machines();
+}
+
+static void gptp_thread(void)
+{
+	int port;
+
+	NET_DBG("Starting PTP thread");
+
+	gptp_init_clock_ds();
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		gptp_init_port_ds(port);
+		gptp_change_port_state(port, GPTP_PORT_DISABLED);
+	}
+
+	while (1) {
+		struct net_pkt *pkt;
+
+		pkt = k_fifo_get(&gptp_rx_queue,
+				 K_MSEC(GPTP_THREAD_WAIT_TIMEOUT_MS));
+		if (pkt) {
+			gptp_handle_msg(pkt);
+			net_pkt_unref(pkt);
+		}
+
+		gptp_state_machine();
+	}
+}
+
+
+static void gptp_add_port(struct net_if *iface, void *user_data)
+{
+	int *num_ports = user_data;
+	const struct device *clk;
+
+	if (*num_ports >= CONFIG_NET_GPTP_NUM_PORTS) {
+		return;
+	}
+
+#if defined(CONFIG_NET_GPTP_VLAN)
+	if (CONFIG_NET_GPTP_VLAN_TAG >= 0 &&
+	    CONFIG_NET_GPTP_VLAN_TAG < NET_VLAN_TAG_UNSPEC) {
+		struct net_if *vlan_iface;
+
+		vlan_iface = net_eth_get_vlan_iface(iface,
+						    CONFIG_NET_GPTP_VLAN_TAG);
+		if (vlan_iface != iface) {
+			return;
+		}
+	}
+#endif /* CONFIG_NET_GPTP_VLAN */
+
+	/* Check if interface has a PTP clock. */
+	clk = net_eth_get_ptp_clock(iface);
+	if (clk) {
+		gptp_domain.iface[*num_ports] = iface;
+		net_eth_set_ptp_port(iface, *num_ports);
+		(*num_ports)++;
+	}
+}
+
+void gptp_set_time_itv(struct gptp_uscaled_ns *interval,
+		       uint16_t seconds,
+		       int8_t log_msg_interval)
+{
+	int i;
+
+	if (seconds == 0U) {
+		interval->low = 0U;
+		interval->high = 0U;
+		return;
+	} else if (log_msg_interval >= 96) {
+		/* Overflow, set maximum. */
+		interval->low = UINT64_MAX;
+		interval->high = UINT32_MAX;
+
+		return;
+	} else if (log_msg_interval <= -64) {
+		/* Underflow, set to 0. */
+		interval->low = 0U;
+		interval->high = 0U;
+		return;
+	}
+
+
+	/* NSEC_PER_SEC is between 2^30 and 2^31, seconds is less thant 2^16,
+	 * thus the computation will be less than 2^63.
+	 */
+	interval->low =	(seconds * (uint64_t)NSEC_PER_SEC) << 16;
+
+	if (log_msg_interval <= 0) {
+		interval->low >>= -log_msg_interval;
+		interval->high = 0U;
+	} else {
+		/* Find highest bit set. */
+		for (i = 63; i >= 0; i--) {
+			if (interval->low >> i) {
+				break;
+			}
+		}
+
+		if ((i + log_msg_interval) >= 96 || log_msg_interval > 64) {
+			/* Overflow, set maximum. */
+			interval->low = UINT64_MAX;
+			interval->high = UINT32_MAX;
+		} else {
+			interval->high =
+				interval->low >> (64 - log_msg_interval);
+
+			/* << operator is undefined if the shift value is equal
+			 * to the number of bits in the left expressionâ€™s type
+			 */
+			if (log_msg_interval == 64) {
+				interval->low = 0U;
+			} else {
+				interval->low <<= log_msg_interval;
+			}
+		}
+	}
+}
+
+int32_t gptp_uscaled_ns_to_timer_ms(struct gptp_uscaled_ns *usns)
+{
+	uint64_t tmp;
+
+	if (usns->high) {
+		/* Do not calculate, it reaches max value. */
+		return INT32_MAX;
+	}
+
+	tmp = (usns->low >> 16) / USEC_PER_SEC;
+	if (tmp == 0U) {
+		/* Timer must be started with a minimum value of 1. */
+		return 1;
+	}
+
+	if (tmp > INT32_MAX) {
+		return INT32_MAX;
+	}
+
+	return (tmp & INT32_MAX);
+
+}
+
+static int32_t timer_get_remaining_and_stop(struct k_timer *timer)
+{
+	unsigned int key;
+	int32_t timer_value;
+
+	key = irq_lock();
+	timer_value = k_timer_remaining_get(timer);
+
+	/* Stop timer as the period is about to be modified. */
+	k_timer_stop(timer);
+	irq_unlock(key);
+
+	return timer_value;
+}
+
+static int32_t update_itv(struct gptp_uscaled_ns *itv,
+			 int8_t *cur_log_itv,
+			 int8_t *ini_log_itv,
+			 int8_t new_log_itv,
+			 int8_t correction_log_itv)
+{
+	switch (new_log_itv) {
+	case GPTP_ITV_KEEP:
+		break;
+	case GPTP_ITV_SET_TO_INIT:
+		*cur_log_itv = *ini_log_itv;
+		gptp_set_time_itv(itv, 1, *ini_log_itv);
+		break;
+	case GPTP_ITV_STOP:
+	default:
+		*cur_log_itv = new_log_itv + correction_log_itv;
+		gptp_set_time_itv(itv, 1, *cur_log_itv);
+		break;
+	}
+
+	return gptp_uscaled_ns_to_timer_ms(itv);
+}
+
+void gptp_update_pdelay_req_interval(int port, int8_t log_val)
+{
+	int32_t remaining;
+	int32_t new_itv, old_itv;
+	struct gptp_pdelay_req_state *state_pdelay;
+	struct gptp_port_ds *port_ds;
+
+	port_ds = GPTP_PORT_DS(port);
+	state_pdelay = &GPTP_PORT_STATE(port)->pdelay_req;
+	remaining = timer_get_remaining_and_stop(&state_pdelay->pdelay_timer);
+
+	old_itv = gptp_uscaled_ns_to_timer_ms(&port_ds->pdelay_req_itv);
+	new_itv = update_itv(&port_ds->pdelay_req_itv,
+			     &port_ds->cur_log_pdelay_req_itv,
+			     &port_ds->ini_log_pdelay_req_itv,
+			     log_val,
+			     0);
+
+	new_itv -= (old_itv-remaining);
+	if (new_itv <= 0) {
+		new_itv = 1;
+	}
+
+	k_timer_start(&state_pdelay->pdelay_timer, K_MSEC(new_itv), K_NO_WAIT);
+}
+
+void gptp_update_sync_interval(int port, int8_t log_val)
+{
+	struct gptp_pss_send_state *state_pss_send;
+	struct gptp_port_ds *port_ds;
+	int32_t new_itv, old_itv, period;
+	int32_t remaining;
+	uint32_t time_spent;
+
+	port_ds = GPTP_PORT_DS(port);
+	state_pss_send = &GPTP_PORT_STATE(port)->pss_send;
+	remaining =
+		timer_get_remaining_and_stop(
+				&state_pss_send->half_sync_itv_timer);
+	old_itv = gptp_uscaled_ns_to_timer_ms(&port_ds->half_sync_itv);
+	new_itv = update_itv(&port_ds->half_sync_itv,
+			     &port_ds->cur_log_half_sync_itv,
+			     &port_ds->ini_log_half_sync_itv,
+			     log_val,
+			     -1);
+	period = new_itv;
+
+	/* Get the time spent from the start of the timer. */
+	time_spent = old_itv;
+	if (state_pss_send->half_sync_itv_timer_expired) {
+		time_spent *= 2U;
+	}
+	time_spent -= remaining;
+
+	/* Calculate remaining time and if half timer has expired. */
+	if ((time_spent / 2U) > new_itv) {
+		state_pss_send->sync_itv_timer_expired = true;
+		state_pss_send->half_sync_itv_timer_expired = true;
+		new_itv = 1;
+	} else if (time_spent > new_itv) {
+		state_pss_send->sync_itv_timer_expired = false;
+		state_pss_send->half_sync_itv_timer_expired = true;
+		new_itv -= (time_spent - new_itv);
+	} else {
+		state_pss_send->sync_itv_timer_expired = false;
+		state_pss_send->half_sync_itv_timer_expired = false;
+		new_itv -= time_spent;
+	}
+
+	if (new_itv <= 0) {
+		new_itv = 1;
+	}
+
+	k_timer_start(&state_pss_send->half_sync_itv_timer, K_MSEC(new_itv),
+		      K_MSEC(period));
+}
+
+void gptp_update_announce_interval(int port, int8_t log_val)
+{
+	int32_t remaining;
+	int32_t new_itv, old_itv;
+	struct gptp_port_announce_transmit_state *state_ann;
+	struct gptp_port_bmca_data *bmca_data;
+	struct gptp_port_ds *port_ds;
+
+	port_ds = GPTP_PORT_DS(port);
+	state_ann = &GPTP_PORT_STATE(port)->pa_transmit;
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	remaining = timer_get_remaining_and_stop(
+			&state_ann->ann_send_periodic_timer);
+
+	old_itv = gptp_uscaled_ns_to_timer_ms(&bmca_data->announce_interval);
+	new_itv = update_itv(&bmca_data->announce_interval,
+			     &port_ds->cur_log_announce_itv,
+			     &port_ds->ini_log_announce_itv,
+			     log_val,
+			     0);
+
+	new_itv -= (old_itv-remaining);
+	if (new_itv <= 0) {
+		new_itv = 1;
+	}
+
+	k_timer_start(&state_ann->ann_send_periodic_timer, K_MSEC(new_itv),
+		      K_NO_WAIT);
+}
+
+struct port_user_data {
+	gptp_port_cb_t cb;
+	void *user_data;
+};
+
+static void gptp_get_port(struct net_if *iface, void *user_data)
+{
+	struct port_user_data *ud = user_data;
+	const struct device *clk;
+
+	/* Check if interface has a PTP clock. */
+	clk = net_eth_get_ptp_clock(iface);
+	if (clk) {
+		int port = gptp_get_port_number(iface);
+
+		if (port < 0) {
+			return;
+		}
+
+		ud->cb(port, iface, ud->user_data);
+	}
+}
+
+void gptp_foreach_port(gptp_port_cb_t cb, void *user_data)
+{
+	struct port_user_data ud = {
+		.cb = cb,
+		.user_data = user_data
+	};
+
+	net_if_foreach(gptp_get_port, &ud);
+}
+
+struct gptp_domain *gptp_get_domain(void)
+{
+	return &gptp_domain;
+}
+
+int gptp_get_port_data(struct gptp_domain *domain,
+		       int port,
+		       struct gptp_port_ds **port_ds,
+		       struct gptp_port_param_ds **port_param_ds,
+		       struct gptp_port_states **port_state,
+		       struct gptp_port_bmca_data **port_bmca_data,
+		       struct net_if **iface)
+{
+	if (domain != &gptp_domain) {
+		return -ENOENT;
+	}
+
+	if (port < GPTP_PORT_START || port >= GPTP_PORT_END) {
+		return -EINVAL;
+	}
+
+	if (port_ds) {
+		*port_ds = GPTP_PORT_DS(port);
+	}
+
+	if (port_param_ds) {
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+		*port_param_ds = GPTP_PORT_PARAM_DS(port);
+#else
+		*port_param_ds = NULL;
+#endif
+	}
+
+	if (port_state) {
+		*port_state = GPTP_PORT_STATE(port);
+	}
+
+	if (port_bmca_data) {
+		*port_bmca_data = GPTP_PORT_BMCA_DATA(port);
+	}
+
+	if (iface) {
+		*iface = GPTP_PORT_IFACE(port);
+	}
+
+	return 0;
+}
+
+static void init_ports(void)
+{
+	net_if_foreach(gptp_add_port, &gptp_domain.default_ds.nb_ports);
+
+	/* Only initialize the state machine once the ports are known. */
+	gptp_init_state_machine();
+
+	tid = k_thread_create(&gptp_thread_data, gptp_stack,
+			      K_KERNEL_STACK_SIZEOF(gptp_stack),
+			      (k_thread_entry_t)gptp_thread,
+			      NULL, NULL, NULL, K_PRIO_COOP(5), 0, K_NO_WAIT);
+	k_thread_name_set(&gptp_thread_data, "gptp");
+}
+
+#if defined(CONFIG_NET_GPTP_VLAN)
+static struct net_mgmt_event_callback vlan_cb;
+
+struct vlan_work {
+	struct k_work work;
+	struct net_if *iface;
+} vlan;
+
+static void disable_port(int port)
+{
+	GPTP_GLOBAL_DS()->selected_role[port] = GPTP_PORT_DISABLED;
+
+	gptp_state_machine();
+}
+
+static void vlan_enabled(struct k_work *work)
+{
+	struct vlan_work *vlan = CONTAINER_OF(work,
+					      struct vlan_work,
+					      work);
+	if (tid) {
+		int port;
+
+		port = gptp_get_port_number(vlan->iface);
+		if (port < 0) {
+			NET_DBG("No port found for iface %p", vlan->iface);
+			return;
+		}
+
+		GPTP_GLOBAL_DS()->selected_role[port] = GPTP_PORT_SLAVE;
+
+		gptp_state_machine();
+	} else {
+		init_ports();
+	}
+}
+
+static void vlan_disabled(struct k_work *work)
+{
+	struct vlan_work *vlan = CONTAINER_OF(work,
+					      struct vlan_work,
+					      work);
+	int port;
+
+	port = gptp_get_port_number(vlan->iface);
+	if (port < 0) {
+		NET_DBG("No port found for iface %p", vlan->iface);
+		return;
+	}
+
+	disable_port(port);
+}
+
+static void vlan_event_handler(struct net_mgmt_event_callback *cb,
+			       uint32_t mgmt_event,
+			       struct net_if *iface)
+{
+	uint16_t tag;
+
+	if (mgmt_event != NET_EVENT_ETHERNET_VLAN_TAG_ENABLED &&
+	    mgmt_event != NET_EVENT_ETHERNET_VLAN_TAG_DISABLED) {
+		return;
+	}
+
+#if defined(CONFIG_NET_MGMT_EVENT_INFO)
+	if (!cb->info) {
+		return;
+	}
+
+	tag = *((uint16_t *)cb->info);
+	if (tag != CONFIG_NET_GPTP_VLAN_TAG) {
+		return;
+	}
+
+	vlan.iface = iface;
+
+	if (mgmt_event == NET_EVENT_ETHERNET_VLAN_TAG_ENABLED) {
+		/* We found the right tag, now start gPTP for this interface */
+		k_work_init(&vlan.work, vlan_enabled);
+
+		NET_DBG("VLAN tag %d %s for iface %p", tag, "enabled", iface);
+	} else {
+		k_work_init(&vlan.work, vlan_disabled);
+
+		NET_DBG("VLAN tag %d %s for iface %p", tag, "disabled", iface);
+	}
+
+	k_work_submit(&vlan.work);
+#else
+	NET_WARN("VLAN event but tag info missing!");
+
+	ARG_UNUSED(tag);
+#endif
+}
+
+static void setup_vlan_events_listener(void)
+{
+	net_mgmt_init_event_callback(&vlan_cb, vlan_event_handler,
+				     NET_EVENT_ETHERNET_VLAN_TAG_ENABLED |
+				     NET_EVENT_ETHERNET_VLAN_TAG_DISABLED);
+	net_mgmt_add_event_callback(&vlan_cb);
+}
+#endif /* CONFIG_NET_GPTP_VLAN */
+
+void net_gptp_init(void)
+{
+	gptp_domain.default_ds.nb_ports = 0U;
+
+#if defined(CONFIG_NET_GPTP_VLAN)
+	/* If user has enabled gPTP over VLAN support, then we start gPTP
+	 * support after we have received correct "VLAN tag enabled" event.
+	 */
+	if (CONFIG_NET_GPTP_VLAN_TAG >= 0 &&
+	    CONFIG_NET_GPTP_VLAN_TAG < NET_VLAN_TAG_UNSPEC) {
+		setup_vlan_events_listener();
+	} else {
+		NET_WARN("VLAN tag %d set but the value is not valid.",
+			 CONFIG_NET_GPTP_VLAN_TAG);
+
+		init_ports();
+	}
+#else
+	init_ports();
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_data_set.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_data_set.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_data_set.h	(working copy)
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2018 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief PTP data sets
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_DS_H
+#define __GPTP_DS_H
+
+#if defined(CONFIG_NET_GPTP)
+
+#include <net/gptp.h>
+#include "gptp_state.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Parameters for PTP data sets. */
+#define GPTP_ALLOWED_LOST_RESP 3
+
+#if defined(CONFIG_NET_GPTP_NEIGHBOR_PROP_DELAY_THR)
+#define GPTP_NEIGHBOR_PROP_DELAY_THR CONFIG_NET_GPTP_NEIGHBOR_PROP_DELAY_THR
+#else
+/* See IEEE802.1AS B.3 should be less than 800ns (cur: 100us). */
+#define GPTP_NEIGHBOR_PROP_DELAY_THR 100000
+#endif
+
+/* Max number of ClockIdentities in pathTrace. */
+#define GPTP_MAX_PATHTRACE_SIZE CONFIG_NET_GPTP_PATH_TRACE_ELEMENTS
+
+/* Helpers to access gptp_domain fields. */
+#define GPTP_PORT_START 1
+#define GPTP_PORT_END (gptp_domain.default_ds.nb_ports + GPTP_PORT_START)
+
+#define GPTP_PORT_INDEX (port - GPTP_PORT_START)
+
+#define GPTP_GLOBAL_DS() (&gptp_domain.global_ds)
+#define GPTP_DEFAULT_DS() (&gptp_domain.default_ds)
+#define GPTP_CURRENT_DS() (&gptp_domain.current_ds)
+#define GPTP_PARENT_DS() (&gptp_domain.parent_ds)
+#define GPTP_PROPERTIES_DS() (&gptp_domain.properties_ds)
+#define GPTP_STATE() (&gptp_domain.state)
+
+#define GPTP_PORT_DS(port) \
+	(&gptp_domain.port_ds[port - GPTP_PORT_START])
+#define GPTP_PORT_STATE(port) \
+	(&gptp_domain.port_state[port - GPTP_PORT_START])
+#define GPTP_PORT_BMCA_DATA(port) \
+	(&gptp_domain.port_bmca_data[port - GPTP_PORT_START])
+#define GPTP_PORT_IFACE(port) \
+	gptp_domain.iface[port - GPTP_PORT_START]
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+#define GPTP_PORT_PARAM_DS(port)				\
+	(&gptp_domain.port_param_ds[port - GPTP_PORT_START])
+#endif
+
+#define CLEAR_RESELECT(global_ds, port) \
+	(global_ds->reselect_array &= (~(1 << (port - 1))))
+#define SET_RESELECT(global_ds, port) \
+	(global_ds->reselect_array |= (1 << (port - 1)))
+#define CLEAR_SELECTED(global_ds, port) \
+	(global_ds->selected_array &= (~(1 << (port - 1))))
+#define SET_SELECTED(global_ds, port) \
+	(global_ds->selected_array |= (1 << (port - 1)))
+#define IS_SELECTED(global_ds, port) \
+	((global_ds->selected_array >> (port - 1)) & 0x1)
+#define IS_RESELECT(global_ds, port) \
+	((global_ds->reselect_array >> (port - 1)) & 0x1)
+
+/*
+ * Global definition of the gPTP domain.
+ * Note: Only one domain is supported for now.
+ */
+extern struct gptp_domain gptp_domain;
+
+/*
+ * Type of TLV message received.
+ */
+enum gptp_tlv_type {
+	GPTP_TLV_MGNT = 0x0001,
+	GPTP_TLV_MGNT_ERR_STATUS              = 0x0002,
+	GPTP_TLV_ORGANIZATION_EXT             = 0x0003,
+	GPTP_TLV_REQ_UNICAST_TX               = 0x0004,
+	GPTP_TLV_GRANT_UNICAST_TX             = 0x0005,
+	GPTP_TLV_CANCEL_UNICAST_TX            = 0x0006,
+	GPTP_TLV_ACK_CANCEL_UNICAST_TX        = 0x0007,
+	GPTP_TLV_PATH_TRACE                   = 0x0008,
+	GPTP_TLV_ALT_TIME_OFFSET_INDICATOR    = 0x0009,
+	GPTP_TLV_AUTH                         = 0x2000,
+	GPTP_TLV_AUTH_CHALLENGE               = 0x2001,
+	GPTP_TLV_SECURITY_ASSOC_UPDATE        = 0x2002,
+	GPTP_TLV_CUM_FREQ_SCALE_FACTOR_OFFSET = 0x2003,
+};
+
+/*
+ * Class of the local clock used for a port.
+ * This is used when determining the Grand Master.
+ */
+enum gptp_clock_class {
+	GPTP_CLASS_PRIMARY                 = 6,
+	GPTP_CLASS_APP_SPECIFIC            = 13,
+	GPTP_CLASS_APP_SPECIFIC_LOST       = 14,
+	GPTP_CLASS_PRIMARY_DEGRADED_A      = 52,
+	GPTP_CLASS_APP_SPECIFIC_DEGRADED_A = 58,
+	GPTP_CLASS_PRIMARY_DEGRADED_B      = 187,
+	GPTP_CLASS_APP_SPECIFIC_DEGRADED_B = 193,
+	GPTP_CLASS_OTHER                   = 248,
+	GPTP_CLASS_SLAVE_ONLY              = 255,
+};
+
+/*
+ * For gPTP, only a subset are used.
+ * - DisabledPort
+ * - MasterPort
+ * - PassivePort
+ * - SlavePort
+ */
+enum gptp_port_state {
+	GPTP_PORT_INITIALIZING,
+	GPTP_PORT_FAULTY,
+	GPTP_PORT_DISABLED,
+	GPTP_PORT_LISTENING,
+	GPTP_PORT_PRE_MASTER,
+	GPTP_PORT_MASTER,
+	GPTP_PORT_PASSIVE,
+	GPTP_PORT_UNCALIBRATED,
+	GPTP_PORT_SLAVE,
+};
+
+enum gptp_received_info {
+	GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO,
+	GPTP_RCVD_INFO_REPEATED_MASTER_INFO,
+	GPTP_RCVD_INFO_INFERIOR_MASTER_INFO,
+	GPTP_RCVD_INFO_OTHER_INFO,
+};
+
+/**
+ * @brief Announce path trace retaining structure.
+ */
+struct gptp_path_trace {
+	/** Length of the path trace. */
+	uint16_t len;
+
+	/** Path trace of the announce message. */
+	uint8_t path_sequence[GPTP_MAX_PATHTRACE_SIZE][GPTP_CLOCK_ID_LEN];
+};
+
+/**
+ * @brief Per-time-aware system global variables.
+ *
+ * Not all variables from the standard are defined yet.
+ * The structure is to be enhanced with missing fields when those are needed.
+ *
+ * selectedRole is not defined here as it is a duplicate of the port_state
+ * variable declared in gptp_port_ds.
+ */
+struct gptp_global_ds {
+	/** Mean time interval between messages providing time-sync info. */
+	uint64_t clk_master_sync_itv;
+
+	/** Value if current time. */
+	uint64_t sync_receipt_local_time;
+
+	/** Fractional frequency offset of the Clock Source entity. */
+	double clk_src_freq_offset;
+
+	/** Last Grand Master Frequency Change. */
+	double clk_src_last_gm_freq_change;
+
+	/** Ratio of the frequency of the ClockSource to the LocalClock. */
+	double gm_rate_ratio;
+
+	/** Last Grand Master Frequency Change. */
+	double last_gm_freq_change;
+
+	/** The synchronized time computed by the ClockSlave entity. */
+	struct net_ptp_extended_time sync_receipt_time;
+
+	/** Last Grand Master Phase Change. */
+	struct gptp_scaled_ns clk_src_last_gm_phase_change;
+
+	/** Last Grand Master Phase Change. */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Global flags. */
+	struct gptp_flags global_flags;
+
+	/** System current flags. */
+	struct gptp_flags sys_flags;
+
+	/** Path trace to be sent in announce message. */
+	struct gptp_path_trace path_trace;
+
+	/** Grand Master priority vector. */
+	struct gptp_priority_vector gm_priority;
+
+	/** Previous Grand Master priority vector. */
+	struct gptp_priority_vector last_gm_priority;
+
+	/** Value of current_time when the last invoke call was received. */
+	struct gptp_uscaled_ns local_time;
+
+	/** Time maintained by the ClockMaster entity. */
+	struct net_ptp_extended_time master_time;
+
+	/** Time provided by the ClockSource entity minus the sync time. */
+	struct gptp_scaled_ns clk_src_phase_offset;
+
+	/** Grand Master Time Base Indicator. */
+	uint16_t gm_time_base_indicator;
+
+	/** Reselect port bit array. */
+	uint32_t reselect_array;
+
+	/** Selected port bit array. */
+	uint32_t selected_array;
+
+	/** Steps removed from selected master. */
+	uint16_t master_steps_removed;
+
+	/** Current UTC offset. */
+	int16_t current_utc_offset;
+
+	/** System current UTC offset. */
+	int16_t sys_current_utc_offset;
+
+	/** Time Base Indicator. */
+	uint16_t clk_src_time_base_indicator;
+
+	/** Previous Time Base Indicator. */
+	uint16_t clk_src_time_base_indicator_prev;
+
+	/** Time source. */
+	enum gptp_time_source time_source;
+
+	/** System time source. */
+	enum gptp_time_source sys_time_source;
+
+	/** Selected port Roles. */
+	enum gptp_port_state selected_role[CONFIG_NET_GPTP_NUM_PORTS + 1];
+
+	/** A Grand Master is present in the domain. */
+	bool gm_present;
+};
+
+/**
+ * @brief Default Parameter Data Set.
+ *
+ * Data Set representing capabilities of the time-aware system.
+ */
+struct gptp_default_ds {
+	/** Quality of the local clock. */
+	struct gptp_clock_quality clk_quality;
+
+	/* Source of time used by the Grand Master Clock. */
+	enum gptp_time_source time_source;
+
+	/** Clock Identity of the local clock. */
+	uint8_t clk_id[GPTP_CLOCK_ID_LEN];
+
+	/** System current flags. */
+	struct gptp_flags flags;
+
+	/** Current UTC offset. */
+	uint16_t cur_utc_offset;
+
+	/** Defines if this system is Grand Master capable. */
+	bool gm_capable;
+
+	/** Number of ports of the time-aware system. */
+	uint8_t nb_ports;
+
+	/** Primary priority of the time-aware system. */
+	uint8_t priority1;
+
+	/** Secondary priority of the time-aware system. */
+	uint8_t priority2;
+};
+
+/**
+ * @brief Current Parameter Data Set.
+ *
+ * Data Set representing information relative to the Grand Master.
+ */
+struct gptp_current_ds {
+	/** Last Grand Master Phase change . */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Time difference between a slave and the Grand Master. */
+	int64_t offset_from_master;
+
+	/** Last Grand Master Frequency change. */
+	double last_gm_freq_change;
+
+	/** Number of times a Grand Master has changed in the domain. */
+	uint32_t gm_change_count;
+
+	/** Time when the most recent Grand Master changed. */
+	uint32_t last_gm_chg_evt_time;
+
+	/** Time when the most recent Grand Master phase changed. */
+	uint32_t last_gm_phase_chg_evt_time;
+
+	/** Time when the most recent Grand Master frequency changed. */
+	uint32_t last_gm_freq_chg_evt_time;
+
+	/** Time Base Indicator of the current Grand Master. */
+	uint16_t gm_timebase_indicator;
+
+	/** Number of steps between the local clock and the Grand Master. */
+	uint8_t steps_removed;
+};
+
+/**
+ * @brief Parent Parameter Data Set.
+ *
+ * Data Set representing the parent capabilities.
+ */
+struct gptp_parent_ds {
+	/** Ratio of the frequency of the GM with the local clock. */
+	int32_t cumulative_rate_ratio;
+
+	/** Clock Identity of the Grand Master clock. */
+	uint8_t gm_id[GPTP_CLOCK_ID_LEN];
+
+	/** Clock Class of the Grand Master clock. */
+	struct gptp_clock_quality gm_clk_quality;
+
+	/** Port Identity of the Master Port attached to this system. */
+	struct gptp_port_identity port_id;
+
+	/** Primary Priority of the Grand Master clock. */
+	uint8_t gm_priority1;
+
+	/** Secondary Priority of the Grand Master clock. */
+	uint8_t gm_priority2;
+};
+
+/**
+ * @brief Time Properties Parameter Data Set.
+ *
+ * Data Set representing Grand Master capabilities from the point of view
+ * of this system.
+ */
+struct gptp_time_prop_ds {
+	/** The time source of the Grand Master. */
+	enum gptp_time_source time_source;
+
+	/** Current UTC offset for the Grand Master. */
+	uint16_t cur_utc_offset;
+
+	/** Current UTC offset valid for the Grand Master. */
+	bool cur_utc_offset_valid : 1;
+
+	/** The Grand Master will have 59s at the end of the current UTC day.
+	 */
+	bool leap59 : 1;
+
+	/** The Grand Master will have 61s at the end of the current UTC day.
+	 */
+	bool leap61 : 1;
+
+	/** The current UTC offset of the GM is traceable to a primary ref. */
+	bool time_traceable : 1;
+
+	/** The frequency of the Grand Master is traceable to a primary ref. */
+	bool freq_traceable : 1;
+};
+
+/**
+ * @brief Port Parameter Data Set.
+ *
+ * Data Set representing port capabilities.
+ */
+struct gptp_port_ds {
+	/** Maximum interval between sync messages. */
+	uint64_t sync_receipt_timeout_time_itv;
+
+	/** Asymmetry on the link relative to the grand master time base. */
+	int64_t delay_asymmetry;
+
+	/** One way propagation time on the link attached to this port. */
+	double neighbor_prop_delay;
+
+	/** Propagation time threshold for the link attached to this port. */
+	double neighbor_prop_delay_thresh;
+
+	/** Estimate of the ratio of the frequency with the peer. */
+	double neighbor_rate_ratio;
+
+	/** Port Identity of the port. */
+	struct gptp_port_identity port_id;
+
+	/** Sync event transmission interval for the port. */
+	struct gptp_uscaled_ns half_sync_itv;
+
+	/** Path Delay Request transmission interval for the port. */
+	struct gptp_uscaled_ns pdelay_req_itv;
+
+	/** Maximum number of Path Delay Requests without a response. */
+	uint16_t allowed_lost_responses;
+
+	/** Current Sync sequence id for this port. */
+	uint16_t sync_seq_id;
+
+	/** Current Path Delay Request sequence id for this port. */
+	uint16_t pdelay_req_seq_id;
+
+	/** Current Announce sequence id for this port. */
+	uint16_t announce_seq_id;
+
+	/** Current Signaling sequence id for this port. */
+	uint16_t signaling_seq_id;
+
+	/** Initial Announce Interval as a Logarithm to base 2. */
+	int8_t ini_log_announce_itv;
+
+	/** Current Announce Interval as a Logarithm to base 2. */
+	int8_t cur_log_announce_itv;
+
+	/** Time without receiving announce messages before running BMCA. */
+	uint8_t announce_receipt_timeout;
+
+	/** Initial Sync Interval as a Logarithm to base 2. */
+	int8_t ini_log_half_sync_itv;
+
+	/** Current Sync Interval as a Logarithm to base 2. */
+	int8_t cur_log_half_sync_itv;
+
+	/** Time without receiving sync messages before running BMCA. */
+	uint8_t sync_receipt_timeout;
+
+	/** Initial Path Delay Request Interval as a Logarithm to base 2. */
+	int8_t ini_log_pdelay_req_itv;
+
+	/** Current Path Delay Request Interval as a Logarithm to base 2. */
+	int8_t cur_log_pdelay_req_itv;
+
+	/** Version of PTP running on this port. */
+	uint8_t version;
+
+	/** Time synchronization and Best Master Selection enabled. */
+	bool ptt_port_enabled : 1;
+
+	/** Previous status of ptt_port_enabled. */
+	bool prev_ptt_port_enabled : 1;
+
+	/** The port is measuring the path delay. */
+	bool is_measuring_delay : 1;
+
+	/** The port is capable of running IEEE802.1AS. */
+	bool as_capable : 1;
+
+	/** Whether neighborRateRatio needs to be computed for this port. */
+	bool compute_neighbor_rate_ratio : 1;
+
+	/** Whether neighborPropDelay needs to be computed for this port. */
+	bool compute_neighbor_prop_delay : 1;
+
+	/** Whether neighbor rate ratio can be used to update clocks. */
+	bool neighbor_rate_ratio_valid : 1;
+};
+
+/**
+ * @brief Port Parameter Statistics.
+ *
+ * Data Set containing statistics associated with various events.
+ */
+struct gptp_port_param_ds {
+	/** Number of Sync messages received. */
+	uint32_t rx_sync_count;
+
+	/** Number of Follow Up messages received. */
+	uint32_t rx_fup_count;
+
+	/** Number of Path Delay Requests messages received. */
+	uint32_t rx_pdelay_req_count;
+
+	/** Number of Path Delay Response messages received. */
+	uint32_t rx_pdelay_resp_count;
+
+	/** Number of Path Delay Follow Up messages received. */
+	uint32_t rx_pdelay_resp_fup_count;
+
+	/** Number of Announce messages received. */
+	uint32_t rx_announce_count;
+
+	/** Number of ptp messages discarded. */
+	uint32_t rx_ptp_packet_discard_count;
+
+	/** Number of Sync reception timeout. */
+	uint32_t sync_receipt_timeout_count;
+
+	/** Number of Announce reception timeout. */
+	uint32_t announce_receipt_timeout_count;
+
+	/** Number Path Delay Requests without a response. */
+	uint32_t pdelay_allowed_lost_resp_exceed_count;
+
+	/** Number of Sync messages sent. */
+	uint32_t tx_sync_count;
+
+	/** Number of Follow Up messages sent. */
+	uint32_t tx_fup_count;
+
+	/** Number of Path Delay Request messages sent. */
+	uint32_t tx_pdelay_req_count;
+
+	/** Number of Path Delay Response messages sent. */
+	uint32_t tx_pdelay_resp_count;
+
+	/** Number of Path Delay Response messages sent. */
+	uint32_t tx_pdelay_resp_fup_count;
+
+	/** Number of Announce messages sent. */
+	uint32_t tx_announce_count;
+
+	/** Neighbor propagation delay threshold exceeded. */
+	uint32_t neighbor_prop_delay_exceeded;
+};
+
+/**
+ * @brief gPTP domain.
+ *
+ * Data Set containing all the information necessary to represent
+ * one time-aware system domain.
+ */
+struct gptp_domain {
+	/** Global Data Set for this gPTP domain. */
+	struct gptp_global_ds global_ds;
+
+	/** Default Data Set for this gPTP domain. */
+	struct gptp_default_ds default_ds;
+
+	/** Current Data Set for this gPTP domain. */
+	struct gptp_current_ds current_ds;
+
+	/** Parent Data Set for this gPTP domain. */
+	struct gptp_parent_ds parent_ds;
+
+	/** Time Properties Data Set for this gPTP domain. */
+	struct gptp_time_prop_ds properties_ds;
+
+	/** Current State of the MI State Machines for this gPTP domain. */
+	struct gptp_states state;
+
+	/** Port Parameter Data Sets for this gPTP domain. */
+	struct gptp_port_ds port_ds[CONFIG_NET_GPTP_NUM_PORTS];
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+	/** Port Parameter Statistics Data Sets for this gPTP domain. */
+	struct gptp_port_param_ds port_param_ds[CONFIG_NET_GPTP_NUM_PORTS];
+#endif /* CONFIG_NET_GPTP_STATISTICS */
+
+	/** Current States of the MD State Machines for this gPTP domain. */
+	struct gptp_port_states port_state[CONFIG_NET_GPTP_NUM_PORTS];
+
+	/** Shared data between BMCA State Machines for this gPTP domain. */
+	struct gptp_port_bmca_data port_bmca_data[CONFIG_NET_GPTP_NUM_PORTS];
+
+	/* Network interface linked to the PTP PORT. */
+	struct net_if *iface[CONFIG_NET_GPTP_NUM_PORTS];
+};
+
+/**
+ * @brief Get port specific data from gPTP domain.
+ * @details This contains all the configuration / status of the gPTP domain.
+ *
+ * @param domain gPTP domain
+ * @param port Port id
+ * @param port_ds Port specific parameter data set (returned to caller)
+ * @param port_param_ds Port parameter statistics data set (returned to caller)
+ * @param port_state Port specific states data set (returned to caller)
+ * @param port_bmca Port BMCA state machine specific data (returned to caller)
+ * @param iface Port specific parameter data set (returned to caller)
+ *
+ * @return 0 if ok, < 0 if error
+ */
+int gptp_get_port_data(struct gptp_domain *domain, int port,
+		       struct gptp_port_ds **port_ds,
+		       struct gptp_port_param_ds **port_param_ds,
+		       struct gptp_port_states **port_state,
+		       struct gptp_port_bmca_data **port_bmca_data,
+		       struct net_if **iface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_GPTP */
+
+#endif /* __GPTP_DS_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.h	(working copy)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief GPTP Media Dependent interface for full duplex and point to point
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_MD_H
+#define __GPTP_MD_H
+
+#include <net/gptp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Media Dependent Sync Information.
+ *
+ * This structure applies for MDSyncReceive as well as MDSyncSend.
+ */
+struct gptp_md_sync_info {
+	/* Time of the current grandmaster compared to the previous. */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Most recent preciseOriginTimestamp from the PortSyncSync. */
+	struct net_ptp_time precise_orig_ts;
+
+	/** Most recent followupCorrectionField from the PortSyncSync. */
+	int64_t follow_up_correction_field;
+
+	/** Most recent upstreamTxTime from the PortSyncSync. */
+	uint64_t upstream_tx_time;
+
+	/* Frequency of the current grandmaster compared to the previous. */
+	double last_gm_freq_change;
+
+	/** Most recent rateRatio from the PortSyncSync. */
+	double rate_ratio;
+
+	/** PortIdentity of this port. */
+	struct gptp_port_identity src_port_id;
+
+	/* Time Base Indicator of the current Grand Master. */
+	uint16_t gm_time_base_indicator;
+
+	/** Current Log Sync Interval for this port. */
+	int8_t log_msg_interval;
+};
+
+/**
+ * @brief Initialize all Media Dependent State Machines.
+ */
+void gptp_md_init_state_machine(void);
+
+/**
+ * @brief Run all Media Dependent State Machines.
+ *
+ * @param port Number of the port the State Machines needs to be run on.
+ */
+void gptp_md_state_machines(int port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPTP_MD_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_md.c	(working copy)
@@ -0,0 +1,898 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
+
+#include "gptp_messages.h"
+#include "gptp_md.h"
+#include "gptp_data_set.h"
+#include "gptp_private.h"
+
+static void gptp_md_sync_prepare(struct net_pkt *pkt,
+				 struct gptp_md_sync_info *sync_send,
+				 int port_number)
+{
+	struct gptp_hdr *hdr;
+
+	hdr = GPTP_HDR(pkt);
+
+	memcpy(&hdr->port_id.clk_id, &sync_send->src_port_id.clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	hdr->port_id.port_number = htons(port_number);
+
+	hdr->log_msg_interval = sync_send->log_msg_interval;
+}
+
+static void gptp_md_follow_up_prepare(struct net_pkt *pkt,
+				      struct gptp_md_sync_info *sync_send,
+				      int port_number)
+{
+	struct gptp_hdr *hdr;
+	struct gptp_follow_up *fup;
+
+	hdr = GPTP_HDR(pkt);
+	fup = GPTP_FOLLOW_UP(pkt);
+
+	/*
+	 * Compute correction field according to IEEE802.1AS 11.2.14.2.3.
+	 *
+	 * The correction_field already contains the timestamp of the sync
+	 * message.
+	 *
+	 * TODO: if the value to be stored in correction_field is too big to
+	 * be represented, the field should be set to all 1's except the most
+	 * significant bit.
+	 */
+	hdr->correction_field -= sync_send->upstream_tx_time;
+	hdr->correction_field *= sync_send->rate_ratio;
+	hdr->correction_field += sync_send->follow_up_correction_field;
+	hdr->correction_field <<= 16;
+
+	memcpy(&hdr->port_id.clk_id, &sync_send->src_port_id.clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	hdr->port_id.port_number = htons(port_number);
+
+	hdr->log_msg_interval = sync_send->log_msg_interval;
+
+	fup->prec_orig_ts_secs_high =
+		htons(sync_send->precise_orig_ts._sec.high);
+	fup->prec_orig_ts_secs_low =
+		htonl(sync_send->precise_orig_ts._sec.low);
+	fup->prec_orig_ts_nsecs =
+		htonl(sync_send->precise_orig_ts.nanosecond);
+
+	fup->tlv_hdr.type = htons(GPTP_TLV_ORGANIZATION_EXT);
+	fup->tlv_hdr.len = htons(sizeof(struct gptp_follow_up_tlv));
+	fup->tlv.org_id[0] = GPTP_FUP_TLV_ORG_ID_BYTE_0;
+	fup->tlv.org_id[1] = GPTP_FUP_TLV_ORG_ID_BYTE_1;
+	fup->tlv.org_id[2] = GPTP_FUP_TLV_ORG_ID_BYTE_2;
+	fup->tlv.org_sub_type[0] = 0U;
+	fup->tlv.org_sub_type[1] = 0U;
+	fup->tlv.org_sub_type[2] = GPTP_FUP_TLV_ORG_SUB_TYPE;
+
+	fup->tlv.cumulative_scaled_rate_offset =
+		(sync_send->rate_ratio - 1.0) * GPTP_POW2_41;
+	fup->tlv.cumulative_scaled_rate_offset =
+		ntohl(fup->tlv.cumulative_scaled_rate_offset);
+	fup->tlv.gm_time_base_indicator =
+		ntohs(sync_send->gm_time_base_indicator);
+	fup->tlv.last_gm_phase_change.high =
+		ntohl(sync_send->last_gm_phase_change.high);
+	fup->tlv.last_gm_phase_change.low =
+		ntohll(sync_send->last_gm_phase_change.low);
+	fup->tlv.scaled_last_gm_freq_change = sync_send->last_gm_freq_change;
+	fup->tlv.scaled_last_gm_freq_change =
+		ntohl(fup->tlv.scaled_last_gm_freq_change);
+}
+
+static int gptp_set_md_sync_receive(int port,
+				    struct gptp_md_sync_info *sync_rcv)
+{
+	struct gptp_sync_rcv_state *state;
+	struct gptp_port_ds *port_ds;
+	struct gptp_hdr *sync_hdr, *fup_hdr;
+	struct gptp_follow_up *fup;
+	struct net_ptp_time *sync_ts;
+	double prop_delay_rated;
+	double delay_asymmetry_rated;
+
+	state = &GPTP_PORT_STATE(port)->sync_rcv;
+	if (!state->rcvd_sync_ptr || !state->rcvd_follow_up_ptr) {
+		return -EINVAL;
+	}
+
+	port_ds = GPTP_PORT_DS(port);
+
+	sync_hdr = GPTP_HDR(state->rcvd_sync_ptr);
+	fup_hdr = GPTP_HDR(state->rcvd_follow_up_ptr);
+	fup = GPTP_FOLLOW_UP(state->rcvd_follow_up_ptr);
+	sync_ts = &state->rcvd_sync_ptr->timestamp;
+
+	sync_rcv->follow_up_correction_field =
+		ntohll(fup_hdr->correction_field);
+	memcpy(&sync_rcv->src_port_id, &sync_hdr->port_id,
+	       sizeof(struct gptp_port_identity));
+	sync_rcv->log_msg_interval = fup_hdr->log_msg_interval;
+	sync_rcv->precise_orig_ts._sec.high =
+		ntohs(fup->prec_orig_ts_secs_high);
+	sync_rcv->precise_orig_ts._sec.low = ntohl(fup->prec_orig_ts_secs_low);
+	sync_rcv->precise_orig_ts.nanosecond = ntohl(fup->prec_orig_ts_nsecs);
+
+	/* Compute time when sync was sent by the remote. */
+	sync_rcv->upstream_tx_time = sync_ts->second;
+	sync_rcv->upstream_tx_time *= NSEC_PER_SEC;
+	sync_rcv->upstream_tx_time += sync_ts->nanosecond;
+
+	prop_delay_rated = port_ds->neighbor_prop_delay;
+	prop_delay_rated /= port_ds->neighbor_rate_ratio;
+
+	sync_rcv->upstream_tx_time -= prop_delay_rated;
+
+	delay_asymmetry_rated = port_ds->delay_asymmetry;
+	delay_asymmetry_rated /= port_ds->neighbor_rate_ratio;
+
+	sync_rcv->upstream_tx_time -= delay_asymmetry_rated;
+
+	sync_rcv->rate_ratio = ntohl(fup->tlv.cumulative_scaled_rate_offset);
+	sync_rcv->rate_ratio /= GPTP_POW2_41;
+	sync_rcv->rate_ratio += 1;
+
+	sync_rcv->gm_time_base_indicator =
+		ntohs(fup->tlv.gm_time_base_indicator);
+	sync_rcv->last_gm_phase_change.high =
+		ntohl(fup->tlv.last_gm_phase_change.high);
+	sync_rcv->last_gm_phase_change.low =
+		ntohll(fup->tlv.last_gm_phase_change.low);
+	sync_rcv->last_gm_freq_change =
+		ntohl(fup->tlv.scaled_last_gm_freq_change);
+
+	return 0;
+}
+
+static void gptp_md_pdelay_reset(int port)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+
+	NET_WARN("Reset Pdelay requests");
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	if (state->lost_responses < port_ds->allowed_lost_responses) {
+		state->lost_responses += 1U;
+	} else {
+		port_ds->is_measuring_delay = false;
+		port_ds->as_capable = false;
+		state->init_pdelay_compute = true;
+	}
+}
+
+static void gptp_md_pdelay_check_multiple_resp(int port)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+	int duration;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	if ((state->rcvd_pdelay_resp > 1) ||
+			(state->rcvd_pdelay_follow_up > 1)) {
+		port_ds->as_capable = false;
+		NET_WARN("Too many responses (%d / %d)",
+			 state->rcvd_pdelay_resp,
+			 state->rcvd_pdelay_follow_up);
+		state->multiple_resp_count++;
+	} else {
+		state->multiple_resp_count = 0U;
+	}
+
+	if (state->multiple_resp_count >= 3U) {
+		state->multiple_resp_count = 0U;
+		k_timer_stop(&state->pdelay_timer);
+		state->pdelay_timer_expired = false;
+
+		/* Subtract time spent since last pDelay request. */
+		duration = GPTP_MULTIPLE_PDELAY_RESP_WAIT -
+			gptp_uscaled_ns_to_timer_ms(&port_ds->pdelay_req_itv);
+
+		k_timer_start(&state->pdelay_timer, K_MSEC(duration),
+			      K_NO_WAIT);
+	} else {
+		state->state = GPTP_PDELAY_REQ_SEND_REQ;
+	}
+}
+
+static void gptp_md_compute_pdelay_rate_ratio(int port)
+{
+	uint64_t ingress_tstamp = 0U;
+	uint64_t resp_evt_tstamp = 0U;
+	struct gptp_pdelay_resp_follow_up *fup;
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+	struct net_pkt *pkt;
+	struct gptp_hdr *hdr;
+	double neighbor_rate_ratio;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Get ingress timestamp. */
+	pkt = state->rcvd_pdelay_resp_ptr;
+	if (pkt) {
+		ingress_tstamp =
+			gptp_timestamp_to_nsec(net_pkt_timestamp(pkt));
+	}
+
+	/* Get peer corrected timestamp. */
+	pkt = state->rcvd_pdelay_follow_up_ptr;
+	if (pkt) {
+		hdr = GPTP_HDR(pkt);
+		fup = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
+
+		resp_evt_tstamp = ntohs(fup->resp_orig_ts_secs_high);
+		resp_evt_tstamp <<= 32;
+		resp_evt_tstamp |= ntohl(fup->resp_orig_ts_secs_low);
+		resp_evt_tstamp *= NSEC_PER_SEC;
+		resp_evt_tstamp += ntohl(fup->resp_orig_ts_nsecs);
+		resp_evt_tstamp += (ntohll(hdr->correction_field) >> 16);
+	}
+
+	if (state->init_pdelay_compute) {
+		state->init_pdelay_compute = false;
+
+		state->ini_resp_ingress_tstamp = ingress_tstamp;
+		state->ini_resp_evt_tstamp = resp_evt_tstamp;
+
+		neighbor_rate_ratio = 1.0;
+
+		state->neighbor_rate_ratio_valid = false;
+	} else {
+		if (resp_evt_tstamp == state->ini_resp_evt_tstamp) {
+			state->neighbor_rate_ratio_valid = false;
+			neighbor_rate_ratio = 1.0;
+		} else {
+			neighbor_rate_ratio =
+				(resp_evt_tstamp - state->ini_resp_evt_tstamp);
+			neighbor_rate_ratio /=
+				(ingress_tstamp -
+				 state->ini_resp_ingress_tstamp);
+
+			/* Measure the ratio with the previously sent response.
+			 */
+			state->ini_resp_ingress_tstamp = ingress_tstamp;
+			state->ini_resp_evt_tstamp = resp_evt_tstamp;
+			state->neighbor_rate_ratio_valid = true;
+		}
+	}
+
+	port_ds->neighbor_rate_ratio = neighbor_rate_ratio;
+	port_ds->neighbor_rate_ratio_valid = state->neighbor_rate_ratio_valid;
+}
+
+static void gptp_md_compute_prop_time(int port)
+{
+	uint64_t t1_ns = 0U, t2_ns = 0U, t3_ns = 0U, t4_ns = 0U;
+	struct gptp_pdelay_resp_follow_up *fup;
+	struct gptp_pdelay_req_state *state;
+	struct gptp_pdelay_resp *resp;
+	struct gptp_port_ds *port_ds;
+	struct gptp_hdr *hdr;
+	struct net_pkt *pkt;
+	double prop_time, turn_around;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Get egress timestamp. */
+	pkt = state->tx_pdelay_req_ptr;
+	if (pkt) {
+		t1_ns = gptp_timestamp_to_nsec(net_pkt_timestamp(pkt));
+	}
+
+	/* Get ingress timestamp. */
+	pkt = state->rcvd_pdelay_resp_ptr;
+	if (pkt) {
+		t4_ns = gptp_timestamp_to_nsec(net_pkt_timestamp(pkt));
+	}
+
+	/* Get peer corrected timestamps. */
+	pkt = state->rcvd_pdelay_resp_ptr;
+	if (pkt) {
+		hdr = GPTP_HDR(pkt);
+		resp = GPTP_PDELAY_RESP(pkt);
+
+		t2_ns = ((uint64_t)ntohs(resp->req_receipt_ts_secs_high)) << 32;
+		t2_ns |= ntohl(resp->req_receipt_ts_secs_low);
+		t2_ns *= NSEC_PER_SEC;
+		t2_ns += ntohl(resp->req_receipt_ts_nsecs);
+		t2_ns += (ntohll(hdr->correction_field) >> 16);
+	}
+
+	pkt = state->rcvd_pdelay_follow_up_ptr;
+	if (pkt) {
+		hdr = GPTP_HDR(pkt);
+		fup = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
+
+		t3_ns = ((uint64_t)ntohs(fup->resp_orig_ts_secs_high)) << 32;
+		t3_ns |= ntohl(fup->resp_orig_ts_secs_low);
+		t3_ns *= NSEC_PER_SEC;
+		t3_ns += ntohl(fup->resp_orig_ts_nsecs);
+		t3_ns += (ntohll(hdr->correction_field) >> 16);
+	}
+
+	prop_time = t4_ns - t1_ns;
+
+	turn_around = t3_ns - t2_ns;
+
+	/* Adjusting the turn-around time for peer to local clock rate
+	 * difference. The check is implemented the same way as how Avnu/gptp
+	 * daemon is doing it. This comment is also found in their source
+	 * for the magic values "TODO: Are these .998 and 1.002 specifically
+	 * defined in the standard?"
+	 */
+	if (port_ds->neighbor_rate_ratio > .998 &&
+	    port_ds->neighbor_rate_ratio < 1.002) {
+		turn_around *= port_ds->neighbor_rate_ratio;
+	}
+
+	prop_time -= turn_around;
+	prop_time /= 2;
+
+	port_ds->neighbor_prop_delay = prop_time;
+}
+
+static void gptp_md_pdelay_compute(int port)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+	struct gptp_hdr *hdr;
+	struct net_pkt *pkt;
+	bool local_clock;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	if (!state->tx_pdelay_req_ptr || !state->rcvd_pdelay_resp_ptr ||
+	    !state->rcvd_pdelay_follow_up_ptr) {
+		NET_ERR("Compute path delay called without buffer ready");
+		port_ds->as_capable = false;
+		goto out;
+	}
+
+	if (port_ds->compute_neighbor_rate_ratio) {
+		gptp_md_compute_pdelay_rate_ratio(port);
+	}
+
+	if (port_ds->compute_neighbor_prop_delay) {
+		gptp_md_compute_prop_time(port);
+
+		NET_DBG("Neighbor prop delay %d",
+			(int32_t)port_ds->neighbor_prop_delay);
+	}
+
+	state->lost_responses = 0U;
+	port_ds->is_measuring_delay = true;
+
+	pkt = state->rcvd_pdelay_follow_up_ptr;
+	hdr = GPTP_HDR(pkt);
+
+	local_clock = !memcmp(gptp_domain.default_ds.clk_id,
+			      hdr->port_id.clk_id,
+			      GPTP_CLOCK_ID_LEN);
+	if (local_clock) {
+		NET_WARN("Discard path delay response from local clock.");
+		goto out;
+	}
+
+	if (!state->neighbor_rate_ratio_valid) {
+		goto out;
+	}
+
+	/*
+	 * Currently, if the computed delay is negative, this means
+	 * that it is negligeable enough compared to other factors.
+	 */
+	if ((port_ds->neighbor_prop_delay <=
+	     port_ds->neighbor_prop_delay_thresh)) {
+		port_ds->as_capable = true;
+	} else {
+		port_ds->as_capable = false;
+
+		NET_WARN("Not AS capable: %u ns > %u ns",
+			 (uint32_t)port_ds->neighbor_prop_delay,
+			 (uint32_t)port_ds->neighbor_prop_delay_thresh);
+
+		GPTP_STATS_INC(port, neighbor_prop_delay_exceeded);
+	}
+
+out:
+	/* Release buffers. */
+	if (state->tx_pdelay_req_ptr) {
+		net_pkt_unref(state->tx_pdelay_req_ptr);
+		state->tx_pdelay_req_ptr = NULL;
+	}
+
+	if (state->rcvd_pdelay_resp_ptr) {
+		net_pkt_unref(state->rcvd_pdelay_resp_ptr);
+		state->rcvd_pdelay_resp_ptr = NULL;
+	}
+
+	if (state->rcvd_pdelay_follow_up_ptr) {
+		net_pkt_unref(state->rcvd_pdelay_follow_up_ptr);
+		state->rcvd_pdelay_follow_up_ptr = NULL;
+	}
+}
+
+static void gptp_md_pdelay_req_timeout(struct k_timer *timer)
+{
+	struct gptp_pdelay_req_state *state;
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pdelay_req;
+		if (timer == &state->pdelay_timer) {
+			state->pdelay_timer_expired = true;
+
+			if (state->rcvd_pdelay_resp == 0U) {
+				GPTP_STATS_INC(port,
+					pdelay_allowed_lost_resp_exceed_count);
+			}
+		}
+	}
+}
+
+static void gptp_md_start_pdelay_req(int port)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+
+	port_ds = GPTP_PORT_DS(port);
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+
+	port_ds->neighbor_rate_ratio = 1.0;
+	port_ds->is_measuring_delay = false;
+	port_ds->as_capable = false;
+	state->lost_responses = 0U;
+	state->rcvd_pdelay_resp = 0U;
+	state->rcvd_pdelay_follow_up = 0U;
+	state->multiple_resp_count = 0U;
+}
+
+static void gptp_md_follow_up_receipt_timeout(struct k_timer *timer)
+{
+	struct gptp_sync_rcv_state *state;
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->sync_rcv;
+		if (timer == &state->follow_up_discard_timer) {
+			NET_WARN("No %s received after %s message",
+				 "FOLLOWUP", "SYNC");
+			state->follow_up_timeout_expired = true;
+		}
+	}
+}
+
+static void gptp_md_init_pdelay_req_state_machine(int port)
+{
+	struct gptp_pdelay_req_state *state;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+
+	k_timer_init(&state->pdelay_timer, gptp_md_pdelay_req_timeout, NULL);
+
+	state->state = GPTP_PDELAY_REQ_NOT_ENABLED;
+
+	state->neighbor_rate_ratio_valid = false;
+	state->init_pdelay_compute = true;
+	state->rcvd_pdelay_resp = 0U;
+	state->rcvd_pdelay_follow_up = 0U;
+	state->pdelay_timer_expired = false;
+
+	state->rcvd_pdelay_resp_ptr = NULL;
+	state->rcvd_pdelay_follow_up_ptr = NULL;
+	state->tx_pdelay_req_ptr = NULL;
+
+	state->ini_resp_evt_tstamp = 0U;
+	state->ini_resp_ingress_tstamp = 0U;
+	state->lost_responses = 0U;
+}
+
+static void gptp_md_init_pdelay_resp_state_machine(int port)
+{
+	struct gptp_pdelay_resp_state *state;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_resp;
+
+	state->state = GPTP_PDELAY_RESP_NOT_ENABLED;
+}
+
+static void gptp_md_init_sync_rcv_state_machine(int port)
+{
+	struct gptp_sync_rcv_state *state;
+
+	state = &GPTP_PORT_STATE(port)->sync_rcv;
+
+	k_timer_init(&state->follow_up_discard_timer,
+		     gptp_md_follow_up_receipt_timeout, NULL);
+
+	state->rcvd_sync = false;
+	state->rcvd_follow_up = false;
+	state->rcvd_sync_ptr = NULL;
+	state->rcvd_follow_up_ptr = NULL;
+
+	state->follow_up_timeout_expired = false;
+	state->follow_up_receipt_timeout = 0U;
+
+	state->state = GPTP_SYNC_RCV_DISCARD;
+}
+
+static void gptp_md_init_sync_send_state_machine(int port)
+{
+	struct gptp_sync_send_state *state;
+
+	state = &GPTP_PORT_STATE(port)->sync_send;
+
+	state->rcvd_md_sync = false;
+	state->md_sync_timestamp_avail = false;
+	state->sync_send_ptr = NULL;
+	state->sync_ptr = NULL;
+
+	state->state = GPTP_SYNC_SEND_INITIALIZING;
+}
+
+void gptp_md_init_state_machine(void)
+{
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		gptp_md_init_pdelay_req_state_machine(port);
+		gptp_md_init_pdelay_resp_state_machine(port);
+		gptp_md_init_sync_rcv_state_machine(port);
+		gptp_md_init_sync_send_state_machine(port);
+	}
+}
+
+static void gptp_md_pdelay_req_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_pdelay_req_state *state;
+	struct net_pkt *pkt;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Unset AS-Capable if multiple responses to a pDelay request have been
+	 * reveived.
+	 */
+	if (state->rcvd_pdelay_resp > 1 || state->rcvd_pdelay_follow_up > 1) {
+		port_ds->as_capable = false;
+	}
+
+	if (!port_ds->ptt_port_enabled) {
+		/* Make sure the timer is stopped. */
+		k_timer_stop(&state->pdelay_timer);
+		state->state = GPTP_PDELAY_REQ_NOT_ENABLED;
+	}
+
+	switch (state->state) {
+	case GPTP_PDELAY_REQ_NOT_ENABLED:
+		if (port_ds->ptt_port_enabled) {
+			/* (Re)Init interval (as defined in
+			 * LinkDelaySyncIntervalSetting state machine).
+			 */
+			port_ds->cur_log_pdelay_req_itv =
+				port_ds->ini_log_pdelay_req_itv;
+
+			gptp_set_time_itv(&port_ds->pdelay_req_itv, 1,
+					  port_ds->cur_log_pdelay_req_itv);
+
+			port_ds->compute_neighbor_rate_ratio = true;
+			port_ds->compute_neighbor_prop_delay = true;
+
+			state->pdelay_timer_expired = true;
+			state->state = GPTP_PDELAY_REQ_INITIAL_SEND_REQ;
+		}
+
+		break;
+
+	case GPTP_PDELAY_REQ_RESET:
+		gptp_md_pdelay_reset(port);
+		/* Send a request on the next timer expiry. */
+		state->state = GPTP_PDELAY_REQ_WAIT_ITV_TIMER;
+		break;
+
+	case GPTP_PDELAY_REQ_INITIAL_SEND_REQ:
+		gptp_md_start_pdelay_req(port);
+		__fallthrough;
+
+	case GPTP_PDELAY_REQ_SEND_REQ:
+		if (state->tx_pdelay_req_ptr) {
+			net_pkt_unref(state->tx_pdelay_req_ptr);
+			state->tx_pdelay_req_ptr = NULL;
+		}
+
+		if (state->rcvd_pdelay_resp_ptr) {
+			net_pkt_unref(state->rcvd_pdelay_resp_ptr);
+			state->rcvd_pdelay_resp_ptr = NULL;
+		}
+
+		if (state->rcvd_pdelay_follow_up_ptr) {
+			net_pkt_unref(state->rcvd_pdelay_follow_up_ptr);
+			state->rcvd_pdelay_follow_up_ptr = NULL;
+		}
+
+		gptp_send_pdelay_req(port);
+
+		k_timer_stop(&state->pdelay_timer);
+		state->pdelay_timer_expired = false;
+		k_timer_start(&state->pdelay_timer,
+			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
+					     &port_ds->pdelay_req_itv)),
+			      K_NO_WAIT);
+		/*
+		 * Transition directly to GPTP_PDELAY_REQ_WAIT_RESP.
+		 * Check for the TX timestamp will be done during
+		 * the computation of the path delay.
+		 */
+		state->state = GPTP_PDELAY_REQ_WAIT_RESP;
+		break;
+
+	case GPTP_PDELAY_REQ_WAIT_RESP:
+		if (state->pdelay_timer_expired) {
+			state->state = GPTP_PDELAY_REQ_RESET;
+		} else if (state->rcvd_pdelay_resp != 0U) {
+			pkt = state->rcvd_pdelay_resp_ptr;
+			if (!gptp_handle_pdelay_resp(port, pkt)) {
+				state->state = GPTP_PDELAY_REQ_WAIT_FOLLOW_UP;
+			} else {
+				state->state = GPTP_PDELAY_REQ_RESET;
+			}
+		}
+
+		break;
+
+	case GPTP_PDELAY_REQ_WAIT_FOLLOW_UP:
+		if (state->pdelay_timer_expired) {
+			state->state = GPTP_PDELAY_REQ_RESET;
+		} else if (state->rcvd_pdelay_follow_up != 0U) {
+			pkt = state->rcvd_pdelay_follow_up_ptr;
+			if (!gptp_handle_pdelay_follow_up(port, pkt)) {
+				gptp_md_pdelay_compute(port);
+				state->state = GPTP_PDELAY_REQ_WAIT_ITV_TIMER;
+			} else {
+				state->state = GPTP_PDELAY_REQ_RESET;
+			}
+		}
+
+		break;
+
+	case GPTP_PDELAY_REQ_WAIT_ITV_TIMER:
+		if (state->pdelay_timer_expired) {
+			gptp_md_pdelay_check_multiple_resp(port);
+
+			state->rcvd_pdelay_resp = 0U;
+			state->rcvd_pdelay_follow_up = 0U;
+		}
+
+		break;
+	}
+}
+
+static void gptp_md_pdelay_resp_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_pdelay_resp_state *state;
+
+	state = &GPTP_PORT_STATE(port)->pdelay_resp;
+	port_ds = GPTP_PORT_DS(port);
+
+	if (!port_ds->ptt_port_enabled) {
+		state->state = GPTP_PDELAY_RESP_NOT_ENABLED;
+	}
+
+	switch (state->state) {
+	case GPTP_PDELAY_RESP_NOT_ENABLED:
+		if (port_ds->ptt_port_enabled) {
+			state->state = GPTP_PDELAY_RESP_INITIAL_WAIT_REQ;
+		}
+
+		break;
+
+	case GPTP_PDELAY_RESP_INITIAL_WAIT_REQ:
+	case GPTP_PDELAY_RESP_WAIT_REQ:
+		/* Handled in gptp_handle_msg for latency considerations. */
+		break;
+
+	case GPTP_PDELAY_RESP_WAIT_TSTAMP:
+		/* Handled in gptp_follow_up_callback. */
+		break;
+	}
+
+}
+
+static void gptp_md_sync_receive_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_sync_rcv_state *state;
+	struct gptp_pss_rcv_state *pss_state;
+
+	state = &GPTP_PORT_STATE(port)->sync_rcv;
+	pss_state = &GPTP_PORT_STATE(port)->pss_rcv;
+	port_ds = GPTP_PORT_DS(port);
+
+	if ((!port_ds->ptt_port_enabled) || !port_ds->as_capable) {
+		/* Make sure the timer is stopped. */
+		k_timer_stop(&state->follow_up_discard_timer);
+
+		/* Discard all received messages. */
+		if (state->rcvd_sync_ptr) {
+			net_pkt_unref(state->rcvd_sync_ptr);
+			state->rcvd_sync_ptr = NULL;
+		}
+
+		if (state->rcvd_follow_up_ptr) {
+			net_pkt_unref(state->rcvd_follow_up_ptr);
+			state->rcvd_follow_up_ptr = NULL;
+		}
+
+		state->rcvd_sync = false;
+		state->rcvd_follow_up = false;
+		state->state = GPTP_SYNC_RCV_DISCARD;
+		return;
+	}
+
+	switch (state->state) {
+	case GPTP_SYNC_RCV_DISCARD:
+	case GPTP_SYNC_RCV_WAIT_SYNC:
+		if (state->rcvd_sync) {
+			gptp_handle_sync(port, state->rcvd_sync_ptr);
+			state->rcvd_sync = false;
+			state->state = GPTP_SYNC_RCV_WAIT_FOLLOW_UP;
+		} else if (state->rcvd_follow_up) {
+			/* Delete late/early message. */
+			if (state->rcvd_follow_up_ptr) {
+				net_pkt_unref(state->rcvd_follow_up_ptr);
+				state->rcvd_follow_up_ptr = NULL;
+			}
+
+			state->rcvd_follow_up = false;
+		}
+
+		break;
+
+	case GPTP_SYNC_RCV_WAIT_FOLLOW_UP:
+		/* Never received a follow up for a sync message. */
+		if (state->follow_up_timeout_expired) {
+			k_timer_stop(&state->follow_up_discard_timer);
+			state->follow_up_timeout_expired = false;
+			state->state = GPTP_SYNC_RCV_DISCARD;
+			if (state->rcvd_sync_ptr) {
+				net_pkt_unref(state->rcvd_sync_ptr);
+				state->rcvd_sync_ptr = NULL;
+			}
+
+			state->rcvd_sync = false;
+		} else if (state->rcvd_sync) {
+			/* Handle received extra sync. */
+			gptp_handle_sync(port, state->rcvd_sync_ptr);
+			state->rcvd_sync = false;
+		} else if (state->rcvd_follow_up) {
+			if (!gptp_handle_follow_up(
+				    port, state->rcvd_follow_up_ptr)) {
+
+				/*
+				 * Fill the structure to be sent to
+				 * PortSyncSyncReceive.
+				 */
+				gptp_set_md_sync_receive(port,
+							 &pss_state->sync_rcv);
+
+				pss_state->rcvd_md_sync = true;
+
+				state->state = GPTP_SYNC_RCV_WAIT_SYNC;
+
+				/* Buffers can be released now. */
+				if (state->rcvd_sync_ptr) {
+					net_pkt_unref(state->rcvd_sync_ptr);
+					state->rcvd_sync_ptr = NULL;
+				}
+
+				k_timer_stop(&state->follow_up_discard_timer);
+				state->follow_up_timeout_expired = false;
+			}
+		}
+
+		if (state->rcvd_follow_up_ptr) {
+			net_pkt_unref(state->rcvd_follow_up_ptr);
+			state->rcvd_follow_up_ptr = NULL;
+		}
+
+		state->rcvd_follow_up = false;
+		break;
+	}
+}
+
+static void gptp_md_sync_send_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_sync_send_state *state;
+	struct net_pkt *pkt;
+
+	state = &GPTP_PORT_STATE(port)->sync_send;
+	port_ds = GPTP_PORT_DS(port);
+
+	if ((!port_ds->ptt_port_enabled) || !port_ds->as_capable) {
+		state->rcvd_md_sync = false;
+		state->state = GPTP_SYNC_SEND_INITIALIZING;
+
+		/* Sync sequence id is initialized in the port_ds init function
+		 */
+		return;
+	}
+
+	switch (state->state) {
+	case GPTP_SYNC_SEND_INITIALIZING:
+		state->state = GPTP_SYNC_SEND_SEND_SYNC;
+		break;
+
+	case GPTP_SYNC_SEND_SEND_SYNC:
+		if (state->rcvd_md_sync) {
+			pkt = gptp_prepare_sync(port);
+			if (pkt) {
+				/* Reference message to track timestamp info */
+				state->sync_ptr = net_pkt_ref(pkt);
+				gptp_md_sync_prepare(pkt,
+						     state->sync_send_ptr,
+						     port);
+				gptp_send_sync(port, pkt);
+			}
+
+			state->rcvd_md_sync = false;
+			state->state = GPTP_SYNC_SEND_SEND_FUP;
+		}
+
+		break;
+
+	case GPTP_SYNC_SEND_SEND_FUP:
+		if (state->md_sync_timestamp_avail) {
+			state->md_sync_timestamp_avail = false;
+
+			if (!state->sync_ptr) {
+				NET_ERR("Sync message not available");
+				break;
+			}
+
+			pkt = gptp_prepare_follow_up(port, state->sync_ptr);
+			if (pkt) {
+				gptp_md_follow_up_prepare(pkt,
+							 state->sync_send_ptr,
+							 port);
+				gptp_send_follow_up(port, pkt);
+			}
+
+			net_pkt_unref(state->sync_ptr);
+			state->sync_ptr = NULL;
+
+			state->state = GPTP_SYNC_SEND_SEND_SYNC;
+		}
+
+		break;
+	}
+}
+
+void gptp_md_state_machines(int port)
+{
+	gptp_md_pdelay_req_state_machine(port);
+	gptp_md_pdelay_resp_state_machine(port);
+	gptp_md_sync_receive_state_machine(port);
+	gptp_md_sync_send_state_machine(port);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.h	(working copy)
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief gPTP message helpers.
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_MESSAGES_H
+#define __GPTP_MESSAGES_H
+
+#include <net/net_pkt.h>
+#include <net/ethernet.h>
+#include <net/gptp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Helpers to access gPTP messages. */
+#define GPTP_HDR(pkt) gptp_get_hdr(pkt)
+#define GPTP_ANNOUNCE(pkt) ((struct gptp_announce *)gptp_data(pkt))
+#define GPTP_SIGNALING(pkt) ((struct gptp_signaling *)gptp_data(pkt))
+#define GPTP_SYNC(pkt) ((struct gptp_sync *)gptp_data(pkt))
+#define GPTP_FOLLOW_UP(pkt) ((struct gptp_follow_up *)gptp_data(pkt))
+#define GPTP_DELAY_REQ(pkt) \
+	((struct gptp_delay_req *)gptp_data(pkt))
+#define GPTP_PDELAY_REQ(pkt) \
+	((struct gptp_pdelay_req *)gptp_data(pkt))
+#define GPTP_PDELAY_RESP(pkt) \
+	((struct gptp_pdelay_resp *)gptp_data(pkt))
+#define GPTP_PDELAY_RESP_FOLLOWUP(pkt) \
+	((struct gptp_pdelay_resp_follow_up *)gptp_data(pkt))
+
+/* Field values. */
+#define GPTP_TRANSPORT_802_1_AS 0x1
+#define GPTP_VERSION 0x2
+
+/* Message Lengths. */
+#define GPTP_PACKET_LEN(pkt) net_pkt_get_len(pkt)
+#define GPTP_VALID_LEN(pkt, len) \
+	(len > (NET_ETH_MINIMAL_FRAME_SIZE - GPTP_L2_HDR_LEN(pkt)))
+#define GPTP_L2_HDR_LEN(pkt) \
+	((long)GPTP_HDR(pkt) - (long)NET_ETH_HDR(pkt))
+
+#define GPTP_SYNC_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_sync))
+#define GPTP_FOLLOW_UP_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_follow_up))
+#define GPTP_PDELAY_REQ_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_req))
+#define GPTP_PDELAY_RESP_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp))
+#define GPTP_PDELAY_RESP_FUP_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp_follow_up))
+#define GPTP_SIGNALING_LEN \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_signaling))
+
+/* For the Announce message, the TLV is variable length. The len field
+ * indicates the length of the TLV not accounting for tlvType and lengthField
+ * which are 4 bytes.
+ */
+#define GPTP_ANNOUNCE_LEN(pkt) \
+	(sizeof(struct gptp_hdr) + sizeof(struct gptp_announce) \
+	 + ntohs(GPTP_ANNOUNCE(pkt)->tlv.len) \
+	 - sizeof(struct gptp_path_trace_tlv) + 4)
+
+#define GPTP_CHECK_LEN(pkt, len) \
+	((GPTP_PACKET_LEN(pkt) != len) && (GPTP_VALID_LEN(pkt, len)))
+#define GPTP_ANNOUNCE_CHECK_LEN(pkt) \
+	((GPTP_PACKET_LEN(pkt) != GPTP_ANNOUNCE_LEN(pkt)) && \
+	 (GPTP_VALID_LEN(pkt, GPTP_ANNOUNCE_LEN(pkt))))
+
+/* Header Flags. Byte 0. */
+#define GPTP_FLAG_ALT_MASTER        BIT(0)
+#define GPTP_FLAG_TWO_STEP          BIT(1)
+#define GPTP_FLAG_UNICAST           BIT(2)
+#define GPTP_FLAG_PROFILE_SPECIFIC1 BIT(5)
+#define GPTP_FLAG_PROFILE_SPECIFIC2 BIT(6)
+
+/* Header Flags. Byte 1. */
+#define GPTP_FLAG_LEAP61            BIT(0)
+#define GPTP_FLAG_LEAP59            BIT(1)
+#define GPTP_FLAG_CUR_UTC_OFF_VALID BIT(2)
+#define GPTP_FLAG_PTP_TIMESCALE     BIT(3)
+#define GPTP_FLAG_TIME_TRACEABLE    BIT(4)
+#define GPTP_FLAG_FREQ_TRACEABLE    BIT(5)
+
+/* Signaling Interval Flags. */
+#define GPTP_FLAG_COMPUTE_NEIGHBOR_RATE_RATIO 0x1
+#define GPTP_FLAG_COMPUTE_NEIGHBOR_PROP_DELAY 0x2
+
+/* Signaling Interval Values. */
+#define GPTP_ITV_KEEP               -128
+#define GPTP_ITV_SET_TO_INIT        126
+#define GPTP_ITV_STOP               127
+
+/* Control. Only set for header compatibility with v1. */
+#define GPTP_SYNC_CONTROL_VALUE     0x0
+#define GPTP_FUP_CONTROL_VALUE      0x2
+#define GPTP_OTHER_CONTROL_VALUE    0x5
+
+/* Other default values. */
+#define GPTP_RESP_LOG_MSG_ITV           0x7F
+#define GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE htons(0x8)
+
+/* Organization Id used for TLV. */
+#define GPTP_FUP_TLV_ORG_ID_BYTE_0  0x00
+#define GPTP_FUP_TLV_ORG_ID_BYTE_1  0x80
+#define GPTP_FUP_TLV_ORG_ID_BYTE_2  0xC2
+#define GPTP_FUP_TLV_ORG_SUB_TYPE   0x01
+
+/**
+ * @brief gPTP Clock Quality
+ *
+ * Defines the quality of a clock.
+ * This is used by the Best Master Clock Algorithm.
+ */
+struct gptp_clock_quality {
+	uint8_t clock_class;
+	uint8_t clock_accuracy;
+	uint16_t offset_scaled_log_var;
+} __packed;
+
+/**
+ * @brief gPTP Root System Identity
+ *
+ * Defines the Grand Master of a clock.
+ * This is used by the Best Master Clock Algorithm.
+ */
+struct gptp_root_system_identity {
+	/** Grand Master priority1 component. */
+	uint8_t grand_master_prio1;
+
+	/** Grand Master clock quality. */
+	struct gptp_clock_quality clk_quality;
+
+	/** Grand Master priority2 component. */
+	uint8_t grand_master_prio2;
+
+	/** Grand Master clock identity. */
+	uint8_t grand_master_id[GPTP_CLOCK_ID_LEN];
+} __packed;
+
+/* Definition of all message types as defined by IEEE802.1AS. */
+
+struct gptp_path_trace_tlv {
+	/** TLV type: 0x8. */
+	uint16_t type;
+
+	/** Length. Number of TLVs * 8 bytes. */
+	uint16_t len;
+
+	/** ClockIdentity array of the successive time-aware systems. */
+	uint8_t  path_sequence[1][8];
+} __packed;
+
+struct gptp_announce {
+	/** Reserved fields. */
+	uint8_t reserved1[10];
+
+	/** Current UTC offset. */
+	int16_t cur_utc_offset;
+
+	/** Reserved field. */
+	uint8_t reserved2;
+
+	/* gmPriorityVector priority 1 of the peer sending the message. */
+	struct gptp_root_system_identity root_system_id;
+
+	/** masterStepsRemoved of the peer sending the message. */
+	uint16_t steps_removed;
+
+	/** timeSource of the peer sending the message. */
+	uint8_t time_source;
+
+	/* Path Trace TLV. This field has a variable length. */
+	struct gptp_path_trace_tlv tlv;
+} __packed;
+
+struct gptp_sync {
+	/** Reserved field. This field is used for PTPv2, unused in gPTP. */
+	uint8_t reserved[10];
+} __packed;
+
+struct gptp_follow_up_tlv_hdr {
+	/** TLV type: 0x3. */
+	uint16_t type;
+
+	/** Length: 28. */
+	uint16_t len;
+} __packed;
+
+struct gptp_follow_up_tlv {
+	/** Organization Id: 00-80-C2. */
+	uint8_t org_id[3];
+
+	/** Organization Sub Type: 1. */
+	uint8_t org_sub_type[3];
+
+	/** Rate ratio relative to the grand master of the peer. */
+	int32_t cumulative_scaled_rate_offset;
+
+	/** Time Base Indicator of the current Grand Master. */
+	uint16_t gm_time_base_indicator;
+
+	/** Difference of the time between the current GM and the previous. */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Diff of the frequency between the current GM and the previous. */
+	int32_t scaled_last_gm_freq_change;
+} __packed;
+
+struct gptp_follow_up {
+	/** Higher 16 bits of the seconds at which the sync was sent. */
+	uint16_t prec_orig_ts_secs_high;
+
+	/** Lower 32 bits of the seconds at which the sync was sent. */
+	uint32_t prec_orig_ts_secs_low;
+
+	/** Nanoseconds at which the sync was sent. */
+	uint32_t prec_orig_ts_nsecs;
+
+	/** Follow up TLV. */
+	struct gptp_follow_up_tlv_hdr tlv_hdr;
+	struct gptp_follow_up_tlv tlv;
+} __packed;
+
+struct gptp_pdelay_req {
+	/** Reserved fields. */
+	uint8_t reserved1[10];
+
+	/** Reserved fields. */
+	uint8_t reserved2[10];
+} __packed;
+
+struct gptp_pdelay_resp {
+	/** Higher 16 bits of the seconds at which the request was received. */
+	uint16_t req_receipt_ts_secs_high;
+
+	/** Lower 32 bits of the seconds at which the request was received. */
+	uint32_t req_receipt_ts_secs_low;
+
+	/** Nanoseconds at which the pdelay request was received. */
+	uint32_t req_receipt_ts_nsecs;
+
+	/** Source Port Id of the Path Delay Request. */
+	struct gptp_port_identity requesting_port_id;
+} __packed;
+
+struct gptp_pdelay_resp_follow_up {
+	/** Higher 16 bits of the seconds at which the response was sent. */
+	uint16_t resp_orig_ts_secs_high;
+
+	/** Lower 32 bits of the seconds at which the response was sent. */
+	uint32_t resp_orig_ts_secs_low;
+
+	/** Nanoseconds at which the response was received. */
+	uint32_t resp_orig_ts_nsecs;
+
+	/** Source Port Id of the Path Delay Request. */
+	struct gptp_port_identity requesting_port_id;
+} __packed;
+
+struct gptp_message_itv_req_tlv {
+	/** TLV type: 0x3. */
+	uint16_t type;
+
+	/** Length field: 12. */
+	uint16_t len;
+
+	/** Organization Id: 00-80-C2. */
+	uint8_t org_id[3];
+
+	/** Organization sub type: 0x2. */
+	uint8_t org_sub_type[3];
+
+	/** Log to base 2 of the mean time interval between pdelay requests. */
+	int8_t link_delay_itv;
+
+	/** Log to base 2 of the mean time interval between syncs. */
+	int8_t time_sync_itv;
+
+	/** Log to base 2 of the mean time interval between announces. */
+	int8_t announce_itv;
+
+	/** Flags (computeNeighborRateRatio and computeNeighborPropDelay). */
+	union {
+		struct {
+		    uint8_t compute_neighbor_rate_ratio : 1;
+		    uint8_t compute_neighbor_prop_delay : 1;
+		};
+		uint8_t flags;
+	};
+	/** Reserved fields. */
+	uint8_t reserved[2];
+} __packed;
+
+struct gptp_signaling {
+	/** Target Port Identity , always 0xFF. */
+	struct gptp_port_identity target_port_id;
+
+	/** Message Interval TLV. */
+	struct gptp_message_itv_req_tlv tlv;
+} __packed;
+
+/**
+ * @brief Compute gPTP message location.
+ *
+ * @param pkt Network Buffer containing a gPTP message.
+ *
+ * @return Pointer to the start of the gPTP message inside the packet.
+ */
+static inline uint8_t *gptp_data(struct net_pkt *pkt)
+{
+	return (uint8_t *)GPTP_HDR(pkt) + sizeof(struct gptp_hdr);
+}
+
+/* Functions to prepare messages. */
+
+/**
+ * @brief Prepare Sync message.
+ *
+ * @param port gPTP port number.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_sync(int port);
+
+/**
+ * @brief Prepare Follow Up message.
+ *
+ * @param port gPTP port number.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync);
+
+/**
+ * @brief Prepare Path Delay Request message.
+ *
+ * @param port gPTP port number.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_pdelay_req(int port);
+
+/**
+ * @brief Prepare Path Delay Response message.
+ *
+ * @param port gPTP port number.
+ * @param req Path Delay Request to reply to.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_pdelay_resp(int port,
+		struct net_pkt *req);
+
+/**
+ * @brief Prepare Announce message.
+ *
+ * @param port gPTP port number.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_announce(int port);
+
+/**
+ * @brief Prepare Path Delay Response message.
+ *
+ * @param port gPTP port number.
+ * @param resp Related Path Delay Follow Up.
+ *
+ * @return Pointer to the prepared Network Buffer.
+ */
+struct net_pkt *gptp_prepare_pdelay_follow_up(int port,
+		struct net_pkt *resp);
+
+/* Functions to handle received messages. */
+
+/**
+ * @brief Handle Sync message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer.
+ */
+void gptp_handle_sync(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Handle Follow Up message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer to parse.
+ *
+ * @return 0 if success, Error Code otherwise.
+ */
+int gptp_handle_follow_up(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Handle Path Delay Request message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer.
+ */
+void gptp_handle_pdelay_req(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Handle Path Delay Response message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer to parse.
+ *
+ * @return 0 if success, Error Code otherwise.
+ */
+int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Handle Path Delay Follow Up message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer to parse.
+ *
+ * @return 0 if success, Error Code otherwise.
+ */
+int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Handle Signaling message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer
+ */
+void gptp_handle_signaling(int port, struct net_pkt *pkt);
+
+/* Functions to send messages. */
+
+/**
+ * @brief Send a Sync message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Sync message.
+ */
+void gptp_send_sync(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Send a Follow Up message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Follow Up message.
+ */
+void gptp_send_follow_up(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Send an Announce message.
+ *
+ * @param port gPTP port number.
+ * @param pkt Announce message.
+ */
+void gptp_send_announce(int port, struct net_pkt *pkt);
+
+/**
+ * @brief Send a Path Delay Request on the given port.
+ *
+ * @param port gPTP port number.
+ */
+void gptp_send_pdelay_req(int port);
+
+/**
+ * @brief Send a Path Delay Response for the given Path Delay Request.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer containing the prepared Path Delay Response.
+ * @param treq Time at which the Path Delay Request was received.
+ */
+void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
+			   struct net_ptp_time *treq);
+
+/**
+ * @brief Send a Path Delay Response for the given Path Delay Request.
+ *
+ * @param port gPTP port number.
+ * @param pkt Network Buffer containing the prepared Path Delay Follow Up.
+ * @param tresp Time at which the Path Delay Response was sent.
+ */
+void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
+				struct net_ptp_time *tresp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPTP_MESSAGES_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_messages.c	(working copy)
@@ -0,0 +1,951 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
+
+#include <net/net_if.h>
+
+#include "gptp_messages.h"
+#include "gptp_data_set.h"
+#include "gptp_md.h"
+#include "gptp_private.h"
+
+#define NET_BUF_TIMEOUT K_MSEC(100)
+
+static struct net_if_timestamp_cb sync_timestamp_cb;
+static struct net_if_timestamp_cb pdelay_response_timestamp_cb;
+static bool sync_cb_registered;
+static bool ts_cb_registered;
+
+static const struct net_eth_addr gptp_multicast_eth_addr = {
+	{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } };
+
+#define NET_GPTP_INFO(msg, pkt)						\
+	if (CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG) {		\
+		struct gptp_hdr *hdr = GPTP_HDR(pkt);			\
+									\
+		if (hdr->message_type == GPTP_ANNOUNCE_MESSAGE) {	\
+			struct gptp_announce *ann = GPTP_ANNOUNCE(pkt);	\
+			char output[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];	\
+									\
+			gptp_sprint_clock_id(				\
+				ann->root_system_id.grand_master_id,	\
+				output,					\
+				sizeof(output));			\
+									\
+			NET_DBG("Sending %s seq %d pkt %p",		\
+				msg,					\
+				ntohs(hdr->sequence_id), pkt);		\
+									\
+			NET_DBG("  GM %d/%d/0x%x/%d/%s",\
+				ann->root_system_id.grand_master_prio1, \
+				ann->root_system_id.clk_quality.clock_class, \
+				ann->root_system_id.clk_quality.clock_accuracy,\
+				ann->root_system_id.grand_master_prio2,	\
+				log_strdup(output));			\
+		} else {						\
+			NET_DBG("Sending %s seq %d pkt %p",		\
+				msg,					\
+				ntohs(hdr->sequence_id), pkt);		\
+		}							\
+	}
+
+struct gptp_hdr *gptp_get_hdr(struct net_pkt *pkt)
+{
+	struct net_buf *buf = pkt->frags;
+
+	NET_ASSERT(buf);
+
+	if (sizeof(struct gptp_hdr) <= buf->len) {
+		return (struct gptp_hdr *)buf->data;
+	}
+
+	/* Check if there is a link layer buf in the front and skip it
+	 * if needed.
+	 */
+	buf = buf->frags;
+	if (!buf) {
+		/* Do not return null here but let the caller failure
+		 * checks to fail the packet.
+		 */
+		return (struct gptp_hdr *)pkt->frags->data;
+	}
+
+	return (struct gptp_hdr *)buf->data;
+}
+
+static void gptp_sync_timestamp_callback(struct net_pkt *pkt)
+{
+	int port = 0;
+	struct gptp_sync_send_state *state;
+	struct gptp_hdr *hdr;
+
+	port = gptp_get_port_number(net_pkt_iface(pkt));
+	if (port == -ENODEV) {
+		NET_DBG("No port found for ptp buffer");
+		return;
+	}
+
+	state = &GPTP_PORT_STATE(port)->sync_send;
+
+	hdr = GPTP_HDR(pkt);
+
+	/* If this buffer is a sync, flag it to the state machine. */
+	if (hdr->message_type == GPTP_SYNC_MESSAGE) {
+		state->md_sync_timestamp_avail = true;
+
+		net_if_unregister_timestamp_cb(&sync_timestamp_cb);
+		sync_cb_registered = false;
+
+		/* The pkt was ref'ed in gptp_send_sync() */
+		net_pkt_unref(pkt);
+	}
+}
+
+static void gptp_pdelay_response_timestamp_callback(struct net_pkt *pkt)
+{
+	int port = 0;
+	struct net_pkt *follow_up;
+	struct gptp_hdr *hdr;
+
+	port = gptp_get_port_number(net_pkt_iface(pkt));
+	if (port == -ENODEV) {
+		NET_DBG("No port found for ptp buffer");
+		goto out;
+	}
+
+	hdr = GPTP_HDR(pkt);
+
+	/* If this buffer is a path delay response, send the follow up. */
+	if (hdr->message_type == GPTP_PATH_DELAY_RESP_MESSAGE) {
+		follow_up = gptp_prepare_pdelay_follow_up(port, pkt);
+		if (!follow_up) {
+			/* Cannot handle the follow up, abort */
+			NET_ERR("Could not get buffer");
+			goto out;
+		}
+
+		net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb);
+		ts_cb_registered = false;
+
+		gptp_send_pdelay_follow_up(port, follow_up,
+					   net_pkt_timestamp(pkt));
+
+out:
+		/* The pkt was ref'ed in gptp_handle_pdelay_req() */
+		net_pkt_unref(pkt);
+	}
+}
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+static struct net_pkt *setup_gptp_frame_debug(struct net_if *iface,
+					      size_t extra_header,
+					      const char *caller,
+					      int line)
+#define setup_gptp_frame(iface, extra_header)				\
+	setup_gptp_frame_debug(iface, extra_header, __func__, __LINE__)
+#else
+static struct net_pkt *setup_gptp_frame(struct net_if *iface,
+					size_t extra_header)
+#endif
+{
+	struct net_pkt *pkt;
+
+#if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
+	pkt = net_pkt_alloc_with_buffer_debug(iface, sizeof(struct gptp_hdr) +
+					      extra_header, AF_UNSPEC, 0,
+					      NET_BUF_TIMEOUT, caller, line);
+#else
+	pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct gptp_hdr) +
+					extra_header, AF_UNSPEC, 0,
+					NET_BUF_TIMEOUT);
+#endif
+	if (!pkt) {
+		return NULL;
+	}
+
+	net_buf_add(pkt->buffer, sizeof(struct gptp_hdr) + extra_header);
+	net_pkt_set_gptp(pkt, true);
+
+	net_pkt_lladdr_src(pkt)->addr = net_if_get_link_addr(iface)->addr;
+	net_pkt_lladdr_src(pkt)->len = net_if_get_link_addr(iface)->len;
+
+	net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)&gptp_multicast_eth_addr;
+	net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_sync(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_sync *sync;
+	struct net_if *iface;
+	struct net_pkt *pkt;
+	struct gptp_hdr *hdr;
+
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+	iface = GPTP_PORT_IFACE(port);
+	NET_ASSERT(iface);
+
+	pkt = setup_gptp_frame(iface, sizeof(struct gptp_sync));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_CA);
+
+	port_ds = GPTP_PORT_DS(port);
+	sync = GPTP_SYNC(pkt);
+	hdr = GPTP_HDR(pkt);
+
+	/*
+	 * Header configuration.
+	 *
+	 * Some fields are set by gptp_md_sync_send_prepare().
+	 */
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->message_type = GPTP_SYNC_MESSAGE;
+	hdr->ptp_version = GPTP_VERSION;
+	hdr->sequence_id = htons(port_ds->sync_seq_id);
+	hdr->domain_number = 0U;
+	hdr->correction_field = 0;
+	hdr->flags.octets[0] = GPTP_FLAG_TWO_STEP;
+	hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_sync));
+	hdr->control = GPTP_SYNC_CONTROL_VALUE;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	/* PTP configuration. */
+	(void)memset(&sync->reserved, 0, sizeof(sync->reserved));
+
+	/* Update sequence number. */
+	port_ds->sync_seq_id++;
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync)
+{
+	struct gptp_hdr *hdr, *sync_hdr;
+	struct gptp_port_ds *port_ds;
+	struct net_if *iface;
+	struct net_pkt *pkt;
+
+	NET_ASSERT(sync);
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+	iface = GPTP_PORT_IFACE(port);
+	NET_ASSERT(iface);
+
+	pkt = setup_gptp_frame(iface, sizeof(struct gptp_follow_up));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_IC);
+
+	port_ds = GPTP_PORT_DS(port);
+	hdr = GPTP_HDR(pkt);
+	sync_hdr = GPTP_HDR(sync);
+
+	/*
+	 * Header configuration.
+	 *
+	 * Some fields are set by gptp_md_follow_up_prepare().
+	 */
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->message_type = GPTP_FOLLOWUP_MESSAGE;
+	hdr->ptp_version = GPTP_VERSION;
+	hdr->sequence_id = sync_hdr->sequence_id;
+	hdr->domain_number = 0U;
+	/* Store timestamp value in correction field. */
+	hdr->correction_field = gptp_timestamp_to_nsec(&sync->timestamp);
+	hdr->flags.octets[0] = 0U;
+	hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_follow_up));
+	hdr->control = GPTP_FUP_CONTROL_VALUE;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	/* PTP configuration will be set by the MDSyncSend state machine. */
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_pdelay_req(int port)
+{
+	struct gptp_pdelay_req *req;
+	struct gptp_port_ds *port_ds;
+	struct net_if *iface;
+	struct net_pkt *pkt;
+	struct gptp_hdr *hdr;
+
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+	iface = GPTP_PORT_IFACE(port);
+	NET_ASSERT(iface);
+
+	pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_req));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_CA);
+
+	port_ds = GPTP_PORT_DS(port);
+	req = GPTP_PDELAY_REQ(pkt);
+	hdr = GPTP_HDR(pkt);
+
+	/* Header configuration. */
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->message_type = GPTP_PATH_DELAY_REQ_MESSAGE;
+	hdr->ptp_version = GPTP_VERSION;
+	hdr->sequence_id = htons(port_ds->pdelay_req_seq_id);
+	hdr->domain_number = 0U;
+	hdr->correction_field = 0;
+	hdr->flags.octets[0] = 0U;
+	hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
+
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_pdelay_req));
+	hdr->port_id.port_number = htons(port_ds->port_id.port_number);
+	hdr->control = GPTP_OTHER_CONTROL_VALUE;
+	hdr->log_msg_interval = port_ds->cur_log_pdelay_req_itv;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	memcpy(hdr->port_id.clk_id,
+	       port_ds->port_id.clk_id, GPTP_CLOCK_ID_LEN);
+
+	/* PTP configuration. */
+	(void)memset(&req->reserved1, 0, sizeof(req->reserved1));
+	(void)memset(&req->reserved2, 0, sizeof(req->reserved2));
+
+	/* Update sequence number. */
+	port_ds->pdelay_req_seq_id++;
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_pdelay_resp(int port,
+					 struct net_pkt *req)
+{
+	struct net_if *iface = net_pkt_iface(req);
+	struct gptp_pdelay_resp *pdelay_resp;
+	struct gptp_pdelay_req *pdelay_req;
+	struct gptp_hdr *hdr, *query;
+	struct gptp_port_ds *port_ds;
+	struct net_pkt *pkt;
+
+	pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_resp));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_CA);
+
+	port_ds = GPTP_PORT_DS(port);
+
+	pdelay_resp = GPTP_PDELAY_RESP(pkt);
+	hdr = GPTP_HDR(pkt);
+
+	pdelay_req = GPTP_PDELAY_REQ(req);
+	query = GPTP_HDR(req);
+
+	/* Header configuration. */
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->message_type = GPTP_PATH_DELAY_RESP_MESSAGE;
+	hdr->ptp_version = GPTP_VERSION;
+	hdr->sequence_id = query->sequence_id;
+	hdr->domain_number = query->domain_number;
+	hdr->correction_field = query->correction_field;
+	hdr->flags.octets[0] = GPTP_FLAG_TWO_STEP;
+	hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
+
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_pdelay_resp));
+	hdr->port_id.port_number = htons(port_ds->port_id.port_number);
+	hdr->control = GPTP_OTHER_CONTROL_VALUE;
+	hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	/* PTP configuration. */
+	pdelay_resp->req_receipt_ts_secs_high = 0U;
+	pdelay_resp->req_receipt_ts_secs_low = 0U;
+	pdelay_resp->req_receipt_ts_nsecs = 0U;
+
+	memcpy(&pdelay_resp->requesting_port_id,
+	       &query->port_id, sizeof(struct gptp_port_identity));
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_pdelay_follow_up(int port,
+					      struct net_pkt *resp)
+{
+	struct net_if *iface = net_pkt_iface(resp);
+	struct gptp_pdelay_resp_follow_up *follow_up;
+	struct gptp_pdelay_resp *pdelay_resp;
+	struct gptp_hdr *hdr, *resp_hdr;
+	struct gptp_port_ds *port_ds;
+	struct net_pkt *pkt;
+
+	pkt = setup_gptp_frame(iface,
+			       sizeof(struct gptp_pdelay_resp_follow_up));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_IC);
+
+	port_ds = GPTP_PORT_DS(port);
+
+	follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
+	hdr = GPTP_HDR(pkt);
+
+	pdelay_resp = GPTP_PDELAY_RESP(resp);
+	resp_hdr = GPTP_HDR(resp);
+
+	/* Header configuration. */
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->ptp_version = GPTP_VERSION;
+	hdr->message_type = GPTP_PATH_DELAY_FOLLOWUP_MESSAGE;
+	hdr->sequence_id = resp_hdr->sequence_id;
+	hdr->domain_number = resp_hdr->domain_number;
+	hdr->correction_field = 0;
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_pdelay_resp_follow_up));
+	hdr->port_id.port_number = htons(port_ds->port_id.port_number);
+	hdr->control = GPTP_OTHER_CONTROL_VALUE;
+	hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
+
+	hdr->flags.octets[0] = 0U;
+	hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	/* PTP configuration. */
+	follow_up->resp_orig_ts_secs_high = 0U;
+	follow_up->resp_orig_ts_secs_low = 0U;
+	follow_up->resp_orig_ts_nsecs = 0U;
+
+	memcpy(&follow_up->requesting_port_id,
+	       &pdelay_resp->requesting_port_id,
+	       sizeof(struct gptp_port_identity));
+
+	return pkt;
+}
+
+struct net_pkt *gptp_prepare_announce(int port)
+{
+	struct gptp_global_ds *global_ds;
+	struct gptp_default_ds *default_ds;
+	struct gptp_port_ds *port_ds;
+	struct gptp_announce *ann;
+	struct net_if *iface;
+	struct net_pkt *pkt;
+	struct gptp_hdr *hdr;
+
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+	global_ds = GPTP_GLOBAL_DS();
+	default_ds = GPTP_DEFAULT_DS();
+	iface = GPTP_PORT_IFACE(port);
+	NET_ASSERT(iface);
+
+	pkt = setup_gptp_frame(iface, sizeof(struct gptp_announce) - 8 +
+			       ntohs(global_ds->path_trace.len));
+	if (!pkt) {
+		NET_DBG("Cannot get gPTP frame");
+		return NULL;
+	}
+
+	net_pkt_set_priority(pkt, NET_PRIORITY_IC);
+
+	hdr = GPTP_HDR(pkt);
+	ann = GPTP_ANNOUNCE(pkt);
+	port_ds = GPTP_PORT_DS(port);
+
+	hdr->message_type = GPTP_ANNOUNCE_MESSAGE;
+	hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
+	hdr->ptp_version = GPTP_VERSION;
+
+	hdr->domain_number = 0U;
+	hdr->correction_field = 0;
+	hdr->flags.octets[0] = 0U;
+
+	/* Copy leap61, leap59, current UTC offset valid, time traceable and
+	 * frequency traceable flags.
+	 */
+	hdr->flags.octets[1] =
+		global_ds->global_flags.octets[1] | GPTP_FLAG_PTP_TIMESCALE;
+
+	memcpy(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	hdr->port_id.port_number = htons(port);
+	hdr->control = GPTP_OTHER_CONTROL_VALUE;
+	hdr->log_msg_interval = port_ds->cur_log_announce_itv;
+
+	/* Clear reserved fields. */
+	hdr->reserved0 = 0U;
+	hdr->reserved1 = 0U;
+	hdr->reserved2 = 0U;
+
+	ann->cur_utc_offset = global_ds->current_utc_offset;
+	ann->time_source = global_ds->time_source;
+
+	switch (GPTP_PORT_BMCA_DATA(port)->info_is) {
+	case GPTP_INFO_IS_MINE:
+		ann->root_system_id.grand_master_prio1 = default_ds->priority1;
+		ann->root_system_id.grand_master_prio2 = default_ds->priority2;
+
+		memcpy(&ann->root_system_id.clk_quality,
+		       &default_ds->clk_quality,
+		       sizeof(struct gptp_clock_quality));
+
+		memcpy(&ann->root_system_id.grand_master_id,
+		       default_ds->clk_id,
+		       GPTP_CLOCK_ID_LEN);
+		break;
+	case GPTP_INFO_IS_RECEIVED:
+		memcpy(&ann->root_system_id,
+		       &GPTP_PORT_BMCA_DATA(port)->
+				master_priority.root_system_id,
+		       sizeof(struct gptp_root_system_identity));
+		break;
+	default:
+		goto fail;
+	}
+
+	ann->steps_removed = global_ds->master_steps_removed;
+	hdr->sequence_id = htons(port_ds->announce_seq_id);
+	port_ds->announce_seq_id++;
+
+	ann->tlv.type = GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE;
+
+	/* Clear reserved fields. */
+	(void)memset(ann->reserved1, 0, sizeof(ann->reserved1));
+	ann->reserved2 = 0U;
+
+	hdr->message_length = htons(sizeof(struct gptp_hdr) +
+				    sizeof(struct gptp_announce) - 8 +
+				    ntohs(global_ds->path_trace.len));
+
+	ann->tlv.len = global_ds->path_trace.len;
+
+	net_pkt_cursor_init(pkt);
+
+	/* setup_gptp_frame() already added all the length, so let's not
+	 * add up more with net_pkt_skip/write_new(), let's just overwrite
+	 */
+	net_pkt_set_overwrite(pkt, true);
+
+	if (net_pkt_skip(pkt, sizeof(struct gptp_hdr) +
+			 sizeof(struct gptp_announce) - 8) ||
+	    net_pkt_write(pkt, &global_ds->path_trace.path_sequence[0][0],
+			  ntohs(global_ds->path_trace.len))) {
+		goto fail;
+	}
+
+	net_pkt_set_overwrite(pkt, false);
+
+	return pkt;
+
+fail:
+	net_pkt_unref(pkt);
+
+	return NULL;
+}
+
+void gptp_handle_sync(int port, struct net_pkt *pkt)
+{
+	struct gptp_sync_rcv_state *state;
+	struct gptp_port_ds *port_ds;
+	struct gptp_hdr *hdr;
+	uint64_t upstream_sync_itv;
+	k_timeout_t duration;
+
+	state = &GPTP_PORT_STATE(port)->sync_rcv;
+	port_ds = GPTP_PORT_DS(port);
+	hdr = GPTP_HDR(state->rcvd_sync_ptr);
+
+	upstream_sync_itv = NSEC_PER_SEC * GPTP_POW2(hdr->log_msg_interval);
+
+	/* Convert ns to ms. */
+	duration = K_MSEC((upstream_sync_itv / 1000000U));
+
+	/* Start timeout timer. */
+	k_timer_start(&state->follow_up_discard_timer, duration, K_NO_WAIT);
+}
+
+int gptp_handle_follow_up(int port, struct net_pkt *pkt)
+{
+	struct gptp_sync_rcv_state *state;
+	struct gptp_hdr *sync_hdr, *hdr;
+	struct gptp_port_ds *port_ds;
+
+	state = &GPTP_PORT_STATE(port)->sync_rcv;
+	port_ds = GPTP_PORT_DS(port);
+
+	sync_hdr = GPTP_HDR(state->rcvd_sync_ptr);
+	hdr = GPTP_HDR(pkt);
+
+	if (sync_hdr->sequence_id != hdr->sequence_id) {
+		NET_WARN("%s sequence id %d %s %s %d",
+			 "FOLLOWUP", ntohs(hdr->sequence_id),
+			 "does not match",
+			 "SYNC", ntohs(sync_hdr->sequence_id));
+		return -EINVAL;
+	}
+
+	GPTP_STATS_INC(port, rx_fup_count);
+
+	return 0;
+}
+
+void gptp_handle_pdelay_req(int port, struct net_pkt *pkt)
+{
+	struct net_pkt *reply;
+
+	GPTP_STATS_INC(port, rx_pdelay_req_count);
+
+	if (ts_cb_registered == true) {
+		NET_WARN("Multiple pdelay requests");
+
+		net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb);
+		net_pkt_unref(pdelay_response_timestamp_cb.pkt);
+
+		ts_cb_registered = false;
+	}
+
+	/* Prepare response and send */
+	reply = gptp_prepare_pdelay_resp(port, pkt);
+	if (!reply) {
+		return;
+	}
+
+	net_if_register_timestamp_cb(&pdelay_response_timestamp_cb,
+				     reply,
+				     net_pkt_iface(pkt),
+				     gptp_pdelay_response_timestamp_callback);
+
+	/* TS thread will send this back to us so increment ref count so that
+	 * the packet is not removed when sending it. This will be unref'ed by
+	 * timestamp callback in gptp_pdelay_response_timestamp_callback()
+	 */
+	net_pkt_ref(reply);
+
+	ts_cb_registered = true;
+
+	gptp_send_pdelay_resp(port, reply, net_pkt_timestamp(pkt));
+}
+
+int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_default_ds *default_ds;
+	struct gptp_pdelay_resp *resp;
+	struct gptp_port_ds *port_ds;
+	struct net_eth_hdr *eth;
+	struct gptp_hdr *hdr, *req_hdr;
+
+	eth = NET_ETH_HDR(pkt);
+	hdr = GPTP_HDR(pkt);
+	resp = GPTP_PDELAY_RESP(pkt);
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+	default_ds = GPTP_DEFAULT_DS();
+
+	if (!state->tx_pdelay_req_ptr) {
+		goto reset;
+	}
+
+	req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
+
+	/* Check clock identity. */
+	if (memcmp(default_ds->clk_id, resp->requesting_port_id.clk_id,
+		   GPTP_CLOCK_ID_LEN)) {
+		NET_WARN("Requesting Clock Identity %s", "does not match");
+		goto reset;
+	}
+	if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
+		   GPTP_CLOCK_ID_LEN) == 0) {
+		NET_WARN("Source Clock Identity is local Clock Identity");
+		goto reset;
+	}
+
+	/* Check port number. */
+	if (resp->requesting_port_id.port_number != htons(port)) {
+		NET_WARN("Requesting Port Number %s", "does not match");
+		goto reset;
+	}
+
+	/* Check sequence id. */
+	if (hdr->sequence_id != req_hdr->sequence_id) {
+		NET_WARN("Sequence Id %d %s %d",
+			 ntohs(hdr->sequence_id),
+			 "does not match",
+			 ntohs(req_hdr->sequence_id));
+		goto reset;
+	}
+
+	GPTP_STATS_INC(port, rx_pdelay_resp_count);
+
+	return 0;
+
+reset:
+	return -EINVAL;
+}
+
+int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt)
+{
+	struct gptp_pdelay_resp_follow_up *follow_up;
+	struct gptp_hdr *hdr, *req_hdr, *resp_hdr;
+	struct gptp_pdelay_req_state *state;
+	struct gptp_default_ds *default_ds;
+	struct gptp_port_ds *port_ds;
+	struct net_eth_hdr *eth;
+
+	eth = NET_ETH_HDR(pkt);
+	hdr = GPTP_HDR(pkt);
+	follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+	default_ds = GPTP_DEFAULT_DS();
+
+	if (!state->tx_pdelay_req_ptr) {
+		goto reset;
+	}
+
+	req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
+
+	if (!state->rcvd_pdelay_resp_ptr) {
+		goto reset;
+	}
+
+	resp_hdr = GPTP_HDR(state->rcvd_pdelay_resp_ptr);
+
+	/* Check clock identity. */
+	if (memcmp(default_ds->clk_id, follow_up->requesting_port_id.clk_id,
+		   GPTP_CLOCK_ID_LEN)) {
+		NET_WARN("Requesting Clock Identity %s", "does not match");
+		goto reset;
+	}
+
+	if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
+		   GPTP_CLOCK_ID_LEN) == 0) {
+		NET_WARN("Source Clock Identity is local Clock Identity");
+		goto reset;
+	}
+
+	/* Check port number. */
+	if (follow_up->requesting_port_id.port_number != htons(port)) {
+		NET_WARN("Requesting Port Number %s", "does not match");
+		goto reset;
+	}
+
+	/* Check sequence id. */
+	if (hdr->sequence_id != req_hdr->sequence_id) {
+		NET_WARN("Sequence Id %d %s %d",
+			 ntohs(hdr->sequence_id),
+			 "does not match",
+			 ntohs(req_hdr->sequence_id));
+		goto reset;
+	}
+
+	/* Check source port. */
+	if (memcmp(&hdr->port_id, &resp_hdr->port_id,
+		   sizeof(hdr->port_id)) != 0) {
+		NET_WARN("pDelay response and follow up port IDs %s",
+			"does not match");
+		goto reset;
+	}
+
+	GPTP_STATS_INC(port, rx_fup_count);
+
+	return 0;
+
+reset:
+	return -EINVAL;
+}
+
+void gptp_handle_signaling(int port, struct net_pkt *pkt)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_signaling *sig;
+
+	sig = GPTP_SIGNALING(pkt);
+	port_ds = GPTP_PORT_DS(port);
+
+	/* If time-synchronization not enabled, drop packet. */
+	if (!port_ds->ptt_port_enabled) {
+		return;
+	}
+
+	/* pDelay interval. */
+	gptp_update_pdelay_req_interval(port, sig->tlv.link_delay_itv);
+
+	/* Sync interval. */
+	gptp_update_sync_interval(port, sig->tlv.time_sync_itv);
+
+	/* Announce interval. */
+	gptp_update_announce_interval(port, sig->tlv.announce_itv);
+
+	port_ds->compute_neighbor_rate_ratio =
+		sig->tlv.compute_neighbor_rate_ratio;
+	port_ds->compute_neighbor_prop_delay =
+		sig->tlv.compute_neighbor_prop_delay;
+}
+
+void gptp_send_sync(int port, struct net_pkt *pkt)
+{
+	if (!sync_cb_registered) {
+		net_if_register_timestamp_cb(&sync_timestamp_cb,
+					     pkt,
+					     net_pkt_iface(pkt),
+					     gptp_sync_timestamp_callback);
+		sync_cb_registered = true;
+	}
+
+	GPTP_STATS_INC(port, tx_sync_count);
+
+	/* TS thread will send this back to us so increment ref count
+	 * so that the packet is not removed when sending it.
+	 * This will be unref'ed by timestamp callback in
+	 * gptp_sync_timestamp_callback()
+	 */
+	net_pkt_ref(pkt);
+
+	NET_GPTP_INFO("SYNC", pkt);
+
+	net_if_queue_tx(net_pkt_iface(pkt), pkt);
+}
+
+void gptp_send_follow_up(int port, struct net_pkt *pkt)
+{
+	GPTP_STATS_INC(port, tx_fup_count);
+
+	NET_GPTP_INFO("FOLLOWUP", pkt);
+
+	net_if_queue_tx(net_pkt_iface(pkt), pkt);
+}
+
+void gptp_send_announce(int port, struct net_pkt *pkt)
+{
+	GPTP_STATS_INC(port, tx_announce_count);
+
+	NET_GPTP_INFO("ANNOUNCE", pkt);
+
+	net_if_queue_tx(net_pkt_iface(pkt), pkt);
+}
+
+void gptp_send_pdelay_req(int port)
+{
+	struct gptp_pdelay_req_state *state;
+	struct gptp_port_ds *port_ds;
+	struct net_pkt *pkt;
+
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+	state = &GPTP_PORT_STATE(port)->pdelay_req;
+	port_ds = GPTP_PORT_DS(port);
+
+	pkt = gptp_prepare_pdelay_req(port);
+	if (pkt) {
+		if (state->tx_pdelay_req_ptr) {
+			NET_DBG("Unref pending %s %p", "PDELAY_REQ",
+				state->tx_pdelay_req_ptr);
+
+			net_pkt_unref(state->tx_pdelay_req_ptr);
+		}
+
+		/* Keep the buffer alive until pdelay_rate_ratio is computed. */
+		state->tx_pdelay_req_ptr = net_pkt_ref(pkt);
+
+		GPTP_STATS_INC(port, tx_pdelay_req_count);
+
+		NET_GPTP_INFO("PDELAY_REQ", pkt);
+
+		net_if_queue_tx(net_pkt_iface(pkt), pkt);
+	} else {
+		NET_ERR("Failed to prepare %s", "PDELAY_REQ");
+	}
+}
+
+void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
+			   struct net_ptp_time *treq)
+{
+	struct gptp_pdelay_resp *resp;
+	struct gptp_hdr *hdr;
+
+	hdr = GPTP_HDR(pkt);
+
+	/* No Fractional nsec .*/
+	hdr->correction_field = 0;
+
+	resp = GPTP_PDELAY_RESP(pkt);
+	resp->req_receipt_ts_secs_high = htons(treq->_sec.high);
+	resp->req_receipt_ts_secs_low = htonl(treq->_sec.low);
+	resp->req_receipt_ts_nsecs = htonl(treq->nanosecond);
+
+	GPTP_STATS_INC(port, tx_pdelay_resp_count);
+
+	NET_GPTP_INFO("PDELAY_RESP", pkt);
+
+	net_if_queue_tx(net_pkt_iface(pkt), pkt);
+}
+
+void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
+				struct net_ptp_time *tresp)
+{
+	struct gptp_pdelay_resp_follow_up *follow_up;
+	struct gptp_hdr *hdr;
+
+	hdr = GPTP_HDR(pkt);
+
+	/* No Fractional nsec .*/
+	hdr->correction_field = 0;
+
+	follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
+	follow_up->resp_orig_ts_secs_high = htons(tresp->_sec.high);
+	follow_up->resp_orig_ts_secs_low = htonl(tresp->_sec.low);
+	follow_up->resp_orig_ts_nsecs = htonl(tresp->nanosecond);
+
+	GPTP_STATS_INC(port, tx_pdelay_resp_fup_count);
+
+	NET_GPTP_INFO("PDELAY_FOLLOWUP", pkt);
+
+	net_if_queue_tx(net_pkt_iface(pkt), pkt);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.h	(working copy)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief GPTP Media Independent interface
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_MI_H
+#define __GPTP_MI_H
+
+#include "gptp_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Media Independent Sync Information.
+ *
+ * This structure applies for MDSyncReceive as well as MDSyncSend.
+ */
+struct gptp_mi_port_sync_sync {
+	/** Time at which the sync receipt timeout occurs. */
+	uint64_t sync_receipt_timeout_time;
+
+	/** Copy of the gptp_md_sync_info to be transmitted. */
+	struct gptp_md_sync_info sync_info;
+
+	/** Port to which the Sync Information belongs to. */
+	uint16_t local_port_number;
+};
+
+/**
+ * @brief Initialize all Media Independent State Machines.
+ */
+void gptp_mi_init_state_machine(void);
+
+/**
+ * @brief Run all Media Independent Port Sync State Machines.
+ *
+ * @param port Number of the port the State Machines needs to be run on.
+ */
+void gptp_mi_port_sync_state_machines(int port);
+
+/**
+ * @brief Run all Media Independent Port BMCA State Machines.
+ *
+ * @param port Number of the port the State Machines needs to be run on.
+ */
+void gptp_mi_port_bmca_state_machines(int port);
+
+/**
+ * @brief Run all Media Independent State Machines.
+ */
+void gptp_mi_state_machines(void);
+
+/**
+ * @brief Return current time in nanoseconds.
+ *
+ * @param port Port number of the clock to use.
+ *
+ * @return Current time in nanoseconds.
+ */
+uint64_t gptp_get_current_time_nanosecond(int port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPTP_MI_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_mi.c	(working copy)
@@ -0,0 +1,2019 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
+
+#include <ptp_clock.h>
+
+#include "gptp_messages.h"
+#include "gptp_data_set.h"
+#include "gptp_state.h"
+#include "gptp_private.h"
+
+#if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
+static const char * const state2str(enum gptp_port_state state)
+{
+	switch (state) {
+	case GPTP_PORT_INITIALIZING:
+		return "INITIALIZING";
+	case GPTP_PORT_FAULTY:
+		return "FAULTY";
+	case GPTP_PORT_DISABLED:
+		return "DISABLED";
+	case GPTP_PORT_LISTENING:
+		return "LISTENING";
+	case GPTP_PORT_PRE_MASTER:
+		return "PRE_MASTER";
+	case GPTP_PORT_MASTER:
+		return "MASTER";
+	case GPTP_PORT_PASSIVE:
+		return "PASSIVE";
+	case GPTP_PORT_UNCALIBRATED:
+		return "UNCALIBRATED";
+	case GPTP_PORT_SLAVE:
+		return "SLAVE";
+	}
+
+	return "<unknown>";
+}
+
+static const char * const pa_info_state2str(enum gptp_pa_info_states state)
+{
+	switch (state) {
+	case GPTP_PA_INFO_DISABLED:
+		return "DISABLED";
+	case GPTP_PA_INFO_POST_DISABLED:
+		return "POST_DISABLED";
+	case GPTP_PA_INFO_AGED:
+		return "AGED";
+	case GPTP_PA_INFO_UPDATE:
+		return "UPDATE";
+	case GPTP_PA_INFO_CURRENT:
+		return "CURRENT";
+	case GPTP_PA_INFO_RECEIVE:
+		return "RECEIVE";
+	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
+		return "SUPERIOR_MASTER_PORT";
+	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
+		return "REPEATED_MASTER_PORT";
+	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
+		return "INFERIOR_MASTER_OR_OTHER_PORT";
+	}
+
+	return "<unknown>";
+}
+#endif
+
+#if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
+void gptp_change_port_state_debug(int port, enum gptp_port_state state,
+				  const char *caller,
+				  int line)
+#else
+void gptp_change_port_state(int port, enum gptp_port_state state)
+#endif
+{
+	struct gptp_global_ds *global_ds = GPTP_GLOBAL_DS();
+
+	if (global_ds->selected_role[port] == state) {
+		return;
+	}
+
+#if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("[%d] state %s -> %s (%s():%d)", port,
+		state2str(global_ds->selected_role[port]),
+		state2str(state), caller, line);
+#endif
+
+	global_ds->selected_role[port] = state;
+};
+
+#if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
+void gptp_change_pa_info_state_debug(
+	int port,
+	struct gptp_port_announce_information_state *pa_info_state,
+	enum gptp_pa_info_states state,
+	const char *caller,
+	int line)
+#else
+void gptp_change_pa_info_state(
+	int port,
+	struct gptp_port_announce_information_state *pa_info_state,
+	enum gptp_pa_info_states state)
+#endif
+{
+	if (pa_info_state->state == state) {
+		return;
+	}
+
+#if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("[%d] PA info state %s -> %s (%s():%d)", port,
+		pa_info_state2str(pa_info_state->state),
+		pa_info_state2str(state), caller, line);
+#endif
+
+	pa_info_state->state = state;
+}
+
+static void gptp_mi_half_sync_itv_timeout(struct k_timer *timer)
+{
+	struct gptp_pss_send_state *state;
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pss_send;
+		if (&state->half_sync_itv_timer == timer) {
+			if (!state->half_sync_itv_timer_expired) {
+				state->half_sync_itv_timer_expired = true;
+			} else {
+				/* We do not need the timer anymore. */
+				k_timer_stop(timer);
+
+				state->sync_itv_timer_expired = true;
+			}
+		}
+	}
+}
+
+static void gptp_mi_rcv_sync_receipt_timeout(struct k_timer *timer)
+{
+	struct gptp_pss_rcv_state *state;
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pss_rcv;
+		if (&state->rcv_sync_receipt_timeout_timer == timer) {
+			state->rcv_sync_receipt_timeout_timer_expired = true;
+		}
+
+		GPTP_STATS_INC(port, sync_receipt_timeout_count);
+	}
+}
+
+static void gptp_mi_send_sync_receipt_timeout(struct k_timer *timer)
+{
+	struct gptp_pss_send_state *state;
+	int port;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pss_send;
+		if (&state->send_sync_receipt_timeout_timer == timer) {
+			state->send_sync_receipt_timeout_timer_expired = true;
+		}
+
+		GPTP_STATS_INC(port, sync_receipt_timeout_count);
+	}
+}
+
+static void gptp_mi_init_port_sync_sync_rcv_sm(int port)
+{
+	struct gptp_pss_rcv_state *pss_rcv;
+
+	pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
+	(void)memset(pss_rcv, 0, sizeof(struct gptp_pss_rcv_state));
+
+	k_timer_init(&pss_rcv->rcv_sync_receipt_timeout_timer,
+		     gptp_mi_rcv_sync_receipt_timeout, NULL);
+
+	pss_rcv->state = GPTP_PSS_RCV_DISCARD;
+}
+
+static void gptp_mi_init_port_sync_sync_send_sm(int port)
+{
+	struct gptp_pss_send_state *pss_send;
+
+	pss_send = &GPTP_PORT_STATE(port)->pss_send;
+	(void)memset(pss_send, 0, sizeof(struct gptp_pss_send_state));
+
+	k_timer_init(&pss_send->half_sync_itv_timer,
+		     gptp_mi_half_sync_itv_timeout, NULL);
+	k_timer_init(&pss_send->send_sync_receipt_timeout_timer,
+		     gptp_mi_send_sync_receipt_timeout, NULL);
+
+	pss_send->state = GPTP_PSS_SEND_TRANSMIT_INIT;
+}
+
+static void gptp_mi_init_site_sync_sync_sm(void)
+{
+	struct gptp_site_sync_sync_state *site_ss;
+
+	site_ss = &GPTP_STATE()->site_ss;
+	(void)memset(site_ss, 0, sizeof(struct gptp_site_sync_sync_state));
+	site_ss->state = GPTP_SSS_INITIALIZING;
+}
+
+static void gptp_mi_init_clock_slave_sync_sm(void)
+{
+	struct gptp_clk_slave_sync_state *clk_ss;
+
+	clk_ss = &GPTP_STATE()->clk_slave_sync;
+	(void)memset(clk_ss, 0, sizeof(struct gptp_clk_slave_sync_state));
+	clk_ss->state = GPTP_CLK_SLAVE_SYNC_INITIALIZING;
+}
+
+static void gptp_mi_init_port_announce_rcv_sm(int port)
+{
+	struct gptp_port_announce_receive_state *pa_rcv;
+
+	pa_rcv = &GPTP_PORT_STATE(port)->pa_rcv;
+	(void)memset(pa_rcv, 0,
+		     sizeof(struct gptp_port_announce_receive_state));
+	pa_rcv->state = GPTP_PA_RCV_DISCARD;
+}
+
+static void gptp_mi_init_clock_master_sync_rcv_sm(void)
+{
+	struct gptp_clk_master_sync_rcv_state *cms_rcv;
+
+	cms_rcv = &GPTP_STATE()->clk_master_sync_receive;
+	(void)memset(cms_rcv, 0, sizeof(struct gptp_clk_master_sync_rcv_state));
+	cms_rcv->state = GPTP_CMS_RCV_INITIALIZING;
+}
+
+static void announce_timer_handler(struct k_timer *timer)
+{
+	int port;
+	struct gptp_port_announce_information_state *state;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pa_info;
+		if (&state->ann_rcpt_expiry_timer == timer) {
+			state->ann_expired = true;
+			GPTP_STATS_INC(port, announce_receipt_timeout_count);
+			break;
+		}
+	}
+}
+
+static void gptp_mi_init_port_announce_info_sm(int port)
+{
+	struct gptp_port_announce_information_state *state;
+
+	state = &GPTP_PORT_STATE(port)->pa_info;
+
+	k_timer_init(&state->ann_rcpt_expiry_timer,
+		     announce_timer_handler, NULL);
+
+	state->ann_expired = false;
+	gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
+}
+
+static void gptp_mi_init_bmca_data(int port)
+{
+	struct gptp_port_bmca_data *bmca_data;
+
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+
+	(void)memset(bmca_data, 0, sizeof(struct gptp_port_bmca_data));
+
+	gptp_set_time_itv(&bmca_data->announce_interval, 1,
+			  CONFIG_NET_GPTP_INIT_LOG_ANNOUNCE_ITV);
+
+	(void)memset(&bmca_data->port_priority, 0xFF,
+		     sizeof(struct gptp_priority_vector));
+	(void)memset(&bmca_data->master_priority, 0xFF,
+		     sizeof(struct gptp_priority_vector));
+}
+
+static void announce_periodic_timer_handler(struct k_timer *timer)
+{
+	int port;
+	struct gptp_port_announce_transmit_state *state;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		state = &GPTP_PORT_STATE(port)->pa_transmit;
+		if (&state->ann_send_periodic_timer == timer) {
+			state->ann_trigger = true;
+			break;
+		}
+	}
+}
+
+static void gptp_mi_init_port_announce_transmit_sm(int port)
+{
+	struct gptp_port_announce_transmit_state *state;
+
+	state = &GPTP_PORT_STATE(port)->pa_transmit;
+
+	k_timer_init(&state->ann_send_periodic_timer,
+		     announce_periodic_timer_handler, NULL);
+
+	state->ann_trigger = false;
+	state->state = GPTP_PA_TRANSMIT_INIT;
+}
+
+static void gptp_mi_init_port_role_selection_sm(void)
+{
+	GPTP_STATE()->pr_sel.state = GPTP_PR_SELECTION_INIT_BRIDGE;
+}
+
+void gptp_mi_init_state_machine(void)
+{
+	int port;
+
+	for (port = GPTP_PORT_START;
+	     port < (GPTP_PORT_START + CONFIG_NET_GPTP_NUM_PORTS); port++) {
+		gptp_mi_init_port_sync_sync_rcv_sm(port);
+		gptp_mi_init_port_sync_sync_send_sm(port);
+		gptp_mi_init_port_announce_rcv_sm(port);
+		gptp_mi_init_port_announce_info_sm(port);
+		gptp_mi_init_port_announce_transmit_sm(port);
+		gptp_mi_init_bmca_data(port);
+	}
+
+	gptp_mi_init_site_sync_sync_sm();
+	gptp_mi_init_clock_slave_sync_sm();
+	gptp_mi_init_port_role_selection_sm();
+	gptp_mi_init_clock_master_sync_rcv_sm();
+}
+
+uint64_t gptp_get_current_time_nanosecond(int port)
+{
+	const struct device *clk;
+
+	clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
+	if (clk) {
+		struct net_ptp_time tm = {};
+
+		ptp_clock_get(clk, &tm);
+
+		if (tm.second == 0U && tm.nanosecond == 0U) {
+			goto use_uptime;
+		}
+
+		return gptp_timestamp_to_nsec(&tm);
+	}
+
+use_uptime:
+	/* A workaround if clock cannot be found. Note that accuracy is
+	 * only in milliseconds.
+	 */
+	return k_uptime_get() * 1000000;
+}
+
+uint64_t gptp_get_current_master_time_nanosecond(void)
+{
+	int port;
+	enum gptp_port_state *port_role;
+
+	port_role = GPTP_GLOBAL_DS()->selected_role;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		if (port_role[port] == GPTP_PORT_MASTER) {
+			return gptp_get_current_time_nanosecond(port);
+		}
+	}
+
+	/* No master */
+	return 0;
+}
+
+static void gptp_mi_pss_rcv_compute(int port)
+{
+	struct gptp_pss_rcv_state *state;
+	struct gptp_mi_port_sync_sync *pss;
+	struct gptp_md_sync_info *sync_rcv;
+	struct gptp_port_ds *port_ds;
+
+	state = &GPTP_PORT_STATE(port)->pss_rcv;
+	pss = &state->pss;
+	sync_rcv = &state->sync_rcv;
+	port_ds = GPTP_PORT_DS(port);
+
+	state->rate_ratio = sync_rcv->rate_ratio;
+	state->rate_ratio += (port_ds->neighbor_rate_ratio - 1.0);
+
+	port_ds->sync_receipt_timeout_time_itv = port_ds->sync_receipt_timeout;
+	port_ds->sync_receipt_timeout_time_itv *= NSEC_PER_SEC;
+	port_ds->sync_receipt_timeout_time_itv *=
+		GPTP_POW2(sync_rcv->log_msg_interval);
+
+	pss->local_port_number = port;
+
+	memcpy(&pss->sync_info, sync_rcv, sizeof(struct gptp_md_sync_info));
+
+	pss->sync_receipt_timeout_time = gptp_get_current_time_nanosecond(port);
+	pss->sync_receipt_timeout_time +=
+		port_ds->sync_receipt_timeout_time_itv;
+
+	pss->sync_info.rate_ratio = state->rate_ratio;
+}
+
+static void start_rcv_sync_timer(struct gptp_port_ds *port_ds,
+				 struct gptp_pss_rcv_state *state)
+{
+	k_timeout_t duration;
+
+	duration = K_MSEC(port_ds->sync_receipt_timeout_time_itv /
+			  (NSEC_PER_USEC * USEC_PER_MSEC));
+
+	k_timer_start(&state->rcv_sync_receipt_timeout_timer, duration,
+		      K_NO_WAIT);
+}
+
+static void gptp_mi_pss_rcv_state_machine(int port)
+{
+	struct gptp_pss_rcv_state *state;
+	struct gptp_site_sync_sync_state *site_ss_state;
+	struct gptp_port_ds *port_ds;
+
+	state = &GPTP_PORT_STATE(port)->pss_rcv;
+	site_ss_state = &GPTP_STATE()->site_ss;
+	port_ds = GPTP_PORT_DS(port);
+
+	if ((!port_ds->ptt_port_enabled) || !port_ds->as_capable) {
+		state->rcvd_md_sync = false;
+		state->state = GPTP_PSS_RCV_DISCARD;
+		return;
+	}
+
+	switch (state->state) {
+	case GPTP_PSS_RCV_DISCARD:
+		k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
+		state->rcv_sync_receipt_timeout_timer_expired = false;
+
+		__fallthrough;
+	case GPTP_PSS_RCV_RECEIVED_SYNC:
+		if (state->rcvd_md_sync) {
+			state->rcvd_md_sync = false;
+			gptp_mi_pss_rcv_compute(port);
+
+			state->state = GPTP_PSS_RCV_RECEIVED_SYNC;
+
+			site_ss_state->pss_rcv_ptr = &state->pss;
+			site_ss_state->rcvd_pss = true;
+
+			k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
+			state->rcv_sync_receipt_timeout_timer_expired = false;
+
+			if (GPTP_GLOBAL_DS()->gm_present) {
+				start_rcv_sync_timer(port_ds, state);
+			}
+		}
+
+		break;
+	}
+}
+
+static void gptp_mi_pss_store_last_pss(int port)
+{
+	struct gptp_pss_send_state *state;
+	struct gptp_mi_port_sync_sync *pss_ptr;
+	struct gptp_md_sync_info *sync_info;
+	struct gptp_port_ds *port_ds;
+
+	state = &GPTP_PORT_STATE(port)->pss_send;
+	port_ds = GPTP_PORT_DS(port);
+	pss_ptr = state->pss_sync_ptr;
+	sync_info = &pss_ptr->sync_info;
+
+	state->last_rcvd_port_num = pss_ptr->local_port_number;
+
+	memcpy(&state->last_precise_orig_ts, &sync_info->precise_orig_ts,
+	       sizeof(struct net_ptp_time));
+	memcpy(&state->last_gm_phase_change, &sync_info->last_gm_phase_change,
+	       sizeof(struct gptp_scaled_ns));
+
+	state->last_follow_up_correction_field =
+		sync_info->follow_up_correction_field;
+	state->last_rate_ratio = sync_info->rate_ratio;
+	state->last_upstream_tx_time = sync_info->upstream_tx_time;
+	state->last_gm_time_base_indicator = sync_info->gm_time_base_indicator;
+	state->last_gm_freq_change = sync_info->last_gm_freq_change;
+}
+
+static void gptp_mi_pss_send_md_sync_send(int port)
+{
+	struct gptp_pss_send_state *state;
+	struct gptp_mi_port_sync_sync *pss_ptr;
+	struct gptp_port_ds *port_ds;
+	struct gptp_sync_send_state *sync_send;
+
+	state = &GPTP_PORT_STATE(port)->pss_send;
+	port_ds = GPTP_PORT_DS(port);
+	pss_ptr = state->pss_sync_ptr;
+	sync_send = &GPTP_PORT_STATE(port)->sync_send;
+
+	memcpy(&state->sync_send, &pss_ptr->sync_info,
+	       sizeof(struct gptp_md_sync_info));
+
+	sync_send->sync_send_ptr = &state->sync_send;
+	sync_send->rcvd_md_sync = true;
+}
+
+static void gptp_mi_pss_send_state_machine(int port)
+{
+	struct gptp_pss_send_state *state;
+	struct gptp_port_ds *port_ds;
+	struct gptp_global_ds *global_ds;
+	k_timeout_t duration;
+
+	global_ds = GPTP_GLOBAL_DS();
+	state = &GPTP_PORT_STATE(port)->pss_send;
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Reset interval as defined in LinkDelaySyncIntervalSetting state
+	 * machine.
+	 */
+	if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
+		gptp_update_sync_interval(port, GPTP_ITV_SET_TO_INIT);
+	}
+
+	if (state->rcvd_pss_sync && ((!port_ds->ptt_port_enabled) ||
+				     !port_ds->as_capable)) {
+		state->rcvd_pss_sync = false;
+		state->state = GPTP_PSS_SEND_TRANSMIT_INIT;
+
+		return;
+	}
+
+	switch (state->state) {
+	case GPTP_PSS_SEND_TRANSMIT_INIT:
+	case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT:
+		if (state->rcvd_pss_sync &&
+		    (state->pss_sync_ptr->local_port_number != port) &&
+		    (global_ds->selected_role[port] == GPTP_PORT_MASTER)) {
+			state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
+		} else {
+			break;
+		}
+
+		__fallthrough;
+	case GPTP_PSS_SEND_SEND_MD_SYNC:
+		if (state->rcvd_pss_sync) {
+			gptp_mi_pss_store_last_pss(port);
+			state->rcvd_pss_sync = false;
+		}
+
+		/* Make sure no previous timer is still running. */
+		k_timer_stop(&state->half_sync_itv_timer);
+		k_timer_stop(&state->send_sync_receipt_timeout_timer);
+
+		state->half_sync_itv_timer_expired = false;
+		state->sync_itv_timer_expired = false;
+		state->send_sync_receipt_timeout_timer_expired = false;
+
+		/* Convert ns to ms. */
+		duration = K_MSEC(gptp_uscaled_ns_to_timer_ms(
+					  &port_ds->half_sync_itv));
+
+		/* Start 0.5 * syncInterval timeout timer. */
+		k_timer_start(&state->half_sync_itv_timer, duration,
+			      K_NO_WAIT);
+
+		gptp_mi_pss_send_md_sync_send(port);
+
+		__fallthrough;
+	case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
+		/* Test conditions have been slightly rearranged compared to
+		 * their definitions in the standard in order not to test
+		 * AsCapable and pttPortEnabled when not needed (they are
+		 * already tested with rcvdPSSync for the reset of this state
+		 * machine).
+		 */
+		if ((global_ds->selected_role[port] == GPTP_PORT_MASTER) &&
+		    ((state->rcvd_pss_sync &&
+		      state->half_sync_itv_timer_expired &&
+		      state->pss_sync_ptr->local_port_number != port) ||
+		     (state->sync_itv_timer_expired &&
+		      (state->last_rcvd_port_num != port) &&
+		      port_ds->as_capable && port_ds->ptt_port_enabled))) {
+
+			state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
+
+		} else if ((state->state == GPTP_PSS_SEND_SEND_MD_SYNC) ||
+			   (state->rcvd_pss_sync &&
+			    !state->sync_itv_timer_expired &&
+			    (global_ds->selected_role[port] ==
+							GPTP_PORT_MASTER) &&
+			    state->pss_sync_ptr->local_port_number != port)) {
+
+			/* Change state as it may have transitioned from
+			 * SEND_MD_SYNC.
+			 */
+			state->state = GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT;
+
+			/* Stop and (re)start receipt timeout timer. */
+			k_timer_stop(&state->send_sync_receipt_timeout_timer);
+			state->send_sync_receipt_timeout_timer_expired = false;
+
+			duration =
+				K_MSEC(port_ds->sync_receipt_timeout_time_itv /
+				       (NSEC_PER_USEC * USEC_PER_MSEC));
+
+			k_timer_start(&state->send_sync_receipt_timeout_timer,
+				      duration, K_NO_WAIT);
+
+		} else if (state->send_sync_receipt_timeout_timer_expired) {
+			state->state = GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT;
+		}
+
+		break;
+	}
+}
+
+static void gptp_mi_site_ss_prepare_pss_send(void)
+{
+	struct gptp_site_sync_sync_state *state;
+
+	state = &GPTP_STATE()->site_ss;
+
+	memcpy(&state->pss_send, state->pss_rcv_ptr,
+	       sizeof(struct gptp_mi_port_sync_sync));
+}
+
+static void gptp_mi_site_ss_send_to_pss(void)
+{
+	struct gptp_site_sync_sync_state *state;
+	struct gptp_pss_send_state *pss_send;
+	int port;
+
+	state = &GPTP_STATE()->site_ss;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		pss_send = &GPTP_PORT_STATE(port)->pss_send;
+		pss_send->pss_sync_ptr = &state->pss_send;
+		pss_send->rcvd_pss_sync = true;
+	}
+}
+
+static void gptp_mi_site_sync_sync_state_machine(void)
+{
+	bool gm_present;
+	uint16_t local_port_number;
+	struct gptp_site_sync_sync_state *state;
+	struct gptp_clk_slave_sync_state *clk_ss;
+
+	state = &GPTP_STATE()->site_ss;
+	clk_ss = &GPTP_STATE()->clk_slave_sync;
+	gm_present = GPTP_GLOBAL_DS()->gm_present;
+
+	if (!state->pss_rcv_ptr) {
+		/* We do not have connection to GM yet */
+		return;
+	}
+
+	local_port_number = state->pss_rcv_ptr->local_port_number;
+
+	switch (state->state) {
+	case GPTP_SSS_INITIALIZING:
+		state->rcvd_pss = false;
+		state->state = GPTP_SSS_RECEIVING_SYNC;
+		break;
+
+	case GPTP_SSS_RECEIVING_SYNC:
+		if (state->rcvd_pss) {
+			state->rcvd_pss = false;
+			if (gptp_is_slave_port(local_port_number) &&
+					gm_present) {
+				gptp_mi_site_ss_prepare_pss_send();
+
+				/*
+				 * Send Port Sync Sync to all
+				 * PortSyncSyncSend State Machines.
+				 */
+				gptp_mi_site_ss_send_to_pss();
+
+				/*
+				 * Send PortSyncSync to
+				 * ClockSlaveSync State Machine.
+				 */
+				clk_ss->pss_rcv_ptr = &state->pss_send;
+				clk_ss->rcvd_pss = true;
+			}
+		}
+
+		break;
+	}
+}
+
+static void gptp_mi_clk_slave_sync_compute(void)
+{
+	struct gptp_clk_slave_sync_state *state;
+	struct gptp_clk_master_sync_offset_state *offset_state;
+	struct gptp_global_ds *global_ds;
+	struct gptp_md_sync_info *pss;
+	struct gptp_port_ds *port_ds;
+	uint64_t sync_receipt_time;
+
+	state = &GPTP_STATE()->clk_slave_sync;
+	offset_state = &GPTP_STATE()->clk_master_sync_offset;
+	global_ds = GPTP_GLOBAL_DS();
+	port_ds = GPTP_PORT_DS(state->pss_rcv_ptr->local_port_number);
+
+	pss = &state->pss_rcv_ptr->sync_info;
+
+	sync_receipt_time = pss->rate_ratio;
+	sync_receipt_time /= port_ds->neighbor_rate_ratio;
+	sync_receipt_time *= port_ds->neighbor_prop_delay;
+	sync_receipt_time += pss->follow_up_correction_field;
+	sync_receipt_time += port_ds->delay_asymmetry;
+
+	global_ds->sync_receipt_time.second = sync_receipt_time / NSEC_PER_SEC;
+	global_ds->sync_receipt_time.fract_nsecond =
+		(sync_receipt_time % NSEC_PER_SEC) * GPTP_POW2_16;
+	global_ds->sync_receipt_time.second += pss->precise_orig_ts.second;
+	global_ds->sync_receipt_time.fract_nsecond +=
+		pss->precise_orig_ts.nanosecond * GPTP_POW2_16;
+
+	global_ds->sync_receipt_local_time = port_ds->delay_asymmetry;
+	global_ds->sync_receipt_local_time /= pss->rate_ratio;
+	global_ds->sync_receipt_local_time +=
+		(port_ds->neighbor_prop_delay / port_ds->neighbor_rate_ratio);
+	global_ds->sync_receipt_local_time += pss->upstream_tx_time;
+
+	global_ds->gm_time_base_indicator = pss->gm_time_base_indicator;
+	global_ds->last_gm_phase_change.high = pss->last_gm_phase_change.high;
+	global_ds->last_gm_phase_change.low = pss->last_gm_phase_change.low;
+	global_ds->last_gm_freq_change = pss->last_gm_freq_change;
+
+	offset_state->rcvd_sync_receipt_time = true;
+}
+
+#if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
+static void gptp_update_local_port_clock(void)
+{
+	struct gptp_clk_slave_sync_state *state;
+	struct gptp_global_ds *global_ds;
+	struct gptp_port_ds *port_ds;
+	int port;
+	int64_t nanosecond_diff;
+	int64_t second_diff;
+	const struct device *clk;
+	struct net_ptp_time tm;
+	int key;
+
+	state = &GPTP_STATE()->clk_slave_sync;
+	global_ds = GPTP_GLOBAL_DS();
+	port = state->pss_rcv_ptr->local_port_number;
+	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
+
+	port_ds = GPTP_PORT_DS(port);
+
+	/* Check if the last neighbor rate ratio can still be used */
+	if (!port_ds->neighbor_rate_ratio_valid) {
+		return;
+	}
+
+	port_ds->neighbor_rate_ratio_valid = false;
+
+	second_diff = global_ds->sync_receipt_time.second -
+		(global_ds->sync_receipt_local_time / NSEC_PER_SEC);
+	nanosecond_diff =
+		(global_ds->sync_receipt_time.fract_nsecond / GPTP_POW2_16) -
+		(global_ds->sync_receipt_local_time % NSEC_PER_SEC);
+
+	clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
+	if (!clk) {
+		return;
+	}
+
+	if (second_diff > 0 && nanosecond_diff < 0) {
+		second_diff--;
+		nanosecond_diff = NSEC_PER_SEC + nanosecond_diff;
+	}
+
+	if (second_diff < 0 && nanosecond_diff > 0) {
+		second_diff++;
+		nanosecond_diff = -NSEC_PER_SEC + nanosecond_diff;
+	}
+
+	ptp_clock_rate_adjust(clk, port_ds->neighbor_rate_ratio);
+
+	/* If time difference is too high, set the clock value.
+	 * Otherwise, adjust it.
+	 */
+	if (second_diff || (second_diff == 0 &&
+			    (nanosecond_diff < -5000 ||
+			     nanosecond_diff > 5000))) {
+		bool underflow = false;
+
+		key = irq_lock();
+		ptp_clock_get(clk, &tm);
+
+		if (second_diff < 0 && tm.second < -second_diff) {
+			NET_DBG("Do not set local clock because %lu < %ld",
+				(unsigned long int)tm.second,
+				(long int)-second_diff);
+			goto skip_clock_set;
+		}
+
+		tm.second += second_diff;
+
+		if (nanosecond_diff < 0 &&
+		    tm.nanosecond < -nanosecond_diff) {
+			underflow = true;
+		}
+
+		tm.nanosecond += nanosecond_diff;
+
+		if (underflow) {
+			tm.second--;
+			tm.nanosecond += NSEC_PER_SEC;
+		} else if (tm.nanosecond >= NSEC_PER_SEC) {
+			tm.second++;
+			tm.nanosecond -= NSEC_PER_SEC;
+		}
+
+		/* This prints too much data normally but can be enabled to see
+		 * what time we are setting to the local clock.
+		 */
+		if (0) {
+			NET_INFO("Set local clock %lu.%lu",
+				 (unsigned long int)tm.second,
+				 (unsigned long int)tm.nanosecond);
+		}
+
+		ptp_clock_set(clk, &tm);
+
+	skip_clock_set:
+		irq_unlock(key);
+	} else {
+		if (nanosecond_diff < -200) {
+			nanosecond_diff = -200;
+		} else if (nanosecond_diff > 200) {
+			nanosecond_diff = 200;
+		}
+
+		ptp_clock_adjust(clk, nanosecond_diff);
+	}
+}
+#endif /* CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE */
+
+static void gptp_mi_clk_slave_sync_state_machine(void)
+{
+	struct gptp_clk_slave_sync_state *state;
+
+	state = &GPTP_STATE()->clk_slave_sync;
+
+	switch (state->state) {
+	case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
+		state->rcvd_pss = false;
+		state->state = GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND;
+		break;
+
+	case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
+		if (state->rcvd_pss) {
+			state->rcvd_pss = false;
+			gptp_mi_clk_slave_sync_compute();
+
+#if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
+			/* Instead of updating SlaveClock, update LocalClock */
+			gptp_update_local_port_clock();
+#endif
+			gptp_call_phase_dis_cb();
+		}
+
+		break;
+	}
+}
+
+static void gptp_mi_clk_master_sync_offset_state_machine(void)
+{
+	struct gptp_clk_master_sync_offset_state *state;
+	struct gptp_global_ds *global_ds;
+
+	state = &GPTP_STATE()->clk_master_sync_offset;
+	global_ds = GPTP_GLOBAL_DS();
+
+	switch (state->state) {
+	case GPTP_CMS_OFFSET_INITIALIZING:
+		state->rcvd_sync_receipt_time = false;
+		state->state = GPTP_CMS_OFFSET_INDICATION;
+		break;
+	case GPTP_CMS_OFFSET_INDICATION:
+		if (!state->rcvd_sync_receipt_time) {
+			break;
+		}
+
+		state->rcvd_sync_receipt_time = false;
+
+		if (global_ds->selected_role[0] == GPTP_PORT_PASSIVE) {
+			/* TODO Calculate real values for proper BC support */
+			memset(&global_ds->clk_src_phase_offset, 0x0,
+			       sizeof(struct gptp_scaled_ns));
+			global_ds->clk_src_freq_offset = 0;
+		} else if (global_ds->clk_src_time_base_indicator_prev
+			   != global_ds->clk_src_time_base_indicator) {
+			memcpy(&global_ds->clk_src_phase_offset,
+			       &global_ds->last_gm_phase_change,
+			       sizeof(struct gptp_scaled_ns));
+
+			global_ds->clk_src_freq_offset =
+				global_ds->last_gm_freq_change;
+		}
+
+		break;
+	default:
+		NET_ERR("Unrecognised state %d", state->state);
+		break;
+	}
+}
+
+#if defined(CONFIG_NET_GPTP_GM_CAPABLE)
+static inline void gptp_mi_setup_sync_send_time(void)
+{
+	struct gptp_clk_master_sync_snd_state *state;
+	struct gptp_global_ds *global_ds;
+	uint64_t time_helper;
+
+	state = &GPTP_STATE()->clk_master_sync_send;
+	global_ds = GPTP_GLOBAL_DS();
+
+	time_helper = state->sync_send_time.low;
+
+	state->sync_send_time.low +=
+		global_ds->clk_master_sync_itv;
+
+	/* Check for overflow */
+	if (state->sync_send_time.low < time_helper) {
+		state->sync_send_time.high += 1U;
+		state->sync_send_time.low =
+			UINT64_MAX - state->sync_send_time.low;
+	}
+}
+
+static void gptp_mi_set_ps_sync_cmss(void)
+{
+	struct gptp_clk_master_sync_snd_state *state;
+	struct gptp_global_ds *global_ds;
+	struct gptp_md_sync_info *sync_info;
+	uint64_t current_time;
+
+	global_ds = GPTP_GLOBAL_DS();
+	state = &GPTP_STATE()->clk_master_sync_send;
+
+	sync_info = &state->pss_snd.sync_info;
+
+	state->pss_snd.local_port_number = 0U;
+
+	current_time = gptp_get_current_master_time_nanosecond();
+
+	sync_info->precise_orig_ts.second = current_time / NSEC_PER_SEC;
+	sync_info->precise_orig_ts.nanosecond = current_time % NSEC_PER_SEC;
+
+	/* TODO calculate correction field properly, rate_ratio is also set to
+	 * zero instead of being copied from global_ds as it affects the final
+	 * value of FUP correction field.
+	 */
+	sync_info->follow_up_correction_field = 0;
+	sync_info->rate_ratio = 0;
+
+	memcpy(&sync_info->src_port_id.clk_id,
+	       GPTP_DEFAULT_DS()->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	sync_info->src_port_id.port_number = 0U;
+	sync_info->log_msg_interval = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV;
+	sync_info->upstream_tx_time = global_ds->local_time.low;
+
+	state->pss_snd.sync_receipt_timeout_time = UINT64_MAX;
+
+	sync_info->gm_time_base_indicator =
+		global_ds->clk_src_time_base_indicator;
+
+	memcpy(&sync_info->last_gm_phase_change,
+	       &global_ds->clk_src_phase_offset,
+	       sizeof(struct gptp_scaled_ns));
+
+	sync_info->last_gm_freq_change = global_ds->clk_src_freq_offset;
+}
+
+static inline void gptp_mi_tx_ps_sync_cmss(void)
+{
+	struct gptp_clk_master_sync_snd_state *state;
+	struct gptp_pss_send_state *pss_send;
+	int port;
+
+	state = &GPTP_STATE()->clk_master_sync_send;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		pss_send = &GPTP_PORT_STATE(port)->pss_send;
+		pss_send->pss_sync_ptr = &state->pss_snd;
+
+		pss_send->rcvd_pss_sync = true;
+	}
+}
+
+static void gptp_mi_clk_master_sync_snd_state_machine(void)
+{
+	struct gptp_clk_master_sync_snd_state *state;
+	struct gptp_global_ds *global_ds;
+	uint64_t current_time;
+
+	state = &GPTP_STATE()->clk_master_sync_send;
+	global_ds = GPTP_GLOBAL_DS();
+
+	switch (state->state) {
+	case GPTP_CMS_SND_INITIALIZING:
+		gptp_mi_setup_sync_send_time();
+
+		state->state = GPTP_CMS_SND_INDICATION;
+		break;
+
+	case GPTP_CMS_SND_INDICATION:
+		current_time = gptp_get_current_master_time_nanosecond();
+
+		if (current_time >= state->sync_send_time.low) {
+			gptp_mi_set_ps_sync_cmss();
+			gptp_mi_tx_ps_sync_cmss();
+
+			gptp_mi_setup_sync_send_time();
+		}
+
+		break;
+
+	default:
+		NET_ERR("Unrecognised state %d", state->state);
+		break;
+	}
+}
+#endif
+
+static void gptp_compute_gm_rate_ratio(void)
+{
+	static struct net_ptp_extended_time src_time_0;
+	static struct gptp_uscaled_ns local_time_0;
+	struct net_ptp_extended_time src_time_n;
+	struct gptp_uscaled_ns local_time_n;
+	struct net_ptp_extended_time src_time_t;
+	struct gptp_uscaled_ns local_time_t;
+	struct gptp_clk_master_sync_rcv_state *state;
+	struct gptp_global_ds *global_ds;
+	double new_gm_rate;
+
+	state = &GPTP_STATE()->clk_master_sync_receive;
+	global_ds = GPTP_GLOBAL_DS();
+
+	/* Get current local and source time */
+	memcpy(&src_time_n, &state->rcvd_clk_src_req.src_time,
+	       sizeof(struct net_ptp_extended_time));
+
+	memcpy(&local_time_n, &global_ds->local_time,
+	       sizeof(struct gptp_uscaled_ns));
+
+	if ((src_time_0.second == 0U && src_time_0.fract_nsecond == 0U)
+	    || (local_time_0.high == 0U && local_time_0.low == 0U)) {
+		memcpy(&src_time_0, &src_time_n,
+		       sizeof(struct net_ptp_extended_time));
+
+		memcpy(&local_time_0, &local_time_n,
+		       sizeof(struct gptp_uscaled_ns));
+
+		global_ds->gm_rate_ratio = 1.0;
+
+		return;
+	}
+
+	/* Take care of the sign of the result */
+	new_gm_rate = 1.0;
+
+	if ((src_time_n.second < src_time_0.second)
+	    || (src_time_n.second == src_time_0.second
+		&& src_time_n.fract_nsecond < src_time_0.fract_nsecond)) {
+		/* Change result sign and swap src_time_n and src_time_0 */
+		memcpy(&src_time_t, &src_time_n,
+		       sizeof(struct net_ptp_extended_time));
+		memcpy(&src_time_n, &src_time_0,
+		       sizeof(struct net_ptp_extended_time));
+		memcpy(&src_time_0, &src_time_t,
+		       sizeof(struct net_ptp_extended_time));
+
+		new_gm_rate *= -1;
+	}
+
+	if ((local_time_n.high < local_time_0.high)
+	    || (local_time_n.high == local_time_0.high
+		&& local_time_n.low < local_time_0.low)) {
+		/* Change result sign and swap local_time_n and local_time_0 */
+		memcpy(&local_time_t, &local_time_n,
+		       sizeof(struct gptp_uscaled_ns));
+		memcpy(&local_time_n, &local_time_0,
+		       sizeof(struct gptp_uscaled_ns));
+		memcpy(&local_time_0, &local_time_t,
+		       sizeof(struct gptp_uscaled_ns));
+
+		new_gm_rate *= -1;
+	}
+
+	/* At this point src_time_n >= src_time_0 */
+	src_time_n.second -= src_time_0.second;
+
+	if (src_time_n.fract_nsecond >= src_time_0.fract_nsecond) {
+		src_time_n.fract_nsecond -= src_time_0.fract_nsecond;
+	} else {
+		src_time_n.second -= 1U;
+		src_time_n.fract_nsecond = (NSEC_PER_SEC * GPTP_POW2_16)
+			- src_time_0.fract_nsecond;
+	}
+
+	/* At this point local_time_n >= local_time_0 */
+	local_time_n.high -= local_time_0.high;
+
+	if (local_time_n.low >= local_time_0.low) {
+		local_time_n.low -= local_time_0.low;
+	} else {
+		local_time_n.high -= 1U;
+		local_time_n.low = UINT64_MAX - local_time_0.low;
+	}
+
+	/* Calculate it in nanoseconds, new_gm_rate is either 1 or -1 here */
+	new_gm_rate *= ((src_time_n.second * NSEC_PER_SEC)
+		+ (src_time_n.fract_nsecond / GPTP_POW2_16));
+
+	new_gm_rate /= local_time_n.low;
+
+	global_ds->gm_rate_ratio = new_gm_rate;
+}
+
+static void gptp_mi_clk_master_sync_rcv_state_machine(void)
+{
+	struct gptp_clk_master_sync_rcv_state *s;
+	struct gptp_global_ds *global_ds;
+
+#ifdef CONFIG_NET_GPTP_PROBE_CLOCK_SOURCE_ON_DEMAND
+	struct gptp_clk_src_time_invoke_params invoke_args = {};
+	uint64_t cur = gptp_get_current_master_time_nanosecond();
+
+	invoke_args.src_time.second = cur / NSEC_PER_SEC;
+	cur -= (invoke_args.src_time.second * NSEC_PER_SEC);
+
+	invoke_args.src_time.fract_nsecond = cur * GPTP_POW2_16;
+
+	memset(&invoke_args.last_gm_phase_change, 0x0,
+	       sizeof(struct gptp_scaled_ns));
+	invoke_args.last_gm_freq_change = 0;
+
+	gptp_clk_src_time_invoke(&invoke_args);
+#endif
+
+	global_ds = GPTP_GLOBAL_DS();
+
+	s = &GPTP_STATE()->clk_master_sync_receive;
+	switch (s->state) {
+	case GPTP_CMS_RCV_INITIALIZING:
+		s->state = GPTP_CMS_RCV_WAITING;
+		break;
+
+	case GPTP_CMS_RCV_WAITING:
+		if (s->rcvd_clock_source_req || s->rcvd_local_clock_tick) {
+			s->state = GPTP_CMS_RCV_SOURCE_TIME;
+		}
+
+		break;
+
+	case GPTP_CMS_RCV_SOURCE_TIME:
+		global_ds->local_time.high = 0U;
+		global_ds->local_time.low =
+			gptp_get_current_master_time_nanosecond();
+
+		if (s->rcvd_clock_source_req) {
+			gptp_compute_gm_rate_ratio();
+
+			global_ds->clk_src_time_base_indicator_prev =
+				global_ds->clk_src_time_base_indicator;
+
+			global_ds->clk_src_time_base_indicator =
+				s->rcvd_clk_src_req.time_base_indicator;
+
+			memcpy(&global_ds->clk_src_last_gm_phase_change,
+			       &s->rcvd_clk_src_req.last_gm_phase_change,
+			       sizeof(struct gptp_scaled_ns));
+
+			global_ds->clk_src_last_gm_freq_change =
+				s->rcvd_clk_src_req.last_gm_freq_change;
+		}
+
+		s->rcvd_clock_source_req = false;
+		s->rcvd_local_clock_tick = false;
+		s->state = GPTP_CMS_RCV_WAITING;
+		break;
+
+	default:
+		NET_ERR("Unrecognised state %d", s->state);
+		break;
+	}
+}
+
+static void copy_path_trace(struct gptp_announce *announce)
+{
+	int len = ntohs(announce->tlv.len);
+	struct gptp_path_trace *sys_path_trace;
+
+	if (len > GPTP_MAX_PATHTRACE_SIZE) {
+		NET_ERR("Too long path trace (%d vs %d)",
+			GPTP_MAX_PATHTRACE_SIZE, len);
+		return;
+	}
+
+	sys_path_trace = &GPTP_GLOBAL_DS()->path_trace;
+
+	sys_path_trace->len = htons(len + GPTP_CLOCK_ID_LEN);
+
+	memcpy(sys_path_trace->path_sequence, announce->tlv.path_sequence,
+	       len);
+
+	/* Append local clockIdentity. */
+	memcpy((uint8_t *)sys_path_trace->path_sequence + len,
+	       GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN);
+}
+
+static bool gptp_mi_qualify_announce(int port, struct net_pkt *announce_msg)
+{
+	struct gptp_announce *announce;
+	struct gptp_hdr *hdr;
+	int i;
+	uint16_t len;
+
+	hdr = GPTP_HDR(announce_msg);
+	announce = GPTP_ANNOUNCE(announce_msg);
+
+	if (memcmp(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
+		   GPTP_CLOCK_ID_LEN) == 0) {
+		return false;
+	}
+
+	len = ntohs(announce->steps_removed);
+	if (len >= 255U) {
+		return false;
+	}
+
+	for (i = 0; i < len + 1; i++) {
+		if (memcmp(announce->tlv.path_sequence[i],
+			   GPTP_DEFAULT_DS()->clk_id,
+			   GPTP_CLOCK_ID_LEN) == 0) {
+			return false;
+		}
+	}
+
+	if (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE) {
+		copy_path_trace(announce);
+	}
+
+	return true;
+}
+
+static void gptp_mi_port_announce_receive_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_port_announce_receive_state *state;
+	struct gptp_port_bmca_data *bmca_data;
+
+	state = &GPTP_PORT_STATE(port)->pa_rcv;
+	port_ds = GPTP_PORT_DS(port);
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+
+	if ((!port_ds->ptt_port_enabled) || (!port_ds->as_capable)) {
+		state->state = GPTP_PA_RCV_DISCARD;
+	}
+
+	switch (state->state) {
+	case GPTP_PA_RCV_DISCARD:
+		state->rcvd_announce = false;
+		bmca_data->rcvd_msg = false;
+		if (bmca_data->rcvd_announce_ptr != NULL) {
+			net_pkt_unref(bmca_data->rcvd_announce_ptr);
+			bmca_data->rcvd_announce_ptr = NULL;
+		}
+
+		state->state = GPTP_PA_RCV_RECEIVE;
+		break;
+
+	case GPTP_PA_RCV_RECEIVE:
+		/* "portEnabled" is not checked: the interface is always up. */
+		if (state->rcvd_announce &&
+		    port_ds->ptt_port_enabled &&
+		    port_ds->as_capable	&&
+		    !bmca_data->rcvd_msg) {
+			state->rcvd_announce = false;
+
+			bmca_data->rcvd_msg = gptp_mi_qualify_announce(
+				port, bmca_data->rcvd_announce_ptr);
+			if (!bmca_data->rcvd_msg) {
+				net_pkt_unref(bmca_data->rcvd_announce_ptr);
+				bmca_data->rcvd_announce_ptr = NULL;
+			}
+		}
+
+		break;
+	}
+}
+
+/*
+ * Compare a vector to an announce message vector.
+ * All must be in big endian (network) order.
+ */
+static enum gptp_received_info compare_priority_vectors(
+		struct gptp_priority_vector *vector,
+		struct net_pkt *pkt, int port)
+{
+	struct gptp_hdr *hdr;
+	struct gptp_announce *announce;
+	struct gptp_port_bmca_data *bmca_data;
+	int rsi_cmp, spi_cmp, port_cmp;
+
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	hdr = GPTP_HDR(pkt);
+	announce = GPTP_ANNOUNCE(pkt);
+
+	/* Compare rootSystemIdentity and stepsRemoved. */
+	rsi_cmp = memcmp(&announce->root_system_id,
+			 &vector->root_system_id,
+			 sizeof(struct gptp_root_system_identity) +
+			 sizeof(uint16_t));
+	if (rsi_cmp < 0) {
+		/* Better rootSystemIdentity. */
+		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
+	}
+
+	/* Compare sourcePortIdentity. */
+	spi_cmp = memcmp(&hdr->port_id, &vector->src_port_id,
+			 sizeof(struct gptp_port_identity));
+
+	port_cmp = (int)port - ntohs(vector->port_number);
+
+	if (spi_cmp == 0) {
+		if (rsi_cmp == 0) {
+			if (port_cmp == 0) {
+				/* Same priority vector. */
+				return GPTP_RCVD_INFO_REPEATED_MASTER_INFO;
+			} else if (port_cmp < 0) {
+				/* Priority vector with better reception port
+				 * number.
+				 */
+				return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
+			}
+		} else {
+			/* Same master port but different Grand Master. */
+			return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
+		}
+	} else if ((spi_cmp < 0) && (rsi_cmp == 0)) {
+		/* Same Grand Master but better masterPort. */
+		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
+	}
+
+	return GPTP_RCVD_INFO_INFERIOR_MASTER_INFO;
+}
+
+static enum gptp_received_info rcv_info(int port)
+{
+	/* TODO
+	 * How can we define that a message does not convey the port
+	 * role Master port ?
+	 * It is needed to define that to be able to send
+	 * GPTP_RCVD_INFO_OTHER_INFO.
+	 */
+	struct gptp_port_bmca_data *bmca_data;
+	struct gptp_announce *announce;
+
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
+
+	bmca_data->message_steps_removed = announce->steps_removed;
+
+	return compare_priority_vectors(&bmca_data->port_priority,
+					bmca_data->rcvd_announce_ptr,
+					port);
+}
+
+static void record_other_announce_info(int port)
+{
+	struct gptp_hdr *hdr;
+	struct gptp_announce *announce;
+	struct gptp_port_bmca_data *bmca_data;
+
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
+	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
+
+	/* Copy leap61, leap59, current UTC offset valid, time traceable and
+	 * frequency traceable flags.
+	 */
+	bmca_data->ann_flags.octets[1] = hdr->flags.octets[1];
+
+	bmca_data->ann_current_utc_offset = ntohs(announce->cur_utc_offset);
+	bmca_data->ann_time_source = announce->time_source;
+}
+
+static void copy_priority_vector(struct gptp_priority_vector *vector,
+				 struct net_pkt *pkt, int port)
+{
+	struct gptp_hdr *hdr;
+	struct gptp_announce *announce;
+
+	hdr = GPTP_HDR(pkt);
+	announce = GPTP_ANNOUNCE(pkt);
+
+	memcpy(&vector->root_system_id, &announce->root_system_id,
+	       sizeof(struct gptp_root_system_identity) + sizeof(uint16_t));
+
+	memcpy(&vector->src_port_id, &hdr->port_id,
+	       sizeof(struct gptp_port_identity));
+
+	vector->port_number = htons(port);
+}
+
+static void gptp_mi_port_announce_information_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_global_ds *global_ds;
+	struct gptp_port_announce_information_state *state;
+	struct gptp_announce *announce;
+	struct gptp_hdr *hdr;
+	struct gptp_port_bmca_data *bmca_data;
+	struct gptp_pss_rcv_state *pss_rcv;
+
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	state = &GPTP_PORT_STATE(port)->pa_info;
+	port_ds = GPTP_PORT_DS(port);
+	global_ds = GPTP_GLOBAL_DS();
+
+	if ((!port_ds->ptt_port_enabled || !port_ds->as_capable) &&
+	    (bmca_data->info_is != GPTP_INFO_IS_DISABLED)) {
+		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
+	}
+
+	switch (state->state) {
+	case GPTP_PA_INFO_DISABLED:
+		bmca_data->rcvd_msg = false;
+		bmca_data->info_is = GPTP_INFO_IS_DISABLED;
+		SET_RESELECT(global_ds, port);
+		CLEAR_SELECTED(global_ds, port);
+		gptp_change_pa_info_state(port, state,
+					  GPTP_PA_INFO_POST_DISABLED);
+		k_timer_stop(&state->ann_rcpt_expiry_timer);
+		state->ann_expired = true;
+		__fallthrough;
+
+	case GPTP_PA_INFO_POST_DISABLED:
+		if (port_ds->ptt_port_enabled && port_ds->as_capable) {
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_AGED);
+		} else if (bmca_data->rcvd_msg) {
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_DISABLED);
+		}
+
+		break;
+
+	case GPTP_PA_INFO_AGED:
+		bmca_data->info_is = GPTP_INFO_IS_AGED;
+		CLEAR_SELECTED(global_ds, port);
+		SET_RESELECT(global_ds, port);
+		/* Transition will be actually tested in UPDATE state. */
+		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_UPDATE);
+		break;
+
+	case GPTP_PA_INFO_UPDATE:
+		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
+			memcpy(&bmca_data->port_priority,
+			       &bmca_data->master_priority,
+			       sizeof(struct gptp_priority_vector));
+
+			bmca_data->port_steps_removed =
+				global_ds->master_steps_removed;
+			bmca_data->updt_info = false;
+			bmca_data->info_is = GPTP_INFO_IS_MINE;
+			bmca_data->new_info = true;
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_CURRENT);
+		}
+
+		break;
+
+	case GPTP_PA_INFO_CURRENT:
+		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
+		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_UPDATE);
+		} else if (bmca_data->rcvd_msg && !bmca_data->updt_info) {
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_RECEIVE);
+		} else if ((bmca_data->info_is == GPTP_INFO_IS_RECEIVED) &&
+			   !bmca_data->updt_info &&
+			   !bmca_data->rcvd_msg &&
+			   (state->ann_expired ||
+			    (global_ds->gm_present &&
+			   pss_rcv->rcv_sync_receipt_timeout_timer_expired))) {
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_AGED);
+		}
+
+		break;
+
+	case GPTP_PA_INFO_RECEIVE:
+		switch (rcv_info(port)) {
+		case GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO:
+			gptp_change_pa_info_state(port, state,
+				GPTP_PA_INFO_SUPERIOR_MASTER_PORT);
+			break;
+		case GPTP_RCVD_INFO_REPEATED_MASTER_INFO:
+			gptp_change_pa_info_state(port, state,
+				GPTP_PA_INFO_REPEATED_MASTER_PORT);
+			break;
+		case GPTP_RCVD_INFO_INFERIOR_MASTER_INFO:
+			__fallthrough;
+		case GPTP_RCVD_INFO_OTHER_INFO:
+			gptp_change_pa_info_state(port, state,
+				GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT);
+			break;
+		}
+
+		break;
+
+	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
+		/* We copy directly the content of the message to the port
+		 * priority vector without using an intermediate
+		 * messagePrioriry structure.
+		 */
+
+		if (!bmca_data->rcvd_announce_ptr) {
+			/* Shouldn't be reached. Checked for safety reason. */
+			bmca_data->rcvd_msg = false;
+			gptp_change_pa_info_state(port, state,
+						  GPTP_PA_INFO_CURRENT);
+			break;
+		}
+
+		copy_priority_vector(&bmca_data->port_priority,
+				     bmca_data->rcvd_announce_ptr, port);
+
+		announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
+		bmca_data->port_steps_removed = ntohs(announce->steps_removed);
+		record_other_announce_info(port);
+		hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
+		gptp_set_time_itv(&bmca_data->ann_rcpt_timeout_time_interval,
+				  port_ds->announce_receipt_timeout,
+				  hdr->log_msg_interval);
+		bmca_data->info_is = GPTP_INFO_IS_RECEIVED;
+		CLEAR_SELECTED(global_ds, port);
+		SET_RESELECT(global_ds, port);
+		__fallthrough;
+
+	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
+		k_timer_stop(&state->ann_rcpt_expiry_timer);
+		state->ann_expired = false;
+		k_timer_start(&state->ann_rcpt_expiry_timer,
+			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
+				  &bmca_data->ann_rcpt_timeout_time_interval)),
+			      K_NO_WAIT);
+		__fallthrough;
+
+	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
+		if (bmca_data->rcvd_announce_ptr != NULL) {
+			net_pkt_unref(bmca_data->rcvd_announce_ptr);
+			bmca_data->rcvd_announce_ptr = NULL;
+		}
+
+		bmca_data->rcvd_msg = false;
+		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_CURRENT);
+		break;
+	}
+}
+
+static void gptp_updt_role_disabled_tree(void)
+{
+	struct gptp_global_ds *global_ds;
+	int port;
+
+	global_ds = GPTP_GLOBAL_DS();
+
+	/* Set all elements of the selectedRole array to DisabledPort. */
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		gptp_change_port_state(port, GPTP_PORT_DISABLED);
+	}
+
+	/* Set lastGmPriority to all ones. */
+	(void)memset(&global_ds->last_gm_priority, 0xFF,
+		     sizeof(struct gptp_priority_vector));
+
+	/* Set pathTrace array to contain the single element thisClock. */
+	global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
+	memcpy(global_ds->path_trace.path_sequence, GPTP_DEFAULT_DS()->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+}
+
+static void gptp_clear_reselect_tree(void)
+{
+	/* Set all the elements of the reselect array to FALSE. */
+	GPTP_GLOBAL_DS()->reselect_array = 0;
+}
+
+static int compute_best_vector(void)
+{
+	struct gptp_priority_vector *gm_prio;
+	struct gptp_default_ds *default_ds;
+	struct gptp_global_ds *global_ds;
+	struct gptp_priority_vector *best_vector, *challenger;
+	int best_port, port, tmp;
+	struct gptp_pss_rcv_state *pss_rcv;
+	struct gptp_port_announce_information_state *pa_info_state;
+
+	default_ds = GPTP_DEFAULT_DS();
+	global_ds = GPTP_GLOBAL_DS();
+	best_port = 0;
+	gm_prio = &global_ds->gm_priority;
+
+	/* Write systemPriority into grandmaster. */
+	(void)memset(gm_prio, 0, sizeof(struct gptp_priority_vector));
+	gm_prio->root_system_id.grand_master_prio1 = default_ds->priority1;
+	gm_prio->root_system_id.grand_master_prio2 = default_ds->priority2;
+	gm_prio->root_system_id.clk_quality.clock_class =
+		default_ds->clk_quality.clock_class;
+	gm_prio->root_system_id.clk_quality.clock_accuracy =
+		default_ds->clk_quality.clock_accuracy;
+	gm_prio->root_system_id.clk_quality.offset_scaled_log_var =
+		htons(default_ds->clk_quality.offset_scaled_log_var);
+
+	memcpy(gm_prio->src_port_id.clk_id, default_ds->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+	memcpy(gm_prio->root_system_id.grand_master_id, default_ds->clk_id,
+	       GPTP_CLOCK_ID_LEN);
+
+	best_vector = gm_prio;
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		challenger = &GPTP_PORT_BMCA_DATA(port)->port_priority;
+		pa_info_state = &GPTP_PORT_STATE(port)->pa_info;
+		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
+
+		if (pa_info_state->ann_expired ||
+		    (global_ds->gm_present &&
+		     pss_rcv->rcv_sync_receipt_timeout_timer_expired)) {
+			continue;
+		}
+
+		if (memcmp(challenger->src_port_id.clk_id, default_ds->clk_id,
+			   GPTP_CLOCK_ID_LEN) == 0) {
+			/* Discard this challenger. */
+			continue;
+		}
+
+		if (best_port == 0) {
+			tmp = memcmp(&challenger->root_system_id,
+				     &best_vector->root_system_id,
+				     sizeof(struct gptp_root_system_identity));
+			if (tmp < 0) {
+				best_vector = challenger;
+				best_port = port;
+			} else if (tmp > 0) {
+				continue;
+			}
+
+			tmp = (int)challenger->steps_removed -
+				((int)ntohs(best_vector->steps_removed) + 1);
+			if (tmp < 0) {
+				best_vector = challenger;
+				best_port = port;
+			} else if (tmp > 0) {
+				continue;
+			}
+
+			tmp = memcmp(&challenger->src_port_id,
+				     &best_vector->src_port_id,
+				     sizeof(struct gptp_port_identity));
+			if (tmp < 0) {
+				best_vector = challenger;
+				best_port = port;
+			} else if (tmp > 0) {
+				continue;
+			}
+
+			if (ntohs(challenger->port_number) <
+			    ntohs(best_vector->port_number)) {
+				best_vector = challenger;
+				best_port = port;
+			}
+
+		} else {
+			/* We can compare portPriority vectors without
+			 * calculating pathPriority vectors.
+			 */
+			if (memcmp(challenger, best_vector,
+				   sizeof(struct gptp_priority_vector)) < 0) {
+				best_vector = challenger;
+				best_port = port;
+			}
+		}
+	}
+
+	if (best_port != 0) {
+		if (&global_ds->gm_priority.root_system_id !=
+		    &best_vector->root_system_id) {
+			memcpy(&global_ds->gm_priority.root_system_id,
+			       &best_vector->root_system_id,
+			       sizeof(struct gptp_root_system_identity));
+		}
+
+		global_ds->gm_priority.steps_removed =
+			htons(ntohs(best_vector->steps_removed) + 1);
+
+		if (&global_ds->gm_priority.src_port_id !=
+		    &best_vector->src_port_id) {
+			memcpy(&global_ds->gm_priority.src_port_id,
+			       &best_vector->src_port_id,
+			       sizeof(struct gptp_port_identity));
+		}
+
+		global_ds->gm_priority.port_number = best_vector->port_number;
+	}
+
+	return best_port;
+}
+
+static void update_bmca(int port,
+			int best_port,
+			struct gptp_global_ds *global_ds,
+			struct gptp_default_ds *default_ds,
+			struct gptp_priority_vector *gm_prio)
+{
+	struct gptp_port_bmca_data *bmca_data = GPTP_PORT_BMCA_DATA(port);
+
+	/* Update masterPriorityVector for the port. */
+	if (best_port == 0) {
+		memcpy(&bmca_data->master_priority, gm_prio,
+		       sizeof(struct gptp_priority_vector));
+
+		bmca_data->master_priority.port_number = htons(port);
+		bmca_data->master_priority.src_port_id.port_number =
+			htons(port);
+	} else {
+		memcpy(&bmca_data->master_priority.root_system_id,
+		       &gm_prio->root_system_id,
+		       sizeof(struct gptp_root_system_identity));
+		memcpy(bmca_data->master_priority.src_port_id.clk_id,
+		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
+		bmca_data->master_priority.port_number = htons(port);
+		bmca_data->master_priority.src_port_id.port_number =
+			htons(port);
+	}
+
+	switch (bmca_data->info_is) {
+	case GPTP_INFO_IS_DISABLED:
+		gptp_change_port_state(port, GPTP_PORT_DISABLED);
+		break;
+
+	case GPTP_INFO_IS_AGED:
+		bmca_data->updt_info = true;
+		gptp_change_port_state(port, GPTP_PORT_MASTER);
+		break;
+
+	case GPTP_INFO_IS_MINE:
+		gptp_change_port_state(port, GPTP_PORT_MASTER);
+
+		if ((memcmp(&bmca_data->port_priority,
+			    &bmca_data->master_priority,
+			    sizeof(struct gptp_priority_vector)) != 0) ||
+		    (bmca_data->port_steps_removed !=
+		     global_ds->master_steps_removed)) {
+			bmca_data->updt_info = true;
+		}
+
+		break;
+
+	case GPTP_INFO_IS_RECEIVED:
+		if (best_port == port) {
+			/* gmPriorityVector is now derived from
+			 * portPriorityVector.
+			 */
+			gptp_change_port_state(port, GPTP_PORT_SLAVE);
+			bmca_data->updt_info = false;
+		} else if (memcmp(&bmca_data->port_priority,
+				  &bmca_data->master_priority,
+				  sizeof(struct gptp_priority_vector)) <= 0) {
+			/* The masterPriorityVector is not better than
+			 * the portPriorityVector.
+			 */
+			gptp_change_port_state(port, GPTP_PORT_PASSIVE);
+
+			if (memcmp(bmca_data->port_priority.src_port_id.clk_id,
+				   default_ds->clk_id,
+				   GPTP_CLOCK_ID_LEN)) {
+				/* The sourcePortIdentity component of
+				 * the portPriorityVector does not
+				 * reflect another port on the
+				 * time-aware system.
+				 */
+				bmca_data->updt_info = true;
+			} else {
+				bmca_data->updt_info = false;
+			}
+		} else {
+			gptp_change_port_state(port, GPTP_PORT_MASTER);
+			bmca_data->updt_info = true;
+		}
+
+		break;
+	}
+}
+
+static void gptp_updt_roles_tree(void)
+{
+	struct gptp_global_ds *global_ds;
+	struct gptp_default_ds *default_ds;
+	struct gptp_priority_vector *gm_prio, *last_gm_prio;
+	struct gptp_port_bmca_data *bmca_data;
+	int port, best_port;
+
+	global_ds = GPTP_GLOBAL_DS();
+	default_ds = GPTP_DEFAULT_DS();
+
+	gm_prio = &global_ds->gm_priority;
+	last_gm_prio = &global_ds->last_gm_priority;
+
+	/* Save gmPriority. */
+	memcpy(last_gm_prio, gm_prio, sizeof(struct gptp_priority_vector));
+
+	best_port = compute_best_vector();
+
+	/* If the best vector was the systemPriorityVector. */
+	if (best_port == 0) {
+		/* Copy leap61, leap59, current UTC offset valid,
+		 * time traceable and frequency traceable flags.
+		 */
+		global_ds->global_flags.octets[1] =
+			global_ds->sys_flags.octets[1];
+		global_ds->current_utc_offset =
+			global_ds->sys_current_utc_offset;
+		global_ds->time_source = global_ds->sys_time_source;
+		global_ds->master_steps_removed = 0U;
+	} else {
+		bmca_data = GPTP_PORT_BMCA_DATA(best_port);
+
+		/* Copy leap61, leap59, current UTC offset valid,
+		 * time traceable and frequency traceable flags.
+		 */
+		global_ds->global_flags.octets[1] =
+			bmca_data->ann_flags.octets[1];
+		global_ds->current_utc_offset =
+			global_ds->sys_current_utc_offset;
+		global_ds->time_source = bmca_data->ann_time_source;
+		global_ds->master_steps_removed =
+			htons(ntohs(bmca_data->message_steps_removed) + 1);
+	}
+
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		update_bmca(port, best_port, global_ds, default_ds, gm_prio);
+	}
+
+	/* Update gmPresent. */
+	global_ds->gm_present =
+		(gm_prio->root_system_id.grand_master_prio1 == 255U) ?
+		false : true;
+
+	/* Assign the port role for port 0. */
+	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
+		if (global_ds->selected_role[port] == GPTP_PORT_SLAVE) {
+			gptp_change_port_state(0, GPTP_PORT_PASSIVE);
+			break;
+		}
+	}
+
+	if (port == GPTP_PORT_END) {
+		gptp_change_port_state(0, GPTP_PORT_SLAVE);
+	}
+
+	/* If current system is the Grand Master, set pathTrace array. */
+	if (memcmp(default_ds->clk_id, gm_prio->root_system_id.grand_master_id,
+		   GPTP_CLOCK_ID_LEN) == 0) {
+		global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
+		memcpy(global_ds->path_trace.path_sequence,
+		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
+	}
+}
+
+static void gptp_set_selected_tree(void)
+{
+	/* Set all the elements of the selected array to TRUE. */
+	GPTP_GLOBAL_DS()->selected_array = ~0;
+}
+
+static void gptp_mi_port_role_selection_state_machine(void)
+{
+	struct gptp_port_role_selection_state *state;
+
+	state = &GPTP_STATE()->pr_sel;
+
+	switch (state->state) {
+	case GPTP_PR_SELECTION_INIT_BRIDGE:
+		gptp_updt_role_disabled_tree();
+		state->state = GPTP_PR_SELECTION_ROLE_SELECTION;
+
+		/* Be sure to enter the "if" statement immediately after. */
+		GPTP_GLOBAL_DS()->reselect_array = ~0;
+		__fallthrough;
+
+	case GPTP_PR_SELECTION_ROLE_SELECTION:
+		if (GPTP_GLOBAL_DS()->reselect_array != 0) {
+			gptp_clear_reselect_tree();
+			gptp_updt_roles_tree();
+			gptp_set_selected_tree();
+		}
+
+		break;
+	}
+}
+
+static void tx_announce(int port)
+{
+	struct net_pkt *pkt;
+
+	pkt = gptp_prepare_announce(port);
+	if (pkt) {
+		gptp_send_announce(port, pkt);
+	}
+}
+
+static void gptp_mi_port_announce_transmit_state_machine(int port)
+{
+	struct gptp_port_ds *port_ds;
+	struct gptp_global_ds *global_ds;
+	struct gptp_port_announce_transmit_state *state;
+	struct gptp_port_bmca_data *bmca_data;
+
+	port_ds = GPTP_PORT_DS(port);
+	global_ds = GPTP_GLOBAL_DS();
+	bmca_data = GPTP_PORT_BMCA_DATA(port);
+	state = &GPTP_PORT_STATE(port)->pa_transmit;
+
+	/* Reset interval as defined in AnnounceIntervalSetting
+	 * state machine.
+	 */
+	if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
+		gptp_update_announce_interval(port, GPTP_ITV_SET_TO_INIT);
+	}
+
+	switch (state->state) {
+	case GPTP_PA_TRANSMIT_INIT:
+		bmca_data->new_info = true;
+		__fallthrough;
+
+	case GPTP_PA_TRANSMIT_IDLE:
+		k_timer_stop(&state->ann_send_periodic_timer);
+		state->ann_trigger = false;
+		k_timer_start(&state->ann_send_periodic_timer,
+			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
+					     &bmca_data->announce_interval)),
+			      K_NO_WAIT);
+
+		state->state = GPTP_PA_TRANSMIT_POST_IDLE;
+		__fallthrough;
+
+	case GPTP_PA_TRANSMIT_POST_IDLE:
+		if (IS_SELECTED(global_ds, port) &&
+		    !bmca_data->updt_info &&
+		    state->ann_trigger) {
+
+			state->state = GPTP_PA_TRANSMIT_PERIODIC;
+
+		} else if (IS_SELECTED(global_ds, port) &&
+			   !bmca_data->updt_info &&
+			   !state->ann_trigger &&
+			   (global_ds->selected_role[port] ==
+			    GPTP_PORT_MASTER) &&
+			   bmca_data->new_info) {
+
+			bmca_data->new_info = false;
+			tx_announce(port);
+			state->state = GPTP_PA_TRANSMIT_IDLE;
+		}
+
+		break;
+
+	case GPTP_PA_TRANSMIT_PERIODIC:
+		if (global_ds->selected_role[port] == GPTP_PORT_MASTER) {
+			bmca_data->new_info = true;
+		}
+		state->state = GPTP_PA_TRANSMIT_IDLE;
+		break;
+	}
+}
+
+
+void gptp_mi_port_sync_state_machines(int port)
+{
+	gptp_mi_pss_rcv_state_machine(port);
+	gptp_mi_pss_send_state_machine(port);
+}
+
+void gptp_mi_port_bmca_state_machines(int port)
+{
+	gptp_mi_port_announce_receive_state_machine(port);
+	gptp_mi_port_announce_information_state_machine(port);
+	gptp_mi_port_announce_transmit_state_machine(port);
+}
+
+void gptp_mi_state_machines(void)
+{
+	gptp_mi_site_sync_sync_state_machine();
+	gptp_mi_clk_slave_sync_state_machine();
+	gptp_mi_port_role_selection_state_machine();
+	gptp_mi_clk_master_sync_offset_state_machine();
+#if defined(CONFIG_NET_GPTP_GM_CAPABLE)
+	gptp_mi_clk_master_sync_snd_state_machine();
+#endif
+	gptp_mi_clk_master_sync_rcv_state_machine();
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_private.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_private.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_private.h	(working copy)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Private functions for the Precision Time Protocol Stack.
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_PRIVATE_H
+#define __GPTP_PRIVATE_H
+
+#include <net/gptp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Common defines for the gPTP stack. */
+#define GPTP_THREAD_WAIT_TIMEOUT_MS 1
+#define GPTP_MULTIPLE_PDELAY_RESP_WAIT (5 * 60 * MSEC_PER_SEC)
+
+#if defined(CONFIG_NET_GPTP_STATISTICS)
+#define GPTP_STATS_INC(port, var) (GPTP_PORT_PARAM_DS(port)->var++)
+#else
+#define GPTP_STATS_INC(port, var)
+#endif
+
+/**
+ * @brief Is a slave acting as a slave.
+ *
+ * Utility to check if a port is configured as a slave.
+ *
+ * @param port Port to check.
+ *
+ * @return True if this is a slave port.
+ */
+bool gptp_is_slave_port(int port);
+
+/**
+ * @brief Convert the network interface to the correct port number.
+ *
+ * @param iface Network Interface acting as a ptp port.
+ *
+ * @return Number of the port if found, ENODEV otherwise.
+ */
+int gptp_get_port_number(struct net_if *iface);
+
+/**
+ * @brief Calculate a logInteral and store in Uscaled ns structure.
+ *
+ * @param interval Result of calculation.
+ *
+ * @param seconds Seconds of interval.
+ *
+ * @param log_msg_interval Logarithm 2 to apply to this interval.
+ */
+void gptp_set_time_itv(struct gptp_uscaled_ns *interval,
+		       uint16_t seconds,
+		       int8_t log_msg_interval);
+
+/**
+ * @brief Convert uscaled ns to ms for timer use.
+ *
+ * @param usns Pointer to uscaled nanoseconds to convert.
+ *
+ * @return INT32_MAX if value exceed timer max value, 0 if the result of the
+ *	    conversion is less 1ms, the converted value otherwise.
+ */
+int32_t gptp_uscaled_ns_to_timer_ms(struct gptp_uscaled_ns *usns);
+
+/**
+ * @brief Update pDelay request interval and its timer.
+ *
+ * @param port Port number.
+ *
+ * @param log_val New logarithm 2 to apply to this interval.
+ */
+void gptp_update_pdelay_req_interval(int port, int8_t log_val);
+
+/**
+ * @brief Update sync interval and its timer.
+ *
+ * @param port Port number.
+ *
+ * @param log_val New logarithm 2 to apply to this interval.
+ */
+void gptp_update_sync_interval(int port, int8_t log_val);
+
+/**
+ * @brief Update announce interval and its timer.
+ *
+ * @param port Port number.
+ *
+ * @param log_val New logarithm 2 to apply to this interval.
+ */
+
+void gptp_update_announce_interval(int port, int8_t log_val);
+
+/**
+ * @brief Convert a ptp timestamp to nanoseconds.
+ *
+ * @param ts A PTP timestamp.
+ *
+ * @return Number of nanoseconds.
+ */
+static inline uint64_t gptp_timestamp_to_nsec(struct net_ptp_time *ts)
+{
+	if (!ts) {
+		return 0;
+	}
+
+	return (ts->second * NSEC_PER_SEC) + ts->nanosecond;
+}
+
+/**
+ * @brief Change the port state
+ *
+ * @param port Port number of the clock to use.
+ * @param state New state
+ */
+#if CONFIG_NET_GPTP_LOG_LEVEL < LOG_LEVEL_DBG
+void gptp_change_port_state(int port, enum gptp_port_state state);
+#else
+#define gptp_change_port_state(port, state)			\
+	gptp_change_port_state_debug(port, state, __func__, __LINE__)
+
+void gptp_change_port_state_debug(int port, enum gptp_port_state state,
+				  const char *caller, int line);
+#endif
+
+#if CONFIG_NET_GPTP_LOG_LEVEL < LOG_LEVEL_DBG
+void gptp_change_pa_info_state(
+	int port,
+	struct gptp_port_announce_information_state *pa_info_state,
+	enum gptp_pa_info_states state);
+#else
+#define gptp_change_pa_info_state(port, pa_info_state, state)		\
+	gptp_change_pa_info_state_debug(port, pa_info_state, state,	\
+					__func__, __LINE__)
+
+void gptp_change_pa_info_state_debug(
+	int port,
+	struct gptp_port_announce_information_state *pa_info_state,
+	enum gptp_pa_info_states state,
+	const char *caller, int line);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPTP_PRIVATE_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_state.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_state.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_state.h	(working copy)
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief PTP state machines
+ *
+ * This is not to be included by the application.
+ */
+
+#ifndef __GPTP_STATE_H
+#define __GPTP_STATE_H
+
+#include "gptp_mi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* PDelayRequest states. */
+enum gptp_pdelay_req_states {
+	GPTP_PDELAY_REQ_NOT_ENABLED,
+	GPTP_PDELAY_REQ_INITIAL_SEND_REQ,
+	GPTP_PDELAY_REQ_RESET,
+	GPTP_PDELAY_REQ_SEND_REQ,
+	GPTP_PDELAY_REQ_WAIT_RESP,
+	GPTP_PDELAY_REQ_WAIT_FOLLOW_UP,
+	GPTP_PDELAY_REQ_WAIT_ITV_TIMER,
+} __packed;
+
+/* Path Delay Response states. */
+enum gptp_pdelay_resp_states {
+	GPTP_PDELAY_RESP_NOT_ENABLED,
+	GPTP_PDELAY_RESP_INITIAL_WAIT_REQ,
+	GPTP_PDELAY_RESP_WAIT_REQ,
+	GPTP_PDELAY_RESP_WAIT_TSTAMP,
+} __packed;
+
+/* SyncReceive states. */
+enum gptp_sync_rcv_states {
+	GPTP_SYNC_RCV_DISCARD,
+	GPTP_SYNC_RCV_WAIT_SYNC,
+	GPTP_SYNC_RCV_WAIT_FOLLOW_UP,
+} __packed;
+
+/* SyncSend states. */
+enum gptp_sync_send_states {
+	GPTP_SYNC_SEND_INITIALIZING,
+	GPTP_SYNC_SEND_SEND_SYNC,
+	GPTP_SYNC_SEND_SEND_FUP,
+} __packed;
+
+/* PortSyncSyncReceive states. */
+enum gptp_pss_rcv_states {
+	GPTP_PSS_RCV_DISCARD,
+	GPTP_PSS_RCV_RECEIVED_SYNC,
+} __packed;
+
+/* PortSyncSyncSend states. */
+enum gptp_pss_send_states {
+	GPTP_PSS_SEND_TRANSMIT_INIT,
+	GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT,
+	GPTP_PSS_SEND_SEND_MD_SYNC,
+	GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT,
+} __packed;
+
+/* SiteSyncSyncReceive states. */
+enum gptp_site_sync_sync_states {
+	GPTP_SSS_INITIALIZING,
+	GPTP_SSS_RECEIVING_SYNC,
+} __packed;
+
+/* ClockSlaveSync states. */
+enum gptp_clk_slave_sync_states {
+	GPTP_CLK_SLAVE_SYNC_INITIALIZING,
+	GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND,
+} __packed;
+
+/* PortAnnounceReceive states. */
+enum gptp_pa_rcv_states {
+	GPTP_PA_RCV_DISCARD,
+	GPTP_PA_RCV_RECEIVE,
+} __packed;
+
+/* PortAnnounceInformation states. */
+enum gptp_pa_info_states {
+	GPTP_PA_INFO_DISABLED,
+	/* State to handle the transition after DISABLED state. */
+	GPTP_PA_INFO_POST_DISABLED,
+	GPTP_PA_INFO_AGED,
+	GPTP_PA_INFO_UPDATE,
+	GPTP_PA_INFO_CURRENT,
+	GPTP_PA_INFO_RECEIVE,
+	GPTP_PA_INFO_SUPERIOR_MASTER_PORT,
+	GPTP_PA_INFO_REPEATED_MASTER_PORT,
+	GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT,
+} __packed;
+
+/* PortRoleSelection states. */
+enum gptp_pr_selection_states {
+	GPTP_PR_SELECTION_INIT_BRIDGE,
+	GPTP_PR_SELECTION_ROLE_SELECTION,
+} __packed;
+
+/* PortAnnounceTransmit states. */
+enum gptp_pa_transmit_states {
+	GPTP_PA_TRANSMIT_INIT,
+	GPTP_PA_TRANSMIT_PERIODIC,
+	GPTP_PA_TRANSMIT_IDLE,
+	GPTP_PA_TRANSMIT_POST_IDLE,
+} __packed;
+
+/* ClockMasterSyncOffset states. */
+enum gptp_cms_offset_states {
+	GPTP_CMS_OFFSET_INITIALIZING,
+	GPTP_CMS_OFFSET_INDICATION,
+} __packed;
+
+/* ClockMasterSyncSend states. */
+enum gptp_cms_snd_states {
+	GPTP_CMS_SND_INITIALIZING,
+	GPTP_CMS_SND_INDICATION,
+} __packed;
+
+/* ClockMasterSyncReceive states. */
+enum gptp_cms_rcv_states {
+	GPTP_CMS_RCV_INITIALIZING,
+	GPTP_CMS_RCV_WAITING,
+	GPTP_CMS_RCV_SOURCE_TIME,
+} __packed;
+
+/* Info_is enumeration2. */
+enum gptp_info_is {
+	GPTP_INFO_IS_RECEIVED,
+	GPTP_INFO_IS_MINE,
+	GPTP_INFO_IS_AGED,
+	GPTP_INFO_IS_DISABLED,
+} __packed;
+
+enum gptp_time_source {
+	GPTP_TS_ATOMIC_CLOCK        = 0x10,
+	GPTP_TS_GPS                 = 0x20,
+	GPTP_TS_TERRESTRIAL_AUDIO   = 0x30,
+	GPTS_TS_PTP                 = 0x40,
+	GPTP_TS_NTP                 = 0x50,
+	GPTP_TS_HAND_SET            = 0x60,
+	GPTP_TS_OTHER               = 0x90,
+	GPTP_TS_INTERNAL_OSCILLATOR = 0xA0,
+} __packed;
+
+/**
+ * @brief gPTP time-synchronization spanning tree priority vector
+ *
+ * Defines the best master selection information.
+ */
+struct gptp_priority_vector {
+	/** Identity of the source clock. */
+	struct gptp_root_system_identity root_system_id;
+
+	/** Steps removed from the announce message transmitter and the
+	 * master clock. Note that this field must be right after
+	 * root_system_id as we are comparing root system id and steps
+	 * removed in one memcmp()
+	 */
+	uint16_t steps_removed;
+
+	/** Port identity of the transmitting time-aware system. */
+	struct gptp_port_identity src_port_id;
+
+	/** Port number of the receiving port. */
+	uint16_t port_number;
+} __packed;
+
+/* Pdelay Request state machine variables. */
+struct gptp_pdelay_req_state {
+	/** Initial Path Delay Response Peer Timestamp. */
+	uint64_t ini_resp_evt_tstamp;
+
+	/** Initial Path Delay Response Ingress Timestamp. */
+	uint64_t ini_resp_ingress_tstamp;
+
+	/** Timer for the Path Delay Request. */
+	struct k_timer pdelay_timer;
+
+	/** Pointer to the received Path Delay Response. */
+	struct net_pkt *rcvd_pdelay_resp_ptr;
+
+	/** Pointer to the received Path Delay Follow Up. */
+	struct net_pkt *rcvd_pdelay_follow_up_ptr;
+
+	/** Pointer to the Path Delay Request to be transmitted. */
+	struct net_pkt *tx_pdelay_req_ptr;
+
+	/** Path Delay Response messages received. */
+	uint32_t rcvd_pdelay_resp;
+
+	/** Path Delay Follow Up messages received. */
+	uint32_t rcvd_pdelay_follow_up;
+
+	/** Number of lost Path Delay Responses. */
+	uint16_t lost_responses;
+
+	/** Current state of the state machine. */
+	enum gptp_pdelay_req_states state;
+
+	/** Timer expired, a new Path Delay Request needs to be sent. */
+	bool pdelay_timer_expired;
+
+	/** NeighborRateRatio has been computed successfully. */
+	bool neighbor_rate_ratio_valid;
+
+	/** Path Delay has already been computed after initialization. */
+	bool init_pdelay_compute;
+
+	/** Count consecutive Pdelay_req with multiple responses. */
+	uint8_t multiple_resp_count;
+};
+
+/**
+ * @brief Pdelay Response state machine variables.
+ */
+struct gptp_pdelay_resp_state {
+	/** Current state of the state machine. */
+	enum gptp_pdelay_resp_states state;
+};
+
+/* SyncReceive state machine variables. */
+struct gptp_sync_rcv_state {
+	/** Time at which a Sync Message without Follow Up will be discarded. */
+	uint64_t follow_up_receipt_timeout;
+
+	/** Timer for the Follow Up discard. */
+	struct k_timer follow_up_discard_timer;
+
+	/** Pointer to the received Sync message. */
+	struct net_pkt *rcvd_sync_ptr;
+
+	/** Pointer to the received Follow Up message. */
+	struct net_pkt *rcvd_follow_up_ptr;
+
+	/** Current state of the state machine. */
+	enum gptp_sync_rcv_states state;
+
+	/** A Sync Message has been received. */
+	bool rcvd_sync;
+
+	/** A Follow Up Message has been received. */
+	bool rcvd_follow_up;
+
+	/** A Follow Up Message has been received. */
+	bool follow_up_timeout_expired;
+};
+
+/* SyncSend state machine variables. */
+struct gptp_sync_send_state {
+	/** Pointer to the received MDSyncSend structure. */
+	struct gptp_md_sync_info *sync_send_ptr;
+
+	/** Pointer to the sync message to be sent. */
+	struct net_pkt *sync_ptr;
+
+	/** Current state of the state machine. */
+	enum gptp_sync_send_states state;
+
+	/** A MDSyncSend structure has been received. */
+	bool rcvd_md_sync;
+
+	/** The timestamp for the sync message has been received. */
+	bool md_sync_timestamp_avail;
+};
+
+/* PortSyncSyncReceive state machine variables. */
+struct gptp_pss_rcv_state {
+	/** Sync receive provided by the MD Sync Receive State Machine. */
+	struct gptp_md_sync_info sync_rcv;
+
+	/** PortSyncSync structure to be transmitted to the Site Sync Sync. */
+	struct gptp_mi_port_sync_sync pss;
+
+	/** SyncReceiptTimeoutTimer for PortAnnounce state machines. */
+	struct k_timer rcv_sync_receipt_timeout_timer;
+
+	/** Ratio of the Grand Master frequency with the Local Clock. */
+	double rate_ratio;
+
+	/** Current state of the state machine. */
+	enum gptp_pss_rcv_states state;
+
+	/** A MDSyncReceive structure is ready to be processed. */
+	bool rcvd_md_sync;
+
+	/** Expiry of SyncReceiptTimeoutTimer. */
+	bool rcv_sync_receipt_timeout_timer_expired;
+};
+
+/* PortSyncSyncSend state machine variables. */
+struct gptp_pss_send_state {
+	/** Precise Origin Timestamp of the last received PortSyncSync. */
+	struct net_ptp_time last_precise_orig_ts;
+
+	/** Half Sync Interval Timer. */
+	struct k_timer half_sync_itv_timer;
+
+	/** syncReceiptTimeout Timer. */
+	struct k_timer send_sync_receipt_timeout_timer;
+
+	/** GM Phase Change of the last received PortSyncSync. */
+	struct gptp_scaled_ns last_gm_phase_change;
+
+	/** Follow Up Correction Field of the last received PortSyncSync. */
+	int64_t last_follow_up_correction_field;
+
+	/** Upstream Tx Time of the last received PortSyncSync. */
+	uint64_t last_upstream_tx_time;
+
+	/** PortSyncSync structure received from the SiteSyncSync. */
+	struct gptp_mi_port_sync_sync *pss_sync_ptr;
+
+	/** Rate Ratio of the last received PortSyncSync. */
+	double last_rate_ratio;
+
+	/** GM Freq Change of the last received PortSyncSync. */
+	double last_gm_freq_change;
+
+	/** Current state of the state machine. */
+	enum gptp_pss_send_states state;
+
+	/** GM Time Base Indicator of the last received PortSyncSync. */
+	uint16_t last_gm_time_base_indicator;
+
+	/** Received Port Number of the last received PortSyncSync. */
+	uint16_t last_rcvd_port_num;
+
+	/** Sync send to be transmitted to the MD Sync Send State Machine. */
+	struct gptp_md_sync_info sync_send;
+
+	/** A PortSyncSync structure is ready to be processed. */
+	bool rcvd_pss_sync;
+
+	/** Flag when the half_sync_itv_timer has expired. */
+	bool half_sync_itv_timer_expired;
+
+	/** Flag when the half_sync_itv_timer has expired twice. */
+	bool sync_itv_timer_expired;
+
+	/** Source Port Identity of the last received PortSyncSync. */
+	struct gptp_port_identity last_src_port_id;
+
+	/** Flag when the syncReceiptTimeoutTime has expired. */
+	bool send_sync_receipt_timeout_timer_expired;
+};
+
+/* SiteSyncSync state machine variables. */
+struct gptp_site_sync_sync_state {
+	/** PortSyncSync structure to be sent to other ports and to the Slave.
+	 */
+	struct gptp_mi_port_sync_sync pss_send;
+
+	/** Pointer to the PortSyncSync structure received. */
+	struct gptp_mi_port_sync_sync *pss_rcv_ptr;
+
+	/** Current state of the state machine. */
+	enum gptp_site_sync_sync_states state;
+
+	/** A PortSyncSync structure is ready to be processed. */
+	bool rcvd_pss;
+};
+
+/* ClockSlaveSync state machine variables. */
+struct gptp_clk_slave_sync_state {
+	/** Pointer to the PortSyncSync structure received. */
+	struct gptp_mi_port_sync_sync *pss_rcv_ptr;
+
+	/** Current state of the state machine. */
+	enum gptp_clk_slave_sync_states state;
+
+	/** A PortSyncSync structure is ready to be processed. */
+	bool rcvd_pss;
+
+	/** The local clock has expired. */
+	bool rcvd_local_clk_tick;
+};
+
+/* ClockMasterSyncOffset state machine variables. */
+struct gptp_clk_master_sync_offset_state {
+	/** Current state of the state machine. */
+	enum gptp_cms_offset_states state;
+
+	/** Notifies the state machine when Sync Receipt Time is received. */
+	bool rcvd_sync_receipt_time;
+};
+
+/* ClockMasterSyncSend state machine variables. */
+struct gptp_clk_master_sync_snd_state {
+	/** Time when synchronization info will be sent. */
+	struct gptp_uscaled_ns sync_send_time;
+
+	/** PortSyncSync structure transmitted by the state machine. */
+	struct gptp_mi_port_sync_sync pss_snd;
+
+	/** Current state of the state machine. */
+	enum gptp_cms_snd_states state;
+};
+
+/* ClockMasterSyncReceive state machine variables. */
+struct gptp_clk_master_sync_rcv_state {
+	/** The received ClockSourceTime.invoke parameters. Note that the
+	 * standard defines this as a pointer, but storing the struct here is
+	 * more convenient
+	 */
+	struct gptp_clk_src_time_invoke_params rcvd_clk_src_req;
+
+	/** Current state of the state machine */
+	enum gptp_cms_rcv_states state;
+
+	/** A ClockSourceTime.invoke function is received from the
+	 * Clock source entity
+	 */
+	bool rcvd_clock_source_req;
+
+	/** The local clock has expired */
+	bool rcvd_local_clock_tick;
+};
+
+/* PortAnnounceReceive state machine variables. */
+struct gptp_port_announce_receive_state {
+	/** Current state of the state machine. */
+	enum gptp_pa_rcv_states state;
+
+	/** An announce message is ready to be processed. */
+	bool rcvd_announce;
+};
+
+struct gptp_port_announce_information_state {
+	/** Timer for the announce expiry. */
+	struct k_timer ann_rcpt_expiry_timer;
+
+	/** PortRoleInformation state machine variables. */
+	enum gptp_pa_info_states state;
+
+	/* Expired announce information. */
+	bool ann_expired;
+};
+
+/* PortRoleSelection state machine variables. */
+struct gptp_port_role_selection_state {
+	enum gptp_pr_selection_states state;
+};
+
+/**
+ * @brief PortAnnounceTransmit state machine variables.
+ */
+struct gptp_port_announce_transmit_state {
+	/** Timer for the announce expiry. */
+	struct k_timer ann_send_periodic_timer;
+
+	/** PortRoleTransmit state machine variables. */
+	enum gptp_pa_transmit_states state;
+
+	/** Trigger announce information. */
+	bool ann_trigger;
+};
+
+/**
+ * @brief Structure maintaining per Time-Aware States.
+ */
+struct gptp_states {
+	/** SiteSyncSync state machine variables. */
+	struct gptp_site_sync_sync_state site_ss;
+
+	/** ClockSlaveSync state machine variables. */
+	struct gptp_clk_slave_sync_state clk_slave_sync;
+
+	/** PortRoleSelection state machine variables. */
+	struct gptp_port_role_selection_state pr_sel;
+
+	/** ClockMasterSyncOffset state machine variables. */
+	struct gptp_clk_master_sync_offset_state clk_master_sync_offset;
+
+	/** ClockMasterSyncSend state machine variables. */
+	struct gptp_clk_master_sync_snd_state clk_master_sync_send;
+
+	/** ClockMasterSyncReceive state machine variables. */
+	struct gptp_clk_master_sync_rcv_state clk_master_sync_receive;
+};
+
+/**
+ * @brief Structure maintaining per Port States.
+ */
+struct gptp_port_states {
+	/** PathDelayRequest state machine variables. */
+	struct gptp_pdelay_req_state pdelay_req;
+
+	/** SyncReceive state machine variables. */
+	struct gptp_sync_rcv_state sync_rcv;
+
+	/** SyncSend state machine variables. */
+	struct gptp_sync_send_state sync_send;
+
+	/** PortSyncSyncReceive state machine variables. */
+	struct gptp_pss_rcv_state pss_rcv;
+
+	/** PortSyncSync Send state machine variables. */
+	struct gptp_pss_send_state pss_send;
+
+	/** PortAnnounceInformation state machine variables. */
+	struct gptp_port_announce_information_state pa_info;
+
+	/** PortAnnounceTransmit state machine variables. */
+	struct gptp_port_announce_transmit_state pa_transmit;
+
+	/** PathDelayResponse state machine variables. */
+	struct gptp_pdelay_resp_state pdelay_resp;
+
+	/** PortAnnounceReceive state machine variables. */
+	struct gptp_port_announce_receive_state pa_rcv;
+};
+
+/**
+ * @brief Structure maintaining per port BMCA state machines variables.
+ */
+struct gptp_port_bmca_data {
+	/** Pointer to announce message. */
+	struct net_pkt *rcvd_announce_ptr;
+
+	/** The masterPriorityVector for the port. */
+	struct gptp_priority_vector master_priority;
+
+	/** The portPriorityVector for the port. */
+	struct gptp_priority_vector port_priority;
+
+	/** Announce interval. */
+	struct gptp_uscaled_ns announce_interval;
+
+	/** Announce receipt timeout time interval. */
+	struct gptp_uscaled_ns ann_rcpt_timeout_time_interval;
+
+	/** Origin and state of the port's spanning tree information. */
+	enum gptp_info_is info_is;
+
+	/** Last announce message time source. */
+	enum gptp_time_source ann_time_source;
+
+	/** Last announce message flags. */
+	struct gptp_flags ann_flags;
+
+	/** The value of steps removed for the port. */
+	uint16_t port_steps_removed;
+
+	/** The value of steps removed for the port. */
+	uint16_t message_steps_removed;
+
+	/** Last announce message current UTC offset value. */
+	int16_t ann_current_utc_offset;
+
+	/** A qualified announce message has been received. */
+	bool rcvd_msg;
+
+	/** Indicate if PortAnnounceInformation should copy the newly determined
+	 * master_prioriry and master_steps_removed.
+	 */
+	bool updt_info;
+
+	/** Cause a port to transmit Announce Information. */
+	bool new_info;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPTP_STATE_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_user_api.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_user_api.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/gptp/gptp_user_api.c	(working copy)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
+
+#include <ptp_clock.h>
+#include <net/gptp.h>
+
+#include "gptp_messages.h"
+#include "gptp_data_set.h"
+
+#include "net_private.h"
+
+static sys_slist_t phase_dis_callbacks;
+
+void gptp_register_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis,
+				gptp_phase_dis_callback_t cb)
+{
+	sys_slist_find_and_remove(&phase_dis_callbacks, &phase_dis->node);
+	sys_slist_prepend(&phase_dis_callbacks, &phase_dis->node);
+
+	phase_dis->cb = cb;
+}
+
+void gptp_unregister_phase_dis_cb(struct gptp_phase_dis_cb *phase_dis)
+{
+	sys_slist_find_and_remove(&phase_dis_callbacks, &phase_dis->node);
+}
+
+void gptp_call_phase_dis_cb(void)
+{
+	struct gptp_global_ds *global_ds;
+	sys_snode_t *sn, *sns;
+	uint8_t *gm_id;
+
+	global_ds = GPTP_GLOBAL_DS();
+	gm_id = &global_ds->gm_priority.root_system_id.grand_master_id[0];
+
+	SYS_SLIST_FOR_EACH_NODE_SAFE(&phase_dis_callbacks, sn, sns) {
+		struct gptp_phase_dis_cb *phase_dis =
+			CONTAINER_OF(sn, struct gptp_phase_dis_cb, node);
+
+		phase_dis->cb(gm_id,
+			      &global_ds->gm_time_base_indicator,
+			      &global_ds->clk_src_last_gm_phase_change,
+			      &global_ds->clk_src_last_gm_freq_change);
+	}
+}
+
+int gptp_event_capture(struct net_ptp_time *slave_time, bool *gm_present)
+{
+	int port, key;
+	const struct device *clk;
+
+	key = irq_lock();
+	*gm_present =  GPTP_GLOBAL_DS()->gm_present;
+
+	for (port = GPTP_PORT_START; port <= GPTP_PORT_END; port++) {
+		/* Get first available clock, or slave clock if GM present. */
+		if (!*gm_present || (GPTP_GLOBAL_DS()->selected_role[port] ==
+				     GPTP_PORT_SLAVE)) {
+			clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
+			if (clk) {
+				ptp_clock_get(clk, slave_time);
+				irq_unlock(key);
+				return 0;
+			}
+		}
+	}
+
+	irq_unlock(key);
+	return -EAGAIN;
+}
+
+char *gptp_sprint_clock_id(const uint8_t *clk_id, char *output, size_t output_len)
+{
+	return net_sprint_ll_addr_buf(clk_id, 8, output, output_len);
+}
+
+void gptp_clk_src_time_invoke(struct gptp_clk_src_time_invoke_params *arg)
+{
+	struct gptp_clk_master_sync_rcv_state *state;
+
+	state = &GPTP_STATE()->clk_master_sync_receive;
+
+	memcpy(&state->rcvd_clk_src_req, arg,
+	       sizeof(struct gptp_clk_src_time_invoke_params));
+
+	state->rcvd_clock_source_req = true;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/CMakeLists.txt	(working copy)
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+
+zephyr_library_sources(lldp.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/Kconfig	(working copy)
@@ -0,0 +1,191 @@
+# Copyright (c) 2017 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_LLDP
+	bool "Enable Link Layer Discovery Protocol (LLDP)"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	help
+	  Enable Link Layer Discovery Protocol (LLDP) Transmit support.
+	  Please refer to IEEE Std 802.1AB for more information.
+
+if NET_LLDP
+
+module = NET_LLDP
+module-dep = NET_LOG
+module-str = Log level for LLDP
+module-help = Enables core LLDP code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+#
+# LLDP Tx state machine config
+#
+config NET_LLDP_TX_INTERVAL
+	int "Time between transmissions in seconds (msgTxInterval)"
+	default 30
+	range 1 3600
+	help
+	  Interval between transmissions of LLDPDUs during normal
+	  (non-fast mode) transmission periods. For further information
+	  please refer to section 9.2.5.7 of the LLDP spec.
+
+config NET_LLDP_TX_HOLD
+	int "Multiplier of Tx Interval to result on Time to Live value"
+	default 4
+	range 1 100
+	help
+	  This value (msgTxHold) is used as a multiplier of
+	  CONFIG_NET_LLDP_TX_INTERVAL, to determine the value to be used
+	  as Time to Live in LLDP frames. For further information please
+	  refer to section 9.2.5.6 of the LLDP spec.
+
+#
+# End of LLDPDU TLV CONFIG
+#
+config NET_LLDP_END_LLDPDU_TLV_ENABLED
+	bool "Enable End of LLDPDU TLV"
+	default y
+	help
+	  Tells whether LLDPDU packet will have marker at the end of the packet.
+
+#
+# CHASSIS ID TLV CONFIG
+#
+config NET_LLDP_CHASSIS_ID_SUBTYPE
+	int "Chassis ID TLV subtype"
+	default 4
+	range 1 7
+	help
+	  Chassis ID subtype options are defined below.
+	  Please refer to section 8.5.2.2 of the 802.1AB for more info.
+	  Subtype 1 = Chassis component
+	  Subtype 2 = Interface alias
+	  Subtype 3 = Port component
+	  Subtype 4 = MAC address
+	  Subtype 5 = Network address
+	  Subtype 6 = Interface name
+	  Subtype 7 = Locally assigned
+	  If subtype 4 is selected, MAC address, then configs
+	  NET_LLDP_CHASSIS_ID_MAC0 through NET_LLDP_CHASSIS_ID_MAC5 must
+	  be defined, otherwise you must use NET_LLDP_CHASSIS_ID instead.
+
+if NET_LLDP_CHASSIS_ID_SUBTYPE = 4
+config NET_LLDP_CHASSIS_ID_MAC0
+	hex "Chassis ID MAC Address Byte 0"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 0 of the MAC address.
+
+config NET_LLDP_CHASSIS_ID_MAC1
+	hex "Chassis ID MAC Address Byte 1"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 1 of the MAC address.
+
+config NET_LLDP_CHASSIS_ID_MAC2
+	hex "Chassis ID MAC Address Byte 2"
+	default 0x5e
+	range 0 0xff
+	help
+	  Byte 2 of the MAC address.
+
+config NET_LLDP_CHASSIS_ID_MAC3
+	hex "Chassis ID MAC Address Byte 3"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 3 of the MAC address.
+
+config NET_LLDP_CHASSIS_ID_MAC4
+	hex "Chassis ID MAC Address Byte 4"
+	default 0x53
+	range 0 0xff
+	help
+	  Byte 4 of the MAC address.
+
+config NET_LLDP_CHASSIS_ID_MAC5
+	hex "Chassis ID MAC Address Byte 5"
+	default 0x8d
+	range 0 0xff
+	help
+	  Byte 5 of the MAC address.
+endif
+
+config NET_LLDP_CHASSIS_ID
+	string "Chassis ID value"
+	default "CHASSIS_ID_PLACEHOLDER"
+	depends on NET_LLDP_CHASSIS_ID_SUBTYPE != 4
+
+#
+# PORT ID TLV CONFIG
+#
+config NET_LLDP_PORT_ID_SUBTYPE
+	int "Port ID TLV subtype"
+	default 5
+	range 1 7
+	help
+	  Port ID subtype options are defined below.
+	  Please refer to section 8.5.3.2 of the 802.1AB for more info.
+	  Subtype 1 = Interface alias
+	  Subtype 2 = Port component
+	  Subtype 3 = MAC address
+	  Subtype 4 = Network address
+	  Subtype 5 = Interface name
+	  Subtype 6 = Agent circuit ID
+	  Subtype 7 = Locally assigned
+	  If subtype 3 is selected (MAC address) then configs
+	  NET_LLDP_PORT_ID_MAC0 through NET_LLDP_PORT_ID_MAC5 must
+	  be defined, otherwise you must use NET_LLDP_PORT_ID instead.
+
+if NET_LLDP_PORT_ID_SUBTYPE = 3
+config NET_LLDP_PORT_ID_MAC0
+	hex "Chassis ID MAC Address Byte 0"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 0 of the MAC address.
+
+config NET_LLDP_PORT_ID_MAC1
+	hex "Chassis ID MAC Address Byte 1"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 1 of the MAC address.
+
+config NET_LLDP_PORT_ID_MAC2
+	hex "Chassis ID MAC Address Byte 2"
+	default 0x5e
+	range 0 0xff
+	help
+	  Byte 2 of the MAC address.
+
+config NET_LLDP_PORT_ID_MAC3
+	hex "Chassis ID MAC Address Byte 3"
+	default 0x00
+	range 0 0xff
+	help
+	  Byte 3 of the MAC address.
+
+config NET_LLDP_PORT_ID_MAC4
+	hex "Chassis ID MAC Address Byte 4"
+	default 0x53
+	range 0 0xff
+	help
+	  Byte 4 of the MAC address.
+
+config NET_LLDP_PORT_ID_MAC5
+	hex "Chassis ID MAC Address Byte 5"
+	default 0x8d
+	range 0 0xff
+	help
+	  Byte 5 of the MAC address.
+endif
+
+config NET_LLDP_PORT_ID
+	string "Port ID value"
+	default "PORT_ID_PLACEHOLDER"
+	depends on NET_LLDP_PORT_ID_SUBTYPE != 3
+
+endif # NET_LLDP
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/lldp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/lldp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ethernet/lldp/lldp.c	(working copy)
@@ -0,0 +1,398 @@
+/** @file
+ * @brief LLDP related functions
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_lldp, CONFIG_NET_LLDP_LOG_LEVEL);
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <net/net_core.h>
+#include <net/ethernet.h>
+#include <net/net_mgmt.h>
+#include <net/lldp.h>
+
+static struct net_mgmt_event_callback cb;
+
+/* Have only one timer in order to save memory */
+static struct k_delayed_work lldp_tx_timer;
+
+/* Track currently active timers */
+static sys_slist_t lldp_ifaces;
+
+#define BUF_ALLOC_TIMEOUT K_MSEC(50)
+
+static int lldp_find(struct ethernet_context *ctx, struct net_if *iface)
+{
+	int i, found = -1;
+
+	for (i = 0; i < ARRAY_SIZE(ctx->lldp); i++) {
+		if (ctx->lldp[i].iface == iface) {
+			return i;
+		}
+
+		if (found < 0 && ctx->lldp[i].iface == NULL) {
+			found = i;
+		}
+	}
+
+	if (found >= 0) {
+		ctx->lldp[found].iface = iface;
+		return found;
+	}
+
+	return -ENOENT;
+}
+
+static void lldp_submit_work(uint32_t timeout)
+{
+	if (!k_delayed_work_remaining_get(&lldp_tx_timer) ||
+	    timeout < k_delayed_work_remaining_get(&lldp_tx_timer)) {
+		k_delayed_work_cancel(&lldp_tx_timer);
+		k_delayed_work_submit(&lldp_tx_timer, K_MSEC(timeout));
+
+		NET_DBG("Next wakeup in %d ms",
+			k_delayed_work_remaining_get(&lldp_tx_timer));
+	}
+}
+
+static bool lldp_check_timeout(int64_t start, uint32_t time, int64_t timeout)
+{
+	start += time;
+	start = abs(start);
+
+	if (start > timeout) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool lldp_timedout(struct ethernet_lldp *lldp, int64_t timeout)
+{
+	return lldp_check_timeout(lldp->tx_timer_start,
+				  lldp->tx_timer_timeout,
+				  timeout);
+}
+
+static int lldp_send(struct ethernet_lldp *lldp)
+{
+	static const struct net_eth_addr lldp_multicast_eth_addr = {
+		{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
+	};
+	int ret = 0;
+	struct net_pkt *pkt;
+	size_t len;
+
+	if (!lldp->lldpdu) {
+		/* The ethernet driver has not set the lldpdu pointer */
+		NET_DBG("The LLDPDU is not set for lldp %p", lldp);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (lldp->optional_du && lldp->optional_len) {
+		len = sizeof(struct net_lldpdu) + lldp->optional_len;
+	} else {
+		len = sizeof(struct net_lldpdu);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_LLDP_END_LLDPDU_TLV_ENABLED)) {
+		len += sizeof(uint16_t);
+	}
+
+	pkt = net_pkt_alloc_with_buffer(lldp->iface, len, AF_UNSPEC, 0,
+					BUF_ALLOC_TIMEOUT);
+	if (!pkt) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	net_pkt_set_lldp(pkt, true);
+
+	ret = net_pkt_write(pkt, (uint8_t *)lldp->lldpdu,
+			    sizeof(struct net_lldpdu));
+	if (ret < 0) {
+		net_pkt_unref(pkt);
+		goto out;
+	}
+
+	if (lldp->optional_du && lldp->optional_len) {
+		ret = net_pkt_write(pkt, (uint8_t *)lldp->optional_du,
+				    lldp->optional_len);
+		if (ret < 0) {
+			net_pkt_unref(pkt);
+			goto out;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_NET_LLDP_END_LLDPDU_TLV_ENABLED)) {
+		uint16_t tlv_end = htons(NET_LLDP_END_LLDPDU_VALUE);
+
+		ret = net_pkt_write(pkt, (uint8_t *)&tlv_end, sizeof(tlv_end));
+		if (ret < 0) {
+			net_pkt_unref(pkt);
+			goto out;
+		}
+	}
+
+	net_pkt_lladdr_src(pkt)->addr = net_if_get_link_addr(lldp->iface)->addr;
+	net_pkt_lladdr_src(pkt)->len = sizeof(struct net_eth_addr);
+	net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)lldp_multicast_eth_addr.addr;
+	net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
+
+	if (net_if_send_data(lldp->iface, pkt) == NET_DROP) {
+		net_pkt_unref(pkt);
+		ret = -EIO;
+	}
+
+out:
+	lldp->tx_timer_start = k_uptime_get();
+
+	return ret;
+}
+
+static uint32_t lldp_manage_timeouts(struct ethernet_lldp *lldp, int64_t timeout)
+{
+	int32_t next_timeout;
+
+	if (lldp_timedout(lldp, timeout)) {
+		lldp_send(lldp);
+	}
+
+	next_timeout = timeout - (lldp->tx_timer_start +
+				  lldp->tx_timer_timeout);
+
+	return abs(next_timeout);
+}
+
+static void lldp_tx_timeout(struct k_work *work)
+{
+	uint32_t timeout_update = UINT32_MAX - 1;
+	int64_t timeout = k_uptime_get();
+	struct ethernet_lldp *current, *next;
+
+	ARG_UNUSED(work);
+
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&lldp_ifaces, current, next, node) {
+		uint32_t next_timeout;
+
+		next_timeout = lldp_manage_timeouts(current, timeout);
+		if (next_timeout < timeout_update) {
+			timeout_update = next_timeout;
+		}
+	}
+
+	if (timeout_update < (UINT32_MAX - 1)) {
+		NET_DBG("Waiting for %u ms", timeout_update);
+
+		k_delayed_work_submit(&lldp_tx_timer, K_MSEC(timeout_update));
+	}
+}
+
+static void lldp_start_timer(struct ethernet_context *ctx,
+			     struct net_if *iface,
+			     int slot)
+{
+	ctx->lldp[slot].iface = iface;
+
+	sys_slist_append(&lldp_ifaces, &ctx->lldp[slot].node);
+
+	ctx->lldp[slot].tx_timer_start = k_uptime_get();
+	ctx->lldp[slot].tx_timer_timeout =
+				CONFIG_NET_LLDP_TX_INTERVAL * MSEC_PER_SEC;
+
+	lldp_submit_work(ctx->lldp[slot].tx_timer_timeout);
+}
+
+static int lldp_check_iface(struct net_if *iface)
+{
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
+		return -ENOENT;
+	}
+
+	if (!(net_eth_get_hw_capabilities(iface) & ETHERNET_LLDP)) {
+		return -ESRCH;
+	}
+
+	return 0;
+}
+
+static int lldp_start(struct net_if *iface, uint32_t mgmt_event)
+{
+	struct ethernet_context *ctx;
+	int ret, slot;
+
+	ret = lldp_check_iface(iface);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ctx = net_if_l2_data(iface);
+
+	ret = lldp_find(ctx, iface);
+	if (ret < 0) {
+		return ret;
+	}
+
+	slot = ret;
+
+	if (mgmt_event == NET_EVENT_IF_DOWN) {
+		sys_slist_find_and_remove(&lldp_ifaces,
+					  &ctx->lldp[slot].node);
+
+		if (sys_slist_is_empty(&lldp_ifaces)) {
+			k_delayed_work_cancel(&lldp_tx_timer);
+		}
+	} else if (mgmt_event == NET_EVENT_IF_UP) {
+		NET_DBG("Starting timer for iface %p", iface);
+		lldp_start_timer(ctx, iface, slot);
+	}
+
+	return 0;
+}
+
+enum net_verdict net_lldp_recv(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct ethernet_context *ctx;
+	net_lldp_recv_cb_t cb;
+	int ret;
+
+	ret = lldp_check_iface(iface);
+	if (ret < 0) {
+		return NET_DROP;
+	}
+
+	ctx = net_if_l2_data(iface);
+
+	ret = lldp_find(ctx, iface);
+	if (ret < 0) {
+		return NET_DROP;
+	}
+
+	cb = ctx->lldp[ret].cb;
+	if (cb) {
+		return cb(iface, pkt);
+	}
+
+	return NET_DROP;
+}
+
+int net_lldp_register_callback(struct net_if *iface, net_lldp_recv_cb_t cb)
+{
+	struct ethernet_context *ctx;
+	int ret;
+
+	ret = lldp_check_iface(iface);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ctx = net_if_l2_data(iface);
+
+	ret = lldp_find(ctx, iface);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ctx->lldp[ret].cb = cb;
+
+	return 0;
+}
+
+static void iface_event_handler(struct net_mgmt_event_callback *cb,
+				uint32_t mgmt_event, struct net_if *iface)
+{
+	lldp_start(iface, mgmt_event);
+}
+
+static void iface_cb(struct net_if *iface, void *user_data)
+{
+	/* If the network interface is already up, then call the sender
+	 * immediately. If the interface is not ethernet one, then
+	 * lldp_start() will return immediately.
+	 */
+	if (net_if_flag_is_set(iface, NET_IF_UP)) {
+		lldp_start(iface, NET_EVENT_IF_UP);
+	}
+}
+
+int net_lldp_config(struct net_if *iface, const struct net_lldpdu *lldpdu)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	int i;
+
+	i = lldp_find(ctx, iface);
+	if (i < 0) {
+		return i;
+	}
+
+	ctx->lldp[i].lldpdu = lldpdu;
+
+	return 0;
+}
+
+int net_lldp_config_optional(struct net_if *iface, const uint8_t *tlv, size_t len)
+{
+	struct ethernet_context *ctx = net_if_l2_data(iface);
+	int i;
+
+	i = lldp_find(ctx, iface);
+	if (i < 0) {
+		return i;
+	}
+
+	ctx->lldp[i].optional_du = tlv;
+	ctx->lldp[i].optional_len = len;
+
+	return 0;
+}
+
+static const struct net_lldpdu lldpdu = {
+	.chassis_id = {
+		.type_length = htons((LLDP_TLV_CHASSIS_ID << 9) |
+			NET_LLDP_CHASSIS_ID_TLV_LEN),
+		.subtype = CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE,
+		.value = NET_LLDP_CHASSIS_ID_VALUE
+	},
+	.port_id = {
+		.type_length = htons((LLDP_TLV_PORT_ID << 9) |
+			NET_LLDP_PORT_ID_TLV_LEN),
+		.subtype = CONFIG_NET_LLDP_PORT_ID_SUBTYPE,
+		.value = NET_LLDP_PORT_ID_VALUE
+	},
+	.ttl = {
+		.type_length = htons((LLDP_TLV_TTL << 9) |
+			NET_LLDP_TTL_TLV_LEN),
+		.ttl = htons(NET_LLDP_TTL)
+	},
+};
+
+int net_lldp_set_lldpdu(struct net_if *iface)
+{
+	return net_lldp_config(iface, &lldpdu);
+}
+
+void net_lldp_unset_lldpdu(struct net_if *iface)
+{
+	net_lldp_config(iface, NULL);
+	net_lldp_config_optional(iface, NULL, 0);
+}
+
+void net_lldp_init(void)
+{
+	k_delayed_work_init(&lldp_tx_timer, lldp_tx_timeout);
+
+	net_if_foreach(iface_cb, NULL);
+
+	net_mgmt_init_event_callback(&cb, iface_event_handler,
+				     NET_EVENT_IF_UP | NET_EVENT_IF_DOWN);
+	net_mgmt_add_event_callback(&cb);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/CMakeLists.txt	(working copy)
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources(
+  ieee802154.c
+  ieee802154_frame.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_FRAGMENT
+  ieee802154_fragment.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_MGMT
+  ieee802154_mgmt.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_RADIO_ALOHA
+  ieee802154_radio_aloha.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA
+  ieee802154_radio_csma_ca.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_SECURITY
+  ieee802154_security.c
+  )
+
+zephyr_library_sources_ifdef(
+  CONFIG_NET_L2_IEEE802154_SHELL
+  ieee802154_shell.c
+  )
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig	(working copy)
@@ -0,0 +1,133 @@
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_L2_IEEE802154
+	bool "Enable IEEE 802.15.4 Radio"
+	help
+	  Add support for low rate WPAN IEEE 802.15.4 technology.
+
+if NET_L2_IEEE802154
+
+config NET_L2_IEEE802154_MGMT
+	bool
+	select NET_MGMT
+	select NET_MGMT_EVENT
+
+config NET_L2_IEEE802154_SUB_GHZ
+	bool
+	help
+	  Enable support for Sub-GHz devices. This will add a tiny bit more
+	  logic in L2 code for channel management. This option is automatically
+	  selected when relevant device driver is enabled.
+
+module = NET_L2_IEEE802154
+module-dep = NET_LOG
+module-str = Log level for IEEE 802.15.4
+module-help = Enables IEEE 802.15.4 code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET
+	bool "Enable IEEE 802.15.4 packet display"
+	depends on NET_LOG
+	help
+	  Enable printing out in/out 802.15.4 packets. This is extremely
+	  verbose, do not enable this unless you know what you are doing.
+
+choice
+	prompt "Which packet do you want to print-out?"
+	default NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_FULL
+	depends on NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET
+
+config NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_FULL
+	bool "Print-out both RX and TX packets"
+	help
+	  This will print-out both received and transmitted packets.
+
+config NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_RX
+	bool "Print-out only RX packets"
+	help
+	  This will print-out received packets only.
+
+config NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_TX
+	bool "Print-out only TX packets"
+	help
+	  This will print-out transmitted packets only.
+
+endchoice
+
+config NET_L2_IEEE802154_ACK_REPLY
+	bool "Enable IEEE 802.15.4 ACK reply logic"
+	help
+	  Enable inner stack's logic on handling ACK request. Note that
+	  if the hw driver has an AUTOACK feature, this is then unnecessary.
+
+choice
+	prompt "Device features level support"
+	default NET_L2_IEEE802154_RFD
+	help
+	  Select which features level you want on the device. Depending on it,
+	  the device might expose more or less 802.15.4 protocol features.
+	  Only RFD is supported for now.
+
+config NET_L2_IEEE802154_RFD
+	bool "Support Reduced Functionality Device level"
+	select NET_L2_IEEE802154_MGMT
+	help
+	  This is the level for PAN device, not PAN coordinator. This will make
+	  possible to do active and/or passive scans, as well as associating
+	  and disassociating to/from a PAN. Current support is very fragile,
+	  thus it is not set as the default level.
+endchoice
+
+config NET_L2_IEEE802154_SHELL
+	bool "Enable IEEE 802.15.4 shell module"
+	select SHELL
+	depends on NET_L2_IEEE802154_RFD
+	help
+	  This can be used for testing 15.4 through the console via exposing
+	  a shell module named "ieee15_4".
+
+config NET_L2_IEEE802154_FRAGMENT
+	bool "Enable 802.15.4 fragmentation support"
+	default y
+	depends on NET_6LO
+	help
+	  If IPv6 packets size more than 802.15.4 MTU, packet is fragmented
+	  and reassemble incoming packets according to RFC4944/6282.
+
+config NET_L2_IEEE802154_FRAGMENT_REASS_CACHE_SIZE
+	int "IEEE 802.15.4 Reassembly cache size"
+	depends on NET_L2_IEEE802154_FRAGMENT
+	default 1
+	help
+	  Simultaneously reassemble 802.15.4 fragments depending on
+	  cache size.
+
+config NET_L2_IEEE802154_REASSEMBLY_TIMEOUT
+	int "IEEE 802.15.4 Reassembly timeout in seconds"
+	depends on NET_L2_IEEE802154_FRAGMENT
+	default 5
+	range 1 60
+	help
+	  Reassembly timer will start as soon as first packet received
+	  from peer. Reassembly should be finished within a given time.
+	  Otherwise all accumulated fragments are dropped.
+
+config NET_L2_IEEE802154_SECURITY
+	bool "Enable IEEE 802.15.4 security [EXPERIMENTAL]"
+	help
+	  Enable 802.15.4 frame security handling, in order to bring data
+	  confidentiality and authenticity.
+
+config NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME
+	string "Crypto device name used for <en/de>cryption"
+	default ""
+	depends on NET_L2_IEEE802154_SECURITY
+	help
+	  This option should be used to set the crypto device name that
+	  IEEE 802.15.4 soft MAC will use to run authentication, encryption and
+	  decryption operations on incoming/outgoing frames.
+
+source "subsys/net/l2/ieee802154/Kconfig.radio"
+
+endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig.radio
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig.radio	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/Kconfig.radio	(working copy)
@@ -0,0 +1,70 @@
+# Copyright (c) 2016 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menu "IEEE 802.15.4 Radio"
+
+config NET_L2_IEEE802154_RADIO_DFLT_TX_POWER
+	int "Default radio transmission power"
+	default 0
+	help
+	  TX power in dbm. Valid setting are: -18, -7, -4, -2, 0, 1, 2, 3, 5
+	  If wrongly set, it will silently fail.
+
+config NET_L2_IEEE802154_RADIO_TX_RETRIES
+	int "Radio Transmission attempts"
+	default 3
+	range 1 7
+	help
+	  Number of transmission attempts radio driver should do, before
+	  replying it could not send the packet.
+
+choice
+	prompt "Radio protocol"
+	default NET_L2_IEEE802154_RADIO_CSMA_CA
+	help
+	  Select which radio protocol to use.
+
+config NET_L2_IEEE802154_RADIO_CSMA_CA
+	bool "IEEE 802.15.4 CSMA-CA radio protocol"
+	help
+	  Use CSMA-CA mechanism to transmit packets. This is the most common
+	  way of transmitting packets and fits most of all the usage.
+	  At least until the version 2011 of the specification.
+
+config NET_L2_IEEE802154_RADIO_ALOHA
+	bool "IEEE 802.15.4 Aloha radio protocol"
+	help
+	  Use Aloha mechanism to transmit packets. This is a simplistic
+	  way of transmitting packets and fits contexts where radio spectrum
+	  is not too heavily loaded.
+endchoice
+
+if NET_L2_IEEE802154_RADIO_CSMA_CA
+
+config NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO
+	int "CSMA maximum backoffs"
+	default 4
+	range 1 5
+	help
+	  The maximum number of backoffs the CSMA-CA algorithm will attempt
+	  before declaring a channel access failure.
+
+config NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE
+	int "CSMA MAC minimum backoff exponent"
+	default 3
+	range 1 8
+	help
+	  The minimum value of the backoff exponent (BE) in the CSMA-CA
+	  algorithm.
+
+config NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BE
+	int "CSMA MAC maximum backoff exponent"
+	default 5
+	range 1 8
+	help
+	  The maximum value of the backoff exponent (BE) in the CSMA-CA
+	  algorithm.
+
+endif # NET_L2_IEEE802154_RADIO_CSMA_CA
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154.c	(working copy)
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+
+#include "ipv6.h"
+
+#include <errno.h>
+
+#include "ieee802154_fragment.h"
+#include <6lo.h>
+
+#include <net/ieee802154_radio.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_mgmt_priv.h"
+#include "ieee802154_security.h"
+#include "ieee802154_utils.h"
+#include "ieee802154_radio_utils.h"
+
+#define BUF_TIMEOUT K_MSEC(50)
+
+/* No need to hold space for the FCS */
+static uint8_t frame_buffer_data[IEEE802154_MTU - 2];
+
+static struct net_buf frame_buf = {
+	.data = frame_buffer_data,
+	.size = IEEE802154_MTU - 2,
+	.frags = NULL,
+	.__buf = frame_buffer_data,
+};
+
+#define PKT_TITLE      "IEEE 802.15.4 packet content:"
+#define TX_PKT_TITLE   "> " PKT_TITLE
+#define RX_PKT_TITLE   "< " PKT_TITLE
+
+#ifdef CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET
+
+#include "net_private.h"
+
+static inline void pkt_hexdump(const char *title, struct net_pkt *pkt,
+			       bool in)
+{
+	if (IS_ENABLED(CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_RX) &&
+	    in) {
+		net_pkt_hexdump(pkt, title);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET_TX) &&
+	    !in) {
+		net_pkt_hexdump(pkt, title);
+	}
+}
+
+#else
+#define pkt_hexdump(...)
+#endif /* CONFIG_NET_DEBUG_L2_IEEE802154_DISPLAY_PACKET */
+
+#ifdef CONFIG_NET_L2_IEEE802154_ACK_REPLY
+static inline void ieee802154_acknowledge(struct net_if *iface,
+					  struct ieee802154_mpdu *mpdu)
+{
+	struct net_pkt *pkt;
+
+	if (!mpdu->mhr.fs->fc.ar) {
+		return;
+	}
+
+	pkt = net_pkt_alloc_with_buffer(iface, IEEE802154_ACK_PKT_LENGTH,
+					AF_UNSPEC, 0, BUF_TIMEOUT);
+	if (!pkt) {
+		return;
+	}
+
+	if (ieee802154_create_ack_frame(iface, pkt, mpdu->mhr.fs->sequence)) {
+		ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
+			      pkt, pkt->buffer);
+	}
+
+	net_pkt_unref(pkt);
+
+	return;
+}
+#else
+#define ieee802154_acknowledge(...)
+#endif /* CONFIG_NET_L2_IEEE802154_ACK_REPLY */
+
+static inline void set_pkt_ll_addr(struct net_linkaddr *addr, bool comp,
+				   enum ieee802154_addressing_mode mode,
+				   struct ieee802154_address_field *ll)
+{
+	if (mode == IEEE802154_ADDR_MODE_NONE) {
+		return;
+	}
+
+	if (mode == IEEE802154_ADDR_MODE_EXTENDED) {
+		addr->len = IEEE802154_EXT_ADDR_LENGTH;
+
+		if (comp) {
+			addr->addr = ll->comp.addr.ext_addr;
+		} else {
+			addr->addr = ll->plain.addr.ext_addr;
+		}
+	} else {
+		/* ToDo: Handle short address (lookup known nbr, ...) */
+		addr->len = 0U;
+		addr->addr = NULL;
+	}
+
+	addr->type = NET_LINK_IEEE802154;
+}
+
+#ifdef CONFIG_NET_6LO
+static inline
+enum net_verdict ieee802154_manage_recv_packet(struct net_if *iface,
+					       struct net_pkt *pkt,
+					       size_t hdr_len)
+{
+	enum net_verdict verdict = NET_CONTINUE;
+	uint32_t src;
+	uint32_t dst;
+
+	/* Upper IP stack expects the link layer address to be in
+	 * big endian format so we must swap it here.
+	 */
+	if (net_pkt_lladdr_src(pkt)->addr &&
+	    net_pkt_lladdr_src(pkt)->len == IEEE802154_EXT_ADDR_LENGTH) {
+		sys_mem_swap(net_pkt_lladdr_src(pkt)->addr,
+			     net_pkt_lladdr_src(pkt)->len);
+	}
+
+	if (net_pkt_lladdr_dst(pkt)->addr &&
+	    net_pkt_lladdr_dst(pkt)->len == IEEE802154_EXT_ADDR_LENGTH) {
+		sys_mem_swap(net_pkt_lladdr_dst(pkt)->addr,
+			     net_pkt_lladdr_dst(pkt)->len);
+	}
+
+	/** Uncompress will drop the current fragment. Pkt ll src/dst address
+	 * will then be wrong and must be updated according to the new fragment.
+	 */
+	src = net_pkt_lladdr_src(pkt)->addr ?
+		net_pkt_lladdr_src(pkt)->addr -
+		(net_pkt_data(pkt) - hdr_len) : 0;
+	dst = net_pkt_lladdr_dst(pkt)->addr ?
+		net_pkt_lladdr_dst(pkt)->addr -
+		(net_pkt_data(pkt) - hdr_len) : 0;
+
+#ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
+	verdict = ieee802154_reassemble(pkt);
+	if (verdict != NET_CONTINUE) {
+		goto out;
+	}
+#else
+	if (!net_6lo_uncompress(pkt)) {
+		NET_DBG("Packet decompression failed");
+		verdict = NET_DROP;
+		goto out;
+	}
+#endif
+	net_pkt_lladdr_src(pkt)->addr = src ?
+		(net_pkt_data(pkt) - hdr_len) + src : NULL;
+	net_pkt_lladdr_dst(pkt)->addr = dst ?
+		(net_pkt_data(pkt) - hdr_len) + dst : NULL;
+
+	pkt_hexdump(RX_PKT_TITLE, pkt, true);
+out:
+	return verdict;
+}
+#else /* CONFIG_NET_6LO */
+#define ieee802154_manage_recv_packet(...) NET_CONTINUE
+#endif /* CONFIG_NET_6LO */
+
+static enum net_verdict ieee802154_recv(struct net_if *iface,
+					struct net_pkt *pkt)
+{
+	struct ieee802154_mpdu mpdu;
+	size_t hdr_len;
+
+	if (!ieee802154_validate_frame(net_pkt_data(pkt),
+				       net_pkt_get_len(pkt), &mpdu)) {
+		return NET_DROP;
+	}
+
+	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
+		return ieee802154_handle_beacon(iface, &mpdu,
+						net_pkt_ieee802154_lqi(pkt));
+	}
+
+	if (ieee802154_is_scanning(iface)) {
+		return NET_DROP;
+	}
+
+	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) {
+		return ieee802154_handle_mac_command(iface, &mpdu);
+	}
+
+	/* At this point the frame has to be a DATA one */
+
+	ieee802154_acknowledge(iface, &mpdu);
+
+	set_pkt_ll_addr(net_pkt_lladdr_src(pkt), mpdu.mhr.fs->fc.pan_id_comp,
+			mpdu.mhr.fs->fc.src_addr_mode, mpdu.mhr.src_addr);
+
+	set_pkt_ll_addr(net_pkt_lladdr_dst(pkt), false,
+			mpdu.mhr.fs->fc.dst_addr_mode, mpdu.mhr.dst_addr);
+
+	if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) {
+		return NET_DROP;
+	}
+
+	pkt_hexdump(RX_PKT_TITLE " (with ll)", pkt, true);
+
+	hdr_len = (uint8_t *)mpdu.payload - net_pkt_data(pkt);
+	net_buf_pull(pkt->buffer, hdr_len);
+
+	return ieee802154_manage_recv_packet(iface, pkt, hdr_len);
+
+}
+
+static int ieee802154_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_fragment_ctx f_ctx;
+	struct net_buf *buf;
+	uint8_t ll_hdr_size;
+	bool fragment;
+	int len;
+
+	if (net_pkt_family(pkt) != AF_INET6) {
+		return -EINVAL;
+	}
+
+	ll_hdr_size = ieee802154_compute_header_size(iface,
+						     &NET_IPV6_HDR(pkt)->dst);
+
+	/* len will hold the hdr size difference on success */
+	len = net_6lo_compress(pkt, true);
+	if (len < 0) {
+		return len;
+	}
+
+	fragment = ieee802154_fragment_is_needed(pkt, ll_hdr_size);
+	ieee802154_fragment_ctx_init(&f_ctx, pkt, len, true);
+
+	len = 0;
+	frame_buf.len = 0U;
+	buf = pkt->buffer;
+
+	while (buf) {
+		int ret;
+
+		net_buf_add(&frame_buf, ll_hdr_size);
+
+		if (fragment) {
+			ieee802154_fragment(&f_ctx, &frame_buf, true);
+			buf = f_ctx.buf;
+		} else {
+			memcpy(frame_buf.data + frame_buf.len,
+			       buf->data, buf->len);
+			net_buf_add(&frame_buf, buf->len);
+			buf = buf->frags;
+		}
+
+		if (!ieee802154_create_data_frame(ctx, net_pkt_lladdr_dst(pkt),
+						  &frame_buf, ll_hdr_size)) {
+			return -EINVAL;
+		}
+
+		if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
+		    ieee802154_get_hw_capabilities(iface) &
+		    IEEE802154_HW_CSMA) {
+			ret = ieee802154_tx(iface, IEEE802154_TX_MODE_CSMA_CA,
+					    pkt, &frame_buf);
+		} else {
+			ret = ieee802154_radio_send(iface, pkt, &frame_buf);
+		}
+
+		if (ret) {
+			return ret;
+		}
+
+		len += frame_buf.len;
+
+		/* Reinitializing frame_buf */
+		frame_buf.len = 0U;
+	}
+
+	net_pkt_unref(pkt);
+
+	return len;
+}
+
+static int ieee802154_enable(struct net_if *iface, bool state)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	NET_DBG("iface %p %s", iface, state ? "up" : "down");
+
+	if (ctx->channel == IEEE802154_NO_CHANNEL) {
+		return -ENETDOWN;
+	}
+
+	if (state) {
+		return ieee802154_start(iface);
+	}
+
+	return ieee802154_stop(iface);
+}
+
+enum net_l2_flags ieee802154_flags(struct net_if *iface)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	return ctx->flags;
+}
+
+NET_L2_INIT(IEEE802154_L2,
+	    ieee802154_recv, ieee802154_send,
+	    ieee802154_enable, ieee802154_flags);
+
+void ieee802154_init(struct net_if *iface)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	const uint8_t *mac = net_if_get_link_addr(iface)->addr;
+	int16_t tx_power = CONFIG_NET_L2_IEEE802154_RADIO_DFLT_TX_POWER;
+	uint8_t long_addr[8];
+
+	NET_DBG("Initializing IEEE 802.15.4 stack on iface %p", iface);
+
+	ctx->channel = IEEE802154_NO_CHANNEL;
+	ctx->flags = NET_L2_MULTICAST;
+
+	if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) {
+		LOG_DBG("Interface auto start disabled.");
+		net_if_flag_set(iface, NET_IF_NO_AUTO_START);
+	}
+
+	ieee802154_mgmt_init(iface);
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (ieee802154_security_init(&ctx->sec_ctx)) {
+		NET_ERR("Initializing link-layer security failed");
+	}
+#endif
+
+	sys_memcpy_swap(long_addr, mac, 8);
+	memcpy(ctx->ext_addr, long_addr, 8);
+	ieee802154_filter_ieee_addr(iface, ctx->ext_addr);
+
+	if (!ieee802154_set_tx_power(iface, tx_power)) {
+		ctx->tx_power = tx_power;
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.h	(working copy)
@@ -0,0 +1,93 @@
+/** @file
+ @brief 802.15.4 fragment handler
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __NET_IEEE802154_FRAGMENT_H__
+#define __NET_IEEE802154_FRAGMENT_H__
+
+#include <sys/slist.h>
+#include <zephyr/types.h>
+
+#include <net/net_pkt.h>
+
+#include "ieee802154_frame.h"
+
+struct ieee802154_fragment_ctx {
+	struct net_buf *buf;
+	uint8_t *pos;
+	uint16_t pkt_size;
+	uint16_t processed;
+	uint8_t hdr_diff;
+	uint8_t offset;
+};
+
+static inline bool ieee802154_fragment_is_needed(struct net_pkt *pkt,
+						 uint8_t ll_hdr_size)
+{
+	return (net_pkt_get_len(pkt) + ll_hdr_size >
+			IEEE802154_MTU - IEEE802154_MFR_LENGTH);
+}
+
+static inline
+void ieee802154_fragment_ctx_init(struct ieee802154_fragment_ctx *ctx,
+				  struct net_pkt *pkt, uint16_t hdr_diff,
+				  bool iphc)
+{
+	ctx->buf = pkt->buffer;
+	ctx->pos = ctx->buf->data;
+	ctx->hdr_diff = hdr_diff;
+	ctx->pkt_size = net_pkt_get_len(pkt) + (iphc ? hdr_diff : -1);
+	ctx->offset = 0U;
+	ctx->processed = 0U;
+}
+
+/**
+ *  @brief Fragment IPv6 packet as per RFC 6282
+ *
+ *  @details After IPv6 compression, transmission of IPv6 over 802.15.4
+ *  needs to be fragmented. Every fragment will have fragmentation header
+ *  data size, data offset, data tag and payload.
+ *
+ *  @param Pointer to valid fragmentation context
+ *  @param Pointer to valid buffer where to write the fragment
+ *  @param bool true for IPHC compression, false for IPv6 dispatch header
+ *
+ *  @return True in case of success, false otherwise
+ */
+#ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
+void ieee802154_fragment(struct ieee802154_fragment_ctx *ctx,
+			 struct net_buf *frame_buf, bool iphc);
+#else
+#define ieee802154_fragment(...)
+#endif
+
+/**
+ *  @brief Reassemble 802.15.4 fragments as per RFC 6282
+ *
+ *  @details If the data does not fit into single fragment whole IPv6 packet
+ *  comes in number of fragments. This function will reassemble them all as
+ *  per data tag, data offset and data size. First packet is uncompressed
+ *  immediately after reception.
+ *
+ *  @param Pointer to network fragment, which gets updated to full reassembled
+ *         packet when verdict is NET_CONTINUE
+ *
+ *  @return NET_CONTINUE reassembly done, pkt is complete
+ *          NET_OK waiting for other fragments,
+ *          NET_DROP invalid fragment.
+ */
+#ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
+enum net_verdict ieee802154_reassemble(struct net_pkt *pkt);
+#else
+#define ieee802154_reassemble(...)
+#endif /* CONFIG_NET_L2_IEEE802154_FRAGMENT */
+
+#endif /* __NET_IEEE802154_FRAGMENT_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_fragment.c	(working copy)
@@ -0,0 +1,573 @@
+/** @file
+ * @brief 802.15.4 fragment related functions
+ */
+
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_fragment,
+		    CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_if.h>
+#include <net/net_stats.h>
+#include <net/udp.h>
+
+#include "ieee802154_fragment.h"
+
+#include "net_private.h"
+#include "6lo.h"
+#include "6lo_private.h"
+
+#define NET_FRAG_DISPATCH_MASK	0xF8
+#define NET_FRAG_OFFSET_POS	(NET_6LO_FRAG_DATAGRAM_SIZE_LEN +	\
+				 NET_6LO_FRAG_DATAGRAM_OFFSET_LEN)
+
+#define BUF_TIMEOUT K_MSEC(50)
+
+#define FRAG_REASSEMBLY_TIMEOUT \
+	K_SECONDS(CONFIG_NET_L2_IEEE802154_REASSEMBLY_TIMEOUT)
+#define REASS_CACHE_SIZE CONFIG_NET_L2_IEEE802154_FRAGMENT_REASS_CACHE_SIZE
+
+static uint16_t datagram_tag;
+
+/**
+ *  Reassemble cache : Depends on cache size it used for reassemble
+ *  IPv6 packets simultaneously.
+ */
+struct frag_cache {
+	struct k_delayed_work timer;	/* Reassemble timer */
+	struct net_pkt *pkt;		/* Reassemble packet */
+	uint16_t size;			/* Datagram size */
+	uint16_t tag;			/* Datagram tag */
+	bool used;
+};
+
+static struct frag_cache cache[REASS_CACHE_SIZE];
+
+/**
+ *  RFC 4944, section 5.3
+ *  If an entire payload (e.g., IPv6) datagram fits within a single 802.15.4
+ *  frame, it is unfragmented and the LoWPAN encapsulation should not contain
+ *  a fragmentation header.  If the datagram does not fit within a single
+ *  IEEE 802.15.4 frame, it SHALL be broken into link fragments.  As the
+ *  fragment offset can only express multiples of eight bytes, all link
+ *  fragments for a datagram except the last one MUST be multiples of eight
+ *  bytes in length.
+ *
+ *  RFC 7668, section 3 (IPv6 over Bluetooth Low Energy)
+ *  Functionality is comprised of link-local IPv6 addresses and stateless
+ *  IPv6 address autoconfiguration, Neighbor Discovery, and header compression
+ *  Fragmentation features from 6LoWPAN standards are not used due to Bluetooth
+ *  LE's link-layer fragmentation support.
+ */
+
+/**
+ *                     1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |1 1 0 0 0|    datagram_size    |         datagram_tag          |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *                     1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |1 1 0 0 0|    datagram_size    |         datagram_tag          |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |datagram_offset|
+ *  +-+-+-+-+-+-+-+-+
+ */
+
+static inline void set_datagram_size(uint8_t *ptr, uint16_t size)
+{
+	ptr[0] |= ((size & 0x7FF) >> 8);
+	ptr[1] = (uint8_t) size;
+}
+
+static inline void set_datagram_tag(uint8_t *ptr, uint16_t tag)
+{
+	ptr[0] = tag >> 8;
+	ptr[1] = (uint8_t) tag;
+}
+
+static inline void set_up_frag_hdr(struct net_buf *frag, uint16_t size,
+				   uint8_t offset)
+{
+	uint8_t pos = frag->len;
+
+	if (!offset) {
+		net_buf_add(frag, NET_6LO_FRAG1_HDR_LEN);
+		frag->data[pos] = NET_6LO_DISPATCH_FRAG1;
+	} else {
+		net_buf_add(frag, NET_6LO_FRAGN_HDR_LEN);
+		frag->data[pos] = NET_6LO_DISPATCH_FRAGN;
+	}
+
+	set_datagram_size(frag->data + pos, size);
+	pos += NET_6LO_FRAG_DATAGRAM_SIZE_LEN;
+
+	set_datagram_tag(frag->data + pos, datagram_tag);
+	pos += NET_6LO_FRAG_DATAGRAM_OFFSET_LEN;
+
+	if (offset) {
+		frag->data[pos] = offset;
+	}
+}
+
+static inline uint8_t calc_max_payload(struct net_buf *frag, uint8_t offset)
+{
+	uint8_t max = frag->size - frag->len;
+
+	return (max & 0xF8);
+}
+
+static inline uint8_t copy_data(struct ieee802154_fragment_ctx *ctx,
+			     struct net_buf *frame_buf, uint8_t max)
+{
+	uint8_t move = ctx->buf->len - (ctx->pos - ctx->buf->data);
+
+	move = MIN(move, max);
+
+	memcpy(frame_buf->data + frame_buf->len, ctx->pos, move);
+
+	net_buf_add(frame_buf, move);
+
+	return move;
+}
+
+static inline void update_fragment_ctx(struct ieee802154_fragment_ctx *ctx,
+				       uint8_t move)
+{
+	if (move == (ctx->buf->len - (ctx->pos - ctx->buf->data))) {
+		ctx->buf = ctx->buf->frags;
+		if (ctx->buf) {
+			ctx->pos = ctx->buf->data;
+		}
+	} else {
+		ctx->pos += move;
+	}
+}
+
+/**
+ *  ch  : compressed (IPv6) header(s)
+ *  fh  : fragment header (dispatch + size + tag + [offset])
+ *  p   : payload (first fragment holds IPv6 hdr as payload)
+ *  e   : empty space
+ *  ll  : link layer
+ *
+ *  Input frame_buf to ieee802154_fragment() looks like below
+ *
+ *  | ll |
+ *
+ *  After fragment creation, frame_buf will look like:
+ *
+ *  | ll + fh + p + e |
+ *
+ *  p being taken from current pkt buffer and position.
+ *
+ *  Space in every fragment is because fragment payload should be multiple
+ *  of 8 octets (we have predefined packets at compile time, data packet mtu
+ *  is set already).
+ *
+ *  If it's the first fragment being created, fh will not own any offset
+ *  (so it will be 1 byte smaller)
+ */
+void ieee802154_fragment(struct ieee802154_fragment_ctx *ctx,
+			 struct net_buf *frame_buf, bool iphc)
+{
+	uint8_t max;
+
+	if (!ctx->offset) {
+		datagram_tag++;
+	}
+
+	set_up_frag_hdr(frame_buf, ctx->pkt_size, ctx->offset);
+	max = calc_max_payload(frame_buf, ctx->offset);
+
+	ctx->processed += max;
+
+	if (!ctx->offset) {
+		/* First fragment needs to take into account 6lo */
+		if (iphc) {
+			max -= ctx->hdr_diff;
+		} else {
+			/* Adding IPv6 dispatch header */
+			max += 1U;
+		}
+	}
+
+	while (max && ctx->buf) {
+		uint8_t move;
+
+		move = copy_data(ctx, frame_buf, max);
+
+		update_fragment_ctx(ctx, move);
+
+		max -= move;
+	}
+
+	ctx->offset = ctx->processed >> 3;
+}
+
+static inline uint16_t get_datagram_size(uint8_t *ptr)
+{
+	return ((ptr[0] & 0x1F) << 8) | ptr[1];
+}
+
+static inline uint16_t get_datagram_tag(uint8_t *ptr)
+{
+	return (ptr[0] << 8) | ptr[1];
+}
+
+static void update_protocol_header_lengths(struct net_pkt *pkt, uint16_t size)
+{
+	NET_PKT_DATA_ACCESS_DEFINE(ipv6_access, struct net_ipv6_hdr);
+	struct net_ipv6_hdr *ipv6;
+
+	ipv6 = (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
+	if (!ipv6) {
+		NET_ERR("could not get IPv6 header");
+		return;
+	}
+
+	net_pkt_set_ip_hdr_len(pkt, NET_IPV6H_LEN);
+	ipv6->len = htons(size - NET_IPV6H_LEN);
+
+	net_pkt_set_data(pkt, &ipv6_access);
+
+	if (ipv6->nexthdr == IPPROTO_UDP) {
+		NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+		struct net_udp_hdr *udp;
+
+		udp = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access);
+		if (udp) {
+			udp->len = htons(size - NET_IPV6H_LEN);
+			net_pkt_set_data(pkt, &udp_access);
+		} else {
+			NET_ERR("could not get UDP header");
+		}
+	}
+}
+
+static inline void clear_reass_cache(uint16_t size, uint16_t tag)
+{
+	uint8_t i;
+
+	for (i = 0U; i < REASS_CACHE_SIZE; i++) {
+		if (!(cache[i].size == size && cache[i].tag == tag)) {
+			continue;
+		}
+
+		if (cache[i].pkt) {
+			net_pkt_unref(cache[i].pkt);
+		}
+
+		cache[i].pkt = NULL;
+		cache[i].size = 0U;
+		cache[i].tag = 0U;
+		cache[i].used = false;
+		k_delayed_work_cancel(&cache[i].timer);
+	}
+}
+
+/**
+ *  If the reassembly not completed within reassembly timeout discard
+ *  the whole packet.
+ */
+static void reass_timeout(struct k_work *work)
+{
+	struct frag_cache *cache = CONTAINER_OF(work, struct frag_cache, timer);
+
+	if (cache->pkt) {
+		net_pkt_unref(cache->pkt);
+	}
+
+	cache->pkt = NULL;
+	cache->size = 0U;
+	cache->tag = 0U;
+	cache->used = false;
+}
+
+/**
+ *  Upon reception of first fragment with respective of size and tag
+ *  create a new cache. If number of unused cache are out then
+ *  discard the fragments.
+ */
+static inline struct frag_cache *set_reass_cache(struct net_pkt *pkt,
+						 uint16_t size, uint16_t tag)
+{
+	int i;
+
+	for (i = 0; i < REASS_CACHE_SIZE; i++) {
+		if (cache[i].used) {
+			continue;
+		}
+
+		cache[i].pkt = pkt;
+		cache[i].size = size;
+		cache[i].tag = tag;
+		cache[i].used = true;
+
+		k_delayed_work_init(&cache[i].timer, reass_timeout);
+		k_delayed_work_submit(&cache[i].timer, FRAG_REASSEMBLY_TIMEOUT);
+		return &cache[i];
+	}
+
+	return NULL;
+}
+
+/**
+ *  Return cache if it matches with size and tag of stored caches,
+ *  otherwise return NULL.
+ */
+static inline struct frag_cache *get_reass_cache(uint16_t size, uint16_t tag)
+{
+	uint8_t i;
+
+	for (i = 0U; i < REASS_CACHE_SIZE; i++) {
+		if (cache[i].used) {
+			if (cache[i].size == size &&
+			    cache[i].tag == tag) {
+				return &cache[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static inline void fragment_append(struct net_pkt *pkt, struct net_buf *frag)
+{
+	if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
+	    NET_6LO_DISPATCH_FRAG1) {
+		/* Always make sure first fragment is inserted first
+		 * This will be useful for fragment_cached_pkt_len()
+		 */
+		frag->frags = pkt->buffer;
+		pkt->buffer = frag;
+	} else {
+		net_pkt_append_buffer(pkt, frag);
+	}
+}
+
+static inline size_t fragment_cached_pkt_len(struct net_pkt *pkt)
+{
+	size_t len = 0U;
+	struct net_buf *frag;
+	int hdr_len;
+	uint8_t *data;
+
+	frag = pkt->buffer;
+	while (frag) {
+		uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;
+
+		if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
+		    NET_6LO_DISPATCH_FRAG1) {
+			hdr_len = NET_6LO_FRAG1_HDR_LEN;
+		}
+
+		len += frag->len - hdr_len;
+
+		frag = frag->frags;
+	}
+
+	/* 6lo assumes that fragment header has been removed,
+	 * and in our side we assume first buffer is always the first fragment.
+	 */
+	data = pkt->buffer->data;
+	pkt->buffer->data += NET_6LO_FRAG1_HDR_LEN;
+
+	hdr_len = net_6lo_uncompress_hdr_diff(pkt);
+
+	pkt->buffer->data = data;
+
+	if (hdr_len == INT_MAX) {
+		return 0;
+	}
+
+	return len + hdr_len;
+}
+
+static inline uint16_t fragment_offset(struct net_buf *frag)
+{
+	if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
+		    NET_6LO_DISPATCH_FRAG1) {
+		return 0;
+	}
+
+	return ((uint16_t)frag->data[NET_FRAG_OFFSET_POS] << 3);
+}
+
+static void fragment_move_back(struct net_pkt *pkt,
+			       struct net_buf *frag, struct net_buf *stop)
+{
+	struct net_buf *prev, *current;
+
+	prev = NULL;
+	current = pkt->buffer;
+
+	while (current && current != stop) {
+		if (fragment_offset(frag) < fragment_offset(current)) {
+			if (prev) {
+				prev->frags = frag;
+			}
+
+			frag->frags = current;
+			break;
+		}
+
+		prev = current;
+		current = current->frags;
+	}
+}
+
+static inline void fragment_remove_headers(struct net_pkt *pkt)
+{
+	struct net_buf *frag;
+
+	frag = pkt->buffer;
+	while (frag) {
+		uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;
+
+		if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
+		    NET_6LO_DISPATCH_FRAG1) {
+			hdr_len = NET_6LO_FRAG1_HDR_LEN;
+		}
+
+		memmove(frag->data, frag->data + hdr_len, frag->len - hdr_len);
+		frag->len -= hdr_len;
+
+		frag = frag->frags;
+	}
+}
+
+static inline void fragment_reconstruct_packet(struct net_pkt *pkt)
+{
+	struct net_buf *prev, *current, *next;
+
+	prev = NULL;
+	current = pkt->buffer;
+
+	while (current) {
+		next = current->frags;
+
+		if (!prev || (fragment_offset(prev) >
+			      fragment_offset(current))) {
+			prev = current;
+		} else {
+			fragment_move_back(pkt, current, prev);
+		}
+
+		current = next;
+	}
+
+	/* Let's remove now useless fragmentation headers */
+	fragment_remove_headers(pkt);
+}
+
+/**
+ *  Parse size and tag from the fragment, check if we have any cache
+ *  related to it. If not create a new cache.
+ *  Remove the fragmentation header and uncompress IPv6 and related headers.
+ *  Cache Rx part of fragment along with data buf for the first fragment
+ *  in the cache, remaining fragments just cache data fragment, unref
+ *  RX pkt. So in both the cases caller can assume packet is consumed.
+ */
+static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
+{
+	bool first_frag = false;
+	struct frag_cache *cache;
+	struct net_buf *frag;
+	uint16_t size;
+	uint16_t tag;
+
+	/* Parse total size of packet */
+	size = get_datagram_size(pkt->buffer->data);
+
+	/* Parse the datagram tag */
+	tag = get_datagram_tag(pkt->buffer->data +
+			       NET_6LO_FRAG_DATAGRAM_SIZE_LEN);
+
+	/* If there are no fragments in the cache means this frag
+	 * is the first one. So cache Rx pkt otherwise not.
+	 */
+	frag = pkt->buffer;
+	pkt->buffer = NULL;
+
+	cache = get_reass_cache(size, tag);
+	if (!cache) {
+		cache = set_reass_cache(pkt, size, tag);
+		if (!cache) {
+			NET_ERR("Could not get a cache entry");
+			pkt->buffer = frag;
+			return NET_DROP;
+		}
+
+		first_frag = true;
+	}
+
+	fragment_append(cache->pkt, frag);
+
+	if (fragment_cached_pkt_len(cache->pkt) == cache->size) {
+		/* Assign buffer back to input packet. */
+		pkt->buffer = cache->pkt->buffer;
+		cache->pkt->buffer = NULL;
+
+		fragment_reconstruct_packet(pkt);
+
+		/* Once reassemble is done, cache is no longer needed. */
+		clear_reass_cache(size, tag);
+
+		if (!net_6lo_uncompress(pkt)) {
+			NET_ERR("Could not uncompress. Bogus packet?");
+			return NET_DROP;
+		}
+
+		net_pkt_cursor_init(pkt);
+
+		update_protocol_header_lengths(pkt, size);
+
+		net_pkt_cursor_init(pkt);
+
+		NET_DBG("All fragments received and reassembled");
+
+		return NET_CONTINUE;
+	}
+
+	/* Unref Rx part of original packet */
+	if (!first_frag) {
+		net_pkt_unref(pkt);
+	}
+
+	return NET_OK;
+}
+
+
+enum net_verdict ieee802154_reassemble(struct net_pkt *pkt)
+{
+	if (!pkt || !pkt->buffer) {
+		NET_ERR("Nothing to reassemble");
+		return NET_DROP;
+	}
+
+	if ((pkt->buffer->data[0] & NET_FRAG_DISPATCH_MASK) >=
+	    NET_6LO_DISPATCH_FRAG1) {
+		return fragment_add_to_cache(pkt);
+	} else {
+		NET_DBG("No frag dispatch (%02x)", pkt->buffer->data[0]);
+		/* Received unfragmented packet, uncompress */
+		if (net_6lo_uncompress(pkt)) {
+			return NET_CONTINUE;
+		}
+
+		NET_ERR("Could not uncompress. Bogus packet?");
+	}
+
+	return NET_DROP;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.h	(working copy)
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief IEEE 802.15.4 Frame API header
+ */
+
+#ifndef __IEEE802154_FRAME_H__
+#define __IEEE802154_FRAME_H__
+
+#include <kernel.h>
+#include <net/net_pkt.h>
+#include <net/ieee802154.h>
+#include <toolchain.h>
+
+#define IEEE802154_MTU				127
+#define IEEE802154_MIN_LENGTH			3
+/* See Section 5.2.1.4 */
+#define IEEE802154_BROADCAST_ADDRESS		0xFFFF
+#define IEEE802154_BROADCAST_PAN_ID		0xFFFF
+/* ACK packet size is the minimum size, see Section 5.2.2.3 */
+#define IEEE802154_ACK_PKT_LENGTH		IEEE802154_MIN_LENGTH
+#define IEEE802154_MFR_LENGTH			2
+
+#define IEEE802154_FCF_SEQ_LENGTH		3
+#define IEEE802154_EXT_ADDR_LENGTH		8
+#define IEEE802154_SHORT_ADDR_LENGTH		2
+#define IEEE802154_SIMPLE_ADDR_LENGTH		1
+#define IEEE802154_PAN_ID_LENGTH		2
+
+#define IEEE802154_BEACON_MIN_SIZE		4
+#define IEEE802154_BEACON_SF_SIZE		2
+#define IEEE802154_BEACON_GTS_SPEC_SIZE		1
+#define IEEE802154_BEACON_GTS_IF_MIN_SIZE	IEEE802154_BEACON_GTS_SPEC_SIZE
+#define IEEE802154_BEACON_PAS_SPEC_SIZE		1
+#define IEEE802154_BEACON_PAS_IF_MIN_SIZE	IEEE802154_BEACON_PAS_SPEC_SIZE
+#define IEEE802154_BEACON_GTS_DIR_SIZE		1
+#define IEEE802154_BEACON_GTS_SIZE		3
+#define IEEE802154_BEACON_GTS_RX		1
+#define IEEE802154_BEACON_GTS_TX		0
+
+/* See Section 5.2.1.1.1 */
+enum ieee802154_frame_type {
+	IEEE802154_FRAME_TYPE_BEACON		= 0x0,
+	IEEE802154_FRAME_TYPE_DATA		= 0x1,
+	IEEE802154_FRAME_TYPE_ACK		= 0x2,
+	IEEE802154_FRAME_TYPE_MAC_COMMAND	= 0x3,
+	IEEE802154_FRAME_TYPE_LLDN		= 0x4,
+	IEEE802154_FRAME_TYPE_MULTIPURPOSE	= 0x5,
+	IEEE802154_FRAME_TYPE_RESERVED		= 0x6,
+};
+
+/* See Section 5.2.1.1.6 */
+enum ieee802154_addressing_mode {
+	IEEE802154_ADDR_MODE_NONE		= 0x0,
+	IEEE802154_ADDR_MODE_SIMPLE		= 0x1,
+	IEEE802154_ADDR_MODE_SHORT		= 0x2,
+	IEEE802154_ADDR_MODE_EXTENDED		= 0x3,
+};
+
+/** Versions 2003/2006 do no support simple addressing mode */
+#define IEEE802154_ADDR_MODE_RESERVED		IEEE802154_ADDR_MODE_SIMPLE
+
+/* See Section 5.2.1.1.7 */
+enum ieee802154_version {
+	IEEE802154_VERSION_802154_2003		= 0x0,
+	IEEE802154_VERSION_802154_2006		= 0x1,
+	IEEE802154_VERSION_802154		= 0x2,
+	IEEE802154_VERSION_RESERVED		= 0x3,
+};
+
+/*
+ * Frame Control Field and sequence number
+ * See Section 5.2.1.1
+ */
+struct ieee802154_fcf_seq {
+	struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+		uint16_t frame_type		:3;
+		uint16_t security_enabled		:1;
+		uint16_t frame_pending		:1;
+		uint16_t ar			:1;
+		uint16_t pan_id_comp		:1;
+		uint16_t reserved			:1;
+		uint16_t seq_num_suppr		:1;
+		uint16_t ie_list			:1;
+		uint16_t dst_addr_mode		:2;
+		uint16_t frame_version		:2;
+		uint16_t src_addr_mode		:2;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+		uint16_t reserved			:1;
+		uint16_t pan_id_comp		:1;
+		uint16_t ar			:1;
+		uint16_t frame_pending		:1;
+		uint16_t security_enabled		:1;
+		uint16_t frame_type		:3;
+		uint16_t src_addr_mode		:2;
+		uint16_t frame_version		:2;
+		uint16_t dst_addr_mode		:2;
+		uint16_t ie_list			:1;
+		uint16_t seq_num_suppr		:1;
+#endif
+	} fc __packed;
+
+	uint8_t sequence;
+} __packed;
+
+struct ieee802154_address {
+	union {
+		uint8_t simple_addr;
+		uint16_t short_addr;
+		uint8_t ext_addr[0];
+	};
+} __packed;
+
+struct ieee802154_address_field_comp {
+	struct ieee802154_address addr;
+} __packed;
+
+struct ieee802154_address_field_plain {
+	uint16_t pan_id;
+	struct ieee802154_address addr;
+} __packed;
+
+struct ieee802154_address_field {
+	union {
+		struct ieee802154_address_field_plain plain;
+		struct ieee802154_address_field_comp comp;
+	};
+} __packed;
+
+/* See Section 7.4.1.1 */
+enum ieee802154_security_level {
+	IEEE802154_SECURITY_LEVEL_NONE			= 0x0,
+	IEEE802154_SECURITY_LEVEL_MIC_32		= 0x1,
+	IEEE802154_SECURITY_LEVEL_MIC_64		= 0x2,
+	IEEE802154_SECURITY_LEVEL_MIC_128		= 0x3,
+	IEEE802154_SECURITY_LEVEL_ENC			= 0x4,
+	IEEE802154_SECURITY_LEVEL_ENC_MIC_32		= 0x5,
+	IEEE802154_SECURITY_LEVEL_ENC_MIC_64		= 0x6,
+	IEEE802154_SECURITY_LEVEL_ENC_MIC_128		= 0x7,
+};
+
+/* This will match above *_MIC_<32/64/128> */
+#define IEEE8021254_AUTH_TAG_LENGTH_32			4
+#define IEEE8021254_AUTH_TAG_LENGTH_64			8
+#define IEEE8021254_AUTH_TAG_LENGTH_128			16
+
+/* See Section 7.4.1.2 */
+enum ieee802154_key_id_mode {
+	IEEE802154_KEY_ID_MODE_IMPLICIT			= 0x0,
+	IEEE802154_KEY_ID_MODE_INDEX			= 0x1,
+	IEEE802154_KEY_ID_MODE_SRC_4_INDEX		= 0x2,
+	IEEE802154_KEY_ID_MODE_SRC_8_INDEX		= 0x3,
+};
+
+#define IEEE8021254_KEY_ID_FIELD_INDEX_LENGTH		1
+#define IEEE8021254_KEY_ID_FIELD_SRC_4_INDEX_LENGTH	5
+#define IEEE8021254_KEY_ID_FIELD_SRC_8_INDEX_LENGTH	9
+
+#define IEEE802154_KEY_MAX_LEN				16
+
+/* See Section 7.4.1 */
+struct ieee802154_security_control_field {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t security_level	:3;
+	uint8_t key_id_mode	:2;
+	uint8_t reserved		:3;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t reserved		:3;
+	uint8_t key_id_mode	:2;
+	uint8_t security_level	:3;
+#endif
+} __packed;
+
+#define IEEE802154_SECURITY_CF_LENGTH	1
+
+/* See Section 7.4.3 */
+struct ieee802154_key_identifier_field {
+	union {
+		/* mode_0 being implicit, it holds no info here */
+		struct {
+			uint8_t key_index;
+		} mode_1;
+
+		struct {
+			uint8_t key_src[4];
+			uint8_t key_index;
+		} mode_2;
+
+		struct {
+			uint8_t key_src[8];
+			uint8_t key_index;
+		} mode_3;
+	};
+} __packed;
+
+/*
+ * Auxiliary Security Header
+ * See Section 7.4
+ */
+struct ieee802154_aux_security_hdr {
+	struct ieee802154_security_control_field control;
+	uint32_t frame_counter;
+	struct ieee802154_key_identifier_field kif;
+} __packed;
+
+#define IEEE802154_SECURITY_FRAME_COUNTER_LENGTH 4
+
+/** MAC header */
+struct ieee802154_mhr {
+	struct ieee802154_fcf_seq *fs;
+	struct ieee802154_address_field *dst_addr;
+	struct ieee802154_address_field *src_addr;
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	struct ieee802154_aux_security_hdr *aux_sec;
+#endif
+};
+
+struct ieee802154_mfr {
+	uint16_t fcs;
+};
+
+struct ieee802154_gts_dir {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t mask			: 7;
+	uint8_t reserved			: 1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t reserved			: 1;
+	uint8_t mask			: 7;
+#endif
+} __packed;
+
+struct ieee802154_gts {
+	uint16_t short_address;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	uint8_t starting_slot		: 4;
+	uint8_t length			: 4;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t length			: 4;
+	uint8_t starting_slot		: 4;
+#endif
+} __packed;
+
+struct ieee802154_gts_spec {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	/* Descriptor Count */
+	uint8_t desc_count			: 3;
+	uint8_t reserved			: 4;
+	/* GTS Permit */
+	uint8_t permit			: 1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	/* GTS Permit */
+	uint8_t permit			: 1;
+	uint8_t reserved			: 4;
+	/* Descriptor Count */
+	uint8_t desc_count			: 3;
+#endif
+} __packed;
+
+struct ieee802154_pas_spec {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	/* Number of Short Addresses Pending */
+	uint8_t nb_sap			: 3;
+	uint8_t reserved_1			: 1;
+	/* Number of Extended Addresses Pending */
+	uint8_t nb_eap			: 3;
+	uint8_t reserved_2			: 1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	uint8_t reserved_1			: 1;
+	/* Number of Extended Addresses Pending */
+	uint8_t nb_eap			: 3;
+	uint8_t reserved_2			: 1;
+	/* Number of Short Addresses Pending */
+	uint8_t nb_sap			: 3;
+#endif
+} __packed;
+
+struct ieee802154_beacon_sf {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	/* Beacon Order*/
+	uint16_t bc_order		: 4;
+	/* Superframe Order*/
+	uint16_t sf_order		: 4;
+	/* Final CAP Slot */
+	uint16_t cap_slot		: 4;
+	/* Battery Life Extension */
+	uint16_t ble		: 1;
+	uint16_t reserved		: 1;
+	/* PAN Coordinator */
+	uint16_t coordinator	: 1;
+	/* Association Permit */
+	uint16_t association	: 1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	/* Superframe Order*/
+	uint16_t sf_order		: 4;
+	/* Beacon Order*/
+	uint16_t bc_order		: 4;
+	/* Association Permit */
+	uint16_t association	: 1;
+	/* PAN Coordinator */
+	uint16_t coordinator	: 1;
+	uint16_t reserved		: 1;
+	/* Battery Life Extension */
+	uint16_t ble		: 1;
+	/* Final CAP Slot */
+	uint16_t cap_slot		: 4;
+#endif
+} __packed;
+
+struct ieee802154_beacon {
+	struct ieee802154_beacon_sf sf;
+
+	/* GTS Fields - Spec is always there */
+	struct ieee802154_gts_spec gts;
+} __packed;
+
+/* See Section 5.3.1 */
+struct ieee802154_cmd_assoc_req {
+	struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+		uint8_t reserved_1		: 1;
+		uint8_t dev_type		: 1;
+		uint8_t power_src		: 1;
+		uint8_t rx_on		: 1;
+		uint8_t reserved_2		: 2;
+		uint8_t sec_capability	: 1;
+		uint8_t alloc_addr		: 1;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+		uint8_t alloc_addr		: 1;
+		uint8_t sec_capability	: 1;
+		uint8_t reserved_2		: 2;
+		uint8_t rx_on		: 1;
+		uint8_t power_src		: 1;
+		uint8_t dev_type		: 1;
+		uint8_t reserved_1		: 1;
+#endif
+	} ci;
+} __packed;
+
+#define IEEE802154_CMD_ASSOC_REQ_LENGTH		1
+
+/* See Section 5.3.2 */
+enum ieee802154_association_status_field {
+	IEEE802154_ASF_SUCCESSFUL		= 0x00,
+	IEEE802154_ASF_PAN_AT_CAPACITY		= 0x01,
+	IEEE802154_ASF_PAN_ACCESS_DENIED	= 0x02,
+	IEEE802154_ASF_RESERVED			= 0x03,
+	IEEE802154_ASF_RESERVED_PRIMITIVES	= 0x80,
+};
+
+struct ieee802154_cmd_assoc_res {
+	uint16_t short_addr;
+	uint8_t status;
+} __packed;
+
+#define IEEE802154_CMD_ASSOC_RES_LENGTH		3
+
+/* See Section 5.3.3 */
+enum ieee802154_disassociation_reason_field {
+	IEEE802154_DRF_RESERVED_1		= 0x00,
+	IEEE802154_DRF_COORDINATOR_WISH		= 0x01,
+	IEEE802154_DRF_DEVICE_WISH		= 0x02,
+	IEEE802154_DRF_RESERVED_2		= 0x03,
+	IEEE802154_DRF_RESERVED_PRIMITIVES	= 0x80,
+};
+
+struct ieee802154_cmd_disassoc_note {
+	uint8_t reason;
+} __packed;
+
+#define IEEE802154_CMD_DISASSOC_NOTE_LENGTH	1
+
+/* See Section 5.3.8 */
+struct ieee802154_cmd_coord_realign {
+	uint16_t pan_id;
+	uint16_t coordinator_short_addr;
+	uint8_t channel;
+	uint16_t short_addr;
+	uint8_t channel_page; /* Optional */
+} __packed;
+
+#define IEEE802154_CMD_COORD_REALIGN_LENGTH	3
+
+/* See Section 5.3.9 */
+struct ieee802154_gts_request {
+	struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+		uint8_t length		: 4;
+		uint8_t direction		: 1;
+		uint8_t type		: 1;
+		uint8_t reserved		: 2;
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+		uint8_t reserved		: 2;
+		uint8_t type		: 1;
+		uint8_t direction		: 1;
+		uint8_t length		: 4;
+#endif
+	} gts;
+} __packed;
+
+#define IEEE802154_GTS_REQUEST_LENGTH		1
+
+/* See Section 5.3 */
+enum ieee802154_cfi {
+	IEEE802154_CFI_UNKNOWN				= 0x00,
+	IEEE802154_CFI_ASSOCIATION_REQUEST		= 0x01,
+	IEEE802154_CFI_ASSOCIATION_RESPONSE		= 0x02,
+	IEEE802154_CFI_DISASSOCIATION_NOTIFICATION	= 0x03,
+	IEEE802154_CFI_DATA_REQUEST			= 0x04,
+	IEEE802154_CFI_PAN_ID_CONLICT_NOTIFICATION	= 0x05,
+	IEEE802154_CFI_ORPHAN_NOTIFICATION		= 0x06,
+	IEEE802154_CFI_BEACON_REQUEST			= 0x07,
+	IEEE802154_CFI_COORDINATOR_REALIGNEMENT		= 0x08,
+	IEEE802154_CFI_GTS_REQUEST			= 0x09,
+	IEEE802154_CFI_RESERVED				= 0x0a,
+};
+
+struct ieee802154_command {
+	uint8_t cfi;
+	union {
+		struct ieee802154_cmd_assoc_req assoc_req;
+		struct ieee802154_cmd_assoc_res assoc_res;
+		struct ieee802154_cmd_disassoc_note disassoc_note;
+		struct ieee802154_cmd_coord_realign coord_realign;
+		struct ieee802154_gts_request gts_request;
+		/* Data request, PAN ID conflict, Orphan notification
+		 * or Beacon request do not provide more than the CIF.
+		 */
+	};
+} __packed;
+
+#define IEEE802154_CMD_CFI_LENGTH		1
+
+/** Frame */
+struct ieee802154_mpdu {
+	struct ieee802154_mhr mhr;
+	union {
+		void *payload;
+		struct ieee802154_beacon *beacon;
+		struct ieee802154_command *command;
+	};
+	struct ieee802154_mfr *mfr;
+} __packed;
+
+/** Frame build parameters */
+struct ieee802154_frame_params {
+	struct {
+		union {
+			uint8_t *ext_addr;
+			uint16_t short_addr;
+		};
+
+		uint16_t len;
+		uint16_t pan_id;
+	} dst;
+
+	uint16_t short_addr;
+	uint16_t pan_id;
+} __packed;
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+struct ieee802154_aux_security_hdr *
+ieee802154_validate_aux_security_hdr(uint8_t *buf, uint8_t **p_buf, uint8_t *length);
+#endif
+
+struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_buf,
+						      uint8_t *length);
+
+bool ieee802154_validate_frame(uint8_t *buf, uint8_t length,
+			       struct ieee802154_mpdu *mpdu);
+
+uint8_t ieee802154_compute_header_size(struct net_if *iface,
+				    struct in6_addr *dst);
+
+bool ieee802154_create_data_frame(struct ieee802154_context *ctx,
+				  struct net_linkaddr *dst,
+				  struct net_buf *frag,
+				  uint8_t hdr_size);
+
+struct net_pkt *
+ieee802154_create_mac_cmd_frame(struct net_if *iface,
+				enum ieee802154_cfi type,
+				struct ieee802154_frame_params *params);
+
+void ieee802154_mac_cmd_finalize(struct net_pkt *pkt,
+				 enum ieee802154_cfi type);
+
+static inline
+struct ieee802154_command *ieee802154_get_mac_command(struct net_pkt *pkt)
+{
+	return (struct ieee802154_command *)(pkt->frags->data +
+					     pkt->frags->len);
+}
+
+#ifdef CONFIG_NET_L2_IEEE802154_ACK_REPLY
+bool ieee802154_create_ack_frame(struct net_if *iface,
+				 struct net_pkt *pkt, uint8_t seq);
+#endif
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_pkt *pkt,
+				    struct ieee802154_mpdu *mpdu);
+#else
+#define ieee802154_decipher_data_frame(...) true
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+#endif /* __IEEE802154_FRAME_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_frame.c	(working copy)
@@ -0,0 +1,989 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_frame, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_if.h>
+
+#include <ipv6.h>
+#include <nbr.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_security.h"
+
+#define dbg_print_fs(fs)						\
+	NET_DBG("fs(1): %u/%u/%u/%u/%u/%u",				\
+		fs->fc.frame_type, fs->fc.security_enabled,		\
+		fs->fc.frame_pending, fs->fc.ar, fs->fc.pan_id_comp,	\
+		fs->fc.reserved);					\
+	NET_DBG("fs(2): %u/%u/%u/%u/%u - %u",				\
+		fs->fc.seq_num_suppr, fs->fc.ie_list,			\
+		fs->fc.dst_addr_mode, fs->fc.frame_version,		\
+		fs->fc.src_addr_mode, fs->sequence)
+
+#define BUF_TIMEOUT K_MSEC(50)
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+const uint8_t level_2_tag_size[4] = {
+	0,
+	IEEE8021254_AUTH_TAG_LENGTH_32,
+	IEEE8021254_AUTH_TAG_LENGTH_64,
+	IEEE8021254_AUTH_TAG_LENGTH_128
+};
+#endif
+
+struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_buf,
+						      uint8_t *length)
+{
+	struct ieee802154_fcf_seq *fs = (struct ieee802154_fcf_seq *)buf;
+
+	dbg_print_fs(fs);
+
+	/** Basic FC checks */
+	if (fs->fc.frame_type >= IEEE802154_FRAME_TYPE_RESERVED ||
+	    fs->fc.frame_version >= IEEE802154_VERSION_RESERVED) {
+		return NULL;
+	}
+
+	/** Only for versions 2003/2006 */
+	if (fs->fc.frame_version < IEEE802154_VERSION_802154 &&
+	    (fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_RESERVED ||
+	     fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_RESERVED ||
+	     fs->fc.frame_type >= IEEE802154_FRAME_TYPE_LLDN)) {
+		return NULL;
+	}
+
+	if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON &&
+	    (fs->fc.dst_addr_mode != IEEE802154_ADDR_MODE_NONE ||
+	     fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_NONE ||
+	     fs->fc.pan_id_comp)) {
+		/** See section 5.2.2.1.1 */
+		return NULL;
+	} else if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_DATA &&
+		   fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_NONE &&
+		   fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_NONE) {
+		/** See section 5.2.2.2.1 */
+		return NULL;
+	} else if (fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND &&
+		   fs->fc.frame_pending) {
+		/** See section 5.3 */
+		return NULL;
+	}
+
+#ifndef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (fs->fc.security_enabled) {
+		return NULL;
+	}
+#endif
+
+	if (p_buf) {
+		*length -= IEEE802154_FCF_SEQ_LENGTH;
+		*p_buf = buf + IEEE802154_FCF_SEQ_LENGTH;
+	}
+
+	return fs;
+}
+
+static inline struct ieee802154_address_field *
+validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
+	      enum ieee802154_addressing_mode mode,
+	      bool pan_id_compression)
+{
+	uint8_t len = 0;
+
+	*p_buf = buf;
+
+	NET_DBG("Buf %p - mode %d - pan id comp %d",
+		buf, mode, pan_id_compression);
+
+	if (mode == IEEE802154_ADDR_MODE_NONE) {
+		return NULL;
+	}
+
+	if (!pan_id_compression) {
+		len = IEEE802154_PAN_ID_LENGTH;
+	}
+
+	if (mode == IEEE802154_ADDR_MODE_SHORT) {
+		len += IEEE802154_SHORT_ADDR_LENGTH;
+	} else {
+		/* IEEE802154_ADDR_MODE_EXTENDED */
+		len += IEEE802154_EXT_ADDR_LENGTH;
+	}
+
+	if (len > *length) {
+		return NULL;
+	}
+
+	*p_buf += len;
+	*length -= len;
+
+	return (struct ieee802154_address_field *)buf;
+}
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+struct ieee802154_aux_security_hdr *
+ieee802154_validate_aux_security_hdr(uint8_t *buf, uint8_t **p_buf, uint8_t *length)
+{
+	struct ieee802154_aux_security_hdr *ash =
+		(struct ieee802154_aux_security_hdr *)buf;
+	uint8_t len =  IEEE802154_SECURITY_CF_LENGTH +
+		IEEE802154_SECURITY_FRAME_COUNTER_LENGTH;
+
+	/* At least the asf is sized of: control field + frame counter */
+	if (*length < len) {
+		return NULL;
+	}
+
+	/* Only implicit key mode is supported for now */
+	if (ash->control.key_id_mode != IEEE802154_KEY_ID_MODE_IMPLICIT) {
+		return NULL;
+	}
+
+	/* Explicit key must have a key index != 0x00, see Section 7.4.3.2 */
+	switch (ash->control.key_id_mode) {
+	case IEEE802154_KEY_ID_MODE_IMPLICIT:
+		break;
+	case IEEE802154_KEY_ID_MODE_INDEX:
+		len +=  IEEE8021254_KEY_ID_FIELD_INDEX_LENGTH;
+		if (*length < len) {
+			return NULL;
+		}
+
+		if (!ash->kif.mode_1.key_index) {
+			return NULL;
+		}
+
+		break;
+	case IEEE802154_KEY_ID_MODE_SRC_4_INDEX:
+		len += IEEE8021254_KEY_ID_FIELD_SRC_4_INDEX_LENGTH;
+		if (*length < len) {
+			return NULL;
+		}
+
+		if (!ash->kif.mode_2.key_index) {
+			return NULL;
+		}
+
+		break;
+	case IEEE802154_KEY_ID_MODE_SRC_8_INDEX:
+		len += IEEE8021254_KEY_ID_FIELD_SRC_8_INDEX_LENGTH;
+		if (*length < len) {
+			return NULL;
+		}
+
+		if (!ash->kif.mode_3.key_index) {
+			return NULL;
+		}
+
+		break;
+	}
+
+	*p_buf = buf + len;
+	*length -= len;
+
+	return ash;
+}
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+static inline bool
+validate_beacon(struct ieee802154_mpdu *mpdu, uint8_t *buf, uint8_t *length)
+{
+	struct ieee802154_beacon *b = (struct ieee802154_beacon *)buf;
+	struct ieee802154_pas_spec *pas;
+	uint8_t len = IEEE802154_BEACON_SF_SIZE +
+		IEEE802154_BEACON_GTS_SPEC_SIZE;
+
+
+	if (*length < len) {
+		return false;
+	}
+
+	if (b->gts.desc_count) {
+		len += IEEE802154_BEACON_GTS_DIR_SIZE +
+			b->gts.desc_count * IEEE802154_BEACON_GTS_SIZE;
+	}
+
+	if (*length < len) {
+		return false;
+	}
+
+	pas = (struct ieee802154_pas_spec *)buf + len;
+
+	len += IEEE802154_BEACON_PAS_SPEC_SIZE;
+	if (*length < len) {
+		return false;
+	}
+
+	if (pas->nb_sap || pas->nb_eap) {
+		len += (pas->nb_sap * IEEE802154_SHORT_ADDR_LENGTH) +
+			(pas->nb_eap * IEEE802154_EXT_ADDR_LENGTH);
+	}
+
+	if (*length < len) {
+		return false;
+	}
+
+	*length -= len;
+	mpdu->beacon = b;
+
+	return true;
+}
+
+static inline bool
+validate_mac_command_cfi_to_mhr(struct ieee802154_mhr *mhr,
+				uint8_t ar, uint8_t comp,
+				uint8_t src, bool src_pan_brdcst_chk,
+				uint8_t dst, bool dst_brdcst_chk)
+{
+	if (mhr->fs->fc.ar != ar || mhr->fs->fc.pan_id_comp != comp) {
+		return false;
+	}
+
+	if ((mhr->fs->fc.src_addr_mode != src) ||
+	    (mhr->fs->fc.dst_addr_mode != dst)) {
+		return false;
+	}
+
+	/* This should be set only when comp == 0 */
+	if (src_pan_brdcst_chk) {
+		if (mhr->src_addr->plain.pan_id !=
+		    IEEE802154_BROADCAST_PAN_ID) {
+			return false;
+		}
+	}
+
+	/* This should be set only when comp == 0 */
+	if (dst_brdcst_chk) {
+		if (mhr->dst_addr->plain.addr.short_addr !=
+		    IEEE802154_BROADCAST_ADDRESS) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static inline bool
+validate_mac_command(struct ieee802154_mpdu *mpdu, uint8_t *buf, uint8_t *length)
+{
+	struct ieee802154_command *c = (struct ieee802154_command *)buf;
+	uint8_t len = IEEE802154_CMD_CFI_LENGTH;
+	bool src_pan_brdcst_chk = false;
+	bool dst_brdcst_chk = false;
+	uint8_t comp = 0U;
+	uint8_t ar = 0U;
+	uint8_t src, dst;
+
+	if (*length < len) {
+		return false;
+	}
+
+	switch (c->cfi) {
+	case IEEE802154_CFI_UNKNOWN:
+		return false;
+	case IEEE802154_CFI_ASSOCIATION_REQUEST:
+		len += IEEE802154_CMD_ASSOC_REQ_LENGTH;
+		src = IEEE802154_EXT_ADDR_LENGTH;
+		src_pan_brdcst_chk = true;
+		dst = IEEE802154_ADDR_MODE_SHORT |
+			IEEE802154_ADDR_MODE_EXTENDED;
+
+		break;
+	case IEEE802154_CFI_ASSOCIATION_RESPONSE:
+		len += IEEE802154_CMD_ASSOC_RES_LENGTH;
+		__fallthrough;
+	case IEEE802154_CFI_DISASSOCIATION_NOTIFICATION:
+		if (c->cfi == IEEE802154_CFI_DISASSOCIATION_NOTIFICATION) {
+			len += IEEE802154_CMD_DISASSOC_NOTE_LENGTH;
+		}
+		__fallthrough;
+	case IEEE802154_CFI_PAN_ID_CONLICT_NOTIFICATION:
+		ar = 1U;
+		comp = 1U;
+		src = IEEE802154_EXT_ADDR_LENGTH;
+		dst = IEEE802154_EXT_ADDR_LENGTH;
+
+		break;
+	case IEEE802154_CFI_DATA_REQUEST:
+		ar = 1U;
+		src = IEEE802154_ADDR_MODE_SHORT |
+			IEEE802154_ADDR_MODE_EXTENDED;
+
+		if (mpdu->mhr.fs->fc.dst_addr_mode ==
+		    IEEE802154_ADDR_MODE_NONE) {
+			dst = IEEE802154_ADDR_MODE_NONE;
+		} else {
+			comp = 1U;
+			dst = IEEE802154_ADDR_MODE_SHORT |
+				IEEE802154_ADDR_MODE_EXTENDED;
+		}
+
+		break;
+	case IEEE802154_CFI_ORPHAN_NOTIFICATION:
+		comp = 1U;
+		src = IEEE802154_EXT_ADDR_LENGTH;
+		dst = IEEE802154_ADDR_MODE_SHORT;
+
+		break;
+	case IEEE802154_CFI_BEACON_REQUEST:
+		src = IEEE802154_ADDR_MODE_NONE;
+		dst = IEEE802154_ADDR_MODE_SHORT;
+		dst_brdcst_chk = true;
+
+		break;
+	case IEEE802154_CFI_COORDINATOR_REALIGNEMENT:
+		len += IEEE802154_CMD_COORD_REALIGN_LENGTH;
+		src = IEEE802154_EXT_ADDR_LENGTH;
+
+		if (mpdu->mhr.fs->fc.dst_addr_mode ==
+		    IEEE802154_ADDR_MODE_SHORT) {
+			dst = IEEE802154_ADDR_MODE_SHORT;
+			dst_brdcst_chk = true;
+		} else {
+			dst = IEEE802154_ADDR_MODE_EXTENDED;
+		}
+
+		break;
+	case IEEE802154_CFI_GTS_REQUEST:
+		len += IEEE802154_GTS_REQUEST_LENGTH;
+		ar = 1U;
+		src = IEEE802154_ADDR_MODE_SHORT;
+		dst = IEEE802154_ADDR_MODE_NONE;
+
+		break;
+	default:
+		return false;
+	}
+
+	if (*length < len) {
+		return false;
+	}
+
+	if (!validate_mac_command_cfi_to_mhr(&mpdu->mhr, ar, comp,
+					     src, src_pan_brdcst_chk,
+					     dst, dst_brdcst_chk)) {
+		return false;
+	}
+
+	*length -= len;
+	mpdu->command = c;
+
+	return true;
+}
+
+static inline bool
+validate_payload_and_mfr(struct ieee802154_mpdu *mpdu,
+			 uint8_t *buf, uint8_t *p_buf, uint8_t *length)
+{
+	uint8_t type = mpdu->mhr.fs->fc.frame_type;
+
+	NET_DBG("Header size: %u, payload size %u",
+		(uint32_t)(p_buf - buf), *length);
+
+	if (type == IEEE802154_FRAME_TYPE_BEACON) {
+		if (!validate_beacon(mpdu, p_buf, length)) {
+			return false;
+		}
+	} else if (type == IEEE802154_FRAME_TYPE_DATA) {
+		 /** A data frame embeds a payload */
+		if (*length == 0U) {
+			return false;
+		}
+
+		mpdu->payload = (void *)p_buf;
+	} else if (type == IEEE802154_FRAME_TYPE_ACK) {
+		/** An ACK frame has no payload */
+		if (*length) {
+			return false;
+		}
+
+		mpdu->payload = NULL;
+	} else {
+		if (!validate_mac_command(mpdu, p_buf, length)) {
+			return false;
+		}
+	}
+
+	if (*length) {
+		mpdu->mfr = (struct ieee802154_mfr *)(p_buf + *length);
+	} else {
+		mpdu->mfr = NULL;
+	}
+
+	return true;
+}
+
+bool ieee802154_validate_frame(uint8_t *buf, uint8_t length,
+			       struct ieee802154_mpdu *mpdu)
+{
+	uint8_t *p_buf = NULL;
+
+	if (length > IEEE802154_MTU || length < IEEE802154_MIN_LENGTH) {
+		NET_DBG("Wrong packet length: %d", length);
+		return false;
+	}
+
+	mpdu->mhr.fs = ieee802154_validate_fc_seq(buf, &p_buf, &length);
+	if (!mpdu->mhr.fs) {
+		return false;
+	}
+
+	/* ToDo: Support later version's frame types */
+	if (mpdu->mhr.fs->fc.frame_type > IEEE802154_FRAME_TYPE_MAC_COMMAND) {
+		return false;
+	}
+
+	mpdu->mhr.dst_addr = validate_addr(p_buf, &p_buf, &length,
+					   mpdu->mhr.fs->fc.dst_addr_mode,
+					   false);
+
+	mpdu->mhr.src_addr = validate_addr(p_buf, &p_buf, &length,
+					   mpdu->mhr.fs->fc.src_addr_mode,
+					   (mpdu->mhr.fs->fc.pan_id_comp));
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (mpdu->mhr.fs->fc.security_enabled) {
+		mpdu->mhr.aux_sec =
+			ieee802154_validate_aux_security_hdr(p_buf, &p_buf,
+							     &length);
+		if (!mpdu->mhr.aux_sec) {
+			return false;
+		}
+	}
+#endif
+
+	return validate_payload_and_mfr(mpdu, buf, p_buf, &length);
+}
+
+uint8_t ieee802154_compute_header_size(struct net_if *iface,
+				    struct in6_addr *dst)
+{
+	uint8_t hdr_len = sizeof(struct ieee802154_fcf_seq);
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	struct ieee802154_security_ctx *sec_ctx =
+		&((struct ieee802154_context *)net_if_l2_data(iface))->sec_ctx;
+#endif
+
+	/** if dst is NULL, we'll consider it as a brodcast header */
+	if (!dst ||
+	    net_ipv6_is_addr_mcast(dst) ||
+	    net_ipv6_is_addr_unspecified(dst)) {
+		NET_DBG("Broadcast destination");
+		/* 4 dst pan/addr + 8 src addr */
+		hdr_len += IEEE802154_PAN_ID_LENGTH +
+			IEEE802154_SHORT_ADDR_LENGTH +
+			IEEE802154_EXT_ADDR_LENGTH;
+		if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_SECURITY)) {
+			NET_DBG("Broadcast packet do not have security");
+			goto done;
+		}
+	} else {
+		struct net_nbr *nbr;
+
+		nbr = net_ipv6_nbr_lookup(iface, dst);
+		if (nbr) {
+			/* ToDo: handle short addresses */
+			/* dst pan/addr + src addr */
+			hdr_len += IEEE802154_PAN_ID_LENGTH +
+				(IEEE802154_EXT_ADDR_LENGTH * 2);
+		} else {
+			/* src pan/addr only */
+			hdr_len += IEEE802154_PAN_ID_LENGTH +
+				IEEE802154_EXT_ADDR_LENGTH;
+		}
+	}
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
+		goto done;
+	}
+
+	/* Compute aux-sec hdr size and add it to hdr_len */
+	hdr_len += IEEE802154_SECURITY_CF_LENGTH +
+		IEEE802154_SECURITY_FRAME_COUNTER_LENGTH;
+
+	switch (sec_ctx->key_mode) {
+	case IEEE802154_KEY_ID_MODE_IMPLICIT:
+		/* The only mode supported for now,
+		 * generate_aux_securiy_hdr() will fail on other modes
+		 */
+		break;
+	case IEEE802154_KEY_ID_MODE_INDEX:
+		hdr_len += IEEE8021254_KEY_ID_FIELD_INDEX_LENGTH;
+		break;
+	case IEEE802154_KEY_ID_MODE_SRC_4_INDEX:
+		hdr_len += IEEE8021254_KEY_ID_FIELD_SRC_4_INDEX_LENGTH;
+		break;
+	case IEEE802154_KEY_ID_MODE_SRC_8_INDEX:
+		hdr_len += IEEE8021254_KEY_ID_FIELD_SRC_8_INDEX_LENGTH;
+	}
+
+	/* This is a _HACK_: as net_buf do not let the possibility to
+	 * reserve tailroom - here for authentication tag - it "reserves"
+	 * it in headroom so the payload won't occupy all the left space
+	 * and then when it will come to finalize the data frame it will
+	 * reduce the reserved space by the tag size, move the payload
+	 * backward accordingly, and only then: run the
+	 * encryption/authentication which will fill the tag space in the end.
+	 */
+	if (sec_ctx->level < IEEE802154_SECURITY_LEVEL_ENC) {
+		hdr_len += level_2_tag_size[sec_ctx->level];
+	} else {
+		hdr_len += level_2_tag_size[sec_ctx->level - 4];
+	}
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+done:
+	NET_DBG("Computed size of %u", hdr_len);
+
+	return hdr_len;
+}
+
+static inline struct ieee802154_fcf_seq *generate_fcf_grounds(uint8_t **p_buf,
+							      bool ack)
+{
+	struct ieee802154_fcf_seq *fs;
+
+	fs = (struct ieee802154_fcf_seq *) *p_buf;
+
+	fs->fc.security_enabled = 0U;
+	fs->fc.frame_pending = 0U;
+	fs->fc.ar = ack;
+	fs->fc.pan_id_comp = 0U;
+	fs->fc.reserved = 0U;
+	/** We support version 2006 only for now */
+	fs->fc.seq_num_suppr = 0U;
+	fs->fc.ie_list = 0U;
+	fs->fc.frame_version = IEEE802154_VERSION_802154_2006;
+
+	*p_buf += sizeof(struct ieee802154_fcf_seq);
+
+	return fs;
+}
+
+static inline enum ieee802154_addressing_mode
+get_dst_addr_mode(struct net_linkaddr *dst, bool *broadcast)
+{
+	if (!dst->addr) {
+		NET_DBG("Broadcast destination");
+
+		*broadcast = true;
+
+		return IEEE802154_ADDR_MODE_SHORT;
+	}
+
+	*broadcast = false;
+
+	if (dst->len == IEEE802154_SHORT_ADDR_LENGTH) {
+		return IEEE802154_ADDR_MODE_SHORT;
+	}
+
+	if (dst->len == IEEE802154_EXT_ADDR_LENGTH) {
+		return IEEE802154_ADDR_MODE_EXTENDED;
+	}
+
+	return IEEE802154_ADDR_MODE_NONE;
+}
+
+static inline
+bool data_addr_to_fs_settings(struct net_linkaddr *dst,
+			      struct ieee802154_fcf_seq *fs,
+			      struct ieee802154_frame_params *params)
+{
+	bool broadcast;
+
+	fs->fc.dst_addr_mode = get_dst_addr_mode(dst, &broadcast);
+	if (fs->fc.dst_addr_mode != IEEE802154_ADDR_MODE_NONE) {
+		fs->fc.pan_id_comp = 1U;
+
+		if (broadcast) {
+			params->dst.short_addr = IEEE802154_BROADCAST_ADDRESS;
+			params->dst.len = IEEE802154_SHORT_ADDR_LENGTH;
+			fs->fc.ar = 0U;
+		} else {
+			params->dst.ext_addr = dst->addr;
+			params->dst.len = dst->len;
+		}
+	}
+
+	if (fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_SHORT && !broadcast) {
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_SHORT;
+	} else {
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+	}
+
+	return broadcast;
+}
+
+static
+uint8_t *generate_addressing_fields(struct ieee802154_context *ctx,
+				 struct ieee802154_fcf_seq *fs,
+				 struct ieee802154_frame_params *params,
+				 uint8_t *p_buf)
+{
+	struct ieee802154_address_field *af;
+	struct ieee802154_address *src_addr;
+
+	if (fs->fc.dst_addr_mode != IEEE802154_ADDR_MODE_NONE) {
+		af = (struct ieee802154_address_field *)p_buf;
+		af->plain.pan_id = params->dst.pan_id;
+
+		if (fs->fc.dst_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
+			af->plain.addr.short_addr =
+				sys_cpu_to_le16(params->dst.short_addr);
+			p_buf += IEEE802154_PAN_ID_LENGTH +
+				IEEE802154_SHORT_ADDR_LENGTH;
+		} else {
+			sys_memcpy_swap(af->plain.addr.ext_addr,
+					params->dst.ext_addr,
+					IEEE802154_EXT_ADDR_LENGTH);
+			p_buf += IEEE802154_PAN_ID_LENGTH +
+				IEEE802154_EXT_ADDR_LENGTH;
+		}
+	}
+
+	if (fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_NONE) {
+		return p_buf;
+	}
+
+	af = (struct ieee802154_address_field *)p_buf;
+
+	if (!fs->fc.pan_id_comp) {
+		af->plain.pan_id = params->pan_id;
+		src_addr = &af->plain.addr;
+		p_buf += IEEE802154_PAN_ID_LENGTH;
+	} else {
+		src_addr = &af->comp.addr;
+	}
+
+	if (fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
+		src_addr->short_addr = sys_cpu_to_le16(params->short_addr);
+		p_buf += IEEE802154_SHORT_ADDR_LENGTH;
+	} else {
+		memcpy(src_addr->ext_addr, ctx->ext_addr,
+		       IEEE802154_EXT_ADDR_LENGTH);
+		p_buf += IEEE802154_EXT_ADDR_LENGTH;
+	}
+
+	return p_buf;
+}
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+static
+uint8_t *generate_aux_security_hdr(struct ieee802154_security_ctx *sec_ctx,
+				uint8_t *p_buf)
+{
+	struct ieee802154_aux_security_hdr *aux_sec;
+
+	if (sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
+		return p_buf;
+	}
+
+	if (sec_ctx->key_mode != IEEE802154_KEY_ID_MODE_IMPLICIT) {
+		/* ToDo: it supports implicit mode only, for now */
+		return NULL;
+	}
+
+	aux_sec = (struct ieee802154_aux_security_hdr *)p_buf;
+
+	aux_sec->control.security_level = sec_ctx->level;
+	aux_sec->control.key_id_mode = sec_ctx->key_mode;
+	aux_sec->control.reserved = 0U;
+
+	aux_sec->frame_counter = sys_cpu_to_le32(sec_ctx->frame_counter);
+
+	return p_buf + IEEE802154_SECURITY_CF_LENGTH +
+		IEEE802154_SECURITY_FRAME_COUNTER_LENGTH;
+}
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+bool ieee802154_create_data_frame(struct ieee802154_context *ctx,
+				  struct net_linkaddr *dst,
+				  struct net_buf *buf,
+				  uint8_t hdr_size)
+{
+	struct ieee802154_frame_params params;
+	struct ieee802154_fcf_seq *fs;
+	uint8_t *p_buf = buf->data;
+	uint8_t *buf_start = p_buf;
+	bool broadcast;
+
+	fs = generate_fcf_grounds(&p_buf, ctx->ack_requested);
+
+	fs->fc.frame_type = IEEE802154_FRAME_TYPE_DATA;
+	fs->sequence = ctx->sequence++;
+
+	params.dst.pan_id = ctx->pan_id;
+	params.pan_id = ctx->pan_id;
+
+	broadcast = data_addr_to_fs_settings(dst, fs, &params);
+
+	p_buf = generate_addressing_fields(ctx, fs, &params, p_buf);
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (broadcast) {
+		NET_DBG("No security hdr needed: broadcasting");
+
+		goto no_security_hdr;
+	}
+
+	fs->fc.security_enabled = 1U;
+
+	p_buf = generate_aux_security_hdr(&ctx->sec_ctx, p_buf);
+
+	/* If tagged, let's retrieve tag space from hdr reserved space.
+	 * See comment in ieee802154_compute_header_size()
+	 */
+	if (ctx->sec_ctx.level != IEEE802154_SECURITY_LEVEL_NONE &&
+	    ctx->sec_ctx.level != IEEE802154_SECURITY_LEVEL_ENC) {
+		uint8_t level;
+
+		level = ctx->sec_ctx.level;
+		if (level >= IEEE802154_SECURITY_LEVEL_ENC) {
+			level -= 4U;
+		}
+
+		/* p_buf should point to the right place */
+		memmove(p_buf, buf->data, buf->len);
+		hdr_size -= level_2_tag_size[level];
+	}
+
+no_security_hdr:
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+	if ((p_buf - buf_start) != hdr_size) {
+		/* hdr_size was too small? We probably overwrote
+		 * payload bytes
+		 */
+		NET_ERR("Could not generate data frame %zu vs %u",
+			(p_buf - buf_start), hdr_size);
+		return false;
+	}
+
+	dbg_print_fs(fs);
+
+	/* Let's encrypt/auth only in the end, is needed */
+	return ieee802154_encrypt_auth(broadcast ? NULL : &ctx->sec_ctx,
+				       buf_start, hdr_size, buf->len,
+				       ctx->ext_addr);
+}
+
+#ifdef CONFIG_NET_L2_IEEE802154_RFD
+
+static inline bool cfi_to_fs_settings(enum ieee802154_cfi cfi,
+				      struct ieee802154_fcf_seq *fs,
+				      struct ieee802154_frame_params *params)
+{
+	switch (cfi) {
+	case IEEE802154_CFI_DISASSOCIATION_NOTIFICATION:
+		fs->fc.ar = 1U;
+		fs->fc.pan_id_comp = 1U;
+
+		__fallthrough;
+	case IEEE802154_CFI_ASSOCIATION_REQUEST:
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+
+		if (params->dst.len == IEEE802154_SHORT_ADDR_LENGTH) {
+			fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_SHORT;
+		} else {
+			fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+		}
+
+		break;
+	case IEEE802154_CFI_ASSOCIATION_RESPONSE:
+	case IEEE802154_CFI_PAN_ID_CONLICT_NOTIFICATION:
+		fs->fc.ar = 1U;
+		fs->fc.pan_id_comp = 1U;
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+		fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+
+		break;
+	case IEEE802154_CFI_DATA_REQUEST:
+		fs->fc.ar = 1U;
+		/* ToDo: src/dst addr mode: see 5.3.4 */
+
+		break;
+	case IEEE802154_CFI_ORPHAN_NOTIFICATION:
+		fs->fc.pan_id_comp = 1U;
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+		fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_SHORT;
+
+		break;
+	case IEEE802154_CFI_BEACON_REQUEST:
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_NONE;
+		fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_SHORT;
+		break;
+	case IEEE802154_CFI_COORDINATOR_REALIGNEMENT:
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
+		/* Todo: ar and dst addr mode: see 5.3.8 */
+
+		break;
+	case IEEE802154_CFI_GTS_REQUEST:
+		fs->fc.ar = 1U;
+		fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_SHORT;
+		fs->fc.dst_addr_mode = IEEE802154_ADDR_MODE_NONE;
+
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+static inline uint8_t mac_command_length(enum ieee802154_cfi cfi)
+{
+	uint8_t length = 1U; /* cfi is at least present */
+
+	switch (cfi) {
+	case IEEE802154_CFI_ASSOCIATION_REQUEST:
+	case IEEE802154_CFI_DISASSOCIATION_NOTIFICATION:
+	case IEEE802154_CFI_GTS_REQUEST:
+		length += 1U;
+		break;
+	case IEEE802154_CFI_ASSOCIATION_RESPONSE:
+		length += 3U;
+		break;
+	case IEEE802154_CFI_COORDINATOR_REALIGNEMENT:
+		length += 8U;
+		break;
+	default:
+		break;
+	}
+
+	return length;
+}
+
+struct net_pkt *
+ieee802154_create_mac_cmd_frame(struct net_if *iface,
+				enum ieee802154_cfi type,
+				struct ieee802154_frame_params *params)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_fcf_seq *fs;
+	struct net_pkt *pkt;
+	uint8_t *p_buf, *p_start;
+
+	/* It would be costly to compute the size when actual frame are never
+	 * bigger than 125 bytes, so let's allocate that size as buffer.
+	 */
+	pkt = net_pkt_alloc_with_buffer(iface,
+					IEEE802154_MTU - IEEE802154_MFR_LENGTH,
+					AF_UNSPEC, 0, BUF_TIMEOUT);
+	if (!pkt) {
+		return NULL;
+	}
+
+	p_buf = net_pkt_data(pkt);
+	p_start = p_buf;
+
+	fs = generate_fcf_grounds(&p_buf,
+				  type == IEEE802154_CFI_BEACON_REQUEST ?
+				  false : ctx->ack_requested);
+
+	fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND;
+	fs->sequence = ctx->sequence;
+
+	if (!cfi_to_fs_settings(type, fs, params)) {
+		goto error;
+	}
+
+	p_buf = generate_addressing_fields(ctx, fs, params, p_buf);
+
+	net_buf_add(pkt->buffer, p_buf - p_start);
+
+	/* Let's insert the cfi */
+	((struct ieee802154_command *)p_buf)->cfi = type;
+
+	dbg_print_fs(fs);
+
+	return pkt;
+error:
+	net_pkt_unref(pkt);
+
+	return NULL;
+}
+
+void ieee802154_mac_cmd_finalize(struct net_pkt *pkt,
+				 enum ieee802154_cfi type)
+{
+	net_buf_add(pkt->buffer, mac_command_length(type));
+}
+
+#endif /* CONFIG_NET_L2_IEEE802154_RFD */
+
+#ifdef CONFIG_NET_L2_IEEE802154_ACK_REPLY
+bool ieee802154_create_ack_frame(struct net_if *iface,
+				 struct net_pkt *pkt, uint8_t seq)
+{
+	uint8_t *p_buf = net_pkt_data(pkt);
+	struct ieee802154_fcf_seq *fs;
+
+	if (!p_buf) {
+		return false;
+	}
+
+	fs = generate_fcf_grounds(&p_buf, false);
+
+	fs->fc.dst_addr_mode = 0U;
+	fs->fc.src_addr_mode = 0U;
+
+	fs->fc.frame_type = IEEE802154_FRAME_TYPE_ACK;
+	fs->sequence = seq;
+
+	net_buf_add(pkt->buffer, IEEE802154_ACK_PKT_LENGTH);
+
+	return true;
+}
+#endif /* CONFIG_NET_L2_IEEE802154_ACK_REPLY */
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_pkt *pkt,
+				    struct ieee802154_mpdu *mpdu)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	uint8_t level;
+
+	if (!mpdu->mhr.fs->fc.security_enabled) {
+		return true;
+	}
+
+	/* Section 7.2.3 (i) talks about "security level policy" conformance
+	 * but such policy does not seem to be detailed. So let's assume both
+	 * ends should have same security level.
+	 */
+	if (mpdu->mhr.aux_sec->control.security_level != ctx->sec_ctx.level) {
+		return false;
+	}
+
+	/* ToDo: handle src short address
+	 * This will require to look up in nbr cache with short addr
+	 * in order to get the extended address related to it
+	 */
+	if (!ieee802154_decrypt_auth(&ctx->sec_ctx, net_pkt_data(pkt),
+				     (uint8_t *)mpdu->payload - net_pkt_data(pkt),
+				     net_pkt_get_len(pkt),
+				     net_pkt_lladdr_src(pkt)->addr,
+				     sys_le32_to_cpu(
+					mpdu->mhr.aux_sec->frame_counter))) {
+		NET_ERR("Could not decipher the frame");
+		return false;
+	}
+
+	level = ctx->sec_ctx.level;
+	if (level >= IEEE802154_SECURITY_LEVEL_ENC) {
+		level -= 4U;
+	}
+
+	/* We remove tag size from buf's length, it is now useless */
+	pkt->buffer->len -= level_2_tag_size[level];
+
+	return true;
+}
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt.c	(working copy)
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_mgmt, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <net/net_core.h>
+
+#include <errno.h>
+
+#include <net/net_if.h>
+#include <net/ieee802154_radio.h>
+#include <net/ieee802154_mgmt.h>
+#include <net/ieee802154.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_mgmt_priv.h"
+#include "ieee802154_security.h"
+#include "ieee802154_utils.h"
+#include "ieee802154_radio_utils.h"
+
+enum net_verdict ieee802154_handle_beacon(struct net_if *iface,
+					  struct ieee802154_mpdu *mpdu,
+					  uint8_t lqi)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	NET_DBG("Beacon received");
+
+	if (!ctx->scan_ctx) {
+		return NET_DROP;
+	}
+
+	if (!mpdu->beacon->sf.association) {
+		return NET_DROP;
+	}
+
+	k_sem_take(&ctx->res_lock, K_FOREVER);
+
+	ctx->scan_ctx->pan_id = mpdu->mhr.src_addr->plain.pan_id;
+	ctx->scan_ctx->lqi = lqi;
+
+	if (mpdu->mhr.fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
+		ctx->scan_ctx->len = IEEE802154_SHORT_ADDR_LENGTH;
+		ctx->scan_ctx->short_addr =
+			mpdu->mhr.src_addr->plain.addr.short_addr;
+	} else {
+		ctx->scan_ctx->len = IEEE802154_EXT_ADDR_LENGTH;
+		sys_memcpy_swap(ctx->scan_ctx->addr,
+				mpdu->mhr.src_addr->plain.addr.ext_addr,
+				IEEE802154_EXT_ADDR_LENGTH);
+	}
+
+	net_mgmt_event_notify(NET_EVENT_IEEE802154_SCAN_RESULT, iface);
+
+	k_sem_give(&ctx->res_lock);
+
+	return NET_OK;
+}
+
+static int ieee802154_cancel_scan(uint32_t mgmt_request, struct net_if *iface,
+				  void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	ARG_UNUSED(data);
+	ARG_UNUSED(len);
+
+	NET_DBG("Cancelling scan request");
+
+	ctx->scan_ctx = NULL;
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_CANCEL_SCAN,
+				  ieee802154_cancel_scan);
+
+static int ieee802154_scan(uint32_t mgmt_request, struct net_if *iface,
+			   void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_req_params *scan =
+		(struct ieee802154_req_params *)data;
+	struct net_pkt *pkt = NULL;
+	uint8_t channel;
+	int ret;
+
+	NET_DBG("%s scan requested",
+		mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN ?
+		"Active" : "Passive");
+
+	if (ctx->scan_ctx) {
+		return -EALREADY;
+	}
+
+	if (scan == NULL) {
+		return -EINVAL;
+	}
+
+	if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
+		struct ieee802154_frame_params params;
+
+		params.dst.short_addr = IEEE802154_BROADCAST_ADDRESS;
+		params.dst.pan_id = IEEE802154_BROADCAST_PAN_ID;
+
+		pkt = ieee802154_create_mac_cmd_frame(
+			iface, IEEE802154_CFI_BEACON_REQUEST, &params);
+		if (!pkt) {
+			NET_DBG("Could not create Beacon Request");
+			return -ENOBUFS;
+		}
+
+		ieee802154_mac_cmd_finalize(pkt, IEEE802154_CFI_BEACON_REQUEST);
+	}
+
+	ctx->scan_ctx = scan;
+	ret = 0;
+
+	ieee802154_filter_pan_id(iface, IEEE802154_BROADCAST_PAN_ID);
+
+	if (ieee802154_start(iface)) {
+		NET_DBG("Could not start device");
+		ret = -EIO;
+
+		goto out;
+	}
+
+	/* ToDo: For now, we assume we are on 2.4Ghz
+	 * (device will have to export capabilities) */
+	for (channel = 11U; channel <= 26U; channel++) {
+		if (IEEE802154_IS_CHAN_UNSCANNED(scan->channel_set, channel)) {
+			continue;
+		}
+
+		scan->channel = channel;
+		NET_DBG("Scanning channel %u", channel);
+		ieee802154_set_channel(iface, channel);
+
+		/* Active scan sends a beacon request */
+		if (mgmt_request == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
+			net_pkt_ref(pkt);
+			net_pkt_frag_ref(pkt->buffer);
+
+			ret = ieee802154_radio_send(iface, pkt, pkt->buffer);
+			if (ret) {
+				NET_DBG("Could not send Beacon Request (%d)",
+					ret);
+				net_pkt_unref(pkt);
+
+				break;
+			}
+		}
+
+		/* Context aware sleep */
+		k_sleep(K_MSEC(scan->duration));
+
+		if (!ctx->scan_ctx) {
+			NET_DBG("Scan request cancelled");
+			ret = -ECANCELED;
+
+			break;
+		}
+	}
+
+	/* Let's come back to context's settings */
+	ieee802154_filter_pan_id(iface, ctx->pan_id);
+	ieee802154_set_channel(iface, ctx->channel);
+out:
+	ctx->scan_ctx = NULL;
+
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	return ret;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_PASSIVE_SCAN,
+				  ieee802154_scan);
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ACTIVE_SCAN,
+				  ieee802154_scan);
+
+enum net_verdict ieee802154_handle_mac_command(struct net_if *iface,
+					       struct ieee802154_mpdu *mpdu)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	if (mpdu->command->cfi == IEEE802154_CFI_ASSOCIATION_RESPONSE) {
+		if (mpdu->command->assoc_res.status !=
+		    IEEE802154_ASF_SUCCESSFUL) {
+			return NET_DROP;
+		}
+
+		ctx->associated = true;
+		k_sem_give(&ctx->req_lock);
+
+		return NET_OK;
+	}
+
+	if (mpdu->command->cfi == IEEE802154_CFI_DISASSOCIATION_NOTIFICATION) {
+		if (mpdu->command->disassoc_note.reason !=
+		    IEEE802154_DRF_COORDINATOR_WISH) {
+			return NET_DROP;
+		}
+
+		if (ctx->associated) {
+			/* ToDo: check src address vs coord ones and reject
+			 * if they don't match
+			 */
+			ctx->associated = false;
+
+			return NET_OK;
+		}
+	}
+
+	NET_DBG("Drop MAC command, unsupported CFI: 0x%x",
+		mpdu->command->cfi);
+
+	return NET_DROP;
+}
+
+static int ieee802154_associate(uint32_t mgmt_request, struct net_if *iface,
+				void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_req_params *req =
+		(struct ieee802154_req_params *)data;
+	struct ieee802154_frame_params params;
+	struct ieee802154_command *cmd;
+	struct net_pkt *pkt;
+	int ret = 0;
+
+	k_sem_take(&ctx->req_lock, K_FOREVER);
+
+	params.dst.len = req->len;
+	if (params.dst.len == IEEE802154_SHORT_ADDR_LENGTH) {
+		params.dst.short_addr = req->short_addr;
+	} else {
+		params.dst.ext_addr = req->addr;
+	}
+
+	params.dst.pan_id = req->pan_id;
+	params.pan_id = req->pan_id;
+
+	/* Set channel first */
+	if (ieee802154_set_channel(iface, req->channel)) {
+		ret = -EIO;
+		goto out;
+	}
+
+	pkt = ieee802154_create_mac_cmd_frame(
+		iface, IEEE802154_CFI_ASSOCIATION_REQUEST, &params);
+	if (!pkt) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	cmd = ieee802154_get_mac_command(pkt);
+	cmd->assoc_req.ci.dev_type = 0U; /* RFD */
+	cmd->assoc_req.ci.power_src = 0U; /* ToDo: set right power source */
+	cmd->assoc_req.ci.rx_on = 1U; /* ToDo: that will depends on PM */
+	cmd->assoc_req.ci.sec_capability = 0U; /* ToDo: security support */
+	cmd->assoc_req.ci.alloc_addr = 0U; /* ToDo: handle short addr */
+
+	ctx->associated = false;
+
+	ieee802154_mac_cmd_finalize(pkt, IEEE802154_CFI_ASSOCIATION_REQUEST);
+
+	if (net_if_send_data(iface, pkt)) {
+		net_pkt_unref(pkt);
+		ret = -EIO;
+		goto out;
+	}
+
+	/* ToDo: current timeout is arbitrary */
+	k_sem_take(&ctx->req_lock, K_SECONDS(1));
+
+	if (ctx->associated) {
+		ctx->channel = req->channel;
+		ctx->pan_id = req->pan_id;
+
+		ctx->coord_addr_len = req->len;
+		if (ctx->coord_addr_len == IEEE802154_SHORT_ADDR_LENGTH) {
+			ctx->coord.short_addr = req->short_addr;
+		} else {
+			memcpy(ctx->coord.ext_addr,
+			       req->addr, IEEE802154_EXT_ADDR_LENGTH);
+		}
+	} else {
+		ret = -EACCES;
+	}
+
+out:
+	k_sem_give(&ctx->req_lock);
+
+	return ret;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_ASSOCIATE,
+				  ieee802154_associate);
+
+static int ieee802154_disassociate(uint32_t mgmt_request, struct net_if *iface,
+				   void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_frame_params params;
+	struct ieee802154_command *cmd;
+	struct net_pkt *pkt;
+
+	if (!ctx->associated) {
+		return -EALREADY;
+	}
+
+	params.dst.pan_id = ctx->pan_id;
+	params.dst.len = ctx->coord_addr_len;
+	if (params.dst.len == IEEE802154_SHORT_ADDR_LENGTH) {
+		params.dst.short_addr = ctx->coord.short_addr;
+	} else {
+		params.dst.ext_addr = ctx->coord.ext_addr;
+	}
+
+	params.pan_id = ctx->pan_id;
+
+	pkt = ieee802154_create_mac_cmd_frame(
+		iface, IEEE802154_CFI_DISASSOCIATION_NOTIFICATION, &params);
+	if (!pkt) {
+		return -ENOBUFS;
+	}
+
+	cmd = ieee802154_get_mac_command(pkt);
+	cmd->disassoc_note.reason = IEEE802154_DRF_DEVICE_WISH;
+
+	ieee802154_mac_cmd_finalize(
+		pkt, IEEE802154_CFI_DISASSOCIATION_NOTIFICATION);
+
+	if (net_if_send_data(iface, pkt)) {
+		net_pkt_unref(pkt);
+		return -EIO;
+	}
+
+	ctx->associated = false;
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_DISASSOCIATE,
+				  ieee802154_disassociate);
+
+static int ieee802154_set_ack(uint32_t mgmt_request, struct net_if *iface,
+			      void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	ARG_UNUSED(data);
+	ARG_UNUSED(len);
+
+	if (mgmt_request == NET_REQUEST_IEEE802154_SET_ACK) {
+		ctx->ack_requested = true;
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_UNSET_ACK) {
+		ctx->ack_requested = false;
+	}
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_ACK,
+				  ieee802154_set_ack);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_UNSET_ACK,
+				  ieee802154_set_ack);
+
+static int ieee802154_set_parameters(uint32_t mgmt_request,
+				     struct net_if *iface,
+				     void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	uint16_t value;
+	int ret = 0;
+
+	if (ctx->associated) {
+		return -EBUSY;
+	}
+
+	if (mgmt_request != NET_REQUEST_IEEE802154_SET_EXT_ADDR &&
+	    (len != sizeof(uint16_t) || !data)) {
+		return -EINVAL;
+	}
+
+	value = *((uint16_t *) data);
+
+	if (mgmt_request == NET_REQUEST_IEEE802154_SET_CHANNEL) {
+		if (ctx->channel != value) {
+			if (!ieee802154_verify_channel(iface, value)) {
+				return -EINVAL;
+			}
+
+			ret = ieee802154_set_channel(iface, value);
+			if (!ret) {
+				ctx->channel = value;
+			}
+		}
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_PAN_ID) {
+		if (ctx->pan_id != value) {
+			ctx->pan_id = value;
+			ieee802154_filter_pan_id(iface, ctx->pan_id);
+		}
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_EXT_ADDR) {
+		if (len != IEEE802154_EXT_ADDR_LENGTH) {
+			return -EINVAL;
+		}
+
+		if (memcmp(ctx->ext_addr, data, IEEE802154_EXT_ADDR_LENGTH)) {
+			memcpy(ctx->ext_addr, data, IEEE802154_EXT_ADDR_LENGTH);
+			ieee802154_filter_ieee_addr(iface, ctx->ext_addr);
+		}
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_SHORT_ADDR) {
+		if (ctx->short_addr != value) {
+			ctx->short_addr = value;
+			ieee802154_filter_short_addr(iface, ctx->short_addr);
+		}
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_TX_POWER) {
+		if (ctx->tx_power != (int16_t)value) {
+			ret = ieee802154_set_tx_power(iface, (int16_t)value);
+			if (!ret) {
+				ctx->tx_power = (int16_t)value;
+			}
+		}
+	}
+
+	return ret;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_CHANNEL,
+				  ieee802154_set_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_PAN_ID,
+				  ieee802154_set_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_EXT_ADDR,
+				  ieee802154_set_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SHORT_ADDR,
+				  ieee802154_set_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_TX_POWER,
+				  ieee802154_set_parameters);
+
+static int ieee802154_get_parameters(uint32_t mgmt_request,
+				     struct net_if *iface,
+				     void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	uint16_t *value;
+
+	if (mgmt_request != NET_REQUEST_IEEE802154_GET_EXT_ADDR &&
+	    (len != sizeof(uint16_t) || !data)) {
+		return -EINVAL;
+	}
+
+	value = (uint16_t *)data;
+
+	if (mgmt_request == NET_REQUEST_IEEE802154_GET_CHANNEL) {
+		*value = ctx->channel;
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_PAN_ID) {
+		*value = ctx->pan_id;
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_EXT_ADDR) {
+		if (len != IEEE802154_EXT_ADDR_LENGTH) {
+			return -EINVAL;
+		}
+
+		memcpy(data, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_SHORT_ADDR) {
+		*value = ctx->short_addr;
+	} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_TX_POWER) {
+		int16_t *s_value = (int16_t *)data;
+
+		*s_value = ctx->tx_power;
+	}
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_CHANNEL,
+				  ieee802154_get_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_PAN_ID,
+				  ieee802154_get_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_EXT_ADDR,
+				  ieee802154_get_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SHORT_ADDR,
+				  ieee802154_get_parameters);
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_TX_POWER,
+				  ieee802154_get_parameters);
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+
+static int ieee802154_set_security_settings(uint32_t mgmt_request,
+					    struct net_if *iface,
+					    void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_security_params *params;
+
+	if (ctx->associated) {
+		return -EBUSY;
+	}
+
+	if (len != sizeof(struct ieee802154_security_params) ||
+	    !data) {
+		return -EINVAL;
+	}
+
+	params = (struct ieee802154_security_params *)data;
+
+	if (ieee802154_security_setup_session(&ctx->sec_ctx, params->level,
+					      params->key_mode, params->key,
+					      params->key_len)) {
+		NET_ERR("Could not set the security parameters");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS,
+				  ieee802154_set_security_settings);
+
+static int ieee802154_get_security_settings(uint32_t mgmt_request,
+					    struct net_if *iface,
+					    void *data, size_t len)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	struct ieee802154_security_params *params;
+
+	if (len != sizeof(struct ieee802154_security_params) ||
+	    !data) {
+		return -EINVAL;
+	}
+
+	params = (struct ieee802154_security_params *)data;
+
+	memcpy(params->key, ctx->sec_ctx.key, ctx->sec_ctx.key_len);
+	params->key_len = ctx->sec_ctx.key_len;
+	params->key_mode = ctx->sec_ctx.key_mode;
+	params->level = ctx->sec_ctx.level;
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SECURITY_SETTINGS,
+				  ieee802154_get_security_settings);
+
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_mgmt_priv.h	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief IEEE 802.15.4 Private Management
+ */
+
+#ifndef __IEEE802154_MGMT_PRIV_H__
+#define __IEEE802154_MGMT_PRIV_H__
+
+#include "ieee802154_frame.h"
+
+#ifdef CONFIG_NET_MGMT
+
+static inline bool ieee802154_is_scanning(struct net_if *iface)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	return !(!ctx->scan_ctx);
+}
+
+static inline void ieee802154_mgmt_init(struct net_if *iface)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	k_sem_init(&ctx->res_lock, 1, 1);
+}
+
+enum net_verdict ieee802154_handle_beacon(struct net_if *iface,
+					  struct ieee802154_mpdu *mpdu,
+					  uint8_t lqi);
+
+enum net_verdict ieee802154_handle_mac_command(struct net_if *iface,
+					       struct ieee802154_mpdu *mpdu);
+
+#else /* CONFIG_NET_MGMT */
+
+#define ieee802154_is_scanning(...) false
+#define ieee802154_mgmt_init(...)
+#define ieee802154_handle_beacon(...) NET_DROP
+#define ieee802154_handle_mac_command(...) NET_DROP
+
+#endif /* CONFIG_NET_MGMT */
+
+#endif /* __IEEE802154_MGMT_PRIV_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c	(working copy)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_aloha, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_if.h>
+
+#include <errno.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_utils.h"
+#include "ieee802154_radio_utils.h"
+
+static inline int aloha_radio_send(struct net_if *iface,
+				   struct net_pkt *pkt,
+				   struct net_buf *frag)
+{
+	uint8_t retries = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES;
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	bool ack_required = prepare_for_ack(ctx, pkt, frag);
+	int ret = -EIO;
+
+	NET_DBG("frag %p", frag);
+
+	while (retries) {
+		retries--;
+
+		ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
+				    pkt, frag);
+		if (ret) {
+			continue;
+		}
+
+		ret = wait_for_ack(iface, ack_required);
+		if (!ret) {
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static enum net_verdict aloha_radio_handle_ack(struct net_if *iface,
+					       struct net_pkt *pkt)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
+	    ieee802154_get_hw_capabilities(iface) & IEEE802154_HW_CSMA) {
+		return NET_OK;
+	}
+
+	return handle_ack(ctx, pkt);
+}
+
+/* Declare the public Radio driver function used by the HW drivers */
+FUNC_ALIAS(aloha_radio_send,
+	   ieee802154_radio_send, int);
+
+FUNC_ALIAS(aloha_radio_handle_ack,
+	   ieee802154_radio_handle_ack, enum net_verdict);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c	(working copy)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_csma, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_if.h>
+
+#include <sys/util.h>
+#include <random/rand32.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_utils.h"
+#include "ieee802154_radio_utils.h"
+
+static inline int csma_ca_radio_send(struct net_if *iface,
+				     struct net_pkt *pkt,
+				     struct net_buf *frag)
+{
+	const uint8_t max_bo = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO;
+	const uint8_t max_be = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BE;
+	uint8_t retries = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES;
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+	bool ack_required = prepare_for_ack(ctx, pkt, frag);
+	uint8_t be = CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE;
+	uint8_t nb = 0U;
+	int ret = -EIO;
+
+	NET_DBG("frag %p", frag);
+
+loop:
+	while (retries) {
+		retries--;
+
+		if (be) {
+			uint8_t bo_n = sys_rand32_get() & ((1 << be) - 1);
+
+			k_busy_wait(bo_n * 20U);
+		}
+
+		while (1) {
+			if (!ieee802154_cca(iface)) {
+				break;
+			}
+
+			be = MIN(be + 1, max_be);
+			nb++;
+
+			if (nb > max_bo) {
+				goto loop;
+			}
+		}
+
+		ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT,
+				    pkt, frag);
+		if (ret) {
+			continue;
+		}
+
+		ret = wait_for_ack(iface, ack_required);
+		if (!ret) {
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static enum net_verdict csma_ca_radio_handle_ack(struct net_if *iface,
+						 struct net_pkt *pkt)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+	if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
+	    ieee802154_get_hw_capabilities(iface) & IEEE802154_HW_CSMA) {
+		return NET_OK;
+	}
+
+	return handle_ack(ctx, pkt);
+}
+
+/* Declare the public Radio driver function used by the HW drivers */
+FUNC_ALIAS(csma_ca_radio_send,
+	   ieee802154_radio_send, int);
+
+FUNC_ALIAS(csma_ca_radio_handle_ack,
+	   ieee802154_radio_handle_ack, enum net_verdict);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_utils.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_utils.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_radio_utils.h	(working copy)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __IEEE802154_RADIO_UTILS_H__
+#define __IEEE802154_RADIO_UTILS_H__
+
+#include "ieee802154_utils.h"
+
+/**
+ * @brief Radio driver sending function that radio drivers should implement
+ *
+ * @param iface A valid pointer on a network interface to send from
+ * @param pkt A valid pointer on a packet to send
+ *
+ * @return 0 on success, negative value otherwise
+ */
+extern int ieee802154_radio_send(struct net_if *iface,
+				 struct net_pkt *pkt,
+				 struct net_buf *frag);
+
+static inline bool prepare_for_ack(struct ieee802154_context *ctx,
+				   struct net_pkt *pkt,
+				   struct net_buf *frag)
+{
+	if (ieee802154_is_ar_flag_set(frag)) {
+		struct ieee802154_fcf_seq *fs;
+
+		fs = (struct ieee802154_fcf_seq *)frag->data;
+
+		ctx->ack_seq = fs->sequence;
+		ctx->ack_received = false;
+		k_sem_init(&ctx->ack_lock, 0, UINT_MAX);
+
+		return true;
+	}
+
+	return false;
+}
+
+static inline int wait_for_ack(struct net_if *iface,
+			       bool ack_required)
+{
+	struct ieee802154_context *ctx = net_if_l2_data(iface);
+
+
+	if (!ack_required ||
+	    (ieee802154_get_hw_capabilities(iface) & IEEE802154_HW_TX_RX_ACK)) {
+		return 0;
+	}
+
+	if (k_sem_take(&ctx->ack_lock, K_MSEC(10)) == 0) {
+		/*
+		 * We reinit the semaphore in case handle_ack
+		 * got called multiple times.
+		 */
+		k_sem_init(&ctx->ack_lock, 0, UINT_MAX);
+	}
+
+	ctx->ack_seq = 0U;
+
+	return ctx->ack_received ? 0 : -EIO;
+}
+
+static inline int handle_ack(struct ieee802154_context *ctx,
+			     struct net_pkt *pkt)
+{
+	if (pkt->buffer->len == IEEE802154_ACK_PKT_LENGTH) {
+		uint8_t len = IEEE802154_ACK_PKT_LENGTH;
+		struct ieee802154_fcf_seq *fs;
+
+		fs = ieee802154_validate_fc_seq(net_pkt_data(pkt), NULL, &len);
+		if (!fs || fs->sequence != ctx->ack_seq) {
+			return NET_CONTINUE;
+		}
+
+		ctx->ack_received = true;
+		k_sem_give(&ctx->ack_lock);
+
+		return NET_OK;
+	}
+
+	return NET_CONTINUE;
+}
+
+#endif /* __IEEE802154_RADIO_UTILS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.h	(working copy)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+
+#include <net/ieee802154.h>
+
+int ieee802154_security_setup_session(struct ieee802154_security_ctx *sec_ctx,
+				      uint8_t level, uint8_t key_mode,
+				      uint8_t *key, uint8_t key_len);
+
+bool ieee802154_decrypt_auth(struct ieee802154_security_ctx *sec_ctx,
+			     uint8_t *frame,
+			     uint8_t auth_payload_len,
+			     uint8_t decrypt_payload_len,
+			     uint8_t *src_ext_addr,
+			     uint32_t frame_counter);
+
+bool ieee802154_encrypt_auth(struct ieee802154_security_ctx *sec_ctx,
+			     uint8_t *frame,
+			     uint8_t auth_payload_len,
+			     uint8_t encrypt_payload_len,
+			     uint8_t *src_ext_addr);
+
+int ieee802154_security_init(struct ieee802154_security_ctx *sec_ctx);
+
+#else
+
+#define ieee802154_decrypt_auth(...) true
+#define ieee802154_encrypt_auth(...) true
+#define ieee802154_security_init(...) 0
+
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_security.c	(working copy)
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_security,
+		    CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <crypto/cipher.h>
+#include <net/net_core.h>
+
+#include "ieee802154_frame.h"
+#include "ieee802154_security.h"
+
+extern const uint8_t level_2_tag_size[4];
+
+int ieee802154_security_setup_session(struct ieee802154_security_ctx *sec_ctx,
+				      uint8_t level, uint8_t key_mode,
+				      uint8_t *key, uint8_t key_len)
+{
+	uint8_t tag_size;
+	int ret;
+
+	if (level > IEEE802154_SECURITY_LEVEL_ENC_MIC_128 ||
+	    key_mode > IEEE802154_KEY_ID_MODE_SRC_8_INDEX) {
+		return -EINVAL;
+	}
+
+	/* ToDo: supporting other key modes */
+	if (level > IEEE802154_SECURITY_LEVEL_NONE &&
+	    (key_len > IEEE802154_KEY_MAX_LEN || !key ||
+	     key_mode != IEEE802154_KEY_ID_MODE_IMPLICIT)) {
+		return -EINVAL;
+	}
+
+	if (level >= IEEE802154_SECURITY_LEVEL_ENC) {
+		tag_size = level_2_tag_size[level - 4];
+	} else {
+		tag_size = level_2_tag_size[level];
+	}
+
+	sec_ctx->level = level;
+
+	if (level > IEEE802154_SECURITY_LEVEL_NONE) {
+		memcpy(sec_ctx->key, key, key_len);
+		sec_ctx->key_len = key_len;
+		sec_ctx->key_mode = key_mode;
+
+		sec_ctx->enc.key.bit_stream = sec_ctx->key;
+		sec_ctx->enc.keylen = sec_ctx->key_len;
+
+		sec_ctx->dec.key.bit_stream = sec_ctx->key;
+		sec_ctx->dec.keylen = sec_ctx->key_len;
+	}
+
+	sec_ctx->enc.mode_params.ccm_info.tag_len = tag_size;
+	sec_ctx->dec.mode_params.ccm_info.tag_len = tag_size;
+
+	ret = cipher_begin_session(sec_ctx->enc.device, &sec_ctx->enc,
+				   CRYPTO_CIPHER_ALGO_AES,
+				   CRYPTO_CIPHER_MODE_CCM,
+				   CRYPTO_CIPHER_OP_ENCRYPT);
+	if (ret) {
+		NET_ERR("Could not setup encryption context");
+
+		return ret;
+	}
+
+	ret = cipher_begin_session(sec_ctx->dec.device, &sec_ctx->dec,
+				   CRYPTO_CIPHER_ALGO_AES,
+				   CRYPTO_CIPHER_MODE_CCM,
+				   CRYPTO_CIPHER_OP_DECRYPT);
+	if (ret) {
+		NET_ERR("Could not setup decryption context");
+		cipher_free_session(sec_ctx->enc.device, &sec_ctx->enc);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+bool ieee802154_decrypt_auth(struct ieee802154_security_ctx *sec_ctx,
+			     uint8_t *frame,
+			     uint8_t auth_payload_len,
+			     uint8_t decrypt_payload_len,
+			     uint8_t *src_ext_addr,
+			     uint32_t frame_counter)
+{
+	struct cipher_aead_pkt apkt;
+	struct cipher_pkt pkt;
+	uint8_t nonce[13];
+	int ret;
+
+	if (!sec_ctx || sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
+		return true;
+	}
+
+	/* See Section 7.3.2 */
+	memcpy(nonce, src_ext_addr, IEEE802154_EXT_ADDR_LENGTH);
+	nonce[8] = (uint8_t)(frame_counter >> 24);
+	nonce[9] = (uint8_t)(frame_counter >> 16);
+	nonce[10] = (uint8_t)(frame_counter >> 8);
+	nonce[11] = (uint8_t)frame_counter;
+	nonce[12] = sec_ctx->level;
+
+	pkt.in_buf = decrypt_payload_len ? frame + auth_payload_len : NULL;
+	pkt.in_len = decrypt_payload_len;
+	pkt.out_buf = frame;
+	pkt.out_buf_max = IEEE802154_MTU - IEEE802154_MFR_LENGTH;
+
+	apkt.ad = frame;
+	apkt.ad_len = auth_payload_len;
+	apkt.tag = sec_ctx->dec.mode_params.ccm_info.tag_len ?
+		frame + auth_payload_len + decrypt_payload_len : NULL;
+	apkt.pkt = &pkt;
+
+	ret = cipher_ccm_op(&sec_ctx->dec, &apkt, nonce);
+	if (ret) {
+		NET_ERR("Cannot decrypt/auth (%i): %p %u/%u - fc %u",
+			ret, frame, auth_payload_len, decrypt_payload_len,
+			frame_counter);
+		return false;
+	}
+
+	return true;
+}
+
+bool ieee802154_encrypt_auth(struct ieee802154_security_ctx *sec_ctx,
+			     uint8_t *frame,
+			     uint8_t auth_payload_len,
+			     uint8_t encrypt_payload_len,
+			     uint8_t *src_ext_addr)
+{
+	struct cipher_aead_pkt apkt;
+	struct cipher_pkt pkt;
+	uint8_t nonce[13];
+	int ret;
+
+	if (!sec_ctx || sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
+		return true;
+	}
+
+	/* See Section 7.3.2 */
+	memcpy(nonce, src_ext_addr, IEEE802154_EXT_ADDR_LENGTH);
+	sys_put_be32(sec_ctx->frame_counter, &nonce[8]);
+	nonce[12] = sec_ctx->level;
+
+	pkt.in_buf = encrypt_payload_len ? frame + auth_payload_len : NULL;
+	pkt.in_len = encrypt_payload_len;
+	pkt.out_buf = frame;
+	pkt.out_buf_max = IEEE802154_MTU - IEEE802154_MFR_LENGTH;
+
+	apkt.ad = frame;
+	apkt.ad_len = auth_payload_len;
+	apkt.tag = NULL;
+	apkt.pkt = &pkt;
+
+	ret = cipher_ccm_op(&sec_ctx->enc, &apkt, nonce);
+	if (ret) {
+		NET_ERR("Cannot encrypt/auth (%i): %p %u/%u - fc %u",
+			ret, frame, auth_payload_len, encrypt_payload_len,
+			sec_ctx->frame_counter);
+		return false;
+	}
+
+	sec_ctx->frame_counter++;
+
+	return true;
+}
+
+int ieee802154_security_init(struct ieee802154_security_ctx *sec_ctx)
+{
+	const struct device *dev;
+
+	(void)memset(&sec_ctx->enc, 0, sizeof(struct cipher_ctx));
+	(void)memset(&sec_ctx->dec, 0, sizeof(struct cipher_ctx));
+
+	dev = device_get_binding(
+		CONFIG_NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME);
+	if (!dev) {
+		return -ENODEV;
+	}
+
+	sec_ctx->enc.flags = cipher_query_hwcaps(dev);
+	sec_ctx->dec.flags = cipher_query_hwcaps(dev);
+
+	sec_ctx->enc.mode_params.ccm_info.nonce_len = 13U;
+	sec_ctx->dec.mode_params.ccm_info.nonce_len = 13U;
+
+	sec_ctx->enc.device = dev;
+	sec_ctx->dec.device = dev;
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_shell.c	(working copy)
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief IEEE 802.15.4 shell module
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ieee802154_shell, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <shell/shell.h>
+#include <sys/printk.h>
+
+#include <net/net_if.h>
+#include <net/ieee802154_mgmt.h>
+
+#include "ieee802154_frame.h"
+
+#define MAX_EXT_ADDR_STR_LEN sizeof("xx:xx:xx:xx:xx:xx:xx:xx")
+
+struct ieee802154_req_params params;
+static struct net_mgmt_event_callback scan_cb;
+static const struct shell *cb_shell;
+
+static int cmd_ieee802154_ack(const struct shell *shell,
+			      size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+
+	ARG_UNUSED(argc);
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (!strcmp(argv[1], "set") || !strcmp(argv[1], "1")) {
+		net_mgmt(NET_REQUEST_IEEE802154_SET_ACK, iface, NULL, 0);
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "ACK flag set on outgoing packets\n");
+
+		return 0;
+	}
+
+	if (!strcmp(argv[1], "unset") || !strcmp(argv[1], "0")) {
+		net_mgmt(NET_REQUEST_IEEE802154_UNSET_ACK, iface, NULL, 0);
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "ACK flag unset on outgoing packets\n");
+
+		return 0;
+	}
+
+	return 0;
+}
+
+static inline void parse_extended_address(char *addr, uint8_t *ext_addr)
+{
+	net_bytes_from_str(ext_addr, IEEE802154_EXT_ADDR_LENGTH, addr);
+}
+
+static int cmd_ieee802154_associate(const struct shell *shell,
+				    size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	char ext_addr[MAX_EXT_ADDR_STR_LEN];
+
+	if (argc < 3) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	params.pan_id = atoi(argv[1]);
+	strncpy(ext_addr, argv[2], MAX_EXT_ADDR_STR_LEN - 1);
+
+	if (strlen(ext_addr) == MAX_EXT_ADDR_STR_LEN) {
+		parse_extended_address(ext_addr, params.addr);
+		params.len = IEEE802154_EXT_ADDR_LENGTH;
+	} else {
+		params.short_addr = (uint16_t) atoi(ext_addr);
+		params.len = IEEE802154_SHORT_ADDR_LENGTH;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_ASSOCIATE, iface,
+		     &params, sizeof(struct ieee802154_req_params))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not associate to %s on PAN ID %u\n",
+			      argv[2], params.pan_id);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Associated to PAN ID %u\n", params.pan_id);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_disassociate(const struct shell *shell,
+				       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	int ret;
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	ret = net_mgmt(NET_REQUEST_IEEE802154_DISASSOCIATE, iface, NULL, 0);
+	if (ret == -EALREADY) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "Interface is not associated\n");
+
+		return -ENOEXEC;
+	} else if (ret) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not disassociate? (status: %i)\n", ret);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Interface is now disassociated\n");
+	}
+
+	return 0;
+}
+
+static inline uint32_t parse_channel_set(char *str_set)
+{
+	uint32_t channel_set = 0U;
+	char *p, *n;
+
+	p = str_set;
+
+	do {
+		uint32_t chan;
+
+		n = strchr(p, ':');
+		if (n) {
+			*n = '\0';
+		}
+
+		chan = atoi(p);
+		if (chan > 0 && chan < 32) {
+			channel_set |= BIT(chan - 1);
+		}
+
+		p = n ? n + 1 : n;
+	} while (n);
+
+	return channel_set;
+}
+
+static inline char *print_coordinator_address(char *buf, int buf_len)
+{
+	if (params.len == IEEE802154_EXT_ADDR_LENGTH) {
+		int i, pos = 0;
+
+		pos += snprintk(buf + pos, buf_len - pos, "(extended) ");
+
+		for (i = IEEE802154_EXT_ADDR_LENGTH - 1; i > -1; i--) {
+			pos += snprintk(buf + pos, buf_len - pos,
+					"%02X:", params.addr[i]);
+		}
+
+		buf[pos - 1] = '\0';
+	} else {
+		snprintk(buf, buf_len, "(short) %u", params.short_addr);
+	}
+
+	return buf;
+}
+
+static void scan_result_cb(struct net_mgmt_event_callback *cb,
+			   uint32_t mgmt_event, struct net_if *iface)
+{
+	char buf[64];
+
+	shell_fprintf(cb_shell, SHELL_NORMAL,
+		      "\nChannel: %u\tPAN ID: %u\tCoordinator Address: %s\t "
+		      "LQI: %u\n", params.channel, params.pan_id,
+		      print_coordinator_address(buf, sizeof(buf)), params.lqi);
+}
+
+static int cmd_ieee802154_scan(const struct shell *shell,
+			       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint32_t scan_type;
+	int ret;
+
+	if (argc < 3) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	(void)memset(&params, 0, sizeof(struct ieee802154_req_params));
+
+	net_mgmt_init_event_callback(&scan_cb, scan_result_cb,
+				     NET_EVENT_IEEE802154_SCAN_RESULT);
+
+	if (!strcmp(argv[1], "active")) {
+		scan_type = NET_REQUEST_IEEE802154_ACTIVE_SCAN;
+	} else if (!strcmp(argv[1], "passive")) {
+		scan_type = NET_REQUEST_IEEE802154_PASSIVE_SCAN;
+	} else {
+		return -ENOEXEC;
+	}
+
+	if (!strcmp(argv[2], "all")) {
+		params.channel_set = IEEE802154_ALL_CHANNELS;
+	} else {
+		params.channel_set = parse_channel_set(argv[2]);
+	}
+
+	if (!params.channel_set) {
+		return -ENOEXEC;
+	}
+
+	params.duration = atoi(argv[3]);
+
+	shell_fprintf(shell, SHELL_NORMAL,
+		      "%s Scanning (channel set: 0x%08x, duration %u ms)...\n",
+		      scan_type == NET_REQUEST_IEEE802154_ACTIVE_SCAN ?
+		      "Active" : "Passive", params.channel_set,
+		      params.duration);
+
+	cb_shell = shell;
+
+	if (scan_type == NET_REQUEST_IEEE802154_ACTIVE_SCAN) {
+		ret = net_mgmt(NET_REQUEST_IEEE802154_ACTIVE_SCAN, iface,
+			       &params, sizeof(struct ieee802154_req_params));
+	} else {
+		ret = net_mgmt(NET_REQUEST_IEEE802154_PASSIVE_SCAN, iface,
+			       &params, sizeof(struct ieee802154_req_params));
+	}
+
+	if (ret) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not raise a scan (status: %i)\n", ret);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Done\n");
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_set_chan(const struct shell *shell,
+				   size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t channel;
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	channel = (uint16_t)atoi(argv[1]);
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_CHANNEL, iface,
+		     &channel, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not set channel %u\n", channel);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Channel %u set\n", channel);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_get_chan(const struct shell *shell,
+				   size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t channel;
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_GET_CHANNEL, iface,
+		     &channel, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not get channel\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Channel %u\n", channel);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_set_pan_id(const struct shell *shell,
+				     size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t pan_id;
+
+	ARG_UNUSED(argc);
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	pan_id = (uint16_t)atoi(argv[1]);
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID, iface,
+		     &pan_id, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not set PAN ID %u\n", pan_id);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "PAN ID %u set\n", pan_id);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_get_pan_id(const struct shell *shell,
+				     size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t pan_id;
+
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_GET_PAN_ID, iface,
+		     &pan_id, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not get PAN ID\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "PAN ID %u (0x%x)\n", pan_id, pan_id);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_set_ext_addr(const struct shell *shell,
+				       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint8_t addr[IEEE802154_EXT_ADDR_LENGTH];
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (strlen(argv[1]) != MAX_EXT_ADDR_STR_LEN) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "%zd characters needed\n", MAX_EXT_ADDR_STR_LEN);
+		return -ENOEXEC;
+	}
+
+	parse_extended_address(argv[1], addr);
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_EXT_ADDR, iface,
+		     addr, IEEE802154_EXT_ADDR_LENGTH)) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not set extended address\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Extended address set\n");
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_get_ext_addr(const struct shell *shell,
+				       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint8_t addr[IEEE802154_EXT_ADDR_LENGTH];
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_GET_EXT_ADDR, iface,
+		     addr, IEEE802154_EXT_ADDR_LENGTH)) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not get extended address\n");
+		return -ENOEXEC;
+	} else {
+		static char ext_addr[MAX_EXT_ADDR_STR_LEN];
+		int i, j;
+
+		for (j = 0, i = IEEE802154_EXT_ADDR_LENGTH - 1; i > -1; i--) {
+			snprintf(&ext_addr[j], 4, "%02X:", addr[i]);
+
+			j += 3;
+		}
+
+		ext_addr[MAX_EXT_ADDR_STR_LEN - 1] = '\0';
+
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Extended address: %s\n", ext_addr);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_set_short_addr(const struct shell *shell,
+					 size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t short_addr;
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	short_addr = (uint16_t)atoi(argv[1]);
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_SHORT_ADDR, iface,
+		     &short_addr, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not set short address %u\n", short_addr);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Short address %u set\n", short_addr);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_get_short_addr(const struct shell *shell,
+					 size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	uint16_t short_addr;
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_GET_SHORT_ADDR, iface,
+		     &short_addr, sizeof(uint16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not get short address\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Short address %u\n", short_addr);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_set_tx_power(const struct shell *shell,
+				       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	int16_t tx_power;
+
+	if (argc < 2) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	tx_power = (int16_t)atoi(argv[1]);
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_TX_POWER, iface,
+		     &tx_power, sizeof(int16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not set TX power %d\n", tx_power);
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "TX power %d set\n", tx_power);
+	}
+
+	return 0;
+}
+
+static int cmd_ieee802154_get_tx_power(const struct shell *shell,
+				       size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_ieee802154();
+	int16_t tx_power;
+
+	if (!iface) {
+		shell_fprintf(shell, SHELL_INFO,
+			      "No IEEE 802.15.4 interface found.\n");
+		return -ENOEXEC;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_GET_TX_POWER, iface,
+		     &tx_power, sizeof(int16_t))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Could not get TX power\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "TX power (in dbm) %d\n", tx_power);
+	}
+
+	return 0;
+}
+
+SHELL_STATIC_SUBCMD_SET_CREATE(ieee802154_commands,
+	SHELL_CMD(ack, NULL,
+		  "<set/1 | unset/0> Set auto-ack flag",
+		  cmd_ieee802154_ack),
+	SHELL_CMD(associate, NULL,
+		  "<pan_id> <PAN coordinator short or long address (EUI-64)>",
+		  cmd_ieee802154_associate),
+	SHELL_CMD(disassociate,	NULL,
+		  "Disassociate from network",
+		  cmd_ieee802154_disassociate),
+	SHELL_CMD(get_chan, NULL,
+		  "Get currently used channel",
+		  cmd_ieee802154_get_chan),
+	SHELL_CMD(get_ext_addr,	NULL,
+		  "Get currently used extended address",
+		  cmd_ieee802154_get_ext_addr),
+	SHELL_CMD(get_pan_id, NULL,
+		  "Get currently used PAN id",
+		  cmd_ieee802154_get_pan_id),
+	SHELL_CMD(get_short_addr, NULL,
+		  "Get currently used short address",
+		  cmd_ieee802154_get_short_addr),
+	SHELL_CMD(get_tx_power,	NULL,
+		  "Get currently used TX power",
+		  cmd_ieee802154_get_tx_power),
+	SHELL_CMD(scan,	NULL,
+		  "<passive|active> <channels set n[:m:...]:x|all>"
+		  " <per-channel duration in ms>",
+		  cmd_ieee802154_scan),
+	SHELL_CMD(set_chan, NULL,
+		  "<channel> Set used channel",
+		  cmd_ieee802154_set_chan),
+	SHELL_CMD(set_ext_addr,	NULL,
+		  "<long/extended address (EUI-64)> Set extended address",
+		  cmd_ieee802154_set_ext_addr),
+	SHELL_CMD(set_pan_id, NULL,
+		  "<pan_id> Set used PAN id",
+		  cmd_ieee802154_set_pan_id),
+	SHELL_CMD(set_short_addr, NULL,
+		  "<short address> Set short address",
+		  cmd_ieee802154_set_short_addr),
+	SHELL_CMD(set_tx_power,	NULL,
+		  "<-18/-7/-4/-2/0/1/2/3/5> Set TX power",
+		  cmd_ieee802154_set_tx_power),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_CMD_REGISTER(ieee802154, &ieee802154_commands, "IEEE 802.15.4 commands",
+		   NULL);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_utils.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_utils.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ieee802154/ieee802154_utils.h	(working copy)
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief IEEE 802.15.4 Management
+ */
+
+#ifndef __IEEE802154_UTILS_H__
+#define __IEEE802154_UTILS_H__
+
+#include <net/ieee802154_radio.h>
+
+static inline
+enum ieee802154_hw_caps ieee802154_get_hw_capabilities(struct net_if *iface)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return 0;
+	}
+
+	return radio->get_capabilities(net_if_get_device(iface));
+}
+
+static inline int ieee802154_cca(struct net_if *iface)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->cca(net_if_get_device(iface));
+}
+
+static inline int ieee802154_set_channel(struct net_if *iface, uint16_t channel)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->set_channel(net_if_get_device(iface), channel);
+}
+
+static inline int ieee802154_set_tx_power(struct net_if *iface, int16_t dbm)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->set_txpower(net_if_get_device(iface), dbm);
+}
+
+static inline int ieee802154_tx(struct net_if *iface,
+				enum ieee802154_tx_mode mode,
+				struct net_pkt *pkt,
+				struct net_buf *buf)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->tx(net_if_get_device(iface), mode, pkt, buf);
+}
+
+static inline int ieee802154_start(struct net_if *iface)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->start(net_if_get_device(iface));
+}
+
+static inline int ieee802154_stop(struct net_if *iface)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return -ENOENT;
+	}
+
+	return radio->stop(net_if_get_device(iface));
+}
+
+static inline void ieee802154_filter_ieee_addr(struct net_if *iface,
+					       uint8_t *ieee_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.ieee_addr = ieee_addr;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_IEEE_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not apply IEEE address filter");
+		}
+	}
+}
+
+static inline void ieee802154_filter_short_addr(struct net_if *iface,
+						uint16_t short_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.short_addr = short_addr;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_SHORT_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not apply short address filter");
+		}
+	}
+}
+
+static inline void ieee802154_filter_pan_id(struct net_if *iface,
+					    uint16_t pan_id)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.pan_id = pan_id;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_PAN_ID,
+				  &filter) != 0) {
+			NET_WARN("Could not apply PAN ID filter");
+		}
+	}
+}
+
+static inline void ieee802154_filter_src_ieee_addr(struct net_if *iface,
+						   uint8_t *ieee_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.ieee_addr = ieee_addr;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not apply SRC IEEE address filter");
+		}
+	}
+}
+
+static inline void ieee802154_filter_src_short_addr(struct net_if *iface,
+						    uint16_t short_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.short_addr = short_addr;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not apply SRC short address filter");
+		}
+	}
+}
+
+static inline void ieee802154_remove_src_ieee_addr(struct net_if *iface,
+						   uint8_t *ieee_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.ieee_addr = ieee_addr;
+
+		if (radio->filter(net_if_get_device(iface), false,
+				  IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not remove SRC IEEE address filter");
+		}
+	}
+}
+
+static inline void ieee802154_remove_src_short_addr(struct net_if *iface,
+						    uint16_t short_addr)
+{
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
+		      IEEE802154_HW_FILTER)) {
+		struct ieee802154_filter filter;
+
+		filter.short_addr = short_addr;
+
+		if (radio->filter(net_if_get_device(iface), true,
+				  IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
+				  &filter) != 0) {
+			NET_WARN("Could not remove SRC short address filter");
+		}
+	}
+}
+
+static inline bool ieee802154_verify_channel(struct net_if *iface,
+					     uint16_t channel)
+{
+	if (channel == IEEE802154_NO_CHANNEL) {
+		return false;
+	}
+
+#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
+	const struct ieee802154_radio_api *radio =
+		net_if_get_device(iface)->api;
+
+	if (!radio) {
+		return false;
+	}
+
+	if (radio->get_capabilities(net_if_get_device(iface)) &
+	    IEEE802154_HW_SUB_GHZ) {
+		if (channel >
+		    radio->get_subg_channel_count(net_if_get_device(iface))) {
+			return false;
+		}
+	}
+#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
+
+	return true;
+}
+
+#endif /* __IEEE802154_UTILS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/CMakeLists.txt	(working copy)
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library_named(subsys__net__ip__l2__openthread)
+zephyr_library_include_directories(. ../../lib/openthread/platform
+  ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources(
+  openthread.c
+  openthread_utils.c
+  )
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig	(working copy)
@@ -0,0 +1,257 @@
+# OpenThread driver configuration options
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_L2_OPENTHREAD
+	bool "OpenThread L2"
+	depends on NETWORKING
+
+	select SETTINGS
+	select FLASH
+	select FLASH_PAGE_LAYOUT
+	select FLASH_MAP
+	select MPU_ALLOW_FLASH_WRITE
+	select NVS
+
+	select CPLUSPLUS
+	select REBOOT
+	select ENTROPY_GENERATOR
+
+	imply NET_UDP
+	imply NET_IPV6
+	imply NET_CONFIG_NEED_IPV6
+
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_IMPLEMENTATION
+	prompt "OpenThread origin selection"
+	help
+	  Select OpenThread to use for build. Custom OpenThread implementations
+	  can be added to the application Kconfig.
+
+config OPENTHREAD_SOURCES
+	bool "OpenThread from sources"
+	help
+	  Build Zephyr's OpenThread port from sources.
+
+endchoice
+
+config OPENTHREAD_MANUAL_START
+	bool "Start OpenThread stack manually"
+	help
+	  If enabled, OpenThread stack will have to be configured and
+	  started manually, with respective API calls or CLI/NCP commands.
+	  Otherwise, OpenThread will configure the network parametrs and try to
+	  join the Thread network automatically during initialization (using
+	  credentials stored in persistend storage, obtained during
+	  commissioning or pre-commissioned with other Kconfig options,
+	  depending on configuration used).
+
+menu "OpenThread stack features"
+source "subsys/net/l2/openthread/Kconfig.features"
+endmenu
+
+menu "Thread Network configuration"
+source "subsys/net/l2/openthread/Kconfig.thread"
+endmenu
+
+menu "Logging"
+
+menuconfig OPENTHREAD_DEBUG
+	bool "OpenThread stack logging support"
+	depends on NET_L2_OPENTHREAD
+	help
+	  This option enables logging support for OpenThread.
+
+choice
+	prompt "OpenThread stack log level"
+	depends on OPENTHREAD_DEBUG
+	help
+	  This option selects log level for OpenThread stack.
+
+config OPENTHREAD_LOG_LEVEL_CRIT
+	bool "Critical"
+config OPENTHREAD_LOG_LEVEL_WARN
+	bool "Warning"
+config OPENTHREAD_LOG_LEVEL_NOTE
+	bool "Notice"
+config OPENTHREAD_LOG_LEVEL_INFO
+	bool "Informational"
+config OPENTHREAD_LOG_LEVEL_DEBG
+	bool "Debug"
+endchoice
+
+config OPENTHREAD_LOG_LEVEL
+	int
+	default 1 if OPENTHREAD_LOG_LEVEL_CRIT
+	default 2 if OPENTHREAD_LOG_LEVEL_WARN
+	default 3 if OPENTHREAD_LOG_LEVEL_NOTE
+	default 4 if OPENTHREAD_LOG_LEVEL_INFO
+	default 5 if OPENTHREAD_LOG_LEVEL_DEBG
+	default 0
+
+menuconfig OPENTHREAD_L2_DEBUG
+	bool "OpenThread L2 log support"
+	help
+	  This option enables log support for OpenThread.
+
+if OPENTHREAD_L2_DEBUG
+
+config OPENTHREAD_L2_DEBUG_DUMP_15_4
+	bool "Dump 802.15.4 packets"
+	help
+	  This option enables dumping of 802.15.4 packets.
+
+config OPENTHREAD_L2_DEBUG_DUMP_IPV6
+	bool "Dump IPv6 packets"
+	help
+	  This option enables dumping of IPv6 packets.
+
+endif # OPENTHREAD_L2_DEBUG
+
+module = OPENTHREAD_L2
+module-dep = NET_LOG
+module-str = Log level for OpenThread driver
+module-help = Enables OpenThread driver to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endmenu # "Logging"
+
+menu "Zephyr optimizations"
+
+config OPENTHREAD_THREAD_PREEMPTIVE
+	bool "Set Openthread thread to be preemptive"
+
+config OPENTHREAD_THREAD_PRIORITY
+	int "OpenThread thread priority"
+	default 0 if OPENTHREAD_THREAD_PREEMPTIVE
+	default 8
+
+config OPENTHREAD_THREAD_STACK_SIZE
+	int "OpenThread thread stack size"
+	default 6144 if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	default 3072
+
+config OPENTHREAD_PKT_LIST_SIZE
+	int "List size for IPv6 packet buffering"
+	default 10
+
+endmenu # "Zephyr optimizations"
+
+config OPENTHREAD_SHELL
+	bool "Enable OpenThread shell"
+	select SHELL
+	default y
+
+config OPENTHREAD_MBEDTLS
+	bool "Enable built-in mbedtls for use with OpenThread"
+	default y
+	select MBEDTLS
+	select MBEDTLS_ENABLE_HEAP
+	select MBEDTLS_CIPHER_AES_ENABLED
+	select MBEDTLS_CIPHER_CCM_ENABLED
+	select MBEDTLS_MAC_SHA256_ENABLED
+	select MBEDTLS_ENTROPY_ENABLED
+	select MBEDTLS_MAC_CMAC_ENABLED
+	select MBEDTLS_CIPHER
+	select MBEDTLS_MD
+	select MBEDTLS_TLS_VERSION_1_2 if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_DTLS if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_ECP_DP_SECP256R1_ENABLED if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_ECP_NIST_OPTIM if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_SSL_EXPORT_KEYS if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_CTR_DRBG_ENABLED if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_HMAC_DRBG_ENABLED if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER
+	select MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED if OPENTHREAD_ECDSA
+
+config OPENTHREAD_MBEDTLS_LIB_NAME
+	string "mbedtls lib name"
+	default "mbedTLS"
+	help
+	  This option allows to specify one or more mbedtls library files to be
+	  linked with OpenThread. Separate multiple values with space " ".
+
+menuconfig OPENTHREAD_NCP
+	bool "Network Co-Processor"
+	select OPENTHREAD_MANUAL_START
+	select RING_BUFFER
+	select UART_INTERRUPT_DRIVEN
+	help
+	  Enable NCP in OpenThread stack.
+
+if OPENTHREAD_NCP
+
+config OPENTHREAD_NCP_RADIO
+	bool "Network Co-Processor as Radio"
+	help
+	  Enable NCP in OpenThread stack as radio-only.
+
+config OPENTHREAD_NCP_SPINEL_ON_UART_DEV_NAME
+	string "UART device to use for NCP SPINEL"
+	default "UART_0"
+	help
+	  UART device to use for NCP SPINEL.
+
+config OPENTHREAD_NCP_UART_RING_BUFFER_SIZE
+	int "Set NCP UART ring buffer size"
+	default 4096
+	help
+	  TX buffer size for the OpenThread NCP UART.
+
+config OPENTHREAD_NCP_SPINEL_ON_UART_ACM
+	bool "Run SPINEL over USB-ACM"
+	depends on USB_CDC_ACM
+	help
+	  Is the SPINEL device a USB-CDC-ACM device.
+
+config OPENTHREAD_NCP_VENDOR_HOOK_SOURCE
+	string "Path to NCP vendor hook source file"
+	help
+	  Provides path to compile ncp vendor hook file inside NCP component.
+
+config OPENTHREAD_NCP_BUFFER_SIZE
+	int "The size of the NCP buffers"
+	default 2048
+	help
+	  The size of the NCP buffers.
+
+endif # OPENTHREAD_NCP
+
+config OPENTHREAD_PLATFORM_INFO
+	string "Platform information for OpenThread"
+	default "ZEPHYR"
+	help
+	  Platform information for OpenThread
+
+config OPENTHREAD_CUSTOM_PARAMETERS
+	string "Custom Parameters to pass to OpenThread build system"
+	default ""
+	help
+	  This option is intended for advanced users only.
+	  Pass additional parameters that do not have corresponding Kconfig
+	  options to the OpenThread build system. Separate multiple values with
+	  space " ", for example:
+	  "OPENTHREAD_CONFIG_JOINER_ENABLE=1 OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES=3"
+
+config OPENTHREAD_NUM_MESSAGE_BUFFERS
+	int "The number of message buffers in the buffer pool"
+	default 128
+	help
+	  "The number of message buffers in the buffer pool."
+
+config OPENTHREAD_MAX_STATECHANGE_HANDLERS
+	int "The maximum number of state-changed callback handlers"
+	default 2
+	help
+	  The maximum number of state-changed callback handlers
+	  set using otSetStateChangedCallback.
+
+config OPENTHREAD_TMF_ADDRESS_CACHE_ENTRIES
+	int "The number of EID-to-RLOC cache entries"
+	default 20
+	help
+	  The number of EID-to-RLOC cache entries.
+
+endif # NET_L2_OPENTHREAD
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.features
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.features	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.features	(working copy)
@@ -0,0 +1,169 @@
+# OpenThread stack features selection
+
+# Copyright (c) 2020 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+choice
+	prompt "OpenThread stack version"
+	help
+	  This option selects version of Thread stack
+
+config OPENTHREAD_THREAD_VERSION_1_1
+	bool "Version 1.1"
+config OPENTHREAD_THREAD_VERSION_1_2
+	bool "Version 1.2"
+endchoice
+
+config OPENTHREAD_THREAD_VERSION
+	string
+	default "1.1" if OPENTHREAD_THREAD_VERSION_1_1
+	default "1.2" if OPENTHREAD_THREAD_VERSION_1_2
+	default "unknown"
+
+config OPENTHREAD_BACKBONE_ROUTER
+	bool "Enable Backbone Router functionality"
+
+config OPENTHREAD_BORDER_AGENT
+	bool "Enable Border Agent support"
+
+config OPENTHREAD_BORDER_ROUTER
+	bool "Enable Border Router support"
+
+config OPENTHREAD_COAP
+	bool "Enable OpenThread CoAP support"
+	help
+	  Enable CoAP API for the application with use of OpenThread stack
+
+config OPENTHREAD_COAPS
+	bool "Enable Secure CoAP API support"
+	depends on OPENTHREAD_COAP
+
+config OPENTHREAD_COAP_OBSERVE
+	bool "Enable CoAP Observe option support"
+
+config OPENTHREAD_COMMISSIONER
+	bool "Enable Commissioner functions support"
+	help
+	  Enable commissioner capability in OpenThread stack. Note, that DTLS
+	  handshake used in the commissioning procedure requires a larger
+	  mbedTLS heap than the default value. A minimum recommended value of
+	  CONFIG_MBEDTLS_HEAP_SIZE for the commissioning is 10KB.
+
+config OPENTHREAD_CHANNEL_MANAGER
+	bool "Enable channel manager support"
+	depends on OPENTHREAD_CHANNEL_MONITOR
+
+config OPENTHREAD_CHANNEL_MONITOR
+	bool "Enable channel monitor support"
+
+config OPENTHREAD_CHILD_SUPERVISION
+	bool "Enable child supervision support"
+
+config OPENTHREAD_CSL_RECEIVER
+	bool "Enable CSL Receiver support"
+	help
+	  Enable CSL Receiver support for Thread 1.2
+
+config OPENTHREAD_DHCP6_CLIENT
+	bool "Enable DHCPv6 client support"
+
+config OPENTHREAD_DHCP6_SERVER
+	bool "Enable DHCPv6 server support"
+
+config OPENTHREAD_DIAG
+	bool "Enable Diagnostic functions support"
+	help
+	  Enable OpenThread CLI diagnostic commands
+
+config OPENTHREAD_DNS_CLIENT
+	bool "Enable DNS client support"
+
+config OPENTHREAD_DUA
+	bool "Enable Domain Unicast Address support"
+	help
+	  Enable Domain Unicast Address feature for Thread 1.2
+
+config OPENTHREAD_LOG_LEVEL_DYNAMIC
+	bool "Enable dynamic log level control"
+
+config OPENTHREAD_ECDSA
+	bool "Enable ECDSA support"
+
+config OPENTHREAD_EXTERNAL_HEAP
+	bool "Enable external heap support"
+
+config OPENTHREAD_IP6_FRAGM
+	bool "Enable IPv6 fragmentation support"
+
+config OPENTHREAD_JAM_DETECTION
+	bool "Enable Jam detection support"
+
+config OPENTHREAD_JOINER
+	bool "Enable Joiner functions support"
+	help
+	  Enable joiner capability in OpenThread stack. Note, that DTLS
+	  handshake used in the commissioning procedure requires a larger
+	  mbedTLS heap than the default value. A minimum recommended value of
+	  CONFIG_MBEDTLS_HEAP_SIZE for the commissioning is 10KB.
+
+config OPENTHREAD_LEGACY
+	bool "Enable legacy network support"
+
+config OPENTHREAD_RAW
+	bool "Enable raw Link support"
+
+config OPENTHREAD_MAC_FILTER
+	bool "Enable MAC filter support"
+
+config OPENTHREAD_MLE_LONG_ROUTES
+	bool "Enable MLE long routes extension (experimental)"
+	help
+	  Enable MLE long routes extension (experimental, breaks Thread conformance)
+
+config OPENTHREAD_MLR
+	bool "Enable Multicast Listener Registration support"
+	help
+	  Enable Multicast Listener Registration support for Thread 1.2
+
+config OPENTHREAD_MTD_NETDIAG
+	bool "Enable TMF network diagnostics on MTDs"
+
+config OPENTHREAD_MULTIPLE_INSTANCE
+	bool "Enable OpenThread multiple instances"
+
+config OPENTHREAD_PLATFORM_UDP
+	bool "Enable platform UDP support"
+
+config OPENTHREAD_PLATFORM_NETIF
+	bool "Enable platform netif support"
+
+config OPENTHREAD_REFERENCE_DEVICE
+	bool "Enable Reference Device support"
+	help
+	  Enable Thread Certification reference device support in OpenThread stack
+
+config OPENTHREAD_ENABLE_SERVICE
+	bool "Enable Service support"
+	help
+	  Enable Thread Services capability in OpenThread stack
+
+config OPENTHREAD_SLAAC
+	bool "Enable SLAAC support"
+
+config OPENTHREAD_SNTP_CLIENT
+	bool "Enable SNTP Client support"
+
+config OPENTHREAD_TIME_SYNC
+	bool "Enable the time synchronization service feature"
+
+config OPENTHREAD_UDP_FORWARD
+	bool "Enable UDP forward support"
+
+config OPENTHREAD_SETTINGS_RAM
+	bool "Enable volatile-only storage of settings"
+
+config OPENTHREAD_OTNS
+	bool "Enable OTNS support"
+
+config OPENTHREAD_FULL_LOGS
+	bool "Enable OpenThread full logs"
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.thread
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.thread	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/Kconfig.thread	(working copy)
@@ -0,0 +1,64 @@
+# Thread network configuration options
+
+# Copyright (c) 2020 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+config OPENTHREAD_PANID
+	int "Default PAN ID"
+	default 43981
+
+config OPENTHREAD_CHANNEL
+	int "Default Channel"
+	default 11
+
+config OPENTHREAD_NETWORK_NAME
+	string "Default network name"
+	default "ot_zephyr"
+	help
+	  Network name for OpenThread
+
+config OPENTHREAD_XPANID
+	string "Default Extended PAN ID"
+	default "de:ad:00:be:ef:00:ca:fe"
+	help
+	  Extended PAN ID for OpenThread with
+	  format "de:ad:00:be:ef:00:ca:fe"
+
+config OPENTHREAD_JOINER_AUTOSTART
+	bool "Enable automatic joiner start"
+	depends on OPENTHREAD_JOINER
+
+config OPENTHREAD_JOINER_PSKD
+	string "Default pre shared key for the Joiner"
+	depends on OPENTHREAD_JOINER_AUTOSTART
+	default "J01NME"
+
+choice
+	prompt "OpenThread device type"
+	help
+	  This option selects Thread network device type
+
+config OPENTHREAD_FTD
+	bool "FTD - Full Thread Device"
+config OPENTHREAD_MTD
+	bool "MTD - Minimal Thread Device"
+endchoice
+
+config OPENTHREAD_MTD_SED
+	bool "SED - Sleepy End Device"
+	depends on OPENTHREAD_MTD
+
+config OPENTHREAD_POLL_PERIOD
+	int "Poll period for sleepy end devices [ms]"
+	default 236000
+	depends on OPENTHREAD_MTD_SED
+
+config OPENTHREAD_MAX_CHILDREN
+	int "The maximum number of children"
+	range 10 512
+	default 32
+
+config OPENTHREAD_MAX_IP_ADDR_PER_CHILD
+	int "The maximum number of IPv6 address registrations per child."
+	range 4 255
+	default 6
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread.c	(working copy)
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/net_mgmt.h>
+#include <net/openthread.h>
+
+#include <net_private.h>
+
+#include <init.h>
+#include <sys/util.h>
+#include <sys/__assert.h>
+#include <version.h>
+
+#include <openthread/cli.h>
+#include <openthread/ip6.h>
+#include <openthread/link.h>
+#include <openthread/link_raw.h>
+#include <openthread/ncp.h>
+#include <openthread/message.h>
+#include <openthread/platform/diag.h>
+#include <openthread/tasklet.h>
+#include <openthread/thread.h>
+#include <openthread/dataset.h>
+#include <openthread/joiner.h>
+#include <openthread-system.h>
+#include <openthread-config-generic.h>
+
+#include <platform-zephyr.h>
+
+#include "openthread_utils.h"
+
+#define OT_STACK_SIZE (CONFIG_OPENTHREAD_THREAD_STACK_SIZE)
+
+#if defined(CONFIG_OPENTHREAD_THREAD_PREEMPTIVE)
+#define OT_PRIORITY K_PRIO_PREEMPT(CONFIG_OPENTHREAD_THREAD_PRIORITY)
+#else
+#define OT_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
+#endif
+
+#if defined(CONFIG_OPENTHREAD_NETWORK_NAME)
+#define OT_NETWORK_NAME CONFIG_OPENTHREAD_NETWORK_NAME
+#else
+#define OT_NETWORK_NAME ""
+#endif
+
+#if defined(CONFIG_OPENTHREAD_CHANNEL)
+#define OT_CHANNEL CONFIG_OPENTHREAD_CHANNEL
+#else
+#define OT_CHANNEL 0
+#endif
+
+#if defined(CONFIG_OPENTHREAD_PANID)
+#define OT_PANID CONFIG_OPENTHREAD_PANID
+#else
+#define OT_PANID 0
+#endif
+
+#if defined(CONFIG_OPENTHREAD_XPANID)
+#define OT_XPANID CONFIG_OPENTHREAD_XPANID
+#else
+#define OT_XPANID ""
+#endif
+
+#if defined(CONFIG_OPENTHREAD_JOINER_PSKD)
+#define OT_JOINER_PSKD CONFIG_OPENTHREAD_JOINER_PSKD
+#else
+#define OT_JOINER_PSKD ""
+#endif
+
+#if defined(CONFIG_OPENTHREAD_PLATFORM_INFO)
+#define OT_PLATFORM_INFO CONFIG_OPENTHREAD_PLATFORM_INFO
+#else
+#define OT_PLATFORM_INFO ""
+#endif
+
+#if defined(CONFIG_OPENTHREAD_POLL_PERIOD)
+#define OT_POLL_PERIOD CONFIG_OPENTHREAD_POLL_PERIOD
+#else
+#define OT_POLL_PERIOD 0
+#endif
+
+#define PACKAGE_NAME "Zephyr"
+#define PACKAGE_VERSION KERNEL_VERSION_STRING
+
+extern void platformShellInit(otInstance *aInstance);
+
+K_SEM_DEFINE(ot_sem, 0, 1);
+
+K_KERNEL_STACK_DEFINE(ot_stack_area, OT_STACK_SIZE);
+static struct k_thread ot_thread_data;
+static k_tid_t ot_tid;
+static struct net_linkaddr *ll_addr;
+static otStateChangedCallback state_changed_cb;
+
+k_tid_t openthread_thread_id_get(void)
+{
+	return ot_tid;
+}
+
+#ifdef CONFIG_NET_MGMT_EVENT
+static struct net_mgmt_event_callback ip6_addr_cb;
+
+static void ipv6_addr_event_handler(struct net_mgmt_event_callback *cb,
+				    uint32_t mgmt_event, struct net_if *iface)
+{
+	struct openthread_context *ot_context = net_if_l2_data(iface);
+
+	if (net_if_l2(iface) != &NET_L2_GET_NAME(OPENTHREAD)) {
+		return;
+	}
+
+	if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
+		add_ipv6_addr_to_ot(ot_context);
+	} else if (mgmt_event == NET_EVENT_IPV6_MADDR_ADD) {
+		add_ipv6_maddr_to_ot(ot_context);
+	}
+}
+#endif
+
+void otPlatRadioGetIeeeEui64(otInstance *instance, uint8_t *ieee_eui64)
+{
+	ARG_UNUSED(instance);
+
+	memcpy(ieee_eui64, ll_addr->addr, ll_addr->len);
+}
+
+void otTaskletsSignalPending(otInstance *instance)
+{
+	k_sem_give(&ot_sem);
+}
+
+void otSysEventSignalPending(void)
+{
+	k_sem_give(&ot_sem);
+}
+
+static void ot_state_changed_handler(uint32_t flags, void *context)
+{
+	struct openthread_context *ot_context = context;
+
+	NET_INFO("State changed! Flags: 0x%08" PRIx32 " Current role: %d",
+		    flags, otThreadGetDeviceRole(ot_context->instance));
+
+	if (flags & OT_CHANGED_IP6_ADDRESS_REMOVED) {
+		NET_DBG("Ipv6 address removed");
+		rm_ipv6_addr_from_zephyr(ot_context);
+	}
+
+	if (flags & OT_CHANGED_IP6_ADDRESS_ADDED) {
+		NET_DBG("Ipv6 address added");
+		add_ipv6_addr_to_zephyr(ot_context);
+	}
+
+	if (flags & OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED) {
+		NET_DBG("Ipv6 multicast address removed");
+		rm_ipv6_maddr_from_zephyr(ot_context);
+	}
+
+	if (flags & OT_CHANGED_IP6_MULTICAST_SUBSCRIBED) {
+		NET_DBG("Ipv6 multicast address added");
+		add_ipv6_maddr_to_zephyr(ot_context);
+	}
+
+	if (state_changed_cb) {
+		state_changed_cb(flags, context);
+	}
+}
+
+static void ot_receive_handler(otMessage *aMessage, void *context)
+{
+	struct openthread_context *ot_context = context;
+
+	uint16_t offset = 0U;
+	uint16_t read_len;
+	struct net_pkt *pkt;
+	struct net_buf *pkt_buf;
+
+	pkt = net_pkt_rx_alloc_with_buffer(ot_context->iface,
+					   otMessageGetLength(aMessage),
+					   AF_UNSPEC, 0, K_NO_WAIT);
+	if (!pkt) {
+		NET_ERR("Failed to reserve net pkt");
+		goto out;
+	}
+
+	pkt_buf = pkt->buffer;
+
+	while (1) {
+		read_len = otMessageRead(aMessage,
+					 offset,
+					 pkt_buf->data,
+					 net_buf_tailroom(pkt_buf));
+		if (!read_len) {
+			break;
+		}
+
+		net_buf_add(pkt_buf, read_len);
+
+		offset += read_len;
+
+		if (!net_buf_tailroom(pkt_buf)) {
+			pkt_buf = pkt_buf->frags;
+			if (!pkt_buf) {
+				break;
+			}
+		}
+	}
+
+	NET_DBG("Injecting Ip6 packet to Zephyr net stack");
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
+		net_pkt_hexdump(pkt, "Received IPv6 packet");
+	}
+
+	if (!pkt_list_is_full(ot_context)) {
+		if (pkt_list_add(ot_context, pkt) != 0) {
+			NET_ERR("pkt_list_add failed");
+			goto out;
+		}
+
+		if (net_recv_data(ot_context->iface, pkt) < 0) {
+			NET_ERR("net_recv_data failed");
+			pkt_list_remove_first(ot_context);
+			goto out;
+		}
+
+		pkt = NULL;
+	} else {
+		NET_INFO("Packet list is full");
+	}
+out:
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	otMessageFree(aMessage);
+}
+
+static void ot_joiner_start_handler(otError error, void *context)
+{
+	struct openthread_context *ot_context = context;
+
+	switch (error) {
+	case OT_ERROR_NONE:
+		NET_INFO("Join success");
+		otThreadSetEnabled(ot_context->instance, true);
+		break;
+	default:
+		NET_ERR("Join failed [%d]", error);
+		break;
+	}
+}
+
+static void openthread_process(void *context, void *arg2, void *arg3)
+{
+	struct openthread_context *ot_context = context;
+
+	while (1) {
+		openthread_api_mutex_lock(ot_context);
+
+		while (otTaskletsArePending(ot_context->instance)) {
+			otTaskletsProcess(ot_context->instance);
+		}
+
+		otSysProcessDrivers(ot_context->instance);
+
+		openthread_api_mutex_unlock(ot_context);
+
+		k_sem_take(&ot_sem, K_FOREVER);
+	}
+}
+
+static enum net_verdict openthread_recv(struct net_if *iface,
+					struct net_pkt *pkt)
+{
+	struct openthread_context *ot_context = net_if_l2_data(iface);
+
+	if (pkt_list_peek(ot_context) == pkt) {
+		pkt_list_remove_last(ot_context);
+		NET_DBG("Got injected Ip6 packet, sending to upper layers");
+
+		if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
+			net_pkt_hexdump(pkt, "Injected IPv6 packet");
+		}
+
+		return NET_CONTINUE;
+	}
+
+	NET_DBG("Got 802.15.4 packet, sending to OT");
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
+		net_pkt_hexdump(pkt, "Received 802.15.4 frame");
+	}
+
+	if (notify_new_rx_frame(pkt) != 0) {
+		NET_ERR("Failed to queue RX packet for OpenThread");
+		return NET_DROP;
+	}
+
+	return NET_OK;
+}
+
+int openthread_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	int len = net_pkt_get_len(pkt);
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)) {
+		net_pkt_hexdump(pkt, "IPv6 packet to send");
+	}
+
+	if (notify_new_tx_frame(pkt) != 0) {
+		net_pkt_unref(pkt);
+	}
+
+	return len;
+}
+
+int openthread_start(struct openthread_context *ot_context)
+{
+	otInstance *ot_instance = ot_context->instance;
+	otError error;
+
+	openthread_api_mutex_lock(ot_context);
+
+	otIp6SetEnabled(ot_context->instance, true);
+
+	/* Sleepy End Device specific configuration. */
+	if (IS_ENABLED(CONFIG_OPENTHREAD_MTD_SED)) {
+		otLinkModeConfig ot_mode = otThreadGetLinkMode(ot_instance);
+
+		/* A SED should always attach the network as a SED to indicate
+		 * increased buffer requirement to a parent.
+		 */
+		ot_mode.mRxOnWhenIdle = false;
+
+		otThreadSetLinkMode(ot_context->instance, ot_mode);
+		otLinkSetPollPeriod(ot_context->instance, OT_POLL_PERIOD);
+	}
+
+	if (otDatasetIsCommissioned(ot_instance)) {
+		/* OpenThread already has dataset stored - skip the
+		 * configuration.
+		 */
+		NET_DBG("OpenThread already commissioned.");
+	} else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
+		/* No dataset - initiate network join procedure. */
+		NET_DBG("Starting OpenThread join procedure.");
+
+		error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL,
+				      PACKAGE_NAME, OT_PLATFORM_INFO,
+				      PACKAGE_VERSION, NULL,
+				      &ot_joiner_start_handler, ot_context);
+
+		if (error != OT_ERROR_NONE) {
+			NET_ERR("Failed to start joiner [%d]", error);
+		}
+
+		goto exit;
+	} else {
+		/* No dataset - load the default configuration. */
+		NET_DBG("Loading OpenThread default configuration.");
+
+		otExtendedPanId xpanid;
+
+		otThreadSetNetworkName(ot_instance, OT_NETWORK_NAME);
+		otLinkSetChannel(ot_instance, OT_CHANNEL);
+		otLinkSetPanId(ot_instance, OT_PANID);
+		net_bytes_from_str(xpanid.m8, 8, (char *)OT_XPANID);
+		otThreadSetExtendedPanId(ot_instance, &xpanid);
+	}
+
+	NET_INFO("OpenThread version: %s", otGetVersionString());
+	NET_INFO("Network name: %s",
+		 log_strdup(otThreadGetNetworkName(ot_instance)));
+
+	/* Start the network. */
+	error = otThreadSetEnabled(ot_instance, true);
+	if (error != OT_ERROR_NONE) {
+		NET_ERR("Failed to start the OpenThread network [%d]", error);
+	}
+
+exit:
+	openthread_api_mutex_unlock(ot_context);
+
+	return error == OT_ERROR_NONE ? 0 : -EIO;
+}
+
+int openthread_stop(struct openthread_context *ot_context)
+{
+	otError error;
+
+	openthread_api_mutex_lock(ot_context);
+
+	error = otThreadSetEnabled(ot_context->instance, false);
+	if (error == OT_ERROR_INVALID_STATE) {
+		NET_DBG("Openthread interface was not up [%d]", error);
+	}
+
+	openthread_api_mutex_unlock(ot_context);
+
+	return 0;
+}
+
+static int openthread_init(struct net_if *iface)
+{
+	struct openthread_context *ot_context = net_if_l2_data(iface);
+
+	NET_DBG("openthread_init");
+
+	k_mutex_init(&ot_context->api_lock);
+
+	ll_addr = net_if_get_link_addr(iface);
+
+	otSysInit(0, NULL);
+
+	ot_context->instance = otInstanceInitSingle();
+	ot_context->iface = iface;
+
+	__ASSERT(ot_context->instance, "OT instance is NULL");
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_SHELL)) {
+		platformShellInit(ot_context->instance);
+	}
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_NCP)) {
+		otNcpInit(ot_context->instance);
+	}
+
+	if (!IS_ENABLED(CONFIG_OPENTHREAD_NCP)) {
+		otIp6SetReceiveFilterEnabled(ot_context->instance, true);
+		otIp6SetReceiveCallback(ot_context->instance,
+					ot_receive_handler, ot_context);
+		otSetStateChangedCallback(
+					ot_context->instance,
+					&ot_state_changed_handler,
+					ot_context);
+	}
+
+	net_mgmt_init_event_callback(&ip6_addr_cb, ipv6_addr_event_handler,
+				     NET_EVENT_IPV6_ADDR_ADD |
+				     NET_EVENT_IPV6_MADDR_ADD);
+	net_mgmt_add_event_callback(&ip6_addr_cb);
+
+	ot_tid = k_thread_create(&ot_thread_data, ot_stack_area,
+				 K_KERNEL_STACK_SIZEOF(ot_stack_area),
+				 openthread_process,
+				 ot_context, NULL, NULL,
+				 OT_PRIORITY, 0, K_NO_WAIT);
+	k_thread_name_set(&ot_thread_data, "openthread");
+
+	return 0;
+}
+
+void ieee802154_init(struct net_if *iface)
+{
+	if (IS_ENABLED(CONFIG_IEEE802154_NET_IF_NO_AUTO_START)) {
+		LOG_DBG("Interface auto start disabled.");
+		net_if_flag_set(iface, NET_IF_NO_AUTO_START);
+	}
+
+	openthread_init(iface);
+}
+
+static enum net_l2_flags openthread_flags(struct net_if *iface)
+{
+	return NET_L2_MULTICAST;
+}
+
+static int openthread_enable(struct net_if *iface, bool state)
+{
+	struct openthread_context *ot_context = net_if_l2_data(iface);
+
+	NET_DBG("iface %p %s", iface, state ? "up" : "down");
+
+	if (state) {
+		if (IS_ENABLED(CONFIG_OPENTHREAD_MANUAL_START)) {
+			NET_DBG("OpenThread manual start.");
+			return 0;
+		}
+
+		return openthread_start(ot_context);
+	}
+
+	return openthread_stop(ot_context);
+}
+
+struct openthread_context *openthread_get_default_context(void)
+{
+	struct net_if *iface;
+	struct openthread_context *ot_context = NULL;
+
+	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(OPENTHREAD));
+	if (!iface) {
+		NET_ERR("There is no net interface for OpenThread");
+		goto exit;
+	}
+
+	ot_context = net_if_l2_data(iface);
+	if (!ot_context) {
+		NET_ERR("There is no Openthread context in net interface data");
+		goto exit;
+	}
+
+exit:
+	return ot_context;
+}
+
+struct otInstance *openthread_get_default_instance(void)
+{
+	struct openthread_context *ot_context =
+		openthread_get_default_context();
+
+	return ot_context ? ot_context->instance : NULL;
+}
+
+void openthread_set_state_changed_cb(otStateChangedCallback cb)
+{
+	state_changed_cb = cb;
+}
+
+void openthread_api_mutex_lock(struct openthread_context *ot_context)
+{
+	(void)k_mutex_lock(&ot_context->api_lock, K_FOREVER);
+}
+
+void openthread_api_mutex_unlock(struct openthread_context *ot_context)
+{
+	(void)k_mutex_unlock(&ot_context->api_lock);
+}
+
+NET_L2_INIT(OPENTHREAD_L2, openthread_recv, openthread_send, openthread_enable,
+	    openthread_flags);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.h	(working copy)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __OPENTHREAD_UTILS_H__
+#define __OPENTHREAD_UTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_15_4) || \
+	defined(CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6)
+
+void dump_pkt(const char *str, struct net_pkt *pkt);
+#else
+#define dump_pkt(...)
+#endif
+
+void add_ipv6_addr_to_zephyr(struct openthread_context *context);
+void add_ipv6_addr_to_ot(struct openthread_context *context);
+void add_ipv6_maddr_to_ot(struct openthread_context *context);
+void add_ipv6_maddr_to_zephyr(struct openthread_context *context);
+void rm_ipv6_addr_from_zephyr(struct openthread_context *context);
+void rm_ipv6_maddr_from_zephyr(struct openthread_context *context);
+
+int pkt_list_add(struct openthread_context *context, struct net_pkt *pkt);
+struct net_pkt *pkt_list_peek(struct openthread_context *context);
+void pkt_list_remove_last(struct openthread_context *context);
+void pkt_list_remove_first(struct openthread_context *context);
+
+static inline int pkt_list_is_full(struct openthread_context *context)
+{
+	return context->pkt_list_full;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OPENTHREAD_UTILS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/openthread/openthread_utils.c	(working copy)
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+#include <net/openthread.h>
+
+#include <openthread/ip6.h>
+#include <openthread/thread.h>
+
+#include "openthread_utils.h"
+
+#define ALOC16_MASK 0xfc
+
+static bool is_anycast_locator(const otNetifAddress *address)
+{
+	return address->mAddress.mFields.m16[4] == htons(0x0000) &&
+	       address->mAddress.mFields.m16[5] == htons(0x00ff) &&
+	       address->mAddress.mFields.m16[6] == htons(0xfe00) &&
+	       address->mAddress.mFields.m8[14] == ALOC16_MASK;
+}
+
+static bool is_mesh_local(struct openthread_context *context,
+			  const uint8_t *address)
+{
+	const otMeshLocalPrefix *ml_prefix =
+				otThreadGetMeshLocalPrefix(context->instance);
+
+	return (memcmp(address, ml_prefix->m8, sizeof(ml_prefix)) == 0);
+}
+
+int pkt_list_add(struct openthread_context *context, struct net_pkt *pkt)
+{
+	uint16_t i_idx = context->pkt_list_in_idx;
+
+	if (context->pkt_list_full) {
+		return -ENOMEM;
+	}
+
+	i_idx++;
+	if (i_idx == CONFIG_OPENTHREAD_PKT_LIST_SIZE) {
+		i_idx = 0U;
+	}
+
+	if (i_idx == context->pkt_list_out_idx) {
+		context->pkt_list_full = 1U;
+	}
+
+	context->pkt_list[context->pkt_list_in_idx].pkt = pkt;
+	context->pkt_list_in_idx = i_idx;
+
+	return 0;
+}
+
+void pkt_list_remove_first(struct openthread_context *context)
+{
+	uint16_t idx = context->pkt_list_in_idx;
+
+	if (idx == 0U) {
+		idx = CONFIG_OPENTHREAD_PKT_LIST_SIZE - 1;
+	} else {
+		idx--;
+	}
+	context->pkt_list_in_idx = idx;
+
+	if (context->pkt_list_full) {
+		context->pkt_list_full = 0U;
+	}
+}
+
+struct net_pkt *pkt_list_peek(struct openthread_context *context)
+{
+	if ((context->pkt_list_in_idx == context->pkt_list_out_idx) &&
+	    (!context->pkt_list_full)) {
+
+		return NULL;
+	}
+	return context->pkt_list[context->pkt_list_out_idx].pkt;
+}
+
+void pkt_list_remove_last(struct openthread_context *context)
+{
+	if ((context->pkt_list_in_idx == context->pkt_list_out_idx) &&
+	    (!context->pkt_list_full)) {
+
+		return;
+	}
+
+	context->pkt_list_out_idx++;
+	if (context->pkt_list_out_idx == CONFIG_OPENTHREAD_PKT_LIST_SIZE) {
+		context->pkt_list_out_idx = 0U;
+	}
+
+	context->pkt_list_full = 0U;
+}
+
+void add_ipv6_addr_to_zephyr(struct openthread_context *context)
+{
+	const otNetifAddress *address;
+	struct net_if_addr *if_addr;
+
+	for (address = otIp6GetUnicastAddresses(context->instance);
+	     address; address = address->mNext) {
+
+		if (address->mRloc || is_anycast_locator(address)) {
+			continue;
+		}
+
+		if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+			char buf[NET_IPV6_ADDR_LEN];
+
+			NET_DBG("Adding %s",
+				log_strdup(net_addr_ntop(AF_INET6,
+				       (struct in6_addr *)(&address->mAddress),
+				       buf, sizeof(buf))));
+		}
+
+		/* Thread and SLAAC are clearly AUTOCONF, handle
+		 * manual/NCP addresses in the same way
+		 */
+		if ((address->mAddressOrigin == OT_ADDRESS_ORIGIN_THREAD) ||
+		    (address->mAddressOrigin == OT_ADDRESS_ORIGIN_SLAAC)) {
+			if_addr = net_if_ipv6_addr_add(
+					context->iface,
+					(struct in6_addr *)(&address->mAddress),
+					NET_ADDR_AUTOCONF, 0);
+		} else if (address->mAddressOrigin ==
+			   OT_ADDRESS_ORIGIN_DHCPV6) {
+			if_addr = net_if_ipv6_addr_add(
+					context->iface,
+					(struct in6_addr *)(&address->mAddress),
+					NET_ADDR_DHCP, 0);
+		} else if (address->mAddressOrigin ==
+			  OT_ADDRESS_ORIGIN_MANUAL) {
+			if_addr = net_if_ipv6_addr_add(
+					context->iface,
+					(struct in6_addr *)(&address->mAddress),
+					NET_ADDR_MANUAL, 0);
+		} else {
+			NET_ERR("Unknown OpenThread address origin ignored.");
+			continue;
+		}
+
+		if (if_addr == NULL) {
+			NET_ERR("Cannot add OpenThread unicast address");
+			continue;
+		}
+
+		if_addr->is_mesh_local = is_mesh_local(
+					context, address->mAddress.mFields.m8);
+	}
+}
+
+void add_ipv6_addr_to_ot(struct openthread_context *context)
+{
+	struct net_if *iface = context->iface;
+	struct otNetifAddress addr;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	(void)memset(&addr, 0, sizeof(addr));
+
+	if (net_if_config_ipv6_get(iface, &ipv6) < 0) {
+		NET_DBG("Cannot allocate IPv6 address");
+		return;
+	}
+
+	/* save the last added IP address for this interface */
+	for (i = NET_IF_MAX_IPV6_ADDR - 1; i >= 0; i--) {
+		if (ipv6->unicast[i].is_used) {
+			memcpy(&addr.mAddress,
+			       &ipv6->unicast[i].address.in6_addr,
+			       sizeof(addr.mAddress));
+			break;
+		}
+	}
+
+	ipv6->unicast[i].is_mesh_local = is_mesh_local(
+			context, ipv6->unicast[i].address.in6_addr.s6_addr);
+
+	addr.mValid = true;
+	addr.mPreferred = true;
+	addr.mPrefixLength = 64;
+
+	if (ipv6->unicast[i].addr_type == NET_ADDR_AUTOCONF) {
+		addr.mAddressOrigin = OT_ADDRESS_ORIGIN_SLAAC;
+	} else if (ipv6->unicast[i].addr_type == NET_ADDR_DHCP) {
+		addr.mAddressOrigin = OT_ADDRESS_ORIGIN_DHCPV6;
+	} else if (ipv6->unicast[i].addr_type == NET_ADDR_MANUAL) {
+		addr.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
+	} else {
+		NET_ERR("Unknown address type");
+		return;
+	}
+
+	openthread_api_mutex_lock(context);
+	otIp6AddUnicastAddress(context->instance, &addr);
+	openthread_api_mutex_unlock(context);
+
+	if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+		char buf[NET_IPV6_ADDR_LEN];
+
+		NET_DBG("Added %s",
+			log_strdup(net_addr_ntop(AF_INET6,
+						 &addr.mAddress, buf,
+						 sizeof(buf))));
+	}
+}
+
+void add_ipv6_maddr_to_ot(struct openthread_context *context)
+{
+	struct otIp6Address addr;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(context->iface, &ipv6) < 0) {
+		NET_DBG("Cannot allocate IPv6 address");
+		return;
+	}
+
+	/* save the last added IP address for this interface */
+	for (i = NET_IF_MAX_IPV6_MADDR - 1; i >= 0; i--) {
+		if (ipv6->mcast[i].is_used) {
+			memcpy(&addr,
+			       &ipv6->mcast[i].address.in6_addr,
+			       sizeof(addr));
+			break;
+		}
+	}
+
+	openthread_api_mutex_lock(context);
+	otIp6SubscribeMulticastAddress(context->instance, &addr);
+	openthread_api_mutex_unlock(context);
+
+	if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+		char buf[NET_IPV6_ADDR_LEN];
+
+		NET_DBG("Added multicast %s",
+			log_strdup(net_addr_ntop(AF_INET6, &addr,
+						 buf, sizeof(buf))));
+	}
+}
+
+void add_ipv6_maddr_to_zephyr(struct openthread_context *context)
+{
+	const otNetifMulticastAddress *maddress;
+
+	for (maddress = otIp6GetMulticastAddresses(context->instance);
+	     maddress; maddress = maddress->mNext) {
+		if (net_if_ipv6_maddr_lookup(
+				(struct in6_addr *)(&maddress->mAddress),
+				&context->iface) != NULL) {
+			continue;
+		}
+
+		if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+			char buf[NET_IPV6_ADDR_LEN];
+
+			NET_DBG("Adding multicast %s",
+				log_strdup(net_addr_ntop(AF_INET6,
+							 (struct in6_addr *)
+							 (&maddress->mAddress),
+							 buf, sizeof(buf))));
+		}
+
+		net_if_ipv6_maddr_add(context->iface,
+				      (struct in6_addr *)(&maddress->mAddress));
+	}
+}
+
+void rm_ipv6_addr_from_zephyr(struct openthread_context *context)
+{
+	struct in6_addr *ot_addr;
+	struct net_if_addr *zephyr_addr;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(context->iface, &ipv6) < 0) {
+		NET_DBG("Cannot find IPv6 address");
+		return;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
+		const otNetifAddress *address;
+		bool used = false;
+
+		zephyr_addr = &ipv6->unicast[i];
+		if (!zephyr_addr->is_used) {
+			continue;
+		}
+
+		for (address = otIp6GetUnicastAddresses(context->instance);
+		     address; address = address->mNext) {
+
+			ot_addr = (struct in6_addr *)(&address->mAddress);
+			if (net_ipv6_addr_cmp(ot_addr,
+					      &zephyr_addr->address.in6_addr)) {
+
+				used = true;
+				break;
+			}
+		}
+		if (!used) {
+			if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+				char buf[NET_IPV6_ADDR_LEN];
+
+				NET_DBG("Removing %s",
+					log_strdup(net_addr_ntop(AF_INET6,
+					      &zephyr_addr->address.in6_addr,
+					      buf, sizeof(buf))));
+			}
+
+			net_if_ipv6_addr_rm(context->iface,
+					    &zephyr_addr->address.in6_addr);
+		}
+	}
+}
+
+void rm_ipv6_maddr_from_zephyr(struct openthread_context *context)
+{
+	struct in6_addr *ot_addr;
+	struct net_if_mcast_addr *zephyr_addr;
+	struct net_if_ipv6 *ipv6;
+	int i;
+
+	if (net_if_config_ipv6_get(context->iface, &ipv6) < 0) {
+		NET_DBG("Cannot find IPv6 address");
+		return;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
+		const otNetifMulticastAddress *maddress;
+		bool used = false;
+
+		zephyr_addr = &ipv6->mcast[i];
+		if (!zephyr_addr->is_used) {
+			continue;
+		}
+
+		for (maddress = otIp6GetMulticastAddresses(context->instance);
+		     maddress; maddress = maddress->mNext) {
+
+			ot_addr = (struct in6_addr *)(&maddress->mAddress);
+			if (net_ipv6_addr_cmp(ot_addr,
+					      &zephyr_addr->address.in6_addr)) {
+
+				used = true;
+				break;
+			}
+		}
+		if (!used) {
+			if (CONFIG_OPENTHREAD_L2_LOG_LEVEL == LOG_LEVEL_DBG) {
+				char buf[NET_IPV6_ADDR_LEN];
+
+				NET_DBG("Removing multicast %s",
+					log_strdup(net_addr_ntop(AF_INET6,
+					      &zephyr_addr->address.in6_addr,
+					      buf, sizeof(buf))));
+			}
+
+			net_if_ipv6_maddr_rm(context->iface,
+					     &zephyr_addr->address.in6_addr);
+		}
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/CMakeLists.txt	(working copy)
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_include_directories(. ${ZEPHYR_BASE}/subsys/net/ip)
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_PPP
+			     ppp_l2.c
+			     fsm.c
+			     lcp.c
+			     options.c
+			     link.c
+			     network.c
+			     misc.c)
+
+zephyr_library_sources_ifdef(CONFIG_NET_STATISTICS_PPP ppp_stats.c)
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_PPP_MGMT ppp_mgmt.c)
+
+if(CONFIG_NET_IPV4)
+  zephyr_library_sources_ifdef(CONFIG_NET_L2_PPP ipcp.c)
+endif()
+
+if(CONFIG_NET_IPV6)
+  zephyr_library_sources_ifdef(CONFIG_NET_L2_PPP ipv6cp.c)
+endif()
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_PPP_PAP pap.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/Kconfig	(working copy)
@@ -0,0 +1,80 @@
+# Copyright (c) 2019 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_L2_PPP
+	bool "Enable point-to-point (PPP) support [EXPERIMENTAL]"
+	help
+	  Add support for PPP.
+
+if NET_L2_PPP
+
+config NET_L2_PPP_DELAY_STARTUP_MS
+	int "PPP delay startup ms"
+	default 0
+	help
+	  If the PPP starts too fast, it is possible to delay it
+	  a bit. This is mostly useful in debugging if you want the
+	  device be fully up before PPP handshake is started.
+	  Wait amount of milliseconds before starting PPP. Value 0 disables
+	  the wait.
+
+config NET_L2_PPP_TIMEOUT
+	int "Maximum timeout in ms for Configure-Req"
+	default 3000
+	range 1 4294967295
+	help
+	  How long to wait Configure-Req.
+
+config NET_L2_PPP_MAX_CONFIGURE_REQ_RETRANSMITS
+	int "Maximum number of Configure-Req retransmits"
+	default 10
+	range 0 4294967295
+	help
+	  How many times to resend Configure-Req messages before deciding the
+	  link is not working properly.
+
+config NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS
+	int "Maximum number of Terminate-Req retransmits"
+	default 2
+	range 0 4294967295
+	help
+	  How many times to resend Terminate-Req messages before terminating
+	  the link.
+
+config NET_L2_PPP_MAX_NACK_LOOPS
+	int "Maximum number of NACK loops accepted"
+	default 5
+	range 0 4294967295
+	help
+	  How many times to accept NACK loops.
+
+config NET_L2_PPP_OPTION_DNS_USE
+	bool "Use negotiated DNS servers"
+	depends on DNS_RESOLVER
+	help
+	  Use the DNS servers negotiated in the IPCP configuration.
+
+config NET_L2_PPP_AUTH_SUPPORT
+	bool
+
+config NET_L2_PPP_PAP
+	bool "PAP authentication protocol"
+	select NET_L2_PPP_AUTH_SUPPORT
+	help
+	  Enable support for PAP authentication protocol.
+
+module = NET_L2_PPP
+module-dep = NET_LOG
+module-str = Log level for ppp L2 layer
+module-help = Enables ppp L2 to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_L2_PPP_MGMT
+	bool "Enable ppp network management interface"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	help
+	  Enable support net_mgmt ppp interface which can be used to
+	  configure at run-time ppp drivers and L2 settings.
+
+endif # NET_L2_PPP
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/fsm.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/fsm.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/fsm.c	(working copy)
@@ -0,0 +1,1188 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+#include <random/rand32.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+/* This timeout is in milliseconds */
+#define FSM_TIMEOUT K_MSEC(CONFIG_NET_L2_PPP_TIMEOUT)
+
+#define MAX_NACK_LOOPS CONFIG_NET_L2_PPP_MAX_NACK_LOOPS
+
+struct ppp_context *ppp_fsm_ctx(struct ppp_fsm *fsm)
+{
+	if (fsm->protocol == PPP_LCP) {
+		return CONTAINER_OF(fsm, struct ppp_context, lcp.fsm);
+#if defined(CONFIG_NET_IPV4)
+	} else if (fsm->protocol == PPP_IPCP) {
+		return CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
+#endif
+#if defined(CONFIG_NET_IPV6)
+	} else if (fsm->protocol == PPP_IPV6CP) {
+		return CONTAINER_OF(fsm, struct ppp_context, ipv6cp.fsm);
+#endif
+#if defined(CONFIG_NET_L2_PPP_PAP)
+	} else if (fsm->protocol == PPP_PAP) {
+		return CONTAINER_OF(fsm, struct ppp_context, pap.fsm);
+#endif
+	}
+
+	return NULL;
+}
+
+struct net_if *ppp_fsm_iface(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = ppp_fsm_ctx(fsm);
+
+	NET_ASSERT(ctx->iface);
+
+	return ctx->iface;
+}
+
+static void fsm_send_configure_req(struct ppp_fsm *fsm, bool retransmit)
+{
+	struct net_pkt *pkt = NULL;
+
+	if (fsm->state != PPP_ACK_RECEIVED &&
+	    fsm->state != PPP_ACK_SENT &&
+	    fsm->state != PPP_REQUEST_SENT) {
+		/* If we are not negotiating options, then reset them */
+		if (fsm->cb.config_info_reset) {
+			fsm->cb.config_info_reset(fsm);
+		}
+
+		fsm->recv_nack_loops = 0;
+		fsm->nack_loops = 0;
+	}
+
+	if (!retransmit) {
+		fsm->retransmits = MAX_CONFIGURE_REQ;
+		fsm->req_id = ++fsm->id;
+	}
+
+	fsm->ack_received = false;
+
+	if (fsm->cb.config_info_add) {
+		pkt = fsm->cb.config_info_add(fsm);
+	}
+
+	NET_DBG("[%s/%p] Sending %s (%d) id %d to peer while in %s (%d)",
+		fsm->name, fsm, ppp_pkt_type2str(PPP_CONFIGURE_REQ),
+		PPP_CONFIGURE_REQ, fsm->req_id, ppp_state_str(fsm->state),
+		fsm->state);
+
+	(void)ppp_send_pkt(fsm, NULL, PPP_CONFIGURE_REQ, fsm->req_id,
+			   pkt, pkt ? net_pkt_get_len(pkt) : 0);
+
+	fsm->retransmits--;
+
+	(void)k_delayed_work_submit(&fsm->timer, FSM_TIMEOUT);
+}
+
+static void ppp_fsm_timeout(struct k_work *work)
+{
+	struct ppp_fsm *fsm = CONTAINER_OF(work, struct ppp_fsm, timer);
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+	case PPP_ACK_SENT:
+	case PPP_REQUEST_SENT:
+		if (fsm->retransmits <= 0) {
+			NET_DBG("[%s/%p] %s retransmit limit %d reached",
+				fsm->name, fsm,
+				ppp_pkt_type2str(PPP_CONFIGURE_REQ),
+				fsm->retransmits);
+
+			ppp_change_state(fsm, PPP_STOPPED);
+
+			if (fsm->cb.finished) {
+				fsm->cb.finished(fsm);
+			}
+		} else {
+			if (fsm->cb.retransmit) {
+				fsm->cb.retransmit(fsm);
+			}
+
+			fsm_send_configure_req(fsm, true);
+
+			if (fsm->state == PPP_ACK_RECEIVED) {
+				ppp_change_state(fsm, PPP_REQUEST_SENT);
+			}
+		}
+
+		break;
+
+	case PPP_CLOSING:
+	case PPP_STOPPING:
+		if (fsm->retransmits <= 0) {
+			ppp_change_state(fsm,
+					 fsm->state == PPP_CLOSING ?
+					 PPP_CLOSED : PPP_STOPPED);
+
+			if (fsm->cb.finished) {
+				fsm->cb.finished(fsm);
+			}
+		} else {
+			fsm->req_id = ++fsm->id;
+
+			ppp_send_pkt(fsm, NULL, PPP_TERMINATE_REQ, fsm->req_id,
+				     fsm->terminate_reason,
+				     strlen(fsm->terminate_reason));
+
+			fsm->retransmits--;
+
+			(void)k_delayed_work_submit(&fsm->timer, FSM_TIMEOUT);
+		}
+
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+static void ppp_pkt_send(struct k_work *work)
+{
+	struct net_pkt *pkt = CONTAINER_OF(work, struct net_pkt, work);
+	int ret;
+
+	ret = net_send_data(pkt);
+	if (ret < 0) {
+		net_pkt_unref(pkt);
+	}
+}
+
+
+void ppp_fsm_init(struct ppp_fsm *fsm, uint16_t protocol)
+{
+	fsm->protocol = protocol;
+	fsm->state = PPP_INITIAL;
+	fsm->flags = 0U;
+
+	k_delayed_work_init(&fsm->timer, ppp_fsm_timeout);
+}
+
+static void fsm_down(struct ppp_fsm *fsm)
+{
+	size_t i;
+
+	for (i = 0; i < fsm->my_options.count; i++) {
+		fsm->my_options.data[i].flags = 0;
+	}
+
+	if (fsm->cb.down) {
+		fsm->cb.down(fsm);
+	}
+}
+
+static void terminate(struct ppp_fsm *fsm, enum ppp_state next_state)
+{
+	if (fsm->state != PPP_OPENED) {
+		k_delayed_work_cancel(&fsm->timer);
+	} else {
+		fsm_down(fsm);
+	}
+
+	fsm->retransmits = MAX_CONFIGURE_REQ;
+	fsm->req_id = ++fsm->id;
+
+	(void)ppp_send_pkt(fsm, NULL, PPP_TERMINATE_REQ, fsm->req_id,
+			   fsm->terminate_reason,
+			   strlen(fsm->terminate_reason));
+
+	if (fsm->retransmits == 0) {
+		ppp_change_state(fsm, next_state);
+
+		if (fsm->cb.finished) {
+			fsm->cb.finished(fsm);
+		}
+
+		return;
+	}
+
+	(void)k_delayed_work_submit(&fsm->timer, FSM_TIMEOUT);
+
+	fsm->retransmits--;
+
+	ppp_change_state(fsm, next_state);
+}
+
+void ppp_fsm_close(struct ppp_fsm *fsm, const uint8_t *reason)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+	case PPP_ACK_SENT:
+	case PPP_OPENED:
+	case PPP_REQUEST_SENT:
+		if (reason) {
+			int len = strlen(reason);
+
+			len = MIN(sizeof(fsm->terminate_reason) - 1, len);
+			strncpy(fsm->terminate_reason, reason, len);
+		}
+
+		terminate(fsm, PPP_CLOSING);
+		break;
+
+	case PPP_INITIAL:
+	case PPP_STARTING:
+		ppp_change_state(fsm, PPP_INITIAL);
+		break;
+
+	case PPP_STOPPED:
+		ppp_change_state(fsm, PPP_CLOSED);
+		break;
+
+	case PPP_STOPPING:
+		ppp_change_state(fsm, PPP_CLOSING);
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+void ppp_fsm_lower_down(struct ppp_fsm *fsm)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+	case PPP_ACK_SENT:
+	case PPP_REQUEST_SENT:
+	case PPP_STOPPING:
+		ppp_change_state(fsm, PPP_STARTING);
+		k_delayed_work_cancel(&fsm->timer);
+		break;
+
+	case PPP_CLOSED:
+		ppp_change_state(fsm, PPP_INITIAL);
+		break;
+
+	case PPP_CLOSING:
+		ppp_change_state(fsm, PPP_INITIAL);
+		k_delayed_work_cancel(&fsm->timer);
+		break;
+
+	case PPP_OPENED:
+		ppp_change_state(fsm, PPP_STARTING);
+		fsm_down(fsm);
+
+		break;
+
+	case PPP_STOPPED:
+		ppp_change_state(fsm, PPP_STARTING);
+		if (fsm->cb.starting) {
+			fsm->cb.starting(fsm);
+		}
+
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+void ppp_fsm_lower_up(struct ppp_fsm *fsm)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_CLOSED:
+		break;
+
+	case PPP_INITIAL:
+		ppp_change_state(fsm, PPP_CLOSED);
+		break;
+
+	case PPP_STARTING:
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+void ppp_fsm_open(struct ppp_fsm *fsm)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_CLOSED:
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		fsm_send_configure_req(fsm, false);
+		break;
+
+	case PPP_CLOSING:
+		ppp_change_state(fsm, PPP_STOPPING);
+		if (fsm->flags & FSM_RESTART) {
+			ppp_fsm_lower_down(fsm);
+			ppp_fsm_lower_up(fsm);
+		}
+
+		break;
+
+	case PPP_INITIAL:
+		ppp_change_state(fsm, PPP_STARTING);
+		if (fsm->cb.starting) {
+			fsm->cb.starting(fsm);
+		}
+
+		break;
+
+	case PPP_OPENED:
+	case PPP_STOPPED:
+		if (fsm->flags & FSM_RESTART) {
+			ppp_fsm_lower_down(fsm);
+			ppp_fsm_lower_up(fsm);
+		}
+
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
+		 enum ppp_packet_type type, uint8_t id,
+		 void *data, uint32_t data_len)
+{
+	/* Note that the data parameter is the received PPP packet if
+	 * we want to send PROTOCOL or CODE reject packet.
+	 */
+	struct net_pkt *req_pkt = data;
+	uint16_t protocol = 0;
+	size_t len = 0;
+	struct ppp_packet ppp;
+	struct net_pkt *pkt = NULL;
+	int ret;
+
+	if (!iface) {
+		if (!fsm) {
+			return -ENOENT;
+		}
+
+		iface = ppp_fsm_iface(fsm);
+	}
+
+	if (fsm) {
+		protocol = fsm->protocol;
+	}
+
+	switch (type) {
+	case PPP_CODE_REJ:
+		len = net_pkt_get_len(req_pkt);
+		len = MIN(len, PPP_MRU);
+		break;
+
+	case PPP_CONFIGURE_ACK:
+	case PPP_CONFIGURE_NACK:
+	case PPP_CONFIGURE_REJ:
+	case PPP_CONFIGURE_REQ:
+		pkt = data;
+		/* 2 + 1 + 1 (configure-[req|ack|nack|rej]) +
+		 * data_len (options)
+		 */
+		len = sizeof(ppp) + data_len;
+		break;
+
+	case PPP_DISCARD_REQ:
+		break;
+
+	case PPP_ECHO_REQ:
+		len = sizeof(ppp) + sizeof(uint32_t) + data_len;
+		break;
+
+	case PPP_ECHO_REPLY:
+		len = sizeof(ppp) + net_pkt_remaining_data(req_pkt);
+		break;
+
+	case PPP_PROTOCOL_REJ:
+		len = sizeof(ppp) + sizeof(uint16_t) +
+			net_pkt_remaining_data(req_pkt);
+		protocol = PPP_LCP;
+		break;
+
+	case PPP_TERMINATE_REQ:
+	case PPP_TERMINATE_ACK:
+		len = sizeof(ppp);
+		break;
+
+	default:
+		break;
+	}
+
+	if (len < sizeof(ppp)) {
+		return -EINVAL;
+	}
+
+	ppp.code = type;
+	ppp.id = id;
+	ppp.length = htons(len);
+
+	if (!pkt) {
+		pkt = net_pkt_alloc_with_buffer(iface,
+						sizeof(uint16_t) + len,
+						AF_UNSPEC, 0,
+						PPP_BUF_ALLOC_TIMEOUT);
+		if (!pkt) {
+			goto out_of_mem;
+		}
+	} else {
+		struct net_buf *buf;
+
+		buf = net_pkt_get_reserve_tx_data(PPP_BUF_ALLOC_TIMEOUT);
+		if (!buf) {
+			LOG_ERR("failed to allocate buffer");
+			goto out_of_mem;
+		}
+
+		net_pkt_frag_insert(pkt, buf);
+		net_pkt_cursor_init(pkt);
+	}
+
+	ret = net_pkt_write_be16(pkt, protocol);
+	if (ret < 0) {
+		goto out_of_mem;
+	}
+
+	ret = net_pkt_write(pkt, &ppp, sizeof(ppp));
+	if (ret < 0) {
+		goto out_of_mem;
+	}
+
+	if (type == PPP_CODE_REJ) {
+		if (!req_pkt) {
+			goto out_of_mem;
+		}
+
+		net_pkt_cursor_init(req_pkt);
+		net_pkt_copy(pkt, req_pkt, len);
+
+	} else if (type == PPP_ECHO_REQ) {
+		struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+						       lcp.fsm);
+		if (ctx->lcp.magic) {
+			ctx->lcp.magic = sys_rand32_get();
+		}
+
+		ret = net_pkt_write_be32(pkt, ctx->lcp.magic);
+		if (ret < 0) {
+			goto out_of_mem;
+		}
+
+		data_len = MIN(data_len, PPP_MRU);
+		if (data_len > 0) {
+			if (data_len == sizeof(uint32_t)) {
+				ret = net_pkt_write_be32(pkt,
+						       POINTER_TO_UINT(data));
+			} else {
+				ret = net_pkt_write(pkt, data, data_len);
+			}
+
+			if (ret < 0) {
+				goto out_of_mem;
+			}
+		}
+	} else if (type == PPP_ECHO_REPLY) {
+		net_pkt_copy(pkt, req_pkt, len);
+	} else if (type == PPP_PROTOCOL_REJ) {
+		net_pkt_cursor_init(req_pkt);
+		net_pkt_copy(pkt, req_pkt, len);
+	}
+
+	NET_DBG("[%s/%p] Sending %zd bytes pkt %p (options len %d)",
+		fsm ? fsm->name : "?", fsm, net_pkt_get_len(pkt), pkt,
+		data_len);
+
+	net_pkt_set_ppp(pkt, true);
+
+	if (fsm) {
+		/* Do not call net_send_data() directly in order to make this
+		 * thread run before the sending happens. If we call the
+		 * net_send_data() from this thread, then in fast link (like
+		 * when running inside QEMU) the reply might arrive before we
+		 * have returned from this function. That is bad because the
+		 * fsm would be in wrong state and the received pkt is dropped.
+		 */
+		k_work_init(net_pkt_work(pkt), ppp_pkt_send);
+		k_work_submit(net_pkt_work(pkt));
+	} else {
+		ret = net_send_data(pkt);
+		if (ret < 0) {
+			net_pkt_unref(pkt);
+		}
+	}
+
+	return 0;
+
+out_of_mem:
+	if (pkt) {
+		net_pkt_unref(pkt);
+	}
+
+	return -ENOMEM;
+}
+
+static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
+					       uint8_t id,
+					       struct net_pkt *pkt,
+					       uint16_t remaining_len)
+{
+	struct net_pkt *out = NULL;
+	int len = 0;
+	enum ppp_packet_type code;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_SENT:
+	case PPP_ACK_RECEIVED:
+		break;
+
+	case PPP_CLOSED:
+		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
+				   id, NULL, 0);
+		return NET_OK;
+
+	case PPP_CLOSING:
+	case PPP_STOPPING:
+		return NET_OK;
+
+	case PPP_OPENED:
+		fsm_down(fsm);
+
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_REQUEST_SENT:
+		/* Received request while waiting ACK */
+		break;
+
+	case PPP_STOPPED:
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	out = net_pkt_alloc_with_buffer(net_pkt_iface(pkt),
+					sizeof(uint16_t) + sizeof(uint16_t) +
+						sizeof(uint8_t) + sizeof(uint8_t) +
+						remaining_len,
+					AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
+	if (!out) {
+		return NET_DROP;
+	}
+
+	net_pkt_cursor_init(out);
+
+	if (fsm->cb.config_info_req) {
+		int ret;
+
+		ret = fsm->cb.config_info_req(fsm, pkt, remaining_len, out);
+		if (ret < 0) {
+			goto unref_out_pkt;
+		}
+
+		if (fsm->nack_loops >= MAX_NACK_LOOPS &&
+		    ret == PPP_CONFIGURE_NACK) {
+			ret = PPP_CONFIGURE_REJ;
+		}
+
+		code = ret;
+		len = net_pkt_get_len(out);
+	} else if (remaining_len) {
+		code = PPP_CONFIGURE_REJ;
+
+		net_pkt_copy(out, pkt, remaining_len);
+		len = remaining_len;
+	} else {
+		code = PPP_CONFIGURE_ACK;
+	}
+
+	NET_DBG("[%s/%p] Sending %s (%d) id %d to peer while in %s (%d)",
+		fsm->name, fsm, ppp_pkt_type2str(code), code, id,
+		ppp_state_str(fsm->state), fsm->state);
+
+	(void)ppp_send_pkt(fsm, NULL, code, id, out, len);
+
+	if (code == PPP_CONFIGURE_ACK) {
+		if (fsm->state == PPP_ACK_RECEIVED) {
+			k_delayed_work_cancel(&fsm->timer);
+
+			ppp_change_state(fsm, PPP_OPENED);
+
+			if (fsm->cb.up) {
+				fsm->cb.up(fsm);
+			}
+		} else {
+			ppp_change_state(fsm, PPP_ACK_SENT);
+		}
+
+		fsm->nack_loops = 0;
+	} else {
+		if (fsm->state != PPP_ACK_RECEIVED) {
+			ppp_change_state(fsm, PPP_REQUEST_SENT);
+		}
+
+		if (code == PPP_CONFIGURE_NACK) {
+			fsm->nack_loops++;
+		}
+	}
+
+	return NET_OK;
+
+unref_out_pkt:
+	net_pkt_unref(out);
+
+	return NET_DROP;
+}
+
+static enum net_verdict fsm_recv_configure_ack(struct ppp_fsm *fsm, uint8_t id,
+					       struct net_pkt *pkt,
+					       uint16_t remaining_len)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	if (id != fsm->req_id || fsm->ack_received) {
+		return NET_DROP;
+	}
+
+	if (fsm->cb.config_info_ack) {
+		if (fsm->cb.config_info_ack(fsm, pkt, remaining_len) < 0) {
+			NET_DBG("[%s/%p] %s %s received", fsm->name, fsm,
+				"Invalid",
+				ppp_pkt_type2str(PPP_CONFIGURE_ACK));
+			return NET_DROP;
+		}
+	}
+
+	fsm->ack_received = true;
+	fsm->recv_nack_loops = 0;
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+		k_delayed_work_cancel(&fsm->timer);
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_ACK_SENT:
+		k_delayed_work_cancel(&fsm->timer);
+		ppp_change_state(fsm, PPP_OPENED);
+		fsm->retransmits = MAX_CONFIGURE_REQ;
+		if (fsm->cb.up) {
+			fsm->cb.up(fsm);
+		}
+
+		break;
+
+	case PPP_CLOSED:
+	case PPP_STOPPED:
+		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
+				   id, NULL, 0);
+		break;
+
+	case PPP_OPENED:
+		fsm_down(fsm);
+
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_REQUEST_SENT:
+		ppp_change_state(fsm, PPP_ACK_RECEIVED);
+		fsm->retransmits = MAX_CONFIGURE_REQ;
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	return NET_OK;
+}
+
+static enum net_verdict fsm_recv_configure_nack_rej(struct ppp_fsm *fsm,
+						    enum ppp_packet_type code,
+						    uint8_t id,
+						    struct net_pkt *pkt,
+						    uint16_t length)
+{
+	bool ret = false;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	if (id != fsm->req_id || fsm->ack_received) {
+		return NET_DROP;
+	}
+
+	if (code == PPP_CONFIGURE_NACK) {
+		bool rejected = false;
+
+		fsm->recv_nack_loops++;
+
+		if (fsm->recv_nack_loops >= MAX_NACK_LOOPS) {
+			rejected = true;
+		}
+
+		if (fsm->cb.config_info_nack) {
+			int err;
+
+			err = fsm->cb.config_info_nack(fsm, pkt, length,
+						       rejected);
+			if (err < 0) {
+				NET_DBG("[%s/%p] %s failed (%d)",
+					fsm->name, fsm, "Nack", err);
+			} else {
+				ret = true;
+			}
+		}
+
+		if (!ret) {
+			NET_DBG("[%s/%p] %s %s (id %d)", fsm->name, fsm,
+				"Invalid", ppp_pkt_type2str(code), id);
+			return NET_DROP;
+		}
+	} else {
+		fsm->recv_nack_loops = 0;
+
+		if (fsm->cb.config_info_rej) {
+			int err;
+
+			err = fsm->cb.config_info_rej(fsm, pkt, length);
+			if (err < 0) {
+				NET_DBG("[%s/%p] %s failed (%d)",
+					fsm->name, fsm, "Reject", err);
+			} else {
+				ret = true;
+			}
+		}
+
+		if (!ret) {
+			NET_DBG("[%s/%p] %s %s (id %d)", fsm->name, fsm,
+				"Invalid", ppp_pkt_type2str(code), id);
+			return NET_DROP;
+		}
+	}
+
+	fsm->ack_received = true;
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+		k_delayed_work_cancel(&fsm->timer);
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_ACK_SENT:
+	case PPP_REQUEST_SENT:
+		k_delayed_work_cancel(&fsm->timer);
+		fsm_send_configure_req(fsm, false);
+		break;
+
+	case PPP_CLOSED:
+	case PPP_STOPPED:
+		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK,
+				   id, NULL, 0);
+		break;
+
+	case PPP_OPENED:
+		fsm_down(fsm);
+
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	return NET_OK;
+}
+
+static enum net_verdict fsm_recv_terminate_req(struct ppp_fsm *fsm, uint8_t id,
+					       struct net_pkt *pkt,
+					       uint16_t length)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+	case PPP_ACK_SENT:
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_OPENED:
+		if (length > 0) {
+			net_pkt_read(pkt, fsm->terminate_reason,
+				     MIN(length,
+					 sizeof(fsm->terminate_reason) - 1));
+
+			NET_DBG("[%s/%p] %s (%s)",
+				fsm->name, fsm, "Terminated by peer",
+				log_strdup(fsm->terminate_reason));
+		} else {
+			NET_DBG("[%s/%p] Terminated by peer",
+				fsm->name, fsm);
+		}
+
+		fsm->retransmits = 0;
+		ppp_change_state(fsm, PPP_STOPPING);
+
+		fsm_down(fsm);
+
+		(void)k_delayed_work_submit(&fsm->timer, FSM_TIMEOUT);
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_TERMINATE_ACK, id,
+			   NULL, 0);
+
+	return NET_OK;
+}
+
+static enum net_verdict fsm_recv_terminate_ack(struct ppp_fsm *fsm, uint8_t id,
+					       struct net_pkt *pkt,
+					       uint16_t length)
+{
+	enum ppp_state new_state;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_CLOSING:
+		new_state = PPP_CLOSED;
+		goto stopped;
+
+	case PPP_OPENED:
+		fsm_down(fsm);
+
+		fsm_send_configure_req(fsm, false);
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	case PPP_STOPPING:
+		new_state = PPP_STOPPED;
+		goto stopped;
+
+	case PPP_ACK_RECEIVED:
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	return NET_OK;
+
+stopped:
+	k_delayed_work_cancel(&fsm->timer);
+	ppp_change_state(fsm, new_state);
+
+	if (fsm->cb.finished) {
+		fsm->cb.finished(fsm);
+	}
+
+	return NET_OK;
+}
+
+static enum net_verdict fsm_recv_code_rej(struct ppp_fsm *fsm,
+					  struct net_pkt *pkt)
+{
+	uint8_t code, id;
+	int ret;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	ret = net_pkt_read_u8(pkt, &code);
+	if (ret < 0) {
+		return NET_DROP;
+	}
+
+	ret = net_pkt_read_u8(pkt, &id);
+	if (ret < 0) {
+		return NET_DROP;
+	}
+
+	NET_DBG("[%s/%p] Received Code-Rej code %d id %d", fsm->name, fsm,
+		code, id);
+
+	if (fsm->state == PPP_ACK_RECEIVED) {
+		ppp_change_state(fsm, PPP_REQUEST_SENT);
+	}
+
+	return NET_OK;
+}
+
+void ppp_fsm_proto_reject(struct ppp_fsm *fsm)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	switch (fsm->state) {
+	case PPP_ACK_RECEIVED:
+	case PPP_ACK_SENT:
+	case PPP_STOPPING:
+	case PPP_REQUEST_SENT:
+		k_delayed_work_cancel(&fsm->timer);
+		ppp_change_state(fsm, PPP_STOPPED);
+		if (fsm->cb.finished) {
+			fsm->cb.finished(fsm);
+		}
+
+		break;
+
+	case PPP_CLOSED:
+		ppp_change_state(fsm, PPP_CLOSED);
+		if (fsm->cb.finished) {
+			fsm->cb.finished(fsm);
+		}
+
+		break;
+
+	case PPP_CLOSING:
+		k_delayed_work_cancel(&fsm->timer);
+		ppp_change_state(fsm, PPP_CLOSED);
+		if (fsm->cb.finished) {
+			fsm->cb.finished(fsm);
+		}
+
+		break;
+
+	case PPP_OPENED:
+		terminate(fsm, PPP_STOPPING);
+		break;
+
+	case PPP_STOPPED:
+		ppp_change_state(fsm, PPP_STOPPED);
+		if (fsm->cb.finished) {
+			fsm->cb.finished(fsm);
+		}
+
+		break;
+
+	default:
+		NET_DBG("[%s/%p] %s state %s (%d)", fsm->name, fsm, "Invalid",
+			ppp_state_str(fsm->state), fsm->state);
+		break;
+	}
+}
+
+enum net_verdict ppp_fsm_input(struct ppp_fsm *fsm, uint16_t proto,
+			       struct net_pkt *pkt)
+{
+	uint8_t code, id;
+	uint16_t length;
+	int ret;
+
+	ret = net_pkt_read_u8(pkt, &code);
+	if (ret < 0) {
+		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
+			fsm->name, fsm, "code", net_pkt_get_len(pkt));
+		return NET_DROP;
+	}
+
+	ret = net_pkt_read_u8(pkt, &id);
+	if (ret < 0) {
+		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
+			fsm->name, fsm, "id", net_pkt_get_len(pkt));
+		return NET_DROP;
+	}
+
+	ret = net_pkt_read_be16(pkt, &length);
+	if (ret < 0) {
+		NET_DBG("[%s/%p] Cannot read %s (pkt len %zd)",
+			fsm->name, fsm, "length", net_pkt_get_len(pkt));
+		return NET_DROP;
+	}
+
+	if (length > PPP_MRU) {
+		NET_DBG("[%s/%p] Too long msg %d", fsm->name, fsm, length);
+		return NET_DROP;
+	}
+
+	if (fsm->state == PPP_INITIAL || fsm->state == PPP_STARTING) {
+		NET_DBG("[%s/%p] Received %s packet in wrong state %s (%d)",
+			fsm->name, fsm, ppp_proto2str(proto),
+			ppp_state_str(fsm->state), fsm->state);
+		return NET_DROP;
+	}
+
+	/* Length will only contain payload/data length */
+	length -= sizeof(code) + sizeof(id) + sizeof(length);
+
+	NET_DBG("[%s/%p] %s %s (%d) id %d payload len %d", fsm->name, fsm,
+		ppp_proto2str(proto), ppp_pkt_type2str(code), code, id,
+		length);
+
+	switch (code) {
+	case PPP_CODE_REJ:
+		return fsm_recv_code_rej(fsm, pkt);
+
+	case PPP_CONFIGURE_ACK:
+		return fsm_recv_configure_ack(fsm, id, pkt, length);
+
+	case PPP_CONFIGURE_NACK:
+		return fsm_recv_configure_nack_rej(fsm, code, id, pkt, length);
+
+	case PPP_CONFIGURE_REQ:
+		return fsm_recv_configure_req(fsm, id, pkt, length);
+
+	case PPP_CONFIGURE_REJ:
+		return fsm_recv_configure_nack_rej(fsm, code, id, pkt, length);
+
+	case PPP_TERMINATE_ACK:
+		return fsm_recv_terminate_ack(fsm, id, pkt, length);
+
+	case PPP_TERMINATE_REQ:
+		return fsm_recv_terminate_req(fsm, id, pkt, length);
+
+	default:
+		if (fsm->cb.proto_extension) {
+			enum net_verdict verdict;
+
+			verdict = fsm->cb.proto_extension(fsm, code, id, pkt);
+			if (verdict != NET_DROP) {
+				return verdict;
+			}
+		}
+
+		(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_CODE_REJ,
+				   id, pkt, 0);
+	}
+
+	return NET_DROP;
+}
+
+enum net_verdict ppp_fsm_recv_protocol_rej(struct ppp_fsm *fsm,
+					   uint8_t id,
+					   struct net_pkt *pkt)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	return NET_DROP;
+}
+
+enum net_verdict ppp_fsm_recv_echo_req(struct ppp_fsm *fsm,
+				       uint8_t id,
+				       struct net_pkt *pkt)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	(void)ppp_send_pkt(fsm, net_pkt_iface(pkt), PPP_ECHO_REPLY,
+		id, pkt, 0);
+
+	return NET_OK;
+}
+
+enum net_verdict ppp_fsm_recv_echo_reply(struct ppp_fsm *fsm,
+					 uint8_t id,
+					 struct net_pkt *pkt)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+#if defined(CONFIG_NET_SHELL)
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+	if (ctx->shell.echo_reply.cb) {
+		ctx->shell.echo_reply.cb(ctx->shell.echo_reply.user_data,
+					 ctx->shell.echo_reply.user_data_len);
+	}
+#endif /* CONFIG_NET_SHELL */
+
+	return NET_OK;
+}
+
+enum net_verdict ppp_fsm_recv_discard_req(struct ppp_fsm *fsm,
+					  uint8_t id,
+					  struct net_pkt *pkt)
+{
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	return NET_OK;
+}
+
+void ppp_send_proto_rej(struct net_if *iface, struct net_pkt *pkt,
+			uint16_t protocol)
+{
+	uint8_t code, id;
+	int ret;
+
+	ret = net_pkt_read_u8(pkt, &code);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	ret = net_pkt_read_u8(pkt, &id);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	(void)ppp_send_pkt(NULL, iface, PPP_PROTOCOL_REJ, id, pkt, 0);
+
+quit:
+	return;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipcp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipcp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipcp.c	(working copy)
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ * Copyright (c) 2020 Endian Technologies AB
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+#include <net/dns_resolve.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+static enum net_verdict ipcp_handle(struct ppp_context *ctx,
+				    struct net_if *iface,
+				    struct net_pkt *pkt)
+{
+	return ppp_fsm_input(&ctx->ipcp.fsm, PPP_IPCP, pkt);
+}
+
+/* Length is (6): code + id + IPv4 address length. RFC 1332 and also
+ * DNS in RFC 1877.
+ */
+#define IP_ADDRESS_OPTION_LEN (1 + 1 + 4)
+
+static int ipcp_add_address(struct ppp_context *ctx, struct net_pkt *pkt,
+			    struct in_addr *addr)
+{
+	net_pkt_write_u8(pkt, 1 + 1 + sizeof(addr->s_addr));
+	return net_pkt_write(pkt, &addr->s_addr, sizeof(addr->s_addr));
+}
+
+static int ipcp_add_ip_address(struct ppp_context *ctx, struct net_pkt *pkt)
+{
+	return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.address);
+}
+
+static int ipcp_add_dns1(struct ppp_context *ctx, struct net_pkt *pkt)
+{
+	return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns1_address);
+}
+
+static int ipcp_add_dns2(struct ppp_context *ctx, struct net_pkt *pkt)
+{
+	return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns2_address);
+}
+
+static int ipcp_ack_check_address(struct net_pkt *pkt, size_t oplen,
+				  struct in_addr *addr)
+{
+	struct in_addr ack_addr;
+	int ret;
+
+	if (oplen != sizeof(ack_addr)) {
+		return -EINVAL;
+	}
+
+	ret = net_pkt_read(pkt, &ack_addr, sizeof(ack_addr));
+	if (ret) {
+		return ret;
+	}
+
+	if (memcmp(&ack_addr, addr, sizeof(ack_addr)) != 0) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ipcp_ack_ip_address(struct ppp_context *ctx, struct net_pkt *pkt,
+			       uint8_t oplen)
+{
+	return ipcp_ack_check_address(pkt, oplen,
+				      &ctx->ipcp.my_options.address);
+}
+
+static int ipcp_ack_dns1(struct ppp_context *ctx, struct net_pkt *pkt,
+			 uint8_t oplen)
+{
+	return ipcp_ack_check_address(pkt, oplen,
+				      &ctx->ipcp.my_options.dns1_address);
+}
+
+static int ipcp_ack_dns2(struct ppp_context *ctx, struct net_pkt *pkt,
+			 uint8_t oplen)
+{
+	return ipcp_ack_check_address(pkt, oplen,
+				      &ctx->ipcp.my_options.dns2_address);
+}
+
+static int ipcp_nak_override_address(struct net_pkt *pkt, size_t oplen,
+				     struct in_addr *addr)
+{
+	if (oplen != sizeof(*addr)) {
+		return -EINVAL;
+	}
+
+	return net_pkt_read(pkt, addr, sizeof(*addr));
+}
+
+static int ipcp_nak_ip_address(struct ppp_context *ctx, struct net_pkt *pkt,
+			       uint8_t oplen)
+{
+	return ipcp_nak_override_address(pkt, oplen,
+					 &ctx->ipcp.my_options.address);
+}
+
+static int ipcp_nak_dns1(struct ppp_context *ctx, struct net_pkt *pkt,
+			 uint8_t oplen)
+{
+	return ipcp_nak_override_address(pkt, oplen,
+					 &ctx->ipcp.my_options.dns1_address);
+}
+
+static int ipcp_nak_dns2(struct ppp_context *ctx, struct net_pkt *pkt,
+			 uint8_t oplen)
+{
+	return ipcp_nak_override_address(pkt, oplen,
+					 &ctx->ipcp.my_options.dns2_address);
+}
+
+static const struct ppp_my_option_info ipcp_my_options[] = {
+	PPP_MY_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_add_ip_address,
+		      ipcp_ack_ip_address, ipcp_nak_ip_address),
+	PPP_MY_OPTION(IPCP_OPTION_DNS1, ipcp_add_dns1,
+		      ipcp_ack_dns1, ipcp_nak_dns1),
+	PPP_MY_OPTION(IPCP_OPTION_DNS2, ipcp_add_dns2,
+		      ipcp_ack_dns2, ipcp_nak_dns2),
+};
+
+BUILD_ASSERT(ARRAY_SIZE(ipcp_my_options) == IPCP_NUM_MY_OPTIONS);
+
+static struct net_pkt *ipcp_config_info_add(struct ppp_fsm *fsm)
+{
+	return ppp_my_options_add(fsm, 3 * IP_ADDRESS_OPTION_LEN);
+}
+
+struct ipcp_peer_option_data {
+	bool addr_present;
+	struct in_addr addr;
+};
+
+static int ipcp_ip_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
+				 void *user_data)
+{
+	struct ipcp_peer_option_data *data = user_data;
+	int ret;
+
+	ret = net_pkt_read(pkt, &data->addr, sizeof(data->addr));
+	if (ret < 0) {
+		/* Should not happen, is the pkt corrupt? */
+		return -EMSGSIZE;
+	}
+
+	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		char dst[INET_ADDRSTRLEN];
+		char *addr_str;
+
+		addr_str = net_addr_ntop(AF_INET, &data->addr, dst,
+					 sizeof(dst));
+
+		NET_DBG("[IPCP] Received peer address %s",
+			log_strdup(addr_str));
+	}
+
+	data->addr_present = true;
+
+	return 0;
+}
+
+static const struct ppp_peer_option_info ipcp_peer_options[] = {
+	PPP_PEER_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_ip_address_parse, NULL),
+};
+
+static int ipcp_config_info_req(struct ppp_fsm *fsm,
+				struct net_pkt *pkt,
+				uint16_t length,
+				struct net_pkt *ret_pkt)
+{
+	struct ppp_context *ctx =
+		CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
+	struct ipcp_peer_option_data data = {
+		.addr_present = false,
+	};
+	int ret;
+
+	ret = ppp_config_info_req(fsm, pkt, length, ret_pkt, PPP_IPCP,
+				  ipcp_peer_options,
+				  ARRAY_SIZE(ipcp_peer_options),
+				  &data);
+	if (ret != PPP_CONFIGURE_ACK) {
+		/* There are some issues with configuration still */
+		return ret;
+	}
+
+	if (!data.addr_present) {
+		NET_DBG("[%s/%p] No %saddress provided",
+			fsm->name, fsm, "peer ");
+		return PPP_CONFIGURE_ACK;
+	}
+
+	/* The address is the remote address, we then need
+	 * to figure out what our address should be.
+	 *
+	 * TODO:
+	 *   - check that the IP address can be accepted
+	 */
+
+	memcpy(&ctx->ipcp.peer_options.address, &data.addr, sizeof(data.addr));
+
+	return PPP_CONFIGURE_ACK;
+}
+
+static void ipcp_set_dns_servers(struct ppp_fsm *fsm)
+{
+#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE)
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipcp.fsm);
+
+	struct dns_resolve_context *dnsctx;
+	struct sockaddr_in dns1 = {
+		.sin_family = AF_INET,
+		.sin_port = htons(53),
+		.sin_addr = ctx->ipcp.my_options.dns1_address
+	};
+	struct sockaddr_in dns2 = {
+		.sin_family = AF_INET,
+		.sin_port = htons(53),
+		.sin_addr = ctx->ipcp.my_options.dns2_address
+	};
+	const struct sockaddr *dns_servers[] = {
+		(struct sockaddr *) &dns1,
+		(struct sockaddr *) &dns2,
+		NULL
+	};
+	int i, ret;
+
+	if (!dns1.sin_addr.s_addr) {
+		return;
+	}
+
+	if (!dns2.sin_addr.s_addr) {
+		dns_servers[1] = NULL;
+	}
+
+	dnsctx = dns_resolve_get_default();
+	for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+		if (!dnsctx->queries[i].cb) {
+			continue;
+		}
+
+		dns_resolve_cancel(dnsctx, dnsctx->queries[i].id);
+	}
+	dns_resolve_close(dnsctx);
+
+	ret = dns_resolve_init(dnsctx, NULL, dns_servers);
+	if (ret < 0) {
+		NET_ERR("Could not set DNS servers");
+		return;
+	}
+#endif
+}
+
+static int ipcp_config_info_nack(struct ppp_fsm *fsm,
+				 struct net_pkt *pkt,
+				 uint16_t length,
+				 bool rejected)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipcp.fsm);
+	int ret;
+
+	ret = ppp_my_options_parse_conf_nak(fsm, pkt, length);
+	if (ret) {
+		return ret;
+	}
+
+	if (!ctx->ipcp.my_options.address.s_addr) {
+		return -EINVAL;
+	}
+
+	ipcp_set_dns_servers(fsm);
+
+	return 0;
+}
+
+static void ipcp_lower_down(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_down(&ctx->ipcp.fsm);
+}
+
+static void ipcp_lower_up(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_up(&ctx->ipcp.fsm);
+}
+
+static void ipcp_open(struct ppp_context *ctx)
+{
+	ppp_fsm_open(&ctx->ipcp.fsm);
+}
+
+static void ipcp_close(struct ppp_context *ctx, const uint8_t *reason)
+{
+	ppp_fsm_close(&ctx->ipcp.fsm, reason);
+}
+
+static void ipcp_up(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipcp.fsm);
+	struct net_if_addr *addr;
+	char dst[INET_ADDRSTRLEN];
+	char *addr_str;
+
+	if (ctx->is_ipcp_up) {
+		return;
+	}
+
+	addr_str = net_addr_ntop(AF_INET, &ctx->ipcp.my_options.address,
+				 dst, sizeof(dst));
+
+	addr = net_if_ipv4_addr_add(ctx->iface,
+				    &ctx->ipcp.my_options.address,
+				    NET_ADDR_MANUAL,
+				    0);
+	if (addr == NULL) {
+		NET_ERR("Could not set IP address %s", log_strdup(addr_str));
+		return;
+	}
+
+	NET_DBG("PPP up with address %s", log_strdup(addr_str));
+	ppp_network_up(ctx, PPP_IP);
+
+	ctx->is_ipcp_up = true;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+}
+
+static void ipcp_down(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipcp.fsm);
+
+	/* Ensure address is always removed if it exists */
+	if (ctx->ipcp.my_options.address.s_addr) {
+		(void)net_if_ipv4_addr_rm(
+			ctx->iface, &ctx->ipcp.my_options.address);
+	}
+
+	memset(&ctx->ipcp.my_options.address, 0,
+	       sizeof(ctx->ipcp.my_options.address));
+	memset(&ctx->ipcp.my_options.dns1_address, 0,
+	       sizeof(ctx->ipcp.my_options.dns1_address));
+	memset(&ctx->ipcp.my_options.dns2_address, 0,
+	       sizeof(ctx->ipcp.my_options.dns2_address));
+
+	if (!ctx->is_ipcp_up) {
+		return;
+	}
+
+	ctx->is_ipcp_up = false;
+
+	ppp_network_down(ctx, PPP_IP);
+}
+
+static void ipcp_finished(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipcp.fsm);
+
+	if (!ctx->is_ipcp_open) {
+		return;
+	}
+
+	ctx->is_ipcp_open = false;
+
+	ppp_network_done(ctx, PPP_IP);
+}
+
+static void ipcp_proto_reject(struct ppp_fsm *fsm)
+{
+	ppp_fsm_lower_down(fsm);
+}
+
+static void ipcp_init(struct ppp_context *ctx)
+{
+	NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_IPCP), PPP_IPCP,
+		&ctx->ipcp.fsm);
+
+	memset(&ctx->ipcp.fsm, 0, sizeof(ctx->ipcp.fsm));
+
+	ppp_fsm_init(&ctx->ipcp.fsm, PPP_IPCP);
+
+	ppp_fsm_name_set(&ctx->ipcp.fsm, ppp_proto2str(PPP_IPCP));
+
+	ctx->ipcp.fsm.my_options.info = ipcp_my_options;
+	ctx->ipcp.fsm.my_options.data = ctx->ipcp.my_options_data;
+	ctx->ipcp.fsm.my_options.count = ARRAY_SIZE(ipcp_my_options);
+
+	ctx->ipcp.fsm.cb.up = ipcp_up;
+	ctx->ipcp.fsm.cb.down = ipcp_down;
+	ctx->ipcp.fsm.cb.finished = ipcp_finished;
+	ctx->ipcp.fsm.cb.proto_reject = ipcp_proto_reject;
+	ctx->ipcp.fsm.cb.config_info_add = ipcp_config_info_add;
+	ctx->ipcp.fsm.cb.config_info_req = ipcp_config_info_req;
+	ctx->ipcp.fsm.cb.config_info_nack = ipcp_config_info_nack;
+	ctx->ipcp.fsm.cb.config_info_rej = ppp_my_options_parse_conf_rej;
+}
+
+PPP_PROTOCOL_REGISTER(IPCP, PPP_IPCP,
+		      ipcp_init, ipcp_handle,
+		      ipcp_lower_up, ipcp_lower_down,
+		      ipcp_open, ipcp_close);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipv6cp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipv6cp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ipv6cp.c	(working copy)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+#include "ipv6.h"
+
+#include "ppp_internal.h"
+
+static enum net_verdict ipv6cp_handle(struct ppp_context *ctx,
+				    struct net_if *iface,
+				    struct net_pkt *pkt)
+{
+	return ppp_fsm_input(&ctx->ipv6cp.fsm, PPP_IPV6CP, pkt);
+}
+
+/* Length is (10): code + id + interface identifier length */
+#define INTERFACE_IDENTIFIER_OPTION_LEN (1 + 1 + 8)
+
+static int ipv6cp_add_iid(struct ppp_context *ctx, struct net_pkt *pkt)
+{
+	uint8_t *iid = ctx->ipv6cp.my_options.iid;
+	size_t iid_len = sizeof(ctx->ipv6cp.my_options.iid);
+	struct net_linkaddr *linkaddr;
+
+	linkaddr = net_if_get_link_addr(ctx->iface);
+	if (linkaddr->len == 8) {
+		memcpy(iid, linkaddr->addr, iid_len);
+	} else {
+		memcpy(iid, linkaddr->addr, 3);
+		iid[3] = 0xff;
+		iid[4] = 0xfe;
+		memcpy(iid + 5, linkaddr->addr + 3, 3);
+	}
+
+	net_pkt_write_u8(pkt, INTERFACE_IDENTIFIER_OPTION_LEN);
+	return net_pkt_write(pkt, iid, iid_len);
+}
+
+static int ipv6cp_ack_iid(struct ppp_context *ctx, struct net_pkt *pkt,
+			  uint8_t oplen)
+{
+	uint8_t *req_iid = ctx->ipv6cp.my_options.iid;
+	uint8_t ack_iid[PPP_INTERFACE_IDENTIFIER_LEN];
+	int ret;
+
+	if (oplen != sizeof(ack_iid)) {
+		return -EINVAL;
+	}
+
+	ret = net_pkt_read(pkt, ack_iid, sizeof(ack_iid));
+	if (ret) {
+		return ret;
+	}
+
+	if (memcmp(ack_iid, req_iid, sizeof(ack_iid)) != 0) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct ppp_my_option_info ipv6cp_my_options[] = {
+	PPP_MY_OPTION(IPV6CP_OPTION_INTERFACE_IDENTIFIER,
+		      ipv6cp_add_iid, ipv6cp_ack_iid, NULL),
+};
+
+BUILD_ASSERT(ARRAY_SIZE(ipv6cp_my_options) == IPV6CP_NUM_MY_OPTIONS);
+
+static struct net_pkt *ipv6cp_config_info_add(struct ppp_fsm *fsm)
+{
+	return ppp_my_options_add(fsm, INTERFACE_IDENTIFIER_OPTION_LEN);
+}
+
+struct ipv6cp_peer_option_data {
+	bool iface_id_present;
+	uint8_t iface_id[PPP_INTERFACE_IDENTIFIER_LEN];
+};
+
+static int ipv6cp_interface_identifier_parse(struct ppp_fsm *fsm,
+					     struct net_pkt *pkt,
+					     void *user_data)
+{
+	struct ipv6cp_peer_option_data *data = user_data;
+	int ret;
+
+	ret = net_pkt_read(pkt, data->iface_id, sizeof(data->iface_id));
+	if (ret < 0) {
+		/* Should not happen, is the pkt corrupt? */
+		return -EMSGSIZE;
+	}
+
+	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		uint8_t iid_str[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+
+		net_sprint_ll_addr_buf(data->iface_id, sizeof(data->iface_id),
+				       iid_str, sizeof(iid_str));
+
+		NET_DBG("[%s/%p] Received %siid %s",
+			fsm->name, fsm, "peer ", log_strdup(iid_str));
+	}
+
+	data->iface_id_present = true;
+
+	return 0;
+}
+
+static const struct ppp_peer_option_info ipv6cp_peer_options[] = {
+	PPP_PEER_OPTION(IPV6CP_OPTION_INTERFACE_IDENTIFIER,
+			ipv6cp_interface_identifier_parse, NULL),
+};
+
+static int ipv6cp_config_info_req(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length,
+				  struct net_pkt *ret_pkt)
+{
+	struct ppp_context *ctx =
+		CONTAINER_OF(fsm, struct ppp_context, ipv6cp.fsm);
+	struct ipv6cp_peer_option_data data = {
+		.iface_id_present = false,
+	};
+	int ret;
+
+	ret = ppp_config_info_req(fsm, pkt, length, ret_pkt, PPP_IPV6CP,
+				  ipv6cp_peer_options,
+				  ARRAY_SIZE(ipv6cp_peer_options),
+				  &data);
+	if (ret != PPP_CONFIGURE_ACK) {
+		/* There are some issues with configuration still */
+		return ret;
+	}
+
+	if (!data.iface_id_present) {
+		/* Interface id option was not present */
+		return -EINVAL;
+	}
+
+	memcpy(ctx->ipv6cp.peer_options.iid, data.iface_id,
+	       sizeof(data.iface_id));
+
+	return PPP_CONFIGURE_ACK;
+}
+
+static int ipv6cp_config_info_ack(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipv6cp.fsm);
+	uint8_t *iid = ctx->ipv6cp.my_options.iid;
+	size_t iid_len = sizeof(ctx->ipv6cp.my_options.iid);
+	int ret;
+
+	ret = ppp_my_options_parse_conf_ack(fsm, pkt, length);
+	if (ret) {
+		return -EINVAL;
+	}
+
+	if (!ppp_my_option_is_acked(fsm, IPV6CP_OPTION_INTERFACE_IDENTIFIER)) {
+		NET_ERR("IID was not acked");
+		return -EINVAL;
+	}
+
+	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		uint8_t iid_str[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+
+		net_sprint_ll_addr_buf(iid, iid_len,
+				       iid_str, sizeof(iid_str));
+
+		NET_DBG("[%s/%p] Received %siid %s",
+			fsm->name, fsm, "", log_strdup(iid_str));
+	}
+
+	return 0;
+}
+
+static void ipv6cp_lower_down(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_down(&ctx->ipv6cp.fsm);
+}
+
+static void ipv6cp_lower_up(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_up(&ctx->ipv6cp.fsm);
+}
+
+static void ipv6cp_open(struct ppp_context *ctx)
+{
+	ppp_fsm_open(&ctx->ipv6cp.fsm);
+}
+
+static void ipv6cp_close(struct ppp_context *ctx, const uint8_t *reason)
+{
+	ppp_fsm_close(&ctx->ipv6cp.fsm, reason);
+}
+
+static void setup_iid_address(uint8_t *iid, struct in6_addr *addr)
+{
+	addr->s6_addr[0] = 0xfe;
+	addr->s6_addr[1] = 0x80;
+	UNALIGNED_PUT(0, &addr->s6_addr16[1]);
+	UNALIGNED_PUT(0, &addr->s6_addr32[1]);
+	memcpy(&addr->s6_addr[8], iid, PPP_INTERFACE_IDENTIFIER_LEN);
+
+	/* TODO: should we toggle local/global bit */
+	/* addr->s6_addr[8] ^= 0x02; */
+}
+
+static void add_iid_address(struct net_if *iface, uint8_t *iid)
+{
+	struct net_if_addr *ifaddr;
+	struct in6_addr addr;
+
+	setup_iid_address(iid, &addr);
+
+	ifaddr = net_if_ipv6_addr_add(iface, &addr, NET_ADDR_AUTOCONF, 0);
+	if (!ifaddr) {
+		NET_ERR("Cannot add %s address to interface %p",
+			log_strdup(net_sprint_ipv6_addr(&addr)), iface);
+	} else {
+		/* As DAD is disabled, we need to mark the address
+		 * as a preferred one.
+		 */
+		ifaddr->addr_state = NET_ADDR_PREFERRED;
+	}
+}
+
+static void ipv6cp_up(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipv6cp.fsm);
+	struct net_nbr *nbr;
+	struct in6_addr peer_addr;
+	struct net_linkaddr peer_lladdr;
+
+	if (ctx->is_ipv6cp_up) {
+		return;
+	}
+
+	ppp_network_up(ctx, PPP_IPV6);
+
+	ctx->is_ipv6cp_up = true;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	add_iid_address(ctx->iface, ctx->ipv6cp.my_options.iid);
+
+	/* Add peer to neighbor table */
+	setup_iid_address(ctx->ipv6cp.peer_options.iid, &peer_addr);
+
+	peer_lladdr.addr = ctx->ipv6cp.peer_options.iid;
+	peer_lladdr.len = sizeof(ctx->ipv6cp.peer_options.iid);
+
+	/* TODO: What should be the type? */
+	peer_lladdr.type = NET_LINK_DUMMY;
+
+	nbr = net_ipv6_nbr_add(ctx->iface, &peer_addr, &peer_lladdr,
+			       false, NET_IPV6_NBR_STATE_STATIC);
+	if (!nbr) {
+		NET_ERR("[%s/%p] Cannot add peer %s to nbr table",
+			fsm->name, fsm,
+			log_strdup(net_sprint_addr(AF_INET6,
+						   (const void *)&peer_addr)));
+	} else {
+		if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+			uint8_t iid_str[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+			char dst[INET6_ADDRSTRLEN];
+			char *addr_str;
+
+			net_sprint_ll_addr_buf(peer_lladdr.addr,
+					       peer_lladdr.len,
+					       iid_str, sizeof(iid_str));
+
+			addr_str = net_addr_ntop(AF_INET6, &peer_addr, dst,
+						 sizeof(dst));
+
+			NET_DBG("[%s/%p] Peer %s [%s] %s nbr cache",
+				fsm->name, fsm, log_strdup(addr_str),
+				log_strdup(iid_str), "added to");
+		}
+	}
+}
+
+static void ipv6cp_down(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipv6cp.fsm);
+	struct net_linkaddr peer_lladdr;
+	struct in6_addr my_addr;
+	struct in6_addr peer_addr;
+	int ret;
+
+	if (!ctx->is_ipv6cp_up) {
+		return;
+	}
+
+	ctx->is_ipv6cp_up = false;
+
+	ppp_network_down(ctx, PPP_IPV6);
+
+	/* Remove my address */
+	setup_iid_address(ctx->ipv6cp.my_options.iid, &my_addr);
+	net_if_ipv6_addr_rm(ctx->iface, &my_addr);
+
+	/* Remove peer from neighbor table */
+	setup_iid_address(ctx->ipv6cp.peer_options.iid, &peer_addr);
+
+	peer_lladdr.addr = ctx->ipv6cp.peer_options.iid;
+	peer_lladdr.len = sizeof(ctx->ipv6cp.peer_options.iid);
+
+	/* TODO: What should be the type? */
+	peer_lladdr.type = NET_LINK_DUMMY;
+
+	ret = net_ipv6_nbr_rm(ctx->iface, &peer_addr);
+	if (!ret) {
+		NET_ERR("[%s/%p] Cannot rm peer %s from nbr table",
+			fsm->name, fsm,
+			log_strdup(net_sprint_addr(AF_INET6,
+						   (const void *)&peer_addr)));
+	} else {
+		if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+			uint8_t iid_str[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+			char dst[INET6_ADDRSTRLEN];
+			char *addr_str;
+
+			net_sprint_ll_addr_buf(ctx->ipv6cp.peer_options.iid,
+					sizeof(ctx->ipv6cp.peer_options.iid),
+					iid_str, sizeof(iid_str));
+
+			addr_str = net_addr_ntop(AF_INET6, &peer_addr, dst,
+						 sizeof(dst));
+
+			NET_DBG("[%s/%p] Peer %s [%s] %s nbr cache",
+				fsm->name, fsm, log_strdup(addr_str),
+				log_strdup(iid_str), "removed from");
+		}
+	}
+}
+
+static void ipv6cp_finished(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       ipv6cp.fsm);
+
+	if (!ctx->is_ipv6cp_open) {
+		return;
+	}
+
+	ctx->is_ipv6cp_open = false;
+
+	ppp_network_done(ctx, PPP_IPV6);
+}
+
+static void ipv6cp_proto_reject(struct ppp_fsm *fsm)
+{
+	ppp_fsm_lower_down(fsm);
+}
+
+static void ipv6cp_init(struct ppp_context *ctx)
+{
+	NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_IPV6CP),
+		PPP_IPV6CP, &ctx->ipv6cp.fsm);
+
+	memset(&ctx->ipv6cp.fsm, 0, sizeof(ctx->ipv6cp.fsm));
+
+	ppp_fsm_init(&ctx->ipv6cp.fsm, PPP_IPV6CP);
+
+	ppp_fsm_name_set(&ctx->ipv6cp.fsm, ppp_proto2str(PPP_IPV6CP));
+
+	ctx->ipv6cp.fsm.my_options.info = ipv6cp_my_options;
+	ctx->ipv6cp.fsm.my_options.data = ctx->ipv6cp.my_options_data;
+	ctx->ipv6cp.fsm.my_options.count = ARRAY_SIZE(ipv6cp_my_options);
+
+	ctx->ipv6cp.fsm.cb.up = ipv6cp_up;
+	ctx->ipv6cp.fsm.cb.down = ipv6cp_down;
+	ctx->ipv6cp.fsm.cb.finished = ipv6cp_finished;
+	ctx->ipv6cp.fsm.cb.proto_reject = ipv6cp_proto_reject;
+	ctx->ipv6cp.fsm.cb.config_info_ack = ipv6cp_config_info_ack;
+	ctx->ipv6cp.fsm.cb.config_info_rej = ppp_my_options_parse_conf_rej;
+	ctx->ipv6cp.fsm.cb.config_info_add = ipv6cp_config_info_add;
+	ctx->ipv6cp.fsm.cb.config_info_req = ipv6cp_config_info_req;
+}
+
+PPP_PROTOCOL_REGISTER(IPV6CP, PPP_IPV6CP,
+		      ipv6cp_init, ipv6cp_handle,
+		      ipv6cp_lower_up, ipv6cp_lower_down,
+		      ipv6cp_open, ipv6cp_close);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/lcp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/lcp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/lcp.c	(working copy)
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/net_mgmt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_stats.h"
+#include "ppp_internal.h"
+
+static enum net_verdict lcp_handle_ext(struct ppp_fsm *fsm,
+				       enum ppp_packet_type code, uint8_t id,
+				       struct net_pkt *pkt)
+{
+	enum net_verdict verdict = NET_DROP;
+
+	switch (code) {
+	case PPP_PROTOCOL_REJ:
+		NET_DBG("PPP Protocol-Rej");
+		return ppp_fsm_recv_protocol_rej(fsm, id, pkt);
+
+	case PPP_ECHO_REQ:
+		NET_DBG("PPP Echo-Req");
+		return ppp_fsm_recv_echo_req(fsm, id, pkt);
+
+	case PPP_ECHO_REPLY:
+		NET_DBG("PPP Echo-Reply");
+		return ppp_fsm_recv_echo_reply(fsm, id, pkt);
+
+	case PPP_DISCARD_REQ:
+		NET_DBG("PPP Discard-Req");
+		return ppp_fsm_recv_discard_req(fsm, id, pkt);
+
+	default:
+		break;
+	}
+
+	return verdict;
+}
+
+static enum net_verdict lcp_handle(struct ppp_context *ctx,
+				   struct net_if *iface,
+				   struct net_pkt *pkt)
+{
+	return ppp_fsm_input(&ctx->lcp.fsm, PPP_LCP, pkt);
+}
+
+struct lcp_option_data {
+	bool auth_proto_present;
+	uint16_t auth_proto;
+};
+
+static const enum ppp_protocol_type lcp_supported_auth_protos[] = {
+#if defined(CONFIG_NET_L2_PPP_PAP)
+	PPP_PAP,
+#endif
+};
+
+static int lcp_auth_proto_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
+				void *user_data)
+{
+	struct lcp_option_data *data = user_data;
+	int ret;
+	int i;
+
+	ret = net_pkt_read_be16(pkt, &data->auth_proto);
+	if (ret < 0) {
+		/* Should not happen, is the pkt corrupt? */
+		return -EMSGSIZE;
+	}
+
+	NET_DBG("[LCP] Received auth protocol %x (%s)",
+		(unsigned int) data->auth_proto,
+		ppp_proto2str(data->auth_proto));
+
+	for (i = 0; i < ARRAY_SIZE(lcp_supported_auth_protos); i++) {
+		if (data->auth_proto == lcp_supported_auth_protos[i]) {
+			data->auth_proto_present = true;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int lcp_auth_proto_nack(struct ppp_fsm *fsm, struct net_pkt *ret_pkt,
+			       void *user_data)
+{
+	(void)net_pkt_write_u8(ret_pkt, LCP_OPTION_AUTH_PROTO);
+	(void)net_pkt_write_u8(ret_pkt, 4);
+	return net_pkt_write_be16(ret_pkt, PPP_PAP);
+}
+
+static const struct ppp_peer_option_info lcp_peer_options[] = {
+	PPP_PEER_OPTION(LCP_OPTION_AUTH_PROTO, lcp_auth_proto_parse,
+			lcp_auth_proto_nack),
+};
+
+static int lcp_config_info_req(struct ppp_fsm *fsm,
+			       struct net_pkt *pkt,
+			       uint16_t length,
+			       struct net_pkt *ret_pkt)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+	struct lcp_option_data data = {
+		.auth_proto_present = false,
+	};
+	int ret;
+
+	ret = ppp_config_info_req(fsm, pkt, length, ret_pkt, PPP_LCP,
+				  lcp_peer_options,
+				  ARRAY_SIZE(lcp_peer_options),
+				  &data);
+	if (ret != PPP_CONFIGURE_ACK) {
+		/* There are some issues with configuration still */
+		return ret;
+	}
+
+	ctx->lcp.peer_options.auth_proto = data.auth_proto;
+
+	if (data.auth_proto_present) {
+		NET_DBG("Authentication protocol negotiated: %x (%s)",
+			(unsigned int) data.auth_proto,
+			ppp_proto2str(data.auth_proto));
+	}
+
+	return PPP_CONFIGURE_ACK;
+}
+
+static void lcp_lower_down(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_down(&ctx->lcp.fsm);
+}
+
+static void lcp_lower_up(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_up(&ctx->lcp.fsm);
+}
+
+static void lcp_open(struct ppp_context *ctx)
+{
+	ppp_fsm_open(&ctx->lcp.fsm);
+}
+
+static void lcp_close(struct ppp_context *ctx, const uint8_t *reason)
+{
+	if (ctx->phase != PPP_DEAD) {
+		ppp_change_phase(ctx, PPP_TERMINATE);
+	}
+
+	ppp_fsm_close(&ctx->lcp.fsm, reason);
+}
+
+static void lcp_down(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+
+	memset(&ctx->lcp.peer_options.auth_proto, 0,
+	       sizeof(ctx->lcp.peer_options.auth_proto));
+
+	ppp_link_down(ctx);
+
+	ppp_change_phase(ctx, PPP_ESTABLISH);
+}
+
+static void lcp_up(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+
+	/* TODO: Set MRU/MTU of the network interface here */
+
+	ppp_link_established(ctx, fsm);
+}
+
+static void lcp_starting(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+
+	ppp_link_needed(ctx);
+}
+
+static void lcp_finished(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       lcp.fsm);
+
+	ppp_link_terminated(ctx);
+}
+
+static void lcp_init(struct ppp_context *ctx)
+{
+	NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_LCP), PPP_LCP,
+		&ctx->lcp.fsm);
+
+	memset(&ctx->lcp.fsm, 0, sizeof(ctx->lcp.fsm));
+
+	ppp_fsm_init(&ctx->lcp.fsm, PPP_LCP);
+
+	ppp_fsm_name_set(&ctx->lcp.fsm, ppp_proto2str(PPP_LCP));
+
+	ctx->lcp.fsm.cb.up = lcp_up;
+	ctx->lcp.fsm.cb.down = lcp_down;
+	ctx->lcp.fsm.cb.starting = lcp_starting;
+	ctx->lcp.fsm.cb.finished = lcp_finished;
+	if (IS_ENABLED(CONFIG_NET_L2_PPP_AUTH_SUPPORT)) {
+		ctx->lcp.fsm.cb.config_info_req = lcp_config_info_req;
+	}
+	ctx->lcp.fsm.cb.proto_extension = lcp_handle_ext;
+}
+
+PPP_PROTOCOL_REGISTER(LCP, PPP_LCP,
+		      lcp_init, lcp_handle,
+		      lcp_lower_up, lcp_lower_down,
+		      lcp_open, lcp_close);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/link.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/link.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/link.c	(working copy)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+static void lcp_up(struct ppp_context *ctx)
+{
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol == PPP_LCP) {
+			continue;
+		}
+
+		if (proto->lower_up) {
+			proto->lower_up(ctx);
+		}
+	}
+}
+
+static void do_network(struct ppp_context *ctx)
+{
+	ppp_change_phase(ctx, PPP_NETWORK);
+
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP) {
+			if (proto->open) {
+				proto->open(ctx);
+			}
+		}
+	}
+
+	/* Do the other network protocols if encryption is not needed for
+	 * them.
+	 */
+	/* TODO possible encryption stuff here*/
+
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol == PPP_CCP || proto->protocol == PPP_ECP ||
+		    proto->protocol >= 0xC000) {
+			continue;
+		}
+
+		if (proto->open) {
+			ctx->network_protos_open++;
+			proto->open(ctx);
+		}
+	}
+
+	if (ctx->network_protos_open == 0) {
+		const struct ppp_protocol_handler *proto = ppp_lcp_get();
+
+		if (proto) {
+			proto->close(ctx, "No network protocols open");
+		}
+	}
+}
+
+static void do_auth(struct ppp_context *ctx)
+{
+	uint16_t auth_proto = 0;
+
+	ppp_change_phase(ctx, PPP_AUTH);
+
+	if (IS_ENABLED(CONFIG_NET_L2_PPP_AUTH_SUPPORT)) {
+		auth_proto = ctx->lcp.peer_options.auth_proto;
+	}
+
+	/* If no authentication is need, then we are done */
+	if (!auth_proto) {
+		ppp_link_authenticated(ctx);
+		return;
+	}
+
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol == auth_proto) {
+			if (proto->open) {
+				proto->open(ctx);
+			}
+
+			break;
+		}
+	}
+}
+
+void ppp_link_established(struct ppp_context *ctx, struct ppp_fsm *fsm)
+{
+	NET_DBG("[%p] Link established", ctx);
+
+	ppp_change_phase(ctx, PPP_ESTABLISH);
+
+	do_auth(ctx);
+
+	lcp_up(ctx);
+}
+
+void ppp_link_authenticated(struct ppp_context *ctx)
+{
+	NET_DBG("[%p] Link authenticated", ctx);
+
+	do_network(ctx);
+}
+
+void ppp_link_terminated(struct ppp_context *ctx)
+{
+	if (ctx->phase == PPP_DEAD) {
+		return;
+	}
+
+	/* TODO: cleanup things etc here if needed */
+
+	ppp_change_phase(ctx, PPP_DEAD);
+
+	NET_DBG("[%p] Link terminated", ctx);
+}
+
+void ppp_link_down(struct ppp_context *ctx)
+{
+	if (ctx->phase == PPP_DEAD) {
+		return;
+	}
+
+	ppp_network_all_down(ctx);
+
+	ppp_change_phase(ctx, PPP_DEAD);
+}
+
+void ppp_link_needed(struct ppp_context *ctx)
+{
+	/* TODO: Try to create link if needed. */
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/misc.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/misc.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/misc.c	(working copy)
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+const char *ppp_phase_str(enum ppp_phase phase)
+{
+#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
+	switch (phase) {
+	case PPP_DEAD:
+		return "DEAD";
+	case PPP_ESTABLISH:
+		return "ESTABLISH";
+	case PPP_AUTH:
+		return "AUTH";
+	case PPP_NETWORK:
+		return "NETWORK";
+	case PPP_RUNNING:
+		return "RUNNING";
+	case PPP_TERMINATE:
+		return "TERMINATE";
+	}
+#else
+	ARG_UNUSED(phase);
+#endif
+
+	return "";
+}
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+static void validate_phase_transition(enum ppp_phase current,
+				      enum ppp_phase new)
+{
+	static const uint8_t valid_transitions[] = {
+		[PPP_DEAD] = 1 << PPP_ESTABLISH,
+		[PPP_ESTABLISH] = 1 << PPP_DEAD |
+				1 << PPP_AUTH |
+				1 << PPP_TERMINATE,
+		[PPP_AUTH] = 1 << PPP_TERMINATE |
+				1 << PPP_NETWORK,
+		[PPP_NETWORK] = 1 << PPP_TERMINATE |
+				1 << PPP_RUNNING,
+		[PPP_RUNNING] = 1 << PPP_TERMINATE |
+				1 << PPP_NETWORK,
+		[PPP_TERMINATE] = 1 << PPP_DEAD,
+	};
+
+	if (!(valid_transitions[current] & 1 << new)) {
+		NET_DBG("Invalid phase transition: %s (%d) => %s (%d)",
+			ppp_phase_str(current), current,
+			ppp_phase_str(new), new);
+	}
+}
+#else
+static inline void validate_phase_transition(enum ppp_phase current,
+					     enum ppp_phase new)
+{
+	ARG_UNUSED(current);
+	ARG_UNUSED(new);
+}
+#endif
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+void ppp_change_phase_debug(struct ppp_context *ctx, enum ppp_phase new_phase,
+			    const char *caller, int line)
+#else
+void ppp_change_phase(struct ppp_context *ctx, enum ppp_phase new_phase)
+#endif
+{
+	NET_ASSERT(ctx);
+
+	if (ctx->phase == new_phase) {
+		return;
+	}
+
+	NET_ASSERT(new_phase >= PPP_DEAD &&
+		   new_phase <= PPP_TERMINATE);
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("[%p] phase %s (%d) => %s (%d) (%s():%d)",
+		ctx, ppp_phase_str(ctx->phase), ctx->phase,
+		ppp_phase_str(new_phase), new_phase, caller, line);
+#endif
+
+	validate_phase_transition(ctx->phase, new_phase);
+
+	ctx->phase = new_phase;
+}
+
+const char *ppp_state_str(enum ppp_state state)
+{
+#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
+	switch (state) {
+	case PPP_INITIAL:
+		return "INITIAL";
+	case PPP_STARTING:
+		return "STARTING";
+	case PPP_CLOSED:
+		return "CLOSED";
+	case PPP_STOPPED:
+		return "STOPPED";
+	case PPP_CLOSING:
+		return "CLOSING";
+	case PPP_STOPPING:
+		return "STOPPING";
+	case PPP_REQUEST_SENT:
+		return "REQUEST_SENT";
+	case PPP_ACK_RECEIVED:
+		return "ACK_RECEIVED";
+	case PPP_ACK_SENT:
+		return "ACK_SENT";
+	case PPP_OPENED:
+		return "OPENED";
+	}
+#else
+	ARG_UNUSED(state);
+#endif
+
+	return "";
+}
+
+const char *ppp_pkt_type2str(enum ppp_packet_type type)
+{
+#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
+	switch (type) {
+	case PPP_CONFIGURE_REQ:
+		return "Configure-Req";
+	case PPP_CONFIGURE_ACK:
+		return "Configure-Ack";
+	case PPP_CONFIGURE_NACK:
+		return "Configure-Nack";
+	case PPP_CONFIGURE_REJ:
+		return "Configure-Rej";
+	case PPP_TERMINATE_REQ:
+		return "Terminate-Req";
+	case PPP_TERMINATE_ACK:
+		return "Terminate-Ack";
+	case PPP_CODE_REJ:
+		return "Code-Rej";
+	case PPP_PROTOCOL_REJ:
+		return "Protocol-Rej";
+	case PPP_ECHO_REQ:
+		return "Echo-Req";
+	case PPP_ECHO_REPLY:
+		return "Echo-Reply";
+	case PPP_DISCARD_REQ:
+		return "Discard-Req";
+	}
+#else
+	ARG_UNUSED(type);
+#endif
+
+	return "";
+}
+
+const char *ppp_proto2str(uint16_t proto)
+{
+#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG)
+	switch (proto) {
+	case PPP_IP:
+		return "IPv4";
+	case PPP_IPV6:
+		return "IPv6";
+	case PPP_ECP:
+		return "ECP";
+	case PPP_CCP:
+		return "CCP";
+	case PPP_LCP:
+		return "LCP";
+	case PPP_IPCP:
+		return "IPCP";
+	case PPP_IPV6CP:
+		return "IPV6CP";
+	case PPP_PAP:
+		return "PAP";
+	case PPP_CHAP:
+		return "CHAP";
+	case PPP_EAP:
+		return "EAP";
+	}
+#else
+	ARG_UNUSED(proto);
+#endif
+
+	return "";
+}
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+static void validate_state_transition(enum ppp_state current,
+				      enum ppp_state new)
+{
+	/* See RFC 1661 ch. 4.1 */
+	static const uint16_t valid_transitions[] = {
+		[PPP_INITIAL] = 1 << PPP_CLOSED |
+				1 << PPP_STARTING,
+		[PPP_STARTING] = 1 << PPP_INITIAL |
+				1 << PPP_REQUEST_SENT,
+		[PPP_CLOSED] = 1 << PPP_INITIAL |
+				1 << PPP_REQUEST_SENT,
+		[PPP_STOPPED] = 1 << PPP_STARTING |
+				1 << PPP_CLOSED |
+				1 << PPP_ACK_RECEIVED |
+				1 << PPP_REQUEST_SENT,
+		[PPP_CLOSING] = 1 << PPP_INITIAL |
+				1 << PPP_STOPPING |
+				1 << PPP_CLOSED,
+		[PPP_STOPPING] = 1 << PPP_STARTING |
+				1 << PPP_CLOSING |
+				1 << PPP_STOPPED,
+		[PPP_REQUEST_SENT] = 1 << PPP_STARTING |
+				1 << PPP_CLOSING |
+				1 << PPP_STOPPED |
+				1 << PPP_ACK_SENT |
+				1 << PPP_ACK_RECEIVED,
+		[PPP_ACK_RECEIVED] = 1 << PPP_STARTING |
+				1 << PPP_CLOSING |
+				1 << PPP_OPENED |
+				1 << PPP_REQUEST_SENT |
+				1 << PPP_STOPPED,
+		[PPP_ACK_SENT] = 1 << PPP_STARTING |
+				1 << PPP_CLOSING |
+				1 << PPP_STOPPED |
+				1 << PPP_REQUEST_SENT |
+				1 << PPP_OPENED,
+		[PPP_OPENED] = 1 << PPP_STARTING |
+				1 << PPP_CLOSING |
+				1 << PPP_ACK_SENT |
+				1 << PPP_REQUEST_SENT |
+				1 << PPP_CLOSING |
+				1 << PPP_STOPPING,
+	};
+
+	if (!(valid_transitions[current] & 1 << new)) {
+		NET_DBG("Invalid state transition: %s (%d) => %s (%d)",
+			ppp_state_str(current), current,
+			ppp_state_str(new), new);
+	}
+}
+#else
+static inline void validate_state_transition(enum ppp_state current,
+					     enum ppp_state new)
+{
+	ARG_UNUSED(current);
+	ARG_UNUSED(new);
+}
+#endif
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+void ppp_change_state_debug(struct ppp_fsm *fsm, enum ppp_state new_state,
+			    const char *caller, int line)
+#else
+void ppp_change_state(struct ppp_fsm *fsm, enum ppp_state new_state)
+#endif
+{
+	NET_ASSERT(fsm);
+
+	if (fsm->state == new_state) {
+		return;
+	}
+
+	NET_ASSERT(new_state >= PPP_INITIAL &&
+		   new_state <= PPP_OPENED);
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+	NET_DBG("[%s/%p] state %s (%d) => %s (%d) (%s():%d)",
+		fsm->name, fsm, ppp_state_str(fsm->state), fsm->state,
+		ppp_state_str(new_state), new_state, caller, line);
+#endif
+
+	validate_state_transition(fsm->state, new_state);
+
+	fsm->state = new_state;
+}
+
+const char *ppp_option2str(enum ppp_protocol_type protocol,
+			   int type)
+{
+#if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL)
+	switch (protocol) {
+	case PPP_LCP:
+		switch (type) {
+		case LCP_OPTION_RESERVED:
+			return "RESERVED";
+		case LCP_OPTION_MRU:
+			return "MRU";
+		case LCP_OPTION_ASYNC_CTRL_CHAR_MAP:
+			return "ASYNC_CTRL_CHAR_MAP";
+		case LCP_OPTION_AUTH_PROTO:
+			return "AUTH_PROTO";
+		case LCP_OPTION_QUALITY_PROTO:
+			return "QUALITY_PROTO";
+		case LCP_OPTION_MAGIC_NUMBER:
+			return "MAGIC_NUMBER";
+		case LCP_OPTION_PROTO_COMPRESS:
+			return "PROTO_COMPRESS";
+		case LCP_OPTION_ADDR_CTRL_COMPRESS:
+			return "ADDR_CTRL_COMPRESS";
+		}
+
+		break;
+
+#if defined(CONFIG_NET_IPV4)
+	case PPP_IPCP:
+		switch (type) {
+		case IPCP_OPTION_RESERVED:
+			return "RESERVED";
+		case IPCP_OPTION_IP_ADDRESSES:
+			return "IP_ADDRESSES";
+		case IPCP_OPTION_IP_COMP_PROTO:
+			return "IP_COMPRESSION_PROTOCOL";
+		case IPCP_OPTION_IP_ADDRESS:
+			return "IP_ADDRESS";
+		case IPCP_OPTION_DNS1:
+			return "DNS1";
+		case IPCP_OPTION_NBNS1:
+			return "NBNS1";
+		case IPCP_OPTION_DNS2:
+			return "DNS2";
+		case IPCP_OPTION_NBNS2:
+			return "NBNS2";
+		}
+
+		break;
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+	case PPP_IPV6CP:
+		switch (type) {
+		case IPV6CP_OPTION_RESERVED:
+			return "RESERVED";
+		case IPV6CP_OPTION_INTERFACE_IDENTIFIER:
+			return "INTERFACE_IDENTIFIER";
+		}
+
+		break;
+#endif
+
+	default:
+		break;
+	}
+#else
+	ARG_UNUSED(type);
+#endif
+
+	return "";
+}
+
+void ppp_fsm_name_set(struct ppp_fsm *fsm, const char *name)
+{
+#if CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG
+	fsm->name = name;
+#else
+	ARG_UNUSED(fsm);
+	ARG_UNUSED(name);
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/network.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/network.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/network.c	(working copy)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+void ppp_network_up(struct ppp_context *ctx, int proto)
+{
+	if (ctx->network_protos_up == 0) {
+		ppp_change_phase(ctx, PPP_RUNNING);
+	}
+
+	ctx->network_protos_up++;
+
+	NET_DBG("[%p] Proto %s (0x%04x) %s (%d)", ctx, ppp_proto2str(proto),
+		proto, "up", ctx->network_protos_up);
+}
+
+void ppp_network_down(struct ppp_context *ctx, int proto)
+{
+	ctx->network_protos_up--;
+
+	if (ctx->network_protos_up <= 0) {
+		ctx->network_protos_up = 0;
+		ppp_change_phase(ctx, PPP_TERMINATE);
+	}
+
+	NET_DBG("[%p] Proto %s (0x%04x) %s (%d)", ctx, ppp_proto2str(proto),
+		proto, "down", ctx->network_protos_up);
+}
+
+void ppp_network_done(struct ppp_context *ctx, int proto)
+{
+	ctx->network_protos_up--;
+	if (ctx->network_protos_up <= 0) {
+		const struct ppp_protocol_handler *proto = ppp_lcp_get();
+
+		if (proto) {
+			proto->close(ctx, "All networks down");
+		}
+	}
+}
+
+void ppp_network_all_down(struct ppp_context *ctx)
+{
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol != PPP_LCP && proto->lower_down) {
+			proto->lower_down(ctx);
+		}
+
+		if (proto->protocol < 0xC000 && proto->close) {
+			ctx->network_protos_open--;
+			proto->close(ctx, "LCP down");
+		}
+	}
+
+	if (ctx->network_protos_open > 0) {
+		NET_WARN("Not all network protocols were closed (%d)",
+			 ctx->network_protos_open);
+	}
+
+	ctx->network_protos_open = 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/options.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/options.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/options.c	(working copy)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_core.h>
+#include <net/net_pkt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_internal.h"
+
+#define ALLOC_TIMEOUT K_MSEC(100)
+
+int ppp_parse_options(struct ppp_fsm *fsm, struct net_pkt *pkt,
+		      uint16_t length,
+		      int (*parse)(struct net_pkt *pkt, uint8_t code,
+				   uint8_t len, void *user_data),
+		      void *user_data)
+{
+	int remaining = length, pkt_remaining;
+	uint8_t opt_type, opt_len, opt_val_len;
+	int ret;
+	struct net_pkt_cursor cursor;
+
+	pkt_remaining = net_pkt_remaining_data(pkt);
+	if (remaining != pkt_remaining) {
+		NET_DBG("Expecting %d but pkt data length is %d bytes",
+			remaining, pkt_remaining);
+		return -EMSGSIZE;
+	}
+
+	while (remaining > 0) {
+		ret = net_pkt_read_u8(pkt, &opt_type);
+		if (ret < 0) {
+			NET_DBG("Cannot read %s (%d) (remaining len %d)",
+				"opt_type", ret, pkt_remaining);
+			return -EBADMSG;
+		}
+
+		ret = net_pkt_read_u8(pkt, &opt_len);
+		if (ret < 0) {
+			NET_DBG("Cannot read %s (%d) (remaining len %d)",
+				"opt_len", ret, remaining);
+			return -EBADMSG;
+		}
+
+		opt_val_len = opt_len - sizeof(opt_type) - sizeof(opt_len);
+
+		net_pkt_cursor_backup(pkt, &cursor);
+
+		NET_DBG("[%s/%p] option %s (%d) len %d", fsm->name, fsm,
+			ppp_option2str(fsm->protocol, opt_type), opt_type,
+			opt_len);
+
+		ret = parse(pkt, opt_type, opt_val_len, user_data);
+		if (ret < 0) {
+			return ret;
+		}
+
+		net_pkt_cursor_restore(pkt, &cursor);
+
+		net_pkt_skip(pkt, opt_val_len);
+		remaining -= opt_len;
+	}
+
+	if (remaining < 0) {
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+static const struct ppp_peer_option_info *
+ppp_peer_option_info_get(const struct ppp_peer_option_info *options,
+			 size_t num_options,
+			 uint8_t code)
+{
+	size_t i;
+
+	for (i = 0; i < num_options; i++) {
+		if (options[i].code == code) {
+			return &options[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct ppp_parse_option_conf_req_data {
+	struct ppp_fsm *fsm;
+	struct net_pkt *ret_pkt;
+	enum ppp_protocol_type protocol;
+	const struct ppp_peer_option_info *options_info;
+	size_t num_options_info;
+	void *user_data;
+
+	int nack_count;
+	int rej_count;
+};
+
+static int ppp_parse_option_conf_req_unsupported(struct net_pkt *pkt,
+						 uint8_t code, uint8_t len,
+						 void *user_data)
+{
+	struct ppp_parse_option_conf_req_data *parse_data = user_data;
+	struct ppp_fsm *fsm = parse_data->fsm;
+	struct net_pkt *ret_pkt = parse_data->ret_pkt;
+	const struct ppp_peer_option_info *option_info =
+		ppp_peer_option_info_get(parse_data->options_info,
+					 parse_data->num_options_info,
+					 code);
+
+	NET_DBG("[%s/%p] %s option %s (%d) len %d",
+		fsm->name, fsm, "Check",
+		ppp_option2str(parse_data->protocol, code),
+		code, len);
+
+	if (option_info) {
+		return 0;
+	}
+
+	parse_data->rej_count++;
+
+	net_pkt_write_u8(ret_pkt, code);
+	net_pkt_write_u8(ret_pkt, len + sizeof(code) + sizeof(len));
+
+	if (len > 0) {
+		net_pkt_copy(ret_pkt, pkt, len);
+	}
+
+	return 0;
+}
+
+static int ppp_parse_option_conf_req_supported(struct net_pkt *pkt,
+					       uint8_t code, uint8_t len,
+					       void *user_data)
+{
+	struct ppp_parse_option_conf_req_data *parse_data = user_data;
+	struct ppp_fsm *fsm = parse_data->fsm;
+	const struct ppp_peer_option_info *option_info =
+		ppp_peer_option_info_get(parse_data->options_info,
+					 parse_data->num_options_info,
+					 code);
+	int ret;
+
+	ret = option_info->parse(fsm, pkt, parse_data->user_data);
+	if (ret == -EINVAL) {
+		parse_data->nack_count++;
+		ret = option_info->nack(fsm, parse_data->ret_pkt,
+					parse_data->user_data);
+	}
+
+	return ret;
+}
+
+int ppp_config_info_req(struct ppp_fsm *fsm,
+			struct net_pkt *pkt,
+			uint16_t length,
+			struct net_pkt *ret_pkt,
+			enum ppp_protocol_type protocol,
+			const struct ppp_peer_option_info *options_info,
+			size_t num_options_info,
+			void *user_data)
+{
+	struct ppp_parse_option_conf_req_data parse_data = {
+		.fsm = fsm,
+		.ret_pkt = ret_pkt,
+		.protocol = protocol,
+		.options_info = options_info,
+		.num_options_info = num_options_info,
+		.user_data = user_data,
+	};
+	struct net_pkt_cursor cursor;
+	int ret;
+
+	net_pkt_cursor_backup(pkt, &cursor);
+
+	ret = ppp_parse_options(fsm, pkt, length,
+				ppp_parse_option_conf_req_unsupported,
+				&parse_data);
+	if (ret < 0) {
+		return -EINVAL;
+	}
+
+	if (parse_data.rej_count) {
+		return PPP_CONFIGURE_REJ;
+	}
+
+	net_pkt_cursor_restore(pkt, &cursor);
+
+	ret = ppp_parse_options(fsm, pkt, length,
+				ppp_parse_option_conf_req_supported,
+				&parse_data);
+	if (ret < 0) {
+		return -EINVAL;
+	}
+
+	if (parse_data.nack_count) {
+		return PPP_CONFIGURE_NACK;
+	}
+
+	net_pkt_cursor_restore(pkt, &cursor);
+	net_pkt_copy(ret_pkt, pkt, length);
+
+	return PPP_CONFIGURE_ACK;
+}
+
+struct net_pkt *ppp_my_options_add(struct ppp_fsm *fsm, size_t packet_len)
+{
+	struct ppp_context *ctx = ppp_fsm_ctx(fsm);
+	const struct ppp_my_option_info *info;
+	struct ppp_my_option_data *data;
+	struct net_pkt *pkt;
+	size_t i;
+	int err;
+
+	pkt = net_pkt_alloc_with_buffer(ppp_fsm_iface(fsm), packet_len,
+					AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
+	if (!pkt) {
+		return NULL;
+	}
+
+	for (i = 0; i < fsm->my_options.count; i++) {
+		info = &fsm->my_options.info[i];
+		data = &fsm->my_options.data[i];
+
+		if (data->flags & PPP_MY_OPTION_REJECTED) {
+			continue;
+		}
+
+		err = net_pkt_write_u8(pkt, info->code);
+		if (err) {
+			goto unref_pkt;
+		}
+
+		err = info->conf_req_add(ctx, pkt);
+		if (err) {
+			goto unref_pkt;
+		}
+	}
+
+	return pkt;
+
+unref_pkt:
+	net_pkt_unref(pkt);
+
+	return NULL;
+}
+
+typedef int (*ppp_my_option_handle_t)(struct ppp_context *ctx,
+				      struct net_pkt *pkt, uint8_t len,
+				      const struct ppp_my_option_info *info,
+				      struct ppp_my_option_data *data);
+
+struct ppp_my_option_handle_data {
+	struct ppp_fsm *fsm;
+	ppp_my_option_handle_t handle;
+};
+
+static int ppp_my_option_get(struct ppp_fsm *fsm, uint8_t code,
+			     const struct ppp_my_option_info **info,
+			     struct ppp_my_option_data **data)
+{
+	int i;
+
+	for (i = 0; i < fsm->my_options.count; i++) {
+		if (fsm->my_options.info[i].code == code) {
+			*info = &fsm->my_options.info[i];
+			*data = &fsm->my_options.data[i];
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int ppp_my_option_parse(struct net_pkt *pkt, uint8_t code,
+			       uint8_t len, void *user_data)
+{
+	struct ppp_my_option_handle_data *d = user_data;
+	struct ppp_context *ctx = ppp_fsm_ctx(d->fsm);
+	const struct ppp_my_option_info *info;
+	struct ppp_my_option_data *data;
+	int ret;
+
+	ret = ppp_my_option_get(d->fsm, code, &info, &data);
+	if (ret < 0) {
+		return 0;
+	}
+
+	return d->handle(ctx, pkt, len, info, data);
+}
+
+static int ppp_my_options_parse(struct ppp_fsm *fsm,
+				struct net_pkt *pkt,
+				uint16_t length,
+				ppp_my_option_handle_t handle)
+{
+	struct ppp_my_option_handle_data parse_data = {
+		.fsm = fsm,
+		.handle = handle,
+	};
+
+	return ppp_parse_options(fsm, pkt, length, ppp_my_option_parse,
+				 &parse_data);
+}
+
+static int ppp_my_option_parse_conf_ack(struct ppp_context *ctx,
+					struct net_pkt *pkt, uint8_t len,
+					const struct ppp_my_option_info *info,
+					struct ppp_my_option_data *data)
+{
+	data->flags |= PPP_MY_OPTION_ACKED;
+
+	if (info->conf_ack_handle) {
+		return info->conf_ack_handle(ctx, pkt, len);
+	}
+
+	return 0;
+}
+
+int ppp_my_options_parse_conf_ack(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length)
+{
+	return ppp_my_options_parse(fsm, pkt, length,
+				    ppp_my_option_parse_conf_ack);
+}
+
+static int ppp_my_option_parse_conf_nak(struct ppp_context *ctx,
+					struct net_pkt *pkt, uint8_t len,
+					const struct ppp_my_option_info *info,
+					struct ppp_my_option_data *data)
+{
+	return info->conf_nak_handle(ctx, pkt, len);
+}
+
+int ppp_my_options_parse_conf_nak(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length)
+{
+	return ppp_my_options_parse(fsm, pkt, length,
+				    ppp_my_option_parse_conf_nak);
+}
+
+static int ppp_my_option_parse_conf_rej(struct ppp_context *ctx,
+					struct net_pkt *pkt, uint8_t len,
+					const struct ppp_my_option_info *info,
+					struct ppp_my_option_data *data)
+{
+	data->flags |= PPP_MY_OPTION_REJECTED;
+
+	return 0;
+}
+
+int ppp_my_options_parse_conf_rej(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length)
+{
+	return ppp_my_options_parse(fsm, pkt, length,
+				    ppp_my_option_parse_conf_rej);
+}
+
+uint32_t ppp_my_option_flags(struct ppp_fsm *fsm, uint8_t code)
+{
+	const struct ppp_my_option_info *info;
+	struct ppp_my_option_data *data;
+	int ret;
+
+	ret = ppp_my_option_get(fsm, code, &info, &data);
+	if (ret) {
+		return false;
+	}
+
+	return data->flags;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/pap.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/pap.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/pap.c	(working copy)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2019-2020 Grinn
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <net/net_pkt.h>
+
+#include "ppp_internal.h"
+
+static enum net_verdict pap_handle(struct ppp_context *ctx,
+				   struct net_if *iface,
+				   struct net_pkt *pkt)
+{
+	return ppp_fsm_input(&ctx->pap.fsm, PPP_PAP, pkt);
+}
+
+static struct net_pkt *pap_config_info_add(struct ppp_fsm *fsm)
+{
+	uint8_t payload[] = { 5, 'b', 'l', 'a', 'n', 'k',
+			      5, 'b', 'l', 'a', 'n', 'k' };
+	struct net_pkt *pkt;
+
+	pkt = net_pkt_alloc_with_buffer(ppp_fsm_iface(fsm), sizeof(payload),
+					AF_UNSPEC, 0, PPP_BUF_ALLOC_TIMEOUT);
+	if (!pkt) {
+		return NULL;
+	}
+
+	(void)net_pkt_write(pkt, payload, sizeof(payload));
+
+	return pkt;
+}
+
+static int pap_config_info_ack(struct ppp_fsm *fsm,
+			       struct net_pkt *pkt,
+			       uint16_t length)
+{
+	/*
+	 * We only support one way negotiation for now, so move to ACK_SENT
+	 * phase right away.
+	 */
+	if (fsm->state == PPP_REQUEST_SENT) {
+		ppp_change_state(fsm, PPP_ACK_SENT);
+	}
+
+	return 0;
+}
+
+static void pap_lower_down(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_down(&ctx->pap.fsm);
+}
+
+static void pap_lower_up(struct ppp_context *ctx)
+{
+	ppp_fsm_lower_up(&ctx->pap.fsm);
+}
+
+static void pap_open(struct ppp_context *ctx)
+{
+	ppp_fsm_open(&ctx->pap.fsm);
+}
+
+static void pap_close(struct ppp_context *ctx, const uint8_t *reason)
+{
+	ppp_fsm_close(&ctx->pap.fsm, reason);
+}
+
+static void pap_up(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       pap.fsm);
+
+	if (ctx->is_pap_up) {
+		return;
+	}
+
+	ctx->is_pap_up = true;
+
+	NET_DBG("[%s/%p] Current state %s (%d)", fsm->name, fsm,
+		ppp_state_str(fsm->state), fsm->state);
+
+	ppp_link_authenticated(ctx);
+}
+
+static void pap_down(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       pap.fsm);
+
+	if (!ctx->is_pap_up) {
+		return;
+	}
+
+	ctx->is_pap_up = false;
+}
+
+static void pap_finished(struct ppp_fsm *fsm)
+{
+	struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context,
+					       pap.fsm);
+
+	if (!ctx->is_pap_open) {
+		return;
+	}
+
+	ctx->is_pap_open = false;
+}
+
+static void pap_proto_reject(struct ppp_fsm *fsm)
+{
+	ppp_fsm_lower_down(fsm);
+}
+
+static void pap_init(struct ppp_context *ctx)
+{
+	NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_PAP), PPP_PAP,
+		&ctx->pap.fsm);
+
+	memset(&ctx->pap.fsm, 0, sizeof(ctx->pap.fsm));
+
+	ppp_fsm_init(&ctx->pap.fsm, PPP_PAP);
+
+	ppp_fsm_name_set(&ctx->pap.fsm, ppp_proto2str(PPP_PAP));
+
+	ctx->pap.fsm.cb.up = pap_up;
+	ctx->pap.fsm.cb.down = pap_down;
+	ctx->pap.fsm.cb.finished = pap_finished;
+	ctx->pap.fsm.cb.proto_reject = pap_proto_reject;
+	ctx->pap.fsm.cb.config_info_add = pap_config_info_add;
+	ctx->pap.fsm.cb.config_info_ack = pap_config_info_ack;
+}
+
+PPP_PROTOCOL_REGISTER(PAP, PPP_PAP,
+		      pap_init, pap_handle,
+		      pap_lower_up, pap_lower_down,
+		      pap_open, pap_close);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_internal.h	(working copy)
@@ -0,0 +1,213 @@
+/** @file
+ @brief PPP private header
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <net/ppp.h>
+
+/**
+ * FSM flags that control how it operates.
+ */
+#define FSM_RESTART    BIT(0) /**< Treat 2nd OPEN as DOWN followed by UP    */
+
+/**
+ * PPP packet format.
+ */
+struct ppp_packet {
+	uint8_t code;
+	uint8_t id;
+	uint16_t length;
+} __packed;
+
+/** Max Terminate-Request transmissions */
+#define MAX_TERMINATE_REQ  CONFIG_NET_L2_PPP_MAX_TERMINATE_REQ_RETRANSMITS
+
+/** Max Configure-Request transmissions */
+#define MAX_CONFIGURE_REQ CONFIG_NET_L2_PPP_MAX_CONFIGURE_REQ_RETRANSMITS
+
+#define PPP_BUF_ALLOC_TIMEOUT	K_MSEC(100)
+
+/** Protocol handler information. */
+struct ppp_protocol_handler {
+	/** Protocol init function */
+	void (*init)(struct ppp_context *ctx);
+
+	/** Process a received packet */
+	enum net_verdict (*handler)(struct ppp_context *ctx,
+				    struct net_if *iface,
+				    struct net_pkt *pkt);
+
+	/** Lower layer up */
+	void (*lower_up)(struct ppp_context *ctx);
+
+	/** Lower layer down */
+	void (*lower_down)(struct ppp_context *ctx);
+
+	/** Enable this protocol */
+	void (*open)(struct ppp_context *ctx);
+
+	/** Disable this protocol */
+	void (*close)(struct ppp_context *ctx, const uint8_t *reason);
+
+	/** PPP protocol number */
+	uint16_t protocol;
+};
+
+struct ppp_peer_option_info {
+	uint8_t code;
+	int (*parse)(struct ppp_fsm *fsm, struct net_pkt *pkt,
+		     void *user_data);
+	int (*nack)(struct ppp_fsm *fsm, struct net_pkt *ret_pkt,
+		    void *user_data);
+};
+
+#define PPP_PEER_OPTION(_code, _parse, _nack)	\
+	{					\
+		.code = _code,			\
+		.parse = _parse,		\
+		.nack = _nack,			\
+	}
+
+int ppp_config_info_req(struct ppp_fsm *fsm,
+			struct net_pkt *pkt,
+			uint16_t length,
+			struct net_pkt *ret_pkt,
+			enum ppp_protocol_type protocol,
+			const struct ppp_peer_option_info *options_info,
+			size_t num_options_info,
+			void *user_data);
+
+#define PPP_PROTO_GET_NAME(proto_name)		\
+	(ppp_protocol_handler_##proto_name)
+
+#define PPP_PROTOCOL_REGISTER(name, proto, init_func, proto_handler,	\
+			      proto_lower_up, proto_lower_down,		\
+			      proto_open, proto_close)			\
+	static const Z_STRUCT_SECTION_ITERABLE(ppp_protocol_handler,	\
+					PPP_PROTO_GET_NAME(name)) = {	\
+		.protocol = proto,					\
+		.init = init_func,					\
+		.handler = proto_handler,				\
+		.lower_up = proto_lower_up,				\
+		.lower_down = proto_lower_down,				\
+		.open = proto_open,					\
+		.close = proto_close,					\
+	}
+
+const char *ppp_phase_str(enum ppp_phase phase);
+const char *ppp_state_str(enum ppp_state state);
+const char *ppp_proto2str(uint16_t proto);
+const char *ppp_pkt_type2str(enum ppp_packet_type type);
+const char *ppp_option2str(enum ppp_protocol_type protocol, int type);
+void ppp_fsm_name_set(struct ppp_fsm *fsm, const char *name);
+
+#if CONFIG_NET_L2_PPP_LOG_LEVEL < LOG_LEVEL_DBG
+void ppp_change_phase(struct ppp_context *ctx, enum ppp_phase new_phase);
+void ppp_change_state(struct ppp_fsm *fsm, enum ppp_state new_state);
+#else
+void ppp_change_phase_debug(struct ppp_context *ctx,
+			    enum ppp_phase new_phase,
+			    const char *caller, int line);
+
+#define ppp_change_phase(ctx, state)				\
+	ppp_change_phase_debug(ctx, state, __func__, __LINE__)
+
+#define ppp_change_state(fsm, state)				\
+	ppp_change_state_debug(fsm, state, __func__, __LINE__)
+
+void ppp_change_state_debug(struct ppp_fsm *fsm, enum ppp_state new_state,
+			    const char *caller, int line);
+#endif
+
+struct ppp_context *ppp_fsm_ctx(struct ppp_fsm *fsm);
+struct net_if *ppp_fsm_iface(struct ppp_fsm *fsm);
+int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
+		 enum ppp_packet_type type, uint8_t id,
+		 void *data, uint32_t data_len);
+void ppp_send_proto_rej(struct net_if *iface, struct net_pkt *pkt,
+			uint16_t protocol);
+
+void ppp_fsm_init(struct ppp_fsm *fsm, uint16_t protocol);
+void ppp_fsm_lower_up(struct ppp_fsm *fsm);
+void ppp_fsm_lower_down(struct ppp_fsm *fsm);
+void ppp_fsm_open(struct ppp_fsm *fsm);
+void ppp_fsm_close(struct ppp_fsm *fsm, const uint8_t *reason);
+void ppp_fsm_proto_reject(struct ppp_fsm *fsm);
+enum net_verdict ppp_fsm_input(struct ppp_fsm *fsm, uint16_t proto,
+			       struct net_pkt *pkt);
+enum net_verdict ppp_fsm_recv_protocol_rej(struct ppp_fsm *fsm,
+					   uint8_t id,
+					   struct net_pkt *pkt);
+enum net_verdict ppp_fsm_recv_echo_req(struct ppp_fsm *fsm,
+				       uint8_t id,
+				       struct net_pkt *pkt);
+enum net_verdict ppp_fsm_recv_echo_reply(struct ppp_fsm *fsm,
+					 uint8_t id,
+					 struct net_pkt *pkt);
+enum net_verdict ppp_fsm_recv_discard_req(struct ppp_fsm *fsm,
+					  uint8_t id,
+					  struct net_pkt *pkt);
+
+const struct ppp_protocol_handler *ppp_lcp_get(void);
+int ppp_parse_options(struct ppp_fsm *fsm, struct net_pkt *pkt,
+		      uint16_t length,
+		      int (*parse)(struct net_pkt *pkt, uint8_t code,
+				   uint8_t len, void *user_data),
+		      void *user_data);
+
+void ppp_link_established(struct ppp_context *ctx, struct ppp_fsm *fsm);
+void ppp_link_authenticated(struct ppp_context *ctx);
+void ppp_link_terminated(struct ppp_context *ctx);
+void ppp_link_down(struct ppp_context *ctx);
+void ppp_link_needed(struct ppp_context *ctx);
+
+void ppp_network_up(struct ppp_context *ctx, int proto);
+void ppp_network_down(struct ppp_context *ctx, int proto);
+void ppp_network_done(struct ppp_context *ctx, int proto);
+void ppp_network_all_down(struct ppp_context *ctx);
+
+struct ppp_my_option_info {
+	uint8_t code;
+	int (*conf_req_add)(struct ppp_context *ctx, struct net_pkt *pkt);
+	int (*conf_ack_handle)(struct ppp_context *ctx, struct net_pkt *pkt,
+			       uint8_t oplen);
+	int (*conf_nak_handle)(struct ppp_context *ctx, struct net_pkt *pkt,
+			       uint8_t oplen);
+};
+
+#define PPP_MY_OPTION(_code, _req_add, _handle_ack, _handle_nak)	\
+	{								\
+		.code = _code,						\
+		.conf_req_add = _req_add,				\
+		.conf_ack_handle = _handle_ack,				\
+		.conf_nak_handle = _handle_nak,				\
+	}
+
+struct net_pkt *ppp_my_options_add(struct ppp_fsm *fsm, size_t packet_len);
+
+int ppp_my_options_parse_conf_ack(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length);
+
+int ppp_my_options_parse_conf_nak(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length);
+
+int ppp_my_options_parse_conf_rej(struct ppp_fsm *fsm,
+				  struct net_pkt *pkt,
+				  uint16_t length);
+
+uint32_t ppp_my_option_flags(struct ppp_fsm *fsm, uint8_t code);
+
+static inline bool ppp_my_option_is_acked(struct ppp_fsm *fsm,
+					  uint8_t code)
+{
+	return ppp_my_option_flags(fsm, code) & PPP_MY_OPTION_ACKED;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_l2.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_l2.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_l2.c	(working copy)
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2019 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <stdlib.h>
+#include <net/net_core.h>
+#include <net/net_l2.h>
+#include <net/net_if.h>
+#include <net/net_pkt.h>
+#include <net/net_mgmt.h>
+
+#include <net/ppp.h>
+
+#include "net_private.h"
+
+#include "ppp_stats.h"
+#include "ppp_internal.h"
+
+static const struct ppp_protocol_handler *ppp_lcp;
+
+static void ppp_update_rx_stats(struct net_if *iface,
+				struct net_pkt *pkt, size_t length)
+{
+#if defined(CONFIG_NET_STATISTICS_PPP)
+	ppp_stats_update_bytes_rx(iface, length);
+	ppp_stats_update_pkts_rx(iface);
+#endif /* CONFIG_NET_STATISTICS_PPP */
+}
+
+static void ppp_update_tx_stats(struct net_if *iface,
+				struct net_pkt *pkt, size_t length)
+{
+#if defined(CONFIG_NET_STATISTICS_PPP)
+	ppp_stats_update_bytes_tx(iface, length);
+	ppp_stats_update_pkts_tx(iface);
+#endif /* CONFIG_NET_STATISTICS_PPP */
+}
+
+#if defined(CONFIG_NET_TEST)
+typedef enum net_verdict (*ppp_l2_callback_t)(struct net_if *iface,
+					      struct net_pkt *pkt);
+
+static ppp_l2_callback_t testing_cb;
+
+void ppp_l2_register_pkt_cb(ppp_l2_callback_t cb)
+{
+	testing_cb = cb;
+}
+#endif
+
+static enum net_verdict process_ppp_msg(struct net_if *iface,
+					struct net_pkt *pkt)
+{
+	struct ppp_context *ctx = net_if_l2_data(iface);
+	enum net_verdict verdict = NET_DROP;
+	uint16_t protocol;
+	int ret;
+
+	if (!ctx->is_ready_to_serve) {
+		goto quit;
+	}
+
+	ret = net_pkt_read_be16(pkt, &protocol);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	if ((IS_ENABLED(CONFIG_NET_IPV4) && protocol == PPP_IP) ||
+	    (IS_ENABLED(CONFIG_NET_IPV6) && protocol == PPP_IPV6)) {
+		/* Remove the protocol field so that IP packet processing
+		 * continues properly in net_core.c:process_data()
+		 */
+		(void)net_buf_pull_be16(pkt->buffer);
+		net_pkt_cursor_init(pkt);
+		return NET_CONTINUE;
+	}
+
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol != protocol) {
+			continue;
+		}
+
+		return proto->handler(ctx, iface, pkt);
+	}
+
+	switch (protocol) {
+	case PPP_IP:
+	case PPP_IPV6:
+	case PPP_ECP:
+	case PPP_CCP:
+	case PPP_LCP:
+	case PPP_IPCP:
+	case PPP_IPV6CP:
+		ppp_send_proto_rej(iface, pkt, protocol);
+		break;
+	default:
+		break;
+	}
+
+	NET_DBG("%s protocol %s%s(0x%02x)",
+		ppp_proto2str(protocol) ? "Unhandled" : "Unknown",
+		ppp_proto2str(protocol),
+		ppp_proto2str(protocol) ? " " : "",
+		protocol);
+
+quit:
+	return verdict;
+}
+
+static enum net_verdict ppp_recv(struct net_if *iface,
+				 struct net_pkt *pkt)
+{
+	enum net_verdict verdict;
+
+#if defined(CONFIG_NET_TEST)
+	/* If we are running a PPP unit test, then feed the packet
+	 * back to test app for verification.
+	 */
+	if (testing_cb) {
+		return testing_cb(iface, pkt);
+	}
+#endif
+
+	ppp_update_rx_stats(iface, pkt, net_pkt_get_len(pkt));
+
+	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		net_pkt_hexdump(pkt, "recv L2");
+	}
+
+	verdict = process_ppp_msg(iface, pkt);
+
+	switch (verdict) {
+	case NET_OK:
+		net_pkt_unref(pkt);
+		break;
+	case NET_DROP:
+		ppp_stats_update_drop_rx(iface);
+		break;
+	case NET_CONTINUE:
+		break;
+	}
+
+	return verdict;
+}
+
+static int ppp_send(struct net_if *iface, struct net_pkt *pkt)
+{
+	const struct ppp_api *api = net_if_get_device(iface)->api;
+	struct ppp_context *ctx = net_if_l2_data(iface);
+	int ret;
+
+	if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
+		net_pkt_hexdump(pkt, "send L2");
+	}
+
+	/* If PPP is not yet ready, then just give error to caller as there
+	 * is no way to send before the PPP handshake is finished.
+	 */
+	if (ctx->phase != PPP_RUNNING && !net_pkt_is_ppp(pkt)) {
+		return -ENETDOWN;
+	}
+
+	ret = api->send(net_if_get_device(iface), pkt);
+	if (!ret) {
+		ret = net_pkt_get_len(pkt);
+		ppp_update_tx_stats(iface, pkt, ret);
+		net_pkt_unref(pkt);
+	}
+
+	return ret;
+}
+
+static void ppp_lower_down(struct ppp_context *ctx)
+{
+	if (ppp_lcp) {
+		ppp_lcp->lower_down(ctx);
+	}
+}
+
+static void ppp_lower_up(struct ppp_context *ctx)
+{
+	if (ppp_lcp) {
+		ppp_lcp->lower_up(ctx);
+	}
+}
+
+static void start_ppp(struct ppp_context *ctx)
+{
+	ppp_change_phase(ctx, PPP_ESTABLISH);
+
+	ppp_lower_up(ctx);
+
+	if (ppp_lcp) {
+		NET_DBG("Starting LCP");
+		ppp_lcp->open(ctx);
+	}
+}
+
+static int ppp_enable(struct net_if *iface, bool state)
+{
+	const struct ppp_api *ppp =
+		net_if_get_device(iface)->api;
+	struct ppp_context *ctx = net_if_l2_data(iface);
+
+
+	if (ctx->is_enabled == state) {
+		return 0;
+	}
+
+	ctx->is_enabled = state;
+
+	if (!state) {
+		ppp_lower_down(ctx);
+
+		if (ppp->stop) {
+			ppp->stop(net_if_get_device(iface));
+		}
+	} else {
+		if (ppp->start) {
+			ppp->start(net_if_get_device(iface));
+		}
+
+		if (ctx->is_startup_pending) {
+			ctx->is_enable_done = true;
+		} else {
+			start_ppp(ctx);
+		}
+	}
+
+	return 0;
+}
+
+static enum net_l2_flags ppp_flags(struct net_if *iface)
+{
+	struct ppp_context *ctx = net_if_l2_data(iface);
+
+	return ctx->ppp_l2_flags;
+}
+
+NET_L2_INIT(PPP_L2, ppp_recv, ppp_send, ppp_enable, ppp_flags);
+
+static void carrier_on(struct k_work *work)
+{
+	struct ppp_context *ctx = CONTAINER_OF(work, struct ppp_context,
+					       carrier_mgmt.work);
+
+	if (ctx->iface == NULL || ctx->carrier_mgmt.enabled) {
+		return;
+	}
+
+	NET_DBG("Carrier ON for interface %p", ctx->iface);
+
+	ppp_mgmt_raise_carrier_on_event(ctx->iface);
+
+	ctx->carrier_mgmt.enabled = true;
+
+	net_if_up(ctx->iface);
+}
+
+static void carrier_off(struct k_work *work)
+{
+	struct ppp_context *ctx = CONTAINER_OF(work, struct ppp_context,
+					       carrier_mgmt.work);
+
+	if (ctx->iface == NULL) {
+		return;
+	}
+
+	NET_DBG("Carrier OFF for interface %p", ctx->iface);
+
+	ppp_lower_down(ctx);
+
+	ppp_change_phase(ctx, PPP_DEAD);
+
+	ppp_mgmt_raise_carrier_off_event(ctx->iface);
+
+	net_if_carrier_down(ctx->iface);
+
+	ctx->carrier_mgmt.enabled = false;
+}
+
+static void handle_carrier(struct ppp_context *ctx,
+			   k_work_handler_t handler)
+{
+	k_work_init(&ctx->carrier_mgmt.work, handler);
+
+	k_work_submit(&ctx->carrier_mgmt.work);
+}
+
+void net_ppp_carrier_on(struct net_if *iface)
+{
+	struct ppp_context *ctx = net_if_l2_data(iface);
+
+	handle_carrier(ctx, carrier_on);
+}
+
+void net_ppp_carrier_off(struct net_if *iface)
+{
+	struct ppp_context *ctx = net_if_l2_data(iface);
+
+	handle_carrier(ctx, carrier_off);
+}
+
+#if defined(CONFIG_NET_SHELL)
+static int get_ppp_context(int idx, struct ppp_context **ctx,
+			   struct net_if **iface)
+{
+	*iface = net_if_get_by_index(idx);
+
+	if (!*iface) {
+		return -ENOENT;
+	}
+
+	if (net_if_l2(*iface) != &NET_L2_GET_NAME(PPP)) {
+		return -ENODEV;
+	}
+
+	*ctx = net_if_l2_data(*iface);
+
+	return 0;
+}
+
+static void echo_reply_handler(void *user_data, size_t user_data_len)
+{
+	struct ppp_context *ctx = user_data;
+	uint32_t end_time = k_cycle_get_32();
+	uint32_t time_diff;
+
+	time_diff = end_time - ctx->shell.echo_req_data;
+	ctx->shell.echo_req_data =
+		k_cyc_to_ns_floor64(time_diff) / 1000;
+
+	k_sem_give(&ctx->shell.wait_echo_reply);
+}
+
+int net_ppp_ping(int idx, int32_t timeout)
+{
+	struct ppp_context *ctx;
+	struct net_if *iface;
+	int ret;
+
+	ret = get_ppp_context(idx, &ctx, &iface);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ctx->shell.echo_req_data = k_cycle_get_32();
+	ctx->shell.echo_reply.cb = echo_reply_handler;
+	ctx->shell.echo_reply.user_data = ctx;
+	ctx->shell.echo_reply.user_data_len = sizeof(ctx);
+
+	ret = ppp_send_pkt(&ctx->lcp.fsm, iface, PPP_ECHO_REQ, 0,
+			   UINT_TO_POINTER(ctx->shell.echo_req_data),
+			   sizeof(ctx->shell.echo_req_data));
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = k_sem_take(&ctx->shell.wait_echo_reply, K_MSEC(timeout));
+
+	ctx->shell.echo_reply.cb = NULL;
+
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* Returns amount of microseconds waited */
+	return ctx->shell.echo_req_data;
+}
+
+struct ppp_context *net_ppp_context_get(int idx)
+{
+	struct ppp_context *ctx;
+	struct net_if *iface;
+	int ret;
+
+	if (idx == 0) {
+		iface = net_if_get_first_by_type(&NET_L2_GET_NAME(PPP));
+		if (!iface) {
+			return NULL;
+		}
+
+		return net_if_l2_data(iface);
+	}
+
+	ret = get_ppp_context(idx, &ctx, &iface);
+	if (ret < 0) {
+		return NULL;
+	}
+
+	return ctx;
+}
+#endif
+
+const struct ppp_protocol_handler *ppp_lcp_get(void)
+{
+	return ppp_lcp;
+}
+
+static void ppp_startup(struct k_work *work)
+{
+	struct ppp_context *ctx = CONTAINER_OF(work, struct ppp_context,
+					       startup);
+	int count = 0;
+
+	NET_DBG("PPP %p startup for interface %p", ctx, ctx->iface);
+
+	Z_STRUCT_SECTION_FOREACH(ppp_protocol_handler, proto) {
+		if (proto->protocol == PPP_LCP) {
+			ppp_lcp = proto;
+		}
+
+		proto->init(ctx);
+		count++;
+	}
+
+	if (count == 0) {
+		NET_ERR("There are no PPP protocols configured!");
+		goto bail_out;
+	}
+
+	if (ppp_lcp == NULL) {
+		NET_ERR("No LCP found!");
+		goto bail_out;
+	}
+
+	ctx->is_ready_to_serve = true;
+
+bail_out:
+	ctx->is_startup_pending = false;
+
+	if (ctx->is_enable_done) {
+		start_ppp(ctx);
+		ctx->is_enable_done = false;
+	}
+}
+
+void net_ppp_init(struct net_if *iface)
+{
+	struct ppp_context *ctx = net_if_l2_data(iface);
+
+	NET_DBG("Initializing PPP L2 %p for iface %p", ctx, iface);
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->ppp_l2_flags = NET_L2_MULTICAST | NET_L2_POINT_TO_POINT;
+	ctx->iface = iface;
+
+#if defined(CONFIG_NET_SHELL)
+	k_sem_init(&ctx->shell.wait_echo_reply, 0, UINT_MAX);
+#endif
+
+	/* TODO: Unify the startup worker code so that we can save
+	 * some memory if there are more than one PPP context in the
+	 * system. The issue is not very likely as typically there
+	 * would be only one PPP network interface in the system.
+	 */
+	k_delayed_work_init(&ctx->startup, ppp_startup);
+
+	ctx->is_startup_pending = true;
+
+	k_delayed_work_submit(&ctx->startup,
+			      K_MSEC(CONFIG_NET_L2_PPP_DELAY_STARTUP_MS));
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_mgmt.c	(working copy)
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020 Lemonbeat GmbH
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <net/ppp.h>
+
+void ppp_mgmt_raise_carrier_on_event(struct net_if *iface)
+{
+	net_mgmt_event_notify(NET_EVENT_PPP_CARRIER_ON, iface);
+}
+
+void ppp_mgmt_raise_carrier_off_event(struct net_if *iface)
+{
+	net_mgmt_event_notify(NET_EVENT_PPP_CARRIER_OFF, iface);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.h	(working copy)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __PPP_STATS_H__
+#define __PPP_STATS_H__
+
+#if defined(CONFIG_NET_STATISTICS_PPP)
+
+#include <net/net_ip.h>
+#include <net/net_stats.h>
+#include <net/net_if.h>
+
+static inline void ppp_stats_update_bytes_rx(struct net_if *iface,
+					     uint32_t bytes)
+{
+	const struct ppp_api *api = (const struct ppp_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->bytes.received += bytes;
+}
+
+static inline void ppp_stats_update_bytes_tx(struct net_if *iface,
+					     uint32_t bytes)
+{
+	const struct ppp_api *api = (const struct ppp_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->bytes.sent += bytes;
+}
+
+static inline void ppp_stats_update_pkts_rx(struct net_if *iface)
+{
+	const struct ppp_api *api = (const struct ppp_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->pkts.rx++;
+}
+
+static inline void ppp_stats_update_pkts_tx(struct net_if *iface)
+{
+	const struct ppp_api *api = (const struct ppp_api *)
+		net_if_get_device(iface)->api;
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->pkts.tx++;
+}
+
+static inline void ppp_stats_update_drop_rx(struct net_if *iface)
+{
+	const struct ppp_api *api = ((const struct ppp_api *)
+		net_if_get_device(iface)->api);
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->drop++;
+}
+
+static inline void ppp_stats_update_fcs_error_rx(struct net_if *iface)
+{
+	const struct ppp_api *api = ((const struct ppp_api *)
+		net_if_get_device(iface)->api);
+	struct net_stats_ppp *stats;
+
+	if (!api->get_stats) {
+		return;
+	}
+
+	stats = api->get_stats(net_if_get_device(iface));
+	if (!stats) {
+		return;
+	}
+
+	stats->chkerr++;
+}
+
+#else /* CONFIG_NET_STATISTICS_PPP */
+
+#define ppp_stats_update_bytes_rx(iface, bytes)
+#define ppp_stats_update_bytes_tx(iface, bytes)
+#define ppp_stats_update_pkts_rx(iface)
+#define ppp_stats_update_pkts_tx(iface)
+#define ppp_stats_update_drop_rx(iface)
+#define ppp_stats_update_fcs_error_rx(iface)
+
+#endif /* CONFIG_NET_STATISTICS_PPP */
+
+#endif /* __PPP_STATS_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/ppp/ppp_stats.c	(working copy)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_ppp_stats, CONFIG_NET_L2_PPP_LOG_LEVEL);
+
+#include <kernel.h>
+#include <string.h>
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/ppp.h>
+
+#include "net_stats.h"
+
+#if defined(CONFIG_NET_STATISTICS_USER_API)
+
+static int ppp_stats_get(uint32_t mgmt_request, struct net_if *iface,
+			 void *data, size_t len)
+{
+	size_t len_chk = 0;
+	void *src = NULL;
+	const struct ppp_api *ppp;
+
+	if (NET_MGMT_GET_COMMAND(mgmt_request) ==
+	    NET_REQUEST_STATS_CMD_GET_PPP) {
+		if (net_if_l2(iface) != &NET_L2_GET_NAME(PPP)) {
+			return -ENOENT;
+		}
+
+		ppp = net_if_get_device(iface)->api;
+		if (ppp->get_stats == NULL) {
+			return -ENOENT;
+		}
+
+		len_chk = sizeof(struct net_stats_ppp);
+		src = ppp->get_stats(net_if_get_device(iface));
+	}
+
+	if (len != len_chk || !src) {
+		return -EINVAL;
+	}
+
+	memcpy(data, src, len);
+
+	return 0;
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PPP,
+				  ppp_stats_get);
+
+#endif /* CONFIG_NET_STATISTICS_USER_API */
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/CMakeLists.txt	(working copy)
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_MGMT wifi_mgmt.c)
+zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_SHELL wifi_shell.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_mgmt.c	(working copy)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL);
+
+#include <errno.h>
+
+#include <net/net_core.h>
+#include <net/net_if.h>
+#include <net/wifi_mgmt.h>
+
+static int wifi_connect(uint32_t mgmt_request, struct net_if *iface,
+			void *data, size_t len)
+{
+	struct wifi_connect_req_params *params =
+		(struct wifi_connect_req_params *)data;
+	const struct device *dev = net_if_get_device(iface);
+	struct net_wifi_mgmt_offload *off_api =
+		(struct net_wifi_mgmt_offload *) dev->api;
+
+	if (off_api == NULL || off_api->connect == NULL) {
+		return -ENOTSUP;
+	}
+
+	LOG_HEXDUMP_DBG(params->ssid, params->ssid_length, "ssid");
+	LOG_HEXDUMP_DBG(params->psk, params->psk_length, "psk");
+	NET_DBG("ch %u sec %u", params->channel, params->security);
+
+	if ((params->security > WIFI_SECURITY_TYPE_PSK) ||
+	    (params->ssid_length > WIFI_SSID_MAX_LEN) ||
+	    (params->ssid_length == 0U) ||
+	    ((params->security == WIFI_SECURITY_TYPE_PSK) &&
+	     ((params->psk_length < 8) || (params->psk_length > 64) ||
+	      (params->psk_length == 0U) || !params->psk)) ||
+	    ((params->channel != WIFI_CHANNEL_ANY) &&
+	     (params->channel > WIFI_CHANNEL_MAX)) ||
+	    !params->ssid) {
+		return -EINVAL;
+	}
+
+	return off_api->connect(dev, params);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT, wifi_connect);
+
+static void scan_result_cb(struct net_if *iface, int status,
+			    struct wifi_scan_result *entry)
+{
+	if (!iface) {
+		return;
+	}
+
+	if (!entry) {
+		struct wifi_status scan_status = {
+			.status = status,
+		};
+
+		net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_DONE,
+						iface, &scan_status,
+						sizeof(struct wifi_status));
+		return;
+	}
+
+	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_SCAN_RESULT, iface,
+					entry, sizeof(struct wifi_scan_result));
+}
+
+static int wifi_scan(uint32_t mgmt_request, struct net_if *iface,
+		     void *data, size_t len)
+{
+	const struct device *dev = net_if_get_device(iface);
+	struct net_wifi_mgmt_offload *off_api =
+		(struct net_wifi_mgmt_offload *) dev->api;
+
+	if (off_api == NULL || off_api->scan == NULL) {
+		return -ENOTSUP;
+	}
+
+	return off_api->scan(dev, scan_result_cb);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN, wifi_scan);
+
+
+static int wifi_disconnect(uint32_t mgmt_request, struct net_if *iface,
+			   void *data, size_t len)
+{
+	const struct device *dev = net_if_get_device(iface);
+	struct net_wifi_mgmt_offload *off_api =
+		(struct net_wifi_mgmt_offload *) dev->api;
+
+	if (off_api == NULL || off_api->disconnect == NULL) {
+		return -ENOTSUP;
+	}
+
+	return off_api->disconnect(dev);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT, wifi_disconnect);
+
+void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status)
+{
+	struct wifi_status cnx_status = {
+		.status = status,
+	};
+
+	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_CONNECT_RESULT,
+					iface, &cnx_status,
+					sizeof(struct wifi_status));
+}
+
+void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status)
+{
+	struct wifi_status cnx_status = {
+		.status = status,
+	};
+
+	net_mgmt_event_notify_with_info(NET_EVENT_WIFI_DISCONNECT_RESULT,
+					iface, &cnx_status,
+					sizeof(struct wifi_status));
+}
+
+static int wifi_ap_enable(uint32_t mgmt_request, struct net_if *iface,
+			  void *data, size_t len)
+{
+	struct wifi_connect_req_params *params =
+		(struct wifi_connect_req_params *)data;
+	const struct device *dev = net_if_get_device(iface);
+	struct net_wifi_mgmt_offload *off_api =
+		(struct net_wifi_mgmt_offload *) dev->api;
+
+	if (off_api == NULL || off_api->ap_enable == NULL) {
+		return -ENOTSUP;
+	}
+
+	return off_api->ap_enable(dev, params);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE, wifi_ap_enable);
+
+static int wifi_ap_disable(uint32_t mgmt_request, struct net_if *iface,
+			  void *data, size_t len)
+{
+	const struct device *dev = net_if_get_device(iface);
+	struct net_wifi_mgmt_offload *off_api =
+		(struct net_wifi_mgmt_offload *) dev->api;
+
+	if (off_api == NULL || off_api->ap_enable == NULL) {
+		return -ENOTSUP;
+	}
+
+	return off_api->ap_disable(dev);
+}
+
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE, wifi_ap_disable);
Index: ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/l2/wifi/wifi_shell.c	(working copy)
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief WiFi shell module
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF);
+
+#include <zephyr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <shell/shell.h>
+#include <sys/printk.h>
+#include <init.h>
+
+#include <net/net_if.h>
+#include <net/wifi_mgmt.h>
+#include <net/net_event.h>
+
+#define WIFI_SHELL_MODULE "wifi"
+
+#define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_SCAN_RESULT |		\
+				NET_EVENT_WIFI_SCAN_DONE |		\
+				NET_EVENT_WIFI_CONNECT_RESULT |		\
+				NET_EVENT_WIFI_DISCONNECT_RESULT)
+
+static struct {
+	const struct shell *shell;
+
+	union {
+		struct {
+
+			uint8_t connecting		: 1;
+			uint8_t disconnecting	: 1;
+			uint8_t _unused		: 6;
+		};
+		uint8_t all;
+	};
+} context;
+
+static uint32_t scan_result;
+
+static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
+
+#define print(shell, level, fmt, ...)					\
+	do {								\
+		if (shell) {						\
+			shell_fprintf(shell, level, fmt, ##__VA_ARGS__); \
+		} else {						\
+			printk(fmt, ##__VA_ARGS__);			\
+		}							\
+	} while (false)
+
+static void handle_wifi_scan_result(struct net_mgmt_event_callback *cb)
+{
+	const struct wifi_scan_result *entry =
+		(const struct wifi_scan_result *)cb->info;
+
+	scan_result++;
+
+	if (scan_result == 1U) {
+		print(context.shell, SHELL_NORMAL,
+		      "%-4s | %-32s %-5s | %-4s | %-4s | %-5s\n",
+		      "Num", "SSID", "(len)", "Chan", "RSSI", "Sec");
+	}
+
+	print(context.shell, SHELL_NORMAL,
+	      "%-4d | %-32s %-5u | %-4u | %-4d | %-5s\n",
+	      scan_result, entry->ssid, entry->ssid_length,
+	      entry->channel, entry->rssi,
+	      (entry->security == WIFI_SECURITY_TYPE_PSK ?
+	       "WPA/WPA2" : "Open"));
+}
+
+static void handle_wifi_scan_done(struct net_mgmt_event_callback *cb)
+{
+	const struct wifi_status *status =
+		(const struct wifi_status *)cb->info;
+
+	if (status->status) {
+		print(context.shell, SHELL_WARNING,
+		      "Scan request failed (%d)\n", status->status);
+	} else {
+		print(context.shell, SHELL_NORMAL, "Scan request done\n");
+	}
+
+	scan_result = 0U;
+}
+
+static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb)
+{
+	const struct wifi_status *status =
+		(const struct wifi_status *) cb->info;
+
+	if (status->status) {
+		print(context.shell, SHELL_WARNING,
+		      "Connection request failed (%d)\n", status->status);
+	} else {
+		print(context.shell, SHELL_NORMAL, "Connected\n");
+	}
+
+	context.connecting = false;
+}
+
+static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
+{
+	const struct wifi_status *status =
+		(const struct wifi_status *) cb->info;
+
+	if (context.disconnecting) {
+		print(context.shell,
+		      status->status ? SHELL_WARNING : SHELL_NORMAL,
+		      "Disconnection request %s (%d)\n",
+		      status->status ? "failed" : "done",
+		      status->status);
+		context.disconnecting = false;
+	} else {
+		print(context.shell, SHELL_NORMAL, "Disconnected\n");
+	}
+}
+
+static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
+				    uint32_t mgmt_event, struct net_if *iface)
+{
+	switch (mgmt_event) {
+	case NET_EVENT_WIFI_SCAN_RESULT:
+		handle_wifi_scan_result(cb);
+		break;
+	case NET_EVENT_WIFI_SCAN_DONE:
+		handle_wifi_scan_done(cb);
+		break;
+	case NET_EVENT_WIFI_CONNECT_RESULT:
+		handle_wifi_connect_result(cb);
+		break;
+	case NET_EVENT_WIFI_DISCONNECT_RESULT:
+		handle_wifi_disconnect_result(cb);
+		break;
+	default:
+		break;
+	}
+}
+
+static int __wifi_args_to_params(size_t argc, char *argv[],
+				struct wifi_connect_req_params *params)
+{
+	char *endptr;
+	int idx = 1;
+
+	if (argc < 1) {
+		return -EINVAL;
+	}
+
+	/* SSID */
+	params->ssid = argv[0];
+	params->ssid_length = strlen(params->ssid);
+
+	/* Channel (optional) */
+	if ((idx < argc) && (strlen(argv[idx]) <= 2)) {
+		params->channel = strtol(argv[idx], &endptr, 10);
+		if (*endptr != '\0') {
+			return -EINVAL;
+		}
+
+		if (params->channel == 0U) {
+			params->channel = WIFI_CHANNEL_ANY;
+		}
+
+		idx++;
+	} else {
+		params->channel = WIFI_CHANNEL_ANY;
+	}
+
+	/* PSK (optional) */
+	if (idx < argc) {
+		params->psk = argv[idx];
+		params->psk_length = strlen(argv[idx]);
+		params->security = WIFI_SECURITY_TYPE_PSK;
+	} else {
+		params->security = WIFI_SECURITY_TYPE_NONE;
+	}
+
+	return 0;
+}
+
+static int cmd_wifi_connect(const struct shell *shell, size_t argc,
+			    char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+	static struct wifi_connect_req_params cnx_params;
+
+	if (__wifi_args_to_params(argc - 1, &argv[1], &cnx_params)) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	context.connecting = true;
+	context.shell = shell;
+
+	if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
+		     &cnx_params, sizeof(struct wifi_connect_req_params))) {
+		shell_fprintf(shell, SHELL_WARNING,
+			      "Connection request failed\n");
+		context.connecting = false;
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Connection requested\n");
+	}
+
+	return 0;
+}
+
+static int cmd_wifi_disconnect(const struct shell *shell, size_t argc,
+			       char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+	int status;
+
+	context.disconnecting = true;
+	context.shell = shell;
+
+	status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
+
+	if (status) {
+		context.disconnecting = false;
+
+		if (status == -EALREADY) {
+			shell_fprintf(shell, SHELL_INFO,
+				      "Already disconnected\n");
+		} else {
+			shell_fprintf(shell, SHELL_WARNING,
+				      "Disconnect request failed\n");
+			return -ENOEXEC;
+		}
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL,
+			      "Disconnect requested\n");
+	}
+
+	return 0;
+}
+
+static int cmd_wifi_scan(const struct shell *shell, size_t argc, char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+
+	context.shell = shell;
+
+	if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) {
+		shell_fprintf(shell, SHELL_WARNING, "Scan request failed\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL, "Scan requested\n");
+	}
+
+	return 0;
+}
+
+static int cmd_wifi_ap_enable(const struct shell *shell, size_t argc,
+			      char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+	static struct wifi_connect_req_params cnx_params;
+
+	if (__wifi_args_to_params(argc - 1, &argv[1], &cnx_params)) {
+		shell_help(shell);
+		return -ENOEXEC;
+	}
+
+	context.shell = shell;
+
+	if (net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, iface,
+		     &cnx_params, sizeof(struct wifi_connect_req_params))) {
+		shell_fprintf(shell, SHELL_WARNING, "AP mode failed\n");
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL, "AP mode enabled\n");
+	}
+
+	return 0;
+}
+
+static int cmd_wifi_ap_disable(const struct shell *shell, size_t argc,
+			       char *argv[])
+{
+	struct net_if *iface = net_if_get_default();
+
+	if (net_mgmt(NET_REQUEST_WIFI_AP_DISABLE, iface, NULL, 0)) {
+		shell_fprintf(shell, SHELL_WARNING, "AP mode disable failed\n");
+
+		return -ENOEXEC;
+	} else {
+		shell_fprintf(shell, SHELL_NORMAL, "AP mode disabled\n");
+	}
+
+	return 0;
+}
+
+SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap,
+	SHELL_CMD(enable, NULL, "<SSID> <SSID length> [channel] [PSK]",
+		  cmd_wifi_ap_enable),
+	SHELL_CMD(disable, NULL,
+		  "Disable Access Point mode",
+		  cmd_wifi_ap_disable),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands,
+	SHELL_CMD(connect, NULL,
+		  "\"<SSID>\"\n<channel number (optional), "
+		  "0 means all>\n"
+		  "<PSK (optional: valid only for secured SSIDs)>",
+		  cmd_wifi_connect),
+	SHELL_CMD(disconnect, NULL, "Disconnect from Wifi AP",
+		  cmd_wifi_disconnect),
+	SHELL_CMD(scan, NULL, "Scan Wifi AP", cmd_wifi_scan),
+	SHELL_CMD(ap, &wifi_cmd_ap, "Access Point mode commands", NULL),
+	SHELL_SUBCMD_SET_END
+);
+
+SHELL_CMD_REGISTER(wifi, &wifi_commands, "Wifi commands", NULL);
+
+static int wifi_shell_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	context.shell = NULL;
+	context.all = 0U;
+	scan_result = 0U;
+
+	net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
+				     wifi_mgmt_event_handler,
+				     WIFI_SHELL_MGMT_EVENTS);
+
+	net_mgmt_add_event_callback(&wifi_shell_mgmt_cb);
+
+	return 0;
+}
+
+SYS_INIT(wifi_shell_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/CMakeLists.txt	(working copy)
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: Apache-2.0
+
+add_subdirectory(utils)
+add_subdirectory_ifdef(CONFIG_COAP coap)
+add_subdirectory_ifdef(CONFIG_LWM2M lwm2m)
+add_subdirectory_ifdef(CONFIG_SOCKS socks)
+add_subdirectory_ifdef(CONFIG_SNTP sntp)
+add_subdirectory_ifdef(CONFIG_MQTT_LIB               mqtt)
+add_subdirectory_ifdef(CONFIG_TFTP_LIB               tftp)
+add_subdirectory_ifdef(CONFIG_NET_CONFIG_SETTINGS    config)
+add_subdirectory_ifdef(CONFIG_NET_SOCKETS            sockets)
+add_subdirectory_ifdef(CONFIG_TLS_CREDENTIALS        tls_credentials)
+add_subdirectory_ifdef(CONFIG_NET_CONNECTION_MANAGER conn_mgr)
+
+if (CONFIG_DNS_RESOLVER
+    OR CONFIG_MDNS_RESPONDER
+    OR CONFIG_LLMNR_RESPONDER)
+  add_subdirectory(dns)
+endif()
+
+if(CONFIG_HTTP_PARSER_URL OR CONFIG_HTTP_PARSER OR CONFIG_HTTP_CLIENT)
+  add_subdirectory(http)
+endif()
+
+add_subdirectory_ifdef(CONFIG_WEBSOCKET_CLIENT websocket)
+add_subdirectory_ifdef(CONFIG_NET_L2_OPENTHREAD openthread)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/Kconfig	(working copy)
@@ -0,0 +1,40 @@
+# Copyright (c) 2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menu "Network Protocols"
+
+source "subsys/net/lib/coap/Kconfig"
+
+source "subsys/net/lib/dns/Kconfig"
+
+source "subsys/net/lib/mqtt/Kconfig"
+
+source "subsys/net/lib/tftp/Kconfig"
+
+source "subsys/net/lib/http/Kconfig"
+
+source "subsys/net/lib/websocket/Kconfig"
+
+source "subsys/net/lib/lwm2m/Kconfig"
+
+source "subsys/net/lib/socks/Kconfig"
+
+source "subsys/net/lib/sntp/Kconfig"
+
+endmenu
+
+menu "Network Libraries"
+
+source "subsys/net/lib/config/Kconfig"
+
+source "subsys/net/lib/sockets/Kconfig"
+
+source "subsys/net/lib/tls_credentials/Kconfig"
+
+endmenu
+
+menu "Network additional services"
+
+source "subsys/net/lib/conn_mgr/Kconfig"
+
+endmenu
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/CMakeLists.txt	(working copy)
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+
+zephyr_sources_ifdef(CONFIG_COAP
+  coap.c
+  coap_link_format.c
+)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/Kconfig	(working copy)
@@ -0,0 +1,75 @@
+# CoAP implementation for Zephyr
+
+# Copyright (c) 2017 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config COAP
+	bool "CoAP Support"
+	help
+	  This option enables the CoAP implementation.
+
+
+if COAP
+
+# This setting is only used by unit test. Do not enable it in applications
+config COAP_TEST_API_ENABLE
+	bool "Enable test API for CoAP unit tests"
+	help
+	  Do not enable this for normal use.
+
+config COAP_WELL_KNOWN_BLOCK_WISE
+	bool "CoAP ./well-known/core services block wise support"
+	help
+	  This option enables the block wise support of CoAP response
+	  to ./well-known/core request. Without this option all resource's
+	  information will be sent in a single IP packet (can be multiple
+	  fragments depends on MTU size). This will be useful in mesh kind
+	  of networks.
+
+config COAP_WELL_KNOWN_BLOCK_WISE_SIZE
+	int "CoAP ./well-known/core services block wise support"
+	default 32
+	depends on COAP_WELL_KNOWN_BLOCK_WISE
+	help
+	  Maximum size of CoAP block. Valid values are 16, 32, 64, 128,
+	  256, 512 and 1024.
+
+config COAP_EXTENDED_OPTIONS_LEN
+	bool "Support for CoAP extended options"
+	help
+	  This option enables the parsing of extended CoAP options length.
+	  CoAP extended options length can be 2 byte value, which
+	  requires more memory. User can save memory by disabling this.
+	  That means only length of maximum 12 bytes are supported by default.
+	  Enable this if length field going to bigger that 12.
+
+config COAP_EXTENDED_OPTIONS_LEN_VALUE
+	int "CoAP extended options length value"
+	default 13
+	depends on COAP_EXTENDED_OPTIONS_LEN
+	help
+	  This option specifies the maximum value of length field when
+	  COAP_EXTENDED_OPTIONS_LEN is enabled. Define the value according to
+	  user requirement.
+
+config COAP_INIT_ACK_TIMEOUT_MS
+	int "base length of the random generated initial ACK timeout in ms"
+	default 2345
+	range 2345 100000
+	help
+	  This value is used as a base value to retry pending CoAP packets.
+
+config COAP_URI_WILDCARD
+	bool "Enable wildcards in CoAP resource path"
+	default y
+	help
+	  This option enables MQTT-style wildcards in path. Disable it if
+	  resource path may contain plus or hash symbol.
+
+module = COAP
+module-dep = NET_LOG
+module-str = Log level for CoAP
+module-help = Enables CoAP debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # COAP
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap.c	(working copy)
@@ -0,0 +1,1459 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_coap, CONFIG_COAP_LOG_LEVEL);
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <random/rand32.h>
+#include <sys/atomic.h>
+
+#include <zephyr/types.h>
+#include <sys/byteorder.h>
+#include <sys/math_extras.h>
+
+#include <net/net_ip.h>
+#include <net/net_core.h>
+#include <net/coap.h>
+
+/* Values as per RFC 7252, section-3.1.
+ *
+ * Option Delta/Length: 4-bit unsigned integer. A value between 0 and
+ * 12 indicates the Option Delta/Length.  Three values are reserved for
+ * special constructs:
+ * 13: An 8-bit unsigned integer precedes the Option Value and indicates
+ *     the Option Delta/Length minus 13.
+ * 14: A 16-bit unsigned integer in network byte order precedes the
+ *     Option Value and indicates the Option Delta/Length minus 269.
+ * 15: Reserved for future use.
+ */
+#define COAP_OPTION_NO_EXT 12 /* Option's Delta/Length without extended data */
+#define COAP_OPTION_EXT_13 13
+#define COAP_OPTION_EXT_14 14
+#define COAP_OPTION_EXT_15 15
+#define COAP_OPTION_EXT_269 269
+
+/* CoAP Version */
+#define COAP_VERSION		1
+
+/* CoAP Payload Marker */
+#define COAP_MARKER		0xFF
+
+#define BASIC_HEADER_SIZE	4
+
+/* The CoAP message ID that is incremented each time coap_next_id() is called. */
+static uint16_t message_id;
+
+static inline bool append_u8(struct coap_packet *cpkt, uint8_t data)
+{
+	if (!cpkt) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < 1) {
+		return false;
+	}
+
+	cpkt->data[cpkt->offset++] = data;
+
+	return true;
+}
+
+static inline bool append_be16(struct coap_packet *cpkt, uint16_t data)
+{
+	if (!cpkt) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < 2) {
+		return false;
+	}
+
+	cpkt->data[cpkt->offset++] = data >> 8;
+	cpkt->data[cpkt->offset++] = (uint8_t) data;
+
+	return true;
+}
+
+static inline bool append(struct coap_packet *cpkt, const uint8_t *data, uint16_t len)
+{
+	if (!cpkt || !data) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < len) {
+		return false;
+	}
+
+	memcpy(cpkt->data + cpkt->offset, data, len);
+	cpkt->offset += len;
+
+	return true;
+}
+
+int coap_packet_init(struct coap_packet *cpkt, uint8_t *data,
+		     uint16_t max_len, uint8_t ver, uint8_t type,
+		     uint8_t tokenlen, uint8_t *token, uint8_t code, uint16_t id)
+{
+	uint8_t hdr;
+	bool res;
+
+	if (!cpkt || !data || !max_len) {
+		return -EINVAL;
+	}
+
+	memset(cpkt, 0, sizeof(*cpkt));
+
+	cpkt->data = data;
+	cpkt->offset = 0U;
+	cpkt->max_len = max_len;
+	cpkt->delta = 0U;
+
+	hdr = (ver & 0x3) << 6;
+	hdr |= (type & 0x3) << 4;
+	hdr |= tokenlen & 0xF;
+
+	res = append_u8(cpkt, hdr);
+	if (!res) {
+		return -EINVAL;
+	}
+
+	res = append_u8(cpkt, code);
+	if (!res) {
+		return -EINVAL;
+	}
+
+	res = append_be16(cpkt, id);
+	if (!res) {
+		return -EINVAL;
+	}
+
+	if (token && tokenlen) {
+		res = append(cpkt, token, tokenlen);
+		if (!res) {
+			return -EINVAL;
+		}
+	}
+
+	/* Header length : (version + type + tkl) + code + id + [token] */
+	cpkt->hdr_len = 1 + 1 + 2 + tokenlen;
+
+	return 0;
+}
+
+static void option_header_set_delta(uint8_t *opt, uint8_t delta)
+{
+	*opt = (delta & 0xF) << 4;
+}
+
+static void option_header_set_len(uint8_t *opt, uint8_t len)
+{
+	*opt |= (len & 0xF);
+}
+
+static uint8_t encode_extended_option(uint16_t num, uint8_t *opt, uint16_t *ext)
+{
+	if (num < COAP_OPTION_EXT_13) {
+		*opt = num;
+		*ext = 0U;
+
+		return 0;
+	} else if (num < COAP_OPTION_EXT_269) {
+		*opt = COAP_OPTION_EXT_13;
+		*ext = num - COAP_OPTION_EXT_13;
+
+		return 1;
+	}
+
+	*opt = COAP_OPTION_EXT_14;
+	*ext = num - COAP_OPTION_EXT_269;
+
+	return 2;
+}
+
+static int encode_option(struct coap_packet *cpkt, uint16_t code,
+			 const uint8_t *value, uint16_t len)
+{
+	uint16_t delta_ext; /* Extended delta */
+	uint16_t len_ext; /* Extended length */
+	uint8_t opt; /* delta | len */
+	uint8_t opt_delta;
+	uint8_t opt_len;
+	uint8_t delta_size;
+	uint8_t len_size;
+	bool res;
+
+	delta_size = encode_extended_option(code, &opt_delta, &delta_ext);
+	len_size = encode_extended_option(len, &opt_len, &len_ext);
+
+	option_header_set_delta(&opt, opt_delta);
+	option_header_set_len(&opt, opt_len);
+
+	res = append_u8(cpkt, opt);
+	if (!res) {
+		return -EINVAL;
+	}
+
+	if (delta_size == 1U) {
+		res = append_u8(cpkt, (uint8_t)delta_ext);
+		if (!res) {
+			return -EINVAL;
+		}
+	} else if (delta_size == 2U) {
+		res = append_be16(cpkt, delta_ext);
+		if (!res) {
+			return -EINVAL;
+		}
+	}
+
+	if (len_size == 1U) {
+		res = append_u8(cpkt, (uint8_t)len_ext);
+		if (!res) {
+			return -EINVAL;
+		}
+	} else if (delta_size == 2U) {
+		res = append_be16(cpkt, len_ext);
+		if (!res) {
+			return -EINVAL;
+		}
+	}
+
+	if (len && value) {
+		res = append(cpkt, value, len);
+		if (!res) {
+			return -EINVAL;
+		}
+	}
+
+	return  (1 + delta_size + len_size + len);
+}
+
+/* TODO Add support for inserting options in proper place
+ * and modify other option's delta accordingly.
+ */
+int coap_packet_append_option(struct coap_packet *cpkt, uint16_t code,
+			      const uint8_t *value, uint16_t len)
+{
+	int r;
+
+	if (!cpkt) {
+		return -EINVAL;
+	}
+
+	if (len && !value) {
+		return -EINVAL;
+	}
+
+	if (code < cpkt->delta) {
+		NET_ERR("Options should be in ascending order");
+		return -EINVAL;
+	}
+
+	/* Calculate delta, if this option is not the first one */
+	if (cpkt->opt_len) {
+		code = (code == cpkt->delta) ? 0 : code - cpkt->delta;
+	}
+
+	r = encode_option(cpkt, code, value, len);
+	if (r < 0) {
+		return -EINVAL;
+	}
+
+	cpkt->opt_len += r;
+	cpkt->delta += code;
+
+	return 0;
+}
+
+int coap_append_option_int(struct coap_packet *cpkt, uint16_t code,
+			   unsigned int val)
+{
+	uint8_t data[4], len;
+
+	if (val == 0U) {
+		data[0] = 0U;
+		len = 0U;
+	} else if (val < 0xFF) {
+		data[0] = (uint8_t) val;
+		len = 1U;
+	} else if (val < 0xFFFF) {
+		sys_put_be16(val, data);
+		len = 2U;
+	} else if (val < 0xFFFFFF) {
+		sys_put_be16(val, &data[1]);
+		data[0] = val >> 16;
+		len = 3U;
+	} else {
+		sys_put_be32(val, data);
+		len = 4U;
+	}
+
+	return coap_packet_append_option(cpkt, code, data, len);
+}
+
+unsigned int coap_option_value_to_int(const struct coap_option *option)
+{
+	switch (option->len) {
+	case 0:
+		return 0;
+	case 1:
+		return option->value[0];
+	case 2:
+		return (option->value[1] << 0) | (option->value[0] << 8);
+	case 3:
+		return (option->value[2] << 0) | (option->value[1] << 8) |
+			(option->value[0] << 16);
+	case 4:
+		return (option->value[3] << 0) | (option->value[2] << 8) |
+			(option->value[1] << 16) | (option->value[0] << 24);
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+int coap_packet_append_payload_marker(struct coap_packet *cpkt)
+{
+	return append_u8(cpkt, COAP_MARKER) ? 0 : -EINVAL;
+}
+
+int coap_packet_append_payload(struct coap_packet *cpkt, uint8_t *payload,
+			       uint16_t payload_len)
+{
+	return append(cpkt, payload, payload_len) ? 0 : -EINVAL;
+}
+
+uint8_t *coap_next_token(void)
+{
+	static uint32_t rand[2];
+
+	rand[0] = sys_rand32_get();
+	rand[1] = sys_rand32_get();
+
+	return (uint8_t *) rand;
+}
+
+static uint8_t option_header_get_delta(uint8_t opt)
+{
+	return (opt & 0xF0) >> 4;
+}
+
+static uint8_t option_header_get_len(uint8_t opt)
+{
+	return opt & 0x0F;
+}
+
+static int read_u8(uint8_t *data, uint16_t offset, uint16_t *pos,
+		   uint16_t max_len, uint8_t *value)
+{
+	if (max_len - offset < 1) {
+		return -EINVAL;
+	}
+
+	*value = data[offset++];
+	*pos = offset;
+
+	return max_len - offset;
+}
+
+static int read_be16(uint8_t *data, uint16_t offset, uint16_t *pos,
+		     uint16_t max_len, uint16_t *value)
+{
+	if (max_len - offset < 2) {
+		return -EINVAL;
+	}
+
+	*value = data[offset++] << 8;
+	*value |= data[offset++];
+	*pos = offset;
+
+	return max_len - offset;
+}
+
+static int read(uint8_t *data, uint16_t offset, uint16_t *pos,
+		uint16_t max_len, uint16_t len, uint8_t *value)
+{
+	if (max_len - offset < len) {
+		return -EINVAL;
+	}
+
+	memcpy(value, data + offset, len);
+	offset += len;
+	*pos = offset;
+
+	return max_len - offset;
+}
+
+static int decode_delta(uint8_t *data, uint16_t offset, uint16_t *pos, uint16_t max_len,
+			uint16_t opt, uint16_t *opt_ext, uint16_t *hdr_len)
+{
+	int ret = 0;
+
+	if (opt == COAP_OPTION_EXT_13) {
+		uint8_t val;
+
+		*hdr_len = 1U;
+
+		ret = read_u8(data, offset, pos, max_len, &val);
+		if (ret < 0) {
+			return -EINVAL;
+		}
+
+		opt = val + COAP_OPTION_EXT_13;
+	} else if (opt == COAP_OPTION_EXT_14) {
+		uint16_t val;
+
+		*hdr_len = 2U;
+
+		ret = read_be16(data, offset, pos, max_len, &val);
+		if (ret < 0) {
+			return -EINVAL;
+		}
+
+		opt = val + COAP_OPTION_EXT_269;
+	} else if (opt == COAP_OPTION_EXT_15) {
+		return -EINVAL;
+	}
+
+	*opt_ext = opt;
+
+	return ret;
+}
+
+static int parse_option(uint8_t *data, uint16_t offset, uint16_t *pos,
+			uint16_t max_len, uint16_t *opt_delta, uint16_t *opt_len,
+			struct coap_option *option)
+{
+	uint16_t hdr_len;
+	uint16_t delta;
+	uint16_t len;
+	uint8_t opt;
+	int r;
+
+	r = read_u8(data, offset, pos, max_len, &opt);
+	if (r < 0) {
+		return r;
+	}
+
+	*opt_len += 1U;
+
+	/* This indicates that options have ended */
+	if (opt == COAP_MARKER) {
+		/* packet w/ marker but no payload is malformed */
+		return r > 0 ? 0 : -EINVAL;
+	}
+
+	delta = option_header_get_delta(opt);
+	len = option_header_get_len(opt);
+
+	/* r == 0 means no more data to read from fragment, but delta
+	 * field shows that packet should contain more data, it must
+	 * be a malformed packet.
+	 */
+	if (r == 0 && delta > COAP_OPTION_NO_EXT) {
+		return -EINVAL;
+	}
+
+	if (delta > COAP_OPTION_NO_EXT) {
+		/* In case 'delta' doesn't fit the option fixed header. */
+		r = decode_delta(data, *pos, pos, max_len,
+				 delta, &delta, &hdr_len);
+		if ((r < 0) || (r == 0 && len > COAP_OPTION_NO_EXT)) {
+			return -EINVAL;
+		}
+
+		if (u16_add_overflow(*opt_len, hdr_len, opt_len)) {
+			return -EINVAL;
+		}
+	}
+
+	if (len > COAP_OPTION_NO_EXT) {
+		/* In case 'len' doesn't fit the option fixed header. */
+		r = decode_delta(data, *pos, pos, max_len,
+				 len, &len, &hdr_len);
+		if (r < 0) {
+			return -EINVAL;
+		}
+
+		if (u16_add_overflow(*opt_len, hdr_len, opt_len)) {
+			return -EINVAL;
+		}
+	}
+
+	if (u16_add_overflow(*opt_delta, delta, opt_delta) ||
+	    u16_add_overflow(*opt_len, len, opt_len)) {
+		return -EINVAL;
+	}
+
+	if (r == 0 && len != 0U) {
+		/* r == 0 means no more data to read from fragment, but len
+		 * field shows that packet should contain more data, it must
+		 * be a malformed packet.
+		 */
+		return -EINVAL;
+	}
+
+	if (option) {
+		/*
+		 * Make sure the option data will fit into the value field of
+		 * coap_option.
+		 * NOTE: To expand the size of the value field set:
+		 * CONFIG_COAP_EXTENDED_OPTIONS_LEN=y
+		 * CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=<size>
+		 */
+		if (len > sizeof(option->value)) {
+			NET_ERR("%u is > sizeof(coap_option->value)(%zu)!",
+				len, sizeof(option->value));
+			return -EINVAL;
+		}
+
+		option->delta = *opt_delta;
+		option->len = len;
+		r = read(data, *pos, pos, max_len, len, &option->value[0]);
+		if (r < 0) {
+			return -EINVAL;
+		}
+	} else {
+		if (u16_add_overflow(*pos, len, pos)) {
+			return -EINVAL;
+		}
+
+		r = max_len - *pos;
+	}
+
+	return r;
+}
+
+int coap_packet_parse(struct coap_packet *cpkt, uint8_t *data, uint16_t len,
+		      struct coap_option *options, uint8_t opt_num)
+{
+	uint16_t opt_len;
+	uint16_t offset;
+	uint16_t delta;
+	uint8_t num;
+	uint8_t tkl;
+	int ret;
+
+	if (!cpkt || !data) {
+		return -EINVAL;
+	}
+
+	if (len < BASIC_HEADER_SIZE) {
+		return -EINVAL;
+	}
+
+	if (options) {
+		memset(options, 0, opt_num * sizeof(struct coap_option));
+	}
+
+	cpkt->data = data;
+	cpkt->offset = 0U;
+	cpkt->max_len = len;
+	cpkt->opt_len = 0U;
+	cpkt->hdr_len = 0U;
+	cpkt->delta = 0U;
+
+	/* Token lengths 9-15 are reserved. */
+	tkl = cpkt->data[0] & 0x0f;
+	if (tkl > 8) {
+		return -EINVAL;
+	}
+
+	cpkt->hdr_len = BASIC_HEADER_SIZE + tkl;
+	if (cpkt->hdr_len > len) {
+		return -EINVAL;
+	}
+
+	cpkt->offset = cpkt->hdr_len;
+	if (cpkt->hdr_len == len) {
+		return 0;
+	}
+
+	offset = cpkt->offset;
+	opt_len = 0U;
+	delta = 0U;
+	num = 0U;
+
+	while (1) {
+		struct coap_option *option;
+
+		option = num < opt_num ? &options[num++] : NULL;
+		ret = parse_option(cpkt->data, offset, &offset, cpkt->max_len,
+				   &delta, &opt_len, option);
+		if (ret < 0) {
+			return ret;
+		} else if (ret == 0) {
+			break;
+		}
+	}
+
+	cpkt->opt_len = opt_len;
+	cpkt->delta = delta;
+	cpkt->offset = offset;
+
+	return 0;
+}
+
+int coap_find_options(const struct coap_packet *cpkt, uint16_t code,
+		      struct coap_option *options, uint16_t veclen)
+{
+	uint16_t opt_len;
+	uint16_t offset;
+	uint16_t delta;
+	uint8_t num;
+	int r;
+
+	offset = cpkt->hdr_len;
+	opt_len = 0U;
+	delta = 0U;
+	num = 0U;
+
+	while (delta <= code && num < veclen) {
+		r = parse_option(cpkt->data, offset, &offset,
+				 cpkt->max_len, &delta, &opt_len,
+				 &options[num]);
+		if (r < 0) {
+			return -EINVAL;
+		}
+
+		if (code == options[num].delta) {
+			num++;
+		}
+
+		if (r == 0) {
+			break;
+		}
+	}
+
+	return num;
+}
+
+uint8_t coap_header_get_version(const struct coap_packet *cpkt)
+{
+	if (!cpkt || !cpkt->data) {
+		return 0;
+	}
+
+	return (cpkt->data[0] & 0xC0) >> 6;
+}
+
+uint8_t coap_header_get_type(const struct coap_packet *cpkt)
+{
+	if (!cpkt || !cpkt->data) {
+		return 0;
+	}
+
+	return (cpkt->data[0] & 0x30) >> 4;
+}
+
+static uint8_t __coap_header_get_code(const struct coap_packet *cpkt)
+{
+	if (!cpkt || !cpkt->data) {
+		return 0;
+	}
+
+	return cpkt->data[1];
+}
+
+uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token)
+{
+	uint8_t tkl;
+
+	if (!cpkt || !cpkt->data) {
+		return 0;
+	}
+
+	tkl = cpkt->data[0] & 0x0f;
+	if (tkl) {
+		memcpy(token, cpkt->data + BASIC_HEADER_SIZE, tkl);
+	}
+
+	return tkl;
+}
+
+uint8_t coap_header_get_code(const struct coap_packet *cpkt)
+{
+	uint8_t code = __coap_header_get_code(cpkt);
+
+	switch (code) {
+	/* Methods are encoded in the code field too */
+	case COAP_METHOD_GET:
+	case COAP_METHOD_POST:
+	case COAP_METHOD_PUT:
+	case COAP_METHOD_DELETE:
+
+	/* All the defined response codes */
+	case COAP_RESPONSE_CODE_OK:
+	case COAP_RESPONSE_CODE_CREATED:
+	case COAP_RESPONSE_CODE_DELETED:
+	case COAP_RESPONSE_CODE_VALID:
+	case COAP_RESPONSE_CODE_CHANGED:
+	case COAP_RESPONSE_CODE_CONTENT:
+	case COAP_RESPONSE_CODE_CONTINUE:
+	case COAP_RESPONSE_CODE_BAD_REQUEST:
+	case COAP_RESPONSE_CODE_UNAUTHORIZED:
+	case COAP_RESPONSE_CODE_BAD_OPTION:
+	case COAP_RESPONSE_CODE_FORBIDDEN:
+	case COAP_RESPONSE_CODE_NOT_FOUND:
+	case COAP_RESPONSE_CODE_NOT_ALLOWED:
+	case COAP_RESPONSE_CODE_NOT_ACCEPTABLE:
+	case COAP_RESPONSE_CODE_INCOMPLETE:
+	case COAP_RESPONSE_CODE_PRECONDITION_FAILED:
+	case COAP_RESPONSE_CODE_REQUEST_TOO_LARGE:
+	case COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT:
+	case COAP_RESPONSE_CODE_INTERNAL_ERROR:
+	case COAP_RESPONSE_CODE_NOT_IMPLEMENTED:
+	case COAP_RESPONSE_CODE_BAD_GATEWAY:
+	case COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE:
+	case COAP_RESPONSE_CODE_GATEWAY_TIMEOUT:
+	case COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED:
+	case COAP_CODE_EMPTY:
+		return code;
+	default:
+		return COAP_CODE_EMPTY;
+	}
+}
+
+uint16_t coap_header_get_id(const struct coap_packet *cpkt)
+{
+	if (!cpkt || !cpkt->data) {
+		return 0;
+	}
+
+	return (cpkt->data[2] << 8) | cpkt->data[3];
+}
+
+const uint8_t *coap_packet_get_payload(const struct coap_packet *cpkt, uint16_t *len)
+{
+	int payload_len;
+
+	if (!cpkt || !len) {
+		return NULL;
+	}
+
+	payload_len = cpkt->max_len - cpkt->hdr_len - cpkt->opt_len;
+	if (payload_len > 0) {
+		*len = payload_len;
+	} else {
+		*len = 0U;
+	}
+
+	return !(*len) ? NULL :
+		cpkt->data + cpkt->hdr_len + cpkt->opt_len;
+}
+
+static bool uri_path_eq(const struct coap_packet *cpkt,
+			const char * const *path,
+			struct coap_option *options,
+			uint8_t opt_num)
+{
+	uint8_t i;
+	uint8_t j = 0U;
+
+	for (i = 0U; i < opt_num && path[j]; i++) {
+		if (options[i].delta != COAP_OPTION_URI_PATH) {
+			continue;
+		}
+
+		if (IS_ENABLED(CONFIG_COAP_URI_WILDCARD) && strlen(path[j]) == 1) {
+			if (*path[j] == '+') {
+				/* Single-level wildcard */
+				j++;
+				continue;
+			} else if (*path[j] == '#') {
+				/* Multi-level wildcard */
+				return true;
+			}
+		}
+
+		if (options[i].len != strlen(path[j])) {
+			return false;
+		}
+
+		if (memcmp(options[i].value, path[j], options[i].len)) {
+			return false;
+		}
+
+		j++;
+	}
+
+	if (path[j]) {
+		return false;
+	}
+
+	for (; i < opt_num; i++) {
+		if (options[i].delta == COAP_OPTION_URI_PATH) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static coap_method_t method_from_code(const struct coap_resource *resource,
+				      uint8_t code)
+{
+	switch (code) {
+	case COAP_METHOD_GET:
+		return resource->get;
+	case COAP_METHOD_POST:
+		return resource->post;
+	case COAP_METHOD_PUT:
+		return resource->put;
+	case COAP_METHOD_DELETE:
+		return resource->del;
+	default:
+		return NULL;
+	}
+}
+
+static bool is_request(const struct coap_packet *cpkt)
+{
+	uint8_t code = coap_header_get_code(cpkt);
+
+	return !(code & ~COAP_REQUEST_MASK);
+}
+
+int coap_handle_request(struct coap_packet *cpkt,
+			struct coap_resource *resources,
+			struct coap_option *options,
+			uint8_t opt_num,
+			struct sockaddr *addr, socklen_t addr_len)
+{
+	struct coap_resource *resource;
+
+	if (!is_request(cpkt)) {
+		return 0;
+	}
+
+	/* FIXME: deal with hierarchical resources */
+	for (resource = resources; resource && resource->path; resource++) {
+		coap_method_t method;
+		uint8_t code;
+
+		if (!uri_path_eq(cpkt, resource->path, options, opt_num)) {
+			continue;
+		}
+
+		code = coap_header_get_code(cpkt);
+		method = method_from_code(resource, code);
+		if (!method) {
+			return -EPERM;
+		}
+
+		return method(resource, cpkt, addr, addr_len);
+	}
+
+	NET_DBG("%d", __LINE__);
+	return -ENOENT;
+}
+
+int coap_block_transfer_init(struct coap_block_context *ctx,
+			      enum coap_block_size block_size,
+			      size_t total_size)
+{
+	ctx->block_size = block_size;
+	ctx->total_size = total_size;
+	ctx->current = 0;
+
+	return 0;
+}
+
+#define GET_BLOCK_SIZE(v) (((v) & 0x7))
+#define GET_MORE(v) (!!((v) & 0x08))
+#define GET_NUM(v) ((v) >> 4)
+
+#define SET_BLOCK_SIZE(v, b) (v |= ((b) & 0x07))
+#define SET_MORE(v, m) ((v) |= (m) ? 0x08 : 0x00)
+#define SET_NUM(v, n) ((v) |= ((n) << 4))
+
+int coap_append_block1_option(struct coap_packet *cpkt,
+			      struct coap_block_context *ctx)
+{
+	uint16_t bytes = coap_block_size_to_bytes(ctx->block_size);
+	unsigned int val = 0U;
+	int r;
+
+	if (is_request(cpkt)) {
+		SET_BLOCK_SIZE(val, ctx->block_size);
+		SET_MORE(val, ctx->current + bytes < ctx->total_size);
+		SET_NUM(val, ctx->current / bytes);
+	} else {
+		SET_BLOCK_SIZE(val, ctx->block_size);
+		SET_NUM(val, ctx->current / bytes);
+	}
+
+	r = coap_append_option_int(cpkt, COAP_OPTION_BLOCK1, val);
+
+	return r;
+}
+
+int coap_append_block2_option(struct coap_packet *cpkt,
+			      struct coap_block_context *ctx)
+{
+	int r, val = 0;
+	uint16_t bytes = coap_block_size_to_bytes(ctx->block_size);
+
+	if (is_request(cpkt)) {
+		SET_BLOCK_SIZE(val, ctx->block_size);
+		SET_NUM(val, ctx->current / bytes);
+	} else {
+		SET_BLOCK_SIZE(val, ctx->block_size);
+		SET_MORE(val, ctx->current + bytes < ctx->total_size);
+		SET_NUM(val, ctx->current / bytes);
+	}
+
+	r = coap_append_option_int(cpkt, COAP_OPTION_BLOCK2, val);
+
+	return r;
+}
+
+int coap_append_size1_option(struct coap_packet *cpkt,
+			     struct coap_block_context *ctx)
+{
+	return coap_append_option_int(cpkt, COAP_OPTION_SIZE1, ctx->total_size);
+}
+
+int coap_append_size2_option(struct coap_packet *cpkt,
+			     struct coap_block_context *ctx)
+{
+	return coap_append_option_int(cpkt, COAP_OPTION_SIZE2, ctx->total_size);
+}
+
+int coap_get_option_int(const struct coap_packet *cpkt, uint16_t code)
+{
+	struct coap_option option = {};
+	unsigned int val;
+	int count = 1;
+
+	count = coap_find_options(cpkt, code, &option, count);
+	if (count <= 0) {
+		return -ENOENT;
+	}
+
+	val = coap_option_value_to_int(&option);
+
+	return val;
+}
+
+static int update_descriptive_block(struct coap_block_context *ctx,
+				    int block, int size)
+{
+	size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
+
+	if (block == -ENOENT) {
+		return 0;
+	}
+
+	if (size && ctx->total_size && ctx->total_size != size) {
+		return -EINVAL;
+	}
+
+	if (ctx->current > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) {
+		return -EINVAL;
+	}
+
+	if (ctx->total_size && new_current > ctx->total_size) {
+		return -EINVAL;
+	}
+
+	if (size) {
+		ctx->total_size = size;
+	}
+	ctx->current = new_current;
+	ctx->block_size = MIN(GET_BLOCK_SIZE(block), ctx->block_size);
+
+	return 0;
+}
+
+static int update_control_block1(struct coap_block_context *ctx,
+				     int block, int size)
+{
+	size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
+
+	if (block == -ENOENT) {
+		return 0;
+	}
+
+	if (new_current != ctx->current) {
+		return -EINVAL;
+	}
+
+	if (GET_BLOCK_SIZE(block) > ctx->block_size) {
+		return -EINVAL;
+	}
+
+	ctx->block_size = GET_BLOCK_SIZE(block);
+	ctx->total_size = size;
+
+	return 0;
+}
+
+static int update_control_block2(struct coap_block_context *ctx,
+				 int block, int size)
+{
+	size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4);
+
+	if (block == -ENOENT) {
+		return 0;
+	}
+
+	if (GET_MORE(block)) {
+		return -EINVAL;
+	}
+
+	if (GET_NUM(block) > 0 && GET_BLOCK_SIZE(block) != ctx->block_size) {
+		return -EINVAL;
+	}
+
+	ctx->current = new_current;
+	ctx->block_size = MIN(GET_BLOCK_SIZE(block), ctx->block_size);
+
+	return 0;
+}
+
+int coap_update_from_block(const struct coap_packet *cpkt,
+			   struct coap_block_context *ctx)
+{
+	int r, block1, block2, size1, size2;
+
+	block1 = coap_get_option_int(cpkt, COAP_OPTION_BLOCK1);
+	block2 = coap_get_option_int(cpkt, COAP_OPTION_BLOCK2);
+	size1 = coap_get_option_int(cpkt, COAP_OPTION_SIZE1);
+	size2 = coap_get_option_int(cpkt, COAP_OPTION_SIZE2);
+
+	size1 = size1 == -ENOENT ? 0 : size1;
+	size2 = size2 == -ENOENT ? 0 : size2;
+
+	if (is_request(cpkt)) {
+		r = update_control_block2(ctx, block2, size2);
+		if (r) {
+			return r;
+		}
+
+		return update_descriptive_block(ctx, block1, size1);
+	}
+
+	r = update_control_block1(ctx, block1, size1);
+	if (r) {
+		return r;
+	}
+
+	return update_descriptive_block(ctx, block2, size2);
+}
+
+size_t coap_next_block(const struct coap_packet *cpkt,
+		       struct coap_block_context *ctx)
+{
+	int block;
+
+	if (is_request(cpkt)) {
+		block = coap_get_option_int(cpkt, COAP_OPTION_BLOCK1);
+	} else {
+		block = coap_get_option_int(cpkt, COAP_OPTION_BLOCK2);
+	}
+
+	if (!GET_MORE(block)) {
+		return 0;
+	}
+
+	ctx->current += coap_block_size_to_bytes(ctx->block_size);
+
+	return ctx->current;
+}
+
+int coap_pending_init(struct coap_pending *pending,
+		      const struct coap_packet *request,
+		      const struct sockaddr *addr)
+{
+	memset(pending, 0, sizeof(*pending));
+
+	pending->id = coap_header_get_id(request);
+
+	memcpy(&pending->addr, addr, sizeof(*addr));
+
+	pending->data = request->data;
+	pending->len = request->offset;
+	pending->t0 = k_uptime_get_32();
+
+	return 0;
+}
+
+struct coap_pending *coap_pending_next_unused(
+	struct coap_pending *pendings, size_t len)
+{
+	struct coap_pending *p;
+	size_t i;
+
+	for (i = 0, p = pendings; i < len; i++, p++) {
+		if (p->timeout == 0) {
+			return p;
+		}
+	}
+
+	return NULL;
+}
+
+struct coap_reply *coap_reply_next_unused(
+	struct coap_reply *replies, size_t len)
+{
+	struct coap_reply *r;
+	size_t i;
+
+	for (i = 0, r = replies; i < len; i++, r++) {
+		if (!r->reply) {
+			return r;
+		}
+	}
+
+	return NULL;
+}
+
+static inline bool is_addr_unspecified(const struct sockaddr *addr)
+{
+	if (addr->sa_family == AF_UNSPEC) {
+		return true;
+	}
+
+	if (addr->sa_family == AF_INET6) {
+		return net_ipv6_is_addr_unspecified(
+			&(net_sin6(addr)->sin6_addr));
+	} else if (addr->sa_family == AF_INET) {
+		return net_sin(addr)->sin_addr.s4_addr32[0] == 0U;
+	}
+
+	return false;
+}
+
+struct coap_observer *coap_observer_next_unused(
+	struct coap_observer *observers, size_t len)
+{
+	struct coap_observer *o;
+	size_t i;
+
+	for (i = 0, o = observers; i < len; i++, o++) {
+		if (is_addr_unspecified(&o->addr)) {
+			return o;
+		}
+	}
+
+	return NULL;
+}
+
+struct coap_pending *coap_pending_received(
+	const struct coap_packet *response,
+	struct coap_pending *pendings, size_t len)
+{
+	struct coap_pending *p;
+	uint16_t resp_id = coap_header_get_id(response);
+	size_t i;
+
+	for (i = 0, p = pendings; i < len; i++, p++) {
+		if (!p->timeout) {
+			continue;
+		}
+
+		if (resp_id != p->id) {
+			continue;
+		}
+
+		return p;
+	}
+
+	return NULL;
+}
+
+struct coap_pending *coap_pending_next_to_expire(
+	struct coap_pending *pendings, size_t len)
+{
+	struct coap_pending *p, *found = NULL;
+	size_t i;
+	uint32_t expiry, min_expiry;
+
+	for (i = 0, p = pendings; i < len; i++, p++) {
+		if (!p->timeout) {
+			continue;
+		}
+
+		expiry = p->t0 + p->timeout;
+
+		if (!found || (int32_t)(expiry - min_expiry) < 0) {
+			min_expiry = expiry;
+			found = p;
+		}
+	}
+
+	return found;
+}
+
+/* TODO: random generated initial ACK timeout
+ * ACK_TIMEOUT < INIT_ACK_TIMEOUT < ACK_TIMEOUT * ACK_RANDOM_FACTOR
+ * where ACK_TIMEOUT = 2 and ACK_RANDOM_FACTOR = 1.5 by default
+ * Ref: https://tools.ietf.org/html/rfc7252#section-4.8
+ */
+#define INIT_ACK_TIMEOUT	CONFIG_COAP_INIT_ACK_TIMEOUT_MS
+
+static int32_t next_timeout(int32_t previous)
+{
+	switch (previous) {
+	case INIT_ACK_TIMEOUT:
+	case (INIT_ACK_TIMEOUT * 2):
+	case (INIT_ACK_TIMEOUT * 4):
+		return previous << 1;
+	case (INIT_ACK_TIMEOUT * 8):
+		/* equal value is returned to end retransmit */
+		return previous;
+	}
+
+	/* initial or unrecognized */
+	return INIT_ACK_TIMEOUT;
+}
+
+bool coap_pending_cycle(struct coap_pending *pending)
+{
+	int32_t old = pending->timeout;
+
+	pending->t0 += pending->timeout;
+	pending->timeout = next_timeout(pending->timeout);
+
+	return (old != pending->timeout);
+}
+
+void coap_pending_clear(struct coap_pending *pending)
+{
+	pending->timeout = 0;
+	pending->data = NULL;
+}
+
+void coap_pendings_clear(struct coap_pending *pendings, size_t len)
+{
+	struct coap_pending *p;
+	size_t i;
+
+	for (i = 0, p = pendings; i < len; i++, p++) {
+		coap_pending_clear(p);
+	}
+}
+
+struct coap_reply *coap_response_received(
+	const struct coap_packet *response,
+	const struct sockaddr *from,
+	struct coap_reply *replies, size_t len)
+{
+	struct coap_reply *r;
+	uint8_t token[8];
+	uint16_t id;
+	uint8_t tkl;
+	size_t i;
+
+	id = coap_header_get_id(response);
+	tkl = coap_header_get_token(response, (uint8_t *)token);
+
+	for (i = 0, r = replies; i < len; i++, r++) {
+		int age;
+
+		if ((r->id == 0U) && (r->tkl == 0U)) {
+			continue;
+		}
+
+		/* Piggybacked must match id when token is empty */
+		if ((r->id != id) && (tkl == 0U)) {
+			continue;
+		}
+
+		if (tkl > 0 && memcmp(r->token, token, tkl)) {
+			continue;
+		}
+
+		age = coap_get_option_int(response, COAP_OPTION_OBSERVE);
+		if (age > 0) {
+			/* age == 2 means that the notifications wrapped,
+			 * or this is the first one
+			 */
+			if (r->age > age && age != 2) {
+				continue;
+			}
+
+			r->age = age;
+		}
+
+		r->reply(response, r, from);
+		return r;
+	}
+
+	return NULL;
+}
+
+void coap_reply_init(struct coap_reply *reply,
+		     const struct coap_packet *request)
+{
+	uint8_t token[8];
+	uint8_t tkl;
+	int age;
+
+	reply->id = coap_header_get_id(request);
+	tkl = coap_header_get_token(request, (uint8_t *)&token);
+
+	if (tkl > 0) {
+		memcpy(reply->token, token, tkl);
+	}
+
+	reply->tkl = tkl;
+
+	age = coap_get_option_int(request, COAP_OPTION_OBSERVE);
+
+	/* It means that the request enabled observing a resource */
+	if (age == 0) {
+		reply->age = 2;
+	}
+}
+
+void coap_reply_clear(struct coap_reply *reply)
+{
+	(void)memset(reply, 0, sizeof(*reply));
+}
+
+void coap_replies_clear(struct coap_reply *replies, size_t len)
+{
+	struct coap_reply *r;
+	size_t i;
+
+	for (i = 0, r = replies; i < len; i++, r++) {
+		coap_reply_clear(r);
+	}
+}
+
+int coap_resource_notify(struct coap_resource *resource)
+{
+	struct coap_observer *o;
+
+	if (!resource->notify) {
+		return -ENOENT;
+	}
+
+	resource->age++;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&resource->observers, o, list) {
+		resource->notify(resource, o);
+	}
+
+	return 0;
+}
+
+bool coap_request_is_observe(const struct coap_packet *request)
+{
+	return coap_get_option_int(request, COAP_OPTION_OBSERVE) == 0;
+}
+
+void coap_observer_init(struct coap_observer *observer,
+			const struct coap_packet *request,
+			const struct sockaddr *addr)
+{
+	observer->tkl = coap_header_get_token(request, observer->token);
+
+	net_ipaddr_copy(&observer->addr, addr);
+}
+
+bool coap_register_observer(struct coap_resource *resource,
+			    struct coap_observer *observer)
+{
+	bool first;
+
+	sys_slist_append(&resource->observers, &observer->list);
+
+	first = resource->age == 0;
+	if (first) {
+		resource->age = 2;
+	}
+
+	return first;
+}
+
+void coap_remove_observer(struct coap_resource *resource,
+			  struct coap_observer *observer)
+{
+	sys_slist_find_and_remove(&resource->observers, &observer->list);
+}
+
+static bool sockaddr_equal(const struct sockaddr *a,
+			   const struct sockaddr *b)
+{
+	/* FIXME: Should we consider ipv6-mapped ipv4 addresses as equal to
+	 * ipv4 addresses?
+	 */
+	if (a->sa_family != b->sa_family) {
+		return false;
+	}
+
+	if (a->sa_family == AF_INET) {
+		const struct sockaddr_in *a4 = net_sin(a);
+		const struct sockaddr_in *b4 = net_sin(b);
+
+		if (a4->sin_port != b4->sin_port) {
+			return false;
+		}
+
+		return net_ipv4_addr_cmp(&a4->sin_addr, &b4->sin_addr);
+	}
+
+	if (b->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *a6 = net_sin6(a);
+		const struct sockaddr_in6 *b6 = net_sin6(b);
+
+		if (a6->sin6_port != b6->sin6_port) {
+			return false;
+		}
+
+		return net_ipv6_addr_cmp(&a6->sin6_addr, &b6->sin6_addr);
+	}
+
+	/* Invalid address family */
+	return false;
+}
+
+struct coap_observer *coap_find_observer_by_addr(
+	struct coap_observer *observers, size_t len,
+	const struct sockaddr *addr)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		struct coap_observer *o = &observers[i];
+
+		if (sockaddr_equal(&o->addr, addr)) {
+			return o;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * @brief Internal initialization function for CoAP library.
+ *
+ * Called by the network layer init procedure. Seeds the CoAP @message_id with a
+ * random number in accordance with recommendations in CoAP specification.
+ *
+ * @note This function is not exposed in a public header, as it's for internal
+ * use and should therefore not be exposed to applications.
+ *
+ * @return N/A
+ */
+void net_coap_init(void)
+{
+	/* Initialize message_id to a random number */
+	message_id = (uint16_t)sys_rand32_get();
+}
+
+uint16_t coap_next_id(void)
+{
+	return message_id++;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap_link_format.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap_link_format.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/coap/coap_link_format.c	(working copy)
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_coap, CONFIG_COAP_LOG_LEVEL);
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <zephyr/types.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <sys/byteorder.h>
+
+#include <sys/printk.h>
+
+#include <net/coap.h>
+#include <net/coap_link_format.h>
+
+static inline bool append_u8(struct coap_packet *cpkt, uint8_t data)
+{
+	if (!cpkt) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < 1) {
+		return false;
+	}
+
+	cpkt->data[cpkt->offset++] = data;
+
+	return true;
+}
+
+static inline bool append_be16(struct coap_packet *cpkt, uint16_t data)
+{
+	if (!cpkt) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < 2) {
+		return false;
+	}
+
+	cpkt->data[cpkt->offset++] = data >> 8;
+	cpkt->data[cpkt->offset++] = (uint8_t) data;
+
+	return true;
+}
+
+static inline bool append(struct coap_packet *cpkt, const uint8_t *data, uint16_t len)
+{
+	if (!cpkt || !data) {
+		return false;
+	}
+
+	if (cpkt->max_len - cpkt->offset < len) {
+		return false;
+	}
+
+	memcpy(cpkt->data + cpkt->offset, data, len);
+	cpkt->offset += len;
+
+	return true;
+}
+
+static bool match_path_uri(const char * const *path,
+			   const char *uri, uint16_t len)
+{
+	const char * const *p = NULL;
+	int i, j, k, plen;
+
+	if (!path) {
+		return false;
+	}
+
+	if (len <= 1U || uri[0] != '/') {
+		return false;
+	}
+
+	p = path;
+	plen = *p ? strlen(*p) : 0;
+	j = 0;
+
+	if (plen == 0) {
+		return false;
+	}
+
+	/* Go through uri and try to find a matching path */
+	for (i = 1; i < len; i++) {
+		while (*p) {
+			plen = strlen(*p);
+
+			k = i;
+
+			for (j = 0; j < plen; j++) {
+				if (uri[k] == '*') {
+					if ((k + 1) == len) {
+						return true;
+					}
+				}
+
+				if (uri[k] != (*p)[j]) {
+					goto next;
+				}
+
+				k++;
+			}
+
+			if (i == (k - 1) && j == plen) {
+				return true;
+			}
+
+			if (k == len && j == plen) {
+				return true;
+			}
+
+next:
+			p++;
+		}
+	}
+
+	/* Did we find the resource or not */
+	if (i == len && !*p) {
+		return false;
+	}
+
+	return true;
+}
+
+static bool match_attributes(const char * const *attributes,
+			     const struct coap_option *query)
+{
+	const char * const *attr;
+
+	/* FIXME: deal with the case when there are multiple options in a
+	 * query, for example: 'rt=lux temperature', if I want to list
+	 * resources with resource type lux or temperature.
+	 */
+	for (attr = attributes; attr && *attr; attr++) {
+		uint16_t attr_len = strlen(*attr);
+
+		if (query->len != attr_len) {
+			continue;
+		}
+
+		if (!strncmp((char *) query->value, *attr, attr_len)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool match_queries_resource(const struct coap_resource *resource,
+				   const struct coap_option *query,
+				   int num_queries)
+{
+	struct coap_core_metadata *meta = resource->user_data;
+	const char * const *attributes = NULL;
+	const int href_len = strlen("href");
+
+	if (num_queries == 0) {
+		return true;
+	}
+
+	if (meta && meta->attributes) {
+		attributes = meta->attributes;
+	}
+
+	if (!attributes) {
+		return false;
+	}
+
+	if (query->len > href_len + 1 &&
+	    !strncmp((char *) query->value, "href", href_len)) {
+		/* The stuff after 'href=' */
+		const char *uri = (char *) query->value + href_len + 1;
+		uint16_t uri_len  = query->len - (href_len + 1);
+
+		return match_path_uri(resource->path, uri, uri_len);
+	}
+
+	return match_attributes(attributes, query);
+}
+
+#if defined(CONFIG_COAP_WELL_KNOWN_BLOCK_WISE)
+
+#define MAX_BLOCK_WISE_TRANSFER_SIZE 2048
+
+enum coap_block_size default_block_size(void)
+{
+	switch (CONFIG_COAP_WELL_KNOWN_BLOCK_WISE_SIZE) {
+	case 16:
+		return COAP_BLOCK_16;
+	case 32:
+		return COAP_BLOCK_32;
+	case 64:
+		return COAP_BLOCK_64;
+	case 128:
+		return COAP_BLOCK_128;
+	case 256:
+		return COAP_BLOCK_256;
+	case 512:
+		return COAP_BLOCK_512;
+	case 1024:
+		return COAP_BLOCK_1024;
+	}
+
+	return COAP_BLOCK_64;
+}
+
+static bool append_to_coap_pkt(struct coap_packet *response,
+			       const char *str, uint16_t len,
+			       uint16_t *remaining, size_t *offset,
+			       size_t current)
+{
+	uint16_t pos = 0U;
+	bool res;
+
+	if (!*remaining) {
+		return true;
+	}
+
+	if (*offset < current) {
+		pos = current - *offset;
+
+		if (len >= pos) {
+			len -= pos;
+			*offset += pos;
+		} else {
+			*offset += len;
+			return true;
+		}
+	}
+
+	if (len > *remaining) {
+		len = *remaining;
+	}
+
+	res = append(response, str + pos, len);
+
+	*remaining -= len;
+	*offset += len;
+
+	return res;
+}
+
+static int format_uri(const char * const *path,
+		      struct coap_packet *response,
+		      uint16_t *remaining, size_t *offset,
+		      size_t current, bool *more)
+{
+	static const char prefix[] = "</";
+	const char * const *p;
+	bool res;
+
+	if (!path) {
+		return -EINVAL;
+	}
+
+	res = append_to_coap_pkt(response, &prefix[0], sizeof(prefix) - 1,
+				 remaining, offset, current);
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	if (!*remaining) {
+		*more = true;
+		return 0;
+	}
+
+	for (p = path; *p; ) {
+		uint16_t path_len = strlen(*p);
+
+		res = append_to_coap_pkt(response, *p, path_len, remaining,
+					 offset, current);
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		if (!*remaining) {
+			*more = true;
+			return 0;
+		}
+
+		p++;
+		if (!*p) {
+			continue;
+		}
+
+		res = append_to_coap_pkt(response, "/", 1, remaining, offset,
+					 current);
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		if (!*remaining) {
+			*more = true;
+			return 0;
+		}
+
+	}
+
+	res = append_to_coap_pkt(response, ">", 1, remaining, offset, current);
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	if (!*remaining) {
+		*more = true;
+		return 0;
+	}
+
+	*more = false;
+
+	return 0;
+}
+
+static int format_attributes(const char * const *attributes,
+			     struct coap_packet *response,
+			     uint16_t *remaining, size_t *offset,
+			     size_t current, bool *more)
+{
+	const char * const *attr;
+	bool res;
+
+	if (!attributes) {
+		goto terminator;
+	}
+
+	for (attr = attributes; *attr; ) {
+		int attr_len = strlen(*attr);
+
+		res = append_to_coap_pkt(response, *attr, attr_len,
+					 remaining, offset, current);
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		if (!*remaining) {
+			*more = true;
+			return 0;
+		}
+
+		attr++;
+		if (!*attr) {
+			continue;
+		}
+
+		res = append_to_coap_pkt(response, ";", 1,
+					 remaining, offset, current);
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		if (!*remaining) {
+			*more = true;
+			return 0;
+		}
+	}
+
+terminator:
+	res = append_to_coap_pkt(response, ";", 1, remaining, offset, current);
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	if (!*remaining) {
+		*more = true;
+		return 0;
+	}
+
+	*more = false;
+
+	return 0;
+}
+
+static int format_resource(const struct coap_resource *resource,
+			   struct coap_packet *response,
+			   uint16_t *remaining, size_t *offset,
+			   size_t current, bool *more)
+{
+	struct coap_core_metadata *meta = resource->user_data;
+	const char * const *attributes = NULL;
+	int r;
+
+	r = format_uri(resource->path, response, remaining,
+		       offset, current, more);
+	if (r < 0) {
+		return r;
+	}
+
+	if (!*remaining) {
+		*more = true;
+		return 0;
+	}
+
+	if (meta && meta->attributes) {
+		attributes = meta->attributes;
+	}
+
+	return format_attributes(attributes, response, remaining, offset,
+				 current, more);
+}
+
+/* coap_well_known_core_get() added Option (delta and len) with
+ * out any extended options so this function will not consider Extended
+ * options at the moment.
+ */
+int clear_more_flag(struct coap_packet *cpkt)
+{
+	uint16_t offset;
+	uint8_t opt;
+	uint8_t delta;
+	uint8_t len;
+
+	offset = cpkt->hdr_len;
+	delta = 0U;
+
+	while (1) {
+		opt = cpkt->data[offset++];
+
+		delta += ((opt & 0xF0) >> 4);
+		len = (opt & 0xF);
+
+		if (delta == COAP_OPTION_BLOCK2) {
+			break;
+		}
+
+		offset += len;
+	}
+
+	/* As per RFC 7959 Sec 2.2 : NUM filed can be on 0-3 bytes.
+	 * Skip NUM field to update M bit.
+	 */
+	if (len > 1) {
+		offset = offset + len - 1;
+	}
+
+	cpkt->data[offset] = cpkt->data[offset] & 0xF7;
+
+	return 0;
+}
+
+int coap_well_known_core_get(struct coap_resource *resource,
+			      struct coap_packet *request,
+			      struct coap_packet *response,
+			      uint8_t *data, uint16_t len)
+{
+	static struct coap_block_context ctx;
+	struct coap_option query;
+	unsigned int num_queries;
+	size_t offset;
+	uint8_t token[8];
+	uint16_t remaining;
+	uint16_t id;
+	uint8_t tkl;
+	uint8_t format;
+	int r;
+	bool more = false;
+
+	if (!resource || !request || !response || !data || !len) {
+		return -EINVAL;
+	}
+
+	if (ctx.total_size == 0) {
+		/* We have to iterate through resources and it's attributes,
+		 * total size is unknown, so initialize it to
+		 * MAX_BLOCK_WISE_TRANSFER_SIZE and update it according to
+		 * offset.
+		 */
+		coap_block_transfer_init(&ctx, default_block_size(),
+					 MAX_BLOCK_WISE_TRANSFER_SIZE);
+	}
+
+	r = coap_update_from_block(request, &ctx);
+	if (r < 0) {
+		goto end;
+	}
+
+	id = coap_header_get_id(request);
+	tkl = coap_header_get_token(request, token);
+
+	/* Per RFC 6690, Section 4.1, only one (or none) query parameter may be
+	 * provided, use the first if multiple.
+	 */
+	r = coap_find_options(request, COAP_OPTION_URI_QUERY, &query, 1);
+	if (r < 0) {
+		goto end;
+	}
+
+	num_queries = r;
+
+	r = coap_packet_init(response, data, len, 1, COAP_TYPE_ACK,
+			     tkl, token, COAP_RESPONSE_CODE_CONTENT, id);
+	if (r < 0) {
+		goto end;
+	}
+
+	format = 40U; /* application/link-format */
+
+	r = coap_packet_append_option(response, COAP_OPTION_CONTENT_FORMAT,
+				      &format, sizeof(format));
+	if (r < 0) {
+		goto end;
+	}
+
+	r = coap_append_block2_option(response, &ctx);
+	if (r < 0) {
+		goto end;
+	}
+
+	r = coap_packet_append_payload_marker(response);
+	if (r < 0) {
+		goto end;
+	}
+
+	offset = 0;
+	remaining = coap_block_size_to_bytes(ctx.block_size);
+
+	while (resource++ && resource->path) {
+		if (!remaining) {
+			more = true;
+			break;
+		}
+
+		if (!match_queries_resource(resource, &query, num_queries)) {
+			continue;
+		}
+
+		r = format_resource(resource, response, &remaining, &offset,
+				    ctx.current, &more);
+		if (r < 0) {
+			goto end;
+		}
+	}
+
+	/* Offset is the total size now, but block2 option is already
+	 * appended. So update only 'more' flag.
+	 */
+	if (!more) {
+		ctx.total_size = offset;
+		r = clear_more_flag(response);
+	}
+
+end:
+	/* So it's a last block, reset context */
+	if (!more) {
+		(void)memset(&ctx, 0, sizeof(ctx));
+	}
+
+	return r;
+}
+
+#else
+
+static int format_uri(const char * const *path, struct coap_packet *response)
+{
+	const char * const *p;
+	char *prefix = "</";
+	bool res;
+
+	if (!path) {
+		return -EINVAL;
+	}
+
+	res = append(response, (uint8_t *) prefix, strlen(prefix));
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	for (p = path; *p; ) {
+		res = append(response, (uint8_t *) *p, strlen(*p));
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		p++;
+		if (*p) {
+			res = append_u8(response, (uint8_t) '/');
+			if (!res) {
+				return -ENOMEM;
+			}
+		}
+	}
+
+	res = append_u8(response, (uint8_t) '>');
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int format_attributes(const char * const *attributes,
+			     struct coap_packet *response)
+{
+	const char * const *attr;
+	bool res;
+
+	if (!attributes) {
+		goto terminator;
+	}
+
+	for (attr = attributes; *attr; ) {
+		res = append(response, (uint8_t *) *attr, strlen(*attr));
+		if (!res) {
+			return -ENOMEM;
+		}
+
+		attr++;
+		if (*attr) {
+			res = append_u8(response, (uint8_t) ';');
+			if (!res) {
+				return -ENOMEM;
+			}
+		}
+	}
+
+terminator:
+	res = append_u8(response, (uint8_t) ';');
+	if (!res) {
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int format_resource(const struct coap_resource *resource,
+			   struct coap_packet *response)
+{
+	struct coap_core_metadata *meta = resource->user_data;
+	const char * const *attributes = NULL;
+	int r;
+
+	r = format_uri(resource->path, response);
+	if (r < 0) {
+		return r;
+	}
+
+	if (meta && meta->attributes) {
+		attributes = meta->attributes;
+	}
+
+	return format_attributes(attributes, response);
+}
+
+int coap_well_known_core_get(struct coap_resource *resource,
+			     struct coap_packet *request,
+			     struct coap_packet *response,
+			     uint8_t *data, uint16_t len)
+{
+	struct coap_option query;
+	uint8_t token[8];
+	uint16_t id;
+	uint8_t tkl;
+	uint8_t format;
+	uint8_t num_queries;
+	int r;
+
+	if (!resource || !request || !response || !data || !len) {
+		return -EINVAL;
+	}
+
+	id = coap_header_get_id(request);
+	tkl = coap_header_get_token(request, token);
+
+	/* Per RFC 6690, Section 4.1, only one (or none) query parameter may be
+	 * provided, use the first if multiple.
+	 */
+	r = coap_find_options(request, COAP_OPTION_URI_QUERY, &query, 1);
+	if (r < 0) {
+		return r;
+	}
+
+	num_queries = r;
+
+	r = coap_packet_init(response, data, len, 1, COAP_TYPE_ACK,
+			     tkl, token, COAP_RESPONSE_CODE_CONTENT, id);
+	if (r < 0) {
+		return r;
+	}
+
+	format = 40U; /* application/link-format */
+	r = coap_packet_append_option(response, COAP_OPTION_CONTENT_FORMAT,
+				      &format, sizeof(format));
+	if (r < 0) {
+		return -EINVAL;
+	}
+
+	r = coap_packet_append_payload_marker(response);
+	if (r < 0) {
+		return -EINVAL;
+	}
+
+	while (resource++ && resource->path) {
+		if (!match_queries_resource(resource, &query, num_queries)) {
+			continue;
+		}
+
+		r = format_resource(resource, response);
+		if (r < 0) {
+			return r;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+/* Exposing some of the APIs to CoAP unit tests in tests/net/lib/coap */
+#if defined(CONFIG_COAP_TEST_API_ENABLE)
+bool _coap_match_path_uri(const char * const *path,
+			  const char *uri, uint16_t len)
+{
+	return match_path_uri(path, uri, len);
+}
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/CMakeLists.txt	(working copy)
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+zephyr_library_compile_definitions_ifdef(
+  CONFIG_NEWLIB_LIBC __LINUX_ERRNO_EXTENSIONS__
+  )
+
+zephyr_library_sources_ifdef(CONFIG_NET_CONFIG_SETTINGS init.c)
+
+if(CONFIG_NET_CONFIG_SETTINGS)
+  zephyr_library_sources_ifdef(
+    CONFIG_NET_L2_IEEE802154
+    ieee802154_settings.c
+    )
+
+  zephyr_library_sources_ifdef(
+    CONFIG_NET_L2_BT
+    bt_settings.c
+  )
+endif()
+
+zephyr_library_sources_ifdef(CONFIG_NET_CONFIG_CLOCK_SNTP_INIT init_clock_sntp.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/Kconfig	(working copy)
@@ -0,0 +1,216 @@
+# Options for networking configuration
+
+# Copyright (c) 2017 Intel Corporation.
+# SPDX-License-Identifier: Apache-2.0
+
+config NET_CONFIG_AUTO_INIT
+	bool "Init networking support automatically during device startup"
+	default n if USB_DEVICE_NETWORK
+	default y
+	help
+	  If this option is set, then the networking system is automatically
+	  initialized when the device is started. If you do not wish to do
+	  this, then disable this and call net_config_init() in your application.
+
+config NET_CONFIG_INIT_PRIO
+	int "Startup priority for the network application init"
+	default 95
+	depends on NET_CONFIG_AUTO_INIT
+
+config NET_CONFIG_INIT_TIMEOUT
+	int "How long to wait for networking to be ready and available"
+	default 30
+	help
+	  The value is in seconds. If for example IPv4 address from DHCPv4 is not
+	  received within this limit, then the net_config_init() call will fail
+	  during the device startup.
+
+config NET_CONFIG_NEED_IPV6
+	bool "This application wants IPv6 support"
+	depends on NET_CONFIG_AUTO_INIT
+	select NET_IPV6
+	help
+	  The network application needs IPv6 support to function properly.
+	  This option makes sure the network application is initialized properly
+	  in order to use IPv6.
+
+config NET_CONFIG_NEED_IPV6_ROUTER
+	bool "This application wants IPv6 router to exists"
+	depends on NET_CONFIG_AUTO_INIT
+	depends on NET_IPV6
+	help
+	  The network application needs IPv6 router to exists before continuing.
+	  What this means that the application wants to wait until it receives
+	  IPv6 router advertisement message before continuing.
+
+config NET_CONFIG_NEED_IPV4
+	bool "This application wants IPv4 support"
+	depends on NET_CONFIG_AUTO_INIT
+	select NET_IPV4
+	help
+	  The network application needs IPv4 support to function properly.
+	  This option makes sure the network application is initialized properly
+	  in order to use IPv4.
+
+module = NET_CONFIG
+module-dep = NET_LOG
+module-str = Log level for network config library
+module-help = Enables net config library to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+menuconfig NET_CONFIG_SETTINGS
+	bool "Set network settings for applications"
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	help
+	  Allow IP addresses to be set in config file for
+	  networking client/server sample applications, or
+	  some link-layer dedicated settings like the channel.
+	  Beware this is not meant to be used for proper
+	  provisioning but quick sampling/testing.
+
+if NET_CONFIG_SETTINGS
+
+if NET_IPV6
+
+config NET_CONFIG_MY_IPV6_ADDR
+	string "My IPv6 address"
+	help
+	  Use 2001:db8::1 here if uncertain.
+
+config NET_CONFIG_PEER_IPV6_ADDR
+	string "Peer IPv6 address"
+	help
+	  This is only applicable in client side applications that try
+	  to establish a connection to peer host.
+	  Use 2001:db8::2 here if uncertain.
+
+endif # NET_IPV6
+
+if NET_IPV4
+
+config NET_CONFIG_MY_IPV4_ADDR
+	string "My IPv4 address"
+	help
+	  Use 192.0.2.1 here if uncertain.
+
+config NET_CONFIG_MY_IPV4_NETMASK
+	string "My IPv4 netmask"
+	default "255.255.255.0"
+	help
+	  Static netmask to use if not overridden by DHCP. Use empty value to
+	  skip setting static value.
+
+config NET_CONFIG_MY_IPV4_GW
+	string "My IPv4 gateway"
+	help
+	  Static gateway to use if not overridden by DHCP. Use empty value to
+	  skip setting static value.
+
+config NET_CONFIG_PEER_IPV4_ADDR
+	string "Peer IPv4 address"
+	help
+	  This is only applicable in client side applications that try
+	  to establish a connection to peer host.
+	  Use 192.0.2.2 here if uncertain.
+
+endif # NET_IPV4
+
+config NET_CONFIG_IEEE802154_DEV_NAME
+	string "IEEE 802.15.4 device name"
+	depends on NET_L2_IEEE802154 || IEEE802154_RAW_MODE || NET_L2_OPENTHREAD
+	help
+	  The device name to get bindings from in the sample application.
+
+if NET_L2_IEEE802154 || IEEE802154_RAW_MODE
+
+config NET_CONFIG_IEEE802154_PAN_ID
+	hex "IEEE 802.15.4 PAN ID"
+	default 0xabcd
+	help
+	  The PAN ID to use by default in the sample.
+
+config NET_CONFIG_IEEE802154_CHANNEL
+	int "IEEE 802.15.4 channel"
+	default 26
+	help
+	  The channel to use by default in the sample application.
+
+config NET_CONFIG_IEEE802154_RADIO_TX_POWER
+	int "IEEE 802.15.4 TX power in dbm"
+	default 0
+	help
+	  The TX power to use by default in the sample application.
+	  See NET_L2_IEEE802154_RADIO_DFLT_TX_POWER for more info.
+
+config NET_CONFIG_IEEE802154_SECURITY_KEY
+	string "IEEE 802.15.4 security key"
+	default "moooh!"
+	depends on NET_L2_IEEE802154_SECURITY
+	help
+	  The key string to use for the link-layer security part.
+
+config NET_CONFIG_IEEE802154_SECURITY_KEY_MODE
+	int "IEEE 802.15.4 security key mode"
+	default 0
+	range 0 0
+	depends on NET_L2_IEEE802154_SECURITY
+	help
+	  The key mode to use for the link-layer security part.
+	  Only implicit mode is supported, thus 0.
+
+config NET_CONFIG_IEEE802154_SECURITY_LEVEL
+	int "IEEE 802.15.4 security level (0-7)"
+	default 0
+	range 0 7
+	depends on NET_L2_IEEE802154_SECURITY
+	help
+	  The security level to use for the link-layer security part.
+	  0 means no security
+	  1 authentication only with a 4 bytes length tag
+	  2 authentication only with a 8 bytes length tag
+	  3 authentication only with a 16 bytes length tag
+	  4 encryption only
+	  5 encryption/authentication with a 4 bytes length tag
+	  6 encryption/authentication with a 8 bytes length tag
+	  7 encryption/authentication with a 16 bytes length tag
+
+endif # NET_L2_IEEE802154 || IEEE802154_RAW_MODE
+
+config NET_CONFIG_BT_NODE
+	bool "Enable Bluetooth node support"
+	depends on NET_L2_BT
+	select NET_L2_BT_MGMT
+	help
+	  Enables application to operate in node mode which requires GATT
+	  service to be registered and start advertising as peripheral.
+
+endif # NET_CONFIG_SETTINGS
+
+config NET_CONFIG_CLOCK_SNTP_INIT
+	bool "Initialize system clock using SNTP on application startup"
+	depends on SNTP && POSIX_CLOCK
+	help
+	  Perform an SNTP request over networking to get and absolute
+	  wall clock time, and initialize system time from it, so
+	  functions like time(), gettimeofday(), etc. returned the
+	  correct absolute time (no just time since system startup).
+	  Requires networking.
+
+if NET_CONFIG_CLOCK_SNTP_INIT
+
+config NET_CONFIG_SNTP_INIT_SERVER
+	string "SNTP server to use for system clock init"
+	default ""
+	help
+	  Zephyr does not provide default setting for this option. Each
+	  application and vendor should choose a suitable setting based
+	  on their locality, needs, and server's terms of service. See
+	  e.g. server information at
+	  https://support.ntp.org/bin/view/Servers/NTPPoolServers
+
+config NET_CONFIG_SNTP_INIT_TIMEOUT
+	int "SNTP timeout to init system clock (ms)"
+	default 3000
+
+endif # NET_CONFIG_CLOCK_SNTP_INIT
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.h	(working copy)
@@ -0,0 +1,13 @@
+/* IEEE 802.15.4 settings header */
+
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_NET_L2_BT) && defined(CONFIG_NET_CONFIG_SETTINGS)
+int z_net_config_bt_setup(void);
+#else
+#define z_net_config_bt_setup(...) 0
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/bt_settings.c	(working copy)
@@ -0,0 +1,62 @@
+/* IEEE 802.15.4 settings code */
+
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <errno.h>
+
+#include <net/net_if.h>
+#include <net/net_core.h>
+#include <net/net_mgmt.h>
+#include <net/bt.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+#include <bluetooth/gatt.h>
+
+#if defined(CONFIG_NET_CONFIG_BT_NODE)
+#define ADV_STR "on"
+
+BT_GATT_SERVICE_DEFINE(ipss_svc,
+	/* IP Support Service Declaration */
+	BT_GATT_PRIMARY_SERVICE(BT_UUID_IPSS),
+);
+#endif
+
+int z_net_config_bt_setup(void)
+{
+	struct net_if *iface;
+	const struct device *dev;
+	int err;
+
+	err = bt_enable(NULL);
+	if (err < 0 && err != -EALREADY) {
+		return err;
+	}
+
+	dev = device_get_binding("net_bt");
+	if (!dev) {
+		return -ENODEV;
+	}
+
+	iface = net_if_lookup_by_dev(dev);
+	if (!iface) {
+		return -EINVAL;
+	}
+
+#if defined(CONFIG_NET_CONFIG_BT_NODE)
+	if (net_mgmt(NET_REQUEST_BT_ADVERTISE, iface, ADV_STR,
+		     sizeof(ADV_STR))) {
+		return -EINVAL;
+	}
+#endif
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.h	(working copy)
@@ -0,0 +1,13 @@
+/* IEEE 802.15.4 settings header */
+
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if defined(CONFIG_NET_L2_IEEE802154) && defined(CONFIG_NET_CONFIG_SETTINGS)
+int z_net_config_ieee802154_setup(void);
+#else
+#define z_net_config_ieee802154_setup(...) 0
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/ieee802154_settings.c	(working copy)
@@ -0,0 +1,67 @@
+/* IEEE 802.15.4 settings code */
+
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <errno.h>
+
+#include <net/net_if.h>
+#include <net/net_core.h>
+#include <net/net_mgmt.h>
+#include <net/ieee802154_mgmt.h>
+
+int z_net_config_ieee802154_setup(void)
+{
+	uint16_t channel = CONFIG_NET_CONFIG_IEEE802154_CHANNEL;
+	uint16_t pan_id = CONFIG_NET_CONFIG_IEEE802154_PAN_ID;
+	int16_t tx_power = CONFIG_NET_CONFIG_IEEE802154_RADIO_TX_POWER;
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	struct ieee802154_security_params sec_params = {
+		.key = CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY,
+		.key_len = sizeof(CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY),
+		.key_mode = CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY_MODE,
+		.level = CONFIG_NET_CONFIG_IEEE802154_SECURITY_LEVEL,
+	};
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+	struct net_if *iface;
+	const struct device *dev;
+
+	dev = device_get_binding(CONFIG_NET_CONFIG_IEEE802154_DEV_NAME);
+	if (!dev) {
+		return -ENODEV;
+	}
+
+	iface = net_if_lookup_by_dev(dev);
+	if (!iface) {
+		return -EINVAL;
+	}
+
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID,
+		     iface, &pan_id, sizeof(uint16_t)) ||
+	    net_mgmt(NET_REQUEST_IEEE802154_SET_CHANNEL,
+		     iface, &channel, sizeof(uint16_t)) ||
+	    net_mgmt(NET_REQUEST_IEEE802154_SET_TX_POWER,
+		     iface, &tx_power, sizeof(int16_t))) {
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
+	if (net_mgmt(NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS, iface,
+		     &sec_params, sizeof(struct ieee802154_security_params))) {
+		return -EINVAL;
+	}
+#endif /* CONFIG_NET_L2_IEEE802154_SECURITY */
+
+	net_if_up(iface);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init.c	(working copy)
@@ -0,0 +1,498 @@
+/* init.c */
+
+/*
+ * Copyright (c) 2017 Intel Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <init.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <logging/log_backend.h>
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/net_if.h>
+#include <net/dhcpv4.h>
+#include <net/net_mgmt.h>
+#include <net/dns_resolve.h>
+
+#include <net/net_config.h>
+
+#include "ieee802154_settings.h"
+#include "bt_settings.h"
+
+extern const struct log_backend *log_backend_net_get(void);
+extern int net_init_clock_via_sntp(void);
+
+static K_SEM_DEFINE(waiter, 0, 1);
+static struct k_sem counter;
+static atomic_t services_flags;
+
+#if defined(CONFIG_NET_NATIVE)
+static struct net_mgmt_event_callback mgmt_iface_cb;
+#endif
+
+static inline void services_notify_ready(int flags)
+{
+	atomic_or(&services_flags, flags);
+	k_sem_give(&waiter);
+}
+
+static inline bool services_are_ready(int flags)
+{
+	return (atomic_get(&services_flags) & flags) == flags;
+}
+
+#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4)
+static struct net_mgmt_event_callback mgmt4_cb;
+
+static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
+				  uint32_t mgmt_event,
+				  struct net_if *iface)
+{
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+	char hr_addr[NET_IPV4_ADDR_LEN];
+#endif
+	int i;
+
+	if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
+		return;
+	}
+
+	for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
+		struct net_if_addr *if_addr =
+					&iface->config.ip.ipv4->unicast[i];
+
+		if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) {
+			continue;
+		}
+
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+		NET_INFO("IPv4 address: %s",
+			 log_strdup(net_addr_ntop(AF_INET,
+						  &if_addr->address.in_addr,
+						  hr_addr, sizeof(hr_addr))));
+		NET_INFO("Lease time: %u seconds",
+			 iface->config.dhcpv4.lease_time);
+		NET_INFO("Subnet: %s",
+			 log_strdup(net_addr_ntop(AF_INET,
+				       &iface->config.ip.ipv4->netmask,
+				       hr_addr, sizeof(hr_addr))));
+		NET_INFO("Router: %s",
+			 log_strdup(net_addr_ntop(AF_INET,
+						  &iface->config.ip.ipv4->gw,
+						  hr_addr, sizeof(hr_addr))));
+#endif
+		break;
+	}
+
+	services_notify_ready(NET_CONFIG_NEED_IPV4);
+}
+
+static void setup_dhcpv4(struct net_if *iface)
+{
+	NET_INFO("Running dhcpv4 client...");
+
+	net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler,
+				     NET_EVENT_IPV4_ADDR_ADD);
+	net_mgmt_add_event_callback(&mgmt4_cb);
+
+	net_dhcpv4_start(iface);
+}
+
+#else
+#define setup_dhcpv4(...)
+#endif /* CONFIG_NET_DHCPV4 */
+
+#if defined(CONFIG_NET_NATIVE_IPV4) && !defined(CONFIG_NET_DHCPV4) && \
+	!defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR)
+#error "You need to define an IPv4 address or enable DHCPv4!"
+#endif
+
+#if defined(CONFIG_NET_NATIVE_IPV4) && defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR)
+
+static void setup_ipv4(struct net_if *iface)
+{
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+	char hr_addr[NET_IPV4_ADDR_LEN];
+#endif
+	struct in_addr addr;
+
+	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_ADDR) == 1) {
+		/* Empty address, skip setting ANY address in this case */
+		return;
+	}
+
+	if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &addr)) {
+		NET_ERR("Invalid address: %s", CONFIG_NET_CONFIG_MY_IPV4_ADDR);
+		return;
+	}
+
+#if defined(CONFIG_NET_DHCPV4)
+	/* In case DHCP is enabled, make the static address tentative,
+	 * to allow DHCP address to override it. This covers a usecase
+	 * of "there should be a static IP address for DHCP-less setups",
+	 * but DHCP should override it (to use it, NET_IF_MAX_IPV4_ADDR
+	 * should be set to 1). There is another usecase: "there should
+	 * always be static IP address, and optionally, DHCP address".
+	 * For that to work, NET_IF_MAX_IPV4_ADDR should be 2 (or more).
+	 * (In this case, an app will need to bind to the needed addr
+	 * explicitly.)
+	 */
+	net_if_ipv4_addr_add(iface, &addr, NET_ADDR_OVERRIDABLE, 0);
+#else
+	net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
+#endif
+
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+	NET_INFO("IPv4 address: %s",
+		 log_strdup(net_addr_ntop(AF_INET, &addr, hr_addr,
+					  sizeof(hr_addr))));
+#endif
+
+	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_NETMASK) > 1) {
+		/* If not empty */
+		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_NETMASK,
+				  &addr)) {
+			NET_ERR("Invalid netmask: %s",
+				CONFIG_NET_CONFIG_MY_IPV4_NETMASK);
+		} else {
+			net_if_ipv4_set_netmask(iface, &addr);
+		}
+	}
+
+	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_GW) > 1) {
+		/* If not empty */
+		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_GW,
+				  &addr)) {
+			NET_ERR("Invalid gateway: %s",
+				CONFIG_NET_CONFIG_MY_IPV4_GW);
+		} else {
+			net_if_ipv4_set_gw(iface, &addr);
+		}
+	}
+
+	services_notify_ready(NET_CONFIG_NEED_IPV4);
+}
+
+#else
+#define setup_ipv4(...)
+#endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */
+
+#if defined(CONFIG_NET_NATIVE_IPV6)
+#if !defined(CONFIG_NET_CONFIG_MY_IPV6_ADDR)
+#error "You need to define an IPv6 address!"
+#endif
+
+static struct net_mgmt_event_callback mgmt6_cb;
+static struct in6_addr laddr;
+
+static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
+			       uint32_t mgmt_event, struct net_if *iface)
+{
+	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
+	int i;
+
+	if (!ipv6) {
+		return;
+	}
+
+	if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
+		/* save the last added IP address for this interface */
+		for (i = NET_IF_MAX_IPV6_ADDR - 1; i >= 0; i--) {
+			if (ipv6->unicast[i].is_used) {
+				memcpy(&laddr,
+				       &ipv6->unicast[i].address.in6_addr,
+				       sizeof(laddr));
+				break;
+			}
+		}
+	}
+
+	if (mgmt_event == NET_EVENT_IPV6_DAD_SUCCEED) {
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+		char hr_addr[NET_IPV6_ADDR_LEN];
+#endif
+		struct net_if_addr *ifaddr;
+
+		ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
+		if (!ifaddr ||
+		    !(net_ipv6_addr_cmp(&ifaddr->address.in6_addr, &laddr) &&
+		      ifaddr->addr_state == NET_ADDR_PREFERRED)) {
+			/* Address is not yet properly setup */
+			return;
+		}
+
+#if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
+		NET_INFO("IPv6 address: %s",
+			 log_strdup(net_addr_ntop(AF_INET6, &laddr, hr_addr,
+						  NET_IPV6_ADDR_LEN)));
+#endif
+
+		services_notify_ready(NET_CONFIG_NEED_IPV6);
+	}
+
+	if (mgmt_event == NET_EVENT_IPV6_ROUTER_ADD) {
+		services_notify_ready(NET_CONFIG_NEED_ROUTER);
+	}
+}
+
+static void setup_ipv6(struct net_if *iface, uint32_t flags)
+{
+	struct net_if_addr *ifaddr;
+	uint32_t mask = NET_EVENT_IPV6_DAD_SUCCEED;
+
+	if (sizeof(CONFIG_NET_CONFIG_MY_IPV6_ADDR) == 1) {
+		/* Empty address, skip setting ANY address in this case */
+		goto exit;
+	}
+
+	if (net_addr_pton(AF_INET6, CONFIG_NET_CONFIG_MY_IPV6_ADDR, &laddr)) {
+		NET_ERR("Invalid address: %s", CONFIG_NET_CONFIG_MY_IPV6_ADDR);
+		/* some interfaces may add IP address later */
+		mask |= NET_EVENT_IPV6_ADDR_ADD;
+	}
+
+	if (flags & NET_CONFIG_NEED_ROUTER) {
+		mask |= NET_EVENT_IPV6_ROUTER_ADD;
+	}
+
+	net_mgmt_init_event_callback(&mgmt6_cb, ipv6_event_handler, mask);
+	net_mgmt_add_event_callback(&mgmt6_cb);
+
+	/*
+	 * check for CMD_ADDR_ADD bit here, NET_EVENT_IPV6_ADDR_ADD is
+	 * a combination of _NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD
+	 * so it will always return != NET_EVENT_IPV6_CMD_ADDR_ADD if any other
+	 * event is set (for instance NET_EVENT_IPV6_ROUTER_ADD)
+	 */
+	if ((mask & NET_EVENT_IPV6_CMD_ADDR_ADD) ==
+	    NET_EVENT_IPV6_CMD_ADDR_ADD) {
+		ifaddr = net_if_ipv6_addr_add(iface, &laddr,
+					      NET_ADDR_MANUAL, 0);
+		if (!ifaddr) {
+			NET_ERR("Cannot add %s to interface",
+				CONFIG_NET_CONFIG_MY_IPV6_ADDR);
+		}
+	}
+
+exit:
+
+#if !defined(CONFIG_NET_IPV6_DAD)
+	services_notify_ready(NET_CONFIG_NEED_IPV6);
+#endif
+
+	return;
+}
+
+#else
+#define setup_ipv6(...)
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_NATIVE)
+static void iface_up_handler(struct net_mgmt_event_callback *cb,
+			     uint32_t mgmt_event, struct net_if *iface)
+{
+	if (mgmt_event == NET_EVENT_IF_UP) {
+		NET_INFO("Interface %d (%p) coming up",
+			 net_if_get_by_iface(iface), iface);
+
+		k_sem_reset(&counter);
+		k_sem_give(&waiter);
+	}
+}
+
+static bool check_interface(struct net_if *iface)
+{
+	if (net_if_is_up(iface)) {
+		k_sem_reset(&counter);
+		k_sem_give(&waiter);
+		return true;
+	}
+
+	NET_INFO("Waiting interface %d (%p) to be up...",
+		 net_if_get_by_iface(iface), iface);
+
+	net_mgmt_init_event_callback(&mgmt_iface_cb, iface_up_handler,
+				     NET_EVENT_IF_UP);
+	net_mgmt_add_event_callback(&mgmt_iface_cb);
+
+	return false;
+}
+#else
+static bool check_interface(struct net_if *iface)
+{
+	k_sem_reset(&counter);
+	k_sem_give(&waiter);
+
+	return true;
+}
+#endif
+
+int net_config_init_by_iface(struct net_if *iface, const char *app_info,
+			     uint32_t flags, int32_t timeout)
+{
+#define LOOP_DIVIDER 10
+	int loop = timeout / LOOP_DIVIDER;
+	int count;
+
+	if (app_info) {
+		NET_INFO("%s", log_strdup(app_info));
+	}
+
+	if (!iface) {
+		iface = net_if_get_default();
+	}
+
+	if (timeout < 0) {
+		count = -1;
+	} else if (timeout == 0) {
+		count = 0;
+	} else {
+		count = timeout / 1000 + 1;
+	}
+
+	/* First make sure that network interface is up */
+	if (check_interface(iface) == false) {
+		k_sem_init(&counter, 1, UINT_MAX);
+
+		while (count-- > 0) {
+			if (!k_sem_count_get(&counter)) {
+				break;
+			}
+
+			if (k_sem_take(&waiter, K_MSEC(loop))) {
+				if (!k_sem_count_get(&counter)) {
+					break;
+				}
+			}
+		}
+
+		/* If the above while() loop timeouted, reset the count so that
+		 * the while() loop below will not wait more.
+		 */
+		if (timeout > 0 && count < 0) {
+			count = 0;
+		}
+
+#if defined(CONFIG_NET_NATIVE)
+		net_mgmt_del_event_callback(&mgmt_iface_cb);
+#endif
+	}
+
+	if (count == 0) {
+		/* Network interface did not come up. We will not try
+		 * to setup things in that case.
+		 */
+		NET_ERR("Timeout while waiting network %s", "interface");
+		return -ENETDOWN;
+	}
+
+	setup_ipv4(iface);
+	setup_dhcpv4(iface);
+	setup_ipv6(iface, flags);
+
+	/* Loop here until we are ready to continue. As we might need
+	 * to wait multiple events, sleep smaller amounts of data.
+	 */
+	while (!services_are_ready(flags) && count-- > 0) {
+		k_sem_take(&waiter, K_MSEC(loop));
+	}
+
+	if (count == -1 && timeout > 0) {
+		NET_ERR("Timeout while waiting network %s", "setup");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int net_config_init(const char *app_info, uint32_t flags,
+		    int32_t timeout)
+{
+	return net_config_init_by_iface(NULL, app_info, flags, timeout);
+}
+
+int net_config_init_app(const struct device *dev, const char *app_info)
+{
+	struct net_if *iface = NULL;
+	uint32_t flags = 0U;
+	int ret;
+
+	if (dev) {
+		iface = net_if_lookup_by_dev(dev);
+		if (iface == NULL) {
+			NET_WARN("No interface for device %p, using default",
+				 dev);
+		}
+	}
+
+#if defined(CONFIG_NET_IPV6)
+	/* IEEE 802.15.4 is only usable if IPv6 is enabled */
+	ret = z_net_config_ieee802154_setup();
+	if (ret < 0) {
+		NET_ERR("Cannot setup IEEE 802.15.4 interface (%d)", ret);
+	}
+
+	ret = z_net_config_bt_setup();
+	if (ret < 0) {
+		NET_ERR("Cannot setup Bluetooth interface (%d)", ret);
+	}
+#endif
+
+	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6)) {
+		flags |= NET_CONFIG_NEED_IPV6;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6_ROUTER)) {
+		flags |= NET_CONFIG_NEED_ROUTER;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV4)) {
+		flags |= NET_CONFIG_NEED_IPV4;
+	}
+
+	/* Initialize the application automatically if needed */
+	ret = net_config_init_by_iface(iface, app_info, flags,
+				CONFIG_NET_CONFIG_INIT_TIMEOUT * MSEC_PER_SEC);
+	if (ret < 0) {
+		NET_ERR("Network initialization failed (%d)", ret);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_CONFIG_CLOCK_SNTP_INIT)) {
+		net_init_clock_via_sntp();
+	}
+
+	/* This is activated late as it requires the network stack to be up
+	 * and running before syslog messages can be sent to network.
+	 */
+	if (IS_ENABLED(CONFIG_LOG_BACKEND_NET)) {
+		const struct log_backend *backend = log_backend_net_get();
+
+		if (!log_backend_is_active(backend)) {
+			log_backend_activate(backend, NULL);
+		}
+	}
+
+	return ret;
+}
+
+#if defined(CONFIG_NET_CONFIG_AUTO_INIT)
+static int init_app(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	(void)net_config_init_app(NULL, "Initializing network");
+
+	return 0;
+}
+
+SYS_INIT(init_app, APPLICATION, CONFIG_NET_CONFIG_INIT_PRIO);
+#endif /* CONFIG_NET_CONFIG_AUTO_INIT */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init_clock_sntp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init_clock_sntp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/config/init_clock_sntp.c	(working copy)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/sntp.h>
+#include <posix/time.h>
+
+int net_init_clock_via_sntp(void)
+{
+	struct sntp_time ts;
+	struct timespec tspec;
+	int res = sntp_simple(CONFIG_NET_CONFIG_SNTP_INIT_SERVER,
+			      CONFIG_NET_CONFIG_SNTP_INIT_TIMEOUT, &ts);
+
+	if (res < 0) {
+		LOG_ERR("Cannot set time using SNTP");
+		return res;
+	}
+
+	tspec.tv_sec = ts.seconds;
+	tspec.tv_nsec = ((uint64_t)ts.fraction * (1000 * 1000 * 1000)) >> 32;
+	res = clock_settime(CLOCK_REALTIME, &tspec);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/CMakeLists.txt	(working copy)
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+
+zephyr_library()
+zephyr_library_sources(
+	conn_mgr.c
+	events_handler.c
+	)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/Kconfig	(working copy)
@@ -0,0 +1,37 @@
+# Copyright (c) 2019 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_CONNECTION_MANAGER
+	bool "Enable network connection manager [EXPERIMENTAL]"
+	depends on NET_IPV6 || NET_IPV4
+	select NET_MGMT
+	select NET_MGMT_EVENT
+	select NET_MGMT_EVENT_INFO
+	help
+	  When enabled, this will start the connection manager that will
+	  listen to network interface and IP events in order to verify
+	  whether an interface is connected or not. It will then raise
+	  L4 events "connected" or "disconnected" depending on the result.
+
+if NET_CONNECTION_MANAGER
+
+module = NET_CONNECTION_MANAGER
+module-dep = NET_LOG
+module-str = Log level for connection manager
+module-help = Enables connection manager code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config NET_CONNECTION_MANAGER_STACK_SIZE
+	int "Size of the stack allocated for the connection manager"
+	default 512
+	help
+	  Sets the stack size which will be used by the connection manager
+	  thread.
+
+config NET_CONNECTION_MANAGER_PRIORITY
+	int "Thread starting priority"
+	default 0
+	help
+	  This sets the starting priority of the connection manager thread.
+
+endif # NET_CONNECTION_MANAGER
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.h	(working copy)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __CONN_MGR_H__
+#define __CONN_MGR_H__
+
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+#define CONN_MGR_IFACE_MAX		MAX(CONFIG_NET_IF_MAX_IPV6_COUNT, \
+					    CONFIG_NET_IF_MAX_IPV4_COUNT)
+#elif defined(CONFIG_NET_IPV6)
+#define CONN_MGR_IFACE_MAX		CONFIG_NET_IF_MAX_IPV6_COUNT
+#else
+#define CONN_MGR_IFACE_MAX		CONFIG_NET_IF_MAX_IPV4_COUNT
+#endif
+
+#define NET_STATE_IFACE_UP		BIT(0)
+#define NET_STATE_IPV6_ADDR_SET		BIT(1)
+#define NET_STATE_IPV6_DAD_OK		BIT(2)
+#define NET_STATE_IPV4_ADDR_SET		BIT(3)
+
+#define NET_STATE_CONNECTED		BIT(14)
+#define NET_STATE_CHANGED		BIT(15)
+
+#define CONN_MGR_IFACE_EVENTS_MASK	(NET_EVENT_IF_DOWN          |	\
+					 NET_EVENT_IF_UP)
+
+#define CONN_MGR_IPV6_EVENTS_MASK	(NET_EVENT_IPV6_ADDR_ADD    |	\
+					 NET_EVENT_IPV6_ADDR_DEL    |	\
+					 NET_EVENT_IPV6_DAD_SUCCEED |	\
+					 NET_EVENT_IPV6_DAD_FAILED)
+
+#define CONN_MGR_IPV4_EVENTS_MASK	(NET_EVENT_IPV4_ADDR_ADD    |	\
+					 NET_EVENT_IPV4_ADDR_DEL)
+
+#define CONN_MGR_IPV6_STATUS_MASK	(NET_STATE_IPV6_ADDR_SET    |	\
+					 NET_STATE_IPV6_DAD_OK)
+
+#define CONN_MGR_IPV4_STATUS_MASK	(NET_STATE_IPV4_ADDR_SET)
+
+extern struct k_sem conn_mgr_lock;
+
+enum net_conn_mgr_state {
+	NET_CONN_MGR_STATE_DISCONNECTED	= 0,
+	NET_CONN_MGR_STATE_CONNECTED	= 1,
+};
+
+void conn_mgr_init_events_handler(void);
+
+#endif /* __CONN_MGR_H__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/conn_mgr.c	(working copy)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(conn_mgr, CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL);
+
+#include <init.h>
+#include <kernel.h>
+#include <errno.h>
+#include <net/net_core.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+
+#include <conn_mgr.h>
+
+uint16_t iface_states[CONN_MGR_IFACE_MAX];
+
+K_SEM_DEFINE(conn_mgr_lock, 1, UINT_MAX);
+
+static enum net_conn_mgr_state conn_mgr_iface_status(int index)
+{
+	if (iface_states[index] & NET_STATE_IFACE_UP) {
+		return NET_CONN_MGR_STATE_CONNECTED;
+	}
+
+	return NET_CONN_MGR_STATE_DISCONNECTED;
+}
+
+#if defined(CONFIG_NET_IPV6)
+static enum net_conn_mgr_state conn_mgr_ipv6_status(int index)
+{
+	if ((iface_states[index] & CONN_MGR_IPV6_STATUS_MASK) ==
+	    CONN_MGR_IPV6_STATUS_MASK) {
+		NET_DBG("IPv6 connected on iface index %u", index + 1);
+		return NET_CONN_MGR_STATE_CONNECTED;
+	}
+
+	return NET_CONN_MGR_STATE_DISCONNECTED;
+}
+#else
+#define conn_mgr_ipv6_status(...) NET_CONN_MGR_STATE_CONNECTED
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+static enum net_conn_mgr_state conn_mgr_ipv4_status(int index)
+{
+	if ((iface_states[index] & CONN_MGR_IPV4_STATUS_MASK) ==
+	    CONN_MGR_IPV4_STATUS_MASK) {
+		NET_DBG("IPv4 connected on iface index %u", index + 1);
+		return NET_CONN_MGR_STATE_CONNECTED;
+	}
+
+	return NET_CONN_MGR_STATE_DISCONNECTED;
+}
+#else
+#define conn_mgr_ipv4_status(...) NET_CONN_MGR_STATE_CONNECTED
+#endif /* CONFIG_NET_IPV4 */
+
+static void conn_mgr_notify_status(int index)
+{
+	struct net_if *iface = net_if_get_by_index(index + 1);
+
+	if (iface_states[index] & NET_STATE_CONNECTED) {
+		NET_DBG("Iface %p connected", iface);
+		net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, iface);
+	} else {
+		NET_DBG("Iface %p disconnected", iface);
+		net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, iface);
+	}
+}
+
+static void conn_mgr_act_on_changes(void)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
+		enum net_conn_mgr_state state;
+
+		if (!(iface_states[idx] & NET_STATE_CHANGED)) {
+			continue;
+		}
+
+		state = NET_CONN_MGR_STATE_CONNECTED;
+
+		state &= conn_mgr_iface_status(idx);
+		if (state) {
+			enum net_conn_mgr_state ip_state =
+				NET_CONN_MGR_STATE_DISCONNECTED;
+
+			if (IS_ENABLED(CONFIG_NET_IPV6)) {
+				ip_state |= conn_mgr_ipv6_status(idx);
+			}
+
+			if (IS_ENABLED(CONFIG_NET_IPV4)) {
+				ip_state |= conn_mgr_ipv4_status(idx);
+			}
+
+			state &= ip_state;
+		}
+
+		iface_states[idx] &= ~NET_STATE_CHANGED;
+
+		if (state == NET_CONN_MGR_STATE_CONNECTED &&
+		    !(iface_states[idx] & NET_STATE_CONNECTED)) {
+			iface_states[idx] |= NET_STATE_CONNECTED;
+
+			conn_mgr_notify_status(idx);
+		} else if (state != NET_CONN_MGR_STATE_CONNECTED &&
+			   (iface_states[idx] & NET_STATE_CONNECTED)) {
+			iface_states[idx] &= ~NET_STATE_CONNECTED;
+
+			conn_mgr_notify_status(idx);
+		}
+	}
+}
+
+static void conn_mgr_initial_state(struct net_if *iface)
+{
+	int idx = net_if_get_by_iface(iface) - 1;
+
+	if (net_if_is_up(iface)) {
+		NET_DBG("Iface %p UP", iface);
+		iface_states[idx] = NET_STATE_IFACE_UP;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_NATIVE_IPV6)) {
+		if (net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
+			NET_DBG("IPv6 addr set");
+			iface_states[idx] |= NET_STATE_IPV6_ADDR_SET |
+						NET_STATE_IPV6_DAD_OK;
+		} else if (net_if_ipv6_get_global_addr(NET_ADDR_TENTATIVE,
+						       &iface)) {
+			iface_states[idx] |= NET_STATE_IPV6_ADDR_SET;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_NET_NATIVE_IPV4)) {
+		if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) {
+			NET_DBG("IPv4 addr set");
+			iface_states[idx] |= NET_STATE_IPV4_ADDR_SET;
+		}
+
+	}
+
+	iface_states[idx] |= NET_STATE_CHANGED;
+}
+
+static void conn_mgr_init_cb(struct net_if *iface, void *user_data)
+{
+	ARG_UNUSED(user_data);
+
+	conn_mgr_initial_state(iface);
+}
+
+static void conn_mgr(void)
+{
+	conn_mgr_init_events_handler();
+
+	net_if_foreach(conn_mgr_init_cb, NULL);
+
+	NET_DBG("Connection Manager started");
+
+	while (true) {
+		k_sem_take(&conn_mgr_lock, K_FOREVER);
+
+		conn_mgr_act_on_changes();
+	}
+}
+
+K_THREAD_DEFINE(conn_mgr_thread, CONFIG_NET_CONNECTION_MANAGER_STACK_SIZE,
+		(k_thread_entry_t)conn_mgr, NULL, NULL, NULL,
+		K_PRIO_COOP(2), 0, 0);
+
+void net_conn_mgr_resend_status(void)
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) {
+		conn_mgr_notify_status(idx);
+	}
+}
+
+static int conn_mgr_init(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	k_thread_start(conn_mgr_thread);
+
+	return 0;
+}
+
+SYS_INIT(conn_mgr_init, APPLICATION, CONFIG_NET_CONNECTION_MANAGER_PRIORITY);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/events_handler.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/events_handler.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/conn_mgr/events_handler.c	(working copy)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(conn_mgr, CONFIG_NET_CONNECTION_MANAGER_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/net_if.h>
+#include <net/net_mgmt.h>
+
+#include <conn_mgr.h>
+
+extern uint16_t iface_states[CONN_MGR_IFACE_MAX];
+
+static struct net_mgmt_event_callback iface_events_cb;
+static struct net_mgmt_event_callback ipv6_events_cb;
+static struct net_mgmt_event_callback ipv4_events_cb;
+
+static void conn_mgr_iface_events_handler(struct net_mgmt_event_callback *cb,
+					  uint32_t mgmt_event,
+					  struct net_if *iface)
+{
+	int idx;
+
+	NET_DBG("Iface event %u received on iface %p", mgmt_event, iface);
+
+	if ((mgmt_event & CONN_MGR_IFACE_EVENTS_MASK) != mgmt_event) {
+		return;
+	}
+
+	idx = net_if_get_by_iface(iface) - 1;
+
+	NET_DBG("Iface index %u", idx);
+
+	switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
+	case NET_EVENT_IF_CMD_DOWN:
+		iface_states[idx] &= ~NET_STATE_IFACE_UP;
+		break;
+	case NET_EVENT_IF_CMD_UP:
+		iface_states[idx] |= NET_STATE_IFACE_UP;
+		break;
+	default:
+		return;
+	}
+
+	iface_states[idx] |= NET_STATE_CHANGED;
+	k_sem_give(&conn_mgr_lock);
+}
+
+#if defined(CONFIG_NET_IPV6)
+static void conn_mgr_ipv6_events_handler(struct net_mgmt_event_callback *cb,
+					 uint32_t mgmt_event,
+					 struct net_if *iface)
+{
+	int idx;
+
+	NET_DBG("IPv6 event %u received on iface %p", mgmt_event, iface);
+
+	if ((mgmt_event & CONN_MGR_IPV6_EVENTS_MASK) != mgmt_event) {
+		return;
+	}
+
+	idx = net_if_get_by_iface(iface) - 1;
+
+	NET_DBG("Iface index %u", idx);
+
+	switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
+	case NET_EVENT_IPV6_CMD_ADDR_ADD:
+		iface_states[idx] |= NET_STATE_IPV6_ADDR_SET;
+		break;
+	case NET_EVENT_IPV6_CMD_ADDR_DEL:
+		if (net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
+			break;
+		}
+
+		iface_states[idx] &= ~NET_STATE_IPV6_ADDR_SET;
+		break;
+	case NET_EVENT_IPV6_CMD_DAD_SUCCEED:
+		iface_states[idx] |= NET_STATE_IPV6_DAD_OK;
+		break;
+	case NET_EVENT_IPV6_CMD_DAD_FAILED:
+		if (net_if_ipv6_get_global_addr(NET_ADDR_PREFERRED, &iface)) {
+			break;
+		}
+
+		iface_states[idx] &= ~NET_STATE_IPV6_DAD_OK;
+		break;
+	default:
+		return;
+	}
+
+	iface_states[idx] |= NET_STATE_CHANGED;
+	k_sem_give(&conn_mgr_lock);
+}
+#else
+static inline
+void conn_mgr_ipv6_events_handler(struct net_mgmt_event_callback *cb,
+				  uint32_t mgmt_event,
+				  struct net_if *iface)
+{
+	ARG_UNUSED(cb);
+	ARG_UNUSED(mgmt_event);
+	ARG_UNUSED(iface);
+}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+static void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb,
+					 uint32_t mgmt_event,
+					 struct net_if *iface)
+{
+	int idx;
+
+	NET_DBG("IPv4 event %u received on iface %p", mgmt_event, iface);
+
+	if ((mgmt_event & CONN_MGR_IPV4_EVENTS_MASK) != mgmt_event) {
+		return;
+	}
+
+	idx = net_if_get_by_iface(iface) - 1;
+
+	NET_DBG("Iface index %u", idx);
+
+	switch (NET_MGMT_GET_COMMAND(mgmt_event)) {
+	case NET_EVENT_IPV4_CMD_ADDR_ADD:
+		iface_states[idx] |= NET_STATE_IPV4_ADDR_SET;
+		break;
+	case NET_EVENT_IPV4_CMD_ADDR_DEL:
+		if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) {
+			break;
+		}
+
+		iface_states[idx] &= ~NET_STATE_IPV4_ADDR_SET;
+		break;
+	default:
+		return;
+	}
+
+	iface_states[idx] |= NET_STATE_CHANGED;
+	k_sem_give(&conn_mgr_lock);
+}
+#else
+static inline
+void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb,
+				  uint32_t mgmt_event,
+				  struct net_if *iface)
+{
+	ARG_UNUSED(cb);
+	ARG_UNUSED(mgmt_event);
+	ARG_UNUSED(iface);
+}
+#endif /* CONFIG_NET_IPV4 */
+
+void conn_mgr_init_events_handler(void)
+{
+	net_mgmt_init_event_callback(&iface_events_cb,
+				     conn_mgr_iface_events_handler,
+				     CONN_MGR_IFACE_EVENTS_MASK);
+	net_mgmt_add_event_callback(&iface_events_cb);
+
+	if (IS_ENABLED(CONFIG_NET_IPV6)) {
+		net_mgmt_init_event_callback(&ipv6_events_cb,
+					     conn_mgr_ipv6_events_handler,
+					     CONN_MGR_IPV6_EVENTS_MASK);
+		net_mgmt_add_event_callback(&ipv6_events_cb);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4)) {
+		net_mgmt_init_event_callback(&ipv4_events_cb,
+					     conn_mgr_ipv4_events_handler,
+					     CONN_MGR_IPV4_EVENTS_MASK);
+		net_mgmt_add_event_callback(&ipv4_events_cb);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/CMakeLists.txt	(working copy)
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+
+zephyr_library()
+zephyr_library_sources(dns_pack.c)
+
+zephyr_library_sources_ifdef(CONFIG_DNS_RESOLVER resolve.c)
+
+if(CONFIG_MDNS_RESPONDER)
+  zephyr_library_sources(mdns_responder.c)
+  zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+endif()
+
+if(CONFIG_LLMNR_RESPONDER)
+  zephyr_library_sources(llmnr_responder.c)
+  zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+endif()
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/Kconfig	(working copy)
@@ -0,0 +1,200 @@
+# Copyright (c) 2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config DNS_RESOLVER
+	bool "DNS resolver"
+	help
+	  This option enables the DNS client side support for Zephyr
+
+if DNS_RESOLVER
+
+config MDNS_RESOLVER
+	bool "Enable mDNS support"
+	help
+	  This option enables multicast DNS client side support.
+	  See RFC 6762 for details.
+
+config LLMNR_RESOLVER
+	bool "Enable LLMNR support"
+	help
+	  This option enables link local multicast name resolution client side
+	  support. See RFC 4795 for details. LLMNR is typically used by Windows
+	  hosts. If you enable this option, then the DNS requests are ONLY sent
+	  to LLMNR well known multicast address 224.0.0.252:5355 or
+	  [ff02::1:3]:5355 and other DNS server addresses are ignored.
+
+
+config DNS_RESOLVER_ADDITIONAL_BUF_CTR
+	int "Additional DNS buffers"
+	default 0
+	help
+	  Number of additional buffers available for the DNS resolver.
+	  The DNS resolver requires at least one buffer. This option
+	  enables additional buffers required for multiple concurrent
+	  DNS connections.
+
+config DNS_RESOLVER_ADDITIONAL_QUERIES
+	int "Additional DNS queries"
+	range 0 2
+	default 1
+	help
+	  Number of additional DNS queries that the DNS resolver may
+	  generate when the RR ANSWER only contains CNAME(s).
+	  The maximum value of this variable is constrained to avoid
+	  'alias loops'.
+
+config DNS_RESOLVER_MAX_SERVERS
+	int "Number of DNS server addresses"
+	range 1 NET_MAX_CONTEXTS
+	default 1
+	help
+	  Max number of DNS servers that we can connect to. Normally one
+	  DNS server is enough. Each connection to DNS server will use one
+	  network context.
+
+menuconfig DNS_SERVER_IP_ADDRESSES
+	bool "Set DNS server IP addresses"
+	help
+	  Allow DNS IP addresses to be set in config file for
+	  networking applications.
+
+if DNS_SERVER_IP_ADDRESSES
+
+config DNS_SERVER1
+	string "DNS server 1"
+	help
+	  DNS server IP address 1. The address can be either IPv4 or IPv6
+	  address. An optional port number can be given.
+	  Following syntax is supported:
+	  192.0.2.1
+	  192.0.2.1:5353
+	  2001:db8::1
+	  [2001:db8::1]:5353
+	  It is not mandatory to use this Kconfig option at all.
+	  The one calling dns_resolve_init() can use this option or not
+	  to populate the server list. If the DNS server addresses are
+	  set here, then we automatically create default DNS context
+	  for the user.
+
+config DNS_SERVER2
+	string "DNS server 2"
+	help
+	  See help in "DNS server 1" option.
+
+config DNS_SERVER3
+	string "DNS server 3"
+	help
+	  See help in "DNS server 1" option.
+
+config DNS_SERVER4
+	string "DNS server 4"
+	help
+	  See help in "DNS server 1" option.
+
+config DNS_SERVER5
+	string "DNS server 5"
+	help
+	  See help in "DNS server 1" option.
+
+endif # DNS_SERVER_IP_ADDRESSES
+
+config DNS_NUM_CONCUR_QUERIES
+	int "Number of simultaneous DNS queries per one DNS context"
+	default 1
+	help
+	  This defines how many concurrent DNS queries can be generated using
+	  same DNS context. Normally 1 is a good default value.
+
+module = DNS_RESOLVER
+module-dep = NET_LOG
+module-str = Log level for DNS resolver
+module-help = Enables DNS resolver code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # DNS_RESOLVER
+
+config MDNS_RESPONDER
+	bool "mDNS responder"
+	select NET_IPV6_MLD if NET_IPV6
+	depends on NET_HOSTNAME_ENABLE
+	help
+	  This option enables the mDNS responder support for Zephyr.
+	  It will listen well-known address ff02::fb and 224.0.0.251.
+	  Currently this only returns IP address information.
+	  You must set CONFIG_NET_HOSTNAME to some meaningful value and
+	  then mDNS will start to respond to <hostname>.local mDNS queries.
+	  See RFC 6762 for more details about mDNS.
+
+if MDNS_RESPONDER
+
+config MDNS_RESPONDER_TTL
+	int "Time-to-Live of returned DNS name"
+	default 600
+	help
+	  DNS answers will use the TTL (in seconds).
+
+config MDNS_RESPONDER_INIT_PRIO
+	int "Startup priority for the mDNS responder init"
+	default 96
+	help
+	  Note that if NET_CONFIG_AUTO_INIT is enabled, then this value
+	  should be bigger than its value.
+
+module = MDNS_RESPONDER
+module-dep = NET_LOG
+module-str = Log level for mDNS responder
+module-help = Enables mDNS responder code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config MDNS_RESOLVER_ADDITIONAL_BUF_CTR
+	int "Additional DNS buffers"
+	default 0
+	help
+	  Number of additional buffers available for the mDNS responder.
+
+endif # MDNS_RESPONDER
+
+config LLMNR_RESPONDER
+	bool "LLMNR responder"
+	select NET_IPV6_MLD if NET_IPV6
+	depends on NET_HOSTNAME_ENABLE
+	help
+	  This option enables the LLMNR responder support for Zephyr.
+	  It will listen well-known address ff02::1:3 and 224.0.0.252.
+	  Currently this only returns IP address information.
+	  You must set CONFIG_NET_HOSTNAME to some meaningful value and
+	  then LLMNR will start to respond to <hostname> LLMNR queries.
+	  Note that LLMNR queries should only contain single-label names
+	  so there should be NO dot (".") in the name (RFC 4795 ch 3).
+	  Current implementation does not support TCP.
+	  See RFC 4795 for more details about LLMNR.
+
+if LLMNR_RESPONDER
+
+config LLMNR_RESPONDER_TTL
+	int "Time-to-Live of returned DNS name"
+	default 30
+	help
+	  DNS answers will use the TTL (in seconds). A default value is 30
+	  seconds as recommended by RFC 4795 chapter 2.8
+
+config LLMNR_RESPONDER_INIT_PRIO
+	int "Startup priority for the LLMNR responder init"
+	default 96
+	help
+	  Note that if NET_CONFIG_AUTO_INIT is enabled, then this value
+	  should be bigger than its value.
+
+module = LLMNR_RESPONDER
+module-dep = NET_LOG
+module-str = Log level for LLMNR responder
+module-help = Enables LLMNR responder code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config LLMNR_RESOLVER_ADDITIONAL_BUF_CTR
+	int "Additional DNS buffers"
+	default 0
+	help
+	  Number of additional buffers available for the LLMNR responder.
+
+endif # LLMNR_RESPONDER
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_internal.h	(working copy)
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/types.h>
+#include <net/buf.h>
+#include <net/dns_resolve.h>
+
+#include "dns_pack.h"
+
+int dns_validate_msg(struct dns_resolve_context *ctx,
+		     struct dns_msg_t *dns_msg,
+		     uint16_t *dns_id,
+		     int *query_idx,
+		     struct net_buf *dns_cname,
+		     uint16_t *query_hash);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.h	(working copy)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _DNS_PACK_H_
+#define _DNS_PACK_H_
+
+#include <net/net_ip.h>
+#include <net/buf.h>
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <errno.h>
+
+/* See RFC 1035, 4.1.1 Header section format
+ * DNS Message Header is always 12 bytes
+ */
+#define DNS_MSG_HEADER_SIZE	12
+
+/* This is the label's length octet, see 4.1.2. Question section format */
+#define DNS_LABEL_LEN_SIZE	1
+#define DNS_LABEL_MAX_SIZE	63
+#define DNS_ANSWER_MIN_SIZE	12
+#define DNS_COMMON_UINT_SIZE	2
+
+#define DNS_HEADER_ID_LEN	2
+#define DNS_HEADER_FLAGS_LEN	2
+#define DNS_QTYPE_LEN		2
+#define DNS_QCLASS_LEN		2
+#define DNS_QDCOUNT_LEN		2
+#define DNS_ANCOUNT_LEN		2
+#define DNS_NSCOUNT_LEN		2
+#define DNS_ARCOUNT_LEN		2
+#define DNS_TTL_LEN		4
+#define DNS_RDLENGTH_LEN	2
+
+#define NS_CMPRSFLGS    0xc0   /* DNS name compression */
+
+/* RFC 1035 '4.1.1. Header section format' defines the following flags:
+ * QR, Opcode, AA, TC, RD, RA, Z and RCODE.
+ * This implementation only uses RD (Recursion Desired).
+ */
+#define DNS_RECURSION		1
+
+/* These two defines represent the 3rd and 4th bytes of the DNS msg header.
+ * See RFC 1035, 4.1.1. Header section format.
+ */
+#define DNS_FLAGS1		DNS_RECURSION	/* QR, Opcode, AA, and TC = 0 */
+#define DNS_FLAGS2		0		/* RA, Z and RCODE = 0 */
+
+/**
+ * DNS message structure for DNS responses
+ *
+ * Structure that points to the buffer containing the DNS message. It also
+ * contains some decodified message's properties that can not be recovered
+ * easily:
+ * - cname_offset
+ * - query_offset
+ * - answer_offset:
+ *     + response_type: It indicates the response's content type. It could be
+ *       an IP address, a CNAME with IP (two answers), a CNAME with no IP
+ *       address. See enum dns_response_type for more details.
+ *     + response_position: this is an offset. It holds the starting byte of
+ *       the field containing the desired info. For example an IPv4 address.
+ *     + response_length: this is an offset. It holds the response's length.
+ */
+struct dns_msg_t {
+	uint8_t *msg;
+
+	int response_type;
+	uint16_t response_position;
+	uint16_t response_length;
+
+	uint16_t query_offset;
+	uint16_t answer_offset;
+	uint16_t msg_size;
+};
+
+#define DNS_MSG_INIT(b, s)	{.msg = b, .msg_size = s,	\
+				 .response_type = -EINVAL}
+
+
+enum dns_rr_type {
+	DNS_RR_TYPE_INVALID = 0,
+	DNS_RR_TYPE_A	= 1,		/* IPv4  */
+	DNS_RR_TYPE_CNAME = 5,		/* CNAME */
+	DNS_RR_TYPE_AAAA = 28		/* IPv6  */
+};
+
+enum dns_response_type {
+	DNS_RESPONSE_INVALID = -EINVAL,
+	DNS_RESPONSE_IP,
+	DNS_RESPONSE_CNAME_WITH_IP,
+	DNS_RESPONSE_CNAME_NO_IP
+};
+
+enum dns_class {
+	DNS_CLASS_INVALID = 0,
+	DNS_CLASS_IN,
+};
+
+enum dns_msg_type {
+	DNS_QUERY = 0,
+	DNS_RESPONSE
+};
+
+enum dns_header_rcode {
+	DNS_HEADER_NOERROR = 0,
+	DNS_HEADER_FORMATERROR,
+	DNS_HEADER_SERVERFAILURE,
+	DNS_HEADER_NAMEERROR,
+	DNS_HEADER_NOTIMPLEMENTED,
+	DNS_HEADER_REFUSED
+};
+
+/** It returns the ID field in the DNS msg header	*/
+static inline int dns_header_id(uint8_t *header)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(header)));
+}
+
+/* inline unpack routines are used to unpack data from network
+ * order to cpu. Similar routines without the unpack prefix are
+ * used for cpu to network order.
+ */
+static inline int dns_unpack_header_id(uint8_t *header)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(header)));
+}
+
+/** It returns the QR field in the DNS msg header	*/
+static inline int dns_header_qr(uint8_t *header)
+{
+	return ((*(header + 2)) & 0x80) ? 1 : 0;
+}
+
+/** It returns the OPCODE field in the DNS msg header	*/
+static inline int dns_header_opcode(uint8_t *header)
+{
+	return ((*(header + 2)) & 0x70) >> 1;
+}
+
+/** It returns the AA field in the DNS msg header	*/
+static inline int dns_header_aa(uint8_t *header)
+{
+	return ((*(header + 2)) & 0x04) ? 1 : 0;
+}
+
+/** It returns the TC field in the DNS msg header	*/
+static inline int dns_header_tc(uint8_t *header)
+{
+	return ((*(header + 2)) & 0x02) ? 1 : 0;
+}
+
+/** It returns the RD field in the DNS msg header	*/
+static inline int dns_header_rd(uint8_t *header)
+{
+	return ((*(header + 2)) & 0x01) ? 1 : 0;
+}
+
+/** It returns the RA field in the DNS msg header	*/
+static inline int dns_header_ra(uint8_t *header)
+{
+	return ((*(header + 3)) & 0x80) >> 7;
+}
+
+/** It returns the Z field in the DNS msg header	*/
+static inline int dns_header_z(uint8_t *header)
+{
+	return ((*(header + 3)) & 0x70) >> 4;
+}
+
+/** It returns the RCODE field in the DNS msg header	*/
+static inline int dns_header_rcode(uint8_t *header)
+{
+	return ((*(header + 3)) & 0x0F);
+}
+
+/** It returns the QDCOUNT field in the DNS msg header	*/
+static inline int dns_header_qdcount(uint8_t *header)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(header + 4)));
+}
+
+static inline int dns_unpack_header_qdcount(uint8_t *header)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(header + 4)));
+}
+
+/** It returns the ANCOUNT field in the DNS msg header	*/
+static inline int dns_header_ancount(uint8_t *header)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(header + 6)));
+}
+
+static inline int dns_unpack_header_ancount(uint8_t *header)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(header + 6)));
+}
+
+/** It returns the NSCOUNT field in the DNS msg header	*/
+static inline int dns_header_nscount(uint8_t *header)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(header + 8)));
+}
+
+/** It returns the ARCOUNT field in the DNS msg header	*/
+static inline int dns_header_arcount(uint8_t *header)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(header + 10)));
+}
+
+static inline int dns_query_qtype(uint8_t *question)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(question + 0)));
+}
+
+static inline int dns_unpack_query_qtype(const uint8_t *question)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(question + 0)));
+}
+
+static inline int dns_query_qclass(uint8_t *question)
+{
+	return htons(UNALIGNED_GET((uint16_t *)(question + 2)));
+}
+
+static inline int dns_unpack_query_qclass(const uint8_t *question)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(question + 2)));
+}
+
+static inline int dns_answer_type(uint16_t dname_size, uint8_t *answer)
+{
+	/* 4.1.3. Resource record format */
+	return ntohs(UNALIGNED_GET((uint16_t *)(answer + dname_size + 0)));
+}
+
+static inline int dns_answer_class(uint16_t dname_size, uint8_t *answer)
+{
+	/* 4.1.3. Resource record format */
+	return ntohs(UNALIGNED_GET((uint16_t *)(answer + dname_size + 2)));
+}
+
+static inline int dns_answer_ttl(uint16_t dname_size, uint8_t *answer)
+{
+	return ntohl(UNALIGNED_GET((uint32_t *)(answer + dname_size + 4)));
+}
+
+static inline int dns_answer_rdlength(uint16_t dname_size,
+					     uint8_t *answer)
+{
+	return ntohs(UNALIGNED_GET((uint16_t *)(answer + dname_size + 8)));
+}
+
+/**
+ * @brief Packs a QNAME
+ *
+ * @param len Bytes used by this function
+ * @param buf Buffer
+ * @param sizeof Buffer's size
+ * @param domain_name Something like www.example.com
+ * @retval 0 on success
+ * @retval -ENOMEM if there is no enough space to store the resultant QNAME
+ * @retval -EINVAL if an invalid parameter was passed as an argument
+ */
+int dns_msg_pack_qname(uint16_t *len, uint8_t *buf, uint16_t size,
+		       const char *domain_name);
+
+/**
+ * @brief Unpacks an answer message
+ *
+ * @param dns_msg Structure
+ * @param dname_ptr An index to the previous CNAME. For example for the
+ *        first answer, ptr must be 0x0c, the DNAME at the question.
+ * @param ttl TTL answer parameter.
+ * @retval 0 on success
+ * @retval -ENOMEM on error
+ */
+int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, uint32_t *ttl);
+
+/**
+ * @brief Unpacks the header's response.
+ *
+ * @param msg Structure containing the response.
+ * @param src_id Transaction id, it must match the id used in the query
+ *        datagram sent to the DNS server.
+ * @retval 0 on success
+ * @retval -ENOMEM if the buffer in msg has no enough space to store the header.
+ *         The header is always 12 bytes length.
+ * @retval -EINVAL if the src_id does not match the header's id, or if the
+ *         header's QR value is not DNS_RESPONSE or if the header's OPCODE
+ *         value is not DNS_QUERY, or if the header's Z value is not 0 or if
+ *         the question counter is not 1 or the answer counter is less than 1.
+ * @retval RFC 1035 RCODEs (> 0) 1 Format error, 2 Server failure, 3 Name Error,
+ *         4 Not Implemented and 5 Refused.
+ */
+int dns_unpack_response_header(struct dns_msg_t *msg, int src_id);
+
+/**
+ * @brief Packs the query message
+ *
+ * @param buf Buffer that will contain the resultant query
+ * @param len Number of bytes used to encode the query
+ * @param size Buffer size
+ * @param qname Domain name represented as a sequence of labels.
+ *        See RFC 1035, 4.1.2. Question section format.
+ * @param qname_len Number of octets in qname.
+ * @param id Transaction Identifier
+ * @param qtype Query type: AA, AAAA. See enum dns_rr_type
+ * @retval 0 on success
+ * @retval On error, a negative value is returned.
+ *         See: dns_msg_pack_query_header and  dns_msg_pack_qname.
+ */
+int dns_msg_pack_query(uint8_t *buf, uint16_t *len, uint16_t size,
+		       uint8_t *qname, uint16_t qname_len, uint16_t id,
+		       enum dns_rr_type qtype);
+
+/**
+ * @brief Unpacks the response's query.
+ *
+ * @details RFC 1035 states that the response's query comes after the first
+ *          12 bytes i.e., after the message's header. This function computes
+ *          the answer_offset field.
+ *
+ * @param dns_msg Structure containing the message.
+ * @retval 0 on success
+ * @retval -ENOMEM if the null label is not found after traversing the buffer
+ *         or if QCLASS and QTYPE are not found.
+ * @retval -EINVAL if QTYPE is not "A" (IPv4) or "AAAA" (IPv6) or if QCLASS
+ *         is not "IN".
+ */
+int dns_unpack_response_query(struct dns_msg_t *dns_msg);
+
+/**
+ * @brief Copies the qname from dns_msg to buf
+ *
+ * @details This routine implements the algorithm described in RFC 1035, 4.1.4.
+ *          Message compression to copy the qname (perhaps containing pointers
+ *          with offset) to the linear buffer buf. Pointers are removed and
+ *          only the "true" labels are copied.
+ *
+ * @param buf Output buffer
+ * @param len Output buffer's length
+ * @param size Output buffer's size
+ * @param dns_msg Structure containing the message
+ * @param pos QNAME's position in dns_msg->msg
+ * @retval 0 on success
+ * @retval -EINVAL if an invalid parameter was passed as an argument
+ * @retval -ENOMEM if the label's size is corrupted
+ */
+int dns_copy_qname(uint8_t *buf, uint16_t *len, uint16_t size,
+		   struct dns_msg_t *dns_msg, uint16_t pos);
+
+/**
+ * @brief Unpacks the mDNS query. This is special version for multicast DNS
+ *        as it skips checks to various fields as described in RFC 6762
+ *        chapter 18.
+ *
+ * @param msg Structure containing the response.
+ * @param src_id Transaction id, this is returned to the caller.
+ * @retval 0 on success, <0 if error
+ * @retval -ENOMEM if the buffer in msg has no enough space to store the header.
+ *         The header is always 12 bytes length.
+ * @retval -EINVAL if the src_id does not match the header's id, or if the
+ *         header's QR value is not DNS_RESPONSE or if the header's OPCODE
+ *         value is not DNS_QUERY, or if the header's Z value is not 0 or if
+ *         the question counter is not 1 or the answer counter is less than 1.
+ * @retval RFC 1035 RCODEs (> 0) 1 Format error, 2 Server failure, 3 Name Error,
+ *         4 Not Implemented and 5 Refused.
+ */
+int mdns_unpack_query_header(struct dns_msg_t *msg, uint16_t *src_id);
+
+static inline int llmnr_unpack_query_header(struct dns_msg_t *msg,
+					    uint16_t *src_id)
+{
+	return mdns_unpack_query_header(msg, src_id);
+}
+
+/**
+ * @brief Unpacks the query.
+ *
+ * @param dns_msg Structure containing the message.
+ * @param buf Result buf
+ * @param qtype Query type is returned to caller
+ * @param qclass Query class is returned to caller
+ * @retval 0 on success
+ * @retval -ENOMEM if the null label is not found after traversing the buffer
+ *         or if QCLASS and QTYPE are not found.
+ * @retval -EINVAL if QTYPE is not "A" (IPv4) or "AAAA" (IPv6) or if QCLASS
+ *         is not "IN".
+ */
+int dns_unpack_query(struct dns_msg_t *dns_msg, struct net_buf *buf,
+		     enum dns_rr_type *qtype,
+		     enum dns_class *qclass);
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/dns_pack.c	(working copy)
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <net/buf.h>
+
+#include "dns_pack.h"
+
+#include "dns_internal.h"
+
+static inline uint16_t dns_strlen(const char *str)
+{
+	if (str == NULL) {
+		return 0;
+	}
+	return (uint16_t)strlen(str);
+}
+
+int dns_msg_pack_qname(uint16_t *len, uint8_t *buf, uint16_t size,
+		       const char *domain_name)
+{
+	uint16_t dn_size;
+	uint16_t lb_start;
+	uint16_t lb_index;
+	uint16_t lb_size;
+	uint16_t i;
+
+	lb_start = 0U;
+	lb_index = 1U;
+	lb_size = 0U;
+
+	dn_size = dns_strlen(domain_name);
+	if (dn_size == 0U) {
+		return -EINVAL;
+	}
+
+	/* traverse the domain name str, including the null-terminator :) */
+	for (i = 0U; i < dn_size + 1; i++) {
+		if (lb_index >= size) {
+			return -ENOMEM;
+		}
+
+		switch (domain_name[i]) {
+		default:
+			buf[lb_index] = domain_name[i];
+			lb_size += 1U;
+			break;
+		case '.':
+			buf[lb_start] = lb_size;
+			lb_size = 0U;
+			lb_start = lb_index;
+			break;
+		case '\0':
+			buf[lb_start] = lb_size;
+			buf[lb_index] = 0U;
+			break;
+		}
+		lb_index += 1U;
+	}
+
+	*len = lb_index;
+
+	return 0;
+}
+
+static inline void set_dns_msg_response(struct dns_msg_t *dns_msg, int type,
+					uint16_t pos, uint16_t len)
+{
+	dns_msg->response_type = type;
+	dns_msg->response_position = pos;
+	dns_msg->response_length = len;
+}
+
+/*
+ * Skip encoded FQDN in DNS message.
+ * Returns size in bytes of encoded FQDN, or negative error code.
+ */
+static int skip_fqdn(uint8_t *answer, int buf_sz)
+{
+	int i = 0;
+
+	while (1) {
+		if (i >= buf_sz) {
+			return -EINVAL;
+		}
+
+		if (answer[i] == 0) {
+			i += 1;
+			break;
+		} else if (answer[i] >= 0xc0) {
+			i += 2;
+			if (i > buf_sz) {
+				return -EINVAL;
+			}
+			break;
+		} else if (answer[i] < DNS_LABEL_MAX_SIZE) {
+			i += answer[i] + 1;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	return i;
+}
+
+int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, uint32_t *ttl)
+{
+	int dname_len;
+	uint16_t rem_size;
+	uint16_t pos;
+	uint16_t len;
+	uint8_t *answer;
+
+	answer = dns_msg->msg + dns_msg->answer_offset;
+
+	dname_len = skip_fqdn(answer,
+			      dns_msg->msg_size - dns_msg->answer_offset);
+	if (dname_len < 0) {
+		return dname_len;
+	}
+
+	/*
+	 * We need to be sure this buffer has enough space
+	 * to contain the answer.
+	 *
+	 * size: dname_size + type + class + ttl + rdlength + rdata
+	 *            2     +   2  +   2   +  4  +     2    +  ?
+	 *
+	 * So, answer size >= 12
+	 *
+	 * See RFC-1035 4.1.3. Resource record format
+	 */
+	rem_size = dns_msg->msg_size - dname_len;
+	if (rem_size < 2 + 2 + 4 + 2) {
+		return -EINVAL;
+	}
+
+	/* Only DNS_CLASS_IN answers. If mDNS is enabled, strip away the
+	 * Cache-Flush bit (highest one).
+	 */
+	if ((dns_answer_class(dname_len, answer) &
+	     (IS_ENABLED(CONFIG_MDNS_RESOLVER) ? 0x7fff : 0xffff))
+							!= DNS_CLASS_IN) {
+		return -EINVAL;
+	}
+
+	/* TTL value */
+	*ttl = dns_answer_ttl(dname_len, answer);
+	len = dns_answer_rdlength(dname_len, answer);
+	pos = dns_msg->answer_offset + dname_len +
+		DNS_COMMON_UINT_SIZE + /* class length */
+		DNS_COMMON_UINT_SIZE + /* type length */
+		DNS_TTL_LEN +
+		DNS_RDLENGTH_LEN;
+
+	switch (dns_answer_type(dname_len, answer)) {
+	case DNS_RR_TYPE_A:
+	case DNS_RR_TYPE_AAAA:
+		set_dns_msg_response(dns_msg, DNS_RESPONSE_IP, pos, len);
+		return 0;
+
+	case DNS_RR_TYPE_CNAME:
+		set_dns_msg_response(dns_msg, DNS_RESPONSE_CNAME_NO_IP,
+				     pos, len);
+		return 0;
+
+	default:
+		/* malformed dns answer */
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int dns_unpack_response_header(struct dns_msg_t *msg, int src_id)
+{
+	uint8_t *dns_header;
+	uint16_t size;
+	int qdcount;
+	int ancount;
+	int rc;
+
+	dns_header = msg->msg;
+	size = msg->msg_size;
+
+	if (size < DNS_MSG_HEADER_SIZE) {
+		return -ENOMEM;
+	}
+
+	if (dns_unpack_header_id(dns_header) != src_id) {
+		return -EINVAL;
+	}
+
+	if (dns_header_qr(dns_header) != DNS_RESPONSE) {
+		return -EINVAL;
+	}
+
+	if (dns_header_opcode(dns_header) != DNS_QUERY) {
+		return -EINVAL;
+	}
+
+	if (dns_header_z(dns_header) != 0) {
+		return -EINVAL;
+	}
+
+	rc = dns_header_rcode(dns_header);
+	switch (rc) {
+	case DNS_HEADER_NOERROR:
+		break;
+	default:
+		return rc;
+
+	}
+
+	qdcount = dns_unpack_header_qdcount(dns_header);
+	ancount = dns_unpack_header_ancount(dns_header);
+
+	/* For mDNS (when src_id == 0) the query count is 0 so accept
+	 * the packet in that case.
+	 */
+	if ((qdcount < 1 && src_id > 0) || ancount < 1) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dns_msg_pack_query_header(uint8_t *buf, uint16_t size, uint16_t id)
+{
+	uint16_t offset;
+
+	if (size < DNS_MSG_HEADER_SIZE) {
+		return -ENOMEM;
+	}
+
+	UNALIGNED_PUT(htons(id), (uint16_t *)(buf));
+
+	/* RD = 1, TC = 0, AA = 0, Opcode = 0, QR = 0 <-> 0x01 (1B)
+	 * RCode = 0, Z = 0, RA = 0		      <-> 0x00 (1B)
+	 *
+	 * QDCOUNT = 1				      <-> 0x0001 (2B)
+	 */
+
+	offset = DNS_HEADER_ID_LEN;
+	/* Split the following assignements just in case we need to alter
+	 * the flags in future releases
+	 */
+	*(buf + offset) = DNS_FLAGS1;		/* QR, Opcode, AA, TC and RD */
+	*(buf + offset + 1) = DNS_FLAGS2;	/* RA, Z and RCODE */
+
+	offset += DNS_HEADER_FLAGS_LEN;
+	/* set question counter */
+	UNALIGNED_PUT(htons(1), (uint16_t *)(buf + offset));
+
+	offset += DNS_QDCOUNT_LEN;
+	/* set answer and ns rr */
+	UNALIGNED_PUT(0, (uint32_t *)(buf + offset));
+
+	offset += DNS_ANCOUNT_LEN + DNS_NSCOUNT_LEN;
+	/* set the additional records */
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+
+	return 0;
+}
+
+int dns_msg_pack_query(uint8_t *buf, uint16_t *len, uint16_t size,
+		       uint8_t *qname, uint16_t qname_len, uint16_t id,
+		       enum dns_rr_type qtype)
+{
+	uint16_t msg_size;
+	uint16_t offset;
+	int rc;
+
+	msg_size = DNS_MSG_HEADER_SIZE + DNS_QTYPE_LEN + DNS_QCLASS_LEN;
+	if (msg_size + qname_len > size) {
+		return -ENOMEM;
+	}
+
+	rc = dns_msg_pack_query_header(buf, size, id);
+	if (rc != 0) {
+		return rc;
+	}
+
+	offset = DNS_MSG_HEADER_SIZE;
+	memcpy(buf + offset, qname, qname_len);
+
+	offset += qname_len;
+
+	/* QType */
+	UNALIGNED_PUT(htons(qtype), (uint16_t *)(buf + offset + 0));
+	offset += DNS_QTYPE_LEN;
+
+	/* QClass */
+	UNALIGNED_PUT(htons(DNS_CLASS_IN), (uint16_t *)(buf + offset));
+
+	*len = offset + DNS_QCLASS_LEN;
+
+	return 0;
+}
+
+static int dns_find_null(int *qname_size, uint8_t *buf, uint16_t size)
+{
+	*qname_size = 0;
+	while (*qname_size < size) {
+		if (buf[(*qname_size)++] == 0x00) {
+			return 0;
+		}
+	}
+
+	return -ENOMEM;
+}
+
+int dns_unpack_response_query(struct dns_msg_t *dns_msg)
+{
+	uint8_t *dns_query;
+	uint8_t *buf;
+	int remaining_size;
+	int qname_size;
+	int offset;
+	int rc;
+
+	dns_msg->query_offset = DNS_MSG_HEADER_SIZE;
+	dns_query = dns_msg->msg + dns_msg->query_offset;
+	remaining_size = dns_msg->msg_size - dns_msg->query_offset;
+
+	rc = dns_find_null(&qname_size, dns_query, remaining_size);
+	if (rc != 0) {
+		return rc;
+	}
+
+	/* header already parsed + qname size */
+	offset = dns_msg->query_offset + qname_size;
+
+	/* 4 bytes more due to qtype and qclass */
+	offset += DNS_QTYPE_LEN + DNS_QCLASS_LEN;
+	if (offset >= dns_msg->msg_size) {
+		return -ENOMEM;
+	}
+
+	buf = dns_query + qname_size;
+	if (dns_unpack_query_qtype(buf) != DNS_RR_TYPE_A &&
+	    dns_unpack_query_qtype(buf) != DNS_RR_TYPE_AAAA) {
+		return -EINVAL;
+	}
+
+	if (dns_unpack_query_qclass(buf) != DNS_CLASS_IN) {
+		return -EINVAL;
+	}
+
+	dns_msg->answer_offset = dns_msg->query_offset + qname_size +
+				 DNS_QTYPE_LEN + DNS_QCLASS_LEN;
+
+	return 0;
+}
+
+int dns_copy_qname(uint8_t *buf, uint16_t *len, uint16_t size,
+		   struct dns_msg_t *dns_msg, uint16_t pos)
+{
+	uint16_t msg_size = dns_msg->msg_size;
+	uint8_t *msg = dns_msg->msg;
+	uint16_t lb_size;
+	int rc = -EINVAL;
+
+	*len = 0U;
+
+	while (1) {
+		if (pos >= msg_size) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		lb_size = msg[pos];
+
+		/* pointer */
+		if (lb_size > DNS_LABEL_MAX_SIZE) {
+			uint8_t mask = DNS_LABEL_MAX_SIZE;
+
+			if (pos + 1 >= msg_size) {
+				rc = -ENOMEM;
+				break;
+			}
+
+			/* See: RFC 1035, 4.1.4. Message compression */
+			pos = ((msg[pos] & mask) << 8) + msg[pos + 1];
+
+			continue;
+		}
+
+		/* validate that the label (i.e. size + elements),
+		 * fits the current msg buffer
+		 */
+		if (DNS_LABEL_LEN_SIZE + lb_size > size - *len) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		/* copy the lb_size value and label elements */
+		memcpy(buf + *len, msg + pos, DNS_LABEL_LEN_SIZE + lb_size);
+		/* update destination buffer len */
+		*len += DNS_LABEL_LEN_SIZE + lb_size;
+		/* update msg ptr position */
+		pos += DNS_LABEL_LEN_SIZE + lb_size;
+
+		/* The domain name terminates with the zero length octet
+		 * for the null label of the root
+		 */
+		if (lb_size == 0U) {
+			rc = 0;
+			break;
+		}
+	}
+
+	return rc;
+}
+
+int mdns_unpack_query_header(struct dns_msg_t *msg, uint16_t *src_id)
+{
+	uint8_t *dns_header;
+	uint16_t size;
+	int qdcount;
+
+	dns_header = msg->msg;
+	size = msg->msg_size;
+
+	if (size < DNS_MSG_HEADER_SIZE) {
+		return -ENOMEM;
+	}
+
+	if (dns_header_qr(dns_header) != DNS_QUERY) {
+		return -EINVAL;
+	}
+
+	if (dns_header_opcode(dns_header) != DNS_QUERY) {
+		return -EINVAL;
+	}
+
+	if (dns_header_opcode(dns_header) != 0) {
+		return -EINVAL;
+	}
+
+	if (dns_header_rcode(dns_header) != 0) {
+		return -EINVAL;
+	}
+
+	qdcount = dns_unpack_header_qdcount(dns_header);
+	if (qdcount < 1) {
+		return -EINVAL;
+	}
+
+	if (src_id) {
+		*src_id = dns_unpack_header_id(dns_header);
+	}
+
+	msg->query_offset = DNS_MSG_HEADER_SIZE;
+
+	return qdcount;
+}
+
+/* Returns the length of the unpacked name */
+static int dns_unpack_name(const uint8_t *msg, int maxlen, const uint8_t *src,
+			   struct net_buf *buf, const uint8_t **eol)
+{
+	int dest_size = net_buf_tailroom(buf);
+	const uint8_t *end_of_label = NULL;
+	const uint8_t *curr_src = src;
+	int loop_check = 0, len = -1;
+	int label_len;
+	int val;
+
+	if (curr_src < msg || curr_src >= (msg + maxlen)) {
+		return -EMSGSIZE;
+	}
+
+	while ((val = *curr_src++)) {
+		if (val & NS_CMPRSFLGS) {
+			/* Follow pointer */
+			int pos;
+
+			if (curr_src >= (msg + maxlen)) {
+				return -EMSGSIZE;
+			}
+
+			if (len < 0) {
+				len = curr_src - src + 1;
+			}
+
+			end_of_label = curr_src + 1;
+
+			/* Strip compress bits from length calculation */
+			pos = ((val & 0x3f) << 8) | (*curr_src & 0xff);
+
+			curr_src = msg + pos;
+			if (curr_src >= (msg + maxlen)) {
+				return -EMSGSIZE;
+			}
+
+			loop_check += 2;
+			if (loop_check >= maxlen) {
+				return -EMSGSIZE;
+			}
+		} else {
+			/* Max label length is 64 bytes (because 2 bits are
+			 * used for pointer)
+			 */
+			label_len = val;
+			if (label_len > 63) {
+				return -EMSGSIZE;
+			}
+
+			if (((buf->data + label_len + 1) >=
+			     (buf->data + dest_size)) ||
+			    ((curr_src + label_len) >= (msg + maxlen))) {
+				return -EMSGSIZE;
+			}
+
+			loop_check += label_len + 1;
+
+			net_buf_add_u8(buf, '.');
+			net_buf_add_mem(buf, curr_src, label_len);
+
+			curr_src += label_len;
+		}
+	}
+
+	buf->data[buf->len] = '\0';
+
+	if (eol) {
+		if (!end_of_label) {
+			end_of_label = curr_src;
+		}
+
+		*eol = end_of_label;
+	}
+
+	return buf->len;
+}
+
+int dns_unpack_query(struct dns_msg_t *dns_msg, struct net_buf *buf,
+		     enum dns_rr_type *qtype, enum dns_class *qclass)
+{
+	const uint8_t *end_of_label;
+	uint8_t *dns_query;
+	int remaining_size;
+	int ret;
+	int query_type, query_class;
+
+	dns_query = dns_msg->msg + dns_msg->query_offset;
+	remaining_size = dns_msg->msg_size - dns_msg->query_offset;
+
+	ret = dns_unpack_name(dns_msg->msg, dns_msg->msg_size, dns_query,
+			      buf, &end_of_label);
+	if (ret < 0) {
+		return ret;
+	}
+
+	query_type = dns_unpack_query_qtype(end_of_label);
+	if (query_type != DNS_RR_TYPE_A && query_type != DNS_RR_TYPE_AAAA) {
+		return -EINVAL;
+	}
+
+	query_class = dns_unpack_query_qclass(end_of_label);
+	if (query_class != DNS_CLASS_IN) {
+		return -EINVAL;
+	}
+
+	if (qtype) {
+		*qtype = query_type;
+	}
+
+	if (qclass) {
+		*qclass = query_class;
+	}
+
+	dns_msg->query_offset = end_of_label - dns_msg->msg + 2 + 2;
+
+	return ret;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/llmnr_responder.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/llmnr_responder.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/llmnr_responder.c	(working copy)
@@ -0,0 +1,661 @@
+/** @file
+ * @brief LLMNR responder
+ *
+ * This listens to LLMNR queries and responds to them.
+ */
+
+/*
+ * Copyright (c) 2018 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_llmnr_responder, CONFIG_LLMNR_RESPONDER_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <init.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/dns_resolve.h>
+#include <net/udp.h>
+
+#include "dns_pack.h"
+#include "ipv6.h"
+
+#include "net_private.h"
+
+#define LLMNR_LISTEN_PORT 5355
+
+#define LLMNR_TTL CONFIG_LLMNR_RESPONDER_TTL /* In seconds */
+
+static struct net_context *ipv4;
+
+#if defined(CONFIG_NET_IPV6)
+static struct net_context *ipv6;
+#endif
+
+#define BUF_ALLOC_TIMEOUT K_MSEC(100)
+
+/* This value is recommended by RFC 1035 */
+#define DNS_RESOLVER_MAX_BUF_SIZE	512
+#define DNS_RESOLVER_MIN_BUF		2
+#define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
+				 CONFIG_LLMNR_RESOLVER_ADDITIONAL_BUF_CTR)
+
+NET_BUF_POOL_DEFINE(llmnr_dns_msg_pool, DNS_RESOLVER_BUF_CTR,
+		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
+
+#if defined(CONFIG_NET_IPV6)
+static void create_ipv6_addr(struct sockaddr_in6 *addr)
+{
+	addr->sin6_family = AF_INET6;
+	addr->sin6_port = htons(LLMNR_LISTEN_PORT);
+
+	/* Well known IPv6 ff02::1:3 address */
+	net_ipv6_addr_create(&addr->sin6_addr,
+			     0xff02, 0, 0, 0, 0, 0, 0x01, 0x03);
+}
+
+static void create_ipv6_dst_addr(struct net_pkt *pkt,
+				 struct sockaddr_in6 *addr)
+{
+	struct net_udp_hdr *udp_hdr, hdr;
+
+	udp_hdr = net_udp_get_hdr(pkt, &hdr);
+	if (!udp_hdr) {
+		return;
+	}
+
+	addr->sin6_family = AF_INET6;
+	addr->sin6_port = udp_hdr->src_port;
+
+	net_ipaddr_copy(&addr->sin6_addr, &NET_IPV6_HDR(pkt)->src);
+}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+static void create_ipv4_addr(struct sockaddr_in *addr)
+{
+	addr->sin_family = AF_INET;
+	addr->sin_port = htons(LLMNR_LISTEN_PORT);
+
+	/* Well known IPv4 224.0.0.252 address */
+	addr->sin_addr.s_addr = htonl(0xE00000FC);
+}
+
+static void create_ipv4_dst_addr(struct net_pkt *pkt,
+				 struct sockaddr_in *addr)
+{
+	struct net_udp_hdr *udp_hdr, hdr;
+
+	udp_hdr = net_udp_get_hdr(pkt, &hdr);
+	if (!udp_hdr) {
+		NET_ERR("could not get UDP header");
+		return;
+	}
+
+	addr->sin_family = AF_INET;
+	addr->sin_port = udp_hdr->src_port;
+
+	net_ipaddr_copy(&addr->sin_addr, &NET_IPV4_HDR(pkt)->src);
+}
+#endif
+
+static struct net_context *get_ctx(sa_family_t family)
+{
+	struct net_context *ctx;
+	int ret;
+
+	ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &ctx);
+	if (ret < 0) {
+		NET_DBG("Cannot get context (%d)", ret);
+		return NULL;
+	}
+
+	return ctx;
+}
+
+static int bind_ctx(struct net_context *ctx,
+		    struct sockaddr *local_addr,
+		    socklen_t addrlen)
+{
+	int ret;
+
+	if (!ctx) {
+		return -EINVAL;
+	}
+
+	ret = net_context_bind(ctx, local_addr, addrlen);
+	if (ret < 0) {
+		NET_DBG("Cannot bind to LLMNR %s port (%d)",
+			local_addr->sa_family == AF_INET ?
+			"IPv4" : "IPv6", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static void setup_dns_hdr(uint8_t *buf, uint16_t answers, uint16_t dns_id)
+{
+	uint16_t offset;
+	uint16_t flags;
+
+	/* See RFC 1035, ch 4.1.1 and RFC 4795 ch 2.1.1 for header details */
+
+	flags = BIT(15);  /* This is response */
+
+	UNALIGNED_PUT(htons(dns_id), (uint16_t *)(buf));
+	offset = DNS_HEADER_ID_LEN;
+
+	UNALIGNED_PUT(htons(flags), (uint16_t *)(buf+offset));
+	offset += DNS_HEADER_FLAGS_LEN;
+
+	UNALIGNED_PUT(htons(1), (uint16_t *)(buf + offset));
+	offset += DNS_QDCOUNT_LEN;
+
+	UNALIGNED_PUT(htons(answers), (uint16_t *)(buf + offset));
+	offset += DNS_ANCOUNT_LEN;
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+	offset += DNS_NSCOUNT_LEN;
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+}
+
+static void add_question(struct net_buf *query, enum dns_rr_type qtype)
+{
+	char *dot = query->data + DNS_MSG_HEADER_SIZE;
+	char *prev = NULL;
+	uint16_t offset;
+
+	while ((dot = strchr(dot, '.'))) {
+		if (!prev) {
+			prev = dot++;
+			continue;
+		}
+
+		*prev = dot - prev - 1;
+		prev = dot++;
+	}
+
+	if (prev) {
+		*prev = strlen(prev) - 1;
+	}
+
+	offset = DNS_MSG_HEADER_SIZE + query->len + 1;
+	UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset));
+
+	offset += DNS_QTYPE_LEN;
+	UNALIGNED_PUT(htons(DNS_CLASS_IN), (uint16_t *)(query->data+offset));
+}
+
+static int add_answer(struct net_buf *query, uint32_t ttl,
+		       uint16_t addr_len, const uint8_t *addr)
+{
+	const uint16_t q_len = query->len + 1 + DNS_QTYPE_LEN + DNS_QCLASS_LEN;
+	uint16_t offset = DNS_MSG_HEADER_SIZE + q_len;
+
+	memcpy(query->data + offset, query->data + DNS_MSG_HEADER_SIZE, q_len);
+	offset += q_len;
+
+	UNALIGNED_PUT(htonl(ttl), query->data + offset);
+	offset += DNS_TTL_LEN;
+
+	UNALIGNED_PUT(htons(addr_len), query->data + offset);
+	offset += DNS_RDLENGTH_LEN;
+
+	memcpy(query->data + offset, addr, addr_len);
+
+	return offset + addr_len;
+}
+
+static int create_answer(struct net_context *ctx,
+			 enum dns_rr_type qtype,
+			 struct net_buf *query,
+			 uint16_t dns_id,
+			 uint16_t addr_len, const uint8_t *addr)
+{
+	/* Prepare the response into the query buffer: move the name
+	 * query buffer has to get enough free space: dns_hdr + query + answer
+	 */
+	if ((query->size - query->len) < (DNS_MSG_HEADER_SIZE +
+					  (DNS_QTYPE_LEN + DNS_QCLASS_LEN) * 2 +
+					  DNS_TTL_LEN + DNS_RDLENGTH_LEN +
+					  addr_len + query->len)) {
+		return -ENOBUFS;
+	}
+
+	memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len);
+
+	setup_dns_hdr(query->data, 1, dns_id);
+
+	add_question(query, qtype);
+
+	query->len = add_answer(query, LLMNR_TTL, addr_len, addr);
+
+	return 0;
+}
+
+#if defined(CONFIG_NET_IPV4)
+static const uint8_t *get_ipv4_src(struct net_if *iface, struct in_addr *dst)
+{
+	const struct in_addr *addr;
+
+	addr = net_if_ipv4_select_src_addr(iface, dst);
+	if (!addr || net_ipv4_is_addr_unspecified(addr)) {
+		return NULL;
+	}
+
+	return (const uint8_t *)addr;
+}
+#endif
+
+#if defined(CONFIG_NET_IPV6)
+static const uint8_t *get_ipv6_src(struct net_if *iface, struct in6_addr *dst)
+{
+	const struct in6_addr *addr;
+
+	addr = net_if_ipv6_select_src_addr(iface, dst);
+	if (!addr || net_ipv6_is_addr_unspecified(addr)) {
+		return NULL;
+	}
+
+	return (const uint8_t *)addr;
+}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+static int create_ipv4_answer(struct net_context *ctx,
+			      struct net_pkt *pkt,
+			      union net_ip_header *ip_hdr,
+			      enum dns_rr_type qtype,
+			      struct net_buf *query,
+			      uint16_t dns_id,
+			      struct sockaddr *dst,
+			      socklen_t *dst_len)
+{
+	const uint8_t *addr;
+	int addr_len;
+
+	create_ipv4_dst_addr(pkt, net_sin(dst));
+	*dst_len = sizeof(struct sockaddr_in);
+
+	if (qtype == DNS_RR_TYPE_A) {
+		/* Select proper address according to destination */
+		addr = get_ipv4_src(net_pkt_iface(pkt),
+				    &net_sin(dst)->sin_addr);
+		if (!addr) {
+			return -ENOENT;
+		}
+
+		addr_len = sizeof(struct in_addr);
+
+	} else if (qtype == DNS_RR_TYPE_AAAA) {
+#if defined(CONFIG_NET_IPV6)
+		addr = get_ipv6_src(net_pkt_iface(pkt),
+				    &ip_hdr->ipv6->src);
+		if (!addr) {
+			return -ENOENT;
+		}
+
+		addr_len = sizeof(struct in6_addr);
+#else
+		addr = NULL;
+		addr_len = 0;
+#endif
+	} else {
+		return -EINVAL;
+	}
+
+	if (create_answer(ctx, qtype, query, dns_id, addr_len, addr)) {
+		return -ENOMEM;
+	}
+
+	net_context_set_ipv4_ttl(ctx, 255);
+
+	return 0;
+}
+#endif /* CONFIG_NET_IPV4 */
+
+static int create_ipv6_answer(struct net_context *ctx,
+			      struct net_pkt *pkt,
+			      union net_ip_header *ip_hdr,
+			      enum dns_rr_type qtype,
+			      struct net_buf *query,
+			      uint16_t dns_id,
+			      struct sockaddr *dst,
+			      socklen_t *dst_len)
+{
+#if defined(CONFIG_NET_IPV6)
+	const uint8_t *addr;
+	int addr_len;
+
+	create_ipv6_dst_addr(pkt, net_sin6(dst));
+	*dst_len = sizeof(struct sockaddr_in6);
+
+	if (qtype == DNS_RR_TYPE_AAAA) {
+		addr = get_ipv6_src(net_pkt_iface(pkt),
+				    &ip_hdr->ipv6->src);
+		if (!addr) {
+			return -ENOENT;
+		}
+
+		addr_len = sizeof(struct in6_addr);
+	} else if (qtype == DNS_RR_TYPE_A) {
+#if defined(CONFIG_NET_IPV4)
+		addr = get_ipv4_src(net_pkt_iface(pkt),
+				    &ip_hdr->ipv4->src);
+		if (!addr) {
+			return -ENOENT;
+		}
+
+		addr_len = sizeof(struct in_addr);
+#else
+		addr_len = 0;
+#endif
+	} else {
+		return -EINVAL;
+	}
+
+	if (create_answer(ctx, qtype, query, dns_id, addr_len, addr)) {
+		return -ENOMEM;
+	}
+
+	net_context_set_ipv6_hop_limit(ctx, 255);
+
+#endif /* CONFIG_NET_IPV6 */
+	return 0;
+}
+
+static int send_response(struct net_context *ctx, struct net_pkt *pkt,
+			 union net_ip_header *ip_hdr, struct net_buf *reply,
+			 enum dns_rr_type qtype, uint16_t dns_id)
+{
+	struct sockaddr dst;
+	socklen_t dst_len;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		ret = create_ipv4_answer(ctx, pkt, ip_hdr, qtype, reply,
+					 dns_id, &dst, &dst_len);
+		if (ret < 0) {
+			return ret;
+		}
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		ret = create_ipv6_answer(ctx, pkt, ip_hdr, qtype, reply,
+					 dns_id, &dst, &dst_len);
+		if (ret < 0) {
+			return ret;
+		}
+	} else {
+		/* TODO: support also service PTRs */
+		return -EPFNOSUPPORT;
+	}
+
+	ret = net_context_sendto(ctx, reply->data, reply->len, &dst,
+				 dst_len, NULL, K_NO_WAIT, NULL);
+	if (ret < 0) {
+		NET_DBG("Cannot send LLMNR reply to %s (%d)",
+			net_pkt_family(pkt) == AF_INET ?
+			log_strdup(net_sprint_ipv4_addr(
+					   &net_sin(&dst)->sin_addr)) :
+			log_strdup(net_sprint_ipv6_addr(
+					   &net_sin6(&dst)->sin6_addr)),
+			ret);
+	}
+
+	return ret;
+}
+
+static int dns_read(struct net_context *ctx,
+		    struct net_pkt *pkt,
+		    union net_ip_header *ip_hdr,
+		    struct net_buf *dns_data,
+		    struct dns_addrinfo *info)
+{
+	/* Helper struct to track the dns msg received from the server */
+	const char *hostname = net_hostname_get();
+	int hostname_len = strlen(hostname);
+	struct net_buf *result;
+	struct dns_msg_t dns_msg;
+	uint16_t dns_id = 0U;
+	int data_len;
+	int queries;
+	int ret;
+
+	data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE);
+
+	/* Store the DNS query name into a temporary net_buf, which will be
+	 * enventually used to send a response
+	 */
+	result = net_buf_alloc(&llmnr_dns_msg_pool, BUF_ALLOC_TIMEOUT);
+	if (!result) {
+		ret = -ENOMEM;
+		goto quit;
+	}
+
+	/* TODO: Instead of this temporary copy, just use the net_pkt directly.
+	 */
+	ret = net_pkt_read(pkt, dns_data->data, data_len);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	dns_msg.msg = dns_data->data;
+	dns_msg.msg_size = data_len;
+
+	ret = llmnr_unpack_query_header(&dns_msg, &dns_id);
+	if (ret < 0) {
+		ret = -EINVAL;
+		goto quit;
+	}
+
+	queries = ret;
+
+	NET_DBG("Received %d %s from %s (id 0x%04x)", queries,
+		queries > 1 ? "queries" : "query",
+		net_pkt_family(pkt) == AF_INET ?
+		log_strdup(net_sprint_ipv4_addr(&ip_hdr->ipv4->src)) :
+		log_strdup(net_sprint_ipv6_addr(&ip_hdr->ipv6->src)),
+		dns_id);
+
+	do {
+		enum dns_rr_type qtype;
+		enum dns_class qclass;
+
+		(void)memset(result->data, 0, result->size);
+		result->len = 0U;
+
+		ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass);
+		if (ret < 0) {
+			goto quit;
+		}
+
+		NET_DBG("[%d] query %s/%s label %s (%d bytes)", queries,
+			qtype == DNS_RR_TYPE_A ? "A" : "AAAA", "IN",
+			log_strdup(result->data), ret);
+
+		/* If the query matches to our hostname, then send reply */
+		if (!strncasecmp(hostname, result->data + 1, hostname_len) &&
+		    (result->len - 1) >= hostname_len) {
+			NET_DBG("LLMNR query to our hostname %s",
+				log_strdup(hostname));
+			ret = send_response(ctx, pkt, ip_hdr, result, qtype,
+					    dns_id);
+			if (ret < 0) {
+				NET_DBG("Cannot send response (%d)", ret);
+			}
+		}
+	} while (--queries);
+
+	ret = 0;
+
+quit:
+	if (result) {
+		net_buf_unref(result);
+	}
+
+	return ret;
+}
+
+static void recv_cb(struct net_context *net_ctx,
+		    struct net_pkt *pkt,
+		    union net_ip_header *ip_hdr,
+		    union net_proto_header *proto_hdr,
+		    int status,
+		    void *user_data)
+{
+	struct net_context *ctx = user_data;
+	struct net_buf *dns_data = NULL;
+	struct dns_addrinfo info = { 0 };
+	int ret;
+
+	ARG_UNUSED(net_ctx);
+	NET_ASSERT(ctx == net_ctx);
+
+	if (!pkt) {
+		return;
+	}
+
+	if (status) {
+		goto quit;
+	}
+
+	dns_data = net_buf_alloc(&llmnr_dns_msg_pool, BUF_ALLOC_TIMEOUT);
+	if (!dns_data) {
+		goto quit;
+	}
+
+	ret = dns_read(ctx, pkt, ip_hdr, dns_data, &info);
+	if (ret < 0 && ret != -EINVAL) {
+		NET_DBG("LLMNR read failed (%d)", ret);
+	}
+
+	net_buf_unref(dns_data);
+
+quit:
+	net_pkt_unref(pkt);
+}
+
+#if defined(CONFIG_NET_IPV6)
+static void iface_ipv6_cb(struct net_if *iface, void *user_data)
+{
+	struct in6_addr *addr = user_data;
+	int ret;
+
+	ret = net_ipv6_mld_join(iface, addr);
+	if (ret < 0) {
+		NET_DBG("Cannot join %s IPv6 multicast group (%d)",
+			log_strdup(net_sprint_ipv6_addr(addr)), ret);
+	}
+}
+
+static void setup_ipv6_addr(struct sockaddr_in6 *local_addr)
+{
+	create_ipv6_addr(local_addr);
+
+	net_if_foreach(iface_ipv6_cb, &local_addr->sin6_addr);
+}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+static void iface_ipv4_cb(struct net_if *iface, void *user_data)
+{
+	struct in_addr *addr = user_data;
+	struct net_if_mcast_addr *ifaddr;
+
+	ifaddr = net_if_ipv4_maddr_add(iface, addr);
+	if (!ifaddr) {
+		NET_DBG("Cannot add IPv4 multicast address to iface %p",
+			iface);
+	}
+}
+
+static void setup_ipv4_addr(struct sockaddr_in *local_addr)
+{
+	create_ipv4_addr(local_addr);
+
+	net_if_foreach(iface_ipv4_cb, &local_addr->sin_addr);
+}
+#endif /* CONFIG_NET_IPV4 */
+
+static int init_listener(void)
+{
+	int ret, ok = 0;
+
+#if defined(CONFIG_NET_IPV6)
+	{
+		static struct sockaddr_in6 local_addr;
+
+		setup_ipv6_addr(&local_addr);
+
+		ipv6 = get_ctx(AF_INET6);
+
+		ret = bind_ctx(ipv6, (struct sockaddr *)&local_addr,
+			       sizeof(local_addr));
+		if (ret < 0) {
+			net_context_put(ipv6);
+			goto ipv6_out;
+		}
+
+		ret = net_context_recv(ipv6, recv_cb, K_NO_WAIT, ipv6);
+		if (ret < 0) {
+			NET_WARN("Cannot receive IPv6 LLMNR data (%d)", ret);
+			net_context_put(ipv6);
+		} else {
+			ok++;
+		}
+	}
+ipv6_out:
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+	{
+		static struct sockaddr_in local_addr;
+
+		setup_ipv4_addr(&local_addr);
+
+		ipv4 = get_ctx(AF_INET);
+
+		ret = bind_ctx(ipv4, (struct sockaddr *)&local_addr,
+			       sizeof(local_addr));
+		if (ret < 0) {
+			net_context_put(ipv4);
+			goto ipv4_out;
+		}
+
+		ret = net_context_recv(ipv4, recv_cb, K_NO_WAIT, ipv4);
+		if (ret < 0) {
+			NET_WARN("Cannot receive IPv4 LLMNR data (%d)", ret);
+			net_context_put(ipv4);
+		} else {
+			ok++;
+		}
+	}
+ipv4_out:
+#endif /* CONFIG_NET_IPV4 */
+
+	if (!ok) {
+		NET_WARN("Cannot start LLMNR responder");
+	}
+
+	return !ok;
+}
+
+static int llmnr_responder_init(const struct device *device)
+{
+	ARG_UNUSED(device);
+
+	return init_listener();
+}
+
+SYS_INIT(llmnr_responder_init, APPLICATION, CONFIG_LLMNR_RESPONDER_INIT_PRIO);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/mdns_responder.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/mdns_responder.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/mdns_responder.c	(working copy)
@@ -0,0 +1,524 @@
+/** @file
+ * @brief mDNS responder
+ *
+ * This listens to mDNS queries and responds to them.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mdns_responder, CONFIG_MDNS_RESPONDER_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <init.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/dns_resolve.h>
+
+#include "dns_pack.h"
+#include "ipv6.h"
+
+#include "net_private.h"
+
+#define MDNS_LISTEN_PORT 5353
+
+#define MDNS_TTL CONFIG_MDNS_RESPONDER_TTL /* In seconds */
+
+#if defined(CONFIG_NET_IPV4)
+static struct net_context *ipv4;
+#endif
+#if defined(CONFIG_NET_IPV6)
+static struct net_context *ipv6;
+#endif
+
+#define BUF_ALLOC_TIMEOUT K_MSEC(100)
+
+/* This value is recommended by RFC 1035 */
+#define DNS_RESOLVER_MAX_BUF_SIZE	512
+#define DNS_RESOLVER_MIN_BUF		2
+#define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
+				 CONFIG_MDNS_RESOLVER_ADDITIONAL_BUF_CTR)
+
+NET_BUF_POOL_DEFINE(mdns_msg_pool, DNS_RESOLVER_BUF_CTR,
+		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
+
+#if defined(CONFIG_NET_IPV6)
+static void create_ipv6_addr(struct sockaddr_in6 *addr)
+{
+	addr->sin6_family = AF_INET6;
+	addr->sin6_port = htons(MDNS_LISTEN_PORT);
+
+	/* Well known IPv6 ff02::fb address */
+	net_ipv6_addr_create(&addr->sin6_addr,
+			     0xff02, 0, 0, 0, 0, 0, 0, 0x00fb);
+}
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+static void create_ipv4_addr(struct sockaddr_in *addr)
+{
+	addr->sin_family = AF_INET;
+	addr->sin_port = htons(MDNS_LISTEN_PORT);
+
+	/* Well known IPv4 224.0.0.251 address */
+	addr->sin_addr.s_addr = htonl(0xE00000FB);
+}
+#endif
+
+static struct net_context *get_ctx(sa_family_t family)
+{
+	struct net_context *ctx;
+	int ret;
+
+	ret = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, &ctx);
+	if (ret < 0) {
+		NET_DBG("Cannot get context (%d)", ret);
+		return NULL;
+	}
+
+	return ctx;
+}
+
+static int bind_ctx(struct net_context *ctx,
+		    struct sockaddr *local_addr,
+		    socklen_t addrlen)
+{
+	int ret;
+
+	if (!ctx) {
+		return -EINVAL;
+	}
+
+	ret = net_context_bind(ctx, local_addr, addrlen);
+	if (ret < 0) {
+		NET_DBG("Cannot bind to mDNS %s port (%d)",
+			local_addr->sa_family == AF_INET ?
+			"IPv4" : "IPv6", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static void setup_dns_hdr(uint8_t *buf, uint16_t answers)
+{
+	uint16_t offset;
+	uint16_t flags;
+
+	/* See RFC 1035, ch 4.1.1 for header details */
+
+	flags = BIT(15);  /* This is response */
+	flags |= BIT(10); /* Authoritative Answer */
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf)); /* Identifier, RFC 6762 ch 18.1 */
+	offset = DNS_HEADER_ID_LEN;
+
+	UNALIGNED_PUT(htons(flags), (uint16_t *)(buf+offset));
+	offset += DNS_HEADER_FLAGS_LEN;
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+	offset += DNS_QDCOUNT_LEN;
+
+	UNALIGNED_PUT(htons(answers), (uint16_t *)(buf + offset));
+	offset += DNS_ANCOUNT_LEN;
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+	offset += DNS_NSCOUNT_LEN;
+
+	UNALIGNED_PUT(0, (uint16_t *)(buf + offset));
+}
+
+static void add_answer(struct net_buf *query, enum dns_rr_type qtype,
+		       uint32_t ttl, uint16_t addr_len, uint8_t *addr)
+{
+	char *dot = query->data + DNS_MSG_HEADER_SIZE;
+	char *prev = NULL;
+	uint16_t offset;
+
+	while ((dot = strchr(dot, '.'))) {
+		if (!prev) {
+			prev = dot++;
+			continue;
+		}
+
+		*prev = dot - prev - 1;
+		prev = dot++;
+	}
+
+	if (prev) {
+		*prev = strlen(prev) - 1;
+	}
+
+	/* terminator byte (0x00) */
+	query->len += 1;
+
+	offset = DNS_MSG_HEADER_SIZE + query->len;
+	UNALIGNED_PUT(htons(qtype), (uint16_t *)(query->data+offset));
+
+	/* Bit 15 tells to flush the cache */
+	offset += DNS_QTYPE_LEN;
+	UNALIGNED_PUT(htons(DNS_CLASS_IN | BIT(15)),
+		      (uint16_t *)(query->data+offset));
+
+
+	offset += DNS_QCLASS_LEN;
+	UNALIGNED_PUT(htonl(ttl), query->data + offset);
+
+	offset += DNS_TTL_LEN;
+	UNALIGNED_PUT(htons(addr_len), query->data + offset);
+
+	offset += DNS_RDLENGTH_LEN;
+	memcpy(query->data + offset, addr, addr_len);
+}
+
+static int create_answer(struct net_context *ctx,
+			 struct net_buf *query,
+			 enum dns_rr_type qtype,
+			 uint16_t addr_len, uint8_t *addr)
+{
+	/* Prepare the response into the query buffer: move the name
+	 * query buffer has to get enough free space: dns_hdr + answer
+	 */
+	if ((query->size - query->len) < (DNS_MSG_HEADER_SIZE +
+					  DNS_QTYPE_LEN + DNS_QCLASS_LEN +
+					  DNS_TTL_LEN + DNS_RDLENGTH_LEN +
+					  addr_len)) {
+		return -ENOBUFS;
+	}
+
+	memmove(query->data + DNS_MSG_HEADER_SIZE, query->data, query->len);
+
+	setup_dns_hdr(query->data, 1);
+
+	add_answer(query, qtype, MDNS_TTL, addr_len, addr);
+
+	query->len += DNS_MSG_HEADER_SIZE +
+		DNS_QTYPE_LEN + DNS_QCLASS_LEN +
+		DNS_TTL_LEN + DNS_RDLENGTH_LEN + addr_len;
+
+	return 0;
+}
+
+static int send_response(struct net_context *ctx,
+			 struct net_pkt *pkt,
+			 union net_ip_header *ip_hdr,
+			 struct net_buf *query,
+			 enum dns_rr_type qtype)
+{
+	struct sockaddr dst;
+	socklen_t dst_len;
+	int ret;
+
+	if (qtype == DNS_RR_TYPE_A) {
+#if defined(CONFIG_NET_IPV4)
+		const struct in_addr *addr;
+
+		addr = net_if_ipv4_select_src_addr(net_pkt_iface(pkt),
+						   &ip_hdr->ipv4->src);
+
+		create_ipv4_addr(net_sin(&dst));
+		dst_len = sizeof(struct sockaddr_in);
+
+		ret = create_answer(ctx, query, qtype,
+				      sizeof(struct in_addr), (uint8_t *)addr);
+		if (ret != 0) {
+			return ret;
+		}
+
+		net_context_set_ipv4_ttl(ctx, 255);
+#else /* CONFIG_NET_IPV4 */
+		return -EPFNOSUPPORT;
+#endif /* CONFIG_NET_IPV4 */
+
+	} else if (qtype == DNS_RR_TYPE_AAAA) {
+#if defined(CONFIG_NET_IPV6)
+		const struct in6_addr *addr;
+
+		addr = net_if_ipv6_select_src_addr(net_pkt_iface(pkt),
+						   &ip_hdr->ipv6->src);
+
+		create_ipv6_addr(net_sin6(&dst));
+		dst_len = sizeof(struct sockaddr_in6);
+
+		ret = create_answer(ctx, query, qtype,
+				      sizeof(struct in6_addr), (uint8_t *)addr);
+		if (ret != 0) {
+			return -ENOMEM;
+		}
+
+		net_context_set_ipv6_hop_limit(ctx, 255);
+#else /* CONFIG_NET_IPV6 */
+		return -EPFNOSUPPORT;
+#endif /* CONFIG_NET_IPV6 */
+
+	} else {
+		/* TODO: support also service PTRs */
+		return -EINVAL;
+	}
+
+	ret = net_context_sendto(ctx, query->data, query->len, &dst,
+				 dst_len, NULL, K_NO_WAIT, NULL);
+	if (ret < 0) {
+		NET_DBG("Cannot send mDNS reply (%d)", ret);
+	}
+
+	return ret;
+}
+
+static int dns_read(struct net_context *ctx,
+		    struct net_pkt *pkt,
+		    union net_ip_header *ip_hdr,
+		    struct net_buf *dns_data,
+		    struct dns_addrinfo *info)
+{
+	/* Helper struct to track the dns msg received from the server */
+	const char *hostname = net_hostname_get();
+	int hostname_len = strlen(hostname);
+	struct net_buf *result;
+	struct dns_msg_t dns_msg;
+	int data_len;
+	int queries;
+	int ret;
+
+	data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE);
+
+	/* Store the DNS query name into a temporary net_buf, which will be
+	 * enventually used to send a response
+	 */
+	result = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT);
+	if (!result) {
+		ret = -ENOMEM;
+		goto quit;
+	}
+
+	/* TODO: Instead of this temporary copy, just use the net_pkt directly.
+	 */
+	ret = net_pkt_read(pkt, dns_data->data, data_len);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	dns_msg.msg = dns_data->data;
+	dns_msg.msg_size = data_len;
+
+	ret = mdns_unpack_query_header(&dns_msg, NULL);
+	if (ret < 0) {
+		ret = -EINVAL;
+		goto quit;
+	}
+
+	queries = ret;
+
+	NET_DBG("Received %d %s from %s", queries,
+		queries > 1 ? "queries" : "query",
+		net_pkt_family(pkt) == AF_INET ?
+		log_strdup(net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src)) :
+		log_strdup(net_sprint_ipv6_addr(&NET_IPV6_HDR(pkt)->src)));
+
+	do {
+		enum dns_rr_type qtype;
+		enum dns_class qclass;
+		uint8_t *lquery;
+
+		(void)memset(result->data, 0, net_buf_tailroom(result));
+		result->len = 0U;
+
+		ret = dns_unpack_query(&dns_msg, result, &qtype, &qclass);
+		if (ret < 0) {
+			goto quit;
+		}
+
+		/* Handle only .local queries */
+		lquery = strrchr(result->data + 1, '.');
+		if (!lquery || memcmp(lquery, (const void *){ ".local" }, 7)) {
+			continue;
+		}
+
+		NET_DBG("[%d] query %s/%s label %s (%d bytes)", queries,
+			qtype == DNS_RR_TYPE_A ? "A" : "AAAA", "IN",
+			log_strdup(result->data), ret);
+
+		/* If the query matches to our hostname, then send reply.
+		 * We skip the first dot, and make sure there is dot after
+		 * matching hostname.
+		 */
+		if (!strncasecmp(hostname, result->data + 1, hostname_len) &&
+		    (result->len - 1) >= hostname_len &&
+		    &(result->data + 1)[hostname_len] == lquery) {
+			NET_DBG("mDNS query to our hostname %s.local",
+				hostname);
+			send_response(ctx, pkt, ip_hdr, result, qtype);
+		}
+	} while (--queries);
+
+	ret = 0;
+
+quit:
+	if (result) {
+		net_buf_unref(result);
+	}
+
+	return ret;
+}
+
+static void recv_cb(struct net_context *net_ctx,
+		    struct net_pkt *pkt,
+		    union net_ip_header *ip_hdr,
+		    union net_proto_header *proto_hdr,
+		    int status,
+		    void *user_data)
+{
+	struct net_context *ctx = user_data;
+	struct net_buf *dns_data = NULL;
+	struct dns_addrinfo info = { 0 };
+	int ret;
+
+	ARG_UNUSED(net_ctx);
+	NET_ASSERT(ctx == net_ctx);
+
+	if (!pkt) {
+		return;
+	}
+
+	if (status) {
+		goto quit;
+	}
+
+	dns_data = net_buf_alloc(&mdns_msg_pool, BUF_ALLOC_TIMEOUT);
+	if (!dns_data) {
+		goto quit;
+	}
+
+	ret = dns_read(ctx, pkt, ip_hdr, dns_data, &info);
+	if (ret < 0 && ret != -EINVAL) {
+		NET_DBG("mDNS read failed (%d)", ret);
+	}
+
+	net_buf_unref(dns_data);
+
+quit:
+	net_pkt_unref(pkt);
+}
+
+#if defined(CONFIG_NET_IPV6)
+static void iface_ipv6_cb(struct net_if *iface, void *user_data)
+{
+	struct in6_addr *addr = user_data;
+	int ret;
+
+	ret = net_ipv6_mld_join(iface, addr);
+	if (ret < 0) {
+		NET_DBG("Cannot join %s IPv6 multicast group (%d)",
+			log_strdup(net_sprint_ipv6_addr(addr)), ret);
+	}
+}
+
+static void setup_ipv6_addr(struct sockaddr_in6 *local_addr)
+{
+	create_ipv6_addr(local_addr);
+
+	net_if_foreach(iface_ipv6_cb, &local_addr->sin6_addr);
+}
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+static void iface_ipv4_cb(struct net_if *iface, void *user_data)
+{
+	struct in_addr *addr = user_data;
+	struct net_if_mcast_addr *ifaddr;
+
+	ifaddr = net_if_ipv4_maddr_add(iface, addr);
+	if (!ifaddr) {
+		NET_DBG("Cannot add IPv4 multicast address to iface %p",
+			iface);
+	}
+}
+
+static void setup_ipv4_addr(struct sockaddr_in *local_addr)
+{
+	create_ipv4_addr(local_addr);
+
+	net_if_foreach(iface_ipv4_cb, &local_addr->sin_addr);
+}
+#endif /* CONFIG_NET_IPV4 */
+
+static int init_listener(void)
+{
+	int ret, ok = 0;
+
+#if defined(CONFIG_NET_IPV6)
+	do {
+		static struct sockaddr_in6 local_addr;
+
+		setup_ipv6_addr(&local_addr);
+
+		ipv6 = get_ctx(AF_INET6);
+
+		ret = bind_ctx(ipv6, (struct sockaddr *)&local_addr,
+			       sizeof(local_addr));
+		if (ret < 0) {
+			net_context_put(ipv6);
+			goto ipv6_out;
+		}
+
+		ret = net_context_recv(ipv6, recv_cb, K_NO_WAIT, ipv6);
+		if (ret < 0) {
+			NET_WARN("Cannot receive IPv6 mDNS data (%d)", ret);
+			net_context_put(ipv6);
+		} else {
+			ok++;
+		}
+	} while (0);
+ipv6_out:
+#endif /* CONFIG_NET_IPV6 */
+
+#if defined(CONFIG_NET_IPV4)
+	do {
+		static struct sockaddr_in local_addr;
+
+		setup_ipv4_addr(&local_addr);
+
+		ipv4 = get_ctx(AF_INET);
+
+		ret = bind_ctx(ipv4, (struct sockaddr *)&local_addr,
+			       sizeof(local_addr));
+		if (ret < 0) {
+			net_context_put(ipv4);
+			goto ipv4_out;
+		}
+
+		ret = net_context_recv(ipv4, recv_cb, K_NO_WAIT, ipv4);
+		if (ret < 0) {
+			NET_WARN("Cannot receive IPv4 mDNS data (%d)", ret);
+			net_context_put(ipv4);
+		} else {
+			ok++;
+		}
+	} while (0);
+ipv4_out:
+#endif /* CONFIG_NET_IPV4 */
+
+	if (!ok) {
+		NET_WARN("Cannot start mDNS responder");
+	}
+
+	return !ok;
+}
+
+static int mdns_responder_init(const struct device *device)
+{
+	ARG_UNUSED(device);
+
+	return init_listener();
+}
+
+SYS_INIT(mdns_responder_init, APPLICATION, CONFIG_MDNS_RESPONDER_INIT_PRIO);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/resolve.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/resolve.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/dns/resolve.c	(working copy)
@@ -0,0 +1,1267 @@
+/** @file
+ * @brief DNS resolve API
+ *
+ * An API for applications to do DNS query.
+ */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_dns_resolve, CONFIG_DNS_RESOLVER_LOG_LEVEL);
+
+#include <zephyr/types.h>
+#include <random/rand32.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <sys/crc.h>
+#include <net/net_ip.h>
+#include <net/net_pkt.h>
+#include <net/net_mgmt.h>
+#include <net/dns_resolve.h>
+#include "dns_pack.h"
+#include "dns_internal.h"
+
+#define DNS_SERVER_COUNT CONFIG_DNS_RESOLVER_MAX_SERVERS
+#define SERVER_COUNT     (DNS_SERVER_COUNT + DNS_MAX_MCAST_SERVERS)
+
+#define MDNS_IPV4_ADDR "224.0.0.251:5353"
+#define MDNS_IPV6_ADDR "[ff02::fb]:5353"
+
+#define LLMNR_IPV4_ADDR "224.0.0.252:5355"
+#define LLMNR_IPV6_ADDR "[ff02::1:3]:5355"
+
+#define DNS_BUF_TIMEOUT K_MSEC(500) /* ms */
+
+/* RFC 1035, 3.1. Name space definitions
+ * To simplify implementations, the total length of a domain name (i.e.,
+ * label octets and label length octets) is restricted to 255 octets or
+ * less.
+ */
+#define DNS_MAX_NAME_LEN	255
+
+#define DNS_QUERY_MAX_SIZE	(DNS_MSG_HEADER_SIZE + DNS_MAX_NAME_LEN + \
+				 DNS_QTYPE_LEN + DNS_QCLASS_LEN)
+
+/* This value is recommended by RFC 1035 */
+#define DNS_RESOLVER_MAX_BUF_SIZE	512
+#define DNS_RESOLVER_MIN_BUF	1
+#define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + \
+				 CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR)
+
+/* Compressed RR uses a pointer to another RR. So, min size is 12 bytes without
+ * considering RR payload.
+ * See https://tools.ietf.org/html/rfc1035#section-4.1.4
+ */
+#define DNS_ANSWER_PTR_LEN	12
+
+/* See dns_unpack_answer, and also see:
+ * https://tools.ietf.org/html/rfc1035#section-4.1.2
+ */
+#define DNS_QUERY_POS		0x0c
+
+#define DNS_IPV4_LEN		sizeof(struct in_addr)
+#define DNS_IPV6_LEN		sizeof(struct in6_addr)
+
+NET_BUF_POOL_DEFINE(dns_msg_pool, DNS_RESOLVER_BUF_CTR,
+		    DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
+
+NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_MAX_NAME_LEN,
+		    0, NULL);
+
+static struct dns_resolve_context dns_default_ctx;
+
+static int dns_write(struct dns_resolve_context *ctx,
+		     int server_idx,
+		     int query_idx,
+		     struct net_buf *dns_data,
+		     struct net_buf *dns_qname,
+		     int hop_limit);
+
+static bool server_is_mdns(sa_family_t family, struct sockaddr *addr)
+{
+	if (family == AF_INET) {
+		if (net_ipv4_is_addr_mcast(&net_sin(addr)->sin_addr) &&
+		    net_sin(addr)->sin_addr.s4_addr[3] == 251U) {
+			return true;
+		}
+
+		return false;
+	}
+
+	if (family == AF_INET6) {
+		if (net_ipv6_is_addr_mcast(&net_sin6(addr)->sin6_addr) &&
+		    net_sin6(addr)->sin6_addr.s6_addr[15] == 0xfb) {
+			return true;
+		}
+
+		return false;
+	}
+
+	return false;
+}
+
+static bool server_is_llmnr(sa_family_t family, struct sockaddr *addr)
+{
+	if (family == AF_INET) {
+		if (net_ipv4_is_addr_mcast(&net_sin(addr)->sin_addr) &&
+		    net_sin(addr)->sin_addr.s4_addr[3] == 252U) {
+			return true;
+		}
+
+		return false;
+	}
+
+	if (family == AF_INET6) {
+		if (net_ipv6_is_addr_mcast(&net_sin6(addr)->sin6_addr) &&
+		    net_sin6(addr)->sin6_addr.s6_addr[15] == 0x03) {
+			return true;
+		}
+
+		return false;
+	}
+
+	return false;
+}
+
+static void dns_postprocess_server(struct dns_resolve_context *ctx, int idx)
+{
+	struct sockaddr *addr = &ctx->servers[idx].dns_server;
+
+	if (addr->sa_family == AF_INET) {
+		ctx->servers[idx].is_mdns = server_is_mdns(AF_INET, addr);
+		if (!ctx->servers[idx].is_mdns) {
+			ctx->servers[idx].is_llmnr =
+				server_is_llmnr(AF_INET, addr);
+		}
+
+		if (net_sin(addr)->sin_port == 0U) {
+			if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
+			    ctx->servers[idx].is_mdns) {
+				/* We only use 5353 as a default port
+				 * if mDNS support is enabled. User can
+				 * override this by defining the port
+				 * in config file.
+				 */
+				net_sin(addr)->sin_port = htons(5353);
+			} else if (IS_ENABLED(CONFIG_LLMNR_RESOLVER) &&
+				   ctx->servers[idx].is_llmnr) {
+				/* We only use 5355 as a default port
+				 * if LLMNR support is enabled. User can
+				 * override this by defining the port
+				 * in config file.
+				 */
+				net_sin(addr)->sin_port = htons(5355);
+			} else {
+				net_sin(addr)->sin_port = htons(53);
+			}
+		}
+	} else {
+		ctx->servers[idx].is_mdns = server_is_mdns(AF_INET6, addr);
+		if (!ctx->servers[idx].is_mdns) {
+			ctx->servers[idx].is_llmnr =
+				server_is_llmnr(AF_INET6, addr);
+		}
+
+		if (net_sin6(addr)->sin6_port == 0U) {
+			if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
+			    ctx->servers[idx].is_mdns) {
+				net_sin6(addr)->sin6_port = htons(5353);
+			} else if (IS_ENABLED(CONFIG_LLMNR_RESOLVER) &&
+				   ctx->servers[idx].is_llmnr) {
+				net_sin6(addr)->sin6_port = htons(5355);
+			} else {
+				net_sin6(addr)->sin6_port = htons(53);
+			}
+		}
+	}
+}
+
+int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[],
+		     const struct sockaddr *servers_sa[])
+{
+#if defined(CONFIG_NET_IPV6)
+	struct sockaddr_in6 local_addr6 = {
+		.sin6_family = AF_INET6,
+		.sin6_port = 0,
+	};
+#endif
+#if defined(CONFIG_NET_IPV4)
+	struct sockaddr_in local_addr4 = {
+		.sin_family = AF_INET,
+		.sin_port = 0,
+	};
+#endif
+	struct sockaddr *local_addr = NULL;
+	socklen_t addr_len = 0;
+	int i = 0, idx = 0;
+	struct net_if *iface;
+	int ret, count;
+
+	if (!ctx) {
+		return -ENOENT;
+	}
+
+	if (ctx->is_used) {
+		return -ENOTEMPTY;
+	}
+
+	(void)memset(ctx, 0, sizeof(*ctx));
+
+	if (servers) {
+		for (i = 0; idx < SERVER_COUNT && servers[i]; i++) {
+			struct sockaddr *addr = &ctx->servers[idx].dns_server;
+
+			(void)memset(addr, 0, sizeof(*addr));
+
+			ret = net_ipaddr_parse(servers[i], strlen(servers[i]),
+					       addr);
+			if (!ret) {
+				continue;
+			}
+
+			dns_postprocess_server(ctx, idx);
+
+			NET_DBG("[%d] %s%s%s", i, log_strdup(servers[i]),
+				IS_ENABLED(CONFIG_MDNS_RESOLVER) ?
+				(ctx->servers[i].is_mdns ? " mDNS" : "") : "",
+				IS_ENABLED(CONFIG_LLMNR_RESOLVER) ?
+				(ctx->servers[i].is_llmnr ?
+							 " LLMNR" : "") : "");
+			idx++;
+		}
+	}
+
+	if (servers_sa) {
+		for (i = 0; idx < SERVER_COUNT && servers_sa[i]; i++) {
+			memcpy(&ctx->servers[idx].dns_server, servers_sa[i],
+			       sizeof(ctx->servers[idx].dns_server));
+			dns_postprocess_server(ctx, idx);
+			idx++;
+		}
+	}
+
+	for (i = 0, count = 0;
+	     i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family; i++) {
+
+		if (ctx->servers[i].dns_server.sa_family == AF_INET6) {
+#if defined(CONFIG_NET_IPV6)
+			local_addr = (struct sockaddr *)&local_addr6;
+			addr_len = sizeof(struct sockaddr_in6);
+
+			if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
+			    ctx->servers[i].is_mdns) {
+				local_addr6.sin6_port = htons(5353);
+			}
+#else
+			continue;
+#endif
+		}
+
+		if (ctx->servers[i].dns_server.sa_family == AF_INET) {
+#if defined(CONFIG_NET_IPV4)
+			local_addr = (struct sockaddr *)&local_addr4;
+			addr_len = sizeof(struct sockaddr_in);
+
+			if (IS_ENABLED(CONFIG_MDNS_RESOLVER) &&
+			    ctx->servers[i].is_mdns) {
+				local_addr4.sin_port = htons(5353);
+			}
+#else
+			continue;
+#endif
+		}
+
+		if (!local_addr) {
+			NET_DBG("Local address not set");
+			return -EAFNOSUPPORT;
+		}
+
+		ret = net_context_get(ctx->servers[i].dns_server.sa_family,
+				      SOCK_DGRAM, IPPROTO_UDP,
+				      &ctx->servers[i].net_ctx);
+		if (ret < 0) {
+			NET_DBG("Cannot get net_context (%d)", ret);
+			return ret;
+		}
+
+		ret = net_context_bind(ctx->servers[i].net_ctx,
+				       local_addr, addr_len);
+		if (ret < 0) {
+			NET_DBG("Cannot bind DNS context (%d)", ret);
+			return ret;
+		}
+
+		iface = net_context_get_iface(ctx->servers[i].net_ctx);
+
+		if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
+			net_mgmt_event_notify_with_info(
+				NET_EVENT_DNS_SERVER_ADD,
+				iface, (void *)&ctx->servers[i].dns_server,
+				sizeof(struct sockaddr));
+		} else {
+			net_mgmt_event_notify(NET_EVENT_DNS_SERVER_ADD, iface);
+		}
+
+#if defined(CONFIG_NET_IPV6)
+		local_addr6.sin6_port = 0;
+#endif
+
+#if defined(CONFIG_NET_IPV4)
+		local_addr4.sin_port = 0;
+#endif
+
+		count++;
+	}
+
+	if (count == 0) {
+		/* No servers defined */
+		NET_DBG("No DNS servers defined.");
+		return -EINVAL;
+	}
+
+	ctx->is_used = true;
+	ctx->buf_timeout = DNS_BUF_TIMEOUT;
+
+	return 0;
+}
+
+static inline int get_cb_slot(struct dns_resolve_context *ctx)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+		if (!ctx->queries[i].cb) {
+			return i;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static inline int get_slot_by_id(struct dns_resolve_context *ctx,
+				 uint16_t dns_id,
+				 uint16_t query_hash)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
+		if (ctx->queries[i].cb && ctx->queries[i].id == dns_id &&
+		    (query_hash == 0 ||
+		     ctx->queries[i].query_hash == query_hash)) {
+			return i;
+		}
+	}
+
+	return -ENOENT;
+}
+
+int dns_validate_msg(struct dns_resolve_context *ctx,
+		     struct dns_msg_t *dns_msg,
+		     uint16_t *dns_id,
+		     int *query_idx,
+		     struct net_buf *dns_cname,
+		     uint16_t *query_hash)
+{
+	struct dns_addrinfo info = { 0 };
+	uint32_t ttl; /* RR ttl, so far it is not passed to caller */
+	uint8_t *src, *addr;
+	const char *query_name;
+	int address_size;
+	/* index that points to the current answer being analyzed */
+	int answer_ptr;
+	int items;
+	int server_idx;
+	int ret = 0;
+
+	/* Make sure that we can read DNS id, flags and rcode */
+	if (dns_msg->msg_size < (sizeof(*dns_id) + sizeof(uint16_t))) {
+		ret = DNS_EAI_FAIL;
+		goto quit;
+	}
+
+	/* The dns_unpack_response_header() has design flaw as it expects
+	 * dns id to be given instead of returning the id to the caller.
+	 * In our case we would like to get it returned instead so that we
+	 * can match the DNS query that we sent. When dns_read() is called,
+	 * we do not know what the DNS id is yet.
+	 */
+	*dns_id = dns_unpack_header_id(dns_msg->msg);
+
+	if (dns_header_rcode(dns_msg->msg) == DNS_HEADER_REFUSED) {
+		ret = DNS_EAI_FAIL;
+		goto quit;
+	}
+
+	/* We might receive a query while we are waiting for a response, in that
+	 * case we just ignore the query instead of making the resolving fail.
+	 */
+	if (dns_header_qr(dns_msg->msg) == DNS_QUERY) {
+		ret = 0;
+		goto quit;
+	}
+
+	ret = dns_unpack_response_header(dns_msg, *dns_id);
+	if (ret < 0) {
+		ret = DNS_EAI_FAIL;
+		goto quit;
+	}
+
+	if (dns_header_qdcount(dns_msg->msg) != 1) {
+		/* For mDNS (when dns_id == 0) the query count is 0 */
+		if (*dns_id > 0) {
+			ret = DNS_EAI_FAIL;
+			goto quit;
+		}
+	}
+
+	ret = dns_unpack_response_query(dns_msg);
+	if (ret < 0) {
+		/* Check mDNS like above */
+		if (*dns_id > 0) {
+			ret = DNS_EAI_FAIL;
+			goto quit;
+		}
+
+		/* mDNS responses to do not have the query part so the
+		 * answer starts immediately after the header.
+		 */
+		dns_msg->answer_offset = dns_msg->query_offset;
+	}
+
+	/* Because in mDNS the DNS id is set to 0 and must be ignored
+	 * on reply, we need to figure out the answer in order to find
+	 * the proper query. To simplify things, the normal DNS responses
+	 * are handled the same way.
+	 */
+
+	answer_ptr = DNS_QUERY_POS;
+	items = 0;
+	server_idx = 0;
+	while (server_idx < dns_header_ancount(dns_msg->msg)) {
+		ret = dns_unpack_answer(dns_msg, answer_ptr, &ttl);
+		if (ret < 0) {
+			ret = DNS_EAI_FAIL;
+			goto quit;
+		}
+
+		switch (dns_msg->response_type) {
+		case DNS_RESPONSE_IP:
+			if (*query_idx >= 0) {
+				goto query_known;
+			}
+
+			query_name = dns_msg->msg + dns_msg->query_offset;
+
+			/* Add \0 and query type (A or AAAA) to the hash */
+			*query_hash = crc16_ansi(query_name,
+						 strlen(query_name) + 1 + 2);
+
+			*query_idx = get_slot_by_id(ctx, *dns_id, *query_hash);
+			if (*query_idx < 0) {
+				ret = DNS_EAI_SYSTEM;
+				goto quit;
+			}
+
+			if (ctx->queries[*query_idx].query_type ==
+							DNS_QUERY_TYPE_A) {
+				if (net_sin(&info.ai_addr)->sin_family ==
+							AF_INET6) {
+					ret = DNS_EAI_ADDRFAMILY;
+					goto quit;
+				}
+
+				address_size = DNS_IPV4_LEN;
+				addr = (uint8_t *)&net_sin(&info.ai_addr)->
+								sin_addr;
+				info.ai_family = AF_INET;
+				info.ai_addr.sa_family = AF_INET;
+				info.ai_addrlen = sizeof(struct sockaddr_in);
+
+			} else if (ctx->queries[*query_idx].query_type ==
+							DNS_QUERY_TYPE_AAAA) {
+				if (net_sin6(&info.ai_addr)->sin6_family ==
+							AF_INET) {
+					ret = DNS_EAI_ADDRFAMILY;
+					goto quit;
+				}
+
+				/* We cannot resolve IPv6 address if IPv6 is
+				 * disabled. The reason being that
+				 * "struct sockaddr" does not have enough space
+				 * for IPv6 address in that case.
+				 */
+#if defined(CONFIG_NET_IPV6)
+				address_size = DNS_IPV6_LEN;
+				addr = (uint8_t *)&net_sin6(&info.ai_addr)->
+								sin6_addr;
+				info.ai_family = AF_INET6;
+				info.ai_addr.sa_family = AF_INET6;
+				info.ai_addrlen = sizeof(struct sockaddr_in6);
+#else
+				ret = DNS_EAI_FAMILY;
+				goto quit;
+#endif
+			} else {
+				ret = DNS_EAI_FAMILY;
+				goto quit;
+			}
+
+			if (dns_msg->response_length < address_size) {
+				/* it seems this is a malformed message */
+				ret = DNS_EAI_FAIL;
+				goto quit;
+			}
+
+			if ((dns_msg->response_position + address_size) >
+			    dns_msg->msg_size) {
+				/* Too short message */
+				ret = DNS_EAI_FAIL;
+				goto quit;
+			}
+
+			src = dns_msg->msg + dns_msg->response_position;
+			memcpy(addr, src, address_size);
+
+		query_known:
+			ctx->queries[*query_idx].cb(DNS_EAI_INPROGRESS, &info,
+					ctx->queries[*query_idx].user_data);
+			items++;
+			break;
+
+		case DNS_RESPONSE_CNAME_NO_IP:
+			/* Instead of using the QNAME at DNS_QUERY_POS,
+			 * we will use this CNAME
+			 */
+			answer_ptr = dns_msg->response_position;
+			break;
+
+		default:
+			ret = DNS_EAI_FAIL;
+			goto quit;
+		}
+
+		/* Update the answer offset to point to the next RR (answer) */
+		dns_msg->answer_offset += dns_msg->response_position -
+							dns_msg->answer_offset;
+		dns_msg->answer_offset += dns_msg->response_length;
+
+		server_idx++;
+	}
+
+	if (*query_idx < 0) {
+		/* If the query_idx is still unknown, try to get it here
+		 * and hope it is found.
+		 */
+		query_name = dns_msg->msg + dns_msg->query_offset;
+		*query_hash = crc16_ansi(query_name,
+					 strlen(query_name) + 1 + 2);
+
+		*query_idx = get_slot_by_id(ctx, *dns_id, *query_hash);
+		if (*query_idx < 0) {
+			ret = DNS_EAI_SYSTEM;
+			goto quit;
+		}
+	}
+
+	/* No IP addresses were found, so we take the last CNAME to generate
+	 * another query. Number of additional queries is controlled via Kconfig
+	 */
+	if (items == 0) {
+		if (dns_msg->response_type == DNS_RESPONSE_CNAME_NO_IP) {
+			uint16_t pos = dns_msg->response_position;
+
+			/* The dns_cname should always be set. As a special
+			 * case, it might not be set for unit tests that call
+			 * this function directly.
+			 */
+			if (dns_cname) {
+				ret = dns_copy_qname(dns_cname->data,
+						     &dns_cname->len,
+						     dns_cname->size,
+						     dns_msg, pos);
+				if (ret < 0) {
+					ret = DNS_EAI_SYSTEM;
+					goto quit;
+				}
+			}
+
+			ret = DNS_EAI_AGAIN;
+			goto quit;
+		}
+	}
+
+	if (items == 0) {
+		ret = DNS_EAI_NODATA;
+	} else {
+		ret = DNS_EAI_ALLDONE;
+	}
+
+quit:
+	return ret;
+}
+
+static int dns_read(struct dns_resolve_context *ctx,
+		    struct net_pkt *pkt,
+		    struct net_buf *dns_data,
+		    uint16_t *dns_id,
+		    struct net_buf *dns_cname,
+		    uint16_t *query_hash)
+{
+	/* Helper struct to track the dns msg received from the server */
+	struct dns_msg_t dns_msg;
+	int data_len;
+	int ret;
+	int query_idx = -1;
+
+	data_len = MIN(net_pkt_remaining_data(pkt), DNS_RESOLVER_MAX_BUF_SIZE);
+
+	/* TODO: Instead of this temporary copy, just use the net_pkt directly.
+	 */
+	ret = net_pkt_read(pkt, dns_data->data, data_len);
+	if (ret < 0) {
+		ret = DNS_EAI_MEMORY;
+		goto quit;
+	}
+
+	dns_msg.msg = dns_data->data;
+	dns_msg.msg_size = data_len;
+
+	ret = dns_validate_msg(ctx, &dns_msg, dns_id, &query_idx,
+			       dns_cname, query_hash);
+	if (ret == DNS_EAI_AGAIN) {
+		goto finished;
+	}
+
+	if (ret < 0) {
+		goto quit;
+	}
+
+	if (k_delayed_work_remaining_get(&ctx->queries[query_idx].timer) > 0) {
+		k_delayed_work_cancel(&ctx->queries[query_idx].timer);
+	}
+
+	/* Marks the end of the results */
+	ctx->queries[query_idx].cb(ret, NULL,
+				   ctx->queries[query_idx].user_data);
+	ctx->queries[query_idx].cb = NULL;
+
+	net_pkt_unref(pkt);
+
+	return 0;
+
+finished:
+	dns_resolve_cancel_with_name(ctx, *dns_id,
+				     ctx->queries[query_idx].query,
+				     ctx->queries[query_idx].query_type);
+quit:
+	net_pkt_unref(pkt);
+
+	return ret;
+}
+
+static void cb_recv(struct net_context *net_ctx,
+		    struct net_pkt *pkt,
+		    union net_ip_header *ip_hdr,
+		    union net_proto_header *proto_hdr,
+		    int status,
+		    void *user_data)
+{
+	struct dns_resolve_context *ctx = user_data;
+	struct net_buf *dns_cname = NULL;
+	struct net_buf *dns_data = NULL;
+	uint16_t query_hash = 0U;
+	uint16_t dns_id = 0U;
+	int ret, i;
+
+	ARG_UNUSED(net_ctx);
+
+	if (status) {
+		ret = DNS_EAI_SYSTEM;
+		goto quit;
+	}
+
+	dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
+	if (!dns_data) {
+		ret = DNS_EAI_MEMORY;
+		goto quit;
+	}
+
+	dns_cname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
+	if (!dns_cname) {
+		ret = DNS_EAI_MEMORY;
+		goto quit;
+	}
+
+	ret = dns_read(ctx, pkt, dns_data, &dns_id, dns_cname, &query_hash);
+	if (!ret) {
+		/* We called the callback already in dns_read() if there
+		 * was no errors.
+		 */
+		goto free_buf;
+	}
+
+	/* Query again if we got CNAME */
+	if (ret == DNS_EAI_AGAIN) {
+		int failure = 0;
+		int j;
+
+		i = get_slot_by_id(ctx, dns_id, query_hash);
+		if (i < 0) {
+			goto free_buf;
+		}
+
+		for (j = 0; j < SERVER_COUNT; j++) {
+			if (!ctx->servers[j].net_ctx) {
+				continue;
+			}
+
+			ret = dns_write(ctx, j, i, dns_data, dns_cname, 0);
+			if (ret < 0) {
+				failure++;
+			}
+		}
+
+		if (failure) {
+			NET_DBG("DNS cname query failed %d times", failure);
+
+			if (failure == j) {
+				ret = DNS_EAI_SYSTEM;
+				goto quit;
+			}
+		}
+
+		goto free_buf;
+	}
+
+quit:
+	i = get_slot_by_id(ctx, dns_id, query_hash);
+	if (i < 0) {
+		goto free_buf;
+	}
+
+	if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
+		k_delayed_work_cancel(&ctx->queries[i].timer);
+	}
+
+	/* Marks the end of the results */
+	ctx->queries[i].cb(ret, NULL, ctx->queries[i].user_data);
+	ctx->queries[i].cb = NULL;
+
+free_buf:
+	if (dns_data) {
+		net_buf_unref(dns_data);
+	}
+
+	if (dns_cname) {
+		net_buf_unref(dns_cname);
+	}
+}
+
+static int dns_write(struct dns_resolve_context *ctx,
+		     int server_idx,
+		     int query_idx,
+		     struct net_buf *dns_data,
+		     struct net_buf *dns_qname,
+		     int hop_limit)
+{
+	enum dns_query_type query_type;
+	struct net_context *net_ctx;
+	struct sockaddr *server;
+	int server_addr_len;
+	uint16_t dns_id;
+	int ret;
+
+	net_ctx = ctx->servers[server_idx].net_ctx;
+	server = &ctx->servers[server_idx].dns_server;
+	dns_id = ctx->queries[query_idx].id;
+	query_type = ctx->queries[query_idx].query_type;
+
+	ret = dns_msg_pack_query(dns_data->data, &dns_data->len, dns_data->size,
+				 dns_qname->data, dns_qname->len, dns_id,
+				 (enum dns_rr_type)query_type);
+	if (ret < 0) {
+		return -EINVAL;
+	}
+
+	/* Add \0 and query type (A or AAAA) to the hash. Note that
+	 * the dns_qname->len contains the length of \0
+	 */
+	ctx->queries[query_idx].query_hash =
+		crc16_ansi(dns_data->data + DNS_MSG_HEADER_SIZE,
+			   dns_qname->len + 2);
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) &&
+	    net_context_get_family(net_ctx) == AF_INET6) {
+		net_context_set_ipv6_hop_limit(net_ctx, hop_limit);
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   net_context_get_family(net_ctx) == AF_INET) {
+		net_context_set_ipv4_ttl(net_ctx, hop_limit);
+	}
+
+	ret = net_context_recv(net_ctx, cb_recv, K_NO_WAIT, ctx);
+	if (ret < 0 && ret != -EALREADY) {
+		NET_DBG("Could not receive from socket (%d)", ret);
+		return ret;
+	}
+
+	if (server->sa_family == AF_INET) {
+		server_addr_len = sizeof(struct sockaddr_in);
+	} else {
+		server_addr_len = sizeof(struct sockaddr_in6);
+	}
+
+	ret = k_delayed_work_submit(&ctx->queries[query_idx].timer,
+				    ctx->queries[query_idx].timeout);
+	if (ret < 0) {
+		NET_DBG("[%u] cannot submit work to server idx %d for id %u "
+			"ret %d", query_idx, server_idx, dns_id, ret);
+		return ret;
+	}
+
+	NET_DBG("[%u] submitting work to server idx %d for id %u "
+		"hash %u", query_idx, server_idx, dns_id,
+		ctx->queries[query_idx].query_hash);
+
+	ret = net_context_sendto(net_ctx, dns_data->data, dns_data->len,
+				 server, server_addr_len, NULL,
+				 K_NO_WAIT, NULL);
+	if (ret < 0) {
+		NET_DBG("Cannot send query (%d)", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dns_resolve_cancel_with_hash(struct dns_resolve_context *ctx,
+					uint16_t dns_id,
+					uint16_t query_hash,
+					const char *query_name)
+{
+	int i;
+
+	i = get_slot_by_id(ctx, dns_id, query_hash);
+	if (i < 0 || !ctx->queries[i].cb) {
+		return -ENOENT;
+	}
+
+	NET_DBG("Cancelling DNS req %u (name %s type %d hash %u)", dns_id,
+		log_strdup(query_name), ctx->queries[i].query_type,
+		query_hash);
+
+	if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
+		k_delayed_work_cancel(&ctx->queries[i].timer);
+	}
+
+	ctx->queries[i].cb(DNS_EAI_CANCELED, NULL, ctx->queries[i].user_data);
+	ctx->queries[i].cb = NULL;
+
+	return 0;
+}
+
+int dns_resolve_cancel_with_name(struct dns_resolve_context *ctx,
+				 uint16_t dns_id,
+				 const char *query_name,
+				 enum dns_query_type query_type)
+{
+	uint16_t query_hash = 0;
+
+	if (query_name) {
+		struct net_buf *buf;
+		uint16_t len;
+		int ret;
+
+		/* Use net_buf as a temporary buffer to store the packed
+		 * DNS name.
+		 */
+		buf = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
+		if (!buf) {
+			return -ENOMEM;
+		}
+
+		ret = dns_msg_pack_qname(&len, buf->data, buf->size,
+					 query_name);
+		if (ret >= 0) {
+			/* If the query string + \0 + query type (A or AAAA)
+			 * does not fit the tmp buf, then bail out
+			 */
+			if ((len + 2) > buf->size) {
+				net_buf_unref(buf);
+				return -ENOMEM;
+			}
+
+			net_buf_add(buf, len);
+			net_buf_add_be16(buf, query_type);
+
+			query_hash = crc16_ansi(buf->data, len + 2);
+		}
+
+		net_buf_unref(buf);
+
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	return dns_resolve_cancel_with_hash(ctx, dns_id, query_hash,
+					    query_name);
+}
+
+int dns_resolve_cancel(struct dns_resolve_context *ctx, uint16_t dns_id)
+{
+	return dns_resolve_cancel_with_name(ctx, dns_id, NULL, 0);
+}
+
+static void query_timeout(struct k_work *work)
+{
+	struct dns_pending_query *pending_query =
+		CONTAINER_OF(work, struct dns_pending_query, timer);
+
+	NET_DBG("Query timeout DNS req %u type %d hash %u", pending_query->id,
+		pending_query->query_type, pending_query->query_hash);
+
+	(void)dns_resolve_cancel_with_hash(pending_query->ctx,
+					   pending_query->id,
+					   pending_query->query_hash,
+					   pending_query->query);
+}
+
+int dns_resolve_name(struct dns_resolve_context *ctx,
+		     const char *query,
+		     enum dns_query_type type,
+		     uint16_t *dns_id,
+		     dns_resolve_cb_t cb,
+		     void *user_data,
+		     int32_t timeout)
+{
+	k_timeout_t tout;
+	struct net_buf *dns_data = NULL;
+	struct net_buf *dns_qname = NULL;
+	struct sockaddr addr;
+	int ret, i = -1, j = 0;
+	int failure = 0;
+	bool mdns_query = false;
+	uint8_t hop_limit;
+
+	if (!ctx || !ctx->is_used || !query || !cb) {
+		return -EINVAL;
+	}
+
+	tout = SYS_TIMEOUT_MS(timeout);
+
+	/* Timeout cannot be 0 as we cannot resolve name that fast.
+	 */
+	if (K_TIMEOUT_EQ(tout, K_NO_WAIT)) {
+		return -EINVAL;
+	}
+
+	ret = net_ipaddr_parse(query, strlen(query), &addr);
+	if (ret) {
+		/* The query name was already in numeric form, no
+		 * need to continue further.
+		 */
+		struct dns_addrinfo info = { 0 };
+
+		if (type == DNS_QUERY_TYPE_A) {
+			if (net_sin(&addr)->sin_family == AF_INET6) {
+				ret = -EPFNOSUPPORT;
+				goto quit;
+			}
+
+			memcpy(net_sin(&info.ai_addr), net_sin(&addr),
+			       sizeof(struct sockaddr_in));
+			info.ai_family = AF_INET;
+			info.ai_addr.sa_family = AF_INET;
+			info.ai_addrlen = sizeof(struct sockaddr_in);
+		} else if (type == DNS_QUERY_TYPE_AAAA) {
+			/* We do not support AI_V4MAPPED atm, so if the user
+			 * asks an IPv6 address but it is an IPv4 one, then
+			 * return an error. Note that getaddrinfo() will swap
+			 * the error to EINVAL, the EPFNOSUPPORT is returned
+			 * here so that we can find it easily.
+			 */
+			if (net_sin(&addr)->sin_family == AF_INET) {
+				ret = -EPFNOSUPPORT;
+				goto quit;
+			}
+
+#if defined(CONFIG_NET_IPV6)
+			memcpy(net_sin6(&info.ai_addr), net_sin6(&addr),
+			       sizeof(struct sockaddr_in6));
+			info.ai_family = AF_INET6;
+			info.ai_addr.sa_family = AF_INET6;
+			info.ai_addrlen = sizeof(struct sockaddr_in6);
+#else
+			ret = -EAFNOSUPPORT;
+			goto quit;
+#endif
+		} else {
+			goto try_resolve;
+		}
+
+		cb(DNS_EAI_INPROGRESS, &info, user_data);
+		cb(DNS_EAI_ALLDONE, NULL, user_data);
+
+		return 0;
+	}
+
+try_resolve:
+	i = get_cb_slot(ctx);
+	if (i < 0) {
+		return -EAGAIN;
+	}
+
+	ctx->queries[i].cb = cb;
+	ctx->queries[i].timeout = tout;
+	ctx->queries[i].query = query;
+	ctx->queries[i].query_type = type;
+	ctx->queries[i].user_data = user_data;
+	ctx->queries[i].ctx = ctx;
+	ctx->queries[i].query_hash = 0;
+
+	k_delayed_work_init(&ctx->queries[i].timer, query_timeout);
+
+	dns_data = net_buf_alloc(&dns_msg_pool, ctx->buf_timeout);
+	if (!dns_data) {
+		ret = -ENOMEM;
+		goto quit;
+	}
+
+	dns_qname = net_buf_alloc(&dns_qname_pool, ctx->buf_timeout);
+	if (!dns_qname) {
+		ret = -ENOMEM;
+		goto quit;
+	}
+
+	ret = dns_msg_pack_qname(&dns_qname->len, dns_qname->data,
+				DNS_MAX_NAME_LEN, ctx->queries[i].query);
+	if (ret < 0) {
+		goto quit;
+	}
+
+	ctx->queries[i].id = sys_rand32_get();
+
+	/* If mDNS is enabled, then send .local queries only to multicast
+	 * address. For mDNS the id should be set to 0, see RFC 6762 ch. 18.1
+	 * for details.
+	 */
+	if (IS_ENABLED(CONFIG_MDNS_RESOLVER)) {
+		const char *ptr = strrchr(query, '.');
+
+		/* Note that we memcmp() the \0 here too */
+		if (ptr && !memcmp(ptr, (const void *){ ".local" }, 7)) {
+			mdns_query = true;
+
+			ctx->queries[i].id = 0;
+		}
+	}
+
+	/* Do this immediately after calculating the Id so that the unit
+	 * test will work properly.
+	 */
+	if (dns_id) {
+		*dns_id = ctx->queries[i].id;
+
+		NET_DBG("DNS id will be %u", *dns_id);
+	}
+
+	for (j = 0; j < SERVER_COUNT; j++) {
+		hop_limit = 0U;
+
+		if (!ctx->servers[j].net_ctx) {
+			continue;
+		}
+
+		/* If mDNS is enabled, then send .local queries only to
+		 * a well known multicast mDNS server address.
+		 */
+		if (IS_ENABLED(CONFIG_MDNS_RESOLVER) && mdns_query &&
+		    !ctx->servers[j].is_mdns) {
+			continue;
+		}
+
+		/* If llmnr is enabled, then all the queries are sent to
+		 * LLMNR multicast address unless it is a mDNS query.
+		 */
+		if (!mdns_query && IS_ENABLED(CONFIG_LLMNR_RESOLVER)) {
+			if (!ctx->servers[j].is_llmnr) {
+				continue;
+			}
+
+			hop_limit = 1U;
+		}
+
+		ret = dns_write(ctx, j, i, dns_data, dns_qname, hop_limit);
+		if (ret < 0) {
+			failure++;
+			continue;
+		}
+
+		/* Do one concurrent query only for each name resolve.
+		 * TODO: Change the i (query index) to do multiple concurrent
+		 *       to each server.
+		 */
+		break;
+	}
+
+	if (failure) {
+		NET_DBG("DNS query failed %d times", failure);
+
+		if (failure == j) {
+			ret = -ENOENT;
+			goto quit;
+		}
+	}
+
+	ret = 0;
+
+quit:
+	if (ret < 0) {
+		if (i >= 0) {
+			if (k_delayed_work_remaining_get(
+				    &ctx->queries[i].timer) > 0) {
+				k_delayed_work_cancel(&ctx->queries[i].timer);
+			}
+
+			ctx->queries[i].cb = NULL;
+		}
+
+		if (dns_id) {
+			*dns_id = 0U;
+		}
+	}
+
+	if (dns_data) {
+		net_buf_unref(dns_data);
+	}
+
+	if (dns_qname) {
+		net_buf_unref(dns_qname);
+	}
+
+	return ret;
+}
+
+int dns_resolve_close(struct dns_resolve_context *ctx)
+{
+	int i;
+
+	if (!ctx->is_used) {
+		return -ENOENT;
+	}
+
+	for (i = 0; i < SERVER_COUNT; i++) {
+		if (ctx->servers[i].net_ctx) {
+			struct net_if *iface;
+
+			iface = net_context_get_iface(ctx->servers[i].net_ctx);
+
+			if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) {
+				net_mgmt_event_notify_with_info(
+					NET_EVENT_DNS_SERVER_DEL,
+					iface,
+					(void *)&ctx->servers[i].dns_server,
+					sizeof(struct sockaddr));
+			} else {
+				net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL,
+						      iface);
+			}
+
+			net_context_put(ctx->servers[i].net_ctx);
+		}
+	}
+
+	ctx->is_used = false;
+
+	return 0;
+}
+
+struct dns_resolve_context *dns_resolve_get_default(void)
+{
+	return &dns_default_ctx;
+}
+
+void dns_init_resolver(void)
+{
+#if defined(CONFIG_DNS_SERVER_IP_ADDRESSES)
+	static const char *dns_servers[SERVER_COUNT + 1];
+	int count = DNS_SERVER_COUNT;
+	int ret;
+
+	if (count > 5) {
+		count = 5;
+	}
+
+	switch (count) {
+#if DNS_SERVER_COUNT > 4
+	case 5:
+		dns_servers[4] = CONFIG_DNS_SERVER5;
+		__fallthrough;
+#endif
+#if DNS_SERVER_COUNT > 3
+	case 4:
+		dns_servers[3] = CONFIG_DNS_SERVER4;
+		__fallthrough;
+#endif
+#if DNS_SERVER_COUNT > 2
+	case 3:
+		dns_servers[2] = CONFIG_DNS_SERVER3;
+		__fallthrough;
+#endif
+#if DNS_SERVER_COUNT > 1
+	case 2:
+		dns_servers[1] = CONFIG_DNS_SERVER2;
+		__fallthrough;
+#endif
+#if DNS_SERVER_COUNT > 0
+	case 1:
+		dns_servers[0] = CONFIG_DNS_SERVER1;
+		__fallthrough;
+#endif
+	case 0:
+		break;
+	}
+
+#if defined(CONFIG_MDNS_RESOLVER) && (MDNS_SERVER_COUNT > 0)
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+	dns_servers[DNS_SERVER_COUNT + 1] = MDNS_IPV6_ADDR;
+	dns_servers[DNS_SERVER_COUNT] = MDNS_IPV4_ADDR;
+#else /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#if defined(CONFIG_NET_IPV6)
+	dns_servers[DNS_SERVER_COUNT] = MDNS_IPV6_ADDR;
+#endif
+#if defined(CONFIG_NET_IPV4)
+	dns_servers[DNS_SERVER_COUNT] = MDNS_IPV4_ADDR;
+#endif
+#endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#endif /* MDNS_RESOLVER && MDNS_SERVER_COUNT > 0 */
+
+#if defined(CONFIG_LLMNR_RESOLVER) && (LLMNR_SERVER_COUNT > 0)
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+	dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT + 1] =
+							LLMNR_IPV6_ADDR;
+	dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV4_ADDR;
+#else /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#if defined(CONFIG_NET_IPV6)
+	dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV6_ADDR;
+#endif
+#if defined(CONFIG_NET_IPV4)
+	dns_servers[DNS_SERVER_COUNT + MDNS_SERVER_COUNT] = LLMNR_IPV4_ADDR;
+#endif
+#endif /* CONFIG_NET_IPV6 && CONFIG_NET_IPV4 */
+#endif /* LLMNR_RESOLVER && LLMNR_SERVER_COUNT > 0 */
+
+	dns_servers[SERVER_COUNT] = NULL;
+
+	ret = dns_resolve_init(dns_resolve_get_default(), dns_servers, NULL);
+	if (ret < 0) {
+		NET_WARN("Cannot initialize DNS resolver (%d)", ret);
+	}
+#endif
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/CMakeLists.txt	(working copy)
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+if(CONFIG_HTTP_PARSER_STRICT)
+zephyr_library_compile_definitions(HTTP_PARSER_STRICT)
+endif()
+
+zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+
+zephyr_library_sources_ifdef(CONFIG_HTTP_PARSER http_parser.c)
+zephyr_library_sources_ifdef(CONFIG_HTTP_PARSER_URL http_parser_url.c)
+zephyr_library_sources_ifdef(CONFIG_HTTP_CLIENT http_client.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/Kconfig	(working copy)
@@ -0,0 +1,36 @@
+# Copyright (c) 2016 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config HTTP_PARSER
+	bool "HTTP Parser support"
+	select HTTP_PARSER_URL
+	help
+	  This option enables the http_parser library from nodejs.
+	  This parser requires some string-related routines commonly
+	  provided by a libc implementation.
+
+config HTTP_PARSER_URL
+	bool "HTTP Parser for URL support"
+	help
+	  This option enables the URI parser library based on source from nodejs.
+	  This parser requires some string-related routines commonly
+	  provided by a libc implementation.
+
+config HTTP_PARSER_STRICT
+	bool "HTTP strict parsing"
+	depends on (HTTP_PARSER || HTTP_PARSER_URL)
+	help
+	  This option enables the strict parsing option
+
+config HTTP_CLIENT
+	bool "HTTP client API [EXPERIMENTAL]"
+	select HTTP_PARSER
+	select HTTP_PARSER_URL
+	help
+	  HTTP client API
+
+module = NET_HTTP
+module-dep = NET_LOG
+module-str = Log level for HTTP client library
+module-help = Enables HTTP client code to output debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/README_http_parser
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/README_http_parser	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/README_http_parser	(working copy)
@@ -0,0 +1,14 @@
+HTTP Parser Support in Zephyr
+-----------------------------
+
+The http-parser library* from the nodejs project is a downstream of an
+externally maintained open source project. The original upstream code
+can be found at:
+
+https://github.com/nodejs/http-parser/releases/tag/v2.7.1
+https://github.com/nodejs/http-parser/archive/v2.7.1.tar.gz
+
+NOTE: The portions which relate to URL parsing have been split out into
+http_parser_url.c (originally located in http_parser.c).
+
+* "http-parser" is the project's name, "http_parser" is used in filenames.
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_client.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_client.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_client.c	(working copy)
@@ -0,0 +1,677 @@
+/** @file
+ * @brief HTTP client API
+ *
+ * An API for applications to send HTTP requests
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_http, CONFIG_NET_HTTP_LOG_LEVEL);
+
+#include <kernel.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <net/net_ip.h>
+#include <net/socket.h>
+#include <net/http_client.h>
+
+#include "net_private.h"
+
+#define HTTP_CONTENT_LEN_SIZE 6
+#define MAX_SEND_BUF_LEN 192
+
+static ssize_t sendall(int sock, const void *buf, size_t len)
+{
+	while (len) {
+		ssize_t out_len = send(sock, buf, len, 0);
+
+		if (out_len < 0) {
+			return -errno;
+		}
+
+		buf = (const char *)buf + out_len;
+		len -= out_len;
+	}
+
+	return 0;
+}
+
+static int http_send_data(int sock, char *send_buf,
+			  size_t send_buf_max_len, size_t *send_buf_pos,
+			  ...)
+{
+	const char *data;
+	va_list va;
+	int ret, end_of_send = *send_buf_pos;
+	int end_of_data, remaining_len;
+
+	va_start(va, send_buf_pos);
+
+	data = va_arg(va, const char *);
+
+	while (data) {
+		end_of_data = 0;
+
+		do {
+			int to_be_copied;
+
+			remaining_len = strlen(data + end_of_data);
+			to_be_copied = send_buf_max_len - end_of_send;
+
+			if (remaining_len > to_be_copied) {
+				strncpy(send_buf + end_of_send,
+					data + end_of_data,
+					to_be_copied);
+
+				end_of_send += to_be_copied;
+				end_of_data += to_be_copied;
+				remaining_len -= to_be_copied;
+
+				LOG_HEXDUMP_DBG(send_buf, end_of_send,
+						"Data to send");
+
+				ret = sendall(sock, send_buf, end_of_send);
+				if (ret < 0) {
+					NET_DBG("Cannot send %d bytes (%d)",
+						end_of_send, ret);
+					goto err;
+				}
+
+				end_of_send = 0;
+				continue;
+			} else {
+				strncpy(send_buf + end_of_send,
+					data + end_of_data,
+					remaining_len);
+				end_of_send += remaining_len;
+				remaining_len = 0;
+			}
+		} while (remaining_len > 0);
+
+		data = va_arg(va, const char *);
+	};
+
+	va_end(va);
+
+	if (end_of_send > (int)send_buf_max_len) {
+		NET_ERR("Sending overflow (%d > %zd)", end_of_send,
+			send_buf_max_len);
+		return -EMSGSIZE;
+	}
+
+	*send_buf_pos = end_of_send;
+
+	return end_of_send;
+
+err:
+	va_end(va);
+
+	return ret;
+}
+
+static int http_flush_data(int sock, const char *send_buf, size_t send_buf_len)
+{
+	LOG_HEXDUMP_DBG(send_buf, send_buf_len, "Data to send");
+
+	return sendall(sock, send_buf, send_buf_len);
+}
+
+static void print_header_field(size_t len, const char *str)
+{
+	if (IS_ENABLED(CONFIG_NET_HTTP_LOG_LEVEL_DBG)) {
+#define MAX_OUTPUT_LEN 128
+		char output[MAX_OUTPUT_LEN];
+
+		/* The value of len does not count \0 so we need to increase it
+		 * by one.
+		 */
+		if ((len + 1) > sizeof(output)) {
+			len = sizeof(output) - 1;
+		}
+
+		snprintk(output, len + 1, "%s", str);
+
+		NET_DBG("[%zd] %s", len, log_strdup(output));
+	}
+}
+
+static int on_url(struct http_parser *parser, const char *at, size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	print_header_field(length, at);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_url) {
+		req->internal.response.http_cb->on_url(parser, at, length);
+	}
+
+	return 0;
+}
+
+static int on_status(struct http_parser *parser, const char *at, size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	uint16_t len;
+
+	len = MIN(length, sizeof(req->internal.response.http_status) - 1);
+	memcpy(req->internal.response.http_status, at, len);
+	req->internal.response.http_status[len] = 0;
+
+	NET_DBG("HTTP response status %d %s", parser->status_code,
+		log_strdup(req->internal.response.http_status));
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_status) {
+		req->internal.response.http_cb->on_status(parser, at, length);
+	}
+
+	return 0;
+}
+
+static int on_header_field(struct http_parser *parser, const char *at,
+			   size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	const char *content_len = "Content-Length";
+	uint16_t len;
+
+	len = strlen(content_len);
+	if (length >= len && strncasecmp(at, content_len, len) == 0) {
+		req->internal.response.cl_present = true;
+	}
+
+	print_header_field(length, at);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_header_field) {
+		req->internal.response.http_cb->on_header_field(parser, at,
+								length);
+	}
+
+	return 0;
+}
+
+#define MAX_NUM_DIGITS	16
+
+static int on_header_value(struct http_parser *parser, const char *at,
+			   size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	char str[MAX_NUM_DIGITS];
+
+	if (req->internal.response.cl_present) {
+		if (length <= MAX_NUM_DIGITS - 1) {
+			long int num;
+
+			memcpy(str, at, length);
+			str[length] = 0;
+
+			num = strtol(str, NULL, 10);
+			if (num == LONG_MIN || num == LONG_MAX) {
+				return -EINVAL;
+			}
+
+			req->internal.response.content_length = num;
+		}
+
+		req->internal.response.cl_present = false;
+	}
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_header_value) {
+		req->internal.response.http_cb->on_header_value(parser, at,
+								length);
+	}
+
+	print_header_field(length, at);
+
+	return 0;
+}
+
+static int on_body(struct http_parser *parser, const char *at, size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	req->internal.response.body_found = 1;
+	req->internal.response.processed += length;
+
+	NET_DBG("Processed %zd length %zd", req->internal.response.processed,
+		length);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_body) {
+		req->internal.response.http_cb->on_body(parser, at, length);
+	}
+
+	if (!req->internal.response.body_start &&
+	    (uint8_t *)at != (uint8_t *)req->internal.response.recv_buf) {
+		req->internal.response.body_start = (uint8_t *)at;
+	}
+
+	if (req->internal.response.cb) {
+		if (http_should_keep_alive(parser)) {
+			NET_DBG("Calling callback for partitioned %zd len data",
+				req->internal.response.data_len);
+
+			req->internal.response.cb(&req->internal.response,
+						  HTTP_DATA_MORE,
+						  req->internal.user_data);
+		} else {
+			NET_DBG("Calling callback for %zd len data",
+				req->internal.response.data_len);
+
+			req->internal.response.cb(&req->internal.response,
+						  HTTP_DATA_FINAL,
+						  req->internal.user_data);
+		}
+
+		/* Re-use the result buffer and start to fill it again */
+		req->internal.response.data_len = 0;
+		req->internal.response.body_start = NULL;
+	}
+
+	return 0;
+}
+
+static int on_headers_complete(struct http_parser *parser)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_headers_complete) {
+		req->internal.response.http_cb->on_headers_complete(parser);
+	}
+
+	if (parser->status_code >= 500 && parser->status_code < 600) {
+		NET_DBG("Status %d, skipping body", parser->status_code);
+		return 1;
+	}
+
+	if ((req->method == HTTP_HEAD || req->method == HTTP_OPTIONS) &&
+	    req->internal.response.content_length > 0) {
+		NET_DBG("No body expected");
+		return 1;
+	}
+
+	NET_DBG("Headers complete");
+
+	return 0;
+}
+
+static int on_message_begin(struct http_parser *parser)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_message_begin) {
+		req->internal.response.http_cb->on_message_begin(parser);
+	}
+
+	NET_DBG("-- HTTP %s response (headers) --",
+		http_method_str(req->method));
+
+	return 0;
+}
+
+static int on_message_complete(struct http_parser *parser)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_message_complete) {
+		req->internal.response.http_cb->on_message_complete(parser);
+	}
+
+	NET_DBG("-- HTTP %s response (complete) --",
+		http_method_str(req->method));
+
+	req->internal.response.message_complete = 1;
+
+	if (req->internal.response.cb) {
+		req->internal.response.cb(&req->internal.response,
+					  HTTP_DATA_FINAL,
+					  req->internal.user_data);
+	}
+
+	return 0;
+}
+
+static int on_chunk_header(struct http_parser *parser)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_chunk_header) {
+		req->internal.response.http_cb->on_chunk_header(parser);
+	}
+
+	return 0;
+}
+
+static int on_chunk_complete(struct http_parser *parser)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+
+	if (req->internal.response.http_cb &&
+	    req->internal.response.http_cb->on_chunk_complete) {
+		req->internal.response.http_cb->on_chunk_complete(parser);
+	}
+
+	return 0;
+}
+
+static void http_client_init_parser(struct http_parser *parser,
+				    struct http_parser_settings *settings)
+{
+	http_parser_init(parser, HTTP_RESPONSE);
+
+	settings->on_body = on_body;
+	settings->on_chunk_complete = on_chunk_complete;
+	settings->on_chunk_header = on_chunk_header;
+	settings->on_headers_complete = on_headers_complete;
+	settings->on_header_field = on_header_field;
+	settings->on_header_value = on_header_value;
+	settings->on_message_begin = on_message_begin;
+	settings->on_message_complete = on_message_complete;
+	settings->on_status = on_status;
+	settings->on_url = on_url;
+}
+
+static int http_wait_data(int sock, struct http_request *req)
+{
+	int total_received = 0;
+	size_t offset = 0;
+	int received, ret;
+
+	do {
+		received = recv(sock, req->internal.response.recv_buf + offset,
+				req->internal.response.recv_buf_len - offset,
+				0);
+		if (received == 0) {
+			/* Connection closed */
+			LOG_DBG("Connection closed");
+			ret = total_received;
+			break;
+		} else if (received < 0) {
+			/* Socket error */
+			LOG_DBG("Connection error (%d)", errno);
+			ret = -errno;
+			break;
+		} else {
+			req->internal.response.data_len += received;
+
+			(void)http_parser_execute(
+				&req->internal.parser,
+				&req->internal.parser_settings,
+				req->internal.response.recv_buf + offset,
+				received);
+		}
+
+		total_received += received;
+		offset += received;
+
+		if (offset >= req->internal.response.recv_buf_len) {
+			offset = 0;
+		}
+
+		if (req->internal.response.message_complete) {
+			ret = total_received;
+			break;
+		}
+
+	} while (true);
+
+	return ret;
+}
+
+static void http_timeout(struct k_work *work)
+{
+	struct http_client_internal_data *data =
+		CONTAINER_OF(work, struct http_client_internal_data, work);
+
+	(void)close(data->sock);
+}
+
+int http_client_req(int sock, struct http_request *req,
+		    int32_t timeout, void *user_data)
+{
+	/* Utilize the network usage by sending data in bigger blocks */
+	char send_buf[MAX_SEND_BUF_LEN];
+	const size_t send_buf_max_len = sizeof(send_buf);
+	size_t send_buf_pos = 0;
+	int total_sent = 0;
+	int ret, total_recv, i;
+	const char *method;
+
+	if (sock < 0 || req == NULL || req->response == NULL ||
+	    req->recv_buf == NULL || req->recv_buf_len == 0) {
+		return -EINVAL;
+	}
+
+	memset(&req->internal.response, 0, sizeof(req->internal.response));
+
+	req->internal.response.http_cb = req->http_cb;
+	req->internal.response.cb = req->response;
+	req->internal.response.recv_buf = req->recv_buf;
+	req->internal.response.recv_buf_len = req->recv_buf_len;
+	req->internal.user_data = user_data;
+	req->internal.sock = sock;
+	req->internal.timeout = SYS_TIMEOUT_MS(timeout);
+
+	method = http_method_str(req->method);
+
+	ret = http_send_data(sock, send_buf, send_buf_max_len, &send_buf_pos,
+			     method, " ", req->url, " ", req->protocol,
+			     HTTP_CRLF, NULL);
+	if (ret < 0) {
+		goto out;
+	}
+
+	total_sent += ret;
+
+	if (req->port) {
+		ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, "Host", ": ", req->host,
+				     ":", req->port, HTTP_CRLF, NULL);
+
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	} else {
+		ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, "Host", ": ", req->host,
+				     HTTP_CRLF, NULL);
+
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	}
+
+	if (req->optional_headers_cb) {
+		ret = http_flush_data(sock, send_buf, send_buf_pos);
+		if (ret < 0) {
+			goto out;
+		}
+
+		send_buf_pos = 0;
+		total_sent += ret;
+
+		ret = req->optional_headers_cb(sock, req, user_data);
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	} else {
+		for (i = 0; req->optional_headers && req->optional_headers[i];
+		     i++) {
+			ret = http_send_data(sock, send_buf, send_buf_max_len,
+					     &send_buf_pos,
+					     req->optional_headers[i], NULL);
+			if (ret < 0) {
+				goto out;
+			}
+
+			total_sent += ret;
+		}
+	}
+
+	for (i = 0; req->header_fields && req->header_fields[i]; i++) {
+		ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, req->header_fields[i],
+				     NULL);
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	}
+
+	if (req->content_type_value) {
+		ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, "Content-Type", ": ",
+				     req->content_type_value, HTTP_CRLF, NULL);
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	}
+
+	if (req->payload || req->payload_cb) {
+		if (req->payload_len) {
+			char content_len_str[HTTP_CONTENT_LEN_SIZE];
+
+			ret = snprintk(content_len_str, HTTP_CONTENT_LEN_SIZE,
+				       "%zd", req->payload_len);
+			if (ret <= 0 || ret >= HTTP_CONTENT_LEN_SIZE) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			ret = http_send_data(sock, send_buf, send_buf_max_len,
+					     &send_buf_pos, "Content-Length", ": ",
+					     content_len_str, HTTP_CRLF,
+					     HTTP_CRLF, NULL);
+		} else {
+			ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, HTTP_CRLF, NULL);
+		}
+
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+
+		ret = http_flush_data(sock, send_buf, send_buf_pos);
+		if (ret < 0) {
+			goto out;
+		}
+
+		send_buf_pos = 0;
+		total_sent += ret;
+
+		if (req->payload_cb) {
+			ret = req->payload_cb(sock, req, user_data);
+			if (ret < 0) {
+				goto out;
+			}
+
+			total_sent += ret;
+		} else {
+			uint32_t length;
+
+			if (req->payload_len == 0) {
+				length = strlen(req->payload);
+			} else {
+				length = req->payload_len;
+			}
+
+			ret = sendall(sock, req->payload, length);
+			if (ret < 0) {
+				goto out;
+			}
+
+			total_sent += length;
+		}
+	} else {
+		ret = http_send_data(sock, send_buf, send_buf_max_len,
+				     &send_buf_pos, HTTP_CRLF, NULL);
+		if (ret < 0) {
+			goto out;
+		}
+	}
+
+	if (send_buf_pos > 0) {
+		ret = http_flush_data(sock, send_buf, send_buf_pos);
+		if (ret < 0) {
+			goto out;
+		}
+
+		total_sent += ret;
+	}
+
+	NET_DBG("Sent %d bytes", total_sent);
+
+	http_client_init_parser(&req->internal.parser,
+				&req->internal.parser_settings);
+
+	if (!K_TIMEOUT_EQ(req->internal.timeout, K_FOREVER) &&
+	    !K_TIMEOUT_EQ(req->internal.timeout, K_NO_WAIT)) {
+		k_delayed_work_init(&req->internal.work, http_timeout);
+		(void)k_delayed_work_submit(&req->internal.work,
+					    req->internal.timeout);
+	}
+
+	/* Request is sent, now wait data to be received */
+	total_recv = http_wait_data(sock, req);
+	if (total_recv < 0) {
+		NET_DBG("Wait data failure (%d)", total_recv);
+	} else {
+		NET_DBG("Received %d bytes", total_recv);
+	}
+
+	if (!K_TIMEOUT_EQ(req->internal.timeout, K_FOREVER) &&
+	    !K_TIMEOUT_EQ(req->internal.timeout, K_NO_WAIT)) {
+		(void)k_delayed_work_cancel(&req->internal.work);
+	}
+
+	return total_sent;
+
+out:
+	return ret;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser.c	(working copy)
@@ -0,0 +1,2364 @@
+/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
+ *
+ * Additional changes are licensed under the same terms as NGINX and
+ * copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <net/http_parser.h>
+#include <sys/__assert.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <toolchain.h>
+
+#ifndef ULLONG_MAX
+# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
+#endif
+
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#ifndef BIT_AT
+# define BIT_AT(a, i)                                                \
+	(!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
+	 (1 << ((unsigned int) (i) & 7))))
+#endif
+
+#ifndef ELEM_AT
+# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
+#endif
+
+#define SET_ERRNO(e)	(parser->http_errno = (e))
+#define CURRENT_STATE() p_state
+#define UPDATE_STATE(V) (p_state = (enum state)(V))
+
+#ifdef __GNUC__
+# define LIKELY(X) __builtin_expect(!!(X), 1)
+# define UNLIKELY(X) __builtin_expect(!!(X), 0)
+#else
+# define LIKELY(X) (X)
+# define UNLIKELY(X) (X)
+#endif
+
+/* Set the mark FOR; non-destructive if mark is already set */
+#define MARK(FOR)                                                          \
+do {                                                                       \
+	if (!FOR##_mark) {                                                 \
+		FOR##_mark = p;                                            \
+	}                                                                  \
+} while (0)
+
+/* Don't allow the total size of the HTTP headers (including the status
+ * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect
+ * embedders against denial-of-service attacks where the attacker feeds
+ * us a never-ending header that the embedder keeps buffering.
+ *
+ * This check is arguably the responsibility of embedders but we're doing
+ * it on the embedder's behalf because most won't bother and this way we
+ * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger
+ * than any reasonable request or response so this should never affect
+ * day-to-day operation.
+ */
+static inline
+int count_header_size(struct http_parser *parser, int bytes)
+{
+	parser->nread += bytes;
+
+	if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) {
+		parser->http_errno = HPE_HEADER_OVERFLOW;
+		return -1;
+	}
+
+	return 0;
+}
+
+#define PROXY_CONNECTION "proxy-connection"
+#define CONNECTION "connection"
+#define CONTENT_LENGTH "content-length"
+#define TRANSFER_ENCODING "transfer-encoding"
+#define UPGRADE "upgrade"
+#define CHUNKED "chunked"
+#define KEEP_ALIVE "keep-alive"
+#define CLOSE "close"
+
+
+static const
+char *method_strings[] = {"DELETE", "GET", "HEAD", "POST", "PUT", "CONNECT",
+			  "OPTIONS", "TRACE", "COPY", "LOCK", "MKCOL", "MOVE",
+			  "PROPFIND", "PROPPATCH", "SEARCH", "UNLOCK", "BIND",
+			  "REBIND", "UNBIND", "ACL", "REPORT", "MKACTIVITY",
+			  "CHECKOUT", "MERGE", "M-SEARCH", "NOTIFY",
+			  "SUBSCRIBE", "UNSUBSCRIBE", "PATCH", "PURGE",
+			  "MKCALENDAR", "LINK", "UNLINK"};
+
+
+/* Tokens as defined by rfc 2616. Also lowercases them.
+ *        token       = 1*<any CHAR except CTLs or separators>
+ *     separators     = "(" | ")" | "<" | ">" | "@"
+ *                    | "," | ";" | ":" | "\" | <">
+ *                    | "/" | "[" | "]" | "?" | "="
+ *                    | "{" | "}" | SP | HT
+ */
+static const char tokens[256] = {
+/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
+	0,       0,       0,       0,       0,       0,       0,       0,
+/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
+	0,       0,       0,       0,       0,       0,       0,       0,
+/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
+	0,       0,       0,       0,       0,       0,       0,       0,
+/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
+	0,       0,       0,       0,       0,       0,       0,       0,
+/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
+	0,      '!',      0,      '#',     '$',     '%',     '&',    '\'',
+/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
+	0,       0,      '*',     '+',      0,      '-',     '.',      0,
+/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
+	'0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
+/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
+	'8',     '9',      0,       0,       0,       0,       0,       0,
+/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
+	0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
+/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
+	'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
+/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
+	'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
+/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
+	'x',     'y',     'z',      0,       0,       0,      '^',     '_',
+/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
+	'`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
+/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
+	'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
+/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
+	'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
+/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
+	'x',     'y',     'z',      0,      '|',      0,      '~',       0
+};
+
+
+static const
+int8_t unhex[256] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+#define PARSING_HEADER(state) (state <= s_headers_done)
+
+enum header_states {
+	h_general = 0,
+	h_C,
+	h_CO,
+	h_CON,
+	h_matching_connection,
+	h_matching_proxy_connection,
+	h_matching_content_length,
+	h_matching_transfer_encoding,
+	h_matching_upgrade,
+	h_connection,
+	h_content_length,
+	h_transfer_encoding,
+	h_upgrade,
+	h_matching_transfer_encoding_chunked,
+	h_matching_connection_token_start,
+	h_matching_connection_keep_alive,
+	h_matching_connection_close,
+	h_matching_connection_upgrade,
+	h_matching_connection_token,
+	h_transfer_encoding_chunked,
+	h_connection_keep_alive,
+	h_connection_close,
+	h_connection_upgrade
+};
+
+static inline
+int cb_notify(struct http_parser *parser, enum state *current_state, http_cb cb,
+	      int cb_error, size_t *parsed, size_t already_parsed)
+{
+	__ASSERT_NO_MSG(HTTP_PARSER_ERRNO(parser) == HPE_OK);
+
+	if (cb == NULL) {
+		return 0;
+	}
+
+	parser->state = *current_state;
+	if (UNLIKELY(cb(parser) != 0)) {
+		SET_ERRNO(cb_error);
+	}
+	*current_state = parser->state;
+	/* We either errored above or got paused; get out */
+	if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {
+		*parsed = already_parsed;
+		return -HTTP_PARSER_ERRNO(parser);
+	}
+
+	return 0;
+}
+
+static inline
+int cb_data(struct http_parser *parser, http_data_cb cb, int cb_error,
+	    enum state *current_state, size_t *parsed, size_t already_parsed,
+	    const char **mark, size_t len)
+{
+	int rc;
+
+	__ASSERT_NO_MSG(HTTP_PARSER_ERRNO(parser) == HPE_OK);
+	if (*mark == NULL) {
+		return 0;
+	}
+	if (cb == NULL) {
+		goto lb_end;
+	}
+
+	parser->state = *current_state;
+	rc = cb(parser, *mark, len);
+	if (UNLIKELY(rc != 0)) {
+		SET_ERRNO(cb_error);
+	}
+	*current_state = parser->state;
+	/* We either errored above or got paused; get out */
+	if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {
+		*parsed = already_parsed;
+		return -HTTP_PARSER_ERRNO(parser);
+	}
+lb_end:
+	*mark = NULL;
+
+	return 0;
+}
+
+
+/* Macros for character classes; depends on strict-mode  */
+#define CR                  '\r'
+#define LF                  '\n'
+#define LOWER(c)            (unsigned char)(c | 0x20)
+#define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
+#define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
+#define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
+#define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
+
+#define IS_MARK(c)		((c) == '-' || (c) == '_' || (c) == '.' || \
+				 (c) == '!' || (c) == '~' || (c) == '*' || \
+				 (c) == '\'' || (c) == '(' || (c) == ')')
+
+#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
+				(c) == ';' || (c) == ':' || (c) == '&' ||  \
+				(c) == '=' || (c) == '+' || (c) == '$' ||  \
+				(c) == ',')
+
+#define STRICT_TOKEN(c)     (tokens[(unsigned char)c])
+
+#ifdef HTTP_PARSER_STRICT
+#define TOKEN(c)            (tokens[(unsigned char)c])
+#define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+#else
+#define TOKEN(c)            ((c == ' ') ? ' ' : tokens[(unsigned char)c])
+#define IS_HOST_CHAR(c)                                                        \
+	(IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
+#endif
+
+/**
+ * Verify that a char is a valid visible (printable) US-ASCII
+ * character or %x80-FF
+ **/
+#define IS_HEADER_CHAR(ch)                                                     \
+	(ch == CR || ch == LF || ch == 9 || \
+	 ((unsigned char)ch > 31 && ch != 127))
+
+#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
+
+
+#ifdef HTTP_PARSER_STRICT
+static inline
+int strict_check(struct http_parser *parser, int c)
+{
+	if (c) {
+		parser->http_errno = HPE_STRICT;
+		return -1;
+	}
+	return 0;
+}
+
+# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
+#else
+static inline
+int strict_check(struct http_parser *parser, int c)
+{
+	(void)parser;
+	(void)c;
+	return 0;
+}
+# define NEW_MESSAGE() start_state
+#endif
+
+static struct {
+	const char *name;
+	const char *description;
+} http_strerror_tab[] = {
+	{"HPE_OK", "success"},
+	{"HPE_CB_message_begin", "the on_message_begin callback failed"},
+	{"HPE_CB_url", "the on_url callback failed"},
+	{"HPE_CB_header_field", "the on_header_field callback failed"},
+	{"HPE_CB_header_value", "the on_header_value callback failed"},
+	{"HPE_CB_headers_complete", "the on_headers_complete callback failed"},
+	{"HPE_CB_body", "the on_body callback failed"},
+	{"HPE_CB_message_complete", "the on_message_complete callback failed"},
+	{"HPE_CB_status", "the on_status callback failed"},
+	{"HPE_CB_chunk_header", "the on_chunk_header callback failed"},
+	{"HPE_CB_chunk_complete", "the on_chunk_complete callback failed"},
+	{"HPE_INVALID_EOF_STATE", "stream ended at an unexpected time"},
+	{"HPE_HEADER_OVERFLOW", "too many header bytes seen; "
+				"overflow detected"},
+	{"HPE_CLOSED_CONNECTION", "data received after completed connection: "
+				  "close message"},
+	{"HPE_INVALID_VERSION", "invalid HTTP version"},
+	{"HPE_INVALID_STATUS", "invalid HTTP status code"},
+	{"HPE_INVALID_METHOD", "invalid HTTP method"},
+	{"HPE_INVALID_URL", "invalid URL"},
+	{"HPE_INVALID_HOST", "invalid host"},
+	{"HPE_INVALID_PORT", "invalid port"},
+	{"HPE_INVALID_PATH", "invalid path"},
+	{"HPE_INVALID_QUERY_STRING", "invalid query string"},
+	{"HPE_INVALID_FRAGMENT", "invalid fragment"},
+	{"HPE_LF_EXPECTED", "LF character expected"},
+	{"HPE_INVALID_HEADER_TOKEN", "invalid character in header"},
+	{"HPE_INVALID_CONTENT_LENGTH", "invalid character in content-length "
+				       "header"},
+	{"HPE_UNEXPECTED_CONTENT_LENGTH", "unexpected content-length header"},
+	{"HPE_INVALID_CHUNK_SIZE", "invalid character in chunk size header"},
+	{"HPE_INVALID_CONSTANT", "invalid constant string"},
+	{"HPE_INVALID_INTERNAL_STATE", "encountered unexpected internal state"},
+	{"HPE_STRICT", "strict mode assertion failed"},
+	{"HPE_PAUSED", "parser is paused"},
+	{"HPE_UNKNOWN", "an unknown error occurred"}
+};
+
+int http_message_needs_eof(const struct http_parser *parser);
+
+static
+int parser_header_state(struct http_parser *parser, char ch, char c)
+{
+	int cond1;
+
+	switch (parser->header_state) {
+	case h_general:
+		break;
+
+	case h_C:
+		parser->index++;
+		parser->header_state = (c == 'o' ? h_CO : h_general);
+		break;
+
+	case h_CO:
+		parser->index++;
+		parser->header_state = (c == 'n' ? h_CON : h_general);
+		break;
+
+	case h_CON:
+		parser->index++;
+		switch (c) {
+		case 'n':
+			parser->header_state = h_matching_connection;
+			break;
+		case 't':
+			parser->header_state = h_matching_content_length;
+			break;
+		default:
+			parser->header_state = h_general;
+			break;
+		}
+		break;
+
+	/* connection */
+
+	case h_matching_connection:
+		parser->index++;
+		cond1 = parser->index > sizeof(CONNECTION) - 1;
+		if (cond1 || c != CONNECTION[parser->index]) {
+			parser->header_state = h_general;
+		} else if (parser->index == sizeof(CONNECTION) - 2) {
+			parser->header_state = h_connection;
+		}
+		break;
+
+	/* proxy-connection */
+
+	case h_matching_proxy_connection:
+		parser->index++;
+		cond1 = parser->index > sizeof(PROXY_CONNECTION) - 1;
+		if (cond1 || c != PROXY_CONNECTION[parser->index]) {
+			parser->header_state = h_general;
+		} else if (parser->index == sizeof(PROXY_CONNECTION) - 2) {
+			parser->header_state = h_connection;
+		}
+		break;
+
+	/* content-length */
+
+	case h_matching_content_length:
+		parser->index++;
+		cond1 = parser->index > sizeof(CONTENT_LENGTH) - 1;
+		if (cond1 || c != CONTENT_LENGTH[parser->index]) {
+			parser->header_state = h_general;
+		} else if (parser->index == sizeof(CONTENT_LENGTH) - 2) {
+			parser->header_state = h_content_length;
+		}
+		break;
+
+	/* transfer-encoding */
+
+	case h_matching_transfer_encoding:
+		parser->index++;
+		cond1 = parser->index > sizeof(TRANSFER_ENCODING) - 1;
+		if (cond1 || c != TRANSFER_ENCODING[parser->index]) {
+			parser->header_state = h_general;
+		} else if (parser->index == sizeof(TRANSFER_ENCODING) - 2) {
+			parser->header_state = h_transfer_encoding;
+		}
+		break;
+
+	/* upgrade */
+
+	case h_matching_upgrade:
+		parser->index++;
+		cond1 = parser->index > sizeof(UPGRADE) - 1;
+		if (cond1 || c != UPGRADE[parser->index]) {
+			parser->header_state = h_general;
+		} else if (parser->index == sizeof(UPGRADE) - 2) {
+			parser->header_state = h_upgrade;
+		}
+		break;
+
+	case h_connection:
+	case h_content_length:
+	case h_transfer_encoding:
+	case h_upgrade:
+		if (ch != ' ') {
+			parser->header_state = h_general;
+		}
+		break;
+
+	default:
+		__ASSERT_NO_MSG(0 && "Unknown header_state");
+		break;
+	}
+	return 0;
+}
+
+static
+int header_states(struct http_parser *parser, const char *data, size_t len,
+		  const char **ptr, enum state *p_state,
+		  enum header_states *header_state, char ch, char c)
+{
+	enum header_states h_state = *header_state;
+	const char *p = *ptr;
+	int cond1;
+
+	switch (h_state) {
+	case h_general: {
+		size_t limit = data + len - p;
+		const char *p_cr;
+		const char *p_lf;
+
+		limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
+		p_cr = (const char *)memchr(p, CR, limit);
+		p_lf = (const char *)memchr(p, LF, limit);
+		if (p_cr != NULL) {
+			if (p_lf != NULL && p_cr >= p_lf) {
+				p = p_lf;
+			} else {
+				p = p_cr;
+			}
+		} else if (UNLIKELY(p_lf != NULL)) {
+			p = p_lf;
+		} else {
+			p = data + len;
+		}
+		--p;
+
+		break;
+	}
+
+	case h_connection:
+	case h_transfer_encoding:
+		__ASSERT_NO_MSG(0 && "Shouldn't get here.");
+		break;
+
+	case h_content_length: {
+		uint64_t t;
+		uint64_t value;
+
+		if (ch == ' ') {
+			break;
+		}
+
+		if (UNLIKELY(!IS_NUM(ch))) {
+			SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+			parser->header_state = h_state;
+			return -1;
+		}
+
+		t = parser->content_length;
+		t *= 10U;
+		t += ch - '0';
+
+		/* Overflow? Test against a conservative limit for simplicity */
+		value = (ULLONG_MAX - 10) / 10;
+
+		if (UNLIKELY(value < parser->content_length)) {
+			SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+			parser->header_state = h_state;
+			return -1;
+		}
+
+		parser->content_length = t;
+		break;
+	}
+
+	/* Transfer-Encoding: chunked */
+	case h_matching_transfer_encoding_chunked:
+		parser->index++;
+		cond1 = parser->index > sizeof(CHUNKED) - 1;
+		if (cond1 || c != CHUNKED[parser->index]) {
+			h_state = h_general;
+		} else if (parser->index == sizeof(CHUNKED) - 2) {
+			h_state = h_transfer_encoding_chunked;
+		}
+		break;
+
+	case h_matching_connection_token_start:
+		/* looking for 'Connection: keep-alive' */
+		if (c == 'k') {
+			h_state = h_matching_connection_keep_alive;
+			/* looking for 'Connection: close' */
+		} else if (c == 'c') {
+			h_state = h_matching_connection_close;
+		} else if (c == 'u') {
+			h_state = h_matching_connection_upgrade;
+		} else if (STRICT_TOKEN(c)) {
+			h_state = h_matching_connection_token;
+		} else if (c == ' ' || c == '\t') {
+			/* Skip lws */
+		} else {
+			h_state = h_general;
+		}
+		break;
+
+	/* looking for 'Connection: keep-alive' */
+	case h_matching_connection_keep_alive:
+		parser->index++;
+		cond1 = parser->index > sizeof(KEEP_ALIVE) - 1;
+		if (cond1 || c != KEEP_ALIVE[parser->index]) {
+			h_state = h_matching_connection_token;
+		} else if (parser->index == sizeof(KEEP_ALIVE) - 2) {
+			h_state = h_connection_keep_alive;
+		}
+		break;
+
+	/* looking for 'Connection: close' */
+	case h_matching_connection_close:
+		parser->index++;
+		cond1 = parser->index > sizeof(CLOSE) - 1;
+		if (cond1 || c != CLOSE[parser->index]) {
+			h_state = h_matching_connection_token;
+		} else if (parser->index == sizeof(CLOSE) - 2) {
+			h_state = h_connection_close;
+		}
+		break;
+
+	/* looking for 'Connection: upgrade' */
+	case h_matching_connection_upgrade:
+		parser->index++;
+		cond1 = parser->index > sizeof(UPGRADE) - 1;
+		if (cond1 || c != UPGRADE[parser->index]) {
+			h_state = h_matching_connection_token;
+		} else if (parser->index == sizeof(UPGRADE) - 2) {
+			h_state = h_connection_upgrade;
+		}
+		break;
+
+	case h_matching_connection_token:
+		if (ch == ',') {
+			h_state = h_matching_connection_token_start;
+			parser->index = 0U;
+		}
+		break;
+
+	case h_transfer_encoding_chunked:
+		if (ch != ' ') {
+			h_state = h_general;
+		}
+		break;
+
+	case h_connection_keep_alive:
+	case h_connection_close:
+	case h_connection_upgrade:
+		if (ch == ',') {
+			if (h_state == h_connection_keep_alive) {
+				parser->flags |= F_CONNECTION_KEEP_ALIVE;
+			} else if (h_state == h_connection_close) {
+				parser->flags |= F_CONNECTION_CLOSE;
+			} else if (h_state == h_connection_upgrade) {
+				parser->flags |= F_CONNECTION_UPGRADE;
+			}
+			h_state = h_matching_connection_token_start;
+			parser->index = 0U;
+		} else if (ch != ' ') {
+			h_state = h_matching_connection_token;
+		}
+		break;
+
+	default:
+		*p_state = s_header_value;
+		h_state = h_general;
+		break;
+	}
+
+	*header_state = h_state;
+	*ptr = p;
+
+	return 0;
+}
+
+static
+int zero_content_length(struct http_parser *parser,
+			const struct http_parser_settings *settings,
+			enum state *current_state, size_t *parsed,
+			const char *p, const char *data)
+{
+	enum state p_state = *current_state;
+	int rc;
+
+	if (parser->content_length == 0U) {
+		/* Content-Length header given but zero:
+		 * Content-Length: 0\r\n
+		 */
+		UPDATE_STATE(NEW_MESSAGE());
+
+		rc = cb_notify(parser, &p_state, settings->on_message_complete,
+			       HPE_CB_message_complete, parsed, p - data + 1);
+		if (rc != 0) {
+			return rc;
+		}
+
+	} else if (parser->content_length != ULLONG_MAX) {
+		/* Content-Length header given and
+		 * non-zero
+		 */
+		UPDATE_STATE(s_body_identity);
+	} else {
+		if (!http_message_needs_eof(parser)) {
+			/* Assume content-length 0 -
+			 * read the next
+			 */
+			UPDATE_STATE(NEW_MESSAGE());
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_message_complete,
+				       HPE_CB_message_complete, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+
+		} else {
+			/* Read body until EOF */
+			UPDATE_STATE(s_body_identity_eof);
+		}
+	}
+
+	*current_state = p_state;
+
+	return 0;
+}
+
+static
+int parser_execute(struct http_parser *parser,
+		   const struct http_parser_settings *settings,
+		   const char *data, size_t len, size_t *parsed)
+{
+	const unsigned int lenient = parser->lenient_http_headers;
+	enum state p_state = (enum state) parser->state;
+	const char *p = data;
+	const char *header_field_mark = 0;
+	const char *header_value_mark = 0;
+	const char *url_mark = 0;
+	const char *body_mark = 0;
+	const char *status_mark = 0;
+	int8_t unhex_val;
+	int rc;
+	char ch;
+	char c;
+
+	*parsed = 0;
+
+	/* We're in an error state. Don't bother doing anything. */
+	if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+		return 0;
+	}
+
+	if (len == 0) {
+		switch (CURRENT_STATE()) {
+		case s_body_identity_eof:
+			/* Use of CALLBACK_NOTIFY() here would erroneously
+			 * return 1 byte read if
+			 * we got paused.
+			 */
+			cb_notify(parser, &p_state,
+				  settings->on_message_complete,
+				  HPE_CB_message_complete, parsed, p - data);
+			return 0;
+
+		case s_dead:
+		case s_start_req_or_res:
+		case s_start_res:
+		case s_start_req:
+			return 0;
+
+		default:
+			SET_ERRNO(HPE_INVALID_EOF_STATE);
+			return 1;
+		}
+	}
+
+
+	if (CURRENT_STATE() == s_header_field) {
+		header_field_mark = data;
+	}
+	if (CURRENT_STATE() == s_header_value) {
+		header_value_mark = data;
+	}
+	switch (CURRENT_STATE()) {
+	case s_req_path:
+	case s_req_schema:
+	case s_req_schema_slash:
+	case s_req_schema_slash_slash:
+	case s_req_server_start:
+	case s_req_server:
+	case s_req_server_with_at:
+	case s_req_query_string_start:
+	case s_req_query_string:
+	case s_req_fragment_start:
+	case s_req_fragment:
+		url_mark = data;
+		break;
+	case s_res_status:
+		status_mark = data;
+		break;
+	default:
+		break;
+	}
+
+	for (p = data; p != data + len; p++) {
+		ch = *p;
+
+		if (PARSING_HEADER(CURRENT_STATE())) {
+			rc = count_header_size(parser, 1);
+			if (rc != 0) {
+				goto error;
+			}
+		}
+
+reexecute:
+		switch (CURRENT_STATE()) {
+
+		case s_dead:
+			/* this state is used after a 'Connection: close'
+			 * message
+			 * the parser will error out if it reads another message
+			 */
+			if (LIKELY(ch == CR || ch == LF)) {
+				break;
+			}
+
+			SET_ERRNO(HPE_CLOSED_CONNECTION);
+			goto error;
+
+		case s_start_req_or_res: {
+			if (ch == CR || ch == LF) {
+				break;
+			}
+			parser->flags = 0U;
+			parser->content_length = ULLONG_MAX;
+
+			if (ch == 'H') {
+				UPDATE_STATE(s_res_or_resp_H);
+
+				rc = cb_notify(parser, &p_state,
+					       settings->on_message_begin,
+					       HPE_CB_message_begin,
+					       parsed, p - data + 1);
+				if (rc != 0) {
+					return rc;
+				}
+			} else {
+				parser->type = HTTP_REQUEST;
+				UPDATE_STATE(s_start_req);
+				goto reexecute;
+			}
+
+			break;
+		}
+
+		case s_res_or_resp_H:
+			if (ch == 'T') {
+				parser->type = HTTP_RESPONSE;
+				UPDATE_STATE(s_res_HT);
+			} else {
+				if (UNLIKELY(ch != 'E')) {
+					SET_ERRNO(HPE_INVALID_CONSTANT);
+					goto error;
+				}
+
+				parser->type = HTTP_REQUEST;
+				parser->method = HTTP_HEAD;
+				parser->index = 2U;
+				UPDATE_STATE(s_req_method);
+			}
+			break;
+
+		case s_start_res: {
+			parser->flags = 0U;
+			parser->content_length = ULLONG_MAX;
+
+			switch (ch) {
+			case 'H':
+				UPDATE_STATE(s_res_H);
+				break;
+
+			case CR:
+			case LF:
+				break;
+
+			default:
+				SET_ERRNO(HPE_INVALID_CONSTANT);
+				goto error;
+			}
+
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_message_begin,
+				       HPE_CB_message_begin, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+			break;
+		}
+
+		case s_res_H:
+			rc = strict_check(parser, ch != 'T');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_res_HT);
+			break;
+
+		case s_res_HT:
+			rc = strict_check(parser, ch != 'T');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_res_HTT);
+			break;
+
+		case s_res_HTT:
+			rc = strict_check(parser, ch != 'P');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_res_HTTP);
+			break;
+
+		case s_res_HTTP:
+			rc = strict_check(parser, ch != '/');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_res_first_http_major);
+			break;
+
+		case s_res_first_http_major:
+			if (UNLIKELY(ch < '0' || ch > '9')) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_major = ch - '0';
+			UPDATE_STATE(s_res_http_major);
+			break;
+
+		/* major HTTP version or dot */
+		case s_res_http_major: {
+			if (ch == '.') {
+				UPDATE_STATE(s_res_first_http_minor);
+				break;
+			}
+
+			if (!IS_NUM(ch)) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_major *= 10U;
+			parser->http_major += ch - '0';
+
+			if (UNLIKELY(parser->http_major > 999)) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			break;
+		}
+
+		/* first digit of minor HTTP version */
+		case s_res_first_http_minor:
+			if (UNLIKELY(!IS_NUM(ch))) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_minor = ch - '0';
+			UPDATE_STATE(s_res_http_minor);
+			break;
+
+		/* minor HTTP version or end of request line */
+		case s_res_http_minor: {
+			if (ch == ' ') {
+				UPDATE_STATE(s_res_first_status_code);
+				break;
+			}
+
+			if (UNLIKELY(!IS_NUM(ch))) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_minor *= 10U;
+			parser->http_minor += ch - '0';
+
+			if (UNLIKELY(parser->http_minor > 999)) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			break;
+		}
+
+		case s_res_first_status_code: {
+			if (!IS_NUM(ch)) {
+				if (ch == ' ') {
+					break;
+				}
+
+				SET_ERRNO(HPE_INVALID_STATUS);
+				goto error;
+			}
+			parser->status_code = ch - '0';
+			UPDATE_STATE(s_res_status_code);
+			break;
+		}
+
+		case s_res_status_code: {
+			if (!IS_NUM(ch)) {
+				switch (ch) {
+				case ' ':
+					UPDATE_STATE(s_res_status_start);
+					break;
+				case CR:
+					UPDATE_STATE(s_res_line_almost_done);
+					break;
+				case LF:
+					UPDATE_STATE(s_header_field_start);
+					break;
+				default:
+					SET_ERRNO(HPE_INVALID_STATUS);
+					goto error;
+				}
+				break;
+			}
+
+			parser->status_code *= 10U;
+			parser->status_code += ch - '0';
+
+			if (UNLIKELY(parser->status_code > 999)) {
+				SET_ERRNO(HPE_INVALID_STATUS);
+				goto error;
+			}
+
+			break;
+		}
+
+		case s_res_status_start: {
+			if (ch == CR) {
+				UPDATE_STATE(s_res_line_almost_done);
+				break;
+			}
+
+			if (ch == LF) {
+				UPDATE_STATE(s_header_field_start);
+				break;
+			}
+
+			MARK(status);
+			UPDATE_STATE(s_res_status);
+			parser->index = 0U;
+			break;
+		}
+
+		case s_res_status:
+			if (ch == CR) {
+				UPDATE_STATE(s_res_line_almost_done);
+				rc = cb_data(parser, settings->on_status,
+					     HPE_CB_status, &p_state, parsed,
+					     p - data + 1, &status_mark,
+					     p - status_mark);
+				if (rc != 0) {
+					return rc;
+				}
+				break;
+			}
+
+			if (ch == LF) {
+				UPDATE_STATE(s_header_field_start);
+				rc = cb_data(parser, settings->on_status,
+					     HPE_CB_status, &p_state, parsed,
+					     p - data + 1, &status_mark,
+					     p - status_mark);
+				if (rc != 0) {
+					return rc;
+				}
+
+				break;
+			}
+
+			break;
+
+		case s_res_line_almost_done:
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_header_field_start);
+			break;
+
+		case s_start_req: {
+			if (ch == CR || ch == LF) {
+				break;
+			}
+			parser->flags = 0U;
+			parser->content_length = ULLONG_MAX;
+
+			if (UNLIKELY(!IS_ALPHA(ch))) {
+				SET_ERRNO(HPE_INVALID_METHOD);
+				goto error;
+			}
+
+			parser->method = (enum http_method) 0;
+			parser->index = 1U;
+			switch (ch) {
+			case 'A':
+				parser->method = HTTP_ACL;
+				break;
+			case 'B':
+				parser->method = HTTP_BIND;
+				break;
+			case 'C':
+				parser->method = HTTP_CONNECT;
+				/* or COPY, CHECKOUT */
+				break;
+			case 'D':
+				parser->method = HTTP_DELETE;
+				break;
+			case 'G':
+				parser->method = HTTP_GET;
+				break;
+			case 'H':
+				parser->method = HTTP_HEAD;
+				break;
+			case 'L':
+				parser->method = HTTP_LOCK; /* or LINK */
+				break;
+			case 'M':
+				parser->method =
+					HTTP_MKCOL;
+				/* or MOVE, MKACTIVITY, MERGE, M-SEARCH,
+				 * MKCALENDAR
+				 */
+				break;
+			case 'N':
+				parser->method = HTTP_NOTIFY;
+				break;
+			case 'O':
+				parser->method = HTTP_OPTIONS;
+				break;
+			case 'P':
+				parser->method = HTTP_POST;
+				/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
+				break;
+			case 'R':
+				parser->method = HTTP_REPORT; /* or REBIND */
+				break;
+			case 'S':
+				parser->method = HTTP_SUBSCRIBE; /* or SEARCH */
+				break;
+			case 'T':
+				parser->method = HTTP_TRACE;
+				break;
+			case 'U':
+				parser->method = HTTP_UNLOCK;
+				/* or UNSUBSCRIBE, UNBIND, UNLINK */
+				break;
+			default:
+				SET_ERRNO(HPE_INVALID_METHOD);
+				goto error;
+			}
+			UPDATE_STATE(s_req_method);
+
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_message_begin,
+				       HPE_CB_message_begin, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+			break;
+		}
+
+		case s_req_method: {
+			const char *matcher;
+
+			if (UNLIKELY(ch == '\0')) {
+				SET_ERRNO(HPE_INVALID_METHOD);
+				goto error;
+			}
+
+			matcher = method_strings[parser->method];
+			if (ch == ' ' && matcher[parser->index] == '\0') {
+				UPDATE_STATE(s_req_spaces_before_url);
+			} else if (ch == matcher[parser->index]) {
+				; /* nada */
+			} else if (IS_ALPHA(ch)) {
+
+				uint64_t sw_option = parser->method << 16 |
+						     parser->index << 8 | ch;
+				switch (sw_option) {
+				case (HTTP_POST << 16 | 1 << 8 | 'U'):
+					parser->method = HTTP_PUT;
+					break;
+				case (HTTP_POST << 16 | 1 << 8 | 'A'):
+					parser->method = HTTP_PATCH;
+					break;
+				case (HTTP_CONNECT << 16 | 1 << 8 | 'H'):
+					parser->method = HTTP_CHECKOUT;
+					break;
+				case (HTTP_CONNECT << 16 | 2 << 8 | 'P'):
+					parser->method = HTTP_COPY;
+					break;
+				case (HTTP_MKCOL << 16 | 1 << 8 | 'O'):
+					parser->method = HTTP_MOVE;
+					break;
+				case (HTTP_MKCOL << 16 | 1 << 8 | 'E'):
+					parser->method = HTTP_MERGE;
+					break;
+				case (HTTP_MKCOL << 16 | 2 << 8 | 'A'):
+					parser->method = HTTP_MKACTIVITY;
+					break;
+				case (HTTP_MKCOL << 16 | 3 << 8 | 'A'):
+					parser->method = HTTP_MKCALENDAR;
+					break;
+				case (HTTP_SUBSCRIBE << 16 | 1 << 8 | 'E'):
+					parser->method = HTTP_SEARCH;
+					break;
+				case (HTTP_REPORT << 16 | 2 << 8 | 'B'):
+					parser->method = HTTP_REBIND;
+					break;
+				case (HTTP_POST << 16 | 1 << 8 | 'R'):
+					parser->method = HTTP_PROPFIND;
+					break;
+				case (HTTP_PROPFIND << 16 | 4 << 8 | 'P'):
+					parser->method = HTTP_PROPPATCH;
+					break;
+				case (HTTP_PUT << 16 | 2 << 8 | 'R'):
+					parser->method = HTTP_PURGE;
+					break;
+				case (HTTP_LOCK << 16 | 1 << 8 | 'I'):
+					parser->method = HTTP_LINK;
+					break;
+				case (HTTP_UNLOCK << 16 | 2 << 8 | 'S'):
+					parser->method = HTTP_UNSUBSCRIBE;
+					break;
+				case (HTTP_UNLOCK << 16 | 2 << 8 | 'B'):
+					parser->method = HTTP_UNBIND;
+					break;
+				case (HTTP_UNLOCK << 16 | 3 << 8 | 'I'):
+					parser->method = HTTP_UNLINK;
+					break;
+				default:
+					parser->http_errno = HPE_INVALID_METHOD;
+					goto error;
+				}
+			} else if (ch == '-' &&
+					parser->index == 1U &&
+					parser->method == HTTP_MKCOL) {
+				parser->method = HTTP_MSEARCH;
+			} else {
+				SET_ERRNO(HPE_INVALID_METHOD);
+				goto error;
+			}
+
+			++parser->index;
+			break;
+		}
+
+		case s_req_spaces_before_url: {
+			if (ch == ' ') {
+				break;
+			}
+
+			MARK(url);
+			if (parser->method == HTTP_CONNECT) {
+				UPDATE_STATE(s_req_server_start);
+			}
+
+			UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
+			if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+				SET_ERRNO(HPE_INVALID_URL);
+				goto error;
+			}
+
+			break;
+		}
+
+		case s_req_schema:
+		case s_req_schema_slash:
+		case s_req_schema_slash_slash:
+		case s_req_server_start: {
+			switch (ch) {
+			/* No whitespace allowed here */
+			case ' ':
+			case CR:
+			case LF:
+				SET_ERRNO(HPE_INVALID_URL);
+				goto error;
+			default:
+				UPDATE_STATE
+					(parse_url_char(CURRENT_STATE(), ch));
+				if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+					SET_ERRNO(HPE_INVALID_URL);
+					goto error;
+				}
+			}
+
+			break;
+		}
+
+		case s_req_server:
+		case s_req_server_with_at:
+		case s_req_path:
+		case s_req_query_string_start:
+		case s_req_query_string:
+		case s_req_fragment_start:
+		case s_req_fragment: {
+			switch (ch) {
+			case ' ':
+				UPDATE_STATE(s_req_http_start);
+				rc = cb_data(parser, settings->on_url,
+					     HPE_CB_url, &p_state, parsed,
+					     p - data + 1, &url_mark,
+					     p - url_mark);
+				if (rc != 0) {
+					return rc;
+				}
+
+				break;
+			case CR:
+			case LF:
+				parser->http_major = 0U;
+				parser->http_minor = 9U;
+				UPDATE_STATE((ch == CR) ?
+					     s_req_line_almost_done :
+					     s_header_field_start);
+				rc = cb_data(parser, settings->on_url,
+					     HPE_CB_url, &p_state, parsed,
+					     p - data + 1, &url_mark,
+					     p - url_mark);
+				if (rc != 0) {
+					return rc;
+				}
+
+				break;
+			default:
+				UPDATE_STATE
+					(parse_url_char(CURRENT_STATE(), ch));
+				if (UNLIKELY(CURRENT_STATE() == s_dead)) {
+					SET_ERRNO(HPE_INVALID_URL);
+					goto error;
+				}
+			}
+			break;
+		}
+
+		case s_req_http_start:
+			switch (ch) {
+			case 'H':
+				UPDATE_STATE(s_req_http_H);
+				break;
+			case ' ':
+				break;
+			default:
+				SET_ERRNO(HPE_INVALID_CONSTANT);
+				goto error;
+			}
+			break;
+
+		case s_req_http_H:
+			rc = strict_check(parser, ch != 'T');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_req_http_HT);
+			break;
+
+		case s_req_http_HT:
+			rc = strict_check(parser, ch != 'T');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_req_http_HTT);
+			break;
+
+		case s_req_http_HTT:
+			rc = strict_check(parser, ch != 'P');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_req_http_HTTP);
+			break;
+
+		case s_req_http_HTTP:
+			rc = strict_check(parser, ch != '/');
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_req_first_http_major);
+			break;
+
+		/* first digit of major HTTP version */
+		case s_req_first_http_major:
+			if (UNLIKELY(ch < '1' || ch > '9')) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_major = ch - '0';
+			UPDATE_STATE(s_req_http_major);
+			break;
+
+		/* major HTTP version or dot */
+		case s_req_http_major: {
+			if (ch == '.') {
+				UPDATE_STATE(s_req_first_http_minor);
+				break;
+			}
+
+			if (UNLIKELY(!IS_NUM(ch))) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_major *= 10U;
+			parser->http_major += ch - '0';
+
+			if (UNLIKELY(parser->http_major > 999)) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			break;
+		}
+
+		/* first digit of minor HTTP version */
+		case s_req_first_http_minor:
+			if (UNLIKELY(!IS_NUM(ch))) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_minor = ch - '0';
+			UPDATE_STATE(s_req_http_minor);
+			break;
+
+		/* minor HTTP version or end of request line */
+		case s_req_http_minor: {
+			if (ch == CR) {
+				UPDATE_STATE(s_req_line_almost_done);
+				break;
+			}
+
+			if (ch == LF) {
+				UPDATE_STATE(s_header_field_start);
+				break;
+			}
+
+			/* XXX allow spaces after digit? */
+
+			if (UNLIKELY(!IS_NUM(ch))) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			parser->http_minor *= 10U;
+			parser->http_minor += ch - '0';
+
+			if (UNLIKELY(parser->http_minor > 999)) {
+				SET_ERRNO(HPE_INVALID_VERSION);
+				goto error;
+			}
+
+			break;
+		}
+
+		/* end of request line */
+		case s_req_line_almost_done: {
+			if (UNLIKELY(ch != LF)) {
+				SET_ERRNO(HPE_LF_EXPECTED);
+				goto error;
+			}
+
+			UPDATE_STATE(s_header_field_start);
+			break;
+		}
+
+		case s_header_field_start: {
+			if (ch == CR) {
+				UPDATE_STATE(s_headers_almost_done);
+				break;
+			}
+
+			if (ch == LF) {
+				/* they might be just sending \n instead of \r\n
+				 * so this would be
+				 * the second \n to denote the end of headers
+				 */
+				UPDATE_STATE(s_headers_almost_done);
+				goto reexecute;
+			}
+
+			c = TOKEN(ch);
+
+			if (UNLIKELY(!c)) {
+				SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+				goto error;
+			}
+
+			MARK(header_field);
+
+			parser->index = 0U;
+			UPDATE_STATE(s_header_field);
+
+			switch (c) {
+			case 'c':
+				parser->header_state = h_C;
+				break;
+
+			case 'p':
+				parser->header_state =
+					h_matching_proxy_connection;
+				break;
+
+			case 't':
+				parser->header_state =
+					h_matching_transfer_encoding;
+				break;
+
+			case 'u':
+				parser->header_state = h_matching_upgrade;
+				break;
+
+			default:
+				parser->header_state = h_general;
+				break;
+			}
+			break;
+		}
+
+		case s_header_field: {
+			const char *start = p;
+
+			for (; p != data + len; p++) {
+				ch = *p;
+				c = TOKEN(ch);
+
+				if (!c) {
+					break;
+				}
+				parser_header_state(parser, ch, c);
+			}
+
+			rc = count_header_size(parser, p - start);
+			if (rc != 0) {
+				goto error;
+			}
+
+			if (p == data + len) {
+				--p;
+				break;
+			}
+
+			if (ch == ':') {
+				UPDATE_STATE(s_header_value_discard_ws);
+				rc = cb_data(parser, settings->on_header_field,
+					     HPE_CB_header_field, &p_state,
+					     parsed, p - data + 1,
+					     &header_field_mark,
+					     p - header_field_mark);
+				if (rc != 0) {
+					return rc;
+				}
+
+				break;
+			}
+
+			SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+			goto error;
+		}
+
+		case s_header_value_discard_ws:
+			if (ch == ' ' || ch == '\t') {
+				break;
+			}
+
+			if (ch == CR) {
+				UPDATE_STATE
+					(s_header_value_discard_ws_almost_done);
+				break;
+			}
+
+			if (ch == LF) {
+				UPDATE_STATE(s_header_value_discard_lws);
+				break;
+			}
+
+			__fallthrough;
+
+		case s_header_value_start: {
+			MARK(header_value);
+
+			UPDATE_STATE(s_header_value);
+			parser->index = 0U;
+
+			c = LOWER(ch);
+
+			switch (parser->header_state) {
+			case h_upgrade:
+				parser->flags |= F_UPGRADE;
+				parser->header_state = h_general;
+				break;
+
+			case h_transfer_encoding:
+				/* looking for 'Transfer-Encoding: chunked' */
+				if ('c' == c) {
+					parser->header_state =
+					   h_matching_transfer_encoding_chunked;
+				} else {
+					parser->header_state = h_general;
+				}
+				break;
+
+			case h_content_length:
+				if (UNLIKELY(!IS_NUM(ch))) {
+					SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+					goto error;
+				}
+
+				if (parser->flags & F_CONTENTLENGTH) {
+					SET_ERRNO
+						(HPE_UNEXPECTED_CONTENT_LENGTH);
+					goto error;
+				}
+
+				parser->flags |= F_CONTENTLENGTH;
+				parser->content_length = ch - '0';
+				break;
+
+			case h_connection:
+				/* looking for 'Connection: keep-alive' */
+				if (c == 'k') {
+					parser->header_state =
+					h_matching_connection_keep_alive;
+					/* looking for 'Connection: close' */
+				} else if (c == 'c') {
+					parser->header_state =
+						h_matching_connection_close;
+				} else if (c == 'u') {
+					parser->header_state =
+						h_matching_connection_upgrade;
+				} else {
+					parser->header_state =
+						h_matching_connection_token;
+				}
+				break;
+
+			/* Multi-value `Connection` header */
+			case h_matching_connection_token_start:
+				break;
+
+			default:
+				parser->header_state = h_general;
+				break;
+			}
+			break;
+		}
+
+		case s_header_value: {
+			const char *start = p;
+			enum header_states h_state =
+				(enum header_states)parser->header_state;
+
+			for (; p != data + len; p++) {
+				ch = *p;
+				if (ch == CR) {
+					UPDATE_STATE(s_header_almost_done);
+					parser->header_state = h_state;
+					rc = cb_data(parser,
+						     settings->on_header_value,
+						     HPE_CB_header_value,
+						     &p_state, parsed,
+						     p - data + 1,
+						     &header_value_mark,
+						     p - header_value_mark);
+					if (rc != 0) {
+						return rc;
+					}
+
+					break;
+				}
+
+				if (ch == LF) {
+					UPDATE_STATE(s_header_almost_done);
+					rc = count_header_size(parser,
+							       p - start);
+					if (rc != 0) {
+						goto error;
+					}
+					parser->header_state = h_state;
+					rc = cb_data(parser,
+						     settings->on_header_value,
+						     HPE_CB_header_value,
+						     &p_state, parsed, p - data,
+						     &header_value_mark,
+						     p - header_value_mark);
+					if (rc != 0) {
+						return rc;
+					}
+
+					goto reexecute;
+				}
+
+				if (!lenient && !IS_HEADER_CHAR(ch)) {
+					SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
+					goto error;
+				}
+
+				c = LOWER(ch);
+
+				rc = header_states(parser, data, len, &p,
+						   &p_state, &h_state, ch, c);
+				if (rc != 0) {
+					goto error;
+				}
+
+			}
+			parser->header_state = h_state;
+
+			rc = count_header_size(parser, p - start);
+			if (rc != 0) {
+				goto error;
+			}
+
+			if (p == data + len) {
+				--p;
+			}
+			break;
+		}
+
+		case s_header_almost_done: {
+			if (UNLIKELY(ch != LF)) {
+				SET_ERRNO(HPE_LF_EXPECTED);
+				goto error;
+			}
+
+			UPDATE_STATE(s_header_value_lws);
+			break;
+		}
+
+		case s_header_value_lws: {
+			if (ch == ' ' || ch == '\t') {
+				UPDATE_STATE(s_header_value_start);
+				goto reexecute;
+			}
+
+			/* finished the header */
+			switch (parser->header_state) {
+			case h_connection_keep_alive:
+				parser->flags |= F_CONNECTION_KEEP_ALIVE;
+				break;
+			case h_connection_close:
+				parser->flags |= F_CONNECTION_CLOSE;
+				break;
+			case h_transfer_encoding_chunked:
+				parser->flags |= F_CHUNKED;
+				break;
+			case h_connection_upgrade:
+				parser->flags |= F_CONNECTION_UPGRADE;
+				break;
+			default:
+				break;
+			}
+
+			UPDATE_STATE(s_header_field_start);
+			goto reexecute;
+		}
+
+		case s_header_value_discard_ws_almost_done: {
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_header_value_discard_lws);
+			break;
+		}
+
+		case s_header_value_discard_lws: {
+			if (ch == ' ' || ch == '\t') {
+				UPDATE_STATE(s_header_value_discard_ws);
+				break;
+			}
+			switch (parser->header_state) {
+			case h_connection_keep_alive:
+				parser->flags |=
+					F_CONNECTION_KEEP_ALIVE;
+				break;
+			case h_connection_close:
+				parser->flags |= F_CONNECTION_CLOSE;
+				break;
+			case h_connection_upgrade:
+				parser->flags |= F_CONNECTION_UPGRADE;
+				break;
+			case h_transfer_encoding_chunked:
+				parser->flags |= F_CHUNKED;
+				break;
+			default:
+				break;
+			}
+
+			/* header value was empty */
+			MARK(header_value);
+			UPDATE_STATE(s_header_field_start);
+			rc = cb_data(parser, settings->on_header_value,
+				     HPE_CB_header_value, &p_state, parsed,
+				     p - data, &header_value_mark,
+				     p - header_value_mark);
+			if (rc != 0) {
+				return rc;
+			}
+
+			goto reexecute;
+		}
+
+		case s_headers_almost_done: {
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+
+			if (parser->flags & F_TRAILING) {
+				/* End of a chunked request */
+				UPDATE_STATE(s_message_done);
+
+				rc = cb_notify(parser, &p_state,
+					       settings->on_chunk_complete,
+					       HPE_CB_chunk_complete, parsed,
+					       p - data);
+				if (rc != 0) {
+					return rc;
+				}
+				goto reexecute;
+			}
+
+			/* Cannot use chunked encoding and a content-length
+			 * header together per the HTTP specification.
+			 */
+			if ((parser->flags & F_CHUNKED) &&
+					(parser->flags & F_CONTENTLENGTH)) {
+				SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
+				goto error;
+			}
+
+			UPDATE_STATE(s_headers_done);
+
+			/* Set this here so that on_headers_complete() callbacks
+			 * can see it
+			 */
+			int flags = (F_UPGRADE | F_CONNECTION_UPGRADE);
+
+			parser->upgrade =
+				((parser->flags & flags) == flags ||
+				 parser->method == HTTP_CONNECT);
+
+			/* Here we call the headers_complete callback. This is
+			 * somewhat
+			 * different than other callbacks because if the user
+			 * returns 1, we
+			 * will interpret that as saying that this message has
+			 * no body. This
+			 * is needed for the annoying case of receiving a
+			 * response to a HEAD
+			 * request.
+			 *
+			 * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but
+			 * we cannot, so
+			 * we have to simulate it by handling a change in errno
+			 * below.
+			 */
+			if (settings->on_headers_complete) {
+				switch (settings->on_headers_complete(parser)) {
+				case 0:
+					break;
+
+				case 2:
+					parser->upgrade = 1U;
+					__fallthrough;
+
+				case 1:
+					parser->flags |= F_SKIPBODY;
+					break;
+
+				default:
+					SET_ERRNO(HPE_CB_headers_complete);
+
+					parser->state = CURRENT_STATE();
+					*parsed = p - data;
+					return -HTTP_PARSER_ERRNO(parser);
+				}
+			}
+
+			if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+				parser->state = CURRENT_STATE();
+				*parsed = p - data;
+				return -HTTP_PARSER_ERRNO(parser);
+			}
+
+			goto reexecute;
+		}
+
+		case s_headers_done: {
+			int hasBody;
+
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+
+			parser->nread = 0U;
+
+			hasBody = parser->flags & F_CHUNKED ||
+				  (parser->content_length > 0 &&
+				   parser->content_length != ULLONG_MAX);
+			if (parser->upgrade &&
+				(parser->method == HTTP_CONNECT ||
+				 (parser->flags & F_SKIPBODY) || !hasBody)) {
+				/* Exit, the rest of the message is in a
+				 * different protocol.
+				 */
+				UPDATE_STATE(NEW_MESSAGE());
+
+				rc = cb_notify(parser, &p_state,
+					       settings->on_message_complete,
+					       HPE_CB_message_complete, parsed,
+					       p - data + 1);
+				if (rc != 0) {
+					return rc;
+				}
+				parser->state = CURRENT_STATE();
+				*parsed = p - data + 1;
+				return 0;
+			}
+
+			if (parser->flags & F_SKIPBODY) {
+				UPDATE_STATE(NEW_MESSAGE());
+
+				rc = cb_notify(parser, &p_state,
+					       settings->on_message_complete,
+					       HPE_CB_message_complete, parsed,
+					       p - data + 1);
+				if (rc != 0) {
+					return rc;
+				}
+
+			} else if (parser->flags & F_CHUNKED) {
+				/* chunked encoding - ignore Content-Length
+				 * header
+				 */
+				UPDATE_STATE(s_chunk_size_start);
+			} else {
+				rc = zero_content_length(parser, settings,
+							 &p_state, parsed, p,
+							 data);
+				if (rc != 0) {
+					return rc;
+				}
+			}
+
+			break;
+		}
+
+		case s_body_identity: {
+			uint64_t to_read = MIN(parser->content_length,
+					       (uint64_t) ((data + len) - p));
+
+			__ASSERT_NO_MSG(parser->content_length != 0U
+			       && parser->content_length != ULLONG_MAX);
+
+			/* The difference between advancing content_length and
+			 * p is because
+			 * the latter will automatically advance on the next
+			 * loop
+			 * iteration.
+			 * Further, if content_length ends up at 0, we want to
+			 * see the last
+			 * byte again for our message complete callback.
+			 */
+			MARK(body);
+			parser->content_length -= to_read;
+			p += to_read - 1;
+
+			if (parser->content_length == 0U) {
+				UPDATE_STATE(s_message_done);
+
+				/* Mimic CALLBACK_DATA_NOADVANCE() but with one
+				 * extra byte.
+				 *
+				 * The alternative to doing this is to wait for
+				 * the next byte to
+				 * trigger the data callback, just as in every
+				 * other case. The
+				 * problem with this is that this makes it
+				 * difficult for the test
+				 * harness to distinguish between
+				 * complete-on-EOF and
+				 * complete-on-length. It's not clear that this
+				 * distinction is
+				 * important for applications, but let's keep it
+				 * for now.
+				 */
+
+				rc = cb_data(parser, settings->on_body,
+					     HPE_CB_body, &p_state, parsed,
+					     p - data, &body_mark,
+					     p - body_mark + 1);
+				if (rc != 0) {
+					return rc;
+				}
+
+				goto reexecute;
+			}
+
+			break;
+		}
+
+		/* read until EOF */
+		case s_body_identity_eof:
+			MARK(body);
+			p = data + len - 1;
+
+			break;
+
+		case s_message_done:
+			UPDATE_STATE(NEW_MESSAGE());
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_message_complete,
+				       HPE_CB_message_complete, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+			if (parser->upgrade) {
+				/* Exit, the rest of the message is in a
+				 * different protocol.
+				 */
+				parser->state = CURRENT_STATE();
+				*parsed = p - data + 1;
+				return 0;
+			}
+			break;
+
+		case s_chunk_size_start: {
+			__ASSERT_NO_MSG(parser->nread == 1U);
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+
+			unhex_val = unhex[(unsigned char)ch];
+			if (UNLIKELY(unhex_val == -1)) {
+				SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+				goto error;
+			}
+
+			parser->content_length = unhex_val;
+			UPDATE_STATE(s_chunk_size);
+			break;
+		}
+
+		case s_chunk_size: {
+			uint64_t t;
+
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+
+			if (ch == CR) {
+				UPDATE_STATE(s_chunk_size_almost_done);
+				break;
+			}
+
+			unhex_val = unhex[(unsigned char)ch];
+
+			if (unhex_val == -1) {
+				if (ch == ';' || ch == ' ') {
+					UPDATE_STATE(s_chunk_parameters);
+					break;
+				}
+
+				SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
+				goto error;
+			}
+
+			t = parser->content_length;
+			t *= 16U;
+			t += unhex_val;
+
+			/* Overflow? Test against a conservative limit for
+			 * simplicity.
+			 */
+			uint64_t ulong_value = (ULLONG_MAX - 16) / 16;
+
+			if (UNLIKELY(ulong_value < parser->content_length)) {
+				SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
+				goto error;
+			}
+
+			parser->content_length = t;
+			break;
+		}
+
+		case s_chunk_parameters: {
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+			/* just ignore this shit. TODO check for overflow */
+			if (ch == CR) {
+				UPDATE_STATE(s_chunk_size_almost_done);
+				break;
+			}
+			break;
+		}
+
+		case s_chunk_size_almost_done: {
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+
+			parser->nread = 0U;
+
+			if (parser->content_length == 0U) {
+				parser->flags |= F_TRAILING;
+				UPDATE_STATE(s_header_field_start);
+			} else {
+				UPDATE_STATE(s_chunk_data);
+			}
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_chunk_header,
+				       HPE_CB_chunk_header, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+			break;
+		}
+
+		case s_chunk_data: {
+			uint64_t to_read = MIN(parser->content_length,
+					       (uint64_t) ((data + len) - p));
+
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+			__ASSERT_NO_MSG(parser->content_length != 0U
+					&& parser->content_length != ULLONG_MAX);
+
+			/* See the explanation in s_body_identity for why the
+			 * content
+			 * length and data pointers are managed this way.
+			 */
+			MARK(body);
+			parser->content_length -= to_read;
+			p += to_read - 1;
+
+			if (parser->content_length == 0U) {
+				UPDATE_STATE(s_chunk_data_almost_done);
+			}
+
+			break;
+		}
+
+		case s_chunk_data_almost_done:
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+			__ASSERT_NO_MSG(parser->content_length == 0U);
+			rc = strict_check(parser, ch != CR);
+			if (rc != 0) {
+				goto error;
+			}
+			UPDATE_STATE(s_chunk_data_done);
+			rc = cb_data(parser, settings->on_body, HPE_CB_body,
+				     &p_state, parsed, p - data + 1, &body_mark,
+				     p - body_mark);
+			if (rc != 0) {
+				return rc;
+			}
+
+			break;
+
+		case s_chunk_data_done:
+			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
+			rc = strict_check(parser, ch != LF);
+			if (rc != 0) {
+				goto error;
+			}
+			parser->nread = 0U;
+			UPDATE_STATE(s_chunk_size_start);
+
+			rc = cb_notify(parser, &p_state,
+				       settings->on_chunk_complete,
+				       HPE_CB_chunk_complete, parsed,
+				       p - data + 1);
+			if (rc != 0) {
+				return rc;
+			}
+			break;
+
+		default:
+			__ASSERT_NO_MSG(0 && "unhandled state");
+			SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
+			goto error;
+		}
+	}
+
+	/* Run callbacks for any marks that we have leftover after we ran our of
+	 * bytes. There should be at most one of these set, so it's OK to invoke
+	 * them in series (unset marks will not result in callbacks).
+	 *
+	 * We use the NOADVANCE() variety of callbacks here because 'p' has
+	 * already
+	 * overflowed 'data' and this allows us to correct for the off-by-one
+	 * that
+	 * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a
+	 * 'p'
+	 * value that's in-bounds).
+	 */
+
+	__ASSERT_NO_MSG(((header_field_mark ? 1 : 0) +
+			(header_value_mark ? 1 : 0) +
+			(url_mark ? 1 : 0)  +
+			(body_mark ? 1 : 0) +
+			(status_mark ? 1 : 0)) <= 1);
+
+	rc = cb_data(parser, settings->on_header_field, HPE_CB_header_field,
+		     &p_state, parsed, p - data, &header_field_mark,
+		     p - header_field_mark);
+	if (rc != 0) {
+		return rc;
+	}
+	rc = cb_data(parser, settings->on_header_value, HPE_CB_header_value,
+		     &p_state, parsed, p - data, &header_value_mark,
+		     p - header_value_mark);
+	if (rc != 0) {
+		return rc;
+	}
+	rc = cb_data(parser, settings->on_url, HPE_CB_url, &p_state, parsed,
+		     p - data, &url_mark, p - url_mark);
+	if (rc != 0) {
+		return rc;
+	}
+	rc = cb_data(parser, settings->on_body, HPE_CB_body, &p_state, parsed,
+		     p - data, &body_mark, p - body_mark);
+	if (rc != 0) {
+		return rc;
+	}
+	rc = cb_data(parser, settings->on_status, HPE_CB_status, &p_state,
+		     parsed, p - data, &status_mark, p - status_mark);
+	if (rc != 0) {
+		return rc;
+	}
+
+	parser->state = CURRENT_STATE();
+	*parsed = len;
+	return 0;
+
+error:
+	if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
+		SET_ERRNO(HPE_UNKNOWN);
+	}
+
+	parser->state = CURRENT_STATE();
+	*parsed = p - data; /* Error */
+	return -HTTP_PARSER_ERRNO(parser);
+}
+
+size_t http_parser_execute(struct http_parser *parser,
+			   const struct http_parser_settings *settings,
+			   const char *data, size_t len)
+{
+	size_t parsed;
+
+	parser_execute(parser, settings, data, len, &parsed);
+	return parsed;
+}
+
+/* Does the parser need to see an EOF to find the end of the message? */
+int http_message_needs_eof(const struct http_parser *parser)
+{
+	if (parser->type == HTTP_REQUEST) {
+		return 0;
+	}
+
+	/* See RFC 2616 section 4.4 */
+	if (parser->status_code / 100 == 1U || /* 1xx e.g. Continue */
+			parser->status_code == 204U ||     /* No Content */
+			parser->status_code == 304U ||     /* Not Modified */
+			parser->flags & F_SKIPBODY) {     /* response to a HEAD
+							   * request
+							   */
+		return 0;
+	}
+
+	if ((parser->flags & F_CHUNKED) ||
+			parser->content_length != ULLONG_MAX) {
+		return 0;
+	}
+
+	return 1;
+}
+
+
+int http_should_keep_alive(const struct http_parser *parser)
+{
+	if (parser->http_major > 0 && parser->http_minor > 0) {
+		/* HTTP/1.1 */
+		if (parser->flags & F_CONNECTION_CLOSE) {
+			return 0;
+		}
+	} else {
+		/* HTTP/1.0 or earlier */
+		if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
+			return 0;
+		}
+	}
+
+	return !http_message_needs_eof(parser);
+}
+
+
+const char *http_method_str(enum http_method m)
+{
+	return ELEM_AT(method_strings, m, "<unknown>");
+}
+
+
+void http_parser_init(struct http_parser *parser, enum http_parser_type t)
+{
+	void *data = parser->data; /* preserve application data */
+
+	(void)memset(parser, 0, sizeof(*parser));
+	parser->data = data;
+	parser->type = t;
+	parser->state =
+		(t == HTTP_REQUEST ? s_start_req :
+		 (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
+	parser->http_errno = HPE_OK;
+}
+
+void http_parser_settings_init(struct http_parser_settings *settings)
+{
+	(void)memset(settings, 0, sizeof(*settings));
+}
+
+const char *http_errno_name(enum http_errno err)
+{
+	__ASSERT_NO_MSG(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+
+	return http_strerror_tab[err].name;
+}
+
+const char *http_errno_description(enum http_errno err)
+{
+	__ASSERT_NO_MSG(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
+
+	return http_strerror_tab[err].description;
+}
+
+void http_parser_pause(struct http_parser *parser, int paused)
+{
+	/* Users should only be pausing/unpausing a parser that is not in an
+	 * error
+	 * state. In non-debug builds, there's not much that we can do about
+	 * this
+	 * other than ignore it.
+	 */
+	if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
+			HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
+		SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
+	} else {
+		__ASSERT_NO_MSG(0 && "Attempting to pause parser in error state");
+	}
+}
+
+int http_body_is_final(const struct http_parser *parser)
+{
+	return parser->state == s_message_done;
+}
+
+unsigned long http_parser_version(void)
+{
+	return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
+	       HTTP_PARSER_VERSION_MINOR * 0x00100 |
+	       HTTP_PARSER_VERSION_PATCH * 0x00001;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser_url.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser_url.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/http/http_parser_url.c	(working copy)
@@ -0,0 +1,574 @@
+/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
+ *
+ * Additional changes are licensed under the same terms as NGINX and
+ * copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <sys/__assert.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <net/http_parser_url.h>
+#include <toolchain.h>
+
+#ifndef BIT_AT
+# define BIT_AT(a, i)                                                \
+	(!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
+	 (1 << ((unsigned int) (i) & 7))))
+#endif
+
+/* Set the mark FOR; non-destructive if mark is already set */
+#define MARK(FOR)                                                          \
+do {                                                                       \
+	if (!FOR##_mark) {                                                 \
+		FOR##_mark = p;                                            \
+	}                                                                  \
+} while (0)
+
+
+#ifdef HTTP_PARSER_STRICT
+# define T(v) 0
+#else
+# define T(v) v
+#endif
+
+
+static const uint8_t normal_url_char[32] = {
+/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
+	0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
+	0    | T(2)   |   0    |   0    | T(16)  |   0    |   0    |   0,
+/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
+	0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
+	0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
+/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
+	0    |   2    |   4    |   0    |   16   |   32   |   64   |  128,
+/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |   0,
+/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
+/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
+	1    |   2    |   4    |   8    |   16   |   32   |   64   |   0,
+};
+
+#undef T
+
+enum http_host_state {
+	s_http_host_dead = 1,
+	s_http_userinfo_start,
+	s_http_userinfo,
+	s_http_host_start,
+	s_http_host_v6_start,
+	s_http_host,
+	s_http_host_v6,
+	s_http_host_v6_end,
+	s_http_host_v6_zone_start,
+	s_http_host_v6_zone,
+	s_http_host_port_start,
+	s_http_host_port
+};
+
+
+/* Macros for character classes; depends on strict-mode  */
+#define LOWER(c)            (unsigned char)(c | 0x20)
+#define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
+#define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
+#define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
+#define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
+
+#define IS_MARK(c)		((c) == '-' || (c) == '_' || (c) == '.' || \
+				 (c) == '!' || (c) == '~' || (c) == '*' || \
+				 (c) == '\'' || (c) == '(' || (c) == ')')
+
+#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
+				(c) == ';' || (c) == ':' || (c) == '&' ||  \
+				(c) == '=' || (c) == '+' || (c) == '$' ||  \
+				(c) == ',')
+
+#ifdef HTTP_PARSER_STRICT
+#define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))
+#define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+#else
+#define IS_URL_CHAR(c)                                                         \
+	(BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
+#define IS_HOST_CHAR(c)                                                        \
+	(IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
+#endif
+
+/* Our URL parser.
+ *
+ * This is designed to be shared by http_parser_execute() for URL validation,
+ * hence it has a state transition + byte-for-byte interface. In addition, it
+ * is meant to be embedded in http_parser_parse_url(), which does the dirty
+ * work of turning state transitions URL components for its API.
+ *
+ * This function should only be invoked with non-space characters. It is
+ * assumed that the caller cares about (and can detect) the transition between
+ * URL and non-URL states by looking for these.
+ */
+enum state parse_url_char(enum state s, const char ch)
+{
+	if (ch == ' ' || ch == '\r' || ch == '\n') {
+		return s_dead;
+	}
+
+#ifdef HTTP_PARSER_STRICT
+	if (ch == '\t' || ch == '\f') {
+		return s_dead;
+	}
+#endif
+
+	switch (s) {
+	case s_req_spaces_before_url:
+		/* Proxied requests are followed by scheme of an absolute URI
+		 * (alpha).
+		 * All methods except CONNECT are followed by '/' or '*'.
+		 */
+
+		if (ch == '/' || ch == '*') {
+			return s_req_path;
+		}
+
+		if (IS_ALPHA(ch)) {
+			return s_req_schema;
+		}
+
+		break;
+
+	case s_req_schema:
+		if (IS_ALPHA(ch)) {
+			return s;
+		}
+
+		if (ch == ':') {
+			return s_req_schema_slash;
+		}
+
+		break;
+
+	case s_req_schema_slash:
+		if (ch == '/') {
+			return s_req_schema_slash_slash;
+		}
+
+		break;
+
+	case s_req_schema_slash_slash:
+		if (ch == '/') {
+			return s_req_server_start;
+		}
+
+		break;
+
+	case s_req_server_with_at:
+		if (ch == '@') {
+			return s_dead;
+		}
+
+		__fallthrough;
+	case s_req_server_start:
+	case s_req_server:
+		if (ch == '/') {
+			return s_req_path;
+		}
+
+		if (ch == '?') {
+			return s_req_query_string_start;
+		}
+
+		if (ch == '@') {
+			return s_req_server_with_at;
+		}
+
+		if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
+			return s_req_server;
+		}
+
+		break;
+
+	case s_req_path:
+		if (IS_URL_CHAR(ch)) {
+			return s;
+		}
+
+		switch (ch) {
+		case '?':
+			return s_req_query_string_start;
+
+		case '#':
+			return s_req_fragment_start;
+		}
+
+		break;
+
+	case s_req_query_string_start:
+	case s_req_query_string:
+		if (IS_URL_CHAR(ch)) {
+			return s_req_query_string;
+		}
+
+		switch (ch) {
+		case '?':
+			/* allow extra '?' in query string */
+			return s_req_query_string;
+
+		case '#':
+			return s_req_fragment_start;
+		}
+
+		break;
+
+	case s_req_fragment_start:
+		if (IS_URL_CHAR(ch)) {
+			return s_req_fragment;
+		}
+
+		switch (ch) {
+		case '?':
+			return s_req_fragment;
+
+		case '#':
+			return s;
+		}
+
+		break;
+
+	case s_req_fragment:
+		if (IS_URL_CHAR(ch)) {
+			return s;
+		}
+
+		switch (ch) {
+		case '?':
+		case '#':
+			return s;
+		}
+
+		break;
+
+	default:
+		break;
+	}
+
+	/* We should never fall out of the switch above unless there's
+	 * an error
+	 */
+	return s_dead;
+}
+
+static enum http_host_state
+http_parse_host_char(enum http_host_state s, const char ch)
+{
+	switch (s) {
+	case s_http_userinfo:
+	case s_http_userinfo_start:
+		if (ch == '@') {
+			return s_http_host_start;
+		}
+
+		if (IS_USERINFO_CHAR(ch)) {
+			return s_http_userinfo;
+		}
+		break;
+
+	case s_http_host_start:
+		if (ch == '[') {
+			return s_http_host_v6_start;
+		}
+
+		if (IS_HOST_CHAR(ch)) {
+			return s_http_host;
+		}
+
+		break;
+
+	case s_http_host:
+		if (IS_HOST_CHAR(ch)) {
+			return s_http_host;
+		}
+
+		__fallthrough;
+	case s_http_host_v6_end:
+		if (ch == ':') {
+			return s_http_host_port_start;
+		}
+
+		break;
+
+	case s_http_host_v6:
+		if (ch == ']') {
+			return s_http_host_v6_end;
+		}
+
+		__fallthrough;
+	case s_http_host_v6_start:
+		if (IS_HEX(ch) || ch == ':' || ch == '.') {
+			return s_http_host_v6;
+		}
+
+		if (s == s_http_host_v6 && ch == '%') {
+			return s_http_host_v6_zone_start;
+		}
+		break;
+
+	case s_http_host_v6_zone:
+		if (ch == ']') {
+			return s_http_host_v6_end;
+		}
+
+		__fallthrough;
+	case s_http_host_v6_zone_start:
+		/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
+		if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' ||
+				ch == '_' ||
+				ch == '~') {
+			return s_http_host_v6_zone;
+		}
+		break;
+
+	case s_http_host_port:
+	case s_http_host_port_start:
+		if (IS_NUM(ch)) {
+			return s_http_host_port;
+		}
+
+		break;
+
+	default:
+		break;
+	}
+	return s_http_host_dead;
+}
+
+static
+int http_parse_host(const char *buf, struct http_parser_url *u,
+		    int found_at)
+{
+	enum http_host_state s;
+	size_t buflen;
+	const char *p;
+
+	buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
+	__ASSERT_NO_MSG(u->field_set & (1 << UF_HOST));
+
+	u->field_data[UF_HOST].len = 0U;
+
+	s = found_at ? s_http_userinfo_start : s_http_host_start;
+
+	for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
+		enum http_host_state new_s = http_parse_host_char(s, *p);
+
+		if (new_s == s_http_host_dead) {
+			return 1;
+		}
+
+		switch (new_s) {
+		case s_http_host:
+			if (s != s_http_host) {
+				u->field_data[UF_HOST].off = p - buf;
+			}
+			u->field_data[UF_HOST].len++;
+			break;
+
+		case s_http_host_v6:
+			if (s != s_http_host_v6) {
+				u->field_data[UF_HOST].off = p - buf;
+			}
+			u->field_data[UF_HOST].len++;
+			break;
+
+		case s_http_host_v6_zone_start:
+		case s_http_host_v6_zone:
+			u->field_data[UF_HOST].len++;
+			break;
+
+		case s_http_host_port:
+			if (s != s_http_host_port) {
+				u->field_data[UF_PORT].off = p - buf;
+				u->field_data[UF_PORT].len = 0U;
+				u->field_set |= (1 << UF_PORT);
+			}
+			u->field_data[UF_PORT].len++;
+			break;
+
+		case s_http_userinfo:
+			if (s != s_http_userinfo) {
+				u->field_data[UF_USERINFO].off = p - buf;
+				u->field_data[UF_USERINFO].len = 0U;
+				u->field_set |= (1 << UF_USERINFO);
+			}
+			u->field_data[UF_USERINFO].len++;
+			break;
+
+		default:
+			break;
+		}
+		s = new_s;
+	}
+
+	/* Make sure we don't end somewhere unexpected */
+	switch (s) {
+	case s_http_host_start:
+	case s_http_host_v6_start:
+	case s_http_host_v6:
+	case s_http_host_v6_zone_start:
+	case s_http_host_v6_zone:
+	case s_http_host_port_start:
+	case s_http_userinfo:
+	case s_http_userinfo_start:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+void
+http_parser_url_init(struct http_parser_url *u)
+{
+	(void)memset(u, 0, sizeof(*u));
+}
+
+int
+http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
+		      struct http_parser_url *u)
+{
+	enum http_parser_url_fields old_uf;
+	enum http_parser_url_fields uf;
+	int found_at = 0;
+	const char *p;
+	enum state s;
+
+	u->port = u->field_set = 0U;
+	s = is_connect ? s_req_server_start : s_req_spaces_before_url;
+	old_uf = UF_MAX;
+
+	for (p = buf; p < buf + buflen; p++) {
+		s = parse_url_char(s, *p);
+
+		/* Figure out the next field that we're operating on */
+		switch (s) {
+		case s_dead:
+			return 1;
+
+		/* Skip delimeters */
+		case s_req_schema_slash:
+		case s_req_schema_slash_slash:
+		case s_req_server_start:
+		case s_req_query_string_start:
+		case s_req_fragment_start:
+			continue;
+
+		case s_req_schema:
+			uf = UF_SCHEMA;
+			break;
+
+		case s_req_server_with_at:
+			found_at = 1;
+			__fallthrough;
+
+		case s_req_server:
+			uf = UF_HOST;
+			break;
+
+		case s_req_path:
+			uf = UF_PATH;
+			break;
+
+		case s_req_query_string:
+			uf = UF_QUERY;
+			break;
+
+		case s_req_fragment:
+			uf = UF_FRAGMENT;
+			break;
+
+		default:
+			__ASSERT_NO_MSG(!"Unexpected state");
+			return 1;
+		}
+
+		/* Nothing's changed; soldier on */
+		if (uf == old_uf) {
+			u->field_data[uf].len++;
+			continue;
+		}
+
+		u->field_data[uf].off = p - buf;
+		u->field_data[uf].len = 1U;
+
+		u->field_set |= (1 << uf);
+		old_uf = uf;
+	}
+
+	/* host must be present if there is a schema */
+	/* parsing http:///toto will fail */
+	if ((u->field_set & (1 << UF_SCHEMA)) &&
+			(u->field_set & (1 << UF_HOST)) == 0U) {
+		return 1;
+	}
+
+	if (u->field_set & (1 << UF_HOST)) {
+		if (http_parse_host(buf, u, found_at) != 0) {
+			return 1;
+		}
+	}
+
+	/* CONNECT requests can only contain "hostname:port" */
+	if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
+		return 1;
+	}
+
+	if (u->field_set & (1 << UF_PORT)) {
+		/* Don't bother with endp; we've already validated the string */
+		unsigned long v;
+
+		v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);
+
+		/* Ports have a max value of 2^16 */
+		if (v > 0xffff) {
+			return 1;
+		}
+
+		u->port = (uint16_t) v;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/CMakeLists.txt	(working copy)
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_include_directories(.)
+
+zephyr_library_sources(
+    lwm2m_engine.c
+    lwm2m_obj_security.c
+    lwm2m_obj_server.c
+    lwm2m_obj_device.c
+    lwm2m_rw_plain_text.c
+    lwm2m_rw_oma_tlv.c
+    lwm2m_util.c
+    )
+
+# LWM2M RD Client Support
+zephyr_library_sources_ifdef(CONFIG_LWM2M_RD_CLIENT_SUPPORT
+    lwm2m_rd_client.c
+    )
+
+# LWM2M Object Support
+zephyr_library_sources_ifdef(CONFIG_LWM2M_CONN_MON_OBJ_SUPPORT
+    lwm2m_obj_connmon.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT
+    lwm2m_obj_firmware.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+    lwm2m_obj_firmware_pull.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_LOCATION_OBJ_SUPPORT
+    lwm2m_obj_location.c
+    )
+
+# JSON Support
+zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_JSON_SUPPORT
+    lwm2m_rw_json.c
+    )
+
+# IPSO Objects
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TEMP_SENSOR
+    ipso_temp_sensor.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_GENERIC_SENSOR
+    ipso_generic_sensor.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_HUMIDITY_SENSOR
+    ipso_humidity_sensor.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_PRESSURE_SENSOR
+    ipso_pressure_sensor.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_LIGHT_CONTROL
+    ipso_light_control.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_ACCELEROMETER
+    ipso_accelerometer.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_BUZZER
+    ipso_buzzer.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TIMER
+    ipso_timer.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_ONOFF_SWITCH
+    ipso_onoff_switch.c
+    )
+zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_PUSH_BUTTON
+    ipso_push_button.c
+    )
+
+zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig	(working copy)
@@ -0,0 +1,286 @@
+# Copyright (c) 2017 Linaro Limited
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig LWM2M
+	bool "OMA LWM2M protocol stack"
+	select COAP
+	select HTTP_PARSER_URL
+	select NET_SOCKETS
+	select NET_SOCKETS_POSIX_NAMES
+	help
+	  This option adds logic for managing OMA LWM2M data
+
+if LWM2M
+
+module = LWM2M
+module-dep = LOG
+module-str = Log level for LWM2M library
+source "subsys/net/Kconfig.template.log_config.net"
+
+config LWM2M_DTLS_SUPPORT
+	bool "Enable DTLS support in the LwM2M client"
+	select TLS_CREDENTIALS
+	select NET_SOCKETS_SOCKOPT_TLS
+	select NET_SOCKETS_ENABLE_DTLS
+
+config LWM2M_DNS_SUPPORT
+	bool "Enable DNS support in the LWM2M client"
+	default y if DNS_RESOLVER
+
+config LWM2M_ENGINE_STACK_SIZE
+	int "LWM2M engine stack size"
+	default 2560 if NET_LOG
+	default 2048
+	help
+	  Set the stack size for the LWM2M library engine (used for handling
+	  OBSERVE and NOTIFY events)
+
+config LWM2M_ENGINE_MAX_MESSAGES
+	int "LWM2M engine max. message object"
+	default 10
+	help
+	  Set the maximum message objects for the LWM2M library client
+
+config LWM2M_COAP_BLOCK_SIZE
+	int "LWM2M CoAP block-wise transfer size"
+	default 256
+	range 64 1024
+	help
+	  CoAP block size used by LWM2M when performing block-wise
+	  transfers. Possible values: 16, 32, 64, 128, 256, 512 and 1024.
+
+config LWM2M_ENGINE_MESSAGE_HEADER_SIZE
+	int "Room for CoAP header data"
+	default 48
+	range 24 128
+	help
+	  Extra room allocated to handle CoAP header data
+
+config LWM2M_ENGINE_MAX_PENDING
+	int "LWM2M engine max. pending objects"
+	default 5
+	help
+	  Set the maximum pending objects for the LWM2M library client
+
+config LWM2M_ENGINE_MAX_REPLIES
+	int "LWM2M engine max. reply objects"
+	default 5
+	help
+	  Set the maximum reply objects for the LWM2M library client
+
+config LWM2M_ENGINE_MAX_OBSERVER
+	int "Maximum # of observable LWM2M resources"
+	default 10
+	range 5 200
+	help
+	  This value sets the maximum number of resources which can be
+	  added to the observe notification list.
+
+config LWM2M_ENGINE_DEFAULT_LIFETIME
+	int "LWM2M engine default server connection lifetime"
+	default 30
+	range 15 65535
+	help
+	  Set the default lifetime (in seconds) for the LWM2M library engine
+
+config LWM2M_SECONDS_TO_UPDATE_EARLY
+	int "LWM2M Registration Update transmission time before timeout"
+	default 6
+	range 1 65535
+	help
+	  Time in seconds before the registration timeout, when the LWM2M
+	  Registration Update is sent by the engine. In networks with large
+	  round trip times (like NB-IoT), it might be needed to set this value
+	  higher, in order to allow the response to arrive before timeout.
+
+config LWM2M_QUEUE_MODE_ENABLED
+	bool "Enable Queue Mode UDP binding"
+	help
+	  Set the transport binding to UDP with Queue Mode (UQ).
+
+config LWM2M_QUEUE_MODE_UPTIME
+	int "Specify time the LWM2M client should stay online in queue mode."
+	default 93
+	help
+	  This config specifies time (in seconds) the device should stay online
+	  after sending a message to the server. Note, that LWM2M specification
+	  recommends this to be CoAP MAX_TRANSMIT_WAIT parameter (which
+	  defaults to 93 seconds, see RFC 7252), it does not forbid other
+	  values though.
+
+config LWM2M_RD_CLIENT_SUPPORT
+	bool "support for LWM2M client bootstrap/registration state machine"
+	default y
+	help
+	  Client will use registration state machine to locate and connect to
+	  LWM2M servers (including bootstrap server support)
+
+config LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP
+	bool "Enable bootstrap support"
+	help
+	  Enabling this setting allows the RD client to support bootstrap mode.
+
+config LWM2M_RD_CLIENT_ENDPOINT_NAME_MAX_LENGTH
+	int "Maximum length of client endpoint name"
+	depends on LWM2M_RD_CLIENT_SUPPORT
+	default 33
+	help
+	  Default: room for 32 hexadeciaml digits (UUID) + NULL
+
+config LWM2M_PEER_PORT
+	int "LWM2M server port"
+	depends on LWM2M_RD_CLIENT_SUPPORT
+	default 5683
+	help
+	  This is the default server port to connect to for LWM2M communication
+
+config LWM2M_SECURITY_INSTANCE_COUNT
+	int "Maximum # of LWM2M Security object instances"
+	default 2 if LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP
+	default 1
+	range 1 10
+	help
+	  This setting establishes the total count of LWM2M Security instances
+	  available to the client.
+
+config LWM2M_SECURITY_KEY_SIZE
+	int "Buffer size of the security key resources"
+	default 16
+	range 16 256
+	help
+	  This setting establishes the size of the key (pre-shared / public)
+	  resources in the security object instances.
+
+config LWM2M_SERVER_DEFAULT_PMIN
+	int "Default server record PMIN"
+	default 10
+	help
+	  Default minimum amount of time in seconds the client must wait
+	  between notifications.  If a resource has to be notified during this
+	  minimum time period, the notification must be sent after the time
+	  period expires.
+
+config LWM2M_SERVER_DEFAULT_PMAX
+	int "Default server record PMAX"
+	default 60
+	help
+	  Default maximum amount of time in seconds the client may wait
+	  between notifications.  When this time period expires a notification
+	  must be sent.
+
+config LWM2M_SERVER_INSTANCE_COUNT
+	int "Maximum # of LWM2M Server object instances"
+	default 2 if LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP
+	default 1
+	range 1 10
+	help
+	  This setting establishes the total count of LWM2M Server instances
+	  available to the client (including: bootstrap and regular servers).
+
+config LWM2M_CONN_MON_OBJ_SUPPORT
+	bool "Connectivity Monitoring object support"
+	help
+	  Include support for LWM2M Connectivity Monitoring Object (ID 4)
+
+config LWM2M_CONN_MON_BEARER_MAX
+	int "Maximum # of available network bearer resource instances"
+	depends on LWM2M_CONN_MON_OBJ_SUPPORT
+	default 1
+	help
+	  This value sets the maximum number of available network bearer
+	  resource instances.  These are displayed via the
+	  "Connection Monitoring" object /4/0/1.
+
+config LWM2M_CONN_MON_APN_MAX
+	int "Maximum # of APN resource instances"
+	depends on LWM2M_CONN_MON_OBJ_SUPPORT
+	default 1
+	help
+	  This value sets the maximum number of APN resource instances.
+	  These are displayed via the "Connection Monitoring" object /4/0/7.
+
+config LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT
+	bool "Firmware Update object support"
+	default y
+	help
+	  Include support for LWM2M Firmware Update Object (ID 5)
+
+config LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+	bool "Firmware Update object pull support"
+	default y
+	depends on LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT
+	depends on (HTTP_PARSER || HTTP_PARSER_URL)
+	help
+	  Include support for pulling a file from a remote server via
+	  block transfer and "FIRMWARE PACKAGE URI" resource.  This option
+	  adds another UDP context and packet handling.
+
+config LWM2M_NUM_BLOCK1_CONTEXT
+	int "Maximum # of LWM2M block1 contexts"
+	default 3
+	help
+	  This value sets up the maximum number of block1 contexts for
+	  CoAP block-wise transfer we can handle at the same time.
+
+config LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT
+	bool "Firmware Update object pull via CoAP-CoAP/HTTP proxy support"
+	depends on LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+	help
+	  Include support for pulling firmware file via a CoAP-CoAP/HTTP proxy.
+
+config LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_ADDR
+	string "CoAP proxy network address"
+	depends on LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT
+	help
+	  Network address of the CoAP proxy server.
+
+config LWM2M_RW_JSON_SUPPORT
+	bool "support for JSON writer"
+	default y
+	help
+	  Include support for writing JSON data
+
+config LWM2M_DEVICE_PWRSRC_MAX
+	int "Maximum # of device power source records"
+	default 5
+	range 1 20
+	help
+	  This value sets the maximum number of power source data that a device
+	  can store.  These are displayed via the "Device" object /3/0/6,
+	  /3/0/7 and /3/0/8 resources.
+
+config LWM2M_DEVICE_ERROR_CODE_MAX
+	int "Maximum # of device obj error codes to store"
+	default 10
+	range 1 20
+	help
+	  This value sets the maximum number of error codes that the device
+	  object will store before ignoring new values.
+
+config LWM2M_DEVICE_EXT_DEV_INFO_MAX
+	int "Maximum # of device obj external device info to store"
+	default 5
+	range 1 20
+	help
+	  This value sets the maximum number of external device info that the
+	  device object will store before ignoring new values.
+
+config LWM2M_NUM_ATTR
+	int "Maximum # of LWM2M attributes"
+	default 20
+	help
+	  This value sets up the maximum number of LwM2M attributes that
+	  we can handle at the same time.
+
+config LWM2M_LOCATION_OBJ_SUPPORT
+	bool "Location object support"
+	help
+	  Include support for LWM2M Location Object (ID 6)
+
+menu "IPSO Alliance Smart Object Support"
+
+source "subsys/net/lib/lwm2m/Kconfig.ipso"
+
+endmenu
+
+endif # LWM2M
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig.ipso
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig.ipso	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/Kconfig.ipso	(working copy)
@@ -0,0 +1,226 @@
+# Copyright (c) 2017 Linaro Limited
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig LWM2M_IPSO_SUPPORT
+	bool "IPSO Alliance Smart Object Support"
+	help
+	  This option adds general support for IPSO objects
+
+if LWM2M_IPSO_SUPPORT
+
+config LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	bool "Nonstandard IPSO object Timestamp resources"
+	help
+	  If you enable this option, various IPSO objects supported below
+	  will optionally include timestamp resources (ID 5518).
+	  This is an LWM2M protocol extension which can be useful to associate
+	  times with events. If unsure, leave at the default n.
+
+config LWM2M_IPSO_TEMP_SENSOR
+	bool "IPSO Temperature Sensor Support"
+	help
+	  This IPSO object should be used with a temperature sensor to
+	  report a temperature measurement. It also provides resources for
+	  minimum/maximum measured values and the minimum/maximum range
+	  that can be measured by the temperature sensor.
+
+config LWM2M_IPSO_TEMP_SENSOR_INSTANCE_COUNT
+	int "Maximum # of IPSO Temperature Sensor object instances"
+	default 1
+	depends on LWM2M_IPSO_TEMP_SENSOR
+	help
+	  This setting establishes the total count of IPSO Temperature
+	  Sensor instances available to the LWM2M client.
+
+config LWM2M_IPSO_TEMP_SENSOR_TIMESTAMP
+	bool "Add timestamp resources to IPSO temperature objects"
+	default y
+	depends on LWM2M_IPSO_TEMP_SENSOR && LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each temperature object.
+
+config LWM2M_IPSO_GENERIC_SENSOR
+	bool "IPSO Generic Sensor Support"
+	help
+	  This IPSO object can be used to prototype a sensor.
+
+if LWM2M_IPSO_GENERIC_SENSOR
+
+config LWM2M_IPSO_GENERIC_SENSOR_INSTANCE_COUNT
+	int "Maximum # of IPSO Generic Sensor object instances"
+	default 1
+	help
+	  This setting establishes the total count of IPSO Generic
+	  Sensor instances available to the LWM2M client.
+
+config LWM2M_IPSO_GENERIC_SENSOR_TIMESTAMP
+	bool "Add timestamp resources to IPSO objects"
+	default y
+	depends on LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each object.
+
+config LWM2M_IPSO_GENERIC_SENSOR_NAME
+	string "Name that will show up in debug output when object is created"
+	default "Generic"
+
+config LWM2M_IPSO_GENERIC_SENSOR_TYPE
+	string "Sensor type"
+	default "Generic sensor"
+	help
+	  The type of the sensor (for instance PIR type).
+
+endif # LWM2M_IPSO_GENERIC_SENSOR
+
+config LWM2M_IPSO_HUMIDITY_SENSOR
+	bool "IPSO Humidity Sensor Support"
+	help
+	  This IPSO object can be used to prototype a sensor.
+
+if LWM2M_IPSO_HUMIDITY_SENSOR
+
+config LWM2M_IPSO_HUMIDITY_SENSOR_INSTANCE_COUNT
+	int "Maximum # of IPSO Humidity Sensor object instances"
+	default 1
+	help
+	  This setting establishes the total count of IPSO Humidity
+	  Sensor instances available to the LWM2M client.
+
+config LWM2M_IPSO_HUMIDITY_SENSOR_TIMESTAMP
+	bool "Add timestamp resources to IPSO objects"
+	default y
+	depends on LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each object.
+
+endif # LWM2M_IPSO_HUMIDITY_SENSOR
+
+config LWM2M_IPSO_PRESSURE_SENSOR
+	bool "IPSO Pressure Sensor Support"
+	help
+	  This IPSO object can be used to prototype a sensor.
+
+if LWM2M_IPSO_PRESSURE_SENSOR
+
+config LWM2M_IPSO_PRESSURE_SENSOR_INSTANCE_COUNT
+	int "Maximum # of IPSO Pressure Sensor object instances"
+	default 1
+	help
+	  This setting establishes the total count of IPSO Pressure
+	  Sensor instances available to the LWM2M client.
+
+config LWM2M_IPSO_PRESSURE_SENSOR_TIMESTAMP
+	bool "Add timestamp resources to IPSO objects"
+	default y
+	depends on LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each object.
+
+endif # LWM2M_IPSO_PRESSURE_SENSOR
+
+config LWM2M_IPSO_LIGHT_CONTROL
+	bool "IPSO Light Control Support"
+	help
+	  This Object is used to control a light source, such as a LED or other
+	  light. It allows a light to be turned on or off and its dimmer
+	  setting to be controlled as a % between 0 and 100. An optional color
+	  setting enables a string to be used to indicate the desired color.
+
+config LWM2M_IPSO_LIGHT_CONTROL_INSTANCE_COUNT
+	int "Maximum # of IPSO Light Control object instances"
+	default 1
+	depends on LWM2M_IPSO_LIGHT_CONTROL
+	help
+	  This setting establishes the total count of IPSO Light Control
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_ACCELEROMETER
+	bool "IPSO Accelerometer Support"
+	help
+	  This Object is used to used to represent a 1-3 axis accelerometer.
+
+config LWM2M_IPSO_ACCELEROMETER_INSTANCE_COUNT
+	int "Maximum # of IPSO Accelerometer object instances"
+	default 1
+	depends on LWM2M_IPSO_ACCELEROMETER
+	help
+	  This setting establishes the total count of IPSO Accelerometer
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_ACCELEROMETER_TIMESTAMP
+	bool "Add timestamp resources to IPSO accelerometer objects"
+	default y
+	depends on LWM2M_IPSO_ACCELEROMETER && LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each accelerometer object.
+
+config LWM2M_IPSO_BUZZER
+	bool "IPSO Buzzer Support"
+	help
+	  This Object is used to actuate an audible alarm such as a buzzer,
+	  beeper, or vibration alarm.
+
+config LWM2M_IPSO_BUZZER_INSTANCE_COUNT
+	int "Maximum # of IPSO Buzzer instances"
+	default 1
+	depends on LWM2M_IPSO_BUZZER
+	help
+	  This setting establishes the total count of IPSO Buzzer
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_TIMER
+	bool "IPSO Light Control Support"
+	help
+	  This Object is used to time events / actions
+
+config LWM2M_IPSO_TIMER_INSTANCE_COUNT
+	int "Maximum # of IPSO Timer object instances"
+	default 1
+	depends on LWM2M_IPSO_TIMER
+	help
+	  This setting establishes the total count of IPSO Timer
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_ONOFF_SWITCH
+	bool "IPSO On/Off Switch Support"
+	help
+	  This object is used with an On/Off switch to report it's state.
+
+config LWM2M_IPSO_ONOFF_SWITCH_INSTANCE_COUNT
+	int "Maximum # of IPSO On/Off Switch object instances"
+	default 1
+	depends on LWM2M_IPSO_ONOFF_SWITCH
+	help
+	  This setting establishes the total count of IPSO On/Off Switch
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_ONOFF_SWITCH_TIMESTAMP
+	bool "Add a timestamp resource to IPSO on/off switch objects"
+	default y
+	depends on LWM2M_IPSO_ONOFF_SWITCH && LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each on/off switch object.
+
+config LWM2M_IPSO_PUSH_BUTTON
+	bool "IPSO Push Button Support"
+	help
+	  This Object is used to report the state of a momentary action push
+	  button control and to count the number of times the control has
+	  been operated since the last observation.
+
+config LWM2M_IPSO_PUSH_BUTTON_INSTANCE_COUNT
+	int "Maximum # of IPSO On/Off Switch object instances"
+	default 1
+	depends on LWM2M_IPSO_PUSH_BUTTON
+	help
+	  This setting establishes the total count of IPSO Push Button
+	  instances available to the LWM2M client.
+
+config LWM2M_IPSO_PUSH_BUTTON_TIMESTAMP
+	bool "Add a timestamp resource to IPSO Push Button objects"
+	default y
+	depends on LWM2M_IPSO_PUSH_BUTTON && LWM2M_IPSO_TIMESTAMP_EXTENSIONS
+	help
+	  Add a non-standard timestamp resource to each Push Button object.
+
+endif # LWM2M_LWM2M_IPSO_SUPPORT
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/buf_util.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/buf_util.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/buf_util.h	(working copy)
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_BUF_UTIL_H_
+#define ZEPHYR_INCLUDE_BUF_UTIL_H_
+
+#include <zephyr/types.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* append */
+static inline int buf_append(uint8_t *dst, uint16_t *dst_len, uint16_t dst_size,
+			     uint8_t *src, uint16_t src_len)
+{
+	if (!dst || !src) {
+		return -EINVAL;
+	}
+
+	if (*dst_len + src_len > dst_size) {
+		return -ENOMEM;
+	}
+
+	memcpy(dst + *dst_len, src, src_len);
+	*dst_len += src_len;
+	return 0;
+}
+
+/* insert */
+static inline int buf_insert(uint8_t *dst, uint16_t *dst_len, uint16_t dst_size,
+			     uint16_t offset, uint8_t *src, uint16_t src_len)
+{
+	if (!dst || !src) {
+		return -EINVAL;
+	}
+
+	if (*dst_len + src_len > dst_size) {
+		return -ENOMEM;
+	}
+
+	/* shift everything in fbuf after offset by len */
+	memmove(dst + offset + src_len, dst + offset, *dst_len - offset);
+
+	/* copy src into fbuf at offset */
+	memcpy(dst + offset, src, src_len);
+	*dst_len += src_len;
+	return 0;
+}
+
+/* read */
+static inline int buf_read(uint8_t *dst, uint16_t len, uint8_t *src, uint16_t src_len,
+			   uint16_t *offset)
+{
+	if (!src) {
+		return -EINVAL;
+	}
+
+	if (*offset + len > src_len) {
+		return -ENOMEM;
+	}
+
+	if (dst) {
+		/* copy data at offset into dst */
+		memcpy(dst, src + *offset, len);
+	}
+
+	*offset += len;
+	return 0;
+}
+
+static inline int buf_skip(uint16_t len, uint8_t *src, uint16_t src_len, uint16_t *offset)
+{
+	return buf_read(NULL, len, src, src_len, offset);
+}
+
+static inline int buf_read_u8(uint8_t *value, uint8_t *src, uint16_t src_len,
+			      uint16_t *offset)
+{
+	return buf_read(value, sizeof(uint8_t), src, src_len, offset);
+}
+
+static inline int buf_read_u16(uint16_t *value, uint8_t *src, uint16_t src_len,
+			       uint16_t *offset)
+{
+	return buf_read((uint8_t *)value, sizeof(uint16_t), src, src_len, offset);
+}
+
+static inline int buf_read_be16(uint16_t *value, uint8_t *src, uint16_t src_len,
+				uint16_t *offset)
+{
+	int ret;
+	uint8_t v16[2];
+
+	ret = buf_read(v16, sizeof(uint16_t), src, src_len, offset);
+	*value = v16[0] << 8 | v16[1];
+
+	return ret;
+}
+
+static inline int buf_read_u32(uint32_t *value, uint8_t *src, uint16_t src_len,
+			       uint16_t *offset)
+{
+	return buf_read((uint8_t *)value, sizeof(uint32_t), src, src_len, offset);
+}
+
+static inline int buf_read_be32(uint32_t *value, uint8_t *src, uint16_t src_len,
+				uint16_t *offset)
+{
+	int ret;
+	uint8_t v32[4];
+
+	ret = buf_read(v32, sizeof(uint32_t), src, src_len, offset);
+	*value = v32[0] << 24 | v32[1] << 16 | v32[2] << 8 | v32[3];
+
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_BUF_UTIL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_accelerometer.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_accelerometer.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_accelerometer.c	(working copy)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO Accelerometer object (3313):
+ * http://www.openmobilealliance.org/tech/profiles/lwm2m/3313.xml
+ */
+
+#define LOG_MODULE_NAME net_ipso_accel
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#ifdef CONFIG_LWM2M_IPSO_ACCELEROMETER_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#else
+#define ADD_TIMESTAMPS 0
+#endif
+/* Server resource IDs */
+#define ACCEL_X_VALUE_ID			5702
+#define ACCEL_Y_VALUE_ID			5703
+#define ACCEL_Z_VALUE_ID			5704
+#define ACCEL_SENSOR_UNITS_ID			5701
+#define ACCEL_MIN_RANGE_VALUE_ID		5603
+#define ACCEL_MAX_RANGE_VALUE_ID		5604
+#if ADD_TIMESTAMPS
+#define ACCEL_TIMESTAMP_ID			5518
+
+#define ACCEL_MAX_ID		7
+#else
+#define ACCEL_MAX_ID		6
+#endif
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_ACCELEROMETER_INSTANCE_COUNT
+
+/*
+ * Calculate resource instances as follows:
+ * start with ACCEL_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT        (ACCEL_MAX_ID)
+
+/* resource state */
+struct ipso_accel_data {
+	float32_value_t x_value;
+	float32_value_t y_value;
+	float32_value_t z_value;
+	float32_value_t min_range;
+	float32_value_t max_range;
+};
+
+static struct ipso_accel_data accel_data[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj accel;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(ACCEL_X_VALUE_ID, R, FLOAT32),
+	OBJ_FIELD_DATA(ACCEL_Y_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(ACCEL_Z_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(ACCEL_SENSOR_UNITS_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(ACCEL_MIN_RANGE_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(ACCEL_MAX_RANGE_VALUE_ID, R_OPT, FLOAT32),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(ACCEL_TIMESTAMP_ID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][ACCEL_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj_inst *accel_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < ARRAY_SIZE(inst); index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	(void)memset(&accel_data[avail], 0, sizeof(accel_data[avail]));
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(ACCEL_X_VALUE_ID, res[avail], i, res_inst[avail], j,
+			  &accel_data[avail].x_value,
+			  sizeof(accel_data[avail].x_value));
+	INIT_OBJ_RES_DATA(ACCEL_Y_VALUE_ID, res[avail], i, res_inst[avail], j,
+			  &accel_data[avail].y_value,
+			  sizeof(accel_data[avail].y_value));
+	INIT_OBJ_RES_DATA(ACCEL_Z_VALUE_ID, res[avail], i, res_inst[avail], j,
+			  &accel_data[avail].z_value,
+			  sizeof(accel_data[avail].z_value));
+	INIT_OBJ_RES_OPTDATA(ACCEL_SENSOR_UNITS_ID, res[avail], i,
+			     res_inst[avail], j);
+	INIT_OBJ_RES_DATA(ACCEL_MIN_RANGE_VALUE_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &accel_data[avail].min_range,
+			  sizeof(accel_data[avail].min_range));
+	INIT_OBJ_RES_DATA(ACCEL_MAX_RANGE_VALUE_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &accel_data[avail].max_range,
+			  sizeof(accel_data[avail].max_range));
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(ACCEL_TIMESTAMP_ID, res[avail], i,
+			     res_inst[avail], j);
+#endif
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO Accelerometer instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_accel_init(const struct device *dev)
+{
+	accel.obj_id = IPSO_OBJECT_ACCELEROMETER_ID;
+	accel.fields = fields;
+	accel.field_count = ARRAY_SIZE(fields);
+	accel.max_instance_count = ARRAY_SIZE(inst);
+	accel.create_cb = accel_create;
+	lwm2m_register_obj(&accel);
+
+	return 0;
+}
+
+SYS_INIT(ipso_accel_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_buzzer.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_buzzer.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_buzzer.c	(working copy)
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO Buzzer object (3338):
+ * http://www.openmobilealliance.org/tech/profiles/lwm2m/3338.xml
+ */
+
+#define LOG_MODULE_NAME net_ipso_buzzer
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* resource IDs */
+#define BUZZER_ON_OFF_ID		5850
+#define BUZZER_LEVEL_ID			5548
+#define BUZZER_DELAY_DURATION_ID	5521
+#define BUZZER_MINIMUM_OFF_TIME_ID	5525
+#define BUZZER_APPLICATION_TYPE_ID	5750
+/* This field is actually not in the spec, so nothing sets it except here
+ * users can listen for post_write events to it for buzzer on/off events
+ */
+#define BUZZER_DIGITAL_STATE_ID		5500
+
+#define BUZZER_MAX_ID			6
+
+#define MAX_INSTANCE_COUNT		CONFIG_LWM2M_IPSO_BUZZER_INSTANCE_COUNT
+
+/*
+ * Calculate resource instances as follows:
+ * start with BUZZER_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT        (BUZZER_MAX_ID)
+
+/* resource state */
+struct ipso_buzzer_data {
+	float32_value_t level;
+	float64_value_t delay_duration;
+	float64_value_t min_off_time;
+
+	uint64_t trigger_offset;
+
+	struct k_delayed_work buzzer_work;
+
+	uint16_t obj_inst_id;
+	bool onoff; /* toggle from resource */
+	bool active; /* digital state */
+};
+
+static struct ipso_buzzer_data buzzer_data[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj buzzer;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(BUZZER_ON_OFF_ID, RW, BOOL),
+	OBJ_FIELD_DATA(BUZZER_LEVEL_ID, RW_OPT, FLOAT32),
+	OBJ_FIELD_DATA(BUZZER_DELAY_DURATION_ID, RW_OPT, FLOAT64),
+	OBJ_FIELD_DATA(BUZZER_MINIMUM_OFF_TIME_ID, RW, FLOAT64),
+	OBJ_FIELD_DATA(BUZZER_APPLICATION_TYPE_ID, RW_OPT, STRING),
+	OBJ_FIELD_DATA(BUZZER_DIGITAL_STATE_ID, R, BOOL),
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][BUZZER_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static int float2ms(float64_value_t *f, uint32_t *ms)
+{
+	*ms = f->val1 * MSEC_PER_SEC;
+	*ms += f->val2 / (LWM2M_FLOAT64_DEC_MAX / MSEC_PER_SEC);
+
+	return 0;
+}
+
+static int get_buzzer_index(uint16_t obj_inst_id)
+{
+	int i, ret = -ENOENT;
+
+	for (i = 0; i < ARRAY_SIZE(inst); i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		ret = i;
+		break;
+	}
+
+	return ret;
+}
+
+static int start_buzzer(struct ipso_buzzer_data *buzzer)
+{
+	uint32_t temp = 0U;
+	char path[MAX_RESOURCE_LEN];
+
+	/* make sure buzzer is currently not active */
+	if (buzzer->active) {
+		return -EINVAL;
+	}
+
+	/* check min off time from last trigger_offset */
+	float2ms(&buzzer->min_off_time, &temp);
+	if (k_uptime_get() < buzzer->trigger_offset + temp) {
+		return -EINVAL;
+	}
+
+	/* TODO: check delay_duration > 0 */
+
+	buzzer->trigger_offset = k_uptime_get();
+	snprintk(path, MAX_RESOURCE_LEN, "%d/%u/%d", IPSO_OBJECT_BUZZER_ID,
+		 buzzer->obj_inst_id, BUZZER_DIGITAL_STATE_ID);
+	lwm2m_engine_set_bool(path, true);
+
+	float2ms(&buzzer->delay_duration, &temp);
+	k_delayed_work_submit(&buzzer->buzzer_work, K_MSEC(temp));
+
+	return 0;
+}
+
+static int stop_buzzer(struct ipso_buzzer_data *buzzer, bool cancel)
+{
+	char path[MAX_RESOURCE_LEN];
+
+	/* make sure buzzer is currently active */
+	if (!buzzer->active) {
+		return -EINVAL;
+	}
+
+	snprintk(path, MAX_RESOURCE_LEN, "%d/%u/%d", IPSO_OBJECT_BUZZER_ID,
+		 buzzer->obj_inst_id, BUZZER_DIGITAL_STATE_ID);
+	lwm2m_engine_set_bool(path, false);
+
+	if (cancel) {
+		k_delayed_work_cancel(&buzzer->buzzer_work);
+	}
+
+	return 0;
+}
+
+static int onoff_post_write_cb(uint16_t obj_inst_id,
+			       uint16_t res_id, uint16_t res_inst_id,
+			       uint8_t *data, uint16_t data_len,
+			       bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_buzzer_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	if (!buzzer_data[i].onoff && buzzer_data[i].active) {
+		return stop_buzzer(&buzzer_data[i], true);
+	} else if (buzzer_data[i].onoff && !buzzer_data[i].active) {
+		return start_buzzer(&buzzer_data[i]);
+	}
+
+	return 0;
+}
+
+static void buzzer_work_cb(struct k_work *work)
+{
+	struct ipso_buzzer_data *buzzer = CONTAINER_OF(work,
+						      struct ipso_buzzer_data,
+						      buzzer_work);
+	stop_buzzer(buzzer, false);
+}
+
+static struct lwm2m_engine_obj_inst *buzzer_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < ARRAY_SIZE(inst); index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	(void)memset(&buzzer_data[avail], 0, sizeof(buzzer_data[avail]));
+	k_delayed_work_init(&buzzer_data[avail].buzzer_work, buzzer_work_cb);
+	buzzer_data[avail].level.val1 = 50; /* 50% */
+	buzzer_data[avail].delay_duration.val1 = 1; /* 1 seconds */
+	buzzer_data[avail].obj_inst_id = obj_inst_id;
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(BUZZER_ON_OFF_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &buzzer_data[avail].onoff,
+		     sizeof(buzzer_data[avail].onoff),
+		     NULL, NULL, onoff_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(BUZZER_LEVEL_ID, res[avail], i, res_inst[avail], j,
+			  &buzzer_data[avail].level,
+			  sizeof(buzzer_data[avail].level));
+	INIT_OBJ_RES_DATA(BUZZER_DELAY_DURATION_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &buzzer_data[avail].delay_duration,
+			  sizeof(buzzer_data[avail].delay_duration));
+	INIT_OBJ_RES_DATA(BUZZER_MINIMUM_OFF_TIME_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &buzzer_data[avail].min_off_time,
+			  sizeof(buzzer_data[avail].min_off_time));
+	INIT_OBJ_RES_OPTDATA(BUZZER_APPLICATION_TYPE_ID, res[avail], i,
+			     res_inst[avail], j);
+	INIT_OBJ_RES_DATA(BUZZER_DIGITAL_STATE_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &buzzer_data[avail].active,
+			  sizeof(buzzer_data[avail].active));
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO Buzzer instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_buzzer_init(const struct device *dev)
+{
+	buzzer.obj_id = IPSO_OBJECT_BUZZER_ID;
+	buzzer.fields = fields;
+	buzzer.field_count = ARRAY_SIZE(fields);
+	buzzer.max_instance_count = ARRAY_SIZE(inst);
+	buzzer.create_cb = buzzer_create;
+	lwm2m_register_obj(&buzzer);
+
+	return 0;
+}
+
+SYS_INIT(ipso_buzzer_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_generic_sensor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_generic_sensor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_generic_sensor.c	(working copy)
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ * Copyright (c) 2020 Laird Connectivity
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Generic sensor is based off temperature sensor.
+ * It is a template used to create other sensors.
+ */
+
+#define LOG_MODULE_NAME net_ipso_generic_sensor
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+#include "lwm2m_resource_ids.h"
+
+#ifdef CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#define NUMBER_OF_OBJ_FIELDS 10
+#else
+#define ADD_TIMESTAMPS 0
+#define NUMBER_OF_OBJ_FIELDS 9
+#endif
+
+#define MAX_INSTANCE_COUNT CONFIG_LWM2M_IPSO_GENERIC_SENSOR_INSTANCE_COUNT
+
+#define IPSO_OBJECT_ID IPSO_OBJECT_GENERIC_SENSOR_ID
+
+#define SENSOR_NAME CONFIG_LWM2M_IPSO_GENERIC_SENSOR_NAME
+
+#define UNIT_STR_MAX_SIZE 8
+#define APP_TYPE_STR_MAX_SIZE 32
+#define SENSOR_TYPE_STR_MAX_SIZE 32
+
+BUILD_ASSERT(SENSOR_TYPE_STR_MAX_SIZE >=
+	     sizeof(CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE),
+	     "CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE is too long.");
+
+/*
+ * Calculate resource instances as follows:
+ * start with NUMBER_OF_OBJ_FIELDS
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
+
+/* resource state variables */
+static float32_value_t sensor_value[MAX_INSTANCE_COUNT];
+static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
+static float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
+static char app_type[MAX_INSTANCE_COUNT][APP_TYPE_STR_MAX_SIZE];
+static char sensor_type[MAX_INSTANCE_COUNT][SENSOR_TYPE_STR_MAX_SIZE];
+
+static struct lwm2m_engine_obj sensor;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT32),
+	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
+	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_EXECUTE_OPT(RESET_MIN_MAX_MEASURED_VALUES_RID),
+	OBJ_FIELD_DATA(APPLICATION_TYPE_RID, RW_OPT, STRING),
+	OBJ_FIELD_DATA(SENSOR_TYPE_RID, R_OPT, STRING),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(TIMESTAMP_RID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][NUMBER_OF_OBJ_FIELDS];
+static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
+					    [RESOURCE_INSTANCE_COUNT];
+
+static void update_min_measured(uint16_t obj_inst_id, int index)
+{
+	min_measured_value[index].val1 = sensor_value[index].val1;
+	min_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
+}
+
+static void update_max_measured(uint16_t obj_inst_id, int index)
+{
+	max_measured_value[index].val1 = sensor_value[index].val1;
+	max_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
+}
+
+static int reset_min_max_measured_values_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	LOG_DBG("RESET MIN/MAX %d", obj_inst_id);
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			update_min_measured(obj_inst_id, i);
+			update_max_measured(obj_inst_id, i);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				 uint16_t res_inst_id, uint8_t *data,
+				 uint16_t data_len, bool last_block,
+				 size_t total_size)
+{
+	int i;
+	bool update_min = false;
+	bool update_max = false;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			/* update min / max */
+			if (sensor_value[i].val1 < min_measured_value[i].val1) {
+				update_min = true;
+			} else if (sensor_value[i].val1 ==
+					   min_measured_value[i].val1 &&
+				   sensor_value[i].val2 <
+					   min_measured_value[i].val2) {
+				update_min = true;
+			}
+
+			if (sensor_value[i].val1 > max_measured_value[i].val1) {
+				update_max = true;
+			} else if (sensor_value[i].val1 ==
+					   max_measured_value[i].val1 &&
+				   sensor_value[i].val2 >
+					   max_measured_value[i].val2) {
+				update_max = true;
+			}
+
+			if (update_min) {
+				update_min_measured(obj_inst_id, i);
+			}
+
+			if (update_max) {
+				update_max_measured(obj_inst_id, i);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *generic_sensor_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u",
+				obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	sensor_value[index].val1 = 0;
+	sensor_value[index].val2 = 0;
+	units[index][0] = '\0';
+	min_measured_value[index].val1 = INT32_MAX;
+	min_measured_value[index].val2 = 0;
+	max_measured_value[index].val1 = -INT32_MAX;
+	max_measured_value[index].val2 = 0;
+	min_range_value[index].val1 = 0;
+	min_range_value[index].val2 = 0;
+	max_range_value[index].val1 = 0;
+	max_range_value[index].val2 = 0;
+	app_type[index][0] = '\0';
+	strncpy(sensor_type[index], CONFIG_LWM2M_IPSO_GENERIC_SENSOR_TYPE,
+		SENSOR_TYPE_STR_MAX_SIZE);
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1,
+		     true, &sensor_value[index], sizeof(*sensor_value), NULL,
+		     NULL, sensor_value_write_cb, NULL);
+	INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j,
+			  units[index], UNIT_STR_MAX_SIZE);
+	INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &min_measured_value[index],
+			  sizeof(*min_measured_value));
+	INIT_OBJ_RES_DATA(MAX_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &max_measured_value[index],
+			  sizeof(*max_measured_value));
+	INIT_OBJ_RES_DATA(MIN_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &min_range_value[index], sizeof(*min_range_value));
+	INIT_OBJ_RES_DATA(MAX_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &max_range_value[index], sizeof(*max_range_value));
+	INIT_OBJ_RES_EXECUTE(RESET_MIN_MAX_MEASURED_VALUES_RID, res[index], i,
+			     reset_min_max_measured_values_cb);
+	INIT_OBJ_RES_DATA(APPLICATION_TYPE_RID, res[index], i, res_inst[index],
+			  j, app_type[index], APP_TYPE_STR_MAX_SIZE);
+	INIT_OBJ_RES_DATA(SENSOR_TYPE_RID, res[index], i, res_inst[index], j,
+			  sensor_type[index], SENSOR_TYPE_STR_MAX_SIZE);
+
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j);
+#endif
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Created IPSO %s Sensor instance: %d", SENSOR_NAME,
+		obj_inst_id);
+	return &inst[index];
+}
+
+static int ipso_generic_sensor_init(const struct device *dev)
+{
+	sensor.obj_id = IPSO_OBJECT_ID;
+	sensor.fields = fields;
+	sensor.field_count = ARRAY_SIZE(fields);
+	sensor.max_instance_count = MAX_INSTANCE_COUNT;
+	sensor.create_cb = generic_sensor_create;
+	lwm2m_register_obj(&sensor);
+
+	return 0;
+}
+
+SYS_INIT(ipso_generic_sensor_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_humidity_sensor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_humidity_sensor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_humidity_sensor.c	(working copy)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ * Copyright (c) 2020 Laird Connectivity
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_ipso_humidity_sensor
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+#include "lwm2m_resource_ids.h"
+
+#ifdef CONFIG_LWM2M_IPSO_HUMIDITY_SENSOR_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#define NUMBER_OF_OBJ_FIELDS 8
+#else
+#define ADD_TIMESTAMPS 0
+#define NUMBER_OF_OBJ_FIELDS 7
+#endif
+
+#define MAX_INSTANCE_COUNT CONFIG_LWM2M_IPSO_HUMIDITY_SENSOR_INSTANCE_COUNT
+
+#define IPSO_OBJECT_ID IPSO_OBJECT_HUMIDITY_SENSOR_ID
+
+#define SENSOR_NAME "Humidity"
+
+#define UNIT_STR_MAX_SIZE 8
+
+/*
+ * Calculate resource instances as follows:
+ * start with NUMBER_OF_OBJ_FIELDS
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
+
+/* resource state variables */
+static float32_value_t sensor_value[MAX_INSTANCE_COUNT];
+static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
+static float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj sensor;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT32),
+	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
+	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_EXECUTE_OPT(RESET_MIN_MAX_MEASURED_VALUES_RID),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(TIMESTAMP_RID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][NUMBER_OF_OBJ_FIELDS];
+static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
+					    [RESOURCE_INSTANCE_COUNT];
+
+static void update_min_measured(uint16_t obj_inst_id, int index)
+{
+	min_measured_value[index].val1 = sensor_value[index].val1;
+	min_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
+}
+
+static void update_max_measured(uint16_t obj_inst_id, int index)
+{
+	max_measured_value[index].val1 = sensor_value[index].val1;
+	max_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
+}
+
+static int reset_min_max_measured_values_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	LOG_DBG("RESET MIN/MAX %d", obj_inst_id);
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			update_min_measured(obj_inst_id, i);
+			update_max_measured(obj_inst_id, i);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				 uint16_t res_inst_id, uint8_t *data,
+				 uint16_t data_len, bool last_block,
+				 size_t total_size)
+{
+	int i;
+	bool update_min = false;
+	bool update_max = false;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			/* update min / max */
+			if (sensor_value[i].val1 < min_measured_value[i].val1) {
+				update_min = true;
+			} else if (sensor_value[i].val1 ==
+					   min_measured_value[i].val1 &&
+				   sensor_value[i].val2 <
+					   min_measured_value[i].val2) {
+				update_min = true;
+			}
+
+			if (sensor_value[i].val1 > max_measured_value[i].val1) {
+				update_max = true;
+			} else if (sensor_value[i].val1 ==
+					   max_measured_value[i].val1 &&
+				   sensor_value[i].val2 >
+					   max_measured_value[i].val2) {
+				update_max = true;
+			}
+
+			if (update_min) {
+				update_min_measured(obj_inst_id, i);
+			}
+
+			if (update_max) {
+				update_max_measured(obj_inst_id, i);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *
+humidity_sensor_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u",
+				obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	sensor_value[index].val1 = 0;
+	sensor_value[index].val2 = 0;
+	units[index][0] = '\0';
+	min_measured_value[index].val1 = INT32_MAX;
+	min_measured_value[index].val2 = 0;
+	max_measured_value[index].val1 = -INT32_MAX;
+	max_measured_value[index].val2 = 0;
+	min_range_value[index].val1 = 0;
+	min_range_value[index].val2 = 0;
+	max_range_value[index].val1 = 0;
+	max_range_value[index].val2 = 0;
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1,
+		     true, &sensor_value[index], sizeof(*sensor_value), NULL,
+		     NULL, sensor_value_write_cb, NULL);
+	INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j,
+			  units[index], UNIT_STR_MAX_SIZE);
+	INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &min_measured_value[index],
+			  sizeof(*min_measured_value));
+	INIT_OBJ_RES_DATA(MAX_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &max_measured_value[index],
+			  sizeof(*max_measured_value));
+	INIT_OBJ_RES_DATA(MIN_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &min_range_value[index], sizeof(*min_range_value));
+	INIT_OBJ_RES_DATA(MAX_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &max_range_value[index], sizeof(*max_range_value));
+	INIT_OBJ_RES_EXECUTE(RESET_MIN_MAX_MEASURED_VALUES_RID, res[index], i,
+			     reset_min_max_measured_values_cb);
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j);
+#endif
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Created IPSO %s Sensor instance: %d", SENSOR_NAME,
+		obj_inst_id);
+	return &inst[index];
+}
+
+static int ipso_humidity_sensor_init(const struct device *dev)
+{
+	sensor.obj_id = IPSO_OBJECT_ID;
+	sensor.fields = fields;
+	sensor.field_count = ARRAY_SIZE(fields);
+	sensor.max_instance_count = MAX_INSTANCE_COUNT;
+	sensor.create_cb = humidity_sensor_create;
+	lwm2m_register_obj(&sensor);
+
+	return 0;
+}
+
+SYS_INIT(ipso_humidity_sensor_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_light_control.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_light_control.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_light_control.c	(working copy)
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO Light Control object (3311):
+ * https://github.com/IPSO-Alliance/pub/blob/master/docs/IPSO-Smart-Objects.pdf
+ * Section: "16. IPSO Object: Light Control"
+ */
+
+#define LOG_MODULE_NAME net_ipso_light_control
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Server resource IDs */
+#define LIGHT_ON_OFF_ID				5850
+#define LIGHT_DIMMER_ID				5851
+#define LIGHT_ON_TIME_ID			5852
+#define LIGHT_CUMULATIVE_ACTIVE_POWER_ID	5805
+#define LIGHT_POWER_FACTOR_ID			5820
+#define LIGHT_COLOUR_ID				5706
+#define LIGHT_SENSOR_UNITS_ID			5701
+#define LIGHT_APPLICATION_TYPE_ID		5750
+
+#define LIGHT_MAX_ID		8
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_LIGHT_CONTROL_INSTANCE_COUNT
+
+#define LIGHT_STRING_SHORT	8
+#define LIGHT_STRING_LONG       64
+
+/*
+ * Calculate resource instances as follows:
+ * start with LIGHT_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT	(LIGHT_MAX_ID)
+
+/* resource state variables */
+static bool on_off_value[MAX_INSTANCE_COUNT];
+static uint8_t dimmer_value[MAX_INSTANCE_COUNT];
+static int32_t on_time_value[MAX_INSTANCE_COUNT];
+static uint32_t on_time_offset[MAX_INSTANCE_COUNT];
+static float32_value_t cumulative_active_value[MAX_INSTANCE_COUNT];
+static float32_value_t power_factor_value[MAX_INSTANCE_COUNT];
+static char colour[MAX_INSTANCE_COUNT][LIGHT_STRING_LONG];
+static char units[MAX_INSTANCE_COUNT][LIGHT_STRING_SHORT];
+
+static struct lwm2m_engine_obj light_control;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(LIGHT_ON_OFF_ID, RW, BOOL),
+	OBJ_FIELD_DATA(LIGHT_DIMMER_ID, RW_OPT, U8),
+	OBJ_FIELD_DATA(LIGHT_ON_TIME_ID, RW_OPT, S32),
+	OBJ_FIELD_DATA(LIGHT_CUMULATIVE_ACTIVE_POWER_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(LIGHT_POWER_FACTOR_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(LIGHT_COLOUR_ID, RW_OPT, STRING),
+	OBJ_FIELD_DATA(LIGHT_SENSOR_UNITS_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(LIGHT_APPLICATION_TYPE_ID, RW_OPT, STRING),
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][LIGHT_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static void *on_time_read_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
+			     size_t *data_len)
+{
+	int i;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		if (on_off_value[i]) {
+			on_time_value[i] = (k_uptime_get() / MSEC_PER_SEC) -
+				on_time_offset[i];
+		}
+
+		*data_len = sizeof(on_time_value[i]);
+		return &on_time_value[i];
+	}
+
+	return NULL;
+}
+
+static int on_time_post_write_cb(uint16_t obj_inst_id,
+				 uint16_t res_id, uint16_t res_inst_id,
+				 uint8_t *data, uint16_t data_len,
+				 bool last_block, size_t total_size)
+{
+	int i;
+
+	if (data_len != 4U) {
+		LOG_ERR("unknown size %u", data_len);
+		return -EINVAL;
+	}
+
+	int32_t counter = *(int32_t *) data;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		if (counter == 0) {
+			on_time_offset[i] =
+				(int32_t)(k_uptime_get() / MSEC_PER_SEC);
+		}
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static struct lwm2m_engine_obj_inst *light_control_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	on_off_value[avail] = false;
+	dimmer_value[avail] = 0U;
+	on_time_value[avail] = 0;
+	on_time_offset[avail] = 0U;
+	cumulative_active_value[avail].val1 = 0;
+	cumulative_active_value[avail].val2 = 0;
+	power_factor_value[avail].val1 = 0;
+	power_factor_value[avail].val2 = 0;
+	colour[avail][0] = '\0';
+	units[avail][0] = '\0';
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(LIGHT_ON_OFF_ID, res[avail], i, res_inst[avail], j,
+			  &on_off_value[avail], sizeof(*on_off_value));
+	INIT_OBJ_RES_DATA(LIGHT_DIMMER_ID, res[avail], i, res_inst[avail], j,
+			  &dimmer_value[avail], sizeof(*dimmer_value));
+	INIT_OBJ_RES(LIGHT_ON_TIME_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &on_time_value[avail], sizeof(*on_time_value),
+		     on_time_read_cb, NULL, on_time_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(LIGHT_CUMULATIVE_ACTIVE_POWER_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &cumulative_active_value[avail],
+			  sizeof(*cumulative_active_value));
+	INIT_OBJ_RES_DATA(LIGHT_POWER_FACTOR_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &power_factor_value[avail],
+			  sizeof(*power_factor_value));
+	INIT_OBJ_RES_DATA(LIGHT_COLOUR_ID, res[avail], i,
+			  res_inst[avail], j,
+			  colour[avail], LIGHT_STRING_LONG);
+	INIT_OBJ_RES_DATA(LIGHT_SENSOR_UNITS_ID, res[avail], i,
+			  res_inst[avail], j,
+			  units[avail], LIGHT_STRING_SHORT);
+	INIT_OBJ_RES_OPTDATA(LIGHT_APPLICATION_TYPE_ID, res[avail], i,
+			     res_inst[avail], j);
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO Light Control instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_light_control_init(const struct device *dev)
+{
+	light_control.obj_id = IPSO_OBJECT_LIGHT_CONTROL_ID;
+	light_control.fields = fields;
+	light_control.field_count = ARRAY_SIZE(fields);
+	light_control.max_instance_count = MAX_INSTANCE_COUNT;
+	light_control.create_cb = light_control_create;
+	lwm2m_register_obj(&light_control);
+
+	return 0;
+}
+
+SYS_INIT(ipso_light_control_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_onoff_switch.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_onoff_switch.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_onoff_switch.c	(working copy)
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO On/Off Switch object (3342):
+ * http://www.openmobilealliance.org/tech/profiles/lwm2m/3342.xml
+ */
+
+#define LOG_MODULE_NAME net_ipso_onoff_switch
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#ifdef CONFIG_LWM2M_IPSO_ONOFF_SWITCH_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#else
+#define ADD_TIMESTAMPS 0
+#endif
+
+/* resource IDs */
+#define SWITCH_DIGITAL_STATE_ID		5500
+#define SWITCH_DIGITAL_INPUT_COUNTER_ID	5501
+#define SWITCH_ON_TIME_ID		5852
+#define SWITCH_OFF_TIME_ID		5854
+#define SWITCH_APPLICATION_TYPE_ID	5750
+#if ADD_TIMESTAMPS
+#define SWITCH_TIMESTAMP_ID		5518
+
+#define SWITCH_MAX_ID			6
+#else
+#define SWITCH_MAX_ID			5
+#endif
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_ONOFF_SWITCH_INSTANCE_COUNT
+
+/*
+ * Calculate resource instances as follows:
+ * start with SWITCH_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT        (SWITCH_MAX_ID)
+
+/* resource state */
+struct ipso_switch_data {
+	uint64_t trigger_offset;
+	uint64_t on_time_sec;
+	uint64_t off_time_sec;
+	uint64_t counter;
+	uint16_t obj_inst_id;
+	bool last_state;
+	bool state;
+};
+
+static struct ipso_switch_data switch_data[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj onoff_switch;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(SWITCH_DIGITAL_STATE_ID, R, BOOL),
+	OBJ_FIELD_DATA(SWITCH_DIGITAL_INPUT_COUNTER_ID, R_OPT, U64),
+	OBJ_FIELD_DATA(SWITCH_ON_TIME_ID, RW_OPT, U64),
+	OBJ_FIELD_DATA(SWITCH_OFF_TIME_ID, RW_OPT, U64),
+	OBJ_FIELD_DATA(SWITCH_APPLICATION_TYPE_ID, RW_OPT, STRING),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(SWITCH_TIMESTAMP_ID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SWITCH_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static int get_switch_index(uint16_t obj_inst_id)
+{
+	int i, ret = -ENOENT;
+
+	for (i = 0; i < ARRAY_SIZE(inst); i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		ret = i;
+		break;
+	}
+
+	return ret;
+}
+
+static int state_post_write_cb(uint16_t obj_inst_id,
+			       uint16_t res_id, uint16_t res_inst_id,
+			       uint8_t *data, uint16_t data_len,
+			       bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_switch_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	if (switch_data[i].state) {
+		/* reset off time */
+		switch_data[i].off_time_sec = 0U;
+		if (!switch_data[i].last_state) {
+			/* off to on transition */
+			switch_data[i].counter++;
+		}
+	} else {
+		/* reset on time */
+		switch_data[i].on_time_sec = 0U;
+	}
+
+	switch_data[i].last_state = switch_data[i].state;
+	switch_data[i].trigger_offset = k_uptime_get();
+	return 0;
+}
+
+static void *on_time_read_cb(uint16_t obj_inst_id,
+			     uint16_t res_id, uint16_t res_inst_id,
+			     size_t *data_len)
+{
+	int i = get_switch_index(obj_inst_id);
+
+	if (i < 0) {
+		return NULL;
+	}
+
+	if (switch_data[i].state) {
+		switch_data[i].on_time_sec =
+			(k_uptime_get() - switch_data[i].trigger_offset) / 1000;
+	}
+
+	*data_len = sizeof(switch_data[i].on_time_sec);
+	return &switch_data[i].on_time_sec;
+}
+
+static void *off_time_read_cb(uint16_t obj_inst_id,
+			      uint16_t res_id, uint16_t res_inst_id,
+			      size_t *data_len)
+{
+	int i = get_switch_index(obj_inst_id);
+
+	if (i < 0) {
+		return NULL;
+	}
+
+	if (!switch_data[i].state) {
+		switch_data[i].off_time_sec =
+			(k_uptime_get() - switch_data[i].trigger_offset) / 1000;
+	}
+
+	*data_len = sizeof(switch_data[i].off_time_sec);
+	return &switch_data[i].off_time_sec;
+}
+
+static int time_post_write_cb(uint16_t obj_inst_id,
+			      uint16_t res_id, uint16_t res_inst_id,
+			      uint8_t *data, uint16_t data_len,
+			      bool last_block, size_t total_size)
+{
+	int i = get_switch_index(obj_inst_id);
+
+	if (i < 0) {
+		return i;
+	}
+
+	switch_data[i].trigger_offset = 0U;
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *switch_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < ARRAY_SIZE(inst); index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	(void)memset(&switch_data[avail], 0, sizeof(switch_data[avail]));
+	switch_data[avail].obj_inst_id = obj_inst_id;
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(SWITCH_DIGITAL_STATE_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &switch_data[avail].state,
+		     sizeof(switch_data[avail].state),
+		     NULL, NULL, state_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(SWITCH_DIGITAL_INPUT_COUNTER_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &switch_data[avail].counter,
+			  sizeof(switch_data[avail].counter));
+	INIT_OBJ_RES_OPT(SWITCH_ON_TIME_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     on_time_read_cb, NULL, time_post_write_cb, NULL);
+	INIT_OBJ_RES_OPT(SWITCH_OFF_TIME_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     off_time_read_cb, NULL, time_post_write_cb, NULL);
+	INIT_OBJ_RES_OPTDATA(SWITCH_APPLICATION_TYPE_ID, res[avail], i,
+			     res_inst[avail], j);
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(SWITCH_TIMESTAMP_ID, res[avail], i,
+			     res_inst[avail], j);
+#endif
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO On/Off Switch instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_switch_init(const struct device *dev)
+{
+	onoff_switch.obj_id = IPSO_OBJECT_ONOFF_SWITCH_ID;
+	onoff_switch.fields = fields;
+	onoff_switch.field_count = ARRAY_SIZE(fields);
+	onoff_switch.max_instance_count = ARRAY_SIZE(inst);
+	onoff_switch.create_cb = switch_create;
+	lwm2m_register_obj(&onoff_switch);
+
+	return 0;
+}
+
+SYS_INIT(ipso_switch_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_pressure_sensor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_pressure_sensor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_pressure_sensor.c	(working copy)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ * Copyright (c) 2020 Laird Connectivity
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_ipso_pressure_sensor
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+#include "lwm2m_resource_ids.h"
+
+#ifdef CONFIG_LWM2M_IPSO_PRESSURE_SENSOR_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#define NUMBER_OF_OBJ_FIELDS 8
+#else
+#define ADD_TIMESTAMPS 0
+#define NUMBER_OF_OBJ_FIELDS 7
+#endif
+
+#define MAX_INSTANCE_COUNT CONFIG_LWM2M_IPSO_PRESSURE_SENSOR_INSTANCE_COUNT
+
+#define IPSO_OBJECT_ID IPSO_OBJECT_PRESSURE_ID
+
+#define SENSOR_NAME "Pressure"
+
+#define UNIT_STR_MAX_SIZE 8
+
+/*
+ * Calculate resource instances as follows:
+ * start with NUMBER_OF_OBJ_FIELDS
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT (NUMBER_OF_OBJ_FIELDS - 1)
+
+/* resource state variables */
+static float32_value_t sensor_value[MAX_INSTANCE_COUNT];
+static char units[MAX_INSTANCE_COUNT][UNIT_STR_MAX_SIZE];
+static float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj sensor;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(SENSOR_VALUE_RID, R, FLOAT32),
+	OBJ_FIELD_DATA(SENSOR_UNITS_RID, R_OPT, STRING),
+	OBJ_FIELD_DATA(MIN_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_MEASURED_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MIN_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(MAX_RANGE_VALUE_RID, R_OPT, FLOAT32),
+	OBJ_FIELD_EXECUTE_OPT(RESET_MIN_MAX_MEASURED_VALUES_RID),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(TIMESTAMP_RID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][NUMBER_OF_OBJ_FIELDS];
+static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT]
+					    [RESOURCE_INSTANCE_COUNT];
+
+static void update_min_measured(uint16_t obj_inst_id, int index)
+{
+	min_measured_value[index].val1 = sensor_value[index].val1;
+	min_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MIN_MEASURED_VALUE_RID);
+}
+
+static void update_max_measured(uint16_t obj_inst_id, int index)
+{
+	max_measured_value[index].val1 = sensor_value[index].val1;
+	max_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_ID, obj_inst_id, MAX_MEASURED_VALUE_RID);
+}
+
+static int reset_min_max_measured_values_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	LOG_DBG("RESET MIN/MAX %d", obj_inst_id);
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			update_min_measured(obj_inst_id, i);
+			update_max_measured(obj_inst_id, i);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int sensor_value_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				 uint16_t res_inst_id, uint8_t *data,
+				 uint16_t data_len, bool last_block,
+				 size_t total_size)
+{
+	int i;
+	bool update_min = false;
+	bool update_max = false;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			/* update min / max */
+			if (sensor_value[i].val1 < min_measured_value[i].val1) {
+				update_min = true;
+			} else if (sensor_value[i].val1 ==
+					   min_measured_value[i].val1 &&
+				   sensor_value[i].val2 <
+					   min_measured_value[i].val2) {
+				update_min = true;
+			}
+
+			if (sensor_value[i].val1 > max_measured_value[i].val1) {
+				update_max = true;
+			} else if (sensor_value[i].val1 ==
+					   max_measured_value[i].val1 &&
+				   sensor_value[i].val2 >
+					   max_measured_value[i].val2) {
+				update_max = true;
+			}
+
+			if (update_min) {
+				update_min_measured(obj_inst_id, i);
+			}
+
+			if (update_max) {
+				update_max_measured(obj_inst_id, i);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *
+pressure_sensor_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u",
+				obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	sensor_value[index].val1 = 0;
+	sensor_value[index].val2 = 0;
+	units[index][0] = '\0';
+	min_measured_value[index].val1 = INT32_MAX;
+	min_measured_value[index].val2 = 0;
+	max_measured_value[index].val1 = -INT32_MAX;
+	max_measured_value[index].val2 = 0;
+	min_range_value[index].val1 = 0;
+	min_range_value[index].val2 = 0;
+	max_range_value[index].val1 = 0;
+	max_range_value[index].val2 = 0;
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(SENSOR_VALUE_RID, res[index], i, res_inst[index], j, 1,
+		     true, &sensor_value[index], sizeof(*sensor_value), NULL,
+		     NULL, sensor_value_write_cb, NULL);
+	INIT_OBJ_RES_DATA(SENSOR_UNITS_RID, res[index], i, res_inst[index], j,
+			  units[index], UNIT_STR_MAX_SIZE);
+	INIT_OBJ_RES_DATA(MIN_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &min_measured_value[index],
+			  sizeof(*min_measured_value));
+	INIT_OBJ_RES_DATA(MAX_MEASURED_VALUE_RID, res[index], i,
+			  res_inst[index], j, &max_measured_value[index],
+			  sizeof(*max_measured_value));
+	INIT_OBJ_RES_DATA(MIN_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &min_range_value[index], sizeof(*min_range_value));
+	INIT_OBJ_RES_DATA(MAX_RANGE_VALUE_RID, res[index], i, res_inst[index],
+			  j, &max_range_value[index], sizeof(*max_range_value));
+	INIT_OBJ_RES_EXECUTE(RESET_MIN_MAX_MEASURED_VALUES_RID, res[index], i,
+			     reset_min_max_measured_values_cb);
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(TIMESTAMP_RID, res[index], i, res_inst[index], j);
+#endif
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Created IPSO %s Sensor instance: %d", SENSOR_NAME,
+		obj_inst_id);
+	return &inst[index];
+}
+
+static int ipso_pressure_sensor_init(const struct device *dev)
+{
+	sensor.obj_id = IPSO_OBJECT_ID;
+	sensor.fields = fields;
+	sensor.field_count = ARRAY_SIZE(fields);
+	sensor.max_instance_count = MAX_INSTANCE_COUNT;
+	sensor.create_cb = pressure_sensor_create;
+	lwm2m_register_obj(&sensor);
+
+	return 0;
+}
+
+SYS_INIT(ipso_pressure_sensor_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_push_button.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_push_button.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_push_button.c	(working copy)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO On/Off Switch object (3347):
+ * http://www.openmobilealliance.org/tech/profiles/lwm2m/3347.xml
+ */
+
+#define LOG_MODULE_NAME net_ipso_button
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#ifdef CONFIG_LWM2M_IPSO_PUSH_BUTTON_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#else
+#define ADD_TIMESTAMPS 0
+#endif
+
+/* resource IDs */
+#define BUTTON_DIGITAL_STATE_ID		5500
+#define BUTTON_DIGITAL_INPUT_COUNTER_ID	5501
+#define BUTTON_APPLICATION_TYPE_ID	5750
+#if ADD_TIMESTAMPS
+#define BUTTON_TIMESTAMP_ID		5518
+
+#define BUTTON_MAX_ID			4
+#else
+#define BUTTON_MAX_ID			3
+#endif
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_PUSH_BUTTON_INSTANCE_COUNT
+
+/*
+ * Calculate resource instances as follows:
+ * start with BUTTON_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT        (BUTTON_MAX_ID)
+
+/* resource state */
+struct ipso_button_data {
+	uint64_t counter;
+	uint16_t obj_inst_id;
+	bool last_state;
+	bool state;
+};
+
+static struct ipso_button_data button_data[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj onoff_switch;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(BUTTON_DIGITAL_STATE_ID, R, BOOL),
+	OBJ_FIELD_DATA(BUTTON_DIGITAL_INPUT_COUNTER_ID, R_OPT, U64),
+	OBJ_FIELD_DATA(BUTTON_APPLICATION_TYPE_ID, RW_OPT, STRING),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(BUTTON_TIMESTAMP_ID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][BUTTON_MAX_ID];
+static struct lwm2m_engine_res_inst
+			res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static int get_button_index(uint16_t obj_inst_id)
+{
+	int i, ret = -ENOENT;
+
+	for (i = 0; i < ARRAY_SIZE(inst); i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		ret = i;
+		break;
+	}
+
+	return ret;
+}
+
+static int state_post_write_cb(uint16_t obj_inst_id,
+			       uint16_t res_id, uint16_t res_inst_id,
+			       uint8_t *data, uint16_t data_len,
+			       bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_button_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	if (button_data[i].state && !button_data[i].last_state) {
+		/* off to on transition */
+		button_data[i].counter++;
+	}
+
+	button_data[i].last_state = button_data[i].state;
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *button_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < ARRAY_SIZE(inst); index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	(void)memset(&button_data[avail], 0, sizeof(button_data[avail]));
+	button_data[avail].obj_inst_id = obj_inst_id;
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(BUTTON_DIGITAL_STATE_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &button_data[avail].state,
+		     sizeof(button_data[avail].state),
+		     NULL, NULL, state_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(BUTTON_DIGITAL_INPUT_COUNTER_ID, res[avail], i,
+			  res_inst[avail], j,
+			  &button_data[avail].counter,
+			  sizeof(button_data[avail].counter));
+	INIT_OBJ_RES_OPTDATA(BUTTON_APPLICATION_TYPE_ID, res[avail], i,
+			     res_inst[avail], j);
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(BUTTON_TIMESTAMP_ID, res[avail], i,
+			     res_inst[avail], j);
+#endif
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO Button instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_button_init(const struct device *dev)
+{
+	onoff_switch.obj_id = IPSO_OBJECT_PUSH_BUTTON_ID;
+	onoff_switch.fields = fields;
+	onoff_switch.field_count = ARRAY_SIZE(fields);
+	onoff_switch.max_instance_count = ARRAY_SIZE(inst);
+	onoff_switch.create_cb = button_create;
+	lwm2m_register_obj(&onoff_switch);
+
+	return 0;
+}
+
+SYS_INIT(ipso_button_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_temp_sensor.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_temp_sensor.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_temp_sensor.c	(working copy)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO Temperature Sensor object (3303):
+ * https://github.com/IPSO-Alliance/pub/blob/master/docs/IPSO-Smart-Objects.pdf
+ * Section: "10. IPSO Object: Temperature"
+ */
+
+#define LOG_MODULE_NAME net_ipso_temp_sensor
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#ifdef CONFIG_LWM2M_IPSO_TEMP_SENSOR_TIMESTAMP
+#define ADD_TIMESTAMPS 1
+#else
+#define ADD_TIMESTAMPS 0
+#endif
+
+/* Server resource IDs */
+#define TEMP_SENSOR_VALUE_ID			5700
+#define TEMP_UNITS_ID				5701
+#define TEMP_MIN_MEASURED_VALUE_ID		5601
+#define TEMP_MAX_MEASURED_VALUE_ID		5602
+#define TEMP_MIN_RANGE_VALUE_ID			5603
+#define TEMP_MAX_RANGE_VALUE_ID			5604
+#define TEMP_RESET_MIN_MAX_MEASURED_VALUES_ID	5605
+#if ADD_TIMESTAMPS
+#define TEMP_TIMESTAMP_ID			5518
+
+#define TEMP_MAX_ID		8
+#else  /* !ADD_TIMESTAMPS */
+#define TEMP_MAX_ID		7
+#endif
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_TEMP_SENSOR_INSTANCE_COUNT
+
+#define TEMP_STRING_SHORT	8
+
+/*
+ * Calculate resource instances as follows:
+ * start with TEMP_MAX_ID
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT	(TEMP_MAX_ID - 1)
+
+/* resource state variables */
+static float32_value_t sensor_value[MAX_INSTANCE_COUNT];
+static char units[MAX_INSTANCE_COUNT][TEMP_STRING_SHORT];
+static float32_value_t min_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_measured_value[MAX_INSTANCE_COUNT];
+static float32_value_t min_range_value[MAX_INSTANCE_COUNT];
+static float32_value_t max_range_value[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj temp_sensor;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(TEMP_SENSOR_VALUE_ID, R, FLOAT32),
+	OBJ_FIELD_DATA(TEMP_UNITS_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(TEMP_MIN_MEASURED_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(TEMP_MAX_MEASURED_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(TEMP_MIN_RANGE_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(TEMP_MAX_RANGE_VALUE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_EXECUTE_OPT(TEMP_RESET_MIN_MAX_MEASURED_VALUES_ID),
+#if ADD_TIMESTAMPS
+	OBJ_FIELD_DATA(TEMP_TIMESTAMP_ID, RW_OPT, TIME),
+#endif
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][TEMP_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static void update_min_measured(uint16_t obj_inst_id, int index)
+{
+	min_measured_value[index].val1 = sensor_value[index].val1;
+	min_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
+			TEMP_MIN_MEASURED_VALUE_ID);
+}
+
+static void update_max_measured(uint16_t obj_inst_id, int index)
+{
+	max_measured_value[index].val1 = sensor_value[index].val1;
+	max_measured_value[index].val2 = sensor_value[index].val2;
+	NOTIFY_OBSERVER(IPSO_OBJECT_TEMP_SENSOR_ID, obj_inst_id,
+			TEMP_MAX_MEASURED_VALUE_ID);
+}
+
+static int reset_min_max_measured_values_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	LOG_DBG("RESET MIN/MAX %d", obj_inst_id);
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			update_min_measured(obj_inst_id, i);
+			update_max_measured(obj_inst_id, i);
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int sensor_value_write_cb(uint16_t obj_inst_id,
+				 uint16_t res_id, uint16_t res_inst_id,
+				 uint8_t *data, uint16_t data_len,
+				 bool last_block, size_t total_size)
+{
+	int i;
+	bool update_min = false;
+	bool update_max = false;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			/* update min / max */
+			if (sensor_value[i].val1 < min_measured_value[i].val1) {
+				update_min = true;
+			} else if (sensor_value[i].val1 ==
+					min_measured_value[i].val1 &&
+				   sensor_value[i].val2 <
+					min_measured_value[i].val2) {
+				update_min = true;
+			}
+
+			if (sensor_value[i].val1 > max_measured_value[i].val1) {
+				update_max = true;
+			} else if (sensor_value[i].val1 ==
+					max_measured_value[i].val1 &&
+				   sensor_value[i].val2 >
+					max_measured_value[i].val2) {
+				update_max = true;
+			}
+
+			if (update_min) {
+				update_min_measured(obj_inst_id, i);
+			}
+
+			if (update_max) {
+				update_max_measured(obj_inst_id, i);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *temp_sensor_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	sensor_value[index].val1 = 0;
+	sensor_value[index].val2 = 0;
+	units[index][0] = '\0';
+	min_measured_value[index].val1 = INT32_MAX;
+	min_measured_value[index].val2 = 0;
+	max_measured_value[index].val1 = -INT32_MAX;
+	max_measured_value[index].val2 = 0;
+	min_range_value[index].val1 = 0;
+	min_range_value[index].val2 = 0;
+	max_range_value[index].val1 = 0;
+	max_range_value[index].val2 = 0;
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES(TEMP_SENSOR_VALUE_ID, res[index], i,
+		     res_inst[index], j, 1, true,
+		     &sensor_value[index], sizeof(*sensor_value),
+		     NULL, NULL, sensor_value_write_cb, NULL);
+	INIT_OBJ_RES_DATA(TEMP_UNITS_ID, res[index], i, res_inst[index], j,
+			  units[index], TEMP_STRING_SHORT);
+	INIT_OBJ_RES_DATA(TEMP_MIN_MEASURED_VALUE_ID, res[index], i,
+			  res_inst[index], j, &min_measured_value[index],
+			  sizeof(*min_measured_value));
+	INIT_OBJ_RES_DATA(TEMP_MAX_MEASURED_VALUE_ID, res[index], i,
+			  res_inst[index], j, &max_measured_value[index],
+			  sizeof(*max_measured_value));
+	INIT_OBJ_RES_DATA(TEMP_MIN_RANGE_VALUE_ID, res[index], i,
+			  res_inst[index], j, &min_range_value[index],
+			  sizeof(*min_range_value));
+	INIT_OBJ_RES_DATA(TEMP_MAX_RANGE_VALUE_ID, res[index], i,
+			  res_inst[index], j, &max_range_value[index],
+			  sizeof(*max_range_value));
+	INIT_OBJ_RES_EXECUTE(TEMP_RESET_MIN_MAX_MEASURED_VALUES_ID,
+			     res[index], i, reset_min_max_measured_values_cb);
+#if ADD_TIMESTAMPS
+	INIT_OBJ_RES_OPTDATA(TEMP_TIMESTAMP_ID, res[index], i,
+			     res_inst[index], j);
+#endif
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Create IPSO Temperature Sensor instance: %d", obj_inst_id);
+	return &inst[index];
+}
+
+static int ipso_temp_sensor_init(const struct device *dev)
+{
+	temp_sensor.obj_id = IPSO_OBJECT_TEMP_SENSOR_ID;
+	temp_sensor.fields = fields;
+	temp_sensor.field_count = ARRAY_SIZE(fields);
+	temp_sensor.max_instance_count = MAX_INSTANCE_COUNT;
+	temp_sensor.create_cb = temp_sensor_create;
+	lwm2m_register_obj(&temp_sensor);
+
+	return 0;
+}
+
+SYS_INIT(ipso_temp_sensor_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_timer.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_timer.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/ipso_timer.c	(working copy)
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Source material for IPSO Timer object (3340):
+ * http://www.openmobilealliance.org/tech/profiles/lwm2m/3340.xml
+ */
+
+#define LOG_MODULE_NAME net_ipso_timer
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Server resource IDs */
+#define TIMER_DELAY_DURATION_ID		5521
+#define TIMER_REMAINING_TIME_ID		5538
+#define TIMER_MINIMUM_OFF_TIME_ID	5525
+#define TIMER_TRIGGER_ID		5523
+#define TIMER_ON_OFF_ID			5850
+#define TIMER_DIGITAL_INPUT_COUNTER_ID	5501
+#define TIMER_CUMULATIVE_TIME_ID	5544
+#define TIMER_DIGITAL_STATE_ID		5543
+#define TIMER_COUNTER_ID		5534
+#define TIMER_MODE_ID			5526
+#define TIMER_APPLICATION_TYPE_ID	5750
+
+#define TIMER_MAX_ID		11
+
+#define MAX_INSTANCE_COUNT	CONFIG_LWM2M_IPSO_TIMER_INSTANCE_COUNT
+
+/*
+ * Calculate resource instances as follows:
+ * start with TIMER_MAX_ID
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT	(TIMER_MAX_ID - 1)
+
+enum ipso_timer_mode {
+	TIMER_MODE_OFF = 0,
+	TIMER_MODE_ONE_SHOT,
+	TIMER_MODE_INTERVAL,		/* TODO */
+	TIMER_MODE_DELAY_ON_PICKUP,	/* TODO */
+	TIMER_MODE_DELAY_ON_DROPOUT,	/* TODO */
+};
+
+/* resource state */
+struct ipso_timer_data {
+	float64_value_t delay_duration;
+	float64_value_t remaining_time;
+	float64_value_t min_off_time;
+	float64_value_t cumulative_time;
+
+	uint64_t trigger_offset;
+	uint32_t trigger_counter;
+	uint32_t cumulative_time_ms;
+
+	struct k_delayed_work timer_work;
+
+	uint16_t obj_inst_id;
+	uint8_t timer_mode;
+	bool enabled;
+	bool active;
+};
+
+static struct ipso_timer_data timer_data[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj timer;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(TIMER_DELAY_DURATION_ID, RW, FLOAT64),
+	OBJ_FIELD_DATA(TIMER_REMAINING_TIME_ID, R_OPT, FLOAT64),
+	OBJ_FIELD_DATA(TIMER_MINIMUM_OFF_TIME_ID, RW_OPT, FLOAT64),
+	OBJ_FIELD_EXECUTE_OPT(TIMER_TRIGGER_ID),
+	OBJ_FIELD_DATA(TIMER_ON_OFF_ID, RW_OPT, BOOL),
+	OBJ_FIELD_DATA(TIMER_DIGITAL_INPUT_COUNTER_ID, RW_OPT, U32), /* TODO */
+	OBJ_FIELD_DATA(TIMER_CUMULATIVE_TIME_ID, RW_OPT, FLOAT64),
+	OBJ_FIELD_DATA(TIMER_DIGITAL_STATE_ID, R_OPT, BOOL),
+	OBJ_FIELD_DATA(TIMER_COUNTER_ID, R_OPT, U32),
+	OBJ_FIELD_DATA(TIMER_MODE_ID, RW_OPT, U8),
+	OBJ_FIELD_DATA(TIMER_APPLICATION_TYPE_ID, RW_OPT, STRING),
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][TIMER_MAX_ID];
+static struct lwm2m_engine_res_inst
+		res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static int ms2float(uint32_t ms, float64_value_t *f)
+{
+	f->val1 = ms / MSEC_PER_SEC;
+	f->val2 = (ms % MSEC_PER_SEC) * (LWM2M_FLOAT64_DEC_MAX / MSEC_PER_SEC);
+
+	return 0;
+}
+
+static int float2ms(float64_value_t *f, uint32_t *ms)
+{
+	*ms = f->val1 * MSEC_PER_SEC;
+	*ms += f->val2 / (LWM2M_FLOAT64_DEC_MAX / MSEC_PER_SEC);
+
+	return 0;
+}
+
+static int get_timer_index(uint16_t obj_inst_id)
+{
+	int i, ret = -ENOENT;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (!inst[i].obj || inst[i].obj_inst_id != obj_inst_id) {
+			continue;
+		}
+
+		ret = i;
+		break;
+	}
+
+	return ret;
+}
+
+static int start_timer(struct ipso_timer_data *timer)
+{
+	uint32_t temp = 0U;
+	char path[MAX_RESOURCE_LEN];
+
+	/* make sure timer is enabled and not already active */
+	if (timer->timer_mode == TIMER_MODE_OFF || timer->active ||
+	    !timer->enabled) {
+		return -EINVAL;
+	}
+
+	/* check min off time from last trigger_offset */
+	float2ms(&timer->min_off_time, &temp);
+	if (k_uptime_get() < timer->trigger_offset + temp) {
+		return -EINVAL;
+	}
+
+	/* TODO: check delay_duration > 0 ? other modes can it be 0? */
+
+	timer->trigger_offset = k_uptime_get();
+	timer->trigger_counter += 1U;
+
+	snprintk(path, MAX_RESOURCE_LEN, "%d/%u/%d", IPSO_OBJECT_TIMER_ID,
+		 timer->obj_inst_id, TIMER_DIGITAL_STATE_ID);
+	lwm2m_engine_set_bool(path, true);
+
+	float2ms(&timer->delay_duration, &temp);
+	k_delayed_work_submit(&timer->timer_work, K_MSEC(temp));
+
+	return 0;
+}
+
+static int stop_timer(struct ipso_timer_data *timer, bool cancel)
+{
+	char path[MAX_RESOURCE_LEN];
+
+	/* make sure timer is active */
+	if (!timer->active) {
+		return -EINVAL;
+	}
+
+	timer->cumulative_time_ms += k_uptime_get() - timer->trigger_offset;
+	snprintk(path, MAX_RESOURCE_LEN, "%d/%u/%d", IPSO_OBJECT_TIMER_ID,
+		 timer->obj_inst_id, TIMER_DIGITAL_STATE_ID);
+	lwm2m_engine_set_bool(path, false);
+
+	if (cancel) {
+		k_delayed_work_cancel(&timer->timer_work);
+	}
+
+	return 0;
+}
+
+static void *remaining_time_read_cb(uint16_t obj_inst_id,
+				    uint16_t res_id, uint16_t res_inst_id,
+				    size_t *data_len)
+{
+	uint32_t temp = 0U;
+	int i;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return NULL;
+	}
+
+	if (timer_data[i].active) {
+		float2ms(&timer_data[i].delay_duration, &temp);
+		temp -= (k_uptime_get() - timer_data[i].trigger_offset);
+		ms2float(temp, &timer_data[i].remaining_time);
+	} else {
+		timer_data[i].remaining_time.val1 = 0;
+		timer_data[i].remaining_time.val2 = 0;
+	}
+
+	*data_len = sizeof(timer_data[i].remaining_time);
+	return &timer_data[i].remaining_time;
+}
+
+static void *cumulative_time_read_cb(uint16_t obj_inst_id,
+				     uint16_t res_id, uint16_t res_inst_id,
+				     size_t *data_len)
+{
+	int i;
+	uint32_t temp;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return NULL;
+	}
+
+	temp = timer_data[i].cumulative_time_ms;
+	if (timer_data[i].active) {
+		temp += k_uptime_get() - timer_data[i].trigger_offset;
+	}
+
+	ms2float(temp, &timer_data[i].cumulative_time);
+
+	*data_len = sizeof(timer_data[i].cumulative_time);
+	return &timer_data[i].cumulative_time;
+}
+
+static int cumulative_time_post_write_cb(uint16_t obj_inst_id,
+					 uint16_t res_id, uint16_t res_inst_id,
+					 uint8_t *data, uint16_t data_len,
+					 bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	timer_data[i].cumulative_time_ms = 0U;
+	return 0;
+}
+
+static int enabled_post_write_cb(uint16_t obj_inst_id,
+				 uint16_t res_id, uint16_t res_inst_id,
+				 uint8_t *data, uint16_t data_len,
+				 bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	/* check if timer is active and move to disabled state */
+	if (!timer_data[i].enabled && timer_data[i].active) {
+		return stop_timer(&timer_data[i], true);
+	}
+
+	return 0;
+}
+
+static int trigger_counter_post_write_cb(uint16_t obj_inst_id,
+					 uint16_t res_id, uint16_t res_inst_id,
+					 uint8_t *data, uint16_t data_len,
+					 bool last_block, size_t total_size)
+{
+	int i;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	timer_data[i].trigger_counter = 0U;
+	return 0;
+}
+
+static void timer_work_cb(struct k_work *work)
+{
+	struct ipso_timer_data *timer = CONTAINER_OF(work,
+						     struct ipso_timer_data,
+						     timer_work);
+	stop_timer(timer, false);
+}
+
+static int timer_trigger_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	i = get_timer_index(obj_inst_id);
+	if (i < 0) {
+		return i;
+	}
+
+	return start_timer(&timer_data[i]);
+}
+
+static struct lwm2m_engine_obj_inst *timer_create(uint16_t obj_inst_id)
+{
+	int index, avail = -1, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+
+		/* Save first available slot index */
+		if (avail < 0 && !inst[index].obj) {
+			avail = index;
+		}
+	}
+
+	if (avail < 0) {
+		LOG_ERR("Can not create instance - no more room: %u",
+			obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	(void)memset(&timer_data[avail], 0, sizeof(timer_data[avail]));
+	k_delayed_work_init(&timer_data[avail].timer_work, timer_work_cb);
+	timer_data[avail].delay_duration.val1 = 5; /* 5 seconds */
+	timer_data[avail].enabled = true;
+	timer_data[avail].timer_mode = TIMER_MODE_ONE_SHOT;
+	timer_data[avail].obj_inst_id = obj_inst_id;
+
+	(void)memset(res[avail], 0,
+		     sizeof(res[avail][0]) * ARRAY_SIZE(res[avail]));
+	init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(TIMER_DELAY_DURATION_ID, res[avail], i,
+			  res_inst[avail], j, &timer_data[avail].delay_duration,
+			  sizeof(timer_data[avail].delay_duration));
+	INIT_OBJ_RES(TIMER_REMAINING_TIME_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &timer_data[avail].remaining_time,
+		     sizeof(timer_data[avail].remaining_time),
+		     remaining_time_read_cb, NULL, NULL, NULL);
+	INIT_OBJ_RES_DATA(TIMER_MINIMUM_OFF_TIME_ID, res[avail], i,
+			  res_inst[avail], j, &timer_data[avail].min_off_time,
+			  sizeof(timer_data[avail].min_off_time));
+	INIT_OBJ_RES_EXECUTE(TIMER_TRIGGER_ID, res[avail], i,
+			     timer_trigger_cb);
+	INIT_OBJ_RES(TIMER_ON_OFF_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &timer_data[avail].enabled,
+		     sizeof(timer_data[avail].enabled),
+		     NULL, NULL, enabled_post_write_cb, NULL);
+	INIT_OBJ_RES(TIMER_CUMULATIVE_TIME_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &timer_data[avail].cumulative_time,
+		     sizeof(timer_data[avail].cumulative_time),
+		     cumulative_time_read_cb, NULL,
+		     cumulative_time_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(TIMER_DIGITAL_STATE_ID, res[avail], i,
+			  res_inst[avail], j, &timer_data[avail].active,
+			  sizeof(timer_data[avail].active));
+	INIT_OBJ_RES(TIMER_COUNTER_ID, res[avail], i,
+		     res_inst[avail], j, 1, true,
+		     &timer_data[avail].trigger_counter,
+		     sizeof(timer_data[avail].trigger_counter),
+		     NULL, NULL, trigger_counter_post_write_cb, NULL);
+	INIT_OBJ_RES_DATA(TIMER_MODE_ID, res[avail], i, res_inst[avail], j,
+			  &timer_data[avail].timer_mode,
+			  sizeof(timer_data[avail].timer_mode));
+	INIT_OBJ_RES_OPTDATA(TIMER_APPLICATION_TYPE_ID, res[avail], i,
+			     res_inst[avail], j);
+
+	inst[avail].resources = res[avail];
+	inst[avail].resource_count = i;
+
+	LOG_DBG("Create IPSO Timer instance: %d", obj_inst_id);
+
+	return &inst[avail];
+}
+
+static int ipso_timer_init(const struct device *dev)
+{
+	timer.obj_id = IPSO_OBJECT_TIMER_ID;
+	timer.fields = fields;
+	timer.field_count = ARRAY_SIZE(fields);
+	timer.max_instance_count = MAX_INSTANCE_COUNT;
+	timer.create_cb = timer_create;
+	lwm2m_register_obj(&timer);
+
+	return 0;
+}
+
+SYS_INIT(ipso_timer_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.h	(working copy)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef LWM2M_ENGINE_H
+#define LWM2M_ENGINE_H
+
+#include "lwm2m_object.h"
+
+#define LWM2M_PROTOCOL_VERSION "1.0"
+
+/* LWM2M / CoAP Content-Formats */
+#define LWM2M_FORMAT_PLAIN_TEXT		0
+#define LWM2M_FORMAT_APP_LINK_FORMAT	40
+#define LWM2M_FORMAT_APP_OCTET_STREAM	42
+#define LWM2M_FORMAT_APP_EXI		47
+#define LWM2M_FORMAT_APP_JSON		50
+#define LWM2M_FORMAT_OMA_PLAIN_TEXT	1541
+#define LWM2M_FORMAT_OMA_OLD_TLV	1542
+#define LWM2M_FORMAT_OMA_OLD_JSON	1543
+#define LWM2M_FORMAT_OMA_OLD_OPAQUE	1544
+#define LWM2M_FORMAT_OMA_TLV		11542
+#define LWM2M_FORMAT_OMA_JSON		11543
+/* 65000 ~ 65535 inclusive are reserved for experiments */
+#define LWM2M_FORMAT_NONE		65535
+
+
+#define COAP_RESPONSE_CODE_CLASS(x)	(x >> 5)
+#define COAP_RESPONSE_CODE_DETAIL(x)	(x & 0x1F)
+
+/* TODO: */
+#define NOTIFY_OBSERVER(o, i, r)	lwm2m_notify_observer(o, i, r)
+#define NOTIFY_OBSERVER_PATH(path)	lwm2m_notify_observer_path(path)
+
+/* Use this value to generate new token */
+#define LWM2M_MSG_TOKEN_GENERATE_NEW 0xFFU
+
+/* length of time in milliseconds to wait for buffer allocations */
+#define BUF_ALLOC_TIMEOUT K_SECONDS(1)
+
+/* coap reply status */
+#define COAP_REPLY_STATUS_NONE		0
+#define COAP_REPLY_STATUS_ERROR		1
+
+/* Establish a request handler callback type */
+typedef int (*udp_request_handler_cb_t)(struct coap_packet *request,
+					struct lwm2m_message *msg);
+
+char *lwm2m_sprint_ip_addr(const struct sockaddr *addr);
+
+int lwm2m_notify_observer(uint16_t obj_id, uint16_t obj_inst_id, uint16_t res_id);
+int lwm2m_notify_observer_path(struct lwm2m_obj_path *path);
+
+void lwm2m_register_obj(struct lwm2m_engine_obj *obj);
+void lwm2m_unregister_obj(struct lwm2m_engine_obj *obj);
+struct lwm2m_engine_obj_field *
+lwm2m_get_engine_obj_field(struct lwm2m_engine_obj *obj, int res_id);
+int  lwm2m_create_obj_inst(uint16_t obj_id, uint16_t obj_inst_id,
+			   struct lwm2m_engine_obj_inst **obj_inst);
+int  lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id);
+int  lwm2m_get_or_create_engine_obj(struct lwm2m_message *msg,
+				    struct lwm2m_engine_obj_inst **obj_inst,
+				    uint8_t *created);
+
+/* LwM2M context functions */
+int lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx);
+void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx);
+
+/* Message buffer functions */
+uint8_t *lwm2m_get_message_buf(void);
+int lwm2m_put_message_buf(uint8_t *buf);
+
+/* LwM2M message functions */
+struct lwm2m_message *lwm2m_get_message(struct lwm2m_ctx *client_ctx);
+void lwm2m_reset_message(struct lwm2m_message *msg, bool release);
+int lwm2m_init_message(struct lwm2m_message *msg);
+int lwm2m_send_message(struct lwm2m_message *msg);
+
+uint16_t lwm2m_get_rd_data(uint8_t *client_data, uint16_t size);
+
+int lwm2m_perform_read_op(struct lwm2m_message *msg, uint16_t content_format);
+
+int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
+			struct lwm2m_engine_res *res,
+			struct lwm2m_engine_res_inst *res_inst,
+			struct lwm2m_engine_obj_field *obj_field,
+			struct lwm2m_message *msg);
+
+enum coap_block_size lwm2m_default_block_size(void);
+
+int lwm2m_engine_add_service(k_work_handler_t service, uint32_t period_ms);
+
+int lwm2m_engine_get_resource(char *pathstr,
+			      struct lwm2m_engine_res **res);
+
+void lwm2m_engine_get_binding(char *binding);
+
+size_t lwm2m_engine_get_opaque_more(struct lwm2m_input_context *in,
+				    uint8_t *buf, size_t buflen,
+				    struct lwm2m_opaque_context *opaque,
+				    bool *last_block);
+
+int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id);
+int lwm2m_security_index_to_inst_id(int index);
+
+int32_t lwm2m_server_get_pmin(uint16_t obj_inst_id);
+int32_t lwm2m_server_get_pmax(uint16_t obj_inst_id);
+int lwm2m_server_short_id_to_inst(uint16_t short_id);
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
+uint8_t lwm2m_firmware_get_update_state(void);
+void lwm2m_firmware_set_update_state(uint8_t state);
+void lwm2m_firmware_set_update_result(uint8_t result);
+uint8_t lwm2m_firmware_get_update_result(void);
+#endif
+
+/* Network Layer */
+int  lwm2m_socket_add(struct lwm2m_ctx *ctx);
+void lwm2m_socket_del(struct lwm2m_ctx *ctx);
+int  lwm2m_socket_start(struct lwm2m_ctx *client_ctx);
+int  lwm2m_parse_peerinfo(char *url, struct sockaddr *addr, bool *use_dtls);
+
+#endif /* LWM2M_ENGINE_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_engine.c	(working copy)
@@ -0,0 +1,4483 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Uses some original concepts by:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ *         Joel Hoglund <joel@sics.se>
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_engine
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <init.h>
+#include <sys/mutex.h>
+#include <sys/printk.h>
+#include <net/net_ip.h>
+#include <net/http_parser_url.h>
+#include <net/socket.h>
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+#include <net/tls_credentials.h>
+#endif
+#if defined(CONFIG_DNS_RESOLVER)
+#include <net/dns_resolve.h>
+#endif
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+#include "lwm2m_rw_plain_text.h"
+#include "lwm2m_rw_oma_tlv.h"
+#ifdef CONFIG_LWM2M_RW_JSON_SUPPORT
+#include "lwm2m_rw_json.h"
+#endif
+#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
+#include "lwm2m_rd_client.h"
+#endif
+
+#define ENGINE_UPDATE_INTERVAL_MS 500
+
+#define WELL_KNOWN_CORE_PATH	"</.well-known/core>"
+
+/*
+ * TODO: to implement a way for clients to specify alternate path
+ * via Kconfig (LwM2M specification 8.2.2 Alternate Path)
+ *
+ * For now, in order to inform server we support JSON format, we have to
+ * report 'ct=11543' to the server. '</>' is required in order to append
+ * content attribute. And resource type attribute is appended because of
+ * Eclipse wakaama will reject the registration when 'rt="oma.lwm2m"' is
+ * missing.
+ */
+
+#define RESOURCE_TYPE		";rt=\"oma.lwm2m\""
+
+#if defined(CONFIG_LWM2M_RW_JSON_SUPPORT)
+#define REG_PREFACE		"</>" RESOURCE_TYPE \
+				";ct=" STRINGIFY(LWM2M_FORMAT_OMA_JSON)
+#else
+#define REG_PREFACE		""
+#endif
+
+#if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN)
+#define	COAP_OPTION_BUF_LEN	(CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE + 1)
+#else
+#define	COAP_OPTION_BUF_LEN	13
+#endif
+
+#define MAX_TOKEN_LEN		8
+
+struct observe_node {
+	sys_snode_t node;
+	struct lwm2m_ctx *ctx;
+	struct lwm2m_obj_path path;
+	uint8_t  token[MAX_TOKEN_LEN];
+	int64_t event_timestamp;
+	int64_t last_timestamp;
+	uint32_t min_period_sec;
+	uint32_t max_period_sec;
+	uint32_t counter;
+	uint16_t format;
+	uint8_t  tkl;
+};
+
+struct notification_attrs {
+	/* use to determine which value is set */
+	float32_value_t gt;
+	float32_value_t lt;
+	float32_value_t st;
+	int32_t pmin;
+	int32_t pmax;
+	uint8_t flags;
+};
+
+static struct observe_node observe_node_data[CONFIG_LWM2M_ENGINE_MAX_OBSERVER];
+
+#define MAX_PERIODIC_SERVICE	10
+
+struct service_node {
+	sys_snode_t node;
+	k_work_handler_t service_work;
+	uint32_t min_call_period; /* ms */
+	uint64_t last_timestamp; /* ms */
+};
+
+static struct service_node service_node_data[MAX_PERIODIC_SERVICE];
+
+static sys_slist_t engine_obj_list;
+static sys_slist_t engine_obj_inst_list;
+static sys_slist_t engine_observer_list;
+static sys_slist_t engine_service_list;
+
+static K_KERNEL_STACK_DEFINE(engine_thread_stack,
+			      CONFIG_LWM2M_ENGINE_STACK_SIZE);
+static struct k_thread engine_thread_data;
+
+#define MAX_POLL_FD		CONFIG_NET_SOCKETS_POLL_MAX
+
+static struct lwm2m_ctx *sock_ctx[MAX_POLL_FD];
+static struct pollfd sock_fds[MAX_POLL_FD];
+static int sock_nfds;
+
+#define NUM_BLOCK1_CONTEXT	CONFIG_LWM2M_NUM_BLOCK1_CONTEXT
+
+/* TODO: figure out what's correct value */
+#define TIMEOUT_BLOCKWISE_TRANSFER_MS (MSEC_PER_SEC * 30)
+
+static struct lwm2m_block_context block1_contexts[NUM_BLOCK1_CONTEXT];
+
+/* write-attribute related definitons */
+static const char * const LWM2M_ATTR_STR[] = { "pmin", "pmax",
+					       "gt", "lt", "st" };
+static const uint8_t LWM2M_ATTR_LEN[] = { 4, 4, 2, 2, 2 };
+
+static struct lwm2m_attr write_attr_pool[CONFIG_LWM2M_NUM_ATTR];
+
+static struct lwm2m_engine_obj *get_engine_obj(int obj_id);
+static struct lwm2m_engine_obj_inst *get_engine_obj_inst(int obj_id,
+							 int obj_inst_id);
+
+/* Shared set of in-flight LwM2M messages */
+static struct lwm2m_message messages[CONFIG_LWM2M_ENGINE_MAX_MESSAGES];
+
+/* for debugging: to print IP addresses */
+char *lwm2m_sprint_ip_addr(const struct sockaddr *addr)
+{
+	static char buf[NET_IPV6_ADDR_LEN];
+
+	if (addr->sa_family == AF_INET6) {
+		return net_addr_ntop(AF_INET6, &net_sin6(addr)->sin6_addr,
+				     buf, sizeof(buf));
+	}
+
+	if (addr->sa_family == AF_INET) {
+		return net_addr_ntop(AF_INET, &net_sin(addr)->sin_addr,
+				     buf, sizeof(buf));
+	}
+
+	LOG_ERR("Unknown IP address family:%d", addr->sa_family);
+	strcpy(buf, "unk");
+	return buf;
+}
+
+static uint8_t to_hex_digit(uint8_t digit)
+{
+	if (digit >= 10U) {
+		return digit - 10U + 'a';
+	}
+
+	return digit + '0';
+}
+
+static char *sprint_token(const uint8_t *token, uint8_t tkl)
+{
+	static char buf[32];
+	char *ptr = buf;
+
+	if (token && tkl != 0) {
+		int i;
+
+		tkl = MIN(tkl, sizeof(buf) / 2 - 1);
+
+		for (i = 0; i < tkl; i++) {
+			*ptr++ = to_hex_digit(token[i] >> 4);
+			*ptr++ = to_hex_digit(token[i] & 0x0F);
+		}
+
+		*ptr = '\0';
+	} else {
+		strcpy(buf, "[no-token]");
+	}
+
+	return buf;
+}
+
+/* block-wise transfer functions */
+
+enum coap_block_size lwm2m_default_block_size(void)
+{
+	switch (CONFIG_LWM2M_COAP_BLOCK_SIZE) {
+	case 16:
+		return COAP_BLOCK_16;
+	case 32:
+		return COAP_BLOCK_32;
+	case 64:
+		return COAP_BLOCK_64;
+	case 128:
+		return COAP_BLOCK_128;
+	case 256:
+		return COAP_BLOCK_256;
+	case 512:
+		return COAP_BLOCK_512;
+	case 1024:
+		return COAP_BLOCK_1024;
+	}
+
+	return COAP_BLOCK_256;
+}
+
+static int init_block_ctx(const uint8_t *token, uint8_t tkl,
+			  struct lwm2m_block_context **ctx)
+{
+	int i;
+	int64_t timestamp;
+
+	*ctx = NULL;
+	timestamp = k_uptime_get();
+	for (i = 0; i < NUM_BLOCK1_CONTEXT; i++) {
+		if (block1_contexts[i].tkl == 0U) {
+			*ctx = &block1_contexts[i];
+			break;
+		}
+
+		if (timestamp - block1_contexts[i].timestamp >
+		    TIMEOUT_BLOCKWISE_TRANSFER_MS) {
+			*ctx = &block1_contexts[i];
+			/* TODO: notify application for block
+			 * transfer timeout
+			 */
+			break;
+		}
+	}
+
+	if (*ctx == NULL) {
+		LOG_ERR("Cannot find free block context");
+		return -ENOMEM;
+	}
+
+	(*ctx)->tkl = tkl;
+	memcpy((*ctx)->token, token, tkl);
+	coap_block_transfer_init(&(*ctx)->ctx, lwm2m_default_block_size(), 0);
+	(*ctx)->timestamp = timestamp;
+	(*ctx)->expected = 0;
+	(*ctx)->last_block = false;
+	memset(&(*ctx)->opaque, 0, sizeof((*ctx)->opaque));
+
+	return 0;
+}
+
+static int get_block_ctx(const uint8_t *token, uint8_t tkl,
+			 struct lwm2m_block_context **ctx)
+{
+	int i;
+
+	*ctx = NULL;
+
+	for (i = 0; i < NUM_BLOCK1_CONTEXT; i++) {
+		if (block1_contexts[i].tkl == tkl &&
+		    memcmp(token, block1_contexts[i].token, tkl) == 0) {
+			*ctx = &block1_contexts[i];
+			/* refresh timestamp */
+			(*ctx)->timestamp = k_uptime_get();
+			break;
+		}
+	}
+
+	if (*ctx == NULL) {
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static void free_block_ctx(struct lwm2m_block_context *ctx)
+{
+	if (ctx == NULL) {
+		return;
+	}
+
+	ctx->tkl = 0U;
+}
+
+/* observer functions */
+
+static int update_attrs(void *ref, struct notification_attrs *out)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
+		if (ref != write_attr_pool[i].ref) {
+			continue;
+		}
+
+		switch (write_attr_pool[i].type) {
+		case LWM2M_ATTR_PMIN:
+			out->pmin = write_attr_pool[i].int_val;
+			break;
+		case LWM2M_ATTR_PMAX:
+			out->pmax = write_attr_pool[i].int_val;
+			break;
+		case LWM2M_ATTR_LT:
+			out->lt = write_attr_pool[i].float_val;
+			break;
+		case LWM2M_ATTR_GT:
+			out->gt = write_attr_pool[i].float_val;
+			break;
+		case LWM2M_ATTR_STEP:
+			out->st = write_attr_pool[i].float_val;
+			break;
+		default:
+			LOG_ERR("Unrecognize attr: %d",
+				write_attr_pool[i].type);
+			return -EINVAL;
+		}
+
+		/* mark as set */
+		out->flags |= BIT(write_attr_pool[i].type);
+	}
+
+	return 0;
+}
+
+static void clear_attrs(void *ref)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
+		if (ref == write_attr_pool[i].ref) {
+			(void)memset(&write_attr_pool[i], 0,
+				     sizeof(write_attr_pool[i]));
+		}
+	}
+}
+
+int lwm2m_notify_observer(uint16_t obj_id, uint16_t obj_inst_id, uint16_t res_id)
+{
+	struct observe_node *obs;
+	int ret = 0;
+
+	/* look for observers which match our resource */
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
+		if (obs->path.obj_id == obj_id &&
+		    obs->path.obj_inst_id == obj_inst_id &&
+		    (obs->path.level < 3 ||
+		     obs->path.res_id == res_id)) {
+			/* update the event time for this observer */
+			obs->event_timestamp = k_uptime_get();
+
+			LOG_DBG("NOTIFY EVENT %u/%u/%u",
+				obj_id, obj_inst_id, res_id);
+
+			ret++;
+		}
+	}
+
+	return ret;
+}
+
+int lwm2m_notify_observer_path(struct lwm2m_obj_path *path)
+{
+	return lwm2m_notify_observer(path->obj_id, path->obj_inst_id,
+				     path->res_id);
+}
+
+static int engine_add_observer(struct lwm2m_message *msg,
+			       const uint8_t *token, uint8_t tkl,
+			       uint16_t format)
+{
+	struct lwm2m_engine_obj *obj = NULL;
+	struct lwm2m_engine_obj_field *obj_field = NULL;
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct observe_node *obs;
+	struct notification_attrs attrs = {
+		.flags = BIT(LWM2M_ATTR_PMIN) | BIT(LWM2M_ATTR_PMAX),
+	};
+	int i, ret;
+
+	if (!msg || !msg->ctx) {
+		LOG_ERR("valid lwm2m message is required");
+		return -EINVAL;
+	}
+
+	if (!token || (tkl == 0U || tkl > MAX_TOKEN_LEN)) {
+		LOG_ERR("token(%p) and token length(%u) must be valid.",
+			token, tkl);
+		return -EINVAL;
+	}
+
+	/* defaults from server object */
+	attrs.pmin = lwm2m_server_get_pmin(msg->ctx->srv_obj_inst);
+	attrs.pmax = lwm2m_server_get_pmax(msg->ctx->srv_obj_inst);
+
+	/* TODO: observe dup checking */
+
+	/* make sure this observer doesn't exist already */
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
+		/* TODO: distinguish server object */
+		if (obs->ctx == msg->ctx &&
+		    memcmp(&obs->path, &msg->path, sizeof(msg->path)) == 0) {
+			/* quietly update the token information */
+			memcpy(obs->token, token, tkl);
+			obs->tkl = tkl;
+
+			LOG_DBG("OBSERVER DUPLICATE %u/%u/%u(%u) [%s]",
+				msg->path.obj_id, msg->path.obj_inst_id,
+				msg->path.res_id, msg->path.level,
+				log_strdup(
+				lwm2m_sprint_ip_addr(&msg->ctx->remote_addr)));
+
+			return 0;
+		}
+	}
+
+	/* check if object exists */
+	obj = get_engine_obj(msg->path.obj_id);
+	if (!obj) {
+		LOG_ERR("unable to find obj: %u", msg->path.obj_id);
+		return -ENOENT;
+	}
+
+	ret = update_attrs(obj, &attrs);
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* check if object instance exists */
+	if (msg->path.level >= 2U) {
+		obj_inst = get_engine_obj_inst(msg->path.obj_id,
+					       msg->path.obj_inst_id);
+		if (!obj_inst) {
+			LOG_ERR("unable to find obj_inst: %u/%u",
+				msg->path.obj_id, msg->path.obj_inst_id);
+			return -ENOENT;
+		}
+
+		ret = update_attrs(obj_inst, &attrs);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	/* check if resource exists */
+	if (msg->path.level >= 3U) {
+		for (i = 0; i < obj_inst->resource_count; i++) {
+			if (obj_inst->resources[i].res_id == msg->path.res_id) {
+				break;
+			}
+		}
+
+		if (i == obj_inst->resource_count) {
+			LOG_ERR("unable to find res_id: %u/%u/%u",
+				msg->path.obj_id, msg->path.obj_inst_id,
+				msg->path.res_id);
+			return -ENOENT;
+		}
+
+		/* load object field data */
+		obj_field = lwm2m_get_engine_obj_field(obj,
+				obj_inst->resources[i].res_id);
+		if (!obj_field) {
+			LOG_ERR("unable to find obj_field: %u/%u/%u",
+				msg->path.obj_id, msg->path.obj_inst_id,
+				msg->path.res_id);
+			return -ENOENT;
+		}
+
+		/* check for READ permission on matching resource */
+		if (!LWM2M_HAS_PERM(obj_field, LWM2M_PERM_R)) {
+			return -EPERM;
+		}
+
+		ret = update_attrs(&obj_inst->resources[i], &attrs);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	/* find an unused observer index node */
+	for (i = 0; i < CONFIG_LWM2M_ENGINE_MAX_OBSERVER; i++) {
+		if (!observe_node_data[i].ctx) {
+			break;
+		}
+	}
+
+	/* couldn't find an index */
+	if (i == CONFIG_LWM2M_ENGINE_MAX_OBSERVER) {
+		return -ENOMEM;
+	}
+
+	/* copy the values and add it to the list */
+	observe_node_data[i].ctx = msg->ctx;
+	memcpy(&observe_node_data[i].path, &msg->path, sizeof(msg->path));
+	memcpy(observe_node_data[i].token, token, tkl);
+	observe_node_data[i].tkl = tkl;
+	observe_node_data[i].last_timestamp = k_uptime_get();
+	observe_node_data[i].event_timestamp =
+			observe_node_data[i].last_timestamp;
+	observe_node_data[i].min_period_sec = attrs.pmin;
+	observe_node_data[i].max_period_sec = MAX(attrs.pmax, attrs.pmin);
+	observe_node_data[i].format = format;
+	observe_node_data[i].counter = 1U;
+	sys_slist_append(&engine_observer_list,
+			 &observe_node_data[i].node);
+
+	LOG_DBG("OBSERVER ADDED %u/%u/%u(%u) token:'%s' addr:%s",
+		msg->path.obj_id, msg->path.obj_inst_id,
+		msg->path.res_id, msg->path.level,
+		log_strdup(sprint_token(token, tkl)),
+		log_strdup(lwm2m_sprint_ip_addr(&msg->ctx->remote_addr)));
+
+	return 0;
+}
+
+static int engine_remove_observer(const uint8_t *token, uint8_t tkl)
+{
+	struct observe_node *obs, *found_obj = NULL;
+	sys_snode_t *prev_node = NULL;
+
+	if (!token || (tkl == 0U || tkl > MAX_TOKEN_LEN)) {
+		LOG_ERR("token(%p) and token length(%u) must be valid.",
+			token, tkl);
+		return -EINVAL;
+	}
+
+	/* find the node index */
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
+		if (memcmp(obs->token, token, tkl) == 0) {
+			found_obj = obs;
+			break;
+		}
+
+		prev_node = &obs->node;
+	}
+
+	if (!found_obj) {
+		return -ENOENT;
+	}
+
+	sys_slist_remove(&engine_observer_list, prev_node, &found_obj->node);
+	(void)memset(found_obj, 0, sizeof(*found_obj));
+
+	LOG_DBG("observer '%s' removed", log_strdup(sprint_token(token, tkl)));
+
+	return 0;
+}
+
+static void engine_remove_observer_by_id(uint16_t obj_id, int32_t obj_inst_id)
+{
+	struct observe_node *obs, *tmp;
+	sys_snode_t *prev_node = NULL;
+
+	/* remove observer instances accordingly */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(
+			&engine_observer_list, obs, tmp, node) {
+		if (!(obj_id == obs->path.obj_id &&
+		      obj_inst_id == obs->path.obj_inst_id)) {
+			prev_node = &obs->node;
+			continue;
+		}
+
+		sys_slist_remove(&engine_observer_list, prev_node, &obs->node);
+		(void)memset(obs, 0, sizeof(*obs));
+	}
+}
+
+/* engine object */
+
+void lwm2m_register_obj(struct lwm2m_engine_obj *obj)
+{
+	sys_slist_append(&engine_obj_list, &obj->node);
+}
+
+void lwm2m_unregister_obj(struct lwm2m_engine_obj *obj)
+{
+	engine_remove_observer_by_id(obj->obj_id, -1);
+	sys_slist_find_and_remove(&engine_obj_list, &obj->node);
+}
+
+static struct lwm2m_engine_obj *get_engine_obj(int obj_id)
+{
+	struct lwm2m_engine_obj *obj;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_list, obj, node) {
+		if (obj->obj_id == obj_id) {
+			return obj;
+		}
+	}
+
+	return NULL;
+}
+
+struct lwm2m_engine_obj_field *
+lwm2m_get_engine_obj_field(struct lwm2m_engine_obj *obj, int res_id)
+{
+	int i;
+
+	if (obj && obj->fields && obj->field_count > 0) {
+		for (i = 0; i < obj->field_count; i++) {
+			if (obj->fields[i].res_id == res_id) {
+				return &obj->fields[i];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/* engine object instance */
+
+static void engine_register_obj_inst(struct lwm2m_engine_obj_inst *obj_inst)
+{
+	sys_slist_append(&engine_obj_inst_list, &obj_inst->node);
+}
+
+static void engine_unregister_obj_inst(struct lwm2m_engine_obj_inst *obj_inst)
+{
+	engine_remove_observer_by_id(
+			obj_inst->obj->obj_id, obj_inst->obj_inst_id);
+	sys_slist_find_and_remove(&engine_obj_inst_list, &obj_inst->node);
+}
+
+static struct lwm2m_engine_obj_inst *get_engine_obj_inst(int obj_id,
+							 int obj_inst_id)
+{
+	struct lwm2m_engine_obj_inst *obj_inst;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_inst_list, obj_inst,
+				     node) {
+		if (obj_inst->obj->obj_id == obj_id &&
+		    obj_inst->obj_inst_id == obj_inst_id) {
+			return obj_inst;
+		}
+	}
+
+	return NULL;
+}
+
+static struct lwm2m_engine_obj_inst *
+next_engine_obj_inst(int obj_id, int obj_inst_id)
+{
+	struct lwm2m_engine_obj_inst *obj_inst, *next = NULL;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_inst_list, obj_inst,
+				     node) {
+		if (obj_inst->obj->obj_id == obj_id &&
+		    obj_inst->obj_inst_id > obj_inst_id &&
+		    (!next || next->obj_inst_id > obj_inst->obj_inst_id)) {
+			next = obj_inst;
+		}
+	}
+
+	return next;
+}
+
+int lwm2m_create_obj_inst(uint16_t obj_id, uint16_t obj_inst_id,
+			  struct lwm2m_engine_obj_inst **obj_inst)
+{
+	struct lwm2m_engine_obj *obj;
+	int ret;
+
+	*obj_inst = NULL;
+	obj = get_engine_obj(obj_id);
+	if (!obj) {
+		LOG_ERR("unable to find obj: %u", obj_id);
+		return -ENOENT;
+	}
+
+	if (!obj->create_cb) {
+		LOG_ERR("obj %u has no create_cb", obj_id);
+		return -EINVAL;
+	}
+
+	if (obj->instance_count + 1 > obj->max_instance_count) {
+		LOG_ERR("no more instances available for obj %u", obj_id);
+		return -ENOMEM;
+	}
+
+	*obj_inst = obj->create_cb(obj_inst_id);
+	if (!*obj_inst) {
+		LOG_ERR("unable to create obj %u instance %u",
+			obj_id, obj_inst_id);
+		/*
+		 * Already checked for instance count total.
+		 * This can only be an error if the object instance exists.
+		 */
+		return -EEXIST;
+	}
+
+	obj->instance_count++;
+	(*obj_inst)->obj = obj;
+	(*obj_inst)->obj_inst_id = obj_inst_id;
+	engine_register_obj_inst(*obj_inst);
+
+	if (obj->user_create_cb) {
+		ret = obj->user_create_cb(obj_inst_id);
+		if (ret < 0) {
+			LOG_ERR("Error in user obj create %u/%u: %d",
+				obj_id, obj_inst_id, ret);
+			lwm2m_delete_obj_inst(obj_id, obj_inst_id);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id)
+{
+	int i, ret = 0;
+	struct lwm2m_engine_obj *obj;
+	struct lwm2m_engine_obj_inst *obj_inst;
+
+	obj = get_engine_obj(obj_id);
+	if (!obj) {
+		return -ENOENT;
+	}
+
+	obj_inst = get_engine_obj_inst(obj_id, obj_inst_id);
+	if (!obj_inst) {
+		return -ENOENT;
+	}
+
+	if (obj->user_delete_cb) {
+		ret = obj->user_delete_cb(obj_inst_id);
+		if (ret < 0) {
+			LOG_ERR("Error in user obj delete %u/%u: %d",
+				obj_id, obj_inst_id, ret);
+			/* don't return error */
+		}
+	}
+
+	engine_unregister_obj_inst(obj_inst);
+	obj->instance_count--;
+
+	if (obj->delete_cb) {
+		ret = obj->delete_cb(obj_inst_id);
+	}
+
+	/* reset obj_inst and res_inst data structure */
+	for (i = 0; i < obj_inst->resource_count; i++) {
+		clear_attrs(&obj_inst->resources[i]);
+		(void)memset(obj_inst->resources + i, 0,
+			     sizeof(struct lwm2m_engine_res));
+	}
+
+	clear_attrs(obj_inst);
+	(void)memset(obj_inst, 0, sizeof(struct lwm2m_engine_obj_inst));
+	return ret;
+}
+
+/* utility functions */
+
+static uint16_t atou16(uint8_t *buf, uint16_t buflen, uint16_t *len)
+{
+	uint16_t val = 0U;
+	uint16_t pos = 0U;
+
+	/* we should get a value first - consume all numbers */
+	while (pos < buflen && isdigit(buf[pos])) {
+		val = val * 10U + (buf[pos] - '0');
+		pos++;
+	}
+
+	*len = pos;
+	return val;
+}
+
+static int atof32(const char *input, float32_value_t *out)
+{
+	char *pos, *end, buf[24];
+	long int val;
+	int32_t base = 1000000, sign = 1;
+
+	if (!input || !out) {
+		return -EINVAL;
+	}
+
+	strncpy(buf, input, sizeof(buf) - 1);
+	buf[sizeof(buf) - 1] = '\0';
+
+	if (strchr(buf, '-')) {
+		sign = -1;
+	}
+
+	pos = strchr(buf, '.');
+	if (pos) {
+		*pos = '\0';
+	}
+
+	errno = 0;
+	val = strtol(buf, &end, 10);
+	if (errno || *end || val < INT_MIN) {
+		return -EINVAL;
+	}
+
+	out->val1 = (int32_t) val;
+	out->val2 = 0;
+
+	if (!pos) {
+		return 0;
+	}
+
+	while (*(++pos) && base > 1 && isdigit((unsigned char)*pos)) {
+		out->val2 = out->val2 * 10 + (*pos - '0');
+		base /= 10;
+	}
+
+	out->val2 *= sign * base;
+	return !*pos || base == 1 ? 0 : -EINVAL;
+}
+
+static int coap_options_to_path(struct coap_option *opt, int options_count,
+				struct lwm2m_obj_path *path)
+{
+	uint16_t len, *id[4] = { &path->obj_id, &path->obj_inst_id,
+			      &path->res_id, &path->res_inst_id };
+
+	path->level = options_count;
+
+	for (int i = 0; i < options_count; i++) {
+		*id[i] = atou16(opt[i].value, opt[i].len, &len);
+		if (len == 0U || opt[i].len != len) {
+			path->level = i;
+			break;
+		}
+	}
+
+	return options_count == path->level ? 0 : -EINVAL;
+}
+
+static struct lwm2m_message *find_msg(struct coap_pending *pending,
+				      struct coap_reply *reply)
+{
+	size_t i;
+
+	if (!pending && !reply) {
+		return NULL;
+	}
+
+	for (i = 0; i < CONFIG_LWM2M_ENGINE_MAX_MESSAGES; i++) {
+		if (messages[i].ctx && messages[i].pending == pending) {
+			return &messages[i];
+		}
+
+		if (messages[i].ctx && messages[i].reply == reply) {
+			return &messages[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct lwm2m_message *lwm2m_get_message(struct lwm2m_ctx *client_ctx)
+{
+	size_t i;
+
+	for (i = 0; i < CONFIG_LWM2M_ENGINE_MAX_MESSAGES; i++) {
+		if (!messages[i].ctx) {
+			messages[i].ctx = client_ctx;
+			return &messages[i];
+		}
+	}
+
+	return NULL;
+}
+
+void lwm2m_reset_message(struct lwm2m_message *msg, bool release)
+{
+	if (!msg) {
+		return;
+	}
+
+	if (msg->pending) {
+		coap_pending_clear(msg->pending);
+	}
+
+	if (msg->reply) {
+		/* make sure we want to clear the reply */
+		coap_reply_clear(msg->reply);
+	}
+
+	if (release) {
+		(void)memset(msg, 0, sizeof(*msg));
+	} else {
+		msg->message_timeout_cb = NULL;
+		(void)memset(&msg->cpkt, 0, sizeof(msg->cpkt));
+	}
+}
+
+int lwm2m_init_message(struct lwm2m_message *msg)
+{
+	uint8_t tokenlen = 0U;
+	uint8_t *token = NULL;
+	int r = 0;
+
+	if (!msg || !msg->ctx) {
+		LOG_ERR("LwM2M message is invalid.");
+		return -EINVAL;
+	}
+
+	if (msg->tkl == LWM2M_MSG_TOKEN_GENERATE_NEW) {
+		tokenlen = 8U;
+		token = coap_next_token();
+	} else if (msg->token && msg->tkl != 0) {
+		tokenlen = msg->tkl;
+		token = msg->token;
+	}
+
+	r = coap_packet_init(&msg->cpkt, msg->msg_data, sizeof(msg->msg_data),
+			     1, msg->type, tokenlen, token, msg->code, msg->mid);
+	if (r < 0) {
+		LOG_ERR("coap packet init error (err:%d)", r);
+		goto cleanup;
+	}
+
+	/* only TYPE_CON messages need pending tracking / reply handling */
+	if (msg->type != COAP_TYPE_CON) {
+		return 0;
+	}
+
+	msg->pending = coap_pending_next_unused(
+				msg->ctx->pendings,
+				CONFIG_LWM2M_ENGINE_MAX_PENDING);
+	if (!msg->pending) {
+		LOG_ERR("Unable to find a free pending to track "
+			"retransmissions.");
+		r = -ENOMEM;
+		goto cleanup;
+	}
+
+	r = coap_pending_init(msg->pending, &msg->cpkt, &msg->ctx->remote_addr);
+	if (r < 0) {
+		LOG_ERR("Unable to initialize a pending "
+			"retransmission (err:%d).", r);
+		goto cleanup;
+	}
+
+	if (msg->reply_cb) {
+		msg->reply = coap_reply_next_unused(
+				msg->ctx->replies,
+				CONFIG_LWM2M_ENGINE_MAX_REPLIES);
+		if (!msg->reply) {
+			LOG_ERR("No resources for waiting for replies.");
+			r = -ENOMEM;
+			goto cleanup;
+		}
+
+		coap_reply_clear(msg->reply);
+		coap_reply_init(msg->reply, &msg->cpkt);
+		msg->reply->reply = msg->reply_cb;
+	}
+
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+
+	return r;
+}
+
+int lwm2m_send_message(struct lwm2m_message *msg)
+{
+	int rc, ret;
+
+	if (!msg || !msg->ctx) {
+		LOG_ERR("LwM2M message is invalid.");
+		return -EINVAL;
+	}
+
+	if (msg->type == COAP_TYPE_CON) {
+		coap_pending_cycle(msg->pending);
+	}
+
+	msg->send_attempts++;
+
+	ret = sys_mutex_lock(&msg->ctx->send_lock, K_FOREVER);
+	__ASSERT(ret == 0, "sys_mutex_lock failed with %d", ret);
+	rc = send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0);
+	ret = sys_mutex_unlock(&msg->ctx->send_lock);
+	__ASSERT(ret == 0, "sys_mutex_unlock failed with %d", ret);
+	ARG_UNUSED(ret);
+	if (rc < 0) {
+		if (msg->type == COAP_TYPE_CON) {
+			coap_pending_clear(msg->pending);
+		}
+
+		LOG_ERR("Failed to send packet, err %d", errno);
+
+		return -errno;
+	}
+
+	if (msg->type == COAP_TYPE_CON) {
+		int32_t remaining = k_delayed_work_remaining_get(
+					&msg->ctx->retransmit_work);
+
+		/* If the item is already pending and its timeout is smaller
+		 * than the new one, skip the submission.
+		 */
+		if (remaining == 0 || remaining > msg->pending->timeout) {
+			k_delayed_work_submit(&msg->ctx->retransmit_work,
+					      K_MSEC(msg->pending->timeout));
+		}
+	} else {
+		lwm2m_reset_message(msg, true);
+	}
+
+	if (IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT) &&
+	    IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED)) {
+		engine_update_tx_time();
+	}
+
+	return 0;
+}
+
+uint16_t lwm2m_get_rd_data(uint8_t *client_data, uint16_t size)
+{
+	struct lwm2m_engine_obj *obj;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	uint8_t temp[32];
+	uint16_t pos = 0U;
+	int len;
+
+	/* Add resource-type/content-type to the registration message */
+	memcpy(client_data, REG_PREFACE, sizeof(REG_PREFACE) - 1);
+	pos += sizeof(REG_PREFACE) - 1;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_list, obj, node) {
+		/* Security obj MUST NOT be part of registration message */
+		if (obj->obj_id == LWM2M_OBJECT_SECURITY_ID) {
+			continue;
+		}
+
+		/* Only report <OBJ_ID> when no instance available */
+		if (obj->instance_count == 0U) {
+			len = snprintk(temp, sizeof(temp), "%s</%u>",
+				       (pos > 0) ? "," : "", obj->obj_id);
+			if (pos + len >= size) {
+				/* full buffer -- exit loop */
+				break;
+			}
+
+			memcpy(&client_data[pos], temp, len);
+			pos += len;
+			continue;
+		}
+
+		SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_inst_list,
+					     obj_inst, node) {
+			if (obj_inst->obj->obj_id == obj->obj_id) {
+				len = snprintk(temp, sizeof(temp),
+					       "%s</%u/%u>",
+					       (pos > 0) ? "," : "",
+					       obj_inst->obj->obj_id,
+					       obj_inst->obj_inst_id);
+				/*
+				 * TODO: iterate through resources once block
+				 * transfer is handled correctly
+				 */
+				if (pos + len >= size) {
+					/* full buffer -- exit loop */
+					break;
+				}
+
+				memcpy(&client_data[pos], temp, len);
+				pos += len;
+			}
+		}
+	}
+
+	client_data[pos] = '\0';
+	return pos;
+}
+
+/* input / output selection */
+
+static int select_writer(struct lwm2m_output_context *out, uint16_t accept)
+{
+	switch (accept) {
+
+	case LWM2M_FORMAT_APP_LINK_FORMAT:
+		/* TODO: rewrite do_discover as content formatter */
+		break;
+
+	case LWM2M_FORMAT_PLAIN_TEXT:
+	case LWM2M_FORMAT_OMA_PLAIN_TEXT:
+		out->writer = &plain_text_writer;
+		break;
+
+	case LWM2M_FORMAT_OMA_TLV:
+	case LWM2M_FORMAT_OMA_OLD_TLV:
+		out->writer = &oma_tlv_writer;
+		break;
+
+#ifdef CONFIG_LWM2M_RW_JSON_SUPPORT
+	case LWM2M_FORMAT_OMA_JSON:
+	case LWM2M_FORMAT_OMA_OLD_JSON:
+		out->writer = &json_writer;
+		break;
+#endif
+
+	default:
+		LOG_WRN("Unknown content type %u", accept);
+		return -ENOMSG;
+
+	}
+
+	return 0;
+}
+
+static int select_reader(struct lwm2m_input_context *in, uint16_t format)
+{
+	switch (format) {
+
+	case LWM2M_FORMAT_APP_OCTET_STREAM:
+	case LWM2M_FORMAT_PLAIN_TEXT:
+	case LWM2M_FORMAT_OMA_PLAIN_TEXT:
+		in->reader = &plain_text_reader;
+		break;
+
+	case LWM2M_FORMAT_OMA_TLV:
+	case LWM2M_FORMAT_OMA_OLD_TLV:
+		in->reader = &oma_tlv_reader;
+		break;
+
+#ifdef CONFIG_LWM2M_RW_JSON_SUPPORT
+	case LWM2M_FORMAT_OMA_JSON:
+	case LWM2M_FORMAT_OMA_OLD_JSON:
+		in->reader = &json_reader;
+		break;
+#endif
+
+	default:
+		LOG_WRN("Unknown content type %u", format);
+		return -ENOMSG;
+	}
+
+	return 0;
+}
+
+/* user data setter functions */
+
+static int string_to_path(char *pathstr, struct lwm2m_obj_path *path,
+			  char delim)
+{
+	uint16_t value, len;
+	int i, tokstart = -1, toklen;
+	int end_index = strlen(pathstr) - 1;
+
+	(void)memset(path, 0, sizeof(*path));
+	for (i = 0; i <= end_index; i++) {
+		/* search for first numeric */
+		if (tokstart == -1) {
+			if (!isdigit((unsigned char)pathstr[i])) {
+				continue;
+			}
+
+			tokstart = i;
+		}
+
+		/* find delimiter char or end of string */
+		if (pathstr[i] == delim || i == end_index) {
+			toklen = i - tokstart + 1;
+
+			/* don't process delimiter char */
+			if (pathstr[i] == delim) {
+				toklen--;
+			}
+
+			if (toklen <= 0) {
+				continue;
+			}
+
+			value = atou16(&pathstr[tokstart], toklen, &len);
+			switch (path->level) {
+
+			case 0:
+				path->obj_id = value;
+				break;
+
+			case 1:
+				path->obj_inst_id = value;
+				break;
+
+			case 2:
+				path->res_id = value;
+				break;
+
+			case 3:
+				path->res_inst_id = value;
+				break;
+
+			default:
+				LOG_ERR("invalid level (%d)", path->level);
+				return -EINVAL;
+
+			}
+
+			/* increase the path level for each token found */
+			path->level++;
+			tokstart = -1;
+		}
+	}
+
+	return 0;
+}
+
+static int path_to_objs(const struct lwm2m_obj_path *path,
+			struct lwm2m_engine_obj_inst **obj_inst,
+			struct lwm2m_engine_obj_field **obj_field,
+			struct lwm2m_engine_res **res,
+			struct lwm2m_engine_res_inst **res_inst)
+{
+	struct lwm2m_engine_obj_inst *oi;
+	struct lwm2m_engine_obj_field *of;
+	struct lwm2m_engine_res *r = NULL;
+	struct lwm2m_engine_res_inst *ri = NULL;
+	int i;
+
+	if (!path) {
+		return -EINVAL;
+	}
+
+	oi = get_engine_obj_inst(path->obj_id, path->obj_inst_id);
+	if (!oi) {
+		LOG_ERR("obj instance %d/%d not found",
+			path->obj_id, path->obj_inst_id);
+		return -ENOENT;
+	}
+
+	if (!oi->resources || oi->resource_count == 0U) {
+		LOG_ERR("obj instance has no resources");
+		return -EINVAL;
+	}
+
+	of = lwm2m_get_engine_obj_field(oi->obj, path->res_id);
+	if (!of) {
+		LOG_ERR("obj field %d not found", path->res_id);
+		return -ENOENT;
+	}
+
+	for (i = 0; i < oi->resource_count; i++) {
+		if (oi->resources[i].res_id == path->res_id) {
+			r = &oi->resources[i];
+			break;
+		}
+	}
+
+	if (!r) {
+		LOG_ERR("resource %d not found", path->res_id);
+		return -ENOENT;
+	}
+
+	for (i = 0; i < r->res_inst_count; i++) {
+		if (r->res_instances[i].res_inst_id == path->res_inst_id) {
+			ri = &r->res_instances[i];
+			break;
+		}
+	}
+
+	/* specifically don't complain about missing resource instance */
+
+	if (obj_inst) {
+		*obj_inst = oi;
+	}
+
+	if (obj_field) {
+		*obj_field = of;
+	}
+
+	if (res) {
+		*res = r;
+	}
+
+	if (ri && res_inst) {
+		*res_inst = ri;
+	}
+
+	return 0;
+}
+
+int lwm2m_engine_create_obj_inst(char *pathstr)
+{
+	struct lwm2m_obj_path path;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	int ret = 0;
+
+	LOG_DBG("path:%s", log_strdup(pathstr));
+
+	/* translate path -> path_obj */
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level != 2U) {
+		LOG_ERR("path must have 2 parts");
+		return -EINVAL;
+	}
+
+	return lwm2m_create_obj_inst(path.obj_id, path.obj_inst_id, &obj_inst);
+}
+
+int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, uint16_t data_len,
+			      uint8_t data_flags)
+{
+	struct lwm2m_obj_path path;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	int ret = 0;
+
+	/* translate path -> path_obj */
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 3) {
+		LOG_ERR("path must have at least 3 parts");
+		return -EINVAL;
+	}
+
+	/* look up resource obj */
+	ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res_inst) {
+		LOG_ERR("res instance %d not found", path.res_inst_id);
+		return -ENOENT;
+	}
+
+	/* assign data elements */
+	res_inst->data_ptr = data_ptr;
+	res_inst->data_len = data_len;
+	res_inst->max_data_len = data_len;
+	res_inst->data_flags = data_flags;
+
+	return ret;
+}
+
+static int lwm2m_engine_set(char *pathstr, void *value, uint16_t len)
+{
+	struct lwm2m_obj_path path;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	struct lwm2m_engine_obj_field *obj_field;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	void *data_ptr = NULL;
+	size_t max_data_len = 0;
+	int ret = 0;
+	bool changed = false;
+
+	LOG_DBG("path:%s, value:%p, len:%d", log_strdup(pathstr), value, len);
+
+	/* translate path -> path_obj */
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 3) {
+		LOG_ERR("path must have at least 3 parts");
+		return -EINVAL;
+	}
+
+	/* look up resource obj */
+	ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res_inst) {
+		LOG_ERR("res instance %d not found", path.res_inst_id);
+		return -ENOENT;
+	}
+
+	if (LWM2M_HAS_RES_FLAG(res_inst, LWM2M_RES_DATA_FLAG_RO)) {
+		LOG_ERR("res instance data pointer is read-only "
+			"[%u/%u/%u/%u:%u]", path.obj_id, path.obj_inst_id,
+			path.res_id, path.res_inst_id, path.level);
+		return -EACCES;
+	}
+
+	/* setup initial data elements */
+	data_ptr = res_inst->data_ptr;
+	max_data_len = res_inst->max_data_len;
+
+	/* allow user to override data elements via callback */
+	if (res->pre_write_cb) {
+		data_ptr = res->pre_write_cb(obj_inst->obj_inst_id,
+					     res->res_id, res_inst->res_inst_id,
+					     &max_data_len);
+	}
+
+	if (!data_ptr) {
+		LOG_ERR("res instance data pointer is NULL [%u/%u/%u/%u:%u]",
+			path.obj_id, path.obj_inst_id, path.res_id,
+			path.res_inst_id, path.level);
+		return -EINVAL;
+	}
+
+	/* check length (note: we add 1 to string length for NULL pad) */
+	if (len > res_inst->max_data_len -
+		(obj_field->data_type == LWM2M_RES_TYPE_STRING ? 1 : 0)) {
+		LOG_ERR("length %u is too long for res instance %d data",
+			len, path.res_id);
+		return -ENOMEM;
+	}
+
+	if (memcmp(data_ptr, value, len) !=  0) {
+		changed = true;
+	}
+
+	switch (obj_field->data_type) {
+
+	case LWM2M_RES_TYPE_OPAQUE:
+		memcpy((uint8_t *)data_ptr, value, len);
+		break;
+
+	case LWM2M_RES_TYPE_STRING:
+		memcpy((uint8_t *)data_ptr, value, len);
+		((uint8_t *)data_ptr)[len] = '\0';
+		break;
+
+	case LWM2M_RES_TYPE_U64:
+		*((uint64_t *)data_ptr) = *(uint64_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_U32:
+	case LWM2M_RES_TYPE_TIME:
+		*((uint32_t *)data_ptr) = *(uint32_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_U16:
+		*((uint16_t *)data_ptr) = *(uint16_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_U8:
+		*((uint8_t *)data_ptr) = *(uint8_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_S64:
+		*((int64_t *)data_ptr) = *(int64_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_S32:
+		*((int32_t *)data_ptr) = *(int32_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_S16:
+		*((int16_t *)data_ptr) = *(int16_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_S8:
+		*((int8_t *)data_ptr) = *(int8_t *)value;
+		break;
+
+	case LWM2M_RES_TYPE_BOOL:
+		*((bool *)data_ptr) = *(bool *)value;
+		break;
+
+	case LWM2M_RES_TYPE_FLOAT32:
+		((float32_value_t *)data_ptr)->val1 =
+				((float32_value_t *)value)->val1;
+		((float32_value_t *)data_ptr)->val2 =
+				((float32_value_t *)value)->val2;
+		break;
+
+	case LWM2M_RES_TYPE_FLOAT64:
+		((float64_value_t *)data_ptr)->val1 =
+				((float64_value_t *)value)->val1;
+		((float64_value_t *)data_ptr)->val2 =
+				((float64_value_t *)value)->val2;
+		break;
+
+	case LWM2M_RES_TYPE_OBJLNK:
+		*((struct lwm2m_objlnk *)data_ptr) =
+				*(struct lwm2m_objlnk *)value;
+		break;
+
+	default:
+		LOG_ERR("unknown obj data_type %d", obj_field->data_type);
+		return -EINVAL;
+
+	}
+
+	res_inst->data_len = len;
+
+	if (res->post_write_cb) {
+		ret = res->post_write_cb(obj_inst->obj_inst_id,
+					 res->res_id, res_inst->res_inst_id,
+					 data_ptr, len, false, 0);
+	}
+
+	if (changed) {
+		NOTIFY_OBSERVER_PATH(&path);
+	}
+
+	return ret;
+}
+
+int lwm2m_engine_set_opaque(char *pathstr, char *data_ptr, uint16_t data_len)
+{
+	return lwm2m_engine_set(pathstr, data_ptr, data_len);
+}
+
+int lwm2m_engine_set_string(char *pathstr, char *data_ptr)
+{
+	return lwm2m_engine_set(pathstr, data_ptr, strlen(data_ptr));
+}
+
+int lwm2m_engine_set_u8(char *pathstr, uint8_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 1);
+}
+
+int lwm2m_engine_set_u16(char *pathstr, uint16_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 2);
+}
+
+int lwm2m_engine_set_u32(char *pathstr, uint32_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 4);
+}
+
+int lwm2m_engine_set_u64(char *pathstr, uint64_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 8);
+}
+
+int lwm2m_engine_set_s8(char *pathstr, int8_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 1);
+}
+
+int lwm2m_engine_set_s16(char *pathstr, int16_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 2);
+}
+
+int lwm2m_engine_set_s32(char *pathstr, int32_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 4);
+}
+
+int lwm2m_engine_set_s64(char *pathstr, int64_t value)
+{
+	return lwm2m_engine_set(pathstr, &value, 8);
+}
+
+int lwm2m_engine_set_bool(char *pathstr, bool value)
+{
+	uint8_t temp = (value != 0 ? 1 : 0);
+
+	return lwm2m_engine_set(pathstr, &temp, 1);
+}
+
+int lwm2m_engine_set_float32(char *pathstr, float32_value_t *value)
+{
+	return lwm2m_engine_set(pathstr, value, sizeof(float32_value_t));
+}
+
+int lwm2m_engine_set_float64(char *pathstr, float64_value_t *value)
+{
+	return lwm2m_engine_set(pathstr, value, sizeof(float64_value_t));
+}
+
+int lwm2m_engine_set_objlnk(char *pathstr, struct lwm2m_objlnk *value)
+{
+	return lwm2m_engine_set(pathstr, value, sizeof(struct lwm2m_objlnk));
+}
+
+/* user data getter functions */
+
+int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, uint16_t *data_len,
+			      uint8_t *data_flags)
+{
+	struct lwm2m_obj_path path;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	int ret = 0;
+
+	/* translate path -> path_obj */
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 3) {
+		LOG_ERR("path must have at least 3 parts");
+		return -EINVAL;
+	}
+
+	/* look up resource obj */
+	ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res_inst) {
+		LOG_ERR("res instance %d not found", path.res_inst_id);
+		return -ENOENT;
+	}
+
+	*data_ptr = res_inst->data_ptr;
+	*data_len = res_inst->data_len;
+	*data_flags = res_inst->data_flags;
+
+	return 0;
+}
+
+static int lwm2m_engine_get(char *pathstr, void *buf, uint16_t buflen)
+{
+	int ret = 0;
+	struct lwm2m_obj_path path;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	struct lwm2m_engine_obj_field *obj_field;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	void *data_ptr = NULL;
+	size_t data_len = 0;
+
+	LOG_DBG("path:%s, buf:%p, buflen:%d", log_strdup(pathstr), buf, buflen);
+
+	/* translate path -> path_obj */
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 3) {
+		LOG_ERR("path must have at least 3 parts");
+		return -EINVAL;
+	}
+
+	/* look up resource obj */
+	ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res_inst) {
+		LOG_ERR("res instance %d not found", path.res_inst_id);
+		return -ENOENT;
+	}
+
+	/* setup initial data elements */
+	data_ptr = res_inst->data_ptr;
+	data_len = res_inst->data_len;
+
+	/* allow user to override data elements via callback */
+	if (res->read_cb) {
+		data_ptr = res->read_cb(obj_inst->obj_inst_id,
+					res->res_id, res_inst->res_inst_id,
+					&data_len);
+	}
+
+	/* TODO: handle data_len > buflen case */
+
+	if (data_ptr && data_len > 0) {
+		switch (obj_field->data_type) {
+
+		case LWM2M_RES_TYPE_OPAQUE:
+			if (data_len > buflen) {
+				return -ENOMEM;
+			}
+
+			memcpy(buf, data_ptr, data_len);
+			break;
+
+		case LWM2M_RES_TYPE_STRING:
+			strncpy((uint8_t *)buf, (uint8_t *)data_ptr, buflen);
+			break;
+
+		case LWM2M_RES_TYPE_U64:
+			*(uint64_t *)buf = *(uint64_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_U32:
+		case LWM2M_RES_TYPE_TIME:
+			*(uint32_t *)buf = *(uint32_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_U16:
+			*(uint16_t *)buf = *(uint16_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_U8:
+			*(uint8_t *)buf = *(uint8_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_S64:
+			*(int64_t *)buf = *(int64_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_S32:
+			*(int32_t *)buf = *(int32_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_S16:
+			*(int16_t *)buf = *(int16_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_S8:
+			*(int8_t *)buf = *(int8_t *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_BOOL:
+			*(bool *)buf = *(bool *)data_ptr;
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT32:
+			((float32_value_t *)buf)->val1 =
+				((float32_value_t *)data_ptr)->val1;
+			((float32_value_t *)buf)->val2 =
+				((float32_value_t *)data_ptr)->val2;
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT64:
+			((float64_value_t *)buf)->val1 =
+				((float64_value_t *)data_ptr)->val1;
+			((float64_value_t *)buf)->val2 =
+				((float64_value_t *)data_ptr)->val2;
+			break;
+
+		case LWM2M_RES_TYPE_OBJLNK:
+			*(struct lwm2m_objlnk *)buf =
+				*(struct lwm2m_objlnk *)data_ptr;
+			break;
+
+		default:
+			LOG_ERR("unknown obj data_type %d",
+				obj_field->data_type);
+			return -EINVAL;
+
+		}
+	}
+
+	return 0;
+}
+
+int lwm2m_engine_get_opaque(char *pathstr, void *buf, uint16_t buflen)
+{
+	return lwm2m_engine_get(pathstr, buf, buflen);
+}
+
+int lwm2m_engine_get_string(char *pathstr, void *buf, uint16_t buflen)
+{
+	return lwm2m_engine_get(pathstr, buf, buflen);
+}
+
+int lwm2m_engine_get_u8(char *pathstr, uint8_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 1);
+}
+
+int lwm2m_engine_get_u16(char *pathstr, uint16_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 2);
+}
+
+int lwm2m_engine_get_u32(char *pathstr, uint32_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 4);
+}
+
+int lwm2m_engine_get_u64(char *pathstr, uint64_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 8);
+}
+
+int lwm2m_engine_get_s8(char *pathstr, int8_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 1);
+}
+
+int lwm2m_engine_get_s16(char *pathstr, int16_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 2);
+}
+
+int lwm2m_engine_get_s32(char *pathstr, int32_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 4);
+}
+
+int lwm2m_engine_get_s64(char *pathstr, int64_t *value)
+{
+	return lwm2m_engine_get(pathstr, value, 8);
+}
+
+int lwm2m_engine_get_bool(char *pathstr, bool *value)
+{
+	int ret = 0;
+	int8_t temp = 0;
+
+	ret = lwm2m_engine_get_s8(pathstr, &temp);
+	if (!ret) {
+		*value = temp != 0;
+	}
+
+	return ret;
+}
+
+int lwm2m_engine_get_float32(char *pathstr, float32_value_t *buf)
+{
+	return lwm2m_engine_get(pathstr, buf, sizeof(float32_value_t));
+}
+
+int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf)
+{
+	return lwm2m_engine_get(pathstr, buf, sizeof(float64_value_t));
+}
+
+int lwm2m_engine_get_objlnk(char *pathstr, struct lwm2m_objlnk *buf)
+{
+	return lwm2m_engine_get(pathstr, buf, sizeof(struct lwm2m_objlnk));
+}
+
+int lwm2m_engine_get_resource(char *pathstr, struct lwm2m_engine_res **res)
+{
+	int ret;
+	struct lwm2m_obj_path path;
+
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 3) {
+		LOG_ERR("path must have 3 parts");
+		return -EINVAL;
+	}
+
+	return path_to_objs(&path, NULL, NULL, res, NULL);
+}
+
+void lwm2m_engine_get_binding(char *binding)
+{
+	if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED)) {
+		strcpy(binding, "UQ");
+	} else {
+		/* Defaults to UDP. */
+		strcpy(binding, "U");
+	}
+}
+
+int lwm2m_engine_create_res_inst(char *pathstr)
+{
+	int ret, i;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	struct lwm2m_obj_path path;
+
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 4) {
+		LOG_ERR("path must have 4 parts");
+		return -EINVAL;
+	}
+
+	ret = path_to_objs(&path, NULL, NULL, &res, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res) {
+		LOG_ERR("resource %u not found", path.res_id);
+		return -ENOENT;
+	}
+
+	if (res_inst && res_inst->res_inst_id != RES_INSTANCE_NOT_CREATED) {
+		LOG_ERR("res instance %u already exists", path.res_inst_id);
+		return -EINVAL;
+	}
+
+	if (!res->res_instances || res->res_inst_count == 0) {
+		LOG_ERR("no available res instances");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < res->res_inst_count; i++) {
+		if (res->res_instances[i].res_inst_id ==
+		    RES_INSTANCE_NOT_CREATED) {
+			break;
+		}
+	}
+
+	if (i >= res->res_inst_count) {
+		LOG_ERR("no available res instances");
+		return -ENOMEM;
+	}
+
+	res->res_instances[i].res_inst_id = path.res_inst_id;
+	return 0;
+}
+
+int lwm2m_engine_delete_res_inst(char *pathstr)
+{
+	int ret;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	struct lwm2m_obj_path path;
+
+	ret = string_to_path(pathstr, &path, '/');
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (path.level < 4) {
+		LOG_ERR("path must have 4 parts");
+		return -EINVAL;
+	}
+
+	ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (!res_inst) {
+		LOG_ERR("res instance %u not found", path.res_inst_id);
+		return -ENOENT;
+	}
+
+	res_inst->data_ptr = NULL;
+	res_inst->max_data_len = 0U;
+	res_inst->data_len = 0U;
+	res_inst->res_inst_id = RES_INSTANCE_NOT_CREATED;
+
+	return 0;
+}
+
+int lwm2m_engine_register_read_callback(char *pathstr,
+					lwm2m_engine_get_data_cb_t cb)
+{
+	int ret;
+	struct lwm2m_engine_res *res = NULL;
+
+	ret = lwm2m_engine_get_resource(pathstr, &res);
+	if (ret < 0) {
+		return ret;
+	}
+
+	res->read_cb = cb;
+	return 0;
+}
+
+int lwm2m_engine_register_pre_write_callback(char *pathstr,
+					     lwm2m_engine_get_data_cb_t cb)
+{
+	int ret;
+	struct lwm2m_engine_res *res = NULL;
+
+	ret = lwm2m_engine_get_resource(pathstr, &res);
+	if (ret < 0) {
+		return ret;
+	}
+
+	res->pre_write_cb = cb;
+	return 0;
+}
+
+int lwm2m_engine_register_post_write_callback(char *pathstr,
+					 lwm2m_engine_set_data_cb_t cb)
+{
+	int ret;
+	struct lwm2m_engine_res *res = NULL;
+
+	ret = lwm2m_engine_get_resource(pathstr, &res);
+	if (ret < 0) {
+		return ret;
+	}
+
+	res->post_write_cb = cb;
+	return 0;
+}
+
+int lwm2m_engine_register_exec_callback(char *pathstr,
+					lwm2m_engine_user_cb_t cb)
+{
+	int ret;
+	struct lwm2m_engine_res *res = NULL;
+
+	ret = lwm2m_engine_get_resource(pathstr, &res);
+	if (ret < 0) {
+		return ret;
+	}
+
+	res->execute_cb = cb;
+	return 0;
+}
+
+int lwm2m_engine_register_create_callback(uint16_t obj_id,
+					  lwm2m_engine_user_cb_t cb)
+{
+	struct lwm2m_engine_obj *obj = NULL;
+
+	obj = get_engine_obj(obj_id);
+	if (!obj) {
+		LOG_ERR("unable to find obj: %u", obj_id);
+		return -ENOENT;
+	}
+
+	obj->user_create_cb = cb;
+	return 0;
+}
+
+int lwm2m_engine_register_delete_callback(uint16_t obj_id,
+					  lwm2m_engine_user_cb_t cb)
+{
+	struct lwm2m_engine_obj *obj = NULL;
+
+	obj = get_engine_obj(obj_id);
+	if (!obj) {
+		LOG_ERR("unable to find obj: %u", obj_id);
+		return -ENOENT;
+	}
+
+	obj->user_delete_cb = cb;
+	return 0;
+}
+
+/* generic data handlers */
+
+static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst,
+			      struct lwm2m_engine_res *res,
+			      struct lwm2m_engine_obj_field *obj_field,
+			      struct lwm2m_message *msg)
+{
+	int i, loop_max = 1, found_values = 0;
+	uint16_t res_inst_id_tmp = 0U;
+	void *data_ptr = NULL;
+	size_t data_len = 0;
+
+	if (!obj_inst || !res || !obj_field || !msg) {
+		return -EINVAL;
+	}
+
+	loop_max = res->res_inst_count;
+	if (loop_max > 1) {
+		/* search for valid resource instances */
+		for (i = 0; i < loop_max; i++) {
+			if (res->res_instances[i].res_inst_id !=
+			    RES_INSTANCE_NOT_CREATED) {
+				found_values = 1;
+				break;
+			}
+		}
+
+		if (!found_values) {
+			return -ENOENT;
+		}
+
+		engine_put_begin_ri(&msg->out, &msg->path);
+		res_inst_id_tmp = msg->path.res_inst_id;
+	}
+
+	for (i = 0; i < loop_max; i++) {
+		if (res->res_instances[i].res_inst_id ==
+		    RES_INSTANCE_NOT_CREATED) {
+			continue;
+		}
+
+		if (res->res_inst_count > 1) {
+			msg->path.res_inst_id =
+				res->res_instances[i].res_inst_id;
+		}
+
+		/* setup initial data elements */
+		data_ptr = res->res_instances[i].data_ptr;
+		data_len = res->res_instances[i].data_len;
+
+		/* allow user to override data elements via callback */
+		if (res->read_cb) {
+			data_ptr = res->read_cb(obj_inst->obj_inst_id,
+					res->res_id,
+					res->res_instances[i].res_inst_id,
+					&data_len);
+		}
+
+		if (!data_ptr || data_len == 0) {
+			return -ENOENT;
+		}
+
+		switch (obj_field->data_type) {
+
+		case LWM2M_RES_TYPE_OPAQUE:
+			engine_put_opaque(&msg->out, &msg->path,
+					  (uint8_t *)data_ptr,
+					  data_len);
+			break;
+
+		case LWM2M_RES_TYPE_STRING:
+			engine_put_string(&msg->out, &msg->path,
+					  (uint8_t *)data_ptr,
+					  strlen((uint8_t *)data_ptr));
+			break;
+
+		case LWM2M_RES_TYPE_U64:
+			engine_put_s64(&msg->out, &msg->path,
+				       (int64_t)*(uint64_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_U32:
+		case LWM2M_RES_TYPE_TIME:
+			engine_put_s32(&msg->out, &msg->path,
+				       (int32_t)*(uint32_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_U16:
+			engine_put_s16(&msg->out, &msg->path,
+				       (int16_t)*(uint16_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_U8:
+			engine_put_s8(&msg->out, &msg->path,
+				      (int8_t)*(uint8_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_S64:
+			engine_put_s64(&msg->out, &msg->path,
+				       *(int64_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_S32:
+			engine_put_s32(&msg->out, &msg->path,
+				       *(int32_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_S16:
+			engine_put_s16(&msg->out, &msg->path,
+				       *(int16_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_S8:
+			engine_put_s8(&msg->out, &msg->path,
+				      *(int8_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_BOOL:
+			engine_put_bool(&msg->out, &msg->path,
+					*(bool *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT32:
+			engine_put_float32fix(&msg->out, &msg->path,
+				(float32_value_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT64:
+			engine_put_float64fix(&msg->out, &msg->path,
+				(float64_value_t *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_OBJLNK:
+			engine_put_objlnk(&msg->out, &msg->path,
+					  (struct lwm2m_objlnk *)data_ptr);
+			break;
+
+		default:
+			LOG_ERR("unknown obj data_type %d",
+				obj_field->data_type);
+			return -EINVAL;
+
+		}
+	}
+
+	if (res->res_inst_count > 1) {
+		engine_put_end_ri(&msg->out, &msg->path);
+		msg->path.res_inst_id = res_inst_id_tmp;
+	}
+
+	return 0;
+}
+
+size_t lwm2m_engine_get_opaque_more(struct lwm2m_input_context *in,
+				    uint8_t *buf, size_t buflen,
+				    struct lwm2m_opaque_context *opaque,
+				    bool *last_block)
+{
+	uint32_t in_len = opaque->remaining;
+	uint16_t remaining = in->in_cpkt->max_len - in->offset;
+
+	if (in_len > buflen) {
+		in_len = buflen;
+	}
+
+	if (in_len > remaining) {
+		in_len = remaining;
+	}
+
+	opaque->remaining -= in_len;
+	remaining -= in_len;
+	if (opaque->remaining == 0U || remaining == 0) {
+		*last_block = true;
+	}
+
+	if (buf_read(buf, in_len, CPKT_BUF_READ(in->in_cpkt),
+		     &in->offset) < 0) {
+		*last_block = true;
+		return 0;
+	}
+
+	return (size_t)in_len;
+}
+
+static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst,
+				      struct lwm2m_engine_res *res,
+				      struct lwm2m_engine_res_inst *res_inst,
+				      struct lwm2m_input_context *in,
+				      void *data_ptr, size_t data_len)
+{
+	size_t len = 1;
+	bool last_pkt_block = false;
+	int ret = 0;
+	bool last_block = true;
+	struct lwm2m_opaque_context opaque_ctx = { 0 };
+
+	if (in->block_ctx != NULL) {
+		last_block = in->block_ctx->last_block;
+
+		/* Restore the opaque context from the block context, if used.
+		*/
+		opaque_ctx = in->block_ctx->opaque;
+	}
+
+	while (!last_pkt_block && len > 0) {
+		len = engine_get_opaque(in, (uint8_t *)data_ptr,
+					data_len, &opaque_ctx, &last_pkt_block);
+		if (len == 0) {
+			/* ignore empty content and continue */
+			return 0;
+		}
+		if (res->post_write_cb) {
+			ret = res->post_write_cb(
+				obj_inst->obj_inst_id, res->res_id,
+				res_inst->res_inst_id, data_ptr, len,
+				last_pkt_block && last_block, opaque_ctx.len);
+			if (ret < 0) {
+				return ret;
+			}
+		}
+	}
+
+	if (in->block_ctx != NULL) {
+		in->block_ctx->opaque = opaque_ctx;
+	}
+
+	return opaque_ctx.len;
+}
+
+/* This function is exposed for the content format writers */
+int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst,
+			struct lwm2m_engine_res *res,
+			struct lwm2m_engine_res_inst *res_inst,
+			struct lwm2m_engine_obj_field *obj_field,
+			struct lwm2m_message *msg)
+{
+	void *data_ptr = NULL;
+	size_t data_len = 0;
+	size_t len = 0;
+	size_t total_size = 0;
+	int64_t temp64 = 0;
+	int32_t temp32 = 0;
+	int ret = 0;
+	bool last_block = true;
+
+	if (!obj_inst || !res || !res_inst || !obj_field || !msg) {
+		return -EINVAL;
+	}
+
+	if (LWM2M_HAS_RES_FLAG(res_inst, LWM2M_RES_DATA_FLAG_RO)) {
+		return -EACCES;
+	}
+
+	/* setup initial data elements */
+	data_ptr = res_inst->data_ptr;
+	data_len = res_inst->max_data_len;
+
+	/* allow user to override data elements via callback */
+	if (res->pre_write_cb) {
+		data_ptr = res->pre_write_cb(obj_inst->obj_inst_id,
+					     res->res_id, res_inst->res_inst_id,
+					     &data_len);
+	}
+
+	if (res->post_write_cb) {
+		if (msg->in.block_ctx != NULL) {
+			/* Get block_ctx for total_size (might be zero) */
+			total_size = msg->in.block_ctx->ctx.total_size;
+			LOG_DBG("BLOCK1: total:%zu current:%zu"
+				" last:%u",
+				msg->in.block_ctx->ctx.total_size,
+				msg->in.block_ctx->ctx.current,
+				msg->in.block_ctx->last_block);
+		}
+	}
+
+	if (data_ptr && data_len > 0) {
+		switch (obj_field->data_type) {
+
+		case LWM2M_RES_TYPE_OPAQUE:
+			ret = lwm2m_write_handler_opaque(obj_inst, res,
+							 res_inst, &msg->in,
+							 data_ptr, data_len);
+			if (ret < 0) {
+				return ret;
+			}
+
+			len = ret;
+			break;
+
+		case LWM2M_RES_TYPE_STRING:
+			engine_get_string(&msg->in, (uint8_t *)data_ptr, data_len);
+			len = strlen((char *)data_ptr);
+			break;
+
+		case LWM2M_RES_TYPE_U64:
+			engine_get_s64(&msg->in, &temp64);
+			*(uint64_t *)data_ptr = temp64;
+			len = 8;
+			break;
+
+		case LWM2M_RES_TYPE_U32:
+		case LWM2M_RES_TYPE_TIME:
+			engine_get_s32(&msg->in, &temp32);
+			*(uint32_t *)data_ptr = temp32;
+			len = 4;
+			break;
+
+		case LWM2M_RES_TYPE_U16:
+			engine_get_s32(&msg->in, &temp32);
+			*(uint16_t *)data_ptr = temp32;
+			len = 2;
+			break;
+
+		case LWM2M_RES_TYPE_U8:
+			engine_get_s32(&msg->in, &temp32);
+			*(uint8_t *)data_ptr = temp32;
+			len = 1;
+			break;
+
+		case LWM2M_RES_TYPE_S64:
+			engine_get_s64(&msg->in, (int64_t *)data_ptr);
+			len = 8;
+			break;
+
+		case LWM2M_RES_TYPE_S32:
+			engine_get_s32(&msg->in, (int32_t *)data_ptr);
+			len = 4;
+			break;
+
+		case LWM2M_RES_TYPE_S16:
+			engine_get_s32(&msg->in, &temp32);
+			*(int16_t *)data_ptr = temp32;
+			len = 2;
+			break;
+
+		case LWM2M_RES_TYPE_S8:
+			engine_get_s32(&msg->in, &temp32);
+			*(int8_t *)data_ptr = temp32;
+			len = 1;
+			break;
+
+		case LWM2M_RES_TYPE_BOOL:
+			engine_get_bool(&msg->in, (bool *)data_ptr);
+			len = 1;
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT32:
+			engine_get_float32fix(&msg->in,
+					      (float32_value_t *)data_ptr);
+			len = sizeof(float32_value_t);
+			break;
+
+		case LWM2M_RES_TYPE_FLOAT64:
+			engine_get_float64fix(&msg->in,
+					      (float64_value_t *)data_ptr);
+			len = sizeof(float64_value_t);
+			break;
+
+		case LWM2M_RES_TYPE_OBJLNK:
+			engine_get_objlnk(&msg->in,
+					  (struct lwm2m_objlnk *)data_ptr);
+			len = sizeof(struct lwm2m_objlnk);
+			break;
+
+		default:
+			LOG_ERR("unknown obj data_type %d",
+				obj_field->data_type);
+			return -EINVAL;
+
+		}
+	} else {
+		return -ENOENT;
+	}
+
+	res_inst->data_len = len;
+
+	if (res->post_write_cb &&
+	    obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) {
+		ret = res->post_write_cb(obj_inst->obj_inst_id,
+					 res->res_id, res_inst->res_inst_id,
+					 data_ptr, len,
+					 last_block, total_size);
+	}
+
+	NOTIFY_OBSERVER_PATH(&msg->path);
+
+	return ret;
+}
+
+static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj,
+				    struct lwm2m_message *msg)
+{
+	bool update_observe_node = false;
+	char opt_buf[COAP_OPTION_BUF_LEN];
+	int nr_opt, i, ret = 0;
+	struct coap_option options[NR_LWM2M_ATTR];
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_attr *attr;
+	struct notification_attrs nattrs = { 0 };
+	struct observe_node *obs;
+	uint8_t type = 0U;
+	void *nattr_ptrs[NR_LWM2M_ATTR] = {
+		&nattrs.pmin, &nattrs.pmax, &nattrs.gt, &nattrs.lt, &nattrs.st
+	};
+	void *ref;
+
+	if (!obj || !msg) {
+		return -EINVAL;
+	}
+
+	/* do not expose security obj */
+	if (obj->obj_id == LWM2M_OBJECT_SECURITY_ID) {
+		return -ENOENT;
+	}
+
+	nr_opt = coap_find_options(msg->in.in_cpkt, COAP_OPTION_URI_QUERY,
+				   options, NR_LWM2M_ATTR);
+	if (nr_opt <= 0) {
+		LOG_ERR("No attribute found!");
+		/* translate as bad request */
+		return -EEXIST;
+	}
+
+	/* get lwm2m_attr slist */
+	if (msg->path.level == 3U) {
+		ret = path_to_objs(&msg->path, NULL, NULL, &res, NULL);
+		if (ret < 0) {
+			return ret;
+		}
+
+		ref = res;
+	} else if (msg->path.level == 1U) {
+		ref = obj;
+	} else if (msg->path.level == 2U) {
+		obj_inst = get_engine_obj_inst(msg->path.obj_id,
+					       msg->path.obj_inst_id);
+		if (!obj_inst) {
+			return -ENOENT;
+		}
+
+		ref = obj_inst;
+	} else {
+		/* bad request */
+		return -EEXIST;
+	}
+
+	/* retrieve existing attributes */
+	ret = update_attrs(ref, &nattrs);
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* loop through options to parse attribute */
+	for (i = 0; i < nr_opt; i++) {
+		int limit = MIN(options[i].len, 5), plen = 0, vlen;
+		float32_value_t val = { 0 };
+		type = 0U;
+
+		/* search for '=' */
+		while (plen < limit && options[i].value[plen] != '=') {
+			plen += 1;
+		}
+
+		/* either length = 2(gt/lt/st) or = 4(pmin/pmax) */
+		if (plen != 2 && plen != 4) {
+			continue;
+		}
+
+		/* matching attribute name */
+		for (type = 0U; type < NR_LWM2M_ATTR; type++) {
+			if (LWM2M_ATTR_LEN[type] == plen &&
+			    !memcmp(options[i].value, LWM2M_ATTR_STR[type],
+				    LWM2M_ATTR_LEN[type])) {
+				break;
+			}
+		}
+
+		/* unrecognized attribute */
+		if (type == NR_LWM2M_ATTR) {
+			continue;
+		}
+
+		/* unset attribute when no value's given */
+		if (options[i].len == plen) {
+			nattrs.flags &= ~BIT(type);
+
+			(void)memset(nattr_ptrs[type], 0,
+				     type <= LWM2M_ATTR_PMAX ? sizeof(int32_t) :
+				     sizeof(float32_value_t));
+			continue;
+		}
+
+		/* gt/lt/st cannot be assigned to obj/obj_inst unless unset */
+		if (plen == 2 && msg->path.level <= 2U) {
+			return -EEXIST;
+		}
+
+		vlen = options[i].len - plen - 1;
+		memcpy(opt_buf, options[i].value + plen + 1, vlen);
+		opt_buf[vlen] = '\0';
+
+		/* convert value to integer or float */
+		if (plen == 4) {
+			char *end;
+			long int v;
+
+			/* pmin/pmax: integer (sec 5.1.2)
+			 * however, negative is non-sense
+			 */
+			errno = 0;
+			v = strtol(opt_buf, &end, 10);
+			if (errno || *end || v < 0) {
+				ret = -EINVAL;
+			}
+
+			val.val1 = v;
+		} else {
+			/* gt/lt/st: type float */
+			ret = atof32(opt_buf, &val);
+		}
+
+		if (ret < 0) {
+			LOG_ERR("invalid attr[%s] value",
+				log_strdup(LWM2M_ATTR_STR[type]));
+			/* bad request */
+			return -EEXIST;
+		}
+
+		if (type <= LWM2M_ATTR_PMAX) {
+			*(int32_t *)nattr_ptrs[type] = val.val1;
+		} else {
+			memcpy(nattr_ptrs[type], &val, sizeof(float32_value_t));
+		}
+
+		nattrs.flags |= BIT(type);
+	}
+
+	if ((nattrs.flags & (BIT(LWM2M_ATTR_PMIN) | BIT(LWM2M_ATTR_PMAX))) &&
+	    nattrs.pmin > nattrs.pmax) {
+		LOG_DBG("pmin (%d) > pmax (%d)", nattrs.pmin, nattrs.pmax);
+		return -EEXIST;
+	}
+
+	if (nattrs.flags & (BIT(LWM2M_ATTR_LT) | BIT(LWM2M_ATTR_GT))) {
+		if (!((nattrs.lt.val1 < nattrs.gt.val1) ||
+		      (nattrs.lt.val2 < nattrs.gt.val2))) {
+			LOG_DBG("lt > gt");
+			return -EEXIST;
+		}
+
+		if (nattrs.flags & BIT(LWM2M_ATTR_STEP)) {
+			int32_t st1 = nattrs.st.val1 * 2 +
+				    nattrs.st.val2 * 2 / 1000000;
+			int32_t st2 = nattrs.st.val2 * 2 % 1000000;
+			if (!(((nattrs.lt.val1 + st1) < nattrs.gt.val1) ||
+			      ((nattrs.lt.val2 + st2) < nattrs.gt.val2))) {
+				LOG_DBG("lt + 2*st > gt");
+				return -EEXIST;
+			}
+		}
+	}
+
+	/* find matching attributes */
+	for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
+		if (ref != write_attr_pool[i].ref) {
+			continue;
+		}
+
+		attr = write_attr_pool + i;
+		type = attr->type;
+
+		if (!(BIT(type) & nattrs.flags)) {
+			LOG_DBG("Unset attr %s",
+				log_strdup(LWM2M_ATTR_STR[type]));
+			(void)memset(attr, 0, sizeof(*attr));
+
+			if (type <= LWM2M_ATTR_PMAX) {
+				update_observe_node = true;
+			}
+
+			continue;
+		}
+
+		nattrs.flags &= ~BIT(type);
+
+		if (type <= LWM2M_ATTR_PMAX) {
+			if (attr->int_val == *(int32_t *)nattr_ptrs[type]) {
+				continue;
+			}
+
+			attr->int_val = *(int32_t *)nattr_ptrs[type];
+			update_observe_node = true;
+		} else {
+			if (!memcmp(&attr->float_val, nattr_ptrs[type],
+				    sizeof(float32_value_t))) {
+				continue;
+			}
+
+			memcpy(&attr->float_val, nattr_ptrs[type],
+			       sizeof(float32_value_t));
+		}
+
+		LOG_DBG("Update %s to %d.%06d",
+			log_strdup(LWM2M_ATTR_STR[type]),
+			attr->float_val.val1, attr->float_val.val2);
+	}
+
+	/* add attribute to obj/obj_inst/res */
+	for (type = 0U; nattrs.flags && type < NR_LWM2M_ATTR; type++) {
+		if (!(BIT(type) & nattrs.flags)) {
+			continue;
+		}
+
+		/* grab an entry for newly added attribute */
+		for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
+			if (!write_attr_pool[i].ref) {
+				break;
+			}
+		}
+
+		if (i == CONFIG_LWM2M_NUM_ATTR) {
+			return -ENOMEM;
+		}
+
+		attr = write_attr_pool + i;
+		attr->type = type;
+		attr->ref = ref;
+
+		if (type <= LWM2M_ATTR_PMAX) {
+			attr->int_val = *(int32_t *)nattr_ptrs[type];
+			update_observe_node = true;
+		} else {
+			memcpy(&attr->float_val, nattr_ptrs[type],
+			       sizeof(float32_value_t));
+		}
+
+		nattrs.flags &= ~BIT(type);
+		LOG_DBG("Add %s to %d.%06d", log_strdup(LWM2M_ATTR_STR[type]),
+			attr->float_val.val1, attr->float_val.val2);
+	}
+
+	/* check only pmin/pmax */
+	if (!update_observe_node) {
+		return 0;
+	}
+
+	/* update observe_node accordingly */
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
+		/* updated path is deeper than obs node, skip */
+		if (msg->path.level > obs->path.level) {
+			continue;
+		}
+
+		/* check obj id matched or not */
+		if (msg->path.obj_id != obs->path.obj_id) {
+			continue;
+		}
+
+		/* defaults from server object */
+		nattrs.pmin = lwm2m_server_get_pmin(msg->ctx->srv_obj_inst);
+		nattrs.pmax = lwm2m_server_get_pmax(msg->ctx->srv_obj_inst);
+
+		ret = update_attrs(obj, &nattrs);
+		if (ret < 0) {
+			return ret;
+		}
+
+		if (obs->path.level > 1) {
+			if (msg->path.level > 1 &&
+			    msg->path.obj_inst_id != obs->path.obj_inst_id) {
+				continue;
+			}
+
+			/* get obj_inst */
+			if (!obj_inst || obj_inst->obj_inst_id !=
+					 obs->path.obj_inst_id) {
+				obj_inst = get_engine_obj_inst(
+						obs->path.obj_id,
+						obs->path.obj_inst_id);
+				if (!obj_inst) {
+					return -ENOENT;
+				}
+			}
+
+			ret = update_attrs(obj_inst, &nattrs);
+			if (ret < 0) {
+				return ret;
+			}
+		}
+
+		if (obs->path.level > 2) {
+			if (msg->path.level > 2 &&
+			    msg->path.res_id != obs->path.res_id) {
+				continue;
+			}
+
+			if (!res || res->res_id != obs->path.res_id) {
+				ret = path_to_objs(&obs->path, NULL, NULL,
+						   &res, NULL);
+				if (ret < 0) {
+					return ret;
+				}
+			}
+
+			ret = update_attrs(res, &nattrs);
+			if (ret < 0) {
+				return ret;
+			}
+		}
+
+		LOG_DBG("%d/%d/%d(%d) updated from %d/%d to %u/%u",
+			obs->path.obj_id, obs->path.obj_inst_id,
+			obs->path.res_id, obs->path.level,
+			obs->min_period_sec, obs->max_period_sec,
+			nattrs.pmin, MAX(nattrs.pmin, nattrs.pmax));
+		obs->min_period_sec = (uint32_t)nattrs.pmin;
+		obs->max_period_sec = (uint32_t)MAX(nattrs.pmin, nattrs.pmax);
+		(void)memset(&nattrs, 0, sizeof(nattrs));
+	}
+
+	return 0;
+}
+
+static int lwm2m_exec_handler(struct lwm2m_message *msg)
+{
+	struct lwm2m_engine_obj_inst *obj_inst;
+	struct lwm2m_engine_res *res = NULL;
+	int ret;
+
+	if (!msg) {
+		return -EINVAL;
+	}
+
+	ret = path_to_objs(&msg->path, &obj_inst, NULL, &res, NULL);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (res->execute_cb) {
+		return res->execute_cb(obj_inst->obj_inst_id);
+	}
+
+	/* TODO: something else to handle for execute? */
+	return -ENOENT;
+}
+
+static int lwm2m_delete_handler(struct lwm2m_message *msg)
+{
+	int ret;
+
+	if (!msg) {
+		return -EINVAL;
+	}
+
+	ret = lwm2m_delete_obj_inst(msg->path.obj_id, msg->path.obj_inst_id);
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT)
+	if (!ret && !msg->ctx->bootstrap_mode) {
+		engine_trigger_update();
+	}
+#endif
+
+	return ret;
+}
+
+static int do_read_op(struct lwm2m_message *msg, uint16_t content_format)
+{
+	switch (content_format) {
+
+	case LWM2M_FORMAT_APP_OCTET_STREAM:
+	case LWM2M_FORMAT_PLAIN_TEXT:
+	case LWM2M_FORMAT_OMA_PLAIN_TEXT:
+		return do_read_op_plain_text(msg, content_format);
+
+	case LWM2M_FORMAT_OMA_TLV:
+	case LWM2M_FORMAT_OMA_OLD_TLV:
+		return do_read_op_tlv(msg, content_format);
+
+#if defined(CONFIG_LWM2M_RW_JSON_SUPPORT)
+	case LWM2M_FORMAT_OMA_JSON:
+	case LWM2M_FORMAT_OMA_OLD_JSON:
+		return do_read_op_json(msg, content_format);
+#endif
+
+	default:
+		LOG_ERR("Unsupported content-format: %u", content_format);
+		return -ENOMSG;
+
+	}
+}
+
+int lwm2m_perform_read_op(struct lwm2m_message *msg, uint16_t content_format)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_obj_field *obj_field;
+	struct lwm2m_obj_path temp_path;
+	int ret = 0, index;
+	uint8_t num_read = 0U;
+
+	if (msg->path.level >= 2U) {
+		obj_inst = get_engine_obj_inst(msg->path.obj_id,
+					       msg->path.obj_inst_id);
+	} else if (msg->path.level == 1U) {
+		/* find first obj_inst with path's obj_id */
+		obj_inst = next_engine_obj_inst(msg->path.obj_id, -1);
+	}
+
+	if (!obj_inst) {
+		return -ENOENT;
+	}
+
+	/* set output content-format */
+	ret = coap_append_option_int(msg->out.out_cpkt,
+				     COAP_OPTION_CONTENT_FORMAT,
+				     content_format);
+	if (ret < 0) {
+		LOG_ERR("Error setting response content-format: %d", ret);
+		return ret;
+	}
+
+	ret = coap_packet_append_payload_marker(msg->out.out_cpkt);
+	if (ret < 0) {
+		LOG_ERR("Error appending payload marker: %d", ret);
+		return ret;
+	}
+
+	/* store original path values so we can change them during processing */
+	memcpy(&temp_path, &msg->path, sizeof(temp_path));
+	engine_put_begin(&msg->out, &msg->path);
+
+	while (obj_inst) {
+		if (!obj_inst->resources || obj_inst->resource_count == 0U) {
+			goto move_forward;
+		}
+
+		/* update the obj_inst_id as we move through the instances */
+		msg->path.obj_inst_id = obj_inst->obj_inst_id;
+
+		if (msg->path.level <= 1U) {
+			/* start instance formatting */
+			engine_put_begin_oi(&msg->out, &msg->path);
+		}
+
+		for (index = 0; index < obj_inst->resource_count; index++) {
+			if (msg->path.level > 2 &&
+			    msg->path.res_id !=
+					obj_inst->resources[index].res_id) {
+				continue;
+			}
+
+			res = &obj_inst->resources[index];
+
+			/*
+			 * On an entire object instance, we need to set path's
+			 * res_id for lwm2m_read_handler to read this specific
+			 * resource.
+			 */
+			msg->path.res_id = res->res_id;
+			obj_field = lwm2m_get_engine_obj_field(obj_inst->obj,
+							       res->res_id);
+			if (!obj_field) {
+				ret = -ENOENT;
+			} else if (!LWM2M_HAS_PERM(obj_field, LWM2M_PERM_R)) {
+				ret = -EPERM;
+			} else {
+				/* start resource formatting */
+				engine_put_begin_r(&msg->out, &msg->path);
+
+				/* perform read operation on this resource */
+				ret = lwm2m_read_handler(obj_inst, res,
+							 obj_field, msg);
+				if (ret < 0) {
+					/* ignore errors unless single read */
+					if (msg->path.level > 2 &&
+					    !LWM2M_HAS_PERM(obj_field,
+						BIT(LWM2M_FLAG_OPTIONAL))) {
+						LOG_ERR("READ OP: %d", ret);
+					}
+				} else {
+					num_read += 1U;
+				}
+
+				/* end resource formatting */
+				engine_put_end_r(&msg->out, &msg->path);
+			}
+
+			/* on single read break if errors */
+			if (ret < 0 && msg->path.level > 2) {
+				break;
+			}
+
+			/* when reading multiple resources ignore return code */
+			ret = 0;
+		}
+
+move_forward:
+		if (msg->path.level <= 1U) {
+			/* end instance formatting */
+			engine_put_end_oi(&msg->out, &msg->path);
+		}
+
+		if (msg->path.level <= 1U) {
+			/* advance to the next object instance */
+			obj_inst = next_engine_obj_inst(msg->path.obj_id,
+							obj_inst->obj_inst_id);
+		} else {
+			obj_inst = NULL;
+		}
+	}
+
+	engine_put_end(&msg->out, &msg->path);
+
+	/* restore original path values */
+	memcpy(&msg->path, &temp_path, sizeof(temp_path));
+
+	/* did not read anything even if we should have - on single item */
+	if (ret == 0 && num_read == 0U && msg->path.level == 3U) {
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+static int print_attr(struct lwm2m_output_context *out,
+		      uint8_t *buf, uint16_t buflen, void *ref)
+{
+	struct lwm2m_attr *attr;
+	int i, used, base, ret;
+	uint8_t digit;
+	int32_t fraction;
+
+	for (i = 0; i < CONFIG_LWM2M_NUM_ATTR; i++) {
+		if (ref != write_attr_pool[i].ref) {
+			continue;
+		}
+
+		attr = write_attr_pool + i;
+
+		/* assuming integer will have float_val.val2 set as 0 */
+
+		used = snprintk(buf, buflen, ";%s=%s%d%s",
+				LWM2M_ATTR_STR[attr->type],
+				attr->float_val.val1 == 0 &&
+				attr->float_val.val2 < 0 ? "-" : "",
+				attr->float_val.val1,
+				attr->float_val.val2 != 0 ? "." : "");
+
+		base = 100000;
+		fraction = attr->float_val.val2 < 0 ?
+			   -attr->float_val.val2 : attr->float_val.val2;
+		while (fraction && used < buflen && base > 0) {
+			digit = fraction / base;
+			buf[used++] = '0' + digit;
+			fraction -= digit * base;
+			base /= 10;
+		}
+
+		ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, used);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int do_discover_op(struct lwm2m_message *msg, bool well_known)
+{
+	static char disc_buf[24];
+	struct lwm2m_engine_obj *obj;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	int ret;
+	bool reported = false;
+
+	/* object ID is required unless it's bootstrap discover or it's
+	 * a ".well-known/core" discovery
+	 * ref: lwm2m spec 20170208-A table 11
+	 */
+	if (!msg->ctx->bootstrap_mode && !well_known &&
+	    (msg->path.level == 0U ||
+	     (msg->path.level > 0 &&
+	      msg->path.obj_id == LWM2M_OBJECT_SECURITY_ID))) {
+		return -EPERM;
+	}
+
+	/* set output content-format */
+	ret = coap_append_option_int(msg->out.out_cpkt,
+				     COAP_OPTION_CONTENT_FORMAT,
+				     LWM2M_FORMAT_APP_LINK_FORMAT);
+	if (ret < 0) {
+		LOG_ERR("Error setting response content-format: %d", ret);
+		return ret;
+	}
+
+	ret = coap_packet_append_payload_marker(msg->out.out_cpkt);
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* Handle CoAP .well-known/core discover */
+	if (well_known) {
+		/* </.well-known/core> */
+		ret = buf_append(CPKT_BUF_WRITE(msg->out.out_cpkt),
+				 WELL_KNOWN_CORE_PATH,
+				 strlen(WELL_KNOWN_CORE_PATH));
+		if (ret < 0) {
+			return ret;
+		}
+
+		SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_list, obj, node) {
+			snprintk(disc_buf, sizeof(disc_buf), ",</%u>",
+				 obj->obj_id);
+
+			ret = buf_append(CPKT_BUF_WRITE(msg->out.out_cpkt),
+					 disc_buf, strlen(disc_buf));
+			if (ret < 0) {
+				return ret;
+			}
+		}
+
+		return 0;
+	}
+
+	/*
+	 * lwm2m spec 20170208-A sec 5.2.7.3 bootstrap discover on "/"
+	 * - (TODO) prefixed w/ lwm2m enabler version. e.g. lwm2m="1.0"
+	 * - returns object and object instances only
+	 */
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_obj_inst_list, obj_inst, node) {
+		/*
+		 * - Avoid discovery for security object (5.2.7.3) unless
+		 *   Bootstrap discover
+		 * - Skip reporting unrelated object
+		 */
+		if ((!msg->ctx->bootstrap_mode &&
+		     obj_inst->obj->obj_id == LWM2M_OBJECT_SECURITY_ID) ||
+		    obj_inst->obj->obj_id != msg->path.obj_id) {
+			continue;
+		}
+
+		if (msg->path.level == 1U) {
+			snprintk(disc_buf, sizeof(disc_buf), "%s</%u>",
+				 reported ? "," : "",
+				 obj_inst->obj->obj_id);
+
+			ret = buf_append(CPKT_BUF_WRITE(msg->out.out_cpkt),
+					 disc_buf, strlen(disc_buf));
+			if (ret < 0) {
+				return ret;
+			}
+
+			/* report object attrs (5.4.2) */
+			ret = print_attr(&msg->out, disc_buf, sizeof(disc_buf),
+					 obj_inst->obj);
+			if (ret < 0) {
+				return ret;
+			}
+
+			reported = true;
+		}
+
+		/* skip unrelated object instance */
+		if (msg->path.level > 1 &&
+		    msg->path.obj_inst_id != obj_inst->obj_inst_id) {
+			continue;
+		}
+
+		if (msg->path.level == 2U) {
+			snprintk(disc_buf, sizeof(disc_buf), "%s</%u/%u>",
+				 reported ? "," : "",
+				 obj_inst->obj->obj_id, obj_inst->obj_inst_id);
+
+			ret = buf_append(CPKT_BUF_WRITE(msg->out.out_cpkt),
+					 disc_buf, strlen(disc_buf));
+			if (ret < 0) {
+				return ret;
+			}
+
+			/* report object instance attrs (5.4.2) */
+			ret = print_attr(&msg->out, disc_buf, sizeof(disc_buf),
+					 obj_inst);
+			if (ret < 0) {
+				return ret;
+			}
+
+			reported = true;
+		}
+
+		/* don't return resource info for bootstrap discovery */
+		if (msg->ctx->bootstrap_mode) {
+			continue;
+		}
+
+		for (int i = 0; i < obj_inst->resource_count; i++) {
+			/* skip unrelated resources */
+			if (msg->path.level == 3U &&
+			    msg->path.res_id != obj_inst->resources[i].res_id) {
+				continue;
+			}
+
+			snprintk(disc_buf, sizeof(disc_buf),
+				 "%s</%u/%u/%u>",
+				 reported ? "," : "",
+				 obj_inst->obj->obj_id,
+				 obj_inst->obj_inst_id,
+				 obj_inst->resources[i].res_id);
+
+			ret = buf_append(CPKT_BUF_WRITE(msg->out.out_cpkt),
+					 disc_buf, strlen(disc_buf));
+			if (ret < 0) {
+				return ret;
+			}
+
+			/* report resource attrs when path > 1 (5.4.2) */
+			if (msg->path.level > 1) {
+				ret = print_attr(&msg->out,
+						 disc_buf, sizeof(disc_buf),
+						 &obj_inst->resources[i]);
+				if (ret < 0) {
+					return ret;
+				}
+			}
+
+			reported = true;
+		}
+	}
+
+	return reported ? 0 : -ENOENT;
+}
+
+int lwm2m_get_or_create_engine_obj(struct lwm2m_message *msg,
+				   struct lwm2m_engine_obj_inst **obj_inst,
+				   uint8_t *created)
+{
+	int ret = 0;
+
+	if (created) {
+		*created = 0U;
+	}
+
+	*obj_inst = get_engine_obj_inst(msg->path.obj_id,
+					msg->path.obj_inst_id);
+	if (!*obj_inst) {
+		ret = lwm2m_create_obj_inst(msg->path.obj_id,
+					    msg->path.obj_inst_id,
+					    obj_inst);
+		if (ret < 0) {
+			return ret;
+		}
+
+		/* set created flag to one */
+		if (created) {
+			*created = 1U;
+		}
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT)
+		if (!msg->ctx->bootstrap_mode) {
+			engine_trigger_update();
+		}
+#endif
+	}
+
+	return ret;
+}
+
+static int do_write_op(struct lwm2m_message *msg,
+		       uint16_t format)
+{
+	switch (format) {
+
+	case LWM2M_FORMAT_APP_OCTET_STREAM:
+	case LWM2M_FORMAT_PLAIN_TEXT:
+	case LWM2M_FORMAT_OMA_PLAIN_TEXT:
+		return do_write_op_plain_text(msg);
+
+	case LWM2M_FORMAT_OMA_TLV:
+	case LWM2M_FORMAT_OMA_OLD_TLV:
+		return do_write_op_tlv(msg);
+
+#ifdef CONFIG_LWM2M_RW_JSON_SUPPORT
+	case LWM2M_FORMAT_OMA_JSON:
+	case LWM2M_FORMAT_OMA_OLD_JSON:
+		return do_write_op_json(msg);
+#endif
+
+	default:
+		LOG_ERR("Unsupported format: %u", format);
+		return -ENOMSG;
+
+	}
+}
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+static int bootstrap_delete(void)
+{
+	struct lwm2m_engine_obj_inst *obj_inst, *tmp;
+	int ret = 0;
+
+	/* delete SECURITY instances > 0 */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&engine_obj_inst_list,
+					  obj_inst, tmp, node) {
+		if (obj_inst->obj->obj_id == LWM2M_OBJECT_SECURITY_ID &&
+		    obj_inst->obj_inst_id > 0) {
+			ret = lwm2m_delete_obj_inst(obj_inst->obj->obj_id,
+						    obj_inst->obj_inst_id);
+			if (ret < 0) {
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+#endif
+
+static int handle_request(struct coap_packet *request,
+			  struct lwm2m_message *msg)
+{
+	int r;
+	uint8_t code;
+	struct coap_option options[4];
+	struct lwm2m_engine_obj *obj = NULL;
+	uint8_t token[8];
+	uint8_t tkl = 0U;
+	uint16_t format = LWM2M_FORMAT_NONE, accept;
+	int observe = -1; /* default to -1, 0 = ENABLE, 1 = DISABLE */
+	bool well_known = false;
+	int block_opt, block_num;
+	struct lwm2m_block_context *block_ctx = NULL;
+	enum coap_block_size block_size;
+	uint16_t payload_len = 0U;
+	bool last_block = false;
+	bool ignore = false;
+
+	/* set CoAP request / message */
+	msg->in.in_cpkt = request;
+	msg->out.out_cpkt = &msg->cpkt;
+
+	/* set default reader/writer */
+	msg->in.reader = &plain_text_reader;
+	msg->out.writer = &plain_text_writer;
+
+	code = coap_header_get_code(msg->in.in_cpkt);
+
+	/* setup response token */
+	tkl = coap_header_get_token(msg->in.in_cpkt, token);
+	if (tkl) {
+		msg->tkl = tkl;
+		msg->token = token;
+	}
+
+	/* parse the URL path into components */
+	r = coap_find_options(msg->in.in_cpkt, COAP_OPTION_URI_PATH, options,
+			      ARRAY_SIZE(options));
+	if (r <= 0) {
+		switch (code & COAP_REQUEST_MASK) {
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+		case COAP_METHOD_DELETE:
+			if (msg->ctx->bootstrap_mode) {
+				r = bootstrap_delete();
+				if (r < 0) {
+					goto error;
+				}
+
+				msg->code = COAP_RESPONSE_CODE_DELETED;
+				r = lwm2m_init_message(msg);
+			} else {
+				r = -EPERM;
+			}
+
+			if (r < 0) {
+				goto error;
+			}
+
+			return 0;
+#endif
+		default:
+			r = -EPERM;
+			goto error;
+		}
+	}
+
+	/* check for .well-known/core URI query (DISCOVER) */
+	if (r == 2 &&
+	    (options[0].len == 11U &&
+	     strncmp(options[0].value, ".well-known", 11) == 0) &&
+	    (options[1].len == 4U &&
+	     strncmp(options[1].value, "core", 4) == 0)) {
+		if ((code & COAP_REQUEST_MASK) != COAP_METHOD_GET) {
+			r = -EPERM;
+			goto error;
+		}
+
+		well_known = true;
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+	/* check for bootstrap-finish */
+	} else if ((code & COAP_REQUEST_MASK) == COAP_METHOD_POST && r == 1 && \
+		   strncmp(options[0].value, "bs", options[0].len) == 0) {
+		engine_bootstrap_finish();
+
+		msg->code = COAP_RESPONSE_CODE_CHANGED;
+
+		r = lwm2m_init_message(msg);
+		if (r < 0) {
+			goto error;
+		}
+
+		return 0;
+#endif
+	} else {
+		r = coap_options_to_path(options, r, &msg->path);
+		if (r < 0) {
+			r = -ENOENT;
+			goto error;
+		}
+	}
+
+	/* read Content Format / setup in.reader */
+	r = coap_find_options(msg->in.in_cpkt, COAP_OPTION_CONTENT_FORMAT,
+			      options, 1);
+	if (r > 0) {
+		format = coap_option_value_to_int(&options[0]);
+		r = select_reader(&msg->in, format);
+		if (r < 0) {
+			goto error;
+		}
+	}
+
+	/* read Accept / setup out.writer */
+	r = coap_find_options(msg->in.in_cpkt, COAP_OPTION_ACCEPT, options, 1);
+	if (r > 0) {
+		accept = coap_option_value_to_int(&options[0]);
+	} else {
+		LOG_DBG("No accept option given. Assume OMA TLV.");
+		accept = LWM2M_FORMAT_OMA_TLV;
+	}
+
+	r = select_writer(&msg->out, accept);
+	if (r < 0) {
+		goto error;
+	}
+
+	if (!well_known) {
+		/* find registered obj */
+		obj = get_engine_obj(msg->path.obj_id);
+		if (!obj) {
+			/* No matching object found - ignore request */
+			r = -ENOENT;
+			goto error;
+		}
+	}
+
+	/* set the operation */
+	switch (code & COAP_REQUEST_MASK) {
+
+	case COAP_METHOD_GET:
+		/*
+		 * LwM2M V1_0_1-20170704-A, table 25,
+		 * Discover: CoAP GET + accept=LWM2M_FORMAT_APP_LINK_FORMAT
+		 */
+		if (well_known || accept == LWM2M_FORMAT_APP_LINK_FORMAT) {
+			msg->operation = LWM2M_OP_DISCOVER;
+			accept = LWM2M_FORMAT_APP_LINK_FORMAT;
+		} else {
+			msg->operation = LWM2M_OP_READ;
+		}
+
+		/* check for observe */
+		observe = coap_get_option_int(msg->in.in_cpkt,
+					      COAP_OPTION_OBSERVE);
+		msg->code = COAP_RESPONSE_CODE_CONTENT;
+		break;
+
+	case COAP_METHOD_POST:
+		if (msg->path.level == 1U) {
+			/* create an object instance */
+			msg->operation = LWM2M_OP_CREATE;
+			msg->code = COAP_RESPONSE_CODE_CREATED;
+		} else if (msg->path.level == 2U) {
+			/* write values to an object instance */
+			msg->operation = LWM2M_OP_WRITE;
+			msg->code = COAP_RESPONSE_CODE_CHANGED;
+		} else {
+			msg->operation = LWM2M_OP_EXECUTE;
+			msg->code = COAP_RESPONSE_CODE_CHANGED;
+		}
+
+		break;
+
+	case COAP_METHOD_PUT:
+		/* write attributes if content-format is absent */
+		if (format == LWM2M_FORMAT_NONE) {
+			msg->operation = LWM2M_OP_WRITE_ATTR;
+		} else {
+			msg->operation = LWM2M_OP_WRITE;
+		}
+
+		msg->code = COAP_RESPONSE_CODE_CHANGED;
+		break;
+
+	case COAP_METHOD_DELETE:
+		msg->operation = LWM2M_OP_DELETE;
+		msg->code = COAP_RESPONSE_CODE_DELETED;
+		break;
+
+	default:
+		break;
+	}
+
+	/* setup incoming data */
+	msg->in.offset = msg->in.in_cpkt->hdr_len + msg->in.in_cpkt->opt_len;
+	coap_packet_get_payload(msg->in.in_cpkt, &payload_len);
+
+	/* Check for block transfer */
+
+	block_opt = coap_get_option_int(msg->in.in_cpkt, COAP_OPTION_BLOCK1);
+	if (block_opt > 0) {
+		last_block = !GET_MORE(block_opt);
+
+		/* RFC7252: 4.6. Message Size */
+		block_size = GET_BLOCK_SIZE(block_opt);
+		if (!last_block &&
+		    coap_block_size_to_bytes(block_size) > payload_len) {
+			LOG_DBG("Trailing payload is discarded!");
+			r = -EFBIG;
+			goto error;
+		}
+
+		block_num = GET_BLOCK_NUM(block_opt);
+
+		/* Try to retrieve existing block context. If one not exists,
+		 * and we've received first block, allocate new context.
+		 */
+		r = get_block_ctx(token, tkl, &block_ctx);
+		if (r < 0 && block_num == 0) {
+			r = init_block_ctx(token, tkl, &block_ctx);
+		}
+
+		if (r < 0) {
+			LOG_ERR("Cannot find block context");
+			goto error;
+		}
+
+		msg->in.block_ctx = block_ctx;
+
+		if (block_num < block_ctx->expected) {
+			LOG_WRN("Block already handled %d, expected %d",
+				block_num, block_ctx->expected);
+			ignore = true;
+		} else if (block_num > block_ctx->expected) {
+			LOG_WRN("Block out of order %d, expected %d",
+				block_num, block_ctx->expected);
+			r = -EFAULT;
+			goto error;
+		} else {
+			r = coap_update_from_block(msg->in.in_cpkt, &block_ctx->ctx);
+			if (r < 0) {
+				LOG_ERR("Error from block update: %d", r);
+				goto error;
+			}
+
+			block_ctx->last_block = last_block;
+
+			/* Initial block sent by the server might be larger than
+			 * our block size therefore it is needed to take this
+			 * into account when calculating next expected block
+			 * number.
+			 */
+			block_ctx->expected += GET_BLOCK_SIZE(block_opt) -
+					       block_ctx->ctx.block_size + 1;
+		}
+
+		/* Handle blockwise 1 (Part 1): Set response code */
+		if (!last_block) {
+			msg->code = COAP_RESPONSE_CODE_CONTINUE;
+		}
+	}
+
+	/* render CoAP packet header */
+	r = lwm2m_init_message(msg);
+	if (r < 0) {
+		goto error;
+	}
+
+	if (!ignore) {
+
+		switch (msg->operation) {
+
+		case LWM2M_OP_READ:
+			if (observe == 0) {
+				/* add new observer */
+				if (msg->token) {
+					r = coap_append_option_int(
+						msg->out.out_cpkt,
+						COAP_OPTION_OBSERVE,
+						1);
+					if (r < 0) {
+						LOG_ERR("OBSERVE option error: %d", r);
+						goto error;
+					}
+
+					r = engine_add_observer(msg, token, tkl,
+								accept);
+					if (r < 0) {
+						LOG_ERR("add OBSERVE error: %d", r);
+						goto error;
+					}
+				} else {
+					LOG_ERR("OBSERVE request missing token");
+					r = -EINVAL;
+					goto error;
+				}
+			} else if (observe == 1) {
+				/* remove observer */
+				r = engine_remove_observer(token, tkl);
+				if (r < 0) {
+					LOG_ERR("remove observe error: %d", r);
+				}
+			}
+
+			r = do_read_op(msg, accept);
+			break;
+
+		case LWM2M_OP_DISCOVER:
+			r = do_discover_op(msg, well_known);
+			break;
+
+		case LWM2M_OP_WRITE:
+		case LWM2M_OP_CREATE:
+			r = do_write_op(msg, format);
+			break;
+
+		case LWM2M_OP_WRITE_ATTR:
+			r = lwm2m_write_attr_handler(obj, msg);
+			break;
+
+		case LWM2M_OP_EXECUTE:
+			r = lwm2m_exec_handler(msg);
+			break;
+
+		case LWM2M_OP_DELETE:
+			r = lwm2m_delete_handler(msg);
+			break;
+
+		default:
+			LOG_ERR("Unknown operation: %u", msg->operation);
+			r = -EINVAL;
+		}
+
+		if (r < 0) {
+			goto error;
+		}
+	}
+
+	/* Handle blockwise 1 (Part 2): Append BLOCK1 option / free context */
+	if (block_ctx) {
+		if (!last_block) {
+			/* More to come, ack with correspond block # */
+			r = coap_append_block1_option(msg->out.out_cpkt,
+						      &block_ctx->ctx);
+			if (r < 0) {
+				/* report as internal server error */
+				LOG_ERR("Fail adding block1 option: %d", r);
+				r = -EINVAL;
+				goto error;
+			}
+		} else {
+			/* Free context when finished */
+			free_block_ctx(block_ctx);
+		}
+	}
+
+	return 0;
+
+error:
+	lwm2m_reset_message(msg, false);
+	if (r == -ENOENT) {
+		msg->code = COAP_RESPONSE_CODE_NOT_FOUND;
+	} else if (r == -EPERM) {
+		msg->code = COAP_RESPONSE_CODE_NOT_ALLOWED;
+	} else if (r == -EEXIST) {
+		msg->code = COAP_RESPONSE_CODE_BAD_REQUEST;
+	} else if (r == -EFAULT) {
+		msg->code = COAP_RESPONSE_CODE_INCOMPLETE;
+	} else if (r == -EFBIG) {
+		msg->code = COAP_RESPONSE_CODE_REQUEST_TOO_LARGE;
+	} else if (r == -ENOTSUP) {
+		msg->code = COAP_RESPONSE_CODE_NOT_IMPLEMENTED;
+	} else if (r == -ENOMSG) {
+		msg->code = COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT;
+	} else {
+		/* Failed to handle the request */
+		msg->code = COAP_RESPONSE_CODE_INTERNAL_ERROR;
+	}
+
+	r = lwm2m_init_message(msg);
+	if (r < 0) {
+		LOG_ERR("Error recreating message: %d", r);
+	}
+
+	/* Free block context when error happened */
+	free_block_ctx(block_ctx);
+
+	return 0;
+}
+
+static void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx,
+			      uint8_t *buf, uint16_t buf_len,
+			      struct sockaddr *from_addr,
+			      udp_request_handler_cb_t udp_request_handler)
+{
+	struct lwm2m_message *msg = NULL;
+	struct coap_pending *pending;
+	struct coap_reply *reply;
+	struct coap_packet response;
+	int r;
+	uint8_t token[8];
+	uint8_t tkl;
+
+	r = coap_packet_parse(&response, buf, buf_len, NULL, 0);
+	if (r < 0) {
+		LOG_ERR("Invalid data received (err:%d)", r);
+		return;
+	}
+
+	tkl = coap_header_get_token(&response, token);
+	pending = coap_pending_received(&response, client_ctx->pendings,
+					CONFIG_LWM2M_ENGINE_MAX_PENDING);
+	/*
+	 * Clear pending pointer because coap_pending_received() calls
+	 * coap_pending_clear, and later when we call lwm2m_reset_message()
+	 * it will try and call coap_pending_clear() again if msg->pending
+	 * is != NULL.
+	 */
+	if (pending) {
+		msg = find_msg(pending, NULL);
+	}
+
+	LOG_DBG("checking for reply from [%s]",
+		log_strdup(lwm2m_sprint_ip_addr(from_addr)));
+	reply = coap_response_received(&response, from_addr,
+				       client_ctx->replies,
+				       CONFIG_LWM2M_ENGINE_MAX_REPLIES);
+	if (reply) {
+		/*
+		 * Separate response is composed of 2 messages, empty ACK with
+		 * no token and an additional message with a matching token id
+		 * (based on the token used by the CON request).
+		 *
+		 * Since the ACK received by the notify CON messages are also
+		 * empty with no token (consequence of always using the same
+		 * token id for all notifications), we have to use an
+		 * additional flag to decide when to clear the reply callback.
+		 */
+		if (client_ctx->handle_separate_response && !tkl &&
+			coap_header_get_type(&response) == COAP_TYPE_ACK) {
+			LOG_DBG("separated response, not removing reply");
+			return;
+		}
+
+		if (!msg) {
+			msg = find_msg(pending, reply);
+		}
+	}
+
+	if (reply || pending) {
+		/* skip release if reply->user_data has error condition */
+		if (reply && reply->user_data != COAP_REPLY_STATUS_NONE) {
+			/* reset reply->user_data for next time */
+			reply->user_data = (void *)COAP_REPLY_STATUS_NONE;
+			LOG_DBG("reply %p NOT removed", reply);
+			return;
+		}
+
+		/* free up msg resources */
+		if (msg) {
+			lwm2m_reset_message(msg, true);
+		}
+
+		LOG_DBG("reply %p handled and removed", reply);
+		return;
+	}
+
+	/*
+	 * If no normal response handler is found, then this is
+	 * a new request coming from the server.  Let's look
+	 * at registered objects to find a handler.
+	 */
+	if (udp_request_handler &&
+	    coap_header_get_type(&response) == COAP_TYPE_CON) {
+		msg = lwm2m_get_message(client_ctx);
+		if (!msg) {
+			LOG_ERR("Unable to get a lwm2m message!");
+			return;
+		}
+
+		/* Create a response message if we reach this point */
+		msg->type = COAP_TYPE_ACK;
+		msg->code = coap_header_get_code(&response);
+		msg->mid = coap_header_get_id(&response);
+		/* skip token generation by default */
+		msg->tkl = 0;
+
+		/* process the response to this request */
+		r = udp_request_handler(&response, msg);
+		if (r < 0) {
+			return;
+		}
+
+		r = lwm2m_send_message(msg);
+		if (r < 0) {
+			LOG_ERR("Err sending response: %d", r);
+			lwm2m_reset_message(msg, true);
+		}
+	} else {
+		LOG_DBG("No handler for response");
+	}
+}
+
+static void retransmit_request(struct k_work *work)
+{
+	struct lwm2m_ctx *client_ctx;
+	struct lwm2m_message *msg;
+	struct coap_pending *pending;
+	int32_t remaining;
+	int ret;
+
+	client_ctx = CONTAINER_OF(work, struct lwm2m_ctx, retransmit_work);
+	pending = coap_pending_next_to_expire(client_ctx->pendings,
+					      CONFIG_LWM2M_ENGINE_MAX_PENDING);
+	if (!pending) {
+		return;
+	}
+
+	remaining = pending->t0 + pending->timeout - k_uptime_get_32();
+	if (remaining > 0) {
+		/* First message to expire was removed from the list,
+		 * schedule next.
+		 */
+		goto next;
+	}
+
+	msg = find_msg(pending, NULL);
+	if (!msg) {
+		LOG_ERR("pending has no valid LwM2M message!");
+		coap_pending_clear(pending);
+		goto next;
+	}
+
+	if (!coap_pending_cycle(pending)) {
+		/* pending request has expired */
+		if (msg->message_timeout_cb) {
+			msg->message_timeout_cb(msg);
+		}
+
+		/*
+		 * coap_pending_clear() is called in lwm2m_reset_message()
+		 * which balances the ref we made in coap_pending_cycle()
+		 */
+		lwm2m_reset_message(msg, true);
+		goto next;
+	}
+
+	LOG_INF("Resending message: %p", msg);
+	msg->send_attempts++;
+
+	ret = sys_mutex_lock(&client_ctx->send_lock, K_FOREVER);
+	__ASSERT(ret == 0, "sys_mutex_lock failed with %d", ret);
+
+	if (msg->ctx == NULL) {
+		LOG_INF("Response for %p already handled", msg);
+		goto next_locked;
+	}
+
+	if (send(msg->ctx->sock_fd, msg->cpkt.data, msg->cpkt.offset, 0) < 0) {
+		LOG_ERR("Error sending lwm2m message: %d", -errno);
+		/* don't error here, retry until timeout */
+	}
+
+next_locked:
+	ret = sys_mutex_unlock(&client_ctx->send_lock);
+	__ASSERT(ret == 0, "sys_mutex_unlock failed with %d", ret);
+	ARG_UNUSED(ret);
+
+next:
+	pending = coap_pending_next_to_expire(client_ctx->pendings,
+					      CONFIG_LWM2M_ENGINE_MAX_PENDING);
+	if (!pending) {
+		return;
+	}
+
+	remaining = pending->t0 + pending->timeout - k_uptime_get_32();
+	if (remaining < 0) {
+		remaining = 0;
+	}
+
+	k_delayed_work_submit(&client_ctx->retransmit_work, K_MSEC(remaining));
+}
+
+static int notify_message_reply_cb(const struct coap_packet *response,
+				   struct coap_reply *reply,
+				   const struct sockaddr *from)
+{
+	int ret = 0;
+	uint8_t type, code;
+
+	type = coap_header_get_type(response);
+	code = coap_header_get_code(response);
+
+	LOG_DBG("NOTIFY ACK type:%u code:%d.%d reply_token:'%s'",
+		type,
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code),
+		log_strdup(sprint_token(reply->token, reply->tkl)));
+
+	/* remove observer on COAP_TYPE_RESET */
+	if (type == COAP_TYPE_RESET) {
+		if (reply->tkl > 0) {
+			ret = engine_remove_observer(reply->token, reply->tkl);
+			if (ret) {
+				LOG_ERR("remove observe error: %d", ret);
+			}
+		} else {
+			LOG_ERR("notify reply missing token -- ignored.");
+		}
+	}
+
+	return 0;
+}
+
+static int generate_notify_message(struct observe_node *obs,
+				   bool manual_trigger)
+{
+	struct lwm2m_message *msg;
+	struct lwm2m_engine_obj_inst *obj_inst;
+	int ret = 0;
+
+	if (!obs->ctx) {
+		LOG_ERR("observer has no valid LwM2M ctx!");
+		return -EINVAL;
+	}
+
+	msg = lwm2m_get_message(obs->ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		return -ENOMEM;
+	}
+
+	/* copy path */
+	memcpy(&msg->path, &obs->path, sizeof(struct lwm2m_obj_path));
+	msg->operation = LWM2M_OP_READ;
+
+	LOG_DBG("[%s] NOTIFY MSG START: %u/%u/%u(%u) token:'%s' [%s] %lld",
+		manual_trigger ? "MANUAL" : "AUTO",
+		obs->path.obj_id,
+		obs->path.obj_inst_id,
+		obs->path.res_id,
+		obs->path.level,
+		log_strdup(sprint_token(obs->token, obs->tkl)),
+		log_strdup(lwm2m_sprint_ip_addr(&obs->ctx->remote_addr)),
+		k_uptime_get());
+
+	obj_inst = get_engine_obj_inst(obs->path.obj_id,
+				       obs->path.obj_inst_id);
+	if (!obj_inst) {
+		LOG_ERR("unable to get engine obj for %u/%u",
+			obs->path.obj_id,
+			obs->path.obj_inst_id);
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	msg->type = COAP_TYPE_CON;
+	msg->code = COAP_RESPONSE_CODE_CONTENT;
+	msg->mid = coap_next_id();
+	msg->token = obs->token;
+	msg->tkl = obs->tkl;
+	msg->reply_cb = notify_message_reply_cb;
+	msg->out.out_cpkt = &msg->cpkt;
+
+	ret = lwm2m_init_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Unable to init lwm2m message! (err: %d)", ret);
+		goto cleanup;
+	}
+
+	/* each notification should increment the obs counter */
+	obs->counter++;
+	ret = coap_append_option_int(&msg->cpkt, COAP_OPTION_OBSERVE,
+				     obs->counter);
+	if (ret < 0) {
+		LOG_ERR("OBSERVE option error: %d", ret);
+		goto cleanup;
+	}
+
+	/* set the output writer */
+	select_writer(&msg->out, obs->format);
+
+	ret = do_read_op(msg, obs->format);
+	if (ret < 0) {
+		LOG_ERR("error in multi-format read (err:%d)", ret);
+		goto cleanup;
+	}
+
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
+		goto cleanup;
+	}
+
+	LOG_DBG("NOTIFY MSG: SENT");
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+	return ret;
+}
+
+int32_t engine_next_service_timeout_ms(uint32_t max_timeout)
+{
+	struct service_node *srv;
+	uint64_t time_left_ms, timestamp = k_uptime_get();
+	uint32_t timeout = max_timeout;
+
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_service_list, srv, node) {
+		time_left_ms = srv->last_timestamp + srv->min_call_period;
+
+		/* service is due */
+		if (time_left_ms < timestamp) {
+			return 0;
+		}
+
+		/* service timeout is less than the current timeout */
+		time_left_ms -= timestamp;
+		if (time_left_ms < timeout) {
+			timeout = time_left_ms;
+		}
+	}
+
+	return timeout;
+}
+
+int lwm2m_engine_add_service(k_work_handler_t service, uint32_t period_ms)
+{
+	int i;
+
+	/* find an unused service index node */
+	for (i = 0; i < MAX_PERIODIC_SERVICE; i++) {
+		if (!service_node_data[i].service_work) {
+			break;
+		}
+	}
+
+	if (i == MAX_PERIODIC_SERVICE) {
+		return -ENOMEM;
+	}
+
+	service_node_data[i].service_work = service;
+	service_node_data[i].min_call_period = period_ms;
+	service_node_data[i].last_timestamp = 0U;
+
+	sys_slist_append(&engine_service_list,
+			 &service_node_data[i].node);
+
+	return 0;
+}
+
+static int lwm2m_engine_service(void)
+{
+	struct observe_node *obs;
+	struct service_node *srv;
+	int64_t timestamp, service_due_timestamp;
+
+	/*
+	 * 1. scan the observer list
+	 * 2. For each notify event found, scan the observer list
+	 * 3. For each observer match, generate a NOTIFY message,
+	 *    attaching the notify response handler
+	 */
+	timestamp = k_uptime_get();
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_observer_list, obs, node) {
+		/*
+		 * manual notify requirements:
+		 * - event_timestamp > last_timestamp
+		 * - current timestamp > last_timestamp + min_period_sec
+		 */
+		if (obs->event_timestamp > obs->last_timestamp &&
+		    timestamp > obs->last_timestamp +
+				MSEC_PER_SEC * obs->min_period_sec) {
+			obs->last_timestamp = k_uptime_get();
+			generate_notify_message(obs, true);
+
+		/*
+		 * automatic time-based notify requirements:
+		 * - current timestamp > last_timestamp + max_period_sec
+		 */
+		} else if (timestamp > obs->last_timestamp +
+				MSEC_PER_SEC * obs->max_period_sec) {
+			obs->last_timestamp = k_uptime_get();
+			generate_notify_message(obs, false);
+		}
+
+	}
+
+	timestamp = k_uptime_get();
+	SYS_SLIST_FOR_EACH_CONTAINER(&engine_service_list, srv, node) {
+		service_due_timestamp = srv->last_timestamp +
+					srv->min_call_period;
+		/* service is due */
+		if (timestamp >= service_due_timestamp) {
+			srv->last_timestamp = k_uptime_get();
+			srv->service_work(NULL);
+		}
+	}
+
+	/* calculate how long to sleep till the next service */
+	return engine_next_service_timeout_ms(ENGINE_UPDATE_INTERVAL_MS);
+}
+
+int lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx)
+{
+	struct observe_node *obs, *tmp;
+	sys_snode_t *prev_node = NULL;
+	int sock_fd = client_ctx->sock_fd;
+	struct lwm2m_message *msg;
+	size_t i;
+
+	/* Cancel pending retransmit work */
+	k_delayed_work_cancel(&client_ctx->retransmit_work);
+
+	/* Remove observes for this context */
+	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&engine_observer_list,
+					  obs, tmp, node) {
+		if (obs->ctx == client_ctx) {
+			sys_slist_remove(&engine_observer_list, prev_node,
+					 &obs->node);
+			(void)memset(obs, 0, sizeof(*obs));
+		} else {
+			prev_node = &obs->node;
+		}
+	}
+
+	for (i = 0, msg = messages; i < ARRAY_SIZE(messages); i++, msg++) {
+		if (msg->ctx == client_ctx) {
+			lwm2m_reset_message(msg, true);
+		}
+	}
+
+	coap_pendings_clear(client_ctx->pendings,
+			    CONFIG_LWM2M_ENGINE_MAX_PENDING);
+	coap_replies_clear(client_ctx->replies,
+			   CONFIG_LWM2M_ENGINE_MAX_REPLIES);
+
+	lwm2m_socket_del(client_ctx);
+	client_ctx->sock_fd = -1;
+	if (sock_fd >= 0) {
+		return close(sock_fd);
+	} else {
+		return 0;
+	}
+}
+
+void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx)
+{
+	k_delayed_work_init(&client_ctx->retransmit_work, retransmit_request);
+	sys_mutex_init(&client_ctx->send_lock);
+}
+
+/* LwM2M Socket Integration */
+
+int lwm2m_socket_add(struct lwm2m_ctx *ctx)
+{
+	if (sock_nfds >= MAX_POLL_FD) {
+		return -ENOMEM;
+	}
+
+	sock_ctx[sock_nfds] = ctx;
+	sock_fds[sock_nfds].fd = ctx->sock_fd;
+	sock_fds[sock_nfds].events = POLLIN;
+	sock_nfds++;
+
+	return 0;
+}
+
+void lwm2m_socket_del(struct lwm2m_ctx *ctx)
+{
+	for (int i = 0; i < sock_nfds; i++) {
+		if (sock_ctx[i] != ctx) {
+			continue;
+		}
+
+		sock_nfds--;
+
+		/* If not last, overwrite the entry with the last one. */
+		if (i < sock_nfds) {
+			sock_ctx[i] = sock_ctx[sock_nfds];
+			sock_fds[i].fd = sock_fds[sock_nfds].fd;
+			sock_fds[i].events = sock_fds[sock_nfds].events;
+		}
+
+		/* Remove the last entry. */
+		sock_ctx[sock_nfds] = NULL;
+		sock_fds[sock_nfds].fd = -1;
+		break;
+	}
+}
+
+/* LwM2M main work loop */
+
+static void socket_receive_loop(void)
+{
+	static uint8_t in_buf[NET_IPV6_MTU];
+	static struct sockaddr from_addr;
+	socklen_t from_addr_len;
+	ssize_t len;
+	int i;
+
+	while (1) {
+		/* wait for sockets */
+		if (sock_nfds < 1) {
+			k_msleep(lwm2m_engine_service());
+			continue;
+		}
+
+		/*
+		 * FIXME: Currently we timeout and restart poll in case fds
+		 *        were modified.
+		 */
+		if (poll(sock_fds, sock_nfds, lwm2m_engine_service()) < 0) {
+			LOG_ERR("Error in poll:%d", errno);
+			errno = 0;
+			k_msleep(ENGINE_UPDATE_INTERVAL_MS);
+			continue;
+		}
+
+		for (i = 0; i < sock_nfds; i++) {
+			if ((sock_fds[i].revents & POLLERR) ||
+			    (sock_fds[i].revents & POLLNVAL) ||
+			    (sock_fds[i].revents & POLLHUP)) {
+				LOG_ERR("Poll reported a socket error, %02x.",
+					sock_fds[i].revents);
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT)
+				engine_trigger_restart();
+#endif
+				continue;
+			}
+
+			if (!(sock_fds[i].revents & POLLIN) ||
+			    sock_ctx[i] == NULL) {
+				sock_fds[i].revents = 0;
+				continue;
+			}
+
+			from_addr_len = sizeof(from_addr);
+			sock_fds[i].revents = 0;
+			len = recvfrom(sock_ctx[i]->sock_fd, in_buf,
+				       sizeof(in_buf) - 1, 0,
+				       &from_addr, &from_addr_len);
+
+			if (len < 0) {
+				LOG_ERR("Error reading response: %d", errno);
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT)
+				engine_trigger_restart();
+#endif
+				continue;
+			}
+
+			if (len == 0) {
+				LOG_ERR("Zero length recv");
+				continue;
+			}
+
+			in_buf[len] = 0U;
+
+			lwm2m_udp_receive(sock_ctx[i], in_buf, len, &from_addr,
+					  handle_request);
+		}
+	}
+}
+
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+static int load_tls_credential(struct lwm2m_ctx *client_ctx, uint16_t res_id,
+			       enum tls_credential_type type)
+{
+	int ret = 0;
+	void *cred = NULL;
+	uint16_t cred_len;
+	uint8_t cred_flags;
+	char pathstr[MAX_RESOURCE_LEN];
+
+	/* ignore error value */
+	tls_credential_delete(client_ctx->tls_tag, type);
+
+	snprintk(pathstr, sizeof(pathstr), "0/%d/%u", client_ctx->sec_obj_inst,
+		 res_id);
+
+	ret = lwm2m_engine_get_res_data(pathstr, &cred, &cred_len, &cred_flags);
+	if (ret < 0) {
+		LOG_ERR("Unable to get resource data for '%s'",
+			log_strdup(pathstr));
+		return ret;
+	}
+
+	ret = tls_credential_add(client_ctx->tls_tag, type, cred, cred_len);
+	if (ret < 0) {
+		LOG_ERR("Error setting cred tag %d type %d: Error %d",
+			client_ctx->tls_tag, type, ret);
+	}
+
+	return ret;
+}
+#endif /* CONFIG_LWM2M_DTLS_SUPPORT */
+
+int lwm2m_socket_start(struct lwm2m_ctx *client_ctx)
+{
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+	int ret;
+
+	if (client_ctx->load_credentials) {
+		ret = client_ctx->load_credentials(client_ctx);
+		if (ret < 0) {
+			return ret;
+		}
+	} else {
+		ret = load_tls_credential(client_ctx, 3, TLS_CREDENTIAL_PSK_ID);
+		if (ret < 0) {
+			return ret;
+		}
+
+		ret = load_tls_credential(client_ctx, 5, TLS_CREDENTIAL_PSK);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	if (client_ctx->use_dtls) {
+		client_ctx->sock_fd = socket(client_ctx->remote_addr.sa_family,
+					     SOCK_DGRAM, IPPROTO_DTLS_1_2);
+	} else
+#endif /* CONFIG_LWM2M_DTLS_SUPPORT */
+	{
+		client_ctx->sock_fd = socket(client_ctx->remote_addr.sa_family,
+					     SOCK_DGRAM, IPPROTO_UDP);
+	}
+
+	if (client_ctx->sock_fd < 0) {
+		LOG_ERR("Failed to create socket: %d", errno);
+		return -errno;
+	}
+
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+	if (client_ctx->use_dtls) {
+		sec_tag_t tls_tag_list[] = {
+			client_ctx->tls_tag,
+		};
+
+		ret = setsockopt(client_ctx->sock_fd, SOL_TLS, TLS_SEC_TAG_LIST,
+				 tls_tag_list, sizeof(tls_tag_list));
+		if (ret < 0) {
+			LOG_ERR("Failed to set TLS_SEC_TAG_LIST option: %d",
+				errno);
+			lwm2m_engine_context_close(client_ctx);
+			return -errno;
+		}
+	}
+#endif /* CONFIG_LWM2M_DTLS_SUPPORT */
+
+	if (connect(client_ctx->sock_fd, &client_ctx->remote_addr,
+		    NET_SOCKADDR_MAX_SIZE) < 0) {
+		LOG_ERR("Cannot connect UDP (-%d)", errno);
+		lwm2m_engine_context_close(client_ctx);
+		return -errno;
+	}
+
+	lwm2m_socket_add(client_ctx);
+	return 0;
+}
+
+int lwm2m_parse_peerinfo(char *url, struct sockaddr *addr, bool *use_dtls)
+{
+	struct http_parser_url parser;
+#if defined(CONFIG_LWM2M_DNS_SUPPORT)
+	struct addrinfo *res, hints = { 0 };
+#endif
+	int ret;
+	uint16_t off, len;
+	uint8_t tmp;
+
+	LOG_DBG("Parse url: %s", log_strdup(url));
+
+	http_parser_url_init(&parser);
+	ret = http_parser_parse_url(url, strlen(url), 0, &parser);
+	if (ret < 0) {
+		LOG_ERR("Invalid url: %s", log_strdup(url));
+		return -ENOTSUP;
+	}
+
+	off = parser.field_data[UF_SCHEMA].off;
+	len = parser.field_data[UF_SCHEMA].len;
+
+	/* check for supported protocol */
+	if (strncmp(url + off, "coaps", len) != 0) {
+		return -EPROTONOSUPPORT;
+	}
+
+	/* check for DTLS requirement */
+	*use_dtls = false;
+	if (len == 5U && strncmp(url + off, "coaps", len) == 0) {
+#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
+		*use_dtls = true;
+#else
+		return -EPROTONOSUPPORT;
+#endif /* CONFIG_LWM2M_DTLS_SUPPORT */
+	}
+
+	if (!(parser.field_set & (1 << UF_PORT))) {
+		/* Set to default port of CoAP */
+		parser.port = CONFIG_LWM2M_PEER_PORT;
+	}
+
+	off = parser.field_data[UF_HOST].off;
+	len = parser.field_data[UF_HOST].len;
+
+	/* truncate host portion */
+	tmp = url[off + len];
+	url[off + len] = '\0';
+
+	/* initialize addr */
+	(void)memset(addr, 0, sizeof(*addr));
+
+	/* try and set IP address directly */
+	addr->sa_family = AF_INET6;
+	ret = net_addr_pton(AF_INET6, url + off,
+			    &((struct sockaddr_in6 *)addr)->sin6_addr);
+	/* Try to parse again using AF_INET */
+	if (ret < 0) {
+		addr->sa_family = AF_INET;
+		ret = net_addr_pton(AF_INET, url + off,
+				    &((struct sockaddr_in *)addr)->sin_addr);
+	}
+
+	if (ret < 0) {
+#if defined(CONFIG_LWM2M_DNS_SUPPORT)
+#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
+		hints.ai_family = AF_UNSPEC;
+#elif defined(CONFIG_NET_IPV6)
+		hints.ai_family = AF_INET6;
+#elif defined(CONFIG_NET_IPV4)
+		hints.ai_family = AF_INET;
+#else
+		hints.ai_family = AF_UNSPEC;
+#endif /* defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4) */
+		hints.ai_socktype = SOCK_DGRAM;
+		ret = getaddrinfo(url + off, NULL, &hints, &res);
+		if (ret != 0) {
+			LOG_ERR("Unable to resolve address");
+			/* DNS error codes don't align with normal errors */
+			ret = -ENOENT;
+			goto cleanup;
+		}
+
+		memcpy(addr, res->ai_addr, sizeof(*addr));
+		addr->sa_family = res->ai_family;
+		freeaddrinfo(res);
+#else
+		goto cleanup;
+#endif /* CONFIG_LWM2M_DNS_SUPPORT */
+	}
+
+	/* set port */
+	if (addr->sa_family == AF_INET6) {
+		net_sin6(addr)->sin6_port = htons(parser.port);
+	} else if (addr->sa_family == AF_INET) {
+		net_sin(addr)->sin_port = htons(parser.port);
+	} else {
+		ret = -EPROTONOSUPPORT;
+	}
+
+cleanup:
+	/* restore host separator */
+	url[off + len] = tmp;
+	return ret;
+}
+
+int lwm2m_engine_start(struct lwm2m_ctx *client_ctx)
+{
+	char pathstr[MAX_RESOURCE_LEN];
+	char *url;
+	uint16_t url_len;
+	uint8_t url_data_flags;
+	int ret = 0U;
+
+	/* get the server URL */
+	snprintk(pathstr, sizeof(pathstr), "0/%d/0", client_ctx->sec_obj_inst);
+	ret = lwm2m_engine_get_res_data(pathstr, (void **)&url, &url_len,
+					&url_data_flags);
+	if (ret < 0) {
+		return ret;
+	}
+
+	url[url_len] = '\0';
+	ret = lwm2m_parse_peerinfo(url, &client_ctx->remote_addr,
+				   &client_ctx->use_dtls);
+	if (ret < 0) {
+		return ret;
+	}
+
+	lwm2m_engine_context_init(client_ctx);
+	return lwm2m_socket_start(client_ctx);
+}
+
+static int lwm2m_engine_init(const struct device *dev)
+{
+	int ret = 0;
+
+	(void)memset(block1_contexts, 0, sizeof(block1_contexts));
+
+	/* start sock receive thread */
+	k_thread_create(&engine_thread_data,
+			&engine_thread_stack[0],
+			K_KERNEL_STACK_SIZEOF(engine_thread_stack),
+			(k_thread_entry_t) socket_receive_loop,
+			NULL, NULL, NULL,
+			/* Lowest priority cooperative thread */
+			K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1),
+			0, K_NO_WAIT);
+	k_thread_name_set(&engine_thread_data, "lwm2m-sock-recv");
+	LOG_DBG("LWM2M engine socket receive thread started");
+
+	return ret;
+}
+
+SYS_INIT(lwm2m_engine_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_connmon.c	(working copy)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_conn_mon
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <string.h>
+#include <init.h>
+#include <net/net_if.h>
+#include <net/net_ip.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Connectivity Monitoring resource IDs */
+#define CONNMON_NETWORK_BEARER_ID		0
+#define CONNMON_AVAIL_NETWORK_BEARER_ID		1
+#define CONNMON_RADIO_SIGNAL_STRENGTH		2
+#define CONNMON_LINK_QUALITY			3
+#define CONNMON_IP_ADDRESSES			4
+#define CONNMON_ROUTER_IP_ADDRESSES		5
+#define CONNMON_LINK_UTILIZATION		6
+#define CONNMON_APN				7
+#define CONNMON_CELLID				8
+#define CONNMON_SMNC				9
+#define CONNMON_SMCC				10
+
+#define CONNMON_MAX_ID				11
+
+#define CONNMON_STRING_SHORT			8
+
+#define CONNMON_AVAIL_BEARER_MAX	CONFIG_LWM2M_CONN_MON_BEARER_MAX
+#define CONNMON_APN_MAX			CONFIG_LWM2M_CONN_MON_APN_MAX
+
+#if defined(CONFIG_NET_IF_MAX_IPV6_COUNT) \
+	&& defined(CONFIG_NET_IF_MAX_IPV4_COUNT)
+#define CONNMON_IP_ADDRESS_MAX		(CONFIG_NET_IF_MAX_IPV6_COUNT + \
+					CONFIG_NET_IF_MAX_IPV4_COUNT)
+#elif defined(CONFIG_NET_IF_MAX_IPV6_COUNT)
+#define CONNMON_IP_ADDRESS_MAX		CONFIG_NET_IF_MAX_IPV6_COUNT
+#elif defined(CONFIG_NET_IF_MAX_IPV4_COUNT)
+#define CONNMON_IP_ADDRESS_MAX		CONFIG_NET_IF_MAX_IPV4_COUNT
+#else
+#define CONNMON_IP_ADDRESS_MAX		1
+#endif
+
+#if defined(CONFIG_NET_MAX_ROUTERS)
+#define CONNMON_ROUTER_IP_ADDRESS_MAX	CONFIG_NET_MAX_ROUTERS
+#else
+#define CONNMON_ROUTER_IP_ADDRESS_MAX	1
+#endif
+
+/*
+ * Calculate resource instances as follows:
+ * start with CONNMON_MAX_ID
+ * subtract MULTI resources because their counts include 0 resource (4)
+ * add CONNMON_AVAIL_BEARER_MAX resource instances
+ * add CONNMON_APN_MAX resource instances
+ * add CONNMON_IP_ADDRESS_MAX resource instances
+ * add CONNMON_ROUTER_IP_ADDRESS_MAX resource instances
+ */
+#define RESOURCE_INSTANCE_COUNT        (CONNMON_MAX_ID - 4 + \
+					CONNMON_AVAIL_BEARER_MAX + \
+					CONNMON_APN_MAX + \
+					CONNMON_IP_ADDRESS_MAX + \
+					CONNMON_ROUTER_IP_ADDRESS_MAX)
+
+/* resource state variables */
+static int8_t net_bearer;
+static int8_t rss;
+static uint8_t link_quality;
+static uint32_t cellid;
+static uint16_t mnc;
+static uint16_t mcc;
+
+/* only 1 instance of Connection Monitoring object exists */
+static struct lwm2m_engine_obj connmon;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(CONNMON_NETWORK_BEARER_ID, R, U8),
+	OBJ_FIELD_DATA(CONNMON_AVAIL_NETWORK_BEARER_ID, R, U8),
+	OBJ_FIELD_DATA(CONNMON_RADIO_SIGNAL_STRENGTH, R, S8),
+	OBJ_FIELD_DATA(CONNMON_LINK_QUALITY, R, U8),
+	OBJ_FIELD_DATA(CONNMON_IP_ADDRESSES, R, STRING),
+	OBJ_FIELD_DATA(CONNMON_ROUTER_IP_ADDRESSES, R_OPT, STRING),
+	OBJ_FIELD_DATA(CONNMON_LINK_UTILIZATION, R_OPT, U8),
+	OBJ_FIELD_DATA(CONNMON_APN, R_OPT, STRING),
+	OBJ_FIELD_DATA(CONNMON_CELLID, R_OPT, U32),
+	OBJ_FIELD_DATA(CONNMON_SMNC, R_OPT, U16),
+	OBJ_FIELD_DATA(CONNMON_SMCC, R_OPT, U16)
+};
+
+static struct lwm2m_engine_obj_inst inst;
+static struct lwm2m_engine_res res[CONNMON_MAX_ID];
+static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj_inst *connmon_create(uint16_t obj_inst_id)
+{
+	int i = 0, j = 0;
+
+	/* Set default values */
+	net_bearer = 42U; /* Ethernet */
+	rss = 0;
+	link_quality = 0U;
+	mnc = 0U;
+	mcc = 0U;
+
+	init_res_instance(res_inst, ARRAY_SIZE(res_inst));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(CONNMON_NETWORK_BEARER_ID, res, i, res_inst, j,
+			  &net_bearer, sizeof(net_bearer));
+	INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_AVAIL_NETWORK_BEARER_ID, res, i,
+				   res_inst, j, CONNMON_AVAIL_BEARER_MAX,
+				   false);
+	INIT_OBJ_RES_DATA(CONNMON_RADIO_SIGNAL_STRENGTH, res, i, res_inst, j,
+			  &rss, sizeof(rss));
+	INIT_OBJ_RES_DATA(CONNMON_LINK_QUALITY, res, i, res_inst, j,
+			  &link_quality, sizeof(link_quality));
+	INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_IP_ADDRESSES, res, i,
+				   res_inst, j, CONNMON_IP_ADDRESS_MAX, false);
+	INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_ROUTER_IP_ADDRESSES, res, i,
+				   res_inst, j, CONNMON_ROUTER_IP_ADDRESS_MAX,
+				   false);
+	INIT_OBJ_RES_MULTI_OPTDATA(CONNMON_APN, res, i, res_inst, j,
+				   CONNMON_APN_MAX, false);
+	INIT_OBJ_RES_DATA(CONNMON_CELLID, res, i, res_inst, j, &cellid,
+			  sizeof(cellid));
+	INIT_OBJ_RES_DATA(CONNMON_SMNC, res, i, res_inst, j, &mnc, sizeof(mnc));
+	INIT_OBJ_RES_DATA(CONNMON_SMCC, res, i, res_inst, j, &mcc, sizeof(mcc));
+
+	inst.resources = res;
+	inst.resource_count = i;
+	LOG_DBG("Create LWM2M connectivity monitoring instance: %d",
+		obj_inst_id);
+	return &inst;
+}
+
+static int lwm2m_connmon_init(const struct device *dev)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	int ret = 0;
+
+	/* initialize the Connection Monitoring field data */
+	connmon.obj_id = LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID;
+	connmon.fields = fields;
+	connmon.field_count = ARRAY_SIZE(fields);
+	connmon.max_instance_count = 1U;
+	connmon.create_cb = connmon_create;
+	lwm2m_register_obj(&connmon);
+
+	/* auto create the only instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID,
+				    0, &obj_inst);
+	if (ret < 0) {
+		LOG_DBG("Create LWM2M instance 0 error: %d", ret);
+	}
+
+	return ret;
+}
+
+SYS_INIT(lwm2m_connmon_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_device.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_device.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_device.c	(working copy)
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * TODO:
+ * - Configurable CURRENT_TIME notification delay
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_device
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <string.h>
+#include <stdio.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Device resource IDs */
+#define DEVICE_MANUFACTURER_ID			0
+#define DEVICE_MODEL_NUMBER_ID			1
+#define DEVICE_SERIAL_NUMBER_ID			2
+#define DEVICE_FIRMWARE_VERSION_ID		3
+#define DEVICE_REBOOT_ID			4
+#define DEVICE_FACTORY_DEFAULT_ID		5
+#define DEVICE_AVAILABLE_POWER_SOURCES_ID	6
+#define DEVICE_POWER_SOURCE_VOLTAGE_ID		7
+#define DEVICE_POWER_SOURCE_CURRENT_ID		8
+#define DEVICE_BATTERY_LEVEL_ID			9
+#define DEVICE_MEMORY_FREE_ID			10
+#define DEVICE_ERROR_CODE_ID			11
+#define DEVICE_RESET_ERROR_CODE_ID		12
+#define DEVICE_CURRENT_TIME_ID			13
+#define DEVICE_UTC_OFFSET_ID			14
+#define DEVICE_TIMEZONE_ID			15
+#define DEVICE_SUPPORTED_BINDING_MODES_ID	16
+#define DEVICE_TYPE_ID				17
+#define DEVICE_HARDWARE_VERSION_ID		18
+#define DEVICE_SOFTWARE_VERSION_ID		19
+#define DEVICE_BATTERY_STATUS_ID		20
+#define DEVICE_MEMORY_TOTAL_ID			21
+#define DEVICE_EXT_DEV_INFO_ID			22
+
+#define DEVICE_MAX_ID				23
+
+#ifdef CONFIG_LWM2M_DEVICE_ERROR_CODE_MAX
+#define DEVICE_ERROR_CODE_MAX	CONFIG_LWM2M_DEVICE_ERROR_CODE_MAX
+#else
+#define DEVICE_ERROR_CODE_MAX	10
+#endif
+
+#ifdef CONFIG_LWM2M_DEVICE_PWRSRC_MAX
+#define DEVICE_PWRSRC_MAX	CONFIG_LWM2M_DEVICE_PWRSRC_MAX
+#else
+#define DEVICE_PWRSRC_MAX	5
+#endif
+
+#ifdef CONFIG_LWM2M_DEVICE_EXT_DEV_INFO_MAX
+#define DEVICE_EXT_DEV_INFO_MAX CONFIG_LWM2M_DEVICE_EXT_DEV_INFO_MAX
+#else
+#define DEVICE_EXT_DEV_INFO_MAX	1
+#endif
+
+#define DEVICE_STRING_SHORT	8
+
+#define DEVICE_SERVICE_INTERVAL_MS (MSEC_PER_SEC * 10)
+
+/*
+ * Calculate resource instances as follows:
+ * start with DEVICE_MAX_ID
+ * subtract EXEC resources (3)
+ * subtract MULTI resources because their counts include 0 resource (5)
+ * add 3x DEVICE_PWRSRC_MAX for POWER SOURCES resource instances
+ * add DEVICE_ERROR_CODE_MAX for ERROR CODE resource instances
+ * add DEVICE_EXT_DEV_INFO_MAX for EXT DEV INFO  resource instances
+ */
+#define RESOURCE_INSTANCE_COUNT	(DEVICE_MAX_ID - 3 - 5 + \
+				 DEVICE_PWRSRC_MAX*3 + DEVICE_ERROR_CODE_MAX + \
+				 DEVICE_EXT_DEV_INFO_MAX)
+
+/* resource state variables */
+static uint8_t  error_code_list[DEVICE_ERROR_CODE_MAX];
+static int32_t time_temp;
+static uint32_t time_offset;
+static uint8_t  binding_mode[DEVICE_STRING_SHORT];
+
+/* only 1 instance of device object exists */
+static struct lwm2m_engine_obj device;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(DEVICE_MANUFACTURER_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_MODEL_NUMBER_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_SERIAL_NUMBER_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_FIRMWARE_VERSION_ID, R_OPT, STRING),
+	OBJ_FIELD_EXECUTE_OPT(DEVICE_REBOOT_ID),
+	OBJ_FIELD_EXECUTE_OPT(DEVICE_FACTORY_DEFAULT_ID),
+	OBJ_FIELD_DATA(DEVICE_AVAILABLE_POWER_SOURCES_ID, R_OPT, U8),
+	OBJ_FIELD_DATA(DEVICE_POWER_SOURCE_VOLTAGE_ID, R_OPT, S32),
+	OBJ_FIELD_DATA(DEVICE_POWER_SOURCE_CURRENT_ID, R_OPT, S32),
+	OBJ_FIELD_DATA(DEVICE_BATTERY_LEVEL_ID, R_OPT, U8),
+	OBJ_FIELD_DATA(DEVICE_MEMORY_FREE_ID, R_OPT, S32),
+	OBJ_FIELD_DATA(DEVICE_ERROR_CODE_ID, R, U8),
+	OBJ_FIELD_EXECUTE_OPT(DEVICE_RESET_ERROR_CODE_ID),
+	OBJ_FIELD_DATA(DEVICE_CURRENT_TIME_ID, RW_OPT, TIME),
+	OBJ_FIELD_DATA(DEVICE_UTC_OFFSET_ID, RW_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_TIMEZONE_ID, RW_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_SUPPORTED_BINDING_MODES_ID, R, STRING),
+	OBJ_FIELD_DATA(DEVICE_TYPE_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_HARDWARE_VERSION_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_SOFTWARE_VERSION_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(DEVICE_BATTERY_STATUS_ID, R_OPT, U8),
+	OBJ_FIELD_DATA(DEVICE_MEMORY_TOTAL_ID, R_OPT, S32),
+	OBJ_FIELD_DATA(DEVICE_EXT_DEV_INFO_ID, R_OPT, OBJLNK)
+};
+
+static struct lwm2m_engine_obj_inst inst;
+static struct lwm2m_engine_res res[DEVICE_MAX_ID];
+static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT];
+
+/* save error code resource instance point so we can easily clear later */
+static struct lwm2m_engine_res_inst *error_code_ri;
+
+/* callbacks */
+
+static int reset_error_list_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	/* "delete" error codes */
+	for (i = 0; i < DEVICE_ERROR_CODE_MAX; i++) {
+		error_code_list[i] = 0;
+		error_code_ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
+	}
+
+	return 0;
+}
+
+static void *current_time_read_cb(uint16_t obj_inst_id, uint16_t res_id,
+				  uint16_t res_inst_id, size_t *data_len)
+{
+	time_temp = time_offset + (k_uptime_get() / 1000);
+	*data_len = sizeof(time_temp);
+
+	return &time_temp;
+}
+
+static void *current_time_pre_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				       uint16_t res_inst_id, size_t *data_len)
+{
+	*data_len = sizeof(time_temp);
+	return &time_temp;
+}
+
+static int current_time_post_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				      uint16_t res_inst_id,
+				      uint8_t *data, uint16_t data_len,
+				      bool last_block, size_t total_size)
+{
+	if (data_len == 4U) {
+		time_offset = *(int32_t *)data - (int32_t)(k_uptime_get() / 1000);
+		return 0;
+	}
+
+	LOG_ERR("unknown size %u", data_len);
+	return -EINVAL;
+}
+
+/* error code function */
+
+int lwm2m_device_add_err(uint8_t error_code)
+{
+	int i;
+
+	for (i = 0; i < DEVICE_ERROR_CODE_MAX; i++) {
+		if (error_code_ri[i].res_inst_id == RES_INSTANCE_NOT_CREATED) {
+			break;
+		}
+	}
+
+	if (i >= DEVICE_ERROR_CODE_MAX) {
+		return -ENOMEM;
+	}
+
+	error_code_list[i] = error_code;
+	error_code_ri[i].res_inst_id = i;
+	NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_ERROR_CODE_ID);
+
+	return 0;
+}
+
+static void device_periodic_service(struct k_work *work)
+{
+	NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_CURRENT_TIME_ID);
+}
+
+static struct lwm2m_engine_obj_inst *device_create(uint16_t obj_inst_id)
+{
+	int i = 0, j = 0;
+
+	init_res_instance(res_inst, ARRAY_SIZE(res_inst));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_OPTDATA(DEVICE_MANUFACTURER_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_MODEL_NUMBER_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_SERIAL_NUMBER_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_FIRMWARE_VERSION_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_EXECUTE(DEVICE_REBOOT_ID, res, i, NULL);
+	INIT_OBJ_RES_EXECUTE(DEVICE_FACTORY_DEFAULT_ID, res, i, NULL);
+	INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_AVAILABLE_POWER_SOURCES_ID, res, i,
+				   res_inst, j, DEVICE_PWRSRC_MAX, false);
+	INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_POWER_SOURCE_VOLTAGE_ID, res, i,
+				   res_inst, j, DEVICE_PWRSRC_MAX, false);
+	INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_POWER_SOURCE_CURRENT_ID, res, i,
+				   res_inst, j, DEVICE_PWRSRC_MAX, false);
+	INIT_OBJ_RES_OPTDATA(DEVICE_BATTERY_LEVEL_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_MEMORY_FREE_ID, res, i, res_inst, j);
+	error_code_ri = &res_inst[j];
+	INIT_OBJ_RES_MULTI_DATA(DEVICE_ERROR_CODE_ID, res, i,
+				res_inst, j, DEVICE_ERROR_CODE_MAX, false,
+				error_code_list, sizeof(*error_code_list));
+	INIT_OBJ_RES_EXECUTE(DEVICE_RESET_ERROR_CODE_ID, res, i,
+			     reset_error_list_cb);
+	INIT_OBJ_RES_OPT(DEVICE_CURRENT_TIME_ID, res, i, res_inst, j, 1, true,
+			 current_time_read_cb,
+			 current_time_pre_write_cb,
+			 current_time_post_write_cb, NULL);
+	INIT_OBJ_RES_OPTDATA(DEVICE_UTC_OFFSET_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_TIMEZONE_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_DATA(DEVICE_SUPPORTED_BINDING_MODES_ID, res, i,
+			  res_inst, j, binding_mode, DEVICE_STRING_SHORT);
+	INIT_OBJ_RES_OPTDATA(DEVICE_TYPE_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_HARDWARE_VERSION_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_SOFTWARE_VERSION_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_BATTERY_STATUS_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_OPTDATA(DEVICE_MEMORY_TOTAL_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_EXT_DEV_INFO_ID, res, i, res_inst, j,
+				   DEVICE_EXT_DEV_INFO_MAX, false);
+
+	inst.resources = res;
+	inst.resource_count = i;
+
+	LOG_DBG("Create LWM2M device instance: %d", obj_inst_id);
+	return &inst;
+}
+
+static int lwm2m_device_init(const struct device *dev)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	int ret = 0;
+
+	/* Set default values */
+	time_offset = 0U;
+	lwm2m_engine_get_binding(binding_mode);
+
+	/* initialize the device field data */
+	device.obj_id = LWM2M_OBJECT_DEVICE_ID;
+	device.fields = fields;
+	device.field_count = ARRAY_SIZE(fields);
+	device.max_instance_count = 1U;
+	device.create_cb = device_create;
+	lwm2m_register_obj(&device);
+
+	/* auto create the only instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_DEVICE_ID, 0, &obj_inst);
+	if (ret < 0) {
+		LOG_DBG("Create LWM2M instance 0 error: %d", ret);
+	}
+
+	/* call device_periodic_service() every 10 seconds */
+	ret = lwm2m_engine_add_service(device_periodic_service,
+				       DEVICE_SERVICE_INTERVAL_MS);
+	return ret;
+}
+
+SYS_INIT(lwm2m_device_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c	(working copy)
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_firmware
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <string.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Firmware resource IDs */
+#define FIRMWARE_PACKAGE_ID			0
+#define FIRMWARE_PACKAGE_URI_ID			1
+#define FIRMWARE_UPDATE_ID			2
+#define FIRMWARE_STATE_ID			3
+#define FIRMWARE_UPDATE_RESULT_ID		5
+#define FIRMWARE_PACKAGE_NAME_ID		6
+#define FIRMWARE_PACKAGE_VERSION_ID		7
+#define FIRMWARE_UPDATE_PROTO_SUPPORT_ID	8 /* TODO */
+#define FIRMWARE_UPDATE_DELIV_METHOD_ID		9
+
+#define FIRMWARE_MAX_ID				10
+
+#define DELIVERY_METHOD_PULL_ONLY		0
+#define DELIVERY_METHOD_PUSH_ONLY		1
+#define DELIVERY_METHOD_BOTH			2
+
+#define PACKAGE_URI_LEN				255
+
+/*
+ * Calculate resource instances as follows:
+ * start with FIRMWARE_MAX_ID
+ * subtract EXEC resources (1)
+ */
+#define RESOURCE_INSTANCE_COUNT	(FIRMWARE_MAX_ID - 1)
+
+/* resource state variables */
+static uint8_t update_state;
+static uint8_t update_result;
+static uint8_t delivery_method;
+static char package_uri[PACKAGE_URI_LEN];
+
+/* only 1 instance of firmware object exists */
+static struct lwm2m_engine_obj firmware;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(FIRMWARE_PACKAGE_ID, W, OPAQUE),
+	OBJ_FIELD_DATA(FIRMWARE_PACKAGE_URI_ID, RW, STRING),
+	OBJ_FIELD_EXECUTE(FIRMWARE_UPDATE_ID),
+	OBJ_FIELD_DATA(FIRMWARE_STATE_ID, R, U8),
+	OBJ_FIELD_DATA(FIRMWARE_UPDATE_RESULT_ID, R, U8),
+	OBJ_FIELD_DATA(FIRMWARE_PACKAGE_NAME_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(FIRMWARE_PACKAGE_VERSION_ID, R_OPT, STRING),
+	OBJ_FIELD_DATA(FIRMWARE_UPDATE_PROTO_SUPPORT_ID, R_OPT, U8),
+	OBJ_FIELD_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, R, U8)
+};
+
+static struct lwm2m_engine_obj_inst inst;
+static struct lwm2m_engine_res res[FIRMWARE_MAX_ID];
+static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT];
+
+static lwm2m_engine_set_data_cb_t write_cb;
+static lwm2m_engine_user_cb_t update_cb;
+
+#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+extern int lwm2m_firmware_start_transfer(char *package_uri);
+#endif
+
+uint8_t lwm2m_firmware_get_update_state(void)
+{
+	return update_state;
+}
+
+void lwm2m_firmware_set_update_state(uint8_t state)
+{
+	bool error = false;
+
+	/* Check LWM2M SPEC appendix E.6.1 */
+	switch (state) {
+	case STATE_DOWNLOADING:
+		if (update_state != STATE_IDLE) {
+			error = true;
+		}
+		break;
+	case STATE_DOWNLOADED:
+		if (update_state != STATE_DOWNLOADING &&
+		    update_state != STATE_UPDATING) {
+			error = true;
+		}
+		break;
+	case STATE_UPDATING:
+		if (update_state != STATE_DOWNLOADED) {
+			error = true;
+		}
+		break;
+	case STATE_IDLE:
+		break;
+	default:
+		LOG_ERR("Unhandled state: %u", state);
+		return;
+	}
+
+	if (error) {
+		LOG_ERR("Invalid state transition: %u -> %u",
+			update_state, state);
+	}
+
+	update_state = state;
+	NOTIFY_OBSERVER(LWM2M_OBJECT_FIRMWARE_ID, 0, FIRMWARE_STATE_ID);
+	LOG_DBG("Update state = %d", update_state);
+}
+
+uint8_t lwm2m_firmware_get_update_result(void)
+{
+	return update_result;
+}
+
+void lwm2m_firmware_set_update_result(uint8_t result)
+{
+	uint8_t state;
+	bool error = false;
+
+	/* Check LWM2M SPEC appendix E.6.1 */
+	switch (result) {
+	case RESULT_DEFAULT:
+		lwm2m_firmware_set_update_state(STATE_IDLE);
+		break;
+	case RESULT_SUCCESS:
+		if (update_state != STATE_UPDATING) {
+			error = true;
+			state = update_state;
+		}
+
+		lwm2m_firmware_set_update_state(STATE_IDLE);
+		break;
+	case RESULT_NO_STORAGE:
+	case RESULT_OUT_OF_MEM:
+	case RESULT_CONNECTION_LOST:
+	case RESULT_UNSUP_FW:
+	case RESULT_INVALID_URI:
+	case RESULT_UNSUP_PROTO:
+		if (update_state != STATE_DOWNLOADING) {
+			error = true;
+			state = update_state;
+		}
+
+		lwm2m_firmware_set_update_state(STATE_IDLE);
+		break;
+	case RESULT_INTEGRITY_FAILED:
+		if (update_state != STATE_DOWNLOADING &&
+		    update_state != STATE_UPDATING) {
+			error = true;
+			state = update_state;
+		}
+
+		lwm2m_firmware_set_update_state(STATE_IDLE);
+		break;
+	case RESULT_UPDATE_FAILED:
+		if (update_state != STATE_DOWNLOADING &&
+		    update_state != STATE_UPDATING) {
+			error = true;
+			state = update_state;
+		}
+
+		lwm2m_firmware_set_update_state(STATE_IDLE);
+		break;
+	default:
+		LOG_ERR("Unhandled result: %u", result);
+		return;
+	}
+
+	if (error) {
+		LOG_ERR("Unexpected result(%u) set while state is %u",
+			result, state);
+	}
+
+	update_result = result;
+	NOTIFY_OBSERVER(LWM2M_OBJECT_FIRMWARE_ID, 0, FIRMWARE_UPDATE_RESULT_ID);
+	LOG_DBG("Update result = %d", update_result);
+}
+
+static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+			    uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
+			    bool last_block, size_t total_size)
+{
+	uint8_t state;
+	int ret;
+
+	state = lwm2m_firmware_get_update_state();
+	if (state == STATE_IDLE) {
+		/* TODO: setup timer to check download status,
+		 * make sure it fail after timeout
+		 */
+		lwm2m_firmware_set_update_state(STATE_DOWNLOADING);
+	} else if (state != STATE_DOWNLOADING) {
+		if (data_len == 0U && state == STATE_DOWNLOADED) {
+			/* reset to state idle and result default */
+			lwm2m_firmware_set_update_result(RESULT_DEFAULT);
+			return 0;
+		}
+
+		LOG_DBG("Cannot download: state = %d", state);
+		return -EPERM;
+	}
+
+	ret = write_cb ? write_cb(obj_inst_id, res_id, res_inst_id,
+				  data, data_len,
+				  last_block, total_size) : 0;
+	if (ret >= 0) {
+		if (last_block) {
+			lwm2m_firmware_set_update_state(STATE_DOWNLOADED);
+		}
+
+		return 0;
+	} else if (ret == -ENOMEM) {
+		lwm2m_firmware_set_update_result(RESULT_OUT_OF_MEM);
+	} else if (ret == -ENOSPC) {
+		lwm2m_firmware_set_update_result(RESULT_NO_STORAGE);
+		/* Response 4.13 (RFC7959, section 2.9.3) */
+		/* TODO: should include size1 option to indicate max size */
+		ret = -EFBIG;
+	} else if (ret == -EFAULT) {
+		lwm2m_firmware_set_update_result(RESULT_INTEGRITY_FAILED);
+	} else {
+		lwm2m_firmware_set_update_result(RESULT_UPDATE_FAILED);
+	}
+
+	return ret;
+}
+
+static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id,
+				uint16_t res_inst_id, uint8_t *data, uint16_t data_len,
+				bool last_block, size_t total_size)
+{
+	LOG_DBG("PACKAGE_URI WRITE: %s", log_strdup(package_uri));
+
+#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+	uint8_t state = lwm2m_firmware_get_update_state();
+
+	if (state == STATE_IDLE) {
+		lwm2m_firmware_set_update_result(RESULT_DEFAULT);
+
+		if (data_len > 0) {
+			lwm2m_firmware_start_transfer(package_uri);
+		}
+	} else if (state == STATE_DOWNLOADED && data_len == 0U) {
+		/* reset to state idle and result default */
+		lwm2m_firmware_set_update_result(RESULT_DEFAULT);
+	}
+
+	return 0;
+#else
+	return -EINVAL;
+#endif
+}
+
+void lwm2m_firmware_set_write_cb(lwm2m_engine_set_data_cb_t cb)
+{
+	write_cb = cb;
+}
+
+lwm2m_engine_set_data_cb_t lwm2m_firmware_get_write_cb(void)
+{
+	return write_cb;
+}
+
+void lwm2m_firmware_set_update_cb(lwm2m_engine_user_cb_t cb)
+{
+	update_cb = cb;
+}
+
+lwm2m_engine_user_cb_t lwm2m_firmware_get_update_cb(void)
+{
+	return update_cb;
+}
+
+static int firmware_update_cb(uint16_t obj_inst_id)
+{
+	lwm2m_engine_user_cb_t callback;
+	uint8_t state;
+	int ret;
+
+	state = lwm2m_firmware_get_update_state();
+	if (state != STATE_DOWNLOADED) {
+		LOG_ERR("State other than downloaded: %d", state);
+		return -EPERM;
+	}
+
+	lwm2m_firmware_set_update_state(STATE_UPDATING);
+
+	callback = lwm2m_firmware_get_update_cb();
+	if (callback) {
+		ret = callback(obj_inst_id);
+		if (ret < 0) {
+			LOG_ERR("Failed to update firmware: %d", ret);
+			lwm2m_firmware_set_update_result(
+				ret == -EINVAL ? RESULT_INTEGRITY_FAILED :
+						 RESULT_UPDATE_FAILED);
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static struct lwm2m_engine_obj_inst *firmware_create(uint16_t obj_inst_id)
+{
+	int i = 0, j = 0;
+
+	init_res_instance(res_inst, ARRAY_SIZE(res_inst));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_OPT(FIRMWARE_PACKAGE_ID, res, i, res_inst, j, 1, true,
+			 NULL, NULL, package_write_cb, NULL);
+	INIT_OBJ_RES(FIRMWARE_PACKAGE_URI_ID, res, i, res_inst, j, 1, true,
+		     package_uri, PACKAGE_URI_LEN,
+		     NULL, NULL, package_uri_write_cb, NULL);
+	INIT_OBJ_RES_EXECUTE(FIRMWARE_UPDATE_ID, res, i, firmware_update_cb);
+	INIT_OBJ_RES_DATA(FIRMWARE_STATE_ID, res, i, res_inst, j,
+			  &update_state, sizeof(update_state));
+	INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_RESULT_ID, res, i, res_inst, j,
+			  &update_result, sizeof(update_result));
+	INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, res, i, res_inst, j,
+			  &delivery_method, sizeof(delivery_method));
+
+	inst.resources = res;
+	inst.resource_count = i;
+
+	LOG_DBG("Create LWM2M firmware instance: %d", obj_inst_id);
+	return &inst;
+}
+
+static int lwm2m_firmware_init(const struct device *dev)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	int ret = 0;
+
+	/* Set default values */
+	package_uri[0] = '\0';
+	/* Initialize state machine */
+	/* TODO: should be restored from the permanent storage */
+	update_state = STATE_IDLE;
+	update_result = RESULT_DEFAULT;
+#ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
+	delivery_method = DELIVERY_METHOD_BOTH;
+#else
+	delivery_method = DELIVERY_METHOD_PUSH_ONLY;
+#endif
+
+	firmware.obj_id = LWM2M_OBJECT_FIRMWARE_ID;
+	firmware.fields = fields;
+	firmware.field_count = ARRAY_SIZE(fields);
+	firmware.max_instance_count = 1U;
+	firmware.create_cb = firmware_create;
+	lwm2m_register_obj(&firmware);
+
+	/* auto create the only instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_FIRMWARE_ID, 0, &obj_inst);
+	if (ret < 0) {
+		LOG_DBG("Create LWM2M instance 0 error: %d", ret);
+	}
+
+	return ret;
+}
+
+SYS_INIT(lwm2m_firmware_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c	(working copy)
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_firmware_pull
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <net/http_parser.h>
+#include <net/socket.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#define URI_LEN		255
+
+#define NETWORK_INIT_TIMEOUT	K_SECONDS(10)
+#define NETWORK_CONNECT_TIMEOUT	K_SECONDS(10)
+#define PACKET_TRANSFER_RETRY_MAX	3
+
+static struct k_work firmware_work;
+static char firmware_uri[URI_LEN];
+static struct lwm2m_ctx firmware_ctx = {
+	.sock_fd = -1
+};
+static int firmware_retry;
+static struct coap_block_context firmware_block_ctx;
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT)
+#define COAP2COAP_PROXY_URI_PATH	"coap2coap"
+#define COAP2HTTP_PROXY_URI_PATH	"coap2http"
+
+static char proxy_uri[URI_LEN];
+#endif
+
+static void do_transmit_timeout_cb(struct lwm2m_message *msg);
+
+static void set_update_result_from_error(int error_code)
+{
+	if (error_code == -ENOMEM) {
+		lwm2m_firmware_set_update_result(RESULT_OUT_OF_MEM);
+	} else if (error_code == -ENOSPC) {
+		lwm2m_firmware_set_update_result(RESULT_NO_STORAGE);
+	} else if (error_code == -EFAULT) {
+		lwm2m_firmware_set_update_result(RESULT_INTEGRITY_FAILED);
+	} else if (error_code == -ENOMSG) {
+		lwm2m_firmware_set_update_result(RESULT_CONNECTION_LOST);
+	} else if (error_code == -ENOTSUP) {
+		lwm2m_firmware_set_update_result(RESULT_INVALID_URI);
+	} else if (error_code == -EPROTONOSUPPORT) {
+		lwm2m_firmware_set_update_result(RESULT_UNSUP_PROTO);
+	} else {
+		lwm2m_firmware_set_update_result(RESULT_UPDATE_FAILED);
+	}
+}
+
+static int transfer_request(struct coap_block_context *ctx,
+			    uint8_t *token, uint8_t tkl,
+			    coap_reply_t reply_cb)
+{
+	struct lwm2m_message *msg;
+	int ret;
+	char *cursor;
+#if !defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT)
+	struct http_parser_url parser;
+	uint16_t off, len;
+	char *next_slash;
+#endif
+
+	msg = lwm2m_get_message(&firmware_ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		return -ENOMEM;
+	}
+
+	msg->type = COAP_TYPE_CON;
+	msg->code = COAP_METHOD_GET;
+	msg->mid = coap_next_id();
+	msg->token = token;
+	msg->tkl = tkl;
+	msg->reply_cb = reply_cb;
+	msg->message_timeout_cb = do_transmit_timeout_cb;
+
+	ret = lwm2m_init_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error setting up lwm2m message");
+		goto cleanup;
+	}
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT)
+	/* TODO: shift to lower case */
+	if (strncmp(firmware_uri, "http", 4) == 0) {
+		cursor = COAP2HTTP_PROXY_URI_PATH;
+	} else if (strncmp(firmware_uri, "coap", 4) == 0) {
+		cursor = COAP2COAP_PROXY_URI_PATH;
+	} else {
+		ret = -EPROTONOSUPPORT;
+		LOG_ERR("Unsupported schema");
+		goto cleanup;
+	}
+
+	ret = coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+					cursor, strlen(cursor));
+	if (ret < 0) {
+		LOG_ERR("Error adding URI_PATH '%s'", log_strdup(cursor));
+		goto cleanup;
+	}
+#else
+	http_parser_url_init(&parser);
+	ret = http_parser_parse_url(firmware_uri, strlen(firmware_uri), 0,
+				    &parser);
+	if (ret < 0) {
+		LOG_ERR("Invalid firmware url: %s", log_strdup(firmware_uri));
+		ret = -ENOTSUP;
+		goto cleanup;
+	}
+
+	/* if path is not available, off/len will be zero */
+	off = parser.field_data[UF_PATH].off;
+	len = parser.field_data[UF_PATH].len;
+	cursor = firmware_uri + off;
+
+	/* add path portions (separated by slashes) */
+	while (len > 0 && (next_slash = strchr(cursor, '/')) != NULL) {
+		if (next_slash != cursor) {
+			ret = coap_packet_append_option(&msg->cpkt,
+							COAP_OPTION_URI_PATH,
+							cursor,
+							next_slash - cursor);
+			if (ret < 0) {
+				LOG_ERR("Error adding URI_PATH");
+				goto cleanup;
+			}
+		}
+
+		/* skip slash */
+		len -= (next_slash - cursor) + 1;
+		cursor = next_slash + 1;
+	}
+
+	if (len > 0) {
+		/* flush the rest */
+		ret = coap_packet_append_option(&msg->cpkt,
+						COAP_OPTION_URI_PATH,
+						cursor, len);
+		if (ret < 0) {
+			LOG_ERR("Error adding URI_PATH");
+			goto cleanup;
+		}
+	}
+#endif
+
+	ret = coap_append_block2_option(&msg->cpkt, ctx);
+	if (ret < 0) {
+		LOG_ERR("Unable to add block2 option.");
+		goto cleanup;
+	}
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT)
+	ret = coap_packet_append_option(&msg->cpkt, COAP_OPTION_PROXY_URI,
+					firmware_uri, strlen(firmware_uri));
+	if (ret < 0) {
+		LOG_ERR("Error adding PROXY_URI '%s'",
+			log_strdup(firmware_uri));
+		goto cleanup;
+	}
+#else
+	/* Ask the server to provide a size estimate */
+	ret = coap_append_option_int(&msg->cpkt, COAP_OPTION_SIZE2, 0);
+	if (ret < 0) {
+		LOG_ERR("Unable to add size2 option.");
+		goto cleanup;
+	}
+#endif
+
+	/* send request */
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+	return ret;
+}
+
+static int transfer_empty_ack(uint16_t mid)
+{
+	struct lwm2m_message *msg;
+	int ret;
+
+	msg = lwm2m_get_message(&firmware_ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		return -ENOMEM;
+	}
+
+	msg->type = COAP_TYPE_ACK;
+	msg->code = COAP_CODE_EMPTY;
+	msg->mid = mid;
+
+	ret = lwm2m_init_message(msg);
+	if (ret) {
+		goto cleanup;
+	}
+
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+	return ret;
+}
+
+static int
+do_firmware_transfer_reply_cb(const struct coap_packet *response,
+			      struct coap_reply *reply,
+			      const struct sockaddr *from)
+{
+	int ret;
+	bool last_block;
+	uint8_t token[8];
+	uint8_t tkl;
+	uint16_t payload_len, payload_offset, len;
+	struct coap_packet *check_response = (struct coap_packet *)response;
+	struct lwm2m_engine_res *res = NULL;
+	lwm2m_engine_set_data_cb_t write_cb;
+	size_t write_buflen;
+	uint8_t resp_code, *write_buf;
+	struct coap_block_context received_block_ctx;
+
+	/* token is used to determine a valid ACK vs a separated response */
+	tkl = coap_header_get_token(check_response, token);
+
+	/* If separated response (ACK) return and wait for response */
+	if (!tkl && coap_header_get_type(response) == COAP_TYPE_ACK) {
+		return 0;
+	} else if (coap_header_get_type(response) == COAP_TYPE_CON) {
+		/* Send back ACK so the server knows we received the pkt */
+		ret = transfer_empty_ack(coap_header_get_id(check_response));
+		if (ret < 0) {
+			LOG_ERR("Error transmitting ACK");
+			goto error;
+		}
+	}
+
+	/* Check response code from server. Expecting (2.05) */
+	resp_code = coap_header_get_code(check_response);
+	if (resp_code != COAP_RESPONSE_CODE_CONTENT) {
+		LOG_ERR("Unexpected response from server: %d.%d",
+			COAP_RESPONSE_CODE_CLASS(resp_code),
+			COAP_RESPONSE_CODE_DETAIL(resp_code));
+		ret = -ENOMSG;
+		goto error;
+	}
+
+	/* save main firmware block context */
+	memcpy(&received_block_ctx, &firmware_block_ctx,
+	       sizeof(firmware_block_ctx));
+
+	ret = coap_update_from_block(check_response, &firmware_block_ctx);
+	if (ret < 0) {
+		LOG_ERR("Error from block update: %d", ret);
+		ret = -EFAULT;
+		goto error;
+	}
+
+	/* test for duplicate transfer */
+	if (firmware_block_ctx.current < received_block_ctx.current) {
+		LOG_WRN("Duplicate packet ignored");
+
+		/* restore main firmware block context */
+		memcpy(&firmware_block_ctx, &received_block_ctx,
+		       sizeof(firmware_block_ctx));
+
+		/* set reply->user_data to error to avoid releasing */
+		reply->user_data = (void *)COAP_REPLY_STATUS_ERROR;
+		return 0;
+	}
+
+	/* Reach last block if ret equals to 0 */
+	last_block = !coap_next_block(check_response, &firmware_block_ctx);
+
+	/* Process incoming data */
+	payload_offset = response->hdr_len + response->opt_len;
+	coap_packet_get_payload(response, &payload_len);
+	if (payload_len > 0) {
+		LOG_DBG("total: %zd, current: %zd",
+			firmware_block_ctx.total_size,
+			firmware_block_ctx.current);
+
+		/* look up firmware package resource */
+		ret = lwm2m_engine_get_resource("5/0/0", &res);
+		if (ret < 0) {
+			goto error;
+		}
+
+		/* get buffer data */
+		write_buf = res->res_instances->data_ptr;
+		write_buflen = res->res_instances->max_data_len;
+
+		/* check for user override to buffer */
+		if (res->pre_write_cb) {
+			write_buf = res->pre_write_cb(0, 0, 0, &write_buflen);
+		}
+
+		write_cb = lwm2m_firmware_get_write_cb();
+		if (write_cb) {
+			/* flush incoming data to write_cb */
+			while (payload_len > 0) {
+				len = (payload_len > write_buflen) ?
+				       write_buflen : payload_len;
+				payload_len -= len;
+				/* check for end of packet */
+				if (buf_read(write_buf, len,
+					     CPKT_BUF_READ(response),
+					     &payload_offset) < 0) {
+					/* malformed packet */
+					ret = -EFAULT;
+					goto error;
+				}
+
+				ret = write_cb(0, 0, 0,
+					       write_buf, len,
+					       last_block &&
+							(payload_len == 0U),
+					       firmware_block_ctx.total_size);
+				if (ret < 0) {
+					goto error;
+				}
+			}
+		}
+	}
+
+	if (!last_block) {
+		/* More block(s) to come, setup next transfer */
+		ret = transfer_request(&firmware_block_ctx, token, tkl,
+				       do_firmware_transfer_reply_cb);
+		if (ret < 0) {
+			goto error;
+		}
+	} else {
+		/* Download finished */
+		lwm2m_firmware_set_update_state(STATE_DOWNLOADED);
+		lwm2m_engine_context_close(&firmware_ctx);
+	}
+
+	return 0;
+
+error:
+	set_update_result_from_error(ret);
+	lwm2m_engine_context_close(&firmware_ctx);
+	return ret;
+}
+
+static void do_transmit_timeout_cb(struct lwm2m_message *msg)
+{
+	int ret;
+
+	if (firmware_retry < PACKET_TRANSFER_RETRY_MAX) {
+		/* retry block */
+		LOG_WRN("TIMEOUT - Sending a retry packet!");
+
+		ret = transfer_request(&firmware_block_ctx,
+				       msg->token, msg->tkl,
+				       do_firmware_transfer_reply_cb);
+		if (ret < 0) {
+			/* abort retries / transfer */
+			set_update_result_from_error(ret);
+			firmware_retry = PACKET_TRANSFER_RETRY_MAX;
+			lwm2m_engine_context_close(&firmware_ctx);
+			return;
+		}
+
+		firmware_retry++;
+	} else {
+		LOG_ERR("TIMEOUT - Too many retry packet attempts! "
+			"Aborting firmware download.");
+		lwm2m_firmware_set_update_result(RESULT_CONNECTION_LOST);
+		lwm2m_engine_context_close(&firmware_ctx);
+	}
+}
+
+static void firmware_transfer(struct k_work *work)
+{
+	int ret;
+	char *server_addr;
+
+#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_SUPPORT)
+	server_addr = CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_COAP_PROXY_ADDR;
+	if (strlen(server_addr) >= URI_LEN) {
+		LOG_ERR("Invalid Proxy URI: %s", log_strdup(server_addr));
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	/* Copy required as it gets modified when port is available */
+	strcpy(proxy_uri, server_addr);
+	server_addr = proxy_uri;
+#else
+	server_addr = firmware_uri;
+#endif
+
+	ret = lwm2m_parse_peerinfo(server_addr, &firmware_ctx.remote_addr,
+				   &firmware_ctx.use_dtls);
+	if (ret < 0) {
+		goto error;
+	}
+
+	lwm2m_engine_context_init(&firmware_ctx);
+	firmware_ctx.handle_separate_response = true;
+	ret = lwm2m_socket_start(&firmware_ctx);
+	if (ret < 0) {
+		LOG_ERR("Cannot start a firmware-pull connection:%d", ret);
+		goto error;
+	}
+
+	LOG_INF("Connecting to server %s", log_strdup(firmware_uri));
+
+	/* reset block transfer context */
+	coap_block_transfer_init(&firmware_block_ctx,
+				 lwm2m_default_block_size(), 0);
+	ret = transfer_request(&firmware_block_ctx, coap_next_token(), 8,
+			       do_firmware_transfer_reply_cb);
+	if (ret < 0) {
+		goto error;
+	}
+
+	return;
+
+error:
+	set_update_result_from_error(ret);
+	lwm2m_engine_context_close(&firmware_ctx);
+}
+
+/* TODO: */
+int lwm2m_firmware_cancel_transfer(void)
+{
+	return 0;
+}
+
+int lwm2m_firmware_start_transfer(char *package_uri)
+{
+	/* close old socket */
+	if (firmware_ctx.sock_fd > -1) {
+		lwm2m_engine_context_close(&firmware_ctx);
+	}
+
+	(void)memset(&firmware_ctx, 0, sizeof(struct lwm2m_ctx));
+	firmware_retry = 0;
+	k_work_init(&firmware_work, firmware_transfer);
+	lwm2m_firmware_set_update_state(STATE_DOWNLOADING);
+
+	/* start file transfer work */
+	strncpy(firmware_uri, package_uri, URI_LEN - 1);
+	k_work_submit(&firmware_work);
+
+	return 0;
+}
+
+/**
+ * @brief Get the block context of the current firmware block.
+ *
+ * @return A pointer to the firmware block context
+ */
+struct coap_block_context *lwm2m_firmware_get_block_context()
+{
+	return &firmware_block_ctx;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_location.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_location.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_location.c	(working copy)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_location
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* resource IDs */
+#define LOCATION_LATITUDE_ID			0
+#define LOCATION_LONGITUDE_ID			1
+#define LOCATION_ALTITUDE_ID			2
+#define LOCATION_RADIUS_ID			3
+#define LOCATION_VELOCITY_ID			4
+#define LOCATION_TIMESTAMP_ID			5
+#define LOCATION_SPEED_ID			6
+
+#define LOCATION_MAX_ID				7
+
+/*
+ * Calculate resource instances as follows:
+ * start with LOCATION_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT	(LOCATION_MAX_ID)
+
+/* resource state */
+static float32_value_t latitude;
+static float32_value_t longitude;
+static float32_value_t altitude;
+static float32_value_t radius;
+static float32_value_t speed;
+static int32_t timestamp;
+
+static struct lwm2m_engine_obj location;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(LOCATION_LATITUDE_ID, R, FLOAT32),
+	OBJ_FIELD_DATA(LOCATION_LONGITUDE_ID, R, FLOAT32),
+	OBJ_FIELD_DATA(LOCATION_ALTITUDE_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(LOCATION_RADIUS_ID, R_OPT, FLOAT32),
+	OBJ_FIELD_DATA(LOCATION_VELOCITY_ID, R_OPT, OPAQUE),
+	OBJ_FIELD_DATA(LOCATION_TIMESTAMP_ID, R, TIME),
+	OBJ_FIELD_DATA(LOCATION_SPEED_ID, R_OPT, FLOAT32),
+};
+
+static struct lwm2m_engine_obj_inst inst;
+static struct lwm2m_engine_res res[LOCATION_MAX_ID];
+static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj_inst *location_create(uint16_t obj_inst_id)
+{
+	int i = 0, j = 0;
+
+	if (inst.resource_count) {
+		LOG_ERR("Only 1 instance of Location object can exist.");
+		return NULL;
+	}
+
+	init_res_instance(res_inst, ARRAY_SIZE(res_inst));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(LOCATION_LATITUDE_ID, res, i, res_inst, j,
+			  &latitude, sizeof(latitude));
+	INIT_OBJ_RES_DATA(LOCATION_LONGITUDE_ID, res, i, res_inst, j,
+			  &longitude, sizeof(longitude));
+	INIT_OBJ_RES_DATA(LOCATION_ALTITUDE_ID, res, i, res_inst, j,
+			  &altitude, sizeof(altitude));
+	INIT_OBJ_RES_DATA(LOCATION_RADIUS_ID, res, i, res_inst, j,
+			  &radius, sizeof(radius));
+	INIT_OBJ_RES_OPTDATA(LOCATION_VELOCITY_ID, res, i, res_inst, j);
+	INIT_OBJ_RES_DATA(LOCATION_TIMESTAMP_ID, res, i, res_inst, j,
+			  &timestamp, sizeof(timestamp));
+	INIT_OBJ_RES_DATA(LOCATION_SPEED_ID, res, i, res_inst, j,
+			  &speed, sizeof(speed));
+
+	inst.resources = res;
+	inst.resource_count = i;
+
+	LOG_DBG("Create Location instance: %d", obj_inst_id);
+
+	return &inst;
+}
+
+static int ipso_location_init(const struct device *dev)
+{
+	int ret;
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+
+	location.obj_id = LWM2M_OBJECT_LOCATION_ID;
+	location.fields = fields;
+	location.field_count = ARRAY_SIZE(fields);
+	location.max_instance_count = 1U;
+	location.create_cb = location_create;
+	lwm2m_register_obj(&location);
+
+	/* auto create the only instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_LOCATION_ID, 0, &obj_inst);
+	if (ret < 0) {
+		LOG_DBG("Create LWM2M instance 0 error: %d", ret);
+	}
+
+	return ret;
+}
+
+SYS_INIT(ipso_location_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_security.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_security.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_security.c	(working copy)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_security
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+/* Security resource IDs */
+#define SECURITY_SERVER_URI_ID			0
+#define SECURITY_BOOTSTRAP_FLAG_ID		1
+#define SECURITY_MODE_ID			2
+#define SECURITY_CLIENT_PK_ID			3
+#define SECURITY_SERVER_PK_ID			4
+#define SECURITY_SECRET_KEY_ID			5
+#define SECURITY_SMS_MODE_ID			6
+#define SECURITY_SMS_BINDING_KEY_PARAM_ID	7
+#define SECURITY_SMS_BINDING_SECRET_KEY_ID	8
+#define SECURITY_LWM2M_SERVER_SMS_NUM_ID	9
+#define SECURITY_SHORT_SERVER_ID		10
+#define SECURITY_CLIENT_HOLD_OFF_TIME_ID	11
+#define SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID	12
+
+#define SECURITY_MAX_ID				13
+
+#define MAX_INSTANCE_COUNT		CONFIG_LWM2M_SECURITY_INSTANCE_COUNT
+
+#define SECURITY_URI_LEN		255
+#define IDENTITY_LEN			128
+#define KEY_LEN				CONFIG_LWM2M_SECURITY_KEY_SIZE
+
+/*
+ * Calculate resource instances as follows:
+ * start with SECURITY_MAX_ID
+ */
+#define RESOURCE_INSTANCE_COUNT	(SECURITY_MAX_ID)
+
+/* resource state variables */
+static char  security_uri[MAX_INSTANCE_COUNT][SECURITY_URI_LEN];
+static uint8_t  client_identity[MAX_INSTANCE_COUNT][IDENTITY_LEN];
+static uint8_t  server_pk[MAX_INSTANCE_COUNT][KEY_LEN];
+static uint8_t  secret_key[MAX_INSTANCE_COUNT][KEY_LEN];
+static bool  bootstrap_flag[MAX_INSTANCE_COUNT];
+static uint8_t  security_mode[MAX_INSTANCE_COUNT];
+static uint16_t short_server_id[MAX_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj security;
+static struct lwm2m_engine_obj_field fields[] = {
+	OBJ_FIELD_DATA(SECURITY_SERVER_URI_ID, RW, STRING),
+	OBJ_FIELD_DATA(SECURITY_BOOTSTRAP_FLAG_ID, W, BOOL),
+	OBJ_FIELD_DATA(SECURITY_MODE_ID, W, U8),
+	OBJ_FIELD_DATA(SECURITY_CLIENT_PK_ID, W, OPAQUE),
+	OBJ_FIELD_DATA(SECURITY_SERVER_PK_ID, W, OPAQUE),
+	OBJ_FIELD_DATA(SECURITY_SECRET_KEY_ID, W, OPAQUE),
+	OBJ_FIELD_DATA(SECURITY_SMS_MODE_ID, W_OPT, U8),
+	OBJ_FIELD_DATA(SECURITY_SMS_BINDING_KEY_PARAM_ID, W_OPT, OPAQUE),
+	OBJ_FIELD_DATA(SECURITY_SMS_BINDING_SECRET_KEY_ID, W_OPT, OPAQUE),
+	OBJ_FIELD_DATA(SECURITY_LWM2M_SERVER_SMS_NUM_ID, W_OPT, STRING),
+	OBJ_FIELD_DATA(SECURITY_SHORT_SERVER_ID, W_OPT, U16),
+	OBJ_FIELD_DATA(SECURITY_CLIENT_HOLD_OFF_TIME_ID, W_OPT, U32),
+	OBJ_FIELD_DATA(SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID, W_OPT, U32)
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID];
+static struct lwm2m_engine_res_inst
+			res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static struct lwm2m_engine_obj_inst *security_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - "
+			"no more room: %u", obj_inst_id);
+		return NULL;
+	}
+
+	/* default values */
+	security_uri[index][0] = '\0';
+	client_identity[index][0] = '\0';
+	bootstrap_flag[index] = 0;
+	security_mode[index] = 0U;
+	short_server_id[index] = 0U;
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(SECURITY_SERVER_URI_ID, res[index], i,
+			  res_inst[index], j,
+			  security_uri[index], SECURITY_URI_LEN);
+	INIT_OBJ_RES_DATA(SECURITY_BOOTSTRAP_FLAG_ID, res[index], i,
+			  res_inst[index], j,
+			  &bootstrap_flag[index], sizeof(*bootstrap_flag));
+	INIT_OBJ_RES_DATA(SECURITY_MODE_ID, res[index], i,
+			  res_inst[index], j,
+			  &security_mode[index], sizeof(*security_mode));
+	INIT_OBJ_RES_DATA(SECURITY_CLIENT_PK_ID, res[index], i,
+			  res_inst[index], j,
+			  &client_identity[index], IDENTITY_LEN);
+	INIT_OBJ_RES_DATA(SECURITY_SERVER_PK_ID, res[index], i,
+			  res_inst[index], j,
+			  &server_pk[index], KEY_LEN);
+	INIT_OBJ_RES_DATA(SECURITY_SECRET_KEY_ID, res[index], i,
+			  res_inst[index], j,
+			  &secret_key[index], KEY_LEN);
+	INIT_OBJ_RES_DATA(SECURITY_SHORT_SERVER_ID, res[index], i,
+			  res_inst[index], j,
+			  &short_server_id[index], sizeof(*short_server_id));
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Create LWM2M security instance: %d", obj_inst_id);
+
+	return &inst[index];
+}
+
+int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)
+{
+	int i;
+
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			return i;
+		}
+	}
+
+	return -ENOENT;
+}
+
+int lwm2m_security_index_to_inst_id(int index)
+{
+	if (index >= MAX_INSTANCE_COUNT) {
+		return -EINVAL;
+	}
+
+	/* not instanstiated */
+	if (!inst[index].obj) {
+		return -ENOENT;
+	}
+
+	return inst[index].obj_inst_id;
+}
+
+static int lwm2m_security_init(const struct device *dev)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	int ret = 0;
+
+	security.obj_id = LWM2M_OBJECT_SECURITY_ID;
+	security.fields = fields;
+	security.field_count = ARRAY_SIZE(fields);
+	security.max_instance_count = MAX_INSTANCE_COUNT;
+	security.create_cb = security_create;
+	lwm2m_register_obj(&security);
+
+	/* auto create the first instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_SECURITY_ID, 0, &obj_inst);
+	if (ret < 0) {
+		LOG_ERR("Create LWM2M security instance 0 error: %d", ret);
+	}
+
+	return ret;
+}
+
+SYS_INIT(lwm2m_security_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_server.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_server.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_obj_server.c	(working copy)
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_obj_server
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdint.h>
+#include <init.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
+#include "lwm2m_rd_client.h"
+#endif
+
+/* Server resource IDs */
+#define SERVER_SHORT_SERVER_ID		0
+#define SERVER_LIFETIME_ID		1
+#define SERVER_DEFAULT_MIN_PERIOD_ID	2
+#define SERVER_DEFAULT_MAX_PERIOD_ID	3
+#define SERVER_DISABLE_ID		4
+#define SERVER_DISABLE_TIMEOUT_ID	5
+#define SERVER_STORE_NOTIFY_ID		6
+#define SERVER_TRANSPORT_BINDING_ID	7
+#define SERVER_REG_UPDATE_TRIGGER_ID	8
+
+#define SERVER_MAX_ID			9
+
+/* Server flags */
+#define SERVER_FLAG_DISABLED		1
+#define SERVER_FLAG_STORE_NOTIFY	2
+
+#define MAX_INSTANCE_COUNT		CONFIG_LWM2M_SERVER_INSTANCE_COUNT
+
+#define TRANSPORT_BINDING_LEN		4
+
+/*
+ * Calculate resource instances as follows:
+ * start with SERVER_MAX_ID
+ * subtract EXEC resources (2)
+ */
+#define RESOURCE_INSTANCE_COUNT	(SERVER_MAX_ID - 2)
+
+/* resource state variables */
+static uint16_t server_id[MAX_INSTANCE_COUNT];
+static uint32_t lifetime[MAX_INSTANCE_COUNT];
+static uint32_t default_min_period[MAX_INSTANCE_COUNT];
+static uint32_t default_max_period[MAX_INSTANCE_COUNT];
+static uint8_t  server_flag_disabled[MAX_INSTANCE_COUNT];
+static uint32_t disabled_timeout[MAX_INSTANCE_COUNT];
+static uint8_t  server_flag_store_notify[MAX_INSTANCE_COUNT];
+static char  transport_binding[MAX_INSTANCE_COUNT][TRANSPORT_BINDING_LEN];
+
+static struct lwm2m_engine_obj server;
+static struct lwm2m_engine_obj_field fields[] = {
+	/*
+	 * LwM2M TS "E.2 LwM2M Object: LwM2M Server" page 107, describes
+	 * Short Server ID as READ-ONLY, but BOOTSTRAP server will attempt
+	 * to write it, so it needs to be RW
+	 */
+	OBJ_FIELD_DATA(SERVER_SHORT_SERVER_ID, RW, U16),
+	OBJ_FIELD_DATA(SERVER_LIFETIME_ID, RW, U32),
+	OBJ_FIELD_DATA(SERVER_DEFAULT_MIN_PERIOD_ID, RW_OPT, U32),
+	OBJ_FIELD_DATA(SERVER_DEFAULT_MAX_PERIOD_ID, RW_OPT, U32),
+	OBJ_FIELD_EXECUTE_OPT(SERVER_DISABLE_ID),
+	OBJ_FIELD_DATA(SERVER_DISABLE_TIMEOUT_ID, RW_OPT, U32),
+	OBJ_FIELD_DATA(SERVER_STORE_NOTIFY_ID, RW, BOOL),
+	/* Mark Transport Binding is RO but BOOTSTRAP needs to write it */
+	OBJ_FIELD_DATA(SERVER_TRANSPORT_BINDING_ID, RW, STRING),
+	OBJ_FIELD_EXECUTE(SERVER_REG_UPDATE_TRIGGER_ID),
+};
+
+static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
+static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SERVER_MAX_ID];
+static struct lwm2m_engine_res_inst
+			res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
+
+static int disable_cb(uint16_t obj_inst_id)
+{
+	int i;
+
+	LOG_DBG("DISABLE %d", obj_inst_id);
+	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			server_flag_disabled[i] = 1U;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static int update_trigger_cb(uint16_t obj_inst_id)
+{
+#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
+	engine_trigger_update();
+	return 0;
+#else
+	return -EPERM;
+#endif
+}
+
+static int32_t server_get_instance_s32(uint16_t obj_inst_id, int32_t *data,
+				     int32_t default_value)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(inst); i++) {
+		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
+			return data[i];
+		}
+	}
+
+	return default_value;
+}
+
+int32_t lwm2m_server_get_pmin(uint16_t obj_inst_id)
+{
+	return server_get_instance_s32(obj_inst_id, default_min_period,
+				       CONFIG_LWM2M_SERVER_DEFAULT_PMIN);
+}
+
+int32_t lwm2m_server_get_pmax(uint16_t obj_inst_id)
+{
+	return server_get_instance_s32(obj_inst_id, default_max_period,
+				       CONFIG_LWM2M_SERVER_DEFAULT_PMAX);
+}
+
+int lwm2m_server_short_id_to_inst(uint16_t short_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(inst); i++) {
+		if (inst[i].obj && server_id[i] == short_id) {
+			return inst[i].obj_inst_id;
+		}
+	}
+
+	return -ENOENT;
+}
+
+static struct lwm2m_engine_obj_inst *server_create(uint16_t obj_inst_id)
+{
+	int index, i = 0, j = 0;
+
+	/* Check that there is no other instance with this ID */
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
+			LOG_ERR("Can not create instance - "
+				"already existing: %u", obj_inst_id);
+			return NULL;
+		}
+	}
+
+	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
+		if (!inst[index].obj) {
+			break;
+		}
+	}
+
+	if (index >= MAX_INSTANCE_COUNT) {
+		LOG_ERR("Can not create instance - "
+			"no more room: %u", obj_inst_id);
+		return NULL;
+	}
+
+	/* Set default values */
+	server_flag_disabled[index] = 0U;
+	server_flag_store_notify[index] = 0U;
+	server_id[index] = index + 1;
+	lifetime[index] = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME;
+	default_min_period[index] = CONFIG_LWM2M_SERVER_DEFAULT_PMIN;
+	default_max_period[index] = CONFIG_LWM2M_SERVER_DEFAULT_PMAX;
+	disabled_timeout[index] = 86400U;
+	lwm2m_engine_get_binding(transport_binding[index]);
+
+	(void)memset(res[index], 0,
+		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
+	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
+
+	/* initialize instance resource data */
+	INIT_OBJ_RES_DATA(SERVER_SHORT_SERVER_ID, res[index], i,
+			  res_inst[index], j,
+			  &server_id[index], sizeof(*server_id));
+	INIT_OBJ_RES_DATA(SERVER_LIFETIME_ID, res[index], i,
+			  res_inst[index], j,
+			  &lifetime[index], sizeof(*lifetime));
+	INIT_OBJ_RES_DATA(SERVER_DEFAULT_MIN_PERIOD_ID, res[index], i,
+			  res_inst[index], j,
+			  &default_min_period[index],
+			  sizeof(*default_min_period));
+	INIT_OBJ_RES_DATA(SERVER_DEFAULT_MAX_PERIOD_ID, res[index], i,
+			  res_inst[index], j,
+			  &default_max_period[index],
+			  sizeof(*default_max_period));
+	INIT_OBJ_RES_EXECUTE(SERVER_DISABLE_ID, res[index], i, disable_cb);
+	INIT_OBJ_RES_DATA(SERVER_DISABLE_TIMEOUT_ID, res[index], i,
+			  res_inst[index], j,
+			  &disabled_timeout[index],
+			  sizeof(*disabled_timeout));
+	INIT_OBJ_RES_DATA(SERVER_STORE_NOTIFY_ID, res[index], i,
+			  res_inst[index], j,
+			  &server_flag_store_notify[index],
+			  sizeof(*server_flag_store_notify));
+	/* Mark Transport Binding RO as we only support UDP atm */
+	INIT_OBJ_RES_DATA(SERVER_TRANSPORT_BINDING_ID, res[index], i,
+			  res_inst[index], j,
+			  transport_binding[index], TRANSPORT_BINDING_LEN);
+	INIT_OBJ_RES_EXECUTE(SERVER_REG_UPDATE_TRIGGER_ID, res[index], i,
+			     update_trigger_cb);
+
+	inst[index].resources = res[index];
+	inst[index].resource_count = i;
+	LOG_DBG("Create LWM2M server instance: %d", obj_inst_id);
+	return &inst[index];
+}
+
+static int lwm2m_server_init(const struct device *dev)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	int ret = 0;
+
+	server.obj_id = LWM2M_OBJECT_SERVER_ID;
+	server.fields = fields;
+	server.field_count = ARRAY_SIZE(fields);
+	server.max_instance_count = MAX_INSTANCE_COUNT;
+	server.create_cb = server_create;
+	lwm2m_register_obj(&server);
+
+	/* auto create the first instance */
+	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_SERVER_ID, 0, &obj_inst);
+	if (ret < 0) {
+		LOG_ERR("Create LWM2M server instance 0 error: %d", ret);
+	}
+
+	return ret;
+}
+
+SYS_INIT(lwm2m_server_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_object.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_object.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_object.h	(working copy)
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+#ifndef LWM2M_OBJECT_H_
+#define LWM2M_OBJECT_H_
+
+/* stdint conversions */
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <kernel.h>
+
+#include <net/net_ip.h>
+#include <sys/printk.h>
+#include <sys/util.h>
+
+#include <net/coap.h>
+#include <net/lwm2m.h>
+
+#include "buf_util.h"
+
+/* #####/###/#####/### + NULL */
+#define MAX_RESOURCE_LEN	20
+
+/* operations / permissions */
+/* values from 0 to 7 can be used as permission checks */
+#define LWM2M_OP_READ		0
+#define LWM2M_OP_WRITE		1
+#define LWM2M_OP_CREATE		2
+#define LWM2M_OP_DELETE		3
+#define LWM2M_OP_EXECUTE	4
+#define LWM2M_FLAG_OPTIONAL	7
+/* values >7 aren't used for permission checks */
+#define LWM2M_OP_DISCOVER	8
+#define LWM2M_OP_WRITE_ATTR	9
+
+/* resource permissions */
+#define LWM2M_PERM_R		BIT(LWM2M_OP_READ)
+#define LWM2M_PERM_R_OPT	(BIT(LWM2M_OP_READ) | \
+				 BIT(LWM2M_FLAG_OPTIONAL))
+#define LWM2M_PERM_W		(BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE))
+#define LWM2M_PERM_W_OPT	(BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE) | \
+				 BIT(LWM2M_FLAG_OPTIONAL))
+#define LWM2M_PERM_X		BIT(LWM2M_OP_EXECUTE)
+#define LWM2M_PERM_X_OPT	(BIT(LWM2M_OP_EXECUTE) | \
+				 BIT(LWM2M_FLAG_OPTIONAL))
+#define LWM2M_PERM_RW		(BIT(LWM2M_OP_READ) | \
+				 BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE))
+#define LWM2M_PERM_RW_OPT	(BIT(LWM2M_OP_READ) | \
+				 BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE) | \
+				 BIT(LWM2M_FLAG_OPTIONAL))
+#define LWM2M_PERM_RWX		(BIT(LWM2M_OP_READ) | \
+				 BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE) | \
+				 BIT(LWM2M_OP_EXECUTE))
+#define LWM2M_PERM_RWX_OPT	(BIT(LWM2M_OP_READ) | \
+				 BIT(LWM2M_OP_WRITE) | \
+				 BIT(LWM2M_OP_CREATE) | \
+				 BIT(LWM2M_OP_EXECUTE) | \
+				 BIT(LWM2M_FLAG_OPTIONAL))
+
+#define LWM2M_HAS_PERM(of, p)	(((of)->permissions & p) == p)
+
+/* resource types */
+#define LWM2M_RES_TYPE_NONE	0
+#define LWM2M_RES_TYPE_OPAQUE	1
+#define LWM2M_RES_TYPE_STRING	2
+#define LWM2M_RES_TYPE_UINT64	3
+#define LWM2M_RES_TYPE_U64	3
+#define LWM2M_RES_TYPE_UINT	4
+#define LWM2M_RES_TYPE_U32	4
+#define LWM2M_RES_TYPE_U16	5
+#define LWM2M_RES_TYPE_U8	6
+#define LWM2M_RES_TYPE_INT64	7
+#define LWM2M_RES_TYPE_S64	7
+#define LWM2M_RES_TYPE_INT	8
+#define LWM2M_RES_TYPE_S32	8
+#define LWM2M_RES_TYPE_S16	9
+#define LWM2M_RES_TYPE_S8	10
+#define LWM2M_RES_TYPE_BOOL	11
+#define LWM2M_RES_TYPE_TIME	12
+#define LWM2M_RES_TYPE_FLOAT32	13
+#define LWM2M_RES_TYPE_FLOAT64	14
+#define LWM2M_RES_TYPE_OBJLNK	15
+
+/* remember that we have already output a value - can be between two block's */
+#define WRITER_OUTPUT_VALUE      1
+#define WRITER_RESOURCE_INSTANCE 2
+
+#define MAX_PACKET_SIZE		(CONFIG_LWM2M_COAP_BLOCK_SIZE + \
+				 CONFIG_LWM2M_ENGINE_MESSAGE_HEADER_SIZE)
+
+/* buffer util macros */
+#define CPKT_BUF_WRITE(cpkt)	(cpkt)->data, &(cpkt)->offset, (cpkt)->max_len
+#define CPKT_BUF_READ(cpkt)	(cpkt)->data, (cpkt)->max_len
+
+struct lwm2m_engine_obj;
+struct lwm2m_message;
+
+/* path representing object instances */
+struct lwm2m_obj_path {
+	uint16_t obj_id;
+	uint16_t obj_inst_id;
+	uint16_t res_id;
+	uint16_t res_inst_id;
+	uint8_t  level;  /* 0/1/2/3/4 (4 = resource instance) */
+};
+
+#define OBJ_FIELD(_id, _perm, _type) \
+	{ .res_id = _id, \
+	  .permissions = LWM2M_PERM_ ## _perm, \
+	  .data_type = LWM2M_RES_TYPE_ ## _type, }
+
+/* Keep OBJ_FIELD_DATA around for historical reasons */
+#define OBJ_FIELD_DATA(res_id, perm, type) \
+	OBJ_FIELD(res_id, perm, type)
+
+#define OBJ_FIELD_EXECUTE(res_id) \
+	OBJ_FIELD(res_id, X, NONE)
+
+#define OBJ_FIELD_EXECUTE_OPT(res_id) \
+	OBJ_FIELD(res_id, X_OPT, NONE)
+
+struct lwm2m_engine_obj_field {
+	uint16_t  res_id;
+	uint8_t   permissions;
+	uint8_t   data_type;
+};
+
+typedef struct lwm2m_engine_obj_inst *
+	(*lwm2m_engine_obj_create_cb_t)(uint16_t obj_inst_id);
+
+struct lwm2m_engine_obj {
+	/* object list */
+	sys_snode_t node;
+
+	/* object field definitions */
+	struct lwm2m_engine_obj_field *fields;
+
+	/* object event callbacks */
+	lwm2m_engine_obj_create_cb_t create_cb;
+	lwm2m_engine_user_cb_t delete_cb;
+	lwm2m_engine_user_cb_t user_create_cb;
+	lwm2m_engine_user_cb_t user_delete_cb;
+
+	/* object member data */
+	uint16_t obj_id;
+	uint16_t field_count;
+	uint16_t instance_count;
+	uint16_t max_instance_count;
+};
+
+/* Resource instances with this value are considered "not created" yet */
+#define RES_INSTANCE_NOT_CREATED 65535
+
+/* Resource macros */
+#define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, \
+		      _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
+	_r_ptr[_r_idx].res_id = _id; \
+	_r_ptr[_r_idx].res_instances = _ri_ptr; \
+	_r_ptr[_r_idx].res_inst_count = _ri_count; \
+	_r_ptr[_r_idx].read_cb = _r_cb; \
+	_r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \
+	_r_ptr[_r_idx].post_write_cb = _post_w_cb; \
+	_r_ptr[_r_idx].execute_cb = _ex_cb
+
+#define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
+			   _data_ptr, _data_len) \
+	do { \
+		if (_ri_ptr != NULL && _ri_count > 0) { \
+			for (int _i = 0; _i < _ri_count; _i++) { \
+				_ri_ptr[_ri_idx + _i].data_ptr = \
+						(_data_ptr + _i); \
+				_ri_ptr[_ri_idx + _i].max_data_len = \
+						_data_len; \
+				_ri_ptr[_ri_idx + _i].data_len = \
+						_data_len; \
+				if (_ri_create) { \
+					_ri_ptr[_ri_idx + _i].res_inst_id = \
+						_i; \
+				} else { \
+					_ri_ptr[_ri_idx + _i].res_inst_id = \
+						RES_INSTANCE_NOT_CREATED; \
+				} \
+			} \
+		} \
+		_ri_idx += _ri_count; \
+	} while (false)
+
+#define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \
+	do { \
+		if (_ri_count > 0) { \
+			for (int _i = 0; _i < _ri_count; _i++) { \
+				_ri_ptr[_ri_idx + _i].data_ptr = NULL; \
+				_ri_ptr[_ri_idx + _i].max_data_len = 0; \
+				_ri_ptr[_ri_idx + _i].data_len = 0; \
+				if (_ri_create) { \
+					_ri_ptr[_ri_idx + _i].res_inst_id = \
+						_i; \
+				} else { \
+					_ri_ptr[_ri_idx + _i].res_inst_id = \
+						RES_INSTANCE_NOT_CREATED; \
+				} \
+			} \
+		} \
+		_ri_idx += _ri_count; \
+	} while (false)
+
+#define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
+		     _ri_ptr, _ri_idx, _ri_count, _ri_create, \
+		     _data_ptr, _data_len, \
+		     _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
+	do { \
+		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
+			      (_ri_ptr + _ri_idx), _ri_count, \
+			      _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \
+		_INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \
+				   _data_ptr, _data_len); \
+	++_r_idx; \
+	} while (false)
+
+
+#define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
+			 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
+			 _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \
+	do { \
+		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
+			      (_ri_ptr + _ri_idx), _ri_count, \
+			      _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \
+		_INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \
+		++_r_idx; \
+	} while (false)
+
+#define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \
+				_ri_ptr, _ri_idx, _ri_count, _ri_create, \
+				_data_ptr, _data_len) \
+	INIT_OBJ_RES(_id, _r_ptr, _r_idx, \
+		     _ri_ptr, _ri_idx, _ri_count, _ri_create, \
+		     _data_ptr, _data_len, NULL, NULL, NULL, NULL)
+
+#define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \
+				   _ri_ptr, _ri_idx, _ri_count, _ri_create) \
+	INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \
+			 _ri_ptr, _ri_idx, _ri_count, _ri_create, \
+			 NULL, NULL, NULL, NULL)
+
+#define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \
+			  _data_ptr, _data_len) \
+	INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \
+		     _data_ptr, _data_len, NULL, NULL, NULL, NULL)
+
+#define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \
+	INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \
+			 NULL, NULL, NULL, NULL)
+
+#define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \
+	do { \
+		_INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, \
+			      NULL, NULL, NULL, _ex_cb); \
+		++_r_idx; \
+	} while (false)
+
+
+#define LWM2M_ATTR_PMIN	0
+#define LWM2M_ATTR_PMAX	1
+#define LWM2M_ATTR_GT	2
+#define LWM2M_ATTR_LT	3
+#define LWM2M_ATTR_STEP	4
+#define NR_LWM2M_ATTR	5
+
+/* TODO: support multiple server (sec 5.4.2) */
+struct lwm2m_attr {
+	void *ref;
+
+	/* values */
+	union {
+		float32_value_t float_val;
+		int32_t int_val;
+	};
+
+	uint8_t type;
+};
+
+struct lwm2m_engine_res_inst {
+	void  *data_ptr;
+	uint16_t max_data_len;
+	uint16_t data_len;
+	uint16_t res_inst_id; /* 65535 == not "created" */
+	uint8_t  data_flags;
+};
+
+struct lwm2m_engine_res {
+	lwm2m_engine_get_data_cb_t		read_cb;
+	lwm2m_engine_get_data_cb_t		pre_write_cb;
+	lwm2m_engine_set_data_cb_t		post_write_cb;
+	lwm2m_engine_user_cb_t			execute_cb;
+
+	struct lwm2m_engine_res_inst *res_instances;
+	uint16_t res_id;
+	uint8_t  res_inst_count;
+};
+
+struct lwm2m_engine_obj_inst {
+	/* instance list */
+	sys_snode_t node;
+
+	struct lwm2m_engine_obj *obj;
+	struct lwm2m_engine_res *resources;
+
+	/* object instance member data */
+	uint16_t obj_inst_id;
+	uint16_t resource_count;
+};
+
+/* Initialize resource instances prior to use */
+static inline void init_res_instance(struct lwm2m_engine_res_inst *ri,
+				     size_t ri_len)
+{
+	size_t i;
+
+	memset(ri, 0, sizeof(*ri) * ri_len);
+	for (i = 0; i < ri_len; i++) {
+		ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED;
+	}
+}
+
+struct lwm2m_opaque_context {
+	size_t len;
+	size_t remaining;
+};
+
+struct lwm2m_block_context {
+	struct coap_block_context ctx;
+	struct lwm2m_opaque_context opaque;
+	int64_t timestamp;
+	uint32_t expected;
+	uint8_t token[8];
+	uint8_t tkl;
+	bool last_block : 1;
+};
+
+struct lwm2m_output_context {
+	const struct lwm2m_writer *writer;
+	struct coap_packet *out_cpkt;
+
+	/* private output data */
+	void *user_data;
+};
+
+struct lwm2m_input_context {
+	const struct lwm2m_reader *reader;
+	struct coap_packet *in_cpkt;
+
+	/* current position in buffer */
+	uint16_t offset;
+
+	/* Corresponding block context. NULL if block transfer is not used. */
+	struct lwm2m_block_context *block_ctx;
+
+	/* private output data */
+	void *user_data;
+};
+
+/* Establish a message timeout callback */
+typedef void (*lwm2m_message_timeout_cb_t)(struct lwm2m_message *msg);
+
+/* Internal LwM2M message structure to track in-flight messages. */
+struct lwm2m_message {
+	/** LwM2M context related to this message */
+	struct lwm2m_ctx *ctx;
+
+	/** Incoming / outgoing contexts */
+	struct lwm2m_input_context in;
+	struct lwm2m_output_context out;
+
+	/** Incoming path */
+	struct lwm2m_obj_path path;
+
+	/** CoAP packet data related to the outgoing message */
+	struct coap_packet cpkt;
+
+	/** Buffer data related outgoing message */
+	uint8_t msg_data[MAX_PACKET_SIZE];
+
+	/** Message transmission handling for TYPE_CON */
+	struct coap_pending *pending;
+	struct coap_reply *reply;
+
+	/** Message configuration */
+	uint8_t *token;
+	coap_reply_t reply_cb;
+	lwm2m_message_timeout_cb_t message_timeout_cb;
+	uint16_t mid;
+	uint8_t type;
+	uint8_t code;
+	uint8_t tkl;
+
+	/** Incoming message action */
+	uint8_t operation;
+
+	/** Counter for message re-send / abort handling */
+	uint8_t send_attempts;
+};
+
+/* LWM2M format writer for the various formats supported */
+struct lwm2m_writer {
+	size_t (*put_begin)(struct lwm2m_output_context *out,
+			    struct lwm2m_obj_path *path);
+	size_t (*put_end)(struct lwm2m_output_context *out,
+			  struct lwm2m_obj_path *path);
+	size_t (*put_begin_oi)(struct lwm2m_output_context *out,
+			       struct lwm2m_obj_path *path);
+	size_t (*put_end_oi)(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path);
+	size_t (*put_begin_r)(struct lwm2m_output_context *out,
+			      struct lwm2m_obj_path *path);
+	size_t (*put_end_r)(struct lwm2m_output_context *out,
+			    struct lwm2m_obj_path *path);
+	size_t (*put_begin_ri)(struct lwm2m_output_context *out,
+			       struct lwm2m_obj_path *path);
+	size_t (*put_end_ri)(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path);
+	size_t (*put_s8)(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 int8_t value);
+	size_t (*put_s16)(struct lwm2m_output_context *out,
+			  struct lwm2m_obj_path *path,
+			  int16_t value);
+	size_t (*put_s32)(struct lwm2m_output_context *out,
+			  struct lwm2m_obj_path *path,
+			  int32_t value);
+	size_t (*put_s64)(struct lwm2m_output_context *out,
+			  struct lwm2m_obj_path *path,
+			  int64_t value);
+	size_t (*put_string)(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     char *buf, size_t buflen);
+	size_t (*put_float32fix)(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float32_value_t *value);
+	size_t (*put_float64fix)(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float64_value_t *value);
+	size_t (*put_bool)(struct lwm2m_output_context *out,
+			   struct lwm2m_obj_path *path,
+			   bool value);
+	size_t (*put_opaque)(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     char *buf, size_t buflen);
+	size_t (*put_objlnk)(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     struct lwm2m_objlnk *value);
+};
+
+struct lwm2m_reader {
+	size_t (*get_s32)(struct lwm2m_input_context *in,
+			  int32_t *value);
+	size_t (*get_s64)(struct lwm2m_input_context *in,
+			  int64_t *value);
+	size_t (*get_string)(struct lwm2m_input_context *in,
+			     uint8_t *buf, size_t buflen);
+	size_t (*get_float32fix)(struct lwm2m_input_context *in,
+				 float32_value_t *value);
+	size_t (*get_float64fix)(struct lwm2m_input_context *in,
+				 float64_value_t *value);
+	size_t (*get_bool)(struct lwm2m_input_context *in,
+			   bool *value);
+	size_t (*get_opaque)(struct lwm2m_input_context *in,
+			     uint8_t *buf, size_t buflen,
+			     struct lwm2m_opaque_context *opaque,
+			     bool *last_block);
+	size_t (*get_objlnk)(struct lwm2m_input_context *in,
+			     struct lwm2m_objlnk *value);
+};
+
+/* output user_data management functions */
+
+static inline void engine_set_out_user_data(struct lwm2m_output_context *out,
+					    void *user_data)
+{
+	out->user_data = user_data;
+}
+
+static inline void *engine_get_out_user_data(struct lwm2m_output_context *out)
+{
+	return out->user_data;
+}
+
+static inline void
+engine_clear_out_user_data(struct lwm2m_output_context *out)
+{
+	out->user_data = NULL;
+}
+
+static inline void engine_set_in_user_data(struct lwm2m_input_context *in,
+					   void *user_data)
+{
+	in->user_data = user_data;
+}
+
+static inline void *engine_get_in_user_data(struct lwm2m_input_context *in)
+{
+	return in->user_data;
+}
+
+static inline void
+engine_clear_in_user_data(struct lwm2m_input_context *in)
+{
+	in->user_data = NULL;
+}
+
+/* inline multi-format write / read functions */
+
+static inline size_t engine_put_begin(struct lwm2m_output_context *out,
+				      struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_begin) {
+		return out->writer->put_begin(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_end(struct lwm2m_output_context *out,
+				    struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_end) {
+		return out->writer->put_end(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_begin_oi(struct lwm2m_output_context *out,
+					 struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_begin_oi) {
+		return out->writer->put_begin_oi(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_end_oi(struct lwm2m_output_context *out,
+				       struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_end_oi) {
+		return out->writer->put_end_oi(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_begin_r(struct lwm2m_output_context *out,
+					struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_begin_r) {
+		return out->writer->put_begin_r(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_end_r(struct lwm2m_output_context *out,
+				      struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_end_r) {
+		return out->writer->put_end_r(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_begin_ri(struct lwm2m_output_context *out,
+					 struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_begin_ri) {
+		return out->writer->put_begin_ri(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_end_ri(struct lwm2m_output_context *out,
+				       struct lwm2m_obj_path *path)
+{
+	if (out->writer->put_end_ri) {
+		return out->writer->put_end_ri(out, path);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_s8(struct lwm2m_output_context *out,
+				   struct lwm2m_obj_path *path,
+				   int8_t value)
+{
+	return out->writer->put_s8(out, path, value);
+}
+
+static inline size_t engine_put_s16(struct lwm2m_output_context *out,
+				    struct lwm2m_obj_path *path,
+				    int16_t value)
+{
+	return out->writer->put_s16(out, path, value);
+}
+
+static inline size_t engine_put_s32(struct lwm2m_output_context *out,
+				    struct lwm2m_obj_path *path,
+				    int32_t value)
+{
+	return out->writer->put_s32(out, path, value);
+}
+
+static inline size_t engine_put_s64(struct lwm2m_output_context *out,
+				    struct lwm2m_obj_path *path,
+				    int64_t value)
+{
+	return out->writer->put_s64(out, path, value);
+}
+
+static inline size_t engine_put_string(struct lwm2m_output_context *out,
+				       struct lwm2m_obj_path *path,
+				       char *buf, size_t buflen)
+{
+	return out->writer->put_string(out, path, buf, buflen);
+}
+
+static inline size_t engine_put_float32fix(struct lwm2m_output_context *out,
+					   struct lwm2m_obj_path *path,
+					   float32_value_t *value)
+{
+	return out->writer->put_float32fix(out, path, value);
+}
+
+static inline size_t engine_put_float64fix(struct lwm2m_output_context *out,
+					   struct lwm2m_obj_path *path,
+					   float64_value_t *value)
+{
+	return out->writer->put_float64fix(out, path, value);
+}
+
+static inline size_t engine_put_bool(struct lwm2m_output_context *out,
+				     struct lwm2m_obj_path *path,
+				     bool value)
+{
+	return out->writer->put_bool(out, path, value);
+}
+
+static inline size_t engine_put_opaque(struct lwm2m_output_context *out,
+				       struct lwm2m_obj_path *path,
+				       char *buf, size_t buflen)
+{
+	if (out->writer->put_opaque) {
+		return out->writer->put_opaque(out, path, buf, buflen);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_put_objlnk(struct lwm2m_output_context *out,
+				       struct lwm2m_obj_path *path,
+				       struct lwm2m_objlnk *value)
+{
+	return out->writer->put_objlnk(out, path, value);
+}
+
+static inline size_t engine_get_s32(struct lwm2m_input_context *in,
+				    int32_t *value)
+{
+	return in->reader->get_s32(in, value);
+}
+
+static inline size_t engine_get_s64(struct lwm2m_input_context *in,
+				    int64_t *value)
+{
+	return in->reader->get_s64(in, value);
+}
+
+static inline size_t engine_get_string(struct lwm2m_input_context *in,
+				       uint8_t *buf, size_t buflen)
+{
+	return in->reader->get_string(in, buf, buflen);
+}
+
+static inline size_t engine_get_float32fix(struct lwm2m_input_context *in,
+					   float32_value_t *value)
+{
+	return in->reader->get_float32fix(in, value);
+}
+
+static inline size_t engine_get_float64fix(struct lwm2m_input_context *in,
+					   float64_value_t *value)
+{
+	return in->reader->get_float64fix(in, value);
+}
+
+static inline size_t engine_get_bool(struct lwm2m_input_context *in,
+				     bool *value)
+{
+	return in->reader->get_bool(in, value);
+}
+
+static inline size_t engine_get_opaque(struct lwm2m_input_context *in,
+				       uint8_t *buf, size_t buflen,
+				       struct lwm2m_opaque_context *opaque,
+				       bool *last_block)
+{
+	if (in->reader->get_opaque) {
+		return in->reader->get_opaque(in, buf, buflen,
+					      opaque, last_block);
+	}
+
+	return 0;
+}
+
+static inline size_t engine_get_objlnk(struct lwm2m_input_context *in,
+				       struct lwm2m_objlnk *value)
+{
+	return in->reader->get_objlnk(in, value);
+}
+
+#endif /* LWM2M_OBJECT_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.h	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2016, SICS Swedish ICT AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LWM2M_RD_CLIENT_H
+#define LWM2M_RD_CLIENT_H
+
+void engine_trigger_restart(void);
+void engine_trigger_update(void);
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+void engine_bootstrap_finish(void);
+#endif
+
+void engine_update_tx_time(void);
+
+#endif /* LWM2M_RD_CLIENT_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rd_client.c	(working copy)
@@ -0,0 +1,982 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2017-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ *         Joel Hoglund <joel@sics.se>
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_rd_client
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <init.h>
+#include <sys/printk.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_engine.h"
+
+#define LWM2M_RD_CLIENT_URI "rd"
+
+#define SECONDS_TO_UPDATE_EARLY	CONFIG_LWM2M_SECONDS_TO_UPDATE_EARLY
+#define STATE_MACHINE_UPDATE_INTERVAL_MS 500
+
+#define CLIENT_EP_LEN		CONFIG_LWM2M_RD_CLIENT_ENDPOINT_NAME_MAX_LENGTH
+
+/* Up to 3 characters + NULL */
+#define CLIENT_BINDING_LEN sizeof("UQS")
+
+/* The states for the RD client state machine */
+/*
+ * When node is unregistered it ends up in UNREGISTERED
+ * and this is going to be there until use X or Y kicks it
+ * back into INIT again
+ */
+enum sm_engine_state {
+	ENGINE_IDLE,
+	ENGINE_INIT,
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+	ENGINE_DO_BOOTSTRAP_REG,
+	ENGINE_BOOTSTRAP_REG_SENT,
+	ENGINE_BOOTSTRAP_REG_DONE,
+	ENGINE_BOOTSTRAP_TRANS_DONE,
+#endif
+	ENGINE_DO_REGISTRATION,
+	ENGINE_REGISTRATION_SENT,
+	ENGINE_REGISTRATION_DONE,
+	ENGINE_REGISTRATION_DONE_RX_OFF,
+	ENGINE_UPDATE_SENT,
+	ENGINE_DEREGISTER,
+	ENGINE_DEREGISTER_SENT,
+	ENGINE_DEREGISTER_FAILED,
+	ENGINE_DEREGISTERED
+};
+
+struct lwm2m_rd_client_info {
+	uint32_t lifetime;
+	struct lwm2m_ctx *ctx;
+	uint8_t engine_state;
+	uint8_t use_bootstrap;
+	uint8_t trigger_update;
+
+	int64_t last_update;
+	int64_t last_tx;
+
+	char ep_name[CLIENT_EP_LEN];
+	char server_ep[CLIENT_EP_LEN];
+
+	lwm2m_ctx_event_cb_t event_cb;
+} client;
+
+/* buffers */
+static char query_buffer[64]; /* allocate some data for queries and updates */
+static uint8_t client_data[256]; /* allocate some data for the RD */
+
+void engine_update_tx_time(void)
+{
+	client.last_tx = k_uptime_get();
+}
+
+static void set_sm_state(uint8_t sm_state)
+{
+	enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE;
+
+	/* Determine if a callback to the app is needed */
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+	if (sm_state == ENGINE_BOOTSTRAP_REG_DONE) {
+		event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE;
+	} else if (client.engine_state == ENGINE_BOOTSTRAP_TRANS_DONE &&
+		   sm_state == ENGINE_DO_REGISTRATION) {
+		event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE;
+	} else
+#endif
+	if (client.engine_state == ENGINE_UPDATE_SENT &&
+	    sm_state == ENGINE_REGISTRATION_DONE) {
+		event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE;
+	} else if (sm_state == ENGINE_REGISTRATION_DONE) {
+		event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE;
+	} else if (sm_state == ENGINE_REGISTRATION_DONE_RX_OFF) {
+		event = LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF;
+	} else if ((sm_state == ENGINE_INIT ||
+		    sm_state == ENGINE_DEREGISTERED) &&
+		   (client.engine_state >= ENGINE_DO_REGISTRATION &&
+		    client.engine_state <= ENGINE_DEREGISTER_SENT)) {
+		event = LWM2M_RD_CLIENT_EVENT_DISCONNECT;
+	}
+
+	/* TODO: add locking? */
+	client.engine_state = sm_state;
+
+	if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
+		client.event_cb(client.ctx, event);
+	}
+}
+
+static bool sm_is_registered(void)
+{
+	return (client.engine_state >= ENGINE_REGISTRATION_DONE &&
+		client.engine_state <= ENGINE_DEREGISTER_FAILED);
+}
+
+static uint8_t get_sm_state(void)
+{
+	/* TODO: add locking? */
+	return client.engine_state;
+}
+
+static void sm_handle_timeout_state(struct lwm2m_message *msg,
+				    enum sm_engine_state sm_state)
+{
+	enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE;
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+	if (client.engine_state == ENGINE_BOOTSTRAP_REG_SENT) {
+		event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE;
+	} else
+#endif
+	if (client.engine_state == ENGINE_REGISTRATION_SENT) {
+		event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE;
+	} else if (client.engine_state == ENGINE_UPDATE_SENT) {
+		event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE;
+	} else if (client.engine_state == ENGINE_DEREGISTER_SENT) {
+		event = LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE;
+	} else {
+		/* TODO: unknown timeout state */
+	}
+
+	set_sm_state(sm_state);
+
+	if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
+		client.event_cb(client.ctx, event);
+	}
+}
+
+/* force state machine restart */
+void engine_trigger_restart(void)
+{
+	lwm2m_engine_context_close(client.ctx);
+
+	client.ctx->sec_obj_inst = -1;
+
+	/* Jump directly to the registration phase. In case there is no valid
+	 * security object for the LWM2M server, it will fall back to the
+	 * bootstrap procedure.
+	 */
+	set_sm_state(ENGINE_DO_REGISTRATION);
+}
+
+/* force re-update with remote peer */
+void engine_trigger_update(void)
+{
+	/* TODO: add locking? */
+	client.trigger_update = 1U;
+}
+
+/* state machine reply callbacks */
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+static int do_bootstrap_reply_cb(const struct coap_packet *response,
+				 struct coap_reply *reply,
+				 const struct sockaddr *from)
+{
+	uint8_t code;
+
+	code = coap_header_get_code(response);
+	LOG_DBG("Bootstrap callback (code:%u.%u)",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+
+	if (code == COAP_RESPONSE_CODE_CHANGED) {
+		LOG_INF("Bootstrap registration done!");
+		set_sm_state(ENGINE_BOOTSTRAP_REG_DONE);
+	} else if (code == COAP_RESPONSE_CODE_NOT_FOUND) {
+		/* TODO: try and find another bootstrap server entry? */
+		LOG_ERR("Failed: NOT_FOUND.  Not Retrying.");
+		set_sm_state(ENGINE_DO_REGISTRATION);
+	} else if (code == COAP_RESPONSE_CODE_FORBIDDEN) {
+		/* TODO: try and find another bootstrap server entry? */
+		LOG_ERR("Failed: 4.03 - Forbidden.  Not Retrying.");
+		set_sm_state(ENGINE_DO_REGISTRATION);
+	} else {
+		/* TODO: Read payload for error message? */
+		LOG_ERR("Failed with code %u.%u. Retrying ...",
+			COAP_RESPONSE_CODE_CLASS(code),
+			COAP_RESPONSE_CODE_DETAIL(code));
+		set_sm_state(ENGINE_INIT);
+	}
+
+	return 0;
+}
+
+static void do_bootstrap_reg_timeout_cb(struct lwm2m_message *msg)
+{
+	LOG_WRN("Bootstrap Timeout");
+
+	/* TODO:
+	 * Look for the "next" BOOTSTRAP server entry in our security info
+	 */
+
+	/* Restart from scratch */
+	sm_handle_timeout_state(msg, ENGINE_INIT);
+}
+#endif
+
+static int do_registration_reply_cb(const struct coap_packet *response,
+				    struct coap_reply *reply,
+				    const struct sockaddr *from)
+{
+	struct coap_option options[2];
+	uint8_t code;
+	int ret;
+
+	code = coap_header_get_code(response);
+	LOG_DBG("Registration callback (code:%u.%u)",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+
+	/* check state and possibly set registration to done */
+	if (code == COAP_RESPONSE_CODE_CREATED) {
+		ret = coap_find_options(response, COAP_OPTION_LOCATION_PATH,
+					options, 2);
+		if (ret < 2) {
+			LOG_ERR("Unexpected endpoint data returned.");
+			return -EINVAL;
+		}
+
+		/* option[0] should be "rd" */
+
+		if (options[1].len + 1 > sizeof(client.server_ep)) {
+			LOG_ERR("Unexpected length of query: "
+				    "%u (expected %zu)\n",
+				    options[1].len,
+				    sizeof(client.server_ep));
+			return -EINVAL;
+		}
+
+		memcpy(client.server_ep, options[1].value,
+		       options[1].len);
+		client.server_ep[options[1].len] = '\0';
+		set_sm_state(ENGINE_REGISTRATION_DONE);
+		LOG_INF("Registration Done (EP='%s')",
+			log_strdup(client.server_ep));
+
+		return 0;
+	} else if (code == COAP_RESPONSE_CODE_NOT_FOUND) {
+		LOG_ERR("Failed: NOT_FOUND.  Not Retrying.");
+		set_sm_state(ENGINE_REGISTRATION_DONE);
+		return 0;
+	} else if (code == COAP_RESPONSE_CODE_FORBIDDEN) {
+		LOG_ERR("Failed: 4.03 - Forbidden.  Not Retrying.");
+		set_sm_state(ENGINE_REGISTRATION_DONE);
+		return 0;
+	}
+
+	/* TODO: Read payload for error message? */
+	/* Possible error response codes: 4.00 Bad request */
+	LOG_ERR("failed with code %u.%u. Re-init network",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+
+	set_sm_state(ENGINE_INIT);
+	return 0;
+}
+
+static void do_registration_timeout_cb(struct lwm2m_message *msg)
+{
+	LOG_WRN("Registration Timeout");
+
+	/* Restart from scratch */
+	sm_handle_timeout_state(msg, ENGINE_INIT);
+}
+
+static int do_update_reply_cb(const struct coap_packet *response,
+			      struct coap_reply *reply,
+			      const struct sockaddr *from)
+{
+	uint8_t code;
+
+	code = coap_header_get_code(response);
+	LOG_INF("Update callback (code:%u.%u)",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+
+	/* If NOT_FOUND just continue on */
+	if ((code == COAP_RESPONSE_CODE_CHANGED) ||
+	    (code == COAP_RESPONSE_CODE_CREATED)) {
+		set_sm_state(ENGINE_REGISTRATION_DONE);
+		LOG_INF("Update Done");
+		return 0;
+	}
+
+	/* TODO: Read payload for error message? */
+	/* Possible error response codes: 4.00 Bad request & 4.04 Not Found */
+	LOG_ERR("Failed with code %u.%u. Retrying registration",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+	set_sm_state(ENGINE_DO_REGISTRATION);
+
+	return 0;
+}
+
+static void do_update_timeout_cb(struct lwm2m_message *msg)
+{
+	LOG_WRN("Registration Update Timeout");
+
+	/* Re-do registration */
+	sm_handle_timeout_state(msg, ENGINE_DO_REGISTRATION);
+}
+
+static int do_deregister_reply_cb(const struct coap_packet *response,
+				  struct coap_reply *reply,
+				  const struct sockaddr *from)
+{
+	uint8_t code;
+
+	code = coap_header_get_code(response);
+	LOG_DBG("Deregister callback (code:%u.%u)",
+		COAP_RESPONSE_CODE_CLASS(code),
+		COAP_RESPONSE_CODE_DETAIL(code));
+
+	if (code == COAP_RESPONSE_CODE_DELETED) {
+		LOG_INF("Deregistration success");
+		lwm2m_engine_context_close(client.ctx);
+		set_sm_state(ENGINE_DEREGISTERED);
+	} else {
+		LOG_ERR("failed with code %u.%u",
+			COAP_RESPONSE_CODE_CLASS(code),
+			COAP_RESPONSE_CODE_DETAIL(code));
+		if (get_sm_state() == ENGINE_DEREGISTER_SENT) {
+			set_sm_state(ENGINE_DEREGISTER_FAILED);
+		}
+	}
+
+	return 0;
+}
+
+static void do_deregister_timeout_cb(struct lwm2m_message *msg)
+{
+	LOG_WRN("De-Registration Timeout");
+
+	/* Abort de-registration and start from scratch */
+	sm_handle_timeout_state(msg, ENGINE_INIT);
+}
+
+static bool sm_bootstrap_verify(bool bootstrap_server, int sec_obj_inst)
+{
+	char pathstr[MAX_RESOURCE_LEN];
+	bool bootstrap;
+	int ret;
+
+	snprintk(pathstr, sizeof(pathstr), "0/%d/1", sec_obj_inst);
+	ret = lwm2m_engine_get_bool(pathstr, &bootstrap);
+	if (ret < 0) {
+		LOG_WRN("Failed to check bootstrap, err %d", ret);
+		return false;
+	}
+
+	if (bootstrap == bootstrap_server) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void sm_update_lifetime(int srv_obj_inst, uint32_t *lifetime)
+{
+	char pathstr[MAX_RESOURCE_LEN];
+
+	snprintk(pathstr, sizeof(pathstr), "1/%d/1", srv_obj_inst);
+	if (lwm2m_engine_get_u32(pathstr, lifetime) < 0) {
+		*lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME;
+		LOG_INF("Using default lifetime: %u", *lifetime);
+	}
+}
+
+static int sm_select_server_inst(int sec_obj_inst, int *srv_obj_inst,
+				 uint32_t *lifetime)
+{
+	char pathstr[MAX_RESOURCE_LEN];
+	uint16_t server_id;
+	int ret, obj_inst_id;
+
+	snprintk(pathstr, sizeof(pathstr), "0/%d/10", sec_obj_inst);
+	ret = lwm2m_engine_get_u16(pathstr, &server_id);
+	if (ret < 0) {
+		LOG_WRN("Failed to obtain Short Server ID, err %d", ret);
+		return -EINVAL;
+	}
+
+	obj_inst_id = lwm2m_server_short_id_to_inst(server_id);
+	if (obj_inst_id < 0) {
+		LOG_WRN("Failed to obtain Server Object instance, err %d",
+			obj_inst_id);
+		return -EINVAL;
+	}
+
+	*srv_obj_inst = obj_inst_id;
+	sm_update_lifetime(*srv_obj_inst, lifetime);
+
+	return 0;
+}
+
+static int sm_select_security_inst(bool bootstrap_server, int *sec_obj_inst)
+{
+	int i, obj_inst_id = -1;
+
+	/* lookup existing index */
+	i = lwm2m_security_inst_id_to_index(*sec_obj_inst);
+	if (i >= 0 && sm_bootstrap_verify(bootstrap_server, *sec_obj_inst)) {
+		return 0;
+	}
+
+	*sec_obj_inst = -1;
+
+	/* Iterate over all instances to find the correct one. */
+	for (i = 0; i < CONFIG_LWM2M_SECURITY_INSTANCE_COUNT; i++) {
+		obj_inst_id = lwm2m_security_index_to_inst_id(i);
+		if (obj_inst_id < 0) {
+			LOG_WRN("Failed to get inst id for %d", i);
+			continue;
+		}
+
+		if (sm_bootstrap_verify(bootstrap_server, obj_inst_id)) {
+			*sec_obj_inst = obj_inst_id;
+			return 0;
+		}
+	}
+
+	LOG_WRN("sec_obj_inst: No matching servers found.");
+
+	return -ENOENT;
+}
+
+/* state machine step functions */
+
+static int sm_do_init(void)
+{
+	client.ctx->sec_obj_inst = -1;
+	client.ctx->srv_obj_inst = -1;
+	client.trigger_update = 0U;
+	client.lifetime = 0U;
+
+	/* Do bootstrap or registration */
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+	if (client.use_bootstrap) {
+		set_sm_state(ENGINE_DO_BOOTSTRAP_REG);
+	} else {
+		set_sm_state(ENGINE_DO_REGISTRATION);
+	}
+#else
+	set_sm_state(ENGINE_DO_REGISTRATION);
+#endif
+	return 0;
+}
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+static int sm_do_bootstrap_reg(void)
+{
+	struct lwm2m_message *msg;
+	int ret;
+
+	/* clear out existing connection data */
+	if (client.ctx->sock_fd > -1) {
+		lwm2m_engine_context_close(client.ctx);
+	}
+
+	client.ctx->bootstrap_mode = true;
+	ret = sm_select_security_inst(client.ctx->bootstrap_mode,
+				      &client.ctx->sec_obj_inst);
+	if (ret < 0) {
+		/* no bootstrap server found, let's move to registration */
+		LOG_WRN("Bootstrap server not found! Try normal registration.");
+		set_sm_state(ENGINE_DO_REGISTRATION);
+		return ret;
+	}
+
+	LOG_INF("Bootstrap started with endpoint '%s' with client lifetime %d",
+		log_strdup(client.ep_name), client.lifetime);
+
+	ret = lwm2m_engine_start(client.ctx);
+	if (ret < 0) {
+		LOG_ERR("Cannot init LWM2M engine (%d)", ret);
+		return ret;
+	}
+
+	msg = lwm2m_get_message(client.ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		ret = -ENOMEM;
+		goto cleanup_engine;
+	}
+
+	msg->type = COAP_TYPE_CON;
+	msg->code = COAP_METHOD_POST;
+	msg->mid = coap_next_id();
+	msg->tkl = LWM2M_MSG_TOKEN_GENERATE_NEW;
+	msg->reply_cb = do_bootstrap_reply_cb;
+	msg->message_timeout_cb = do_bootstrap_reg_timeout_cb;
+
+	ret = lwm2m_init_message(msg);
+	if (ret) {
+		goto cleanup;
+	}
+
+	/* TODO: handle return error */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+				  "bs", strlen("bs"));
+
+	snprintk(query_buffer, sizeof(query_buffer) - 1, "ep=%s",
+		 client.ep_name);
+	/* TODO: handle return error */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
+				  query_buffer, strlen(query_buffer));
+
+	/* log the bootstrap attempt */
+	LOG_DBG("Register ID with bootstrap server as '%s'",
+		log_strdup(query_buffer));
+
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).",
+			    ret);
+		goto cleanup;
+	}
+
+	set_sm_state(ENGINE_BOOTSTRAP_REG_SENT);
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+cleanup_engine:
+	lwm2m_engine_context_close(client.ctx);
+	return ret;
+}
+
+void engine_bootstrap_finish(void)
+{
+	LOG_INF("Bootstrap data transfer done!");
+	set_sm_state(ENGINE_BOOTSTRAP_TRANS_DONE);
+}
+
+static int sm_bootstrap_trans_done(void)
+{
+	/* close down context resources */
+	lwm2m_engine_context_close(client.ctx);
+
+	/* reset security object instance */
+	client.ctx->sec_obj_inst = -1;
+
+	set_sm_state(ENGINE_DO_REGISTRATION);
+
+	return 0;
+}
+#endif
+
+static int sm_send_registration(bool send_obj_support_data,
+				coap_reply_t reply_cb,
+				lwm2m_message_timeout_cb_t timeout_cb)
+{
+	struct lwm2m_message *msg;
+	uint16_t client_data_len;
+	int ret;
+	char binding[CLIENT_BINDING_LEN];
+
+	msg = lwm2m_get_message(client.ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		return -ENOMEM;
+	}
+
+	/* remember the last reg time */
+	client.last_update = k_uptime_get();
+
+	msg->type = COAP_TYPE_CON;
+	msg->code = COAP_METHOD_POST;
+	msg->mid = coap_next_id();
+	msg->tkl = LWM2M_MSG_TOKEN_GENERATE_NEW;
+	msg->reply_cb = reply_cb;
+	msg->message_timeout_cb = timeout_cb;
+
+	ret = lwm2m_init_message(msg);
+	if (ret) {
+		goto cleanup;
+	}
+
+	/* TODO: handle return error */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+				  LWM2M_RD_CLIENT_URI,
+				  strlen(LWM2M_RD_CLIENT_URI));
+
+	if (!sm_is_registered()) {
+		/* include client endpoint in URI QUERY on 1st registration */
+		coap_append_option_int(&msg->cpkt, COAP_OPTION_CONTENT_FORMAT,
+				       LWM2M_FORMAT_APP_LINK_FORMAT);
+		snprintk(query_buffer, sizeof(query_buffer) - 1,
+			 "lwm2m=%s", LWM2M_PROTOCOL_VERSION);
+		/* TODO: handle return error */
+		coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
+					  query_buffer, strlen(query_buffer));
+		snprintk(query_buffer, sizeof(query_buffer) - 1,
+			 "ep=%s", client.ep_name);
+		/* TODO: handle return error */
+		coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
+					  query_buffer, strlen(query_buffer));
+	} else {
+		/* include server endpoint in URI PATH otherwise */
+		/* TODO: handle return error */
+		coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+					  client.server_ep,
+					  strlen(client.server_ep));
+	}
+
+	snprintk(query_buffer, sizeof(query_buffer) - 1,
+		 "lt=%d", client.lifetime);
+	/* TODO: handle return error */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
+				  query_buffer, strlen(query_buffer));
+
+	lwm2m_engine_get_binding(binding);
+	/* UDP is a default binding, no need to add option if UDP is used. */
+	if (strcmp(binding, "U") != 0) {
+		snprintk(query_buffer, sizeof(query_buffer) - 1,
+			 "b=%s", binding);
+		/* TODO: handle return error */
+		coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
+					  query_buffer, strlen(query_buffer));
+	}
+
+	if (send_obj_support_data) {
+		ret = coap_packet_append_payload_marker(&msg->cpkt);
+		if (ret < 0) {
+			goto cleanup;
+		}
+
+		/* generate the rd data */
+		client_data_len = lwm2m_get_rd_data(client_data,
+						    sizeof(client_data));
+		ret = buf_append(CPKT_BUF_WRITE(&msg->cpkt), client_data,
+				 client_data_len);
+		if (ret < 0) {
+			goto cleanup;
+		}
+	}
+
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
+		goto cleanup;
+	}
+
+	/* log the registration attempt */
+	LOG_DBG("registration sent [%s]",
+		log_strdup(lwm2m_sprint_ip_addr(&client.ctx->remote_addr)));
+
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+	return ret;
+}
+
+static int sm_do_registration(void)
+{
+	int ret = 0;
+
+	/* clear out existing connection data */
+	if (client.ctx->sock_fd > -1) {
+		lwm2m_engine_context_close(client.ctx);
+	}
+
+	client.ctx->bootstrap_mode = false;
+	ret = sm_select_security_inst(client.ctx->bootstrap_mode,
+				      &client.ctx->sec_obj_inst);
+	if (ret < 0) {
+		LOG_ERR("Unable to find a valid security instance.");
+		set_sm_state(ENGINE_INIT);
+		return -EINVAL;
+	}
+
+	ret = sm_select_server_inst(client.ctx->sec_obj_inst,
+				    &client.ctx->srv_obj_inst,
+				    &client.lifetime);
+	if (ret < 0) {
+		LOG_ERR("Unable to find a valid server instance.");
+		set_sm_state(ENGINE_INIT);
+		return -EINVAL;
+	}
+
+	LOG_INF("RD Client started with endpoint '%s' with client lifetime %d",
+		log_strdup(client.ep_name), client.lifetime);
+
+	ret = lwm2m_engine_start(client.ctx);
+	if (ret < 0) {
+		LOG_ERR("Cannot init LWM2M engine (%d)", ret);
+		return ret;
+	}
+
+	ret = sm_send_registration(true,
+				   do_registration_reply_cb,
+				   do_registration_timeout_cb);
+	if (!ret) {
+		set_sm_state(ENGINE_REGISTRATION_SENT);
+	} else {
+		LOG_ERR("Registration err: %d", ret);
+		lwm2m_engine_context_close(client.ctx);
+		/* exit and try again */
+	}
+
+	return ret;
+}
+
+static int sm_registration_done(void)
+{
+	int ret = 0;
+	bool forced_update;
+
+	/*
+	 * check for lifetime seconds - SECONDS_TO_UPDATE_EARLY
+	 * so that we can update early and avoid lifetime timeout
+	 */
+	if (sm_is_registered() &&
+	    (client.trigger_update ||
+	     ((client.lifetime - SECONDS_TO_UPDATE_EARLY) <=
+	      (k_uptime_get() - client.last_update) / 1000))) {
+		forced_update = client.trigger_update;
+		client.trigger_update = 0U;
+
+		/** The LwM2M server might've changed the lifetime,
+		 *  update it just in case.
+		 */
+		sm_update_lifetime(client.ctx->srv_obj_inst, &client.lifetime);
+
+		ret = sm_send_registration(forced_update,
+					   do_update_reply_cb,
+					   do_update_timeout_cb);
+		if (!ret) {
+			set_sm_state(ENGINE_UPDATE_SENT);
+		} else {
+			LOG_ERR("Registration update err: %d", ret);
+			lwm2m_engine_context_close(client.ctx);
+			/* perform full registration */
+			set_sm_state(ENGINE_DO_REGISTRATION);
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED) &&
+	    (client.engine_state != ENGINE_REGISTRATION_DONE_RX_OFF) &&
+	    (((k_uptime_get() - client.last_tx) / 1000) >=
+	     CONFIG_LWM2M_QUEUE_MODE_UPTIME)) {
+		set_sm_state(ENGINE_REGISTRATION_DONE_RX_OFF);
+	}
+
+	return ret;
+}
+
+static int sm_do_deregister(void)
+{
+	struct lwm2m_message *msg;
+	int ret;
+
+	msg = lwm2m_get_message(client.ctx);
+	if (!msg) {
+		LOG_ERR("Unable to get a lwm2m message!");
+		return -ENOMEM;
+	}
+
+	msg->type = COAP_TYPE_CON;
+	msg->code = COAP_METHOD_DELETE;
+	msg->mid = coap_next_id();
+	msg->tkl = LWM2M_MSG_TOKEN_GENERATE_NEW;
+	msg->reply_cb = do_deregister_reply_cb;
+	msg->message_timeout_cb = do_deregister_timeout_cb;
+
+	ret = lwm2m_init_message(msg);
+	if (ret) {
+		goto cleanup;
+	}
+
+	/* TODO: handle return error */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+				  LWM2M_RD_CLIENT_URI,
+				  strlen(LWM2M_RD_CLIENT_URI));
+	/* include server endpoint in URI PATH */
+	coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
+				  client.server_ep,
+				  strlen(client.server_ep));
+
+	LOG_INF("Deregister from '%s'", log_strdup(client.server_ep));
+
+	ret = lwm2m_send_message(msg);
+	if (ret < 0) {
+		LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
+		goto cleanup;
+	}
+
+	set_sm_state(ENGINE_DEREGISTER_SENT);
+	return 0;
+
+cleanup:
+	lwm2m_reset_message(msg, true);
+	lwm2m_engine_context_close(client.ctx);
+	return ret;
+}
+
+static void lwm2m_rd_client_service(struct k_work *work)
+{
+	if (client.ctx) {
+		switch (get_sm_state()) {
+		case ENGINE_IDLE:
+			break;
+
+		case ENGINE_INIT:
+			sm_do_init();
+			break;
+
+#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
+		case ENGINE_DO_BOOTSTRAP_REG:
+			sm_do_bootstrap_reg();
+			break;
+
+		case ENGINE_BOOTSTRAP_REG_SENT:
+			/* wait for bootstrap registration done */
+			break;
+
+		case ENGINE_BOOTSTRAP_REG_DONE:
+			/* wait for transfer done */
+			break;
+
+		case ENGINE_BOOTSTRAP_TRANS_DONE:
+			sm_bootstrap_trans_done();
+			break;
+#endif
+
+		case ENGINE_DO_REGISTRATION:
+			sm_do_registration();
+			break;
+
+		case ENGINE_REGISTRATION_SENT:
+			/* wait registration to be done or timeout */
+			break;
+
+		case ENGINE_REGISTRATION_DONE:
+		case ENGINE_REGISTRATION_DONE_RX_OFF:
+			sm_registration_done();
+			break;
+
+		case ENGINE_UPDATE_SENT:
+			/* wait update to be done or abort */
+			break;
+
+		case ENGINE_DEREGISTER:
+			sm_do_deregister();
+			break;
+
+		case ENGINE_DEREGISTER_SENT:
+			/* wait for deregister to be done or reset */
+			break;
+
+		case ENGINE_DEREGISTER_FAILED:
+			set_sm_state(ENGINE_IDLE);
+			break;
+
+		case ENGINE_DEREGISTERED:
+			set_sm_state(ENGINE_IDLE);
+			break;
+
+		default:
+			LOG_ERR("Unhandled state: %d", get_sm_state());
+
+		}
+	}
+}
+
+void lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, const char *ep_name,
+			   uint32_t flags, lwm2m_ctx_event_cb_t event_cb)
+{
+	if (!IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP) &&
+	    (flags & LWM2M_RD_CLIENT_FLAG_BOOTSTRAP)) {
+		LOG_ERR("Bootstrap support is disabled. Please enable "
+			"CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP.");
+		return;
+	}
+
+	client.ctx = client_ctx;
+	client.ctx->sock_fd = -1;
+	client.event_cb = event_cb;
+	client.use_bootstrap = flags & LWM2M_RD_CLIENT_FLAG_BOOTSTRAP;
+
+	set_sm_state(ENGINE_INIT);
+	strncpy(client.ep_name, ep_name, CLIENT_EP_LEN - 1);
+	LOG_INF("Start LWM2M Client: %s", log_strdup(client.ep_name));
+}
+
+void lwm2m_rd_client_stop(struct lwm2m_ctx *client_ctx,
+			   lwm2m_ctx_event_cb_t event_cb)
+{
+	client.ctx = client_ctx;
+	client.event_cb = event_cb;
+
+	if (sm_is_registered()) {
+		set_sm_state(ENGINE_DEREGISTER);
+	} else {
+		if (client.ctx->sock_fd > -1) {
+			lwm2m_engine_context_close(client.ctx);
+		}
+		set_sm_state(ENGINE_IDLE);
+	}
+
+	LOG_INF("Stop LWM2M Client: %s", log_strdup(client.ep_name));
+}
+
+static int lwm2m_rd_client_init(const struct device *dev)
+{
+	return lwm2m_engine_add_service(lwm2m_rd_client_service,
+					STATE_MACHINE_UPDATE_INTERVAL_MS);
+
+}
+
+SYS_INIT(lwm2m_rd_client_init, APPLICATION,
+	 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_resource_ids.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_resource_ids.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_resource_ids.h	(working copy)
@@ -0,0 +1,25 @@
+/**
+ * @file lwm2m_resource_ids.h
+ * @brief
+ *
+ * Copyright (c) 2020 Laird Connectivity
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __LWM2M_RESOURCE_IDS__
+#define __LWM2M_RESOURCE_IDS__
+
+/* clang-format off */
+#define TIMESTAMP_RID                     5518
+#define MIN_MEASURED_VALUE_RID            5601
+#define MAX_MEASURED_VALUE_RID            5602
+#define MIN_RANGE_VALUE_RID               5603
+#define MAX_RANGE_VALUE_RID               5604
+#define RESET_MIN_MAX_MEASURED_VALUES_RID 5605
+#define SENSOR_VALUE_RID                  5700
+#define SENSOR_UNITS_RID                  5701
+#define APPLICATION_TYPE_RID              5750
+#define SENSOR_TYPE_RID                   5751
+/* clang-format on */
+
+#endif /* __LWM2M_RESOURCE_IDS__ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.h	(working copy)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2016, Eistec AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Author:
+ *         Joakim Nohlgأ¥rd <joakim.nohlgard@eistec.se>
+ */
+
+#ifndef LWM2M_RW_JSON_H_
+#define LWM2M_RW_JSON_H_
+
+#include "lwm2m_object.h"
+
+extern const struct lwm2m_writer json_writer;
+extern const struct lwm2m_reader json_reader;
+
+int do_read_op_json(struct lwm2m_message *msg, int content_format);
+int do_write_op_json(struct lwm2m_message *msg);
+
+#endif /* LWM2M_RW_JSON_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_json.c	(working copy)
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2016, Eistec AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Nohlgأ¥rd <joakim.nohlgard@eistec.se>
+ *         Joakim Eriksson <joakime@sics.se> added JSON reader parts
+ */
+
+/*
+ * Zephyr Contribution by Michael Scott <michael.scott@linaro.org>
+ * - Zephyr code style changes / code cleanup
+ * - Move to Zephyr APIs where possible
+ * - Convert to Zephyr int/uint types
+ * - Remove engine dependency (replace with writer/reader context)
+ * - Add write / read int64 functions
+ */
+
+/*
+ * TODO:
+ * - Debug formatting errors in Leshan
+ * - Replace magic #'s with defines
+ * - Research using Zephyr JSON lib for json_next_token()
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_json
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_rw_json.h"
+#include "lwm2m_rw_plain_text.h"
+#include "lwm2m_engine.h"
+
+#define T_OBJECT_BEGIN	BIT(0)
+#define T_OBJECT_END	BIT(1)
+#define T_STRING_BEGIN	BIT(2)
+#define T_STRING_END	BIT(3)
+#define T_VALUE		BIT(4)
+
+#define SEPARATOR(f)	((f & WRITER_OUTPUT_VALUE) ? "," : "")
+
+/* writer modes */
+#define MODE_NONE      0
+#define MODE_INSTANCE  1
+#define MODE_VALUE     2
+#define MODE_READY     3
+
+#define TOKEN_BUF_LEN	64
+
+struct json_out_formatter_data {
+	/* offset position storage */
+	uint16_t mark_pos_ri;
+
+	/* flags */
+	uint8_t writer_flags;
+
+	/* path storage */
+	uint8_t path_level;
+};
+
+struct json_in_formatter_data {
+	/* name info */
+	uint16_t name_offset;
+	uint16_t name_len;
+
+	/* value info */
+	uint16_t value_offset;
+	uint16_t value_len;
+
+	/* state */
+	uint16_t offset;
+
+	/* flags */
+	uint8_t json_flags;
+};
+
+/* some temporary buffer space for format conversions */
+static char json_buffer[TOKEN_BUF_LEN];
+
+static void json_add_char(struct lwm2m_input_context *in,
+			  struct json_in_formatter_data *fd)
+{
+	if ((fd->json_flags & T_VALUE) ||
+	    ((fd->json_flags & T_STRING_BEGIN) &&
+	    !(fd->json_flags & T_STRING_END))) {
+		if (fd->json_flags & T_VALUE) {
+			fd->value_len++;
+			if (fd->value_len == 1U) {
+				fd->value_offset = fd->offset;
+			}
+		} else {
+			fd->name_len++;
+			if (fd->name_len == 1U) {
+				fd->name_offset = fd->offset;
+			}
+		}
+	}
+}
+
+/* Simlified JSON style reader for reading in values from a LWM2M JSON string */
+static int json_next_token(struct lwm2m_input_context *in,
+			   struct json_in_formatter_data *fd)
+{
+	uint8_t cont, c;
+	bool escape = false;
+
+	(void)memset(fd, 0, sizeof(*fd));
+	cont = 1U;
+
+	/* We will be either at start, or at a specific position */
+	while (in->offset < in->in_cpkt->offset && cont) {
+		fd->offset = in->offset;
+		if (buf_read_u8(&c, CPKT_BUF_READ(in->in_cpkt),
+				&in->offset) < 0) {
+			break;
+		}
+
+		if (c == '\\') {
+			escape = true;
+			/* Keep track of the escape codes */
+			json_add_char(in, fd);
+			continue;
+		}
+
+		switch (c) {
+
+		case '[':
+			if (!escape) {
+				fd->json_flags |= T_OBJECT_BEGIN;
+				cont = 0U;
+			} else {
+				json_add_char(in, fd);
+			}
+			break;
+		case ']':
+			if (!escape) {
+				fd->json_flags |= T_OBJECT_END;
+				cont = 0U;
+			} else {
+				json_add_char(in, fd);
+			}
+			break;
+		case '{':
+			if (!escape) {
+				fd->json_flags |= T_OBJECT_BEGIN;
+			} else {
+				json_add_char(in, fd);
+			}
+
+			break;
+
+		case '}':
+		case ',':
+			if (!escape) {
+				cont = 0U;
+			} else {
+				json_add_char(in, fd);
+			}
+
+			break;
+
+		case '"':
+			if (!escape) {
+				if (fd->json_flags & T_STRING_BEGIN) {
+					fd->json_flags &= ~T_STRING_BEGIN;
+					fd->json_flags |= T_STRING_END;
+				} else {
+					fd->json_flags &= ~T_STRING_END;
+					fd->json_flags |= T_STRING_BEGIN;
+				}
+			} else {
+				json_add_char(in, fd);
+			}
+
+			break;
+
+		case ':':
+			if (!escape) {
+				fd->json_flags &= ~T_STRING_END;
+				fd->json_flags |= T_VALUE;
+			} else {
+				json_add_char(in, fd);
+			}
+
+			break;
+
+		/* ignore whitespace */
+		case ' ':
+		case '\n':
+		case '\t':
+			if (!(fd->json_flags & T_STRING_BEGIN)) {
+				break;
+			}
+
+			__fallthrough;
+
+		default:
+			json_add_char(in, fd);
+
+		}
+
+		if (escape) {
+			escape = false;
+		}
+	}
+
+	/* OK if cont == 0 othewise we failed */
+	return (cont == 0U);
+}
+
+static size_t put_begin(struct lwm2m_output_context *out,
+			struct lwm2m_obj_path *path)
+{
+	int len = -1;
+
+	if (path->level >= 2U) {
+		len = snprintk(json_buffer, sizeof(json_buffer),
+			       "{\"bn\":\"/%u/%u/\",\"e\":[",
+			       path->obj_id, path->obj_inst_id);
+	} else {
+		len = snprintk(json_buffer, sizeof(json_buffer),
+			       "{\"bn\":\"/%u/\",\"e\":[",
+			       path->obj_id);
+	}
+
+	if (len < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), json_buffer, len) < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	return (size_t)len;
+}
+
+static size_t put_end(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path)
+{
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), "]}", 2) < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	return 2;
+}
+
+static size_t put_begin_ri(struct lwm2m_output_context *out,
+			   struct lwm2m_obj_path *path)
+{
+	struct json_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	fd->writer_flags |= WRITER_RESOURCE_INSTANCE;
+	return 0;
+}
+
+static size_t put_end_ri(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path)
+{
+	struct json_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	fd->writer_flags &= ~WRITER_RESOURCE_INSTANCE;
+	return 0;
+}
+
+static size_t put_char(struct lwm2m_output_context *out,
+		       char c)
+{
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), &c, sizeof(c)) < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	return 1;
+}
+
+static size_t put_json_prefix(struct lwm2m_output_context *out,
+			      struct lwm2m_obj_path *path,
+			      const char *format)
+{
+	struct json_out_formatter_data *fd;
+	char *sep;
+	int len = 0;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	sep = SEPARATOR(fd->writer_flags);
+	if (fd->path_level >= 2U) {
+		if (fd->writer_flags & WRITER_RESOURCE_INSTANCE) {
+			len = snprintk(json_buffer, sizeof(json_buffer),
+				       "%s{\"n\":\"%u/%u\",%s:",
+				       sep, path->res_id, path->res_inst_id,
+				       format);
+		} else {
+			len = snprintk(json_buffer, sizeof(json_buffer),
+				       "%s{\"n\":\"%u\",%s:",
+				       sep, path->res_id, format);
+		}
+	} else {
+		if (fd->writer_flags & WRITER_RESOURCE_INSTANCE) {
+			len = snprintk(json_buffer, sizeof(json_buffer),
+				       "%s{\"n\":\"%u/%u/%u\",%s:",
+				       sep, path->obj_inst_id, path->res_id,
+				       path->res_inst_id, format);
+		} else {
+			len = snprintk(json_buffer, sizeof(json_buffer),
+				       "%s{\"n\":\"%u/%u\",%s:",
+				       sep, path->obj_inst_id, path->res_id,
+				       format);
+		}
+	}
+
+	if (len < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), json_buffer, len) < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	return len;
+}
+
+static size_t put_json_postfix(struct lwm2m_output_context *out)
+{
+	struct json_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	if (put_char(out, '}') < 1) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	fd->writer_flags |= WRITER_OUTPUT_VALUE;
+	return 1;
+}
+
+static size_t put_s32(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int32_t value)
+{
+	int len;
+
+	len = put_json_prefix(out, path, "\"v\"");
+	len += plain_text_put_format(out, "%d", value);
+	len += put_json_postfix(out);
+
+	return (size_t)len;
+}
+
+static size_t put_s16(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int16_t value)
+{
+	return put_s32(out, path, (int32_t)value);
+}
+
+static size_t put_s8(struct lwm2m_output_context *out,
+		     struct lwm2m_obj_path *path, int8_t value)
+{
+	return put_s32(out, path, (int32_t)value);
+}
+
+static size_t put_s64(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int64_t value)
+{
+	int len;
+
+	len = put_json_prefix(out, path, "\"v\"");
+	len += plain_text_put_format(out, "%lld", value);
+	len += put_json_postfix(out);
+	return (size_t)len;
+}
+
+static size_t put_string(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 char *buf, size_t buflen)
+{
+	size_t i;
+	size_t len = 0;
+	int res;
+
+	res = put_json_prefix(out, path, "\"sv\"");
+	res += put_char(out, '"');
+
+	if (res < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	len += res;
+
+	for (i = 0; i < buflen; ++i) {
+		/* Escape special characters */
+		/* TODO: Handle UTF-8 strings */
+		if (buf[i] < '\x20') {
+			res = snprintk(json_buffer, sizeof(json_buffer),
+				       "\\x%x", buf[i]);
+			if (res < 0) {
+				/* TODO: Generate error? */
+				return 0;
+			}
+
+			if (buf_append(CPKT_BUF_WRITE(out->out_cpkt),
+				       json_buffer, res) < 0) {
+				/* TODO: Generate error? */
+				return 0;
+			}
+
+			len += res;
+			continue;
+		} else if (buf[i] == '"' || buf[i] == '\\') {
+			len += put_char(out, '\\');
+		}
+
+		len += put_char(out, buf[i]);
+	}
+
+	res = put_char(out, '"');
+	if (res < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	len += res;
+	len += put_json_postfix(out);
+	return len;
+}
+
+static size_t put_float32fix(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     float32_value_t *value)
+{
+	size_t len;
+
+	len = put_json_prefix(out, path, "\"v\"");
+	len += plain_text_put_float32fix(out, path, value);
+	len += put_json_postfix(out);
+	return len;
+}
+
+static size_t put_float64fix(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     float64_value_t *value)
+{
+	size_t len;
+
+	len = put_json_prefix(out, path, "\"v\"");
+	len += plain_text_put_float64fix(out, path, value);
+	len += put_json_postfix(out);
+	return len;
+}
+
+static size_t put_bool(struct lwm2m_output_context *out,
+		       struct lwm2m_obj_path *path,
+		       bool value)
+{
+	size_t len;
+
+	len = put_json_prefix(out, path, "\"bv\"");
+	len += plain_text_put_format(out, "%s", value ? "true" : "false");
+	len += put_json_postfix(out);
+	return (size_t)len;
+}
+
+static size_t put_objlnk(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 struct lwm2m_objlnk *value)
+{
+	size_t len;
+
+	len = put_json_prefix(out, path, "\"ov\"");
+	len += plain_text_put_format(out, "\"%u:%u\"", value->obj_id,
+				     value->obj_inst);
+	len += put_json_postfix(out);
+
+	return len;
+}
+
+static size_t read_number(struct lwm2m_input_context *in,
+			  int64_t *value1, int64_t *value2,
+			  bool accept_sign, bool accept_dot)
+{
+	struct json_in_formatter_data *fd;
+	int64_t *counter = value1;
+	uint8_t *buf;
+	size_t i = 0;
+	bool neg = false;
+	bool dot_found = false;
+	char c;
+
+	/* initialize values to 0 */
+	*value1 = 0;
+	if (value2) {
+		*value2 = 0;
+	}
+
+	fd = engine_get_in_user_data(in);
+	if (!fd) {
+		return 0;
+	}
+
+	buf = in->in_cpkt->data + fd->value_offset;
+	while (*(buf + i) && i < fd->value_len) {
+		c = *(buf + i);
+		if (c == '-' && accept_sign && i == 0) {
+			neg = true;
+		} else if (c == '.' && i > 0 && accept_dot && !dot_found &&
+			   value2) {
+			dot_found = true;
+			counter = value2;
+		} else if (isdigit(c)) {
+			*counter = *counter * 10 + (c - '0');
+		} else {
+			/* anything else stop reading */
+			break;
+		}
+
+		i++;
+	}
+
+	if (neg) {
+		*value1 = -*value1;
+	}
+
+	return i;
+}
+
+static size_t get_s64(struct lwm2m_input_context *in, int64_t *value)
+{
+	return read_number(in, value, NULL, true, true);
+}
+
+static size_t get_s32(struct lwm2m_input_context *in, int32_t *value)
+{
+	int64_t tmp = 0;
+	size_t len = 0;
+
+	len = read_number(in, &tmp, NULL, true, true);
+	if (len > 0) {
+		*value = (int32_t)tmp;
+	}
+
+	return len;
+}
+
+static size_t get_string(struct lwm2m_input_context *in,
+			 uint8_t *buf, size_t buflen)
+{
+	struct json_in_formatter_data *fd;
+	int ret;
+
+	fd = engine_get_in_user_data(in);
+	if (!fd) {
+		return 0;
+	}
+
+	if (fd->value_len > buflen) {
+		/* TODO: generate warning? */
+		fd->value_len = buflen - 1;
+	}
+
+	/* TODO: Handle escape codes */
+	ret = buf_read(buf, fd->value_len, CPKT_BUF_READ(in->in_cpkt),
+		       &fd->value_offset);
+	if (ret < 0) {
+		return 0;
+	}
+
+	return fd->value_len;
+}
+
+static size_t get_float32fix(struct lwm2m_input_context *in,
+			     float32_value_t *value)
+{
+	int64_t tmp1, tmp2;
+	size_t len;
+
+	len = read_number(in, &tmp1, &tmp2, true, true);
+	if (len > 0) {
+		value->val1 = (int32_t)tmp1;
+		value->val2 = (int32_t)tmp2;
+	}
+
+	return len;
+}
+
+static size_t get_float64fix(struct lwm2m_input_context *in,
+			     float64_value_t *value)
+{
+	int64_t tmp1, tmp2;
+	size_t len;
+
+	len = read_number(in, &tmp1, &tmp2, true, true);
+	if (len > 0) {
+		value->val1 = tmp1;
+		value->val2 = tmp2;
+	}
+
+	return len;
+}
+
+static size_t get_bool(struct lwm2m_input_context *in, bool *value)
+{
+	struct json_in_formatter_data *fd;
+
+	fd = engine_get_in_user_data(in);
+	if (!fd) {
+		return 0;
+	}
+
+	if (strncmp(in->in_cpkt->data + fd->value_offset,
+		    "true", 4) == 0) {
+		*value = true;
+	} else if (strncmp(in->in_cpkt->data + fd->value_offset,
+		   "false", 5) == 0) {
+		*value = false;
+	}
+
+	return fd->value_len;
+}
+
+static size_t get_opaque(struct lwm2m_input_context *in,
+			 uint8_t *value, size_t buflen,
+			 struct lwm2m_opaque_context *opaque,
+			 bool *last_block)
+{
+	/* TODO */
+	return 0;
+}
+
+static size_t get_objlnk(struct lwm2m_input_context *in,
+			 struct lwm2m_objlnk *value)
+{
+	int64_t tmp;
+	size_t len;
+	uint16_t value_offset;
+	struct json_in_formatter_data *fd;
+
+	fd = engine_get_in_user_data(in);
+	if (!fd) {
+		return 0;
+	}
+
+	/* Store the original value offset. */
+	value_offset = fd->value_offset;
+
+	len = read_number(in, &tmp, NULL, false, false);
+	value->obj_id = (uint16_t)tmp;
+
+	len++;  /* +1 for ':' delimeter. */
+	fd->value_offset += len;
+
+	len += read_number(in, &tmp, NULL, false, false);
+	value->obj_inst = (uint16_t)tmp;
+
+	/* Restore the original value offset. */
+	fd->value_offset = value_offset;
+
+	return len;
+}
+
+const struct lwm2m_writer json_writer = {
+	.put_begin = put_begin,
+	.put_end = put_end,
+	.put_begin_ri = put_begin_ri,
+	.put_end_ri = put_end_ri,
+	.put_s8 = put_s8,
+	.put_s16 = put_s16,
+	.put_s32 = put_s32,
+	.put_s64 = put_s64,
+	.put_string = put_string,
+	.put_float32fix = put_float32fix,
+	.put_float64fix = put_float64fix,
+	.put_bool = put_bool,
+	.put_objlnk = put_objlnk,
+};
+
+const struct lwm2m_reader json_reader = {
+	.get_s32 = get_s32,
+	.get_s64 = get_s64,
+	.get_string = get_string,
+	.get_float32fix = get_float32fix,
+	.get_float64fix = get_float64fix,
+	.get_bool = get_bool,
+	.get_opaque = get_opaque,
+	.get_objlnk = get_objlnk,
+};
+
+int do_read_op_json(struct lwm2m_message *msg, int content_format)
+{
+	struct json_out_formatter_data fd;
+	int ret;
+
+	(void)memset(&fd, 0, sizeof(fd));
+	engine_set_out_user_data(&msg->out, &fd);
+	/* save the level for output processing */
+	fd.path_level = msg->path.level;
+	ret = lwm2m_perform_read_op(msg, content_format);
+	engine_clear_out_user_data(&msg->out);
+
+	return ret;
+}
+
+static int parse_path(const uint8_t *buf, uint16_t buflen,
+		      struct lwm2m_obj_path *path)
+{
+	int ret = 0;
+	int pos = 0;
+	uint16_t val;
+	uint8_t c = 0U;
+
+	(void)memset(path, 0, sizeof(*path));
+	do {
+		val = 0U;
+		c = buf[pos];
+		/* we should get a value first - consume all numbers */
+		while (pos < buflen && isdigit(c)) {
+			val = val * 10U + (c - '0');
+			c = buf[++pos];
+		}
+
+		/* slash will mote thing forward */
+		if (pos == 0 && c == '/') {
+			/* skip leading slashes */
+			pos++;
+		} else if (c == '/' || pos == buflen) {
+			LOG_DBG("Setting %u = %u", ret, val);
+			if (ret == 0) {
+				path->obj_id = val;
+			} else if (ret == 1) {
+				path->obj_inst_id = val;
+			} else if (ret == 2) {
+				path->res_id = val;
+			} else if (ret == 3) {
+				path->res_inst_id = val;
+			}
+
+			ret++;
+			pos++;
+		} else {
+			LOG_ERR("Error: illegal char '%c' at pos:%d",
+				c, pos);
+			return -1;
+		}
+	} while (pos < buflen);
+
+	return ret;
+}
+
+int do_write_op_json(struct lwm2m_message *msg)
+{
+	struct lwm2m_engine_obj_field *obj_field = NULL;
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	struct lwm2m_obj_path orig_path;
+	struct json_in_formatter_data fd;
+	int ret = 0, index;
+	uint8_t value[TOKEN_BUF_LEN];
+	uint8_t base_name[MAX_RESOURCE_LEN];
+	uint8_t full_name[MAX_RESOURCE_LEN];
+	uint8_t created;
+
+	(void)memset(&fd, 0, sizeof(fd));
+	engine_set_in_user_data(&msg->in, &fd);
+
+	/* store a copy of the original path */
+	memcpy(&orig_path, &msg->path, sizeof(msg->path));
+
+	/* PARSE base name "bn" */
+	json_next_token(&msg->in, &fd);
+	/* TODO: validate name == "bn" */
+	if (buf_read(base_name, fd.value_len,
+		     CPKT_BUF_READ(msg->in.in_cpkt),
+		     &fd.value_offset) < 0) {
+		LOG_ERR("Error parsing base name!");
+		return -EINVAL;
+	}
+
+	/* skip to elements */
+	json_next_token(&msg->in, &fd);
+	/* TODO: validate name == "bv" */
+
+	while (json_next_token(&msg->in, &fd)) {
+
+		if (!(fd.json_flags & T_VALUE)) {
+			continue;
+		}
+
+		if (buf_read(value, fd.name_len,
+			     CPKT_BUF_READ(msg->in.in_cpkt),
+			     &fd.name_offset) < 0) {
+			LOG_ERR("Error parsing name!");
+			continue;
+		}
+
+		/* handle resource name */
+		if (value[0] == 'n') {
+			/* reset values */
+			created = 0U;
+
+			/* get value for relative path */
+			if (buf_read(value, fd.value_len,
+				     CPKT_BUF_READ(msg->in.in_cpkt),
+				     &fd.value_offset) < 0) {
+				LOG_ERR("Error parsing relative path!");
+				continue;
+			}
+
+			/* combine base_name + name */
+			snprintk(full_name, sizeof(full_name), "%s%s",
+				 base_name, value);
+
+			/* parse full_name into path */
+			ret = parse_path(full_name, strlen(full_name),
+					 &msg->path);
+			if (ret < 0) {
+				break;
+			}
+
+			/* if valid, use the return value as level */
+			msg->path.level = ret;
+
+			ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst,
+							     &created);
+			if (ret < 0) {
+				break;
+			}
+
+			obj_field = lwm2m_get_engine_obj_field(
+							obj_inst->obj,
+							msg->path.res_id);
+			/*
+			 * if obj_field is not found,
+			 * treat as an optional resource
+			 */
+			if (!obj_field) {
+				ret = -ENOENT;
+				break;
+			}
+
+			/*
+			 * TODO: support BOOTSTRAP WRITE where optional
+			 * resources are ignored
+			 */
+
+			if (!LWM2M_HAS_PERM(obj_field, LWM2M_PERM_W)) {
+				ret = -EPERM;
+				break;
+			}
+
+			if (!obj_inst->resources ||
+			    obj_inst->resource_count == 0U) {
+				ret = -EINVAL;
+				break;
+			}
+
+			for (index = 0; index < obj_inst->resource_count;
+			     index++) {
+				if (obj_inst->resources[index].res_id ==
+				    msg->path.res_id) {
+					res = &obj_inst->resources[index];
+					break;
+				}
+			}
+
+			if (!res) {
+				ret = -ENOENT;
+				break;
+			}
+
+			for (index = 0; index < res->res_inst_count; index++) {
+				if (res->res_instances[index].res_inst_id ==
+				    msg->path.res_inst_id) {
+					res_inst = &res->res_instances[index];
+					break;
+				}
+			}
+
+			if (!res_inst) {
+				ret = -ENOENT;
+				break;
+			}
+		} else if (res && res_inst) {
+			/* handle value assignment */
+			ret = lwm2m_write_handler(obj_inst, res, res_inst,
+						  obj_field, msg);
+			if (orig_path.level >= 3U && ret < 0) {
+				/* return errors on a single write */
+				break;
+			}
+		} else {
+			/* complain about error? */
+		}
+	}
+
+	engine_clear_in_user_data(&msg->in);
+
+	return ret;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.h	(working copy)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+#ifndef LWM2M_RW_OMA_TLV_H_
+#define LWM2M_RW_OMA_TLV_H_
+
+#include "lwm2m_object.h"
+
+extern const struct lwm2m_writer oma_tlv_writer;
+extern const struct lwm2m_reader oma_tlv_reader;
+
+int do_read_op_tlv(struct lwm2m_message *msg, int content_format);
+int do_write_op_tlv(struct lwm2m_message *msg);
+
+#endif /* LWM2M_RW_OMA_TLV_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c	(working copy)
@@ -0,0 +1,1022 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+/*
+ * Zephyr Contribution by Michael Scott <michael.scott@linaro.org>
+ * - Zephyr code style changes / code cleanup
+ * - Move to Zephyr APIs where possible
+ * - Convert to Zephyr int/uint types
+ * - Remove engine dependency (replace with writer context)
+ * - Add write int64 function
+ */
+
+/*
+ * TODO:
+ * - Lots of byte-order API clean up
+ * - Var / parameter type cleanup
+ * - Replace magic #'s with defines
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_oma_tlv
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <string.h>
+#include <stdint.h>
+#include <sys/byteorder.h>
+
+#include "lwm2m_rw_oma_tlv.h"
+#include "lwm2m_engine.h"
+#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
+#include "lwm2m_rd_client.h"
+#endif
+#include "lwm2m_util.h"
+
+enum {
+	OMA_TLV_TYPE_OBJECT_INSTANCE   = 0,
+	OMA_TLV_TYPE_RESOURCE_INSTANCE = 1,
+	OMA_TLV_TYPE_MULTI_RESOURCE    = 2,
+	OMA_TLV_TYPE_RESOURCE          = 3
+};
+
+struct oma_tlv {
+	uint8_t  type;
+	uint16_t id; /* can be 8-bit or 16-bit when serialized */
+	uint32_t length;
+};
+
+struct tlv_out_formatter_data {
+	/* offset position storage */
+	uint16_t mark_pos;
+	uint16_t mark_pos_oi;
+	uint16_t mark_pos_ri;
+	uint8_t writer_flags;
+};
+
+static uint8_t get_len_type(const struct oma_tlv *tlv)
+{
+	if (tlv->length < 8) {
+		return 0;
+	} else if (tlv->length < 0x100) {
+		return 1;
+	} else if (tlv->length < 0x10000) {
+		return 2;
+	}
+
+	return 3;
+}
+
+static uint8_t tlv_calc_type(uint8_t flags)
+{
+	return flags & WRITER_RESOURCE_INSTANCE ?
+			OMA_TLV_TYPE_RESOURCE_INSTANCE : OMA_TLV_TYPE_RESOURCE;
+}
+
+static uint16_t tlv_calc_id(uint8_t flags, struct lwm2m_obj_path *path)
+{
+	return flags & WRITER_RESOURCE_INSTANCE ?
+			path->res_inst_id : path->res_id;
+}
+
+static void tlv_setup(struct oma_tlv *tlv, uint8_t type, uint16_t id,
+		      uint32_t buflen)
+{
+	if (tlv) {
+		tlv->type = type;
+		tlv->id = id;
+		tlv->length = buflen;
+	}
+}
+
+static int oma_tlv_put_u8(struct lwm2m_output_context *out,
+			  uint8_t value, bool insert)
+{
+	struct tlv_out_formatter_data *fd;
+	int ret;
+
+	if (insert) {
+		fd = engine_get_out_user_data(out);
+		if (!fd) {
+			return 0;
+		}
+
+		ret = buf_insert(CPKT_BUF_WRITE(out->out_cpkt),
+				 fd->mark_pos, &value, 1);
+		if (ret < 0) {
+			return ret;
+		}
+
+		fd->mark_pos++;
+	} else {
+		ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), &value, 1);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static size_t oma_tlv_put(const struct oma_tlv *tlv,
+			  struct lwm2m_output_context *out,
+			  uint8_t *value, bool insert)
+{
+	size_t pos;
+	int ret, i;
+	uint8_t len_type, tmp;
+
+	/* len_type is the same as number of bytes required for length */
+	len_type = get_len_type(tlv);
+
+	/* first type byte in TLV header */
+	tmp = (tlv->type << 6) |
+	      (tlv->id > 255 ? (1 << 5) : 0) |
+	      (len_type << 3) |
+	      (len_type == 0U ? tlv->length : 0);
+
+	ret = oma_tlv_put_u8(out, tmp, insert);
+	if (ret < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	pos = 1;
+
+	/* The ID */
+	if (tlv->id > 255) {
+		ret = oma_tlv_put_u8(out, (tlv->id >> 8) & 0xff, insert);
+		if (ret < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		pos++;
+	}
+
+	ret = oma_tlv_put_u8(out, tlv->id & 0xff, insert);
+	if (ret < 0) {
+		/* TODO: Generate error? */
+		return 0;
+	}
+
+	pos++;
+
+	for (i = 2; i >= 0; i--) {
+		if (len_type > i) {
+			ret = oma_tlv_put_u8(out,
+					     (tlv->length >> (i * 8)) & 0xff,
+					     insert);
+			if (ret < 0) {
+				/* TODO: Generate error? */
+				return 0;
+			}
+
+			pos++;
+		}
+	}
+
+	/* finally add the value */
+	if (value != NULL && tlv->length > 0 && !insert) {
+		if (buf_append(CPKT_BUF_WRITE(out->out_cpkt),
+			       value, tlv->length) < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+	}
+
+	return pos + tlv->length;
+}
+
+static size_t oma_tlv_get(struct oma_tlv *tlv,
+			  struct lwm2m_input_context *in,
+			  bool dont_advance)
+{
+	uint8_t len_type;
+	uint8_t len_pos = 1U;
+	size_t tlv_len;
+	uint16_t tmp_offset;
+	uint8_t buf[2];
+
+	tmp_offset = in->offset;
+	if (buf_read_u8(&buf[0], CPKT_BUF_READ(in->in_cpkt), &tmp_offset) < 0) {
+		goto error;
+	}
+
+	tlv->type = (buf[0] >> 6) & 3;
+	len_type = (buf[0] >> 3) & 3;
+	len_pos = 1 + (((buf[0] & (1 << 5)) != 0U) ? 2 : 1);
+
+	if (buf_read_u8(&buf[1], CPKT_BUF_READ(in->in_cpkt), &tmp_offset) < 0) {
+		return 0;
+	}
+
+	tlv->id = buf[1];
+
+	/* if len_pos > 2 it means that there are more ID to read */
+	if (len_pos > 2) {
+		if (buf_read_u8(&buf[1], CPKT_BUF_READ(in->in_cpkt),
+				&tmp_offset) < 0) {
+			goto error;
+		}
+
+		tlv->id = (tlv->id << 8) + buf[1];
+	}
+
+	if (len_type == 0U) {
+		tlv_len = buf[0] & 7;
+	} else {
+		/* read the length */
+		tlv_len = 0;
+		while (len_type > 0) {
+			if (buf_read_u8(&buf[1], CPKT_BUF_READ(in->in_cpkt),
+					&tmp_offset) < 0) {
+				goto error;
+			}
+
+			len_pos++;
+			tlv_len = tlv_len << 8 | buf[1];
+			len_type--;
+		}
+	}
+
+	/* and read out the data??? */
+	tlv->length = tlv_len;
+
+	if (!dont_advance) {
+		in->offset = tmp_offset;
+	}
+
+	return len_pos + tlv_len;
+
+error:
+	/* TODO: Generate error? */
+	if (!dont_advance) {
+		in->offset = tmp_offset;
+	}
+
+	return 0;
+}
+
+static size_t put_begin_tlv(struct lwm2m_output_context *out, uint16_t *mark_pos,
+			    uint8_t *writer_flags, int writer_flag)
+{
+	/* set flags */
+	*writer_flags |= writer_flag;
+
+	/*
+	 * store position for inserting TLV when we know the length
+	 */
+	*mark_pos = out->out_cpkt->offset;
+
+	return 0;
+}
+
+static size_t put_end_tlv(struct lwm2m_output_context *out, uint16_t mark_pos,
+			  uint8_t *writer_flags, uint8_t writer_flag,
+			  int tlv_type, int tlv_id)
+{
+	struct tlv_out_formatter_data *fd;
+	struct oma_tlv tlv;
+	uint32_t len = 0U;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	*writer_flags &= ~writer_flag;
+
+	len = out->out_cpkt->offset - mark_pos;
+
+	/* use stored location */
+	fd->mark_pos = mark_pos;
+
+	/* set instance length */
+	tlv_setup(&tlv, tlv_type, tlv_id, len);
+	len = oma_tlv_put(&tlv, out, NULL, true) - tlv.length;
+
+	return len;
+}
+
+static size_t put_begin_oi(struct lwm2m_output_context *out,
+			   struct lwm2m_obj_path *path)
+{
+	struct tlv_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	return put_begin_tlv(out, &fd->mark_pos_oi, &fd->writer_flags, 0);
+}
+
+static size_t put_end_oi(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path)
+{
+	struct tlv_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	return put_end_tlv(out, fd->mark_pos_oi, &fd->writer_flags, 0,
+			   OMA_TLV_TYPE_OBJECT_INSTANCE, path->obj_inst_id);
+}
+
+static size_t put_begin_ri(struct lwm2m_output_context *out,
+			   struct lwm2m_obj_path *path)
+{
+	struct tlv_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	return put_begin_tlv(out, &fd->mark_pos_ri, &fd->writer_flags,
+			     WRITER_RESOURCE_INSTANCE);
+}
+
+static size_t put_end_ri(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path)
+{
+	struct tlv_out_formatter_data *fd;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	return put_end_tlv(out, fd->mark_pos_ri, &fd->writer_flags,
+			   WRITER_RESOURCE_INSTANCE,
+			   OMA_TLV_TYPE_MULTI_RESOURCE, path->res_id);
+}
+
+static size_t put_s8(struct lwm2m_output_context *out,
+		     struct lwm2m_obj_path *path, int8_t value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(value));
+
+	len = oma_tlv_put(&tlv, out, (uint8_t *)&value, false);
+	return len;
+}
+
+static size_t put_s16(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int16_t value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+	int16_t net_value;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	net_value = sys_cpu_to_be16(value);
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(net_value));
+
+	len = oma_tlv_put(&tlv, out, (uint8_t *)&net_value, false);
+	return len;
+}
+
+static size_t put_s32(struct lwm2m_output_context *out,
+			struct lwm2m_obj_path *path, int32_t value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+	int32_t net_value;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	net_value = sys_cpu_to_be32(value);
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(net_value));
+
+	len = oma_tlv_put(&tlv, out, (uint8_t *)&net_value, false);
+	return len;
+}
+
+static size_t put_s64(struct lwm2m_output_context *out,
+			struct lwm2m_obj_path *path, int64_t value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+	int64_t net_value;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	net_value = sys_cpu_to_be64(value);
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(net_value));
+
+	len = oma_tlv_put(&tlv, out, (uint8_t *)&net_value, false);
+	return len;
+}
+
+static size_t put_string(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 char *buf, size_t buflen)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), (uint32_t)buflen);
+	len = oma_tlv_put(&tlv, out, (uint8_t *)buf, false);
+	return len;
+}
+
+static size_t put_float32fix(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     float32_value_t *value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+	int ret;
+	uint8_t b32[4];
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	ret = lwm2m_f32_to_b32(value, b32, sizeof(b32));
+	if (ret < 0) {
+		LOG_ERR("float32 conversion error: %d", ret);
+		return 0;
+	}
+
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(b32));
+	len = oma_tlv_put(&tlv, out, b32, false);
+	return len;
+}
+
+static size_t put_float64fix(struct lwm2m_output_context *out,
+			     struct lwm2m_obj_path *path,
+			     float64_value_t *value)
+{
+	struct tlv_out_formatter_data *fd;
+	size_t len;
+	struct oma_tlv tlv;
+	uint8_t b64[8];
+	int ret;
+
+	fd = engine_get_out_user_data(out);
+	if (!fd) {
+		return 0;
+	}
+
+	ret = lwm2m_f64_to_b64(value, b64, sizeof(b64));
+	if (ret < 0) {
+		LOG_ERR("float64 conversion error: %d", ret);
+		return 0;
+	}
+
+	tlv_setup(&tlv, tlv_calc_type(fd->writer_flags),
+		  tlv_calc_id(fd->writer_flags, path), sizeof(b64));
+	len = oma_tlv_put(&tlv, out, b64, false);
+	return len;
+}
+
+static size_t put_bool(struct lwm2m_output_context *out,
+		       struct lwm2m_obj_path *path, bool value)
+{
+	int8_t value_s8 = (value != 0 ? 1 : 0);
+
+	return put_s8(out, path, value_s8);
+}
+
+static size_t put_opaque(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 char *buf, size_t buflen)
+{
+	return put_string(out, path, buf, buflen);
+}
+
+static size_t put_objlnk(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 struct lwm2m_objlnk *value)
+{
+	int32_t value_s32 = (value->obj_id << 16) | value->obj_inst;
+
+	return put_s32(out, path, value_s32);
+}
+
+static size_t get_number(struct lwm2m_input_context *in, int64_t *value,
+			 uint8_t max_len)
+{
+	struct oma_tlv tlv;
+	size_t size = oma_tlv_get(&tlv, in, false);
+	int64_t temp;
+
+	*value = 0;
+	if (size > 0) {
+		if (tlv.length > max_len) {
+			LOG_ERR("invalid length: %u", tlv.length);
+			return 0;
+		}
+
+		if (buf_read((uint8_t *)&temp, tlv.length,
+			     CPKT_BUF_READ(in->in_cpkt), &in->offset) < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		switch (tlv.length) {
+		case 1:
+			*value = (int8_t)temp;
+			break;
+		case 2:
+			*value = sys_cpu_to_be16((int16_t)temp);
+			break;
+		case 4:
+			*value = sys_cpu_to_be32((int32_t)temp);
+			break;
+		case 8:
+			*value = sys_cpu_to_be64(temp);
+			break;
+		default:
+			LOG_ERR("invalid length: %u", tlv.length);
+			return 0;
+		}
+	}
+
+	return size;
+}
+
+static size_t get_s64(struct lwm2m_input_context *in, int64_t *value)
+{
+	return get_number(in, value, 8);
+}
+
+static size_t get_s32(struct lwm2m_input_context *in, int32_t *value)
+{
+	int64_t temp;
+	size_t size;
+
+	*value = 0;
+	size = get_number(in, &temp, 4);
+	if (size > 0) {
+		*value = (int32_t)temp;
+	}
+
+	return size;
+}
+
+static size_t get_string(struct lwm2m_input_context *in,
+			 uint8_t *buf, size_t buflen)
+{
+	struct oma_tlv tlv;
+	size_t size = oma_tlv_get(&tlv, in, false);
+
+	if (size > 0) {
+		if (buflen <= tlv.length) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		if (buf_read(buf, tlv.length, CPKT_BUF_READ(in->in_cpkt),
+			     &in->offset) < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		buf[tlv.length] = '\0';
+	}
+
+	return size;
+}
+
+/* convert float to fixpoint */
+static size_t get_float32fix(struct lwm2m_input_context *in,
+			     float32_value_t *value)
+{
+	struct oma_tlv tlv;
+	size_t size = oma_tlv_get(&tlv, in, false);
+	uint8_t b32[4];
+	int ret;
+
+	if (size > 0) {
+		if (tlv.length != 4U) {
+			LOG_ERR("Invalid float32 length: %d", tlv.length);
+
+			/* dummy read */
+			while (tlv.length--) {
+				if (buf_read_u8(b32,
+						CPKT_BUF_READ(in->in_cpkt),
+						&in->offset) < 0) {
+					break;
+				}
+			}
+
+			return 0;
+		}
+
+		/* read b32 in network byte order */
+		if (buf_read(b32, tlv.length, CPKT_BUF_READ(in->in_cpkt),
+			     &in->offset) < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		ret = lwm2m_b32_to_f32(b32, sizeof(b32), value);
+		if (ret < 0) {
+			LOG_ERR("binary32 conversion error: %d", ret);
+			return 0;
+		}
+	}
+
+	return size;
+}
+
+static size_t get_float64fix(struct lwm2m_input_context *in,
+			     float64_value_t *value)
+{
+	struct oma_tlv tlv;
+	size_t size = oma_tlv_get(&tlv, in, false);
+	uint8_t b64[8];
+	int ret;
+
+	if (size > 0) {
+		if (tlv.length != 8U) {
+			LOG_ERR("invalid float64 length: %d", tlv.length);
+
+			/* dummy read */
+			while (tlv.length--) {
+				if (buf_read_u8(b64,
+						CPKT_BUF_READ(in->in_cpkt),
+						&in->offset) < 0) {
+					break;
+				}
+			}
+
+			return 0;
+		}
+
+		/* read b64 in network byte order */
+		if (buf_read(b64, tlv.length, CPKT_BUF_READ(in->in_cpkt),
+			     &in->offset) < 0) {
+			/* TODO: Generate error? */
+			return 0;
+		}
+
+		ret = lwm2m_b64_to_f64(b64, sizeof(b64), value);
+		if (ret < 0) {
+			LOG_ERR("binary64 conversion error: %d", ret);
+			return 0;
+		}
+	}
+
+	return size;
+}
+
+static size_t get_bool(struct lwm2m_input_context *in, bool *value)
+{
+	int64_t temp;
+	size_t size;
+
+	*value = 0;
+	size = get_number(in, &temp, 2);
+	if (size > 0) {
+		*value = (temp != 0);
+	}
+
+	return size;
+}
+
+static size_t get_opaque(struct lwm2m_input_context *in,
+			 uint8_t *value, size_t buflen,
+			 struct lwm2m_opaque_context *opaque,
+			 bool *last_block)
+{
+	struct oma_tlv tlv;
+	size_t size;
+
+	/* Get the TLV header only on first read. */
+	if (opaque->remaining == 0) {
+		size = oma_tlv_get(&tlv, in, false);
+
+		opaque->len = tlv.length;
+		opaque->remaining = tlv.length;
+	}
+
+	return lwm2m_engine_get_opaque_more(in, value, buflen,
+					    opaque, last_block);
+}
+
+static size_t get_objlnk(struct lwm2m_input_context *in,
+			 struct lwm2m_objlnk *value)
+{
+	int32_t value_s32;
+	size_t size;
+
+	size = get_s32(in, &value_s32);
+
+	value->obj_id = (value_s32 >> 16) & 0xFFFF;
+	value->obj_inst = value_s32 & 0xFFFF;
+
+	return size;
+}
+
+const struct lwm2m_writer oma_tlv_writer = {
+	.put_begin_oi = put_begin_oi,
+	.put_end_oi = put_end_oi,
+	.put_begin_ri = put_begin_ri,
+	.put_end_ri = put_end_ri,
+	.put_s8 = put_s8,
+	.put_s16 = put_s16,
+	.put_s32 = put_s32,
+	.put_s64 = put_s64,
+	.put_string = put_string,
+	.put_float32fix = put_float32fix,
+	.put_float64fix = put_float64fix,
+	.put_bool = put_bool,
+	.put_opaque = put_opaque,
+	.put_objlnk = put_objlnk,
+};
+
+const struct lwm2m_reader oma_tlv_reader = {
+	.get_s32 = get_s32,
+	.get_s64 = get_s64,
+	.get_string = get_string,
+	.get_float32fix = get_float32fix,
+	.get_float64fix = get_float64fix,
+	.get_bool = get_bool,
+	.get_opaque = get_opaque,
+	.get_objlnk = get_objlnk,
+};
+
+int do_read_op_tlv(struct lwm2m_message *msg, int content_format)
+{
+	struct tlv_out_formatter_data fd;
+	int ret;
+
+	(void)memset(&fd, 0, sizeof(fd));
+	engine_set_out_user_data(&msg->out, &fd);
+	ret = lwm2m_perform_read_op(msg, content_format);
+	engine_clear_out_user_data(&msg->out);
+	return ret;
+}
+
+static int do_write_op_tlv_dummy_read(struct lwm2m_message *msg)
+{
+	struct oma_tlv tlv;
+	uint8_t read_char;
+
+	oma_tlv_get(&tlv, &msg->in, false);
+	while (tlv.length--) {
+		if (buf_read_u8(&read_char, CPKT_BUF_READ(msg->in.in_cpkt),
+				&msg->in.offset) < 0) {
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int do_write_op_tlv_item(struct lwm2m_message *msg)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	struct lwm2m_engine_obj_field *obj_field = NULL;
+	uint8_t created = 0U;
+	int ret, i;
+
+	ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
+	if (ret < 0) {
+		goto error;
+	}
+
+	obj_field = lwm2m_get_engine_obj_field(obj_inst->obj,
+					       msg->path.res_id);
+	if (!obj_field) {
+		ret = -ENOENT;
+		goto error;
+	}
+
+	if (!LWM2M_HAS_PERM(obj_field, LWM2M_PERM_W)) {
+		ret = -EPERM;
+		goto error;
+	}
+
+	if (!obj_inst->resources || obj_inst->resource_count == 0U) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	for (i = 0; i < obj_inst->resource_count; i++) {
+		if (obj_inst->resources[i].res_id == msg->path.res_id) {
+			res = &obj_inst->resources[i];
+			break;
+		}
+	}
+
+	if (res) {
+		for (i = 0; i < res->res_inst_count; i++) {
+			if (res->res_instances[i].res_inst_id ==
+			    msg->path.res_inst_id) {
+				res_inst = &res->res_instances[i];
+				break;
+			}
+		}
+	}
+
+	if (!res || !res_inst) {
+		/* if OPTIONAL and BOOTSTRAP-WRITE or CREATE use ENOTSUP */
+		if ((msg->ctx->bootstrap_mode ||
+		     msg->operation == LWM2M_OP_CREATE) &&
+		    LWM2M_HAS_PERM(obj_field, BIT(LWM2M_FLAG_OPTIONAL))) {
+			ret = -ENOTSUP;
+			goto error;
+		}
+
+		ret = -ENOENT;
+		goto error;
+	}
+
+	ret = lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
+	if (ret == -EACCES || ret == -ENOENT) {
+		/* if read-only or non-existent data buffer move on */
+		do_write_op_tlv_dummy_read(msg);
+		ret = 0;
+	}
+
+	return ret;
+
+error:
+	do_write_op_tlv_dummy_read(msg);
+	return ret;
+}
+
+int do_write_op_tlv(struct lwm2m_message *msg)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	size_t len;
+	struct oma_tlv tlv;
+	int ret;
+
+	/* In case of Firmware object Package resource go directly to the
+	 * message processing - consecutive blocks will not carry the TLV
+	 * header.
+	 */
+	if (msg->path.obj_id == 5 && msg->path.res_id == 0) {
+		ret = do_write_op_tlv_item(msg);
+		if (ret < 0) {
+			return ret;
+		}
+	}
+
+	while (true) {
+		/*
+		 * This initial read of TLV data won't advance frag/offset.
+		 * We need tlv.type to determine how to proceed.
+		 */
+		len = oma_tlv_get(&tlv, &msg->in, true);
+		if (len == 0) {
+			break;
+		}
+
+		if (tlv.type == OMA_TLV_TYPE_OBJECT_INSTANCE) {
+			struct oma_tlv tlv2;
+			int len2;
+			int pos = 0;
+
+			oma_tlv_get(&tlv, &msg->in, false);
+			msg->path.obj_inst_id = tlv.id;
+			if (tlv.length == 0U) {
+				/* Create only - no data */
+				ret = lwm2m_create_obj_inst(
+						msg->path.obj_id,
+						msg->path.obj_inst_id,
+						&obj_inst);
+				if (ret < 0) {
+					return ret;
+				}
+
+#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
+				if (!msg->ctx->bootstrap_mode) {
+					engine_trigger_update();
+				}
+#endif
+			}
+
+			while (pos < tlv.length &&
+			       (len2 = oma_tlv_get(&tlv2, &msg->in, true))) {
+				if (tlv2.type != OMA_TLV_TYPE_RESOURCE) {
+					pos += len2;
+					continue;
+				}
+
+				msg->path.res_id = tlv2.id;
+				msg->path.level = 3U;
+				ret = do_write_op_tlv_item(msg);
+				/*
+				 * ignore errors for CREATE op
+				 * for OP_CREATE and BOOTSTRAP WRITE: errors on
+				 * optional resources are ignored (ENOTSUP)
+				 */
+				if (ret < 0 &&
+				    !((ret == -ENOTSUP) &&
+				      (msg->ctx->bootstrap_mode ||
+				       msg->operation == LWM2M_OP_CREATE))) {
+					return ret;
+				}
+
+				pos += len2;
+			}
+		} else if (tlv.type == OMA_TLV_TYPE_RESOURCE) {
+			msg->path.res_id = tlv.id;
+			msg->path.level = 3U;
+			ret = do_write_op_tlv_item(msg);
+			/*
+			 * ignore errors for CREATE op
+			 * for OP_CREATE and BOOTSTRAP WRITE: errors on optional
+			 * resources are ignored (ENOTSUP)
+			 */
+			if (ret < 0 &&
+			    !((ret == -ENOTSUP) &&
+			      (msg->ctx->bootstrap_mode ||
+			       msg->operation == LWM2M_OP_CREATE))) {
+				return ret;
+			}
+		} else {
+			return -ENOTSUP;
+		}
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.h	(working copy)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+#ifndef LWM2M_RW_PLAIN_TEXT_H_
+#define LWM2M_RW_PLAIN_TEXT_H_
+
+#include "lwm2m_object.h"
+
+extern const struct lwm2m_writer plain_text_writer;
+extern const struct lwm2m_reader plain_text_reader;
+
+size_t plain_text_put_format(struct lwm2m_output_context *out,
+			     const char *format, ...);
+
+size_t plain_text_put_float32fix(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float32_value_t *value);
+size_t plain_text_put_float64fix(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float64_value_t *value);
+
+
+int do_read_op_plain_text(struct lwm2m_message *msg, int content_format);
+int do_write_op_plain_text(struct lwm2m_message *msg);
+
+#endif /* LWM2M_RW_PLAIN_TEXT_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c	(working copy)
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2015, Yanzi Networks AB.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Original Authors:
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+/*
+ * Zephyr Contribution by Michael Scott <michael.scott@linaro.org>
+ * - Zephyr code style changes / code cleanup
+ * - Move to Zephyr APIs where possible
+ * - Convert to Zephyr int/uint types
+ * - Remove engine dependency (replace with writer context)
+ * - Add write int64 function
+ */
+
+/*
+ * TODO:
+ * - Type cleanups
+ * - Cleanup integer parsing
+ */
+
+#define LOG_MODULE_NAME net_lwm2m_plain_text
+#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "lwm2m_object.h"
+#include "lwm2m_rw_plain_text.h"
+#include "lwm2m_engine.h"
+
+/* some temporary buffer space for format conversions */
+static char pt_buffer[42]; /* can handle float64 format */
+
+size_t plain_text_put_format(struct lwm2m_output_context *out,
+			     const char *format, ...)
+{
+	va_list vargs;
+	int n;
+
+	va_start(vargs, format);
+	n = vsnprintk(pt_buffer, sizeof(pt_buffer), format, vargs);
+	va_end(vargs);
+	if (n < 0) {
+		/* TODO: generate an error? */
+		return 0;
+	}
+
+	n = strlen(pt_buffer);
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), pt_buffer, n) < 0) {
+		return 0;
+	}
+
+	return (size_t)n;
+}
+
+static size_t put_s32(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int32_t value)
+{
+	return plain_text_put_format(out, "%d", value);
+}
+
+static size_t put_s8(struct lwm2m_output_context *out,
+		     struct lwm2m_obj_path *path, int8_t value)
+{
+	return plain_text_put_format(out, "%d", value);
+}
+
+static size_t put_s16(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int16_t value)
+{
+	return plain_text_put_format(out, "%d", value);
+}
+
+static size_t put_s64(struct lwm2m_output_context *out,
+		      struct lwm2m_obj_path *path, int64_t value)
+{
+	return plain_text_put_format(out, "%lld", value);
+}
+
+size_t plain_text_put_float32fix(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float32_value_t *value)
+{
+	size_t len;
+	char buf[sizeof("000000")];
+
+	/* value of 123 -> "000123" -- ignore sign */
+	len = snprintk(buf, sizeof(buf), "%06d", abs(value->val2));
+	if (len != 6U) {
+		strcpy(buf, "0");
+	} else {
+		/* clear ending zeroes, but leave 1 if needed */
+		while (len > 1U && buf[len - 1] == '0') {
+			buf[--len] = '\0';
+		}
+	}
+
+	return plain_text_put_format(out, "%s%d.%s",
+				     /* handle negative val2 when val1 is 0 */
+				     (value->val1 == 0 && value->val2 < 0) ?
+						"-" : "",
+				     value->val1, buf);
+}
+
+size_t plain_text_put_float64fix(struct lwm2m_output_context *out,
+				 struct lwm2m_obj_path *path,
+				 float64_value_t *value)
+{
+	size_t len;
+	char buf[sizeof("000000000")];
+
+	/* value of 123 -> "000000123" -- ignore sign */
+	len = snprintf(buf, sizeof(buf), "%09lld",
+		       (long long int)abs(value->val2));
+	if (len != 9U) {
+		strcpy(buf, "0");
+	} else {
+		/* clear ending zeroes, but leave 1 if needed */
+		while (len > 1U && buf[len - 1] == '0') {
+			buf[--len] = '\0';
+		}
+	}
+
+	return plain_text_put_format(out, "%s%lld.%s",
+				     /* handle negative val2 when val1 is 0 */
+				     (value->val1 == 0 && value->val2 < 0) ?
+						"-" : "",
+				     value->val1, buf);
+}
+
+static size_t put_string(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 char *buf, size_t buflen)
+{
+	if (buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, buflen) < 0) {
+		return 0;
+	}
+
+	return buflen;
+}
+
+static size_t put_bool(struct lwm2m_output_context *out,
+		       struct lwm2m_obj_path *path,
+		       bool value)
+{
+	if (value) {
+		return plain_text_put_format(out, "%u", 1);
+	} else {
+		return plain_text_put_format(out, "%u", 0);
+	}
+}
+
+static size_t put_objlnk(struct lwm2m_output_context *out,
+			 struct lwm2m_obj_path *path,
+			 struct lwm2m_objlnk *value)
+{
+	return plain_text_put_format(out, "%u:%u", value->obj_id,
+				     value->obj_inst);
+}
+
+static size_t plain_text_read_number(struct lwm2m_input_context *in,
+				     int64_t *value1,
+				     int64_t *value2,
+				     bool accept_sign, bool accept_dot)
+{
+	int64_t *counter = value1;
+	int i = 0;
+	bool neg = false;
+	bool dot_found = false;
+	uint8_t tmp;
+
+	/* initialize values to 0 */
+	*value1 = 0;
+	if (value2) {
+		*value2 = 0;
+	}
+
+	while (in->offset < in->in_cpkt->offset) {
+		if (buf_read_u8(&tmp, CPKT_BUF_READ(in->in_cpkt),
+				&in->offset) < 0) {
+			break;
+		}
+
+		if (tmp == '-' && accept_sign && i == 0) {
+			neg = true;
+		} else if (tmp == '.' && i > 0 && accept_dot && !dot_found &&
+			   value2) {
+			dot_found = true;
+			counter = value2;
+		} else if (isdigit(tmp)) {
+			*counter = *counter * 10 + (tmp - '0');
+		} else {
+			/* anything else stop reading */
+			in->offset--;
+			break;
+		}
+
+		i++;
+	}
+
+	if (neg) {
+		*value1 = -*value1;
+	}
+
+	return i;
+}
+
+static size_t get_s32(struct lwm2m_input_context *in, int32_t *value)
+{
+	int64_t tmp = 0;
+	size_t len = 0;
+
+	len = plain_text_read_number(in, &tmp, NULL, true, false);
+	if (len > 0) {
+		*value = (int32_t)tmp;
+	}
+
+	return len;
+}
+
+static size_t get_s64(struct lwm2m_input_context *in, int64_t *value)
+{
+	return plain_text_read_number(in, value, NULL, true, false);
+}
+
+static size_t get_string(struct lwm2m_input_context *in,
+			 uint8_t *value, size_t buflen)
+{
+	uint16_t in_len;
+
+	coap_packet_get_payload(in->in_cpkt, &in_len);
+
+	if (in_len > buflen) {
+		/* TODO: generate warning? */
+		in_len = buflen - 1;
+	}
+
+	if (buf_read(value, in_len, CPKT_BUF_READ(in->in_cpkt),
+		     &in->offset) < 0) {
+		value[0] = '\0';
+		return 0;
+	}
+
+	value[in_len] = '\0';
+	return (size_t)in_len;
+}
+
+static size_t get_float32fix(struct lwm2m_input_context *in,
+			     float32_value_t *value)
+{
+	int64_t tmp1, tmp2;
+	size_t len = 0;
+
+	len = plain_text_read_number(in, &tmp1, &tmp2, true, true);
+	if (len > 0) {
+		value->val1 = (int32_t)tmp1;
+		value->val2 = (int32_t)tmp2;
+	}
+
+	return len;
+}
+
+static size_t get_float64fix(struct lwm2m_input_context *in,
+			     float64_value_t *value)
+{
+	return plain_text_read_number(in, &value->val1, &value->val2,
+				      true, true);
+}
+
+static size_t get_bool(struct lwm2m_input_context *in,
+		       bool *value)
+{
+	uint8_t tmp;
+
+	if (buf_read_u8(&tmp, CPKT_BUF_READ(in->in_cpkt), &in->offset) < 0) {
+		return 0;
+	}
+
+	if (tmp == '1' || tmp == '0') {
+		*value = (tmp == '1') ? true : false;
+		return 1;
+	}
+
+	return 0;
+}
+
+static size_t get_opaque(struct lwm2m_input_context *in,
+			 uint8_t *value, size_t buflen,
+			 struct lwm2m_opaque_context *opaque,
+			 bool *last_block)
+{
+	uint16_t in_len;
+
+	if (opaque->remaining == 0) {
+		coap_packet_get_payload(in->in_cpkt, &in_len);
+
+		if (in->block_ctx != NULL) {
+			uint32_t block_num =
+				in->block_ctx->ctx.current /
+				coap_block_size_to_bytes(
+					in->block_ctx->ctx.block_size);
+
+			if (block_num == 0) {
+				opaque->len = in->block_ctx->ctx.total_size;
+			}
+
+			if (opaque->len == 0) {
+				/* No size1 option provided, use current
+				 * payload size. This will reset on next packet
+				 * received.
+				 */
+				opaque->remaining = in_len;
+			} else {
+				opaque->remaining = opaque->len;
+			}
+
+		} else {
+			opaque->len = in_len;
+			opaque->remaining = in_len;
+		}
+	}
+
+	return lwm2m_engine_get_opaque_more(in, value, buflen,
+					    opaque, last_block);
+}
+
+
+static size_t get_objlnk(struct lwm2m_input_context *in,
+			 struct lwm2m_objlnk *value)
+{
+	int64_t tmp;
+	size_t len;
+
+	len = plain_text_read_number(in, &tmp, NULL, false, false);
+	value->obj_id = (uint16_t)tmp;
+
+	/* Skip ':' delimeter. */
+	in->offset++;
+	len++;
+
+	len += plain_text_read_number(in, &tmp, NULL, false, false);
+	value->obj_inst = (uint16_t)tmp;
+
+	return len;
+}
+
+const struct lwm2m_writer plain_text_writer = {
+	.put_s8 = put_s8,
+	.put_s16 = put_s16,
+	.put_s32 = put_s32,
+	.put_s64 = put_s64,
+	.put_string = put_string,
+	.put_float32fix = plain_text_put_float32fix,
+	.put_float64fix = plain_text_put_float64fix,
+	.put_bool = put_bool,
+	.put_objlnk = put_objlnk,
+};
+
+const struct lwm2m_reader plain_text_reader = {
+	.get_s32 = get_s32,
+	.get_s64 = get_s64,
+	.get_string = get_string,
+	.get_float32fix = get_float32fix,
+	.get_float64fix = get_float64fix,
+	.get_bool = get_bool,
+	.get_opaque = get_opaque,
+	.get_objlnk = get_objlnk,
+};
+
+int do_read_op_plain_text(struct lwm2m_message *msg, int content_format)
+{
+	/* Plain text can only return single resource */
+	if (msg->path.level != 3U) {
+		return -EPERM; /* NOT_ALLOWED */
+	}
+
+	return lwm2m_perform_read_op(msg, content_format);
+}
+
+int do_write_op_plain_text(struct lwm2m_message *msg)
+{
+	struct lwm2m_engine_obj_inst *obj_inst = NULL;
+	struct lwm2m_engine_obj_field *obj_field;
+	struct lwm2m_engine_res *res = NULL;
+	struct lwm2m_engine_res_inst *res_inst = NULL;
+	int ret, i;
+	uint8_t created = 0U;
+
+	ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
+	if (ret < 0) {
+		return ret;
+	}
+
+	obj_field = lwm2m_get_engine_obj_field(obj_inst->obj, msg->path.res_id);
+	if (!obj_field) {
+		return -ENOENT;
+	}
+
+	if (!LWM2M_HAS_PERM(obj_field, LWM2M_PERM_W)) {
+		return -EPERM;
+	}
+
+	if (!obj_inst->resources || obj_inst->resource_count == 0U) {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < obj_inst->resource_count; i++) {
+		if (obj_inst->resources[i].res_id == msg->path.res_id) {
+			res = &obj_inst->resources[i];
+			break;
+		}
+	}
+
+	if (!res) {
+		return -ENOENT;
+	}
+
+	for (i = 0; i < res->res_inst_count; i++) {
+		if (res->res_instances[i].res_inst_id ==
+		    msg->path.res_inst_id) {
+			res_inst = &res->res_instances[i];
+			break;
+		}
+	}
+
+	if (!res_inst) {
+		return -ENOENT;
+	}
+
+	if (msg->path.level < 3) {
+		msg->path.level = 3U;
+	}
+
+	return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.h	(working copy)
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018-2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef LWM2M_UTIL_H_
+#define LWM2M_UTIL_H_
+
+#include <net/lwm2m.h>
+
+/* convert float struct to binary format */
+int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len);
+int lwm2m_f64_to_b64(float64_value_t *f64, uint8_t *b64, size_t len);
+
+/* convert binary format to float struct */
+int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32);
+int lwm2m_b64_to_f64(uint8_t *b64, size_t len, float64_value_t *f64);
+
+#endif /* LWM2M_UTIL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/lwm2m/lwm2m_util.c	(working copy)
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2019 Foundries.io
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <stdlib.h>
+#include "lwm2m_util.h"
+
+#define SHIFT_LEFT(v, o, m) (((v) << (o)) & (m))
+#define SHIFT_RIGHT(v, o, m) (((v) >> (o)) & (m))
+
+/* convert from float32 to binary32 */
+int lwm2m_f32_to_b32(float32_value_t *f32, uint8_t *b32, size_t len)
+{
+	int32_t e = -1, v, f = 0;
+	int i;
+
+	if (len != 4) {
+		return -EINVAL;
+	}
+
+	/* handle zero value special case */
+	if (f32->val1 == 0 && f32->val2 == 0) {
+		memset(b32, 0, len);
+		return 0;
+	}
+
+	/* sign handled later */
+	v = abs(f32->val1);
+
+	/* add whole value to fraction */
+	while (v > 0) {
+		f >>= 1;
+
+		if (v & 1) {
+			f |= (1 << 23);
+		}
+
+		v >>= 1;
+		e++;
+	}
+
+	/* sign handled later */
+	v = abs(f32->val2);
+
+	/* add decimal to fraction */
+	i = e;
+	while (v > 0 && i < 23) {
+		v *= 2;
+		if (!f && e < 0 && v < LWM2M_FLOAT32_DEC_MAX) {
+			/* handle -e */
+			e--;
+			continue;
+		} else if (v >= LWM2M_FLOAT32_DEC_MAX) {
+			v -= LWM2M_FLOAT32_DEC_MAX;
+			f |= 1 << (22 - i);
+		}
+
+		if (v == 0) {
+			break;
+		}
+
+		i++;
+	}
+
+	/* adjust exponent for bias */
+	e += 127;
+
+	memset(b32, 0, len);
+
+	/* sign: bit 31 */
+	if (f32->val1 == 0) {
+		b32[0] = f32->val2 < 0 ? 0x80 : 0;
+	} else {
+		b32[0] = f32->val1 < 0 ? 0x80 : 0;
+	}
+
+	/* exponent: bits 30-23 */
+	b32[0] |= e >> 1;
+	b32[1] = (e & 1) << 7;
+
+	/* fraction: bits 22-0 */
+	/* NOTE: ignore the "hidden" bit 23 in fraction */
+	b32[1] |= (f >> 16) & 0x7F;
+	b32[2] = (f >> 8) & 0xFF;
+	b32[3] = f & 0xFF;
+
+	return 0;
+}
+
+/* convert from float64 to binary64 */
+int lwm2m_f64_to_b64(float64_value_t *f64, uint8_t *b64, size_t len)
+{
+	int64_t v, f = 0;
+	int32_t e = -1;
+	int i;
+
+	if (len != 8) {
+		return -EINVAL;
+	}
+
+	/* handle zero value special case */
+	if (f64->val1 == 0LL && f64->val2 == 0LL) {
+		memset(b64, 0, len);
+		return 0;
+	}
+
+	/* sign handled later */
+	v = abs(f64->val1);
+
+	/* add whole value to fraction */
+	while (v > 0) {
+		f >>= 1;
+
+		if (v & 1) {
+			f |= ((int64_t)1 << 52);
+		}
+
+		v >>= 1;
+		e++;
+	}
+
+	/* sign handled later */
+	v = abs(f64->val2);
+
+	/* add decimal to fraction */
+	i = e;
+	while (v > 0 && i < 52) {
+		v *= 2;
+		if (!f && e < 0 && v < LWM2M_FLOAT64_DEC_MAX) {
+			/* handle -e */
+			e--;
+			continue;
+		} else if (v >= LWM2M_FLOAT64_DEC_MAX) {
+			v -= LWM2M_FLOAT64_DEC_MAX;
+			f |= (int64_t)1 << (51 - i);
+		}
+
+		if (v == 0) {
+			break;
+		}
+
+		i++;
+	}
+
+	/* adjust exponent for bias */
+	e += 1023;
+
+	memset(b64, 0, len);
+
+	/* sign: bit 63 */
+	if (f64->val1 == 0) {
+		b64[0] = f64->val2 < 0 ? 0x80 : 0;
+	} else {
+		b64[0] = f64->val1 < 0 ? 0x80 : 0;
+	}
+
+	/* exponent: bits 62-52 */
+	b64[0] |= (e >> 4);
+	b64[1] = ((e & 0xF) << 4);
+
+	/* fraction: bits 51-0 */
+	/* NOTE: ignore the "hidden" bit 52 in fraction */
+	b64[1] |= ((f >> 48) & 0xF);
+	b64[2] = (f >> 40) & 0xFF;
+	b64[3] = (f >> 32) & 0xFF;
+	b64[4] = (f >> 24) & 0xFF;
+	b64[5] = (f >> 16) & 0xFF;
+	b64[6] = (f >> 8) & 0xFF;
+	b64[7] = f & 0xFF;
+
+	return 0;
+}
+
+/* convert from binary32 to float32 */
+int lwm2m_b32_to_f32(uint8_t *b32, size_t len, float32_value_t *f32)
+{
+	int32_t f, k, i, e;
+	bool sign = false;
+
+	if (len != 4) {
+		return -EINVAL;
+	}
+
+	f32->val1 = 0;
+	f32->val2 = 0;
+
+	/* calc sign: bit 31 */
+	sign = SHIFT_RIGHT(b32[0], 7, 0x1);
+
+	/* calc exponent: bits 30-23 */
+	e  = SHIFT_LEFT(b32[0], 1, 0xFF);
+	e += SHIFT_RIGHT(b32[1], 7, 0x1);
+	/* remove bias */
+	e -= 127;
+
+	/* enable "hidden" fraction bit 23 which is always 1 */
+	f  = ((int32_t)1 << 22);
+	/* calc fraction: bits 22-0 */
+	f += ((int32_t)(b32[1] & 0x7F) << 16);
+	f += ((int32_t)b32[2] << 8);
+	f += b32[3];
+
+	/* handle whole number */
+	if (e > -1) {
+		/* precision overflow */
+		if (e > 23) {
+			e = 23;
+		}
+
+		f32->val1 = (f >> (23 - e)) * (sign ? -1 : 1);
+	}
+
+	/* calculate the rest of the decimal */
+	k = LWM2M_FLOAT32_DEC_MAX;
+
+	/* account for -e */
+	while (e < -1) {
+		k /= 2;
+		e++;
+	}
+
+	for (i = 22 - e; i >= 0; i--) {
+		k /= 2;
+		if (f & (1 << i)) {
+			f32->val2 += k;
+
+		}
+	}
+
+	return 0;
+}
+
+/* convert from binary64 to float64 */
+int lwm2m_b64_to_f64(uint8_t *b64, size_t len, float64_value_t *f64)
+{
+	int64_t f, k;
+	int i, e;
+	bool sign = false;
+
+	if (len != 8) {
+		return -EINVAL;
+	}
+
+	f64->val1 = 0LL;
+	f64->val2 = 0LL;
+
+	/* calc sign: bit 63 */
+	sign = SHIFT_RIGHT(b64[0], 7, 0x1);
+
+	/* get exponent: bits 62-52 */
+	e  = SHIFT_LEFT((uint16_t)b64[0], 4, 0x7F0);
+	e += SHIFT_RIGHT(b64[1], 4, 0xF);
+	/* remove bias */
+	e -= 1023;
+
+	/* enable "hidden" fraction bit 53 which is always 1 */
+	f  = ((int64_t)1 << 52);
+	/* get fraction: bits 51-0 */
+	f += ((int64_t)(b64[1] & 0xF) << 48);
+	f += ((int64_t)b64[2] << 40);
+	f += ((int64_t)b64[3] << 32);
+	f += ((int64_t)b64[4] << 24);
+	f += ((int64_t)b64[5] << 16);
+	f += ((int64_t)b64[6] << 8);
+	f += b64[7];
+
+	/* handle whole number */
+	if (e > -1) {
+		/* precision overflow */
+		if (e > 52) {
+			e = 52;
+		}
+
+		f64->val1 = (f >> (52 - e)) * (sign ? -1 : 1);
+	}
+
+	/* calculate the rest of the decimal */
+	k = LWM2M_FLOAT64_DEC_MAX;
+
+	/* account for -e */
+	while (e < -1) {
+		k /= 2;
+		e++;
+	}
+
+	for (i = 51 - e; i >= 0; i--) {
+		k /= 2;
+		if (f & ((int64_t)1 << i)) {
+			f64->val2 += k;
+
+		}
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/CMakeLists.txt	(working copy)
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources(
+  mqtt_decoder.c
+  mqtt_encoder.c
+  mqtt_rx.c
+  mqtt_transport_socket_tcp.c
+  mqtt_transport.c
+  mqtt.c
+  )
+
+zephyr_library_sources_ifdef(CONFIG_MQTT_LIB_TLS
+  mqtt_transport_socket_tls.c
+  )
+
+zephyr_library_sources_ifdef(CONFIG_MQTT_LIB_WEBSOCKET
+  mqtt_transport_websocket.c
+  )
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/Kconfig	(working copy)
@@ -0,0 +1,49 @@
+# Socket MQTT Library for Zephyr
+
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+config MQTT_LIB
+	bool "Socket MQTT Library Support"
+	select NET_SOCKETS
+	help
+	  Enable the Zephyr MQTT Library
+
+if MQTT_LIB
+
+module=MQTT
+module-dep=NET_LOG
+module-str=Log level for MQTT
+module-help=Enables mqtt debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config MQTT_KEEPALIVE
+	int "Maximum number of clients Keep alive time for MQTT (in seconds)"
+	default 60
+	help
+	  Keep alive time for MQTT (in seconds). Sending of Ping Requests to
+	  keep the connection alive are governed by this value.
+
+config MQTT_LIB_TLS
+	bool "TLS support for socket MQTT Library"
+	help
+	  Enable TLS support for socket MQTT Library
+
+config MQTT_LIB_WEBSOCKET
+	bool "Websocket support for socket MQTT Library"
+	help
+	  Enable Websocket support for socket MQTT Library.
+
+config MQTT_CLEAN_SESSION
+	bool "MQTT Clean Session Flag."
+	help
+	  When a client connects to a MQTT broker using a persistent session,
+	  the message broker saves all subscriptions. When the client
+	  disconnects, the message broker stores unacknowledged QoS 1 messages
+	  and new QoS 1 messages published to topics to which the client is
+	  subscribed. When the client reconnects to the persistent session,
+	  all subscriptions are reinstated and all stored messages are sent to
+	  the client. Setting this flag to 0 allows the client to create a
+	  persistent session.
+
+endif # MQTT_LIB
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt.c	(working copy)
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt.c
+ *
+ * @brief MQTT Client API Implementation.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt, CONFIG_MQTT_LOG_LEVEL);
+
+#include <net/mqtt.h>
+
+#include "mqtt_transport.h"
+#include "mqtt_internal.h"
+#include "mqtt_os.h"
+
+static void client_reset(struct mqtt_client *client)
+{
+	MQTT_STATE_INIT(client);
+
+	client->internal.last_activity = 0U;
+	client->internal.rx_buf_datalen = 0U;
+	client->internal.remaining_payload = 0U;
+}
+
+/** @brief Initialize tx buffer. */
+static void tx_buf_init(struct mqtt_client *client, struct buf_ctx *buf)
+{
+	memset(client->tx_buf, 0, client->tx_buf_size);
+	buf->cur = client->tx_buf;
+	buf->end = client->tx_buf + client->tx_buf_size;
+}
+
+void event_notify(struct mqtt_client *client, const struct mqtt_evt *evt)
+{
+	if (client->evt_cb != NULL) {
+		mqtt_mutex_unlock(client);
+
+		client->evt_cb(client, evt);
+
+		mqtt_mutex_lock(client);
+	}
+}
+
+static void client_disconnect(struct mqtt_client *client, int result,
+			      bool notify)
+{
+	int err_code;
+
+	err_code = mqtt_transport_disconnect(client);
+	if (err_code < 0) {
+		MQTT_ERR("Failed to disconnect transport!");
+	}
+
+	/* Reset internal state. */
+	client_reset(client);
+
+	if (notify) {
+		struct mqtt_evt evt = {
+			.type = MQTT_EVT_DISCONNECT,
+			.result = result,
+		};
+
+		/* Notify application. */
+		event_notify(client, &evt);
+	}
+}
+
+static int client_connect(struct mqtt_client *client)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	err_code = mqtt_transport_connect(client);
+	if (err_code < 0) {
+		return err_code;
+	}
+
+	tx_buf_init(client, &packet);
+	MQTT_SET_STATE(client, MQTT_STATE_TCP_CONNECTED);
+
+	err_code = connect_request_encode(client, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	/* Send MQTT identification message to broker. */
+	err_code = mqtt_transport_write(client, packet.cur,
+					packet.end - packet.cur);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	client->internal.last_activity = mqtt_sys_tick_in_ms_get();
+
+	/* Reset the unanswered ping count for a new connection */
+	client->unacked_ping = 0;
+
+	MQTT_TRC("Connect completed");
+
+	return 0;
+
+error:
+	client_disconnect(client, err_code, false);
+	return err_code;
+}
+
+static int client_read(struct mqtt_client *client)
+{
+	int err_code;
+
+	if (client->internal.remaining_payload > 0) {
+		return -EBUSY;
+	}
+
+	err_code = mqtt_handle_rx(client);
+	if (err_code < 0) {
+		client_disconnect(client, err_code, true);
+	}
+
+	return err_code;
+}
+
+static int client_write(struct mqtt_client *client, const uint8_t *data,
+			uint32_t datalen)
+{
+	int err_code;
+
+	MQTT_TRC("[%p]: Transport writing %d bytes.", client, datalen);
+
+	err_code = mqtt_transport_write(client, data, datalen);
+	if (err_code < 0) {
+		MQTT_TRC("Transport write failed, err_code = %d, "
+			 "closing connection", err_code);
+		client_disconnect(client, err_code, true);
+		return err_code;
+	}
+
+	MQTT_TRC("[%p]: Transport write complete.", client);
+	client->internal.last_activity = mqtt_sys_tick_in_ms_get();
+
+	return 0;
+}
+
+static int client_write_msg(struct mqtt_client *client,
+			    const struct msghdr *message)
+{
+	int err_code;
+
+	MQTT_TRC("[%p]: Transport writing message.", client);
+
+	err_code = mqtt_transport_write_msg(client, message);
+	if (err_code < 0) {
+		MQTT_TRC("Transport write failed, err_code = %d, "
+			 "closing connection", err_code);
+		client_disconnect(client, err_code, true);
+		return err_code;
+	}
+
+	MQTT_TRC("[%p]: Transport write complete.", client);
+	client->internal.last_activity = mqtt_sys_tick_in_ms_get();
+
+	return 0;
+}
+
+void mqtt_client_init(struct mqtt_client *client)
+{
+	NULL_PARAM_CHECK_VOID(client);
+
+	memset(client, 0, sizeof(*client));
+
+	MQTT_STATE_INIT(client);
+	mqtt_mutex_init(client);
+
+	client->protocol_version = MQTT_VERSION_3_1_1;
+	client->clean_session = MQTT_CLEAN_SESSION;
+	client->keepalive = MQTT_KEEPALIVE;
+}
+
+#if defined(CONFIG_SOCKS)
+int mqtt_client_set_proxy(struct mqtt_client *client,
+			  struct sockaddr *proxy_addr,
+			  socklen_t addrlen)
+{
+	if (IS_ENABLED(CONFIG_SOCKS)) {
+		if (!client || !proxy_addr) {
+			return -EINVAL;
+		}
+
+		client->transport.proxy.addrlen = addrlen;
+		memcpy(&client->transport.proxy.addr, proxy_addr, addrlen);
+
+		return 0;
+	}
+
+	return -ENOTSUP;
+}
+#endif
+
+int mqtt_connect(struct mqtt_client *client)
+{
+	int err_code;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(client->client_id.utf8);
+
+	mqtt_mutex_lock(client);
+
+	if ((client->tx_buf == NULL) || (client->rx_buf == NULL)) {
+		err_code = -ENOMEM;
+		goto error;
+	}
+
+	err_code = client_connect(client);
+
+error:
+	if (err_code < 0) {
+		client_reset(client);
+	}
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+static int verify_tx_state(const struct mqtt_client *client)
+{
+	if (!MQTT_HAS_STATE(client, MQTT_STATE_CONNECTED)) {
+		return -ENOTCONN;
+	}
+
+	return 0;
+}
+
+int mqtt_publish(struct mqtt_client *client,
+		 const struct mqtt_publish_param *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+	struct iovec io_vector[2];
+	struct msghdr msg;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> Topic size 0x%08x, "
+		 "Data size 0x%08x", client, client->internal.state,
+		 param->message.topic.topic.size,
+		 param->message.payload.len);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = publish_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	io_vector[0].iov_base = packet.cur;
+	io_vector[0].iov_len = packet.end - packet.cur;
+	io_vector[1].iov_base = param->message.payload.data;
+	io_vector[1].iov_len = param->message.payload.len;
+
+	memset(&msg, 0, sizeof(msg));
+
+	msg.msg_iov = io_vector;
+	msg.msg_iovlen = ARRAY_SIZE(io_vector);
+
+	err_code = client_write_msg(client, &msg);
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+			 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_publish_qos1_ack(struct mqtt_client *client,
+			  const struct mqtt_puback_param *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> Message id 0x%04x",
+		 client, client->internal.state, param->message_id);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = publish_ack_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+		 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_publish_qos2_receive(struct mqtt_client *client,
+			      const struct mqtt_pubrec_param *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> Message id 0x%04x",
+		 client, client->internal.state, param->message_id);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = publish_receive_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+		 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_publish_qos2_release(struct mqtt_client *client,
+			      const struct mqtt_pubrel_param *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> Message id 0x%04x",
+		 client, client->internal.state, param->message_id);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = publish_release_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+		 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_publish_qos2_complete(struct mqtt_client *client,
+			       const struct mqtt_pubcomp_param *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> Message id 0x%04x",
+		 client, client->internal.state, param->message_id);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = publish_complete_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+	if (err_code < 0) {
+		goto error;
+	}
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+		 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_disconnect(struct mqtt_client *client)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = disconnect_encode(&packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	client_disconnect(client, 0, true);
+
+error:
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_subscribe(struct mqtt_client *client,
+		   const struct mqtt_subscription_list *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	MQTT_TRC("[CID %p]:[State 0x%02x]: >> message id 0x%04x "
+		 "topic count 0x%04x", client, client->internal.state,
+		 param->message_id, param->list_count);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = subscribe_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+error:
+	MQTT_TRC("[CID %p]:[State 0x%02x]: << result 0x%08x",
+		 client, client->internal.state, err_code);
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_unsubscribe(struct mqtt_client *client,
+		     const struct mqtt_subscription_list *param)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+	NULL_PARAM_CHECK(param);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = unsubscribe_encode(param, &packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+error:
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_ping(struct mqtt_client *client)
+{
+	int err_code;
+	struct buf_ctx packet;
+
+	NULL_PARAM_CHECK(client);
+
+	mqtt_mutex_lock(client);
+
+	tx_buf_init(client, &packet);
+
+	err_code = verify_tx_state(client);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = ping_request_encode(&packet);
+	if (err_code < 0) {
+		goto error;
+	}
+
+	err_code = client_write(client, packet.cur, packet.end - packet.cur);
+
+	if (client->unacked_ping >= INT8_MAX) {
+		MQTT_TRC("PING count overflow!");
+	} else {
+		client->unacked_ping++;
+	}
+
+error:
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+int mqtt_abort(struct mqtt_client *client)
+{
+	mqtt_mutex_lock(client);
+
+	NULL_PARAM_CHECK(client);
+
+	if (client->internal.state != MQTT_STATE_IDLE) {
+		client_disconnect(client, -ECONNABORTED, true);
+	}
+
+	mqtt_mutex_unlock(client);
+
+	return 0;
+}
+
+int mqtt_live(struct mqtt_client *client)
+{
+	int err_code = 0;
+	uint32_t elapsed_time;
+	bool ping_sent = false;
+
+	NULL_PARAM_CHECK(client);
+
+	mqtt_mutex_lock(client);
+
+	elapsed_time = mqtt_elapsed_time_in_ms_get(
+				client->internal.last_activity);
+	if ((client->keepalive > 0) &&
+	    (elapsed_time >= (client->keepalive * 1000))) {
+		err_code = mqtt_ping(client);
+		ping_sent = true;
+	}
+
+	mqtt_mutex_unlock(client);
+
+	if (ping_sent) {
+		return err_code;
+	} else {
+		return -EAGAIN;
+	}
+}
+
+uint32_t mqtt_keepalive_time_left(const struct mqtt_client *client)
+{
+	uint32_t elapsed_time = mqtt_elapsed_time_in_ms_get(
+					client->internal.last_activity);
+	uint32_t keepalive_ms = 1000U * client->keepalive;
+
+	if (client->keepalive == 0) {
+		/* Keep alive not enabled. */
+		return UINT32_MAX;
+	}
+
+	if (keepalive_ms <= elapsed_time) {
+		return 0;
+	}
+
+	return keepalive_ms - elapsed_time;
+}
+
+int mqtt_input(struct mqtt_client *client)
+{
+	int err_code = 0;
+
+	NULL_PARAM_CHECK(client);
+
+	mqtt_mutex_lock(client);
+
+	MQTT_TRC("state:0x%08x", client->internal.state);
+
+	if (MQTT_HAS_STATE(client, MQTT_STATE_TCP_CONNECTED)) {
+		err_code = client_read(client);
+	} else {
+		err_code = -EACCES;
+	}
+
+	mqtt_mutex_unlock(client);
+
+	return err_code;
+}
+
+static int read_publish_payload(struct mqtt_client *client, void *buffer,
+				size_t length, bool shall_block)
+{
+	int ret;
+
+	NULL_PARAM_CHECK(client);
+
+	mqtt_mutex_lock(client);
+
+	if (client->internal.remaining_payload == 0U) {
+		ret = 0;
+		goto exit;
+	}
+
+	if (client->internal.remaining_payload < length) {
+		length = client->internal.remaining_payload;
+	}
+
+	ret = mqtt_transport_read(client, buffer, length, shall_block);
+	if (!shall_block && ret == -EAGAIN) {
+		goto exit;
+	}
+
+	if (ret <= 0) {
+		if (ret == 0) {
+			ret = -ENOTCONN;
+		}
+
+		client_disconnect(client, ret, true);
+		goto exit;
+	}
+
+	client->internal.remaining_payload -= ret;
+
+exit:
+	mqtt_mutex_unlock(client);
+
+	return ret;
+}
+
+int mqtt_read_publish_payload(struct mqtt_client *client, void *buffer,
+			      size_t length)
+{
+	return read_publish_payload(client, buffer, length, false);
+}
+
+int mqtt_read_publish_payload_blocking(struct mqtt_client *client, void *buffer,
+				       size_t length)
+{
+	return read_publish_payload(client, buffer, length, true);
+}
+
+int mqtt_readall_publish_payload(struct mqtt_client *client, uint8_t *buffer,
+				 size_t length)
+{
+	uint8_t *end = buffer + length;
+
+	while (buffer < end) {
+		int ret = mqtt_read_publish_payload_blocking(client, buffer,
+							     end - buffer);
+
+		if (ret < 0) {
+			return ret;
+		} else if (ret == 0) {
+			return -EIO;
+		}
+
+		buffer += ret;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_decoder.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_decoder.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_decoder.c	(working copy)
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_decoder.c
+ *
+ * @brief Decoder functions needed for decoding packets received from the
+ *        broker.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_dec, CONFIG_MQTT_LOG_LEVEL);
+
+#include "mqtt_internal.h"
+#include "mqtt_os.h"
+
+/**
+ * @brief Unpacks unsigned 8 bit value from the buffer from the offset
+ *        requested.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] val Memory where the value is to be unpacked.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EINVAL if the buffer would be exceeded during the read
+ */
+static int unpack_uint8(struct buf_ctx *buf, uint8_t *val)
+{
+	MQTT_TRC(">> cur:%p, end:%p", buf->cur, buf->end);
+
+	if ((buf->end - buf->cur) < sizeof(uint8_t)) {
+		return -EINVAL;
+	}
+
+	*val = *(buf->cur++);
+
+	MQTT_TRC("<< val:%02x", *val);
+
+	return 0;
+}
+
+/**
+ * @brief Unpacks unsigned 16 bit value from the buffer from the offset
+ *        requested.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] val Memory where the value is to be unpacked.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EINVAL if the buffer would be exceeded during the read
+ */
+static int unpack_uint16(struct buf_ctx *buf, uint16_t *val)
+{
+	MQTT_TRC(">> cur:%p, end:%p", buf->cur, buf->end);
+
+	if ((buf->end - buf->cur) < sizeof(uint16_t)) {
+		return -EINVAL;
+	}
+
+	*val = *(buf->cur++) << 8; /* MSB */
+	*val |= *(buf->cur++); /* LSB */
+
+	MQTT_TRC("<< val:%04x", *val);
+
+	return 0;
+}
+
+/**
+ * @brief Unpacks utf8 string from the buffer from the offset requested.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] str Pointer to a string that will hold the string location
+ *                 in the buffer.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EINVAL if the buffer would be exceeded during the read
+ */
+static int unpack_utf8_str(struct buf_ctx *buf, struct mqtt_utf8 *str)
+{
+	uint16_t utf8_strlen;
+	int err_code;
+
+	MQTT_TRC(">> cur:%p, end:%p", buf->cur, buf->end);
+
+	err_code = unpack_uint16(buf, &utf8_strlen);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	if ((buf->end - buf->cur) < utf8_strlen) {
+		return -EINVAL;
+	}
+
+	str->size = utf8_strlen;
+	/* Zero length UTF8 strings permitted. */
+	if (utf8_strlen) {
+		/* Point to right location in buffer. */
+		str->utf8 = buf->cur;
+		buf->cur += utf8_strlen;
+	} else {
+		str->utf8 = NULL;
+	}
+
+	MQTT_TRC("<< str_size:%08x", (uint32_t)GET_UT8STR_BUFFER_SIZE(str));
+
+	return 0;
+}
+
+/**
+ * @brief Unpacks binary string from the buffer from the offset requested.
+ *
+ * @param[in] length Binary string length.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] str Pointer to a binary string that will hold the binary string
+ *                 location in the buffer.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EINVAL if the buffer would be exceeded during the read
+ */
+static int unpack_data(uint32_t length, struct buf_ctx *buf,
+		       struct mqtt_binstr *str)
+{
+	MQTT_TRC(">> cur:%p, end:%p", buf->cur, buf->end);
+
+	if ((buf->end - buf->cur) < length) {
+		return -EINVAL;
+	}
+
+	str->len = length;
+
+	/* Zero length binary strings are permitted. */
+	if (length > 0) {
+		str->data = buf->cur;
+		buf->cur += length;
+	} else {
+		str->data = NULL;
+	}
+
+	MQTT_TRC("<< bin len:%08x", GET_BINSTR_BUFFER_SIZE(str));
+
+	return 0;
+}
+
+/**@brief Decode MQTT Packet Length in the MQTT fixed header.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] length Length of variable header and payload in the
+ *                              MQTT message.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EINVAL if the length decoding would use more that 4 bytes.
+ * @retval -EAGAIN if the buffer would be exceeded during the read.
+ */
+static int packet_length_decode(struct buf_ctx *buf, uint32_t *length)
+{
+	uint8_t shift = 0U;
+	uint8_t bytes = 0U;
+
+	*length = 0U;
+	do {
+		if (bytes >= MQTT_MAX_LENGTH_BYTES) {
+			return -EINVAL;
+		}
+
+		if (buf->cur >= buf->end) {
+			return -EAGAIN;
+		}
+
+		*length += ((uint32_t)*(buf->cur) & MQTT_LENGTH_VALUE_MASK)
+								<< shift;
+		shift += MQTT_LENGTH_SHIFT;
+		bytes++;
+	} while ((*(buf->cur++) & MQTT_LENGTH_CONTINUATION_BIT) != 0U);
+
+	if (*length > MQTT_MAX_PAYLOAD_SIZE) {
+		return -EINVAL;
+	}
+
+	MQTT_TRC("length:0x%08x", *length);
+
+	return 0;
+}
+
+int fixed_header_decode(struct buf_ctx *buf, uint8_t *type_and_flags,
+			uint32_t *length)
+{
+	int err_code;
+
+	err_code = unpack_uint8(buf, type_and_flags);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	return packet_length_decode(buf, length);
+}
+
+int connect_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf,
+		       struct mqtt_connack_param *param)
+{
+	int err_code;
+	uint8_t flags, ret_code;
+
+	err_code = unpack_uint8(buf, &flags);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	err_code = unpack_uint8(buf, &ret_code);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	if (client->protocol_version == MQTT_VERSION_3_1_1) {
+		param->session_present_flag =
+			flags & MQTT_CONNACK_FLAG_SESSION_PRESENT;
+
+		MQTT_TRC("[CID %p]: session_present_flag: %d", client,
+			 param->session_present_flag);
+	}
+
+	param->return_code = (enum mqtt_conn_return_code)ret_code;
+
+	return 0;
+}
+
+int publish_decode(uint8_t flags, uint32_t var_length, struct buf_ctx *buf,
+		   struct mqtt_publish_param *param)
+{
+	int err_code;
+	uint32_t var_header_length;
+
+	param->dup_flag = flags & MQTT_HEADER_DUP_MASK;
+	param->retain_flag = flags & MQTT_HEADER_RETAIN_MASK;
+	param->message.topic.qos = ((flags & MQTT_HEADER_QOS_MASK) >> 1);
+
+	err_code = unpack_utf8_str(buf, &param->message.topic.topic);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	var_header_length = param->message.topic.topic.size + sizeof(uint16_t);
+
+	if (param->message.topic.qos > MQTT_QOS_0_AT_MOST_ONCE) {
+		err_code = unpack_uint16(buf, &param->message_id);
+		if (err_code != 0) {
+			return err_code;
+		}
+
+		var_header_length += sizeof(uint16_t);
+	}
+
+	if (var_length < var_header_length) {
+		MQTT_ERR("Corrupted PUBLISH message, header length (%u) larger "
+			 "than total length (%u)", var_header_length,
+			 var_length);
+		return -EINVAL;
+	}
+
+	param->message.payload.data = NULL;
+	param->message.payload.len = var_length - var_header_length;
+
+	return 0;
+}
+
+int publish_ack_decode(struct buf_ctx *buf, struct mqtt_puback_param *param)
+{
+	return unpack_uint16(buf, &param->message_id);
+}
+
+int publish_receive_decode(struct buf_ctx *buf, struct mqtt_pubrec_param *param)
+{
+	return unpack_uint16(buf, &param->message_id);
+}
+
+int publish_release_decode(struct buf_ctx *buf, struct mqtt_pubrel_param *param)
+{
+	return unpack_uint16(buf, &param->message_id);
+}
+
+int publish_complete_decode(struct buf_ctx *buf,
+			    struct mqtt_pubcomp_param *param)
+{
+	return unpack_uint16(buf, &param->message_id);
+}
+
+int subscribe_ack_decode(struct buf_ctx *buf, struct mqtt_suback_param *param)
+{
+	int err_code;
+
+	err_code = unpack_uint16(buf, &param->message_id);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	return unpack_data(buf->end - buf->cur, buf, &param->return_codes);
+}
+
+int unsubscribe_ack_decode(struct buf_ctx *buf,
+			   struct mqtt_unsuback_param *param)
+{
+	return unpack_uint16(buf, &param->message_id);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_encoder.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_encoder.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_encoder.c	(working copy)
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_encoder.c
+ *
+ * @brief Encoding functions needed to create packet to be sent to the broker.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_enc, CONFIG_MQTT_LOG_LEVEL);
+
+#include "mqtt_internal.h"
+#include "mqtt_os.h"
+
+static const struct mqtt_utf8 mqtt_3_1_0_proto_desc =
+	MQTT_UTF8_LITERAL("MQIsdp");
+
+static const struct mqtt_utf8 mqtt_3_1_1_proto_desc =
+	MQTT_UTF8_LITERAL("MQTT");
+
+/** Never changing ping request, needed for Keep Alive. */
+static const uint8_t ping_packet[MQTT_FIXED_HEADER_MIN_SIZE] = {
+	MQTT_PKT_TYPE_PINGREQ,
+	0x00
+};
+
+/** Never changing disconnect request. */
+static const uint8_t disc_packet[MQTT_FIXED_HEADER_MIN_SIZE] = {
+	MQTT_PKT_TYPE_DISCONNECT,
+	0x00
+};
+
+/**
+ * @brief Packs unsigned 8 bit value to the buffer at the offset requested.
+ *
+ * @param[in] val Value to be packed.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ *
+ * @retval 0 if procedure is successful.
+ * @retval -ENOMEM if there is no place in the buffer to store the value.
+ */
+static int pack_uint8(uint8_t val, struct buf_ctx *buf)
+{
+	if ((buf->end - buf->cur) < sizeof(uint8_t)) {
+		return -ENOMEM;
+	}
+
+	MQTT_TRC(">> val:%02x cur:%p, end:%p", val, buf->cur, buf->end);
+
+	/* Pack value. */
+	*(buf->cur++) = val;
+
+	return 0;
+}
+
+/**
+ * @brief Packs unsigned 16 bit value to the buffer at the offset requested.
+ *
+ * @param[in] val Value to be packed.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -ENOMEM if there is no place in the buffer to store the value.
+ */
+static int pack_uint16(uint16_t val, struct buf_ctx *buf)
+{
+	if ((buf->end - buf->cur) < sizeof(uint16_t)) {
+		return -ENOMEM;
+	}
+
+	MQTT_TRC(">> val:%04x cur:%p, end:%p", val, buf->cur, buf->end);
+
+	/* Pack value. */
+	*(buf->cur++) = (val >> 8) & 0xFF;
+	*(buf->cur++) = val & 0xFF;
+
+	return 0;
+}
+
+/**
+ * @brief Packs utf8 string to the buffer at the offset requested.
+ *
+ * @param[in] str UTF-8 string and its length to be packed.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -ENOMEM if there is no place in the buffer to store the string.
+ */
+static int pack_utf8_str(const struct mqtt_utf8 *str, struct buf_ctx *buf)
+{
+	if ((buf->end - buf->cur) < GET_UT8STR_BUFFER_SIZE(str)) {
+		return -ENOMEM;
+	}
+
+	MQTT_TRC(">> str_size:%08x cur:%p, end:%p",
+		 (uint32_t)GET_UT8STR_BUFFER_SIZE(str), buf->cur, buf->end);
+
+	/* Pack length followed by string. */
+	(void)pack_uint16(str->size, buf);
+
+	memcpy(buf->cur, str->utf8, str->size);
+	buf->cur += str->size;
+
+	return 0;
+}
+
+/**
+ * @brief Computes and encodes length for the MQTT fixed header.
+ *
+ * @note The remaining length is not packed as a fixed unsigned 32 bit integer.
+ *       Instead it is packed on algorithm below:
+ *
+ * @code
+ * do
+ *            encodedByte = X MOD 128
+ *            X = X DIV 128
+ *            // if there are more data to encode, set the top bit of this byte
+ *            if ( X > 0 )
+ *                encodedByte = encodedByte OR 128
+ *            endif
+ *                'output' encodedByte
+ *       while ( X > 0 )
+ * @endcode
+ *
+ * @param[in] length Length of variable header and payload in the MQTT message.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position. May be NULL (in this case function will
+ *                   only calculate number of bytes needed).
+ *
+ * @return Number of bytes needed to encode length value.
+ */
+static uint8_t packet_length_encode(uint32_t length, struct buf_ctx *buf)
+{
+	uint8_t encoded_bytes = 0U;
+
+	MQTT_TRC(">> length:0x%08x cur:%p, end:%p", length,
+		 (buf == NULL) ? 0 : buf->cur, (buf == NULL) ? 0 : buf->end);
+
+	do {
+		encoded_bytes++;
+
+		if (buf != NULL) {
+			*(buf->cur) = length & MQTT_LENGTH_VALUE_MASK;
+		}
+
+		length >>= MQTT_LENGTH_SHIFT;
+
+		if (buf != NULL) {
+			if (length > 0) {
+				*(buf->cur) |= MQTT_LENGTH_CONTINUATION_BIT;
+			}
+			buf->cur++;
+		}
+	} while (length > 0);
+
+	return encoded_bytes;
+}
+
+/**
+ * @brief Encodes fixed header for the MQTT message and provides pointer to
+ *        start of the header.
+ *
+ * @param[in] message_type Message type containing packet type and the flags.
+ *                         Use @ref MQTT_MESSAGES_OPTIONS to construct the
+ *                         message_type.
+ * @param[in] start  Pointer to the start of the variable header.
+ * @param[inout] buf Buffer context used to encode the frame.
+ *                   The 5 bytes before the start of the message are assumed
+ *                   by the routine to be available to pack the fixed header.
+ *                   However, since the fixed header length is variable
+ *                   length, the pointer to the start of the MQTT message
+ *                   along with encoded fixed header is supplied as output
+ *                   parameter if the procedure was successful.
+ *                   As output, the pointers will point to beginning and the end
+ *                   of the frame.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -EMSGSIZE if the message is too big for MQTT.
+ */
+static uint32_t mqtt_encode_fixed_header(uint8_t message_type, uint8_t *start,
+				      struct buf_ctx *buf)
+{
+	uint32_t length = buf->cur - start;
+	uint8_t fixed_header_length;
+
+	if (length > MQTT_MAX_PAYLOAD_SIZE) {
+		return -EMSGSIZE;
+	}
+
+	MQTT_TRC("<< msg type:0x%02x length:0x%08x", message_type, length);
+
+	fixed_header_length = packet_length_encode(length, NULL);
+	fixed_header_length += sizeof(uint8_t);
+
+	MQTT_TRC("Fixed header length = %02x", fixed_header_length);
+
+	/* Set the pointer at the start of the frame before encoding. */
+	buf->cur = start - fixed_header_length;
+
+	(void)pack_uint8(message_type, buf);
+	(void)packet_length_encode(length, buf);
+
+	/* Set the cur pointer back at the start of the frame,
+	 * and end pointer to the end of the frame.
+	 */
+	buf->cur = buf->cur - fixed_header_length;
+	buf->end = buf->cur + length + fixed_header_length;
+
+	return 0;
+}
+
+/**
+ * @brief Encodes a string of a zero length.
+ *
+ * @param[in] buffer_len Total size of the buffer on which string will be
+ *                       encoded. This shall not be zero.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ *
+ * @retval 0 if the procedure is successful.
+ * @retval -ENOMEM if there is no place in the buffer to store the binary
+ *                 string.
+ */
+static int zero_len_str_encode(struct buf_ctx *buf)
+{
+	return pack_uint16(0x0000, buf);
+}
+
+/**
+ * @brief Encodes and sends messages that contain only message id in
+ *        the variable header.
+ *
+ * @param[in] message_type Message type and reserved bit fields.
+ * @param[in] message_id Message id to be encoded in the variable header.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *
+ * @retval 0 or an error code indicating a reason for failure.
+ */
+static int mqtt_message_id_only_enc(uint8_t message_type, uint16_t message_id,
+				    struct buf_ctx *buf)
+{
+	int err_code;
+	uint8_t *start;
+
+	/* Message id zero is not permitted by spec. */
+	if (message_id == 0U) {
+		return -EINVAL;
+	}
+
+	/* Reserve space for fixed header. */
+	buf->cur += MQTT_FIXED_HEADER_MAX_SIZE;
+	start = buf->cur;
+
+	err_code = pack_uint16(message_id, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	return mqtt_encode_fixed_header(message_type, start, buf);
+}
+
+int connect_request_encode(const struct mqtt_client *client,
+			   struct buf_ctx *buf)
+{
+	uint8_t connect_flags = client->clean_session << 1;
+	const uint8_t message_type =
+			MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_CONNECT, 0, 0, 0);
+	const struct mqtt_utf8 *mqtt_proto_desc;
+	uint8_t *connect_flags_pos;
+	int err_code;
+	uint8_t *start;
+
+	if (client->protocol_version == MQTT_VERSION_3_1_1) {
+		mqtt_proto_desc = &mqtt_3_1_1_proto_desc;
+	} else {
+		mqtt_proto_desc = &mqtt_3_1_0_proto_desc;
+	}
+
+	/* Reserve space for fixed header. */
+	buf->cur += MQTT_FIXED_HEADER_MAX_SIZE;
+	start = buf->cur;
+
+	MQTT_TRC("Encoding Protocol Description. Str:%s Size:%08x.",
+		 mqtt_proto_desc->utf8, mqtt_proto_desc->size);
+
+	err_code = pack_utf8_str(mqtt_proto_desc, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	MQTT_TRC("Encoding Protocol Version %02x.", client->protocol_version);
+	err_code = pack_uint8(client->protocol_version, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	/* Remember position of connect flag and leave one byte for it to
+	 * be packed once we determine its value.
+	 */
+	connect_flags_pos = buf->cur;
+
+	err_code = pack_uint8(0, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	MQTT_TRC("Encoding Keep Alive Time %04x.", client->keepalive);
+	err_code = pack_uint16(client->keepalive, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	MQTT_TRC("Encoding Client Id. Str:%s Size:%08x.",
+		 client->client_id.utf8, client->client_id.size);
+	err_code = pack_utf8_str(&client->client_id, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	/* Pack will topic and QoS */
+	if (client->will_topic != NULL) {
+		connect_flags |= MQTT_CONNECT_FLAG_WILL_TOPIC;
+		/* QoS is always 1 as of now. */
+		connect_flags |= ((client->will_topic->qos & 0x03) << 3);
+		connect_flags |= client->will_retain << 5;
+
+		MQTT_TRC("Encoding Will Topic. Str:%s Size:%08x.",
+			 client->will_topic->topic.utf8,
+			 client->will_topic->topic.size);
+		err_code = pack_utf8_str(&client->will_topic->topic, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+
+		if (client->will_message != NULL) {
+			MQTT_TRC("Encoding Will Message. Str:%s Size:%08x.",
+				 client->will_message->utf8,
+				 client->will_message->size);
+			err_code = pack_utf8_str(client->will_message, buf);
+			if (err_code != 0) {
+				return err_code;
+			}
+		} else {
+			MQTT_TRC("Encoding Zero Length Will Message.");
+			err_code = zero_len_str_encode(buf);
+			if (err_code != 0) {
+				return err_code;
+			}
+		}
+	}
+
+	/* Pack Username if any. */
+	if (client->user_name != NULL) {
+		connect_flags |= MQTT_CONNECT_FLAG_USERNAME;
+
+		MQTT_TRC("Encoding Username. Str:%s, Size:%08x.",
+			 client->user_name->utf8, client->user_name->size);
+		err_code = pack_utf8_str(client->user_name, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+	}
+
+	/* Pack Password if any. */
+	if (client->password != NULL) {
+		connect_flags |= MQTT_CONNECT_FLAG_PASSWORD;
+
+		MQTT_TRC("Encoding Password. Str:%s Size:%08x.",
+			 client->password->utf8, client->password->size);
+		err_code = pack_utf8_str(client->password, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+	}
+
+	/* Write the flags the connect flags. */
+	*connect_flags_pos = connect_flags;
+
+	return mqtt_encode_fixed_header(message_type, start, buf);
+}
+
+int publish_encode(const struct mqtt_publish_param *param, struct buf_ctx *buf)
+{
+	const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
+			MQTT_PKT_TYPE_PUBLISH, param->dup_flag,
+			param->message.topic.qos, param->retain_flag);
+	int err_code;
+	uint8_t *start;
+
+	/* Message id zero is not permitted by spec. */
+	if ((param->message.topic.qos) && (param->message_id == 0U)) {
+		return -EINVAL;
+	}
+
+	/* Reserve space for fixed header. */
+	buf->cur += MQTT_FIXED_HEADER_MAX_SIZE;
+	start = buf->cur;
+
+	err_code = pack_utf8_str(&param->message.topic.topic, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	if (param->message.topic.qos) {
+		err_code = pack_uint16(param->message_id, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+	}
+
+	/* Do not copy payload. We move the buffer pointer to ensure that
+	 * message length in fixed header is encoded correctly.
+	 */
+	buf->cur += param->message.payload.len;
+
+	err_code = mqtt_encode_fixed_header(message_type, start, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	buf->end -= param->message.payload.len;
+
+	return 0;
+}
+
+int publish_ack_encode(const struct mqtt_puback_param *param,
+		       struct buf_ctx *buf)
+{
+	const uint8_t message_type =
+		MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_PUBACK, 0, 0, 0);
+
+	return mqtt_message_id_only_enc(message_type, param->message_id, buf);
+}
+
+int publish_receive_encode(const struct mqtt_pubrec_param *param,
+			   struct buf_ctx *buf)
+{
+	const uint8_t message_type =
+		MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_PUBREC, 0, 0, 0);
+
+	return mqtt_message_id_only_enc(message_type, param->message_id, buf);
+}
+
+int publish_release_encode(const struct mqtt_pubrel_param *param,
+			   struct buf_ctx *buf)
+{
+	const uint8_t message_type =
+		MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_PUBREL, 0, 1, 0);
+
+	return mqtt_message_id_only_enc(message_type, param->message_id, buf);
+}
+
+int publish_complete_encode(const struct mqtt_pubcomp_param *param,
+			    struct buf_ctx *buf)
+{
+	const uint8_t message_type =
+		MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_PUBCOMP, 0, 0, 0);
+
+	return mqtt_message_id_only_enc(message_type, param->message_id, buf);
+}
+
+int disconnect_encode(struct buf_ctx *buf)
+{
+	if (buf->end - buf->cur < sizeof(disc_packet)) {
+		return -ENOMEM;
+	}
+
+	memcpy(buf->cur, disc_packet, sizeof(disc_packet));
+	buf->end = buf->cur + sizeof(disc_packet);
+
+	return 0;
+}
+
+int subscribe_encode(const struct mqtt_subscription_list *param,
+		     struct buf_ctx *buf)
+{
+	const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
+			MQTT_PKT_TYPE_SUBSCRIBE, 0, 1, 0);
+	int err_code, i;
+	uint8_t *start;
+
+	/* Message id zero is not permitted by spec. */
+	if (param->message_id == 0U) {
+		return -EINVAL;
+	}
+
+	/* Reserve space for fixed header. */
+	buf->cur += MQTT_FIXED_HEADER_MAX_SIZE;
+	start = buf->cur;
+
+	err_code = pack_uint16(param->message_id, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	for (i = 0; i < param->list_count; i++) {
+		err_code = pack_utf8_str(&param->list[i].topic, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+
+		err_code = pack_uint8(param->list[i].qos, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+	}
+
+	return mqtt_encode_fixed_header(message_type, start, buf);
+}
+
+int unsubscribe_encode(const struct mqtt_subscription_list *param,
+		       struct buf_ctx *buf)
+{
+	const uint8_t message_type = MQTT_MESSAGES_OPTIONS(
+		MQTT_PKT_TYPE_UNSUBSCRIBE, 0, MQTT_QOS_1_AT_LEAST_ONCE, 0);
+	int err_code, i;
+	uint8_t *start;
+
+	/* Reserve space for fixed header. */
+	buf->cur += MQTT_FIXED_HEADER_MAX_SIZE;
+	start = buf->cur;
+
+	err_code = pack_uint16(param->message_id, buf);
+	if (err_code != 0) {
+		return err_code;
+	}
+
+	for (i = 0; i < param->list_count; i++) {
+		err_code = pack_utf8_str(&param->list[i].topic, buf);
+		if (err_code != 0) {
+			return err_code;
+		}
+	}
+
+	return mqtt_encode_fixed_header(message_type, start, buf);
+}
+
+int ping_request_encode(struct buf_ctx *buf)
+{
+	if (buf->end - buf->cur < sizeof(ping_packet)) {
+		return -ENOMEM;
+	}
+
+	memcpy(buf->cur, ping_packet, sizeof(ping_packet));
+	buf->end = buf->cur + sizeof(ping_packet);
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_internal.h	(working copy)
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_internal.h
+ *
+ * @brief Function and data structures internal to MQTT module.
+ */
+
+#ifndef MQTT_INTERNAL_H_
+#define MQTT_INTERNAL_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include <net/mqtt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Keep alive time for MQTT (in seconds). Sending of Ping Requests to
+ *        keep the connection alive are governed by this value.
+ */
+#define MQTT_KEEPALIVE CONFIG_MQTT_KEEPALIVE
+
+/**@brief Clean session on every connect (1) or keep subscriptions and messages
+ *        between connects (0)
+ */
+#define MQTT_CLEAN_SESSION (IS_ENABLED(CONFIG_MQTT_CLEAN_SESSION) ? 1U : 0U)
+
+/**@brief Minimum mandatory size of fixed header. */
+#define MQTT_FIXED_HEADER_MIN_SIZE 2
+
+/**@brief Maximum size of the fixed header. Remaining length size is 4 in this
+ *        case.
+ */
+#define MQTT_FIXED_HEADER_MAX_SIZE 5
+
+/**@brief MQTT Control Packet Types. */
+#define MQTT_PKT_TYPE_CONNECT     0x10
+#define MQTT_PKT_TYPE_CONNACK     0x20
+#define MQTT_PKT_TYPE_PUBLISH     0x30
+#define MQTT_PKT_TYPE_PUBACK      0x40
+#define MQTT_PKT_TYPE_PUBREC      0x50
+#define MQTT_PKT_TYPE_PUBREL      0x60
+#define MQTT_PKT_TYPE_PUBCOMP     0x70
+#define MQTT_PKT_TYPE_SUBSCRIBE   0x80
+#define MQTT_PKT_TYPE_SUBACK      0x90
+#define MQTT_PKT_TYPE_UNSUBSCRIBE 0xA0
+#define MQTT_PKT_TYPE_UNSUBACK    0xB0
+#define MQTT_PKT_TYPE_PINGREQ     0xC0
+#define MQTT_PKT_TYPE_PINGRSP     0xD0
+#define MQTT_PKT_TYPE_DISCONNECT  0xE0
+
+/**@brief Masks for MQTT header flags. */
+#define MQTT_HEADER_DUP_MASK     0x08
+#define MQTT_HEADER_QOS_MASK     0x06
+#define MQTT_HEADER_RETAIN_MASK  0x01
+
+/**@brief Masks for MQTT header flags. */
+#define MQTT_CONNECT_FLAG_CLEAN_SESSION   0x02
+#define MQTT_CONNECT_FLAG_WILL_TOPIC      0x04
+#define MQTT_CONNECT_FLAG_WILL_RETAIN     0x20
+#define MQTT_CONNECT_FLAG_PASSWORD        0x40
+#define MQTT_CONNECT_FLAG_USERNAME        0x80
+
+#define MQTT_CONNACK_FLAG_SESSION_PRESENT 0x01
+
+/**@brief Maximum payload size of MQTT packet. */
+#define MQTT_MAX_PAYLOAD_SIZE 0x0FFFFFFF
+
+/**@brief Computes total size needed to pack a UTF8 string. */
+#define GET_UT8STR_BUFFER_SIZE(STR) (sizeof(uint16_t) + (STR)->size)
+
+/**@brief Computes total size needed to pack a binary stream. */
+#define GET_BINSTR_BUFFER_SIZE(STR) ((STR)->len)
+
+/**@brief Sets MQTT Client's state with one indicated in 'STATE'. */
+#define MQTT_SET_STATE(CLIENT, STATE) ((CLIENT)->internal.state |= (STATE))
+
+/**@brief Sets MQTT Client's state exclusive to 'STATE'. */
+#define MQTT_SET_STATE_EXCLUSIVE(CLIENT, STATE) \
+					((CLIENT)->internal.state = (STATE))
+
+/**@brief Verifies if MQTT Client's state is set with one indicated in 'STATE'.
+ */
+#define MQTT_HAS_STATE(CLIENT, STATE) ((CLIENT)->internal.state & (STATE))
+
+/**@brief Reset 'STATE' in MQTT Client's state. */
+#define MQTT_RESET_STATE(CLIENT, STATE) ((CLIENT)->internal.state &= ~(STATE))
+
+/**@brief Initialize MQTT Client's state. */
+#define MQTT_STATE_INIT(CLIENT) ((CLIENT)->internal.state = MQTT_STATE_IDLE)
+
+/**@brief Computes the first byte of MQTT message header based on message type,
+ *        duplication flag, QoS and  the retain flag.
+ */
+#define MQTT_MESSAGES_OPTIONS(TYPE, DUP, QOS, RETAIN) \
+	(((TYPE)      & 0xF0)  | \
+	 (((DUP) << 3) & 0x08) | \
+	 (((QOS) << 1) & 0x06) | \
+	 ((RETAIN) & 0x01))
+
+#define MQTT_MAX_LENGTH_BYTES 4
+#define MQTT_LENGTH_VALUE_MASK 0x7F
+#define MQTT_LENGTH_CONTINUATION_BIT 0x80
+#define MQTT_LENGTH_SHIFT 7
+
+/**@brief Check if the input pointer is NULL, if so it returns -EINVAL. */
+#define NULL_PARAM_CHECK(param) \
+	do { \
+		if ((param) == NULL) { \
+			return -EINVAL; \
+		} \
+	} while (0)
+
+#define NULL_PARAM_CHECK_VOID(param) \
+	do { \
+		if ((param) == NULL) { \
+			return; \
+		} \
+	} while (0)
+
+/** Buffer context to iterate over buffer. */
+struct buf_ctx {
+	uint8_t *cur;
+	uint8_t *end;
+};
+
+/**@brief MQTT States. */
+enum mqtt_state {
+	/** Idle state, implying the client entry in the table is unused/free.
+	 */
+	MQTT_STATE_IDLE                 = 0x00000000,
+
+	/** TCP Connection has been requested, awaiting result of the request.
+	 */
+	MQTT_STATE_TCP_CONNECTING       = 0x00000001,
+
+	/** TCP Connection successfully established. */
+	MQTT_STATE_TCP_CONNECTED        = 0x00000002,
+
+	/** MQTT Connection successful. */
+	MQTT_STATE_CONNECTED            = 0x00000004,
+};
+
+/**@brief Notify application about MQTT event.
+ *
+ * @param[in] client Identifies the client for which event occurred.
+ * @param[in] evt MQTT event.
+ */
+void event_notify(struct mqtt_client *client, const struct mqtt_evt *evt);
+
+/**@brief Handles MQTT messages received from the peer.
+ *
+ * @param[in] client Identifies the client for which the data was received.
+
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int mqtt_handle_rx(struct mqtt_client *client);
+
+/**@brief Constructs/encodes Connect packet.
+ *
+ * @param[in] client Identifies the client for which the procedure is requested.
+ *                   All information required for creating the packet like
+ *                   client id, clean session flag, retain session flag etc are
+ *                   assumed to be populated for the client instance when this
+ *                   procedure is requested.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int connect_request_encode(const struct mqtt_client *client,
+			   struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Publish packet.
+ *
+ * @param[in] param Publish message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_encode(const struct mqtt_publish_param *param, struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Publish Ack packet.
+ *
+ * @param[in] param Publish Ack message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_ack_encode(const struct mqtt_puback_param *param,
+		       struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Publish Receive packet.
+ *
+ * @param[in] param Publish Receive message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_receive_encode(const struct mqtt_pubrec_param *param,
+			   struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Publish Release packet.
+ *
+ * @param[in] param Publish Release message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_release_encode(const struct mqtt_pubrel_param *param,
+			   struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Publish Complete packet.
+ *
+ * @param[in] param Publish Complete message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_complete_encode(const struct mqtt_pubcomp_param *param,
+			    struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Disconnect packet.
+ *
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int disconnect_encode(struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Subscribe packet.
+ *
+ * @param[in] param Subscribe message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int subscribe_encode(const struct mqtt_subscription_list *param,
+		     struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Unsubscribe packet.
+ *
+ * @param[in] param Unsubscribe message parameters.
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int unsubscribe_encode(const struct mqtt_subscription_list *param,
+		       struct buf_ctx *buf);
+
+/**@brief Constructs/encodes Ping Request packet.
+ *
+ * @param[inout] buf_ctx Pointer to the buffer context structure,
+ *                       containing buffer for the encoded message.
+ *                       As output points to the beginning and end of
+ *                       the frame.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int ping_request_encode(struct buf_ctx *buf);
+
+/**@brief Decode MQTT Packet Type and Length in the MQTT fixed header.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] type_and_flags Message type and flags.
+ * @param[out] length Length of variable header and payload in the MQTT message.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int fixed_header_decode(struct buf_ctx *buf, uint8_t *type_and_flags,
+			uint32_t *length);
+
+/**@brief Decode MQTT Connect Ack packet.
+ *
+ * @param[in] client MQTT client for which packet is decoded.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Connect Ack parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int connect_ack_decode(const struct mqtt_client *client, struct buf_ctx *buf,
+		       struct mqtt_connack_param *param);
+
+/**@brief Decode MQTT Publish packet.
+ *
+ * @param[in] flags Byte containing message type and flags.
+ * @param[in] var_length Length of the variable part of the message.
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Publish parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_decode(uint8_t flags, uint32_t var_length, struct buf_ctx *buf,
+		   struct mqtt_publish_param *param);
+
+/**@brief Decode MQTT Publish Ack packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Publish Ack parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_ack_decode(struct buf_ctx *buf, struct mqtt_puback_param *param);
+
+/**@brief Decode MQTT Publish Receive packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Publish Receive parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_receive_decode(struct buf_ctx *buf,
+			   struct mqtt_pubrec_param *param);
+
+/**@brief Decode MQTT Publish Release packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Publish Release parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_release_decode(struct buf_ctx *buf,
+			   struct mqtt_pubrel_param *param);
+
+/**@brief Decode MQTT Publish Complete packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Publish Complete parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int publish_complete_decode(struct buf_ctx *buf,
+			    struct mqtt_pubcomp_param *param);
+
+/**@brief Decode MQTT Subscribe packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Subscribe parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int subscribe_ack_decode(struct buf_ctx *buf,
+			 struct mqtt_suback_param *param);
+
+/**@brief Decode MQTT Unsubscribe packet.
+ *
+ * @param[inout] buf A pointer to the buf_ctx structure containing current
+ *                   buffer position.
+ * @param[out] param Pointer to buffer for decoded Unsubscribe parameters.
+ *
+ * @return 0 if the procedure is successful, an error code otherwise.
+ */
+int unsubscribe_ack_decode(struct buf_ctx *buf,
+			   struct mqtt_unsuback_param *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MQTT_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_os.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_os.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_os.h	(working copy)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_os.h
+ *
+ * @brief MQTT Client depends on certain OS specific functionality. The needed
+ *        methods are mapped here and should be implemented based on OS in use.
+ *
+ * @details Memory management, mutex, logging and wall clock are the needed
+ *          functionality for MQTT module. The needed interfaces are defined
+ *          in the OS. OS specific port of the interface shall be provided.
+ *
+ */
+
+#ifndef MQTT_OS_H_
+#define MQTT_OS_H_
+
+#include <stddef.h>
+#include <kernel.h>
+#include <sys/mutex.h>
+
+#include <net/net_core.h>
+
+#include "mqtt_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Method to get trace logs from the module. */
+#define MQTT_TRC(...) NET_DBG(__VA_ARGS__)
+
+/**@brief Method to error logs from the module. */
+#define MQTT_ERR(...) NET_ERR(__VA_ARGS__)
+
+/**@brief Initialize the mutex for the module, if any.
+ *
+ * @details This method is called during module initialization @ref mqtt_init.
+ */
+static inline void mqtt_mutex_init(struct mqtt_client *client)
+{
+	sys_mutex_init(&client->internal.mutex);
+}
+
+/**@brief Acquire lock on the module specific mutex, if any.
+ *
+ * @details This is assumed to be a blocking method until the acquisition
+ *          of the mutex succeeds.
+ */
+static inline void mqtt_mutex_lock(struct mqtt_client *client)
+{
+	int ret = sys_mutex_lock(&client->internal.mutex, K_FOREVER);
+
+	__ASSERT(ret == 0, "sys_mutex_lock failed with %d", ret);
+	(void)ret;
+}
+
+/**@brief Release the lock on the module specific mutex, if any.
+ */
+static inline void mqtt_mutex_unlock(struct mqtt_client *client)
+{
+	int ret = sys_mutex_unlock(&client->internal.mutex);
+
+	__ASSERT(ret == 0, "sys_mutex_unlock failed with %d", ret);
+	(void)ret;
+}
+
+/**@brief Method to get the sys tick or a wall clock in millisecond resolution.
+ *
+ * @retval Current wall clock or sys tick value in milliseconds.
+ */
+static inline uint32_t mqtt_sys_tick_in_ms_get(void)
+{
+	return k_uptime_get_32();
+}
+
+/**@brief Method to get elapsed time in milliseconds since the last activity.
+ *
+ * @param[in] last_activity The value since elapsed time is requested.
+ *
+ * @retval Time elapsed since last_activity time.
+ */
+static inline uint32_t mqtt_elapsed_time_in_ms_get(uint32_t last_activity)
+{
+	int32_t diff = k_uptime_get_32() - last_activity;
+
+	if (diff < 0) {
+		return 0;
+	}
+
+	return diff;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MQTT_OS_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_rx.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_rx.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_rx.c	(working copy)
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_rx, CONFIG_MQTT_LOG_LEVEL);
+
+#include "mqtt_internal.h"
+#include "mqtt_transport.h"
+#include "mqtt_os.h"
+
+/** @file mqtt_rx.c
+ *
+ * @brief MQTT Received data handling.
+ */
+
+static int mqtt_handle_packet(struct mqtt_client *client,
+			      uint8_t type_and_flags,
+			      uint32_t var_length,
+			      struct buf_ctx *buf)
+{
+	int err_code = 0;
+	bool notify_event = true;
+	struct mqtt_evt evt;
+
+	/* Success by default, overwritten in special cases. */
+	evt.result = 0;
+
+	switch (type_and_flags & 0xF0) {
+	case MQTT_PKT_TYPE_CONNACK:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_CONNACK!", client);
+
+		evt.type = MQTT_EVT_CONNACK;
+		err_code = connect_ack_decode(client, buf, &evt.param.connack);
+		if (err_code == 0) {
+			MQTT_TRC("[CID %p]: return_code: %d", client,
+				 evt.param.connack.return_code);
+
+			if (evt.param.connack.return_code ==
+						MQTT_CONNECTION_ACCEPTED) {
+				/* Set state. */
+				MQTT_SET_STATE(client, MQTT_STATE_CONNECTED);
+			} else {
+				err_code = -ECONNREFUSED;
+			}
+
+			evt.result = evt.param.connack.return_code;
+		} else {
+			evt.result = err_code;
+		}
+
+		break;
+
+	case MQTT_PKT_TYPE_PUBLISH:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PUBLISH", client);
+
+		evt.type = MQTT_EVT_PUBLISH;
+		err_code = publish_decode(type_and_flags, var_length, buf,
+					  &evt.param.publish);
+		evt.result = err_code;
+
+		client->internal.remaining_payload =
+					evt.param.publish.message.payload.len;
+
+		MQTT_TRC("PUB QoS:%02x, message len %08x, topic len %08x",
+			 evt.param.publish.message.topic.qos,
+			 evt.param.publish.message.payload.len,
+			 evt.param.publish.message.topic.topic.size);
+
+		break;
+
+	case MQTT_PKT_TYPE_PUBACK:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PUBACK!", client);
+
+		evt.type = MQTT_EVT_PUBACK;
+		err_code = publish_ack_decode(buf, &evt.param.puback);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_PUBREC:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PUBREC!", client);
+
+		evt.type = MQTT_EVT_PUBREC;
+		err_code = publish_receive_decode(buf, &evt.param.pubrec);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_PUBREL:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PUBREL!", client);
+
+		evt.type = MQTT_EVT_PUBREL;
+		err_code = publish_release_decode(buf, &evt.param.pubrel);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_PUBCOMP:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PUBCOMP!", client);
+
+		evt.type = MQTT_EVT_PUBCOMP;
+		err_code = publish_complete_decode(buf, &evt.param.pubcomp);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_SUBACK:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_SUBACK!", client);
+
+		evt.type = MQTT_EVT_SUBACK;
+		err_code = subscribe_ack_decode(buf, &evt.param.suback);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_UNSUBACK:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_UNSUBACK!", client);
+
+		evt.type = MQTT_EVT_UNSUBACK;
+		err_code = unsubscribe_ack_decode(buf, &evt.param.unsuback);
+		evt.result = err_code;
+		break;
+
+	case MQTT_PKT_TYPE_PINGRSP:
+		MQTT_TRC("[CID %p]: Received MQTT_PKT_TYPE_PINGRSP!", client);
+
+		if (client->unacked_ping <= 0) {
+			MQTT_TRC("Unexpected PINGRSP");
+			client->unacked_ping = 0;
+		} else {
+			client->unacked_ping--;
+		}
+
+		evt.type = MQTT_EVT_PINGRESP;
+		break;
+
+	default:
+		/* Nothing to notify. */
+		notify_event = false;
+		break;
+	}
+
+	if (notify_event == true) {
+		event_notify(client, &evt);
+	}
+
+	return err_code;
+}
+
+static int mqtt_read_message_chunk(struct mqtt_client *client,
+				   struct buf_ctx *buf, uint32_t length)
+{
+	uint32_t remaining;
+	int len;
+
+	/* In case all data requested has already been buffered, return. */
+	if (length <= (buf->end - buf->cur)) {
+		return 0;
+	}
+
+	/* Calculate how much data we need to read from the transport,
+	 * given the already buffered data.
+	 */
+	remaining = length - (buf->end - buf->cur);
+
+	/* Check if read does not exceed the buffer. */
+	if ((buf->end + remaining > client->rx_buf + client->rx_buf_size) ||
+	    (buf->end + remaining < client->rx_buf)) {
+		MQTT_ERR("[CID %p]: Read would exceed RX buffer bounds.",
+			 client);
+		return -ENOMEM;
+	}
+
+	len = mqtt_transport_read(client, buf->end, remaining, false);
+	if (len < 0) {
+		MQTT_TRC("[CID %p]: Transport read error: %d", client, len);
+		return len;
+	}
+
+	if (len == 0) {
+		MQTT_TRC("[CID %p]: Connection closed.", client);
+		return -ENOTCONN;
+	}
+
+	client->internal.rx_buf_datalen += len;
+	buf->end += len;
+
+	if (len < remaining) {
+		MQTT_TRC("[CID %p]: Message partially received.", client);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static int mqtt_read_publish_var_header(struct mqtt_client *client,
+					uint8_t type_and_flags,
+					struct buf_ctx *buf)
+{
+	uint8_t qos = (type_and_flags & MQTT_HEADER_QOS_MASK) >> 1;
+	int err_code;
+	uint32_t variable_header_length;
+
+	/* Read topic length field. */
+	err_code = mqtt_read_message_chunk(client, buf, sizeof(uint16_t));
+	if (err_code < 0) {
+		return err_code;
+	}
+
+	variable_header_length = *buf->cur << 8; /* MSB */
+	variable_header_length |= *(buf->cur + 1); /* LSB */
+
+	/* Add two bytes for topic length field. */
+	variable_header_length += sizeof(uint16_t);
+
+	/* Add two bytes for message_id, if needed. */
+	if (qos > MQTT_QOS_0_AT_MOST_ONCE) {
+		variable_header_length += sizeof(uint16_t);
+	}
+
+	/* Now we can read the whole header. */
+	err_code = mqtt_read_message_chunk(client, buf,
+					   variable_header_length);
+	if (err_code < 0) {
+		return err_code;
+	}
+
+	return 0;
+}
+
+static int mqtt_read_and_parse_fixed_header(struct mqtt_client *client,
+					    uint8_t *type_and_flags,
+					    uint32_t *var_length,
+					    struct buf_ctx *buf)
+{
+	/* Read the mandatory part of the fixed header in first iteration. */
+	uint8_t chunk_size = MQTT_FIXED_HEADER_MIN_SIZE;
+	int err_code;
+
+	do {
+		err_code = mqtt_read_message_chunk(client, buf, chunk_size);
+		if (err_code < 0) {
+			return err_code;
+		}
+
+		/* Reset to pointer to the beginning of the frame. */
+		buf->cur = client->rx_buf;
+		chunk_size = 1U;
+
+		err_code = fixed_header_decode(buf, type_and_flags, var_length);
+	} while (err_code == -EAGAIN);
+
+	return err_code;
+}
+
+int mqtt_handle_rx(struct mqtt_client *client)
+{
+	int err_code;
+	uint8_t type_and_flags;
+	uint32_t var_length;
+	struct buf_ctx buf;
+
+	buf.cur = client->rx_buf;
+	buf.end = client->rx_buf + client->internal.rx_buf_datalen;
+
+	err_code = mqtt_read_and_parse_fixed_header(client, &type_and_flags,
+						    &var_length, &buf);
+	if (err_code < 0) {
+		return (err_code == -EAGAIN) ? 0 : err_code;
+	}
+
+	if ((type_and_flags & 0xF0) == MQTT_PKT_TYPE_PUBLISH) {
+		err_code = mqtt_read_publish_var_header(client, type_and_flags,
+							&buf);
+	} else {
+		err_code = mqtt_read_message_chunk(client, &buf, var_length);
+	}
+
+	if (err_code < 0) {
+		return (err_code == -EAGAIN) ? 0 : err_code;
+	}
+
+	/* At this point, packet is ready to be passed to the application. */
+	err_code = mqtt_handle_packet(client, type_and_flags, var_length, &buf);
+	if (err_code < 0) {
+		return err_code;
+	}
+
+	client->internal.rx_buf_datalen = 0U;
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.h	(working copy)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_transport.h
+ *
+ * @brief Internal functions to handle transport in MQTT module.
+ */
+
+#ifndef MQTT_TRANSPORT_H_
+#define MQTT_TRANSPORT_H_
+
+#include <net/mqtt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Transport for handling transport connect procedure. */
+typedef int (*transport_connect_handler_t)(struct mqtt_client *client);
+
+/**@brief Transport write handler. */
+typedef int (*transport_write_handler_t)(struct mqtt_client *client,
+					 const uint8_t *data, uint32_t datalen);
+
+/**@brief Transport write message handler, similar to POSIX sendmsg function. */
+typedef int (*transport_write_msg_handler_t)(struct mqtt_client *client,
+					     const struct msghdr *message);
+
+/**@brief Transport read handler. */
+typedef int (*transport_read_handler_t)(struct mqtt_client *client, uint8_t *data,
+					uint32_t buflen, bool shall_block);
+
+/**@brief Transport disconnect handler. */
+typedef int (*transport_disconnect_handler_t)(struct mqtt_client *client);
+
+/**@brief Transport procedure handlers. */
+struct transport_procedure {
+	/** Transport connect handler. Handles TCP connection callback based on
+	 *  type of transport.
+	 */
+	transport_connect_handler_t connect;
+
+	/** Transport write handler. Handles transport write based on type of
+	 *  transport.
+	 */
+	transport_write_handler_t write;
+
+	/** Transport write message handler. Handles transport write based
+	 *  on type of transport.
+	 */
+	transport_write_msg_handler_t write_msg;
+
+	/** Transport read handler. Handles transport read based on type of
+	 *  transport.
+	 */
+	transport_read_handler_t read;
+
+	/** Transport disconnect handler. Handles transport disconnection based
+	 *  on type of transport.
+	 */
+	transport_disconnect_handler_t disconnect;
+};
+
+/**@brief Handles TCP Connection Complete for configured transport.
+ *
+ * @param[in] client Identifies the client on which the procedure is requested.
+ *
+ * @retval 0 or an error code indicating reason for failure.
+ */
+int mqtt_transport_connect(struct mqtt_client *client);
+
+/**@brief Handles write requests on configured transport.
+ *
+ * @param[in] client Identifies the client on which the procedure is requested.
+ * @param[in] data Data to be written on the transport.
+ * @param[in] datalen Length of data to be written on the transport.
+ *
+ * @retval 0 or an error code indicating reason for failure.
+ */
+int mqtt_transport_write(struct mqtt_client *client, const uint8_t *data,
+			 uint32_t datalen);
+
+/**@brief Handles write message requests on configured transport.
+ *
+ * @param[in] client Identifies the client on which the procedure is requested.
+ * @param[in] message Pointer to the `struct msghdr` structure, containing data
+ *            to be written on the transport.
+ *
+ * @retval 0 or an error code indicating reason for failure.
+ */
+int mqtt_transport_write_msg(struct mqtt_client *client,
+			     const struct msghdr *message);
+
+/**@brief Handles read requests on configured transport.
+ *
+ * @param[in] client Identifies the client on which the procedure is requested.
+ * @param[in] data Pointer where read data is to be fetched.
+ * @param[in] buflen Size of memory provided for the operation.
+ * @param[in] shall_block Information whether the call should block or not.
+ *
+ * @retval Number of bytes read or an error code indicating reason for failure.
+ *         0 if connection was closed.
+ */
+int mqtt_transport_read(struct mqtt_client *client, uint8_t *data, uint32_t buflen,
+			bool shall_block);
+
+/**@brief Handles transport disconnection requests on configured transport.
+ *
+ * @param[in] client Identifies the client on which the procedure is requested.
+ *
+ * @retval 0 or an error code indicating reason for failure.
+ */
+int mqtt_transport_disconnect(struct mqtt_client *client);
+
+/* Transport handler functions for TCP socket transport. */
+int mqtt_client_tcp_connect(struct mqtt_client *client);
+int mqtt_client_tcp_write(struct mqtt_client *client, const uint8_t *data,
+			  uint32_t datalen);
+int mqtt_client_tcp_write_msg(struct mqtt_client *client,
+			      const struct msghdr *message);
+int mqtt_client_tcp_read(struct mqtt_client *client, uint8_t *data,
+			 uint32_t buflen, bool shall_block);
+int mqtt_client_tcp_disconnect(struct mqtt_client *client);
+
+#if defined(CONFIG_MQTT_LIB_TLS)
+/* Transport handler functions for TLS socket transport. */
+int mqtt_client_tls_connect(struct mqtt_client *client);
+int mqtt_client_tls_write(struct mqtt_client *client, const uint8_t *data,
+			  uint32_t datalen);
+int mqtt_client_tls_write_msg(struct mqtt_client *client,
+			      const struct msghdr *message);
+int mqtt_client_tls_read(struct mqtt_client *client, uint8_t *data,
+			 uint32_t buflen, bool shall_block);
+int mqtt_client_tls_disconnect(struct mqtt_client *client);
+#endif /* CONFIG_MQTT_LIB_TLS */
+
+#if defined(CONFIG_MQTT_LIB_WEBSOCKET)
+int mqtt_client_websocket_connect(struct mqtt_client *client);
+int mqtt_client_websocket_write(struct mqtt_client *client, const uint8_t *data,
+				uint32_t datalen);
+int mqtt_client_websocket_write_msg(struct mqtt_client *client,
+				    const struct msghdr *message);
+int mqtt_client_websocket_read(struct mqtt_client *client, uint8_t *data,
+			       uint32_t buflen, bool shall_block);
+int mqtt_client_websocket_disconnect(struct mqtt_client *client);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MQTT_TRANSPORT_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport.c	(working copy)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_transport.c
+ *
+ * @brief Internal functions to handle transport in MQTT module.
+ */
+
+#include "mqtt_transport.h"
+
+/**@brief Function pointer array for TCP/TLS transport handlers. */
+const struct transport_procedure transport_fn[MQTT_TRANSPORT_NUM] = {
+	{
+		mqtt_client_tcp_connect,
+		mqtt_client_tcp_write,
+		mqtt_client_tcp_write_msg,
+		mqtt_client_tcp_read,
+		mqtt_client_tcp_disconnect,
+	},
+#if defined(CONFIG_MQTT_LIB_TLS)
+	{
+		mqtt_client_tls_connect,
+		mqtt_client_tls_write,
+		mqtt_client_tls_write_msg,
+		mqtt_client_tls_read,
+		mqtt_client_tls_disconnect,
+	},
+#endif /* CONFIG_MQTT_LIB_TLS */
+#if defined(CONFIG_MQTT_LIB_WEBSOCKET)
+	{
+		mqtt_client_websocket_connect,
+		mqtt_client_websocket_write,
+		mqtt_client_websocket_write_msg,
+		mqtt_client_websocket_read,
+		mqtt_client_websocket_disconnect,
+	},
+#if defined(CONFIG_MQTT_LIB_TLS)
+	{
+		mqtt_client_websocket_connect,
+		mqtt_client_websocket_write,
+		mqtt_client_websocket_write_msg,
+		mqtt_client_websocket_read,
+		mqtt_client_websocket_disconnect,
+	},
+#endif /* CONFIG_MQTT_LIB_TLS */
+#endif /* CONFIG_MQTT_LIB_WEBSOCKET */
+};
+
+int mqtt_transport_connect(struct mqtt_client *client)
+{
+	return transport_fn[client->transport.type].connect(client);
+}
+
+int mqtt_transport_write(struct mqtt_client *client, const uint8_t *data,
+			 uint32_t datalen)
+{
+	return transport_fn[client->transport.type].write(client, data,
+							  datalen);
+}
+
+int mqtt_transport_write_msg(struct mqtt_client *client,
+			     const struct msghdr *message)
+{
+	return transport_fn[client->transport.type].write_msg(client, message);
+}
+
+int mqtt_transport_read(struct mqtt_client *client, uint8_t *data, uint32_t buflen,
+			bool shall_block)
+{
+	return transport_fn[client->transport.type].read(client, data, buflen,
+							 shall_block);
+}
+
+int mqtt_transport_disconnect(struct mqtt_client *client)
+{
+	return transport_fn[client->transport.type].disconnect(client);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c	(working copy)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_transport_socket_tcp.h
+ *
+ * @brief Internal functions to handle transport over TCP socket.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_sock_tcp, CONFIG_MQTT_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/socket.h>
+#include <net/mqtt.h>
+
+#include "mqtt_os.h"
+
+int mqtt_client_tcp_connect(struct mqtt_client *client)
+{
+	const struct sockaddr *broker = client->broker;
+	int ret;
+
+	client->transport.tcp.sock = zsock_socket(broker->sa_family, SOCK_STREAM,
+						  IPPROTO_TCP);
+	if (client->transport.tcp.sock < 0) {
+		return -errno;
+	}
+
+#if defined(CONFIG_SOCKS)
+	if (client->transport.proxy.addrlen != 0) {
+		ret = setsockopt(client->transport.tcp.sock,
+				 SOL_SOCKET, SO_SOCKS5,
+				 &client->transport.proxy.addr,
+				 client->transport.proxy.addrlen);
+		if (ret < 0) {
+			return -errno;
+		}
+	}
+#endif
+
+	MQTT_TRC("Created socket %d", client->transport.tcp.sock);
+
+	size_t peer_addr_size = sizeof(struct sockaddr_in6);
+
+	if (broker->sa_family == AF_INET) {
+		peer_addr_size = sizeof(struct sockaddr_in);
+	}
+
+	ret = zsock_connect(client->transport.tcp.sock, client->broker,
+			    peer_addr_size);
+	if (ret < 0) {
+		(void) zsock_close(client->transport.tcp.sock);
+		return -errno;
+	}
+
+	MQTT_TRC("Connect completed");
+	return 0;
+}
+
+int mqtt_client_tcp_write(struct mqtt_client *client, const uint8_t *data,
+			  uint32_t datalen)
+{
+	uint32_t offset = 0U;
+	int ret;
+
+	while (offset < datalen) {
+		ret = zsock_send(client->transport.tcp.sock, data + offset,
+				 datalen - offset, 0);
+		if (ret < 0) {
+			return -errno;
+		}
+
+		offset += ret;
+	}
+
+	return 0;
+}
+
+int mqtt_client_tcp_write_msg(struct mqtt_client *client,
+			      const struct msghdr *message)
+
+{
+	int ret;
+
+	ret = zsock_sendmsg(client->transport.tcp.sock, message, 0);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return 0;
+}
+
+int mqtt_client_tcp_read(struct mqtt_client *client, uint8_t *data, uint32_t buflen,
+			 bool shall_block)
+{
+	int flags = 0;
+	int ret;
+
+	if (!shall_block) {
+		flags |= ZSOCK_MSG_DONTWAIT;
+	}
+
+	ret = zsock_recv(client->transport.tcp.sock, data, buflen, flags);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return ret;
+}
+
+int mqtt_client_tcp_disconnect(struct mqtt_client *client)
+{
+	int ret;
+
+	MQTT_TRC("Closing socket %d", client->transport.tcp.sock);
+
+	ret = zsock_close(client->transport.tcp.sock);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c	(working copy)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_transport_socket_tls.h
+ *
+ * @brief Internal functions to handle transport over TLS socket.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_sock_tls, CONFIG_MQTT_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/socket.h>
+#include <net/mqtt.h>
+
+#include "mqtt_os.h"
+
+int mqtt_client_tls_connect(struct mqtt_client *client)
+{
+	const struct sockaddr *broker = client->broker;
+	struct mqtt_sec_config *tls_config = &client->transport.tls.config;
+	int ret;
+
+	client->transport.tls.sock = zsock_socket(broker->sa_family,
+						  SOCK_STREAM, IPPROTO_TLS_1_2);
+	if (client->transport.tls.sock < 0) {
+		return -errno;
+	}
+
+	MQTT_TRC("Created socket %d", client->transport.tls.sock);
+
+#if defined(CONFIG_SOCKS)
+	if (client->transport.proxy.addrlen != 0) {
+		ret = setsockopt(client->transport.tls.sock,
+				 SOL_SOCKET, SO_SOCKS5,
+				 &client->transport.proxy.addr,
+				 client->transport.proxy.addrlen);
+		if (ret < 0) {
+			return -errno;
+		}
+	}
+#endif
+	/* Set secure socket options. */
+	ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, TLS_PEER_VERIFY,
+			       &tls_config->peer_verify,
+			       sizeof(tls_config->peer_verify));
+	if (ret < 0) {
+		goto error;
+	}
+
+	if (tls_config->cipher_list != NULL && tls_config->cipher_count > 0) {
+		ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
+				       TLS_CIPHERSUITE_LIST, tls_config->cipher_list,
+				       sizeof(int) * tls_config->cipher_count);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	if (tls_config->sec_tag_list != NULL && tls_config->sec_tag_count > 0) {
+		ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
+				       TLS_SEC_TAG_LIST, tls_config->sec_tag_list,
+				       sizeof(sec_tag_t) * tls_config->sec_tag_count);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	if (tls_config->hostname) {
+		ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS,
+				       TLS_HOSTNAME, tls_config->hostname,
+				       strlen(tls_config->hostname));
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	size_t peer_addr_size = sizeof(struct sockaddr_in6);
+
+	if (broker->sa_family == AF_INET) {
+		peer_addr_size = sizeof(struct sockaddr_in);
+	}
+
+	ret = zsock_connect(client->transport.tls.sock, client->broker,
+			    peer_addr_size);
+	if (ret < 0) {
+		goto error;
+	}
+
+	MQTT_TRC("Connect completed");
+	return 0;
+
+error:
+	(void) zsock_close(client->transport.tls.sock);
+	return -errno;
+}
+
+int mqtt_client_tls_write(struct mqtt_client *client, const uint8_t *data,
+			  uint32_t datalen)
+{
+	uint32_t offset = 0U;
+	int ret;
+
+	while (offset < datalen) {
+		ret = zsock_send(client->transport.tls.sock, data + offset,
+				 datalen - offset, 0);
+		if (ret < 0) {
+			return -errno;
+		}
+
+		offset += ret;
+	}
+
+	return 0;
+}
+
+int mqtt_client_tls_write_msg(struct mqtt_client *client,
+			      const struct msghdr *message)
+{
+	int ret;
+
+	ret = zsock_sendmsg(client->transport.tls.sock, message, 0);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return 0;
+}
+
+int mqtt_client_tls_read(struct mqtt_client *client, uint8_t *data, uint32_t buflen,
+			 bool shall_block)
+{
+	int flags = 0;
+	int ret;
+
+	if (!shall_block) {
+		flags |= ZSOCK_MSG_DONTWAIT;
+	}
+
+	ret = zsock_recv(client->transport.tls.sock, data, buflen, flags);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return ret;
+}
+
+int mqtt_client_tls_disconnect(struct mqtt_client *client)
+{
+	int ret;
+
+	MQTT_TRC("Closing socket %d", client->transport.tls.sock);
+	ret = zsock_close(client->transport.tls.sock);
+	if (ret < 0) {
+		return -errno;
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_websocket.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_websocket.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/mqtt/mqtt_transport_websocket.c	(working copy)
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file mqtt_transport_websocket.c
+ *
+ * @brief Internal functions to handle transport over Websocket.
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_mqtt_websocket, CONFIG_MQTT_LOG_LEVEL);
+
+#include <errno.h>
+#include <net/socket.h>
+#include <net/mqtt.h>
+#include <net/websocket.h>
+
+#include "mqtt_os.h"
+#include "mqtt_transport.h"
+
+int mqtt_client_websocket_connect(struct mqtt_client *client)
+{
+	const char *extra_headers[] = {
+		"Sec-WebSocket-Protocol: mqtt\r\n",
+		NULL
+	};
+	int transport_sock;
+	int ret;
+
+	if (client->transport.type == MQTT_TRANSPORT_NON_SECURE_WEBSOCKET) {
+		ret = mqtt_client_tcp_connect(client);
+		if (ret < 0) {
+			return ret;
+		}
+
+		transport_sock = client->transport.tcp.sock;
+	}
+#if defined(CONFIG_MQTT_LIB_TLS)
+	else if (client->transport.type == MQTT_TRANSPORT_SECURE_WEBSOCKET) {
+		ret = mqtt_client_tls_connect(client);
+		if (ret < 0) {
+			return ret;
+		}
+
+		transport_sock = client->transport.tls.sock;
+	}
+#endif
+	else {
+		return -EINVAL;
+	}
+
+	if (client->transport.websocket.config.url == NULL) {
+		client->transport.websocket.config.url = "/mqtt";
+	}
+
+	if (client->transport.websocket.config.host == NULL) {
+		client->transport.websocket.config.host = "localhost";
+	}
+
+	/* If application needs to set some extra header options, then
+	 * it can set the optional_headers_cb. In this case the app
+	 * will need to also send "Sec-WebSocket-Protocol: mqtt\r\n"
+	 * field as the optional_headers field is ignored if the callback
+	 * is set.
+	 */
+	client->transport.websocket.config.optional_headers = extra_headers;
+
+	client->transport.websocket.sock = websocket_connect(
+			transport_sock,
+			&client->transport.websocket.config,
+			client->transport.websocket.timeout,
+			NULL);
+	if (client->transport.websocket.sock < 0) {
+		MQTT_TRC("Websocket connect failed (%d)",
+			 client->transport.websocket.sock);
+
+		(void)close(transport_sock);
+		return client->transport.websocket.sock;
+	}
+
+	MQTT_TRC("Connect completed");
+
+	return 0;
+}
+
+int mqtt_client_websocket_write(struct mqtt_client *client, const uint8_t *data,
+				uint32_t datalen)
+{
+	uint32_t offset = 0U;
+	int ret;
+
+	while (offset < datalen) {
+		ret = websocket_send_msg(client->transport.websocket.sock,
+					 data + offset, datalen - offset,
+					 WEBSOCKET_OPCODE_DATA_BINARY,
+					 true, true, SYS_FOREVER_MS);
+		if (ret < 0) {
+			return -errno;
+		}
+
+		offset += ret;
+	}
+
+	return 0;
+}
+
+int mqtt_client_websocket_write_msg(struct mqtt_client *client,
+				    const struct msghdr *message)
+{
+	enum websocket_opcode opcode = WEBSOCKET_OPCODE_DATA_BINARY;
+	bool final = false;
+	ssize_t len;
+	ssize_t ret;
+	int i;
+
+	len = 0;
+	for (i = 0; i < message->msg_iovlen; i++) {
+		if (i == message->msg_iovlen - 1) {
+			final = true;
+		}
+
+		ret = websocket_send_msg(client->transport.websocket.sock,
+					 message->msg_iov[i].iov_base,
+					 message->msg_iov[i].iov_len, opcode,
+					 true, final, SYS_FOREVER_MS);
+		if (ret < 0) {
+			return ret;
+		}
+
+		opcode = WEBSOCKET_OPCODE_CONTINUE;
+		len += ret;
+	}
+
+	return len;
+}
+
+int mqtt_client_websocket_read(struct mqtt_client *client, uint8_t *data,
+			       uint32_t buflen, bool shall_block)
+{
+	int32_t timeout = SYS_FOREVER_MS;
+	uint32_t message_type = 0U;
+	int ret;
+
+	if (!shall_block) {
+		timeout = 0;
+	}
+
+	ret = websocket_recv_msg(client->transport.websocket.sock,
+				 data, buflen, &message_type, NULL, timeout);
+	if (ret > 0 && message_type > 0) {
+		if (message_type & WEBSOCKET_FLAG_CLOSE) {
+			return 0;
+		}
+
+		if (!(message_type & WEBSOCKET_FLAG_BINARY)) {
+			return -EAGAIN;
+		}
+	}
+
+	return ret;
+}
+
+int mqtt_client_websocket_disconnect(struct mqtt_client *client)
+{
+	MQTT_TRC("Closing socket %d", client->transport.websocket.sock);
+
+	return websocket_disconnect(client->transport.websocket.sock);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/CMakeLists.txt	(working copy)
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: Apache-2.0
+
+add_subdirectory(platform)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/CMakeLists.txt	(working copy)
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library_named(openthread_platform)
+zephyr_library_sources(
+  alarm.c
+  entropy.c
+  misc.c
+  platform.c
+  radio.c
+  settings.c
+  spi.c
+  )
+
+zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_DIAG diag.c)
+zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_NCP uart.c)
+zephyr_library_sources_ifdef(CONFIG_OPENTHREAD_SHELL shell.c)
+zephyr_library_sources_ifndef(CONFIG_LOG_BACKEND_SPINEL logging.c)
+
+zephyr_include_directories(.)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/alarm.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/alarm.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/alarm.c	(working copy)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME net_openthread_alarm
+#define LOG_LEVEL CONFIG_OPENTHREAD_LOG_LEVEL
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <kernel.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <openthread/platform/alarm-milli.h>
+#include <openthread-system.h>
+
+#include <stdio.h>
+
+#include "platform-zephyr.h"
+
+static bool timer_fired;
+
+static void ot_timer_fired(struct k_timer *timer)
+{
+	ARG_UNUSED(timer);
+
+	timer_fired = true;
+	otSysEventSignalPending();
+}
+
+K_TIMER_DEFINE(ot_timer, ot_timer_fired, NULL);
+
+void platformAlarmInit(void)
+{
+	/* Intentionally empty */
+}
+
+uint32_t otPlatAlarmMilliGetNow(void)
+{
+	return k_uptime_get_32();
+}
+
+void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t t0, uint32_t dt)
+{
+	ARG_UNUSED(aInstance);
+
+	int64_t reftime = (int64_t)t0 + (int64_t)dt;
+	int64_t delta = -k_uptime_delta(&reftime);
+
+	if (delta > 0) {
+		k_timer_start(&ot_timer, K_MSEC(delta), K_NO_WAIT);
+	} else {
+		ot_timer_fired(NULL);
+	}
+}
+
+void otPlatAlarmMilliStop(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	k_timer_stop(&ot_timer);
+}
+
+
+void platformAlarmProcess(otInstance *aInstance)
+{
+	if (timer_fired) {
+		timer_fired = false;
+		otPlatAlarmMilliFired(aInstance);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/diag.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/diag.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/diag.c	(working copy)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <openthread/platform/diag.h>
+
+#include "platform-zephyr.h"
+
+/**
+ * Diagnostics mode variables.
+ *
+ */
+static bool sDiagMode;
+
+otError otPlatDiagProcess(otInstance *aInstance,
+			  uint8_t argc,
+			  char   *argv[],
+			  char   *aOutput,
+			  size_t  aOutputMaxLen)
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(aInstance);
+
+	/* Add more plarform specific diagnostics features here. */
+	snprintk(aOutput, aOutputMaxLen,
+		 "diag feature '%s' is not supported\r\n", argv[0]);
+
+	return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+void otPlatDiagModeSet(bool aMode)
+{
+	sDiagMode = aMode;
+}
+
+bool otPlatDiagModeGet(void)
+{
+	return sDiagMode;
+}
+
+void otPlatDiagChannelSet(uint8_t aChannel)
+{
+	ARG_UNUSED(aChannel);
+}
+
+void otPlatDiagTxPowerSet(int8_t aTxPower)
+{
+	ARG_UNUSED(aTxPower);
+}
+
+void otPlatDiagRadioReceived(otInstance *aInstance,
+			     otRadioFrame *aFrame,
+			     otError aError)
+{
+	ARG_UNUSED(aInstance);
+	ARG_UNUSED(aFrame);
+	ARG_UNUSED(aError);
+}
+
+void otPlatDiagAlarmCallback(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/entropy.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/entropy.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/entropy.c	(working copy)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <string.h>
+#include <drivers/entropy.h>
+#include <logging/log.h>
+
+#include <openthread/platform/entropy.h>
+
+#include "platform-zephyr.h"
+
+LOG_MODULE_REGISTER(net_otPlat_entropy, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
+
+#if !defined(CONFIG_ENTROPY_HAS_DRIVER)
+#error OpenThread requires an entropy source for a TRNG
+#endif
+
+otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
+{
+	/* static to obtain it once in a first call */
+	static const struct device *dev;
+	int err;
+
+	if ((aOutput == NULL) || (aOutputLength == 0)) {
+		return OT_ERROR_INVALID_ARGS;
+	}
+
+	if (dev == NULL) {
+		dev = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
+		if (dev == NULL) {
+			LOG_ERR("Failed to obtain entropy device");
+			return OT_ERROR_FAILED;
+		}
+	}
+
+	err = entropy_get_entropy(dev, aOutput, aOutputLength);
+	if (err != 0) {
+		LOG_ERR("Failed to obtain entropy, err %d", err);
+		return OT_ERROR_FAILED;
+	}
+
+	return OT_ERROR_NONE;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/logging.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/logging.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/logging.c	(working copy)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018 - 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <openthread/platform/logging.h>
+#include "openthread-core-zephyr-config.h"
+
+#define LOG_MODULE_NAME net_openthread
+#define LOG_LEVEL LOG_LEVEL_DBG
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include "platform-zephyr.h"
+
+
+void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion,
+	       const char *aFormat, ...)
+{
+	/*
+	 * The following speed optimization have been used:
+	 * - arguments are counted at compile time
+	 * - for none arguments aFormat is not checked for %s
+	 * - for up to three arguments program uses fast path
+	 * - time consuming string formatting is posponed to idle time
+	 * TODO : add support for ll (problem for 32 bit processors)
+	 */
+
+
+#ifdef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION__COUNT_ARGS
+	/* The arguments number has been counted by macro at compile time,
+	 * and the value has been passed in unused (now) aLogRegion.
+	 * If LogRegion value from OT is needed, rewrite macro
+	 * OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION__COUNT_ARGS and use higher bits.
+	 * to pass args_num.
+	 */
+	uint32_t args_num = (uint32_t) aLogRegion;
+#else
+	ARG_UNUSED(aLogRegion);
+
+	uint32_t args_num = log_count_args(aFormat);
+#endif
+
+	va_list param_list;
+
+	va_start(param_list, aFormat);
+
+	/* We assume, that OT has no access to strdup utility,
+	 * and we are not obliged to check, if string has already
+	 * been duplicated. So, to save time, in Z_LOG_VA macro calls
+	 * we will use LOG_STRDUP_EXEC option.
+	 */
+	switch (aLogLevel) {
+	case OT_LOG_LEVEL_CRIT:
+		Z_LOG_VA(LOG_LEVEL_ERR, aFormat, param_list, args_num,
+			LOG_STRDUP_EXEC);
+		break;
+	case OT_LOG_LEVEL_WARN:
+		Z_LOG_VA(LOG_LEVEL_WRN, aFormat, param_list, args_num,
+			LOG_STRDUP_EXEC);
+		break;
+	case OT_LOG_LEVEL_NOTE:
+	case OT_LOG_LEVEL_INFO:
+		Z_LOG_VA(LOG_LEVEL_INF, aFormat, param_list, args_num,
+			LOG_STRDUP_EXEC);
+		break;
+	case OT_LOG_LEVEL_DEBG:
+		Z_LOG_VA(LOG_LEVEL_DBG, aFormat, param_list, args_num,
+			LOG_STRDUP_EXEC);
+		break;
+	default:
+		break;
+	}
+	va_end(param_list);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/misc.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/misc.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/misc.c	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <power/reboot.h>
+#include <openthread/instance.h>
+#include <openthread/platform/misc.h>
+
+#include "platform-zephyr.h"
+
+void otPlatReset(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	/* This function does nothing on the Posix platform. */
+	sys_reboot(SYS_REBOOT_WARM);
+}
+
+otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	return OT_PLAT_RESET_REASON_POWER_ON;
+}
+
+void otPlatWakeHost(void)
+{
+	/* TODO */
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h	(working copy)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *   This file includes Zephyr compile-time configuration constants
+ *   for OpenThread.
+ */
+
+#ifndef OPENTHREAD_CORE_ZEPHYR_CONFIG_H_
+#define OPENTHREAD_CORE_ZEPHYR_CONFIG_H_
+
+#include <autoconf.h>
+#include <devicetree.h>
+#include <toolchain.h>
+
+/**
+ * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
+ *
+ * The number of message buffers in the buffer pool.
+ *
+ */
+#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS                   CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS
+
+/**
+ * @def OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS
+ *
+ * The maximum number of state-changed callback handlers
+ * (set using `otSetStateChangedCallback()`).
+ *
+ */
+#define OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS              CONFIG_OPENTHREAD_MAX_STATECHANGE_HANDLERS
+
+/**
+ * @def OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES
+ *
+ * The number of EID-to-RLOC cache entries.
+ *
+ */
+#define OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES             CONFIG_OPENTHREAD_TMF_ADDRESS_CACHE_ENTRIES
+
+/**
+ * @def OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
+ *
+ * Define to prepend the log level to all log messages.
+ *
+ */
+#define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL                     0
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
+ *
+ * Define to 1 to enable software ACK timeout logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE       1
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+ *
+ * Define to 1 to enable software retransmission logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE        1
+
+/**
+ * @def SETTINGS_CONFIG_BASE_ADDRESS
+ *
+ * The base address of settings.
+ *
+ */
+#define SETTINGS_CONFIG_BASE_ADDRESS                            0
+
+/**
+ * @def SETTINGS_CONFIG_PAGE_SIZE
+ *
+ * The page size of settings. Ensure that 'erase-block-size'
+ * is set in your SOC dts file.
+ *
+ */
+#define SETTINGS_CONFIG_PAGE_SIZE \
+	DT_PROP(DT_CHOSEN(zephyr_flash), erase_block_size)
+
+/**
+ * @def SETTINGS_CONFIG_PAGE_NUM
+ *
+ * The page number of settings.
+ *
+ */
+#define SETTINGS_CONFIG_PAGE_NUM                                4
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
+ *
+ * Define to 1 if you want to enable microsecond backoff timer implemented
+ * in platform.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE            0
+
+/* Zephyr does not use OpenThreads heap. mbedTLS will use heap memory allocated
+ * by Zephyr. Here, we use some dummy values to prevent OpenThread warnings.
+ */
+
+/**
+ * @def OPENTHREAD_CONFIG_HEAP_SIZE
+ *
+ * The size of heap buffer when DTLS is enabled.
+ *
+ */
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE (4 * sizeof(void *))
+
+/**
+ * @def OPENTHREAD_CONFIG_HEAP_SIZE_NO_DTLS
+ *
+ * The size of heap buffer when DTLS is disabled.
+ *
+ */
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS (4 * sizeof(void *))
+
+/* Disable software srouce address matching. */
+
+/**
+ * @def RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM
+ *
+ * The number of short source address table entries.
+ *
+ */
+#define RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM 0
+
+/**
+ * @def OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
+ *
+ * The maximum number of children.
+ *
+ */
+#ifdef CONFIG_OPENTHREAD_MAX_CHILDREN
+#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN CONFIG_OPENTHREAD_MAX_CHILDREN
+#endif /* CONFIG_OPENTHREAD_MAX_CHILDREN */
+
+/**
+ * @def OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD
+ *
+ * The maximum number of supported IPv6 address registrations per child.
+ *
+ */
+#ifdef CONFIG_OPENTHREAD_MAX_IP_ADDR_PER_CHILD
+#define OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD \
+	CONFIG_OPENTHREAD_MAX_IP_ADDR_PER_CHILD
+#endif /* CONFIG_OPENTHREAD_MAX_IP_ADDR_PER_CHILD */
+
+/**
+ * @def RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
+ *
+ * The number of extended source address table entries.
+ *
+ */
+#define RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM 0
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_BUFFER_SIZE
+ *
+ * The size of the NCP buffers.
+ *
+ */
+#define OPENTHREAD_CONFIG_NCP_BUFFER_SIZE CONFIG_OPENTHREAD_NCP_BUFFER_SIZE
+
+/**
+ * @def OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
+ *
+ * The platform logging function for openthread.
+ *
+ */
+#define _OT_CONF_PLAT_LOG_FUN_NARGS__IMPL(		\
+		_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,\
+		_11, _12, _13, _14, N, ...) N
+
+#define _OT_CONF_PLAT_LOG_FUN_NARGS__GET(...) \
+		_OT_CONF_PLAT_LOG_FUN_NARGS__IMPL(__VA_ARGS__,\
+		15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ~)
+
+#define OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION__COUNT_ARGS(aLogLevel, unused, \
+							aFormat, ...) \
+	do { \
+		ARG_UNUSED(unused); \
+		otPlatLog( \
+		  aLogLevel, \
+		  (otLogRegion)_OT_CONF_PLAT_LOG_FUN_NARGS__GET(__VA_ARGS__),\
+		  aFormat, ##__VA_ARGS__); \
+	} while (false)
+
+#ifdef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
+#error OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION \
+	"OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION mustn't be defined before"
+#endif
+
+#define OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION \
+	OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION__COUNT_ARGS
+
+#endif  /* OPENTHREAD_CORE_NRF52840_CONFIG_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform-zephyr.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform-zephyr.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform-zephyr.h	(working copy)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief
+ *   This file includes the Zephyr platform-specific initializers.
+ */
+
+#ifndef PLATFORM_ZEPHYR_H_
+#define PLATFORM_ZEPHYR_H_
+
+#include <stdint.h>
+
+#include <openthread/instance.h>
+#include <net/net_pkt.h>
+
+/**
+ * This function initializes the alarm service used by OpenThread.
+ *
+ */
+void platformAlarmInit(void);
+
+/**
+ * This function performs alarm driver processing.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ *
+ */
+void platformAlarmProcess(otInstance *aInstance);
+
+/**
+ * This function initializes the radio service used by OpenThread.
+ *
+ */
+void platformRadioInit(void);
+
+/**
+ * This function performs radio driver processing.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ *
+ */
+void platformRadioProcess(otInstance *aInstance);
+
+/**
+ * This function performs UART driver processing.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ *
+ */
+void platformUartProcess(otInstance *aInstance);
+
+/**
+ * Outer component calls this method to notify UART driver that it should
+ * switch to panic mode and work in synchronous way.
+ */
+void platformUartPanic(void);
+
+/**
+ * Get current channel from radio driver.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ *
+ * @return Current channel radio driver operates on.
+ *
+ */
+uint16_t platformRadioChannelGet(otInstance *aInstance);
+
+/**
+ * This function initializes the random number service used by OpenThread.
+ *
+ */
+void platformRandomInit(void);
+
+
+/**
+ *  Initialize platform Shell driver.
+ */
+void platformShellInit(otInstance *aInstance);
+
+
+/**
+ * Notify OpenThread task about new rx message.
+ */
+int notify_new_rx_frame(struct net_pkt *pkt);
+
+/**
+ * Notify OpenThread task about new tx message.
+ */
+int notify_new_tx_frame(struct net_pkt *pkt);
+
+#endif  /* PLATFORM_POSIX_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/platform.c	(working copy)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief
+ *   This file includes the platform-specific initializers.
+ */
+
+#include <kernel.h>
+#include <openthread/instance.h>
+#include <openthread/tasklet.h>
+
+#include "platform-zephyr.h"
+
+void otSysInit(int argc, char *argv[])
+{
+	ARG_UNUSED(argc);
+	ARG_UNUSED(argv);
+
+	platformAlarmInit();
+	platformRadioInit();
+}
+
+void otSysProcessDrivers(otInstance *aInstance)
+{
+	platformRadioProcess(aInstance);
+	platformAlarmProcess(aInstance);
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_NCP)) {
+		platformUartProcess(aInstance);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/radio.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/radio.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/radio.c	(working copy)
@@ -0,0 +1,890 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *   This file implements the OpenThread platform abstraction
+ *   for radio communication.
+ *
+ */
+
+#define LOG_MODULE_NAME net_otPlat_radio
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <kernel.h>
+#include <device.h>
+#include <net/ieee802154_radio.h>
+#include <net/net_pkt.h>
+#include <sys/__assert.h>
+
+#include <openthread/ip6.h>
+#include <openthread-system.h>
+#include <openthread/instance.h>
+#include <openthread/platform/radio.h>
+#include <openthread/platform/diag.h>
+#include <openthread/message.h>
+
+#include "platform-zephyr.h"
+
+#define SHORT_ADDRESS_SIZE 2
+
+#define FCS_SIZE 2
+#define ACK_PKT_LENGTH 3
+
+#define FRAME_TYPE_MASK 0x07
+#define FRAME_TYPE_ACK 0x02
+
+#define OT_WORKER_STACK_SIZE 512
+#define OT_WORKER_PRIORITY   K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
+
+enum pending_events {
+	PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send  */
+	PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */
+	PENDING_EVENT_RX_FAILED, /* The RX failed */
+	PENDING_EVENT_TX_STARTED, /* Radio has started transmitting */
+	PENDING_EVENT_TX_DONE, /* Radio transmission finished */
+	PENDING_EVENT_DETECT_ENERGY, /* Requested to start Energy Detection
+				      * procedure.
+				      */
+	PENDING_EVENT_DETECT_ENERGY_DONE, /* Energy Detection finished. */
+	PENDING_EVENT_COUNT /* keep last */
+};
+
+K_SEM_DEFINE(radio_sem, 0, 1);
+
+static otRadioState sState = OT_RADIO_STATE_DISABLED;
+
+static otRadioFrame sTransmitFrame;
+static otRadioFrame ack_frame;
+static uint8_t ack_psdu[ACK_PKT_LENGTH];
+
+static struct net_pkt *tx_pkt;
+static struct net_buf *tx_payload;
+
+static const struct device *radio_dev;
+static struct ieee802154_radio_api *radio_api;
+
+static int8_t tx_power;
+static uint16_t channel;
+static bool promiscuous;
+
+static uint16_t energy_detection_time;
+static uint8_t  energy_detection_channel;
+static int16_t energy_detected_value;
+
+ATOMIC_DEFINE(pending_events, PENDING_EVENT_COUNT);
+K_KERNEL_STACK_DEFINE(ot_task_stack, OT_WORKER_STACK_SIZE);
+static struct k_work_q ot_work_q;
+static otError tx_rx_result;
+
+K_FIFO_DEFINE(rx_pkt_fifo);
+K_FIFO_DEFINE(tx_pkt_fifo);
+
+static inline bool is_pending_event_set(enum pending_events event)
+{
+	return atomic_test_bit(pending_events, event);
+}
+
+static void set_pending_event(enum pending_events event)
+{
+	atomic_set_bit(pending_events, event);
+	otSysEventSignalPending();
+}
+
+static void reset_pending_event(enum pending_events event)
+{
+	atomic_clear_bit(pending_events, event);
+}
+
+static inline void clear_pending_events(void)
+{
+	atomic_clear(pending_events);
+}
+
+void energy_detected(const struct device *dev, int16_t max_ed)
+{
+	if (dev == radio_dev) {
+		energy_detected_value = max_ed;
+		set_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
+	}
+}
+
+enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
+					     struct net_pkt *pkt)
+{
+	ARG_UNUSED(iface);
+
+	size_t ack_len = net_pkt_get_len(pkt);
+
+	if (ack_len != ACK_PKT_LENGTH) {
+		return NET_CONTINUE;
+	}
+
+	if ((*net_pkt_data(pkt) & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) {
+		return NET_CONTINUE;
+	}
+
+	if (ack_frame.mLength != 0) {
+		LOG_ERR("Overwriting unhandled ACK frame.");
+	}
+
+	if (net_pkt_read(pkt, ack_psdu, ack_len) < 0) {
+		LOG_ERR("Failed to read ACK frame.");
+		return NET_CONTINUE;
+	}
+
+	ack_frame.mPsdu = ack_psdu;
+	ack_frame.mLength = ack_len;
+	ack_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt);
+	ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt);
+
+	return NET_OK;
+}
+
+void handle_radio_event(const struct device *dev, enum ieee802154_event evt,
+			void *event_params)
+{
+	ARG_UNUSED(event_params);
+
+	switch (evt) {
+	case IEEE802154_EVENT_TX_STARTED:
+		if (sState == OT_RADIO_STATE_TRANSMIT) {
+			set_pending_event(PENDING_EVENT_TX_STARTED);
+		}
+		break;
+	case IEEE802154_EVENT_RX_FAILED:
+		if (sState == OT_RADIO_STATE_RECEIVE) {
+			switch (*(enum ieee802154_rx_fail_reason *)
+				event_params) {
+			case IEEE802154_RX_FAIL_NOT_RECEIVED:
+				tx_rx_result = OT_ERROR_NO_FRAME_RECEIVED;
+				break;
+
+			case IEEE802154_RX_FAIL_INVALID_FCS:
+				tx_rx_result = OT_ERROR_FCS;
+				break;
+
+			case IEEE802154_RX_FAIL_ADDR_FILTERED:
+				tx_rx_result
+					= OT_ERROR_DESTINATION_ADDRESS_FILTERED;
+				break;
+
+			case IEEE802154_RX_FAIL_OTHER:
+			default:
+				tx_rx_result = OT_ERROR_FAILED;
+				break;
+			}
+			set_pending_event(PENDING_EVENT_RX_FAILED);
+		}
+	default:
+		/* do nothing - ignore event */
+		break;
+	}
+}
+
+static void dataInit(void)
+{
+	tx_pkt = net_pkt_alloc(K_NO_WAIT);
+	__ASSERT_NO_MSG(tx_pkt != NULL);
+
+	tx_payload = net_pkt_get_reserve_tx_data(K_NO_WAIT);
+	__ASSERT_NO_MSG(tx_payload != NULL);
+
+	net_pkt_append_buffer(tx_pkt, tx_payload);
+
+	sTransmitFrame.mPsdu = tx_payload->data;
+}
+
+void platformRadioInit(void)
+{
+	struct ieee802154_config cfg;
+
+	dataInit();
+
+	radio_dev = device_get_binding(CONFIG_NET_CONFIG_IEEE802154_DEV_NAME);
+	__ASSERT_NO_MSG(radio_dev != NULL);
+
+	radio_api = (struct ieee802154_radio_api *)radio_dev->api;
+	if (!radio_api) {
+		return;
+	}
+
+	k_work_q_start(&ot_work_q, ot_task_stack,
+		       K_KERNEL_STACK_SIZEOF(ot_task_stack),
+		       OT_WORKER_PRIORITY);
+
+	if ((radio_api->get_capabilities(radio_dev) &
+	     IEEE802154_HW_TX_RX_ACK) != IEEE802154_HW_TX_RX_ACK) {
+		LOG_ERR("Only radios with automatic ack handling "
+			"are currently supported");
+		k_panic();
+	}
+
+	cfg.event_handler = handle_radio_event;
+	radio_api->configure(radio_dev, IEEE802154_CONFIG_EVENT_HANDLER, &cfg);
+}
+
+void transmit_message(struct k_work *tx_job)
+{
+	ARG_UNUSED(tx_job);
+
+	tx_rx_result = OT_ERROR_NONE;
+	/*
+	 * The payload is already in tx_payload->data,
+	 * but we need to set the length field
+	 * according to sTransmitFrame.length.
+	 * We subtract the FCS size as radio driver
+	 * adds CRC and increases frame length on its own.
+	 */
+	tx_payload->len = sTransmitFrame.mLength - FCS_SIZE;
+
+	channel = sTransmitFrame.mChannel;
+
+	radio_api->set_channel(radio_dev, sTransmitFrame.mChannel);
+	radio_api->set_txpower(radio_dev, tx_power);
+
+	if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) {
+		if (radio_api->get_capabilities(radio_dev) &
+		    IEEE802154_HW_CSMA) {
+			if (radio_api->tx(radio_dev,
+					  IEEE802154_TX_MODE_CSMA_CA,
+					  tx_pkt, tx_payload) != 0) {
+				tx_rx_result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+			}
+		} else if (radio_api->cca(radio_dev) != 0 ||
+			   radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT,
+					 tx_pkt, tx_payload) != 0) {
+			tx_rx_result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+		}
+	} else {
+		if (radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT,
+				  tx_pkt, tx_payload)) {
+			tx_rx_result = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+		}
+	}
+
+	set_pending_event(PENDING_EVENT_TX_DONE);
+}
+
+static inline void handle_tx_done(otInstance *aInstance)
+{
+	if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
+		otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame,
+					    tx_rx_result);
+	} else {
+		if (sTransmitFrame.mPsdu[0] & IEEE802154_AR_FLAG_SET) {
+			if (ack_frame.mLength == 0) {
+				LOG_DBG("No ACK received.");
+				otPlatRadioTxDone(aInstance, &sTransmitFrame,
+						  NULL, OT_ERROR_NO_ACK);
+			} else {
+				otPlatRadioTxDone(aInstance, &sTransmitFrame,
+						  &ack_frame, tx_rx_result);
+			}
+		} else {
+			otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL,
+					  tx_rx_result);
+		}
+		ack_frame.mLength = 0;
+	}
+}
+
+static void openthread_handle_received_frame(otInstance *instance,
+					     struct net_pkt *pkt)
+{
+	otRadioFrame recv_frame;
+
+	recv_frame.mPsdu = net_buf_frag_last(pkt->buffer)->data;
+	/* Length inc. CRC. */
+	recv_frame.mLength = net_buf_frags_len(pkt->buffer);
+	recv_frame.mChannel = platformRadioChannelGet(instance);
+	recv_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt);
+	recv_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt);
+	recv_frame.mInfo.mRxInfo.mAckedWithFramePending =
+						net_pkt_ieee802154_ack_fpb(pkt);
+
+#if defined(CONFIG_NET_PKT_TIMESTAMP)
+	struct net_ptp_time *time = net_pkt_timestamp(pkt);
+
+	recv_frame.mInfo.mRxInfo.mTimestamp = time->second * USEC_PER_SEC +
+					      time->nanosecond / NSEC_PER_USEC;
+#endif
+
+	if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
+		otPlatDiagRadioReceiveDone(instance,
+					   &recv_frame, OT_ERROR_NONE);
+	} else {
+		otPlatRadioReceiveDone(instance,
+				       &recv_frame, OT_ERROR_NONE);
+	}
+
+	net_pkt_unref(pkt);
+}
+
+static void openthread_handle_frame_to_send(otInstance *instance,
+					    struct net_pkt *pkt)
+{
+	struct net_buf *buf;
+	otMessage *message;
+	otMessageSettings settings;
+
+	NET_DBG("Sending Ip6 packet to ot stack");
+
+	settings.mPriority = OT_MESSAGE_PRIORITY_NORMAL;
+	settings.mLinkSecurityEnabled = true;
+	message = otIp6NewMessage(instance, &settings);
+	if (message == NULL) {
+		goto exit;
+	}
+
+	for (buf = pkt->buffer; buf; buf = buf->frags) {
+		if (otMessageAppend(message, buf->data,
+				    buf->len) != OT_ERROR_NONE) {
+			NET_ERR("Error while appending to otMessage");
+			otMessageFree(message);
+			goto exit;
+		}
+	}
+
+	if (otIp6Send(instance, message) != OT_ERROR_NONE) {
+		NET_ERR("Error while calling otIp6Send");
+		goto exit;
+	}
+
+exit:
+	net_pkt_unref(pkt);
+}
+
+int notify_new_rx_frame(struct net_pkt *pkt)
+{
+	k_fifo_put(&rx_pkt_fifo, pkt);
+	set_pending_event(PENDING_EVENT_FRAME_RECEIVED);
+
+	return 0;
+}
+
+int notify_new_tx_frame(struct net_pkt *pkt)
+{
+	k_fifo_put(&tx_pkt_fifo, pkt);
+	set_pending_event(PENDING_EVENT_FRAME_TO_SEND);
+
+	return 0;
+}
+
+static int run_tx_task(otInstance *aInstance)
+{
+	static struct k_work tx_job;
+
+	ARG_UNUSED(aInstance);
+
+	if (k_work_pending(&tx_job) == 0) {
+		sState = OT_RADIO_STATE_TRANSMIT;
+
+		k_work_init(&tx_job, transmit_message);
+		k_work_submit_to_queue(&ot_work_q, &tx_job);
+		return 0;
+	} else {
+		return -EBUSY;
+	}
+}
+
+void platformRadioProcess(otInstance *aInstance)
+{
+	bool event_pending = false;
+
+	if (is_pending_event_set(PENDING_EVENT_FRAME_TO_SEND)) {
+		struct net_pkt *tx_pkt;
+
+		reset_pending_event(PENDING_EVENT_FRAME_TO_SEND);
+		while ((tx_pkt = (struct net_pkt *)k_fifo_get(&tx_pkt_fifo,
+							      K_NO_WAIT))
+		      != NULL) {
+			openthread_handle_frame_to_send(aInstance, tx_pkt);
+		}
+	}
+
+	if (is_pending_event_set(PENDING_EVENT_FRAME_RECEIVED)) {
+		struct net_pkt *rx_pkt;
+
+		reset_pending_event(PENDING_EVENT_FRAME_RECEIVED);
+		while ((rx_pkt = (struct net_pkt *)k_fifo_get(&rx_pkt_fifo,
+							      K_NO_WAIT))
+		      != NULL) {
+			openthread_handle_received_frame(aInstance, rx_pkt);
+		}
+	}
+
+	if (is_pending_event_set(PENDING_EVENT_RX_FAILED)) {
+		reset_pending_event(PENDING_EVENT_RX_FAILED);
+		if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) {
+			otPlatDiagRadioReceiveDone(aInstance,
+						   NULL, tx_rx_result);
+		} else {
+			otPlatRadioReceiveDone(aInstance,
+					       NULL, tx_rx_result);
+		}
+	}
+
+	if (is_pending_event_set(PENDING_EVENT_TX_STARTED)) {
+		reset_pending_event(PENDING_EVENT_TX_STARTED);
+		otPlatRadioTxStarted(aInstance, &sTransmitFrame);
+	}
+
+	if (is_pending_event_set(PENDING_EVENT_TX_DONE)) {
+		reset_pending_event(PENDING_EVENT_TX_DONE);
+
+		if (sState == OT_RADIO_STATE_TRANSMIT) {
+			sState = OT_RADIO_STATE_RECEIVE;
+			handle_tx_done(aInstance);
+		}
+	}
+
+	/* handle events that can't run during transmission */
+	if (sState != OT_RADIO_STATE_TRANSMIT) {
+		if (is_pending_event_set(PENDING_EVENT_DETECT_ENERGY)) {
+			radio_api->set_channel(radio_dev,
+					       energy_detection_channel);
+
+			if (!radio_api->ed_scan(radio_dev,
+						energy_detection_time,
+						energy_detected)) {
+				reset_pending_event(
+					PENDING_EVENT_DETECT_ENERGY);
+			} else {
+				event_pending = true;
+			}
+		}
+
+		if (is_pending_event_set(PENDING_EVENT_DETECT_ENERGY_DONE)) {
+			otPlatRadioEnergyScanDone(aInstance,
+						(int8_t)energy_detected_value);
+			reset_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
+		}
+	}
+
+	if (event_pending) {
+		otSysEventSignalPending();
+	}
+}
+
+uint16_t platformRadioChannelGet(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	return channel;
+}
+
+void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
+{
+	ARG_UNUSED(aInstance);
+
+	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_PAN_ID,
+			  (struct ieee802154_filter *) &aPanId);
+}
+
+void otPlatRadioSetExtendedAddress(otInstance *aInstance,
+				   const otExtAddress *aExtAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_IEEE_ADDR,
+			  (struct ieee802154_filter *) &aExtAddress);
+}
+
+void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	radio_api->filter(radio_dev, true, IEEE802154_FILTER_TYPE_SHORT_ADDR,
+			  (struct ieee802154_filter *) &aShortAddress);
+}
+
+bool otPlatRadioIsEnabled(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	return (sState != OT_RADIO_STATE_DISABLED) ? true : false;
+}
+
+otError otPlatRadioEnable(otInstance *aInstance)
+{
+	if (!otPlatRadioIsEnabled(aInstance)) {
+		sState = OT_RADIO_STATE_SLEEP;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioDisable(otInstance *aInstance)
+{
+	if (otPlatRadioIsEnabled(aInstance)) {
+		sState = OT_RADIO_STATE_DISABLED;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioSleep(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	otError error = OT_ERROR_INVALID_STATE;
+
+	if (sState == OT_RADIO_STATE_SLEEP ||
+	    sState == OT_RADIO_STATE_RECEIVE ||
+	    sState == OT_RADIO_STATE_TRANSMIT) {
+		error = OT_ERROR_NONE;
+		sState = OT_RADIO_STATE_SLEEP;
+		radio_api->stop(radio_dev);
+	}
+
+	return error;
+}
+
+otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
+{
+	ARG_UNUSED(aInstance);
+
+	channel = aChannel;
+
+	radio_api->set_channel(radio_dev, aChannel);
+	radio_api->set_txpower(radio_dev, tx_power);
+	radio_api->start(radio_dev);
+	sState = OT_RADIO_STATE_RECEIVE;
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aPacket)
+{
+	otError error = OT_ERROR_INVALID_STATE;
+
+	ARG_UNUSED(aInstance);
+	ARG_UNUSED(aPacket);
+
+	__ASSERT_NO_MSG(aPacket == &sTransmitFrame);
+
+	enum ieee802154_hw_caps radio_caps;
+
+	radio_caps = radio_api->get_capabilities(radio_dev);
+
+	if ((sState == OT_RADIO_STATE_RECEIVE) ||
+		(radio_caps & IEEE802154_HW_SLEEP_TO_TX)) {
+		if (run_tx_task(aInstance) == 0) {
+			error = OT_ERROR_NONE;
+		}
+	}
+
+	return error;
+}
+
+otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	return &sTransmitFrame;
+}
+
+static void get_rssi_energy_detected(const struct device *dev, int16_t max_ed)
+{
+	ARG_UNUSED(dev);
+	energy_detected_value = max_ed;
+	k_sem_give(&radio_sem);
+}
+
+int8_t otPlatRadioGetRssi(otInstance *aInstance)
+{
+	int8_t ret_rssi = INT8_MAX;
+	int error = 0;
+	const uint16_t energy_detection_time = 1;
+	enum ieee802154_hw_caps radio_caps;
+	ARG_UNUSED(aInstance);
+
+	radio_caps = radio_api->get_capabilities(radio_dev);
+
+	if (!(radio_caps & IEEE802154_HW_ENERGY_SCAN)) {
+		/*
+		 * TODO: No API in Zephyr to get the RSSI
+		 * when IEEE802154_HW_ENERGY_SCAN is not available
+		 */
+		ret_rssi = 0;
+	} else {
+		/*
+		 * Blocking implementation of get RSSI
+		 * using no-blocking ed_scan
+		 */
+		error = radio_api->ed_scan(radio_dev, energy_detection_time,
+					   get_rssi_energy_detected);
+
+		if (error == 0) {
+			k_sem_take(&radio_sem, K_FOREVER);
+
+			ret_rssi = (int8_t)energy_detected_value;
+		}
+	}
+
+	return ret_rssi;
+}
+
+otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
+{
+	otRadioCaps caps = OT_RADIO_CAPS_NONE;
+
+	enum ieee802154_hw_caps radio_caps;
+	ARG_UNUSED(aInstance);
+	__ASSERT(radio_api,
+	    "platformRadioInit needs to be called prior to otPlatRadioGetCaps");
+
+	radio_caps = radio_api->get_capabilities(radio_dev);
+
+	if (radio_caps & IEEE802154_HW_ENERGY_SCAN) {
+		caps |= OT_RADIO_CAPS_ENERGY_SCAN;
+	}
+
+	if (radio_caps & IEEE802154_HW_CSMA) {
+		caps |= OT_RADIO_CAPS_CSMA_BACKOFF;
+	}
+
+	if (radio_caps & IEEE802154_HW_TX_RX_ACK) {
+		caps |= OT_RADIO_CAPS_ACK_TIMEOUT;
+	}
+
+	if (radio_caps & IEEE802154_HW_SLEEP_TO_TX) {
+		caps |= OT_RADIO_CAPS_SLEEP_TO_TX;
+	}
+
+	return caps;
+}
+
+bool otPlatRadioGetPromiscuous(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("PromiscuousMode=%d", promiscuous ? 1 : 0);
+
+	return promiscuous;
+}
+
+void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
+{
+	struct ieee802154_config config = {
+		.promiscuous = aEnable
+	};
+
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("PromiscuousMode=%d", aEnable ? 1 : 0);
+
+	promiscuous = aEnable;
+	radio_api->configure(radio_dev, IEEE802154_CONFIG_PROMISCUOUS, &config);
+}
+
+otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel,
+			      uint16_t aScanDuration)
+{
+	energy_detection_time    = aScanDuration;
+	energy_detection_channel = aScanChannel;
+
+	if (radio_api->ed_scan == NULL) {
+		return OT_ERROR_NOT_IMPLEMENTED;
+	}
+
+	reset_pending_event(PENDING_EVENT_DETECT_ENERGY);
+	reset_pending_event(PENDING_EVENT_DETECT_ENERGY_DONE);
+
+	radio_api->set_channel(radio_dev, aScanChannel);
+
+	if (radio_api->ed_scan(radio_dev, energy_detection_time,
+				    energy_detected) != 0) {
+		/*
+		 * OpenThread API does not accept failure of this function,
+		 * it can return 'No Error' or 'Not Implemented' error only.
+		 * If ed_scan start failed event is set to schedule the scan at
+		 * later time.
+		 */
+		LOG_ERR("Failed do start energy scan, scheduling for later");
+		set_pending_event(PENDING_EVENT_DETECT_ENERGY);
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance,
+					       int8_t *aThreshold)
+{
+	OT_UNUSED_VARIABLE(aInstance);
+	OT_UNUSED_VARIABLE(aThreshold);
+
+	return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance,
+					       int8_t aThreshold)
+{
+	OT_UNUSED_VARIABLE(aInstance);
+	OT_UNUSED_VARIABLE(aThreshold);
+
+	return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
+{
+	ARG_UNUSED(aInstance);
+
+	struct ieee802154_config config = {
+		.auto_ack_fpb.enabled = aEnable,
+		.auto_ack_fpb.mode = IEEE802154_FPB_ADDR_MATCH_THREAD,
+	};
+
+	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_AUTO_ACK_FPB,
+				   &config);
+}
+
+otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance,
+					 const uint16_t aShortAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	uint8_t short_address[SHORT_ADDRESS_SIZE];
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = true,
+		.ack_fpb.addr = short_address,
+		.ack_fpb.extended = false
+	};
+
+	sys_put_le16(aShortAddress, short_address);
+
+	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				 &config) != 0) {
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance,
+				       const otExtAddress *aExtAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = true,
+		.ack_fpb.addr = (uint8_t *)aExtAddress->m8,
+		.ack_fpb.extended = true
+	};
+
+	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				 &config) != 0) {
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance,
+					   const uint16_t aShortAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	uint8_t short_address[SHORT_ADDRESS_SIZE];
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = false,
+		.ack_fpb.addr = short_address,
+		.ack_fpb.extended = false
+	};
+
+	sys_put_le16(aShortAddress, short_address);
+
+	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				 &config) != 0) {
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance,
+					 const otExtAddress *aExtAddress)
+{
+	ARG_UNUSED(aInstance);
+
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = false,
+		.ack_fpb.addr = (uint8_t *)aExtAddress->m8,
+		.ack_fpb.extended = true
+	};
+
+	if (radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				 &config) != 0) {
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = false,
+		.ack_fpb.addr = NULL,
+		.ack_fpb.extended = false
+	};
+
+	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				   &config);
+}
+
+void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	struct ieee802154_config config = {
+		.ack_fpb.enabled = false,
+		.ack_fpb.addr = NULL,
+		.ack_fpb.extended = true
+	};
+
+	(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_ACK_FPB,
+				   &config);
+}
+
+int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	return -100;
+}
+
+otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
+{
+	ARG_UNUSED(aInstance);
+
+	if (aPower == NULL) {
+		return OT_ERROR_INVALID_ARGS;
+	}
+
+	*aPower = tx_power;
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
+{
+	ARG_UNUSED(aInstance);
+
+	tx_power = aPower;
+
+	return OT_ERROR_NONE;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/settings.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/settings.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/settings.c	(working copy)
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <logging/log.h>
+#include <settings/settings.h>
+#include <random/rand32.h>
+
+#include <openthread/platform/settings.h>
+
+LOG_MODULE_REGISTER(net_otPlat_settings, CONFIG_OPENTHREAD_L2_LOG_LEVEL);
+
+#define OT_SETTINGS_ROOT_KEY "ot"
+#define OT_SETTINGS_MAX_PATH_LEN 32
+
+struct ot_setting_delete_ctx {
+	/* Setting subtree to delete. */
+	const char *subtree;
+
+	/* Current entry index, used to iterate over multiple setting
+	 * instances.
+	 */
+	int index;
+
+	/* Target index to delete. -1 to delete entire subtree. */
+	int target_index;
+
+	/* Operation result. */
+	int status;
+};
+
+static int ot_setting_delete_cb(const char *key, size_t len,
+				settings_read_cb read_cb, void *cb_arg,
+				void *param)
+{
+	int ret;
+	char path[OT_SETTINGS_MAX_PATH_LEN];
+	struct ot_setting_delete_ctx *ctx =
+		(struct ot_setting_delete_ctx *)param;
+
+	ARG_UNUSED(len);
+	ARG_UNUSED(read_cb);
+	ARG_UNUSED(cb_arg);
+
+	if ((ctx->target_index != -1) && (ctx->target_index != ctx->index)) {
+		ctx->index++;
+		return 0;
+	}
+
+	ret = snprintk(path, sizeof(path), "%s%s%s", ctx->subtree,
+		       key ? "/" : "", key ? key : "");
+	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");
+
+	LOG_DBG("Removing: %s", log_strdup(path));
+
+	ret = settings_delete(path);
+	if (ret != 0) {
+		LOG_ERR("Failed to remove setting %s, ret %d", log_strdup(path),
+			ret);
+	}
+
+	ctx->status = 0;
+
+	if (ctx->target_index == ctx->index) {
+		/* Break the loop on index match, otherwise it was -1
+		 * (delete all).
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+static int ot_setting_delete_subtree(int key, int index)
+{
+	int ret;
+	char subtree[OT_SETTINGS_MAX_PATH_LEN];
+	struct ot_setting_delete_ctx delete_ctx = {
+		.subtree = subtree,
+		.status = -ENOENT,
+		.target_index = index
+	};
+
+	if (key == -1) {
+		ret = snprintk(subtree, sizeof(subtree), "%s",
+			       OT_SETTINGS_ROOT_KEY);
+	} else {
+		ret = snprintk(subtree, sizeof(subtree), "%s/%x",
+			       OT_SETTINGS_ROOT_KEY, key);
+	}
+	__ASSERT(ret < sizeof(subtree), "Setting path buffer too small.");
+
+	ret = settings_load_subtree_direct(subtree, ot_setting_delete_cb,
+					   &delete_ctx);
+	if (ret != 0) {
+		LOG_ERR("Failed to delete OT subtree %s, index %d, ret %d",
+			subtree, index, ret);
+	}
+
+	return delete_ctx.status;
+}
+
+static int ot_setting_exists_cb(const char *key, size_t len,
+				settings_read_cb read_cb, void *cb_arg,
+				void *param)
+{
+	bool *exists = (bool *)param;
+
+	ARG_UNUSED(len);
+	ARG_UNUSED(read_cb);
+	ARG_UNUSED(cb_arg);
+	ARG_UNUSED(key);
+
+	*exists = true;
+
+	return 1;
+}
+
+static bool ot_setting_exists(const char *path)
+{
+	bool exists = false;
+
+	(void)settings_load_subtree_direct(path, ot_setting_exists_cb, &exists);
+
+	return exists;
+}
+
+struct ot_setting_read_ctx {
+	/* Buffer for the setting. */
+	uint8_t *value;
+
+	/* Buffer length on input, setting length read on output. */
+	uint16_t *length;
+
+	/* Current entry index, used to iterate over multiple setting
+	 * instances.
+	 */
+	int index;
+
+	/* Target instnace to read. */
+	int target_index;
+
+	/* Operation result. */
+	int status;
+};
+
+static int ot_setting_read_cb(const char *key, size_t len,
+			      settings_read_cb read_cb, void *cb_arg,
+			      void *param)
+{
+	int ret;
+	struct ot_setting_read_ctx *ctx = (struct ot_setting_read_ctx *)param;
+
+	ARG_UNUSED(len);
+	ARG_UNUSED(read_cb);
+	ARG_UNUSED(cb_arg);
+
+	if (ctx->target_index != ctx->index) {
+		ctx->index++;
+		return 0;
+	}
+
+	/* Found setting, break the loop. */
+
+	if ((ctx->value == NULL) || (ctx->length == NULL)) {
+		goto out;
+	}
+
+	if (*(ctx->length) < len) {
+		len = *(ctx->length);
+	}
+
+	ret = read_cb(cb_arg, ctx->value, len);
+	if (ret <= 0) {
+		LOG_ERR("Failed to read the setting, ret: %d", ret);
+		ctx->status = -EIO;
+		return 1;
+	}
+
+out:
+	if (ctx->length != NULL) {
+		*(ctx->length) = len;
+	}
+
+	ctx->status = 0;
+
+	return 1;
+}
+
+/* OpenThread APIs */
+
+void otPlatSettingsInit(otInstance *aInstance)
+{
+	int ret;
+
+	ARG_UNUSED(aInstance);
+
+	ret = settings_subsys_init();
+	if (ret != 0) {
+		LOG_ERR("settings_subsys_init failed (ret %d)", ret);
+	}
+}
+
+otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex,
+			  uint8_t *aValue, uint16_t *aValueLength)
+{
+	int ret;
+	char path[OT_SETTINGS_MAX_PATH_LEN];
+	struct ot_setting_read_ctx read_ctx = {
+		.value = aValue,
+		.length = (uint16_t *)aValueLength,
+		.status = -ENOENT,
+		.target_index = aIndex
+	};
+
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("%s Entry aKey %u aIndex %d", __func__, aKey, aIndex);
+
+	ret = snprintk(path, sizeof(path), "%s/%x", OT_SETTINGS_ROOT_KEY, aKey);
+	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");
+
+	ret = settings_load_subtree_direct(path, ot_setting_read_cb, &read_ctx);
+	if (ret != 0) {
+		LOG_ERR("Failed to load OT setting aKey %d, aIndex %d, ret %d",
+			aKey, aIndex, ret);
+	}
+
+	if (read_ctx.status != 0) {
+		LOG_DBG("aKey %u aIndex %d not found", aKey, aIndex);
+		return OT_ERROR_NOT_FOUND;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey,
+			  const uint8_t *aValue, uint16_t aValueLength)
+{
+	int ret;
+	char path[OT_SETTINGS_MAX_PATH_LEN];
+
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("%s Entry aKey %u", __func__, aKey);
+
+	(void)ot_setting_delete_subtree(aKey, -1);
+
+	ret = snprintk(path, sizeof(path), "%s/%x/%08x", OT_SETTINGS_ROOT_KEY,
+		       aKey, sys_rand32_get());
+	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");
+
+	ret = settings_save_one(path, aValue, aValueLength);
+	if (ret != 0) {
+		LOG_ERR("Failed to store setting %d, ret %d", aKey, ret);
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey,
+			  const uint8_t *aValue, uint16_t aValueLength)
+{
+	int ret;
+	char path[OT_SETTINGS_MAX_PATH_LEN];
+
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("%s Entry aKey %u", __func__, aKey);
+
+	do {
+		ret = snprintk(path, sizeof(path), "%s/%x/%08x",
+			       OT_SETTINGS_ROOT_KEY, aKey, sys_rand32_get());
+		__ASSERT(ret < sizeof(path), "Setting path buffer too small.");
+	} while (ot_setting_exists(path));
+
+	ret = settings_save_one(path, aValue, aValueLength);
+	if (ret != 0) {
+		LOG_ERR("Failed to store setting %d, ret %d", aKey, ret);
+		return OT_ERROR_NO_BUFS;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
+{
+	int ret;
+
+	ARG_UNUSED(aInstance);
+
+	LOG_DBG("%s Entry aKey %u aIndex %d", __func__, aKey, aIndex);
+
+	ret = ot_setting_delete_subtree(aKey, aIndex);
+	if (ret != 0) {
+		LOG_DBG("Entry not found aKey %u aIndex %d", aKey, aIndex);
+		return OT_ERROR_NOT_FOUND;
+	}
+
+	return OT_ERROR_NONE;
+}
+
+void otPlatSettingsWipe(otInstance *aInstance)
+{
+	ARG_UNUSED(aInstance);
+
+	(void)ot_setting_delete_subtree(-1, -1);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/shell.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/shell.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/shell.c	(working copy)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <stdio.h>
+#include <net/openthread.h>
+#include <sys/printk.h>
+#include <shell/shell.h>
+#include <shell/shell_uart.h>
+
+#include <openthread/cli.h>
+#include <openthread/instance.h>
+
+#include "platform-zephyr.h"
+
+#define OT_SHELL_BUFFER_SIZE CONFIG_SHELL_CMD_BUFF_SIZE
+
+static char rx_buffer[OT_SHELL_BUFFER_SIZE];
+
+static const struct shell *shell_p;
+
+int otConsoleOutputCallback(const char *aBuf, uint16_t aBufLength,
+			    void *aContext)
+{
+	ARG_UNUSED(aContext);
+
+	shell_fprintf(shell_p, SHELL_NORMAL, "%s", aBuf);
+
+	return aBufLength;
+}
+
+#define SHELL_HELP_OT	"OpenThread subcommands\n" \
+			"Use \"ot help\" to get the list of subcommands"
+
+static int ot_cmd(const struct shell *shell, size_t argc, char *argv[])
+{
+	char *buf_ptr = rx_buffer;
+	size_t buf_len = OT_SHELL_BUFFER_SIZE;
+	size_t arg_len = 0;
+	k_tid_t ot_tid = openthread_thread_id_get();
+	int i;
+
+	for (i = 1; i < argc; i++) {
+		if (arg_len) {
+			buf_len -= arg_len + 1;
+			if (buf_len) {
+				buf_ptr[arg_len] = ' ';
+			}
+			buf_ptr += arg_len + 1;
+		}
+
+		arg_len = snprintk(buf_ptr, buf_len, "%s", argv[i]);
+
+		if (arg_len >= buf_len) {
+			shell_fprintf(shell, SHELL_WARNING,
+				      "OT shell buffer full\n");
+			return -ENOEXEC;
+		}
+	}
+
+	if (i == argc) {
+		buf_len -= arg_len;
+	}
+
+	shell_p = shell;
+
+	/* Halt the OpenThread thread execution. This will prevent from being
+	 * rescheduled into the OT thread in the middle of command processing.
+	 */
+	k_thread_suspend(ot_tid);
+	otCliConsoleInputLine(rx_buffer, OT_SHELL_BUFFER_SIZE - buf_len);
+	k_thread_resume(ot_tid);
+
+	return 0;
+}
+
+SHELL_CMD_ARG_REGISTER(ot, NULL, SHELL_HELP_OT, ot_cmd, 2, 255);
+
+void platformShellInit(otInstance *aInstance)
+{
+	otCliConsoleInit(aInstance, otConsoleOutputCallback, NULL);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/spi.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/spi.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/spi.c	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <openthread/platform/uart.h>
+#include <openthread/platform/spi-slave.h>
+
+#include "platform-zephyr.h"
+
+/* Spi-slave stubs */
+
+otError otPlatSpiSlaveEnable(
+	otPlatSpiSlaveTransactionCompleteCallback aCompleteCallback,
+	otPlatSpiSlaveTransactionProcessCallback aProcessCallback,
+	void *aContext)
+{
+	ARG_UNUSED(aCompleteCallback);
+	ARG_UNUSED(aProcessCallback);
+	ARG_UNUSED(aContext);
+
+	return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+void otPlatSpiSlaveDisable(void)
+{
+	/* Intentionally empty */
+}
+
+otError otPlatSpiSlavePrepareTransaction(
+	uint8_t *anOutputBuf,
+	uint16_t anOutputBufLen,
+	uint8_t *anInputBuf,
+	uint16_t anInputBufLen,
+	bool aRequestTransactionFlag
+)
+{
+	ARG_UNUSED(anOutputBuf);
+	ARG_UNUSED(anOutputBufLen);
+	ARG_UNUSED(anInputBuf);
+	ARG_UNUSED(anInputBufLen);
+	ARG_UNUSED(aRequestTransactionFlag);
+
+	return OT_ERROR_NOT_IMPLEMENTED;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/uart.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/uart.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/openthread/platform/uart.c	(working copy)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2020 Tridonic GmbH & Co KG
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_LEVEL CONFIG_OPENTHREAD_LOG_LEVEL
+#define LOG_MODULE_NAME net_otPlat_uart
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <kernel.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <drivers/uart.h>
+
+#include <sys/ring_buffer.h>
+#include <sys/atomic.h>
+
+#ifdef CONFIG_OPENTHREAD_NCP_SPINEL_ON_UART_ACM
+#include <usb/usb_device.h>
+#endif
+
+#include <openthread-system.h>
+#include <openthread/platform/uart.h>
+
+#include "platform-zephyr.h"
+
+struct openthread_uart {
+	struct ring_buf *rx_ringbuf;
+	const struct device *dev;
+	atomic_t tx_busy;
+	atomic_t tx_finished;
+};
+
+#define OT_UART_DEFINE(_name, _ringbuf_size) \
+	RING_BUF_DECLARE(_name##_rx_ringbuf, _ringbuf_size); \
+	static struct openthread_uart _name = { \
+		.rx_ringbuf = &_name##_rx_ringbuf, \
+	}
+
+OT_UART_DEFINE(ot_uart, CONFIG_OPENTHREAD_NCP_UART_RING_BUFFER_SIZE);
+
+#define RX_FIFO_SIZE 128
+
+static bool is_panic_mode;
+static const uint8_t *write_buffer;
+static uint16_t write_length;
+
+static void uart_rx_handle(const struct device *dev)
+{
+	uint8_t *data;
+	uint32_t len;
+	uint32_t rd_len;
+	bool new_data = false;
+
+	do {
+		len = ring_buf_put_claim(
+			ot_uart.rx_ringbuf, &data,
+			ot_uart.rx_ringbuf->size);
+		if (len > 0) {
+			rd_len = uart_fifo_read(dev, data, len);
+			if (rd_len > 0) {
+				new_data = true;
+			}
+
+			int err = ring_buf_put_finish(
+				ot_uart.rx_ringbuf, rd_len);
+			(void)err;
+			__ASSERT_NO_MSG(err == 0);
+		} else {
+			uint8_t dummy;
+
+			/* No space in the ring buffer - consume byte. */
+			LOG_WRN("RX ring buffer full.");
+
+			rd_len = uart_fifo_read(dev, &dummy, 1);
+		}
+	} while (rd_len && (rd_len == len));
+
+	if (new_data) {
+		otSysEventSignalPending();
+	}
+}
+
+static void uart_tx_handle(const struct device *dev)
+{
+	uint32_t len;
+
+	if (write_length) {
+		len = uart_fifo_fill(dev, write_buffer, write_length);
+		write_buffer += len;
+		write_length -= len;
+	} else {
+		uart_irq_tx_disable(dev);
+		ot_uart.tx_busy = 0;
+		atomic_set(&(ot_uart.tx_finished), 1);
+		otSysEventSignalPending();
+	}
+}
+
+static void uart_callback(const struct device *dev, void *user_data)
+{
+	ARG_UNUSED(user_data);
+
+	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
+
+		if (uart_irq_rx_ready(dev)) {
+			uart_rx_handle(dev);
+		}
+
+		if (uart_irq_tx_ready(dev)) {
+			uart_tx_handle(dev);
+		}
+	}
+}
+
+void platformUartProcess(otInstance *aInstance)
+{
+	uint32_t len = 0;
+	const uint8_t *data;
+
+	/* Process UART RX */
+	while ((len = ring_buf_get_claim(
+			ot_uart.rx_ringbuf,
+			(uint8_t **)&data,
+			ot_uart.rx_ringbuf->size)) > 0) {
+		int err;
+
+		otPlatUartReceived(data, len);
+		err = ring_buf_get_finish(
+				ot_uart.rx_ringbuf,
+				len);
+		(void)err;
+		__ASSERT_NO_MSG(err == 0);
+	}
+
+	/* Process UART TX */
+	if (ot_uart.tx_finished) {
+		LOG_DBG("UART TX done");
+		otPlatUartSendDone();
+		ot_uart.tx_finished = 0;
+	}
+};
+
+otError otPlatUartEnable(void)
+{
+	ot_uart.dev = device_get_binding(
+		CONFIG_OPENTHREAD_NCP_SPINEL_ON_UART_DEV_NAME);
+
+	if ((&ot_uart)->dev == NULL) {
+		LOG_ERR("UART device not found");
+		return OT_ERROR_FAILED;
+	}
+
+	uart_irq_callback_user_data_set(ot_uart.dev,
+					uart_callback,
+					(void *)&ot_uart);
+	uart_irq_rx_enable(ot_uart.dev);
+
+	return OT_ERROR_NONE;
+};
+
+otError otPlatUartDisable(void)
+{
+#ifdef CONFIG_OPENTHREAD_NCP_SPINEL_ON_UART_ACM
+	int ret = usb_disable();
+
+	if (ret) {
+		LOG_WRN("Failed to disable USB (%d)", ret);
+	}
+#endif
+
+	uart_irq_tx_disable(ot_uart.dev);
+	uart_irq_rx_disable(ot_uart.dev);
+	return OT_ERROR_NONE;
+};
+
+
+otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
+{
+	if (aBuf == NULL) {
+		return OT_ERROR_FAILED;
+	}
+
+	write_buffer = aBuf;
+	write_length = aBufLength;
+
+	if (atomic_set(&(ot_uart.tx_busy), 1) == 0) {
+		if (is_panic_mode) {
+			/* In panic mode all data have to be send immediately
+			 * without using interrupts
+			 */
+			otPlatUartFlush();
+		} else {
+			uart_irq_tx_enable(ot_uart.dev);
+		}
+	}
+
+	return OT_ERROR_NONE;
+};
+
+otError otPlatUartFlush(void)
+{
+	otError result = OT_ERROR_NONE;
+
+	if (write_length) {
+		for (size_t i = 0; i < write_length; i++) {
+			uart_poll_out(ot_uart.dev, *(write_buffer+i));
+		}
+	}
+
+	ot_uart.tx_busy = 0;
+	atomic_set(&(ot_uart.tx_finished), 1);
+	otSysEventSignalPending();
+	return result;
+}
+
+void platformUartPanic(void)
+{
+	is_panic_mode = true;
+	/* In panic mode data are send without using interrupts.
+	 * Reception in this mode is not supported.
+	 */
+	uart_irq_tx_disable(ot_uart.dev);
+	uart_irq_rx_disable(ot_uart.dev);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/CMakeLists.txt	(working copy)
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_sources(
+  sntp.c
+  sntp_simple.c
+)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/Kconfig	(working copy)
@@ -0,0 +1,18 @@
+# Copyright (c) 2017 Linaro Limited
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig SNTP
+	bool "SNTP"
+	select NET_SOCKETS
+	help
+	  Enable SNTP client library
+
+if SNTP
+
+module = SNTP
+module-dep = NET_LOG
+module-str = Log level for SNTP
+module-help = Enable debug message of SNTP client library.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # SNTP
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp.c	(working copy)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sntp, CONFIG_SNTP_LOG_LEVEL);
+
+#include <net/sntp.h>
+#include "sntp_pkt.h"
+
+#define SNTP_LI_MAX 3
+#define SNTP_VERSION_NUMBER 3
+#define SNTP_MODE_CLIENT 3
+#define SNTP_MODE_SERVER 4
+#define SNTP_STRATUM_KOD 0 /* kiss-o'-death */
+#define OFFSET_1970_JAN_1 2208988800
+
+static void sntp_pkt_dump(struct sntp_pkt *pkt)
+{
+	if (!pkt) {
+		return;
+	}
+
+	NET_DBG("li               %x", SNTP_GET_LI(pkt->lvm));
+	NET_DBG("vn               %x", SNTP_GET_VN(pkt->lvm));
+	NET_DBG("mode             %x", SNTP_GET_MODE(pkt->lvm));
+	NET_DBG("stratum:         %x", pkt->stratum);
+	NET_DBG("poll:            %x", pkt->poll);
+	NET_DBG("precision:       %x", pkt->precision);
+	NET_DBG("root_delay:      %x", pkt->root_delay);
+	NET_DBG("root_dispersion: %x", pkt->root_dispersion);
+	NET_DBG("ref_id:          %x", pkt->ref_id);
+	NET_DBG("ref_tm_s:        %x", pkt->ref_tm_s);
+	NET_DBG("ref_tm_f:        %x", pkt->ref_tm_f);
+	NET_DBG("orig_tm_s:       %x", pkt->orig_tm_s);
+	NET_DBG("orig_tm_f:       %x", pkt->orig_tm_f);
+	NET_DBG("rx_tm_s:         %x", pkt->rx_tm_s);
+	NET_DBG("rx_tm_f:         %x", pkt->rx_tm_f);
+	NET_DBG("tx_tm_s:         %x", pkt->tx_tm_s);
+	NET_DBG("tx_tm_f:         %x", pkt->tx_tm_f);
+}
+
+static int32_t parse_response(uint8_t *data, uint16_t len, uint32_t orig_ts,
+			    struct sntp_time *time)
+{
+	struct sntp_pkt *pkt = (struct sntp_pkt *)data;
+	uint32_t ts;
+
+	sntp_pkt_dump(pkt);
+
+	if (ntohl(pkt->orig_tm_s) != orig_ts) {
+		NET_DBG("Mismatch originate timestamp: %d, expect: %d",
+			ntohl(pkt->orig_tm_s), orig_ts);
+		return -EINVAL;
+	}
+
+	if (SNTP_GET_MODE(pkt->lvm) != SNTP_MODE_SERVER) {
+		/* For unicast and manycast, server should return 4.
+		 * For broadcast (which is not supported now), server should
+		 * return 5.
+		 */
+		NET_DBG("Unexpected mode: %d", SNTP_GET_MODE(pkt->lvm));
+		return -EINVAL;
+	}
+
+	if (pkt->stratum == SNTP_STRATUM_KOD) {
+		NET_DBG("kiss-o'-death stratum");
+		return -EBUSY;
+	}
+
+	if (ntohl(pkt->tx_tm_s) == 0 && ntohl(pkt->tx_tm_f) == 0) {
+		NET_DBG("zero transmit timestamp");
+		return -EINVAL;
+	}
+
+	time->fraction = ntohl(pkt->tx_tm_f);
+	ts = ntohl(pkt->tx_tm_s);
+
+	/* Check if most significant bit is set */
+	if (ts & 0x80000000) {
+		/* UTC time is reckoned from 0h 0m 0s UTC
+		 * on 1 January 1900.
+		 */
+		if (ts >= OFFSET_1970_JAN_1) {
+			time->seconds = ts - OFFSET_1970_JAN_1;
+		} else {
+			return -EINVAL;
+		}
+	} else {
+		/* UTC time is reckoned from 6h 28m 16s UTC
+		 * on 7 February 2036.
+		 */
+		time->seconds = ts + 0x100000000ULL - OFFSET_1970_JAN_1;
+	}
+
+	return 0;
+}
+
+static int sntp_recv_response(struct sntp_ctx *sntp, uint32_t timeout,
+			      struct sntp_time *time)
+{
+	struct sntp_pkt buf = { 0 };
+	int status;
+	int rcvd;
+
+	status = poll(sntp->sock.fds, sntp->sock.nfds, timeout);
+	if (status < 0) {
+		NET_ERR("Error in poll:%d", errno);
+		return -errno;
+	}
+
+	if (status == 0) {
+		return -ETIMEDOUT;
+	}
+
+	rcvd = recv(sntp->sock.fd, (uint8_t *)&buf, sizeof(buf), 0);
+	if (rcvd < 0) {
+		return -errno;
+	}
+
+	if (rcvd != sizeof(struct sntp_pkt)) {
+		return -EMSGSIZE;
+	}
+
+	status = parse_response((uint8_t *)&buf, sizeof(buf),
+				sntp->expected_orig_ts,
+				time);
+	return status;
+}
+
+static uint32_t get_uptime_in_sec(void)
+{
+	uint64_t time;
+
+	time = k_uptime_get_32();
+
+	return time / MSEC_PER_SEC;
+}
+
+int sntp_init(struct sntp_ctx *ctx, struct sockaddr *addr, socklen_t addr_len)
+{
+	int ret;
+
+	if (!ctx || !addr) {
+		return -EFAULT;
+	}
+
+	memset(ctx, 0, sizeof(struct sntp_ctx));
+
+	ctx->sock.fd = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (ctx->sock.fd < 0) {
+		NET_ERR("Failed to create UDP socket %d", errno);
+		return -errno;
+	}
+
+	ret = connect(ctx->sock.fd, addr, addr_len);
+	if (ret < 0) {
+		(void)close(ctx->sock.fd);
+		NET_ERR("Cannot connect to UDP remote : %d", errno);
+		return -errno;
+	}
+
+	ctx->sock.fds[ctx->sock.nfds].fd = ctx->sock.fd;
+	ctx->sock.fds[ctx->sock.nfds].events = POLLIN;
+	ctx->sock.nfds++;
+
+	return 0;
+}
+
+int sntp_query(struct sntp_ctx *ctx, uint32_t timeout, struct sntp_time *time)
+{
+	struct sntp_pkt tx_pkt = { 0 };
+	int ret = 0;
+
+	if (!ctx || !time) {
+		return -EFAULT;
+	}
+
+	/* prepare request pkt */
+	SNTP_SET_LI(tx_pkt.lvm, 0);
+	SNTP_SET_VN(tx_pkt.lvm, SNTP_VERSION_NUMBER);
+	SNTP_SET_MODE(tx_pkt.lvm, SNTP_MODE_CLIENT);
+	ctx->expected_orig_ts = get_uptime_in_sec() + OFFSET_1970_JAN_1;
+	tx_pkt.tx_tm_s = htonl(ctx->expected_orig_ts);
+
+	ret = send(ctx->sock.fd, (uint8_t *)&tx_pkt, sizeof(tx_pkt), 0);
+	if (ret < 0) {
+		NET_ERR("Failed to send over UDP socket %d", ret);
+		return ret;
+	}
+
+	return sntp_recv_response(ctx, timeout, time);
+}
+
+void sntp_close(struct sntp_ctx *ctx)
+{
+	if (ctx) {
+		(void)close(ctx->sock.fd);
+	}
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_pkt.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_pkt.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_pkt.h	(working copy)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __SNTP_PKT_H
+#define __SNTP_PKT_H
+
+#include <zephyr/types.h>
+
+#define SNTP_LI_MASK   0xC0
+#define SNTP_VN_MASK   0x38
+#define SNTP_MODE_MASK 0x07
+
+#define SNTP_LI_SHIFT   6
+#define SNTP_VN_SHIFT   3
+#define SNTP_MODE_SHIFT 0
+
+#define SNTP_GET_LI(x)    ((x & SNTP_LI_MASK) >> SNTP_LI_SHIFT)
+#define SNTP_GET_VN(x)    ((x & SNTP_VN_MASK) >> SNTP_VN_SHIFT)
+#define SNTP_GET_MODE(x)  ((x & SNTP_MODE_MASK) >> SNTP_MODE_SHIFT)
+
+#define SNTP_SET_LI(x, v)   (x = x | (v << SNTP_LI_SHIFT))
+#define SNTP_SET_VN(x, v)   (x = x | (v << SNTP_VN_SHIFT))
+#define SNTP_SET_MODE(x, v) (x = x | (v << SNTP_MODE_SHIFT))
+
+struct sntp_pkt {
+	uint8_t lvm;		/* li, vn, and mode in big endian fashion */
+	uint8_t stratum;
+	uint8_t poll;
+	uint8_t precision;
+	uint32_t root_delay;
+	uint32_t root_dispersion;
+	uint32_t ref_id;
+	uint32_t ref_tm_s;
+	uint32_t ref_tm_f;
+	uint32_t orig_tm_s;	/* Originate timestamp seconds */
+	uint32_t orig_tm_f;	/* Originate timsstamp seconds fraction */
+	uint32_t rx_tm_s;		/* Receive timestamp seconds */
+	uint32_t rx_tm_f;		/* Receive timestamp seconds fraction */
+	uint32_t tx_tm_s;		/* Transimit timestamp seconds */
+	uint32_t tx_tm_f;		/* Transimit timestamp seconds fraction */
+} __packed;
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_simple.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_simple.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sntp/sntp_simple.c	(working copy)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <errno.h>
+
+#include <net/sntp.h>
+#include <net/socketutils.h>
+
+int sntp_simple(const char *server, uint32_t timeout, struct sntp_time *time)
+{
+	int res;
+	static struct addrinfo hints;
+	struct addrinfo *addr;
+	struct sntp_ctx sntp_ctx;
+	uint64_t deadline;
+	uint32_t iter_timeout;
+
+	hints.ai_family = AF_INET;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_protocol = 0;
+	/* 123 is the standard SNTP port per RFC4330 */
+	res = net_getaddrinfo_addr_str(server, "123", &hints, &addr);
+
+	if (res < 0) {
+		/* Just in case, as namespace for getaddrinfo errors is
+		 * different from errno errors.
+		 */
+		errno = EDOM;
+		return res;
+	}
+
+	res = sntp_init(&sntp_ctx, addr->ai_addr, addr->ai_addrlen);
+	if (res < 0) {
+		goto freeaddr;
+	}
+
+	if (timeout == SYS_FOREVER_MS) {
+		deadline = (uint64_t)timeout;
+	} else {
+		deadline = k_uptime_get() + (uint64_t)timeout;
+	}
+
+	/* Timeout for current iteration */
+	iter_timeout = 100;
+
+	while (k_uptime_get() < deadline) {
+		res = sntp_query(&sntp_ctx, iter_timeout, time);
+
+		if (res != -ETIMEDOUT) {
+			break;
+		}
+
+		/* Exponential backoff with limit */
+		if (iter_timeout < 1000) {
+			iter_timeout *= 2;
+		}
+	}
+
+	sntp_close(&sntp_ctx);
+
+freeaddr:
+	freeaddrinfo(addr);
+
+	return res;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/CMakeLists.txt	(working copy)
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+
+zephyr_sources(
+  getaddrinfo.c
+  sockets.c
+  sockets_select.c
+)
+
+if(NOT CONFIG_NET_SOCKETS_OFFLOAD)
+zephyr_sources(
+  getnameinfo.c
+  sockets_misc.c
+  )
+zephyr_sources_ifdef(CONFIG_NET_SOCKETS_PACKET sockets_packet.c)
+zephyr_sources_ifdef(CONFIG_NET_SOCKETS_CAN sockets_can.c)
+endif()
+zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD     socket_offload.c)
+
+if (CONFIG_NET_SOCKETS_SOCKOPT_TLS AND NOT CONFIG_NET_SOCKETS_OFFLOAD_TLS)
+zephyr_sources(sockets_tls.c)
+endif()
+
+if(CONFIG_NET_SOCKETS_NET_MGMT)
+  zephyr_sources(sockets_net_mgmt.c)
+  zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
+endif()
+
+if(CONFIG_SOCKS)
+  zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/lib/socks)
+endif()
+
+zephyr_sources_ifdef(CONFIG_NET_SOCKETPAIR socketpair.c)
+
+zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/Kconfig	(working copy)
@@ -0,0 +1,200 @@
+# BSD Sockets compatible API
+
+# Copyright (c) 2017 Linaro Limited.
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig NET_SOCKETS
+	bool "BSD Sockets compatible API"
+	help
+	  Provide BSD Sockets like API on top of native Zephyr networking API.
+
+if NET_SOCKETS
+
+config NET_SOCKETS_POSIX_NAMES
+	bool "Standard POSIX names for Sockets API"
+	depends on !POSIX_API
+	help
+	  By default, Sockets API function are prefixed with ``zsock_`` to avoid
+	  namespacing issues. If this option is enabled, they will be provided
+	  with standard POSIX names like socket(), recv(), and close(), to help
+	  with porting existing code. Note that close() may require a special
+	  attention, as in POSIX it closes any file descriptor, while with this
+	  option enabled, it will still apply only to sockets.
+
+config NET_SOCKETS_POLL_MAX
+	int "Max number of supported poll() entries"
+	default 3
+	help
+	  Maximum number of entries supported for poll() call.
+
+config NET_SOCKETS_CONNECT_TIMEOUT
+	int "Timeout value in milliseconds to CONNECT"
+	default 3000
+	range 0 60000
+	help
+	  This variable specifies time in milliseconds after connect()
+	  API call will timeout if we have not received SYN-ACK from
+	  peer.
+
+config NET_SOCKETS_DNS_TIMEOUT
+	int "Timeout value in milliseconds for DNS queries"
+	default 2000
+	range 1000 300000
+	depends on DNS_RESOLVER
+	help
+	  This variable specifies time in milliseconds after which DNS
+	  query is considered timeout. Minimum timeout is 1 second and
+	  maximum timeout is 5 min.
+
+config NET_SOCKETS_SOCKOPT_TLS
+	bool "Enable TCP TLS socket option support [EXPERIMENTAL]"
+	imply TLS_CREDENTIALS
+	select MBEDTLS if NET_NATIVE
+	help
+	  Enable TLS socket option support which automatically establishes
+	  a TLS connection to the remote host.
+
+config NET_SOCKETS_ENABLE_DTLS
+	bool "Enable DTLS socket support [EXPERIMENTAL]"
+	depends on NET_SOCKETS_SOCKOPT_TLS
+	select MBEDTLS_DTLS if NET_NATIVE
+	help
+	  Enable DTLS socket support. By default only TLS over TCP is supported.
+
+config NET_SOCKETS_DTLS_TIMEOUT
+	int "Timeout value in milliseconds for DTLS connection"
+	default 5000
+	depends on NET_SOCKETS_ENABLE_DTLS
+	help
+	  This variable specifies time in milliseconds after which DTLS
+	  connection is considered dead by TLS server and DTLS resources are
+	  freed. This is needed to prevent situation when DTLS client shuts down
+	  without closing connection gracefully, which can prevent other peers
+	  from connecting. Value of 0 indicates no timeout - resources will be
+	  freed only when connection is gracefully closed by peer sending TLS
+	  notification or socket is closed.
+
+config NET_SOCKETS_TLS_MAX_CONTEXTS
+	int "Maximum number of TLS/DTLS contexts"
+	default 1
+	depends on NET_SOCKETS_SOCKOPT_TLS
+	help
+	  "This variable specifies maximum number of TLS/DTLS contexts that can
+	   be allocated at the same time."
+
+config NET_SOCKETS_TLS_MAX_CREDENTIALS
+	int "Maximum number of TLS/DTLS credentials per socket"
+	default 4
+	depends on NET_SOCKETS_SOCKOPT_TLS
+	help
+	  This variable sets maximum number of TLS/DTLS credentials that can be
+	  used with a specific socket.
+
+config NET_SOCKETS_TLS_MAX_CIPHERSUITES
+	int "Maximum number of TLS/DTLS ciphersuites per socket"
+	default 4
+	depends on NET_SOCKETS_SOCKOPT_TLS
+	help
+	  This variable sets maximum number of TLS/DTLS ciphersuites that can
+	  be used with specific socket, if set explicitly by socket option.
+	  By default, all ciphersuites that are available in the system are
+	  available to the socket.
+
+config NET_SOCKETS_OFFLOAD
+	bool "Offload Socket APIs [EXPERIMENTAL]"
+	help
+	  Enables direct offloading of socket operations to dedicated TCP/IP
+	  hardware.
+	  This feature is intended to save resources by bypassing the Zephyr
+	  TCP/IP stack in the case where there is only one network interface
+	  required in the system, providing full BSD socket offload capability.
+	  As a result, it bypasses any potential IP routing that Zephyr might
+	  provide between multiple network interfaces.
+	  See NET_OFFLOAD for a more deeply integrated approach which offloads
+	  from the net_context() API within the Zephyr IP stack.
+
+config NET_SOCKETS_OFFLOAD_TLS
+	bool "Offload TLS socket calls to the offloaded sockets"
+	depends on NET_SOCKETS_OFFLOAD
+	default y
+	help
+	  If enabled, the offloading engine is expected to handle TLS/DTLS
+	  socket calls. Othwerwise, Zephyrs native TLS socket implementation
+	  will be used, and only TCP/UDP socket calls will be offloaded.
+
+config NET_SOCKETS_PACKET
+	bool "Enable packet socket support"
+	depends on NET_L2_ETHERNET
+	help
+	  This is an initial version of packet socket support (special type
+	  raw socket). Packets are passed to and from the device driver
+	  without any changes in the packet headers. It's API caller
+	  responsibility to provide all the headers (e.g L2, L3 and so on)
+	  while sending. While receiving, packets (including all the headers)
+	  will be feed to sockets as it as from the driver.
+
+config NET_SOCKETS_PACKET_DGRAM
+	bool "Enable packet socket SOCK_DGRAM support"
+	depends on NET_SOCKETS_PACKET
+	default y
+	help
+	  For AF_PACKET sockets with SOCK_DGRAM type, the L2 header
+	  is removed before the packet is passed to the user.  Packets sent
+	  through a SOCK_DGRAM packet socket get a suitable L2 header based
+	  on the information in the sockaddr_ll destination address before
+	  they are queued.
+
+config NET_SOCKETS_CAN
+	bool "Enable socket CAN support [EXPERIMENTAL]"
+	select NET_L2_CANBUS_RAW
+	help
+	  The value depends on your network needs.
+
+config NET_SOCKETS_CAN_RECEIVERS
+	int "How many simultaneous SocketCAN receivers are allowed"
+	default 1
+	depends on NET_SOCKETS_CAN
+	help
+	  The value tells how many sockets can receive data from same
+	  Socket-CAN interface.
+
+config NET_SOCKETPAIR
+	bool "Support for the socketpair syscall [EXPERIMENTAL]"
+	depends on HEAP_MEM_POOL_SIZE != 0
+	help
+	  Choose y here if you would like to use the socketpair(2)
+	  system call.
+
+config NET_SOCKETPAIR_BUFFER_SIZE
+	int "Size of the intermediate buffer, in bytes"
+	default 64
+	range 1 4096
+	depends on NET_SOCKETPAIR
+	help
+	  Buffer size for socketpair(2)
+
+config NET_SOCKETS_NET_MGMT
+	bool "Enable network management socket support [EXPERIMENTAL]"
+	depends on NET_MGMT_EVENT
+	select NET_MGMT_EVENT_INFO
+	help
+	  Select this if you want to use socket API to get network
+	  managements events to your application.
+
+config NET_SOCKETS_NET_MGMT_MAX_LISTENERS
+	int "Max number of sockets to listen"
+	default 1
+	depends on NET_SOCKETS_NET_MGMT
+	help
+	  This sets the maximum number of net_mgmt sockets that can
+	  be set by the socket interface. So if you have two separate
+	  sockets that are used for listening events, you need to set
+	  this to two.
+
+module = NET_SOCKETS
+module-dep = NET_LOG
+module-str = Log level for BSD sockets compatible API calls
+module-help = Enables logging for sockets code.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # NET_SOCKETS
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getaddrinfo.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getaddrinfo.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getaddrinfo.c	(working copy)
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* libc headers */
+#include <stdlib.h>
+#include <ctype.h>
+
+/* Zephyr headers */
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock_addr, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <net/socket.h>
+#include <net/socket_offload.h>
+#include <syscall_handler.h>
+
+#define AI_ARR_MAX	2
+
+#if defined(CONFIG_DNS_RESOLVER)
+
+/* Helper macros which take into account the fact that ai_family as passed
+ * into getaddrinfo() may take values AF_INET, AF_INET6, or AF_UNSPEC, where
+ * AF_UNSPEC means resolve both AF_INET and AF_INET6.
+ */
+#define RESOLVE_IPV4(ai_family) \
+	(IS_ENABLED(CONFIG_NET_IPV4) && (ai_family) != AF_INET6)
+#define RESOLVE_IPV6(ai_family) \
+	(IS_ENABLED(CONFIG_NET_IPV6) && (ai_family) != AF_INET)
+
+struct getaddrinfo_state {
+	const struct zsock_addrinfo *hints;
+	struct k_sem sem;
+	int status;
+	uint16_t idx;
+	uint16_t port;
+	struct zsock_addrinfo *ai_arr;
+};
+
+/* Initialize static fields of addrinfo structure. A macro to let it work
+ * with any sockaddr_* type.
+ */
+#define INIT_ADDRINFO(addrinfo, sockaddr) { \
+		(addrinfo)->ai_addr = &(addrinfo)->_ai_addr; \
+		(addrinfo)->ai_addrlen = sizeof(*sockaddr); \
+		(addrinfo)->ai_canonname = (addrinfo)->_ai_canonname; \
+		(addrinfo)->_ai_canonname[0] = '\0'; \
+		(addrinfo)->ai_next = NULL; \
+	}
+
+static void dns_resolve_cb(enum dns_resolve_status status,
+			   struct dns_addrinfo *info, void *user_data)
+{
+	struct getaddrinfo_state *state = user_data;
+	struct zsock_addrinfo *ai;
+	int socktype = SOCK_STREAM;
+	int proto;
+
+	NET_DBG("dns status: %d", status);
+
+	if (info == NULL) {
+		if (status == DNS_EAI_ALLDONE) {
+			status = 0;
+		}
+		state->status = status;
+		k_sem_give(&state->sem);
+		return;
+	}
+
+	if (state->idx >= AI_ARR_MAX) {
+		NET_DBG("getaddrinfo entries overflow");
+		return;
+	}
+
+	ai = &state->ai_arr[state->idx];
+	memcpy(&ai->_ai_addr, &info->ai_addr, info->ai_addrlen);
+	net_sin(&ai->_ai_addr)->sin_port = state->port;
+	ai->ai_addr = &ai->_ai_addr;
+	ai->ai_addrlen = info->ai_addrlen;
+	memcpy(&ai->_ai_canonname, &info->ai_canonname,
+	       sizeof(ai->_ai_canonname));
+	ai->ai_canonname = ai->_ai_canonname;
+	ai->ai_family = info->ai_family;
+
+	if (state->hints) {
+		if (state->hints->ai_socktype) {
+			socktype = state->hints->ai_socktype;
+		}
+	}
+
+	proto = IPPROTO_TCP;
+	if (socktype == SOCK_DGRAM) {
+		proto = IPPROTO_UDP;
+	}
+
+	ai->ai_socktype = socktype;
+	ai->ai_protocol = proto;
+
+	state->idx++;
+}
+
+static int exec_query(const char *host, int family,
+		      struct getaddrinfo_state *ai_state)
+{
+	enum dns_query_type qtype = DNS_QUERY_TYPE_A;
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
+		qtype = DNS_QUERY_TYPE_AAAA;
+	}
+
+	return dns_get_addr_info(host, qtype, NULL,
+				 dns_resolve_cb, ai_state,
+				 CONFIG_NET_SOCKETS_DNS_TIMEOUT);
+}
+
+static int getaddrinfo_null_host(int port, const struct zsock_addrinfo *hints,
+				struct zsock_addrinfo *res)
+{
+	if (hints && (hints->ai_flags & AI_PASSIVE)) {
+		struct sockaddr_in *addr =
+		    (struct sockaddr_in *)&res->_ai_addr;
+		addr->sin_addr.s_addr = INADDR_ANY;
+		addr->sin_port = htons(port);
+		addr->sin_family = AF_INET;
+		INIT_ADDRINFO(res, addr);
+		res->ai_family = AF_INET;
+		res->ai_socktype = SOCK_STREAM;
+		res->ai_protocol = IPPROTO_TCP;
+		return 0;
+	}
+
+	return DNS_EAI_FAIL;
+}
+
+int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
+				       const struct zsock_addrinfo *hints,
+				       struct zsock_addrinfo *res)
+{
+	int family = AF_UNSPEC;
+	int ai_flags = 0;
+	long int port = 0;
+	int st1 = DNS_EAI_ADDRFAMILY, st2 = DNS_EAI_ADDRFAMILY;
+	struct sockaddr *ai_addr;
+	int ret;
+	struct getaddrinfo_state ai_state;
+
+	if (hints) {
+		family = hints->ai_family;
+		ai_flags = hints->ai_flags;
+	}
+
+	if (service) {
+		port = strtol(service, NULL, 10);
+		if (port < 1 || port > 65535) {
+			return DNS_EAI_NONAME;
+		}
+	}
+
+	if (host == NULL) {
+		/* Per POSIX, both can't be NULL. */
+		if (service == NULL) {
+			errno = EINVAL;
+			return DNS_EAI_SYSTEM;
+		}
+
+		return getaddrinfo_null_host(port, hints, res);
+	}
+
+#define SIN_ADDR(ptr) (net_sin(ptr)->sin_addr)
+
+	/* Check for IPv4 numeric address. Start with a quick heuristic check,
+	 * of first char of the address, then do long validating inet_pton()
+	 * call if needed.
+	 */
+	if (RESOLVE_IPV4(family) &&
+	    isdigit((int)*host) &&
+	    zsock_inet_pton(AF_INET, host,
+			    &SIN_ADDR(&res->_ai_addr)) == 1) {
+		struct sockaddr_in *addr =
+			(struct sockaddr_in *)&res->_ai_addr;
+
+		addr->sin_port = htons(port);
+		addr->sin_family = AF_INET;
+		INIT_ADDRINFO(res, addr);
+		res->ai_family = AF_INET;
+		res->ai_socktype = SOCK_STREAM;
+		res->ai_protocol = IPPROTO_TCP;
+		return 0;
+	}
+
+	if (ai_flags & AI_NUMERICHOST) {
+		/* Asked to resolve host as numeric, but it wasn't possible
+		 * to do that.
+		 */
+		return DNS_EAI_FAIL;
+	}
+
+	ai_state.hints = hints;
+	ai_state.idx = 0U;
+	ai_state.port = htons(port);
+	ai_state.ai_arr = res;
+	k_sem_init(&ai_state.sem, 0, UINT_MAX);
+
+	/* Link entries in advance */
+	ai_state.ai_arr[0].ai_next = &ai_state.ai_arr[1];
+
+	/* If the family is AF_UNSPEC, then we query IPv4 address first */
+	ret = exec_query(host, family, &ai_state);
+	if (ret == 0) {
+		/* If the DNS query for reason fails so that the
+		 * dns_resolve_cb() would not be called, then we want the
+		 * semaphore to timeout so that we will not hang forever.
+		 * So make the sem timeout longer than the DNS timeout so that
+		 * we do not need to start to cancel any pending DNS queries.
+		 */
+		int ret = k_sem_take(&ai_state.sem,
+				     K_MSEC(CONFIG_NET_SOCKETS_DNS_TIMEOUT +
+					    100));
+		if (ret == -EAGAIN) {
+			return DNS_EAI_AGAIN;
+		}
+
+		st1 = ai_state.status;
+	} else {
+		/* If we are returned -EPFNOSUPPORT then that will indicate
+		 * wrong address family type queried. Check that and return
+		 * DNS_EAI_ADDRFAMILY and set errno to EINVAL.
+		 */
+		if (ret == -EPFNOSUPPORT) {
+			errno = EINVAL;
+			st1 = DNS_EAI_ADDRFAMILY;
+		} else {
+			errno = -ret;
+			st1 = DNS_EAI_SYSTEM;
+		}
+	}
+
+	/* If family is AF_UNSPEC, the IPv4 query has been already done
+	 * so we can do IPv6 query next if IPv6 is enabled in the config.
+	 */
+	if (family == AF_UNSPEC && IS_ENABLED(CONFIG_NET_IPV6)) {
+		ret = exec_query(host, AF_INET6, &ai_state);
+		if (ret == 0) {
+			int ret = k_sem_take(
+				&ai_state.sem,
+				K_MSEC(CONFIG_NET_SOCKETS_DNS_TIMEOUT + 100));
+			if (ret == -EAGAIN) {
+				return DNS_EAI_AGAIN;
+			}
+
+			st2 = ai_state.status;
+		} else {
+			errno = -ret;
+			st2 = DNS_EAI_SYSTEM;
+		}
+	}
+
+	if (ai_state.idx > 0) {
+		ai_addr = &ai_state.ai_arr[ai_state.idx - 1]._ai_addr;
+		net_sin(ai_addr)->sin_port = htons(port);
+	}
+
+	/* If both attempts failed, it's error */
+	if (st1 && st2) {
+		if (st1 != DNS_EAI_ADDRFAMILY) {
+			return st1;
+		}
+		return st2;
+	}
+
+	/* Mark entry as last */
+	ai_state.ai_arr[ai_state.idx - 1].ai_next = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_z_zsock_getaddrinfo_internal(const char *host,
+					const char *service,
+				       const struct zsock_addrinfo *hints,
+				       struct zsock_addrinfo *res)
+{
+	struct zsock_addrinfo hints_copy;
+	char *host_copy = NULL, *service_copy = NULL;
+	uint32_t ret;
+
+	if (hints) {
+		Z_OOPS(z_user_from_copy(&hints_copy, (void *)hints,
+					sizeof(hints_copy)));
+	}
+	Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(res, AI_ARR_MAX,
+					    sizeof(struct zsock_addrinfo)));
+
+	if (service) {
+		service_copy = z_user_string_alloc_copy((char *)service, 64);
+		if (!service_copy) {
+			ret = DNS_EAI_MEMORY;
+			goto out;
+		}
+	}
+
+	if (host) {
+		host_copy = z_user_string_alloc_copy((char *)host, 64);
+		if (!host_copy) {
+			ret = DNS_EAI_MEMORY;
+			goto out;
+		}
+	}
+
+	ret = z_impl_z_zsock_getaddrinfo_internal(host_copy, service_copy,
+						 hints ? &hints_copy : NULL,
+						 (struct zsock_addrinfo *)res);
+out:
+	k_free(service_copy);
+	k_free(host_copy);
+
+	return ret;
+}
+#include <syscalls/z_zsock_getaddrinfo_internal_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+#endif /* defined(CONFIG_DNS_RESOLVER) */
+
+int zsock_getaddrinfo(const char *host, const char *service,
+		      const struct zsock_addrinfo *hints,
+		      struct zsock_addrinfo **res)
+{
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_OFFLOAD)) {
+		return socket_offload_getaddrinfo(host, service, hints, res);
+	}
+
+#if defined(CONFIG_DNS_RESOLVER)
+	int ret;
+
+	*res = calloc(AI_ARR_MAX, sizeof(struct zsock_addrinfo));
+	if (!(*res)) {
+		return DNS_EAI_MEMORY;
+	}
+	ret = z_zsock_getaddrinfo_internal(host, service, hints, *res);
+	if (ret) {
+		free(*res);
+		*res = NULL;
+	}
+	return ret;
+#endif
+
+	return DNS_EAI_FAIL;
+}
+
+void zsock_freeaddrinfo(struct zsock_addrinfo *ai)
+{
+	if (IS_ENABLED(CONFIG_NET_SOCKETS_OFFLOAD)) {
+		return socket_offload_freeaddrinfo(ai);
+	}
+
+	free(ai);
+}
+
+#define ERR(e) case DNS_ ## e: return #e
+const char *zsock_gai_strerror(int errcode)
+{
+	switch (errcode) {
+	ERR(EAI_BADFLAGS);
+	ERR(EAI_NONAME);
+	ERR(EAI_AGAIN);
+	ERR(EAI_FAIL);
+	ERR(EAI_NODATA);
+	ERR(EAI_MEMORY);
+	ERR(EAI_SYSTEM);
+	ERR(EAI_SERVICE);
+
+	default:
+		return "EAI_UNKNOWN";
+	}
+}
+#undef ERR
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getnameinfo.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getnameinfo.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/getnameinfo.c	(working copy)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <net/socket.h>
+
+int zsock_getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
+		      char *host, socklen_t hostlen,
+		      char *serv, socklen_t servlen, int flags)
+{
+	/* Both sockaddr_in & _in6 have same offsets for family and address. */
+	struct sockaddr_in *a = (struct sockaddr_in *)addr;
+
+	if (host != NULL) {
+		void *res = zsock_inet_ntop(a->sin_family, &a->sin_addr,
+					    host, hostlen);
+
+		if (res == NULL) {
+			return DNS_EAI_SYSTEM;
+		}
+	}
+
+	if (serv != NULL) {
+		snprintk(serv, servlen, "%hu", ntohs(a->sin_port));
+	}
+
+	return 0;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socket_offload.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socket_offload.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socket_offload.c	(working copy)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 Linaro Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_socket_offload, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <net/socket_offload.h>
+#include <net/socket.h>
+
+#include "sockets_internal.h"
+
+const struct socket_dns_offload *dns_offload;
+
+void socket_offload_dns_register(const struct socket_dns_offload *ops)
+{
+	__ASSERT_NO_MSG(ops);
+	__ASSERT_NO_MSG(dns_offload == NULL);
+
+	dns_offload = ops;
+}
+
+int socket_offload_getaddrinfo(const char *node, const char *service,
+			       const struct zsock_addrinfo *hints,
+			       struct zsock_addrinfo **res)
+{
+	__ASSERT_NO_MSG(dns_offload);
+	__ASSERT_NO_MSG(dns_offload->getaddrinfo);
+
+	return dns_offload->getaddrinfo(node, service, hints, res);
+}
+
+void socket_offload_freeaddrinfo(struct zsock_addrinfo *res)
+{
+	__ASSERT_NO_MSG(dns_offload);
+	__ASSERT_NO_MSG(dns_offload->freeaddrinfo);
+
+	return dns_offload->freeaddrinfo(res);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socketpair.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socketpair.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/socketpair.c	(working copy)
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <fcntl.h>
+
+/* Zephyr headers */
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_spair, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <net/socket.h>
+#include <syscall_handler.h>
+#include <sys/__assert.h>
+#include <sys/fdtable.h>
+
+#include "sockets_internal.h"
+
+enum {
+	SPAIR_SIG_CANCEL, /**< operation has been canceled */
+	SPAIR_SIG_DATA,   /**< @ref spair.recv_q has been updated */
+};
+
+enum {
+	SPAIR_FLAG_NONBLOCK = (1 << 0), /**< socket is non-blocking */
+};
+
+#define SPAIR_FLAGS_DEFAULT 0
+
+/**
+ * Socketpair endpoint structure
+ *
+ * This structure represents one half of a socketpair (an 'endpoint').
+ *
+ * The implementation strives for compatibility with socketpair(2).
+ *
+ * Resources contained within this structure are said to be 'local', while
+ * reources contained within the other half of the socketpair (or other
+ * endpoint) are said to be 'remote'.
+ *
+ * Theory of operation:
+ * - each end of a socketpair owns a @a recv_q
+ * - since there is no write queue, data is either written or not
+ * - read and write operations may return partial transfers
+ * - read operations may block if the local @a recv_q is empty
+ * - write operations may block if the remote @a recv_q is full
+ * - each endpoint may be blocking or non-blocking
+ */
+__net_socket struct spair {
+	int remote; /**< the remote endpoint file descriptor */
+	uint32_t flags; /**< status and option bits */
+	struct k_sem sem; /**< semaphore for exclusive structure access */
+	struct k_pipe recv_q; /**< receive queue of local endpoint */
+	/** indicates write of local @a recv_q occurred */
+	struct k_poll_signal write_signal;
+	/** indicates read of local @a recv_q occurred */
+	struct k_poll_signal read_signal;
+	/** buffer for @a recv_q recv_q */
+	uint8_t buf[CONFIG_NET_SOCKETPAIR_BUFFER_SIZE];
+};
+
+/* forward declaration */
+static const struct socket_op_vtable spair_fd_op_vtable;
+
+#undef sock_is_nonblock
+/** Determine if a @ref spair is in non-blocking mode */
+static inline bool sock_is_nonblock(const struct spair *spair)
+{
+	return !!(spair->flags & SPAIR_FLAG_NONBLOCK);
+}
+
+/** Determine if a @ref spair is connected */
+static inline bool sock_is_connected(const struct spair *spair)
+{
+	const struct spair *remote = z_get_fd_obj(spair->remote,
+		(const struct fd_op_vtable *)&spair_fd_op_vtable, 0);
+
+	if (remote == NULL) {
+		return false;
+	}
+
+	return true;
+}
+
+#undef sock_is_eof
+/** Determine if a @ref spair has encountered end-of-file */
+static inline bool sock_is_eof(const struct spair *spair)
+{
+	return !sock_is_connected(spair);
+}
+
+/**
+ * Determine bytes available to write
+ *
+ * Specifically, this function calculates the number of bytes that may be
+ * written to a given @ref spair without blocking.
+ */
+static inline size_t spair_write_avail(struct spair *spair)
+{
+	struct spair *const remote = z_get_fd_obj(spair->remote,
+		(const struct fd_op_vtable *)&spair_fd_op_vtable, 0);
+
+	if (remote == NULL) {
+		return 0;
+	}
+
+	return k_pipe_write_avail(&remote->recv_q);
+}
+
+/**
+ * Determine bytes available to read
+ *
+ * Specifically, this function calculates the number of bytes that may be
+ * read from a given @ref spair without blocking.
+ */
+static inline size_t spair_read_avail(struct spair *spair)
+{
+	return k_pipe_read_avail(&spair->recv_q);
+}
+
+/** Swap two 32-bit integers */
+static inline void swap32(uint32_t *a, uint32_t *b)
+{
+	uint32_t c;
+
+	c = *b;
+	*b = *a;
+	*a = c;
+}
+
+/**
+ * Delete @param spair
+ *
+ * This function deletes one endpoint of a socketpair.
+ *
+ * Theory of operation:
+ * - we have a socketpair with two endpoints: A and B
+ * - we have two threads: T1 and T2
+ * - T1 operates on endpoint A
+ * - T2 operates on endpoint B
+ *
+ * There are two possible cases where a blocking operation must be notified
+ * when one endpoint is closed:
+ * -# T1 is blocked reading from A and T2 closes B
+ *    T1 waits on A's write signal. T2 triggers the remote
+ *    @ref spair.write_signal
+ * -# T1 is blocked writing to A and T2 closes B
+ *    T1 is waits on B's read signal. T2 triggers the local
+ *    @ref spair.read_signal.
+ *
+ * If the remote endpoint is already closed, the former operation does not
+ * take place. Otherwise, the @ref spair.remote of the local endpoint is
+ * set to -1.
+ *
+ * If no threads are blocking on A, then the signals have no effect.
+ *
+ * The memeory associated with the local endpoint is cleared and freed.
+ */
+static void spair_delete(struct spair *spair)
+{
+	int res;
+	struct spair *remote = NULL;
+	bool have_remote_sem = false;
+
+	if (spair == NULL) {
+		return;
+	}
+
+	if (spair->remote != -1) {
+		remote = z_get_fd_obj(spair->remote,
+			(const struct fd_op_vtable *)&spair_fd_op_vtable, 0);
+
+		if (remote != NULL) {
+			res = k_sem_take(&remote->sem, K_FOREVER);
+			if (res == 0) {
+				have_remote_sem = true;
+				remote->remote = -1;
+				res = k_poll_signal_raise(&remote->write_signal,
+					SPAIR_SIG_CANCEL);
+				__ASSERT(res == 0,
+					"k_poll_signal_raise() failed: %d",
+					res);
+			}
+		}
+	}
+
+	spair->remote = -1;
+
+	res = k_poll_signal_raise(&spair->read_signal, SPAIR_SIG_CANCEL);
+	__ASSERT(res == 0, "k_poll_signal_raise() failed: %d", res);
+
+	/* ensure no private information is released to the memory pool */
+	memset(spair, 0, sizeof(*spair));
+#ifdef CONFIG_USERSPACE
+	k_object_free(spair);
+#else
+	k_free(spair);
+#endif
+
+	if (remote != NULL && have_remote_sem) {
+		k_sem_give(&remote->sem);
+	}
+}
+
+/**
+ * Create a @ref spair (1/2 of a socketpair)
+ *
+ * The idea is to call this twice, but store the "local" side in the
+ * @ref spair.remote field initially.
+ *
+ * If both allocations are successful, then swap the @ref spair.remote
+ * fields in the two @ref spair instances.
+ */
+static struct spair *spair_new(void)
+{
+	struct spair *spair;
+
+#ifdef CONFIG_USERSPACE
+	struct z_object *zo = z_dynamic_object_create(sizeof(*spair));
+
+	if (zo == NULL) {
+		spair = NULL;
+	} else {
+		spair = zo->name;
+		zo->type = K_OBJ_NET_SOCKET;
+	}
+#else
+	spair = k_malloc(sizeof(*spair));
+#endif
+	if (spair == NULL) {
+		errno = ENOMEM;
+		goto out;
+	}
+	memset(spair, 0, sizeof(*spair));
+
+	/* initialize any non-zero default values */
+	spair->remote = -1;
+	spair->flags = SPAIR_FLAGS_DEFAULT;
+
+	k_sem_init(&spair->sem, 1, 1);
+	k_pipe_init(&spair->recv_q, spair->buf, sizeof(spair->buf));
+	k_poll_signal_init(&spair->write_signal);
+	k_poll_signal_init(&spair->read_signal);
+
+	spair->remote = z_reserve_fd();
+	if (spair->remote == -1) {
+		errno = ENFILE;
+		goto cleanup;
+	}
+
+	z_finalize_fd(spair->remote, spair,
+		      (const struct fd_op_vtable *)&spair_fd_op_vtable);
+
+	goto out;
+
+cleanup:
+	spair_delete(spair);
+	spair = NULL;
+
+out:
+	return spair;
+}
+
+int z_impl_zsock_socketpair(int family, int type, int proto, int *sv)
+{
+	int res;
+	size_t i;
+	struct spair *obj[2] = {};
+
+	if (family != AF_UNIX) {
+		errno = EAFNOSUPPORT;
+		res = -1;
+		goto errout;
+	}
+
+	if (type != SOCK_STREAM) {
+		errno = EPROTOTYPE;
+		res = -1;
+		goto errout;
+	}
+
+	if (proto != 0) {
+		errno = EPROTONOSUPPORT;
+		res = -1;
+		goto errout;
+	}
+
+	if (sv == NULL) {
+		/* not listed in normative spec, but mimics Linux behaviour */
+		errno = EFAULT;
+		res = -1;
+		goto errout;
+	}
+
+	for (i = 0; i < 2; ++i) {
+		obj[i] = spair_new();
+		if (!obj[i]) {
+			res = -1;
+			goto cleanup;
+		}
+	}
+
+	/* connect the two endpoints */
+	swap32(&obj[0]->remote, &obj[1]->remote);
+
+	for (i = 0; i < 2; ++i) {
+		sv[i] = obj[i]->remote;
+		k_sem_give(&obj[0]->sem);
+	}
+
+	return 0;
+
+cleanup:
+	for (i = 0; i < 2; ++i) {
+		spair_delete(obj[i]);
+	}
+
+errout:
+	return res;
+}
+
+#ifdef CONFIG_USERSPACE
+int z_vrfy_zsock_socketpair(int family, int type, int proto, int *sv)
+{
+	int ret;
+	int tmp[2];
+
+	if (!sv || Z_SYSCALL_MEMORY_WRITE(sv, sizeof(tmp)) != 0) {
+		/* not listed in normative spec, but mimics linux behaviour */
+		errno = EFAULT;
+		ret = -1;
+		goto out;
+	}
+
+	ret = z_impl_zsock_socketpair(family, type, proto, tmp);
+	if (ret == 0) {
+		Z_OOPS(z_user_to_copy(sv, tmp, sizeof(tmp)));
+	}
+
+out:
+	return ret;
+}
+
+#include <syscalls/zsock_socketpair_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+/**
+ * Write data to one end of a @ref spair
+ *
+ * Data written on one file descriptor of a socketpair can be read at the
+ * other end using common POSIX calls such as read(2) or recv(2).
+ *
+ * If the underlying file descriptor has the @ref O_NONBLOCK flag set then
+ * this function will return immediately. If no data was written on a
+ * non-blocking file descriptor, then -1 will be returned and @ref errno will
+ * be set to @ref EAGAIN.
+ *
+ * Blocking write operations occur when the @ref O_NONBLOCK flag is @em not
+ * set and there is insufficient space in the @em remote @ref spair.pipe.
+ *
+ * Such a blocking write will suspend execution of the current thread until
+ * one of two possible results is received on the @em remote
+ * @ref spair.read_signal:
+ *
+ * 1) @ref SPAIR_SIG_DATA - data has been read from the @em remote
+ *    @ref spair.pipe. Thus, allowing more data to be written.
+ *
+ * 2) @ref SPAIR_SIG_CANCEL - the @em remote socketpair endpoint was closed
+ *    Receipt of this result is analagous to SIGPIPE from POSIX
+ *    ("Write on a pipe with no one to read it."). In this case, the function
+ *    will return -1 and set @ref errno to @ref EPIPE.
+ *
+ * @param obj the address of an @ref spair object cast to `void *`
+ * @param buffer the buffer to write
+ * @param count the number of bytes to write from @p buffer
+ *
+ * @return on success, a number > 0 representing the number of bytes written
+ * @return -1 on error, with @ref errno set appropriately.
+ */
+static ssize_t spair_write(void *obj, const void *buffer, size_t count)
+{
+	int res;
+	int key;
+	size_t avail;
+	bool is_nonblock;
+	size_t bytes_written;
+	bool have_local_sem = false;
+	bool have_remote_sem = false;
+	bool will_block = false;
+	struct spair *const spair = (struct spair *)obj;
+	struct spair *remote = NULL;
+
+	if (obj == NULL || buffer == NULL || count == 0) {
+		errno = EINVAL;
+		res = -1;
+		goto out;
+	}
+
+	key = irq_lock();
+	is_nonblock = sock_is_nonblock(spair);
+	res = k_sem_take(&spair->sem, K_NO_WAIT);
+	irq_unlock(key);
+	if (res < 0) {
+		if (is_nonblock) {
+			errno = EAGAIN;
+			res = -1;
+			goto out;
+		}
+
+		res = k_sem_take(&spair->sem, K_FOREVER);
+		if (res < 0) {
+			errno = -res;
+			res = -1;
+			goto out;
+		}
+		is_nonblock = sock_is_nonblock(spair);
+	}
+
+	have_local_sem = true;
+
+	remote = z_get_fd_obj(spair->remote,
+		(const struct fd_op_vtable *)&spair_fd_op_vtable, 0);
+
+	if (remote == NULL) {
+		errno = EPIPE;
+		res = -1;
+		goto out;
+	}
+
+	res = k_sem_take(&remote->sem, K_NO_WAIT);
+	if (res < 0) {
+		if (is_nonblock) {
+			errno = EAGAIN;
+			res = -1;
+			goto out;
+		}
+		res = k_sem_take(&remote->sem, K_FOREVER);
+		if (res < 0) {
+			errno = -res;
+			res = -1;
+			goto out;
+		}
+	}
+
+	have_remote_sem = true;
+
+	avail = spair_write_avail(spair);
+
+	if (avail == 0) {
+		if (is_nonblock) {
+			errno = EAGAIN;
+			res = -1;
+			goto out;
+		}
+		will_block = true;
+	}
+
+	if (will_block) {
+
+		for (int signaled = false, result = -1; !signaled;
+			result = -1) {
+
+			struct k_poll_event events[] = {
+				K_POLL_EVENT_INITIALIZER(
+					K_POLL_TYPE_SIGNAL,
+					K_POLL_MODE_NOTIFY_ONLY,
+					&remote->read_signal),
+			};
+
+			k_sem_give(&remote->sem);
+			have_remote_sem = false;
+
+			res = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
+			if (res < 0) {
+				errno = -res;
+				res = -1;
+				goto out;
+			}
+
+			remote = z_get_fd_obj(spair->remote,
+				(const struct fd_op_vtable *)
+				&spair_fd_op_vtable, 0);
+
+			if (remote == NULL) {
+				errno = EPIPE;
+				res = -1;
+				goto out;
+			}
+
+			res = k_sem_take(&remote->sem, K_FOREVER);
+			if (res < 0) {
+				errno = -res;
+				res = -1;
+				goto out;
+			}
+
+			have_remote_sem = true;
+
+			k_poll_signal_check(&remote->read_signal, &signaled,
+					    &result);
+			if (!signaled) {
+				continue;
+			}
+
+			switch (result) {
+				case SPAIR_SIG_DATA: {
+					break;
+				}
+
+				case SPAIR_SIG_CANCEL: {
+					errno = EPIPE;
+					res = -1;
+					goto out;
+				}
+
+				default: {
+					__ASSERT(false,
+						"unrecognized result: %d",
+						result);
+					continue;
+				}
+			}
+
+			/* SPAIR_SIG_DATA was received */
+			break;
+		}
+	}
+
+	res = k_pipe_put(&remote->recv_q, (void *)buffer, count,
+			 &bytes_written, 1, K_NO_WAIT);
+	__ASSERT(res == 0, "k_pipe_put() failed: %d", res);
+
+	res = k_poll_signal_raise(&remote->write_signal, SPAIR_SIG_DATA);
+	__ASSERT(res == 0, "k_poll_signal_raise() failed: %d", res);
+
+	res = bytes_written;
+
+out:
+
+	if (remote != NULL && have_remote_sem) {
+		k_sem_give(&remote->sem);
+	}
+	if (spair != NULL && have_local_sem) {
+		k_sem_give(&spair->sem);
+	}
+
+	return res;
+}
+
+/**
+ * Read data from one end of a @ref spair
+ *
+ * Data written on one file descriptor of a socketpair (with e.g. write(2) or
+ * send(2)) can be read at the other end using common POSIX calls such as
+ * read(2) or recv(2).
+ *
+ * If the underlying file descriptor has the @ref O_NONBLOCK flag set then
+ * this function will return immediately. If no data was read from a
+ * non-blocking file descriptor, then -1 will be returned and @ref errno will
+ * be set to @ref EAGAIN.
+ *
+ * Blocking read operations occur when the @ref O_NONBLOCK flag is @em not set
+ * and there are no bytes to read in the @em local @ref spair.pipe.
+ *
+ * Such a blocking read will suspend execution of the current thread until
+ * one of two possible results is received on the @em local
+ * @ref spair.write_signal:
+ *
+ * -# @ref SPAIR_SIG_DATA - data has been written to the @em local
+ *    @ref spair.pipe. Thus, allowing more data to be read.
+ *
+ * -# @ref SPAIR_SIG_CANCEL - read of the the @em local @spair.pipe
+ *    must be cancelled for some reason (e.g. the file descriptor will be
+ *    closed imminently). In this case, the function will return -1 and set
+ *    @ref errno to @ref EINTR.
+ *
+ * @param obj the address of an @ref spair object cast to `void *`
+ * @param buffer the buffer in which to read
+ * @param count the number of bytes to read
+ *
+ * @return on success, a number > 0 representing the number of bytes written
+ * @return -1 on error, with @ref errno set appropriately.
+ */
+static ssize_t spair_read(void *obj, void *buffer, size_t count)
+{
+	int res;
+	int key;
+	bool is_connected;
+	size_t avail;
+	bool is_nonblock;
+	size_t bytes_read;
+	bool have_local_sem = false;
+	bool will_block = false;
+	struct spair *const spair = (struct spair *)obj;
+
+	if (obj == NULL || buffer == NULL || count == 0) {
+		errno = EINVAL;
+		res = -1;
+		goto out;
+	}
+
+	key = irq_lock();
+	is_nonblock = sock_is_nonblock(spair);
+	res = k_sem_take(&spair->sem, K_NO_WAIT);
+	irq_unlock(key);
+	if (res < 0) {
+		if (is_nonblock) {
+			errno = EAGAIN;
+			res = -1;
+			goto out;
+		}
+
+		res = k_sem_take(&spair->sem, K_FOREVER);
+		if (res < 0) {
+			errno = -res;
+			res = -1;
+			goto out;
+		}
+		is_nonblock = sock_is_nonblock(spair);
+	}
+
+	have_local_sem = true;
+
+	is_connected = sock_is_connected(spair);
+	avail = spair_read_avail(spair);
+
+	if (avail == 0) {
+		if (!is_connected) {
+			/* signal EOF */
+			res = 0;
+			goto out;
+		}
+
+		if (is_nonblock) {
+			errno = EAGAIN;
+			res = -1;
+			goto out;
+		}
+
+		will_block = true;
+	}
+
+	if (will_block) {
+
+		for (int signaled = false, result = -1; !signaled;
+			result = -1) {
+
+			struct k_poll_event events[] = {
+				K_POLL_EVENT_INITIALIZER(
+					K_POLL_TYPE_SIGNAL,
+					K_POLL_MODE_NOTIFY_ONLY,
+					&spair->write_signal
+				),
+			};
+
+			k_sem_give(&spair->sem);
+			have_local_sem = false;
+
+			res = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
+			__ASSERT(res == 0, "k_poll() failed: %d", res);
+
+			res = k_sem_take(&spair->sem, K_FOREVER);
+			__ASSERT(res == 0, "failed to take local sem: %d", res);
+
+			have_local_sem = true;
+
+			k_poll_signal_check(&spair->write_signal, &signaled,
+					    &result);
+			if (!signaled) {
+				continue;
+			}
+
+			switch (result) {
+				case SPAIR_SIG_DATA: {
+					break;
+				}
+
+				case SPAIR_SIG_CANCEL: {
+					errno = EPIPE;
+					res = -1;
+					goto out;
+				}
+
+				default: {
+					__ASSERT(false,
+						"unrecognized result: %d",
+						result);
+					continue;
+				}
+			}
+
+			/* SPAIR_SIG_DATA was received */
+			break;
+		}
+	}
+
+	res = k_pipe_get(&spair->recv_q, (void *)buffer, count, &bytes_read,
+			 1, K_NO_WAIT);
+	__ASSERT(res == 0, "k_pipe_get() failed: %d", res);
+
+	if (is_connected) {
+		res = k_poll_signal_raise(&spair->read_signal, SPAIR_SIG_DATA);
+		__ASSERT(res == 0, "k_poll_signal_raise() failed: %d", res);
+	}
+
+	res = bytes_read;
+
+out:
+
+	if (spair != NULL && have_local_sem) {
+		k_sem_give(&spair->sem);
+	}
+
+	return res;
+}
+
+static int zsock_poll_prepare_ctx(struct spair *const spair,
+				  struct zsock_pollfd *const pfd,
+				  struct k_poll_event **pev,
+				  struct k_poll_event *pev_end)
+{
+	int res;
+
+	struct spair *remote = NULL;
+	bool have_remote_sem = false;
+
+	if (pfd->events & ZSOCK_POLLIN) {
+
+		/* Tell poll() to short-circuit wait */
+		if (sock_is_eof(spair)) {
+			res = -EALREADY;
+			goto out;
+		}
+
+		if (*pev == pev_end) {
+			res = -ENOMEM;
+			goto out;
+		}
+
+		/* Wait until data has been written to the local end */
+		(*pev)->obj = &spair->write_signal;
+	}
+
+	if (pfd->events & ZSOCK_POLLOUT) {
+
+		/* Tell poll() to short-circuit wait */
+		if (!sock_is_connected(spair)) {
+			res = -EALREADY;
+			goto out;
+		}
+
+		if (*pev == pev_end) {
+			res = -ENOMEM;
+			goto out;
+		}
+
+		remote = z_get_fd_obj(spair->remote,
+			(const struct fd_op_vtable *)
+			&spair_fd_op_vtable, 0);
+
+		__ASSERT(remote != NULL, "remote is NULL");
+
+		res = k_sem_take(&remote->sem, K_FOREVER);
+		if (res < 0) {
+			goto out;
+		}
+
+		have_remote_sem = true;
+
+		/* Wait until data has been read from the remote end */
+		(*pev)->obj = &remote->read_signal;
+	}
+
+	(*pev)->type = K_POLL_TYPE_SIGNAL;
+	(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
+	(*pev)->state = K_POLL_STATE_NOT_READY;
+	k_poll_signal_reset((*pev)->obj);
+
+	(*pev)++;
+
+	res = 0;
+
+out:
+
+	if (remote != NULL && have_remote_sem) {
+		k_sem_give(&remote->sem);
+	}
+
+	return res;
+}
+
+static int zsock_poll_update_ctx(struct spair *const spair,
+				 struct zsock_pollfd *const pfd,
+				 struct k_poll_event **pev)
+{
+	int res;
+	int signaled;
+	int result;
+	struct spair *remote = NULL;
+	bool have_remote_sem = false;
+
+	if (pfd->events & ZSOCK_POLLOUT) {
+		if (!sock_is_connected(spair)) {
+			pfd->revents |= ZSOCK_POLLHUP;
+			goto pollout_done;
+		}
+
+		remote = z_get_fd_obj(spair->remote,
+			(const struct fd_op_vtable *) &spair_fd_op_vtable, 0);
+
+		__ASSERT(remote != NULL, "remote is NULL");
+
+		res = k_sem_take(&remote->sem, K_FOREVER);
+		if (res < 0) {
+			/* if other end is deleted, this might occur */
+			goto pollout_done;
+		}
+
+		have_remote_sem = true;
+
+		if (spair_write_avail(spair) > 0) {
+			pfd->revents |= ZSOCK_POLLOUT;
+			goto pollout_done;
+		}
+
+		/* check to see if op was canceled */
+		signaled = false;
+		k_poll_signal_check(&remote->read_signal, &signaled, &result);
+		if (signaled) {
+			/* Cannot be SPAIR_SIG_DATA, because
+			 * spair_write_avail() would have
+			 * returned 0
+			 */
+			__ASSERT(result == SPAIR_SIG_CANCEL,
+				"invalid result %d", result);
+			pfd->revents |= ZSOCK_POLLHUP;
+		}
+	}
+
+pollout_done:
+
+	if (pfd->events & ZSOCK_POLLIN) {
+		if (sock_is_eof(spair)) {
+			pfd->revents |= ZSOCK_POLLIN;
+			goto pollin_done;
+		}
+
+		if (spair_read_avail(spair) > 0) {
+			pfd->revents |= ZSOCK_POLLIN;
+			goto pollin_done;
+		}
+
+		/* check to see if op was canceled */
+		signaled = false;
+		k_poll_signal_check(&spair->write_signal, &signaled, &result);
+		if (signaled) {
+			/* Cannot be SPAIR_SIG_DATA, because
+			 * spair_read_avail() would have
+			 * returned 0
+			 */
+			__ASSERT(result == SPAIR_SIG_CANCEL,
+					 "invalid result %d", result);
+			pfd->revents |= ZSOCK_POLLIN;
+		}
+	}
+
+pollin_done:
+	res = 0;
+
+	(*pev)++;
+
+	if (remote != NULL && have_remote_sem) {
+		k_sem_give(&remote->sem);
+	}
+
+	return res;
+}
+
+static int spair_ioctl(void *obj, unsigned int request, va_list args)
+{
+	int res;
+	struct zsock_pollfd *pfd;
+	struct k_poll_event **pev;
+	struct k_poll_event *pev_end;
+	int flags = 0;
+	bool have_local_sem = false;
+	struct spair *const spair = (struct spair *)obj;
+
+	if (spair == NULL) {
+		errno = EINVAL;
+		res = -1;
+		goto out;
+	}
+
+	/* The local sem is always taken in this function. If a subsequent
+	 * function call requires the remote sem, it must acquire and free the
+	 * remote sem.
+	 */
+	res = k_sem_take(&spair->sem, K_FOREVER);
+	__ASSERT(res == 0, "failed to take local sem: %d", res);
+
+	have_local_sem = true;
+
+	switch (request) {
+		case F_GETFL: {
+			if (sock_is_nonblock(spair)) {
+				flags |= O_NONBLOCK;
+			}
+
+			res = flags;
+			goto out;
+		}
+
+		case F_SETFL: {
+			flags = va_arg(args, int);
+
+			if (flags & O_NONBLOCK) {
+				spair->flags |= SPAIR_FLAG_NONBLOCK;
+			} else {
+				spair->flags &= ~SPAIR_FLAG_NONBLOCK;
+			}
+
+			res = 0;
+			goto out;
+		}
+
+		case ZFD_IOCTL_POLL_PREPARE: {
+			pfd = va_arg(args, struct zsock_pollfd *);
+			pev = va_arg(args, struct k_poll_event **);
+			pev_end = va_arg(args, struct k_poll_event *);
+
+			res = zsock_poll_prepare_ctx(obj, pfd, pev, pev_end);
+			goto out;
+		}
+
+		case ZFD_IOCTL_POLL_UPDATE: {
+			pfd = va_arg(args, struct zsock_pollfd *);
+			pev = va_arg(args, struct k_poll_event **);
+
+			res = zsock_poll_update_ctx(obj, pfd, pev);
+			goto out;
+		}
+
+		default: {
+			errno = EOPNOTSUPP;
+			res = -1;
+			goto out;
+		}
+	}
+
+out:
+	if (spair != NULL && have_local_sem) {
+		k_sem_give(&spair->sem);
+	}
+
+	return res;
+}
+
+static int spair_bind(void *obj, const struct sockaddr *addr,
+		      socklen_t addrlen)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(addr);
+	ARG_UNUSED(addrlen);
+
+	errno = EISCONN;
+	return -1;
+}
+
+static int spair_connect(void *obj, const struct sockaddr *addr,
+			 socklen_t addrlen)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(addr);
+	ARG_UNUSED(addrlen);
+
+	errno = EISCONN;
+	return -1;
+}
+
+static int spair_listen(void *obj, int backlog)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(backlog);
+
+	errno = EINVAL;
+	return -1;
+}
+
+static int spair_accept(void *obj, struct sockaddr *addr,
+			socklen_t *addrlen)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(addr);
+	ARG_UNUSED(addrlen);
+
+	errno = EOPNOTSUPP;
+	return -1;
+}
+
+static ssize_t spair_sendto(void *obj, const void *buf, size_t len,
+			    int flags, const struct sockaddr *dest_addr,
+				 socklen_t addrlen)
+{
+	ARG_UNUSED(flags);
+	ARG_UNUSED(dest_addr);
+	ARG_UNUSED(addrlen);
+
+	return spair_write(obj, buf, len);
+}
+
+static ssize_t spair_sendmsg(void *obj, const struct msghdr *msg,
+			     int flags)
+{
+	ARG_UNUSED(flags);
+
+	int res;
+	size_t len = 0;
+	bool is_connected;
+	size_t avail;
+	bool is_nonblock;
+	struct spair *const spair = (struct spair *)obj;
+
+	if (spair == NULL || msg == NULL) {
+		errno = EINVAL;
+		res = -1;
+		goto out;
+	}
+
+	is_connected = sock_is_connected(spair);
+	avail = is_connected ? spair_write_avail(spair) : 0;
+	is_nonblock = sock_is_nonblock(spair);
+
+	for (size_t i = 0; i < msg->msg_iovlen; ++i) {
+		/* check & msg->msg_iov[i]? */
+		/* check & msg->msg_iov[i].iov_base? */
+		len += msg->msg_iov[i].iov_len;
+	}
+
+	if (!is_connected) {
+		errno = EPIPE;
+		res = -1;
+		goto out;
+	}
+
+	if (len == 0) {
+		res = 0;
+		goto out;
+	}
+
+	if (len > avail && is_nonblock) {
+		errno = EMSGSIZE;
+		res = -1;
+		goto out;
+	}
+
+	for (size_t i = 0; i < msg->msg_iovlen; ++i) {
+		res = spair_write(spair, msg->msg_iov[i].iov_base,
+			msg->msg_iov[i].iov_len);
+		if (res == -1) {
+			goto out;
+		}
+	}
+
+	res = len;
+
+out:
+	return res;
+}
+
+static ssize_t spair_recvfrom(void *obj, void *buf, size_t max_len,
+			      int flags, struct sockaddr *src_addr,
+				   socklen_t *addrlen)
+{
+	(void)flags;
+	(void)src_addr;
+	(void)addrlen;
+
+	if (addrlen != NULL) {
+		/* Protocol (PF_UNIX) does not support addressing with connected
+		 * sockets and, therefore, it is unspecified behaviour to modify
+		 * src_addr. However, it would be ambiguous to leave addrlen
+		 * untouched if the user expects it to be updated. It is not
+		 * mentioned that modifying addrlen is unspecified. Therefore
+		 * we choose to eliminate ambiguity.
+		 *
+		 * Setting it to zero mimics Linux's behaviour.
+		 */
+		*addrlen = 0;
+	}
+
+	return spair_read(obj, buf, max_len);
+}
+
+static int spair_getsockopt(void *obj, int level, int optname,
+			    void *optval, socklen_t *optlen)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(level);
+	ARG_UNUSED(optname);
+	ARG_UNUSED(optval);
+	ARG_UNUSED(optlen);
+
+	errno = ENOPROTOOPT;
+	return -1;
+}
+
+static int spair_setsockopt(void *obj, int level, int optname,
+			    const void *optval, socklen_t optlen)
+{
+	ARG_UNUSED(obj);
+	ARG_UNUSED(level);
+	ARG_UNUSED(optname);
+	ARG_UNUSED(optval);
+	ARG_UNUSED(optlen);
+
+	errno = ENOPROTOOPT;
+	return -1;
+}
+
+static int spair_close(void *obj)
+{
+	struct spair *const spair = (struct spair *)obj;
+	int res;
+
+	res = k_sem_take(&spair->sem, K_FOREVER);
+	__ASSERT(res == 0, "failed to take local sem: %d", res);
+
+	/* disconnect the remote endpoint */
+	spair_delete(spair);
+
+	/* Note that the semaphore released already so need to do it here */
+
+	return 0;
+}
+
+static const struct socket_op_vtable spair_fd_op_vtable = {
+	.fd_vtable = {
+		.read = spair_read,
+		.write = spair_write,
+		.close = spair_close,
+		.ioctl = spair_ioctl,
+	},
+	.bind = spair_bind,
+	.connect = spair_connect,
+	.listen = spair_listen,
+	.accept = spair_accept,
+	.sendto = spair_sendto,
+	.sendmsg = spair_sendmsg,
+	.recvfrom = spair_recvfrom,
+	.getsockopt = spair_getsockopt,
+	.setsockopt = spair_setsockopt,
+};
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets.c	(working copy)
@@ -0,0 +1,1912 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* libc headers */
+#include <fcntl.h>
+
+/* Zephyr headers */
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <net/net_context.h>
+#include <net/net_pkt.h>
+#include <net/socket.h>
+#include <syscall_handler.h>
+#include <sys/fdtable.h>
+#include <sys/math_extras.h>
+
+#if defined(CONFIG_SOCKS)
+#include "socks.h"
+#endif
+
+#include "../../ip/net_stats.h"
+
+#include "sockets_internal.h"
+
+#define SET_ERRNO(x) \
+	{ int _err = x; if (_err < 0) { errno = -_err; return -1; } }
+
+#define VTABLE_CALL(fn, sock, ...) \
+	do { \
+		const struct socket_op_vtable *vtable; \
+		void *ctx = get_sock_vtable(sock, &vtable); \
+		if (ctx == NULL || vtable->fn == NULL) { \
+			errno = EBADF; \
+			return -1; \
+		} \
+		return vtable->fn(ctx, __VA_ARGS__); \
+	} while (0)
+
+const struct socket_op_vtable sock_fd_op_vtable;
+
+static inline void *get_sock_vtable(
+			int sock, const struct socket_op_vtable **vtable)
+{
+	void *ctx;
+
+	ctx = z_get_fd_obj_and_vtable(sock,
+				      (const struct fd_op_vtable **)vtable);
+
+#ifdef CONFIG_USERSPACE
+	if (ctx != NULL && z_is_in_user_syscall()) {
+		struct z_object *zo;
+		int ret;
+
+		zo = z_object_find(ctx);
+		ret = z_object_validate(zo, K_OBJ_NET_SOCKET, _OBJ_INIT_TRUE);
+
+		if (ret != 0) {
+			z_dump_object_error(ret, ctx, zo, K_OBJ_NET_SOCKET);
+			/* Invalidate the context, the caller doesn't have
+			 * sufficient permission or there was some other
+			 * problem with the net socket object
+			 */
+			ctx = NULL;
+		}
+	}
+#endif /* CONFIG_USERSPACE */
+
+	if (ctx == NULL) {
+		NET_ERR("invalid access on sock %d by thread %p", sock,
+			_current);
+	}
+
+	return ctx;
+}
+
+void *z_impl_zsock_get_context_object(int sock)
+{
+	const struct socket_op_vtable *ignored;
+
+	return get_sock_vtable(sock, &ignored);
+}
+
+#ifdef CONFIG_USERSPACE
+void *z_vrfy_zsock_get_context_object(int sock)
+{
+	/* All checking done in implementation */
+	return z_impl_zsock_get_context_object(sock);
+}
+
+#include <syscalls/zsock_get_context_object_mrsh.c>
+#endif
+
+static void zsock_received_cb(struct net_context *ctx,
+			      struct net_pkt *pkt,
+			      union net_ip_header *ip_hdr,
+			      union net_proto_header *proto_hdr,
+			      int status,
+			      void *user_data);
+
+static inline int k_fifo_wait_non_empty(struct k_fifo *fifo,
+					k_timeout_t timeout)
+{
+	struct k_poll_event events[] = {
+		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+					 K_POLL_MODE_NOTIFY_ONLY, fifo),
+	};
+
+	return k_poll(events, ARRAY_SIZE(events), timeout);
+}
+
+static void zsock_flush_queue(struct net_context *ctx)
+{
+	bool is_listen = net_context_get_state(ctx) == NET_CONTEXT_LISTENING;
+	void *p;
+
+	/* recv_q and accept_q are shared via a union */
+	while ((p = k_fifo_get(&ctx->recv_q, K_NO_WAIT)) != NULL) {
+		if (is_listen) {
+			NET_DBG("discarding ctx %p", p);
+			net_context_put(p);
+		} else {
+			NET_DBG("discarding pkt %p", p);
+			net_pkt_unref(p);
+		}
+	}
+
+	/* Some threads might be waiting on recv, cancel the wait */
+	k_fifo_cancel_wait(&ctx->recv_q);
+}
+
+int zsock_socket_internal(int family, int type, int proto)
+{
+	int fd = z_reserve_fd();
+	struct net_context *ctx;
+	int res;
+
+	if (fd < 0) {
+		return -1;
+	}
+
+	if (proto == 0) {
+		if (family == AF_INET || family == AF_INET6) {
+			if (type == SOCK_DGRAM) {
+				proto = IPPROTO_UDP;
+			} else if (type == SOCK_STREAM) {
+				proto = IPPROTO_TCP;
+			}
+		}
+	}
+
+	res = net_context_get(family, type, proto, &ctx);
+	if (res < 0) {
+		z_free_fd(fd);
+		errno = -res;
+		return -1;
+	}
+
+	/* Initialize user_data, all other calls will preserve it */
+	ctx->user_data = NULL;
+
+	/* The socket flags are stored here */
+	ctx->socket_data = NULL;
+
+	/* recv_q and accept_q are in union */
+	k_fifo_init(&ctx->recv_q);
+
+	/* TCP context is effectively owned by both application
+	 * and the stack: stack may detect that peer closed/aborted
+	 * connection, but it must not dispose of the context behind
+	 * the application back. Likewise, when application "closes"
+	 * context, it's not disposed of immediately - there's yet
+	 * closing handshake for stack to perform.
+	 */
+	if (proto == IPPROTO_TCP) {
+		net_context_ref(ctx);
+	}
+
+	z_finalize_fd(fd, ctx, (const struct fd_op_vtable *)&sock_fd_op_vtable);
+
+	NET_DBG("socket: ctx=%p, fd=%d", ctx, fd);
+
+	return fd;
+}
+
+int z_impl_zsock_socket(int family, int type, int proto)
+{
+	Z_STRUCT_SECTION_FOREACH(net_socket_register, sock_family) {
+		if (sock_family->family != family &&
+		    sock_family->family != AF_UNSPEC) {
+			continue;
+		}
+
+		NET_ASSERT(sock_family->is_supported);
+
+		if (!sock_family->is_supported(family, type, proto)) {
+			continue;
+		}
+
+		return sock_family->handler(family, type, proto);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_NATIVE)) {
+		return zsock_socket_internal(family, type, proto);
+	}
+
+	errno = EAFNOSUPPORT;
+	return -1;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_socket(int family, int type, int proto)
+{
+	/* implementation call to net_context_get() should do all necessary
+	 * checking
+	 */
+	return z_impl_zsock_socket(family, type, proto);
+}
+#include <syscalls/zsock_socket_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_close_ctx(struct net_context *ctx)
+{
+	/* Reset callbacks to avoid any race conditions while
+	 * flushing queues. No need to check return values here,
+	 * as these are fail-free operations and we're closing
+	 * socket anyway.
+	 */
+	if (net_context_get_state(ctx) == NET_CONTEXT_LISTENING) {
+		(void)net_context_accept(ctx, NULL, K_NO_WAIT, NULL);
+	} else {
+		(void)net_context_recv(ctx, NULL, K_NO_WAIT, NULL);
+	}
+
+	zsock_flush_queue(ctx);
+
+	SET_ERRNO(net_context_put(ctx));
+
+	return 0;
+}
+
+int z_impl_zsock_close(int sock)
+{
+	const struct socket_op_vtable *vtable;
+	void *ctx = get_sock_vtable(sock, &vtable);
+	int ret;
+
+	if (ctx == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	NET_DBG("close: ctx=%p, fd=%d", ctx, sock);
+
+	ret = vtable->fd_vtable.close(ctx);
+
+	z_free_fd(sock);
+
+	return ret;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_close(int sock)
+{
+	return z_impl_zsock_close(sock);
+}
+#include <syscalls/zsock_close_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int z_impl_zsock_shutdown(int sock, int how)
+{
+	/* shutdown() is described by POSIX as just disabling recv() and/or
+	 * send() operations on socket. Of course, real-world software mostly
+	 * calls it for side effects. We treat it as null operation so far.
+	 */
+	ARG_UNUSED(sock);
+	ARG_UNUSED(how);
+
+	LOG_WRN("shutdown() not implemented");
+
+	return 0;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_shutdown(int sock, int how)
+{
+	return z_impl_zsock_shutdown(sock, how);
+}
+#include <syscalls/zsock_shutdown_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static void zsock_accepted_cb(struct net_context *new_ctx,
+			      struct sockaddr *addr, socklen_t addrlen,
+			      int status, void *user_data) {
+	struct net_context *parent = user_data;
+
+	NET_DBG("parent=%p, ctx=%p, st=%d", parent, new_ctx, status);
+
+	if (status == 0) {
+		/* This just installs a callback, so cannot fail. */
+		(void)net_context_recv(new_ctx, zsock_received_cb, K_NO_WAIT,
+				       NULL);
+		k_fifo_init(&new_ctx->recv_q);
+
+		k_fifo_put(&parent->accept_q, new_ctx);
+	}
+}
+
+static void zsock_received_cb(struct net_context *ctx,
+			      struct net_pkt *pkt,
+			      union net_ip_header *ip_hdr,
+			      union net_proto_header *proto_hdr,
+			      int status,
+			      void *user_data)
+{
+	NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
+		user_data);
+
+	/* if pkt is NULL, EOF */
+	if (!pkt) {
+		struct net_pkt *last_pkt = k_fifo_peek_tail(&ctx->recv_q);
+
+		if (!last_pkt) {
+			/* If there're no packets in the queue, recv() may
+			 * be blocked waiting on it to become non-empty,
+			 * so cancel that wait.
+			 */
+			sock_set_eof(ctx);
+			k_fifo_cancel_wait(&ctx->recv_q);
+			NET_DBG("Marked socket %p as peer-closed", ctx);
+		} else {
+			net_pkt_set_eof(last_pkt, true);
+			NET_DBG("Set EOF flag on pkt %p", last_pkt);
+		}
+		return;
+	}
+
+	/* Normal packet */
+	net_pkt_set_eof(pkt, false);
+
+	if (net_context_get_type(ctx) == SOCK_STREAM) {
+		net_context_update_recv_wnd(ctx, -net_pkt_remaining_data(pkt));
+	}
+
+	net_pkt_set_rx_stats_tick(pkt, k_cycle_get_32());
+
+	k_fifo_put(&ctx->recv_q, pkt);
+}
+
+int zsock_bind_ctx(struct net_context *ctx, const struct sockaddr *addr,
+		   socklen_t addrlen)
+{
+	SET_ERRNO(net_context_bind(ctx, addr, addrlen));
+	/* For DGRAM socket, we expect to receive packets after call to
+	 * bind(), but for STREAM socket, next expected operation is
+	 * listen(), which doesn't work if recv callback is set.
+	 */
+	if (net_context_get_type(ctx) == SOCK_DGRAM) {
+		SET_ERRNO(net_context_recv(ctx, zsock_received_cb, K_NO_WAIT,
+					   ctx->user_data));
+	}
+
+	return 0;
+}
+
+int z_impl_zsock_bind(int sock, const struct sockaddr *addr, socklen_t addrlen)
+{
+	VTABLE_CALL(bind, sock, addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_bind(int sock, const struct sockaddr *addr,
+				    socklen_t addrlen)
+{
+	struct sockaddr_storage dest_addr_copy;
+
+	Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy)));
+	Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)addr, addrlen));
+
+	return z_impl_zsock_bind(sock, (struct sockaddr *)&dest_addr_copy,
+				addrlen);
+}
+#include <syscalls/zsock_bind_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_connect_ctx(struct net_context *ctx, const struct sockaddr *addr,
+		      socklen_t addrlen)
+{
+#if defined(CONFIG_SOCKS)
+	if (net_context_is_proxy_enabled(ctx)) {
+		SET_ERRNO(net_socks5_connect(ctx, addr, addrlen));
+		SET_ERRNO(net_context_recv(ctx, zsock_received_cb,
+					   K_NO_WAIT, ctx->user_data));
+		return 0;
+	}
+#endif
+	SET_ERRNO(net_context_connect(ctx, addr, addrlen, NULL,
+			      K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
+			      NULL));
+	SET_ERRNO(net_context_recv(ctx, zsock_received_cb, K_NO_WAIT,
+				   ctx->user_data));
+
+	return 0;
+}
+
+int z_impl_zsock_connect(int sock, const struct sockaddr *addr,
+			socklen_t addrlen)
+{
+	VTABLE_CALL(connect, sock, addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+int z_vrfy_zsock_connect(int sock, const struct sockaddr *addr,
+			socklen_t addrlen)
+{
+	struct sockaddr_storage dest_addr_copy;
+
+	Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy)));
+	Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)addr, addrlen));
+
+	return z_impl_zsock_connect(sock, (struct sockaddr *)&dest_addr_copy,
+				   addrlen);
+}
+#include <syscalls/zsock_connect_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_listen_ctx(struct net_context *ctx, int backlog)
+{
+	SET_ERRNO(net_context_listen(ctx, backlog));
+	SET_ERRNO(net_context_accept(ctx, zsock_accepted_cb, K_NO_WAIT, ctx));
+
+	return 0;
+}
+
+int z_impl_zsock_listen(int sock, int backlog)
+{
+	VTABLE_CALL(listen, sock, backlog);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_listen(int sock, int backlog)
+{
+	return z_impl_zsock_listen(sock, backlog);
+}
+#include <syscalls/zsock_listen_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_accept_ctx(struct net_context *parent, struct sockaddr *addr,
+		     socklen_t *addrlen)
+{
+	k_timeout_t timeout = K_FOREVER;
+	struct net_context *ctx;
+	struct net_pkt *last_pkt;
+	int fd;
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		return -1;
+	}
+
+	if (sock_is_nonblock(parent)) {
+		timeout = K_NO_WAIT;
+	}
+
+	ctx = k_fifo_get(&parent->accept_q, timeout);
+	if (ctx == NULL) {
+		z_free_fd(fd);
+		if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
+			/* For non-blocking sockets return EAGAIN because it
+			 * just means the fifo is empty at this time
+			 */
+			errno = EAGAIN;
+		} else {
+			/* For blocking sockets return EINVAL because it means
+			 * the socket was closed while we were waiting for
+			 * connections. This is the same error code returned
+			 * under Linux when calling shutdown on a blocked accept
+			 * call
+			 */
+			errno = EINVAL;
+		}
+
+		return -1;
+	}
+
+	/* Check if the connection is already disconnected */
+	last_pkt = k_fifo_peek_tail(&ctx->recv_q);
+	if (last_pkt) {
+		if (net_pkt_eof(last_pkt)) {
+			sock_set_eof(ctx);
+			z_free_fd(fd);
+			errno = ECONNABORTED;
+			return -1;
+		}
+	}
+
+	if (net_context_is_closing(ctx)) {
+		errno = ECONNABORTED;
+		z_free_fd(fd);
+		return -1;
+	}
+
+	net_context_set_accepting(ctx, false);
+
+
+	if (addr != NULL && addrlen != NULL) {
+		int len = MIN(*addrlen, sizeof(ctx->remote));
+
+		memcpy(addr, &ctx->remote, len);
+		/* addrlen is a value-result argument, set to actual
+		 * size of source address
+		 */
+		if (ctx->remote.sa_family == AF_INET) {
+			*addrlen = sizeof(struct sockaddr_in);
+		} else if (ctx->remote.sa_family == AF_INET6) {
+			*addrlen = sizeof(struct sockaddr_in6);
+		} else {
+			z_free_fd(fd);
+			errno = ENOTSUP;
+			return -1;
+		}
+	}
+
+	/* TCP context is effectively owned by both application
+	 * and the stack: stack may detect that peer closed/aborted
+	 * connection, but it must not dispose of the context behind
+	 * the application back. Likewise, when application "closes"
+	 * context, it's not disposed of immediately - there's yet
+	 * closing handshake for stack to perform.
+	 */
+	net_context_ref(ctx);
+
+	NET_DBG("accept: ctx=%p, fd=%d", ctx, fd);
+
+	z_finalize_fd(fd, ctx, (const struct fd_op_vtable *)&sock_fd_op_vtable);
+
+	return fd;
+}
+
+int z_impl_zsock_accept(int sock, struct sockaddr *addr, socklen_t *addrlen)
+{
+	VTABLE_CALL(accept, sock, addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_accept(int sock, struct sockaddr *addr,
+				      socklen_t *addrlen)
+{
+	socklen_t addrlen_copy;
+	int ret;
+
+	Z_OOPS(z_user_from_copy(&addrlen_copy, (void *)addrlen,
+			     sizeof(socklen_t)));
+
+	if (Z_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) {
+		errno = EFAULT;
+		return -1;
+	}
+
+	ret = z_impl_zsock_accept(sock, (struct sockaddr *)addr, &addrlen_copy);
+
+	if (ret >= 0 &&
+	    z_user_to_copy((void *)addrlen, &addrlen_copy,
+			   sizeof(socklen_t))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return ret;
+}
+#include <syscalls/zsock_accept_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+#define WAIT_BUFS K_MSEC(100)
+#define MAX_WAIT_BUFS K_SECONDS(10)
+
+ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
+			 int flags,
+			 const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	k_timeout_t timeout = K_FOREVER;
+	uint64_t buf_timeout = 0;
+	int status;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	} else {
+		buf_timeout = 1;//z_timeout_end_calc(timeout);
+	}
+
+	/* Register the callback before sending in order to receive the response
+	 * from the peer.
+	 */
+	status = net_context_recv(ctx, zsock_received_cb,
+				  K_NO_WAIT, ctx->user_data);
+	if (status < 0) {
+		errno = -status;
+		return -1;
+	}
+
+	while (1) {
+		if (dest_addr) {
+			status = net_context_sendto(ctx, buf, len, dest_addr,
+						    addrlen, NULL, timeout,
+						    ctx->user_data);
+		} else {
+			status = net_context_send(ctx, buf, len, NULL, timeout,
+						  ctx->user_data);
+		}
+
+		if (status < 0) {
+			if (((status == -ENOBUFS) || (status == -EAGAIN)) &&
+			    K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+				/* If we cannot get any buffers in reasonable
+				 * amount of time, then do not wait forever as
+				 * there might be some bigger issue.
+				 * If we get -EAGAIN and cannot recover, then
+				 * it means that the sending window is blocked
+				 * and we just cannot send anything.
+				 */
+				int64_t remaining = buf_timeout - z_tick_get();
+
+				if (remaining <= 0) {
+					if (status == -ENOBUFS) {
+						errno = ENOMEM;
+					} else {
+						errno = ENOBUFS;
+					}
+
+					return -1;
+				}
+
+				k_sleep(WAIT_BUFS);
+				continue;
+			} else {
+				errno = -status;
+				return -1;
+			}
+		}
+
+		break;
+	}
+
+	return status;
+}
+
+ssize_t z_impl_zsock_sendto(int sock, const void *buf, size_t len, int flags,
+			   const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	VTABLE_CALL(sendto, sock, buf, len, flags, dest_addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+ssize_t z_vrfy_zsock_sendto(int sock, const void *buf, size_t len, int flags,
+			   const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	struct sockaddr_storage dest_addr_copy;
+
+	Z_OOPS(Z_SYSCALL_MEMORY_READ(buf, len));
+	if (dest_addr) {
+		Z_OOPS(Z_SYSCALL_VERIFY(addrlen <= sizeof(dest_addr_copy)));
+		Z_OOPS(z_user_from_copy(&dest_addr_copy, (void *)dest_addr,
+					addrlen));
+	}
+
+	return z_impl_zsock_sendto(sock, (const void *)buf, len, flags,
+			dest_addr ? (struct sockaddr *)&dest_addr_copy : NULL,
+			addrlen);
+}
+#include <syscalls/zsock_sendto_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+ssize_t zsock_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg,
+			  int flags)
+{
+	k_timeout_t timeout = K_FOREVER;
+	int status;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	status = net_context_sendmsg(ctx, msg, flags, NULL, timeout, NULL);
+	if (status < 0) {
+		errno = -status;
+		return -1;
+	}
+
+	return status;
+}
+
+ssize_t z_impl_zsock_sendmsg(int sock, const struct msghdr *msg, int flags)
+{
+	VTABLE_CALL(sendmsg, sock, msg, flags);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline ssize_t z_vrfy_zsock_sendmsg(int sock,
+					   const struct msghdr *msg,
+					   int flags)
+{
+	struct msghdr msg_copy;
+	size_t i;
+	int ret;
+
+	Z_OOPS(z_user_from_copy(&msg_copy, (void *)msg, sizeof(msg_copy)));
+
+	msg_copy.msg_name = NULL;
+	msg_copy.msg_control = NULL;
+
+	msg_copy.msg_iov = z_user_alloc_from_copy(msg->msg_iov,
+				       msg->msg_iovlen * sizeof(struct iovec));
+	if (!msg_copy.msg_iov) {
+		errno = ENOMEM;
+		goto fail;
+	}
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		msg_copy.msg_iov[i].iov_base =
+			z_user_alloc_from_copy(msg->msg_iov[i].iov_base,
+					       msg->msg_iov[i].iov_len);
+		if (!msg_copy.msg_iov[i].iov_base) {
+			errno = ENOMEM;
+			goto fail;
+		}
+
+		msg_copy.msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
+	}
+
+	if (msg->msg_namelen > 0) {
+		msg_copy.msg_name = z_user_alloc_from_copy(msg->msg_name,
+							   msg->msg_namelen);
+		if (!msg_copy.msg_name) {
+			errno = ENOMEM;
+			goto fail;
+		}
+	}
+
+	if (msg->msg_controllen > 0) {
+		msg_copy.msg_control = z_user_alloc_from_copy(msg->msg_control,
+							  msg->msg_controllen);
+		if (!msg_copy.msg_control) {
+			errno = ENOMEM;
+			goto fail;
+		}
+	}
+
+	ret = z_impl_zsock_sendmsg(sock, (const struct msghdr *)&msg_copy,
+				   flags);
+
+	k_free(msg_copy.msg_name);
+	k_free(msg_copy.msg_control);
+
+	for (i = 0; i < msg_copy.msg_iovlen; i++) {
+		k_free(msg_copy.msg_iov[i].iov_base);
+	}
+
+	k_free(msg_copy.msg_iov);
+
+	return ret;
+
+fail:
+	if (msg_copy.msg_name) {
+		k_free(msg_copy.msg_name);
+	}
+
+	if (msg_copy.msg_control) {
+		k_free(msg_copy.msg_control);
+	}
+
+	if (msg_copy.msg_iov) {
+		for (i = 0; i < msg_copy.msg_iovlen; i++) {
+			if (msg_copy.msg_iov[i].iov_base) {
+				k_free(msg_copy.msg_iov[i].iov_base);
+			}
+		}
+
+		k_free(msg_copy.msg_iov);
+	}
+
+	return -1;
+}
+#include <syscalls/zsock_sendmsg_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static int sock_get_pkt_src_addr(struct net_pkt *pkt,
+				 enum net_ip_protocol proto,
+				 struct sockaddr *addr,
+				 socklen_t addrlen)
+{
+	int ret = 0;
+	struct net_pkt_cursor backup;
+	uint16_t *port;
+
+	if (!addr || !pkt) {
+		return -EINVAL;
+	}
+
+	net_pkt_cursor_backup(pkt, &backup);
+	net_pkt_cursor_init(pkt);
+
+	addr->sa_family = net_pkt_family(pkt);
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) &&
+	    net_pkt_family(pkt) == AF_INET) {
+		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv4_access,
+						      struct net_ipv4_hdr);
+		struct sockaddr_in *addr4 = net_sin(addr);
+		struct net_ipv4_hdr *ipv4_hdr;
+
+		if (addrlen < sizeof(struct sockaddr_in)) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		ipv4_hdr = (struct net_ipv4_hdr *)net_pkt_get_data(
+							pkt, &ipv4_access);
+		if (!ipv4_hdr ||
+		    net_pkt_acknowledge_data(pkt, &ipv4_access) ||
+		    net_pkt_skip(pkt, net_pkt_ipv4_opts_len(pkt))) {
+			ret = -ENOBUFS;
+			goto error;
+		}
+
+		net_ipaddr_copy(&addr4->sin_addr, &ipv4_hdr->src);
+		port = &addr4->sin_port;
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   net_pkt_family(pkt) == AF_INET6) {
+		NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access,
+						      struct net_ipv6_hdr);
+		struct sockaddr_in6 *addr6 = net_sin6(addr);
+		struct net_ipv6_hdr *ipv6_hdr;
+
+		if (addrlen < sizeof(struct sockaddr_in6)) {
+			ret = -EINVAL;
+			goto error;
+		}
+
+		ipv6_hdr = (struct net_ipv6_hdr *)net_pkt_get_data(
+							pkt, &ipv6_access);
+		if (!ipv6_hdr ||
+		    net_pkt_acknowledge_data(pkt, &ipv6_access) ||
+		    net_pkt_skip(pkt, net_pkt_ipv6_ext_len(pkt))) {
+			ret = -ENOBUFS;
+			goto error;
+		}
+
+		net_ipaddr_copy(&addr6->sin6_addr, &ipv6_hdr->src);
+		port = &addr6->sin6_port;
+	} else {
+		ret = -ENOTSUP;
+		goto error;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
+		NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
+		struct net_udp_hdr *udp_hdr;
+
+		udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt,
+								 &udp_access);
+		if (!udp_hdr) {
+			ret = -ENOBUFS;
+			goto error;
+		}
+
+		*port = udp_hdr->src_port;
+	} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
+		NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr);
+		struct net_tcp_hdr *tcp_hdr;
+
+		tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt,
+								 &tcp_access);
+		if (!tcp_hdr) {
+			ret = -ENOBUFS;
+			goto error;
+		}
+
+		*port = tcp_hdr->src_port;
+	} else {
+		ret = -ENOTSUP;
+	}
+
+error:
+	net_pkt_cursor_restore(pkt, &backup);
+
+	return ret;
+}
+
+void net_socket_update_tc_rx_time(struct net_pkt *pkt, uint32_t end_tick)
+{
+	net_pkt_set_rx_stats_tick(pkt, end_tick);
+
+	net_stats_update_tc_rx_time(net_pkt_iface(pkt),
+				    net_pkt_priority(pkt),
+				    net_pkt_timestamp(pkt)->nanosecond,
+				    end_tick);
+
+	if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS_DETAIL)) {
+		uint32_t val, prev = net_pkt_timestamp(pkt)->nanosecond;
+		int i;
+
+		for (i = 0; i < net_pkt_stats_tick_count(pkt); i++) {
+			if (!net_pkt_stats_tick(pkt)[i]) {
+				break;
+			}
+
+			val = net_pkt_stats_tick(pkt)[i] - prev;
+			prev = net_pkt_stats_tick(pkt)[i];
+			net_pkt_stats_tick(pkt)[i] = val;
+		}
+
+		net_stats_update_tc_rx_time_detail(
+			net_pkt_iface(pkt),
+			net_pkt_priority(pkt),
+			net_pkt_stats_tick(pkt));
+	}
+}
+
+static inline ssize_t zsock_recv_dgram(struct net_context *ctx,
+				       void *buf,
+				       size_t max_len,
+				       int flags,
+				       struct sockaddr *src_addr,
+				       socklen_t *addrlen)
+{
+	k_timeout_t timeout = K_FOREVER;
+	size_t recv_len = 0;
+	struct net_pkt_cursor backup;
+	struct net_pkt *pkt;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	if (flags & ZSOCK_MSG_PEEK) {
+		int res;
+
+		res = k_fifo_wait_non_empty(&ctx->recv_q, timeout);
+		/* EAGAIN when timeout expired, EINTR when cancelled */
+		if (res && res != -EAGAIN && res != -EINTR) {
+			errno = -res;
+			return -1;
+		}
+
+		pkt = k_fifo_peek_head(&ctx->recv_q);
+	} else {
+		pkt = k_fifo_get(&ctx->recv_q, timeout);
+	}
+
+	if (!pkt) {
+		errno = EAGAIN;
+		return -1;
+	}
+
+	net_pkt_cursor_backup(pkt, &backup);
+
+	if (src_addr && addrlen) {
+		int rv;
+
+		rv = sock_get_pkt_src_addr(pkt, net_context_get_ip_proto(ctx),
+					   src_addr, *addrlen);
+		if (rv < 0) {
+			errno = -rv;
+			goto fail;
+		}
+
+		/* addrlen is a value-result argument, set to actual
+		 * size of source address
+		 */
+		if (src_addr->sa_family == AF_INET) {
+			*addrlen = sizeof(struct sockaddr_in);
+		} else if (src_addr->sa_family == AF_INET6) {
+			*addrlen = sizeof(struct sockaddr_in6);
+		} else {
+			errno = ENOTSUP;
+			goto fail;
+		}
+	}
+
+	recv_len = net_pkt_remaining_data(pkt);
+	if (recv_len > max_len) {
+		recv_len = max_len;
+	}
+
+	if (net_pkt_read(pkt, buf, recv_len)) {
+		errno = ENOBUFS;
+		goto fail;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) &&
+	    !(flags & ZSOCK_MSG_PEEK)) {
+		net_socket_update_tc_rx_time(pkt, k_cycle_get_32());
+	}
+
+	if (!(flags & ZSOCK_MSG_PEEK)) {
+		net_pkt_unref(pkt);
+	} else {
+		net_pkt_cursor_restore(pkt, &backup);
+	}
+
+	return recv_len;
+
+fail:
+	if (!(flags & ZSOCK_MSG_PEEK)) {
+		net_pkt_unref(pkt);
+	}
+
+	return -1;
+}
+
+static inline ssize_t zsock_recv_stream(struct net_context *ctx,
+					void *buf,
+					size_t max_len,
+					int flags)
+{
+	k_timeout_t timeout = K_FOREVER;
+	size_t recv_len = 0;
+	struct net_pkt_cursor backup;
+	int res;
+
+	if (!net_context_is_used(ctx)) {
+		errno = EBADF;
+		return -1;
+	}
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	do {
+		struct net_pkt *pkt;
+		size_t data_len;
+
+		if (sock_is_eof(ctx)) {
+			return 0;
+		}
+
+		res = k_fifo_wait_non_empty(&ctx->recv_q, timeout);
+		/* EAGAIN when timeout expired, EINTR when cancelled */
+		if (res && res != -EAGAIN && res != -EINTR) {
+			errno = -res;
+			return -1;
+		}
+
+		pkt = k_fifo_peek_head(&ctx->recv_q);
+		if (!pkt) {
+			/* Either timeout expired, or wait was cancelled
+			 * due to connection closure by peer.
+			 */
+			NET_DBG("NULL return from fifo");
+			if (sock_is_eof(ctx)) {
+				return 0;
+			} else {
+				errno = EAGAIN;
+				return -1;
+			}
+		}
+
+		net_pkt_cursor_backup(pkt, &backup);
+
+		data_len = net_pkt_remaining_data(pkt);
+		recv_len = data_len;
+		if (recv_len > max_len) {
+			recv_len = max_len;
+		}
+
+		/* Actually copy data to application buffer */
+		if (net_pkt_read(pkt, buf, recv_len)) {
+			errno = ENOBUFS;
+			return -1;
+		}
+
+		if (!(flags & ZSOCK_MSG_PEEK)) {
+			if (recv_len == data_len) {
+				/* Finished processing head pkt in
+				 * the fifo. Drop it from there.
+				 */
+				k_fifo_get(&ctx->recv_q, K_NO_WAIT);
+				if (net_pkt_eof(pkt)) {
+					sock_set_eof(ctx);
+				}
+
+				if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS)) {
+					net_socket_update_tc_rx_time(
+						pkt, k_cycle_get_32());
+				}
+
+				net_pkt_unref(pkt);
+			}
+		} else {
+			net_pkt_cursor_restore(pkt, &backup);
+		}
+	} while (recv_len == 0);
+
+	if (!(flags & ZSOCK_MSG_PEEK)) {
+		net_context_update_recv_wnd(ctx, recv_len);
+	}
+
+	return recv_len;
+}
+
+ssize_t zsock_recvfrom_ctx(struct net_context *ctx, void *buf, size_t max_len,
+			   int flags,
+			   struct sockaddr *src_addr, socklen_t *addrlen)
+{
+	enum net_sock_type sock_type = net_context_get_type(ctx);
+
+	if (max_len == 0) {
+		return 0;
+	}
+
+	if (sock_type == SOCK_DGRAM) {
+		return zsock_recv_dgram(ctx, buf, max_len, flags, src_addr, addrlen);
+	} else if (sock_type == SOCK_STREAM) {
+		return zsock_recv_stream(ctx, buf, max_len, flags);
+	} else {
+		__ASSERT(0, "Unknown socket type");
+	}
+
+	return 0;
+}
+
+ssize_t z_impl_zsock_recvfrom(int sock, void *buf, size_t max_len, int flags,
+			     struct sockaddr *src_addr, socklen_t *addrlen)
+{
+	VTABLE_CALL(recvfrom, sock, buf, max_len, flags, src_addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+ssize_t z_vrfy_zsock_recvfrom(int sock, void *buf, size_t max_len, int flags,
+			      struct sockaddr *src_addr, socklen_t *addrlen)
+{
+	socklen_t addrlen_copy;
+	ssize_t ret;
+
+	if (Z_SYSCALL_MEMORY_WRITE(buf, max_len)) {
+		errno = EFAULT;
+		return -1;
+	}
+
+	if (addrlen) {
+		Z_OOPS(z_user_from_copy(&addrlen_copy, addrlen,
+					sizeof(socklen_t)));
+	}
+	Z_OOPS(src_addr && Z_SYSCALL_MEMORY_WRITE(src_addr, addrlen_copy));
+
+	ret = z_impl_zsock_recvfrom(sock, (void *)buf, max_len, flags,
+				   (struct sockaddr *)src_addr,
+				   addrlen ? &addrlen_copy : NULL);
+
+	if (addrlen) {
+		Z_OOPS(z_user_to_copy(addrlen, &addrlen_copy,
+				      sizeof(socklen_t)));
+	}
+
+	return ret;
+}
+#include <syscalls/zsock_recvfrom_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+/* As this is limited function, we don't follow POSIX signature, with
+ * "..." instead of last arg.
+ */
+int z_impl_zsock_fcntl(int sock, int cmd, int flags)
+{
+	const struct socket_op_vtable *vtable;
+	void *obj;
+
+	obj = get_sock_vtable(sock, &vtable);
+	if (obj == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	return z_fdtable_call_ioctl((const struct fd_op_vtable *)vtable,
+				    obj, cmd, flags);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_fcntl(int sock, int cmd, int flags)
+{
+	return z_impl_zsock_fcntl(sock, cmd, flags);
+}
+#include <syscalls/zsock_fcntl_mrsh.c>
+#endif
+
+static int zsock_poll_prepare_ctx(struct net_context *ctx,
+				  struct zsock_pollfd *pfd,
+				  struct k_poll_event **pev,
+				  struct k_poll_event *pev_end)
+{
+	if (pfd->events & ZSOCK_POLLIN) {
+		if (*pev == pev_end) {
+			return -ENOMEM;
+		}
+
+		(*pev)->obj = &ctx->recv_q;
+		(*pev)->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
+		(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
+		(*pev)->state = K_POLL_STATE_NOT_READY;
+		(*pev)++;
+	}
+
+	if (pfd->events & ZSOCK_POLLOUT) {
+		return -EALREADY;
+	}
+
+	/* If socket is already in EOF, it can be reported
+	 * immediately, so we tell poll() to short-circuit wait.
+	 */
+	if (sock_is_eof(ctx)) {
+		return -EALREADY;
+	}
+
+	return 0;
+}
+
+static int zsock_poll_update_ctx(struct net_context *ctx,
+				 struct zsock_pollfd *pfd,
+				 struct k_poll_event **pev)
+{
+	ARG_UNUSED(ctx);
+
+	/* For now, assume that socket is always writable */
+	if (pfd->events & ZSOCK_POLLOUT) {
+		pfd->revents |= ZSOCK_POLLOUT;
+	}
+
+	if (pfd->events & ZSOCK_POLLIN) {
+		if ((*pev)->state != K_POLL_STATE_NOT_READY || sock_is_eof(ctx)) {
+			pfd->revents |= ZSOCK_POLLIN;
+		}
+		(*pev)++;
+	}
+
+	return 0;
+}
+
+static inline int time_left(uint32_t start, uint32_t timeout)
+{
+	uint32_t elapsed = k_uptime_get_32() - start;
+
+	return timeout - elapsed;
+}
+
+int z_impl_zsock_poll(struct zsock_pollfd *fds, int nfds, int poll_timeout)
+{
+	bool retry;
+	int ret = 0;
+	int i;
+	struct zsock_pollfd *pfd;
+	struct k_poll_event poll_events[CONFIG_NET_SOCKETS_POLL_MAX];
+	struct k_poll_event *pev;
+	struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events);
+	const struct fd_op_vtable *vtable;
+	k_timeout_t timeout;
+	uint64_t end;
+	bool offload = false;
+	const struct fd_op_vtable *offl_vtable = NULL;
+	void *offl_ctx = NULL;
+
+	if (poll_timeout < 0) {
+		timeout = K_FOREVER;
+		poll_timeout = SYS_FOREVER_MS;
+	} else {
+		timeout = K_MSEC(poll_timeout);
+	}
+
+	end = 1;//z_timeout_end_calc(timeout);
+
+	pev = poll_events;
+	for (pfd = fds, i = nfds; i--; pfd++) {
+		void *ctx;
+		int result;
+
+		/* Per POSIX, negative fd's are just ignored */
+		if (pfd->fd < 0) {
+			continue;
+		}
+
+		ctx = get_sock_vtable(pfd->fd,
+				(const struct socket_op_vtable **)&vtable);
+		if (ctx == NULL) {
+			/* Will set POLLNVAL in return loop */
+			continue;
+		}
+
+		result = z_fdtable_call_ioctl(vtable, ctx,
+					      ZFD_IOCTL_POLL_PREPARE,
+					      pfd, &pev, pev_end);
+		if (result == -EALREADY) {
+			/* If POLL_PREPARE returned with EALREADY, it means
+			 * it already detected that some socket is ready. In
+			 * this case, we still perform a k_poll to pick up
+			 * as many events as possible, but without any wait.
+			 */
+			timeout = K_NO_WAIT;
+			continue;
+		} else if (result == -EXDEV) {
+			/* If POLL_PREPARE returned EXDEV, it means
+			 * it detected an offloaded socket.
+			 * If offloaded socket is used with native TLS, the TLS
+			 * wrapper for the offloaded poll will be used.
+			 * In case the fds array contains a mixup of offloaded
+			 * and non-offloaded sockets, the offloaded poll handler
+			 * shall return an error.
+			 */
+			offload = true;
+			if (offl_vtable == NULL || net_socket_is_tls(ctx)) {
+				offl_vtable = vtable;
+				offl_ctx = ctx;
+			}
+			continue;
+		} else if (result != 0) {
+			errno = -result;
+			return -1;
+		}
+	}
+
+	if (offload) {
+		return z_fdtable_call_ioctl(offl_vtable, offl_ctx,
+					    ZFD_IOCTL_POLL_OFFLOAD,
+					    fds, nfds, poll_timeout);
+	}
+
+	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+	    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+		int64_t remaining = end - z_tick_get();
+
+		if (remaining <= 0) {
+			timeout = K_NO_WAIT;
+		} else {
+			timeout = Z_TIMEOUT_TICKS(remaining);
+		}
+	}
+
+	do {
+		ret = k_poll(poll_events, pev - poll_events, timeout);
+		/* EAGAIN when timeout expired, EINTR when cancelled (i.e. EOF) */
+		if (ret != 0 && ret != -EAGAIN && ret != -EINTR) {
+			errno = -ret;
+			return -1;
+		}
+
+		retry = false;
+		ret = 0;
+
+		pev = poll_events;
+		for (pfd = fds, i = nfds; i--; pfd++) {
+			void *ctx;
+			int result;
+
+			pfd->revents = 0;
+
+			if (pfd->fd < 0) {
+				continue;
+			}
+
+			ctx = get_sock_vtable(pfd->fd,
+				(const struct socket_op_vtable **)&vtable);
+			if (ctx == NULL) {
+				pfd->revents = ZSOCK_POLLNVAL;
+				ret++;
+				continue;
+			}
+
+			result = z_fdtable_call_ioctl(vtable, ctx,
+						      ZFD_IOCTL_POLL_UPDATE,
+						      pfd, &pev);
+			if (result == -EAGAIN) {
+				retry = true;
+				continue;
+			} else if (result != 0) {
+				errno = -result;
+				return -1;
+			}
+
+			if (pfd->revents != 0) {
+				ret++;
+			}
+		}
+
+		if (retry) {
+			if (ret > 0) {
+				break;
+			}
+
+			if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
+				break;
+			}
+
+			if (!K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+				int64_t remaining = end - z_tick_get();
+
+				if (remaining <= 0) {
+					break;
+				} else {
+					timeout = Z_TIMEOUT_TICKS(remaining);
+				}
+			}
+		}
+	} while (retry);
+
+	return ret;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_poll(struct zsock_pollfd *fds,
+				    int nfds, int timeout)
+{
+	struct zsock_pollfd *fds_copy;
+	size_t fds_size;
+	int ret;
+
+	/* Copy fds array from user mode */
+	if (size_mul_overflow(nfds, sizeof(struct zsock_pollfd), &fds_size)) {
+		errno = EFAULT;
+		return -1;
+	}
+	fds_copy = z_user_alloc_from_copy((void *)fds, fds_size);
+	if (!fds_copy) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	ret = z_impl_zsock_poll(fds_copy, nfds, timeout);
+
+	if (ret >= 0) {
+		z_user_to_copy((void *)fds, fds_copy, fds_size);
+	}
+	k_free(fds_copy);
+
+	return ret;
+}
+#include <syscalls/zsock_poll_mrsh.c>
+#endif
+
+int z_impl_zsock_inet_pton(sa_family_t family, const char *src, void *dst)
+{
+	if (net_addr_pton(family, src, dst) == 0) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_inet_pton(sa_family_t family,
+					 const char *src, void *dst)
+{
+	int dst_size;
+	char src_copy[NET_IPV6_ADDR_LEN];
+	char dst_copy[sizeof(struct in6_addr)];
+	int ret;
+
+	switch (family) {
+	case AF_INET:
+		dst_size = sizeof(struct in_addr);
+		break;
+	case AF_INET6:
+		dst_size = sizeof(struct in6_addr);
+		break;
+	default:
+		errno = EAFNOSUPPORT;
+		return -1;
+	}
+
+	Z_OOPS(z_user_string_copy(src_copy, (char *)src, sizeof(src_copy)));
+	ret = z_impl_zsock_inet_pton(family, src_copy, dst_copy);
+	Z_OOPS(z_user_to_copy(dst, dst_copy, dst_size));
+
+	return ret;
+}
+#include <syscalls/zsock_inet_pton_mrsh.c>
+#endif
+
+int zsock_getsockopt_ctx(struct net_context *ctx, int level, int optname,
+			 void *optval, socklen_t *optlen)
+{
+	int ret;
+
+	switch (level) {
+	case SOL_SOCKET:
+		switch (optname) {
+		case SO_TXTIME:
+			if (IS_ENABLED(CONFIG_NET_CONTEXT_TXTIME)) {
+				ret = net_context_get_option(ctx,
+							     NET_OPT_TXTIME,
+							     optval, optlen);
+				if (ret < 0) {
+					errno = -ret;
+					return -1;
+				}
+
+				return 0;
+			}
+		}
+
+		break;
+	}
+
+	errno = ENOPROTOOPT;
+	return -1;
+}
+
+int z_impl_zsock_getsockopt(int sock, int level, int optname,
+			    void *optval, socklen_t *optlen)
+{
+	VTABLE_CALL(getsockopt, sock, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_USERSPACE
+int z_vrfy_zsock_getsockopt(int sock, int level, int optname,
+			    void *optval, socklen_t *optlen)
+{
+	socklen_t kernel_optlen = *(socklen_t *)optlen;
+	void *kernel_optval;
+	int ret;
+
+	if (Z_SYSCALL_MEMORY_WRITE(optval, kernel_optlen)) {
+		errno = -EPERM;
+		return -1;
+	}
+
+	kernel_optval = z_user_alloc_from_copy((const void *)optval,
+					       kernel_optlen);
+	Z_OOPS(!kernel_optval);
+
+	ret = z_impl_zsock_getsockopt(sock, level, optname,
+				      kernel_optval, &kernel_optlen);
+
+	Z_OOPS(z_user_to_copy((void *)optval, kernel_optval, kernel_optlen));
+	Z_OOPS(z_user_to_copy((void *)optlen, &kernel_optlen,
+			      sizeof(socklen_t)));
+
+	k_free(kernel_optval);
+
+	return ret;
+}
+#include <syscalls/zsock_getsockopt_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_setsockopt_ctx(struct net_context *ctx, int level, int optname,
+			 const void *optval, socklen_t optlen)
+{
+	int ret;
+
+	switch (level) {
+	case SOL_SOCKET:
+		switch (optname) {
+		case SO_REUSEADDR:
+			/* Ignore for now. Provided to let port
+			 * existing apps.
+			 */
+			return 0;
+
+		case SO_PRIORITY:
+			if (IS_ENABLED(CONFIG_NET_CONTEXT_PRIORITY)) {
+				ret = net_context_set_option(ctx,
+							     NET_OPT_PRIORITY,
+							     optval, optlen);
+				if (ret < 0) {
+					errno = -ret;
+					return -1;
+				}
+
+				return 0;
+			}
+
+			break;
+
+		case SO_TIMESTAMPING:
+			/* Calculate TX network packet timings */
+			if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP)) {
+				ret = net_context_set_option(ctx,
+							     NET_OPT_TIMESTAMP,
+							     optval, optlen);
+				if (ret < 0) {
+					errno = -ret;
+					return -1;
+				}
+
+				return 0;
+			}
+
+			break;
+
+		case SO_TXTIME:
+			if (IS_ENABLED(CONFIG_NET_CONTEXT_TXTIME)) {
+				ret = net_context_set_option(ctx,
+							     NET_OPT_TXTIME,
+							     optval, optlen);
+				if (ret < 0) {
+					errno = -ret;
+					return -1;
+				}
+
+				return 0;
+			}
+
+			break;
+
+		case SO_SOCKS5:
+			if (IS_ENABLED(CONFIG_SOCKS)) {
+				ret = net_context_set_option(ctx,
+							     NET_OPT_SOCKS5,
+							     optval, optlen);
+				if (ret < 0) {
+					errno = -ret;
+					return -1;
+				}
+
+				net_context_set_proxy_enabled(ctx, true);
+
+				return 0;
+			}
+
+			break;
+		}
+
+		break;
+
+	case IPPROTO_TCP:
+		switch (optname) {
+		case TCP_NODELAY:
+			/* Ignore for now. Provided to let port
+			 * existing apps.
+			 */
+			return 0;
+		}
+		break;
+
+	case IPPROTO_IPV6:
+		switch (optname) {
+		case IPV6_V6ONLY:
+			/* Ignore for now. Provided to let port
+			 * existing apps.
+			 */
+			return 0;
+		}
+		break;
+	}
+
+	errno = ENOPROTOOPT;
+	return -1;
+}
+
+int z_impl_zsock_setsockopt(int sock, int level, int optname,
+			    const void *optval, socklen_t optlen)
+{
+	VTABLE_CALL(setsockopt, sock, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_USERSPACE
+int z_vrfy_zsock_setsockopt(int sock, int level, int optname,
+			    const void *optval, socklen_t optlen)
+{
+	void *kernel_optval;
+	int ret;
+
+	kernel_optval = z_user_alloc_from_copy((const void *)optval, optlen);
+	Z_OOPS(!kernel_optval);
+
+	ret = z_impl_zsock_setsockopt(sock, level, optname,
+				      kernel_optval, optlen);
+
+	k_free(kernel_optval);
+
+	return ret;
+}
+#include <syscalls/zsock_setsockopt_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+int zsock_getsockname_ctx(struct net_context *ctx, struct sockaddr *addr,
+			  socklen_t *addrlen)
+{
+	socklen_t newlen = 0;
+
+	/* If we don't have a connection handler, the socket is not bound */
+	if (!ctx->conn_handler) {
+		SET_ERRNO(-EINVAL);
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV4) && ctx->local.family == AF_INET) {
+		struct sockaddr_in addr4 = { 0 };
+
+		addr4.sin_family = AF_INET;
+		addr4.sin_port = net_sin_ptr(&ctx->local)->sin_port;
+		memcpy(&addr4.sin_addr, net_sin_ptr(&ctx->local)->sin_addr,
+		       sizeof(struct in_addr));
+		newlen = sizeof(struct sockaddr_in);
+
+		memcpy(addr, &addr4, MIN(*addrlen, newlen));
+	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
+		   ctx->local.family == AF_INET6) {
+		struct sockaddr_in6 addr6 = { 0 };
+
+		addr6.sin6_family = AF_INET6;
+		addr6.sin6_port = net_sin6_ptr(&ctx->local)->sin6_port;
+		memcpy(&addr6.sin6_addr, net_sin6_ptr(&ctx->local)->sin6_addr,
+		       sizeof(struct in6_addr));
+		newlen = sizeof(struct sockaddr_in6);
+
+		memcpy(addr, &addr6, MIN(*addrlen, newlen));
+	} else {
+		SET_ERRNO(-EINVAL);
+	}
+
+	*addrlen = newlen;
+
+	return 0;
+}
+
+int z_impl_zsock_getsockname(int sock, struct sockaddr *addr,
+			     socklen_t *addrlen)
+{
+	const struct socket_op_vtable *vtable;
+	void *ctx = get_sock_vtable(sock, &vtable);
+
+	if (ctx == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	NET_DBG("getsockname: ctx=%p, fd=%d", ctx, sock);
+
+	return vtable->getsockname(ctx, addr, addrlen);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_getsockname(int sock, struct sockaddr *addr,
+					   socklen_t *addrlen)
+{
+	socklen_t addrlen_copy;
+	int ret;
+
+	Z_OOPS(z_user_from_copy(&addrlen_copy, (void *)addrlen,
+				sizeof(socklen_t)));
+
+	if (Z_SYSCALL_MEMORY_WRITE(addr, addrlen_copy)) {
+		errno = EFAULT;
+		return -1;
+	}
+
+	ret = z_impl_zsock_getsockname(sock, (struct sockaddr *)addr,
+				       &addrlen_copy);
+
+	if (ret == 0 &&
+	    z_user_to_copy((void *)addrlen, &addrlen_copy,
+			   sizeof(socklen_t))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return ret;
+}
+#include <syscalls/zsock_getsockname_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+static ssize_t sock_read_vmeth(void *obj, void *buffer, size_t count)
+{
+	return zsock_recvfrom_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t sock_write_vmeth(void *obj, const void *buffer, size_t count)
+{
+	return zsock_sendto_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static int sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
+{
+	switch (request) {
+
+	/* In Zephyr, fcntl() is just an alias of ioctl(). */
+	case F_GETFL:
+		if (sock_is_nonblock(obj)) {
+		    return O_NONBLOCK;
+		}
+
+		return 0;
+
+	case F_SETFL: {
+		int flags;
+
+		flags = va_arg(args, int);
+
+		if (flags & O_NONBLOCK) {
+			sock_set_flag(obj, SOCK_NONBLOCK, SOCK_NONBLOCK);
+		} else {
+			sock_set_flag(obj, SOCK_NONBLOCK, 0);
+		}
+
+		return 0;
+	}
+
+	case ZFD_IOCTL_POLL_PREPARE: {
+		struct zsock_pollfd *pfd;
+		struct k_poll_event **pev;
+		struct k_poll_event *pev_end;
+
+		pfd = va_arg(args, struct zsock_pollfd *);
+		pev = va_arg(args, struct k_poll_event **);
+		pev_end = va_arg(args, struct k_poll_event *);
+
+		return zsock_poll_prepare_ctx(obj, pfd, pev, pev_end);
+	}
+
+	case ZFD_IOCTL_POLL_UPDATE: {
+		struct zsock_pollfd *pfd;
+		struct k_poll_event **pev;
+
+		pfd = va_arg(args, struct zsock_pollfd *);
+		pev = va_arg(args, struct k_poll_event **);
+
+		return zsock_poll_update_ctx(obj, pfd, pev);
+	}
+
+	default:
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+}
+
+static int sock_bind_vmeth(void *obj, const struct sockaddr *addr,
+			   socklen_t addrlen)
+{
+	return zsock_bind_ctx(obj, addr, addrlen);
+}
+
+static int sock_connect_vmeth(void *obj, const struct sockaddr *addr,
+			      socklen_t addrlen)
+{
+	return zsock_connect_ctx(obj, addr, addrlen);
+}
+
+static int sock_listen_vmeth(void *obj, int backlog)
+{
+	return zsock_listen_ctx(obj, backlog);
+}
+
+static int sock_accept_vmeth(void *obj, struct sockaddr *addr,
+			     socklen_t *addrlen)
+{
+	return zsock_accept_ctx(obj, addr, addrlen);
+}
+
+static ssize_t sock_sendto_vmeth(void *obj, const void *buf, size_t len,
+				 int flags, const struct sockaddr *dest_addr,
+				 socklen_t addrlen)
+{
+	return zsock_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
+}
+
+static ssize_t sock_sendmsg_vmeth(void *obj, const struct msghdr *msg,
+				  int flags)
+{
+	return zsock_sendmsg_ctx(obj, msg, flags);
+}
+
+static ssize_t sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
+				   int flags, struct sockaddr *src_addr,
+				   socklen_t *addrlen)
+{
+	return zsock_recvfrom_ctx(obj, buf, max_len, flags,
+				  src_addr, addrlen);
+}
+
+static int sock_getsockopt_vmeth(void *obj, int level, int optname,
+				 void *optval, socklen_t *optlen)
+{
+	return zsock_getsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int sock_setsockopt_vmeth(void *obj, int level, int optname,
+				 const void *optval, socklen_t optlen)
+{
+	return zsock_setsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int sock_close_vmeth(void *obj)
+{
+	return zsock_close_ctx(obj);
+}
+
+static int sock_getsockname_vmeth(void *obj, struct sockaddr *addr,
+				  socklen_t *addrlen)
+{
+	return zsock_getsockname_ctx(obj, addr, addrlen);
+}
+
+const struct socket_op_vtable sock_fd_op_vtable = {
+	.fd_vtable = {
+		.read = sock_read_vmeth,
+		.write = sock_write_vmeth,
+		.close = sock_close_vmeth,
+		.ioctl = sock_ioctl_vmeth,
+	},
+	.bind = sock_bind_vmeth,
+	.connect = sock_connect_vmeth,
+	.listen = sock_listen_vmeth,
+	.accept = sock_accept_vmeth,
+	.sendto = sock_sendto_vmeth,
+	.sendmsg = sock_sendmsg_vmeth,
+	.recvfrom = sock_recvfrom_vmeth,
+	.getsockopt = sock_getsockopt_vmeth,
+	.setsockopt = sock_setsockopt_vmeth,
+	.getsockname = sock_getsockname_vmeth,
+};
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_can.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_can.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_can.c	(working copy)
@@ -0,0 +1,701 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <fcntl.h>
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock_can, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <drivers/entropy.h>
+#include <sys/util.h>
+#include <net/net_context.h>
+#include <net/net_pkt.h>
+#include <net/socket.h>
+#include <syscall_handler.h>
+#include <sys/fdtable.h>
+#include <net/socket_can.h>
+
+#include "sockets_internal.h"
+
+#define MEM_ALLOC_TIMEOUT K_MSEC(50)
+
+struct can_recv {
+	struct net_if *iface;
+	struct net_context *ctx;
+	canid_t can_id;
+	canid_t can_mask;
+};
+
+static struct can_recv receivers[CONFIG_NET_SOCKETS_CAN_RECEIVERS];
+
+extern const struct socket_op_vtable sock_fd_op_vtable;
+
+static const struct socket_op_vtable can_sock_fd_op_vtable;
+
+static inline int k_fifo_wait_non_empty(struct k_fifo *fifo,
+					k_timeout_t timeout)
+{
+	struct k_poll_event events[] = {
+		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+					 K_POLL_MODE_NOTIFY_ONLY, fifo),
+	};
+
+	return k_poll(events, ARRAY_SIZE(events), timeout);
+}
+
+int zcan_socket(int family, int type, int proto)
+{
+	struct net_context *ctx;
+	int fd;
+	int ret;
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		return -1;
+	}
+
+	ret = net_context_get(family, type, proto, &ctx);
+	if (ret < 0) {
+		z_free_fd(fd);
+		errno = -ret;
+		return -1;
+	}
+
+	/* Initialize user_data, all other calls will preserve it */
+	ctx->user_data = NULL;
+
+	k_fifo_init(&ctx->recv_q);
+
+	z_finalize_fd(fd, ctx,
+		      (const struct fd_op_vtable *)&can_sock_fd_op_vtable);
+
+	return fd;
+}
+
+static void zcan_received_cb(struct net_context *ctx, struct net_pkt *pkt,
+			     union net_ip_header *ip_hdr,
+			     union net_proto_header *proto_hdr,
+			     int status, void *user_data)
+{
+	/* The ctx parameter is not really relevant here. It refers to first
+	 * net_context that was used when registering CAN socket.
+	 * In practice there can be multiple sockets that are interested in
+	 * same CAN id packets. That is why we need to implement the dispatcher
+	 * which will give the packet to correct net_context(s).
+	 */
+	struct net_pkt *clone = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(receivers); i++) {
+		struct zcan_frame *zframe =
+			(struct zcan_frame *)net_pkt_data(pkt);
+		struct can_frame frame;
+
+		if (!receivers[i].ctx ||
+		    receivers[i].iface != net_pkt_iface(pkt)) {
+			continue;
+		}
+
+		can_copy_zframe_to_frame(zframe, &frame);
+
+		if ((frame.can_id & receivers[i].can_mask) !=
+		    (receivers[i].can_id & receivers[i].can_mask)) {
+			continue;
+		}
+
+		/* If there are multiple receivers configured, we use the
+		 * original net_pkt as a template, and just clone it to all
+		 * recipients. This is done like this so that we avoid the
+		 * original net_pkt being freed while we are cloning it.
+		 */
+		if (pkt != NULL && ARRAY_SIZE(receivers) > 1) {
+			/* There are multiple receivers, we need to clone
+			 * the packet.
+			 */
+			clone = net_pkt_clone(pkt, MEM_ALLOC_TIMEOUT);
+			if (!clone) {
+				/* Sent the packet to at least one recipient
+				 * if there is no memory to clone the packet.
+				 */
+				clone = pkt;
+			}
+		} else {
+			clone = pkt;
+		}
+
+		ctx = receivers[i].ctx;
+
+		NET_DBG("[%d] ctx %p pkt %p st %d", i, ctx, clone, status);
+
+		/* if pkt is NULL, EOF */
+		if (!clone) {
+			struct net_pkt *last_pkt =
+				k_fifo_peek_tail(&ctx->recv_q);
+
+			if (!last_pkt) {
+				/* If there're no packets in the queue,
+				 * recv() may be blocked waiting on it to
+				 * become non-empty, so cancel that wait.
+				 */
+				sock_set_eof(ctx);
+				k_fifo_cancel_wait(&ctx->recv_q);
+
+				NET_DBG("Marked socket %p as peer-closed", ctx);
+			} else {
+				net_pkt_set_eof(last_pkt, true);
+
+				NET_DBG("Set EOF flag on pkt %p", ctx);
+			}
+
+			return;
+		} else {
+			/* Normal packet */
+			net_pkt_set_eof(clone, false);
+
+			k_fifo_put(&ctx->recv_q, clone);
+		}
+	}
+
+	if (clone && clone != pkt) {
+		net_pkt_unref(pkt);
+	}
+}
+
+static int zcan_bind_ctx(struct net_context *ctx, const struct sockaddr *addr,
+			 socklen_t addrlen)
+{
+	struct sockaddr_can *can_addr = (struct sockaddr_can *)addr;
+	struct net_if *iface;
+	int ret;
+
+	if (addrlen != sizeof(struct sockaddr_can)) {
+		return -EINVAL;
+	}
+
+	iface = net_if_get_by_index(can_addr->can_ifindex);
+	if (!iface) {
+		return -ENOENT;
+	}
+
+	net_context_set_iface(ctx, iface);
+
+	ret = net_context_bind(ctx, addr, addrlen);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	/* For CAN socket, we expect to receive packets after call to bind().
+	 */
+	ret = net_context_recv(ctx, zcan_received_cb, K_NO_WAIT,
+			       ctx->user_data);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	return 0;
+}
+
+ssize_t zcan_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
+			int flags, const struct sockaddr *dest_addr,
+			socklen_t addrlen)
+{
+	struct sockaddr_can can_addr;
+	struct zcan_frame zframe;
+	k_timeout_t timeout = K_FOREVER;
+	int ret;
+
+	/* Setting destination address does not probably make sense here so
+	 * ignore it. You need to use bind() to set the CAN interface.
+	 */
+	if (dest_addr) {
+		NET_DBG("CAN destination address ignored");
+	}
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	if (addrlen == 0) {
+		addrlen = sizeof(struct sockaddr_can);
+	}
+
+	if (dest_addr == NULL) {
+		memset(&can_addr, 0, sizeof(can_addr));
+
+		can_addr.can_ifindex = -1;
+		can_addr.can_family = AF_CAN;
+
+		dest_addr = (struct sockaddr *)&can_addr;
+	}
+
+	NET_ASSERT(len == sizeof(struct can_frame));
+
+	can_copy_frame_to_zframe((struct can_frame *)buf, &zframe);
+
+	ret = net_context_sendto(ctx, (void *)&zframe, sizeof(zframe),
+				 dest_addr, addrlen, NULL, timeout,
+				 ctx->user_data);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	return len;
+}
+
+static ssize_t zcan_recvfrom_ctx(struct net_context *ctx, void *buf,
+				 size_t max_len, int flags,
+				 struct sockaddr *src_addr,
+				 socklen_t *addrlen)
+{
+	struct zcan_frame zframe;
+	size_t recv_len = 0;
+	k_timeout_t timeout = K_FOREVER;
+	struct net_pkt *pkt;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	if (flags & ZSOCK_MSG_PEEK) {
+		int ret;
+
+		ret = k_fifo_wait_non_empty(&ctx->recv_q, timeout);
+		/* EAGAIN when timeout expired, EINTR when cancelled */
+		if (ret && ret != -EAGAIN && ret != -EINTR) {
+			errno = -ret;
+			return -1;
+		}
+
+		pkt = k_fifo_peek_head(&ctx->recv_q);
+	} else {
+		pkt = k_fifo_get(&ctx->recv_q, timeout);
+	}
+
+	if (!pkt) {
+		errno = EAGAIN;
+		return -1;
+	}
+
+	/* We do not handle any headers here, just pass the whole packet to
+	 * the caller.
+	 */
+	recv_len = net_pkt_get_len(pkt);
+	if (recv_len > max_len) {
+		recv_len = max_len;
+	}
+
+	if (net_pkt_read(pkt, (void *)&zframe, sizeof(zframe))) {
+		net_pkt_unref(pkt);
+
+		errno = EIO;
+		return -1;
+	}
+
+	NET_ASSERT(recv_len == sizeof(struct can_frame));
+
+	can_copy_zframe_to_frame(&zframe, (struct can_frame *)buf);
+
+	net_pkt_unref(pkt);
+
+	return recv_len;
+}
+
+static int zcan_getsockopt_ctx(struct net_context *ctx, int level, int optname,
+			       void *optval, socklen_t *optlen)
+{
+	if (!optval || !optlen) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return sock_fd_op_vtable.getsockopt(ctx, level, optname,
+					    optval, optlen);
+}
+
+static int zcan_setsockopt_ctx(struct net_context *ctx, int level, int optname,
+			       const void *optval, socklen_t optlen)
+{
+	return sock_fd_op_vtable.setsockopt(ctx, level, optname,
+					    optval, optlen);
+}
+
+static ssize_t can_sock_read_vmeth(void *obj, void *buffer, size_t count)
+{
+	return zcan_recvfrom_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t can_sock_write_vmeth(void *obj, const void *buffer,
+				    size_t count)
+{
+	return zcan_sendto_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static bool is_already_attached(struct can_filter *filter,
+				struct net_if *iface,
+				struct net_context *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(receivers); i++) {
+		if (receivers[i].ctx != ctx && receivers[i].iface == iface &&
+		    ((receivers[i].can_id & receivers[i].can_mask) ==
+		     (UNALIGNED_GET(&filter->can_id) &
+		      UNALIGNED_GET(&filter->can_mask)))) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int close_socket(struct net_context *ctx)
+{
+	const struct canbus_api *api;
+	struct net_if *iface;
+	const struct device *dev;
+
+	iface = net_context_get_iface(ctx);
+	dev = net_if_get_device(iface);
+	api = dev->api;
+
+	if (!api || !api->close) {
+		return -ENOTSUP;
+	}
+
+	api->close(dev, net_context_get_filter_id(ctx));
+
+	return 0;
+}
+
+static int can_close_socket(struct net_context *ctx)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(receivers); i++) {
+		if (receivers[i].ctx == ctx) {
+			struct can_filter filter;
+
+			receivers[i].ctx = NULL;
+
+			filter.can_id = receivers[i].can_id;
+			filter.can_mask = receivers[i].can_mask;
+
+			if (!is_already_attached(&filter,
+						net_context_get_iface(ctx),
+						ctx)) {
+				/* We can detach now as there are no other
+				 * sockets that have same filter.
+				 */
+				ret = close_socket(ctx);
+				if (ret < 0) {
+					return ret;
+				}
+			}
+
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int can_sock_close_vmeth(void *obj)
+{
+	int ret;
+
+	ret = can_close_socket(obj);
+	if (ret < 0) {
+		NET_DBG("Cannot detach net_context %p (%d)", obj, ret);
+
+		errno = -ret;
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static int can_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
+{
+	return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
+}
+
+/*
+ * TODO: A CAN socket can be bound to a network device using SO_BINDTODEVICE.
+ */
+static int can_sock_bind_vmeth(void *obj, const struct sockaddr *addr,
+			       socklen_t addrlen)
+{
+	return zcan_bind_ctx(obj, addr, addrlen);
+}
+
+/* The connect() function is no longer necessary. */
+static int can_sock_connect_vmeth(void *obj, const struct sockaddr *addr,
+				  socklen_t addrlen)
+{
+	return 0;
+}
+
+/*
+ * The listen() and accept() functions are without any functionality,
+ * since the client-Server-Semantic is no longer present.
+ * When we use RAW-sockets we are sending unconnected packets.
+ */
+static int can_sock_listen_vmeth(void *obj, int backlog)
+{
+	return 0;
+}
+
+static int can_sock_accept_vmeth(void *obj, struct sockaddr *addr,
+				 socklen_t *addrlen)
+{
+	return 0;
+}
+
+static ssize_t can_sock_sendto_vmeth(void *obj, const void *buf, size_t len,
+				     int flags,
+				     const struct sockaddr *dest_addr,
+				     socklen_t addrlen)
+{
+	return zcan_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
+}
+
+static ssize_t can_sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
+				       int flags, struct sockaddr *src_addr,
+				       socklen_t *addrlen)
+{
+	return zcan_recvfrom_ctx(obj, buf, max_len, flags,
+				 src_addr, addrlen);
+}
+
+static int can_sock_getsockopt_vmeth(void *obj, int level, int optname,
+				     void *optval, socklen_t *optlen)
+{
+	if (level == SOL_CAN_RAW) {
+		const struct canbus_api *api;
+		struct net_if *iface;
+		const struct device *dev;
+
+		if (optval == NULL) {
+			errno = EINVAL;
+			return -1;
+		}
+
+		iface = net_context_get_iface(obj);
+		dev = net_if_get_device(iface);
+		api = dev->api;
+
+		if (!api || !api->getsockopt) {
+			errno = ENOTSUP;
+			return -1;
+		}
+
+		return api->getsockopt(dev, obj, level, optname, optval,
+				       optlen);
+	}
+
+	return zcan_getsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int can_register_receiver(struct net_if *iface, struct net_context *ctx,
+				 canid_t can_id, canid_t can_mask)
+{
+	int i;
+
+	NET_DBG("Max %lu receivers", ARRAY_SIZE(receivers));
+
+	for (i = 0; i < ARRAY_SIZE(receivers); i++) {
+		if (receivers[i].ctx != NULL) {
+			continue;
+		}
+
+		receivers[i].ctx = ctx;
+		receivers[i].iface = iface;
+		receivers[i].can_id = can_id;
+		receivers[i].can_mask = can_mask;
+
+		return i;
+	}
+
+	return -ENOENT;
+}
+
+static void can_unregister_receiver(struct net_if *iface,
+				    struct net_context *ctx,
+				    canid_t can_id, canid_t can_mask)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(receivers); i++) {
+		if (receivers[i].ctx == ctx &&
+		    receivers[i].iface == iface &&
+		    receivers[i].can_id == can_id &&
+		    receivers[i].can_mask == can_mask) {
+			receivers[i].ctx = NULL;
+			return;
+		}
+	}
+}
+
+static int can_register_filters(struct net_if *iface, struct net_context *ctx,
+				const struct can_filter *filters, int count)
+{
+	int i, ret;
+
+	NET_DBG("Registering %d filters", count);
+
+	for (i = 0; i < count; i++) {
+		ret = can_register_receiver(iface, ctx, filters[i].can_id,
+					    filters[i].can_mask);
+		if (ret < 0) {
+			goto revert;
+		}
+	}
+
+	return 0;
+
+revert:
+	for (i = 0; i < count; i++) {
+		can_unregister_receiver(iface, ctx, filters[i].can_id,
+					filters[i].can_mask);
+	}
+
+	return ret;
+}
+
+static void can_unregister_filters(struct net_if *iface,
+				   struct net_context *ctx,
+				   const struct can_filter *filters,
+				   int count)
+{
+	int i;
+
+	NET_DBG("Unregistering %d filters", count);
+
+	for (i = 0; i < count; i++) {
+		can_unregister_receiver(iface, ctx, filters[i].can_id,
+					filters[i].can_mask);
+	}
+}
+
+static int can_sock_setsockopt_vmeth(void *obj, int level, int optname,
+				     const void *optval, socklen_t optlen)
+{
+	const struct canbus_api *api;
+	struct net_if *iface;
+	const struct device *dev;
+	int ret;
+
+	if (level != SOL_CAN_RAW) {
+		return zcan_setsockopt_ctx(obj, level, optname, optval, optlen);
+	}
+
+	/* The application must use CAN_filter and then we convert
+	 * it to zcan_filter as the CANBUS drivers expects that.
+	 */
+	if (optname == CAN_RAW_FILTER && optlen != sizeof(struct can_filter)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (optval == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	iface = net_context_get_iface(obj);
+	dev = net_if_get_device(iface);
+	api = dev->api;
+
+	if (!api || !api->setsockopt) {
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	if (optname == CAN_RAW_FILTER) {
+		int count, i;
+
+		if (optlen % sizeof(struct can_filter) != 0) {
+			errno = EINVAL;
+			return -1;
+		}
+
+		count = optlen / sizeof(struct can_filter);
+
+		ret = can_register_filters(iface, obj, optval, count);
+		if (ret < 0) {
+			errno = -ret;
+			return -1;
+		}
+
+		for (i = 0; i < count; i++) {
+			struct can_filter *filter;
+			struct zcan_filter zfilter;
+			bool duplicate;
+
+			filter = &((struct can_filter *)optval)[i];
+
+			/* If someone has already attached the same filter to
+			 * same interface, we do not need to do it here again.
+			 */
+			duplicate = is_already_attached(filter, iface, obj);
+			if (duplicate) {
+				continue;
+			}
+
+			can_copy_filter_to_zfilter(filter, &zfilter);
+
+			ret = api->setsockopt(dev, obj, level, optname,
+					      &zfilter, sizeof(zfilter));
+			if (ret < 0) {
+				break;
+			}
+		}
+
+		if (ret < 0) {
+			can_unregister_filters(iface, obj, optval, count);
+
+			errno = -ret;
+			return -1;
+		}
+
+		return 0;
+	}
+
+	return api->setsockopt(dev, obj, level, optname, optval, optlen);
+}
+
+static const struct socket_op_vtable can_sock_fd_op_vtable = {
+	.fd_vtable = {
+		.read = can_sock_read_vmeth,
+		.write = can_sock_write_vmeth,
+		.close = can_sock_close_vmeth,
+		.ioctl = can_sock_ioctl_vmeth,
+	},
+	.bind = can_sock_bind_vmeth,
+	.connect = can_sock_connect_vmeth,
+	.listen = can_sock_listen_vmeth,
+	.accept = can_sock_accept_vmeth,
+	.sendto = can_sock_sendto_vmeth,
+	.recvfrom = can_sock_recvfrom_vmeth,
+	.getsockopt = can_sock_getsockopt_vmeth,
+	.setsockopt = can_sock_setsockopt_vmeth,
+};
+
+static bool can_is_supported(int family, int type, int proto)
+{
+	if (type != SOCK_RAW || proto != CAN_RAW) {
+		return false;
+	}
+
+	return true;
+}
+
+NET_SOCKET_REGISTER(af_can, AF_CAN, can_is_supported, zcan_socket);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_internal.h	(working copy)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _SOCKETS_INTERNAL_H_
+#define _SOCKETS_INTERNAL_H_
+
+#include <sys/fdtable.h>
+
+#define SOCK_EOF 1
+#define SOCK_NONBLOCK 2
+
+static inline void sock_set_flag(struct net_context *ctx, uintptr_t mask,
+				 uintptr_t flag)
+{
+	uintptr_t val = POINTER_TO_UINT(ctx->socket_data);
+
+	val = (val & ~mask) | flag;
+	(ctx)->socket_data = UINT_TO_POINTER(val);
+}
+
+static inline uintptr_t sock_get_flag(struct net_context *ctx, uintptr_t mask)
+{
+	return POINTER_TO_UINT(ctx->socket_data) & mask;
+}
+
+void net_socket_update_tc_rx_time(struct net_pkt *pkt, uint32_t end_tick);
+
+#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) && \
+    !defined(CONFIG_NET_SOCKETS_OFFLOAD_TLS)
+bool net_socket_is_tls(void *obj);
+#else
+static inline bool net_socket_is_tls(void *obj)
+{
+	ARG_UNUSED(obj);
+
+	return false;
+}
+#endif
+
+#define sock_is_eof(ctx) sock_get_flag(ctx, SOCK_EOF)
+#define sock_set_eof(ctx) sock_set_flag(ctx, SOCK_EOF, SOCK_EOF)
+#define sock_is_nonblock(ctx) sock_get_flag(ctx, SOCK_NONBLOCK)
+
+struct socket_op_vtable {
+	struct fd_op_vtable fd_vtable;
+	int (*bind)(void *obj, const struct sockaddr *addr, socklen_t addrlen);
+	int (*connect)(void *obj, const struct sockaddr *addr,
+		       socklen_t addrlen);
+	int (*listen)(void *obj, int backlog);
+	int (*accept)(void *obj, struct sockaddr *addr, socklen_t *addrlen);
+	ssize_t (*sendto)(void *obj, const void *buf, size_t len, int flags,
+			  const struct sockaddr *dest_addr, socklen_t addrlen);
+	ssize_t (*recvfrom)(void *obj, void *buf, size_t max_len, int flags,
+			    struct sockaddr *src_addr, socklen_t *addrlen);
+	int (*getsockopt)(void *obj, int level, int optname,
+			  void *optval, socklen_t *optlen);
+	int (*setsockopt)(void *obj, int level, int optname,
+			  const void *optval, socklen_t optlen);
+	ssize_t (*sendmsg)(void *obj, const struct msghdr *msg, int flags);
+	int (*getsockname)(void *obj, struct sockaddr *addr,
+			   socklen_t *addrlen);
+};
+
+#endif /* _SOCKETS_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_misc.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_misc.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_misc.c	(working copy)
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <net/socket.h>
+#include <syscall_handler.h>
+
+int z_impl_zsock_gethostname(char *buf, size_t len)
+{
+	const char *p = net_hostname_get();
+
+	strncpy(buf, p, len);
+
+	return 0;
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int z_vrfy_zsock_gethostname(char *buf, size_t len)
+{
+	Z_OOPS(Z_SYSCALL_MEMORY_WRITE(buf, len));
+	return z_impl_zsock_gethostname(buf, len);
+}
+#include <syscalls/zsock_gethostname_mrsh.c>
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_net_mgmt.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_net_mgmt.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_net_mgmt.c	(working copy)
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <fcntl.h>
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock_mgmt, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <sys/util.h>
+#include <net/socket.h>
+#include <syscall_handler.h>
+#include <sys/fdtable.h>
+#include <net/socket_net_mgmt.h>
+#include <net/ethernet_mgmt.h>
+
+#include "sockets_internal.h"
+#include "net_private.h"
+
+#define MSG_ALLOC_TIMEOUT K_MSEC(100)
+
+__net_socket struct net_mgmt_socket {
+	/* Network interface related to this socket */
+	struct net_if *iface;
+
+	/* A way to separate different sockets that listen same events */
+	uintptr_t pid;
+
+	/* net_mgmt mask */
+	uint32_t mask;
+
+	/* Message allocation timeout */
+	k_timeout_t alloc_timeout;
+
+	/* net_mgmt event timeout */
+	k_timeout_t wait_timeout;
+
+	/* Socket protocol */
+	int proto;
+
+	/* Is this entry in use (true) or not (false) */
+	uint8_t is_in_use : 1;
+};
+
+static struct net_mgmt_socket
+		mgmt_sockets[CONFIG_NET_SOCKETS_NET_MGMT_MAX_LISTENERS];
+
+static const struct socket_op_vtable net_mgmt_sock_fd_op_vtable;
+
+int znet_mgmt_socket(int family, int type, int proto)
+{
+	struct net_mgmt_socket *mgmt = NULL;
+	int fd, i;
+
+	for (i = 0; i < ARRAY_SIZE(mgmt_sockets); i++) {
+		if (mgmt_sockets[i].is_in_use) {
+			continue;
+		}
+
+		mgmt = &mgmt_sockets[i];
+	}
+
+	if (mgmt == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		errno = ENOSPC;
+		return -1;
+	}
+
+	mgmt->is_in_use = true;
+	mgmt->proto = proto;
+	mgmt->alloc_timeout = MSG_ALLOC_TIMEOUT;
+	mgmt->wait_timeout = K_FOREVER;
+
+	z_finalize_fd(fd, mgmt,
+		     (const struct fd_op_vtable *)&net_mgmt_sock_fd_op_vtable);
+
+	return fd;
+}
+
+static int znet_mgmt_bind(struct net_mgmt_socket *mgmt,
+			  const struct sockaddr *addr,
+			  socklen_t addrlen)
+{
+	struct sockaddr_nm *nm_addr = (struct sockaddr_nm *)addr;
+
+	if (addrlen != sizeof(struct sockaddr_nm)) {
+		return -EINVAL;
+	}
+
+	if (nm_addr->nm_ifindex) {
+		mgmt->iface = net_if_get_by_index(nm_addr->nm_ifindex);
+		if (!mgmt->iface) {
+			errno = ENOENT;
+			return -1;
+		}
+	} else {
+		mgmt->iface = NULL;
+	}
+
+	mgmt->pid = nm_addr->nm_pid;
+
+	if (mgmt->proto == NET_MGMT_EVENT_PROTO) {
+		mgmt->mask = nm_addr->nm_mask;
+
+		if (mgmt->iface) {
+			mgmt->mask |= NET_MGMT_IFACE_BIT;
+		}
+	}
+
+	return 0;
+}
+
+ssize_t znet_mgmt_sendto(struct net_mgmt_socket *mgmt,
+			 const void *buf, size_t len,
+			 int flags, const struct sockaddr *dest_addr,
+			 socklen_t addrlen)
+{
+	if (mgmt->proto == NET_MGMT_EVENT_PROTO) {
+		/* For net_mgmt events, we only listen and never send */
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	/* Add handling of other network management operations here when
+	 * needed.
+	 */
+
+	errno = EINVAL;
+	return -1;
+}
+
+static ssize_t znet_mgmt_recvfrom(struct net_mgmt_socket *mgmt, void *buf,
+				  size_t max_len, int flags,
+				  struct sockaddr *src_addr,
+				  socklen_t *addrlen)
+{
+	struct sockaddr_nm *nm_addr = (struct sockaddr_nm *)src_addr;
+	k_timeout_t timeout = mgmt->wait_timeout;
+	uint32_t raised_event = 0;
+	uint8_t *copy_to = buf;
+	struct net_mgmt_msghdr hdr;
+	struct net_if *iface;
+	const uint8_t *info;
+	size_t info_len;
+	int ret;
+
+	if (flags & ZSOCK_MSG_DONTWAIT) {
+		timeout = K_NO_WAIT;
+	}
+
+again:
+	if (mgmt->iface == NULL) {
+		ret = net_mgmt_event_wait(mgmt->mask, &raised_event,
+					  &iface, (const void **)&info,
+					  &info_len, timeout);
+	} else {
+		ret = net_mgmt_event_wait_on_iface(mgmt->iface,
+						   mgmt->mask,
+						   &raised_event,
+						   (const void **)&info,
+						   &info_len,
+						   timeout);
+		iface = mgmt->iface;
+	}
+
+	if (ret == -ETIMEDOUT) {
+		errno = EAGAIN;
+		return -1;
+	}
+
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	if ((mgmt->mask & raised_event) != raised_event) {
+		if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			goto again;
+		}
+
+		errno = EAGAIN;
+		return -1;
+	}
+
+	if (nm_addr) {
+		if (iface) {
+			nm_addr->nm_ifindex = net_if_get_by_iface(iface);
+		} else {
+			nm_addr->nm_ifindex = 0;
+		}
+
+		nm_addr->nm_pid = mgmt->pid;
+		nm_addr->nm_family = AF_NET_MGMT;
+		nm_addr->nm_mask = raised_event;
+	}
+
+	if (info) {
+		ret = info_len + sizeof(hdr);
+		ret = MIN(max_len, ret);
+		memcpy(&copy_to[sizeof(hdr)], info, ret);
+	} else {
+		ret = 0;
+	}
+
+	hdr.nm_msg_version = NET_MGMT_SOCKET_VERSION_1;
+	hdr.nm_msg_len = ret;
+
+	memcpy(copy_to, &hdr, sizeof(hdr));
+
+	return ret;
+}
+
+static int znet_mgmt_getsockopt(struct net_mgmt_socket *mgmt, int level,
+				int optname, void *optval, socklen_t *optlen)
+{
+	if (level != SOL_NET_MGMT_RAW || !optval || !optlen) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (mgmt->iface == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_L2_ETHERNET_MGMT)) {
+		if (optname == NET_REQUEST_ETHERNET_GET_QAV_PARAM) {
+			int ret;
+
+			ret = net_mgmt(NET_REQUEST_ETHERNET_GET_QAV_PARAM,
+				       mgmt->iface, (void *)optval, *optlen);
+			if (ret < 0) {
+				errno = -ret;
+				return -1;
+			}
+
+			return 0;
+
+		} else {
+			errno = EINVAL;
+			return -1;
+		}
+	}
+
+	errno = ENOTSUP;
+	return -1;
+}
+
+static int znet_mgmt_setsockopt(struct net_mgmt_socket *mgmt, int level,
+				int optname, const void *optval,
+				socklen_t optlen)
+{
+	if (level != SOL_NET_MGMT_RAW || !optval || !optlen) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (mgmt->iface == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_L2_ETHERNET_MGMT)) {
+		if (optname == NET_REQUEST_ETHERNET_SET_QAV_PARAM) {
+			int ret;
+
+			ret = net_mgmt(NET_REQUEST_ETHERNET_SET_QAV_PARAM,
+				       mgmt->iface, (void *)optval, optlen);
+			if (ret < 0) {
+				errno = -ret;
+				return -1;
+			}
+
+			return 0;
+		} else {
+			errno = EINVAL;
+			return -1;
+		}
+	}
+
+	errno = ENOTSUP;
+	return -1;
+}
+
+static ssize_t net_mgmt_sock_read(void *obj, void *buffer, size_t count)
+{
+	return znet_mgmt_recvfrom(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t net_mgmt_sock_write(void *obj, const void *buffer,
+				   size_t count)
+{
+	return znet_mgmt_sendto(obj, buffer, count, 0, NULL, 0);
+}
+
+static int net_mgmt_sock_ioctl(void *obj, unsigned int request,
+			       va_list args)
+{
+	return 0;
+}
+
+static int net_mgmt_sock_bind(void *obj, const struct sockaddr *addr,
+			      socklen_t addrlen)
+{
+	return znet_mgmt_bind(obj, addr, addrlen);
+}
+
+/* The connect() function is not needed */
+static int net_mgmt_sock_connect(void *obj, const struct sockaddr *addr,
+				 socklen_t addrlen)
+{
+	return 0;
+}
+
+/*
+ * The listen() and accept() functions are without any functionality.
+ */
+static int net_mgmt_sock_listen(void *obj, int backlog)
+{
+	return 0;
+}
+
+static int net_mgmt_sock_accept(void *obj, struct sockaddr *addr,
+				socklen_t *addrlen)
+{
+	return 0;
+}
+
+static ssize_t net_mgmt_sock_sendto(void *obj, const void *buf,
+				    size_t len, int flags,
+				    const struct sockaddr *dest_addr,
+				    socklen_t addrlen)
+{
+	return znet_mgmt_sendto(obj, buf, len, flags, dest_addr, addrlen);
+}
+
+static ssize_t net_mgmt_sock_recvfrom(void *obj, void *buf,
+				      size_t max_len, int flags,
+				      struct sockaddr *src_addr,
+				      socklen_t *addrlen)
+{
+	return znet_mgmt_recvfrom(obj, buf, max_len, flags,
+				  src_addr, addrlen);
+}
+
+static int net_mgmt_sock_getsockopt(void *obj, int level, int optname,
+				    void *optval, socklen_t *optlen)
+{
+	return znet_mgmt_getsockopt(obj, level, optname, optval, optlen);
+}
+
+static int net_mgmt_sock_setsockopt(void *obj, int level, int optname,
+				    const void *optval, socklen_t optlen)
+{
+	return znet_mgmt_setsockopt(obj, level, optname, optval, optlen);
+}
+
+static const struct socket_op_vtable net_mgmt_sock_fd_op_vtable = {
+	.fd_vtable = {
+		.read = net_mgmt_sock_read,
+		.write = net_mgmt_sock_write,
+		.ioctl = net_mgmt_sock_ioctl,
+	},
+	.bind = net_mgmt_sock_bind,
+	.connect = net_mgmt_sock_connect,
+	.listen = net_mgmt_sock_listen,
+	.accept = net_mgmt_sock_accept,
+	.sendto = net_mgmt_sock_sendto,
+	.recvfrom = net_mgmt_sock_recvfrom,
+	.getsockopt = net_mgmt_sock_getsockopt,
+	.setsockopt = net_mgmt_sock_setsockopt,
+};
+
+static bool net_mgmt_is_supported(int family, int type, int proto)
+{
+	if ((type != SOCK_RAW && type != SOCK_DGRAM) ||
+	    (proto != NET_MGMT_EVENT_PROTO)) {
+		return false;
+	}
+
+	return true;
+}
+
+NET_SOCKET_REGISTER(af_net_mgmt, AF_NET_MGMT, net_mgmt_is_supported,
+		    znet_mgmt_socket);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_packet.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_packet.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_packet.c	(working copy)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <fcntl.h>
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock_packet, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <kernel.h>
+#include <drivers/entropy.h>
+#include <sys/util.h>
+#include <net/net_context.h>
+#include <net/net_pkt.h>
+#include <net/socket.h>
+#include <net/ethernet.h>
+#include <syscall_handler.h>
+#include <sys/fdtable.h>
+
+#include "../../ip/net_stats.h"
+
+#include "sockets_internal.h"
+
+extern const struct socket_op_vtable sock_fd_op_vtable;
+
+static const struct socket_op_vtable packet_sock_fd_op_vtable;
+
+static inline int k_fifo_wait_non_empty(struct k_fifo *fifo,
+					k_timeout_t timeout)
+{
+	struct k_poll_event events[] = {
+		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
+					 K_POLL_MODE_NOTIFY_ONLY, fifo),
+	};
+
+	return k_poll(events, ARRAY_SIZE(events), timeout);
+}
+
+static int zpacket_socket(int family, int type, int proto)
+{
+	struct net_context *ctx;
+	int fd;
+	int ret;
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		return -1;
+	}
+
+	if (proto == 0) {
+		if (type == SOCK_RAW) {
+			proto = IPPROTO_RAW;
+		}
+	}
+
+	ret = net_context_get(family, type, proto, &ctx);
+	if (ret < 0) {
+		z_free_fd(fd);
+		errno = -ret;
+		return -1;
+	}
+
+	/* Initialize user_data, all other calls will preserve it */
+	ctx->user_data = NULL;
+
+	/* recv_q and accept_q are in union */
+	k_fifo_init(&ctx->recv_q);
+	z_finalize_fd(fd, ctx,
+		      (const struct fd_op_vtable *)&packet_sock_fd_op_vtable);
+
+	return fd;
+}
+
+static void zpacket_received_cb(struct net_context *ctx,
+				struct net_pkt *pkt,
+				union net_ip_header *ip_hdr,
+				union net_proto_header *proto_hdr,
+				int status,
+				void *user_data)
+{
+	NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
+		user_data);
+
+	/* if pkt is NULL, EOF */
+	if (!pkt) {
+		struct net_pkt *last_pkt = k_fifo_peek_tail(&ctx->recv_q);
+
+		if (!last_pkt) {
+			/* If there're no packets in the queue, recv() may
+			 * be blocked waiting on it to become non-empty,
+			 * so cancel that wait.
+			 */
+			sock_set_eof(ctx);
+			k_fifo_cancel_wait(&ctx->recv_q);
+			NET_DBG("Marked socket %p as peer-closed", ctx);
+		} else {
+			net_pkt_set_eof(last_pkt, true);
+			NET_DBG("Set EOF flag on pkt %p", ctx);
+		}
+
+		return;
+	}
+
+	/* Normal packet */
+	net_pkt_set_eof(pkt, false);
+
+	k_fifo_put(&ctx->recv_q, pkt);
+}
+
+static int zpacket_bind_ctx(struct net_context *ctx,
+			    const struct sockaddr *addr,
+			    socklen_t addrlen)
+{
+	int ret = 0;
+
+	ret = net_context_bind(ctx, addr, addrlen);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	/* For packet socket, we expect to receive packets after call
+	 * to bind().
+	 */
+	ret = net_context_recv(ctx, zpacket_received_cb, K_NO_WAIT,
+			       ctx->user_data);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	return 0;
+}
+
+ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
+			   int flags, const struct sockaddr *dest_addr,
+			   socklen_t addrlen)
+{
+	k_timeout_t timeout = K_FOREVER;
+	int status;
+
+	if (!dest_addr) {
+		errno = EDESTADDRREQ;
+		return -1;
+	}
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	/* Register the callback before sending in order to receive the response
+	 * from the peer.
+	 */
+
+	status = net_context_recv(ctx, zpacket_received_cb, K_NO_WAIT,
+				  ctx->user_data);
+	if (status < 0) {
+		errno = -status;
+		return -1;
+	}
+
+	status = net_context_sendto(ctx, buf, len, dest_addr, addrlen,
+				    NULL, timeout, ctx->user_data);
+	if (status < 0) {
+		errno = -status;
+		return -1;
+	}
+
+	return status;
+}
+
+ssize_t zpacket_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg,
+			    int flags)
+{
+	k_timeout_t timeout = K_FOREVER;
+	int status;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	status = net_context_sendmsg(ctx, msg, flags, NULL, timeout, NULL);
+	if (status < 0) {
+		errno = -status;
+		return -1;
+	}
+
+	return status;
+}
+
+ssize_t zpacket_recvfrom_ctx(struct net_context *ctx, void *buf, size_t max_len,
+			     int flags, struct sockaddr *src_addr,
+			     socklen_t *addrlen)
+{
+	size_t recv_len = 0;
+	k_timeout_t timeout = K_FOREVER;
+	struct net_pkt *pkt;
+
+	if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
+		timeout = K_NO_WAIT;
+	}
+
+	if (flags & ZSOCK_MSG_PEEK) {
+		int res;
+
+		res = k_fifo_wait_non_empty(&ctx->recv_q, timeout);
+		/* EAGAIN when timeout expired, EINTR when cancelled */
+		if (res && res != -EAGAIN && res != -EINTR) {
+			errno = -res;
+			return -1;
+		}
+
+		pkt = k_fifo_peek_head(&ctx->recv_q);
+	} else {
+		pkt = k_fifo_get(&ctx->recv_q, timeout);
+	}
+
+	if (!pkt) {
+		errno = EAGAIN;
+		return -1;
+	}
+
+	/* We do not handle any headers here,
+	 * just pass the whole packet to caller.
+	 */
+	recv_len = net_pkt_get_len(pkt);
+	if (recv_len > max_len) {
+		recv_len = max_len;
+	}
+
+	if (net_pkt_read(pkt, buf, recv_len)) {
+		errno = ENOBUFS;
+		return -1;
+	}
+
+
+	if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) &&
+	    !(flags & ZSOCK_MSG_PEEK)) {
+		net_socket_update_tc_rx_time(pkt, k_cycle_get_32());
+	}
+
+	if (!(flags & ZSOCK_MSG_PEEK)) {
+		net_pkt_unref(pkt);
+	} else {
+		net_pkt_cursor_init(pkt);
+	}
+
+	return recv_len;
+}
+
+int zpacket_getsockopt_ctx(struct net_context *ctx, int level, int optname,
+			   void *optval, socklen_t *optlen)
+{
+	if (!optval || !optlen) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	return sock_fd_op_vtable.getsockopt(ctx, level, optname,
+					    optval, optlen);
+}
+
+int zpacket_setsockopt_ctx(struct net_context *ctx, int level, int optname,
+			const void *optval, socklen_t optlen)
+{
+	return sock_fd_op_vtable.setsockopt(ctx, level, optname,
+					    optval, optlen);
+}
+
+static ssize_t packet_sock_read_vmeth(void *obj, void *buffer, size_t count)
+{
+	return zpacket_recvfrom_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t packet_sock_write_vmeth(void *obj, const void *buffer,
+				       size_t count)
+{
+	return zpacket_sendto_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static int packet_sock_ioctl_vmeth(void *obj, unsigned int request,
+				   va_list args)
+{
+	return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
+}
+
+/*
+ * TODO: A packet socket can be bound to a network device using SO_BINDTODEVICE.
+ */
+static int packet_sock_bind_vmeth(void *obj, const struct sockaddr *addr,
+				  socklen_t addrlen)
+{
+	return zpacket_bind_ctx(obj, addr, addrlen);
+}
+
+/* The connect() function is no longer necessary. */
+static int packet_sock_connect_vmeth(void *obj, const struct sockaddr *addr,
+				     socklen_t addrlen)
+{
+	return -EOPNOTSUPP;
+}
+
+/*
+ * The listen() and accept() functions are without any functionality,
+ * since the client-Server-Semantic is no longer present.
+ * When we use packet sockets we are sending unconnected packets.
+ */
+static int packet_sock_listen_vmeth(void *obj, int backlog)
+{
+	return -EOPNOTSUPP;
+}
+
+static int packet_sock_accept_vmeth(void *obj, struct sockaddr *addr,
+				    socklen_t *addrlen)
+{
+	return -EOPNOTSUPP;
+}
+
+static ssize_t packet_sock_sendto_vmeth(void *obj, const void *buf, size_t len,
+					int flags,
+					const struct sockaddr *dest_addr,
+					socklen_t addrlen)
+{
+	return zpacket_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
+}
+
+static ssize_t packet_sock_sendmsg_vmeth(void *obj, const struct msghdr *msg,
+					 int flags)
+{
+	return zpacket_sendmsg_ctx(obj, msg, flags);
+}
+
+static ssize_t packet_sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
+					  int flags, struct sockaddr *src_addr,
+					  socklen_t *addrlen)
+{
+	return zpacket_recvfrom_ctx(obj, buf, max_len, flags,
+				    src_addr, addrlen);
+}
+
+static int packet_sock_getsockopt_vmeth(void *obj, int level, int optname,
+					void *optval, socklen_t *optlen)
+{
+	return zpacket_getsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int packet_sock_setsockopt_vmeth(void *obj, int level, int optname,
+					const void *optval, socklen_t optlen)
+{
+	return zpacket_setsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static const struct socket_op_vtable packet_sock_fd_op_vtable = {
+	.fd_vtable = {
+		.read = packet_sock_read_vmeth,
+		.write = packet_sock_write_vmeth,
+		.ioctl = packet_sock_ioctl_vmeth,
+	},
+	.bind = packet_sock_bind_vmeth,
+	.connect = packet_sock_connect_vmeth,
+	.listen = packet_sock_listen_vmeth,
+	.accept = packet_sock_accept_vmeth,
+	.sendto = packet_sock_sendto_vmeth,
+	.sendmsg = packet_sock_sendmsg_vmeth,
+	.recvfrom = packet_sock_recvfrom_vmeth,
+	.getsockopt = packet_sock_getsockopt_vmeth,
+	.setsockopt = packet_sock_setsockopt_vmeth,
+};
+
+static bool packet_is_supported(int family, int type, int proto)
+{
+	if (((type == SOCK_RAW) && (proto == ETH_P_ALL)) ||
+	    ((type == SOCK_DGRAM) && (proto > 0))) {
+		return true;
+	}
+
+	return false;
+}
+
+NET_SOCKET_REGISTER(af_packet, AF_PACKET, packet_is_supported, zpacket_socket);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_select.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_select.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_select.c	(working copy)
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <net/socket.h>
+
+/* Get size, in elements, of an array within a struct. */
+#define STRUCT_MEMBER_ARRAY_SIZE(type, field) ARRAY_SIZE(((type *)0)->field)
+
+/* Returns results in word_idx and bit_mask "output" params */
+#define FD_SET_CALC_OFFSETS(set, word_idx, bit_mask) { \
+	unsigned int b_idx = fd % (sizeof(set->bitset[0]) * 8); \
+	word_idx = fd / (sizeof(set->bitset[0]) * 8); \
+	bit_mask = 1 << b_idx; \
+	}
+
+void ZSOCK_FD_ZERO(zsock_fd_set *set)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(set->bitset); i++) {
+		set->bitset[i] = 0U;
+	}
+}
+
+int ZSOCK_FD_ISSET(int fd, zsock_fd_set *set)
+{
+	uint32_t word_idx, bit_mask;
+
+	if (fd < 0 || fd >= ZSOCK_FD_SETSIZE) {
+		return 0;
+	}
+
+	FD_SET_CALC_OFFSETS(set, word_idx, bit_mask);
+
+	return (set->bitset[word_idx] & bit_mask) != 0U;
+}
+
+void ZSOCK_FD_CLR(int fd, zsock_fd_set *set)
+{
+	uint32_t word_idx, bit_mask;
+
+	if (fd < 0 || fd >= ZSOCK_FD_SETSIZE) {
+		return;
+	}
+
+	FD_SET_CALC_OFFSETS(set, word_idx, bit_mask);
+
+	set->bitset[word_idx] &= ~bit_mask;
+}
+
+void ZSOCK_FD_SET(int fd, zsock_fd_set *set)
+{
+	uint32_t word_idx, bit_mask;
+
+	if (fd < 0 || fd >= ZSOCK_FD_SETSIZE) {
+		return;
+	}
+
+	FD_SET_CALC_OFFSETS(set, word_idx, bit_mask);
+
+	set->bitset[word_idx] |= bit_mask;
+}
+
+int zsock_select(int nfds, zsock_fd_set *readfds, zsock_fd_set *writefds,
+		 zsock_fd_set *exceptfds, struct zsock_timeval *timeout)
+{
+	struct zsock_pollfd pfds[CONFIG_NET_SOCKETS_POLL_MAX];
+	int i, res, poll_timeout;
+	int num_pfds = 0;
+	int num_selects = 0;
+	int fd_no = 0;
+
+	for (i = 0; i < STRUCT_MEMBER_ARRAY_SIZE(zsock_fd_set, bitset); i++) {
+		uint32_t bit_mask = 1U;
+		uint32_t read_mask = 0U, write_mask = 0U, except_mask = 0U;
+		uint32_t ored_mask;
+
+		if (readfds != NULL) {
+			read_mask = readfds->bitset[i];
+		}
+
+		if (writefds != NULL) {
+			write_mask = writefds->bitset[i];
+		}
+
+		if (exceptfds != NULL) {
+			except_mask = exceptfds->bitset[i];
+		}
+
+		ored_mask = read_mask | write_mask | except_mask;
+		if (ored_mask == 0U) {
+			continue;
+		}
+
+		do {
+			if (ored_mask & bit_mask) {
+				int events = 0;
+
+				if (num_pfds >= ARRAY_SIZE(pfds)) {
+					errno = ENOMEM;
+					return -1;
+				}
+
+				if (read_mask & bit_mask) {
+					events |= ZSOCK_POLLIN;
+				}
+
+				if (write_mask & bit_mask) {
+					events |= ZSOCK_POLLOUT;
+				}
+
+				if (except_mask & bit_mask) {
+					events |= ZSOCK_POLLPRI;
+				}
+
+				pfds[num_pfds].fd = fd_no;
+				pfds[num_pfds++].events = events;
+			}
+
+			bit_mask <<= 1;
+			fd_no++;
+		} while (bit_mask != 0U);
+	}
+
+	poll_timeout = -1;
+	if (timeout != NULL) {
+		poll_timeout = timeout->tv_sec * 1000
+			       + timeout->tv_usec / 1000;
+	}
+
+	res = zsock_poll(pfds, num_pfds, poll_timeout);
+	if (res == -1) {
+		return -1;
+	}
+
+	if (readfds != NULL) {
+		ZSOCK_FD_ZERO(readfds);
+	}
+
+	if (writefds != NULL) {
+		ZSOCK_FD_ZERO(writefds);
+	}
+
+	if (exceptfds != NULL) {
+		ZSOCK_FD_ZERO(exceptfds);
+	}
+
+	for (i = 0; i < num_pfds && res > 0; i++) {
+		short revents = pfds[i].revents;
+		int fd = pfds[i].fd;
+
+		if (revents == 0) {
+			continue;
+		}
+
+		/* POSIX: "EBADF: One or more of the file descriptor sets
+		 * specified a file descriptor that is not a valid open
+		 * file descriptor."
+		 * So, unlike poll(), a single invalid fd aborts the entire
+		 * select().
+		 */
+		if (revents & ZSOCK_POLLNVAL) {
+			errno = EBADF;
+			return -1;
+		}
+
+		if (revents & ZSOCK_POLLIN) {
+			if (readfds != NULL) {
+				ZSOCK_FD_SET(fd, readfds);
+				num_selects++;
+			}
+		}
+
+		if (revents & ZSOCK_POLLOUT) {
+			if (writefds != NULL) {
+				ZSOCK_FD_SET(fd, writefds);
+				num_selects++;
+			}
+		}
+
+		/* It's unclear if HUP/ERR belong here. At least not ignore
+		 * them. Zephyr doesn't use HUP and barely use ERR so far.
+		 */
+		if (revents & (ZSOCK_POLLPRI | ZSOCK_POLLHUP | ZSOCK_POLLERR)) {
+			if (exceptfds != NULL) {
+				ZSOCK_FD_SET(fd, exceptfds);
+				num_selects++;
+			}
+		}
+
+		res--;
+	}
+
+	return num_selects;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_tls.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_tls.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/sockets/sockets_tls.c	(working copy)
@@ -0,0 +1,2161 @@
+/*
+ * Copyright (c) 2018 Intel Corporation
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <fcntl.h>
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_sock_tls, CONFIG_NET_SOCKETS_LOG_LEVEL);
+
+#include <init.h>
+#include <drivers/entropy.h>
+#include <sys/util.h>
+#include <net/socket.h>
+#include <random/rand32.h>
+#include <syscall_handler.h>
+#include <sys/fdtable.h>
+
+#if defined(CONFIG_MBEDTLS)
+#if !defined(CONFIG_MBEDTLS_CFG_FILE)
+#include "mbedtls/config.h"
+#else
+#include CONFIG_MBEDTLS_CFG_FILE
+#endif /* CONFIG_MBEDTLS_CFG_FILE */
+
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/net_sockets.h>
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/ssl.h>
+#include <mbedtls/ssl_cookie.h>
+#include <mbedtls/error.h>
+#include <mbedtls/debug.h>
+#endif /* CONFIG_MBEDTLS */
+
+#include "sockets_internal.h"
+#include "tls_internal.h"
+
+static const struct socket_op_vtable tls_sock_fd_op_vtable;
+
+/** A list of secure tags that TLS context should use. */
+struct sec_tag_list {
+	/** An array of secure tags referencing TLS credentials. */
+	sec_tag_t sec_tags[CONFIG_NET_SOCKETS_TLS_MAX_CREDENTIALS];
+
+	/** Number of configured secure tags. */
+	int sec_tag_count;
+};
+
+/** Timer context for DTLS. */
+struct dtls_timing_context {
+	/** Current time, stored during timer set. */
+	uint32_t snapshot;
+
+	/** Intermediate delay value. For details, refer to mbedTLS API
+	 *  documentation (mbedtls_ssl_set_timer_t).
+	 */
+	uint32_t int_ms;
+
+	/** Final delay value. For details, refer to mbedTLS API documentation
+	 *  (mbedtls_ssl_set_timer_t).
+	 */
+	uint32_t fin_ms;
+};
+
+/** TLS context information. */
+struct tls_context {
+	/** Information whether TLS context is used. */
+	bool is_used;
+
+	/** Underlying TCP/UDP socket. */
+	int sock;
+
+	/** Socket type. */
+	enum net_sock_type type;
+
+	/** Secure protocol version running on TLS context. */
+	enum net_ip_protocol_secure tls_version;
+
+	/** Socket flags passed to a socket call. */
+	int flags;
+
+	/** Information whether TLS context was initialized. */
+	bool is_initialized;
+
+	/** Information whether underlying socket is listening. */
+	bool is_listening;
+
+	/** Information whether TLS handshake is complete or not. */
+	struct k_sem tls_established;
+
+	/** TLS specific option values. */
+	struct {
+		/** Select which credentials to use with TLS. */
+		struct sec_tag_list sec_tag_list;
+
+		/** 0-terminated list of allowed ciphersuites (mbedTLS format).
+		 */
+		int ciphersuites[CONFIG_NET_SOCKETS_TLS_MAX_CIPHERSUITES + 1];
+
+		/** Information if hostname was explicitly set on a socket. */
+		bool is_hostname_set;
+
+		/** Peer verification level. */
+		int8_t verify_level;
+
+		/** DTLS role, client by default. */
+		int8_t role;
+	} options;
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	/** Context information for DTLS timing. */
+	struct dtls_timing_context dtls_timing;
+
+	/** mbedTLS cookie context for DTLS */
+	mbedtls_ssl_cookie_ctx cookie;
+
+	/** DTLS peer address. */
+	struct sockaddr dtls_peer_addr;
+
+	/** DTLS peer address length. */
+	socklen_t dtls_peer_addrlen;
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+#if defined(CONFIG_MBEDTLS)
+	/** mbedTLS context. */
+	mbedtls_ssl_context ssl;
+
+	/** mbedTLS configuration. */
+	mbedtls_ssl_config config;
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	/** mbedTLS structure for CA chain. */
+	mbedtls_x509_crt ca_chain;
+
+	/** mbedTLS structure for own certificate. */
+	mbedtls_x509_crt own_cert;
+
+	/** mbedTLS structure for own private key. */
+	mbedtls_pk_context priv_key;
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+#endif /* CONFIG_MBEDTLS */
+};
+
+#if defined(CONFIG_ENTROPY_HAS_DRIVER)
+static const struct device *entropy_dev;
+#endif
+
+static mbedtls_ctr_drbg_context tls_ctr_drbg;
+
+/* A global pool of TLS contexts. */
+static struct tls_context tls_contexts[CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS];
+
+/* A mutex for protecting TLS context allocation. */
+static struct k_mutex context_lock;
+
+bool net_socket_is_tls(void *obj)
+{
+	return PART_OF_ARRAY(tls_contexts, (struct tls_context *)obj);
+}
+
+#if defined(MBEDTLS_DEBUG_C) && (CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG)
+static void tls_debug(void *ctx, int level, const char *file,
+		      int line, const char *str)
+{
+	const char *p, *basename;
+
+	ARG_UNUSED(ctx);
+
+	if (!file || !str) {
+		return;
+	}
+
+	/* Extract basename from file */
+	for (p = basename = file; *p != '\0'; p++) {
+		if (*p == '/' || *p == '\\') {
+			basename = p + 1;
+		}
+	}
+
+	NET_DBG("%s:%04d: |%d| %s", basename, line, level,
+		log_strdup(str));
+}
+#endif /* defined(MBEDTLS_DEBUG_C) && (CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG) */
+
+#if defined(CONFIG_ENTROPY_HAS_DRIVER)
+static int tls_entropy_func(void *ctx, unsigned char *buf, size_t len)
+{
+	ARG_UNUSED(ctx);
+
+	return entropy_get_entropy(entropy_dev, buf, len);
+}
+#else
+static int tls_entropy_func(void *ctx, unsigned char *buf, size_t len)
+{
+	ARG_UNUSED(ctx);
+
+	size_t i = len / 4;
+	uint32_t val;
+
+	while (i--) {
+		val = sys_rand32_get();
+		UNALIGNED_PUT(val, (uint32_t *)buf);
+		buf += 4;
+	}
+
+	i = len & 0x3;
+	val = sys_rand32_get();
+	while (i--) {
+		*buf++ = val;
+		val >>= 8;
+	}
+
+	return 0;
+}
+#endif /* defined(CONFIG_ENTROPY_HAS_DRIVER) */
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+/* mbedTLS-defined function for setting timer. */
+static void dtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms)
+{
+	struct dtls_timing_context *ctx = data;
+
+	ctx->int_ms = int_ms;
+	ctx->fin_ms = fin_ms;
+
+	if (fin_ms != 0U) {
+		ctx->snapshot = k_uptime_get_32();
+	}
+}
+
+/* mbedTLS-defined function for getting timer status.
+ * The return values are specified by mbedTLS. The callback must return:
+ *   -1 if cancelled (fin_ms == 0),
+ *    0 if none of the delays have passed,
+ *    1 if only the intermediate delay has passed,
+ *    2 if the final delay has passed.
+ */
+static int dtls_timing_get_delay(void *data)
+{
+	struct dtls_timing_context *timing = data;
+	unsigned long elapsed_ms;
+
+	NET_ASSERT(timing);
+
+	if (timing->fin_ms == 0U) {
+		return -1;
+	}
+
+	elapsed_ms = k_uptime_get_32() - timing->snapshot;
+
+	if (elapsed_ms >= timing->fin_ms) {
+		return 2;
+	}
+
+	if (elapsed_ms >= timing->int_ms) {
+		return 1;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+/* Initialize TLS internals. */
+static int tls_init(const struct device *unused)
+{
+	ARG_UNUSED(unused);
+
+	int ret;
+	static const unsigned char drbg_seed[] = "zephyr";
+
+#if defined(CONFIG_ENTROPY_HAS_DRIVER)
+	entropy_dev = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
+	if (!entropy_dev) {
+		NET_ERR("Failed to obtain entropy device");
+		return -ENODEV;
+	}
+#else
+	NET_WARN("No entropy device on the system, "
+		 "TLS communication may be insecure!");
+#endif /* defined(CONFIG_ENTROPY_HAS_DRIVER) */
+
+	(void)memset(tls_contexts, 0, sizeof(tls_contexts));
+
+	k_mutex_init(&context_lock);
+
+	mbedtls_ctr_drbg_init(&tls_ctr_drbg);
+
+	ret = mbedtls_ctr_drbg_seed(&tls_ctr_drbg, tls_entropy_func, NULL,
+				    drbg_seed, sizeof(drbg_seed));
+	if (ret != 0) {
+		mbedtls_ctr_drbg_free(&tls_ctr_drbg);
+		NET_ERR("TLS entropy source initialization failed");
+		return -EFAULT;
+	}
+
+#if defined(MBEDTLS_DEBUG_C) && (CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG)
+	mbedtls_debug_set_threshold(CONFIG_MBEDTLS_DEBUG_LEVEL);
+#endif
+
+	return 0;
+}
+
+SYS_INIT(tls_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
+
+static inline bool is_handshake_complete(struct tls_context *ctx)
+{
+	return k_sem_count_get(&ctx->tls_established) != 0;
+}
+
+/* Allocate TLS context. */
+static struct tls_context *tls_alloc(void)
+{
+	int i;
+	struct tls_context *tls = NULL;
+
+	k_mutex_lock(&context_lock, K_FOREVER);
+
+	for (i = 0; i < ARRAY_SIZE(tls_contexts); i++) {
+		if (!tls_contexts[i].is_used) {
+			tls = &tls_contexts[i];
+			(void)memset(tls, 0, sizeof(*tls));
+			tls->is_used = true;
+			tls->options.verify_level = -1;
+			tls->sock = -1;
+
+			NET_DBG("Allocated TLS context, %p", tls);
+			break;
+		}
+	}
+
+	k_mutex_unlock(&context_lock);
+
+	if (tls) {
+		k_sem_init(&tls->tls_established, 0, 1);
+
+		mbedtls_ssl_init(&tls->ssl);
+		mbedtls_ssl_config_init(&tls->config);
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+		mbedtls_ssl_cookie_init(&tls->cookie);
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+		mbedtls_x509_crt_init(&tls->ca_chain);
+		mbedtls_x509_crt_init(&tls->own_cert);
+		mbedtls_pk_init(&tls->priv_key);
+#endif
+
+#if defined(MBEDTLS_DEBUG_C) && (CONFIG_NET_SOCKETS_LOG_LEVEL >= LOG_LEVEL_DBG)
+		mbedtls_ssl_conf_dbg(&tls->config, tls_debug, NULL);
+#endif
+	} else {
+		NET_WARN("Failed to allocate TLS context");
+	}
+
+	return tls;
+}
+
+/* Allocate new TLS context and copy the content from the source context. */
+static struct tls_context *tls_clone(struct tls_context *source_tls)
+{
+	struct tls_context *target_tls;
+
+	target_tls = tls_alloc();
+	if (!target_tls) {
+		return NULL;
+	}
+
+	target_tls->tls_version = source_tls->tls_version;
+	target_tls->type = source_tls->type;
+
+	memcpy(&target_tls->options, &source_tls->options,
+	       sizeof(target_tls->options));
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	if (target_tls->options.is_hostname_set) {
+		mbedtls_ssl_set_hostname(&target_tls->ssl,
+					 source_tls->ssl.hostname);
+	}
+#endif
+
+	return target_tls;
+}
+
+/* Release TLS context. */
+static int tls_release(struct tls_context *tls)
+{
+	if (!PART_OF_ARRAY(tls_contexts, tls)) {
+		NET_ERR("Invalid TLS context");
+		return -EBADF;
+	}
+
+	if (!tls->is_used) {
+		NET_ERR("Deallocating unused TLS context");
+		return -EBADF;
+	}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	mbedtls_ssl_cookie_free(&tls->cookie);
+#endif
+	mbedtls_ssl_config_free(&tls->config);
+	mbedtls_ssl_free(&tls->ssl);
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	mbedtls_x509_crt_free(&tls->ca_chain);
+	mbedtls_x509_crt_free(&tls->own_cert);
+	mbedtls_pk_free(&tls->priv_key);
+#endif
+
+	tls->is_used = false;
+
+	return 0;
+}
+
+static inline int time_left(uint32_t start, uint32_t timeout)
+{
+	uint32_t elapsed = k_uptime_get_32() - start;
+
+	return timeout - elapsed;
+}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+static bool dtls_is_peer_addr_valid(struct tls_context *context,
+				    const struct sockaddr *peer_addr,
+				    socklen_t addrlen)
+{
+	if (context->dtls_peer_addrlen != addrlen ||
+	    context->dtls_peer_addr.sa_family != peer_addr->sa_family) {
+		return false;
+	}
+
+	if (IS_ENABLED(CONFIG_NET_IPV6) && peer_addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *addr1 = net_sin6(peer_addr);
+		struct sockaddr_in6 *addr2 =
+				net_sin6(&context->dtls_peer_addr);
+
+		return (addr1->sin6_port == addr2->sin6_port) &&
+			net_ipv6_addr_cmp(&addr1->sin6_addr, &addr2->sin6_addr);
+	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
+		   peer_addr->sa_family == AF_INET) {
+		struct sockaddr_in *addr1 = net_sin(peer_addr);
+		struct sockaddr_in *addr2 =
+				net_sin(&context->dtls_peer_addr);
+
+		return (addr1->sin_port == addr2->sin_port) &&
+			net_ipv4_addr_cmp(&addr1->sin_addr, &addr2->sin_addr);
+	}
+
+	return false;
+}
+
+static void dtls_peer_address_set(struct tls_context *context,
+				  const struct sockaddr *peer_addr,
+				  socklen_t addrlen)
+{
+	if (addrlen <= sizeof(context->dtls_peer_addr)) {
+		memcpy(&context->dtls_peer_addr, peer_addr, addrlen);
+		context->dtls_peer_addrlen = addrlen;
+	}
+}
+
+static void dtls_peer_address_get(struct tls_context *context,
+				  struct sockaddr *peer_addr,
+				  socklen_t *addrlen)
+{
+	socklen_t len = MIN(context->dtls_peer_addrlen, *addrlen);
+
+	memcpy(peer_addr, &context->dtls_peer_addr, len);
+	*addrlen = len;
+}
+
+static int dtls_tx(void *ctx, const unsigned char *buf, size_t len)
+{
+	struct tls_context *tls_ctx = ctx;
+	ssize_t sent;
+
+	sent = zsock_sendto(tls_ctx->sock, buf, len, tls_ctx->flags,
+			    &tls_ctx->dtls_peer_addr,
+			    tls_ctx->dtls_peer_addrlen);
+	if (sent < 0) {
+		if (errno == EAGAIN) {
+			return MBEDTLS_ERR_SSL_WANT_WRITE;
+		}
+
+		return MBEDTLS_ERR_NET_SEND_FAILED;
+	}
+
+	return sent;
+}
+
+static int dtls_rx(void *ctx, unsigned char *buf, size_t len,
+		   uint32_t dtls_timeout)
+{
+	struct tls_context *tls_ctx = ctx;
+	bool is_block = !((tls_ctx->flags & ZSOCK_MSG_DONTWAIT) ||
+			  (zsock_fcntl(tls_ctx->sock, F_GETFL, 0) &
+			   O_NONBLOCK));
+	int timeout = (dtls_timeout == 0U) ? -1 : dtls_timeout;
+	uint32_t entry_time = k_uptime_get_32();
+	socklen_t addrlen = sizeof(struct sockaddr);
+	struct sockaddr addr;
+	int err;
+	ssize_t received;
+	bool retry;
+	struct zsock_pollfd fds;
+
+	do {
+		retry = false;
+
+		/* mbedtLS does not allow blocking rx for DTLS, therefore use
+		 * k_poll for timeout functionality.
+		 */
+		if (is_block) {
+			fds.fd = tls_ctx->sock;
+			fds.events = ZSOCK_POLLIN;
+
+			if (zsock_poll(&fds, 1, timeout) == 0) {
+				return MBEDTLS_ERR_SSL_TIMEOUT;
+			}
+		}
+
+		received = zsock_recvfrom(
+				tls_ctx->sock, buf, len, tls_ctx->flags,
+				&addr, &addrlen);
+		if (received < 0) {
+			if (errno == EAGAIN) {
+				return MBEDTLS_ERR_SSL_WANT_READ;
+			}
+
+			return MBEDTLS_ERR_NET_RECV_FAILED;
+		}
+
+		if (tls_ctx->dtls_peer_addrlen == 0) {
+			/* Only allow to store peer address for DTLS servers. */
+			if (tls_ctx->options.role == MBEDTLS_SSL_IS_SERVER) {
+				dtls_peer_address_set(tls_ctx, &addr, addrlen);
+
+				err = mbedtls_ssl_set_client_transport_id(
+					&tls_ctx->ssl,
+					(const unsigned char *)&addr, addrlen);
+				if (err < 0) {
+					return err;
+				}
+			} else {
+				/* For clients it's incorrect to receive when
+				 * no peer has been set up.
+				 */
+				return MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED;
+			}
+		} else if (!dtls_is_peer_addr_valid(tls_ctx, &addr, addrlen)) {
+			/* Received data from different peer, ignore it. */
+			retry = true;
+
+			if (timeout != -1) {
+				/* Recalculate the timeout value. */
+				timeout = time_left(entry_time, dtls_timeout);
+
+				if (timeout <= 0) {
+					return MBEDTLS_ERR_SSL_TIMEOUT;
+				}
+			}
+		}
+	} while (retry);
+
+	return received;
+}
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+static int tls_tx(void *ctx, const unsigned char *buf, size_t len)
+{
+	struct tls_context *tls_ctx = ctx;
+	ssize_t sent;
+
+	sent = zsock_sendto(tls_ctx->sock, buf, len,
+			    tls_ctx->flags, NULL, 0);
+	if (sent < 0) {
+		if (errno == EAGAIN) {
+			return MBEDTLS_ERR_SSL_WANT_WRITE;
+		}
+
+		return MBEDTLS_ERR_NET_SEND_FAILED;
+	}
+
+	return sent;
+}
+
+static int tls_rx(void *ctx, unsigned char *buf, size_t len)
+{
+	struct tls_context *tls_ctx = ctx;
+	ssize_t received;
+
+	received = zsock_recvfrom(tls_ctx->sock, buf, len,
+				  tls_ctx->flags, NULL, 0);
+	if (received < 0) {
+		if (errno == EAGAIN) {
+			return MBEDTLS_ERR_SSL_WANT_READ;
+		}
+
+		return MBEDTLS_ERR_NET_RECV_FAILED;
+	}
+
+	return received;
+}
+
+static int tls_add_ca_certificate(struct tls_context *tls,
+				  struct tls_credential *ca_cert)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	int err = mbedtls_x509_crt_parse(&tls->ca_chain,
+					 ca_cert->buf, ca_cert->len);
+	if (err != 0) {
+		return -EINVAL;
+	}
+
+	return 0;
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+	return -ENOTSUP;
+}
+
+static void tls_set_ca_chain(struct tls_context *tls)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	mbedtls_ssl_conf_ca_chain(&tls->config, &tls->ca_chain, NULL);
+	mbedtls_ssl_conf_cert_profile(&tls->config,
+				      &mbedtls_x509_crt_profile_default);
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+}
+
+static int tls_set_own_cert(struct tls_context *tls,
+			    struct tls_credential *own_cert,
+			    struct tls_credential *priv_key)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	int err = mbedtls_x509_crt_parse(&tls->own_cert,
+					 own_cert->buf, own_cert->len);
+	if (err != 0) {
+		return -EINVAL;
+	}
+
+	err = mbedtls_pk_parse_key(&tls->priv_key, priv_key->buf,
+				   priv_key->len, NULL, 0);
+	if (err != 0) {
+		return -EINVAL;
+	}
+
+	err = mbedtls_ssl_conf_own_cert(&tls->config, &tls->own_cert,
+					&tls->priv_key);
+	if (err != 0) {
+		err = -ENOMEM;
+	}
+
+	return 0;
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+	return -ENOTSUP;
+}
+
+static int tls_set_psk(struct tls_context *tls,
+		       struct tls_credential *psk,
+		       struct tls_credential *psk_id)
+{
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
+	int err = mbedtls_ssl_conf_psk(&tls->config,
+				       psk->buf, psk->len,
+				       (const unsigned char *)psk_id->buf,
+				       psk_id->len);
+	if (err != 0) {
+		return -EINVAL;
+	}
+
+	return 0;
+#endif
+
+	return -ENOTSUP;
+}
+
+static int tls_set_credential(struct tls_context *tls,
+			      struct tls_credential *cred)
+{
+	switch (cred->type) {
+	case TLS_CREDENTIAL_CA_CERTIFICATE:
+		return tls_add_ca_certificate(tls, cred);
+
+	case TLS_CREDENTIAL_SERVER_CERTIFICATE:
+	{
+		struct tls_credential *priv_key =
+			credential_get(cred->tag, TLS_CREDENTIAL_PRIVATE_KEY);
+		if (!priv_key) {
+			return -ENOENT;
+		}
+
+		return tls_set_own_cert(tls, cred, priv_key);
+	}
+
+	case TLS_CREDENTIAL_PRIVATE_KEY:
+		/* Ignore private key - it will be used together
+		 * with public certificate
+		 */
+		break;
+
+	case TLS_CREDENTIAL_PSK:
+	{
+		struct tls_credential *psk_id =
+			credential_get(cred->tag, TLS_CREDENTIAL_PSK_ID);
+		if (!psk_id) {
+			return -ENOENT;
+		}
+
+		return tls_set_psk(tls, cred, psk_id);
+	}
+
+	case TLS_CREDENTIAL_PSK_ID:
+		/* Ignore PSK ID - it will be used together
+		 * with PSK
+		 */
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tls_mbedtls_set_credentials(struct tls_context *tls)
+{
+	struct tls_credential *cred;
+	sec_tag_t tag;
+	int i, err = 0;
+	bool tag_found, ca_cert_present = false;
+
+	credentials_lock();
+
+	for (i = 0; i < tls->options.sec_tag_list.sec_tag_count; i++) {
+		tag = tls->options.sec_tag_list.sec_tags[i];
+		cred = NULL;
+		tag_found = false;
+
+		while ((cred = credential_next_get(tag, cred)) != NULL) {
+			tag_found = true;
+
+			err = tls_set_credential(tls, cred);
+			if (err != 0) {
+				goto exit;
+			}
+
+			if (cred->type == TLS_CREDENTIAL_CA_CERTIFICATE) {
+				ca_cert_present = true;
+			}
+		}
+
+		if (!tag_found) {
+			err = -ENOENT;
+			goto exit;
+		}
+	}
+
+exit:
+	credentials_unlock();
+
+	if (err == 0 && ca_cert_present) {
+		tls_set_ca_chain(tls);
+	}
+
+	return err;
+}
+
+static int tls_mbedtls_reset(struct tls_context *context)
+{
+	int ret;
+
+	ret = mbedtls_ssl_session_reset(&context->ssl);
+	if (ret != 0) {
+		return ret;
+	}
+
+	k_sem_init(&context->tls_established, 0, 1);
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	(void)memset(&context->dtls_peer_addr, 0,
+		     sizeof(context->dtls_peer_addr));
+	context->dtls_peer_addrlen = 0;
+#endif
+
+	return 0;
+}
+
+static int tls_mbedtls_handshake(struct tls_context *context, bool block)
+{
+	int ret;
+
+	while ((ret = mbedtls_ssl_handshake(&context->ssl)) != 0) {
+		if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
+		    ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+			if (block) {
+				continue;
+			}
+
+			ret = -EAGAIN;
+			break;
+		} else if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
+			ret = tls_mbedtls_reset(context);
+			if (ret == 0) {
+				if (block) {
+					continue;
+				}
+
+				ret = -EAGAIN;
+				break;
+			}
+		}
+
+		NET_ERR("TLS handshake error: -%x", -ret);
+		ret = -ECONNABORTED;
+		break;
+	}
+
+	if (ret == 0) {
+		k_sem_give(&context->tls_established);
+	}
+
+	return ret;
+}
+
+static int tls_mbedtls_init(struct tls_context *context, bool is_server)
+{
+	int role, type, ret;
+
+	role = is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT;
+
+	type = (context->type == SOCK_STREAM) ?
+		MBEDTLS_SSL_TRANSPORT_STREAM :
+		MBEDTLS_SSL_TRANSPORT_DATAGRAM;
+
+	if (type == MBEDTLS_SSL_TRANSPORT_STREAM) {
+		mbedtls_ssl_set_bio(&context->ssl, context,
+				    tls_tx, tls_rx, NULL);
+	} else {
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+		mbedtls_ssl_set_bio(&context->ssl, context,
+				    dtls_tx, NULL, dtls_rx);
+#else
+		return -ENOTSUP;
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+	}
+
+	ret = mbedtls_ssl_config_defaults(&context->config, role, type,
+					  MBEDTLS_SSL_PRESET_DEFAULT);
+	if (ret != 0) {
+		/* According to mbedTLS API documentation,
+		 * mbedtls_ssl_config_defaults can fail due to memory
+		 * allocation failure
+		 */
+		return -ENOMEM;
+	}
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+	mbedtls_ssl_conf_legacy_renegotiation(&context->config,
+					   MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE);
+	mbedtls_ssl_conf_renegotiation(&context->config,
+				       MBEDTLS_SSL_RENEGOTIATION_ENABLED);
+#endif
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	if (type == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+		/* DTLS requires timer callbacks to operate */
+		mbedtls_ssl_set_timer_cb(&context->ssl,
+					 &context->dtls_timing,
+					 dtls_timing_set_delay,
+					 dtls_timing_get_delay);
+
+		/* Configure cookie for DTLS server */
+		if (role == MBEDTLS_SSL_IS_SERVER) {
+			ret = mbedtls_ssl_cookie_setup(&context->cookie,
+						       mbedtls_ctr_drbg_random,
+						       &tls_ctr_drbg);
+			if (ret != 0) {
+				return -ENOMEM;
+			}
+
+			mbedtls_ssl_conf_dtls_cookies(&context->config,
+						      mbedtls_ssl_cookie_write,
+						      mbedtls_ssl_cookie_check,
+						      &context->cookie);
+
+			mbedtls_ssl_conf_read_timeout(
+					&context->config,
+					CONFIG_NET_SOCKETS_DTLS_TIMEOUT);
+		}
+	}
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	/* For TLS clients, set hostname to empty string to enforce it's
+	 * verification - only if hostname option was not set. Otherwise
+	 * depend on user configuration.
+	 */
+	if (!is_server && !context->options.is_hostname_set) {
+		mbedtls_ssl_set_hostname(&context->ssl, "");
+	}
+#endif
+
+	/* If verification level was specified explicitly, set it. Otherwise,
+	 * use mbedTLS default values (required for client, none for server)
+	 */
+	if (context->options.verify_level != -1) {
+		mbedtls_ssl_conf_authmode(&context->config,
+					  context->options.verify_level);
+	}
+
+	mbedtls_ssl_conf_rng(&context->config,
+			     mbedtls_ctr_drbg_random,
+			     &tls_ctr_drbg);
+
+	ret = tls_mbedtls_set_credentials(context);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = mbedtls_ssl_setup(&context->ssl,
+				&context->config);
+	if (ret != 0) {
+		/* According to mbedTLS API documentation,
+		 * mbedtls_ssl_setup can fail due to memory allocation failure
+		 */
+		return -ENOMEM;
+	}
+
+	context->is_initialized = true;
+
+	return 0;
+}
+
+static int tls_opt_sec_tag_list_set(struct tls_context *context,
+				    const void *optval, socklen_t optlen)
+{
+	int sec_tag_cnt;
+
+	if (!optval) {
+		return -EINVAL;
+	}
+
+	if (optlen % sizeof(sec_tag_t) != 0) {
+		return -EINVAL;
+	}
+
+	sec_tag_cnt = optlen / sizeof(sec_tag_t);
+	if (sec_tag_cnt >
+		ARRAY_SIZE(context->options.sec_tag_list.sec_tags)) {
+		return -EINVAL;
+	}
+
+	memcpy(context->options.sec_tag_list.sec_tags, optval, optlen);
+	context->options.sec_tag_list.sec_tag_count = sec_tag_cnt;
+
+	return 0;
+}
+
+static int tls_opt_sec_tag_list_get(struct tls_context *context,
+				    void *optval, socklen_t *optlen)
+{
+	int len;
+
+	if (*optlen % sizeof(sec_tag_t) != 0 || *optlen == 0) {
+		return -EINVAL;
+	}
+
+	len = MIN(context->options.sec_tag_list.sec_tag_count *
+		  sizeof(sec_tag_t), *optlen);
+
+	memcpy(optval, context->options.sec_tag_list.sec_tags, len);
+	*optlen = len;
+
+	return 0;
+}
+
+static int tls_opt_hostname_set(struct tls_context *context,
+				const void *optval, socklen_t optlen)
+{
+	ARG_UNUSED(optlen);
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+	if (mbedtls_ssl_set_hostname(&context->ssl, optval) != 0) {
+		return -EINVAL;
+	}
+#else
+	return -ENOPROTOOPT;
+#endif
+
+	context->options.is_hostname_set = true;
+
+	return 0;
+}
+
+static int tls_opt_ciphersuite_list_set(struct tls_context *context,
+					const void *optval, socklen_t optlen)
+{
+	int cipher_cnt;
+
+	if (!optval) {
+		return -EINVAL;
+	}
+
+	if (optlen % sizeof(int) != 0) {
+		return -EINVAL;
+	}
+
+	cipher_cnt = optlen / sizeof(int);
+
+	/* + 1 for 0-termination. */
+	if (cipher_cnt + 1 > ARRAY_SIZE(context->options.ciphersuites)) {
+		return -EINVAL;
+	}
+
+	memcpy(context->options.ciphersuites, optval, optlen);
+	context->options.ciphersuites[cipher_cnt] = 0;
+
+	return 0;
+}
+
+static int tls_opt_ciphersuite_list_get(struct tls_context *context,
+					void *optval, socklen_t *optlen)
+{
+	const int *selected_ciphers;
+	int cipher_cnt, i = 0;
+	int *ciphers = optval;
+
+	if (*optlen % sizeof(int) != 0 || *optlen == 0) {
+		return -EINVAL;
+	}
+
+	if (context->options.ciphersuites[0] == 0) {
+		/* No specific ciphersuites configured, return all available. */
+		selected_ciphers = mbedtls_ssl_list_ciphersuites();
+	} else {
+		selected_ciphers = context->options.ciphersuites;
+	}
+
+	cipher_cnt = *optlen / sizeof(int);
+	while (selected_ciphers[i] != 0) {
+		ciphers[i] = selected_ciphers[i];
+
+		if (++i == cipher_cnt) {
+			break;
+		}
+	}
+
+	*optlen = i * sizeof(int);
+
+	return 0;
+}
+
+static int tls_opt_ciphersuite_used_get(struct tls_context *context,
+					void *optval, socklen_t *optlen)
+{
+	const char *ciph;
+
+	if (*optlen != sizeof(int)) {
+		return -EINVAL;
+	}
+
+	ciph = mbedtls_ssl_get_ciphersuite(&context->ssl);
+	if (ciph == NULL) {
+		return -ENOTCONN;
+	}
+
+	*(int *)optval = mbedtls_ssl_get_ciphersuite_id(ciph);
+
+	return 0;
+}
+
+static int tls_opt_peer_verify_set(struct tls_context *context,
+				   const void *optval, socklen_t optlen)
+{
+	int *peer_verify;
+
+	if (!optval) {
+		return -EINVAL;
+	}
+
+	if (optlen != sizeof(int)) {
+		return -EINVAL;
+	}
+
+	peer_verify = (int *)optval;
+
+	if (*peer_verify != MBEDTLS_SSL_VERIFY_NONE &&
+	    *peer_verify != MBEDTLS_SSL_VERIFY_OPTIONAL &&
+	    *peer_verify != MBEDTLS_SSL_VERIFY_REQUIRED) {
+		return -EINVAL;
+	}
+
+	context->options.verify_level = *peer_verify;
+
+	return 0;
+}
+
+static int tls_opt_dtls_role_set(struct tls_context *context,
+				 const void *optval, socklen_t optlen)
+{
+	int *role;
+
+	if (!optval) {
+		return -EINVAL;
+	}
+
+	if (optlen != sizeof(int)) {
+		return -EINVAL;
+	}
+
+	role = (int *)optval;
+	if (*role != MBEDTLS_SSL_IS_CLIENT &&
+	    *role != MBEDTLS_SSL_IS_SERVER) {
+		return -EINVAL;
+	}
+
+	context->options.role = *role;
+
+	return 0;
+}
+
+static int protocol_check(int family, int type, int *proto)
+{
+	if (family != AF_INET && family != AF_INET6) {
+		return -EAFNOSUPPORT;
+	}
+
+	if (*proto >= IPPROTO_TLS_1_0 && *proto <= IPPROTO_TLS_1_2) {
+		if (type != SOCK_STREAM) {
+			return -EPROTOTYPE;
+		}
+
+		*proto = IPPROTO_TCP;
+	} else if (*proto >= IPPROTO_DTLS_1_0 && *proto <= IPPROTO_DTLS_1_2) {
+		if (!IS_ENABLED(CONFIG_NET_SOCKETS_ENABLE_DTLS)) {
+			return -EPROTONOSUPPORT;
+		}
+
+		if (type != SOCK_DGRAM) {
+			return -EPROTOTYPE;
+		}
+
+		*proto = IPPROTO_UDP;
+	} else {
+		return -EPROTONOSUPPORT;
+	}
+
+	return 0;
+}
+
+static int ztls_socket(int family, int type, int proto)
+{
+	enum net_ip_protocol_secure tls_proto = proto;
+	int fd = z_reserve_fd();
+	int sock = -1;
+	int ret;
+	struct tls_context *ctx;
+
+	if (fd < 0) {
+		return -1;
+	}
+
+	ret = protocol_check(family, type, &proto);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	ctx = tls_alloc();
+	if (ctx == NULL) {
+		errno = ENOMEM;
+		goto error;
+	}
+
+	sock = zsock_socket(family, type, proto);
+	if (sock < 0) {
+		goto error;
+	}
+
+	ctx->tls_version = tls_proto;
+	ctx->type = (proto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
+	ctx->sock = sock;
+
+	z_finalize_fd(
+		fd, ctx, (const struct fd_op_vtable *)&tls_sock_fd_op_vtable);
+
+	return fd;
+
+error:
+	z_free_fd(fd);
+
+	return -1;
+}
+
+int ztls_close_ctx(struct tls_context *ctx)
+{
+	int ret, err = 0;
+
+	/* Try to send close notification. */
+	ctx->flags = 0;
+
+	(void)mbedtls_ssl_close_notify(&ctx->ssl);
+
+	err = tls_release(ctx);
+	ret = zsock_close(ctx->sock);
+
+	/* In case close fails, we propagate errno value set by close.
+	 * In case close succeeds, but tls_release fails, set errno
+	 * according to tls_release return value.
+	 */
+	if (ret == 0 && err < 0) {
+		errno = -err;
+		ret = -1;
+	}
+
+	return ret;
+}
+
+int ztls_connect_ctx(struct tls_context *ctx, const struct sockaddr *addr,
+		     socklen_t addrlen)
+{
+	int ret;
+
+	ret = zsock_connect(ctx->sock, addr, addrlen);
+	if (ret < 0) {
+		return ret;
+	}
+
+	if (ctx->type == SOCK_STREAM) {
+		/* Do the handshake for TLS, not DTLS. */
+		ret = tls_mbedtls_init(ctx, false);
+		if (ret < 0) {
+			goto error;
+		}
+
+		/* Do not use any socket flags during the handshake. */
+		ctx->flags = 0;
+
+		/* TODO For simplicity, TLS handshake blocks the socket
+		 * even for non-blocking socket.
+		 */
+		ret = tls_mbedtls_handshake(ctx, true);
+		if (ret < 0) {
+			goto error;
+		}
+	} else {
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+		/* Just store the address. */
+		dtls_peer_address_set(ctx, addr, addrlen);
+#else
+		ret = -ENOTSUP;
+		goto error;
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+	}
+
+	return 0;
+
+error:
+	errno = -ret;
+	return -1;
+}
+
+int ztls_accept_ctx(struct tls_context *parent, struct sockaddr *addr,
+		    socklen_t *addrlen)
+{
+	struct tls_context *child = NULL;
+	int ret, err, fd, sock;
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		return -1;
+	}
+
+	sock = zsock_accept(parent->sock, addr, addrlen);
+	if (sock < 0) {
+		ret = -errno;
+		goto error;
+	}
+
+	child = tls_clone(parent);
+	if (child == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	z_finalize_fd(
+		fd, child, (const struct fd_op_vtable *)&tls_sock_fd_op_vtable);
+
+	child->sock = sock;
+
+	ret = tls_mbedtls_init(child, true);
+	if (ret < 0) {
+		goto error;
+	}
+
+	/* Do not use any socket flags during the handshake. */
+	child->flags = 0;
+
+	/* TODO For simplicity, TLS handshake blocks the socket even for
+	 * non-blocking socket.
+	 */
+	ret = tls_mbedtls_handshake(child, true);
+	if (ret < 0) {
+		goto error;
+	}
+
+	return fd;
+
+error:
+	if (child != NULL) {
+		err = tls_release(child);
+		__ASSERT(err == 0, "TLS context release failed");
+	}
+
+	if (sock >= 0) {
+		err = zsock_close(sock);
+		__ASSERT(err == 0, "Child socket close failed");
+	}
+
+	z_free_fd(fd);
+
+	errno = -ret;
+	return -1;
+}
+
+static ssize_t send_tls(struct tls_context *ctx, const void *buf,
+			size_t len, int flags)
+{
+	int ret;
+
+	ret = mbedtls_ssl_write(&ctx->ssl, buf, len);
+	if (ret >= 0) {
+		return ret;
+	}
+
+	if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
+	    ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+		errno = EAGAIN;
+	} else {
+		errno = EIO;
+	}
+
+	return -1;
+}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+static ssize_t sendto_dtls_client(struct tls_context *ctx, const void *buf,
+				  size_t len, int flags,
+				  const struct sockaddr *dest_addr,
+				  socklen_t addrlen)
+{
+	int ret;
+
+	if (!dest_addr) {
+		/* No address provided, check if we have stored one,
+		 * otherwise return error.
+		 */
+		if (ctx->dtls_peer_addrlen == 0) {
+			ret = -EDESTADDRREQ;
+			goto error;
+		}
+	} else if (ctx->dtls_peer_addrlen == 0) {
+		/* Address provided and no peer address stored. */
+		dtls_peer_address_set(ctx, dest_addr, addrlen);
+	} else if (!dtls_is_peer_addr_valid(ctx, dest_addr, addrlen) != 0) {
+		/* Address provided but it does not match stored one */
+		ret = -EISCONN;
+		goto error;
+	}
+
+	if (!ctx->is_initialized) {
+		ret = tls_mbedtls_init(ctx, false);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	if (!is_handshake_complete(ctx)) {
+		/* TODO For simplicity, TLS handshake blocks the socket even for
+		 * non-blocking socket.
+		 */
+		ret = tls_mbedtls_handshake(ctx, true);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	return send_tls(ctx, buf, len, flags);
+
+error:
+	errno = -ret;
+	return -1;
+}
+
+static ssize_t sendto_dtls_server(struct tls_context *ctx, const void *buf,
+				  size_t len, int flags,
+				  const struct sockaddr *dest_addr,
+				  socklen_t addrlen)
+{
+	/* For DTLS server, require to have established DTLS connection
+	 * in order to send data.
+	 */
+	if (!is_handshake_complete(ctx)) {
+		errno = ENOTCONN;
+		return -1;
+	}
+
+	/* Verify we are sending to a peer that we have connection with. */
+	if (dest_addr &&
+	    !dtls_is_peer_addr_valid(ctx, dest_addr, addrlen) != 0) {
+		errno = EISCONN;
+		return -1;
+	}
+
+	return send_tls(ctx, buf, len, flags);
+}
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+ssize_t ztls_sendto_ctx(struct tls_context *ctx, const void *buf, size_t len,
+			int flags, const struct sockaddr *dest_addr,
+			socklen_t addrlen)
+{
+	ctx->flags = flags;
+
+	/* TLS */
+	if (ctx->type == SOCK_STREAM) {
+		return send_tls(ctx, buf, len, flags);
+	}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	/* DTLS */
+	if (ctx->options.role == MBEDTLS_SSL_IS_SERVER) {
+		return sendto_dtls_server(ctx, buf, len, flags,
+					  dest_addr, addrlen);
+	}
+
+	return sendto_dtls_client(ctx, buf, len, flags, dest_addr, addrlen);
+#else
+	errno = ENOTSUP;
+	return -1;
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+}
+
+ssize_t ztls_sendmsg_ctx(struct tls_context *ctx, const struct msghdr *msg,
+			 int flags)
+{
+	ssize_t len;
+	ssize_t ret;
+	int i;
+
+	len = 0;
+	if (msg) {
+		for (i = 0; i < msg->msg_iovlen; i++) {
+			ret = ztls_sendto_ctx(ctx, msg->msg_iov[i].iov_base,
+					      msg->msg_iov[i].iov_len, flags,
+					      msg->msg_name, msg->msg_namelen);
+			if (ret < 0) {
+				return ret;
+			}
+			len += ret;
+		}
+	}
+
+	return len;
+}
+
+static ssize_t recv_tls(struct tls_context *ctx, void *buf,
+			size_t max_len, int flags)
+{
+	int ret;
+
+	ret = mbedtls_ssl_read(&ctx->ssl, buf, max_len);
+	if (ret >= 0) {
+		return ret;
+	}
+
+	if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
+		/* Peer notified that it's closing the connection. */
+		return 0;
+	}
+
+	if (ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) {
+		/* Client reconnect on the same socket is not
+		 * supported. See mbedtls_ssl_read API documentation.
+		 */
+		return 0;
+	}
+
+	if (ret == MBEDTLS_ERR_SSL_WANT_READ ||
+	    ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+		ret = -EAGAIN;
+	} else {
+		ret = -EIO;
+	}
+
+	errno = -ret;
+	return -1;
+}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+static ssize_t recvfrom_dtls_client(struct tls_context *ctx, void *buf,
+				    size_t max_len, int flags,
+				    struct sockaddr *src_addr,
+				    socklen_t *addrlen)
+{
+	int ret;
+
+	if (!is_handshake_complete(ctx)) {
+		ret = -ENOTCONN;
+		goto error;
+	}
+
+	ret = mbedtls_ssl_read(&ctx->ssl, buf, max_len);
+	if (ret >= 0) {
+		if (src_addr && addrlen) {
+			dtls_peer_address_get(ctx, src_addr, addrlen);
+		}
+		return ret;
+	}
+
+	switch (ret) {
+	case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+		/* Peer notified that it's closing the connection. */
+		return 0;
+
+	case MBEDTLS_ERR_SSL_TIMEOUT:
+		(void)mbedtls_ssl_close_notify(&ctx->ssl);
+		ret = -ETIMEDOUT;
+		break;
+
+	case MBEDTLS_ERR_SSL_WANT_READ:
+	case MBEDTLS_ERR_SSL_WANT_WRITE:
+		ret = -EAGAIN;
+		break;
+
+	default:
+		ret = -EIO;
+		break;
+	}
+
+error:
+	errno = -ret;
+	return -1;
+}
+
+static ssize_t recvfrom_dtls_server(struct tls_context *ctx, void *buf,
+				    size_t max_len, int flags,
+				    struct sockaddr *src_addr,
+				    socklen_t *addrlen)
+{
+	int ret;
+	bool repeat;
+	bool is_block = !((flags & ZSOCK_MSG_DONTWAIT) ||
+			  (zsock_fcntl(ctx->sock, F_GETFL, 0) & O_NONBLOCK));
+
+	if (!ctx->is_initialized) {
+		ret = tls_mbedtls_init(ctx, true);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
+	/* Loop to enable DTLS reconnection for servers without closing
+	 * a socket.
+	 */
+	do {
+		repeat = false;
+
+		if (!is_handshake_complete(ctx)) {
+			ret = tls_mbedtls_handshake(ctx, is_block);
+			if (ret < 0) {
+				/* In case of EAGAIN, just exit. */
+				if (ret == -EAGAIN) {
+					break;
+				}
+
+				ret = tls_mbedtls_reset(ctx);
+				if (ret == 0) {
+					repeat = true;
+				} else {
+					ret = -ECONNABORTED;
+				}
+
+				continue;
+			}
+		}
+
+		ret = mbedtls_ssl_read(&ctx->ssl, buf, max_len);
+		if (ret >= 0) {
+			if (src_addr && addrlen) {
+				dtls_peer_address_get(ctx, src_addr, addrlen);
+			}
+			return ret;
+		}
+
+		switch (ret) {
+		case MBEDTLS_ERR_SSL_TIMEOUT:
+			(void)mbedtls_ssl_close_notify(&ctx->ssl);
+			__fallthrough;
+			/* fallthrough */
+
+		case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+		case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
+			ret = tls_mbedtls_reset(ctx);
+			if (ret == 0) {
+				repeat = true;
+			} else {
+				ret = -ECONNABORTED;
+			}
+			break;
+
+		case MBEDTLS_ERR_SSL_WANT_READ:
+		case MBEDTLS_ERR_SSL_WANT_WRITE:
+			ret = -EAGAIN;
+			break;
+
+		default:
+			ret = -EIO;
+			break;
+		}
+	} while (repeat);
+
+error:
+	errno = -ret;
+	return -1;
+}
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+
+ssize_t ztls_recvfrom_ctx(struct tls_context *ctx, void *buf, size_t max_len,
+			  int flags, struct sockaddr *src_addr,
+			  socklen_t *addrlen)
+{
+	if (flags & ZSOCK_MSG_PEEK) {
+		/* TODO mbedTLS does not support 'peeking' This could be
+		 * bypassed by having intermediate buffer for peeking
+		 */
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	ctx->flags = flags;
+
+	/* TLS */
+	if (ctx->type == SOCK_STREAM) {
+		return recv_tls(ctx, buf, max_len, flags);
+	}
+
+#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
+	/* DTLS */
+	if (ctx->options.role == MBEDTLS_SSL_IS_SERVER) {
+		return recvfrom_dtls_server(ctx, buf, max_len, flags,
+					    src_addr, addrlen);
+	}
+
+	return recvfrom_dtls_client(ctx, buf, max_len, flags,
+				    src_addr, addrlen);
+#else
+	errno = ENOTSUP;
+	return -1;
+#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
+}
+
+static int ztls_poll_prepare_pollin(struct tls_context *ctx)
+{
+	/* If there already is mbedTLS data to read, there is no
+	 * need to set the k_poll_event object. Return EALREADY
+	 * so we won't block in the k_poll.
+	 */
+	if (!ctx->is_listening) {
+		if (mbedtls_ssl_get_bytes_avail(&ctx->ssl) > 0) {
+			return -EALREADY;
+		}
+	}
+
+	return 0;
+}
+
+static int ztls_poll_prepare_ctx(struct tls_context *ctx,
+				 struct zsock_pollfd *pfd,
+				 struct k_poll_event **pev,
+				 struct k_poll_event *pev_end)
+{
+	const struct fd_op_vtable *vtable;
+	void *obj;
+	int ret;
+
+	obj = z_get_fd_obj_and_vtable(
+		ctx->sock, (const struct fd_op_vtable **)&vtable);
+	if (obj == NULL) {
+		return -EBADF;
+	}
+
+	ret = z_fdtable_call_ioctl(vtable, obj, ZFD_IOCTL_POLL_PREPARE,
+				   pfd, pev, pev_end);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (pfd->events & ZSOCK_POLLIN) {
+		ret = ztls_poll_prepare_pollin(ctx);
+	}
+
+	return ret;
+}
+
+static int ztls_poll_update_pollin(int fd, struct tls_context *ctx,
+				   struct zsock_pollfd *pfd)
+{
+	int ret;
+
+	if (!ctx->is_listening) {
+		/* Already had TLS data to read on socket. */
+		if (mbedtls_ssl_get_bytes_avail(&ctx->ssl) > 0) {
+			pfd->revents |= ZSOCK_POLLIN;
+			goto next;
+		}
+	}
+
+	if (!(pfd->revents & ZSOCK_POLLIN)) {
+		/* No new data on a socket. */
+		goto next;
+	}
+
+	if (ctx->is_listening) {
+		goto next;
+	}
+
+	if (!is_handshake_complete(ctx)) {
+		goto again;
+	}
+
+	ret = zsock_recv(fd, NULL, 0, ZSOCK_MSG_DONTWAIT);
+	if (ret == 0 && ctx->type == SOCK_STREAM) {
+		pfd->revents |= ZSOCK_POLLHUP;
+		goto next;
+	/* EAGAIN might happen during or just after DTLS  handshake. */
+	} else if (ret < 0 && errno != EAGAIN) {
+		pfd->revents |= ZSOCK_POLLERR;
+		goto next;
+	}
+
+	if (mbedtls_ssl_get_bytes_avail(&ctx->ssl) == 0) {
+		goto again;
+	}
+
+next:
+	return 0;
+
+again:
+	/* Received encrypted data, but still not enough
+	 * to decrypt it and return data through socket,
+	 * ask for retry if no other events are set.
+	 */
+	pfd->revents &= ~ZSOCK_POLLIN;
+
+	return -EAGAIN;
+}
+
+static int ztls_poll_update_ctx(struct tls_context *ctx,
+				struct zsock_pollfd *pfd,
+				struct k_poll_event **pev)
+{
+	const struct fd_op_vtable *vtable;
+	void *obj;
+	int ret;
+
+	obj = z_get_fd_obj_and_vtable(
+		ctx->sock, (const struct fd_op_vtable **)&vtable);
+	if (obj == NULL) {
+		return -EBADF;
+	}
+
+	ret = z_fdtable_call_ioctl(vtable, obj, ZFD_IOCTL_POLL_UPDATE,
+				   pfd, pev);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (pfd->events & ZSOCK_POLLIN) {
+		ret = ztls_poll_update_pollin(pfd->fd, ctx, pfd);
+		if (ret == -EAGAIN && pfd->revents != 0) {
+			(*pev - 1)->state = K_POLL_STATE_NOT_READY;
+			return -EAGAIN;
+		}
+	}
+
+	return ret;
+}
+
+static inline int ztls_poll_offload(struct zsock_pollfd *fds, int nfds, int timeout)
+{
+	int fd_backup[CONFIG_NET_SOCKETS_POLL_MAX];
+	const struct fd_op_vtable *vtable;
+	void *ctx;
+	int ret = 0;
+	int result;
+	int i;
+	bool retry;
+	int remaining;
+	uint32_t entry = k_uptime_get_32();
+
+	/* Overwrite TLS file decriptors with underlying ones. */
+	for (i = 0; i < nfds; i++) {
+		fd_backup[i] = fds[i].fd;
+
+		ctx = z_get_fd_obj(fds[i].fd,
+				   (const struct fd_op_vtable *)
+						     &tls_sock_fd_op_vtable,
+				   0);
+		if (ctx == NULL) {
+			continue;
+		}
+
+		if (fds[i].events & ZSOCK_POLLIN) {
+			ret = ztls_poll_prepare_pollin(ctx);
+			/* In case data is already available in mbedtls,
+			 * do not wait in poll.
+			 */
+			if (ret == -EALREADY) {
+				timeout = 0;
+			}
+		}
+
+		fds[i].fd = ((struct tls_context *)ctx)->sock;
+	}
+
+	/* Get offloaded sockets vtable. */
+	ctx = z_get_fd_obj_and_vtable(fds[0].fd,
+				      (const struct fd_op_vtable **)&vtable);
+	if (ctx == NULL) {
+		errno = EINVAL;
+		goto exit;
+	}
+
+	remaining = timeout;
+
+	do {
+		for (i = 0; i < nfds; i++) {
+			fds[i].revents = 0;
+		}
+
+		ret = z_fdtable_call_ioctl(vtable, ctx, ZFD_IOCTL_POLL_OFFLOAD,
+					   fds, nfds, remaining);
+		if (ret < 0) {
+			goto exit;
+		}
+
+		retry = false;
+		ret = 0;
+
+		for (i = 0; i < nfds; i++) {
+			ctx = z_get_fd_obj(fd_backup[i],
+					   (const struct fd_op_vtable *)
+							&tls_sock_fd_op_vtable,
+					   0);
+			if (ctx != NULL) {
+				if (fds[i].events & ZSOCK_POLLIN) {
+					result = ztls_poll_update_pollin(
+						    fd_backup[i], ctx, &fds[i]);
+					if (result == -EAGAIN) {
+						retry = true;
+					}
+				}
+			}
+
+			if (fds[i].revents != 0) {
+				ret++;
+			}
+		}
+
+		if (retry) {
+			if (ret > 0 || timeout == 0) {
+				goto exit;
+			}
+
+			if (timeout > 0) {
+				remaining = time_left(entry, timeout);
+				if (remaining <= 0) {
+					goto exit;
+				}
+			}
+		}
+	} while (retry);
+
+exit:
+	/* Restore original fds. */
+	for (i = 0; i < nfds; i++) {
+		fds[i].fd = fd_backup[i];
+	}
+
+	return ret;
+}
+
+int ztls_getsockopt_ctx(struct tls_context *ctx, int level, int optname,
+			void *optval, socklen_t *optlen)
+{
+	int err;
+
+	if (!optval || !optlen) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (level != SOL_TLS) {
+		return zsock_getsockopt(ctx->sock, level, optname,
+					optval, optlen);
+	}
+
+	switch (optname) {
+	case TLS_SEC_TAG_LIST:
+		err =  tls_opt_sec_tag_list_get(ctx, optval, optlen);
+		break;
+
+	case TLS_CIPHERSUITE_LIST:
+		err = tls_opt_ciphersuite_list_get(ctx, optval, optlen);
+		break;
+
+	case TLS_CIPHERSUITE_USED:
+		err = tls_opt_ciphersuite_used_get(ctx, optval, optlen);
+		break;
+
+	default:
+		/* Unknown or write-only option. */
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	if (err < 0) {
+		errno = -err;
+		return -1;
+	}
+
+	return 0;
+}
+
+int ztls_setsockopt_ctx(struct tls_context *ctx, int level, int optname,
+			const void *optval, socklen_t optlen)
+{
+	int err;
+
+	if (level != SOL_TLS) {
+		return zsock_setsockopt(ctx->sock, level, optname,
+					optval, optlen);
+	}
+
+	switch (optname) {
+	case TLS_SEC_TAG_LIST:
+		err =  tls_opt_sec_tag_list_set(ctx, optval, optlen);
+		break;
+
+	case TLS_HOSTNAME:
+		err = tls_opt_hostname_set(ctx, optval, optlen);
+		break;
+
+	case TLS_CIPHERSUITE_LIST:
+		err = tls_opt_ciphersuite_list_set(ctx, optval, optlen);
+		break;
+
+	case TLS_PEER_VERIFY:
+		err = tls_opt_peer_verify_set(ctx, optval, optlen);
+		break;
+
+	case TLS_DTLS_ROLE:
+		err = tls_opt_dtls_role_set(ctx, optval, optlen);
+		break;
+
+	default:
+		/* Unknown or read-only option. */
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	if (err < 0) {
+		errno = -err;
+		return -1;
+	}
+
+	return 0;
+}
+
+static ssize_t tls_sock_read_vmeth(void *obj, void *buffer, size_t count)
+{
+	return ztls_recvfrom_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static ssize_t tls_sock_write_vmeth(void *obj, const void *buffer,
+				    size_t count)
+{
+	return ztls_sendto_ctx(obj, buffer, count, 0, NULL, 0);
+}
+
+static int tls_sock_ioctl_vmeth(void *obj, unsigned int request, va_list args)
+{
+	struct tls_context *ctx = obj;
+
+	switch (request) {
+	/* fcntl() commands */
+	case F_GETFL:
+	case F_SETFL: {
+		const struct fd_op_vtable *vtable;
+		void *obj;
+
+		obj = z_get_fd_obj_and_vtable(ctx->sock,
+					(const struct fd_op_vtable **)&vtable);
+		if (obj == NULL) {
+			errno = EBADF;
+			return -1;
+		}
+
+		/* Pass the call to the core socket implementation. */
+		return vtable->ioctl(obj, request, args);
+	}
+
+	case ZFD_IOCTL_POLL_PREPARE: {
+		struct zsock_pollfd *pfd;
+		struct k_poll_event **pev;
+		struct k_poll_event *pev_end;
+
+		pfd = va_arg(args, struct zsock_pollfd *);
+		pev = va_arg(args, struct k_poll_event **);
+		pev_end = va_arg(args, struct k_poll_event *);
+
+		return ztls_poll_prepare_ctx(obj, pfd, pev, pev_end);
+	}
+
+	case ZFD_IOCTL_POLL_UPDATE: {
+		struct zsock_pollfd *pfd;
+		struct k_poll_event **pev;
+
+		pfd = va_arg(args, struct zsock_pollfd *);
+		pev = va_arg(args, struct k_poll_event **);
+
+		return ztls_poll_update_ctx(obj, pfd, pev);
+	}
+
+	case ZFD_IOCTL_POLL_OFFLOAD: {
+		struct zsock_pollfd *fds;
+		int nfds;
+		int timeout;
+
+		fds = va_arg(args, struct zsock_pollfd *);
+		nfds = va_arg(args, int);
+		timeout = va_arg(args, int);
+
+		return ztls_poll_offload(fds, nfds, timeout);
+	}
+
+	default:
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+}
+
+static int tls_sock_bind_vmeth(void *obj, const struct sockaddr *addr,
+			       socklen_t addrlen)
+{
+	struct tls_context *ctx = obj;
+
+	return zsock_bind(ctx->sock, addr, addrlen);
+}
+
+static int tls_sock_connect_vmeth(void *obj, const struct sockaddr *addr,
+				  socklen_t addrlen)
+{
+	return ztls_connect_ctx(obj, addr, addrlen);
+}
+
+static int tls_sock_listen_vmeth(void *obj, int backlog)
+{
+	struct tls_context *ctx = obj;
+
+	ctx->is_listening = true;
+
+	return zsock_listen(ctx->sock, backlog);
+}
+
+static int tls_sock_accept_vmeth(void *obj, struct sockaddr *addr,
+				 socklen_t *addrlen)
+{
+	return ztls_accept_ctx(obj, addr, addrlen);
+}
+
+static ssize_t tls_sock_sendto_vmeth(void *obj, const void *buf, size_t len,
+				     int flags,
+				     const struct sockaddr *dest_addr,
+				     socklen_t addrlen)
+{
+	return ztls_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
+}
+
+static ssize_t tls_sock_sendmsg_vmeth(void *obj, const struct msghdr *msg,
+				      int flags)
+{
+	return ztls_sendmsg_ctx(obj, msg, flags);
+}
+
+static ssize_t tls_sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
+				       int flags, struct sockaddr *src_addr,
+				       socklen_t *addrlen)
+{
+	return ztls_recvfrom_ctx(obj, buf, max_len, flags,
+				 src_addr, addrlen);
+}
+
+static int tls_sock_getsockopt_vmeth(void *obj, int level, int optname,
+				     void *optval, socklen_t *optlen)
+{
+	return ztls_getsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int tls_sock_setsockopt_vmeth(void *obj, int level, int optname,
+				     const void *optval, socklen_t optlen)
+{
+	return ztls_setsockopt_ctx(obj, level, optname, optval, optlen);
+}
+
+static int tls_sock_close_vmeth(void *obj)
+{
+	return ztls_close_ctx(obj);
+}
+
+static int tls_sock_getsockname_vmeth(void *obj, struct sockaddr *addr,
+				      socklen_t *addrlen)
+{
+	struct tls_context *ctx = obj;
+
+	return zsock_getsockname(ctx->sock, addr, addrlen);
+}
+
+static const struct socket_op_vtable tls_sock_fd_op_vtable = {
+	.fd_vtable = {
+		.read = tls_sock_read_vmeth,
+		.write = tls_sock_write_vmeth,
+		.close = tls_sock_close_vmeth,
+		.ioctl = tls_sock_ioctl_vmeth,
+	},
+	.bind = tls_sock_bind_vmeth,
+	.connect = tls_sock_connect_vmeth,
+	.listen = tls_sock_listen_vmeth,
+	.accept = tls_sock_accept_vmeth,
+	.sendto = tls_sock_sendto_vmeth,
+	.sendmsg = tls_sock_sendmsg_vmeth,
+	.recvfrom = tls_sock_recvfrom_vmeth,
+	.getsockopt = tls_sock_getsockopt_vmeth,
+	.setsockopt = tls_sock_setsockopt_vmeth,
+	.getsockname = tls_sock_getsockname_vmeth,
+};
+
+static bool tls_is_supported(int family, int type, int proto)
+{
+	if (protocol_check(family, type, &proto) == 0) {
+		return true;
+	}
+
+	return false;
+}
+
+NET_SOCKET_REGISTER(tls, AF_UNSPEC, tls_is_supported, ztls_socket);
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/CMakeLists.txt	(working copy)
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources_ifdef(CONFIG_SOCKS socks.c)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/Kconfig	(working copy)
@@ -0,0 +1,19 @@
+# Copyright (c) 2018 Antmicro Ltd
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig SOCKS
+	bool "SOCKS5 proxy"
+	select NET_SOCKETS
+	select NET_SOCKETS_POSIX_NAMES
+	help
+	  Enable SOCKS5 proxy support
+
+if SOCKS
+
+module = SOCKS
+module-dep = NET_LOG
+module-str = Log level for SOCKS proxy
+module-help = Enable debug messages for SOCKS5 protocol
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif # SOCKS
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.h	(working copy)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Antmicro Ltd
+ *
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_NET_SOCKS_H_
+#define ZEPHYR_INCLUDE_NET_SOCKS_H_
+
+#include <net/socket.h>
+
+/**@brief Connects to destination through a SOCKS5 proxy server.
+ *
+ * @param[in] ctx Network context.
+ * @param[in] dest Address of the destination server.
+ * @param[in] dest_len Address length of the destination server.
+ *
+ * @retval 0 or an error code if it was unsuccessful.
+ */
+#if defined(CONFIG_SOCKS)
+int net_socks5_connect(struct net_context *ctx,
+		       const struct sockaddr *dest,
+		       socklen_t dest_len);
+#else
+inline int net_socks5_connect(struct net_context *ctx,
+			      const struct sockaddr *dest,
+			      socklen_t dest_len)
+{
+	ARG_UNUSED(ctx);
+	ARG_UNUSED(dest);
+	ARG_UNUSED(dest_len);
+
+	return -ENOTSUP;
+}
+#endif
+
+#endif /* ZEPHYR_INCLUDE_NET_SOCKS_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks.c	(working copy)
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2019 Antmicro Ltd
+ *
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_socks, CONFIG_SOCKS_LOG_LEVEL);
+
+#include <zephyr.h>
+#include <net/socket.h>
+#include <net/net_pkt.h>
+
+#include "socks.h"
+#include "socks_internal.h"
+
+static void socks5_method_rsp_cb(struct net_context *ctx,
+				 struct net_pkt *pkt,
+				 union net_ip_header *ip_hdr,
+				 union net_proto_header *proto_hdr,
+				 int status,
+				 void *user_data)
+{
+	struct socks5_method_response *method_rsp =
+			(struct socks5_method_response *)user_data;
+
+	if (!pkt || status) {
+		memset(method_rsp, 0, sizeof(struct socks5_method_response));
+		goto end;
+	}
+
+	if (net_pkt_read(pkt, (uint8_t *)method_rsp,
+			 sizeof(struct socks5_method_response))) {
+		memset(method_rsp, 0, sizeof(struct socks5_method_response));
+	}
+
+end:
+	net_pkt_unref(pkt);
+}
+
+static void socks5_cmd_rsp_cb(struct net_context *ctx,
+			      struct net_pkt *pkt,
+			      union net_ip_header *ip_hdr,
+			      union net_proto_header *proto_hdr,
+			      int status,
+			      void *user_data)
+{
+	struct socks5_command_response *cmd_rsp =
+			(struct socks5_command_response *)user_data;
+	int size;
+
+	if (!pkt || status) {
+		memset(cmd_rsp, 0,
+		       sizeof(struct socks5_command_request_common));
+		goto end;
+	}
+
+	size = sizeof(struct socks5_command_request_common);
+
+	if (net_pkt_read(pkt, (uint8_t *)cmd_rsp, size)) {
+		memset(cmd_rsp, 0,
+		       sizeof(struct socks5_command_request_common));
+	}
+
+end:
+	net_pkt_unref(pkt);
+}
+
+static int socks5_tcp_connect(struct net_context *ctx,
+			      const struct sockaddr *proxy,
+			      socklen_t proxy_len,
+			      const struct sockaddr *dest,
+			      socklen_t dest_len)
+{
+	struct socks5_method_request method_req;
+	struct socks5_method_response method_rsp;
+	struct socks5_command_request cmd_req;
+	struct socks5_command_response cmd_rsp;
+	int size;
+	int ret;
+
+	/* Negotiate authentication method */
+	method_req.r.ver = SOCKS5_PKT_MAGIC;
+
+	/* We only support NOAUTH at the moment */
+	method_req.r.nmethods = 1U;
+	method_req.methods[0] = SOCKS5_AUTH_METHOD_NOAUTH;
+
+	/* size + 1 because just one method is supported */
+	size = sizeof(struct socks5_method_request_common) + 1;
+
+	ret = net_context_sendto(ctx, (uint8_t *)&method_req, size,
+				 proxy, proxy_len, NULL, K_NO_WAIT,
+				 ctx->user_data);
+	if (ret < 0) {
+		LOG_ERR("Could not send negotiation packet");
+		return ret;
+	}
+
+	ret = net_context_recv(ctx, socks5_method_rsp_cb,
+			       K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
+			       &method_rsp);
+	if (ret < 0) {
+		LOG_ERR("Could not receive negotiation response");
+		return ret;
+	}
+
+	if (method_rsp.ver != SOCKS5_PKT_MAGIC) {
+		LOG_ERR("Invalid negotiation response magic");
+		return -EINVAL;
+	}
+
+	if (method_rsp.method != SOCKS5_AUTH_METHOD_NOAUTH) {
+		LOG_ERR("Invalid negotiation response");
+		return -ENOTSUP;
+	}
+
+	/* Negotiation complete - now connect to destination */
+	cmd_req.r.ver = SOCKS5_PKT_MAGIC;
+	cmd_req.r.cmd = SOCKS5_CMD_CONNECT;
+	cmd_req.r.rsv = SOCKS5_PKT_RSV;
+
+	if (proxy->sa_family == AF_INET) {
+		const struct sockaddr_in *d4 =
+			(struct sockaddr_in *)dest;
+
+		cmd_req.r.atyp = SOCKS5_ATYP_IPV4;
+
+		memcpy(&cmd_req.ipv4_addr.addr,
+		       (uint8_t *)&d4->sin_addr,
+		       sizeof(cmd_req.ipv4_addr.addr));
+
+		cmd_req.ipv4_addr.port = d4->sin_port;
+
+		size = sizeof(struct socks5_command_request_common)
+			+ sizeof(struct socks5_ipv4_addr);
+	} else if (proxy->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *d6 =
+			(struct sockaddr_in6 *)dest;
+
+		cmd_req.r.atyp = SOCKS5_ATYP_IPV6;
+
+		memcpy(&cmd_req.ipv6_addr.addr,
+		       (uint8_t *)&d6->sin6_addr,
+		       sizeof(cmd_req.ipv6_addr.addr));
+
+		cmd_req.ipv6_addr.port = d6->sin6_port;
+
+		size = sizeof(struct socks5_command_request_common)
+			+ sizeof(struct socks5_ipv6_addr);
+	}
+
+	ret = net_context_sendto(ctx, (uint8_t *)&cmd_req, size,
+				 proxy, proxy_len, NULL, K_NO_WAIT,
+				 ctx->user_data);
+	if (ret < 0) {
+		LOG_ERR("Could not send CONNECT command");
+		return ret;
+	}
+
+	ret = net_context_recv(ctx, socks5_cmd_rsp_cb,
+			       K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
+			       &cmd_rsp);
+	if (ret < 0) {
+		LOG_ERR("Could not receive CONNECT response");
+		return ret;
+	}
+
+	if (cmd_rsp.r.ver != SOCKS5_PKT_MAGIC) {
+		LOG_ERR("Invalid CONNECT response");
+		return -EINVAL;
+	}
+
+	if (cmd_rsp.r.rep != SOCKS5_CMD_RESP_SUCCESS) {
+		LOG_ERR("Unable to connect to destination");
+		return -EINVAL;
+	}
+
+	/* Verifying the rest is not required */
+
+	LOG_DBG("Connection through SOCKS5 proxy successful");
+
+	return 0;
+}
+
+int net_socks5_connect(struct net_context *ctx, const struct sockaddr *addr,
+		       socklen_t addrlen)
+{
+	struct sockaddr proxy;
+	socklen_t proxy_len;
+	int type;
+	int ret;
+
+	type = net_context_get_type(ctx);
+	/* TODO: Only TCP and TLS supported, UDP and DTLS yet to support. */
+	if (type != SOCK_STREAM) {
+		return -ENOTSUP;
+	}
+
+	ret = net_context_get_option(ctx, NET_OPT_SOCKS5, &proxy, &proxy_len);
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* Connect to Proxy Server */
+	ret = net_context_connect(ctx, &proxy, proxy_len, NULL,
+				  K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
+				  NULL);
+	if (ret < 0) {
+		return ret;
+	}
+
+	return socks5_tcp_connect(ctx, &proxy, proxy_len, addr, addrlen);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/socks/socks_internal.h	(working copy)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018 Antmicro Ltd
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_SUBSYS_NET_LIB_SOCKS_SOCKS_INTERNAL_H_
+#define ZEPHYR_SUBSYS_NET_LIB_SOCKS_SOCKS_INTERNAL_H_
+
+#define SOCKS5_PKT_MAGIC			0x05
+#define SOCKS5_PKT_RSV				0x00
+
+#define SOCKS5_AUTH_METHOD_NOAUTH		0x00
+#define SOCKS5_AUTH_METHOD_GSSAPI		0x01
+#define SOCKS5_AUTH_METHOD_USERPASS		0x02
+#define SOCKS5_AUTH_METHOD_NONEG		0xFF
+
+#define SOCKS5_CMD_CONNECT			0x01
+#define SOCKS5_CMD_BIND				0x02
+#define SOCKS5_CMD_UDP_ASSOCIATE		0x03
+
+#define SOCKS5_ATYP_IPV4			0x01
+#define SOCKS5_ATYP_DOMAINNAME			0x03
+#define SOCKS5_ATYP_IPV6			0x04
+
+#define SOCKS5_CMD_RESP_SUCCESS			0x00
+#define SOCKS5_CMD_RESP_FAILURE			0x01
+#define SOCKS5_CMD_RESP_NOT_ALLOWED		0x02
+#define SOCKS5_CMD_RESP_NET_UNREACHABLE		0x03
+#define SOCKS5_CMD_RESP_HOST_UNREACHABLE	0x04
+#define SOCKS5_CMD_RESP_REFUSED			0x05
+#define SOCKS5_CMD_RESP_TTL_EXPIRED		0x06
+#define SOCKS5_CMD_RESP_CMD_NOT_SUPPORTED	0x07
+#define SOCKS5_CMD_RESP_ATYP_NOT_SUPPORTED	0x08
+
+struct socks5_method_request_common {
+	uint8_t ver;
+	uint8_t nmethods;
+} __packed;
+
+struct socks5_method_request {
+	struct socks5_method_request_common r;
+	uint8_t methods[255];
+} __packed;
+
+struct socks5_method_response {
+	uint8_t ver;
+	uint8_t method;
+} __packed;
+
+struct socks5_ipv4_addr {
+	uint8_t addr[4];
+	uint16_t port;
+} __packed;
+
+struct socks5_ipv6_addr {
+	uint8_t addr[16];
+	uint16_t port;
+} __packed;
+
+struct socks5_command_request_common {
+	uint8_t ver;
+	uint8_t cmd;
+	uint8_t rsv;
+	uint8_t atyp;
+} __packed;
+
+struct socks5_command_request {
+	struct socks5_command_request_common r;
+	union {
+		struct socks5_ipv4_addr ipv4_addr;
+		struct socks5_ipv6_addr ipv6_addr;
+	};
+} __packed;
+
+struct socks5_command_response_common {
+	uint8_t ver;
+	uint8_t rep;
+	uint8_t rsv;
+	uint8_t atyp;
+} __packed;
+
+struct socks5_command_response {
+	struct socks5_command_response_common r;
+	union {
+		struct socks5_ipv4_addr ipv4_addr;
+		struct socks5_ipv6_addr ipv6_addr;
+	};
+} __packed;
+
+#endif /* ZEPHYR_SUBSYS_NET_LIB_SOCKS_SOCKS_INTERNAL_H_ */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/CMakeLists.txt	(working copy)
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources(
+  tftp_client.c
+  )
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/Kconfig	(working copy)
@@ -0,0 +1,40 @@
+# Socket TFTP Library for Zephyr
+
+# Copyright (c) 2020 InnBlue
+# SPDX-License-Identifier: Apache-2.0
+
+config TFTP_LIB
+	bool "Socket TFTP Library Support [EXPERIMENTAL]"
+	select NET_SOCKETS
+	select NET_SOCKETS_POSIX_NAMES
+	help
+	  Enable the Zephyr TFTP Library
+
+if TFTP_LIB
+
+module=TFTP
+module-dep=NET_LOG
+module-str=Log level for TFTP
+module-help=Enables tftp debug messages.
+source "subsys/net/Kconfig.template.log_config.net"
+
+config TFTPC_REQUEST_TIMEOUT
+	int "Maximum amount of time the TFTP Client will wait for a response from the server."
+	default 5000
+	help
+	  Maximum amount of time (in msec) that the TFTP Client will wait for
+	  data from the TFTP Server. Once this time has elasped, the TFTP Client
+	  will assume that the Server failed and close the connection.
+
+config TFTPC_REQUEST_RETRANSMITS
+	int "Number of times the TFTP Client will retransmit the request to the server."
+	default 5
+	help
+	  Once the TFTP Client sends out a request, it will wait
+	  TFTPC_REQUEST_TIMEOUT msecs for the data to arrive from the TFTP Server.
+	  However, if it doesn't arrive within the given time we will re-transmit
+	  the request to the server in hopes that the server will respond within
+	  time to this request. This number dictates the number of times we will
+	  do re-tx of our request before giving up and exiting.
+
+endif # TFTP_LIB
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.h	(working copy)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020 InnBlue
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Generic header files required by the TFTPC Module. */
+#include <zephyr.h>
+#include <errno.h>
+#include <net/socket.h>
+
+/* Defines for creating static arrays for TFTP communication. */
+#define TFTP_HEADER_SIZE         4
+#define TFTP_BLOCK_SIZE          512
+#define TFTP_MAX_MODE_SIZE       8
+#define TFTP_REQ_RETX            CONFIG_TFTPC_REQUEST_RETRANSMITS
+
+/* Maximum amount of data that can be received in a single go ! */
+#define TFTPC_MAX_BUF_SIZE       (TFTP_BLOCK_SIZE + TFTP_HEADER_SIZE)
+
+/* Maximum filename size allowed by the TFTP Client. This is used as
+ * an upper bound in the "make_request" function to ensure that there
+ * are no buffer overflows. The complete "tftpc_buffer" has the size of
+ * "TFTPC_MAX_BUF_SIZE" which is used when creating a request. From this
+ * total size, we need 2 bytes for request info, 2 dummy NULL bytes and
+ * "TFTP_MAX_MODE_SIZE" for mode info. Everything else can be used for
+ * filename.
+ */
+#define TFTP_MAX_FILENAME_SIZE   (TFTPC_MAX_BUF_SIZE - TFTP_MAX_MODE_SIZE - 4)
+
+/* TFTP Opcodes. */
+#define READ_REQUEST             0x1
+#define WRITE_REQUEST            0x2
+#define DATA_OPCODE              0x3
+#define ACK_OPCODE               0x4
+#define ERROR_OPCODE             0x5
+
+#define RECV_DATA_SIZE()         (tftpc_buffer_size - TFTP_HEADER_SIZE)
+
+/* Name: send_ack
+ * Description: This function sends an Ack to the TFTP
+ * Server (in response to the data sent by the
+ * Server).
+ */
+static inline int send_ack(int sock, int block)
+{
+	uint8_t tmp[4];
+
+	LOG_INF("Client acking Block Number: %d", block);
+
+	/* Fill in the "Ack" Opcode and the block no. */
+	sys_put_be16(ACK_OPCODE, tmp);
+	sys_put_be16(block, tmp + 2);
+
+	/* Lets send this request buffer out. Size of request
+	 * buffer is 4 bytes.
+	 */
+	return send(sock, tmp, 4, 0);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tftp/tftp_client.c	(working copy)
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2020 InnBlue
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(tftp_client, LOG_LEVEL_DBG);
+
+/* Public / Internal TFTP header file. */
+#include <net/tftp.h>
+#include "tftp_client.h"
+
+/* TFTP Global Buffer. */
+static uint8_t   tftpc_buffer[TFTPC_MAX_BUF_SIZE];
+static uint32_t  tftpc_buffer_size;
+
+/* TFTP Request block number property. */
+static uint32_t  tftpc_block_no;
+static uint32_t  tftpc_index;
+
+/* Global mutex to protect critical resources. */
+K_MUTEX_DEFINE(tftpc_lock);
+
+/* Name: make_request
+ * Description: This function takes in a given list of parameters and
+ * returns a read request packet. This packet can be sent
+ * out directly to the TFTP server.
+ */
+static uint32_t make_request(const char *remote_file, const char *mode,
+			  uint8_t request_type)
+{
+	uint32_t      req_size;
+	const char def_mode[] = "octet";
+
+	/* Populate the read request with the provided params. Note that this
+	 * is created per RFC1350.
+	 */
+
+	/* Fill in the Request Type. Also keep tabs on the request size. */
+	sys_put_be16(request_type, tftpc_buffer);
+	req_size = 2;
+
+	/* Copy in the name of the remote file - the file we need to get
+	 * from the server. Add an upper bound to ensure no buffers overflow.
+	 */
+	strncpy(tftpc_buffer + req_size, remote_file, TFTP_MAX_FILENAME_SIZE);
+	req_size += strlen(remote_file);
+
+	/* Fill in 0. */
+	tftpc_buffer[req_size] = 0x0;
+	req_size++;
+
+	/* Default to "Octet" if mode not specified. */
+	if (mode == NULL) {
+		mode = def_mode;
+	}
+
+	/* Copy the mode of operation. */
+	strncpy(tftpc_buffer + req_size, mode, TFTP_MAX_MODE_SIZE);
+	req_size += strlen(mode);
+
+	/* Fill in 0. */
+	tftpc_buffer[req_size] = 0x0;
+	req_size++;
+
+	return req_size;
+}
+
+/* Name: send_err
+ * Description: This function sends an Error report to the TFTP Server.
+ */
+static inline int send_err(int sock, int err_code, char *err_string)
+{
+	uint32_t req_size;
+
+	LOG_ERR("Client Error. Sending code: %d(%s)", err_code, err_string);
+
+	/* Fill in the "Err" Opcode and the actual error code. */
+	sys_put_be16(ERROR_OPCODE, tftpc_buffer);
+	sys_put_be16(err_code, tftpc_buffer + 2);
+	req_size = 4;
+
+	/* Copy the Error String. */
+	strcpy(tftpc_buffer + req_size, err_string);
+	req_size += strlen(err_string);
+
+	/* Send Error to server. */
+	return send(sock, tftpc_buffer, req_size, 0);
+}
+
+/* Name: tftpc_recv_data
+ * Description: This function tries to get data from the TFTP Server
+ * (either response or data). Times out eventually.
+ */
+static int tftpc_recv_data(int sock)
+{
+	int           stat;
+	struct pollfd fds;
+
+	/* Setup FDS. */
+	fds.fd     = sock;
+	fds.events = ZSOCK_POLLIN;
+
+	/* Enable poll on this socket. Wait for the specified number
+	 * of milliseconds before exiting the call.
+	 */
+	stat = poll(&fds, 1, CONFIG_TFTPC_REQUEST_TIMEOUT);
+	if (stat > 0) {
+		/* Receive data from the TFTP Server. */
+		stat = recv(sock, tftpc_buffer, TFTPC_MAX_BUF_SIZE, 0);
+
+		/* Store the amount of data received in the global variable. */
+		tftpc_buffer_size = stat;
+	}
+
+	return stat;
+}
+
+/* Name: tftpc_process_resp
+ * Description: This function will process the data received from the
+ * TFTP Server (a file or part of the file) and place it in the user buffer.
+ * Return Value: This function will return one of the following values,
+ * -> TFTPC_DUPLICATE_DATA: If the block is already received by the client.
+ * -> TFTPC_BUFFER_OVERFLOW: If the data is more than the user provided buffer.
+ * -> TFTPC_DATA_RX_SUCCESS: data received but their is more to come.
+ * -> TFTPC_SUCCESS: Block received successfully and no more data is coming.
+ */
+static int tftpc_process_resp(int sock, struct tftpc *client)
+{
+	uint16_t    block_no;
+
+	/* Get the block number as received in the packet. */
+	block_no = sys_get_be16(tftpc_buffer + 2);
+	if (tftpc_block_no > block_no) {
+		LOG_DBG("Duplicate block received: %d", block_no);
+		LOG_DBG("Client waiting for Block Number: %d", tftpc_block_no);
+
+		send_ack(sock, block_no);
+
+		/* Duplicate block received. */
+		return TFTPC_DUPLICATE_DATA;
+	}
+
+	/* Valid block number received. */
+	LOG_DBG("Block Number: %d received", tftpc_block_no);
+
+	/* Only copy block if the user buffer has enough space. */
+	if (RECV_DATA_SIZE() > (client->user_buf_size - tftpc_index)) {
+		send_err(sock, 0x3, "Buffer Overflow");
+		return TFTPC_BUFFER_OVERFLOW;
+	}
+
+	/* Perform the actual copy and update the index. */
+	memcpy(client->user_buf + tftpc_index,
+	       tftpc_buffer + TFTP_HEADER_SIZE, RECV_DATA_SIZE());
+	tftpc_index += RECV_DATA_SIZE();
+
+	/* "block" of data received. */
+	send_ack(sock, block_no);
+	tftpc_block_no++;
+
+	/* For RFC1350, the block size will always be 512.
+	 * -> If block_size == 512, the transfer is still in progress.
+	 * -> If block_size < 512, we will conclude the transfer.
+	 */
+	return (RECV_DATA_SIZE() == TFTP_BLOCK_SIZE) ? TFTP_BLOCK_SIZE :
+		TFTPC_SUCCESS;
+}
+
+/* Name: tftp_send_request
+ * Description: This function sends out a request to the TFTP Server
+ * (Read / Write) and waits for a response. Once we get some response
+ * from the server, it is interpreted and ensured to be correct.
+ * If not, we keep on poking the server for data until we eventually
+ * give up.
+ * Return Value: This function will return the "opcode" received from
+ * the remote server, i.e.
+ * -> ERROR_OPCODE: If the remote server responded with "Error" or if
+ *    the client was unable to send / receive anything from the server.
+ * -> DATA_OPCODE:  If the remote server responded with "Data".
+ * -> ACK_OPCODE:   If the remote server responded with "Ack".
+ */
+static int tftp_send_request(int sock, uint8_t request,
+			     const char *remote_file, const char *mode)
+{
+	uint8_t    retx_cnt = 0;
+	uint32_t   req_size;
+
+	/* Create TFTP Request. */
+	req_size = make_request(remote_file, mode, request);
+
+send_req:
+
+	/* Send this request to the server. */
+	if (send(sock, tftpc_buffer, req_size, 0)) {
+		if (tftpc_recv_data(sock)) {
+			return sys_get_be16(tftpc_buffer);
+		}
+	}
+
+	/* No of times we had to re-tx this "request". */
+	retx_cnt++;
+
+	/* Log this out. */
+	LOG_DBG("Unable to get data from the TFTP Server.");
+	LOG_DBG("no_of_retransmists = %d", retx_cnt);
+
+	/* Are we retransmitting? */
+	if (retx_cnt < TFTP_REQ_RETX) {
+		LOG_DBG("Are we re-transmitting: YES");
+		goto send_req;
+	}
+
+	LOG_DBG("Are we re-transmitting: NO");
+	return ERROR_OPCODE;
+}
+
+/* Name: tftp_get
+ * Description: This function gets "file" from the remote server.
+ */
+int tftp_get(struct sockaddr *server, struct tftpc *client,
+	     const char *remote_file, const char *mode)
+{
+
+	int32_t   stat     = TFTPC_UNKNOWN_FAILURE;
+	uint8_t    retx_cnt = 0;
+	int32_t   sock;
+
+	/* Re-init the global "block number" variable. */
+	tftpc_block_no = 1;
+	tftpc_index    = 0;
+
+	/* Create Socket for TFTP (IPv4 / UDP) */
+	sock = socket(server->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0) {
+		LOG_ERR("Failed to create UDP socket (IPv4): %d", errno);
+		return -errno;
+	}
+
+	/* Connect with the address.  */
+	stat = connect(sock, server, sizeof(struct sockaddr_in6));
+	if (stat < 0) {
+		LOG_ERR("Cannot connect to UDP remote (IPv4): %d", errno);
+		return -errno;
+	}
+
+	/* Obtain Global Lock before accessing critical resources. */
+	k_mutex_lock(&tftpc_lock, K_FOREVER);
+
+	/* Send out the request to the TFTP Server. */
+	stat = tftp_send_request(sock, READ_REQUEST, remote_file, mode);
+	if (stat == ERROR_OPCODE) {
+		LOG_ERR("Server responded with error.");
+		return TFTPC_REMOTE_ERROR;
+	}
+
+process_resp:
+
+	/* Process server response. */
+	stat = tftpc_process_resp(sock, client);
+	if (stat == TFTPC_BUFFER_OVERFLOW ||
+	    stat == TFTPC_SUCCESS) {
+		goto req_done;
+	}
+
+tftpc_recv:
+
+	/* More data is available - Read (or we read a duplicate). */
+	stat = tftpc_recv_data(sock);
+	if (stat <= 0) {
+		/* No response from server. */
+		LOG_DBG("Server response timeout.");
+
+		/* Retries exhausted ? */
+		if (++retx_cnt >= TFTP_REQ_RETX) {
+			LOG_ERR("No more retransmits available. Exiting");
+			return TFTPC_RETRIES_EXHAUSTED;
+		}
+
+		/* Start Retransmission. */
+		LOG_DBG("Starting Re-transmission.");
+		send_ack(sock, tftpc_block_no);
+		goto tftpc_recv;
+	}
+
+	/* Received response from the server. */
+	LOG_DBG("Received data of size: %d", stat);
+	goto process_resp;
+
+req_done:
+	/* Clean up. */
+	k_mutex_unlock(&tftpc_lock);
+	close(sock);
+	return stat;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/CMakeLists.txt	(working copy)
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+zephyr_sources(
+  tls_credentials.c
+)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/Kconfig	(working copy)
@@ -0,0 +1,30 @@
+# Copyright (c) 2018 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig TLS_CREDENTIALS
+	bool "TLS credentials management"
+	help
+	  Enable TLS credentials management subsystem.
+
+if TLS_CREDENTIALS
+
+config TLS_MAX_CREDENTIALS_NUMBER
+	int "Maximum number of TLS credentials"
+	default 4
+	help
+	  Maximum number of TLS credentials that can be registered.
+
+config TLS_CREDENTIAL_FILENAMES
+	bool "Specify TLS credential filenames"
+	depends on NET_SOCKETS_OFFLOAD
+	help
+	  Allows clients of the socket APIs to specify filenames
+	  of security certificates and private keys
+	  to use during subsequent TLS/SSL negotiations.
+	  The secure files will have been previously provisioned to the
+	  device's secure file system; eg, via a vendor tool or
+	  by executing a separate binary.
+	  This option is currently only available for secure
+	  socket offload devices.
+
+endif # TLS_CREDENTIALS
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_credentials.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_credentials.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_credentials.c	(working copy)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+
+#include <init.h>
+#include <kernel.h>
+
+#include "tls_internal.h"
+
+/* Global pool of credentials shared among TLS contexts. */
+static struct tls_credential credentials[CONFIG_TLS_MAX_CREDENTIALS_NUMBER];
+
+/* A mutex for protecting access to the credentials array. */
+static struct k_mutex credential_lock;
+
+static int credentials_init(const struct device *unused)
+{
+	(void)memset(credentials, 0, sizeof(credentials));
+
+	k_mutex_init(&credential_lock);
+
+	return 0;
+}
+SYS_INIT(credentials_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
+
+static struct tls_credential *unused_credential_get(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(credentials); i++) {
+		if (credentials[i].type == TLS_CREDENTIAL_NONE) {
+			return &credentials[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct tls_credential *credential_get(sec_tag_t tag,
+				      enum tls_credential_type type)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(credentials); i++) {
+		if (credentials[i].type == type && credentials[i].tag == tag) {
+			return &credentials[i];
+		}
+	}
+
+	return NULL;
+}
+
+struct tls_credential *credential_next_get(sec_tag_t tag,
+					   struct tls_credential *iter)
+{
+	int i;
+
+	if (!iter) {
+		iter = credentials;
+	} else {
+		iter++;
+	}
+
+	for (i = iter - credentials; i < ARRAY_SIZE(credentials); i++) {
+		if (credentials[i].type != TLS_CREDENTIAL_NONE &&
+		    credentials[i].tag == tag) {
+			return &credentials[i];
+		}
+	}
+
+	return NULL;
+}
+
+void credentials_lock(void)
+{
+	k_mutex_lock(&credential_lock, K_FOREVER);
+}
+
+void credentials_unlock(void)
+{
+	k_mutex_unlock(&credential_lock);
+}
+
+int tls_credential_add(sec_tag_t tag, enum tls_credential_type type,
+		       const void *cred, size_t credlen)
+{
+	struct tls_credential *credential;
+	int ret = 0;
+
+	credentials_lock();
+
+	credential = credential_get(tag, type);
+	if (credential != NULL) {
+		ret = -EEXIST;
+		goto exit;
+	}
+
+	credential = unused_credential_get();
+	if (credential == NULL) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	credential->tag = tag;
+	credential->type = type;
+	credential->buf = cred;
+	credential->len = credlen;
+
+exit:
+	credentials_unlock();
+
+	return ret;
+}
+
+int tls_credential_get(sec_tag_t tag, enum tls_credential_type type,
+		       void *cred, size_t *credlen)
+{
+	struct tls_credential *credential;
+	int ret = 0;
+
+	credentials_lock();
+
+	credential = credential_get(tag, type);
+	if (credential == NULL) {
+		ret = -ENOENT;
+		goto exit;
+	}
+
+	if (credential->len > *credlen) {
+		ret = -EFBIG;
+		goto exit;
+	}
+
+	*credlen = credential->len;
+	memcpy(cred, credential->buf, credential->len);
+
+exit:
+	credentials_unlock();
+
+	return ret;
+}
+
+int tls_credential_delete(sec_tag_t tag, enum tls_credential_type type)
+{
+	struct tls_credential *credential;
+	int ret = 0;
+
+	credentials_lock();
+
+	credential = credential_get(tag, type);
+
+	if (!credential) {
+		ret = -ENOENT;
+		goto exit;
+	}
+
+	(void)memset(credential, 0, sizeof(struct tls_credential));
+	credential->type = TLS_CREDENTIAL_NONE;
+
+exit:
+	credentials_unlock();
+
+	return ret;
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/tls_credentials/tls_internal.h	(working copy)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/** @file
+ * @brief Internal API for fetching TLS credentials
+ */
+
+#ifndef __TLS_INTERNAL_H
+#define __TLS_INTERNAL_H
+
+#include <net/tls_credentials.h>
+
+/* Internal structure representing TLS credential. */
+struct tls_credential {
+	/* TLS credential type. */
+	enum tls_credential_type type;
+
+	/* Secure tag that credential can be referenced with. */
+	sec_tag_t tag;
+
+	/* A pointer to the credential buffer. */
+	const void *buf;
+
+	/* Credential length. */
+	size_t len;
+};
+
+/* Lock TLS credential access. */
+void credentials_lock(void);
+
+/* Unlock TLS credential access. */
+void credentials_unlock(void);
+
+/* Function for getting credential by tag and type.
+ *
+ * Note, that to assure thread safety, credential access should be locked with
+ * credentials_lock before calling this function.
+ */
+struct tls_credential *credential_get(sec_tag_t tag,
+				      enum tls_credential_type type);
+
+
+/* Function for iterating over credentials by tag.
+ *
+ * Note, that to assure thread safety, credential access should be locked with
+ * credentials_lock before calling this function.
+ */
+struct tls_credential *credential_next_get(sec_tag_t tag,
+					   struct tls_credential *iter);
+
+#endif /* __TLS_INTERNAL_H */
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/CMakeLists.txt	(working copy)
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_sources(
+  addr_utils.c
+)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/addr_utils.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/addr_utils.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/utils/addr_utils.c	(working copy)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 Linaro Limited
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef CONFIG_NET_SOCKETS
+
+#include <net/socketutils.h>
+
+const char *net_addr_str_find_port(const char *addr_str)
+{
+	const char *p = strrchr(addr_str, ':');
+
+	if (p == NULL) {
+		return NULL;
+	}
+
+	/* If it's not IPv6 numeric notation, we guaranteedly got a port */
+	if (*addr_str != '[') {
+		return p + 1;
+	}
+
+	/* IPv6 numeric address, and ':' preceded by ']' */
+	if (p[-1] == ']') {
+		return p + 1;
+	}
+
+	/* Otherwise, just raw IPv6 address, ':' is component separator */
+	return NULL;
+}
+
+int net_getaddrinfo_addr_str(const char *addr_str, const char *def_port,
+			     const struct addrinfo *hints,
+			     struct addrinfo **res)
+{
+	const char *port;
+	char host[NI_MAXHOST];
+
+	if (addr_str == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	port  = net_addr_str_find_port(addr_str);
+
+	if (port == NULL) {
+		port = def_port;
+	} else {
+		int host_len = port - addr_str - 1;
+
+		if (host_len > sizeof(host) - 1) {
+			errno = EINVAL;
+			return -1;
+		}
+		strncpy(host, addr_str, host_len + 1);
+		host[host_len] = '\0';
+		addr_str = host;
+	}
+
+	return getaddrinfo(addr_str, port, hints, res);
+}
+
+#endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/CMakeLists.txt
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/CMakeLists.txt	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/CMakeLists.txt	(working copy)
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library_named(websocket_client)
+zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/lib/sockets)
+
+zephyr_library_sources(
+  websocket.c
+)
+
+zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/Kconfig
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/Kconfig	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/Kconfig	(working copy)
@@ -0,0 +1,29 @@
+# Copyright (c) 2019 Intel Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+menuconfig WEBSOCKET_CLIENT
+	bool "Websocket client support [EXPERIMENTAL]"
+	select NET_SOCKETS
+	select HTTP_PARSER
+	select HTTP_PARSER_URL
+	select HTTP_CLIENT
+	select MBEDTLS
+	select BASE64
+	help
+	  Enable Websocket client library.
+
+if WEBSOCKET_CLIENT
+
+config WEBSOCKET_MAX_CONTEXTS
+	int "Max number of websockets to allocate"
+	default 1
+	help
+	  How many Websockets can be created in the system.
+
+module = NET_WEBSOCKET
+module-dep = NET_LOG
+module-str = Log level for Websocket
+module-help = Enable debug message of Websocket client library.
+source "subsys/net/Kconfig.template.log_config.net"
+
+endif
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket.c	(working copy)
@@ -0,0 +1,991 @@
+/** @file
+ * @brief Websocket client API
+ *
+ * An API for applications to setup a websocket connections.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <logging/log.h>
+LOG_MODULE_REGISTER(net_websocket, CONFIG_NET_WEBSOCKET_LOG_LEVEL);
+
+#include <kernel.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <sys/fdtable.h>
+#include <net/net_core.h>
+#include <net/net_ip.h>
+#include <net/socket.h>
+#include <net/http_client.h>
+#include <net/websocket.h>
+
+#include <random/rand32.h>
+#include <sys/byteorder.h>
+#include <sys/base64.h>
+#include <mbedtls/sha1.h>
+
+#include "net_private.h"
+#include "sockets_internal.h"
+#include "websocket_internal.h"
+
+/* If you want to see the data that is being sent or received,
+ * then you can enable debugging and set the following variables to 1.
+ * This will print a lot of data so is not enabled by default.
+ */
+#define HEXDUMP_SENT_PACKETS 0
+#define HEXDUMP_RECV_PACKETS 0
+
+static struct websocket_context contexts[CONFIG_WEBSOCKET_MAX_CONTEXTS];
+
+static struct k_sem contexts_lock;
+
+extern const struct socket_op_vtable sock_fd_op_vtable;
+static const struct socket_op_vtable websocket_fd_op_vtable;
+
+#if defined(CONFIG_NET_TEST)
+int verify_sent_and_received_msg(struct msghdr *msg, bool split_msg);
+#endif
+
+static const char *opcode2str(enum websocket_opcode opcode)
+{
+	switch (opcode) {
+	case WEBSOCKET_OPCODE_DATA_TEXT:
+		return "TEXT";
+	case WEBSOCKET_OPCODE_DATA_BINARY:
+		return "BIN";
+	case WEBSOCKET_OPCODE_CONTINUE:
+		return "CONT";
+	case WEBSOCKET_OPCODE_CLOSE:
+		return "CLOSE";
+	case WEBSOCKET_OPCODE_PING:
+		return "PING";
+	case WEBSOCKET_OPCODE_PONG:
+		return "PONG";
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
+static int websocket_context_ref(struct websocket_context *ctx)
+{
+	int old_rc = atomic_inc(&ctx->refcount);
+
+	return old_rc + 1;
+}
+
+static int websocket_context_unref(struct websocket_context *ctx)
+{
+	int old_rc = atomic_dec(&ctx->refcount);
+
+	if (old_rc != 1) {
+		return old_rc - 1;
+	}
+
+	return 0;
+}
+
+static inline bool websocket_context_is_used(struct websocket_context *ctx)
+{
+	NET_ASSERT(ctx);
+
+	return !!atomic_get(&ctx->refcount);
+}
+
+static struct websocket_context *websocket_get(void)
+{
+	struct websocket_context *ctx = NULL;
+	int i;
+
+	k_sem_take(&contexts_lock, K_FOREVER);
+
+	for (i = 0; i < ARRAY_SIZE(contexts); i++) {
+		if (websocket_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		websocket_context_ref(&contexts[i]);
+		ctx = &contexts[i];
+		break;
+	}
+
+	k_sem_give(&contexts_lock);
+
+	return ctx;
+}
+
+static struct websocket_context *websocket_find(int real_sock)
+{
+	struct websocket_context *ctx = NULL;
+	int i;
+
+	k_sem_take(&contexts_lock, K_FOREVER);
+
+	for (i = 0; i < ARRAY_SIZE(contexts); i++) {
+		if (!websocket_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		if (contexts[i].real_sock != real_sock) {
+			continue;
+		}
+
+		ctx = &contexts[i];
+		break;
+	}
+
+	k_sem_give(&contexts_lock);
+
+	return ctx;
+}
+
+static void response_cb(struct http_response *rsp,
+			enum http_final_call final_data,
+			void *user_data)
+{
+	struct websocket_context *ctx = user_data;
+
+	if (final_data == HTTP_DATA_MORE) {
+		NET_DBG("[%p] Partial data received (%zd bytes)", ctx,
+			rsp->data_len);
+		ctx->all_received = false;
+	} else if (final_data == HTTP_DATA_FINAL) {
+		NET_DBG("[%p] All the data received (%zd bytes)", ctx,
+			rsp->data_len);
+		ctx->all_received = true;
+	}
+}
+
+static int on_header_field(struct http_parser *parser, const char *at,
+			   size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	struct websocket_context *ctx = req->internal.user_data;
+	const char *ws_accept_str = "Sec-WebSocket-Accept";
+	uint16_t len;
+
+	len = strlen(ws_accept_str);
+	if (length >= len && strncasecmp(at, ws_accept_str, len) == 0) {
+		ctx->sec_accept_present = true;
+	}
+
+	if (ctx->http_cb && ctx->http_cb->on_header_field) {
+		ctx->http_cb->on_header_field(parser, at, length);
+	}
+
+	return 0;
+}
+
+#define MAX_SEC_ACCEPT_LEN 32
+
+static int on_header_value(struct http_parser *parser, const char *at,
+			   size_t length)
+{
+	struct http_request *req = CONTAINER_OF(parser,
+						struct http_request,
+						internal.parser);
+	struct websocket_context *ctx = req->internal.user_data;
+	char str[MAX_SEC_ACCEPT_LEN];
+
+	if (ctx->sec_accept_present) {
+		int ret;
+		size_t olen;
+
+		ctx->sec_accept_ok = false;
+		ctx->sec_accept_present = false;
+
+		ret = base64_encode(str, sizeof(str) - 1, &olen,
+				    ctx->sec_accept_key,
+				    WS_SHA1_OUTPUT_LEN);
+		if (ret == 0) {
+			if (strncmp(at, str, length)) {
+				NET_DBG("[%p] Security keys do not match "
+					"%s vs %s", ctx, str, at);
+			} else {
+				ctx->sec_accept_ok = true;
+			}
+		}
+	}
+
+	if (ctx->http_cb && ctx->http_cb->on_header_value) {
+		ctx->http_cb->on_header_value(parser, at, length);
+	}
+
+	return 0;
+}
+
+int websocket_connect(int sock, struct websocket_request *wreq,
+		      int32_t timeout, void *user_data)
+{
+	/* This is the expected Sec-WebSocket-Accept key. We are storing a
+	 * pointer to this in ctx but the value is only used for the duration
+	 * of this function call so there is no issue even if this variable
+	 * is allocated from stack.
+	 */
+	uint8_t sec_accept_key[WS_SHA1_OUTPUT_LEN];
+	struct http_parser_settings http_parser_settings;
+	struct websocket_context *ctx;
+	struct http_request req;
+	int ret, fd, key_len;
+	size_t olen;
+	char key_accept[MAX_SEC_ACCEPT_LEN + sizeof(WS_MAGIC)];
+	uint32_t rnd_value = sys_rand32_get();
+	char sec_ws_key[] =
+		"Sec-WebSocket-Key: 0123456789012345678901==\r\n";
+	char *headers[] = {
+		sec_ws_key,
+		"Upgrade: websocket\r\n",
+		"Connection: Upgrade\r\n",
+		"Sec-WebSocket-Version: 13\r\n",
+		NULL
+	};
+
+	fd = -1;
+
+	if (sock < 0 || wreq == NULL || wreq->host == NULL ||
+	    wreq->url == NULL) {
+		return -EINVAL;
+	}
+
+	ctx = websocket_find(sock);
+	if (ctx) {
+		NET_DBG("[%p] Websocket for sock %d already exists!", ctx,
+			sock);
+		return -EEXIST;
+	}
+
+	ctx = websocket_get();
+	if (!ctx) {
+		return -ENOENT;
+	}
+
+	ctx->real_sock = sock;
+	ctx->tmp_buf = wreq->tmp_buf;
+	ctx->tmp_buf_len = wreq->tmp_buf_len;
+	ctx->sec_accept_key = sec_accept_key;
+	ctx->http_cb = wreq->http_cb;
+
+	mbedtls_sha1_ret((const unsigned char *)&rnd_value, sizeof(rnd_value),
+			 sec_accept_key);
+
+	ret = base64_encode(sec_ws_key + sizeof("Sec-Websocket-Key: ") - 1,
+			    sizeof(sec_ws_key) -
+					sizeof("Sec-Websocket-Key: "),
+			    &olen, sec_accept_key,
+			    /* We are only interested in 16 first bytes so
+			     * substract 4 from the SHA-1 length
+			     */
+			    sizeof(sec_accept_key) - 4);
+	if (ret) {
+		NET_DBG("[%p] Cannot encode base64 (%d)", ctx, ret);
+		goto out;
+	}
+
+	if ((olen + sizeof("Sec-Websocket-Key: ") + 2) > sizeof(sec_ws_key)) {
+		NET_DBG("[%p] Too long message (%zd > %zd)", ctx,
+			olen + sizeof("Sec-Websocket-Key: ") + 2,
+			sizeof(sec_ws_key));
+		ret = -EMSGSIZE;
+		goto out;
+	}
+
+	memcpy(sec_ws_key + sizeof("Sec-Websocket-Key: ") - 1 + olen,
+	       HTTP_CRLF, sizeof(HTTP_CRLF));
+
+	memset(&req, 0, sizeof(req));
+
+	req.method = HTTP_GET;
+	req.url = wreq->url;
+	req.host = wreq->host;
+	req.protocol = "HTTP/1.1";
+	req.header_fields = (const char **)headers;
+	req.optional_headers_cb = wreq->optional_headers_cb;
+	req.optional_headers = wreq->optional_headers;
+	req.response = response_cb;
+	req.http_cb = &http_parser_settings;
+	req.recv_buf = wreq->tmp_buf;
+	req.recv_buf_len = wreq->tmp_buf_len;
+
+	/* We need to catch the Sec-WebSocket-Accept field in order to verify
+	 * that it contains the stuff that we sent in Sec-WebSocket-Key field
+	 * so setup HTTP callbacks so that we will get the needed fields.
+	 */
+	if (ctx->http_cb) {
+		memcpy(&http_parser_settings, ctx->http_cb,
+		       sizeof(http_parser_settings));
+	} else {
+		memset(&http_parser_settings, 0, sizeof(http_parser_settings));
+	}
+
+	http_parser_settings.on_header_field = on_header_field;
+	http_parser_settings.on_header_value = on_header_value;
+
+	/* Pre-calculate the expected Sec-Websocket-Accept field */
+	key_len = MIN(sizeof(key_accept) - 1, olen);
+	strncpy(key_accept, sec_ws_key + sizeof("Sec-Websocket-Key: ") - 1,
+		key_len);
+
+	olen = MIN(sizeof(key_accept) - 1 - key_len, sizeof(WS_MAGIC) - 1);
+	strncpy(key_accept + key_len, WS_MAGIC, olen);
+
+	/* This SHA-1 value is then checked when we receive the response */
+	mbedtls_sha1_ret(key_accept, olen + key_len, sec_accept_key);
+
+	ret = http_client_req(sock, &req, timeout, ctx);
+	if (ret < 0) {
+		NET_DBG("[%p] Cannot connect to Websocket host %s", ctx,
+			wreq->host);
+		ret = -ECONNABORTED;
+		goto out;
+	}
+
+	if (!(ctx->all_received && ctx->sec_accept_ok)) {
+		NET_DBG("[%p] WS handshake failed (%d/%d)", ctx,
+			ctx->all_received, ctx->sec_accept_ok);
+		ret = -ECONNABORTED;
+		goto out;
+	}
+
+	ctx->user_data = user_data;
+
+	fd = z_reserve_fd();
+	if (fd < 0) {
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	ctx->sock = fd;
+	z_finalize_fd(fd, ctx,
+		      (const struct fd_op_vtable *)&websocket_fd_op_vtable);
+
+	/* Call the user specified callback and if it accepts the connection
+	 * then continue.
+	 */
+	if (wreq->cb) {
+		ret = wreq->cb(fd, &req, user_data);
+		if (ret < 0) {
+			NET_DBG("[%p] Connection aborted (%d)", ctx, ret);
+			goto out;
+		}
+	}
+
+	NET_DBG("[%p] WS connection to peer established (fd %d)", ctx, fd);
+
+	/* We will re-use the temp buffer in receive function if needed but
+	 * in order that to work the amount of data in buffer must be set to 0
+	 */
+	ctx->tmp_buf_pos = 0;
+
+	return fd;
+
+out:
+	if (fd >= 0) {
+		(void)close(fd);
+	}
+
+	websocket_context_unref(ctx);
+	return ret;
+}
+
+int websocket_disconnect(int ws_sock)
+{
+	return close(ws_sock);
+}
+
+static int websocket_interal_disconnect(struct websocket_context *ctx)
+{
+	int ret;
+
+	if (ctx == NULL) {
+		return -ENOENT;
+	}
+
+	NET_DBG("[%p] Disconnecting", ctx);
+
+	ret = close(ctx->real_sock);
+
+	websocket_context_unref(ctx);
+
+	return ret;
+}
+
+static int websocket_close_vmeth(void *obj)
+{
+	struct websocket_context *ctx = obj;
+	int ret;
+
+	ret = websocket_interal_disconnect(ctx);
+	if (ret < 0) {
+		NET_DBG("[%p] Cannot close (%d)", obj, ret);
+
+		errno = -ret;
+		return -1;
+	}
+
+	return ret;
+}
+
+static int websocket_ioctl_vmeth(void *obj, unsigned int request, va_list args)
+{
+	return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
+}
+
+static int websocket_prepare_and_send(struct websocket_context *ctx,
+				      uint8_t *header, size_t header_len,
+				      uint8_t *payload, size_t payload_len,
+				      int32_t timeout)
+{
+	struct iovec io_vector[2];
+	struct msghdr msg;
+
+	io_vector[0].iov_base = header;
+	io_vector[0].iov_len = header_len;
+	io_vector[1].iov_base = payload;
+	io_vector[1].iov_len = payload_len;
+
+	memset(&msg, 0, sizeof(msg));
+
+	msg.msg_iov = io_vector;
+	msg.msg_iovlen = ARRAY_SIZE(io_vector);
+
+	if (HEXDUMP_SENT_PACKETS) {
+		LOG_HEXDUMP_DBG(header, header_len, "Header");
+		LOG_HEXDUMP_DBG(payload, payload_len, "Payload");
+	}
+
+#if defined(CONFIG_NET_TEST)
+	/* Simulate a case where the payload is split to two. The unit test
+	 * does not set mask bit in this case.
+	 */
+	return verify_sent_and_received_msg(&msg, !(header[1] & BIT(7)));
+#else
+	k_timeout_t tout = K_FOREVER;
+
+	if (timeout != SYS_FOREVER_MS) {
+		tout = K_MSEC(timeout);
+	}
+
+	return sendmsg(ctx->real_sock, &msg,
+		       K_TIMEOUT_EQ(tout, K_NO_WAIT) ? MSG_DONTWAIT : 0);
+#endif /* CONFIG_NET_TEST */
+}
+
+int websocket_send_msg(int ws_sock, const uint8_t *payload, size_t payload_len,
+		       enum websocket_opcode opcode, bool mask, bool final,
+		       int32_t timeout)
+{
+	struct websocket_context *ctx;
+	uint8_t header[MAX_HEADER_LEN], hdr_len = 2;
+	uint8_t *data_to_send = (uint8_t *)payload;
+	int ret;
+
+	if (opcode != WEBSOCKET_OPCODE_DATA_TEXT &&
+	    opcode != WEBSOCKET_OPCODE_DATA_BINARY &&
+	    opcode != WEBSOCKET_OPCODE_CONTINUE &&
+	    opcode != WEBSOCKET_OPCODE_CLOSE &&
+	    opcode != WEBSOCKET_OPCODE_PING &&
+	    opcode != WEBSOCKET_OPCODE_PONG) {
+		return -EINVAL;
+	}
+
+#if defined(CONFIG_NET_TEST)
+	/* Websocket unit test does not use socket layer but feeds
+	 * the data directly here when testing this function.
+	 */
+	ctx = INT_TO_POINTER(ws_sock);
+#else
+	ctx = z_get_fd_obj(ws_sock, NULL, 0);
+	if (ctx == NULL) {
+		return -EBADF;
+	}
+
+	if (!PART_OF_ARRAY(contexts, ctx)) {
+		return -ENOENT;
+	}
+#endif /* CONFIG_NET_TEST */
+
+	NET_DBG("[%p] Len %zd %s/%d/%s", ctx, payload_len, opcode2str(opcode),
+		mask, final ? "final" : "more");
+
+	memset(header, 0, sizeof(header));
+
+	/* Is this the last packet? */
+	header[0] = final ? BIT(7) : 0;
+
+	/* Text, binary, ping, pong or close ? */
+	header[0] |= opcode;
+
+	/* Masking */
+	header[1] = mask ? BIT(7) : 0;
+
+	if (payload_len < 126) {
+		header[1] |= payload_len;
+	} else if (payload_len < 65536) {
+		header[1] |= 126;
+		header[2] = payload_len >> 8;
+		header[3] = payload_len;
+		hdr_len += 2;
+	} else {
+		header[1] |= 127;
+		header[2] = 0;
+		header[3] = 0;
+		header[4] = 0;
+		header[5] = 0;
+		header[6] = payload_len >> 24;
+		header[7] = payload_len >> 16;
+		header[8] = payload_len >> 8;
+		header[9] = payload_len;
+		hdr_len += 8;
+	}
+
+	/* Add masking value if needed */
+	if (mask) {
+		int i;
+
+		ctx->masking_value = sys_rand32_get();
+
+		header[hdr_len++] |= ctx->masking_value >> 24;
+		header[hdr_len++] |= ctx->masking_value >> 16;
+		header[hdr_len++] |= ctx->masking_value >> 8;
+		header[hdr_len++] |= ctx->masking_value;
+
+		data_to_send = k_malloc(payload_len);
+		if (!data_to_send) {
+			return -ENOMEM;
+		}
+
+		memcpy(data_to_send, payload, payload_len);
+
+		for (i = 0; i < payload_len; i++) {
+			data_to_send[i] ^=
+				ctx->masking_value >> (8 * (3 - i % 4));
+		}
+	}
+
+	ret = websocket_prepare_and_send(ctx, header, hdr_len,
+					 data_to_send, payload_len, timeout);
+	if (ret < 0) {
+		NET_DBG("Cannot send ws msg (%d)", -errno);
+		goto quit;
+	}
+
+quit:
+	if (data_to_send != payload) {
+		k_free(data_to_send);
+	}
+
+	return ret - hdr_len;
+}
+
+static bool websocket_parse_header(uint8_t *buf, size_t buf_len, bool *masked,
+				   uint32_t *mask_value, uint64_t *message_length,
+				   uint32_t *message_type_flag,
+				   size_t *header_len)
+{
+	uint8_t len_len; /* length of the length field in header */
+	uint8_t len;     /* message length byte */
+	uint16_t value;
+
+	value = sys_get_be16(&buf[0]);
+	if (value & 0x8000) {
+		*message_type_flag |= WEBSOCKET_FLAG_FINAL;
+	}
+
+	switch (value & 0x0f00) {
+	case 0x0100:
+		*message_type_flag |= WEBSOCKET_FLAG_TEXT;
+		break;
+	case 0x0200:
+		*message_type_flag |= WEBSOCKET_FLAG_BINARY;
+		break;
+	case 0x0800:
+		*message_type_flag |= WEBSOCKET_FLAG_CLOSE;
+		break;
+	case 0x0900:
+		*message_type_flag |= WEBSOCKET_FLAG_PING;
+		break;
+	case 0x0A00:
+		*message_type_flag |= WEBSOCKET_FLAG_PONG;
+		break;
+	}
+
+	len = value & 0x007f;
+	if (len < 126) {
+		len_len = 0;
+		*message_length = len;
+	} else if (len == 126) {
+		len_len = 2;
+		*message_length = sys_get_be16(&buf[2]);
+	} else {
+		len_len = 8;
+		*message_length = sys_get_be64(&buf[2]);
+	}
+
+	/* Minimum websocket header is 2 bytes, header length might be
+	 * bigger depending on length field len.
+	 */
+	*header_len = MIN_HEADER_LEN + len_len;
+
+	if (buf_len >= *header_len) {
+		if (value & 0x0080) {
+			*masked = true;
+			*mask_value = sys_get_be32(&buf[2 + len_len]);
+			*header_len += 4;
+		} else {
+			*masked = false;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len,
+		       uint32_t *message_type, uint64_t *remaining, int32_t timeout)
+{
+	struct websocket_context *ctx;
+	size_t header_len = 0;
+	int recv_len = 0;
+	size_t can_copy, left;
+	int ret;
+	k_timeout_t tout = K_FOREVER;
+
+	if (timeout != SYS_FOREVER_MS) {
+		tout = K_MSEC(timeout);
+	}
+
+#if defined(CONFIG_NET_TEST)
+	/* Websocket unit test does not use socket layer but feeds
+	 * the data directly here when testing this function.
+	 */
+	struct test_data {
+		uint8_t *input_buf;
+		size_t input_len;
+		struct websocket_context *ctx;
+	};
+
+	struct test_data *test_data = INT_TO_POINTER(ws_sock);
+
+	ctx = test_data->ctx;
+#else
+	ctx = z_get_fd_obj(ws_sock, NULL, 0);
+	if (ctx == NULL) {
+		return -EBADF;
+	}
+
+	if (!PART_OF_ARRAY(contexts, ctx)) {
+		return -ENOENT;
+	}
+#endif /* CONFIG_NET_TEST */
+
+	/* If we have not received the websocket header yet, read it first */
+	if (!ctx->header_received) {
+#if defined(CONFIG_NET_TEST)
+		size_t input_len = MIN(ctx->tmp_buf_len - ctx->tmp_buf_pos,
+				       test_data->input_len);
+
+		memcpy(&ctx->tmp_buf[ctx->tmp_buf_pos], test_data->input_buf,
+		       input_len);
+		test_data->input_buf += input_len;
+		ret = input_len;
+#else
+		ret = recv(ctx->real_sock, &ctx->tmp_buf[ctx->tmp_buf_pos],
+			   ctx->tmp_buf_len - ctx->tmp_buf_pos,
+			   K_TIMEOUT_EQ(tout, K_NO_WAIT) ? MSG_DONTWAIT : 0);
+#endif /* CONFIG_NET_TEST */
+
+		if (ret < 0) {
+			return -errno;
+		}
+
+		if (ret == 0) {
+			/* Socket closed */
+			return 0;
+		}
+
+		ctx->tmp_buf_pos += ret;
+
+		if (ctx->tmp_buf_pos >= MIN_HEADER_LEN) {
+			bool masked;
+
+			/* Now we will be able to figure out what is the
+			 * actual size of the header.
+			 */
+			if (websocket_parse_header(&ctx->tmp_buf[0],
+						   ctx->tmp_buf_pos,
+						   &masked,
+						   &ctx->masking_value,
+						   &ctx->message_len,
+						   &ctx->message_type,
+						   &header_len)) {
+				ctx->masked = masked;
+
+				if (message_type) {
+					*message_type = ctx->message_type;
+				}
+			} else {
+				return -EAGAIN;
+			}
+		} else {
+			return -EAGAIN;
+		}
+
+		if (ctx->tmp_buf_pos < header_len) {
+			return -EAGAIN;
+		}
+
+		/* All of the header is now received, we can read the payload
+		 * data next.
+		 */
+		ctx->header_received = true;
+
+		if (HEXDUMP_RECV_PACKETS) {
+			LOG_HEXDUMP_DBG(&ctx->tmp_buf[0], header_len,
+					"Header");
+			NET_DBG("[%p] masked %d mask 0x%04x hdr %zd msg %zd",
+				ctx, ctx->masked,
+				ctx->masked ? ctx->masking_value : 0,
+				header_len, (size_t)ctx->message_len);
+		}
+
+		ctx->total_read = 0;
+
+		memmove(ctx->tmp_buf, &ctx->tmp_buf[header_len],
+			ctx->tmp_buf_len - header_len);
+		ctx->tmp_buf_pos -= header_len;
+
+		if (ctx->tmp_buf_pos == 0) {
+			/* No data after the header, let the caller call
+			 * this function again to get the payload.
+			 */
+			return -EAGAIN;
+		}
+
+		NET_DBG("There is %zd bytes of data", ctx->tmp_buf_pos);
+	}
+
+	/* Now read the whole payload or parts of it */
+
+	if (ctx->tmp_buf_pos == 0) {
+		/* Read more data into temp buffer */
+#if defined(CONFIG_NET_TEST)
+		size_t input_len = MIN(ctx->tmp_buf_len, test_data->input_len);
+
+		memcpy(ctx->tmp_buf, test_data->input_buf, input_len);
+		test_data->input_buf += input_len;
+
+		ret = input_len;
+#else
+		ret = recv(ctx->real_sock, ctx->tmp_buf, ctx->tmp_buf_len,
+			   K_TIMEOUT_EQ(tout, K_NO_WAIT) ? MSG_DONTWAIT : 0);
+#endif /* CONFIG_NET_TEST */
+
+		if (ret < 0) {
+			return -errno;
+		}
+
+		if (ret == 0) {
+			return 0;
+		}
+
+		ctx->tmp_buf_pos = ret;
+	}
+
+	if (ctx->tmp_buf_pos <= buf_len) {
+		/* Is there already any data in the temp buffer? If yes,
+		 * just return it to the caller.
+		 */
+		can_copy = MIN(ctx->message_len - ctx->total_read,
+			       ctx->tmp_buf_pos);
+	} else {
+		/* We have more data in tmp buffer that will fit into
+		 * user buffer.
+		 */
+		can_copy = MIN(ctx->message_len - ctx->total_read, buf_len);
+	}
+
+	left = ctx->tmp_buf_pos - can_copy;
+
+	NET_ASSERT(ctx->tmp_buf_pos >= can_copy);
+
+	memmove(buf, ctx->tmp_buf, can_copy);
+	recv_len = can_copy;
+
+	if (left > 0) {
+		memmove(ctx->tmp_buf, &ctx->tmp_buf[can_copy], left);
+	}
+
+	ctx->tmp_buf_pos = left;
+	ctx->total_read += recv_len;
+
+	/* Unmask the data */
+	if (ctx->masked) {
+		/* As we might have less than 4 received bytes, we must select
+		 * which byte from masking value to take. The mask_shift will
+		 * tell that.
+		 */
+		int mask_shift = (ctx->total_read - recv_len) % sizeof(uint32_t);
+		int i;
+
+		for (i = 0; i < recv_len; i++) {
+			buf[i] ^= ctx->masking_value >>
+				(8 * (3 - (i + mask_shift) % 4));
+		}
+	}
+
+#if HEXDUMP_RECV_PACKETS
+	LOG_HEXDUMP_DBG(buf, recv_len, "Payload");
+#endif
+
+	if (remaining) {
+		*remaining = ctx->message_len - ctx->total_read;
+	}
+
+	/* Start to read the header again if all the data has been received */
+	if (ctx->message_len == ctx->total_read) {
+		ctx->header_received = false;
+		ctx->message_len = 0;
+		ctx->message_type = 0;
+		ctx->total_read = 0;
+	}
+
+	return recv_len;
+}
+
+static int websocket_send(struct websocket_context *ctx, const uint8_t *buf,
+			  size_t buf_len, int32_t timeout)
+{
+	int ret;
+
+	NET_DBG("[%p] Sending %zd bytes", ctx, buf_len);
+
+	ret = websocket_send_msg(ctx->sock, buf, buf_len,
+				 WEBSOCKET_OPCODE_DATA_TEXT,
+				 true, true, timeout);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	NET_DBG("[%p] Sent %d bytes", ctx, ret);
+
+	return ret;
+}
+
+static int websocket_recv(struct websocket_context *ctx, uint8_t *buf,
+			  size_t buf_len, int32_t timeout)
+{
+	uint32_t message_type;
+	uint64_t remaining;
+	int ret;
+
+	NET_DBG("[%p] Waiting data, buf len %zd bytes", ctx, buf_len);
+
+	/* TODO: add support for recvmsg() so that we could return the
+	 *       websocket specific information in ancillary data.
+	 */
+	ret = websocket_recv_msg(ctx->sock, buf, buf_len, &message_type,
+				 &remaining, timeout);
+	if (ret < 0) {
+		errno = -ret;
+		return -1;
+	}
+
+	NET_DBG("[%p] Received %d bytes", ctx, ret);
+
+	return ret;
+}
+
+static ssize_t websocket_read_vmeth(void *obj, void *buffer, size_t count)
+{
+	return (ssize_t)websocket_recv(obj, buffer, count, SYS_FOREVER_MS);
+}
+
+static ssize_t websocket_write_vmeth(void *obj, const void *buffer,
+				     size_t count)
+{
+	return (ssize_t)websocket_send(obj, buffer, count, SYS_FOREVER_MS);
+}
+
+static ssize_t websocket_sendto_ctx(void *obj, const void *buf, size_t len,
+				    int flags,
+				    const struct sockaddr *dest_addr,
+				    socklen_t addrlen)
+{
+	struct websocket_context *ctx = obj;
+	int32_t timeout = SYS_FOREVER_MS;
+
+	if (flags & ZSOCK_MSG_DONTWAIT) {
+		timeout = 0;
+	}
+
+	ARG_UNUSED(dest_addr);
+	ARG_UNUSED(addrlen);
+
+	return (ssize_t)websocket_send(ctx, buf, len, timeout);
+}
+
+static ssize_t websocket_recvfrom_ctx(void *obj, void *buf, size_t max_len,
+				      int flags, struct sockaddr *src_addr,
+				      socklen_t *addrlen)
+{
+	struct websocket_context *ctx = obj;
+	int32_t timeout = SYS_FOREVER_MS;
+
+	if (flags & ZSOCK_MSG_DONTWAIT) {
+		timeout = 0;
+	}
+
+	ARG_UNUSED(src_addr);
+	ARG_UNUSED(addrlen);
+
+	return (ssize_t)websocket_recv(ctx, buf, max_len, timeout);
+}
+
+static const struct socket_op_vtable websocket_fd_op_vtable = {
+	.fd_vtable = {
+		.read = websocket_read_vmeth,
+		.write = websocket_write_vmeth,
+		.close = websocket_close_vmeth,
+		.ioctl = websocket_ioctl_vmeth,
+	},
+	.sendto = websocket_sendto_ctx,
+	.recvfrom = websocket_recvfrom_ctx,
+};
+
+void websocket_context_foreach(websocket_context_cb_t cb, void *user_data)
+{
+	int i;
+
+	k_sem_take(&contexts_lock, K_FOREVER);
+
+	for (i = 0; i < ARRAY_SIZE(contexts); i++) {
+		if (!websocket_context_is_used(&contexts[i])) {
+			continue;
+		}
+
+		k_mutex_lock(&contexts[i].lock, K_FOREVER);
+
+		cb(&contexts[i], user_data);
+
+		k_mutex_unlock(&contexts[i].lock);
+	}
+
+	k_sem_give(&contexts_lock);
+}
+
+void websocket_init(void)
+{
+	k_sem_init(&contexts_lock, 1, UINT_MAX);
+}
Index: ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket_internal.h
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket_internal.h	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/subsys/net/lib/websocket/websocket_internal.h	(working copy)
@@ -0,0 +1,134 @@
+/** @file
+ @brief Websocket private header
+
+ This is not to be included by the application.
+ */
+
+/*
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <toolchain/common.h>
+
+#define WS_SHA1_OUTPUT_LEN 20
+
+/* Min Websocket header length */
+#define MIN_HEADER_LEN 2
+
+/* Max Websocket header length */
+#define MAX_HEADER_LEN 14
+
+/* From RFC 6455 chapter 4.2.2 */
+#define WS_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+/**
+ * Websocket connection information
+ */
+__net_socket struct websocket_context {
+	union {
+		/** User data.
+		 */
+		void *user_data;
+
+		/** This is used during HTTP handshake to verify that the
+		 * peer sent proper Sec-WebSocket-Accept key.
+		 */
+		uint8_t *sec_accept_key;
+	};
+
+	/** Reference count.
+	 */
+	atomic_t refcount;
+
+	/** Internal lock for protecting this context from multiple access.
+	 */
+	struct k_mutex lock;
+
+	/* The socket number is valid only after HTTP handshake is done
+	 * so we can share the memory for these.
+	 */
+	union {
+		/** HTTP parser settings for the application usage */
+		const struct http_parser_settings *http_cb;
+
+		/** The Websocket socket id. If data is sent via this socket, it
+		 * will automatically add Websocket headers etc into the data.
+		 */
+		int sock;
+	};
+
+	/** Temporary buffers used for HTTP handshakes and Websocket protocol
+	 * headers. User must provide the actual buffer where the headers are
+	 * stored temporarily.
+	 */
+	uint8_t *tmp_buf;
+
+	/** Temporary buffer length.
+	 */
+	size_t tmp_buf_len;
+
+	/** Current reading position in the tmp_buf
+	 */
+	size_t tmp_buf_pos;
+
+	/** The real TCP socket to use when sending Websocket data to peer.
+	 */
+	int real_sock;
+
+	/** Websocket connection masking value */
+	uint32_t masking_value;
+
+	/** Amount of data received. */
+	uint64_t total_read;
+
+	/** Message length */
+	uint64_t message_len;
+
+	/** Message type */
+	uint32_t message_type;
+
+	/** Is the message masked */
+	uint8_t masked : 1;
+
+	/** Did we receive Sec-WebSocket-Accept: field */
+	uint8_t sec_accept_present : 1;
+
+	/** Is Sec-WebSocket-Accept field correct */
+	uint8_t sec_accept_ok : 1;
+
+	/** Did we receive all from peer during HTTP handshake */
+	uint8_t all_received : 1;
+
+	/** Header received */
+	uint8_t header_received : 1;
+};
+
+/**
+ * @brief Disconnect the Websocket.
+ *
+ * @param sock Websocket id returned by websocket_connect() call.
+ *
+ * @return 0 if ok, <0 if error
+ */
+int websocket_disconnect(int sock);
+
+/**
+ * @typedef websocket_context_cb_t
+ * @brief Callback used while iterating over websocket contexts
+ *
+ * @param context A valid pointer on current websocket context
+ * @param user_data A valid pointer on some user data or NULL
+ */
+typedef void (*websocket_context_cb_t)(struct websocket_context *ctx,
+				       void *user_data);
+
+/**
+ * @brief Iterate over websocket context. This is mainly used by net-shell
+ * to show information about websockets.
+ *
+ * @param cb Websocket context callback
+ * @param user_data Caller specific data.
+ */
+void websocket_context_foreach(websocket_context_cb_t cb, void *user_data);
Index: ModuleDemo/BLE/CM0/User/utils/buf.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/buf.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/buf.c	(working copy)
@@ -0,0 +1,1101 @@
+/* buf.c - Buffer management */
+
+/*
+ * Copyright (c) 2015-2019 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_MODULE_NAME "net_buf"
+#define LOG_LEVEL CONFIG_NET_BUF_LOG_LEVEL
+
+#include <logging/log.h>
+//LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+#include <stdio.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/byteorder.h>
+
+#include <net/buf.h>
+
+#if defined(CONFIG_NET_BUF_LOG)
+#define NET_BUF_DBG(fmt, ...) LOG_DBG(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define NET_BUF_ERR(fmt, ...) LOG_ERR(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define NET_BUF_WARN(fmt, ...) LOG_WRN(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#define NET_BUF_INFO(fmt, ...) LOG_INF(LOG_MODULE_NAME, LOG_LEVEL, fmt, ##__VA_ARGS__)
+#else
+
+#define NET_BUF_DBG(fmt, ...)
+#define NET_BUF_ERR(fmt, ...)
+#define NET_BUF_WARN(fmt, ...)
+#define NET_BUF_INFO(fmt, ...)
+#endif /* CONFIG_NET_BUF_LOG */
+
+#define NET_BUF_ASSERT(cond, ...) __ASSERT(cond, "" __VA_ARGS__)
+
+#if CONFIG_NET_BUF_WARN_ALLOC_INTERVAL > 0
+#define WARN_ALLOC_INTERVAL K_SECONDS(CONFIG_NET_BUF_WARN_ALLOC_INTERVAL)
+#else
+#define WARN_ALLOC_INTERVAL K_FOREVER
+#endif
+
+/* Linker-defined symbol bound to the static pool structs */
+//extern struct net_buf_pool _net_buf_pool_list[];
+//struct net_buf_pool _net_buf_pool_list[10];
+
+struct net_buf_pool *net_buf_pool_get(int id)
+{
+	//return NULL;
+	return (struct net_buf_pool *)(id);
+}
+
+static int pool_id(struct net_buf_pool *pool)
+{
+	return (int)(pool);
+}
+
+int net_buf_id(struct net_buf *buf)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return buf - pool->__bufs;
+}
+
+static inline struct net_buf *pool_get_uninit(struct net_buf_pool *pool,
+					      uint16_t uninit_count)
+{
+	struct net_buf *buf;
+
+	buf = &pool->__bufs[pool->buf_count - uninit_count];
+    NET_BUF_DBG("pool_get_uninit buf: %p, pool_id: %p", buf, pool_id(pool));
+
+	buf->pool_id = pool_id(pool);
+
+	return buf;
+}
+
+void net_buf_reset(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf->flags == 0U);
+	__ASSERT_NO_MSG(buf->frags == NULL);
+
+	net_buf_simple_reset(&buf->b);
+}
+
+static uint8_t *generic_data_ref(struct net_buf *buf, uint8_t *data)
+{
+	uint8_t *ref_count;
+
+	ref_count = data - 1;
+	(*ref_count)++;
+
+	return data;
+}
+
+static uint8_t *fixed_data_alloc(struct net_buf *buf, size_t *size,
+			      k_timeout_t timeout)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	*size = MIN(fixed->data_size, *size);
+
+	return fixed->data_pool + fixed->data_size * net_buf_id(buf);
+}
+
+static void fixed_data_unref(struct net_buf *buf, uint8_t *data)
+{
+	/* Nothing needed for fixed-size data pools */
+}
+
+const struct net_buf_data_cb net_buf_fixed_cb = {
+	.alloc = fixed_data_alloc,
+	.unref = fixed_data_unref,
+};
+
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+
+static uint8_t *heap_data_alloc(struct net_buf *buf, size_t *size,
+			     k_timeout_t timeout)
+{
+	uint8_t *ref_count;
+
+	ref_count = k_malloc(1 + *size);
+	if (!ref_count) {
+		return NULL;
+	}
+
+	*ref_count = 1U;
+
+	return ref_count + 1;
+}
+
+static void heap_data_unref(struct net_buf *buf, uint8_t *data)
+{
+	uint8_t *ref_count;
+
+	ref_count = data - 1;
+	if (--(*ref_count)) {
+		return;
+	}
+
+	k_free(ref_count);
+}
+
+static const struct net_buf_data_cb net_buf_heap_cb = {
+	.alloc = heap_data_alloc,
+	.ref   = generic_data_ref,
+	.unref = heap_data_unref,
+};
+
+const struct net_buf_data_alloc net_buf_heap_alloc = {
+	.cb = &net_buf_heap_cb,
+};
+
+#endif /* CONFIG_HEAP_MEM_POOL_SIZE > 0 */
+
+static uint8_t *data_alloc(struct net_buf *buf, size_t *size, k_timeout_t timeout)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return pool->alloc->cb->alloc(buf, size, timeout);
+}
+
+static uint8_t *data_ref(struct net_buf *buf, uint8_t *data)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	return pool->alloc->cb->ref(buf, data);
+}
+
+static void data_unref(struct net_buf *buf, uint8_t *data)
+{
+	struct net_buf_pool *pool = net_buf_pool_get(buf->pool_id);
+
+	if (buf->flags & NET_BUF_EXTERNAL_DATA) {
+		return;
+	}
+
+	pool->alloc->cb->unref(buf, data);
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_len_debug(struct net_buf_pool *pool, size_t size,
+					k_timeout_t timeout, const char *func,
+					int line)
+#else
+struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size,
+				  k_timeout_t timeout)
+#endif
+{
+	uint64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf *buf;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(pool);
+
+	NET_BUF_DBG("%s():%d: pool %p size %zu", func, line, pool, size);
+
+	/* We need to lock interrupts temporarily to prevent race conditions
+	 * when accessing pool->uninit_count.
+	 */
+	key = irq_lock();
+
+	/* If there are uninitialized buffers we're guaranteed to succeed
+	 * with the allocation one way or another.
+	 */
+	if (pool->uninit_count) {
+		uint16_t uninit_count;
+
+		/* If this is not the first access to the pool, we can
+		 * be opportunistic and try to fetch a previously used
+		 * buffer from the LIFO with K_NO_WAIT.
+		 */
+		if (pool->uninit_count < pool->buf_count) {
+            NET_BUF_DBG("pool get free, uninit_count %d, buf_count %d"
+                , pool->uninit_count, pool->buf_count);
+			buf = k_lifo_get(&pool->free, K_NO_WAIT);
+			if (buf) {
+				irq_unlock(key);
+				goto success;
+			}
+		}
+
+		uninit_count = pool->uninit_count--;
+		irq_unlock(key);
+        
+        NET_BUF_DBG("pool_get_uninit, uninit_count %d", uninit_count);
+
+		buf = pool_get_uninit(pool, uninit_count);
+		goto success;
+	}
+
+	irq_unlock(key);
+#if 0
+//#if defined(CONFIG_NET_BUF_LOG) && (CONFIG_NET_BUF_LOG_LEVEL >= LOG_LEVEL_WRN)
+	if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+		uint32_t ref = k_uptime_get_32();
+		buf = k_lifo_get(&pool->free, K_NO_WAIT);
+		while (!buf) {
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+			NET_BUF_WARN("%s():%d: Pool %s low on buffers.",
+				     func, line, pool->name);
+#else
+			NET_BUF_WARN("%s():%d: Pool %p low on buffers.",
+				     func, line, pool);
+#endif
+			buf = k_lifo_get(&pool->free, WARN_ALLOC_INTERVAL);
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+			NET_BUF_WARN("%s():%d: Pool %s blocked for %u secs",
+				     func, line, pool->name,
+				     (k_uptime_get_32() - ref) / MSEC_PER_SEC);
+#else
+			NET_BUF_WARN("%s():%d: Pool %p blocked for %u secs",
+				     func, line, pool,
+				     (k_uptime_get_32() - ref) / MSEC_PER_SEC);
+#endif
+		}
+	} else {
+		buf = k_lifo_get(&pool->free, timeout);
+	}
+#else
+	buf = k_lifo_get(&pool->free, timeout);
+#endif
+	if (!buf) {
+		NET_BUF_ERR("%s():%d: Failed to get free buffer", func, line);
+		return NULL;
+	}
+
+success:
+	NET_BUF_DBG("allocated buf %p", buf);
+
+	if (size) {
+#if __ASSERT_ON
+		size_t req_size = size;
+#endif
+#if 0
+		if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+		    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			int64_t remaining = end - z_tick_get();
+
+			if (remaining <= 0) {
+				timeout = K_NO_WAIT;
+			} else {
+				timeout = Z_TIMEOUT_TICKS(remaining);
+			}
+		}
+#endif
+
+		buf->__buf = data_alloc(buf, &size, timeout);
+		if (!buf->__buf) {
+			NET_BUF_ERR("%s():%d: Failed to allocate data",
+				    func, line);
+			net_buf_destroy(buf);
+			return NULL;
+		}
+
+		NET_BUF_ASSERT(req_size <= size);
+	} else {
+		buf->__buf = NULL;
+	}
+
+	buf->ref   = 1U;
+	buf->flags = 0U;
+	buf->frags = NULL;
+	buf->size  = size;
+	net_buf_reset(buf);
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+	pool->avail_count--;
+	__ASSERT_NO_MSG(pool->avail_count >= 0);
+#endif
+	return buf;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_fixed_debug(struct net_buf_pool *pool,
+					  k_timeout_t timeout, const char *func,
+					  int line)
+{
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	return net_buf_alloc_len_debug(pool, fixed->data_size, timeout, func,
+				       line);
+}
+#else
+struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool,
+				    k_timeout_t timeout)
+{
+	const struct net_buf_pool_fixed *fixed = pool->alloc->alloc_data;
+
+	return net_buf_alloc_len(pool, fixed->data_size, timeout);
+}
+#endif
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_alloc_with_data_debug(struct net_buf_pool *pool,
+					      void *data, size_t size,
+					      k_timeout_t timeout,
+					      const char *func, int line)
+#else
+struct net_buf *net_buf_alloc_with_data(struct net_buf_pool *pool,
+					void *data, size_t size,
+					k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf;
+
+#if defined(CONFIG_NET_BUF_LOG)
+	buf = net_buf_alloc_len_debug(pool, 0, timeout, func, line);
+#else
+	buf = net_buf_alloc_len(pool, 0, timeout);
+#endif
+	if (!buf) {
+		return NULL;
+	}
+
+	net_buf_simple_init_with_data(&buf->b, data, size);
+	buf->flags = NET_BUF_EXTERNAL_DATA;
+
+	return buf;
+}
+
+struct net_buf *net_buf_is_empty(struct k_fifo *fifo)
+{
+	struct net_buf *buf, *frag;
+
+	buf = k_fifo_is_empty(fifo);
+	if (!buf) {
+		return NULL;
+	}
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_get_debug(struct k_fifo *fifo, k_timeout_t timeout,
+				  const char *func, int line)
+#else
+struct net_buf *net_buf_get(struct k_fifo *fifo, k_timeout_t timeout)
+#endif
+{
+	struct net_buf *buf, *frag;
+
+	NET_BUF_DBG("%s():%d: fifo %p", func, line, fifo);
+
+	buf = k_fifo_get(fifo, timeout);
+	if (!buf) {
+		return NULL;
+	}
+
+	NET_BUF_DBG("%s():%d: buf %p fifo %p", func, line, buf, fifo);
+
+	/* Get any fragments belonging to this buffer */
+	for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) {
+		frag->frags = k_fifo_get(fifo, K_NO_WAIT);
+		__ASSERT_NO_MSG(frag->frags);
+
+		/* The fragments flag is only for FIFO-internal usage */
+		frag->flags &= ~NET_BUF_FRAGS;
+	}
+
+	/* Mark the end of the fragment list */
+	frag->frags = NULL;
+
+	return buf;
+}
+
+void net_buf_simple_init_with_data(struct net_buf_simple *buf,
+				   void *data, size_t size)
+{
+	buf->__buf = data;
+	buf->data  = data;
+	buf->size  = size;
+	buf->len   = size;
+}
+
+void net_buf_simple_reserve(struct net_buf_simple *buf, size_t reserve)
+{
+	__ASSERT_NO_MSG(buf);
+	__ASSERT_NO_MSG(buf->len == 0U);
+	NET_BUF_DBG("buf %p reserve %zu", buf, reserve);
+
+	buf->data = buf->__buf + reserve;
+}
+
+void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf)
+{
+	struct net_buf *tail;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(list);
+	__ASSERT_NO_MSG(buf);
+
+	for (tail = buf; tail->frags; tail = tail->frags) {
+		tail->flags |= NET_BUF_FRAGS;
+	}
+
+	key = irq_lock();
+	sys_slist_append_list(list, &buf->node, &tail->node);
+	irq_unlock(key);
+}
+
+struct net_buf *net_buf_slist_get(sys_slist_t *list)
+{
+	struct net_buf *buf, *frag;
+	unsigned int key;
+
+	__ASSERT_NO_MSG(list);
+
+	key = irq_lock();
+	buf = (void *)sys_slist_get(list);
+	irq_unlock(key);
+
+	if (!buf) {
+		return NULL;
+	}
+
+	/* Get any fragments belonging to this buffer */
+	for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) {
+		key = irq_lock();
+		frag->frags = (void *)sys_slist_get(list);
+		irq_unlock(key);
+
+		__ASSERT_NO_MSG(frag->frags);
+
+		/* The fragments flag is only for list-internal usage */
+		frag->flags &= ~NET_BUF_FRAGS;
+	}
+
+	/* Mark the end of the fragment list */
+	frag->frags = NULL;
+
+	return buf;
+}
+
+void net_buf_put(struct k_fifo *fifo, struct net_buf *buf)
+{
+	struct net_buf *tail;
+
+	__ASSERT_NO_MSG(fifo);
+	__ASSERT_NO_MSG(buf);
+
+	for (tail = buf; tail->frags; tail = tail->frags) {
+		tail->flags |= NET_BUF_FRAGS;
+	}
+
+	k_fifo_put_list(fifo, buf, tail);
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+void net_buf_unref_debug(struct net_buf *buf, const char *func, int line)
+#else
+void net_buf_unref(struct net_buf *buf)
+#endif
+{
+	__ASSERT_NO_MSG(buf);
+
+	while (buf) {
+		struct net_buf *frags = buf->frags;
+		struct net_buf_pool *pool;
+
+#if defined(CONFIG_NET_BUF_LOG)
+		if (!buf->ref) {
+			NET_BUF_ERR("%s():%d: net_buf_unref, buf %p double free", func, line,
+				    buf);
+			return;
+		}
+		NET_BUF_DBG("%s():%d: net_buf_unref, buf %p", func, line,
+			    buf);
+#endif
+		NET_BUF_DBG("net_buf_unref, buf %p ref %u pool_id %p frags %p", buf, buf->ref,
+			    buf->pool_id, buf->frags);
+
+		if (--buf->ref > 0) {
+			return;
+		}
+
+		if (buf->__buf) {
+			data_unref(buf, buf->__buf);
+			buf->__buf = NULL;
+		}
+
+		buf->data = NULL;
+		buf->frags = NULL;
+
+		pool = net_buf_pool_get(buf->pool_id);
+
+#if defined(CONFIG_NET_BUF_POOL_USAGE)
+		pool->avail_count++;
+		__ASSERT_NO_MSG(pool->avail_count <= pool->buf_count);
+#endif
+
+		if (pool->destroy) {
+			pool->destroy(buf);
+		} else {
+			net_buf_destroy(buf);
+		}
+
+		buf = frags;
+	}
+}
+
+struct net_buf *net_buf_ref(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf);
+
+	NET_BUF_DBG("net_buf_ref, buf %p (old) ref %u pool_id %p",
+		    buf, buf->ref, buf->pool_id);
+	buf->ref++;
+	return buf;
+}
+
+struct net_buf *net_buf_clone(struct net_buf *buf, k_timeout_t timeout)
+{
+	int64_t end = 1;//z_timeout_end_calc(timeout);
+	struct net_buf_pool *pool;
+	struct net_buf *clone;
+
+	__ASSERT_NO_MSG(buf);
+
+	pool = net_buf_pool_get(buf->pool_id);
+
+	clone = net_buf_alloc_len(pool, 0, timeout);
+	if (!clone) {
+		return NULL;
+	}
+
+	/* If the pool supports data referencing use that. Otherwise
+	 * we need to allocate new data and make a copy.
+	 */
+	if (pool->alloc->cb->ref && !(buf->flags & NET_BUF_EXTERNAL_DATA)) {
+		clone->__buf = data_ref(buf, buf->__buf);
+		clone->data = buf->data;
+		clone->len = buf->len;
+		clone->size = buf->size;
+	} else {
+		size_t size = buf->size;
+#if 0
+		if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT) &&
+		    !K_TIMEOUT_EQ(timeout, K_FOREVER)) {
+			int64_t remaining = end - z_tick_get();
+
+			if (remaining <= 0) {
+				timeout = K_NO_WAIT;
+			} else {
+				timeout = Z_TIMEOUT_TICKS(remaining);
+			}
+		}
+#endif
+		clone->__buf = data_alloc(clone, &size, timeout);
+		if (!clone->__buf || size < buf->size) {
+			net_buf_destroy(clone);
+			return NULL;
+		}
+
+		clone->size = size;
+		clone->data = clone->__buf + net_buf_headroom(buf);
+		net_buf_add_mem(clone, buf->data, buf->len);
+	}
+
+	return clone;
+}
+
+struct net_buf *net_buf_frag_last(struct net_buf *buf)
+{
+	__ASSERT_NO_MSG(buf);
+
+	while (buf->frags) {
+		buf = buf->frags;
+	}
+
+	return buf;
+}
+
+void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag)
+{
+	__ASSERT_NO_MSG(parent);
+	__ASSERT_NO_MSG(frag);
+
+	if (parent->frags) {
+		net_buf_frag_last(frag)->frags = parent->frags;
+	}
+	/* Take ownership of the fragment reference */
+	parent->frags = frag;
+}
+
+struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag)
+{
+	__ASSERT_NO_MSG(frag);
+
+	if (!head) {
+		return net_buf_ref(frag);
+	}
+
+	net_buf_frag_insert(net_buf_frag_last(head), frag);
+
+	return head;
+}
+
+#if defined(CONFIG_NET_BUF_LOG)
+struct net_buf *net_buf_frag_del_debug(struct net_buf *parent,
+				       struct net_buf *frag,
+				       const char *func, int line)
+#else
+struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag)
+#endif
+{
+	struct net_buf *next_frag;
+
+	__ASSERT_NO_MSG(frag);
+
+	if (parent) {
+		__ASSERT_NO_MSG(parent->frags);
+		__ASSERT_NO_MSG(parent->frags == frag);
+		parent->frags = frag->frags;
+	}
+
+	next_frag = frag->frags;
+
+	frag->frags = NULL;
+
+#if defined(CONFIG_NET_BUF_LOG)
+	net_buf_unref_debug(frag, func, line);
+#else
+	net_buf_unref(frag);
+#endif
+
+	return next_frag;
+}
+
+size_t net_buf_linearize(void *dst, size_t dst_len, struct net_buf *src,
+			 size_t offset, size_t len)
+{
+	struct net_buf *frag;
+	size_t to_copy;
+	size_t copied;
+
+	len = MIN(len, dst_len);
+
+	frag = src;
+
+	/* find the right fragment to start copying from */
+	while (frag && offset >= frag->len) {
+		offset -= frag->len;
+		frag = frag->frags;
+	}
+
+	/* traverse the fragment chain until len bytes are copied */
+	copied = 0;
+	while (frag && len > 0) {
+		to_copy = MIN(len, frag->len - offset);
+		memcpy((uint8_t *)dst + copied, frag->data + offset, to_copy);
+
+		copied += to_copy;
+
+		/* to_copy is always <= len */
+		len -= to_copy;
+		frag = frag->frags;
+
+		/* after the first iteration, this value will be 0 */
+		offset = 0;
+	}
+
+	return copied;
+}
+
+/* This helper routine will append multiple bytes, if there is no place for
+ * the data in current fragment then create new fragment and add it to
+ * the buffer. It assumes that the buffer has at least one fragment.
+ */
+size_t net_buf_append_bytes(struct net_buf *buf, size_t len,
+			    const void *value, k_timeout_t timeout,
+			    net_buf_allocator_cb allocate_cb, void *user_data)
+{
+	struct net_buf *frag = net_buf_frag_last(buf);
+	size_t added_len = 0;
+	const uint8_t *value8 = value;
+
+	do {
+		uint16_t count = MIN(len, net_buf_tailroom(frag));
+
+		net_buf_add_mem(frag, value8, count);
+		len -= count;
+		added_len += count;
+		value8 += count;
+
+		if (len == 0) {
+			return added_len;
+		}
+
+		frag = allocate_cb(timeout, user_data);
+		if (!frag) {
+			return added_len;
+		}
+
+		net_buf_frag_add(buf, frag);
+	} while (1);
+
+	/* Unreachable */
+	return 0;
+}
+
+#if defined(CONFIG_NET_BUF_SIMPLE_LOG)
+#define NET_BUF_SIMPLE_DBG(fmt, ...) NET_BUF_DBG(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_ERR(fmt, ...) NET_BUF_ERR(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_WARN(fmt, ...) NET_BUF_WARN(fmt, ##__VA_ARGS__)
+#define NET_BUF_SIMPLE_INFO(fmt, ...) NET_BUF_INFO(fmt, ##__VA_ARGS__)
+#else
+#define NET_BUF_SIMPLE_DBG(fmt, ...)
+#define NET_BUF_SIMPLE_ERR(fmt, ...)
+#define NET_BUF_SIMPLE_WARN(fmt, ...)
+#define NET_BUF_SIMPLE_INFO(fmt, ...)
+#endif /* CONFIG_NET_BUF_SIMPLE_LOG */
+
+void net_buf_simple_clone(const struct net_buf_simple *original,
+			  struct net_buf_simple *clone)
+{
+	memcpy(clone, original, sizeof(struct net_buf_simple));
+}
+
+void *net_buf_simple_add(struct net_buf_simple *buf, size_t len)
+{
+	uint8_t *tail = net_buf_simple_tail(buf);
+
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add, buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(net_buf_simple_tailroom(buf) >= len);
+
+	buf->len += len;
+	return tail;
+}
+
+void *net_buf_simple_add_mem(struct net_buf_simple *buf, const void *mem,
+			     size_t len)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_mem, buf %p len %zu", buf, len);
+
+	return memcpy(net_buf_simple_add(buf, len), mem, len);
+}
+
+uint8_t *net_buf_simple_add_u8(struct net_buf_simple *buf, uint8_t val)
+{
+	uint8_t *u8;
+
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_u8, buf %p val 0x%02x", buf, val);
+
+	u8 = net_buf_simple_add(buf, 1);
+	*u8 = val;
+
+	return u8;
+}
+
+void net_buf_simple_add_le16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_le16, buf %p val %u", buf, val);
+
+	sys_put_le16(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_be16, buf %p val %u", buf, val);
+
+	sys_put_be16(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_le24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_le24, buf %p val %u", buf, val);
+
+	sys_put_le24(val, net_buf_simple_add(buf, 3));
+}
+
+void net_buf_simple_add_be24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_be24, buf %p val %u", buf, val);
+
+	sys_put_be24(val, net_buf_simple_add(buf, 3));
+}
+
+void net_buf_simple_add_le32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_le32, buf %p val %u", buf, val);
+
+	sys_put_le32(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_be32, buf %p val %u", buf, val);
+
+	sys_put_be32(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_le48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_le48, buf %p val %" PRIu64, buf, val);
+
+	sys_put_le48(val, net_buf_simple_add(buf, 6));
+}
+
+void net_buf_simple_add_be48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_be48, buf %p val %" PRIu64, buf, val);
+
+	sys_put_be48(val, net_buf_simple_add(buf, 6));
+}
+
+void net_buf_simple_add_le64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_le64, buf %p val %" PRIu64, buf, val);
+
+	sys_put_le64(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void net_buf_simple_add_be64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_add_be64, buf %p val %" PRIu64, buf, val);
+
+	sys_put_be64(val, net_buf_simple_add(buf, sizeof(val)));
+}
+
+void *net_buf_simple_push(struct net_buf_simple *buf, size_t len)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push, buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(net_buf_simple_headroom(buf) >= len);
+
+	buf->data -= len;
+	buf->len += len;
+	return buf->data;
+}
+
+void net_buf_simple_push_le16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_le16, buf %p val %u", buf, val);
+
+	sys_put_le16(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be16(struct net_buf_simple *buf, uint16_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_be16, buf %p val %u", buf, val);
+
+	sys_put_be16(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_u8(struct net_buf_simple *buf, uint8_t val)
+{
+	uint8_t *data = net_buf_simple_push(buf, 1);
+
+	*data = val;
+}
+
+void net_buf_simple_push_le24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_le24, buf %p val %u", buf, val);
+
+	sys_put_le24(val, net_buf_simple_push(buf, 3));
+}
+
+void net_buf_simple_push_be24(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_be24, buf %p val %u", buf, val);
+
+	sys_put_be24(val, net_buf_simple_push(buf, 3));
+}
+
+void net_buf_simple_push_le32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_le32, buf %p val %u", buf, val);
+
+	sys_put_le32(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be32(struct net_buf_simple *buf, uint32_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_be32, buf %p val %u", buf, val);
+
+	sys_put_be32(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_le48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_le48, buf %p val %" PRIu64, buf, val);
+
+	sys_put_le48(val, net_buf_simple_push(buf, 6));
+}
+
+void net_buf_simple_push_be48(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_be48, buf %p val %" PRIu64, buf, val);
+
+	sys_put_be48(val, net_buf_simple_push(buf, 6));
+}
+
+void net_buf_simple_push_le64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_le64, buf %p val %" PRIu64, buf, val);
+
+	sys_put_le64(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void net_buf_simple_push_be64(struct net_buf_simple *buf, uint64_t val)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_push_be64, buf %p val %" PRIu64, buf, val);
+
+	sys_put_be64(val, net_buf_simple_push(buf, sizeof(val)));
+}
+
+void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len)
+{
+	NET_BUF_SIMPLE_DBG("net_buf_simple_pull, buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(buf->len >= len);
+
+	buf->len -= len;
+	return buf->data += len;
+}
+
+void *net_buf_simple_pull_mem(struct net_buf_simple *buf, size_t len)
+{
+	void *data = buf->data;
+
+	NET_BUF_SIMPLE_DBG("net_buf_simple_pull_mem, buf %p len %zu", buf, len);
+
+	__ASSERT_NO_MSG(buf->len >= len);
+
+	buf->len -= len;
+	buf->data += len;
+
+	return data;
+}
+
+uint8_t net_buf_simple_pull_u8(struct net_buf_simple *buf)
+{
+	uint8_t val;
+
+	val = buf->data[0];
+	net_buf_simple_pull(buf, 1);
+
+	return val;
+}
+
+uint16_t net_buf_simple_pull_le16(struct net_buf_simple *buf)
+{
+	uint16_t val;
+
+	val = UNALIGNED_GET((uint16_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le16_to_cpu(val);
+}
+
+uint16_t net_buf_simple_pull_be16(struct net_buf_simple *buf)
+{
+	uint16_t val;
+
+	val = UNALIGNED_GET((uint16_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be16_to_cpu(val);
+}
+
+uint32_t net_buf_simple_pull_le24(struct net_buf_simple *buf)
+{
+	struct uint24 {
+		uint32_t u24:24;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint24 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le24_to_cpu(val.u24);
+}
+
+uint32_t net_buf_simple_pull_be24(struct net_buf_simple *buf)
+{
+	struct uint24 {
+		uint32_t u24:24;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint24 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be24_to_cpu(val.u24);
+}
+
+uint32_t net_buf_simple_pull_le32(struct net_buf_simple *buf)
+{
+	uint32_t val;
+
+	val = UNALIGNED_GET((uint32_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le32_to_cpu(val);
+}
+
+uint32_t net_buf_simple_pull_be32(struct net_buf_simple *buf)
+{
+	uint32_t val;
+
+	val = UNALIGNED_GET((uint32_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be32_to_cpu(val);
+}
+
+uint64_t net_buf_simple_pull_le48(struct net_buf_simple *buf)
+{
+	struct uint48 {
+		uint64_t u48:48;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint48 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le48_to_cpu(val.u48);
+}
+
+uint64_t net_buf_simple_pull_be48(struct net_buf_simple *buf)
+{
+	struct uint48 {
+		uint64_t u48:48;
+	} __packed val;
+
+	val = UNALIGNED_GET((struct uint48 *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be48_to_cpu(val.u48);
+}
+
+uint64_t net_buf_simple_pull_le64(struct net_buf_simple *buf)
+{
+	uint64_t val;
+
+	val = UNALIGNED_GET((uint64_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_le64_to_cpu(val);
+}
+
+uint64_t net_buf_simple_pull_be64(struct net_buf_simple *buf)
+{
+	uint64_t val;
+
+	val = UNALIGNED_GET((uint64_t *)buf->data);
+	net_buf_simple_pull(buf, sizeof(val));
+
+	return sys_be64_to_cpu(val);
+}
+
+size_t net_buf_simple_headroom(struct net_buf_simple *buf)
+{
+	return buf->data - buf->__buf;
+}
+
+size_t net_buf_simple_tailroom(struct net_buf_simple *buf)
+{
+	return buf->size - net_buf_simple_headroom(buf) - buf->len;
+}
Index: ModuleDemo/BLE/CM0/User/utils/hex.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/hex.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/hex.c	(working copy)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <types.h>
+#include <errno.h>
+#include <sys/util.h>
+
+int char2hex(char c, uint8_t *x)
+{
+	if (c >= '0' && c <= '9') {
+		*x = c - '0';
+	} else if (c >= 'a' && c <= 'f') {
+		*x = c - 'a' + 10;
+	} else if (c >= 'A' && c <= 'F') {
+		*x = c - 'A' + 10;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int hex2char(uint8_t x, char *c)
+{
+	if (x <= 9) {
+		*c = x + '0';
+	} else  if (x <= 15) {
+		*c = x - 10 + 'a';
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
+{
+	if ((hexlen + 1) < buflen * 2) {
+		return 0;
+	}
+
+	for (size_t i = 0; i < buflen; i++) {
+		if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
+			return 0;
+		}
+		if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
+			return 0;
+		}
+	}
+
+	hex[2 * buflen] = '\0';
+	return 2 * buflen;
+}
+
+size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen)
+{
+	uint8_t dec;
+
+	if (buflen < hexlen / 2 + hexlen % 2) {
+		return 0;
+	}
+
+	/* if hexlen is uneven, insert leading zero nibble */
+	if (hexlen % 2) {
+		if (char2hex(hex[0], &dec) < 0) {
+			return 0;
+		}
+		buf[0] = dec;
+		hex++;
+		buf++;
+	}
+
+	/* regular hex conversion */
+	for (size_t i = 0; i < hexlen / 2; i++) {
+		if (char2hex(hex[2 * i], &dec) < 0) {
+			return 0;
+		}
+		buf[i] = dec << 4;
+
+		if (char2hex(hex[2 * i + 1], &dec) < 0) {
+			return 0;
+		}
+		buf[i] += dec;
+	}
+
+	return hexlen / 2 + hexlen % 2;
+}
Index: ModuleDemo/BLE/CM0/User/utils/mem_slab.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/mem_slab.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/mem_slab.c	(working copy)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <sys/dlist.h>
+#include <init.h>
+#include <sys/check.h>
+
+/**
+ * @brief Initialize kernel memory slab subsystem.
+ *
+ * Perform any initialization of memory slabs that wasn't done at build time.
+ * Currently this just involves creating the list of free blocks for each slab.
+ *
+ * @return N/A
+ */
+int create_free_list(struct k_mem_slab *slab)
+{
+	uint32_t j;
+	char *p;
+
+	/* blocks must be word aligned */
+	CHECKIF(((slab->block_size | (uintptr_t)slab->buffer) &
+				(sizeof(void *) - 1)) != 0) {
+		return -EINVAL;
+	}
+
+	slab->free_list = NULL;
+	p = slab->buffer;
+
+	for (j = 0U; j < slab->num_blocks; j++) {
+		*(char **)p = slab->free_list;
+		slab->free_list = p;
+		p += slab->block_size;
+	}
+	return 0;
+}
+
+
+int k_mem_slab_init(struct k_mem_slab *slab, void *buffer,
+		    size_t block_size, uint32_t num_blocks)
+{
+	int rc = 0;
+
+	slab->num_blocks = num_blocks;
+	slab->block_size = block_size;
+	slab->buffer = buffer;
+	slab->num_used = 0U;
+	rc = create_free_list(slab);
+	if (rc < 0) {
+		goto out;
+	}
+
+out:
+	return rc;
+}
+
+int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout)
+{
+	int result;
+
+	if (slab->free_list != NULL) {
+		/* take a free block */
+		*mem = slab->free_list;
+		slab->free_list = *(char **)(slab->free_list);
+		slab->num_used++;
+		result = 0;
+	} else {
+		/* don't wait for a free block to become available */
+		*mem = NULL;
+		result = -ENOMEM;
+	}
+
+	return result;
+}
+
+void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
+{
+    **(char ***)mem = slab->free_list;
+    slab->free_list = *(char **)mem;
+    slab->num_used--;
+}
Index: ModuleDemo/BLE/CM0/User/utils/mempool.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/mempool.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/mempool.c	(working copy)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <kernel.h>
+#include <string.h>
+
+void k_mem_pool_free(struct k_mem_block *block)
+{
+	//k_mem_pool_free_id(&block->id);
+}
+
+void *k_mem_pool_malloc(struct k_mem_pool *pool, size_t size)
+{
+	return 0;
+	#if 0
+	struct k_mem_block block;
+
+	/*
+	 * get a block large enough to hold an initial (hidden) block
+	 * descriptor, as well as the space the caller requested
+	 */
+	if (size_add_overflow(size, WB_UP(sizeof(struct k_mem_block_id)),
+			      &size)) {
+		return NULL;
+	}
+	if (k_mem_pool_alloc(pool, &block, size, K_NO_WAIT) != 0) {
+		return NULL;
+	}
+
+	/* save the block descriptor info at the start of the actual block */
+	(void)memcpy(block.data, &block.id, sizeof(struct k_mem_block_id));
+
+	/* return address of the user area part of the block to the caller */
+	return (char *)block.data + WB_UP(sizeof(struct k_mem_block_id));
+	#endif
+}
+
+void k_free(void *ptr)
+{
+	#if 0
+	if (ptr != NULL) {
+		/* point to hidden block descriptor at start of block */
+		ptr = (char *)ptr - WB_UP(sizeof(struct k_mem_block_id));
+
+		/* return block to the heap memory pool */
+		k_mem_pool_free_id(ptr);
+	}
+	#endif
+}
+
+#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+
+/*
+ * Heap is defined using HEAP_MEM_POOL_SIZE configuration option.
+ *
+ * This module defines the heap memory pool and the _HEAP_MEM_POOL symbol
+ * that has the address of the associated memory pool struct.
+ */
+
+K_MEM_POOL_DEFINE(_heap_mem_pool, CONFIG_HEAP_MEM_POOL_MIN_SIZE,
+		  CONFIG_HEAP_MEM_POOL_SIZE, 1, 4);
+#define _HEAP_MEM_POOL (&_heap_mem_pool)
+
+void *k_malloc(size_t size)
+{
+	return k_mem_pool_malloc(_HEAP_MEM_POOL, size);
+}
+
+void *k_calloc(size_t nmemb, size_t size)
+{
+	void *ret;
+	size_t bounds;
+
+	if (size_mul_overflow(nmemb, size, &bounds)) {
+		return NULL;
+	}
+
+	ret = k_malloc(bounds);
+	if (ret != NULL) {
+		(void)memset(ret, 0, bounds);
+	}
+	return ret;
+}
+
+void k_thread_system_pool_assign(struct k_thread *thread)
+{
+	thread->resource_pool = _HEAP_MEM_POOL;
+}
+#else
+#define _HEAP_MEM_POOL	NULL
+#endif
+
+void *z_thread_malloc(size_t size)
+{
+	void *ret;
+	#if 0
+	struct k_mem_pool *pool;
+
+	if (k_is_in_isr()) {
+		pool = _HEAP_MEM_POOL;
+	} else {
+		pool = _current->resource_pool;
+	}
+
+	if (pool) {
+		ret = k_mem_pool_malloc(pool, size);
+	} else {
+		ret = NULL;
+	}
+	#endif
+
+	return ret;
+}
Index: ModuleDemo/BLE/CM0/User/utils/printk.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/printk.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/printk.c	(working copy)
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2010, 2013-2014 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Low-level debug output
+ *
+ * Low-level debugging output. Platform installs a character output routine at
+ * init time. If no routine is installed, a nop routine is called.
+ */
+
+#include <kernel.h>
+#include <sys/printk.h>
+#include <stdarg.h>
+#include <toolchain.h>
+#include <types.h>
+#include <yc_debug.h>
+
+typedef int (*out_func_t)(int c, void *ctx);
+
+enum pad_type {
+	PAD_NONE,
+	PAD_ZERO_BEFORE,
+	PAD_SPACE_BEFORE,
+	PAD_SPACE_AFTER,
+};
+
+#ifdef CONFIG_PRINTK64
+typedef uint64_t printk_val_t;
+#else
+typedef uint32_t printk_val_t;
+#endif
+
+/* Maximum number of digits in a printed decimal value (hex is always
+ * less, obviously).  Funny formula produces 10 max digits for 32 bit,
+ * 21 for 64.
+ */
+#define DIGITS_BUFLEN (11U * (sizeof(printk_val_t) / 4U) - 1U)
+
+#ifdef CONFIG_PRINTK_SYNC
+static struct k_spinlock lock;
+#endif
+
+#ifdef CONFIG_PRINTK
+/**
+ * @brief Default character output routine that does nothing
+ * @param c Character to swallow
+ *
+ * Note this is defined as a weak symbol, allowing architecture code
+ * to override it where possible to enable very early logging.
+ *
+ * @return 0
+ */
+/* LCOV_EXCL_START */
+__attribute__((weak)) int arch_printk_char_out(int c)
+{
+	ARG_UNUSED(c);
+
+	/* do nothing */
+	return 0;
+}
+/* LCOV_EXCL_STOP */
+
+int (*_char_out)(int) = arch_printk_char_out;
+
+/**
+ * @brief Install the character output routine for printk
+ *
+ * To be called by the platform's console driver at init time. Installs a
+ * routine that outputs one ASCII character at a time.
+ * @param fn putc routine to install
+ *
+ * @return N/A
+ */
+void __printk_hook_install(int (*fn)(int))
+{
+	_char_out = fn;
+}
+
+/**
+ * @brief Get the current character output routine for printk
+ *
+ * To be called by any console driver that would like to save
+ * current hook - if any - for later re-installation.
+ *
+ * @return a function pointer or NULL if no hook is set
+ */
+void *__printk_get_hook(void)
+{
+	return _char_out;
+}
+#endif /* CONFIG_PRINTK */
+
+static void print_digits(out_func_t out, void *ctx, printk_val_t num, unsigned int base,
+			 bool pad_before, char pad_char, int min_width)
+{
+	char buf[DIGITS_BUFLEN];
+	unsigned int i;
+
+	/* Print it backwards into the end of the buffer, low digits first */
+	for (i = DIGITS_BUFLEN - 1U; num != 0U; i--) {
+		buf[i] = "0123456789abcdef"[num % base];
+		num /= base;
+	}
+
+	if (i == DIGITS_BUFLEN - 1U) {
+		buf[i] = '0';
+	} else {
+		i++;
+	}
+
+	int pad = MAX(min_width - (int)(DIGITS_BUFLEN - i), 0);
+
+	for (/**/; pad > 0 && pad_before; pad--) {
+		out(pad_char, ctx);
+	}
+	for (/**/; i < DIGITS_BUFLEN; i++) {
+		out(buf[i], ctx);
+	}
+	for (/**/; pad > 0; pad--) {
+		out(pad_char, ctx);
+	}
+}
+
+static void print_hex(out_func_t out, void *ctx, printk_val_t num,
+		      enum pad_type padding, int min_width)
+{
+	print_digits(out, ctx, num, 16U, padding != PAD_SPACE_AFTER,
+		     padding == PAD_ZERO_BEFORE ? '0' : ' ', min_width);
+}
+
+static void print_dec(out_func_t out, void *ctx, printk_val_t num,
+		      enum pad_type padding, int min_width)
+{
+	print_digits(out, ctx, num, 10U, padding != PAD_SPACE_AFTER,
+		     padding == PAD_ZERO_BEFORE ? '0' : ' ', min_width);
+}
+
+static bool ok64(out_func_t out, void *ctx, long long val)
+{
+	if (sizeof(printk_val_t) < 8U && val != (long) val) {
+		out('E', ctx);
+		out('R', ctx);
+		out('R', ctx);
+		return false;
+	}
+	return true;
+}
+
+static bool negative(printk_val_t val)
+{
+	const printk_val_t hibit = ~(((printk_val_t) ~1) >> 1U);
+
+	return (val & hibit) != 0U;
+}
+
+/**
+ * @brief Printk internals
+ *
+ * See printk() for description.
+ * @param fmt Format string
+ * @param ap Variable parameters
+ *
+ * @return N/A
+ */
+void z_vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
+{
+	int might_format = 0; /* 1 if encountered a '%' */
+	enum pad_type padding = PAD_NONE;
+	int min_width = -1;
+	char length_mod = 0;
+
+	/* fmt has already been adjusted if needed */
+
+	while (*fmt) {
+		if (!might_format) {
+			if (*fmt != '%') {
+				out((int)*fmt, ctx);
+			} else {
+				might_format = 1;
+				min_width = -1;
+				padding = PAD_NONE;
+				length_mod = 0;
+			}
+		} else {
+			switch (*fmt) {
+			case '-':
+				padding = PAD_SPACE_AFTER;
+				goto still_might_format;
+			case '0':
+				if (min_width < 0 && padding == PAD_NONE) {
+					padding = PAD_ZERO_BEFORE;
+					goto still_might_format;
+				}
+				__fallthrough;
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+				if (min_width < 0) {
+					min_width = *fmt - '0';
+				} else {
+					min_width = 10 * min_width + *fmt - '0';
+				}
+
+				if (padding == PAD_NONE) {
+					padding = PAD_SPACE_BEFORE;
+				}
+				goto still_might_format;
+			case 'h':
+			case 'l':
+			case 'z':
+				if (*fmt == 'h' && length_mod == 'h') {
+					length_mod = 'H';
+				} else if (*fmt == 'l' && length_mod == 'l') {
+					length_mod = 'L';
+				} else if (length_mod == 0) {
+					length_mod = *fmt;
+				} else {
+					out((int)'%', ctx);
+					out((int)*fmt, ctx);
+					break;
+				}
+				goto still_might_format;
+			case 'd':
+			case 'i':
+			case 'u': {
+				printk_val_t d;
+
+				if (length_mod == 'z') {
+					d = va_arg(ap, ssize_t);
+				} else if (length_mod == 'l') {
+					d = va_arg(ap, long);
+				} else if (length_mod == 'L') {
+					long long lld = va_arg(ap, long long);
+					if (!ok64(out, ctx, lld)) {
+						break;
+					}
+					d = (printk_val_t) lld;
+				} else if (*fmt == 'u') {
+					d = va_arg(ap, unsigned int);
+				} else {
+					d = va_arg(ap, int);
+				}
+
+				if (*fmt != 'u' && negative(d)) {
+					out((int)'-', ctx);
+					d = -d;
+					min_width--;
+				}
+				print_dec(out, ctx, d, padding, min_width);
+				break;
+			}
+			case 'p':
+				out('0', ctx);
+				out('x', ctx);
+				/* left-pad pointers with zeros */
+				padding = PAD_ZERO_BEFORE;
+				min_width = sizeof(void *) * 2U;
+				__fallthrough;
+			case 'x':
+			case 'X': {
+				printk_val_t x;
+
+				if (*fmt == 'p') {
+					x = (uintptr_t)va_arg(ap, void *);
+				} else if (length_mod == 'l') {
+					x = va_arg(ap, unsigned long);
+				} else if (length_mod == 'L') {
+					x = va_arg(ap, unsigned long long);
+				} else {
+					x = va_arg(ap, unsigned int);
+				}
+
+				print_hex(out, ctx, x, padding, min_width);
+				break;
+			}
+			case 's': {
+				char *s = va_arg(ap, char *);
+				char *start = s;
+
+				while (*s) {
+					out((int)(*s++), ctx);
+				}
+
+				if (padding == PAD_SPACE_AFTER) {
+					int remaining = min_width - (s - start);
+					while (remaining-- > 0) {
+						out(' ', ctx);
+					}
+				}
+				break;
+			}
+			case 'c': {
+				int c = va_arg(ap, int);
+
+				out(c, ctx);
+				break;
+			}
+			case '%': {
+				out((int)'%', ctx);
+				break;
+			}
+			default:
+				out((int)'%', ctx);
+				out((int)*fmt, ctx);
+				break;
+			}
+			might_format = 0;
+		}
+still_might_format:
+		++fmt;
+	}
+}
+
+#ifdef CONFIG_PRINTK
+#ifdef CONFIG_USERSPACE
+struct buf_out_context {
+	int count;
+	unsigned int buf_count;
+	char buf[CONFIG_PRINTK_BUFFER_SIZE];
+};
+
+static void buf_flush(struct buf_out_context *ctx)
+{
+	k_str_out(ctx->buf, ctx->buf_count);
+	ctx->buf_count = 0U;
+}
+
+static int buf_char_out(int c, void *ctx_p)
+{
+	struct buf_out_context *ctx = ctx_p;
+
+	ctx->count++;
+	ctx->buf[ctx->buf_count++] = c;
+	if (ctx->buf_count == CONFIG_PRINTK_BUFFER_SIZE) {
+		buf_flush(ctx);
+	}
+
+	return c;
+}
+#endif /* CONFIG_USERSPACE */
+
+struct out_context {
+	int count;
+};
+
+static int char_out(int c, void *ctx_p)
+{
+	struct out_context *ctx = ctx_p;
+
+	ctx->count++;
+	return _char_out(c);
+}
+
+#ifdef CONFIG_USERSPACE
+void vprintk(const char *fmt, va_list ap)
+{
+	if (_is_user_context()) {
+		struct buf_out_context ctx = { 0 };
+
+		z_vprintk(buf_char_out, &ctx, fmt, ap);
+
+		if (ctx.buf_count) {
+			buf_flush(&ctx);
+		}
+	} else {
+		struct out_context ctx = { 0 };
+#ifdef CONFIG_PRINTK_SYNC
+		k_spinlock_key_t key = k_spin_lock(&lock);
+#endif
+
+		z_vprintk(char_out, &ctx, fmt, ap);
+
+#ifdef CONFIG_PRINTK_SYNC
+		k_spin_unlock(&lock, key);
+#endif
+	}
+}
+#else
+void vprintk(const char *fmt, va_list ap)
+{
+	struct out_context ctx = { 0 };
+#ifdef CONFIG_PRINTK_SYNC
+	k_spinlock_key_t key = k_spin_lock(&lock);
+#endif
+
+	z_vprintk(char_out, &ctx, fmt, ap);
+
+#ifdef CONFIG_PRINTK_SYNC
+	k_spin_unlock(&lock, key);
+#endif
+}
+#endif /* CONFIG_USERSPACE */
+
+void z_impl_k_str_out(char *c, size_t n)
+{
+	size_t i;
+#ifdef CONFIG_PRINTK_SYNC
+	k_spinlock_key_t key = k_spin_lock(&lock);
+#endif
+
+	for (i = 0; i < n; i++) {
+		_char_out(c[i]);
+	}
+
+#ifdef CONFIG_PRINTK_SYNC
+	k_spin_unlock(&lock, key);
+#endif
+}
+
+#ifdef CONFIG_USERSPACE
+static inline void z_vrfy_k_str_out(char *c, size_t n)
+{
+	Z_OOPS(Z_SYSCALL_MEMORY_READ(c, n));
+	z_impl_k_str_out((char *)c, n);
+}
+#include <syscalls/k_str_out_mrsh.c>
+#endif /* CONFIG_USERSPACE */
+
+/**
+ * @brief Output a string
+ *
+ * Output a string on output installed by platform at init time. Some
+ * printf-like formatting is available.
+ *
+ * Available formatting:
+ * - %x/%X:  outputs a number in hexadecimal format
+ * - %s:     outputs a null-terminated string
+ * - %p:     pointer, same as %x with a 0x prefix
+ * - %u:     outputs a number in unsigned decimal format
+ * - %d/%i:  outputs a number in signed decimal format
+ *
+ * Field width (with or without leading zeroes) is supported.
+ * Length attributes h, hh, l, ll and z are supported. However, integral
+ * values with %lld and %lli are only printed if they fit in a long
+ * otherwise 'ERR' is printed. Full 64-bit values may be printed with %llx.
+ *
+ * @param fmt formatted string to output
+ *
+ * @return N/A
+ */
+void printk(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+
+    print_string_log_raw(fmt, ap);
+
+#if 0
+	if (IS_ENABLED(CONFIG_LOG_PRINTK)) {
+		log_printk(fmt, ap);
+	} else {
+		vprintk(fmt, ap);
+	}
+#endif
+	va_end(ap);
+}
+#endif /* CONFIG_PRINTK */
+
+struct str_context {
+	char *str;
+	int max;
+	int count;
+};
+
+static int str_out(int c, struct str_context *ctx)
+{
+	if (ctx->str == NULL || ctx->count >= ctx->max) {
+		ctx->count++;
+		return c;
+	}
+
+	if (ctx->count == ctx->max - 1) {
+		ctx->str[ctx->count++] = '\0';
+	} else {
+		ctx->str[ctx->count++] = c;
+	}
+
+	return c;
+}
+
+int snprintk(char *str, size_t size, const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	ret = vsnprintk(str, size, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+int vsnprintk(char *str, size_t size, const char *fmt, va_list ap)
+{
+	struct str_context ctx = { str, size, 0 };
+
+	z_vprintk((out_func_t)str_out, &ctx, fmt, ap);
+
+	if (ctx.count < ctx.max) {
+		str[ctx.count] = '\0';
+	}
+
+	return ctx.count;
+}
Index: ModuleDemo/BLE/CM0/User/utils/queue.c
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/queue.c	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/User/utils/queue.c	(working copy)
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2010-2016 Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ *
+ * @brief dynamic-size QUEUE object.
+ */
+
+
+#include <kernel.h>
+#include <toolchain.h>
+#include <init.h>
+#include <sys/check.h>
+
+struct alloc_node {
+	sys_sfnode_t node;
+	void *data;
+};
+
+void *z_queue_node_peek(sys_sfnode_t *node, bool needs_free)
+{
+	void *ret;
+
+	if ((node != NULL) && (sys_sfnode_flags_get(node) != (uint8_t)0)) {
+		/* If the flag is set, then the enqueue operation for this item
+		 * did a behind-the scenes memory allocation of an alloc_node
+		 * struct, which is what got put in the queue. Free it and pass
+		 * back the data pointer.
+		 */
+		struct alloc_node *anode;
+
+		anode = CONTAINER_OF(node, struct alloc_node, node);
+		ret = anode->data;
+		if (needs_free) {
+			k_free(anode);
+		}
+	} else {
+		/* Data was directly placed in the queue, the first word
+		 * reserved for the linked list. User mode isn't allowed to
+		 * do this, although it can get data sent this way.
+		 */
+		ret = (void *)node;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_OBJECT_TRACING
+
+struct k_queue *_trace_list_k_queue;
+
+/*
+ * Complete initialization of statically defined queues.
+ */
+static int init_queue_module(const struct device *dev)
+{
+	ARG_UNUSED(dev);
+
+	Z_STRUCT_SECTION_FOREACH(k_queue, queue) {
+		SYS_TRACING_OBJ_INIT(k_queue, queue);
+	}
+	return 0;
+}
+
+SYS_INIT(init_queue_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
+
+#endif /* CONFIG_OBJECT_TRACING */
+
+void z_impl_k_queue_init(struct k_queue *queue)
+{
+	sys_sflist_init(&queue->data_q);
+	//queue->lock = (struct k_spinlock) {};
+	//z_waitq_init(&queue->wait_q);
+#if defined(CONFIG_POLL)
+	sys_dlist_init(&queue->poll_events);
+#endif
+
+	//SYS_TRACING_OBJ_INIT(k_queue, queue);
+	//z_object_init(queue);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline void z_vrfy_k_queue_init(struct k_queue *queue)
+{
+	Z_OOPS(Z_SYSCALL_OBJ_NEVER_INIT(queue, K_OBJ_QUEUE));
+	z_impl_k_queue_init(queue);
+}
+#include <syscalls/k_queue_init_mrsh.c>
+#endif
+
+static void prepare_thread_to_run(struct k_thread *thread, void *data)
+{
+	//z_thread_return_value_set_with_data(thread, 0, data);
+	//z_ready_thread(thread);
+}
+
+static inline void handle_poll_events(struct k_queue *queue, uint32_t state)
+{
+#ifdef CONFIG_POLL
+	z_handle_obj_poll_events(&queue->poll_events, state);
+#endif
+}
+
+void z_impl_k_queue_cancel_wait(struct k_queue *queue)
+{
+	//k_spinlock_key_t key = k_spin_lock(&queue->lock);
+	//struct k_thread *first_pending_thread;
+
+	//first_pending_thread = z_unpend_first_thread(&queue->wait_q);
+
+	//if (first_pending_thread != NULL) {
+	//	prepare_thread_to_run(first_pending_thread, NULL);
+	//}
+
+	//handle_poll_events(queue, K_POLL_STATE_CANCELLED);
+	//z_reschedule(&queue->lock, key);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline void z_vrfy_k_queue_cancel_wait(struct k_queue *queue)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	z_impl_k_queue_cancel_wait(queue);
+}
+#include <syscalls/k_queue_cancel_wait_mrsh.c>
+#endif
+
+static int32_t queue_insert(struct k_queue *queue, void *prev, void *data,
+			  bool alloc)
+{
+	//k_spinlock_key_t key = k_spin_lock(&queue->lock);
+	//struct k_thread *first_pending_thread;
+
+	//first_pending_thread = z_unpend_first_thread(&queue->wait_q);
+
+	//if (first_pending_thread != NULL) {
+	//	prepare_thread_to_run(first_pending_thread, data);
+	//	z_reschedule(&queue->lock, key);
+	//	return 0;
+	//}
+
+	/* Only need to actually allocate if no threads are pending */
+	if (alloc) {
+		struct alloc_node *anode;
+
+		//anode = z_thread_malloc(sizeof(*anode));
+		if (anode == NULL) {
+			//k_spin_unlock(&queue->lock, key);
+			return -ENOMEM;
+		}
+		anode->data = data;
+		sys_sfnode_init(&anode->node, 0x1);
+		data = anode;
+	} else {
+		sys_sfnode_init(data, 0x0);
+	}
+
+	sys_sflist_insert(&queue->data_q, prev, data);
+	handle_poll_events(queue, K_POLL_STATE_DATA_AVAILABLE);
+	//z_reschedule(&queue->lock, key);
+	return 0;
+}
+
+void k_queue_insert(struct k_queue *queue, void *prev, void *data)
+{
+	(void)queue_insert(queue, prev, data, false);
+}
+
+void k_queue_append(struct k_queue *queue, void *data)
+{
+	(void)queue_insert(queue, sys_sflist_peek_tail(&queue->data_q),
+			   data, false);
+}
+
+void k_queue_prepend(struct k_queue *queue, void *data)
+{
+	(void)queue_insert(queue, NULL, data, false);
+}
+
+int32_t z_impl_k_queue_alloc_append(struct k_queue *queue, void *data)
+{
+	return queue_insert(queue, sys_sflist_peek_tail(&queue->data_q), data,
+			    true);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int32_t z_vrfy_k_queue_alloc_append(struct k_queue *queue,
+						void *data)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_alloc_append(queue, data);
+}
+#include <syscalls/k_queue_alloc_append_mrsh.c>
+#endif
+
+int32_t z_impl_k_queue_alloc_prepend(struct k_queue *queue, void *data)
+{
+	return queue_insert(queue, NULL, data, true);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline int32_t z_vrfy_k_queue_alloc_prepend(struct k_queue *queue,
+						 void *data)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_alloc_prepend(queue, data);
+}
+#include <syscalls/k_queue_alloc_prepend_mrsh.c>
+#endif
+
+int k_queue_append_list(struct k_queue *queue, void *head, void *tail)
+{
+	/* invalid head or tail of list */
+	CHECKIF(head == NULL || tail == NULL) {
+		return -EINVAL;
+	}
+
+	//k_spinlock_key_t key = k_spin_lock(&queue->lock);
+	//struct k_thread *thread = NULL;
+
+	if (head != NULL) {
+		//thread = z_unpend_first_thread(&queue->wait_q);
+	}
+
+	//while ((head != NULL) && (thread != NULL)) {
+	//	prepare_thread_to_run(thread, head);
+	//	head = *(void **)head;
+	//	thread = z_unpend_first_thread(&queue->wait_q);
+	//}
+
+	if (head != NULL) {
+		sys_sflist_append_list(&queue->data_q, head, tail);
+	}
+
+	handle_poll_events(queue, K_POLL_STATE_DATA_AVAILABLE);
+	//z_reschedule(&queue->lock, key);
+	return 0;
+}
+
+int k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list)
+{
+	int ret;
+
+	/* list must not be empty */
+	CHECKIF(sys_slist_is_empty(list)) {
+		return -EINVAL;
+	}
+
+	/*
+	 * note: this works as long as:
+	 * - the slist implementation keeps the next pointer as the first
+	 *   field of the node object type
+	 * - list->tail->next = NULL.
+	 * - sflist implementation only differs from slist by stuffing
+	 *   flag bytes in the lower order bits of the data pointer
+	 * - source list is really an slist and not an sflist with flags set
+	 */
+	ret = k_queue_append_list(queue, list->head, list->tail);
+	CHECKIF(ret != 0) {
+		return ret;
+	}
+	sys_slist_init(list);
+
+	return 0;
+}
+
+void *z_impl_k_queue_get(struct k_queue *queue, k_timeout_t timeout)
+{
+	//k_spinlock_key_t key = k_spin_lock(&queue->lock);
+	void *data;
+
+	if (likely(!sys_sflist_is_empty(&queue->data_q))) {
+		sys_sfnode_t *node;
+
+		node = sys_sflist_get_not_empty(&queue->data_q);
+		data = z_queue_node_peek(node, true);
+		//k_spin_unlock(&queue->lock, key);
+		return data;
+	}
+
+	//if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
+	//	k_spin_unlock(&queue->lock, key);
+	//	return NULL;
+	//}
+
+	//int ret = z_pend_curr(&queue->lock, key, &queue->wait_q, timeout);
+
+	//return (ret != 0) ? NULL : _current->base.swap_data;
+	return 0;
+}
+void *k_queue_get(struct k_queue *queue, k_timeout_t timeout)
+{
+	return z_impl_k_queue_get(queue, timeout);
+}
+
+#ifdef CONFIG_USERSPACE
+static inline void *z_vrfy_k_queue_get(struct k_queue *queue,
+				       k_timeout_t timeout)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_get(queue, timeout);
+}
+#include <syscalls/k_queue_get_mrsh.c>
+
+static inline int z_vrfy_k_queue_is_empty(struct k_queue *queue)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_is_empty(queue);
+}
+#include <syscalls/k_queue_is_empty_mrsh.c>
+
+static inline void *z_vrfy_k_queue_peek_head(struct k_queue *queue)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_peek_head(queue);
+}
+#include <syscalls/k_queue_peek_head_mrsh.c>
+
+static inline void *z_vrfy_k_queue_peek_tail(struct k_queue *queue)
+{
+	Z_OOPS(Z_SYSCALL_OBJ(queue, K_OBJ_QUEUE));
+	return z_impl_k_queue_peek_tail(queue);
+}
+#include <syscalls/k_queue_peek_tail_mrsh.c>
+
+#endif /* CONFIG_USERSPACE */
Index: ModuleDemo/BLE/CM0/respin/memmap.format
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/memmap.format	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/memmap.format	(working copy)
@@ -0,0 +1,1704 @@
+0x0000 mem_le_adv_transmit
+0x0001 mem_le_adv_waitcnt
+0x0002 mem_sbc_error
+0x0002 mem_le_adv_rcv
+0x0003 mem_le_req_rcv
+0x0004 mem_le_scanrsp_rcv
+0x0005 mem_le_conn_rcv
+0x0006 mem_inquiryscan_waitcnt
+0x0007 mem_inquiryscan_rcvcnt
+0x0008 mem_pagescan_waitcnt
+0x0009 mem_pagescan_rcvcnt
+0x000a mem_pagescan_rcvfhscnt
+0x000b mem_slave_rcvcnt
+0x000c mem_page_transmit
+0x000d mem_page_rcv
+0x000e mem_page_rcv_fhs
+0x000f mem_master_rcvcnt
+0x0010 mem_fhs_wait_counter
+0x0011 mem_newconnto_counter
+0x0012 mem_inquiry_transmit
+0x0013 mem_inquiry_rcv
+0x0014 mem_fw_ver
+0x0015 mem_current_context
+0x0016 mem_empty_block
+0x0017 mem_last_freq
+0x0018 mem_rssi
+0x0019 mem_rx_type
+0x001a mem_rx_hec_err
+0x001c mem_rx_crc_err
+0x001e mem_context_ptr
+0x0020 mem_display
+0x0028 mem_bcd
+0x0030 mem_state
+0x0031 mem_mode
+0x0032 mem_tsniff
+0x0034 mem_sniff_anchor
+0x0038 mem_clk_offset
+0x003e mem_rx_window
+0x0040 mem_plap
+0x0043 mem_puap
+0x0044 mem_pnap
+0x0046 mem_conn_handle
+0x0047 mem_cur_arq
+0x0048 mem_lmp_to_send
+0x0049 mem_lmi_opcode
+0x004a mem_lmo_reason
+0x004b mem_op
+0x004c mem_state_map
+0x004d mem_supervision_timer
+0x0051 mem_supervision_to
+0x0053 mem_name_offset
+0x0054 mem_key_size
+0x0055 mem_reconn_lmp_sm
+0x0056 mem_aco
+0x0062 mem_kc
+0x0072 mem_conn_timer
+0x0073 mem_sniff_attempt
+0x0074 mem_sniff_timeout
+0x0075 mem_dsniff
+0x0077 mem_amaddr
+0x0078 mem_lmo_opcode1
+0x0079 mem_lmi_opcode1
+0x007a mem_lmo_reason1
+0x007b mem_lmo_tid1
+0x007c mem_lmo_opcode2
+0x007d mem_lmi_opcode2
+0x007e mem_lmo_reason2
+0x007f mem_lmo_tid2
+0x0080 mem_mark_load
+0x0088 mem_hci_version
+0x008b mem_acl_pktlen
+0x008d mem_sco_pktlen
+0x008e mem_acl_pktcnt
+0x0090 mem_sco_pktcnt
+0x0092 mem_current_sniff_attempt
+0x0093 mem_current_sniff_timeout
+0x0094 mem_nfreq_index_inq
+0x0095 mem_nfreq_index_page
+0x0096 mem_ninqy_index
+0x0097 mem_fhs_misc
+0x0098 mem_tx_lch
+0x0099 mem_tx_len
+0x009b mem_subsniff_instant
+0x009f mem_subsniff_rate
+0x00a0 mem_subsniff_tcmax
+0x00a2 mem_subsniff_tsniff
+0x00a3 mem_lpm_adjust
+0x00a4 mem_sync_clke
+0x00aa mem_lpm_current_mult
+0x00ab mem_gpio_wakeup_low
+0x00b0 mem_gpio_wakeup_high
+0x00b5 mem_npage_index
+0x00b6 mem_page_mode
+0x00b7 mem_page_clk
+0x00bb mem_tst_pktcnt_sync
+0x00bd mem_tst_pktcnt_hec
+0x00bf mem_tst_pktcnt_crc
+0x00c1 mem_tst_pktcnt_dmh
+0x00c3 mem_tmp_buffer_head
+0x00c6 mem_tmp_buffer
+0x0116 mem_tester_emulate
+0x0117 mem_temp_payload
+0x0117 test_mode_scenario
+0x0118 test_mode_hopping_mode
+0x0119 test_mode_tx_freq
+0x011a test_mode_rx_freq
+0x011b test_mode_power_mode
+0x011c test_mode_poll_period
+0x011d test_mode_packet_type
+0x011e test_mode_data_length
+0x0120 mem_test_mode_old_debug_config
+0x0121 mem_tester_cnt
+0x0122 mem_temp_am_addr
+0x0123 mem_temp_arq
+0x0124 mem_pdatatemp
+0x012c mem_len
+0x012e mem_clkn_bt
+0x0132 mem_clke_bt
+0x0136 mem_dpll_clkn
+0x013a mem_connection_options
+0x013b mem_nameres_cnt
+0x013c mem_txptr
+0x013e mem_slot_offset
+0x0140 mem_wait_auth_clk
+0x0144 extm_fhs_misc
+0x0145 extm_newconn_am_addr
+0x0146 extm_class
+0x0149 extm_lap
+0x014c extm_uap
+0x014d extm_nap
+0x0150 mem_debug_config
+0x0151 mem_lch_code
+0x0152 mem_fhs_am_addr
+0x0153 mem_dpll_error
+0x0155 mem_bdaddr_list_buff
+0x0179 mem_select_list_item
+0x017a mem_temp_reconn_record
+0x017a mem_record_bt_mode
+0x017b mem_temp_lap
+0x0181 mem_list_item_ptr
+0x0183 mem_eir
+0x01e7 mem_switch_timeout
+0x01e9 mem_acl_dsniff
+0x01eb mem_acl_tsniff
+0x01ed mem_acl_attempt
+0x01ee mem_acl_timeout
+0x01ef mem_temp_force_nack
+0x01f0 mem_avdtp_signal_cmd
+0x01f1 mem_transaction_label
+0x01f2 mem_temp_sbc_decode_buffer_size
+0x01f4 mem_temp_dac_soft_dma_work_wptr
+0x01f6 mem_temp_sbc_soft_dma_start_addr
+0x01f8 mem_temp_dac_soft_dma_start_addr
+0x01fa mem_temp_soft_dma_work_length
+0x01fc mem_temp_soft_dma_work_table_index_value
+0x01fd mem_ucode_status
+0x01fe mem_ucode_flag
+0x0200 mem_qspi_tbuf/* spid buf: 03 addr[23:16] addr[15:8] addr[7:0] */
+0x0201 mem_iicd_tbuf/* iicd buf: iic_adr addr[15:8] addr[7:0] iic_adr */
+0x0201 mem_addr_hi
+0x0202 mem_eep_addr_hi
+0x0202 mem_addr_mi
+0x0203 mem_addr_lo
+0x0204 mem_iicd_addr
+0x0205 mem_spid_rbuf
+0x0209 mem_ucode_buf
+0x020b mem_ucode_len
+0x020d mem_sched_addr
+0x020f mem_ucode_ptr
+0x0212 mem_ucode_keybuf
+0x0222 mem_check_plap_temp
+0x0234 mem_start_addr_temp
+0x0237 mem_spid_tbuf
+0x0239 mem_qspi_defualt
+0x023a mem_switch_fail_master_count
+0x023b mem_app_evt_timer_count
+0x023c mem_flash_address
+0x023f mem_flash_data_address
+0x0241 mem_flash_trans_length
+0x0243 mem_soft_dma_src_addr
+0x0247 mem_soft_dma_dst_addr
+0x024b mem_avctp_command_response
+0x024c mem_avrcp_vol
+0x024d mem_avctp_rx_label
+0x024e mem_h5rx_ackcnt
+0x024f mem_check_err_acl_cont
+0x0250 mem_rp_packets
+0x0251 mem_packet_type
+0x0253 mem_hci_sniff_conn_handle
+0x0255 mem_hci_sniff_max_interval
+0x0257 mem_hci_sniff_min_interval
+0x0259 mem_hci_sniff_attempt
+0x025b mem_hci_sniff_timeout
+0x025d mem_voice_setting
+0x025f mem_retransmission_effort
+0x0260 mem_sco_ptype
+0x0262 mem_extm_uap_restore
+0x0265 mem_h5rx_rptr
+0x0267 mem_h5rx_ack
+0x0268 mem_h5tx_ack
+0x0269 mem_h5tx_rptr
+0x026b mem_h5tx_wptr
+0x026d mem_h5tx_free
+0x026f mem_h5rx_tmp
+0x0270 mem_h5tx_seq
+0x0271 mem_hci_acl_queue_wptr
+0x0273 mem_hci_acl_queue_rptr
+0x0275 mem_hci_acl_queue_end
+0x0277 mem_hci_acl_queue_wcnt
+0x0278 mem_hci_acl_cnt
+0x0279 mem_hci_acl_tx_trigger_wptr//tx via uart
+0x027b mem_ucode_id_local
+0x027c mem_ucode_id_remote
+0x027d mem_check_sum
+0x027e mem_ucode_temp
+0x027f mem_ucode_temp1
+0x0280 mem_lock_in_enc
+0x0281 mem_hci_disconn_reason
+0x0282 mem_hci_curr_len
+0x0283 mem_hci_curr_target
+0x0285 mem_coef_table_temp
+0x03d7 mem_sco_indata
+0x0413 mem_sco_outdata
+0x044f mem_phone_num_count
+0x0450 mem_phone_num_len
+0x0451 mem_phone_number
+0x0460 mem_at_command_data
+0x047e mem_sco_flag
+0x047f mem_l2cap_mem_start
+0x047f mem_l2cap_rxbuff1_len
+0x0481 mem_l2cap_rxbuff2_len
+0x0483 mem_l2cap_rxbuff_new_temp
+0x0484 mem_l2cap_rxbuff_new
+0x0485 mem_l2cap_rxbuff_fifo
+0x0485 mem_l2cap_rxbuff_fifo1
+0x0486 mem_l2cap_rxbuff_fifo2
+0x0487 mem_l2cap_payload_ptr
+0x0489 mem_l2cap_rx_pkt_length
+0x048b mem_l2cap_rx_cid
+0x048d mem_l2cap_rx_done
+0x048e mem_l2cap_signal_ident
+0x048f mem_sdp_tx_buff_ptr
+0x0491 mem_sdp_tx_payload_ptr
+0x0493 mem_sdp_tx_pkt_length
+0x0495 mem_tx_malloc_log
+0x04d5 mem_l2cap_temp_ch_info
+0x04d5 mem_l2cap_temp_ch_psm
+0x04d6 mem_l2cap_temp_ch_state
+0x04d7 mem_l2cap_temp_local_cid
+0x04d9 mem_l2cap_temp_remote_cid
+0x04db mem_l2cap_mem_end
+0x04db mem_le_rxbuf
+0x0503 mem_le_l2capbuf
+0x05db mem_le_mic
+0x05df mem_le_peer_mic
+0x05e3 mem_le_skdm
+0x05eb mem_le_skds
+0x05f3 mem_le_peer_ltk
+0x0603 mem_le_my_ltk
+0x0613 mem_le_mrand
+0x0623 mem_le_state
+0x0624 mem_le_mode
+0x0625 mem_le_tsniff
+0x0627 mem_le_anchor
+0x062b mem_le_clk_offset
+0x0631 mem_le_receive_window
+0x0633 mem_le_plap
+0x0639 mem_le_conn_handle
+0x063a mem_le_arq
+0x063b mem_le_ch
+0x063c mem_le_hop
+0x063d mem_le_event_count
+0x063f mem_le_supervision_timer
+0x0643 mem_le_instant
+0x0645 mem_le_channels
+0x0646 mem_le_conn_sm
+0x0647 mem_le_op
+0x0648 mem_le_access
+0x064c mem_le_crcinit
+0x064f mem_le_window_size
+0x0650 mem_le_slave_latency
+0x0652 mem_le_superto
+0x0654 mem_le_channel_map
+0x0659 mem_le_no_using
+0x065b mem_le_peer_sca
+0x065c mem_le_att_opcode
+0x065d mem_le_att_handle
+0x065f mem_le_err_code
+0x0660 mem_le_ll_pairing_fail_reason
+0x0661 mem_le_sk
+0x0671 mem_le_testtype
+0x0672 mem_le_test_sync
+0x0674 mem_le_test_pcnt
+0x0676 mem_le_notify_len
+0x0677 mem_cmd_le_create_conn
+0x0678 mem_le_adv_temp
+0x068c mem_le_packet_size
+0x068d mem_le_packet_llid
+0x068e mem_le_payload_ptr
+0x0690 mem_lmo_header_length
+0x0691 mem_lmo_header_opcode
+0x0692 mem_lmo_payload
+0x06a3 mem_lmi_accepted_opcode
+0x06a4 mem_disconn_reason_send
+0x06a5 mem_tx_fixed_freq
+0x06a6 mem_rx_fixed_freq
+0x06a7 mem_ext_features_page
+0x06a8 mem_lmpext_ssp_enable
+0x06aa mem_remote_sppcap
+0x06ab mem_lmp_conn_state
+0x06ac mem_soft_timer
+0x06ae mem_pincode_state
+0x06af mem_sres_tid
+0x06b0 mem_accptsco_tid
+0x06b1 mem_wait_encryption
+0x06b2 mem_sniff_payload
+0x06c2 mem_aurand_send_delay_time
+0x06c6 mem_prcp_data
+0x06da mem_prcp
+0x06db mem_prcp_tx_len
+0x06dc rx_buf_data_ptr
+0x06de mem_mod2div_temp
+0x06e1 mem_contw_temp
+0x06e3 mem_rfc_adss
+0x06e4 mem_rfc_current_channel
+0x06e5 mem_rfc_frame_type
+0x06e6 mem_current_fcs
+0x06e7 mem_rfc_paylead_length
+0x06e9 mem_rfc_paylead_ptr
+0x06eb mem_uih_cmd_type
+0x06ec mem_uih_length
+0x06ee mem_rfc_payload_ptr
+0x06f0 mem_ms_param
+0x06f1 mem_pn_credit_flow_type_info
+0x06f2 mem_pn_priority
+0x06f3 mem_pn_acknowledg_timer
+0x06f4 mem_pn_max_retrans
+0x06f5 mem_rfcomm_send_adss
+0x06f6 mem_rfcomm_send_frame_type
+0x06f7 mem_rfcomm_send_fcs
+0x06f8 mem_sdp_mem_start
+0x06f8 mem_sdp_uuid_search_ptr
+0x0700 mem_sdp_continue_byte
+0x0702 mem_sdp_pduid
+0x0703 mem_sdp_transactionid
+0x0705 mem_sdp_transactionid_local
+0x0707 mem_sdp_attribute_maxbyte
+0x0709 mem_sdp_record_maxcnt
+0x070b mem_sdp_record_handle
+0x070f mem_sdp_LACAP_found
+0x0710 mem_sdp_RFCOMM_found
+0x0711 mem_sdp_handle_list
+0x0711 mem_sdp_attrib_list
+0x0731 mem_sdp_error_code
+0x0733 mem_sdp_all_length
+0x0735 mem_handle_humber
+0x0736 mem_search_uuid
+0x0738 mem_sdp_mem_end
+0x0738 mem_rxbuf
+0x0749 mem_random_number
+0x0759 mem_round_key
+0x0769 mem_kinit
+0x0779 mem_input_store
+0x0789 mem_x
+0x0799 mem_y
+0x07a8 mem_y15
+0x07a9 mem_key_store
+0x07ba mem_key_store_end
+0x07bb memp_ar_key
+0x07bd memp_ar_input
+0x07bf mem_ar_hround
+0x07c9 mem_ec_infinite
+0x07ca mem_ec_loopc
+0x07cc mem_aes_cmac_data_length
+0x07cd memdat
+0x07cd mem_ax
+0x07e5 mem_ay
+0x07fd mem_az
+0x0815 mem_bx
+0x082d mem_ax_256//32 bytes
+0x082d mem_by
+0x0845 mem_bz
+0x084d mem_ay_256// 32 bytes
+0x085d mem_cx
+0x086d mem_az_256// 32 bytes
+0x0875 mem_cy
+0x088c mem_cy5
+0x088d mem_bx_256// 32 bytes
+0x088d mem_cz
+0x08a5 mem_k
+0x08ad mem_by_256// 31 bytes
+0x08bd mem_align
+0x08cd mem_bz_256//32 bytes
+0x08cd mem_tmp1
+0x08cd memahbak
+0x08e5 mem_tmp5
+0x08ed mem_cx_256//32 bytes
+0x08ed memahsave
+0x08fd mem_tmp2
+0x090d mem_cy_256// 32 bytes
+0x090d memahsave_end
+0x090d mem_addr_padding
+0x090e mem_addr_value/* 12 bytes     */ 
+0x0915 mem_tmp3
+0x0915 mem_t1
+0x091a mem_addr_value_end
+0x091d mem_addr_iocap_end
+0x092c mem_cy5_256// 1 byte
+0x092d mem_cz_256// 32 bytes
+0x092d mem_tmp0
+0x092d mem_t0
+0x0935 mem_tmp0a
+0x0945 mem_t2
+0x094d mem_k_256//32 bytes
+0x095d mem_t3
+0x096d mem_tmp1_256//32 bytes
+0x0975 mem_t7
+0x098d mem_tmp5_256
+0x09ad mem_tmp2_256
+0x09cd mem_tmp3_256
+0x09cd mem_t1_256
+0x09ed mem_tmp0_256
+0x09ed mem_t0_256
+0x0a0d mem_t2_256
+0x0a2d mem_t3_256
+0x0a4d mem_t7_256
+0x0a6d mem_p
+0x0a85 mem_a
+0x0a9d mem_b
+0x0ab5 mem_gx
+0x0acd mem_gy
+0x0ae5 memh0
+0x0b05 mem_p_256
+0x0b25 mem_a_256
+0x0b45 mem_gx_256
+0x0b65 mem_gy_256
+0x0b85 mem_le_slat
+0x0b95 mem_sp_state_start
+0x0b95 mem_sp_state
+0x0b96 mem_master_sp_state
+0x0b97 mem_sp_flag
+0x0b98 mem_master_sp_flag
+0x0b99 mem_sp_calc
+0x0b9a mem_sp_dh_ready
+0x0b9b mem_sp_localsm
+0x0b9c mem_pairing_auth
+0x0b9d mem_sp_flag_start
+0x0b9d mem_sp_local_key_send_count
+0x0b9e mem_sp_remote_key_recv_count
+0x0b9f mem_sp_remote_key_invalid
+0x0ba0 mem_sp_dhkey_invalid
+0x0ba1 mem_gkey
+0x0ba5 mem_le_pubkey_remote_x_256
+0x0bad mem_sp_pubkey_remote
+0x0bad mem_sp_pubkey_remote_x
+0x0bc5 mem_sp_pubkey_remote_x_end
+0x0bc5 mem_sp_pubkey_remote_y
+0x0bc5 mem_le_pubkey_remote_y_256
+0x0be5 mem_le_dhkey_256
+0x0bed mem_sp_dhkey
+0x0c05 mem_sp_dhkey_end
+0x0c05 mem_sp_random_local
+0x0c15 mem_sp_random_local_end
+0x0c15 mem_sp_random_remote
+0x0c25 mem_sp_random_remote_end
+0x0c25 memresult
+0x0c25 mem_sp_calc_result
+0x0c25 memh
+0x0c29 memg
+0x0c2d memf
+0x0c31 meme
+0x0c35 mem_sp_calc_result_high
+0x0c35 memd
+0x0c39 memc
+0x0c3d memb
+0x0c41 mema
+0x0c45 mem_sp_check_result
+0x0c55 mem_sp_confirm_remote
+0x0c65 mem_sp_prarm_stack
+0x0c75 mem_ipc_skip_continue_proc
+0x0c76 mem_row_scanned_record
+0x0c77 mem_col_scanned_record
+0x0c78 mem_get_keypress_flag_record
+0x0c79 mem_usb_status
+0x0c7a mem_usb_fifo_empty
+0x0c7b mem_usb_read_len
+0x0c7d mem_usb_txbuf
+0x0cbe mem_usb_txbuf1
+0x0cc8 mem_usb_txbuf2
+0x0cd2 mem_usb_rxbuf
+0x0d0e mem_usb_rxbuf_end
+0x0d0f mem_usb_state
+0x0d10 mem_bufptr
+0x0d12 mem_remain
+0x0d13 mem_devicedesc
+0x0d27 mem_hidreportdesc_kb
+0x0d6d mem_hidreportdesc_m
+0x0e35 mem_confdesc
+0x0e7b mem_string0
+0x0e80 mem_string1
+0x0e9e mem_string2
+0x0ebc mem_string3
+0x0eda mem_usb_setup
+0x0eda mem_usb_setup_bmRequestType
+0x0edb mem_usb_setup_bRequest
+0x0edc mem_usb_setup_bValue
+0x0edd mem_usb_setup_bValueH
+0x0ede mem_usb_setup_wIndex
+0x0ee0 mem_usb_setup_bLength
+0x0ee1 mem_usb_setup_bLengthH
+0x0ee2 mem_usb0_setup_ptr
+0x0ee4 mem_usb0_set_report_data_ptr
+0x0ee6 mem_usb_setup_bValue_temp
+0x0ee8 mem_usb0_get_set_report
+0x0ee9 mem_usb0_data_ready_report
+0x0eea mem_usb_tx_win_enable
+0x0eeb mem_usb_tx_mac_enable
+0x0eec mem_usb_zero_packet
+0x0eee mem_usb_ones_packet
+0x0ef0 mem_usb_two_packet
+0x0ef2 mem_usb_idle_flag
+0x0ef3 mem_usb_idle_rate
+0x0ef4 mem_usb_get_protocol_flag
+0x0ef5 mem_usb_set_protocol_status
+0x0ef6 mem_usb_set_protocol_value
+0x0ef7 mem_usb0_state
+0x0ef8 mem_usb_remote_wakeup
+0x0ef9 mem_usb_clear_remote_wakeup
+0x0efa mem_usb_ep0_stall_status
+0x0efb mem_usb_ep1_stall_status
+0x0efc mem_usb_ep2_stall_status
+0x0efd mem_usb_ep3_stall_status
+0x0efe mem_dsc_info_data_pointer
+0x0f00 mem_dsc_info_len
+0x0f01 mem_usb_ep1_data
+0x0f02 mem_usb_ep2_data
+0x0f03 mem_usb_tx_enable
+0x0f04 mem_usb_device_enumeration_endflag
+0x0f05 mem_usb_wakestate_onetime_flag
+0x0f06 mem_usb_mac_wakeup_trig
+0x0f07 mem_usb_set_high_addr_flag
+0x0f08 mem_usb_clear_halt
+0x0f09 mem_hold_contr
+0x0f0b mem_hold_contw
+0x0f0d mem_fifo_temp
+0x0f0e mem_max_bitsneed
+0x0f12 mem_bits_need00
+0x0f12 mem_temp
+0x0f16 mem_bits_need01
+0x0f16 mem_temp1
+0x0f1a mem_bits_need02
+0x0f1a mem_timeup
+0x0f1e mem_bits_need03
+0x0f1e mem_rega
+0x0f22 mem_bits_need04
+0x0f22 mem_regb
+0x0f26 mem_bits_need05
+0x0f26 mem_regc
+0x0f2a mem_bits_need06
+0x0f2a mem_contr
+0x0f2c mem_contw
+0x0f2e mem_bits_need07
+0x0f32 mem_bits_need10
+0x0f36 mem_bits_need11
+0x0f3a mem_bits_need12
+0x0f3e mem_bits_need13
+0x0f42 mem_bits_need14
+0x0f46 mem_bits_need15
+0x0f4a mem_bits_need16
+0x0f4e mem_bits_need17
+0x0f52 mem_wakup_from_power_flag
+0x0f53 mem_saved_gpio_in
+0x0f57 mem_flash_data_address_t
+0x0f57 mem_le_data_len_temp//1byte
+0x0f57 mem_tx_fifo_map_temp
+0x0f57 mem_rpn_dlci//1byte
+0x0f57 mem_event_cmd_response_content//2byte
+0x0f57 mem_le_prand//16byte
+0x0f57 mem_AES_CMAC_k//16 bytes
+0x0f57 mem_regext_index//1 bytes
+0x0f57 mem_temp_block0
+0x0f58 mem_le_data_temp//15bytes
+0x0f58 mem_temp_block1
+0x0f67 mem_le_aes_128//16byte
+0x0f67 mem_regext//64 bytes
+0x0f67 mem_AES_CMAC_k1//16 bytes
+0x0f67 mem_sum_temp
+0x0f67 mem_temp_block2
+0x0f77 mem_AES_CMAC_k2//16 bytes
+0x0f77 mem_temp_block3
+0x0f87 mem_AES_CMAC_temp// 16 bytes
+0x0f87 mem_temp_block4
+0x0f97 mem_AES_CMAC_M_last// 16 bytes
+0x0f97 mem_temp_block5
+0x0fa7 mem_le_mackey//16 bytes
+0x0fa7 mem_temp_block6
+0x0fb7 mem_zcode_temp_param0
+0x0fb8 mem_zcode_temp_param1
+0x0fba mem_zcode_temp_param2
+0x0fbc mem_tws_sync_clk
+0x0fc0 mem_tws_connecting_phase
+0x0fc1 mem_temp_tx_power
+0x0fc2 mem_msbc_miss
+0x0fc4 mem_msbc_error
+0x0fc6 mem_vp_length
+0x0fc9 mem_ota_cmd
+0x0fca mem_ota_return_result
+0x0fcb mem_ota_update_flash_mode
+0x0fcc mem_ota_write_index
+0x0fce mem_ota_write_length
+0x0fd0 mem_ota_write_data_addr
+0x0fd3 mem_ota_write_flash_addr
+0x0fd6 mem_ota_enable_xip_flag
+0x0fd7 mem_xip_flash_offset_mram
+0x0fda mem_storage_start_addr_mram
+0x0fdd mem_ota_notify_handle_mram
+0x0fde mem_ota_write_handle_mram
+0x0fdf mem_ota_buck_size_mram
+0x0fe1 mem_ota_packet_max_len_mram
+0x0fe3 mem_ota_wdt_en_flag
+0x0fe4 mem_ota_wdt_m0_en
+0x4000 mem_patch00
+0x4001 mem_patch01
+0x4002 mem_patch02
+0x4003 mem_patch03
+0x4004 mem_patch04
+0x4005 mem_patch05
+0x4006 mem_patch06
+0x4007 mem_patch07
+0x4008 mem_patch08
+0x4009 mem_patch09
+0x400a mem_patch0a
+0x400b mem_patch0b
+0x400c mem_patch0c
+0x400d mem_patch0d
+0x400e mem_patch0e
+0x400f mem_patch0f
+0x4010 mem_patch10
+0x4011 mem_patch11
+0x4012 mem_patch12
+0x4013 mem_patch13
+0x4014 mem_patch14
+0x4015 mem_patch15
+0x4016 mem_patch16
+0x4017 mem_patch17
+0x4018 mem_patch18
+0x4019 mem_patch19
+0x401a mem_patch1a
+0x401b mem_patch1b
+0x401c mem_patch1c
+0x401d mem_patch1d
+0x401e mem_patch1e
+0x401f mem_patch1f
+0x4020 mem_patch20
+0x4021 mem_patch21
+0x4022 mem_patch22
+0x4023 mem_patch23
+0x4024 mem_patch24
+0x4025 mem_patch25
+0x4026 mem_patch26
+0x4027 mem_patch27
+0x4028 mem_patch28
+0x4029 mem_patch29
+0x402a mem_patch2a
+0x402b mem_patch2b
+0x402c mem_patch2c
+0x402d mem_patch2d
+0x402e mem_patch2e
+0x402f mem_patch2f
+0x4030 mem_patch30
+0x4031 mem_patch31
+0x4032 mem_patch32
+0x4033 mem_patch33
+0x4034 mem_patch34
+0x4035 mem_patch35
+0x4036 mem_patch36
+0x4037 mem_patch37
+0x4038 mem_patch38
+0x4039 mem_patch39
+0x403a mem_patch3a
+0x403b mem_patch3b
+0x403c mem_patch3c
+0x403d mem_patch3d
+0x403e mem_patch3e
+0x403f mem_patch3f
+0x4040 mem_context
+0x4130 mem_current_amaddr
+0x4131 mem_lpm_mode
+0x4132 mem_device_option
+0x4133 mem_scan_mode
+0x4134 mem_last_clkn
+0x4138 mem_features
+0x4140 mem_lap
+0x4143 mem_uap
+0x4144 mem_nap
+0x4146 mem_npage
+0x4147 mem_glap
+0x414a mem_class
+0x414d mem_iscan_window
+0x414f mem_iscan_interval
+0x4151 mem_pscan_window
+0x4153 mem_pscan_interval
+0x4155 mem_page_interval
+0x4157 mem_page_window
+0x4159 mem_page_to
+0x415b mem_inq_window
+0x415d mem_fcomp_mul
+0x415e mem_fcomp_div
+0x415f mem_rx_window_init
+0x4161 mem_rx_window_sniff
+0x4163 mem_rf_init_ptr
+0x4165 mem_rf_init
+0x4166 mem_last_type
+0x4167 mem_retransmission_cnt
+0x4169 mem_next_btclk
+0x416d mem_seqi
+0x416e mem_rf_rccal
+0x416f mem_handle_num
+0x4170 mem_max_slot
+0x4171 mem_eir_enable
+0x4172 mem_afh_instant
+0x4176 mem_afh_error_total
+0x4178 mem_afh_cfg
+0x4179 mem_afh_new_mod
+0x417a mem_afh_map_lo
+0x417f mem_afh_map_hi
+0x4184 mem_afh_used
+0x4185 mem_afh_index
+0x4187 mem_afh_map_new
+0x4192 mem_afh_map
+0x41e2 mem_afh_timer
+0x41e6 mem_afh_classify_channel_map
+0x41f0 mem_chip_functions
+0x41f2 mem_lpm_wake_lock
+0x41f4 mem_lpm_interval
+0x41f6 mem_lpm_overhead
+0x41f7 mem_lpm_hibernate_switch
+0x41f8 mem_sniff_unint_lost
+0x41f9 mem_ptt
+0x41fa mem_sleep_counter//should be 0x41fc in REVC
+0x41fe mem_sleep_counter_all
+0x4202 mem_sleep_clkn
+0x4208 mem_sniff_rcv
+0x420b mem_sniff_lost
+0x420e mem_clks_per_lpo
+0x4211 mem_lpm_loadcode_switch
+0x4212 mem_lpm_memory_choose
+0x4213 mem_lpm_mult
+0x4214 mem_lpm_mult_timeout
+0x4215 mem_lpm_mult_cnt
+0x4216 mem_lpm_config
+0x4219 mem_lpm_xtalcnt
+0x421a mem_lpm_buckcnt
+0x421b mem_lpm_ldocnt
+0x421c mem_lpm_isogate
+0x421d mem_lpm_isogate_final
+0x421e mem_saved_gpio// should be 0x421e in REVC
+0x4246 mem_saved_mark
+0x424e mem_saved_spidctrl
+0x424f mem_patch_ptr
+0x4251 mem_patch_len
+0x4253 mem_timers
+0x4293 mem_link_key_exists
+0x4294 mem_link_key_eeprom_head
+0x4297 mem_link_key
+0x42a7 mem_hci_cmd
+0x42a8 mem_hci_conn_handle
+0x42a9 mem_hci_plap
+0x42ac mem_hci_puap
+0x42ad mem_hci_pnap
+0x42af mem_uartd_rxitems_got_data
+0x42b0 mem_uartd_rxitems_threshold
+0x42b1 mem_uartd_rx_timeout
+0x42b3 mem_sco_attempt_cout
+0x42b4 mem_tx_power
+0x42b5 mem_sfreq_enable
+0x42b6 mem_param_rf_setup
+0x42b8 mem_param_pll_setup
+0x42ba mem_avdtp_xmem_start
+0x42ba mem_avdtpsignal_l2capch_ptr
+0x42bc mem_avdtpmedia_l2capch_ptr
+0x42be mem_audio_allow
+0x42bf mem_audio_state
+0x42c0 mem_audio_src_endpoint
+0x42c1 mem_audio_src_endpoint_state
+0x42c2 mem_a2dp_reconnct_delay_timer
+0x42c3 mem_avdtp_xmem_end
+0x42c3 mem_get_media_type
+0x42c4 mem_get_codec_type
+0x42c5 mem_get_samplefreq_channelmode
+0x42c6 mem_get_blocklen_subb_allocation
+0x42c7 mem_get_min_bitpool
+0x42c8 mem_get_max_bitpool
+0x42c9 mem_get_r_media_type
+0x42ca mem_get_r_codec_type
+0x42cb mem_get_r_samplefreq_channelmode
+0x42cc mem_get_r_blocklen_subb_allocation
+0x42cd mem_get_r_min_bitpool
+0x42ce mem_get_r_max_bitpool
+0x42cf mem_conf_media_type
+0x42d0 mem_conf_codec_type
+0x42d1 mem_conf_samplefreq_channelmode
+0x42d2 mem_conf_blocklen_subb_allocation
+0x42d3 mem_conf_min_bitpool
+0x42d4 mem_conf_max_bitpool
+0x42d5 mem_avc_local_transaction_label
+0x42d6 mem_avdtp_signal
+0x42d8 mem_avdtp_media
+0x42da mem_a2dp_state
+0x42db mem_a2dp_seq_num
+0x42dd mem_audio_output_setting
+0x42de mem_param_sco_use_cm0
+0x42df mem_media_in_fast_mode
+0x42e0 mem_a2dp_buffer_judge_add
+0x42e1 mem_param_a2dp_buffer_judge_add_limit
+0x42e2 mem_a2dp_buffer_judge_drop
+0x42e3 mem_param_a2dp_buffer_judge_drop_limit
+0x42e4 mem_drop_or_add_process_state
+0x42e5 mem_drop_or_add_min_receive_packet_size
+0x42e7 mem_first_buffer_cache
+0x42e8 mem_farrow_filter_delta_uk_sign_bit
+0x42e9 mem_farrow_filter_delta_uk
+0x42ed mem_a2dp_adjust_delta_uk_sign_bit
+0x42ee mem_a2dp_adjust_delta_uk
+0x42f2 mem_a2dp_adjust_total_work_sample
+0x42f6 mem_a2dp_adjust_delta_bytes_sign_bit
+0x42f7 mem_a2dp_adjust_delta_bytes
+0x42f9 mem_slave_force_mute_a2dp_voice
+0x42fa mem_slave_force_mute_a2dp_voice_cnt
+0x42fb mem_tws_wait_sync_ok
+0x42fc mem_last_a2dp_seq_num
+0x42fe mem_param_a2dp_dac_sbc_same_buffer_flag
+0x42ff mem_param_a2dp_dac_buffer_addr_mram_flag
+0x4300 mem_param_a2dp_dac_buffer_start_addr
+0x4302 mem_param_a2dp_dac_buffer_size
+0x4304 mem_param_a2dp_sbc_buffer_addr_mram_flag
+0x4305 mem_param_a2dp_sbc_buffer_start_addr
+0x4307 mem_param_a2dp_sbc_buffer_size
+0x4309 mem_app_state
+0x430a mem_app_handshake_flag
+0x430b mem_sniff_param_interval
+0x430d mem_sniff_param_attempt
+0x430f mem_sniff_param_timeout
+0x4311 mem_cb_check_wakelock
+0x4313 mem_cb_before_hibernate
+0x4315 mem_cb_before_lpm
+0x4317 mem_cb_le_process
+0x4319 mem_cb_bt_process
+0x431b mem_cb_idle_process
+0x431d mem_cb_bb_event_process
+0x431f mem_cb_event_timer
+0x4321 mem_cb_keyscan
+0x4323 mem_device_nums
+0x4324 mem_uart_txpin
+0x4325 mem_uart_rxpin
+0x4326 mem_uart_rtspin
+0x4327 mem_uart_ctspin
+0x4328 mem_uartb_txpin
+0x4329 mem_uartb_rxpin
+0x432a mem_uartb_rtspin
+0x432b mem_uartb_ctspin
+0x432c mem_spid_sclkpin
+0x432d mem_spid_sdiopin
+0x432e mem_iic_sda_pin
+0x432f mem_iic_scl_pin
+0x4330 mem_ef_base
+0x4333 mem_eeprom_block_size
+0x4335 mem_mram_qspi_tx_addr
+0x4337 mem_poweron_state
+0x4338 mem_app_connection_options
+0x4339 mem_app_disconn_reason
+0x433b mem_app_disconn_reason_flag
+0x433d mem_storage_start_addr
+0x4340 mem_local_bdaddr
+0x4346 mem_qspi_gpio_ncs
+0x4347 mem_qspi_gpio_sck
+0x4348 mem_qspi_gpio_io0
+0x4349 mem_qspi_gpio_io1
+0x434a mem_qspi_gpio_io2
+0x434b mem_qspi_gpio_io3
+0x434c mem_nv_data_ptr
+0x434e mem_nv_data_number
+0x434f mem_saradc_check_clk
+0x4350 mem_saradc_flag
+0x4351 mem_bat_read_timer
+0x4352 mem_rf_debug_enable
+0x4353 mem_rf_debug_rf_rx_debug_gpio
+0x4354 mem_rf_debug_rf_tx_debug_gpio
+0x4355 mem_rf_debug_rf_sync_detect_debug_gpio
+0x4356 mem_rf_debug_rf_crc_error_debug_gpio
+0x4357 mem_param_soft_dma_enable
+0x4358 mem_param_soft_dma_table_start_addr
+0x435b mem_param_m0_respin_sco_buffer_start_addr
+0x435e mem_param_app_debug_info_timeout
+0x435f mem_app_debug_info_timer
+0x4360 mem_public_code_svn_version_code
+0x4362 mem_public_code_time_info
+0x4366 mem_public_code_size
+0x4369 mem_fixed_param_area_start
+0x4369 mem_fixed_param_area_reserve
+0x436e mem_param_use_cm0_control_flag
+0x436f mem_avctp_xmem_start
+0x436f mem_avctp_tx_label
+0x4370 mem_avr_state
+0x4371 mem_avr_l2capch_ptr
+0x4373 mem_hp_avctp_timer
+0x4374 mem_avctp_play_state
+0x4375 mem_vlm_notify_enable
+0x4376 mem_vlm_notify_label
+0x4377 mem_avctp_xmem_end
+0x4377 mem_cvsd_in_addr_end
+0x4379 mem_cvsd_in_addr_ptr
+0x437b mem_cvsd_out_addr_start
+0x437d mem_cvsd_out_addr_end
+0x437f mem_cvsd_out_addr_ptr
+0x4381 mem_pcm_in_addr_end
+0x4383 mem_param_pcm_in_buffer_addr_mram_flag
+0x4384 mem_param_pcm_in_buffer_addr
+0x4386 mem_param_cvsd_out_buffer_addr_mram_flag
+0x4387 mem_param_cvsd_out_buffer_addr
+0x4389 mem_param_cvsd_in_buffer_addr_mram_flag
+0x438a mem_param_cvsd_in_buffer_addr
+0x438c mem_param_pcm_8k_out_buffer_addr_mram_flag
+0x438d mem_param_pcm_8k_out_buffer_addr
+0x438f mem_param_pcm_48k_out_buffer_addr_mram_flag
+0x4390 mem_param_pcm_48k_out_buffer_addr
+0x4392 mem_cvsd_start_send
+0x4393 mem_baud
+0x4395 mem_hci_lt_rx_state
+0x4396 mem_hid_xmem_start
+0x4396 mem_hid_l2capch_ptr
+0x4398 mem_hidint_l2capch_ptr
+0x439a mem_hid_xmem_end
+0x439a mem_xmem_sco_start
+0x439a mem_sco_asso_handle
+0x439b mem_sco_handle
+0x439d mem_sco_dsniff
+0x439f mem_sco_tsniff
+0x43a1 mem_sco_wsniff
+0x43a2 mem_sco_tx_packet_type
+0x43a3 mem_sco_rx_packet_type
+0x43a4 mem_sco_rx_packet_len
+0x43a6 mem_sco_tx_packet_len
+0x43a8 mem_air_mode
+0x43a9 mem_neogotiation_state
+0x43aa mem_acl_amaddr
+0x43ab mem_esco_amaddr
+0x43ac mem_esco_arq
+0x43ad mem_acl_arq
+0x43ae mem_last_type_esco
+0x43af mem_last_type_acl
+0x43b0 mem_sco_poll
+0x43b1 mem_esco_attempt
+0x43b2 mem_esco_abnormal_attempt
+0x43b3 mem_xmem_sco_end
+0x43b3 mem_xmem_hf_state_start
+0x43b3 mem_hf_state
+0x43b4 mem_hf_call_state
+0x43b5 mem_hf_command
+0x43b6 mem_agoption
+0x43b8 mem_AG_indicator_map
+0x43bf mem_AG_indicator
+0x43c6 mem_telephone_dialing_state
+0x43c7 mem_telephone_dialing_timer
+0x43c8 mem_xmem_hf_state_end
+0x43c8 mem_hf_vlm_speaker
+0x43c9 mem_music_vlm_speaker
+0x43ca mem_hf_vlm_mic
+0x43cb mem_at_payload_ptr
+0x43cd mem_at_command_ptr
+0x43cf mem_at_rfcomm_data_ptr
+0x43d1 mem_UI_HF_brsf_feature
+0x43d4 mem_codec_type
+0x43d5 mem_codec_msbc_support
+0x43d6 mem_cb_hfp_result_code
+0x43d8 mem_hfp_battery_state
+0x43d9 mem_esco_test
+0x43da mem_sco_transaction_enable
+0x43db mem_local_sco_in_process_flag
+0x43dc mem_ipc_mcu_phase
+0x43dd mem_ipc_mcu_state
+0x43de mem_ipc_enable
+0x43df mem_ipc_le_data_len
+0x43e0 mem_ipc_le_data_att_handle
+0x43e2 mem_ipc_tx_data_len
+0x43e3 mem_ipc_tx_data_ptr
+0x43e5 mem_ipc_loss_packet
+0x43e7 mem_temp_for_addr
+0x43ea mem_ipc_test_buff
+0x43f4 mem_param_ipc_mem_block_start_addr
+0x43f4 mem_param_ipc_to_bt_buf_start_addr
+0x43f7 mem_param_ipc_to_bt_buf_end_addr
+0x43fa mem_param_ipc_to_bt_wptr_addr
+0x43fd mem_param_ipc_to_bt_rptr_addr
+0x4400 mem_param_ipc_to_m0_wptr_addr
+0x4403 mem_param_ipc_to_m0_rptr_addr
+0x4406 mem_param_ipc_to_m0_buf_start_addr
+0x4409 mem_param_ipc_mem_block_end_addr
+0x4409 mem_param_ipc_to_m0_buf_end_addr
+0x440c mem_param_debug_log_func_enable
+0x440d mem_debug_log_temp_point
+0x4411 mem_param_debug_log_mem_block_start_addr
+0x4411 mem_param_debug_log_initial_flag_addr
+0x4414 mem_param_debug_log_lock_flag_cm0_addr
+0x4417 mem_param_debug_log_lock_flag_respin_addr
+0x441a mem_param_debug_log_lock_victim_addr
+0x441d mem_param_debug_log_read_index_addr
+0x4420 mem_param_debug_log_write_index_addr
+0x4423 mem_param_debug_log_buffer_start_addr
+0x4426 mem_param_debug_log_mem_block_end_addr
+0x4426 mem_param_debug_log_buffer_end_addr
+0x4429 mem_wake_flag
+0x442a mem_m0_lpm_flag
+0x442c mem_l2cap_xmem_start
+0x442c mem_l2cap_tx_multi_offset//0 means single packet
+0x442e mem_l2cap_pending_info
+0x442e mem_l2cap_pending_id0
+0x442f mem_l2cap_pending_delay_time0
+0x4433 mem_l2cap_pending_ptr0
+0x4435 mem_l2cap_pending_id1
+0x4436 mem_l2cap_pending_delay_time1
+0x443a mem_l2cap_pending_ptr1
+0x443c mem_l2cap_pending_id2
+0x443d mem_l2cap_pending_delay_time2
+0x4441 mem_l2cap_pending_ptr2
+0x4443 mem_l2cap_pending_count
+0x4444 mem_l2cap_active_ch_count
+0x4445 mem_l2cap_ch_info
+0x4445 mem_l2cap_ch_psm0
+0x4446 mem_l2cap_ch_state0
+0x4447 mem_l2cap_local_cid0
+0x4449 mem_l2cap_remote_cid0
+0x444b mem_l2cap_ch_psm1
+0x444c mem_l2cap_ch_state1
+0x444d mem_l2cap_local_cid1
+0x444f mem_l2cap_remote_cid1
+0x4451 mem_l2cap_ch_psm2
+0x4452 mem_l2cap_ch_state2
+0x4453 mem_l2cap_local_cid2
+0x4455 mem_l2cap_remote_cid2
+0x4457 mem_l2cap_ch_psm3
+0x4458 mem_l2cap_ch_state3
+0x4459 mem_l2cap_local_cid3
+0x445b mem_l2cap_remote_cid3
+0x445d mem_l2cap_ch_psm4
+0x445e mem_l2cap_ch_state4
+0x445f mem_l2cap_local_cid4
+0x4461 mem_l2cap_remote_cid4
+0x4463 mem_l2cap_ch_psm5
+0x4464 mem_l2cap_ch_state5
+0x4465 mem_l2cap_local_cid5
+0x4467 mem_l2cap_remote_cid5
+0x4469 mem_l2cap_ch_psm6
+0x446a mem_l2cap_ch_state6
+0x446b mem_l2cap_local_cid6
+0x446d mem_l2cap_remote_cid6
+0x446f mem_l2cap_ch_psm7
+0x4470 mem_l2cap_ch_state7
+0x4471 mem_l2cap_local_cid7
+0x4473 mem_l2cap_remote_cid7
+0x4475 mem_l2cap_prepare_confreq_count
+0x4476 mem_l2cap_channel_disconnect_timer
+0x4477 mem_sdp_state
+0x4478 mem_ML2CAP_comm_id
+0x4479 mem_used_map
+0x447a mem_tx_fifo0
+0x447a mem_tx_fifo0_map
+0x447b mem_tx_fifo0_ptr
+0x447d mem_tx_fifo1
+0x447d mem_tx_fifo1_map
+0x447e mem_tx_fifo1_ptr
+0x4480 mem_tx_fifo2
+0x4480 mem_tx_fifo2_map
+0x4481 mem_tx_fifo2_ptr
+0x4483 mem_tx_fifo3
+0x4483 mem_tx_fifo3_map
+0x4484 mem_tx_fifo3_ptr
+0x4486 mem_tx_fifo_end
+0x4486 mem_alloc_block
+0x4486 mem_alloc_header
+0x4488 mem_alloc_rptr
+0x448a mem_alloc_wptr
+0x448c mem_alloc_end
+0x448e mem_alloc_cur_len
+0x448f mem_alloc_block_start
+0x449e mem_media_release
+0x449f mem_media_block
+0x449f mem_media_header
+0x44a1 mem_media_rptr
+0x44a3 mem_media_wptr
+0x44a5 mem_media_end
+0x44a7 mem_media_cur_len
+0x44a8 mem_media_block_start
+0x44b7 mem_lcp_block
+0x44b7 mem_lcp_header
+0x44b9 mem_lcp_rptr
+0x44bb mem_lcp_wptr
+0x44bd mem_lcp_end
+0x44bf mem_lcp_cur_len
+0x44c0 mem_lcp_block_start
+0x44cf mem_l2cap_flow_ctrl_flag
+0x44d0 mem_l2cap_pending_item
+0x44d1 mem_l2cap_rxbuff_len_error
+0x44d2 mem_l2cap_xmem_end
+0x44d2 mem_l2cap_rx_max_lenth
+0x44d4 mem_l2cap_rx_malloc_num
+0x44d5 mem_le_dsniff
+0x44d7 mem_le_conn_interval
+0x44d9 mem_le_scan_enable
+0x44da mem_le_scan_interval
+0x44dc mem_le_scan_window
+0x44de mem_le_adv_enable
+0x44df mem_le_adv_data_len
+0x44e0 mem_le_adv_data
+0x44ff mem_le_scan_data_len
+0x4500 mem_le_scan_data
+0x451f mem_le_interal_min
+0x4521 mem_le_interal_max
+0x4523 mem_le_latency
+0x4525 mem_le_timeout
+0x4527 mem_le_ch_mapped
+0x4528 mem_le_new_map
+0x452d mem_le_new_param
+0x452d mem_le_new_transmitwindowsize
+0x452e mem_le_new_transmitwindowoffset
+0x4530 mem_le_new_conninterval
+0x4532 mem_le_new_connslavelatency
+0x4534 mem_le_new_connsupervisiontimeout
+0x4536 mem_le_txheader
+0x4537 mem_le_txlen
+0x4538 mem_le_txpayload
+0x453a mem_le_txcid
+0x453c mem_le_l2cap
+0x453d mem_le_l2cap_response
+0x453e mem_le_txbdy
+0x455d mem_le_pcnt_tx
+0x4562 mem_le_pcnt_rx
+0x4567 mem_le_last_mic
+0x456b mem_le_ivm
+0x456f mem_le_ivs
+0x4573 mem_le_ltk
+0x4583 mem_ltk_exists
+0x4584 mem_le_rconfirm
+0x4594 mem_le_srand
+0x45a4 mem_le_iat
+0x45a5 mem_le_rat
+0x45a6 mem_le_preq
+0x45a7 mem_le_preq_iocap
+0x45a8 mem_le_preq_oob
+0x45a9 mem_le_preq_auth
+0x45aa mem_le_preq_max_keysize
+0x45ab mem_le_preq_init_key_distribution
+0x45ac mem_le_preq_resp_key_distribution
+0x45ad mem_le_pres
+0x45ae mem_le_pres_iocap
+0x45af mem_le_pres_oob
+0x45b0 mem_le_pres_auth
+0x45b1 mem_le_pres_max_keysize
+0x45b2 mem_le_pres_init_key_distribution
+0x45b3 mem_le_pres_resp_key_distribution
+0x45b4 mem_le_pairing_state
+0x45b5 mem_le_enc_state
+0x45b6 mem_le_pairing_mode
+0x45b7 mem_le_tk
+0x45bb mem_le_ediv
+0x45bd mem_le_rand
+0x45c5 mem_le_irk
+0x45d5 mem_le_fixed_passkey_flag
+0x45d6 mem_le_secure_connect_enable
+0x45d7 mem_le_secure_connect_flag
+0x45d8 mem_le_sc_calc
+0x45d9 mem_le_secure_connect_state
+0x45da mem_le_sc_confirm_gkey_flag
+0x45db mem_le_sc_local_key_invalid
+0x45dc mem_le_pairing_handle
+0x45de mem_le_search_handle_start
+0x45e0 mem_le_search_handle_end
+0x45e2 mem_le_att_offset
+0x45e2 mem_le_search_att_type_length
+0x45e3 mem_le_search_att_type
+0x45f3 mem_le_notify_handle
+0x45f5 mem_le_search_uuid_length
+0x45f6 mem_le_search_uuid
+0x4606 mem_le_handle_data_len
+0x4607 mem_le_handle_data
+0x4617 mem_le_adv_param
+0x4617 mem_le_adv_interval_min
+0x4619 mem_le_adv_interval_max
+0x461b mem_le_adv_type
+0x461c mem_le_adv_own_addr_type
+0x461d mem_le_adv_direct_addr_type
+0x461e mem_le_adv_direct_addr
+0x4624 mem_le_adv_channel_map
+0x4625 mem_le_adv_filter_policy
+0x4626 mem_le_conn_param
+0x4626 mem_le_conn_peer_addr_type
+0x4627 mem_le_conn_peer_addr
+0x462d mem_le_conn_own_addr_type
+0x462e mem_le_conn_interval_min
+0x4630 mem_le_conn_interval_max
+0x4632 mem_le_conn_latency
+0x4634 mem_le_conn_superto
+0x4636 mem_le_scan_params
+0x4636 mem_le_scan_type
+0x4637 mem_le_scan_own_addr_type
+0x4638 mem_le_scan_filter_policy
+0x4639 mem_le_lap
+0x463c mem_le_uap
+0x463d mem_le_nap
+0x463f mem_le_xtype_fifo
+0x4644 mem_le_transmit_window
+0x4648 mem_le_connection_updata_param
+0x4658 mem_le_l2cap_size
+0x465a mem_le_packet_len_recved
+0x465b mem_le_tx_buff_used
+0x465c mem_le_tx_ptr0
+0x465e mem_le_tx_ptr1
+0x4660 mem_le_tx_ptr2
+0x4662 mem_le_tx_ptr3
+0x4664 mem_ui_le_uuid_table
+0x4666 mem_le_cur_attlist_start_ptr
+0x4668 mem_le_cur_handle_start
+0x466a mem_le_cur_handle_end
+0x466c mem_le_cur_uuid_lenth
+0x466d mem_le_cur_uuid
+0x467d mem_notify_handle_pool
+0x4681 mem_le_curr_att_len
+0x4682 mem_le_signaling_identifier
+0x4683 mem_le_more_data
+0x4684 mem_lmp_version
+0x4687 mem_lmp_subversion
+0x4689 mem_local_name_length
+0x468a mem_local_name
+0x468d mem_local_name2
+0x46cd mem_local_name_end
+0x46ce mem_unsniff2sniff_timer
+0x46cf mem_switch_flag
+0x46d0 mem_role_switch_flag
+0x46d1 mem_eeprom_ota_base_addr/*the start- writing addr in eeprom  */
+0x46d3 mem_rfc_xmem_start
+0x46d3 mem_pn_dlci
+0x46d4 mem_pn_max_frame_size
+0x46d6 memFCStemp1
+0x46d7 memFCStemp2
+0x46d8 memFCStemp3
+0x46d9 mem_rfcomm_initiator
+0x46da mem_remote_spp_channel
+0x46db mem_HIUfcs_SPP
+0x46dc mem_HIUfcs_SPP_WCredits
+0x46dd mem_remote_credits
+0x46df mem_credit_given
+0x46e0 mem_ms_channel
+0x46e1 mem_current_packet_length
+0x46e3 mem_profile_channel
+0x46e4 mem_rfc_l2capch_ptr
+0x46e6 mem_rfc_server_state
+0x46e8 mem_rfc_xmem_end
+0x46e8 mem_ui_uuid_table
+0x46ea mem_all_uuid_16bits
+0x4700 mem_all_uuid_128bits
+0x4722 mem_sdp_l2capch_ptr
+0x4724 mem_sp_local_key_invalid
+0x4725 mem_le_private_key_256
+0x4745 mem_le_pubkey_local_x_256
+0x4765 mem_le_pubkey_local_y_256
+0x4785 mem_sp_private_key
+0x479d mem_sp_pubkey_local
+0x479d mem_sp_pubkey_local_x
+0x47b5 mem_sp_pubkey_local_x_end
+0x47b5 mem_sp_pubkey_local_y
+0x47cd mem_ssp_enable
+0x47ce mem_sp_iocap_local
+0x47d1 mem_ssp_mode_flag
+0x47d2 mem_spp_reject_justwork_flag
+0x47d3 mem_sp_iocap_remote
+0x47d6 mem_flag_mode_ssp_pin
+0x47d7 mem_authentication_passkey_times
+0x47d8 mem_passkey_1bit
+0x47d9 mem_flag_pairing_state
+0x47da mem_ipc_lock_bt
+0x47db mem_ipc_lock_c51
+0x47dc mem_ipc_fifo_bt2c51
+0x47e1 mem_ipc_fifo_c512bt
+0x47e6 mem_ui_timer_last_btclk
+0x47ea mem_ui_state_map
+0x47ec mem_discovery_timer_count
+0x47ee mem_discovery_timeout
+0x47f0 mem_ui_profile_supported
+0x47f1 mem_pin_length
+0x47f2 mem_pin
+0x4802 mem_keyscan_switch
+0x4803 mem_kscan_row_nums
+0x4804 mem_kscan_col_nums
+0x4805 mem_row_scanned
+0x4806 mem_col_scanned
+0x4807 mem_row_cnt
+0x4808 mem_get_keypress_flag
+0x4809 mem_kscan_row_gpio_pin
+0x4829 mem_kscan_col_gpio_pin
+0x4849 mem_button_gpio1
+0x484a mem_button_last_state1
+0x484b mem_button_timer1
+0x484c mem_button_press_count1
+0x484d mem_button_timeout1
+0x484e mem_button_press_timeout1
+0x484f mem_button_down_cb1
+0x4851 mem_button_up_cb1
+0x4853 mem_button_longpress_cb1
+0x4855 mem_button_long_release_cb1
+0x4857 mem_button_gpio2
+0x4858 mem_button_last_state2
+0x4859 mem_button_timer2
+0x485a mem_button_press_count2
+0x485b mem_button_timeout2
+0x485c mem_button_press_timeout2
+0x485d mem_button_down_cb2
+0x485f mem_button_up_cb2
+0x4861 mem_button_longpress_cb2
+0x4863 mem_button_long_release_cb2
+0x4865 mem_led_gpio1
+0x4866 mem_led_state1
+0x4867 mem_led_on_timer1
+0x4868 mem_led_off_timer1
+0x4869 mem_led_repeat1
+0x486a mem_led_timer1
+0x486b mem_led_gpio2
+0x486c mem_led_state2
+0x486d mem_led_on_timer2
+0x486e mem_led_off_timer2
+0x486f mem_led_repeat2
+0x4870 mem_led_timer2
+0x4871 mem_uppersm_xmem_start
+0x4871 mem_major_uppersm
+0x4872 mem_sub_uppersm
+0x4873 mem_uppersm_list
+0x4878 mem_uppersm_disl2capch_index
+0x4879 mem_uppersm_xmem_end
+0x4879 mem_m0_lock_qspi
+0x487a mem_m0_pause_state
+0x487b mem_xip_flash_offset
+0x487e mem_xip_option
+0x4880 mem_xip_flash_read_cmd
+0x4881 mem_zcode_current_number
+0x4882 mem_zcode_buff
+0x4884 mem_tws_bdaddr
+0x4884 mem_tws_lap
+0x4887 mem_tws_uap
+0x4888 mem_tws_nap
+0x488a mem_hsp_role
+0x488b mem_auto_hsp_role
+0x488c mem_tws_allow_pairing_rssi_limit
+0x488d mem_tws_role
+0x488e mem_tws_state
+0x488f mem_tws_last_rcv_phone_packet_crc_fail
+0x4890 mem_tws_rcv_ack
+0x4891 mem_tws_local_rcv_packet
+0x4892 mem_tws_last_send_ack
+0x4893 mem_tws_timeout_timer
+0x4894 mem_param_tws_timeout_master
+0x4895 mem_param_tws_timeout_slave
+0x4896 mem_tws_observe_wait_connect_timeout_timer
+0x4897 mem_param_tws_observe_wait_connect_timeout_no_connect
+0x4898 mem_param_tws_observe_wait_connect_timeout_error_disconnect
+0x4899 mem_tws_slave_loss_link_listen_master_timeout_timer
+0x489a mem_param_tws_slave_loss_link_listen_master_timeout
+0x489b mem_tws_poll_slave_timer
+0x489c mem_param_tws_poll_slave
+0x489d mem_tws_master_wait_slave_timeout_timer
+0x489e mem_param_tws_master_wait_slave_timeout
+0x489f mem_tws_m2s_ack_send_timeout_count
+0x48a0 mem_param_tws_m2s_ack_send_timeout
+0x48a1 mem_tws_poll_null_ack_interval
+0x48a2 mem_tws_poll_null_ack_interval_count
+0x48a3 mem_loss_match
+0x48a5 mem_count_rcv_adv
+0x48a6 mem_tws_adv_match
+0x48a7 mem_tws_ack
+0x48a8 mem_tws_count_poll
+0x48aa mem_tws_role_switch_in_process
+0x48ab mem_tws_slave_wait_master_first_polling_flag
+0x48ac mem_tws_profile_connected
+0x48ad mem_tws_profile_disconnected_after_connected
+0x48ae mem_tws_adv_count
+0x48af mem_tws_adv_try_num
+0x48b0 mem_tws_snd_op
+0x48b1 mem_tws_snd_op_nextseq
+0x48b2 mem_tws_snd_cur_arq
+0x48b3 mem_tws_rcv_op
+0x48b4 mem_tws_rcv_op_nextseq
+0x48b5 mem_tws_rcv_old_seq
+0x48b6 mem_tws_cmd_fifo
+0x48bb mem_tws_no_connect_cmd_trans_limit
+0x48bc mem_tws_no_connect_cmd
+0x48bd mem_tws_is_slave_send
+0x48be mem_tws_is_need_send_header
+0x48bf mem_tws_remote_version
+0x48c1 mem_param_tws_tx_power
+0x48c2 mem_le_tws_scan_interval_min
+0x48c4 mem_le_tws_scan_interval_max
+0x48c6 mem_le_tws_scan_interval
+0x48c8 mem_le_tws_scan_window
+0x48ca mem_le_tws_adv_interval
+0x48cc mem_param_le_tws_adv_interval_normal
+0x48ce mem_param_le_tws_adv_interval_master_listen
+0x48d0 mem_tws_first_packet_dynamic_buffer
+0x48d0 mem_tws_first_packet_dynamic_buffer_status
+0x48d2 mem_tws_first_packet_dynamic_buffer_local_bdaddr
+0x48d8 mem_tws_first_packet_dynamic_buffer_paired_bdaddr
+0x48de mem_tws_first_packet_dynamic_buffer_reserved
+0x48ee mem_tws_allow_pairing
+0x48ef mem_tws_last_paired_lap
+0x48f5 mem_tws_rf_start_anchor
+0x48f7 mem_tws_rf_rcv_window_size
+0x48f9 mem_tws_rf_packet_rx_window_size
+0x48fb mem_tws_rf_slave_send_full_packet_sleep_time
+0x48fd mem_tws_rf_master_check_raw_id_time
+0x48ff mem_temp_rf_freq_index
+0x4900 mem_temp_rf_switch_flag
+0x4901 mem_tws_buffer_master_switch
+0x4901 mem_tws_buffer_master_switch_reason
+0x4902 mem_process_sync_buffer
+0x4902 mem_process_a2dp_seq_num
+0x4904 mem_process_clk
+0x4908 mem_process_clkrt
+0x490a mem_process_used_buffer_size
+0x490c mem_process_audio_vol
+0x490d mem_process_sync_receive_buffer// Tws process sync packet
+0x490d mem_process_receive_a2dp_seq_num
+0x490f mem_process_receive_clk
+0x4913 mem_process_receive_clkrt
+0x4915 mem_process_receive_used_buffer_size
+0x4917 mem_process_receive_audio_vol
+0x4918 mem_enable_hfp_start_sync// Tws hfp start sync control
+0x4919 mem_hfp_start_sync_buffer// Tws hfp start sync packet
+0x4919 mem_hfp_start_sync_clk
+0x491d mem_param_tws_send_channel_array
+0x4921 mem_tws_last_send_channel_index
+0x4922 mem_save_state
+0x4923 mem_white_list
+0x4953 mem_remote_rx_max_octets
+0x4955 mem_remote_rx_max_time
+0x4957 mem_remote_tx_max_octets
+0x4959 mem_remote_tx_max_time
+0x495b mem_local_rx_max_octets
+0x495d mem_local_rx_max_time
+0x495f mem_local_tx_max_octets
+0x4961 mem_local_tx_max_time
+0x4963 mem_remote_reserve
+0x49f3 mem_sequence_number_rx
+0x49f4 mem_sequence_number_tx
+0x49f5 mem_msbc_pcm_in_wptr
+0x49f7 mem_msbc_pcm_in_rptr
+0x49f9 mem_msbc_out_wptr
+0x49fb mem_msbc_out_rptr
+0x49fd mem_msbc_in_wptr
+0x49ff mem_msbc_in_rptr
+0x4a01 mem_msbc_pcm_out_saddr
+0x4a03 mem_msbc_pcm_out_wptr
+0x4a05 mem_msbc_pcm_out_rptr
+0x4a07 mem_msbc_packet_len
+0x4a09 mem_msbc_pcm_packet_len
+0x4a0b mem_msbc_enc_dec_bt_lock
+0x4a0c mem_msbc_enc_dec_m0_lock
+0x4a0d mem_msbc_adc_start_send
+0x4a0e mem_vp_language
+0x4a0f mem_vp_play_phonenumber
+0x4a10 mem_vp_mram_flag
+0x4a11 mem_vp_addr_temp
+0x4a14 mem_vp_enable
+0x4a15 mem_vp_dac_addr
+0x4a17 mem_vp_dac_half
+0x4a19 mem_vp_play_block_num
+0x4a1a mem_vp_offset
+0x4a1c mem_vp_start_addr
+0x4a1f mem_vp_end_addr
+0x4a22 mem_vp_play_by_cmd
+0x4a23 mem_vp_play_addr_offset_temp
+0x4a24 mem_param_tishi_start_addr
+0x4a26 mem_nv_le_data
+0x4a26 mem_vp_addr
+0x4ab6 mem_vp_end
+0x4ab6 mem_ota_notify_handle
+0x4ab7 mem_ota_write_handle
+0x4ab8 mem_ota_version
+0x4aba mem_ota_buck_size
+0x4abc mem_ota_packet_max_len
+0x4abe mem_ota_work_mode
+0x4abf mem_adc_start_addr
+0x4ac1 mem_adc_buf_size
+0x4ac3 mem_dac_start_addr
+0x4ac5 mem_dac_buf_size
+0x4ac7 mem_dac_clk
+0x4ac8 mem_dac_mram_flag
+0x4ac9 mem_adc_mram_flag
+0x4aca mem_mono_flag
+0x4acb mem_l_din_sel
+0x4acc mem_r_din_sel
+0x4acd mem_eq_flag
+0x4ace mem_acl_credits
+0x4ad0 mem_allow_switch
+0x4ad1 mem_hci_acl_queue_start/*param_acl_pktcnt+2 byte*/
+0x4ad5 mem_hci_wake_clk
+0x4ace mem_nv_data
+0x4ace mem_nv_data0
+0x4ae6 mem_nv_data1
+0x4afe mem_nv_data2
+0x4b16 mem_nv_data3
+0x4b2e mem_nv_data4
+0x4b46 mem_battery_vol
+0x4b47 mem_coef_base_addr
+0x4b4a mem_ipc_tx_buf
+0x4bae mem_le_att_list
+0x4bb0 mem_tws_fac_adv_name
+0x4bcc mem_param_bt_tx_power
+0x4bcd mem_leadv_action//OTA use,don't change location
+0x4bce mem_hibernate_flag
+0x4bcf mem_lpm_write_temp_adc_low
+0x4bd3 mem_lpm_write_temp_adc_high
+0x4bd7 mem_lpm_write_temp_charge_control
+0x4bdb mem_lpm_write_temp_charge_wakeup_low_active
+0x4bdd mem_lpm_write_temp_charge_wakeup_high_active
+0x4bdf mem_efuse_dc_offset
+0x4bdf mem_efuse_dc_offset_l
+0x4be1 mem_efuse_dc_offset_r
+0x4be3 mem_efuse_dc_offset_f6
+0x4be3 mem_efuse_dc_offset_l_f6
+0x4be5 mem_efuse_dc_offset_r_f6
+0x4be7 mem_efuse_adc_offset
+0x4be7 mem_0_5_adc_io_data
+0x4be9 mem_3v_adc_hvin_data
+0x4beb mem_1v_adc_io_data
+0x4bed mem_5v_adc_hvin_data
+0x4bef mem_xlmp_conn_state
+0x4bf0 mem_xlmp_clock_offset_valid
+0x4bf1 mem_rf_power_fix
+0x4bf2 mem_ipc_rx_ptr
+0x4bf5 mem_module_le_rx_data_len
+0x4bf6 mem_module_le_rx_data_address
+0x4bf8 mem_module_le_rx_data_handle
+0x4bfa mem_module_data_write_handle
+0x4bfc mem_module_data_write_handle2
+0x4bfe mem_module_flag
+0x4bff mem_module_hci_notify_len
+0x4c00 mem_module_hci_notify_handle
+0x4c02 mem_module_hci_nofiy_addr
+0x4c04 mem_last_transmite_clock
+0x4c08 mem_module_le_att_list
+0x4c09 mem_module_le_att_list_end
+0x4c09 mem_le_disconnect_reason
+0x4c0a mem_mesh_le_features
+0x4c12 mem_mesh_le_version
+0x4c17 mem_mesh_le_version_exchange_times
+0x4c18 mem_mesh_hci_opcode_ocf
+0x4c1a mem_mesh_hci_opcode_ogf
+0x4c1b mem_mesh_hci_cmd_len
+0x4c1c mem_mesh_event_mask
+0x4c24 mem_mesh_read_local_version_info
+0x4c24 mem_mesh_read_local_version_info_hci_version
+0x4c25 mem_mesh_read_local_version_info_hci_revision
+0x4c27 mem_mesh_read_local_version_info_lmp_version
+0x4c28 mem_mesh_read_local_version_info_manufacturer
+0x4c2a mem_mesh_read_local_version_info_lmp_subversion
+0x4c2c mem_mesh_read_local_support_command
+0x4c6c mem_mesh_le_event_mask
+0x4c74 mem_mesh_le_public_address
+0x4c7a mem_mesh_le_random_address
+0x4c80 mem_mesh_vendor_tx_flag
+0x4c81 mem_mesh_vendor_tx_freq
+0x4c82 mem_mesh_vendor_tx_data
+0x4c83 mem_mesh_vendor_tx_power_calibration
+0x4c84 mem_mesh_vendor_rx_flag
+0x4c85 mem_mesh_vendor_rx_freq
+0x4c86 mem_mesh_event_head_type
+0x4c87 mem_mesh_event_head_event_code
+0x4c88 mem_mesh_event_para_total_length
+0x4c89 mem_mesh_event_parameter_rtn
+0x4c8a mem_mesh_event_parameter_status
+0x4c8b mem_mesh_creat_connection_flag
+0x4c8c mem_mesh_recevie_acl_packet_number
+0x4c8d mem_device_public_address
+0x4c93 mem_mesh_command_complete_num_hci_command_packet
+0x4c94 mem_mesh_command_complete_command_opcode
+0x4c94 mem_mesh_hci_opcode
+0x4c96 mem_mesh_command_complete_return_parameter_status
+0x4c97 mem_simple_pairing_mode
+0x4c98 mem_fec_required
+0x4c99 mem_inquiry_num_responses
+0x4c9a mem_inquiry_num_check
+0x4c9b mem_conn_status
+0x4c9c mem_inquiry_mode
+0x4c9d mem_inquiry_eir_data
+0x4c9f mem_io_cap_flag
+0x4ca0 mem_page_scan_repetition_mode
+0x4ca1 mem_conn_req_status
+0x4ca2 mem_alloc_normal_block
+0x4ca2 mem_alloc_normal_header
+0x4ca4 mem_alloc_normal_rptr
+0x4ca6 mem_alloc_normal_wptr
+0x4ca8 mem_alloc_normal_end
+0x4caa mem_alloc_normal_total_size
+0x4cab mem_alloc_normal_cur_len
+0x4cac mem_alloc_normal_block_start
+0x4cca mem_alloc_big_block
+0x4cca mem_alloc_big_header
+0x4ccc mem_alloc_big_rptr
+0x4cce mem_alloc_big_wptr
+0x4cd0 mem_alloc_big_end
+0x4cd2 mem_alloc_big_total_size
+0x4cd3 mem_alloc_big_cur_len
+0x4cd4 mem_alloc_big_block_start
+0x4cf2 mem_normal_block_ptr_list
+0x4d10 mem_big_block_ptr_list
+0x4d2e mem_rcv_br_queue_ptr
+0x4d31 mem_rcv_ble_queue_ptr
+0x4d34 mem_snd_br_block
+0x4d34 mem_snd_br_header
+0x4d36 mem_snd_br_rptr
+0x4d38 mem_snd_br_wptr
+0x4d3a mem_snd_br_end
+0x4d3c mem_snd_br_total_size
+0x4d3d mem_snd_br_cur_len
+0x4d3e mem_snd_br_block_start
+0x4d5c mem_snd_ble_block
+0x4d5c mem_snd_ble_header
+0x4d5e mem_snd_ble_rptr
+0x4d60 mem_snd_ble_wptr
+0x4d62 mem_snd_ble_end
+0x4d64 mem_snd_ble_total_size
+0x4d65 mem_snd_ble_cur_len
+0x4d66 mem_snd_ble_block_start
+0x4d84 mem_snd_hci_block
+0x4d84 mem_snd_hci_header
+0x4d86 mem_snd_hci_rptr
+0x4d88 mem_snd_hci_wptr
+0x4d8a mem_snd_hci_end
+0x4d8c mem_snd_hci_total_size
+0x4d8e mem_snd_hci_cur_len
+0x4d8f mem_snd_hci_block_start
+0x4dad mem_regd
+0x4db1 mem_alloc_buffer_len
+0x4db3 mem_temp_alloc_big_malloc_cnt
+0x4db5 mem_temp_alloc_normal_malloc_cnt
+0x4db7 mem_temp_send_br_malloc_cnt
+0x4db9 mem_temp_media_malloc_cnt
+0x4dbb mem_temp_lcp_malloc_cnt
+0x4dbd mem_temp_sco_rx_malloc_cnt
+0x4dbf mem_temp_sco_tx_malloc_cnt
+0x4dc1 mem_temp_alloc_big_free_cnt
+0x4dc3 mem_temp_alloc_normal_free_cnt
+0x4dc5 mem_temp_send_br_free_cnt
+0x4dc7 mem_temp_media_free_cnt
+0x4dc9 mem_temp_lcp_free_cnt
+0x4dcb mem_temp_sco_rx_free_cnt
+0x4dcd mem_temp_sco_tx_free_cnt
+0x4dcf mem_param_alloc_normal_buffer_start_address
+0x4dd1 mem_param_alloc_normal_buffer_max_length
+0x4dd3 mem_param_alloc_big_buffer_start_address
+0x4dd5 mem_param_alloc_big_buffer_max_length
+0x4dd7 mem_ipc_data_rx_buf_subtype
+0x4dd8 mem_ipc_data_rx_buf_payload_ptr
+0x4ddb mem_ipc_data_tx_buf_subtype
+0x4ddc mem_ipc_data_tx_buf_payload_ptr
+0x4ddf mem_le_features
+0x4de7 mem_le_supported_host
+0x4de8 mem_simultaneous_le_host
+0x4de9 mem_default_link_policy_settings
+0x4deb mem_link_policy_settings
+0x4ded mem_le_white_list_cnt
+0x4dee mem_le_white_list
+0x4e0a mem_le_white_list_type_and_bd_addr
+0x4e11 mem_le_white_list_filter_policy
+0x4e12 mem_hci_acl_packet_pb_flag
+0x4e13 mem_hci_acl_packet_len_recved
+0x4e15 mem_hci_acl_packet_payload_ptr
+0x4e17 mem_le_first_packet_count
+0x4e18 mem_hci_record_disc_conn_handle
+0x4e19 mem_fsc_rtk_host
+0x4e1a mem_remote_features
+0x4e22 mem_remote_ext_features0
+0x4e2a mem_remote_ext_features1
+0x4e32 mem_le_scan_window_temp
+0x4e34 mem_zcode_buff_user
+0x4f34 mem_queue_init_flag
+0x4f35 mem_hci_version_svnid
+0x4f37 mem_bd_addr_new
+0x4f3d mem_efuse_encryp_data
+0x4f5d mem_encryp_inital_value
+0x4f5f mem_encryp_param
+0x4f61 mem_encryp_count
+0x4f62 mem_qspi_lock_flag_cm0
+0x4f63 mem_qspi_lock_flag_respin
+0x4f64 mem_qspi_lock_victim
+0x4f65 mem_efuse_64_bytes
+0x4fa5 mem_check_attempt_limit
+0x4fa6 mem_hci_remote_name_req_flag
+0x4fa7 mem_hci_remote_name
+0x4fe7 mem_le_wait_process_cmd
+0x4fe8 mem_loopcnt
+0x4fea mem_le_master_sm
+0x4feb mem_headset_end
+0x4ace mem_usb_mouse_data
+0x4ade mem_usb_kb_data
+0x4aee mem_usb_kb_multikey
+0x4afe mem_usb0_get_report_data
Index: ModuleDemo/BLE/CM0/respin/ramcode.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/ramcode.rom	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/ramcode.rom	(working copy)
@@ -0,0 +1,1836 @@
+20200040
+20000001
+20000002
+20000003
+20000004
+20000005
+20000006
+20000007
+20000008
+20000009
+2000000a
+2000000b
+2000000c
+2000000d
+2000000e
+2000000f
+20000010
+20000011
+20000012
+20000013
+20000014
+20000015
+20000016
+20000017
+20000018
+20000019
+2000001a
+2000001b
+2000001c
+2000001d
+2000001e
+2000001f
+20000020
+20000021
+20000022
+20000023
+20000024
+20000025
+20000026
+20000027
+20000028
+20000029
+2000002a
+2000002b
+2000002c
+2000002d
+2000002e
+2000002f
+20000030
+20000031
+20000032
+20000033
+20000034
+20000035
+20000036
+20000037
+20000038
+20000039
+2000003a
+2000003b
+2000003c
+2000003d
+2000003e
+2000003f
+c2840060
+c0010084
+c0070186
+c0080194
+c00e0177
+c00f0199
+c0100221
+c01201f1
+c0190159
+c01c8166
+c01d0168
+c01f0216
+c02081e6
+c02206c8
+c02a06c4
+c02c062e
+c02e064a
+c02e8650
+c03506ca
+c03586cc
+c03601dd
+c04080eb
+c0428109
+c04300ce
+c04f00d2
+c050014b
+c05206ad
+c054069f
+c05c86ce
+c05d05ba
+c0700142
+20202baf
+c00386d0
+c006023e
+c00906d2
+c0098561
+c00a0540
+c0118554
+c0128652
+c0130656
+c0138658
+c014065a
+c014865b
+c0150660
+c01d83ba
+c01f03c3
+c01f836c
+c02084c9
+c0210696
+c0240470
+c02584cd
+c027844c
+c02905d9
+c02c06d4
+c02d85f2
+c02e86d6
+c03005fc
+c03205f8
+c0370676
+c03806d8
+c03886da
+c03a014d
+c0490661
+c052860b
+c053060b
+c1590000
+c16a0000
+20202baf
+20406490
+20406863
+20406326
+2040009f
+2040203c
+20403153
+2040008e
+2040233d
+20400094
+20202021
+c68e0000
+18000e02
+20407148
+7d3a001c
+243a209e
+202006dc
+6fe24133
+c4008000
+6fe20030
+c3800000
+18000e06
+20407148
+247a0000
+68444151
+78487c00
+18423600
+202023b7
+204045b4
+204000a2
+2020455e
+6fe244d9
+c1808000
+d8e00003
+20407148
+247a0000
+6fe444da
+d8e00003
+20407141
+20404735
+2040460a
+6fe444dc
+67e44e32
+7854fc00
+78487c00
+69644e32
+204000c3
+243680c0
+204047d5
+1a227e00
+67e24626
+6fec04dd
+67ec0633
+6fe24c8b
+c000838f
+204002d3
+204046d3
+243680c0
+6fe204dc
+c00300c0
+204002d3
+6fe44e32
+243a00ae
+20600000
+204045c7
+204045bd
+7856fc00
+7826fc00
+7830fc00
+78507c00
+19623600
+37c18400
+1b627e00
+67e44e32
+2020465b
+6fe24013
+793ffe06
+67e24013
+202000d4
+204000d4
+20202bd8
+20405900
+70894bba
+204000dd
+708907ff
+20402a70
+70895074
+7089520e
+70896d07
+20600000
+6fe242b4
+c00080e1
+c00200e7
+c00100e1
+5888e0d0
+67e68955
+584a103c
+67e68958
+70895468
+20600000
+5888c0d0
+67e68955
+584a106c
+202000e4
+20407a63
+203080f8
+708955d4
+20000004
+708955d2
+20000004
+708955d1
+20000004
+6fe242b4
+c00080f6
+c0020106
+708955d0
+708956e0
+18002a08
+18002a00
+7850fc00
+78507c00
+782f7c00
+70890200
+70890100
+70890000
+70890300
+70890470
+6fe28906
+793ffe00
+67e28906
+20600000
+708955d0
+708956c0
+202000f8
+60420017
+1840a200
+6fe242b5
+245a2a2d
+20402a7b
+58000250
+20402bb1
+204000dd
+6fe28906
+79207e00
+67e28906
+7089003c
+708901e0
+2000000a
+70890201
+7089023d
+2000000a
+708903b7
+2000000a
+7089027d
+6fe242b4
+c0000130
+c002012b
+70894cfb
+70894def
+70894eec
+70894f5e
+c0008132
+c0028127
+20202a51
+708956ff
+20402a5d
+708955ff
+20600000
+20400136
+708956cc
+20402a5d
+708955d8
+20600000
+20400136
+20202a49
+708956f7
+20402a5d
+708955df
+20600000
+70894c5b
+70894d96
+70894e2c
+70894f46
+20600000
+37d98200
+37d98200
+37d98200
+37d98200
+37d98200
+20600000
+20600000
+20600000
+6fe8833e
+793ffe1d
+67e8804c
+20200147
+37d98200
+70800520
+37d98200
+20600000
+d85fffff
+20202cb8
+78547c00
+204052b0
+6fe20048
+207a0000
+202006de
+204006e0
+2020022d
+6fe2004b
+79207e03
+67e2004b
+70007201
+20600000
+6fe20183
+203a2378
+d8c00183
+df2000f0
+d8400000
+20400161
+60440099
+2020238d
+efe20006
+207a0000
+18408401
+c2000161
+20600000
+704fa500
+20202414
+6fe24fa5
+1fe0fe01
+67e24fa5
+20405b02
+20402588
+2436a429
+20402bab
+20405b20
+20402500
+2040245a
+20402841
+20402827
+20404b89
+2040017a
+20202425
+20404b89
+2040017a
+20202198
+6fe242a7
+207a0000
+6fe2007c
+247a0000
+202006e2
+704c9b02
+704c8a00
+20200184
+704c9b00
+704ca100
+704c9f00
+202006e4
+6fe24c9a
+203a06e6
+6fe24c99
+203a06dc
+1fe0ffff
+67e24c99
+202006e6
+6fe20018
+1ff18400
+184f840a
+1fe17e0f
+98408400
+18467e00
+20600000
+20402108
+6fe24fa6
+243a01c1
+704c8a04
+20200182
+204024d2
+7854fc00
+6fe24c9b
+c0008194
+6fe2004c
+c28221c5
+6fe20030
+c30221c4
+202002bb
+6fe24c9c
+c00001a8
+c00081ab
+c00101ae
+704c8702
+20600000
+704c880f
+704c8702
+20600000
+704c880f
+704c8722
+20600000
+704c88ff
+704c872f
+20600000
+6fe24fa6
+203a4dab
+6fe4012c
+1fe0f3fd
+68420739
+580000c6
+98408a00
+d8c0073b
+2040713a
+204001d5
+68420053
+6fe2073a
+98467e00
+1fe67c0e
+202101c1
+20204db7
+704c88ff
+704c8707
+20400303
+58000000
+e7e20005
+6fec42a9
+e7ec0005
+df200040
+d8c04fa7
+2040712d
+df2000b8
+204070e4
+2040030d
+6fe24fa6
+704fa600
+70005300
+c00101d3
+20204dbb
+20404f5f
+20204dbb
+68420739
+58004fa7
+98408a00
+6fe2073a
+68420739
+98467200
+d8c0073b
+2020712d
+6fe24fa5
+1fe67c64
+242127fd
+202027ea
+20400249
+68420046
+98467c00
+20628000
+20200297
+20402337
+202c01ee
+204024ca
+243a01e6
+78587c00
+1d027e00
+67e84169
+20600000
+2040248f
+704c8a00
+202006e8
+204021ec
+24740000
+78547c00
+70001120
+793f800b
+20402b71
+2040232b
+c5058201
+204024ca
+243a01f6
+78547c00
+1c427e00
+67e84169
+78387c00
+7834fc00
+202006ea
+20402b6f
+d8200010
+20402321
+78587c00
+7854fc00
+20402917
+204024ab
+204024f3
+2036820d
+204024ca
+243a0208
+202001fb
+18000401
+6fe20031
+793ffe01
+67e20031
+20402bab
+20402940
+78347c00
+704c8a01
+202006e8
+70011600
+70015000
+204024d2
+793f8011
+2040724d
+6fe24c9b
+207a0000
+202002bb
+20404d8e
+c6108000
+2020022d
+6fe20030
+c283a1e1
+6fe20b9c
+203a21e1
+700b9c00
+6fe2004b
+2feffe01
+793ffe01
+67e2004b
+204021e1
+c6108000
+202006e0
+704c8803
+704c8706
+20400303
+18007e00
+e7e20005
+6fe20046
+e7e40005
+2020030d
+704c8806
+704c8717
+20400303
+6fec0040
+e7ec0005
+2020030d
+704c8806
+704c8716
+20200237
+6fe243de
+207a0000
+20403e9d
+20628000
+1fe20c00
+20403e92
+c0058287
+20203ef4
+2040025d
+2040712d
+2020025a
+2040025d
+efe40006
+2020025a
+2040025d
+efe60006
+2020025a
+2040025d
+efec0006
+2020025a
+2040025d
+efee0006
+2020025a
+2040025d
+eff00006
+2020025a
+2040025d
+efe20006
+18c20400
+60464bf2
+20600000
+68464bf2
+18420c00
+20600000
+704e1102
+20600000
+7044d901
+704c8b01
+202002a9
+6fec4c8d
+67ec4639
+67ec4140
+20600000
+20600000
+704ddb00
+2020026e
+704ddb03
+2020026e
+62464ddc
+58004b4a
+67e443e3
+1fe20a00
+5800000a
+e7e20005
+18007e04
+e7e20005
+6fe24ddb
+e7e20005
+6fe64ddc
+e7e60005
+18007e06
+67e243e2
+20203f1a
+204006ec
+6a464dd8
+2020026a
+20400283
+6a464dd8
+20200581
+2040025d
+df200003
+d8a04dd8
+20203e88
+20403e92
+20403e92
+67e24dd7
+2040025a
+6fe24dd7
+c0000280
+204005a2
+207a0000
+20400283
+6fe24dd7
+c001827d
+20202baf
+704c9612
+2020029a
+704c9601
+2020029a
+704c960c
+2020029a
+704c9600
+df200001
+2040029e
+2020030d
+704c9600
+204002a2
+6fe24c96
+e7e20005
+20600000
+704c870e
+1f20fe03
+67e24c88
+20400303
+6fe64c93
+e7e60005
+20600000
+700f1200
+202002ae
+700f120c
+202002ae
+700f1202
+704c870f
+704c8804
+20400303
+6fe20f12
+e7e20005
+6fe64c93
+e7e60005
+2020030d
+6ff04c6c
+c4020000
+6fe20639
+67e24e18
+202006ee
+6fe20046
+67e24e18
+793f8021
+70004600
+704ca100
+704c9b00
+202006ee
+6fe20624
+d8400000
+c1018000
+d8400001
+20600000
+6fe204db
+1fe17e0f
+d8400000
+c1000000
+d8400001
+c1008000
+d8400002
+c1030000
+d8400003
+c1010000
+d8400004
+20600000
+6ff04c6c
+c4008000
+dfe00006
+684204dc
+9840fe00
+67e24c88
+1fe0fe03
+67e44db1
+da204cca
+20400551
+1fe67c02
+20610000
+704c873e
+20400303
+58000002
+e7e20005
+58000001
+e7e20005
+204002c7
+e0420005
+204047d5
+1a227e00
+e7e20005
+684204dc
+184085fa
+efec0006
+e7ec0005
+e0420005
+18427200
+2040712d
+2040018d
+e7e20005
+2020030d
+6fe20046
+67e242a8
+202002f9
+6fe20639
+67e242a8
+704c8805
+704c8713
+20400303
+58000001
+e7e20005
+6fe242a8
+e7e40005
+58000001
+e7e40005
+2020030d
+6fe24c88
+1fe0fe03
+67e44db1
+2040030a
+6fe64c86
+e7e60005
+20600000
+2040055e
+1a420a00
+20600000
+da204d84
+20403fa5
+2020026c
+18000400
+18000201
+60421001
+6842063a
+79200405
+18417efc
+9821fe00
+67e2063a
+1fe17e1f
+280ffe26
+7920fe04
+67e21000
+20600000
+6fe2063a
+c3828000
+2040033f
+20400353
+203a0310
+efe20006
+ea220006
+9a267e00
+18c20a00
+68444953
+2040726f
+1fe20400
+18a20c00
+e8220006
+1a227e00
+98c08c00
+d8a01002
+18427200
+2040712d
+2040480e
+20400312
+20400353
+efe20006
+1fe22200
+18c23000
+ea420006
+9a467e00
+68444953
+2040726f
+9a40fe00
+e7e20018
+9a267c00
+24628000
+202049f1
+6fe24683
+203a480c
+20400349
+c6130000
+da204d5c
+20400551
+c000480c
+c000c80c
+79200026
+20600000
+20400353
+203a480c
+efe20006
+e8420006
+98460400
+6fe44953
+98467c00
+2021480c
+79200026
+20600000
+da204d5c
+20203fa1
+20400357
+20202739
+204045bd
+204045cd
+20407a47
+79202a00
+782efc00
+78307c00
+7850fc00
+20404644
+19317e00
+1fecfe00
+1ff1fe00
+08008628
+7823fc00
+7824fc00
+6fe21000
+08008608
+efe20006
+1fe27200
+08008608
+2022c6a6
+202046a3
+20407a4f
+204045aa
+20404766
+2040031d
+20400355
+20400527
+20404594
+20340536
+2020458a
+6fe20623
+79207e05
+67e20623
+70452d01
+58000003
+67e4452e
+6fe444d7
+67e44530
+6fe44632
+67e44532
+6fe44634
+67e44534
+6fe4063d
+1fe0fe10
+67e40643
+da20000c
+d8200003
+204049ab
+58000000
+e7e20005
+6ff2452d
+e7f20005
+6fe40643
+e7e40005
+20400423
+202006f0
+6fec0633
+684c4627
+98467c00
+24628000
+20402266
+24628000
+204046f1
+2040454a
+7042a700
+70065b00
+204047d2
+202006f2
+204005ae
+67e64e15
+58000000
+67e64d2e
+6fe20046
+67e242a8
+704ddb05
+202003aa
+204005b4
+67e64e15
+58000000
+67e64d31
+6fe20639
+67e242a8
+704ddb04
+58004b4a
+67e443e3
+1fe20a00
+5800000a
+e7e20005
+18007e06
+e7e20005
+6fe24ddb
+e7e20005
+6fe64e15
+e7e60005
+6fe242a8
+e7e40005
+18007e08
+67e243e2
+20203f1a
+20404536
+70100001
+70100100
+5800001b
+67e44953
+204024ce
+1fe0fe18
+67e20639
+20600000
+204045b4
+2040315c
+6fe20624
+c001840b
+20204579
+20400249
+67e242a8
+20400249
+1febfe00
+67e444d7
+20400249
+20400249
+67e44632
+20400249
+67e44634
+20400425
+202002a9
+20400357
+2020053a
+6fe24fea
+c00003f3
+c00083f6
+c00183f8
+c00203fa
+c00303f4
+c00503de
+20600000
+6fe20623
+79207e06
+67e20623
+5fcf3ff3
+67e84528
+5800001f
+e7e20005
+704feaff
+da20000c
+d8200003
+204049ab
+58000001
+e7e20005
+6fea4528
+e7ea0005
+580000fe
+6fe4063d
+1fe0fe40
+e7e40005
+67e40643
+20600000
+20600000
+704fea0a
+20600000
+704fea02
+202048f0
+704fea04
+20600000
+704fea05
+da200009
+d8200003
+204049ab
+58000008
+e7e20005
+58000001
+e7f00005
+20600000
+6fe24fea
+c1828000
+704fea06
+20600000
+6fe24fea
+c1810000
+704fea03
+20600000
+7834fc00
+204048fd
+2021069c
+204003d6
+2040031d
+204045fc
+7856fc00
+204003d4
+24368440
+20407a4f
+2040043a
+20404766
+20400527
+20404594
+20340427
+2040041d
+7854fc00
+20202739
+6fe20623
+c3830000
+6fe24fe7
+207a0000
+c0098375
+20202baf
+704fe700
+20600000
+704fe713
+20600000
+2040031d
+2040042d
+78377c00
+2040053a
+20368414
+2020041a
+2040042f
+20202739
+204045bd
+204045cd
+20407a47
+79202a00
+782efc00
+78307c00
+7850fc00
+20400438
+2020035f
+37c18200
+20600000
+6fe20623
+c3818000
+79207e03
+67e20623
+704fea01
+20600000
+6fe20623
+c281841a
+6fe24e17
+1fe67c06
+2421069c
+1fe0fe01
+67e24e17
+2020041a
+684c4639
+20600000
+684c4c7a
+20600000
+6fe2461b
+c000c6bd
+6fe2461c
+1ff27e00
+1febfe00
+6842461b
+9840fe00
+67e24536
+684244df
+1840fe06
+67e24537
+18427200
+6fe2461c
+205a0448
+245a044a
+604c4538
+d8c044e0
+2040712d
+202046cd
+6fe20623
+c4028000
+6fe4063d
+68440643
+98467e00
+67e40124
+24610000
+2040473e
+202006f0
+6a280f1e
+6a480f22
+6a660f26
+20600000
+62280f1e
+62480f22
+62660f26
+20600000
+2040046c
+67244fe8
+1a208c01
+efe20006
+c4000000
+1a208a1a
+efe40005
+1fe0fe01
+e7e40005
+2040049c
+2040048b
+20404618
+20400468
+6f244fe8
+20600000
+1a208c31
+efea0006
+18000400
+18007225
+c3004628
+18408401
+1fe37e00
+c2000483
+1840ffff
+1a208a22
+e7e20005
+20600000
+1a208c00
+efe20006
+c4030000
+1a208c1a
+efe40006
+68440643
+98467e00
+24610000
+1a208a00
+efe20005
+793ffe06
+e7e20005
+67e20623
+6fea4528
+1a208a31
+e7ea0005
+2020047f
+1a208c00
+efe20006
+c4028000
+1a208c01
+efe20006
+c4008000
+1a208c1a
+e8440006
+6fe40643
+98467e00
+1fe67c01
+202284b2
+20600000
+1a208c1a
+efe40006
+1a208c20
+efe40006
+98467e00
+d840ffff
+98467c00
+202284b2
+20600000
+efe20011
+793ffe05
+e7e20011
+1a208c04
+e8480006
+6fe2452d
+1a208a2c
+e7e20005
+efe40006
+1febfe00
+98409600
+19609601
+1a208a04
+19627e00
+e7e80005
+efe40006
+1febfe00
+1a208a02
+e7e40005
+efe80006
+1a208a2d
+e7e80005
+20600000
+20404972
+2040475a
+2040045f
+20202940
+78287c00
+6fe40631
+68484644
+98409600
+204045c7
+204045bd
+7856fc00
+78567c00
+7826fc00
+7830fc00
+78507c00
+19623600
+37c18400
+203704dd
+1b420400
+604c00a4
+242c2739
+203704e4
+dd2001e0
+1c225000
+6fe20623
+c30184e4
+2055ac9c
+20402abc
+7823fc00
+7824fc00
+09800008
+19897e00
+67e204db
+6842063a
+1fe37e00
+9842fe00
+2feffe02
+7920800f
+09800008
+19897e00
+67e204dc
+1fe27200
+67e2068c
+203a050e
+6fe204db
+1fe17e03
+c0018503
+c5078505
+da204cca
+20400551
+c0008505
+204005aa
+203a0505
+204005b4
+18c20a00
+6fe404db
+e7e40005
+2020050a
+d8a004dd
+2020050a
+09800008
+19897e00
+c2000505
+78367c00
+2020050e
+09800008
+19897e00
+e7e20005
+c200050a
+09800018
+78287c00
+db600664
+20360515
+1fef7e00
+1ff17e00
+e7e60005
+20437a57
+20232739
+7836fc00
+6fe242b5
+243a051d
+6fe20017
+1fe0a200
+20402a7b
+7846fc00
+20202a17
+efe20006
+1fe17e03
+67e2068d
+efe20006
+67e2068c
+207a0000
+60c4068e
+20600000
+c6078000
+c68d0000
+20760000
+6fe204dc
+207a0000
+6fe204db
+1fe17e03
+c001c866
+204005b4
+2040051f
+6fe2068c
+207a0000
+6fe2068d
+c001c866
+202003a3
+78377c00
+2040053a
+2036c582
+2020458a
+68420017
+20402a1f
+20402a23
+78287c00
+d9601388
+202004d2
+1a208409
+efe20002
+203a2baf
+1a20fe02
+e844003f
+ea460002
+58000000
+e7e60002
+1840a603
+20403f8d
+1a20fe02
+e264003f
+1a208409
+efe20002
+1fe0ffff
+e7e20002
+20600000
+1a208409
+efe20002
+20600000
+dee002a8
+6fe204d5
+c1018000
+20204146
+20400573
+da204d34
+20203f94
+da204d34
+20403fa5
+20200581
+20400573
+da204d84
+20203f94
+1a20fe04
+e844003f
+e2460002
+1840a603
+20403f8d
+1a20fe04
+e264003f
+1a20a609
+e8420013
+18408401
+e0420013
+1a20a608
+efe20013
+98467c00
+24212baf
+1a420c00
+1a427e00
+20600000
+20400595
+203a2baf
+6fe44dd1
+1fe0fff6
+68444db1
+98467c00
+2021057c
+da204cca
+20203fa5
+da204ca2
+20400551
+203a057a
+da204ca2
+20203fa5
+2040058d
+da204ca2
+203a0586
+da204cca
+20203f94
+2040058a
+203a2baf
+da204ca2
+20203f94
+6f224caa
+d8c04cf2
+2020058f
+6f224cd2
+d8c04d10
+efe60006
+9a467c00
+20228593
+c200058f
+1f227e00
+20600000
+6fe44dd1
+1fe0fff6
+68444db1
+98467c00
+2021059c
+da204cca
+20200551
+da204ca2
+20400551
+247a0000
+2020059a
+6fe44dd5
+202005a3
+58000010
+67e44db1
+62280f1e
+20400595
+6a280f1e
+20600000
+da204cca
+20203fa5
+6fe44d2e
+247a0000
+da204cca
+20200551
+6fe64d2e
+243a7111
+204005a8
+1a427e00
+67e64d2e
+20207111
+6fe64d31
+243a7111
+204005a8
+1a427e00
+67e64d31
+20207111
+da2047dc
+2040725d
+207a0000
+1fe22600
+20203190
+1a627e00
+c00a85c2
+20203168
+704c8c00
+704c1700
+204006f4
+204002b6
+202031c3
+6842063a
+284c0005
+20608000
+6fe204db
+1fe3fe00
+9842fe00
+c4018000
+793f8405
+79400403
+6042063a
+28400603
+24608000
+6fe245b5
+c0014794
+6fe21002
+c001069c
+c002c790
+20600000
+20404906
+204005c7
+6fe204db
+2feffe04
+79208027
+1fe37e00
+9842fe00
+2feffe02
+7920800f
+6fe204dc
+203a05eb
+6fe20623
+c30205eb
+c6078000
+20406246
+204061b6
+793a001a
+247a0000
+20760000
+c6078000
+7920001a
+6842063a
+79400402
+6042063a
+20600000
+6fe244de
+207a0000
+d8e00001
+20407148
+247a0000
+202006f6
+20400608
+18227e00
+c1018000
+202002f7
+62244db1
+20400605
+1a420a00
+6fe44db1
+e7e20005
+58000000
+e7e20005
+e0220005
+20600000
+20400573
+da204d5c
+20203f94
+da204d5c
+20403fa5
+20200581
+6fe20b97
+243a06f8
+6fe20b98
+243a06f8
+20600000
+6fe2004b
+79207e02
+67e2004b
+20404f51
+7006ae01
+2040023b
+204052de
+2420cf59
+2434cd67
+20600000
+6fe24c97
+207a0000
+6fe20b95
+247a0000
+20400621
+704c9f01
+20600000
+704c8806
+704c8731
+20400303
+6fec0040
+e7ec0005
+2020030d
+6fe20151
+1fe17e03
+c080a68a
+da204cca
+20403fb4
+203a2739
+2020268a
+1f227e00
+67e4012c
+203a0627
+9ea67c00
+20212729
+18017e01
+243a0639
+6fe20151
+1fe17e03
+c001a649
+c507a6f0
+684444d2
+184085fd
+6fe4012c
+98467c00
+20212729
+da204cca
+20400551
+c000a739
+204005aa
+203a2739
+204005ae
+18c20a00
+6fe20151
+e7e20005
+6fe4012c
+e7e40005
+20202686
+09800010
+20437a57
+20232722
+c58026ba
+793f8000
+20600000
+2040039b
+202026dd
+62244db1
+20400558
+6a244db1
+20600000
+da204d34
+20203fa1
+2040055b
+202002f4
+2020055b
+204005a0
+203a729b
+2020729d
+da204d34
+20200551
+20202baf
+2040065e
+207a0000
+6fe2004b
+c3830000
+2040419e
+efe40006
+67e40099
+efe20006
+79207e02
+67e20098
+18c27e00
+67e4013c
+6fe4442c
+203a0670
+20205b2e
+6fe40099
+203a2baf
+d84002a7
+98467e00
+2022db44
+20205b3e
+70429300
+20204b77
+67e40fb7
+2020067a
+68440fb7
+18518400
+6fe44881
+98467c00
+2022d86b
+60444881
+58000100
+984f8400
+6fe6487b
+98467e00
+6846433d
+9840fe00
+1fe0fffc
+67e6023c
+58000100
+67e40241
+58004e34
+67e4023f
+204006bd
+204057e8
+6fe280a0
+67e20124
+20405589
+6fe20124
+67e280a0
+704f6300
+58004e34
+20205866
+20404528
+204045a4
+20403212
+2040682b
+700f0d15
+20206b2e
+20400697
+7854fc00
+20600000
+6fe24040
+c3800000
+c3818000
+6fe247cd
+203a06a6
+6fe24724
+207a0000
+20202d53
+6fe206ab
+67e24bef
+202006fa
+7043dd01
+20403f41
+202006fa
+6fe20fd6
+c05506bc
+6fe24131
+207a0000
+2040065e
+247a0000
+da204d5c
+20400551
+247a0000
+da204cca
+20400551
+68424caa
+98467c00
+24628000
+20202d15
+20202001
+704f6301
+704f6453
+6fe24f62
+207a0000
+6fe24f64
+c1a98000
+202006bf
+18227e00
+c003a739
+c0032739
+202025df
+580002e0
+20200678
+580002a0
+20200678
+580002b0
+20200678
+58000240
+20200678
+58000250
+20200678
+580000f0
+20200678
+58000320
+20200678
+580002f0
+20200678
+58000200
+20200678
+580001c0
+20200678
+58000230
+20200678
+58000300
+20200678
+58000190
+20200678
+58000290
+20200678
+58000120
+20200678
+58000170
+20200678
+580002c0
+20200678
+580002d0
+20200678
+580001e0
+20200678
+58000140
+20200678
+580001b0
+20200678
+580001a0
+20200678
+580001f0
+20200678
+58000260
+20200678
+58000270
+20200678
+58000280
+20200678
+58000080
+20200678
+58000070
+20200678
+580000d0
+20200678
+58000060
+20200678
+580000c0
+20200678
+58000090
+20200678
+580000a0
+20200678
+580000b0
+20200678
+580000e0
+20200678
+58000160
+20200678
+58000100
+20200678
+58000010
+20200678
+58000020
+20200678
+58000030
+20200678
+58000040
+20200678
+58000050
+20200678
+58000110
+20200678
+58000210
+20200678
+58000220
+20200678
+580001d0
+20200678
+58000150
+20200678
+58000180
+20200678
+58000310
+20200678
+58000330
+20200678
Index: ModuleDemo/BLE/CM0/respin/sched.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/sched.rom	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/sched.rom	(working copy)
@@ -0,0 +1,425 @@
+
+mem_patch00:     
+04   #mem_patch00
+40   #mem_patch01
+01   #mem_patch02
+50   #mem_patch03
+11   #mem_patch04
+00   #mem_patch05
+04   #mem_patch06
+46   #mem_patch07
+12   #mem_patch08
+00   #mem_patch09
+10   #mem_patch0A
+31   #mem_patch0B
+00   #mem_patch0C
+1c   #mem_patch0D
+00   #mem_patch0E
+00   #mem_patch0F
+62   #mem_patch10
+00   #mem_patch11
+00   #mem_patch12
+40   #mem_patch13
+11   #mem_patch14
+01   #mem_patch15
+00   #mem_patch16
+06   #mem_patch17
+00   #mem_patch18
+00   #mem_patch19
+00   #mem_patch1A
+00   #mem_patch1B
+01   #mem_patch1C
+00   #mem_patch1D  
+00   #mem_patch1E
+00   #mem_patch1F
+80   #mem_patch20
+10   #mem_patch21
+1c   #mem_patch22
+00   #mem_patch23
+e8   #mem_patch24
+07   #mem_patch25
+00   #mem_patch26
+c8   #mem_patch27
+06   #mem_patch28
+89   #mem_patch29
+04   #mem_patch2A
+29   #mem_patch2B
+11   #mem_patch2C
+40   #mem_patch2D
+13    #mem_patch2E
+00   #mem_patch2F
+00   #mem_patch30
+00   #mem_patch31
+04   #mem_patch32
+00   #mem_patch33
+60   #mem_patch34
+00   #mem_patch35
+04   #mem_patch36
+00   #mem_patch37
+00   #mem_patch38
+00   #mem_patch39
+10   #mem_patch3A
+00   #mem_patch3B
+00   #mem_patch3C
+00   #mem_patch3D
+00   #mem_patch3E
+00   #mem_patch3F
+
+
+##############NVRAM CONFIG##############
+mem_nv_data_ptr:mem_nv_data
+mem_nv_data_number:05
+#####################################
+
+##############BLUETOOTH CONFIG##############
+###commom###
+mem_device_option:0f
+mem_lmp_version:09 0e 05 06 00
+###ble###
+mem_le_lap:d5 cc aa aa cc 52
+
+mem_le_adv_data_len:12
+mem_le_adv_data:
+02 01 0e 
+04 09 4f 54 41
+09 ff 0e 05 21 11
+
+mem_le_scan_data_len:05
+mem_le_scan_data:
+'\09OTA
+
+
+mem_le_adv_enable:00
+mem_le_scan_type:01
+mem_le_adv_type:00
+mem_le_adv_direct_addr_type:00
+mem_le_scan_own_addr_type:00
+mem_le_scan_filter_policy:00
+mem_le_scan_interval:28
+mem_le_scan_window:0c 00
+mem_le_transmit_window:50
+mem_le_adv_interval_max:60 01 
+mem_le_adv_own_addr_type:00
+
+mem_le_pairing_mode:00
+mem_le_secure_connect_enable:00
+mem_le_pres:02 03 00 01 10 02 03 #justwork
+
+mem_le_pairing_handle:00 00
+
+mem_le_interal_min:
+10 00 #interval max
+10 00 #interval min
+00 00 #latency
+00 01 #supervision timeout
+
+###3.0###
+mem_sp_iocap_local:03 00 00
+mem_role_switch_flag:00
+mem_scan_mode:00
+mem_class: 04 04 24
+mem_local_name_length:
+'EVKOTA
+
+#FF FF FF is Fixed for OTA.
+mem_lap:45 FF 31 FF FF FF
+
+mem_discovery_timeout:00 07 
+mem_ssp_enable:01
+mem_ui_profile_supported:48
+mem_app_connection_options:17
+mem_eir_enable:01
+mem_all_uuid_16bits:
+05
+03#Type: Complete list of 16-bit UUIDs
+1e11 0e11 0811 0d11 0b11
+
+mem_all_uuid_128bits:00
+
+mem_ota_version:0a 00
+mem_ota_write_handle:06
+mem_ota_notify_handle:03
+mem_ota_buck_size:00 10
+mem_ota_packet_max_len:be 00
+
+#attribute list: handle 2bytes, uuid 2bytes, length 1bytes, attribute Nbytes
+mem_le_att_list:
+
+#Primary service yichip transmit ------
+01 00 02 00 28 02 ff ff
+#Characteristic tx--notify
+02 00 02 03 28 01 10
+03 00 02 11 ff 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#Client Characteristic Configuration
+04 00 02 02 29 02 01 00
+
+#Characteristic rx--write
+05 00 02 03 28 01 04
+06 00 02 22 ff  14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+#End of Attribute list
+00 00
+
+
+
+mem_lpm_mode:00
+mem_lpm_overhead:08
+mem_lpm_interval:00 02
+mem_lpm_mult:03
+mem_lpm_mult_timeout:03
+mem_ptt:01
+mem_features:
+ff
+ff
+ff
+fa	#fe--EDR  F8--BR
+db	#AFHclose 83  #AFHenable_slave cap and classification LMP_SLAVE_AFH_CLASSIFICATION enable 9b, disable 8b
+fd    #9d
+7b
+83
+
+mem_le_features:
+21				//length extension
+00
+00
+00
+00
+00
+00
+00
+
+
+mem_xip_option:5d 40 bb
+
+mem_ui_le_uuid_table:mem_le_att_list
+
+mem_seqi:7f
+
+mem_le_connection_updata_param:
+06 00
+06 00
+00 00
+f4 01
+
+
+mem_codec_msbc_support:00
+mem_codec_type:01
+mem_eq_flag:01
+
+mem_UI_HF_brsf_feature:313538 #30 33 30 
+mem_le_more_data:01
+mem_ipc_enable:01
+
+mem_tws_state:00
+mem_tws_bdaddr:96 55 12 11 33 62
+#mem_tws_bdaddr:96 45 12 00 19 62
+
+
+mem_hsp_role:00
+mem_auto_hsp_role:01
+mem_tws_allow_pairing:01
+mem_tws_allow_pairing_rssi_limit:45
+
+mem_tws_rf_start_anchor:b0 04   # 0x1e0 40us,   0x78 10us,   0x4b0 100us,   0x618 130us
+mem_tws_rf_rcv_window_size:78 00
+
+mem_tws_rf_packet_rx_window_size:f0 0a # 2800
+mem_tws_rf_slave_send_full_packet_sleep_time:58 02 # 50us
+# mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us)
+# send delay is mem_tws_rf_slave_send_full_packet_sleep_time, so we can think the judge below
+# mem_tws_rf_packet_rx_window_size - (mem_tws_rf_rcv_window_size + 72us + hardware_delay(18us) + mem_tws_rf_slave_send_full_packet_sleep_time/2)
+mem_tws_rf_master_check_raw_id_time:db 04
+
+mem_rf_debug_enable: 00
+mem_rf_debug_rf_rx_debug_gpio: 0c
+mem_rf_debug_rf_tx_debug_gpio: 0e
+mem_rf_debug_rf_sync_detect_debug_gpio: 13
+mem_rf_debug_rf_crc_error_debug_gpio: 19
+
+
+mem_param_sco_use_cm0:01
+
+
+# ipc define
+#mem_param_ipc_mem_block_start_addr
+mem_param_ipc_to_bt_buf_start_addr:00 d8 01
+mem_param_ipc_to_bt_buf_end_addr:00 db 01
+mem_param_ipc_to_bt_wptr_addr:00 db 01
+mem_param_ipc_to_bt_rptr_addr:04 db 01
+mem_param_ipc_to_m0_wptr_addr:08 db 01
+mem_param_ipc_to_m0_rptr_addr:0c db 01
+mem_param_ipc_to_m0_buf_start_addr:50 db 01
+mem_param_ipc_to_m0_buf_end_addr:00 dd 01
+#mem_param_ipc_mem_block_end_addr
+
+
+# debug log define
+#mem_param_debug_log_mem_block_start_addr
+mem_param_debug_log_func_enable:00
+
+mem_param_debug_log_initial_flag_addr:10 db 01
+mem_param_debug_log_lock_flag_cm0_addr:11 db 01
+mem_param_debug_log_lock_flag_respin_addr:12 db 01
+mem_param_debug_log_lock_victim_addr:13 db 01
+mem_param_debug_log_read_index_addr:14 db 01
+mem_param_debug_log_write_index_addr:16 db 01
+mem_param_debug_log_buffer_start_addr:18 db 01
+mem_param_debug_log_buffer_end_addr:50 db 01
+#mem_param_debug_log_mem_block_end_addr
+
+# soft dma define
+# size is SOFT_DMA_TABLE_TOTAL_COUNT*4 + SOFT_DMA_TABLE_TOTAL_COUNT*SOFT_DMA_TABLE_UNIT_SIZE = 0x100
+mem_param_soft_dma_enable:01
+mem_param_soft_dma_table_start_addr:10 d5 01
+
+
+# sco m0 rx buffer define
+# size is M0_SCO_RX_BUFFER_SIZE + M0_SCO_TX_BUFFER_SIZE
+mem_param_m0_respin_sco_buffer_start_addr:10 d6 01
+
+
+mem_param_use_cm0_control_flag:01
+# tishi buffer size is 0x2000
+mem_param_tishi_start_addr:00 a0
+
+#mem_app_debug_info_timer use to set first debug timeout
+#mem_param_app_debug_info_timeout use to set period
+mem_app_debug_info_timer:05
+mem_param_app_debug_info_timeout:32
+
+mem_param_tws_tx_power:02
+
+mem_param_tws_send_channel_array:08 24 08 24
+#mem_param_tws_send_channel_array:20 20 20 20
+#mem_param_tws_send_channel_array:08 09 10 11
+
+mem_tx_power:02
+
+mem_sfreq_enable:01
+#mem_param_rf_setup must big then mem_param_pll_setup, be-careful, mem_param_rf_setup real value = 0xEA6 - value
+#we suggest must reserve 0x3A6, means mem_param_rf_setup = (0xEA6 - mem_param_pll_setup - 0x3A6)
+#mem_param_rf_setup:B8 07
+#mem_param_pll_setup:48 03
+mem_param_rf_setup:00 06
+mem_param_pll_setup:00 05
+
+mem_audio_output_setting: 01
+
+
+mem_mram_qspi_tx_addr:00 60
+
+mem_vp_addr:
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+000000 000000
+
+mem_fec_required:00		
+mem_eir:
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 		00 00 00 00 00 00 00 00 00 00 00 00
+mem_simple_pairing_mode:00	
+mem_conn_status:00
+mem_io_cap_flag:00
+mem_inquiry_mode:00
+
+
+mem_param_alloc_normal_buffer_start_address:00 18
+mem_param_alloc_normal_buffer_max_length:83 00
+mem_param_alloc_big_buffer_start_address:00 20
+mem_param_alloc_big_buffer_max_length:b0 02
+mem_l2cap_rx_max_lenth:b0 02
+
+
+mem_alloc_normal_total_size:0a
+mem_alloc_big_total_size:0a
+mem_snd_br_total_size:0a
+mem_snd_ble_total_size:0a
+mem_snd_hci_total_size:0a
+
+mem_hci_version_svnid:4486
+
+mem_keyscan_switch:00
+
+mem_public_code_svn_version_code:00 00 00 00 00 00 00 00 00
+
+mem_le_tws_scan_interval:28 00
+mem_le_tws_scan_window:0c 00
+mem_param_le_tws_adv_interval_normal:00 01 
+mem_param_le_tws_adv_interval_master_listen:58 00 
+
+
+#mesh init
+mem_mesh_event_head_type:04	#HCI_H4_TYPE_EVENT
+
+mem_mesh_command_complete_num_hci_command_packet:01
+
+mem_mesh_read_local_version_info:
+09		#hci_version BT_HCI_VERSION_5_0
+00 00	#hci_revsion
+09		#lmp_version RADIO_BLE_VERSION_NUMBER:BT_HCI_VERSION_5_0
+0e 05	#manufacture_name Yichip Microelectronics (Hangzhou) Co.,Ltd.
+FF FF	#LPM_subversion
+
+mem_mesh_read_local_support_command:02 05 ff
+
+mem_device_public_address:11 22 33 44 55 66
+
+mem_local_rx_max_octets:fb 00 48 08 fb 00 48 08  
+
+
+mem_lpm_config:8f 10 ca
+mem_lpm_buckcnt:0a 0b ef 07
+mem_lpm_hibernate_switch:00
+mem_gpio_wakeup_low:00 00 00 00 00 00 00 00
+mem_fcomp_mul:02
+mem_fcomp_div:24
+mem_iscan_window:20 00
+mem_iscan_interval:00 04
+mem_pscan_window:16 00
+mem_pscan_interval:00 04
+mem_inq_window:20 00
+mem_page_window:30 00
+mem_page_to:00 30
+mem_rx_window_init:80 03
+mem_rx_window_sniff:00 06
+
+#if you find lpo_time not near 0x2a, you must think the pre timer maybe error.
+#DVDD 0.1uF, VFB 1uF    Time:   DVDD up time: 4us, VFB up time: 255us
+#DVDD 0.1uF, VFB 10uF    Time:   DVDD up time: 4us, VFB up time: 305us 
+#clock unit is internal 32K, 1 step is near 32us
+#so we set:
+#1: digldo pre-on counter(DVDD):  0x02
+#2: exen pre-on counter(VFB):  0x14
+#3: xtal pre-on counter(XTAL) set to zero becouse it will set in lpm_cal_xtal_startup
+mem_lpm_xtalcnt:00 20 18 bf 07
+
+mem_ef_base:00 ff 87
+mem_eeprom_block_size:80
+
+mem_rf_init:
+ff
+
+mem_rf_init_ptr:mem_rf_init
+
Index: ModuleDemo/BLE/CM0/respin/zcode.rom
===================================================================
--- /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/zcode.rom	(nonexistent)
+++ /YC1121E/SoftCode/1121EB/branch/HciDongle_Zephyr/ModuleDemo/BLE/CM0/respin/zcode.rom	(working copy)
@@ -0,0 +1,3264 @@
+20200040
+6fe204dd
+c00a0021
+c00a800d
+c0010006
+20204868
+efe20006
+67e206a4
+20204890
+98467c00
+20610000
+1fe20400
+20600000
+eff00006
+67f04953
+6fe44953
+6844495f
+20400009
+60444953
+6fe44957
+6844495b
+20400009
+60444957
+704c880b
+704c873e
+20400303
+58000007
+e7e20005
+6fe20639
+e7e40005
+6ff04953
+e7f00005
+2020030d
+2040000d
+da200009
+d8200003
+204049ab
+58000015
+e7e20005
+6ff0495b
+e7f00005
+20600000
+da400014
+20200022
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe204dd
+c0040013
+c004801c
+c006002b
+c0008008
+c0004880
+2020072a
+efea0006
+67ea4528
+efe40006
+67e40643
+6844063d
+98467c00
+24214890
+6fe20623
+79207e06
+67e20623
+20600000
+2040001c
+da200009
+d8200003
+204049ab
+58000009
+e7e20005
+6ff04ddf
+e7f00005
+20600000
+eff00006
+67f04c0a
+20400403
+6ff04c6c
+c4018000
+704c880c
+704c873e
+20400303
+58000004
+e7e40005
+6fe20639
+e7e40005
+6ff04c0a
+e7f00005
+2020030d
+efea0006
+67ea4c12
+20400407
+20348034
+6fe24c17
+247a0000
+1fe0fe01
+67e24c17
+202048f0
+6ff04c6c
+c4028000
+704c8808
+704c870c
+20400303
+58000000
+e7e20005
+6fe20639
+e7e40005
+6fea4c12
+e7ea0005
+2020030d
+20200040
+da204140
+2040604d
+18007e05
+2040528d
+6fe80779
+e7e80005
+d84006af
+204052d0
+20406142
+204052e7
+20208011
+7006b101
+c5108017
+6fe20b9c
+207a0000
+70007c0b
+c5108017
+6fe24293
+207a0000
+204052e7
+24208017
+20600000
+c6908000
+793f8021
+20200152
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+da201001
+68420048
+20407a08
+6fe20048
+c2838726
+c0188021
+c0060728
+c0038030
+c005800b
+20204f6c
+6fe20b9c
+203a0011
+204052e7
+2040d2da
+2440d2d6
+20200012
+204052da
+204052f6
+18007e11
+2040528d
+d8c00749
+204070de
+6842004c
+18410401
+6fe20048
+1fe3fe00
+c590801e
+7d34fe00
+202052ab
+7934fe00
+9842fe00
+202052ab
+6fe20030
+79207e04
+67e20030
+1c427e00
+67e806c2
+6fe206ab
+c281802e
+79207e03
+67e206ab
+18007e01
+2040528d
+204052a6
+2020017f
+70004800
+20600000
+18007e02
+2040528d
+6fe206a4
+e7e20005
+204052a6
+20200154
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe204db
+684c4639
+c2838005
+20200006
+684c4c7a
+6fec04e3
+98467c00
+24628000
+2040493a
+202006f2
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+20404b82
+204024ce
+1fe67c0f
+24210006
+202024b9
+70416f01
+202024b9
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8a00
+24348004
+704c8a01
+704c8808
+704c8712
+20400303
+18007e35
+e7e20005
+6fec0040
+e7ec0005
+6fe24c8a
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8808
+704c8712
+20400303
+18007e00
+e7e20005
+6fec0040
+e7ec0005
+6fe24c8a
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe20030
+c4008000
+793ffe01
+67e20030
+6fe4415f
+67e4003e
+7855fc00
+704c8a00
+20200724
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+c5958006
+1c40a200
+20348009
+1d00a200
+20200009
+1c40a203
+20348009
+1d00a203
+68440032
+1a227e00
+793ffe1b
+9846fc00
+6fe40075
+204071c9
+18072600
+9a667e00
+20210013
+9840fe00
+9a20fe00
+67e80034
+7046cf00
+6fe20030
+79207e01
+67e20030
+6fe20073
+67e20092
+58000000
+67e64208
+67e6420b
+67e241f8
+6fe44161
+67e4003e
+24348023
+18808fff
+704c8a02
+20200724
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+204033cc
+24228010
+6fe242a7
+c001b3e2
+c004b3e8
+c00533f4
+c005b3fa
+c0063404
+c0043446
+c00c33da
+c003b3d4
+c00cb3d8
+c00d345d
+c0093422
+c0098018
+204033d0
+247a0000
+6fe242a7
+c006801a
+c00e8016
+202033bf
+70007c37
+202033ca
+70007c18
+202033ca
+6fe2004b
+79207e01
+67e2004b
+6fe20030
+c283b413
+20400235
+202033ca
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+2040554f
+20400012
+df200020
+d8c08080
+18c20a00
+efe20006
+c001800e
+c002000e
+c002800e
+c003800e
+c016000e
+c016800e
+c0800010
+58000080
+e7e20005
+c2000005
+20600000
+df200008
+d8c0812a
+20200005
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+20400008
+6fe20b97
+207a0000
+700b9700
+6fe20b95
+c004800f
+20206472
+6fe20b98
+207a0000
+700b9800
+6fe20b96
+c009001f
+c004800f
+20206481
+204063ce
+704c8807
+704c8736
+20400303
+58000000
+e7e20005
+6fec0040
+e7ec0005
+2020030d
+202052d6
+700b960f
+204052da
+204052f2
+2020e406
+20206410
+20600000
+700b9801
+700b9613
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+7854fc00
+78287c00
+20404735
+2040460a
+204046ad
+2436c91c
+6fe20003
+1fe0fe01
+67e20003
+6fe204db
+1fe17e0f
+c001800e
+2020491b
+d8400004
+6fe2461c
+7d3a0406
+60424536
+684244ff
+1840fe06
+67e24537
+18427200
+6fe2461c
+205a0448
+245a044a
+604c4538
+d8c04500
+2040713a
+2020468c
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+20400006
+20400004
+20203e60
+d8e00009
+20207357
+70442901
+20758000
+70442900
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+700fd600
+71f0001c
+70804205
+20400032
+6fe28341
+67e24bce
+6fe24bef
+67e206ab
+24558038
+20407988
+2040001c
+580005bf
+67e4431d
+58000142
+67e4431f
+58000141
+67e4431b
+580006a7
+67e44315
+580006aa
+67e44313
+2055802e
+24358020
+20403e79
+204057bf
+700f0d66
+20203f28
+58000000
+da204f65
+d8400040
+202056bd
+6fec4140
+67ec4340
+70801002
+204057bf
+6fe24bce
+c282802b
+700f0d65
+20403f28
+58001171
+67e44f5d
+20200722
+20400143
+700f0d6a
+20203f28
+204054b0
+204054b5
+200007d0
+2020553b
+6848833e
+6048804c
+70804de6
+2040013b
+70800520
+2020013b
+58000034
+da204be7
+d8400008
+202056bd
+00000000
+00000000
+00000000
+00000000
+20200040
+793f801c
+704c8801
+704c8701
+20400303
+58000000
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24ca1
+c0008010
+20400015
+704c880a
+704c8704
+20400303
+6fec0040
+e7ec0005
+6fe60146
+e7e60005
+58000001
+e7e20005
+6fec0040
+67ec4f37
+2020030d
+6fec4f37
+684c0040
+98467c00
+20228003
+20600000
+704ca101
+704c9b00
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe2007d
+c0060009
+c00b8010
+c0058013
+c0198720
+c017001d
+c0208025
+20204ba4
+da200040
+2040604d
+6fe80739
+68480779
+98467c00
+2022821e
+20204d8b
+6fe44de9
+c3014e10
+20204def
+20404d6f
+67e206af
+20404f51
+70007c0c
+6fe24293
+247a0000
+6fe20030
+c3830000
+20404d80
+20200235
+6fe24170
+1fe0fe01
+68420739
+98467c00
+24210029
+60424170
+20404d51
+2020002b
+6fe20b96
+c0058027
+70007c03
+20204eb4
+70007c04
+20600000
+704c8803
+704c871b
+20400303
+6fe20046
+e7e40005
+6fe24170
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+da201000
+68440738
+20407a08
+6fe2007d
+c001800e
+c0020020
+c0088014
+c0138033
+c014003b
+c0038037
+c0040610
+c00101b1
+2020071e
+6fe20739
+67e206a3
+c0088012
+20204cad
+20404d0a
+20200016
+20404e14
+20200016
+704c8804
+704c8708
+20400303
+58000000
+e7e20005
+68420046
+e0440005
+58000001
+e7e20005
+2020030d
+6fe20739
+67e206a3
+c0058024
+20204cc0
+6fe24132
+c087cd22
+6fe24293
+207a0000
+68420055
+70005500
+70429300
+6fe2073a
+c1830000
+60420055
+700b9b01
+2040061a
+6fe24c97
+203a023b
+20600000
+20404dc7
+6ff00739
+67f04e1a
+20600000
+6fe20739
+67e206a4
+20400154
+20204d51
+20404edd
+20200034
+00000000
+00000000
+00000000
+20200040
+6fe64d31
+245a000e
+58000000
+67e64d31
+dfe04d5c
+67e40f12
+6a240f12
+20400551
+207a0000
+6a240f12
+20403fa5
+20400581
+20200007
+1fe22400
+20200581
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+68464dd8
+2040025b
+20400258
+c0008007
+c0010012
+20202baf
+20400249
+67e44c94
+d84003ff
+98410400
+60444c18
+1feb7e00
+1fecfe00
+67e24c1a
+20400258
+67e24c1b
+2020071c
+20400249
+67e242a8
+20400034
+20400249
+67e40f12
+20402284
+24628000
+1a208c01
+efe20006
+c280002c
+6fe40f12
+67e44db1
+20400595
+205a723a
+6fe40f12
+1fe22200
+1fe22400
+20404185
+1a420a00
+6fe40f12
+e7e40005
+e0220005
+6fe40f12
+1fe27200
+2040025d
+2020712d
+6fe40f12
+2040003a
+247a0000
+6fe40f12
+1fe22200
+1fe22400
+204049ab
+20200028
+1fecfe00
+1ff1fe00
+18000201
+c1008000
+18000202
+20600000
+204005a3
+203a729b
+2020729d
+00000000
+00000000
+00000000
+20200040
+dfe00020
+da204f3d
+d8400020
+204056bd
+d8c04f3d
+efe40006
+207a0000
+67e44f5f
+2040000d
+20400011
+2040000d
+2020001d
+da204f3f
+df200006
+704f6101
+20600000
+efe40011
+68444f5d
+9840fe00
+67e44f5d
+6fe24f61
+9a20a200
+1a20a202
+6fe24f61
+1fe0fe01
+67e24f61
+c2000011
+20600000
+efe40011
+68444f5d
+9842fe00
+67e44f5d
+6fe24f61
+9a20a200
+1a20a202
+6fe24f61
+1fe0fe01
+67e24f61
+c200001d
+6fe44f5d
+68444f5f
+98467c00
+2422abaf
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe20739
+79207e07
+67e2007d
+c0418009
+c042000e
+c04c8010
+c04d0013
+20204c5a
+20404c9e
+6fe4073a
+6ff0073c
+67f04e22
+20600000
+20404ca0
+2020000a
+20404c78
+20400019
+20200621
+20400019
+20404c78
+20404c7c
+700b9801
+700b9603
+20600000
+704c8809
+704c8732
+20400303
+6fec0040
+e7ec0005
+6fe647d3
+e7e60005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6ff04c6c
+c4010000
+704c880a
+704c873e
+20400303
+58000003
+e7e40005
+6fe20639
+e7e40005
+6fec4530
+e7ec0005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6ff04c6c
+c4000000
+704c8813
+704c873e
+20400303
+58000001
+e7e40005
+6fe20639
+e7e40005
+204002c2
+e0420005
+6fe24626
+e7e20005
+6fec0633
+e7ec0005
+6fe40625
+1feb7e00
+e7e40005
+6fe80650
+e7e80005
+6fe2065b
+e7e20005
+6fe20639
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8817
+704c8718
+20400303
+6fec0040
+e7ec0005
+d8c04297
+18007210
+2040712d
+18007e00
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe20048
+c0420005
+c0418008
+20204f9d
+68424c97
+604206a9
+20205046
+68424c97
+604206a9
+202050ba
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c9c
+c0810006
+204020dc
+246c0000
+c6000000
+684c0149
+20402289
+20628000
+204001a2
+20400303
+58000001
+e7e20005
+6fec0149
+e7ec0005
+6fe20144
+1fe20400
+1fe97e00
+1fe97e00
+e7e20005
+58000000
+e7e20005
+6fe24c9c
+c0800020
+58000000
+e7e20005
+6fe60146
+e7e60005
+6fe80132
+9c467e00
+e7e40005
+2020030d
+6fe60146
+e7e60005
+6fe80132
+9c467e00
+e7e40005
+6fe20018
+2040018d
+e7e20005
+6fe24c9c
+c001002b
+2020030d
+6fe64d2e
+1fe20c00
+efe20006
+efe40006
+207a0000
+1fe20400
+1fe27200
+2040712d
+184672f0
+20407100
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0090005
+c011001a
+20200295
+6fe24ded
+203a0297
+20400252
+67ee4e0a
+2040000e
+6fe24ded
+1fe0ffff
+67e24ded
+20200299
+20400269
+243a0297
+1a420a00
+1a40a407
+1a420c00
+efee0006
+e7ee0005
+c2000010
+58000000
+18a08bf9
+e7ee0005
+20600000
+20400249
+67e4495f
+20400249
+67e44961
+20400024
+df200003
+2040029d
+6fe20639
+e7e40005
+2020030d
+da400014
+da200009
+d8200003
+204049ab
+58000015
+e7e20005
+6ff0495b
+e7f00005
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8806
+704c8714
+20400303
+6fe24c89
+e7e20005
+6fe20046
+e7e40005
+6fe24c8a
+e7e20005
+203a000e
+6fe40032
+1fe37e00
+2020000f
+58000000
+e7e40005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8804
+704c8705
+20400303
+58000000
+e7e20005
+6fe24e18
+e7e40005
+6fe206a4
+e7e20005
+6fe2004c
+793ffe05
+67e2004c
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c8807
+704c8720
+20400303
+6fec0040
+e7ec0005
+6fe24ca0
+e7e20005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+704c880b
+704c8703
+20400303
+6fe24c8a
+e7e20005
+6fe20046
+e7e40005
+6fec0040
+e7ec0005
+18007e01
+e7e20005
+18007e00
+6842004c
+284ffe02
+7920fe00
+e7e20005
+6fe20046
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c1a
+c000800b
+c001000f
+c001800c
+c002000d
+c0028010
+c0030011
+c004000e
+c01f8012
+20200295
+20200712
+20200714
+20200716
+20200718
+2020071a
+20200295
+20200295
+6fe24c18
+c0008019
+c00b801d
+c010001f
+c0518024
+c0300034
+20200295
+2040024f
+67ec4c8d
+20400265
+20200299
+704e193f
+20200299
+df200002
+204002a2
+58000000
+e7e40005
+2020030d
+20400249
+68420046
+98467c00
+2022802b
+68420639
+98467c00
+24628000
+604242a8
+df200003
+204002a2
+6fe242a8
+e7e40005
+6fe20018
+2040018d
+e7e20005
+2020030d
+df200002
+204002a2
+6fe44f35
+e7e40005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe64d2e
+245a000f
+58000000
+67e64d2e
+dfe04d34
+67e40f12
+20200008
+6a240f12
+20400551
+207a0000
+6a240f12
+20403fa5
+20400581
+20200008
+1fe22400
+20200581
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24f34
+243a0710
+704f3401
+20400023
+6f224cd2
+6a444dd3
+6fe44dd5
+67e40f12
+58004cca
+67e40f16
+2040001d
+6fe24cd2
+1feff203
+d8c04cd4
+d8a04d10
+2040712d
+6f224caa
+6a444dcf
+6fe44dd1
+67e40f12
+58004ca2
+67e40f16
+2040001d
+6fe24caa
+1feff203
+d8c04cac
+d8a04cf2
+2020712d
+6a240f16
+20403f94
+6fe40f12
+9a40a400
+c200001d
+20600000
+58004ca2
+2040002c
+58004cca
+2040002c
+58004d34
+2040002c
+58004d5c
+2040002c
+58004d84
+1fe20a00
+1fe0a208
+1fe0fe0a
+e7e40005
+e7e40005
+e7e40005
+e8420011
+184f8403
+9840fe00
+e7e40005
+18a08a01
+58000000
+e7e20005
+18427200
+20207100
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c005001a
+c007001d
+c00983c8
+c00b000f
+c00b8019
+c00c0019
+c00c8019
+c00d0019
+c00d8019
+c0078020
+c0080025
+c0088029
+2020070e
+20400249
+204002a9
+da200009
+d8200003
+204049ab
+58000008
+e7e20005
+6ff04ddf
+e7f00005
+20600000
+20200295
+20400258
+67e244de
+20200299
+7044d900
+704c8b00
+20200299
+df200002
+2040029d
+58000004
+e7e20005
+2020030d
+704ded00
+704e0a00
+704dee00
+20200299
+68424ded
+18467c04
+20228297
+20400252
+67ee4e0a
+20400030
+20200299
+6fe24ded
+d8a04dee
+1feffe07
+98a08a00
+6fee4e0a
+e7ee0005
+6fe24ded
+1fe0fe01
+67e24ded
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0040008
+c004800d
+c0058012
+c0060025
+c0068029
+2020070c
+20400258
+67e244df
+1fe27200
+20400246
+20200299
+20400258
+67e244ff
+1fe27200
+20400246
+20200299
+6fe244d9
+243a0297
+20400258
+67e24636
+20400249
+67e444da
+20400249
+67e444dc
+20400258
+67e24637
+20400258
+67e24e11
+6fe444da
+684444dc
+98467c00
+24228299
+1fe3fe00
+67e444da
+20200299
+20400258
+67e244d9
+20400258
+20200299
+20400249
+67e444da
+20400249
+67e444dc
+20400258
+67e24e11
+98267c00
+20428260
+20400258
+67e24626
+2040024f
+67ec4627
+20400258
+67e2462d
+20400249
+1febfe00
+67e444d7
+20400249
+20400249
+67e44632
+20400249
+67e44634
+20200262
+20200040
+6fe24c18
+c001800a
+c01b8015
+c029001e
+c02a8024
+c02b0029
+c036002d
+c0368032
+20200295
+20400299
+5800003f
+67f04c6c
+5fffffff
+67f04c1c
+58000000
+67ec4c7a
+67e244de
+67e244d9
+67e24133
+20200265
+204001e1
+20400249
+67e40051
+df200003
+2040029d
+6fe20046
+e7e40005
+7042a71d
+2020030d
+20400258
+67e24c98
+df200064
+d8a00183
+20400246
+20200299
+df200002
+2040029d
+6fe24c97
+e7e20005
+2020030d
+20400258
+67e24c97
+203a0293
+20200299
+df200003
+2040029d
+6fe44de7
+e7e40005
+2020030d
+20400249
+67e44de7
+20200299
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0158005
+c0160015
+20200295
+2040024f
+67ec42a9
+2040024c
+67e647ce
+df200007
+2040029d
+6fec0040
+e7ec0005
+2040030d
+6fe24c9f
+c0008012
+7042a716
+20600000
+204033e5
+700b9b01
+20600000
+2040024f
+67ec42a9
+2040001d
+df200007
+2040029d
+6fec0040
+e7ec0005
+2020030d
+700b950a
+700b9701
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c00c8007
+c00e0018
+c00e8020
+c00d802b
+2020070a
+704fa601
+2040024f
+67ec42a9
+20400249
+67e200b6
+20400249
+9c40fe00
+1fe17ffc
+67e800b7
+df200008
+d8a04fa7
+204070e4
+20402287
+20228016
+704fa602
+7042a703
+202002a9
+6fe24c9b
+c08102ad
+20400249
+203a02ad
+20400258
+67e206a7
+7042a715
+202002a9
+20400249
+67e242a8
+20402284
+242282ad
+1a208c01
+efe20006
+c2800029
+204002a9
+20203420
+204002a9
+202048f0
+6fe24c9b
+c08102ad
+20400249
+67e242a8
+203a02ad
+204002a9
+6ff04e1a
+243a0035
+7042a704
+20600000
+704c880b
+704c870b
+20400303
+58000000
+e7e20005
+6fe20046
+e7e40005
+6ff04e1a
+e7f00005
+2020030d
+00000000
+20200040
+6fe24c18
+c0058009
+c0060011
+c0068019
+c0070022
+c008802a
+c009802e
+20200708
+2040024f
+67ec42a9
+d8a04297
+18007210
+20400246
+70429301
+7042a70b
+20200025
+2040024f
+67ec42a9
+7042a70c
+20400025
+2040061a
+6fe24c97
+203a023b
+20600000
+2040024f
+67ec42a9
+20400258
+67e247f1
+98007200
+d8a047f2
+20400246
+7042a709
+20200025
+2040024f
+67ec42a9
+7042a70a
+df200007
+2040029d
+6fec0040
+e7ec0005
+2020030d
+20400249
+67e242a8
+7042a70d
+202002a9
+20400249
+67e242a8
+20400258
+1fe0fe0e
+67e242a7
+202002a9
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0030006
+c004001c
+c005002f
+20200706
+20400249
+67e242a8
+20400258
+67e206a4
+20402284
+242282ad
+1a208c01
+efe20006
+c2800018
+7042a706
+6fe242a8
+6842439b
+98467c00
+242282a9
+7042a711
+6fe2439a
+67e242a8
+202002a9
+6fe206a4
+67e20f12
+20404894
+202002a9
+2040024f
+67ec42a9
+7042a71a
+6fe24c9b
+c0008025
+c0010023
+20200029
+704c960b
+2020002a
+704c9600
+2040002a
+704c8a02
+20200184
+704c9602
+df200007
+2040029e
+6fec42a9
+e7ec0005
+2020030d
+6fe24ca1
+c00002ad
+c00102ab
+6fe24c9b
+c00102ab
+704ca102
+2040024f
+67ec42a9
+20400258
+67e24c8a
+7042a708
+204002a9
+20200184
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c00e000f
+c00e8014
+c00f001b
+c0118020
+c0120025
+c0210028
+c0218029
+c022002b
+c0228030
+c0230033
+c0238034
+c0288036
+20200704
+20400249
+67e44153
+20400249
+67e44151
+20200299
+df200005
+2040029d
+6fe4414f
+e7e40005
+6fe4414d
+e7e40005
+2020030d
+20400249
+67e4414f
+20400249
+67e4414d
+20200299
+df200004
+2040029d
+6fe6414a
+e7e60005
+2020030d
+2040024c
+67e6414a
+20200299
+20200295
+20400258
+20200295
+df200002
+2040029d
+6fe24c9c
+e7e20005
+2020030d
+20400258
+67e24c9c
+20200299
+20200295
+20400258
+20200295
+df2000f2
+2040029d
+6fe24c98
+e7e20005
+d8c00183
+df200064
+2040713a
+2020030d
+00000000
+00000000
+20200040
+6fe24c18
+c0070005
+c007800a
+20200295
+df200003
+2040029d
+6fe44de9
+e7e40005
+2020030d
+20400249
+67e44de9
+20200299
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0018008
+c002001c
+c0058022
+c006002d
+c0068035
+20200702
+6fe44deb
+c30102ab
+6fe44de9
+c30102ab
+6fe24c9b
+c08102ad
+20400249
+67e40253
+20400249
+67e40255
+20400249
+67e40257
+58000040
+67e4430b
+20400249
+67e4430d
+20400249
+67e4430f
+7042a712
+202002a9
+20400249
+67e40253
+6fe20031
+c30302ab
+7042a713
+202002a9
+6fe24c9b
+c08102ad
+6fe44deb
+c30002ab
+6fe44de9
+c30002ab
+2040024f
+67ec42a9
+20400258
+7042a718
+202002a9
+204001e1
+df200005
+2040029d
+6fe20046
+e7e40005
+6fe44deb
+e7e40005
+2020030d
+204001e1
+20400249
+67e44deb
+df200003
+2040029d
+6fe20046
+e7e40005
+2020030d
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0008008
+c001000b
+c0018010
+c0028015
+c003001a
+20200700
+20400255
+67f04c6c
+20200299
+df200004
+2040029d
+580400fb
+e7e60005
+2020030d
+df200009
+2040029d
+6ff04ddf
+e7f00005
+2020030d
+6fe244de
+243a0297
+2040024f
+67ec4c7a
+20200299
+6fe244de
+243a0297
+20400249
+67e44617
+20400249
+67e44619
+20400258
+2040002d
+6042461b
+20400258
+205a0035
+245a0039
+20400258
+2040024f
+20400258
+67e24624
+20400258
+67e24e11
+20200299
+d8400000
+c1000000
+d8400002
+c1018000
+d8400006
+c1010000
+d8400001
+20600000
+684c4c8d
+604c4639
+70461c00
+20600000
+70461c01
+20600000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0008009
+c001000e
+c0018014
+c002001e
+c002801e
+c0048019
+20200295
+df200009
+2040029d
+6ff04c24
+e7f00005
+2020030d
+df200041
+2040029d
+d8c04c2c
+df200040
+2040713a
+2020030d
+df200009
+2040029d
+6ff04138
+e7f00005
+2020030d
+df200007
+2040029d
+6fec4140
+e7ec0005
+2020030d
+df200008
+2040029d
+580002a8
+e7e40005
+5800003c
+e7e20005
+58000008
+e7e40005
+e7e40005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c000800b
+c009800e
+c00a0018
+c00b8020
+c00c0025
+c00c8028
+c00d002d
+c00d8030
+202006fe
+20400255
+67f04c1c
+20200299
+2040025d
+d8a0468a
+df200042
+2040713a
+df200042
+d8c0468a
+d8400000
+20400161
+60424689
+20200299
+df2000f9
+2040029d
+d8c0468a
+df200040
+2040713c
+df200017
+204070e4
+2020030d
+df200003
+2040029d
+6fe44159
+e7e40005
+2020030d
+20400249
+67e44159
+20200299
+df200002
+2040029d
+6fe24133
+e7e20005
+2020030d
+20400258
+67e24133
+20200299
+df200005
+2040029d
+6fe44153
+e7e40005
+6fe44151
+e7e40005
+2020030d
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+20200040
+6fe24c18
+c0008007
+c0010017
+c0028019
+c0048025
+202006fc
+7920001c
+2040024c
+67e64147
+20400258
+d8400800
+984ffe00
+d840ffff
+98467c00
+24210011
+18427e00
+18000e02
+20407141
+20400258
+67e24c99
+67e24c9a
+202002a9
+7042a702
+20200299
+2040024f
+67ec42a9
+20400249
+67e40251
+20400249
+67e200b6
+20400249
+20400258
+67e24ad0
+704c9b01
+7042a705
+202002a9
+6fe24ca1
+c00002ad
+c00102ab
+6fe24c9b
+c00102ab
+2040024f
+67ec42a9
+7042a707
+20400258
+c00082a9
+7042a719
+204002a9
+20204d51
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
+00000000
